From f90fa84e898341871482bd951c92c7b97aa0d6ee Mon Sep 17 00:00:00 2001 From: Xiangfu Liu Date: Wed, 15 Jul 2009 23:21:21 +0800 Subject: [PATCH] some cleanup. cleanup Makefile and README --- Makefile | 140 +- README | 67 +- openwrt/Makefile | 7 - openwrt/openwrt-jz47x0-r15323.diff | 243285 -------------------------- 4 files changed, 55 insertions(+), 243444 deletions(-) delete mode 100644 openwrt/Makefile delete mode 100644 openwrt/openwrt-jz47x0-r15323.diff diff --git a/Makefile b/Makefile index a5c2cd5..d3c736e 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,7 @@ - -# "PI Makefile" - for setting up the PI development environment +# "PanGu Makefile" - for setting up the PanGu development environment # -# (C) Copyright 2009 PI. -# Author: xiangfu liu +# Copyright 2009 (C) Qi Hardware inc., +# Author: Xiangfu Liu # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -18,138 +17,26 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA -BINUTILS_VER=binutils-2.17 -GCC_VER=gcc-4.1.2 -GLIBC_VER=glibc-2.6.1 -GLIBC_PORTS_VER=glibc-ports-2.6.1 -KERNEL_HEADERS_VER=linux-headers-2.6.24.3 - -TOOLCHAIN_PATH=toolchain -DL_PATH=$(TOOLCHAIN_PATH)/dl -INSTALL_PATH=install -PATCHES_PATH=$(TOOLCHAIN_PATH)/patches -GLIBC_PATCHES_PATH=$(PATCHES_PATH)/glibc - -BINUTILS_PACKAGE=$(BINUTILS_VER).tar.bz2 -BINUTILS_URL= \ - ftp://ftp.gnu.org/gnu/binutils/$(BINUTILS_PACKAGE) -GCC_PACKAGE=$(GCC_VER).tar.bz2 -GCC_URL=ftp://ftp.gnu.org/gnu/gcc/$(GCC_VER)/$(GCC_PACKAGE) -GLIBC_PACKAGE=$(GLIBC_VER).tar.bz2 -GLIBC_URL=ftp://ftp.gnu.org/gnu/glibc/$(GLIBC_PACKAGE) -GLIBC_PORTS_PACKAGE=$(GLIBC_PORTS_VER).tar.bz2 -GLIBC_PORTS_URL=ftp://ftp.gnu.org/gnu/glibc/$(GLIBC_PORTS_PACKAGE) -KERNEL_HEADERS_PACKAGE=$(KERNEL_HEADERS_VER).tar.bz2 -KERNEL_HEADERS_URL= - # for the device stage FLASH_TOOL_PATH = ./usbboot -FLASH_TOOL_BIN_PATH = $(FLASH_TOOL_PATH)/bin STAGE1_PATH = $(FLASH_TOOL_PATH)/xburst_stage1 STAGE2_PATH = $(FLASH_TOOL_PATH)/xburst_stage2 CROSS_COMPILE ?= mipsel-openwrt-linux- CFLAGS="-O2" -export PATH:=$(PWD)/install/bin:$(PATH) - -# this glibc version does not build with gcc 4.3 - hence this special compat parameter -GCC_VERSION=$(shell [ "`gcc --version | grep '4.3'`" ] && echo "43" ) -ifeq ($(GCC_VERSION),43) -BUILD_CC="gcc -fgnu89-inline" -else -BUILD_CC="gcc" -endif - -toolchain: binutils gcc glibc - -### misc - -$(DL_PATH): - mkdir -p $(DL_PATH) - -$(INSTALL_PATH): - mkdir -p $(INSTALL_PATH) - -%$(BINUTILS_PACKAGE): URL=$(BINUTILS_URL) -%$(GCC_PACKAGE): URL=$(GCC_URL) -%$(GLIBC_PACKAGE): URL=$(GLIBC_URL) -%$(GLIBC_PORTS_PACKAGE): URL=$(GLIBC_PORTS_URL) - -.tar.bz2: $(DL_PATH) $(INSTALL_PATH) - wget -c -O $@ $(URL) - touch $@ - - -### toolchain stuff -binutils: $(DL_PATH)/$(BINUTILS_PACKAGE) - tar -xvjf $(DL_PATH)/$(BINUTILS_PACKAGE) -C $(TOOLCHAIN_PATH) - mkdir -p $(TOOLCHAIN_PATH)/$(BINUTILS_VER)/build - cd $(TOOLCHAIN_PATH)/$(BINUTILS_VER)/build && \ - ../configure --target=mipsel-linux --prefix=$(PWD)/$(INSTALL_PATH) --disable-werror \ - && make CFLAGS=$(CFLAGS) && make install - touch $@ - -gcc: $(DL_PATH)/$(GCC_PACKAGE) - tar -xvjf $(DL_PATH)/$(GCC_PACKAGE) -C $(TOOLCHAIN_PATH) - cd $(TOOLCHAIN_PATH)/$(GCC_VER)/libiberty && \ - cat strsignal.c | sed -e 's/#ifndef HAVE_PSIGNAL/#if 0/g' >junk.c && \ - cp -f strsignal.c strsignal.c.fixed && mv -f junk.c strsignal.c - mkdir -p $(TOOLCHAIN_PATH)/$(GCC_VER)/build - cd $(TOOLCHAIN_PATH)/$(GCC_VER)/build && \ - ../configure --target=mipsel-linux \ - --host=i686-pc-linux-gnu --prefix=$(PWD)/$(INSTALL_PATH) \ - --disable-shared --disable-threads --disable-multilib \ - --enable-languages=c && make CFLAGS=$(CFLAGS) all-gcc && make install-gcc - touch $@ - -glibc: $(DL_PATH)/$(GLIBC_PACKAGE) $(DL_PATH)/$(GLIBC_PORTS_PACKAGE) $(DL_PATH)/$(KERNEL_HEADERS_PACKAGE) - tar -xvjf $(DL_PATH)/$(KERNEL_HEADERS_PACKAGE) -C $(TOOLCHAIN_PATH) - tar -xvjf $(DL_PATH)/$(GLIBC_PACKAGE) -C $(TOOLCHAIN_PATH) - tar -xvjf $(DL_PATH)/$(GLIBC_PORTS_PACKAGE) -C $(TOOLCHAIN_PATH)/$(GLIBC_VER) - mv $(TOOLCHAIN_PATH)/$(GLIBC_VER)/$(GLIBC_PORTS_VER) $(TOOLCHAIN_PATH)/$(GLIBC_VER)/ports - cd $(TOOLCHAIN_PATH)/$(GLIBC_VER) && \ - patch -Np1 -i $(PWD)/$(GLIBC_PATCHES_PATH)/glibc-2.6.1-cross_hacks-1.patch && \ - patch -Np1 -i $(PWD)/$(GLIBC_PATCHES_PATH)/glibc-2.6.1-libgcc_eh-1.patch && \ - patch -Np1 -i $(PWD)/$(GLIBC_PATCHES_PATH)/glibc-2.6.1-localedef_segfault-1.patch && \ - patch -Np1 -i $(PWD)/$(GLIBC_PATCHES_PATH)/glibc-2.6.1-mawk_fix-1.patch -# patch -Np1 -i $(PWD)/$(GLIBC_PATCHES_PATH)/glibc-2.6.1-alpha_ioperm_fix-1.patch && \ -# patch -Np1 -i $(PWD)/$(GLIBC_PATCHES_PATH)/glibc-2.6.1-RTLD_SINGLE_THREAD_P-1.patch && \ -# patch -Np1 -i $(PWD)/$(GLIBC_PATCHES_PATH)/glibc-2.6.1-sysdep_cancel-1.patch && \ -# patch -Np1 -i $(PWD)/$(GLIBC_PATCHES_PATH)/glibc-2.6.1-hppa_nptl-1.patch - mkdir -p $(TOOLCHAIN_PATH)/$(GLIBC_VER)/build - cd $(TOOLCHAIN_PATH)/$(GLIBC_VER)/build && \ - echo "libc_cv_forced_unwind=yes" > config.cache && \ - echo "libc_cv_c_cleanup=yes" >> config.cache && \ - echo "libc_cv_mips_tls=yes" >> config.cache && \ - BUILD_CC=$(BUILD_CC) CC="mipsel-linux-gcc" \ - AR="mipsel-linux-ar" RANLIB="mipsel-linux-ranlib" \ - ../configure --prefix=$(PWD)/$(INSTALL_PATH) --libexecdir=$(PWD)/$(INSTALL_PATH)/libexec/glibc \ - --host=mipsel-linux --build=i686-pc-linux-gnu \ - --disable-profile --enable-add-ons --with-tls --enable-kernel=2.6.0 \ - --with-__thread --with-binutils=$(PWD)/$(INSTALL_PATH)/bin \ - --with-headers=$(PWD)/$(TOOLCHAIN_PATH)/$(KERNEL_HEADERS_VER) \ - --cache-file=config.cache && \ - make CFLAGS=$(CFLAGS) && make install - cp $(GLIBC_PATCHES_PATH)/SUPPORTED $(TOOLCHAIN_PATH)/$(GLIBC_VER)/localedata/ - cd $(TOOLCHAIN_PATH)/$(GLIBC_VER)/build && \ - make localedata/install-locales - touch $@ - ### u-boot .PHONY: u-boot u-boot: - export PATH=/opt/mipseltools-gcc412-glibc261/bin:$PATH - git clone git://github.com/xiangfu/pi-u-boot.git u-boot + git clone git://github.com/xiangfu/qi-u-boot.git u-boot cd u-boot && \ - make pi_config && \ + make qi_lb60_config && \ make ### kernel .PHONY: kernel kernel: - export PATH=/opt/mipseltools-gcc412-glibc261/bin:$PATH - git clone git://github.com/xiangfu/pi-kernel.git kernel + git clone git://github.com/xiangfu/qi-kernel.git kernel cd kernel && \ make pi_defconfig && \ make uImage @@ -157,13 +44,10 @@ kernel: ### flash-boot .PHONY: usbboot usbboot: stage1 stage2 - mkdir -p $(FLASH_TOOL_BIN_PATH) - cp $(FLASH_TOOL_PATH)/src/usbboot.cfg $(FLASH_TOOL_BIN_PATH) - cd $(FLASH_TOOL_PATH) && \ + cd $(FLASH_TOOL_PATH) ./autogen.sh && \ ./configure && \ make - cp $(FLASH_TOOL_PATH)/src/usbboot $(FLASH_TOOL_BIN_PATH) stage1: make CROSS_COMPILE=$(CROSS_COMPILE) -C $(STAGE1_PATH) @@ -172,7 +56,7 @@ stage2: make CROSS_COMPILE=$(CROSS_COMPILE) -C $(STAGE2_PATH) ### clean up -distclean: clean clean-usbboot clean-toolchain +distclean: clean clean-usbboot clean: @@ -181,14 +65,6 @@ clean-usbboot: make clean CROSS_COMPILE=$(CROSS_COMPILE) -C $(STAGE2_PATH) make clean -C $(FLASH_TOOL_PATH) -clean-toolchain: clean-glibc - rm -rf $(TOOLCHAIN_PATH)/$(BINUTILS_VER) binutils - rm -rf $(TOOLCHAIN_PATH)/$(GCC_VER) gcc - rm -rf $(INSTALL_PATH) - -clean-glibc: - rm -rf $(TOOLCHAIN_PATH)/$(GLIBC_VER) glibc - help: @make --print-data-base --question | \ awk '/^[^.%][-A-Za-z0-9_]*:/ \ diff --git a/README b/README index f11b5ee..c9673ae 100644 --- a/README +++ b/README @@ -1,22 +1,28 @@ -=Cross toolchain= -you can get the cross toolchain at: - http://www.openmobilefree.net/other/file/mipseltools-gcc412-glibc261.tar.bz2 - ftp://ftp.ingenic.cn/3sw/01linux/00toolchain/mipseltools-gcc412-glibc261.tar.bz2 - ftp://ftp.ingenic.cn/3sw/01linux/00toolchain/jz-crosstools-src.tar.bz2 +=serial console= + take off the cover of PCB, then you will send the "GND" and "TXD" + and th TP74 is the "RXD", you can get serial output from those pins + you need a TTL <-> RS232 converter. here[1] is the serial PIN in the board. -or you can build is from source: - make toolchain +=toolchain= + $ git clone git://github.com/lindnermarek/openwrt-x-burst.git[2] + $ git checkout --track -b x-burst origin/x-burst + $ make menuconfig + (select 'XBurst JZ47x0 [2.6]' in Target System + for configure the u-boot in setp: 4) + $ make + we will get toolchain under /PATH/TO/openwrt-x-burst/staging_dir/ + toolchain-mipsel_gcc-4.1.2_uClibc-0.9.30.1/usr/bin -=Serial Console= -1. open the case +=xburst-tools (reflash tools)= + you can get source in git://github.com/xiangfu/xburst-tools.git[3] -2. take off the cover of PCB - then you will send the "GND" and "TXD" - and th TP74 is the "RXD" - you can get serial output from those pins +=u-boot= + in openWRT menuconfig-->Target Images-->Build U-Boot bootloader --> + U-Boot target board (NEW) --> input 'qi_lb60' + here[4] is the u-boot github URL -3. you need a "RS-232 <--> TTL" converter to - get the correct output date +=kernel(2.6.24)= + here[5] is the kernel GIT URL. =CPU Jz4740= Jz4740 is a multimedia application processor targeted at mobile devices @@ -26,18 +32,23 @@ high performance and a low power consumption solution for embedded devices. Boot up The Jz4740 can be set to boot from NOR or NAND. -If booted from NAND, the CPU fetches the first page from NAND and uses the first 4 bytes on it to know how the NAND chip should be treated (16/8-bit bus, 2/3 row cycles). -After that it copies the first 8kB from NAND and copies it to the I-Cache for execution. +If booted from NAND, the CPU fetches the first page from NAND and uses the +first 4 bytes on it to know how the NAND chip should be treated (16/8-bit +bus, 2/3 row cycles). After that it copies the first 8kB from NAND and +copies it to the I-Cache for execution. Ingenic Media Extension Instruction Set -According to the MXU User Guide, the XBurst processor supports additional instructions called the Ingenic Media Extension Instruction Set (they call it an SIMD instruction set). +According to the MXU User Guide, the XBurst processor supports additional +instructions called the Ingenic Media Extension Instruction Set (they +call it an SIMD instruction set). Excerpt from the PDF: -Processors (such as the Jz4740) have 60 extra SIMD commands used for the optimization of multimedia codecs such as MPEG4, H264, VC-1, RMVB, ... and other multimedia decoder algorithms that can be optimized using the MXU. +Processors (such as the Jz4740) have 60 extra SIMD commands used for the +optimization of multimedia codecs such as MPEG4, H264, VC-1, RMVB, ... +and other multimedia decoder algorithms that can be optimized using the MXU. Image Processing Unit The Jz4740 also has an IPU which has the following features: - * Video frame resize * Color space conversion: 420/444/422 YUV to RGB convert @@ -46,3 +57,19 @@ The Jz4740 also has an IPU which has the following features: 2. edit the file under 'debian' folder (create by 'dh_make') 3. run 'dpkg-buildpackage -rfakeroot' to create the deb package and source package + +---- +[1] http://www.openmobilefree.net/?p=61 +[2] here is the web site +http://github.com/lindnermarek/openwrt-x-burst/commits/x-burst + now we put the code in github.com +[3] in folder 'usbboot', here is the tar package and Debian package. + http://cloud.github.com/downloads/xiangfu/xburst-tools/xburst-tools_0.0_200906.tar.gz + http://cloud.github.com/downloads/xiangfu/xburst-tools/xburst-tools_0.0_200906-1_i386.deb +[4] http://github.com/xiangfu/qi-u-boot/tree + this git repos have two branch [master] [pi] + [master] is the v2009.06 + [pi] is 1.1.6 old version.(will detele laster) +[5] git://github.com/xiangfu/qi-kernel.git + only one master branch in kernel git. so you can just + 'git clone' and 'make uImage' to get the kernel image diff --git a/openwrt/Makefile b/openwrt/Makefile deleted file mode 100644 index 1b7f025..0000000 --- a/openwrt/Makefile +++ /dev/null @@ -1,7 +0,0 @@ - -OWRT_SVN_PATH = openwrt-trunk - -owrt_checkout: - svn co -r r15323 svn://svn.openwrt.org/openwrt/trunk $(OWRT_SVN_PATH) - cd $(OWRT_SVN_PATH) && patch -p0 < ../openwrt-jz47x0-r15323.diff - touch $@ diff --git a/openwrt/openwrt-jz47x0-r15323.diff b/openwrt/openwrt-jz47x0-r15323.diff deleted file mode 100644 index 21f14ab..0000000 --- a/openwrt/openwrt-jz47x0-r15323.diff +++ /dev/null @@ -1,243285 +0,0 @@ -Index: target/linux/jz47x0/image/Makefile -=================================================================== ---- target/linux/jz47x0/image/Makefile (revision 0) -+++ target/linux/jz47x0/image/Makefile (revision 0) -@@ -0,0 +1,27 @@ -+# -+# Copyright (C) 2009 OpenWrt.org -+# -+# This is free software, licensed under the GNU General Public License v2. -+# See /LICENSE for more information. -+# -+include $(TOPDIR)/rules.mk -+include $(INCLUDE_DIR)/image.mk -+ -+define Image/BuildKernel -+ cp $(KDIR)/vmlinux.elf $(BIN_DIR)/openwrt-$(BOARD)-vmlinux.elf -+ gzip -9 -c $(KDIR)/vmlinux > $(KDIR)/vmlinux.bin.gz -+ $(STAGING_DIR_HOST)/bin/lzma e $(KDIR)/vmlinux $(KDIR)/vmlinux.bin.l7 -+ dd if=$(KDIR)/vmlinux.bin.l7 of=$(BIN_DIR)/openwrt-$(BOARD)-vmlinux.lzma bs=65536 conv=sync -+ dd if=$(KDIR)/vmlinux.bin.gz of=$(BIN_DIR)/openwrt-$(BOARD)-vmlinux.gz bs=65536 conv=sync -+endef -+ -+define Image/Build/squashfs -+ $(call prepare_generic_squashfs,$(KDIR)/root.squashfs) -+endef -+ -+define Image/Build -+ $(call Image/Build/$(1)) -+ dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/openwrt-$(BOARD)-root.$(1) bs=128k conv=sync -+endef -+ -+$(eval $(call BuildImage)) -Index: target/linux/jz47x0/config-2.6.24 -=================================================================== ---- target/linux/jz47x0/config-2.6.24 (revision 0) -+++ target/linux/jz47x0/config-2.6.24 (revision 0) -@@ -0,0 +1,453 @@ -+CONFIG_32BIT=y -+# CONFIG_5x5_KEYBOARD_JZ is not set -+# CONFIG_64BIT is not set -+# CONFIG_ARCH_HAS_ILOG2_U32 is not set -+# CONFIG_ARCH_HAS_ILOG2_U64 is not set -+CONFIG_ARCH_POPULATES_NODE_MAP=y -+# CONFIG_ARCH_SUPPORTS_MSI is not set -+CONFIG_ARCH_SUPPORTS_OPROFILE=y -+# CONFIG_ARPD is not set -+CONFIG_BASE_SMALL=0 -+# CONFIG_BCM47XX is not set -+CONFIG_BITREVERSE=y -+# CONFIG_BLK_DEV_INITRD is not set -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_RAM=y -+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -+CONFIG_BLK_DEV_RAM_COUNT=16 -+CONFIG_BLK_DEV_RAM_SIZE=4096 -+CONFIG_BLK_DEV_SD=y -+# CONFIG_BRIDGE is not set -+# CONFIG_BROADCOM_PHY is not set -+# CONFIG_BSD_DISKLABEL is not set -+# CONFIG_BSD_PROCESS_ACCT is not set -+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -+# CONFIG_CONFIGFS_FS is not set -+# CONFIG_CPU_BIG_ENDIAN is not set -+CONFIG_CPU_FREQ=y -+# CONFIG_CPU_FREQ_DEBUG is not set -+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set -+CONFIG_CPU_FREQ_JZ=y -+CONFIG_CPU_FREQ_STAT=y -+# CONFIG_CPU_FREQ_STAT_DETAILS is not set -+CONFIG_CPU_FREQ_TABLE=y -+CONFIG_CPU_HAS_LLSC=y -+CONFIG_CPU_HAS_PREFETCH=y -+CONFIG_CPU_HAS_SYNC=y -+CONFIG_CPU_LITTLE_ENDIAN=y -+# CONFIG_CPU_LOONGSON2 is not set -+CONFIG_CPU_MIPS32=y -+CONFIG_CPU_MIPS32_R1=y -+# CONFIG_CPU_MIPS32_R2 is not set -+# CONFIG_CPU_MIPS64_R1 is not set -+# CONFIG_CPU_MIPS64_R2 is not set -+CONFIG_CPU_MIPSR1=y -+# CONFIG_CPU_NEVADA is not set -+# CONFIG_CPU_R10000 is not set -+# CONFIG_CPU_R3000 is not set -+# CONFIG_CPU_R4300 is not set -+# CONFIG_CPU_R4X00 is not set -+# CONFIG_CPU_R5000 is not set -+# CONFIG_CPU_R5432 is not set -+# CONFIG_CPU_R6000 is not set -+# CONFIG_CPU_R8000 is not set -+# CONFIG_CPU_RM7000 is not set -+# CONFIG_CPU_RM9000 is not set -+# CONFIG_CPU_SB1 is not set -+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -+CONFIG_CPU_SUPPORTS_HIGHMEM=y -+# CONFIG_CPU_TX39XX is not set -+# CONFIG_CPU_TX49XX is not set -+# CONFIG_CPU_VR41XX is not set -+CONFIG_CRYPTO_ALGAPI=y -+CONFIG_CRYPTO_BLKCIPHER=y -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_HW=y -+# CONFIG_CRYPTO_LZO is not set -+CONFIG_CRYPTO_MANAGER=y -+CONFIG_CRYPTO_MD5=y -+CONFIG_DEFAULT_AS=y -+# CONFIG_DEFAULT_DEADLINE is not set -+CONFIG_DEFAULT_IOSCHED="anticipatory" -+CONFIG_DEFAULT_TCP_CONG="cubic" -+# CONFIG_DM9000 is not set -+CONFIG_DMA_NEED_PCI_MAP_STATE=y -+CONFIG_DMA_NONCOHERENT=y -+CONFIG_DNOTIFY=y -+CONFIG_DUMMY_CONSOLE=y -+CONFIG_ELF_CORE=y -+CONFIG_ENABLE_MUST_CHECK=y -+CONFIG_EXT2_FS=y -+# CONFIG_EXT2_FS_POSIX_ACL is not set -+# CONFIG_EXT2_FS_SECURITY is not set -+CONFIG_EXT2_FS_XATTR=y -+# CONFIG_FAIR_CGROUP_SCHED is not set -+CONFIG_FAIR_GROUP_SCHED=y -+CONFIG_FAIR_USER_SCHED=y -+CONFIG_FAT_FS=y -+CONFIG_FB=y -+# CONFIG_FB_BACKLIGHT is not set -+CONFIG_FB_CFB_COPYAREA=y -+CONFIG_FB_CFB_FILLRECT=y -+CONFIG_FB_CFB_IMAGEBLIT=y -+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -+# CONFIG_FB_DDC is not set -+CONFIG_FB_DEFERRED_IO=y -+# CONFIG_FB_JZ4740_SLCD is not set -+# CONFIG_FB_JZLCD_4730_4740 is not set -+CONFIG_FB_JZSOC=y -+# CONFIG_FB_MACMODES is not set -+# CONFIG_FB_MODE_HELPERS is not set -+# CONFIG_FB_S1D13XXX is not set -+# CONFIG_FB_SVGALIB is not set -+# CONFIG_FB_SYS_COPYAREA is not set -+# CONFIG_FB_SYS_FILLRECT is not set -+# CONFIG_FB_SYS_FOPS is not set -+# CONFIG_FB_SYS_IMAGEBLIT is not set -+# CONFIG_FB_TILEBLITTING is not set -+# CONFIG_FB_VIRTUAL is not set -+# CONFIG_FIRMWARE_EDID is not set -+# CONFIG_FIXED_PHY is not set -+CONFIG_FONTS=y -+# CONFIG_FONT_10x18 is not set -+# CONFIG_FONT_6x11 is not set -+# CONFIG_FONT_7x14 is not set -+CONFIG_FONT_8x16=y -+CONFIG_FONT_8x8=y -+# CONFIG_FONT_ACORN_8x8 is not set -+# CONFIG_FONT_MINI_4x6 is not set -+# CONFIG_FONT_PEARL_8x8 is not set -+# CONFIG_FONT_SUN12x22 is not set -+# CONFIG_FONT_SUN8x16 is not set -+CONFIG_FORCE_MAX_ZONEORDER=12 -+CONFIG_FRAMEBUFFER_CONSOLE=y -+# CONFIG_FRAMEBUFFER_CONSOLE_CURSOR_FLASH is not set -+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -+CONFIG_FS_MBCACHE=y -+CONFIG_FS_POSIX_ACL=y -+# CONFIG_FW_LOADER is not set -+CONFIG_GENERIC_CLOCKEVENTS=y -+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -+CONFIG_GENERIC_CMOS_UPDATE=y -+CONFIG_GENERIC_FIND_NEXT_BIT=y -+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set -+# CONFIG_HAMRADIO is not set -+CONFIG_HAS_DMA=y -+CONFIG_HAS_IOMEM=y -+CONFIG_HAS_IOPORT=y -+CONFIG_HID=y -+CONFIG_HID_SUPPORT=y -+# CONFIG_HIGH_RES_TIMERS is not set -+CONFIG_HW_CONSOLE=y -+# CONFIG_HW_RANDOM is not set -+# CONFIG_I2C is not set -+# CONFIG_I2S_AK4642EN is not set -+# CONFIG_I2S_DLV is not set -+CONFIG_I2S_ICODEC=y -+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -+# CONFIG_IBM_NEW_EMAC_RGMII is not set -+# CONFIG_IBM_NEW_EMAC_TAH is not set -+# CONFIG_IBM_NEW_EMAC_ZMII is not set -+# CONFIG_IDE is not set -+CONFIG_INET_DIAG=m -+CONFIG_INET_TCP_DIAG=m -+CONFIG_INOTIFY=y -+CONFIG_INOTIFY_USER=y -+CONFIG_INPUT=y -+CONFIG_INPUT_KEYBOARD=y -+CONFIG_INPUT_MOUSEDEV=y -+CONFIG_INPUT_MOUSEDEV_PSAUX=y -+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -+CONFIG_INSTRUMENTATION=y -+CONFIG_IOSCHED_AS=y -+CONFIG_IOSCHED_CFQ=y -+# CONFIG_IP_ADVANCED_ROUTER is not set -+# CONFIG_IP_MULTICAST is not set -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_BOOTP=y -+CONFIG_IP_PNP_DHCP=y -+# CONFIG_IP_PNP_RARP is not set -+# CONFIG_JFFS2_FS is not set -+# CONFIG_JZ4720_VIRGO is not set -+# CONFIG_JZ4725_DIPPER is not set -+# CONFIG_JZ4730_PMP is not set -+# CONFIG_JZ4740_LEO is not set -+# CONFIG_JZ4740_LYRA is not set -+CONFIG_JZ4740_PAVO=y -+# CONFIG_JZ4750D_FUWA1 is not set -+# CONFIG_JZ4750_APUS is not set -+# CONFIG_JZ4750_FUWA is not set -+CONFIG_JZCHAR=y -+CONFIG_JZCS8900=y -+CONFIG_JZRISC=y -+CONFIG_JZSOC=y -+# CONFIG_JZ_CIM is not set -+# CONFIG_JZ_OW is not set -+CONFIG_JZ_POWEROFF=y -+CONFIG_JZ_SADC=y -+CONFIG_JZ_TCSM=y -+CONFIG_JZ_TPANEL=y -+# CONFIG_JZ_TPANEL_AK4182 is not set -+# CONFIG_JZ_TPANEL_ATA2508 is not set -+# CONFIG_JZ_TPANEL_UCB1400 is not set -+# CONFIG_JZ_TPANEL_WM9712 is not set -+# CONFIG_JZ_UDC_HOTPLUG is not set -+CONFIG_KALLSYMS=y -+CONFIG_KEYBOARD_ATKBD=y -+# CONFIG_KEYBOARD_GPIO is not set -+# CONFIG_KEYBOARD_JZ is not set -+# CONFIG_KEYBOARD_LKKBD is not set -+# CONFIG_KEYBOARD_NEWTON is not set -+# CONFIG_KEYBOARD_STOWAWAY is not set -+# CONFIG_KEYBOARD_SUNKBD is not set -+# CONFIG_KEYBOARD_XTKBD is not set -+CONFIG_KMOD=y -+CONFIG_LEGACY_PTYS=y -+CONFIG_LEGACY_PTY_COUNT=2 -+# CONFIG_LEMOTE_FULONG is not set -+CONFIG_LOCALVERSION_AUTO=y -+CONFIG_LOCKD=y -+CONFIG_LOCK_KERNEL=y -+CONFIG_LOGO=y -+CONFIG_LOGO_LINUX_CLUT224=y -+CONFIG_LOGO_LINUX_MONO=y -+CONFIG_LOGO_LINUX_VGA16=y -+# CONFIG_MACH_ALCHEMY is not set -+# CONFIG_MACH_DECSTATION is not set -+# CONFIG_MACH_JAZZ is not set -+# CONFIG_MACH_VR41XX is not set -+# CONFIG_MAC_PARTITION is not set -+CONFIG_MAGIC_SYSRQ=y -+# CONFIG_MARKERS is not set -+# CONFIG_MDIO_BITBANG is not set -+CONFIG_MINIX_FS=y -+CONFIG_MIPS=y -+# CONFIG_MIPS_ATLAS is not set -+# CONFIG_MIPS_COBALT is not set -+CONFIG_MIPS_L1_CACHE_SHIFT=5 -+# CONFIG_MIPS_MALTA is not set -+CONFIG_MIPS_MT_DISABLED=y -+# CONFIG_MIPS_MT_SMP is not set -+# CONFIG_MIPS_MT_SMTC is not set -+# CONFIG_MIPS_SEAD is not set -+# CONFIG_MIPS_SIM is not set -+CONFIG_MMC=y -+CONFIG_MMC_BLOCK=y -+CONFIG_MMC_BLOCK_BOUNCE=y -+# CONFIG_MMC_DEBUG is not set -+# CONFIG_MMC_JZ is not set -+# CONFIG_MMC_UNSAFE_RESUME is not set -+CONFIG_MODULE_SRCVERSION_ALL=y -+CONFIG_MODVERSIONS=y -+CONFIG_MSDOS_FS=y -+CONFIG_MTD=y -+# CONFIG_MTD_ABSENT is not set -+# CONFIG_MTD_ALAUDA is not set -+CONFIG_MTD_BADBLOCK_FLAG_PAGE=127 -+CONFIG_MTD_BLKDEVS=y -+CONFIG_MTD_BLOCK=y -+# CONFIG_MTD_BLOCK2MTD is not set -+# CONFIG_MTD_CFI is not set -+CONFIG_MTD_CFI_I1=y -+CONFIG_MTD_CFI_I2=y -+# CONFIG_MTD_CFI_I4 is not set -+# CONFIG_MTD_CFI_I8 is not set -+CONFIG_MTD_CHAR=y -+# CONFIG_MTD_CMDLINE_PARTS is not set -+# CONFIG_MTD_COMPLEX_MAPPINGS is not set -+# CONFIG_MTD_CONCAT is not set -+# CONFIG_MTD_DEBUG is not set -+# CONFIG_MTD_DOC2000 is not set -+# CONFIG_MTD_DOC2001 is not set -+# CONFIG_MTD_DOC2001PLUS is not set -+# CONFIG_MTD_HW_BCH_ECC is not set -+CONFIG_MTD_HW_HM_ECC=y -+# CONFIG_MTD_HW_RS_ECC is not set -+# CONFIG_MTD_JEDECPROBE is not set -+CONFIG_MTD_MAP_BANK_WIDTH_1=y -+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -+CONFIG_MTD_MAP_BANK_WIDTH_2=y -+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -+CONFIG_MTD_MAP_BANK_WIDTH_4=y -+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -+# CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE is not set -+# CONFIG_MTD_MTDRAM is not set -+CONFIG_MTD_NAND=y -+# CONFIG_MTD_NAND_CS2 is not set -+# CONFIG_MTD_NAND_CS3 is not set -+# CONFIG_MTD_NAND_CS4 is not set -+# CONFIG_MTD_NAND_DISKONCHIP is not set -+# CONFIG_MTD_NAND_ECC_SMC is not set -+CONFIG_MTD_NAND_IDS=y -+CONFIG_MTD_NAND_JZ4740=y -+CONFIG_MTD_NAND_MULTI_PLANE=y -+# CONFIG_MTD_NAND_MUSEUM_IDS is not set -+# CONFIG_MTD_NAND_NANDSIM is not set -+# CONFIG_MTD_NAND_PLATFORM is not set -+# CONFIG_MTD_NAND_VERIFY_WRITE is not set -+# CONFIG_MTD_ONENAND is not set -+CONFIG_MTD_OOB_COPIES=3 -+CONFIG_MTD_PARTITIONS=y -+# CONFIG_MTD_PHRAM is not set -+# CONFIG_MTD_PLATRAM is not set -+# CONFIG_MTD_RAM is not set -+# CONFIG_MTD_REDBOOT_PARTS is not set -+# CONFIG_MTD_ROM is not set -+# CONFIG_MTD_SLRAM is not set -+# CONFIG_MTD_SW_HM_ECC is not set -+# CONFIG_MTD_UBI_BLKDEVS is not set -+# CONFIG_NETFILTER is not set -+# CONFIG_NET_SCHED is not set -+# CONFIG_NEW_LEDS is not set -+CONFIG_NFS_ACL_SUPPORT=y -+CONFIG_NFS_DIRECTIO=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NLS=y -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_CODEPAGE_936=y -+CONFIG_NLS_ISO8859_1=y -+# CONFIG_NO_IOPORT is not set -+CONFIG_OSS_OBSOLETE=y -+# CONFIG_PACKET_MMAP is not set -+# CONFIG_PAGE_SIZE_16KB is not set -+CONFIG_PAGE_SIZE_4KB=y -+# CONFIG_PAGE_SIZE_64KB is not set -+# CONFIG_PAGE_SIZE_8KB is not set -+CONFIG_PHYLIB=y -+CONFIG_PM=y -+# CONFIG_PMC_MSP is not set -+# CONFIG_PMC_YOSEMITE is not set -+# CONFIG_PM_DEBUG is not set -+CONFIG_PM_LEGACY=y -+# CONFIG_PNP is not set -+# CONFIG_PNX8550_JBS is not set -+# CONFIG_PNX8550_STB810 is not set -+CONFIG_PREEMPT=y -+CONFIG_PREEMPT_BKL=y -+# CONFIG_PREEMPT_NONE is not set -+# CONFIG_QSEMI_PHY is not set -+CONFIG_REED_SOLOMON=y -+CONFIG_REED_SOLOMON_DEC8=y -+CONFIG_REED_SOLOMON_ENC8=y -+CONFIG_RELAY=y -+CONFIG_ROOT_NFS=y -+CONFIG_RPCSEC_GSS_KRB5=y -+# CONFIG_RTC is not set -+# CONFIG_RTC_JZ is not set -+CONFIG_RTC_LIB=y -+# CONFIG_RTC_PCF8563 is not set -+CONFIG_RWSEM_GENERIC_SPINLOCK=y -+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -+CONFIG_SCSI=y -+# CONFIG_SCSI_MULTI_LUN is not set -+CONFIG_SCSI_WAIT_SCAN=m -+# CONFIG_SDIO_UART is not set -+CONFIG_SECCOMP=y -+# CONFIG_SERIAL_8250_EXTENDED is not set -+CONFIG_SERIAL_8250_NR_UARTS=4 -+CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -+CONFIG_SERIO=y -+# CONFIG_SERIO_I8042 is not set -+CONFIG_SERIO_LIBPS2=y -+# CONFIG_SERIO_RAW is not set -+CONFIG_SERIO_SERPORT=y -+# CONFIG_SGI_IP22 is not set -+# CONFIG_SGI_IP27 is not set -+# CONFIG_SGI_IP32 is not set -+# CONFIG_SIBYTE_BIGSUR is not set -+# CONFIG_SIBYTE_CARMEL is not set -+# CONFIG_SIBYTE_CRHINE is not set -+# CONFIG_SIBYTE_CRHONE is not set -+# CONFIG_SIBYTE_LITTLESUR is not set -+# CONFIG_SIBYTE_PTSWARM is not set -+# CONFIG_SIBYTE_RHONE is not set -+# CONFIG_SIBYTE_SENTOSA is not set -+# CONFIG_SIBYTE_SWARM is not set -+CONFIG_SLABINFO=y -+# CONFIG_SMSC_PHY is not set -+CONFIG_SOC_JZ4740=y -+CONFIG_SOUND=y -+# CONFIG_SOUND_JZ_AC97 is not set -+CONFIG_SOUND_JZ_I2S=y -+# CONFIG_SOUND_MSNDCLAS is not set -+# CONFIG_SOUND_MSNDPIN is not set -+CONFIG_SOUND_PRIME=y -+# CONFIG_SPARSEMEM_STATIC is not set -+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -+CONFIG_SSB_POSSIBLE=y -+CONFIG_SUNRPC=y -+CONFIG_SUNRPC_GSS=y -+# CONFIG_SUSPEND is not set -+# CONFIG_SYN_COOKIES is not set -+CONFIG_SYSFS_DEPRECATED=y -+CONFIG_SYSVIPC_SYSCTL=y -+CONFIG_SYS_HAS_CPU_MIPS32_R1=y -+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -+# CONFIG_TCP_CONG_ADVANCED is not set -+CONFIG_TCP_CONG_CUBIC=y -+# CONFIG_TICK_ONESHOT is not set -+# CONFIG_TOSHIBA_JMR3927 is not set -+# CONFIG_TOSHIBA_RBTX4927 is not set -+# CONFIG_TOSHIBA_RBTX4938 is not set -+CONFIG_TRAD_SIGNALS=y -+CONFIG_USB=y -+# CONFIG_USB_ARCH_HAS_EHCI is not set -+# CONFIG_USB_DEVICEFS is not set -+CONFIG_USB_DEVICE_CLASS=y -+CONFIG_USB_HID=y -+CONFIG_USB_HIDDEV=y -+CONFIG_USB_MON=y -+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set -+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set -+CONFIG_USB_OHCI_HCD=y -+# CONFIG_USB_PERSIST is not set -+CONFIG_USB_STORAGE=y -+# CONFIG_USB_STORAGE_ALAUDA is not set -+# CONFIG_USB_STORAGE_DATAFAB is not set -+# CONFIG_USB_STORAGE_DPCM is not set -+# CONFIG_USB_STORAGE_FREECOM is not set -+# CONFIG_USB_STORAGE_JUMPSHOT is not set -+# CONFIG_USB_STORAGE_KARMA is not set -+# CONFIG_USB_STORAGE_SDDR09 is not set -+# CONFIG_USB_STORAGE_SDDR55 is not set -+# CONFIG_USB_STORAGE_USBAT is not set -+# CONFIG_USB_SUSPEND is not set -+# CONFIG_USER_NS is not set -+CONFIG_VFAT_FS=y -+# CONFIG_VGASTATE is not set -+# CONFIG_VGA_CONSOLE is not set -+# CONFIG_VLAN_8021Q is not set -+CONFIG_VM_EVENT_COUNTERS=y -+CONFIG_VT=y -+CONFIG_VT_CONSOLE=y -+CONFIG_VT_HW_CONSOLE_BINDING=y -+# CONFIG_WATCHDOG is not set -+# CONFIG_WLAN_80211 is not set -+CONFIG_YAFFS_AUTO_YAFFS2=y -+CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10 -+CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK=y -+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set -+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set -+# CONFIG_YAFFS_DOES_ECC is not set -+# CONFIG_YAFFS_ECC_HAMMING is not set -+CONFIG_YAFFS_ECC_RS=y -+CONFIG_YAFFS_FS=y -+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y -+CONFIG_YAFFS_YAFFS1=y -+CONFIG_YAFFS_YAFFS2=y -+CONFIG_ZONE_DMA_FLAG=0 -Index: target/linux/jz47x0/Makefile -=================================================================== ---- target/linux/jz47x0/Makefile (revision 0) -+++ target/linux/jz47x0/Makefile (revision 0) -@@ -0,0 +1,24 @@ -+# -+# Copyright (C) 2009 OpenWrt.org -+# -+# This is free software, licensed under the GNU General Public License v2. -+# See /LICENSE for more information. -+# -+include $(TOPDIR)/rules.mk -+ -+ARCH:=mipsel -+BOARD:=jz47x0 -+BOARDNAME:=Ingenic JZ47x0 -+FEATURES:=squashfs jffs2 -+ -+LINUX_VERSION:=2.6.24.7 -+ -+include $(INCLUDE_DIR)/target.mk -+ -+DEFAULT_PACKAGES += hostapd-mini kmod-madwifi gpioctl -+ -+define Target/Description -+ Build firmware images for Ingenic JZ47x0 based boards. -+endef -+ -+$(eval $(call BuildTarget)) -Index: target/linux/jz47x0/patches-2.6.24/001-board.patch -=================================================================== ---- target/linux/jz47x0/patches-2.6.24/001-board.patch (revision 0) -+++ target/linux/jz47x0/patches-2.6.24/001-board.patch (revision 0) -@@ -0,0 +1,233914 @@ -+diff -urN linux-2.6.24.7.old/Changelog linux-2.6.24.7/Changelog -+--- linux-2.6.24.7.old/Changelog 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/Changelog 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,364 @@ -++2009.02.17 -++* Modify oss driver to support jz4750 i2s codec. -++ Update Files: -++ sound/oss/Kconfig -++ sound/oss/Makefile -++ sound/oss/jz_i2s.c -++ Add Files: -++ sound/oss/jzdlv.h -++ sound/oss/jzdlv.c -++ -++2008.12.08 -++* Power management is supported for jz4750. -++ Update Files: -++ arch/mips/jz4750/pm.c -++ drivers/char/jzchar/poweroff.c -++ -++2008.12.04 -++* Whether NAND multiple planes operation for one partition is used or not could be -++ determined by the value of use_planes in partition_info[] in drivers/mtd/nand/jz47xx_nand.c -++ Updated files: -++ include/linux/mtd/partitions.h -++ drivers/mtd/nand/nand_base.c -++ drivers/mtd/nand/jz4740_nand.c -++ drivers/mtd/mtdpart.c -++* Supported 4KB page size nand with 2 planes -++ Update Files: -++ include/linux/mtd/nand.h -++ drivers/mtd/nand/nand_base.c -++ fs/yaffs2/utils/mkyaffs2image.c -++ drivers/mtd/mtd-utils/nandwrite_mlc.c -++ -++ -++2008.11.07 -++* The ubi was modified to support MTD of 64bit. -++ Updated file: -++ drivers/mtd/ubi/io.c -++* The ubi and ubifs were modified by changing vmalloc and vfree to kmalloc and kfree -++ to provide DMA buffer for NAND driver. But the NAND driver will use DMA buffer in -++ itself instead of in ubi and ubifs when CONFIG_MTD_NAND_DMABUF is defined. -++ Updated files: -++ drivers/mtd/ubi/build.c -++ drivers/mtd/ubi/cdev.c -++ drivers/mtd/ubi/gluebi.c -++ drivers/mtd/ubi/misc.c -++ drivers/mtd/ubi/scan.c -++ drivers/mtd/ubi/ubiblk.c -++ drivers/mtd/ubi/upd.c -++ drivers/mtd/ubi/vtbl.c -++ fs/ubifs/build.c -++ fs/ubifs/log.c -++ fs/ubifs/lpt.c -++ fs/ubifs/lpt_commit.c -++ fs/ubifs/orphan.c -++ fs/ubifs/recovery.c -++ fs/ubifs/replay.c -++ fs/ubifs/super.c -++ -++ -++2008.10.31 -++* Converted MTD from 32bit to 64bit to support the NAND larger than 4GB, and yaffs2 was -++ modified accordingly. -++ Updated file: -++ include/mtd/mtd-abi.h -++ include/linux/mtd/mtd.h -++ include/linux/mtd/partitions.h -++ include/linux/mtd/nand.h -++ drivers/mtd/mtdcore.c -++ drivers/mtd/mtdchar.c -++ drivers/mtd/mtdpart.c -++ drivers/mtd/mtdblock-jz.c -++ drivers/mtd/nand/nand_base.c -++ drivers/mtd/nand/nand_bbt.c -++ drivers/mtd/mtd-utils/include/mtd/mtd-abi.h -++ drivers/mtd/mtd-utils/flash_eraseall.c -++ drivers/mtd/mtd-utils/nandwrite_mlc.c -++ drivers/mtd/mtd-utils/nandwrite.c -++ fs/yaffs2/yaffs_fs.c -++ fs/yaffs2/yaffs_mtdif.c -++ fs/yaffs2/yaffs_mtdif2.c -++ -++2008.10.29 -++* Modified yaffs2 utils mkyaffs2image to support writting 4KB pagesize NAND. NAND layout -++ is (0 - raw(512B pagesize), 1 - nand_oob_64(2KB pagesize), 2 - nand_oob_128(4KB pagesize)). -++ -++ Updated file: -++ fs/yaffs2/utils/mkyaffs2image.c -++ -++2008.10.27 -++* Supported multiply chip selecting for NAND flash. -++ Updated files: -++ include/linux/mtd/nand.h -++ drivers/mtd/nand/nand_base.c -++ drivers/mtd/nand/jz4750_nand.c -++ drivers/mtd/nand/jz4740_nand.c -++ -++2008.10.23 -++* Modified yaffs2 utils mkyaffs2image to enable writing soft reed-solomn ECC for -++ yaffs2 file system information in oob area of MLC nand, getting CONFIG_YAFFS_ECC_RS -++ from .config, so when CONFIG_YAFFS_ECC_RS is changed, mkyaffs2image should be built -++ again. -++ Updated files: -++ fs/yaffs2/yaffs_ecc.c -++ fs/yaffs2/utils/Makefile -++ Added files: -++ fs/yaffs2/utils/ssfdc_rs_ecc.c -++ fs/yaffs2/utils/ssfdc_rs_ecc.h -++ -++2008.09.26 -++ -++* Fixed a fatal bug for mplayer, which may cause some files cannot be played and -++ the system is crashed. -++ Updated file: arch/mips/jz4740/proc.c -++ -++2008.08.30 -++* For jz4750, DMA clock for each channel should be enabled before using the channel. -++ So REG_DMAC_DMACKE and __dmac_channel_enable_clk(n) were added. -++ Updated files: -++ include/asm-mips/mach-jz4750/regs.h -++ include/asm-mips/mach-jz4750/ops.h -++ Regen, -++ -++2008.08.19 -++* Modify jzfb_mmap() for cacheable framebuffer access. -++ Updated files: -++ drivers/video/jzlcd.c -++ drivers/video/jz4740_slcd.c -++ drivers/video/jz4750_lcd.c -++ -++2008.08.15 -++* Modify ipu interface to toggle PID of MPlayer in TLB. -++* Modify OSS ioctl function to play movie with mono channel better. -++ Update Files: -++ arch/mips/jz4740/proc.c -++ sound/oss/jz_i2s.c -++ Richard Feng, -++ -++2008.08.04 -++* Check whether the free block is erased before erasing it, 'unsigned int' instead of -++ 'unsigned short' was used to store block number, and heap sort for lifetime after -++ erasing a block was replaced by another faster method. -++ Update File: -++ drivers/mtd/mtdblock-jz.uu -++ -++* Cache read was used in nand_read_page_hwecc_rs() for Jz4740. -++ Update File: -++ drivers/mtd/nand/nand_base.c -++ -++* Faster timing in REG_EMC_SMCR1 whose value is 0x09221200 was used. -++ Update File: -++ drivers/mtd/nand/jz4740_nand.c -++ -++ Regen, -++ -++2008.07.21 -++* Supported 4KB page size nand -++ Update File: -++ drivers/mtd/nand/nand_base.c -++ include/linux/mtd/nand.h -++ include/mtd/mtd-abi.h -++ drivers/mtd/mtd-utils/include/mtd/mtd-abi.h -++ Regen, -++ -++2008.07.18 -++* Soft reed solomon ECC was supported for yaffs2 information which is 16 bytes in nand -++ oob, and it should be used for MLC nand. -++ Update File: -++ fs/yaffs2/yaffs_ecc.c -++ fs/yaffs2/yaffs_ecc.h -++ fs/yaffs2/yaffs_fs.c -++ fs/yaffs2/yaffs_packedtags2.c -++ Regen, -++ -++2008.07.10 -++* Added support to generate any frequency baud rate of uart for both Jz4740 and Jz4750. -++ Update File: -++ drivers/serial/8250.c -++ Regen, -++ -++2008.07.03 -++* Modified Jz4750's INTC, CIM, TSSI, macros. -++ Update Files: -++ include/asm-mips/mach-jz4750/regs.h -++ include/asm-mips/mach-jz4750/ops.h -++ -++2008.06.24 -++* Combined Jz4750 SLCD Controller support into drivers/video/jz4750_lcd.c. -++* drivers/video/jz4750_lcd.c, now support: LCD Controller, Slcd Controller, TVE. -++* And add smart lcd panel TRULY_TFT_GG1P0319LTSW_W support. -++ Update Files: -++ drivers/video/Kconfig -++ drivers/video/jz4750_lcd.h -++ drivers/video/jz4750_lcd.c -++ Wolfgang Wang, -++ -++2008.06.20 -++* Add Jz4750 LCDC and TVE driver. -++ Update Files: -++ arch/asm-mips/mach-jz4750/regs.h -++ arch/asm-mips/mach-jz4750/ops.h -++ drivers/video/Kconfig -++ drivers/video/Makefile -++ Add Files: -++ drivers/video/jz4750_lcd.h -++ drivers/video/jz4750_lcd.c -++ drivers/video/jz4750_tve.h -++ drivers/video/jz4750_tve.c -++ -++2008.06.12 -++* Modified CONFIG_FB_JZXXX macros, rename drivers/video/jzslcd.x to drivers/video/jz4740_slcd.x -++ Update Files: -++ drivers/video/Kconfig -++ drivers/video/Makefile -++ arch/mips/configs/dipper_defconfig -++ arch/mips/configs/leo_defconfig -++ arch/mips/configs/lyra_defconfig -++ arch/mips/configs/pavo_defconfig -++ arch/mips/configs/virgo_defconfig -++ -++ -++2008.06.10 -++* Add jz_clocksource, upgrade the system time's accuracy from 10ms to about 1(or 2) us. -++ but the system timer remained 10ms. -++ Files modified: -++ arch/mips/jz4730/time.c -++ arch/mips/jz4740/time.c -++ arch/mips/jz4750/time.c -++ -++ -++2008.05.31 -++ -++* Updated UBIFS. -++ -++2008.05.30 -++ -++* Added JZ4720 virgo board support. -++ -++2008.05.29 -++ -++* Added definition of CONFIG_SOC_JZ4725 and CONFIG_SOC_JZ4720. -++* Added selection of 4-bit/1-bit data bus for MMC/SD card driver. -++* Added dipper_defconfig for JZ4725 DIPPER board. -++ -++2008.05.29: -++ -++* Modified sound/oss/jz_i2s.c to increase the sound buffer. -++* Modified pavo_defconfig to select the oss sound driver by default. -++* Fixed jzlcd.h for jz4730 pmp. -++* Modified jzcs8900a.c to not test the chip ID. -++ -++2008.05.22: -++ -++* jzcs8900a.c: fixed the bug of "No network devices available". -++ -++2008.05.13: -++ -++* Rewrote all of the UBI and UBIFS codes. -++ -++2008.05.07: -++* Add GPIO group E group F irq, DMAC1 irq. Add SSI1 macros. -++ -++ -++2008.05.06: -++ -++* Modified MMC/SD driver jz_mmc.c to support PM callback. -++ -++2008.05.04: -++ -++* Fixed a bug of mtdblock-jz.uu of using the badblock_table. -++ -++2008.04.26: -++ -++* Patch jz4740_nand.c to optimize the RS correction algorithm. -++ -++2008.04.24 -++* Jzlcd driver add Framebuffer Rotate support. -++ Update files: -++ drivers/video/Kconfig -++ drivers/video/jzlcd.h -++ drivers/video/jzlcd.c -++ -++ -++2008.04.21: -++* Modified LCD_CFG_MODE_INTER_CCIR656 define -++ #define LCD_CFG_MODE_INTER_CCIR656 (5 << LCD_CFG_MODE_BIT) -++ should be ==>> -++ #define LCD_CFG_MODE_INTER_CCIR656 (6 << LCD_CFG_MODE_BIT) -++ Update files: -++ include/asm-mips/mach-jz4730/regs.h -++ include/asm-mips/mach-jz4740/regs.h -++ include/asm-mips/mach-jz4750/regs.h -++ -++2008.04.14: -++ -++* Modify drivers/video/jzslcd.c to suport Smart LCD switches between -++ always refresh and event-driven refresh . -++ -++2008.04.01: -++ -++* Support multi-framebuffers, update files: -++ drivers/video/Kconfig, add: CONFIG_JZLCD_FRAMEBUFFER_MAX=1 -++ drivers/video/jzlcd.h -++ drivers/video/jzlcd.c -++ arch/mips/configs/pavo_defconfig, add: CONFIG_JZLCD_FRAMEBUFFER_MAX=1 -++ -++ -++2008.03.29: -++ -++* Modified sound/soc/jz4740/jz4740-i2s.c to support 32KHz PCM sample. -++ -++2008.03.28 -++ -++* Ported new mtd-utils and mkfs.ubifs. -++ -++2008.03.27 -++ -++* board_fuwa.h, change GPIO_DISP_OFF_N to GPD25. -++* Added lyra_defconfig for JZ4740 LYRA (MP4) board. -++ -++2008.03.24: -++ -++* Added jzslcd.c for Smart LCD framebuffer driver. -++* Modified rtc_jz.c to use some functions in rtc library instead of our function. -++ -++* Added jz_keypad.c and gpio_keys.c for scan keypad drivers. -++ -++2008.03.19: -++ -++* Added block-jz.c to support block device layer on top of ubi. -++ -++ -++2008.03.17: -++ -++* Modified jz4740_udc.c to enable the suspend irq when host unloads us. -++ -++* pavo_defconfig: select CONFIG_WIRELESS_EXT, CONFIG_PNP and CONFIG_SERIAL_8250_PNP. -++ -++ -++2008.03.14: -++ -++* Modified jz_ts.c jz_ts.h and sadc.c to release CPU by interrupt mode instead of pio mode. -++ -++ -++2008.03.13: -++ -++* Fixed a bug in jz4740_udc.c and jz4730_udc.c during rmmod the driver. -++ -++ -++2008.03.10: -++ -++* Modified jz_i2s.c to fix the jz_audio_release(). -++ -++2008.03.08: -++ -++* Fixed udc_hotplug.c to avoid the "unexpected IRQ". -++* Fixed jz4740/cpufreq.c of calculating the new_mclk. -++ -++2008.03.05: -++ -++* Modified drivers/video/console/fbcon.c by adding fb_flashcursor selection. -++ -++ -++2008.03.04: -++ -++* Initial release. -+diff -urN linux-2.6.24.7.old/README-JZ linux-2.6.24.7/README-JZ -+--- linux-2.6.24.7.old/README-JZ 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/README-JZ 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1181 @@ -++ -++ Linux 2.6 Kernel Release for Ingenic -++ -++ (Updated: 2008-12-29) -++ -++------------- -++** Content ** -++------------- -++ -++** Quick start ** -++** Supported SOC and Platforms ** -++** Overview of source tree ** -++** NAND Flash Filesystem ** -++** UBI, UBIFS and UBI Block Layer ** -++** UBI and UBIFS images ** -++** YAFFS2 ** -++** MTD Block Layer ** -++** About Bad Blocks of NAND ** -++** SLC and MLC NAND Flash ** -++** Initramfs ** -++** Audio full duplex mode ** -++** Support ** -++ -++ -++----------------- -++** Quick Start ** -++----------------- -++ -++To build linux 2.6, you needs a mipsel-linux-gcc version 4. Please -++download it from Ingenic website http://www.ingenic.cn. -++ -++You should have downloaded the linux-2.6.24.3.tar.bz2 and the latest kernel -++patch. The patch file was named as "linux-2.6.24.3-jz-yyyymmdd.patch.gz". -++ -++Follow next steps to install the full kernel source: -++ -++ $ tar -xjf linux-2.6.24.3.tar.bz2 -++ $ cd linux-2.6.24.3 -++ $ gzip -cd ../linux-2.6.24.3-jz-yyyymmdd.patch.gz | patch -p1 -++ -++Now you can configure and build the kernel. -++ -++First, you need to do a 'make board_defconfig' to select a board. -++ -++For example: -++ -++ - make pavo_defconfig # JZ4740 PAVO board default configuration -++ - make pmp_defconfig # JZ4730 PMP ver 2.x board default configuration -++ - make dipper_defconfig # JZ4725 PMP ver 1.x board default configuration -++ -++Then, configure and compile the kernel: -++ -++ - make xconfig or make menuconfig, if you want to change the configuration. -++ - make, make uImage, or make zImage, to build the kernel. -++ -++The ELF format kernel image is linux-2.6.24.3/vmlinux. -++The U-Boot format kernel image is linux-2.6.24.3/arch/mips/boot/uImage. -++The compressed raw kernel image is linux-2.6.24.3/arch/mips/boot/compressed/zImage. -++ -++ -++--------------------------------- -++** Supported SOC and Platforms ** -++--------------------------------- -++ -++This release supports several platforms based on JZ4730, JZ4740 and JZ4750. -++ -++JZ4750 based platforms: -++ -++ - apus: JZ4750 development board -++ -++JZ4740 based platforms: -++ -++ - pavo: JZ4740 reference board -++ - leo: JZ4740 development board -++ -++JZ4730 based platforms: -++ -++ - pmp: JZ4730 reference board version 2.x -++ -++JZ4725 based platforms: -++ -++ - dipper: JZ4725 reference board version 1.x -++ -++ -++----------------------------- -++** Overview of source tree ** -++----------------------------- -++ -++ - Changelog : Revision history -++ - README-JZ : This file -++ - arch/mips/ -++ - kernel/ : MIPS kernel common code -++ - mm/ : MIPS memory common code -++ - jz4730/ : JZ4730 code -++ - jz4740/ : JZ4740 JZ4725 JZ4720 code -++ - jz4750/ : JZ4750 code -++ - configs/ -++ - apus_defconfig : jz4750 based apus default configuration -++ - pavo_defconfig : jz4740 based pavo default configuration -++ - pmp_defconfig : jz4730 based pmp default configuration -++ - dipper_defconfig : jz4725 based dipper default configuration -++ - include/asm-mips/ : MIPS asm common include -++ - jzsoc.h : JZ SoC common include -++ - mach-jz4730/ : JZ4730 SoC headers -++ - mach-jz4740/ : JZ4740 JZ4725 JZ4720 SoC headers -++ - mach-jz4750/ : JZ4750 SoC headers -++ - fs/ -++ - jffs2/ : JFFS2 file system -++ - yaffs2/ : YAFFS2 file system -++ - utils/ : YAFFS2 utilities, like mkyaffs2image -++ - ubifs/ : ubifs file system -++ - mkfs.ubifs/ : mkfs.ubifs util to create UBIFS -++ - sound/ -++ oss/ : OSS audio driver -++ soc/jz4740/ : JZ4740 ALSA audio driver -++ - drivers/ -++ - char/ -++ - serial.c : serial port driver -++ - rtc_pcf8563.c : PCF8563 RTC driver -++ - rtc_jz.c : JZSOC On-Chip RTC driver -++ - jzchar/ : jzchar devices -++ - jz_ts.c : generic touch screen driver -++ - sadc.c : JZ4740 SADC driver -++ - ak4182.c : AK4182 touch driver -++ - udc_hotplug.c : UDC hotplug management -++ - poweroff.c : suspend/poweroff management -++ - input/keyboard/ -++ - jz_keypad.c : scan keypad driver -++ - gpio_keys.c : gpio keypad driver -++ - media/video/ -++ - jz_cim.c : generic camera driver -++ - jz_sensor.c : generic sensor driver -++ - mmc/host/ -++ - jz_mmc.c : jz mmc/sd card driver -++ - mtd/ -++ - mtdblock-jz.c : NAND Flash translation layer driver -++ - nand/ -++ - nand_base.c : NAND flash interface to MTD -++ - jz4730_nand.c : NAND flash definition on JZ4730 boards -++ - jz4740_nand.c : NAND flash definition on JZ4740 boards -++ - jz4750_nand.c : NAND flash definition on JZ4750 boards -++ - ubi/ : MTD utilities like flash_eraseall, nandwrite etc. -++ - ubiblk.c : UBI block layer driver on top of UBI -++ - mtd-utils/ : MTD and UBI utilities, like flash_eraseall, nandwrite and ubimkvol etc. -++ - ubi-utils : UBI utils like ubimkvol/ubirmvol/ubinize etc. -++ - net/ -++ - jz_eth.c : JZ4730 On-Chip ethernet driver -++ - jzcs8900a.c : cs8900a ethernet driver -++ - serial/ -++ - 8250.c : standard 16550A serial driver -++ - usb/ : USB OHCI host driver -++ - usb/host/ -++ ohci-jz.c : JZ OHCI driver -++ - usb/gadget/ -++ - jz4730_udc.c : JZ4730 UDC low-level driver -++ - jz4740_udc.c : JZ4740 and JZ4750 UDC low-level driver -++ - file_storage.c : USB mass storage class driver -++ - serial.c : USB serial class driver -++ - video/ -++ - jzlcd.c : JZ LCD controller framebuffer driver for JZ4730 and JZ4740 -++ - jz4740_slcd.c : JZ Smart LCD controller framebuffer driver for JZ4740 -++ - jz4750_lcd.c : JZ LCD and Smart LCD controller driver for JZ4750 -++ - jz4750_tve.c : JZ TV encoder controller driver for JZ4750 -++ - watchdog/ -++ - jz_wdt.c : JZ On-Chip watchdog driver -++ -++ -++--------------------------- -++** NAND Flash Filesystem ** -++--------------------------- -++ -++NAND Flash is the main non-volatile storage for most embedded devices. -++So, it's very important to implement a stable and reasonable filesystem on -++NAND flash. -++ -++In Linux, the MTD subsystem provides a common interface for operating with -++many flash devices, such as NOR, NAND etc. And the MTD subsystem was modified -++by Ingenic to support the NAND larger than 2GB. -++ -++Above MTD layer, we can implement the YAFFS2 filesystem. Or we can implement -++a MTD block device, on top of it we can implement the general filesystem -++such as FAT and EXT2. -++ -++The Linux 2.6 kernel also implements the UBI (Unsorted Block Images). UBI -++is a software layer above MTD layer which admits of LVM-like logical volumes -++on top of MTD devices, hides some complexities of flash chips like wear -++and bad blocks and provides some other useful capabilities. Please, consult -++the MTD web site for more details (www.linux-mtd.infradead.org). -++ -++On top of UBI, we can implement the UBIFS filesystem. We can also emulate -++block devices above UBI, such that we can use the general filesystem such as -++FAT and EXT2 on it. -++ -++The architecture of the NAND flash filesystem is illustrated as below: -++ -++ -++ -++ +-----------+ +-------------+ +-------------+ -++ | YAFFS2 | | UBIFS | | FAT or EXT2 | Filesystems -++ +-----------+ +-------------+ +-------------+ -++ \ | / \ -++ \ | / \ -++ \ | / \ -++ \ | +-----------------+ +-----------------+ -++ \ | | UBI Block Layer | | MTD Block Layer | -++ \ | +-----------------+ +-----------------+ -++ \ | / / -++ \ | / / -++ \ +-------------+ / -++ \ | UBI | / -++ \ +-------------+ / -++ \ | / -++ +-------------------------------------------+ -++ | MTD | -++ +-------------------------------------------+ -++ | -++ +--------------------+ -++ | nand_base.c | -++ +--------------------+ -++ | -++ +--------------------+ -++ | jz4740_nand.c | -++ +--------------------+ -++ -++ -++The related source codes are listed below: -++ -++fs/yaffs2: YAFFS2 -++fs/ubifs: UBIFS -++fs/fat: FAT -++fs/ext2: EXT2 -++drivers/mtd: MTD -++drivers/mtd/ubi: UBI -++drivers/mtd/ubi/ubiblk.c: UBI Block Layer -++drivers/mtd/mtdblock-jz.c: MTD Block Layer -++drivers/mtd/mtd-utils: MTD and UBI utils (flash_eraseall/ubimkvol/ubinfo/ubinize etc.) -++fs/ubifs/mkfs.ubifs: UBIFS util to create ubifs image (mkfs.ubifs) -++fs/yaffs2/util: YAFFS2 util (mkyaffs2image) -++ -++To build mtd utils, go to drivers/mtd/mtd-utils, type 'make' and -++'make install DESTDIR=/nfsroot/root26'. -++ -++To build yaffs2 util, go to fs/yaffs2/utils and type 'make'. -++ -++To build ubifs util, go to fs/ubifs/mkfs.ubifs and type 'make'. -++ -++Except 'UBI Block Layer' and 'MTD Block Layer', which are implement by Ingenic -++ourself, the others are general in the linux kernel tree. -++ -++User can select any one of these drivers to implement the filesystem. It all -++depends on yourself. -++ -++Following sections will describe how to use these drivers in details. -++ -++ -++------------------------------------ -++** UBI, UBIFS and UBI Block Layer ** -++------------------------------------ -++ -++UBIFS is a new flash file system which is designed to work on top of UBI. -++ -++Here is a short and unsorted list of some of UBIFS features: -++ -++* write-back support - This dramatically improves the throughput of the -++file-system comparing to JFFS2, which is write-through; -++ -++* fast mount time -++ -++* tolerance to unclean reboots - UBIFS is a journaling file system and it -++tolerates sudden crashes and unclean reboots; -++ -++* fast I/O - even with write-back disabled; -++ -++* on-the-flight compression - the data is stored in compressed form on -++the flash media, which makes it possible to put considerably more data to -++the flash as if the data would not be compressed; -++ -++Please, consult the MTD web site for more details (www.linux-mtd.infradead.org). -++ -++The UBI and UBIFS can be compiled as modules or built into the kernel. -++ -++To enable UBI, you need to select following configurations: -++ -++CONFIG_MTD_UBI: Enable UBI -++CONFIG_MTD_UBI_WL_THRESHOLD: UBI wear-leveling threshold -++CONFIG_MTD_UBI_BEB_RESERVE: Percentage of reserved eraseblocks for bad eraseblocks handling -++ -++To enable 'UBI Block Layer', you need to select following configurations: -++ -++CONFIG_MTD_UBI_BLKDEVS: Common interface to block layer for UBI -++CONFIG_MTD_UBI_BLOCK: Emulate block devices -++ -++To enable UBIFS, you need to select following configurations: -++ -++CONFIG_UBIFS_FS: UBIFS file system support -++CONFIG_UBIFS_COMPRESSION_OPTIONS: Advanced compression options for UBIFS -++CONFIG_UBIFS_LZO: UBIFS LZO compression support -++CONFIG_UBIFS_ZLIB: UBIFS ZLIB compression support -++CONFIG_UBIFS_FS_DEBUG: UBIFS debugging -++ -++If you want to compile as modules, take next steps: -++ -++Type 'make modules' to compile the modules. -++ -++Type 'make modules_install INSTALL_MOD_PATH=/nfsroot/root26' to install the -++modules to the target root. -++ -++You also need to compile the MTD and UBIFS utilities and install them to the -++target root. -++ -++ -++Now boot your board and mounted root FS with these modules, and below is a -++simple guide to test and use the UBIFS and 'UBI Block Layer': -++ -++Here we will create UBI volumes on mtd5. -++ -++First, format mtd5: -++ -++# flash_eraseall /dev/mtd5 -++Erasing 256 Kibyte @ 1ffc0000 -- 99 % complete. -++ -++Install UBI module, attached it to mtd5: -++ -++# modprobe ubi mtd=5 -++UBI: empty MTD device detected -++UBI: create volume table (copy #1) -++UBI: create volume table (copy #2) -++UBI: attached mtd5 to ubi0 -++UBI: MTD device name: "NAND VFAT partition" -++UBI: MTD device size: 512 MiB -++UBI: physical eraseblock size: 262144 bytes (256 KiB) -++UBI: logical eraseblock size: 258048 bytes -++UBI: number of good PEBs: 2048 -++UBI: number of bad PEBs: 0 -++UBI: smallest flash I/O unit: 2048 -++UBI: VID header offset: 2048 (aligned 2048) -++UBI: data offset: 4096 -++UBI: max. allowed volumes: 128 -++UBI: wear-leveling threshold: 4096 -++UBI: number of internal volumes: 1 -++UBI: number of user volumes: 0 -++UBI: available PEBs: 2024 -++UBI: total number of reserved PEBs: 24 -++UBI: number of PEBs reserved for bad PEB handling: 20 -++UBI: max/mean erase counter: 0/0 -++UBI: background thread "ubi_bgt0d" started, PID 241 -++ -++Now, create two UBI volumes, one is called ubifs and size is 200MB, the -++other is called vfat and size is 298MB. -++ -++# ubimkvol /dev/ubi0 -s 200MiB -N ubifs -++Volume ID 0, size 813 LEBs (209793024 bytes, 200.1 MiB), LEB size 258048 bytes (252.0 KiB), dynamic, name "ubifs", alignment 1 -++# ubimkvol /dev/ubi0 -s 298MiB -N vfat -++Volume ID 1, size 1211 LEBs (312496128 bytes, 298.0 MiB), LEB size 258048 bytes (252.0 KiB), dynamic, name "vfat", alignment 1 -++ -++Then you can use 'ubinfo' to query the UBI volume info: -++ -++# ubinfo -a -++UBI version: 1 -++Count of UBI devices: 1 -++UBI control device major/minor: 10:63 -++Present UBI devices: ubi0 -++ -++ubi0: -++Volumes count: 2 -++Logical eraseblock size: 258048 -++Total amount of logical eraseblocks: 2048 (528482304 bytes, 504.0 MiB) -++Amount of available logical eraseblocks: 0 (0 bytes) -++Maximum count of volumes 128 -++Count of bad physical eraseblocks: 0 -++Count of reserved physical eraseblocks: 20 -++Current maximum erase counter value: 3 -++Minimum input/output unit size: 2048 bytes -++Character device major/minor: 252:0 -++Present volumes: 0, 1 -++ -++Volume ID: 0 (on ubi0) -++Type: dynamic -++Alignment: 1 -++Size: 813 LEBs (209793024 bytes, 200.1 MiB) -++State: OK -++Name: ubifs -++Character device major/minor: 252:1 -++----------------------------------- -++Volume ID: 1 (on ubi0) -++Type: dynamic -++Alignment: 1 -++Size: 1211 LEBs (312496128 bytes, 298.0 MiB) -++State: OK -++Name: vfat -++Character device major/minor: 252:2 -++ -++ -++It shows that we have successfully created two UBI volumes (Volume ID 0 and 1) -++on ubi0. -++ -++Now you can install the UBIFS and 'UBI Block Layer' modules and create -++UBIFS and FAT on UBI volume 0 and 1 respectively. -++ -++# modprobe ubifs -++# modprobe ubiblk -++ -++# lsmod -++Module Size Used by Not tainted -++ubiblk 7696 0 -++bdev 10016 1 ubiblk -++deflate 4256 1 -++zlib_deflate 22256 1 deflate -++zlib_inflate 16992 1 deflate -++lzo 2400 1 -++lzo_decompress 2816 1 lzo -++lzo_compress 2848 1 lzo -++ubifs 208560 0 -++crc16 2048 1 ubifs -++ubi 103664 4 ubiblk,bdev,ubifs -++ -++Mount UBI volume 0 (the name is "ubifs") on ubi0 with type ubifs: -++ -++# mount -t ubifs ubi0:ubifs /mnt/ubifs/ -++UBIFS: mounted UBI device 0, volume 0 -++UBIFS: minimal I/O unit size: 2048 bytes -++UBIFS: logical eraseblock size: 258048 bytes (252 KiB) -++UBIFS: file system size: 207212544 bytes (202356 KiB, 197 MiB, 803 LEBs) -++UBIFS: journal size: 9420800 bytes (9200 KiB, 8 MiB, 37 LEBs) -++UBIFS: data journal heads: 1 -++UBIFS: default compressor: LZO -++ -++It shows that we have mounted it sucessfully. -++ -++Format /dev/ubiblock1 (the block device for UBI volume 1) and mount it with -++type vfat: -++ -++# mkfs.vfat /dev/ubiblock1 -++# mount -t vfat /dev/ubiblock1 /mnt/ubiblock1 -++ -++Please refer to the linux26_developer_guide.pdf for more details about -++the UBI and UBIFS. -++ -++ -++-------------------------- -++** UBI and UBIFS images ** -++-------------------------- -++ -++Generally, you want to create UBIFS and VFAT images respectively and combine -++these two images into one single image, and then use the nandwrite command -++to write this image to the MTD partition. -++ -++First of all, you need to compile the mkfs.ubifs utility. We use mkfs.ubifs -++to create the UBIFS image, like this: -++ -++Note: download the linux-nand-utils.tar.gz package from www.ingenic.cn and -++follows the guide to compile and run the mkfs.ubifs. -++ -++On the PC host: -++ -++$ mkfs.ubifs -h -++Usage: mkfs.ubifs [OPTIONS] -++Make a UBIFS file system image from an existing directory tree -++ -++Options: -++ -r, -d, --root=DIR Build file system from directory DIR -++ -m, --min-io-size=SIZE Minimum I/O size SIZE -++ -e, --leb-size=SIZE Use logical erase block size SIZE -++ -c, --max-leb-cnt=COUNT Use maximum logical erase block count COUNT -++ -o, --output=FILE Output to FILE -++ -j, --jrn-size=SIZE Use journal size SIZE bytes -++ -x, --compr=TYPE Use compression type TYPE (lzo, zlib or none) (default: lzo) -++ -f, --fanout=NUM Use fanout NUM (default: 8) -++ -k, --keyhash=TYPE Use key hash type TYPE (r5 or test) (default: r5) -++ -l, --log-lebs=COUNT Use COUNT erase blocks for the log -++ -p, --orph-lebs=COUNT Use COUNT erase blocks for orphans (default: 1) -++ -v, --verbose Verbose operation -++ -V, --version Display version information -++ -g, --debug=LEVEL Display debug information -++ -h, --help Display this help text -++ -++$ mkfs.ubifs -r /nfsroot/root26 -m 2048 -e 258048 -c 813 -o ubifs.img -++ -++This will create an UBIFS image called ubifs.img. The argument values -++can be obtained from the 'ubinfo -a' command. -++ -++Follow next steps to create a 30MB FAT32 image called vfat.img: -++ -++# dd if=/dev/zero of=vfat.img bs=1M count=30 -++# losetup /dev/loop0 vfat.img -++# mkfs.vfat /dev/loop0 -++# mount -t vfat /dev/loop0 /mnt/vfat -++# cp * /mnt/vfat -++# umount /mnt/vfat -++# losetup -d /dev/loop0 -++ -++Now the two images ubifs.img and vfat.img are ready, and we want to -++create two UBI volumes and write these two images to the two UBI volumes -++respectively. We can do like this: -++ -++First, use 'ubinize' command to combine ubifs.img and vfat.img into one -++UBI image called ubi.img. -++ -++Second, use 'nandwrite_mlc_ubi' command to write the ubi.img to the -++MTD partition. -++ -++To use 'ubinize' command, you should prepare an INI file for it. The -++content of the INI file are as below: -++ -++# cat ubinize.cfg -++[ubifs] -++mode=ubi -++image=ubifs.img -++vol_id=0 -++vol_size=200MiB -++vol_type=dynamic -++vol_name=ubifs -++vol_alignment=1 -++vol_flag=autoresize -++ -++[vfat] -++mode=ubi -++image=vfat.img -++vol_id=1 -++vol_size=298MiB -++vol_type=dynamic -++vol_name=vfat -++vol_alignment=1 -++vol_flag=autoresize -++ -++ -++Now you can boot your board and follow next guides to create the UBI -++image and burn the UBI image. -++ -++On the target board side: -++ -++# ubinize -o ubi.img ubinize.cfg -p 262144 -m 2048 -++ -++If things go well, you can get the UBI image ubi.img. -++ -++Then use 'nandwrite_ubi' command to write it to the MTD partition. -++ -++# flash_eraseall /dev/mtd5 -++# nandwrite_ubi -a -q -m /dev/mtd5 ubi.img -++ -++Now the UBI image has been written to the NAND mtd5 partition. -++ -++Use next commands to test it. -++ -++# modprobe ubi mtd=5 -++ -++# ubinfo -a -++UBI version: 1 -++Count of UBI devices: 1 -++UBI control device major/minor: 10:63 -++Present UBI devices: ubi0 -++ -++ubi0: -++Volumes count: 2 -++Logical eraseblock size: 258048 -++Total amount of logical eraseblocks: 2048 (528482304 bytes, 504.0 MiB) -++Amount of available logical eraseblocks: 0 (0 bytes) -++Maximum count of volumes 128 -++Count of bad physical eraseblocks: 0 -++Count of reserved physical eraseblocks: 20 -++Current maximum erase counter value: 1 -++Minimum input/output unit size: 2048 bytes -++Character device major/minor: 252:0 -++Present volumes: 0, 1 -++ -++Volume ID: 0 (on ubi0) -++Type: dynamic -++Alignment: 1 -++Size: 813 LEBs (209793024 bytes, 200.1 MiB) -++State: OK -++Name: ubifs -++Character device major/minor: 252:1 -++----------------------------------- -++Volume ID: 1 (on ubi0) -++Type: dynamic -++Alignment: 1 -++Size: 1211 LEBs (312496128 bytes, 298.0 MiB) -++State: OK -++Name: vfat -++Character device major/minor: 252:2 -++ -++ -++This shows that two UBI volumes are present on ubi0. -++ -++# modprobe ubifs -++# mount -t ubifs ubi0:ubifs /mnt/ubifs/ -++UBIFS: mounted UBI device 0, volume 0 -++UBIFS: minimal I/O unit size: 2048 bytes -++UBIFS: logical eraseblock size: 258048 bytes (252 KiB) -++UBIFS: file system size: 207212544 bytes (202356 KiB, 197 MiB, 803 LEBs) -++UBIFS: journal size: 9420800 bytes (9200 KiB, 8 MiB, 37 LEBs) -++UBIFS: data journal heads: 1 -++UBIFS: default compressor: LZO -++ -++# modprobe ubiblk -++# mount -t vfat /dev/ubiblock1 /mnt/ubiblock1 -++ -++# df -++Filesystem 1k-blocks Used Available Use% Mounted on -++tmpfs 30196 56 30140 0% /dev -++ubi0:ubifs 197536 48228 149308 24% /mnt/ubifs -++/dev/ubiblock1 30642 5762 24880 19% /mnt/ubiblock1 -++ -++It shows that the UBIFS and VFAT are all mounted successfully. -++ -++ -++------------ -++** YAFFS2 ** -++------------ -++ -++YAFFS (Yet Another Flash File System) was written to satisfy the -++special needs of NAND flash. The second release of YAFFS especially -++points to supporting newer NAND flash chips with 2k page size and -++up to 128MB capacity. -++ -++YAFFS2 is supported in this kernel. It's built on top of MTD directly. -++Go to fs/yaffs2 for more details. -++ -++To build the utility of YAFFS2, change to directory fs/yaffs2/utils/ -++and type 'make'. -++ -++To create a YAFFS2 image, mkyaffs2image command is used On PC host: -++ -++ usage: mkyaffs2image layout# dir image_file [convert] -++ -++ layout# NAND OOB layout: -++ 0 - nand_oob_raw, no used, -++ 1 - nand_oob_64, for 2KB pagesize, -++ 2 - nand_oob_128, for 2KB pagesize using multiple planes or 4KB pagesize, -++ 3 - nand_oob_256, for 4KB pagesize using multiple planes -++ dir the directory tree to be converted -++ image_file the output file to hold the image -++ -++ e.g., for 2KB page size NAND not using multi-plane: -++ -++ $ mkyaffs2image 1 /nfsroot/root26 root26.yaffs2 -++ -++To burn the yaffs2 image to the NAND, use next command (On target board): -++ -++ # nandwrite -a -o /dev/mtd2 root26.yaffs2 -++ -++To format and mount YAFFS2 (On target board): -++ -++ # flash_eraseall /dev/mtd2 -++ # mount -t yaffs2 /dev/mtdblock2 /mnt/mtdblock2 -++ -++ -++--------------------- -++** MTD Block Layer ** -++--------------------- -++ -++Ingenic implement the 'MTD Block Layer' by ourself. This gives you a choice -++to implement a general filesystem such as FAT and ext2 on NAND flash. -++ -++Which partition used for VFAT should be set in bootargs of u-boot for kernel cmdline, -++so the kernel kowns other partitions aren't base on MTD Block Layer, and their mounting -++speed will be faster. For example, if mtdblock5 is used for VFAT, you can -++ -++set bootargs mem=64M console=ttyS1,57600n8 ip=dhcp root=/dev/mtdblock2 rw mtdblk=5 -++ -++and the mounting speed of mtdblock2 which is not based on MTD Block Layer will be faster. -++ -++ -++Features of the 'MTD Block Layer' include: -++ -++1. Block unit management (address mapping & block cache operations) -++2. Wear-leveling -++3. Bad block management -++4. Write verify enable -++5. mutiple choice of ECC algorithms (hardware Hamming ECC & Reed Solomon ECC, -++software Hamming ECC) -++ -++Kernel configurations related to the 'MTD Block Layer': -++ -++* CONFIG_MTD_OOB_COPIES: defines how many copies of the critical oob data for -++ each block. Since the page data can be corrected by the ECC algorithm but -++ the oob data can't, we want to ensure the correction of the oob data by this -++ way. The mtdblock-jz translation layer driver uses block mode to manipulate -++ the NAND flash. It makes several copies of the oobinfo data for each block, -++ so that it can get a correct copy even there is an error in one of them. -++ -++* CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE: defines this to enable the write -++ verification function, which will read back data to verify during a write -++ operation. -++ -++Take following steps to use the 'MTD Block Layer': -++ -++ # flash_eraseall /dev/mtd3 -++ # mkfs.vfat /dev/mtdblock3 -++ # mount -t vfat /dev/mtdblock3 /mnt/vfat -++ -++ -++NOTICE: -++ -++You can define mutiple VFAT partitions, all the VFAT partitions share -++the same above configurations. -++ -++Each VFAT partition have its own block cache which resides only in RAM. -++Generally, the block cache flush operation is triggered when the access -++address exceeds block boundary. The last block cache usually will be -++flushed to NAND device when the device is closed (eg: umount /mnt/vfat; -++use system call close(fd)). -++ -++Abrupt poweroff without flushing the last block cache will cause the -++VFAT partition to lose the most significant data which records the -++information of the file system management such as FAT table, inodes ... -++ -++To avoid this bad thing, you have to flush block cache as soon as possible. -++Please do remember to flush block cache manually when you finish -++a write operation. -++ -++The MTD block layer driver supplys an ioctl for triggering flush block cache -++operation. The code attached behind is a reference for you to use. -++ -++eg: -++ -++ # cp * /mnt/vfat -++ # sync ; this step is necessary to flush the FS cache -++ # flushcache /dev/mtdblock3 ; this step is necessary to flush the NFTL block cache -++ -++ -++/* flushcache.c */ -++#include -++#include -++#include -++#include -++ -++int main(int argc,char **argv) -++{ -++ int fd; -++ -++ if( argc != 2 ){ -++ printf( "Usage:%s device name(full path)\n", argv[0] ); -++ return -1; -++ } -++ -++ if( (fd = open( argv[1], O_RDONLY ) ) == -1) { -++ printf( "Open %s failed\n", argv[1] ); -++ return -1; -++ } -++ -++ if( ioctl( fd, BLKFLSBUF) == -1) -++ printf("flush catche failed\n"); -++ -++ close(fd); -++ return 0; -++} -++ -++ -++------------------------------ -++** About Bad Blocks of NAND ** -++------------------------------ -++ -++NAND is a special flash type which there are new bad blocks generated during -++the whole period of using it. So the NAND driver should know how to detect -++a bad block and how to mark a new block bad. -++ -++Some types of NAND flash mark the bad block in the spare area of the first -++page but others in the last page. So we define a kernel configuration called -++CONFIG_MTD_BADBLOCK_FLAG_PAGE and use it to decide the bad block. -++ -++CONFIG_MTD_BADBLOCK_FLAG_PAGE: page in a block to store the badblock mark -++ -++Following functions should be cared: -++ -++nand_base.c: -++ -++ - nand_block_bad() -++ - nand_default_block_markbad() -++ -++nand_bbt.c: -++ -++ - create_bbt() -++ -++--------------------------------------- -++** Multiple plane operation for NAND ** -++--------------------------------------- -++ -++NAND multiple plane is a feature enabling support of simultaneous write/erase -++operations for NAND devices with multiplane architecture. This feature -++significantly increases write performance. It could give performance benefits -++if NAND device supports ultiple plane architecture only. If NAND device does -++not support multiple plane and CONFIG_MTD_NAND_MULTI_PLANE was set to yes when -++compiling kernel, code will parse device capabilities and NAND device will work -++in single plane mode. For safe, you'd better set CONFIG_MTD_NAND_MULTI_PLANE to -++no if NAND device does not support multiple plane. -++ -++If the NAND device support multiple plane, you could determine which partitions -++use multiple plane and which use single plane by setting the value of -++partition_info[] in driver/mtd/nand/jz47xx_nand.c, if the value of use_planes -++for a partition is 0, then the partition uses single plane, or else it uses -++multiple plane. e.g. -++ -++static struct mtd_partition partition_info[] = { -++ {name:"NAND BOOT partition", -++ offset:0 * 0x100000, -++ size:4 * 0x100000, -++ use_planes: 0}, -++ {name:"NAND KERNEL partition", -++ offset:4 * 0x100000, -++ size:4 * 0x100000, -++ use_planes: 0}, -++ {name:"NAND ROOTFS partition", -++ offset:8 * 0x100000, -++ size:120 * 0x100000, -++ use_planes: 1}, -++ {name:"NAND DATA1 partition", -++ offset:128 * 0x100000, -++ size:128 * 0x100000, -++ use_planes: 1}, -++ {name:"NAND DATA2 partition", -++ offset:256 * 0x100000, -++ size:256 * 0x100000, -++ use_planes: 1}, -++ {name:"NAND VFAT partition", -++ offset:512 * 0x100000, -++ size:512 * 0x100000, -++ use_planes: 1}, -++}; -++ -++--------------------------------------- -++** Multiple chip selecting for NAND ** -++--------------------------------------- -++ -++CS1_N pin on Jz4740 or Jz4750 will be used for NAND defaultly; besides CS2_N, -++CS3_N, and CS4_N pins could be used for NAND, too. You can configure the kernel -++and select the configuration at: -++ -++ [Memory Technology Devices (MTD)] --> [NAND Device Support] -++ -++ --> [ECC Type] --> [Use NAND on CS2_N of JZSOC] -++ [Use NAND on CS3_N of JZSOC] -++ [Use NAND on CS4_N of JZSOC] -++ -++ -++---------------------------- -++** SLC and MLC NAND Flash ** -++---------------------------- -++ -++Single-Level Cell (SLC) and Multi-Level Cell (MLC) are both NAND-based -++non-volatile memory technologies. MLC NAND Flash allows each memory cell -++to store two bits of information, compared to the one bit-per-cell SLC -++NAND Flash allows. As a result, 90 nanometer (nm) MLC NAND offers a -++larger capacity (typically twice the density of SLC) and at a cost point -++appropriate for consumer products. -++ -++Though SLC NAND offers a lower density, it also provides an enhanced -++level of performance in the form of faster write speeds. Because SLC -++stores only one bit per cell, the likelihood for error is reduced. -++At 90 nanometer process, it is recommended to implement a 1 to 2-bit -++ECC for SLC, whereas 4-bit ECC is recommended on the MLC architecture. -++ -++The linux kernel from ingenic provides MLC NAND support through Hardware -++ECC algorithm. Jz4740 supports Reed-Solomon (RS) ECC algorithm, which can -++detect and correct 4-bit errors per 512 bytes at least. Jz4750 supports -++4-bit and 8-bit BCH ECC algorithm, 4-bit BCH ECC can detect and correct -++4 bits for up to 1010 bytes and 8-bit BCH ECC can detect and correct -++8 bits errors for up to 1016 bytes. -++ -++To include MLC NAND support, you are required to configure the kernel -++and select the configuration CONFIG_MTD_HW_RS_ECC for Jz4740, and -++CONFIG_MTD_HW_BCH_ECC for Jz4750, which can be found at: -++ -++ [Memory Technology Devices (MTD)] --> [NAND Device Support] -++ -++ --> [ECC Type] --> [Select hardware RS ECC] -++ [Select hardware BCH ECC] -++ -++ -++--------------- -++** Initramfs ** -++--------------- -++ -++Please read Documentation/filesystems/ramfs-rootfs-initramfs.txt for -++more information about how to use initramfs. -++ -++Following are some steps to help you to create root fs by using initramfs: -++ -++# cd /rootfs/ -++# find . | cpio -c -o | gzip -9 > ../rootfs.cpio.gz -++ -++Reconfigure the Linux kernel and select next configurations: -++ -++CONFIG_BLK_DEV_INITRD=y -++CONFIG_INITRAMFS_SOURCE="/rootfs.cpio.gz" -++CONFIG_INITRAMFS_ROOT_UID=0 -++CONFIG_INITRAMFS_ROOT_GID=0 -++ -++Rebuild the kernel and boot the kernel with next command lines: -++ -++"root=/dev/ram0 rw rdinit=/sbin/init" -++ -++ -++---------------------------- -++** Audio full duplex mode ** -++---------------------------- -++ -++OSS audio driver supports full duplex mode, that is to say, you can -++record while replaying. -++ -++The user application want to do some jobs to enable the full duplex mode -++of the OSS driver. The following are two examples: -++ -++ -++One is: -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#define AUDIO_FILE "/dev/dsp" -++#define FREQS 48000 -++#define CHANNELS 2 -++#define TEST_TIME 10 -++#define SAMPLES 16 -++#define BUF_SIZE 8192 -++#define MAX_LEN (FREQS * CHANNELS * TEST_TIME * SAMPLES / 8) -++ -++int main(int argc, char *argv[]) -++{ -++ FILE *fp; -++ pid_t pid; -++ int audio_fd, i; -++ char *play_name; -++ char *rec_name; -++ -++ int play_count, play_cnt, played; -++ int rec_count, rec_cnt, recorded; -++ -++ u_char play_arr[MAX_LEN]; -++ u_char rec_arr[MAX_LEN]; -++ int err = 0; -++ -++ play_name = argv[1]; -++ rec_name = argv[2]; -++ -++ if ((audio_fd = open("/dev/dsp", O_RDWR)) < 0) { -++ printf(" Can't open sound device!\n"); -++ exit(-1); -++ } -++ -++ i = BUF_SIZE; -++ ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &i); -++ ioctl(audio_fd, SNDCTL_DSP_SYNC, NULL); -++ -++ i = CHANNELS; -++ ioctl(audio_fd, SNDCTL_DSP_STEREO, (u_char *) &i); -++ -++ i = SAMPLES; -++ ioctl(audio_fd, SNDCTL_DSP_SAMPLESIZE, (u_char *) &i); -++ -++ i = FREQS; -++ ioctl(audio_fd, SNDCTL_DSP_SPEED, (u_char *) &i); -++ -++ fp=fopen(play_name, "r"); -++ fread(play_arr, 1, MAX_LEN, fp); -++ fclose(fp); -++ -++ -++ play_count = MAX_LEN; -++ played = 0; -++ -++ rec_count = MAX_LEN; -++ recorded = 0; -++ -++ switch(pid = fork()) { -++ case -1: -++ printf("error\n"); -++ break; -++ case 0: -++ printf(" playing\n"); -++ while (play_count) { -++ play_cnt = play_count; -++ if (play_cnt > BUF_SIZE) -++ play_cnt = BUF_SIZE; -++ -++ write (audio_fd, (char *)play_arr+played, play_cnt); -++ played += play_cnt; -++ play_count -= play_cnt; -++ }/* while (count) */ -++ exit(0); -++ break; -++ default: -++ printf(" recording\n"); -++ while (rec_count) { -++ rec_cnt = rec_count; -++ if (rec_cnt > BUF_SIZE) -++ rec_cnt = BUF_SIZE; -++ -++ read (audio_fd, (char *)rec_arr+recorded, rec_cnt); -++ recorded += rec_cnt; -++ rec_count -= rec_cnt; -++ }/* while (count) */ -++ break; -++ } -++ close(audio_fd); -++ -++ printf("write data to file, waiting for a while\n"); -++ fp=fopen(rec_name, "w"); -++ fwrite(rec_arr, 1, MAX_LEN, fp); -++ fclose(fp); -++ -++ return err; -++} -++ -++The other is : -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#define AUDIO_FILE "/dev/dsp" -++#define FREQS_PLAY 22050 -++#define FREQS_REC 8000 -++#define FREQS 22050 -++#define CHANNELS 1 -++#define TEST_TIME 10 -++#define SAMPLES 16 -++#define BUF_SIZE 8192 -++#define MAX_LEN (FREQS * CHANNELS * TEST_TIME * SAMPLES / 8) -++ -++int main(int argc, char *argv[]) -++{ -++ FILE *fp; -++ pid_t pid; -++ int audio_fd, i; -++ char *play_name; -++ char *rec_name1, *rec_name2, *rec_name3; -++ int mixerfd, vol, savevol; -++ -++ int count; -++ int play_count, play_cnt, played; -++ int rec_count, rec_cnt, recorded; -++ -++ u_char play_arr[MAX_LEN]; -++ u_char rec_arr[MAX_LEN]; -++ int err = 0; -++ -++ play_name = argv[1]; -++ rec_name1 = argv[2]; -++ rec_name2 = argv[3]; -++ rec_name3 = argv[4]; -++ -++ if ((mixerfd = open("/dev/mixer", O_RDWR)) < 0) { -++ perror("/dev/mixer"); -++ exit(1); -++ } -++ -++ if ((audio_fd = open("/dev/dsp", O_RDWR)) < 0) { -++ printf(" Can't open sound device!\n"); -++ exit(-1); -++ } -++ -++ i = BUF_SIZE; -++ ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &i);// midify buffer lenth -++ ioctl(audio_fd, SNDCTL_DSP_SYNC, NULL); -++ -++ i = CHANNELS; -++ ioctl(audio_fd, SNDCTL_DSP_CHANNELS, (u_char *) &i); -++ -++ i = SAMPLES; -++ ioctl(audio_fd, SNDCTL_DSP_SAMPLESIZE, (u_char *) &i); -++ -++ fp=fopen(play_name, "r"); -++ fread(play_arr, 1, MAX_LEN, fp); -++ fclose(fp); -++ -++ if (ioctl(mixerfd, SOUND_MIXER_READ_MIC, &savevol) == -1) { -++ perror("SOUND_MIXER_READ_DEVMASK mic"); -++ exit(-1); -++ } -++ -++ savevol = savevol & 0xff; -++ -++ for (count = 1; count <= 3; count++) { -++ -++ play_count = MAX_LEN; -++ played = 0; -++ -++ rec_count = MAX_LEN; -++ recorded = 0; -++ -++ -++ i = FREQS_PLAY; -++ ioctl(audio_fd, SNDCTL_DSP_SPEED, (u_char *) &i); -++ -++ printf(" playing %d\n", i); -++ while (play_count) { -++ play_cnt = play_count; -++ if (play_cnt > BUF_SIZE) -++ play_cnt = BUF_SIZE; -++ -++ write (audio_fd, (char *)play_arr+played, play_cnt); -++ played += play_cnt; -++ play_count -= play_cnt; -++ }/* while (count) */ -++ -++ /* wait for sync */ -++ ioctl(audio_fd, SNDCTL_DSP_SYNC, NULL); -++ -++ /* set mic gain 0 */ -++ vol = 0; -++ if (ioctl(mixerfd, SOUND_MIXER_WRITE_MIC, &vol) == -1) { -++ perror("SOUND_MIXER_WRITE_DEVMASK mic"); -++ exit(-1); -++ } -++ i = FREQS_REC; -++ ioctl(audio_fd, SNDCTL_DSP_SPEED, (u_char *) &i); -++ /* set mic gain orgin */ -++ vol = savevol; -++ if (ioctl(mixerfd, SOUND_MIXER_WRITE_MIC, &vol) == -1) { -++ perror("SOUND_MIXER_READ_DEVMASK mic"); -++ exit(-1); -++ } -++ -++ printf(" recording %d\n", i); -++ while (rec_count) { -++ rec_cnt = rec_count; -++ if (rec_cnt > BUF_SIZE) -++ rec_cnt = BUF_SIZE; -++ -++ read (audio_fd, (char *)rec_arr+recorded, rec_cnt); -++ recorded += rec_cnt; -++ rec_count -= rec_cnt; -++ }/* while (count) */ -++ -++ switch (count) { -++ case 1: -++ printf(" write to %s\n",rec_name1); -++ fp=fopen(rec_name1, "w"); -++ fwrite(rec_arr, 1, MAX_LEN, fp); -++ fclose(fp); -++ break; -++ case 2: -++ printf(" write to %s\n",rec_name2); -++ fp=fopen(rec_name2, "w"); -++ fwrite(rec_arr, 1, MAX_LEN, fp); -++ fclose(fp); -++ break; -++ case 3: -++ printf(" write to %s\n",rec_name3); -++ fp=fopen(rec_name3, "w"); -++ fwrite(rec_arr, 1, MAX_LEN, fp); -++ fclose(fp); -++ break; -++ } -++ sleep(1); -++ } -++ -++ close(audio_fd); -++ -++ return err; -++} -++ -++------------- -++** Support ** -++------------- -++ -++Welcome to Ingenic website: -++ -++More details, please refer to linux26_developer_guide.pdf. -+diff -urN linux-2.6.24.7.old/arch/mips/Kconfig linux-2.6.24.7/arch/mips/Kconfig -+--- linux-2.6.24.7.old/arch/mips/Kconfig 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/arch/mips/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -16,6 +16,82 @@ -+ prompt "System type" -+ default SGI_IP22 -+ -++config JZ4730_PMP -++ bool "Ingenic JZ4730 PMP board" -++ select DMA_NONCOHERENT -++ select SYS_HAS_CPU_MIPS32_R1 -++ select SYS_SUPPORTS_32BIT_KERNEL -++ select SYS_SUPPORTS_LITTLE_ENDIAN -++ select SOC_JZ4730 -++ -++config JZ4740_PAVO -++ bool "Ingenic JZ4740 PAVO board" -++ select DMA_NONCOHERENT -++ select SYS_HAS_CPU_MIPS32_R1 -++ select SYS_SUPPORTS_32BIT_KERNEL -++ select SYS_SUPPORTS_LITTLE_ENDIAN -++ select SOC_JZ4740 -++ -++config JZ4740_LEO -++ bool "Ingenic JZ4740 LEO board" -++ select DMA_NONCOHERENT -++ select SYS_HAS_CPU_MIPS32_R1 -++ select SYS_SUPPORTS_32BIT_KERNEL -++ select SYS_SUPPORTS_LITTLE_ENDIAN -++ select SOC_JZ4740 -++ -++config JZ4740_LYRA -++ bool "Ingenic JZ4740 LYRA board" -++ select DMA_NONCOHERENT -++ select SYS_HAS_CPU_MIPS32_R1 -++ select SYS_SUPPORTS_32BIT_KERNEL -++ select SYS_SUPPORTS_LITTLE_ENDIAN -++ select SOC_JZ4740 -++ -++config JZ4725_DIPPER -++ bool "Ingenic JZ4725 DIPPER board" -++ select DMA_NONCOHERENT -++ select SYS_HAS_CPU_MIPS32_R1 -++ select SYS_SUPPORTS_32BIT_KERNEL -++ select SYS_SUPPORTS_LITTLE_ENDIAN -++ select SOC_JZ4740 -++ select SOC_JZ4725 -++ -++config JZ4720_VIRGO -++ bool "Ingenic JZ4720 VIRGO board" -++ select DMA_NONCOHERENT -++ select SYS_HAS_CPU_MIPS32_R1 -++ select SYS_SUPPORTS_32BIT_KERNEL -++ select SYS_SUPPORTS_LITTLE_ENDIAN -++ select SOC_JZ4740 -++ select SOC_JZ4720 -++ -++config JZ4750_FUWA -++ bool "Ingenic JZ4750 FUWA board" -++ select DMA_NONCOHERENT -++ select SYS_HAS_CPU_MIPS32_R1 -++ select SYS_SUPPORTS_32BIT_KERNEL -++ select SYS_SUPPORTS_LITTLE_ENDIAN -++ select SOC_JZ4750 -++ select JZ_FPGA -++ -++config JZ4750D_FUWA1 -++ bool "Ingenic JZ4750d FUWA1 board" -++ select DMA_NONCOHERENT -++ select SYS_HAS_CPU_MIPS32_R1 -++ select SYS_SUPPORTS_32BIT_KERNEL -++ select SYS_SUPPORTS_LITTLE_ENDIAN -++ select SOC_JZ4750D -++ select JZ_FPGA -++ -++config JZ4750_APUS -++ bool "Ingenic JZ4750 APUS board" -++ select DMA_NONCOHERENT -++ select SYS_HAS_CPU_MIPS32_R1 -++ select SYS_SUPPORTS_32BIT_KERNEL -++ select SYS_SUPPORTS_LITTLE_ENDIAN -++ select SOC_JZ4750 -++ -+ config MACH_ALCHEMY -+ bool "Alchemy processor based machines" -+ -+@@ -701,6 +777,48 @@ -+ -+ endmenu -+ -++##################################################### -++# Ingenic SOC series -++##################################################### -++ -++config SOC_JZ4730 -++ bool -++ select JZSOC -++ -++config SOC_JZ4740 -++ bool -++ select JZSOC -++ -++config SOC_JZ4725 -++ bool -++ select JZSOC -++ -++config SOC_JZ4720 -++ bool -++ select JZSOC -++ -++config SOC_JZ4750 -++ bool -++ select JZSOC -++ -++config SOC_JZ4750D -++ bool -++ select JZSOC -++ -++config JZ_FPGA -++ bool -++ -++config JZSOC -++ bool -++ select JZRISC -++ select SYS_HAS_CPU_MIPS32_R1 -++ select SYS_SUPPORTS_32BIT_KERNEL -++ -++config JZRISC -++ bool -++ -++#################################################### -++ -+ config RWSEM_GENERIC_SPINLOCK -+ bool -+ default y -+@@ -1770,6 +1888,14 @@ -+ -+ source "kernel/time/Kconfig" -+ -++# the value of (max order + 1) -++config FORCE_MAX_ZONEORDER -++ prompt "MAX_ZONEORDER" -++ int -++ default "12" -++ help -++ The max memory that can be allocated = 4KB * 2^(CONFIG_FORCE_MAX_ZONEORDER - 1) -++ -+ # -+ # Timer Interrupt Frequency Configuration -+ # -+@@ -2046,6 +2172,23 @@ -+ -+ endmenu -+ -++menu "CPU Frequency scaling" -++ -++config CPU_FREQ_JZ -++ tristate "CPUfreq driver for JZ CPUs" -++ depends on JZSOC -++ default n -++ help -++ This enables the CPUfreq driver for JZ CPUs. -++ -++ If in doubt, say N. -++ -++if (CPU_FREQ_JZ) -++source "drivers/cpufreq/Kconfig" -++endif -++ -++endmenu -++ -+ menu "Power management options" -+ -+ source "kernel/power/Kconfig" -+diff -urN linux-2.6.24.7.old/arch/mips/Makefile linux-2.6.24.7/arch/mips/Makefile -+--- linux-2.6.24.7.old/arch/mips/Makefile 2009-04-12 18:05:07.000000000 +0200 -++++ linux-2.6.24.7/arch/mips/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -159,6 +159,37 @@ -+ # -+ -+ # -++# Commond Ingenic JZ4730 series -++# -++core-$(CONFIG_SOC_JZ4730) += arch/mips/jz4730/ -++cflags-$(CONFIG_SOC_JZ4730) += -Iinclude/asm-mips/mach-jz4730 -++load-$(CONFIG_SOC_JZ4730) += 0xffffffff80010000 -++ -++# -++# Commond Ingenic JZ4740 series -++# -++ -++core-$(CONFIG_SOC_JZ4740) += arch/mips/jz4740/ -++cflags-$(CONFIG_SOC_JZ4740) += -Iinclude/asm-mips/mach-jz4740 -++load-$(CONFIG_SOC_JZ4740) += 0xffffffff80010000 -++ -++# -++# Commond Ingenic JZ4750 series -++# -++ -++core-$(CONFIG_SOC_JZ4750) += arch/mips/jz4750/ -++cflags-$(CONFIG_SOC_JZ4750) += -Iinclude/asm-mips/mach-jz4750 -++load-$(CONFIG_SOC_JZ4750) += 0xffffffff80010000 -++ -++# -++# Commond Ingenic JZ4750d series -++# -++ -++core-$(CONFIG_SOC_JZ4750D) += arch/mips/jz4750d/ -++cflags-$(CONFIG_SOC_JZ4750D) += -Iinclude/asm-mips/mach-jz4750d -++load-$(CONFIG_SOC_JZ4750D) += 0xffffffff80010000 -++ -++# -+ # Acer PICA 61, Mips Magnum 4000 and Olivetti M700. -+ # -+ core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/ -+@@ -673,6 +704,12 @@ -+ -+ all: $(all-y) -+ -++uImage: $(vmlinux-32) -++ +@$(call makeboot,$@) -++ -++zImage: $(vmlinux-32) -++ +@$(call makeboot,$@) -++ -+ vmlinux.bin: $(vmlinux-32) -+ +@$(call makeboot,$@) -+ -+@@ -697,12 +734,13 @@ -+ -+ archclean: -+ @$(MAKE) $(clean)=arch/mips/boot -++ @$(MAKE) $(clean)=arch/mips/boot/compressed -+ @$(MAKE) $(clean)=arch/mips/lasat -+ -+ define archhelp -+- echo ' vmlinux.ecoff - ECOFF boot image' -+- echo ' vmlinux.bin - Raw binary boot image' -+- echo ' vmlinux.srec - SREC boot image' -++ echo ' uImage - u-boot format image (arch/$(ARCH)/boot/uImage)' -++ echo ' zImage - Compressed binary image (arch/$(ARCH)/boot/compressed/zImage)' -++ echo ' vmlinux.bin - Uncompressed binary image (arch/$(ARCH)/boot/vmlinux.bin)' -+ echo -+ echo ' These will be default as apropriate for a configured platform.' -+ endef -+diff -urN linux-2.6.24.7.old/arch/mips/Makefile.orig linux-2.6.24.7/arch/mips/Makefile.orig -+--- linux-2.6.24.7.old/arch/mips/Makefile.orig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/Makefile.orig 2009-04-12 18:01:55.000000000 +0200 -+@@ -0,0 +1,712 @@ -++# -++# This file is subject to the terms and conditions of the GNU General Public -++# License. See the file "COPYING" in the main directory of this archive -++# for more details. -++# -++# Copyright (C) 1994, 95, 96, 2003 by Ralf Baechle -++# DECStation modifications by Paul M. Antoine, 1996 -++# Copyright (C) 2002, 2003, 2004 Maciej W. Rozycki -++# -++# This file is included by the global makefile so that you can add your own -++# architecture-specific flags and dependencies. Remember to do have actions -++# for "archclean" cleaning up for this architecture. -++# -++ -++cflags-y := -++ -++# -++# Select the object file format to substitute into the linker script. -++# -++ifdef CONFIG_CPU_LITTLE_ENDIAN -++32bit-tool-archpref = mipsel -++64bit-tool-archpref = mips64el -++32bit-bfd = elf32-tradlittlemips -++64bit-bfd = elf64-tradlittlemips -++32bit-emul = elf32ltsmip -++64bit-emul = elf64ltsmip -++else -++32bit-tool-archpref = mips -++64bit-tool-archpref = mips64 -++32bit-bfd = elf32-tradbigmips -++64bit-bfd = elf64-tradbigmips -++32bit-emul = elf32btsmip -++64bit-emul = elf64btsmip -++endif -++ -++ifdef CONFIG_32BIT -++tool-archpref = $(32bit-tool-archpref) -++UTS_MACHINE := mips -++endif -++ifdef CONFIG_64BIT -++tool-archpref = $(64bit-tool-archpref) -++UTS_MACHINE := mips64 -++endif -++ -++ifneq ($(SUBARCH),$(ARCH)) -++ ifeq ($(CROSS_COMPILE),) -++ CROSS_COMPILE := $(call cc-cross-prefix, $(tool-archpref)-linux- $(tool-archpref)-linux-gnu- $(tool-archpref)-unknown-linux-gnu-) -++ endif -++endif -++ -++ifdef CONFIG_32BIT -++ld-emul = $(32bit-emul) -++vmlinux-32 = vmlinux -++vmlinux-64 = vmlinux.64 -++ -++cflags-y += -mabi=32 -++endif -++ -++ifdef CONFIG_64BIT -++ld-emul = $(64bit-emul) -++vmlinux-32 = vmlinux.32 -++vmlinux-64 = vmlinux -++ -++cflags-y += -mabi=64 -++endif -++ -++all-$(CONFIG_BOOT_ELF32) := $(vmlinux-32) -++all-$(CONFIG_BOOT_ELF64) := $(vmlinux-64) -++ -++# -++# GCC uses -G 0 -mabicalls -fpic as default. We don't want PIC in the kernel -++# code since it only slows down the whole thing. At some point we might make -++# use of global pointer optimizations but their use of $28 conflicts with -++# the current pointer optimization. -++# -++# The DECStation requires an ECOFF kernel for remote booting, other MIPS -++# machines may also. Since BFD is incredibly buggy with respect to -++# crossformat linking we rely on the elf2ecoff tool for format conversion. -++# -++cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -++cflags-y += -msoft-float -++LDFLAGS_vmlinux += -G 0 -static -n -nostdlib -++MODFLAGS += -mlong-calls -++ -++cflags-y += -ffreestanding -++ -++# -++# We explicitly add the endianness specifier if needed, this allows -++# to compile kernels with a toolchain for the other endianness. We -++# carefully avoid to add it redundantly because gcc 3.3/3.4 complains -++# when fed the toolchain default! -++# -++# Certain gcc versions upto gcc 4.1.1 (probably 4.2-subversion as of -++# 2006-10-10 don't properly change the predefined symbols if -EB / -EL -++# are used, so we kludge that here. A bug has been filed at -++# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29413. -++# -++undef-all += -UMIPSEB -U_MIPSEB -U__MIPSEB -U__MIPSEB__ -++undef-all += -UMIPSEL -U_MIPSEL -U__MIPSEL -U__MIPSEL__ -++predef-be += -DMIPSEB -D_MIPSEB -D__MIPSEB -D__MIPSEB__ -++predef-le += -DMIPSEL -D_MIPSEL -D__MIPSEL -D__MIPSEL__ -++cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB $(undef-all) $(predef-be)) -++cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL $(undef-all) $(predef-le)) -++ -++cflags-$(CONFIG_CPU_HAS_SMARTMIPS) += $(call cc-option,-msmartmips) -++ -++cflags-$(CONFIG_SB1XXX_CORELIS) += $(call cc-option,-mno-sched-prolog) \ -++ -fno-omit-frame-pointer -++ -++# -++# CPU-dependent compiler/assembler options for optimization. -++# -++cflags-$(CONFIG_CPU_R3000) += -march=r3000 -++cflags-$(CONFIG_CPU_TX39XX) += -march=r3900 -++cflags-$(CONFIG_CPU_R6000) += -march=r6000 -Wa,--trap -++cflags-$(CONFIG_CPU_R4300) += -march=r4300 -Wa,--trap -++cflags-$(CONFIG_CPU_VR41XX) += -march=r4100 -Wa,--trap -++cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap -++cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap -++cflags-$(CONFIG_CPU_LOONGSON2) += -march=r4600 -Wa,--trap -++cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ -++ -Wa,-mips32 -Wa,--trap -++cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ -++ -Wa,-mips32r2 -Wa,--trap -++cflags-$(CONFIG_CPU_MIPS64_R1) += $(call cc-option,-march=mips64,-mips64 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \ -++ -Wa,-mips64 -Wa,--trap -++cflags-$(CONFIG_CPU_MIPS64_R2) += $(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \ -++ -Wa,-mips64r2 -Wa,--trap -++cflags-$(CONFIG_CPU_R5000) += -march=r5000 -Wa,--trap -++cflags-$(CONFIG_CPU_R5432) += $(call cc-option,-march=r5400,-march=r5000) \ -++ -Wa,--trap -++cflags-$(CONFIG_CPU_NEVADA) += $(call cc-option,-march=rm5200,-march=r5000) \ -++ -Wa,--trap -++cflags-$(CONFIG_CPU_RM7000) += $(call cc-option,-march=rm7000,-march=r5000) \ -++ -Wa,--trap -++cflags-$(CONFIG_CPU_RM9000) += $(call cc-option,-march=rm9000,-march=r5000) \ -++ -Wa,--trap -++cflags-$(CONFIG_CPU_SB1) += $(call cc-option,-march=sb1,-march=r5000) \ -++ -Wa,--trap -++cflags-$(CONFIG_CPU_R8000) += -march=r8000 -Wa,--trap -++cflags-$(CONFIG_CPU_R10000) += $(call cc-option,-march=r10000,-march=r8000) \ -++ -Wa,--trap -++ -++ifdef CONFIG_CPU_SB1 -++ifdef CONFIG_SB1_PASS_1_WORKAROUNDS -++MODFLAGS += -msb1-pass1-workarounds -++endif -++endif -++ -++# -++# Firmware support -++# -++libs-$(CONFIG_ARC) += arch/mips/fw/arc/ -++libs-$(CONFIG_CFE) += arch/mips/fw/cfe/ -++libs-$(CONFIG_SIBYTE_CFE) += arch/mips/sibyte/cfe/ -++ -++# -++# Board-dependent options and extra files -++# -++ -++# -++# Acer PICA 61, Mips Magnum 4000 and Olivetti M700. -++# -++core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/ -++cflags-$(CONFIG_MACH_JAZZ) += -Iinclude/asm-mips/mach-jazz -++load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000 -++ -++# -++# Common Alchemy Au1x00 stuff -++# -++core-$(CONFIG_SOC_AU1X00) += arch/mips/au1000/common/ -++cflags-$(CONFIG_SOC_AU1X00) += -Iinclude/asm-mips/mach-au1x00 -++ -++# -++# AMD Alchemy Pb1000 eval board -++# -++libs-$(CONFIG_MIPS_PB1000) += arch/mips/au1000/pb1000/ -++cflags-$(CONFIG_MIPS_PB1000) += -Iinclude/asm-mips/mach-pb1x00 -++load-$(CONFIG_MIPS_PB1000) += 0xffffffff80100000 -++ -++# -++# AMD Alchemy Pb1100 eval board -++# -++libs-$(CONFIG_MIPS_PB1100) += arch/mips/au1000/pb1100/ -++cflags-$(CONFIG_MIPS_PB1100) += -Iinclude/asm-mips/mach-pb1x00 -++load-$(CONFIG_MIPS_PB1100) += 0xffffffff80100000 -++ -++# -++# AMD Alchemy Pb1500 eval board -++# -++libs-$(CONFIG_MIPS_PB1500) += arch/mips/au1000/pb1500/ -++cflags-$(CONFIG_MIPS_PB1500) += -Iinclude/asm-mips/mach-pb1x00 -++load-$(CONFIG_MIPS_PB1500) += 0xffffffff80100000 -++ -++# -++# AMD Alchemy Pb1550 eval board -++# -++libs-$(CONFIG_MIPS_PB1550) += arch/mips/au1000/pb1550/ -++cflags-$(CONFIG_MIPS_PB1550) += -Iinclude/asm-mips/mach-pb1x00 -++load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000 -++ -++# -++# AMD Alchemy Pb1200 eval board -++# -++libs-$(CONFIG_MIPS_PB1200) += arch/mips/au1000/pb1200/ -++cflags-$(CONFIG_MIPS_PB1200) += -Iinclude/asm-mips/mach-pb1x00 -++load-$(CONFIG_MIPS_PB1200) += 0xffffffff80100000 -++ -++# -++# AMD Alchemy Db1000 eval board -++# -++libs-$(CONFIG_MIPS_DB1000) += arch/mips/au1000/db1x00/ -++cflags-$(CONFIG_MIPS_DB1000) += -Iinclude/asm-mips/mach-db1x00 -++load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000 -++ -++# -++# AMD Alchemy Db1100 eval board -++# -++libs-$(CONFIG_MIPS_DB1100) += arch/mips/au1000/db1x00/ -++cflags-$(CONFIG_MIPS_DB1100) += -Iinclude/asm-mips/mach-db1x00 -++load-$(CONFIG_MIPS_DB1100) += 0xffffffff80100000 -++ -++# -++# AMD Alchemy Db1500 eval board -++# -++libs-$(CONFIG_MIPS_DB1500) += arch/mips/au1000/db1x00/ -++cflags-$(CONFIG_MIPS_DB1500) += -Iinclude/asm-mips/mach-db1x00 -++load-$(CONFIG_MIPS_DB1500) += 0xffffffff80100000 -++ -++# -++# AMD Alchemy Db1550 eval board -++# -++libs-$(CONFIG_MIPS_DB1550) += arch/mips/au1000/db1x00/ -++cflags-$(CONFIG_MIPS_DB1550) += -Iinclude/asm-mips/mach-db1x00 -++load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000 -++ -++# -++# AMD Alchemy Db1200 eval board -++# -++libs-$(CONFIG_MIPS_DB1200) += arch/mips/au1000/pb1200/ -++cflags-$(CONFIG_MIPS_DB1200) += -Iinclude/asm-mips/mach-db1x00 -++load-$(CONFIG_MIPS_DB1200) += 0xffffffff80100000 -++ -++# -++# AMD Alchemy Bosporus eval board -++# -++libs-$(CONFIG_MIPS_BOSPORUS) += arch/mips/au1000/db1x00/ -++cflags-$(CONFIG_MIPS_BOSPORUS) += -Iinclude/asm-mips/mach-db1x00 -++load-$(CONFIG_MIPS_BOSPORUS) += 0xffffffff80100000 -++ -++# -++# AMD Alchemy Mirage eval board -++# -++libs-$(CONFIG_MIPS_MIRAGE) += arch/mips/au1000/db1x00/ -++cflags-$(CONFIG_MIPS_MIRAGE) += -Iinclude/asm-mips/mach-db1x00 -++load-$(CONFIG_MIPS_MIRAGE) += 0xffffffff80100000 -++ -++# -++# 4G-Systems eval board -++# -++libs-$(CONFIG_MIPS_MTX1) += arch/mips/au1000/mtx-1/ -++load-$(CONFIG_MIPS_MTX1) += 0xffffffff80100000 -++ -++# -++# MyCable eval board -++# -++libs-$(CONFIG_MIPS_XXS1500) += arch/mips/au1000/xxs1500/ -++load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000 -++ -++# -++# Cobalt Server -++# -++core-$(CONFIG_MIPS_COBALT) += arch/mips/cobalt/ -++cflags-$(CONFIG_MIPS_COBALT) += -Iinclude/asm-mips/mach-cobalt -++load-$(CONFIG_MIPS_COBALT) += 0xffffffff80080000 -++ -++# -++# DECstation family -++# -++core-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/ -++cflags-$(CONFIG_MACH_DECSTATION)+= -Iinclude/asm-mips/mach-dec -++libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/ -++load-$(CONFIG_MACH_DECSTATION) += 0xffffffff80040000 -++ -++# -++# Wind River PPMC Board (4KC + GT64120) -++# -++core-$(CONFIG_WR_PPMC) += arch/mips/gt64120/wrppmc/ -++cflags-$(CONFIG_WR_PPMC) += -Iinclude/asm-mips/mach-wrppmc -++load-$(CONFIG_WR_PPMC) += 0xffffffff80100000 -++ -++# -++# lemote fulong mini-PC board -++# -++core-$(CONFIG_LEMOTE_FULONG) +=arch/mips/lemote/lm2e/ -++load-$(CONFIG_LEMOTE_FULONG) +=0xffffffff80100000 -++cflags-$(CONFIG_LEMOTE_FULONG) += -Iinclude/asm-mips/mach-lemote -++ -++# -++# For all MIPS, Inc. eval boards -++# -++core-$(CONFIG_MIPS_BOARDS_GEN) += arch/mips/mips-boards/generic/ -++ -++# -++# MIPS Atlas board -++# -++core-$(CONFIG_MIPS_ATLAS) += arch/mips/mips-boards/atlas/ -++cflags-$(CONFIG_MIPS_ATLAS) += -Iinclude/asm-mips/mach-atlas -++cflags-$(CONFIG_MIPS_ATLAS) += -Iinclude/asm-mips/mach-mips -++load-$(CONFIG_MIPS_ATLAS) += 0xffffffff80100000 -++all-$(CONFIG_MIPS_ATLAS) := vmlinux.srec -++ -++# -++# MIPS Malta board -++# -++core-$(CONFIG_MIPS_MALTA) += arch/mips/mips-boards/malta/ -++cflags-$(CONFIG_MIPS_MALTA) += -Iinclude/asm-mips/mach-mips -++load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000 -++all-$(CONFIG_MIPS_MALTA) := vmlinux.srec -++ -++# -++# MIPS SEAD board -++# -++core-$(CONFIG_MIPS_SEAD) += arch/mips/mips-boards/sead/ -++cflags-$(CONFIG_MIPS_SEAD) += -Iinclude/asm-mips/mach-mips -++load-$(CONFIG_MIPS_SEAD) += 0xffffffff80100000 -++all-$(CONFIG_MIPS_SEAD) := vmlinux.srec -++ -++# -++# MIPS SIM -++# -++core-$(CONFIG_MIPS_SIM) += arch/mips/mipssim/ -++cflags-$(CONFIG_MIPS_SIM) += -Iinclude/asm-mips/mach-mipssim -++load-$(CONFIG_MIPS_SIM) += 0x80100000 -++ -++# -++# PMC-Sierra MSP SOCs -++# -++core-$(CONFIG_PMC_MSP) += arch/mips/pmc-sierra/msp71xx/ -++cflags-$(CONFIG_PMC_MSP) += -Iinclude/asm-mips/pmc-sierra/msp71xx \ -++ -mno-branch-likely -++load-$(CONFIG_PMC_MSP) += 0xffffffff80100000 -++ -++# -++# PMC-Sierra Yosemite -++# -++core-$(CONFIG_PMC_YOSEMITE) += arch/mips/pmc-sierra/yosemite/ -++cflags-$(CONFIG_PMC_YOSEMITE) += -Iinclude/asm-mips/mach-yosemite -++load-$(CONFIG_PMC_YOSEMITE) += 0xffffffff80100000 -++ -++# -++# Qemu simulating MIPS32 4Kc -++# -++core-$(CONFIG_QEMU) += arch/mips/qemu/ -++cflags-$(CONFIG_QEMU) += -Iinclude/asm-mips/mach-qemu -++load-$(CONFIG_QEMU) += 0xffffffff80010000 -++all-$(CONFIG_QEMU) := vmlinux.bin -++ -++# -++# Basler eXcite -++# -++core-$(CONFIG_BASLER_EXCITE) += arch/mips/basler/excite/ -++cflags-$(CONFIG_BASLER_EXCITE) += -Iinclude/asm-mips/mach-excite -++load-$(CONFIG_BASLER_EXCITE) += 0x80100000 -++ -++# -++# LASAT platforms -++# -++core-$(CONFIG_LASAT) += arch/mips/lasat/ -++cflags-$(CONFIG_LASAT) += -Iinclude/asm-mips/mach-lasat -++load-$(CONFIG_LASAT) += 0xffffffff80000000 -++ -++# -++# Common VR41xx -++# -++core-$(CONFIG_MACH_VR41XX) += arch/mips/vr41xx/common/ -++cflags-$(CONFIG_MACH_VR41XX) += -Iinclude/asm-mips/mach-vr41xx -++ -++# -++# NEC VR4133 -++# -++core-$(CONFIG_NEC_CMBVR4133) += arch/mips/vr41xx/nec-cmbvr4133/ -++load-$(CONFIG_NEC_CMBVR4133) += 0xffffffff80100000 -++ -++# -++# ZAO Networks Capcella (VR4131) -++# -++load-$(CONFIG_ZAO_CAPCELLA) += 0xffffffff80000000 -++ -++# -++# Victor MP-C303/304 (VR4122) -++# -++load-$(CONFIG_VICTOR_MPC30X) += 0xffffffff80001000 -++ -++# -++# IBM WorkPad z50 (VR4121) -++# -++core-$(CONFIG_IBM_WORKPAD) += arch/mips/vr41xx/ibm-workpad/ -++load-$(CONFIG_IBM_WORKPAD) += 0xffffffff80004000 -++ -++# -++# CASIO CASSIPEIA E-55/65 (VR4111) -++# -++core-$(CONFIG_CASIO_E55) += arch/mips/vr41xx/casio-e55/ -++load-$(CONFIG_CASIO_E55) += 0xffffffff80004000 -++ -++# -++# TANBAC VR4131 multichip module(TB0225) and TANBAC VR4131DIMM(TB0229) (VR4131) -++# -++load-$(CONFIG_TANBAC_TB022X) += 0xffffffff80000000 -++ -++# -++# Common Philips PNX8550 -++# -++core-$(CONFIG_SOC_PNX8550) += arch/mips/philips/pnx8550/common/ -++cflags-$(CONFIG_SOC_PNX8550) += -Iinclude/asm-mips/mach-pnx8550 -++ -++# -++# Philips PNX8550 JBS board -++# -++libs-$(CONFIG_PNX8550_JBS) += arch/mips/philips/pnx8550/jbs/ -++#cflags-$(CONFIG_PNX8550_JBS) += -Iinclude/asm-mips/mach-pnx8550 -++load-$(CONFIG_PNX8550_JBS) += 0xffffffff80060000 -++ -++# Philips PNX8550 STB810 board -++# -++libs-$(CONFIG_PNX8550_STB810) += arch/mips/philips/pnx8550/stb810/ -++load-$(CONFIG_PNX8550_STB810) += 0xffffffff80060000 -++ -++# NEC EMMA2RH boards -++# -++core-$(CONFIG_EMMA2RH) += arch/mips/emma2rh/common/ -++cflags-$(CONFIG_EMMA2RH) += -Iinclude/asm-mips/mach-emma2rh -++ -++# NEC EMMA2RH Mark-eins -++core-$(CONFIG_MARKEINS) += arch/mips/emma2rh/markeins/ -++load-$(CONFIG_MARKEINS) += 0xffffffff88100000 -++ -++# -++# SGI IP22 (Indy/Indigo2) -++# -++# Set the load address to >= 0xffffffff88069000 if you want to leave space for -++# symmon, 0xffffffff80002000 for production kernels. Note that the value must -++# be aligned to a multiple of the kernel stack size or the handling of the -++# current variable will break so for 64-bit kernels we have to raise the start -++# address by 8kb. -++# -++core-$(CONFIG_SGI_IP22) += arch/mips/sgi-ip22/ -++cflags-$(CONFIG_SGI_IP22) += -Iinclude/asm-mips/mach-ip22 -++ifdef CONFIG_32BIT -++load-$(CONFIG_SGI_IP22) += 0xffffffff88002000 -++endif -++ifdef CONFIG_64BIT -++load-$(CONFIG_SGI_IP22) += 0xffffffff88004000 -++endif -++ -++# -++# SGI-IP27 (Origin200/2000) -++# -++# Set the load address to >= 0xc000000000300000 if you want to leave space for -++# symmon, 0xc00000000001c000 for production kernels. Note that the value must -++# be 16kb aligned or the handling of the current variable will break. -++# -++ifdef CONFIG_SGI_IP27 -++core-$(CONFIG_SGI_IP27) += arch/mips/sgi-ip27/ -++cflags-$(CONFIG_SGI_IP27) += -Iinclude/asm-mips/mach-ip27 -++ifdef CONFIG_MAPPED_KERNEL -++load-$(CONFIG_SGI_IP27) += 0xc00000004001c000 -++OBJCOPYFLAGS := --change-addresses=0x3fffffff80000000 -++dataoffset-$(CONFIG_SGI_IP27) += 0x01000000 -++else -++load-$(CONFIG_SGI_IP27) += 0xa80000000001c000 -++OBJCOPYFLAGS := --change-addresses=0x57ffffff80000000 -++endif -++endif -++ -++# -++# SGI-IP32 (O2) -++# -++# Set the load address to >= 80069000 if you want to leave space for symmon, -++# 0xffffffff80004000 for production kernels. Note that the value must be aligned to -++# a multiple of the kernel stack size or the handling of the current variable -++# will break. -++# -++core-$(CONFIG_SGI_IP32) += arch/mips/sgi-ip32/ -++cflags-$(CONFIG_SGI_IP32) += -Iinclude/asm-mips/mach-ip32 -++load-$(CONFIG_SGI_IP32) += 0xffffffff80004000 -++ -++# -++# Sibyte SB1250/BCM1480 SOC -++# -++# This is a LIB so that it links at the end, and initcalls are later -++# the sequence; but it is built as an object so that modules don't get -++# removed (as happens, even if they have __initcall/module_init) -++# -++core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/sb1250/ -++core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/common/ -++cflags-$(CONFIG_SIBYTE_BCM112X) += -Iinclude/asm-mips/mach-sibyte \ -++ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL -++ -++core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/sb1250/ -++core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/common/ -++cflags-$(CONFIG_SIBYTE_SB1250) += -Iinclude/asm-mips/mach-sibyte \ -++ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL -++ -++core-$(CONFIG_SIBYTE_BCM1x55) += arch/mips/sibyte/bcm1480/ -++core-$(CONFIG_SIBYTE_BCM1x55) += arch/mips/sibyte/common/ -++cflags-$(CONFIG_SIBYTE_BCM1x55) += -Iinclude/asm-mips/mach-sibyte \ -++ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL -++ -++core-$(CONFIG_SIBYTE_BCM1x80) += arch/mips/sibyte/bcm1480/ -++core-$(CONFIG_SIBYTE_BCM1x80) += arch/mips/sibyte/common/ -++cflags-$(CONFIG_SIBYTE_BCM1x80) += -Iinclude/asm-mips/mach-sibyte \ -++ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL -++ -++# -++# Sibyte BCM91120x (Carmel) board -++# Sibyte BCM91120C (CRhine) board -++# Sibyte BCM91125C (CRhone) board -++# Sibyte BCM91125E (Rhone) board -++# Sibyte SWARM board -++# Sibyte BCM91x80 (BigSur) board -++# -++libs-$(CONFIG_SIBYTE_CARMEL) += arch/mips/sibyte/swarm/ -++load-$(CONFIG_SIBYTE_CARMEL) := 0xffffffff80100000 -++libs-$(CONFIG_SIBYTE_CRHINE) += arch/mips/sibyte/swarm/ -++load-$(CONFIG_SIBYTE_CRHINE) := 0xffffffff80100000 -++libs-$(CONFIG_SIBYTE_CRHONE) += arch/mips/sibyte/swarm/ -++load-$(CONFIG_SIBYTE_CRHONE) := 0xffffffff80100000 -++libs-$(CONFIG_SIBYTE_RHONE) += arch/mips/sibyte/swarm/ -++load-$(CONFIG_SIBYTE_RHONE) := 0xffffffff80100000 -++libs-$(CONFIG_SIBYTE_SENTOSA) += arch/mips/sibyte/swarm/ -++load-$(CONFIG_SIBYTE_SENTOSA) := 0xffffffff80100000 -++libs-$(CONFIG_SIBYTE_SWARM) += arch/mips/sibyte/swarm/ -++load-$(CONFIG_SIBYTE_SWARM) := 0xffffffff80100000 -++libs-$(CONFIG_SIBYTE_BIGSUR) += arch/mips/sibyte/swarm/ -++load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000 -++ -++# -++# Broadcom BCM47XX boards -++# -++core-$(CONFIG_BCM47XX) += arch/mips/bcm47xx/ -++cflags-$(CONFIG_BCM47XX) += -Iinclude/asm-mips/mach-bcm47xx -++load-$(CONFIG_BCM47XX) := 0xffffffff80001000 -++ -++# -++# SNI RM -++# -++core-$(CONFIG_SNI_RM) += arch/mips/sni/ -++cflags-$(CONFIG_SNI_RM) += -Iinclude/asm-mips/mach-rm -++load-$(CONFIG_SNI_RM) += 0xffffffff80600000 -++all-$(CONFIG_SNI_RM) := vmlinux.ecoff -++ -++# -++# Toshiba JMR-TX3927 board -++# -++core-$(CONFIG_TOSHIBA_JMR3927) += arch/mips/jmr3927/rbhma3100/ \ -++ arch/mips/jmr3927/common/ -++cflags-$(CONFIG_TOSHIBA_JMR3927) += -Iinclude/asm-mips/mach-jmr3927 -++load-$(CONFIG_TOSHIBA_JMR3927) += 0xffffffff80050000 -++ -++# -++# Toshiba RBTX4927 board or -++# Toshiba RBTX4937 board -++# -++core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/tx4927/toshiba_rbtx4927/ -++core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/tx4927/common/ -++cflags-$(CONFIG_TOSHIBA_RBTX4927) += -Iinclude/asm-mips/mach-tx49xx -++load-$(CONFIG_TOSHIBA_RBTX4927) += 0xffffffff80020000 -++ -++# -++# Toshiba RBTX4938 board -++# -++core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/tx4938/toshiba_rbtx4938/ -++core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/tx4938/common/ -++cflags-$(CONFIG_TOSHIBA_RBTX4938) += -Iinclude/asm-mips/mach-tx49xx -++load-$(CONFIG_TOSHIBA_RBTX4938) += 0xffffffff80100000 -++ -++# temporary until string.h is fixed -++cflags-y += -ffreestanding -++ -++cflags-y += -Iinclude/asm-mips/mach-generic -++drivers-$(CONFIG_PCI) += arch/mips/pci/ -++ -++ifdef CONFIG_32BIT -++ifdef CONFIG_CPU_LITTLE_ENDIAN -++JIFFIES = jiffies_64 -++else -++JIFFIES = jiffies_64 + 4 -++endif -++else -++JIFFIES = jiffies_64 -++endif -++ -++# -++# Automatically detect the build format. By default we choose -++# the elf format according to the load address. -++# We can always force a build with a 64-bits symbol format by -++# passing 'KBUILD_SYM32=no' option to the make's command line. -++# -++ifdef CONFIG_64BIT -++ ifndef KBUILD_SYM32 -++ ifeq ($(shell expr $(load-y) \< 0xffffffff80000000), 0) -++ KBUILD_SYM32 = y -++ endif -++ endif -++ -++ ifeq ($(KBUILD_SYM32), y) -++ ifeq ($(call cc-option-yn,-msym32), y) -++ cflags-y += -msym32 -DKBUILD_64BIT_SYM32 -++ endif -++ endif -++endif -++ -++KBUILD_AFLAGS += $(cflags-y) -++KBUILD_CFLAGS += $(cflags-y) \ -++ -D"VMLINUX_LOAD_ADDRESS=$(load-y)" -++ -++LDFLAGS += -m $(ld-emul) -++ -++ifdef CONFIG_MIPS -++CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -xc /dev/null | \ -++ egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \ -++ sed -e 's/^\#define /-D/' -e "s/ /='/" -e "s/$$/'/") -++ifdef CONFIG_64BIT -++CHECKFLAGS += -m64 -++endif -++endif -++ -++OBJCOPYFLAGS += --remove-section=.reginfo -++ -++# -++# Choosing incompatible machines durings configuration will result in -++# error messages during linking. Select a default linkscript if -++# none has been choosen above. -++# -++ -++CPPFLAGS_vmlinux.lds := \ -++ $(KBUILD_CFLAGS) \ -++ -D"LOADADDR=$(load-y)" \ -++ -D"JIFFIES=$(JIFFIES)" \ -++ -D"DATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)" -++ -++head-y := arch/mips/kernel/head.o arch/mips/kernel/init_task.o -++ -++libs-y += arch/mips/lib/ -++ -++core-y += arch/mips/kernel/ arch/mips/mm/ arch/mips/math-emu/ -++ -++drivers-$(CONFIG_OPROFILE) += arch/mips/oprofile/ -++ -++ifdef CONFIG_LASAT -++rom.bin rom.sw: vmlinux -++ $(Q)$(MAKE) $(build)=arch/mips/lasat/image $@ -++endif -++ -++# -++# Some machines like the Indy need 32-bit ELF binaries for booting purposes. -++# Other need ECOFF, so we build a 32-bit ELF binary for them which we then -++# convert to ECOFF using elf2ecoff. -++# -++vmlinux.32: vmlinux -++ $(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@ -++ -++# -++# The 64-bit ELF tools are pretty broken so at this time we generate 64-bit -++# ELF files from 32-bit files by conversion. -++# -++vmlinux.64: vmlinux -++ $(OBJCOPY) -O $(64bit-bfd) $(OBJCOPYFLAGS) $< $@ -++ -++makeboot =$(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) $(1) -++ -++all: $(all-y) -++ -++vmlinux.bin: $(vmlinux-32) -++ +@$(call makeboot,$@) -++ -++vmlinux.ecoff: $(vmlinux-32) -++ +@$(call makeboot,$@) -++ -++vmlinux.srec: $(vmlinux-32) -++ +@$(call makeboot,$@) -++ -++CLEAN_FILES += vmlinux.ecoff \ -++ vmlinux.srec -++ -++archprepare: -++ifdef CONFIG_MIPS32_N32 -++ @echo ' Checking missing-syscalls for N32' -++ $(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=n32" -++endif -++ifdef CONFIG_MIPS32_O32 -++ @echo ' Checking missing-syscalls for O32' -++ $(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=32" -++endif -++ -++archclean: -++ @$(MAKE) $(clean)=arch/mips/boot -++ @$(MAKE) $(clean)=arch/mips/lasat -++ -++define archhelp -++ echo ' vmlinux.ecoff - ECOFF boot image' -++ echo ' vmlinux.bin - Raw binary boot image' -++ echo ' vmlinux.srec - SREC boot image' -++ echo -++ echo ' These will be default as apropriate for a configured platform.' -++endef -++ -++CLEAN_FILES += vmlinux.32 \ -++ vmlinux.64 \ -++ vmlinux.ecoff -+diff -urN linux-2.6.24.7.old/arch/mips/boot/Makefile linux-2.6.24.7/arch/mips/boot/Makefile -+--- linux-2.6.24.7.old/arch/mips/boot/Makefile 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/arch/mips/boot/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -7,6 +7,9 @@ -+ # Copyright (C) 2004 Maciej W. Rozycki -+ # -+ -++# This one must match the LOADADDR in arch/mips/Makefile! -++LOADADDR=0x80010000 -++ -+ # -+ # Some DECstations need all possible sections of an ECOFF executable -+ # -+@@ -25,7 +28,7 @@ -+ -+ VMLINUX = vmlinux -+ -+-all: vmlinux.ecoff vmlinux.srec addinitrd -++all: vmlinux.ecoff vmlinux.srec addinitrd uImage zImage -+ -+ vmlinux.ecoff: $(obj)/elf2ecoff $(VMLINUX) -+ $(obj)/elf2ecoff $(VMLINUX) vmlinux.ecoff $(E2EFLAGS) -+@@ -42,8 +45,24 @@ -+ $(obj)/addinitrd: $(obj)/addinitrd.c -+ $(HOSTCC) -o $@ $^ -+ -++uImage: $(VMLINUX) vmlinux.bin -++ rm -f $(obj)/vmlinux.bin.gz -++ gzip -9 $(obj)/vmlinux.bin -++ mkimage -A mips -O linux -T kernel -C gzip \ -++ -a $(LOADADDR) -e $(shell sh ./$(obj)/tools/entry $(NM) $(VMLINUX) ) \ -++ -n 'Linux-$(KERNELRELEASE)' \ -++ -d $(obj)/vmlinux.bin.gz $(obj)/uImage -++ @echo ' Kernel: arch/mips/boot/$@ is ready' -++ -++zImage: -++ $(Q)$(MAKE) $(build)=$(obj)/compressed loadaddr=$(LOADADDR) $@ -++ @echo ' Kernel: arch/mips/boot/compressed/$@ is ready' -++ -+ clean-files += addinitrd \ -+ elf2ecoff \ -+ vmlinux.bin \ -+ vmlinux.ecoff \ -+- vmlinux.srec -++ vmlinux.srec \ -++ vmlinux.bin.gz \ -++ uImage \ -++ zImage -+diff -urN linux-2.6.24.7.old/arch/mips/boot/compressed/Makefile linux-2.6.24.7/arch/mips/boot/compressed/Makefile -+--- linux-2.6.24.7.old/arch/mips/boot/compressed/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/boot/compressed/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,42 @@ -++# -++# linux/arch/mips/boot/compressed/Makefile -++# -++# create a compressed zImage from the original vmlinux -++# -++ -++targets := zImage vmlinuz vmlinux.bin.gz head.o misc.o piggy.o dummy.o -++ -++OBJS := $(obj)/head.o $(obj)/misc.o -++ -++LD_ARGS := -T $(obj)/ld.script -Ttext 0x80600000 -Bstatic -++OBJCOPY_ARGS := -O elf32-tradlittlemips -++ -++ENTRY := $(obj)/../tools/entry -++FILESIZE := $(obj)/../tools/filesize -++ -++drop-sections = .reginfo .mdebug .comment .note .pdr .options .MIPS.options -++strip-flags = $(addprefix --remove-section=,$(drop-sections)) -++ -++ -++$(obj)/vmlinux.bin.gz: vmlinux -++ rm -f $(obj)/vmlinux.bin.gz -++ $(OBJCOPY) -O binary $(strip-flags) vmlinux $(obj)/vmlinux.bin -++ gzip -v9f $(obj)/vmlinux.bin -++ -++$(obj)/head.o: $(obj)/head.S $(obj)/vmlinux.bin.gz vmlinux -++ $(CC) $(KBUILD_AFLAGS) \ -++ -DIMAGESIZE=$(shell sh $(FILESIZE) $(obj)/vmlinux.bin.gz) \ -++ -DKERNEL_ENTRY=$(shell sh $(ENTRY) $(NM) vmlinux ) \ -++ -DLOADADDR=$(loadaddr) \ -++ -c -o $(obj)/head.o $< -++ -++$(obj)/vmlinuz: $(OBJS) $(obj)/ld.script $(obj)/vmlinux.bin.gz $(obj)/dummy.o -++ $(OBJCOPY) \ -++ --add-section=.image=$(obj)/vmlinux.bin.gz \ -++ --set-section-flags=.image=contents,alloc,load,readonly,data \ -++ $(obj)/dummy.o $(obj)/piggy.o -++ $(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/piggy.o -++ $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr -R .initrd -R .sysmap -++ -++zImage: $(obj)/vmlinuz -++ $(OBJCOPY) -O binary $(obj)/vmlinuz $(obj)/zImage -+diff -urN linux-2.6.24.7.old/arch/mips/boot/compressed/dummy.c linux-2.6.24.7/arch/mips/boot/compressed/dummy.c -+--- linux-2.6.24.7.old/arch/mips/boot/compressed/dummy.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/boot/compressed/dummy.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,4 @@ -++int main(void) -++{ -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/arch/mips/boot/compressed/head.S linux-2.6.24.7/arch/mips/boot/compressed/head.S -+--- linux-2.6.24.7.old/arch/mips/boot/compressed/head.S 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/boot/compressed/head.S 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,85 @@ -++/* -++ * linux/arch/mips/boot/compressed/head.S -++ * -++ * Copyright (C) 2005-2008 Ingenic Semiconductor Inc. -++ */ -++ -++#include -++#include -++#include -++#include -++ -++#define IndexInvalidate_I 0x00 -++#define IndexWriteBack_D 0x01 -++ -++ .set noreorder -++ LEAF(startup) -++startup: -++ move s0, a0 /* Save the boot loader transfered args */ -++ move s1, a1 -++ move s2, a2 -++ move s3, a3 -++ -++ la a0, _edata -++ la a1, _end -++1: sw zero, 0(a0) /* Clear BSS section */ -++ bne a1, a0, 1b -++ addu a0, 4 -++ -++ la sp, (.stack + 8192) -++ -++ la a0, __image_begin -++ la a1, IMAGESIZE -++ la a2, LOADADDR -++ la ra, 1f -++ la k0, decompress_kernel -++ jr k0 -++ nop -++1: -++ -++ move a0, s0 -++ move a1, s1 -++ move a2, s2 -++ move a3, s3 -++ li k0, KERNEL_ENTRY -++ jr k0 -++ nop -++2: -++ b 32 -++ END(startup) -++ -++ -++ LEAF(flushcaches) -++ la t0, 1f -++ la t1, 0xa0000000 -++ or t0, t0, t1 -++ jr t0 -++ nop -++1: -++ li k0, 0x80000000 # start address -++ li k1, 0x80004000 # end address (16KB I-Cache) -++ subu k1, 128 -++ -++2: -++ .set mips3 -++ cache IndexWriteBack_D, 0(k0) -++ cache IndexWriteBack_D, 32(k0) -++ cache IndexWriteBack_D, 64(k0) -++ cache IndexWriteBack_D, 96(k0) -++ cache IndexInvalidate_I, 0(k0) -++ cache IndexInvalidate_I, 32(k0) -++ cache IndexInvalidate_I, 64(k0) -++ cache IndexInvalidate_I, 96(k0) -++ .set mips0 -++ -++ bne k0, k1, 2b -++ addu k0, k0, 128 -++ la t0, 3f -++ jr t0 -++ nop -++3: -++ jr ra -++ nop -++ END(flushcaches) -++ -++ .comm .stack,4096*2,4 -+diff -urN linux-2.6.24.7.old/arch/mips/boot/compressed/ld.script linux-2.6.24.7/arch/mips/boot/compressed/ld.script -+--- linux-2.6.24.7.old/arch/mips/boot/compressed/ld.script 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/boot/compressed/ld.script 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,151 @@ -++OUTPUT_ARCH(mips) -++ENTRY(startup) -++SECTIONS -++{ -++ /* Read-only sections, merged into text segment: */ -++ -++ .init : { *(.init) } =0 -++ .text : -++ { -++ _ftext = . ; -++ *(.text) -++ *(.rodata) -++ *(.rodata1) -++ /* .gnu.warning sections are handled specially by elf32.em. */ -++ *(.gnu.warning) -++ } =0 -++ .kstrtab : { *(.kstrtab) } -++ -++ . = ALIGN(16); /* Exception table */ -++ __start___ex_table = .; -++ __ex_table : { *(__ex_table) } -++ __stop___ex_table = .; -++ -++ __start___dbe_table = .; /* Exception table for data bus errors */ -++ __dbe_table : { *(__dbe_table) } -++ __stop___dbe_table = .; -++ -++ __start___ksymtab = .; /* Kernel symbol table */ -++ __ksymtab : { *(__ksymtab) } -++ __stop___ksymtab = .; -++ -++ _etext = .; -++ -++ . = ALIGN(8192); -++ .data.init_task : { *(.data.init_task) } -++ -++ /* Startup code */ -++ . = ALIGN(4096); -++ __init_begin = .; -++ .text.init : { *(.text.init) } -++ .data.init : { *(.data.init) } -++ . = ALIGN(16); -++ __setup_start = .; -++ .setup.init : { *(.setup.init) } -++ __setup_end = .; -++ __initcall_start = .; -++ .initcall.init : { *(.initcall.init) } -++ __initcall_end = .; -++ . = ALIGN(4096); /* Align double page for init_task_union */ -++ __init_end = .; -++ -++ . = ALIGN(4096); -++ .data.page_aligned : { *(.data.idt) } -++ -++ . = ALIGN(32); -++ .data.cacheline_aligned : { *(.data.cacheline_aligned) } -++ -++ .fini : { *(.fini) } =0 -++ .reginfo : { *(.reginfo) } -++ /* Adjust the address for the data segment. We want to adjust up to -++ the same address within the page on the next page up. It would -++ be more correct to do this: -++ . = .; -++ The current expression does not correctly handle the case of a -++ text segment ending precisely at the end of a page; it causes the -++ data segment to skip a page. The above expression does not have -++ this problem, but it will currently (2/95) cause BFD to allocate -++ a single segment, combining both text and data, for this case. -++ This will prevent the text segment from being shared among -++ multiple executions of the program; I think that is more -++ important than losing a page of the virtual address space (note -++ that no actual memory is lost; the page which is skipped can not -++ be referenced). */ -++ . = .; -++ .data : -++ { -++ _fdata = . ; -++ *(.data) -++ -++ /* Put the compressed image here, so bss is on the end. */ -++ __image_begin = .; -++ *(.image) -++ __image_end = .; -++ /* Align the initial ramdisk image (INITRD) on page boundaries. */ -++ . = ALIGN(4096); -++ __ramdisk_begin = .; -++ *(.initrd) -++ __ramdisk_end = .; -++ . = ALIGN(4096); -++ -++ CONSTRUCTORS -++ } -++ .data1 : { *(.data1) } -++ _gp = . + 0x8000; -++ .lit8 : { *(.lit8) } -++ .lit4 : { *(.lit4) } -++ .ctors : { *(.ctors) } -++ .dtors : { *(.dtors) } -++ .got : { *(.got.plt) *(.got) } -++ .dynamic : { *(.dynamic) } -++ /* We want the small data sections together, so single-instruction offsets -++ can access them all, and initialized data all before uninitialized, so -++ we can shorten the on-disk segment size. */ -++ .sdata : { *(.sdata) } -++ . = ALIGN(4); -++ _edata = .; -++ PROVIDE (edata = .); -++ -++ __bss_start = .; -++ _fbss = .; -++ .sbss : { *(.sbss) *(.scommon) } -++ .bss : -++ { -++ *(.dynbss) -++ *(.bss) -++ *(COMMON) -++ . = ALIGN(4); -++ _end = . ; -++ PROVIDE (end = .); -++ } -++ -++ /* Sections to be discarded */ -++ /DISCARD/ : -++ { -++ *(.text.exit) -++ *(.data.exit) -++ *(.exitcall.exit) -++ } -++ -++ /* This is the MIPS specific mdebug section. */ -++ .mdebug : { *(.mdebug) } -++ /* These are needed for ELF backends which have not yet been -++ converted to the new style linker. */ -++ .stab 0 : { *(.stab) } -++ .stabstr 0 : { *(.stabstr) } -++ /* DWARF debug sections. -++ Symbols in the .debug DWARF section are relative to the beginning of the -++ section so we begin .debug at 0. It's not clear yet what needs to happen -++ for the others. */ -++ .debug 0 : { *(.debug) } -++ .debug_srcinfo 0 : { *(.debug_srcinfo) } -++ .debug_aranges 0 : { *(.debug_aranges) } -++ .debug_pubnames 0 : { *(.debug_pubnames) } -++ .debug_sfnames 0 : { *(.debug_sfnames) } -++ .line 0 : { *(.line) } -++ /* These must appear regardless of . */ -++ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } -++ .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } -++ .comment : { *(.comment) } -++ .note : { *(.note) } -++} -+diff -urN linux-2.6.24.7.old/arch/mips/boot/compressed/misc.c linux-2.6.24.7/arch/mips/boot/compressed/misc.c -+--- linux-2.6.24.7.old/arch/mips/boot/compressed/misc.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/boot/compressed/misc.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,242 @@ -++/* -++ * linux/arch/mips/boot/compressed/misc.c -++ * -++ * This is a collection of several routines from gzip-1.0.3 -++ * adapted for Linux. -++ * -++ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 -++ * -++ * Adapted for JZSOC by Peter Wei, 2008 -++ * -++ */ -++ -++#define size_t int -++#define NULL 0 -++ -++/* -++ * gzip declarations -++ */ -++ -++#define OF(args) args -++#define STATIC static -++ -++#undef memset -++#undef memcpy -++#define memzero(s, n) memset ((s), 0, (n)) -++ -++typedef unsigned char uch; -++typedef unsigned short ush; -++typedef unsigned long ulg; -++ -++#define WSIZE 0x8000 /* Window size must be at least 32k, */ -++ /* and a power of two */ -++ -++static uch *inbuf; /* input buffer */ -++static uch window[WSIZE]; /* Sliding window buffer */ -++ -++static unsigned insize = 0; /* valid bytes in inbuf */ -++static unsigned inptr = 0; /* index of next byte to be processed in inbuf */ -++static unsigned outcnt = 0; /* bytes in output buffer */ -++ -++/* gzip flag byte */ -++#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ -++#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ -++#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -++#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -++#define COMMENT 0x10 /* bit 4 set: file comment present */ -++#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ -++#define RESERVED 0xC0 /* bit 6,7: reserved */ -++ -++#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) -++ -++/* Diagnostic functions */ -++#ifdef DEBUG -++# define Assert(cond,msg) {if(!(cond)) error(msg);} -++# define Trace(x) fprintf x -++# define Tracev(x) {if (verbose) fprintf x ;} -++# define Tracevv(x) {if (verbose>1) fprintf x ;} -++# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -++# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} -++#else -++# define Assert(cond,msg) -++# define Trace(x) -++# define Tracev(x) -++# define Tracevv(x) -++# define Tracec(c,x) -++# define Tracecv(c,x) -++#endif -++ -++static int fill_inbuf(void); -++static void flush_window(void); -++static void error(char *m); -++static void gzip_mark(void **); -++static void gzip_release(void **); -++ -++void* memset(void* s, int c, size_t n); -++void* memcpy(void* __dest, __const void* __src, size_t __n); -++ -++extern void flushcaches(void); /* defined in head.S */ -++ -++char *input_data; -++int input_len; -++ -++static long bytes_out = 0; -++static uch *output_data; -++static unsigned long output_ptr = 0; -++ -++ -++static void *malloc(int size); -++static void free(void *where); -++static void error(char *m); -++static void gzip_mark(void **); -++static void gzip_release(void **); -++ -++static void puts(const char *str) -++{ -++} -++ -++extern unsigned char _end[]; -++static unsigned long free_mem_ptr; -++static unsigned long free_mem_end_ptr; -++ -++#define HEAP_SIZE 0x10000 -++ -++#include "../../../../lib/inflate.c" -++ -++static void *malloc(int size) -++{ -++ void *p; -++ -++ if (size <0) error("Malloc error\n"); -++ if (free_mem_ptr == 0) error("Memory error\n"); -++ -++ free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ -++ -++ p = (void *)free_mem_ptr; -++ free_mem_ptr += size; -++ -++ if (free_mem_ptr >= free_mem_end_ptr) -++ error("\nOut of memory\n"); -++ -++ return p; -++} -++ -++static void free(void *where) -++{ /* Don't care */ -++} -++ -++static void gzip_mark(void **ptr) -++{ -++ *ptr = (void *) free_mem_ptr; -++} -++ -++static void gzip_release(void **ptr) -++{ -++ free_mem_ptr = (long) *ptr; -++} -++ -++void* memset(void* s, int c, size_t n) -++{ -++ int i; -++ char *ss = (char*)s; -++ -++ for (i=0;i> 3; i > 0; i--) { -++ *d++ = *s++; -++ *d++ = *s++; -++ *d++ = *s++; -++ *d++ = *s++; -++ *d++ = *s++; -++ *d++ = *s++; -++ *d++ = *s++; -++ *d++ = *s++; -++ } -++ -++ if (__n & 1 << 2) { -++ *d++ = *s++; -++ *d++ = *s++; -++ *d++ = *s++; -++ *d++ = *s++; -++ } -++ -++ if (__n & 1 << 1) { -++ *d++ = *s++; -++ *d++ = *s++; -++ } -++ -++ if (__n & 1) -++ *d++ = *s++; -++ -++ return __dest; -++} -++ -++/* =========================================================================== -++ * Fill the input buffer. This is called only when the buffer is empty -++ * and at least one byte is really needed. -++ */ -++static int fill_inbuf(void) -++{ -++ if (insize != 0) { -++ error("ran out of input data\n"); -++ } -++ -++ inbuf = input_data; -++ insize = input_len; -++ inptr = 1; -++ return inbuf[0]; -++} -++ -++/* =========================================================================== -++ * Write the output window window[0..outcnt-1] and update crc and bytes_out. -++ * (Used for the decompressed data only.) -++ */ -++static void flush_window(void) -++{ -++ ulg c = crc; /* temporary variable */ -++ unsigned n; -++ uch *in, *out, ch; -++ -++ in = window; -++ out = &output_data[output_ptr]; -++ for (n = 0; n < outcnt; n++) { -++ ch = *out++ = *in++; -++ c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); -++ } -++ crc = c; -++ bytes_out += (ulg)outcnt; -++ output_ptr += (ulg)outcnt; -++ outcnt = 0; -++} -++ -++static void error(char *x) -++{ -++ puts("\n\n"); -++ puts(x); -++ puts("\n\n -- System halted"); -++ -++ while(1); /* Halt */ -++} -++ -++void decompress_kernel(unsigned int imageaddr, unsigned int imagesize, unsigned int loadaddr) -++{ -++ input_data = (char *)imageaddr; -++ input_len = imagesize; -++ output_ptr = 0; -++ output_data = (uch *)loadaddr; -++ free_mem_ptr = (unsigned long)_end; -++ free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; -++ -++ makecrc(); -++ puts("Uncompressing Linux..."); -++ gunzip(); -++ flushcaches(); -++ puts("Ok, booting the kernel."); -++} -+diff -urN linux-2.6.24.7.old/arch/mips/boot/tools/entry linux-2.6.24.7/arch/mips/boot/tools/entry -+--- linux-2.6.24.7.old/arch/mips/boot/tools/entry 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/boot/tools/entry 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,12 @@ -++#!/bin/sh -++ -++# grab the kernel_entry address from the vmlinux elf image -++entry=`$1 $2 | grep kernel_entry` -++ -++fs=`echo $entry | grep ffffffff` # check toolchain output -++ -++if [ -n "$fs" ]; then -++ echo "0x"`$1 $2 | grep kernel_entry | cut -c9- | awk '{print $1}'` -++else -++ echo "0x"`$1 $2 | grep kernel_entry | cut -c1- | awk '{print $1}'` -++fi -+diff -urN linux-2.6.24.7.old/arch/mips/boot/tools/filesize linux-2.6.24.7/arch/mips/boot/tools/filesize -+--- linux-2.6.24.7.old/arch/mips/boot/tools/filesize 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/boot/tools/filesize 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,7 @@ -++#!/bin/sh -++HOSTNAME=`uname` -++if [ "$HOSTNAME" = "Linux" ]; then -++echo `ls -l $1 | awk '{print $5}'` -++else -++echo `ls -l $1 | awk '{print $6}'` -++fi -+diff -urN linux-2.6.24.7.old/arch/mips/configs/apus_defconfig linux-2.6.24.7/arch/mips/configs/apus_defconfig -+--- linux-2.6.24.7.old/arch/mips/configs/apus_defconfig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/configs/apus_defconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1205 @@ -++# -++# Automatically generated make config: don't edit -++# Linux kernel version: 2.6.24.3 -++# Fri Dec 12 17:16:48 2008 -++# -++CONFIG_MIPS=y -++ -++# -++# Machine selection -++# -++# CONFIG_JZ4730_PMP is not set -++# CONFIG_JZ4740_PAVO is not set -++# CONFIG_JZ4740_LEO is not set -++# CONFIG_JZ4740_LYRA is not set -++# CONFIG_JZ4725_DIPPER is not set -++# CONFIG_JZ4720_VIRGO is not set -++# CONFIG_JZ4750_FUWA is not set -++CONFIG_JZ4750_APUS=y -++# CONFIG_MACH_ALCHEMY is not set -++# CONFIG_BASLER_EXCITE is not set -++# CONFIG_BCM47XX is not set -++# CONFIG_MIPS_COBALT is not set -++# CONFIG_MACH_DECSTATION is not set -++# CONFIG_MACH_JAZZ is not set -++# CONFIG_LASAT is not set -++# CONFIG_LEMOTE_FULONG is not set -++# CONFIG_MIPS_ATLAS is not set -++# CONFIG_MIPS_MALTA is not set -++# CONFIG_MIPS_SEAD is not set -++# CONFIG_MIPS_SIM is not set -++# CONFIG_MARKEINS is not set -++# CONFIG_MACH_VR41XX is not set -++# CONFIG_PNX8550_JBS is not set -++# CONFIG_PNX8550_STB810 is not set -++# CONFIG_PMC_MSP is not set -++# CONFIG_PMC_YOSEMITE is not set -++# CONFIG_QEMU is not set -++# CONFIG_SGI_IP22 is not set -++# CONFIG_SGI_IP27 is not set -++# CONFIG_SGI_IP32 is not set -++# CONFIG_SIBYTE_CRHINE is not set -++# CONFIG_SIBYTE_CARMEL is not set -++# CONFIG_SIBYTE_CRHONE is not set -++# CONFIG_SIBYTE_RHONE is not set -++# CONFIG_SIBYTE_SWARM is not set -++# CONFIG_SIBYTE_LITTLESUR is not set -++# CONFIG_SIBYTE_SENTOSA is not set -++# CONFIG_SIBYTE_PTSWARM is not set -++# CONFIG_SIBYTE_BIGSUR is not set -++# CONFIG_SNI_RM is not set -++# CONFIG_TOSHIBA_JMR3927 is not set -++# CONFIG_TOSHIBA_RBTX4927 is not set -++# CONFIG_TOSHIBA_RBTX4938 is not set -++# CONFIG_WR_PPMC is not set -++CONFIG_SOC_JZ4750=y -++CONFIG_JZSOC=y -++CONFIG_JZRISC=y -++CONFIG_RWSEM_GENERIC_SPINLOCK=y -++# CONFIG_ARCH_HAS_ILOG2_U32 is not set -++# CONFIG_ARCH_HAS_ILOG2_U64 is not set -++CONFIG_ARCH_SUPPORTS_OPROFILE=y -++CONFIG_GENERIC_FIND_NEXT_BIT=y -++CONFIG_GENERIC_HWEIGHT=y -++CONFIG_GENERIC_CALIBRATE_DELAY=y -++CONFIG_GENERIC_CLOCKEVENTS=y -++CONFIG_GENERIC_TIME=y -++CONFIG_GENERIC_CMOS_UPDATE=y -++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -++# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set -++CONFIG_DMA_NONCOHERENT=y -++CONFIG_DMA_NEED_PCI_MAP_STATE=y -++# CONFIG_HOTPLUG_CPU is not set -++# CONFIG_NO_IOPORT is not set -++# CONFIG_CPU_BIG_ENDIAN is not set -++CONFIG_CPU_LITTLE_ENDIAN=y -++CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -++CONFIG_MIPS_L1_CACHE_SHIFT=5 -++ -++# -++# CPU selection -++# -++# CONFIG_CPU_LOONGSON2 is not set -++CONFIG_CPU_MIPS32_R1=y -++# CONFIG_CPU_MIPS32_R2 is not set -++# CONFIG_CPU_MIPS64_R1 is not set -++# CONFIG_CPU_MIPS64_R2 is not set -++# CONFIG_CPU_R3000 is not set -++# CONFIG_CPU_TX39XX is not set -++# CONFIG_CPU_VR41XX is not set -++# CONFIG_CPU_R4300 is not set -++# CONFIG_CPU_R4X00 is not set -++# CONFIG_CPU_TX49XX is not set -++# CONFIG_CPU_R5000 is not set -++# CONFIG_CPU_R5432 is not set -++# CONFIG_CPU_R6000 is not set -++# CONFIG_CPU_NEVADA is not set -++# CONFIG_CPU_R8000 is not set -++# CONFIG_CPU_R10000 is not set -++# CONFIG_CPU_RM7000 is not set -++# CONFIG_CPU_RM9000 is not set -++# CONFIG_CPU_SB1 is not set -++CONFIG_SYS_HAS_CPU_MIPS32_R1=y -++CONFIG_CPU_MIPS32=y -++CONFIG_CPU_MIPSR1=y -++CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -++CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -++ -++# -++# Kernel type -++# -++CONFIG_32BIT=y -++# CONFIG_64BIT is not set -++CONFIG_PAGE_SIZE_4KB=y -++# CONFIG_PAGE_SIZE_8KB is not set -++# CONFIG_PAGE_SIZE_16KB is not set -++# CONFIG_PAGE_SIZE_64KB is not set -++CONFIG_CPU_HAS_PREFETCH=y -++CONFIG_MIPS_MT_DISABLED=y -++# CONFIG_MIPS_MT_SMP is not set -++# CONFIG_MIPS_MT_SMTC is not set -++CONFIG_CPU_HAS_LLSC=y -++CONFIG_CPU_HAS_SYNC=y -++CONFIG_GENERIC_HARDIRQS=y -++CONFIG_GENERIC_IRQ_PROBE=y -++CONFIG_CPU_SUPPORTS_HIGHMEM=y -++CONFIG_ARCH_FLATMEM_ENABLE=y -++CONFIG_ARCH_POPULATES_NODE_MAP=y -++CONFIG_SELECT_MEMORY_MODEL=y -++CONFIG_FLATMEM_MANUAL=y -++# CONFIG_DISCONTIGMEM_MANUAL is not set -++# CONFIG_SPARSEMEM_MANUAL is not set -++CONFIG_FLATMEM=y -++CONFIG_FLAT_NODE_MEM_MAP=y -++# CONFIG_SPARSEMEM_STATIC is not set -++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -++CONFIG_SPLIT_PTLOCK_CPUS=4 -++# CONFIG_RESOURCES_64BIT is not set -++CONFIG_ZONE_DMA_FLAG=0 -++CONFIG_VIRT_TO_BUS=y -++# CONFIG_TICK_ONESHOT is not set -++# CONFIG_NO_HZ is not set -++# CONFIG_HIGH_RES_TIMERS is not set -++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -++CONFIG_FORCE_MAX_ZONEORDER=12 -++# CONFIG_HZ_48 is not set -++CONFIG_HZ_100=y -++# CONFIG_HZ_128 is not set -++# CONFIG_HZ_250 is not set -++# CONFIG_HZ_256 is not set -++# CONFIG_HZ_1000 is not set -++# CONFIG_HZ_1024 is not set -++CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -++CONFIG_HZ=100 -++# CONFIG_PREEMPT_NONE is not set -++# CONFIG_PREEMPT_VOLUNTARY is not set -++CONFIG_PREEMPT=y -++CONFIG_PREEMPT_BKL=y -++# CONFIG_KEXEC is not set -++CONFIG_SECCOMP=y -++CONFIG_LOCKDEP_SUPPORT=y -++CONFIG_STACKTRACE_SUPPORT=y -++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -++ -++# -++# General setup -++# -++CONFIG_EXPERIMENTAL=y -++CONFIG_BROKEN_ON_SMP=y -++CONFIG_LOCK_KERNEL=y -++CONFIG_INIT_ENV_ARG_LIMIT=32 -++CONFIG_LOCALVERSION="" -++CONFIG_LOCALVERSION_AUTO=y -++CONFIG_SWAP=y -++CONFIG_SYSVIPC=y -++CONFIG_SYSVIPC_SYSCTL=y -++# CONFIG_POSIX_MQUEUE is not set -++# CONFIG_BSD_PROCESS_ACCT is not set -++# CONFIG_TASKSTATS is not set -++# CONFIG_USER_NS is not set -++# CONFIG_PID_NS is not set -++# CONFIG_AUDIT is not set -++# CONFIG_IKCONFIG is not set -++CONFIG_LOG_BUF_SHIFT=14 -++# CONFIG_CGROUPS is not set -++CONFIG_FAIR_GROUP_SCHED=y -++CONFIG_FAIR_USER_SCHED=y -++# CONFIG_FAIR_CGROUP_SCHED is not set -++CONFIG_SYSFS_DEPRECATED=y -++CONFIG_RELAY=y -++# CONFIG_BLK_DEV_INITRD is not set -++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -++CONFIG_SYSCTL=y -++CONFIG_EMBEDDED=y -++CONFIG_SYSCTL_SYSCALL=y -++CONFIG_KALLSYMS=y -++# CONFIG_KALLSYMS_EXTRA_PASS is not set -++CONFIG_HOTPLUG=y -++CONFIG_PRINTK=y -++CONFIG_BUG=y -++CONFIG_ELF_CORE=y -++CONFIG_BASE_FULL=y -++CONFIG_FUTEX=y -++CONFIG_ANON_INODES=y -++CONFIG_EPOLL=y -++CONFIG_SIGNALFD=y -++CONFIG_EVENTFD=y -++CONFIG_SHMEM=y -++CONFIG_VM_EVENT_COUNTERS=y -++CONFIG_SLAB=y -++# CONFIG_SLUB is not set -++# CONFIG_SLOB is not set -++CONFIG_SLABINFO=y -++CONFIG_RT_MUTEXES=y -++# CONFIG_TINY_SHMEM is not set -++CONFIG_BASE_SMALL=0 -++CONFIG_MODULES=y -++CONFIG_MODULE_UNLOAD=y -++# CONFIG_MODULE_FORCE_UNLOAD is not set -++CONFIG_MODVERSIONS=y -++CONFIG_MODULE_SRCVERSION_ALL=y -++CONFIG_KMOD=y -++CONFIG_BLOCK=y -++# CONFIG_LBD is not set -++# CONFIG_BLK_DEV_IO_TRACE is not set -++# CONFIG_LSF is not set -++# CONFIG_BLK_DEV_BSG is not set -++ -++# -++# IO Schedulers -++# -++CONFIG_IOSCHED_NOOP=y -++CONFIG_IOSCHED_AS=y -++CONFIG_IOSCHED_DEADLINE=y -++CONFIG_IOSCHED_CFQ=y -++CONFIG_DEFAULT_AS=y -++# CONFIG_DEFAULT_DEADLINE is not set -++# CONFIG_DEFAULT_CFQ is not set -++# CONFIG_DEFAULT_NOOP is not set -++CONFIG_DEFAULT_IOSCHED="anticipatory" -++ -++# -++# Bus options (PCI, PCMCIA, EISA, ISA, TC) -++# -++# CONFIG_ARCH_SUPPORTS_MSI is not set -++CONFIG_MMU=y -++# CONFIG_PCCARD is not set -++ -++# -++# Executable file formats -++# -++CONFIG_BINFMT_ELF=y -++# CONFIG_BINFMT_MISC is not set -++CONFIG_TRAD_SIGNALS=y -++ -++# -++# CPU Frequency scaling -++# -++CONFIG_CPU_FREQ_JZ=y -++CONFIG_CPU_FREQ=y -++CONFIG_CPU_FREQ_TABLE=y -++# CONFIG_CPU_FREQ_DEBUG is not set -++CONFIG_CPU_FREQ_STAT=y -++# CONFIG_CPU_FREQ_STAT_DETAILS is not set -++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -++# CONFIG_CPU_FREQ_GOV_USERSPACE is not set -++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set -++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -++ -++# -++# Power management options -++# -++CONFIG_PM=y -++CONFIG_PM_LEGACY=y -++# CONFIG_PM_DEBUG is not set -++CONFIG_SUSPEND_UP_POSSIBLE=y -++# CONFIG_SUSPEND is not set -++ -++# -++# Networking -++# -++CONFIG_NET=y -++ -++# -++# Networking options -++# -++CONFIG_PACKET=y -++# CONFIG_PACKET_MMAP is not set -++CONFIG_UNIX=y -++# CONFIG_NET_KEY is not set -++CONFIG_INET=y -++# CONFIG_IP_MULTICAST is not set -++# CONFIG_IP_ADVANCED_ROUTER is not set -++CONFIG_IP_FIB_HASH=y -++CONFIG_IP_PNP=y -++CONFIG_IP_PNP_DHCP=y -++CONFIG_IP_PNP_BOOTP=y -++# CONFIG_IP_PNP_RARP is not set -++# CONFIG_NET_IPIP is not set -++# CONFIG_NET_IPGRE is not set -++# CONFIG_ARPD is not set -++# CONFIG_SYN_COOKIES is not set -++# CONFIG_INET_AH is not set -++# CONFIG_INET_ESP is not set -++# CONFIG_INET_IPCOMP is not set -++# CONFIG_INET_XFRM_TUNNEL is not set -++# CONFIG_INET_TUNNEL is not set -++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -++# CONFIG_INET_XFRM_MODE_TUNNEL is not set -++# CONFIG_INET_XFRM_MODE_BEET is not set -++# CONFIG_INET_LRO is not set -++CONFIG_INET_DIAG=m -++CONFIG_INET_TCP_DIAG=m -++# CONFIG_TCP_CONG_ADVANCED is not set -++CONFIG_TCP_CONG_CUBIC=y -++CONFIG_DEFAULT_TCP_CONG="cubic" -++# CONFIG_TCP_MD5SIG is not set -++# CONFIG_IPV6 is not set -++# CONFIG_INET6_XFRM_TUNNEL is not set -++# CONFIG_INET6_TUNNEL is not set -++# CONFIG_NETWORK_SECMARK is not set -++# CONFIG_NETFILTER is not set -++# CONFIG_IP_DCCP is not set -++# CONFIG_IP_SCTP is not set -++# CONFIG_TIPC is not set -++# CONFIG_ATM is not set -++# CONFIG_BRIDGE is not set -++# CONFIG_VLAN_8021Q is not set -++# CONFIG_DECNET is not set -++# CONFIG_LLC2 is not set -++# CONFIG_IPX is not set -++# CONFIG_ATALK is not set -++# CONFIG_X25 is not set -++# CONFIG_LAPB is not set -++# CONFIG_ECONET is not set -++# CONFIG_WAN_ROUTER is not set -++# CONFIG_NET_SCHED is not set -++ -++# -++# Network testing -++# -++# CONFIG_NET_PKTGEN is not set -++# CONFIG_HAMRADIO is not set -++# CONFIG_IRDA is not set -++# CONFIG_BT is not set -++# CONFIG_AF_RXRPC is not set -++ -++# -++# Wireless -++# -++# CONFIG_CFG80211 is not set -++CONFIG_WIRELESS_EXT=y -++# CONFIG_MAC80211 is not set -++# CONFIG_IEEE80211 is not set -++# CONFIG_RFKILL is not set -++# CONFIG_NET_9P is not set -++ -++# -++# Device Drivers -++# -++ -++# -++# Generic Driver Options -++# -++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -++CONFIG_STANDALONE=y -++CONFIG_PREVENT_FIRMWARE_BUILD=y -++# CONFIG_FW_LOADER is not set -++# CONFIG_SYS_HYPERVISOR is not set -++# CONFIG_CONNECTOR is not set -++CONFIG_MTD=y -++# CONFIG_MTD_DEBUG is not set -++# CONFIG_MTD_CONCAT is not set -++CONFIG_MTD_PARTITIONS=y -++# CONFIG_MTD_REDBOOT_PARTS is not set -++# CONFIG_MTD_CMDLINE_PARTS is not set -++ -++# -++# User Modules And Translation Layers -++# -++CONFIG_MTD_CHAR=y -++CONFIG_MTD_BLKDEVS=y -++CONFIG_MTD_BLOCK=y -++# CONFIG_FTL is not set -++# CONFIG_NFTL is not set -++# CONFIG_INFTL is not set -++# CONFIG_RFD_FTL is not set -++# CONFIG_SSFDC is not set -++# CONFIG_MTD_OOPS is not set -++ -++# -++# RAM/ROM/Flash chip drivers -++# -++# CONFIG_MTD_CFI is not set -++# CONFIG_MTD_JEDECPROBE is not set -++CONFIG_MTD_MAP_BANK_WIDTH_1=y -++CONFIG_MTD_MAP_BANK_WIDTH_2=y -++CONFIG_MTD_MAP_BANK_WIDTH_4=y -++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -++CONFIG_MTD_CFI_I1=y -++CONFIG_MTD_CFI_I2=y -++# CONFIG_MTD_CFI_I4 is not set -++# CONFIG_MTD_CFI_I8 is not set -++# CONFIG_MTD_RAM is not set -++# CONFIG_MTD_ROM is not set -++# CONFIG_MTD_ABSENT is not set -++ -++# -++# Mapping drivers for chip access -++# -++# CONFIG_MTD_COMPLEX_MAPPINGS is not set -++# CONFIG_MTD_PLATRAM is not set -++ -++# -++# Self-contained MTD device drivers -++# -++# CONFIG_MTD_SLRAM is not set -++# CONFIG_MTD_PHRAM is not set -++# CONFIG_MTD_MTDRAM is not set -++# CONFIG_MTD_BLOCK2MTD is not set -++ -++# -++# Disk-On-Chip Device Drivers -++# -++# CONFIG_MTD_DOC2000 is not set -++# CONFIG_MTD_DOC2001 is not set -++# CONFIG_MTD_DOC2001PLUS is not set -++CONFIG_MTD_NAND=y -++# CONFIG_MTD_NAND_VERIFY_WRITE is not set -++# CONFIG_MTD_NAND_ECC_SMC is not set -++# CONFIG_MTD_NAND_MUSEUM_IDS is not set -++CONFIG_MTD_NAND_IDS=y -++# CONFIG_MTD_NAND_DISKONCHIP is not set -++# CONFIG_MTD_NAND_NANDSIM is not set -++# CONFIG_MTD_NAND_PLATFORM is not set -++# CONFIG_MTD_ALAUDA is not set -++CONFIG_MTD_NAND_JZ4750=y -++# CONFIG_MTD_NAND_CS2 is not set -++# CONFIG_MTD_NAND_CS3 is not set -++# CONFIG_MTD_NAND_CS4 is not set -++CONFIG_MTD_NAND_MULTI_PLANE=y -++# CONFIG_MTD_HW_HM_ECC is not set -++# CONFIG_MTD_SW_HM_ECC is not set -++# CONFIG_MTD_HW_RS_ECC is not set -++CONFIG_MTD_HW_BCH_ECC=y -++CONFIG_MTD_HW_BCH_4BIT=y -++# CONFIG_MTD_HW_BCH_8BIT is not set -++CONFIG_MTD_NAND_DMA=y -++# CONFIG_MTD_NAND_DMABUF is not set -++# CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE is not set -++CONFIG_MTD_OOB_COPIES=3 -++CONFIG_MTD_BADBLOCK_FLAG_PAGE=127 -++# CONFIG_MTD_ONENAND is not set -++ -++# -++# UBI - Unsorted block images -++# -++# CONFIG_MTD_UBI is not set -++# CONFIG_MTD_UBI_BLKDEVS is not set -++# CONFIG_PARPORT is not set -++# CONFIG_PNP is not set -++CONFIG_BLK_DEV=y -++# CONFIG_BLK_DEV_COW_COMMON is not set -++CONFIG_BLK_DEV_LOOP=y -++# CONFIG_BLK_DEV_CRYPTOLOOP is not set -++# CONFIG_BLK_DEV_NBD is not set -++# CONFIG_BLK_DEV_UB is not set -++CONFIG_BLK_DEV_RAM=y -++CONFIG_BLK_DEV_RAM_COUNT=16 -++CONFIG_BLK_DEV_RAM_SIZE=4096 -++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -++# CONFIG_CDROM_PKTCDVD is not set -++# CONFIG_ATA_OVER_ETH is not set -++CONFIG_MISC_DEVICES=y -++# CONFIG_EEPROM_93CX6 is not set -++# CONFIG_IDE is not set -++ -++# -++# SCSI device support -++# -++# CONFIG_RAID_ATTRS is not set -++CONFIG_SCSI=y -++CONFIG_SCSI_DMA=y -++# CONFIG_SCSI_TGT is not set -++# CONFIG_SCSI_NETLINK is not set -++CONFIG_SCSI_PROC_FS=y -++ -++# -++# SCSI support type (disk, tape, CD-ROM) -++# -++CONFIG_BLK_DEV_SD=y -++# CONFIG_CHR_DEV_ST is not set -++# CONFIG_CHR_DEV_OSST is not set -++# CONFIG_BLK_DEV_SR is not set -++# CONFIG_CHR_DEV_SG is not set -++# CONFIG_CHR_DEV_SCH is not set -++ -++# -++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -++# -++# CONFIG_SCSI_MULTI_LUN is not set -++# CONFIG_SCSI_CONSTANTS is not set -++# CONFIG_SCSI_LOGGING is not set -++# CONFIG_SCSI_SCAN_ASYNC is not set -++CONFIG_SCSI_WAIT_SCAN=m -++ -++# -++# SCSI Transports -++# -++# CONFIG_SCSI_SPI_ATTRS is not set -++# CONFIG_SCSI_FC_ATTRS is not set -++# CONFIG_SCSI_ISCSI_ATTRS is not set -++# CONFIG_SCSI_SAS_LIBSAS is not set -++# CONFIG_SCSI_SRP_ATTRS is not set -++CONFIG_SCSI_LOWLEVEL=y -++# CONFIG_ISCSI_TCP is not set -++# CONFIG_SCSI_DEBUG is not set -++# CONFIG_ATA is not set -++# CONFIG_MD is not set -++CONFIG_NETDEVICES=y -++# CONFIG_NETDEVICES_MULTIQUEUE is not set -++# CONFIG_DUMMY is not set -++# CONFIG_BONDING is not set -++# CONFIG_MACVLAN is not set -++# CONFIG_EQUALIZER is not set -++# CONFIG_TUN is not set -++# CONFIG_VETH is not set -++CONFIG_PHYLIB=y -++ -++# -++# MII PHY device drivers -++# -++# CONFIG_MARVELL_PHY is not set -++# CONFIG_DAVICOM_PHY is not set -++# CONFIG_QSEMI_PHY is not set -++# CONFIG_LXT_PHY is not set -++# CONFIG_CICADA_PHY is not set -++# CONFIG_VITESSE_PHY is not set -++# CONFIG_SMSC_PHY is not set -++# CONFIG_BROADCOM_PHY is not set -++# CONFIG_ICPLUS_PHY is not set -++# CONFIG_FIXED_PHY is not set -++# CONFIG_MDIO_BITBANG is not set -++CONFIG_NET_ETHERNET=y -++CONFIG_MII=y -++CONFIG_JZCS8900=y -++# CONFIG_AX88796 is not set -++# CONFIG_DM9000 is not set -++# CONFIG_IBM_NEW_EMAC_ZMII is not set -++# CONFIG_IBM_NEW_EMAC_RGMII is not set -++# CONFIG_IBM_NEW_EMAC_TAH is not set -++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -++# CONFIG_B44 is not set -++# CONFIG_NETDEV_1000 is not set -++# CONFIG_NETDEV_10000 is not set -++ -++# -++# Wireless LAN -++# -++# CONFIG_WLAN_PRE80211 is not set -++# CONFIG_WLAN_80211 is not set -++ -++# -++# USB Network Adapters -++# -++# CONFIG_USB_CATC is not set -++# CONFIG_USB_KAWETH is not set -++# CONFIG_USB_PEGASUS is not set -++# CONFIG_USB_RTL8150 is not set -++# CONFIG_USB_USBNET is not set -++# CONFIG_WAN is not set -++# CONFIG_PPP is not set -++# CONFIG_SLIP is not set -++# CONFIG_SHAPER is not set -++# CONFIG_NETCONSOLE is not set -++# CONFIG_NETPOLL is not set -++# CONFIG_NET_POLL_CONTROLLER is not set -++# CONFIG_ISDN is not set -++# CONFIG_PHONE is not set -++ -++# -++# Input device support -++# -++CONFIG_INPUT=y -++# CONFIG_INPUT_FF_MEMLESS is not set -++# CONFIG_INPUT_POLLDEV is not set -++ -++# -++# Userland interfaces -++# -++CONFIG_INPUT_MOUSEDEV=y -++CONFIG_INPUT_MOUSEDEV_PSAUX=y -++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -++# CONFIG_INPUT_JOYDEV is not set -++# CONFIG_INPUT_EVDEV is not set -++# CONFIG_INPUT_EVBUG is not set -++ -++# -++# Input Device Drivers -++# -++CONFIG_INPUT_KEYBOARD=y -++CONFIG_KEYBOARD_ATKBD=y -++# CONFIG_KEYBOARD_SUNKBD is not set -++# CONFIG_KEYBOARD_LKKBD is not set -++# CONFIG_KEYBOARD_XTKBD is not set -++# CONFIG_KEYBOARD_NEWTON is not set -++# CONFIG_KEYBOARD_STOWAWAY is not set -++# CONFIG_KEYBOARD_JZ is not set -++# CONFIG_KEYBOARD_GPIO is not set -++# CONFIG_INPUT_MOUSE is not set -++# CONFIG_INPUT_JOYSTICK is not set -++# CONFIG_INPUT_TABLET is not set -++# CONFIG_INPUT_TOUCHSCREEN is not set -++# CONFIG_INPUT_MISC is not set -++ -++# -++# Hardware I/O ports -++# -++CONFIG_SERIO=y -++# CONFIG_SERIO_I8042 is not set -++CONFIG_SERIO_SERPORT=y -++CONFIG_SERIO_LIBPS2=y -++# CONFIG_SERIO_RAW is not set -++# CONFIG_GAMEPORT is not set -++ -++# -++# Character devices -++# -++CONFIG_VT=y -++CONFIG_VT_CONSOLE=y -++CONFIG_HW_CONSOLE=y -++CONFIG_VT_HW_CONSOLE_BINDING=y -++# CONFIG_SERIAL_NONSTANDARD is not set -++ -++# -++# Serial drivers -++# -++CONFIG_SERIAL_8250=y -++CONFIG_SERIAL_8250_CONSOLE=y -++CONFIG_SERIAL_8250_NR_UARTS=4 -++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -++# CONFIG_SERIAL_8250_EXTENDED is not set -++ -++# -++# Non-8250 serial port support -++# -++CONFIG_SERIAL_CORE=y -++CONFIG_SERIAL_CORE_CONSOLE=y -++CONFIG_UNIX98_PTYS=y -++CONFIG_LEGACY_PTYS=y -++CONFIG_LEGACY_PTY_COUNT=2 -++# CONFIG_IPMI_HANDLER is not set -++# CONFIG_HW_RANDOM is not set -++# CONFIG_RTC is not set -++# CONFIG_RTC_PCF8563 is not set -++# CONFIG_RTC_JZ is not set -++# CONFIG_R3964 is not set -++# CONFIG_RAW_DRIVER is not set -++# CONFIG_TCG_TPM is not set -++ -++# -++# JZSOC char device support -++# -++CONFIG_JZCHAR=y -++# CONFIG_JZ_CIM is not set -++# CONFIG_JZ_TPANEL_ATA2508 is not set -++CONFIG_JZ_TPANEL=y -++CONFIG_JZ_SADC=y -++# CONFIG_JZ_TPANEL_AK4182 is not set -++# CONFIG_JZ_TPANEL_UCB1400 is not set -++# CONFIG_JZ_TPANEL_WM9712 is not set -++# CONFIG_JZ_UDC_HOTPLUG is not set -++CONFIG_JZ_POWEROFF=y -++# CONFIG_JZ_OW is not set -++CONFIG_JZ_TCSM=y -++# CONFIG_I2C is not set -++ -++# -++# SPI support -++# -++# CONFIG_SPI is not set -++# CONFIG_SPI_MASTER is not set -++# CONFIG_W1 is not set -++# CONFIG_POWER_SUPPLY is not set -++# CONFIG_HWMON is not set -++# CONFIG_WATCHDOG is not set -++ -++# -++# Sonics Silicon Backplane -++# -++CONFIG_SSB_POSSIBLE=y -++# CONFIG_SSB is not set -++ -++# -++# Multifunction device drivers -++# -++# CONFIG_MFD_SM501 is not set -++ -++# -++# Multimedia devices -++# -++# CONFIG_VIDEO_DEV is not set -++# CONFIG_DVB_CORE is not set -++# CONFIG_DAB is not set -++ -++# -++# Graphics support -++# -++# CONFIG_VGASTATE is not set -++# CONFIG_VIDEO_OUTPUT_CONTROL is not set -++CONFIG_FB=y -++# CONFIG_FIRMWARE_EDID is not set -++# CONFIG_FB_DDC is not set -++CONFIG_FB_CFB_FILLRECT=y -++CONFIG_FB_CFB_COPYAREA=y -++CONFIG_FB_CFB_IMAGEBLIT=y -++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -++# CONFIG_FB_SYS_FILLRECT is not set -++# CONFIG_FB_SYS_COPYAREA is not set -++# CONFIG_FB_SYS_IMAGEBLIT is not set -++# CONFIG_FB_SYS_FOPS is not set -++CONFIG_FB_DEFERRED_IO=y -++# CONFIG_FB_SVGALIB is not set -++# CONFIG_FB_MACMODES is not set -++# CONFIG_FB_BACKLIGHT is not set -++# CONFIG_FB_MODE_HELPERS is not set -++# CONFIG_FB_TILEBLITTING is not set -++ -++# -++# Frame buffer hardware drivers -++# -++CONFIG_FB_JZSOC=y -++CONFIG_FB_JZ4750_TVE=y -++# CONFIG_IPU_JZ4750 is not set -++CONFIG_FB_JZ4750_LCD=y -++# CONFIG_FB_JZ4750_LCD_USE_2LAYER_FRAMEBUFFER is not set -++# CONFIG_FB_JZ4750_SLCD is not set -++# CONFIG_JZ4750_LCD_SAMSUNG_LTP400WQF01 is not set -++# CONFIG_JZ4750_LCD_SAMSUNG_LTP400WQF02 is not set -++CONFIG_JZ4750_LCD_AUO_A043FL01V2=y -++# CONFIG_JZ4750_LCD_FOXCONN_PT035TN01 is not set -++# CONFIG_JZ4750_LCD_INNOLUX_PT035TN01_SERIAL is not set -++# CONFIG_JZ4750_LCD_TOPPOLY_TD025THEA7_RGB_DELTA is not set -++# CONFIG_JZ4750_LCD_TRULY_TFTG320240DTSW_18BIT is not set -++# CONFIG_JZ4750_LCD_TRULY_TFT_GG1P0319LTSW_W is not set -++# CONFIG_JZ4750_SLCD_KGM701A3_TFT_SPFD5420A is not set -++# CONFIG_FB_S1D13XXX is not set -++# CONFIG_FB_VIRTUAL is not set -++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set -++ -++# -++# Display device support -++# -++# CONFIG_DISPLAY_SUPPORT is not set -++ -++# -++# Console display driver support -++# -++# CONFIG_VGA_CONSOLE is not set -++CONFIG_DUMMY_CONSOLE=y -++CONFIG_FRAMEBUFFER_CONSOLE=y -++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -++# CONFIG_FRAMEBUFFER_CONSOLE_CURSOR_FLASH is not set -++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -++CONFIG_FONTS=y -++CONFIG_FONT_8x8=y -++CONFIG_FONT_8x16=y -++# CONFIG_FONT_6x11 is not set -++# CONFIG_FONT_7x14 is not set -++# CONFIG_FONT_PEARL_8x8 is not set -++# CONFIG_FONT_ACORN_8x8 is not set -++# CONFIG_FONT_MINI_4x6 is not set -++# CONFIG_FONT_SUN8x16 is not set -++# CONFIG_FONT_SUN12x22 is not set -++# CONFIG_FONT_10x18 is not set -++CONFIG_LOGO=y -++CONFIG_LOGO_LINUX_MONO=y -++CONFIG_LOGO_LINUX_VGA16=y -++CONFIG_LOGO_LINUX_CLUT224=y -++ -++# -++# Sound -++# -++CONFIG_SOUND=y -++ -++# -++# Advanced Linux Sound Architecture -++# -++# CONFIG_SND is not set -++ -++# -++# Open Sound System -++# -++CONFIG_SOUND_PRIME=y -++CONFIG_OSS_OBSOLETE=y -++# CONFIG_SOUND_JZ_AC97 is not set -++CONFIG_SOUND_JZ_I2S=y -++# CONFIG_SOUND_JZ_PCM is not set -++# CONFIG_I2S_AK4642EN is not set -++# CONFIG_I2S_ICODEC is not set -++CONFIG_I2S_DLV=y -++# CONFIG_SOUND_MSNDCLAS is not set -++# CONFIG_SOUND_MSNDPIN is not set -++CONFIG_HID_SUPPORT=y -++CONFIG_HID=y -++# CONFIG_HID_DEBUG is not set -++# CONFIG_HIDRAW is not set -++ -++# -++# USB Input Devices -++# -++CONFIG_USB_HID=y -++# CONFIG_USB_HIDINPUT_POWERBOOK is not set -++# CONFIG_HID_FF is not set -++CONFIG_USB_HIDDEV=y -++CONFIG_USB_SUPPORT=y -++CONFIG_USB_ARCH_HAS_HCD=y -++CONFIG_USB_ARCH_HAS_OHCI=y -++# CONFIG_USB_ARCH_HAS_EHCI is not set -++CONFIG_USB=y -++# CONFIG_USB_DEBUG is not set -++ -++# -++# Miscellaneous USB options -++# -++# CONFIG_USB_DEVICEFS is not set -++CONFIG_USB_DEVICE_CLASS=y -++# CONFIG_USB_DYNAMIC_MINORS is not set -++# CONFIG_USB_SUSPEND is not set -++# CONFIG_USB_PERSIST is not set -++# CONFIG_USB_OTG is not set -++ -++# -++# USB Host Controller Drivers -++# -++# CONFIG_USB_ISP116X_HCD is not set -++CONFIG_USB_OHCI_HCD=y -++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set -++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set -++CONFIG_USB_OHCI_LITTLE_ENDIAN=y -++# CONFIG_USB_SL811_HCD is not set -++# CONFIG_USB_R8A66597_HCD is not set -++ -++# -++# USB Device Class drivers -++# -++# CONFIG_USB_ACM is not set -++# CONFIG_USB_PRINTER is not set -++ -++# -++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -++# -++ -++# -++# may also be needed; see USB_STORAGE Help for more information -++# -++CONFIG_USB_STORAGE=y -++# CONFIG_USB_STORAGE_DEBUG is not set -++# CONFIG_USB_STORAGE_DATAFAB is not set -++# CONFIG_USB_STORAGE_FREECOM is not set -++# CONFIG_USB_STORAGE_ISD200 is not set -++# CONFIG_USB_STORAGE_DPCM is not set -++# CONFIG_USB_STORAGE_USBAT is not set -++# CONFIG_USB_STORAGE_SDDR09 is not set -++# CONFIG_USB_STORAGE_SDDR55 is not set -++# CONFIG_USB_STORAGE_JUMPSHOT is not set -++# CONFIG_USB_STORAGE_ALAUDA is not set -++# CONFIG_USB_STORAGE_KARMA is not set -++# CONFIG_USB_LIBUSUAL is not set -++ -++# -++# USB Imaging devices -++# -++# CONFIG_USB_MDC800 is not set -++# CONFIG_USB_MICROTEK is not set -++CONFIG_USB_MON=y -++ -++# -++# USB port drivers -++# -++ -++# -++# USB Serial Converter support -++# -++# CONFIG_USB_SERIAL is not set -++ -++# -++# USB Miscellaneous drivers -++# -++# CONFIG_USB_EMI62 is not set -++# CONFIG_USB_EMI26 is not set -++# CONFIG_USB_ADUTUX is not set -++# CONFIG_USB_AUERSWALD is not set -++# CONFIG_USB_RIO500 is not set -++# CONFIG_USB_LEGOTOWER is not set -++# CONFIG_USB_LCD is not set -++# CONFIG_USB_BERRY_CHARGE is not set -++# CONFIG_USB_LED is not set -++# CONFIG_USB_CYPRESS_CY7C63 is not set -++# CONFIG_USB_CYTHERM is not set -++# CONFIG_USB_PHIDGET is not set -++# CONFIG_USB_IDMOUSE is not set -++# CONFIG_USB_FTDI_ELAN is not set -++# CONFIG_USB_APPLEDISPLAY is not set -++# CONFIG_USB_LD is not set -++# CONFIG_USB_TRANCEVIBRATOR is not set -++# CONFIG_USB_IOWARRIOR is not set -++ -++# -++# USB DSL modem support -++# -++ -++# -++# USB Gadget Support -++# -++# CONFIG_USB_GADGET is not set -++CONFIG_MMC=y -++# CONFIG_MMC_DEBUG is not set -++# CONFIG_MMC_UNSAFE_RESUME is not set -++ -++# -++# MMC/SD Card Drivers -++# -++CONFIG_MMC_BLOCK=y -++CONFIG_MMC_BLOCK_BOUNCE=y -++# CONFIG_SDIO_UART is not set -++ -++# -++# MMC/SD Host Controller Drivers -++# -++CONFIG_MSC0_JZ4750=y -++# CONFIG_JZ4750_MSC0_BUS_1 is not set -++CONFIG_JZ4750_MSC0_BUS_4=y -++# CONFIG_JZ4750_MSC0_BUS_8 is not set -++# CONFIG_MSC1_JZ4750 is not set -++# CONFIG_JZ4750_BOOT_FROM_MSC0 is not set -++# CONFIG_NEW_LEDS is not set -++CONFIG_RTC_LIB=y -++# CONFIG_RTC_CLASS is not set -++ -++# -++# Userspace I/O -++# -++# CONFIG_UIO is not set -++ -++# -++# File systems -++# -++CONFIG_EXT2_FS=y -++CONFIG_EXT2_FS_XATTR=y -++# CONFIG_EXT2_FS_POSIX_ACL is not set -++# CONFIG_EXT2_FS_SECURITY is not set -++# CONFIG_EXT2_FS_XIP is not set -++# CONFIG_EXT3_FS is not set -++# CONFIG_EXT4DEV_FS is not set -++CONFIG_FS_MBCACHE=y -++# CONFIG_REISERFS_FS is not set -++# CONFIG_JFS_FS is not set -++CONFIG_FS_POSIX_ACL=y -++# CONFIG_XFS_FS is not set -++# CONFIG_GFS2_FS is not set -++# CONFIG_OCFS2_FS is not set -++CONFIG_MINIX_FS=y -++# CONFIG_ROMFS_FS is not set -++CONFIG_INOTIFY=y -++CONFIG_INOTIFY_USER=y -++# CONFIG_QUOTA is not set -++CONFIG_DNOTIFY=y -++# CONFIG_AUTOFS_FS is not set -++# CONFIG_AUTOFS4_FS is not set -++# CONFIG_FUSE_FS is not set -++ -++# -++# CD-ROM/DVD Filesystems -++# -++# CONFIG_ISO9660_FS is not set -++# CONFIG_UDF_FS is not set -++ -++# -++# DOS/FAT/NT Filesystems -++# -++CONFIG_FAT_FS=y -++CONFIG_MSDOS_FS=y -++CONFIG_VFAT_FS=y -++CONFIG_FAT_DEFAULT_CODEPAGE=437 -++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -++# CONFIG_NTFS_FS is not set -++ -++# -++# Pseudo filesystems -++# -++CONFIG_PROC_FS=y -++CONFIG_PROC_KCORE=y -++CONFIG_PROC_SYSCTL=y -++CONFIG_SYSFS=y -++CONFIG_TMPFS=y -++# CONFIG_TMPFS_POSIX_ACL is not set -++# CONFIG_HUGETLB_PAGE is not set -++# CONFIG_CONFIGFS_FS is not set -++ -++# -++# Miscellaneous filesystems -++# -++# CONFIG_ADFS_FS is not set -++# CONFIG_AFFS_FS is not set -++# CONFIG_HFS_FS is not set -++# CONFIG_HFSPLUS_FS is not set -++# CONFIG_BEFS_FS is not set -++# CONFIG_BFS_FS is not set -++# CONFIG_EFS_FS is not set -++# CONFIG_JFFS2_FS is not set -++# CONFIG_CRAMFS is not set -++# CONFIG_VXFS_FS is not set -++# CONFIG_HPFS_FS is not set -++# CONFIG_QNX4FS_FS is not set -++# CONFIG_SYSV_FS is not set -++# CONFIG_UFS_FS is not set -++CONFIG_NETWORK_FILESYSTEMS=y -++CONFIG_NFS_FS=y -++CONFIG_NFS_V3=y -++CONFIG_NFS_V3_ACL=y -++CONFIG_NFS_V4=y -++CONFIG_NFS_DIRECTIO=y -++# CONFIG_NFSD is not set -++CONFIG_ROOT_NFS=y -++CONFIG_LOCKD=y -++CONFIG_LOCKD_V4=y -++CONFIG_NFS_ACL_SUPPORT=y -++CONFIG_NFS_COMMON=y -++CONFIG_SUNRPC=y -++CONFIG_SUNRPC_GSS=y -++# CONFIG_SUNRPC_BIND34 is not set -++CONFIG_RPCSEC_GSS_KRB5=y -++# CONFIG_RPCSEC_GSS_SPKM3 is not set -++# CONFIG_SMB_FS is not set -++# CONFIG_CIFS is not set -++# CONFIG_NCP_FS is not set -++# CONFIG_CODA_FS is not set -++# CONFIG_AFS_FS is not set -++ -++# -++# Partition Types -++# -++CONFIG_PARTITION_ADVANCED=y -++# CONFIG_ACORN_PARTITION is not set -++# CONFIG_OSF_PARTITION is not set -++# CONFIG_AMIGA_PARTITION is not set -++# CONFIG_ATARI_PARTITION is not set -++# CONFIG_MAC_PARTITION is not set -++CONFIG_MSDOS_PARTITION=y -++# CONFIG_BSD_DISKLABEL is not set -++# CONFIG_MINIX_SUBPARTITION is not set -++# CONFIG_SOLARIS_X86_PARTITION is not set -++# CONFIG_UNIXWARE_DISKLABEL is not set -++# CONFIG_LDM_PARTITION is not set -++# CONFIG_SGI_PARTITION is not set -++# CONFIG_ULTRIX_PARTITION is not set -++# CONFIG_SUN_PARTITION is not set -++# CONFIG_KARMA_PARTITION is not set -++# CONFIG_EFI_PARTITION is not set -++# CONFIG_SYSV68_PARTITION is not set -++CONFIG_NLS=y -++CONFIG_NLS_DEFAULT="iso8859-1" -++CONFIG_NLS_CODEPAGE_437=y -++# CONFIG_NLS_CODEPAGE_737 is not set -++# CONFIG_NLS_CODEPAGE_775 is not set -++# CONFIG_NLS_CODEPAGE_850 is not set -++# CONFIG_NLS_CODEPAGE_852 is not set -++# CONFIG_NLS_CODEPAGE_855 is not set -++# CONFIG_NLS_CODEPAGE_857 is not set -++# CONFIG_NLS_CODEPAGE_860 is not set -++# CONFIG_NLS_CODEPAGE_861 is not set -++# CONFIG_NLS_CODEPAGE_862 is not set -++# CONFIG_NLS_CODEPAGE_863 is not set -++# CONFIG_NLS_CODEPAGE_864 is not set -++# CONFIG_NLS_CODEPAGE_865 is not set -++# CONFIG_NLS_CODEPAGE_866 is not set -++# CONFIG_NLS_CODEPAGE_869 is not set -++CONFIG_NLS_CODEPAGE_936=y -++# CONFIG_NLS_CODEPAGE_950 is not set -++# CONFIG_NLS_CODEPAGE_932 is not set -++# CONFIG_NLS_CODEPAGE_949 is not set -++# CONFIG_NLS_CODEPAGE_874 is not set -++# CONFIG_NLS_ISO8859_8 is not set -++# CONFIG_NLS_CODEPAGE_1250 is not set -++# CONFIG_NLS_CODEPAGE_1251 is not set -++CONFIG_NLS_ASCII=y -++CONFIG_NLS_ISO8859_1=y -++# CONFIG_NLS_ISO8859_2 is not set -++# CONFIG_NLS_ISO8859_3 is not set -++# CONFIG_NLS_ISO8859_4 is not set -++# CONFIG_NLS_ISO8859_5 is not set -++# CONFIG_NLS_ISO8859_6 is not set -++# CONFIG_NLS_ISO8859_7 is not set -++# CONFIG_NLS_ISO8859_9 is not set -++# CONFIG_NLS_ISO8859_13 is not set -++# CONFIG_NLS_ISO8859_14 is not set -++# CONFIG_NLS_ISO8859_15 is not set -++# CONFIG_NLS_KOI8_R is not set -++# CONFIG_NLS_KOI8_U is not set -++# CONFIG_NLS_UTF8 is not set -++# CONFIG_DLM is not set -++ -++# -++# Yaffs2 Filesystems -++# -++CONFIG_YAFFS_FS=y -++CONFIG_YAFFS_YAFFS1=y -++# CONFIG_YAFFS_DOES_ECC is not set -++CONFIG_YAFFS_YAFFS2=y -++CONFIG_YAFFS_AUTO_YAFFS2=y -++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set -++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set -++CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK=y -++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y -++CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10 -++CONFIG_INSTRUMENTATION=y -++# CONFIG_PROFILING is not set -++# CONFIG_MARKERS is not set -++ -++# -++# Kernel hacking -++# -++CONFIG_TRACE_IRQFLAGS_SUPPORT=y -++# CONFIG_PRINTK_TIME is not set -++CONFIG_ENABLE_WARN_DEPRECATED=y -++CONFIG_ENABLE_MUST_CHECK=y -++CONFIG_MAGIC_SYSRQ=y -++# CONFIG_UNUSED_SYMBOLS is not set -++# CONFIG_DEBUG_FS is not set -++# CONFIG_HEADERS_CHECK is not set -++# CONFIG_DEBUG_KERNEL is not set -++# CONFIG_SAMPLES is not set -++CONFIG_CMDLINE="" -++ -++# -++# Security options -++# -++# CONFIG_KEYS is not set -++# CONFIG_SECURITY is not set -++# CONFIG_SECURITY_FILE_CAPABILITIES is not set -++CONFIG_CRYPTO=y -++CONFIG_CRYPTO_ALGAPI=y -++CONFIG_CRYPTO_BLKCIPHER=y -++CONFIG_CRYPTO_MANAGER=y -++# CONFIG_CRYPTO_HMAC is not set -++# CONFIG_CRYPTO_XCBC is not set -++# CONFIG_CRYPTO_NULL is not set -++# CONFIG_CRYPTO_MD4 is not set -++CONFIG_CRYPTO_MD5=y -++# CONFIG_CRYPTO_SHA1 is not set -++# CONFIG_CRYPTO_SHA256 is not set -++# CONFIG_CRYPTO_SHA512 is not set -++# CONFIG_CRYPTO_WP512 is not set -++# CONFIG_CRYPTO_TGR192 is not set -++# CONFIG_CRYPTO_GF128MUL is not set -++# CONFIG_CRYPTO_ECB is not set -++CONFIG_CRYPTO_CBC=y -++# CONFIG_CRYPTO_PCBC is not set -++# CONFIG_CRYPTO_LRW is not set -++# CONFIG_CRYPTO_XTS is not set -++# CONFIG_CRYPTO_CRYPTD is not set -++CONFIG_CRYPTO_DES=y -++# CONFIG_CRYPTO_FCRYPT is not set -++# CONFIG_CRYPTO_BLOWFISH is not set -++# CONFIG_CRYPTO_TWOFISH is not set -++# CONFIG_CRYPTO_SERPENT is not set -++# CONFIG_CRYPTO_AES is not set -++# CONFIG_CRYPTO_CAST5 is not set -++# CONFIG_CRYPTO_CAST6 is not set -++# CONFIG_CRYPTO_TEA is not set -++# CONFIG_CRYPTO_ARC4 is not set -++# CONFIG_CRYPTO_KHAZAD is not set -++# CONFIG_CRYPTO_ANUBIS is not set -++# CONFIG_CRYPTO_SEED is not set -++# CONFIG_CRYPTO_DEFLATE is not set -++# CONFIG_CRYPTO_MICHAEL_MIC is not set -++# CONFIG_CRYPTO_CRC32C is not set -++# CONFIG_CRYPTO_CAMELLIA is not set -++# CONFIG_CRYPTO_TEST is not set -++# CONFIG_CRYPTO_AUTHENC is not set -++# CONFIG_CRYPTO_LZO is not set -++CONFIG_CRYPTO_HW=y -++ -++# -++# Library routines -++# -++CONFIG_BITREVERSE=y -++# CONFIG_CRC_CCITT is not set -++# CONFIG_CRC16 is not set -++# CONFIG_CRC_ITU_T is not set -++CONFIG_CRC32=y -++# CONFIG_CRC7 is not set -++# CONFIG_LIBCRC32C is not set -++CONFIG_PLIST=y -++CONFIG_HAS_IOMEM=y -++CONFIG_HAS_IOPORT=y -++CONFIG_HAS_DMA=y -+diff -urN linux-2.6.24.7.old/arch/mips/configs/dipper_defconfig linux-2.6.24.7/arch/mips/configs/dipper_defconfig -+--- linux-2.6.24.7.old/arch/mips/configs/dipper_defconfig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/configs/dipper_defconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1281 @@ -++# -++# Automatically generated make config: don't edit -++# Linux kernel version: 2.6.24.3 -++# Thu Jun 12 13:55:45 2008 -++# -++CONFIG_MIPS=y -++ -++# -++# Machine selection -++# -++# CONFIG_JZ4730_PMP is not set -++# CONFIG_JZ4740_PAVO is not set -++# CONFIG_JZ4740_LEO is not set -++# CONFIG_JZ4740_LYRA is not set -++CONFIG_JZ4725_DIPPER=y -++# CONFIG_JZ4720_VIRGO is not set -++# CONFIG_JZ4750_FUWA is not set -++# CONFIG_MACH_ALCHEMY is not set -++# CONFIG_BASLER_EXCITE is not set -++# CONFIG_BCM47XX is not set -++# CONFIG_MIPS_COBALT is not set -++# CONFIG_MACH_DECSTATION is not set -++# CONFIG_MACH_JAZZ is not set -++# CONFIG_LASAT is not set -++# CONFIG_LEMOTE_FULONG is not set -++# CONFIG_MIPS_ATLAS is not set -++# CONFIG_MIPS_MALTA is not set -++# CONFIG_MIPS_SEAD is not set -++# CONFIG_MIPS_SIM is not set -++# CONFIG_MARKEINS is not set -++# CONFIG_MACH_VR41XX is not set -++# CONFIG_PNX8550_JBS is not set -++# CONFIG_PNX8550_STB810 is not set -++# CONFIG_PMC_MSP is not set -++# CONFIG_PMC_YOSEMITE is not set -++# CONFIG_QEMU is not set -++# CONFIG_SGI_IP22 is not set -++# CONFIG_SGI_IP27 is not set -++# CONFIG_SGI_IP32 is not set -++# CONFIG_SIBYTE_CRHINE is not set -++# CONFIG_SIBYTE_CARMEL is not set -++# CONFIG_SIBYTE_CRHONE is not set -++# CONFIG_SIBYTE_RHONE is not set -++# CONFIG_SIBYTE_SWARM is not set -++# CONFIG_SIBYTE_LITTLESUR is not set -++# CONFIG_SIBYTE_SENTOSA is not set -++# CONFIG_SIBYTE_PTSWARM is not set -++# CONFIG_SIBYTE_BIGSUR is not set -++# CONFIG_SNI_RM is not set -++# CONFIG_TOSHIBA_JMR3927 is not set -++# CONFIG_TOSHIBA_RBTX4927 is not set -++# CONFIG_TOSHIBA_RBTX4938 is not set -++# CONFIG_WR_PPMC is not set -++CONFIG_SOC_JZ4740=y -++CONFIG_SOC_JZ4725=y -++CONFIG_JZSOC=y -++CONFIG_JZRISC=y -++CONFIG_RWSEM_GENERIC_SPINLOCK=y -++# CONFIG_ARCH_HAS_ILOG2_U32 is not set -++# CONFIG_ARCH_HAS_ILOG2_U64 is not set -++CONFIG_ARCH_SUPPORTS_OPROFILE=y -++CONFIG_GENERIC_FIND_NEXT_BIT=y -++CONFIG_GENERIC_HWEIGHT=y -++CONFIG_GENERIC_CALIBRATE_DELAY=y -++CONFIG_GENERIC_CLOCKEVENTS=y -++CONFIG_GENERIC_TIME=y -++CONFIG_GENERIC_CMOS_UPDATE=y -++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -++# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set -++CONFIG_DMA_NONCOHERENT=y -++CONFIG_DMA_NEED_PCI_MAP_STATE=y -++# CONFIG_HOTPLUG_CPU is not set -++# CONFIG_NO_IOPORT is not set -++# CONFIG_CPU_BIG_ENDIAN is not set -++CONFIG_CPU_LITTLE_ENDIAN=y -++CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -++CONFIG_MIPS_L1_CACHE_SHIFT=5 -++ -++# -++# CPU selection -++# -++# CONFIG_CPU_LOONGSON2 is not set -++CONFIG_CPU_MIPS32_R1=y -++# CONFIG_CPU_MIPS32_R2 is not set -++# CONFIG_CPU_MIPS64_R1 is not set -++# CONFIG_CPU_MIPS64_R2 is not set -++# CONFIG_CPU_R3000 is not set -++# CONFIG_CPU_TX39XX is not set -++# CONFIG_CPU_VR41XX is not set -++# CONFIG_CPU_R4300 is not set -++# CONFIG_CPU_R4X00 is not set -++# CONFIG_CPU_TX49XX is not set -++# CONFIG_CPU_R5000 is not set -++# CONFIG_CPU_R5432 is not set -++# CONFIG_CPU_R6000 is not set -++# CONFIG_CPU_NEVADA is not set -++# CONFIG_CPU_R8000 is not set -++# CONFIG_CPU_R10000 is not set -++# CONFIG_CPU_RM7000 is not set -++# CONFIG_CPU_RM9000 is not set -++# CONFIG_CPU_SB1 is not set -++CONFIG_SYS_HAS_CPU_MIPS32_R1=y -++CONFIG_CPU_MIPS32=y -++CONFIG_CPU_MIPSR1=y -++CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -++CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -++ -++# -++# Kernel type -++# -++CONFIG_32BIT=y -++# CONFIG_64BIT is not set -++CONFIG_PAGE_SIZE_4KB=y -++# CONFIG_PAGE_SIZE_8KB is not set -++# CONFIG_PAGE_SIZE_16KB is not set -++# CONFIG_PAGE_SIZE_64KB is not set -++CONFIG_CPU_HAS_PREFETCH=y -++CONFIG_MIPS_MT_DISABLED=y -++# CONFIG_MIPS_MT_SMP is not set -++# CONFIG_MIPS_MT_SMTC is not set -++CONFIG_CPU_HAS_LLSC=y -++CONFIG_CPU_HAS_SYNC=y -++CONFIG_GENERIC_HARDIRQS=y -++CONFIG_GENERIC_IRQ_PROBE=y -++CONFIG_CPU_SUPPORTS_HIGHMEM=y -++CONFIG_ARCH_FLATMEM_ENABLE=y -++CONFIG_ARCH_POPULATES_NODE_MAP=y -++CONFIG_SELECT_MEMORY_MODEL=y -++CONFIG_FLATMEM_MANUAL=y -++# CONFIG_DISCONTIGMEM_MANUAL is not set -++# CONFIG_SPARSEMEM_MANUAL is not set -++CONFIG_FLATMEM=y -++CONFIG_FLAT_NODE_MEM_MAP=y -++# CONFIG_SPARSEMEM_STATIC is not set -++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -++CONFIG_SPLIT_PTLOCK_CPUS=4 -++# CONFIG_RESOURCES_64BIT is not set -++CONFIG_ZONE_DMA_FLAG=0 -++CONFIG_VIRT_TO_BUS=y -++# CONFIG_TICK_ONESHOT is not set -++# CONFIG_NO_HZ is not set -++# CONFIG_HIGH_RES_TIMERS is not set -++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -++# CONFIG_HZ_48 is not set -++CONFIG_HZ_100=y -++# CONFIG_HZ_128 is not set -++# CONFIG_HZ_250 is not set -++# CONFIG_HZ_256 is not set -++# CONFIG_HZ_1000 is not set -++# CONFIG_HZ_1024 is not set -++CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -++CONFIG_HZ=100 -++# CONFIG_PREEMPT_NONE is not set -++# CONFIG_PREEMPT_VOLUNTARY is not set -++CONFIG_PREEMPT=y -++CONFIG_PREEMPT_BKL=y -++# CONFIG_KEXEC is not set -++CONFIG_SECCOMP=y -++CONFIG_LOCKDEP_SUPPORT=y -++CONFIG_STACKTRACE_SUPPORT=y -++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -++ -++# -++# General setup -++# -++CONFIG_EXPERIMENTAL=y -++CONFIG_BROKEN_ON_SMP=y -++CONFIG_LOCK_KERNEL=y -++CONFIG_INIT_ENV_ARG_LIMIT=32 -++CONFIG_LOCALVERSION="" -++CONFIG_LOCALVERSION_AUTO=y -++CONFIG_SWAP=y -++CONFIG_SYSVIPC=y -++CONFIG_SYSVIPC_SYSCTL=y -++# CONFIG_POSIX_MQUEUE is not set -++# CONFIG_BSD_PROCESS_ACCT is not set -++# CONFIG_TASKSTATS is not set -++# CONFIG_USER_NS is not set -++# CONFIG_PID_NS is not set -++# CONFIG_AUDIT is not set -++# CONFIG_IKCONFIG is not set -++CONFIG_LOG_BUF_SHIFT=14 -++# CONFIG_CGROUPS is not set -++CONFIG_FAIR_GROUP_SCHED=y -++CONFIG_FAIR_USER_SCHED=y -++# CONFIG_FAIR_CGROUP_SCHED is not set -++CONFIG_SYSFS_DEPRECATED=y -++CONFIG_RELAY=y -++# CONFIG_BLK_DEV_INITRD is not set -++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -++CONFIG_SYSCTL=y -++CONFIG_EMBEDDED=y -++CONFIG_SYSCTL_SYSCALL=y -++CONFIG_KALLSYMS=y -++# CONFIG_KALLSYMS_EXTRA_PASS is not set -++CONFIG_HOTPLUG=y -++CONFIG_PRINTK=y -++CONFIG_BUG=y -++CONFIG_ELF_CORE=y -++CONFIG_BASE_FULL=y -++CONFIG_FUTEX=y -++CONFIG_ANON_INODES=y -++CONFIG_EPOLL=y -++CONFIG_SIGNALFD=y -++CONFIG_EVENTFD=y -++CONFIG_SHMEM=y -++CONFIG_VM_EVENT_COUNTERS=y -++CONFIG_SLAB=y -++# CONFIG_SLUB is not set -++# CONFIG_SLOB is not set -++CONFIG_SLABINFO=y -++CONFIG_RT_MUTEXES=y -++# CONFIG_TINY_SHMEM is not set -++CONFIG_BASE_SMALL=0 -++CONFIG_MODULES=y -++CONFIG_MODULE_UNLOAD=y -++# CONFIG_MODULE_FORCE_UNLOAD is not set -++CONFIG_MODVERSIONS=y -++CONFIG_MODULE_SRCVERSION_ALL=y -++CONFIG_KMOD=y -++CONFIG_BLOCK=y -++# CONFIG_LBD is not set -++# CONFIG_BLK_DEV_IO_TRACE is not set -++# CONFIG_LSF is not set -++# CONFIG_BLK_DEV_BSG is not set -++ -++# -++# IO Schedulers -++# -++CONFIG_IOSCHED_NOOP=y -++CONFIG_IOSCHED_AS=y -++CONFIG_IOSCHED_DEADLINE=y -++CONFIG_IOSCHED_CFQ=y -++CONFIG_DEFAULT_AS=y -++# CONFIG_DEFAULT_DEADLINE is not set -++# CONFIG_DEFAULT_CFQ is not set -++# CONFIG_DEFAULT_NOOP is not set -++CONFIG_DEFAULT_IOSCHED="anticipatory" -++ -++# -++# Bus options (PCI, PCMCIA, EISA, ISA, TC) -++# -++# CONFIG_ARCH_SUPPORTS_MSI is not set -++CONFIG_MMU=y -++# CONFIG_PCCARD is not set -++ -++# -++# Executable file formats -++# -++CONFIG_BINFMT_ELF=y -++# CONFIG_BINFMT_MISC is not set -++CONFIG_TRAD_SIGNALS=y -++ -++# -++# CPU Frequency scaling -++# -++CONFIG_CPU_FREQ_JZ=y -++CONFIG_CPU_FREQ=y -++CONFIG_CPU_FREQ_TABLE=y -++# CONFIG_CPU_FREQ_DEBUG is not set -++CONFIG_CPU_FREQ_STAT=y -++# CONFIG_CPU_FREQ_STAT_DETAILS is not set -++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -++CONFIG_CPU_FREQ_GOV_USERSPACE=y -++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set -++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -++ -++# -++# Power management options -++# -++CONFIG_PM=y -++CONFIG_PM_LEGACY=y -++# CONFIG_PM_DEBUG is not set -++CONFIG_SUSPEND_UP_POSSIBLE=y -++# CONFIG_SUSPEND is not set -++ -++# -++# Networking -++# -++CONFIG_NET=y -++ -++# -++# Networking options -++# -++CONFIG_PACKET=y -++# CONFIG_PACKET_MMAP is not set -++CONFIG_UNIX=y -++# CONFIG_NET_KEY is not set -++CONFIG_INET=y -++# CONFIG_IP_MULTICAST is not set -++# CONFIG_IP_ADVANCED_ROUTER is not set -++CONFIG_IP_FIB_HASH=y -++CONFIG_IP_PNP=y -++CONFIG_IP_PNP_DHCP=y -++CONFIG_IP_PNP_BOOTP=y -++# CONFIG_IP_PNP_RARP is not set -++# CONFIG_NET_IPIP is not set -++# CONFIG_NET_IPGRE is not set -++# CONFIG_ARPD is not set -++# CONFIG_SYN_COOKIES is not set -++# CONFIG_INET_AH is not set -++# CONFIG_INET_ESP is not set -++# CONFIG_INET_IPCOMP is not set -++# CONFIG_INET_XFRM_TUNNEL is not set -++# CONFIG_INET_TUNNEL is not set -++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -++# CONFIG_INET_XFRM_MODE_TUNNEL is not set -++# CONFIG_INET_XFRM_MODE_BEET is not set -++# CONFIG_INET_LRO is not set -++# CONFIG_INET_DIAG is not set -++# CONFIG_TCP_CONG_ADVANCED is not set -++CONFIG_TCP_CONG_CUBIC=y -++CONFIG_DEFAULT_TCP_CONG="cubic" -++# CONFIG_TCP_MD5SIG is not set -++# CONFIG_IPV6 is not set -++# CONFIG_INET6_XFRM_TUNNEL is not set -++# CONFIG_INET6_TUNNEL is not set -++# CONFIG_NETWORK_SECMARK is not set -++# CONFIG_NETFILTER is not set -++# CONFIG_IP_DCCP is not set -++# CONFIG_IP_SCTP is not set -++# CONFIG_TIPC is not set -++# CONFIG_ATM is not set -++# CONFIG_BRIDGE is not set -++# CONFIG_VLAN_8021Q is not set -++# CONFIG_DECNET is not set -++# CONFIG_LLC2 is not set -++# CONFIG_IPX is not set -++# CONFIG_ATALK is not set -++# CONFIG_X25 is not set -++# CONFIG_LAPB is not set -++# CONFIG_ECONET is not set -++# CONFIG_WAN_ROUTER is not set -++# CONFIG_NET_SCHED is not set -++ -++# -++# Network testing -++# -++# CONFIG_NET_PKTGEN is not set -++# CONFIG_HAMRADIO is not set -++# CONFIG_IRDA is not set -++# CONFIG_BT is not set -++# CONFIG_AF_RXRPC is not set -++ -++# -++# Wireless -++# -++# CONFIG_CFG80211 is not set -++CONFIG_WIRELESS_EXT=y -++# CONFIG_MAC80211 is not set -++# CONFIG_IEEE80211 is not set -++# CONFIG_RFKILL is not set -++# CONFIG_NET_9P is not set -++ -++# -++# Device Drivers -++# -++ -++# -++# Generic Driver Options -++# -++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -++CONFIG_STANDALONE=y -++CONFIG_PREVENT_FIRMWARE_BUILD=y -++# CONFIG_FW_LOADER is not set -++# CONFIG_SYS_HYPERVISOR is not set -++# CONFIG_CONNECTOR is not set -++CONFIG_MTD=y -++# CONFIG_MTD_DEBUG is not set -++# CONFIG_MTD_CONCAT is not set -++CONFIG_MTD_PARTITIONS=y -++# CONFIG_MTD_REDBOOT_PARTS is not set -++# CONFIG_MTD_CMDLINE_PARTS is not set -++ -++# -++# User Modules And Translation Layers -++# -++CONFIG_MTD_CHAR=y -++CONFIG_MTD_BLKDEVS=y -++CONFIG_MTD_BLOCK=y -++# CONFIG_FTL is not set -++# CONFIG_NFTL is not set -++# CONFIG_INFTL is not set -++# CONFIG_RFD_FTL is not set -++# CONFIG_SSFDC is not set -++# CONFIG_MTD_OOPS is not set -++ -++# -++# RAM/ROM/Flash chip drivers -++# -++# CONFIG_MTD_CFI is not set -++# CONFIG_MTD_JEDECPROBE is not set -++CONFIG_MTD_MAP_BANK_WIDTH_1=y -++CONFIG_MTD_MAP_BANK_WIDTH_2=y -++CONFIG_MTD_MAP_BANK_WIDTH_4=y -++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -++CONFIG_MTD_CFI_I1=y -++CONFIG_MTD_CFI_I2=y -++# CONFIG_MTD_CFI_I4 is not set -++# CONFIG_MTD_CFI_I8 is not set -++# CONFIG_MTD_RAM is not set -++# CONFIG_MTD_ROM is not set -++# CONFIG_MTD_ABSENT is not set -++ -++# -++# Mapping drivers for chip access -++# -++# CONFIG_MTD_COMPLEX_MAPPINGS is not set -++# CONFIG_MTD_PLATRAM is not set -++ -++# -++# Self-contained MTD device drivers -++# -++# CONFIG_MTD_SLRAM is not set -++# CONFIG_MTD_PHRAM is not set -++# CONFIG_MTD_MTDRAM is not set -++# CONFIG_MTD_BLOCK2MTD is not set -++ -++# -++# Disk-On-Chip Device Drivers -++# -++# CONFIG_MTD_DOC2000 is not set -++# CONFIG_MTD_DOC2001 is not set -++# CONFIG_MTD_DOC2001PLUS is not set -++CONFIG_MTD_NAND=y -++# CONFIG_MTD_NAND_VERIFY_WRITE is not set -++# CONFIG_MTD_NAND_ECC_SMC is not set -++# CONFIG_MTD_NAND_MUSEUM_IDS is not set -++CONFIG_MTD_NAND_IDS=y -++# CONFIG_MTD_NAND_DISKONCHIP is not set -++# CONFIG_MTD_NAND_NANDSIM is not set -++# CONFIG_MTD_NAND_PLATFORM is not set -++# CONFIG_MTD_ALAUDA is not set -++CONFIG_MTD_NAND_JZ4740=y -++# CONFIG_MTD_HW_HM_ECC is not set -++# CONFIG_MTD_SW_HM_ECC is not set -++CONFIG_MTD_HW_RS_ECC=y -++# CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE is not set -++CONFIG_MTD_OOB_COPIES=3 -++CONFIG_MTD_BADBLOCK_FLAG_PAGE=0 -++# CONFIG_MTD_ONENAND is not set -++ -++# -++# UBI - Unsorted block images -++# -++CONFIG_MTD_UBI=m -++CONFIG_MTD_UBI_WL_THRESHOLD=256 -++CONFIG_MTD_UBI_BEB_RESERVE=1 -++# CONFIG_MTD_UBI_GLUEBI is not set -++ -++# -++# UBI debugging options -++# -++# CONFIG_MTD_UBI_DEBUG is not set -++CONFIG_MTD_UBI_BLKDEVS=m -++CONFIG_MTD_UBI_BLOCK=m -++# CONFIG_PARPORT is not set -++CONFIG_PNP=y -++# CONFIG_PNP_DEBUG is not set -++ -++# -++# Protocols -++# -++# CONFIG_PNPACPI is not set -++CONFIG_BLK_DEV=y -++# CONFIG_BLK_DEV_COW_COMMON is not set -++CONFIG_BLK_DEV_LOOP=y -++# CONFIG_BLK_DEV_CRYPTOLOOP is not set -++# CONFIG_BLK_DEV_NBD is not set -++# CONFIG_BLK_DEV_UB is not set -++CONFIG_BLK_DEV_RAM=y -++CONFIG_BLK_DEV_RAM_COUNT=2 -++CONFIG_BLK_DEV_RAM_SIZE=4096 -++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -++# CONFIG_CDROM_PKTCDVD is not set -++# CONFIG_ATA_OVER_ETH is not set -++CONFIG_MISC_DEVICES=y -++# CONFIG_EEPROM_93CX6 is not set -++# CONFIG_IDE is not set -++ -++# -++# SCSI device support -++# -++# CONFIG_RAID_ATTRS is not set -++CONFIG_SCSI=y -++CONFIG_SCSI_DMA=y -++# CONFIG_SCSI_TGT is not set -++# CONFIG_SCSI_NETLINK is not set -++CONFIG_SCSI_PROC_FS=y -++ -++# -++# SCSI support type (disk, tape, CD-ROM) -++# -++CONFIG_BLK_DEV_SD=y -++# CONFIG_CHR_DEV_ST is not set -++# CONFIG_CHR_DEV_OSST is not set -++# CONFIG_BLK_DEV_SR is not set -++# CONFIG_CHR_DEV_SG is not set -++# CONFIG_CHR_DEV_SCH is not set -++ -++# -++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -++# -++# CONFIG_SCSI_MULTI_LUN is not set -++# CONFIG_SCSI_CONSTANTS is not set -++# CONFIG_SCSI_LOGGING is not set -++# CONFIG_SCSI_SCAN_ASYNC is not set -++CONFIG_SCSI_WAIT_SCAN=m -++ -++# -++# SCSI Transports -++# -++# CONFIG_SCSI_SPI_ATTRS is not set -++# CONFIG_SCSI_FC_ATTRS is not set -++# CONFIG_SCSI_ISCSI_ATTRS is not set -++# CONFIG_SCSI_SAS_LIBSAS is not set -++# CONFIG_SCSI_SRP_ATTRS is not set -++CONFIG_SCSI_LOWLEVEL=y -++# CONFIG_ISCSI_TCP is not set -++# CONFIG_SCSI_DEBUG is not set -++# CONFIG_ATA is not set -++# CONFIG_MD is not set -++CONFIG_NETDEVICES=y -++# CONFIG_NETDEVICES_MULTIQUEUE is not set -++# CONFIG_DUMMY is not set -++# CONFIG_BONDING is not set -++# CONFIG_MACVLAN is not set -++# CONFIG_EQUALIZER is not set -++# CONFIG_TUN is not set -++# CONFIG_VETH is not set -++# CONFIG_NET_SB1000 is not set -++CONFIG_PHYLIB=y -++ -++# -++# MII PHY device drivers -++# -++# CONFIG_MARVELL_PHY is not set -++# CONFIG_DAVICOM_PHY is not set -++# CONFIG_QSEMI_PHY is not set -++# CONFIG_LXT_PHY is not set -++# CONFIG_CICADA_PHY is not set -++# CONFIG_VITESSE_PHY is not set -++# CONFIG_SMSC_PHY is not set -++# CONFIG_BROADCOM_PHY is not set -++# CONFIG_ICPLUS_PHY is not set -++# CONFIG_FIXED_PHY is not set -++# CONFIG_MDIO_BITBANG is not set -++CONFIG_NET_ETHERNET=y -++CONFIG_MII=y -++CONFIG_JZCS8900=y -++# CONFIG_AX88796 is not set -++# CONFIG_DM9000 is not set -++# CONFIG_IBM_NEW_EMAC_ZMII is not set -++# CONFIG_IBM_NEW_EMAC_RGMII is not set -++# CONFIG_IBM_NEW_EMAC_TAH is not set -++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -++# CONFIG_B44 is not set -++# CONFIG_NETDEV_1000 is not set -++# CONFIG_NETDEV_10000 is not set -++ -++# -++# Wireless LAN -++# -++# CONFIG_WLAN_PRE80211 is not set -++# CONFIG_WLAN_80211 is not set -++ -++# -++# USB Network Adapters -++# -++# CONFIG_USB_CATC is not set -++# CONFIG_USB_KAWETH is not set -++# CONFIG_USB_PEGASUS is not set -++# CONFIG_USB_RTL8150 is not set -++# CONFIG_USB_USBNET is not set -++# CONFIG_WAN is not set -++# CONFIG_PPP is not set -++# CONFIG_SLIP is not set -++# CONFIG_SHAPER is not set -++# CONFIG_NETCONSOLE is not set -++# CONFIG_NETPOLL is not set -++# CONFIG_NET_POLL_CONTROLLER is not set -++# CONFIG_ISDN is not set -++# CONFIG_PHONE is not set -++ -++# -++# Input device support -++# -++CONFIG_INPUT=y -++# CONFIG_INPUT_FF_MEMLESS is not set -++# CONFIG_INPUT_POLLDEV is not set -++ -++# -++# Userland interfaces -++# -++CONFIG_INPUT_MOUSEDEV=y -++CONFIG_INPUT_MOUSEDEV_PSAUX=y -++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -++# CONFIG_INPUT_JOYDEV is not set -++CONFIG_INPUT_EVDEV=y -++# CONFIG_INPUT_EVBUG is not set -++ -++# -++# Input Device Drivers -++# -++# CONFIG_INPUT_KEYBOARD is not set -++# CONFIG_INPUT_MOUSE is not set -++# CONFIG_INPUT_JOYSTICK is not set -++# CONFIG_INPUT_TABLET is not set -++# CONFIG_INPUT_TOUCHSCREEN is not set -++# CONFIG_INPUT_MISC is not set -++ -++# -++# Hardware I/O ports -++# -++CONFIG_SERIO=y -++# CONFIG_SERIO_I8042 is not set -++CONFIG_SERIO_SERPORT=y -++# CONFIG_SERIO_LIBPS2 is not set -++# CONFIG_SERIO_RAW is not set -++# CONFIG_GAMEPORT is not set -++ -++# -++# Character devices -++# -++CONFIG_VT=y -++CONFIG_VT_CONSOLE=y -++CONFIG_HW_CONSOLE=y -++CONFIG_VT_HW_CONSOLE_BINDING=y -++# CONFIG_SERIAL_NONSTANDARD is not set -++ -++# -++# Serial drivers -++# -++CONFIG_SERIAL_8250=y -++CONFIG_SERIAL_8250_CONSOLE=y -++CONFIG_SERIAL_8250_PNP=y -++CONFIG_SERIAL_8250_NR_UARTS=2 -++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 -++# CONFIG_SERIAL_8250_EXTENDED is not set -++ -++# -++# Non-8250 serial port support -++# -++CONFIG_SERIAL_CORE=y -++CONFIG_SERIAL_CORE_CONSOLE=y -++CONFIG_UNIX98_PTYS=y -++CONFIG_LEGACY_PTYS=y -++CONFIG_LEGACY_PTY_COUNT=2 -++# CONFIG_IPMI_HANDLER is not set -++# CONFIG_HW_RANDOM is not set -++# CONFIG_RTC is not set -++# CONFIG_RTC_PCF8563 is not set -++CONFIG_RTC_JZ=y -++# CONFIG_R3964 is not set -++# CONFIG_RAW_DRIVER is not set -++# CONFIG_TCG_TPM is not set -++ -++# -++# JZSOC char device support -++# -++CONFIG_JZCHAR=y -++# CONFIG_JZ_CIM is not set -++# CONFIG_JZ_TPANEL_ATA2508 is not set -++CONFIG_JZ_TPANEL=y -++CONFIG_JZ_SADC=y -++# CONFIG_JZ_TPANEL_AK4182 is not set -++# CONFIG_JZ_TPANEL_UCB1400 is not set -++# CONFIG_JZ_TPANEL_WM9712 is not set -++CONFIG_JZ_UDC_HOTPLUG=y -++CONFIG_JZ_POWEROFF=y -++# CONFIG_JZ_OW is not set -++# CONFIG_I2C is not set -++ -++# -++# SPI support -++# -++# CONFIG_SPI is not set -++# CONFIG_SPI_MASTER is not set -++# CONFIG_W1 is not set -++# CONFIG_POWER_SUPPLY is not set -++# CONFIG_HWMON is not set -++CONFIG_WATCHDOG=y -++# CONFIG_WATCHDOG_NOWAYOUT is not set -++ -++# -++# Watchdog Device Drivers -++# -++CONFIG_JZ_WDT=y -++# CONFIG_SOFT_WATCHDOG is not set -++ -++# -++# USB-based Watchdog Cards -++# -++# CONFIG_USBPCWATCHDOG is not set -++ -++# -++# Sonics Silicon Backplane -++# -++CONFIG_SSB_POSSIBLE=y -++# CONFIG_SSB is not set -++ -++# -++# Multifunction device drivers -++# -++# CONFIG_MFD_SM501 is not set -++ -++# -++# Multimedia devices -++# -++CONFIG_VIDEO_DEV=y -++CONFIG_VIDEO_V4L1=y -++CONFIG_VIDEO_V4L1_COMPAT=y -++CONFIG_VIDEO_V4L2=y -++CONFIG_VIDEO_CAPTURE_DRIVERS=y -++# CONFIG_VIDEO_ADV_DEBUG is not set -++CONFIG_VIDEO_HELPER_CHIPS_AUTO=y -++# CONFIG_VIDEO_VIVI is not set -++# CONFIG_VIDEO_CPIA is not set -++# CONFIG_VIDEO_CPIA2 is not set -++CONFIG_VIDEO_JZ_CIM=y -++CONFIG_VIDEO_JZ_SENSOR=y -++CONFIG_V4L_USB_DRIVERS=y -++# CONFIG_USB_VICAM is not set -++# CONFIG_USB_IBMCAM is not set -++# CONFIG_USB_KONICAWC is not set -++# CONFIG_USB_QUICKCAM_MESSENGER is not set -++# CONFIG_USB_ET61X251 is not set -++# CONFIG_USB_OV511 is not set -++# CONFIG_USB_SE401 is not set -++# CONFIG_USB_SN9C102 is not set -++# CONFIG_USB_STV680 is not set -++# CONFIG_USB_ZC0301 is not set -++# CONFIG_USB_PWC is not set -++# CONFIG_USB_ZR364XX is not set -++CONFIG_RADIO_ADAPTERS=y -++# CONFIG_USB_DSBR is not set -++# CONFIG_DVB_CORE is not set -++# CONFIG_DAB is not set -++ -++# -++# Graphics support -++# -++# CONFIG_VGASTATE is not set -++# CONFIG_VIDEO_OUTPUT_CONTROL is not set -++CONFIG_FB=y -++# CONFIG_FIRMWARE_EDID is not set -++# CONFIG_FB_DDC is not set -++CONFIG_FB_CFB_FILLRECT=y -++CONFIG_FB_CFB_COPYAREA=y -++CONFIG_FB_CFB_IMAGEBLIT=y -++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -++# CONFIG_FB_SYS_FILLRECT is not set -++# CONFIG_FB_SYS_COPYAREA is not set -++# CONFIG_FB_SYS_IMAGEBLIT is not set -++# CONFIG_FB_SYS_FOPS is not set -++CONFIG_FB_DEFERRED_IO=y -++# CONFIG_FB_SVGALIB is not set -++# CONFIG_FB_MACMODES is not set -++# CONFIG_FB_BACKLIGHT is not set -++# CONFIG_FB_MODE_HELPERS is not set -++# CONFIG_FB_TILEBLITTING is not set -++ -++# -++# Frame buffer hardware drivers -++# -++CONFIG_FB_JZSOC=y -++# CONFIG_FB_JZ4740_SLCD is not set -++CONFIG_FB_JZLCD_4730_4740=y -++CONFIG_JZLCD_FRAMEBUFFER_MAX=1 -++# CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT is not set -++# CONFIG_JZLCD_SHARP_LQ035Q7 is not set -++# CONFIG_JZLCD_SAMSUNG_LTS350Q1 is not set -++# CONFIG_JZLCD_SAMSUNG_LTV350QVF04 is not set -++# CONFIG_JZLCD_SAMSUNG_LTP400WQF01 is not set -++CONFIG_JZLCD_SAMSUNG_LTP400WQF02=y -++# CONFIG_JZLCD_AUO_A030FL01_V1 is not set -++# CONFIG_JZLCD_TRULY_TFTG320240DTSW is not set -++# CONFIG_JZLCD_TRULY_TFTG320240DTSW_SERIAL is not set -++# CONFIG_JZLCD_TRULY_TFTG240320UTSW_63W_E is not set -++# CONFIG_JZLCD_FOXCONN_PT035TN01 is not set -++# CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL is not set -++# CONFIG_JZLCD_TOSHIBA_LTM084P363 is not set -++# CONFIG_JZLCD_HYNIX_HT10X21 is not set -++# CONFIG_JZLCD_INNOLUX_AT080TN42 is not set -++# CONFIG_JZLCD_CSTN_800x600 is not set -++# CONFIG_JZLCD_CSTN_320x240 is not set -++# CONFIG_JZLCD_MSTN_480x320 is not set -++# CONFIG_JZLCD_MSTN_320x240 is not set -++# CONFIG_JZLCD_MSTN_240x128 is not set -++# CONFIG_FB_S1D13XXX is not set -++# CONFIG_FB_VIRTUAL is not set -++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set -++ -++# -++# Display device support -++# -++# CONFIG_DISPLAY_SUPPORT is not set -++ -++# -++# Console display driver support -++# -++# CONFIG_VGA_CONSOLE is not set -++CONFIG_DUMMY_CONSOLE=y -++CONFIG_FRAMEBUFFER_CONSOLE=y -++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -++# CONFIG_FRAMEBUFFER_CONSOLE_CURSOR_FLASH is not set -++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -++CONFIG_FONTS=y -++CONFIG_FONT_8x8=y -++CONFIG_FONT_8x16=y -++# CONFIG_FONT_6x11 is not set -++# CONFIG_FONT_7x14 is not set -++# CONFIG_FONT_PEARL_8x8 is not set -++# CONFIG_FONT_ACORN_8x8 is not set -++# CONFIG_FONT_MINI_4x6 is not set -++# CONFIG_FONT_SUN8x16 is not set -++# CONFIG_FONT_SUN12x22 is not set -++# CONFIG_FONT_10x18 is not set -++CONFIG_LOGO=y -++CONFIG_LOGO_LINUX_MONO=y -++CONFIG_LOGO_LINUX_VGA16=y -++CONFIG_LOGO_LINUX_CLUT224=y -++ -++# -++# Sound -++# -++CONFIG_SOUND=y -++ -++# -++# Advanced Linux Sound Architecture -++# -++# CONFIG_SND is not set -++ -++# -++# Open Sound System -++# -++CONFIG_SOUND_PRIME=y -++CONFIG_OSS_OBSOLETE=y -++# CONFIG_SOUND_JZ_AC97 is not set -++CONFIG_SOUND_JZ_I2S=y -++# CONFIG_SOUND_JZ_PCM is not set -++# CONFIG_I2S_AK4642EN is not set -++CONFIG_I2S_ICODEC=y -++# CONFIG_SOUND_MSNDCLAS is not set -++# CONFIG_SOUND_MSNDPIN is not set -++CONFIG_HID_SUPPORT=y -++CONFIG_HID=y -++# CONFIG_HID_DEBUG is not set -++# CONFIG_HIDRAW is not set -++ -++# -++# USB Input Devices -++# -++CONFIG_USB_HID=y -++# CONFIG_USB_HIDINPUT_POWERBOOK is not set -++# CONFIG_HID_FF is not set -++# CONFIG_USB_HIDDEV is not set -++CONFIG_USB_SUPPORT=y -++CONFIG_USB_ARCH_HAS_HCD=y -++CONFIG_USB_ARCH_HAS_OHCI=y -++# CONFIG_USB_ARCH_HAS_EHCI is not set -++CONFIG_USB=y -++# CONFIG_USB_DEBUG is not set -++ -++# -++# Miscellaneous USB options -++# -++# CONFIG_USB_DEVICEFS is not set -++CONFIG_USB_DEVICE_CLASS=y -++# CONFIG_USB_DYNAMIC_MINORS is not set -++# CONFIG_USB_SUSPEND is not set -++# CONFIG_USB_PERSIST is not set -++# CONFIG_USB_OTG is not set -++ -++# -++# USB Host Controller Drivers -++# -++# CONFIG_USB_ISP116X_HCD is not set -++CONFIG_USB_OHCI_HCD=y -++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set -++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set -++CONFIG_USB_OHCI_LITTLE_ENDIAN=y -++# CONFIG_USB_SL811_HCD is not set -++# CONFIG_USB_R8A66597_HCD is not set -++ -++# -++# USB Device Class drivers -++# -++# CONFIG_USB_ACM is not set -++# CONFIG_USB_PRINTER is not set -++ -++# -++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -++# -++ -++# -++# may also be needed; see USB_STORAGE Help for more information -++# -++CONFIG_USB_STORAGE=y -++# CONFIG_USB_STORAGE_DEBUG is not set -++# CONFIG_USB_STORAGE_DATAFAB is not set -++# CONFIG_USB_STORAGE_FREECOM is not set -++# CONFIG_USB_STORAGE_ISD200 is not set -++# CONFIG_USB_STORAGE_DPCM is not set -++# CONFIG_USB_STORAGE_USBAT is not set -++# CONFIG_USB_STORAGE_SDDR09 is not set -++# CONFIG_USB_STORAGE_SDDR55 is not set -++# CONFIG_USB_STORAGE_JUMPSHOT is not set -++# CONFIG_USB_STORAGE_ALAUDA is not set -++# CONFIG_USB_STORAGE_KARMA is not set -++# CONFIG_USB_LIBUSUAL is not set -++ -++# -++# USB Imaging devices -++# -++# CONFIG_USB_MDC800 is not set -++# CONFIG_USB_MICROTEK is not set -++CONFIG_USB_MON=y -++ -++# -++# USB port drivers -++# -++ -++# -++# USB Serial Converter support -++# -++# CONFIG_USB_SERIAL is not set -++ -++# -++# USB Miscellaneous drivers -++# -++# CONFIG_USB_EMI62 is not set -++# CONFIG_USB_EMI26 is not set -++# CONFIG_USB_ADUTUX is not set -++# CONFIG_USB_AUERSWALD is not set -++# CONFIG_USB_RIO500 is not set -++# CONFIG_USB_LEGOTOWER is not set -++# CONFIG_USB_LCD is not set -++# CONFIG_USB_BERRY_CHARGE is not set -++# CONFIG_USB_LED is not set -++# CONFIG_USB_CYPRESS_CY7C63 is not set -++# CONFIG_USB_CYTHERM is not set -++# CONFIG_USB_PHIDGET is not set -++# CONFIG_USB_IDMOUSE is not set -++# CONFIG_USB_FTDI_ELAN is not set -++# CONFIG_USB_APPLEDISPLAY is not set -++# CONFIG_USB_LD is not set -++# CONFIG_USB_TRANCEVIBRATOR is not set -++# CONFIG_USB_IOWARRIOR is not set -++ -++# -++# USB DSL modem support -++# -++ -++# -++# USB Gadget Support -++# -++CONFIG_USB_GADGET=m -++# CONFIG_USB_GADGET_DEBUG_FILES is not set -++# CONFIG_USB_GADGET_DEBUG_FS is not set -++CONFIG_USB_GADGET_SELECTED=y -++CONFIG_USB_GADGET_JZ4740=y -++CONFIG_USB_JZ4740=m -++# CONFIG_USB_GADGET_JZ4730 is not set -++# CONFIG_USB_GADGET_AMD5536UDC is not set -++# CONFIG_USB_GADGET_ATMEL_USBA is not set -++# CONFIG_USB_GADGET_FSL_USB2 is not set -++# CONFIG_USB_GADGET_NET2280 is not set -++# CONFIG_USB_GADGET_PXA2XX is not set -++# CONFIG_USB_GADGET_M66592 is not set -++# CONFIG_USB_GADGET_GOKU is not set -++# CONFIG_USB_GADGET_LH7A40X is not set -++# CONFIG_USB_GADGET_OMAP is not set -++# CONFIG_USB_GADGET_S3C2410 is not set -++# CONFIG_USB_GADGET_AT91 is not set -++# CONFIG_USB_GADGET_DUMMY_HCD is not set -++CONFIG_USB_GADGET_DUALSPEED=y -++# CONFIG_USB_ZERO is not set -++# CONFIG_USB_ETH is not set -++# CONFIG_USB_GADGETFS is not set -++CONFIG_USB_FILE_STORAGE=m -++# CONFIG_USB_FILE_STORAGE_TEST is not set -++# CONFIG_USB_G_SERIAL is not set -++# CONFIG_USB_MIDI_GADGET is not set -++CONFIG_MMC=y -++# CONFIG_MMC_DEBUG is not set -++# CONFIG_MMC_UNSAFE_RESUME is not set -++ -++# -++# MMC/SD Card Drivers -++# -++CONFIG_MMC_BLOCK=y -++CONFIG_MMC_BLOCK_BOUNCE=y -++# CONFIG_SDIO_UART is not set -++ -++# -++# MMC/SD Host Controller Drivers -++# -++CONFIG_MMC_JZ=y -++# CONFIG_JZ_MMC_BUS_4 is not set -++CONFIG_JZ_MMC_BUS_1=y -++# CONFIG_NEW_LEDS is not set -++CONFIG_RTC_LIB=y -++# CONFIG_RTC_CLASS is not set -++ -++# -++# Userspace I/O -++# -++# CONFIG_UIO is not set -++ -++# -++# File systems -++# -++CONFIG_EXT2_FS=y -++CONFIG_EXT2_FS_XATTR=y -++# CONFIG_EXT2_FS_POSIX_ACL is not set -++# CONFIG_EXT2_FS_SECURITY is not set -++# CONFIG_EXT2_FS_XIP is not set -++# CONFIG_EXT3_FS is not set -++# CONFIG_EXT4DEV_FS is not set -++CONFIG_FS_MBCACHE=y -++# CONFIG_REISERFS_FS is not set -++# CONFIG_JFS_FS is not set -++CONFIG_FS_POSIX_ACL=y -++# CONFIG_XFS_FS is not set -++# CONFIG_GFS2_FS is not set -++# CONFIG_OCFS2_FS is not set -++CONFIG_MINIX_FS=y -++# CONFIG_ROMFS_FS is not set -++CONFIG_INOTIFY=y -++CONFIG_INOTIFY_USER=y -++# CONFIG_QUOTA is not set -++CONFIG_DNOTIFY=y -++# CONFIG_AUTOFS_FS is not set -++# CONFIG_AUTOFS4_FS is not set -++# CONFIG_FUSE_FS is not set -++ -++# -++# CD-ROM/DVD Filesystems -++# -++# CONFIG_ISO9660_FS is not set -++# CONFIG_UDF_FS is not set -++ -++# -++# DOS/FAT/NT Filesystems -++# -++CONFIG_FAT_FS=y -++CONFIG_MSDOS_FS=y -++CONFIG_VFAT_FS=y -++CONFIG_FAT_DEFAULT_CODEPAGE=437 -++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -++# CONFIG_NTFS_FS is not set -++ -++# -++# Pseudo filesystems -++# -++CONFIG_PROC_FS=y -++CONFIG_PROC_KCORE=y -++CONFIG_PROC_SYSCTL=y -++CONFIG_SYSFS=y -++CONFIG_TMPFS=y -++# CONFIG_TMPFS_POSIX_ACL is not set -++# CONFIG_HUGETLB_PAGE is not set -++# CONFIG_CONFIGFS_FS is not set -++ -++# -++# Miscellaneous filesystems -++# -++# CONFIG_ADFS_FS is not set -++# CONFIG_AFFS_FS is not set -++# CONFIG_HFS_FS is not set -++# CONFIG_HFSPLUS_FS is not set -++# CONFIG_BEFS_FS is not set -++# CONFIG_BFS_FS is not set -++# CONFIG_EFS_FS is not set -++# CONFIG_JFFS2_FS is not set -++CONFIG_UBIFS_FS=m -++# CONFIG_UBIFS_FS_XATTR is not set -++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set -++CONFIG_UBIFS_FS_LZO=y -++CONFIG_UBIFS_FS_ZLIB=y -++# CONFIG_UBIFS_FS_DEBUG is not set -++# CONFIG_CRAMFS is not set -++# CONFIG_VXFS_FS is not set -++# CONFIG_HPFS_FS is not set -++# CONFIG_QNX4FS_FS is not set -++# CONFIG_SYSV_FS is not set -++# CONFIG_UFS_FS is not set -++CONFIG_NETWORK_FILESYSTEMS=y -++CONFIG_NFS_FS=y -++CONFIG_NFS_V3=y -++CONFIG_NFS_V3_ACL=y -++CONFIG_NFS_V4=y -++CONFIG_NFS_DIRECTIO=y -++# CONFIG_NFSD is not set -++CONFIG_ROOT_NFS=y -++CONFIG_LOCKD=y -++CONFIG_LOCKD_V4=y -++CONFIG_NFS_ACL_SUPPORT=y -++CONFIG_NFS_COMMON=y -++CONFIG_SUNRPC=y -++CONFIG_SUNRPC_GSS=y -++# CONFIG_SUNRPC_BIND34 is not set -++CONFIG_RPCSEC_GSS_KRB5=y -++# CONFIG_RPCSEC_GSS_SPKM3 is not set -++# CONFIG_SMB_FS is not set -++# CONFIG_CIFS is not set -++# CONFIG_NCP_FS is not set -++# CONFIG_CODA_FS is not set -++# CONFIG_AFS_FS is not set -++ -++# -++# Partition Types -++# -++CONFIG_PARTITION_ADVANCED=y -++# CONFIG_ACORN_PARTITION is not set -++# CONFIG_OSF_PARTITION is not set -++# CONFIG_AMIGA_PARTITION is not set -++# CONFIG_ATARI_PARTITION is not set -++# CONFIG_MAC_PARTITION is not set -++CONFIG_MSDOS_PARTITION=y -++# CONFIG_BSD_DISKLABEL is not set -++# CONFIG_MINIX_SUBPARTITION is not set -++# CONFIG_SOLARIS_X86_PARTITION is not set -++# CONFIG_UNIXWARE_DISKLABEL is not set -++# CONFIG_LDM_PARTITION is not set -++# CONFIG_SGI_PARTITION is not set -++# CONFIG_ULTRIX_PARTITION is not set -++# CONFIG_SUN_PARTITION is not set -++# CONFIG_KARMA_PARTITION is not set -++# CONFIG_EFI_PARTITION is not set -++# CONFIG_SYSV68_PARTITION is not set -++CONFIG_NLS=y -++CONFIG_NLS_DEFAULT="iso8859-1" -++CONFIG_NLS_CODEPAGE_437=y -++# CONFIG_NLS_CODEPAGE_737 is not set -++# CONFIG_NLS_CODEPAGE_775 is not set -++# CONFIG_NLS_CODEPAGE_850 is not set -++# CONFIG_NLS_CODEPAGE_852 is not set -++# CONFIG_NLS_CODEPAGE_855 is not set -++# CONFIG_NLS_CODEPAGE_857 is not set -++# CONFIG_NLS_CODEPAGE_860 is not set -++# CONFIG_NLS_CODEPAGE_861 is not set -++# CONFIG_NLS_CODEPAGE_862 is not set -++# CONFIG_NLS_CODEPAGE_863 is not set -++# CONFIG_NLS_CODEPAGE_864 is not set -++# CONFIG_NLS_CODEPAGE_865 is not set -++# CONFIG_NLS_CODEPAGE_866 is not set -++# CONFIG_NLS_CODEPAGE_869 is not set -++CONFIG_NLS_CODEPAGE_936=y -++# CONFIG_NLS_CODEPAGE_950 is not set -++# CONFIG_NLS_CODEPAGE_932 is not set -++# CONFIG_NLS_CODEPAGE_949 is not set -++# CONFIG_NLS_CODEPAGE_874 is not set -++# CONFIG_NLS_ISO8859_8 is not set -++# CONFIG_NLS_CODEPAGE_1250 is not set -++# CONFIG_NLS_CODEPAGE_1251 is not set -++CONFIG_NLS_ASCII=y -++CONFIG_NLS_ISO8859_1=y -++# CONFIG_NLS_ISO8859_2 is not set -++# CONFIG_NLS_ISO8859_3 is not set -++# CONFIG_NLS_ISO8859_4 is not set -++# CONFIG_NLS_ISO8859_5 is not set -++# CONFIG_NLS_ISO8859_6 is not set -++# CONFIG_NLS_ISO8859_7 is not set -++# CONFIG_NLS_ISO8859_9 is not set -++# CONFIG_NLS_ISO8859_13 is not set -++# CONFIG_NLS_ISO8859_14 is not set -++# CONFIG_NLS_ISO8859_15 is not set -++# CONFIG_NLS_KOI8_R is not set -++# CONFIG_NLS_KOI8_U is not set -++# CONFIG_NLS_UTF8 is not set -++# CONFIG_DLM is not set -++ -++# -++# Yaffs2 Filesystems -++# -++CONFIG_YAFFS_FS=y -++CONFIG_YAFFS_YAFFS1=y -++# CONFIG_YAFFS_DOES_ECC is not set -++CONFIG_YAFFS_YAFFS2=y -++CONFIG_YAFFS_AUTO_YAFFS2=y -++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set -++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set -++CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK=y -++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y -++CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10 -++CONFIG_INSTRUMENTATION=y -++# CONFIG_PROFILING is not set -++# CONFIG_MARKERS is not set -++ -++# -++# Kernel hacking -++# -++CONFIG_TRACE_IRQFLAGS_SUPPORT=y -++# CONFIG_PRINTK_TIME is not set -++CONFIG_ENABLE_WARN_DEPRECATED=y -++CONFIG_ENABLE_MUST_CHECK=y -++CONFIG_MAGIC_SYSRQ=y -++# CONFIG_UNUSED_SYMBOLS is not set -++CONFIG_DEBUG_FS=y -++# CONFIG_HEADERS_CHECK is not set -++# CONFIG_DEBUG_KERNEL is not set -++# CONFIG_SAMPLES is not set -++CONFIG_CMDLINE="" -++ -++# -++# Security options -++# -++# CONFIG_KEYS is not set -++# CONFIG_SECURITY is not set -++# CONFIG_SECURITY_FILE_CAPABILITIES is not set -++CONFIG_CRYPTO=y -++CONFIG_CRYPTO_ALGAPI=y -++CONFIG_CRYPTO_BLKCIPHER=y -++CONFIG_CRYPTO_MANAGER=y -++# CONFIG_CRYPTO_HMAC is not set -++# CONFIG_CRYPTO_XCBC is not set -++# CONFIG_CRYPTO_NULL is not set -++# CONFIG_CRYPTO_MD4 is not set -++CONFIG_CRYPTO_MD5=y -++# CONFIG_CRYPTO_SHA1 is not set -++# CONFIG_CRYPTO_SHA256 is not set -++# CONFIG_CRYPTO_SHA512 is not set -++# CONFIG_CRYPTO_WP512 is not set -++# CONFIG_CRYPTO_TGR192 is not set -++# CONFIG_CRYPTO_GF128MUL is not set -++# CONFIG_CRYPTO_ECB is not set -++CONFIG_CRYPTO_CBC=y -++# CONFIG_CRYPTO_PCBC is not set -++# CONFIG_CRYPTO_LRW is not set -++# CONFIG_CRYPTO_XTS is not set -++# CONFIG_CRYPTO_CRYPTD is not set -++CONFIG_CRYPTO_DES=y -++# CONFIG_CRYPTO_FCRYPT is not set -++# CONFIG_CRYPTO_BLOWFISH is not set -++# CONFIG_CRYPTO_TWOFISH is not set -++# CONFIG_CRYPTO_SERPENT is not set -++# CONFIG_CRYPTO_AES is not set -++# CONFIG_CRYPTO_CAST5 is not set -++# CONFIG_CRYPTO_CAST6 is not set -++# CONFIG_CRYPTO_TEA is not set -++# CONFIG_CRYPTO_ARC4 is not set -++# CONFIG_CRYPTO_KHAZAD is not set -++# CONFIG_CRYPTO_ANUBIS is not set -++# CONFIG_CRYPTO_SEED is not set -++CONFIG_CRYPTO_DEFLATE=m -++# CONFIG_CRYPTO_MICHAEL_MIC is not set -++# CONFIG_CRYPTO_CRC32C is not set -++# CONFIG_CRYPTO_CAMELLIA is not set -++# CONFIG_CRYPTO_TEST is not set -++# CONFIG_CRYPTO_AUTHENC is not set -++CONFIG_CRYPTO_LZO=m -++CONFIG_CRYPTO_HW=y -++ -++# -++# Library routines -++# -++CONFIG_BITREVERSE=y -++# CONFIG_CRC_CCITT is not set -++CONFIG_CRC16=m -++# CONFIG_CRC_ITU_T is not set -++CONFIG_CRC32=y -++# CONFIG_CRC7 is not set -++# CONFIG_LIBCRC32C is not set -++CONFIG_ZLIB_INFLATE=m -++CONFIG_ZLIB_DEFLATE=m -++CONFIG_LZO_COMPRESS=m -++CONFIG_LZO_DECOMPRESS=m -++CONFIG_PLIST=y -++CONFIG_HAS_IOMEM=y -++CONFIG_HAS_IOPORT=y -++CONFIG_HAS_DMA=y -+diff -urN linux-2.6.24.7.old/arch/mips/configs/fuwa_defconfig linux-2.6.24.7/arch/mips/configs/fuwa_defconfig -+--- linux-2.6.24.7.old/arch/mips/configs/fuwa_defconfig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/configs/fuwa_defconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,928 @@ -++# -++# Automatically generated make config: don't edit -++# Linux kernel version: 2.6.24.3 -++# Fri Jul 4 19:20:22 2008 -++# -++CONFIG_MIPS=y -++ -++# -++# Machine selection -++# -++# CONFIG_JZ4730_PMP is not set -++# CONFIG_JZ4740_PAVO is not set -++# CONFIG_JZ4740_LEO is not set -++# CONFIG_JZ4740_LYRA is not set -++# CONFIG_JZ4725_DIPPER is not set -++# CONFIG_JZ4720_VIRGO is not set -++CONFIG_JZ4750_FUWA=y -++# CONFIG_MACH_ALCHEMY is not set -++# CONFIG_BASLER_EXCITE is not set -++# CONFIG_BCM47XX is not set -++# CONFIG_MIPS_COBALT is not set -++# CONFIG_MACH_DECSTATION is not set -++# CONFIG_MACH_JAZZ is not set -++# CONFIG_LASAT is not set -++# CONFIG_LEMOTE_FULONG is not set -++# CONFIG_MIPS_ATLAS is not set -++# CONFIG_MIPS_MALTA is not set -++# CONFIG_MIPS_SEAD is not set -++# CONFIG_MIPS_SIM is not set -++# CONFIG_MARKEINS is not set -++# CONFIG_MACH_VR41XX is not set -++# CONFIG_PNX8550_JBS is not set -++# CONFIG_PNX8550_STB810 is not set -++# CONFIG_PMC_MSP is not set -++# CONFIG_PMC_YOSEMITE is not set -++# CONFIG_QEMU is not set -++# CONFIG_SGI_IP22 is not set -++# CONFIG_SGI_IP27 is not set -++# CONFIG_SGI_IP32 is not set -++# CONFIG_SIBYTE_CRHINE is not set -++# CONFIG_SIBYTE_CARMEL is not set -++# CONFIG_SIBYTE_CRHONE is not set -++# CONFIG_SIBYTE_RHONE is not set -++# CONFIG_SIBYTE_SWARM is not set -++# CONFIG_SIBYTE_LITTLESUR is not set -++# CONFIG_SIBYTE_SENTOSA is not set -++# CONFIG_SIBYTE_PTSWARM is not set -++# CONFIG_SIBYTE_BIGSUR is not set -++# CONFIG_SNI_RM is not set -++# CONFIG_TOSHIBA_JMR3927 is not set -++# CONFIG_TOSHIBA_RBTX4927 is not set -++# CONFIG_TOSHIBA_RBTX4938 is not set -++# CONFIG_WR_PPMC is not set -++CONFIG_SOC_JZ4750=y -++CONFIG_JZ_FPGA=y -++CONFIG_JZSOC=y -++CONFIG_JZRISC=y -++CONFIG_RWSEM_GENERIC_SPINLOCK=y -++# CONFIG_ARCH_HAS_ILOG2_U32 is not set -++# CONFIG_ARCH_HAS_ILOG2_U64 is not set -++CONFIG_ARCH_SUPPORTS_OPROFILE=y -++CONFIG_GENERIC_FIND_NEXT_BIT=y -++CONFIG_GENERIC_HWEIGHT=y -++CONFIG_GENERIC_CALIBRATE_DELAY=y -++CONFIG_GENERIC_CLOCKEVENTS=y -++CONFIG_GENERIC_TIME=y -++CONFIG_GENERIC_CMOS_UPDATE=y -++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -++# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set -++CONFIG_DMA_NONCOHERENT=y -++CONFIG_DMA_NEED_PCI_MAP_STATE=y -++# CONFIG_HOTPLUG_CPU is not set -++# CONFIG_NO_IOPORT is not set -++# CONFIG_CPU_BIG_ENDIAN is not set -++CONFIG_CPU_LITTLE_ENDIAN=y -++CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -++CONFIG_MIPS_L1_CACHE_SHIFT=5 -++ -++# -++# CPU selection -++# -++# CONFIG_CPU_LOONGSON2 is not set -++CONFIG_CPU_MIPS32_R1=y -++# CONFIG_CPU_MIPS32_R2 is not set -++# CONFIG_CPU_MIPS64_R1 is not set -++# CONFIG_CPU_MIPS64_R2 is not set -++# CONFIG_CPU_R3000 is not set -++# CONFIG_CPU_TX39XX is not set -++# CONFIG_CPU_VR41XX is not set -++# CONFIG_CPU_R4300 is not set -++# CONFIG_CPU_R4X00 is not set -++# CONFIG_CPU_TX49XX is not set -++# CONFIG_CPU_R5000 is not set -++# CONFIG_CPU_R5432 is not set -++# CONFIG_CPU_R6000 is not set -++# CONFIG_CPU_NEVADA is not set -++# CONFIG_CPU_R8000 is not set -++# CONFIG_CPU_R10000 is not set -++# CONFIG_CPU_RM7000 is not set -++# CONFIG_CPU_RM9000 is not set -++# CONFIG_CPU_SB1 is not set -++CONFIG_SYS_HAS_CPU_MIPS32_R1=y -++CONFIG_CPU_MIPS32=y -++CONFIG_CPU_MIPSR1=y -++CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -++CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -++ -++# -++# Kernel type -++# -++CONFIG_32BIT=y -++# CONFIG_64BIT is not set -++CONFIG_PAGE_SIZE_4KB=y -++# CONFIG_PAGE_SIZE_8KB is not set -++# CONFIG_PAGE_SIZE_16KB is not set -++# CONFIG_PAGE_SIZE_64KB is not set -++CONFIG_CPU_HAS_PREFETCH=y -++CONFIG_MIPS_MT_DISABLED=y -++# CONFIG_MIPS_MT_SMP is not set -++# CONFIG_MIPS_MT_SMTC is not set -++CONFIG_CPU_HAS_LLSC=y -++CONFIG_CPU_HAS_SYNC=y -++CONFIG_GENERIC_HARDIRQS=y -++CONFIG_GENERIC_IRQ_PROBE=y -++CONFIG_CPU_SUPPORTS_HIGHMEM=y -++CONFIG_ARCH_FLATMEM_ENABLE=y -++CONFIG_ARCH_POPULATES_NODE_MAP=y -++CONFIG_SELECT_MEMORY_MODEL=y -++CONFIG_FLATMEM_MANUAL=y -++# CONFIG_DISCONTIGMEM_MANUAL is not set -++# CONFIG_SPARSEMEM_MANUAL is not set -++CONFIG_FLATMEM=y -++CONFIG_FLAT_NODE_MEM_MAP=y -++# CONFIG_SPARSEMEM_STATIC is not set -++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -++CONFIG_SPLIT_PTLOCK_CPUS=4 -++# CONFIG_RESOURCES_64BIT is not set -++CONFIG_ZONE_DMA_FLAG=0 -++CONFIG_VIRT_TO_BUS=y -++# CONFIG_TICK_ONESHOT is not set -++# CONFIG_NO_HZ is not set -++# CONFIG_HIGH_RES_TIMERS is not set -++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -++# CONFIG_HZ_48 is not set -++CONFIG_HZ_100=y -++# CONFIG_HZ_128 is not set -++# CONFIG_HZ_250 is not set -++# CONFIG_HZ_256 is not set -++# CONFIG_HZ_1000 is not set -++# CONFIG_HZ_1024 is not set -++CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -++CONFIG_HZ=100 -++# CONFIG_PREEMPT_NONE is not set -++# CONFIG_PREEMPT_VOLUNTARY is not set -++CONFIG_PREEMPT=y -++CONFIG_PREEMPT_BKL=y -++# CONFIG_KEXEC is not set -++CONFIG_SECCOMP=y -++CONFIG_LOCKDEP_SUPPORT=y -++CONFIG_STACKTRACE_SUPPORT=y -++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -++ -++# -++# General setup -++# -++CONFIG_EXPERIMENTAL=y -++CONFIG_BROKEN_ON_SMP=y -++CONFIG_LOCK_KERNEL=y -++CONFIG_INIT_ENV_ARG_LIMIT=32 -++CONFIG_LOCALVERSION="" -++CONFIG_LOCALVERSION_AUTO=y -++CONFIG_SWAP=y -++CONFIG_SYSVIPC=y -++CONFIG_SYSVIPC_SYSCTL=y -++# CONFIG_POSIX_MQUEUE is not set -++# CONFIG_BSD_PROCESS_ACCT is not set -++# CONFIG_TASKSTATS is not set -++# CONFIG_USER_NS is not set -++# CONFIG_PID_NS is not set -++# CONFIG_AUDIT is not set -++# CONFIG_IKCONFIG is not set -++CONFIG_LOG_BUF_SHIFT=14 -++# CONFIG_CGROUPS is not set -++CONFIG_FAIR_GROUP_SCHED=y -++CONFIG_FAIR_USER_SCHED=y -++# CONFIG_FAIR_CGROUP_SCHED is not set -++CONFIG_SYSFS_DEPRECATED=y -++CONFIG_RELAY=y -++# CONFIG_BLK_DEV_INITRD is not set -++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -++CONFIG_SYSCTL=y -++CONFIG_EMBEDDED=y -++CONFIG_SYSCTL_SYSCALL=y -++CONFIG_KALLSYMS=y -++# CONFIG_KALLSYMS_EXTRA_PASS is not set -++CONFIG_HOTPLUG=y -++CONFIG_PRINTK=y -++CONFIG_BUG=y -++CONFIG_ELF_CORE=y -++CONFIG_BASE_FULL=y -++CONFIG_FUTEX=y -++CONFIG_ANON_INODES=y -++CONFIG_EPOLL=y -++CONFIG_SIGNALFD=y -++CONFIG_EVENTFD=y -++CONFIG_SHMEM=y -++CONFIG_VM_EVENT_COUNTERS=y -++CONFIG_SLAB=y -++# CONFIG_SLUB is not set -++# CONFIG_SLOB is not set -++CONFIG_SLABINFO=y -++CONFIG_RT_MUTEXES=y -++# CONFIG_TINY_SHMEM is not set -++CONFIG_BASE_SMALL=0 -++CONFIG_MODULES=y -++CONFIG_MODULE_UNLOAD=y -++# CONFIG_MODULE_FORCE_UNLOAD is not set -++CONFIG_MODVERSIONS=y -++CONFIG_MODULE_SRCVERSION_ALL=y -++CONFIG_KMOD=y -++CONFIG_BLOCK=y -++# CONFIG_LBD is not set -++# CONFIG_BLK_DEV_IO_TRACE is not set -++# CONFIG_LSF is not set -++# CONFIG_BLK_DEV_BSG is not set -++ -++# -++# IO Schedulers -++# -++CONFIG_IOSCHED_NOOP=y -++CONFIG_IOSCHED_AS=y -++CONFIG_IOSCHED_DEADLINE=y -++CONFIG_IOSCHED_CFQ=y -++CONFIG_DEFAULT_AS=y -++# CONFIG_DEFAULT_DEADLINE is not set -++# CONFIG_DEFAULT_CFQ is not set -++# CONFIG_DEFAULT_NOOP is not set -++CONFIG_DEFAULT_IOSCHED="anticipatory" -++ -++# -++# Bus options (PCI, PCMCIA, EISA, ISA, TC) -++# -++# CONFIG_ARCH_SUPPORTS_MSI is not set -++CONFIG_MMU=y -++# CONFIG_PCCARD is not set -++ -++# -++# Executable file formats -++# -++CONFIG_BINFMT_ELF=y -++# CONFIG_BINFMT_MISC is not set -++CONFIG_TRAD_SIGNALS=y -++ -++# -++# CPU Frequency scaling -++# -++# CONFIG_CPU_FREQ_JZ is not set -++ -++# -++# Power management options -++# -++# CONFIG_PM is not set -++CONFIG_SUSPEND_UP_POSSIBLE=y -++ -++# -++# Networking -++# -++CONFIG_NET=y -++ -++# -++# Networking options -++# -++CONFIG_PACKET=y -++# CONFIG_PACKET_MMAP is not set -++CONFIG_UNIX=y -++# CONFIG_NET_KEY is not set -++CONFIG_INET=y -++# CONFIG_IP_MULTICAST is not set -++# CONFIG_IP_ADVANCED_ROUTER is not set -++CONFIG_IP_FIB_HASH=y -++CONFIG_IP_PNP=y -++CONFIG_IP_PNP_DHCP=y -++CONFIG_IP_PNP_BOOTP=y -++# CONFIG_IP_PNP_RARP is not set -++# CONFIG_NET_IPIP is not set -++# CONFIG_NET_IPGRE is not set -++# CONFIG_ARPD is not set -++# CONFIG_SYN_COOKIES is not set -++# CONFIG_INET_AH is not set -++# CONFIG_INET_ESP is not set -++# CONFIG_INET_IPCOMP is not set -++# CONFIG_INET_XFRM_TUNNEL is not set -++# CONFIG_INET_TUNNEL is not set -++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -++# CONFIG_INET_XFRM_MODE_TUNNEL is not set -++# CONFIG_INET_XFRM_MODE_BEET is not set -++# CONFIG_INET_LRO is not set -++CONFIG_INET_DIAG=m -++CONFIG_INET_TCP_DIAG=m -++# CONFIG_TCP_CONG_ADVANCED is not set -++CONFIG_TCP_CONG_CUBIC=y -++CONFIG_DEFAULT_TCP_CONG="cubic" -++# CONFIG_TCP_MD5SIG is not set -++# CONFIG_IPV6 is not set -++# CONFIG_INET6_XFRM_TUNNEL is not set -++# CONFIG_INET6_TUNNEL is not set -++# CONFIG_NETWORK_SECMARK is not set -++# CONFIG_NETFILTER is not set -++# CONFIG_IP_DCCP is not set -++# CONFIG_IP_SCTP is not set -++# CONFIG_TIPC is not set -++# CONFIG_ATM is not set -++# CONFIG_BRIDGE is not set -++# CONFIG_VLAN_8021Q is not set -++# CONFIG_DECNET is not set -++# CONFIG_LLC2 is not set -++# CONFIG_IPX is not set -++# CONFIG_ATALK is not set -++# CONFIG_X25 is not set -++# CONFIG_LAPB is not set -++# CONFIG_ECONET is not set -++# CONFIG_WAN_ROUTER is not set -++# CONFIG_NET_SCHED is not set -++ -++# -++# Network testing -++# -++# CONFIG_NET_PKTGEN is not set -++# CONFIG_HAMRADIO is not set -++# CONFIG_IRDA is not set -++# CONFIG_BT is not set -++# CONFIG_AF_RXRPC is not set -++ -++# -++# Wireless -++# -++# CONFIG_CFG80211 is not set -++# CONFIG_WIRELESS_EXT is not set -++# CONFIG_MAC80211 is not set -++# CONFIG_IEEE80211 is not set -++# CONFIG_RFKILL is not set -++# CONFIG_NET_9P is not set -++ -++# -++# Device Drivers -++# -++ -++# -++# Generic Driver Options -++# -++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -++CONFIG_STANDALONE=y -++CONFIG_PREVENT_FIRMWARE_BUILD=y -++# CONFIG_FW_LOADER is not set -++# CONFIG_SYS_HYPERVISOR is not set -++# CONFIG_CONNECTOR is not set -++CONFIG_MTD=y -++# CONFIG_MTD_DEBUG is not set -++# CONFIG_MTD_CONCAT is not set -++CONFIG_MTD_PARTITIONS=y -++# CONFIG_MTD_REDBOOT_PARTS is not set -++# CONFIG_MTD_CMDLINE_PARTS is not set -++ -++# -++# User Modules And Translation Layers -++# -++CONFIG_MTD_CHAR=y -++CONFIG_MTD_BLKDEVS=y -++CONFIG_MTD_BLOCK=y -++# CONFIG_FTL is not set -++# CONFIG_NFTL is not set -++# CONFIG_INFTL is not set -++# CONFIG_RFD_FTL is not set -++# CONFIG_SSFDC is not set -++# CONFIG_MTD_OOPS is not set -++ -++# -++# RAM/ROM/Flash chip drivers -++# -++# CONFIG_MTD_CFI is not set -++# CONFIG_MTD_JEDECPROBE is not set -++CONFIG_MTD_MAP_BANK_WIDTH_1=y -++CONFIG_MTD_MAP_BANK_WIDTH_2=y -++CONFIG_MTD_MAP_BANK_WIDTH_4=y -++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -++CONFIG_MTD_CFI_I1=y -++CONFIG_MTD_CFI_I2=y -++# CONFIG_MTD_CFI_I4 is not set -++# CONFIG_MTD_CFI_I8 is not set -++# CONFIG_MTD_RAM is not set -++# CONFIG_MTD_ROM is not set -++# CONFIG_MTD_ABSENT is not set -++ -++# -++# Mapping drivers for chip access -++# -++# CONFIG_MTD_COMPLEX_MAPPINGS is not set -++# CONFIG_MTD_PLATRAM is not set -++ -++# -++# Self-contained MTD device drivers -++# -++# CONFIG_MTD_SLRAM is not set -++# CONFIG_MTD_PHRAM is not set -++# CONFIG_MTD_MTDRAM is not set -++# CONFIG_MTD_BLOCK2MTD is not set -++ -++# -++# Disk-On-Chip Device Drivers -++# -++# CONFIG_MTD_DOC2000 is not set -++# CONFIG_MTD_DOC2001 is not set -++# CONFIG_MTD_DOC2001PLUS is not set -++CONFIG_MTD_NAND=y -++# CONFIG_MTD_NAND_VERIFY_WRITE is not set -++# CONFIG_MTD_NAND_ECC_SMC is not set -++# CONFIG_MTD_NAND_MUSEUM_IDS is not set -++CONFIG_MTD_NAND_IDS=y -++# CONFIG_MTD_NAND_DISKONCHIP is not set -++# CONFIG_MTD_NAND_NANDSIM is not set -++# CONFIG_MTD_NAND_PLATFORM is not set -++CONFIG_MTD_NAND_JZ4750=y -++# CONFIG_MTD_HW_HM_ECC is not set -++# CONFIG_MTD_SW_HM_ECC is not set -++# CONFIG_MTD_HW_RS_ECC is not set -++CONFIG_MTD_HW_BCH_ECC=y -++CONFIG_MTD_NAND_DMA=y -++# CONFIG_MTD_NAND_NO_DMA is not set -++CONFIG_MTD_HW_BCH_4BIT=y -++# CONFIG_MTD_HW_BCH_8BIT is not set -++# CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE is not set -++CONFIG_MTD_OOB_COPIES=0 -++CONFIG_MTD_BADBLOCK_FLAG_PAGE=127 -++# CONFIG_MTD_ONENAND is not set -++ -++# -++# UBI - Unsorted block images -++# -++# CONFIG_MTD_UBI is not set -++# CONFIG_MTD_UBI_BLKDEVS is not set -++# CONFIG_PARPORT is not set -++# CONFIG_PNP is not set -++CONFIG_BLK_DEV=y -++# CONFIG_BLK_DEV_COW_COMMON is not set -++CONFIG_BLK_DEV_LOOP=y -++# CONFIG_BLK_DEV_CRYPTOLOOP is not set -++# CONFIG_BLK_DEV_NBD is not set -++CONFIG_BLK_DEV_RAM=y -++CONFIG_BLK_DEV_RAM_COUNT=16 -++CONFIG_BLK_DEV_RAM_SIZE=4096 -++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -++# CONFIG_CDROM_PKTCDVD is not set -++# CONFIG_ATA_OVER_ETH is not set -++CONFIG_MISC_DEVICES=y -++# CONFIG_EEPROM_93CX6 is not set -++# CONFIG_IDE is not set -++ -++# -++# SCSI device support -++# -++# CONFIG_RAID_ATTRS is not set -++# CONFIG_SCSI is not set -++# CONFIG_SCSI_DMA is not set -++# CONFIG_SCSI_NETLINK is not set -++# CONFIG_ATA is not set -++# CONFIG_MD is not set -++CONFIG_NETDEVICES=y -++# CONFIG_NETDEVICES_MULTIQUEUE is not set -++# CONFIG_DUMMY is not set -++# CONFIG_BONDING is not set -++# CONFIG_MACVLAN is not set -++# CONFIG_EQUALIZER is not set -++# CONFIG_TUN is not set -++# CONFIG_VETH is not set -++CONFIG_PHYLIB=y -++ -++# -++# MII PHY device drivers -++# -++# CONFIG_MARVELL_PHY is not set -++# CONFIG_DAVICOM_PHY is not set -++# CONFIG_QSEMI_PHY is not set -++# CONFIG_LXT_PHY is not set -++# CONFIG_CICADA_PHY is not set -++# CONFIG_VITESSE_PHY is not set -++# CONFIG_SMSC_PHY is not set -++# CONFIG_BROADCOM_PHY is not set -++# CONFIG_ICPLUS_PHY is not set -++# CONFIG_FIXED_PHY is not set -++# CONFIG_MDIO_BITBANG is not set -++CONFIG_NET_ETHERNET=y -++CONFIG_MII=y -++CONFIG_JZ_ETH=y -++# CONFIG_AX88796 is not set -++# CONFIG_DM9000 is not set -++# CONFIG_IBM_NEW_EMAC_ZMII is not set -++# CONFIG_IBM_NEW_EMAC_RGMII is not set -++# CONFIG_IBM_NEW_EMAC_TAH is not set -++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -++# CONFIG_B44 is not set -++CONFIG_NETDEV_1000=y -++CONFIG_NETDEV_10000=y -++ -++# -++# Wireless LAN -++# -++# CONFIG_WLAN_PRE80211 is not set -++# CONFIG_WLAN_80211 is not set -++# CONFIG_WAN is not set -++# CONFIG_PPP is not set -++# CONFIG_SLIP is not set -++# CONFIG_SHAPER is not set -++# CONFIG_NETCONSOLE is not set -++# CONFIG_NETPOLL is not set -++# CONFIG_NET_POLL_CONTROLLER is not set -++# CONFIG_ISDN is not set -++# CONFIG_PHONE is not set -++ -++# -++# Input device support -++# -++CONFIG_INPUT=y -++# CONFIG_INPUT_FF_MEMLESS is not set -++# CONFIG_INPUT_POLLDEV is not set -++ -++# -++# Userland interfaces -++# -++# CONFIG_INPUT_MOUSEDEV is not set -++# CONFIG_INPUT_JOYDEV is not set -++# CONFIG_INPUT_EVDEV is not set -++# CONFIG_INPUT_EVBUG is not set -++ -++# -++# Input Device Drivers -++# -++# CONFIG_INPUT_KEYBOARD is not set -++# CONFIG_INPUT_MOUSE is not set -++# CONFIG_INPUT_JOYSTICK is not set -++# CONFIG_INPUT_TABLET is not set -++# CONFIG_INPUT_TOUCHSCREEN is not set -++# CONFIG_INPUT_MISC is not set -++ -++# -++# Hardware I/O ports -++# -++CONFIG_SERIO=y -++# CONFIG_SERIO_I8042 is not set -++CONFIG_SERIO_SERPORT=y -++# CONFIG_SERIO_LIBPS2 is not set -++# CONFIG_SERIO_RAW is not set -++# CONFIG_GAMEPORT is not set -++ -++# -++# Character devices -++# -++CONFIG_VT=y -++CONFIG_VT_CONSOLE=y -++CONFIG_HW_CONSOLE=y -++CONFIG_VT_HW_CONSOLE_BINDING=y -++# CONFIG_SERIAL_NONSTANDARD is not set -++ -++# -++# Serial drivers -++# -++CONFIG_SERIAL_8250=y -++CONFIG_SERIAL_8250_CONSOLE=y -++CONFIG_SERIAL_8250_NR_UARTS=4 -++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -++# CONFIG_SERIAL_8250_EXTENDED is not set -++ -++# -++# Non-8250 serial port support -++# -++CONFIG_SERIAL_CORE=y -++CONFIG_SERIAL_CORE_CONSOLE=y -++CONFIG_UNIX98_PTYS=y -++CONFIG_LEGACY_PTYS=y -++CONFIG_LEGACY_PTY_COUNT=2 -++# CONFIG_IPMI_HANDLER is not set -++# CONFIG_HW_RANDOM is not set -++# CONFIG_RTC is not set -++# CONFIG_RTC_PCF8563 is not set -++# CONFIG_RTC_JZ is not set -++# CONFIG_R3964 is not set -++# CONFIG_RAW_DRIVER is not set -++# CONFIG_TCG_TPM is not set -++ -++# -++# JZSOC char device support -++# -++# CONFIG_JZCHAR is not set -++# CONFIG_I2C is not set -++ -++# -++# SPI support -++# -++# CONFIG_SPI is not set -++# CONFIG_SPI_MASTER is not set -++# CONFIG_W1 is not set -++# CONFIG_POWER_SUPPLY is not set -++# CONFIG_HWMON is not set -++# CONFIG_WATCHDOG is not set -++ -++# -++# Sonics Silicon Backplane -++# -++CONFIG_SSB_POSSIBLE=y -++# CONFIG_SSB is not set -++ -++# -++# Multifunction device drivers -++# -++# CONFIG_MFD_SM501 is not set -++ -++# -++# Multimedia devices -++# -++# CONFIG_VIDEO_DEV is not set -++# CONFIG_DVB_CORE is not set -++# CONFIG_DAB is not set -++ -++# -++# Graphics support -++# -++# CONFIG_VGASTATE is not set -++# CONFIG_VIDEO_OUTPUT_CONTROL is not set -++# CONFIG_FB is not set -++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set -++ -++# -++# Display device support -++# -++# CONFIG_DISPLAY_SUPPORT is not set -++ -++# -++# Console display driver support -++# -++# CONFIG_VGA_CONSOLE is not set -++CONFIG_DUMMY_CONSOLE=y -++ -++# -++# Sound -++# -++# CONFIG_SOUND is not set -++CONFIG_HID_SUPPORT=y -++CONFIG_HID=y -++# CONFIG_HID_DEBUG is not set -++# CONFIG_HIDRAW is not set -++CONFIG_USB_SUPPORT=y -++CONFIG_USB_ARCH_HAS_HCD=y -++CONFIG_USB_ARCH_HAS_OHCI=y -++# CONFIG_USB_ARCH_HAS_EHCI is not set -++# CONFIG_USB is not set -++ -++# -++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -++# -++ -++# -++# USB Gadget Support -++# -++# CONFIG_USB_GADGET is not set -++# CONFIG_MMC is not set -++# CONFIG_NEW_LEDS is not set -++CONFIG_RTC_LIB=y -++# CONFIG_RTC_CLASS is not set -++ -++# -++# Userspace I/O -++# -++# CONFIG_UIO is not set -++ -++# -++# File systems -++# -++CONFIG_EXT2_FS=y -++CONFIG_EXT2_FS_XATTR=y -++# CONFIG_EXT2_FS_POSIX_ACL is not set -++# CONFIG_EXT2_FS_SECURITY is not set -++# CONFIG_EXT2_FS_XIP is not set -++# CONFIG_EXT3_FS is not set -++# CONFIG_EXT4DEV_FS is not set -++CONFIG_FS_MBCACHE=y -++# CONFIG_REISERFS_FS is not set -++# CONFIG_JFS_FS is not set -++CONFIG_FS_POSIX_ACL=y -++# CONFIG_XFS_FS is not set -++# CONFIG_GFS2_FS is not set -++# CONFIG_OCFS2_FS is not set -++CONFIG_MINIX_FS=y -++# CONFIG_ROMFS_FS is not set -++CONFIG_INOTIFY=y -++CONFIG_INOTIFY_USER=y -++# CONFIG_QUOTA is not set -++CONFIG_DNOTIFY=y -++# CONFIG_AUTOFS_FS is not set -++# CONFIG_AUTOFS4_FS is not set -++# CONFIG_FUSE_FS is not set -++ -++# -++# CD-ROM/DVD Filesystems -++# -++# CONFIG_ISO9660_FS is not set -++# CONFIG_UDF_FS is not set -++ -++# -++# DOS/FAT/NT Filesystems -++# -++CONFIG_FAT_FS=y -++CONFIG_MSDOS_FS=y -++CONFIG_VFAT_FS=y -++CONFIG_FAT_DEFAULT_CODEPAGE=437 -++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -++# CONFIG_NTFS_FS is not set -++ -++# -++# Pseudo filesystems -++# -++CONFIG_PROC_FS=y -++CONFIG_PROC_KCORE=y -++CONFIG_PROC_SYSCTL=y -++CONFIG_SYSFS=y -++CONFIG_TMPFS=y -++# CONFIG_TMPFS_POSIX_ACL is not set -++# CONFIG_HUGETLB_PAGE is not set -++# CONFIG_CONFIGFS_FS is not set -++ -++# -++# Miscellaneous filesystems -++# -++# CONFIG_ADFS_FS is not set -++# CONFIG_AFFS_FS is not set -++# CONFIG_HFS_FS is not set -++# CONFIG_HFSPLUS_FS is not set -++# CONFIG_BEFS_FS is not set -++# CONFIG_BFS_FS is not set -++# CONFIG_EFS_FS is not set -++# CONFIG_JFFS2_FS is not set -++# CONFIG_CRAMFS is not set -++# CONFIG_VXFS_FS is not set -++# CONFIG_HPFS_FS is not set -++# CONFIG_QNX4FS_FS is not set -++# CONFIG_SYSV_FS is not set -++# CONFIG_UFS_FS is not set -++CONFIG_NETWORK_FILESYSTEMS=y -++CONFIG_NFS_FS=y -++CONFIG_NFS_V3=y -++CONFIG_NFS_V3_ACL=y -++CONFIG_NFS_V4=y -++CONFIG_NFS_DIRECTIO=y -++# CONFIG_NFSD is not set -++CONFIG_ROOT_NFS=y -++CONFIG_LOCKD=y -++CONFIG_LOCKD_V4=y -++CONFIG_NFS_ACL_SUPPORT=y -++CONFIG_NFS_COMMON=y -++CONFIG_SUNRPC=y -++CONFIG_SUNRPC_GSS=y -++# CONFIG_SUNRPC_BIND34 is not set -++CONFIG_RPCSEC_GSS_KRB5=y -++# CONFIG_RPCSEC_GSS_SPKM3 is not set -++# CONFIG_SMB_FS is not set -++# CONFIG_CIFS is not set -++# CONFIG_NCP_FS is not set -++# CONFIG_CODA_FS is not set -++# CONFIG_AFS_FS is not set -++ -++# -++# Partition Types -++# -++CONFIG_PARTITION_ADVANCED=y -++# CONFIG_ACORN_PARTITION is not set -++# CONFIG_OSF_PARTITION is not set -++# CONFIG_AMIGA_PARTITION is not set -++# CONFIG_ATARI_PARTITION is not set -++# CONFIG_MAC_PARTITION is not set -++CONFIG_MSDOS_PARTITION=y -++# CONFIG_BSD_DISKLABEL is not set -++# CONFIG_MINIX_SUBPARTITION is not set -++# CONFIG_SOLARIS_X86_PARTITION is not set -++# CONFIG_UNIXWARE_DISKLABEL is not set -++# CONFIG_LDM_PARTITION is not set -++# CONFIG_SGI_PARTITION is not set -++# CONFIG_ULTRIX_PARTITION is not set -++# CONFIG_SUN_PARTITION is not set -++# CONFIG_KARMA_PARTITION is not set -++# CONFIG_EFI_PARTITION is not set -++# CONFIG_SYSV68_PARTITION is not set -++CONFIG_NLS=y -++CONFIG_NLS_DEFAULT="iso8859-1" -++CONFIG_NLS_CODEPAGE_437=y -++# CONFIG_NLS_CODEPAGE_737 is not set -++# CONFIG_NLS_CODEPAGE_775 is not set -++# CONFIG_NLS_CODEPAGE_850 is not set -++# CONFIG_NLS_CODEPAGE_852 is not set -++# CONFIG_NLS_CODEPAGE_855 is not set -++# CONFIG_NLS_CODEPAGE_857 is not set -++# CONFIG_NLS_CODEPAGE_860 is not set -++# CONFIG_NLS_CODEPAGE_861 is not set -++# CONFIG_NLS_CODEPAGE_862 is not set -++# CONFIG_NLS_CODEPAGE_863 is not set -++# CONFIG_NLS_CODEPAGE_864 is not set -++# CONFIG_NLS_CODEPAGE_865 is not set -++# CONFIG_NLS_CODEPAGE_866 is not set -++# CONFIG_NLS_CODEPAGE_869 is not set -++CONFIG_NLS_CODEPAGE_936=y -++# CONFIG_NLS_CODEPAGE_950 is not set -++# CONFIG_NLS_CODEPAGE_932 is not set -++# CONFIG_NLS_CODEPAGE_949 is not set -++# CONFIG_NLS_CODEPAGE_874 is not set -++# CONFIG_NLS_ISO8859_8 is not set -++# CONFIG_NLS_CODEPAGE_1250 is not set -++# CONFIG_NLS_CODEPAGE_1251 is not set -++CONFIG_NLS_ASCII=y -++CONFIG_NLS_ISO8859_1=y -++# CONFIG_NLS_ISO8859_2 is not set -++# CONFIG_NLS_ISO8859_3 is not set -++# CONFIG_NLS_ISO8859_4 is not set -++# CONFIG_NLS_ISO8859_5 is not set -++# CONFIG_NLS_ISO8859_6 is not set -++# CONFIG_NLS_ISO8859_7 is not set -++# CONFIG_NLS_ISO8859_9 is not set -++# CONFIG_NLS_ISO8859_13 is not set -++# CONFIG_NLS_ISO8859_14 is not set -++# CONFIG_NLS_ISO8859_15 is not set -++# CONFIG_NLS_KOI8_R is not set -++# CONFIG_NLS_KOI8_U is not set -++# CONFIG_NLS_UTF8 is not set -++# CONFIG_DLM is not set -++ -++# -++# Yaffs2 Filesystems -++# -++CONFIG_YAFFS_FS=y -++CONFIG_YAFFS_YAFFS1=y -++# CONFIG_YAFFS_DOES_ECC is not set -++CONFIG_YAFFS_YAFFS2=y -++CONFIG_YAFFS_AUTO_YAFFS2=y -++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set -++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set -++CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK=y -++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y -++CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10 -++CONFIG_INSTRUMENTATION=y -++# CONFIG_PROFILING is not set -++# CONFIG_MARKERS is not set -++ -++# -++# Kernel hacking -++# -++CONFIG_TRACE_IRQFLAGS_SUPPORT=y -++# CONFIG_PRINTK_TIME is not set -++CONFIG_ENABLE_WARN_DEPRECATED=y -++CONFIG_ENABLE_MUST_CHECK=y -++CONFIG_MAGIC_SYSRQ=y -++# CONFIG_UNUSED_SYMBOLS is not set -++# CONFIG_DEBUG_FS is not set -++# CONFIG_HEADERS_CHECK is not set -++# CONFIG_DEBUG_KERNEL is not set -++# CONFIG_SAMPLES is not set -++CONFIG_CMDLINE="" -++ -++# -++# Security options -++# -++# CONFIG_KEYS is not set -++# CONFIG_SECURITY is not set -++# CONFIG_SECURITY_FILE_CAPABILITIES is not set -++CONFIG_CRYPTO=y -++CONFIG_CRYPTO_ALGAPI=y -++CONFIG_CRYPTO_BLKCIPHER=y -++CONFIG_CRYPTO_MANAGER=y -++# CONFIG_CRYPTO_HMAC is not set -++# CONFIG_CRYPTO_XCBC is not set -++# CONFIG_CRYPTO_NULL is not set -++# CONFIG_CRYPTO_MD4 is not set -++CONFIG_CRYPTO_MD5=y -++# CONFIG_CRYPTO_SHA1 is not set -++# CONFIG_CRYPTO_SHA256 is not set -++# CONFIG_CRYPTO_SHA512 is not set -++# CONFIG_CRYPTO_WP512 is not set -++# CONFIG_CRYPTO_TGR192 is not set -++# CONFIG_CRYPTO_GF128MUL is not set -++# CONFIG_CRYPTO_ECB is not set -++CONFIG_CRYPTO_CBC=y -++# CONFIG_CRYPTO_PCBC is not set -++# CONFIG_CRYPTO_LRW is not set -++# CONFIG_CRYPTO_XTS is not set -++# CONFIG_CRYPTO_CRYPTD is not set -++CONFIG_CRYPTO_DES=y -++# CONFIG_CRYPTO_FCRYPT is not set -++# CONFIG_CRYPTO_BLOWFISH is not set -++# CONFIG_CRYPTO_TWOFISH is not set -++# CONFIG_CRYPTO_SERPENT is not set -++# CONFIG_CRYPTO_AES is not set -++# CONFIG_CRYPTO_CAST5 is not set -++# CONFIG_CRYPTO_CAST6 is not set -++# CONFIG_CRYPTO_TEA is not set -++# CONFIG_CRYPTO_ARC4 is not set -++# CONFIG_CRYPTO_KHAZAD is not set -++# CONFIG_CRYPTO_ANUBIS is not set -++# CONFIG_CRYPTO_SEED is not set -++# CONFIG_CRYPTO_DEFLATE is not set -++# CONFIG_CRYPTO_MICHAEL_MIC is not set -++# CONFIG_CRYPTO_CRC32C is not set -++# CONFIG_CRYPTO_CAMELLIA is not set -++# CONFIG_CRYPTO_TEST is not set -++# CONFIG_CRYPTO_AUTHENC is not set -++# CONFIG_CRYPTO_LZO is not set -++CONFIG_CRYPTO_HW=y -++ -++# -++# Library routines -++# -++CONFIG_BITREVERSE=y -++# CONFIG_CRC_CCITT is not set -++# CONFIG_CRC16 is not set -++# CONFIG_CRC_ITU_T is not set -++CONFIG_CRC32=y -++# CONFIG_CRC7 is not set -++# CONFIG_LIBCRC32C is not set -++CONFIG_PLIST=y -++CONFIG_HAS_IOMEM=y -++CONFIG_HAS_IOPORT=y -++CONFIG_HAS_DMA=y -+diff -urN linux-2.6.24.7.old/arch/mips/configs/leo_defconfig linux-2.6.24.7/arch/mips/configs/leo_defconfig -+--- linux-2.6.24.7.old/arch/mips/configs/leo_defconfig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/configs/leo_defconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1256 @@ -++# -++# Automatically generated make config: don't edit -++# Linux kernel version: 2.6.24.3 -++# Thu Jun 12 13:59:18 2008 -++# -++CONFIG_MIPS=y -++ -++# -++# Machine selection -++# -++# CONFIG_JZ4730_PMP is not set -++# CONFIG_JZ4740_PAVO is not set -++CONFIG_JZ4740_LEO=y -++# CONFIG_JZ4740_LYRA is not set -++# CONFIG_JZ4725_DIPPER is not set -++# CONFIG_JZ4720_VIRGO is not set -++# CONFIG_JZ4750_FUWA is not set -++# CONFIG_MACH_ALCHEMY is not set -++# CONFIG_BASLER_EXCITE is not set -++# CONFIG_BCM47XX is not set -++# CONFIG_MIPS_COBALT is not set -++# CONFIG_MACH_DECSTATION is not set -++# CONFIG_MACH_JAZZ is not set -++# CONFIG_LASAT is not set -++# CONFIG_LEMOTE_FULONG is not set -++# CONFIG_MIPS_ATLAS is not set -++# CONFIG_MIPS_MALTA is not set -++# CONFIG_MIPS_SEAD is not set -++# CONFIG_MIPS_SIM is not set -++# CONFIG_MARKEINS is not set -++# CONFIG_MACH_VR41XX is not set -++# CONFIG_PNX8550_JBS is not set -++# CONFIG_PNX8550_STB810 is not set -++# CONFIG_PMC_MSP is not set -++# CONFIG_PMC_YOSEMITE is not set -++# CONFIG_QEMU is not set -++# CONFIG_SGI_IP22 is not set -++# CONFIG_SGI_IP27 is not set -++# CONFIG_SGI_IP32 is not set -++# CONFIG_SIBYTE_CRHINE is not set -++# CONFIG_SIBYTE_CARMEL is not set -++# CONFIG_SIBYTE_CRHONE is not set -++# CONFIG_SIBYTE_RHONE is not set -++# CONFIG_SIBYTE_SWARM is not set -++# CONFIG_SIBYTE_LITTLESUR is not set -++# CONFIG_SIBYTE_SENTOSA is not set -++# CONFIG_SIBYTE_PTSWARM is not set -++# CONFIG_SIBYTE_BIGSUR is not set -++# CONFIG_SNI_RM is not set -++# CONFIG_TOSHIBA_JMR3927 is not set -++# CONFIG_TOSHIBA_RBTX4927 is not set -++# CONFIG_TOSHIBA_RBTX4938 is not set -++# CONFIG_WR_PPMC is not set -++CONFIG_SOC_JZ4740=y -++CONFIG_JZSOC=y -++CONFIG_JZRISC=y -++CONFIG_RWSEM_GENERIC_SPINLOCK=y -++# CONFIG_ARCH_HAS_ILOG2_U32 is not set -++# CONFIG_ARCH_HAS_ILOG2_U64 is not set -++CONFIG_ARCH_SUPPORTS_OPROFILE=y -++CONFIG_GENERIC_FIND_NEXT_BIT=y -++CONFIG_GENERIC_HWEIGHT=y -++CONFIG_GENERIC_CALIBRATE_DELAY=y -++CONFIG_GENERIC_CLOCKEVENTS=y -++CONFIG_GENERIC_TIME=y -++CONFIG_GENERIC_CMOS_UPDATE=y -++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -++# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set -++CONFIG_DMA_NONCOHERENT=y -++CONFIG_DMA_NEED_PCI_MAP_STATE=y -++# CONFIG_HOTPLUG_CPU is not set -++# CONFIG_NO_IOPORT is not set -++# CONFIG_CPU_BIG_ENDIAN is not set -++CONFIG_CPU_LITTLE_ENDIAN=y -++CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -++CONFIG_MIPS_L1_CACHE_SHIFT=5 -++ -++# -++# CPU selection -++# -++# CONFIG_CPU_LOONGSON2 is not set -++CONFIG_CPU_MIPS32_R1=y -++# CONFIG_CPU_MIPS32_R2 is not set -++# CONFIG_CPU_MIPS64_R1 is not set -++# CONFIG_CPU_MIPS64_R2 is not set -++# CONFIG_CPU_R3000 is not set -++# CONFIG_CPU_TX39XX is not set -++# CONFIG_CPU_VR41XX is not set -++# CONFIG_CPU_R4300 is not set -++# CONFIG_CPU_R4X00 is not set -++# CONFIG_CPU_TX49XX is not set -++# CONFIG_CPU_R5000 is not set -++# CONFIG_CPU_R5432 is not set -++# CONFIG_CPU_R6000 is not set -++# CONFIG_CPU_NEVADA is not set -++# CONFIG_CPU_R8000 is not set -++# CONFIG_CPU_R10000 is not set -++# CONFIG_CPU_RM7000 is not set -++# CONFIG_CPU_RM9000 is not set -++# CONFIG_CPU_SB1 is not set -++CONFIG_SYS_HAS_CPU_MIPS32_R1=y -++CONFIG_CPU_MIPS32=y -++CONFIG_CPU_MIPSR1=y -++CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -++CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -++ -++# -++# Kernel type -++# -++CONFIG_32BIT=y -++# CONFIG_64BIT is not set -++CONFIG_PAGE_SIZE_4KB=y -++# CONFIG_PAGE_SIZE_8KB is not set -++# CONFIG_PAGE_SIZE_16KB is not set -++# CONFIG_PAGE_SIZE_64KB is not set -++CONFIG_CPU_HAS_PREFETCH=y -++CONFIG_MIPS_MT_DISABLED=y -++# CONFIG_MIPS_MT_SMP is not set -++# CONFIG_MIPS_MT_SMTC is not set -++CONFIG_CPU_HAS_LLSC=y -++CONFIG_CPU_HAS_SYNC=y -++CONFIG_GENERIC_HARDIRQS=y -++CONFIG_GENERIC_IRQ_PROBE=y -++CONFIG_CPU_SUPPORTS_HIGHMEM=y -++CONFIG_ARCH_FLATMEM_ENABLE=y -++CONFIG_ARCH_POPULATES_NODE_MAP=y -++CONFIG_SELECT_MEMORY_MODEL=y -++CONFIG_FLATMEM_MANUAL=y -++# CONFIG_DISCONTIGMEM_MANUAL is not set -++# CONFIG_SPARSEMEM_MANUAL is not set -++CONFIG_FLATMEM=y -++CONFIG_FLAT_NODE_MEM_MAP=y -++# CONFIG_SPARSEMEM_STATIC is not set -++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -++CONFIG_SPLIT_PTLOCK_CPUS=4 -++# CONFIG_RESOURCES_64BIT is not set -++CONFIG_ZONE_DMA_FLAG=0 -++CONFIG_VIRT_TO_BUS=y -++# CONFIG_TICK_ONESHOT is not set -++# CONFIG_NO_HZ is not set -++# CONFIG_HIGH_RES_TIMERS is not set -++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -++# CONFIG_HZ_48 is not set -++CONFIG_HZ_100=y -++# CONFIG_HZ_128 is not set -++# CONFIG_HZ_250 is not set -++# CONFIG_HZ_256 is not set -++# CONFIG_HZ_1000 is not set -++# CONFIG_HZ_1024 is not set -++CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -++CONFIG_HZ=100 -++# CONFIG_PREEMPT_NONE is not set -++# CONFIG_PREEMPT_VOLUNTARY is not set -++CONFIG_PREEMPT=y -++CONFIG_PREEMPT_BKL=y -++# CONFIG_KEXEC is not set -++CONFIG_SECCOMP=y -++CONFIG_LOCKDEP_SUPPORT=y -++CONFIG_STACKTRACE_SUPPORT=y -++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -++ -++# -++# General setup -++# -++CONFIG_EXPERIMENTAL=y -++CONFIG_BROKEN_ON_SMP=y -++CONFIG_LOCK_KERNEL=y -++CONFIG_INIT_ENV_ARG_LIMIT=32 -++CONFIG_LOCALVERSION="" -++CONFIG_LOCALVERSION_AUTO=y -++CONFIG_SWAP=y -++CONFIG_SYSVIPC=y -++CONFIG_SYSVIPC_SYSCTL=y -++# CONFIG_POSIX_MQUEUE is not set -++# CONFIG_BSD_PROCESS_ACCT is not set -++# CONFIG_TASKSTATS is not set -++# CONFIG_USER_NS is not set -++# CONFIG_PID_NS is not set -++# CONFIG_AUDIT is not set -++# CONFIG_IKCONFIG is not set -++CONFIG_LOG_BUF_SHIFT=14 -++# CONFIG_CGROUPS is not set -++CONFIG_FAIR_GROUP_SCHED=y -++CONFIG_FAIR_USER_SCHED=y -++# CONFIG_FAIR_CGROUP_SCHED is not set -++CONFIG_SYSFS_DEPRECATED=y -++CONFIG_RELAY=y -++# CONFIG_BLK_DEV_INITRD is not set -++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -++CONFIG_SYSCTL=y -++CONFIG_EMBEDDED=y -++CONFIG_SYSCTL_SYSCALL=y -++CONFIG_KALLSYMS=y -++CONFIG_KALLSYMS_ALL=y -++# CONFIG_KALLSYMS_EXTRA_PASS is not set -++CONFIG_HOTPLUG=y -++CONFIG_PRINTK=y -++CONFIG_BUG=y -++CONFIG_ELF_CORE=y -++CONFIG_BASE_FULL=y -++CONFIG_FUTEX=y -++CONFIG_ANON_INODES=y -++CONFIG_EPOLL=y -++CONFIG_SIGNALFD=y -++CONFIG_EVENTFD=y -++CONFIG_SHMEM=y -++CONFIG_VM_EVENT_COUNTERS=y -++CONFIG_SLAB=y -++# CONFIG_SLUB is not set -++# CONFIG_SLOB is not set -++CONFIG_SLABINFO=y -++CONFIG_RT_MUTEXES=y -++# CONFIG_TINY_SHMEM is not set -++CONFIG_BASE_SMALL=0 -++CONFIG_MODULES=y -++CONFIG_MODULE_UNLOAD=y -++# CONFIG_MODULE_FORCE_UNLOAD is not set -++CONFIG_MODVERSIONS=y -++CONFIG_MODULE_SRCVERSION_ALL=y -++CONFIG_KMOD=y -++CONFIG_BLOCK=y -++# CONFIG_LBD is not set -++# CONFIG_BLK_DEV_IO_TRACE is not set -++# CONFIG_LSF is not set -++# CONFIG_BLK_DEV_BSG is not set -++ -++# -++# IO Schedulers -++# -++CONFIG_IOSCHED_NOOP=y -++CONFIG_IOSCHED_AS=y -++CONFIG_IOSCHED_DEADLINE=y -++CONFIG_IOSCHED_CFQ=y -++CONFIG_DEFAULT_AS=y -++# CONFIG_DEFAULT_DEADLINE is not set -++# CONFIG_DEFAULT_CFQ is not set -++# CONFIG_DEFAULT_NOOP is not set -++CONFIG_DEFAULT_IOSCHED="anticipatory" -++ -++# -++# Bus options (PCI, PCMCIA, EISA, ISA, TC) -++# -++# CONFIG_ARCH_SUPPORTS_MSI is not set -++CONFIG_MMU=y -++# CONFIG_PCCARD is not set -++ -++# -++# Executable file formats -++# -++CONFIG_BINFMT_ELF=y -++# CONFIG_BINFMT_MISC is not set -++CONFIG_TRAD_SIGNALS=y -++ -++# -++# CPU Frequency scaling -++# -++CONFIG_CPU_FREQ_JZ=y -++CONFIG_CPU_FREQ=y -++CONFIG_CPU_FREQ_TABLE=y -++# CONFIG_CPU_FREQ_DEBUG is not set -++CONFIG_CPU_FREQ_STAT=y -++# CONFIG_CPU_FREQ_STAT_DETAILS is not set -++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -++CONFIG_CPU_FREQ_GOV_USERSPACE=y -++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set -++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -++ -++# -++# Power management options -++# -++CONFIG_PM=y -++CONFIG_PM_LEGACY=y -++# CONFIG_PM_DEBUG is not set -++CONFIG_SUSPEND_UP_POSSIBLE=y -++# CONFIG_SUSPEND is not set -++ -++# -++# Networking -++# -++CONFIG_NET=y -++ -++# -++# Networking options -++# -++CONFIG_PACKET=y -++# CONFIG_PACKET_MMAP is not set -++CONFIG_UNIX=y -++# CONFIG_NET_KEY is not set -++CONFIG_INET=y -++# CONFIG_IP_MULTICAST is not set -++# CONFIG_IP_ADVANCED_ROUTER is not set -++CONFIG_IP_FIB_HASH=y -++CONFIG_IP_PNP=y -++CONFIG_IP_PNP_DHCP=y -++CONFIG_IP_PNP_BOOTP=y -++# CONFIG_IP_PNP_RARP is not set -++# CONFIG_NET_IPIP is not set -++# CONFIG_NET_IPGRE is not set -++# CONFIG_ARPD is not set -++# CONFIG_SYN_COOKIES is not set -++# CONFIG_INET_AH is not set -++# CONFIG_INET_ESP is not set -++# CONFIG_INET_IPCOMP is not set -++# CONFIG_INET_XFRM_TUNNEL is not set -++# CONFIG_INET_TUNNEL is not set -++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -++# CONFIG_INET_XFRM_MODE_TUNNEL is not set -++# CONFIG_INET_XFRM_MODE_BEET is not set -++# CONFIG_INET_LRO is not set -++# CONFIG_INET_DIAG is not set -++# CONFIG_TCP_CONG_ADVANCED is not set -++CONFIG_TCP_CONG_CUBIC=y -++CONFIG_DEFAULT_TCP_CONG="cubic" -++# CONFIG_TCP_MD5SIG is not set -++# CONFIG_IPV6 is not set -++# CONFIG_INET6_XFRM_TUNNEL is not set -++# CONFIG_INET6_TUNNEL is not set -++# CONFIG_NETWORK_SECMARK is not set -++# CONFIG_NETFILTER is not set -++# CONFIG_IP_DCCP is not set -++# CONFIG_IP_SCTP is not set -++# CONFIG_TIPC is not set -++# CONFIG_ATM is not set -++# CONFIG_BRIDGE is not set -++# CONFIG_VLAN_8021Q is not set -++# CONFIG_DECNET is not set -++# CONFIG_LLC2 is not set -++# CONFIG_IPX is not set -++# CONFIG_ATALK is not set -++# CONFIG_X25 is not set -++# CONFIG_LAPB is not set -++# CONFIG_ECONET is not set -++# CONFIG_WAN_ROUTER is not set -++# CONFIG_NET_SCHED is not set -++ -++# -++# Network testing -++# -++# CONFIG_NET_PKTGEN is not set -++# CONFIG_HAMRADIO is not set -++# CONFIG_IRDA is not set -++# CONFIG_BT is not set -++# CONFIG_AF_RXRPC is not set -++ -++# -++# Wireless -++# -++# CONFIG_CFG80211 is not set -++CONFIG_WIRELESS_EXT=y -++# CONFIG_MAC80211 is not set -++# CONFIG_IEEE80211 is not set -++# CONFIG_RFKILL is not set -++# CONFIG_NET_9P is not set -++ -++# -++# Device Drivers -++# -++ -++# -++# Generic Driver Options -++# -++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -++CONFIG_STANDALONE=y -++CONFIG_PREVENT_FIRMWARE_BUILD=y -++# CONFIG_FW_LOADER is not set -++# CONFIG_SYS_HYPERVISOR is not set -++# CONFIG_CONNECTOR is not set -++CONFIG_MTD=y -++# CONFIG_MTD_DEBUG is not set -++CONFIG_MTD_CONCAT=y -++CONFIG_MTD_PARTITIONS=y -++# CONFIG_MTD_REDBOOT_PARTS is not set -++# CONFIG_MTD_CMDLINE_PARTS is not set -++ -++# -++# User Modules And Translation Layers -++# -++CONFIG_MTD_CHAR=y -++CONFIG_MTD_BLKDEVS=y -++CONFIG_MTD_BLOCK=y -++# CONFIG_FTL is not set -++# CONFIG_NFTL is not set -++# CONFIG_INFTL is not set -++# CONFIG_RFD_FTL is not set -++# CONFIG_SSFDC is not set -++# CONFIG_MTD_OOPS is not set -++ -++# -++# RAM/ROM/Flash chip drivers -++# -++# CONFIG_MTD_CFI is not set -++# CONFIG_MTD_JEDECPROBE is not set -++CONFIG_MTD_MAP_BANK_WIDTH_1=y -++CONFIG_MTD_MAP_BANK_WIDTH_2=y -++CONFIG_MTD_MAP_BANK_WIDTH_4=y -++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -++CONFIG_MTD_CFI_I1=y -++CONFIG_MTD_CFI_I2=y -++# CONFIG_MTD_CFI_I4 is not set -++# CONFIG_MTD_CFI_I8 is not set -++# CONFIG_MTD_RAM is not set -++# CONFIG_MTD_ROM is not set -++# CONFIG_MTD_ABSENT is not set -++ -++# -++# Mapping drivers for chip access -++# -++# CONFIG_MTD_COMPLEX_MAPPINGS is not set -++# CONFIG_MTD_PLATRAM is not set -++ -++# -++# Self-contained MTD device drivers -++# -++# CONFIG_MTD_SLRAM is not set -++# CONFIG_MTD_PHRAM is not set -++# CONFIG_MTD_MTDRAM is not set -++CONFIG_MTD_BLOCK2MTD=y -++ -++# -++# Disk-On-Chip Device Drivers -++# -++# CONFIG_MTD_DOC2000 is not set -++# CONFIG_MTD_DOC2001 is not set -++# CONFIG_MTD_DOC2001PLUS is not set -++CONFIG_MTD_NAND=y -++# CONFIG_MTD_NAND_VERIFY_WRITE is not set -++# CONFIG_MTD_NAND_ECC_SMC is not set -++# CONFIG_MTD_NAND_MUSEUM_IDS is not set -++CONFIG_MTD_NAND_IDS=y -++# CONFIG_MTD_NAND_DISKONCHIP is not set -++# CONFIG_MTD_NAND_NANDSIM is not set -++# CONFIG_MTD_NAND_PLATFORM is not set -++# CONFIG_MTD_ALAUDA is not set -++CONFIG_MTD_NAND_JZ4740=y -++# CONFIG_MTD_HW_HM_ECC is not set -++CONFIG_MTD_SW_HM_ECC=y -++# CONFIG_MTD_HW_RS_ECC is not set -++# CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE is not set -++CONFIG_MTD_OOB_COPIES=3 -++CONFIG_MTD_BADBLOCK_FLAG_PAGE=0 -++# CONFIG_MTD_ONENAND is not set -++ -++# -++# UBI - Unsorted block images -++# -++CONFIG_MTD_UBI=m -++CONFIG_MTD_UBI_WL_THRESHOLD=4096 -++CONFIG_MTD_UBI_BEB_RESERVE=1 -++# CONFIG_MTD_UBI_GLUEBI is not set -++ -++# -++# UBI debugging options -++# -++# CONFIG_MTD_UBI_DEBUG is not set -++CONFIG_MTD_UBI_BLKDEVS=m -++CONFIG_MTD_UBI_BLOCK=m -++# CONFIG_PARPORT is not set -++CONFIG_PNP=y -++# CONFIG_PNP_DEBUG is not set -++ -++# -++# Protocols -++# -++# CONFIG_PNPACPI is not set -++CONFIG_BLK_DEV=y -++# CONFIG_BLK_DEV_COW_COMMON is not set -++CONFIG_BLK_DEV_LOOP=y -++# CONFIG_BLK_DEV_CRYPTOLOOP is not set -++# CONFIG_BLK_DEV_NBD is not set -++# CONFIG_BLK_DEV_UB is not set -++CONFIG_BLK_DEV_RAM=y -++CONFIG_BLK_DEV_RAM_COUNT=2 -++CONFIG_BLK_DEV_RAM_SIZE=4096 -++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -++# CONFIG_CDROM_PKTCDVD is not set -++# CONFIG_ATA_OVER_ETH is not set -++CONFIG_MISC_DEVICES=y -++# CONFIG_EEPROM_93CX6 is not set -++# CONFIG_IDE is not set -++ -++# -++# SCSI device support -++# -++# CONFIG_RAID_ATTRS is not set -++CONFIG_SCSI=y -++CONFIG_SCSI_DMA=y -++# CONFIG_SCSI_TGT is not set -++# CONFIG_SCSI_NETLINK is not set -++CONFIG_SCSI_PROC_FS=y -++ -++# -++# SCSI support type (disk, tape, CD-ROM) -++# -++CONFIG_BLK_DEV_SD=y -++# CONFIG_CHR_DEV_ST is not set -++# CONFIG_CHR_DEV_OSST is not set -++# CONFIG_BLK_DEV_SR is not set -++# CONFIG_CHR_DEV_SG is not set -++# CONFIG_CHR_DEV_SCH is not set -++ -++# -++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -++# -++# CONFIG_SCSI_MULTI_LUN is not set -++# CONFIG_SCSI_CONSTANTS is not set -++# CONFIG_SCSI_LOGGING is not set -++# CONFIG_SCSI_SCAN_ASYNC is not set -++CONFIG_SCSI_WAIT_SCAN=m -++ -++# -++# SCSI Transports -++# -++# CONFIG_SCSI_SPI_ATTRS is not set -++# CONFIG_SCSI_FC_ATTRS is not set -++# CONFIG_SCSI_ISCSI_ATTRS is not set -++# CONFIG_SCSI_SAS_LIBSAS is not set -++# CONFIG_SCSI_SRP_ATTRS is not set -++CONFIG_SCSI_LOWLEVEL=y -++# CONFIG_ISCSI_TCP is not set -++# CONFIG_SCSI_DEBUG is not set -++# CONFIG_ATA is not set -++# CONFIG_MD is not set -++# CONFIG_NETDEVICES is not set -++# CONFIG_ISDN is not set -++# CONFIG_PHONE is not set -++ -++# -++# Input device support -++# -++CONFIG_INPUT=y -++# CONFIG_INPUT_FF_MEMLESS is not set -++# CONFIG_INPUT_POLLDEV is not set -++ -++# -++# Userland interfaces -++# -++CONFIG_INPUT_MOUSEDEV=y -++CONFIG_INPUT_MOUSEDEV_PSAUX=y -++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -++# CONFIG_INPUT_JOYDEV is not set -++CONFIG_INPUT_EVDEV=y -++# CONFIG_INPUT_EVBUG is not set -++ -++# -++# Input Device Drivers -++# -++# CONFIG_INPUT_KEYBOARD is not set -++# CONFIG_INPUT_MOUSE is not set -++# CONFIG_INPUT_JOYSTICK is not set -++# CONFIG_INPUT_TABLET is not set -++# CONFIG_INPUT_TOUCHSCREEN is not set -++# CONFIG_INPUT_MISC is not set -++ -++# -++# Hardware I/O ports -++# -++CONFIG_SERIO=y -++# CONFIG_SERIO_I8042 is not set -++CONFIG_SERIO_SERPORT=y -++# CONFIG_SERIO_LIBPS2 is not set -++# CONFIG_SERIO_RAW is not set -++# CONFIG_GAMEPORT is not set -++ -++# -++# Character devices -++# -++CONFIG_VT=y -++CONFIG_VT_CONSOLE=y -++CONFIG_HW_CONSOLE=y -++CONFIG_VT_HW_CONSOLE_BINDING=y -++# CONFIG_SERIAL_NONSTANDARD is not set -++ -++# -++# Serial drivers -++# -++CONFIG_SERIAL_8250=y -++CONFIG_SERIAL_8250_CONSOLE=y -++CONFIG_SERIAL_8250_PNP=y -++CONFIG_SERIAL_8250_NR_UARTS=2 -++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 -++# CONFIG_SERIAL_8250_EXTENDED is not set -++ -++# -++# Non-8250 serial port support -++# -++CONFIG_SERIAL_CORE=y -++CONFIG_SERIAL_CORE_CONSOLE=y -++CONFIG_UNIX98_PTYS=y -++CONFIG_LEGACY_PTYS=y -++CONFIG_LEGACY_PTY_COUNT=2 -++# CONFIG_IPMI_HANDLER is not set -++# CONFIG_HW_RANDOM is not set -++# CONFIG_RTC is not set -++# CONFIG_RTC_PCF8563 is not set -++CONFIG_RTC_JZ=y -++# CONFIG_R3964 is not set -++# CONFIG_RAW_DRIVER is not set -++# CONFIG_TCG_TPM is not set -++ -++# -++# JZSOC char device support -++# -++CONFIG_JZCHAR=y -++# CONFIG_JZ_CIM is not set -++# CONFIG_JZ_TPANEL_ATA2508 is not set -++CONFIG_JZ_TPANEL=y -++CONFIG_JZ_SADC=y -++# CONFIG_JZ_TPANEL_AK4182 is not set -++# CONFIG_JZ_TPANEL_UCB1400 is not set -++# CONFIG_JZ_TPANEL_WM9712 is not set -++CONFIG_JZ_UDC_HOTPLUG=y -++CONFIG_JZ_POWEROFF=y -++# CONFIG_JZ_OW is not set -++# CONFIG_I2C is not set -++ -++# -++# SPI support -++# -++# CONFIG_SPI is not set -++# CONFIG_SPI_MASTER is not set -++# CONFIG_W1 is not set -++# CONFIG_POWER_SUPPLY is not set -++# CONFIG_HWMON is not set -++CONFIG_WATCHDOG=y -++# CONFIG_WATCHDOG_NOWAYOUT is not set -++ -++# -++# Watchdog Device Drivers -++# -++CONFIG_JZ_WDT=y -++# CONFIG_SOFT_WATCHDOG is not set -++ -++# -++# USB-based Watchdog Cards -++# -++# CONFIG_USBPCWATCHDOG is not set -++ -++# -++# Sonics Silicon Backplane -++# -++CONFIG_SSB_POSSIBLE=y -++# CONFIG_SSB is not set -++ -++# -++# Multifunction device drivers -++# -++# CONFIG_MFD_SM501 is not set -++ -++# -++# Multimedia devices -++# -++CONFIG_VIDEO_DEV=y -++CONFIG_VIDEO_V4L1=y -++CONFIG_VIDEO_V4L1_COMPAT=y -++CONFIG_VIDEO_V4L2=y -++CONFIG_VIDEO_CAPTURE_DRIVERS=y -++# CONFIG_VIDEO_ADV_DEBUG is not set -++CONFIG_VIDEO_HELPER_CHIPS_AUTO=y -++# CONFIG_VIDEO_VIVI is not set -++# CONFIG_VIDEO_CPIA is not set -++# CONFIG_VIDEO_CPIA2 is not set -++CONFIG_VIDEO_JZ_CIM=y -++CONFIG_VIDEO_JZ_SENSOR=y -++CONFIG_V4L_USB_DRIVERS=y -++# CONFIG_USB_VICAM is not set -++# CONFIG_USB_IBMCAM is not set -++# CONFIG_USB_KONICAWC is not set -++# CONFIG_USB_QUICKCAM_MESSENGER is not set -++# CONFIG_USB_ET61X251 is not set -++# CONFIG_USB_OV511 is not set -++# CONFIG_USB_SE401 is not set -++# CONFIG_USB_SN9C102 is not set -++# CONFIG_USB_STV680 is not set -++# CONFIG_USB_ZC0301 is not set -++# CONFIG_USB_PWC is not set -++# CONFIG_USB_ZR364XX is not set -++CONFIG_RADIO_ADAPTERS=y -++# CONFIG_USB_DSBR is not set -++# CONFIG_DVB_CORE is not set -++# CONFIG_DAB is not set -++ -++# -++# Graphics support -++# -++# CONFIG_VGASTATE is not set -++# CONFIG_VIDEO_OUTPUT_CONTROL is not set -++CONFIG_FB=y -++# CONFIG_FIRMWARE_EDID is not set -++# CONFIG_FB_DDC is not set -++CONFIG_FB_CFB_FILLRECT=y -++CONFIG_FB_CFB_COPYAREA=y -++CONFIG_FB_CFB_IMAGEBLIT=y -++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -++# CONFIG_FB_SYS_FILLRECT is not set -++# CONFIG_FB_SYS_COPYAREA is not set -++# CONFIG_FB_SYS_IMAGEBLIT is not set -++# CONFIG_FB_SYS_FOPS is not set -++CONFIG_FB_DEFERRED_IO=y -++# CONFIG_FB_SVGALIB is not set -++# CONFIG_FB_MACMODES is not set -++# CONFIG_FB_BACKLIGHT is not set -++# CONFIG_FB_MODE_HELPERS is not set -++# CONFIG_FB_TILEBLITTING is not set -++ -++# -++# Frame buffer hardware drivers -++# -++CONFIG_FB_JZSOC=y -++# CONFIG_FB_JZ4740_SLCD is not set -++CONFIG_FB_JZLCD_4730_4740=y -++CONFIG_JZLCD_FRAMEBUFFER_MAX=1 -++# CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT is not set -++# CONFIG_JZLCD_SHARP_LQ035Q7 is not set -++# CONFIG_JZLCD_SAMSUNG_LTS350Q1 is not set -++# CONFIG_JZLCD_SAMSUNG_LTV350QVF04 is not set -++# CONFIG_JZLCD_SAMSUNG_LTP400WQF01 is not set -++CONFIG_JZLCD_SAMSUNG_LTP400WQF02=y -++# CONFIG_JZLCD_AUO_A030FL01_V1 is not set -++# CONFIG_JZLCD_TRULY_TFTG320240DTSW is not set -++# CONFIG_JZLCD_TRULY_TFTG320240DTSW_SERIAL is not set -++# CONFIG_JZLCD_TRULY_TFTG240320UTSW_63W_E is not set -++# CONFIG_JZLCD_FOXCONN_PT035TN01 is not set -++# CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL is not set -++# CONFIG_JZLCD_TOSHIBA_LTM084P363 is not set -++# CONFIG_JZLCD_HYNIX_HT10X21 is not set -++# CONFIG_JZLCD_INNOLUX_AT080TN42 is not set -++# CONFIG_JZLCD_CSTN_800x600 is not set -++# CONFIG_JZLCD_CSTN_320x240 is not set -++# CONFIG_JZLCD_MSTN_480x320 is not set -++# CONFIG_JZLCD_MSTN_320x240 is not set -++# CONFIG_JZLCD_MSTN_240x128 is not set -++# CONFIG_FB_S1D13XXX is not set -++# CONFIG_FB_VIRTUAL is not set -++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set -++ -++# -++# Display device support -++# -++# CONFIG_DISPLAY_SUPPORT is not set -++ -++# -++# Console display driver support -++# -++# CONFIG_VGA_CONSOLE is not set -++CONFIG_DUMMY_CONSOLE=y -++CONFIG_FRAMEBUFFER_CONSOLE=y -++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -++# CONFIG_FRAMEBUFFER_CONSOLE_CURSOR_FLASH is not set -++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -++CONFIG_FONTS=y -++CONFIG_FONT_8x8=y -++CONFIG_FONT_8x16=y -++# CONFIG_FONT_6x11 is not set -++# CONFIG_FONT_7x14 is not set -++# CONFIG_FONT_PEARL_8x8 is not set -++# CONFIG_FONT_ACORN_8x8 is not set -++# CONFIG_FONT_MINI_4x6 is not set -++# CONFIG_FONT_SUN8x16 is not set -++# CONFIG_FONT_SUN12x22 is not set -++# CONFIG_FONT_10x18 is not set -++CONFIG_LOGO=y -++CONFIG_LOGO_LINUX_MONO=y -++CONFIG_LOGO_LINUX_VGA16=y -++CONFIG_LOGO_LINUX_CLUT224=y -++ -++# -++# Sound -++# -++CONFIG_SOUND=y -++ -++# -++# Advanced Linux Sound Architecture -++# -++CONFIG_SND=y -++CONFIG_SND_TIMER=y -++CONFIG_SND_PCM=y -++# CONFIG_SND_SEQUENCER is not set -++CONFIG_SND_OSSEMUL=y -++CONFIG_SND_MIXER_OSS=y -++CONFIG_SND_PCM_OSS=y -++CONFIG_SND_PCM_OSS_PLUGINS=y -++# CONFIG_SND_DYNAMIC_MINORS is not set -++CONFIG_SND_SUPPORT_OLD_API=y -++CONFIG_SND_VERBOSE_PROCFS=y -++# CONFIG_SND_VERBOSE_PRINTK is not set -++# CONFIG_SND_DEBUG is not set -++ -++# -++# Generic devices -++# -++# CONFIG_SND_DUMMY is not set -++# CONFIG_SND_MTPAV is not set -++# CONFIG_SND_SERIAL_U16550 is not set -++# CONFIG_SND_MPU401 is not set -++ -++# -++# ALSA MIPS devices -++# -++ -++# -++# USB devices -++# -++# CONFIG_SND_USB_AUDIO is not set -++# CONFIG_SND_USB_CAIAQ is not set -++ -++# -++# System on Chip audio support -++# -++CONFIG_SND_SOC=y -++ -++# -++# SoC Audio support for SuperH -++# -++ -++# -++# Open Sound System -++# -++# CONFIG_SOUND_PRIME is not set -++CONFIG_HID_SUPPORT=y -++CONFIG_HID=y -++# CONFIG_HID_DEBUG is not set -++# CONFIG_HIDRAW is not set -++ -++# -++# USB Input Devices -++# -++CONFIG_USB_HID=y -++# CONFIG_USB_HIDINPUT_POWERBOOK is not set -++# CONFIG_HID_FF is not set -++# CONFIG_USB_HIDDEV is not set -++CONFIG_USB_SUPPORT=y -++CONFIG_USB_ARCH_HAS_HCD=y -++CONFIG_USB_ARCH_HAS_OHCI=y -++# CONFIG_USB_ARCH_HAS_EHCI is not set -++CONFIG_USB=y -++# CONFIG_USB_DEBUG is not set -++ -++# -++# Miscellaneous USB options -++# -++# CONFIG_USB_DEVICEFS is not set -++CONFIG_USB_DEVICE_CLASS=y -++# CONFIG_USB_DYNAMIC_MINORS is not set -++# CONFIG_USB_SUSPEND is not set -++# CONFIG_USB_PERSIST is not set -++# CONFIG_USB_OTG is not set -++ -++# -++# USB Host Controller Drivers -++# -++# CONFIG_USB_ISP116X_HCD is not set -++CONFIG_USB_OHCI_HCD=y -++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set -++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set -++CONFIG_USB_OHCI_LITTLE_ENDIAN=y -++# CONFIG_USB_SL811_HCD is not set -++# CONFIG_USB_R8A66597_HCD is not set -++ -++# -++# USB Device Class drivers -++# -++# CONFIG_USB_ACM is not set -++# CONFIG_USB_PRINTER is not set -++ -++# -++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -++# -++ -++# -++# may also be needed; see USB_STORAGE Help for more information -++# -++CONFIG_USB_STORAGE=y -++# CONFIG_USB_STORAGE_DEBUG is not set -++# CONFIG_USB_STORAGE_DATAFAB is not set -++# CONFIG_USB_STORAGE_FREECOM is not set -++# CONFIG_USB_STORAGE_ISD200 is not set -++# CONFIG_USB_STORAGE_DPCM is not set -++# CONFIG_USB_STORAGE_USBAT is not set -++# CONFIG_USB_STORAGE_SDDR09 is not set -++# CONFIG_USB_STORAGE_SDDR55 is not set -++# CONFIG_USB_STORAGE_JUMPSHOT is not set -++# CONFIG_USB_STORAGE_ALAUDA is not set -++# CONFIG_USB_STORAGE_KARMA is not set -++# CONFIG_USB_LIBUSUAL is not set -++ -++# -++# USB Imaging devices -++# -++# CONFIG_USB_MDC800 is not set -++# CONFIG_USB_MICROTEK is not set -++CONFIG_USB_MON=y -++ -++# -++# USB port drivers -++# -++ -++# -++# USB Serial Converter support -++# -++# CONFIG_USB_SERIAL is not set -++ -++# -++# USB Miscellaneous drivers -++# -++# CONFIG_USB_EMI62 is not set -++# CONFIG_USB_EMI26 is not set -++# CONFIG_USB_ADUTUX is not set -++# CONFIG_USB_AUERSWALD is not set -++# CONFIG_USB_RIO500 is not set -++# CONFIG_USB_LEGOTOWER is not set -++# CONFIG_USB_LCD is not set -++# CONFIG_USB_BERRY_CHARGE is not set -++# CONFIG_USB_LED is not set -++# CONFIG_USB_CYPRESS_CY7C63 is not set -++# CONFIG_USB_CYTHERM is not set -++# CONFIG_USB_PHIDGET is not set -++# CONFIG_USB_IDMOUSE is not set -++# CONFIG_USB_FTDI_ELAN is not set -++# CONFIG_USB_APPLEDISPLAY is not set -++# CONFIG_USB_LD is not set -++# CONFIG_USB_TRANCEVIBRATOR is not set -++# CONFIG_USB_IOWARRIOR is not set -++ -++# -++# USB DSL modem support -++# -++ -++# -++# USB Gadget Support -++# -++CONFIG_USB_GADGET=m -++# CONFIG_USB_GADGET_DEBUG_FILES is not set -++# CONFIG_USB_GADGET_DEBUG_FS is not set -++CONFIG_USB_GADGET_SELECTED=y -++CONFIG_USB_GADGET_JZ4740=y -++CONFIG_USB_JZ4740=m -++# CONFIG_USB_GADGET_JZ4730 is not set -++# CONFIG_USB_GADGET_AMD5536UDC is not set -++# CONFIG_USB_GADGET_ATMEL_USBA is not set -++# CONFIG_USB_GADGET_FSL_USB2 is not set -++# CONFIG_USB_GADGET_NET2280 is not set -++# CONFIG_USB_GADGET_PXA2XX is not set -++# CONFIG_USB_GADGET_M66592 is not set -++# CONFIG_USB_GADGET_GOKU is not set -++# CONFIG_USB_GADGET_LH7A40X is not set -++# CONFIG_USB_GADGET_OMAP is not set -++# CONFIG_USB_GADGET_S3C2410 is not set -++# CONFIG_USB_GADGET_AT91 is not set -++# CONFIG_USB_GADGET_DUMMY_HCD is not set -++CONFIG_USB_GADGET_DUALSPEED=y -++# CONFIG_USB_ZERO is not set -++# CONFIG_USB_ETH is not set -++# CONFIG_USB_GADGETFS is not set -++CONFIG_USB_FILE_STORAGE=m -++CONFIG_USB_FILE_STORAGE_TEST=y -++# CONFIG_USB_G_SERIAL is not set -++# CONFIG_USB_MIDI_GADGET is not set -++CONFIG_MMC=y -++# CONFIG_MMC_DEBUG is not set -++# CONFIG_MMC_UNSAFE_RESUME is not set -++ -++# -++# MMC/SD Card Drivers -++# -++CONFIG_MMC_BLOCK=y -++CONFIG_MMC_BLOCK_BOUNCE=y -++# CONFIG_SDIO_UART is not set -++ -++# -++# MMC/SD Host Controller Drivers -++# -++CONFIG_MMC_JZ=y -++CONFIG_JZ_MMC_BUS_4=y -++# CONFIG_JZ_MMC_BUS_1 is not set -++# CONFIG_NEW_LEDS is not set -++CONFIG_RTC_LIB=y -++# CONFIG_RTC_CLASS is not set -++ -++# -++# Userspace I/O -++# -++# CONFIG_UIO is not set -++ -++# -++# File systems -++# -++CONFIG_EXT2_FS=y -++CONFIG_EXT2_FS_XATTR=y -++# CONFIG_EXT2_FS_POSIX_ACL is not set -++# CONFIG_EXT2_FS_SECURITY is not set -++# CONFIG_EXT2_FS_XIP is not set -++# CONFIG_EXT3_FS is not set -++# CONFIG_EXT4DEV_FS is not set -++CONFIG_FS_MBCACHE=y -++# CONFIG_REISERFS_FS is not set -++# CONFIG_JFS_FS is not set -++CONFIG_FS_POSIX_ACL=y -++# CONFIG_XFS_FS is not set -++# CONFIG_GFS2_FS is not set -++# CONFIG_OCFS2_FS is not set -++CONFIG_MINIX_FS=y -++# CONFIG_ROMFS_FS is not set -++CONFIG_INOTIFY=y -++CONFIG_INOTIFY_USER=y -++# CONFIG_QUOTA is not set -++CONFIG_DNOTIFY=y -++# CONFIG_AUTOFS_FS is not set -++# CONFIG_AUTOFS4_FS is not set -++# CONFIG_FUSE_FS is not set -++ -++# -++# CD-ROM/DVD Filesystems -++# -++# CONFIG_ISO9660_FS is not set -++# CONFIG_UDF_FS is not set -++ -++# -++# DOS/FAT/NT Filesystems -++# -++CONFIG_FAT_FS=y -++CONFIG_MSDOS_FS=y -++CONFIG_VFAT_FS=y -++CONFIG_FAT_DEFAULT_CODEPAGE=437 -++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -++# CONFIG_NTFS_FS is not set -++ -++# -++# Pseudo filesystems -++# -++CONFIG_PROC_FS=y -++CONFIG_PROC_KCORE=y -++CONFIG_PROC_SYSCTL=y -++CONFIG_SYSFS=y -++CONFIG_TMPFS=y -++# CONFIG_TMPFS_POSIX_ACL is not set -++# CONFIG_HUGETLB_PAGE is not set -++# CONFIG_CONFIGFS_FS is not set -++ -++# -++# Miscellaneous filesystems -++# -++# CONFIG_ADFS_FS is not set -++# CONFIG_AFFS_FS is not set -++# CONFIG_HFS_FS is not set -++# CONFIG_HFSPLUS_FS is not set -++# CONFIG_BEFS_FS is not set -++# CONFIG_BFS_FS is not set -++# CONFIG_EFS_FS is not set -++# CONFIG_JFFS2_FS is not set -++CONFIG_UBIFS_FS=m -++# CONFIG_UBIFS_FS_XATTR is not set -++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set -++CONFIG_UBIFS_FS_LZO=y -++CONFIG_UBIFS_FS_ZLIB=y -++CONFIG_UBIFS_FS_DEBUG=y -++CONFIG_UBIFS_FS_DEBUG_MSG_LVL=0 -++# CONFIG_UBIFS_FS_DEBUG_CHKS is not set -++# CONFIG_CRAMFS is not set -++# CONFIG_VXFS_FS is not set -++# CONFIG_HPFS_FS is not set -++# CONFIG_QNX4FS_FS is not set -++# CONFIG_SYSV_FS is not set -++# CONFIG_UFS_FS is not set -++CONFIG_NETWORK_FILESYSTEMS=y -++CONFIG_NFS_FS=y -++CONFIG_NFS_V3=y -++CONFIG_NFS_V3_ACL=y -++CONFIG_NFS_V4=y -++CONFIG_NFS_DIRECTIO=y -++# CONFIG_NFSD is not set -++CONFIG_ROOT_NFS=y -++CONFIG_LOCKD=y -++CONFIG_LOCKD_V4=y -++CONFIG_NFS_ACL_SUPPORT=y -++CONFIG_NFS_COMMON=y -++CONFIG_SUNRPC=y -++CONFIG_SUNRPC_GSS=y -++# CONFIG_SUNRPC_BIND34 is not set -++CONFIG_RPCSEC_GSS_KRB5=y -++# CONFIG_RPCSEC_GSS_SPKM3 is not set -++# CONFIG_SMB_FS is not set -++# CONFIG_CIFS is not set -++# CONFIG_NCP_FS is not set -++# CONFIG_CODA_FS is not set -++# CONFIG_AFS_FS is not set -++ -++# -++# Partition Types -++# -++CONFIG_PARTITION_ADVANCED=y -++# CONFIG_ACORN_PARTITION is not set -++# CONFIG_OSF_PARTITION is not set -++# CONFIG_AMIGA_PARTITION is not set -++# CONFIG_ATARI_PARTITION is not set -++# CONFIG_MAC_PARTITION is not set -++CONFIG_MSDOS_PARTITION=y -++# CONFIG_BSD_DISKLABEL is not set -++# CONFIG_MINIX_SUBPARTITION is not set -++# CONFIG_SOLARIS_X86_PARTITION is not set -++# CONFIG_UNIXWARE_DISKLABEL is not set -++# CONFIG_LDM_PARTITION is not set -++# CONFIG_SGI_PARTITION is not set -++# CONFIG_ULTRIX_PARTITION is not set -++# CONFIG_SUN_PARTITION is not set -++# CONFIG_KARMA_PARTITION is not set -++# CONFIG_EFI_PARTITION is not set -++# CONFIG_SYSV68_PARTITION is not set -++CONFIG_NLS=y -++CONFIG_NLS_DEFAULT="iso8859-1" -++CONFIG_NLS_CODEPAGE_437=y -++# CONFIG_NLS_CODEPAGE_737 is not set -++# CONFIG_NLS_CODEPAGE_775 is not set -++# CONFIG_NLS_CODEPAGE_850 is not set -++# CONFIG_NLS_CODEPAGE_852 is not set -++# CONFIG_NLS_CODEPAGE_855 is not set -++# CONFIG_NLS_CODEPAGE_857 is not set -++# CONFIG_NLS_CODEPAGE_860 is not set -++# CONFIG_NLS_CODEPAGE_861 is not set -++# CONFIG_NLS_CODEPAGE_862 is not set -++# CONFIG_NLS_CODEPAGE_863 is not set -++# CONFIG_NLS_CODEPAGE_864 is not set -++# CONFIG_NLS_CODEPAGE_865 is not set -++# CONFIG_NLS_CODEPAGE_866 is not set -++# CONFIG_NLS_CODEPAGE_869 is not set -++CONFIG_NLS_CODEPAGE_936=y -++# CONFIG_NLS_CODEPAGE_950 is not set -++# CONFIG_NLS_CODEPAGE_932 is not set -++# CONFIG_NLS_CODEPAGE_949 is not set -++# CONFIG_NLS_CODEPAGE_874 is not set -++# CONFIG_NLS_ISO8859_8 is not set -++# CONFIG_NLS_CODEPAGE_1250 is not set -++# CONFIG_NLS_CODEPAGE_1251 is not set -++CONFIG_NLS_ASCII=y -++CONFIG_NLS_ISO8859_1=y -++# CONFIG_NLS_ISO8859_2 is not set -++# CONFIG_NLS_ISO8859_3 is not set -++# CONFIG_NLS_ISO8859_4 is not set -++# CONFIG_NLS_ISO8859_5 is not set -++# CONFIG_NLS_ISO8859_6 is not set -++# CONFIG_NLS_ISO8859_7 is not set -++# CONFIG_NLS_ISO8859_9 is not set -++# CONFIG_NLS_ISO8859_13 is not set -++# CONFIG_NLS_ISO8859_14 is not set -++# CONFIG_NLS_ISO8859_15 is not set -++# CONFIG_NLS_KOI8_R is not set -++# CONFIG_NLS_KOI8_U is not set -++# CONFIG_NLS_UTF8 is not set -++# CONFIG_DLM is not set -++ -++# -++# Yaffs2 Filesystems -++# -++CONFIG_YAFFS_FS=y -++CONFIG_YAFFS_YAFFS1=y -++# CONFIG_YAFFS_DOES_ECC is not set -++CONFIG_YAFFS_YAFFS2=y -++CONFIG_YAFFS_AUTO_YAFFS2=y -++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set -++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set -++CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK=y -++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y -++CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10 -++CONFIG_INSTRUMENTATION=y -++# CONFIG_PROFILING is not set -++# CONFIG_MARKERS is not set -++ -++# -++# Kernel hacking -++# -++CONFIG_TRACE_IRQFLAGS_SUPPORT=y -++# CONFIG_PRINTK_TIME is not set -++CONFIG_ENABLE_WARN_DEPRECATED=y -++CONFIG_ENABLE_MUST_CHECK=y -++CONFIG_MAGIC_SYSRQ=y -++# CONFIG_UNUSED_SYMBOLS is not set -++CONFIG_DEBUG_FS=y -++# CONFIG_HEADERS_CHECK is not set -++# CONFIG_DEBUG_KERNEL is not set -++# CONFIG_SAMPLES is not set -++CONFIG_CMDLINE="" -++ -++# -++# Security options -++# -++# CONFIG_KEYS is not set -++# CONFIG_SECURITY is not set -++# CONFIG_SECURITY_FILE_CAPABILITIES is not set -++CONFIG_CRYPTO=y -++CONFIG_CRYPTO_ALGAPI=y -++CONFIG_CRYPTO_BLKCIPHER=y -++CONFIG_CRYPTO_MANAGER=y -++# CONFIG_CRYPTO_HMAC is not set -++# CONFIG_CRYPTO_XCBC is not set -++# CONFIG_CRYPTO_NULL is not set -++# CONFIG_CRYPTO_MD4 is not set -++CONFIG_CRYPTO_MD5=y -++# CONFIG_CRYPTO_SHA1 is not set -++# CONFIG_CRYPTO_SHA256 is not set -++# CONFIG_CRYPTO_SHA512 is not set -++# CONFIG_CRYPTO_WP512 is not set -++# CONFIG_CRYPTO_TGR192 is not set -++# CONFIG_CRYPTO_GF128MUL is not set -++# CONFIG_CRYPTO_ECB is not set -++CONFIG_CRYPTO_CBC=y -++# CONFIG_CRYPTO_PCBC is not set -++# CONFIG_CRYPTO_LRW is not set -++# CONFIG_CRYPTO_XTS is not set -++# CONFIG_CRYPTO_CRYPTD is not set -++CONFIG_CRYPTO_DES=y -++# CONFIG_CRYPTO_FCRYPT is not set -++# CONFIG_CRYPTO_BLOWFISH is not set -++# CONFIG_CRYPTO_TWOFISH is not set -++# CONFIG_CRYPTO_SERPENT is not set -++# CONFIG_CRYPTO_AES is not set -++# CONFIG_CRYPTO_CAST5 is not set -++# CONFIG_CRYPTO_CAST6 is not set -++# CONFIG_CRYPTO_TEA is not set -++# CONFIG_CRYPTO_ARC4 is not set -++# CONFIG_CRYPTO_KHAZAD is not set -++# CONFIG_CRYPTO_ANUBIS is not set -++# CONFIG_CRYPTO_SEED is not set -++CONFIG_CRYPTO_DEFLATE=m -++# CONFIG_CRYPTO_MICHAEL_MIC is not set -++# CONFIG_CRYPTO_CRC32C is not set -++# CONFIG_CRYPTO_CAMELLIA is not set -++# CONFIG_CRYPTO_TEST is not set -++# CONFIG_CRYPTO_AUTHENC is not set -++CONFIG_CRYPTO_LZO=m -++CONFIG_CRYPTO_HW=y -++ -++# -++# Library routines -++# -++CONFIG_BITREVERSE=y -++# CONFIG_CRC_CCITT is not set -++CONFIG_CRC16=m -++# CONFIG_CRC_ITU_T is not set -++CONFIG_CRC32=y -++# CONFIG_CRC7 is not set -++# CONFIG_LIBCRC32C is not set -++CONFIG_ZLIB_INFLATE=m -++CONFIG_ZLIB_DEFLATE=m -++CONFIG_LZO_COMPRESS=m -++CONFIG_LZO_DECOMPRESS=m -++CONFIG_PLIST=y -++CONFIG_HAS_IOMEM=y -++CONFIG_HAS_IOPORT=y -++CONFIG_HAS_DMA=y -+diff -urN linux-2.6.24.7.old/arch/mips/configs/lyra_defconfig linux-2.6.24.7/arch/mips/configs/lyra_defconfig -+--- linux-2.6.24.7.old/arch/mips/configs/lyra_defconfig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/configs/lyra_defconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,981 @@ -++# -++# Automatically generated make config: don't edit -++# Linux kernel version: 2.6.24.3 -++# Thu Jun 12 13:53:57 2008 -++# -++CONFIG_MIPS=y -++ -++# -++# Machine selection -++# -++# CONFIG_JZ4730_PMP is not set -++# CONFIG_JZ4740_PAVO is not set -++# CONFIG_JZ4740_LEO is not set -++CONFIG_JZ4740_LYRA=y -++# CONFIG_JZ4725_DIPPER is not set -++# CONFIG_JZ4720_VIRGO is not set -++# CONFIG_JZ4750_FUWA is not set -++# CONFIG_MACH_ALCHEMY is not set -++# CONFIG_BASLER_EXCITE is not set -++# CONFIG_BCM47XX is not set -++# CONFIG_MIPS_COBALT is not set -++# CONFIG_MACH_DECSTATION is not set -++# CONFIG_MACH_JAZZ is not set -++# CONFIG_LASAT is not set -++# CONFIG_LEMOTE_FULONG is not set -++# CONFIG_MIPS_ATLAS is not set -++# CONFIG_MIPS_MALTA is not set -++# CONFIG_MIPS_SEAD is not set -++# CONFIG_MIPS_SIM is not set -++# CONFIG_MARKEINS is not set -++# CONFIG_MACH_VR41XX is not set -++# CONFIG_PNX8550_JBS is not set -++# CONFIG_PNX8550_STB810 is not set -++# CONFIG_PMC_MSP is not set -++# CONFIG_PMC_YOSEMITE is not set -++# CONFIG_QEMU is not set -++# CONFIG_SGI_IP22 is not set -++# CONFIG_SGI_IP27 is not set -++# CONFIG_SGI_IP32 is not set -++# CONFIG_SIBYTE_CRHINE is not set -++# CONFIG_SIBYTE_CARMEL is not set -++# CONFIG_SIBYTE_CRHONE is not set -++# CONFIG_SIBYTE_RHONE is not set -++# CONFIG_SIBYTE_SWARM is not set -++# CONFIG_SIBYTE_LITTLESUR is not set -++# CONFIG_SIBYTE_SENTOSA is not set -++# CONFIG_SIBYTE_PTSWARM is not set -++# CONFIG_SIBYTE_BIGSUR is not set -++# CONFIG_SNI_RM is not set -++# CONFIG_TOSHIBA_JMR3927 is not set -++# CONFIG_TOSHIBA_RBTX4927 is not set -++# CONFIG_TOSHIBA_RBTX4938 is not set -++# CONFIG_WR_PPMC is not set -++CONFIG_SOC_JZ4740=y -++CONFIG_JZSOC=y -++CONFIG_JZRISC=y -++CONFIG_RWSEM_GENERIC_SPINLOCK=y -++# CONFIG_ARCH_HAS_ILOG2_U32 is not set -++# CONFIG_ARCH_HAS_ILOG2_U64 is not set -++CONFIG_ARCH_SUPPORTS_OPROFILE=y -++CONFIG_GENERIC_FIND_NEXT_BIT=y -++CONFIG_GENERIC_HWEIGHT=y -++CONFIG_GENERIC_CALIBRATE_DELAY=y -++CONFIG_GENERIC_CLOCKEVENTS=y -++CONFIG_GENERIC_TIME=y -++CONFIG_GENERIC_CMOS_UPDATE=y -++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -++# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set -++CONFIG_DMA_NONCOHERENT=y -++CONFIG_DMA_NEED_PCI_MAP_STATE=y -++# CONFIG_HOTPLUG_CPU is not set -++# CONFIG_NO_IOPORT is not set -++# CONFIG_CPU_BIG_ENDIAN is not set -++CONFIG_CPU_LITTLE_ENDIAN=y -++CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -++CONFIG_MIPS_L1_CACHE_SHIFT=5 -++ -++# -++# CPU selection -++# -++# CONFIG_CPU_LOONGSON2 is not set -++CONFIG_CPU_MIPS32_R1=y -++# CONFIG_CPU_MIPS32_R2 is not set -++# CONFIG_CPU_MIPS64_R1 is not set -++# CONFIG_CPU_MIPS64_R2 is not set -++# CONFIG_CPU_R3000 is not set -++# CONFIG_CPU_TX39XX is not set -++# CONFIG_CPU_VR41XX is not set -++# CONFIG_CPU_R4300 is not set -++# CONFIG_CPU_R4X00 is not set -++# CONFIG_CPU_TX49XX is not set -++# CONFIG_CPU_R5000 is not set -++# CONFIG_CPU_R5432 is not set -++# CONFIG_CPU_R6000 is not set -++# CONFIG_CPU_NEVADA is not set -++# CONFIG_CPU_R8000 is not set -++# CONFIG_CPU_R10000 is not set -++# CONFIG_CPU_RM7000 is not set -++# CONFIG_CPU_RM9000 is not set -++# CONFIG_CPU_SB1 is not set -++CONFIG_SYS_HAS_CPU_MIPS32_R1=y -++CONFIG_CPU_MIPS32=y -++CONFIG_CPU_MIPSR1=y -++CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -++CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -++ -++# -++# Kernel type -++# -++CONFIG_32BIT=y -++# CONFIG_64BIT is not set -++CONFIG_PAGE_SIZE_4KB=y -++# CONFIG_PAGE_SIZE_8KB is not set -++# CONFIG_PAGE_SIZE_16KB is not set -++# CONFIG_PAGE_SIZE_64KB is not set -++CONFIG_CPU_HAS_PREFETCH=y -++CONFIG_MIPS_MT_DISABLED=y -++# CONFIG_MIPS_MT_SMP is not set -++# CONFIG_MIPS_MT_SMTC is not set -++CONFIG_CPU_HAS_LLSC=y -++CONFIG_CPU_HAS_SYNC=y -++CONFIG_GENERIC_HARDIRQS=y -++CONFIG_GENERIC_IRQ_PROBE=y -++CONFIG_CPU_SUPPORTS_HIGHMEM=y -++CONFIG_ARCH_FLATMEM_ENABLE=y -++CONFIG_ARCH_POPULATES_NODE_MAP=y -++CONFIG_SELECT_MEMORY_MODEL=y -++CONFIG_FLATMEM_MANUAL=y -++# CONFIG_DISCONTIGMEM_MANUAL is not set -++# CONFIG_SPARSEMEM_MANUAL is not set -++CONFIG_FLATMEM=y -++CONFIG_FLAT_NODE_MEM_MAP=y -++# CONFIG_SPARSEMEM_STATIC is not set -++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -++CONFIG_SPLIT_PTLOCK_CPUS=4 -++# CONFIG_RESOURCES_64BIT is not set -++CONFIG_ZONE_DMA_FLAG=0 -++CONFIG_VIRT_TO_BUS=y -++# CONFIG_TICK_ONESHOT is not set -++# CONFIG_NO_HZ is not set -++# CONFIG_HIGH_RES_TIMERS is not set -++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -++# CONFIG_HZ_48 is not set -++CONFIG_HZ_100=y -++# CONFIG_HZ_128 is not set -++# CONFIG_HZ_250 is not set -++# CONFIG_HZ_256 is not set -++# CONFIG_HZ_1000 is not set -++# CONFIG_HZ_1024 is not set -++CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -++CONFIG_HZ=100 -++# CONFIG_PREEMPT_NONE is not set -++# CONFIG_PREEMPT_VOLUNTARY is not set -++CONFIG_PREEMPT=y -++CONFIG_PREEMPT_BKL=y -++# CONFIG_KEXEC is not set -++CONFIG_SECCOMP=y -++CONFIG_LOCKDEP_SUPPORT=y -++CONFIG_STACKTRACE_SUPPORT=y -++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -++ -++# -++# General setup -++# -++CONFIG_EXPERIMENTAL=y -++CONFIG_BROKEN_ON_SMP=y -++CONFIG_LOCK_KERNEL=y -++CONFIG_INIT_ENV_ARG_LIMIT=32 -++CONFIG_LOCALVERSION="" -++CONFIG_LOCALVERSION_AUTO=y -++CONFIG_SWAP=y -++CONFIG_SYSVIPC=y -++CONFIG_SYSVIPC_SYSCTL=y -++# CONFIG_BSD_PROCESS_ACCT is not set -++# CONFIG_USER_NS is not set -++# CONFIG_PID_NS is not set -++# CONFIG_IKCONFIG is not set -++CONFIG_LOG_BUF_SHIFT=14 -++# CONFIG_CGROUPS is not set -++CONFIG_FAIR_GROUP_SCHED=y -++CONFIG_FAIR_USER_SCHED=y -++# CONFIG_FAIR_CGROUP_SCHED is not set -++CONFIG_SYSFS_DEPRECATED=y -++CONFIG_RELAY=y -++# CONFIG_BLK_DEV_INITRD is not set -++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -++CONFIG_SYSCTL=y -++CONFIG_EMBEDDED=y -++CONFIG_SYSCTL_SYSCALL=y -++CONFIG_KALLSYMS=y -++CONFIG_KALLSYMS_ALL=y -++# CONFIG_KALLSYMS_EXTRA_PASS is not set -++CONFIG_HOTPLUG=y -++CONFIG_PRINTK=y -++CONFIG_BUG=y -++CONFIG_ELF_CORE=y -++CONFIG_BASE_FULL=y -++CONFIG_FUTEX=y -++CONFIG_ANON_INODES=y -++CONFIG_EPOLL=y -++CONFIG_SIGNALFD=y -++CONFIG_EVENTFD=y -++CONFIG_SHMEM=y -++CONFIG_VM_EVENT_COUNTERS=y -++CONFIG_SLAB=y -++# CONFIG_SLUB is not set -++# CONFIG_SLOB is not set -++CONFIG_SLABINFO=y -++CONFIG_RT_MUTEXES=y -++# CONFIG_TINY_SHMEM is not set -++CONFIG_BASE_SMALL=0 -++CONFIG_MODULES=y -++CONFIG_MODULE_UNLOAD=y -++# CONFIG_MODULE_FORCE_UNLOAD is not set -++CONFIG_MODVERSIONS=y -++CONFIG_MODULE_SRCVERSION_ALL=y -++CONFIG_KMOD=y -++CONFIG_BLOCK=y -++# CONFIG_LBD is not set -++# CONFIG_BLK_DEV_IO_TRACE is not set -++# CONFIG_LSF is not set -++# CONFIG_BLK_DEV_BSG is not set -++ -++# -++# IO Schedulers -++# -++CONFIG_IOSCHED_NOOP=y -++CONFIG_IOSCHED_AS=y -++CONFIG_IOSCHED_DEADLINE=y -++CONFIG_IOSCHED_CFQ=y -++CONFIG_DEFAULT_AS=y -++# CONFIG_DEFAULT_DEADLINE is not set -++# CONFIG_DEFAULT_CFQ is not set -++# CONFIG_DEFAULT_NOOP is not set -++CONFIG_DEFAULT_IOSCHED="anticipatory" -++ -++# -++# Bus options (PCI, PCMCIA, EISA, ISA, TC) -++# -++# CONFIG_ARCH_SUPPORTS_MSI is not set -++CONFIG_MMU=y -++# CONFIG_PCCARD is not set -++ -++# -++# Executable file formats -++# -++CONFIG_BINFMT_ELF=y -++# CONFIG_BINFMT_MISC is not set -++CONFIG_TRAD_SIGNALS=y -++ -++# -++# CPU Frequency scaling -++# -++CONFIG_CPU_FREQ_JZ=y -++CONFIG_CPU_FREQ=y -++CONFIG_CPU_FREQ_TABLE=y -++# CONFIG_CPU_FREQ_DEBUG is not set -++CONFIG_CPU_FREQ_STAT=y -++# CONFIG_CPU_FREQ_STAT_DETAILS is not set -++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -++CONFIG_CPU_FREQ_GOV_USERSPACE=y -++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set -++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -++ -++# -++# Power management options -++# -++CONFIG_PM=y -++CONFIG_PM_LEGACY=y -++# CONFIG_PM_DEBUG is not set -++CONFIG_PM_SLEEP=y -++CONFIG_SUSPEND_UP_POSSIBLE=y -++CONFIG_SUSPEND=y -++ -++# -++# Networking -++# -++# CONFIG_NET is not set -++ -++# -++# Device Drivers -++# -++ -++# -++# Generic Driver Options -++# -++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -++CONFIG_STANDALONE=y -++CONFIG_PREVENT_FIRMWARE_BUILD=y -++# CONFIG_FW_LOADER is not set -++# CONFIG_SYS_HYPERVISOR is not set -++CONFIG_MTD=y -++# CONFIG_MTD_DEBUG is not set -++CONFIG_MTD_CONCAT=y -++CONFIG_MTD_PARTITIONS=y -++# CONFIG_MTD_REDBOOT_PARTS is not set -++# CONFIG_MTD_CMDLINE_PARTS is not set -++ -++# -++# User Modules And Translation Layers -++# -++CONFIG_MTD_CHAR=y -++CONFIG_MTD_BLKDEVS=y -++CONFIG_MTD_BLOCK=y -++# CONFIG_FTL is not set -++# CONFIG_NFTL is not set -++# CONFIG_INFTL is not set -++# CONFIG_RFD_FTL is not set -++# CONFIG_SSFDC is not set -++# CONFIG_MTD_OOPS is not set -++ -++# -++# RAM/ROM/Flash chip drivers -++# -++# CONFIG_MTD_CFI is not set -++# CONFIG_MTD_JEDECPROBE is not set -++CONFIG_MTD_MAP_BANK_WIDTH_1=y -++CONFIG_MTD_MAP_BANK_WIDTH_2=y -++CONFIG_MTD_MAP_BANK_WIDTH_4=y -++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -++CONFIG_MTD_CFI_I1=y -++CONFIG_MTD_CFI_I2=y -++# CONFIG_MTD_CFI_I4 is not set -++# CONFIG_MTD_CFI_I8 is not set -++# CONFIG_MTD_RAM is not set -++# CONFIG_MTD_ROM is not set -++# CONFIG_MTD_ABSENT is not set -++ -++# -++# Mapping drivers for chip access -++# -++# CONFIG_MTD_COMPLEX_MAPPINGS is not set -++# CONFIG_MTD_PLATRAM is not set -++ -++# -++# Self-contained MTD device drivers -++# -++# CONFIG_MTD_SLRAM is not set -++# CONFIG_MTD_PHRAM is not set -++# CONFIG_MTD_MTDRAM is not set -++CONFIG_MTD_BLOCK2MTD=y -++ -++# -++# Disk-On-Chip Device Drivers -++# -++# CONFIG_MTD_DOC2000 is not set -++# CONFIG_MTD_DOC2001 is not set -++# CONFIG_MTD_DOC2001PLUS is not set -++CONFIG_MTD_NAND=y -++# CONFIG_MTD_NAND_VERIFY_WRITE is not set -++# CONFIG_MTD_NAND_ECC_SMC is not set -++# CONFIG_MTD_NAND_MUSEUM_IDS is not set -++CONFIG_MTD_NAND_IDS=y -++# CONFIG_MTD_NAND_DISKONCHIP is not set -++# CONFIG_MTD_NAND_NANDSIM is not set -++# CONFIG_MTD_NAND_PLATFORM is not set -++CONFIG_MTD_NAND_JZ4740=y -++# CONFIG_MTD_HW_HM_ECC is not set -++# CONFIG_MTD_SW_HM_ECC is not set -++CONFIG_MTD_HW_RS_ECC=y -++# CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE is not set -++CONFIG_MTD_OOB_COPIES=3 -++CONFIG_MTD_BADBLOCK_FLAG_PAGE=127 -++# CONFIG_MTD_ONENAND is not set -++ -++# -++# UBI - Unsorted block images -++# -++CONFIG_MTD_UBI=m -++CONFIG_MTD_UBI_WL_THRESHOLD=4096 -++CONFIG_MTD_UBI_BEB_RESERVE=1 -++CONFIG_MTD_UBI_GLUEBI=y -++ -++# -++# UBI debugging options -++# -++# CONFIG_MTD_UBI_DEBUG is not set -++# CONFIG_MTD_UBI_BLKDEVS is not set -++# CONFIG_PARPORT is not set -++# CONFIG_PNP is not set -++CONFIG_BLK_DEV=y -++# CONFIG_BLK_DEV_COW_COMMON is not set -++CONFIG_BLK_DEV_LOOP=y -++# CONFIG_BLK_DEV_CRYPTOLOOP is not set -++CONFIG_BLK_DEV_RAM=y -++CONFIG_BLK_DEV_RAM_COUNT=16 -++CONFIG_BLK_DEV_RAM_SIZE=4096 -++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -++# CONFIG_CDROM_PKTCDVD is not set -++CONFIG_MISC_DEVICES=y -++# CONFIG_EEPROM_93CX6 is not set -++# CONFIG_IDE is not set -++ -++# -++# SCSI device support -++# -++# CONFIG_RAID_ATTRS is not set -++CONFIG_SCSI=y -++CONFIG_SCSI_DMA=y -++# CONFIG_SCSI_TGT is not set -++# CONFIG_SCSI_NETLINK is not set -++CONFIG_SCSI_PROC_FS=y -++ -++# -++# SCSI support type (disk, tape, CD-ROM) -++# -++CONFIG_BLK_DEV_SD=y -++# CONFIG_CHR_DEV_ST is not set -++# CONFIG_CHR_DEV_OSST is not set -++# CONFIG_BLK_DEV_SR is not set -++# CONFIG_CHR_DEV_SG is not set -++# CONFIG_CHR_DEV_SCH is not set -++ -++# -++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -++# -++# CONFIG_SCSI_MULTI_LUN is not set -++# CONFIG_SCSI_CONSTANTS is not set -++# CONFIG_SCSI_LOGGING is not set -++# CONFIG_SCSI_SCAN_ASYNC is not set -++CONFIG_SCSI_WAIT_SCAN=m -++ -++# -++# SCSI Transports -++# -++# CONFIG_SCSI_SPI_ATTRS is not set -++# CONFIG_SCSI_FC_ATTRS is not set -++# CONFIG_SCSI_SAS_LIBSAS is not set -++# CONFIG_SCSI_SRP_ATTRS is not set -++CONFIG_SCSI_LOWLEVEL=y -++# CONFIG_SCSI_DEBUG is not set -++# CONFIG_ATA is not set -++# CONFIG_MD is not set -++# CONFIG_PHONE is not set -++ -++# -++# Input device support -++# -++CONFIG_INPUT=y -++# CONFIG_INPUT_FF_MEMLESS is not set -++# CONFIG_INPUT_POLLDEV is not set -++ -++# -++# Userland interfaces -++# -++CONFIG_INPUT_MOUSEDEV=y -++CONFIG_INPUT_MOUSEDEV_PSAUX=y -++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -++# CONFIG_INPUT_JOYDEV is not set -++CONFIG_INPUT_EVDEV=y -++# CONFIG_INPUT_EVBUG is not set -++ -++# -++# Input Device Drivers -++# -++# CONFIG_INPUT_KEYBOARD is not set -++# CONFIG_INPUT_MOUSE is not set -++# CONFIG_INPUT_JOYSTICK is not set -++# CONFIG_INPUT_TABLET is not set -++# CONFIG_INPUT_TOUCHSCREEN is not set -++# CONFIG_INPUT_MISC is not set -++ -++# -++# Hardware I/O ports -++# -++CONFIG_SERIO=y -++# CONFIG_SERIO_I8042 is not set -++CONFIG_SERIO_SERPORT=y -++# CONFIG_SERIO_LIBPS2 is not set -++# CONFIG_SERIO_RAW is not set -++# CONFIG_GAMEPORT is not set -++ -++# -++# Character devices -++# -++CONFIG_VT=y -++CONFIG_VT_CONSOLE=y -++CONFIG_HW_CONSOLE=y -++CONFIG_VT_HW_CONSOLE_BINDING=y -++# CONFIG_SERIAL_NONSTANDARD is not set -++ -++# -++# Serial drivers -++# -++CONFIG_SERIAL_8250=y -++CONFIG_SERIAL_8250_CONSOLE=y -++CONFIG_SERIAL_8250_NR_UARTS=4 -++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -++# CONFIG_SERIAL_8250_EXTENDED is not set -++ -++# -++# Non-8250 serial port support -++# -++CONFIG_SERIAL_CORE=y -++CONFIG_SERIAL_CORE_CONSOLE=y -++CONFIG_UNIX98_PTYS=y -++CONFIG_LEGACY_PTYS=y -++CONFIG_LEGACY_PTY_COUNT=256 -++# CONFIG_IPMI_HANDLER is not set -++# CONFIG_HW_RANDOM is not set -++# CONFIG_RTC is not set -++# CONFIG_RTC_PCF8563 is not set -++CONFIG_RTC_JZ=y -++# CONFIG_R3964 is not set -++# CONFIG_RAW_DRIVER is not set -++# CONFIG_TCG_TPM is not set -++ -++# -++# JZSOC char device support -++# -++CONFIG_JZCHAR=y -++# CONFIG_JZ_CIM is not set -++CONFIG_JZ_TPANEL_ATA2508=y -++# CONFIG_JZ_TPANEL is not set -++CONFIG_JZ_UDC_HOTPLUG=y -++CONFIG_JZ_POWEROFF=y -++# CONFIG_JZ_OW is not set -++# CONFIG_I2C is not set -++ -++# -++# SPI support -++# -++# CONFIG_SPI is not set -++# CONFIG_SPI_MASTER is not set -++# CONFIG_W1 is not set -++# CONFIG_POWER_SUPPLY is not set -++# CONFIG_HWMON is not set -++CONFIG_WATCHDOG=y -++# CONFIG_WATCHDOG_NOWAYOUT is not set -++ -++# -++# Watchdog Device Drivers -++# -++CONFIG_JZ_WDT=y -++# CONFIG_SOFT_WATCHDOG is not set -++ -++# -++# Sonics Silicon Backplane -++# -++CONFIG_SSB_POSSIBLE=y -++# CONFIG_SSB is not set -++ -++# -++# Multifunction device drivers -++# -++# CONFIG_MFD_SM501 is not set -++ -++# -++# Multimedia devices -++# -++# CONFIG_VIDEO_DEV is not set -++# CONFIG_DAB is not set -++ -++# -++# Graphics support -++# -++# CONFIG_VGASTATE is not set -++# CONFIG_VIDEO_OUTPUT_CONTROL is not set -++CONFIG_FB=y -++# CONFIG_FIRMWARE_EDID is not set -++# CONFIG_FB_DDC is not set -++CONFIG_FB_CFB_FILLRECT=y -++CONFIG_FB_CFB_COPYAREA=y -++CONFIG_FB_CFB_IMAGEBLIT=y -++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -++# CONFIG_FB_SYS_FILLRECT is not set -++# CONFIG_FB_SYS_COPYAREA is not set -++# CONFIG_FB_SYS_IMAGEBLIT is not set -++# CONFIG_FB_SYS_FOPS is not set -++CONFIG_FB_DEFERRED_IO=y -++# CONFIG_FB_SVGALIB is not set -++# CONFIG_FB_MACMODES is not set -++# CONFIG_FB_BACKLIGHT is not set -++# CONFIG_FB_MODE_HELPERS is not set -++# CONFIG_FB_TILEBLITTING is not set -++ -++# -++# Frame buffer hardware drivers -++# -++CONFIG_FB_JZSOC=y -++# CONFIG_FB_JZ4740_SLCD is not set -++CONFIG_FB_JZLCD_4730_4740=y -++CONFIG_JZLCD_FRAMEBUFFER_MAX=1 -++# CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT is not set -++# CONFIG_JZLCD_SHARP_LQ035Q7 is not set -++# CONFIG_JZLCD_SAMSUNG_LTS350Q1 is not set -++# CONFIG_JZLCD_SAMSUNG_LTV350QVF04 is not set -++# CONFIG_JZLCD_SAMSUNG_LTP400WQF01 is not set -++# CONFIG_JZLCD_SAMSUNG_LTP400WQF02 is not set -++CONFIG_JZLCD_AUO_A030FL01_V1=y -++# CONFIG_JZLCD_TRULY_TFTG320240DTSW is not set -++# CONFIG_JZLCD_TRULY_TFTG320240DTSW_SERIAL is not set -++# CONFIG_JZLCD_TRULY_TFTG240320UTSW_63W_E is not set -++# CONFIG_JZLCD_FOXCONN_PT035TN01 is not set -++# CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL is not set -++# CONFIG_JZLCD_TOSHIBA_LTM084P363 is not set -++# CONFIG_JZLCD_HYNIX_HT10X21 is not set -++# CONFIG_JZLCD_INNOLUX_AT080TN42 is not set -++# CONFIG_JZLCD_CSTN_800x600 is not set -++# CONFIG_JZLCD_CSTN_320x240 is not set -++# CONFIG_JZLCD_MSTN_480x320 is not set -++# CONFIG_JZLCD_MSTN_320x240 is not set -++# CONFIG_JZLCD_MSTN_240x128 is not set -++# CONFIG_FB_S1D13XXX is not set -++# CONFIG_FB_VIRTUAL is not set -++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set -++ -++# -++# Display device support -++# -++# CONFIG_DISPLAY_SUPPORT is not set -++ -++# -++# Console display driver support -++# -++# CONFIG_VGA_CONSOLE is not set -++CONFIG_DUMMY_CONSOLE=y -++CONFIG_FRAMEBUFFER_CONSOLE=y -++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -++# CONFIG_FRAMEBUFFER_CONSOLE_CURSOR_FLASH is not set -++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -++CONFIG_FONTS=y -++CONFIG_FONT_8x8=y -++CONFIG_FONT_8x16=y -++# CONFIG_FONT_6x11 is not set -++# CONFIG_FONT_7x14 is not set -++# CONFIG_FONT_PEARL_8x8 is not set -++# CONFIG_FONT_ACORN_8x8 is not set -++# CONFIG_FONT_MINI_4x6 is not set -++# CONFIG_FONT_SUN8x16 is not set -++# CONFIG_FONT_SUN12x22 is not set -++# CONFIG_FONT_10x18 is not set -++CONFIG_LOGO=y -++CONFIG_LOGO_LINUX_MONO=y -++CONFIG_LOGO_LINUX_VGA16=y -++CONFIG_LOGO_LINUX_CLUT224=y -++ -++# -++# Sound -++# -++CONFIG_SOUND=y -++ -++# -++# Advanced Linux Sound Architecture -++# -++# CONFIG_SND is not set -++ -++# -++# Open Sound System -++# -++CONFIG_SOUND_PRIME=y -++CONFIG_OSS_OBSOLETE=y -++# CONFIG_SOUND_JZ_AC97 is not set -++CONFIG_SOUND_JZ_I2S=y -++# CONFIG_SOUND_JZ_PCM is not set -++# CONFIG_I2S_AK4642EN is not set -++CONFIG_I2S_ICODEC=y -++# CONFIG_SOUND_MSNDCLAS is not set -++# CONFIG_SOUND_MSNDPIN is not set -++CONFIG_HID_SUPPORT=y -++CONFIG_HID=y -++# CONFIG_HID_DEBUG is not set -++# CONFIG_HIDRAW is not set -++CONFIG_USB_SUPPORT=y -++CONFIG_USB_ARCH_HAS_HCD=y -++CONFIG_USB_ARCH_HAS_OHCI=y -++# CONFIG_USB_ARCH_HAS_EHCI is not set -++# CONFIG_USB is not set -++ -++# -++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -++# -++ -++# -++# USB Gadget Support -++# -++CONFIG_USB_GADGET=m -++CONFIG_USB_GADGET_DEBUG_FILES=y -++# CONFIG_USB_GADGET_DEBUG_FS is not set -++CONFIG_USB_GADGET_SELECTED=y -++CONFIG_USB_GADGET_JZ4740=y -++CONFIG_USB_JZ4740=m -++# CONFIG_USB_GADGET_JZ4730 is not set -++# CONFIG_USB_GADGET_AMD5536UDC is not set -++# CONFIG_USB_GADGET_ATMEL_USBA is not set -++# CONFIG_USB_GADGET_FSL_USB2 is not set -++# CONFIG_USB_GADGET_NET2280 is not set -++# CONFIG_USB_GADGET_PXA2XX is not set -++# CONFIG_USB_GADGET_M66592 is not set -++# CONFIG_USB_GADGET_GOKU is not set -++# CONFIG_USB_GADGET_LH7A40X is not set -++# CONFIG_USB_GADGET_OMAP is not set -++# CONFIG_USB_GADGET_S3C2410 is not set -++# CONFIG_USB_GADGET_AT91 is not set -++# CONFIG_USB_GADGET_DUMMY_HCD is not set -++CONFIG_USB_GADGET_DUALSPEED=y -++# CONFIG_USB_ZERO is not set -++# CONFIG_USB_ETH is not set -++# CONFIG_USB_GADGETFS is not set -++CONFIG_USB_FILE_STORAGE=m -++# CONFIG_USB_FILE_STORAGE_TEST is not set -++CONFIG_USB_G_SERIAL=m -++# CONFIG_USB_MIDI_GADGET is not set -++CONFIG_MMC=y -++# CONFIG_MMC_DEBUG is not set -++# CONFIG_MMC_UNSAFE_RESUME is not set -++ -++# -++# MMC/SD Card Drivers -++# -++CONFIG_MMC_BLOCK=y -++CONFIG_MMC_BLOCK_BOUNCE=y -++# CONFIG_SDIO_UART is not set -++ -++# -++# MMC/SD Host Controller Drivers -++# -++# CONFIG_MMC_JZ is not set -++# CONFIG_NEW_LEDS is not set -++CONFIG_RTC_LIB=y -++# CONFIG_RTC_CLASS is not set -++ -++# -++# Userspace I/O -++# -++# CONFIG_UIO is not set -++ -++# -++# File systems -++# -++CONFIG_EXT2_FS=y -++CONFIG_EXT2_FS_XATTR=y -++# CONFIG_EXT2_FS_POSIX_ACL is not set -++# CONFIG_EXT2_FS_SECURITY is not set -++# CONFIG_EXT2_FS_XIP is not set -++CONFIG_EXT3_FS=y -++CONFIG_EXT3_FS_XATTR=y -++# CONFIG_EXT3_FS_POSIX_ACL is not set -++# CONFIG_EXT3_FS_SECURITY is not set -++# CONFIG_EXT4DEV_FS is not set -++CONFIG_JBD=y -++# CONFIG_JBD_DEBUG is not set -++CONFIG_FS_MBCACHE=y -++# CONFIG_REISERFS_FS is not set -++# CONFIG_JFS_FS is not set -++# CONFIG_FS_POSIX_ACL is not set -++# CONFIG_XFS_FS is not set -++# CONFIG_GFS2_FS is not set -++CONFIG_MINIX_FS=y -++# CONFIG_ROMFS_FS is not set -++CONFIG_INOTIFY=y -++CONFIG_INOTIFY_USER=y -++# CONFIG_QUOTA is not set -++CONFIG_DNOTIFY=y -++# CONFIG_AUTOFS_FS is not set -++# CONFIG_AUTOFS4_FS is not set -++# CONFIG_FUSE_FS is not set -++ -++# -++# CD-ROM/DVD Filesystems -++# -++# CONFIG_ISO9660_FS is not set -++# CONFIG_UDF_FS is not set -++ -++# -++# DOS/FAT/NT Filesystems -++# -++CONFIG_FAT_FS=y -++CONFIG_MSDOS_FS=y -++CONFIG_VFAT_FS=y -++CONFIG_FAT_DEFAULT_CODEPAGE=437 -++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -++# CONFIG_NTFS_FS is not set -++ -++# -++# Pseudo filesystems -++# -++CONFIG_PROC_FS=y -++CONFIG_PROC_KCORE=y -++CONFIG_PROC_SYSCTL=y -++CONFIG_SYSFS=y -++CONFIG_TMPFS=y -++# CONFIG_TMPFS_POSIX_ACL is not set -++# CONFIG_HUGETLB_PAGE is not set -++# CONFIG_CONFIGFS_FS is not set -++ -++# -++# Miscellaneous filesystems -++# -++# CONFIG_ADFS_FS is not set -++# CONFIG_AFFS_FS is not set -++# CONFIG_HFS_FS is not set -++# CONFIG_HFSPLUS_FS is not set -++# CONFIG_BEFS_FS is not set -++# CONFIG_BFS_FS is not set -++# CONFIG_EFS_FS is not set -++# CONFIG_JFFS2_FS is not set -++CONFIG_UBIFS_FS=m -++# CONFIG_UBIFS_FS_XATTR is not set -++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set -++CONFIG_UBIFS_FS_LZO=y -++CONFIG_UBIFS_FS_ZLIB=y -++CONFIG_UBIFS_FS_DEBUG=y -++CONFIG_UBIFS_FS_DEBUG_MSG_LVL=0 -++# CONFIG_UBIFS_FS_DEBUG_CHKS is not set -++# CONFIG_CRAMFS is not set -++# CONFIG_VXFS_FS is not set -++# CONFIG_HPFS_FS is not set -++# CONFIG_QNX4FS_FS is not set -++# CONFIG_SYSV_FS is not set -++# CONFIG_UFS_FS is not set -++ -++# -++# Partition Types -++# -++CONFIG_PARTITION_ADVANCED=y -++# CONFIG_ACORN_PARTITION is not set -++# CONFIG_OSF_PARTITION is not set -++# CONFIG_AMIGA_PARTITION is not set -++# CONFIG_ATARI_PARTITION is not set -++# CONFIG_MAC_PARTITION is not set -++CONFIG_MSDOS_PARTITION=y -++# CONFIG_BSD_DISKLABEL is not set -++# CONFIG_MINIX_SUBPARTITION is not set -++# CONFIG_SOLARIS_X86_PARTITION is not set -++# CONFIG_UNIXWARE_DISKLABEL is not set -++# CONFIG_LDM_PARTITION is not set -++# CONFIG_SGI_PARTITION is not set -++# CONFIG_ULTRIX_PARTITION is not set -++# CONFIG_SUN_PARTITION is not set -++# CONFIG_KARMA_PARTITION is not set -++# CONFIG_EFI_PARTITION is not set -++# CONFIG_SYSV68_PARTITION is not set -++CONFIG_NLS=y -++CONFIG_NLS_DEFAULT="iso8859-1" -++CONFIG_NLS_CODEPAGE_437=y -++# CONFIG_NLS_CODEPAGE_737 is not set -++# CONFIG_NLS_CODEPAGE_775 is not set -++# CONFIG_NLS_CODEPAGE_850 is not set -++# CONFIG_NLS_CODEPAGE_852 is not set -++# CONFIG_NLS_CODEPAGE_855 is not set -++# CONFIG_NLS_CODEPAGE_857 is not set -++# CONFIG_NLS_CODEPAGE_860 is not set -++# CONFIG_NLS_CODEPAGE_861 is not set -++# CONFIG_NLS_CODEPAGE_862 is not set -++# CONFIG_NLS_CODEPAGE_863 is not set -++# CONFIG_NLS_CODEPAGE_864 is not set -++# CONFIG_NLS_CODEPAGE_865 is not set -++# CONFIG_NLS_CODEPAGE_866 is not set -++# CONFIG_NLS_CODEPAGE_869 is not set -++CONFIG_NLS_CODEPAGE_936=y -++# CONFIG_NLS_CODEPAGE_950 is not set -++# CONFIG_NLS_CODEPAGE_932 is not set -++# CONFIG_NLS_CODEPAGE_949 is not set -++# CONFIG_NLS_CODEPAGE_874 is not set -++# CONFIG_NLS_ISO8859_8 is not set -++# CONFIG_NLS_CODEPAGE_1250 is not set -++# CONFIG_NLS_CODEPAGE_1251 is not set -++CONFIG_NLS_ASCII=y -++CONFIG_NLS_ISO8859_1=y -++# CONFIG_NLS_ISO8859_2 is not set -++# CONFIG_NLS_ISO8859_3 is not set -++# CONFIG_NLS_ISO8859_4 is not set -++# CONFIG_NLS_ISO8859_5 is not set -++# CONFIG_NLS_ISO8859_6 is not set -++# CONFIG_NLS_ISO8859_7 is not set -++# CONFIG_NLS_ISO8859_9 is not set -++# CONFIG_NLS_ISO8859_13 is not set -++# CONFIG_NLS_ISO8859_14 is not set -++# CONFIG_NLS_ISO8859_15 is not set -++# CONFIG_NLS_KOI8_R is not set -++# CONFIG_NLS_KOI8_U is not set -++# CONFIG_NLS_UTF8 is not set -++ -++# -++# Yaffs2 Filesystems -++# -++CONFIG_YAFFS_FS=y -++CONFIG_YAFFS_YAFFS1=y -++# CONFIG_YAFFS_DOES_ECC is not set -++CONFIG_YAFFS_YAFFS2=y -++CONFIG_YAFFS_AUTO_YAFFS2=y -++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set -++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set -++CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK=y -++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y -++CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10 -++CONFIG_INSTRUMENTATION=y -++# CONFIG_PROFILING is not set -++# CONFIG_MARKERS is not set -++ -++# -++# Kernel hacking -++# -++CONFIG_TRACE_IRQFLAGS_SUPPORT=y -++# CONFIG_PRINTK_TIME is not set -++CONFIG_ENABLE_WARN_DEPRECATED=y -++CONFIG_ENABLE_MUST_CHECK=y -++CONFIG_MAGIC_SYSRQ=y -++# CONFIG_UNUSED_SYMBOLS is not set -++CONFIG_DEBUG_FS=y -++# CONFIG_HEADERS_CHECK is not set -++# CONFIG_DEBUG_KERNEL is not set -++# CONFIG_SAMPLES is not set -++CONFIG_CMDLINE="" -++ -++# -++# Security options -++# -++# CONFIG_KEYS is not set -++# CONFIG_SECURITY is not set -++# CONFIG_SECURITY_FILE_CAPABILITIES is not set -++CONFIG_CRYPTO=y -++CONFIG_CRYPTO_ALGAPI=y -++CONFIG_CRYPTO_BLKCIPHER=y -++CONFIG_CRYPTO_MANAGER=y -++# CONFIG_CRYPTO_HMAC is not set -++# CONFIG_CRYPTO_XCBC is not set -++# CONFIG_CRYPTO_NULL is not set -++# CONFIG_CRYPTO_MD4 is not set -++CONFIG_CRYPTO_MD5=y -++# CONFIG_CRYPTO_SHA1 is not set -++# CONFIG_CRYPTO_SHA256 is not set -++# CONFIG_CRYPTO_SHA512 is not set -++# CONFIG_CRYPTO_WP512 is not set -++# CONFIG_CRYPTO_TGR192 is not set -++# CONFIG_CRYPTO_GF128MUL is not set -++# CONFIG_CRYPTO_ECB is not set -++CONFIG_CRYPTO_CBC=y -++# CONFIG_CRYPTO_PCBC is not set -++# CONFIG_CRYPTO_LRW is not set -++# CONFIG_CRYPTO_XTS is not set -++# CONFIG_CRYPTO_CRYPTD is not set -++CONFIG_CRYPTO_DES=y -++# CONFIG_CRYPTO_FCRYPT is not set -++# CONFIG_CRYPTO_BLOWFISH is not set -++# CONFIG_CRYPTO_TWOFISH is not set -++# CONFIG_CRYPTO_SERPENT is not set -++# CONFIG_CRYPTO_AES is not set -++# CONFIG_CRYPTO_CAST5 is not set -++# CONFIG_CRYPTO_CAST6 is not set -++# CONFIG_CRYPTO_TEA is not set -++# CONFIG_CRYPTO_ARC4 is not set -++# CONFIG_CRYPTO_KHAZAD is not set -++# CONFIG_CRYPTO_ANUBIS is not set -++# CONFIG_CRYPTO_SEED is not set -++CONFIG_CRYPTO_DEFLATE=m -++# CONFIG_CRYPTO_MICHAEL_MIC is not set -++# CONFIG_CRYPTO_CRC32C is not set -++# CONFIG_CRYPTO_CAMELLIA is not set -++# CONFIG_CRYPTO_TEST is not set -++# CONFIG_CRYPTO_AUTHENC is not set -++CONFIG_CRYPTO_LZO=m -++CONFIG_CRYPTO_HW=y -++ -++# -++# Library routines -++# -++CONFIG_BITREVERSE=y -++# CONFIG_CRC_CCITT is not set -++CONFIG_CRC16=m -++# CONFIG_CRC_ITU_T is not set -++CONFIG_CRC32=y -++# CONFIG_CRC7 is not set -++# CONFIG_LIBCRC32C is not set -++CONFIG_ZLIB_INFLATE=m -++CONFIG_ZLIB_DEFLATE=m -++CONFIG_LZO_COMPRESS=m -++CONFIG_LZO_DECOMPRESS=m -++CONFIG_PLIST=y -++CONFIG_HAS_IOMEM=y -++CONFIG_HAS_IOPORT=y -++CONFIG_HAS_DMA=y -+diff -urN linux-2.6.24.7.old/arch/mips/configs/pavo_defconfig linux-2.6.24.7/arch/mips/configs/pavo_defconfig -+--- linux-2.6.24.7.old/arch/mips/configs/pavo_defconfig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/configs/pavo_defconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1293 @@ -++# -++# Automatically generated make config: don't edit -++# Linux kernel version: 2.6.24.3 -++# Sat Nov 15 16:15:17 2008 -++# -++CONFIG_MIPS=y -++ -++# -++# Machine selection -++# -++# CONFIG_JZ4730_PMP is not set -++CONFIG_JZ4740_PAVO=y -++# CONFIG_JZ4740_LEO is not set -++# CONFIG_JZ4740_LYRA is not set -++# CONFIG_JZ4725_DIPPER is not set -++# CONFIG_JZ4720_VIRGO is not set -++# CONFIG_JZ4750_FUWA is not set -++# CONFIG_JZ4750_APUS is not set -++# CONFIG_MACH_ALCHEMY is not set -++# CONFIG_BASLER_EXCITE is not set -++# CONFIG_BCM47XX is not set -++# CONFIG_MIPS_COBALT is not set -++# CONFIG_MACH_DECSTATION is not set -++# CONFIG_MACH_JAZZ is not set -++# CONFIG_LASAT is not set -++# CONFIG_LEMOTE_FULONG is not set -++# CONFIG_MIPS_ATLAS is not set -++# CONFIG_MIPS_MALTA is not set -++# CONFIG_MIPS_SEAD is not set -++# CONFIG_MIPS_SIM is not set -++# CONFIG_MARKEINS is not set -++# CONFIG_MACH_VR41XX is not set -++# CONFIG_PNX8550_JBS is not set -++# CONFIG_PNX8550_STB810 is not set -++# CONFIG_PMC_MSP is not set -++# CONFIG_PMC_YOSEMITE is not set -++# CONFIG_QEMU is not set -++# CONFIG_SGI_IP22 is not set -++# CONFIG_SGI_IP27 is not set -++# CONFIG_SGI_IP32 is not set -++# CONFIG_SIBYTE_CRHINE is not set -++# CONFIG_SIBYTE_CARMEL is not set -++# CONFIG_SIBYTE_CRHONE is not set -++# CONFIG_SIBYTE_RHONE is not set -++# CONFIG_SIBYTE_SWARM is not set -++# CONFIG_SIBYTE_LITTLESUR is not set -++# CONFIG_SIBYTE_SENTOSA is not set -++# CONFIG_SIBYTE_PTSWARM is not set -++# CONFIG_SIBYTE_BIGSUR is not set -++# CONFIG_SNI_RM is not set -++# CONFIG_TOSHIBA_JMR3927 is not set -++# CONFIG_TOSHIBA_RBTX4927 is not set -++# CONFIG_TOSHIBA_RBTX4938 is not set -++# CONFIG_WR_PPMC is not set -++CONFIG_SOC_JZ4740=y -++CONFIG_JZSOC=y -++CONFIG_JZRISC=y -++CONFIG_RWSEM_GENERIC_SPINLOCK=y -++# CONFIG_ARCH_HAS_ILOG2_U32 is not set -++# CONFIG_ARCH_HAS_ILOG2_U64 is not set -++CONFIG_ARCH_SUPPORTS_OPROFILE=y -++CONFIG_GENERIC_FIND_NEXT_BIT=y -++CONFIG_GENERIC_HWEIGHT=y -++CONFIG_GENERIC_CALIBRATE_DELAY=y -++CONFIG_GENERIC_CLOCKEVENTS=y -++CONFIG_GENERIC_TIME=y -++CONFIG_GENERIC_CMOS_UPDATE=y -++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -++# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set -++CONFIG_DMA_NONCOHERENT=y -++CONFIG_DMA_NEED_PCI_MAP_STATE=y -++# CONFIG_HOTPLUG_CPU is not set -++# CONFIG_NO_IOPORT is not set -++# CONFIG_CPU_BIG_ENDIAN is not set -++CONFIG_CPU_LITTLE_ENDIAN=y -++CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -++CONFIG_MIPS_L1_CACHE_SHIFT=5 -++ -++# -++# CPU selection -++# -++# CONFIG_CPU_LOONGSON2 is not set -++CONFIG_CPU_MIPS32_R1=y -++# CONFIG_CPU_MIPS32_R2 is not set -++# CONFIG_CPU_MIPS64_R1 is not set -++# CONFIG_CPU_MIPS64_R2 is not set -++# CONFIG_CPU_R3000 is not set -++# CONFIG_CPU_TX39XX is not set -++# CONFIG_CPU_VR41XX is not set -++# CONFIG_CPU_R4300 is not set -++# CONFIG_CPU_R4X00 is not set -++# CONFIG_CPU_TX49XX is not set -++# CONFIG_CPU_R5000 is not set -++# CONFIG_CPU_R5432 is not set -++# CONFIG_CPU_R6000 is not set -++# CONFIG_CPU_NEVADA is not set -++# CONFIG_CPU_R8000 is not set -++# CONFIG_CPU_R10000 is not set -++# CONFIG_CPU_RM7000 is not set -++# CONFIG_CPU_RM9000 is not set -++# CONFIG_CPU_SB1 is not set -++CONFIG_SYS_HAS_CPU_MIPS32_R1=y -++CONFIG_CPU_MIPS32=y -++CONFIG_CPU_MIPSR1=y -++CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -++CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -++ -++# -++# Kernel type -++# -++CONFIG_32BIT=y -++# CONFIG_64BIT is not set -++CONFIG_PAGE_SIZE_4KB=y -++# CONFIG_PAGE_SIZE_8KB is not set -++# CONFIG_PAGE_SIZE_16KB is not set -++# CONFIG_PAGE_SIZE_64KB is not set -++CONFIG_CPU_HAS_PREFETCH=y -++CONFIG_MIPS_MT_DISABLED=y -++# CONFIG_MIPS_MT_SMP is not set -++# CONFIG_MIPS_MT_SMTC is not set -++CONFIG_CPU_HAS_LLSC=y -++CONFIG_CPU_HAS_SYNC=y -++CONFIG_GENERIC_HARDIRQS=y -++CONFIG_GENERIC_IRQ_PROBE=y -++CONFIG_CPU_SUPPORTS_HIGHMEM=y -++CONFIG_ARCH_FLATMEM_ENABLE=y -++CONFIG_ARCH_POPULATES_NODE_MAP=y -++CONFIG_SELECT_MEMORY_MODEL=y -++CONFIG_FLATMEM_MANUAL=y -++# CONFIG_DISCONTIGMEM_MANUAL is not set -++# CONFIG_SPARSEMEM_MANUAL is not set -++CONFIG_FLATMEM=y -++CONFIG_FLAT_NODE_MEM_MAP=y -++# CONFIG_SPARSEMEM_STATIC is not set -++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -++CONFIG_SPLIT_PTLOCK_CPUS=4 -++# CONFIG_RESOURCES_64BIT is not set -++CONFIG_ZONE_DMA_FLAG=0 -++CONFIG_VIRT_TO_BUS=y -++# CONFIG_TICK_ONESHOT is not set -++# CONFIG_NO_HZ is not set -++# CONFIG_HIGH_RES_TIMERS is not set -++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -++# CONFIG_HZ_48 is not set -++CONFIG_HZ_100=y -++# CONFIG_HZ_128 is not set -++# CONFIG_HZ_250 is not set -++# CONFIG_HZ_256 is not set -++# CONFIG_HZ_1000 is not set -++# CONFIG_HZ_1024 is not set -++CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -++CONFIG_HZ=100 -++# CONFIG_PREEMPT_NONE is not set -++# CONFIG_PREEMPT_VOLUNTARY is not set -++CONFIG_PREEMPT=y -++CONFIG_PREEMPT_BKL=y -++# CONFIG_KEXEC is not set -++CONFIG_SECCOMP=y -++CONFIG_LOCKDEP_SUPPORT=y -++CONFIG_STACKTRACE_SUPPORT=y -++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -++ -++# -++# General setup -++# -++CONFIG_EXPERIMENTAL=y -++CONFIG_BROKEN_ON_SMP=y -++CONFIG_LOCK_KERNEL=y -++CONFIG_INIT_ENV_ARG_LIMIT=32 -++CONFIG_LOCALVERSION="" -++CONFIG_LOCALVERSION_AUTO=y -++CONFIG_SWAP=y -++CONFIG_SYSVIPC=y -++CONFIG_SYSVIPC_SYSCTL=y -++# CONFIG_POSIX_MQUEUE is not set -++# CONFIG_BSD_PROCESS_ACCT is not set -++# CONFIG_TASKSTATS is not set -++# CONFIG_USER_NS is not set -++# CONFIG_PID_NS is not set -++# CONFIG_AUDIT is not set -++# CONFIG_IKCONFIG is not set -++CONFIG_LOG_BUF_SHIFT=14 -++# CONFIG_CGROUPS is not set -++CONFIG_FAIR_GROUP_SCHED=y -++CONFIG_FAIR_USER_SCHED=y -++# CONFIG_FAIR_CGROUP_SCHED is not set -++CONFIG_SYSFS_DEPRECATED=y -++CONFIG_RELAY=y -++# CONFIG_BLK_DEV_INITRD is not set -++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -++CONFIG_SYSCTL=y -++CONFIG_EMBEDDED=y -++CONFIG_SYSCTL_SYSCALL=y -++CONFIG_KALLSYMS=y -++# CONFIG_KALLSYMS_EXTRA_PASS is not set -++CONFIG_HOTPLUG=y -++CONFIG_PRINTK=y -++CONFIG_BUG=y -++CONFIG_ELF_CORE=y -++CONFIG_BASE_FULL=y -++CONFIG_FUTEX=y -++CONFIG_ANON_INODES=y -++CONFIG_EPOLL=y -++CONFIG_SIGNALFD=y -++CONFIG_EVENTFD=y -++CONFIG_SHMEM=y -++CONFIG_VM_EVENT_COUNTERS=y -++CONFIG_SLAB=y -++# CONFIG_SLUB is not set -++# CONFIG_SLOB is not set -++CONFIG_SLABINFO=y -++CONFIG_RT_MUTEXES=y -++# CONFIG_TINY_SHMEM is not set -++CONFIG_BASE_SMALL=0 -++CONFIG_MODULES=y -++CONFIG_MODULE_UNLOAD=y -++# CONFIG_MODULE_FORCE_UNLOAD is not set -++CONFIG_MODVERSIONS=y -++CONFIG_MODULE_SRCVERSION_ALL=y -++CONFIG_KMOD=y -++CONFIG_BLOCK=y -++# CONFIG_LBD is not set -++# CONFIG_BLK_DEV_IO_TRACE is not set -++# CONFIG_LSF is not set -++# CONFIG_BLK_DEV_BSG is not set -++ -++# -++# IO Schedulers -++# -++CONFIG_IOSCHED_NOOP=y -++CONFIG_IOSCHED_AS=y -++CONFIG_IOSCHED_DEADLINE=y -++CONFIG_IOSCHED_CFQ=y -++CONFIG_DEFAULT_AS=y -++# CONFIG_DEFAULT_DEADLINE is not set -++# CONFIG_DEFAULT_CFQ is not set -++# CONFIG_DEFAULT_NOOP is not set -++CONFIG_DEFAULT_IOSCHED="anticipatory" -++ -++# -++# Bus options (PCI, PCMCIA, EISA, ISA, TC) -++# -++# CONFIG_ARCH_SUPPORTS_MSI is not set -++CONFIG_MMU=y -++# CONFIG_PCCARD is not set -++ -++# -++# Executable file formats -++# -++CONFIG_BINFMT_ELF=y -++# CONFIG_BINFMT_MISC is not set -++CONFIG_TRAD_SIGNALS=y -++ -++# -++# CPU Frequency scaling -++# -++CONFIG_CPU_FREQ_JZ=y -++CONFIG_CPU_FREQ=y -++CONFIG_CPU_FREQ_TABLE=y -++# CONFIG_CPU_FREQ_DEBUG is not set -++CONFIG_CPU_FREQ_STAT=y -++# CONFIG_CPU_FREQ_STAT_DETAILS is not set -++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -++CONFIG_CPU_FREQ_GOV_USERSPACE=y -++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set -++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -++ -++# -++# Power management options -++# -++CONFIG_PM=y -++CONFIG_PM_LEGACY=y -++# CONFIG_PM_DEBUG is not set -++CONFIG_SUSPEND_UP_POSSIBLE=y -++# CONFIG_SUSPEND is not set -++ -++# -++# Networking -++# -++CONFIG_NET=y -++ -++# -++# Networking options -++# -++CONFIG_PACKET=y -++# CONFIG_PACKET_MMAP is not set -++CONFIG_UNIX=y -++# CONFIG_NET_KEY is not set -++CONFIG_INET=y -++# CONFIG_IP_MULTICAST is not set -++# CONFIG_IP_ADVANCED_ROUTER is not set -++CONFIG_IP_FIB_HASH=y -++CONFIG_IP_PNP=y -++CONFIG_IP_PNP_DHCP=y -++CONFIG_IP_PNP_BOOTP=y -++# CONFIG_IP_PNP_RARP is not set -++# CONFIG_NET_IPIP is not set -++# CONFIG_NET_IPGRE is not set -++# CONFIG_ARPD is not set -++# CONFIG_SYN_COOKIES is not set -++# CONFIG_INET_AH is not set -++# CONFIG_INET_ESP is not set -++# CONFIG_INET_IPCOMP is not set -++# CONFIG_INET_XFRM_TUNNEL is not set -++# CONFIG_INET_TUNNEL is not set -++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -++# CONFIG_INET_XFRM_MODE_TUNNEL is not set -++# CONFIG_INET_XFRM_MODE_BEET is not set -++# CONFIG_INET_LRO is not set -++# CONFIG_INET_DIAG is not set -++# CONFIG_TCP_CONG_ADVANCED is not set -++CONFIG_TCP_CONG_CUBIC=y -++CONFIG_DEFAULT_TCP_CONG="cubic" -++# CONFIG_TCP_MD5SIG is not set -++# CONFIG_IPV6 is not set -++# CONFIG_INET6_XFRM_TUNNEL is not set -++# CONFIG_INET6_TUNNEL is not set -++# CONFIG_NETWORK_SECMARK is not set -++# CONFIG_NETFILTER is not set -++# CONFIG_IP_DCCP is not set -++# CONFIG_IP_SCTP is not set -++# CONFIG_TIPC is not set -++# CONFIG_ATM is not set -++# CONFIG_BRIDGE is not set -++# CONFIG_VLAN_8021Q is not set -++# CONFIG_DECNET is not set -++# CONFIG_LLC2 is not set -++# CONFIG_IPX is not set -++# CONFIG_ATALK is not set -++# CONFIG_X25 is not set -++# CONFIG_LAPB is not set -++# CONFIG_ECONET is not set -++# CONFIG_WAN_ROUTER is not set -++# CONFIG_NET_SCHED is not set -++ -++# -++# Network testing -++# -++# CONFIG_NET_PKTGEN is not set -++# CONFIG_HAMRADIO is not set -++# CONFIG_IRDA is not set -++# CONFIG_BT is not set -++# CONFIG_AF_RXRPC is not set -++ -++# -++# Wireless -++# -++# CONFIG_CFG80211 is not set -++CONFIG_WIRELESS_EXT=y -++# CONFIG_MAC80211 is not set -++# CONFIG_IEEE80211 is not set -++# CONFIG_RFKILL is not set -++# CONFIG_NET_9P is not set -++ -++# -++# Device Drivers -++# -++ -++# -++# Generic Driver Options -++# -++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -++CONFIG_STANDALONE=y -++CONFIG_PREVENT_FIRMWARE_BUILD=y -++# CONFIG_FW_LOADER is not set -++# CONFIG_SYS_HYPERVISOR is not set -++# CONFIG_CONNECTOR is not set -++CONFIG_MTD=y -++# CONFIG_MTD_DEBUG is not set -++# CONFIG_MTD_CONCAT is not set -++CONFIG_MTD_PARTITIONS=y -++# CONFIG_MTD_REDBOOT_PARTS is not set -++# CONFIG_MTD_CMDLINE_PARTS is not set -++ -++# -++# User Modules And Translation Layers -++# -++CONFIG_MTD_CHAR=y -++CONFIG_MTD_BLKDEVS=y -++CONFIG_MTD_BLOCK=y -++# CONFIG_FTL is not set -++# CONFIG_NFTL is not set -++# CONFIG_INFTL is not set -++# CONFIG_RFD_FTL is not set -++# CONFIG_SSFDC is not set -++# CONFIG_MTD_OOPS is not set -++ -++# -++# RAM/ROM/Flash chip drivers -++# -++# CONFIG_MTD_CFI is not set -++# CONFIG_MTD_JEDECPROBE is not set -++CONFIG_MTD_MAP_BANK_WIDTH_1=y -++CONFIG_MTD_MAP_BANK_WIDTH_2=y -++CONFIG_MTD_MAP_BANK_WIDTH_4=y -++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -++CONFIG_MTD_CFI_I1=y -++CONFIG_MTD_CFI_I2=y -++# CONFIG_MTD_CFI_I4 is not set -++# CONFIG_MTD_CFI_I8 is not set -++# CONFIG_MTD_RAM is not set -++# CONFIG_MTD_ROM is not set -++# CONFIG_MTD_ABSENT is not set -++ -++# -++# Mapping drivers for chip access -++# -++# CONFIG_MTD_COMPLEX_MAPPINGS is not set -++# CONFIG_MTD_PLATRAM is not set -++ -++# -++# Self-contained MTD device drivers -++# -++# CONFIG_MTD_SLRAM is not set -++# CONFIG_MTD_PHRAM is not set -++# CONFIG_MTD_MTDRAM is not set -++# CONFIG_MTD_BLOCK2MTD is not set -++ -++# -++# Disk-On-Chip Device Drivers -++# -++# CONFIG_MTD_DOC2000 is not set -++# CONFIG_MTD_DOC2001 is not set -++# CONFIG_MTD_DOC2001PLUS is not set -++CONFIG_MTD_NAND=y -++# CONFIG_MTD_NAND_VERIFY_WRITE is not set -++# CONFIG_MTD_NAND_ECC_SMC is not set -++# CONFIG_MTD_NAND_MUSEUM_IDS is not set -++CONFIG_MTD_NAND_IDS=y -++# CONFIG_MTD_NAND_DISKONCHIP is not set -++# CONFIG_MTD_NAND_NANDSIM is not set -++# CONFIG_MTD_NAND_PLATFORM is not set -++# CONFIG_MTD_ALAUDA is not set -++CONFIG_MTD_NAND_JZ4740=y -++# CONFIG_MTD_NAND_CS2 is not set -++# CONFIG_MTD_NAND_CS3 is not set -++# CONFIG_MTD_NAND_CS4 is not set -++CONFIG_MTD_NAND_MULTI_PLANE=y -++# CONFIG_MTD_HW_HM_ECC is not set -++# CONFIG_MTD_SW_HM_ECC is not set -++CONFIG_MTD_HW_RS_ECC=y -++# CONFIG_MTD_HW_BCH_ECC is not set -++# CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE is not set -++CONFIG_MTD_OOB_COPIES=3 -++CONFIG_MTD_BADBLOCK_FLAG_PAGE=127 -++# CONFIG_MTD_ONENAND is not set -++ -++# -++# UBI - Unsorted block images -++# -++CONFIG_MTD_UBI=m -++CONFIG_MTD_UBI_WL_THRESHOLD=256 -++CONFIG_MTD_UBI_BEB_RESERVE=1 -++# CONFIG_MTD_UBI_GLUEBI is not set -++ -++# -++# UBI debugging options -++# -++# CONFIG_MTD_UBI_DEBUG is not set -++CONFIG_MTD_UBI_BLKDEVS=m -++CONFIG_MTD_UBI_BLOCK=m -++# CONFIG_PARPORT is not set -++CONFIG_PNP=y -++# CONFIG_PNP_DEBUG is not set -++ -++# -++# Protocols -++# -++# CONFIG_PNPACPI is not set -++CONFIG_BLK_DEV=y -++# CONFIG_BLK_DEV_COW_COMMON is not set -++CONFIG_BLK_DEV_LOOP=y -++# CONFIG_BLK_DEV_CRYPTOLOOP is not set -++# CONFIG_BLK_DEV_NBD is not set -++# CONFIG_BLK_DEV_UB is not set -++CONFIG_BLK_DEV_RAM=y -++CONFIG_BLK_DEV_RAM_COUNT=2 -++CONFIG_BLK_DEV_RAM_SIZE=4096 -++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -++# CONFIG_CDROM_PKTCDVD is not set -++# CONFIG_ATA_OVER_ETH is not set -++CONFIG_MISC_DEVICES=y -++# CONFIG_EEPROM_93CX6 is not set -++# CONFIG_IDE is not set -++ -++# -++# SCSI device support -++# -++# CONFIG_RAID_ATTRS is not set -++CONFIG_SCSI=y -++CONFIG_SCSI_DMA=y -++# CONFIG_SCSI_TGT is not set -++# CONFIG_SCSI_NETLINK is not set -++CONFIG_SCSI_PROC_FS=y -++ -++# -++# SCSI support type (disk, tape, CD-ROM) -++# -++CONFIG_BLK_DEV_SD=y -++# CONFIG_CHR_DEV_ST is not set -++# CONFIG_CHR_DEV_OSST is not set -++# CONFIG_BLK_DEV_SR is not set -++# CONFIG_CHR_DEV_SG is not set -++# CONFIG_CHR_DEV_SCH is not set -++ -++# -++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -++# -++# CONFIG_SCSI_MULTI_LUN is not set -++# CONFIG_SCSI_CONSTANTS is not set -++# CONFIG_SCSI_LOGGING is not set -++# CONFIG_SCSI_SCAN_ASYNC is not set -++CONFIG_SCSI_WAIT_SCAN=m -++ -++# -++# SCSI Transports -++# -++# CONFIG_SCSI_SPI_ATTRS is not set -++# CONFIG_SCSI_FC_ATTRS is not set -++# CONFIG_SCSI_ISCSI_ATTRS is not set -++# CONFIG_SCSI_SAS_LIBSAS is not set -++# CONFIG_SCSI_SRP_ATTRS is not set -++CONFIG_SCSI_LOWLEVEL=y -++# CONFIG_ISCSI_TCP is not set -++# CONFIG_SCSI_DEBUG is not set -++# CONFIG_ATA is not set -++# CONFIG_MD is not set -++CONFIG_NETDEVICES=y -++# CONFIG_NETDEVICES_MULTIQUEUE is not set -++# CONFIG_DUMMY is not set -++# CONFIG_BONDING is not set -++# CONFIG_MACVLAN is not set -++# CONFIG_EQUALIZER is not set -++# CONFIG_TUN is not set -++# CONFIG_VETH is not set -++# CONFIG_NET_SB1000 is not set -++CONFIG_PHYLIB=y -++ -++# -++# MII PHY device drivers -++# -++# CONFIG_MARVELL_PHY is not set -++# CONFIG_DAVICOM_PHY is not set -++# CONFIG_QSEMI_PHY is not set -++# CONFIG_LXT_PHY is not set -++# CONFIG_CICADA_PHY is not set -++# CONFIG_VITESSE_PHY is not set -++# CONFIG_SMSC_PHY is not set -++# CONFIG_BROADCOM_PHY is not set -++# CONFIG_ICPLUS_PHY is not set -++# CONFIG_FIXED_PHY is not set -++# CONFIG_MDIO_BITBANG is not set -++CONFIG_NET_ETHERNET=y -++CONFIG_MII=y -++CONFIG_JZCS8900=y -++# CONFIG_AX88796 is not set -++# CONFIG_DM9000 is not set -++# CONFIG_IBM_NEW_EMAC_ZMII is not set -++# CONFIG_IBM_NEW_EMAC_RGMII is not set -++# CONFIG_IBM_NEW_EMAC_TAH is not set -++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -++# CONFIG_B44 is not set -++# CONFIG_NETDEV_1000 is not set -++# CONFIG_NETDEV_10000 is not set -++ -++# -++# Wireless LAN -++# -++# CONFIG_WLAN_PRE80211 is not set -++# CONFIG_WLAN_80211 is not set -++ -++# -++# USB Network Adapters -++# -++# CONFIG_USB_CATC is not set -++# CONFIG_USB_KAWETH is not set -++# CONFIG_USB_PEGASUS is not set -++# CONFIG_USB_RTL8150 is not set -++# CONFIG_USB_USBNET is not set -++# CONFIG_WAN is not set -++# CONFIG_PPP is not set -++# CONFIG_SLIP is not set -++# CONFIG_SHAPER is not set -++# CONFIG_NETCONSOLE is not set -++# CONFIG_NETPOLL is not set -++# CONFIG_NET_POLL_CONTROLLER is not set -++# CONFIG_ISDN is not set -++# CONFIG_PHONE is not set -++ -++# -++# Input device support -++# -++CONFIG_INPUT=y -++# CONFIG_INPUT_FF_MEMLESS is not set -++# CONFIG_INPUT_POLLDEV is not set -++ -++# -++# Userland interfaces -++# -++CONFIG_INPUT_MOUSEDEV=y -++CONFIG_INPUT_MOUSEDEV_PSAUX=y -++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -++# CONFIG_INPUT_JOYDEV is not set -++CONFIG_INPUT_EVDEV=y -++# CONFIG_INPUT_EVBUG is not set -++ -++# -++# Input Device Drivers -++# -++# CONFIG_INPUT_KEYBOARD is not set -++# CONFIG_INPUT_MOUSE is not set -++# CONFIG_INPUT_JOYSTICK is not set -++# CONFIG_INPUT_TABLET is not set -++# CONFIG_INPUT_TOUCHSCREEN is not set -++# CONFIG_INPUT_MISC is not set -++ -++# -++# Hardware I/O ports -++# -++CONFIG_SERIO=y -++# CONFIG_SERIO_I8042 is not set -++CONFIG_SERIO_SERPORT=y -++# CONFIG_SERIO_LIBPS2 is not set -++# CONFIG_SERIO_RAW is not set -++# CONFIG_GAMEPORT is not set -++ -++# -++# Character devices -++# -++CONFIG_VT=y -++CONFIG_VT_CONSOLE=y -++CONFIG_HW_CONSOLE=y -++CONFIG_VT_HW_CONSOLE_BINDING=y -++# CONFIG_SERIAL_NONSTANDARD is not set -++ -++# -++# Serial drivers -++# -++CONFIG_SERIAL_8250=y -++CONFIG_SERIAL_8250_CONSOLE=y -++CONFIG_SERIAL_8250_PNP=y -++CONFIG_SERIAL_8250_NR_UARTS=2 -++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 -++# CONFIG_SERIAL_8250_EXTENDED is not set -++ -++# -++# Non-8250 serial port support -++# -++CONFIG_SERIAL_CORE=y -++CONFIG_SERIAL_CORE_CONSOLE=y -++CONFIG_UNIX98_PTYS=y -++CONFIG_LEGACY_PTYS=y -++CONFIG_LEGACY_PTY_COUNT=2 -++# CONFIG_IPMI_HANDLER is not set -++# CONFIG_HW_RANDOM is not set -++# CONFIG_RTC is not set -++# CONFIG_RTC_PCF8563 is not set -++CONFIG_RTC_JZ=y -++# CONFIG_R3964 is not set -++# CONFIG_RAW_DRIVER is not set -++# CONFIG_TCG_TPM is not set -++ -++# -++# JZSOC char device support -++# -++CONFIG_JZCHAR=y -++# CONFIG_JZ_CIM is not set -++# CONFIG_JZ_TPANEL_ATA2508 is not set -++CONFIG_JZ_TPANEL=y -++CONFIG_JZ_SADC=y -++# CONFIG_JZ_TPANEL_AK4182 is not set -++# CONFIG_JZ_TPANEL_UCB1400 is not set -++# CONFIG_JZ_TPANEL_WM9712 is not set -++CONFIG_JZ_UDC_HOTPLUG=y -++CONFIG_JZ_POWEROFF=y -++# CONFIG_JZ_OW is not set -++# CONFIG_I2C is not set -++ -++# -++# SPI support -++# -++# CONFIG_SPI is not set -++# CONFIG_SPI_MASTER is not set -++# CONFIG_W1 is not set -++# CONFIG_POWER_SUPPLY is not set -++# CONFIG_HWMON is not set -++CONFIG_WATCHDOG=y -++# CONFIG_WATCHDOG_NOWAYOUT is not set -++ -++# -++# Watchdog Device Drivers -++# -++CONFIG_JZ_WDT=y -++# CONFIG_SOFT_WATCHDOG is not set -++ -++# -++# USB-based Watchdog Cards -++# -++# CONFIG_USBPCWATCHDOG is not set -++ -++# -++# Sonics Silicon Backplane -++# -++CONFIG_SSB_POSSIBLE=y -++# CONFIG_SSB is not set -++ -++# -++# Multifunction device drivers -++# -++# CONFIG_MFD_SM501 is not set -++ -++# -++# Multimedia devices -++# -++CONFIG_VIDEO_DEV=y -++CONFIG_VIDEO_V4L1=y -++CONFIG_VIDEO_V4L1_COMPAT=y -++CONFIG_VIDEO_V4L2=y -++CONFIG_VIDEO_CAPTURE_DRIVERS=y -++# CONFIG_VIDEO_ADV_DEBUG is not set -++CONFIG_VIDEO_HELPER_CHIPS_AUTO=y -++# CONFIG_VIDEO_VIVI is not set -++# CONFIG_VIDEO_CPIA is not set -++# CONFIG_VIDEO_CPIA2 is not set -++CONFIG_VIDEO_JZ_CIM=y -++CONFIG_VIDEO_JZ_SENSOR=y -++CONFIG_V4L_USB_DRIVERS=y -++# CONFIG_USB_VICAM is not set -++# CONFIG_USB_IBMCAM is not set -++# CONFIG_USB_KONICAWC is not set -++# CONFIG_USB_QUICKCAM_MESSENGER is not set -++# CONFIG_USB_ET61X251 is not set -++# CONFIG_USB_OV511 is not set -++# CONFIG_USB_SE401 is not set -++# CONFIG_USB_SN9C102 is not set -++# CONFIG_USB_STV680 is not set -++# CONFIG_USB_ZC0301 is not set -++# CONFIG_USB_PWC is not set -++# CONFIG_USB_ZR364XX is not set -++CONFIG_RADIO_ADAPTERS=y -++# CONFIG_USB_DSBR is not set -++# CONFIG_DVB_CORE is not set -++# CONFIG_DAB is not set -++ -++# -++# Graphics support -++# -++# CONFIG_VGASTATE is not set -++# CONFIG_VIDEO_OUTPUT_CONTROL is not set -++CONFIG_FB=y -++# CONFIG_FIRMWARE_EDID is not set -++# CONFIG_FB_DDC is not set -++CONFIG_FB_CFB_FILLRECT=y -++CONFIG_FB_CFB_COPYAREA=y -++CONFIG_FB_CFB_IMAGEBLIT=y -++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -++# CONFIG_FB_SYS_FILLRECT is not set -++# CONFIG_FB_SYS_COPYAREA is not set -++# CONFIG_FB_SYS_IMAGEBLIT is not set -++# CONFIG_FB_SYS_FOPS is not set -++CONFIG_FB_DEFERRED_IO=y -++# CONFIG_FB_SVGALIB is not set -++# CONFIG_FB_MACMODES is not set -++# CONFIG_FB_BACKLIGHT is not set -++# CONFIG_FB_MODE_HELPERS is not set -++# CONFIG_FB_TILEBLITTING is not set -++ -++# -++# Frame buffer hardware drivers -++# -++CONFIG_FB_JZSOC=y -++# CONFIG_FB_JZ4740_SLCD is not set -++CONFIG_FB_JZLCD_4730_4740=y -++CONFIG_JZLCD_FRAMEBUFFER_MAX=1 -++# CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT is not set -++# CONFIG_JZLCD_SHARP_LQ035Q7 is not set -++# CONFIG_JZLCD_SAMSUNG_LTS350Q1 is not set -++# CONFIG_JZLCD_SAMSUNG_LTV350QVF04 is not set -++# CONFIG_JZLCD_SAMSUNG_LTP400WQF01 is not set -++CONFIG_JZLCD_SAMSUNG_LTP400WQF02=y -++# CONFIG_JZLCD_AUO_A030FL01_V1 is not set -++# CONFIG_JZLCD_TRULY_TFTG320240DTSW is not set -++# CONFIG_JZLCD_TRULY_TFTG320240DTSW_SERIAL is not set -++# CONFIG_JZLCD_TRULY_TFTG240320UTSW_63W_E is not set -++# CONFIG_JZLCD_FOXCONN_PT035TN01 is not set -++# CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL is not set -++# CONFIG_JZLCD_TOSHIBA_LTM084P363 is not set -++# CONFIG_JZLCD_HYNIX_HT10X21 is not set -++# CONFIG_JZLCD_INNOLUX_AT080TN42 is not set -++# CONFIG_JZLCD_CSTN_800x600 is not set -++# CONFIG_JZLCD_CSTN_320x240 is not set -++# CONFIG_JZLCD_MSTN_480x320 is not set -++# CONFIG_JZLCD_MSTN_320x240 is not set -++# CONFIG_JZLCD_MSTN_240x128 is not set -++# CONFIG_FB_S1D13XXX is not set -++# CONFIG_FB_VIRTUAL is not set -++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set -++ -++# -++# Display device support -++# -++# CONFIG_DISPLAY_SUPPORT is not set -++ -++# -++# Console display driver support -++# -++# CONFIG_VGA_CONSOLE is not set -++CONFIG_DUMMY_CONSOLE=y -++CONFIG_FRAMEBUFFER_CONSOLE=y -++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -++# CONFIG_FRAMEBUFFER_CONSOLE_CURSOR_FLASH is not set -++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -++CONFIG_FONTS=y -++CONFIG_FONT_8x8=y -++CONFIG_FONT_8x16=y -++# CONFIG_FONT_6x11 is not set -++# CONFIG_FONT_7x14 is not set -++# CONFIG_FONT_PEARL_8x8 is not set -++# CONFIG_FONT_ACORN_8x8 is not set -++# CONFIG_FONT_MINI_4x6 is not set -++# CONFIG_FONT_SUN8x16 is not set -++# CONFIG_FONT_SUN12x22 is not set -++# CONFIG_FONT_10x18 is not set -++CONFIG_LOGO=y -++CONFIG_LOGO_LINUX_MONO=y -++CONFIG_LOGO_LINUX_VGA16=y -++CONFIG_LOGO_LINUX_CLUT224=y -++ -++# -++# Sound -++# -++CONFIG_SOUND=y -++ -++# -++# Advanced Linux Sound Architecture -++# -++# CONFIG_SND is not set -++ -++# -++# Open Sound System -++# -++CONFIG_SOUND_PRIME=y -++CONFIG_OSS_OBSOLETE=y -++# CONFIG_SOUND_JZ_AC97 is not set -++CONFIG_SOUND_JZ_I2S=y -++# CONFIG_SOUND_JZ_PCM is not set -++# CONFIG_I2S_AK4642EN is not set -++CONFIG_I2S_ICODEC=y -++# CONFIG_I2S_DLV is not set -++# CONFIG_SOUND_MSNDCLAS is not set -++# CONFIG_SOUND_MSNDPIN is not set -++CONFIG_HID_SUPPORT=y -++CONFIG_HID=y -++# CONFIG_HID_DEBUG is not set -++# CONFIG_HIDRAW is not set -++ -++# -++# USB Input Devices -++# -++CONFIG_USB_HID=y -++# CONFIG_USB_HIDINPUT_POWERBOOK is not set -++# CONFIG_HID_FF is not set -++# CONFIG_USB_HIDDEV is not set -++CONFIG_USB_SUPPORT=y -++CONFIG_USB_ARCH_HAS_HCD=y -++CONFIG_USB_ARCH_HAS_OHCI=y -++# CONFIG_USB_ARCH_HAS_EHCI is not set -++CONFIG_USB=y -++# CONFIG_USB_DEBUG is not set -++ -++# -++# Miscellaneous USB options -++# -++# CONFIG_USB_DEVICEFS is not set -++CONFIG_USB_DEVICE_CLASS=y -++# CONFIG_USB_DYNAMIC_MINORS is not set -++# CONFIG_USB_SUSPEND is not set -++# CONFIG_USB_PERSIST is not set -++# CONFIG_USB_OTG is not set -++ -++# -++# USB Host Controller Drivers -++# -++# CONFIG_USB_ISP116X_HCD is not set -++CONFIG_USB_OHCI_HCD=y -++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set -++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set -++CONFIG_USB_OHCI_LITTLE_ENDIAN=y -++# CONFIG_USB_SL811_HCD is not set -++# CONFIG_USB_R8A66597_HCD is not set -++ -++# -++# USB Device Class drivers -++# -++# CONFIG_USB_ACM is not set -++# CONFIG_USB_PRINTER is not set -++ -++# -++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -++# -++ -++# -++# may also be needed; see USB_STORAGE Help for more information -++# -++CONFIG_USB_STORAGE=y -++# CONFIG_USB_STORAGE_DEBUG is not set -++# CONFIG_USB_STORAGE_DATAFAB is not set -++# CONFIG_USB_STORAGE_FREECOM is not set -++# CONFIG_USB_STORAGE_ISD200 is not set -++# CONFIG_USB_STORAGE_DPCM is not set -++# CONFIG_USB_STORAGE_USBAT is not set -++# CONFIG_USB_STORAGE_SDDR09 is not set -++# CONFIG_USB_STORAGE_SDDR55 is not set -++# CONFIG_USB_STORAGE_JUMPSHOT is not set -++# CONFIG_USB_STORAGE_ALAUDA is not set -++# CONFIG_USB_STORAGE_KARMA is not set -++# CONFIG_USB_LIBUSUAL is not set -++ -++# -++# USB Imaging devices -++# -++# CONFIG_USB_MDC800 is not set -++# CONFIG_USB_MICROTEK is not set -++CONFIG_USB_MON=y -++ -++# -++# USB port drivers -++# -++ -++# -++# USB Serial Converter support -++# -++# CONFIG_USB_SERIAL is not set -++ -++# -++# USB Miscellaneous drivers -++# -++# CONFIG_USB_EMI62 is not set -++# CONFIG_USB_EMI26 is not set -++# CONFIG_USB_ADUTUX is not set -++# CONFIG_USB_AUERSWALD is not set -++# CONFIG_USB_RIO500 is not set -++# CONFIG_USB_LEGOTOWER is not set -++# CONFIG_USB_LCD is not set -++# CONFIG_USB_BERRY_CHARGE is not set -++# CONFIG_USB_LED is not set -++# CONFIG_USB_CYPRESS_CY7C63 is not set -++# CONFIG_USB_CYTHERM is not set -++# CONFIG_USB_PHIDGET is not set -++# CONFIG_USB_IDMOUSE is not set -++# CONFIG_USB_FTDI_ELAN is not set -++# CONFIG_USB_APPLEDISPLAY is not set -++# CONFIG_USB_LD is not set -++# CONFIG_USB_TRANCEVIBRATOR is not set -++# CONFIG_USB_IOWARRIOR is not set -++ -++# -++# USB DSL modem support -++# -++ -++# -++# USB Gadget Support -++# -++CONFIG_USB_GADGET=m -++# CONFIG_USB_GADGET_DEBUG_FILES is not set -++# CONFIG_USB_GADGET_DEBUG_FS is not set -++CONFIG_USB_GADGET_SELECTED=y -++CONFIG_USB_GADGET_JZ4740=y -++CONFIG_USB_JZ4740=m -++# CONFIG_USB_GADGET_JZ4730 is not set -++# CONFIG_USB_GADGET_AMD5536UDC is not set -++# CONFIG_USB_GADGET_ATMEL_USBA is not set -++# CONFIG_USB_GADGET_FSL_USB2 is not set -++# CONFIG_USB_GADGET_NET2280 is not set -++# CONFIG_USB_GADGET_PXA2XX is not set -++# CONFIG_USB_GADGET_M66592 is not set -++# CONFIG_USB_GADGET_GOKU is not set -++# CONFIG_USB_GADGET_LH7A40X is not set -++# CONFIG_USB_GADGET_OMAP is not set -++# CONFIG_USB_GADGET_S3C2410 is not set -++# CONFIG_USB_GADGET_AT91 is not set -++# CONFIG_USB_GADGET_DUMMY_HCD is not set -++CONFIG_USB_GADGET_DUALSPEED=y -++# CONFIG_USB_ZERO is not set -++# CONFIG_USB_ETH is not set -++# CONFIG_USB_GADGETFS is not set -++CONFIG_USB_FILE_STORAGE=m -++# CONFIG_USB_FILE_STORAGE_TEST is not set -++# CONFIG_USB_G_SERIAL is not set -++# CONFIG_USB_MIDI_GADGET is not set -++CONFIG_MMC=y -++# CONFIG_MMC_DEBUG is not set -++# CONFIG_MMC_UNSAFE_RESUME is not set -++ -++# -++# MMC/SD Card Drivers -++# -++CONFIG_MMC_BLOCK=y -++CONFIG_MMC_BLOCK_BOUNCE=y -++# CONFIG_SDIO_UART is not set -++ -++# -++# MMC/SD Host Controller Drivers -++# -++CONFIG_MMC_JZ=y -++# CONFIG_JZ_MMC_BUS_1 is not set -++CONFIG_JZ_MMC_BUS_4=y -++# CONFIG_NEW_LEDS is not set -++CONFIG_RTC_LIB=y -++# CONFIG_RTC_CLASS is not set -++ -++# -++# Userspace I/O -++# -++# CONFIG_UIO is not set -++ -++# -++# File systems -++# -++CONFIG_EXT2_FS=y -++CONFIG_EXT2_FS_XATTR=y -++# CONFIG_EXT2_FS_POSIX_ACL is not set -++# CONFIG_EXT2_FS_SECURITY is not set -++# CONFIG_EXT2_FS_XIP is not set -++# CONFIG_EXT3_FS is not set -++# CONFIG_EXT4DEV_FS is not set -++CONFIG_FS_MBCACHE=y -++# CONFIG_REISERFS_FS is not set -++# CONFIG_JFS_FS is not set -++CONFIG_FS_POSIX_ACL=y -++# CONFIG_XFS_FS is not set -++# CONFIG_GFS2_FS is not set -++# CONFIG_OCFS2_FS is not set -++CONFIG_MINIX_FS=y -++# CONFIG_ROMFS_FS is not set -++CONFIG_INOTIFY=y -++CONFIG_INOTIFY_USER=y -++# CONFIG_QUOTA is not set -++CONFIG_DNOTIFY=y -++# CONFIG_AUTOFS_FS is not set -++# CONFIG_AUTOFS4_FS is not set -++# CONFIG_FUSE_FS is not set -++ -++# -++# CD-ROM/DVD Filesystems -++# -++# CONFIG_ISO9660_FS is not set -++# CONFIG_UDF_FS is not set -++ -++# -++# DOS/FAT/NT Filesystems -++# -++CONFIG_FAT_FS=y -++CONFIG_MSDOS_FS=y -++CONFIG_VFAT_FS=y -++CONFIG_FAT_DEFAULT_CODEPAGE=437 -++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -++# CONFIG_NTFS_FS is not set -++ -++# -++# Pseudo filesystems -++# -++CONFIG_PROC_FS=y -++CONFIG_PROC_KCORE=y -++CONFIG_PROC_SYSCTL=y -++CONFIG_SYSFS=y -++CONFIG_TMPFS=y -++# CONFIG_TMPFS_POSIX_ACL is not set -++# CONFIG_HUGETLB_PAGE is not set -++# CONFIG_CONFIGFS_FS is not set -++ -++# -++# Miscellaneous filesystems -++# -++# CONFIG_ADFS_FS is not set -++# CONFIG_AFFS_FS is not set -++# CONFIG_HFS_FS is not set -++# CONFIG_HFSPLUS_FS is not set -++# CONFIG_BEFS_FS is not set -++# CONFIG_BFS_FS is not set -++# CONFIG_EFS_FS is not set -++# CONFIG_JFFS2_FS is not set -++CONFIG_UBIFS_FS=m -++# CONFIG_UBIFS_FS_XATTR is not set -++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set -++CONFIG_UBIFS_FS_LZO=y -++CONFIG_UBIFS_FS_ZLIB=y -++# CONFIG_UBIFS_FS_DEBUG is not set -++# CONFIG_CRAMFS is not set -++# CONFIG_VXFS_FS is not set -++# CONFIG_HPFS_FS is not set -++# CONFIG_QNX4FS_FS is not set -++# CONFIG_SYSV_FS is not set -++# CONFIG_UFS_FS is not set -++CONFIG_NETWORK_FILESYSTEMS=y -++CONFIG_NFS_FS=y -++CONFIG_NFS_V3=y -++CONFIG_NFS_V3_ACL=y -++CONFIG_NFS_V4=y -++CONFIG_NFS_DIRECTIO=y -++# CONFIG_NFSD is not set -++CONFIG_ROOT_NFS=y -++CONFIG_LOCKD=y -++CONFIG_LOCKD_V4=y -++CONFIG_NFS_ACL_SUPPORT=y -++CONFIG_NFS_COMMON=y -++CONFIG_SUNRPC=y -++CONFIG_SUNRPC_GSS=y -++# CONFIG_SUNRPC_BIND34 is not set -++CONFIG_RPCSEC_GSS_KRB5=y -++# CONFIG_RPCSEC_GSS_SPKM3 is not set -++# CONFIG_SMB_FS is not set -++# CONFIG_CIFS is not set -++# CONFIG_NCP_FS is not set -++# CONFIG_CODA_FS is not set -++# CONFIG_AFS_FS is not set -++ -++# -++# Partition Types -++# -++CONFIG_PARTITION_ADVANCED=y -++# CONFIG_ACORN_PARTITION is not set -++# CONFIG_OSF_PARTITION is not set -++# CONFIG_AMIGA_PARTITION is not set -++# CONFIG_ATARI_PARTITION is not set -++# CONFIG_MAC_PARTITION is not set -++CONFIG_MSDOS_PARTITION=y -++# CONFIG_BSD_DISKLABEL is not set -++# CONFIG_MINIX_SUBPARTITION is not set -++# CONFIG_SOLARIS_X86_PARTITION is not set -++# CONFIG_UNIXWARE_DISKLABEL is not set -++# CONFIG_LDM_PARTITION is not set -++# CONFIG_SGI_PARTITION is not set -++# CONFIG_ULTRIX_PARTITION is not set -++# CONFIG_SUN_PARTITION is not set -++# CONFIG_KARMA_PARTITION is not set -++# CONFIG_EFI_PARTITION is not set -++# CONFIG_SYSV68_PARTITION is not set -++CONFIG_NLS=y -++CONFIG_NLS_DEFAULT="iso8859-1" -++CONFIG_NLS_CODEPAGE_437=y -++# CONFIG_NLS_CODEPAGE_737 is not set -++# CONFIG_NLS_CODEPAGE_775 is not set -++# CONFIG_NLS_CODEPAGE_850 is not set -++# CONFIG_NLS_CODEPAGE_852 is not set -++# CONFIG_NLS_CODEPAGE_855 is not set -++# CONFIG_NLS_CODEPAGE_857 is not set -++# CONFIG_NLS_CODEPAGE_860 is not set -++# CONFIG_NLS_CODEPAGE_861 is not set -++# CONFIG_NLS_CODEPAGE_862 is not set -++# CONFIG_NLS_CODEPAGE_863 is not set -++# CONFIG_NLS_CODEPAGE_864 is not set -++# CONFIG_NLS_CODEPAGE_865 is not set -++# CONFIG_NLS_CODEPAGE_866 is not set -++# CONFIG_NLS_CODEPAGE_869 is not set -++CONFIG_NLS_CODEPAGE_936=y -++# CONFIG_NLS_CODEPAGE_950 is not set -++# CONFIG_NLS_CODEPAGE_932 is not set -++# CONFIG_NLS_CODEPAGE_949 is not set -++# CONFIG_NLS_CODEPAGE_874 is not set -++# CONFIG_NLS_ISO8859_8 is not set -++# CONFIG_NLS_CODEPAGE_1250 is not set -++# CONFIG_NLS_CODEPAGE_1251 is not set -++CONFIG_NLS_ASCII=y -++CONFIG_NLS_ISO8859_1=y -++# CONFIG_NLS_ISO8859_2 is not set -++# CONFIG_NLS_ISO8859_3 is not set -++# CONFIG_NLS_ISO8859_4 is not set -++# CONFIG_NLS_ISO8859_5 is not set -++# CONFIG_NLS_ISO8859_6 is not set -++# CONFIG_NLS_ISO8859_7 is not set -++# CONFIG_NLS_ISO8859_9 is not set -++# CONFIG_NLS_ISO8859_13 is not set -++# CONFIG_NLS_ISO8859_14 is not set -++# CONFIG_NLS_ISO8859_15 is not set -++# CONFIG_NLS_KOI8_R is not set -++# CONFIG_NLS_KOI8_U is not set -++# CONFIG_NLS_UTF8 is not set -++# CONFIG_DLM is not set -++ -++# -++# Yaffs2 Filesystems -++# -++CONFIG_YAFFS_FS=y -++CONFIG_YAFFS_YAFFS1=y -++# CONFIG_YAFFS_DOES_ECC is not set -++CONFIG_YAFFS_YAFFS2=y -++# CONFIG_YAFFS_ECC_BCH is not set -++CONFIG_YAFFS_ECC_RS=y -++# CONFIG_YAFFS_ECC_HAMMING is not set -++CONFIG_YAFFS_AUTO_YAFFS2=y -++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set -++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set -++CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK=y -++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y -++CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10 -++CONFIG_INSTRUMENTATION=y -++# CONFIG_PROFILING is not set -++# CONFIG_MARKERS is not set -++ -++# -++# Kernel hacking -++# -++CONFIG_TRACE_IRQFLAGS_SUPPORT=y -++# CONFIG_PRINTK_TIME is not set -++CONFIG_ENABLE_WARN_DEPRECATED=y -++CONFIG_ENABLE_MUST_CHECK=y -++CONFIG_MAGIC_SYSRQ=y -++# CONFIG_UNUSED_SYMBOLS is not set -++CONFIG_DEBUG_FS=y -++# CONFIG_HEADERS_CHECK is not set -++# CONFIG_DEBUG_KERNEL is not set -++# CONFIG_SAMPLES is not set -++CONFIG_CMDLINE="" -++ -++# -++# Security options -++# -++# CONFIG_KEYS is not set -++# CONFIG_SECURITY is not set -++# CONFIG_SECURITY_FILE_CAPABILITIES is not set -++CONFIG_CRYPTO=y -++CONFIG_CRYPTO_ALGAPI=y -++CONFIG_CRYPTO_BLKCIPHER=y -++CONFIG_CRYPTO_MANAGER=y -++# CONFIG_CRYPTO_HMAC is not set -++# CONFIG_CRYPTO_XCBC is not set -++# CONFIG_CRYPTO_NULL is not set -++# CONFIG_CRYPTO_MD4 is not set -++CONFIG_CRYPTO_MD5=y -++# CONFIG_CRYPTO_SHA1 is not set -++# CONFIG_CRYPTO_SHA256 is not set -++# CONFIG_CRYPTO_SHA512 is not set -++# CONFIG_CRYPTO_WP512 is not set -++# CONFIG_CRYPTO_TGR192 is not set -++# CONFIG_CRYPTO_GF128MUL is not set -++# CONFIG_CRYPTO_ECB is not set -++CONFIG_CRYPTO_CBC=y -++# CONFIG_CRYPTO_PCBC is not set -++# CONFIG_CRYPTO_LRW is not set -++# CONFIG_CRYPTO_XTS is not set -++# CONFIG_CRYPTO_CRYPTD is not set -++CONFIG_CRYPTO_DES=y -++# CONFIG_CRYPTO_FCRYPT is not set -++# CONFIG_CRYPTO_BLOWFISH is not set -++# CONFIG_CRYPTO_TWOFISH is not set -++# CONFIG_CRYPTO_SERPENT is not set -++# CONFIG_CRYPTO_AES is not set -++# CONFIG_CRYPTO_CAST5 is not set -++# CONFIG_CRYPTO_CAST6 is not set -++# CONFIG_CRYPTO_TEA is not set -++# CONFIG_CRYPTO_ARC4 is not set -++# CONFIG_CRYPTO_KHAZAD is not set -++# CONFIG_CRYPTO_ANUBIS is not set -++# CONFIG_CRYPTO_SEED is not set -++CONFIG_CRYPTO_DEFLATE=m -++# CONFIG_CRYPTO_MICHAEL_MIC is not set -++# CONFIG_CRYPTO_CRC32C is not set -++# CONFIG_CRYPTO_CAMELLIA is not set -++# CONFIG_CRYPTO_TEST is not set -++# CONFIG_CRYPTO_AUTHENC is not set -++CONFIG_CRYPTO_LZO=m -++CONFIG_CRYPTO_HW=y -++ -++# -++# Library routines -++# -++CONFIG_BITREVERSE=y -++# CONFIG_CRC_CCITT is not set -++CONFIG_CRC16=m -++# CONFIG_CRC_ITU_T is not set -++CONFIG_CRC32=y -++# CONFIG_CRC7 is not set -++# CONFIG_LIBCRC32C is not set -++CONFIG_ZLIB_INFLATE=m -++CONFIG_ZLIB_DEFLATE=m -++CONFIG_LZO_COMPRESS=m -++CONFIG_LZO_DECOMPRESS=m -++CONFIG_REED_SOLOMON=y -++CONFIG_REED_SOLOMON_ENC8=y -++CONFIG_REED_SOLOMON_DEC8=y -++CONFIG_PLIST=y -++CONFIG_HAS_IOMEM=y -++CONFIG_HAS_IOPORT=y -++CONFIG_HAS_DMA=y -+diff -urN linux-2.6.24.7.old/arch/mips/configs/pmp_defconfig linux-2.6.24.7/arch/mips/configs/pmp_defconfig -+--- linux-2.6.24.7.old/arch/mips/configs/pmp_defconfig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/configs/pmp_defconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1212 @@ -++# -++# Automatically generated make config: don't edit -++# Linux kernel version: 2.6.24.3 -++# Thu Jun 12 13:37:10 2008 -++# -++CONFIG_MIPS=y -++ -++# -++# Machine selection -++# -++CONFIG_JZ4730_PMP=y -++# CONFIG_JZ4740_PAVO is not set -++# CONFIG_JZ4740_LEO is not set -++# CONFIG_JZ4740_LYRA is not set -++# CONFIG_JZ4725_DIPPER is not set -++# CONFIG_JZ4720_VIRGO is not set -++# CONFIG_JZ4750_FUWA is not set -++# CONFIG_MACH_ALCHEMY is not set -++# CONFIG_BASLER_EXCITE is not set -++# CONFIG_BCM47XX is not set -++# CONFIG_MIPS_COBALT is not set -++# CONFIG_MACH_DECSTATION is not set -++# CONFIG_MACH_JAZZ is not set -++# CONFIG_LASAT is not set -++# CONFIG_LEMOTE_FULONG is not set -++# CONFIG_MIPS_ATLAS is not set -++# CONFIG_MIPS_MALTA is not set -++# CONFIG_MIPS_SEAD is not set -++# CONFIG_MIPS_SIM is not set -++# CONFIG_MARKEINS is not set -++# CONFIG_MACH_VR41XX is not set -++# CONFIG_PNX8550_JBS is not set -++# CONFIG_PNX8550_STB810 is not set -++# CONFIG_PMC_MSP is not set -++# CONFIG_PMC_YOSEMITE is not set -++# CONFIG_QEMU is not set -++# CONFIG_SGI_IP22 is not set -++# CONFIG_SGI_IP27 is not set -++# CONFIG_SGI_IP32 is not set -++# CONFIG_SIBYTE_CRHINE is not set -++# CONFIG_SIBYTE_CARMEL is not set -++# CONFIG_SIBYTE_CRHONE is not set -++# CONFIG_SIBYTE_RHONE is not set -++# CONFIG_SIBYTE_SWARM is not set -++# CONFIG_SIBYTE_LITTLESUR is not set -++# CONFIG_SIBYTE_SENTOSA is not set -++# CONFIG_SIBYTE_PTSWARM is not set -++# CONFIG_SIBYTE_BIGSUR is not set -++# CONFIG_SNI_RM is not set -++# CONFIG_TOSHIBA_JMR3927 is not set -++# CONFIG_TOSHIBA_RBTX4927 is not set -++# CONFIG_TOSHIBA_RBTX4938 is not set -++# CONFIG_WR_PPMC is not set -++CONFIG_SOC_JZ4730=y -++CONFIG_JZSOC=y -++CONFIG_JZRISC=y -++CONFIG_RWSEM_GENERIC_SPINLOCK=y -++# CONFIG_ARCH_HAS_ILOG2_U32 is not set -++# CONFIG_ARCH_HAS_ILOG2_U64 is not set -++CONFIG_ARCH_SUPPORTS_OPROFILE=y -++CONFIG_GENERIC_FIND_NEXT_BIT=y -++CONFIG_GENERIC_HWEIGHT=y -++CONFIG_GENERIC_CALIBRATE_DELAY=y -++CONFIG_GENERIC_CLOCKEVENTS=y -++CONFIG_GENERIC_TIME=y -++CONFIG_GENERIC_CMOS_UPDATE=y -++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -++# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set -++CONFIG_DMA_NONCOHERENT=y -++CONFIG_DMA_NEED_PCI_MAP_STATE=y -++# CONFIG_HOTPLUG_CPU is not set -++# CONFIG_NO_IOPORT is not set -++# CONFIG_CPU_BIG_ENDIAN is not set -++CONFIG_CPU_LITTLE_ENDIAN=y -++CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -++CONFIG_MIPS_L1_CACHE_SHIFT=5 -++ -++# -++# CPU selection -++# -++# CONFIG_CPU_LOONGSON2 is not set -++CONFIG_CPU_MIPS32_R1=y -++# CONFIG_CPU_MIPS32_R2 is not set -++# CONFIG_CPU_MIPS64_R1 is not set -++# CONFIG_CPU_MIPS64_R2 is not set -++# CONFIG_CPU_R3000 is not set -++# CONFIG_CPU_TX39XX is not set -++# CONFIG_CPU_VR41XX is not set -++# CONFIG_CPU_R4300 is not set -++# CONFIG_CPU_R4X00 is not set -++# CONFIG_CPU_TX49XX is not set -++# CONFIG_CPU_R5000 is not set -++# CONFIG_CPU_R5432 is not set -++# CONFIG_CPU_R6000 is not set -++# CONFIG_CPU_NEVADA is not set -++# CONFIG_CPU_R8000 is not set -++# CONFIG_CPU_R10000 is not set -++# CONFIG_CPU_RM7000 is not set -++# CONFIG_CPU_RM9000 is not set -++# CONFIG_CPU_SB1 is not set -++CONFIG_SYS_HAS_CPU_MIPS32_R1=y -++CONFIG_CPU_MIPS32=y -++CONFIG_CPU_MIPSR1=y -++CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -++CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -++ -++# -++# Kernel type -++# -++CONFIG_32BIT=y -++# CONFIG_64BIT is not set -++CONFIG_PAGE_SIZE_4KB=y -++# CONFIG_PAGE_SIZE_8KB is not set -++# CONFIG_PAGE_SIZE_16KB is not set -++# CONFIG_PAGE_SIZE_64KB is not set -++CONFIG_CPU_HAS_PREFETCH=y -++CONFIG_MIPS_MT_DISABLED=y -++# CONFIG_MIPS_MT_SMP is not set -++# CONFIG_MIPS_MT_SMTC is not set -++CONFIG_CPU_HAS_LLSC=y -++CONFIG_CPU_HAS_SYNC=y -++CONFIG_GENERIC_HARDIRQS=y -++CONFIG_GENERIC_IRQ_PROBE=y -++CONFIG_CPU_SUPPORTS_HIGHMEM=y -++CONFIG_ARCH_FLATMEM_ENABLE=y -++CONFIG_ARCH_POPULATES_NODE_MAP=y -++CONFIG_SELECT_MEMORY_MODEL=y -++CONFIG_FLATMEM_MANUAL=y -++# CONFIG_DISCONTIGMEM_MANUAL is not set -++# CONFIG_SPARSEMEM_MANUAL is not set -++CONFIG_FLATMEM=y -++CONFIG_FLAT_NODE_MEM_MAP=y -++# CONFIG_SPARSEMEM_STATIC is not set -++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -++CONFIG_SPLIT_PTLOCK_CPUS=4 -++# CONFIG_RESOURCES_64BIT is not set -++CONFIG_ZONE_DMA_FLAG=0 -++CONFIG_VIRT_TO_BUS=y -++# CONFIG_TICK_ONESHOT is not set -++# CONFIG_NO_HZ is not set -++# CONFIG_HIGH_RES_TIMERS is not set -++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -++# CONFIG_HZ_48 is not set -++CONFIG_HZ_100=y -++# CONFIG_HZ_128 is not set -++# CONFIG_HZ_250 is not set -++# CONFIG_HZ_256 is not set -++# CONFIG_HZ_1000 is not set -++# CONFIG_HZ_1024 is not set -++CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -++CONFIG_HZ=100 -++# CONFIG_PREEMPT_NONE is not set -++# CONFIG_PREEMPT_VOLUNTARY is not set -++CONFIG_PREEMPT=y -++CONFIG_PREEMPT_BKL=y -++# CONFIG_KEXEC is not set -++CONFIG_SECCOMP=y -++CONFIG_LOCKDEP_SUPPORT=y -++CONFIG_STACKTRACE_SUPPORT=y -++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -++ -++# -++# General setup -++# -++CONFIG_EXPERIMENTAL=y -++CONFIG_BROKEN_ON_SMP=y -++CONFIG_LOCK_KERNEL=y -++CONFIG_INIT_ENV_ARG_LIMIT=32 -++CONFIG_LOCALVERSION="" -++CONFIG_LOCALVERSION_AUTO=y -++CONFIG_SWAP=y -++CONFIG_SYSVIPC=y -++CONFIG_SYSVIPC_SYSCTL=y -++# CONFIG_POSIX_MQUEUE is not set -++# CONFIG_BSD_PROCESS_ACCT is not set -++# CONFIG_TASKSTATS is not set -++# CONFIG_USER_NS is not set -++# CONFIG_PID_NS is not set -++# CONFIG_AUDIT is not set -++# CONFIG_IKCONFIG is not set -++CONFIG_LOG_BUF_SHIFT=14 -++# CONFIG_CGROUPS is not set -++CONFIG_FAIR_GROUP_SCHED=y -++CONFIG_FAIR_USER_SCHED=y -++# CONFIG_FAIR_CGROUP_SCHED is not set -++CONFIG_SYSFS_DEPRECATED=y -++CONFIG_RELAY=y -++# CONFIG_BLK_DEV_INITRD is not set -++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -++CONFIG_SYSCTL=y -++CONFIG_EMBEDDED=y -++CONFIG_SYSCTL_SYSCALL=y -++CONFIG_KALLSYMS=y -++# CONFIG_KALLSYMS_EXTRA_PASS is not set -++CONFIG_HOTPLUG=y -++CONFIG_PRINTK=y -++CONFIG_BUG=y -++CONFIG_ELF_CORE=y -++CONFIG_BASE_FULL=y -++CONFIG_FUTEX=y -++CONFIG_ANON_INODES=y -++CONFIG_EPOLL=y -++CONFIG_SIGNALFD=y -++CONFIG_EVENTFD=y -++CONFIG_SHMEM=y -++CONFIG_VM_EVENT_COUNTERS=y -++CONFIG_SLAB=y -++# CONFIG_SLUB is not set -++# CONFIG_SLOB is not set -++CONFIG_SLABINFO=y -++CONFIG_RT_MUTEXES=y -++# CONFIG_TINY_SHMEM is not set -++CONFIG_BASE_SMALL=0 -++CONFIG_MODULES=y -++CONFIG_MODULE_UNLOAD=y -++# CONFIG_MODULE_FORCE_UNLOAD is not set -++CONFIG_MODVERSIONS=y -++CONFIG_MODULE_SRCVERSION_ALL=y -++CONFIG_KMOD=y -++CONFIG_BLOCK=y -++# CONFIG_LBD is not set -++# CONFIG_BLK_DEV_IO_TRACE is not set -++# CONFIG_LSF is not set -++# CONFIG_BLK_DEV_BSG is not set -++ -++# -++# IO Schedulers -++# -++CONFIG_IOSCHED_NOOP=y -++CONFIG_IOSCHED_AS=y -++CONFIG_IOSCHED_DEADLINE=y -++CONFIG_IOSCHED_CFQ=y -++CONFIG_DEFAULT_AS=y -++# CONFIG_DEFAULT_DEADLINE is not set -++# CONFIG_DEFAULT_CFQ is not set -++# CONFIG_DEFAULT_NOOP is not set -++CONFIG_DEFAULT_IOSCHED="anticipatory" -++ -++# -++# Bus options (PCI, PCMCIA, EISA, ISA, TC) -++# -++# CONFIG_ARCH_SUPPORTS_MSI is not set -++CONFIG_MMU=y -++# CONFIG_PCCARD is not set -++ -++# -++# Executable file formats -++# -++CONFIG_BINFMT_ELF=y -++# CONFIG_BINFMT_MISC is not set -++CONFIG_TRAD_SIGNALS=y -++ -++# -++# CPU Frequency scaling -++# -++CONFIG_CPU_FREQ_JZ=y -++CONFIG_CPU_FREQ=y -++CONFIG_CPU_FREQ_TABLE=y -++# CONFIG_CPU_FREQ_DEBUG is not set -++CONFIG_CPU_FREQ_STAT=y -++# CONFIG_CPU_FREQ_STAT_DETAILS is not set -++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -++CONFIG_CPU_FREQ_GOV_USERSPACE=y -++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set -++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -++ -++# -++# Power management options -++# -++CONFIG_PM=y -++CONFIG_PM_LEGACY=y -++# CONFIG_PM_DEBUG is not set -++CONFIG_PM_SLEEP=y -++CONFIG_SUSPEND_UP_POSSIBLE=y -++CONFIG_SUSPEND=y -++ -++# -++# Networking -++# -++CONFIG_NET=y -++ -++# -++# Networking options -++# -++CONFIG_PACKET=y -++# CONFIG_PACKET_MMAP is not set -++CONFIG_UNIX=y -++# CONFIG_NET_KEY is not set -++CONFIG_INET=y -++# CONFIG_IP_MULTICAST is not set -++# CONFIG_IP_ADVANCED_ROUTER is not set -++CONFIG_IP_FIB_HASH=y -++CONFIG_IP_PNP=y -++CONFIG_IP_PNP_DHCP=y -++CONFIG_IP_PNP_BOOTP=y -++# CONFIG_IP_PNP_RARP is not set -++# CONFIG_NET_IPIP is not set -++# CONFIG_NET_IPGRE is not set -++# CONFIG_ARPD is not set -++# CONFIG_SYN_COOKIES is not set -++# CONFIG_INET_AH is not set -++# CONFIG_INET_ESP is not set -++# CONFIG_INET_IPCOMP is not set -++# CONFIG_INET_XFRM_TUNNEL is not set -++# CONFIG_INET_TUNNEL is not set -++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -++# CONFIG_INET_XFRM_MODE_TUNNEL is not set -++# CONFIG_INET_XFRM_MODE_BEET is not set -++# CONFIG_INET_LRO is not set -++# CONFIG_INET_DIAG is not set -++# CONFIG_TCP_CONG_ADVANCED is not set -++CONFIG_TCP_CONG_CUBIC=y -++CONFIG_DEFAULT_TCP_CONG="cubic" -++# CONFIG_TCP_MD5SIG is not set -++# CONFIG_IPV6 is not set -++# CONFIG_INET6_XFRM_TUNNEL is not set -++# CONFIG_INET6_TUNNEL is not set -++# CONFIG_NETWORK_SECMARK is not set -++# CONFIG_NETFILTER is not set -++# CONFIG_IP_DCCP is not set -++# CONFIG_IP_SCTP is not set -++# CONFIG_TIPC is not set -++# CONFIG_ATM is not set -++# CONFIG_BRIDGE is not set -++# CONFIG_VLAN_8021Q is not set -++# CONFIG_DECNET is not set -++# CONFIG_LLC2 is not set -++# CONFIG_IPX is not set -++# CONFIG_ATALK is not set -++# CONFIG_X25 is not set -++# CONFIG_LAPB is not set -++# CONFIG_ECONET is not set -++# CONFIG_WAN_ROUTER is not set -++# CONFIG_NET_SCHED is not set -++ -++# -++# Network testing -++# -++# CONFIG_NET_PKTGEN is not set -++# CONFIG_HAMRADIO is not set -++# CONFIG_IRDA is not set -++# CONFIG_BT is not set -++# CONFIG_AF_RXRPC is not set -++ -++# -++# Wireless -++# -++# CONFIG_CFG80211 is not set -++# CONFIG_WIRELESS_EXT is not set -++# CONFIG_MAC80211 is not set -++# CONFIG_IEEE80211 is not set -++# CONFIG_RFKILL is not set -++# CONFIG_NET_9P is not set -++ -++# -++# Device Drivers -++# -++ -++# -++# Generic Driver Options -++# -++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -++CONFIG_STANDALONE=y -++CONFIG_PREVENT_FIRMWARE_BUILD=y -++# CONFIG_FW_LOADER is not set -++# CONFIG_SYS_HYPERVISOR is not set -++# CONFIG_CONNECTOR is not set -++CONFIG_MTD=y -++# CONFIG_MTD_DEBUG is not set -++CONFIG_MTD_CONCAT=y -++CONFIG_MTD_PARTITIONS=y -++# CONFIG_MTD_REDBOOT_PARTS is not set -++# CONFIG_MTD_CMDLINE_PARTS is not set -++ -++# -++# User Modules And Translation Layers -++# -++CONFIG_MTD_CHAR=y -++CONFIG_MTD_BLKDEVS=y -++CONFIG_MTD_BLOCK=y -++# CONFIG_FTL is not set -++# CONFIG_NFTL is not set -++# CONFIG_INFTL is not set -++# CONFIG_RFD_FTL is not set -++# CONFIG_SSFDC is not set -++# CONFIG_MTD_OOPS is not set -++ -++# -++# RAM/ROM/Flash chip drivers -++# -++# CONFIG_MTD_CFI is not set -++# CONFIG_MTD_JEDECPROBE is not set -++CONFIG_MTD_MAP_BANK_WIDTH_1=y -++CONFIG_MTD_MAP_BANK_WIDTH_2=y -++CONFIG_MTD_MAP_BANK_WIDTH_4=y -++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -++CONFIG_MTD_CFI_I1=y -++CONFIG_MTD_CFI_I2=y -++# CONFIG_MTD_CFI_I4 is not set -++# CONFIG_MTD_CFI_I8 is not set -++# CONFIG_MTD_RAM is not set -++# CONFIG_MTD_ROM is not set -++# CONFIG_MTD_ABSENT is not set -++ -++# -++# Mapping drivers for chip access -++# -++# CONFIG_MTD_COMPLEX_MAPPINGS is not set -++# CONFIG_MTD_PLATRAM is not set -++ -++# -++# Self-contained MTD device drivers -++# -++# CONFIG_MTD_SLRAM is not set -++# CONFIG_MTD_PHRAM is not set -++# CONFIG_MTD_MTDRAM is not set -++# CONFIG_MTD_BLOCK2MTD is not set -++ -++# -++# Disk-On-Chip Device Drivers -++# -++# CONFIG_MTD_DOC2000 is not set -++# CONFIG_MTD_DOC2001 is not set -++# CONFIG_MTD_DOC2001PLUS is not set -++CONFIG_MTD_NAND=y -++# CONFIG_MTD_NAND_VERIFY_WRITE is not set -++# CONFIG_MTD_NAND_ECC_SMC is not set -++# CONFIG_MTD_NAND_MUSEUM_IDS is not set -++CONFIG_MTD_NAND_IDS=y -++# CONFIG_MTD_NAND_DISKONCHIP is not set -++# CONFIG_MTD_NAND_NANDSIM is not set -++# CONFIG_MTD_NAND_PLATFORM is not set -++# CONFIG_MTD_ALAUDA is not set -++CONFIG_MTD_NAND_JZ4730=y -++CONFIG_MTD_HW_HM_ECC=y -++# CONFIG_MTD_SW_HM_ECC is not set -++# CONFIG_MTD_HW_RS_ECC is not set -++# CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE is not set -++CONFIG_MTD_OOB_COPIES=3 -++CONFIG_MTD_BADBLOCK_FLAG_PAGE=0 -++# CONFIG_MTD_ONENAND is not set -++ -++# -++# UBI - Unsorted block images -++# -++# CONFIG_MTD_UBI is not set -++# CONFIG_MTD_UBI_BLKDEVS is not set -++# CONFIG_PARPORT is not set -++# CONFIG_PNP is not set -++CONFIG_BLK_DEV=y -++# CONFIG_BLK_DEV_COW_COMMON is not set -++CONFIG_BLK_DEV_LOOP=y -++# CONFIG_BLK_DEV_CRYPTOLOOP is not set -++# CONFIG_BLK_DEV_NBD is not set -++# CONFIG_BLK_DEV_UB is not set -++CONFIG_BLK_DEV_RAM=y -++CONFIG_BLK_DEV_RAM_COUNT=16 -++CONFIG_BLK_DEV_RAM_SIZE=4096 -++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -++# CONFIG_CDROM_PKTCDVD is not set -++# CONFIG_ATA_OVER_ETH is not set -++CONFIG_MISC_DEVICES=y -++# CONFIG_EEPROM_93CX6 is not set -++# CONFIG_IDE is not set -++ -++# -++# SCSI device support -++# -++# CONFIG_RAID_ATTRS is not set -++CONFIG_SCSI=y -++CONFIG_SCSI_DMA=y -++# CONFIG_SCSI_TGT is not set -++# CONFIG_SCSI_NETLINK is not set -++CONFIG_SCSI_PROC_FS=y -++ -++# -++# SCSI support type (disk, tape, CD-ROM) -++# -++CONFIG_BLK_DEV_SD=y -++# CONFIG_CHR_DEV_ST is not set -++# CONFIG_CHR_DEV_OSST is not set -++# CONFIG_BLK_DEV_SR is not set -++# CONFIG_CHR_DEV_SG is not set -++# CONFIG_CHR_DEV_SCH is not set -++ -++# -++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -++# -++# CONFIG_SCSI_MULTI_LUN is not set -++# CONFIG_SCSI_CONSTANTS is not set -++# CONFIG_SCSI_LOGGING is not set -++# CONFIG_SCSI_SCAN_ASYNC is not set -++CONFIG_SCSI_WAIT_SCAN=m -++ -++# -++# SCSI Transports -++# -++# CONFIG_SCSI_SPI_ATTRS is not set -++# CONFIG_SCSI_FC_ATTRS is not set -++# CONFIG_SCSI_ISCSI_ATTRS is not set -++# CONFIG_SCSI_SAS_LIBSAS is not set -++# CONFIG_SCSI_SRP_ATTRS is not set -++CONFIG_SCSI_LOWLEVEL=y -++# CONFIG_ISCSI_TCP is not set -++# CONFIG_SCSI_DEBUG is not set -++# CONFIG_ATA is not set -++# CONFIG_MD is not set -++CONFIG_NETDEVICES=y -++# CONFIG_NETDEVICES_MULTIQUEUE is not set -++# CONFIG_DUMMY is not set -++# CONFIG_BONDING is not set -++# CONFIG_MACVLAN is not set -++# CONFIG_EQUALIZER is not set -++# CONFIG_TUN is not set -++# CONFIG_VETH is not set -++CONFIG_PHYLIB=y -++ -++# -++# MII PHY device drivers -++# -++# CONFIG_MARVELL_PHY is not set -++# CONFIG_DAVICOM_PHY is not set -++# CONFIG_QSEMI_PHY is not set -++# CONFIG_LXT_PHY is not set -++# CONFIG_CICADA_PHY is not set -++# CONFIG_VITESSE_PHY is not set -++# CONFIG_SMSC_PHY is not set -++# CONFIG_BROADCOM_PHY is not set -++# CONFIG_ICPLUS_PHY is not set -++# CONFIG_FIXED_PHY is not set -++# CONFIG_MDIO_BITBANG is not set -++CONFIG_NET_ETHERNET=y -++CONFIG_MII=y -++CONFIG_JZ_ETH=y -++# CONFIG_AX88796 is not set -++# CONFIG_DM9000 is not set -++# CONFIG_IBM_NEW_EMAC_ZMII is not set -++# CONFIG_IBM_NEW_EMAC_RGMII is not set -++# CONFIG_IBM_NEW_EMAC_TAH is not set -++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -++# CONFIG_B44 is not set -++# CONFIG_NETDEV_1000 is not set -++# CONFIG_NETDEV_10000 is not set -++ -++# -++# Wireless LAN -++# -++# CONFIG_WLAN_PRE80211 is not set -++# CONFIG_WLAN_80211 is not set -++ -++# -++# USB Network Adapters -++# -++# CONFIG_USB_CATC is not set -++# CONFIG_USB_KAWETH is not set -++# CONFIG_USB_PEGASUS is not set -++# CONFIG_USB_RTL8150 is not set -++# CONFIG_USB_USBNET is not set -++# CONFIG_WAN is not set -++# CONFIG_PPP is not set -++# CONFIG_SLIP is not set -++# CONFIG_SHAPER is not set -++# CONFIG_NETCONSOLE is not set -++# CONFIG_NETPOLL is not set -++# CONFIG_NET_POLL_CONTROLLER is not set -++# CONFIG_ISDN is not set -++# CONFIG_PHONE is not set -++ -++# -++# Input device support -++# -++CONFIG_INPUT=y -++# CONFIG_INPUT_FF_MEMLESS is not set -++# CONFIG_INPUT_POLLDEV is not set -++ -++# -++# Userland interfaces -++# -++CONFIG_INPUT_MOUSEDEV=y -++CONFIG_INPUT_MOUSEDEV_PSAUX=y -++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -++# CONFIG_INPUT_JOYDEV is not set -++CONFIG_INPUT_EVDEV=y -++# CONFIG_INPUT_EVBUG is not set -++ -++# -++# Input Device Drivers -++# -++# CONFIG_INPUT_KEYBOARD is not set -++# CONFIG_INPUT_MOUSE is not set -++# CONFIG_INPUT_JOYSTICK is not set -++# CONFIG_INPUT_TABLET is not set -++# CONFIG_INPUT_TOUCHSCREEN is not set -++# CONFIG_INPUT_MISC is not set -++ -++# -++# Hardware I/O ports -++# -++CONFIG_SERIO=y -++# CONFIG_SERIO_I8042 is not set -++CONFIG_SERIO_SERPORT=y -++# CONFIG_SERIO_LIBPS2 is not set -++# CONFIG_SERIO_RAW is not set -++# CONFIG_GAMEPORT is not set -++ -++# -++# Character devices -++# -++CONFIG_VT=y -++CONFIG_VT_CONSOLE=y -++CONFIG_HW_CONSOLE=y -++CONFIG_VT_HW_CONSOLE_BINDING=y -++# CONFIG_SERIAL_NONSTANDARD is not set -++ -++# -++# Serial drivers -++# -++CONFIG_SERIAL_8250=y -++CONFIG_SERIAL_8250_CONSOLE=y -++CONFIG_SERIAL_8250_NR_UARTS=4 -++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -++# CONFIG_SERIAL_8250_EXTENDED is not set -++ -++# -++# Non-8250 serial port support -++# -++CONFIG_SERIAL_CORE=y -++CONFIG_SERIAL_CORE_CONSOLE=y -++CONFIG_UNIX98_PTYS=y -++CONFIG_LEGACY_PTYS=y -++CONFIG_LEGACY_PTY_COUNT=256 -++# CONFIG_IPMI_HANDLER is not set -++# CONFIG_HW_RANDOM is not set -++# CONFIG_RTC is not set -++CONFIG_RTC_PCF8563=y -++# CONFIG_RTC_JZ is not set -++# CONFIG_R3964 is not set -++# CONFIG_RAW_DRIVER is not set -++# CONFIG_TCG_TPM is not set -++ -++# -++# JZSOC char device support -++# -++CONFIG_JZCHAR=y -++# CONFIG_JZ_CIM is not set -++# CONFIG_JZ_TPANEL_ATA2508 is not set -++CONFIG_JZ_TPANEL=y -++# CONFIG_JZ_SADC is not set -++CONFIG_JZ_TPANEL_AK4182=y -++# CONFIG_JZ_TPANEL_UCB1400 is not set -++# CONFIG_JZ_TPANEL_WM9712 is not set -++# CONFIG_JZ_UDC_HOTPLUG is not set -++CONFIG_JZ_POWEROFF=y -++# CONFIG_JZ_OW is not set -++# CONFIG_I2C is not set -++ -++# -++# SPI support -++# -++# CONFIG_SPI is not set -++# CONFIG_SPI_MASTER is not set -++# CONFIG_W1 is not set -++# CONFIG_POWER_SUPPLY is not set -++# CONFIG_HWMON is not set -++CONFIG_WATCHDOG=y -++# CONFIG_WATCHDOG_NOWAYOUT is not set -++ -++# -++# Watchdog Device Drivers -++# -++CONFIG_JZ_WDT=y -++# CONFIG_SOFT_WATCHDOG is not set -++ -++# -++# USB-based Watchdog Cards -++# -++# CONFIG_USBPCWATCHDOG is not set -++ -++# -++# Sonics Silicon Backplane -++# -++CONFIG_SSB_POSSIBLE=y -++# CONFIG_SSB is not set -++ -++# -++# Multifunction device drivers -++# -++# CONFIG_MFD_SM501 is not set -++ -++# -++# Multimedia devices -++# -++CONFIG_VIDEO_DEV=y -++# CONFIG_VIDEO_V4L1 is not set -++# CONFIG_VIDEO_V4L1_COMPAT is not set -++CONFIG_VIDEO_V4L2=y -++CONFIG_VIDEO_CAPTURE_DRIVERS=y -++# CONFIG_VIDEO_ADV_DEBUG is not set -++# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set -++ -++# -++# Encoders/decoders and other helper chips -++# -++ -++# -++# Audio decoders -++# -++ -++# -++# Video decoders -++# -++ -++# -++# Video and audio decoders -++# -++ -++# -++# MPEG video encoders -++# -++# CONFIG_VIDEO_CX2341X is not set -++ -++# -++# Video encoders -++# -++ -++# -++# Video improvement chips -++# -++# CONFIG_VIDEO_VIVI is not set -++CONFIG_VIDEO_JZ_CIM=m -++CONFIG_VIDEO_JZ_SENSOR=m -++# CONFIG_V4L_USB_DRIVERS is not set -++CONFIG_RADIO_ADAPTERS=y -++# CONFIG_USB_DSBR is not set -++# CONFIG_DVB_CORE is not set -++# CONFIG_DAB is not set -++ -++# -++# Graphics support -++# -++# CONFIG_VGASTATE is not set -++# CONFIG_VIDEO_OUTPUT_CONTROL is not set -++CONFIG_FB=y -++# CONFIG_FIRMWARE_EDID is not set -++# CONFIG_FB_DDC is not set -++CONFIG_FB_CFB_FILLRECT=y -++CONFIG_FB_CFB_COPYAREA=y -++CONFIG_FB_CFB_IMAGEBLIT=y -++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -++# CONFIG_FB_SYS_FILLRECT is not set -++# CONFIG_FB_SYS_COPYAREA is not set -++# CONFIG_FB_SYS_IMAGEBLIT is not set -++# CONFIG_FB_SYS_FOPS is not set -++CONFIG_FB_DEFERRED_IO=y -++# CONFIG_FB_SVGALIB is not set -++# CONFIG_FB_MACMODES is not set -++# CONFIG_FB_BACKLIGHT is not set -++# CONFIG_FB_MODE_HELPERS is not set -++# CONFIG_FB_TILEBLITTING is not set -++ -++# -++# Frame buffer hardware drivers -++# -++CONFIG_FB_JZSOC=y -++CONFIG_FB_JZLCD_4730_4740=y -++CONFIG_JZLCD_FRAMEBUFFER_MAX=1 -++# CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT is not set -++# CONFIG_JZLCD_SHARP_LQ035Q7 is not set -++# CONFIG_JZLCD_SAMSUNG_LTS350Q1 is not set -++# CONFIG_JZLCD_SAMSUNG_LTV350QVF04 is not set -++CONFIG_JZLCD_SAMSUNG_LTP400WQF01=y -++# CONFIG_JZLCD_SAMSUNG_LTP400WQF02 is not set -++# CONFIG_JZLCD_AUO_A030FL01_V1 is not set -++# CONFIG_JZLCD_TRULY_TFTG320240DTSW is not set -++# CONFIG_JZLCD_TRULY_TFTG320240DTSW_SERIAL is not set -++# CONFIG_JZLCD_TRULY_TFTG240320UTSW_63W_E is not set -++# CONFIG_JZLCD_FOXCONN_PT035TN01 is not set -++# CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL is not set -++# CONFIG_JZLCD_TOSHIBA_LTM084P363 is not set -++# CONFIG_JZLCD_HYNIX_HT10X21 is not set -++# CONFIG_JZLCD_INNOLUX_AT080TN42 is not set -++# CONFIG_JZLCD_CSTN_800x600 is not set -++# CONFIG_JZLCD_CSTN_320x240 is not set -++# CONFIG_JZLCD_MSTN_480x320 is not set -++# CONFIG_JZLCD_MSTN_320x240 is not set -++# CONFIG_JZLCD_MSTN_240x128 is not set -++# CONFIG_FB_S1D13XXX is not set -++# CONFIG_FB_VIRTUAL is not set -++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set -++ -++# -++# Display device support -++# -++# CONFIG_DISPLAY_SUPPORT is not set -++ -++# -++# Console display driver support -++# -++# CONFIG_VGA_CONSOLE is not set -++CONFIG_DUMMY_CONSOLE=y -++CONFIG_FRAMEBUFFER_CONSOLE=y -++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -++# CONFIG_FRAMEBUFFER_CONSOLE_CURSOR_FLASH is not set -++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -++CONFIG_FONTS=y -++CONFIG_FONT_8x8=y -++CONFIG_FONT_8x16=y -++# CONFIG_FONT_6x11 is not set -++# CONFIG_FONT_7x14 is not set -++# CONFIG_FONT_PEARL_8x8 is not set -++# CONFIG_FONT_ACORN_8x8 is not set -++# CONFIG_FONT_MINI_4x6 is not set -++# CONFIG_FONT_SUN8x16 is not set -++# CONFIG_FONT_SUN12x22 is not set -++# CONFIG_FONT_10x18 is not set -++CONFIG_LOGO=y -++CONFIG_LOGO_LINUX_MONO=y -++CONFIG_LOGO_LINUX_VGA16=y -++CONFIG_LOGO_LINUX_CLUT224=y -++ -++# -++# Sound -++# -++# CONFIG_SOUND is not set -++CONFIG_HID_SUPPORT=y -++CONFIG_HID=y -++# CONFIG_HID_DEBUG is not set -++# CONFIG_HIDRAW is not set -++ -++# -++# USB Input Devices -++# -++CONFIG_USB_HID=y -++# CONFIG_USB_HIDINPUT_POWERBOOK is not set -++# CONFIG_HID_FF is not set -++CONFIG_USB_HIDDEV=y -++CONFIG_USB_SUPPORT=y -++CONFIG_USB_ARCH_HAS_HCD=y -++CONFIG_USB_ARCH_HAS_OHCI=y -++# CONFIG_USB_ARCH_HAS_EHCI is not set -++CONFIG_USB=y -++# CONFIG_USB_DEBUG is not set -++ -++# -++# Miscellaneous USB options -++# -++CONFIG_USB_DEVICEFS=y -++# CONFIG_USB_DEVICE_CLASS is not set -++# CONFIG_USB_DYNAMIC_MINORS is not set -++# CONFIG_USB_SUSPEND is not set -++# CONFIG_USB_PERSIST is not set -++# CONFIG_USB_OTG is not set -++ -++# -++# USB Host Controller Drivers -++# -++# CONFIG_USB_ISP116X_HCD is not set -++CONFIG_USB_OHCI_HCD=y -++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set -++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set -++CONFIG_USB_OHCI_LITTLE_ENDIAN=y -++# CONFIG_USB_SL811_HCD is not set -++# CONFIG_USB_R8A66597_HCD is not set -++ -++# -++# USB Device Class drivers -++# -++# CONFIG_USB_ACM is not set -++# CONFIG_USB_PRINTER is not set -++ -++# -++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -++# -++ -++# -++# may also be needed; see USB_STORAGE Help for more information -++# -++CONFIG_USB_STORAGE=y -++# CONFIG_USB_STORAGE_DEBUG is not set -++# CONFIG_USB_STORAGE_DATAFAB is not set -++# CONFIG_USB_STORAGE_FREECOM is not set -++# CONFIG_USB_STORAGE_ISD200 is not set -++# CONFIG_USB_STORAGE_DPCM is not set -++# CONFIG_USB_STORAGE_USBAT is not set -++# CONFIG_USB_STORAGE_SDDR09 is not set -++# CONFIG_USB_STORAGE_SDDR55 is not set -++# CONFIG_USB_STORAGE_JUMPSHOT is not set -++# CONFIG_USB_STORAGE_ALAUDA is not set -++# CONFIG_USB_STORAGE_KARMA is not set -++# CONFIG_USB_LIBUSUAL is not set -++ -++# -++# USB Imaging devices -++# -++# CONFIG_USB_MDC800 is not set -++# CONFIG_USB_MICROTEK is not set -++# CONFIG_USB_MON is not set -++ -++# -++# USB port drivers -++# -++ -++# -++# USB Serial Converter support -++# -++# CONFIG_USB_SERIAL is not set -++ -++# -++# USB Miscellaneous drivers -++# -++# CONFIG_USB_EMI62 is not set -++# CONFIG_USB_EMI26 is not set -++# CONFIG_USB_ADUTUX is not set -++# CONFIG_USB_AUERSWALD is not set -++# CONFIG_USB_RIO500 is not set -++# CONFIG_USB_LEGOTOWER is not set -++# CONFIG_USB_LCD is not set -++# CONFIG_USB_BERRY_CHARGE is not set -++# CONFIG_USB_LED is not set -++# CONFIG_USB_CYPRESS_CY7C63 is not set -++# CONFIG_USB_CYTHERM is not set -++# CONFIG_USB_PHIDGET is not set -++# CONFIG_USB_IDMOUSE is not set -++# CONFIG_USB_FTDI_ELAN is not set -++# CONFIG_USB_APPLEDISPLAY is not set -++# CONFIG_USB_LD is not set -++# CONFIG_USB_TRANCEVIBRATOR is not set -++# CONFIG_USB_IOWARRIOR is not set -++# CONFIG_USB_TEST is not set -++ -++# -++# USB DSL modem support -++# -++ -++# -++# USB Gadget Support -++# -++CONFIG_USB_GADGET=m -++# CONFIG_USB_GADGET_DEBUG_FILES is not set -++CONFIG_USB_GADGET_SELECTED=y -++# CONFIG_USB_GADGET_JZ4740 is not set -++CONFIG_USB_GADGET_JZ4730=y -++CONFIG_USB_JZ4730=m -++# CONFIG_USB_GADGET_AMD5536UDC is not set -++# CONFIG_USB_GADGET_ATMEL_USBA is not set -++# CONFIG_USB_GADGET_FSL_USB2 is not set -++# CONFIG_USB_GADGET_NET2280 is not set -++# CONFIG_USB_GADGET_PXA2XX is not set -++# CONFIG_USB_GADGET_M66592 is not set -++# CONFIG_USB_GADGET_GOKU is not set -++# CONFIG_USB_GADGET_LH7A40X is not set -++# CONFIG_USB_GADGET_OMAP is not set -++# CONFIG_USB_GADGET_S3C2410 is not set -++# CONFIG_USB_GADGET_AT91 is not set -++# CONFIG_USB_GADGET_DUMMY_HCD is not set -++# CONFIG_USB_GADGET_DUALSPEED is not set -++# CONFIG_USB_ZERO is not set -++CONFIG_USB_ETH=m -++CONFIG_USB_ETH_RNDIS=y -++# CONFIG_USB_GADGETFS is not set -++CONFIG_USB_FILE_STORAGE=m -++# CONFIG_USB_FILE_STORAGE_TEST is not set -++CONFIG_USB_G_SERIAL=m -++# CONFIG_USB_MIDI_GADGET is not set -++CONFIG_MMC=y -++# CONFIG_MMC_DEBUG is not set -++# CONFIG_MMC_UNSAFE_RESUME is not set -++ -++# -++# MMC/SD Card Drivers -++# -++CONFIG_MMC_BLOCK=y -++CONFIG_MMC_BLOCK_BOUNCE=y -++# CONFIG_SDIO_UART is not set -++ -++# -++# MMC/SD Host Controller Drivers -++# -++CONFIG_MMC_JZ=y -++CONFIG_JZ_MMC_BUS_4=y -++# CONFIG_JZ_MMC_BUS_1 is not set -++# CONFIG_NEW_LEDS is not set -++CONFIG_RTC_LIB=y -++# CONFIG_RTC_CLASS is not set -++ -++# -++# Userspace I/O -++# -++# CONFIG_UIO is not set -++ -++# -++# File systems -++# -++CONFIG_EXT2_FS=y -++CONFIG_EXT2_FS_XATTR=y -++# CONFIG_EXT2_FS_POSIX_ACL is not set -++# CONFIG_EXT2_FS_SECURITY is not set -++# CONFIG_EXT2_FS_XIP is not set -++CONFIG_EXT3_FS=y -++CONFIG_EXT3_FS_XATTR=y -++# CONFIG_EXT3_FS_POSIX_ACL is not set -++# CONFIG_EXT3_FS_SECURITY is not set -++# CONFIG_EXT4DEV_FS is not set -++CONFIG_JBD=y -++CONFIG_FS_MBCACHE=y -++# CONFIG_REISERFS_FS is not set -++# CONFIG_JFS_FS is not set -++# CONFIG_FS_POSIX_ACL is not set -++# CONFIG_XFS_FS is not set -++# CONFIG_GFS2_FS is not set -++# CONFIG_OCFS2_FS is not set -++CONFIG_MINIX_FS=y -++# CONFIG_ROMFS_FS is not set -++CONFIG_INOTIFY=y -++CONFIG_INOTIFY_USER=y -++# CONFIG_QUOTA is not set -++CONFIG_DNOTIFY=y -++# CONFIG_AUTOFS_FS is not set -++# CONFIG_AUTOFS4_FS is not set -++# CONFIG_FUSE_FS is not set -++ -++# -++# CD-ROM/DVD Filesystems -++# -++# CONFIG_ISO9660_FS is not set -++# CONFIG_UDF_FS is not set -++ -++# -++# DOS/FAT/NT Filesystems -++# -++CONFIG_FAT_FS=y -++CONFIG_MSDOS_FS=y -++CONFIG_VFAT_FS=y -++CONFIG_FAT_DEFAULT_CODEPAGE=437 -++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -++# CONFIG_NTFS_FS is not set -++ -++# -++# Pseudo filesystems -++# -++CONFIG_PROC_FS=y -++CONFIG_PROC_KCORE=y -++CONFIG_PROC_SYSCTL=y -++CONFIG_SYSFS=y -++CONFIG_TMPFS=y -++# CONFIG_TMPFS_POSIX_ACL is not set -++# CONFIG_HUGETLB_PAGE is not set -++# CONFIG_CONFIGFS_FS is not set -++ -++# -++# Miscellaneous filesystems -++# -++# CONFIG_ADFS_FS is not set -++# CONFIG_AFFS_FS is not set -++# CONFIG_HFS_FS is not set -++# CONFIG_HFSPLUS_FS is not set -++# CONFIG_BEFS_FS is not set -++# CONFIG_BFS_FS is not set -++# CONFIG_EFS_FS is not set -++# CONFIG_JFFS2_FS is not set -++# CONFIG_CRAMFS is not set -++# CONFIG_VXFS_FS is not set -++# CONFIG_HPFS_FS is not set -++# CONFIG_QNX4FS_FS is not set -++# CONFIG_SYSV_FS is not set -++# CONFIG_UFS_FS is not set -++CONFIG_NETWORK_FILESYSTEMS=y -++CONFIG_NFS_FS=y -++CONFIG_NFS_V3=y -++# CONFIG_NFS_V3_ACL is not set -++# CONFIG_NFS_V4 is not set -++# CONFIG_NFS_DIRECTIO is not set -++# CONFIG_NFSD is not set -++CONFIG_ROOT_NFS=y -++CONFIG_LOCKD=y -++CONFIG_LOCKD_V4=y -++CONFIG_NFS_COMMON=y -++CONFIG_SUNRPC=y -++# CONFIG_SUNRPC_BIND34 is not set -++# CONFIG_RPCSEC_GSS_KRB5 is not set -++# CONFIG_RPCSEC_GSS_SPKM3 is not set -++# CONFIG_SMB_FS is not set -++# CONFIG_CIFS is not set -++# CONFIG_NCP_FS is not set -++# CONFIG_CODA_FS is not set -++# CONFIG_AFS_FS is not set -++ -++# -++# Partition Types -++# -++CONFIG_PARTITION_ADVANCED=y -++# CONFIG_ACORN_PARTITION is not set -++# CONFIG_OSF_PARTITION is not set -++# CONFIG_AMIGA_PARTITION is not set -++# CONFIG_ATARI_PARTITION is not set -++# CONFIG_MAC_PARTITION is not set -++CONFIG_MSDOS_PARTITION=y -++CONFIG_BSD_DISKLABEL=y -++# CONFIG_MINIX_SUBPARTITION is not set -++# CONFIG_SOLARIS_X86_PARTITION is not set -++# CONFIG_UNIXWARE_DISKLABEL is not set -++# CONFIG_LDM_PARTITION is not set -++# CONFIG_SGI_PARTITION is not set -++# CONFIG_ULTRIX_PARTITION is not set -++# CONFIG_SUN_PARTITION is not set -++# CONFIG_KARMA_PARTITION is not set -++# CONFIG_EFI_PARTITION is not set -++# CONFIG_SYSV68_PARTITION is not set -++CONFIG_NLS=y -++CONFIG_NLS_DEFAULT="iso8859-1" -++CONFIG_NLS_CODEPAGE_437=y -++# CONFIG_NLS_CODEPAGE_737 is not set -++# CONFIG_NLS_CODEPAGE_775 is not set -++# CONFIG_NLS_CODEPAGE_850 is not set -++# CONFIG_NLS_CODEPAGE_852 is not set -++# CONFIG_NLS_CODEPAGE_855 is not set -++# CONFIG_NLS_CODEPAGE_857 is not set -++# CONFIG_NLS_CODEPAGE_860 is not set -++# CONFIG_NLS_CODEPAGE_861 is not set -++# CONFIG_NLS_CODEPAGE_862 is not set -++# CONFIG_NLS_CODEPAGE_863 is not set -++# CONFIG_NLS_CODEPAGE_864 is not set -++# CONFIG_NLS_CODEPAGE_865 is not set -++# CONFIG_NLS_CODEPAGE_866 is not set -++# CONFIG_NLS_CODEPAGE_869 is not set -++CONFIG_NLS_CODEPAGE_936=y -++# CONFIG_NLS_CODEPAGE_950 is not set -++# CONFIG_NLS_CODEPAGE_932 is not set -++# CONFIG_NLS_CODEPAGE_949 is not set -++# CONFIG_NLS_CODEPAGE_874 is not set -++# CONFIG_NLS_ISO8859_8 is not set -++# CONFIG_NLS_CODEPAGE_1250 is not set -++# CONFIG_NLS_CODEPAGE_1251 is not set -++CONFIG_NLS_ASCII=y -++CONFIG_NLS_ISO8859_1=y -++# CONFIG_NLS_ISO8859_2 is not set -++# CONFIG_NLS_ISO8859_3 is not set -++# CONFIG_NLS_ISO8859_4 is not set -++# CONFIG_NLS_ISO8859_5 is not set -++# CONFIG_NLS_ISO8859_6 is not set -++# CONFIG_NLS_ISO8859_7 is not set -++# CONFIG_NLS_ISO8859_9 is not set -++# CONFIG_NLS_ISO8859_13 is not set -++# CONFIG_NLS_ISO8859_14 is not set -++# CONFIG_NLS_ISO8859_15 is not set -++# CONFIG_NLS_KOI8_R is not set -++# CONFIG_NLS_KOI8_U is not set -++# CONFIG_NLS_UTF8 is not set -++# CONFIG_DLM is not set -++ -++# -++# Yaffs2 Filesystems -++# -++CONFIG_YAFFS_FS=y -++CONFIG_YAFFS_YAFFS1=y -++# CONFIG_YAFFS_DOES_ECC is not set -++CONFIG_YAFFS_YAFFS2=y -++CONFIG_YAFFS_AUTO_YAFFS2=y -++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set -++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set -++CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK=y -++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y -++CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10 -++CONFIG_INSTRUMENTATION=y -++# CONFIG_PROFILING is not set -++# CONFIG_MARKERS is not set -++ -++# -++# Kernel hacking -++# -++CONFIG_TRACE_IRQFLAGS_SUPPORT=y -++# CONFIG_PRINTK_TIME is not set -++CONFIG_ENABLE_WARN_DEPRECATED=y -++CONFIG_ENABLE_MUST_CHECK=y -++CONFIG_MAGIC_SYSRQ=y -++# CONFIG_UNUSED_SYMBOLS is not set -++# CONFIG_DEBUG_FS is not set -++# CONFIG_HEADERS_CHECK is not set -++# CONFIG_DEBUG_KERNEL is not set -++# CONFIG_SAMPLES is not set -++CONFIG_CMDLINE="" -++ -++# -++# Security options -++# -++# CONFIG_KEYS is not set -++# CONFIG_SECURITY is not set -++# CONFIG_SECURITY_FILE_CAPABILITIES is not set -++# CONFIG_CRYPTO is not set -++ -++# -++# Library routines -++# -++CONFIG_BITREVERSE=y -++# CONFIG_CRC_CCITT is not set -++# CONFIG_CRC16 is not set -++# CONFIG_CRC_ITU_T is not set -++CONFIG_CRC32=y -++# CONFIG_CRC7 is not set -++# CONFIG_LIBCRC32C is not set -++CONFIG_PLIST=y -++CONFIG_HAS_IOMEM=y -++CONFIG_HAS_IOPORT=y -++CONFIG_HAS_DMA=y -+diff -urN linux-2.6.24.7.old/arch/mips/configs/slt50_defconfig linux-2.6.24.7/arch/mips/configs/slt50_defconfig -+--- linux-2.6.24.7.old/arch/mips/configs/slt50_defconfig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/configs/slt50_defconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1036 @@ -++# -++# Automatically generated make config: don't edit -++# Linux kernel version: 2.6.24.3 -++# Tue Nov 25 09:38:56 2008 -++# -++CONFIG_MIPS=y -++ -++# -++# Machine selection -++# -++# CONFIG_JZ4730_PMP is not set -++# CONFIG_JZ4740_PAVO is not set -++# CONFIG_JZ4740_LEO is not set -++# CONFIG_JZ4740_LYRA is not set -++# CONFIG_JZ4725_DIPPER is not set -++# CONFIG_JZ4720_VIRGO is not set -++# CONFIG_JZ4750_FUWA is not set -++# CONFIG_JZ4750_APUS is not set -++CONFIG_JZ4750_SLT50=y -++# CONFIG_MACH_ALCHEMY is not set -++# CONFIG_BASLER_EXCITE is not set -++# CONFIG_BCM47XX is not set -++# CONFIG_MIPS_COBALT is not set -++# CONFIG_MACH_DECSTATION is not set -++# CONFIG_MACH_JAZZ is not set -++# CONFIG_LASAT is not set -++# CONFIG_LEMOTE_FULONG is not set -++# CONFIG_MIPS_ATLAS is not set -++# CONFIG_MIPS_MALTA is not set -++# CONFIG_MIPS_SEAD is not set -++# CONFIG_MIPS_SIM is not set -++# CONFIG_MARKEINS is not set -++# CONFIG_MACH_VR41XX is not set -++# CONFIG_PNX8550_JBS is not set -++# CONFIG_PNX8550_STB810 is not set -++# CONFIG_PMC_MSP is not set -++# CONFIG_PMC_YOSEMITE is not set -++# CONFIG_QEMU is not set -++# CONFIG_SGI_IP22 is not set -++# CONFIG_SGI_IP27 is not set -++# CONFIG_SGI_IP32 is not set -++# CONFIG_SIBYTE_CRHINE is not set -++# CONFIG_SIBYTE_CARMEL is not set -++# CONFIG_SIBYTE_CRHONE is not set -++# CONFIG_SIBYTE_RHONE is not set -++# CONFIG_SIBYTE_SWARM is not set -++# CONFIG_SIBYTE_LITTLESUR is not set -++# CONFIG_SIBYTE_SENTOSA is not set -++# CONFIG_SIBYTE_PTSWARM is not set -++# CONFIG_SIBYTE_BIGSUR is not set -++# CONFIG_SNI_RM is not set -++# CONFIG_TOSHIBA_JMR3927 is not set -++# CONFIG_TOSHIBA_RBTX4927 is not set -++# CONFIG_TOSHIBA_RBTX4938 is not set -++# CONFIG_WR_PPMC is not set -++CONFIG_SOC_JZ4750=y -++CONFIG_JZSOC=y -++CONFIG_JZRISC=y -++CONFIG_RWSEM_GENERIC_SPINLOCK=y -++# CONFIG_ARCH_HAS_ILOG2_U32 is not set -++# CONFIG_ARCH_HAS_ILOG2_U64 is not set -++CONFIG_ARCH_SUPPORTS_OPROFILE=y -++CONFIG_GENERIC_FIND_NEXT_BIT=y -++CONFIG_GENERIC_HWEIGHT=y -++CONFIG_GENERIC_CALIBRATE_DELAY=y -++CONFIG_GENERIC_CLOCKEVENTS=y -++CONFIG_GENERIC_TIME=y -++CONFIG_GENERIC_CMOS_UPDATE=y -++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -++# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set -++CONFIG_DMA_NONCOHERENT=y -++CONFIG_DMA_NEED_PCI_MAP_STATE=y -++# CONFIG_HOTPLUG_CPU is not set -++# CONFIG_NO_IOPORT is not set -++# CONFIG_CPU_BIG_ENDIAN is not set -++CONFIG_CPU_LITTLE_ENDIAN=y -++CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -++CONFIG_MIPS_L1_CACHE_SHIFT=5 -++ -++# -++# CPU selection -++# -++# CONFIG_CPU_LOONGSON2 is not set -++CONFIG_CPU_MIPS32_R1=y -++# CONFIG_CPU_MIPS32_R2 is not set -++# CONFIG_CPU_MIPS64_R1 is not set -++# CONFIG_CPU_MIPS64_R2 is not set -++# CONFIG_CPU_R3000 is not set -++# CONFIG_CPU_TX39XX is not set -++# CONFIG_CPU_VR41XX is not set -++# CONFIG_CPU_R4300 is not set -++# CONFIG_CPU_R4X00 is not set -++# CONFIG_CPU_TX49XX is not set -++# CONFIG_CPU_R5000 is not set -++# CONFIG_CPU_R5432 is not set -++# CONFIG_CPU_R6000 is not set -++# CONFIG_CPU_NEVADA is not set -++# CONFIG_CPU_R8000 is not set -++# CONFIG_CPU_R10000 is not set -++# CONFIG_CPU_RM7000 is not set -++# CONFIG_CPU_RM9000 is not set -++# CONFIG_CPU_SB1 is not set -++CONFIG_SYS_HAS_CPU_MIPS32_R1=y -++CONFIG_CPU_MIPS32=y -++CONFIG_CPU_MIPSR1=y -++CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -++CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -++ -++# -++# Kernel type -++# -++CONFIG_32BIT=y -++# CONFIG_64BIT is not set -++CONFIG_PAGE_SIZE_4KB=y -++# CONFIG_PAGE_SIZE_8KB is not set -++# CONFIG_PAGE_SIZE_16KB is not set -++# CONFIG_PAGE_SIZE_64KB is not set -++CONFIG_CPU_HAS_PREFETCH=y -++CONFIG_MIPS_MT_DISABLED=y -++# CONFIG_MIPS_MT_SMP is not set -++# CONFIG_MIPS_MT_SMTC is not set -++CONFIG_CPU_HAS_LLSC=y -++CONFIG_CPU_HAS_SYNC=y -++CONFIG_GENERIC_HARDIRQS=y -++CONFIG_GENERIC_IRQ_PROBE=y -++CONFIG_CPU_SUPPORTS_HIGHMEM=y -++CONFIG_ARCH_FLATMEM_ENABLE=y -++CONFIG_ARCH_POPULATES_NODE_MAP=y -++CONFIG_SELECT_MEMORY_MODEL=y -++CONFIG_FLATMEM_MANUAL=y -++# CONFIG_DISCONTIGMEM_MANUAL is not set -++# CONFIG_SPARSEMEM_MANUAL is not set -++CONFIG_FLATMEM=y -++CONFIG_FLAT_NODE_MEM_MAP=y -++# CONFIG_SPARSEMEM_STATIC is not set -++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -++CONFIG_SPLIT_PTLOCK_CPUS=4 -++# CONFIG_RESOURCES_64BIT is not set -++CONFIG_ZONE_DMA_FLAG=0 -++CONFIG_VIRT_TO_BUS=y -++# CONFIG_TICK_ONESHOT is not set -++# CONFIG_NO_HZ is not set -++# CONFIG_HIGH_RES_TIMERS is not set -++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -++# CONFIG_HZ_48 is not set -++CONFIG_HZ_100=y -++# CONFIG_HZ_128 is not set -++# CONFIG_HZ_250 is not set -++# CONFIG_HZ_256 is not set -++# CONFIG_HZ_1000 is not set -++# CONFIG_HZ_1024 is not set -++CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -++CONFIG_HZ=100 -++# CONFIG_PREEMPT_NONE is not set -++# CONFIG_PREEMPT_VOLUNTARY is not set -++CONFIG_PREEMPT=y -++CONFIG_PREEMPT_BKL=y -++# CONFIG_KEXEC is not set -++CONFIG_SECCOMP=y -++CONFIG_LOCKDEP_SUPPORT=y -++CONFIG_STACKTRACE_SUPPORT=y -++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -++ -++# -++# General setup -++# -++CONFIG_EXPERIMENTAL=y -++CONFIG_BROKEN_ON_SMP=y -++CONFIG_LOCK_KERNEL=y -++CONFIG_INIT_ENV_ARG_LIMIT=32 -++CONFIG_LOCALVERSION="" -++CONFIG_LOCALVERSION_AUTO=y -++CONFIG_SWAP=y -++CONFIG_SYSVIPC=y -++CONFIG_SYSVIPC_SYSCTL=y -++# CONFIG_POSIX_MQUEUE is not set -++# CONFIG_BSD_PROCESS_ACCT is not set -++# CONFIG_TASKSTATS is not set -++# CONFIG_USER_NS is not set -++# CONFIG_PID_NS is not set -++# CONFIG_AUDIT is not set -++# CONFIG_IKCONFIG is not set -++CONFIG_LOG_BUF_SHIFT=14 -++# CONFIG_CGROUPS is not set -++CONFIG_FAIR_GROUP_SCHED=y -++CONFIG_FAIR_USER_SCHED=y -++# CONFIG_FAIR_CGROUP_SCHED is not set -++CONFIG_SYSFS_DEPRECATED=y -++CONFIG_RELAY=y -++# CONFIG_BLK_DEV_INITRD is not set -++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -++CONFIG_SYSCTL=y -++CONFIG_EMBEDDED=y -++CONFIG_SYSCTL_SYSCALL=y -++CONFIG_KALLSYMS=y -++# CONFIG_KALLSYMS_EXTRA_PASS is not set -++CONFIG_HOTPLUG=y -++CONFIG_PRINTK=y -++CONFIG_BUG=y -++CONFIG_ELF_CORE=y -++CONFIG_BASE_FULL=y -++CONFIG_FUTEX=y -++CONFIG_ANON_INODES=y -++CONFIG_EPOLL=y -++CONFIG_SIGNALFD=y -++CONFIG_EVENTFD=y -++CONFIG_SHMEM=y -++CONFIG_VM_EVENT_COUNTERS=y -++CONFIG_SLAB=y -++# CONFIG_SLUB is not set -++# CONFIG_SLOB is not set -++CONFIG_SLABINFO=y -++CONFIG_RT_MUTEXES=y -++# CONFIG_TINY_SHMEM is not set -++CONFIG_BASE_SMALL=0 -++CONFIG_MODULES=y -++CONFIG_MODULE_UNLOAD=y -++# CONFIG_MODULE_FORCE_UNLOAD is not set -++CONFIG_MODVERSIONS=y -++CONFIG_MODULE_SRCVERSION_ALL=y -++CONFIG_KMOD=y -++CONFIG_BLOCK=y -++# CONFIG_LBD is not set -++# CONFIG_BLK_DEV_IO_TRACE is not set -++# CONFIG_LSF is not set -++# CONFIG_BLK_DEV_BSG is not set -++ -++# -++# IO Schedulers -++# -++CONFIG_IOSCHED_NOOP=y -++CONFIG_IOSCHED_AS=y -++CONFIG_IOSCHED_DEADLINE=y -++CONFIG_IOSCHED_CFQ=y -++CONFIG_DEFAULT_AS=y -++# CONFIG_DEFAULT_DEADLINE is not set -++# CONFIG_DEFAULT_CFQ is not set -++# CONFIG_DEFAULT_NOOP is not set -++CONFIG_DEFAULT_IOSCHED="anticipatory" -++ -++# -++# Bus options (PCI, PCMCIA, EISA, ISA, TC) -++# -++# CONFIG_ARCH_SUPPORTS_MSI is not set -++CONFIG_MMU=y -++# CONFIG_PCCARD is not set -++ -++# -++# Executable file formats -++# -++CONFIG_BINFMT_ELF=y -++# CONFIG_BINFMT_MISC is not set -++CONFIG_TRAD_SIGNALS=y -++ -++# -++# CPU Frequency scaling -++# -++# CONFIG_CPU_FREQ_JZ is not set -++ -++# -++# Power management options -++# -++# CONFIG_PM is not set -++CONFIG_SUSPEND_UP_POSSIBLE=y -++ -++# -++# Networking -++# -++CONFIG_NET=y -++ -++# -++# Networking options -++# -++CONFIG_PACKET=y -++# CONFIG_PACKET_MMAP is not set -++CONFIG_UNIX=y -++# CONFIG_NET_KEY is not set -++CONFIG_INET=y -++# CONFIG_IP_MULTICAST is not set -++# CONFIG_IP_ADVANCED_ROUTER is not set -++CONFIG_IP_FIB_HASH=y -++CONFIG_IP_PNP=y -++CONFIG_IP_PNP_DHCP=y -++CONFIG_IP_PNP_BOOTP=y -++# CONFIG_IP_PNP_RARP is not set -++# CONFIG_NET_IPIP is not set -++# CONFIG_NET_IPGRE is not set -++# CONFIG_ARPD is not set -++# CONFIG_SYN_COOKIES is not set -++# CONFIG_INET_AH is not set -++# CONFIG_INET_ESP is not set -++# CONFIG_INET_IPCOMP is not set -++# CONFIG_INET_XFRM_TUNNEL is not set -++# CONFIG_INET_TUNNEL is not set -++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -++# CONFIG_INET_XFRM_MODE_TUNNEL is not set -++# CONFIG_INET_XFRM_MODE_BEET is not set -++# CONFIG_INET_LRO is not set -++CONFIG_INET_DIAG=m -++CONFIG_INET_TCP_DIAG=m -++# CONFIG_TCP_CONG_ADVANCED is not set -++CONFIG_TCP_CONG_CUBIC=y -++CONFIG_DEFAULT_TCP_CONG="cubic" -++# CONFIG_TCP_MD5SIG is not set -++# CONFIG_IPV6 is not set -++# CONFIG_INET6_XFRM_TUNNEL is not set -++# CONFIG_INET6_TUNNEL is not set -++# CONFIG_NETWORK_SECMARK is not set -++# CONFIG_NETFILTER is not set -++# CONFIG_IP_DCCP is not set -++# CONFIG_IP_SCTP is not set -++# CONFIG_TIPC is not set -++# CONFIG_ATM is not set -++# CONFIG_BRIDGE is not set -++# CONFIG_VLAN_8021Q is not set -++# CONFIG_DECNET is not set -++# CONFIG_LLC2 is not set -++# CONFIG_IPX is not set -++# CONFIG_ATALK is not set -++# CONFIG_X25 is not set -++# CONFIG_LAPB is not set -++# CONFIG_ECONET is not set -++# CONFIG_WAN_ROUTER is not set -++# CONFIG_NET_SCHED is not set -++ -++# -++# Network testing -++# -++# CONFIG_NET_PKTGEN is not set -++# CONFIG_HAMRADIO is not set -++# CONFIG_IRDA is not set -++# CONFIG_BT is not set -++# CONFIG_AF_RXRPC is not set -++ -++# -++# Wireless -++# -++# CONFIG_CFG80211 is not set -++CONFIG_WIRELESS_EXT=y -++# CONFIG_MAC80211 is not set -++# CONFIG_IEEE80211 is not set -++# CONFIG_RFKILL is not set -++# CONFIG_NET_9P is not set -++ -++# -++# Device Drivers -++# -++ -++# -++# Generic Driver Options -++# -++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -++CONFIG_STANDALONE=y -++CONFIG_PREVENT_FIRMWARE_BUILD=y -++# CONFIG_FW_LOADER is not set -++# CONFIG_SYS_HYPERVISOR is not set -++# CONFIG_CONNECTOR is not set -++CONFIG_MTD=y -++# CONFIG_MTD_DEBUG is not set -++# CONFIG_MTD_CONCAT is not set -++CONFIG_MTD_PARTITIONS=y -++# CONFIG_MTD_REDBOOT_PARTS is not set -++# CONFIG_MTD_CMDLINE_PARTS is not set -++ -++# -++# User Modules And Translation Layers -++# -++CONFIG_MTD_CHAR=y -++CONFIG_MTD_BLKDEVS=y -++CONFIG_MTD_BLOCK=y -++# CONFIG_FTL is not set -++# CONFIG_NFTL is not set -++# CONFIG_INFTL is not set -++# CONFIG_RFD_FTL is not set -++# CONFIG_SSFDC is not set -++# CONFIG_MTD_OOPS is not set -++ -++# -++# RAM/ROM/Flash chip drivers -++# -++# CONFIG_MTD_CFI is not set -++# CONFIG_MTD_JEDECPROBE is not set -++CONFIG_MTD_MAP_BANK_WIDTH_1=y -++CONFIG_MTD_MAP_BANK_WIDTH_2=y -++CONFIG_MTD_MAP_BANK_WIDTH_4=y -++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -++CONFIG_MTD_CFI_I1=y -++CONFIG_MTD_CFI_I2=y -++# CONFIG_MTD_CFI_I4 is not set -++# CONFIG_MTD_CFI_I8 is not set -++# CONFIG_MTD_RAM is not set -++# CONFIG_MTD_ROM is not set -++# CONFIG_MTD_ABSENT is not set -++ -++# -++# Mapping drivers for chip access -++# -++# CONFIG_MTD_COMPLEX_MAPPINGS is not set -++# CONFIG_MTD_PLATRAM is not set -++ -++# -++# Self-contained MTD device drivers -++# -++# CONFIG_MTD_SLRAM is not set -++# CONFIG_MTD_PHRAM is not set -++# CONFIG_MTD_MTDRAM is not set -++# CONFIG_MTD_BLOCK2MTD is not set -++ -++# -++# Disk-On-Chip Device Drivers -++# -++# CONFIG_MTD_DOC2000 is not set -++# CONFIG_MTD_DOC2001 is not set -++# CONFIG_MTD_DOC2001PLUS is not set -++CONFIG_MTD_NAND=y -++# CONFIG_MTD_NAND_VERIFY_WRITE is not set -++# CONFIG_MTD_NAND_ECC_SMC is not set -++# CONFIG_MTD_NAND_MUSEUM_IDS is not set -++CONFIG_MTD_NAND_IDS=y -++# CONFIG_MTD_NAND_DISKONCHIP is not set -++# CONFIG_MTD_NAND_NANDSIM is not set -++# CONFIG_MTD_NAND_PLATFORM is not set -++# CONFIG_MTD_ALAUDA is not set -++CONFIG_MTD_NAND_JZ4750=y -++# CONFIG_MTD_NAND_CS2 is not set -++# CONFIG_MTD_NAND_CS3 is not set -++# CONFIG_MTD_NAND_CS4 is not set -++# CONFIG_MTD_NAND_MULTI_PLANE is not set -++# CONFIG_MTD_HW_HM_ECC is not set -++# CONFIG_MTD_SW_HM_ECC is not set -++# CONFIG_MTD_HW_RS_ECC is not set -++CONFIG_MTD_HW_BCH_ECC=y -++CONFIG_MTD_HW_BCH_4BIT=y -++# CONFIG_MTD_HW_BCH_8BIT is not set -++CONFIG_MTD_NAND_DMA=y -++# CONFIG_MTD_NAND_DMABUF is not set -++# CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE is not set -++CONFIG_MTD_OOB_COPIES=3 -++CONFIG_MTD_BADBLOCK_FLAG_PAGE=127 -++# CONFIG_MTD_ONENAND is not set -++ -++# -++# UBI - Unsorted block images -++# -++# CONFIG_MTD_UBI is not set -++# CONFIG_MTD_UBI_BLKDEVS is not set -++# CONFIG_PARPORT is not set -++# CONFIG_PNP is not set -++CONFIG_BLK_DEV=y -++# CONFIG_BLK_DEV_COW_COMMON is not set -++CONFIG_BLK_DEV_LOOP=y -++# CONFIG_BLK_DEV_CRYPTOLOOP is not set -++# CONFIG_BLK_DEV_NBD is not set -++# CONFIG_BLK_DEV_UB is not set -++CONFIG_BLK_DEV_RAM=y -++CONFIG_BLK_DEV_RAM_COUNT=16 -++CONFIG_BLK_DEV_RAM_SIZE=4096 -++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -++# CONFIG_CDROM_PKTCDVD is not set -++# CONFIG_ATA_OVER_ETH is not set -++CONFIG_MISC_DEVICES=y -++# CONFIG_EEPROM_93CX6 is not set -++# CONFIG_IDE is not set -++ -++# -++# SCSI device support -++# -++# CONFIG_RAID_ATTRS is not set -++CONFIG_SCSI=y -++CONFIG_SCSI_DMA=y -++# CONFIG_SCSI_TGT is not set -++# CONFIG_SCSI_NETLINK is not set -++CONFIG_SCSI_PROC_FS=y -++ -++# -++# SCSI support type (disk, tape, CD-ROM) -++# -++CONFIG_BLK_DEV_SD=y -++# CONFIG_CHR_DEV_ST is not set -++# CONFIG_CHR_DEV_OSST is not set -++# CONFIG_BLK_DEV_SR is not set -++# CONFIG_CHR_DEV_SG is not set -++# CONFIG_CHR_DEV_SCH is not set -++ -++# -++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -++# -++# CONFIG_SCSI_MULTI_LUN is not set -++# CONFIG_SCSI_CONSTANTS is not set -++# CONFIG_SCSI_LOGGING is not set -++# CONFIG_SCSI_SCAN_ASYNC is not set -++CONFIG_SCSI_WAIT_SCAN=m -++ -++# -++# SCSI Transports -++# -++# CONFIG_SCSI_SPI_ATTRS is not set -++# CONFIG_SCSI_FC_ATTRS is not set -++# CONFIG_SCSI_ISCSI_ATTRS is not set -++# CONFIG_SCSI_SAS_LIBSAS is not set -++# CONFIG_SCSI_SRP_ATTRS is not set -++CONFIG_SCSI_LOWLEVEL=y -++# CONFIG_ISCSI_TCP is not set -++# CONFIG_SCSI_DEBUG is not set -++# CONFIG_ATA is not set -++# CONFIG_MD is not set -++# CONFIG_NETDEVICES is not set -++# CONFIG_ISDN is not set -++# CONFIG_PHONE is not set -++ -++# -++# Input device support -++# -++CONFIG_INPUT=y -++# CONFIG_INPUT_FF_MEMLESS is not set -++# CONFIG_INPUT_POLLDEV is not set -++ -++# -++# Userland interfaces -++# -++CONFIG_INPUT_MOUSEDEV=y -++CONFIG_INPUT_MOUSEDEV_PSAUX=y -++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -++# CONFIG_INPUT_JOYDEV is not set -++# CONFIG_INPUT_EVDEV is not set -++# CONFIG_INPUT_EVBUG is not set -++ -++# -++# Input Device Drivers -++# -++CONFIG_INPUT_KEYBOARD=y -++CONFIG_KEYBOARD_ATKBD=y -++# CONFIG_KEYBOARD_SUNKBD is not set -++# CONFIG_KEYBOARD_LKKBD is not set -++# CONFIG_KEYBOARD_XTKBD is not set -++# CONFIG_KEYBOARD_NEWTON is not set -++# CONFIG_KEYBOARD_STOWAWAY is not set -++# CONFIG_KEYBOARD_JZ is not set -++# CONFIG_KEYBOARD_GPIO is not set -++# CONFIG_INPUT_MOUSE is not set -++# CONFIG_INPUT_JOYSTICK is not set -++# CONFIG_INPUT_TABLET is not set -++# CONFIG_INPUT_TOUCHSCREEN is not set -++# CONFIG_INPUT_MISC is not set -++ -++# -++# Hardware I/O ports -++# -++CONFIG_SERIO=y -++# CONFIG_SERIO_I8042 is not set -++CONFIG_SERIO_SERPORT=y -++CONFIG_SERIO_LIBPS2=y -++# CONFIG_SERIO_RAW is not set -++# CONFIG_GAMEPORT is not set -++ -++# -++# Character devices -++# -++CONFIG_VT=y -++CONFIG_VT_CONSOLE=y -++CONFIG_HW_CONSOLE=y -++CONFIG_VT_HW_CONSOLE_BINDING=y -++# CONFIG_SERIAL_NONSTANDARD is not set -++ -++# -++# Serial drivers -++# -++CONFIG_SERIAL_8250=y -++CONFIG_SERIAL_8250_CONSOLE=y -++CONFIG_SERIAL_8250_NR_UARTS=4 -++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -++# CONFIG_SERIAL_8250_EXTENDED is not set -++ -++# -++# Non-8250 serial port support -++# -++CONFIG_SERIAL_CORE=y -++CONFIG_SERIAL_CORE_CONSOLE=y -++CONFIG_UNIX98_PTYS=y -++CONFIG_LEGACY_PTYS=y -++CONFIG_LEGACY_PTY_COUNT=2 -++# CONFIG_IPMI_HANDLER is not set -++# CONFIG_HW_RANDOM is not set -++# CONFIG_RTC is not set -++# CONFIG_RTC_PCF8563 is not set -++# CONFIG_RTC_JZ is not set -++# CONFIG_R3964 is not set -++# CONFIG_RAW_DRIVER is not set -++# CONFIG_TCG_TPM is not set -++ -++# -++# JZSOC char device support -++# -++CONFIG_JZCHAR=y -++# CONFIG_JZ_CIM is not set -++# CONFIG_JZ_TPANEL_ATA2508 is not set -++# CONFIG_JZ_TPANEL is not set -++CONFIG_JZ_UDC_HOTPLUG=y -++# CONFIG_JZ_POWEROFF is not set -++# CONFIG_JZ_OW is not set -++# CONFIG_I2C is not set -++ -++# -++# SPI support -++# -++# CONFIG_SPI is not set -++# CONFIG_SPI_MASTER is not set -++# CONFIG_W1 is not set -++# CONFIG_POWER_SUPPLY is not set -++# CONFIG_HWMON is not set -++# CONFIG_WATCHDOG is not set -++ -++# -++# Sonics Silicon Backplane -++# -++CONFIG_SSB_POSSIBLE=y -++# CONFIG_SSB is not set -++ -++# -++# Multifunction device drivers -++# -++# CONFIG_MFD_SM501 is not set -++ -++# -++# Multimedia devices -++# -++# CONFIG_VIDEO_DEV is not set -++# CONFIG_DVB_CORE is not set -++# CONFIG_DAB is not set -++ -++# -++# Graphics support -++# -++# CONFIG_VGASTATE is not set -++# CONFIG_VIDEO_OUTPUT_CONTROL is not set -++# CONFIG_FB is not set -++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set -++ -++# -++# Display device support -++# -++# CONFIG_DISPLAY_SUPPORT is not set -++ -++# -++# Console display driver support -++# -++# CONFIG_VGA_CONSOLE is not set -++CONFIG_DUMMY_CONSOLE=y -++ -++# -++# Sound -++# -++# CONFIG_SOUND is not set -++CONFIG_HID_SUPPORT=y -++CONFIG_HID=y -++# CONFIG_HID_DEBUG is not set -++# CONFIG_HIDRAW is not set -++ -++# -++# USB Input Devices -++# -++CONFIG_USB_HID=y -++# CONFIG_USB_HIDINPUT_POWERBOOK is not set -++# CONFIG_HID_FF is not set -++CONFIG_USB_HIDDEV=y -++CONFIG_USB_SUPPORT=y -++CONFIG_USB_ARCH_HAS_HCD=y -++CONFIG_USB_ARCH_HAS_OHCI=y -++# CONFIG_USB_ARCH_HAS_EHCI is not set -++CONFIG_USB=y -++# CONFIG_USB_DEBUG is not set -++ -++# -++# Miscellaneous USB options -++# -++# CONFIG_USB_DEVICEFS is not set -++CONFIG_USB_DEVICE_CLASS=y -++# CONFIG_USB_DYNAMIC_MINORS is not set -++# CONFIG_USB_OTG is not set -++ -++# -++# USB Host Controller Drivers -++# -++# CONFIG_USB_ISP116X_HCD is not set -++CONFIG_USB_OHCI_HCD=y -++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set -++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set -++CONFIG_USB_OHCI_LITTLE_ENDIAN=y -++# CONFIG_USB_SL811_HCD is not set -++# CONFIG_USB_R8A66597_HCD is not set -++ -++# -++# USB Device Class drivers -++# -++# CONFIG_USB_ACM is not set -++# CONFIG_USB_PRINTER is not set -++ -++# -++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -++# -++ -++# -++# may also be needed; see USB_STORAGE Help for more information -++# -++CONFIG_USB_STORAGE=y -++# CONFIG_USB_STORAGE_DEBUG is not set -++# CONFIG_USB_STORAGE_DATAFAB is not set -++# CONFIG_USB_STORAGE_FREECOM is not set -++# CONFIG_USB_STORAGE_ISD200 is not set -++# CONFIG_USB_STORAGE_DPCM is not set -++# CONFIG_USB_STORAGE_USBAT is not set -++# CONFIG_USB_STORAGE_SDDR09 is not set -++# CONFIG_USB_STORAGE_SDDR55 is not set -++# CONFIG_USB_STORAGE_JUMPSHOT is not set -++# CONFIG_USB_STORAGE_ALAUDA is not set -++# CONFIG_USB_STORAGE_KARMA is not set -++# CONFIG_USB_LIBUSUAL is not set -++ -++# -++# USB Imaging devices -++# -++# CONFIG_USB_MDC800 is not set -++# CONFIG_USB_MICROTEK is not set -++CONFIG_USB_MON=y -++ -++# -++# USB port drivers -++# -++ -++# -++# USB Serial Converter support -++# -++# CONFIG_USB_SERIAL is not set -++ -++# -++# USB Miscellaneous drivers -++# -++# CONFIG_USB_EMI62 is not set -++# CONFIG_USB_EMI26 is not set -++# CONFIG_USB_ADUTUX is not set -++# CONFIG_USB_AUERSWALD is not set -++# CONFIG_USB_RIO500 is not set -++# CONFIG_USB_LEGOTOWER is not set -++# CONFIG_USB_LCD is not set -++# CONFIG_USB_BERRY_CHARGE is not set -++# CONFIG_USB_LED is not set -++# CONFIG_USB_CYPRESS_CY7C63 is not set -++# CONFIG_USB_CYTHERM is not set -++# CONFIG_USB_PHIDGET is not set -++# CONFIG_USB_IDMOUSE is not set -++# CONFIG_USB_FTDI_ELAN is not set -++# CONFIG_USB_APPLEDISPLAY is not set -++# CONFIG_USB_LD is not set -++# CONFIG_USB_TRANCEVIBRATOR is not set -++# CONFIG_USB_IOWARRIOR is not set -++ -++# -++# USB DSL modem support -++# -++ -++# -++# USB Gadget Support -++# -++# CONFIG_USB_GADGET is not set -++# CONFIG_MMC is not set -++# CONFIG_NEW_LEDS is not set -++CONFIG_RTC_LIB=y -++# CONFIG_RTC_CLASS is not set -++ -++# -++# Userspace I/O -++# -++# CONFIG_UIO is not set -++ -++# -++# File systems -++# -++CONFIG_EXT2_FS=y -++CONFIG_EXT2_FS_XATTR=y -++# CONFIG_EXT2_FS_POSIX_ACL is not set -++# CONFIG_EXT2_FS_SECURITY is not set -++# CONFIG_EXT2_FS_XIP is not set -++# CONFIG_EXT3_FS is not set -++# CONFIG_EXT4DEV_FS is not set -++CONFIG_FS_MBCACHE=y -++# CONFIG_REISERFS_FS is not set -++# CONFIG_JFS_FS is not set -++CONFIG_FS_POSIX_ACL=y -++# CONFIG_XFS_FS is not set -++# CONFIG_GFS2_FS is not set -++# CONFIG_OCFS2_FS is not set -++CONFIG_MINIX_FS=y -++# CONFIG_ROMFS_FS is not set -++CONFIG_INOTIFY=y -++CONFIG_INOTIFY_USER=y -++# CONFIG_QUOTA is not set -++CONFIG_DNOTIFY=y -++# CONFIG_AUTOFS_FS is not set -++# CONFIG_AUTOFS4_FS is not set -++# CONFIG_FUSE_FS is not set -++ -++# -++# CD-ROM/DVD Filesystems -++# -++# CONFIG_ISO9660_FS is not set -++# CONFIG_UDF_FS is not set -++ -++# -++# DOS/FAT/NT Filesystems -++# -++CONFIG_FAT_FS=y -++CONFIG_MSDOS_FS=y -++CONFIG_VFAT_FS=y -++CONFIG_FAT_DEFAULT_CODEPAGE=437 -++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -++# CONFIG_NTFS_FS is not set -++ -++# -++# Pseudo filesystems -++# -++CONFIG_PROC_FS=y -++CONFIG_PROC_KCORE=y -++CONFIG_PROC_SYSCTL=y -++CONFIG_SYSFS=y -++CONFIG_TMPFS=y -++# CONFIG_TMPFS_POSIX_ACL is not set -++# CONFIG_HUGETLB_PAGE is not set -++# CONFIG_CONFIGFS_FS is not set -++ -++# -++# Miscellaneous filesystems -++# -++# CONFIG_ADFS_FS is not set -++# CONFIG_AFFS_FS is not set -++# CONFIG_HFS_FS is not set -++# CONFIG_HFSPLUS_FS is not set -++# CONFIG_BEFS_FS is not set -++# CONFIG_BFS_FS is not set -++# CONFIG_EFS_FS is not set -++# CONFIG_JFFS2_FS is not set -++# CONFIG_CRAMFS is not set -++# CONFIG_VXFS_FS is not set -++# CONFIG_HPFS_FS is not set -++# CONFIG_QNX4FS_FS is not set -++# CONFIG_SYSV_FS is not set -++# CONFIG_UFS_FS is not set -++CONFIG_NETWORK_FILESYSTEMS=y -++CONFIG_NFS_FS=y -++CONFIG_NFS_V3=y -++CONFIG_NFS_V3_ACL=y -++CONFIG_NFS_V4=y -++CONFIG_NFS_DIRECTIO=y -++# CONFIG_NFSD is not set -++CONFIG_ROOT_NFS=y -++CONFIG_LOCKD=y -++CONFIG_LOCKD_V4=y -++CONFIG_NFS_ACL_SUPPORT=y -++CONFIG_NFS_COMMON=y -++CONFIG_SUNRPC=y -++CONFIG_SUNRPC_GSS=y -++# CONFIG_SUNRPC_BIND34 is not set -++CONFIG_RPCSEC_GSS_KRB5=y -++# CONFIG_RPCSEC_GSS_SPKM3 is not set -++# CONFIG_SMB_FS is not set -++# CONFIG_CIFS is not set -++# CONFIG_NCP_FS is not set -++# CONFIG_CODA_FS is not set -++# CONFIG_AFS_FS is not set -++ -++# -++# Partition Types -++# -++CONFIG_PARTITION_ADVANCED=y -++# CONFIG_ACORN_PARTITION is not set -++# CONFIG_OSF_PARTITION is not set -++# CONFIG_AMIGA_PARTITION is not set -++# CONFIG_ATARI_PARTITION is not set -++# CONFIG_MAC_PARTITION is not set -++CONFIG_MSDOS_PARTITION=y -++# CONFIG_BSD_DISKLABEL is not set -++# CONFIG_MINIX_SUBPARTITION is not set -++# CONFIG_SOLARIS_X86_PARTITION is not set -++# CONFIG_UNIXWARE_DISKLABEL is not set -++# CONFIG_LDM_PARTITION is not set -++# CONFIG_SGI_PARTITION is not set -++# CONFIG_ULTRIX_PARTITION is not set -++# CONFIG_SUN_PARTITION is not set -++# CONFIG_KARMA_PARTITION is not set -++# CONFIG_EFI_PARTITION is not set -++# CONFIG_SYSV68_PARTITION is not set -++CONFIG_NLS=y -++CONFIG_NLS_DEFAULT="iso8859-1" -++CONFIG_NLS_CODEPAGE_437=y -++# CONFIG_NLS_CODEPAGE_737 is not set -++# CONFIG_NLS_CODEPAGE_775 is not set -++# CONFIG_NLS_CODEPAGE_850 is not set -++# CONFIG_NLS_CODEPAGE_852 is not set -++# CONFIG_NLS_CODEPAGE_855 is not set -++# CONFIG_NLS_CODEPAGE_857 is not set -++# CONFIG_NLS_CODEPAGE_860 is not set -++# CONFIG_NLS_CODEPAGE_861 is not set -++# CONFIG_NLS_CODEPAGE_862 is not set -++# CONFIG_NLS_CODEPAGE_863 is not set -++# CONFIG_NLS_CODEPAGE_864 is not set -++# CONFIG_NLS_CODEPAGE_865 is not set -++# CONFIG_NLS_CODEPAGE_866 is not set -++# CONFIG_NLS_CODEPAGE_869 is not set -++CONFIG_NLS_CODEPAGE_936=y -++# CONFIG_NLS_CODEPAGE_950 is not set -++# CONFIG_NLS_CODEPAGE_932 is not set -++# CONFIG_NLS_CODEPAGE_949 is not set -++# CONFIG_NLS_CODEPAGE_874 is not set -++# CONFIG_NLS_ISO8859_8 is not set -++# CONFIG_NLS_CODEPAGE_1250 is not set -++# CONFIG_NLS_CODEPAGE_1251 is not set -++CONFIG_NLS_ASCII=y -++CONFIG_NLS_ISO8859_1=y -++# CONFIG_NLS_ISO8859_2 is not set -++# CONFIG_NLS_ISO8859_3 is not set -++# CONFIG_NLS_ISO8859_4 is not set -++# CONFIG_NLS_ISO8859_5 is not set -++# CONFIG_NLS_ISO8859_6 is not set -++# CONFIG_NLS_ISO8859_7 is not set -++# CONFIG_NLS_ISO8859_9 is not set -++# CONFIG_NLS_ISO8859_13 is not set -++# CONFIG_NLS_ISO8859_14 is not set -++# CONFIG_NLS_ISO8859_15 is not set -++# CONFIG_NLS_KOI8_R is not set -++# CONFIG_NLS_KOI8_U is not set -++# CONFIG_NLS_UTF8 is not set -++# CONFIG_DLM is not set -++ -++# -++# Yaffs2 Filesystems -++# -++CONFIG_YAFFS_FS=y -++CONFIG_YAFFS_YAFFS1=y -++# CONFIG_YAFFS_DOES_ECC is not set -++CONFIG_YAFFS_YAFFS2=y -++# CONFIG_YAFFS_ECC_BCH is not set -++CONFIG_YAFFS_ECC_RS=y -++# CONFIG_YAFFS_ECC_HAMMING is not set -++CONFIG_YAFFS_AUTO_YAFFS2=y -++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set -++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set -++CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK=y -++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y -++CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10 -++CONFIG_INSTRUMENTATION=y -++# CONFIG_PROFILING is not set -++# CONFIG_MARKERS is not set -++ -++# -++# Kernel hacking -++# -++CONFIG_TRACE_IRQFLAGS_SUPPORT=y -++# CONFIG_PRINTK_TIME is not set -++CONFIG_ENABLE_WARN_DEPRECATED=y -++CONFIG_ENABLE_MUST_CHECK=y -++CONFIG_MAGIC_SYSRQ=y -++# CONFIG_UNUSED_SYMBOLS is not set -++# CONFIG_DEBUG_FS is not set -++# CONFIG_HEADERS_CHECK is not set -++# CONFIG_DEBUG_KERNEL is not set -++# CONFIG_SAMPLES is not set -++CONFIG_CMDLINE="" -++ -++# -++# Security options -++# -++# CONFIG_KEYS is not set -++# CONFIG_SECURITY is not set -++# CONFIG_SECURITY_FILE_CAPABILITIES is not set -++CONFIG_CRYPTO=y -++CONFIG_CRYPTO_ALGAPI=y -++CONFIG_CRYPTO_BLKCIPHER=y -++CONFIG_CRYPTO_MANAGER=y -++# CONFIG_CRYPTO_HMAC is not set -++# CONFIG_CRYPTO_XCBC is not set -++# CONFIG_CRYPTO_NULL is not set -++# CONFIG_CRYPTO_MD4 is not set -++CONFIG_CRYPTO_MD5=y -++# CONFIG_CRYPTO_SHA1 is not set -++# CONFIG_CRYPTO_SHA256 is not set -++# CONFIG_CRYPTO_SHA512 is not set -++# CONFIG_CRYPTO_WP512 is not set -++# CONFIG_CRYPTO_TGR192 is not set -++# CONFIG_CRYPTO_GF128MUL is not set -++# CONFIG_CRYPTO_ECB is not set -++CONFIG_CRYPTO_CBC=y -++# CONFIG_CRYPTO_PCBC is not set -++# CONFIG_CRYPTO_LRW is not set -++# CONFIG_CRYPTO_XTS is not set -++# CONFIG_CRYPTO_CRYPTD is not set -++CONFIG_CRYPTO_DES=y -++# CONFIG_CRYPTO_FCRYPT is not set -++# CONFIG_CRYPTO_BLOWFISH is not set -++# CONFIG_CRYPTO_TWOFISH is not set -++# CONFIG_CRYPTO_SERPENT is not set -++# CONFIG_CRYPTO_AES is not set -++# CONFIG_CRYPTO_CAST5 is not set -++# CONFIG_CRYPTO_CAST6 is not set -++# CONFIG_CRYPTO_TEA is not set -++# CONFIG_CRYPTO_ARC4 is not set -++# CONFIG_CRYPTO_KHAZAD is not set -++# CONFIG_CRYPTO_ANUBIS is not set -++# CONFIG_CRYPTO_SEED is not set -++# CONFIG_CRYPTO_DEFLATE is not set -++# CONFIG_CRYPTO_MICHAEL_MIC is not set -++# CONFIG_CRYPTO_CRC32C is not set -++# CONFIG_CRYPTO_CAMELLIA is not set -++# CONFIG_CRYPTO_TEST is not set -++# CONFIG_CRYPTO_AUTHENC is not set -++# CONFIG_CRYPTO_LZO is not set -++CONFIG_CRYPTO_HW=y -++ -++# -++# Library routines -++# -++CONFIG_BITREVERSE=y -++# CONFIG_CRC_CCITT is not set -++# CONFIG_CRC16 is not set -++# CONFIG_CRC_ITU_T is not set -++CONFIG_CRC32=y -++# CONFIG_CRC7 is not set -++# CONFIG_LIBCRC32C is not set -++CONFIG_REED_SOLOMON=y -++CONFIG_REED_SOLOMON_ENC8=y -++CONFIG_REED_SOLOMON_DEC8=y -++CONFIG_PLIST=y -++CONFIG_HAS_IOMEM=y -++CONFIG_HAS_IOPORT=y -++CONFIG_HAS_DMA=y -+diff -urN linux-2.6.24.7.old/arch/mips/configs/virgo_defconfig linux-2.6.24.7/arch/mips/configs/virgo_defconfig -+--- linux-2.6.24.7.old/arch/mips/configs/virgo_defconfig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/configs/virgo_defconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1281 @@ -++# -++# Automatically generated make config: don't edit -++# Linux kernel version: 2.6.24.3 -++# Thu Jun 12 13:52:15 2008 -++# -++CONFIG_MIPS=y -++ -++# -++# Machine selection -++# -++# CONFIG_JZ4730_PMP is not set -++# CONFIG_JZ4740_PAVO is not set -++# CONFIG_JZ4740_LEO is not set -++# CONFIG_JZ4740_LYRA is not set -++# CONFIG_JZ4725_DIPPER is not set -++CONFIG_JZ4720_VIRGO=y -++# CONFIG_JZ4750_FUWA is not set -++# CONFIG_MACH_ALCHEMY is not set -++# CONFIG_BASLER_EXCITE is not set -++# CONFIG_BCM47XX is not set -++# CONFIG_MIPS_COBALT is not set -++# CONFIG_MACH_DECSTATION is not set -++# CONFIG_MACH_JAZZ is not set -++# CONFIG_LASAT is not set -++# CONFIG_LEMOTE_FULONG is not set -++# CONFIG_MIPS_ATLAS is not set -++# CONFIG_MIPS_MALTA is not set -++# CONFIG_MIPS_SEAD is not set -++# CONFIG_MIPS_SIM is not set -++# CONFIG_MARKEINS is not set -++# CONFIG_MACH_VR41XX is not set -++# CONFIG_PNX8550_JBS is not set -++# CONFIG_PNX8550_STB810 is not set -++# CONFIG_PMC_MSP is not set -++# CONFIG_PMC_YOSEMITE is not set -++# CONFIG_QEMU is not set -++# CONFIG_SGI_IP22 is not set -++# CONFIG_SGI_IP27 is not set -++# CONFIG_SGI_IP32 is not set -++# CONFIG_SIBYTE_CRHINE is not set -++# CONFIG_SIBYTE_CARMEL is not set -++# CONFIG_SIBYTE_CRHONE is not set -++# CONFIG_SIBYTE_RHONE is not set -++# CONFIG_SIBYTE_SWARM is not set -++# CONFIG_SIBYTE_LITTLESUR is not set -++# CONFIG_SIBYTE_SENTOSA is not set -++# CONFIG_SIBYTE_PTSWARM is not set -++# CONFIG_SIBYTE_BIGSUR is not set -++# CONFIG_SNI_RM is not set -++# CONFIG_TOSHIBA_JMR3927 is not set -++# CONFIG_TOSHIBA_RBTX4927 is not set -++# CONFIG_TOSHIBA_RBTX4938 is not set -++# CONFIG_WR_PPMC is not set -++CONFIG_SOC_JZ4740=y -++CONFIG_SOC_JZ4720=y -++CONFIG_JZSOC=y -++CONFIG_JZRISC=y -++CONFIG_RWSEM_GENERIC_SPINLOCK=y -++# CONFIG_ARCH_HAS_ILOG2_U32 is not set -++# CONFIG_ARCH_HAS_ILOG2_U64 is not set -++CONFIG_ARCH_SUPPORTS_OPROFILE=y -++CONFIG_GENERIC_FIND_NEXT_BIT=y -++CONFIG_GENERIC_HWEIGHT=y -++CONFIG_GENERIC_CALIBRATE_DELAY=y -++CONFIG_GENERIC_CLOCKEVENTS=y -++CONFIG_GENERIC_TIME=y -++CONFIG_GENERIC_CMOS_UPDATE=y -++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -++# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set -++CONFIG_DMA_NONCOHERENT=y -++CONFIG_DMA_NEED_PCI_MAP_STATE=y -++# CONFIG_HOTPLUG_CPU is not set -++# CONFIG_NO_IOPORT is not set -++# CONFIG_CPU_BIG_ENDIAN is not set -++CONFIG_CPU_LITTLE_ENDIAN=y -++CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -++CONFIG_MIPS_L1_CACHE_SHIFT=5 -++ -++# -++# CPU selection -++# -++# CONFIG_CPU_LOONGSON2 is not set -++CONFIG_CPU_MIPS32_R1=y -++# CONFIG_CPU_MIPS32_R2 is not set -++# CONFIG_CPU_MIPS64_R1 is not set -++# CONFIG_CPU_MIPS64_R2 is not set -++# CONFIG_CPU_R3000 is not set -++# CONFIG_CPU_TX39XX is not set -++# CONFIG_CPU_VR41XX is not set -++# CONFIG_CPU_R4300 is not set -++# CONFIG_CPU_R4X00 is not set -++# CONFIG_CPU_TX49XX is not set -++# CONFIG_CPU_R5000 is not set -++# CONFIG_CPU_R5432 is not set -++# CONFIG_CPU_R6000 is not set -++# CONFIG_CPU_NEVADA is not set -++# CONFIG_CPU_R8000 is not set -++# CONFIG_CPU_R10000 is not set -++# CONFIG_CPU_RM7000 is not set -++# CONFIG_CPU_RM9000 is not set -++# CONFIG_CPU_SB1 is not set -++CONFIG_SYS_HAS_CPU_MIPS32_R1=y -++CONFIG_CPU_MIPS32=y -++CONFIG_CPU_MIPSR1=y -++CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -++CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -++ -++# -++# Kernel type -++# -++CONFIG_32BIT=y -++# CONFIG_64BIT is not set -++CONFIG_PAGE_SIZE_4KB=y -++# CONFIG_PAGE_SIZE_8KB is not set -++# CONFIG_PAGE_SIZE_16KB is not set -++# CONFIG_PAGE_SIZE_64KB is not set -++CONFIG_CPU_HAS_PREFETCH=y -++CONFIG_MIPS_MT_DISABLED=y -++# CONFIG_MIPS_MT_SMP is not set -++# CONFIG_MIPS_MT_SMTC is not set -++CONFIG_CPU_HAS_LLSC=y -++CONFIG_CPU_HAS_SYNC=y -++CONFIG_GENERIC_HARDIRQS=y -++CONFIG_GENERIC_IRQ_PROBE=y -++CONFIG_CPU_SUPPORTS_HIGHMEM=y -++CONFIG_ARCH_FLATMEM_ENABLE=y -++CONFIG_ARCH_POPULATES_NODE_MAP=y -++CONFIG_SELECT_MEMORY_MODEL=y -++CONFIG_FLATMEM_MANUAL=y -++# CONFIG_DISCONTIGMEM_MANUAL is not set -++# CONFIG_SPARSEMEM_MANUAL is not set -++CONFIG_FLATMEM=y -++CONFIG_FLAT_NODE_MEM_MAP=y -++# CONFIG_SPARSEMEM_STATIC is not set -++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -++CONFIG_SPLIT_PTLOCK_CPUS=4 -++# CONFIG_RESOURCES_64BIT is not set -++CONFIG_ZONE_DMA_FLAG=0 -++CONFIG_VIRT_TO_BUS=y -++# CONFIG_TICK_ONESHOT is not set -++# CONFIG_NO_HZ is not set -++# CONFIG_HIGH_RES_TIMERS is not set -++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -++# CONFIG_HZ_48 is not set -++CONFIG_HZ_100=y -++# CONFIG_HZ_128 is not set -++# CONFIG_HZ_250 is not set -++# CONFIG_HZ_256 is not set -++# CONFIG_HZ_1000 is not set -++# CONFIG_HZ_1024 is not set -++CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -++CONFIG_HZ=100 -++# CONFIG_PREEMPT_NONE is not set -++# CONFIG_PREEMPT_VOLUNTARY is not set -++CONFIG_PREEMPT=y -++CONFIG_PREEMPT_BKL=y -++# CONFIG_KEXEC is not set -++CONFIG_SECCOMP=y -++CONFIG_LOCKDEP_SUPPORT=y -++CONFIG_STACKTRACE_SUPPORT=y -++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -++ -++# -++# General setup -++# -++CONFIG_EXPERIMENTAL=y -++CONFIG_BROKEN_ON_SMP=y -++CONFIG_LOCK_KERNEL=y -++CONFIG_INIT_ENV_ARG_LIMIT=32 -++CONFIG_LOCALVERSION="" -++CONFIG_LOCALVERSION_AUTO=y -++CONFIG_SWAP=y -++CONFIG_SYSVIPC=y -++CONFIG_SYSVIPC_SYSCTL=y -++# CONFIG_POSIX_MQUEUE is not set -++# CONFIG_BSD_PROCESS_ACCT is not set -++# CONFIG_TASKSTATS is not set -++# CONFIG_USER_NS is not set -++# CONFIG_PID_NS is not set -++# CONFIG_AUDIT is not set -++# CONFIG_IKCONFIG is not set -++CONFIG_LOG_BUF_SHIFT=14 -++# CONFIG_CGROUPS is not set -++CONFIG_FAIR_GROUP_SCHED=y -++CONFIG_FAIR_USER_SCHED=y -++# CONFIG_FAIR_CGROUP_SCHED is not set -++CONFIG_SYSFS_DEPRECATED=y -++CONFIG_RELAY=y -++# CONFIG_BLK_DEV_INITRD is not set -++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -++CONFIG_SYSCTL=y -++CONFIG_EMBEDDED=y -++CONFIG_SYSCTL_SYSCALL=y -++CONFIG_KALLSYMS=y -++# CONFIG_KALLSYMS_EXTRA_PASS is not set -++CONFIG_HOTPLUG=y -++CONFIG_PRINTK=y -++CONFIG_BUG=y -++CONFIG_ELF_CORE=y -++CONFIG_BASE_FULL=y -++CONFIG_FUTEX=y -++CONFIG_ANON_INODES=y -++CONFIG_EPOLL=y -++CONFIG_SIGNALFD=y -++CONFIG_EVENTFD=y -++CONFIG_SHMEM=y -++CONFIG_VM_EVENT_COUNTERS=y -++CONFIG_SLAB=y -++# CONFIG_SLUB is not set -++# CONFIG_SLOB is not set -++CONFIG_SLABINFO=y -++CONFIG_RT_MUTEXES=y -++# CONFIG_TINY_SHMEM is not set -++CONFIG_BASE_SMALL=0 -++CONFIG_MODULES=y -++CONFIG_MODULE_UNLOAD=y -++# CONFIG_MODULE_FORCE_UNLOAD is not set -++CONFIG_MODVERSIONS=y -++CONFIG_MODULE_SRCVERSION_ALL=y -++CONFIG_KMOD=y -++CONFIG_BLOCK=y -++# CONFIG_LBD is not set -++# CONFIG_BLK_DEV_IO_TRACE is not set -++# CONFIG_LSF is not set -++# CONFIG_BLK_DEV_BSG is not set -++ -++# -++# IO Schedulers -++# -++CONFIG_IOSCHED_NOOP=y -++CONFIG_IOSCHED_AS=y -++CONFIG_IOSCHED_DEADLINE=y -++CONFIG_IOSCHED_CFQ=y -++CONFIG_DEFAULT_AS=y -++# CONFIG_DEFAULT_DEADLINE is not set -++# CONFIG_DEFAULT_CFQ is not set -++# CONFIG_DEFAULT_NOOP is not set -++CONFIG_DEFAULT_IOSCHED="anticipatory" -++ -++# -++# Bus options (PCI, PCMCIA, EISA, ISA, TC) -++# -++# CONFIG_ARCH_SUPPORTS_MSI is not set -++CONFIG_MMU=y -++# CONFIG_PCCARD is not set -++ -++# -++# Executable file formats -++# -++CONFIG_BINFMT_ELF=y -++# CONFIG_BINFMT_MISC is not set -++CONFIG_TRAD_SIGNALS=y -++ -++# -++# CPU Frequency scaling -++# -++CONFIG_CPU_FREQ_JZ=y -++CONFIG_CPU_FREQ=y -++CONFIG_CPU_FREQ_TABLE=y -++# CONFIG_CPU_FREQ_DEBUG is not set -++CONFIG_CPU_FREQ_STAT=y -++# CONFIG_CPU_FREQ_STAT_DETAILS is not set -++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -++CONFIG_CPU_FREQ_GOV_USERSPACE=y -++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set -++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -++ -++# -++# Power management options -++# -++CONFIG_PM=y -++CONFIG_PM_LEGACY=y -++# CONFIG_PM_DEBUG is not set -++CONFIG_SUSPEND_UP_POSSIBLE=y -++# CONFIG_SUSPEND is not set -++ -++# -++# Networking -++# -++CONFIG_NET=y -++ -++# -++# Networking options -++# -++CONFIG_PACKET=y -++# CONFIG_PACKET_MMAP is not set -++CONFIG_UNIX=y -++# CONFIG_NET_KEY is not set -++CONFIG_INET=y -++# CONFIG_IP_MULTICAST is not set -++# CONFIG_IP_ADVANCED_ROUTER is not set -++CONFIG_IP_FIB_HASH=y -++CONFIG_IP_PNP=y -++CONFIG_IP_PNP_DHCP=y -++CONFIG_IP_PNP_BOOTP=y -++# CONFIG_IP_PNP_RARP is not set -++# CONFIG_NET_IPIP is not set -++# CONFIG_NET_IPGRE is not set -++# CONFIG_ARPD is not set -++# CONFIG_SYN_COOKIES is not set -++# CONFIG_INET_AH is not set -++# CONFIG_INET_ESP is not set -++# CONFIG_INET_IPCOMP is not set -++# CONFIG_INET_XFRM_TUNNEL is not set -++# CONFIG_INET_TUNNEL is not set -++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -++# CONFIG_INET_XFRM_MODE_TUNNEL is not set -++# CONFIG_INET_XFRM_MODE_BEET is not set -++# CONFIG_INET_LRO is not set -++# CONFIG_INET_DIAG is not set -++# CONFIG_TCP_CONG_ADVANCED is not set -++CONFIG_TCP_CONG_CUBIC=y -++CONFIG_DEFAULT_TCP_CONG="cubic" -++# CONFIG_TCP_MD5SIG is not set -++# CONFIG_IPV6 is not set -++# CONFIG_INET6_XFRM_TUNNEL is not set -++# CONFIG_INET6_TUNNEL is not set -++# CONFIG_NETWORK_SECMARK is not set -++# CONFIG_NETFILTER is not set -++# CONFIG_IP_DCCP is not set -++# CONFIG_IP_SCTP is not set -++# CONFIG_TIPC is not set -++# CONFIG_ATM is not set -++# CONFIG_BRIDGE is not set -++# CONFIG_VLAN_8021Q is not set -++# CONFIG_DECNET is not set -++# CONFIG_LLC2 is not set -++# CONFIG_IPX is not set -++# CONFIG_ATALK is not set -++# CONFIG_X25 is not set -++# CONFIG_LAPB is not set -++# CONFIG_ECONET is not set -++# CONFIG_WAN_ROUTER is not set -++# CONFIG_NET_SCHED is not set -++ -++# -++# Network testing -++# -++# CONFIG_NET_PKTGEN is not set -++# CONFIG_HAMRADIO is not set -++# CONFIG_IRDA is not set -++# CONFIG_BT is not set -++# CONFIG_AF_RXRPC is not set -++ -++# -++# Wireless -++# -++# CONFIG_CFG80211 is not set -++CONFIG_WIRELESS_EXT=y -++# CONFIG_MAC80211 is not set -++# CONFIG_IEEE80211 is not set -++# CONFIG_RFKILL is not set -++# CONFIG_NET_9P is not set -++ -++# -++# Device Drivers -++# -++ -++# -++# Generic Driver Options -++# -++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -++CONFIG_STANDALONE=y -++CONFIG_PREVENT_FIRMWARE_BUILD=y -++# CONFIG_FW_LOADER is not set -++# CONFIG_SYS_HYPERVISOR is not set -++# CONFIG_CONNECTOR is not set -++CONFIG_MTD=y -++# CONFIG_MTD_DEBUG is not set -++# CONFIG_MTD_CONCAT is not set -++CONFIG_MTD_PARTITIONS=y -++# CONFIG_MTD_REDBOOT_PARTS is not set -++# CONFIG_MTD_CMDLINE_PARTS is not set -++ -++# -++# User Modules And Translation Layers -++# -++CONFIG_MTD_CHAR=y -++CONFIG_MTD_BLKDEVS=y -++CONFIG_MTD_BLOCK=y -++# CONFIG_FTL is not set -++# CONFIG_NFTL is not set -++# CONFIG_INFTL is not set -++# CONFIG_RFD_FTL is not set -++# CONFIG_SSFDC is not set -++# CONFIG_MTD_OOPS is not set -++ -++# -++# RAM/ROM/Flash chip drivers -++# -++# CONFIG_MTD_CFI is not set -++# CONFIG_MTD_JEDECPROBE is not set -++CONFIG_MTD_MAP_BANK_WIDTH_1=y -++CONFIG_MTD_MAP_BANK_WIDTH_2=y -++CONFIG_MTD_MAP_BANK_WIDTH_4=y -++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -++CONFIG_MTD_CFI_I1=y -++CONFIG_MTD_CFI_I2=y -++# CONFIG_MTD_CFI_I4 is not set -++# CONFIG_MTD_CFI_I8 is not set -++# CONFIG_MTD_RAM is not set -++# CONFIG_MTD_ROM is not set -++# CONFIG_MTD_ABSENT is not set -++ -++# -++# Mapping drivers for chip access -++# -++# CONFIG_MTD_COMPLEX_MAPPINGS is not set -++# CONFIG_MTD_PLATRAM is not set -++ -++# -++# Self-contained MTD device drivers -++# -++# CONFIG_MTD_SLRAM is not set -++# CONFIG_MTD_PHRAM is not set -++# CONFIG_MTD_MTDRAM is not set -++# CONFIG_MTD_BLOCK2MTD is not set -++ -++# -++# Disk-On-Chip Device Drivers -++# -++# CONFIG_MTD_DOC2000 is not set -++# CONFIG_MTD_DOC2001 is not set -++# CONFIG_MTD_DOC2001PLUS is not set -++CONFIG_MTD_NAND=y -++# CONFIG_MTD_NAND_VERIFY_WRITE is not set -++# CONFIG_MTD_NAND_ECC_SMC is not set -++# CONFIG_MTD_NAND_MUSEUM_IDS is not set -++CONFIG_MTD_NAND_IDS=y -++# CONFIG_MTD_NAND_DISKONCHIP is not set -++# CONFIG_MTD_NAND_NANDSIM is not set -++# CONFIG_MTD_NAND_PLATFORM is not set -++# CONFIG_MTD_ALAUDA is not set -++CONFIG_MTD_NAND_JZ4740=y -++# CONFIG_MTD_HW_HM_ECC is not set -++# CONFIG_MTD_SW_HM_ECC is not set -++CONFIG_MTD_HW_RS_ECC=y -++# CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE is not set -++CONFIG_MTD_OOB_COPIES=3 -++CONFIG_MTD_BADBLOCK_FLAG_PAGE=127 -++# CONFIG_MTD_ONENAND is not set -++ -++# -++# UBI - Unsorted block images -++# -++CONFIG_MTD_UBI=m -++CONFIG_MTD_UBI_WL_THRESHOLD=256 -++CONFIG_MTD_UBI_BEB_RESERVE=1 -++# CONFIG_MTD_UBI_GLUEBI is not set -++ -++# -++# UBI debugging options -++# -++# CONFIG_MTD_UBI_DEBUG is not set -++CONFIG_MTD_UBI_BLKDEVS=m -++CONFIG_MTD_UBI_BLOCK=m -++# CONFIG_PARPORT is not set -++CONFIG_PNP=y -++# CONFIG_PNP_DEBUG is not set -++ -++# -++# Protocols -++# -++# CONFIG_PNPACPI is not set -++CONFIG_BLK_DEV=y -++# CONFIG_BLK_DEV_COW_COMMON is not set -++CONFIG_BLK_DEV_LOOP=y -++# CONFIG_BLK_DEV_CRYPTOLOOP is not set -++# CONFIG_BLK_DEV_NBD is not set -++# CONFIG_BLK_DEV_UB is not set -++CONFIG_BLK_DEV_RAM=y -++CONFIG_BLK_DEV_RAM_COUNT=2 -++CONFIG_BLK_DEV_RAM_SIZE=4096 -++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -++# CONFIG_CDROM_PKTCDVD is not set -++# CONFIG_ATA_OVER_ETH is not set -++CONFIG_MISC_DEVICES=y -++# CONFIG_EEPROM_93CX6 is not set -++# CONFIG_IDE is not set -++ -++# -++# SCSI device support -++# -++# CONFIG_RAID_ATTRS is not set -++CONFIG_SCSI=y -++CONFIG_SCSI_DMA=y -++# CONFIG_SCSI_TGT is not set -++# CONFIG_SCSI_NETLINK is not set -++CONFIG_SCSI_PROC_FS=y -++ -++# -++# SCSI support type (disk, tape, CD-ROM) -++# -++CONFIG_BLK_DEV_SD=y -++# CONFIG_CHR_DEV_ST is not set -++# CONFIG_CHR_DEV_OSST is not set -++# CONFIG_BLK_DEV_SR is not set -++# CONFIG_CHR_DEV_SG is not set -++# CONFIG_CHR_DEV_SCH is not set -++ -++# -++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -++# -++# CONFIG_SCSI_MULTI_LUN is not set -++# CONFIG_SCSI_CONSTANTS is not set -++# CONFIG_SCSI_LOGGING is not set -++# CONFIG_SCSI_SCAN_ASYNC is not set -++CONFIG_SCSI_WAIT_SCAN=m -++ -++# -++# SCSI Transports -++# -++# CONFIG_SCSI_SPI_ATTRS is not set -++# CONFIG_SCSI_FC_ATTRS is not set -++# CONFIG_SCSI_ISCSI_ATTRS is not set -++# CONFIG_SCSI_SAS_LIBSAS is not set -++# CONFIG_SCSI_SRP_ATTRS is not set -++CONFIG_SCSI_LOWLEVEL=y -++# CONFIG_ISCSI_TCP is not set -++# CONFIG_SCSI_DEBUG is not set -++# CONFIG_ATA is not set -++# CONFIG_MD is not set -++CONFIG_NETDEVICES=y -++# CONFIG_NETDEVICES_MULTIQUEUE is not set -++# CONFIG_DUMMY is not set -++# CONFIG_BONDING is not set -++# CONFIG_MACVLAN is not set -++# CONFIG_EQUALIZER is not set -++# CONFIG_TUN is not set -++# CONFIG_VETH is not set -++# CONFIG_NET_SB1000 is not set -++CONFIG_PHYLIB=y -++ -++# -++# MII PHY device drivers -++# -++# CONFIG_MARVELL_PHY is not set -++# CONFIG_DAVICOM_PHY is not set -++# CONFIG_QSEMI_PHY is not set -++# CONFIG_LXT_PHY is not set -++# CONFIG_CICADA_PHY is not set -++# CONFIG_VITESSE_PHY is not set -++# CONFIG_SMSC_PHY is not set -++# CONFIG_BROADCOM_PHY is not set -++# CONFIG_ICPLUS_PHY is not set -++# CONFIG_FIXED_PHY is not set -++# CONFIG_MDIO_BITBANG is not set -++CONFIG_NET_ETHERNET=y -++CONFIG_MII=y -++CONFIG_JZCS8900=y -++# CONFIG_AX88796 is not set -++# CONFIG_DM9000 is not set -++# CONFIG_IBM_NEW_EMAC_ZMII is not set -++# CONFIG_IBM_NEW_EMAC_RGMII is not set -++# CONFIG_IBM_NEW_EMAC_TAH is not set -++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -++# CONFIG_B44 is not set -++# CONFIG_NETDEV_1000 is not set -++# CONFIG_NETDEV_10000 is not set -++ -++# -++# Wireless LAN -++# -++# CONFIG_WLAN_PRE80211 is not set -++# CONFIG_WLAN_80211 is not set -++ -++# -++# USB Network Adapters -++# -++# CONFIG_USB_CATC is not set -++# CONFIG_USB_KAWETH is not set -++# CONFIG_USB_PEGASUS is not set -++# CONFIG_USB_RTL8150 is not set -++# CONFIG_USB_USBNET is not set -++# CONFIG_WAN is not set -++# CONFIG_PPP is not set -++# CONFIG_SLIP is not set -++# CONFIG_SHAPER is not set -++# CONFIG_NETCONSOLE is not set -++# CONFIG_NETPOLL is not set -++# CONFIG_NET_POLL_CONTROLLER is not set -++# CONFIG_ISDN is not set -++# CONFIG_PHONE is not set -++ -++# -++# Input device support -++# -++CONFIG_INPUT=y -++# CONFIG_INPUT_FF_MEMLESS is not set -++# CONFIG_INPUT_POLLDEV is not set -++ -++# -++# Userland interfaces -++# -++CONFIG_INPUT_MOUSEDEV=y -++CONFIG_INPUT_MOUSEDEV_PSAUX=y -++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -++# CONFIG_INPUT_JOYDEV is not set -++CONFIG_INPUT_EVDEV=y -++# CONFIG_INPUT_EVBUG is not set -++ -++# -++# Input Device Drivers -++# -++# CONFIG_INPUT_KEYBOARD is not set -++# CONFIG_INPUT_MOUSE is not set -++# CONFIG_INPUT_JOYSTICK is not set -++# CONFIG_INPUT_TABLET is not set -++# CONFIG_INPUT_TOUCHSCREEN is not set -++# CONFIG_INPUT_MISC is not set -++ -++# -++# Hardware I/O ports -++# -++CONFIG_SERIO=y -++# CONFIG_SERIO_I8042 is not set -++CONFIG_SERIO_SERPORT=y -++# CONFIG_SERIO_LIBPS2 is not set -++# CONFIG_SERIO_RAW is not set -++# CONFIG_GAMEPORT is not set -++ -++# -++# Character devices -++# -++CONFIG_VT=y -++CONFIG_VT_CONSOLE=y -++CONFIG_HW_CONSOLE=y -++CONFIG_VT_HW_CONSOLE_BINDING=y -++# CONFIG_SERIAL_NONSTANDARD is not set -++ -++# -++# Serial drivers -++# -++CONFIG_SERIAL_8250=y -++CONFIG_SERIAL_8250_CONSOLE=y -++CONFIG_SERIAL_8250_PNP=y -++CONFIG_SERIAL_8250_NR_UARTS=2 -++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 -++# CONFIG_SERIAL_8250_EXTENDED is not set -++ -++# -++# Non-8250 serial port support -++# -++CONFIG_SERIAL_CORE=y -++CONFIG_SERIAL_CORE_CONSOLE=y -++CONFIG_UNIX98_PTYS=y -++CONFIG_LEGACY_PTYS=y -++CONFIG_LEGACY_PTY_COUNT=2 -++# CONFIG_IPMI_HANDLER is not set -++# CONFIG_HW_RANDOM is not set -++# CONFIG_RTC is not set -++# CONFIG_RTC_PCF8563 is not set -++CONFIG_RTC_JZ=y -++# CONFIG_R3964 is not set -++# CONFIG_RAW_DRIVER is not set -++# CONFIG_TCG_TPM is not set -++ -++# -++# JZSOC char device support -++# -++CONFIG_JZCHAR=y -++# CONFIG_JZ_CIM is not set -++# CONFIG_JZ_TPANEL_ATA2508 is not set -++CONFIG_JZ_TPANEL=y -++CONFIG_JZ_SADC=y -++# CONFIG_JZ_TPANEL_AK4182 is not set -++# CONFIG_JZ_TPANEL_UCB1400 is not set -++# CONFIG_JZ_TPANEL_WM9712 is not set -++CONFIG_JZ_UDC_HOTPLUG=y -++CONFIG_JZ_POWEROFF=y -++# CONFIG_JZ_OW is not set -++# CONFIG_I2C is not set -++ -++# -++# SPI support -++# -++# CONFIG_SPI is not set -++# CONFIG_SPI_MASTER is not set -++# CONFIG_W1 is not set -++# CONFIG_POWER_SUPPLY is not set -++# CONFIG_HWMON is not set -++CONFIG_WATCHDOG=y -++# CONFIG_WATCHDOG_NOWAYOUT is not set -++ -++# -++# Watchdog Device Drivers -++# -++CONFIG_JZ_WDT=y -++# CONFIG_SOFT_WATCHDOG is not set -++ -++# -++# USB-based Watchdog Cards -++# -++# CONFIG_USBPCWATCHDOG is not set -++ -++# -++# Sonics Silicon Backplane -++# -++CONFIG_SSB_POSSIBLE=y -++# CONFIG_SSB is not set -++ -++# -++# Multifunction device drivers -++# -++# CONFIG_MFD_SM501 is not set -++ -++# -++# Multimedia devices -++# -++CONFIG_VIDEO_DEV=y -++CONFIG_VIDEO_V4L1=y -++CONFIG_VIDEO_V4L1_COMPAT=y -++CONFIG_VIDEO_V4L2=y -++CONFIG_VIDEO_CAPTURE_DRIVERS=y -++# CONFIG_VIDEO_ADV_DEBUG is not set -++CONFIG_VIDEO_HELPER_CHIPS_AUTO=y -++# CONFIG_VIDEO_VIVI is not set -++# CONFIG_VIDEO_CPIA is not set -++# CONFIG_VIDEO_CPIA2 is not set -++CONFIG_VIDEO_JZ_CIM=y -++CONFIG_VIDEO_JZ_SENSOR=y -++CONFIG_V4L_USB_DRIVERS=y -++# CONFIG_USB_VICAM is not set -++# CONFIG_USB_IBMCAM is not set -++# CONFIG_USB_KONICAWC is not set -++# CONFIG_USB_QUICKCAM_MESSENGER is not set -++# CONFIG_USB_ET61X251 is not set -++# CONFIG_USB_OV511 is not set -++# CONFIG_USB_SE401 is not set -++# CONFIG_USB_SN9C102 is not set -++# CONFIG_USB_STV680 is not set -++# CONFIG_USB_ZC0301 is not set -++# CONFIG_USB_PWC is not set -++# CONFIG_USB_ZR364XX is not set -++CONFIG_RADIO_ADAPTERS=y -++# CONFIG_USB_DSBR is not set -++# CONFIG_DVB_CORE is not set -++# CONFIG_DAB is not set -++ -++# -++# Graphics support -++# -++# CONFIG_VGASTATE is not set -++# CONFIG_VIDEO_OUTPUT_CONTROL is not set -++CONFIG_FB=y -++# CONFIG_FIRMWARE_EDID is not set -++# CONFIG_FB_DDC is not set -++CONFIG_FB_CFB_FILLRECT=y -++CONFIG_FB_CFB_COPYAREA=y -++CONFIG_FB_CFB_IMAGEBLIT=y -++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -++# CONFIG_FB_SYS_FILLRECT is not set -++# CONFIG_FB_SYS_COPYAREA is not set -++# CONFIG_FB_SYS_IMAGEBLIT is not set -++# CONFIG_FB_SYS_FOPS is not set -++CONFIG_FB_DEFERRED_IO=y -++# CONFIG_FB_SVGALIB is not set -++# CONFIG_FB_MACMODES is not set -++# CONFIG_FB_BACKLIGHT is not set -++# CONFIG_FB_MODE_HELPERS is not set -++# CONFIG_FB_TILEBLITTING is not set -++ -++# -++# Frame buffer hardware drivers -++# -++CONFIG_FB_JZSOC=y -++# CONFIG_FB_JZ4740_SLCD is not set -++CONFIG_FB_JZLCD_4730_4740=y -++CONFIG_JZLCD_FRAMEBUFFER_MAX=1 -++# CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT is not set -++# CONFIG_JZLCD_SHARP_LQ035Q7 is not set -++# CONFIG_JZLCD_SAMSUNG_LTS350Q1 is not set -++# CONFIG_JZLCD_SAMSUNG_LTV350QVF04 is not set -++# CONFIG_JZLCD_SAMSUNG_LTP400WQF01 is not set -++CONFIG_JZLCD_SAMSUNG_LTP400WQF02=y -++# CONFIG_JZLCD_AUO_A030FL01_V1 is not set -++# CONFIG_JZLCD_TRULY_TFTG320240DTSW is not set -++# CONFIG_JZLCD_TRULY_TFTG320240DTSW_SERIAL is not set -++# CONFIG_JZLCD_TRULY_TFTG240320UTSW_63W_E is not set -++# CONFIG_JZLCD_FOXCONN_PT035TN01 is not set -++# CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL is not set -++# CONFIG_JZLCD_TOSHIBA_LTM084P363 is not set -++# CONFIG_JZLCD_HYNIX_HT10X21 is not set -++# CONFIG_JZLCD_INNOLUX_AT080TN42 is not set -++# CONFIG_JZLCD_CSTN_800x600 is not set -++# CONFIG_JZLCD_CSTN_320x240 is not set -++# CONFIG_JZLCD_MSTN_480x320 is not set -++# CONFIG_JZLCD_MSTN_320x240 is not set -++# CONFIG_JZLCD_MSTN_240x128 is not set -++# CONFIG_FB_S1D13XXX is not set -++# CONFIG_FB_VIRTUAL is not set -++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set -++ -++# -++# Display device support -++# -++# CONFIG_DISPLAY_SUPPORT is not set -++ -++# -++# Console display driver support -++# -++# CONFIG_VGA_CONSOLE is not set -++CONFIG_DUMMY_CONSOLE=y -++CONFIG_FRAMEBUFFER_CONSOLE=y -++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -++# CONFIG_FRAMEBUFFER_CONSOLE_CURSOR_FLASH is not set -++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -++CONFIG_FONTS=y -++CONFIG_FONT_8x8=y -++CONFIG_FONT_8x16=y -++# CONFIG_FONT_6x11 is not set -++# CONFIG_FONT_7x14 is not set -++# CONFIG_FONT_PEARL_8x8 is not set -++# CONFIG_FONT_ACORN_8x8 is not set -++# CONFIG_FONT_MINI_4x6 is not set -++# CONFIG_FONT_SUN8x16 is not set -++# CONFIG_FONT_SUN12x22 is not set -++# CONFIG_FONT_10x18 is not set -++CONFIG_LOGO=y -++CONFIG_LOGO_LINUX_MONO=y -++CONFIG_LOGO_LINUX_VGA16=y -++CONFIG_LOGO_LINUX_CLUT224=y -++ -++# -++# Sound -++# -++CONFIG_SOUND=y -++ -++# -++# Advanced Linux Sound Architecture -++# -++# CONFIG_SND is not set -++ -++# -++# Open Sound System -++# -++CONFIG_SOUND_PRIME=y -++CONFIG_OSS_OBSOLETE=y -++# CONFIG_SOUND_JZ_AC97 is not set -++CONFIG_SOUND_JZ_I2S=y -++# CONFIG_SOUND_JZ_PCM is not set -++# CONFIG_I2S_AK4642EN is not set -++CONFIG_I2S_ICODEC=y -++# CONFIG_SOUND_MSNDCLAS is not set -++# CONFIG_SOUND_MSNDPIN is not set -++CONFIG_HID_SUPPORT=y -++CONFIG_HID=y -++# CONFIG_HID_DEBUG is not set -++# CONFIG_HIDRAW is not set -++ -++# -++# USB Input Devices -++# -++CONFIG_USB_HID=y -++# CONFIG_USB_HIDINPUT_POWERBOOK is not set -++# CONFIG_HID_FF is not set -++# CONFIG_USB_HIDDEV is not set -++CONFIG_USB_SUPPORT=y -++CONFIG_USB_ARCH_HAS_HCD=y -++CONFIG_USB_ARCH_HAS_OHCI=y -++# CONFIG_USB_ARCH_HAS_EHCI is not set -++CONFIG_USB=y -++# CONFIG_USB_DEBUG is not set -++ -++# -++# Miscellaneous USB options -++# -++# CONFIG_USB_DEVICEFS is not set -++CONFIG_USB_DEVICE_CLASS=y -++# CONFIG_USB_DYNAMIC_MINORS is not set -++# CONFIG_USB_SUSPEND is not set -++# CONFIG_USB_PERSIST is not set -++# CONFIG_USB_OTG is not set -++ -++# -++# USB Host Controller Drivers -++# -++# CONFIG_USB_ISP116X_HCD is not set -++CONFIG_USB_OHCI_HCD=y -++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set -++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set -++CONFIG_USB_OHCI_LITTLE_ENDIAN=y -++# CONFIG_USB_SL811_HCD is not set -++# CONFIG_USB_R8A66597_HCD is not set -++ -++# -++# USB Device Class drivers -++# -++# CONFIG_USB_ACM is not set -++# CONFIG_USB_PRINTER is not set -++ -++# -++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -++# -++ -++# -++# may also be needed; see USB_STORAGE Help for more information -++# -++CONFIG_USB_STORAGE=y -++# CONFIG_USB_STORAGE_DEBUG is not set -++# CONFIG_USB_STORAGE_DATAFAB is not set -++# CONFIG_USB_STORAGE_FREECOM is not set -++# CONFIG_USB_STORAGE_ISD200 is not set -++# CONFIG_USB_STORAGE_DPCM is not set -++# CONFIG_USB_STORAGE_USBAT is not set -++# CONFIG_USB_STORAGE_SDDR09 is not set -++# CONFIG_USB_STORAGE_SDDR55 is not set -++# CONFIG_USB_STORAGE_JUMPSHOT is not set -++# CONFIG_USB_STORAGE_ALAUDA is not set -++# CONFIG_USB_STORAGE_KARMA is not set -++# CONFIG_USB_LIBUSUAL is not set -++ -++# -++# USB Imaging devices -++# -++# CONFIG_USB_MDC800 is not set -++# CONFIG_USB_MICROTEK is not set -++CONFIG_USB_MON=y -++ -++# -++# USB port drivers -++# -++ -++# -++# USB Serial Converter support -++# -++# CONFIG_USB_SERIAL is not set -++ -++# -++# USB Miscellaneous drivers -++# -++# CONFIG_USB_EMI62 is not set -++# CONFIG_USB_EMI26 is not set -++# CONFIG_USB_ADUTUX is not set -++# CONFIG_USB_AUERSWALD is not set -++# CONFIG_USB_RIO500 is not set -++# CONFIG_USB_LEGOTOWER is not set -++# CONFIG_USB_LCD is not set -++# CONFIG_USB_BERRY_CHARGE is not set -++# CONFIG_USB_LED is not set -++# CONFIG_USB_CYPRESS_CY7C63 is not set -++# CONFIG_USB_CYTHERM is not set -++# CONFIG_USB_PHIDGET is not set -++# CONFIG_USB_IDMOUSE is not set -++# CONFIG_USB_FTDI_ELAN is not set -++# CONFIG_USB_APPLEDISPLAY is not set -++# CONFIG_USB_LD is not set -++# CONFIG_USB_TRANCEVIBRATOR is not set -++# CONFIG_USB_IOWARRIOR is not set -++ -++# -++# USB DSL modem support -++# -++ -++# -++# USB Gadget Support -++# -++CONFIG_USB_GADGET=m -++# CONFIG_USB_GADGET_DEBUG_FILES is not set -++# CONFIG_USB_GADGET_DEBUG_FS is not set -++CONFIG_USB_GADGET_SELECTED=y -++CONFIG_USB_GADGET_JZ4740=y -++CONFIG_USB_JZ4740=m -++# CONFIG_USB_GADGET_JZ4730 is not set -++# CONFIG_USB_GADGET_AMD5536UDC is not set -++# CONFIG_USB_GADGET_ATMEL_USBA is not set -++# CONFIG_USB_GADGET_FSL_USB2 is not set -++# CONFIG_USB_GADGET_NET2280 is not set -++# CONFIG_USB_GADGET_PXA2XX is not set -++# CONFIG_USB_GADGET_M66592 is not set -++# CONFIG_USB_GADGET_GOKU is not set -++# CONFIG_USB_GADGET_LH7A40X is not set -++# CONFIG_USB_GADGET_OMAP is not set -++# CONFIG_USB_GADGET_S3C2410 is not set -++# CONFIG_USB_GADGET_AT91 is not set -++# CONFIG_USB_GADGET_DUMMY_HCD is not set -++CONFIG_USB_GADGET_DUALSPEED=y -++# CONFIG_USB_ZERO is not set -++# CONFIG_USB_ETH is not set -++# CONFIG_USB_GADGETFS is not set -++CONFIG_USB_FILE_STORAGE=m -++# CONFIG_USB_FILE_STORAGE_TEST is not set -++# CONFIG_USB_G_SERIAL is not set -++# CONFIG_USB_MIDI_GADGET is not set -++CONFIG_MMC=y -++# CONFIG_MMC_DEBUG is not set -++# CONFIG_MMC_UNSAFE_RESUME is not set -++ -++# -++# MMC/SD Card Drivers -++# -++CONFIG_MMC_BLOCK=y -++CONFIG_MMC_BLOCK_BOUNCE=y -++# CONFIG_SDIO_UART is not set -++ -++# -++# MMC/SD Host Controller Drivers -++# -++CONFIG_MMC_JZ=y -++CONFIG_JZ_MMC_BUS_4=y -++# CONFIG_JZ_MMC_BUS_1 is not set -++# CONFIG_NEW_LEDS is not set -++CONFIG_RTC_LIB=y -++# CONFIG_RTC_CLASS is not set -++ -++# -++# Userspace I/O -++# -++# CONFIG_UIO is not set -++ -++# -++# File systems -++# -++CONFIG_EXT2_FS=y -++CONFIG_EXT2_FS_XATTR=y -++# CONFIG_EXT2_FS_POSIX_ACL is not set -++# CONFIG_EXT2_FS_SECURITY is not set -++# CONFIG_EXT2_FS_XIP is not set -++# CONFIG_EXT3_FS is not set -++# CONFIG_EXT4DEV_FS is not set -++CONFIG_FS_MBCACHE=y -++# CONFIG_REISERFS_FS is not set -++# CONFIG_JFS_FS is not set -++CONFIG_FS_POSIX_ACL=y -++# CONFIG_XFS_FS is not set -++# CONFIG_GFS2_FS is not set -++# CONFIG_OCFS2_FS is not set -++CONFIG_MINIX_FS=y -++# CONFIG_ROMFS_FS is not set -++CONFIG_INOTIFY=y -++CONFIG_INOTIFY_USER=y -++# CONFIG_QUOTA is not set -++CONFIG_DNOTIFY=y -++# CONFIG_AUTOFS_FS is not set -++# CONFIG_AUTOFS4_FS is not set -++# CONFIG_FUSE_FS is not set -++ -++# -++# CD-ROM/DVD Filesystems -++# -++# CONFIG_ISO9660_FS is not set -++# CONFIG_UDF_FS is not set -++ -++# -++# DOS/FAT/NT Filesystems -++# -++CONFIG_FAT_FS=y -++CONFIG_MSDOS_FS=y -++CONFIG_VFAT_FS=y -++CONFIG_FAT_DEFAULT_CODEPAGE=437 -++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -++# CONFIG_NTFS_FS is not set -++ -++# -++# Pseudo filesystems -++# -++CONFIG_PROC_FS=y -++CONFIG_PROC_KCORE=y -++CONFIG_PROC_SYSCTL=y -++CONFIG_SYSFS=y -++CONFIG_TMPFS=y -++# CONFIG_TMPFS_POSIX_ACL is not set -++# CONFIG_HUGETLB_PAGE is not set -++# CONFIG_CONFIGFS_FS is not set -++ -++# -++# Miscellaneous filesystems -++# -++# CONFIG_ADFS_FS is not set -++# CONFIG_AFFS_FS is not set -++# CONFIG_HFS_FS is not set -++# CONFIG_HFSPLUS_FS is not set -++# CONFIG_BEFS_FS is not set -++# CONFIG_BFS_FS is not set -++# CONFIG_EFS_FS is not set -++# CONFIG_JFFS2_FS is not set -++CONFIG_UBIFS_FS=m -++# CONFIG_UBIFS_FS_XATTR is not set -++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set -++CONFIG_UBIFS_FS_LZO=y -++CONFIG_UBIFS_FS_ZLIB=y -++# CONFIG_UBIFS_FS_DEBUG is not set -++# CONFIG_CRAMFS is not set -++# CONFIG_VXFS_FS is not set -++# CONFIG_HPFS_FS is not set -++# CONFIG_QNX4FS_FS is not set -++# CONFIG_SYSV_FS is not set -++# CONFIG_UFS_FS is not set -++CONFIG_NETWORK_FILESYSTEMS=y -++CONFIG_NFS_FS=y -++CONFIG_NFS_V3=y -++CONFIG_NFS_V3_ACL=y -++CONFIG_NFS_V4=y -++CONFIG_NFS_DIRECTIO=y -++# CONFIG_NFSD is not set -++CONFIG_ROOT_NFS=y -++CONFIG_LOCKD=y -++CONFIG_LOCKD_V4=y -++CONFIG_NFS_ACL_SUPPORT=y -++CONFIG_NFS_COMMON=y -++CONFIG_SUNRPC=y -++CONFIG_SUNRPC_GSS=y -++# CONFIG_SUNRPC_BIND34 is not set -++CONFIG_RPCSEC_GSS_KRB5=y -++# CONFIG_RPCSEC_GSS_SPKM3 is not set -++# CONFIG_SMB_FS is not set -++# CONFIG_CIFS is not set -++# CONFIG_NCP_FS is not set -++# CONFIG_CODA_FS is not set -++# CONFIG_AFS_FS is not set -++ -++# -++# Partition Types -++# -++CONFIG_PARTITION_ADVANCED=y -++# CONFIG_ACORN_PARTITION is not set -++# CONFIG_OSF_PARTITION is not set -++# CONFIG_AMIGA_PARTITION is not set -++# CONFIG_ATARI_PARTITION is not set -++# CONFIG_MAC_PARTITION is not set -++CONFIG_MSDOS_PARTITION=y -++# CONFIG_BSD_DISKLABEL is not set -++# CONFIG_MINIX_SUBPARTITION is not set -++# CONFIG_SOLARIS_X86_PARTITION is not set -++# CONFIG_UNIXWARE_DISKLABEL is not set -++# CONFIG_LDM_PARTITION is not set -++# CONFIG_SGI_PARTITION is not set -++# CONFIG_ULTRIX_PARTITION is not set -++# CONFIG_SUN_PARTITION is not set -++# CONFIG_KARMA_PARTITION is not set -++# CONFIG_EFI_PARTITION is not set -++# CONFIG_SYSV68_PARTITION is not set -++CONFIG_NLS=y -++CONFIG_NLS_DEFAULT="iso8859-1" -++CONFIG_NLS_CODEPAGE_437=y -++# CONFIG_NLS_CODEPAGE_737 is not set -++# CONFIG_NLS_CODEPAGE_775 is not set -++# CONFIG_NLS_CODEPAGE_850 is not set -++# CONFIG_NLS_CODEPAGE_852 is not set -++# CONFIG_NLS_CODEPAGE_855 is not set -++# CONFIG_NLS_CODEPAGE_857 is not set -++# CONFIG_NLS_CODEPAGE_860 is not set -++# CONFIG_NLS_CODEPAGE_861 is not set -++# CONFIG_NLS_CODEPAGE_862 is not set -++# CONFIG_NLS_CODEPAGE_863 is not set -++# CONFIG_NLS_CODEPAGE_864 is not set -++# CONFIG_NLS_CODEPAGE_865 is not set -++# CONFIG_NLS_CODEPAGE_866 is not set -++# CONFIG_NLS_CODEPAGE_869 is not set -++CONFIG_NLS_CODEPAGE_936=y -++# CONFIG_NLS_CODEPAGE_950 is not set -++# CONFIG_NLS_CODEPAGE_932 is not set -++# CONFIG_NLS_CODEPAGE_949 is not set -++# CONFIG_NLS_CODEPAGE_874 is not set -++# CONFIG_NLS_ISO8859_8 is not set -++# CONFIG_NLS_CODEPAGE_1250 is not set -++# CONFIG_NLS_CODEPAGE_1251 is not set -++CONFIG_NLS_ASCII=y -++CONFIG_NLS_ISO8859_1=y -++# CONFIG_NLS_ISO8859_2 is not set -++# CONFIG_NLS_ISO8859_3 is not set -++# CONFIG_NLS_ISO8859_4 is not set -++# CONFIG_NLS_ISO8859_5 is not set -++# CONFIG_NLS_ISO8859_6 is not set -++# CONFIG_NLS_ISO8859_7 is not set -++# CONFIG_NLS_ISO8859_9 is not set -++# CONFIG_NLS_ISO8859_13 is not set -++# CONFIG_NLS_ISO8859_14 is not set -++# CONFIG_NLS_ISO8859_15 is not set -++# CONFIG_NLS_KOI8_R is not set -++# CONFIG_NLS_KOI8_U is not set -++# CONFIG_NLS_UTF8 is not set -++# CONFIG_DLM is not set -++ -++# -++# Yaffs2 Filesystems -++# -++CONFIG_YAFFS_FS=y -++CONFIG_YAFFS_YAFFS1=y -++# CONFIG_YAFFS_DOES_ECC is not set -++CONFIG_YAFFS_YAFFS2=y -++CONFIG_YAFFS_AUTO_YAFFS2=y -++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set -++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set -++CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK=y -++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y -++CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10 -++CONFIG_INSTRUMENTATION=y -++# CONFIG_PROFILING is not set -++# CONFIG_MARKERS is not set -++ -++# -++# Kernel hacking -++# -++CONFIG_TRACE_IRQFLAGS_SUPPORT=y -++# CONFIG_PRINTK_TIME is not set -++CONFIG_ENABLE_WARN_DEPRECATED=y -++CONFIG_ENABLE_MUST_CHECK=y -++CONFIG_MAGIC_SYSRQ=y -++# CONFIG_UNUSED_SYMBOLS is not set -++CONFIG_DEBUG_FS=y -++# CONFIG_HEADERS_CHECK is not set -++# CONFIG_DEBUG_KERNEL is not set -++# CONFIG_SAMPLES is not set -++CONFIG_CMDLINE="" -++ -++# -++# Security options -++# -++# CONFIG_KEYS is not set -++# CONFIG_SECURITY is not set -++# CONFIG_SECURITY_FILE_CAPABILITIES is not set -++CONFIG_CRYPTO=y -++CONFIG_CRYPTO_ALGAPI=y -++CONFIG_CRYPTO_BLKCIPHER=y -++CONFIG_CRYPTO_MANAGER=y -++# CONFIG_CRYPTO_HMAC is not set -++# CONFIG_CRYPTO_XCBC is not set -++# CONFIG_CRYPTO_NULL is not set -++# CONFIG_CRYPTO_MD4 is not set -++CONFIG_CRYPTO_MD5=y -++# CONFIG_CRYPTO_SHA1 is not set -++# CONFIG_CRYPTO_SHA256 is not set -++# CONFIG_CRYPTO_SHA512 is not set -++# CONFIG_CRYPTO_WP512 is not set -++# CONFIG_CRYPTO_TGR192 is not set -++# CONFIG_CRYPTO_GF128MUL is not set -++# CONFIG_CRYPTO_ECB is not set -++CONFIG_CRYPTO_CBC=y -++# CONFIG_CRYPTO_PCBC is not set -++# CONFIG_CRYPTO_LRW is not set -++# CONFIG_CRYPTO_XTS is not set -++# CONFIG_CRYPTO_CRYPTD is not set -++CONFIG_CRYPTO_DES=y -++# CONFIG_CRYPTO_FCRYPT is not set -++# CONFIG_CRYPTO_BLOWFISH is not set -++# CONFIG_CRYPTO_TWOFISH is not set -++# CONFIG_CRYPTO_SERPENT is not set -++# CONFIG_CRYPTO_AES is not set -++# CONFIG_CRYPTO_CAST5 is not set -++# CONFIG_CRYPTO_CAST6 is not set -++# CONFIG_CRYPTO_TEA is not set -++# CONFIG_CRYPTO_ARC4 is not set -++# CONFIG_CRYPTO_KHAZAD is not set -++# CONFIG_CRYPTO_ANUBIS is not set -++# CONFIG_CRYPTO_SEED is not set -++CONFIG_CRYPTO_DEFLATE=m -++# CONFIG_CRYPTO_MICHAEL_MIC is not set -++# CONFIG_CRYPTO_CRC32C is not set -++# CONFIG_CRYPTO_CAMELLIA is not set -++# CONFIG_CRYPTO_TEST is not set -++# CONFIG_CRYPTO_AUTHENC is not set -++CONFIG_CRYPTO_LZO=m -++CONFIG_CRYPTO_HW=y -++ -++# -++# Library routines -++# -++CONFIG_BITREVERSE=y -++# CONFIG_CRC_CCITT is not set -++CONFIG_CRC16=m -++# CONFIG_CRC_ITU_T is not set -++CONFIG_CRC32=y -++# CONFIG_CRC7 is not set -++# CONFIG_LIBCRC32C is not set -++CONFIG_ZLIB_INFLATE=m -++CONFIG_ZLIB_DEFLATE=m -++CONFIG_LZO_COMPRESS=m -++CONFIG_LZO_DECOMPRESS=m -++CONFIG_PLIST=y -++CONFIG_HAS_IOMEM=y -++CONFIG_HAS_IOPORT=y -++CONFIG_HAS_DMA=y -+diff -urN linux-2.6.24.7.old/arch/mips/jz4730/Makefile linux-2.6.24.7/arch/mips/jz4730/Makefile -+--- linux-2.6.24.7.old/arch/mips/jz4730/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4730/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,22 @@ -++# -++# Makefile for the Ingenic JZ4730. -++# -++ -++# Object file lists. -++ -++obj-y += prom.o irq.o time.o reset.o setup.o dma.o \ -++ platform.o i2c.o -++ -++obj-$(CONFIG_PROC_FS) += proc.o -++ -++# board specific support -++ -++obj-$(CONFIG_JZ4730_PMP) += board-pmp.o -++ -++# CPU Frequency scaling support -++ -++obj-$(CONFIG_CPU_FREQ_JZ) +=cpufreq.o -++ -++# PM support -++ -++obj-$(CONFIG_PM_LEGACY) +=pm.o sleep.o -+diff -urN linux-2.6.24.7.old/arch/mips/jz4730/board-pmp.c linux-2.6.24.7/arch/mips/jz4730/board-pmp.c -+--- linux-2.6.24.7.old/arch/mips/jz4730/board-pmp.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4730/board-pmp.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,109 @@ -++/* -++ * linux/arch/mips/jz4730/board-pmp.c -++ * -++ * JZ4730 PMP board setup routines. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include -++ -++extern void (*jz_timer_callback)(void); -++ -++static void dancing(void) -++{ -++ static unsigned int count = 0; -++ -++ count ++; -++ count &= 1; -++ if (count) -++ __gpio_set_pin(GPIO_LED_EN); -++ else -++ __gpio_clear_pin(GPIO_LED_EN); -++} -++ -++static void pmp_timer_ack(void) -++{ -++ static unsigned int count = 0; -++ count ++; -++ if (count % 100 == 0) { -++ count = 0; -++ dancing(); -++ } -++} -++ -++static void __init board_cpm_setup(void) -++{ -++ __cpm_start_all(); -++} -++ -++static void __init board_gpio_setup(void) -++{ -++ /* -++ * Most of the gpios have been setup in the bootloader. -++ */ -++ -++ __harb_usb0_uhc(); -++ __gpio_as_dma(); -++ __gpio_as_eth(); -++ __gpio_as_usb(); -++ __gpio_as_lcd_master(); -++#if defined(CONFIG_I2S_AK4642EN) -++ __gpio_as_scc1(); -++#endif -++#if defined(CONFIG_I2S_TSC2301) || defined(CONFIG_I2S_TLC320AIC23) -++ __gpio_as_ssi(); -++#endif -++ //__gpio_as_ac97(); -++#if defined(CONFIG_I2S_TSC2301) || defined(CONFIG_I2S_TLC320AIC23) || defined(CONFIG_I2S_CS42L51) -++ __gpio_as_i2s_slave(); -++#endif -++ __gpio_as_cim(); -++ __gpio_as_msc(); -++ -++ __gpio_as_output(GPIO_LED_EN); -++ __gpio_set_pin(GPIO_LED_EN); -++ -++ __gpio_as_output(GPIO_DISP_OFF_N); -++ __gpio_set_pin(GPIO_DISP_OFF_N); -++ __gpio_as_output(GPIO_PWM0); -++ __gpio_set_pin(GPIO_PWM0); -++ -++ __gpio_as_input(GPIO_RTC_IRQ); -++ __gpio_as_output(GPIO_USB_CLK_EN); -++ __gpio_set_pin(GPIO_USB_CLK_EN); -++ -++ __gpio_as_input(GPIO_CHARG_STAT); -++ __gpio_disable_pull(GPIO_CHARG_STAT); -++ -++ __gpio_as_input(GPIO_UDC_HOTPLUG); -++ __gpio_disable_pull(GPIO_UDC_HOTPLUG); -++ __gpio_disable_pull(54); /* fixed ic bug, the pull of gpio pin 86 is as pin 54 */ -++} -++ -++void __init jz_board_setup(void) -++{ -++ printk("JZ4730 PMP board setup\n"); -++ -++ board_cpm_setup(); -++ board_gpio_setup(); -++ -++ jz_timer_callback = pmp_timer_ack; -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4730/cpufreq.c linux-2.6.24.7/arch/mips/jz4730/cpufreq.c -+--- linux-2.6.24.7.old/arch/mips/jz4730/cpufreq.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4730/cpufreq.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,596 @@ -++ -++/* -++ * linux/arch/mips/jz4730/cpufreq.c -++ * -++ * cpufreq driver for JZ4730 -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++ -++#include -++ -++#include -++#include -++ -++#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \ -++ "cpufreq-jz4730", msg) -++ -++#undef CHANGE_PLL -++ -++#define PLL_UNCHANGED 0 -++#define PLL_GOES_UP 1 -++#define PLL_GOES_DOWN 2 -++ -++#define PLL_WAIT_500NS (500*(__cpm_get_iclk()/1000000000)) -++ -++/* Saved the boot-time parameters */ -++static struct { -++ /* SDRAM parameters */ -++ unsigned int mclk; /* memory clock, KHz */ -++ unsigned int tras; /* RAS pulse width, cycles of mclk */ -++ unsigned int rcd; /* RAS to CAS Delay, cycles of mclk */ -++ unsigned int tpc; /* RAS Precharge time, cycles of mclk */ -++ unsigned int trwl; /* Write Precharge Time, cycles of mclk */ -++ unsigned int trc; /* RAS Cycle Time, cycles of mclk */ -++ unsigned int rtcor; /* Refresh Time Constant */ -++ unsigned int sdram_initialized; -++ -++ /* LCD parameters */ -++ unsigned int lcd_clk; /* LCD clock, Hz */ -++ unsigned int lcdpix_clk; /* LCD Pixel clock, Hz */ -++ unsigned int lcd_clks_initialized; -++} boot_config; -++ -++struct jz4730_freq_percpu_info { -++ struct cpufreq_frequency_table table[7]; -++}; -++ -++static struct jz4730_freq_percpu_info jz4730_freq_table; -++ -++/* -++ * This contains the registers value for an operating point. -++ * If only part of a register needs to change then there is -++ * a mask value for that register. -++ * When going to a new operating point the current register -++ * value is ANDed with the ~mask and ORed with the new value. -++ */ -++struct dpm_regs { -++ u32 cfcr; /* Clock Freq Control Register */ -++ u32 cfcr_mask; /* Clock Freq Control Register mask */ -++ u32 cfcr2; /* Clock Freq Control Register 2 */ -++ u32 cfcr2_mask; /* Clock Freq Control Register 2 mask */ -++ u32 plcr1; /* PLL1 Control Register */ -++ u32 plcr1_mask; /* PLL1 Control Register mask */ -++ u32 pll_up_flag; /* New PLL freq is higher than current or not */ -++}; -++ -++extern jz_clocks_t jz_clocks; -++ -++static void jz_update_clocks(void) -++{ -++ /* Next clocks must be updated if we have changed -++ * the PLL or divisors. -++ */ -++ jz_clocks.iclk = __cpm_get_iclk(); -++ jz_clocks.sclk = __cpm_get_sclk(); -++ jz_clocks.mclk = __cpm_get_mclk(); -++ jz_clocks.pclk = __cpm_get_pclk(); -++ jz_clocks.lcdclk = __cpm_get_lcdclk(); -++ jz_clocks.pixclk = __cpm_get_pixclk(); -++} -++ -++static void -++jz_init_boot_config(void) -++{ -++ if (!boot_config.lcd_clks_initialized) { -++ /* the first time to scale pll */ -++ boot_config.lcd_clk = __cpm_get_lcdclk(); -++ boot_config.lcdpix_clk = __cpm_get_pixclk(); -++ boot_config.lcd_clks_initialized = 1; -++ } -++ -++ if (!boot_config.sdram_initialized) { -++ /* the first time to scale frequencies */ -++ unsigned int dmcr, rtcor; -++ unsigned int tras, rcd, tpc, trwl, trc; -++ -++ dmcr = REG_EMC_DMCR; -++ rtcor = REG_EMC_RTCOR; -++ -++ tras = (dmcr >> 13) & 0x7; -++ rcd = (dmcr >> 11) & 0x3; -++ tpc = (dmcr >> 8) & 0x7; -++ trwl = (dmcr >> 5) & 0x3; -++ trc = (dmcr >> 2) & 0x7; -++ -++ boot_config.mclk = __cpm_get_mclk() / 1000; -++ boot_config.tras = tras + 4; -++ boot_config.rcd = rcd + 1; -++ boot_config.tpc = tpc + 1; -++ boot_config.trwl = trwl + 1; -++ boot_config.trc = trc * 2 + 1; -++ boot_config.rtcor = rtcor; -++ -++ boot_config.sdram_initialized = 1; -++ } -++} -++ -++static void jz_update_dram_rtcor(unsigned int new_mclk) -++{ -++ unsigned int rtcor; -++ -++ new_mclk /= 1000; -++ rtcor = boot_config.rtcor * new_mclk / boot_config.mclk; -++ rtcor--; -++ -++ if (rtcor < 1) rtcor = 1; -++ if (rtcor > 255) rtcor = 255; -++ -++ REG_EMC_RTCOR = rtcor; -++ REG_EMC_RTCNT = rtcor; -++} -++ -++static void jz_update_dram_dmcr(unsigned int new_mclk) -++{ -++ unsigned int dmcr; -++ unsigned int tras, rcd, tpc, trwl, trc; -++ unsigned int valid_time, new_time; /* ns */ -++ -++ new_mclk /= 1000; -++ tras = boot_config.tras * new_mclk / boot_config.mclk; -++ rcd = boot_config.rcd * new_mclk / boot_config.mclk; -++ tpc = boot_config.tpc * new_mclk / boot_config.mclk; -++ trwl = boot_config.trwl * new_mclk / boot_config.mclk; -++ trc = boot_config.trc * new_mclk / boot_config.mclk; -++ -++ /* Validation checking */ -++ valid_time = (boot_config.tras * 1000000) / boot_config.mclk; -++ new_time = (tras * 1000000) / new_mclk; -++ if (new_time < valid_time) tras += 1; -++ -++ valid_time = (boot_config.rcd * 1000000) / boot_config.mclk; -++ new_time = (rcd * 1000000) / new_mclk; -++ if (new_time < valid_time) rcd += 1; -++ -++ valid_time = (boot_config.tpc * 1000000) / boot_config.mclk; -++ new_time = (tpc * 1000000) / new_mclk; -++ if (new_time < valid_time) tpc += 1; -++ -++ valid_time = (boot_config.trwl * 1000000) / boot_config.mclk; -++ new_time = (trwl * 1000000) / new_mclk; -++ if (new_time < valid_time) trwl += 1; -++ -++ valid_time = (boot_config.trc * 1000000) / boot_config.mclk; -++ new_time = (trc * 1000000) / new_mclk; -++ if (new_time < valid_time) trc += 2; -++ -++ tras = (tras < 4) ? 4: tras; -++ tras = (tras > 11) ? 11: tras; -++ tras -= 4; -++ -++ rcd = (rcd < 1) ? 1: rcd; -++ rcd = (rcd > 4) ? 4: rcd; -++ rcd -= 1; -++ -++ tpc = (tpc < 1) ? 1: tpc; -++ tpc = (tpc > 8) ? 8: tpc; -++ tpc -= 1; -++ -++ trwl = (trwl < 1) ? 1: trwl; -++ trwl = (trwl > 4) ? 4: trwl; -++ trwl -= 1; -++ -++ trc = (trc < 1) ? 1: trc; -++ trc = (trc > 15) ? 15: trc; -++ trc /= 2; -++ -++ dmcr = REG_EMC_DMCR; -++ -++ dmcr &= ~(EMC_DMCR_TRAS_MASK | EMC_DMCR_RCD_MASK | EMC_DMCR_TPC_MASK | EMC_DMCR_TRWL_MASK | EMC_DMCR_TRC_MASK); -++ dmcr |= ((tras << EMC_DMCR_TRAS_BIT) | (rcd << EMC_DMCR_RCD_BIT) | (tpc << EMC_DMCR_TPC_BIT) | (trwl << EMC_DMCR_TRWL_BIT) | (trc << EMC_DMCR_TRC_BIT)); -++ -++ REG_EMC_DMCR = dmcr; -++} -++ -++static void jz_update_dram_prev(unsigned int cur_mclk, unsigned int new_mclk) -++{ -++ /* No risk, no fun: run with interrupts on! */ -++ if (new_mclk > cur_mclk) { -++ /* We're going FASTER, so first update TRAS, RCD, TPC, TRWL -++ * and TRC of DMCR before changing the frequency. -++ */ -++ jz_update_dram_dmcr(new_mclk); -++ } else { -++ /* We're going SLOWER: first update RTCOR value -++ * before changing the frequency. -++ */ -++ jz_update_dram_rtcor(new_mclk); -++ } -++} -++ -++static void jz_update_dram_post(unsigned int cur_mclk, unsigned int new_mclk) -++{ -++ /* No risk, no fun: run with interrupts on! */ -++ if (new_mclk > cur_mclk) { -++ /* We're going FASTER, so update RTCOR -++ * after changing the frequency -++ */ -++ jz_update_dram_rtcor(new_mclk); -++ } else { -++ /* We're going SLOWER: so update TRAS, RCD, TPC, TRWL -++ * and TRC of DMCR after changing the frequency. -++ */ -++ jz_update_dram_dmcr(new_mclk); -++ } -++} -++ -++static void jz_scale_divisors(struct dpm_regs *regs) -++{ -++ unsigned int cfcr; -++ unsigned int cur_mclk, new_mclk; -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ unsigned int tmp = 0, wait = PLL_WAIT_500NS; -++ -++ cfcr = REG_CPM_CFCR; -++ cfcr &= ~((unsigned long)regs->cfcr_mask); -++ cfcr |= regs->cfcr; -++ cfcr |= CPM_CFCR_UPE; /* update immediately */ -++ -++ cur_mclk = __cpm_get_mclk(); -++ new_mclk = __cpm_get_pllout() / div[(cfcr & CPM_CFCR_MFR_MASK) >> CPM_CFCR_MFR_BIT]; -++ -++ /* Update some DRAM parameters before changing frequency */ -++ jz_update_dram_prev(cur_mclk, new_mclk); -++ -++ /* update register to change the clocks. -++ * align this code to a cache line. -++ */ -++ __asm__ __volatile__( -++ ".set noreorder\n\t" -++ ".align 5\n" -++ "sw %1,0(%0)\n\t" -++ "li %3,0\n\t" -++ "1:\n\t" -++ "bne %3,%2,1b\n\t" -++ "addi %3, 1\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ ".set reorder\n\t" -++ : -++ : "r" (CPM_CFCR), "r" (cfcr), "r" (wait), "r" (tmp)); -++ -++ /* Update some other DRAM parameters after changing frequency */ -++ jz_update_dram_post(cur_mclk, new_mclk); -++} -++ -++#ifdef CHANGE_PLL -++/* Maintain the LCD clock and pixel clock */ -++static void jz_scale_lcd_divisors(struct dpm_regs *regs) -++{ -++ unsigned int new_pll, new_lcd_div, new_lcdpix_div; -++ unsigned int cfcr; -++ unsigned int tmp = 0, wait = PLL_WAIT_500NS; -++ -++ if (!boot_config.lcd_clks_initialized) return; -++ -++ new_pll = __cpm_get_pllout(); -++ new_lcd_div = new_pll / boot_config.lcd_clk; -++ new_lcdpix_div = new_pll / boot_config.lcdpix_clk; -++ -++ if (new_lcd_div < 1) -++ new_lcd_div = 1; -++ if (new_lcd_div > 16) -++ new_lcd_div = 16; -++ -++ if (new_lcdpix_div < 1) -++ new_lcdpix_div = 1; -++ if (new_lcdpix_div > 512) -++ new_lcdpix_div = 512; -++ -++ REG_CPM_CFCR2 = new_lcdpix_div - 1; -++ -++ cfcr = REG_CPM_CFCR; -++ cfcr &= ~CPM_CFCR_LFR_MASK; -++ cfcr |= ((new_lcd_div - 1) << CPM_CFCR_LFR_BIT); -++ cfcr |= CPM_CFCR_UPE; /* update immediately */ -++ -++ /* update register to change the clocks. -++ * align this code to a cache line. -++ */ -++ __asm__ __volatile__( -++ ".set noreorder\n\t" -++ ".align 5\n" -++ "sw %1,0(%0)\n\t" -++ "li %3,0\n\t" -++ "1:\n\t" -++ "bne %3,%2,1b\n\t" -++ "addi %3, 1\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ ".set reorder\n\t" -++ : -++ : "r" (CPM_CFCR), "r" (cfcr), "r" (wait), "r" (tmp)); -++} -++ -++static void jz_scale_pll(struct dpm_regs *regs) -++{ -++ unsigned int plcr1; -++ unsigned int cur_mclk, new_mclk, new_pll; -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ int od[] = {1, 2, 2, 4}; -++ -++ plcr1 = REG_CPM_PLCR1; -++ plcr1 &= ~(regs->plcr1_mask | CPM_PLCR1_PLL1S | CPM_PLCR1_PLL1EN | CPM_PLCR1_PLL1ST_MASK); -++ regs->plcr1 &= ~CPM_PLCR1_PLL1EN; -++ plcr1 |= (regs->plcr1 | 0xff); -++ -++ /* Update some DRAM parameters before changing frequency */ -++ new_pll = JZ_EXTAL * ((plcr1>>23)+2) / ((((plcr1>>18)&0x1f)+2) * od[(plcr1>>16)&0x03]); -++ cur_mclk = __cpm_get_mclk(); -++ new_mclk = new_pll / div[(REG_CPM_CFCR>>16) & 0xf]; -++ -++ /* -++ * Update some SDRAM parameters -++ */ -++ jz_update_dram_prev(cur_mclk, new_mclk); -++ -++ /* -++ * Update PLL, align code to cache line. -++ */ -++ plcr1 |= CPM_PLCR1_PLL1EN; -++ __asm__ __volatile__( -++ ".set noreorder\n\t" -++ ".align 5\n" -++ "sw %1,0(%0)\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ ".set reorder\n\t" -++ : -++ : "r" (CPM_PLCR1), "r" (plcr1)); -++ -++ /* Update some other DRAM parameters after changing frequency */ -++ jz_update_dram_post(cur_mclk, new_mclk); -++} -++#endif -++ -++static void jz4730_transition(struct dpm_regs *regs) -++{ -++ /* -++ * Get and save some boot-time conditions. -++ */ -++ jz_init_boot_config(); -++ -++#ifdef CHANGE_PLL -++ /* -++ * Disable LCD before scaling pll. -++ * LCD and LCD pixel clocks should not be changed even if the PLL -++ * output frequency has been changed. -++ */ -++ REG_LCD_CTRL &= ~LCD_CTRL_ENA; -++#endif -++ /* -++ * Stop module clocks before scaling PLL -++ */ -++ __cpm_stop_eth(); -++ __cpm_stop_aic_pclk(); -++ __cpm_stop_aic_bitclk(); -++ -++ /* ... add more as necessary */ -++ -++ if (regs->pll_up_flag == PLL_GOES_UP) { -++ /* the pll frequency is going up, so change dividors first */ -++ jz_scale_divisors(regs); -++#ifdef CHANGE_PLL -++ jz_scale_pll(regs); -++#endif -++ } -++ else if (regs->pll_up_flag == PLL_GOES_DOWN) { -++ /* the pll frequency is going down, so change pll first */ -++#ifdef CHANGE_PLL -++ jz_scale_pll(regs); -++#endif -++ jz_scale_divisors(regs); -++ } -++ else { -++ /* the pll frequency is unchanged, so change divisors only */ -++ jz_scale_divisors(regs); -++ } -++ -++ /* -++ * Restart module clocks before scaling PLL -++ */ -++ __cpm_start_eth(); -++ __cpm_start_aic_pclk(); -++ __cpm_start_aic_bitclk(); -++ -++ /* ... add more as necessary */ -++ -++#ifdef CHANGE_PLL -++ /* Scale the LCD divisors after scaling pll */ -++ if (regs->pll_up_flag != PLL_UNCHANGED) { -++ jz_scale_lcd_divisors(regs); -++ } -++ -++ /* Enable LCD controller */ -++ REG_LCD_CTRL &= ~LCD_CTRL_DIS; -++ REG_LCD_CTRL |= LCD_CTRL_ENA; -++#endif -++ -++ /* Update system clocks */ -++ jz_update_clocks(); -++} -++ -++extern unsigned int idle_times; -++static unsigned int jz4730_freq_get(unsigned int cpu) -++{ -++ return (__cpm_get_iclk() / 1000); -++} -++ -++static unsigned int index_to_divisor(unsigned int index, struct dpm_regs *regs) -++{ -++ int n2FR[33] = { -++ 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, -++ 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, -++ 9 -++ }; -++ int div[4] = {1, 2, 2, 2}; /* divisors of I:S:P:M */ -++ unsigned int div_of_cclk, new_freq, i; -++ -++ regs->pll_up_flag = PLL_UNCHANGED; -++ regs->cfcr_mask = CPM_CFCR_IFR_MASK | CPM_CFCR_SFR_MASK | CPM_CFCR_PFR_MASK | CPM_CFCR_MFR_MASK; -++ -++ new_freq = jz4730_freq_table.table[index].frequency; -++ -++ do { -++ div_of_cclk = __cpm_get_pllout() / (1000 * new_freq); -++ } while (div_of_cclk==0); -++ -++ if(div_of_cclk == 1 || div_of_cclk == 2 || div_of_cclk == 4) { -++ for(i = 1; i<4; i++) { -++ div[i] = 3; -++ } -++ } else { -++ for(i = 1; i<4; i++) { -++ div[i] = 2; -++ } -++ } -++ -++ for(i = 0; i<4; i++) { -++ div[i] *= div_of_cclk; -++ } -++ -++ dprintk("divisors of I:S:P:M = %d:%d:%d:%d\n", div[0], div[1], div[2], div[3]); -++ -++ regs->cfcr = (n2FR[div[0]] << CPM_CFCR_IFR_BIT) | -++ (n2FR[div[1]] << CPM_CFCR_SFR_BIT) | -++ (n2FR[div[2]] << CPM_CFCR_PFR_BIT) | -++ (n2FR[div[3]] << CPM_CFCR_MFR_BIT); -++ -++ return div_of_cclk; -++} -++ -++static void jz4730_set_cpu_divider_index(unsigned int cpu, unsigned int index) -++{ -++ unsigned long divisor, old_divisor; -++ struct cpufreq_freqs freqs; -++ struct dpm_regs regs; -++ -++ old_divisor = __cpm_get_pllout() / __cpm_get_iclk(); -++ divisor = index_to_divisor(index, ®s); -++ -++ freqs.old = __cpm_get_iclk() / 1000; -++ freqs.new = __cpm_get_pllout() / (1000 * divisor); -++ freqs.cpu = cpu; -++ -++ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); -++ -++ if (old_divisor != divisor) -++ jz4730_transition(®s); -++ -++ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); -++} -++ -++static int jz4730_freq_target(struct cpufreq_policy *policy, -++ unsigned int target_freq, -++ unsigned int relation) -++{ -++ unsigned int new_index = 0; -++ -++ if (cpufreq_frequency_table_target(policy, -++ &jz4730_freq_table.table[0], -++ target_freq, relation, &new_index)) -++ return -EINVAL; -++ -++ jz4730_set_cpu_divider_index(policy->cpu, new_index); -++ -++ dprintk("new frequency is %d KHz (REG_CPM_CFCR:0x%x)\n", __cpm_get_iclk() / 1000, REG_CPM_CFCR); -++ -++ return 0; -++} -++ -++static int jz4730_freq_verify(struct cpufreq_policy *policy) -++{ -++ return cpufreq_frequency_table_verify(policy, -++ &jz4730_freq_table.table[0]); -++} -++ -++static int __init jz4730_cpufreq_driver_init(struct cpufreq_policy *policy) -++{ -++ -++ struct cpufreq_frequency_table *table = &jz4730_freq_table.table[0]; -++ unsigned int MAX_FREQ; -++ -++ dprintk(KERN_INFO "Jz4730 cpufreq driver\n"); -++ -++ if (policy->cpu != 0) -++ return -EINVAL; -++ -++ policy->cur = MAX_FREQ = __cpm_get_iclk() / 1000; /* in kHz. Current and max frequency is determined by u-boot */ -++ policy->governor = CPUFREQ_DEFAULT_GOVERNOR; -++ -++ policy->cpuinfo.min_freq = MAX_FREQ/8; -++ policy->cpuinfo.max_freq = MAX_FREQ; -++ policy->cpuinfo.transition_latency = 100000; /* in 10^(-9) s = nanoseconds */ -++ -++ table[0].index = 0; -++ table[0].frequency = MAX_FREQ/8; -++ table[1].index = 1; -++ table[1].frequency = MAX_FREQ/6; -++ table[2].index = 2; -++ table[2].frequency = MAX_FREQ/4; -++ table[3].index = 3; -++ table[3].frequency = MAX_FREQ/3; -++ table[4].index = 4; -++ table[4].frequency = MAX_FREQ/2; -++ table[5].index = 5; -++ table[5].frequency = MAX_FREQ; -++ table[6].index = 6; -++ table[6].frequency = CPUFREQ_TABLE_END; -++ -++ return cpufreq_frequency_table_cpuinfo(policy, table); -++} -++ -++static struct cpufreq_driver cpufreq_jz4730_driver = { -++// .flags = CPUFREQ_STICKY, -++ .init = jz4730_cpufreq_driver_init, -++ .verify = jz4730_freq_verify, -++ .target = jz4730_freq_target, -++ .get = jz4730_freq_get, -++ .name = "jz4730", -++}; -++ -++static int __init jz4730_cpufreq_init(void) -++{ -++ return cpufreq_register_driver(&cpufreq_jz4730_driver); -++} -++ -++static void __exit jz4730_cpufreq_exit(void) -++{ -++ cpufreq_unregister_driver(&cpufreq_jz4730_driver); -++} -++ -++module_init(jz4730_cpufreq_init); -++module_exit(jz4730_cpufreq_exit); -++ -++MODULE_AUTHOR("Regen "); -++MODULE_DESCRIPTION("cpufreq driver for Jz4730"); -++MODULE_LICENSE("GPL"); -++ -+diff -urN linux-2.6.24.7.old/arch/mips/jz4730/dma.c linux-2.6.24.7/arch/mips/jz4730/dma.c -+--- linux-2.6.24.7.old/arch/mips/jz4730/dma.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4730/dma.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,509 @@ -++/* -++ * linux/arch/mips/jz4730/dma.c -++ * -++ * JZ4730 DMA PC-like APIs. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++ -++/* -++ * A note on resource allocation: -++ * -++ * All drivers needing DMA channels, should allocate and release them -++ * through the public routines `jz_request_dma()' and `jz_free_dma()'. -++ * -++ * In order to avoid problems, all processes should allocate resources in -++ * the same sequence and release them in the reverse order. -++ * -++ * So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ. -++ * When releasing them, first release the IRQ, then release the DMA. The -++ * main reason for this order is that, if you are requesting the DMA buffer -++ * done interrupt, you won't know the irq number until the DMA channel is -++ * returned from jz_request_dma(). -++ */ -++ -++struct jz_dma_chan jz_dma_table[NUM_DMA] = { -++ {dev_id:-1,}, -++ {dev_id:-1,}, -++ {dev_id:-1,}, -++ {dev_id:-1,}, -++ {dev_id:-1,}, -++ {dev_id:-1,}, -++}; -++ -++ -++// Device FIFO addresses and default DMA modes -++static const struct { -++ unsigned int fifo_addr; -++ unsigned int dma_mode; -++ unsigned int dma_source; -++} dma_dev_table[NUM_DMA_DEV] = { -++ {CPHYSADDR(UART0_BASE), DMA_8bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_UART0OUT}, -++ {CPHYSADDR(UART0_BASE), DMA_8bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_UART0IN}, -++ {CPHYSADDR(UART1_BASE), DMA_8bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_UART1OUT}, -++ {CPHYSADDR(UART1_BASE), DMA_8bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_UART1IN}, -++ {CPHYSADDR(UART2_BASE), DMA_8bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_UART2OUT}, -++ {CPHYSADDR(UART2_BASE), DMA_8bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_UART2IN}, -++ {CPHYSADDR(UART3_BASE), DMA_8bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_UART3OUT}, -++ {CPHYSADDR(UART3_BASE), DMA_8bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_UART3IN}, -++ {CPHYSADDR(SSI_DR), DMA_32bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_SSIOUT}, -++ {CPHYSADDR(SSI_DR), DMA_32bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_SSIIN}, -++ {CPHYSADDR(MSC_TXFIFO), DMA_32bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_MSCOUT}, -++ {CPHYSADDR(MSC_RXFIFO), DMA_32bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_MSCIN}, -++ {CPHYSADDR(AIC_DR), DMA_32bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_AICOUT}, -++ {CPHYSADDR(AIC_DR), DMA_32bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_AICIN}, -++ {0, DMA_AUTOINIT, 0}, -++}; -++ -++ -++int jz_dma_read_proc(char *buf, char **start, off_t fpos, -++ int length, int *eof, void *data) -++{ -++ int i, len = 0; -++ struct jz_dma_chan *chan; -++ -++ for (i = 0; i < NUM_DMA; i++) { -++ if ((chan = get_dma_chan(i)) != NULL) { -++ len += sprintf(buf + len, "%2d: %s\n", -++ i, chan->dev_str); -++ } -++ } -++ -++ if (fpos >= len) { -++ *start = buf; -++ *eof = 1; -++ return 0; -++ } -++ *start = buf + fpos; -++ if ((len -= fpos) > length) -++ return length; -++ *eof = 1; -++ return len; -++} -++ -++ -++void dump_jz_dma_channel(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan; -++ -++ if (dmanr > NUM_DMA) -++ return; -++ chan = &jz_dma_table[dmanr]; -++ -++ printk(KERN_INFO "DMA%d Register Dump:\n", dmanr); -++ printk(KERN_INFO " DMACR= 0x%08x\n", REG_DMAC_DMACR); -++ printk(KERN_INFO " DSAR = 0x%08x\n", REG_DMAC_DSAR(dmanr)); -++ printk(KERN_INFO " DDAR = 0x%08x\n", REG_DMAC_DDAR(dmanr)); -++ printk(KERN_INFO " DTCR = 0x%08x\n", REG_DMAC_DTCR(dmanr)); -++ printk(KERN_INFO " DRSR = 0x%08x\n", REG_DMAC_DRSR(dmanr)); -++ printk(KERN_INFO " DCCSR = 0x%08x\n", REG_DMAC_DCCSR(dmanr)); -++} -++ -++ -++/** -++ * jz_request_dma - dynamically allcate an idle DMA channel to return -++ * @dev_id: the specified dma device id or DMA_ID_RAW_REQ -++ * @dev_str: the specified dma device string name -++ * @irqhandler: the irq handler, or NULL -++ * @irqflags: the irq handler flags -++ * @irq_dev_id: the irq handler device id for shared irq -++ * -++ * Finds a free channel, and binds the requested device to it. -++ * Returns the allocated channel number, or negative on error. -++ * Requests the DMA done IRQ if irqhandler != NULL. -++ * -++*/ -++int jz_request_dma(int dev_id, const char *dev_str, -++ irqreturn_t (*irqhandler)(int, void *), -++ unsigned long irqflags, -++ void *irq_dev_id) -++{ -++ struct jz_dma_chan *chan; -++ int i, ret; -++ -++ if (dev_id < 0 || dev_id >= NUM_DMA_DEV) -++ return -EINVAL; -++ -++ for (i = 0; i < NUM_DMA; i++) { -++ if (jz_dma_table[i].dev_id < 0) -++ break; -++ } -++ if (i == NUM_DMA) -++ return -ENODEV; -++ -++ chan = &jz_dma_table[i]; -++ -++ if (irqhandler) { -++ chan->irq = IRQ_DMA_0 + i; // see intc.h -++ chan->irq_dev = irq_dev_id; -++ if ((ret = request_irq(chan->irq, irqhandler, irqflags, -++ dev_str, chan->irq_dev))) { -++ chan->irq = 0; -++ chan->irq_dev = NULL; -++ return ret; -++ } -++ } else { -++ chan->irq = 0; -++ chan->irq_dev = NULL; -++ } -++ -++ // fill it in -++ chan->io = i; -++ chan->dev_id = dev_id; -++ chan->dev_str = dev_str; -++ chan->fifo_addr = dma_dev_table[dev_id].fifo_addr; -++ chan->mode = dma_dev_table[dev_id].dma_mode; -++ chan->source = dma_dev_table[dev_id].dma_source; -++ -++ return i; -++} -++ -++void jz_free_dma(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) { -++ printk("Trying to free DMA%d\n", dmanr); -++ return; -++ } -++ -++ disable_dma(dmanr); -++ if (chan->irq) -++ free_irq(chan->irq, chan->irq_dev); -++ -++ chan->irq = 0; -++ chan->irq_dev = NULL; -++ chan->dev_id = -1; -++} -++ -++void jz_set_dma_dest_width(int dmanr, int nbit) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ chan->mode &= ~DMAC_DCCSR_DWDH_MASK; -++ switch (nbit) { -++ case 8: -++ chan->mode |= DMAC_DCCSR_DWDH_8; -++ break; -++ case 16: -++ chan->mode |= DMAC_DCCSR_DWDH_16; -++ break; -++ case 32: -++ chan->mode |= DMAC_DCCSR_DWDH_32; -++ break; -++ } -++} -++ -++void jz_set_dma_src_width(int dmanr, int nbit) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ chan->mode &= ~DMAC_DCCSR_SWDH_MASK; -++ switch (nbit) { -++ case 8: -++ chan->mode |= DMAC_DCCSR_SWDH_8; -++ break; -++ case 16: -++ chan->mode |= DMAC_DCCSR_SWDH_16; -++ break; -++ case 32: -++ chan->mode |= DMAC_DCCSR_SWDH_32; -++ break; -++ } -++} -++ -++void jz_set_dma_block_size(int dmanr, int nbyte) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ chan->mode &= ~DMAC_DCCSR_DS_MASK; -++ switch (nbyte) { -++ case 1: -++ chan->mode |= DMAC_DCCSR_DS_8b; -++ break; -++ case 2: -++ chan->mode |= DMAC_DCCSR_DS_16b; -++ break; -++ case 4: -++ chan->mode |= DMAC_DCCSR_DS_32b; -++ break; -++ case 16: -++ chan->mode |= DMAC_DCCSR_DS_16B; -++ break; -++ case 32: -++ chan->mode |= DMAC_DCCSR_DS_32B; -++ break; -++ } -++} -++ -++/** -++ * jz_set_dma_mode - do the raw settings for the specified DMA channel -++ * @dmanr: the specified DMA channel -++ * @mode: dma operate mode, DMA_MODE_READ or DMA_MODE_WRITE -++ * @dma_mode: dma raw mode -++ * @dma_source: dma raw request source -++ * @fifo_addr: dma raw device fifo address -++ * -++ * Ensure call jz_request_dma(DMA_ID_RAW_REQ, ...) first, then call -++ * jz_set_dma_mode() rather than set_dma_mode() if you work with -++ * and external request dma device. -++ * -++ * NOTE: Don not dynamically allocate dma channel if one external request -++ * dma device will occupy this channel. -++*/ -++int jz_set_dma_mode(unsigned int dmanr, unsigned int mode, -++ unsigned int dma_mode, unsigned int dma_source, -++ unsigned int fifo_addr) -++{ -++ int dev_id, i; -++ struct jz_dma_chan *chan; -++ -++ if (dmanr > NUM_DMA) -++ return -ENODEV; -++ for (i = 0; i < NUM_DMA; i++) { -++ if (jz_dma_table[i].dev_id < 0) -++ break; -++ } -++ if (i == NUM_DMA) -++ return -ENODEV; -++ -++ chan = &jz_dma_table[dmanr]; -++ dev_id = chan->dev_id; -++ if (dev_id > 0) { -++ printk(KERN_DEBUG "%s sets the allocated DMA channel %d!\n", -++ __FUNCTION__, dmanr); -++ return -ENODEV; -++ } -++ -++ /* clone it from the dynamically allocated. */ -++ if (i != dmanr) { -++ chan->irq = jz_dma_table[i].irq; -++ chan->irq_dev = jz_dma_table[i].irq_dev; -++ chan->dev_str = jz_dma_table[i].dev_str; -++ jz_dma_table[i].irq = 0; -++ jz_dma_table[i].irq_dev = NULL; -++ jz_dma_table[i].dev_id = -1; -++ } -++ chan->dev_id = DMA_ID_RAW_SET; -++ chan->io = dmanr; -++ chan->fifo_addr = fifo_addr; -++ chan->mode = dma_mode; -++ chan->source = dma_source; -++ -++ set_dma_mode(dmanr, dma_mode); -++ -++ return dmanr; -++} -++ -++void enable_dma(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ -++ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TC | DMAC_DCCSR_AR); -++ __dmac_enable_channel(dmanr); -++ if (chan->irq) -++ __dmac_channel_enable_irq(dmanr); -++} -++ -++#define DMA_DISABLE_POLL 0x5000 -++ -++void disable_dma(unsigned int dmanr) -++{ -++ int i; -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ if (!__dmac_channel_enabled(dmanr)) -++ return; -++ -++ for (i = 0; i < DMA_DISABLE_POLL; i++) -++ if (__dmac_channel_transmit_end_detected(dmanr)) -++ break; -++#if 0 -++ if (i == DMA_DISABLE_POLL) -++ printk(KERN_INFO "disable_dma: poll expired!\n"); -++#endif -++ -++ __dmac_disable_channel(dmanr); -++ if (chan->irq) -++ __dmac_channel_disable_irq(dmanr); -++} -++ -++/* note: DMA_MODE_MASK is simulated by sw, DCCSR_MODE_MASK mask hw bits */ -++void set_dma_mode(unsigned int dmanr, unsigned int mode) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ mode &= ~(DMAC_DCCSR_TC | DMAC_DCCSR_AR); -++ chan->mode |= mode & ~(DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM | DMAC_DCCSR_DAM); -++ mode &= DMA_MODE_MASK; -++ if (mode == DMA_MODE_READ) { -++ chan->mode |= DMAC_DCCSR_DAM; -++ chan->mode &= ~DMAC_DCCSR_SAM; -++ } else if (mode == DMA_MODE_WRITE) { -++ chan->mode |= DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM; -++ chan->mode &= ~DMAC_DCCSR_DAM; -++ } else { -++ printk(KERN_DEBUG "set_dma_mode() support DMA_MODE_READ or DMA_MODE_WRITE!\n"); -++ } -++ REG_DMAC_DCCSR(chan->io) = chan->mode & ~DMA_MODE_MASK; -++ REG_DMAC_DRSR(chan->io) = chan->source; -++} -++ -++void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ switch (audio_fmt) { -++ case AFMT_U8: -++ /* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */ -++ break; -++ case AFMT_S16_LE: -++ /* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */ -++ if (mode == DMA_MODE_READ) { -++ mode &= ~(DMAC_DCCSR_TC | DMAC_DCCSR_AR); -++ chan->mode = DMA_AIC_32_16BYTE_RX_CMD | DMA_MODE_READ; -++ chan->mode |= mode & ~(DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM | DMAC_DCCSR_DAM); -++ mode &= DMA_MODE_MASK; -++ chan->mode |= DMAC_DCCSR_DAM; -++ chan->mode &= ~DMAC_DCCSR_SAM; -++ } else if (mode == DMA_MODE_WRITE) { -++ mode &= ~(DMAC_DCCSR_TC | DMAC_DCCSR_AR); -++ chan->mode = DMA_AIC_32_16BYTE_TX_CMD | DMA_MODE_WRITE; -++ chan->mode |= mode & ~(DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM |DMAC_DCCSR_DAM); -++ mode &= DMA_MODE_MASK; -++ chan->mode |= DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM; -++ chan->mode &= ~DMAC_DCCSR_DAM; -++ } else -++ printk("jz_set_oss_dma() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -++ -++ REG_DMAC_DCCSR(chan->io) = chan->mode & ~DMA_MODE_MASK; -++ REG_DMAC_DRSR(chan->io) = chan->source; -++ break; -++ } -++} -++ -++void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ switch (audio_fmt) { -++ case 8: -++ /* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */ -++ break; -++ case 16: -++ /* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */ -++ if (mode == DMA_MODE_READ) { -++ mode &= ~(DMAC_DCCSR_TC | DMAC_DCCSR_AR); -++ chan->mode = DMA_AIC_16BYTE_RX_CMD | DMA_MODE_READ; -++ chan->mode |= mode & ~(DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM | DMAC_DCCSR_DAM); -++ mode &= DMA_MODE_MASK; -++ chan->mode |= DMAC_DCCSR_DAM; -++ chan->mode &= ~DMAC_DCCSR_SAM; -++ } else if (mode == DMA_MODE_WRITE) { -++ mode &= ~(DMAC_DCCSR_TC | DMAC_DCCSR_AR); -++ chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE; -++ chan->mode |= mode & ~(DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM | DMAC_DCCSR_DAM); -++ mode &= DMA_MODE_MASK; -++ chan->mode |= DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM; -++ chan->mode &= ~DMAC_DCCSR_DAM; -++ } else -++ printk("jz_set_alsa_dma() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -++ -++ REG_DMAC_DCCSR(chan->io) = chan->mode & ~DMA_MODE_MASK; -++ REG_DMAC_DRSR(chan->io) = chan->source; -++ break; -++ } -++} -++ -++void set_dma_addr(unsigned int dmanr, unsigned int a) -++{ -++ unsigned int mode; -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ mode = chan->mode & DMA_MODE_MASK; -++ if (mode == DMA_MODE_READ) { -++ REG_DMAC_DSAR(chan->io) = chan->fifo_addr; -++ REG_DMAC_DDAR(chan->io) = a; -++ } else if (mode == DMA_MODE_WRITE) { -++ REG_DMAC_DSAR(chan->io) = a; -++ REG_DMAC_DDAR(chan->io) = chan->fifo_addr; -++ } else -++ printk(KERN_DEBUG "Driver should call set_dma_mode() ahead set_dma_addr()!\n"); -++} -++ -++void set_dma_count(unsigned int dmanr, unsigned int count) -++{ -++ unsigned int mode; -++ int dma_ds[] = {4, 1, 2, 16, 32}; -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ mode = (chan->mode & DMAC_DCCSR_DS_MASK) >> DMAC_DCCSR_DS_BIT; -++ count = count / dma_ds[mode]; -++ REG_DMAC_DTCR(chan->io) = count; -++} -++ -++int get_dma_residue(unsigned int dmanr) -++{ -++ int count; -++ unsigned int mode; -++ int dma_ds[] = {4, 1, 2, 16, 32}; -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return 0; -++ -++ mode = (chan->mode & DMAC_DCCSR_DS_MASK) >> DMAC_DCCSR_DS_BIT; -++ count = REG_DMAC_DTCR(chan->io); -++ count = count * dma_ds[mode]; -++ -++ return count; -++} -++ -++EXPORT_SYMBOL(jz_dma_table); -++EXPORT_SYMBOL(jz_request_dma); -++EXPORT_SYMBOL(jz_free_dma); -++EXPORT_SYMBOL(jz_set_dma_src_width); -++EXPORT_SYMBOL(jz_set_dma_dest_width); -++EXPORT_SYMBOL(jz_set_dma_block_size); -++EXPORT_SYMBOL(jz_set_dma_mode); -++EXPORT_SYMBOL(set_dma_mode); -++EXPORT_SYMBOL(jz_set_oss_dma); -++EXPORT_SYMBOL(jz_set_alsa_dma); -++EXPORT_SYMBOL(set_dma_addr); -++EXPORT_SYMBOL(set_dma_count); -++EXPORT_SYMBOL(get_dma_residue); -++EXPORT_SYMBOL(enable_dma); -++EXPORT_SYMBOL(disable_dma); -++EXPORT_SYMBOL(dump_jz_dma_channel); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4730/i2c.c linux-2.6.24.7/arch/mips/jz4730/i2c.c -+--- linux-2.6.24.7.old/arch/mips/jz4730/i2c.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4730/i2c.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,214 @@ -++/* -++ * linux/arch/mips/jz4730/i2c.c -++ * -++ * JZ4730 I2C APIs. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++ -++/* I2C protocol */ -++#define I2C_READ 1 -++#define I2C_WRITE 0 -++ -++#define TIMEOUT 1000 -++ -++/* -++ * I2C bus protocol basic routines -++ */ -++static int i2c_put_data(unsigned char data) -++{ -++ unsigned int timeout = TIMEOUT * 10; -++ -++ __i2c_write(data); -++ __i2c_set_drf(); -++ while (__i2c_check_drf() != 0); -++ while (!__i2c_transmit_ended()); -++ while (!__i2c_received_ack() && timeout) -++ timeout--; -++ -++ if (timeout) -++ return 0; -++ else -++ return -ETIMEDOUT; -++} -++ -++static int i2c_get_data(unsigned char *data, int ack) -++{ -++ int timeout = TIMEOUT*10; -++ -++ if (!ack) -++ __i2c_send_nack(); -++ else -++ __i2c_send_ack(); -++ -++ while (__i2c_check_drf() == 0 && timeout) -++ timeout--; -++ -++ if (timeout) { -++ if (!ack) -++ __i2c_send_stop(); -++ *data = __i2c_read(); -++ __i2c_clear_drf(); -++ return 0; -++ } else -++ return -ETIMEDOUT; -++} -++ -++/* -++ * I2C interface -++ */ -++void i2c_open(void) -++{ -++ __i2c_set_clk(jz_clocks.devclk, 10000); /* default 10 KHz */ -++ __i2c_enable(); -++} -++ -++void i2c_close(void) -++{ -++ udelay(300); /* wait for STOP goes over. */ -++ __i2c_disable(); -++} -++ -++void i2c_setclk(unsigned int i2cclk) -++{ -++ __i2c_set_clk(jz_clocks.devclk, i2cclk); -++} -++ -++int i2c_lseek(unsigned char device, unsigned char offset) -++{ -++ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -++ goto device_err; -++ if (i2c_put_data(offset) < 0) -++ goto address_err; -++ return 0; -++ device_err: -++ printk(KERN_DEBUG "No I2C device (0x%02x) installed.\n", device); -++ __i2c_send_stop(); -++ return -ENODEV; -++ address_err: -++ printk(KERN_DEBUG "No I2C device (0x%02x) response.\n", device); -++ __i2c_send_stop(); -++ return -EREMOTEIO; -++} -++ -++int i2c_read(unsigned char device, unsigned char *buf, -++ unsigned char address, int count) -++{ -++ int cnt = count; -++ int timeout = 5; -++ -++L_try_again: -++ -++ if (timeout < 0) -++ goto L_timeout; -++ -++ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -++ goto device_werr; -++ if (i2c_put_data(address) < 0) -++ goto address_err; -++ -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_READ ) < 0) -++ goto device_rerr; -++ __i2c_send_ack(); /* Master sends ACK for continue reading */ -++ while (cnt) { -++ if (cnt == 1) { -++ if (i2c_get_data(buf, 0) < 0) -++ break; -++ } else { -++ if (i2c_get_data(buf, 1) < 0) -++ break; -++ } -++ cnt--; -++ buf++; -++ } -++ -++ __i2c_send_stop(); -++ return count - cnt; -++ device_rerr: -++ device_werr: -++ address_err: -++ timeout --; -++ __i2c_send_stop(); -++ goto L_try_again; -++ -++L_timeout: -++ __i2c_send_stop(); -++ printk("Read I2C device 0x%2x failed.\n", device); -++ return -ENODEV; -++} -++ -++int i2c_write(unsigned char device, unsigned char *buf, -++ unsigned char address, int count) -++{ -++ int cnt = count; -++ int cnt_in_pg; -++ int timeout = 5; -++ unsigned char *tmpbuf; -++ unsigned char tmpaddr; -++ -++ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -++ -++ W_try_again: -++ if (timeout < 0) -++ goto W_timeout; -++ -++ cnt = count; -++ tmpbuf = (unsigned char *)buf; -++ tmpaddr = address; -++ -++ start_write_page: -++ cnt_in_pg = 0; -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -++ goto device_err; -++ if (i2c_put_data(tmpaddr) < 0) -++ goto address_err; -++ while (cnt) { -++ if (++cnt_in_pg > 8) { -++ __i2c_send_stop(); -++ mdelay(1); -++ tmpaddr += 8; -++ goto start_write_page; -++ } -++ if (i2c_put_data(*tmpbuf) < 0) -++ break; -++ cnt--; -++ tmpbuf++; -++ } -++ __i2c_send_stop(); -++ return count - cnt; -++ device_err: -++ address_err: -++ timeout--; -++ __i2c_send_stop(); -++ goto W_try_again; -++ -++ W_timeout: -++ printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device); -++ __i2c_send_stop(); -++ return -ENODEV; -++} -++ -++EXPORT_SYMBOL(i2c_open); -++EXPORT_SYMBOL(i2c_close); -++EXPORT_SYMBOL(i2c_setclk); -++EXPORT_SYMBOL(i2c_read); -++EXPORT_SYMBOL(i2c_write); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4730/irq.c linux-2.6.24.7/arch/mips/jz4730/irq.c -+--- linux-2.6.24.7.old/arch/mips/jz4730/irq.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4730/irq.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,266 @@ -++/* -++ * linux/arch/mips/jz4730/irq.c -++ * -++ * JZ4730 interrupt routines. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++ -++/* -++ * INTC irq type -++ */ -++ -++static void enable_intc_irq(unsigned int irq) -++{ -++ __intc_unmask_irq(irq); -++} -++ -++static void disable_intc_irq(unsigned int irq) -++{ -++ __intc_mask_irq(irq); -++} -++ -++static void mask_and_ack_intc_irq(unsigned int irq) -++{ -++ __intc_mask_irq(irq); -++ __intc_ack_irq(irq); -++} -++ -++static void end_intc_irq(unsigned int irq) -++{ -++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -++ enable_intc_irq(irq); -++ } -++} -++ -++static unsigned int startup_intc_irq(unsigned int irq) -++{ -++ enable_intc_irq(irq); -++ return 0; -++} -++ -++static void shutdown_intc_irq(unsigned int irq) -++{ -++ disable_intc_irq(irq); -++} -++ -++static struct irq_chip intc_irq_type = { -++ .typename = "INTC", -++ .startup = startup_intc_irq, -++ .shutdown = shutdown_intc_irq, -++ .enable = enable_intc_irq, -++ .disable = disable_intc_irq, -++ .ack = mask_and_ack_intc_irq, -++ .end = end_intc_irq, -++}; -++ -++/* -++ * GPIO irq type -++ */ -++ -++static void enable_gpio_irq(unsigned int irq) -++{ -++ unsigned int intc_irq; -++ -++ if (irq < (IRQ_GPIO_0 + 32)) { -++ intc_irq = IRQ_GPIO0; -++ } -++ else if (irq < (IRQ_GPIO_0 + 64)) { -++ intc_irq = IRQ_GPIO1; -++ } -++ else if (irq < (IRQ_GPIO_0 + 96)) { -++ intc_irq = IRQ_GPIO2; -++ } -++ else { -++ intc_irq = IRQ_GPIO3; -++ } -++ -++ enable_intc_irq(intc_irq); -++ __gpio_unmask_irq(irq - IRQ_GPIO_0); -++} -++ -++static void disable_gpio_irq(unsigned int irq) -++{ -++ __gpio_mask_irq(irq - IRQ_GPIO_0); -++} -++ -++static void mask_and_ack_gpio_irq(unsigned int irq) -++{ -++ __gpio_mask_irq(irq - IRQ_GPIO_0); -++ __gpio_ack_irq(irq - IRQ_GPIO_0); -++} -++ -++static void end_gpio_irq(unsigned int irq) -++{ -++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -++ enable_gpio_irq(irq); -++ } -++} -++ -++static unsigned int startup_gpio_irq(unsigned int irq) -++{ -++ enable_gpio_irq(irq); -++ return 0; -++} -++ -++static void shutdown_gpio_irq(unsigned int irq) -++{ -++ disable_gpio_irq(irq); -++} -++ -++static struct irq_chip gpio_irq_type = { -++ .typename = "GPIO", -++ .startup = startup_gpio_irq, -++ .shutdown = shutdown_gpio_irq, -++ .enable = enable_gpio_irq, -++ .disable = disable_gpio_irq, -++ .ack = mask_and_ack_gpio_irq, -++ .end = end_gpio_irq, -++}; -++ -++/* -++ * DMA irq type -++ */ -++ -++static void enable_dma_irq(unsigned int irq) -++{ -++ __intc_unmask_irq(IRQ_DMAC); -++ __dmac_channel_enable_irq(irq - IRQ_DMA_0); -++} -++ -++static void disable_dma_irq(unsigned int irq) -++{ -++ __dmac_channel_disable_irq(irq - IRQ_DMA_0); -++} -++ -++static void mask_and_ack_dma_irq(unsigned int irq) -++{ -++ __intc_ack_irq(IRQ_DMAC); -++ __dmac_channel_disable_irq(irq - IRQ_DMA_0); -++} -++ -++static void end_dma_irq(unsigned int irq) -++{ -++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -++ enable_dma_irq(irq); -++ } -++} -++ -++static unsigned int startup_dma_irq(unsigned int irq) -++{ -++ enable_dma_irq(irq); -++ return 0; -++} -++ -++static void shutdown_dma_irq(unsigned int irq) -++{ -++ disable_dma_irq(irq); -++} -++ -++static struct irq_chip dma_irq_type = { -++ .typename = "DMA", -++ .startup = startup_dma_irq, -++ .shutdown = shutdown_dma_irq, -++ .enable = enable_dma_irq, -++ .disable = disable_dma_irq, -++ .ack = mask_and_ack_dma_irq, -++ .end = end_dma_irq, -++}; -++ -++//---------------------------------------------------------------------- -++ -++void __init arch_init_irq(void) -++{ -++ int i; -++ -++ clear_c0_status(0xff04); /* clear ERL */ -++ set_c0_status(0x0400); /* set IP2 */ -++ -++ /* Set up INTC irq -++ */ -++ for (i = 0; i < 32; i++) { -++ disable_intc_irq(i); -++ irq_desc[i].chip = &intc_irq_type; -++ } -++ -++ /* Set up DMAC irq -++ */ -++ for (i = 0; i < NUM_DMA; i++) { -++ disable_dma_irq(IRQ_DMA_0 + i); -++ irq_desc[IRQ_DMA_0 + i].chip = &dma_irq_type; -++ } -++ -++ /* Set up GPIO irq -++ */ -++ for (i = 0; i < NUM_GPIO; i++) { -++ disable_gpio_irq(IRQ_GPIO_0 + i); -++ irq_desc[IRQ_GPIO_0 + i].chip = &gpio_irq_type; -++ } -++} -++ -++static int plat_real_irq(int irq) -++{ -++ switch (irq) { -++ case IRQ_GPIO0: -++ irq = __gpio_group_irq(0) + IRQ_GPIO_0; -++ break; -++ case IRQ_GPIO1: -++ irq = __gpio_group_irq(1) + IRQ_GPIO_0 + 32; -++ break; -++ case IRQ_GPIO2: -++ irq = __gpio_group_irq(2) + IRQ_GPIO_0 + 64; -++ break; -++ case IRQ_GPIO3: -++ irq = __gpio_group_irq(3) + IRQ_GPIO_0 + 96; -++ break; -++ case IRQ_DMAC: -++ irq = __dmac_get_irq() + IRQ_DMA_0; -++ break; -++ } -++ -++ return irq; -++} -++ -++asmlinkage void plat_irq_dispatch(void) -++{ -++ int irq = 0; -++ static unsigned long intc_ipr = 0; -++ -++ intc_ipr |= REG_INTC_IPR; -++ -++ if (!intc_ipr) return; -++ -++ irq = ffs(intc_ipr) - 1; -++ intc_ipr &= ~(1< -++ * -++ * This file is licensed under the terms of the GNU General Public -++ * License version 2. This program is licensed "as is" without any -++ * warranty of any kind, whether express or implied. -++ */ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++ -++/* OHCI (USB full speed host controller) */ -++static struct resource jz_usb_ohci_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(UHC_BASE), // phys addr for ioremap -++ .end = CPHYSADDR(UHC_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_UHC, -++ .end = IRQ_UHC, -++ .flags = IORESOURCE_IRQ, -++ }, -++}; -++ -++/* The dmamask must be set for OHCI to work */ -++static u64 ohci_dmamask = ~(u32)0; -++ -++static struct platform_device jz_usb_ohci_device = { -++ .name = "jz-ohci", -++ .id = 0, -++ .dev = { -++ .dma_mask = &ohci_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_usb_ohci_resources), -++ .resource = jz_usb_ohci_resources, -++}; -++ -++/*** LCD controller ***/ -++static struct resource jz_lcd_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(LCD_BASE), -++ .end = CPHYSADDR(LCD_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_LCD, -++ .end = IRQ_LCD, -++ .flags = IORESOURCE_IRQ, -++ } -++}; -++ -++static u64 jz_lcd_dmamask = ~(u32)0; -++ -++static struct platform_device jz_lcd_device = { -++ .name = "jz-lcd", -++ .id = 0, -++ .dev = { -++ .dma_mask = &jz_lcd_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_lcd_resources), -++ .resource = jz_lcd_resources, -++}; -++ -++/* UDC (USB gadget controller) */ -++static struct resource jz_usb_gdt_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(UDC_BASE), -++ .end = CPHYSADDR(UDC_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_UDC, -++ .end = IRQ_UDC, -++ .flags = IORESOURCE_IRQ, -++ }, -++}; -++ -++static u64 udc_dmamask = ~(u32)0; -++ -++static struct platform_device jz_usb_gdt_device = { -++ .name = "jz-udc", -++ .id = 0, -++ .dev = { -++ .dma_mask = &udc_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_usb_gdt_resources), -++ .resource = jz_usb_gdt_resources, -++}; -++ -++/** MMC/SD controller **/ -++static struct resource jz_mmc_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(MSC_BASE), -++ .end = CPHYSADDR(MSC_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_MSC, -++ .end = IRQ_MSC, -++ .flags = IORESOURCE_IRQ, -++ } -++}; -++ -++static u64 jz_mmc_dmamask = ~(u32)0; -++ -++static struct platform_device jz_mmc_device = { -++ .name = "jz-mmc", -++ .id = 0, -++ .dev = { -++ .dma_mask = &jz_mmc_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_mmc_resources), -++ .resource = jz_mmc_resources, -++}; -++ -++/* All */ -++static struct platform_device *jz_platform_devices[] __initdata = { -++ &jz_usb_ohci_device, -++ &jz_lcd_device, -++ &jz_usb_gdt_device, -++ &jz_mmc_device, -++}; -++ -++static int __init jz_platform_init(void) -++{ -++ return platform_add_devices(jz_platform_devices, ARRAY_SIZE(jz_platform_devices)); -++} -++ -++arch_initcall(jz_platform_init); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4730/pm.c linux-2.6.24.7/arch/mips/jz4730/pm.c -+--- linux-2.6.24.7.old/arch/mips/jz4730/pm.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4730/pm.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1098 @@ -++/* -++ * linux/arch/mips/jz4730/pm.c -++ * -++ * Jz4730 Power Management Routines -++ * -++ * Copyright 2005 Ingenic Semiconductor -++ * Wei Jianli -++ * Huang Lihong -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++extern void jz_cpu_suspend(void); -++extern void jz_cpu_resume(void); -++ -++static void jz_board_pm_suspend(void); -++ -++#define SAVE(x,s) sleep_save[SLEEP_SAVE_##x] = REG##s(x) -++#define RESTORE(x,s) REG##s(x) = sleep_save[SLEEP_SAVE_##x] -++ -++/* -++ * List of global jz4730 peripheral registers to preserve. -++ * More ones like core register and general purpose register values -++ * are preserved with the stack pointer in sleep.S. -++ */ -++enum { SLEEP_SAVE_START = 0, -++ -++ /* CPM */ -++ SLEEP_SAVE_CPM_MSCR, SLEEP_SAVE_CPM_PLCR1, -++ -++ /* WDT */ -++ SLEEP_SAVE_WDT_WTCNT, SLEEP_SAVE_WDT_WTCSR, -++ -++ /* OST */ -++ SLEEP_SAVE_OST_TER, -++ SLEEP_SAVE_OST_TCSR0, SLEEP_SAVE_OST_TCSR1, SLEEP_SAVE_OST_TCSR2, -++ SLEEP_SAVE_OST_TRDR0, SLEEP_SAVE_OST_TRDR1, SLEEP_SAVE_OST_TRDR2, -++ SLEEP_SAVE_OST_TCNT0, SLEEP_SAVE_OST_TCNT1, SLEEP_SAVE_OST_TCNT2, -++ -++ /* HARB */ -++ SLEEP_SAVE_HARB_HAPOR, SLEEP_SAVE_HARB_HMCTR, SLEEP_SAVE_HARB_HMLTR, -++ -++ /* EMC */ -++ SLEEP_SAVE_EMC_SMCR0, SLEEP_SAVE_EMC_SMCR1, SLEEP_SAVE_EMC_SMCR2, SLEEP_SAVE_EMC_SMCR3, -++ SLEEP_SAVE_EMC_SMCR4, SLEEP_SAVE_EMC_SMCR5, -++ -++ /* GPIO */ -++ SLEEP_SAVE_GPIO_GPDR0, SLEEP_SAVE_GPIO_GPDR1, SLEEP_SAVE_GPIO_GPDR2, SLEEP_SAVE_GPIO_GPDR3, -++ SLEEP_SAVE_GPIO_GPDIR0, SLEEP_SAVE_GPIO_GPDIR1, SLEEP_SAVE_GPIO_GPDIR2, SLEEP_SAVE_GPIO_GPDIR3, -++ SLEEP_SAVE_GPIO_GPODR0, SLEEP_SAVE_GPIO_GPODR1, SLEEP_SAVE_GPIO_GPODR2, SLEEP_SAVE_GPIO_GPODR3, -++ SLEEP_SAVE_GPIO_GPPUR0, SLEEP_SAVE_GPIO_GPPUR1, SLEEP_SAVE_GPIO_GPPUR2, SLEEP_SAVE_GPIO_GPPUR3, -++ SLEEP_SAVE_GPIO_GPALR0, SLEEP_SAVE_GPIO_GPALR1, SLEEP_SAVE_GPIO_GPALR2, SLEEP_SAVE_GPIO_GPALR3, -++ SLEEP_SAVE_GPIO_GPAUR0, SLEEP_SAVE_GPIO_GPAUR1, SLEEP_SAVE_GPIO_GPAUR2, SLEEP_SAVE_GPIO_GPAUR3, -++ SLEEP_SAVE_GPIO_GPIDLR0, SLEEP_SAVE_GPIO_GPIDLR1, SLEEP_SAVE_GPIO_GPIDLR2, SLEEP_SAVE_GPIO_GPIDLR3, -++ SLEEP_SAVE_GPIO_GPIDUR0, SLEEP_SAVE_GPIO_GPIDUR1, SLEEP_SAVE_GPIO_GPIDUR2, SLEEP_SAVE_GPIO_GPIDUR3, -++ SLEEP_SAVE_GPIO_GPIER0, SLEEP_SAVE_GPIO_GPIER1, SLEEP_SAVE_GPIO_GPIER2, SLEEP_SAVE_GPIO_GPIER3, -++ SLEEP_SAVE_GPIO_GPIMR0, SLEEP_SAVE_GPIO_GPIMR1, SLEEP_SAVE_GPIO_GPIMR2, SLEEP_SAVE_GPIO_GPIMR3, -++ SLEEP_SAVE_GPIO_GPFR0, SLEEP_SAVE_GPIO_GPFR1, SLEEP_SAVE_GPIO_GPFR2, SLEEP_SAVE_GPIO_GPFR3, -++ -++ /* UART(0-3) */ -++ SLEEP_SAVE_UART0_IER, SLEEP_SAVE_UART0_LCR, SLEEP_SAVE_UART0_MCR, SLEEP_SAVE_UART0_SPR, SLEEP_SAVE_UART0_DLLR, SLEEP_SAVE_UART0_DLHR, -++ SLEEP_SAVE_UART1_IER, SLEEP_SAVE_UART1_LCR, SLEEP_SAVE_UART1_MCR, SLEEP_SAVE_UART1_SPR, SLEEP_SAVE_UART1_DLLR, SLEEP_SAVE_UART1_DLHR, -++ SLEEP_SAVE_UART2_IER, SLEEP_SAVE_UART2_LCR, SLEEP_SAVE_UART2_MCR, SLEEP_SAVE_UART2_SPR, SLEEP_SAVE_UART2_DLLR, SLEEP_SAVE_UART2_DLHR, -++ SLEEP_SAVE_UART3_IER, SLEEP_SAVE_UART3_LCR, SLEEP_SAVE_UART3_MCR, SLEEP_SAVE_UART3_SPR, SLEEP_SAVE_UART3_DLLR, SLEEP_SAVE_UART3_DLHR, -++ -++ /* DMAC */ -++ SLEEP_SAVE_DMAC_DMACR, -++ SLEEP_SAVE_DMAC_DSAR0, SLEEP_SAVE_DMAC_DSAR1, SLEEP_SAVE_DMAC_DSAR2, SLEEP_SAVE_DMAC_DSAR3, SLEEP_SAVE_DMAC_DSAR4, SLEEP_SAVE_DMAC_DSAR5, SLEEP_SAVE_DMAC_DSAR6, SLEEP_SAVE_DMAC_DSAR7, -++ SLEEP_SAVE_DMAC_DDAR0, SLEEP_SAVE_DMAC_DDAR1, SLEEP_SAVE_DMAC_DDAR2, SLEEP_SAVE_DMAC_DDAR3, SLEEP_SAVE_DMAC_DDAR4, SLEEP_SAVE_DMAC_DDAR5, SLEEP_SAVE_DMAC_DDAR6, SLEEP_SAVE_DMAC_DDAR7, -++ SLEEP_SAVE_DMAC_DTCR0, SLEEP_SAVE_DMAC_DTCR1, SLEEP_SAVE_DMAC_DTCR2, SLEEP_SAVE_DMAC_DTCR3, SLEEP_SAVE_DMAC_DTCR4, SLEEP_SAVE_DMAC_DTCR5, SLEEP_SAVE_DMAC_DTCR6, SLEEP_SAVE_DMAC_DTCR7, -++ SLEEP_SAVE_DMAC_DRSR0, SLEEP_SAVE_DMAC_DRSR1, SLEEP_SAVE_DMAC_DRSR2, SLEEP_SAVE_DMAC_DRSR3, SLEEP_SAVE_DMAC_DRSR4, SLEEP_SAVE_DMAC_DRSR5, SLEEP_SAVE_DMAC_DRSR6, SLEEP_SAVE_DMAC_DRSR7, -++ SLEEP_SAVE_DMAC_DCCSR0, SLEEP_SAVE_DMAC_DCCSR1, SLEEP_SAVE_DMAC_DCCSR2, SLEEP_SAVE_DMAC_DCCSR3, SLEEP_SAVE_DMAC_DCCSR4, SLEEP_SAVE_DMAC_DCCSR5, SLEEP_SAVE_DMAC_DCCSR6, SLEEP_SAVE_DMAC_DCCSR7, -++ -++ /* INTC */ -++ SLEEP_SAVE_INTC_IPR, SLEEP_SAVE_INTC_ISR, SLEEP_SAVE_INTC_IMR, -++ -++ /* Checksum */ -++ SLEEP_SAVE_CKSUM, -++ -++ SLEEP_SAVE_SIZE -++}; -++ -++static unsigned long sleep_save[SLEEP_SAVE_SIZE]; -++ -++static int jz_pm_do_suspend(void) -++{ -++ unsigned long checksum = 0; -++ unsigned long imr = REG_INTC_IMR; -++ int i; -++ -++ printk("Put cpu into suspend mode.\n"); -++ -++ /* Mask all interrupts */ -++ REG_INTC_IMSR = 0xffffffff; -++ -++ /* Preserve current time */ -++ REG_RTC_RSR = xtime.tv_sec; -++ -++ REG_CPM_OCR |= CPM_OCR_SUSPEND_PHY0; /* suspend USB PHY 0 */ -++ REG_CPM_OCR |= CPM_OCR_SUSPEND_PHY1; /* suspend USB PHY 1 */ -++ REG_CPM_OCR |= CPM_OCR_EXT_RTC_CLK; /* select the external RTC clock (32.768KHz) */ -++ -++ /* Disable NAND ctroller */ -++ REG_EMC_NFCSR &= ~(EMC_NFCSR_NFE | EMC_NFCSR_FCE); -++ -++ /* -++ * Temporary solution. This won't be necessary once -++ * we move this support into the device drivers. -++ * Save the on-chip modules -++ */ -++ SAVE(UART0_LCR, 8); SAVE(UART0_MCR, 8); SAVE(UART0_SPR, 8); -++ REG8(UART0_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ -++ SAVE(UART0_DLLR, 8); SAVE(UART0_DLHR, 8); -++ REG8(UART0_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ -++ SAVE(UART0_IER, 8); -++ -++ SAVE(UART1_LCR, 8); SAVE(UART1_MCR, 8); SAVE(UART1_SPR, 8); -++ REG8(UART1_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ -++ SAVE(UART1_DLLR, 8); SAVE(UART1_DLHR, 8); -++ REG8(UART1_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ -++ SAVE(UART1_IER, 8); -++ -++ SAVE(UART2_LCR, 8); SAVE(UART2_MCR, 8); SAVE(UART2_SPR, 8); -++ REG8(UART2_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ -++ SAVE(UART2_DLLR, 8); SAVE(UART2_DLHR, 8); -++ REG8(UART2_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ -++ SAVE(UART2_IER, 8); -++ -++ SAVE(UART3_LCR, 8); SAVE(UART3_MCR, 8); SAVE(UART3_SPR, 8); -++ REG8(UART3_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ -++ SAVE(UART3_DLLR, 8); SAVE(UART3_DLHR, 8); -++ REG8(UART3_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ -++ SAVE(UART3_IER, 8); -++ -++ /* Save vital registers */ -++ -++ SAVE(OST_TER, 8); -++ SAVE(OST_TCSR0, 16); SAVE(OST_TCSR1, 16); SAVE(OST_TCSR2, 16); -++ SAVE(OST_TRDR0, 32); SAVE(OST_TRDR1, 32); SAVE(OST_TRDR2, 32); -++ SAVE(OST_TCNT0, 32); SAVE(OST_TCNT1, 32); SAVE(OST_TCNT2, 32); -++ -++ SAVE(HARB_HAPOR, 32); SAVE(HARB_HMCTR, 32); SAVE(HARB_HMLTR, 32); -++ -++ SAVE(EMC_SMCR0, 32); SAVE(EMC_SMCR1, 32); SAVE(EMC_SMCR2, 32); SAVE(EMC_SMCR3, 32); -++ SAVE(EMC_SMCR4, 32); SAVE(EMC_SMCR5, 32); -++ -++ SAVE(GPIO_GPDR0, 32); SAVE(GPIO_GPDR1, 32); SAVE(GPIO_GPDR2, 32); -++ SAVE(GPIO_GPDR3, 32); -++ SAVE(GPIO_GPDIR0, 32); SAVE(GPIO_GPDIR1, 32); SAVE(GPIO_GPDIR2, 32); -++ SAVE(GPIO_GPDIR3, 32); -++ SAVE(GPIO_GPODR0, 32); SAVE(GPIO_GPODR1, 32); SAVE(GPIO_GPODR2, 32); -++ SAVE(GPIO_GPODR3, 32); -++ SAVE(GPIO_GPPUR0, 32); SAVE(GPIO_GPPUR1, 32); SAVE(GPIO_GPPUR2, 32); -++ SAVE(GPIO_GPPUR3, 32); -++ SAVE(GPIO_GPALR0, 32); SAVE(GPIO_GPALR1, 32); SAVE(GPIO_GPALR2, 32); -++ SAVE(GPIO_GPALR3, 32); -++ SAVE(GPIO_GPAUR0, 32); SAVE(GPIO_GPAUR1, 32); SAVE(GPIO_GPAUR2, 32); -++ SAVE(GPIO_GPAUR3, 32); -++ SAVE(GPIO_GPIDLR0, 32); SAVE(GPIO_GPIDLR1, 32); SAVE(GPIO_GPIDLR2, 32); -++ SAVE(GPIO_GPIDLR3, 32); -++ SAVE(GPIO_GPIDUR0, 32); SAVE(GPIO_GPIDUR1, 32); SAVE(GPIO_GPIDUR2, 32); -++ SAVE(GPIO_GPIDUR3, 32); -++ SAVE(GPIO_GPIER0, 32); SAVE(GPIO_GPIER1, 32); SAVE(GPIO_GPIER2, 32); -++ SAVE(GPIO_GPIER3, 32); -++ SAVE(GPIO_GPIMR0, 32); SAVE(GPIO_GPIMR1, 32); SAVE(GPIO_GPIMR2, 32); -++ SAVE(GPIO_GPIMR3, 32); -++ SAVE(GPIO_GPFR0, 32); SAVE(GPIO_GPFR1, 32); SAVE(GPIO_GPFR2, 32); -++ SAVE(GPIO_GPFR3, 32); -++ -++ SAVE(DMAC_DMACR, 32); -++ SAVE(DMAC_DSAR0, 32); SAVE(DMAC_DSAR1, 32); SAVE(DMAC_DSAR2, 32); SAVE(DMAC_DSAR3, 32); SAVE(DMAC_DSAR4, 32); SAVE(DMAC_DSAR5, 32); SAVE(DMAC_DSAR6, 32); SAVE(DMAC_DSAR7, 32); -++ SAVE(DMAC_DDAR0, 32); SAVE(DMAC_DDAR1, 32); SAVE(DMAC_DDAR2, 32); SAVE(DMAC_DDAR3, 32); SAVE(DMAC_DDAR4, 32); SAVE(DMAC_DDAR5, 32); SAVE(DMAC_DDAR6, 32); SAVE(DMAC_DDAR7, 32); -++ SAVE(DMAC_DTCR0, 32); SAVE(DMAC_DTCR1, 32); SAVE(DMAC_DTCR2, 32); SAVE(DMAC_DTCR3, 32); SAVE(DMAC_DTCR4, 32); SAVE(DMAC_DTCR5, 32); SAVE(DMAC_DTCR6, 32); SAVE(DMAC_DTCR7, 32); -++ SAVE(DMAC_DRSR0, 32); SAVE(DMAC_DRSR1, 32); SAVE(DMAC_DRSR2, 32); SAVE(DMAC_DRSR3, 32); SAVE(DMAC_DRSR4, 32); SAVE(DMAC_DRSR5, 32); SAVE(DMAC_DRSR6, 32); SAVE(DMAC_DRSR7, 32); -++ SAVE(DMAC_DCCSR0, 32); SAVE(DMAC_DCCSR1, 32); SAVE(DMAC_DCCSR2, 32); SAVE(DMAC_DCCSR3, 32); SAVE(DMAC_DCCSR4, 32); SAVE(DMAC_DCCSR5, 32); SAVE(DMAC_DCCSR6, 32); SAVE(DMAC_DCCSR7, 32); -++ -++ SAVE(INTC_IPR, 32);SAVE(INTC_ISR, 32);SAVE(INTC_IMR, 32); -++ -++ SAVE(WDT_WTCNT, 32);SAVE(WDT_WTCSR, 8); -++ -++ /* Mask all interrupts */ -++ REG_INTC_IMSR = 0xffffffff; -++ -++ /* Save module clocks */ -++ SAVE(CPM_MSCR, 32); -++ -++ /* Save PLL */ -++ SAVE(CPM_PLCR1, 32); -++ -++ /* Stop module clocks */ -++ __cpm_stop_uart0(); -++ __cpm_stop_uart1(); -++ __cpm_stop_uart2(); -++ __cpm_stop_uart3(); -++ __cpm_stop_uhc(); -++ __cpm_stop_udc(); -++ __cpm_stop_eth(); -++ __cpm_stop_cim(); -++ __cpm_stop_kbc(); -++ __cpm_stop_scc(); -++ __cpm_stop_ssi(); -++ __cpm_stop_ost(); -++ -++ /* platform-specific pm routine */ -++ jz_board_pm_suspend(); -++ -++ /* Clear previous reset status */ -++ REG_CPM_RSTR &= ~(CPM_RSTR_HR | CPM_RSTR_WR | CPM_RSTR_SR); -++ -++ /* Set resume return address */ -++ REG_CPM_SPR = virt_to_phys(jz_cpu_resume); -++ -++ /* Before sleeping, calculate and save a checksum */ -++ for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++) -++ checksum += sleep_save[i]; -++ sleep_save[SLEEP_SAVE_CKSUM] = checksum; -++ -++ /* *** go zzz *** */ -++ jz_cpu_suspend(); -++#if 0 -++ /* after sleeping, validate the checksum */ -++ checksum = 0; -++ for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++) -++ checksum += sleep_save[i]; -++ -++ /* if invalid, display message and wait for a hardware reset */ -++ if (checksum != sleep_save[SLEEP_SAVE_CKSUM]) { -++ /** Add platform-specific message display codes here **/ -++ while (1); -++ } -++#endif -++ /* Restore PLL */ -++ RESTORE(CPM_PLCR1, 32); -++ -++ /* Restore module clocks */ -++ RESTORE(CPM_MSCR, 32); -++ -++ /* Ensure not to come back here if it wasn't intended */ -++ REG_CPM_SPR = 0; -++ -++ /* Restore registers */ -++ -++ RESTORE(GPIO_GPDR0, 32); RESTORE(GPIO_GPDR1, 32); RESTORE(GPIO_GPDR2, 32); -++ RESTORE(GPIO_GPDR3, 32); -++ RESTORE(GPIO_GPDIR0, 32); RESTORE(GPIO_GPDIR1, 32); RESTORE(GPIO_GPDIR2, 32); -++ RESTORE(GPIO_GPDIR3, 32); -++ RESTORE(GPIO_GPODR0, 32); RESTORE(GPIO_GPODR1, 32); RESTORE(GPIO_GPODR2, 32); -++ RESTORE(GPIO_GPODR3, 32); -++ RESTORE(GPIO_GPPUR0, 32); RESTORE(GPIO_GPPUR1, 32); RESTORE(GPIO_GPPUR2, 32); -++ RESTORE(GPIO_GPPUR3, 32); -++ RESTORE(GPIO_GPALR0, 32); RESTORE(GPIO_GPALR1, 32); RESTORE(GPIO_GPALR2, 32); -++ RESTORE(GPIO_GPALR3, 32); -++ RESTORE(GPIO_GPAUR0, 32); RESTORE(GPIO_GPAUR1, 32); RESTORE(GPIO_GPAUR2, 32); -++ RESTORE(GPIO_GPAUR3, 32); -++ RESTORE(GPIO_GPIDLR0, 32);RESTORE(GPIO_GPIDLR1, 32);RESTORE(GPIO_GPIDLR2, 32); -++ RESTORE(GPIO_GPIDLR3, 32); -++ RESTORE(GPIO_GPIDUR0, 32);RESTORE(GPIO_GPIDUR1, 32);RESTORE(GPIO_GPIDUR2, 32); -++ RESTORE(GPIO_GPIDUR3, 32); -++ RESTORE(GPIO_GPIER0, 32); RESTORE(GPIO_GPIER1, 32); RESTORE(GPIO_GPIER2, 32); -++ RESTORE(GPIO_GPIER3, 32); -++ RESTORE(GPIO_GPIMR0, 32); RESTORE(GPIO_GPIMR1, 32); RESTORE(GPIO_GPIMR2, 32); -++ RESTORE(GPIO_GPIMR3, 32); -++ RESTORE(GPIO_GPFR0, 32); RESTORE(GPIO_GPFR1, 32); RESTORE(GPIO_GPFR2, 32); -++ RESTORE(GPIO_GPFR3, 32); -++ -++ RESTORE(EMC_SMCR0, 32); RESTORE(EMC_SMCR1, 32); RESTORE(EMC_SMCR2, 32); RESTORE(EMC_SMCR3, 32); -++ RESTORE(EMC_SMCR4, 32); RESTORE(EMC_SMCR5, 32); -++ -++ RESTORE(HARB_HAPOR, 32); RESTORE(HARB_HMCTR, 32); RESTORE(HARB_HMLTR, 32); -++ -++ RESTORE(OST_TCNT0, 32); RESTORE(OST_TCNT1, 32); RESTORE(OST_TCNT2, 32); -++ RESTORE(OST_TRDR0, 32); RESTORE(OST_TRDR1, 32); RESTORE(OST_TRDR2, 32); -++ RESTORE(OST_TCSR0, 16); RESTORE(OST_TCSR1, 16); RESTORE(OST_TCSR2, 16); -++ RESTORE(OST_TER, 8); -++ -++ RESTORE(DMAC_DMACR, 32); -++ RESTORE(DMAC_DSAR0, 32); RESTORE(DMAC_DSAR1, 32); RESTORE(DMAC_DSAR2, 32); RESTORE(DMAC_DSAR3, 32); RESTORE(DMAC_DSAR4, 32); RESTORE(DMAC_DSAR5, 32); RESTORE(DMAC_DSAR6, 32); RESTORE(DMAC_DSAR7, 32); -++ RESTORE(DMAC_DDAR0, 32); RESTORE(DMAC_DDAR1, 32); RESTORE(DMAC_DDAR2, 32); RESTORE(DMAC_DDAR3, 32); RESTORE(DMAC_DDAR4, 32); RESTORE(DMAC_DDAR5, 32); RESTORE(DMAC_DDAR6, 32); RESTORE(DMAC_DDAR7, 32); -++ RESTORE(DMAC_DTCR0, 32); RESTORE(DMAC_DTCR1, 32); RESTORE(DMAC_DTCR2, 32); RESTORE(DMAC_DTCR3, 32); RESTORE(DMAC_DTCR4, 32); RESTORE(DMAC_DTCR5, 32); RESTORE(DMAC_DTCR6, 32); RESTORE(DMAC_DTCR7, 32); -++ RESTORE(DMAC_DRSR0, 32); RESTORE(DMAC_DRSR1, 32); RESTORE(DMAC_DRSR2, 32); RESTORE(DMAC_DRSR3, 32); RESTORE(DMAC_DRSR4, 32); RESTORE(DMAC_DRSR5, 32); RESTORE(DMAC_DRSR6, 32); RESTORE(DMAC_DRSR7, 32); -++ RESTORE(DMAC_DCCSR0, 32); RESTORE(DMAC_DCCSR1, 32); RESTORE(DMAC_DCCSR2, 32); RESTORE(DMAC_DCCSR3, 32); RESTORE(DMAC_DCCSR4, 32); RESTORE(DMAC_DCCSR5, 32); RESTORE(DMAC_DCCSR6, 32); RESTORE(DMAC_DCCSR7, 32); -++ -++ RESTORE(INTC_IPR, 32);RESTORE(INTC_ISR, 32);RESTORE(INTC_IMR, 32); -++ -++ REG_WDT_WTCNT = 0; RESTORE(WDT_WTCSR, 8); -++ -++ /* -++ * Temporary solution. This won't be necessary once -++ * we move this support into the device drivers. -++ * Restore the on-chip modules. -++ */ -++ -++ /* FIFO control reg, write-only */ -++ REG8(UART0_FCR) = UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS | UARTFCR_UUE; -++ REG8(UART1_FCR) = UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS | UARTFCR_UUE; -++ REG8(UART2_FCR) = UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS | UARTFCR_UUE; -++ REG8(UART3_FCR) = UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS | UARTFCR_UUE; -++ -++ REG8(UART0_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ -++ RESTORE(UART0_DLLR, 8); RESTORE(UART0_DLHR, 8); -++ REG8(UART0_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ -++ RESTORE(UART0_IER, 8); -++ RESTORE(UART0_MCR, 8); RESTORE(UART0_SPR, 8); RESTORE(UART0_LCR, 8); -++ -++ REG8(UART1_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ -++ RESTORE(UART1_DLLR, 8); RESTORE(UART1_DLHR, 8); -++ REG8(UART1_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ -++ RESTORE(UART1_IER, 8); -++ RESTORE(UART1_MCR, 8); RESTORE(UART1_SPR, 8); RESTORE(UART1_LCR, 8); -++ -++ REG8(UART2_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ -++ RESTORE(UART2_DLLR, 8); RESTORE(UART2_DLHR, 8); -++ REG8(UART2_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ -++ RESTORE(UART2_IER, 8); -++ RESTORE(UART2_MCR, 8); RESTORE(UART2_SPR, 8); RESTORE(UART2_LCR, 8); -++ -++ REG8(UART3_LCR) |= UARTLCR_DLAB; /* Access to DLLR/DLHR */ -++ RESTORE(UART3_DLLR, 8); RESTORE(UART3_DLHR, 8); -++ REG8(UART3_LCR) &= ~UARTLCR_DLAB; /* Access to IER */ -++ RESTORE(UART3_IER, 8); -++ RESTORE(UART3_MCR, 8); RESTORE(UART3_SPR, 8); RESTORE(UART3_LCR, 8); -++ -++ REG_CPM_OCR &= ~CPM_OCR_SUSPEND_PHY0; /* resume USB PHY 0 */ -++ REG_CPM_OCR &= ~CPM_OCR_SUSPEND_PHY1; /* resume USB PHY 1 */ -++#if 0 -++ REG_CPM_OCR &= ~CPM_OCR_EXT_RTC_CLK; /* use internal RTC clock (JZ_EXTAL/128 Hz) */ -++#else -++ REG_CPM_OCR |= CPM_OCR_EXT_RTC_CLK; /* use external RTC clock (32.768 KHz) */ -++#endif -++ -++ /* Enable NAND ctroller */ -++ REG_EMC_NFCSR |= EMC_NFCSR_NFE; -++ -++ /* Restore current time */ -++ xtime.tv_sec = REG_RTC_RSR; -++ -++ /* Restore interrupts */ -++ REG_INTC_IMSR = imr; -++ REG_INTC_IMCR = ~imr; -++ -++ return 0; -++} -++ -++/* NOTES: -++ * 1: Pins that are floated (NC) should be set as input and pull-enable. -++ * 2: Pins that are pull-up or pull-down by outside should be set as input -++ * and pull-disable. -++ * 3: Pins that are connected to a chipset should be set as pull-disable. -++ */ -++static void jz_board_pm_gpio_setup(void) -++{ -++ /* CIM_D0(IN)/PULL-UP/GP0 */ -++ __gpio_as_input(0); -++ __gpio_enable_pull(0); -++ -++ /* CIM_D1(IN)/PULL-UP/GP1 */ -++ __gpio_as_input(1); -++ __gpio_enable_pull(1); -++ -++ /* CIM_D2(IN)/PULL-UP/GP2 */ -++ __gpio_as_input(2); -++ __gpio_enable_pull(2); -++ -++ /* CIM_D3(IN)/PULL-UP/GP3 */ -++ __gpio_as_input(3); -++ __gpio_enable_pull(3); -++ -++ /* CIM_D4(IN)/PULL-DOWN/GP4 */ -++ __gpio_as_input(4); -++ __gpio_enable_pull(4); -++ -++ /* CIM_D5(IN)/PULL-DOWN/GP5 */ -++ __gpio_as_input(5); -++ __gpio_enable_pull(5); -++ -++ /* CIM_D6(IN)/PULL-DOWN/GP6 */ -++ __gpio_as_input(6); -++ __gpio_enable_pull(6); -++ -++ /* CIM_D7(IN)/PULL-DOWN/GP7 */ -++ __gpio_as_input(7); -++ __gpio_enable_pull(7); -++ -++ /* CIM_VSYNC(IN)/PULL-DOWN/GP8 */ -++ __gpio_as_input(8); -++ __gpio_enable_pull(8); -++ -++ /* CIM_HSYNC(IN)/PULL-UP/GP9 */ -++ __gpio_as_input(9); -++ __gpio_enable_pull(9); -++ -++ /* CIM_PCLK(IN)/PULL-DOWN/GP10 */ -++ __gpio_as_input(10); -++ __gpio_enable_pull(10); -++ -++ /* CIM_MCLK(OUT)/PULL-DOWN/GP11 */ -++ __gpio_as_input(11); -++ __gpio_enable_pull(11); -++ -++ /* DMA_DREQ0(IN)/CHIP_MODE/PULL-UP/GP12 */ -++ __gpio_as_input(12); -++ __gpio_enable_pull(12); -++ -++ /* DMA_DACK0(OUT)/PULL-UP/GP13 */ /* GPIO13 */ -++ __gpio_as_input(13); -++ __gpio_disable_pull(13); -++ -++ /* GP14 */ -++ /* GP15 */ -++ -++ /* RXD3(IN)/PULL-UP/GP16 */ -++ __gpio_as_input(16); -++ __gpio_enable_pull(16); -++ -++ /* CTS3(IN)/PULL-UP/GP17 */ -++ __gpio_as_input(17); -++ __gpio_enable_pull(17); -++ -++ /* GP18 */ -++ /* GP19 */ -++ /* GP20 */ -++ -++ /* TXD3(OUT)/PULL-UP/GP21 */ -++ __gpio_as_input(21); -++ __gpio_enable_pull(21); -++ -++ /* GP22 */ -++ -++ /* RTS3(OUT)/PULL-UP/GP23 */ -++ __gpio_as_input(23); -++ __gpio_enable_pull(23); -++ -++ /* RXD1(IN)/PULL-UP/GP24 */ /* IR_RXD */ -++ __gpio_as_input(24); -++ __gpio_enable_pull(24); -++ -++ /* TXD1(OUT)/PULL-UP/GP25 */ /* IR_TXD */ -++ __gpio_disable_pull(25); -++ __gpio_as_output(25); -++ __cpm_set_pin(25); -++ -++ /* DMA_AEN(OUT)/PULL-UP/GP26 */ /* CIM_PWD_N */ -++ __gpio_as_input(26); -++ __gpio_disable_pull(26); -++ -++ /* DMA_EOP(OUT)/PULL-UP/GP27 */ /* SW4 */ -++ __gpio_as_input(27); -++ __gpio_disable_pull(27); -++ -++ /* USB_CLK(IN)/PULL-UP/GP28 */ -++ __gpio_as_input(28); -++ __gpio_disable_pull(28); -++ -++ /* USB_PPWR0(OUT)/PULL-UP/GP29 */ /* USB_CLK_EN */ -++ __gpio_disable_pull(29); -++ __gpio_as_output(29); -++ __cpm_clear_pin(29); /* disable USB 48MHz clock */ -++ -++ /* GP30 */ -++ /* GP31 */ -++ -++ /* PS2_KCLK(IO)/PULL-UP/GP32 */ -++ __gpio_as_input(32); -++ __gpio_enable_pull(32); -++ -++ /* PS2_KDATA(IO)/PULL-UP/GP33 */ /* CIM_RST */ -++ __gpio_as_input(33); -++ __gpio_enable_pull(33); -++ -++ /* MSC_D0(IO)/PULL-UP/GP34 */ -++ __gpio_as_input(34); -++ __gpio_disable_pull(34); -++ -++ /* MSC_D1(IO)/PULL-UP/GP35 */ -++ __gpio_as_input(35); -++ __gpio_disable_pull(35); -++ -++ /* MSC_D2(IO)/PULL-UP/GP36 */ -++ __gpio_as_input(36); -++ __gpio_disable_pull(36); -++ -++ /* MSC_D3(IO)/PULL-UP/GP37 */ -++ __gpio_as_input(37); -++ __gpio_disable_pull(37); -++ -++ /* MSC_CMD(IO)/PULL-UP/GP38 */ -++ __gpio_as_input(38); -++ __gpio_disable_pull(38); -++ -++ /* MSC_CLK(OUT)/PULL-UP/GP39 */ -++ __gpio_as_input(39); -++ __gpio_enable_pull(39); -++ -++ /* LCD_D0(OUT)/PULL-UP/GP40 */ -++ __gpio_as_input(40); -++ __gpio_enable_pull(40); -++ -++ /* LCD_D1(OUT)/PULL-UP/GP41 */ -++ __gpio_as_input(41); -++ __gpio_enable_pull(41); -++ -++ /* LCD_D2(OUT)/PULL-UP/GP42 */ -++ __gpio_as_input(42); -++ __gpio_enable_pull(42); -++ -++ /* LCD_D3(OUT)/PULL-UP/GP43 */ -++ __gpio_as_input(43); -++ __gpio_enable_pull(43); -++ -++ /* LCD_D4(OUT)/PULL-UP/GP44 */ -++ __gpio_as_input(44); -++ __gpio_enable_pull(44); -++ -++ /* LCD_D5(OUT)/PULL-UP/GP45 */ -++ __gpio_as_input(45); -++ __gpio_enable_pull(45); -++ -++ /* LCD_D6(OUT)/PULL-UP/GP46 */ -++ __gpio_as_input(46); -++ __gpio_enable_pull(46); -++ -++ /* LCD_D7(OUT)/PULL-UP/GP47 */ -++ __gpio_as_input(47); -++ __gpio_enable_pull(47); -++ -++ /* LCD_D8(OUT)/PULL-DOWN/GP48 */ -++ __gpio_as_input(48); -++ __gpio_enable_pull(48); -++ -++ /* LCD_D9(OUT)/PULL-DOWN/GP49 */ -++ __gpio_as_input(49); -++ __gpio_enable_pull(49); -++ -++ /* LCD_D10(OUT)/PULL-DOWN/GP50 */ -++ __gpio_as_input(50); -++ __gpio_enable_pull(50); -++ -++ /* LCD_D11(OUT)/PULL-DOWN/GP51 */ -++ __gpio_as_input(51); -++ __gpio_enable_pull(51); -++ -++ /* LCD_D12(OUT)/PULL-DOWN/GP52 */ -++ __gpio_as_input(52); -++ __gpio_enable_pull(52); -++ -++ /* LCD_D13(OUT)/PULL-DOWN/GP53 */ -++ __gpio_as_input(53); -++ __gpio_enable_pull(53); -++ -++ /* LCD_D14(OUT)/PULL-DOWN/GP54 */ -++ __gpio_as_input(54); -++ __gpio_enable_pull(54); -++ -++ /* LCD_D15(OUT)/PULL-DOWN/GP55 */ -++ __gpio_as_input(55); -++ __gpio_enable_pull(55); -++ -++ /* LCD_VSYNC(IN)/PULL-DOWN/GP56 */ -++ __gpio_as_input(56); -++ __gpio_enable_pull(56); -++ -++ /* LCD_HSYNC(IN)/PULL-UP/GP57 */ -++ __gpio_as_input(57); -++ __gpio_enable_pull(57); -++ -++ /* LCD_PCLK(IN)/PULL-DOWN/GP58 */ -++ __gpio_as_input(58); -++ __gpio_enable_pull(58); -++ -++ /* LCD_DE(OUT)/PULL-DOWN/GP59 */ -++ __gpio_as_input(59); -++ __gpio_enable_pull(59); -++ -++ /* LCD_SPL(OUT)/PULL-UP/GP60 */ -++ __gpio_as_input(60); -++ __gpio_disable_pull(60); -++ -++ /* LCD_CLS(OUT)/PULL-UP/GP61 */ -++ __gpio_as_input(61); -++ __gpio_disable_pull(61); -++ -++ /* LCD_PS(OUT)/PULL-UP/GP62 */ -++ __gpio_as_input(62); -++ __gpio_disable_pull(62); -++ -++ /* LCD_REV(OUT)/PULL-UP/GP63 */ -++ __gpio_as_input(63); -++ __gpio_enable_pull(63); -++ -++ /* SCC0_DAT(IO)/PULL-UP/GP64 */ /* Keypad */ -++ __gpio_as_input(64); -++ __gpio_enable_pull(64); -++ -++ /* SCC1_DAT(IO)/PULL-UP/GP65 */ /* SW5 */ -++ __gpio_as_input(65); -++ __gpio_disable_pull(65); -++ -++ /* SCC0_CLK(OUT)/PULL-UP/GP66 */ /* PW_O */ -++ __gpio_disable_pull(66); -++ __gpio_as_output(66); -++ __cpm_set_pin(66); -++ -++ /* SCC1_CLK(OUT)/PULL-UP/GP67 */ /* SW6 */ -++ __gpio_as_input(67); -++ __gpio_disable_pull(67); -++ -++ /* SYS_CLK(OUT)/PULL-UP/GP68 */ /* I2S_CLK */ -++ __gpio_disable_pull(68); -++ -++ /* ACRESET_N(OUT)/PULL-UP/GP69 */ /* AK4642 PDN */ -++ __gpio_disable_pull(69); -++ __gpio_as_output(69); -++ __cpm_clear_pin(69); -++ -++ /* SDATA_OUT(OUT)/PULL-UP/GP70 */ /* I2S_DIN */ -++ __gpio_disable_pull(70); -++ -++ /* SDATA_IN(IN)/PULL-UP/GP71 */ /* I2S_DOUT */ -++ __gpio_disable_pull(71); -++ -++ /* SSI_CLK(OUT)/PULL-UP/GP72 */ /* SSI_CLK */ -++ __gpio_as_input(72); -++ __gpio_enable_pull(72); -++ -++ /* SSI_CE1_N(OUT)/PULL-UP/GP73 */ /* SSI_CE1_N */ -++ __gpio_as_input(73); -++ __gpio_enable_pull(73); -++ -++ /* SSI_DT(OUT)/PULL-UP/GP74 */ /* SSI_DT */ -++ __gpio_as_input(74); -++ __gpio_enable_pull(74); -++ -++ /* SSI_DR(IN)/PULL-UP/GP75 */ /* SSI_DR */ -++ __gpio_as_input(75); -++ __gpio_enable_pull(75); -++ -++ /* SSI_CE2_N(OUT)/SSI_GPC/PULL-UP/GP76 */ -++ __gpio_as_input(76); -++ __gpio_enable_pull(76); -++ -++ /* BITCLK_IN(IN)/PULL-UP/GP77 */ /* I2S_BITCLK */ -++ __gpio_disable_pull(77); -++ -++ /* SYNC_IN(IN)/PULL-UP/GP78 */ /* I2S_LRCIN */ -++ __gpio_disable_pull(78); -++ -++ /* FRE_N(OUT)/PULL-UP/GP79 */ -++ __gpio_enable_pull(79); -++ __gpio_as_input(79); -++ -++ /* FWE_N(OUT)/PULL-UP/GP80 */ -++ __gpio_enable_pull(80); -++ __gpio_as_input(80); -++ -++ /* FRB_N(IN)/PULL-UP/GP81 */ -++ __gpio_enable_pull(81); -++ __gpio_as_input(81); -++ -++ /* DCS1_N(OUT)/PULL-UP/GP82 */ /* SD_WP */ -++ __gpio_as_input(82); -++ __gpio_enable_pull(82); -++ -++ /* CS1_N(OUT)/PULL-UP/GP83 */ /* JACK_PLUG */ -++ __gpio_as_input(83); -++ __gpio_disable_pull(83); -++ -++ /* CS2_N(OUT)/PULL-UP/GP84 */ /* DC_DETE */ -++ __gpio_as_input(84); -++ __gpio_disable_pull(84); -++ -++ /* CS3_N(OUT)/PULL-UP/GP85 */ /* NAND CS# */ -++ __gpio_enable_pull(85); -++ __gpio_as_input(85); -++ -++ /* CS4_N/(OUT)PULL-UP/GP86 */ /* PULL_OFF */ -++ __gpio_disable_pull(86); -++ __gpio_as_output(86); -++// __cpm_set_pin(86); -++ __cpm_clear_pin(86); -++ -++ /* CS5_N(OUT)/PULL-UP/GP87 */ /* IR_SD */ -++ __gpio_as_input(87); -++ __gpio_disable_pull(87); -++ -++ /* INPACK_N(IN)/PULL-UP/GP88 */ /* SW7 */ -++ __gpio_as_input(88); -++ __gpio_disable_pull(88); -++ -++ /* BVD2(IN)/PULL-UP/GP89 */ /* SW8 */ -++ __gpio_as_input(89); -++ __gpio_disable_pull(89); -++ -++ /* PCE1_N(OUT)/PULL-UP/GP90 */ /* SD_CD_N */ -++ __gpio_as_input(90); -++ __gpio_enable_pull(90); -++ -++ /* PSKTSEL_N(OUT)/PULL-UP/GP91 */ /* SD_VCC_3V_EN_N */ -++ __gpio_disable_pull(91); -++ __gpio_as_output(91); -++ __cpm_clear_pin(91); -++ -++ /* IOIS16_N(IN)/PULL-UP/GP92 */ /* LED_EN */ -++ __gpio_disable_pull(92); -++ __gpio_as_output(92); -++ __cpm_clear_pin(92); -++ -++ /* PCE2_N(OUT)/PULL-UP/GP93 */ /* LCD_DISP_OFF_N */ -++ __gpio_disable_pull(93); -++ __gpio_as_input(93); -++ -++ /* PWM0(OUT)/PULL-UP/GP94 */ /* LCD backlight off */ -++ __gpio_disable_pull(94); -++ __gpio_as_output(94); -++ __cpm_clear_pin(94); -++ -++ /* PWM1(OUT)/PULL-UP/GP95 */ -++ __gpio_disable_pull(95); -++ __gpio_as_output(95); -++ __cpm_clear_pin(95); -++ -++ /* PRT(OUT)/PULL-UP/GP96 */ /* RTC_IRQ */ -++ __gpio_as_input(96); -++ __gpio_disable_pull(96); -++ -++ /* PRT(OUT)/PULL-UP/GP97 */ /* PW_I */ -++ __gpio_as_input(97); -++ __gpio_disable_pull(97); -++ -++ /* PRT(OUT)/PULL-UP/GP98 */ /* Keypad */ -++ __gpio_as_input(98); -++ __gpio_disable_pull(98); -++ -++ /* PRT(OUT)/PULL-UP/GP99 */ /* Keypad */ -++ __gpio_as_input(99); -++ __gpio_disable_pull(99); -++ -++ /* PRT(OUT)/PULL-UP/GP100 */ /* Keypad */ -++ __gpio_as_input(100); -++ __gpio_disable_pull(100); -++ -++ /* PRT(OUT)/PULL-UP/GP101 */ /* Keypad */ -++ __gpio_as_input(101); -++ __gpio_disable_pull(101); -++ -++ /* PRT(OUT)/PULL-UP/GP102 */ /* Keypad */ -++ __gpio_as_input(102); -++ __gpio_disable_pull(102); -++ -++ /* PRT(OUT)/PULL-UP/GP103 */ /* Keypad */ -++ __gpio_as_input(103); -++ __gpio_enable_pull(103); -++ -++ /* PRT(OUT)/PULL-UP/GP104 */ /* Keypad */ -++ __gpio_as_input(104); -++ __gpio_enable_pull(104); -++ -++ /* PRT(OUT)/PULL-UP/GP105 */ /* Keypad */ -++ __gpio_as_input(105); -++ __gpio_enable_pull(105); -++ -++ /* PRT(OUT)/PULL-UP/GP106 */ /* 5V_ON */ -++ __gpio_disable_pull(106); -++ __gpio_as_output(106); -++ __cpm_clear_pin(106); -++ -++ /* PRT(IN)/PULL-UP/GP107 */ /* GSM_BOOT */ -++ __gpio_as_input(107); -++ __gpio_enable_pull(107); -++ -++ /* PRT(IN)/PULL-UP/GP108 */ /* GSM_RESET */ -++ __gpio_as_input(108); -++ __gpio_enable_pull(108); -++ -++ /* PRT(IN)/PULL-UP/GP109 */ /* GSM_EN */ -++ __gpio_as_input(109); -++ __gpio_enable_pull(109); -++ -++ /* PRT(IN)/PULL-UP/GP110 */ /* GSM_RING */ -++ __gpio_as_input(110); -++ __gpio_enable_pull(110); -++ -++ /* PRT(IN)/UART2_RXD/PULL-UP/GP111 */ /* Keypad */ -++ __gpio_as_input(111); -++ __gpio_enable_pull(111); -++ -++ /* MII_TX_EN(OUT)/PULL-UP/GP112 */ -++ __gpio_as_input(112); -++ __gpio_enable_pull(112); -++ -++ /* MII_RX_DV(IN)/PULL-UP/GP113 */ -++ __gpio_as_input(113); -++ __gpio_enable_pull(113); -++ -++ /* MII_RX_ER(IN)/PULL-UP/GP114 */ -++ __gpio_as_input(114); -++ __gpio_enable_pull(114); -++ -++ /* MII_COL(IN)/PULL-UP/GP115 */ -++ __gpio_as_input(115); -++ __gpio_enable_pull(115); -++ -++ /* MII_CRS(IN)/PULL-UP/GP116 */ -++ __gpio_as_input(116); -++ __gpio_enable_pull(116); -++ -++ /* MII_TXD0(OUT)/PULL-UP/GP117 */ -++ __gpio_as_input(117); -++ __gpio_enable_pull(117); -++ -++ /* MII_TXD1(OUT)/PULL-UP/GP118 */ -++ __gpio_as_input(118); -++ __gpio_enable_pull(118); -++ -++ /* MII_TXD2(OUT)/PULL-UP/GP119 */ -++ __gpio_as_input(119); -++ __gpio_enable_pull(119); -++ -++ /* MII_TXD3(OUT)/PULL-UP/GP120 */ -++ __gpio_as_input(120); -++ __gpio_enable_pull(120); -++ -++ /* MII_RXD0(IN)/PULL-UP/GP121 */ -++ __gpio_as_input(121); -++ __gpio_enable_pull(121); -++ -++ /* MII_RXD1(IN)/PULL-UP/GP122 */ -++ __gpio_as_input(122); -++ __gpio_enable_pull(122); -++ -++ /* MII_RXD2(IN)/PULL-UP/GP123 */ -++ __gpio_as_input(123); -++ __gpio_enable_pull(123); -++ -++ /* MII_RXD3(IN)/PULL-UP/GP124 */ -++ __gpio_as_input(124); -++ __gpio_enable_pull(124); -++ -++ /* UART2_TXD(OUT)/PULL-UP/GP125 */ /* CHARG_STAT */ -++ __gpio_as_output(125); -++ __gpio_disable_pull(125); -++ __cpm_clear_pin(125); -++ -++ /* UART0_RXD(IN)/PULL-UP/GP126 */ -++ __gpio_as_input(126); -++ __gpio_enable_pull(126); -++ -++ /* UART0_TXD(OUT)/PULL-UP/GP127 */ -++ __gpio_as_input(127); -++ __gpio_enable_pull(127); -++} -++ -++/* -++ * In order to save power most, all gpio pins should be put to their -++ * proper states during low power mode. -++ */ -++static void jz_board_pm_suspend(void) -++{ -++ /* Setup the state of all the GPIO pins during low-power mode */ -++ jz_board_pm_gpio_setup(); -++ -++ /* Allow next interrupts to wakeup the system. -++ */ -++ REG_CPM_WER = 0; /* Clear all first */ -++ -++ /* RTC alarm */ -++ REG_CPM_WER |= 1 << 0; -++ REG_CPM_WRER |= 1 << 0; -++ REG_CPM_WFER |= 1 << 0; -++ __gpio_as_irq_rise_edge(96); -++ -++ /* Power_I key */ -++ REG_CPM_WER |= 1 << 1; -++ REG_CPM_WRER |= 1 << 1; -++ REG_CPM_WFER |= 1 << 1; -++ __gpio_as_irq_rise_edge(97); -++ -++ /* enable INTC irq */ -++ __intc_unmask_irq(IRQ_GPIO3); -++ -++#if 0 -++ /* Enable RTC alarm */ -++ REG_CPM_WER |= CPM_WER_WERTC; -++ REG_RTC_RGR = 32767; -++ REG_RTC_RCR &= ~RTC_RCR_AE; -++ REG_RTC_RSR = 0; -++ REG_RTC_RSAR = 30; -++ REG_RTC_RCR = RTC_RCR_AE | RTC_RCR_AIE | RTC_RCR_START; -++#endif -++} -++ -++/* -++ * We don't use sleep mode of jz4730 for it has bug, the suspend mode -++ * implemented by hibernate mode is used instead of it. -++ */ -++static int jz_pm_do_sleep(void) -++{ -++ printk("It was deprecated, please use /proc/sys/pm/suspend.\n"); -++#if 0 -++ unsigned long imr = REG_INTC_IMR; -++ -++ /* Preserve current time */ -++ REG_RTC_RSR = xtime.tv_sec; -++ -++ /* Mask all interrupts */ -++ REG_INTC_IMSR = 0xffffffff; -++ -++ /* Just allow next interrupts to wakeup the system. -++ * Note: modify this according to your system. -++ */ -++ /* RTC alarm */ -++ __gpio_as_irq_fall_edge(96); /* GPIO 96 */ -++ -++ /* POWER_I key */ -++ __gpio_as_irq_rise_edge(97); /* GPIO 97 */ -++ -++ /* Enable INTC */ -++ __intc_unmask_irq(IRQ_GPIO3); -++ -++ /* Disable modules e.g. LCD backlight */ -++ -++ /* Stop module clocks */ -++ __cpm_stop_uhc(); -++ -++ /* Enter SLEEP mode -++ * Put SDRAM into self-refresh mode. -++ */ -++ REG_CPM_LPCR &= ~CPM_LPCR_LPM_MASK; -++ REG_CPM_LPCR |= CPM_LPCR_LPM_SLEEP; -++ -++ __asm__(".set\tmips3\n\t" -++ ".set noreorder\n\t" -++ ".align 5\n\t" -++ "wait\n\t" -++ "nop\n\t" -++ ".set reorder\n\t" -++ ".set\tmips0"); -++ -++ /* Restore to IDLE mode */ -++ REG_CPM_LPCR &= ~CPM_LPCR_LPM_MASK; -++ REG_CPM_LPCR |= CPM_LPCR_LPM_IDLE; -++ -++ /* Restore clock of usb host */ -++ __cpm_start_uhc(); -++ -++ /* Restore interrupts */ -++ REG_INTC_IMSR = imr; -++ REG_INTC_IMCR = ~imr; -++ -++ /* Restore current time */ -++ xtime.tv_sec = REG_RTC_RSR; -++#endif -++ return 0; -++} -++ -++#define K0BASE KSEG0 -++void jz_flush_cache_all(void) -++{ -++ unsigned long addr; -++ -++ /* Clear CP0 TagLo */ -++ asm volatile ("mtc0 $0, $28\n\t"::); -++ -++ for (addr = K0BASE; addr < (K0BASE + 0x4000); addr += 32) { -++ asm volatile ( -++ ".set mips3\n\t" -++ " cache %0, 0(%1)\n\t" -++ ".set mips2\n\t" -++ : -++ : "I" (Index_Writeback_Inv_D), "r"(addr)); -++ -++ asm volatile ( -++ ".set mips3\n\t" -++ " cache %0, 0(%1)\n\t" -++ ".set mips2\n\t" -++ : -++ : "I" (Index_Store_Tag_I), "r"(addr)); -++ } -++ -++ asm volatile ("sync\n\t"::); -++ -++ /* invalidate BTB */ -++ asm volatile ( -++ ".set mips32\n\t" -++ " mfc0 %0, $16, 7\n\t" -++ " nop\n\t" -++ " ori $0, 2\n\t" -++ " mtc0 %0, $16, 7\n\t" -++ " nop\n\t" -++ ".set mips2\n\t" -++ : -++ : "r"(addr)); -++} -++ -++/* Put CPU to HIBERNATE mode */ -++int jz_pm_suspend(void) -++{ -++ int retval; -++ -++ pm_send_all(PM_SUSPEND, (void *)3); -++ -++ retval = jz_pm_do_suspend(); -++ -++ pm_send_all(PM_RESUME, (void *)0); -++ -++ return retval; -++} -++ -++#if 0 -++/* Put CPU to SLEEP mode */ -++int jz_pm_sleep(void) -++{ -++ return jz_pm_do_sleep(); -++} -++ -++/* Put CPU to IDLE mode, used for dpm in linux 2.4 */ -++void jz_pm_idle(void) -++{ -++ local_irq_disable(); -++ if (!need_resched()) { -++ local_irq_enable(); -++ cpu_wait(); -++ } -++} -++#endif -++ -++#ifdef CONFIG_SYSCTL -++ -++/* -++ * Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6 -++ * when all the PM interfaces exist nicely. -++ */ -++#define CTL_PM_SUSPEND 1 -++#define CTL_PM_HIBERNATE 2 -++ -++/*---------------------------------------------------------------------------- -++ * Power Management sleep sysctl proc interface -++ * -++ * A write to /proc/sys/pm/suspend invokes this function -++ * which initiates a sleep. -++ *--------------------------------------------------------------------------*/ -++static int sysctl_jz_pm_sleep(void) -++{ -++ return jz_pm_suspend(); -++} -++ -++static struct ctl_table pm_table[] = -++{ -++ { -++ .ctl_name = CTL_UNNUMBERED, -++ .procname = "suspend", -++ .data = NULL, -++ .maxlen = 0, -++ .mode = 0600, -++ .proc_handler = &sysctl_jz_pm_sleep, -++ }, -++ { .ctl_name = 0} -++}; -++ -++static struct ctl_table pm_dir_table[] = -++{ -++ { -++ .ctl_name = CTL_UNNUMBERED, -++ .procname = "pm", -++ .mode = 0555, -++ .child = pm_table, -++ }, -++ { .ctl_name = 0} -++}; -++ -++#endif /* CONFIG_SYSCTL */ -++ -++/* -++ * Initialize power interface -++ */ -++static int __init jz_pm_init(void) -++{ -++ printk("Power Management for JZ\n"); -++ -++#ifdef CONFIG_SYSCTL -++ register_sysctl_table(pm_dir_table); -++#endif -++ -++ return 0; -++} -++ -++module_init(jz_pm_init); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4730/proc.c linux-2.6.24.7/arch/mips/jz4730/proc.c -+--- linux-2.6.24.7.old/arch/mips/jz4730/proc.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4730/proc.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,292 @@ -++/* -++ * linux/arch/mips/jz4730/proc.c -++ * -++ * /proc/jz/ procfs for on-chip peripherals. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++struct proc_dir_entry *proc_jz_root; -++ -++/* -++ * EMC Module -++ */ -++static int emc_read_proc (char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ -++ len += sprintf (page+len, "BCR: 0x%08x\n", REG_EMC_BCR); -++ len += sprintf (page+len, "SMCR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SMCR0, REG_EMC_SMCR1, REG_EMC_SMCR2, REG_EMC_SMCR3, REG_EMC_SMCR4, REG_EMC_SMCR5); -++ len += sprintf (page+len, "SACR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SACR0, REG_EMC_SACR1, REG_EMC_SACR2, REG_EMC_SACR3, REG_EMC_SACR4, REG_EMC_SACR5); -++ len += sprintf (page+len, "DMCR: 0x%08x\n", REG_EMC_DMCR); -++ len += sprintf (page+len, "RTCSR: 0x%04x\n", REG_EMC_RTCSR); -++ len += sprintf (page+len, "RTCOR: 0x%04x\n", REG_EMC_RTCOR); -++ len += sprintf (page+len, "DMAR(0-1): 0x%08x 0x%08x\n", REG_EMC_DMAR1, REG_EMC_DMAR2); -++ return len; -++} -++ -++/* -++ * Power Manager Module -++ */ -++static int pmc_read_proc (char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ unsigned long lpcr = REG_CPM_LPCR; -++ unsigned long mscr = REG_CPM_MSCR; -++ -++ len += sprintf (page+len, "LPCR : 0x%08lx\n", lpcr); -++ len += sprintf (page+len, "Low Power Mode : %s\n", -++ ((lpcr & CPM_LPCR_LPM_MASK) == (CPM_LPCR_LPM_IDLE)) ? -++ "idle" : (((lpcr & CPM_LPCR_LPM_MASK) == (CPM_LPCR_LPM_SLEEP)) ? "sleep" : "hibernate")); -++ len += sprintf (page+len, "Doze Mode : %s\n", -++ (lpcr & CPM_LPCR_DOZE) ? "on" : "off"); -++ if (lpcr & CPM_LPCR_DOZE) -++ len += sprintf (page+len, " duty : %d\n", (int)((lpcr & CPM_LPCR_DUTY_MASK) >> CPM_LPCR_DUTY_BIT)); -++ len += sprintf (page+len, "CKO1 : %s\n", -++ (REG_CPM_CFCR & CPM_CFCR_CKOEN1) ? "enable" : "disable"); -++ len += sprintf (page+len, "UART0 : %s\n", -++ (mscr & CPM_MSCR_MSTP_UART0) ? "stopped" : "running"); -++ len += sprintf (page+len, "UART1 : %s\n", -++ (mscr & CPM_MSCR_MSTP_UART1) ? "stopped" : "running"); -++ len += sprintf (page+len, "UART2 : %s\n", -++ (mscr & CPM_MSCR_MSTP_UART2) ? "stopped" : "running"); -++ len += sprintf (page+len, "UART3 : %s\n", -++ (mscr & CPM_MSCR_MSTP_UART3) ? "stopped" : "running"); -++ len += sprintf (page+len, "OST : %s\n", -++ (mscr & CPM_MSCR_MSTP_OST) ? "stopped" : "running"); -++ len += sprintf (page+len, "DMAC : %s\n", -++ (mscr & CPM_MSCR_MSTP_DMAC) ? "stopped" : "running"); -++ len += sprintf (page+len, "ETH : %s\n", -++ (mscr & CPM_MSCR_MSTP_ETH) ? "stopped" : "running"); -++ len += sprintf (page+len, "UHC/UDC : %s\n", -++ (mscr & CPM_MSCR_MSTP_UHC) ? "stopped" : "running"); -++ len += sprintf (page+len, "PWM0 : %s\n", -++ (mscr & CPM_MSCR_MSTP_PWM0) ? "stopped" : "running"); -++ len += sprintf (page+len, "PWM1 : %s\n", -++ (mscr & CPM_MSCR_MSTP_PWM1) ? "stopped" : "running"); -++ len += sprintf (page+len, "I2C : %s\n", -++ (mscr & CPM_MSCR_MSTP_I2C) ? "stopped" : "running"); -++ len += sprintf (page+len, "SSI : %s\n", -++ (mscr & CPM_MSCR_MSTP_SSI) ? "stopped" : "running"); -++ len += sprintf (page+len, "SCC : %s\n", -++ (mscr & CPM_MSCR_MSTP_SCC) ? "stopped" : "running"); -++ return len; -++} -++ -++static int pmc_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data) -++{ -++ REG_CPM_MSCR = simple_strtoul(buffer, 0, 16); -++ return count; -++} -++ -++/* -++ * Clock Generation Module -++ */ -++static int cgm_read_proc (char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ unsigned int cfcr = REG_CPM_CFCR; -++ unsigned int plcr1 = REG_CPM_PLCR1; -++ unsigned int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ unsigned int od[4] = {1, 2, 2, 4}; -++ -++ -++ len += sprintf (page+len, "PLCR1 : 0x%08x\n", plcr1); -++ len += sprintf (page+len, "CFCR : 0x%08x\n", cfcr); -++ len += sprintf (page+len, "PLL : %s\n", -++ (plcr1 & CPM_PLCR1_PLL1EN) ? "ON" : "OFF"); -++ len += sprintf (page+len, "NF:NR:NO : %d:%d:%d\n", -++ __cpm_plcr1_fd() + 2, -++ __cpm_plcr1_rd() + 2, -++ od[__cpm_plcr1_od()] -++ ); -++ len += sprintf (page+len, "I:S:M:P : %d:%d:%d:%d\n", -++ div[(cfcr & CPM_CFCR_IFR_MASK) >> CPM_CFCR_IFR_BIT], -++ div[(cfcr & CPM_CFCR_SFR_MASK) >> CPM_CFCR_SFR_BIT], -++ div[(cfcr & CPM_CFCR_MFR_MASK) >> CPM_CFCR_MFR_BIT], -++ div[(cfcr & CPM_CFCR_PFR_MASK) >> CPM_CFCR_PFR_BIT] -++ ); -++ len += sprintf (page+len, "PLL Freq : %d MHz\n", __cpm_get_pllout()/1000000); -++ len += sprintf (page+len, "ICLK : %d MHz\n", __cpm_get_iclk()/1000000); -++ len += sprintf (page+len, "SCLK : %d MHz\n", __cpm_get_sclk()/1000000); -++ len += sprintf (page+len, "MCLK : %d MHz\n", __cpm_get_mclk()/1000000); -++ len += sprintf (page+len, "PCLK : %d MHz\n", __cpm_get_pclk()/1000000); -++ len += sprintf (page+len, "DEVCLK : %d MHz\n", __cpm_get_devclk()/1000000); -++ len += sprintf (page+len, "RTCCLK : %d KHz\n", __cpm_get_rtcclk()/1000); -++ len += sprintf (page+len, "USBCLK : %d MHz\n", __cpm_get_usbclk()/1000000); -++#if defined(CONFIG_FB_JZ) -++ len += sprintf (page+len, "LCDCLK : %d MHz\n", __cpm_get_lcdclk()/1000000); -++ len += sprintf (page+len, "PIXCLK : %d MHz\n", __cpm_get_pixclk()/1000000); -++#endif -++ return len; -++} -++ -++static int cgm_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -++{ -++ REG_CPM_CFCR = simple_strtoul(buffer, 0, 16); -++ return count; -++} -++ -++/* -++ * WDT -++ */ -++static int wdt_read_proc (char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ -++ len += sprintf (page+len, "WDT_WTCSR : 0x%08x\n", REG_WDT_WTCSR); -++ len += sprintf (page+len, "WDT_WTCNT : 0x%08x\n", REG_WDT_WTCNT); -++ -++ return len; -++} -++ -++static int wdt_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -++{ -++ unsigned long cnt = simple_strtoul(buffer, 0, 16); -++ -++ REG_WDT_WTCNT = cnt; -++ REG_WDT_WTCSR = WDT_WTCSR_START; -++ -++ return count; -++} -++ -++/* -++ * PWM -++ */ -++ -++static int proc_jz_pwm_read_byte(char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ return sprintf (page, "0x%02x\n", REG8(data)); -++} -++ -++static int proc_jz_pwm_read_word(char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ return sprintf (page, "0x%04x\n", REG16(data)); -++} -++ -++static int proc_jz_pwm_write_byte(struct file *file, const char *buffer, unsigned long count, void *data) -++{ -++ REG8(data) = simple_strtoul(buffer, 0, 16); -++ return count; -++} -++ -++static int proc_jz_pwm_write_word(struct file *file, const char *buffer, unsigned long count, void *data) -++{ -++ REG16(data) = simple_strtoul(buffer, 0, 16); -++ return count; -++} -++ -++#define PWM_NUM 2 -++ -++static int jz_pwm_proc_init(void) -++{ -++ struct proc_dir_entry *proc_jz_pwm, *res; -++ char name[16]; -++ unsigned char i; -++ -++ for (i = 0; i < PWM_NUM; i++) { -++ sprintf(name, "pwm%d", i); -++ proc_jz_pwm = proc_mkdir(name, proc_jz_root); -++ res = create_proc_entry("control", 0600, proc_jz_pwm); -++ if ( res) { -++ res->read_proc = proc_jz_pwm_read_byte; -++ res->write_proc = proc_jz_pwm_write_byte; -++ if (i) -++ res->data = (void * )PWM_CTR(1); -++ else -++ res->data = (void * )PWM_CTR(0); -++ } -++ res = create_proc_entry("period", 0600, proc_jz_pwm); -++ if ( res) { -++ res->read_proc = proc_jz_pwm_read_word; -++ res->write_proc = proc_jz_pwm_write_word; -++ if (i) -++ res->data = (void *)PWM_PER(1); -++ else -++ res->data = (void *)PWM_PER(0); -++ } -++ res = create_proc_entry("duty", 0600, proc_jz_pwm); -++ if ( res) { -++ res->read_proc = proc_jz_pwm_read_word; -++ res->write_proc = proc_jz_pwm_write_word; -++ if (i) -++ res->data = (void * )PWM_DUT(1); -++ else -++ res->data = (void * )PWM_DUT(0); -++ } -++ } -++ return 0; -++} -++ -++/* -++ * /proc/jz/xxx entry -++ * -++ */ -++static int __init jz_proc_init(void) -++{ -++ struct proc_dir_entry *entry; -++ -++ /* create /proc/jz */ -++ proc_jz_root = proc_mkdir("jz", 0); -++ -++ /* create /proc/jz/emc */ -++ entry = create_proc_entry("emc", 0644, proc_jz_root); -++ if (entry) { -++ entry->read_proc = emc_read_proc; -++ entry->write_proc = NULL; -++ entry->data = NULL; -++ } -++ -++ /* create /proc/jz/pmc */ -++ entry = create_proc_entry("pmc", 0644, proc_jz_root); -++ if (entry) { -++ entry->read_proc = pmc_read_proc; -++ entry->write_proc = pmc_write_proc; -++ entry->data = NULL; -++ } -++ -++ /* create /proc/jz/cgm */ -++ entry = create_proc_entry("cgm", 0644, proc_jz_root); -++ if (entry) { -++ entry->read_proc = cgm_read_proc; -++ entry->write_proc = cgm_write_proc; -++ entry->data = NULL; -++ } -++ -++ /* create /proc/jz/wdt */ -++ entry = create_proc_entry("wdt", 0644, proc_jz_root); -++ if (entry) { -++ entry->read_proc = wdt_read_proc; -++ entry->write_proc = wdt_write_proc; -++ entry->data = NULL; -++ } -++ -++ /* PWM */ -++ jz_pwm_proc_init(); -++ -++ return 0; -++} -++ -++__initcall(jz_proc_init); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4730/prom.c linux-2.6.24.7/arch/mips/jz4730/prom.c -+--- linux-2.6.24.7.old/arch/mips/jz4730/prom.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4730/prom.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,198 @@ -++/* -++ * -++ * BRIEF MODULE DESCRIPTION -++ * PROM library initialisation code, supports YAMON and U-Boot. -++ * -++ * Copyright 2000, 2001, 2006 MontaVista Software Inc. -++ * Author: MontaVista Software, Inc. -++ * ppopov@mvista.com or source@mvista.com -++ * -++ * This file was derived from Carsten Langgaard's -++ * arch/mips/mips-boards/xx files. -++ * -++ * Carsten Langgaard, carstenl@mips.com -++ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ * -++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++/* #define DEBUG_CMDLINE */ -++ -++int prom_argc; -++char **prom_argv, **prom_envp; -++ -++char * prom_getcmdline(void) -++{ -++ return &(arcs_cmdline[0]); -++} -++ -++void prom_init_cmdline(void) -++{ -++ char *cp; -++ int actr; -++ -++ actr = 1; /* Always ignore argv[0] */ -++ -++ cp = &(arcs_cmdline[0]); -++ while(actr < prom_argc) { -++ strcpy(cp, prom_argv[actr]); -++ cp += strlen(prom_argv[actr]); -++ *cp++ = ' '; -++ actr++; -++ } -++ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ -++ --cp; -++ if (prom_argc > 1) -++ *cp = '\0'; -++ -++} -++ -++ -++char *prom_getenv(char *envname) -++{ -++#if 0 -++ /* -++ * Return a pointer to the given environment variable. -++ * YAMON uses "name", "value" pairs, while U-Boot uses "name=value". -++ */ -++ -++ char **env = prom_envp; -++ int i = strlen(envname); -++ int yamon = (*env && strchr(*env, '=') == NULL); -++ -++ while (*env) { -++ if (yamon) { -++ if (strcmp(envname, *env++) == 0) -++ return *env; -++ } else { -++ if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=') -++ return *env + i + 1; -++ } -++ env++; -++ } -++#endif -++ return NULL; -++} -++ -++inline unsigned char str2hexnum(unsigned char c) -++{ -++ if(c >= '0' && c <= '9') -++ return c - '0'; -++ if(c >= 'a' && c <= 'f') -++ return c - 'a' + 10; -++ if(c >= 'A' && c <= 'F') -++ return c - 'A' + 10; -++ return 0; /* foo */ -++} -++ -++inline void str2eaddr(unsigned char *ea, unsigned char *str) -++{ -++ int i; -++ -++ for(i = 0; i < 6; i++) { -++ unsigned char num; -++ -++ if((*str == '.') || (*str == ':')) -++ str++; -++ num = str2hexnum(*str++) << 4; -++ num |= (str2hexnum(*str++)); -++ ea[i] = num; -++ } -++} -++ -++int get_ethernet_addr(char *ethernet_addr) -++{ -++ char *ethaddr_str; -++ -++ ethaddr_str = prom_getenv("ethaddr"); -++ if (!ethaddr_str) { -++ printk("ethaddr not set in boot prom\n"); -++ return -1; -++ } -++ str2eaddr(ethernet_addr, ethaddr_str); -++ -++#if 0 -++ { -++ int i; -++ -++ printk("get_ethernet_addr: "); -++ for (i=0; i<5; i++) -++ printk("%02x:", (unsigned char)*(ethernet_addr+i)); -++ printk("%02x\n", *(ethernet_addr+i)); -++ } -++#endif -++ -++ return 0; -++} -++ -++void __init prom_free_prom_memory(void) -++{ -++} -++ -++void __init prom_init(void) -++{ -++ unsigned char *memsize_str; -++ unsigned long memsize; -++ -++ prom_argc = (int) fw_arg0; -++ prom_argv = (char **) fw_arg1; -++ prom_envp = (char **) fw_arg2; -++ -++ mips_machtype = MACH_INGENIC_JZ4730; -++ -++ prom_init_cmdline(); -++ memsize_str = prom_getenv("memsize"); -++ if (!memsize_str) { -++ memsize = 0x04000000; -++ } else { -++ memsize = simple_strtol(memsize_str, NULL, 0); -++ } -++ add_memory_region(0, memsize, BOOT_MEM_RAM); -++} -++ -++/* used by early printk */ -++void prom_putchar(char c) -++{ -++ volatile u8 *uart_lsr = (volatile u8 *)(UART3_BASE + OFF_LSR); -++ volatile u8 *uart_tdr = (volatile u8 *)(UART3_BASE + OFF_TDR); -++ -++ /* Wait for fifo to shift out some bytes */ -++ while ( !((*uart_lsr & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60) ); -++ -++ *uart_tdr = (u8)c; -++} -++ -++const char *get_system_type(void) -++{ -++ return "JZ4730"; -++} -++ -++EXPORT_SYMBOL(prom_getcmdline); -++EXPORT_SYMBOL(get_ethernet_addr); -++EXPORT_SYMBOL(str2eaddr); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4730/reset.c linux-2.6.24.7/arch/mips/jz4730/reset.c -+--- linux-2.6.24.7.old/arch/mips/jz4730/reset.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4730/reset.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,40 @@ -++/* -++ * linux/arch/mips/jz4730/reset.c -++ * -++ * JZ4730 reset routines. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++void jz_restart(char *command) -++{ -++ __wdt_set_count(0xffffffff-32); /* reset after 1/1024 s */ -++ __wdt_start(); -++ while (1); -++} -++ -++void jz_halt(void) -++{ -++ __wdt_set_count(0xffffffff-32); /* reset after 1/1024 s */ -++ __wdt_start(); -++ while (1); -++} -++ -++void jz_power_off(void) -++{ -++ jz_halt(); -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4730/setup.c linux-2.6.24.7/arch/mips/jz4730/setup.c -+--- linux-2.6.24.7.old/arch/mips/jz4730/setup.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4730/setup.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,182 @@ -++/* -++ * linux/arch/mips/jz4730/setup.c -++ * -++ * JZ4730 CPU common setup routines. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#ifdef CONFIG_PC_KEYB -++#include -++#endif -++ -++jz_clocks_t jz_clocks; -++ -++extern char * __init prom_getcmdline(void); -++extern void __init jz_board_setup(void); -++extern void jz_restart(char *); -++extern void jz_halt(void); -++extern void jz_power_off(void); -++extern void jz_time_init(void); -++ -++static void __init sysclocks_setup(void) -++{ -++#ifndef CONFIG_JZ4730_URANUS -++ jz_clocks.iclk = __cpm_get_iclk(); -++ jz_clocks.sclk = __cpm_get_sclk(); -++ jz_clocks.mclk = __cpm_get_mclk(); -++ jz_clocks.pclk = __cpm_get_pclk(); -++ jz_clocks.devclk = __cpm_get_devclk(); -++ jz_clocks.rtcclk = __cpm_get_rtcclk(); -++ jz_clocks.uartclk = __cpm_get_uartclk(); -++ jz_clocks.lcdclk = __cpm_get_lcdclk(); -++ jz_clocks.pixclk = __cpm_get_pixclk(); -++ jz_clocks.usbclk = __cpm_get_usbclk(); -++ jz_clocks.i2sclk = __cpm_get_i2sclk(); -++ jz_clocks.mscclk = __cpm_get_mscclk(); -++#else /* URANUS FPGA */ -++ -++#define FPGACLK 8000000 -++ -++ jz_clocks.iclk = FPGACLK; -++ jz_clocks.sclk = FPGACLK; -++ jz_clocks.mclk = FPGACLK; -++ jz_clocks.devclk = FPGACLK; -++ jz_clocks.rtcclk = FPGACLK; -++ jz_clocks.uartclk = FPGACLK; -++ jz_clocks.pixclk = FPGACLK; -++ jz_clocks.lcdclk = FPGACLK; -++ jz_clocks.usbclk = FPGACLK; -++ jz_clocks.i2sclk = FPGACLK; -++ jz_clocks.mscclk = FPGACLK; -++#endif -++ -++ printk("CPU clock: %dMHz, System clock: %dMHz, Memory clock: %dMHz, Peripheral clock: %dMHz\n", -++ (jz_clocks.iclk + 500000) / 1000000, -++ (jz_clocks.sclk + 500000) / 1000000, -++ (jz_clocks.mclk + 500000) / 1000000, -++ (jz_clocks.pclk + 500000) / 1000000); -++} -++ -++static void __init soc_cpm_setup(void) -++{ -++ __cpm_idle_mode(); -++ __cpm_enable_cko1(); -++ __cpm_start_all(); -++ -++ /* get system clocks */ -++ sysclocks_setup(); -++} -++ -++static void __init soc_harb_setup(void) -++{ -++// __harb_set_priority(0x00); /* CIM>LCD>DMA>ETH>PCI>USB>CBB */ -++// __harb_set_priority(0x03); /* LCD>CIM>DMA>ETH>PCI>USB>CBB */ -++ __harb_set_priority(0x08); /* DMAC>LCD>CIM>ETH>USB>CIM */ -++// __harb_set_priority(0x0a); /* ETH>LCD>CIM>DMA>PCI>USB>CBB */ -++} -++ -++static void __init soc_emc_setup(void) -++{ -++} -++ -++static void __init soc_dmac_setup(void) -++{ -++ __dmac_enable_all_channels(); -++} -++ -++static void __init jz_soc_setup(void) -++{ -++ soc_cpm_setup(); -++ soc_harb_setup(); -++ soc_emc_setup(); -++ soc_dmac_setup(); -++} -++ -++static void __init jz_serial_setup(void) -++{ -++#ifdef CONFIG_SERIAL_8250 -++ struct uart_port s; -++ -++ memset(&s, 0, sizeof(s)); -++ -++ s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; -++ s.iotype = UPIO_MEM; -++ s.regshift = 2; -++ s.uartclk = jz_clocks.uartclk; -++ -++ s.line = 0; -++ s.membase = (u8 *)UART0_BASE; -++ s.irq = IRQ_UART0; -++ if (early_serial_setup(&s) != 0) { -++ printk(KERN_ERR "Serial ttyS0 setup failed!\n"); -++ } -++ -++ s.line = 1; -++ s.membase = (u8 *)UART1_BASE; -++ s.irq = IRQ_UART1; -++ if (early_serial_setup(&s) != 0) { -++ printk(KERN_ERR "Serial ttyS1 setup failed!\n"); -++ } -++ -++ s.line = 2; -++ s.membase = (u8 *)UART2_BASE; -++ s.irq = IRQ_UART2; -++ if (early_serial_setup(&s) != 0) { -++ printk(KERN_ERR "Serial ttyS2 setup failed!\n"); -++ } -++ -++ s.line = 3; -++ s.membase = (u8 *)UART3_BASE; -++ s.irq = IRQ_UART3; -++ if (early_serial_setup(&s) != 0) { -++ printk(KERN_ERR "Serial ttyS3 setup failed!\n"); -++ } -++#endif -++} -++ -++void __init plat_mem_setup(void) -++{ -++ char *argptr; -++ -++ argptr = prom_getcmdline(); -++ -++ /* IO/MEM resources. */ -++ set_io_port_base(0); -++ ioport_resource.start = 0x00000000; -++ ioport_resource.end = 0xffffffff; -++ iomem_resource.start = 0x00000000; -++ iomem_resource.end = 0xffffffff; -++ -++ _machine_restart = jz_restart; -++ _machine_halt = jz_halt; -++ pm_power_off = jz_power_off; -++ -++ jz_soc_setup(); /* soc specific setup */ -++ jz_serial_setup(); /* serial port setup */ -++ jz_board_setup(); /* board specific setup */ -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4730/sleep.S linux-2.6.24.7/arch/mips/jz4730/sleep.S -+--- linux-2.6.24.7.old/arch/mips/jz4730/sleep.S 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4730/sleep.S 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,307 @@ -++/* -++ * linux/arch/mips/jz4730/sleep.S -++ * -++ * jz4730 Assembler Sleep/WakeUp Management Routines -++ * -++ * Copyright (C) 2005 Ingenic Semiconductor -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ */ -++ -++#include -++#include -++#include -++ -++ .text -++ .set noreorder -++ .set noat -++ -++ .extern jz_flush_cache_all -++ -++/* -++ * jz_cpu_suspend() -++ * -++ * Forces CPU into hibernate mode -++ */ -++ -++ .globl jz_cpu_suspend -++jz_cpu_suspend: -++ -++ /* save hi, lo and general registers except k0($26) and k1($27) (total 32) */ -++ move k0, sp -++ addiu k0, k0, -(32*4) -++ mfhi k1 -++ sw $0, 0(k0) -++ sw $1, 4(k0) -++ sw k1, 120(k0) /* hi */ -++ mflo k1 -++ sw $2, 8(k0) -++ sw $3, 12(k0) -++ sw k1, 124(k0) /* lo */ -++ sw $4, 16(k0) -++ sw $5, 20(k0) -++ sw $6, 24(k0) -++ sw $7, 28(k0) -++ sw $8, 32(k0) -++ sw $9, 36(k0) -++ sw $10, 40(k0) -++ sw $11, 44(k0) -++ sw $12, 48(k0) -++ sw $13, 52(k0) -++ sw $14, 56(k0) -++ sw $15, 60(k0) -++ sw $16, 64(k0) -++ sw $17, 68(k0) -++ sw $18, 72(k0) -++ sw $19, 76(k0) -++ sw $20, 80(k0) -++ sw $21, 84(k0) -++ sw $22, 88(k0) -++ sw $23, 92(k0) -++ sw $24, 96(k0) -++ sw $25, 100(k0) -++ sw $28, 104(k0) -++ sw $29, 108(k0) /* saved sp */ -++ sw $30, 112(k0) -++ sw $31, 116(k0) /* saved ra */ -++ move sp, k0 -++ -++ /* save CP0 registers and sp (total 26) */ -++ move k0, sp -++ addiu k0, k0, -(26*4) -++ -++ mfc0 $1, CP0_INDEX -++ mfc0 $2, CP0_RANDOM -++ mfc0 $3, CP0_ENTRYLO0 -++ mfc0 $4, CP0_ENTRYLO1 -++ mfc0 $5, CP0_CONTEXT -++ mfc0 $6, CP0_PAGEMASK -++ mfc0 $7, CP0_WIRED -++ mfc0 $8, CP0_BADVADDR -++ mfc0 $9, CP0_ENTRYHI -++ mfc0 $10, CP0_STATUS -++/* mfc0 $11, $12, 1*/ /* IntCtl */ -++ mfc0 $12, CP0_CAUSE -++ mfc0 $13, CP0_EPC -++/* mfc0 $14, $15, 1*/ /* EBase */ -++ mfc0 $15, CP0_CONFIG -++/* mfc0 $16, CP0_CONFIG, 7*/ /* Config 7 */ -++ mfc0 $17, CP0_LLADDR -++ mfc0 $18, CP0_WATCHLO -++ mfc0 $19, CP0_WATCHHI -++ mfc0 $20, CP0_DEBUG -++ mfc0 $21, CP0_DEPC -++ mfc0 $22, CP0_ECC -++ mfc0 $23, CP0_TAGLO -++ mfc0 $24, CP0_ERROREPC -++ mfc0 $25, CP0_DESAVE -++ -++ sw $1, 0(k0) -++ sw $2, 4(k0) -++ sw $3, 8(k0) -++ sw $4, 12(k0) -++ sw $5, 16(k0) -++ sw $6, 20(k0) -++ sw $7, 24(k0) -++ sw $8, 28(k0) -++ sw $9, 32(k0) -++ sw $10, 36(k0) -++ sw $11, 40(k0) -++ sw $12, 44(k0) -++ sw $13, 48(k0) -++ sw $14, 52(k0) -++ sw $15, 56(k0) -++ sw $16, 60(k0) -++ sw $17, 64(k0) -++ sw $18, 68(k0) -++ sw $19, 72(k0) -++ sw $20, 76(k0) -++ sw $21, 80(k0) -++ sw $22, 84(k0) -++ sw $23, 88(k0) -++ sw $24, 92(k0) -++ sw $25, 96(k0) -++ sw $29, 100(k0) /* saved sp */ -++ move sp, k0 -++ -++ /* preserve virtual address of stack */ -++ la k0, suspend_save_sp -++ sw sp, 0(k0) -++ -++ /* flush caches and write buffers */ -++ jal jz_flush_cache_all -++ nop -++ -++ /* set new sdram refresh constant */ -++ li t0, 1 -++ la t1, EMC_RTCOR -++ sh t0, 0(t1) -++ -++ /* disable PLL */ -++ la t0, CPM_PLCR1 -++ sw $0, 0(t0) -++ -++ /* put CPU to hibernate mode */ -++ la t0, CPM_LPCR -++ lw t1, 0(t0) -++ li t2, ~CPM_LPCR_LPM_MASK -++ and t1, t2 -++ ori t1, CPM_LPCR_LPM_HIBERNATE -++ -++ .align 5 -++ /* align execution to a cache line */ -++ j 1f -++ -++ .align 5 -++1: -++ /* all needed values are now in registers. -++ * These last instructions should be in cache -++ */ -++ nop -++ nop -++ -++ /* set hibernate mode */ -++ sw t1, 0(t0) -++ nop -++ -++ /* enter hibernate mode */ -++ .set mips3 -++ wait -++ nop -++ .set mips2 -++ -++2: j 2b /* loop waiting for suspended */ -++ nop -++ -++/* -++ * jz_cpu_resume() -++ * -++ * entry point from bootloader into kernel during resume -++ */ -++ -++ .align 5 -++ .globl jz_cpu_resume -++jz_cpu_resume: -++ /* clear SCR.HGP */ -++ la t0, CPM_SCR -++ lw t1, 0(t0) -++ li t2, ~CPM_SCR_HGP -++ and t1, t2 -++ sw t1, 0(t0) -++ -++ /* restore LPCR.LPM to IDLE mode */ -++ la t0, CPM_LPCR -++ lw t1, 0(t0) -++ li t2, ~CPM_LPCR_LPM_MASK -++ and t1, t2 -++ ori t1, CPM_LPCR_LPM_IDLE -++ sw t1, 0(t0) -++ -++ /* restore saved sp */ -++ la t0, suspend_save_sp -++ lw sp, 0(t0) -++ -++ /* restore CP0 registers */ -++ move k0, sp -++ lw $1, 0(k0) -++ lw $2, 4(k0) -++ lw $3, 8(k0) -++ lw $4, 12(k0) -++ lw $5, 16(k0) -++ lw $6, 20(k0) -++ lw $7, 24(k0) -++ lw $8, 28(k0) -++ lw $9, 32(k0) -++ lw $10, 36(k0) -++ lw $11, 40(k0) -++ lw $12, 44(k0) -++ lw $13, 48(k0) -++ lw $14, 52(k0) -++ lw $15, 56(k0) -++ lw $16, 60(k0) -++ lw $17, 64(k0) -++ lw $18, 68(k0) -++ lw $19, 72(k0) -++ lw $20, 76(k0) -++ lw $21, 80(k0) -++ lw $22, 84(k0) -++ lw $23, 88(k0) -++ lw $24, 92(k0) -++ lw $25, 96(k0) -++ lw $29, 100(k0) /* saved sp */ -++ -++ mtc0 $1, CP0_INDEX -++ mtc0 $2, CP0_RANDOM -++ mtc0 $3, CP0_ENTRYLO0 -++ mtc0 $4, CP0_ENTRYLO1 -++ mtc0 $5, CP0_CONTEXT -++ mtc0 $6, CP0_PAGEMASK -++ mtc0 $7, CP0_WIRED -++ mtc0 $8, CP0_BADVADDR -++ mtc0 $9, CP0_ENTRYHI -++ mtc0 $10, CP0_STATUS -++/* mtc0 $11, $12, 1*/ /* IntCtl */ -++ mtc0 $12, CP0_CAUSE -++ mtc0 $13, CP0_EPC -++/* mtc0 $14, $15, 1*/ /* EBase */ -++ mtc0 $15, CP0_CONFIG -++/* mtc0 $16, CP0_CONFIG, 7*/ /* Config 7 */ -++ mtc0 $17, CP0_LLADDR -++ mtc0 $18, CP0_WATCHLO -++ mtc0 $19, CP0_WATCHHI -++ mtc0 $20, CP0_DEBUG -++ mtc0 $21, CP0_DEPC -++ mtc0 $22, CP0_ECC -++ mtc0 $23, CP0_TAGLO -++ mtc0 $24, CP0_ERROREPC -++ mtc0 $25, CP0_DESAVE -++ -++ /* restore general registers */ -++ move k0, sp -++ lw k1, 120(k0) /* hi */ -++ lw $0, 0(k0) -++ lw $1, 4(k0) -++ mthi k1 -++ lw k1, 124(k0) /* lo */ -++ lw $2, 8(k0) -++ lw $3, 12(k0) -++ mtlo k1 -++ lw $4, 16(k0) -++ lw $5, 20(k0) -++ lw $6, 24(k0) -++ lw $7, 28(k0) -++ lw $8, 32(k0) -++ lw $9, 36(k0) -++ lw $10, 40(k0) -++ lw $11, 44(k0) -++ lw $12, 48(k0) -++ lw $13, 52(k0) -++ lw $14, 56(k0) -++ lw $15, 60(k0) -++ lw $16, 64(k0) -++ lw $17, 68(k0) -++ lw $18, 72(k0) -++ lw $19, 76(k0) -++ lw $20, 80(k0) -++ lw $21, 84(k0) -++ lw $22, 88(k0) -++ lw $23, 92(k0) -++ lw $24, 96(k0) -++ lw $25, 100(k0) -++ lw $28, 104(k0) -++ lw $29, 108(k0) /* saved sp */ -++ lw $30, 112(k0) -++ lw $31, 116(k0) /* saved ra */ -++ -++ /* return to caller */ -++ jr ra -++ nop -++ -++suspend_save_sp: -++ .word 0 /* preserve sp here */ -++ -++ .set reorder -+diff -urN linux-2.6.24.7.old/arch/mips/jz4730/time.c linux-2.6.24.7/arch/mips/jz4730/time.c -+--- linux-2.6.24.7.old/arch/mips/jz4730/time.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4730/time.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,129 @@ -++/* -++ * linux/arch/mips/jz4730/time.c -++ * -++ * Setting up the clock on the JZ4730 boards. -++ * -++ * Copyright (c) 2006-2008 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#define JZ_TIMER_CHAN 0 -++#define JZ_TIMER_IRQ IRQ_OST0 -++#define JZ_TIMER_CLOCK JZ_EXTAL -++ -++static unsigned int timer_latch; -++ -++void (*jz_timer_callback)(void); -++ -++static void jz_set_mode(enum clock_event_mode mode, -++ struct clock_event_device *evt) -++{ -++ switch (mode) { -++ case CLOCK_EVT_MODE_PERIODIC: -++ break; -++ case CLOCK_EVT_MODE_ONESHOT: -++ case CLOCK_EVT_MODE_UNUSED: -++ case CLOCK_EVT_MODE_SHUTDOWN: -++ break; -++ case CLOCK_EVT_MODE_RESUME: -++ break; -++ } -++} -++ -++static struct clock_event_device jz_clockevent_device = { -++ .name = "jz-timer", -++ .features = CLOCK_EVT_FEAT_PERIODIC, -++ -++ /* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */ -++ -++ .rating = 300, -++ .irq = JZ_TIMER_IRQ, -++ .set_mode = jz_set_mode, -++}; -++ -++static irqreturn_t jz_timer_interrupt(int irq, void *dev_id) -++{ -++ struct clock_event_device *cd = dev_id; -++ -++ __ost_clear_uf(JZ_TIMER_CHAN); /* ACK timer */ -++ -++ if (jz_timer_callback) -++ jz_timer_callback(); -++ -++ cd->event_handler(cd); -++ -++ return IRQ_HANDLED; -++} -++ -++static struct irqaction jz_irqaction = { -++ .handler = jz_timer_interrupt, -++ .flags = IRQF_DISABLED | IRQF_PERCPU, -++ .name = "jz-timer", -++}; -++ -++cycle_t jz_get_cycles(void) -++{ -++ unsigned int jz_timer_cnt; -++#if 0 /* clock source use pll, read directly */ -++ jz_timer_cnt = timer_latch - REG_OST_TCNT(JZ_TIMER_CHAN); -++#else /* clock source use RTCClock or Extall Clock, wait read ready */ -++ jz_timer_cnt = REG_OST_TCNT(JZ_TIMER_CHAN); /* dummy read */ -++ while ( __ost_is_busy(JZ_TIMER_CHAN) ) ; /* wait read ready */ -++ jz_timer_cnt = timer_latch - REG_OST_TCRB(JZ_TIMER_CHAN); -++#endif -++ -++ /* convert jiffes to jz timer cycles */ -++ return (cycle_t)( jiffies*((JZ_TIMER_CLOCK)/HZ) + jz_timer_cnt); -++} -++ -++static struct clocksource clocksource_jz = { -++ .name = "jz_clocksource", -++ .rating = 300, -++ .read = jz_get_cycles, -++ .mask = 0xFFFFFFFF, -++ .shift = 10, /* control clocksource.mult's accuracy */ -++ .flags = CLOCK_SOURCE_WATCHDOG, -++}; -++ -++static int __init jz_clocksource_init(void) -++{ -++ clocksource_jz.mult = clocksource_hz2mult(JZ_TIMER_CLOCK, clocksource_jz.shift); -++ clocksource_register(&clocksource_jz); -++ return 0; -++} -++ -++static void __init jz_timer_setup(void) -++{ -++ struct clock_event_device *cd = &jz_clockevent_device; -++ struct irqaction *action = &jz_irqaction; -++ unsigned int cpu = smp_processor_id(); -++ -++ jz_clocksource_init(); -++ cd->cpumask = cpumask_of_cpu(cpu); -++ clockevents_register_device(cd); -++ action->dev_id = cd; -++ setup_irq(JZ_TIMER_IRQ, &jz_irqaction); -++} -++ -++void __init plat_time_init(void) -++{ -++ /* Init timer, timer clock soure use extal clock */ -++ timer_latch = (JZ_TIMER_CLOCK + (HZ>>1)) / HZ; -++ __ost_set_mode(JZ_TIMER_CHAN, OST_TCSR_UIE | OST_TCSR_CKS_EXTAL); -++ __ost_set_reload(JZ_TIMER_CHAN, timer_latch); -++ __ost_set_count(JZ_TIMER_CHAN, timer_latch); -++ __ost_enable_channel(JZ_TIMER_CHAN); -++ -++ jz_timer_setup(); -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4740/Makefile linux-2.6.24.7/arch/mips/jz4740/Makefile -+--- linux-2.6.24.7.old/arch/mips/jz4740/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4740/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,26 @@ -++# -++# Makefile for the Ingenic JZ4740. -++# -++ -++# Object file lists. -++ -++obj-y += prom.o irq.o time.o reset.o setup.o dma.o \ -++ platform.o i2c.o -++ -++obj-$(CONFIG_PROC_FS) += proc.o -++ -++# board specific support -++ -++obj-$(CONFIG_JZ4740_PAVO) += board-pavo.o -++obj-$(CONFIG_JZ4740_LEO) += board-leo.o -++obj-$(CONFIG_JZ4740_LYRA) += board-lyra.o -++obj-$(CONFIG_JZ4725_DIPPER) += board-dipper.o -++obj-$(CONFIG_JZ4720_VIRGO) += board-virgo.o -++ -++# PM support -++ -++obj-$(CONFIG_PM_LEGACY) +=pm.o -++ -++# CPU Frequency scaling support -++ -++obj-$(CONFIG_CPU_FREQ_JZ) +=cpufreq.o -+diff -urN linux-2.6.24.7.old/arch/mips/jz4740/board-dipper.c linux-2.6.24.7/arch/mips/jz4740/board-dipper.c -+--- linux-2.6.24.7.old/arch/mips/jz4740/board-dipper.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4740/board-dipper.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,117 @@ -++/* -++ * linux/arch/mips/jz4740/board-dipper.c -++ * -++ * JZ4725 Dipper board setup routines. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include -++ -++extern void (*jz_timer_callback)(void); -++ -++#if 0 -++static void dancing(void) -++{ -++ static unsigned int count = 0; -++ -++ count ++; -++ count &= 1; -++ -++ if (count) -++ __gpio_set_pin(GPIO_LED_EN); -++ else -++ __gpio_clear_pin(GPIO_LED_EN); -++} -++#endif -++ -++static void dipper_timer_callback(void) -++{ -++ static unsigned long count = 0; -++ -++ if ((++count) % 50 == 0) { -++// dancing(); -++ count = 0; -++ } -++} -++ -++static void __init board_cpm_setup(void) -++{ -++ /* Stop unused module clocks here. -++ * We have started all module clocks at arch/mips/jz4740/setup.c. -++ */ -++} -++ -++static void __init board_gpio_setup(void) -++{ -++ /* -++ * Most of the GPIO pins should have been initialized by the boot-loader -++ */ -++ -++ /* -++ * Initialize MSC pins -++ */ -++ __gpio_as_msc(); -++ -++ /* -++ * Initialize Smart LCD pins -++ */ -++// __gpio_as_slcd_18bit(); -++ -++ /* -++ * Initialize SSI pins -++ */ -++ __gpio_as_ssi(); -++ -++ /* -++ * Initialize I2C pins -++ */ -++ __gpio_as_i2c(); -++ -++ /* -++ * Initialize Other pins -++ */ -++ __gpio_as_output(GPIO_SD_VCC_EN_N); -++ __gpio_clear_pin(GPIO_SD_VCC_EN_N); -++ -++ __gpio_as_input(GPIO_SD_CD_N); -++ __gpio_disable_pull(GPIO_SD_CD_N); -++ -++ __gpio_as_input(GPIO_SD_WP); -++ __gpio_disable_pull(GPIO_SD_WP); -++ -++ __gpio_as_input(GPIO_DC_DETE_N); -++ __gpio_as_input(GPIO_CHARG_STAT_N); -++ __gpio_as_input(GPIO_USB_DETE); -++ -++ __gpio_as_output(GPIO_DISP_OFF_N); -++ -++// __gpio_as_output(GPIO_LED_EN); -++} -++ -++void __init jz_board_setup(void) -++{ -++ printk("JZ4725 DIPPER board setup\n"); -++ -++ board_cpm_setup(); -++ board_gpio_setup(); -++ -++ jz_timer_callback = dipper_timer_callback; -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4740/board-leo.c linux-2.6.24.7/arch/mips/jz4740/board-leo.c -+--- linux-2.6.24.7.old/arch/mips/jz4740/board-leo.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4740/board-leo.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,67 @@ -++/* -++ * linux/arch/mips/jz4740/board-leo.c -++ * -++ * JZ4740 LEO board setup routines. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include -++ -++extern void (*jz_timer_callback)(void); -++ -++static void dancing(void) -++{ -++ static unsigned char slash[] = "\\|/-"; -++ static volatile unsigned char *p = (unsigned char *)0xb6000016; -++ static unsigned int count = 0; -++ *p = slash[count++]; -++ count &= 3; -++} -++ -++static void leo_timer_callback(void) -++{ -++ static unsigned long count = 0; -++ -++ if ((++count) % 10 == 0) { -++ dancing(); -++ count = 0; -++ } -++} -++ -++static void __init board_cpm_setup(void) -++{ -++ /* Stop unused module clocks here. -++ * We have started all module clocks at arch/mips/jz4740/setup.c. -++ */ -++} -++ -++static void __init board_gpio_setup(void) -++{ -++ /* All GPIO pins should have been initialized by the boot-loader */ -++} -++ -++void __init jz_board_setup(void) -++{ -++ board_cpm_setup(); -++ board_gpio_setup(); -++ printk(" BOARD SETUP"); -++ jz_timer_callback = leo_timer_callback; -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4740/board-lyra.c linux-2.6.24.7/arch/mips/jz4740/board-lyra.c -+--- linux-2.6.24.7.old/arch/mips/jz4740/board-lyra.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4740/board-lyra.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,114 @@ -++/* -++ * linux/arch/mips/jz4740/board-lyra.c -++ * -++ * JZ4740 LYRA board setup routines. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include -++ -++extern void (*jz_timer_callback)(void); -++ -++static void dancing(void) -++{ -++ static unsigned int count = 0; -++ -++ count ++; -++ count &= 1; -++ if (count) -++ __gpio_set_pin(GPIO_LED_EN); -++ else -++ __gpio_clear_pin(GPIO_LED_EN); -++} -++ -++static void lyra_timer_callback(void) -++{ -++ static unsigned long count = 0; -++ -++ if ((++count) % 50 == 0) { -++ dancing(); -++ count = 0; -++ } -++} -++ -++static void __init board_cpm_setup(void) -++{ -++ /* Stop unused module clocks here. -++ * We have started all module clocks at arch/mips/jz4740/setup.c. -++ */ -++} -++ -++static void __init board_gpio_setup(void) -++{ -++ /* -++ * Most of the GPIO pins should have been initialized by the boot-loader -++ */ -++ -++ /* -++ * Initialize MSC pins -++ */ -++ __gpio_as_msc(); -++ -++ /* -++ * Initialize LCD pins -++ */ -++ __gpio_as_lcd_18bit(); -++ -++ /* -++ * Initialize SSI pins -++ */ -++ __gpio_as_ssi(); -++ -++ /* -++ * Initialize I2C pins -++ */ -++ __gpio_as_i2c(); -++ -++ /* -++ * Initialize Other pins -++ */ -++ __gpio_as_output(GPIO_SD_VCC_EN_N); -++ __gpio_clear_pin(GPIO_SD_VCC_EN_N); -++ -++ __gpio_as_input(GPIO_SD_CD_N); -++ __gpio_disable_pull(GPIO_SD_CD_N); -++ -++ __gpio_as_input(GPIO_SD_WP); -++ __gpio_disable_pull(GPIO_SD_WP); -++ -++ __gpio_as_input(GPIO_DC_DETE_N); -++ __gpio_as_input(GPIO_CHARG_STAT_N); -++ __gpio_as_input(GPIO_USB_DETE); -++ -++ __gpio_as_output(GPIO_DISP_OFF_N); -++ -++ __gpio_as_output(GPIO_LED_EN); -++} -++ -++void __init jz_board_setup(void) -++{ -++ printk("JZ4740 LYRA board setup\n"); -++ -++ board_cpm_setup(); -++ board_gpio_setup(); -++ -++ jz_timer_callback = lyra_timer_callback; -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4740/board-pavo.c linux-2.6.24.7/arch/mips/jz4740/board-pavo.c -+--- linux-2.6.24.7.old/arch/mips/jz4740/board-pavo.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4740/board-pavo.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,114 @@ -++/* -++ * linux/arch/mips/jz4740/board-pavo.c -++ * -++ * JZ4740 PAVO board setup routines. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include -++ -++extern void (*jz_timer_callback)(void); -++ -++static void dancing(void) -++{ -++ static unsigned int count = 0; -++ -++ count ++; -++ count &= 1; -++ if (count) -++ __gpio_set_pin(GPIO_LED_EN); -++ else -++ __gpio_clear_pin(GPIO_LED_EN); -++} -++ -++static void pavo_timer_callback(void) -++{ -++ static unsigned long count = 0; -++ -++ if ((++count) % 50 == 0) { -++ dancing(); -++ count = 0; -++ } -++} -++ -++static void __init board_cpm_setup(void) -++{ -++ /* Stop unused module clocks here. -++ * We have started all module clocks at arch/mips/jz4740/setup.c. -++ */ -++} -++ -++static void __init board_gpio_setup(void) -++{ -++ /* -++ * Most of the GPIO pins should have been initialized by the boot-loader -++ */ -++ -++ /* -++ * Initialize MSC pins -++ */ -++ __gpio_as_msc(); -++ -++ /* -++ * Initialize LCD pins -++ */ -++ __gpio_as_lcd_18bit(); -++ -++ /* -++ * Initialize SSI pins -++ */ -++ __gpio_as_ssi(); -++ -++ /* -++ * Initialize I2C pins -++ */ -++ __gpio_as_i2c(); -++ -++ /* -++ * Initialize Other pins -++ */ -++ __gpio_as_output(GPIO_SD_VCC_EN_N); -++ __gpio_clear_pin(GPIO_SD_VCC_EN_N); -++ -++ __gpio_as_input(GPIO_SD_CD_N); -++ __gpio_disable_pull(GPIO_SD_CD_N); -++ -++ __gpio_as_input(GPIO_SD_WP); -++ __gpio_disable_pull(GPIO_SD_WP); -++ -++ __gpio_as_input(GPIO_DC_DETE_N); -++ __gpio_as_input(GPIO_CHARG_STAT_N); -++ __gpio_as_input(GPIO_USB_DETE); -++ -++ __gpio_as_output(GPIO_DISP_OFF_N); -++ -++ __gpio_as_output(GPIO_LED_EN); -++} -++ -++void __init jz_board_setup(void) -++{ -++ printk("JZ4740 PAVO board setup\n"); -++ -++ board_cpm_setup(); -++ board_gpio_setup(); -++ -++ jz_timer_callback = pavo_timer_callback; -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4740/board-virgo.c linux-2.6.24.7/arch/mips/jz4740/board-virgo.c -+--- linux-2.6.24.7.old/arch/mips/jz4740/board-virgo.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4740/board-virgo.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,114 @@ -++/* -++ * linux/arch/mips/jz4740/board-virgo.c -++ * -++ * JZ4720 VIRGO board setup routines. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include -++ -++extern void (*jz_timer_callback)(void); -++ -++static void dancing(void) -++{ -++ static unsigned int count = 0; -++ -++ count ++; -++ count &= 1; -++ if (count) -++ __gpio_set_pin(GPIO_LED_EN); -++ else -++ __gpio_clear_pin(GPIO_LED_EN); -++} -++ -++static void virgo_timer_callback(void) -++{ -++ static unsigned long count = 0; -++ -++ if ((++count) % 50 == 0) { -++ dancing(); -++ count = 0; -++ } -++} -++ -++static void __init board_cpm_setup(void) -++{ -++ /* Stop unused module clocks here. -++ * We have started all module clocks at arch/mips/jz4740/setup.c. -++ */ -++} -++ -++static void __init board_gpio_setup(void) -++{ -++ /* -++ * Most of the GPIO pins should have been initialized by the boot-loader -++ */ -++ -++ /* -++ * Initialize MSC pins -++ */ -++ __gpio_as_msc(); -++ -++ /* -++ * Initialize LCD pins -++ */ -++// __gpio_as_lcd_18bit(); -++ -++ /* -++ * Initialize SSI pins -++ */ -++ __gpio_as_ssi(); -++ -++ /* -++ * Initialize I2C pins -++ */ -++ __gpio_as_i2c(); -++ -++ /* -++ * Initialize Other pins -++ */ -++ __gpio_as_output(GPIO_SD_VCC_EN_N); -++ __gpio_clear_pin(GPIO_SD_VCC_EN_N); -++ -++ __gpio_as_input(GPIO_SD_CD_N); -++ __gpio_disable_pull(GPIO_SD_CD_N); -++ -++// __gpio_as_input(GPIO_SD_WP); -++// __gpio_disable_pull(GPIO_SD_WP); -++ -++ __gpio_as_input(GPIO_DC_DETE_N); -++// __gpio_as_input(GPIO_CHARG_STAT_N); -++ __gpio_as_input(GPIO_USB_DETE); -++ -++ __gpio_as_output(GPIO_DISP_OFF_N); -++ -++// __gpio_as_output(GPIO_LED_EN); -++} -++ -++void __init jz_board_setup(void) -++{ -++ printk("JZ4720 VIRGO board setup\n"); -++ -++ board_cpm_setup(); -++ board_gpio_setup(); -++ -++ jz_timer_callback = virgo_timer_callback; -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4740/cpufreq.c linux-2.6.24.7/arch/mips/jz4740/cpufreq.c -+--- linux-2.6.24.7.old/arch/mips/jz4740/cpufreq.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4740/cpufreq.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,602 @@ -++/* -++ * linux/arch/mips/jz4740/cpufreq.c -++ * -++ * cpufreq driver for JZ4740 -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++ -++#include -++ -++#include -++#include -++ -++#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \ -++ "cpufreq-jz4740", msg) -++ -++#undef CHANGE_PLL -++ -++#define PLL_UNCHANGED 0 -++#define PLL_GOES_UP 1 -++#define PLL_GOES_DOWN 2 -++ -++#define PLL_WAIT_500NS (500*(__cpm_get_cclk()/1000000000)) -++ -++/* Saved the boot-time parameters */ -++static struct { -++ /* SDRAM parameters */ -++ unsigned int mclk; /* memory clock, KHz */ -++ unsigned int tras; /* RAS pulse width, cycles of mclk */ -++ unsigned int rcd; /* RAS to CAS Delay, cycles of mclk */ -++ unsigned int tpc; /* RAS Precharge time, cycles of mclk */ -++ unsigned int trwl; /* Write Precharge Time, cycles of mclk */ -++ unsigned int trc; /* RAS Cycle Time, cycles of mclk */ -++ unsigned int rtcor; /* Refresh Time Constant */ -++ unsigned int sdram_initialized; -++ -++ /* LCD parameters */ -++ unsigned int lcd_clk; /* LCD clock, Hz */ -++ unsigned int lcdpix_clk; /* LCD Pixel clock, Hz */ -++ unsigned int lcd_clks_initialized; -++} boot_config; -++ -++struct jz4740_freq_percpu_info { -++ struct cpufreq_frequency_table table[7]; -++}; -++ -++static struct jz4740_freq_percpu_info jz4740_freq_table; -++ -++/* -++ * This contains the registers value for an operating point. -++ * If only part of a register needs to change then there is -++ * a mask value for that register. -++ * When going to a new operating point the current register -++ * value is ANDed with the ~mask and ORed with the new value. -++ */ -++struct dpm_regs { -++ u32 cpccr; /* Clock Freq Control Register */ -++ u32 cpccr_mask; /* Clock Freq Control Register mask */ -++ u32 cppcr; /* PLL1 Control Register */ -++ u32 cppcr_mask; /* PLL1 Control Register mask */ -++ u32 pll_up_flag; /* New PLL freq is higher than current or not */ -++}; -++ -++extern jz_clocks_t jz_clocks; -++ -++static void jz_update_clocks(void) -++{ -++ /* Next clocks must be updated if we have changed -++ * the PLL or divisors. -++ */ -++ jz_clocks.cclk = __cpm_get_cclk(); -++ jz_clocks.hclk = __cpm_get_hclk(); -++ jz_clocks.mclk = __cpm_get_mclk(); -++ jz_clocks.pclk = __cpm_get_pclk(); -++ jz_clocks.lcdclk = __cpm_get_lcdclk(); -++ jz_clocks.pixclk = __cpm_get_pixclk(); -++ jz_clocks.i2sclk = __cpm_get_i2sclk(); -++ jz_clocks.usbclk = __cpm_get_usbclk(); -++ jz_clocks.mscclk = __cpm_get_mscclk(); -++} -++ -++static void -++jz_init_boot_config(void) -++{ -++ if (!boot_config.lcd_clks_initialized) { -++ /* the first time to scale pll */ -++ boot_config.lcd_clk = __cpm_get_lcdclk(); -++ boot_config.lcdpix_clk = __cpm_get_pixclk(); -++ boot_config.lcd_clks_initialized = 1; -++ } -++ -++ if (!boot_config.sdram_initialized) { -++ /* the first time to scale frequencies */ -++ unsigned int dmcr, rtcor; -++ unsigned int tras, rcd, tpc, trwl, trc; -++ -++ dmcr = REG_EMC_DMCR; -++ rtcor = REG_EMC_RTCOR; -++ -++ tras = (dmcr >> 13) & 0x7; -++ rcd = (dmcr >> 11) & 0x3; -++ tpc = (dmcr >> 8) & 0x7; -++ trwl = (dmcr >> 5) & 0x3; -++ trc = (dmcr >> 2) & 0x7; -++ -++ boot_config.mclk = __cpm_get_mclk() / 1000; -++ boot_config.tras = tras + 4; -++ boot_config.rcd = rcd + 1; -++ boot_config.tpc = tpc + 1; -++ boot_config.trwl = trwl + 1; -++ boot_config.trc = trc * 2 + 1; -++ boot_config.rtcor = rtcor; -++ -++ boot_config.sdram_initialized = 1; -++ } -++} -++ -++static void jz_update_dram_rtcor(unsigned int new_mclk) -++{ -++ unsigned int rtcor; -++ -++ new_mclk /= 1000; -++ rtcor = boot_config.rtcor * new_mclk / boot_config.mclk; -++ rtcor--; -++ -++ if (rtcor < 1) rtcor = 1; -++ if (rtcor > 255) rtcor = 255; -++ -++ REG_EMC_RTCOR = rtcor; -++ REG_EMC_RTCNT = rtcor; -++} -++ -++static void jz_update_dram_dmcr(unsigned int new_mclk) -++{ -++ unsigned int dmcr; -++ unsigned int tras, rcd, tpc, trwl, trc; -++ unsigned int valid_time, new_time; /* ns */ -++ -++ new_mclk /= 1000; -++ tras = boot_config.tras * new_mclk / boot_config.mclk; -++ rcd = boot_config.rcd * new_mclk / boot_config.mclk; -++ tpc = boot_config.tpc * new_mclk / boot_config.mclk; -++ trwl = boot_config.trwl * new_mclk / boot_config.mclk; -++ trc = boot_config.trc * new_mclk / boot_config.mclk; -++ -++ /* Validation checking */ -++ valid_time = (boot_config.tras * 1000000) / boot_config.mclk; -++ new_time = (tras * 1000000) / new_mclk; -++ if (new_time < valid_time) tras += 1; -++ -++ valid_time = (boot_config.rcd * 1000000) / boot_config.mclk; -++ new_time = (rcd * 1000000) / new_mclk; -++ if (new_time < valid_time) rcd += 1; -++ -++ valid_time = (boot_config.tpc * 1000000) / boot_config.mclk; -++ new_time = (tpc * 1000000) / new_mclk; -++ if (new_time < valid_time) tpc += 1; -++ -++ valid_time = (boot_config.trwl * 1000000) / boot_config.mclk; -++ new_time = (trwl * 1000000) / new_mclk; -++ if (new_time < valid_time) trwl += 1; -++ -++ valid_time = (boot_config.trc * 1000000) / boot_config.mclk; -++ new_time = (trc * 1000000) / new_mclk; -++ if (new_time < valid_time) trc += 2; -++ -++ tras = (tras < 4) ? 4: tras; -++ tras = (tras > 11) ? 11: tras; -++ tras -= 4; -++ -++ rcd = (rcd < 1) ? 1: rcd; -++ rcd = (rcd > 4) ? 4: rcd; -++ rcd -= 1; -++ -++ tpc = (tpc < 1) ? 1: tpc; -++ tpc = (tpc > 8) ? 8: tpc; -++ tpc -= 1; -++ -++ trwl = (trwl < 1) ? 1: trwl; -++ trwl = (trwl > 4) ? 4: trwl; -++ trwl -= 1; -++ -++ trc = (trc < 1) ? 1: trc; -++ trc = (trc > 15) ? 15: trc; -++ trc /= 2; -++ -++ dmcr = REG_EMC_DMCR; -++ -++ dmcr &= ~(EMC_DMCR_TRAS_MASK | EMC_DMCR_RCD_MASK | EMC_DMCR_TPC_MASK | EMC_DMCR_TRWL_MASK | EMC_DMCR_TRC_MASK); -++ dmcr |= ((tras << EMC_DMCR_TRAS_BIT) | (rcd << EMC_DMCR_RCD_BIT) | (tpc << EMC_DMCR_TPC_BIT) | (trwl << EMC_DMCR_TRWL_BIT) | (trc << EMC_DMCR_TRC_BIT)); -++ -++ REG_EMC_DMCR = dmcr; -++} -++ -++static void jz_update_dram_prev(unsigned int cur_mclk, unsigned int new_mclk) -++{ -++ /* No risk, no fun: run with interrupts on! */ -++ if (new_mclk > cur_mclk) { -++ /* We're going FASTER, so first update TRAS, RCD, TPC, TRWL -++ * and TRC of DMCR before changing the frequency. -++ */ -++ jz_update_dram_dmcr(new_mclk); -++ } else { -++ /* We're going SLOWER: first update RTCOR value -++ * before changing the frequency. -++ */ -++ jz_update_dram_rtcor(new_mclk); -++ } -++} -++ -++static void jz_update_dram_post(unsigned int cur_mclk, unsigned int new_mclk) -++{ -++ /* No risk, no fun: run with interrupts on! */ -++ if (new_mclk > cur_mclk) { -++ /* We're going FASTER, so update RTCOR -++ * after changing the frequency -++ */ -++ jz_update_dram_rtcor(new_mclk); -++ } else { -++ /* We're going SLOWER: so update TRAS, RCD, TPC, TRWL -++ * and TRC of DMCR after changing the frequency. -++ */ -++ jz_update_dram_dmcr(new_mclk); -++ } -++} -++ -++static void jz_scale_divisors(struct dpm_regs *regs) -++{ -++ unsigned int cpccr; -++ unsigned int cur_mclk, new_mclk; -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ unsigned int tmp = 0, wait = PLL_WAIT_500NS; -++ -++ cpccr = REG_CPM_CPCCR; -++ cpccr &= ~((unsigned long)regs->cpccr_mask); -++ cpccr |= regs->cpccr; -++ cpccr |= CPM_CPCCR_CE; /* update immediately */ -++ -++ cur_mclk = __cpm_get_mclk(); -++ new_mclk = __cpm_get_pllout() / div[(cpccr & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT]; -++ -++ /* Update some DRAM parameters before changing frequency */ -++ jz_update_dram_prev(cur_mclk, new_mclk); -++ -++ /* update register to change the clocks. -++ * align this code to a cache line. -++ */ -++ __asm__ __volatile__( -++ ".set noreorder\n\t" -++ ".align 5\n" -++ "sw %1,0(%0)\n\t" -++ "li %3,0\n\t" -++ "1:\n\t" -++ "bne %3,%2,1b\n\t" -++ "addi %3, 1\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ ".set reorder\n\t" -++ : -++ : "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp)); -++ -++ /* Update some other DRAM parameters after changing frequency */ -++ jz_update_dram_post(cur_mclk, new_mclk); -++} -++ -++#ifdef CHANGE_PLL -++/* Maintain the LCD clock and pixel clock */ -++static void jz_scale_lcd_divisors(struct dpm_regs *regs) -++{ -++ unsigned int new_pll, new_lcd_div, new_lcdpix_div; -++ unsigned int cpccr; -++ unsigned int tmp = 0, wait = PLL_WAIT_500NS; -++ -++ if (!boot_config.lcd_clks_initialized) return; -++ -++ new_pll = __cpm_get_pllout(); -++ new_lcd_div = new_pll / boot_config.lcd_clk; -++ new_lcdpix_div = new_pll / boot_config.lcdpix_clk; -++ -++ if (new_lcd_div < 1) -++ new_lcd_div = 1; -++ if (new_lcd_div > 16) -++ new_lcd_div = 16; -++ -++ if (new_lcdpix_div < 1) -++ new_lcdpix_div = 1; -++ if (new_lcdpix_div > 512) -++ new_lcdpix_div = 512; -++ -++// REG_CPM_CPCCR2 = new_lcdpix_div - 1; -++ -++ cpccr = REG_CPM_CPCCR; -++ cpccr &= ~CPM_CPCCR_LDIV_MASK; -++ cpccr |= ((new_lcd_div - 1) << CPM_CPCCR_LDIV_BIT); -++ cpccr |= CPM_CPCCR_CE; /* update immediately */ -++ -++ /* update register to change the clocks. -++ * align this code to a cache line. -++ */ -++ __asm__ __volatile__( -++ ".set noreorder\n\t" -++ ".align 5\n" -++ "sw %1,0(%0)\n\t" -++ "li %3,0\n\t" -++ "1:\n\t" -++ "bne %3,%2,1b\n\t" -++ "addi %3, 1\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ ".set reorder\n\t" -++ : -++ : "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp)); -++} -++ -++static void jz_scale_pll(struct dpm_regs *regs) -++{ -++ unsigned int cppcr; -++ unsigned int cur_mclk, new_mclk, new_pll; -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ int od[] = {1, 2, 2, 4}; -++ -++ cppcr = REG_CPM_CPPCR; -++ cppcr &= ~(regs->cppcr_mask | CPM_CPPCR_PLLS | CPM_CPPCR_PLLEN | CPM_CPPCR_PLLST_MASK); -++ regs->cppcr &= ~CPM_CPPCR_PLLEN; -++ cppcr |= (regs->cppcr | 0xff); -++ -++ /* Update some DRAM parameters before changing frequency */ -++ new_pll = JZ_EXTAL * ((cppcr>>23)+2) / ((((cppcr>>18)&0x1f)+2) * od[(cppcr>>16)&0x03]); -++ cur_mclk = __cpm_get_mclk(); -++ new_mclk = new_pll / div[(REG_CPM_CPCCR>>CPM_CPCCR_MDIV_BIT) & 0xf]; -++ -++ /* -++ * Update some SDRAM parameters -++ */ -++ jz_update_dram_prev(cur_mclk, new_mclk); -++ -++ /* -++ * Update PLL, align code to cache line. -++ */ -++ cppcr |= CPM_CPPCR_PLLEN; -++ __asm__ __volatile__( -++ ".set noreorder\n\t" -++ ".align 5\n" -++ "sw %1,0(%0)\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ ".set reorder\n\t" -++ : -++ : "r" (CPM_CPPCR), "r" (cppcr)); -++ -++ /* Update some other DRAM parameters after changing frequency */ -++ jz_update_dram_post(cur_mclk, new_mclk); -++} -++#endif -++ -++static void jz4740_transition(struct dpm_regs *regs) -++{ -++ /* -++ * Get and save some boot-time conditions. -++ */ -++ jz_init_boot_config(); -++ -++#ifdef CHANGE_PLL -++ /* -++ * Disable LCD before scaling pll. -++ * LCD and LCD pixel clocks should not be changed even if the PLL -++ * output frequency has been changed. -++ */ -++ REG_LCD_CTRL &= ~LCD_CTRL_ENA; -++ -++ /* -++ * Stop module clocks before scaling PLL -++ */ -++ __cpm_stop_eth(); -++ __cpm_stop_aic(1); -++ __cpm_stop_aic(2); -++#endif -++ -++ /* ... add more as necessary */ -++ -++ if (regs->pll_up_flag == PLL_GOES_UP) { -++ /* the pll frequency is going up, so change dividors first */ -++ jz_scale_divisors(regs); -++#ifdef CHANGE_PLL -++ jz_scale_pll(regs); -++#endif -++ } -++ else if (regs->pll_up_flag == PLL_GOES_DOWN) { -++ /* the pll frequency is going down, so change pll first */ -++#ifdef CHANGE_PLL -++ jz_scale_pll(regs); -++#endif -++ jz_scale_divisors(regs); -++ } -++ else { -++ /* the pll frequency is unchanged, so change divisors only */ -++ jz_scale_divisors(regs); -++ } -++ -++#ifdef CHANGE_PLL -++ /* -++ * Restart module clocks before scaling PLL -++ */ -++ __cpm_start_eth(); -++ __cpm_start_aic(1); -++ __cpm_start_aic(2); -++ -++ /* ... add more as necessary */ -++ -++ /* Scale the LCD divisors after scaling pll */ -++ if (regs->pll_up_flag != PLL_UNCHANGED) { -++ jz_scale_lcd_divisors(regs); -++ } -++ -++ /* Enable LCD controller */ -++ REG_LCD_CTRL &= ~LCD_CTRL_DIS; -++ REG_LCD_CTRL |= LCD_CTRL_ENA; -++#endif -++ -++ /* Update system clocks */ -++ jz_update_clocks(); -++} -++ -++extern unsigned int idle_times; -++static unsigned int jz4740_freq_get(unsigned int cpu) -++{ -++ return (__cpm_get_cclk() / 1000); -++} -++ -++static unsigned int index_to_divisor(unsigned int index, struct dpm_regs *regs) -++{ -++ int n2FR[33] = { -++ 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, -++ 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, -++ 9 -++ }; -++ int div[4] = {1, 2, 2, 2}; /* divisors of I:S:P:M */ -++ unsigned int div_of_cclk, new_freq, i; -++ -++ regs->pll_up_flag = PLL_UNCHANGED; -++ regs->cpccr_mask = CPM_CPCCR_CDIV_MASK | CPM_CPCCR_HDIV_MASK | CPM_CPCCR_PDIV_MASK | CPM_CPCCR_MDIV_MASK; -++ -++ new_freq = jz4740_freq_table.table[index].frequency; -++ -++ do { -++ div_of_cclk = __cpm_get_pllout() / (1000 * new_freq); -++ } while (div_of_cclk==0); -++ -++ if(div_of_cclk == 1 || div_of_cclk == 2 || div_of_cclk == 4) { -++ for(i = 1; i<4; i++) { -++ div[i] = 3; -++ } -++ } else { -++ for(i = 1; i<4; i++) { -++ div[i] = 2; -++ } -++ } -++ -++ for(i = 0; i<4; i++) { -++ div[i] *= div_of_cclk; -++ } -++ -++ dprintk("divisors of I:S:P:M = %d:%d:%d:%d\n", div[0], div[1], div[2], div[3]); -++ -++ regs->cpccr = -++ (n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) | -++ (n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) | -++ (n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) | -++ (n2FR[div[3]] << CPM_CPCCR_MDIV_BIT); -++ -++ return div_of_cclk; -++} -++ -++static void jz4740_set_cpu_divider_index(unsigned int cpu, unsigned int index) -++{ -++ unsigned long divisor, old_divisor; -++ struct cpufreq_freqs freqs; -++ struct dpm_regs regs; -++ -++ old_divisor = __cpm_get_pllout() / __cpm_get_cclk(); -++ divisor = index_to_divisor(index, ®s); -++ -++ freqs.old = __cpm_get_cclk() / 1000; -++ freqs.new = __cpm_get_pllout() / (1000 * divisor); -++ freqs.cpu = cpu; -++ -++ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); -++ -++ if (old_divisor != divisor) -++ jz4740_transition(®s); -++ -++ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); -++} -++ -++static int jz4740_freq_target(struct cpufreq_policy *policy, -++ unsigned int target_freq, -++ unsigned int relation) -++{ -++ unsigned int new_index = 0; -++ -++ if (cpufreq_frequency_table_target(policy, -++ &jz4740_freq_table.table[0], -++ target_freq, relation, &new_index)) -++ return -EINVAL; -++ -++ jz4740_set_cpu_divider_index(policy->cpu, new_index); -++ -++ dprintk("new frequency is %d KHz (REG_CPM_CPCCR:0x%x)\n", __cpm_get_cclk() / 1000, REG_CPM_CPCCR); -++ -++ return 0; -++} -++ -++static int jz4740_freq_verify(struct cpufreq_policy *policy) -++{ -++ return cpufreq_frequency_table_verify(policy, -++ &jz4740_freq_table.table[0]); -++} -++ -++static int __init jz4740_cpufreq_driver_init(struct cpufreq_policy *policy) -++{ -++ -++ struct cpufreq_frequency_table *table = &jz4740_freq_table.table[0]; -++ unsigned int MAX_FREQ; -++ -++ dprintk(KERN_INFO "Jz4740 cpufreq driver\n"); -++ -++ if (policy->cpu != 0) -++ return -EINVAL; -++ -++ policy->cur = MAX_FREQ = __cpm_get_cclk() / 1000; /* in kHz. Current and max frequency is determined by u-boot */ -++ policy->governor = CPUFREQ_DEFAULT_GOVERNOR; -++ -++ policy->cpuinfo.min_freq = MAX_FREQ/8; -++ policy->cpuinfo.max_freq = MAX_FREQ; -++ policy->cpuinfo.transition_latency = 100000; /* in 10^(-9) s = nanoseconds */ -++ -++ table[0].index = 0; -++ table[0].frequency = MAX_FREQ/8; -++ table[1].index = 1; -++ table[1].frequency = MAX_FREQ/6; -++ table[2].index = 2; -++ table[2].frequency = MAX_FREQ/4; -++ table[3].index = 3; -++ table[3].frequency = MAX_FREQ/3; -++ table[4].index = 4; -++ table[4].frequency = MAX_FREQ/2; -++ table[5].index = 5; -++ table[5].frequency = MAX_FREQ; -++ table[6].index = 6; -++ table[6].frequency = CPUFREQ_TABLE_END; -++ -++#ifdef CONFIG_CPU_FREQ_STAT_DETAILS -++ cpufreq_frequency_table_get_attr(table, policy->cpu); /* for showing /sys/devices/system/cpu/cpuX/cpufreq/stats/ */ -++#endif -++ -++ return cpufreq_frequency_table_cpuinfo(policy, table); -++} -++ -++static struct cpufreq_driver cpufreq_jz4740_driver = { -++// .flags = CPUFREQ_STICKY, -++ .init = jz4740_cpufreq_driver_init, -++ .verify = jz4740_freq_verify, -++ .target = jz4740_freq_target, -++ .get = jz4740_freq_get, -++ .name = "jz4740", -++}; -++ -++static int __init jz4740_cpufreq_init(void) -++{ -++ return cpufreq_register_driver(&cpufreq_jz4740_driver); -++} -++ -++static void __exit jz4740_cpufreq_exit(void) -++{ -++ cpufreq_unregister_driver(&cpufreq_jz4740_driver); -++} -++ -++module_init(jz4740_cpufreq_init); -++module_exit(jz4740_cpufreq_exit); -++ -++MODULE_AUTHOR("Regen "); -++MODULE_DESCRIPTION("cpufreq driver for Jz4740"); -++MODULE_LICENSE("GPL"); -++ -+diff -urN linux-2.6.24.7.old/arch/mips/jz4740/dma.c linux-2.6.24.7/arch/mips/jz4740/dma.c -+--- linux-2.6.24.7.old/arch/mips/jz4740/dma.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4740/dma.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,768 @@ -++/* -++ * linux/arch/mips/jz4740/dma.c -++ * -++ * Support functions for the JZ4740 internal DMA channels. -++ * No-descriptor transfer only. -++ * Descriptor transfer should also call jz_request_dma() to get a free -++ * channel and call jz_free_dma() to free the channel. And driver should -++ * build the DMA descriptor and setup the DMA channel by itself. -++ * -++ * Copyright (C) 2006 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++ -++/* -++ * A note on resource allocation: -++ * -++ * All drivers needing DMA channels, should allocate and release them -++ * through the public routines `jz_request_dma()' and `jz_free_dma()'. -++ * -++ * In order to avoid problems, all processes should allocate resources in -++ * the same sequence and release them in the reverse order. -++ * -++ * So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ. -++ * When releasing them, first release the IRQ, then release the DMA. The -++ * main reason for this order is that, if you are requesting the DMA buffer -++ * done interrupt, you won't know the irq number until the DMA channel is -++ * returned from jz_request_dma(). -++ */ -++ -++struct jz_dma_chan jz_dma_table[MAX_DMA_NUM] = { -++ {dev_id:-1,}, -++ {dev_id:-1,}, -++ {dev_id:-1,}, -++ {dev_id:-1,}, -++ {dev_id:-1,}, -++ {dev_id:-1,}, -++}; -++ -++// Device FIFO addresses and default DMA modes -++static const struct { -++ unsigned int fifo_addr; -++ unsigned int dma_mode; -++ unsigned int dma_source; -++} dma_dev_table[DMA_ID_MAX] = { -++ {CPHYSADDR(UART0_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART0OUT}, -++ {CPHYSADDR(UART0_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART0IN}, -++ {CPHYSADDR(SSI_DR), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSIOUT}, -++ {CPHYSADDR(SSI_DR), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSIIN}, -++ {CPHYSADDR(AIC_DR), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_AICOUT}, -++ {CPHYSADDR(AIC_DR), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_AICIN}, -++ {CPHYSADDR(MSC_TXFIFO), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSCOUT}, -++ {CPHYSADDR(MSC_RXFIFO), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSCIN}, -++ {0, DMA_AUTOINIT, DMAC_DRSR_RS_TCU}, -++ {0, DMA_AUTOINIT, DMAC_DRSR_RS_AUTO}, -++ {}, -++}; -++ -++ -++int jz_dma_read_proc(char *buf, char **start, off_t fpos, -++ int length, int *eof, void *data) -++{ -++ int i, len = 0; -++ struct jz_dma_chan *chan; -++ -++ for (i = 0; i < MAX_DMA_NUM; i++) { -++ if ((chan = get_dma_chan(i)) != NULL) { -++ len += sprintf(buf + len, "%2d: %s\n", -++ i, chan->dev_str); -++ } -++ } -++ -++ if (fpos >= len) { -++ *start = buf; -++ *eof = 1; -++ return 0; -++ } -++ *start = buf + fpos; -++ if ((len -= fpos) > length) -++ return length; -++ *eof = 1; -++ return len; -++} -++ -++ -++void dump_jz_dma_channel(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan; -++ -++ if (dmanr > MAX_DMA_NUM) -++ return; -++ chan = &jz_dma_table[dmanr]; -++ -++ printk("DMA%d Registers:\n", dmanr); -++ printk(" DMACR = 0x%08x\n", REG_DMAC_DMACR); -++ printk(" DSAR = 0x%08x\n", REG_DMAC_DSAR(dmanr)); -++ printk(" DTAR = 0x%08x\n", REG_DMAC_DTAR(dmanr)); -++ printk(" DTCR = 0x%08x\n", REG_DMAC_DTCR(dmanr)); -++ printk(" DRSR = 0x%08x\n", REG_DMAC_DRSR(dmanr)); -++ printk(" DCCSR = 0x%08x\n", REG_DMAC_DCCSR(dmanr)); -++ printk(" DCMD = 0x%08x\n", REG_DMAC_DCMD(dmanr)); -++ printk(" DDA = 0x%08x\n", REG_DMAC_DDA(dmanr)); -++ printk(" DMADBR = 0x%08x\n", REG_DMAC_DMADBR); -++} -++ -++ -++/** -++ * jz_request_dma - dynamically allcate an idle DMA channel to return -++ * @dev_id: the specified dma device id or DMA_ID_RAW_SET -++ * @dev_str: the specified dma device string name -++ * @irqhandler: the irq handler, or NULL -++ * @irqflags: the irq handler flags -++ * @irq_dev_id: the irq handler device id for shared irq -++ * -++ * Finds a free channel, and binds the requested device to it. -++ * Returns the allocated channel number, or negative on error. -++ * Requests the DMA done IRQ if irqhandler != NULL. -++ * -++*/ -++/*int jz_request_dma(int dev_id, const char *dev_str, -++ void (*irqhandler)(int, void *, struct pt_regs *), -++ unsigned long irqflags, -++ void *irq_dev_id) -++*/ -++ -++int jz_request_dma(int dev_id, const char *dev_str, -++ irqreturn_t (*irqhandler)(int, void *), -++ unsigned long irqflags, -++ void *irq_dev_id) -++{ -++ struct jz_dma_chan *chan; -++ int i, ret; -++ -++ if (dev_id < 0 || dev_id >= DMA_ID_MAX) -++ return -EINVAL; -++ -++ for (i = 0; i < MAX_DMA_NUM; i++) { -++ if (jz_dma_table[i].dev_id < 0) -++ break; -++ } -++ if (i == MAX_DMA_NUM) /* no free channel */ -++ return -ENODEV; -++ -++ /* we got a free channel */ -++ chan = &jz_dma_table[i]; -++ -++ if (irqhandler) { -++ chan->irq = IRQ_DMA_0 + i; // allocate irq number -++ chan->irq_dev = irq_dev_id; -++ if ((ret = request_irq(chan->irq, irqhandler, irqflags, -++ dev_str, chan->irq_dev))) { -++ chan->irq = -1; -++ chan->irq_dev = NULL; -++ return ret; -++ } -++ } else { -++ chan->irq = -1; -++ chan->irq_dev = NULL; -++ } -++ -++ // fill it in -++ chan->io = i; -++ chan->dev_id = dev_id; -++ chan->dev_str = dev_str; -++ chan->fifo_addr = dma_dev_table[dev_id].fifo_addr; -++ chan->mode = dma_dev_table[dev_id].dma_mode; -++ chan->source = dma_dev_table[dev_id].dma_source; -++ -++ return i; -++} -++ -++void jz_free_dma(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) { -++ printk("Trying to free DMA%d\n", dmanr); -++ return; -++ } -++ -++ disable_dma(dmanr); -++ if (chan->irq) -++ free_irq(chan->irq, chan->irq_dev); -++ -++ chan->irq = -1; -++ chan->irq_dev = NULL; -++ chan->dev_id = -1; -++} -++ -++void jz_set_dma_dest_width(int dmanr, int nbit) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ chan->mode &= ~DMAC_DCMD_DWDH_MASK; -++ switch (nbit) { -++ case 8: -++ chan->mode |= DMAC_DCMD_DWDH_8; -++ break; -++ case 16: -++ chan->mode |= DMAC_DCMD_DWDH_16; -++ break; -++ case 32: -++ chan->mode |= DMAC_DCMD_DWDH_32; -++ break; -++ } -++} -++ -++void jz_set_dma_src_width(int dmanr, int nbit) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ chan->mode &= ~DMAC_DCMD_SWDH_MASK; -++ switch (nbit) { -++ case 8: -++ chan->mode |= DMAC_DCMD_SWDH_8; -++ break; -++ case 16: -++ chan->mode |= DMAC_DCMD_SWDH_16; -++ break; -++ case 32: -++ chan->mode |= DMAC_DCMD_SWDH_32; -++ break; -++ } -++} -++ -++void jz_set_dma_block_size(int dmanr, int nbyte) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ chan->mode &= ~DMAC_DCMD_DS_MASK; -++ switch (nbyte) { -++ case 1: -++ chan->mode |= DMAC_DCMD_DS_8BIT; -++ break; -++ case 2: -++ chan->mode |= DMAC_DCMD_DS_16BIT; -++ break; -++ case 4: -++ chan->mode |= DMAC_DCMD_DS_32BIT; -++ break; -++ case 16: -++ chan->mode |= DMAC_DCMD_DS_16BYTE; -++ break; -++ case 32: -++ chan->mode |= DMAC_DCMD_DS_32BYTE; -++ break; -++ } -++} -++ -++unsigned int jz_get_dma_command(int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ return chan->mode; -++} -++ -++/** -++ * jz_set_dma_mode - do the raw settings for the specified DMA channel -++ * @dmanr: the specified DMA channel -++ * @mode: dma operate mode, DMA_MODE_READ or DMA_MODE_WRITE -++ * @dma_mode: dma raw mode -++ * @dma_source: dma raw request source -++ * @fifo_addr: dma raw device fifo address -++ * -++ * Ensure call jz_request_dma(DMA_ID_RAW_SET, ...) first, then call -++ * jz_set_dma_mode() rather than set_dma_mode() if you work with -++ * and external request dma device. -++ * -++ * NOTE: Don not dynamically allocate dma channel if one external request -++ * dma device will occupy this channel. -++*/ -++int jz_set_dma_mode(unsigned int dmanr, unsigned int mode, -++ unsigned int dma_mode, unsigned int dma_source, -++ unsigned int fifo_addr) -++{ -++ int dev_id, i; -++ struct jz_dma_chan *chan; -++ -++ if (dmanr > MAX_DMA_NUM) -++ return -ENODEV; -++ for (i = 0; i < MAX_DMA_NUM; i++) { -++ if (jz_dma_table[i].dev_id < 0) -++ break; -++ } -++ if (i == MAX_DMA_NUM) -++ return -ENODEV; -++ -++ chan = &jz_dma_table[dmanr]; -++ dev_id = chan->dev_id; -++ if (dev_id > 0) { -++ printk(KERN_DEBUG "%s sets the allocated DMA channel %d!\n", -++ __FUNCTION__, dmanr); -++ return -ENODEV; -++ } -++ -++ /* clone it from the dynamically allocated. */ -++ if (i != dmanr) { -++ chan->irq = jz_dma_table[i].irq; -++ chan->irq_dev = jz_dma_table[i].irq_dev; -++ chan->dev_str = jz_dma_table[i].dev_str; -++ jz_dma_table[i].irq = 0; -++ jz_dma_table[i].irq_dev = NULL; -++ jz_dma_table[i].dev_id = -1; -++ } -++ chan->dev_id = DMA_ID_RAW_SET; -++ chan->io = dmanr; -++ chan->fifo_addr = fifo_addr; -++ chan->mode = dma_mode; -++ chan->source = dma_source; -++ -++ set_dma_mode(dmanr, dma_mode); -++ -++ return dmanr; -++} -++ -++void enable_dma(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ REG_DMAC_DCCSR(dmanr) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -++ REG_DMAC_DCCSR(dmanr) |= DMAC_DCCSR_NDES; /* No-descriptor transfer */ -++ __dmac_enable_channel(dmanr); -++ if (chan->irq) -++ __dmac_channel_enable_irq(dmanr); -++} -++ -++#define DMA_DISABLE_POLL 0x10000 -++ -++void disable_dma(unsigned int dmanr) -++{ -++ int i; -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ if (!__dmac_channel_enabled(dmanr)) -++ return; -++ -++ for (i = 0; i < DMA_DISABLE_POLL; i++) -++ if (__dmac_channel_transmit_end_detected(dmanr)) -++ break; -++#if 0 -++ if (i == DMA_DISABLE_POLL) -++ printk(KERN_INFO "disable_dma: poll expired!\n"); -++#endif -++ -++ __dmac_disable_channel(dmanr); -++ if (chan->irq) -++ __dmac_channel_disable_irq(dmanr); -++} -++ -++/* Note: DMA_MODE_MASK is simulated by sw */ -++void set_dma_mode(unsigned int dmanr, unsigned int mode) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -++ mode &= DMA_MODE_MASK; -++ if (mode == DMA_MODE_READ) { -++ chan->mode |= DMAC_DCMD_DAI; -++ chan->mode &= ~DMAC_DCMD_SAI; -++ } else if (mode == DMA_MODE_WRITE) { -++ chan->mode |= DMAC_DCMD_SAI; -++ chan->mode &= ~DMAC_DCMD_DAI; -++ } else { -++ printk(KERN_DEBUG "set_dma_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -++ } -++ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -++ REG_DMAC_DRSR(chan->io) = chan->source; -++} -++ -++void set_dma_addr(unsigned int dmanr, unsigned int phyaddr) -++{ -++ unsigned int mode; -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ mode = chan->mode & DMA_MODE_MASK; -++ if (mode == DMA_MODE_READ) { -++ REG_DMAC_DSAR(chan->io) = chan->fifo_addr; -++ REG_DMAC_DTAR(chan->io) = phyaddr; -++ } else if (mode == DMA_MODE_WRITE) { -++ REG_DMAC_DSAR(chan->io) = phyaddr; -++ REG_DMAC_DTAR(chan->io) = chan->fifo_addr; -++ } else -++ printk(KERN_DEBUG "Driver should call set_dma_mode() ahead set_dma_addr()!\n"); -++} -++ -++void set_dma_count(unsigned int dmanr, unsigned int bytecnt) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ int dma_ds[] = {4, 1, 2, 16, 32}; -++ unsigned int ds; -++ -++ if (!chan) -++ return; -++ -++ ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT; -++ REG_DMAC_DTCR(chan->io) = bytecnt / dma_ds[ds]; // transfer count -++} -++ -++unsigned int get_dma_residue(unsigned int dmanr) -++{ -++ unsigned int count, ds; -++ int dma_ds[] = {4, 1, 2, 16, 32}; -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return 0; -++ -++ ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT; -++ count = REG_DMAC_DTCR(chan->io); -++ count = count * dma_ds[ds]; -++ -++ return count; -++} -++ -++void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ switch (audio_fmt) { -++ case AFMT_U8: -++ /* burst mode : 32BIT */ -++ break; -++ case AFMT_S16_LE: -++ /* burst mode : 16BYTE */ -++ if (mode == DMA_MODE_READ) { -++ chan->mode = DMA_AIC_32_16BYTE_RX_CMD | DMA_MODE_READ; -++ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -++ mode &= DMA_MODE_MASK; -++ chan->mode |= DMAC_DCMD_DAI; -++ chan->mode &= ~DMAC_DCMD_SAI; -++ } else if (mode == DMA_MODE_WRITE) { -++ chan->mode = DMA_AIC_32_16BYTE_TX_CMD | DMA_MODE_WRITE; -++ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -++ mode &= DMA_MODE_MASK; -++ chan->mode |= DMAC_DCMD_SAI; -++ chan->mode &= ~DMAC_DCMD_DAI; -++ } else -++ printk("oss_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -++ -++ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -++ REG_DMAC_DRSR(chan->io) = chan->source; -++ break; -++ } -++} -++ -++void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ switch (audio_fmt) { -++ case 8: -++ /* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */ -++ break; -++ case 16: -++ /* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */ -++ if (mode == DMA_MODE_READ) { -++ chan->mode = DMA_AIC_16BYTE_RX_CMD | DMA_MODE_READ; -++ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -++ mode &= DMA_MODE_MASK; -++ chan->mode |= DMAC_DCMD_DAI; -++ chan->mode &= ~DMAC_DCMD_SAI; -++ } else if (mode == DMA_MODE_WRITE) { -++ chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE; -++ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -++ mode &= DMA_MODE_MASK; -++ chan->mode |= DMAC_DCMD_SAI; -++ chan->mode &= ~DMAC_DCMD_DAI; -++ } else -++ printk("alsa_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -++ -++ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -++ REG_DMAC_DRSR(chan->io) = chan->source; -++ break; -++ } -++} -++ -++#undef JZ4740_DMAC_TEST_ENABLE -++ -++#ifdef JZ4740_DMAC_TEST_ENABLE -++ -++/* -++ * DMA test: external address <--> external address -++ */ -++#define TEST_DMA_SIZE 16*1024 -++ -++static jz_dma_desc *dma_desc; -++ -++static int dma_chan; -++static dma_addr_t dma_desc_phys_addr; -++static unsigned int dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr; -++ -++static int dma_check_result(void *src, void *dst, int size) -++{ -++ unsigned int addr1, addr2, i, err = 0; -++ -++ addr1 = (unsigned int)src; -++ addr2 = (unsigned int)dst; -++ -++ for (i = 0; i < size; i += 4) { -++ if (*(volatile unsigned int *)addr1 != *(volatile unsigned int *)addr2) { -++ err++; -++ printk("wrong data at 0x%08x: src 0x%08x dst 0x%08x\n", addr2, *(volatile unsigned int *)addr1, *(volatile unsigned int *)addr2); -++ } -++ addr1 += 4; -++ addr2 += 4; -++ } -++ printk("check DMA result err=%d\n", err); -++ return err; -++} -++ -++static void jz4740_dma_irq(int irq, void *dev_id, struct pt_regs *regs) -++{ -++ printk("jz4740_dma_irq %d\n", irq); -++ -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ -++ if (__dmac_channel_transmit_halt_detected(dma_chan)) { -++ printk("DMA HALT\n"); -++ __dmac_channel_clear_transmit_halt(dma_chan); -++ } -++ -++ if (__dmac_channel_address_error_detected(dma_chan)) { -++ printk("DMA ADDR ERROR\n"); -++ __dmac_channel_clear_address_error(dma_chan); -++ } -++ -++ if (__dmac_channel_descriptor_invalid_detected(dma_chan)) { -++ printk("DMA DESC INVALID\n"); -++ __dmac_channel_clear_descriptor_invalid(dma_chan); -++ } -++ -++ if (__dmac_channel_count_terminated_detected(dma_chan)) { -++ printk("DMA CT\n"); -++ __dmac_channel_clear_count_terminated(dma_chan); -++ } -++ -++ if (__dmac_channel_transmit_end_detected(dma_chan)) { -++ printk("DMA TT\n"); -++ __dmac_channel_clear_transmit_end(dma_chan); -++ dump_jz_dma_channel(dma_chan); -++ dma_check_result((void *)dma_src_addr, (void *)dma_dst_addr, TEST_DMA_SIZE); -++ } -++ -++ /* free buffers */ -++ printk("free DMA buffers\n"); -++ free_pages(dma_src_addr, 2); -++ free_pages(dma_dst_addr, 2); -++ -++ if (dma_desc) -++ free_pages((unsigned int)dma_desc, 0); -++ -++ /* free dma */ -++ jz_free_dma(dma_chan); -++} -++ -++void dma_nodesc_test(void) -++{ -++ unsigned int addr, i; -++ -++ printk("dma_nodesc_test\n"); -++ -++ /* Request DMA channel and setup irq handler */ -++ dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4740_dma_irq, -++ SA_INTERRUPT, NULL); -++ if (dma_chan < 0) { -++ printk("Setup irq failed\n"); -++ return; -++ } -++ -++ printk("Requested DMA channel = %d\n", dma_chan); -++ -++ /* Allocate DMA buffers */ -++ dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -++ dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -++ -++ dma_src_phys_addr = CPHYSADDR(dma_src_addr); -++ dma_dst_phys_addr = CPHYSADDR(dma_dst_addr); -++ -++ printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n", -++ dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr); -++ -++ /* Prepare data for source buffer */ -++ addr = (unsigned int)dma_src_addr; -++ for (i = 0; i < TEST_DMA_SIZE; i += 4) { -++ *(volatile unsigned int *)addr = addr; -++ addr += 4; -++ } -++ dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE); -++ -++ /* Init target buffer */ -++ memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE); -++ dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE); -++ -++ /* Init DMA module */ -++ printk("Starting DMA\n"); -++ REG_DMAC_DMACR = 0; -++ REG_DMAC_DCCSR(dma_chan) = 0; -++ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; -++ REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr; -++ REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr; -++ REG_DMAC_DTCR(dma_chan) = 512; -++ REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TIE; -++ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; -++ REG_DMAC_DMACR = DMAC_DMACR_DMAE; /* global DMA enable bit */ -++ -++ printk("DMA started. IMR=%08x\n", REG_INTC_IMR); -++} -++ -++void dma_desc_test(void) -++{ -++ unsigned int next, addr, i; -++ static jz_dma_desc *desc; -++ -++ printk("dma_desc_test\n"); -++ -++ /* Request DMA channel and setup irq handler */ -++ dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4740_dma_irq, -++ SA_INTERRUPT, NULL); -++ if (dma_chan < 0) { -++ printk("Setup irq failed\n"); -++ return; -++ } -++ -++ printk("Requested DMA channel = %d\n", dma_chan); -++ -++ /* Allocate DMA buffers */ -++ dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -++ dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -++ -++ dma_src_phys_addr = CPHYSADDR(dma_src_addr); -++ dma_dst_phys_addr = CPHYSADDR(dma_dst_addr); -++ -++ printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n", -++ dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr); -++ -++ /* Prepare data for source buffer */ -++ addr = (unsigned int)dma_src_addr; -++ for (i = 0; i < TEST_DMA_SIZE; i += 4) { -++ *(volatile unsigned int *)addr = addr; -++ addr += 4; -++ } -++ dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE); -++ -++ /* Init target buffer */ -++ memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE); -++ dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE); -++ -++ /* Allocate DMA descriptors */ -++ dma_desc = (jz_dma_desc *)__get_free_pages(GFP_KERNEL, 0); -++ dma_desc_phys_addr = CPHYSADDR((unsigned long)dma_desc); -++ -++ printk("DMA descriptor address: 0x%08x 0x%08x\n", (u32)dma_desc, dma_desc_phys_addr); -++ -++ /* Setup DMA descriptors */ -++ desc = dma_desc; -++ next = (dma_desc_phys_addr + (sizeof(jz_dma_desc))) >> 4; -++ -++ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TM | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -++ desc->dsadr = dma_src_phys_addr; /* DMA source address */ -++ desc->dtadr = dma_dst_phys_addr; /* DMA target address */ -++ desc->ddadr = (next << 24) + 128; /* size: 128*32 bytes = 4096 bytes */ -++ -++ desc++; -++ next = (dma_desc_phys_addr + 2*(sizeof(jz_dma_desc))) >> 4; -++ -++ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -++ desc->dsadr = dma_src_phys_addr + 4096; /* DMA source address */ -++ desc->dtadr = dma_dst_phys_addr + 4096; /* DMA target address */ -++ desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */ -++ -++ desc++; -++ next = (dma_desc_phys_addr + 3*(sizeof(jz_dma_desc))) >> 4; -++ -++ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -++ desc->dsadr = dma_src_phys_addr + 8192; /* DMA source address */ -++ desc->dtadr = dma_dst_phys_addr + 8192; /* DMA target address */ -++ desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */ -++ -++ desc++; -++ next = (dma_desc_phys_addr + 4*(sizeof(jz_dma_desc))) >> 4; -++ -++ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE; -++ desc->dsadr = dma_src_phys_addr + 12*1024; /* DMA source address */ -++ desc->dtadr = dma_dst_phys_addr + 12*1024; /* DMA target address */ -++ desc->ddadr = (next << 24) + 1024; /* size: 1024*4 bytes = 4096 bytes */ -++ -++ dma_cache_wback((unsigned long)dma_desc, 4*(sizeof(jz_dma_desc))); -++ -++ /* Setup DMA descriptor address */ -++ REG_DMAC_DDA(dma_chan) = dma_desc_phys_addr; -++ -++ /* Setup request source */ -++ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; -++ -++ /* Setup DMA channel control/status register */ -++ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; /* descriptor transfer, clear status, start channel */ -++ -++ /* Enable DMA */ -++ REG_DMAC_DMACR = DMAC_DMACR_DMAE; -++ -++ /* DMA doorbell set -- start DMA now ... */ -++ REG_DMAC_DMADBSR = 1 << dma_chan; -++ -++ printk("DMA started. IMR=%08x\n", REG_INTC_IMR); -++} -++ -++#endif -++ -++//EXPORT_SYMBOL_NOVERS(jz_dma_table); -++EXPORT_SYMBOL(jz_dma_table); -++EXPORT_SYMBOL(jz_request_dma); -++EXPORT_SYMBOL(jz_free_dma); -++EXPORT_SYMBOL(jz_set_dma_src_width); -++EXPORT_SYMBOL(jz_set_dma_dest_width); -++EXPORT_SYMBOL(jz_set_dma_block_size); -++EXPORT_SYMBOL(jz_set_dma_mode); -++EXPORT_SYMBOL(set_dma_mode); -++EXPORT_SYMBOL(jz_set_oss_dma); -++EXPORT_SYMBOL(jz_set_alsa_dma); -++EXPORT_SYMBOL(set_dma_addr); -++EXPORT_SYMBOL(set_dma_count); -++EXPORT_SYMBOL(get_dma_residue); -++EXPORT_SYMBOL(enable_dma); -++EXPORT_SYMBOL(disable_dma); -++EXPORT_SYMBOL(dump_jz_dma_channel); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4740/i2c.c linux-2.6.24.7/arch/mips/jz4740/i2c.c -+--- linux-2.6.24.7.old/arch/mips/jz4740/i2c.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4740/i2c.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,273 @@ -++/* -++ * linux/arch/mips/jz4740/i2c.c -++ * -++ * Jz4740 I2C routines. -++ * -++ * Copyright (C) 2005,2006 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can distribute it and/or modify it -++ * under the terms of the GNU General Public License (Version 2) as -++ * published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -++ * -++ */ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++ -++/* I2C protocol */ -++#define I2C_READ 1 -++#define I2C_WRITE 0 -++ -++#define TIMEOUT 1000 -++ -++/* -++ * I2C bus protocol basic routines -++ */ -++static int i2c_put_data(unsigned char data) -++{ -++ unsigned int timeout = TIMEOUT*10; -++ -++ __i2c_write(data); -++ __i2c_set_drf(); -++ while (__i2c_check_drf() != 0); -++ while (!__i2c_transmit_ended()); -++ while (!__i2c_received_ack() && timeout) -++ timeout--; -++ -++ if (timeout) -++ return 0; -++ else -++ return -ETIMEDOUT; -++} -++ -++#ifdef CONFIG_JZ_TPANEL_ATA2508 -++static int i2c_put_data_nack(unsigned char data) -++{ -++ unsigned int timeout = TIMEOUT*10; -++ -++ __i2c_write(data); -++ __i2c_set_drf(); -++ while (__i2c_check_drf() != 0); -++ while (!__i2c_transmit_ended()); -++ while (timeout--); -++ return 0; -++} -++#endif -++ -++static int i2c_get_data(unsigned char *data, int ack) -++{ -++ int timeout = TIMEOUT*10; -++ -++ if (!ack) -++ __i2c_send_nack(); -++ else -++ __i2c_send_ack(); -++ -++ while (__i2c_check_drf() == 0 && timeout) -++ timeout--; -++ -++ if (timeout) { -++ if (!ack) -++ __i2c_send_stop(); -++ *data = __i2c_read(); -++ __i2c_clear_drf(); -++ return 0; -++ } else -++ return -ETIMEDOUT; -++} -++ -++/* -++ * I2C interface -++ */ -++void i2c_open(void) -++{ -++ __i2c_set_clk(jz_clocks.extalclk, 10000); /* default 10 KHz */ -++ __i2c_enable(); -++} -++ -++void i2c_close(void) -++{ -++ udelay(300); /* wait for STOP goes over. */ -++ __i2c_disable(); -++} -++ -++void i2c_setclk(unsigned int i2cclk) -++{ -++ __i2c_set_clk(jz_clocks.extalclk, i2cclk); -++} -++ -++int i2c_lseek(unsigned char device, unsigned char offset) -++{ -++ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -++ goto device_err; -++ if (i2c_put_data(offset) < 0) -++ goto address_err; -++ return 0; -++ device_err: -++ printk(KERN_DEBUG "No I2C device (0x%02x) installed.\n", device); -++ __i2c_send_stop(); -++ return -ENODEV; -++ address_err: -++ printk(KERN_DEBUG "No I2C device (0x%02x) response.\n", device); -++ __i2c_send_stop(); -++ return -EREMOTEIO; -++} -++ -++int i2c_read(unsigned char device, unsigned char *buf, -++ unsigned char address, int count) -++{ -++ int cnt = count; -++ int timeout = 5; -++ -++L_try_again: -++ -++ if (timeout < 0) -++ goto L_timeout; -++ -++ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -++ goto device_werr; -++ if (i2c_put_data(address) < 0) -++ goto address_err; -++ -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_READ ) < 0) -++ goto device_rerr; -++ __i2c_send_ack(); /* Master sends ACK for continue reading */ -++ while (cnt) { -++ if (cnt == 1) { -++ if (i2c_get_data(buf, 0) < 0) -++ break; -++ } else { -++ if (i2c_get_data(buf, 1) < 0) -++ break; -++ } -++ cnt--; -++ buf++; -++ } -++ -++ __i2c_send_stop(); -++ return count - cnt; -++ device_rerr: -++ device_werr: -++ address_err: -++ timeout --; -++ __i2c_send_stop(); -++ goto L_try_again; -++ -++L_timeout: -++ __i2c_send_stop(); -++ printk("Read I2C device 0x%2x failed.\n", device); -++ return -ENODEV; -++} -++ -++int i2c_write(unsigned char device, unsigned char *buf, -++ unsigned char address, int count) -++{ -++ int cnt = count; -++ int cnt_in_pg; -++ int timeout = 5; -++ unsigned char *tmpbuf; -++ unsigned char tmpaddr; -++ -++ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -++ -++ W_try_again: -++ if (timeout < 0) -++ goto W_timeout; -++ -++ cnt = count; -++ tmpbuf = (unsigned char *)buf; -++ tmpaddr = address; -++ -++ start_write_page: -++ cnt_in_pg = 0; -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -++ goto device_err; -++#ifdef CONFIG_JZ_TPANEL_ATA2508 -++ if (address == 0xff) { -++ if (i2c_put_data_nack(tmpaddr) < 0) -++ goto address_err; -++ while (cnt) { -++ if (++cnt_in_pg > 8) { -++ __i2c_send_stop(); -++ mdelay(1); -++ tmpaddr += 8; -++ goto start_write_page; -++ } -++ if (i2c_put_data_nack(*tmpbuf) < 0) -++ break; -++ cnt--; -++ tmpbuf++; -++ } -++ } -++ else { -++ -++ if (i2c_put_data(tmpaddr) < 0) -++ goto address_err; -++ while (cnt) { -++ if (++cnt_in_pg > 8) { -++ __i2c_send_stop(); -++ mdelay(1); -++ tmpaddr += 8; -++ goto start_write_page; -++ } -++ if (i2c_put_data(*tmpbuf) < 0) -++ break; -++ cnt--; -++ tmpbuf++; -++ } -++ } -++#else -++ if (i2c_put_data(tmpaddr) < 0) -++ goto address_err; -++ while (cnt) { -++ if (++cnt_in_pg > 8) { -++ __i2c_send_stop(); -++ mdelay(1); -++ tmpaddr += 8; -++ goto start_write_page; -++ } -++ if (i2c_put_data(*tmpbuf) < 0) -++ break; -++ cnt--; -++ tmpbuf++; -++ } -++#endif -++ __i2c_send_stop(); -++ return count - cnt; -++ device_err: -++ address_err: -++ timeout--; -++ __i2c_send_stop(); -++ goto W_try_again; -++ -++ W_timeout: -++ printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device); -++ __i2c_send_stop(); -++ return -ENODEV; -++} -++ -++EXPORT_SYMBOL(i2c_open); -++EXPORT_SYMBOL(i2c_close); -++EXPORT_SYMBOL(i2c_setclk); -++EXPORT_SYMBOL(i2c_read); -++EXPORT_SYMBOL(i2c_write); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4740/irq.c linux-2.6.24.7/arch/mips/jz4740/irq.c -+--- linux-2.6.24.7.old/arch/mips/jz4740/irq.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4740/irq.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,265 @@ -++/* -++ * linux/arch/mips/jz4740/irq.c -++ * -++ * JZ4740 interrupt routines. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++ -++/* -++ * INTC irq type -++ */ -++ -++static void enable_intc_irq(unsigned int irq) -++{ -++ __intc_unmask_irq(irq); -++} -++ -++static void disable_intc_irq(unsigned int irq) -++{ -++ __intc_mask_irq(irq); -++} -++ -++static void mask_and_ack_intc_irq(unsigned int irq) -++{ -++ __intc_mask_irq(irq); -++ __intc_ack_irq(irq); -++} -++ -++static void end_intc_irq(unsigned int irq) -++{ -++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -++ enable_intc_irq(irq); -++ } -++} -++ -++static unsigned int startup_intc_irq(unsigned int irq) -++{ -++ enable_intc_irq(irq); -++ return 0; -++} -++ -++static void shutdown_intc_irq(unsigned int irq) -++{ -++ disable_intc_irq(irq); -++} -++ -++static struct irq_chip intc_irq_type = { -++ .typename = "INTC", -++ .startup = startup_intc_irq, -++ .shutdown = shutdown_intc_irq, -++ .enable = enable_intc_irq, -++ .disable = disable_intc_irq, -++ .ack = mask_and_ack_intc_irq, -++ .end = end_intc_irq, -++}; -++ -++/* -++ * GPIO irq type -++ */ -++ -++static void enable_gpio_irq(unsigned int irq) -++{ -++ unsigned int intc_irq; -++ -++ if (irq < (IRQ_GPIO_0 + 32)) { -++ intc_irq = IRQ_GPIO0; -++ } -++ else if (irq < (IRQ_GPIO_0 + 64)) { -++ intc_irq = IRQ_GPIO1; -++ } -++ else if (irq < (IRQ_GPIO_0 + 96)) { -++ intc_irq = IRQ_GPIO2; -++ } -++ else { -++ intc_irq = IRQ_GPIO3; -++ } -++ -++ enable_intc_irq(intc_irq); -++ __gpio_unmask_irq(irq - IRQ_GPIO_0); -++} -++ -++static void disable_gpio_irq(unsigned int irq) -++{ -++ __gpio_mask_irq(irq - IRQ_GPIO_0); -++} -++ -++static void mask_and_ack_gpio_irq(unsigned int irq) -++{ -++ __gpio_mask_irq(irq - IRQ_GPIO_0); -++ __gpio_ack_irq(irq - IRQ_GPIO_0); -++} -++ -++static void end_gpio_irq(unsigned int irq) -++{ -++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -++ enable_gpio_irq(irq); -++ } -++} -++ -++static unsigned int startup_gpio_irq(unsigned int irq) -++{ -++ enable_gpio_irq(irq); -++ return 0; -++} -++ -++static void shutdown_gpio_irq(unsigned int irq) -++{ -++ disable_gpio_irq(irq); -++} -++ -++static struct irq_chip gpio_irq_type = { -++ .typename = "GPIO", -++ .startup = startup_gpio_irq, -++ .shutdown = shutdown_gpio_irq, -++ .enable = enable_gpio_irq, -++ .disable = disable_gpio_irq, -++ .ack = mask_and_ack_gpio_irq, -++ .end = end_gpio_irq, -++}; -++ -++/* -++ * DMA irq type -++ */ -++ -++static void enable_dma_irq(unsigned int irq) -++{ -++ __intc_unmask_irq(IRQ_DMAC); -++ __dmac_channel_enable_irq(irq - IRQ_DMA_0); -++} -++ -++static void disable_dma_irq(unsigned int irq) -++{ -++ __dmac_channel_disable_irq(irq - IRQ_DMA_0); -++} -++ -++static void mask_and_ack_dma_irq(unsigned int irq) -++{ -++ __intc_ack_irq(IRQ_DMAC); -++ __dmac_channel_disable_irq(irq - IRQ_DMA_0); -++} -++ -++static void end_dma_irq(unsigned int irq) -++{ -++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -++ enable_dma_irq(irq); -++ } -++} -++ -++static unsigned int startup_dma_irq(unsigned int irq) -++{ -++ enable_dma_irq(irq); -++ return 0; -++} -++ -++static void shutdown_dma_irq(unsigned int irq) -++{ -++ disable_dma_irq(irq); -++} -++ -++static struct irq_chip dma_irq_type = { -++ .typename = "DMA", -++ .startup = startup_dma_irq, -++ .shutdown = shutdown_dma_irq, -++ .enable = enable_dma_irq, -++ .disable = disable_dma_irq, -++ .ack = mask_and_ack_dma_irq, -++ .end = end_dma_irq, -++}; -++ -++//---------------------------------------------------------------------- -++ -++void __init arch_init_irq(void) -++{ -++ int i; -++ -++ clear_c0_status(0xff04); /* clear ERL */ -++ set_c0_status(0x0400); /* set IP2 */ -++ -++ /* Set up INTC irq -++ */ -++ for (i = 0; i < 32; i++) { -++ disable_intc_irq(i); -++ irq_desc[i].chip = &intc_irq_type; -++ } -++ -++ /* Set up DMAC irq -++ */ -++ for (i = 0; i < NUM_DMA; i++) { -++ disable_dma_irq(IRQ_DMA_0 + i); -++ irq_desc[IRQ_DMA_0 + i].chip = &dma_irq_type; -++ } -++ -++ /* Set up GPIO irq -++ */ -++ for (i = 0; i < NUM_GPIO; i++) { -++ disable_gpio_irq(IRQ_GPIO_0 + i); -++ irq_desc[IRQ_GPIO_0 + i].chip = &gpio_irq_type; -++ } -++} -++ -++static int plat_real_irq(int irq) -++{ -++ switch (irq) { -++ case IRQ_GPIO0: -++ irq = __gpio_group_irq(0) + IRQ_GPIO_0; -++ break; -++ case IRQ_GPIO1: -++ irq = __gpio_group_irq(1) + IRQ_GPIO_0 + 32; -++ break; -++ case IRQ_GPIO2: -++ irq = __gpio_group_irq(2) + IRQ_GPIO_0 + 64; -++ break; -++ case IRQ_GPIO3: -++ irq = __gpio_group_irq(3) + IRQ_GPIO_0 + 96; -++ break; -++ case IRQ_DMAC: -++ irq = __dmac_get_irq() + IRQ_DMA_0; -++ break; -++ } -++ -++ return irq; -++} -++ -++asmlinkage void plat_irq_dispatch(void) -++{ -++ int irq = 0; -++ static unsigned long intc_ipr = 0; -++ -++ intc_ipr |= REG_INTC_IPR; -++ -++ if (!intc_ipr) return; -++ -++ irq = ffs(intc_ipr) - 1; -++ intc_ipr &= ~(1< -++ * -++ * This file is licensed under the terms of the GNU General Public -++ * License version 2. This program is licensed "as is" without any -++ * warranty of any kind, whether express or implied. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++ -++/* OHCI (USB full speed host controller) */ -++static struct resource jz_usb_ohci_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(UHC_BASE), // phys addr for ioremap -++ .end = CPHYSADDR(UHC_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_UHC, -++ .end = IRQ_UHC, -++ .flags = IORESOURCE_IRQ, -++ }, -++}; -++ -++/* The dmamask must be set for OHCI to work */ -++static u64 ohci_dmamask = ~(u32)0; -++ -++static struct platform_device jz_usb_ohci_device = { -++ .name = "jz-ohci", -++ .id = 0, -++ .dev = { -++ .dma_mask = &ohci_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_usb_ohci_resources), -++ .resource = jz_usb_ohci_resources, -++}; -++ -++/*** LCD controller ***/ -++static struct resource jz_lcd_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(LCD_BASE), -++ .end = CPHYSADDR(LCD_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_LCD, -++ .end = IRQ_LCD, -++ .flags = IORESOURCE_IRQ, -++ } -++}; -++ -++static u64 jz_lcd_dmamask = ~(u32)0; -++ -++static struct platform_device jz_lcd_device = { -++ .name = "jz-lcd", -++ .id = 0, -++ .dev = { -++ .dma_mask = &jz_lcd_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_lcd_resources), -++ .resource = jz_lcd_resources, -++}; -++ -++/* UDC (USB gadget controller) */ -++static struct resource jz_usb_gdt_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(UDC_BASE), -++ .end = CPHYSADDR(UDC_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_UDC, -++ .end = IRQ_UDC, -++ .flags = IORESOURCE_IRQ, -++ }, -++}; -++ -++static u64 udc_dmamask = ~(u32)0; -++ -++static struct platform_device jz_usb_gdt_device = { -++ .name = "jz-udc", -++ .id = 0, -++ .dev = { -++ .dma_mask = &udc_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_usb_gdt_resources), -++ .resource = jz_usb_gdt_resources, -++}; -++ -++/** MMC/SD controller **/ -++static struct resource jz_mmc_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(MSC_BASE), -++ .end = CPHYSADDR(MSC_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_MSC, -++ .end = IRQ_MSC, -++ .flags = IORESOURCE_IRQ, -++ } -++}; -++ -++static u64 jz_mmc_dmamask = ~(u32)0; -++ -++static struct platform_device jz_mmc_device = { -++ .name = "jz-mmc", -++ .id = 0, -++ .dev = { -++ .dma_mask = &jz_mmc_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_mmc_resources), -++ .resource = jz_mmc_resources, -++}; -++ -++/** I2C controller **/ -++static struct resource jz_i2c_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(I2C_BASE), -++ .end = CPHYSADDR(I2C_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_I2C, -++ .end = IRQ_I2C, -++ .flags = IORESOURCE_IRQ, -++ } -++}; -++ -++static u64 jz_i2c_dmamask = ~(u32)0; -++ -++static struct platform_device jz_i2c_device = { -++ .name = "jz_i2c", -++ .id = 0, -++ .dev = { -++ .dma_mask = &jz_i2c_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_i2c_resources), -++ .resource = jz_i2c_resources, -++}; -++ -++/* All */ -++static struct platform_device *jz_platform_devices[] __initdata = { -++ &jz_usb_ohci_device, -++ &jz_lcd_device, -++ &jz_usb_gdt_device, -++ &jz_mmc_device, -++ &jz_i2c_device, -++}; -++ -++static int __init jz_platform_init(void) -++{ -++ return platform_add_devices(jz_platform_devices, ARRAY_SIZE(jz_platform_devices)); -++} -++ -++arch_initcall(jz_platform_init); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4740/pm.c linux-2.6.24.7/arch/mips/jz4740/pm.c -+--- linux-2.6.24.7.old/arch/mips/jz4740/pm.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4740/pm.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,462 @@ -++/* -++ * linux/arch/mips/jz4740/common/pm.c -++ * -++ * JZ4740 Power Management Routines -++ * -++ * Copyright (C) 2006 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can distribute it and/or modify it -++ * under the terms of the GNU General Public License (Version 2) as -++ * published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#undef DEBUG -++//#define DEBUG -++#ifdef DEBUG -++#define dprintk(x...) printk(x) -++#else -++#define dprintk(x...) -++#endif -++ -++#define GPIO_WAKEUP 125 /* set SW7(GPIO 125) as WAKEUP key */ -++ -++/* -++ * __gpio_as_sleep set all pins to pull-disable, and set all pins as input -++ * except sdram, nand flash pins and the pins which can be used as CS1_N -++ * to CS4_N for chip select. -++ */ -++#define __gpio_as_sleep() \ -++do { \ -++ REG_GPIO_PXFUNC(1) = ~0x9ff9ffff; \ -++ REG_GPIO_PXSELC(1) = ~0x9ff9ffff; \ -++ REG_GPIO_PXDIRC(1) = ~0x9ff9ffff; \ -++ REG_GPIO_PXPES(1) = 0xffffffff; \ -++ REG_GPIO_PXFUNC(2) = ~0x37000000; \ -++ REG_GPIO_PXSELC(2) = ~0x37000000; \ -++ REG_GPIO_PXDIRC(2) = ~0x37000000; \ -++ REG_GPIO_PXPES(2) = 0xffffffff; \ -++ REG_GPIO_PXFUNC(3) = 0xffffffff; \ -++ REG_GPIO_PXSELC(3) = 0xffffffff; \ -++ REG_GPIO_PXDIRC(3) = 0xffffffff; \ -++ REG_GPIO_PXPES(3) = 0xffffffff; \ -++} while (0) -++ -++static int jz_pm_do_hibernate(void) -++{ -++ printk("Put CPU into hibernate mode.\n"); -++ -++ /* Mask all interrupts */ -++ REG_INTC_IMSR = 0xffffffff; -++ -++ /* -++ * RTC Wakeup or 1Hz interrupt can be enabled or disabled -++ * through RTC driver's ioctl (linux/driver/char/rtc_jz.c). -++ */ -++ -++ /* Set minimum wakeup_n pin low-level assertion time for wakeup: 100ms */ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_HWFCR = (100 << RTC_HWFCR_BIT); -++ -++ /* Set reset pin low-level assertion time after wakeup: must > 60ms */ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_HRCR = (60 << RTC_HRCR_BIT); /* 60 ms */ -++ -++ /* Scratch pad register to be reserved */ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_HSPR = 0x12345678; -++ -++ /* clear wakeup status register */ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_HWRSR = 0x0; -++ -++ /* Put CPU to power down mode */ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_HCR = RTC_HCR_PD; -++ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ while(1); -++ -++ /* We can't get here */ -++ return 0; -++} -++ -++/* NOTES: -++ * 1: Pins that are floated (NC) should be set as input and pull-enable. -++ * 2: Pins that are pull-up or pull-down by outside should be set as input -++ * and pull-disable. -++ * 3: Pins that are connected to a chip except sdram and nand flash -++ * should be set as input and pull-disable, too. -++ */ -++static void jz_board_do_sleep(unsigned long *ptr) -++{ -++ unsigned char i; -++ -++ /* Print messages of GPIO registers for debug */ -++ for(i=0;i<4;i++) { -++ dprintk("run dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \ -++ REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \ -++ REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i)); -++ } -++ -++ /* Save GPIO registers */ -++ for(i = 1; i < 4; i++) { -++ *ptr++ = REG_GPIO_PXFUN(i); -++ *ptr++ = REG_GPIO_PXSEL(i); -++ *ptr++ = REG_GPIO_PXDIR(i); -++ *ptr++ = REG_GPIO_PXPE(i); -++ *ptr++ = REG_GPIO_PXIM(i); -++ *ptr++ = REG_GPIO_PXDAT(i); -++ *ptr++ = REG_GPIO_PXTRG(i); -++ } -++ -++ /* -++ * Set all pins to pull-disable, and set all pins as input except -++ * sdram, nand flash pins and the pins which can be used as CS1_N -++ * to CS4_N for chip select. -++ */ -++ __gpio_as_sleep(); -++ -++ /* -++ * Set proper status for GPB25 to GPB28 which can be used as CS1_N to CS4_N. -++ * Keep the pins' function used for chip select(CS) here according to your -++ * system to avoid chip select crashing with sdram when resuming from sleep mode. -++ */ -++ -++#if defined(CONFIG_JZ4740_PAVO) -++ /* GPB25/CS1_N is used as chip select for nand flash, shouldn't be change. */ -++ -++ /* GPB26/CS2_N is connected to nand flash, needn't be changed. */ -++ -++ /* GPB27/CS3_N is used as EXT_INT for CS8900 on debug board, it should be set as input.*/ -++ __gpio_as_input(32+27); -++ -++ /* GPB28/CS4_N is used as cs8900's chip select, shouldn't be changed. */ -++#endif -++ -++ /* -++ * Enable pull for NC pins here according to your system -++ */ -++ -++#if defined(CONFIG_JZ4740_PAVO) -++ /* GPB30-27 <-> J1: WE_N RD_N CS4_N EXT_INT */ -++ for(i=27;i<31;i++) { -++ __gpio_enable_pull(32+i); -++ } -++ -++ /* GPC27<-> WAIT_N */ -++ __gpio_enable_pull(32*2+27); -++ -++ /* GPD16<->SD_WP; GPD13-10<->MSC_D0-3; GPD9<->MSC_CMD; GPD8<->MSC_CLK */ -++ __gpio_enable_pull(32*3+16); -++ for(i=8;i<14;i++) { -++ __gpio_enable_pull(32*3+i); -++ } -++#endif -++ -++ /* -++ * If you must set some GPIOs as output to high level or low level, -++ * you can set them here, using: -++ * __gpio_as_output(n); -++ * __gpio_set_pin(n); or __gpio_clear_pin(n); -++ */ -++ -++#if defined(CONFIG_JZ4740_PAVO) -++ /* GPD16 which is used as AMPEN_N should be set to high to disable audio amplifier */ -++ __gpio_set_pin(32*3+4); -++#endif -++ -++#ifdef DEBUG -++ /* Keep uart0 function for printing debug message */ -++ __gpio_as_uart0(); -++ -++ /* Print messages of GPIO registers for debug */ -++ for(i=0;i<4;i++) { -++ dprintk("sleep dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \ -++ REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \ -++ REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i)); -++ } -++#endif -++} -++ -++static void jz_board_do_resume(unsigned long *ptr) -++{ -++ unsigned char i; -++ -++ /* Restore GPIO registers */ -++ for(i = 1; i < 4; i++) { -++ REG_GPIO_PXFUNS(i) = *ptr; -++ REG_GPIO_PXFUNC(i) = ~(*ptr++); -++ -++ REG_GPIO_PXSELS(i) = *ptr; -++ REG_GPIO_PXSELC(i) = ~(*ptr++); -++ -++ REG_GPIO_PXDIRS(i) = *ptr; -++ REG_GPIO_PXDIRC(i) = ~(*ptr++); -++ -++ REG_GPIO_PXPES(i) = *ptr; -++ REG_GPIO_PXPEC(i) = ~(*ptr++); -++ -++ REG_GPIO_PXIMS(i)=*ptr; -++ REG_GPIO_PXIMC(i)=~(*ptr++); -++ -++ REG_GPIO_PXDATS(i)=*ptr; -++ REG_GPIO_PXDATC(i)=~(*ptr++); -++ -++ REG_GPIO_PXTRGS(i)=*ptr; -++ REG_GPIO_PXTRGC(i)=~(*ptr++); -++ } -++ -++ /* Print messages of GPIO registers for debug */ -++ for(i=0;i<4;i++) { -++ dprintk("resume dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \ -++ REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \ -++ REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i)); -++ } -++} -++ -++ -++ -++static int jz_pm_do_sleep(void) -++{ -++ unsigned long delta; -++ unsigned long nfcsr = REG_EMC_NFCSR; -++ unsigned long scr = REG_CPM_SCR; -++ unsigned long imr = REG_INTC_IMR; -++ unsigned long sadc = REG_SADC_ENA; -++ unsigned long sleep_gpio_save[7*3]; -++ -++ printk("Put CPU into sleep mode.\n"); -++ -++ /* Preserve current time */ -++ delta = xtime.tv_sec - REG_RTC_RSR; -++ -++ /* Disable nand flash */ -++ REG_EMC_NFCSR = ~0xff; -++ -++ /* stop sadc */ -++ REG_SADC_ENA &= ~0x7; -++ while((REG_SADC_ENA & 0x7) != 0); -++ udelay(100); -++ -++ /*stop udc and usb*/ -++ REG_CPM_SCR &= ~( 1<<6 | 1<<7); -++ REG_CPM_SCR |= 0<<6 | 1<<7; -++ -++ /* Sleep on-board modules */ -++ jz_board_do_sleep(sleep_gpio_save); -++ -++ /* Mask all interrupts */ -++ REG_INTC_IMSR = 0xffffffff; -++ -++ /* Just allow following interrupts to wakeup the system. -++ * Note: modify this according to your system. -++ */ -++ -++ /* enable RTC alarm */ -++ __intc_unmask_irq(IRQ_RTC); -++#if 0 -++ /* make system wake up after n seconds by RTC alarm */ -++ unsigned int v, n; -++ n = 10; -++ while (!__rtc_write_ready()); -++ __rtc_enable_alarm(); -++ while (!__rtc_write_ready()); -++ __rtc_enable_alarm_irq(); -++ while (!__rtc_write_ready()); -++ v = __rtc_get_second(); -++ while (!__rtc_write_ready()); -++ __rtc_set_alarm_second(v+n); -++#endif -++ -++ /* WAKEUP key */ -++ __gpio_as_irq_rise_edge(GPIO_WAKEUP); -++ __gpio_unmask_irq(GPIO_WAKEUP); -++ __intc_unmask_irq(IRQ_GPIO3); /* IRQ_GPIOn depends on GPIO_WAKEUP */ -++ -++ /* Enter SLEEP mode */ -++ REG_CPM_LCR &= ~CPM_LCR_LPM_MASK; -++ REG_CPM_LCR |= CPM_LCR_LPM_SLEEP; -++ __asm__(".set\tmips3\n\t" -++ "wait\n\t" -++ ".set\tmips0"); -++ -++ /* Restore to IDLE mode */ -++ REG_CPM_LCR &= ~CPM_LCR_LPM_MASK; -++ REG_CPM_LCR |= CPM_LCR_LPM_IDLE; -++ -++ /* Restore nand flash control register */ -++ REG_EMC_NFCSR = nfcsr; -++ -++ /* Restore interrupts */ -++ REG_INTC_IMSR = imr; -++ REG_INTC_IMCR = ~imr; -++ -++ /* Restore sadc */ -++ REG_SADC_ENA = sadc; -++ -++ /* Resume on-board modules */ -++ jz_board_do_resume(sleep_gpio_save); -++ -++ /* Restore sleep control register */ -++ REG_CPM_SCR = scr; -++ -++ /* Restore current time */ -++ xtime.tv_sec = REG_RTC_RSR + delta; -++ -++ return 0; -++} -++ -++/* Put CPU to HIBERNATE mode */ -++int jz_pm_hibernate(void) -++{ -++ return jz_pm_do_hibernate(); -++} -++ -++#ifndef CONFIG_JZ_POWEROFF -++static irqreturn_t pm_irq_handler (int irq, void *dev_id) -++{ -++ return IRQ_HANDLED; -++} -++#endif -++ -++/* Put CPU to SLEEP mode */ -++int jz_pm_sleep(void) -++{ -++ int retval; -++ -++#ifndef CONFIG_JZ_POWEROFF -++ if ((retval = request_irq (IRQ_GPIO_0 + GPIO_WAKEUP, pm_irq_handler, IRQF_DISABLED, -++ "PM", NULL))) { -++ printk ("PM could not get IRQ for GPIO_WAKEUP\n"); -++ return retval; -++ } -++#endif -++ -++ pm_send_all(PM_SUSPEND, (void *)3); -++ retval = jz_pm_do_sleep(); -++ pm_send_all(PM_RESUME, (void *)0); -++ -++#ifndef CONFIG_JZ_POWEROFF -++ free_irq (IRQ_GPIO_0 + GPIO_WAKEUP, NULL); -++#endif -++ -++ return retval; -++} -++ -++#if 0 -++/* Deprecated ,was used by dpm */ -++void jz_pm_idle(void) -++{ -++ local_irq_disable(); -++ if (!need_resched()) { -++ local_irq_enable(); -++ cpu_wait(); -++ } -++} -++#endif -++ -++#ifdef CONFIG_SYSCTL -++ -++/* -++ * Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6 -++ * when all the PM interfaces exist nicely. -++ */ -++#define CTL_PM_SUSPEND 1 -++#define CTL_PM_HIBERNATE 2 -++ -++/*---------------------------------------------------------------------------- -++ * Power Management sleep sysctl proc interface -++ * -++ * A write to /proc/sys/pm/suspend invokes this function -++ * which initiates a sleep. -++ *--------------------------------------------------------------------------*/ -++static int sysctl_jz_pm_sleep(struct ctl_table *ctl, int write, struct file * filp, -++ void __user *buffer, size_t *lenp, loff_t *ppos) -++{ -++ return jz_pm_sleep(); -++} -++ -++/*---------------------------------------------------------------------------- -++ * Power Management sleep sysctl proc interface -++ * -++ * A write to /proc/sys/pm/hibernate invokes this function -++ * which initiates a poweroff. -++ *--------------------------------------------------------------------------*/ -++static int sysctl_jz_pm_hibernate(struct ctl_table *ctl, int write, struct file * filp, -++ void __user *buffer, size_t *lenp, loff_t *ppos) -++{ -++ return jz_pm_hibernate(); -++} -++ -++static struct ctl_table pm_table[] = -++{ -++ { -++ .ctl_name = CTL_UNNUMBERED, -++ .procname = "suspend", -++ .data = NULL, -++ .maxlen = 0, -++ .mode = 0600, -++ .proc_handler = &sysctl_jz_pm_sleep, -++ }, -++ { -++ .ctl_name = CTL_UNNUMBERED, -++ .procname = "hibernate", -++ .data = NULL, -++ .maxlen = 0, -++ .mode = 0600, -++ .proc_handler = &sysctl_jz_pm_hibernate, -++ }, -++ { .ctl_name = 0} -++}; -++ -++static struct ctl_table pm_dir_table[] = -++{ -++ { -++ .ctl_name = CTL_UNNUMBERED, -++ .procname = "pm", -++ .mode = 0555, -++ .child = pm_table, -++ }, -++ { .ctl_name = 0} -++}; -++ -++#endif /* CONFIG_SYSCTL */ -++ -++/* -++ * Initialize power interface -++ */ -++static int __init jz_pm_init(void) -++{ -++ printk("Power Management for JZ\n"); -++ -++#ifdef CONFIG_SYSCTL -++ register_sysctl_table(pm_dir_table); -++#endif -++ -++ return 0; -++} -++ -++module_init(jz_pm_init); -++ -+diff -urN linux-2.6.24.7.old/arch/mips/jz4740/proc.c linux-2.6.24.7/arch/mips/jz4740/proc.c -+--- linux-2.6.24.7.old/arch/mips/jz4740/proc.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4740/proc.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,887 @@ -++/* -++ * linux/arch/mips/jz4740/proc.c -++ * -++ * /proc/jz/ procfs for jz4740 on-chip modules. -++ * -++ * Copyright (C) 2006 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can distribute it and/or modify it -++ * under the terms of the GNU General Public License (Version 2) as -++ * published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -++ * -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++//#define DEBUG 1 -++#undef DEBUG -++ -++/* Define this to reserve total 4MB contineous physical memory for IPU. -++ * MPlayer will use IPU to optimize the decoding process. -++ * -++ * If you do not want to run the MPlayer, you can comment it. -++ */ -++#define CONFIG_RESERVE_IPU_MEM 1 -++ -++struct proc_dir_entry *proc_jz_root; -++ -++ -++/* -++ * EMC Modules -++ */ -++static int emc_read_proc (char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ -++ len += sprintf (page+len, "SMCR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SMCR0, REG_EMC_SMCR1, REG_EMC_SMCR2, REG_EMC_SMCR3, REG_EMC_SMCR4); -++ len += sprintf (page+len, "SACR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SACR0, REG_EMC_SACR1, REG_EMC_SACR2, REG_EMC_SACR3, REG_EMC_SACR4); -++ len += sprintf (page+len, "DMCR: 0x%08x\n", REG_EMC_DMCR); -++ len += sprintf (page+len, "RTCSR: 0x%04x\n", REG_EMC_RTCSR); -++ len += sprintf (page+len, "RTCOR: 0x%04x\n", REG_EMC_RTCOR); -++ return len; -++} -++ -++/* -++ * Power Manager Module -++ */ -++static int pmc_read_proc (char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ unsigned long lcr = REG_CPM_LCR; -++ unsigned long clkgr = REG_CPM_CLKGR; -++ -++ len += sprintf (page+len, "Low Power Mode : %s\n", -++ ((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_IDLE)) ? -++ "IDLE" : (((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_SLEEP)) ? -++ "SLEEP" : "HIBERNATE")); -++ len += sprintf (page+len, "Doze Mode : %s\n", -++ (lcr & CPM_LCR_DOZE_ON) ? "on" : "off"); -++ if (lcr & CPM_LCR_DOZE_ON) -++ len += sprintf (page+len, " duty : %d\n", (int)((lcr & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT)); -++ len += sprintf (page+len, "IPU : %s\n", -++ (clkgr & CPM_CLKGR_IPU) ? "stopped" : "running"); -++ len += sprintf (page+len, "DMAC : %s\n", -++ (clkgr & CPM_CLKGR_DMAC) ? "stopped" : "running"); -++ len += sprintf (page+len, "UHC : %s\n", -++ (clkgr & CPM_CLKGR_UHC) ? "stopped" : "running"); -++ len += sprintf (page+len, "UDC : %s\n", -++ (clkgr & CPM_CLKGR_UDC) ? "stopped" : "running"); -++ len += sprintf (page+len, "LCD : %s\n", -++ (clkgr & CPM_CLKGR_LCD) ? "stopped" : "running"); -++ len += sprintf (page+len, "CIM : %s\n", -++ (clkgr & CPM_CLKGR_CIM) ? "stopped" : "running"); -++ len += sprintf (page+len, "SADC : %s\n", -++ (clkgr & CPM_CLKGR_SADC) ? "stopped" : "running"); -++ len += sprintf (page+len, "MSC : %s\n", -++ (clkgr & CPM_CLKGR_MSC) ? "stopped" : "running"); -++ len += sprintf (page+len, "AIC1 : %s\n", -++ (clkgr & CPM_CLKGR_AIC1) ? "stopped" : "running"); -++ len += sprintf (page+len, "AIC2 : %s\n", -++ (clkgr & CPM_CLKGR_AIC2) ? "stopped" : "running"); -++ len += sprintf (page+len, "SSI : %s\n", -++ (clkgr & CPM_CLKGR_SSI) ? "stopped" : "running"); -++ len += sprintf (page+len, "I2C : %s\n", -++ (clkgr & CPM_CLKGR_I2C) ? "stopped" : "running"); -++ len += sprintf (page+len, "RTC : %s\n", -++ (clkgr & CPM_CLKGR_RTC) ? "stopped" : "running"); -++ len += sprintf (page+len, "TCU : %s\n", -++ (clkgr & CPM_CLKGR_TCU) ? "stopped" : "running"); -++ len += sprintf (page+len, "UART1 : %s\n", -++ (clkgr & CPM_CLKGR_UART1) ? "stopped" : "running"); -++ len += sprintf (page+len, "UART0 : %s\n", -++ (clkgr & CPM_CLKGR_UART0) ? "stopped" : "running"); -++ return len; -++} -++ -++static int pmc_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -++{ -++ REG_CPM_CLKGR = simple_strtoul(buffer, 0, 16); -++ return count; -++} -++ -++/* -++ * Clock Generation Module -++ */ -++#define TO_MHZ(x) (x/1000000),(x%1000000)/10000 -++#define TO_KHZ(x) (x/1000),(x%1000)/10 -++ -++static int cgm_read_proc (char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ unsigned int cppcr = REG_CPM_CPPCR; /* PLL Control Register */ -++ unsigned int cpccr = REG_CPM_CPCCR; /* Clock Control Register */ -++ unsigned int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ unsigned int od[4] = {1, 2, 2, 4}; -++ -++ len += sprintf (page+len, "CPPCR : 0x%08x\n", cppcr); -++ len += sprintf (page+len, "CPCCR : 0x%08x\n", cpccr); -++ len += sprintf (page+len, "PLL : %s\n", -++ (cppcr & CPM_CPPCR_PLLEN) ? "ON" : "OFF"); -++ len += sprintf (page+len, "m:n:o : %d:%d:%d\n", -++ __cpm_get_pllm() + 2, -++ __cpm_get_plln() + 2, -++ od[__cpm_get_pllod()] -++ ); -++ len += sprintf (page+len, "C:H:M:P : %d:%d:%d:%d\n", -++ div[__cpm_get_cdiv()], -++ div[__cpm_get_hdiv()], -++ div[__cpm_get_mdiv()], -++ div[__cpm_get_pdiv()] -++ ); -++ len += sprintf (page+len, "PLL Freq : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pllout())); -++ len += sprintf (page+len, "CCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_cclk())); -++ len += sprintf (page+len, "HCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_hclk())); -++ len += sprintf (page+len, "MCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mclk())); -++ len += sprintf (page+len, "PCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pclk())); -++ len += sprintf (page+len, "LCDCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_lcdclk())); -++ len += sprintf (page+len, "PIXCLK : %3d.%02d KHz\n", TO_KHZ(__cpm_get_pixclk())); -++ len += sprintf (page+len, "I2SCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_i2sclk())); -++ len += sprintf (page+len, "USBCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_usbclk())); -++ len += sprintf (page+len, "MSCCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mscclk())); -++ len += sprintf (page+len, "EXTALCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_extalclk())); -++ len += sprintf (page+len, "RTCCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_rtcclk())); -++ -++ return len; -++} -++ -++static int cgm_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -++{ -++ REG_CPM_CPCCR = simple_strtoul(buffer, 0, 16); -++ return count; -++} -++ -++ -++/* -++ * UDC hotplug -++ */ -++#ifdef CONFIG_JZ_UDC_HOTPLUG -++extern int jz_udc_active; /* defined in drivers/char/jzchar/jz_udc_hotplug.c */ -++#endif -++ -++#ifndef GPIO_UDC_HOTPLUG -++#define GPIO_UDC_HOTPLUG 86 -++#endif -++ -++static int udc_read_proc(char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ -++ if (__gpio_get_pin(GPIO_UDC_HOTPLUG)) { -++ -++#ifdef CONFIG_JZ_UDC_HOTPLUG -++ -++ /* Cable has connected, wait for disconnection. */ -++ __gpio_as_irq_fall_edge(GPIO_UDC_HOTPLUG); -++ -++ if (jz_udc_active) -++ len += sprintf (page+len, "CONNECT_CABLE\n"); -++ else -++ len += sprintf (page+len, "CONNECT_POWER\n"); -++#else -++ len += sprintf (page+len, "CONNECT\n"); -++#endif -++ } -++ else { -++ -++#ifdef CONFIG_JZ_UDC_HOTPLUG -++ /* Cable has disconnected, wait for connection. */ -++ __gpio_as_irq_rise_edge(GPIO_UDC_HOTPLUG); -++#endif -++ -++ len += sprintf (page+len, "REMOVE\n"); -++ } -++ -++ return len; -++} -++ -++/* -++ * MMC/SD hotplug -++ */ -++ -++#ifndef MSC_HOTPLUG_PIN -++#define MSC_HOTPLUG_PIN 90 -++#endif -++ -++static int mmc_read_proc (char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ -++#if defined(CONFIG_JZ4740_LYRA) -++ if (!(__gpio_get_pin(MSC_HOTPLUG_PIN))) -++#else -++ if (__gpio_get_pin(MSC_HOTPLUG_PIN)) -++#endif -++ len += sprintf (page+len, "REMOVE\n"); -++ else -++ len += sprintf (page+len, "INSERT\n"); -++ -++ return len; -++} -++ -++#ifdef CONFIG_RESERVE_IPU_MEM -++ -++/* USAGE: -++ * echo n > /proc/jz/ipu // n = [1,...,9], alloc mem, 2^n pages. -++ * echo FF > /proc/jz/ipu // 255, free all buffer -++ * echo xxxx > /proc/jz/ipu // free buffer which addr is xxxx -++ * echo llll > /proc/jz/ipu // add_wired_entry(l,l,l,l) -++ * echo 0 > /proc/jz/ipu // debug, print ipu_buf -++ * od -X /proc/jz/ipu // read mem addr -++ */ -++ -++typedef struct _ipu_buf { -++ unsigned int addr; /* phys addr */ -++ unsigned int page_shift; -++} ipu_buf_t; -++ -++#define IPU_BUF_MAX 4 /* 4 buffers */ -++ -++static struct _ipu_buf ipu_buf[IPU_BUF_MAX]; -++static int ipu_buf_cnt = 0; -++static unsigned char g_asid=0; -++ -++extern void local_flush_tlb_all(void); -++ -++/* CP0 hazard avoidance. */ -++#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ -++ "nop; nop; nop; nop; nop; nop;\n\t" \ -++ ".set reorder\n\t") -++void show_tlb(void) -++{ -++#define ASID_MASK 0xFF -++ -++ unsigned long flags; -++ unsigned int old_ctx; -++ unsigned int entry; -++ unsigned int entrylo0, entrylo1, entryhi; -++ unsigned int pagemask; -++ -++ local_irq_save(flags); -++ -++ /* Save old context */ -++ old_ctx = (read_c0_entryhi() & 0xff); -++ -++ printk("TLB content:\n"); -++ entry = 0; -++ while(entry < 32) { -++ write_c0_index(entry); -++ BARRIER; -++ tlb_read(); -++ BARRIER; -++ entryhi = read_c0_entryhi(); -++ entrylo0 = read_c0_entrylo0(); -++ entrylo1 = read_c0_entrylo1(); -++ pagemask = read_c0_pagemask(); -++ printk("%02d: ASID=%02d%s VA=0x%08x ", entry, entryhi & ASID_MASK, (entrylo0 & entrylo1 & 1) ? "(G)" : " ", entryhi & ~ASID_MASK); -++ printk("PA0=0x%08x C0=%x %s%s%s\n", (entrylo0>>6)<<12, (entrylo0>>3) & 7, (entrylo0 & 4) ? "Dirty " : "", (entrylo0 & 2) ? "Valid " : "Invalid ", (entrylo0 & 1) ? "Global" : ""); -++ printk("\t\t\t PA1=0x%08x C1=%x %s%s%s\n", (entrylo1>>6)<<12, (entrylo1>>3) & 7, (entrylo1 & 4) ? "Dirty " : "", (entrylo1 & 2) ? "Valid " : "Invalid ", (entrylo1 & 1) ? "Global" : ""); -++ -++ printk("\t\tpagemask=0x%08x", pagemask); -++ printk("\tentryhi=0x%08x\n", entryhi); -++ printk("\t\tentrylo0=0x%08x", entrylo0); -++ printk("\tentrylo1=0x%08x\n", entrylo1); -++ -++ entry++; -++ } -++ BARRIER; -++ write_c0_entryhi(old_ctx); -++ -++ local_irq_restore(flags); -++} -++ -++static void ipu_add_wired_entry(unsigned long pid, -++ unsigned long entrylo0, unsigned long entrylo1, -++ unsigned long entryhi, unsigned long pagemask) -++{ -++ unsigned long flags; -++ unsigned long wired; -++ unsigned long old_pagemask; -++ unsigned long old_ctx; -++ struct task_struct *g, *p; -++ -++ /* We will lock an 4MB page size entry to map the 4MB reserved IPU memory */ -++ wired = read_c0_wired(); -++ if (wired) return; -++ -++ do_each_thread(g, p) { -++ if (p->pid == pid ) -++ g_asid = p->mm->context[0]; -++ } while_each_thread(g, p); -++ -++ local_irq_save(flags); -++ -++ entrylo0 = entrylo0 >> 6; /* PFN */ -++ entrylo0 |= 0x6 | (0 << 3); /* Write-through cacheable, dirty, valid */ -++ -++ /* Save old context and create impossible VPN2 value */ -++ old_ctx = read_c0_entryhi() & 0xff; -++ old_pagemask = read_c0_pagemask(); -++ write_c0_wired(wired + 1); -++ write_c0_index(wired); -++ BARRIER; -++ entryhi &= ~0xff; /* new add, 20070906 */ -++ entryhi |= g_asid; /* new add, 20070906 */ -++// entryhi |= old_ctx; /* new add, 20070906 */ -++ write_c0_pagemask(pagemask); -++ write_c0_entryhi(entryhi); -++ write_c0_entrylo0(entrylo0); -++ write_c0_entrylo1(entrylo1); -++ BARRIER; -++ tlb_write_indexed(); -++ BARRIER; -++ -++ write_c0_entryhi(old_ctx); -++ BARRIER; -++ write_c0_pagemask(old_pagemask); -++ local_flush_tlb_all(); -++ local_irq_restore(flags); -++#if defined(DEBUG) -++ printk("\nold_ctx=%03d\n", old_ctx); -++ -++ show_tlb(); -++#endif -++} -++ -++static void ipu_del_wired_entry( void ) -++{ -++ unsigned long flags; -++ unsigned long wired; -++ -++ /* Free all lock entry */ -++ local_irq_save(flags); -++ wired = read_c0_wired(); -++ if (wired) -++ write_c0_wired(0); -++ local_irq_restore(flags); -++} -++ -++static inline void ipu_buf_get( unsigned int page_shift ) -++{ -++ unsigned char * virt_addr; -++ int i; -++ for ( i=0; i< IPU_BUF_MAX; ++i ) { -++ if ( ipu_buf[i].addr == 0 ) { -++ break; -++ } -++ } -++ -++ if ( (ipu_buf_cnt = i) == IPU_BUF_MAX ) { -++ printk("Error, no free ipu buffer.\n"); -++ return ; -++ } -++ -++ virt_addr = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); -++ -++ if ( virt_addr ) { -++ ipu_buf[ipu_buf_cnt].addr = (unsigned int)virt_to_phys((void *)virt_addr); -++ ipu_buf[ipu_buf_cnt].page_shift = page_shift; -++ -++ for (i = 0; i < (1<= IPU_BUF_MAX ) { /* failed alloc mem, rturn 0 */ -++ printk("no free buffer.\n"); -++ *pint = 0; -++ } -++ else -++ *pint = (unsigned int )ipu_buf[ipu_buf_cnt].addr; /* phys addr */ -++ len += sizeof(unsigned int); -++ -++#if defined(DEBUG) -++ show_tlb(); -++#endif -++ return len; -++ -++} -++ -++static int ipu_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -++{ -++ unsigned int val ; -++ int cnt,i; -++ char buf[12]; -++ unsigned long pid, entrylo0, entrylo1, entryhi, pagemask; -++#if defined(DEBUG) -++ printk("ipu write count=%u\n", count); -++#endif -++ if (count == (8*5+1)) { -++ for (i=0;i<12;i++) buf[i]=0; -++ strncpy(buf, buffer+8*0, 8); -++ pid = simple_strtoul(buf, 0, 16); -++ for (i=0;i<12;i++) buf[i]=0; -++ strncpy(buf, buffer+8*1, 8); -++ entrylo0 = simple_strtoul(buf, 0, 16); -++ for (i=0;i<12;i++) buf[i]=0; -++ strncpy(buf, buffer+8*2, 8); -++ entrylo1 = simple_strtoul(buf, 0, 16); -++ for (i=0;i<12;i++) buf[i]=0; -++ strncpy(buf, buffer+8*3, 8); -++ entryhi = simple_strtoul(buf, 0, 16); -++ for (i=0;i<12;i++) buf[i]=0; -++ strncpy(buf, buffer+8*4, 8); -++ pagemask = simple_strtoul(buf, 0, 16); -++ -++#if defined(DEBUG) -++ printk("pid=0x%08x, entrylo0=0x%08x, entrylo1=0x%08x, entryhi=0x%08x, pagemask=0x%08x\n", -++ pid, entrylo0, entrylo1, entryhi, pagemask); -++#endif -++ ipu_add_wired_entry( pid, entrylo0, entrylo1, entryhi, pagemask); -++ return 41; -++ } else if ( count <= 8+1 ) { -++ for (i=0;i<12;i++) buf[i]=0; -++ strncpy(buf, buffer, 8); -++ val = simple_strtoul(buf, 0, 16); -++ } else if (count == 44) { -++ for (i = 0; i < 12; i++) -++ buf[i] = 0; -++ strncpy(buf, buffer, 10); -++ pid = simple_strtoul(buf, 0, 16); -++ for (i = 0; i < 12; i++) -++ buf[i] = 0; -++ strncpy(buf, buffer + 11, 10); -++ entryhi = simple_strtoul(buf, 0, 16);//vaddr -++ for (i = 0; i < 12; i++) -++ buf[i] = 0; -++ strncpy(buf, buffer + 22, 10); -++ entrylo0 = simple_strtoul(buf, 0, 16);//paddr -++ for (i = 0; i < 12; i++) -++ buf[i] = 0; -++ strncpy(buf, buffer + 33, 10); -++ pagemask = simple_strtoul(buf, 0, 16); -++ pagemask = 0x3ff << 13; /* Fixed to 4MB page size */ -++ ipu_add_wired_entry(pid, entrylo0, 0, entryhi, pagemask); -++ return 44; -++ } else { -++ printk("ipu write count error, count=%d\n.", (unsigned int)count); -++ return -1; -++ } -++ -++ /* val: 1-9, page_shift, val>= 10: ipu_buf.addr */ -++ if ( val == 0 ) { /* debug, print ipu_buf info */ -++ for ( cnt=0; cnt /proc/jz/imem // n = [0,...,10], allocate memory, 2^n pages -++ * echo xxxxxxxx > /proc/jz/imem // free buffer which addr is xxxxxxxx -++ * echo FF > /proc/jz/ipu // FF, free all buffers -++ * od -X /proc/jz/imem // return the allocated buffer address and the max order of free buffer -++ */ -++ -++//#define DEBUG_IMEM 1 -++ -++#define IMEM_MAX_ORDER 10 /* max 2^10 * 4096 = 4MB */ -++ -++static unsigned int jz_imem_base; /* physical base address of ipu memory */ -++ -++static unsigned int allocated_phys_addr = 0; -++ -++/* -++ * Allocated buffer list -++ */ -++typedef struct imem_list { -++ unsigned int phys_start; /* physical start addr */ -++ unsigned int phys_end; /* physical end addr */ -++ struct imem_list *next; -++} imem_list_t; -++ -++static struct imem_list *imem_list_head = NULL; /* up sorted by phys_start */ -++ -++#ifdef DEBUG_IMEM -++static void dump_imem_list(void) -++{ -++ struct imem_list *imem; -++ -++ printk("*** dump_imem_list 0x%x ***\n", (u32)imem_list_head); -++ imem = imem_list_head; -++ while (imem) { -++ printk("imem=0x%x phys_start=0x%x phys_end=0x%x next=0x%x\n", (u32)imem, imem->phys_start, imem->phys_end, (u32)imem->next); -++ imem = imem->next; -++ } -++} -++#endif -++ -++/* allocate 2^order pages inside the 4MB memory */ -++static int imem_alloc(unsigned int order) -++{ -++ int alloc_ok = 0; -++ unsigned int start, end; -++ unsigned int size = (1 << order) * PAGE_SIZE; -++ struct imem_list *imem, *imemn, *imemp; -++ -++ allocated_phys_addr = 0; -++ -++ start = jz_imem_base; -++ end = start + (1 << IMEM_MAX_ORDER) * PAGE_SIZE; -++ -++ imem = imem_list_head; -++ while (imem) { -++ if ((imem->phys_start - start) >= size) { -++ /* we got a valid address range */ -++ alloc_ok = 1; -++ break; -++ } -++ -++ start = imem->phys_end + 1; -++ imem = imem->next; -++ } -++ -++ if (!alloc_ok) { -++ if ((end - start) >= size) -++ alloc_ok = 1; -++ } -++ -++ if (alloc_ok) { -++ end = start + size - 1; -++ allocated_phys_addr = start; -++ -++ /* add to imem_list, up sorted by phys_start */ -++ imemn = kmalloc(sizeof(struct imem_list), GFP_KERNEL); -++ if (!imemn) { -++ return -ENOMEM; -++ } -++ imemn->phys_start = start; -++ imemn->phys_end = end; -++ imemn->next = NULL; -++ -++ if (!imem_list_head) -++ imem_list_head = imemn; -++ else { -++ imem = imemp = imem_list_head; -++ while (imem) { -++ if (start < imem->phys_start) { -++ break; -++ } -++ -++ imemp = imem; -++ imem = imem->next; -++ } -++ -++ if (imem == imem_list_head) { -++ imem_list_head = imemn; -++ imemn->next = imem; -++ } -++ else { -++ imemn->next = imemp->next; -++ imemp->next = imemn; -++ } -++ } -++ } -++ -++#ifdef DEBUG_IMEM -++ dump_imem_list(); -++#endif -++ return 0; -++} -++ -++static void imem_free(unsigned int phys_addr) -++{ -++ struct imem_list *imem, *imemp; -++ -++ imem = imemp = imem_list_head; -++ while (imem) { -++ if (phys_addr == imem->phys_start) { -++ if (imem == imem_list_head) { -++ imem_list_head = imem->next; -++ } -++ else { -++ imemp->next = imem->next; -++ } -++ -++ kfree(imem); -++ break; -++ } -++ -++ imemp = imem; -++ imem = imem->next; -++ } -++ -++#ifdef DEBUG_IMEM -++ dump_imem_list(); -++#endif -++} -++ -++static void imem_free_all(void) -++{ -++ struct imem_list *imem; -++ -++ imem = imem_list_head; -++ while (imem) { -++ kfree(imem); -++ imem = imem->next; -++ } -++ -++ imem_list_head = NULL; -++ -++ allocated_phys_addr = 0; -++ -++#ifdef DEBUG_IMEM -++ dump_imem_list(); -++#endif -++} -++ -++/* -++ * Return the allocated buffer address and the max order of free buffer -++ */ -++static int imem_read_proc(char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ unsigned int start_addr, end_addr, max_order, max_size; -++ struct imem_list *imem; -++ -++ unsigned int *tmp = (unsigned int *)(page + len); -++ -++ start_addr = jz_imem_base; -++ end_addr = start_addr + (1 << IMEM_MAX_ORDER) * PAGE_SIZE; -++ -++ if (!imem_list_head) -++ max_size = end_addr - start_addr; -++ else { -++ max_size = 0; -++ imem = imem_list_head; -++ while (imem) { -++ if (max_size < (imem->phys_start - start_addr)) -++ max_size = imem->phys_start - start_addr; -++ -++ start_addr = imem->phys_end + 1; -++ imem = imem->next; -++ } -++ -++ if (max_size < (end_addr - start_addr)) -++ max_size = end_addr - start_addr; -++ } -++ -++ if (max_size > 0) { -++ max_order = get_order(max_size); -++ if (((1 << max_order) * PAGE_SIZE) > max_size) -++ max_order--; -++ } -++ else { -++ max_order = 0xffffffff; /* No any free buffer */ -++ } -++ -++ *tmp++ = allocated_phys_addr; /* address allocated by 'echo n > /proc/jz/imem' */ -++ *tmp = max_order; /* max order of current free buffers */ -++ -++ len += 2 * sizeof(unsigned int); -++ -++ return len; -++} -++ -++static int imem_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -++{ -++ unsigned int val; -++ -++ val = simple_strtoul(buffer, 0, 16); -++ -++ if (val == 0xff) { -++ /* free all memory */ -++ imem_free_all(); -++ ipu_del_wired_entry(); -++ } -++ else if ((val >= 0) && (val <= IMEM_MAX_ORDER)) { -++ /* allocate 2^val pages */ -++ imem_alloc(val); -++ } -++ else { -++ /* free buffer which phys_addr is val */ -++ imem_free(val); -++ } -++ -++ return count; -++} -++ -++#endif /* CONFIG_RESERVE_IPU_MEM */ -++ -++/* -++ * /proc/jz/xxx entry -++ * -++ */ -++static int __init jz_proc_init(void) -++{ -++ struct proc_dir_entry *res; -++#ifdef CONFIG_RESERVE_IPU_MEM -++ unsigned int virt_addr, i; -++#endif -++ -++ proc_jz_root = proc_mkdir("jz", 0); -++ -++ /* External Memory Controller */ -++ res = create_proc_entry("emc", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = emc_read_proc; -++ res->write_proc = NULL; -++ res->data = NULL; -++ } -++ -++ /* Power Management Controller */ -++ res = create_proc_entry("pmc", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = pmc_read_proc; -++ res->write_proc = pmc_write_proc; -++ res->data = NULL; -++ } -++ -++ /* Clock Generation Module */ -++ res = create_proc_entry("cgm", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = cgm_read_proc; -++ res->write_proc = cgm_write_proc; -++ res->data = NULL; -++ } -++ -++ /* udc hotplug */ -++ res = create_proc_entry("udc", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = udc_read_proc; -++ res->write_proc = NULL; -++ res->data = NULL; -++ } -++ -++ /* mmc hotplug */ -++ res = create_proc_entry("mmc", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = mmc_read_proc; -++ res->write_proc = NULL; -++ res->data = NULL; -++ } -++ -++#ifdef CONFIG_RESERVE_IPU_MEM -++ /* Image process unit */ -++ res = create_proc_entry("ipu", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = ipu_read_proc; -++ res->write_proc = ipu_write_proc; -++ res->data = NULL; -++ } -++ -++ /* -++ * Reserve a 4MB memory for IPU on JZ4740. -++ */ -++ jz_imem_base = (unsigned int)__get_free_pages(GFP_KERNEL, IMEM_MAX_ORDER); -++ if (jz_imem_base) { -++ /* imem (IPU memory management) */ -++ res = create_proc_entry("imem", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = imem_read_proc; -++ res->write_proc = imem_write_proc; -++ res->data = NULL; -++ } -++ -++ /* Set page reserved */ -++ virt_addr = jz_imem_base; -++ for (i = 0; i < (1 << IMEM_MAX_ORDER); i++) { -++ SetPageReserved(virt_to_page((void *)virt_addr)); -++ virt_addr += PAGE_SIZE; -++ } -++ -++ /* Convert to physical address */ -++ jz_imem_base = virt_to_phys((void *)jz_imem_base); -++ -++ printk("Total %dMB memory at 0x%x was reserved for IPU\n", -++ (unsigned int)((1 << IMEM_MAX_ORDER) * PAGE_SIZE)/1000000, jz_imem_base); -++ } -++#endif -++ -++ return 0; -++} -++ -++__initcall(jz_proc_init); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4740/prom.c linux-2.6.24.7/arch/mips/jz4740/prom.c -+--- linux-2.6.24.7.old/arch/mips/jz4740/prom.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4740/prom.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,198 @@ -++/* -++ * -++ * BRIEF MODULE DESCRIPTION -++ * PROM library initialisation code, supports YAMON and U-Boot. -++ * -++ * Copyright 2000, 2001, 2006 MontaVista Software Inc. -++ * Author: MontaVista Software, Inc. -++ * ppopov@mvista.com or source@mvista.com -++ * -++ * This file was derived from Carsten Langgaard's -++ * arch/mips/mips-boards/xx files. -++ * -++ * Carsten Langgaard, carstenl@mips.com -++ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ * -++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++/* #define DEBUG_CMDLINE */ -++ -++int prom_argc; -++char **prom_argv, **prom_envp; -++ -++char * prom_getcmdline(void) -++{ -++ return &(arcs_cmdline[0]); -++} -++ -++void prom_init_cmdline(void) -++{ -++ char *cp; -++ int actr; -++ -++ actr = 1; /* Always ignore argv[0] */ -++ -++ cp = &(arcs_cmdline[0]); -++ while(actr < prom_argc) { -++ strcpy(cp, prom_argv[actr]); -++ cp += strlen(prom_argv[actr]); -++ *cp++ = ' '; -++ actr++; -++ } -++ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ -++ --cp; -++ if (prom_argc > 1) -++ *cp = '\0'; -++ -++} -++ -++ -++char *prom_getenv(char *envname) -++{ -++#if 0 -++ /* -++ * Return a pointer to the given environment variable. -++ * YAMON uses "name", "value" pairs, while U-Boot uses "name=value". -++ */ -++ -++ char **env = prom_envp; -++ int i = strlen(envname); -++ int yamon = (*env && strchr(*env, '=') == NULL); -++ -++ while (*env) { -++ if (yamon) { -++ if (strcmp(envname, *env++) == 0) -++ return *env; -++ } else { -++ if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=') -++ return *env + i + 1; -++ } -++ env++; -++ } -++#endif -++ return NULL; -++} -++ -++inline unsigned char str2hexnum(unsigned char c) -++{ -++ if(c >= '0' && c <= '9') -++ return c - '0'; -++ if(c >= 'a' && c <= 'f') -++ return c - 'a' + 10; -++ if(c >= 'A' && c <= 'F') -++ return c - 'A' + 10; -++ return 0; /* foo */ -++} -++ -++inline void str2eaddr(unsigned char *ea, unsigned char *str) -++{ -++ int i; -++ -++ for(i = 0; i < 6; i++) { -++ unsigned char num; -++ -++ if((*str == '.') || (*str == ':')) -++ str++; -++ num = str2hexnum(*str++) << 4; -++ num |= (str2hexnum(*str++)); -++ ea[i] = num; -++ } -++} -++ -++int get_ethernet_addr(char *ethernet_addr) -++{ -++ char *ethaddr_str; -++ -++ ethaddr_str = prom_getenv("ethaddr"); -++ if (!ethaddr_str) { -++ printk("ethaddr not set in boot prom\n"); -++ return -1; -++ } -++ str2eaddr(ethernet_addr, ethaddr_str); -++ -++#if 0 -++ { -++ int i; -++ -++ printk("get_ethernet_addr: "); -++ for (i=0; i<5; i++) -++ printk("%02x:", (unsigned char)*(ethernet_addr+i)); -++ printk("%02x\n", *(ethernet_addr+i)); -++ } -++#endif -++ -++ return 0; -++} -++ -++void __init prom_free_prom_memory(void) -++{ -++} -++ -++void __init prom_init(void) -++{ -++ unsigned char *memsize_str; -++ unsigned long memsize; -++ -++ prom_argc = (int) fw_arg0; -++ prom_argv = (char **) fw_arg1; -++ prom_envp = (char **) fw_arg2; -++ -++ mips_machtype = MACH_INGENIC_JZ4740; -++ -++ prom_init_cmdline(); -++ memsize_str = prom_getenv("memsize"); -++ if (!memsize_str) { -++ memsize = 0x04000000; -++ } else { -++ memsize = simple_strtol(memsize_str, NULL, 0); -++ } -++ add_memory_region(0, memsize, BOOT_MEM_RAM); -++} -++ -++/* used by early printk */ -++void prom_putchar(char c) -++{ -++ volatile u8 *uart_lsr = (volatile u8 *)(UART0_BASE + OFF_LSR); -++ volatile u8 *uart_tdr = (volatile u8 *)(UART0_BASE + OFF_TDR); -++ -++ /* Wait for fifo to shift out some bytes */ -++ while ( !((*uart_lsr & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60) ); -++ -++ *uart_tdr = (u8)c; -++} -++ -++const char *get_system_type(void) -++{ -++ return "JZ4740"; -++} -++ -++EXPORT_SYMBOL(prom_getcmdline); -++EXPORT_SYMBOL(get_ethernet_addr); -++EXPORT_SYMBOL(str2eaddr); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4740/reset.c linux-2.6.24.7/arch/mips/jz4740/reset.c -+--- linux-2.6.24.7.old/arch/mips/jz4740/reset.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4740/reset.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,46 @@ -++/* -++ * linux/arch/mips/jz4740/reset.c -++ * -++ * JZ4740 reset routines. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++void jz_restart(char *command) -++{ -++ printk("Restarting after 4 ms\n"); -++ REG_WDT_TCSR = WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN; -++ REG_WDT_TCNT = 0; -++ REG_WDT_TDR = JZ_EXTAL/1000; /* reset after 4ms */ -++ REG_TCU_TSCR = TCU_TSSR_WDTSC; /* enable wdt clock */ -++ REG_WDT_TCER = WDT_TCER_TCEN; /* wdt start */ -++ while (1); -++} -++ -++void jz_halt(void) -++{ -++ printk(KERN_NOTICE "\n** You can safely turn off the power\n"); -++ -++ while (1) -++ __asm__(".set\tmips3\n\t" -++ "wait\n\t" -++ ".set\tmips0"); -++} -++ -++void jz_power_off(void) -++{ -++ jz_halt(); -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4740/setup.c linux-2.6.24.7/arch/mips/jz4740/setup.c -+--- linux-2.6.24.7.old/arch/mips/jz4740/setup.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4740/setup.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,182 @@ -++/* -++ * linux/arch/mips/jz4740/common/setup.c -++ * -++ * JZ4740 common setup routines. -++ * -++ * Copyright (C) 2006 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can distribute it and/or modify it -++ * under the terms of the GNU General Public License (Version 2) as -++ * published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -++ * -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#ifdef CONFIG_PC_KEYB -++#include -++#endif -++ -++jz_clocks_t jz_clocks; -++ -++extern char * __init prom_getcmdline(void); -++extern void __init jz_board_setup(void); -++extern void jz_restart(char *); -++extern void jz_halt(void); -++extern void jz_power_off(void); -++extern void jz_time_init(void); -++ -++static void __init sysclocks_setup(void) -++{ -++#ifndef CONFIG_MIPS_JZ_EMURUS /* FPGA */ -++ jz_clocks.cclk = __cpm_get_cclk(); -++ jz_clocks.hclk = __cpm_get_hclk(); -++ jz_clocks.pclk = __cpm_get_pclk(); -++ jz_clocks.mclk = __cpm_get_mclk(); -++ jz_clocks.lcdclk = __cpm_get_lcdclk(); -++ jz_clocks.pixclk = __cpm_get_pixclk(); -++ jz_clocks.i2sclk = __cpm_get_i2sclk(); -++ jz_clocks.usbclk = __cpm_get_usbclk(); -++ jz_clocks.mscclk = __cpm_get_mscclk(); -++ jz_clocks.extalclk = __cpm_get_extalclk(); -++ jz_clocks.rtcclk = __cpm_get_rtcclk(); -++#else -++ -++#define FPGACLK 8000000 -++ -++ jz_clocks.cclk = FPGACLK; -++ jz_clocks.hclk = FPGACLK; -++ jz_clocks.pclk = FPGACLK; -++ jz_clocks.mclk = FPGACLK; -++ jz_clocks.lcdclk = FPGACLK; -++ jz_clocks.pixclk = FPGACLK; -++ jz_clocks.i2sclk = FPGACLK; -++ jz_clocks.usbclk = FPGACLK; -++ jz_clocks.mscclk = FPGACLK; -++ jz_clocks.extalclk = FPGACLK; -++ jz_clocks.rtcclk = FPGACLK; -++#endif -++ -++ printk("CPU clock: %dMHz, System clock: %dMHz, Peripheral clock: %dMHz, Memory clock: %dMHz\n", -++ (jz_clocks.cclk + 500000) / 1000000, -++ (jz_clocks.hclk + 500000) / 1000000, -++ (jz_clocks.pclk + 500000) / 1000000, -++ (jz_clocks.mclk + 500000) / 1000000); -++} -++ -++static void __init soc_cpm_setup(void) -++{ -++ /* Start all module clocks -++ */ -++ __cpm_start_all(); -++ -++ /* Enable CKO to external memory */ -++ __cpm_enable_cko(); -++ -++ /* CPU enters IDLE mode when executing 'wait' instruction */ -++ __cpm_idle_mode(); -++ -++ /* Setup system clocks */ -++ sysclocks_setup(); -++} -++ -++static void __init soc_harb_setup(void) -++{ -++// __harb_set_priority(0x00); /* CIM>LCD>DMA>ETH>PCI>USB>CBB */ -++// __harb_set_priority(0x03); /* LCD>CIM>DMA>ETH>PCI>USB>CBB */ -++// __harb_set_priority(0x0a); /* ETH>LCD>CIM>DMA>PCI>USB>CBB */ -++} -++ -++static void __init soc_emc_setup(void) -++{ -++} -++ -++static void __init soc_dmac_setup(void) -++{ -++ __dmac_enable_module(); -++} -++ -++static void __init jz_soc_setup(void) -++{ -++ soc_cpm_setup(); -++ soc_harb_setup(); -++ soc_emc_setup(); -++ soc_dmac_setup(); -++} -++ -++static void __init jz_serial_setup(void) -++{ -++#ifdef CONFIG_SERIAL_8250 -++ struct uart_port s; -++ REG8(UART0_FCR) |= UARTFCR_UUE; /* enable UART module */ -++ memset(&s, 0, sizeof(s)); -++ s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; -++ s.iotype = SERIAL_IO_MEM; -++ s.regshift = 2; -++ s.uartclk = jz_clocks.extalclk ; -++ -++ s.line = 0; -++ s.membase = (u8 *)UART0_BASE; -++ s.irq = IRQ_UART0; -++ if (early_serial_setup(&s) != 0) { -++ printk(KERN_ERR "Serial ttyS0 setup failed!\n"); -++ } -++ -++ s.line = 1; -++ s.membase = (u8 *)UART1_BASE; -++ s.irq = IRQ_UART1; -++ if (early_serial_setup(&s) != 0) { -++ printk(KERN_ERR "Serial ttyS1 setup failed!\n"); -++ } -++#endif -++} -++ -++void __init plat_mem_setup(void) -++{ -++ char *argptr; -++ -++ argptr = prom_getcmdline(); -++ -++ /* IO/MEM resources. Which will be the addtion value in `inX' and -++ * `outX' macros defined in asm/io.h */ -++ set_io_port_base(0); -++ ioport_resource.start = 0x00000000; -++ ioport_resource.end = 0xffffffff; -++ iomem_resource.start = 0x00000000; -++ iomem_resource.end = 0xffffffff; -++ -++ _machine_restart = jz_restart; -++ _machine_halt = jz_halt; -++ pm_power_off = jz_power_off; -++ -++ jz_soc_setup(); -++ jz_serial_setup(); -++ jz_board_setup(); -++} -++ -+diff -urN linux-2.6.24.7.old/arch/mips/jz4740/time.c linux-2.6.24.7/arch/mips/jz4740/time.c -+--- linux-2.6.24.7.old/arch/mips/jz4740/time.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4740/time.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,158 @@ -++/* -++ * linux/arch/mips/jz4740/time.c -++ * -++ * Setting up the clock on the JZ4740 boards. -++ * -++ * Copyright (C) 2008 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can distribute it and/or modify it -++ * under the terms of the GNU General Public License (Version 2) as -++ * published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -++ * -++ */ -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++/* This is for machines which generate the exact clock. */ -++ -++#define JZ_TIMER_CHAN 0 -++#define JZ_TIMER_IRQ IRQ_TCU0 -++ -++#define JZ_TIMER_CLOCK (JZ_EXTAL>>4) /* Jz timer clock frequency */ -++ -++static struct clocksource clocksource_jz; /* Jz clock source */ -++static struct clock_event_device jz_clockevent_device; /* Jz clock event */ -++ -++void (*jz_timer_callback)(void); -++ -++static irqreturn_t jz_timer_interrupt(int irq, void *dev_id) -++{ -++ struct clock_event_device *cd = dev_id; -++ -++ REG_TCU_TFCR = 1 << JZ_TIMER_CHAN; /* ACK timer */ -++ -++ if (jz_timer_callback) -++ jz_timer_callback(); -++ -++ cd->event_handler(cd); -++ -++ return IRQ_HANDLED; -++} -++ -++static struct irqaction jz_irqaction = { -++ .handler = jz_timer_interrupt, -++ .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, -++ .name = "jz-timerirq", -++}; -++ -++ -++cycle_t jz_get_cycles(void) -++{ -++ /* convert jiffes to jz timer cycles */ -++ return (cycle_t)( jiffies*((JZ_TIMER_CLOCK)/HZ) + REG_TCU_TCNT(JZ_TIMER_CHAN)); -++} -++ -++static struct clocksource clocksource_jz = { -++ .name = "jz_clocksource", -++ .rating = 300, -++ .read = jz_get_cycles, -++ .mask = 0xFFFF, -++ .shift = 10, -++ .flags = CLOCK_SOURCE_WATCHDOG, -++}; -++ -++static int __init jz_clocksource_init(void) -++{ -++ clocksource_jz.mult = clocksource_hz2mult(JZ_TIMER_CLOCK, clocksource_jz.shift); -++ clocksource_register(&clocksource_jz); -++ return 0; -++} -++ -++static int jz_set_next_event(unsigned long evt, -++ struct clock_event_device *unused) -++{ -++ return 0; -++} -++ -++static void jz_set_mode(enum clock_event_mode mode, -++ struct clock_event_device *evt) -++{ -++ switch (mode) { -++ case CLOCK_EVT_MODE_PERIODIC: -++ break; -++ case CLOCK_EVT_MODE_ONESHOT: -++ case CLOCK_EVT_MODE_UNUSED: -++ case CLOCK_EVT_MODE_SHUTDOWN: -++ break; -++ case CLOCK_EVT_MODE_RESUME: -++ break; -++ } -++} -++ -++static struct clock_event_device jz_clockevent_device = { -++ .name = "jz-clockenvent", -++ .features = CLOCK_EVT_FEAT_PERIODIC, -++// .features = CLOCK_EVT_FEAT_ONESHOT, /* Jz4740 not support dynamic clock now */ -++ -++ /* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */ -++ .rating = 300, -++ .irq = JZ_TIMER_IRQ, -++ .set_mode = jz_set_mode, -++ .set_next_event = jz_set_next_event, -++}; -++ -++static void __init jz_clockevent_init(void) -++{ -++ struct clock_event_device *cd = &jz_clockevent_device; -++ unsigned int cpu = smp_processor_id(); -++ -++ cd->cpumask = cpumask_of_cpu(cpu); -++ clockevents_register_device(cd); -++} -++ -++static void __init jz_timer_setup(void) -++{ -++ jz_clocksource_init(); /* init jz clock source */ -++ jz_clockevent_init(); /* init jz clock event */ -++ -++ /* -++ * Make irqs happen for the system timer -++ */ -++ jz_irqaction.dev_id = &jz_clockevent_device; -++ setup_irq(JZ_TIMER_IRQ, &jz_irqaction); -++} -++ -++ -++void __init plat_time_init(void) -++{ -++ unsigned int latch; -++ /* Init timer */ -++ latch = ( JZ_TIMER_CLOCK + (HZ>>1)) / HZ; -++ -++ REG_TCU_TCSR(JZ_TIMER_CHAN) = TCU_TCSR_PRESCALE16 | TCU_TCSR_EXT_EN; -++ REG_TCU_TCNT(JZ_TIMER_CHAN) = 0; -++ REG_TCU_TDHR(JZ_TIMER_CHAN) = 0; -++ REG_TCU_TDFR(JZ_TIMER_CHAN) = latch; -++ -++ REG_TCU_TMSR = (1 << (JZ_TIMER_CHAN + 16)); /* mask half irq */ -++ REG_TCU_TMCR = (1 << JZ_TIMER_CHAN); /* unmask full irq */ -++ REG_TCU_TSCR = (1 << JZ_TIMER_CHAN); /* enable timer clock */ -++ REG_TCU_TESR = (1 << JZ_TIMER_CHAN); /* start counting up */ -++ -++ jz_timer_setup(); -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750/Makefile linux-2.6.24.7/arch/mips/jz4750/Makefile -+--- linux-2.6.24.7.old/arch/mips/jz4750/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,23 @@ -++# -++# Makefile for the Ingenic JZ4750. -++# -++ -++# Object file lists. -++ -++obj-y += prom.o irq.o time.o reset.o setup.o dma.o \ -++ platform.o i2c.o -++ -++obj-$(CONFIG_PROC_FS) += proc.o -++ -++# board specific support -++ -++obj-$(CONFIG_JZ4750_FUWA) += board-fuwa.o -++obj-$(CONFIG_JZ4750_APUS) += board-apus.o -++ -++# PM support -++ -++obj-$(CONFIG_PM_LEGACY) +=pm.o -++ -++# CPU Frequency scaling support -++ -++obj-$(CONFIG_CPU_FREQ_JZ) +=cpufreq.o -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750/board-apus.c linux-2.6.24.7/arch/mips/jz4750/board-apus.c -+--- linux-2.6.24.7.old/arch/mips/jz4750/board-apus.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750/board-apus.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,64 @@ -++/* -++ * linux/arch/mips/jz4750/board-apus.c -++ * -++ * JZ4750 APUS board setup routines. -++ * -++ * Copyright (c) 2006-2008 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include -++ -++extern void (*jz_timer_callback)(void); -++ -++static void dancing(void) -++{ -++} -++ -++static void apus_timer_callback(void) -++{ -++ static unsigned long count = 0; -++ -++ if ((++count) % 50 == 0) { -++ dancing(); -++ count = 0; -++ } -++} -++ -++static void __init board_cpm_setup(void) -++{ -++ /* Stop unused module clocks here. -++ * We have started all module clocks at arch/mips/jz4750/setup.c. -++ */ -++} -++ -++static void __init board_gpio_setup(void) -++{ -++ __gpio_as_pcm(); -++} -++ -++void __init jz_board_setup(void) -++{ -++ printk("JZ4750 APUS board setup\n"); -++ -++ board_cpm_setup(); -++ board_gpio_setup(); -++ -++ jz_timer_callback = apus_timer_callback; -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750/board-fuwa.c linux-2.6.24.7/arch/mips/jz4750/board-fuwa.c -+--- linux-2.6.24.7.old/arch/mips/jz4750/board-fuwa.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750/board-fuwa.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,105 @@ -++/* -++ * linux/arch/mips/jz4750/board-fuwa.c -++ * -++ * JZ4750 FUWA board setup routines. -++ * -++ * Copyright (c) 2006-2008 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include -++ -++extern void (*jz_timer_callback)(void); -++ -++static void dancing(void) -++{ -++ static unsigned char slash[] = "\\|/-"; -++// static volatile unsigned char *p = (unsigned char *)0xb6000058; -++ static volatile unsigned char *p = (unsigned char *)0xb6000016; -++ static unsigned int count = 0; -++ *p = slash[count++]; -++ count &= 3; -++} -++ -++static void fuwa_timer_callback(void) -++{ -++ static unsigned long count = 0; -++ -++ if ((++count) % 50 == 0) { -++ dancing(); -++ count = 0; -++ } -++} -++ -++static void __init board_cpm_setup(void) -++{ -++ /* Stop unused module clocks here. -++ * We have started all module clocks at arch/mips/jz4750/setup.c. -++ */ -++} -++ -++static void __init board_gpio_setup(void) -++{ -++ /* -++ * Initialize SDRAM pins -++ */ -++ -++ /* PORT A: D0 ~ D31 */ -++ REG_GPIO_PXFUNS(0) = 0xffffffff; -++ REG_GPIO_PXSELC(0) = 0xffffffff; -++ -++ /* PORT B: A0 ~ A16, DCS#, RAS#, CAS#, CKE#, RDWE#, CKO#, WE0# */ -++ REG_GPIO_PXFUNS(1) = 0x81f9ffff; -++ REG_GPIO_PXSELC(1) = 0x81f9ffff; -++ -++ /* PORT C: WE1#, WE2#, WE3# */ -++ REG_GPIO_PXFUNS(2) = 0x07000000; -++ REG_GPIO_PXSELC(2) = 0x07000000; -++ -++ -++ /* -++ * Initialize UART0 pins -++ */ -++ -++ /* PORT D: TXD/RXD */ -++ REG_GPIO_PXFUNS(3) = 0x06000000; -++ REG_GPIO_PXSELS(3) = 0x06000000; -++ -++ -++ /* -++ * Initialize LED pins -++ */ -++ __gpio_as_lcd_18bit(); -++ -++ /* CS2# */ -++ REG_GPIO_PXFUNS(1) = 0x04000000; -++ REG_GPIO_PXSELC(1) = 0x04000000; -++ -++ __gpio_as_pcm(); -++} -++ -++void __init jz_board_setup(void) -++{ -++ printk("JZ4750 FUWA board setup\n"); -++ -++ board_cpm_setup(); -++ board_gpio_setup(); -++ -++ jz_timer_callback = fuwa_timer_callback; -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750/board-slt50.c linux-2.6.24.7/arch/mips/jz4750/board-slt50.c -+--- linux-2.6.24.7.old/arch/mips/jz4750/board-slt50.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750/board-slt50.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,64 @@ -++/* -++ * linux/arch/mips/jz4750/board-apus.c -++ * -++ * JZ4750 APUS board setup routines. -++ * -++ * Copyright (c) 2006-2008 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include -++ -++extern void (*jz_timer_callback)(void); -++ -++static void dancing(void) -++{ -++} -++ -++static void apus_timer_callback(void) -++{ -++ static unsigned long count = 0; -++ -++ if ((++count) % 50 == 0) { -++ dancing(); -++ count = 0; -++ } -++} -++ -++static void __init board_cpm_setup(void) -++{ -++ /* Stop unused module clocks here. -++ * We have started all module clocks at arch/mips/jz4750/setup.c. -++ */ -++} -++ -++static void __init board_gpio_setup(void) -++{ -++ __gpio_as_pcm(); -++} -++ -++void __init jz_board_setup(void) -++{ -++ printk("JZ4750 SLT_50 board setup\n"); -++ -++ board_cpm_setup(); -++ board_gpio_setup(); -++ -++ jz_timer_callback = apus_timer_callback; -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750/cpufreq.c linux-2.6.24.7/arch/mips/jz4750/cpufreq.c -+--- linux-2.6.24.7.old/arch/mips/jz4750/cpufreq.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750/cpufreq.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,601 @@ -++/* -++ * linux/arch/mips/jz4750/cpufreq.c -++ * -++ * cpufreq driver for JZ4750 -++ * -++ * Copyright (c) 2006-2008 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++ -++#include -++ -++#include -++#include -++ -++#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \ -++ "cpufreq-jz4750", msg) -++ -++#undef CHANGE_PLL -++ -++#define PLL_UNCHANGED 0 -++#define PLL_GOES_UP 1 -++#define PLL_GOES_DOWN 2 -++ -++#define PLL_WAIT_500NS (500*(__cpm_get_cclk()/1000000000)) -++ -++/* Saved the boot-time parameters */ -++static struct { -++ /* SDRAM parameters */ -++ unsigned int mclk; /* memory clock, KHz */ -++ unsigned int tras; /* RAS pulse width, cycles of mclk */ -++ unsigned int rcd; /* RAS to CAS Delay, cycles of mclk */ -++ unsigned int tpc; /* RAS Precharge time, cycles of mclk */ -++ unsigned int trwl; /* Write Precharge Time, cycles of mclk */ -++ unsigned int trc; /* RAS Cycle Time, cycles of mclk */ -++ unsigned int rtcor; /* Refresh Time Constant */ -++ unsigned int sdram_initialized; -++ -++ /* LCD parameters */ -++ unsigned int lcd_clk; /* LCD clock, Hz */ -++ unsigned int lcdpix_clk; /* LCD Pixel clock, Hz */ -++ unsigned int lcd_clks_initialized; -++} boot_config; -++ -++struct jz4750_freq_percpu_info { -++ struct cpufreq_frequency_table table[7]; -++}; -++ -++static struct jz4750_freq_percpu_info jz4750_freq_table; -++ -++/* -++ * This contains the registers value for an operating point. -++ * If only part of a register needs to change then there is -++ * a mask value for that register. -++ * When going to a new operating point the current register -++ * value is ANDed with the ~mask and ORed with the new value. -++ */ -++struct dpm_regs { -++ u32 cpccr; /* Clock Freq Control Register */ -++ u32 cpccr_mask; /* Clock Freq Control Register mask */ -++ u32 cppcr; /* PLL1 Control Register */ -++ u32 cppcr_mask; /* PLL1 Control Register mask */ -++ u32 pll_up_flag; /* New PLL freq is higher than current or not */ -++}; -++ -++extern jz_clocks_t jz_clocks; -++ -++static void jz_update_clocks(void) -++{ -++ /* Next clocks must be updated if we have changed -++ * the PLL or divisors. -++ */ -++ jz_clocks.cclk = __cpm_get_cclk(); -++ jz_clocks.hclk = __cpm_get_hclk(); -++ jz_clocks.mclk = __cpm_get_mclk(); -++ jz_clocks.pclk = __cpm_get_pclk(); -++ jz_clocks.lcdclk = __cpm_get_lcdclk(); -++ jz_clocks.pixclk = __cpm_get_pixclk(); -++ jz_clocks.i2sclk = __cpm_get_i2sclk(); -++ jz_clocks.usbclk = __cpm_get_usbclk(); -++ jz_clocks.mscclk = __cpm_get_mscclk(0); -++} -++ -++static void -++jz_init_boot_config(void) -++{ -++ if (!boot_config.lcd_clks_initialized) { -++ /* the first time to scale pll */ -++ boot_config.lcd_clk = __cpm_get_lcdclk(); -++ boot_config.lcdpix_clk = __cpm_get_pixclk(); -++ boot_config.lcd_clks_initialized = 1; -++ } -++ -++ if (!boot_config.sdram_initialized) { -++ /* the first time to scale frequencies */ -++ unsigned int dmcr, rtcor; -++ unsigned int tras, rcd, tpc, trwl, trc; -++ -++ dmcr = REG_EMC_DMCR; -++ rtcor = REG_EMC_RTCOR; -++ -++ tras = (dmcr >> 13) & 0x7; -++ rcd = (dmcr >> 11) & 0x3; -++ tpc = (dmcr >> 8) & 0x7; -++ trwl = (dmcr >> 5) & 0x3; -++ trc = (dmcr >> 2) & 0x7; -++ -++ boot_config.mclk = __cpm_get_mclk() / 1000; -++ boot_config.tras = tras + 4; -++ boot_config.rcd = rcd + 1; -++ boot_config.tpc = tpc + 1; -++ boot_config.trwl = trwl + 1; -++ boot_config.trc = trc * 2 + 1; -++ boot_config.rtcor = rtcor; -++ -++ boot_config.sdram_initialized = 1; -++ } -++} -++ -++static void jz_update_dram_rtcor(unsigned int new_mclk) -++{ -++ unsigned int rtcor; -++ -++ new_mclk /= 1000; -++ rtcor = boot_config.rtcor * new_mclk / boot_config.mclk; -++ rtcor--; -++ -++ if (rtcor < 1) rtcor = 1; -++ if (rtcor > 255) rtcor = 255; -++ -++ REG_EMC_RTCOR = rtcor; -++ REG_EMC_RTCNT = rtcor; -++} -++ -++static void jz_update_dram_dmcr(unsigned int new_mclk) -++{ -++ unsigned int dmcr; -++ unsigned int tras, rcd, tpc, trwl, trc; -++ unsigned int valid_time, new_time; /* ns */ -++ -++ new_mclk /= 1000; -++ tras = boot_config.tras * new_mclk / boot_config.mclk; -++ rcd = boot_config.rcd * new_mclk / boot_config.mclk; -++ tpc = boot_config.tpc * new_mclk / boot_config.mclk; -++ trwl = boot_config.trwl * new_mclk / boot_config.mclk; -++ trc = boot_config.trc * new_mclk / boot_config.mclk; -++ -++ /* Validation checking */ -++ valid_time = (boot_config.tras * 1000000) / boot_config.mclk; -++ new_time = (tras * 1000000) / new_mclk; -++ if (new_time < valid_time) tras += 1; -++ -++ valid_time = (boot_config.rcd * 1000000) / boot_config.mclk; -++ new_time = (rcd * 1000000) / new_mclk; -++ if (new_time < valid_time) rcd += 1; -++ -++ valid_time = (boot_config.tpc * 1000000) / boot_config.mclk; -++ new_time = (tpc * 1000000) / new_mclk; -++ if (new_time < valid_time) tpc += 1; -++ -++ valid_time = (boot_config.trwl * 1000000) / boot_config.mclk; -++ new_time = (trwl * 1000000) / new_mclk; -++ if (new_time < valid_time) trwl += 1; -++ -++ valid_time = (boot_config.trc * 1000000) / boot_config.mclk; -++ new_time = (trc * 1000000) / new_mclk; -++ if (new_time < valid_time) trc += 2; -++ -++ tras = (tras < 4) ? 4: tras; -++ tras = (tras > 11) ? 11: tras; -++ tras -= 4; -++ -++ rcd = (rcd < 1) ? 1: rcd; -++ rcd = (rcd > 4) ? 4: rcd; -++ rcd -= 1; -++ -++ tpc = (tpc < 1) ? 1: tpc; -++ tpc = (tpc > 8) ? 8: tpc; -++ tpc -= 1; -++ -++ trwl = (trwl < 1) ? 1: trwl; -++ trwl = (trwl > 4) ? 4: trwl; -++ trwl -= 1; -++ -++ trc = (trc < 1) ? 1: trc; -++ trc = (trc > 15) ? 15: trc; -++ trc /= 2; -++ -++ dmcr = REG_EMC_DMCR; -++ -++ dmcr &= ~(EMC_DMCR_TRAS_MASK | EMC_DMCR_RCD_MASK | EMC_DMCR_TPC_MASK | EMC_DMCR_TRWL_MASK | EMC_DMCR_TRC_MASK); -++ dmcr |= ((tras << EMC_DMCR_TRAS_BIT) | (rcd << EMC_DMCR_RCD_BIT) | (tpc << EMC_DMCR_TPC_BIT) | (trwl << EMC_DMCR_TRWL_BIT) | (trc << EMC_DMCR_TRC_BIT)); -++ -++ REG_EMC_DMCR = dmcr; -++} -++ -++static void jz_update_dram_prev(unsigned int cur_mclk, unsigned int new_mclk) -++{ -++ /* No risk, no fun: run with interrupts on! */ -++ if (new_mclk > cur_mclk) { -++ /* We're going FASTER, so first update TRAS, RCD, TPC, TRWL -++ * and TRC of DMCR before changing the frequency. -++ */ -++ jz_update_dram_dmcr(new_mclk); -++ } else { -++ /* We're going SLOWER: first update RTCOR value -++ * before changing the frequency. -++ */ -++ jz_update_dram_rtcor(new_mclk); -++ } -++} -++ -++static void jz_update_dram_post(unsigned int cur_mclk, unsigned int new_mclk) -++{ -++ /* No risk, no fun: run with interrupts on! */ -++ if (new_mclk > cur_mclk) { -++ /* We're going FASTER, so update RTCOR -++ * after changing the frequency -++ */ -++ jz_update_dram_rtcor(new_mclk); -++ } else { -++ /* We're going SLOWER: so update TRAS, RCD, TPC, TRWL -++ * and TRC of DMCR after changing the frequency. -++ */ -++ jz_update_dram_dmcr(new_mclk); -++ } -++} -++ -++static void jz_scale_divisors(struct dpm_regs *regs) -++{ -++ unsigned int cpccr; -++ unsigned int cur_mclk, new_mclk; -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ unsigned int tmp = 0, wait = PLL_WAIT_500NS; -++ -++ cpccr = REG_CPM_CPCCR; -++ cpccr &= ~((unsigned long)regs->cpccr_mask); -++ cpccr |= regs->cpccr; -++ cpccr |= CPM_CPCCR_CE; /* update immediately */ -++ -++ cur_mclk = __cpm_get_mclk(); -++ new_mclk = __cpm_get_pllout() / div[(cpccr & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT]; -++ -++ /* Update some DRAM parameters before changing frequency */ -++ jz_update_dram_prev(cur_mclk, new_mclk); -++ -++ /* update register to change the clocks. -++ * align this code to a cache line. -++ */ -++ __asm__ __volatile__( -++ ".set noreorder\n\t" -++ ".align 5\n" -++ "sw %1,0(%0)\n\t" -++ "li %3,0\n\t" -++ "1:\n\t" -++ "bne %3,%2,1b\n\t" -++ "addi %3, 1\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ ".set reorder\n\t" -++ : -++ : "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp)); -++ -++ /* Update some other DRAM parameters after changing frequency */ -++ jz_update_dram_post(cur_mclk, new_mclk); -++} -++ -++#ifdef CHANGE_PLL -++/* Maintain the LCD clock and pixel clock */ -++static void jz_scale_lcd_divisors(struct dpm_regs *regs) -++{ -++ unsigned int new_pll, new_lcd_div, new_lcdpix_div; -++ unsigned int cpccr; -++ unsigned int tmp = 0, wait = PLL_WAIT_500NS; -++ -++ if (!boot_config.lcd_clks_initialized) return; -++ -++ new_pll = __cpm_get_pllout(); -++ new_lcd_div = new_pll / boot_config.lcd_clk; -++ new_lcdpix_div = new_pll / boot_config.lcdpix_clk; -++ -++ if (new_lcd_div < 1) -++ new_lcd_div = 1; -++ if (new_lcd_div > 16) -++ new_lcd_div = 16; -++ -++ if (new_lcdpix_div < 1) -++ new_lcdpix_div = 1; -++ if (new_lcdpix_div > 512) -++ new_lcdpix_div = 512; -++ -++// REG_CPM_CPCCR2 = new_lcdpix_div - 1; -++ -++ cpccr = REG_CPM_CPCCR; -++ cpccr &= ~CPM_CPCCR_LDIV_MASK; -++ cpccr |= ((new_lcd_div - 1) << CPM_CPCCR_LDIV_BIT); -++ cpccr |= CPM_CPCCR_CE; /* update immediately */ -++ -++ /* update register to change the clocks. -++ * align this code to a cache line. -++ */ -++ __asm__ __volatile__( -++ ".set noreorder\n\t" -++ ".align 5\n" -++ "sw %1,0(%0)\n\t" -++ "li %3,0\n\t" -++ "1:\n\t" -++ "bne %3,%2,1b\n\t" -++ "addi %3, 1\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ ".set reorder\n\t" -++ : -++ : "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp)); -++} -++ -++static void jz_scale_pll(struct dpm_regs *regs) -++{ -++ unsigned int cppcr; -++ unsigned int cur_mclk, new_mclk, new_pll; -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ int od[] = {1, 2, 2, 4}; -++ -++ cppcr = REG_CPM_CPPCR; -++ cppcr &= ~(regs->cppcr_mask | CPM_CPPCR_PLLS | CPM_CPPCR_PLLEN | CPM_CPPCR_PLLST_MASK); -++ regs->cppcr &= ~CPM_CPPCR_PLLEN; -++ cppcr |= (regs->cppcr | 0xff); -++ -++ /* Update some DRAM parameters before changing frequency */ -++ new_pll = JZ_EXTAL * ((cppcr>>23)+2) / ((((cppcr>>18)&0x1f)+2) * od[(cppcr>>16)&0x03]); -++ cur_mclk = __cpm_get_mclk(); -++ new_mclk = new_pll / div[(REG_CPM_CPCCR>>16) & 0xf]; -++ -++ /* -++ * Update some SDRAM parameters -++ */ -++ jz_update_dram_prev(cur_mclk, new_mclk); -++ -++ /* -++ * Update PLL, align code to cache line. -++ */ -++ cppcr |= CPM_CPPCR_PLLEN; -++ __asm__ __volatile__( -++ ".set noreorder\n\t" -++ ".align 5\n" -++ "sw %1,0(%0)\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ ".set reorder\n\t" -++ : -++ : "r" (CPM_CPPCR), "r" (cppcr)); -++ -++ /* Update some other DRAM parameters after changing frequency */ -++ jz_update_dram_post(cur_mclk, new_mclk); -++} -++#endif -++ -++static void jz4750_transition(struct dpm_regs *regs) -++{ -++ /* -++ * Get and save some boot-time conditions. -++ */ -++ jz_init_boot_config(); -++ -++#ifdef CHANGE_PLL -++ /* -++ * Disable LCD before scaling pll. -++ * LCD and LCD pixel clocks should not be changed even if the PLL -++ * output frequency has been changed. -++ */ -++ REG_LCD_CTRL &= ~LCD_CTRL_ENA; -++ -++ /* -++ * Stop module clocks before scaling PLL -++ */ -++ __cpm_stop_eth(); -++ __cpm_stop_aic(1); -++ __cpm_stop_aic(2); -++#endif -++ -++ /* ... add more as necessary */ -++ -++ if (regs->pll_up_flag == PLL_GOES_UP) { -++ /* the pll frequency is going up, so change dividors first */ -++ jz_scale_divisors(regs); -++#ifdef CHANGE_PLL -++ jz_scale_pll(regs); -++#endif -++ } -++ else if (regs->pll_up_flag == PLL_GOES_DOWN) { -++ /* the pll frequency is going down, so change pll first */ -++#ifdef CHANGE_PLL -++ jz_scale_pll(regs); -++#endif -++ jz_scale_divisors(regs); -++ } -++ else { -++ /* the pll frequency is unchanged, so change divisors only */ -++ jz_scale_divisors(regs); -++ } -++ -++#ifdef CHANGE_PLL -++ /* -++ * Restart module clocks before scaling PLL -++ */ -++ __cpm_start_eth(); -++ __cpm_start_aic(1); -++ __cpm_start_aic(2); -++ -++ /* ... add more as necessary */ -++ -++ /* Scale the LCD divisors after scaling pll */ -++ if (regs->pll_up_flag != PLL_UNCHANGED) { -++ jz_scale_lcd_divisors(regs); -++ } -++ -++ /* Enable LCD controller */ -++ REG_LCD_CTRL &= ~LCD_CTRL_DIS; -++ REG_LCD_CTRL |= LCD_CTRL_ENA; -++#endif -++ -++ /* Update system clocks */ -++ jz_update_clocks(); -++} -++ -++extern unsigned int idle_times; -++static unsigned int jz4750_freq_get(unsigned int cpu) -++{ -++ return (__cpm_get_cclk() / 1000); -++} -++ -++static unsigned int index_to_divisor(unsigned int index, struct dpm_regs *regs) -++{ -++ int n2FR[33] = { -++ 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, -++ 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, -++ 9 -++ }; -++ int div[4] = {1, 2, 2, 2}; /* divisors of I:S:P:M */ -++ unsigned int div_of_cclk, new_freq, i; -++ -++ regs->pll_up_flag = PLL_UNCHANGED; -++ regs->cpccr_mask = CPM_CPCCR_CDIV_MASK | CPM_CPCCR_HDIV_MASK | CPM_CPCCR_PDIV_MASK | CPM_CPCCR_MDIV_MASK; -++ -++ new_freq = jz4750_freq_table.table[index].frequency; -++ -++ do { -++ div_of_cclk = __cpm_get_pllout() / (1000 * new_freq); -++ } while (div_of_cclk==0); -++ -++ if(div_of_cclk == 1 || div_of_cclk == 2 || div_of_cclk == 4) { -++ for(i = 1; i<4; i++) { -++ div[i] = 3; -++ } -++ } else { -++ for(i = 1; i<4; i++) { -++ div[i] = 2; -++ } -++ } -++ -++ for(i = 0; i<4; i++) { -++ div[i] *= div_of_cclk; -++ } -++ -++ dprintk("divisors of I:S:P:M = %d:%d:%d:%d\n", div[0], div[1], div[2], div[3]); -++ -++ regs->cpccr = -++ (n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) | -++ (n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) | -++ (n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) | -++ (n2FR[div[3]] << CPM_CPCCR_MDIV_BIT); -++ -++ return div_of_cclk; -++} -++ -++static void jz4750_set_cpu_divider_index(unsigned int cpu, unsigned int index) -++{ -++ unsigned long divisor, old_divisor; -++ struct cpufreq_freqs freqs; -++ struct dpm_regs regs; -++ -++ old_divisor = __cpm_get_pllout() / __cpm_get_cclk(); -++ divisor = index_to_divisor(index, ®s); -++ -++ freqs.old = __cpm_get_cclk() / 1000; -++ freqs.new = __cpm_get_pllout() / (1000 * divisor); -++ freqs.cpu = cpu; -++ -++ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); -++ -++ if (old_divisor != divisor) -++ jz4750_transition(®s); -++ -++ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); -++} -++ -++static int jz4750_freq_target(struct cpufreq_policy *policy, -++ unsigned int target_freq, -++ unsigned int relation) -++{ -++ unsigned int new_index = 0; -++ -++ if (cpufreq_frequency_table_target(policy, -++ &jz4750_freq_table.table[0], -++ target_freq, relation, &new_index)) -++ return -EINVAL; -++ -++ jz4750_set_cpu_divider_index(policy->cpu, new_index); -++ -++ dprintk("new frequency is %d KHz (REG_CPM_CPCCR:0x%x)\n", __cpm_get_cclk() / 1000, REG_CPM_CPCCR); -++ -++ return 0; -++} -++ -++static int jz4750_freq_verify(struct cpufreq_policy *policy) -++{ -++ return cpufreq_frequency_table_verify(policy, -++ &jz4750_freq_table.table[0]); -++} -++ -++static int __init jz4750_cpufreq_driver_init(struct cpufreq_policy *policy) -++{ -++ -++ struct cpufreq_frequency_table *table = &jz4750_freq_table.table[0]; -++ unsigned int MAX_FREQ; -++ -++ dprintk(KERN_INFO "Jz4750 cpufreq driver\n"); -++ -++ if (policy->cpu != 0) -++ return -EINVAL; -++ -++ policy->cur = MAX_FREQ = __cpm_get_cclk() / 1000; /* in kHz. Current and max frequency is determined by u-boot */ -++ policy->governor = CPUFREQ_DEFAULT_GOVERNOR; -++ -++ policy->cpuinfo.min_freq = MAX_FREQ/8; -++ policy->cpuinfo.max_freq = MAX_FREQ; -++ policy->cpuinfo.transition_latency = 100000; /* in 10^(-9) s = nanoseconds */ -++ -++ table[0].index = 0; -++ table[0].frequency = MAX_FREQ/8; -++ table[1].index = 1; -++ table[1].frequency = MAX_FREQ/6; -++ table[2].index = 2; -++ table[2].frequency = MAX_FREQ/4; -++ table[3].index = 3; -++ table[3].frequency = MAX_FREQ/3; -++ table[4].index = 4; -++ table[4].frequency = MAX_FREQ/2; -++ table[5].index = 5; -++ table[5].frequency = MAX_FREQ; -++ table[6].index = 6; -++ table[6].frequency = CPUFREQ_TABLE_END; -++ -++#ifdef CONFIG_CPU_FREQ_STAT_DETAILS -++ cpufreq_frequency_table_get_attr(table, policy->cpu); /* for showing /sys/devices/system/cpu/cpuX/cpufreq/stats/ */ -++#endif -++ -++ return cpufreq_frequency_table_cpuinfo(policy, table); -++} -++ -++static struct cpufreq_driver cpufreq_jz4750_driver = { -++// .flags = CPUFREQ_STICKY, -++ .init = jz4750_cpufreq_driver_init, -++ .verify = jz4750_freq_verify, -++ .target = jz4750_freq_target, -++ .get = jz4750_freq_get, -++ .name = "jz4750", -++}; -++ -++static int __init jz4750_cpufreq_init(void) -++{ -++ return cpufreq_register_driver(&cpufreq_jz4750_driver); -++} -++ -++static void __exit jz4750_cpufreq_exit(void) -++{ -++ cpufreq_unregister_driver(&cpufreq_jz4750_driver); -++} -++ -++module_init(jz4750_cpufreq_init); -++module_exit(jz4750_cpufreq_exit); -++ -++MODULE_AUTHOR("Regen "); -++MODULE_DESCRIPTION("cpufreq driver for Jz4750"); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750/dma.c linux-2.6.24.7/arch/mips/jz4750/dma.c -+--- linux-2.6.24.7.old/arch/mips/jz4750/dma.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750/dma.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,836 @@ -++/* -++ * linux/arch/mips/jz4750/dma.c -++ * -++ * Support functions for the JZ4750 internal DMA channels. -++ * No-descriptor transfer only. -++ * Descriptor transfer should also call jz_request_dma() to get a free -++ * channel and call jz_free_dma() to free the channel. And driver should -++ * build the DMA descriptor and setup the DMA channel by itself. -++ * -++ * Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++ -++/* -++ * A note on resource allocation: -++ * -++ * All drivers needing DMA channels, should allocate and release them -++ * through the public routines `jz_request_dma()' and `jz_free_dma()'. -++ * -++ * In order to avoid problems, all processes should allocate resources in -++ * the same sequence and release them in the reverse order. -++ * -++ * So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ. -++ * When releasing them, first release the IRQ, then release the DMA. The -++ * main reason for this order is that, if you are requesting the DMA buffer -++ * done interrupt, you won't know the irq number until the DMA channel is -++ * returned from jz_request_dma(). -++ */ -++ -++struct jz_dma_chan jz_dma_table[MAX_DMA_NUM] = { -++ {dev_id:DMA_ID_BCH_ENC,}, /* DMAC0 channel 0, reserved for BCH */ -++ {dev_id:-1,}, /* DMAC0 channel 1 */ -++ {dev_id:-1,}, /* DMAC0 channel 2 */ -++ {dev_id:-1,}, /* DMAC0 channel 3 */ -++ {dev_id:-1,}, /* DMAC0 channel 4 */ -++ {dev_id:-1,}, /* DMAC0 channel 5 */ -++ {dev_id:-1,}, /* DMAC1 channel 0 */ -++ {dev_id:-1,}, /* DMAC1 channel 1 */ -++ {dev_id:-1,}, /* DMAC1 channel 2 */ -++ {dev_id:-1,}, /* DMAC1 channel 3 */ -++ {dev_id:-1,}, /* DMAC1 channel 4 */ -++ {dev_id:-1,}, /* DMAC1 channel 5 */ -++}; -++ -++// Device FIFO addresses and default DMA modes -++static const struct { -++ unsigned int fifo_addr; -++ unsigned int dma_mode; -++ unsigned int dma_source; -++} dma_dev_table[DMA_ID_MAX] = { -++ {0, DMA_AUTOINIT, DMAC_DRSR_RS_EXT}, /* External request with DREQn */ -++ {0x18000000, DMA_AUTOINIT, DMAC_DRSR_RS_NAND}, /* NAND request */ -++ {CPHYSADDR(BCH_DR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_BCH_ENC}, -++ {CPHYSADDR(BCH_DR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_BCH_DEC}, -++ {0, DMA_AUTOINIT, DMAC_DRSR_RS_AUTO}, -++// {CPHYSADDR(TSSI_FIFO), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_TSSIIN}, -++ {CPHYSADDR(UART3_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART3OUT}, -++ {CPHYSADDR(UART3_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART3IN}, -++ {CPHYSADDR(UART2_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART2OUT}, -++ {CPHYSADDR(UART2_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART2IN}, -++ {CPHYSADDR(UART1_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART1OUT}, -++ {CPHYSADDR(UART1_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART1IN}, -++ {CPHYSADDR(UART0_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART0OUT}, -++ {CPHYSADDR(UART0_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART0IN}, -++ {CPHYSADDR(SSI_DR(0)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSI0OUT}, -++ {CPHYSADDR(SSI_DR(0)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSI0IN}, -++ {CPHYSADDR(AIC_DR), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_AICOUT}, -++ {CPHYSADDR(AIC_DR), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_AICIN}, -++ {CPHYSADDR(MSC_TXFIFO(0)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSC0OUT}, -++ {CPHYSADDR(MSC_RXFIFO(0)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSC0IN}, -++ {0, DMA_AUTOINIT, DMAC_DRSR_RS_TCU}, -++ {SADC_TSDAT, DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SADC},/* Touch Screen Data Register */ -++ {CPHYSADDR(MSC_TXFIFO(1)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSC1OUT}, /* SSC1 TX */ -++ {CPHYSADDR(MSC_RXFIFO(1)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSC1IN}, /* SSC1 RX */ -++ {CPHYSADDR(SSI_DR(1)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSI1OUT}, -++ {CPHYSADDR(SSI_DR(1)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSI1IN}, -++ {CPHYSADDR(PCM_DP), DMA_16BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_PMOUT}, -++ {CPHYSADDR(PCM_DP), DMA_16BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_PMIN}, -++ {}, -++}; -++ -++ -++int jz_dma_read_proc(char *buf, char **start, off_t fpos, -++ int length, int *eof, void *data) -++{ -++ int i, len = 0; -++ struct jz_dma_chan *chan; -++ -++ for (i = 0; i < MAX_DMA_NUM; i++) { -++ if ((chan = get_dma_chan(i)) != NULL) { -++ len += sprintf(buf + len, "%2d: %s\n", -++ i, chan->dev_str); -++ } -++ } -++ -++ if (fpos >= len) { -++ *start = buf; -++ *eof = 1; -++ return 0; -++ } -++ *start = buf + fpos; -++ if ((len -= fpos) > length) -++ return length; -++ *eof = 1; -++ return len; -++} -++ -++ -++void dump_jz_dma_channel(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan; -++ -++ if (dmanr > MAX_DMA_NUM) -++ return; -++ chan = &jz_dma_table[dmanr]; -++ -++ printk("DMA%d Registers:\n", dmanr); -++ printk(" DMACR = 0x%08x\n", REG_DMAC_DMACR(chan->io/HALF_DMA_NUM)); -++ printk(" DSAR = 0x%08x\n", REG_DMAC_DSAR(dmanr)); -++ printk(" DTAR = 0x%08x\n", REG_DMAC_DTAR(dmanr)); -++ printk(" DTCR = 0x%08x\n", REG_DMAC_DTCR(dmanr)); -++ printk(" DRSR = 0x%08x\n", REG_DMAC_DRSR(dmanr)); -++ printk(" DCCSR = 0x%08x\n", REG_DMAC_DCCSR(dmanr)); -++ printk(" DCMD = 0x%08x\n", REG_DMAC_DCMD(dmanr)); -++ printk(" DDA = 0x%08x\n", REG_DMAC_DDA(dmanr)); -++ printk(" DMADBR = 0x%08x\n", REG_DMAC_DMADBR(chan->io/HALF_DMA_NUM)); -++} -++ -++ -++/** -++ * jz_request_dma - dynamically allcate an idle DMA channel to return -++ * @dev_id: the specified dma device id or DMA_ID_RAW_SET -++ * @dev_str: the specified dma device string name -++ * @irqhandler: the irq handler, or NULL -++ * @irqflags: the irq handler flags -++ * @irq_dev_id: the irq handler device id for shared irq -++ * -++ * Finds a free channel, and binds the requested device to it. -++ * Returns the allocated channel number, or negative on error. -++ * Requests the DMA done IRQ if irqhandler != NULL. -++ * -++*/ -++/*int jz_request_dma(int dev_id, const char *dev_str, -++ void (*irqhandler)(int, void *, struct pt_regs *), -++ unsigned long irqflags, -++ void *irq_dev_id) -++*/ -++ -++int jz_request_dma(int dev_id, const char *dev_str, -++ irqreturn_t (*irqhandler)(int, void *), -++ unsigned long irqflags, -++ void *irq_dev_id) -++{ -++ struct jz_dma_chan *chan; -++ int i, ret, chan0; -++ -++ if (dev_id < 0 || dev_id >= DMA_ID_MAX) -++ return -EINVAL; -++ -++ /* Because of a bug in DMA controller of jz4750, which causes auto -++ request and device request can't be allocated in a same DMA -++ controller, all device requests should be put in the second DMA -++ controller -++ */ -++ if (dev_id > DMA_ID_AUTO) -++ chan0 = 6; -++ else -++ chan0 = 0; -++ -++ for (i = chan0; i < MAX_DMA_NUM; i++) { -++ if (jz_dma_table[i].dev_id < 0) -++ break; -++ } -++ if (i == MAX_DMA_NUM) /* no free channel */ -++ return -ENODEV; -++ -++ /* we got a free channel */ -++ chan = &jz_dma_table[i]; -++ -++ if (irqhandler) { -++ chan->irq = IRQ_DMA_0 + i; // allocate irq number -++ chan->irq_dev = irq_dev_id; -++ if ((ret = request_irq(chan->irq, irqhandler, irqflags, -++ dev_str, chan->irq_dev))) { -++ chan->irq = -1; -++ chan->irq_dev = NULL; -++ return ret; -++ } -++ } else { -++ chan->irq = -1; -++ chan->irq_dev = NULL; -++ } -++ -++ // fill it in -++ chan->io = i; -++ chan->dev_id = dev_id; -++ chan->dev_str = dev_str; -++ chan->fifo_addr = dma_dev_table[dev_id].fifo_addr; -++ chan->mode = dma_dev_table[dev_id].dma_mode; -++ chan->source = dma_dev_table[dev_id].dma_source; -++ -++ if (i < 6) -++ REG_DMAC_DMACKE(0) = 1 << i; -++ else -++ REG_DMAC_DMACKE(1) = 1 << (i - 6); -++ -++ return i; -++} -++ -++void jz_free_dma(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) { -++ printk("Trying to free DMA%d\n", dmanr); -++ return; -++ } -++ -++ disable_dma(dmanr); -++ if (chan->irq) -++ free_irq(chan->irq, chan->irq_dev); -++ -++ chan->irq = -1; -++ chan->irq_dev = NULL; -++ chan->dev_id = -1; -++} -++ -++void jz_set_dma_dest_width(int dmanr, int nbit) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ chan->mode &= ~DMAC_DCMD_DWDH_MASK; -++ switch (nbit) { -++ case 8: -++ chan->mode |= DMAC_DCMD_DWDH_8; -++ break; -++ case 16: -++ chan->mode |= DMAC_DCMD_DWDH_16; -++ break; -++ case 32: -++ chan->mode |= DMAC_DCMD_DWDH_32; -++ break; -++ } -++} -++ -++void jz_set_dma_src_width(int dmanr, int nbit) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ chan->mode &= ~DMAC_DCMD_SWDH_MASK; -++ switch (nbit) { -++ case 8: -++ chan->mode |= DMAC_DCMD_SWDH_8; -++ break; -++ case 16: -++ chan->mode |= DMAC_DCMD_SWDH_16; -++ break; -++ case 32: -++ chan->mode |= DMAC_DCMD_SWDH_32; -++ break; -++ } -++} -++ -++void jz_set_dma_block_size(int dmanr, int nbyte) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ chan->mode &= ~DMAC_DCMD_DS_MASK; -++ switch (nbyte) { -++ case 1: -++ chan->mode |= DMAC_DCMD_DS_8BIT; -++ break; -++ case 2: -++ chan->mode |= DMAC_DCMD_DS_16BIT; -++ break; -++ case 4: -++ chan->mode |= DMAC_DCMD_DS_32BIT; -++ break; -++ case 16: -++ chan->mode |= DMAC_DCMD_DS_16BYTE; -++ break; -++ case 32: -++ chan->mode |= DMAC_DCMD_DS_32BYTE; -++ break; -++ } -++} -++ -++unsigned int jz_get_dma_command(int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ return chan->mode; -++} -++ -++/** -++ * jz_set_dma_mode - do the raw settings for the specified DMA channel -++ * @dmanr: the specified DMA channel -++ * @mode: dma operate mode, DMA_MODE_READ or DMA_MODE_WRITE -++ * @dma_mode: dma raw mode -++ * @dma_source: dma raw request source -++ * @fifo_addr: dma raw device fifo address -++ * -++ * Ensure call jz_request_dma(DMA_ID_RAW_SET, ...) first, then call -++ * jz_set_dma_mode() rather than set_dma_mode() if you work with -++ * and external request dma device. -++ * -++ * NOTE: Don not dynamically allocate dma channel if one external request -++ * dma device will occupy this channel. -++*/ -++int jz_set_dma_mode(unsigned int dmanr, unsigned int mode, -++ unsigned int dma_mode, unsigned int dma_source, -++ unsigned int fifo_addr) -++{ -++ int dev_id, i; -++ struct jz_dma_chan *chan; -++ -++ if (dmanr > MAX_DMA_NUM) -++ return -ENODEV; -++ for (i = 0; i < MAX_DMA_NUM; i++) { -++ if (jz_dma_table[i].dev_id < 0) -++ break; -++ } -++ if (i == MAX_DMA_NUM) -++ return -ENODEV; -++ -++ chan = &jz_dma_table[dmanr]; -++ dev_id = chan->dev_id; -++ if (dev_id > 0) { -++ printk(KERN_DEBUG "%s sets the allocated DMA channel %d!\n", -++ __FUNCTION__, dmanr); -++ return -ENODEV; -++ } -++ -++ /* clone it from the dynamically allocated. */ -++ if (i != dmanr) { -++ chan->irq = jz_dma_table[i].irq; -++ chan->irq_dev = jz_dma_table[i].irq_dev; -++ chan->dev_str = jz_dma_table[i].dev_str; -++ jz_dma_table[i].irq = 0; -++ jz_dma_table[i].irq_dev = NULL; -++ jz_dma_table[i].dev_id = -1; -++ } -++ chan->dev_id = DMA_ID_RAW_SET; -++ chan->io = dmanr; -++ chan->fifo_addr = fifo_addr; -++ chan->mode = dma_mode; -++ chan->source = dma_source; -++ -++ set_dma_mode(dmanr, dma_mode); -++ -++ return dmanr; -++} -++ -++void enable_dma(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ REG_DMAC_DCCSR(dmanr) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -++ REG_DMAC_DCCSR(dmanr) |= DMAC_DCCSR_NDES; /* No-descriptor transfer */ -++ __dmac_enable_channel(dmanr); -++ if (chan->irq) -++ __dmac_channel_enable_irq(dmanr); -++} -++ -++#define DMA_DISABLE_POLL 0x10000 -++ -++void disable_dma(unsigned int dmanr) -++{ -++ int i; -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ if (!__dmac_channel_enabled(dmanr)) -++ return; -++ -++ for (i = 0; i < DMA_DISABLE_POLL; i++) -++ if (__dmac_channel_transmit_end_detected(dmanr)) -++ break; -++#if 0 -++ if (i == DMA_DISABLE_POLL) -++ printk(KERN_INFO "disable_dma: poll expired!\n"); -++#endif -++ -++ __dmac_disable_channel(dmanr); -++ if (chan->irq) -++ __dmac_channel_disable_irq(dmanr); -++} -++ -++/* Note: DMA_MODE_MASK is simulated by sw */ -++void set_dma_mode(unsigned int dmanr, unsigned int mode) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -++ mode &= DMA_MODE_MASK; -++ if (mode == DMA_MODE_READ) { -++ chan->mode |= DMAC_DCMD_DAI; -++ chan->mode &= ~DMAC_DCMD_SAI; -++ } else if (mode == DMA_MODE_WRITE) { -++ chan->mode |= DMAC_DCMD_SAI; -++ chan->mode &= ~DMAC_DCMD_DAI; -++ } else { -++ printk(KERN_DEBUG "set_dma_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -++ } -++ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -++ REG_DMAC_DRSR(chan->io) = chan->source; -++} -++ -++void set_dma_addr(unsigned int dmanr, unsigned int phyaddr) -++{ -++ unsigned int mode; -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ mode = chan->mode & DMA_MODE_MASK; -++ if (mode == DMA_MODE_READ) { -++ REG_DMAC_DSAR(chan->io) = chan->fifo_addr; -++ REG_DMAC_DTAR(chan->io) = phyaddr; -++ } else if (mode == DMA_MODE_WRITE) { -++ REG_DMAC_DSAR(chan->io) = phyaddr; -++ REG_DMAC_DTAR(chan->io) = chan->fifo_addr; -++ } else -++ printk(KERN_DEBUG "Driver should call set_dma_mode() ahead set_dma_addr()!\n"); -++} -++ -++void set_dma_count(unsigned int dmanr, unsigned int bytecnt) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ int dma_ds[] = {4, 1, 2, 16, 32}; -++ unsigned int ds; -++ -++ if (!chan) -++ return; -++ -++ ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT; -++ REG_DMAC_DTCR(chan->io) = bytecnt / dma_ds[ds]; // transfer count -++} -++ -++unsigned int get_dma_residue(unsigned int dmanr) -++{ -++ unsigned int count, ds; -++ int dma_ds[] = {4, 1, 2, 16, 32}; -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return 0; -++ -++ ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT; -++ count = REG_DMAC_DTCR(chan->io); -++ count = count * dma_ds[ds]; -++ -++ return count; -++} -++ -++void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ switch (audio_fmt) { -++ case AFMT_U8: -++ /* burst mode : 32BIT */ -++ break; -++ case AFMT_S16_LE: -++ /* burst mode : 16BYTE */ -++ if (mode == DMA_MODE_READ) { -++ chan->mode = DMA_AIC_32_16BYTE_RX_CMD | DMA_MODE_READ; -++ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -++ mode &= DMA_MODE_MASK; -++ chan->mode |= DMAC_DCMD_DAI; -++ chan->mode &= ~DMAC_DCMD_SAI; -++ } else if (mode == DMA_MODE_WRITE) { -++ chan->mode = DMA_AIC_32_16BYTE_TX_CMD | DMA_MODE_WRITE; -++ //chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE; -++ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -++ mode &= DMA_MODE_MASK; -++ chan->mode |= DMAC_DCMD_SAI; -++ chan->mode &= ~DMAC_DCMD_DAI; -++ } else -++ printk("oss_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -++ -++ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -++ REG_DMAC_DRSR(chan->io) = chan->source; -++ break; -++ } -++} -++ -++void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ switch (audio_fmt) { -++ case 8: -++ /* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */ -++ break; -++ case 16: -++ /* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */ -++ if (mode == DMA_MODE_READ) { -++ chan->mode = DMA_AIC_16BYTE_RX_CMD | DMA_MODE_READ; -++ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -++ mode &= DMA_MODE_MASK; -++ chan->mode |= DMAC_DCMD_DAI; -++ chan->mode &= ~DMAC_DCMD_SAI; -++ } else if (mode == DMA_MODE_WRITE) { -++ chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE; -++ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -++ mode &= DMA_MODE_MASK; -++ chan->mode |= DMAC_DCMD_SAI; -++ chan->mode &= ~DMAC_DCMD_DAI; -++ } else -++ printk("alsa_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -++ -++ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -++ REG_DMAC_DRSR(chan->io) = chan->source; -++ break; -++ } -++} -++ -++//#define JZ4750_DMAC_TEST_ENABLE -++#undef JZ4750_DMAC_TEST_ENABLE -++ -++#ifdef JZ4750_DMAC_TEST_ENABLE -++ -++/* -++ * DMA test: external address <--> external address -++ */ -++#define TEST_DMA_SIZE 16*1024 -++ -++static jz_dma_desc *dma_desc; -++ -++static int dma_chan; -++static dma_addr_t dma_desc_phys_addr; -++static unsigned int dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr; -++ -++static int dma_check_result(void *src, void *dst, int size) -++{ -++ unsigned int addr1, addr2, i, err = 0; -++ -++ addr1 = (unsigned int)src; -++ addr2 = (unsigned int)dst; -++ -++ for (i = 0; i < size; i += 4) { -++ if (*(volatile unsigned int *)addr1 != *(volatile unsigned int *)addr2) { -++ err++; -++ printk("wrong data at 0x%08x: src 0x%08x dst 0x%08x\n", addr2, *(volatile unsigned int *)addr1, *(volatile unsigned int *)addr2); -++ } -++ addr1 += 4; -++ addr2 += 4; -++ } -++ printk("check DMA result err=%d\n", err); -++ return err; -++} -++ -++static irqreturn_t jz4750_dma_irq(int irq, void *dev_id) -++{ -++ printk("jz4750_dma_irq %d\n", irq); -++ -++ -++ if (__dmac_channel_transmit_halt_detected(dma_chan)) { -++ printk("DMA HALT\n"); -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ __dmac_channel_clear_transmit_halt(dma_chan); -++ } -++ -++ if (__dmac_channel_address_error_detected(dma_chan)) { -++ printk("DMA ADDR ERROR\n"); -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ REG_DMAC_DSAR(dma_chan) = 0; /* clear source address register */ -++ REG_DMAC_DTAR(dma_chan) = 0; /* clear target address register */ -++ __dmac_channel_clear_address_error(dma_chan); -++ } -++ -++ if (__dmac_channel_descriptor_invalid_detected(dma_chan)) { -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ printk("DMA DESC INVALID\n"); -++ __dmac_channel_clear_descriptor_invalid(dma_chan); -++ } -++ -++ if (__dmac_channel_count_terminated_detected(dma_chan)) { -++ printk("DMA CT\n"); -++ __dmac_channel_clear_count_terminated(dma_chan); -++ } -++ -++ if (__dmac_channel_transmit_end_detected(dma_chan)) { -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ printk("DMA TT\n"); -++ __dmac_channel_clear_transmit_end(dma_chan); -++ dump_jz_dma_channel(dma_chan); -++ dma_check_result((void *)dma_src_addr, (void *)dma_dst_addr, TEST_DMA_SIZE); -++ } -++ -++ return IRQ_HANDLED; -++} -++ -++void dma_nodesc_test(void) -++{ -++ unsigned int addr, i; -++ -++ printk("dma_nodesc_test\n"); -++ -++ /* Request DMA channel and setup irq handler */ -++ dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4750_dma_irq, -++ IRQF_DISABLED, NULL); -++ if (dma_chan < 0) { -++ printk("Setup irq failed\n"); -++ return; -++ } -++ -++ printk("Requested DMA channel = %d\n", dma_chan); -++ -++ /* Allocate DMA buffers */ -++ dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -++ dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -++ -++ dma_src_phys_addr = CPHYSADDR(dma_src_addr); -++ dma_dst_phys_addr = CPHYSADDR(dma_dst_addr); -++ -++ printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n", -++ dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr); -++ -++ /* Prepare data for source buffer */ -++ addr = (unsigned int)dma_src_addr; -++ for (i = 0; i < TEST_DMA_SIZE; i += 4) { -++ *(volatile unsigned int *)addr = addr; -++ addr += 4; -++ } -++ dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE); -++ -++ /* Init target buffer */ -++ memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE); -++ dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE); -++ -++ /* Init DMA module */ -++ printk("Starting DMA\n"); -++ REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = 0; -++ REG_DMAC_DCCSR(dma_chan) = 0; -++ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; -++ REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr; -++ REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr; -++ REG_DMAC_DTCR(dma_chan) = 512; -++ REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TIE; -++ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; -++ REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = DMAC_DMACR_DMAE; /* global DMA enable bit */ -++ -++ printk("DMA started. IMR=%08x\n", REG_INTC_IMR); -++ -++ /* wait a long time, ensure transfer end */ -++ printk("wait 3s...\n"); -++ mdelay(3000); /* wait 3s */ -++ -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ /* free buffers */ -++ printk("free DMA buffers\n"); -++ free_pages(dma_src_addr, 2); -++ free_pages(dma_dst_addr, 2); -++ -++ if (dma_desc) -++ free_pages((unsigned int)dma_desc, 0); -++ -++ /* free dma */ -++ jz_free_dma(dma_chan); -++} -++ -++void dma_desc_test(void) -++{ -++ unsigned int next, addr, i; -++ static jz_dma_desc *desc; -++ -++ printk("dma_desc_test\n"); -++ -++ /* Request DMA channel and setup irq handler */ -++ dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4750_dma_irq, -++ IRQF_DISABLED, NULL); -++ if (dma_chan < 0) { -++ printk("Setup irq failed\n"); -++ return; -++ } -++ -++ printk("Requested DMA channel = %d\n", dma_chan); -++ -++ /* Allocate DMA buffers */ -++ dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -++ dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -++ -++ dma_src_phys_addr = CPHYSADDR(dma_src_addr); -++ dma_dst_phys_addr = CPHYSADDR(dma_dst_addr); -++ -++ printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n", -++ dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr); -++ -++ /* Prepare data for source buffer */ -++ addr = (unsigned int)dma_src_addr; -++ for (i = 0; i < TEST_DMA_SIZE; i += 4) { -++ *(volatile unsigned int *)addr = addr; -++ addr += 4; -++ } -++ dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE); -++ -++ /* Init target buffer */ -++ memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE); -++ dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE); -++ -++ /* Allocate DMA descriptors */ -++ dma_desc = (jz_dma_desc *)__get_free_pages(GFP_KERNEL, 0); -++ dma_desc_phys_addr = CPHYSADDR((unsigned long)dma_desc); -++ -++ printk("DMA descriptor address: 0x%08x 0x%08x\n", (u32)dma_desc, dma_desc_phys_addr); -++ -++ /* Setup DMA descriptors */ -++ desc = dma_desc; -++ next = (dma_desc_phys_addr + (sizeof(jz_dma_desc))) >> 4; -++ -++ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -++ desc->dsadr = dma_src_phys_addr; /* DMA source address */ -++ desc->dtadr = dma_dst_phys_addr; /* DMA target address */ -++ desc->ddadr = (next << 24) + 128; /* size: 128*32 bytes = 4096 bytes */ -++ -++ desc++; -++ next = (dma_desc_phys_addr + 2*(sizeof(jz_dma_desc))) >> 4; -++ -++ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -++ desc->dsadr = dma_src_phys_addr + 4096; /* DMA source address */ -++ desc->dtadr = dma_dst_phys_addr + 4096; /* DMA target address */ -++ desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */ -++ -++ desc++; -++ next = (dma_desc_phys_addr + 3*(sizeof(jz_dma_desc))) >> 4; -++ -++ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -++ desc->dsadr = dma_src_phys_addr + 8192; /* DMA source address */ -++ desc->dtadr = dma_dst_phys_addr + 8192; /* DMA target address */ -++ desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */ -++ -++ desc++; -++ next = (dma_desc_phys_addr + 4*(sizeof(jz_dma_desc))) >> 4; -++ -++ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE; -++ desc->dsadr = dma_src_phys_addr + 12*1024; /* DMA source address */ -++ desc->dtadr = dma_dst_phys_addr + 12*1024; /* DMA target address */ -++ desc->ddadr = (next << 24) + 1024; /* size: 1024*4 bytes = 4096 bytes */ -++ -++ dma_cache_wback((unsigned long)dma_desc, 4*(sizeof(jz_dma_desc))); -++ -++ /* Setup DMA descriptor address */ -++ REG_DMAC_DDA(dma_chan) = dma_desc_phys_addr; -++ -++ /* Setup request source */ -++ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; -++ -++ /* Setup DMA channel control/status register */ -++ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; /* descriptor transfer, clear status, start channel */ -++ -++ /* Enable DMA */ -++ REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = DMAC_DMACR_DMAE; -++ -++ /* DMA doorbell set -- start DMA now ... */ -++ REG_DMAC_DMADBSR(dma_chan/HALF_DMA_NUM) = 1 << dma_chan; -++ -++ printk("DMA started. IMR=%08x\n", REG_INTC_IMR); -++ /* wait a long time, ensure transfer end */ -++ printk("wait 3s...\n"); -++ mdelay(3000); /* wait 3s */ -++ -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ /* free buffers */ -++ printk("free DMA buffers\n"); -++ free_pages(dma_src_addr, 2); -++ free_pages(dma_dst_addr, 2); -++ -++ if (dma_desc) -++ free_pages((unsigned int)dma_desc, 0); -++ -++ /* free dma */ -++ jz_free_dma(dma_chan); -++} -++ -++#endif -++ -++//EXPORT_SYMBOL_NOVERS(jz_dma_table); -++EXPORT_SYMBOL(jz_dma_table); -++EXPORT_SYMBOL(jz_request_dma); -++EXPORT_SYMBOL(jz_free_dma); -++EXPORT_SYMBOL(jz_set_dma_src_width); -++EXPORT_SYMBOL(jz_set_dma_dest_width); -++EXPORT_SYMBOL(jz_set_dma_block_size); -++EXPORT_SYMBOL(jz_set_dma_mode); -++EXPORT_SYMBOL(set_dma_mode); -++EXPORT_SYMBOL(jz_set_oss_dma); -++EXPORT_SYMBOL(jz_set_alsa_dma); -++EXPORT_SYMBOL(set_dma_addr); -++EXPORT_SYMBOL(set_dma_count); -++EXPORT_SYMBOL(get_dma_residue); -++EXPORT_SYMBOL(enable_dma); -++EXPORT_SYMBOL(disable_dma); -++EXPORT_SYMBOL(dump_jz_dma_channel); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750/i2c.c linux-2.6.24.7/arch/mips/jz4750/i2c.c -+--- linux-2.6.24.7.old/arch/mips/jz4750/i2c.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750/i2c.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,273 @@ -++/* -++ * linux/arch/mips/jz4750/i2c.c -++ * -++ * Jz4750 I2C routines. -++ * -++ * Copyright (C) 2005,2006 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can distribute it and/or modify it -++ * under the terms of the GNU General Public License (Version 2) as -++ * published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -++ * -++ */ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++ -++/* I2C protocol */ -++#define I2C_READ 1 -++#define I2C_WRITE 0 -++ -++#define TIMEOUT 1000 -++ -++/* -++ * I2C bus protocol basic routines -++ */ -++static int i2c_put_data(unsigned char data) -++{ -++ unsigned int timeout = TIMEOUT*10; -++ -++ __i2c_write(data); -++ __i2c_set_drf(); -++ while (__i2c_check_drf() != 0); -++ while (!__i2c_transmit_ended()); -++ while (!__i2c_received_ack() && timeout) -++ timeout--; -++ -++ if (timeout) -++ return 0; -++ else -++ return -ETIMEDOUT; -++} -++ -++#ifdef CONFIG_JZ_TPANEL_ATA2508 -++static int i2c_put_data_nack(unsigned char data) -++{ -++ unsigned int timeout = TIMEOUT*10; -++ -++ __i2c_write(data); -++ __i2c_set_drf(); -++ while (__i2c_check_drf() != 0); -++ while (!__i2c_transmit_ended()); -++ while (timeout--); -++ return 0; -++} -++#endif -++ -++static int i2c_get_data(unsigned char *data, int ack) -++{ -++ int timeout = TIMEOUT*10; -++ -++ if (!ack) -++ __i2c_send_nack(); -++ else -++ __i2c_send_ack(); -++ -++ while (__i2c_check_drf() == 0 && timeout) -++ timeout--; -++ -++ if (timeout) { -++ if (!ack) -++ __i2c_send_stop(); -++ *data = __i2c_read(); -++ __i2c_clear_drf(); -++ return 0; -++ } else -++ return -ETIMEDOUT; -++} -++ -++/* -++ * I2C interface -++ */ -++void i2c_open(void) -++{ -++ __i2c_set_clk(jz_clocks.extalclk, 10000); /* default 10 KHz */ -++ __i2c_enable(); -++} -++ -++void i2c_close(void) -++{ -++ udelay(300); /* wait for STOP goes over. */ -++ __i2c_disable(); -++} -++ -++void i2c_setclk(unsigned int i2cclk) -++{ -++ __i2c_set_clk(jz_clocks.extalclk, i2cclk); -++} -++ -++int i2c_lseek(unsigned char device, unsigned char offset) -++{ -++ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -++ goto device_err; -++ if (i2c_put_data(offset) < 0) -++ goto address_err; -++ return 0; -++ device_err: -++ printk(KERN_DEBUG "No I2C device (0x%02x) installed.\n", device); -++ __i2c_send_stop(); -++ return -ENODEV; -++ address_err: -++ printk(KERN_DEBUG "No I2C device (0x%02x) response.\n", device); -++ __i2c_send_stop(); -++ return -EREMOTEIO; -++} -++ -++int i2c_read(unsigned char device, unsigned char *buf, -++ unsigned char address, int count) -++{ -++ int cnt = count; -++ int timeout = 5; -++ -++L_try_again: -++ -++ if (timeout < 0) -++ goto L_timeout; -++ -++ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -++ goto device_werr; -++ if (i2c_put_data(address) < 0) -++ goto address_err; -++ -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_READ ) < 0) -++ goto device_rerr; -++ __i2c_send_ack(); /* Master sends ACK for continue reading */ -++ while (cnt) { -++ if (cnt == 1) { -++ if (i2c_get_data(buf, 0) < 0) -++ break; -++ } else { -++ if (i2c_get_data(buf, 1) < 0) -++ break; -++ } -++ cnt--; -++ buf++; -++ } -++ -++ __i2c_send_stop(); -++ return count - cnt; -++ device_rerr: -++ device_werr: -++ address_err: -++ timeout --; -++ __i2c_send_stop(); -++ goto L_try_again; -++ -++L_timeout: -++ __i2c_send_stop(); -++ printk("Read I2C device 0x%2x failed.\n", device); -++ return -ENODEV; -++} -++ -++int i2c_write(unsigned char device, unsigned char *buf, -++ unsigned char address, int count) -++{ -++ int cnt = count; -++ int cnt_in_pg; -++ int timeout = 5; -++ unsigned char *tmpbuf; -++ unsigned char tmpaddr; -++ -++ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -++ -++ W_try_again: -++ if (timeout < 0) -++ goto W_timeout; -++ -++ cnt = count; -++ tmpbuf = (unsigned char *)buf; -++ tmpaddr = address; -++ -++ start_write_page: -++ cnt_in_pg = 0; -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -++ goto device_err; -++#ifdef CONFIG_JZ_TPANEL_ATA2508 -++ if (address == 0xff) { -++ if (i2c_put_data_nack(tmpaddr) < 0) -++ goto address_err; -++ while (cnt) { -++ if (++cnt_in_pg > 8) { -++ __i2c_send_stop(); -++ mdelay(1); -++ tmpaddr += 8; -++ goto start_write_page; -++ } -++ if (i2c_put_data_nack(*tmpbuf) < 0) -++ break; -++ cnt--; -++ tmpbuf++; -++ } -++ } -++ else { -++ -++ if (i2c_put_data(tmpaddr) < 0) -++ goto address_err; -++ while (cnt) { -++ if (++cnt_in_pg > 8) { -++ __i2c_send_stop(); -++ mdelay(1); -++ tmpaddr += 8; -++ goto start_write_page; -++ } -++ if (i2c_put_data(*tmpbuf) < 0) -++ break; -++ cnt--; -++ tmpbuf++; -++ } -++ } -++#else -++ if (i2c_put_data(tmpaddr) < 0) -++ goto address_err; -++ while (cnt) { -++ if (++cnt_in_pg > 8) { -++ __i2c_send_stop(); -++ mdelay(1); -++ tmpaddr += 8; -++ goto start_write_page; -++ } -++ if (i2c_put_data(*tmpbuf) < 0) -++ break; -++ cnt--; -++ tmpbuf++; -++ } -++#endif -++ __i2c_send_stop(); -++ return count - cnt; -++ device_err: -++ address_err: -++ timeout--; -++ __i2c_send_stop(); -++ goto W_try_again; -++ -++ W_timeout: -++ printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device); -++ __i2c_send_stop(); -++ return -ENODEV; -++} -++ -++EXPORT_SYMBOL(i2c_open); -++EXPORT_SYMBOL(i2c_close); -++EXPORT_SYMBOL(i2c_setclk); -++EXPORT_SYMBOL(i2c_read); -++EXPORT_SYMBOL(i2c_write); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750/irq.c linux-2.6.24.7/arch/mips/jz4750/irq.c -+--- linux-2.6.24.7.old/arch/mips/jz4750/irq.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750/irq.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,299 @@ -++/* -++ * linux/arch/mips/jz4750/irq.c -++ * -++ * JZ4750 interrupt routines. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++ -++/* -++ * INTC irq type -++ */ -++ -++static void enable_intc_irq(unsigned int irq) -++{ -++ __intc_unmask_irq(irq); -++} -++ -++static void disable_intc_irq(unsigned int irq) -++{ -++ __intc_mask_irq(irq); -++} -++ -++static void mask_and_ack_intc_irq(unsigned int irq) -++{ -++ __intc_mask_irq(irq); -++ __intc_ack_irq(irq); -++} -++ -++static void end_intc_irq(unsigned int irq) -++{ -++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -++ enable_intc_irq(irq); -++ } -++} -++ -++static unsigned int startup_intc_irq(unsigned int irq) -++{ -++ enable_intc_irq(irq); -++ return 0; -++} -++ -++static void shutdown_intc_irq(unsigned int irq) -++{ -++ disable_intc_irq(irq); -++} -++ -++static struct irq_chip intc_irq_type = { -++ .typename = "INTC", -++ .startup = startup_intc_irq, -++ .shutdown = shutdown_intc_irq, -++ .enable = enable_intc_irq, -++ .disable = disable_intc_irq, -++ .ack = mask_and_ack_intc_irq, -++ .end = end_intc_irq, -++}; -++ -++/* -++ * GPIO irq type -++ */ -++ -++static void enable_gpio_irq(unsigned int irq) -++{ -++ unsigned int intc_irq; -++ -++ if (irq < (IRQ_GPIO_0 + 32)) { -++ intc_irq = IRQ_GPIO0; -++ } -++ else if (irq < (IRQ_GPIO_0 + 64)) { -++ intc_irq = IRQ_GPIO1; -++ } -++ else if (irq < (IRQ_GPIO_0 + 96)) { -++ intc_irq = IRQ_GPIO2; -++ } -++ else if (irq < (IRQ_GPIO_0 + 128)) { -++ intc_irq = IRQ_GPIO3; -++ } -++ else if (irq < (IRQ_GPIO_0 + 160)) { -++ intc_irq = IRQ_GPIO4; -++ } -++ else { -++ intc_irq = IRQ_GPIO5; -++ } -++ -++ enable_intc_irq(intc_irq); -++ __gpio_unmask_irq(irq - IRQ_GPIO_0); -++} -++ -++static void disable_gpio_irq(unsigned int irq) -++{ -++ __gpio_mask_irq(irq - IRQ_GPIO_0); -++} -++ -++static void mask_and_ack_gpio_irq(unsigned int irq) -++{ -++ __gpio_mask_irq(irq - IRQ_GPIO_0); -++ __gpio_ack_irq(irq - IRQ_GPIO_0); -++} -++ -++static void end_gpio_irq(unsigned int irq) -++{ -++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -++ enable_gpio_irq(irq); -++ } -++} -++ -++static unsigned int startup_gpio_irq(unsigned int irq) -++{ -++ enable_gpio_irq(irq); -++ return 0; -++} -++ -++static void shutdown_gpio_irq(unsigned int irq) -++{ -++ disable_gpio_irq(irq); -++} -++ -++static struct irq_chip gpio_irq_type = { -++ .typename = "GPIO", -++ .startup = startup_gpio_irq, -++ .shutdown = shutdown_gpio_irq, -++ .enable = enable_gpio_irq, -++ .disable = disable_gpio_irq, -++ .ack = mask_and_ack_gpio_irq, -++ .end = end_gpio_irq, -++}; -++ -++/* -++ * DMA irq type -++ */ -++ -++static void enable_dma_irq(unsigned int irq) -++{ -++ unsigned int intc_irq; -++ -++ if ( irq < (IRQ_DMA_0 + HALF_DMA_NUM) ) /* DMAC Group 0 irq */ -++ intc_irq = IRQ_DMAC0; -++ else if ( irq < (IRQ_DMA_0 + MAX_DMA_NUM) ) /* DMAC Group 1 irq */ -++ intc_irq = IRQ_DMAC1; -++ else { -++ printk("%s, unexpected dma irq #%d\n", __FILE__, irq); -++ return; -++ } -++ __intc_unmask_irq(intc_irq); -++ __dmac_channel_enable_irq(irq - IRQ_DMA_0); -++} -++ -++static void disable_dma_irq(unsigned int irq) -++{ -++ __dmac_channel_disable_irq(irq - IRQ_DMA_0); -++} -++ -++static void mask_and_ack_dma_irq(unsigned int irq) -++{ -++ unsigned int intc_irq; -++ -++ if ( irq < (IRQ_DMA_0 + HALF_DMA_NUM) ) /* DMAC Group 0 irq */ -++ intc_irq = IRQ_DMAC0; -++ else if ( irq < (IRQ_DMA_0 + MAX_DMA_NUM) ) /* DMAC Group 1 irq */ -++ intc_irq = IRQ_DMAC1; -++ else { -++ printk("%s, unexpected dma irq #%d\n", __FILE__, irq); -++ return ; -++ } -++ __intc_ack_irq(intc_irq); -++ __dmac_channel_ack_irq(irq-IRQ_DMA_0); /* needed?? add 20080506, Wolfgang */ -++ __dmac_channel_disable_irq(irq - IRQ_DMA_0); -++} -++ -++static void end_dma_irq(unsigned int irq) -++{ -++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -++ enable_dma_irq(irq); -++ } -++} -++ -++static unsigned int startup_dma_irq(unsigned int irq) -++{ -++ enable_dma_irq(irq); -++ return 0; -++} -++ -++static void shutdown_dma_irq(unsigned int irq) -++{ -++ disable_dma_irq(irq); -++} -++ -++static struct irq_chip dma_irq_type = { -++ .typename = "DMA", -++ .startup = startup_dma_irq, -++ .shutdown = shutdown_dma_irq, -++ .enable = enable_dma_irq, -++ .disable = disable_dma_irq, -++ .ack = mask_and_ack_dma_irq, -++ .end = end_dma_irq, -++}; -++ -++//---------------------------------------------------------------------- -++ -++void __init arch_init_irq(void) -++{ -++ int i; -++ -++ clear_c0_status(0xff04); /* clear ERL */ -++ set_c0_status(0x0400); /* set IP2 */ -++ -++ /* Set up INTC irq -++ */ -++ for (i = 0; i < 32; i++) { -++ disable_intc_irq(i); -++ irq_desc[i].chip = &intc_irq_type; -++ } -++ -++ /* Set up DMAC irq -++ */ -++ for (i = 0; i < NUM_DMA; i++) { -++ disable_dma_irq(IRQ_DMA_0 + i); -++ irq_desc[IRQ_DMA_0 + i].chip = &dma_irq_type; -++ } -++ -++ /* Set up GPIO irq -++ */ -++ for (i = 0; i < NUM_GPIO; i++) { -++ disable_gpio_irq(IRQ_GPIO_0 + i); -++ irq_desc[IRQ_GPIO_0 + i].chip = &gpio_irq_type; -++ } -++} -++ -++static int plat_real_irq(int irq) -++{ -++ switch (irq) { -++ case IRQ_GPIO0: -++ irq = __gpio_group_irq(0) + IRQ_GPIO_0; -++ break; -++ case IRQ_GPIO1: -++ irq = __gpio_group_irq(1) + IRQ_GPIO_0 + 32; -++ break; -++ case IRQ_GPIO2: -++ irq = __gpio_group_irq(2) + IRQ_GPIO_0 + 64; -++ break; -++ case IRQ_GPIO3: -++ irq = __gpio_group_irq(3) + IRQ_GPIO_0 + 96; -++ break; -++ case IRQ_GPIO4: -++ irq = __gpio_group_irq(4) + IRQ_GPIO_0 + 128; -++ break; -++ case IRQ_GPIO5: -++ irq = __gpio_group_irq(5) + IRQ_GPIO_0 + 160; -++ break; -++ case IRQ_DMAC0: -++ case IRQ_DMAC1: -++ irq = __dmac_get_irq() + IRQ_DMA_0; -++ break; -++ } -++ -++ return irq; -++} -++ -++asmlinkage void plat_irq_dispatch(void) -++{ -++ int irq = 0; -++ static unsigned long intc_ipr = 0; -++ -++ intc_ipr |= REG_INTC_IPR; -++ -++ if (!intc_ipr) return; -++ -++ irq = ffs(intc_ipr) - 1; -++ intc_ipr &= ~(1< -++ * -++ * This file is licensed under the terms of the GNU General Public -++ * License version 2. This program is licensed "as is" without any -++ * warranty of any kind, whether express or implied. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++ -++/* OHCI (USB full speed host controller) */ -++static struct resource jz_usb_ohci_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(UHC_BASE), // phys addr for ioremap -++ .end = CPHYSADDR(UHC_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_UHC, -++ .end = IRQ_UHC, -++ .flags = IORESOURCE_IRQ, -++ }, -++}; -++ -++/* The dmamask must be set for OHCI to work */ -++static u64 ohci_dmamask = ~(u32)0; -++ -++static struct platform_device jz_usb_ohci_device = { -++ .name = "jz-ohci", -++ .id = 0, -++ .dev = { -++ .dma_mask = &ohci_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_usb_ohci_resources), -++ .resource = jz_usb_ohci_resources, -++}; -++ -++/*** LCD controller ***/ -++static struct resource jz_lcd_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(LCD_BASE), -++ .end = CPHYSADDR(LCD_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_LCD, -++ .end = IRQ_LCD, -++ .flags = IORESOURCE_IRQ, -++ } -++}; -++ -++static u64 jz_lcd_dmamask = ~(u32)0; -++ -++static struct platform_device jz_lcd_device = { -++ .name = "jz-lcd", -++ .id = 0, -++ .dev = { -++ .dma_mask = &jz_lcd_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_lcd_resources), -++ .resource = jz_lcd_resources, -++}; -++ -++/* UDC (USB gadget controller) */ -++static struct resource jz_usb_gdt_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(UDC_BASE), -++ .end = CPHYSADDR(UDC_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_UDC, -++ .end = IRQ_UDC, -++ .flags = IORESOURCE_IRQ, -++ }, -++}; -++ -++static u64 udc_dmamask = ~(u32)0; -++ -++static struct platform_device jz_usb_gdt_device = { -++ .name = "jz-udc", -++ .id = 0, -++ .dev = { -++ .dma_mask = &udc_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_usb_gdt_resources), -++ .resource = jz_usb_gdt_resources, -++}; -++ -++/** MMC/SD controller **/ -++static struct resource jz_mmc_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(MSC_BASE), -++ .end = CPHYSADDR(MSC_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_MSC0, -++ .end = IRQ_MSC0, -++ .flags = IORESOURCE_IRQ, -++ } -++}; -++ -++static u64 jz_mmc_dmamask = ~(u32)0; -++ -++static struct platform_device jz_mmc_device = { -++ .name = "jz-mmc", -++ .id = 0, -++ .dev = { -++ .dma_mask = &jz_mmc_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_mmc_resources), -++ .resource = jz_mmc_resources, -++}; -++ -++/* All */ -++static struct platform_device *jz_platform_devices[] __initdata = { -++ &jz_usb_ohci_device, -++ &jz_lcd_device, -++ &jz_usb_gdt_device, -++ &jz_mmc_device, -++}; -++ -++static int __init jz_platform_init(void) -++{ -++ return platform_add_devices(jz_platform_devices, ARRAY_SIZE(jz_platform_devices)); -++} -++ -++arch_initcall(jz_platform_init); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750/pm.c linux-2.6.24.7/arch/mips/jz4750/pm.c -+--- linux-2.6.24.7.old/arch/mips/jz4750/pm.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750/pm.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,461 @@ -++/* -++ * linux/arch/mips/jz4750/common/pm.c -++ * -++ * JZ4750 Power Management Routines -++ * -++ * Copyright (C) 2006 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can distribute it and/or modify it -++ * under the terms of the GNU General Public License (Version 2) as -++ * published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#undef DEBUG -++//#define DEBUG -++#ifdef DEBUG -++#define dprintk(x...) printk(x) -++#else -++#define dprintk(x...) -++#endif -++ -++#define GPIO_PORT_NUM 6 -++ -++/* -++ * __gpio_as_sleep set all pins to pull-disable, and set all pins as input -++ * except sdram and the pins which can be used as CS1_N to CS4_N for chip select. -++ */ -++#define __gpio_as_sleep() \ -++do { \ -++ REG_GPIO_PXFUNC(1) = ~0x03ff7fff; \ -++ REG_GPIO_PXSELC(1) = ~0x03ff7fff; \ -++ REG_GPIO_PXDIRC(1) = ~0x03ff7fff; \ -++ REG_GPIO_PXPES(1) = 0xffffffff; \ -++ REG_GPIO_PXFUNC(2) = ~0x01e00000; \ -++ REG_GPIO_PXSELC(2) = ~0x01e00000; \ -++ REG_GPIO_PXDIRC(2) = ~0x01e00000; \ -++ REG_GPIO_PXPES(2) = 0xffffffff; \ -++ REG_GPIO_PXFUNC(3) = 0xffffffff; \ -++ REG_GPIO_PXSELC(3) = 0xffffffff; \ -++ REG_GPIO_PXDIRC(3) = 0xffffffff; \ -++ REG_GPIO_PXPES(3) = 0xffffffff; \ -++ REG_GPIO_PXFUNC(4) = 0xffffffff; \ -++ REG_GPIO_PXSELC(4) = 0xffffffff; \ -++ REG_GPIO_PXDIRC(4) = 0xffffffff; \ -++ REG_GPIO_PXPES(4) = 0xffffffff; \ -++ REG_GPIO_PXFUNC(5) = 0xffffffff; \ -++ REG_GPIO_PXSELC(5) = 0xffffffff; \ -++ REG_GPIO_PXDIRC(5) = 0xffffffff; \ -++ REG_GPIO_PXPES(5) = 0xffffffff; \ -++} while (0) -++ -++static int jz_pm_do_hibernate(void) -++{ -++ printk("Put CPU into hibernate mode.\n"); -++ -++ /* Mask all interrupts */ -++ REG_INTC_IMSR = 0xffffffff; -++ -++ /* -++ * RTC Wakeup or 1Hz interrupt can be enabled or disabled -++ * through RTC driver's ioctl (linux/driver/char/rtc_jz.c). -++ */ -++ -++ /* Set minimum wakeup_n pin low-level assertion time for wakeup: 100ms */ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_HWFCR = (100 << RTC_HWFCR_BIT); -++ -++ /* Set reset pin low-level assertion time after wakeup: must > 60ms */ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_HRCR = (60 << RTC_HRCR_BIT); /* 60 ms */ -++ -++ /* Scratch pad register to be reserved */ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_HSPR = 0x12345678; -++ -++ /* clear wakeup status register */ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_HWRSR = 0x0; -++ -++ /* Put CPU to power down mode */ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_HCR = RTC_HCR_PD; -++ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ while(1); -++ -++ /* We can't get here */ -++ return 0; -++} -++ -++/* NOTES: -++ * 1: Pins that are floated (NC) should be set as input and pull-enable. -++ * 2: Pins that are pull-up or pull-down by outside should be set as input -++ * and pull-disable. -++ * 3: Pins that are connected to a chip except sdram and nand flash -++ * should be set as input and pull-disable, too. -++ */ -++static void jz_board_do_sleep(unsigned long *ptr) -++{ -++ unsigned char i; -++ -++ /* Print messages of GPIO registers for debug */ -++ for(i=0;i -++ * -++ * This program is free software; you can distribute it and/or modify it -++ * under the terms of the GNU General Public License (Version 2) as -++ * published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -++ * -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++//#define DEBUG 1 -++#undef DEBUG -++ -++ -++struct proc_dir_entry *proc_jz_root; -++ -++ -++/* -++ * EMC Modules -++ */ -++static int emc_read_proc (char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ -++ len += sprintf (page+len, "SMCR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SMCR0, REG_EMC_SMCR1, REG_EMC_SMCR2, REG_EMC_SMCR3, REG_EMC_SMCR4); -++ len += sprintf (page+len, "SACR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SACR0, REG_EMC_SACR1, REG_EMC_SACR2, REG_EMC_SACR3, REG_EMC_SACR4); -++ len += sprintf (page+len, "DMCR: 0x%08x\n", REG_EMC_DMCR); -++ len += sprintf (page+len, "RTCSR: 0x%04x\n", REG_EMC_RTCSR); -++ len += sprintf (page+len, "RTCOR: 0x%04x\n", REG_EMC_RTCOR); -++ return len; -++} -++ -++/* -++ * Power Manager Module -++ */ -++static int pmc_read_proc (char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ unsigned long lcr = REG_CPM_LCR; -++ unsigned long clkgr = REG_CPM_CLKGR; -++ -++ len += sprintf (page+len, "Low Power Mode : %s\n", -++ ((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_IDLE)) ? -++ "IDLE" : (((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_SLEEP)) ? -++ "SLEEP" : "HIBERNATE")); -++ len += sprintf (page+len, "Doze Mode : %s\n", -++ (lcr & CPM_LCR_DOZE_ON) ? "on" : "off"); -++ if (lcr & CPM_LCR_DOZE_ON) -++ len += sprintf (page+len, " duty : %d\n", (int)((lcr & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT)); -++ len += sprintf (page+len, "IPU : %s\n", -++ (clkgr & CPM_CLKGR_IPU) ? "stopped" : "running"); -++ len += sprintf (page+len, "DMAC : %s\n", -++ (clkgr & CPM_CLKGR_DMAC) ? "stopped" : "running"); -++ len += sprintf (page+len, "UHC : %s\n", -++ (clkgr & CPM_CLKGR_UHC) ? "stopped" : "running"); -++ len += sprintf (page+len, "UDC : %s\n", -++ (clkgr & CPM_CLKGR_UDC) ? "stopped" : "running"); -++ len += sprintf (page+len, "LCD : %s\n", -++ (clkgr & CPM_CLKGR_LCD) ? "stopped" : "running"); -++ len += sprintf (page+len, "CIM : %s\n", -++ (clkgr & CPM_CLKGR_CIM) ? "stopped" : "running"); -++ len += sprintf (page+len, "SADC : %s\n", -++ (clkgr & CPM_CLKGR_SADC) ? "stopped" : "running"); -++ len += sprintf (page+len, "MSC0 : %s\n", -++ (clkgr & CPM_CLKGR_MSC0) ? "stopped" : "running"); -++ len += sprintf (page+len, "MSC1 : %s\n", -++ (clkgr & CPM_CLKGR_MSC1) ? "stopped" : "running"); -++ len += sprintf (page+len, "AIC1 : %s\n", -++ (clkgr & CPM_CLKGR_AIC1) ? "stopped" : "running"); -++ len += sprintf (page+len, "AIC2 : %s\n", -++ (clkgr & CPM_CLKGR_AIC2) ? "stopped" : "running"); -++ len += sprintf (page+len, "SSI0 : %s\n", -++ (clkgr & CPM_CLKGR_SSI0) ? "stopped" : "running"); -++ len += sprintf (page+len, "SSI1 : %s\n", -++ (clkgr & CPM_CLKGR_SSI1) ? "stopped" : "running"); -++ len += sprintf (page+len, "I2C : %s\n", -++ (clkgr & CPM_CLKGR_I2C) ? "stopped" : "running"); -++ len += sprintf (page+len, "RTC : %s\n", -++ (clkgr & CPM_CLKGR_RTC) ? "stopped" : "running"); -++ len += sprintf (page+len, "TCU : %s\n", -++ (clkgr & CPM_CLKGR_TCU) ? "stopped" : "running"); -++ len += sprintf (page+len, "UART1 : %s\n", -++ (clkgr & CPM_CLKGR_UART1) ? "stopped" : "running"); -++ len += sprintf (page+len, "UART0 : %s\n", -++ (clkgr & CPM_CLKGR_UART0) ? "stopped" : "running"); -++ return len; -++} -++ -++static int pmc_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -++{ -++ REG_CPM_CLKGR = simple_strtoul(buffer, 0, 16); -++ return count; -++} -++ -++/* -++ * Clock Generation Module -++ */ -++#define TO_MHZ(x) (x/1000000),(x%1000000)/10000 -++#define TO_KHZ(x) (x/1000),(x%1000)/10 -++ -++static int cgm_read_proc (char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ unsigned int cppcr = REG_CPM_CPPCR; /* PLL Control Register */ -++ unsigned int cpccr = REG_CPM_CPCCR; /* Clock Control Register */ -++ unsigned int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ unsigned int od[4] = {1, 2, 2, 4}; -++ -++ len += sprintf (page+len, "CPPCR : 0x%08x\n", cppcr); -++ len += sprintf (page+len, "CPCCR : 0x%08x\n", cpccr); -++ len += sprintf (page+len, "PLL : %s\n", -++ (cppcr & CPM_CPPCR_PLLEN) ? "ON" : "OFF"); -++ len += sprintf (page+len, "m:n:o : %d:%d:%d\n", -++ __cpm_get_pllm() + 2, -++ __cpm_get_plln() + 2, -++ od[__cpm_get_pllod()] -++ ); -++ len += sprintf (page+len, "C:H:M:P : %d:%d:%d:%d\n", -++ div[__cpm_get_cdiv()], -++ div[__cpm_get_hdiv()], -++ div[__cpm_get_mdiv()], -++ div[__cpm_get_pdiv()] -++ ); -++ len += sprintf (page+len, "PLL Freq : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pllout())); -++ len += sprintf (page+len, "CCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_cclk())); -++ len += sprintf (page+len, "HCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_hclk())); -++ len += sprintf (page+len, "MCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mclk())); -++ len += sprintf (page+len, "PCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pclk())); -++ len += sprintf (page+len, "LCDCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_lcdclk())); -++ len += sprintf (page+len, "PIXCLK : %3d.%02d KHz\n", TO_KHZ(__cpm_get_pixclk())); -++ len += sprintf (page+len, "I2SCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_i2sclk())); -++ len += sprintf (page+len, "USBCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_usbclk())); -++ len += sprintf (page+len, "MSC0CLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mscclk(0))); -++ len += sprintf (page+len, "MSC1CLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mscclk(1))); -++ len += sprintf (page+len, "EXTALCLK0 : %3d.%02d MHz\n", TO_MHZ(__cpm_get_extalclk0())); -++ len += sprintf (page+len, "EXTALCLK(by CPM): %3d.%02d MHz\n", TO_MHZ(__cpm_get_extalclk())); -++ len += sprintf (page+len, "RTCCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_rtcclk())); -++ -++ return len; -++} -++ -++static int cgm_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -++{ -++ REG_CPM_CPCCR = simple_strtoul(buffer, 0, 16); -++ return count; -++} -++ -++ -++/* USAGE: -++ * echo n > /proc/jz/ipu // n = [1,...,9], alloc mem, 2^n pages. -++ * echo FF > /proc/jz/ipu // 255, free all buffer -++ * echo xxxx > /proc/jz/ipu // free buffer which addr is xxxx -++ * echo llll > /proc/jz/ipu // add_wired_entry(l,l,l,l) -++ * echo 0 > /proc/jz/ipu // debug, print ipu_buf -++ * od -X /proc/jz/ipu // read mem addr -++ */ -++ -++typedef struct _ipu_buf { -++ unsigned int addr; /* phys addr */ -++ unsigned int page_shift; -++} ipu_buf_t; -++ -++#define IPU_BUF_MAX 4 /* 4 buffers */ -++ -++static struct _ipu_buf ipu_buf[IPU_BUF_MAX]; -++static int ipu_buf_cnt = 0; -++static unsigned char g_asid=0; -++ -++extern void local_flush_tlb_all(void); -++ -++/* CP0 hazard avoidance. */ -++#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ -++ "nop; nop; nop; nop; nop; nop;\n\t" \ -++ ".set reorder\n\t") -++void show_tlb(void) -++{ -++#define ASID_MASK 0xFF -++ -++ unsigned long flags; -++ unsigned int old_ctx; -++ unsigned int entry; -++ unsigned int entrylo0, entrylo1, entryhi; -++ unsigned int pagemask; -++ -++ local_irq_save(flags); -++ -++ /* Save old context */ -++ old_ctx = (read_c0_entryhi() & 0xff); -++ -++ printk("TLB content:\n"); -++ entry = 0; -++ while(entry < 32) { -++ write_c0_index(entry); -++ BARRIER; -++ tlb_read(); -++ BARRIER; -++ entryhi = read_c0_entryhi(); -++ entrylo0 = read_c0_entrylo0(); -++ entrylo1 = read_c0_entrylo1(); -++ pagemask = read_c0_pagemask(); -++ printk("%02d: ASID=%02d%s VA=0x%08x ", entry, entryhi & ASID_MASK, (entrylo0 & entrylo1 & 1) ? "(G)" : " ", entryhi & ~ASID_MASK); -++ printk("PA0=0x%08x C0=%x %s%s%s\n", (entrylo0>>6)<<12, (entrylo0>>3) & 7, (entrylo0 & 4) ? "Dirty " : "", (entrylo0 & 2) ? "Valid " : "Invalid ", (entrylo0 & 1) ? "Global" : ""); -++ printk("\t\t\t PA1=0x%08x C1=%x %s%s%s\n", (entrylo1>>6)<<12, (entrylo1>>3) & 7, (entrylo1 & 4) ? "Dirty " : "", (entrylo1 & 2) ? "Valid " : "Invalid ", (entrylo1 & 1) ? "Global" : ""); -++ -++ printk("\t\tpagemask=0x%08x", pagemask); -++ printk("\tentryhi=0x%08x\n", entryhi); -++ printk("\t\tentrylo0=0x%08x", entrylo0); -++ printk("\tentrylo1=0x%08x\n", entrylo1); -++ -++ entry++; -++ } -++ BARRIER; -++ write_c0_entryhi(old_ctx); -++ -++ local_irq_restore(flags); -++} -++ -++static void ipu_add_wired_entry(unsigned long pid, -++ unsigned long entrylo0, unsigned long entrylo1, -++ unsigned long entryhi, unsigned long pagemask) -++{ -++ unsigned long flags; -++ unsigned long wired; -++ unsigned long old_pagemask; -++ unsigned long old_ctx; -++ struct task_struct *g, *p; -++ -++ /* We will lock an 4MB page size entry to map the 4MB reserved IPU memory */ -++ entrylo0 = entrylo0 >> 6; -++ entrylo0 |= 0x6 | (0 << 3); -++ /*entrylo0 |= 0x6 | (1 << 3);*/ -++ -++ do_each_thread(g, p) { -++ if (p->pid == pid ) -++ g_asid = p->mm->context[0]; -++ } while_each_thread(g, p); -++ -++ local_irq_save(flags); -++ /* Save old context and create impossible VPN2 value */ -++ old_ctx = read_c0_entryhi() & 0xff; -++ old_pagemask = read_c0_pagemask(); -++ wired = read_c0_wired(); -++ write_c0_wired(wired + 1); -++ write_c0_index(wired); -++ BARRIER; -++ entryhi &= ~0xff; /* new add, 20070906 */ -++ entryhi |= g_asid; /* new add, 20070906 */ -++// entryhi |= old_ctx; /* new add, 20070906 */ -++ write_c0_pagemask(pagemask); -++ write_c0_entryhi(entryhi); -++ write_c0_entrylo0(entrylo0); -++ write_c0_entrylo1(entrylo1); -++ BARRIER; -++ tlb_write_indexed(); -++ BARRIER; -++ -++ write_c0_entryhi(old_ctx); -++ BARRIER; -++ write_c0_pagemask(old_pagemask); -++ local_flush_tlb_all(); -++ local_irq_restore(flags); -++#if defined(DEBUG) -++ printk("\nold_ctx=%03d\n", old_ctx); -++ -++ show_tlb(); -++#endif -++} -++ -++static void ipu_del_wired_entry( void ) -++{ -++ unsigned long flags; -++ unsigned long wired; -++ -++ local_irq_save(flags); -++ wired = read_c0_wired(); -++ if (wired) { -++ write_c0_wired(0); -++ } -++ local_irq_restore(flags); -++} -++ -++static inline void ipu_buf_get( unsigned int page_shift ) -++{ -++ unsigned char * virt_addr; -++ int i; -++ for ( i=0; i< IPU_BUF_MAX; ++i ) { -++ if ( ipu_buf[i].addr == 0 ) { -++ break; -++ } -++ } -++ -++ if ( (ipu_buf_cnt = i) == IPU_BUF_MAX ) { -++ printk("Error, no free ipu buffer.\n"); -++ return ; -++ } -++ -++ virt_addr = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); -++ -++ if ( virt_addr ) { -++ ipu_buf[ipu_buf_cnt].addr = (unsigned int)virt_to_phys((void *)virt_addr); -++ ipu_buf[ipu_buf_cnt].page_shift = page_shift; -++ -++ for (i = 0; i < (1<= IPU_BUF_MAX ) { /* failed alloc mem, rturn 0 */ -++ printk("no free buffer.\n"); -++ *pint = 0; -++ } -++ else -++ *pint = (unsigned int )ipu_buf[ipu_buf_cnt].addr; /* phys addr */ -++ len += sizeof(unsigned int); -++ -++#if defined(DEBUG) -++ show_tlb(); -++#endif -++ return len; -++ -++} -++ -++static int ipu_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -++{ -++ unsigned int val ; -++ int cnt,i; -++ char buf[12]; -++ unsigned long pid, entrylo0, entrylo1, entryhi, pagemask; -++#if defined(DEBUG) -++ printk("ipu write count=%u\n", count); -++#endif -++ if (count == 41) { -++ for (i=0;i<12;i++) -++ buf[i]=0; -++ strncpy(buf, buffer+8*0, 8); -++ pid = simple_strtoul(buf, 0, 16); -++ for (i=0;i<12;i++) -++ buf[i]=0; -++ strncpy(buf, buffer+8*1, 8); -++ entrylo0 = simple_strtoul(buf, 0, 16); -++ for (i=0;i<12;i++) -++ buf[i]=0; -++ strncpy(buf, buffer+8*2, 8); -++ entrylo1 = simple_strtoul(buf, 0, 16); -++ for (i=0;i<12;i++) -++ buf[i]=0; -++ strncpy(buf, buffer+8*3, 8); -++ entryhi = simple_strtoul(buf, 0, 16); -++ for (i=0;i<12;i++) -++ buf[i]=0; -++ strncpy(buf, buffer+8*4, 8); -++ pagemask = simple_strtoul(buf, 0, 16); -++ -++#if defined(DEBUG) -++ printk("pid=0x%08x, entrylo0=0x%08x, entrylo1=0x%08x, entryhi=0x%08x, pagemask=0x%08x\n", -++ pid, entrylo0, entrylo1, entryhi, pagemask); -++#endif -++ ipu_add_wired_entry( pid, entrylo0, entrylo1, entryhi, pagemask); -++ return 41; -++ } else if ( count <= 9 ) { -++ for (i=0;i<12;i++) buf[i]=0; -++ strncpy(buf, buffer, 8); -++ val = simple_strtoul(buf, 0, 16); -++ } else if (count == 44) { -++ for (i = 0; i < 12; i++) -++ buf[i] = 0; -++ strncpy(buf, buffer, 10); -++ pid = simple_strtoul(buf, 0, 16); -++ -++ for (i = 0; i < 12; i++) -++ buf[i] = 0; -++ strncpy(buf, buffer + 11, 10); -++ entryhi = simple_strtoul(buf, 0, 16);//vaddr -++ -++ for (i = 0; i < 12; i++) -++ buf[i] = 0; -++ strncpy(buf, buffer + 22, 10); -++ entrylo0 = simple_strtoul(buf, 0, 16);//paddr -++ -++ for (i = 0; i < 12; i++) -++ buf[i] = 0; -++ strncpy(buf, buffer + 33, 10); -++ pagemask = simple_strtoul(buf, 0, 16); -++ pagemask = 0x3ff << 13; /* Fixed to 4MB page size */ -++ //pagemask = 0xfff << 13; /* Fixed to 16MB page size */ -++ -++ ipu_add_wired_entry(pid, entrylo0, 0, entryhi, pagemask); -++ return 44; -++ } else if (count == 12) { -++ printk("\necho release tlb > /proc/jz/ipu\n"); -++ ipu_del_wired_entry(); -++ return 12; -++ } else { -++ printk("ipu write count error, count=%d\n.", (unsigned int)count); -++ return -1; -++ } -++ -++ /* val: 1-9, page_shift, val>= 10: ipu_buf.addr */ -++ if ( val == 0 ) { /* debug, print ipu_buf info */ -++ for ( cnt=0; cnt /proc/jz/imem // n = [0,...,10], allocate memory, 2^n pages -++ * echo xxxxxxxx > /proc/jz/imem // free buffer which addr is xxxxxxxx -++ * echo FF > /proc/jz/ipu // FF, free all buffers -++ * od -X /proc/jz/imem // return the allocated buffer address and the max order of free buffer -++ */ -++ -++//#define DEBUG_IMEM 1 -++ -++#define IMEM_MAX_ORDER 10 /* max 2^10 * 4096 = 4MB */ -++ -++static unsigned int jz_imem_base; /* physical base address of ipu memory */ -++ -++static unsigned int allocated_phys_addr = 0; -++ -++/* -++ * Allocated buffer list -++ */ -++typedef struct imem_list { -++ unsigned int phys_start; /* physical start addr */ -++ unsigned int phys_end; /* physical end addr */ -++ struct imem_list *next; -++} imem_list_t; -++ -++static struct imem_list *imem_list_head = NULL; /* up sorted by phys_start */ -++ -++#ifdef DEBUG_IMEM -++static void dump_imem_list(void) -++{ -++ struct imem_list *imem; -++ -++ printk("*** dump_imem_list 0x%x ***\n", (u32)imem_list_head); -++ imem = imem_list_head; -++ while (imem) { -++ printk("imem=0x%x phys_start=0x%x phys_end=0x%x next=0x%x\n", (u32)imem, imem->phys_start, imem->phys_end, (u32)imem->next); -++ imem = imem->next; -++ } -++} -++#endif -++ -++/* allocate 2^order pages inside the 4MB memory */ -++static int imem_alloc(unsigned int order) -++{ -++ int alloc_ok = 0; -++ unsigned int start, end; -++ unsigned int size = (1 << order) * PAGE_SIZE; -++ struct imem_list *imem, *imemn, *imemp; -++ -++ allocated_phys_addr = 0; -++ -++ start = jz_imem_base; -++ end = start + (1 << IMEM_MAX_ORDER) * PAGE_SIZE; -++ -++ imem = imem_list_head; -++ while (imem) { -++ if ((imem->phys_start - start) >= size) { -++ /* we got a valid address range */ -++ alloc_ok = 1; -++ break; -++ } -++ -++ start = imem->phys_end + 1; -++ imem = imem->next; -++ } -++ -++ if (!alloc_ok) { -++ if ((end - start) >= size) -++ alloc_ok = 1; -++ } -++ -++ if (alloc_ok) { -++ end = start + size - 1; -++ allocated_phys_addr = start; -++ -++ /* add to imem_list, up sorted by phys_start */ -++ imemn = kmalloc(sizeof(struct imem_list), GFP_KERNEL); -++ if (!imemn) { -++ return -ENOMEM; -++ } -++ imemn->phys_start = start; -++ imemn->phys_end = end; -++ imemn->next = NULL; -++ -++ if (!imem_list_head) -++ imem_list_head = imemn; -++ else { -++ imem = imemp = imem_list_head; -++ while (imem) { -++ if (start < imem->phys_start) { -++ break; -++ } -++ -++ imemp = imem; -++ imem = imem->next; -++ } -++ -++ if (imem == imem_list_head) { -++ imem_list_head = imemn; -++ imemn->next = imem; -++ } -++ else { -++ imemn->next = imemp->next; -++ imemp->next = imemn; -++ } -++ } -++ } -++ -++#ifdef DEBUG_IMEM -++ dump_imem_list(); -++#endif -++ return 0; -++} -++ -++static void imem_free(unsigned int phys_addr) -++{ -++ struct imem_list *imem, *imemp; -++ -++ imem = imemp = imem_list_head; -++ while (imem) { -++ if (phys_addr == imem->phys_start) { -++ if (imem == imem_list_head) { -++ imem_list_head = imem->next; -++ } -++ else { -++ imemp->next = imem->next; -++ } -++ -++ kfree(imem); -++ break; -++ } -++ -++ imemp = imem; -++ imem = imem->next; -++ } -++ -++#ifdef DEBUG_IMEM -++ dump_imem_list(); -++#endif -++} -++ -++static void imem_free_all(void) -++{ -++ struct imem_list *imem; -++ -++ imem = imem_list_head; -++ while (imem) { -++ kfree(imem); -++ imem = imem->next; -++ } -++ -++ imem_list_head = NULL; -++ -++ allocated_phys_addr = 0; -++ -++#ifdef DEBUG_IMEM -++ dump_imem_list(); -++#endif -++} -++ -++/* -++ * Return the allocated buffer address and the max order of free buffer -++ */ -++static int imem_read_proc(char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ unsigned int start_addr, end_addr, max_order, max_size; -++ struct imem_list *imem; -++ -++ unsigned int *tmp = (unsigned int *)(page + len); -++ -++ start_addr = jz_imem_base; -++ end_addr = start_addr + (1 << IMEM_MAX_ORDER) * PAGE_SIZE; -++ -++ if (!imem_list_head) -++ max_size = end_addr - start_addr; -++ else { -++ max_size = 0; -++ imem = imem_list_head; -++ while (imem) { -++ if (max_size < (imem->phys_start - start_addr)) -++ max_size = imem->phys_start - start_addr; -++ -++ start_addr = imem->phys_end + 1; -++ imem = imem->next; -++ } -++ -++ if (max_size < (end_addr - start_addr)) -++ max_size = end_addr - start_addr; -++ } -++ -++ if (max_size > 0) { -++ max_order = get_order(max_size); -++ if (((1 << max_order) * PAGE_SIZE) > max_size) -++ max_order--; -++ } -++ else { -++ max_order = 0xffffffff; /* No any free buffer */ -++ } -++ -++ *tmp++ = allocated_phys_addr; /* address allocated by 'echo n > /proc/jz/imem' */ -++ *tmp = max_order; /* max order of current free buffers */ -++ -++ len += 2 * sizeof(unsigned int); -++ -++ return len; -++} -++ -++static int imem_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -++{ -++ unsigned int val; -++ -++ val = simple_strtoul(buffer, 0, 16); -++ -++ if (val == 0xff) { -++ /* free all memory */ -++ imem_free_all(); -++ ipu_del_wired_entry(); -++ } else if ((val >= 0) && (val <= IMEM_MAX_ORDER)) { -++ /* allocate 2^val pages */ -++ imem_alloc(val); -++ } else { -++ /* free buffer which phys_addr is val */ -++ imem_free(val); -++ } -++ -++ return count; -++} -++ -++/* -++ * /proc/jz/xxx entry -++ * -++ */ -++static int __init jz_proc_init(void) -++{ -++ struct proc_dir_entry *res; -++ unsigned int virt_addr, i; -++ -++ proc_jz_root = proc_mkdir("jz", 0); -++ -++ /* External Memory Controller */ -++ res = create_proc_entry("emc", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = emc_read_proc; -++ res->write_proc = NULL; -++ res->data = NULL; -++ } -++ -++ /* Power Management Controller */ -++ res = create_proc_entry("pmc", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = pmc_read_proc; -++ res->write_proc = pmc_write_proc; -++ res->data = NULL; -++ } -++ -++ /* Clock Generation Module */ -++ res = create_proc_entry("cgm", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = cgm_read_proc; -++ res->write_proc = cgm_write_proc; -++ res->data = NULL; -++ } -++ -++ /* Image process unit */ -++ res = create_proc_entry("ipu", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = ipu_read_proc; -++ res->write_proc = ipu_write_proc; -++ res->data = NULL; -++ } -++ -++ /* udc hotplug */ -++ res = create_proc_entry("udc", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = udc_read_proc; -++ res->write_proc = NULL; -++ res->data = NULL; -++ } -++ -++ /* mmc hotplug */ -++ res = create_proc_entry("mmc", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = mmc_read_proc; -++ res->write_proc = NULL; -++ res->data = NULL; -++ } -++ -++ /* show tlb */ -++ res = create_proc_entry("tlb", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = tlb_read_proc; -++ res->write_proc = NULL; -++ res->data = NULL; -++ } -++ -++ /* -++ * Reserve a 4MB memory for IPU on JZ4750. -++ */ -++ jz_imem_base = (unsigned int)__get_free_pages(GFP_KERNEL, IMEM_MAX_ORDER); -++ if (jz_imem_base) { -++ /* imem (IPU memory management) */ -++ res = create_proc_entry("imem", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = imem_read_proc; -++ res->write_proc = imem_write_proc; -++ res->data = NULL; -++ } -++ -++ /* Set page reserved */ -++ virt_addr = jz_imem_base; -++ for (i = 0; i < (1 << IMEM_MAX_ORDER); i++) { -++ SetPageReserved(virt_to_page((void *)virt_addr)); -++ virt_addr += PAGE_SIZE; -++ } -++ -++ /* Convert to physical address */ -++ jz_imem_base = virt_to_phys((void *)jz_imem_base); -++ -++ printk("Total %dMB memory at 0x%x was reserved for IPU\n", -++ (unsigned int)((1 << IMEM_MAX_ORDER) * PAGE_SIZE)/1000000, jz_imem_base); -++ } else -++ printk("NOT enough memory for imem\n"); -++ -++ return 0; -++} -++ -++__initcall(jz_proc_init); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750/prom.c linux-2.6.24.7/arch/mips/jz4750/prom.c -+--- linux-2.6.24.7.old/arch/mips/jz4750/prom.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750/prom.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,198 @@ -++/* -++ * -++ * BRIEF MODULE DESCRIPTION -++ * PROM library initialisation code, supports YAMON and U-Boot. -++ * -++ * Copyright 2000, 2001, 2006 MontaVista Software Inc. -++ * Author: MontaVista Software, Inc. -++ * ppopov@mvista.com or source@mvista.com -++ * -++ * This file was derived from Carsten Langgaard's -++ * arch/mips/mips-boards/xx files. -++ * -++ * Carsten Langgaard, carstenl@mips.com -++ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ * -++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++/* #define DEBUG_CMDLINE */ -++ -++int prom_argc; -++char **prom_argv, **prom_envp; -++ -++char * prom_getcmdline(void) -++{ -++ return &(arcs_cmdline[0]); -++} -++ -++void prom_init_cmdline(void) -++{ -++ char *cp; -++ int actr; -++ -++ actr = 1; /* Always ignore argv[0] */ -++ -++ cp = &(arcs_cmdline[0]); -++ while(actr < prom_argc) { -++ strcpy(cp, prom_argv[actr]); -++ cp += strlen(prom_argv[actr]); -++ *cp++ = ' '; -++ actr++; -++ } -++ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ -++ --cp; -++ if (prom_argc > 1) -++ *cp = '\0'; -++ -++} -++ -++ -++char *prom_getenv(char *envname) -++{ -++#if 0 -++ /* -++ * Return a pointer to the given environment variable. -++ * YAMON uses "name", "value" pairs, while U-Boot uses "name=value". -++ */ -++ -++ char **env = prom_envp; -++ int i = strlen(envname); -++ int yamon = (*env && strchr(*env, '=') == NULL); -++ -++ while (*env) { -++ if (yamon) { -++ if (strcmp(envname, *env++) == 0) -++ return *env; -++ } else { -++ if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=') -++ return *env + i + 1; -++ } -++ env++; -++ } -++#endif -++ return NULL; -++} -++ -++inline unsigned char str2hexnum(unsigned char c) -++{ -++ if(c >= '0' && c <= '9') -++ return c - '0'; -++ if(c >= 'a' && c <= 'f') -++ return c - 'a' + 10; -++ if(c >= 'A' && c <= 'F') -++ return c - 'A' + 10; -++ return 0; /* foo */ -++} -++ -++inline void str2eaddr(unsigned char *ea, unsigned char *str) -++{ -++ int i; -++ -++ for(i = 0; i < 6; i++) { -++ unsigned char num; -++ -++ if((*str == '.') || (*str == ':')) -++ str++; -++ num = str2hexnum(*str++) << 4; -++ num |= (str2hexnum(*str++)); -++ ea[i] = num; -++ } -++} -++ -++int get_ethernet_addr(char *ethernet_addr) -++{ -++ char *ethaddr_str; -++ -++ ethaddr_str = prom_getenv("ethaddr"); -++ if (!ethaddr_str) { -++ printk("ethaddr not set in boot prom\n"); -++ return -1; -++ } -++ str2eaddr(ethernet_addr, ethaddr_str); -++ -++#if 0 -++ { -++ int i; -++ -++ printk("get_ethernet_addr: "); -++ for (i=0; i<5; i++) -++ printk("%02x:", (unsigned char)*(ethernet_addr+i)); -++ printk("%02x\n", *(ethernet_addr+i)); -++ } -++#endif -++ -++ return 0; -++} -++ -++void __init prom_free_prom_memory(void) -++{ -++} -++ -++void __init prom_init(void) -++{ -++ unsigned char *memsize_str; -++ unsigned long memsize; -++ -++ prom_argc = (int) fw_arg0; -++ prom_argv = (char **) fw_arg1; -++ prom_envp = (char **) fw_arg2; -++ -++ mips_machtype = MACH_INGENIC_JZ4750; -++ -++ prom_init_cmdline(); -++ memsize_str = prom_getenv("memsize"); -++ if (!memsize_str) { -++ memsize = 0x04000000; -++ } else { -++ memsize = simple_strtol(memsize_str, NULL, 0); -++ } -++ add_memory_region(0, memsize, BOOT_MEM_RAM); -++} -++ -++/* used by early printk */ -++void prom_putchar(char c) -++{ -++ volatile u8 *uart_lsr = (volatile u8 *)(UART0_BASE + OFF_LSR); -++ volatile u8 *uart_tdr = (volatile u8 *)(UART0_BASE + OFF_TDR); -++ -++ /* Wait for fifo to shift out some bytes */ -++ while ( !((*uart_lsr & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60) ); -++ -++ *uart_tdr = (u8)c; -++} -++ -++const char *get_system_type(void) -++{ -++ return "JZ4750"; -++} -++ -++EXPORT_SYMBOL(prom_getcmdline); -++EXPORT_SYMBOL(get_ethernet_addr); -++EXPORT_SYMBOL(str2eaddr); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750/reset.c linux-2.6.24.7/arch/mips/jz4750/reset.c -+--- linux-2.6.24.7.old/arch/mips/jz4750/reset.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750/reset.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,46 @@ -++/* -++ * linux/arch/mips/jz4750/reset.c -++ * -++ * JZ4750 reset routines. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++void jz_restart(char *command) -++{ -++ printk("Restarting after 4 ms\n"); -++ REG_WDT_TCSR = WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN; -++ REG_WDT_TCNT = 0; -++ REG_WDT_TDR = JZ_EXTAL/1000; /* reset after 4ms */ -++ REG_TCU_TSCR = TCU_TSCR_WDTSC; /* enable wdt clock */ -++ REG_WDT_TCER = WDT_TCER_TCEN; /* wdt start */ -++ while (1); -++} -++ -++void jz_halt(void) -++{ -++ printk(KERN_NOTICE "\n** You can safely turn off the power\n"); -++ -++ while (1) -++ __asm__(".set\tmips3\n\t" -++ "wait\n\t" -++ ".set\tmips0"); -++} -++ -++void jz_power_off(void) -++{ -++ jz_halt(); -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750/setup.c linux-2.6.24.7/arch/mips/jz4750/setup.c -+--- linux-2.6.24.7.old/arch/mips/jz4750/setup.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750/setup.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,197 @@ -++/* -++ * linux/arch/mips/jz4750/common/setup.c -++ * -++ * JZ4750 common setup routines. -++ * -++ * Copyright (C) 2006 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can distribute it and/or modify it -++ * under the terms of the GNU General Public License (Version 2) as -++ * published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -++ * -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#ifdef CONFIG_PC_KEYB -++#include -++#endif -++ -++jz_clocks_t jz_clocks; -++ -++extern char * __init prom_getcmdline(void); -++extern void __init jz_board_setup(void); -++extern void jz_restart(char *); -++extern void jz_halt(void); -++extern void jz_power_off(void); -++extern void jz_time_init(void); -++ -++static void __init sysclocks_setup(void) -++{ -++#ifndef CONFIG_MIPS_JZ_EMURUS /* FPGA */ -++ jz_clocks.cclk = __cpm_get_cclk(); -++ jz_clocks.hclk = __cpm_get_hclk(); -++ jz_clocks.pclk = __cpm_get_pclk(); -++ jz_clocks.mclk = __cpm_get_mclk(); -++ jz_clocks.lcdclk = __cpm_get_lcdclk(); -++ jz_clocks.pixclk = __cpm_get_pixclk(); -++ jz_clocks.i2sclk = __cpm_get_i2sclk(); -++ jz_clocks.usbclk = __cpm_get_usbclk(); -++ jz_clocks.mscclk = __cpm_get_mscclk(0); -++ jz_clocks.extalclk = __cpm_get_extalclk(); -++ jz_clocks.rtcclk = __cpm_get_rtcclk(); -++#else -++ -++#define FPGACLK 8000000 -++ -++ jz_clocks.cclk = FPGACLK; -++ jz_clocks.hclk = FPGACLK; -++ jz_clocks.pclk = FPGACLK; -++ jz_clocks.mclk = FPGACLK; -++ jz_clocks.lcdclk = FPGACLK; -++ jz_clocks.pixclk = FPGACLK; -++ jz_clocks.i2sclk = FPGACLK; -++ jz_clocks.usbclk = FPGACLK; -++ jz_clocks.mscclk = FPGACLK; -++ jz_clocks.extalclk = FPGACLK; -++ jz_clocks.rtcclk = FPGACLK; -++#endif -++ -++ printk("CPU clock: %dMHz, System clock: %dMHz, Peripheral clock: %dMHz, Memory clock: %dMHz\n", -++ (jz_clocks.cclk + 500000) / 1000000, -++ (jz_clocks.hclk + 500000) / 1000000, -++ (jz_clocks.pclk + 500000) / 1000000, -++ (jz_clocks.mclk + 500000) / 1000000); -++} -++ -++static void __init soc_cpm_setup(void) -++{ -++ /* Start all module clocks -++ */ -++ __cpm_start_all(); -++ -++ /* Enable CKO to external memory */ -++ __cpm_enable_cko(); -++ -++ /* CPU enters IDLE mode when executing 'wait' instruction */ -++ __cpm_idle_mode(); -++ -++ /* Setup system clocks */ -++ sysclocks_setup(); -++} -++ -++static void __init soc_harb_setup(void) -++{ -++// __harb_set_priority(0x00); /* CIM>LCD>DMA>ETH>PCI>USB>CBB */ -++// __harb_set_priority(0x03); /* LCD>CIM>DMA>ETH>PCI>USB>CBB */ -++// __harb_set_priority(0x0a); /* ETH>LCD>CIM>DMA>PCI>USB>CBB */ -++} -++ -++static void __init soc_emc_setup(void) -++{ -++} -++ -++static void __init soc_dmac_setup(void) -++{ -++ __dmac_enable_module(0); -++ __dmac_enable_module(1); -++} -++ -++static void __init jz_soc_setup(void) -++{ -++ soc_cpm_setup(); -++ soc_harb_setup(); -++ soc_emc_setup(); -++ soc_dmac_setup(); -++} -++ -++static void __init jz_serial_setup(void) -++{ -++#ifdef CONFIG_SERIAL_8250 -++ struct uart_port s; -++ REG8(UART0_FCR) |= UARTFCR_UUE; /* enable UART module */ -++ memset(&s, 0, sizeof(s)); -++ s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; -++ s.iotype = SERIAL_IO_MEM; -++ s.regshift = 2; -++ s.uartclk = jz_clocks.extalclk ; -++ -++ s.line = 0; -++ s.membase = (u8 *)UART0_BASE; -++ s.irq = IRQ_UART0; -++ if (early_serial_setup(&s) != 0) { -++ printk(KERN_ERR "Serial ttyS0 setup failed!\n"); -++ } -++ -++ s.line = 1; -++ s.membase = (u8 *)UART1_BASE; -++ s.irq = IRQ_UART1; -++ if (early_serial_setup(&s) != 0) { -++ printk(KERN_ERR "Serial ttyS1 setup failed!\n"); -++ } -++ -++ s.line = 2; -++ s.membase = (u8 *)UART2_BASE; -++ s.irq = IRQ_UART2; -++ if (early_serial_setup(&s) != 0) { -++ printk(KERN_ERR "Serial ttyS2 setup failed!\n"); -++ } -++ -++ s.line = 3; -++ s.membase = (u8 *)UART3_BASE; -++ s.irq = IRQ_UART3; -++ if (early_serial_setup(&s) != 0) { -++ printk(KERN_ERR "Serial ttyS3 setup failed!\n"); -++ } -++#endif -++} -++ -++void __init plat_mem_setup(void) -++{ -++ char *argptr; -++ -++ argptr = prom_getcmdline(); -++ -++ /* IO/MEM resources. Which will be the addtion value in `inX' and -++ * `outX' macros defined in asm/io.h */ -++ set_io_port_base(0); -++ ioport_resource.start = 0x00000000; -++ ioport_resource.end = 0xffffffff; -++ iomem_resource.start = 0x00000000; -++ iomem_resource.end = 0xffffffff; -++ -++ _machine_restart = jz_restart; -++ _machine_halt = jz_halt; -++ pm_power_off = jz_power_off; -++ -++ jz_soc_setup(); -++ jz_serial_setup(); -++ jz_board_setup(); -++} -++ -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750/time.c linux-2.6.24.7/arch/mips/jz4750/time.c -+--- linux-2.6.24.7.old/arch/mips/jz4750/time.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750/time.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,156 @@ -++/* -++ * linux/arch/mips/jz4750/time.c -++ * -++ * Setting up the clock on the JZ4750 boards. -++ * -++ * Copyright (C) 2008 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can distribute it and/or modify it -++ * under the terms of the GNU General Public License (Version 2) as -++ * published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -++ * -++ */ -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++/* This is for machines which generate the exact clock. */ -++ -++#define JZ_TIMER_IRQ IRQ_TCU0 -++ -++#define JZ_TIMER_CLOCK (JZ_EXTAL>>4) /* Jz timer clock frequency */ -++ -++static struct clocksource clocksource_jz; /* Jz clock source */ -++static struct clock_event_device jz_clockevent_device; /* Jz clock event */ -++ -++void (*jz_timer_callback)(void); -++ -++static irqreturn_t jz_timer_interrupt(int irq, void *dev_id) -++{ -++ struct clock_event_device *cd = dev_id; -++ -++ REG_TCU_TFCR = TCU_TFCR_OSTFCL; /* ACK timer */ -++ -++ if (jz_timer_callback) -++ jz_timer_callback(); -++ -++ cd->event_handler(cd); -++ -++ return IRQ_HANDLED; -++} -++ -++static struct irqaction jz_irqaction = { -++ .handler = jz_timer_interrupt, -++ .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, -++ .name = "jz-timerirq", -++}; -++ -++ -++cycle_t jz_get_cycles(void) -++{ -++ /* convert jiffes to jz timer cycles */ -++ return (cycle_t)( jiffies*((JZ_TIMER_CLOCK)/HZ) + REG_TCU_OSTCNT); -++} -++ -++static struct clocksource clocksource_jz = { -++ .name = "jz_clocksource", -++ .rating = 300, -++ .read = jz_get_cycles, -++ .mask = 0xFFFFFFFF, -++ .shift = 10, -++ .flags = CLOCK_SOURCE_WATCHDOG, -++}; -++ -++static int __init jz_clocksource_init(void) -++{ -++ clocksource_jz.mult = clocksource_hz2mult(JZ_TIMER_CLOCK, clocksource_jz.shift); -++ clocksource_register(&clocksource_jz); -++ return 0; -++} -++ -++static int jz_set_next_event(unsigned long evt, -++ struct clock_event_device *unused) -++{ -++ return 0; -++} -++ -++static void jz_set_mode(enum clock_event_mode mode, -++ struct clock_event_device *evt) -++{ -++ switch (mode) { -++ case CLOCK_EVT_MODE_PERIODIC: -++ break; -++ case CLOCK_EVT_MODE_ONESHOT: -++ case CLOCK_EVT_MODE_UNUSED: -++ case CLOCK_EVT_MODE_SHUTDOWN: -++ break; -++ case CLOCK_EVT_MODE_RESUME: -++ break; -++ } -++} -++ -++static struct clock_event_device jz_clockevent_device = { -++ .name = "jz-clockenvent", -++ .features = CLOCK_EVT_FEAT_PERIODIC, -++// .features = CLOCK_EVT_FEAT_ONESHOT, /* Jz4740 not support dynamic clock now */ -++ -++ /* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */ -++ .rating = 300, -++ .irq = JZ_TIMER_IRQ, -++ .set_mode = jz_set_mode, -++ .set_next_event = jz_set_next_event, -++}; -++ -++static void __init jz_clockevent_init(void) -++{ -++ struct clock_event_device *cd = &jz_clockevent_device; -++ unsigned int cpu = smp_processor_id(); -++ -++ cd->cpumask = cpumask_of_cpu(cpu); -++ clockevents_register_device(cd); -++} -++ -++static void __init jz_timer_setup(void) -++{ -++ jz_clocksource_init(); /* init jz clock source */ -++ jz_clockevent_init(); /* init jz clock event */ -++ -++ /* -++ * Make irqs happen for the system timer -++ */ -++ jz_irqaction.dev_id = &jz_clockevent_device; -++ setup_irq(JZ_TIMER_IRQ, &jz_irqaction); -++} -++ -++ -++void __init plat_time_init(void) -++{ -++ unsigned int latch; -++ -++ /* Init timer */ -++ latch = (JZ_TIMER_CLOCK + (HZ>>1)) / HZ; -++ -++ REG_TCU_OSTCSR = TCU_OSTCSR_PRESCALE16 | TCU_OSTCSR_EXT_EN; -++ REG_TCU_OSTCNT = 0; -++ REG_TCU_OSTDR = latch; -++ -++ REG_TCU_TMCR = TCU_TMCR_OSTMCL; /* unmask match irq */ -++ REG_TCU_TSCR = TCU_TSCR_OSTSC; /* enable timer clock */ -++ REG_TCU_TESR = TCU_TESR_OSTST; /* start counting up */ -++ -++ jz_timer_setup(); -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750d/Makefile linux-2.6.24.7/arch/mips/jz4750d/Makefile -+--- linux-2.6.24.7.old/arch/mips/jz4750d/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750d/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,22 @@ -++# -++# Makefile for the Ingenic JZ4750D. -++# -++ -++# Object file lists. -++ -++obj-y += prom.o irq.o time.o reset.o setup.o dma.o \ -++ platform.o i2c.o -++ -++obj-$(CONFIG_PROC_FS) += proc.o -++ -++# board specific support -++ -++obj-$(CONFIG_JZ4750D_FUWA1) += board-fuwa1.o -++ -++# PM support -++ -++obj-$(CONFIG_PM_LEGACY) +=pm.o -++ -++# CPU Frequency scaling support -++ -++obj-$(CONFIG_CPU_FREQ_JZ) +=cpufreq.o -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750d/board-fuwa1.c linux-2.6.24.7/arch/mips/jz4750d/board-fuwa1.c -+--- linux-2.6.24.7.old/arch/mips/jz4750d/board-fuwa1.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750d/board-fuwa1.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,72 @@ -++/* -++ * linux/arch/mips/jz4750d/board-fuwa1.c -++ * -++ * JZ4750D FUWA1 board setup routines. -++ * -++ * Copyright (c) 2006-2008 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include -++ -++extern void (*jz_timer_callback)(void); -++ -++static void dancing(void) -++{ -++ static unsigned char slash[] = "\\|/-"; -++// static volatile unsigned char *p = (unsigned char *)0xb6000058; -++ static volatile unsigned char *p = (unsigned char *)0xb6000016; -++ static unsigned int count = 0; -++ *p = slash[count++]; -++ count &= 3; -++} -++ -++static void fuwa1_timer_callback(void) -++{ -++ static unsigned long count = 0; -++ -++ if ((++count) % 50 == 0) { -++ dancing(); -++ count = 0; -++ } -++} -++ -++static void __init board_cpm_setup(void) -++{ -++ /* Stop unused module clocks here. -++ * We have started all module clocks at arch/mips/jz4750d/setup.c. -++ */ -++} -++ -++static void __init board_gpio_setup(void) -++{ -++ /* -++ * Initialize SDRAM pins -++ */ -++} -++ -++void __init jz_board_setup(void) -++{ -++ printk("JZ4750D FUWA1 board setup\n"); -++ -++ board_cpm_setup(); -++ board_gpio_setup(); -++ -++ jz_timer_callback = fuwa1_timer_callback; -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750d/cpufreq.c linux-2.6.24.7/arch/mips/jz4750d/cpufreq.c -+--- linux-2.6.24.7.old/arch/mips/jz4750d/cpufreq.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750d/cpufreq.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,601 @@ -++/* -++ * linux/arch/mips/jz4750d/cpufreq.c -++ * -++ * cpufreq driver for JZ4750D -++ * -++ * Copyright (c) 2006-2008 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++ -++#include -++ -++#include -++#include -++ -++#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \ -++ "cpufreq-jz4750d", msg) -++ -++#undef CHANGE_PLL -++ -++#define PLL_UNCHANGED 0 -++#define PLL_GOES_UP 1 -++#define PLL_GOES_DOWN 2 -++ -++#define PLL_WAIT_500NS (500*(__cpm_get_cclk()/1000000000)) -++ -++/* Saved the boot-time parameters */ -++static struct { -++ /* SDRAM parameters */ -++ unsigned int mclk; /* memory clock, KHz */ -++ unsigned int tras; /* RAS pulse width, cycles of mclk */ -++ unsigned int rcd; /* RAS to CAS Delay, cycles of mclk */ -++ unsigned int tpc; /* RAS Precharge time, cycles of mclk */ -++ unsigned int trwl; /* Write Precharge Time, cycles of mclk */ -++ unsigned int trc; /* RAS Cycle Time, cycles of mclk */ -++ unsigned int rtcor; /* Refresh Time Constant */ -++ unsigned int sdram_initialized; -++ -++ /* LCD parameters */ -++ unsigned int lcd_clk; /* LCD clock, Hz */ -++ unsigned int lcdpix_clk; /* LCD Pixel clock, Hz */ -++ unsigned int lcd_clks_initialized; -++} boot_config; -++ -++struct jz4750d_freq_percpu_info { -++ struct cpufreq_frequency_table table[7]; -++}; -++ -++static struct jz4750d_freq_percpu_info jz4750d_freq_table; -++ -++/* -++ * This contains the registers value for an operating point. -++ * If only part of a register needs to change then there is -++ * a mask value for that register. -++ * When going to a new operating point the current register -++ * value is ANDed with the ~mask and ORed with the new value. -++ */ -++struct dpm_regs { -++ u32 cpccr; /* Clock Freq Control Register */ -++ u32 cpccr_mask; /* Clock Freq Control Register mask */ -++ u32 cppcr; /* PLL1 Control Register */ -++ u32 cppcr_mask; /* PLL1 Control Register mask */ -++ u32 pll_up_flag; /* New PLL freq is higher than current or not */ -++}; -++ -++extern jz_clocks_t jz_clocks; -++ -++static void jz_update_clocks(void) -++{ -++ /* Next clocks must be updated if we have changed -++ * the PLL or divisors. -++ */ -++ jz_clocks.cclk = __cpm_get_cclk(); -++ jz_clocks.hclk = __cpm_get_hclk(); -++ jz_clocks.mclk = __cpm_get_mclk(); -++ jz_clocks.pclk = __cpm_get_pclk(); -++ jz_clocks.lcdclk = __cpm_get_lcdclk(); -++ jz_clocks.pixclk = __cpm_get_pixclk(); -++ jz_clocks.i2sclk = __cpm_get_i2sclk(); -++ jz_clocks.usbclk = __cpm_get_usbclk(); -++ jz_clocks.mscclk = __cpm_get_mscclk(0); -++} -++ -++static void -++jz_init_boot_config(void) -++{ -++ if (!boot_config.lcd_clks_initialized) { -++ /* the first time to scale pll */ -++ boot_config.lcd_clk = __cpm_get_lcdclk(); -++ boot_config.lcdpix_clk = __cpm_get_pixclk(); -++ boot_config.lcd_clks_initialized = 1; -++ } -++ -++ if (!boot_config.sdram_initialized) { -++ /* the first time to scale frequencies */ -++ unsigned int dmcr, rtcor; -++ unsigned int tras, rcd, tpc, trwl, trc; -++ -++ dmcr = REG_EMC_DMCR; -++ rtcor = REG_EMC_RTCOR; -++ -++ tras = (dmcr >> 13) & 0x7; -++ rcd = (dmcr >> 11) & 0x3; -++ tpc = (dmcr >> 8) & 0x7; -++ trwl = (dmcr >> 5) & 0x3; -++ trc = (dmcr >> 2) & 0x7; -++ -++ boot_config.mclk = __cpm_get_mclk() / 1000; -++ boot_config.tras = tras + 4; -++ boot_config.rcd = rcd + 1; -++ boot_config.tpc = tpc + 1; -++ boot_config.trwl = trwl + 1; -++ boot_config.trc = trc * 2 + 1; -++ boot_config.rtcor = rtcor; -++ -++ boot_config.sdram_initialized = 1; -++ } -++} -++ -++static void jz_update_dram_rtcor(unsigned int new_mclk) -++{ -++ unsigned int rtcor; -++ -++ new_mclk /= 1000; -++ rtcor = boot_config.rtcor * new_mclk / boot_config.mclk; -++ rtcor--; -++ -++ if (rtcor < 1) rtcor = 1; -++ if (rtcor > 255) rtcor = 255; -++ -++ REG_EMC_RTCOR = rtcor; -++ REG_EMC_RTCNT = rtcor; -++} -++ -++static void jz_update_dram_dmcr(unsigned int new_mclk) -++{ -++ unsigned int dmcr; -++ unsigned int tras, rcd, tpc, trwl, trc; -++ unsigned int valid_time, new_time; /* ns */ -++ -++ new_mclk /= 1000; -++ tras = boot_config.tras * new_mclk / boot_config.mclk; -++ rcd = boot_config.rcd * new_mclk / boot_config.mclk; -++ tpc = boot_config.tpc * new_mclk / boot_config.mclk; -++ trwl = boot_config.trwl * new_mclk / boot_config.mclk; -++ trc = boot_config.trc * new_mclk / boot_config.mclk; -++ -++ /* Validation checking */ -++ valid_time = (boot_config.tras * 1000000) / boot_config.mclk; -++ new_time = (tras * 1000000) / new_mclk; -++ if (new_time < valid_time) tras += 1; -++ -++ valid_time = (boot_config.rcd * 1000000) / boot_config.mclk; -++ new_time = (rcd * 1000000) / new_mclk; -++ if (new_time < valid_time) rcd += 1; -++ -++ valid_time = (boot_config.tpc * 1000000) / boot_config.mclk; -++ new_time = (tpc * 1000000) / new_mclk; -++ if (new_time < valid_time) tpc += 1; -++ -++ valid_time = (boot_config.trwl * 1000000) / boot_config.mclk; -++ new_time = (trwl * 1000000) / new_mclk; -++ if (new_time < valid_time) trwl += 1; -++ -++ valid_time = (boot_config.trc * 1000000) / boot_config.mclk; -++ new_time = (trc * 1000000) / new_mclk; -++ if (new_time < valid_time) trc += 2; -++ -++ tras = (tras < 4) ? 4: tras; -++ tras = (tras > 11) ? 11: tras; -++ tras -= 4; -++ -++ rcd = (rcd < 1) ? 1: rcd; -++ rcd = (rcd > 4) ? 4: rcd; -++ rcd -= 1; -++ -++ tpc = (tpc < 1) ? 1: tpc; -++ tpc = (tpc > 8) ? 8: tpc; -++ tpc -= 1; -++ -++ trwl = (trwl < 1) ? 1: trwl; -++ trwl = (trwl > 4) ? 4: trwl; -++ trwl -= 1; -++ -++ trc = (trc < 1) ? 1: trc; -++ trc = (trc > 15) ? 15: trc; -++ trc /= 2; -++ -++ dmcr = REG_EMC_DMCR; -++ -++ dmcr &= ~(EMC_DMCR_TRAS_MASK | EMC_DMCR_RCD_MASK | EMC_DMCR_TPC_MASK | EMC_DMCR_TRWL_MASK | EMC_DMCR_TRC_MASK); -++ dmcr |= ((tras << EMC_DMCR_TRAS_BIT) | (rcd << EMC_DMCR_RCD_BIT) | (tpc << EMC_DMCR_TPC_BIT) | (trwl << EMC_DMCR_TRWL_BIT) | (trc << EMC_DMCR_TRC_BIT)); -++ -++ REG_EMC_DMCR = dmcr; -++} -++ -++static void jz_update_dram_prev(unsigned int cur_mclk, unsigned int new_mclk) -++{ -++ /* No risk, no fun: run with interrupts on! */ -++ if (new_mclk > cur_mclk) { -++ /* We're going FASTER, so first update TRAS, RCD, TPC, TRWL -++ * and TRC of DMCR before changing the frequency. -++ */ -++ jz_update_dram_dmcr(new_mclk); -++ } else { -++ /* We're going SLOWER: first update RTCOR value -++ * before changing the frequency. -++ */ -++ jz_update_dram_rtcor(new_mclk); -++ } -++} -++ -++static void jz_update_dram_post(unsigned int cur_mclk, unsigned int new_mclk) -++{ -++ /* No risk, no fun: run with interrupts on! */ -++ if (new_mclk > cur_mclk) { -++ /* We're going FASTER, so update RTCOR -++ * after changing the frequency -++ */ -++ jz_update_dram_rtcor(new_mclk); -++ } else { -++ /* We're going SLOWER: so update TRAS, RCD, TPC, TRWL -++ * and TRC of DMCR after changing the frequency. -++ */ -++ jz_update_dram_dmcr(new_mclk); -++ } -++} -++ -++static void jz_scale_divisors(struct dpm_regs *regs) -++{ -++ unsigned int cpccr; -++ unsigned int cur_mclk, new_mclk; -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ unsigned int tmp = 0, wait = PLL_WAIT_500NS; -++ -++ cpccr = REG_CPM_CPCCR; -++ cpccr &= ~((unsigned long)regs->cpccr_mask); -++ cpccr |= regs->cpccr; -++ cpccr |= CPM_CPCCR_CE; /* update immediately */ -++ -++ cur_mclk = __cpm_get_mclk(); -++ new_mclk = __cpm_get_pllout() / div[(cpccr & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT]; -++ -++ /* Update some DRAM parameters before changing frequency */ -++ jz_update_dram_prev(cur_mclk, new_mclk); -++ -++ /* update register to change the clocks. -++ * align this code to a cache line. -++ */ -++ __asm__ __volatile__( -++ ".set noreorder\n\t" -++ ".align 5\n" -++ "sw %1,0(%0)\n\t" -++ "li %3,0\n\t" -++ "1:\n\t" -++ "bne %3,%2,1b\n\t" -++ "addi %3, 1\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ ".set reorder\n\t" -++ : -++ : "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp)); -++ -++ /* Update some other DRAM parameters after changing frequency */ -++ jz_update_dram_post(cur_mclk, new_mclk); -++} -++ -++#ifdef CHANGE_PLL -++/* Maintain the LCD clock and pixel clock */ -++static void jz_scale_lcd_divisors(struct dpm_regs *regs) -++{ -++ unsigned int new_pll, new_lcd_div, new_lcdpix_div; -++ unsigned int cpccr; -++ unsigned int tmp = 0, wait = PLL_WAIT_500NS; -++ -++ if (!boot_config.lcd_clks_initialized) return; -++ -++ new_pll = __cpm_get_pllout(); -++ new_lcd_div = new_pll / boot_config.lcd_clk; -++ new_lcdpix_div = new_pll / boot_config.lcdpix_clk; -++ -++ if (new_lcd_div < 1) -++ new_lcd_div = 1; -++ if (new_lcd_div > 16) -++ new_lcd_div = 16; -++ -++ if (new_lcdpix_div < 1) -++ new_lcdpix_div = 1; -++ if (new_lcdpix_div > 512) -++ new_lcdpix_div = 512; -++ -++// REG_CPM_CPCCR2 = new_lcdpix_div - 1; -++ -++ cpccr = REG_CPM_CPCCR; -++ cpccr &= ~CPM_CPCCR_LDIV_MASK; -++ cpccr |= ((new_lcd_div - 1) << CPM_CPCCR_LDIV_BIT); -++ cpccr |= CPM_CPCCR_CE; /* update immediately */ -++ -++ /* update register to change the clocks. -++ * align this code to a cache line. -++ */ -++ __asm__ __volatile__( -++ ".set noreorder\n\t" -++ ".align 5\n" -++ "sw %1,0(%0)\n\t" -++ "li %3,0\n\t" -++ "1:\n\t" -++ "bne %3,%2,1b\n\t" -++ "addi %3, 1\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ ".set reorder\n\t" -++ : -++ : "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp)); -++} -++ -++static void jz_scale_pll(struct dpm_regs *regs) -++{ -++ unsigned int cppcr; -++ unsigned int cur_mclk, new_mclk, new_pll; -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ int od[] = {1, 2, 2, 4}; -++ -++ cppcr = REG_CPM_CPPCR; -++ cppcr &= ~(regs->cppcr_mask | CPM_CPPCR_PLLS | CPM_CPPCR_PLLEN | CPM_CPPCR_PLLST_MASK); -++ regs->cppcr &= ~CPM_CPPCR_PLLEN; -++ cppcr |= (regs->cppcr | 0xff); -++ -++ /* Update some DRAM parameters before changing frequency */ -++ new_pll = JZ_EXTAL * ((cppcr>>23)+2) / ((((cppcr>>18)&0x1f)+2) * od[(cppcr>>16)&0x03]); -++ cur_mclk = __cpm_get_mclk(); -++ new_mclk = new_pll / div[(REG_CPM_CPCCR>>16) & 0xf]; -++ -++ /* -++ * Update some SDRAM parameters -++ */ -++ jz_update_dram_prev(cur_mclk, new_mclk); -++ -++ /* -++ * Update PLL, align code to cache line. -++ */ -++ cppcr |= CPM_CPPCR_PLLEN; -++ __asm__ __volatile__( -++ ".set noreorder\n\t" -++ ".align 5\n" -++ "sw %1,0(%0)\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ "nop\n\t" -++ ".set reorder\n\t" -++ : -++ : "r" (CPM_CPPCR), "r" (cppcr)); -++ -++ /* Update some other DRAM parameters after changing frequency */ -++ jz_update_dram_post(cur_mclk, new_mclk); -++} -++#endif -++ -++static void jz4750d_transition(struct dpm_regs *regs) -++{ -++ /* -++ * Get and save some boot-time conditions. -++ */ -++ jz_init_boot_config(); -++ -++#ifdef CHANGE_PLL -++ /* -++ * Disable LCD before scaling pll. -++ * LCD and LCD pixel clocks should not be changed even if the PLL -++ * output frequency has been changed. -++ */ -++ REG_LCD_CTRL &= ~LCD_CTRL_ENA; -++ -++ /* -++ * Stop module clocks before scaling PLL -++ */ -++ __cpm_stop_eth(); -++ __cpm_stop_aic(1); -++ __cpm_stop_aic(2); -++#endif -++ -++ /* ... add more as necessary */ -++ -++ if (regs->pll_up_flag == PLL_GOES_UP) { -++ /* the pll frequency is going up, so change dividors first */ -++ jz_scale_divisors(regs); -++#ifdef CHANGE_PLL -++ jz_scale_pll(regs); -++#endif -++ } -++ else if (regs->pll_up_flag == PLL_GOES_DOWN) { -++ /* the pll frequency is going down, so change pll first */ -++#ifdef CHANGE_PLL -++ jz_scale_pll(regs); -++#endif -++ jz_scale_divisors(regs); -++ } -++ else { -++ /* the pll frequency is unchanged, so change divisors only */ -++ jz_scale_divisors(regs); -++ } -++ -++#ifdef CHANGE_PLL -++ /* -++ * Restart module clocks before scaling PLL -++ */ -++ __cpm_start_eth(); -++ __cpm_start_aic(1); -++ __cpm_start_aic(2); -++ -++ /* ... add more as necessary */ -++ -++ /* Scale the LCD divisors after scaling pll */ -++ if (regs->pll_up_flag != PLL_UNCHANGED) { -++ jz_scale_lcd_divisors(regs); -++ } -++ -++ /* Enable LCD controller */ -++ REG_LCD_CTRL &= ~LCD_CTRL_DIS; -++ REG_LCD_CTRL |= LCD_CTRL_ENA; -++#endif -++ -++ /* Update system clocks */ -++ jz_update_clocks(); -++} -++ -++extern unsigned int idle_times; -++static unsigned int jz4750d_freq_get(unsigned int cpu) -++{ -++ return (__cpm_get_cclk() / 1000); -++} -++ -++static unsigned int index_to_divisor(unsigned int index, struct dpm_regs *regs) -++{ -++ int n2FR[33] = { -++ 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, -++ 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, -++ 9 -++ }; -++ int div[4] = {1, 2, 2, 2}; /* divisors of I:S:P:M */ -++ unsigned int div_of_cclk, new_freq, i; -++ -++ regs->pll_up_flag = PLL_UNCHANGED; -++ regs->cpccr_mask = CPM_CPCCR_CDIV_MASK | CPM_CPCCR_HDIV_MASK | CPM_CPCCR_PDIV_MASK | CPM_CPCCR_MDIV_MASK; -++ -++ new_freq = jz4750d_freq_table.table[index].frequency; -++ -++ do { -++ div_of_cclk = __cpm_get_pllout() / (1000 * new_freq); -++ } while (div_of_cclk==0); -++ -++ if(div_of_cclk == 1 || div_of_cclk == 2 || div_of_cclk == 4) { -++ for(i = 1; i<4; i++) { -++ div[i] = 3; -++ } -++ } else { -++ for(i = 1; i<4; i++) { -++ div[i] = 2; -++ } -++ } -++ -++ for(i = 0; i<4; i++) { -++ div[i] *= div_of_cclk; -++ } -++ -++ dprintk("divisors of I:S:P:M = %d:%d:%d:%d\n", div[0], div[1], div[2], div[3]); -++ -++ regs->cpccr = -++ (n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) | -++ (n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) | -++ (n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) | -++ (n2FR[div[3]] << CPM_CPCCR_MDIV_BIT); -++ -++ return div_of_cclk; -++} -++ -++static void jz4750d_set_cpu_divider_index(unsigned int cpu, unsigned int index) -++{ -++ unsigned long divisor, old_divisor; -++ struct cpufreq_freqs freqs; -++ struct dpm_regs regs; -++ -++ old_divisor = __cpm_get_pllout() / __cpm_get_cclk(); -++ divisor = index_to_divisor(index, ®s); -++ -++ freqs.old = __cpm_get_cclk() / 1000; -++ freqs.new = __cpm_get_pllout() / (1000 * divisor); -++ freqs.cpu = cpu; -++ -++ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); -++ -++ if (old_divisor != divisor) -++ jz4750d_transition(®s); -++ -++ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); -++} -++ -++static int jz4750d_freq_target(struct cpufreq_policy *policy, -++ unsigned int target_freq, -++ unsigned int relation) -++{ -++ unsigned int new_index = 0; -++ -++ if (cpufreq_frequency_table_target(policy, -++ &jz4750d_freq_table.table[0], -++ target_freq, relation, &new_index)) -++ return -EINVAL; -++ -++ jz4750d_set_cpu_divider_index(policy->cpu, new_index); -++ -++ dprintk("new frequency is %d KHz (REG_CPM_CPCCR:0x%x)\n", __cpm_get_cclk() / 1000, REG_CPM_CPCCR); -++ -++ return 0; -++} -++ -++static int jz4750d_freq_verify(struct cpufreq_policy *policy) -++{ -++ return cpufreq_frequency_table_verify(policy, -++ &jz4750d_freq_table.table[0]); -++} -++ -++static int __init jz4750d_cpufreq_driver_init(struct cpufreq_policy *policy) -++{ -++ -++ struct cpufreq_frequency_table *table = &jz4750d_freq_table.table[0]; -++ unsigned int MAX_FREQ; -++ -++ dprintk(KERN_INFO "Jz4750d cpufreq driver\n"); -++ -++ if (policy->cpu != 0) -++ return -EINVAL; -++ -++ policy->cur = MAX_FREQ = __cpm_get_cclk() / 1000; /* in kHz. Current and max frequency is determined by u-boot */ -++ policy->governor = CPUFREQ_DEFAULT_GOVERNOR; -++ -++ policy->cpuinfo.min_freq = MAX_FREQ/8; -++ policy->cpuinfo.max_freq = MAX_FREQ; -++ policy->cpuinfo.transition_latency = 100000; /* in 10^(-9) s = nanoseconds */ -++ -++ table[0].index = 0; -++ table[0].frequency = MAX_FREQ/8; -++ table[1].index = 1; -++ table[1].frequency = MAX_FREQ/6; -++ table[2].index = 2; -++ table[2].frequency = MAX_FREQ/4; -++ table[3].index = 3; -++ table[3].frequency = MAX_FREQ/3; -++ table[4].index = 4; -++ table[4].frequency = MAX_FREQ/2; -++ table[5].index = 5; -++ table[5].frequency = MAX_FREQ; -++ table[6].index = 6; -++ table[6].frequency = CPUFREQ_TABLE_END; -++ -++#ifdef CONFIG_CPU_FREQ_STAT_DETAILS -++ cpufreq_frequency_table_get_attr(table, policy->cpu); /* for showing /sys/devices/system/cpu/cpuX/cpufreq/stats/ */ -++#endif -++ -++ return cpufreq_frequency_table_cpuinfo(policy, table); -++} -++ -++static struct cpufreq_driver cpufreq_jz4750d_driver = { -++// .flags = CPUFREQ_STICKY, -++ .init = jz4750d_cpufreq_driver_init, -++ .verify = jz4750d_freq_verify, -++ .target = jz4750d_freq_target, -++ .get = jz4750d_freq_get, -++ .name = "jz4750d", -++}; -++ -++static int __init jz4750d_cpufreq_init(void) -++{ -++ return cpufreq_register_driver(&cpufreq_jz4750d_driver); -++} -++ -++static void __exit jz4750d_cpufreq_exit(void) -++{ -++ cpufreq_unregister_driver(&cpufreq_jz4750d_driver); -++} -++ -++module_init(jz4750d_cpufreq_init); -++module_exit(jz4750d_cpufreq_exit); -++ -++MODULE_AUTHOR("Regen "); -++MODULE_DESCRIPTION("cpufreq driver for Jz4750d"); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750d/dma.c linux-2.6.24.7/arch/mips/jz4750d/dma.c -+--- linux-2.6.24.7.old/arch/mips/jz4750d/dma.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750d/dma.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,822 @@ -++/* -++ * linux/arch/mips/jz4750d/dma.c -++ * -++ * Support functions for the JZ4750D internal DMA channels. -++ * No-descriptor transfer only. -++ * Descriptor transfer should also call jz_request_dma() to get a free -++ * channel and call jz_free_dma() to free the channel. And driver should -++ * build the DMA descriptor and setup the DMA channel by itself. -++ * -++ * Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++ -++/* -++ * A note on resource allocation: -++ * -++ * All drivers needing DMA channels, should allocate and release them -++ * through the public routines `jz_request_dma()' and `jz_free_dma()'. -++ * -++ * In order to avoid problems, all processes should allocate resources in -++ * the same sequence and release them in the reverse order. -++ * -++ * So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ. -++ * When releasing them, first release the IRQ, then release the DMA. The -++ * main reason for this order is that, if you are requesting the DMA buffer -++ * done interrupt, you won't know the irq number until the DMA channel is -++ * returned from jz_request_dma(). -++ */ -++ -++struct jz_dma_chan jz_dma_table[MAX_DMA_NUM] = { -++ {dev_id:DMA_ID_BCH_ENC,}, /* DMAC0 channel 0, reserved for BCH */ -++ {dev_id:-1,}, /* DMAC0 channel 1 */ -++ {dev_id:-1,}, /* DMAC0 channel 2 */ -++ {dev_id:-1,}, /* DMAC0 channel 3 */ -++ {dev_id:-1,}, /* DMAC1 channel 0 */ -++ {dev_id:-1,}, /* DMAC1 channel 1 */ -++ {dev_id:-1,}, /* DMAC1 channel 2 */ -++ {dev_id:-1,}, /* DMAC1 channel 3 */ -++}; -++ -++// Device FIFO addresses and default DMA modes -++static const struct { -++ unsigned int fifo_addr; -++ unsigned int dma_mode; -++ unsigned int dma_source; -++} dma_dev_table[DMA_ID_MAX] = { -++ {0, DMA_AUTOINIT, DMAC_DRSR_RS_EXT}, /* External request with DREQn */ -++ {0x18000000, DMA_AUTOINIT, DMAC_DRSR_RS_NAND}, /* NAND request */ -++ {CPHYSADDR(BCH_DR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_BCH_ENC}, -++ {CPHYSADDR(BCH_DR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_BCH_DEC}, -++ {0, DMA_AUTOINIT, DMAC_DRSR_RS_AUTO}, -++// {CPHYSADDR(TSSI_FIFO), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_TSSIIN}, -++ {CPHYSADDR(UART3_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART3OUT}, -++ {CPHYSADDR(UART3_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART3IN}, -++ {CPHYSADDR(UART2_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART2OUT}, -++ {CPHYSADDR(UART2_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART2IN}, -++ {CPHYSADDR(UART1_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART1OUT}, -++ {CPHYSADDR(UART1_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART1IN}, -++ {CPHYSADDR(UART0_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART0OUT}, -++ {CPHYSADDR(UART0_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART0IN}, -++ {CPHYSADDR(SSI_DR(0)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSI0OUT}, -++ {CPHYSADDR(SSI_DR(0)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSI0IN}, -++ {CPHYSADDR(AIC_DR), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_AICOUT}, -++ {CPHYSADDR(AIC_DR), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_AICIN}, -++ {CPHYSADDR(MSC_TXFIFO(0)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSC0OUT}, -++ {CPHYSADDR(MSC_RXFIFO(0)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSC0IN}, -++ {0, DMA_AUTOINIT, DMAC_DRSR_RS_TCU}, -++ {SADC_TSDAT, DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SADC},/* Touch Screen Data Register */ -++ {CPHYSADDR(MSC_TXFIFO(1)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSC1OUT}, /* SSC1 TX */ -++ {CPHYSADDR(MSC_RXFIFO(1)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSC1IN}, /* SSC1 RX */ -++ {CPHYSADDR(SSI_DR(1)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSI1OUT}, -++ {CPHYSADDR(SSI_DR(1)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSI1IN}, -++ {CPHYSADDR(PCM_DP), DMA_16BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_PMOUT}, -++ {CPHYSADDR(PCM_DP), DMA_16BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_PMIN}, -++ {}, -++}; -++ -++ -++int jz_dma_read_proc(char *buf, char **start, off_t fpos, -++ int length, int *eof, void *data) -++{ -++ int i, len = 0; -++ struct jz_dma_chan *chan; -++ -++ for (i = 0; i < MAX_DMA_NUM; i++) { -++ if ((chan = get_dma_chan(i)) != NULL) { -++ len += sprintf(buf + len, "%2d: %s\n", -++ i, chan->dev_str); -++ } -++ } -++ -++ if (fpos >= len) { -++ *start = buf; -++ *eof = 1; -++ return 0; -++ } -++ *start = buf + fpos; -++ if ((len -= fpos) > length) -++ return length; -++ *eof = 1; -++ return len; -++} -++ -++ -++void dump_jz_dma_channel(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan; -++ -++ if (dmanr > MAX_DMA_NUM) -++ return; -++ chan = &jz_dma_table[dmanr]; -++ -++ printk("DMA%d Registers:\n", dmanr); -++ printk(" DMACR = 0x%08x\n", REG_DMAC_DMACR(chan->io/HALF_DMA_NUM)); -++ printk(" DSAR = 0x%08x\n", REG_DMAC_DSAR(dmanr)); -++ printk(" DTAR = 0x%08x\n", REG_DMAC_DTAR(dmanr)); -++ printk(" DTCR = 0x%08x\n", REG_DMAC_DTCR(dmanr)); -++ printk(" DRSR = 0x%08x\n", REG_DMAC_DRSR(dmanr)); -++ printk(" DCCSR = 0x%08x\n", REG_DMAC_DCCSR(dmanr)); -++ printk(" DCMD = 0x%08x\n", REG_DMAC_DCMD(dmanr)); -++ printk(" DDA = 0x%08x\n", REG_DMAC_DDA(dmanr)); -++ printk(" DMADBR = 0x%08x\n", REG_DMAC_DMADBR(chan->io/HALF_DMA_NUM)); -++} -++ -++ -++/** -++ * jz_request_dma - dynamically allcate an idle DMA channel to return -++ * @dev_id: the specified dma device id or DMA_ID_RAW_SET -++ * @dev_str: the specified dma device string name -++ * @irqhandler: the irq handler, or NULL -++ * @irqflags: the irq handler flags -++ * @irq_dev_id: the irq handler device id for shared irq -++ * -++ * Finds a free channel, and binds the requested device to it. -++ * Returns the allocated channel number, or negative on error. -++ * Requests the DMA done IRQ if irqhandler != NULL. -++ * -++*/ -++/*int jz_request_dma(int dev_id, const char *dev_str, -++ void (*irqhandler)(int, void *, struct pt_regs *), -++ unsigned long irqflags, -++ void *irq_dev_id) -++*/ -++ -++int jz_request_dma(int dev_id, const char *dev_str, -++ irqreturn_t (*irqhandler)(int, void *), -++ unsigned long irqflags, -++ void *irq_dev_id) -++{ -++ struct jz_dma_chan *chan; -++ int i, ret; -++ -++ if (dev_id < 0 || dev_id >= DMA_ID_MAX) -++ return -EINVAL; -++ -++ for (i = 0; i < MAX_DMA_NUM; i++) { -++ if (jz_dma_table[i].dev_id < 0) -++ break; -++ } -++ if (i == MAX_DMA_NUM) /* no free channel */ -++ return -ENODEV; -++ -++ /* we got a free channel */ -++ chan = &jz_dma_table[i]; -++ -++ if (irqhandler) { -++ chan->irq = IRQ_DMA_0 + i; // allocate irq number -++ chan->irq_dev = irq_dev_id; -++ if ((ret = request_irq(chan->irq, irqhandler, irqflags, -++ dev_str, chan->irq_dev))) { -++ chan->irq = -1; -++ chan->irq_dev = NULL; -++ return ret; -++ } -++ } else { -++ chan->irq = -1; -++ chan->irq_dev = NULL; -++ } -++ -++ // fill it in -++ chan->io = i; -++ chan->dev_id = dev_id; -++ chan->dev_str = dev_str; -++ chan->fifo_addr = dma_dev_table[dev_id].fifo_addr; -++ chan->mode = dma_dev_table[dev_id].dma_mode; -++ chan->source = dma_dev_table[dev_id].dma_source; -++ -++ if (i < HALF_DMA_NUM) -++ REG_DMAC_DMACKE(0) = 1 << i; -++ else -++ REG_DMAC_DMACKE(1) = 1 << (i - HALF_DMA_NUM); -++ -++ return i; -++} -++ -++void jz_free_dma(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) { -++ printk("Trying to free DMA%d\n", dmanr); -++ return; -++ } -++ -++ disable_dma(dmanr); -++ if (chan->irq) -++ free_irq(chan->irq, chan->irq_dev); -++ -++ chan->irq = -1; -++ chan->irq_dev = NULL; -++ chan->dev_id = -1; -++} -++ -++void jz_set_dma_dest_width(int dmanr, int nbit) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ chan->mode &= ~DMAC_DCMD_DWDH_MASK; -++ switch (nbit) { -++ case 8: -++ chan->mode |= DMAC_DCMD_DWDH_8; -++ break; -++ case 16: -++ chan->mode |= DMAC_DCMD_DWDH_16; -++ break; -++ case 32: -++ chan->mode |= DMAC_DCMD_DWDH_32; -++ break; -++ } -++} -++ -++void jz_set_dma_src_width(int dmanr, int nbit) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ chan->mode &= ~DMAC_DCMD_SWDH_MASK; -++ switch (nbit) { -++ case 8: -++ chan->mode |= DMAC_DCMD_SWDH_8; -++ break; -++ case 16: -++ chan->mode |= DMAC_DCMD_SWDH_16; -++ break; -++ case 32: -++ chan->mode |= DMAC_DCMD_SWDH_32; -++ break; -++ } -++} -++ -++void jz_set_dma_block_size(int dmanr, int nbyte) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ chan->mode &= ~DMAC_DCMD_DS_MASK; -++ switch (nbyte) { -++ case 1: -++ chan->mode |= DMAC_DCMD_DS_8BIT; -++ break; -++ case 2: -++ chan->mode |= DMAC_DCMD_DS_16BIT; -++ break; -++ case 4: -++ chan->mode |= DMAC_DCMD_DS_32BIT; -++ break; -++ case 16: -++ chan->mode |= DMAC_DCMD_DS_16BYTE; -++ break; -++ case 32: -++ chan->mode |= DMAC_DCMD_DS_32BYTE; -++ break; -++ } -++} -++ -++unsigned int jz_get_dma_command(int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ return chan->mode; -++} -++ -++/** -++ * jz_set_dma_mode - do the raw settings for the specified DMA channel -++ * @dmanr: the specified DMA channel -++ * @mode: dma operate mode, DMA_MODE_READ or DMA_MODE_WRITE -++ * @dma_mode: dma raw mode -++ * @dma_source: dma raw request source -++ * @fifo_addr: dma raw device fifo address -++ * -++ * Ensure call jz_request_dma(DMA_ID_RAW_SET, ...) first, then call -++ * jz_set_dma_mode() rather than set_dma_mode() if you work with -++ * and external request dma device. -++ * -++ * NOTE: Don not dynamically allocate dma channel if one external request -++ * dma device will occupy this channel. -++*/ -++int jz_set_dma_mode(unsigned int dmanr, unsigned int mode, -++ unsigned int dma_mode, unsigned int dma_source, -++ unsigned int fifo_addr) -++{ -++ int dev_id, i; -++ struct jz_dma_chan *chan; -++ -++ if (dmanr > MAX_DMA_NUM) -++ return -ENODEV; -++ for (i = 0; i < MAX_DMA_NUM; i++) { -++ if (jz_dma_table[i].dev_id < 0) -++ break; -++ } -++ if (i == MAX_DMA_NUM) -++ return -ENODEV; -++ -++ chan = &jz_dma_table[dmanr]; -++ dev_id = chan->dev_id; -++ if (dev_id > 0) { -++ printk(KERN_DEBUG "%s sets the allocated DMA channel %d!\n", -++ __FUNCTION__, dmanr); -++ return -ENODEV; -++ } -++ -++ /* clone it from the dynamically allocated. */ -++ if (i != dmanr) { -++ chan->irq = jz_dma_table[i].irq; -++ chan->irq_dev = jz_dma_table[i].irq_dev; -++ chan->dev_str = jz_dma_table[i].dev_str; -++ jz_dma_table[i].irq = 0; -++ jz_dma_table[i].irq_dev = NULL; -++ jz_dma_table[i].dev_id = -1; -++ } -++ chan->dev_id = DMA_ID_RAW_SET; -++ chan->io = dmanr; -++ chan->fifo_addr = fifo_addr; -++ chan->mode = dma_mode; -++ chan->source = dma_source; -++ -++ set_dma_mode(dmanr, dma_mode); -++ -++ return dmanr; -++} -++ -++void enable_dma(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ REG_DMAC_DCCSR(dmanr) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -++ REG_DMAC_DCCSR(dmanr) |= DMAC_DCCSR_NDES; /* No-descriptor transfer */ -++ __dmac_enable_channel(dmanr); -++ if (chan->irq) -++ __dmac_channel_enable_irq(dmanr); -++} -++ -++#define DMA_DISABLE_POLL 0x10000 -++ -++void disable_dma(unsigned int dmanr) -++{ -++ int i; -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ if (!__dmac_channel_enabled(dmanr)) -++ return; -++ -++ for (i = 0; i < DMA_DISABLE_POLL; i++) -++ if (__dmac_channel_transmit_end_detected(dmanr)) -++ break; -++#if 0 -++ if (i == DMA_DISABLE_POLL) -++ printk(KERN_INFO "disable_dma: poll expired!\n"); -++#endif -++ -++ __dmac_disable_channel(dmanr); -++ if (chan->irq) -++ __dmac_channel_disable_irq(dmanr); -++} -++ -++/* Note: DMA_MODE_MASK is simulated by sw */ -++void set_dma_mode(unsigned int dmanr, unsigned int mode) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -++ mode &= DMA_MODE_MASK; -++ if (mode == DMA_MODE_READ) { -++ chan->mode |= DMAC_DCMD_DAI; -++ chan->mode &= ~DMAC_DCMD_SAI; -++ } else if (mode == DMA_MODE_WRITE) { -++ chan->mode |= DMAC_DCMD_SAI; -++ chan->mode &= ~DMAC_DCMD_DAI; -++ } else { -++ printk(KERN_DEBUG "set_dma_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -++ } -++ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -++ REG_DMAC_DRSR(chan->io) = chan->source; -++} -++ -++void set_dma_addr(unsigned int dmanr, unsigned int phyaddr) -++{ -++ unsigned int mode; -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ mode = chan->mode & DMA_MODE_MASK; -++ if (mode == DMA_MODE_READ) { -++ REG_DMAC_DSAR(chan->io) = chan->fifo_addr; -++ REG_DMAC_DTAR(chan->io) = phyaddr; -++ } else if (mode == DMA_MODE_WRITE) { -++ REG_DMAC_DSAR(chan->io) = phyaddr; -++ REG_DMAC_DTAR(chan->io) = chan->fifo_addr; -++ } else -++ printk(KERN_DEBUG "Driver should call set_dma_mode() ahead set_dma_addr()!\n"); -++} -++ -++void set_dma_count(unsigned int dmanr, unsigned int bytecnt) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ int dma_ds[] = {4, 1, 2, 16, 32}; -++ unsigned int ds; -++ -++ if (!chan) -++ return; -++ -++ ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT; -++ REG_DMAC_DTCR(chan->io) = bytecnt / dma_ds[ds]; // transfer count -++} -++ -++unsigned int get_dma_residue(unsigned int dmanr) -++{ -++ unsigned int count, ds; -++ int dma_ds[] = {4, 1, 2, 16, 32}; -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return 0; -++ -++ ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT; -++ count = REG_DMAC_DTCR(chan->io); -++ count = count * dma_ds[ds]; -++ -++ return count; -++} -++ -++void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ switch (audio_fmt) { -++ case AFMT_U8: -++ /* burst mode : 32BIT */ -++ break; -++ case AFMT_S16_LE: -++ /* burst mode : 16BYTE */ -++ if (mode == DMA_MODE_READ) { -++ chan->mode = DMA_AIC_32_16BYTE_RX_CMD | DMA_MODE_READ; -++ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -++ mode &= DMA_MODE_MASK; -++ chan->mode |= DMAC_DCMD_DAI; -++ chan->mode &= ~DMAC_DCMD_SAI; -++ } else if (mode == DMA_MODE_WRITE) { -++ chan->mode = DMA_AIC_32_16BYTE_TX_CMD | DMA_MODE_WRITE; -++ //chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE; -++ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -++ mode &= DMA_MODE_MASK; -++ chan->mode |= DMAC_DCMD_SAI; -++ chan->mode &= ~DMAC_DCMD_DAI; -++ } else -++ printk("oss_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -++ -++ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -++ REG_DMAC_DRSR(chan->io) = chan->source; -++ break; -++ } -++} -++ -++void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ -++ if (!chan) -++ return; -++ -++ switch (audio_fmt) { -++ case 8: -++ /* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */ -++ break; -++ case 16: -++ /* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */ -++ if (mode == DMA_MODE_READ) { -++ chan->mode = DMA_AIC_16BYTE_RX_CMD | DMA_MODE_READ; -++ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -++ mode &= DMA_MODE_MASK; -++ chan->mode |= DMAC_DCMD_DAI; -++ chan->mode &= ~DMAC_DCMD_SAI; -++ } else if (mode == DMA_MODE_WRITE) { -++ chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE; -++ chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI); -++ mode &= DMA_MODE_MASK; -++ chan->mode |= DMAC_DCMD_SAI; -++ chan->mode &= ~DMAC_DCMD_DAI; -++ } else -++ printk("alsa_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n"); -++ -++ REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK; -++ REG_DMAC_DRSR(chan->io) = chan->source; -++ break; -++ } -++} -++ -++//#define JZ4750D_DMAC_TEST_ENABLE -++#undef JZ4750D_DMAC_TEST_ENABLE -++ -++#ifdef JZ4750D_DMAC_TEST_ENABLE -++ -++/* -++ * DMA test: external address <--> external address -++ */ -++#define TEST_DMA_SIZE 16*1024 -++ -++static jz_dma_desc *dma_desc; -++ -++static int dma_chan; -++static dma_addr_t dma_desc_phys_addr; -++static unsigned int dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr; -++ -++static int dma_check_result(void *src, void *dst, int size) -++{ -++ unsigned int addr1, addr2, i, err = 0; -++ -++ addr1 = (unsigned int)src; -++ addr2 = (unsigned int)dst; -++ -++ for (i = 0; i < size; i += 4) { -++ if (*(volatile unsigned int *)addr1 != *(volatile unsigned int *)addr2) { -++ err++; -++ printk("wrong data at 0x%08x: src 0x%08x dst 0x%08x\n", addr2, *(volatile unsigned int *)addr1, *(volatile unsigned int *)addr2); -++ } -++ addr1 += 4; -++ addr2 += 4; -++ } -++ printk("check DMA result err=%d\n", err); -++ return err; -++} -++ -++static irqreturn_t jz4750d_dma_irq(int irq, void *dev_id) -++{ -++ printk("jz4750d_dma_irq %d\n", irq); -++ -++ -++ if (__dmac_channel_transmit_halt_detected(dma_chan)) { -++ printk("DMA HALT\n"); -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ __dmac_channel_clear_transmit_halt(dma_chan); -++ } -++ -++ if (__dmac_channel_address_error_detected(dma_chan)) { -++ printk("DMA ADDR ERROR\n"); -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ REG_DMAC_DSAR(dma_chan) = 0; /* clear source address register */ -++ REG_DMAC_DTAR(dma_chan) = 0; /* clear target address register */ -++ __dmac_channel_clear_address_error(dma_chan); -++ } -++ -++ if (__dmac_channel_descriptor_invalid_detected(dma_chan)) { -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ printk("DMA DESC INVALID\n"); -++ __dmac_channel_clear_descriptor_invalid(dma_chan); -++ } -++ -++ if (__dmac_channel_count_terminated_detected(dma_chan)) { -++ printk("DMA CT\n"); -++ __dmac_channel_clear_count_terminated(dma_chan); -++ } -++ -++ if (__dmac_channel_transmit_end_detected(dma_chan)) { -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ printk("DMA TT\n"); -++ __dmac_channel_clear_transmit_end(dma_chan); -++ dump_jz_dma_channel(dma_chan); -++ dma_check_result((void *)dma_src_addr, (void *)dma_dst_addr, TEST_DMA_SIZE); -++ } -++ -++ return IRQ_HANDLED; -++} -++ -++void dma_nodesc_test(void) -++{ -++ unsigned int addr, i; -++ -++ printk("dma_nodesc_test\n"); -++ -++ /* Request DMA channel and setup irq handler */ -++ dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4750d_dma_irq, -++ IRQF_DISABLED, NULL); -++ if (dma_chan < 0) { -++ printk("Setup irq failed\n"); -++ return; -++ } -++ -++ printk("Requested DMA channel = %d\n", dma_chan); -++ -++ /* Allocate DMA buffers */ -++ dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -++ dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -++ -++ dma_src_phys_addr = CPHYSADDR(dma_src_addr); -++ dma_dst_phys_addr = CPHYSADDR(dma_dst_addr); -++ -++ printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n", -++ dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr); -++ -++ /* Prepare data for source buffer */ -++ addr = (unsigned int)dma_src_addr; -++ for (i = 0; i < TEST_DMA_SIZE; i += 4) { -++ *(volatile unsigned int *)addr = addr; -++ addr += 4; -++ } -++ dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE); -++ -++ /* Init target buffer */ -++ memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE); -++ dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE); -++ -++ /* Init DMA module */ -++ printk("Starting DMA\n"); -++ REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = 0; -++ REG_DMAC_DCCSR(dma_chan) = 0; -++ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; -++ REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr; -++ REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr; -++ REG_DMAC_DTCR(dma_chan) = 512; -++ REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TIE; -++ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; -++ REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = DMAC_DMACR_DMAE; /* global DMA enable bit */ -++ -++ printk("DMA started. IMR=%08x\n", REG_INTC_IMR); -++ -++ /* wait a long time, ensure transfer end */ -++ printk("wait 3s...\n"); -++ mdelay(3000); /* wait 3s */ -++ -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ /* free buffers */ -++ printk("free DMA buffers\n"); -++ free_pages(dma_src_addr, 2); -++ free_pages(dma_dst_addr, 2); -++ -++ if (dma_desc) -++ free_pages((unsigned int)dma_desc, 0); -++ -++ /* free dma */ -++ jz_free_dma(dma_chan); -++} -++ -++void dma_desc_test(void) -++{ -++ unsigned int next, addr, i; -++ static jz_dma_desc *desc; -++ -++ printk("dma_desc_test\n"); -++ -++ /* Request DMA channel and setup irq handler */ -++ dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4750d_dma_irq, -++ IRQF_DISABLED, NULL); -++ if (dma_chan < 0) { -++ printk("Setup irq failed\n"); -++ return; -++ } -++ -++ printk("Requested DMA channel = %d\n", dma_chan); -++ -++ /* Allocate DMA buffers */ -++ dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -++ dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */ -++ -++ dma_src_phys_addr = CPHYSADDR(dma_src_addr); -++ dma_dst_phys_addr = CPHYSADDR(dma_dst_addr); -++ -++ printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n", -++ dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr); -++ -++ /* Prepare data for source buffer */ -++ addr = (unsigned int)dma_src_addr; -++ for (i = 0; i < TEST_DMA_SIZE; i += 4) { -++ *(volatile unsigned int *)addr = addr; -++ addr += 4; -++ } -++ dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE); -++ -++ /* Init target buffer */ -++ memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE); -++ dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE); -++ -++ /* Allocate DMA descriptors */ -++ dma_desc = (jz_dma_desc *)__get_free_pages(GFP_KERNEL, 0); -++ dma_desc_phys_addr = CPHYSADDR((unsigned long)dma_desc); -++ -++ printk("DMA descriptor address: 0x%08x 0x%08x\n", (u32)dma_desc, dma_desc_phys_addr); -++ -++ /* Setup DMA descriptors */ -++ desc = dma_desc; -++ next = (dma_desc_phys_addr + (sizeof(jz_dma_desc))) >> 4; -++ -++ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -++ desc->dsadr = dma_src_phys_addr; /* DMA source address */ -++ desc->dtadr = dma_dst_phys_addr; /* DMA target address */ -++ desc->ddadr = (next << 24) + 128; /* size: 128*32 bytes = 4096 bytes */ -++ -++ desc++; -++ next = (dma_desc_phys_addr + 2*(sizeof(jz_dma_desc))) >> 4; -++ -++ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -++ desc->dsadr = dma_src_phys_addr + 4096; /* DMA source address */ -++ desc->dtadr = dma_dst_phys_addr + 4096; /* DMA target address */ -++ desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */ -++ -++ desc++; -++ next = (dma_desc_phys_addr + 3*(sizeof(jz_dma_desc))) >> 4; -++ -++ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK; -++ desc->dsadr = dma_src_phys_addr + 8192; /* DMA source address */ -++ desc->dtadr = dma_dst_phys_addr + 8192; /* DMA target address */ -++ desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */ -++ -++ desc++; -++ next = (dma_desc_phys_addr + 4*(sizeof(jz_dma_desc))) >> 4; -++ -++ desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE; -++ desc->dsadr = dma_src_phys_addr + 12*1024; /* DMA source address */ -++ desc->dtadr = dma_dst_phys_addr + 12*1024; /* DMA target address */ -++ desc->ddadr = (next << 24) + 1024; /* size: 1024*4 bytes = 4096 bytes */ -++ -++ dma_cache_wback((unsigned long)dma_desc, 4*(sizeof(jz_dma_desc))); -++ -++ /* Setup DMA descriptor address */ -++ REG_DMAC_DDA(dma_chan) = dma_desc_phys_addr; -++ -++ /* Setup request source */ -++ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; -++ -++ /* Setup DMA channel control/status register */ -++ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; /* descriptor transfer, clear status, start channel */ -++ -++ /* Enable DMA */ -++ REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = DMAC_DMACR_DMAE; -++ -++ /* DMA doorbell set -- start DMA now ... */ -++ REG_DMAC_DMADBSR(dma_chan/HALF_DMA_NUM) = 1 << dma_chan; -++ -++ printk("DMA started. IMR=%08x\n", REG_INTC_IMR); -++ /* wait a long time, ensure transfer end */ -++ printk("wait 3s...\n"); -++ mdelay(3000); /* wait 3s */ -++ -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ /* free buffers */ -++ printk("free DMA buffers\n"); -++ free_pages(dma_src_addr, 2); -++ free_pages(dma_dst_addr, 2); -++ -++ if (dma_desc) -++ free_pages((unsigned int)dma_desc, 0); -++ -++ /* free dma */ -++ jz_free_dma(dma_chan); -++} -++ -++#endif -++ -++//EXPORT_SYMBOL_NOVERS(jz_dma_table); -++EXPORT_SYMBOL(jz_dma_table); -++EXPORT_SYMBOL(jz_request_dma); -++EXPORT_SYMBOL(jz_free_dma); -++EXPORT_SYMBOL(jz_set_dma_src_width); -++EXPORT_SYMBOL(jz_set_dma_dest_width); -++EXPORT_SYMBOL(jz_set_dma_block_size); -++EXPORT_SYMBOL(jz_set_dma_mode); -++EXPORT_SYMBOL(set_dma_mode); -++EXPORT_SYMBOL(jz_set_oss_dma); -++EXPORT_SYMBOL(jz_set_alsa_dma); -++EXPORT_SYMBOL(set_dma_addr); -++EXPORT_SYMBOL(set_dma_count); -++EXPORT_SYMBOL(get_dma_residue); -++EXPORT_SYMBOL(enable_dma); -++EXPORT_SYMBOL(disable_dma); -++EXPORT_SYMBOL(dump_jz_dma_channel); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750d/i2c.c linux-2.6.24.7/arch/mips/jz4750d/i2c.c -+--- linux-2.6.24.7.old/arch/mips/jz4750d/i2c.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750d/i2c.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,273 @@ -++/* -++ * linux/arch/mips/jz4750d/i2c.c -++ * -++ * Jz4750D I2C routines. -++ * -++ * Copyright (C) 2005,2006 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can distribute it and/or modify it -++ * under the terms of the GNU General Public License (Version 2) as -++ * published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -++ * -++ */ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++ -++/* I2C protocol */ -++#define I2C_READ 1 -++#define I2C_WRITE 0 -++ -++#define TIMEOUT 1000 -++ -++/* -++ * I2C bus protocol basic routines -++ */ -++static int i2c_put_data(unsigned char data) -++{ -++ unsigned int timeout = TIMEOUT*10; -++ -++ __i2c_write(data); -++ __i2c_set_drf(); -++ while (__i2c_check_drf() != 0); -++ while (!__i2c_transmit_ended()); -++ while (!__i2c_received_ack() && timeout) -++ timeout--; -++ -++ if (timeout) -++ return 0; -++ else -++ return -ETIMEDOUT; -++} -++ -++#ifdef CONFIG_JZ_TPANEL_ATA2508 -++static int i2c_put_data_nack(unsigned char data) -++{ -++ unsigned int timeout = TIMEOUT*10; -++ -++ __i2c_write(data); -++ __i2c_set_drf(); -++ while (__i2c_check_drf() != 0); -++ while (!__i2c_transmit_ended()); -++ while (timeout--); -++ return 0; -++} -++#endif -++ -++static int i2c_get_data(unsigned char *data, int ack) -++{ -++ int timeout = TIMEOUT*10; -++ -++ if (!ack) -++ __i2c_send_nack(); -++ else -++ __i2c_send_ack(); -++ -++ while (__i2c_check_drf() == 0 && timeout) -++ timeout--; -++ -++ if (timeout) { -++ if (!ack) -++ __i2c_send_stop(); -++ *data = __i2c_read(); -++ __i2c_clear_drf(); -++ return 0; -++ } else -++ return -ETIMEDOUT; -++} -++ -++/* -++ * I2C interface -++ */ -++void i2c_open(void) -++{ -++ __i2c_set_clk(jz_clocks.extalclk, 10000); /* default 10 KHz */ -++ __i2c_enable(); -++} -++ -++void i2c_close(void) -++{ -++ udelay(300); /* wait for STOP goes over. */ -++ __i2c_disable(); -++} -++ -++void i2c_setclk(unsigned int i2cclk) -++{ -++ __i2c_set_clk(jz_clocks.extalclk, i2cclk); -++} -++ -++int i2c_lseek(unsigned char device, unsigned char offset) -++{ -++ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -++ goto device_err; -++ if (i2c_put_data(offset) < 0) -++ goto address_err; -++ return 0; -++ device_err: -++ printk(KERN_DEBUG "No I2C device (0x%02x) installed.\n", device); -++ __i2c_send_stop(); -++ return -ENODEV; -++ address_err: -++ printk(KERN_DEBUG "No I2C device (0x%02x) response.\n", device); -++ __i2c_send_stop(); -++ return -EREMOTEIO; -++} -++ -++int i2c_read(unsigned char device, unsigned char *buf, -++ unsigned char address, int count) -++{ -++ int cnt = count; -++ int timeout = 5; -++ -++L_try_again: -++ -++ if (timeout < 0) -++ goto L_timeout; -++ -++ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -++ goto device_werr; -++ if (i2c_put_data(address) < 0) -++ goto address_err; -++ -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_READ ) < 0) -++ goto device_rerr; -++ __i2c_send_ack(); /* Master sends ACK for continue reading */ -++ while (cnt) { -++ if (cnt == 1) { -++ if (i2c_get_data(buf, 0) < 0) -++ break; -++ } else { -++ if (i2c_get_data(buf, 1) < 0) -++ break; -++ } -++ cnt--; -++ buf++; -++ } -++ -++ __i2c_send_stop(); -++ return count - cnt; -++ device_rerr: -++ device_werr: -++ address_err: -++ timeout --; -++ __i2c_send_stop(); -++ goto L_try_again; -++ -++L_timeout: -++ __i2c_send_stop(); -++ printk("Read I2C device 0x%2x failed.\n", device); -++ return -ENODEV; -++} -++ -++int i2c_write(unsigned char device, unsigned char *buf, -++ unsigned char address, int count) -++{ -++ int cnt = count; -++ int cnt_in_pg; -++ int timeout = 5; -++ unsigned char *tmpbuf; -++ unsigned char tmpaddr; -++ -++ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -++ -++ W_try_again: -++ if (timeout < 0) -++ goto W_timeout; -++ -++ cnt = count; -++ tmpbuf = (unsigned char *)buf; -++ tmpaddr = address; -++ -++ start_write_page: -++ cnt_in_pg = 0; -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -++ goto device_err; -++#ifdef CONFIG_JZ_TPANEL_ATA2508 -++ if (address == 0xff) { -++ if (i2c_put_data_nack(tmpaddr) < 0) -++ goto address_err; -++ while (cnt) { -++ if (++cnt_in_pg > 8) { -++ __i2c_send_stop(); -++ mdelay(1); -++ tmpaddr += 8; -++ goto start_write_page; -++ } -++ if (i2c_put_data_nack(*tmpbuf) < 0) -++ break; -++ cnt--; -++ tmpbuf++; -++ } -++ } -++ else { -++ -++ if (i2c_put_data(tmpaddr) < 0) -++ goto address_err; -++ while (cnt) { -++ if (++cnt_in_pg > 8) { -++ __i2c_send_stop(); -++ mdelay(1); -++ tmpaddr += 8; -++ goto start_write_page; -++ } -++ if (i2c_put_data(*tmpbuf) < 0) -++ break; -++ cnt--; -++ tmpbuf++; -++ } -++ } -++#else -++ if (i2c_put_data(tmpaddr) < 0) -++ goto address_err; -++ while (cnt) { -++ if (++cnt_in_pg > 8) { -++ __i2c_send_stop(); -++ mdelay(1); -++ tmpaddr += 8; -++ goto start_write_page; -++ } -++ if (i2c_put_data(*tmpbuf) < 0) -++ break; -++ cnt--; -++ tmpbuf++; -++ } -++#endif -++ __i2c_send_stop(); -++ return count - cnt; -++ device_err: -++ address_err: -++ timeout--; -++ __i2c_send_stop(); -++ goto W_try_again; -++ -++ W_timeout: -++ printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device); -++ __i2c_send_stop(); -++ return -ENODEV; -++} -++ -++EXPORT_SYMBOL(i2c_open); -++EXPORT_SYMBOL(i2c_close); -++EXPORT_SYMBOL(i2c_setclk); -++EXPORT_SYMBOL(i2c_read); -++EXPORT_SYMBOL(i2c_write); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750d/irq.c linux-2.6.24.7/arch/mips/jz4750d/irq.c -+--- linux-2.6.24.7.old/arch/mips/jz4750d/irq.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750d/irq.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,299 @@ -++/* -++ * linux/arch/mips/jz4750d/irq.c -++ * -++ * JZ4750D interrupt routines. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++ -++/* -++ * INTC irq type -++ */ -++ -++static void enable_intc_irq(unsigned int irq) -++{ -++ __intc_unmask_irq(irq); -++} -++ -++static void disable_intc_irq(unsigned int irq) -++{ -++ __intc_mask_irq(irq); -++} -++ -++static void mask_and_ack_intc_irq(unsigned int irq) -++{ -++ __intc_mask_irq(irq); -++ __intc_ack_irq(irq); -++} -++ -++static void end_intc_irq(unsigned int irq) -++{ -++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -++ enable_intc_irq(irq); -++ } -++} -++ -++static unsigned int startup_intc_irq(unsigned int irq) -++{ -++ enable_intc_irq(irq); -++ return 0; -++} -++ -++static void shutdown_intc_irq(unsigned int irq) -++{ -++ disable_intc_irq(irq); -++} -++ -++static struct irq_chip intc_irq_type = { -++ .typename = "INTC", -++ .startup = startup_intc_irq, -++ .shutdown = shutdown_intc_irq, -++ .enable = enable_intc_irq, -++ .disable = disable_intc_irq, -++ .ack = mask_and_ack_intc_irq, -++ .end = end_intc_irq, -++}; -++ -++/* -++ * GPIO irq type -++ */ -++ -++static void enable_gpio_irq(unsigned int irq) -++{ -++ unsigned int intc_irq; -++ -++ if (irq < (IRQ_GPIO_0 + 32)) { -++ intc_irq = IRQ_GPIO0; -++ } -++ else if (irq < (IRQ_GPIO_0 + 64)) { -++ intc_irq = IRQ_GPIO1; -++ } -++ else if (irq < (IRQ_GPIO_0 + 96)) { -++ intc_irq = IRQ_GPIO2; -++ } -++ else if (irq < (IRQ_GPIO_0 + 128)) { -++ intc_irq = IRQ_GPIO3; -++ } -++ else if (irq < (IRQ_GPIO_0 + 160)) { -++ intc_irq = IRQ_GPIO4; -++ } -++ else { -++ intc_irq = IRQ_GPIO5; -++ } -++ -++ enable_intc_irq(intc_irq); -++ __gpio_unmask_irq(irq - IRQ_GPIO_0); -++} -++ -++static void disable_gpio_irq(unsigned int irq) -++{ -++ __gpio_mask_irq(irq - IRQ_GPIO_0); -++} -++ -++static void mask_and_ack_gpio_irq(unsigned int irq) -++{ -++ __gpio_mask_irq(irq - IRQ_GPIO_0); -++ __gpio_ack_irq(irq - IRQ_GPIO_0); -++} -++ -++static void end_gpio_irq(unsigned int irq) -++{ -++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -++ enable_gpio_irq(irq); -++ } -++} -++ -++static unsigned int startup_gpio_irq(unsigned int irq) -++{ -++ enable_gpio_irq(irq); -++ return 0; -++} -++ -++static void shutdown_gpio_irq(unsigned int irq) -++{ -++ disable_gpio_irq(irq); -++} -++ -++static struct irq_chip gpio_irq_type = { -++ .typename = "GPIO", -++ .startup = startup_gpio_irq, -++ .shutdown = shutdown_gpio_irq, -++ .enable = enable_gpio_irq, -++ .disable = disable_gpio_irq, -++ .ack = mask_and_ack_gpio_irq, -++ .end = end_gpio_irq, -++}; -++ -++/* -++ * DMA irq type -++ */ -++ -++static void enable_dma_irq(unsigned int irq) -++{ -++ unsigned int intc_irq; -++ -++ if ( irq < (IRQ_DMA_0 + HALF_DMA_NUM) ) /* DMAC Group 0 irq */ -++ intc_irq = IRQ_DMAC0; -++ else if ( irq < (IRQ_DMA_0 + MAX_DMA_NUM) ) /* DMAC Group 1 irq */ -++ intc_irq = IRQ_DMAC1; -++ else { -++ printk("%s, unexpected dma irq #%d\n", __FILE__, irq); -++ return; -++ } -++ __intc_unmask_irq(intc_irq); -++ __dmac_channel_enable_irq(irq - IRQ_DMA_0); -++} -++ -++static void disable_dma_irq(unsigned int irq) -++{ -++ __dmac_channel_disable_irq(irq - IRQ_DMA_0); -++} -++ -++static void mask_and_ack_dma_irq(unsigned int irq) -++{ -++ unsigned int intc_irq; -++ -++ if ( irq < (IRQ_DMA_0 + HALF_DMA_NUM) ) /* DMAC Group 0 irq */ -++ intc_irq = IRQ_DMAC0; -++ else if ( irq < (IRQ_DMA_0 + MAX_DMA_NUM) ) /* DMAC Group 1 irq */ -++ intc_irq = IRQ_DMAC1; -++ else { -++ printk("%s, unexpected dma irq #%d\n", __FILE__, irq); -++ return ; -++ } -++ __intc_ack_irq(intc_irq); -++ __dmac_channel_ack_irq(irq-IRQ_DMA_0); /* needed?? add 20080506, Wolfgang */ -++ __dmac_channel_disable_irq(irq - IRQ_DMA_0); -++} -++ -++static void end_dma_irq(unsigned int irq) -++{ -++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { -++ enable_dma_irq(irq); -++ } -++} -++ -++static unsigned int startup_dma_irq(unsigned int irq) -++{ -++ enable_dma_irq(irq); -++ return 0; -++} -++ -++static void shutdown_dma_irq(unsigned int irq) -++{ -++ disable_dma_irq(irq); -++} -++ -++static struct irq_chip dma_irq_type = { -++ .typename = "DMA", -++ .startup = startup_dma_irq, -++ .shutdown = shutdown_dma_irq, -++ .enable = enable_dma_irq, -++ .disable = disable_dma_irq, -++ .ack = mask_and_ack_dma_irq, -++ .end = end_dma_irq, -++}; -++ -++//---------------------------------------------------------------------- -++ -++void __init arch_init_irq(void) -++{ -++ int i; -++ -++ clear_c0_status(0xff04); /* clear ERL */ -++ set_c0_status(0x0400); /* set IP2 */ -++ -++ /* Set up INTC irq -++ */ -++ for (i = 0; i < 32; i++) { -++ disable_intc_irq(i); -++ irq_desc[i].chip = &intc_irq_type; -++ } -++ -++ /* Set up DMAC irq -++ */ -++ for (i = 0; i < NUM_DMA; i++) { -++ disable_dma_irq(IRQ_DMA_0 + i); -++ irq_desc[IRQ_DMA_0 + i].chip = &dma_irq_type; -++ } -++ -++ /* Set up GPIO irq -++ */ -++ for (i = 0; i < NUM_GPIO; i++) { -++ disable_gpio_irq(IRQ_GPIO_0 + i); -++ irq_desc[IRQ_GPIO_0 + i].chip = &gpio_irq_type; -++ } -++} -++ -++static int plat_real_irq(int irq) -++{ -++ switch (irq) { -++ case IRQ_GPIO0: -++ irq = __gpio_group_irq(0) + IRQ_GPIO_0; -++ break; -++ case IRQ_GPIO1: -++ irq = __gpio_group_irq(1) + IRQ_GPIO_0 + 32; -++ break; -++ case IRQ_GPIO2: -++ irq = __gpio_group_irq(2) + IRQ_GPIO_0 + 64; -++ break; -++ case IRQ_GPIO3: -++ irq = __gpio_group_irq(3) + IRQ_GPIO_0 + 96; -++ break; -++ case IRQ_GPIO4: -++ irq = __gpio_group_irq(4) + IRQ_GPIO_0 + 128; -++ break; -++ case IRQ_GPIO5: -++ irq = __gpio_group_irq(5) + IRQ_GPIO_0 + 160; -++ break; -++ case IRQ_DMAC0: -++ case IRQ_DMAC1: -++ irq = __dmac_get_irq() + IRQ_DMA_0; -++ break; -++ } -++ -++ return irq; -++} -++ -++asmlinkage void plat_irq_dispatch(void) -++{ -++ int irq = 0; -++ static unsigned long intc_ipr = 0; -++ -++ intc_ipr |= REG_INTC_IPR; -++ -++ if (!intc_ipr) return; -++ -++ irq = ffs(intc_ipr) - 1; -++ intc_ipr &= ~(1< -++ * -++ * This file is licensed under the terms of the GNU General Public -++ * License version 2. This program is licensed "as is" without any -++ * warranty of any kind, whether express or implied. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#if 0 -++/* OHCI (USB full speed host controller) */ -++static struct resource jz_usb_ohci_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(UHC_BASE), // phys addr for ioremap -++ .end = CPHYSADDR(UHC_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_UHC, -++ .end = IRQ_UHC, -++ .flags = IORESOURCE_IRQ, -++ }, -++}; -++ -++/* The dmamask must be set for OHCI to work */ -++static u64 ohci_dmamask = ~(u32)0; -++ -++static struct platform_device jz_usb_ohci_device = { -++ .name = "jz-ohci", -++ .id = 0, -++ .dev = { -++ .dma_mask = &ohci_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_usb_ohci_resources), -++ .resource = jz_usb_ohci_resources, -++}; -++#endif -++/*** LCD controller ***/ -++static struct resource jz_lcd_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(LCD_BASE), -++ .end = CPHYSADDR(LCD_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_LCD, -++ .end = IRQ_LCD, -++ .flags = IORESOURCE_IRQ, -++ } -++}; -++ -++static u64 jz_lcd_dmamask = ~(u32)0; -++ -++static struct platform_device jz_lcd_device = { -++ .name = "jz-lcd", -++ .id = 0, -++ .dev = { -++ .dma_mask = &jz_lcd_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_lcd_resources), -++ .resource = jz_lcd_resources, -++}; -++ -++/* UDC (USB gadget controller) */ -++static struct resource jz_usb_gdt_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(UDC_BASE), -++ .end = CPHYSADDR(UDC_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_UDC, -++ .end = IRQ_UDC, -++ .flags = IORESOURCE_IRQ, -++ }, -++}; -++ -++static u64 udc_dmamask = ~(u32)0; -++ -++static struct platform_device jz_usb_gdt_device = { -++ .name = "jz-udc", -++ .id = 0, -++ .dev = { -++ .dma_mask = &udc_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_usb_gdt_resources), -++ .resource = jz_usb_gdt_resources, -++}; -++ -++/** MMC/SD controller **/ -++static struct resource jz_mmc_resources[] = { -++ [0] = { -++ .start = CPHYSADDR(MSC_BASE), -++ .end = CPHYSADDR(MSC_BASE) + 0x10000 - 1, -++ .flags = IORESOURCE_MEM, -++ }, -++ [1] = { -++ .start = IRQ_MSC0, -++ .end = IRQ_MSC0, -++ .flags = IORESOURCE_IRQ, -++ } -++}; -++ -++static u64 jz_mmc_dmamask = ~(u32)0; -++ -++static struct platform_device jz_mmc_device = { -++ .name = "jz-mmc", -++ .id = 0, -++ .dev = { -++ .dma_mask = &jz_mmc_dmamask, -++ .coherent_dma_mask = 0xffffffff, -++ }, -++ .num_resources = ARRAY_SIZE(jz_mmc_resources), -++ .resource = jz_mmc_resources, -++}; -++ -++/* All */ -++static struct platform_device *jz_platform_devices[] __initdata = { -++// &jz_usb_ohci_device, -++ &jz_lcd_device, -++ &jz_usb_gdt_device, -++ &jz_mmc_device, -++}; -++ -++static int __init jz_platform_init(void) -++{ -++ return platform_add_devices(jz_platform_devices, ARRAY_SIZE(jz_platform_devices)); -++} -++ -++arch_initcall(jz_platform_init); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750d/pm.c linux-2.6.24.7/arch/mips/jz4750d/pm.c -+--- linux-2.6.24.7.old/arch/mips/jz4750d/pm.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750d/pm.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,461 @@ -++/* -++ * linux/arch/mips/jz4750d/common/pm.c -++ * -++ * JZ4750D Power Management Routines -++ * -++ * Copyright (C) 2006 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can distribute it and/or modify it -++ * under the terms of the GNU General Public License (Version 2) as -++ * published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#undef DEBUG -++//#define DEBUG -++#ifdef DEBUG -++#define dprintk(x...) printk(x) -++#else -++#define dprintk(x...) -++#endif -++ -++#define GPIO_PORT_NUM 6 -++ -++/* -++ * __gpio_as_sleep set all pins to pull-disable, and set all pins as input -++ * except sdram and the pins which can be used as CS1_N to CS4_N for chip select. -++ */ -++#define __gpio_as_sleep() \ -++do { \ -++ REG_GPIO_PXFUNC(1) = ~0x03ff7fff; \ -++ REG_GPIO_PXSELC(1) = ~0x03ff7fff; \ -++ REG_GPIO_PXDIRC(1) = ~0x03ff7fff; \ -++ REG_GPIO_PXPES(1) = 0xffffffff; \ -++ REG_GPIO_PXFUNC(2) = ~0x01e00000; \ -++ REG_GPIO_PXSELC(2) = ~0x01e00000; \ -++ REG_GPIO_PXDIRC(2) = ~0x01e00000; \ -++ REG_GPIO_PXPES(2) = 0xffffffff; \ -++ REG_GPIO_PXFUNC(3) = 0xffffffff; \ -++ REG_GPIO_PXSELC(3) = 0xffffffff; \ -++ REG_GPIO_PXDIRC(3) = 0xffffffff; \ -++ REG_GPIO_PXPES(3) = 0xffffffff; \ -++ REG_GPIO_PXFUNC(4) = 0xffffffff; \ -++ REG_GPIO_PXSELC(4) = 0xffffffff; \ -++ REG_GPIO_PXDIRC(4) = 0xffffffff; \ -++ REG_GPIO_PXPES(4) = 0xffffffff; \ -++ REG_GPIO_PXFUNC(5) = 0xffffffff; \ -++ REG_GPIO_PXSELC(5) = 0xffffffff; \ -++ REG_GPIO_PXDIRC(5) = 0xffffffff; \ -++ REG_GPIO_PXPES(5) = 0xffffffff; \ -++} while (0) -++ -++static int jz_pm_do_hibernate(void) -++{ -++ printk("Put CPU into hibernate mode.\n"); -++ -++ /* Mask all interrupts */ -++ REG_INTC_IMSR = 0xffffffff; -++ -++ /* -++ * RTC Wakeup or 1Hz interrupt can be enabled or disabled -++ * through RTC driver's ioctl (linux/driver/char/rtc_jz.c). -++ */ -++ -++ /* Set minimum wakeup_n pin low-level assertion time for wakeup: 100ms */ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_HWFCR = (100 << RTC_HWFCR_BIT); -++ -++ /* Set reset pin low-level assertion time after wakeup: must > 60ms */ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_HRCR = (60 << RTC_HRCR_BIT); /* 60 ms */ -++ -++ /* Scratch pad register to be reserved */ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_HSPR = 0x12345678; -++ -++ /* clear wakeup status register */ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_HWRSR = 0x0; -++ -++ /* Put CPU to power down mode */ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_HCR = RTC_HCR_PD; -++ -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ while(1); -++ -++ /* We can't get here */ -++ return 0; -++} -++ -++/* NOTES: -++ * 1: Pins that are floated (NC) should be set as input and pull-enable. -++ * 2: Pins that are pull-up or pull-down by outside should be set as input -++ * and pull-disable. -++ * 3: Pins that are connected to a chip except sdram and nand flash -++ * should be set as input and pull-disable, too. -++ */ -++static void jz_board_do_sleep(unsigned long *ptr) -++{ -++ unsigned char i; -++ -++ /* Print messages of GPIO registers for debug */ -++ for(i=0;i -++ * -++ * This program is free software; you can distribute it and/or modify it -++ * under the terms of the GNU General Public License (Version 2) as -++ * published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -++ * -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++//#define DEBUG 1 -++#undef DEBUG -++ -++ -++struct proc_dir_entry *proc_jz_root; -++ -++ -++/* -++ * EMC Modules -++ */ -++static int emc_read_proc (char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ -++ len += sprintf (page+len, "SMCR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SMCR0, REG_EMC_SMCR1, REG_EMC_SMCR2, REG_EMC_SMCR3, REG_EMC_SMCR4); -++ len += sprintf (page+len, "SACR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SACR0, REG_EMC_SACR1, REG_EMC_SACR2, REG_EMC_SACR3, REG_EMC_SACR4); -++ len += sprintf (page+len, "DMCR: 0x%08x\n", REG_EMC_DMCR); -++ len += sprintf (page+len, "RTCSR: 0x%04x\n", REG_EMC_RTCSR); -++ len += sprintf (page+len, "RTCOR: 0x%04x\n", REG_EMC_RTCOR); -++ return len; -++} -++ -++/* -++ * Power Manager Module -++ */ -++static int pmc_read_proc (char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ unsigned long lcr = REG_CPM_LCR; -++ unsigned long clkgr = REG_CPM_CLKGR; -++ -++ len += sprintf (page+len, "Low Power Mode : %s\n", -++ ((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_IDLE)) ? -++ "IDLE" : (((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_SLEEP)) ? -++ "SLEEP" : "HIBERNATE")); -++ len += sprintf (page+len, "Doze Mode : %s\n", -++ (lcr & CPM_LCR_DOZE_ON) ? "on" : "off"); -++ if (lcr & CPM_LCR_DOZE_ON) -++ len += sprintf (page+len, " duty : %d\n", (int)((lcr & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT)); -++ len += sprintf (page+len, "IPU : %s\n", -++ (clkgr & CPM_CLKGR_IPU) ? "stopped" : "running"); -++ len += sprintf (page+len, "DMAC : %s\n", -++ (clkgr & CPM_CLKGR_DMAC) ? "stopped" : "running"); -++ len += sprintf (page+len, "UHC : %s\n", -++ (clkgr & CPM_CLKGR_UHC) ? "stopped" : "running"); -++ len += sprintf (page+len, "UDC : %s\n", -++ (clkgr & CPM_CLKGR_UDC) ? "stopped" : "running"); -++ len += sprintf (page+len, "LCD : %s\n", -++ (clkgr & CPM_CLKGR_LCD) ? "stopped" : "running"); -++ len += sprintf (page+len, "CIM : %s\n", -++ (clkgr & CPM_CLKGR_CIM) ? "stopped" : "running"); -++ len += sprintf (page+len, "SADC : %s\n", -++ (clkgr & CPM_CLKGR_SADC) ? "stopped" : "running"); -++ len += sprintf (page+len, "MSC0 : %s\n", -++ (clkgr & CPM_CLKGR_MSC0) ? "stopped" : "running"); -++ len += sprintf (page+len, "MSC1 : %s\n", -++ (clkgr & CPM_CLKGR_MSC1) ? "stopped" : "running"); -++ len += sprintf (page+len, "AIC1 : %s\n", -++ (clkgr & CPM_CLKGR_AIC1) ? "stopped" : "running"); -++ len += sprintf (page+len, "AIC2 : %s\n", -++ (clkgr & CPM_CLKGR_AIC2) ? "stopped" : "running"); -++ len += sprintf (page+len, "SSI0 : %s\n", -++ (clkgr & CPM_CLKGR_SSI0) ? "stopped" : "running"); -++ len += sprintf (page+len, "SSI1 : %s\n", -++ (clkgr & CPM_CLKGR_SSI1) ? "stopped" : "running"); -++ len += sprintf (page+len, "I2C : %s\n", -++ (clkgr & CPM_CLKGR_I2C) ? "stopped" : "running"); -++ len += sprintf (page+len, "RTC : %s\n", -++ (clkgr & CPM_CLKGR_RTC) ? "stopped" : "running"); -++ len += sprintf (page+len, "TCU : %s\n", -++ (clkgr & CPM_CLKGR_TCU) ? "stopped" : "running"); -++ len += sprintf (page+len, "UART1 : %s\n", -++ (clkgr & CPM_CLKGR_UART1) ? "stopped" : "running"); -++ len += sprintf (page+len, "UART0 : %s\n", -++ (clkgr & CPM_CLKGR_UART0) ? "stopped" : "running"); -++ return len; -++} -++ -++static int pmc_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -++{ -++ REG_CPM_CLKGR = simple_strtoul(buffer, 0, 16); -++ return count; -++} -++ -++/* -++ * Clock Generation Module -++ */ -++#define TO_MHZ(x) (x/1000000),(x%1000000)/10000 -++#define TO_KHZ(x) (x/1000),(x%1000)/10 -++ -++static int cgm_read_proc (char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ unsigned int cppcr = REG_CPM_CPPCR; /* PLL Control Register */ -++ unsigned int cpccr = REG_CPM_CPCCR; /* Clock Control Register */ -++ unsigned int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ unsigned int od[4] = {1, 2, 2, 4}; -++ -++ len += sprintf (page+len, "CPPCR : 0x%08x\n", cppcr); -++ len += sprintf (page+len, "CPCCR : 0x%08x\n", cpccr); -++ len += sprintf (page+len, "PLL : %s\n", -++ (cppcr & CPM_CPPCR_PLLEN) ? "ON" : "OFF"); -++ len += sprintf (page+len, "m:n:o : %d:%d:%d\n", -++ __cpm_get_pllm() + 2, -++ __cpm_get_plln() + 2, -++ od[__cpm_get_pllod()] -++ ); -++ len += sprintf (page+len, "C:H:M:P : %d:%d:%d:%d\n", -++ div[__cpm_get_cdiv()], -++ div[__cpm_get_hdiv()], -++ div[__cpm_get_mdiv()], -++ div[__cpm_get_pdiv()] -++ ); -++ len += sprintf (page+len, "PLL Freq : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pllout())); -++ len += sprintf (page+len, "CCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_cclk())); -++ len += sprintf (page+len, "HCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_hclk())); -++ len += sprintf (page+len, "MCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mclk())); -++ len += sprintf (page+len, "PCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pclk())); -++ len += sprintf (page+len, "LCDCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_lcdclk())); -++ len += sprintf (page+len, "PIXCLK : %3d.%02d KHz\n", TO_KHZ(__cpm_get_pixclk())); -++ len += sprintf (page+len, "I2SCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_i2sclk())); -++ len += sprintf (page+len, "USBCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_usbclk())); -++ len += sprintf (page+len, "MSC0CLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mscclk(0))); -++ len += sprintf (page+len, "MSC1CLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mscclk(1))); -++ len += sprintf (page+len, "EXTALCLK0 : %3d.%02d MHz\n", TO_MHZ(__cpm_get_extalclk0())); -++ len += sprintf (page+len, "EXTALCLK(by CPM): %3d.%02d MHz\n", TO_MHZ(__cpm_get_extalclk())); -++ len += sprintf (page+len, "RTCCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_rtcclk())); -++ -++ return len; -++} -++ -++static int cgm_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -++{ -++ REG_CPM_CPCCR = simple_strtoul(buffer, 0, 16); -++ return count; -++} -++ -++ -++/* USAGE: -++ * echo n > /proc/jz/ipu // n = [1,...,9], alloc mem, 2^n pages. -++ * echo FF > /proc/jz/ipu // 255, free all buffer -++ * echo xxxx > /proc/jz/ipu // free buffer which addr is xxxx -++ * echo llll > /proc/jz/ipu // add_wired_entry(l,l,l,l) -++ * echo 0 > /proc/jz/ipu // debug, print ipu_buf -++ * od -X /proc/jz/ipu // read mem addr -++ */ -++ -++typedef struct _ipu_buf { -++ unsigned int addr; /* phys addr */ -++ unsigned int page_shift; -++} ipu_buf_t; -++ -++#define IPU_BUF_MAX 4 /* 4 buffers */ -++ -++static struct _ipu_buf ipu_buf[IPU_BUF_MAX]; -++static int ipu_buf_cnt = 0; -++static unsigned char g_asid=0; -++ -++extern void local_flush_tlb_all(void); -++ -++/* CP0 hazard avoidance. */ -++#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ -++ "nop; nop; nop; nop; nop; nop;\n\t" \ -++ ".set reorder\n\t") -++void show_tlb(void) -++{ -++#define ASID_MASK 0xFF -++ -++ unsigned long flags; -++ unsigned int old_ctx; -++ unsigned int entry; -++ unsigned int entrylo0, entrylo1, entryhi; -++ unsigned int pagemask; -++ -++ local_irq_save(flags); -++ -++ /* Save old context */ -++ old_ctx = (read_c0_entryhi() & 0xff); -++ -++ printk("TLB content:\n"); -++ entry = 0; -++ while(entry < 32) { -++ write_c0_index(entry); -++ BARRIER; -++ tlb_read(); -++ BARRIER; -++ entryhi = read_c0_entryhi(); -++ entrylo0 = read_c0_entrylo0(); -++ entrylo1 = read_c0_entrylo1(); -++ pagemask = read_c0_pagemask(); -++ printk("%02d: ASID=%02d%s VA=0x%08x ", entry, entryhi & ASID_MASK, (entrylo0 & entrylo1 & 1) ? "(G)" : " ", entryhi & ~ASID_MASK); -++ printk("PA0=0x%08x C0=%x %s%s%s\n", (entrylo0>>6)<<12, (entrylo0>>3) & 7, (entrylo0 & 4) ? "Dirty " : "", (entrylo0 & 2) ? "Valid " : "Invalid ", (entrylo0 & 1) ? "Global" : ""); -++ printk("\t\t\t PA1=0x%08x C1=%x %s%s%s\n", (entrylo1>>6)<<12, (entrylo1>>3) & 7, (entrylo1 & 4) ? "Dirty " : "", (entrylo1 & 2) ? "Valid " : "Invalid ", (entrylo1 & 1) ? "Global" : ""); -++ -++ printk("\t\tpagemask=0x%08x", pagemask); -++ printk("\tentryhi=0x%08x\n", entryhi); -++ printk("\t\tentrylo0=0x%08x", entrylo0); -++ printk("\tentrylo1=0x%08x\n", entrylo1); -++ -++ entry++; -++ } -++ BARRIER; -++ write_c0_entryhi(old_ctx); -++ -++ local_irq_restore(flags); -++} -++ -++static void ipu_add_wired_entry(unsigned long pid, -++ unsigned long entrylo0, unsigned long entrylo1, -++ unsigned long entryhi, unsigned long pagemask) -++{ -++ unsigned long flags; -++ unsigned long wired; -++ unsigned long old_pagemask; -++ unsigned long old_ctx; -++ struct task_struct *g, *p; -++ -++ /* We will lock an 4MB page size entry to map the 4MB reserved IPU memory */ -++ wired = read_c0_wired(); -++ if (wired) return; -++ -++ do_each_thread(g, p) { -++ if (p->pid == pid ) -++ g_asid = p->mm->context[0]; -++ } while_each_thread(g, p); -++ -++ -++ local_irq_save(flags); -++ -++ entrylo0 = entrylo0 >> 6; /* PFN */ -++ entrylo0 |= 0x6 | (0 << 3); /* Write-through cacheable, dirty, valid */ -++ -++ /* Save old context and create impossible VPN2 value */ -++ old_ctx = read_c0_entryhi() & 0xff; -++ old_pagemask = read_c0_pagemask(); -++ wired = read_c0_wired(); -++ write_c0_wired(wired + 1); -++ write_c0_index(wired); -++ BARRIER; -++ entryhi &= ~0xff; /* new add, 20070906 */ -++ entryhi |= g_asid; /* new add, 20070906 */ -++// entryhi |= old_ctx; /* new add, 20070906 */ -++ write_c0_pagemask(pagemask); -++ write_c0_entryhi(entryhi); -++ write_c0_entrylo0(entrylo0); -++ write_c0_entrylo1(entrylo1); -++ BARRIER; -++ tlb_write_indexed(); -++ BARRIER; -++ -++ write_c0_entryhi(old_ctx); -++ BARRIER; -++ write_c0_pagemask(old_pagemask); -++ local_flush_tlb_all(); -++ local_irq_restore(flags); -++#if defined(DEBUG) -++ printk("\nold_ctx=%03d\n", old_ctx); -++ -++ show_tlb(); -++#endif -++} -++ -++static void ipu_del_wired_entry( void ) -++{ -++ unsigned long flags; -++ unsigned long wired; -++ -++ local_irq_save(flags); -++ wired = read_c0_wired(); -++ if ( wired > 0 ) { -++ write_c0_wired(wired - 1); -++ } -++ local_irq_restore(flags); -++} -++ -++static inline void ipu_buf_get( unsigned int page_shift ) -++{ -++ unsigned char * virt_addr; -++ int i; -++ for ( i=0; i< IPU_BUF_MAX; ++i ) { -++ if ( ipu_buf[i].addr == 0 ) { -++ break; -++ } -++ } -++ -++ if ( (ipu_buf_cnt = i) == IPU_BUF_MAX ) { -++ printk("Error, no free ipu buffer.\n"); -++ return ; -++ } -++ -++ virt_addr = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); -++ -++ if ( virt_addr ) { -++ ipu_buf[ipu_buf_cnt].addr = (unsigned int)virt_to_phys((void *)virt_addr); -++ ipu_buf[ipu_buf_cnt].page_shift = page_shift; -++ -++ for (i = 0; i < (1<= IPU_BUF_MAX ) { /* failed alloc mem, rturn 0 */ -++ printk("no free buffer.\n"); -++ *pint = 0; -++ } -++ else -++ *pint = (unsigned int )ipu_buf[ipu_buf_cnt].addr; /* phys addr */ -++ len += sizeof(unsigned int); -++ -++#if defined(DEBUG) -++ show_tlb(); -++#endif -++ return len; -++ -++} -++ -++static int ipu_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -++{ -++ unsigned int val ; -++ int cnt,i; -++ char buf[12]; -++ unsigned long pid, entrylo0, entrylo1, entryhi, pagemask; -++#if defined(DEBUG) -++ printk("ipu write count=%u\n", count); -++#endif -++ if (count == (8*5+1)) { -++ for (i=0;i<12;i++) buf[i]=0; -++ strncpy(buf, buffer+8*0, 8); -++ pid = simple_strtoul(buf, 0, 16); -++ for (i=0;i<12;i++) buf[i]=0; -++ strncpy(buf, buffer+8*1, 8); -++ entrylo0 = simple_strtoul(buf, 0, 16); -++ for (i=0;i<12;i++) buf[i]=0; -++ strncpy(buf, buffer+8*2, 8); -++ entrylo1 = simple_strtoul(buf, 0, 16); -++ for (i=0;i<12;i++) buf[i]=0; -++ strncpy(buf, buffer+8*3, 8); -++ entryhi = simple_strtoul(buf, 0, 16); -++ for (i=0;i<12;i++) buf[i]=0; -++ strncpy(buf, buffer+8*4, 8); -++ pagemask = simple_strtoul(buf, 0, 16); -++ -++#if defined(DEBUG) -++ printk("pid=0x%08x, entrylo0=0x%08x, entrylo1=0x%08x, entryhi=0x%08x, pagemask=0x%08x\n", -++ pid, entrylo0, entrylo1, entryhi, pagemask); -++#endif -++ ipu_add_wired_entry( pid, entrylo0, entrylo1, entryhi, pagemask); -++ return 41; -++ } -++ else if ( count <= 8+1 ) { -++ for (i=0;i<12;i++) buf[i]=0; -++ strncpy(buf, buffer, 8); -++ val = simple_strtoul(buf, 0, 16); -++ } else if (count == 44) { -++ for (i = 0; i < 12; i++) -++ buf[i] = 0; -++ strncpy(buf, buffer, 10); -++ pid = simple_strtoul(buf, 0, 16); -++ for (i = 0; i < 12; i++) -++ buf[i] = 0; -++ strncpy(buf, buffer + 11, 10); -++ entryhi = simple_strtoul(buf, 0, 16);//vaddr -++ for (i = 0; i < 12; i++) -++ buf[i] = 0; -++ strncpy(buf, buffer + 22, 10); -++ entrylo0 = simple_strtoul(buf, 0, 16);//paddr -++ for (i = 0; i < 12; i++) -++ buf[i] = 0; -++ strncpy(buf, buffer + 33, 10); -++ pagemask = simple_strtoul(buf, 0, 16); -++ pagemask = 0x3ff << 13; /* Fixed to 4MB page size */ -++ ipu_add_wired_entry(pid, entrylo0, 0, entryhi, pagemask); -++ return 44; -++ } else { -++ printk("ipu write count error, count=%d\n.", (unsigned int)count); -++ return -1; -++ } -++ -++ /* val: 1-9, page_shift, val>= 10: ipu_buf.addr */ -++ if ( val == 0 ) { /* debug, print ipu_buf info */ -++ for ( cnt=0; cnt /proc/jz/imem // n = [0,...,10], allocate memory, 2^n pages -++ * echo xxxxxxxx > /proc/jz/imem // free buffer which addr is xxxxxxxx -++ * echo FF > /proc/jz/ipu // FF, free all buffers -++ * od -X /proc/jz/imem // return the allocated buffer address and the max order of free buffer -++ */ -++ -++//#define DEBUG_IMEM 1 -++ -++#define IMEM_MAX_ORDER 10 /* max 2^10 * 4096 = 4MB */ -++ -++static unsigned int jz_imem_base; /* physical base address of ipu memory */ -++ -++static unsigned int allocated_phys_addr = 0; -++ -++/* -++ * Allocated buffer list -++ */ -++typedef struct imem_list { -++ unsigned int phys_start; /* physical start addr */ -++ unsigned int phys_end; /* physical end addr */ -++ struct imem_list *next; -++} imem_list_t; -++ -++static struct imem_list *imem_list_head = NULL; /* up sorted by phys_start */ -++ -++#ifdef DEBUG_IMEM -++static void dump_imem_list(void) -++{ -++ struct imem_list *imem; -++ -++ printk("*** dump_imem_list 0x%x ***\n", (u32)imem_list_head); -++ imem = imem_list_head; -++ while (imem) { -++ printk("imem=0x%x phys_start=0x%x phys_end=0x%x next=0x%x\n", (u32)imem, imem->phys_start, imem->phys_end, (u32)imem->next); -++ imem = imem->next; -++ } -++} -++#endif -++ -++/* allocate 2^order pages inside the 4MB memory */ -++static int imem_alloc(unsigned int order) -++{ -++ int alloc_ok = 0; -++ unsigned int start, end; -++ unsigned int size = (1 << order) * PAGE_SIZE; -++ struct imem_list *imem, *imemn, *imemp; -++ -++ allocated_phys_addr = 0; -++ -++ start = jz_imem_base; -++ end = start + (1 << IMEM_MAX_ORDER) * PAGE_SIZE; -++ -++ imem = imem_list_head; -++ while (imem) { -++ if ((imem->phys_start - start) >= size) { -++ /* we got a valid address range */ -++ alloc_ok = 1; -++ break; -++ } -++ -++ start = imem->phys_end + 1; -++ imem = imem->next; -++ } -++ -++ if (!alloc_ok) { -++ if ((end - start) >= size) -++ alloc_ok = 1; -++ } -++ -++ if (alloc_ok) { -++ end = start + size - 1; -++ allocated_phys_addr = start; -++ -++ /* add to imem_list, up sorted by phys_start */ -++ imemn = kmalloc(sizeof(struct imem_list), GFP_KERNEL); -++ if (!imemn) { -++ return -ENOMEM; -++ } -++ imemn->phys_start = start; -++ imemn->phys_end = end; -++ imemn->next = NULL; -++ -++ if (!imem_list_head) -++ imem_list_head = imemn; -++ else { -++ imem = imemp = imem_list_head; -++ while (imem) { -++ if (start < imem->phys_start) { -++ break; -++ } -++ -++ imemp = imem; -++ imem = imem->next; -++ } -++ -++ if (imem == imem_list_head) { -++ imem_list_head = imemn; -++ imemn->next = imem; -++ } -++ else { -++ imemn->next = imemp->next; -++ imemp->next = imemn; -++ } -++ } -++ } -++ -++#ifdef DEBUG_IMEM -++ dump_imem_list(); -++#endif -++ return 0; -++} -++ -++static void imem_free(unsigned int phys_addr) -++{ -++ struct imem_list *imem, *imemp; -++ -++ imem = imemp = imem_list_head; -++ while (imem) { -++ if (phys_addr == imem->phys_start) { -++ if (imem == imem_list_head) { -++ imem_list_head = imem->next; -++ } -++ else { -++ imemp->next = imem->next; -++ } -++ -++ kfree(imem); -++ break; -++ } -++ -++ imemp = imem; -++ imem = imem->next; -++ } -++ -++#ifdef DEBUG_IMEM -++ dump_imem_list(); -++#endif -++} -++ -++static void imem_free_all(void) -++{ -++ struct imem_list *imem; -++ -++ imem = imem_list_head; -++ while (imem) { -++ kfree(imem); -++ imem = imem->next; -++ } -++ -++ imem_list_head = NULL; -++ -++ allocated_phys_addr = 0; -++ -++#ifdef DEBUG_IMEM -++ dump_imem_list(); -++#endif -++} -++ -++/* -++ * Return the allocated buffer address and the max order of free buffer -++ */ -++static int imem_read_proc(char *page, char **start, off_t off, -++ int count, int *eof, void *data) -++{ -++ int len = 0; -++ unsigned int start_addr, end_addr, max_order, max_size; -++ struct imem_list *imem; -++ -++ unsigned int *tmp = (unsigned int *)(page + len); -++ -++ start_addr = jz_imem_base; -++ end_addr = start_addr + (1 << IMEM_MAX_ORDER) * PAGE_SIZE; -++ -++ if (!imem_list_head) -++ max_size = end_addr - start_addr; -++ else { -++ max_size = 0; -++ imem = imem_list_head; -++ while (imem) { -++ if (max_size < (imem->phys_start - start_addr)) -++ max_size = imem->phys_start - start_addr; -++ -++ start_addr = imem->phys_end + 1; -++ imem = imem->next; -++ } -++ -++ if (max_size < (end_addr - start_addr)) -++ max_size = end_addr - start_addr; -++ } -++ -++ if (max_size > 0) { -++ max_order = get_order(max_size); -++ if (((1 << max_order) * PAGE_SIZE) > max_size) -++ max_order--; -++ } -++ else { -++ max_order = 0xffffffff; /* No any free buffer */ -++ } -++ -++ *tmp++ = allocated_phys_addr; /* address allocated by 'echo n > /proc/jz/imem' */ -++ *tmp = max_order; /* max order of current free buffers */ -++ -++ len += 2 * sizeof(unsigned int); -++ -++ return len; -++} -++ -++static int imem_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -++{ -++ unsigned int val; -++ -++ val = simple_strtoul(buffer, 0, 16); -++ -++ if (val == 0xff) { -++ /* free all memory */ -++ imem_free_all(); -++ } -++ else if ((val >= 0) && (val <= IMEM_MAX_ORDER)) { -++ /* allocate 2^val pages */ -++ imem_alloc(val); -++ } -++ else { -++ /* free buffer which phys_addr is val */ -++ imem_free(val); -++ } -++ -++ return count; -++} -++ -++/* -++ * /proc/jz/xxx entry -++ * -++ */ -++static int __init jz_proc_init(void) -++{ -++ struct proc_dir_entry *res; -++ unsigned int virt_addr, i; -++ -++ proc_jz_root = proc_mkdir("jz", 0); -++ -++ /* External Memory Controller */ -++ res = create_proc_entry("emc", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = emc_read_proc; -++ res->write_proc = NULL; -++ res->data = NULL; -++ } -++ -++ /* Power Management Controller */ -++ res = create_proc_entry("pmc", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = pmc_read_proc; -++ res->write_proc = pmc_write_proc; -++ res->data = NULL; -++ } -++ -++ /* Clock Generation Module */ -++ res = create_proc_entry("cgm", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = cgm_read_proc; -++ res->write_proc = cgm_write_proc; -++ res->data = NULL; -++ } -++ -++ /* Image process unit */ -++ res = create_proc_entry("ipu", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = ipu_read_proc; -++ res->write_proc = ipu_write_proc; -++ res->data = NULL; -++ } -++ -++ /* udc hotplug */ -++ res = create_proc_entry("udc", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = udc_read_proc; -++ res->write_proc = NULL; -++ res->data = NULL; -++ } -++ -++ /* mmc hotplug */ -++ res = create_proc_entry("mmc", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = mmc_read_proc; -++ res->write_proc = NULL; -++ res->data = NULL; -++ } -++ -++ /* -++ * Reserve a 4MB memory for IPU on JZ4750D. -++ */ -++ jz_imem_base = (unsigned int)__get_free_pages(GFP_KERNEL, IMEM_MAX_ORDER); -++ if (jz_imem_base) { -++ /* imem (IPU memory management) */ -++ res = create_proc_entry("imem", 0644, proc_jz_root); -++ if (res) { -++ res->read_proc = imem_read_proc; -++ res->write_proc = imem_write_proc; -++ res->data = NULL; -++ } -++ -++ /* Set page reserved */ -++ virt_addr = jz_imem_base; -++ for (i = 0; i < (1 << IMEM_MAX_ORDER); i++) { -++ SetPageReserved(virt_to_page((void *)virt_addr)); -++ virt_addr += PAGE_SIZE; -++ } -++ -++ /* Convert to physical address */ -++ jz_imem_base = virt_to_phys((void *)jz_imem_base); -++ -++ printk("Total %dMB memory at 0x%x was reserved for IPU\n", -++ (unsigned int)((1 << IMEM_MAX_ORDER) * PAGE_SIZE)/1000000, jz_imem_base); -++ } -++ -++ return 0; -++} -++ -++__initcall(jz_proc_init); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750d/prom.c linux-2.6.24.7/arch/mips/jz4750d/prom.c -+--- linux-2.6.24.7.old/arch/mips/jz4750d/prom.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750d/prom.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,198 @@ -++/* -++ * -++ * BRIEF MODULE DESCRIPTION -++ * PROM library initialisation code, supports YAMON and U-Boot. -++ * -++ * Copyright 2000, 2001, 2006 MontaVista Software Inc. -++ * Author: MontaVista Software, Inc. -++ * ppopov@mvista.com or source@mvista.com -++ * -++ * This file was derived from Carsten Langgaard's -++ * arch/mips/mips-boards/xx files. -++ * -++ * Carsten Langgaard, carstenl@mips.com -++ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ * -++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++/* #define DEBUG_CMDLINE */ -++ -++int prom_argc; -++char **prom_argv, **prom_envp; -++ -++char * prom_getcmdline(void) -++{ -++ return &(arcs_cmdline[0]); -++} -++ -++void prom_init_cmdline(void) -++{ -++ char *cp; -++ int actr; -++ -++ actr = 1; /* Always ignore argv[0] */ -++ -++ cp = &(arcs_cmdline[0]); -++ while(actr < prom_argc) { -++ strcpy(cp, prom_argv[actr]); -++ cp += strlen(prom_argv[actr]); -++ *cp++ = ' '; -++ actr++; -++ } -++ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ -++ --cp; -++ if (prom_argc > 1) -++ *cp = '\0'; -++ -++} -++ -++ -++char *prom_getenv(char *envname) -++{ -++#if 0 -++ /* -++ * Return a pointer to the given environment variable. -++ * YAMON uses "name", "value" pairs, while U-Boot uses "name=value". -++ */ -++ -++ char **env = prom_envp; -++ int i = strlen(envname); -++ int yamon = (*env && strchr(*env, '=') == NULL); -++ -++ while (*env) { -++ if (yamon) { -++ if (strcmp(envname, *env++) == 0) -++ return *env; -++ } else { -++ if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=') -++ return *env + i + 1; -++ } -++ env++; -++ } -++#endif -++ return NULL; -++} -++ -++inline unsigned char str2hexnum(unsigned char c) -++{ -++ if(c >= '0' && c <= '9') -++ return c - '0'; -++ if(c >= 'a' && c <= 'f') -++ return c - 'a' + 10; -++ if(c >= 'A' && c <= 'F') -++ return c - 'A' + 10; -++ return 0; /* foo */ -++} -++ -++inline void str2eaddr(unsigned char *ea, unsigned char *str) -++{ -++ int i; -++ -++ for(i = 0; i < 6; i++) { -++ unsigned char num; -++ -++ if((*str == '.') || (*str == ':')) -++ str++; -++ num = str2hexnum(*str++) << 4; -++ num |= (str2hexnum(*str++)); -++ ea[i] = num; -++ } -++} -++ -++int get_ethernet_addr(char *ethernet_addr) -++{ -++ char *ethaddr_str; -++ -++ ethaddr_str = prom_getenv("ethaddr"); -++ if (!ethaddr_str) { -++ printk("ethaddr not set in boot prom\n"); -++ return -1; -++ } -++ str2eaddr(ethernet_addr, ethaddr_str); -++ -++#if 0 -++ { -++ int i; -++ -++ printk("get_ethernet_addr: "); -++ for (i=0; i<5; i++) -++ printk("%02x:", (unsigned char)*(ethernet_addr+i)); -++ printk("%02x\n", *(ethernet_addr+i)); -++ } -++#endif -++ -++ return 0; -++} -++ -++void __init prom_free_prom_memory(void) -++{ -++} -++ -++void __init prom_init(void) -++{ -++ unsigned char *memsize_str; -++ unsigned long memsize; -++ -++ prom_argc = (int) fw_arg0; -++ prom_argv = (char **) fw_arg1; -++ prom_envp = (char **) fw_arg2; -++ -++ mips_machtype = MACH_INGENIC_JZ4750D; -++ -++ prom_init_cmdline(); -++ memsize_str = prom_getenv("memsize"); -++ if (!memsize_str) { -++ memsize = 0x04000000; -++ } else { -++ memsize = simple_strtol(memsize_str, NULL, 0); -++ } -++ add_memory_region(0, memsize, BOOT_MEM_RAM); -++} -++ -++/* used by early printk */ -++void prom_putchar(char c) -++{ -++ volatile u8 *uart_lsr = (volatile u8 *)(UART0_BASE + OFF_LSR); -++ volatile u8 *uart_tdr = (volatile u8 *)(UART0_BASE + OFF_TDR); -++ -++ /* Wait for fifo to shift out some bytes */ -++ while ( !((*uart_lsr & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60) ); -++ -++ *uart_tdr = (u8)c; -++} -++ -++const char *get_system_type(void) -++{ -++ return "JZ4750D"; -++} -++ -++EXPORT_SYMBOL(prom_getcmdline); -++EXPORT_SYMBOL(get_ethernet_addr); -++EXPORT_SYMBOL(str2eaddr); -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750d/reset.c linux-2.6.24.7/arch/mips/jz4750d/reset.c -+--- linux-2.6.24.7.old/arch/mips/jz4750d/reset.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750d/reset.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,46 @@ -++/* -++ * linux/arch/mips/jz4750/reset.c -++ * -++ * JZ4750 reset routines. -++ * -++ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++void jz_restart(char *command) -++{ -++ printk("Restarting after 4 ms\n"); -++ REG_WDT_TCSR = WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN; -++ REG_WDT_TCNT = 0; -++ REG_WDT_TDR = JZ_EXTAL/1000; /* reset after 4ms */ -++ REG_TCU_TSCR = TCU_TSCR_WDTSC; /* enable wdt clock */ -++ REG_WDT_TCER = WDT_TCER_TCEN; /* wdt start */ -++ while (1); -++} -++ -++void jz_halt(void) -++{ -++ printk(KERN_NOTICE "\n** You can safely turn off the power\n"); -++ -++ while (1) -++ __asm__(".set\tmips3\n\t" -++ "wait\n\t" -++ ".set\tmips0"); -++} -++ -++void jz_power_off(void) -++{ -++ jz_halt(); -++} -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750d/setup.c linux-2.6.24.7/arch/mips/jz4750d/setup.c -+--- linux-2.6.24.7.old/arch/mips/jz4750d/setup.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750d/setup.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,199 @@ -++/* -++ * linux/arch/mips/jz4750d/common/setup.c -++ * -++ * JZ4750D common setup routines. -++ * -++ * Copyright (C) 2006 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can distribute it and/or modify it -++ * under the terms of the GNU General Public License (Version 2) as -++ * published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -++ * -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#ifdef CONFIG_PC_KEYB -++#include -++#endif -++ -++jz_clocks_t jz_clocks; -++ -++extern char * __init prom_getcmdline(void); -++extern void __init jz_board_setup(void); -++extern void jz_restart(char *); -++extern void jz_halt(void); -++extern void jz_power_off(void); -++extern void jz_time_init(void); -++ -++static void __init sysclocks_setup(void) -++{ -++#ifndef CONFIG_MIPS_JZ_EMURUS /* FPGA */ -++ jz_clocks.cclk = __cpm_get_cclk(); -++ jz_clocks.hclk = __cpm_get_hclk(); -++ jz_clocks.pclk = __cpm_get_pclk(); -++ jz_clocks.mclk = __cpm_get_mclk(); -++ jz_clocks.lcdclk = __cpm_get_lcdclk(); -++ jz_clocks.pixclk = __cpm_get_pixclk(); -++ jz_clocks.i2sclk = __cpm_get_i2sclk(); -++ jz_clocks.usbclk = __cpm_get_usbclk(); -++ jz_clocks.mscclk = __cpm_get_mscclk(0); -++ jz_clocks.extalclk = __cpm_get_extalclk(); -++ jz_clocks.rtcclk = __cpm_get_rtcclk(); -++#else -++ -++#define FPGACLK 8000000 -++ -++ jz_clocks.cclk = FPGACLK; -++ jz_clocks.hclk = FPGACLK; -++ jz_clocks.pclk = FPGACLK; -++ jz_clocks.mclk = FPGACLK; -++ jz_clocks.lcdclk = FPGACLK; -++ jz_clocks.pixclk = FPGACLK; -++ jz_clocks.i2sclk = FPGACLK; -++ jz_clocks.usbclk = FPGACLK; -++ jz_clocks.mscclk = FPGACLK; -++ jz_clocks.extalclk = FPGACLK; -++ jz_clocks.rtcclk = FPGACLK; -++#endif -++ -++ printk("CPU clock: %dMHz, System clock: %dMHz, Peripheral clock: %dMHz, Memory clock: %dMHz\n", -++ (jz_clocks.cclk + 500000) / 1000000, -++ (jz_clocks.hclk + 500000) / 1000000, -++ (jz_clocks.pclk + 500000) / 1000000, -++ (jz_clocks.mclk + 500000) / 1000000); -++} -++ -++static void __init soc_cpm_setup(void) -++{ -++ /* Start all module clocks -++ */ -++ __cpm_start_all(); -++ -++ /* Enable CKO to external memory */ -++ __cpm_enable_cko(); -++ -++ /* CPU enters IDLE mode when executing 'wait' instruction */ -++ __cpm_idle_mode(); -++ -++ /* Setup system clocks */ -++ sysclocks_setup(); -++} -++ -++static void __init soc_harb_setup(void) -++{ -++// __harb_set_priority(0x00); /* CIM>LCD>DMA>ETH>PCI>USB>CBB */ -++// __harb_set_priority(0x03); /* LCD>CIM>DMA>ETH>PCI>USB>CBB */ -++// __harb_set_priority(0x0a); /* ETH>LCD>CIM>DMA>PCI>USB>CBB */ -++} -++ -++static void __init soc_emc_setup(void) -++{ -++} -++ -++static void __init soc_dmac_setup(void) -++{ -++ __dmac_enable_module(0); -++ __dmac_enable_module(1); -++} -++ -++static void __init jz_soc_setup(void) -++{ -++ soc_cpm_setup(); -++ soc_harb_setup(); -++ soc_emc_setup(); -++ soc_dmac_setup(); -++} -++ -++static void __init jz_serial_setup(void) -++{ -++#ifdef CONFIG_SERIAL_8250 -++ struct uart_port s; -++ REG8(UART0_FCR) |= UARTFCR_UUE; /* enable UART module */ -++ memset(&s, 0, sizeof(s)); -++ s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; -++ s.iotype = SERIAL_IO_MEM; -++ s.regshift = 2; -++ s.uartclk = jz_clocks.extalclk ; -++ -++ s.line = 0; -++ s.membase = (u8 *)UART0_BASE; -++ s.irq = IRQ_UART0; -++ if (early_serial_setup(&s) != 0) { -++ printk(KERN_ERR "Serial ttyS0 setup failed!\n"); -++ } -++ -++ s.line = 1; -++ s.membase = (u8 *)UART1_BASE; -++ s.irq = IRQ_UART1; -++ if (early_serial_setup(&s) != 0) { -++ printk(KERN_ERR "Serial ttyS1 setup failed!\n"); -++ } -++ -++ s.line = 2; -++ s.membase = (u8 *)UART2_BASE; -++ s.irq = IRQ_UART2; -++ -++ if (early_serial_setup(&s) != 0) { -++ printk(KERN_ERR "Serial ttyS2 setup failed!\n"); -++ } -++/* -++ s.line = 3; -++ s.membase = (u8 *)UART3_BASE; -++ s.irq = IRQ_UART3; -++ if (early_serial_setup(&s) != 0) { -++ printk(KERN_ERR "Serial ttyS3 setup failed!\n"); -++ } -++*/ -++#endif -++} -++ -++void __init plat_mem_setup(void) -++{ -++ char *argptr; -++ -++ argptr = prom_getcmdline(); -++ -++ /* IO/MEM resources. Which will be the addtion value in `inX' and -++ * `outX' macros defined in asm/io.h */ -++ set_io_port_base(0); -++ ioport_resource.start = 0x00000000; -++ ioport_resource.end = 0xffffffff; -++ iomem_resource.start = 0x00000000; -++ iomem_resource.end = 0xffffffff; -++ -++ _machine_restart = jz_restart; -++ _machine_halt = jz_halt; -++ pm_power_off = jz_power_off; -++ -++ jz_soc_setup(); -++ jz_serial_setup(); -++ jz_board_setup(); -++} -++ -+diff -urN linux-2.6.24.7.old/arch/mips/jz4750d/time.c linux-2.6.24.7/arch/mips/jz4750d/time.c -+--- linux-2.6.24.7.old/arch/mips/jz4750d/time.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/arch/mips/jz4750d/time.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,156 @@ -++/* -++ * linux/arch/mips/jz4750d/time.c -++ * -++ * Setting up the clock on the JZ4750D boards. -++ * -++ * Copyright (C) 2008 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can distribute it and/or modify it -++ * under the terms of the GNU General Public License (Version 2) as -++ * published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -++ * -++ */ -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++/* This is for machines which generate the exact clock. */ -++ -++#define JZ_TIMER_IRQ IRQ_TCU0 -++ -++#define JZ_TIMER_CLOCK (JZ_EXTAL>>4) /* Jz timer clock frequency */ -++ -++static struct clocksource clocksource_jz; /* Jz clock source */ -++static struct clock_event_device jz_clockevent_device; /* Jz clock event */ -++ -++void (*jz_timer_callback)(void); -++ -++static irqreturn_t jz_timer_interrupt(int irq, void *dev_id) -++{ -++ struct clock_event_device *cd = dev_id; -++ -++ REG_TCU_TFCR = TCU_TFCR_OSTFCL; /* ACK timer */ -++ -++ if (jz_timer_callback) -++ jz_timer_callback(); -++ -++ cd->event_handler(cd); -++ -++ return IRQ_HANDLED; -++} -++ -++static struct irqaction jz_irqaction = { -++ .handler = jz_timer_interrupt, -++ .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, -++ .name = "jz-timerirq", -++}; -++ -++ -++cycle_t jz_get_cycles(void) -++{ -++ /* convert jiffes to jz timer cycles */ -++ return (cycle_t)( jiffies*((JZ_TIMER_CLOCK)/HZ) + REG_TCU_OSTCNT); -++} -++ -++static struct clocksource clocksource_jz = { -++ .name = "jz_clocksource", -++ .rating = 300, -++ .read = jz_get_cycles, -++ .mask = 0xFFFFFFFF, -++ .shift = 10, -++ .flags = CLOCK_SOURCE_WATCHDOG, -++}; -++ -++static int __init jz_clocksource_init(void) -++{ -++ clocksource_jz.mult = clocksource_hz2mult(JZ_TIMER_CLOCK, clocksource_jz.shift); -++ clocksource_register(&clocksource_jz); -++ return 0; -++} -++ -++static int jz_set_next_event(unsigned long evt, -++ struct clock_event_device *unused) -++{ -++ return 0; -++} -++ -++static void jz_set_mode(enum clock_event_mode mode, -++ struct clock_event_device *evt) -++{ -++ switch (mode) { -++ case CLOCK_EVT_MODE_PERIODIC: -++ break; -++ case CLOCK_EVT_MODE_ONESHOT: -++ case CLOCK_EVT_MODE_UNUSED: -++ case CLOCK_EVT_MODE_SHUTDOWN: -++ break; -++ case CLOCK_EVT_MODE_RESUME: -++ break; -++ } -++} -++ -++static struct clock_event_device jz_clockevent_device = { -++ .name = "jz-clockenvent", -++ .features = CLOCK_EVT_FEAT_PERIODIC, -++// .features = CLOCK_EVT_FEAT_ONESHOT, /* Jz4740 not support dynamic clock now */ -++ -++ /* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */ -++ .rating = 300, -++ .irq = JZ_TIMER_IRQ, -++ .set_mode = jz_set_mode, -++ .set_next_event = jz_set_next_event, -++}; -++ -++static void __init jz_clockevent_init(void) -++{ -++ struct clock_event_device *cd = &jz_clockevent_device; -++ unsigned int cpu = smp_processor_id(); -++ -++ cd->cpumask = cpumask_of_cpu(cpu); -++ clockevents_register_device(cd); -++} -++ -++static void __init jz_timer_setup(void) -++{ -++ jz_clocksource_init(); /* init jz clock source */ -++ jz_clockevent_init(); /* init jz clock event */ -++ -++ /* -++ * Make irqs happen for the system timer -++ */ -++ jz_irqaction.dev_id = &jz_clockevent_device; -++ setup_irq(JZ_TIMER_IRQ, &jz_irqaction); -++} -++ -++ -++void __init plat_time_init(void) -++{ -++ unsigned int latch; -++ -++ /* Init timer */ -++ latch = (JZ_TIMER_CLOCK + (HZ>>1)) / HZ; -++ -++ REG_TCU_OSTCSR = TCU_OSTCSR_PRESCALE16 | TCU_OSTCSR_EXT_EN; -++ REG_TCU_OSTCNT = 0; -++ REG_TCU_OSTDR = latch; -++ -++ REG_TCU_TMCR = TCU_TMCR_OSTMCL; /* unmask match irq */ -++ REG_TCU_TSCR = TCU_TSCR_OSTSC; /* enable timer clock */ -++ REG_TCU_TESR = TCU_TESR_OSTST; /* start counting up */ -++ -++ jz_timer_setup(); -++} -+diff -urN linux-2.6.24.7.old/arch/mips/kernel/cpu-probe.c linux-2.6.24.7/arch/mips/kernel/cpu-probe.c -+--- linux-2.6.24.7.old/arch/mips/kernel/cpu-probe.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/arch/mips/kernel/cpu-probe.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -160,6 +160,7 @@ -+ case CPU_25KF: -+ case CPU_PR4450: -+ case CPU_BCM3302: -++ case CPU_JZRISC: -+ cpu_wait = r4k_wait; -+ break; -+ -+@@ -802,6 +803,22 @@ -+ } -+ } -+ -++static inline void cpu_probe_ingenic(struct cpuinfo_mips *c) -++{ -++ decode_configs(c); -++ c->options &= ~MIPS_CPU_COUNTER; /* JZRISC does not implement the CP0 counter. */ -++ switch (c->processor_id & 0xff00) { -++ case PRID_IMP_JZRISC: -++ c->cputype = CPU_JZRISC; -++ c->isa_level = MIPS_CPU_ISA_M32R1; -++ c->tlbsize = 32; -++ break; -++ default: -++ panic("Unknown Ingenic Processor ID!"); -++ break; -++ } -++} -++ -+ const char *__cpu_name[NR_CPUS]; -+ -+ /* -+@@ -880,6 +897,7 @@ -+ case CPU_BCM4710: name = "Broadcom BCM4710"; break; -+ case CPU_PR4450: name = "Philips PR4450"; break; -+ case CPU_LOONGSON2: name = "ICT Loongson-2"; break; -++ case CPU_JZRISC: name = "Ingenic JZRISC"; break; -+ default: -+ BUG(); -+ } -+@@ -919,6 +937,9 @@ -+ case PRID_COMP_PHILIPS: -+ cpu_probe_philips(c); -+ break; -++ case PRID_COMP_INGENIC: -++ cpu_probe_ingenic(c); -++ break; -+ default: -+ c->cputype = CPU_UNKNOWN; -+ } -+diff -urN linux-2.6.24.7.old/arch/mips/mm/c-r4k.c linux-2.6.24.7/arch/mips/mm/c-r4k.c -+--- linux-2.6.24.7.old/arch/mips/mm/c-r4k.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/arch/mips/mm/c-r4k.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -874,6 +874,36 @@ -+ c->dcache.waybit = 0; -+ break; -+ -++ case CPU_JZRISC: -++ config1 = read_c0_config1(); -++ config1 = (config1 >> 22) & 0x07; -++ if (config1 == 0x07) -++ config1 = 10; -++ else -++ config1 = config1 + 11; -++ config1 += 2; -++ icache_size = (1 << config1); -++ c->icache.linesz = 32; -++ c->icache.ways = 4; -++ c->icache.waybit = __ffs(icache_size / c->icache.ways); -++ -++ config1 = read_c0_config1(); -++ config1 = (config1 >> 13) & 0x07; -++ if (config1 == 0x07) -++ config1 = 10; -++ else -++ config1 = config1 + 11; -++ config1 += 2; -++ dcache_size = (1 << config1); -++ c->dcache.linesz = 32; -++ c->dcache.ways = 4; -++ c->dcache.waybit = __ffs(dcache_size / c->dcache.ways); -++ -++ c->dcache.flags = 0; -++ c->options |= MIPS_CPU_PREFETCH; -++ -++ break; -++ -+ default: -+ if (!(config & MIPS_CONF_M)) -+ panic("Don't know how to probe P-caches on this cpu."); -+diff -urN linux-2.6.24.7.old/arch/mips/mm/cache.c linux-2.6.24.7/arch/mips/mm/cache.c -+--- linux-2.6.24.7.old/arch/mips/mm/cache.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/arch/mips/mm/cache.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -47,6 +47,8 @@ -+ void (*_dma_cache_inv)(unsigned long start, unsigned long size); -+ -+ EXPORT_SYMBOL(_dma_cache_wback_inv); -++EXPORT_SYMBOL(_dma_cache_wback); -++EXPORT_SYMBOL(_dma_cache_inv); -+ -+ #endif /* CONFIG_DMA_NONCOHERENT */ -+ -+diff -urN linux-2.6.24.7.old/arch/mips/mm/tlbex.c linux-2.6.24.7/arch/mips/mm/tlbex.c -+--- linux-2.6.24.7.old/arch/mips/mm/tlbex.c 2009-04-12 18:05:07.000000000 +0200 -++++ linux-2.6.24.7/arch/mips/mm/tlbex.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -981,6 +981,11 @@ -+ tlbw(p); -+ break; -+ -++ case CPU_JZRISC: -++ tlbw(p); -++ i_nop(p); -++ break; -++ -+ default: -+ panic("No TLB refill handler yet (CPU type: %d)", -+ current_cpu_data.cputype); -+diff -urN linux-2.6.24.7.old/crypto/Kconfig linux-2.6.24.7/crypto/Kconfig -+--- linux-2.6.24.7.old/crypto/Kconfig 2009-04-12 18:05:07.000000000 +0200 -++++ linux-2.6.24.7/crypto/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -502,6 +502,14 @@ -+ Authenc: Combined mode wrapper for IPsec. -+ This is required for IPSec. -+ -++config CRYPTO_LZO -++ tristate "LZO compression algorithm" -++ select CRYPTO_ALGAPI -++ select LZO_COMPRESS -++ select LZO_DECOMPRESS -++ help -++ This is the LZO algorithm. -++ -+ source "drivers/crypto/Kconfig" -+ -+ endif # if CRYPTO -+diff -urN linux-2.6.24.7.old/crypto/Makefile linux-2.6.24.7/crypto/Makefile -+--- linux-2.6.24.7.old/crypto/Makefile 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/crypto/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -51,6 +51,7 @@ -+ obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o -+ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o -+ obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o -++obj-$(CONFIG_CRYPTO_LZO) += lzo.o -+ obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o -+ -+ obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o -+diff -urN linux-2.6.24.7.old/crypto/lzo.c linux-2.6.24.7/crypto/lzo.c -+--- linux-2.6.24.7.old/crypto/lzo.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/crypto/lzo.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,106 @@ -++/* -++ * Cryptographic API. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++struct lzo_ctx { -++ void *lzo_comp_mem; -++}; -++ -++static int lzo_init(struct crypto_tfm *tfm) -++{ -++ struct lzo_ctx *ctx = crypto_tfm_ctx(tfm); -++ -++ ctx->lzo_comp_mem = vmalloc(LZO1X_MEM_COMPRESS); -++ if (!ctx->lzo_comp_mem) -++ return -ENOMEM; -++ -++ return 0; -++} -++ -++static void lzo_exit(struct crypto_tfm *tfm) -++{ -++ struct lzo_ctx *ctx = crypto_tfm_ctx(tfm); -++ -++ vfree(ctx->lzo_comp_mem); -++} -++ -++static int lzo_compress(struct crypto_tfm *tfm, const u8 *src, -++ unsigned int slen, u8 *dst, unsigned int *dlen) -++{ -++ struct lzo_ctx *ctx = crypto_tfm_ctx(tfm); -++ size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */ -++ int err; -++ -++ err = lzo1x_1_compress(src, slen, dst, &tmp_len, ctx->lzo_comp_mem); -++ -++ if (err != LZO_E_OK) -++ return -EINVAL; -++ -++ *dlen = tmp_len; -++ return 0; -++} -++ -++static int lzo_decompress(struct crypto_tfm *tfm, const u8 *src, -++ unsigned int slen, u8 *dst, unsigned int *dlen) -++{ -++ int err; -++ size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */ -++ -++ err = lzo1x_decompress_safe(src, slen, dst, &tmp_len); -++ -++ if (err != LZO_E_OK) -++ return -EINVAL; -++ -++ *dlen = tmp_len; -++ return 0; -++ -++} -++ -++static struct crypto_alg alg = { -++ .cra_name = "lzo", -++ .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, -++ .cra_ctxsize = sizeof(struct lzo_ctx), -++ .cra_module = THIS_MODULE, -++ .cra_list = LIST_HEAD_INIT(alg.cra_list), -++ .cra_init = lzo_init, -++ .cra_exit = lzo_exit, -++ .cra_u = { .compress = { -++ .coa_compress = lzo_compress, -++ .coa_decompress = lzo_decompress } } -++}; -++ -++static int __init init(void) -++{ -++ return crypto_register_alg(&alg); -++} -++ -++static void __exit fini(void) -++{ -++ crypto_unregister_alg(&alg); -++} -++ -++module_init(init); -++module_exit(fini); -++ -++MODULE_LICENSE("GPL"); -++MODULE_DESCRIPTION("LZO Compression Algorithm"); -+diff -urN linux-2.6.24.7.old/crypto/tcrypt.c linux-2.6.24.7/crypto/tcrypt.c -+--- linux-2.6.24.7.old/crypto/tcrypt.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/crypto/tcrypt.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -78,7 +78,7 @@ -+ "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", -+ "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", -+ "khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", "fcrypt", -+- "camellia", "seed", NULL -++ "camellia", "seed", "lzo", NULL -+ }; -+ -+ static void hexdump(unsigned char *buf, unsigned int len) -+@@ -800,7 +800,8 @@ -+ crypto_free_hash(tfm); -+ } -+ -+-static void test_deflate(void) -++static void test_comp(char *algo, struct comp_testvec *ctemplate, -++ struct comp_testvec *dtemplate, int ctcount, int dtcount) -+ { -+ unsigned int i; -+ char result[COMP_BUF_SIZE]; -+@@ -808,25 +809,26 @@ -+ struct comp_testvec *tv; -+ unsigned int tsize; -+ -+- printk("\ntesting deflate compression\n"); -++ printk("\ntesting %s compression\n", algo); -+ -+- tsize = sizeof (deflate_comp_tv_template); -++ tsize = sizeof(struct comp_testvec); -++ tsize *= ctcount; -+ if (tsize > TVMEMSIZE) { -+ printk("template (%u) too big for tvmem (%u)\n", tsize, -+ TVMEMSIZE); -+ return; -+ } -+ -+- memcpy(tvmem, deflate_comp_tv_template, tsize); -++ memcpy(tvmem, ctemplate, tsize); -+ tv = (void *)tvmem; -+ -+- tfm = crypto_alloc_comp("deflate", 0, CRYPTO_ALG_ASYNC); -++ tfm = crypto_alloc_comp(algo, 0, CRYPTO_ALG_ASYNC); -+ if (IS_ERR(tfm)) { -+- printk("failed to load transform for deflate\n"); -++ printk("failed to load transform for %s\n", algo); -+ return; -+ } -+ -+- for (i = 0; i < DEFLATE_COMP_TEST_VECTORS; i++) { -++ for (i = 0; i < ctcount; i++) { -+ int ilen, ret, dlen = COMP_BUF_SIZE; -+ -+ printk("test %u:\n", i + 1); -+@@ -845,19 +847,20 @@ -+ ilen, dlen); -+ } -+ -+- printk("\ntesting deflate decompression\n"); -++ printk("\ntesting %s decompression\n", algo); -+ -+- tsize = sizeof (deflate_decomp_tv_template); -++ tsize = sizeof(struct comp_testvec); -++ tsize *= dtcount; -+ if (tsize > TVMEMSIZE) { -+ printk("template (%u) too big for tvmem (%u)\n", tsize, -+ TVMEMSIZE); -+ goto out; -+ } -+ -+- memcpy(tvmem, deflate_decomp_tv_template, tsize); -++ memcpy(tvmem, dtemplate, tsize); -+ tv = (void *)tvmem; -+ -+- for (i = 0; i < DEFLATE_DECOMP_TEST_VECTORS; i++) { -++ for (i = 0; i < dtcount; i++) { -+ int ilen, ret, dlen = COMP_BUF_SIZE; -+ -+ printk("test %u:\n", i + 1); -+@@ -1057,7 +1060,11 @@ -+ test_hash("tgr192", tgr192_tv_template, TGR192_TEST_VECTORS); -+ test_hash("tgr160", tgr160_tv_template, TGR160_TEST_VECTORS); -+ test_hash("tgr128", tgr128_tv_template, TGR128_TEST_VECTORS); -+- test_deflate(); -++ test_comp("deflate", deflate_comp_tv_template, -++ deflate_decomp_tv_template, DEFLATE_COMP_TEST_VECTORS, -++ DEFLATE_DECOMP_TEST_VECTORS); -++ test_comp("lzo", lzo_comp_tv_template, lzo_decomp_tv_template, -++ LZO_COMP_TEST_VECTORS, LZO_DECOMP_TEST_VECTORS); -+ test_hash("crc32c", crc32c_tv_template, CRC32C_TEST_VECTORS); -+ test_hash("hmac(md5)", hmac_md5_tv_template, -+ HMAC_MD5_TEST_VECTORS); -+@@ -1167,7 +1174,9 @@ -+ break; -+ -+ case 13: -+- test_deflate(); -++ test_comp("deflate", deflate_comp_tv_template, -++ deflate_decomp_tv_template, DEFLATE_COMP_TEST_VECTORS, -++ DEFLATE_DECOMP_TEST_VECTORS); -+ break; -+ -+ case 14: -+@@ -1292,6 +1301,11 @@ -+ CAMELLIA_CBC_DEC_TEST_VECTORS); -+ break; -+ -++ case 33: -++ test_comp("lzo", lzo_comp_tv_template, lzo_decomp_tv_template, -++ LZO_COMP_TEST_VECTORS, LZO_DECOMP_TEST_VECTORS); -++ break; -++ -+ case 100: -+ test_hash("hmac(md5)", hmac_md5_tv_template, -+ HMAC_MD5_TEST_VECTORS); -+diff -urN linux-2.6.24.7.old/crypto/tcrypt.h linux-2.6.24.7/crypto/tcrypt.h -+--- linux-2.6.24.7.old/crypto/tcrypt.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/crypto/tcrypt.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -4408,6 +4408,88 @@ -+ }; -+ -+ /* -++ * LZO test vectors (null-terminated strings). -++ */ -++#define LZO_COMP_TEST_VECTORS 2 -++#define LZO_DECOMP_TEST_VECTORS 2 -++ -++static struct comp_testvec lzo_comp_tv_template[] = { -++ { -++ .inlen = 70, -++ .outlen = 46, -++ .input = "Join us now and share the software " -++ "Join us now and share the software ", -++ .output = { 0x00, 0x0d, 0x4a, 0x6f, 0x69, 0x6e, 0x20, 0x75, -++ 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x6e, -++ 0x64, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x20, -++ 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x66, 0x74, -++ 0x77, 0x70, 0x01, 0x01, 0x4a, 0x6f, 0x69, 0x6e, -++ 0x3d, 0x88, 0x00, 0x11, 0x00, 0x00 }, -++ }, { -++ .inlen = 159, -++ .outlen = 133, -++ .input = "This document describes a compression method based on the LZO " -++ "compression algorithm. This document defines the application of " -++ "the LZO algorithm used in UBIFS.", -++ .output = { 0x00, 0x2b, 0x54, 0x68, 0x69, 0x73, 0x20, 0x64, -++ 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, -++ 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, -++ 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70, -++ 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, -++ 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x62, -++ 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, -++ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x5a, 0x4f, 0x2b, -++ 0x8c, 0x00, 0x0d, 0x61, 0x6c, 0x67, 0x6f, 0x72, -++ 0x69, 0x74, 0x68, 0x6d, 0x2e, 0x20, 0x20, 0x54, -++ 0x68, 0x69, 0x73, 0x2a, 0x54, 0x01, 0x02, 0x66, -++ 0x69, 0x6e, 0x65, 0x73, 0x94, 0x06, 0x05, 0x61, -++ 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x76, -++ 0x0a, 0x6f, 0x66, 0x88, 0x02, 0x60, 0x09, 0x27, -++ 0xf0, 0x00, 0x0c, 0x20, 0x75, 0x73, 0x65, 0x64, -++ 0x20, 0x69, 0x6e, 0x20, 0x55, 0x42, 0x49, 0x46, -++ 0x53, 0x2e, 0x11, 0x00, 0x00 }, -++ }, -++}; -++ -++static struct comp_testvec lzo_decomp_tv_template[] = { -++ { -++ .inlen = 133, -++ .outlen = 159, -++ .input = { 0x00, 0x2b, 0x54, 0x68, 0x69, 0x73, 0x20, 0x64, -++ 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, -++ 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, -++ 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70, -++ 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, -++ 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x62, -++ 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, -++ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x5a, 0x4f, 0x2b, -++ 0x8c, 0x00, 0x0d, 0x61, 0x6c, 0x67, 0x6f, 0x72, -++ 0x69, 0x74, 0x68, 0x6d, 0x2e, 0x20, 0x20, 0x54, -++ 0x68, 0x69, 0x73, 0x2a, 0x54, 0x01, 0x02, 0x66, -++ 0x69, 0x6e, 0x65, 0x73, 0x94, 0x06, 0x05, 0x61, -++ 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x76, -++ 0x0a, 0x6f, 0x66, 0x88, 0x02, 0x60, 0x09, 0x27, -++ 0xf0, 0x00, 0x0c, 0x20, 0x75, 0x73, 0x65, 0x64, -++ 0x20, 0x69, 0x6e, 0x20, 0x55, 0x42, 0x49, 0x46, -++ 0x53, 0x2e, 0x11, 0x00, 0x00 }, -++ .output = "This document describes a compression method based on the LZO " -++ "compression algorithm. This document defines the application of " -++ "the LZO algorithm used in UBIFS.", -++ }, { -++ .inlen = 46, -++ .outlen = 70, -++ .input = { 0x00, 0x0d, 0x4a, 0x6f, 0x69, 0x6e, 0x20, 0x75, -++ 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x6e, -++ 0x64, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x20, -++ 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x66, 0x74, -++ 0x77, 0x70, 0x01, 0x01, 0x4a, 0x6f, 0x69, 0x6e, -++ 0x3d, 0x88, 0x00, 0x11, 0x00, 0x00 }, -++ .output = "Join us now and share the software " -++ "Join us now and share the software ", -++ }, -++}; -++ -++/* -+ * Michael MIC test vectors from IEEE 802.11i -+ */ -+ #define MICHAEL_MIC_TEST_VECTORS 6 -+diff -urN linux-2.6.24.7.old/drivers/char/Kconfig linux-2.6.24.7/drivers/char/Kconfig -+--- linux-2.6.24.7.old/drivers/char/Kconfig 2009-04-12 18:05:07.000000000 +0200 -++++ linux-2.6.24.7/drivers/char/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -731,6 +731,16 @@ -+ To compile this driver as a module, choose M here: the -+ module will be called rtc. -+ -++config RTC_PCF8563 -++ bool 'Philips PCF8563 Real Time Clock (I2C Bus)' -++ help -++ Philips PCF8563 Real Time Clock (I2C Bus) -++ -++config RTC_JZ -++ bool 'Jz47XX On-Chip Real Time Clock' -++ help -++ Jz47XX On-Chip Real Time Clock -++ -+ config JS_RTC -+ tristate "Enhanced Real Time Clock Support" -+ depends on SPARC32 && PCI -+@@ -1046,6 +1056,7 @@ -+ default y -+ -+ source "drivers/s390/char/Kconfig" -++source "drivers/char/jzchar/Kconfig" -+ -+ endmenu -+ -+diff -urN linux-2.6.24.7.old/drivers/char/Kconfig.orig linux-2.6.24.7/drivers/char/Kconfig.orig -+--- linux-2.6.24.7.old/drivers/char/Kconfig.orig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/Kconfig.orig 2009-04-12 18:01:55.000000000 +0200 -+@@ -0,0 +1,1051 @@ -++# -++# Character device configuration -++# -++ -++menu "Character devices" -++ -++config VT -++ bool "Virtual terminal" if EMBEDDED -++ depends on !S390 -++ select INPUT -++ default y if !VIOCONS -++ ---help--- -++ If you say Y here, you will get support for terminal devices with -++ display and keyboard devices. These are called "virtual" because you -++ can run several virtual terminals (also called virtual consoles) on -++ one physical terminal. This is rather useful, for example one -++ virtual terminal can collect system messages and warnings, another -++ one can be used for a text-mode user session, and a third could run -++ an X session, all in parallel. Switching between virtual terminals -++ is done with certain key combinations, usually Alt-. -++ -++ The setterm command ("man setterm") can be used to change the -++ properties (such as colors or beeping) of a virtual terminal. The -++ man page console_codes(4) ("man console_codes") contains the special -++ character sequences that can be used to change those properties -++ directly. The fonts used on virtual terminals can be changed with -++ the setfont ("man setfont") command and the key bindings are defined -++ with the loadkeys ("man loadkeys") command. -++ -++ You need at least one virtual terminal device in order to make use -++ of your keyboard and monitor. Therefore, only people configuring an -++ embedded system would want to say N here in order to save some -++ memory; the only way to log into such a system is then via a serial -++ or network connection. -++ -++ If unsure, say Y, or else you won't be able to do much with your new -++ shiny Linux system :-) -++ -++config VT_CONSOLE -++ bool "Support for console on virtual terminal" if EMBEDDED -++ depends on VT -++ default y -++ ---help--- -++ The system console is the device which receives all kernel messages -++ and warnings and which allows logins in single user mode. If you -++ answer Y here, a virtual terminal (the device used to interact with -++ a physical terminal) can be used as system console. This is the most -++ common mode of operations, so you should say Y here unless you want -++ the kernel messages be output only to a serial port (in which case -++ you should say Y to "Console on serial port", below). -++ -++ If you do say Y here, by default the currently visible virtual -++ terminal (/dev/tty0) will be used as system console. You can change -++ that with a kernel command line option such as "console=tty3" which -++ would use the third virtual terminal as system console. (Try "man -++ bootparam" or see the documentation of your boot loader (lilo or -++ loadlin) about how to pass options to the kernel at boot time.) -++ -++ If unsure, say Y. -++ -++config HW_CONSOLE -++ bool -++ depends on VT && !S390 && !UML -++ default y -++ -++config VT_HW_CONSOLE_BINDING -++ bool "Support for binding and unbinding console drivers" -++ depends on HW_CONSOLE -++ default n -++ ---help--- -++ The virtual terminal is the device that interacts with the physical -++ terminal through console drivers. On these systems, at least one -++ console driver is loaded. In other configurations, additional console -++ drivers may be enabled, such as the framebuffer console. If more than -++ 1 console driver is enabled, setting this to 'y' will allow you to -++ select the console driver that will serve as the backend for the -++ virtual terminals. -++ -++ See for more -++ information. For framebuffer console users, please refer to -++ . -++ -++config SERIAL_NONSTANDARD -++ bool "Non-standard serial port support" -++ depends on HAS_IOMEM -++ ---help--- -++ Say Y here if you have any non-standard serial boards -- boards -++ which aren't supported using the standard "dumb" serial driver. -++ This includes intelligent serial boards such as Cyclades, -++ Digiboards, etc. These are usually used for systems that need many -++ serial ports because they serve many terminals or dial-in -++ connections. -++ -++ Note that the answer to this question won't directly affect the -++ kernel: saying N will just cause the configurator to skip all -++ the questions about non-standard serial boards. -++ -++ Most people can say N here. -++ -++config COMPUTONE -++ tristate "Computone IntelliPort Plus serial support" -++ depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) -++ ---help--- -++ This driver supports the entire family of Intelliport II/Plus -++ controllers with the exception of the MicroChannel controllers and -++ products previous to the Intelliport II. These are multiport cards, -++ which give you many serial ports. You would need something like this -++ to connect more than two modems to your Linux box, for instance in -++ order to become a dial-in server. If you have a card like that, say -++ Y here and read . -++ -++ To compile this driver as modules, choose M here: the -++ modules will be called ip2 and ip2main. -++ -++config ROCKETPORT -++ tristate "Comtrol RocketPort support" -++ depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) -++ help -++ This driver supports Comtrol RocketPort and RocketModem PCI boards. -++ These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or -++ modems. For information about the RocketPort/RocketModem boards -++ and this driver read . -++ -++ To compile this driver as a module, choose M here: the -++ module will be called rocket. -++ -++ If you want to compile this driver into the kernel, say Y here. If -++ you don't have a Comtrol RocketPort/RocketModem card installed, say N. -++ -++config CYCLADES -++ tristate "Cyclades async mux support" -++ depends on SERIAL_NONSTANDARD && (PCI || ISA) -++ select FW_LOADER -++ ---help--- -++ This driver supports Cyclades Z and Y multiserial boards. -++ You would need something like this to connect more than two modems to -++ your Linux box, for instance in order to become a dial-in server. -++ -++ For information about the Cyclades-Z card, read -++ . -++ -++ To compile this driver as a module, choose M here: the -++ module will be called cyclades. -++ -++ If you haven't heard about it, it's safe to say N. -++ -++config CYZ_INTR -++ bool "Cyclades-Z interrupt mode operation (EXPERIMENTAL)" -++ depends on EXPERIMENTAL && CYCLADES -++ help -++ The Cyclades-Z family of multiport cards allows 2 (two) driver op -++ modes: polling and interrupt. In polling mode, the driver will check -++ the status of the Cyclades-Z ports every certain amount of time -++ (which is called polling cycle and is configurable). In interrupt -++ mode, it will use an interrupt line (IRQ) in order to check the -++ status of the Cyclades-Z ports. The default op mode is polling. If -++ unsure, say N. -++ -++config DIGIEPCA -++ tristate "Digiboard Intelligent Async Support" -++ depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) -++ ---help--- -++ This is a driver for Digi International's Xx, Xeve, and Xem series -++ of cards which provide multiple serial ports. You would need -++ something like this to connect more than two modems to your Linux -++ box, for instance in order to become a dial-in server. This driver -++ supports the original PC (ISA) boards as well as PCI, and EISA. If -++ you have a card like this, say Y here and read the file -++ . -++ -++ To compile this driver as a module, choose M here: the -++ module will be called epca. -++ -++config ESPSERIAL -++ tristate "Hayes ESP serial port support" -++ depends on SERIAL_NONSTANDARD && ISA && ISA_DMA_API -++ help -++ This is a driver which supports Hayes ESP serial ports. Both single -++ port cards and multiport cards are supported. Make sure to read -++ . -++ -++ To compile this driver as a module, choose M here: the -++ module will be called esp. -++ -++ If unsure, say N. -++ -++config MOXA_INTELLIO -++ tristate "Moxa Intellio support" -++ depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) -++ help -++ Say Y here if you have a Moxa Intellio multiport serial card. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called moxa. -++ -++config MOXA_SMARTIO -++ tristate "Moxa SmartIO support (OBSOLETE)" -++ depends on SERIAL_NONSTANDARD -++ help -++ Say Y here if you have a Moxa SmartIO multiport serial card. -++ -++ This driver can also be built as a module ( = code which can be -++ inserted in and removed from the running kernel whenever you want). -++ The module will be called mxser. If you want to do that, say M -++ here. -++ -++config MOXA_SMARTIO_NEW -++ tristate "Moxa SmartIO support v. 2.0" -++ depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) -++ help -++ Say Y here if you have a Moxa SmartIO multiport serial card and/or -++ want to help develop a new version of this driver. -++ -++ This is upgraded (1.9.1) driver from original Moxa drivers with -++ changes finally resulting in PCI probing. -++ -++ This driver can also be built as a module. The module will be called -++ mxser_new. If you want to do that, say M here. -++ -++config ISI -++ tristate "Multi-Tech multiport card support (EXPERIMENTAL)" -++ depends on SERIAL_NONSTANDARD && PCI -++ select FW_LOADER -++ help -++ This is a driver for the Multi-Tech cards which provide several -++ serial ports. The driver is experimental and can currently only be -++ built as a module. The module will be called isicom. -++ If you want to do that, choose M here. -++ -++config SYNCLINK -++ tristate "Microgate SyncLink card support" -++ depends on SERIAL_NONSTANDARD && PCI && ISA_DMA_API -++ help -++ Provides support for the SyncLink ISA and PCI multiprotocol serial -++ adapters. These adapters support asynchronous and HDLC bit -++ synchronous communication up to 10Mbps (PCI adapter). -++ -++ This driver can only be built as a module ( = code which can be -++ inserted in and removed from the running kernel whenever you want). -++ The module will be called synclink. If you want to do that, say M -++ here. -++ -++config SYNCLINKMP -++ tristate "SyncLink Multiport support" -++ depends on SERIAL_NONSTANDARD && PCI -++ help -++ Enable support for the SyncLink Multiport (2 or 4 ports) -++ serial adapter, running asynchronous and HDLC communications up -++ to 2.048Mbps. Each ports is independently selectable for -++ RS-232, V.35, RS-449, RS-530, and X.21 -++ -++ This driver may be built as a module ( = code which can be -++ inserted in and removed from the running kernel whenever you want). -++ The module will be called synclinkmp. If you want to do that, say M -++ here. -++ -++config SYNCLINK_GT -++ tristate "SyncLink GT/AC support" -++ depends on SERIAL_NONSTANDARD && PCI -++ help -++ Support for SyncLink GT and SyncLink AC families of -++ synchronous and asynchronous serial adapters -++ manufactured by Microgate Systems, Ltd. (www.microgate.com) -++ -++config N_HDLC -++ tristate "HDLC line discipline support" -++ depends on SERIAL_NONSTANDARD -++ help -++ Allows synchronous HDLC communications with tty device drivers that -++ support synchronous HDLC such as the Microgate SyncLink adapter. -++ -++ This driver can only be built as a module ( = code which can be -++ inserted in and removed from the running kernel whenever you want). -++ The module will be called n_hdlc. If you want to do that, say M -++ here. -++ -++config RISCOM8 -++ tristate "SDL RISCom/8 card support" -++ depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP -++ help -++ This is a driver for the SDL Communications RISCom/8 multiport card, -++ which gives you many serial ports. You would need something like -++ this to connect more than two modems to your Linux box, for instance -++ in order to become a dial-in server. If you have a card like that, -++ say Y here and read the file . -++ -++ Also it's possible to say M here and compile this driver as kernel -++ loadable module; the module will be called riscom8. -++ -++config SPECIALIX -++ tristate "Specialix IO8+ card support" -++ depends on SERIAL_NONSTANDARD -++ help -++ This is a driver for the Specialix IO8+ multiport card (both the -++ ISA and the PCI version) which gives you many serial ports. You -++ would need something like this to connect more than two modems to -++ your Linux box, for instance in order to become a dial-in server. -++ -++ If you have a card like that, say Y here and read the file -++ . Also it's possible to say M here -++ and compile this driver as kernel loadable module which will be -++ called specialix. -++ -++config SPECIALIX_RTSCTS -++ bool "Specialix DTR/RTS pin is RTS" -++ depends on SPECIALIX -++ help -++ The Specialix IO8+ card can only support either RTS or DTR. If you -++ say N here, the driver will use the pin as "DTR" when the tty is in -++ software handshake mode. If you say Y here or hardware handshake is -++ on, it will always be RTS. Read the file -++ for more information. -++ -++config SX -++ tristate "Specialix SX (and SI) card support" -++ depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) -++ help -++ This is a driver for the SX and SI multiport serial cards. -++ Please read the file for details. -++ -++ This driver can only be built as a module ( = code which can be -++ inserted in and removed from the running kernel whenever you want). -++ The module will be called sx. If you want to do that, say M here. -++ -++config RIO -++ tristate "Specialix RIO system support" -++ depends on SERIAL_NONSTANDARD -++ help -++ This is a driver for the Specialix RIO, a smart serial card which -++ drives an outboard box that can support up to 128 ports. Product -++ information is at . -++ There are both ISA and PCI versions. -++ -++config RIO_OLDPCI -++ bool "Support really old RIO/PCI cards" -++ depends on RIO -++ help -++ Older RIO PCI cards need some initialization-time configuration to -++ determine the IRQ and some control addresses. If you have a RIO and -++ this doesn't seem to work, try setting this to Y. -++ -++config STALDRV -++ bool "Stallion multiport serial support" -++ depends on SERIAL_NONSTANDARD -++ help -++ Stallion cards give you many serial ports. You would need something -++ like this to connect more than two modems to your Linux box, for -++ instance in order to become a dial-in server. If you say Y here, -++ you will be asked for your specific card model in the next -++ questions. Make sure to read in -++ this case. If you have never heard about all this, it's safe to -++ say N. -++ -++config STALLION -++ tristate "Stallion EasyIO or EC8/32 support" -++ depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI) -++ help -++ If you have an EasyIO or EasyConnection 8/32 multiport Stallion -++ card, then this is for you; say Y. Make sure to read -++ . -++ -++ To compile this driver as a module, choose M here: the -++ module will be called stallion. -++ -++config ISTALLION -++ tristate "Stallion EC8/64, ONboard, Brumby support" -++ depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI) -++ help -++ If you have an EasyConnection 8/64, ONboard, Brumby or Stallion -++ serial multiport card, say Y here. Make sure to read -++ . -++ -++ To compile this driver as a module, choose M here: the -++ module will be called istallion. -++ -++config A2232 -++ tristate "Commodore A2232 serial support (EXPERIMENTAL)" -++ depends on EXPERIMENTAL && ZORRO && BROKEN_ON_SMP -++ ---help--- -++ This option supports the 2232 7-port serial card shipped with the -++ Amiga 2000 and other Zorro-bus machines, dating from 1989. At -++ a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip -++ each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The -++ ports were connected with 8 pin DIN connectors on the card bracket, -++ for which 8 pin to DB25 adapters were supplied. The card also had -++ jumpers internally to toggle various pinning configurations. -++ -++ This driver can be built as a module; but then "generic_serial" -++ will also be built as a module. This has to be loaded before -++ "ser_a2232". If you want to do this, answer M here. -++ -++config SGI_SNSC -++ bool "SGI Altix system controller communication support" -++ depends on (IA64_SGI_SN2 || IA64_GENERIC) -++ help -++ If you have an SGI Altix and you want to enable system -++ controller communication from user space (you want this!), -++ say Y. Otherwise, say N. -++ -++config SGI_TIOCX -++ bool "SGI TIO CX driver support" -++ depends on (IA64_SGI_SN2 || IA64_GENERIC) -++ help -++ If you have an SGI Altix and you have fpga devices attached -++ to your TIO, say Y here, otherwise say N. -++ -++config SGI_MBCS -++ tristate "SGI FPGA Core Services driver support" -++ depends on SGI_TIOCX -++ help -++ If you have an SGI Altix with an attached SABrick -++ say Y or M here, otherwise say N. -++ -++source "drivers/serial/Kconfig" -++ -++config UNIX98_PTYS -++ bool "Unix98 PTY support" if EMBEDDED -++ default y -++ ---help--- -++ A pseudo terminal (PTY) is a software device consisting of two -++ halves: a master and a slave. The slave device behaves identical to -++ a physical terminal; the master device is used by a process to -++ read data from and write data to the slave, thereby emulating a -++ terminal. Typical programs for the master side are telnet servers -++ and xterms. -++ -++ Linux has traditionally used the BSD-like names /dev/ptyxx for -++ masters and /dev/ttyxx for slaves of pseudo terminals. This scheme -++ has a number of problems. The GNU C library glibc 2.1 and later, -++ however, supports the Unix98 naming standard: in order to acquire a -++ pseudo terminal, a process opens /dev/ptmx; the number of the pseudo -++ terminal is then made available to the process and the pseudo -++ terminal slave can be accessed as /dev/pts/. What was -++ traditionally /dev/ttyp2 will then be /dev/pts/2, for example. -++ -++ All modern Linux systems use the Unix98 ptys. Say Y unless -++ you're on an embedded system and want to conserve memory. -++ -++config LEGACY_PTYS -++ bool "Legacy (BSD) PTY support" -++ default y -++ ---help--- -++ A pseudo terminal (PTY) is a software device consisting of two -++ halves: a master and a slave. The slave device behaves identical to -++ a physical terminal; the master device is used by a process to -++ read data from and write data to the slave, thereby emulating a -++ terminal. Typical programs for the master side are telnet servers -++ and xterms. -++ -++ Linux has traditionally used the BSD-like names /dev/ptyxx -++ for masters and /dev/ttyxx for slaves of pseudo -++ terminals. This scheme has a number of problems, including -++ security. This option enables these legacy devices; on most -++ systems, it is safe to say N. -++ -++ -++config LEGACY_PTY_COUNT -++ int "Maximum number of legacy PTY in use" -++ depends on LEGACY_PTYS -++ range 0 256 -++ default "256" -++ ---help--- -++ The maximum number of legacy PTYs that can be used at any one time. -++ The default is 256, and should be more than enough. Embedded -++ systems may want to reduce this to save memory. -++ -++ When not in use, each legacy PTY occupies 12 bytes on 32-bit -++ architectures and 24 bytes on 64-bit architectures. -++ -++config BRIQ_PANEL -++ tristate 'Total Impact briQ front panel driver' -++ depends on PPC_CHRP -++ ---help--- -++ The briQ is a small footprint CHRP computer with a frontpanel VFD, a -++ tristate led and two switches. It is the size of a CDROM drive. -++ -++ If you have such one and want anything showing on the VFD then you -++ must answer Y here. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called briq_panel. -++ -++ It's safe to say N here. -++ -++config PRINTER -++ tristate "Parallel printer support" -++ depends on PARPORT -++ ---help--- -++ If you intend to attach a printer to the parallel port of your Linux -++ box (as opposed to using a serial printer; if the connector at the -++ printer has 9 or 25 holes ["female"], then it's serial), say Y. -++ Also read the Printing-HOWTO, available from -++ . -++ -++ It is possible to share one parallel port among several devices -++ (e.g. printer and ZIP drive) and it is safe to compile the -++ corresponding drivers into the kernel. -++ -++ To compile this driver as a module, choose M here and read -++ . The module will be called lp. -++ -++ If you have several parallel ports, you can specify which ports to -++ use with the "lp" kernel command line option. (Try "man bootparam" -++ or see the documentation of your boot loader (lilo or loadlin) about -++ how to pass options to the kernel at boot time.) The syntax of the -++ "lp" command line option can be found in . -++ -++ If you have more than 8 printers, you need to increase the LP_NO -++ macro in lp.c and the PARPORT_MAX macro in parport.h. -++ -++config LP_CONSOLE -++ bool "Support for console on line printer" -++ depends on PRINTER -++ ---help--- -++ If you want kernel messages to be printed out as they occur, you -++ can have a console on the printer. This option adds support for -++ doing that; to actually get it to happen you need to pass the -++ option "console=lp0" to the kernel at boot time. -++ -++ If the printer is out of paper (or off, or unplugged, or too -++ busy..) the kernel will stall until the printer is ready again. -++ By defining CONSOLE_LP_STRICT to 0 (at your own risk) you -++ can make the kernel continue when this happens, -++ but it'll lose the kernel messages. -++ -++ If unsure, say N. -++ -++config PPDEV -++ tristate "Support for user-space parallel port device drivers" -++ depends on PARPORT -++ ---help--- -++ Saying Y to this adds support for /dev/parport device nodes. This -++ is needed for programs that want portable access to the parallel -++ port, for instance deviceid (which displays Plug-and-Play device -++ IDs). -++ -++ This is the parallel port equivalent of SCSI generic support (sg). -++ It is safe to say N to this -- it is not needed for normal printing -++ or parallel port CD-ROM/disk support. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called ppdev. -++ -++ If unsure, say N. -++ -++config HVC_DRIVER -++ bool -++ help -++ Generic "hypervisor virtual console" infrastructure for various -++ hypervisors (pSeries, iSeries, Xen, lguest). -++ It will automatically be selected if one of the back-end console drivers -++ is selected. -++ -++ -++config HVC_CONSOLE -++ bool "pSeries Hypervisor Virtual Console support" -++ depends on PPC_PSERIES -++ select HVC_DRIVER -++ help -++ pSeries machines when partitioned support a hypervisor virtual -++ console. This driver allows each pSeries partition to have a console -++ which is accessed via the HMC. -++ -++config HVC_ISERIES -++ bool "iSeries Hypervisor Virtual Console support" -++ depends on PPC_ISERIES -++ default y -++ select HVC_DRIVER -++ help -++ iSeries machines support a hypervisor virtual console. -++ -++config HVC_RTAS -++ bool "IBM RTAS Console support" -++ depends on PPC_RTAS -++ select HVC_DRIVER -++ help -++ IBM Console device driver which makes use of RTAS -++ -++config HVC_BEAT -++ bool "Toshiba's Beat Hypervisor Console support" -++ depends on PPC_CELLEB -++ select HVC_DRIVER -++ help -++ Toshiba's Cell Reference Set Beat Console device driver -++ -++config HVC_XEN -++ bool "Xen Hypervisor Console support" -++ depends on XEN -++ select HVC_DRIVER -++ default y -++ help -++ Xen virtual console device driver -++ -++config VIRTIO_CONSOLE -++ bool -++ select HVC_DRIVER -++ -++config HVCS -++ tristate "IBM Hypervisor Virtual Console Server support" -++ depends on PPC_PSERIES -++ help -++ Partitionable IBM Power5 ppc64 machines allow hosting of -++ firmware virtual consoles from one Linux partition by -++ another Linux partition. This driver allows console data -++ from Linux partitions to be accessed through TTY device -++ interfaces in the device tree of a Linux partition running -++ this driver. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called hvcs.ko. Additionally, this module -++ will depend on arch specific APIs exported from hvcserver.ko -++ which will also be compiled when this driver is built as a -++ module. -++ -++source "drivers/char/ipmi/Kconfig" -++ -++config DS1620 -++ tristate "NetWinder thermometer support" -++ depends on ARCH_NETWINDER -++ help -++ Say Y here to include support for the thermal management hardware -++ found in the NetWinder. This driver allows the user to control the -++ temperature set points and to read the current temperature. -++ -++ It is also possible to say M here to build it as a module (ds1620) -++ It is recommended to be used on a NetWinder, but it is not a -++ necessity. -++ -++config NWBUTTON -++ tristate "NetWinder Button" -++ depends on ARCH_NETWINDER -++ ---help--- -++ If you say Y here and create a character device node /dev/nwbutton -++ with major and minor numbers 10 and 158 ("man mknod"), then every -++ time the orange button is pressed a number of times, the number of -++ times the button was pressed will be written to that device. -++ -++ This is most useful for applications, as yet unwritten, which -++ perform actions based on how many times the button is pressed in a -++ row. -++ -++ Do not hold the button down for too long, as the driver does not -++ alter the behaviour of the hardware reset circuitry attached to the -++ button; it will still execute a hard reset if the button is held -++ down for longer than approximately five seconds. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called nwbutton. -++ -++ Most people will answer Y to this question and "Reboot Using Button" -++ below to be able to initiate a system shutdown from the button. -++ -++config NWBUTTON_REBOOT -++ bool "Reboot Using Button" -++ depends on NWBUTTON -++ help -++ If you say Y here, then you will be able to initiate a system -++ shutdown and reboot by pressing the orange button a number of times. -++ The number of presses to initiate the shutdown is two by default, -++ but this can be altered by modifying the value of NUM_PRESSES_REBOOT -++ in nwbutton.h and recompiling the driver or, if you compile the -++ driver as a module, you can specify the number of presses at load -++ time with "insmod button reboot_count=". -++ -++config NWFLASH -++ tristate "NetWinder flash support" -++ depends on ARCH_NETWINDER -++ ---help--- -++ If you say Y here and create a character device /dev/flash with -++ major 10 and minor 160 you can manipulate the flash ROM containing -++ the NetWinder firmware. Be careful as accidentally overwriting the -++ flash contents can render your computer unbootable. On no account -++ allow random users access to this device. :-) -++ -++ To compile this driver as a module, choose M here: the -++ module will be called nwflash. -++ -++ If you're not sure, say N. -++ -++source "drivers/char/hw_random/Kconfig" -++ -++config NVRAM -++ tristate "/dev/nvram support" -++ depends on ATARI || X86 || ARM || GENERIC_NVRAM -++ ---help--- -++ If you say Y here and create a character special file /dev/nvram -++ with major number 10 and minor number 144 using mknod ("man mknod"), -++ you get read and write access to the extra bytes of non-volatile -++ memory in the real time clock (RTC), which is contained in every PC -++ and most Ataris. The actual number of bytes varies, depending on the -++ nvram in the system, but is usually 114 (128-14 for the RTC). -++ -++ This memory is conventionally called "CMOS RAM" on PCs and "NVRAM" -++ on Ataris. /dev/nvram may be used to view settings there, or to -++ change them (with some utility). It could also be used to frequently -++ save a few bits of very important data that may not be lost over -++ power-off and for which writing to disk is too insecure. Note -++ however that most NVRAM space in a PC belongs to the BIOS and you -++ should NEVER idly tamper with it. See Ralf Brown's interrupt list -++ for a guide to the use of CMOS bytes by your BIOS. -++ -++ On Atari machines, /dev/nvram is always configured and does not need -++ to be selected. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called nvram. -++ -++config RTC -++ tristate "Enhanced Real Time Clock Support" -++ depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV && !ARM && !SUPERH && !S390 -++ ---help--- -++ If you say Y here and create a character special file /dev/rtc with -++ major number 10 and minor number 135 using mknod ("man mknod"), you -++ will get access to the real time clock (or hardware clock) built -++ into your computer. -++ -++ Every PC has such a clock built in. It can be used to generate -++ signals from as low as 1Hz up to 8192Hz, and can also be used -++ as a 24 hour alarm. It reports status information via the file -++ /proc/driver/rtc and its behaviour is set by various ioctls on -++ /dev/rtc. -++ -++ If you run Linux on a multiprocessor machine and said Y to -++ "Symmetric Multi Processing" above, you should say Y here to read -++ and set the RTC in an SMP compatible fashion. -++ -++ If you think you have a use for such a device (such as periodic data -++ sampling), then say Y here, and read -++ for details. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called rtc. -++ -++config JS_RTC -++ tristate "Enhanced Real Time Clock Support" -++ depends on SPARC32 && PCI -++ ---help--- -++ If you say Y here and create a character special file /dev/rtc with -++ major number 10 and minor number 135 using mknod ("man mknod"), you -++ will get access to the real time clock (or hardware clock) built -++ into your computer. -++ -++ Every PC has such a clock built in. It can be used to generate -++ signals from as low as 1Hz up to 8192Hz, and can also be used -++ as a 24 hour alarm. It reports status information via the file -++ /proc/driver/rtc and its behaviour is set by various ioctls on -++ /dev/rtc. -++ -++ If you think you have a use for such a device (such as periodic data -++ sampling), then say Y here, and read -++ for details. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called js-rtc. -++ -++config SGI_DS1286 -++ tristate "SGI DS1286 RTC support" -++ depends on SGI_IP22 -++ help -++ If you say Y here and create a character special file /dev/rtc with -++ major number 10 and minor number 135 using mknod ("man mknod"), you -++ will get access to the real time clock built into your computer. -++ Every SGI has such a clock built in. It reports status information -++ via the file /proc/rtc and its behaviour is set by various ioctls on -++ /dev/rtc. -++ -++config SGI_IP27_RTC -++ bool "SGI M48T35 RTC support" -++ depends on SGI_IP27 -++ help -++ If you say Y here and create a character special file /dev/rtc with -++ major number 10 and minor number 135 using mknod ("man mknod"), you -++ will get access to the real time clock built into your computer. -++ Every SGI has such a clock built in. It reports status information -++ via the file /proc/rtc and its behaviour is set by various ioctls on -++ /dev/rtc. -++ -++config GEN_RTC -++ tristate "Generic /dev/rtc emulation" -++ depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH -++ ---help--- -++ If you say Y here and create a character special file /dev/rtc with -++ major number 10 and minor number 135 using mknod ("man mknod"), you -++ will get access to the real time clock (or hardware clock) built -++ into your computer. -++ -++ It reports status information via the file /proc/driver/rtc and its -++ behaviour is set by various ioctls on /dev/rtc. If you enable the -++ "extended RTC operation" below it will also provide an emulation -++ for RTC_UIE which is required by some programs and may improve -++ precision in some cases. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called genrtc. -++ -++config GEN_RTC_X -++ bool "Extended RTC operation" -++ depends on GEN_RTC -++ help -++ Provides an emulation for RTC_UIE which is required by some programs -++ and may improve precision of the generic RTC support in some cases. -++ -++config EFI_RTC -++ bool "EFI Real Time Clock Services" -++ depends on IA64 -++ -++config DS1302 -++ tristate "DS1302 RTC support" -++ depends on M32R && (PLAT_M32700UT || PLAT_OPSPUT) -++ help -++ If you say Y here and create a character special file /dev/rtc with -++ major number 121 and minor number 0 using mknod ("man mknod"), you -++ will get access to the real time clock (or hardware clock) built -++ into your computer. -++ -++config COBALT_LCD -++ bool "Support for Cobalt LCD" -++ depends on MIPS_COBALT -++ help -++ This option enables support for the LCD display and buttons found -++ on Cobalt systems through a misc device. -++ -++config DTLK -++ tristate "Double Talk PC internal speech card support" -++ depends on ISA -++ help -++ This driver is for the DoubleTalk PC, a speech synthesizer -++ manufactured by RC Systems (). It is also -++ called the `internal DoubleTalk'. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called dtlk. -++ -++config R3964 -++ tristate "Siemens R3964 line discipline" -++ ---help--- -++ This driver allows synchronous communication with devices using the -++ Siemens R3964 packet protocol. Unless you are dealing with special -++ hardware like PLCs, you are unlikely to need this. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called n_r3964. -++ -++ If unsure, say N. -++ -++config APPLICOM -++ tristate "Applicom intelligent fieldbus card support" -++ depends on PCI -++ ---help--- -++ This driver provides the kernel-side support for the intelligent -++ fieldbus cards made by Applicom International. More information -++ about these cards can be found on the WWW at the address -++ , or by email from David Woodhouse -++ . -++ -++ To compile this driver as a module, choose M here: the -++ module will be called applicom. -++ -++ If unsure, say N. -++ -++config SONYPI -++ tristate "Sony Vaio Programmable I/O Control Device support (EXPERIMENTAL)" -++ depends on EXPERIMENTAL && X86 && PCI && INPUT && !64BIT -++ ---help--- -++ This driver enables access to the Sony Programmable I/O Control -++ Device which can be found in many (all ?) Sony Vaio laptops. -++ -++ If you have one of those laptops, read -++ , and say Y or M here. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called sonypi. -++ -++config GPIO_TB0219 -++ tristate "TANBAC TB0219 GPIO support" -++ depends on TANBAC_TB022X -++ select GPIO_VR41XX -++ -++source "drivers/char/pcmcia/Kconfig" -++ -++config MWAVE -++ tristate "ACP Modem (Mwave) support" -++ depends on X86 -++ select SERIAL_8250 -++ ---help--- -++ The ACP modem (Mwave) for Linux is a WinModem. It is composed of a -++ kernel driver and a user level application. Together these components -++ support direct attachment to public switched telephone networks (PSTNs) -++ and support selected world wide countries. -++ -++ This version of the ACP Modem driver supports the IBM Thinkpad 600E, -++ 600, and 770 that include on board ACP modem hardware. -++ -++ The modem also supports the standard communications port interface -++ (ttySx) and is compatible with the Hayes AT Command Set. -++ -++ The user level application needed to use this driver can be found at -++ the IBM Linux Technology Center (LTC) web site: -++ . -++ -++ If you own one of the above IBM Thinkpads which has the Mwave chipset -++ in it, say Y. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called mwave. -++ -++config SCx200_GPIO -++ tristate "NatSemi SCx200 GPIO Support" -++ depends on SCx200 -++ select NSC_GPIO -++ help -++ Give userspace access to the GPIO pins on the National -++ Semiconductor SCx200 processors. -++ -++ If compiled as a module, it will be called scx200_gpio. -++ -++config PC8736x_GPIO -++ tristate "NatSemi PC8736x GPIO Support" -++ depends on X86 -++ default SCx200_GPIO # mostly N -++ select NSC_GPIO # needed for support routines -++ help -++ Give userspace access to the GPIO pins on the National -++ Semiconductor PC-8736x (x=[03456]) SuperIO chip. The chip -++ has multiple functional units, inc several managed by -++ hwmon/pc87360 driver. Tested with PC-87366 -++ -++ If compiled as a module, it will be called pc8736x_gpio. -++ -++config NSC_GPIO -++ tristate "NatSemi Base GPIO Support" -++ depends on X86_32 -++ # selected by SCx200_GPIO and PC8736x_GPIO -++ # what about 2 selectors differing: m != y -++ help -++ Common support used (and needed) by scx200_gpio and -++ pc8736x_gpio drivers. If those drivers are built as -++ modules, this one will be too, named nsc_gpio -++ -++config CS5535_GPIO -++ tristate "AMD CS5535/CS5536 GPIO (Geode Companion Device)" -++ depends on X86_32 -++ help -++ Give userspace access to the GPIO pins on the AMD CS5535 and -++ CS5536 Geode companion devices. -++ -++ If compiled as a module, it will be called cs5535_gpio. -++ -++config GPIO_DEVICE -++ tristate "GPIO device support" -++ depends on GENERIC_GPIO -++ help -++ Say Y to enable Linux GPIO device support. This allows control of -++ GPIO pins using a character device -++ -++config GPIO_VR41XX -++ tristate "NEC VR4100 series General-purpose I/O Unit support" -++ depends on CPU_VR41XX -++ -++config RAW_DRIVER -++ tristate "RAW driver (/dev/raw/rawN)" -++ depends on BLOCK -++ help -++ The raw driver permits block devices to be bound to /dev/raw/rawN. -++ Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. -++ See the raw(8) manpage for more details. -++ -++ Applications should preferably open the device (eg /dev/hda1) -++ with the O_DIRECT flag. -++ -++config MAX_RAW_DEVS -++ int "Maximum number of RAW devices to support (1-8192)" -++ depends on RAW_DRIVER -++ default "256" -++ help -++ The maximum number of RAW devices that are supported. -++ Default is 256. Increase this number in case you need lots of -++ raw devices. -++ -++config HPET -++ bool "HPET - High Precision Event Timer" if (X86 || IA64) -++ default n -++ depends on ACPI -++ help -++ If you say Y here, you will have a miscdevice named "/dev/hpet/". Each -++ open selects one of the timers supported by the HPET. The timers are -++ non-periodic and/or periodic. -++ -++config HPET_RTC_IRQ -++ bool "HPET Control RTC IRQ" if !HPET_EMULATE_RTC -++ default n -++ depends on HPET -++ help -++ If you say Y here, you will disable RTC_IRQ in drivers/char/rtc.c. It -++ is assumed the platform called hpet_alloc with the RTC IRQ values for -++ the HPET timers. -++ -++config HPET_MMAP -++ bool "Allow mmap of HPET" -++ default y -++ depends on HPET -++ help -++ If you say Y here, user applications will be able to mmap -++ the HPET registers. -++ -++ In some hardware implementations, the page containing HPET -++ registers may also contain other things that shouldn't be -++ exposed to the user. If this applies to your hardware, -++ say N here. -++ -++config HANGCHECK_TIMER -++ tristate "Hangcheck timer" -++ depends on X86 || IA64 || PPC64 || S390 -++ help -++ The hangcheck-timer module detects when the system has gone -++ out to lunch past a certain margin. It can reboot the system -++ or merely print a warning. -++ -++config MMTIMER -++ tristate "MMTIMER Memory mapped RTC for SGI Altix" -++ depends on IA64_GENERIC || IA64_SGI_SN2 -++ default y -++ help -++ The mmtimer device allows direct userspace access to the -++ Altix system timer. -++ -++source "drivers/char/tpm/Kconfig" -++ -++config TELCLOCK -++ tristate "Telecom clock driver for ATCA SBC" -++ depends on EXPERIMENTAL && X86 -++ default n -++ help -++ The telecom clock device is specific to the MPCBL0010 and MPCBL0050 -++ ATCA computers and allows direct userspace access to the -++ configuration of the telecom clock configuration settings. This -++ device is used for hardware synchronization across the ATCA backplane -++ fabric. Upon loading, the driver exports a sysfs directory, -++ /sys/devices/platform/telco_clock, with a number of files for -++ controlling the behavior of this hardware. -++ -++config DEVPORT -++ bool -++ depends on !M68K -++ depends on ISA || PCI -++ default y -++ -++source "drivers/s390/char/Kconfig" -++ -++endmenu -++ -+diff -urN linux-2.6.24.7.old/drivers/char/Makefile linux-2.6.24.7/drivers/char/Makefile -+--- linux-2.6.24.7.old/drivers/char/Makefile 2009-04-12 18:05:07.000000000 +0200 -++++ linux-2.6.24.7/drivers/char/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -98,6 +98,10 @@ -+ obj-$(CONFIG_GPIO_TB0219) += tb0219.o -+ obj-$(CONFIG_TELCLOCK) += tlclk.o -+ -++obj-$(CONFIG_RTC_PCF8563) += rtc_pcf8563.o -++obj-$(CONFIG_RTC_JZ) += rtc_jz.o -++obj-$(CONFIG_JZCHAR) += jzchar/ -++ -+ obj-$(CONFIG_MWAVE) += mwave/ -+ obj-$(CONFIG_AGP) += agp/ -+ obj-$(CONFIG_DRM) += drm/ -+diff -urN linux-2.6.24.7.old/drivers/char/Makefile.orig linux-2.6.24.7/drivers/char/Makefile.orig -+--- linux-2.6.24.7.old/drivers/char/Makefile.orig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/Makefile.orig 2009-04-12 18:01:55.000000000 +0200 -+@@ -0,0 +1,138 @@ -++# -++# Makefile for the kernel character device drivers. -++# -++ -++# -++# This file contains the font map for the default (hardware) font -++# -++FONTMAPFILE = cp437.uni -++ -++obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o -++ -++obj-$(CONFIG_LEGACY_PTYS) += pty.o -++obj-$(CONFIG_UNIX98_PTYS) += pty.o -++obj-y += misc.o -++obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o \ -++ consolemap_deftbl.o selection.o keyboard.o -++obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o -++obj-$(CONFIG_AUDIT) += tty_audit.o -++obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o -++obj-$(CONFIG_ESPSERIAL) += esp.o -++obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o -++obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o -++obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o -++obj-$(CONFIG_ROCKETPORT) += rocket.o -++obj-$(CONFIG_SERIAL167) += serial167.o -++obj-$(CONFIG_CYCLADES) += cyclades.o -++obj-$(CONFIG_STALLION) += stallion.o -++obj-$(CONFIG_ISTALLION) += istallion.o -++obj-$(CONFIG_DIGIEPCA) += epca.o -++obj-$(CONFIG_SPECIALIX) += specialix.o -++obj-$(CONFIG_MOXA_INTELLIO) += moxa.o -++obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o -++obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o -++obj-$(CONFIG_MOXA_SMARTIO) += mxser.o -++obj-$(CONFIG_MOXA_SMARTIO_NEW) += mxser_new.o -++obj-$(CONFIG_COMPUTONE) += ip2/ -++obj-$(CONFIG_RISCOM8) += riscom8.o -++obj-$(CONFIG_ISI) += isicom.o -++obj-$(CONFIG_SYNCLINK) += synclink.o -++obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o -++obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o -++obj-$(CONFIG_N_HDLC) += n_hdlc.o -++obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o -++obj-$(CONFIG_SX) += sx.o generic_serial.o -++obj-$(CONFIG_RIO) += rio/ generic_serial.o -++obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o -++obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o -++obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o -++obj-$(CONFIG_HVC_BEAT) += hvc_beat.o -++obj-$(CONFIG_HVC_DRIVER) += hvc_console.o -++obj-$(CONFIG_HVC_XEN) += hvc_xen.o -++obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o -++obj-$(CONFIG_RAW_DRIVER) += raw.o -++obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o -++obj-$(CONFIG_MSPEC) += mspec.o -++obj-$(CONFIG_MMTIMER) += mmtimer.o -++obj-$(CONFIG_VIOCONS) += viocons.o -++obj-$(CONFIG_VIOTAPE) += viotape.o -++obj-$(CONFIG_HVCS) += hvcs.o -++obj-$(CONFIG_SGI_MBCS) += mbcs.o -++obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o -++ -++obj-$(CONFIG_PRINTER) += lp.o -++obj-$(CONFIG_TIPAR) += tipar.o -++ -++obj-$(CONFIG_APM_EMULATION) += apm-emulation.o -++ -++obj-$(CONFIG_DTLK) += dtlk.o -++obj-$(CONFIG_R3964) += n_r3964.o -++obj-$(CONFIG_APPLICOM) += applicom.o -++obj-$(CONFIG_SONYPI) += sonypi.o -++obj-$(CONFIG_RTC) += rtc.o -++obj-$(CONFIG_HPET) += hpet.o -++obj-$(CONFIG_GEN_RTC) += genrtc.o -++obj-$(CONFIG_EFI_RTC) += efirtc.o -++obj-$(CONFIG_SGI_DS1286) += ds1286.o -++obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o -++obj-$(CONFIG_DS1302) += ds1302.o -++ifeq ($(CONFIG_GENERIC_NVRAM),y) -++ obj-$(CONFIG_NVRAM) += generic_nvram.o -++else -++ obj-$(CONFIG_NVRAM) += nvram.o -++endif -++obj-$(CONFIG_TOSHIBA) += toshiba.o -++obj-$(CONFIG_I8K) += i8k.o -++obj-$(CONFIG_DS1620) += ds1620.o -++obj-$(CONFIG_HW_RANDOM) += hw_random/ -++obj-$(CONFIG_COBALT_LCD) += lcd.o -++obj-$(CONFIG_PPDEV) += ppdev.o -++obj-$(CONFIG_NWBUTTON) += nwbutton.o -++obj-$(CONFIG_NWFLASH) += nwflash.o -++obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o -++obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o -++obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o -++obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o -++obj-$(CONFIG_GPIO_DEVICE) += gpio_dev.o -++obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o -++obj-$(CONFIG_GPIO_TB0219) += tb0219.o -++obj-$(CONFIG_TELCLOCK) += tlclk.o -++ -++obj-$(CONFIG_MWAVE) += mwave/ -++obj-$(CONFIG_AGP) += agp/ -++obj-$(CONFIG_DRM) += drm/ -++obj-$(CONFIG_PCMCIA) += pcmcia/ -++obj-$(CONFIG_IPMI_HANDLER) += ipmi/ -++ -++obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o -++obj-$(CONFIG_TCG_TPM) += tpm/ -++ -++obj-$(CONFIG_PS3_FLASH) += ps3flash.o -++ -++obj-$(CONFIG_JS_RTC) += js-rtc.o -++js-rtc-y = rtc.o -++ -++# Files generated that shall be removed upon make clean -++clean-files := consolemap_deftbl.c defkeymap.c -++ -++quiet_cmd_conmk = CONMK $@ -++ cmd_conmk = scripts/conmakehash $< > $@ -++ -++$(obj)/consolemap_deftbl.c: $(src)/$(FONTMAPFILE) -++ $(call cmd,conmk) -++ -++$(obj)/defkeymap.o: $(obj)/defkeymap.c -++ -++# Uncomment if you're changing the keymap and have an appropriate -++# loadkeys version for the map. By default, we'll use the shipped -++# versions. -++# GENERATE_KEYMAP := 1 -++ -++ifdef GENERATE_KEYMAP -++ -++$(obj)/defkeymap.c: $(obj)/%.c: $(src)/%.map -++ loadkeys --mktable $< > $@.tmp -++ sed -e 's/^static *//' $@.tmp > $@ -++ rm $@.tmp -++ -++endif -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/Kconfig linux-2.6.24.7/drivers/char/jzchar/Kconfig -+--- linux-2.6.24.7.old/drivers/char/jzchar/Kconfig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,70 @@ -++# -++# JzSOC char devices configuration -++# -++ -++menu "JZSOC char device support" -++ depends on SOC_JZ4740 || SOC_JZ4730 || SOC_JZ4750 || SOC_JZ4750D -++ -++config JZCHAR -++ tristate 'JzSOC char device support' -++ -++config JZ_CAMERA_SENSOR -++ bool -++ -++config JZ_CIM -++ tristate 'JzSOC Camera Interface Module (CIM) support' -++ depends on JZCHAR -++ select JZ_CAMERA_SENSOR -++ -++config JZ_TPANEL_ATA2508 -++ tristate 'JzSOC MPEG4 TOUCH PANEL ATA2508 support' -++ depends on JZCHAR -++ -++config JZ_TPANEL -++ tristate 'JzSOC touchpanel driver support' -++ depends on JZCHAR -++# select JZ_SADC if SOC_JZ4740 -++# select JZ_TPANEL_AK4182 if SOC_JZ4730 -++ -++choice -++ prompt "Touch Panel ADC type" -++ depends on JZ_TPANEL -++ default JZ_SADC if SOC_JZ4740 || SOC_JZ4750 || SOC_JZ4750D -++ default JZ_TPANEL_AK4182 if SOC_JZ4730 -++ -++config JZ_SADC -++ bool 'Select the JZ47XX internal SADC' -++ -++config JZ_TPANEL_AK4182 -++ bool 'Select the AK4182 codec' -++ -++config JZ_TPANEL_UCB1400 -++ bool 'Select the UCB1400 codec' -++ -++config JZ_TPANEL_WM9712 -++ bool 'Select the WM9712 codec' -++ -++endchoice -++ -++config JZ_UDC_HOTPLUG -++ tristate 'JZ UDC hotplug driver support' -++ depends on JZCHAR -++ -++config JZ_POWEROFF -++ tristate 'JZ board poweroff support' -++ depends on JZCHAR -++ -++config JZ_OW -++ tristate 'JZ One-wire bus support' -++ depends on JZCHAR -++ -++config JZ_TCSM -++ tristate 'JZ TCSM support' -++ depends on JZCHAR -++ -++config JZ_TSSI -++ tristate 'JZ MPEG2-TS interface support' -++ depends on JZCHAR && (SOC_JZ4750 || SOC_JZ4750D) -++ -++endmenu -++ -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/Makefile linux-2.6.24.7/drivers/char/jzchar/Makefile -+--- linux-2.6.24.7.old/drivers/char/jzchar/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,24 @@ -++# -++# Makefile for jzchar -++# -++obj-$(CONFIG_JZCHAR) += jzchars.o -++ -++obj-$(CONFIG_JZ_SCC) += scc.o -++obj-$(CONFIG_JZ_CIM) += cim.o -++obj-$(CONFIG_JZ_TPANEL_ATA2508) += ata2508.o -++obj-$(CONFIG_JZ_CAMERA_SENSOR) += sensor.o -++obj-$(CONFIG_JZ_I2C_EEPROM) += eeprom.o -++obj-$(CONFIG_JZ_EJTAG) += ejtag.o -++obj-$(CONFIG_JZ_POWEROFF) += poweroff.o -++ -++obj-$(CONFIG_JZ_TPANEL) += jz_ts.o -++obj-$(CONFIG_JZ_TPANEL_UCB1400) += ucb1400.o -++obj-$(CONFIG_JZ_TPANEL_WM9712) += wm9712.o -++obj-$(CONFIG_JZ_TPANEL_AK4182) += ak4182.o -++obj-$(CONFIG_JZ_SADC) += sadc.o -++ -++obj-$(CONFIG_JZ_SMART_LCD) += slcd.o -++obj-$(CONFIG_JZ_UDC_HOTPLUG) += udc_hotplug.o -++obj-$(CONFIG_JZ_OW) += jz_ow.o -++obj-$(CONFIG_JZ_TCSM) += tcsm.o -++obj-$(CONFIG_JZ_TSSI) += jz_tssi.o -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/ak4182.c linux-2.6.24.7/drivers/char/jzchar/ak4182.c -+--- linux-2.6.24.7.old/drivers/char/jzchar/ak4182.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/ak4182.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,657 @@ -++/* -++ * ak4182.c using national microwire protocol -++ * -++ * Touch screen driver interface to the AK4182A . -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include "jz_ts.h" -++#include "ak4182.h" -++ -++#define TS_PIN GPIO_TS_PENIRQ -++#define TS_IRQ (IRQ_GPIO_0 + TS_PIN) -++ -++static int samples = 5; -++static int first_time = 0; -++static unsigned long last_x, last_y, last_p; -++ -++static int adcsync = 0; -++ -++static struct ak4182 *ak; -++ -++extern unsigned int (*codec_read_battery)(void); -++ -++/*------------------JzSoc SSI configure----------------*/ -++static void ak4182_ssi_reset(void) -++{ -++ REG_SSI_CR0 = 0x0000; -++ REG_SSI_CR1 = 0x00007960; -++ REG_SSI_SR = 0x00000098; -++ REG_SSI_ITR = 0x0000; -++ REG_SSI_ICR = 0x00; -++ REG_SSI_GR = 0x0000; -++ -++ __ssi_disable(); -++ __ssi_flush_fifo(); -++ __ssi_clear_errors(); -++ __ssi_select_ce(); -++} -++ -++static void ak4182_ssi_enable(void) -++{ -++ __ssi_enable(); -++} -++ -++#ifdef CONFIG_PM -++static void ak4182_ssi_disable(void) -++{ -++ __ssi_disable(); -++} -++#endif -++ -++static void ak4182_ssi_set_trans_mode_format(void) -++{ -++ __ssi_microwire_format(); -++ __ssi_set_msb(); -++ __ssi_set_microwire_command_length(8); -++ __ssi_set_frame_length(12); -++} -++ -++static void ak4182_ssi_set_clk_div_ratio(int dev_clk, int ssi_clk) -++{ -++ __ssi_set_clk(dev_clk, ssi_clk); -++} -++ -++static void ak4182_ssi_set_normal_mode(void) -++{ -++ __ssi_normal_mode(); -++} -++ -++static void ak4182_ssi_set_IRQ(void) -++{ -++ __ssi_disable_tx_intr(); -++ __ssi_disable_rx_intr(); -++} -++ -++/*------------------ AK4182 routines ------------------*/ -++static inline void ak4182_reg_write(unsigned short val) -++{ -++ __ssi_transmit_data(val); -++} -++ -++static inline unsigned int ak4182_reg_read(void) -++{ -++ unsigned int val; -++ val = __ssi_receive_data(); -++ return val; -++} -++ -++static unsigned int ak4182_adc_read(int cmd_code, int sync) -++{ -++ unsigned int val, timeout = 10000; -++ unsigned int status,valid1,valid2,dataentry; -++ -++ ak4182_reg_write(cmd_code); -++ udelay(2);//wait 2 D_CLK -++ for (;;) { -++ status =0; -++ status = REG_SSI_SR; -++ valid1 = (status>>7) & 1; -++ valid2 = (status>>6) & 1; -++ if( valid1==1 && valid2==0 )//SSI transfer is finished -++ { -++ //Receive FIFO data entry number -++ dataentry = val = 0; -++ dataentry = (status>>8) & 0x1F; -++ if( dataentry > 5 ) -++ { -++ printk("R-FIFO entry=%d,SSI transfer is wrong!\n",dataentry); -++ while(dataentry > 0) -++ { -++ ak4182_reg_read(); -++ dataentry--; -++ } -++ return 0; -++ } -++ while(dataentry > 0) -++ { -++ val = ak4182_reg_read(); -++ dataentry--; -++ } -++ return val; -++ } -++ -++ if (--timeout == 0) -++ break; -++ udelay(1); -++ } -++ return 0; -++} -++ -++ -++//enable pen down IRQ -++static void ak4182_enable_irq(void) -++{ -++ unsigned long flags; -++ -++ spin_lock_irqsave(&ak->lock, flags); -++ __gpio_unmask_irq(TS_PIN); -++ spin_unlock_irqrestore(&ak->lock, flags); -++} -++ -++//disable pen down IRQ -++static void ak4182_disable_irq(void) -++{ -++ unsigned long flags; -++ -++ spin_lock_irqsave(&ak->lock, flags); -++ __gpio_mask_irq(TS_PIN); -++// spin_unlock_irqrestore(&ucb->lock, flags); -++ spin_unlock_irqrestore(&ak->lock, flags); -++} -++/* -++ * Switch to X position mode and measure Y plate. We switch the plate -++ * configuration in pressure mode, then switch to position mode. This -++ * gives a faster response time. Even so, we need to wait about 55us -++ * for things to stabilise. -++ */ -++static inline unsigned int ak4182_ts_read_xpos(void) -++{ -++ return ak4182_adc_read(0xD0, adcsync);//X-axis,0xD0 for 12bit,0xD8 for 8bit -++} -++ -++ -++/* -++ * Switch to pressure mode, and read pressure. We don't need to wait -++ * here, since both plates are being driven. -++ */ -++static inline unsigned int ak4182_ts_read_pressure(void) -++{ -++ unsigned int z1,z2,xpos,pressureval=0;//300 Om -++ //Z1 pressure -++ z1 = ak4182_adc_read(0xB0, adcsync);//0xB0 for 12bit,0xB8 for 8bit -++ if(z1>0) -++ { -++ //Z2 pressure -++ z2 = ak4182_adc_read(0xC0, adcsync);//0xC0 for 12bit,0xC8 for 8bit -++ if(z2>z1) -++ { -++ xpos = ak4182_ts_read_xpos(); -++ pressureval = (300*xpos*(z2-z1))/(4096*z1); -++ } -++ } -++ -++ return pressureval; -++} -++ -++ -++/* -++ * Switch to Y position mode and measure X plate. We switch the plate -++ * configuration in pressure mode, then switch to position mode. This -++ * gives a faster response time. Even so, we need to wait about 55us -++ * for things to stabilise. -++ */ -++static inline unsigned int ak4182_ts_read_ypos(void) -++{ -++ return ak4182_adc_read(0x90, adcsync);//Y-axis,0x90 for 12bit,0x98 for 8bit -++} -++ -++/*------------------------------------------------------------ -++ * Read the battery voltage -++ */ -++ -++unsigned int ak4182_read_battery(void) -++{ -++ unsigned int v; -++ int bat_val[5]; -++ int total = 0, max_bat, min_bat; -++ -++ v = ak4182_adc_read(0xA7, adcsync); -++ v = ak4182_adc_read(0xA7, adcsync); -++ for(v = 0;v <= 4;v++) -++ bat_val[v] = ak4182_adc_read(0xA7, adcsync); -++ -++ ak4182_adc_read(0xA4, adcsync); -++ max_bat = min_bat = bat_val[0]; -++ for(v = 0;v <= 4;v++) { -++ total += bat_val[v]; -++ if(bat_val[v] > max_bat) -++ max_bat = bat_val[v]; -++ if(bat_val[v] < min_bat) -++ min_bat = bat_val[v]; -++ } -++ total = total - max_bat - min_bat; -++ v = total / 3; -++ return v; -++} -++ -++/*------------------ Calibrate samples -------------------*/ -++ -++#define DIFF(a,b) ((a>b)?(a-b):(b-a)) -++ -++static int calibrate_samples(void *xbuf, void *ybuf, void *pbuf, int count) -++{ -++ unsigned long *xp = (unsigned long *)xbuf; -++ unsigned long *yp = (unsigned long *)ybuf; -++ unsigned long *pp = (unsigned long *)pbuf; -++ unsigned long x_cal = 0, y_cal = 0, p_cal = 0, tmp; -++ int ignored, i, j; -++ int valid = 0; -++ -++ /* throw away the max cases */ -++ tmp = xp[0]; -++ ignored = 0; -++ for (i = 1; i < count; i++) { -++ if (xp[i] > tmp) { -++ tmp = xp[i]; -++ ignored = i; -++ } -++ }//find the max val -++ j = 0; -++ for (i = 0; i < count; i++) { -++ if (i == ignored) -++ continue; -++ xp[j++] = xp[i]; -++ }//shift val and delete the max val -++ -++ tmp = yp[0]; -++ ignored = 0; -++ for (i = 1; i < count; i++) { -++ if (yp[i] > tmp) { -++ tmp = yp[i]; -++ ignored = i; -++ } -++ } -++ j = 0; -++ for (i = 0; i < count; i++) { -++ if (i == ignored) -++ continue; -++ yp[j++] = yp[i]; -++ } -++ -++ tmp = pp[0]; -++ ignored = 0; -++ for (i = 1; i < count; i++) { -++ if (pp[i] > tmp) { -++ tmp = pp[i]; -++ ignored = i; -++ } -++ } -++ j = 0; -++ for (i = 0; i < count; i++) { -++ if (i == ignored) -++ continue; -++ pp[j++] = pp[i]; -++ } -++ -++ /* throw away the min cases */ -++ -++ count -= 1; // decrement by 1 -++ -++ tmp = xp[0]; -++ ignored = 0; -++ for (i = 1; i < count; i++) { -++ if (xp[i] < tmp) { -++ tmp = xp[i]; -++ ignored = i; -++ } -++ } -++ j = 0; -++ for (i = 0; i < count; i++) { -++ if (i == ignored) -++ continue; -++ xp[j++] = xp[i]; -++ } -++ -++ tmp = yp[0]; -++ ignored = 0; -++ for (i = 1; i < count; i++) { -++ if (yp[i] < tmp) { -++ tmp = yp[i]; -++ ignored = i; -++ } -++ } -++ j = 0; -++ for (i = 0; i < count; i++) { -++ if (i == ignored) -++ continue; -++ yp[j++] = yp[i]; -++ } -++ -++ tmp = pp[0]; -++ ignored = 0; -++ for (i = 1; i < count; i++) { -++ if (pp[i] < tmp) { -++ tmp = pp[i]; -++ ignored = i; -++ } -++ } -++ j = 0; -++ for (i = 0; i < count; i++) { -++ if (i == ignored) -++ continue; -++ pp[j++] = pp[i]; -++ } -++ -++ count -= 1; // decrement by 1 -++ -++ /* calculate the average of the rest */ -++ for (i = 0; i < count; i++) { -++ x_cal += xp[i]; -++ y_cal += yp[i]; -++ p_cal += pp[i]; -++ } -++ x_cal /= count; -++ y_cal /= count; -++ p_cal /= count; -++ -++ if (first_time) { -++ first_time = 0; -++ last_x = x_cal; -++ last_y = y_cal; -++ last_p = p_cal; -++ valid = 1; -++ } -++ else { -++ if ((DIFF(x_cal, last_x) > 100) || -++ (DIFF(y_cal, last_y) > 100)) -++ valid = 0; -++ else -++ valid = 1; -++ } -++ -++ //printk("x_cal=%d y_cal=%d p_cal=%d valid=%d\n", x_cal, y_cal, p_cal, valid); -++ -++ if (valid) { -++ *xp = last_x = x_cal; -++ *yp = last_y = y_cal; -++ *pp = last_p = p_cal; -++ } -++ -++ return valid; -++} -++ -++ -++#define TSMAXX 945 -++#define TSMAXY 830 -++#define TSMINX 90 -++#define TSMINY 105 -++ -++#define SCREEN_X 480 -++#define SCREEN_Y 272 -++ -++static unsigned long transform_to_screen_x(struct jz_ts_t *ts, unsigned long x ) -++{ -++ -++ if (ts->minx) -++ { -++ if (x < ts->minx) x = ts->minx; -++ if (x > ts->maxx) x = ts->maxx; -++ -++ return (x - ts->minx) * SCREEN_X / (ts->maxx - ts->minx); -++ } -++ else -++ { -++ if (x < TSMINX) x = TSMINX; -++ if (x > TSMAXX) x = TSMAXX; -++ -++ return (x - TSMINX) * SCREEN_X / (TSMAXX - TSMINX); -++ } -++} -++ -++static unsigned long transform_to_screen_y(struct jz_ts_t *ts, unsigned long y) -++{ -++ if (ts->miny) -++ { -++ if (y < ts->miny) y = ts->miny; -++ if (y > ts->maxy) y = ts->maxy; -++ -++ return (y - ts->miny) * SCREEN_Y / (ts->maxy - ts->miny); -++ } -++ else -++ { -++ if (y < TSMINY) y = TSMINY; -++ if (y > TSMAXY) y = TSMAXY; -++ -++ return (y - TSMINY) * SCREEN_Y / (TSMAXY - TSMINY); -++ } -++} -++ -++/*------------------ Common routines -------------------*/ -++ -++void ts_enable_irq(void) -++{ -++ /* interrupt mode */ -++ ak4182_enable_irq(); -++ enable_irq(TS_IRQ); -++} -++ -++void ts_disable_irq(void) -++{ -++ ak4182_disable_irq(); -++ disable_irq(TS_IRQ); -++} -++ -++int ts_request_irq(u32 *irq, -++ irqreturn_t (*handler)(int, void *), -++ const char *devname, -++ void *dev_id) -++{ -++ int retval; -++ -++ /* return the irq number */ -++ *irq = TS_IRQ; -++ /* initializate ssi for AK4182 */ -++ ak4182_ssi_reset(); -++ ak4182_ssi_set_trans_mode_format(); -++ ak4182_ssi_set_normal_mode(); -++ ak4182_ssi_set_clk_div_ratio(JZ_EXTAL, 200*1000);//DCLK is 1.5M Hz max -++ ak4182_ssi_set_IRQ(); -++ -++ ak4182_enable_irq(); -++ -++ /* enable gpio irq */ -++ __gpio_as_irq_fall_edge(TS_PIN); -++ -++ /* register irq handler */ -++ retval = request_irq(TS_IRQ, handler, IRQF_DISABLED, devname, dev_id); -++ ak4182_ssi_enable(); -++ udelay(10); -++ return retval; -++} -++ -++void ts_free_irq(struct jz_ts_t *ts) -++{ -++ free_irq(ts->pendown_irq, ts); -++ //Close SSI mode -++ ak4182_ssi_reset(); -++} -++ -++void ts_irq_callback(void) -++{ -++ /* clear interrupt status */ -++ __gpio_ack_irq(TS_PIN); -++ first_time = 1; // first time to acquire sample -++} -++ -++int PenIsDown(void) -++{ -++ unsigned int p; -++ p = ak4182_ts_read_pressure(); -++ return (p > 100) ? 1 : 0; -++} -++ -++/* -++ * Acquire Raw pen coodinate data and compute touch screen -++ * pressure resistance. Hold spinlock when calling. -++ */ -++int AcquireEvent(struct jz_ts_t *ts, struct ts_event *event) -++{ -++ unsigned int x_raw[8], y_raw[8], p_raw[8]; -++ int valid, i; -++ -++ for (i = 0; i < samples; i++) { -++ x_raw[i] = ak4182_ts_read_xpos(); -++ } -++ for (i = 0; i < samples; i++) { -++ y_raw[i] = ak4182_ts_read_ypos(); -++ } -++ for (i = 0; i < samples; i++) { -++ p_raw[i] = ak4182_ts_read_pressure(); -++ } -++ -++ valid = calibrate_samples(x_raw, y_raw, p_raw, samples); -++ -++ if (valid) { -++ unsigned int x_scr, y_scr; -++ -++ if(ts->filter) { -++ x_scr = transform_to_screen_x(ts, x_raw[0]); -++ y_scr = transform_to_screen_y(ts, y_raw[0]); -++ -++ if (ts->prints) -++ printk("filter:x_raw:%d,y_raw:%d,x_tran:%d,y_tran:%d\n", x_raw[0], y_raw[0], x_scr, y_scr); -++ } -++ else { -++ x_scr = x_raw[0]; -++ y_scr = y_raw[0]; -++ -++ if (ts->prints) -++ printk("no filter:x_raw=%d y_raw=%d \n", x_raw[0], y_raw[0]); -++ } -++ -++ event->x = x_scr; -++ event->y = y_scr; -++ event->pressure = (u16)p_raw[0]; -++ event->status = PENDOWN; -++ return 1; -++ } -++ return 0; -++} -++ -++#ifdef CONFIG_PM -++ -++/* -++ * Suspend the Touch pad. -++ */ -++static int ak4182_suspend(struct ak4182 *ak , int state) -++{ -++ ak4182_ssi_disable(); -++ -++ return 0; -++} -++ -++/* -++ * Resume the Touch panel. -++ */ -++static int ak4182_resume(struct ak4182 *ak) -++{ -++ /* initializate ssi for AK4182 */ -++ ak4182_ssi_reset(); -++ ak4182_ssi_set_trans_mode_format(); -++ ak4182_ssi_set_normal_mode(); -++ ak4182_ssi_set_clk_div_ratio(JZ_EXTAL, 200*1000);//DCLK is 1.5M Hz max -++ ak4182_ssi_set_IRQ(); -++ -++ ak4182_enable_irq(); -++ -++ ak4182_ssi_enable(); -++ -++ return 0; -++} -++ -++static int ak4182_pm_callback(struct pm_dev *pm_dev, pm_request_t rqst, void *data) -++{ -++ int ret; -++ struct ak4182 *akinfo = pm_dev->data; -++ -++ if (!akinfo) -++ return -EINVAL; -++ -++ -++ switch (rqst) { -++ case PM_SUSPEND: -++ ret = ak4182_suspend(akinfo, (int)data); -++ break; -++ -++ case PM_RESUME: -++ ret = ak4182_resume(akinfo); -++ break; -++ -++ default: -++ ret = -EINVAL; -++ break; -++ } -++ -++ return ret; -++} -++ -++#endif /* CONFIG_PM */ -++ -++ -++/* -++ * Module init and exit -++ */ -++ -++int __init ak4182_init(void) -++{ -++ ak = kmalloc(sizeof(struct ak4182), GFP_KERNEL); -++ if (!ak) return -ENOMEM; -++ -++ memset(ak, 0, sizeof(struct ak4182)); -++ -++ codec_read_battery = ak4182_read_battery; -++ -++ spin_lock_init(&ak->lock); -++ sema_init(&ak->adc_sem, 1); -++ -++ //initialize AK4182 register -++ __gpio_clear_pin(73); -++ __gpio_as_output(73); -++ mdelay(2); -++ __gpio_set_pin(73); -++ __gpio_as_ssi(); -++ -++ ak4182_read_battery(); -++ -++#ifdef CONFIG_PM -++ ak->pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ak4182_pm_callback); -++ if (ak->pmdev) -++ { -++ ak->pmdev->data = ak; -++ } -++#endif -++ -++ printk("AK4182 touch screen driver initialized\n"); -++ -++ return 0; -++} -++ -++void ak4182_cleanup(void) -++{ -++} -++ -++module_init(ak4182_init); -++module_exit(ak4182_cleanup); -++ -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/ak4182.h linux-2.6.24.7/drivers/char/jzchar/ak4182.h -+--- linux-2.6.24.7.old/drivers/char/jzchar/ak4182.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/ak4182.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,16 @@ -++#ifndef __AK4182_H__ -++#define __AK4182_H__ -++ -++/* Device data structure */ -++ -++struct ak4182 { -++ spinlock_t lock; -++ struct pm_dev *pmdev; -++ struct semaphore adc_sem; -++ u16 adc_cr; -++ u16 irq_fal_enbl; -++ u16 irq_ris_enbl; -++ int irq_enabled; -++}; -++ -++#endif /* __AK4182_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/ata2508.c linux-2.6.24.7/drivers/char/jzchar/ata2508.c -+--- linux-2.6.24.7.old/drivers/char/jzchar/ata2508.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/ata2508.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,227 @@ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++ -++#define MP4_KEY_RST (32*3+3) -++#define MP4_KEY_TINT (32*3+2) -++#define MP4_KEY_SCL (32*3+1) -++#define MP4_KEY_SDA (32*3+0) -++#define MP4_TINT_IRQ (IRQ_GPIO_0 + MP4_KEY_TINT) -++ -++#define ADDR_WARM_RESET 0xFF -++#define ATA2508_SENSOR_MASK 0x1F -++ -++const unsigned char init_data_burst[] = {//Address:0x0D-0x3E -++ 0x04, // BETA -++ 0x27, // AIC_WAIT -++ //0x32, // REF_DELAY -++ 0x16, // REF_DELAY -++ 0x02, // HYSTERESIS01 -++ 0x02, // HYSTERESIS1 -++ 0x02, // HYSTERESIS2 -++ 0x02, // HYSTERESIS3 -++ 0x02, // HYSTERESIS4 -++ 0x02, // HYSTERESIS51 -++ 0x02, // HYSTERESIS61 -++ 0x02, // HYSTERESIS7 -++ 0x02, // HYSTERESIS8 -++ 0x02, // HYSTERESIS9 -++ 0x02, // HYSTERESIS10 -++ 0x02, // HYSTERESIS11 -++ 0x64, // STRENGTH_THRESHOLD0 -++ 0x64, // STRENGTH_THRESHOLD1 -++ 0x64, // STRENGTH_THRESHOLD2 -++ 0x64, // STRENGTH_THRESHOLD3 -++ 0x64, // STRENGTH_THRESHOLD4 -++ 0x64, // STRENGTH_THRESHOLD5 -++ 0x64, // STRENGTH_THRESHOLD6 -++ 0x64, // STRENGTH_THRESHOLD7 -++ 0x64, // STRENGTH_THRESHOLD8 -++ 0x64, // STRENGTH_THRESHOLD9 -++ 0x64, // STRENGTH_THRESHOLD10 -++ 0x64, // STRENGTH_THRESHOLD11 -++ 0x0f, // Sampling Interval -++ 0xC8, // INTEGRATION TIME -++ 0x0f, // IDLE TIME -++ 0x00, // SIF_SETUP(RESERVED) -++ 0x01, // MODE -++ 0x00, // GPIO_REG_L -++ 0x00, // GPIO_REG_H -++ 0x00, // GPIO_CONFIGURATION_L -++ 0x00, // GPIO_CONFIGURATION_H -++ 0x00, // GPIO_DIR_L -++ 0x00, // GPIO_DIR_H -++ 0x0c, // CONTROL -++ 0x38, // INT_MASK -++ 0x00, // INT_CLEAR -++ 0xFF, // INT_edge -++ 0x02, // CONTROL_2 -++ 0xAF, // BEEP_TIME -++ 0x7F, // BEEP_FREQUENCY -++ 0x30, // CALIBRATION INTERVAL -++ 0x00, // EINT_ENABLE -++ 0x00, // EINT_POL -++ 0x00, // FILTER_PERIOD -++ 0x00, // FILTER_THRESHOLD -++}; -++const unsigned char init_data_alpha[] = {//Address:0x00-0x0C -++ 0x02, // APIS -++ 0x08, // ALPHA0 -++ 0x08, // ALPHA1 -++ 0x08, // ALPHA2 -++ 0x08, // ALPHA3 -++ 0x08, // ALPHA4 -++ 0x28, // ALPHA5 -++ 0x28, // ALPHA6 -++ 0x28, // ALPHA7 -++ 0x28, // ALPHA8 -++ 0x28, // ALPHA9 -++ 0x28, // ALPHA10 -++ 0x28, // ALPHA11 -++}; -++static unsigned int i2c_addr = 0x58; -++static unsigned int i2c_clk = 100000; -++ -++static void write_reg(u8 reg, u8 val) -++{ -++ int ret; -++ i2c_open(); -++ i2c_setclk(i2c_clk); -++ ret = i2c_write(i2c_addr, &val, reg, 1); -++ i2c_close(); -++} -++ -++static u8 read_reg(u8 reg) -++{ -++ u8 val; -++ -++ i2c_open(); -++ i2c_setclk(i2c_clk); -++ i2c_read(i2c_addr, &val, reg, 1); -++ i2c_close(); -++ return val; -++} -++ -++/* -++ * Interrupt handler -++ */ -++static irqreturn_t mp4_tint_irq(int irq, void *dev_id) -++{ -++ int key_num = 0; -++ u8 value0, value1; -++ -++ __gpio_ack_irq(MP4_KEY_TINT); -++ value0 = read_reg(0x75); -++ value1 = read_reg(0x76); -++ value0 &= ATA2508_SENSOR_MASK; -++ if (value0 == 0) { -++ printk("\nRelease key!\n"); -++ return IRQ_HANDLED; -++ } -++ while(value0 >> 1){ -++ value0 >>= 1; -++ key_num++; -++ } -++ -++ printk("\nPress key %d!\n", key_num); -++ return IRQ_HANDLED; -++} -++ -++static int __init init_ata2508(void) -++{ -++ int i; -++ unsigned char data1; -++ int retval; -++ -++ __gpio_as_output(MP4_KEY_RST); -++ __gpio_set_pin(MP4_KEY_RST); -++ mdelay(100); -++ __gpio_clear_pin(MP4_KEY_RST); -++ mdelay(800); -++ __gpio_set_pin(MP4_KEY_RST); -++ __gpio_mask_irq(MP4_KEY_TINT); -++ -++ /*write registers*/ -++ for(i=0; i<13; i++) -++ { -++ data1 = init_data_alpha[i]; -++ write_reg(i, data1); -++ } -++ -++ for(i=13; i<63; i++) -++ { -++ data1 = init_data_burst[i-13]; -++ write_reg(i, data1); -++ } -++#if 0 -++ for (i = 0; i < 63; i++) -++ { -++ data1 = read_reg(i); -++ printk("REG0x%02x = 0x%02x\n", i, data1); -++ } -++#endif -++ -++ /* wait for 1 ms*/ -++ mdelay(1); -++#if 0 -++ while(1) -++ { -++ data1 = read_reg(0x68); -++ printk("REG0x68 = %d\n", data1); -++ data1 = read_reg(0x75); -++ printk("REG0x75 = 0x%02x\n", data1); -++ data1 = read_reg(0x76); -++ printk("REG0x76 = 0x%02x\n", data1); -++ mdelay(2000); -++ } -++#endif -++ data1 = read_reg(0x68); -++ printk("REG0x68 = %d\n", data1); -++ -++ /* to activate all the new settings, give a WARM RESET.*/ -++ write_reg(ADDR_WARM_RESET, 0x00); //ADDR_WARM_RESET=0xFF -++ -++ //printk("REG0x68 = %d\n", data1); -++ -++ /* wait for 1 ~ 10 ms.*/ -++ mdelay(10); -++ data1 = read_reg(0x68); -++ -++ /* Enable INT that connected to ATA2508's TINT.*/ -++ __gpio_as_irq_rise_edge(MP4_KEY_TINT); -++ -++ retval = request_irq(MP4_TINT_IRQ, mp4_tint_irq, -++ IRQF_DISABLED, "mp4_key_tint", NULL); -++ if (retval) { -++ printk("Could not get mp4 key irq %d\n", MP4_TINT_IRQ); -++ return retval; -++ } -++ -++ printk("MP4 touch panel register!\n"); -++ -++ return 0; -++} -++ -++static void __exit exit_ata2508(void) -++{ -++ free_irq(MP4_TINT_IRQ, NULL); -++} -++ -++module_init(init_ata2508); -++module_exit(exit_ata2508); -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/cim.c linux-2.6.24.7/drivers/char/jzchar/cim.c -+--- linux-2.6.24.7.old/drivers/char/jzchar/cim.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/cim.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,366 @@ -++/* -++ * linux/drivers/char/jzchar/cim.c -++ * -++ * Camera Interface Module (CIM) driver for JzSOC -++ * This driver is independent of the camera sensor -++ * -++ * Copyright (C) 2005 JunZheng semiconductor -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software Foundation, -++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++ -++#include "jzchars.h" -++ -++#define CIM_NAME "cim" -++ -++MODULE_AUTHOR("Jianli Wei"); -++MODULE_DESCRIPTION("JzSOC Camera Interface Module driver"); -++MODULE_LICENSE("GPL"); -++ -++/* -++ * Define the Max Image Size -++ */ -++#define MAX_IMAGE_WIDTH 640 -++#define MAX_IMAGE_HEIGHT 480 -++#define MAX_IMAGE_BPP 16 -++#define MAX_FRAME_SIZE (MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * MAX_IMAGE_BPP / 8) -++ -++typedef struct -++{ -++ u32 width; -++ u32 height; -++ u32 bpp; -++} img_param_t; -++ -++typedef struct -++{ -++ u32 cfg; -++ u32 ctrl; -++ u32 mclk; -++} cim_config_t; -++ -++/* -++ * IOCTL_XXX commands -++ */ -++#define IOCTL_SET_IMG_PARAM 0 // arg type: img_param_t * -++#define IOCTL_CIM_CONFIG 1 // arg type: cim_config_t * -++ -++/* Actual image size, must less than max values */ -++static int img_width = MAX_IMAGE_WIDTH, img_height = MAX_IMAGE_HEIGHT, img_bpp = MAX_IMAGE_BPP; -++ -++/* -++ * CIM DMA descriptor -++ */ -++struct cim_desc { -++ u32 nextdesc; /* Physical address of next desc */ -++ u32 framebuf; /* Physical address of frame buffer */ -++ u32 frameid; /* Frame ID */ -++ u32 dmacmd; /* DMA command */ -++}; -++ -++/* -++ * CIM device structure -++ */ -++struct cim_device { -++ unsigned char *framebuf; -++ unsigned int frame_size; -++ unsigned int page_order; -++ wait_queue_head_t wait_queue; -++ struct cim_desc frame_desc __attribute__ ((aligned (16))); -++}; -++ -++// global -++static struct cim_device *cim_dev; -++ -++/*========================================================================== -++ * CIM init routines -++ *========================================================================*/ -++ -++static void cim_config(cim_config_t *c) -++{ -++ REG_CIM_CFG = c->cfg; -++ REG_CIM_CTRL = c->ctrl; -++ // Set the master clock output -++#if defined(CONFIG_SOC_JZ4730) -++ __cim_set_master_clk(__cpm_get_sclk(), c->mclk); -++#elif defined(CONFIG_SOC_JZ4740) || defined(CONFIG_SOC_JZ4750) -++ __cim_set_master_clk(__cpm_get_hclk(), c->mclk); -++#else -++ __cim_set_master_clk(__cpm_get_sclk(), c->mclk); -++#endif -++ // Enable sof, eof and stop interrupts -++ __cim_enable_sof_intr(); -++ __cim_enable_eof_intr(); -++ __cim_enable_stop_intr(); -++} -++ -++/*========================================================================== -++ * CIM start/stop operations -++ *========================================================================*/ -++ -++static int cim_start_dma(char *ubuf) -++{ -++ __cim_disable(); -++ -++ dma_cache_wback((unsigned long)cim_dev->framebuf, (2 ^ (cim_dev->page_order)) * 4096); -++ -++ // set the desc addr -++ __cim_set_da(virt_to_phys(&(cim_dev->frame_desc))); -++ -++ __cim_clear_state(); // clear state register -++ __cim_reset_rxfifo(); // resetting rxfifo -++ __cim_unreset_rxfifo(); -++ __cim_enable_dma(); // enable dma -++ -++ // start -++ __cim_enable(); -++ -++ // wait for interrupts -++ interruptible_sleep_on(&cim_dev->wait_queue); -++ -++ // copy frame data to user buffer -++ memcpy(ubuf, cim_dev->framebuf, cim_dev->frame_size); -++ -++ return cim_dev->frame_size; -++} -++ -++static void cim_stop(void) -++{ -++ __cim_disable(); -++ __cim_clear_state(); -++} -++ -++/*========================================================================== -++ * Framebuffer allocation and destroy -++ *========================================================================*/ -++ -++static void cim_fb_destroy(void) -++{ -++ if (cim_dev->framebuf) { -++ free_pages((unsigned long)(cim_dev->framebuf), cim_dev->page_order); -++ cim_dev->framebuf = NULL; -++ } -++} -++ -++static int cim_fb_alloc(void) -++{ -++ cim_dev->frame_size = img_width * img_height * (img_bpp/8); -++ cim_dev->page_order = get_order(cim_dev->frame_size); -++ -++ /* frame buffer */ -++ cim_dev->framebuf = (unsigned char *)__get_free_pages(GFP_KERNEL, cim_dev->page_order); -++ if ( !(cim_dev->framebuf) ) { -++ return -ENOMEM; -++ } -++ -++ cim_dev->frame_desc.nextdesc = virt_to_phys(&(cim_dev->frame_desc)); -++ cim_dev->frame_desc.framebuf = virt_to_phys(cim_dev->framebuf); -++ cim_dev->frame_desc.frameid = 0x52052018; -++ cim_dev->frame_desc.dmacmd = CIM_CMD_EOFINT | CIM_CMD_STOP | (cim_dev->frame_size >> 2); // stop after capturing a frame -++ -++ dma_cache_wback((unsigned long)(&(cim_dev->frame_desc)), 16); -++ -++ return 0; -++} -++ -++/*========================================================================== -++ * File operations -++ *========================================================================*/ -++ -++static int cim_open(struct inode *inode, struct file *filp); -++static int cim_release(struct inode *inode, struct file *filp); -++static ssize_t cim_read(struct file *filp, char *buf, size_t size, loff_t *l); -++static ssize_t cim_write(struct file *filp, const char *buf, size_t size, loff_t *l); -++static int cim_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -++ -++static struct file_operations cim_fops = -++{ -++ open: cim_open, -++ release: cim_release, -++ read: cim_read, -++ write: cim_write, -++ ioctl: cim_ioctl -++}; -++ -++static int cim_open(struct inode *inode, struct file *filp) -++{ -++ try_module_get(THIS_MODULE); -++ return 0; -++} -++ -++static int cim_release(struct inode *inode, struct file *filp) -++{ -++ cim_stop(); -++ -++ module_put(THIS_MODULE); -++ return 0; -++} -++ -++static ssize_t cim_read(struct file *filp, char *buf, size_t size, loff_t *l) -++{ -++ if (size < cim_dev->frame_size) -++ return -EINVAL; -++ -++ return cim_start_dma(buf); -++} -++ -++static ssize_t cim_write(struct file *filp, const char *buf, size_t size, loff_t *l) -++{ -++ printk("cim error: write is not implemented\n"); -++ return -1; -++} -++ -++static int cim_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -++{ -++ switch (cmd) { -++ case IOCTL_SET_IMG_PARAM: -++ { -++ img_param_t i; -++ -++ if (copy_from_user((void *)&i, (void *)arg, sizeof(img_param_t))) -++ return -EFAULT; -++ -++ img_width = i.width; -++ img_height = i.height; -++ img_bpp = i.bpp; -++ -++ if ((img_width * img_height * img_bpp/8) > MAX_FRAME_SIZE) { -++ /* realloc the buffer */ -++ cim_fb_destroy(); -++ if (cim_fb_alloc() < 0) -++ return -ENOMEM; -++ } -++ -++ cim_dev->frame_size = img_width * img_height * (img_bpp/8); -++ -++ cim_dev->frame_desc.dmacmd = CIM_CMD_EOFINT | CIM_CMD_STOP | (cim_dev->frame_size >> 2); // stop after capturing a frame -++ -++ dma_cache_wback((unsigned long)(&(cim_dev->frame_desc)), 16); -++ -++ break; -++ } -++ case IOCTL_CIM_CONFIG: -++ { -++ cim_config_t c; -++ -++ if (copy_from_user((void *)&c, (void *)arg, sizeof(cim_config_t))) -++ return -EFAULT; -++ -++ cim_config(&c); -++ -++ break; -++ } -++ default: -++ printk("Not supported command: 0x%x\n", cmd); -++ return -EINVAL; -++ break; -++ } -++ return 0; -++} -++ -++/*========================================================================== -++ * Interrupt handler -++ *========================================================================*/ -++ -++static irqreturn_t cim_irq_handler(int irq, void *dev_id) -++{ -++ u32 state = REG_CIM_STATE; -++#if 0 -++ if (state & CIM_STATE_DMA_EOF) { -++ wake_up_interruptible(&cim_dev->wait_queue); -++ } -++#endif -++ if (state & CIM_STATE_DMA_STOP) { -++ // Got a frame, wake up wait routine -++ wake_up_interruptible(&cim_dev->wait_queue); -++ } -++ -++ // clear status flags -++ REG_CIM_STATE = 0; -++ return IRQ_HANDLED; -++} -++ -++/*========================================================================== -++ * Module init and exit -++ *========================================================================*/ -++ -++static int __init cim_init(void) -++{ -++ struct cim_device *dev; -++ int ret; -++ -++ /* allocate device */ -++ dev = kmalloc(sizeof(struct cim_device), GFP_KERNEL); -++ if (!dev) return -ENOMEM; -++ -++ /* record device */ -++ cim_dev = dev; -++ -++ /* allocate a frame buffer */ -++ if (cim_fb_alloc() < 0) { -++ kfree(dev); -++ return -ENOMEM; -++ } -++ -++ init_waitqueue_head(&dev->wait_queue); -++ -++ ret = jz_register_chrdev(CIM_MINOR, CIM_NAME, &cim_fops, dev); -++ if (ret < 0) { -++ cim_fb_destroy(); -++ kfree(dev); -++ return ret; -++ } -++ -++ if ((ret = request_irq(IRQ_CIM, cim_irq_handler, IRQF_DISABLED, -++ CIM_NAME, dev))) { -++ cim_fb_destroy(); -++ kfree(dev); -++ printk(KERN_ERR "CIM could not get IRQ"); -++ return ret; -++ } -++ -++ printk("JzSOC Camera Interface Module (CIM) driver registered\n"); -++ -++ return 0; -++} -++ -++static void __exit cim_exit(void) -++{ -++ free_irq(IRQ_CIM, cim_dev); -++ jz_unregister_chrdev(CIM_MINOR, CIM_NAME); -++ cim_fb_destroy(); -++ kfree(cim_dev); -++} -++ -++module_init(cim_init); -++module_exit(cim_exit); -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/cim.h linux-2.6.24.7/drivers/char/jzchar/cim.h -+--- linux-2.6.24.7.old/drivers/char/jzchar/cim.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/cim.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,36 @@ -++/* -++ * JzSOC CIM driver -++ * -++ * Copyright (C) 2005 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ * GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ */ -++ -++#ifndef __CIM_H__ -++#define __CIM_H__ -++ -++typedef struct -++{ -++ u32 width; -++ u32 height; -++ u32 bpp; -++} IMG_PARAM; -++ -++/* -++ * IOCTL_XXX commands -++ */ -++#define IOCTL_SET_IMG_PARAM 0 // arg type: IMG_PARAM * -++ -++#endif /* __CIM_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/jz_ow.c linux-2.6.24.7/drivers/char/jzchar/jz_ow.c -+--- linux-2.6.24.7.old/drivers/char/jzchar/jz_ow.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/jz_ow.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,497 @@ -++/* -++ * linux/drivers/char/jzchar/jz_ow.c -++ * -++ * One Wire Bus test driver -++ * -++ * Copyright (C) 2006 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "jzchars.h" -++ -++#define OW_CPU_READ_ROM 1 -++#define OW_INTC_READ_ROM 1 -++#define OW_CPU_SEARCH_ROM 0 -++#define OW_INTC_SEARCH_ROM 0 -++ -++#define OW_DEBUG 0 -++#if OW_DEBUG -++#define OWI_MAX 10 -++static char CFG[OWI_MAX]; -++static char CTL[OWI_MAX]; -++static char STS[OWI_MAX]; -++static char DAT[OWI_MAX]; -++static char DIV[OWI_MAX]; -++static void owi_register_dump(int i) -++{ -++ CFG[i]= REG_OWI_CFG; -++ CTL[i]= REG_OWI_CTL; -++ STS[i]= REG_OWI_STS; -++ DAT[i]= REG_OWI_DAT; -++ DIV[i]= REG_OWI_DIV; -++} -++static void owi_register_print(int i) -++{ -++ printk(" REG_OWI_CFG: 0x%08x\n", CFG[i]); -++ printk(" REG_OWI_CTL: 0x%08x\n", CTL[i]); -++ printk(" REG_OWI_STS: 0x%08x\n", STS[i]); -++ printk(" REG_OWI_DAT: 0x%08x\n", DAT[i]); -++ printk(" REG_OWI_DIV: 0x%08x\n", DIV[i]); -++} -++#endif -++ -++static DECLARE_WAIT_QUEUE_HEAD (ow_wait_queue); -++ -++/* -++ * fops routines -++ */ -++static int ow_open(struct inode *inode, struct file *filp); -++static int ow_release(struct inode *inode, struct file *filp); -++static ssize_t ow_read(struct file *filp, char *buf, size_t size, loff_t *l); -++static ssize_t ow_write(struct file *filp, const char *buf, size_t size, loff_t *l); -++static int ow_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -++ -++static void do_ow_rddata(void); -++static void do_ow_wrdata(void); -++static void do_ow_wr1rd(void); -++static void do_ow_wr0(void); -++static void do_ow_rst(void); -++ -++static void do_interrupt_mode_test(void); -++static void do_cpu_mode_test(void); -++ -++static struct file_operations ow_fops = -++{ -++ open: ow_open, -++ release: ow_release, -++ read: ow_read, -++ write: ow_write, -++ ioctl: ow_ioctl, -++}; -++ -++static int ow_open(struct inode *inode, struct file *filp) -++{ -++ try_module_get(THIS_MODULE); -++ return 0; -++} -++ -++static int ow_release(struct inode *inode, struct file *filp) -++{ -++ module_put(THIS_MODULE); -++ return 0; -++} -++ -++static ssize_t ow_read(struct file *filp, char *buf, size_t size, loff_t *l) -++{ -++ printk("OW: read is not implemented\n"); -++ return -1; -++} -++ -++static ssize_t ow_write(struct file *filp, const char *buf, size_t size, loff_t *l) -++{ -++ printk("ow: write is not implemented\n"); -++ return -1; -++} -++ -++static int ow_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -++{ -++ int ret = 0; -++ switch (cmd) { -++ -++ default: -++ printk("Not supported command: 0x%x\n", cmd); -++ return -EINVAL; -++ break; -++ } -++ return ret; -++} -++ -++static void do_ow_rddata(void) -++{ -++ __owi_clr_sts(); -++ __owi_set_rddata(); -++ __owi_enable_ow_ops(); -++} -++ -++static void do_ow_wrdata(void) -++{ -++ __owi_clr_sts(); -++ __owi_set_wrdata(); -++ __owi_enable_ow_ops(); -++} -++ -++static void do_ow_wr1rd(void) -++{ -++ __owi_clr_sts(); -++ __owi_set_wr1rd(); -++ __owi_enable_ow_ops(); -++} -++ -++static void do_ow_wr0(void) -++{ -++ __owi_clr_sts(); -++ __owi_set_wr0(); -++ __owi_enable_ow_ops(); -++} -++ -++static void do_ow_rst(void) -++{ -++ __owi_clr_sts(); -++ __owi_set_rst(); -++ __owi_enable_ow_ops(); -++} -++ -++static irqreturn_t ow_interrupt(int irq, void *dev_id) -++{ -++ __owi_clr_sts(); -++ wake_up(&ow_wait_queue); -++ -++ return IRQ_HANDLED; -++} -++ -++static void ow_intcm_read_rom(char *rom) -++{ -++ int i; -++ -++ __owi_select_regular_mode(); -++ REG_OWI_DIV = 23; -++ __owi_clr_sts(); -++ __intc_unmask_irq(IRQ_OWI); -++ __owi_enable_all_interrupts(); -++ -++ do_ow_rst(); -++ sleep_on(&ow_wait_queue); -++ -++ REG_OWI_DAT = 0x33; -++ do_ow_wrdata(); -++ sleep_on(&ow_wait_queue); -++ -++ for(i=0; i<8; i++){ -++ do_ow_rddata(); -++ sleep_on(&ow_wait_queue); -++ rom[i] = REG_OWI_DAT; -++ } -++ __intc_mask_irq(IRQ_OWI); -++} -++ -++static void ow_intcm_search_rom(void) -++{ -++ int i, j; -++ int normal, reverse; -++#if 1 -++ unsigned char rom[8]={0x01, 0xf9, 0x35, 0x53, 0x11, 0x00, 0x00, 0x3e}; -++#else -++ unsigned char rom[8]={0x01, 0xd8, 0x10, 0x02, 0x10, 0x00, 0x00, 0x22}; -++#endif -++ __owi_select_regular_mode(); -++ REG_OWI_DIV = __cpm_get_extalclk()/1000000 - 1; -++ __owi_clr_sts(); -++ __intc_unmask_irq(IRQ_OWI); -++ __owi_enable_all_interrupts(); -++ -++ /* reset */ -++ do_ow_rst(); -++ sleep_on(&ow_wait_queue); -++ -++ /* send search ROM command */ -++ REG_OWI_DAT = 0xf0; -++ do_ow_wrdata(); -++ sleep_on(&ow_wait_queue); -++ -++ for( i=0; i<8; i++){ -++ for (j=0; j<8; j++){ -++ do_ow_wr1rd(); -++ sleep_on(&ow_wait_queue); -++ normal = ( __owi_get_rdst() !=0); -++ printk("normal: %d\n",normal); -++ -++ do_ow_wr1rd(); -++ sleep_on(&ow_wait_queue); -++ reverse = ( __owi_get_rdst() !=0); -++ printk("reverse: %d\n",reverse); -++ -++ if(normal ==1 && reverse ==1){ -++ printk("Search rom INTC mode: 11 NO device found\n"); -++ __intc_mask_irq(IRQ_OWI); -++ return; -++ } -++#if 1 -++ if ( (rom[i]>>j) & 1 ){ -++ printk("write 1\n"); -++ do_ow_wr1rd(); -++ sleep_on(&ow_wait_queue); -++ } -++ else{ -++ printk("write 0\n"); -++ do_ow_wr0(); -++ sleep_on(&ow_wait_queue); -++ } -++ -++#else -++ if(normal ==0 && reverse ==0){ -++ if (!((rom[i]>>j) & 1) ){ -++ printk("write 1\n"); -++ do_ow_wr1rd(); -++ sleep_on(&ow_wait_queue); -++ } -++ else{ -++ printk("write 0\n"); -++ do_ow_wr0(); -++ sleep_on(&ow_wait_queue); -++ } -++ }else{ -++ -++ if(normal ==0){ -++ printk("write 0\n"); -++ do_ow_wr0(); -++ sleep_on(&ow_wait_queue); -++ } -++ if(normal ==1){ -++ printk("write 1\n"); -++ do_ow_wr1rd(); -++ sleep_on(&ow_wait_queue); -++ } -++ } -++#endif -++ -++ } -++ printk("\n\n"); -++ } -++ -++ printk("\nSearch rom INTC mode: device found SUCCESSFULLY\n"); -++ __intc_mask_irq(IRQ_OWI); -++ -++} -++ -++static void ow_cpum_read_rom(char *rom) -++{ -++ int i; -++ -++ __owi_select_regular_mode(); -++ REG_OWI_DIV = __cpm_get_extalclk()/1000000 - 1; -++ __owi_clr_sts(); -++ __owi_disable_all_interrupts(); -++ -++ do_ow_rst(); -++ __owi_wait_ops_rdy(); -++ -++ if(!__owi_get_sts_pst()) -++ printk("read rom no device found\n"); -++ -++ REG_OWI_DAT = 0x33; -++ do_ow_wrdata(); -++ __owi_wait_ops_rdy(); -++ -++ for(i=0; i<8; i++){ -++ do_ow_rddata(); -++ __owi_wait_ops_rdy(); -++ rom[i] = REG_OWI_DAT; -++ } -++} -++ -++ -++static void ow_comm_bit(unsigned comm) -++{ -++ int i; -++ for(i=0; i<8; i++){ -++ if ( comm & (1<>j) & 1 ){ -++ printk("write 1\n"); -++ do_ow_wr1rd(); -++ while(!__owi_get_sts_bit_rdy()) ; -++ } -++ else{ -++ printk("write 0\n"); -++ do_ow_wr0(); -++ while(!__owi_get_sts_bit_rdy()) ; -++ } -++ -++#else -++ if(normal ==0 && reverse ==0){ -++ if (!((rom[i]>>j) & 1) ){ -++ printk("write 1\n"); -++ do_ow_wr1rd(); -++ while(!__owi_get_sts_bit_rdy()) ; -++ } -++ else{ -++ printk("write 0\n"); -++ do_ow_wr0(); -++ while(!__owi_get_sts_bit_rdy()) ; -++ } -++ }else{ -++ -++ if(normal ==0){ -++ printk("write 0\n"); -++ do_ow_wr0(); -++ while(!__owi_get_sts_bit_rdy()) ; -++ } -++ if(normal ==1){ -++ printk("write 1\n"); -++ do_ow_wr1rd(); -++ while(!__owi_get_sts_bit_rdy()) ; -++ } -++ } -++#endif -++ -++ } -++ printk("\n\n"); -++ } -++ printk("\nSearch rom CPU mode: device found SUCCESSFULLY\n"); -++} -++ -++static void do_interrupt_mode_test(void) -++{ -++ int ret, i; -++ unsigned char rom[8]; -++ -++ /* interrupt mode */ -++ ret = request_irq(IRQ_OWI, ow_interrupt, IRQF_DISABLED, -++ "JZ_OWI", NULL); -++ if(ret) -++ printk("failed irq \n"); -++ -++#if OW_INTC_READ_ROM -++ ow_intcm_read_rom(rom); -++ printk("\n\nAfter intc mode read ROM ops: \n"); -++ printk("ROM: "); -++ for(i=0; i<8; i++) -++ printk("0x%02x,",rom[i]); -++#endif -++ -++#if OW_INTC_SEARCH_ROM -++ ow_intcm_search_rom(); -++#endif -++ -++} -++ -++static void do_cpu_mode_test(void) -++{ -++ -++#if OW_CPU_READ_ROM -++ int i; -++ unsigned char rom[8]; -++ -++ ow_cpum_read_rom(rom); -++ printk("\n\nAfter CPU mode read ROM ops: \n"); -++ printk("ROM: "); -++ for(i=0; i<8; i++) -++ printk("0x%02x,",rom[i]); -++#endif -++ -++#if OW_CPU_SEARCH_ROM -++ ow_cpum_search_rom(); -++#endif -++} -++ -++/* -++ * Module init and exit -++ */ -++static int __init ow_init(void) -++{ -++ int ret; -++ -++ ret = jz_register_chrdev(OW_MINOR, "ow", &ow_fops, NULL); -++ if (ret < 0) { -++ return ret; -++ } -++ __gpio_as_func1(153); -++ -++ REG_OWI_CFG=0; -++ REG_OWI_CTL=0; -++ REG_OWI_STS=0; -++ REG_OWI_DAT=0; -++ REG_OWI_DIV=0; -++ -++ do_interrupt_mode_test(); -++ do_cpu_mode_test(); -++ -++ printk("Ingenic OW driver registered\n"); -++ -++ return 0; -++} -++ -++static void __exit ow_exit(void) -++{ -++ free_irq(IRQ_OWI, NULL); -++ jz_unregister_chrdev(OW_MINOR, "ow"); -++} -++ -++module_init(ow_init); -++module_exit(ow_exit); -++ -++MODULE_AUTHOR("Yurong Tan"); -++MODULE_DESCRIPTION("One Wire Bus test Driver"); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/jz_ts.c linux-2.6.24.7/drivers/char/jzchar/jz_ts.c -+--- linux-2.6.24.7.old/drivers/char/jzchar/jz_ts.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/jz_ts.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,443 @@ -++/* -++ * jz_ts.c -++ * -++ * Touch screen driver for the Ingenic JZ47XX. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "jz_ts.h" -++ -++MODULE_AUTHOR("Peter Wei "); -++MODULE_DESCRIPTION("Ingenic Touch Screen Driver"); -++MODULE_LICENSE("GPL"); -++ -++#define TS_NAME "jz-ts" -++#define TS_MINOR 16 /* MAJOR: 10, MINOR: 16 */ -++#define PFX TS_NAME -++ -++//#define JZ_TS_DEBUG -++ -++#ifdef JZ_TS_DEBUG -++#define dbg(format, arg...) printk(KERN_DEBUG PFX ": " format "\n" , ## arg) -++#else -++#define dbg(format, arg...) do {} while (0) -++#endif -++#define err(format, arg...) printk(KERN_ERR PFX ": " format "\n" , ## arg) -++#define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg) -++#define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg) -++ -++static struct jz_ts_t jz_ts; -++ -++unsigned int (*codec_read_battery)(void) = NULL; -++ -++// hold the spinlock before calling. -++static void event_add(struct jz_ts_t *ts, struct ts_event *event) -++{ -++ unsigned long flags; -++ -++ spin_lock_irqsave(&ts->lock, flags); -++ -++ // add this event to the event queue -++ ts->event_buf[ts->nextIn] = *event; -++ ts->nextIn = (ts->nextIn + 1) & (EVENT_BUFSIZE - 1); -++ if (ts->event_count < EVENT_BUFSIZE) { -++ ts->event_count++; -++ } else { -++ // throw out the oldest event -++ ts->nextOut = (ts->nextOut + 1) & (EVENT_BUFSIZE - 1); -++ } -++ -++ spin_unlock_irqrestore(&ts->lock, flags); -++ -++ // async notify -++ if (ts->fasync) -++ kill_fasync(&ts->fasync, SIGIO, POLL_IN); -++ // wake up any read call -++ if (waitqueue_active(&ts->wait)) -++ wake_up_interruptible(&ts->wait); -++} -++ -++static int event_pull(struct jz_ts_t *ts, struct ts_event *event) -++{ -++ unsigned long flags; -++ int ret; -++ -++ spin_lock_irqsave(&ts->lock, flags); -++ ret = ts->event_count; -++ if (ts->event_count) { -++ *event = ts->event_buf[ts->nextOut]; -++ ts->nextOut = (ts->nextOut + 1) & (EVENT_BUFSIZE - 1); -++ ts->event_count--; -++ } -++ spin_unlock_irqrestore(&ts->lock, flags); -++ -++ return ret; -++} -++ -++static int pen_is_down = 0; -++ -++static irqreturn_t pendown_interrupt(int irq, void * dev_id) -++{ -++ struct jz_ts_t* ts = &jz_ts; -++ struct ts_event event; -++ -++ dbg("pen down"); -++#if defined(CONFIG_SOC_JZ4740) -++ if (ts->sleeping) { -++ ts->sleeping = 0; -++ ts_data_ready(); -++ return IRQ_HANDLED; -++ } -++#endif -++ spin_lock(&ts->lock); -++ -++ if (ts->irq_enabled) { -++ ts->irq_enabled = 0; -++ } -++ else -++ ts->irq_enabled = 1; -++ -++ -++ if (pen_is_down) -++ pen_is_down = 0; -++ else -++ pen_is_down = 1; -++ -++ // callback routine to clear irq status -++ ts_irq_callback(); -++ -++ if ( (pen_is_down == 0)){ -++ del_timer(&ts->acq_timer); -++ spin_unlock(&ts->lock); -++ event.x = event.y = event.pressure = 0; -++ event.status = PENUP; -++ ts->first_read = 0; -++ event_add(ts, &event); -++ return IRQ_HANDLED; -++ } -++ -++ if ( (pen_is_down == 1)) -++ { -++ ts->acq_timer.expires = jiffies + HZ / 100; -++ del_timer(&ts->acq_timer); -++ ts->first_read = 1; -++ add_timer(&ts->acq_timer); -++ spin_unlock(&ts->lock); -++ } -++ return IRQ_HANDLED; -++} -++ -++ -++/* -++ * Raw X,Y,pressure acquisition timer function. It gets scheduled -++ * only while pen is down. Its duration between calls is the polling -++ * rate. -++ */ -++static void -++jz_acq_timer(unsigned long data) -++{ -++ struct jz_ts_t *ts = (struct jz_ts_t *)data; -++ struct ts_event event; -++ int pen_was_down = ts->pen_is_down; -++ -++ spin_lock(&ts->lock); -++ -++ if (PenIsDown()) { -++ -++ ts->pen_is_down = 1; -++ -++ if (AcquireEvent(ts, &event)) // check event is valid or not? -++ event_add(ts, &event); -++ -++ // schedule next acquire -++ ts->acq_timer.expires = jiffies + HZ / 100; -++ del_timer(&ts->acq_timer); -++ add_timer(&ts->acq_timer); -++ } else { -++ -++ if (!ts->irq_enabled) { -++ ts->irq_enabled = 1; -++ } -++ ts->pen_is_down = 0; -++ if (pen_was_down) { -++ event.x = event.y = event.pressure = 0; -++ event.status = PENUP; -++ event_add(ts, &event); -++ } -++ } -++ -++ spin_unlock(&ts->lock); -++} -++ -++/* +++++++++++++ Read battery voltage routine ++++++++++++++*/ -++ -++unsigned int jz_read_battery(void) -++{ -++ unsigned int v = 0; -++ struct jz_ts_t *ts = &jz_ts; -++ -++ spin_lock(&ts->lock); -++ -++ if (codec_read_battery) -++ v = codec_read_battery(); -++ -++ spin_unlock(&ts->lock); -++ -++ return v; -++} -++ -++/* +++++++++++++ File operations ++++++++++++++*/ -++ -++static int -++jz_fasync(int fd, struct file *filp, int mode) -++{ -++ struct jz_ts_t *ts = (struct jz_ts_t *)filp->private_data; -++ return fasync_helper(fd, filp, mode, &ts->fasync); -++} -++ -++ -++static unsigned int -++jz_poll(struct file * filp, poll_table * wait) -++{ -++ struct jz_ts_t* ts = (struct jz_ts_t*)filp->private_data; -++ poll_wait(filp, &ts->wait, wait); -++ if (ts->event_count) -++ return POLLIN | POLLRDNORM; -++ return 0; -++} -++ -++static ssize_t -++jz_read(struct file * filp, char * buffer, size_t count, loff_t * ppos) -++{ -++ DECLARE_WAITQUEUE(wait, current); -++ struct jz_ts_t* ts = (struct jz_ts_t*)filp->private_data; -++ char *ptr = buffer; -++ struct ts_event event; -++ int err = 0; -++ -++ dbg("jz_read"); -++ -++ add_wait_queue(&ts->wait, &wait); -++ while (count >= sizeof(struct ts_event)) { -++ err = -ERESTARTSYS; -++ if (signal_pending(current)) -++ break; -++ -++ -++ if (event_pull(ts, &event)) { -++ err = copy_to_user(ptr, &event, -++ sizeof(struct ts_event)); -++ if (err) -++ break; -++ ptr += sizeof(struct ts_event); -++ count -= sizeof(struct ts_event); -++ } else { -++ set_current_state(TASK_INTERRUPTIBLE); -++ err = -EAGAIN; -++ if (filp->f_flags & O_NONBLOCK) -++ break; -++ schedule(); -++ } -++ } -++ -++ current->state = TASK_RUNNING; -++ remove_wait_queue(&ts->wait, &wait); -++ -++ return ptr == buffer ? err : ptr - buffer; -++} -++ -++ -++static int -++jz_open(struct inode * inode, struct file * filp) -++{ -++ struct jz_ts_t *ts; -++ int retval; -++ -++ dbg("open ts device"); -++ filp->private_data = ts = &jz_ts; -++ -++ spin_lock(&ts->lock); -++ -++ ts->pen_is_down = 0; // start with pen up -++ ts->sleeping = 0; -++ // flush event queue -++ ts->nextIn = ts->nextOut = ts->event_count = 0; -++ -++ // Init acquisition timer function -++ init_timer(&ts->acq_timer); -++ ts->acq_timer.function = jz_acq_timer; -++ ts->acq_timer.data = (unsigned long)ts; -++ -++ ts->irq_enabled = 1; -++ -++ spin_unlock(&ts->lock); -++ -++ /* Since ts interrupt can happen immediately after request_irq, -++ * we wait until we've completed init of all relevent driver -++ * state variables. Now we grab the PenDown IRQ -++ */ -++ retval = ts_request_irq(&ts->pendown_irq, pendown_interrupt, TS_NAME, ts); -++ if (retval) { -++ err("unable to get PenDown IRQ %d", ts->pendown_irq); -++ return retval; -++ } -++ -++ try_module_get(THIS_MODULE); -++ return 0; -++} -++ -++static int -++jz_release(struct inode * inode, struct file * filp) -++{ -++ struct jz_ts_t* ts = (struct jz_ts_t*)filp->private_data; -++ -++ ts_free_irq(ts); -++ jz_fasync(-1, filp, 0); -++ del_timer_sync(&ts->acq_timer); -++ -++ module_put(THIS_MODULE); -++ return 0; -++} -++ -++static int jz_ioctl(struct inode *inode, struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) -++{ -++ struct txy { -++ int minx; -++ int miny; -++ int maxx; -++ int maxy; -++ }; -++ -++ struct txy ch; -++ -++ /* -++ * Switch according to the ioctl called -++ */ -++ switch (ioctl_num) -++ { -++ case IOCTL_SET_MSG: -++ jz_ts.filter=1; -++ break; -++ case IOCTL_SET_NUM: -++ if (copy_from_user((void *)&ch, (void *)ioctl_param, sizeof(ch))) -++ return -EFAULT; -++ jz_ts.minx = ch.minx; -++ jz_ts.miny = ch.miny; -++ jz_ts.maxx = ch.maxx; -++ jz_ts.maxy = ch.maxy; -++ break; -++ } -++ -++ return 0; -++} -++ -++static struct file_operations ts_fops = { -++ owner: THIS_MODULE, -++ read: jz_read, -++ poll: jz_poll, -++ fasync: jz_fasync, -++ ioctl: jz_ioctl, -++ open: jz_open, -++ release: jz_release, -++}; -++ -++/* +++++++++++++ End File operations ++++++++++++++*/ -++ -++static int __init minx_setup(char *str) -++{ -++ int i; -++ -++ if (get_option(&str,&i)) jz_ts.minx = i; -++ jz_ts.filter=i; -++ return 1; -++} -++ -++__setup("ts_minx=", minx_setup); -++ -++static int __init miny_setup(char *str) -++{ -++ int i; -++ if (get_option(&str,&i)) jz_ts.miny = i; -++ return 1; -++} -++ -++__setup("ts_miny=", miny_setup); -++ -++static int __init maxx_setup(char *str) -++{ -++ int i; -++ if (get_option(&str,&i)) jz_ts.maxx = i; -++ return 1; -++} -++ -++__setup("ts_maxx=", maxx_setup); -++ -++static int __init maxy_setup(char *str) -++{ -++ int i; -++ if (get_option(&str,&i)) jz_ts.maxy = i; -++ return 1; -++} -++ -++__setup("ts_maxy=", maxy_setup); -++ -++static int __init printraw_setup(char *str) -++{ -++ if (str) -++ jz_ts.prints = 1; -++ -++ return 0; -++} -++ -++__setup("ts_debug", printraw_setup); -++ -++ -++static struct miscdevice jz_ts_dev = { -++ minor: TS_MINOR, -++ name: TS_NAME, -++ fops: &ts_fops, -++}; -++ -++static int __init jzts_init_module(void) -++{ -++ struct jz_ts_t *ts = &jz_ts; -++ int ret; -++ -++ if ((ret = misc_register(&jz_ts_dev)) < 0) { -++ err("can't register misc device"); -++ return ret; -++ } -++ -++// memset(ts, 0, sizeof(struct jz_ts_t)); -++ init_waitqueue_head(&ts->wait); -++ spin_lock_init(&ts->lock); -++ -++ printk("Jz generic touch screen driver registered\n"); -++ -++ return 0; -++} -++ -++static void jzts_cleanup_module(void) -++{ -++ misc_deregister(&jz_ts_dev); -++} -++ -++module_init(jzts_init_module); -++module_exit(jzts_cleanup_module); -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/jz_ts.h linux-2.6.24.7/drivers/char/jzchar/jz_ts.h -+--- linux-2.6.24.7.old/drivers/char/jzchar/jz_ts.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/jz_ts.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,54 @@ -++#ifndef __JZ_TS_H__ -++#define __JZ_TS_H__ -++ -++/* -++ * IOCTL commands -++ */ -++#define IOCTL_SET_MSG 0 -++#define IOCTL_SET_NUM 1 -++ -++ -++/* -++ * TS Event type -++ */ -++struct ts_event { -++ u16 status; -++ u16 x; -++ u16 y; -++ u16 pressure; -++ u16 pad; -++}; -++ -++/* TS event status */ -++#define PENUP 0x00 -++#define PENDOWN 0x01 -++ -++#define EVENT_BUFSIZE 64 // must be power of two -++ -++struct jz_ts_t { -++ int pendown_irq; // IRQ of pendown interrupt -++ int pen_is_down; // 1 = pen is down, 0 = pen is up -++ int irq_enabled; -++ struct ts_event event_buf[EVENT_BUFSIZE];// The event queue -++ int nextIn, nextOut; -++ int event_count; -++ struct fasync_struct *fasync; // asynch notification -++ struct timer_list acq_timer; // Timer for triggering acquisitions -++ wait_queue_head_t wait; // read wait queue -++ spinlock_t lock; -++ int minx, miny, maxx, maxy; -++ int filter, prints; -++ int sleeping; -++ int first_read; -++}; -++ -++extern void ts_enable_irq(void); -++extern void ts_disable_irq(void); -++extern int ts_request_irq(u32 *irq,irqreturn_t (*handler)(int, void *), const char *devname, void *dev_id); -++extern void ts_free_irq(struct jz_ts_t *ts); -++extern int PenIsDown(void); -++extern int AcquireEvent(struct jz_ts_t *ts, struct ts_event *event); -++extern void ts_irq_callback(void); -++extern void ts_data_ready(void); -++ -++#endif /* __JZ_TS_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/jz_tssi.c linux-2.6.24.7/drivers/char/jzchar/jz_tssi.c -+--- linux-2.6.24.7.old/drivers/char/jzchar/jz_tssi.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/jz_tssi.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,457 @@ -++/* -++ * jz_tssi.c -++ * -++ * MPEG2-TS interface driver for the Ingenic JZ47XX. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "jzchars.h" -++ -++#include "jz_tssi.h" -++ -++ -++MODULE_AUTHOR("Lucifer Liu "); -++MODULE_DESCRIPTION("Ingenic MPEG2-TS interface Driver"); -++MODULE_LICENSE("GPL"); -++ -++#define TSSI_NAME "JZ MPEG2-TS SI" -++#define TSSI_MINOR 204 /* MAJOR: 10, MINOR: 16 */ -++#define TSSI_IRQ IRQ_TSSI -++#define PFX TSSI_NAME -++#define RING_BUF_NUM 100 -++ -++#define USE_DMA -++#define TRIG_PIN ( 32 * 2 + 15 ) -++#define DMA_ID_TSSI 5 -++//#define JZ_TSSI_DEBUG -++ -++#ifdef JZ_TSSISI_DEBUG -++#define dbg(format, arg...) printk(KERN_DEBUG PFX ": " format "\n" , ## arg) -++#else -++#define dbg(format, arg...) do {} while (0) -++#endif -++#define err(format, arg...) printk(KERN_ERR PFX ": " format "\n" , ## arg) -++#define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg) -++#define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg) -++ -++static struct jz_tssi_t jz_tssi_g; -++static struct jz_tssi_buf_ring_t jz_tssi_ring_g; -++static int tssi_dma_reinit(int dma_chan, unsigned char *dma_buf, int size); -++ -++static void print_reg( void ) -++{ -++ printk("REG_TSSI_ENA %8x \n ", REG8( TSSI_ENA )); -++ printk("REG_TSSI_CFG %8x \n ", REG16( TSSI_CFG )); -++ printk("REG_TSSI_CTRL %8x \n ", REG8( TSSI_CTRL )); -++ printk("REG_TSSI_STAT %8x \n ", REG8( TSSI_STAT )); -++ printk("REG_TSSI_FIFO %8x \n ", REG32( TSSI_FIFO )); -++ printk("REG_TSSI_PEN %8x \n ", REG32( TSSI_PEN )); -++ printk("REG_TSSI_PID0 %8x \n ", REG32( TSSI_PID0 )); -++ printk("REG_TSSI_PID1 %8x \n ", REG32( TSSI_PID1 )); -++ printk("REG_TSSI_PID2 %8x \n ", REG32( TSSI_PID2 )); -++ printk("REG_TSSI_PID3 %8x \n ", REG32( TSSI_PID3 )); -++ printk("REG_TSSI_PID4 %8x \n ", REG32( TSSI_PID4 )); -++ printk("REG_TSSI_PID5 %8x \n ", REG32( TSSI_PID5 )); -++ printk("REG_TSSI_PID6 %8x \n ", REG32( TSSI_PID6 )); -++ printk("REG_TSSI_PID7 %8x \n ", REG32( TSSI_PID7 )); -++} -++ -++void dump_dma_channel(unsigned int dmanr) -++{ -++ printk("DMA%d Registers:\n", dmanr); -++ printk(" DMACR = 0x%8x\n", REG_DMAC_DMACR(0)); -++ printk(" DSAR = 0x%8x\n", REG_DMAC_DSAR(dmanr)); -++ printk(" DTAR = 0x%8x\n", REG_DMAC_DTAR(dmanr)); -++ printk(" DTCR = 0x%8x\n", REG_DMAC_DTCR(dmanr)); -++ printk(" DRSR = 0x%8x\n", REG_DMAC_DRSR(dmanr)); -++ printk(" DCCSR = 0x%8x\n", REG_DMAC_DCCSR(dmanr)); -++ printk(" DCMD = 0x%8x\n", REG_DMAC_DCMD(dmanr)); -++ printk(" DDA = 0x%8x\n", REG_DMAC_DDA(dmanr)); -++ printk(" DMADBR = 0x%8x\n", REG_DMAC_DMADBR(1)); -++} -++ -++static int tssi_buf_init( struct jz_tssi_buf_ring_t * ring ) -++{ -++ int i; -++ struct jz_tssi_buf * bp,* ap, *cp; -++ -++ ap = cp = bp = (struct jz_tssi_buf *)kmalloc( sizeof( struct jz_tssi_buf ) ,GFP_KERNEL ); //the first -++ if ( !bp ) { -++ printk("Can not malloc buffer! \n"); -++ return -1; -++ } -++ -++ for ( i = 0; i < RING_BUF_NUM; i ++ ) { -++ bp = ap; -++ bp->buf = (unsigned int *) kmalloc(MPEG2_TS_PACHAGE_SIZE / 4 * sizeof(unsigned int) ,GFP_KERNEL); -++ if ( !bp->buf ) { -++ printk("Can not malloc buffer! \n"); -++ return -1; -++ } -++ bp->index = i; -++ bp->pos = 0; -++ ap = (struct jz_tssi_buf *)kmalloc( sizeof( struct jz_tssi_buf ) ,GFP_KERNEL ); -++ if ( !ap ) { -++ printk("Can not malloc buffer! \n"); -++ return -1; -++ } -++ -++ bp->next = ap; //point to next ! -++ } -++ -++ bp->next = cp; //point loop to first! -++ ring->front = cp; -++ ring->rear = cp; -++ ring->fu_num = 0; -++ kfree(ap); -++ return 0; -++} -++ -++static void tssi_free_buf( struct jz_tssi_buf_ring_t * ring ) -++{ -++ int i; -++ struct jz_tssi_buf * ap; -++ for ( i = 0; i < RING_BUF_NUM; i ++ ) -++ { -++ ap = ring->front; -++ ring->front = ring->front->next; -++ kfree( ap ); -++ } -++} -++ -++#if 0 -++static void tssi_read_fifo(void *dev_id) -++{ -++ struct jz_tssi_t* tssi = ( struct jz_tssi_t* )dev_id; -++ struct jz_tssi_buf_ring_t * ring = tssi->cur_buf; -++ struct jz_tssi_buf *buf = ring->rear; -++ int i; -++#if 0 -++ if ( ring->fu_num > RING_BUF_NUM ) -++ { -++ printk("Ring buffer full ! %d \n",ring->fu_num); -++ return; -++ } -++#endif -++ -++ for ( i = 0; i < 8 ; i ++ ) -++ { -++ ring->front->buf[ring->front->pos++] = REG_TSSI_FIFO; -++ } -++ -++ if ( ring->front->pos >= MPEG2_TS_PACHAGE_SIZE ) -++ { -++ ring->fu_num ++; -++ ring->front = ring->front->next; -++ ring->front->pos = 0; -++ } -++} -++#endif -++ -++static void tssi_config_filting( void ) -++{ -++ __tssi_soft_reset(); -++ __gpio_as_tssi(); -++ __tssi_disable_ovrn_irq(); //use dma ,no need irq -++ __tssi_disable_trig_irq(); -++ __tssi_set_tigger_num( 8 ); //trig is 4 word! -++// __tssi_filter_enable(); -++ __tssi_clear_state(); -++ __tssi_filter_disable(); -++ __tssi_state_clear_overrun(); -++// __tssi_clear_trig_irq_flag(); -++#ifdef USE_DMA -++ __tssi_dma_enable(); -++#else -++ __tssi_dma_disable(); -++#endif -++ -++ __tssi_enable_ovrn_irq(); -++// __tssi_enable_trig_irq(); -++ -++ //set config -++// __tssi_set_bt_1(); -++ __tssi_set_wd_1(); -++ __tssi_set_data_use_data7(); -++ __tssi_set_data_pola_high(); -++// __tssi_select_serail_mode(); -++ __tssi_select_paral_mode(); -++ __tssi_select_clk_fast(); -++ __tssi_select_clk_posi_edge(); -++ __tssi_select_frm_act_high(); -++ __tssi_select_str_act_high(); -++ __tssi_select_fail_act_high(); -++// __tssi_select_fail_act_low(); -++ __tssi_disable_filte_pid0(); //we disable pid0 filter for ever! -++} -++ -++static void tssi_add_pid(int pid_num, int pid) -++{ -++ unsigned int addr ; -++ int n = pid_num / 2, hl = pid_num % 2; -++ if ( hl ) //use high pid, pid1 -++ { -++ addr = TSSI_PID0 + ( n * 4 ); -++ REG32( addr ) |= ( (pid & 0x1fff) << 16 ); //13bit -++ REG_TSSI_PEN |= ( 1 << (16 + n) ); -++ } -++ else //use low pid, pid0 -++ { -++ addr = TSSI_PID0 + ( n * 4 ); -++ REG32( addr ) |= pid & 0x1fff; //13bit -++ REG_TSSI_PEN |= ( 1 << n ); -++ } -++} -++ -++static irqreturn_t tssi_dma_irq(int irq, void * dev_id) -++{ -++ struct jz_tssi_t *tssi = (struct jz_tssi_t *)dev_id; -++ struct jz_tssi_buf_ring_t *buf = tssi->cur_buf; -++ -++ REG_DMAC_DCCSR(tssi->dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ -++ if (__dmac_channel_transmit_end_detected(tssi->dma_chan)) { -++ __dmac_channel_clear_transmit_end(tssi->dma_chan); -++ if ( buf->fu_num < RING_BUF_NUM ) -++ { -++ buf->front = buf->front->next; -++ REG_DMAC_DSAR(tssi->dma_chan) = CPHYSADDR(TSSI_FIFO); -++ REG_DMAC_DTAR(tssi->dma_chan) = CPHYSADDR((unsigned int)buf->front->buf); -++ REG_DMAC_DTCR(tssi->dma_chan) = MPEG2_TS_PACHAGE_SIZE / 32; -++ REG_DMAC_DCCSR(tssi->dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; -++ buf->fu_num ++; -++ } -++ __tssi_clear_state(); -++ } -++ -++ if (__dmac_channel_transmit_halt_detected(tssi->dma_chan)) { -++ printk("DMA HALT\n"); -++ __dmac_channel_clear_transmit_halt(tssi->dma_chan); -++ } -++ -++ if (__dmac_channel_address_error_detected(tssi->dma_chan)) { -++ printk("DMA ADDR ERROR\n"); -++ __dmac_channel_clear_address_error(tssi->dma_chan); -++ } -++ -++ if (__dmac_channel_descriptor_invalid_detected(tssi->dma_chan)) { -++ printk("DMA DESC INVALID\n"); -++ __dmac_channel_clear_descriptor_invalid(tssi->dma_chan); -++ } -++ -++ if (__dmac_channel_count_terminated_detected(tssi->dma_chan)) { -++ printk("DMA CT\n"); -++ __dmac_channel_clear_count_terminated(tssi->dma_chan); -++ } -++ -++ return IRQ_HANDLED; -++} -++ -++static irqreturn_t tssi_interrupt(int irq, void * dev_id) -++{ -++ __intc_mask_irq(TSSI_IRQ); -++#if 1 -++ if ( REG_TSSI_STAT & TSSI_STAT_OVRN ) -++ { -++ printk("tssi over run occur! %x\n",REG8( TSSI_STAT )); -++ __tssi_clear_state(); -++ printk("clear ! %x\n",REG8( TSSI_STAT )); -++ } -++#endif -++ if ( REG_TSSI_STAT & TSSI_STAT_TRIG ) -++ { -++ printk("tssi trig irq occur! \n"); -++ tssi_read_fifo( dev_id ); -++ } -++ -++ __intc_ack_irq(TSSI_IRQ); -++ __intc_unmask_irq(TSSI_IRQ); -++ return IRQ_HANDLED; -++} -++ -++static ssize_t jz_read(struct file * filp, char * buffer, size_t count, loff_t * ppos) -++{ -++ jz_char_dev_t *adev = (jz_char_dev_t *)filp->private_data; -++ struct jz_tssi_t* tssi = (struct jz_tssi_t*)adev->private; -++ struct jz_tssi_buf_ring_t* ring = tssi->cur_buf; -++ -++ int i; -++ -++ count /= MPEG2_TS_PACHAGE_SIZE; -++ -++ if ( count > ring->fu_num ) -++ count = ring->fu_num; -++ -++ for ( i = 0; i < count; i ++ ) -++ { -++ memcpy( buffer + ( i * MPEG2_TS_PACHAGE_SIZE), -++ ring->rear->buf, MPEG2_TS_PACHAGE_SIZE ); -++ ring->rear->pos = 0; -++ ring->rear = ring->rear->next; -++ } -++ ring->fu_num -= count; -++ return count * MPEG2_TS_PACHAGE_SIZE; -++} -++ -++static int tssi_dma_reinit(int dma_chan, unsigned char *dma_buf, int size) -++{ -++ static unsigned int dma_src_phys_addr, dma_dst_phys_addr; -++ REG_DMAC_DMACKE(0) = 0xff; -++ dma_src_phys_addr = CPHYSADDR(TSSI_FIFO); -++ dma_dst_phys_addr = CPHYSADDR((unsigned int)dma_buf); -++ REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = 0; -++ REG_DMAC_DCCSR(dma_chan) = 0; -++ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_TSSIIN; -++ REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr; -++ REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr; -++ REG_DMAC_DTCR(dma_chan) = size / 32; -++ REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TIE; -++ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; -++ REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = DMAC_DMACR_DMAE; /* global DMA enable bit */ -++ return 0; -++} -++ -++static int jz_open(struct inode * inode, struct file * filp) -++{ -++ try_module_get(THIS_MODULE); -++ -++ __tssi_soft_reset(); -++ __intc_mask_irq(TSSI_IRQ); -++ tssi_config_filting(); -++ -++ return 0; -++} -++ -++static int jz_release(struct inode * inode, struct file * filp) -++{ -++ __intc_mask_irq(TSSI_IRQ); -++ module_put(THIS_MODULE); -++ return 0; -++} -++ -++static int jz_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -++{ -++ jz_char_dev_t *adev = (jz_char_dev_t *)file->private_data; -++ struct jz_tssi_t* tssi = (struct jz_tssi_t*)adev->private; -++ -++ switch (cmd) -++ { -++ case IOCTL_TSSI_ENABLE : -++ __intc_ack_irq(TSSI_IRQ); -++ __intc_unmask_irq(TSSI_IRQ); -++ __tssi_enable(); -++ print_reg(); -++ -++ break; -++ case IOCTL_TSSI_DISABLE : -++ __tssi_disable(); -++ -++ break; -++ case IOCTL_TSSI_SOFTRESET : -++ __tssi_soft_reset(); -++ -++ break; -++ case IOCTL_TSSI_ENFILTER : -++ __tssi_filter_enable(); -++ break; -++ case IOCTL_TSSI_DEFILTER : -++ __tssi_filter_disable(); -++ break; -++ case IOCTL_TSSI_ADDPID : //add one pid to filter -++ if ( tssi->pid_num < 15 ) -++ { -++ tssi_add_pid(tssi->pid_num, arg); -++ tssi->pid_num ++ ; -++ } -++ break; -++ -++ case IOCTL_TSSI_FLUSHPID : //set all filting pid to false -++ REG_TSSI_PEN = 0x0; -++ REG_TSSI_PID0 = 0x0; -++ REG_TSSI_PID1 = 0x0; -++ REG_TSSI_PID2 = 0x0; -++ REG_TSSI_PID3 = 0x0; -++ REG_TSSI_PID4 = 0x0; -++ REG_TSSI_PID5 = 0x0; -++ REG_TSSI_PID6 = 0x0; -++ REG_TSSI_PID7 = 0x0; -++ break; -++ -++ case IOCTL_TSSI_INIT_DMA: -++ tssi_dma_reinit(tssi->dma_chan, tssi->cur_buf->front->buf, MPEG2_TS_PACHAGE_SIZE); -++ break; -++ case IOCTL_TSSI_DISABLE_DMA: -++ REG_DMAC_DCCSR(tssi->dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ break; -++ } -++ -++ return 0; -++} -++ -++static struct file_operations tssi_fops = { -++ owner: THIS_MODULE, -++ read: jz_read, -++ poll: NULL, -++ fasync: NULL, -++ ioctl: jz_ioctl, -++ open: jz_open, -++ release: jz_release, -++}; -++ -++static int __init jztssi_init_module(void) -++{ -++ int retval; -++ struct jz_tssi_t *tssi = &jz_tssi_g; -++ -++ __cpm_start_tssi(); -++ __cpm_start_dmac(); -++ tssi_buf_init( &jz_tssi_ring_g ); -++ tssi->cur_buf = &jz_tssi_ring_g; -++ tssi->pid_num = 0; -++ retval = request_irq(TSSI_IRQ, tssi_interrupt, IRQF_DISABLED, TSSI_NAME, &jz_tssi_g); -++ -++ if (retval) { -++ printk("unable to get IRQ %d",TSSI_IRQ); -++ return retval; -++ } -++ -++ tssi->dma_chan = jz_request_dma(DMA_ID_TSSI, "tssi", tssi_dma_irq, -++ IRQF_DISABLED, &jz_tssi_g); -++ if ( tssi->dma_chan < 0 ) -++ { -++ printk("MPEG2-TS request irq fail! \n"); -++ return -1; -++ } -++ -++ jz_register_chrdev(TSSI_MINOR, TSSI_NAME, &tssi_fops, &jz_tssi_g); -++ -++ printk("Jz MPEG2-TS interface driver registered %x %d\n",&jz_tssi_g,tssi->dma_chan); -++ return 0; -++} -++ -++static void jztssi_cleanup_module(void) -++{ -++ free_irq(TSSI_IRQ,0); -++ jz_free_dma(jz_tssi_g.dma_chan); -++ tssi_free_buf( &jz_tssi_ring_g ); -++ jz_unregister_chrdev(TSSI_MINOR, TSSI_NAME); -++} -++ -++module_init(jztssi_init_module); -++module_exit(jztssi_cleanup_module); -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/jz_tssi.h linux-2.6.24.7/drivers/char/jzchar/jz_tssi.h -+--- linux-2.6.24.7.old/drivers/char/jzchar/jz_tssi.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/jz_tssi.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,76 @@ -++#ifndef __JZ_TSSI_H__ -++#define __JZ_TSSI_H__ -++ -++/* -++ * IOCTL commands -++ */ -++#define IOCTL_TSSI_ENABLE 0x01 -++#define IOCTL_TSSI_DISABLE 0x02 -++#define IOCTL_TSSI_SOFTRESET 0x03 -++#define IOCTL_TSSI_ENFILTER 0x04 -++#define IOCTL_TSSI_DEFILTER 0x05 -++#define IOCTL_TSSI_ADDPID 0x06 -++#define IOCTL_TSSI_FLUSHPID 0x07 -++#define IOCTL_TSSI_INIT_DMA 0x08 -++#define IOCTL_TSSI_DISABLE_DMA 0x09 -++ -++#if 0 -++#define IOCTL_TSSI_SET_CFG 0x06 -++#define IOCTL_TSSI_GET_CFG 0x07 -++#define IOCTL_TSSI_ENIRQ_TRIG 0x08 -++#define IOCTL_TSSI_DEIRQ_TRIG 0x09 -++#define IOCTL_TSSI_ENIRQ_OVRN 0x0a -++#define IOCTL_TSSI_DEIRQ_OVRN 0x0b -++#define IOCTL_TSSI_ENPID0 0x0c -++#define IOCTL_TSSI_DEPID0 0x0d -++#define IOCTL_TSSI_ENPIDN 0x0e -++#define IOCTL_TSSI_DEPIDN 0x0f -++#define IOCTL_TSSI_SETPIDN 0x10 -++#define IOCTL_TSSI_SET_TRIG 0x11 -++#endif -++ -++#define MAX_PID_NUM 15 -++#define MPEG2_TS_PACHAGE_SIZE 19200 -++ -++struct jz_tssi_cfg_t -++{ -++ unsigned char wordorder; -++ unsigned char byteorder; -++ unsigned char dataploa; -++ unsigned char use0; -++ unsigned char clkch; -++ unsigned char mode; -++ unsigned char clkpola; -++ unsigned char frmpola; -++ unsigned char strpola; -++ unsigned char failpola; -++ unsigned char trignum; -++ -++ unsigned short pid; -++ unsigned char pid_index; //0 to 15 -++}; -++ -++struct jz_tssi_buf -++{ -++ unsigned int *buf; -++ unsigned int pos; -++ unsigned int index; -++ struct jz_tssi_buf *next; -++}; -++ -++struct jz_tssi_buf_ring_t -++{ -++ struct jz_tssi_buf *front; -++ struct jz_tssi_buf *rear; -++ unsigned int fu_num; -++}; -++ -++struct jz_tssi_t -++{ -++ struct jz_tssi_cfg_t cur_config; -++ struct jz_tssi_buf_ring_t *cur_buf; -++ struct semaphore tssi_sem; -++ int dma_chan, pid_num; -++}; -++ -++#endif /* __JZ_TSSI_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/jzchars.c linux-2.6.24.7/drivers/char/jzchar/jzchars.c -+--- linux-2.6.24.7.old/drivers/char/jzchar/jzchars.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/jzchars.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,158 @@ -++/* -++ * linux/drivers/char/jzchar/jzchars.c -++ * -++ * JzSOC char device family common layer. -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include "jzchars.h" -++ -++LIST_HEAD(jz_char_devs); -++ -++int jz_register_chrdev(unsigned char minor, const char *name, -++ struct file_operations *fops, void *private) -++{ -++ struct list_head *p; -++ jz_char_dev_t *new; -++ list_for_each(p, &jz_char_devs) { -++ jz_char_dev_t *dev = (jz_char_dev_t *)p; -++ if (minor == dev->dev_minor) -++ return -EBUSY; -++ } -++ new = (jz_char_dev_t *)kmalloc(sizeof(jz_char_dev_t), GFP_KERNEL); -++ new->dev_minor = minor; -++ new->name = (char *)name; -++ new->fops = fops; -++ new->private = private; -++ list_add_tail((struct list_head *)new, &jz_char_devs); -++ return 0; -++} -++ -++int jz_unregister_chrdev(unsigned char minor, const char *name) -++{ -++ struct list_head *p; -++ jz_char_dev_t *dev = NULL; -++ list_for_each(p, &jz_char_devs) { -++ jz_char_dev_t *one = (jz_char_dev_t *)p; -++ if (minor == one->dev_minor) { -++ dev = one; -++ break; -++ } -++ } -++ if (dev == NULL) -++ return -EINVAL; -++ list_del((struct list_head *)dev); -++ kfree(dev); -++ return 0; -++} -++ -++static ssize_t jz_char_read(struct file *, char *, size_t, loff_t *); -++static ssize_t jz_char_write(struct file *, const char *, size_t, loff_t *); -++static int jz_char_open(struct inode *, struct file *); -++static int jz_char_release(struct inode *, struct file *); -++static int jz_char_ioctl(struct inode *, struct file *, -++ unsigned int, unsigned long); -++ -++static struct file_operations jz_char_fops = -++{ -++ read: jz_char_read, -++ write: jz_char_write, -++ ioctl: jz_char_ioctl, -++ open: jz_char_open, -++ release: jz_char_release -++}; -++ -++static int __init jz_char_family_init(void) -++{ -++ printk("JzSOC: char device family.\n"); -++ return register_chrdev(JZ_CHAR_MAJOR, "JzChar", &jz_char_fops); -++} -++ -++static void __exit jz_char_family_exit(void) -++{ -++ printk("JzSOC: exit char device family.\n"); -++ unregister_chrdev(JZ_CHAR_MAJOR, "JzChar"); -++} -++ -++module_init(jz_char_family_init); -++module_exit(jz_char_family_exit); -++ -++static int jz_char_open(struct inode *inode, struct file *filp) -++{ -++ jz_char_dev_t *dev = NULL; -++ unsigned int minor = iminor(inode); //minor extend to 20bit! -++ struct list_head *p; -++ list_for_each(p, &jz_char_devs) { -++ jz_char_dev_t *one = (jz_char_dev_t *)p; -++ if (one->dev_minor == minor) { -++ dev = one; -++ filp->private_data = dev; -++ return dev->fops->open(inode, filp); -++ } -++ } -++ printk("JzChar: No such device\n"); -++ return -EINVAL; -++} -++ -++static int jz_char_release(struct inode *inode, struct file *filp) -++{ -++ jz_char_dev_t *dev = (jz_char_dev_t *)filp->private_data; -++ if (dev->fops->release) -++ return dev->fops->release(inode, filp); -++ return 0; -++} -++ -++static int jz_char_ioctl(struct inode *inode, struct file *filp, -++ unsigned int cmd, unsigned long arg) -++{ -++ jz_char_dev_t *dev = (jz_char_dev_t *)filp->private_data; -++ if (dev->fops->ioctl) -++ return dev->fops->ioctl(inode, filp, cmd, arg); -++ return 0; -++} -++ -++static ssize_t jz_char_read(struct file *filp, char *buf, -++ size_t count, loff_t *ppos) -++{ -++ jz_char_dev_t *dev = (jz_char_dev_t *)filp->private_data; -++ if (dev->fops->read) -++ return dev->fops->read(filp, buf, count, ppos); -++ return 0; -++} -++ -++static ssize_t jz_char_write(struct file *filp, const char *buf, -++ size_t count, loff_t *ppos) -++{ -++ jz_char_dev_t *dev = (jz_char_dev_t *)filp->private_data; -++ if (dev->fops->write) -++ return dev->fops->write(filp, buf, count, ppos); -++ return 0; -++} -++ -++EXPORT_SYMBOL(jz_register_chrdev); -++EXPORT_SYMBOL(jz_unregister_chrdev); -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/jzchars.h linux-2.6.24.7/drivers/char/jzchar/jzchars.h -+--- linux-2.6.24.7.old/drivers/char/jzchar/jzchars.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/jzchars.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,47 @@ -++#ifndef __JZ_CHARS_H__ -++#define __JZ_CHARS_H__ -++ -++#include -++#include -++ -++#define JZ_CHAR_MAJOR 238 -++ -++#define UPRT_MINOR 0 // Micro printer -++#define CIM_MINOR 1 // Camera interface module -++#define TPANEL_MINOR 2 // Touchpanel -++#define KEYPAD_MINOR 3 // Keypad -++#define MEMCARD_MINOR 4 // Memory card -++#define MAGCARD_MINOR 5 // Magcard -++#define VFD_MINOR 6 // VFD -++#define POWERFAIL_MINOR 7 // Powerfail -++#define EJTAG_MINOR 8 // EJTAG emulation -++#define REMR0_MINOR 9 // Remote output receive 0 -++#define REMR1_MINOR 10 // Remote output receive 1 -++#define USPI_MINOR 11 // Ultra-speed SPI device -++#define SADC_MINOR 12 // SAR-ADC -++#define SLCD_MINOR 13 // Smart LCD -++ -++// 32 to 47 are reserved for SCC -++#define SCC_MINOR 32 -++// 48 to 63 are reserved for Camera sensor -++#define SENSOR_MINOR 48 -++// 64 to 71 are for EEPROM -++#define EEPROM_MINOR_BASE 64 -++// 72 for OWI -++#define OW_MINOR 72 -++// 73 for TCSM_MINOR -++#define TCSM_MINOR 73 -++ -++typedef struct { -++ struct list_head list; -++ char *name; -++ struct file_operations *fops; -++ void *private; -++ unsigned short dev_minor; -++} jz_char_dev_t; -++ -++extern int jz_register_chrdev(unsigned char minor, const char *name, -++ struct file_operations *fops, void * private); -++extern int jz_unregister_chrdev(unsigned char minor, const char *name); -++ -++#endif /* __JZ_CHARS_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/poweroff.c linux-2.6.24.7/drivers/char/jzchar/poweroff.c -+--- linux-2.6.24.7.old/drivers/char/jzchar/poweroff.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/poweroff.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,383 @@ -++/* -++ * linux/drivers/char/jzchar/poweroff.c -++ * -++ * Power off handling. -++ * -++ * Copyright (C) 2005-2007 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++ -++#include "jzchars.h" -++ -++MODULE_AUTHOR("Jianli Wei "); -++MODULE_DESCRIPTION("Poweroff handling"); -++MODULE_LICENSE("GPL"); -++ -++#undef DEBUG -++//#define DEBUG -++#ifdef DEBUG -++#define dprintk(x...) printk(x) -++#else -++#define dprintk(x...) -++#endif -++ -++//#define USE_SUSPEND_HOTPLUG -++ -++#ifdef CONFIG_SOC_JZ4730 -++#define GPIO_PW_I 97 -++#define GPIO_PW_O 66 -++#define POWEROFF_PIN_DOWN 1 -++#define SET_POWEROFF_PIN_AS_IRQ __gpio_as_irq_rise_edge(POWEROFF_PIN) -++#define DO_SHUTDOWN_SYSTEM __gpio_clear_pin(GPIO_PW_O) -++#define DO_SUSPEND jz_pm_suspend() -++ -++#define GPIO_DISP_OFF_N 93 -++#define __lcd_set_backlight_level(n) \ -++do { \ -++ REG_PWM_DUT(0) = n; \ -++ REG_PWM_PER(0) = 7; \ -++ REG_PWM_CTR(0) = 0x81; \ -++} while (0) -++#define __lcd_close_backlight() \ -++do { \ -++ __lcd_set_backlight_level(0); \ -++} while (0) -++#endif -++ -++#ifdef CONFIG_SOC_JZ4740 -++#define GPIO_PW_I 125 -++#define POWEROFF_PIN_DOWN 0 -++#define SET_POWEROFF_PIN_AS_IRQ __gpio_as_irq_fall_edge(POWEROFF_PIN) -++#define DO_SHUTDOWN_SYSTEM jz_pm_hibernate() -++#define DO_SUSPEND { \ -++ jz_pm_sleep();\ -++ suspend_flag = 0;\ -++ SET_POWEROFF_PIN_AS_IRQ;\ -++ } -++ -++#define GPIO_DISP_OFF_N 118 -++#define GPIO_PWM 123 -++#define __lcd_close_backlight() \ -++do { \ -++__gpio_as_output(GPIO_PWM); \ -++__gpio_clear_pin(GPIO_PWM); \ -++} while (0) -++#endif -++ -++#ifdef CONFIG_SOC_JZ4750 -++#define GPIO_PW_I GPIO_WAKEUP -++#define POWEROFF_PIN_DOWN 0 -++#define SET_POWEROFF_PIN_AS_IRQ __gpio_as_irq_fall_edge(POWEROFF_PIN) -++#define DO_SHUTDOWN_SYSTEM jz_pm_hibernate() -++#define DO_SUSPEND { \ -++ jz_pm_sleep();\ -++ suspend_flag = 0;\ -++ SET_POWEROFF_PIN_AS_IRQ;\ -++ } -++#endif -++ -++#define POWEROFF_PIN GPIO_PW_I -++#define POWEROFF_IRQ (IRQ_GPIO_0 + POWEROFF_PIN) -++ -++#define POWEROFF_PERIOD 1000 /* unit: ms */ -++#define POWEROFF_DELAY 100 /* unit: ms */ -++ -++static struct timer_list poweroff_timer; -++static struct timer_list poweroff_delaytimer; -++static struct work_struct suspend_work; -++ -++static int poweroff_flag = 0; -++static int suspend_flag = 0; -++static int num_seconds = 0; -++ -++#ifdef CONFIG_JZ_UDC_HOTPLUG -++extern int jz_udc_active; -++#endif -++ -++extern void jz_pm_suspend(void); -++extern int jz_pm_hibernate(void); -++extern int jz_pm_sleep(void); -++ -++static void poweroff_timer_routine(unsigned long dummy) -++{ -++ if (__gpio_get_pin(POWEROFF_PIN) == POWEROFF_PIN_DOWN) { -++ if (++num_seconds > 3) -++ { -++ printk("\nShutdown system now ..\n"); -++ -++#ifndef USE_SUSPEND_HOTPLUG -++ /* Turn off LCD to inform user that the system is shutting down. -++ * But the information of shutting down system will be shown -++ * by userspace program if hotplug is used. -++ */ -++ __lcd_close_backlight(); -++#endif -++ -++ /* -++ * Wait until the power key is up, or the system will reset with -++ * power key down after entering hibernate. -++ */ -++ while(__gpio_get_pin(POWEROFF_PIN)==POWEROFF_PIN_DOWN); -++ -++ poweroff_flag = 1; -++ schedule_work(&suspend_work); /* inform user to poweroff */ -++ } -++ else { -++ del_timer(&poweroff_timer); -++ init_timer(&poweroff_timer); -++ poweroff_timer.expires = jiffies + POWEROFF_PERIOD/10; -++ poweroff_timer.data = 0; -++ poweroff_timer.function = poweroff_timer_routine; -++ add_timer(&poweroff_timer); -++ } -++ } -++ else -++ { -++ printk("\nSuspend system now ..\n"); -++ num_seconds = 0; -++ suspend_flag = 1; -++ poweroff_flag = 0; -++ schedule_work(&suspend_work); /* we are entering suspend */ -++ } -++} -++ -++static void poweroff_delaytimer_routine(unsigned long dummy) -++{ -++ __gpio_as_input(POWEROFF_PIN); -++ if (__gpio_get_pin(POWEROFF_PIN)==POWEROFF_PIN_DOWN) { -++ if (suspend_flag) { -++ suspend_flag = 0; -++ del_timer(&poweroff_delaytimer); -++ SET_POWEROFF_PIN_AS_IRQ; -++ __gpio_unmask_irq(POWEROFF_PIN); -++ return; -++ } -++ del_timer(&poweroff_delaytimer); -++ del_timer(&poweroff_timer); -++ init_timer(&poweroff_timer); -++ poweroff_timer.expires = jiffies + POWEROFF_PERIOD/100; -++ poweroff_timer.data = 0; -++ poweroff_timer.function = poweroff_timer_routine; -++ add_timer(&poweroff_timer); -++ } -++ else { -++ del_timer(&poweroff_delaytimer); -++ SET_POWEROFF_PIN_AS_IRQ; -++ __gpio_unmask_irq(POWEROFF_PIN); -++ -++ printk("This is a dummy key\n"); -++ } -++} -++ -++/* -++ * Poweroff pin interrupt handler -++ */ -++static irqreturn_t poweroff_irq(int irq, void *dev_id) -++{ -++ __gpio_ack_irq(POWEROFF_PIN); -++ __gpio_mask_irq(POWEROFF_PIN); -++ __gpio_as_input(POWEROFF_PIN); -++#ifdef CONFIG_JZ_UDC_HOTPLUG -++ if (__gpio_get_pin(POWEROFF_PIN)==POWEROFF_PIN_DOWN && jz_udc_active == 0){ -++#else -++ if (__gpio_get_pin(POWEROFF_PIN)==POWEROFF_PIN_DOWN){ -++#endif -++ del_timer(&poweroff_delaytimer); -++ init_timer(&poweroff_delaytimer); -++ poweroff_delaytimer.expires = jiffies + POWEROFF_DELAY/10; -++ poweroff_delaytimer.data = 0; -++ poweroff_delaytimer.function = poweroff_delaytimer_routine; -++ add_timer(&poweroff_delaytimer); -++ } -++ else { -++ -++/* -++ * If it reaches here without jz_udc_active == 0, then it indicates POWEROFF_PIN was -++ * changed to WAKEUP key in pm.c for hand is not able to rise up so quickly, so the -++ * irq handler entered because of WAKEUP key not POWEROFF_PIN. -++ */ -++ -++#ifdef CONFIG_JZ_UDC_HOTPLUG -++ if (jz_udc_active == 1) -++ printk("\nUSB is working; Operation is denied\n"); -++#endif -++ SET_POWEROFF_PIN_AS_IRQ; -++ __gpio_unmask_irq(POWEROFF_PIN); -++ } -++ -++ return IRQ_HANDLED; -++} -++ -++#ifdef CONFIG_PM -++ -++static struct pm_dev *poweroff_dev; -++ -++static int poweroff_suspend(int *poweroff , int state) -++{ -++ suspend_flag = 1; -++ poweroff_flag = 0; -++ -++ return 0; -++} -++ -++static int poweroff_resume(int *poweroff) -++{ -++ suspend_flag = 0; -++ SET_POWEROFF_PIN_AS_IRQ; -++ __gpio_unmask_irq(POWEROFF_PIN); -++ -++ return 0; -++} -++ -++static int poweroff_pm_callback(struct pm_dev *pm_dev, pm_request_t rqst, void *data) -++{ -++ int ret; -++ int *poweroff_info = pm_dev->data; -++ -++ if (!poweroff_info) -++ return -EINVAL; -++ -++ switch (rqst) { -++ case PM_SUSPEND: -++ ret = poweroff_suspend(poweroff_info, (int)data); -++ break; -++ case PM_RESUME: -++ ret = poweroff_resume(poweroff_info); -++ break; -++ -++ default: -++ ret = -EINVAL; -++ break; -++ } -++ -++ return ret; -++} -++ -++#endif /* CONFIG_PM */ -++ -++#ifdef USE_SUSPEND_HOTPLUG -++static void run_sbin_hotplug(int state) -++{ -++ int i; -++ char *argv[3], *envp[8]; -++ char media[64], slotnum[16]; -++ if (!uevent_helper[0]) -++ return; -++ -++ i = 0; -++ argv[i++] = uevent_helper; -++ //argv[i++] = "home/lhhuang/hotplug"; -++ -++ if ( poweroff_flag == 1 ) -++ argv[i++] = "poweroff"; -++ else -++ argv[i++] = "suspend"; -++ -++ argv[i] = 0; -++ -++ /* minimal command environment */ -++ i = 0; -++ envp[i++] = "HOME=/"; -++ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; -++ -++ /* other stuff we want to pass to /sbin/hotplug */ -++ sprintf(slotnum, "SLOT=0"); -++ -++ if ( poweroff_flag == 1 ) -++ sprintf(media, "MEDIA=poweroff"); -++ else -++ sprintf(media, "MEDIA=suspend"); -++ -++ envp[i++] = slotnum; -++ envp[i++] = media; -++ -++ if (state) -++ envp[i++] = "ACTION=enter"; -++ else -++ envp[i++] = "ACTION=exit"; -++ -++ envp[i] = 0; -++ -++ dprintk("SUSPEND: hotplug path=%s state=%d\n", argv[0], state); -++ -++ SET_POWEROFF_PIN_AS_IRQ; -++ __gpio_unmask_irq(POWEROFF_PIN); /* set it because call hotplug with call_usermodehelper() \ -++ might failed, especially when using nfsroot */ -++ -++ call_usermodehelper (argv [0], argv, envp, -1); -++} -++#endif -++ -++static void suspend_handler(struct work_struct *work) -++{ -++#ifdef USE_SUSPEND_HOTPLUG -++ int state = 1; -++ run_sbin_hotplug(state); -++#else -++ if (poweroff_flag) { -++ dprintk("DO_SHUTDOWN_SYSTEM\n"); -++ DO_SHUTDOWN_SYSTEM; -++ } else { -++ dprintk("DO_SUSPEND\n"); -++ DO_SUSPEND; -++ } -++#endif -++} -++ -++static int __init poweroff_init(void) -++{ -++ int retval; -++ -++ retval = request_irq(POWEROFF_IRQ, poweroff_irq, -++ IRQF_DISABLED, "poweroff", NULL); -++ -++ SET_POWEROFF_PIN_AS_IRQ; -++ -++ if (retval) { -++ printk("Could not get poweroff irq %d\n", POWEROFF_IRQ); -++ return retval; -++ } -++ -++#ifdef CONFIG_PM -++ poweroff_dev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, poweroff_pm_callback); -++ if (poweroff_dev) { -++ poweroff_dev->data = &poweroff_dev; -++ } -++#endif -++ -++ INIT_WORK(&suspend_work, suspend_handler); -++ -++ return 0; -++} -++ -++static void __exit poweroff_exit(void) -++{ -++ free_irq(POWEROFF_IRQ, NULL); -++} -++ -++module_init(poweroff_init); -++module_exit(poweroff_exit); -++ -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/sadc.c linux-2.6.24.7/drivers/char/jzchar/sadc.c -+--- linux-2.6.24.7.old/drivers/char/jzchar/sadc.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/sadc.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,580 @@ -++/* -++ * linux/drivers/char/jzchar/sadc.c -++ * -++ * SAR-ADC driver for JZ4740. -++ * -++ * Copyright (C) 2006 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software Foundation, -++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++ -++#include "jzchars.h" -++#include "jz_ts.h" -++ -++MODULE_AUTHOR("Jianli Wei"); -++MODULE_DESCRIPTION("JZ4740 SADC driver"); -++MODULE_LICENSE("GPL"); -++ -++#define SADC_NAME "sadc" -++static DECLARE_WAIT_QUEUE_HEAD (sadc_wait_queue); -++ -++struct sadc_device { -++ int mode; -++ int dma_chan; -++ char *ts_buf; -++ char *pbat_buf; -++}; -++ -++static struct sadc_device *sadc_dev; -++ -++static int samples = 3; /* we sample 3 every time */ -++static int first_time = 0; -++static unsigned long last_x, last_y, last_p; -++ -++typedef struct datasource { -++ u16 xbuf; -++ u16 ybuf; -++ u16 zbuf; -++}datasource_t; -++ -++static datasource_t data_s; -++static unsigned int p; -++static unsigned int old_x, old_y; -++extern unsigned int (*codec_read_battery)(void); -++ -++/* -++ * set adc clock to 12MHz/div. A/D works at freq between 500KHz to 6MHz. -++ */ -++static void sadc_init_clock(int div) -++{ -++ if (div < 2) div = 2; -++ if (div > 23) div = 23; -++#if defined(CONFIG_SOC_JZ4740) -++ REG_SADC_CFG &= ~SADC_CFG_CLKDIV_MASK; -++ REG_SADC_CFG |= (div - 1) << SADC_CFG_CLKDIV_BIT; -++#endif -++#if defined(CONFIG_SOC_JZ4750) -++ REG_SADC_ADCLK &= ~SADC_ADCLK_CLKDIV_MASK; -++ REG_SADC_ADCLK |= (div - 1) << SADC_ADCLK_CLKDIV_BIT; -++ REG_SADC_ADCLK &= ~SADC_ADCLK_CLKDIV_BIT; -++ REG_SADC_ADCLK |= 39 << SADC_ADCLK_CLKDIV_10_BIT; /* if div ==3,here is 39 */ -++#endif -++} -++ -++void start_sadcin(void) -++{ -++ REG_SADC_CTRL &= ~SADC_CTRL_SRDYM; /* enable interrupt */ -++ REG_SADC_ENA |= SADC_ENA_SADCINEN; -++} -++ -++void start_pbat_adc(void) -++{ -++ REG_SADC_CFG |= SADC_CFG_PBAT_HIGH ; /* full baterry voltage >= 2.5V */ -++// REG_SADC_CFG |= SADC_CFG_PBAT_LOW; /* full baterry voltage < 2.5V */ -++ -++ REG_SADC_ENA |= SADC_ENA_PBATEN; /* Enable pbat adc */ -++} -++ -++void start_ts_adc(void) -++{ -++ REG_SADC_SAMETIME = 10; /* about 0.1 ms,you can change it */ -++ REG_SADC_WAITTIME = 2; /* about 0.02 ms,you can change it */ -++ -++ REG_SADC_CFG &= ~(SADC_CFG_TS_DMA | SADC_CFG_XYZ_MASK | SADC_CFG_SNUM_MASK); -++ REG_SADC_CFG |= (SADC_CFG_EXIN | SADC_CFG_XYZ | SADC_CFG_SNUM_3); -++ REG_SADC_CTRL |= (SADC_CTRL_TSRDYM|SADC_CTRL_PBATRDYM|SADC_CTRL_PENUM |SADC_CTRL_SRDYM); -++ REG_SADC_CTRL &= ~SADC_CTRL_PENDM; -++ REG_SADC_ENA |= SADC_ENA_TSEN; -++} -++ -++static int jz4740_adc_read(struct jz_ts_t *ts) -++{ -++ struct datasource *ds = &data_s; -++ u32 xybuf,z; -++ -++ if (!(REG_SADC_STATE & SADC_STATE_TSRDY)) { -++ /* sleep */ -++ REG_SADC_CTRL &= ~SADC_CTRL_TSRDYM; -++ ts->sleeping = 1; -++ sleep_on(&sadc_wait_queue); -++ } -++ ts->sleeping = 0; -++ -++ xybuf = REG_SADC_TSDAT; -++ ds->xbuf = (xybuf>>16) & 0x0fff; -++ ds->ybuf = (xybuf)& 0x0fff; -++ z = REG_SADC_TSDAT; -++ ds->zbuf = z& 0x0fff; -++ REG_SADC_STATE &= ~SADC_STATE_TSRDY; -++ return 0; -++} -++ -++/*------------------------------------------------------------ -++ * Read the battery voltage -++ */ -++unsigned int jz4740_read_battery(void) -++{ -++ unsigned int v; -++ unsigned int timeout = 0x3ff; -++ u16 pbat; -++ -++ if(!(REG_SADC_STATE & SADC_STATE_PBATRDY) ==1) -++ start_pbat_adc(); -++ -++ while(!(REG_SADC_STATE & SADC_STATE_PBATRDY) && --timeout) -++ ; -++ -++ pbat = REG_SADC_BATDAT; -++ v = pbat & 0x0fff; -++ REG_SADC_STATE = SADC_STATE_PBATRDY; -++ return v; -++} -++ -++/*------------------ Calibrate samples -------------------*/ -++ -++#define DIFF(a,b) (((a)>(b))?((a)-(b)):((b)-(a))) -++#define MIN(a,b) (((a)<(b))?(a):(b)) -++ -++#if 0 -++#define XM 36 /* XM and YM may be changed for your screen */ -++#define YM 20 -++static int calibrate_samples(void *xbuf, void *ybuf, void *pbuf, int count) -++{ -++ unsigned long usd0,usd1,usd2; -++ int xMaxError = XM,yMaxError = YM; -++ int x_valid = 0,y_valid = 0,valid = 0; -++ unsigned long x_cal = 0, y_cal = 0, p_cal = 0; -++ unsigned long *xp = (unsigned long *)xbuf; -++ unsigned long *yp = (unsigned long *)ybuf; -++ unsigned long *pp = (unsigned long *)pbuf; -++ -++ usd0 = (xp[0] > xp[1]) ? (xp[0] - xp[1]) : (xp[1] - xp[0]); -++ usd1 = (xp[1] > xp[2]) ? (xp[1] - xp[2]) : (xp[2] - xp[1]); -++ usd2 = (xp[2] > xp[0]) ? (xp[2] - xp[0]) : (xp[0] - xp[2]); -++ -++ if ( usd0 < usd1) -++ x_cal = xp[0] + ((usd2 < usd0) ? xp[2] : xp[1]); -++ else -++ x_cal= xp[2] + ((usd2 < usd1) ? xp[0] : xp[1]); -++ x_cal >>= 1; -++ -++ if ( (usd0 < xMaxError) && (usd1 < xMaxError) && (usd2 < xMaxError) ) -++ x_valid = 1; -++ -++ usd0 = (yp[0] > yp[1]) ? (yp[0] - yp[1]) : (yp[1] - yp[0]); -++ usd1 = (yp[1] > yp[2]) ? (yp[1] - yp[2]) : (yp[2] - yp[1]); -++ usd2 = (yp[2] > yp[0]) ? (yp[2] - yp[0]) : (yp[0] - yp[2]); -++ -++ if ( usd0 < usd1) -++ y_cal = yp[0] + ((usd2 < usd0) ? yp[2] : yp[1]); -++ else -++ y_cal = yp[2] + ((usd2 < usd1) ? yp[0] : yp[1]); -++ -++ y_cal >>= 1; -++ -++ if ( (usd0 < yMaxError) && (usd1 < yMaxError) && (usd2 < yMaxError) ) -++ y_valid = 1; -++ -++ if( x_valid && y_valid) -++ valid = 1; -++ -++ usd0 = (pp[0] > pp[1]) ? (pp[0] - pp[1]) : (pp[1] - pp[0]); -++ usd1 = (pp[1] > pp[2]) ? (pp[1] - pp[2]) : (pp[2] - pp[1]); -++ usd2 = (pp[2] > pp[0]) ? (pp[2] - pp[0]) : (pp[0] - pp[2]); -++ -++ if ( usd0 < usd1) -++ p_cal = pp[0] + ((usd2 < usd0) ? pp[2] : pp[1]); -++ else -++ p_cal= pp[2] + ((usd2 < usd1) ? pp[0] : pp[1]); -++ -++ p_cal >>= 1; -++ -++ if (first_time) { -++ first_time = 0; -++ last_x = x_cal; -++ last_y = y_cal; -++ last_p = p_cal; -++ } -++ else{ -++ if ((DIFF(x_cal, last_x) > 50) || -++ (DIFF(y_cal, last_y) > 50)) -++ valid = 0; -++ else -++ valid = 1; -++ } -++ *xp = last_x = x_cal; -++ *yp = last_y = y_cal; -++ *pp = last_p = p_cal; -++ -++ return valid; -++} -++#endif -++ -++static int calibrate_samples(void *xbuf, void *ybuf, void *pbuf, int count) -++{ -++ unsigned long *xp = (unsigned long *)xbuf; -++ unsigned long *yp = (unsigned long *)ybuf; -++ unsigned long *pp = (unsigned long *)pbuf; -++ unsigned long x_cal = 0, y_cal = 0, p_cal = 0; -++ int i; -++ int valid = 1; -++ -++ /* calculate the average of the rest */ -++ for (i = 0; i < count; i++) { -++ x_cal += xp[i]; -++ y_cal += yp[i]; -++ p_cal += pp[i]; -++ } -++ x_cal /= count; -++ y_cal /= count; -++ p_cal /= count; -++ -++ if (first_time) { -++ first_time = 0; -++ last_x = x_cal; -++ last_y = y_cal; -++ last_p = p_cal; -++ } -++ else { -++ if ((DIFF(x_cal, last_x) > 50) || -++ (DIFF(y_cal, last_y) > 50)) -++ valid = 0; -++ else -++ valid = 1; -++ } -++ -++ *xp = last_x = x_cal; -++ *yp = last_y = y_cal; -++ *pp = last_p = p_cal; -++ -++ return valid; -++} -++ -++#define TSMAXX 945 -++#define TSMAXY 830 -++#define TSMINX 90 -++#define TSMINY 105 -++ -++#define SCREEN_X 480 -++#define SCREEN_Y 272 -++ -++static unsigned long transform_to_screen_x(struct jz_ts_t *ts, unsigned long x ) -++{ -++ -++ if (ts->minx) -++ { -++ if (x < ts->minx) x = ts->minx; -++ if (x > ts->maxx) x = ts->maxx; -++ -++ return (x - ts->minx) * SCREEN_X / (ts->maxx - ts->minx); -++ } -++ else -++ { -++ if (x < TSMINX) x = TSMINX; -++ if (x > TSMAXX) x = TSMAXX; -++ -++ return (x - TSMINX) * SCREEN_X / (TSMAXX - TSMINX); -++ } -++} -++ -++static unsigned long transform_to_screen_y(struct jz_ts_t *ts, unsigned long y) -++{ -++ if (ts->minx) -++ { -++ if (y < ts->minx) y = ts->miny; -++ if (y > ts->maxx) y = ts->maxy; -++ -++ return (y - ts->miny) * SCREEN_Y / (ts->maxy - ts->miny); -++ } -++ else -++ { -++ if (y < TSMINX) y = TSMINY; -++ if (y > TSMAXX) y = TSMAXY; -++ -++ return (y - TSMINY) * SCREEN_Y / (TSMAXY - TSMINY); -++ } -++} -++ -++/* -++ * File operations -++ */ -++static int sadc_open(struct inode *inode, struct file *filp); -++static int sadc_release(struct inode *inode, struct file *filp); -++static ssize_t sadc_read(struct file *filp, char *buf, size_t size, loff_t *l); -++static ssize_t sadc_write(struct file *filp, const char *buf, size_t size, loff_t *l); -++static int sadc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -++ -++static struct file_operations sadc_fops = -++{ -++ open: sadc_open, -++ release: sadc_release, -++ read: sadc_read, -++ write: sadc_write, -++ ioctl: sadc_ioctl -++}; -++ -++static int sadc_open(struct inode *inode, struct file *filp) -++{ -++ try_module_get(THIS_MODULE); -++ return 0; -++} -++ -++static int sadc_release(struct inode *inode, struct file *filp) -++{ -++ module_put(THIS_MODULE); -++ return 0; -++} -++ -++static ssize_t sadc_read(struct file *filp, char *buf, size_t size, loff_t *l) -++{ -++ return size; -++} -++ -++static ssize_t sadc_write(struct file *filp, const char *buf, size_t size, loff_t *l) -++{ -++ return size; -++} -++ -++static int sadc_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -++{ -++ switch (cmd) { -++ default: -++ printk("Not supported command: 0x%x\n", cmd); -++ return -EINVAL; -++ break; -++ } -++ return 0; -++} -++ -++/*------------------ Common routines -------------------*/ -++ -++void ts_enable_irq(void) -++{ -++ REG_SADC_CTRL &= ~SADC_CTRL_PENDM; -++} -++ -++void ts_disable_irq(void) -++{ -++ REG_SADC_CTRL |= (SADC_CTRL_PENDM | SADC_CTRL_PENUM); -++} -++ -++void ts_free_irq(struct jz_ts_t *ts) -++{ -++ free_irq(ts->pendown_irq, ts); -++} -++ -++void ts_data_ready(void) -++{ -++ REG_SADC_CTRL |= SADC_CTRL_TSRDYM; -++ wake_up(&sadc_wait_queue); -++} -++ -++/* -++ * Interrupt handler -++ */ -++void ts_irq_callback(void) -++{ -++ u32 state; -++ -++ state = REG_SADC_STATE; -++ if (!(REG_SADC_CTRL&SADC_CTRL_PENDM)&&(REG_SADC_STATE & SADC_STATE_PEND)) { -++ REG_SADC_STATE = SADC_STATE_PEND; -++ REG_SADC_STATE = SADC_STATE_PENU; -++ REG_SADC_CTRL |= SADC_CTRL_PENDM; -++ REG_SADC_CTRL &= ~SADC_CTRL_PENUM; -++ p = 1; -++ } -++ -++ if (!(REG_SADC_CTRL&SADC_CTRL_PENUM)&&(REG_SADC_STATE & SADC_STATE_PENU)) { -++ REG_SADC_STATE = SADC_STATE_PENU; -++ REG_SADC_CTRL |= SADC_CTRL_PENUM; -++ REG_SADC_CTRL &= ~SADC_CTRL_PENDM; -++ p = 0; -++ } -++ -++ first_time = 1; // first time to acquire sample -++} -++ -++int PenIsDown(void) -++{ -++ return p; -++} -++ -++int ts_request_irq(u32 *irq, -++ irqreturn_t (*handler)(int, void *), -++ const char *devname, -++ void *dev_id) -++{ -++ int ret; -++ -++ /* return the irq number */ -++ *irq = IRQ_SADC; -++ ts_disable_irq(); -++ /* interrupt mode */ -++ ret = request_irq(IRQ_SADC, handler, IRQF_DISABLED, -++ devname, dev_id); -++ if(ret) -++ printk("failed irq \n"); -++ -++ start_ts_adc(); -++ return ret; -++} -++ -++/* -++ * Acquire Raw pen coodinate data and compute touch screen -++ * pressure resistance. Hold spinlock when calling. -++ */ -++int AcquireEvent(struct jz_ts_t *ts, struct ts_event *event) -++{ -++ unsigned int x_raw[8], y_raw[8], p_raw[8]; -++ int valid, i; -++ unsigned int avl_x, avl_y, diff_x, diff_y; -++ struct datasource *ds = &data_s; -++ avl_x = avl_y = 0; -++ -++ for (i = 0; i < samples; i++) { -++ if (jz4740_adc_read(ts)) { -++ return 0; -++ } -++ -++ x_raw[i] = ds->ybuf; -++ y_raw[i] = ds->xbuf; -++ p_raw[i] = ds->zbuf; -++ avl_x += x_raw[i]; -++ avl_y += y_raw[i]; -++#if 0 -++ printk("x_raw=%x y_raw=%x z_raw=%x\n",x_raw[i],y_raw[i],p_raw[i]); -++#endif -++ } -++ -++ avl_x /= samples; -++ avl_y /= samples; -++#define MAX_DELTA 20 -++ valid = 1; -++ -++ for (i = 1; i < samples; i++) -++ { -++ if ((100 * DIFF(x_raw[i],x_raw[i-1])/MIN(x_raw[i],x_raw[i-1])) > MAX_DELTA) { -++ valid = 0; -++ break; -++ } -++ -++ if ((100 * DIFF(y_raw[i],y_raw[i-1])/MIN(y_raw[i],y_raw[i-1])) > MAX_DELTA) { -++ valid = 0; -++ break; -++ } -++ -++ if ((100 * DIFF(p_raw[i],p_raw[i-1])/MIN(p_raw[i],p_raw[i-1])) > MAX_DELTA) { -++ valid = 0; -++ break; -++ } -++ } -++ -++ if (valid) { -++ if (ts->first_read) { -++ ts->first_read = 0; -++ old_x = avl_x; -++ old_y = avl_y; -++ } -++ diff_x = DIFF(old_x, avl_x); -++ diff_y = DIFF(old_y, avl_y); -++ if (diff_x < 100 && diff_y < 100) { -++ old_x = avl_x; -++ old_y = avl_y; -++ } else -++ valid = 0; -++ } -++ if (valid) { -++ valid = calibrate_samples(x_raw, y_raw, p_raw, samples); -++ } -++ -++ if (valid) { -++ unsigned int x_scr, y_scr; -++ -++ if(ts->filter) { -++ x_scr = transform_to_screen_x(ts, x_raw[0]); -++ y_scr = transform_to_screen_y(ts, y_raw[0]); -++ -++ if (ts->prints) -++ printk("x_raw=%d y_raw=%d x_transform=%d y_transform=%d\n", x_raw[0], y_raw[0], x_scr, y_scr); -++ } -++ else { -++ x_scr = x_raw[0]; -++ y_scr = y_raw[0]; -++ -++ if (ts->prints) -++ printk("x_raw=%d y_raw=%d \n", x_raw[0], y_raw[0]); -++ } -++ -++ event->x = x_scr; -++ event->y = y_scr; -++ event->pressure = (u16)p_raw[0]; -++ event->status = PENDOWN; -++ return 1; -++ } -++ return 0; -++} -++ -++/* -++ * Module init and exit -++ */ -++static int __init sadc_init(void) -++{ -++ struct sadc_device *dev; -++ int ret; -++ -++ /* allocate device */ -++ dev = kmalloc(sizeof(struct sadc_device), GFP_KERNEL); -++ if (!dev) return -ENOMEM; -++ -++ sadc_dev = dev; -++ ret = jz_register_chrdev(SADC_MINOR, SADC_NAME, &sadc_fops, dev); -++ if (ret < 0) { -++ kfree(dev); -++ return ret; -++ } -++ -++ codec_read_battery = jz4740_read_battery; -++ sadc_init_clock(3); -++ -++ printk("JZ4740 SAR-ADC driver registered\n"); -++ return 0; -++} -++ -++static void __exit sadc_exit(void) -++{ -++ struct sadc_device *dev = sadc_dev; -++ -++ free_irq(IRQ_SADC, dev); -++ jz_unregister_chrdev(SADC_MINOR, SADC_NAME); -++ kfree(dev); -++} -++ -++module_init(sadc_init); -++module_exit(sadc_exit); -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/sensor.c linux-2.6.24.7/drivers/char/jzchar/sensor.c -+--- linux-2.6.24.7.old/drivers/char/jzchar/sensor.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/sensor.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,182 @@ -++/* -++ * linux/drivers/char/jzchar/sensor.c -++ * -++ * Common CMOS Camera Sensor Driver -++ * -++ * Copyright (C) 2006 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++ -++#include "jzchars.h" -++ -++MODULE_AUTHOR("Jianli Wei"); -++MODULE_DESCRIPTION("Common CMOS Camera Sensor Driver"); -++MODULE_LICENSE("GPL"); -++ -++/* -++ * ioctl commands -++ */ -++#define IOCTL_SET_ADDR 0 /* set i2c address */ -++#define IOCTL_SET_CLK 1 /* set i2c clock */ -++#define IOCTL_WRITE_REG 2 /* write sensor register */ -++#define IOCTL_READ_REG 3 /* read sensor register */ -++ -++/* -++ * i2c related -++ */ -++static unsigned int i2c_addr = 0x42; -++static unsigned int i2c_clk = 100000; -++ -++static void write_reg(u8 reg, u8 val) -++{ -++ i2c_open(); -++ i2c_setclk(i2c_clk); -++ i2c_write((i2c_addr >> 1), &val, reg, 1); -++ i2c_close(); -++} -++ -++static u8 read_reg(u8 reg) -++{ -++ u8 val; -++ -++ i2c_open(); -++ i2c_setclk(i2c_clk); -++ i2c_read((i2c_addr >> 1), &val, reg, 1); -++ i2c_close(); -++ return val; -++} -++ -++/* -++ * fops routines -++ */ -++ -++static int sensor_open(struct inode *inode, struct file *filp); -++static int sensor_release(struct inode *inode, struct file *filp); -++static ssize_t sensor_read(struct file *filp, char *buf, size_t size, loff_t *l); -++static ssize_t sensor_write(struct file *filp, const char *buf, size_t size, loff_t *l); -++static int sensor_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -++ -++static struct file_operations sensor_fops = -++{ -++ open: sensor_open, -++ release: sensor_release, -++ read: sensor_read, -++ write: sensor_write, -++ ioctl: sensor_ioctl, -++}; -++ -++static int sensor_open(struct inode *inode, struct file *filp) -++{ -++ try_module_get(THIS_MODULE); -++ return 0; -++} -++ -++static int sensor_release(struct inode *inode, struct file *filp) -++{ -++ module_put(THIS_MODULE); -++ return 0; -++} -++ -++static ssize_t sensor_read(struct file *filp, char *buf, size_t size, loff_t *l) -++{ -++ printk("sensor: read is not implemented\n"); -++ return -1; -++} -++ -++static ssize_t sensor_write(struct file *filp, const char *buf, size_t size, loff_t *l) -++{ -++ printk("sensor: write is not implemented\n"); -++ return -1; -++} -++ -++static int sensor_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -++{ -++ int ret = 0; -++ -++ switch (cmd) { -++ case IOCTL_SET_ADDR: -++ if (copy_from_user(&i2c_addr, (void *)arg, 4)) -++ return -EFAULT; -++ break; -++ case IOCTL_SET_CLK: -++ if (copy_from_user(&i2c_clk, (void *)arg, 4)) -++ return -EFAULT; -++ break; -++ case IOCTL_WRITE_REG: -++ { -++ u8 regval[2]; -++ -++ if (copy_from_user(regval, (void *)arg, 2)) -++ return -EFAULT; -++ -++ write_reg(regval[0], regval[1]); -++ break; -++ } -++ case IOCTL_READ_REG: -++ { -++ u8 reg, val; -++ -++ if (copy_from_user(®, (void *)arg, 1)) -++ return -EFAULT; -++ -++ val = read_reg(reg); -++ -++ if (copy_to_user((void *)(arg + 1), &val, 1)) -++ return -EFAULT; -++ break; -++ } -++ default: -++ printk("Not supported command: 0x%x\n", cmd); -++ return -EINVAL; -++ break; -++ } -++ return ret; -++} -++ -++/* -++ * Module init and exit -++ */ -++ -++static int __init sensor_init(void) -++{ -++ int ret; -++ -++ ret = jz_register_chrdev(SENSOR_MINOR, "sensor", &sensor_fops, NULL); -++ if (ret < 0) { -++ return ret; -++ } -++ -++ printk("Ingenic CMOS camera sensor driver registered\n"); -++ -++ return 0; -++} -++ -++static void __exit sensor_exit(void) -++{ -++ jz_unregister_chrdev(SENSOR_MINOR, "sensor"); -++} -++ -++module_init(sensor_init); -++module_exit(sensor_exit); -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/tcsm.c linux-2.6.24.7/drivers/char/jzchar/tcsm.c -+--- linux-2.6.24.7.old/drivers/char/jzchar/tcsm.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/tcsm.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,123 @@ -++/* -++ * linux/drivers/char/jzchar/tcsm.c -++ * -++ * Virtual device driver with tricky appoach to manage TCSM -++ * -++ * Copyright (C) 2006 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include "jzchars.h" -++ -++MODULE_AUTHOR("Jianli Wei"); -++MODULE_DESCRIPTION("Virtual Driver of TCSM"); -++MODULE_LICENSE("GPL"); -++ -++/* -++ * fops routines -++ */ -++ -++static int tcsm_open(struct inode *inode, struct file *filp); -++static int tcsm_release(struct inode *inode, struct file *filp); -++static ssize_t tcsm_read(struct file *filp, char *buf, size_t size, loff_t *l); -++static ssize_t tcsm_write(struct file *filp, const char *buf, size_t size, loff_t *l); -++static int tcsm_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -++ -++static struct file_operations tcsm_fops = -++{ -++ open: tcsm_open, -++ release: tcsm_release, -++ read: tcsm_read, -++ write: tcsm_write, -++ ioctl: tcsm_ioctl, -++}; -++ -++static int tcsm_open(struct inode *inode, struct file *filp) -++{ -++ // printk("%d[%s]\n", __LINE__, __FILE__); -++ struct pt_regs *info = task_pt_regs(current); -++ printk("pt_regs =%p\n", info); -++ printk("cp0 status=0x%08x\n", info->cp0_status); -++ info->cp0_status &= ~0x10; -++ info->cp0_status |= 0x08000000; // a tricky -++ printk("cp0 status=0x%08x\n", info->cp0_status); -++ return 0; -++} -++ -++static int tcsm_release(struct inode *inode, struct file *filp) -++{ -++ struct pt_regs *info = task_pt_regs(current); -++ info->cp0_status |= 0x10; -++ info->cp0_status &= ~0x08000000; // a tricky -++ return 0; -++} -++ -++static ssize_t tcsm_read(struct file *filp, char *buf, size_t size, loff_t *l) -++{ -++ printk("tcsm: read is not implemented\n"); -++ return -1; -++} -++ -++static ssize_t tcsm_write(struct file *filp, const char *buf, size_t size, loff_t *l) -++{ -++ printk("tcsm: write is not implemented\n"); -++ return -1; -++} -++ -++static int tcsm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -++{ -++ int ret = 0; -++ printk("tcsm: ioctl is not implemented\n"); -++ return ret; -++} -++ -++/* -++ * Module init and exit -++ */ -++ -++static int __init tcsm_init(void) -++{ -++ int ret; -++ -++ ret = jz_register_chrdev(TCSM_MINOR, "tcsm", &tcsm_fops, NULL); -++ if (ret < 0) { -++ return ret; -++ } -++ -++ printk("Virtual Driver of TCSM registered\n"); -++ return 0; -++} -++ -++static void __exit tcsm_exit(void) -++{ -++ jz_unregister_chrdev(TCSM_MINOR, "tcsm"); -++} -++ -++module_init(tcsm_init); -++module_exit(tcsm_exit); -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/ucb1400.c linux-2.6.24.7/drivers/char/jzchar/ucb1400.c -+--- linux-2.6.24.7.old/drivers/char/jzchar/ucb1400.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/ucb1400.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,585 @@ -++/* -++ * ucb1400.c -++ * -++ * Touch screen driver interface to the UCB1400 codec. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "jz_ts.h" -++#include "ucb1400.h" -++ -++#ifndef GPIO_TS_PENIRQ -++#define GPIO_TS_PENIRQ 68 -++#endif -++ -++#define TS_PIN GPIO_TS_PENIRQ -++#define TS_IRQ (IRQ_GPIO_0 + TS_PIN) -++ -++static int samples = 5; /* we sample 5 every time, and throw away the max and min cases, then use the average of the other 3 samples */ -++static int first_time = 0; -++static unsigned long last_x, last_y, last_p; -++ -++static int adcsync = 0; -++ -++static unsigned int ucb_id = 0; -++static struct ucb1400 *ucb; -++ -++extern struct ac97_codec * find_ac97_codec(void); -++ -++extern unsigned int (*codec_read_battery)(void); -++ -++/*------------------ UCB1400 routines ------------------*/ -++ -++static inline void ucb1400_reg_write(unsigned char reg, unsigned short val) -++{ -++ struct ac97_codec *codec = find_ac97_codec(); -++ if (!codec) -++ return; -++ codec->codec_write(codec, reg, val); -++} -++ -++static inline unsigned int ucb1400_reg_read(unsigned char reg) -++{ -++ struct ac97_codec *codec = find_ac97_codec(); -++ if (!codec) -++ return 0; -++ return codec->codec_read(codec, reg); -++} -++ -++static void ucb1400_adc_enable(void) -++{ -++ down(&ucb->adc_sem); -++ -++ ucb->adc_cr |= UCB_ADC_ENA; -++ ucb1400_reg_write(UCB_ADC_CR, ucb->adc_cr); -++} -++ -++static unsigned int ucb1400_adc_read(int adc_channel, int sync) -++{ -++ unsigned int val, timeout = 10000; -++ -++ if (sync) -++ adc_channel |= UCB_ADC_SYNC_ENA; -++ -++ ucb1400_reg_write(UCB_ADC_CR, ucb->adc_cr | adc_channel); -++ ucb1400_reg_write(UCB_ADC_CR, ucb->adc_cr | adc_channel | UCB_ADC_START); -++ -++ for (;;) { -++ val = ucb1400_reg_read(UCB_ADC_DATA); -++ if (val & UCB_ADC_DAT_VAL) -++ break; -++ if (--timeout == 0) -++ break; -++ udelay(1); -++ } -++ -++ return UCB_ADC_DAT(val); -++} -++ -++static void ucb1400_adc_disable(void) -++{ -++ ucb->adc_cr &= ~UCB_ADC_ENA; -++ ucb1400_reg_write(UCB_ADC_CR, ucb->adc_cr); -++ -++ up(&ucb->adc_sem); -++} -++ -++static void ucb1400_enable_irq(unsigned int idx, int edges) -++{ -++ unsigned long flags; -++ -++ if (idx < 16) { -++ spin_lock_irqsave(&ucb->lock, flags); -++ -++ /* This prevents spurious interrupts on the UCB1400 */ -++ ucb1400_reg_write(UCB_IE_CLEAR, 1 << idx); -++ ucb1400_reg_write(UCB_IE_CLEAR, 0); -++ -++ if (edges & UCB_RISING) { -++ ucb->irq_ris_enbl |= 1 << idx; -++ ucb1400_reg_write(UCB_IE_RIS, ucb->irq_ris_enbl); -++ } -++ if (edges & UCB_FALLING) { -++ ucb->irq_fal_enbl |= 1 << idx; -++ ucb1400_reg_write(UCB_IE_FAL, ucb->irq_fal_enbl); -++ } -++ spin_unlock_irqrestore(&ucb->lock, flags); -++ } -++} -++ -++static void ucb1400_disable_irq(unsigned int idx, int edges) -++{ -++ unsigned long flags; -++ -++ if (idx < 16) { -++ spin_lock_irqsave(&ucb->lock, flags); -++ -++ if (edges & UCB_RISING) { -++ ucb->irq_ris_enbl &= ~(1 << idx); -++ ucb1400_reg_write(UCB_IE_RIS, ucb->irq_ris_enbl); -++ } -++ if (edges & UCB_FALLING) { -++ ucb->irq_fal_enbl &= ~(1 << idx); -++ ucb1400_reg_write(UCB_IE_FAL, ucb->irq_fal_enbl); -++ } -++ spin_unlock_irqrestore(&ucb->lock, flags); -++ } -++} -++ -++/* -++ * Switch to interrupt mode. -++ */ -++static inline void ucb1400_ts_mode_int(void) -++{ -++ if (!ucb_id) { -++ ucb_id = ucb1400_reg_read(UCB_ID); -++ } -++ -++ if (ucb_id == UCB_ID_1400_BUGGY) -++ ucb1400_reg_write(UCB_TS_CR, -++ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | -++ UCB_TS_CR_MODE_INT); -++ else -++ ucb1400_reg_write(UCB_TS_CR, -++ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | -++ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | -++ UCB_TS_CR_MODE_INT); -++} -++ -++/* -++ * Switch to pressure mode, and read pressure. We don't need to wait -++ * here, since both plates are being driven. -++ */ -++static inline unsigned int ucb1400_ts_read_pressure(void) -++{ -++ ucb1400_reg_write(UCB_TS_CR, -++ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | -++ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | -++ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -++ -++ return ucb1400_adc_read(UCB_ADC_INP_TSPY, adcsync); -++} -++ -++/* -++ * Switch to X position mode and measure Y plate. We switch the plate -++ * configuration in pressure mode, then switch to position mode. This -++ * gives a faster response time. Even so, we need to wait about 55us -++ * for things to stabilise. -++ */ -++static inline unsigned int ucb1400_ts_read_xpos(void) -++{ -++ ucb1400_reg_write(UCB_TS_CR, -++ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | -++ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -++ ucb1400_reg_write(UCB_TS_CR, -++ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | -++ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -++ ucb1400_reg_write(UCB_TS_CR, -++ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | -++ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); -++ -++ udelay(55); -++ -++ return ucb1400_adc_read(UCB_ADC_INP_TSPY, adcsync); -++} -++ -++/* -++ * Switch to Y position mode and measure X plate. We switch the plate -++ * configuration in pressure mode, then switch to position mode. This -++ * gives a faster response time. Even so, we need to wait about 55us -++ * for things to stabilise. -++ */ -++static inline unsigned int ucb1400_ts_read_ypos(void) -++{ -++ ucb1400_reg_write(UCB_TS_CR, -++ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | -++ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -++ ucb1400_reg_write(UCB_TS_CR, -++ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | -++ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); -++ ucb1400_reg_write(UCB_TS_CR, -++ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | -++ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); -++ -++ udelay(55); -++ -++ return ucb1400_adc_read(UCB_ADC_INP_TSPX, adcsync); -++} -++ -++/*------------------------------------------------------------ -++ * Read the battery voltage -++ */ -++ -++unsigned int ucb1400_read_battery(void) -++{ -++ unsigned int v; -++ -++ ucb1400_adc_enable(); -++ -++ // read twice to reduce fault value -++ v = ucb1400_adc_read(UCB_ADC_INP_AD0, adcsync); -++ v = ucb1400_adc_read(UCB_ADC_INP_AD0, adcsync); -++ -++ ucb1400_adc_disable(); -++ -++// printk("ucb1400_read_battery v=%d\n", v); -++ -++ return v; -++} -++ -++/*------------------ Calibrate samples -------------------*/ -++ -++#define DIFF(a,b) ((a>b)?(a-b):(b-a)) -++ -++static int calibrate_samples(void *xbuf, void *ybuf, void *pbuf, int count) -++{ -++ unsigned long *xp = (unsigned long *)xbuf; -++ unsigned long *yp = (unsigned long *)ybuf; -++ unsigned long *pp = (unsigned long *)pbuf; -++ unsigned long x_cal = 0, y_cal = 0, p_cal = 0, tmp; -++ int ignored, i, j; -++ int valid = 0; -++ -++ /* throw away the max cases */ -++ tmp = xp[0]; -++ ignored = 0; -++ for (i = 1; i < count; i++) { -++ if (xp[i] > tmp) { -++ tmp = xp[i]; -++ ignored = i; -++ } -++ } -++ j = 0; -++ for (i = 0; i < count; i++) { -++ if (i == ignored) -++ continue; -++ xp[j++] = xp[i]; -++ } -++ -++ tmp = yp[0]; -++ ignored = 0; -++ for (i = 1; i < count; i++) { -++ if (yp[i] > tmp) { -++ tmp = yp[i]; -++ ignored = i; -++ } -++ } -++ j = 0; -++ for (i = 0; i < count; i++) { -++ if (i == ignored) -++ continue; -++ yp[j++] = yp[i]; -++ } -++ -++ tmp = pp[0]; -++ ignored = 0; -++ for (i = 1; i < count; i++) { -++ if (pp[i] > tmp) { -++ tmp = pp[i]; -++ ignored = i; -++ } -++ } -++ j = 0; -++ for (i = 0; i < count; i++) { -++ if (i == ignored) -++ continue; -++ pp[j++] = pp[i]; -++ } -++ -++ /* throw away the min cases */ -++ -++ count -= 1; // decrement by 1 -++ -++ tmp = xp[0]; -++ ignored = 0; -++ for (i = 1; i < count; i++) { -++ if (xp[i] < tmp) { -++ tmp = xp[i]; -++ ignored = i; -++ } -++ } -++ j = 0; -++ for (i = 0; i < count; i++) { -++ if (i == ignored) -++ continue; -++ xp[j++] = xp[i]; -++ } -++ -++ tmp = yp[0]; -++ ignored = 0; -++ for (i = 1; i < count; i++) { -++ if (yp[i] < tmp) { -++ tmp = yp[i]; -++ ignored = i; -++ } -++ } -++ j = 0; -++ for (i = 0; i < count; i++) { -++ if (i == ignored) -++ continue; -++ yp[j++] = yp[i]; -++ } -++ -++ tmp = pp[0]; -++ ignored = 0; -++ for (i = 1; i < count; i++) { -++ if (pp[i] < tmp) { -++ tmp = pp[i]; -++ ignored = i; -++ } -++ } -++ j = 0; -++ for (i = 0; i < count; i++) { -++ if (i == ignored) -++ continue; -++ pp[j++] = pp[i]; -++ } -++ -++ count -= 1; // decrement by 1 -++ -++ /* calculate the average of the rest */ -++ for (i = 0; i < count; i++) { -++ x_cal += xp[i]; -++ y_cal += yp[i]; -++ p_cal += pp[i]; -++ } -++ x_cal /= count; -++ y_cal /= count; -++ p_cal /= count; -++ -++ if (first_time) { -++ first_time = 0; -++ last_x = x_cal; -++ last_y = y_cal; -++ last_p = p_cal; -++ valid = 1; -++ } -++ else { -++ if ((DIFF(x_cal, last_x) > 50) || -++ (DIFF(y_cal, last_y) > 50)) -++ valid = 0; -++ else -++ valid = 1; -++ } -++ -++// printk("x_cal=%d y_cal=%d p_cal=%d valid=%d\n", x_cal, y_cal, p_cal, valid); -++ -++ if (valid) { -++ *xp = last_x = x_cal; -++ *yp = last_y = y_cal; -++ *pp = last_p = p_cal; -++ } -++ -++ return valid; -++} -++ -++ -++#define TSMAXX 945 -++#define TSMAXY 830 -++#define TSMINX 90 -++#define TSMINY 105 -++ -++#define SCREEN_X 480 -++#define SCREEN_Y 272 -++ -++static unsigned long transform_to_screen_x(struct jz_ts_t *ts, unsigned long x ) -++{ -++ -++ if (ts->minx) -++ { -++ if (x < ts->minx) x = ts->minx; -++ if (x > ts->maxx) x = ts->maxx; -++ -++ return (x - ts->minx) * SCREEN_X / (ts->maxx - ts->minx); -++ } -++ else -++ { -++ if (x < TSMINX) x = TSMINX; -++ if (x > TSMAXX) x = TSMAXX; -++ -++ return (x - TSMINX) * SCREEN_X / (TSMAXX - TSMINX); -++ } -++} -++ -++static unsigned long transform_to_screen_y(struct jz_ts_t *ts, unsigned long y) -++{ -++ if (ts->minx) -++ { -++ if (y < ts->minx) y = ts->miny; -++ if (y > ts->maxx) y = ts->maxy; -++ -++ return (y - ts->miny) * SCREEN_Y / (ts->maxy - ts->miny); -++ } -++ else -++ { -++ if (y < TSMINX) y = TSMINY; -++ if (y > TSMAXX) y = TSMAXY; -++ -++ return (y - TSMINY) * SCREEN_Y / (TSMAXY - TSMINY); -++ } -++} -++ -++/*------------------ Common routines -------------------*/ -++ -++void ts_enable_irq(void) -++{ -++ /* interrupt mode */ -++ ucb1400_ts_mode_int(); -++ ucb1400_enable_irq(UCB_IRQ_TSPX, UCB_FALLING); -++ -++ enable_irq(TS_IRQ); -++} -++ -++void ts_disable_irq(void) -++{ -++ ucb1400_disable_irq(UCB_IRQ_TSPX, UCB_FALLING); -++ disable_irq(TS_IRQ); -++} -++ -++int ts_request_irq(u32 *irq, -++ void (*handler)(int, void *, struct pt_regs *), -++ const char *devname, -++ void *dev_id) -++{ -++ int retval; -++ -++ /* return the irq number */ -++ *irq = TS_IRQ; -++ -++ /* interrupt mode */ -++ ucb1400_ts_mode_int(); -++ ucb1400_enable_irq(UCB_IRQ_TSPX, UCB_FALLING); -++ -++ /* enable gpio irq */ -++ __gpio_as_irq_rise_edge(TS_PIN); -++ -++ /* register irq handler */ -++ retval = request_irq(TS_IRQ, handler, SA_INTERRUPT, devname, dev_id); -++ -++ return retval; -++} -++ -++void ts_free_irq(struct jz_ts_t *ts) -++{ -++ free_irq(ts->pendown_irq, ts); -++} -++ -++void ts_irq_callback(void) -++{ -++ /* clear interrupt status */ -++ ucb1400_reg_write(UCB_IE_CLEAR, ucb1400_reg_read(UCB_IE_STATUS)); -++ __gpio_ack_irq(TS_PIN); -++ -++ first_time = 1; // first time to acquire sample -++} -++ -++int PenIsDown(void) -++{ -++ unsigned int p; -++ -++ ucb1400_adc_enable(); -++ p = ucb1400_ts_read_pressure(); -++ ucb1400_adc_disable(); -++ -++ return (p > 100) ? 1 : 0; -++} -++ -++/* -++ * Acquire Raw pen coodinate data and compute touch screen -++ * pressure resistance. Hold spinlock when calling. -++ */ -++int AcquireEvent(struct jz_ts_t *ts, struct ts_event *event) -++{ -++ unsigned int x_raw[8], y_raw[8], p_raw[8]; -++ int valid, i; -++ -++ /* Enable ADC */ -++ ucb1400_adc_enable(); -++ -++ for (i = 0; i < samples; i++) { -++ x_raw[i] = ucb1400_ts_read_xpos(); -++ } -++ for (i = 0; i < samples; i++) { -++ y_raw[i] = ucb1400_ts_read_ypos(); -++ } -++ for (i = 0; i < samples; i++) { -++ p_raw[i] = ucb1400_ts_read_pressure(); -++ } -++ -++ /* Disable ADC */ -++ ucb1400_adc_disable(); -++ -++ valid = calibrate_samples(x_raw, y_raw, p_raw, samples); -++ -++ if (valid) { -++ unsigned int x_scr, y_scr; -++ -++ if(ts->filter) { -++ x_scr = transform_to_screen_x(ts, x_raw[0]); -++ y_scr = transform_to_screen_y(ts, y_raw[0]); -++ -++ if (ts->prints) -++ printk("x_raw=%d y_raw=%d x_transform=%d y_transform=%d\n", x_raw[0], y_raw[0], x_scr, y_scr); -++ } -++ else { -++ x_scr = x_raw[0]; -++ y_scr = y_raw[0]; -++ -++ if (ts->prints) -++ printk("x_raw=%d y_raw=%d \n", x_raw[0], y_raw[0]); -++ } -++ -++ event->x = x_scr; -++ event->y = y_scr; -++ event->pressure = (u16)p_raw[0]; -++ event->status = PENDOWN; -++ return 1; -++ } -++ return 0; -++} -++ -++/* -++ * Module init and exit -++ */ -++ -++int __init ucb1400_init(void) -++{ -++ ucb = kmalloc(sizeof(struct ucb1400), GFP_KERNEL); -++ if (!ucb) return -ENOMEM; -++ -++ memset(ucb, 0, sizeof(struct ucb1400)); -++ -++ codec_read_battery = ucb1400_read_battery; -++ -++ spin_lock_init(&ucb->lock); -++ sema_init(&ucb->adc_sem, 1); -++ -++ return 0; -++} -++ -++void ucb1400_cleanup(void) -++{ -++ kfree(ucb); -++} -++ -++module_init(ucb1400_init); -++module_exit(ucb1400_cleanup); -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/ucb1400.h linux-2.6.24.7/drivers/char/jzchar/ucb1400.h -+--- linux-2.6.24.7.old/drivers/char/jzchar/ucb1400.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/ucb1400.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,113 @@ -++#ifndef __UCB1400_H__ -++#define __UCB1400_H__ -++ -++/* ucb1400 aclink register mappings */ -++ -++#define UCB_IO_DATA 0x5a -++#define UCB_IO_DIR 0x5c -++#define UCB_IE_RIS 0x5e -++#define UCB_IE_FAL 0x60 -++#define UCB_IE_STATUS 0x62 -++#define UCB_IE_CLEAR 0x62 -++#define UCB_TS_CR 0x64 -++#define UCB_ADC_CR 0x66 -++#define UCB_ADC_DATA 0x68 -++#define UCB_ID 0x7e /* 7c is mfr id, 7e part id (from aclink spec) */ -++ -++#define UCB_ADC_DAT(x) ((x) & 0x3ff) -++ -++/* register bits */ -++ -++#define UCB_IO_0 (1 << 0) -++#define UCB_IO_1 (1 << 1) -++#define UCB_IO_2 (1 << 2) -++#define UCB_IO_3 (1 << 3) -++#define UCB_IO_4 (1 << 4) -++#define UCB_IO_5 (1 << 5) -++#define UCB_IO_6 (1 << 6) -++#define UCB_IO_7 (1 << 7) -++#define UCB_IO_8 (1 << 8) -++#define UCB_IO_9 (1 << 9) -++ -++#define UCB_IE_ADC (1 << 11) -++#define UCB_IE_TSPX (1 << 12) -++#define UCB_IE_TSMX (1 << 13) -++#define UCB_IE_TCLIP (1 << 14) -++#define UCB_IE_ACLIP (1 << 15) -++ -++#define UCB_IRQ_TSPX 12 -++ -++#define UCB_TC_A_LOOP (1 << 7) /* UCB1200 */ -++#define UCB_TC_A_AMPL (1 << 7) /* UCB1300 */ -++ -++#define UCB_TC_B_VOICE_ENA (1 << 3) -++#define UCB_TC_B_CLIP (1 << 4) -++#define UCB_TC_B_ATT (1 << 6) -++#define UCB_TC_B_SIDE_ENA (1 << 11) -++#define UCB_TC_B_MUTE (1 << 13) -++#define UCB_TC_B_IN_ENA (1 << 14) -++#define UCB_TC_B_OUT_ENA (1 << 15) -++ -++#define UCB_AC_B_LOOP (1 << 8) -++#define UCB_AC_B_MUTE (1 << 13) -++#define UCB_AC_B_IN_ENA (1 << 14) -++#define UCB_AC_B_OUT_ENA (1 << 15) -++ -++#define UCB_TS_CR_TSMX_POW (1 << 0) -++#define UCB_TS_CR_TSPX_POW (1 << 1) -++#define UCB_TS_CR_TSMY_POW (1 << 2) -++#define UCB_TS_CR_TSPY_POW (1 << 3) -++#define UCB_TS_CR_TSMX_GND (1 << 4) -++#define UCB_TS_CR_TSPX_GND (1 << 5) -++#define UCB_TS_CR_TSMY_GND (1 << 6) -++#define UCB_TS_CR_TSPY_GND (1 << 7) -++#define UCB_TS_CR_MODE_INT (0 << 8) -++#define UCB_TS_CR_MODE_PRES (1 << 8) -++#define UCB_TS_CR_MODE_POS (2 << 8) -++#define UCB_TS_CR_BIAS_ENA (1 << 11) -++#define UCB_TS_CR_TSPX_LOW (1 << 12) -++#define UCB_TS_CR_TSMX_LOW (1 << 13) -++ -++#define UCB_ADC_SYNC_ENA (1 << 0) -++#define UCB_ADC_VREFBYP_CON (1 << 1) -++#define UCB_ADC_INP_TSPX (0 << 2) -++#define UCB_ADC_INP_TSMX (1 << 2) -++#define UCB_ADC_INP_TSPY (2 << 2) -++#define UCB_ADC_INP_TSMY (3 << 2) -++#define UCB_ADC_INP_AD0 (4 << 2) -++#define UCB_ADC_INP_AD1 (5 << 2) -++#define UCB_ADC_INP_AD2 (6 << 2) -++#define UCB_ADC_INP_AD3 (7 << 2) -++#define UCB_ADC_EXT_REF (1 << 5) -++#define UCB_ADC_START (1 << 7) -++#define UCB_ADC_ENA (1 << 15) -++ -++#define UCB_ADC_DAT_VAL (1 << 15) -++ -++#define UCB_ID_1200 0x1004 -++#define UCB_ID_1300 0x1005 -++#define UCB_ID_1400 0x4304 -++#define UCB_ID_1400_BUGGY 0x4303 /* fake ID */ -++ -++#define UCB_MODE_DYN_VFLAG_ENA (1 << 12) -++#define UCB_MODE_AUD_OFF_CAN (1 << 13) -++ -++/* -++ * Which edges of the IRQ do you want to control today? -++ */ -++#define UCB_RISING (1 << 0) -++#define UCB_FALLING (1 << 1) -++ -++/* Device data structure */ -++ -++struct ucb1400 { -++ spinlock_t lock; -++ struct pm_dev *pmdev; -++ struct semaphore adc_sem; -++ u16 adc_cr; -++ u16 irq_fal_enbl; -++ u16 irq_ris_enbl; -++ int irq_enabled; -++}; -++ -++#endif /* __UCB1400_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/udc_hotplug.c linux-2.6.24.7/drivers/char/jzchar/udc_hotplug.c -+--- linux-2.6.24.7.old/drivers/char/jzchar/udc_hotplug.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/udc_hotplug.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,451 @@ -++/* -++ * linux/drivers/char/jzchar/udc_hotplug.c -++ * -++ * New UDC hotplug driver. -++ * -++ * Copyright (C) 2007 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include "jzchars.h" -++ -++#ifndef GPIO_UDC_HOTPLUG -++#define GPIO_UDC_HOTPLUG 86 -++#endif -++ -++#define UDC_HOTPLUG_PIN GPIO_UDC_HOTPLUG -++#define UDC_HOTPLUG_IRQ (IRQ_GPIO_0 + UDC_HOTPLUG_PIN) -++ -++#define dprintk(x,...) -++ -++//simple meaning define -++#define NOT_CONNECT 0 -++#define YES_CONNECT 1 -++#define MAX_GPIO_TIME 50 -++ -++#define EVENT_USB_ADD 1 -++#define EVENT_USB_REMOVE 2 -++#define EVENT_POWER_ADD 3 -++#define EVENT_POWER_REMOVE 4 -++#define EVENT_POWER_TO_USB 5 -++#define EVENT_USB_SUSPEND_POWER 6 -++ -++struct udc_pnp_stat -++{ -++ char cable_stat, old_cable_stat; -++ char protl_stat, old_protl_stat; -++ char object_stat1; -++ char object_stat2; -++}; -++ -++static struct udc_pnp_stat cur_pnp_stat; -++ -++static struct file_operations cable_fops = { -++ owner: THIS_MODULE, -++}; -++ -++static struct miscdevice cable_dev= -++{ -++ 231, -++ "udc_cable", -++ &cable_fops -++}; -++ -++static struct file_operations power_fops = { -++ owner: THIS_MODULE, -++}; -++ -++static struct miscdevice power_dev= -++{ -++ 232, -++ "power_cable", -++ &power_fops -++}; -++ -++int jz_udc_active = 0; /* 0: Have no actions; 1: Have actions */ -++ -++static int udc_pin_level; -++static int udc_old_state; -++static int udc_pin_time; -++ -++static struct timer_list udc_long_timer, udc_gpio_timer; -++ -++/* Kernel thread to deliver event to user space */ -++static struct task_struct *kudcd_task; -++ -++static void udc_gpio_timer_routine(unsigned long data) -++{ -++ wake_up_process(kudcd_task); -++} -++ -++static void udc_long_timer_routine(unsigned long data) -++{ -++ dprintk("udc_timer\n"); -++ if (jz_udc_active) -++ udc_old_state = 1; -++ if (!jz_udc_active && udc_old_state) //udc irq timeout! do suspend -++ { -++ dprintk("udc suspend!\n"); -++ udc_old_state = 0; -++ cur_pnp_stat.protl_stat = NOT_CONNECT; -++ del_timer(&udc_long_timer); -++ wake_up_process(kudcd_task); -++ return; -++ } -++ jz_udc_active = 0; -++ udc_long_timer.expires = jiffies + 3 * HZ; /* about 3 s */ -++ add_timer(&udc_long_timer); -++} -++ -++static int udc_get_pnp_stat(void) -++{ -++ udc_pin_level = __gpio_get_pin(UDC_HOTPLUG_PIN); -++ udc_pin_time = 1; -++ -++ init_timer(&udc_gpio_timer); -++ del_timer(&udc_gpio_timer); -++ udc_gpio_timer.function = udc_gpio_timer_routine; -++ udc_gpio_timer.expires = jiffies + 1; /* about 10 ms */ -++ add_timer(&udc_gpio_timer); -++ -++ while(1) -++ { -++ set_current_state(TASK_INTERRUPTIBLE); -++ schedule(); -++ -++ if (__gpio_get_pin(UDC_HOTPLUG_PIN) != udc_pin_level) -++ { -++ udc_pin_level = __gpio_get_pin(UDC_HOTPLUG_PIN); -++ udc_pin_time = 1; -++ dprintk("udc gpio detect restart! \n"); -++ } -++ -++ udc_pin_time ++; -++ if (udc_pin_time > MAX_GPIO_TIME) -++ break; -++ -++ del_timer(&udc_gpio_timer); -++ udc_gpio_timer.function = udc_gpio_timer_routine; -++ udc_gpio_timer.expires = jiffies + 1; /* about 10 ms */ -++ add_timer(&udc_gpio_timer); -++ } -++ -++ del_timer(&udc_gpio_timer); -++ if (__gpio_get_pin(UDC_HOTPLUG_PIN)) -++ return YES_CONNECT; -++ else -++ return NOT_CONNECT; -++} -++ -++static void udc_get_cable(void) -++{ -++ u32 intr_usb; -++ -++ __intc_mask_irq(IRQ_UDC); -++ -++ /* Now enable PHY to start detect */ -++#ifdef CONFIG_SOC_JZ4740 -++ REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; -++#elif CONFIG_SOC_JZ4750 -++ REG_CPM_OPCR |= CPM_OPCR_UDCPHY_ENABLE; -++#endif -++ /* Clear IRQs */ -++ REG16(USB_REG_INTRINE) = 0; -++ REG16(USB_REG_INTROUTE) = 0; -++ REG8(USB_REG_INTRUSBE) = 0; -++ -++ /* disable UDC IRQs first */ -++ REG16(USB_REG_INTRINE) = 0; -++ REG16(USB_REG_INTROUTE) = 0; -++ REG8(USB_REG_INTRUSBE) = 0; -++ -++ /* Disable DMA */ -++ REG32(USB_REG_CNTL1) = 0; -++ REG32(USB_REG_CNTL2) = 0; -++ -++ /* Enable HS Mode */ -++ REG8(USB_REG_POWER) |= USB_POWER_HSENAB; -++ /* Enable soft connect */ -++ REG8(USB_REG_POWER) |= USB_POWER_SOFTCONN; -++ -++ dprintk("enable phy! %x %x %x %x %x\n", -++ REG8(USB_REG_POWER), -++ REG_CPM_SCR, -++ REG16(USB_REG_INTRINE), -++ REG16(USB_REG_INTROUTE), -++ REG8(USB_REG_INTRUSBE)); -++ -++ init_timer(&udc_gpio_timer); -++ del_timer(&udc_gpio_timer); -++ udc_gpio_timer.function = udc_gpio_timer_routine; -++ udc_gpio_timer.expires = jiffies + 11; /* about 100 ms */ -++ add_timer(&udc_gpio_timer); -++ /* Sleep a short time to see result */ -++ set_current_state(TASK_INTERRUPTIBLE); -++ schedule(); -++ -++ del_timer(&udc_gpio_timer); -++ intr_usb = REG8(USB_REG_INTRUSB); -++ if ((intr_usb & USB_INTR_RESET) || -++ (intr_usb & USB_INTR_RESUME) || -++ (intr_usb & USB_INTR_SUSPEND)) -++ { -++ cur_pnp_stat.protl_stat = YES_CONNECT; -++ dprintk("cable is usb! \n"); -++ } -++ else -++ { -++ cur_pnp_stat.protl_stat = NOT_CONNECT; -++ dprintk("cable is power! \n"); -++ } -++ -++ /* Detect finish ,clean every thing */ -++ /* Disconnect from usb */ -++ REG8(USB_REG_POWER) &= ~USB_POWER_SOFTCONN; -++ /* Disable the USB PHY */ -++#ifdef CONFIG_SOC_JZ4740 -++ REG_CPM_SCR &= ~CPM_SCR_USBPHY_ENABLE; -++#elif CONFIG_SOC_JZ4750 -++ REG_CPM_OPCR &= ~CPM_OPCR_UDCPHY_ENABLE; -++#endif -++ /* Clear IRQs */ -++ REG16(USB_REG_INTRINE) = 0; -++ REG16(USB_REG_INTROUTE) = 0; -++ REG8(USB_REG_INTRUSBE) = 0; -++ __intc_ack_irq(IRQ_UDC); -++ __intc_unmask_irq(IRQ_UDC); -++} -++ -++static void send_event_udev(int event) -++{ -++ dprintk("Send udev message: cable=%d old=%d protl=%d old=%d \n", -++ cur_pnp_stat.cable_stat, -++ cur_pnp_stat.old_cable_stat, -++ cur_pnp_stat.protl_stat, -++ cur_pnp_stat.old_protl_stat); -++ -++ switch (event) -++ { -++ case EVENT_USB_ADD: -++ printk("usb cable insert! \n"); -++ misc_register(&cable_dev); -++ kobject_uevent(&cable_dev.this_device->kobj, KOBJ_ADD); -++ init_timer(&udc_long_timer); -++ del_timer(&udc_long_timer); -++ udc_long_timer.function = udc_long_timer_routine; -++ udc_long_timer.expires = jiffies + 3 * HZ; /* about 3 s */ -++ add_timer(&udc_long_timer); -++ break; -++ case EVENT_USB_REMOVE: -++ printk("usb cable remove! \n"); -++ kobject_uevent(&cable_dev.this_device->kobj, KOBJ_REMOVE); -++ misc_deregister(&cable_dev); -++ del_timer(&udc_long_timer); -++ break; -++ case EVENT_POWER_ADD: -++ printk("power cable insert! \n"); -++ misc_register(&power_dev); -++ kobject_uevent(&power_dev.this_device->kobj, KOBJ_ADD); -++ break; -++ case EVENT_POWER_REMOVE: -++ printk("power cable remove! \n"); -++ kobject_uevent(&power_dev.this_device->kobj, KOBJ_REMOVE); -++ misc_deregister(&power_dev); -++ break; -++ case EVENT_POWER_TO_USB: -++ printk("change power cable to usb! \n"); -++ kobject_uevent(&power_dev.this_device->kobj, KOBJ_REMOVE); -++ misc_deregister(&power_dev); -++ misc_register(&cable_dev); -++ kobject_uevent(&cable_dev.this_device->kobj, KOBJ_ADD); -++ break; -++ case EVENT_USB_SUSPEND_POWER: -++ printk("usb cable suspend! \n"); -++ printk("as power cable insert! \n"); -++ kobject_uevent(&cable_dev.this_device->kobj, KOBJ_REMOVE); -++ misc_deregister(&cable_dev); -++ misc_register(&power_dev); -++ kobject_uevent(&power_dev.this_device->kobj, KOBJ_ADD); -++ break; -++ }; -++} -++ -++static void udc_pnp_detect(void) -++{ -++ if (cur_pnp_stat.cable_stat == YES_CONNECT) /* already connected! */ -++ { -++ if (udc_get_pnp_stat() == NOT_CONNECT) -++ { -++ dprintk("cable real out! \n"); -++ cur_pnp_stat.cable_stat = NOT_CONNECT; -++ cur_pnp_stat.protl_stat = NOT_CONNECT; -++ /* Deliver this event to user space in udev model */ -++ if (cur_pnp_stat.old_protl_stat) -++ send_event_udev(EVENT_USB_REMOVE); -++ else -++ send_event_udev(EVENT_POWER_REMOVE); -++ cur_pnp_stat.old_cable_stat = cur_pnp_stat.cable_stat; -++ cur_pnp_stat.old_protl_stat = cur_pnp_stat.protl_stat; -++ } -++ else -++ { -++ if (cur_pnp_stat.old_protl_stat != cur_pnp_stat.protl_stat) -++ { -++ send_event_udev(EVENT_USB_SUSPEND_POWER); -++ cur_pnp_stat.old_cable_stat = cur_pnp_stat.cable_stat; -++ cur_pnp_stat.old_protl_stat = cur_pnp_stat.protl_stat; -++ } -++ else //change power to cable -++ { -++#if 0 //not support yet! -++ udc_get_cable(); -++ if (cur_pnp_stat.old_protl_stat != cur_pnp_stat.protl_stat) -++ send_event_udev(EVENT_POWER_TO_USB); -++ cur_pnp_stat.old_cable_stat = cur_pnp_stat.cable_stat; -++ cur_pnp_stat.old_protl_stat = cur_pnp_stat.protl_stat; -++#endif -++ } -++ } -++ } -++ else -++ { -++ if (udc_get_pnp_stat() == YES_CONNECT) -++ { -++ dprintk("cable real in! \n"); -++ cur_pnp_stat.cable_stat = YES_CONNECT; -++ udc_get_cable(); -++ /* Deliver this event to user space in udev model */ -++ if (cur_pnp_stat.protl_stat) -++ send_event_udev(EVENT_USB_ADD); -++ else -++ send_event_udev(EVENT_POWER_ADD); -++ cur_pnp_stat.old_cable_stat = cur_pnp_stat.cable_stat; -++ cur_pnp_stat.old_protl_stat = cur_pnp_stat.protl_stat; -++ } -++ else -++ dprintk("cable false in! \n"); -++ -++ } -++} -++ -++static void udc_pnp_set_gpio(void) -++{ -++ if (cur_pnp_stat.cable_stat == YES_CONNECT) -++ __gpio_as_irq_fall_edge(UDC_HOTPLUG_PIN); -++ else -++ __gpio_as_irq_rise_edge(UDC_HOTPLUG_PIN); -++ -++ /* clear interrupt pending status */ -++ __gpio_ack_irq(UDC_HOTPLUG_PIN); -++ /* unmask interrupt */ -++ __gpio_unmask_irq(UDC_HOTPLUG_PIN); -++} -++ -++static int udc_pnp_thread(void *unused) -++{ -++ printk(KERN_NOTICE "UDC starting pnp monitor thread\n"); -++ -++ while(1) -++ { -++ set_current_state(TASK_INTERRUPTIBLE); -++ schedule(); -++ -++ dprintk("pnp thread wake up! \n"); -++ /* wake up here */ -++ udc_pnp_detect(); -++ /* Reset gpio state last */ -++ udc_pnp_set_gpio(); -++ } -++} -++ -++static irqreturn_t udc_pnp_irq(int irq, void *dev_id) -++{ -++ -++ /* clear interrupt pending status */ -++ __gpio_ack_irq(UDC_HOTPLUG_PIN); -++ /* mask interrupt */ -++ __gpio_mask_irq(UDC_HOTPLUG_PIN); -++ /* wake up pnp detect thread */ -++ wake_up_process(kudcd_task); -++ -++ return IRQ_HANDLED; -++} -++ -++/* -++ * Module init and exit -++ */ -++static int __init udc_hotplug_init(void) -++{ -++ int retval; -++ /* Init pnp stat first */ -++ cur_pnp_stat.cable_stat = NOT_CONNECT; -++ cur_pnp_stat.protl_stat = NOT_CONNECT; -++ cur_pnp_stat.old_cable_stat = NOT_CONNECT; -++ cur_pnp_stat.old_protl_stat = NOT_CONNECT; -++ cur_pnp_stat.object_stat1 = NOT_CONNECT; -++ cur_pnp_stat.object_stat2 = NOT_CONNECT; -++ udc_old_state = 0; -++ -++ /* create pnp thread and register IRQ */ -++ kudcd_task = kthread_run(udc_pnp_thread, NULL, "kudcd"); -++ if (IS_ERR(kudcd_task)) { -++ printk(KERN_ERR "jz_udc_hotplug: Failed to create system monitor thread.\n"); -++ return PTR_ERR(kudcd_task); -++ } -++ -++ retval = request_irq(UDC_HOTPLUG_IRQ, udc_pnp_irq, -++ IRQF_DISABLED, "udc_pnp", NULL); -++ if (retval) { -++ printk("Could not get udc hotplug irq %d\n", UDC_HOTPLUG_IRQ); -++ return retval; -++ } -++ -++ /* get current pin level */ -++ __gpio_disable_pull(UDC_HOTPLUG_PIN); -++ __gpio_as_input(UDC_HOTPLUG_PIN); -++ udelay(1); -++ udc_pin_level = __gpio_get_pin(UDC_HOTPLUG_PIN); -++ -++ if (udc_pin_level) { -++ dprintk("Cable already in! \n"); -++ /* Post a event */ -++ wake_up_process(kudcd_task); -++ } -++ else { -++ __gpio_as_irq_rise_edge(UDC_HOTPLUG_PIN); -++ dprintk("Cable not in! \n"); -++ } -++ -++ printk("JZ UDC hotplug driver registered\n"); -++ -++ return 0; -++} -++ -++static void __exit udc_hotplug_exit(void) -++{ -++ free_irq(UDC_HOTPLUG_IRQ, NULL); -++} -++ -++module_init(udc_hotplug_init); -++module_exit(udc_hotplug_exit); -++ -++EXPORT_SYMBOL(jz_udc_active); -++ -++MODULE_AUTHOR("Lucifer "); -++MODULE_DESCRIPTION("JzSOC OnChip udc hotplug driver"); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/wm9712.c linux-2.6.24.7/drivers/char/jzchar/wm9712.c -+--- linux-2.6.24.7.old/drivers/char/jzchar/wm9712.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/wm9712.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,334 @@ -++/* -++ * wm9712.c -++ * -++ * Touch screen driver interface to the Wolfson WM9712 codec. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "jz_ts.h" -++#include "wm9712.h" -++ -++#define POLL_TIMES 10 -++ -++static int samples = 1; -++static int inited = 0, started = 0; -++ -++extern struct ac97_codec * find_ac97_codec(void); -++extern int PenIsDown(void); -++ -++ -++static inline void wm9712_reg_write(unsigned int reg, unsigned int val) -++{ -++ struct ac97_codec *codec = find_ac97_codec(); -++ if (!codec) -++ return; -++ codec->codec_write(codec, reg, val); -++} -++ -++static inline unsigned int wm9712_reg_read(unsigned int reg) -++{ -++ struct ac97_codec *codec = find_ac97_codec(); -++ if (!codec) -++ return 0; -++ return codec->codec_read(codec, reg); -++} -++ -++static unsigned int wm9712_adc_read(int adc_channel) -++{ -++ unsigned int val; -++ -++ if (!PenIsDown()) -++ return 0; -++ -++ val = wm9712_reg_read(DIGI_REG1); -++ wm9712_reg_write(DIGI_REG1, val|adc_channel|DIGI_REG1_POLL); -++ -++ for (;;) { -++ if (wm9712_reg_read(0x54) & (1 << 12)) { -++ val = wm9712_reg_read(DIGI_READBACK); -++ break; -++ } -++ } -++ -++ /* stop the measure */ -++ wm9712_reg_write(DIGI_REG1, 0); -++ -++ return (val & 0x0fff); -++} -++ -++static struct timer_list pndn_timer; -++static void (*irq_handler)(int, void *, struct pt_regs *) = NULL; -++ -++void ts_irq_callback(void) -++{ -++#ifdef TS_IRQ -++ __gpio_ack_irq(TS_IRQ); -++#else -++#endif -++} -++ -++void ts_enable_irq(void) -++{ -++ if (!inited) -++ return; -++#ifdef TS_IRQ -++ enable_irq(TS_IRQ); -++#else -++ pndn_timer.expires = jiffies + HZ/POLL_TIMES; -++ add_timer(&pndn_timer); -++#endif -++} -++ -++void ts_disable_irq(void) -++{ -++ if (!inited) -++ return; -++#ifdef TS_IRQ -++ disable_irq(TS_IRQ); -++#endif -++} -++ -++#ifndef TS_IRQ -++static void pndn_detect(unsigned long data) -++{ -++ if (PenIsDown()) { -++ if (!started) -++ return; -++ if (irq_handler) -++ irq_handler(NULL, data, NULL); -++ } else { -++ pndn_timer.expires = jiffies + HZ/POLL_TIMES; -++ add_timer(&pndn_timer); -++ } -++} -++#endif -++ -++void ts_free_irq(struct jz_ts_t *ts) -++{ -++#ifdef TS_IRQ -++ free_irq(ts->pendown_irq, ts); -++#else -++ started = 0; -++ del_timer_sync(&pndn_timer); -++#endif -++} -++ -++int ts_request_irq(u32 *irq, -++ void (*handler)(int, void *, struct pt_regs *), -++ const char *devname, -++ void *dev_id) -++{ -++ /* 4wire, Ip=400uA, Rpu=64Kohm/64, wake-up on pendown without -++ * reset, meassure on pen down. Do not use wait mode. -++ */ -++ started = 1; -++ if (!inited) { -++ wm9712_reg_write(DIGI_REG2, -++ DIGI_REG2_WIRE_4 | -++ DIGI_REG2_PIL_200uA | -++ (31 << DIGI_REG2_RPU_BIT) | -++ DIGI_REG2_PRP_ALLON | -++ DIGI_REG2_RPR_NWOR); -++ /* Polling mode and no measurement */ -++ wm9712_reg_write(DIGI_REG1, 0); -++ } -++ -++#ifdef TS_IRQ -++ /* Generate irq request on PENDOWN pin, pendown cause the level high */ -++ wm9712_reg_write(0x56, wm9712_reg_read(0x56) & ~(1 << 3)); -++ wm9712_reg_write(0x4c, wm9712_reg_read(0x4c) & ~(1 << 3)); -++ -++ *irq = TS_IRQ; -++ return request_irq(TS_IRQ, handler, SA_INTERRUPT, devname, dev_id); -++#else -++ if (!inited) { -++ irq_handler = handler; -++ init_timer(&pndn_timer); -++ pndn_timer.function = pndn_detect; -++ pndn_timer.data = (unsigned long)dev_id; -++ pndn_timer.expires = jiffies + HZ/POLL_TIMES; -++ add_timer(&pndn_timer); -++ inited = 1; -++ } else { -++ pndn_timer.expires = jiffies + HZ/POLL_TIMES; -++ add_timer(&pndn_timer); -++ } -++ return 0; -++#endif -++} -++ -++int PenIsDown(void) -++{ -++ if (wm9712_reg_read(DIGI_READBACK) & DIGI_READBACK_PNDN) -++ return 1; -++ return 0; -++} -++ -++#if defined(CONFIG_MIPS_JZ4730_GPS) -++#define adj_data(r1, r2, r3, s) \ -++do { \ -++ if (r1 < 0x90) \ -++ r1 = 0x90; \ -++ if (r2 < 0xed) \ -++ r2 = 0xed; \ -++ r1 = ((r1 - 0x90) * 240) / 3354; \ -++ r2 = ((r2 - 0xed) * 320) / 3671; \ -++ if (r1 > 239) \ -++ r1 = 239; \ -++ if (r2 > 319) \ -++ r2 = 319; \ -++ \ -++ *s = r2; \ -++ *(s+1) = 239 - r1; \ -++ *(s+2) = z_raw; \ -++} while (0) -++#endif -++ -++#ifndef adj_data -++#define adj_data(r1, r2, r3, s) -++#endif -++ -++static int read_adc(unsigned int *sdata) -++{ -++ unsigned long x_raw=0, y_raw=0, z_raw=0, t, fail = 0; -++ int i; -++ -++ for (i=0; i 1) { -++ x_raw = (x_raw + (samples>>1)) / samples; -++ y_raw = (y_raw + (samples>>1)) / samples; -++ z_raw = (z_raw + (samples>>1)) / samples; -++ } -++ -++ adj_data (x_raw, y_raw, z_raw, sdata); -++ -++ return 1; -++} -++ -++ -++#define TSMAXX 945 -++#define TSMAXY 830 -++#define TSMINX 90 -++#define TSMINY 105 -++ -++#define SCREEN_X 480 -++#define SCREEN_Y 272 -++ -++static unsigned long transform_to_screen_x(struct jz_ts_t *ts, unsigned long x ) -++{ -++ -++ if (ts->minx) -++ { -++ if (x < ts->minx) x = ts->minx; -++ if (x > ts->maxx) x = ts->maxx; -++ -++ return (x - ts->minx) * SCREEN_X / (ts->maxx - ts->minx); -++ } -++ else -++ { -++ if (x < TSMINX) x = TSMINX; -++ if (x > TSMAXX) x = TSMAXX; -++ -++ return (x - TSMINX) * SCREEN_X / (TSMAXX - TSMINX); -++ } -++} -++ -++static unsigned long transform_to_screen_y(struct jz_ts_t *ts, unsigned long y) -++{ -++ if (ts->minx) -++ { -++ if (y < ts->minx) y = ts->miny; -++ if (y > ts->maxx) y = ts->maxy; -++ -++ return (y - ts->miny) * SCREEN_Y / (ts->maxy - ts->miny); -++ } -++ else -++ { -++ if (y < TSMINX) y = TSMINY; -++ if (y > TSMAXX) y = TSMAXY; -++ -++ return (y - TSMINY) * SCREEN_Y / (TSMAXY - TSMINY); -++ } -++} -++ -++ -++/* -++ * Acquire Raw pen coodinate data and compute touch screen -++ * pressure resistance. Hold spinlock when calling. -++ */ -++int AcquireEvent(struct jz_ts_t *ts, struct ts_event *event) -++{ -++ unsigned int s[3]; -++ unsigned int x_scr, y_scr; -++ if (!read_adc(s)) -++ return 0; -++ if(ts->filter) { -++ x_scr = transform_to_screen_x(ts, s[0]); -++ y_scr = transform_to_screen_y(ts, s[1]); -++ -++ if (ts->prints) -++ printk("x_raw=%d y_raw=%d x_transform=%d y_transform=%d\n", s[0], s[1], x_scr, y_scr); } -++ else { -++ x_scr = s[0]; -++ y_scr = s[1]; -++ -++ if (ts->prints) -++ printk("x_raw=%d y_raw=%d \n", s[0], s[1]); -++ } -++ event->x = x_scr; -++ event->y = y_scr; -++ event->pressure = (u16)s[2]; -++ event->status = PENDOWN; -++ return 1; -++#if 0 -++ do_gettimeofday(&event->stamp); -++#endif -++} -++ -++int __init wm9712_init(void) -++{ -++ return 0; -++} -++ -++void wm9712_cleanup(void) -++{ -++} -++ -++module_init(wm9712_init); -++module_exit(wm9712_cleanup); -++ -+diff -urN linux-2.6.24.7.old/drivers/char/jzchar/wm9712.h linux-2.6.24.7/drivers/char/jzchar/wm9712.h -+--- linux-2.6.24.7.old/drivers/char/jzchar/wm9712.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/jzchar/wm9712.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,58 @@ -++#ifndef __WM9712_H__ -++#define __WM9712_H__ -++ -++#define DIGI_REG1 0x76 -++#define DIGI_REG2 0x78 -++#define DIGI_READBACK 0x7A -++ -++#define ADCSEL_BIT 12 -++#define ADCSEL_MASK (7 << ADCSEL_BIT) -++#define ADCSEL_NONE (0 << ADCSEL_BIT) -++#define ADCSEL_XPOS (1 << ADCSEL_BIT) -++#define ADCSEL_YPOS (2 << ADCSEL_BIT) -++#define ADCSEL_PRESSURE (3 << ADCSEL_BIT) -++#define ADCSEL_COMP1 (4 << ADCSEL_BIT) -++#define ADCSEL_COMP2 (5 << ADCSEL_BIT) -++#define ADCSEL_BMON (6 << ADCSEL_BIT) -++#define ADCSEL_WIPER (7 << ADCSEL_BIT) -++ -++#define DIGI_REG1_CTC (1 << 10) -++#define DIGI_REG1_POLL (1 << 15) -++#define DIGI_REG1_CR_BIT 8 -++#define DIGI_REG1_CR_MASK (3 << DIGI_REG1_CR_BIT) -++#define DIGI_REG1_COO (1 << 11) -++#define DIGI_REG1_SLEN (1 << 3) -++#define DIGI_REG1_SLT_BIT 0 -++#define DIGI_REG1_SLT_MASK (7 << DIGI_REG1_SLT_BIT) -++#define DIGI_REG1_SLT_5 (0 << DIGI_REG1_SLT_BIT) -++#define DIGI_REG1_SLT_6 (1 << DIGI_REG1_SLT_BIT) -++#define DIGI_REG1_SLT_7 (2 << DIGI_REG1_SLT_BIT) -++#define DIGI_REG1_SLT_8 (3 << DIGI_REG1_SLT_BIT) -++#define DIGI_REG1_SLT_9 (4 << DIGI_REG1_SLT_BIT) -++#define DIGI_REG1_SLT_10 (5 << DIGI_REG1_SLT_BIT) -++#define DIGI_REG1_SLT_11 (6 << DIGI_REG1_SLT_BIT) -++#define DIGI_REG1_SLT_RES (7 << DIGI_REG1_SLT_BIT) -++#define DIGI_REG1_DEL_BIT 4 -++#define DIGI_REG1_DEL_MASK (0x0f << DIGI_REG1_DEL_BIT) -++ -++#define DIGI_REG2_WIRE_5 (1 << 12) -++#define DIGI_REG2_WIRE_4 (0 << 12) -++#define DIGI_REG2_RPU_BIT 0 -++#define DIGI_REG2_RPU_MASK (0x3f << DIGI_REG2_RPU_BIT) -++#define DIGI_REG2_PIL_400uA (1 << 8) -++#define DIGI_REG2_PIL_200uA (0 << 8) -++#define DIGI_REG2_PRP_BIT 14 -++#define DIGI_REG2_PRP_MASK (3 << DIGI_REG2_PRP_BIT) -++#define DIGI_REG2_PRP_ALLOFF (0 << DIGI_REG2_PRP_BIT) -++#define DIGI_REG2_PRP_WOP (1 << DIGI_REG2_PRP_BIT) -++#define DIGI_REG2_PRP_NWOP (2 << DIGI_REG2_PRP_BIT) -++#define DIGI_REG2_PRP_ALLON (3 << DIGI_REG2_PRP_BIT) -++#define DIGI_REG2_RPR_WOR (0 << 13) -++#define DIGI_REG2_RPR_NWOR (1 << 13) -++#define DIGI_REG2_PDEN (1 << 11) -++#define DIGI_REG2_WAIT (1 << 9) -++ -++#define DIGI_READBACK_PNDN (1 << 15) -++ -++#endif /* __WM9712_H__ */ -++ -+diff -urN linux-2.6.24.7.old/drivers/char/rtc_jz.c linux-2.6.24.7/drivers/char/rtc_jz.c -+--- linux-2.6.24.7.old/drivers/char/rtc_jz.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/rtc_jz.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,503 @@ -++/* -++ * Jz OnChip Real Time Clock interface for Linux -++ * -++ * NOTE: we need to wait rtc write ready before read or write RTC registers. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include /* get the user-level API */ -++#include -++#include -++ -++#include "rtc_jz.h" -++ -++ -++char sbin_rtc_alarm_handler_path[] = "/sbin/rtcalarm"; -++//call_usermodehelper(char *path, char **argv, char **envp, int wait) -++//extern int call_usermodehelper(char *path, char **argv, char **envp); -++ -++extern spinlock_t rtc_lock; -++ -++static int rtc_ioctl(struct inode *inode, struct file *file, -++ unsigned int cmd, unsigned long arg); -++ -++ -++static void get_rtc_time (struct rtc_time *rtc_tm); -++static int set_rtc_time (struct rtc_time *rtc_tm); -++static void get_rtc_alm_time (struct rtc_time *alm_tm); -++static int set_rtc_alm_time (struct rtc_time *alm_tm); -++ -++static void set_rtc_irq_bit(int bit); -++static void mask_rtc_irq_bit(int bit); -++ -++static unsigned int rtc_status = 0; -++static unsigned int epoch = 1900; -++ -++static void get_rtc_time(struct rtc_time *rtc_tm) -++{ -++ unsigned long lval; -++ struct rtc_time ltm; -++ -++ spin_lock_irq(&rtc_lock); -++ while ( !__rtc_write_ready() ) ; -++ lval = REG_RTC_RSR; -++ rtc_time_to_tm(lval, <m); -++ if(rtc_valid_tm(<m) == 0) { -++ /* is valid */ -++ rtc_tm->tm_sec = ltm.tm_sec; -++ rtc_tm->tm_min = ltm.tm_min; -++ rtc_tm->tm_hour = ltm.tm_hour; -++ rtc_tm->tm_mday = ltm.tm_mday; -++ rtc_tm->tm_wday = ltm.tm_wday; -++ rtc_tm->tm_mon = ltm.tm_mon; -++ rtc_tm->tm_year = ltm.tm_year; -++ } else { -++ printk("invlaid data / time!\n"); -++ } -++ spin_unlock_irq(&rtc_lock); -++} -++ -++static int set_rtc_time(struct rtc_time *rtc_tm) -++{ -++ unsigned long lval; -++ -++ rtc_tm_to_time(rtc_tm, &lval); -++ -++ spin_lock_irq(&rtc_lock); -++ while ( !__rtc_write_ready() ) ; -++ REG_RTC_RSR = lval; -++ -++ spin_unlock_irq(&rtc_lock); -++ -++ return 0; -++ -++} -++ -++static void get_rtc_alm_time(struct rtc_time *alm_tm) -++{ -++ unsigned long lval; -++ struct rtc_time altm; -++ -++ spin_lock_irq(&rtc_lock); -++ while ( !__rtc_write_ready() ) ; -++ lval = REG_RTC_RSAR; -++ rtc_time_to_tm(lval, &altm); -++ if(rtc_valid_tm(&altm) == 0) { -++ /* is valid */ -++ alm_tm->tm_sec = altm.tm_sec; -++ alm_tm->tm_min = altm.tm_min; -++ alm_tm->tm_hour = altm.tm_hour; -++ alm_tm->tm_mday = altm.tm_mday; -++ alm_tm->tm_wday = altm.tm_wday; -++ alm_tm->tm_mon = altm.tm_mon; -++ alm_tm->tm_year = altm.tm_year; -++ } else { -++ printk("invlaid data / time in Line:%d!\n",__LINE__); -++ } -++ spin_unlock_irq(&rtc_lock); -++} -++ -++static int set_rtc_alm_time(struct rtc_time *alm_tm) -++{ -++ unsigned long lval; -++ -++ rtc_tm_to_time(alm_tm, &lval); -++ -++ spin_lock_irq(&rtc_lock); -++ while ( !__rtc_write_ready() ) ; -++ REG_RTC_RSAR = lval; -++ -++ while ( !__rtc_write_ready() ) ; /* set alarm function */ -++ if ( !((REG_RTC_RCR>>2) & 0x1) ) { -++ while ( !__rtc_write_ready() ) ; -++ __rtc_enable_alarm(); -++ } -++ -++ while ( !__rtc_write_ready() ) ; -++ if ( !(REG_RTC_RCR & RTC_RCR_AIE) ) { /* Enable alarm irq */ -++ __rtc_enable_alarm_irq(); -++ } -++ -++ spin_unlock_irq(&rtc_lock); -++ -++ return 0; -++} -++ -++static void get_rtc_wakeup_alarm(struct rtc_wkalrm *wkalm) -++{ -++ int enabled, pending; -++ -++ get_rtc_alm_time(&wkalm->time); -++ -++ spin_lock_irq(&rtc_lock); -++ while ( !__rtc_write_ready() ) ; -++ enabled = (REG_RTC_HWCR & 0x1); -++ pending = 0; -++ if ( enabled ) { -++ if ( (u32)REG_RTC_RSAR > (u32)REG_RTC_RSR ) /* 32bit val */ -++ pending = 1; -++ } -++ -++ wkalm->enabled = enabled; -++ wkalm->pending = pending; -++ spin_unlock_irq(&rtc_lock); -++} -++ -++static int set_rtc_wakeup_alarm(struct rtc_wkalrm *wkalm) -++{ -++ int enabled; -++ //int pending; -++ -++ enabled = wkalm->enabled; -++ //pending = wkalm->pending; /* Fix me, what's pending mean??? */ -++ -++ while ( !__rtc_write_ready() ) ; /* set wakeup alarm enable */ -++ if ( enabled != (REG_RTC_HWCR & 0x1) ) { -++ while ( !__rtc_write_ready() ) ; -++ REG_RTC_HWCR = (REG_RTC_HWCR & ~0x1) | enabled; -++ } -++ while ( !__rtc_write_ready() ) ; /* set alarm function */ -++ if ( enabled != ((REG_RTC_RCR>>2) & 0x1) ) { -++ while ( !__rtc_write_ready() ) ; -++ REG_RTC_RCR = (REG_RTC_RCR & ~(1<<2)) | (enabled<<2); -++ } -++ -++ if ( !enabled ) /* if disabled wkalrm, rturn. */ -++ { -++ return 0; -++ } -++ -++ while ( !__rtc_write_ready() ) ; -++ if ( !(REG_RTC_RCR & RTC_RCR_AIE) ) { /* Enable alarm irq */ -++ __rtc_enable_alarm_irq(); -++ } -++ -++ set_rtc_alm_time(&wkalm->time); -++ -++ return 0; -++} -++ -++ -++static void set_rtc_irq_bit( int bit ) -++{ -++ spin_lock_irq(&rtc_lock); -++ -++ while ( !__rtc_write_ready() ) ; -++ REG_RTC_RCR |= (1<= 0xc0 -++ * means "don't care" or "match all". Only the tm_hour, -++ * tm_min, and tm_sec values are filled in. -++ */ -++ -++ get_rtc_alm_time(&wtime); -++ return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; -++ -++ case RTC_ALM_SET: /* Store a time into the alarm */ -++ { -++ struct rtc_time alm_tm; -++ -++ if (copy_from_user(&alm_tm, (struct rtc_time*)arg, -++ sizeof(struct rtc_time))) -++ return -EFAULT; -++ if(rtc_valid_tm(&alm_tm) != 0) { -++ printk("invalid time set in Line:%d! \n",__LINE__); -++ return -EFAULT; -++ } -++ -++ return set_rtc_alm_time(&alm_tm); -++ } -++ case RTC_RD_TIME: /* Read the time/date from RTC */ -++ get_rtc_time(&wtime); -++ return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; -++ case RTC_SET_TIME: /* Set the RTC */ -++ { -++ struct rtc_time rtc_tm; -++ -++ if (!capable(CAP_SYS_TIME)) -++ return -EACCES; -++ -++ if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, -++ sizeof(struct rtc_time))) -++ return -EFAULT; -++ if(rtc_valid_tm(&rtc_tm) != 0) { -++ printk("invalid time set in Line:%d! \n",__LINE__); -++ return -EFAULT; -++ } -++ -++ return set_rtc_time(&rtc_tm); -++ } -++ case RTC_EPOCH_READ: /* Read the epoch. */ -++ return put_user (epoch, (unsigned long *)arg); -++ case RTC_EPOCH_SET: /* Set the epoch. */ -++ /* -++ * There were no RTC clocks before 1900. -++ */ -++ if (arg < 1900) -++ return -EINVAL; -++ -++ if (!capable(CAP_SYS_TIME)) -++ return -EACCES; -++ -++ epoch = arg; -++ return 0; -++ case RTC_WKALM_SET: /* Wake alarm set. */ -++ { -++ struct rtc_wkalrm wkalrm; -++ -++ if (copy_from_user(&wkalrm, (struct rtc_wkalrm*)arg, -++ sizeof(struct rtc_wkalrm))) -++ return -EFAULT; -++ return set_rtc_wakeup_alarm(&wkalrm); -++ } -++ case RTC_WKALM_RD: /* Wake alarm read. */ -++ { -++ struct rtc_wkalrm wkalrm; -++ get_rtc_wakeup_alarm(&wkalrm); -++ return copy_to_user((void *)arg, &wkalrm, sizeof(struct rtc_wkalrm)) ? -EFAULT : 0; -++ } -++ /* set power down: shut down the machine. */ -++ case RTC_POWER_DOWN: /* enter HIBERNATE mode */ -++ dprintk("Power down. Bye....\n"); -++ while ( !__rtc_write_ready() ) ; -++ REG_RTC_HCR = 0x1; -++ return 0; -++#ifdef DEBUG -++ case RTC_PRINT_REG: /* Print RTC registers */ -++ print_rtc_registers(); -++ return 0; -++#endif -++ default: -++ return -EINVAL; -++ } -++ return 0; -++} -++ -++/* -++ * We enforce only one user at a time here with the open/close. -++ * Also clear the previous interrupt data on an open, and clean -++ * up things on a close. -++ */ -++ -++/* We use rtc_lock to protect against concurrent opens. So the BKL is not -++ * needed here. Or anywhere else in this driver. */ -++static int rtc_open(struct inode *inode, struct file *file) -++{ -++ spin_lock_irq (&rtc_lock); -++ -++ if(rtc_status) -++ goto out_busy; -++ -++ rtc_status = 1; -++ -++ spin_unlock_irq (&rtc_lock); -++ return 0; -++ -++out_busy: -++ return -EBUSY; -++} -++ -++static int rtc_release(struct inode *inode, struct file *file) -++{ -++ -++ rtc_status = 0; -++ /* No need for locking -- nobody else can do anything until this rmw is -++ * committed, and no timer is running. */ -++ return 0; -++} -++ -++/* -++ * The various file operations we support. -++ */ -++ -++static struct file_operations rtc_fops = { -++ owner: THIS_MODULE, -++ llseek: no_llseek, -++ ioctl: rtc_ioctl, -++ open: rtc_open, -++ release: rtc_release, -++}; -++ -++ -++static void run_sbin_rtc_alarm( void ) -++{ -++ int i; -++ char *argv[2], *envp[3]; -++ -++ if (!sbin_rtc_alarm_handler_path[0]) -++ return; -++ -++ print_dbg(": sbin_rtc_alarm_handler_path=%s\n", sbin_rtc_alarm_handler_path); -++ -++ i = 0; -++ argv[i++] = sbin_rtc_alarm_handler_path; -++ argv[i] = 0; -++ -++ /* minimal command environment */ -++ i = 0; -++ envp[i++] = "HOME=/"; -++ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; -++ -++ /* other stuff we want to pass to /sbin/hotplug */ -++ -++ envp[i] = 0; -++ -++ call_usermodehelper (argv [0], argv, envp, 0); -++} -++ -++static void rtc_alarm_task_handler(struct work_struct *work) -++{ -++ run_sbin_rtc_alarm(); -++} -++ -++static struct work_struct rtc_alarm_task; -++ -++static irqreturn_t jz_rtc_interrupt(int irq, void *dev_id) -++{ -++ REG_RTC_HCR = 0x0; -++ printk("%s:%s:%d\n",__FILE__,__FUNCTION__,__LINE__); -++ spin_lock_irq(&rtc_lock); -++ -++ if ( __rtc_get_1Hz_flag() ) { -++ while ( !__rtc_write_ready() ) ; -++ __rtc_clear_1Hz_flag(); -++ dprintk("RTC 1Hz interrupt occur.\n"); -++ } -++ -++ if ( __rtc_get_alarm_flag() ) { /* rtc alarm interrupt */ -++ while ( !__rtc_write_ready() ) ; -++ __rtc_clear_alarm_flag(); -++ dprintk("RTC alarm interrupt occur.\n"); -++ //schedule_task( &rtc_alarm_task ); -++ schedule_work( &rtc_alarm_task ); -++ } -++ spin_unlock_irq(&rtc_lock); -++ -++ return IRQ_HANDLED; -++} -++ -++ -++#define RTC_MINOR 135 -++ -++static struct miscdevice rtc_dev= -++{ -++ RTC_MINOR, -++ "rtc", -++ &rtc_fops -++}; -++ -++int __init Jz_rtc_init(void) -++{ -++ -++ INIT_WORK(&rtc_alarm_task, rtc_alarm_task_handler); -++ -++ /* Enabled rtc function, enable rtc alarm function */ -++ while ( !__rtc_write_ready() ) ; /* need we wait for WRDY??? */ -++ if ( !(REG_RTC_RCR & RTC_RCR_RTCE) || !(REG_RTC_RCR &RTC_RCR_AE) ) { -++ REG_RTC_RCR |= RTC_RCR_AE | RTC_RCR_RTCE; -++ } -++ /* clear irq flags */ -++ __rtc_clear_1Hz_flag(); -++ /* In a alarm reset, we expect a alarm interrupt. -++ * We can do something in the interrupt handler. -++ * So, do not clear alarm flag. -++ */ -++/* __rtc_clear_alarm_flag(); */ -++ -++ if (request_irq(IRQ_RTC, jz_rtc_interrupt, 0, "rtc", NULL) < 0) -++ return -EBUSY; -++ -++ misc_register(&rtc_dev); -++ -++ printk("JzSOC onchip RTC installed !!!\n"); -++ return 0; -++ -++} -++ -++void __exit Jz_rtc_exit (void) -++{ -++ misc_deregister(&rtc_dev); -++ free_irq (IRQ_RTC, NULL); -++} -++ -++module_init(Jz_rtc_init); -++module_exit(Jz_rtc_exit); -++ -+diff -urN linux-2.6.24.7.old/drivers/char/rtc_jz.h linux-2.6.24.7/drivers/char/rtc_jz.h -+--- linux-2.6.24.7.old/drivers/char/rtc_jz.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/rtc_jz.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,74 @@ -++#ifndef __RTC_JZ_H__ -++#define __RTC_JZ_H__ -++ -++//#define DEBUG 1 -++#undef DEBUG -++ -++#ifdef DEBUG -++#define dprintk(x...) printk(x) -++#define print_dbg(f, arg...) \ -++ printk("%s, %s[%d]:" f , __FUNCTION__, __FILE__, __LINE__ , ##arg ) -++#else -++#define dprintk(x...) -++#define print_dbg(n, arg...) -++#endif -++ -++ -++#ifdef DEBUG -++ -++static void print_rtc_time( struct rtc_time * tm ) -++{ -++ printk("%02d%02d-%02d:%02d:%02d-%d\n", tm->tm_mon, tm->tm_mday, -++ tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_year); -++ printk("sec:\t%d\n", tm->tm_sec); -++ printk("min:\t%d\n", tm->tm_min); -++ printk("hour:\t%d\n", tm->tm_hour); -++ printk("mday:\t%d\n", tm->tm_mday); -++ printk("mon:\t%d\n", tm->tm_mon); -++ printk("year:\t%d\n", tm->tm_year); -++ printk("wday:\t%d\n", tm->tm_wday); -++ printk("yday:\t%d\n", tm->tm_yday); -++ printk("isdst:\t%d\n", tm->tm_isdst); -++ -++} -++ -++static void print_rtc_registers( void ) -++{ -++ while ( !__rtc_write_ready() ) ; -++ printk("REG_RTC_RCR:\t 0x%8.8x\n", REG_RTC_RCR ); -++ printk("REG_RTC_RSR:\t 0x%8.8x\n", REG_RTC_RSR ); -++ printk("REG_RTC_RSAR:\t 0x%8.8x\n", REG_RTC_RSAR ); -++ printk("REG_RTC_RGR:\t 0x%8.8x\n", REG_RTC_RGR ); -++ printk("REG_RTC_HCR:\t 0x%8.8x\n", REG_RTC_HCR ); -++ printk("REG_RTC_HWFCR:\t 0x%8.8x\n", REG_RTC_HWFCR ); -++ printk("REG_RTC_HRCR:\t 0x%8.8x\n", REG_RTC_HRCR ); -++ printk("REG_RTC_HWCR:\t 0x%8.8x\n", REG_RTC_HWCR ); -++ printk("REG_RTC_HWRSR:\t 0x%8.8x\n", REG_RTC_HWRSR ); -++ printk("REG_RTC_HSPR:\t 0x%8.8x\n", REG_RTC_HSPR ); -++} -++ -++#define RTC_PRINT_REG _IOR('p', 0x12, unsigned long)/* Set power down */ -++#endif /* #ifdef DEBUG */ -++ -++ -++/* -++ * JZSOC ioctl calls that are permitted to the /dev/rtc interface -++ */ -++ -++#define RTC_ENABLED _IO('p', 0x11) /* enable rtc */ -++#define RTC_DISABLED _IO('p', 0x12) /* disable rtc */ -++#define RTC_ALM_ON _IO('p', 0x13) /* enable rtc */ -++#define RTC_ALM_OFF _IO('p', 0x14) /* disable rtc */ -++#define RTC_1HZIE_ON _IO('p', 0x15) /* 1Hz int. enable on */ -++#define RTC_1HZIE_OFF _IO('p', 0x16) /* ... off */ -++ -++#define RTC_POWER_DOWN _IOR('p', 0x11, unsigned long)/* Set power down */ -++ -++/* Registers define */ -++/* RTC Control register */ -++#define RTC_AIE 3 /* jz4740_06_rtc_spec.pdf, RTC Control Register */ -++#define RTC_1HZIE 5 /* ... */ -++#define RTC_ALM_EN 2 /* ... */ -++#define RTC_EN 0 /* ... */ -++ -++#endif /* #define __RTC_JZ_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/char/rtc_pcf8563.c linux-2.6.24.7/drivers/char/rtc_pcf8563.c -+--- linux-2.6.24.7.old/drivers/char/rtc_pcf8563.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/char/rtc_pcf8563.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,448 @@ -++/* -++ * PCF8563 Real Time Clock interface for Linux -++ * -++ * It only support 24Hour Mode, And the stored values are in BCD format. -++ * The alarm register is start at minute reg, no second alarm register. -++ */ -++ -++//#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include /* get the user-level API */ -++#include -++#include -++ -++/********************************************************************** -++ * register summary -++ **********************************************************************/ -++#define RTC_SECONDS 2 -++#define RTC_MINUTES 3 -++#define RTC_HOURS 4 -++#define RTC_DAY_OF_MONTH 5 -++#define RTC_DAY_OF_WEEK 6 -++#define RTC_MONTH 7 -++#define RTC_YEAR 8 -++ -++#define RTC_MINUTES_ALARM 9 -++#define RTC_HOURS_ALARM 0x0a -++#define RTC_DAY_ALARM 0x0b -++#define RTC_WEEKDAY_ALARM 0x0c -++ -++/* control registers - Moto names -++ */ -++#define RTC_CONTROL 0x00 -++#define RTC_STATUS 0x01 -++#define RTC_CLKOUT 0x0d -++#define RTC_TIMERCTL 0x0e -++#define RTC_TIMERCOUNTDOWN 0x0f -++ -++ -++/* example: !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) -++ * determines if the following two #defines are needed -++ */ -++#ifndef BCD2BIN -++#define BCD2BIN(val) (((val) & 0x0f) + ((val) >> 4) * 10) -++#endif -++ -++#ifndef BIN2BCD -++#define BIN2BCD(val) ((((val) / 10) << 4) + (val) % 10) -++#endif -++ -++extern spinlock_t rtc_lock; -++extern void i2c_open(void); -++extern void i2c_close(void); -++extern int i2c_read(unsigned char device, unsigned char *buf, -++ unsigned char address, int count); -++extern int i2c_write(unsigned char device, unsigned char *buf, -++ unsigned char address, int count); -++/* -++ * We sponge a minor off of the misc major. No need slurping -++ * up another valuable major dev number for this. If you add -++ * an ioctl, make sure you don't conflict with SPARC's RTC -++ * ioctls. -++ */ -++ -++static int rtc_ioctl(struct inode *inode, struct file *file, -++ unsigned int cmd, unsigned long arg); -++ -++ -++static void get_rtc_time (struct rtc_time *rtc_tm); -++static void get_rtc_alm_time (struct rtc_time *alm_tm); -++ -++/* -++ * rtc_status is never changed by rtc_interrupt, and ioctl/open/close is -++ * protected by the big kernel lock. However, ioctl can still disable the timer -++ * in rtc_status and then with del_timer after the interrupt has read -++ * rtc_status but before mod_timer is called, which would then reenable the -++ * timer (but you would need to have an awful timing before you'd trip on it) -++ */ -++static unsigned long rtc_status = 0; /* bitmapped status byte. */ -++ -++/* -++ * If this driver ever becomes modularised, it will be really nice -++ * to make the epoch retain its value across module reload... -++ */ -++static unsigned int epoch = 1900; -++static const unsigned char days_in_mo[] = -++{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; -++ -++static unsigned char rtcframe[16]; -++ -++static void read_rtcframe(void) -++{ -++ i2c_open(); -++ i2c_read(0x51, rtcframe, 0, 16); -++ i2c_close(); -++} -++ -++static void write_rtcframe(void) -++{ -++ i2c_open(); -++ i2c_write(0x51, rtcframe, 0, 16); -++ i2c_close(); -++} -++ -++static void write_rtc(unsigned char addr, unsigned char val) -++{ -++ volatile unsigned char v = val; -++ i2c_open(); -++ i2c_write(0x51, (unsigned char *)&v, addr, 1); -++ i2c_close(); -++} -++ -++static unsigned char read_rtc(unsigned char addr) -++{ -++ volatile unsigned char v; -++ i2c_open(); -++ i2c_read(0x51, (unsigned char *)&v, addr, 1); -++ i2c_close(); -++ return v; -++} -++ -++static void CMOS_WRITE(unsigned char addr, unsigned char val) -++{ -++ rtcframe[addr] = val; -++} -++ -++static unsigned char CMOS_READ(unsigned char addr) -++{ -++ return rtcframe[addr]; -++} -++ -++static void get_rtc_time(struct rtc_time *rtc_tm) -++{ -++ unsigned char sec,mon,mday,wday,year,hour,min; -++ -++ /* -++ * Only the values that we read from the RTC are set. We leave -++ * tm_wday, tm_yday and tm_isdst untouched. Even though the -++ * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated -++ * by the RTC when initially set to a non-zero value. -++ */ -++ -++ spin_lock_irq(&rtc_lock); -++ read_rtcframe(); -++ sec = CMOS_READ(RTC_SECONDS) & ~0x80; -++ min = CMOS_READ(RTC_MINUTES) & ~0x80; -++ hour = CMOS_READ(RTC_HOURS) & ~0xc0; -++ mday = CMOS_READ(RTC_DAY_OF_MONTH) & ~0xc0; -++ wday = CMOS_READ(RTC_DAY_OF_WEEK) & ~0xf8; -++ mon = CMOS_READ(RTC_MONTH) & ~0xe0; -++ year = CMOS_READ(RTC_YEAR) ; -++ -++ rtc_tm->tm_sec = BCD2BIN(sec); -++ rtc_tm->tm_min = BCD2BIN(min); -++ rtc_tm->tm_hour = BCD2BIN(hour); -++ rtc_tm->tm_mday = BCD2BIN(mday); -++ rtc_tm->tm_wday = wday; -++ /* Don't use centry, but start from year 1970 */ -++ rtc_tm->tm_mon = BCD2BIN(mon); -++ year = BCD2BIN(year); -++ if ((year += (epoch - 1900)) <= 69) -++ year += 100; -++ rtc_tm->tm_year = year; -++ -++ spin_unlock_irq(&rtc_lock); -++ -++ -++ /* -++ * Account for differences between how the RTC uses the values -++ * and how they are defined in a struct rtc_time; -++ */ -++ rtc_tm->tm_mon--; -++} -++ -++static void get_rtc_alm_time(struct rtc_time *alm_tm) -++{ -++ unsigned char sec, min, hour; -++ -++ /* -++ * Only the values that we read from the RTC are set. That -++ * means only tm_hour, tm_min, and tm_sec. -++ */ -++ spin_lock_irq(&rtc_lock); -++ read_rtcframe(); -++ sec = 0; -++ min = CMOS_READ(RTC_MINUTES_ALARM); -++ hour = CMOS_READ(RTC_HOURS_ALARM); -++ -++ alm_tm->tm_sec = sec;//not set sec -++ alm_tm->tm_min = BCD2BIN(min); -++ alm_tm->tm_hour = BCD2BIN(hour); -++ -++ spin_unlock_irq(&rtc_lock); -++} -++ -++static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, -++ unsigned long arg) -++{ -++ struct rtc_time wtime; -++ switch (cmd) { -++ case RTC_ALM_READ: /* Read the present alarm time */ -++ { -++ /* -++ * This returns a struct rtc_time. Reading >= 0xc0 -++ * means "don't care" or "match all". Only the tm_hour, -++ * tm_min, and tm_sec values are filled in. -++ */ -++ -++ get_rtc_alm_time(&wtime); -++ break; -++ } -++ case RTC_ALM_SET: /* Store a time into the alarm */ -++ { -++ unsigned char hrs, min, sec; -++ struct rtc_time alm_tm; -++ -++ if (copy_from_user(&alm_tm, (struct rtc_time*)arg, -++ sizeof(struct rtc_time))) -++ return -EFAULT; -++ -++ hrs = alm_tm.tm_hour; -++ min = alm_tm.tm_min; -++ sec = alm_tm.tm_sec; -++ -++ -++ -++ if (hrs >= 24) -++ return -EINVAL; -++ -++ hrs = BIN2BCD(hrs); -++ -++ if (min >= 60) -++ return -EINVAL; -++ -++ min = BIN2BCD(min); -++ -++ if (sec >= 60) -++ return -EINVAL; -++ -++ spin_lock_irq(&rtc_lock); -++ read_rtcframe(); -++ CMOS_WRITE(RTC_HOURS_ALARM, hrs | 0x80); -++ CMOS_WRITE(RTC_MINUTES_ALARM, min | 0x80); -++ -++ CMOS_WRITE(RTC_DAY_ALARM, CMOS_READ(RTC_DAY_ALARM) | 0x80); -++ CMOS_WRITE(RTC_WEEKDAY_ALARM, CMOS_READ(RTC_WEEKDAY_ALARM) | 0x80); -++ CMOS_WRITE(RTC_STATUS, CMOS_READ(RTC_STATUS) | 0x02);/*open alarm int*/ -++ write_rtcframe(); -++ spin_unlock_irq(&rtc_lock); -++ break; -++ } -++ case RTC_RD_TIME: /* Read the time/date from RTC */ -++ { -++ get_rtc_time(&wtime); -++ break; -++ } -++ case RTC_SET_TIME: /* Set the RTC */ -++ { -++ struct rtc_time rtc_tm; -++ unsigned char mon, day, hrs, min, sec, leap_yr, date; -++ unsigned int yrs; -++// unsigned char ctr; -++ -++ if (!capable(CAP_SYS_TIME)) -++ return -EACCES; -++ -++ if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, -++ sizeof(struct rtc_time))) -++ return -EFAULT; -++ -++ -++ yrs = rtc_tm.tm_year + 1900; -++ mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ -++ day = rtc_tm.tm_wday; -++ date = rtc_tm.tm_mday; -++ hrs = rtc_tm.tm_hour; -++ min = rtc_tm.tm_min; -++ sec = rtc_tm.tm_sec; -++ -++ -++ if (yrs < 1970) -++ return -EINVAL; -++ -++ leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); -++ -++ if ((mon > 12) || (date == 0)) -++ return -EINVAL; -++ -++ if (date > (days_in_mo[mon] + ((mon == 2) && leap_yr))) -++ return -EINVAL; -++ -++ if ((hrs >= 24) || (min >= 60) || (sec >= 60)) -++ return -EINVAL; -++ -++ if ((yrs -= epoch) > 255) /* They are unsigned */ -++ return -EINVAL; -++ -++ spin_lock_irq(&rtc_lock); -++ /* These limits and adjustments are independant of -++ * whether the chip is in binary mode or not. -++ */ -++ if (yrs > 169) { -++ spin_unlock_irq(&rtc_lock); -++ return -EINVAL; -++ } -++ -++ if (yrs >= 100) -++ yrs -= 100; -++ -++ min = BIN2BCD(min); -++ sec = BIN2BCD(sec); -++ hrs = BIN2BCD(hrs); -++ mon = BIN2BCD(mon); -++ yrs = BIN2BCD(yrs); -++ date = BIN2BCD(date); -++ -++ read_rtcframe(); -++ CMOS_WRITE(RTC_SECONDS, sec ); -++ CMOS_WRITE(RTC_MINUTES, min); -++ CMOS_WRITE(RTC_HOURS, hrs); -++ CMOS_WRITE(RTC_DAY_OF_MONTH, date); -++ CMOS_WRITE(RTC_DAY_OF_WEEK, day); -++ CMOS_WRITE(RTC_MONTH, mon); -++ CMOS_WRITE(RTC_YEAR, yrs); -++ write_rtcframe(); -++ -++ spin_unlock_irq(&rtc_lock); -++ return 0; -++ } -++ case RTC_EPOCH_READ: /* Read the epoch. */ -++ { -++ return put_user (epoch, (unsigned long *)arg); -++ } -++ case RTC_EPOCH_SET: /* Set the epoch. */ -++ { -++ /* -++ * There were no RTC clocks before 1900. -++ */ -++ if (arg < 1900) -++ return -EINVAL; -++ -++ if (!capable(CAP_SYS_TIME)) -++ return -EACCES; -++ -++ epoch = arg; -++ return 0; -++ } -++ default: -++ return -EINVAL; -++ } -++ return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; -++} -++ -++/* -++ * We enforce only one user at a time here with the open/close. -++ * Also clear the previous interrupt data on an open, and clean -++ * up things on a close. -++ */ -++ -++/* We use rtc_lock to protect against concurrent opens. So the BKL is not -++ * needed here. Or anywhere else in this driver. */ -++static int rtc_open(struct inode *inode, struct file *file) -++{ -++ spin_lock_irq (&rtc_lock); -++ -++ if(rtc_status) -++ goto out_busy; -++ -++ rtc_status = 1; -++ -++ spin_unlock_irq (&rtc_lock); -++ return 0; -++ -++out_busy: -++ spin_unlock_irq (&rtc_lock); -++ return -EBUSY; -++} -++ -++static int rtc_release(struct inode *inode, struct file *file) -++{ -++ -++ -++ /* No need for locking -- nobody else can do anything until this rmw is -++ * committed, and no timer is running. */ -++ rtc_status = 0; -++ return 0; -++} -++ -++/* -++ * The various file operations we support. -++ */ -++ -++static struct file_operations rtc_fops = { -++ owner: THIS_MODULE, -++ llseek: no_llseek, -++ ioctl: rtc_ioctl, -++ open: rtc_open, -++ release: rtc_release, -++}; -++ -++#define RTC_MINOR 135 -++ -++static struct miscdevice rtc_dev= -++{ -++ RTC_MINOR, -++ "rtc", -++ &rtc_fops -++}; -++ -++int __init pcf_rtc_init(void) -++{ -++ int r; -++ unsigned char ctr; -++ r = misc_register(&rtc_dev); -++ -++ ctr = read_rtc(RTC_CONTROL); -++ write_rtc(RTC_CONTROL,0x00 ); -++ -++ read_rtcframe(); -++ CMOS_WRITE(RTC_STATUS, 0x00); -++ CMOS_WRITE(RTC_CLKOUT, 0x80); -++ /* RTC clock out, 32.768k */ -++ -++ CMOS_WRITE(RTC_TIMERCTL, 0x00); -++ CMOS_WRITE(RTC_TIMERCOUNTDOWN, 0x00); -++ write_rtcframe(); -++ -++ printk("PCF8563 RTC installed !!!\n"); -++ return 0; -++ -++} -++ -++void __exit pcf_rtc_exit (void) -++{ -++ misc_deregister(&rtc_dev); -++} -++ -++module_init(pcf_rtc_init); -++module_exit(pcf_rtc_exit); -+diff -urN linux-2.6.24.7.old/drivers/i2c/busses/Kconfig linux-2.6.24.7/drivers/i2c/busses/Kconfig -+--- linux-2.6.24.7.old/drivers/i2c/busses/Kconfig 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/i2c/busses/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -4,6 +4,14 @@ -+ -+ menu "I2C Hardware Bus support" -+ -++config I2C_JZ47XX -++ tristate "JZ47XX I2C Interface support" -++ depends on SOC_JZ4730 || SOC_JZ4740 -++ help -++ If you have devices in the Ingenic JZ4730/JZ4740 I2C bus, say yes to -++ this option. This driver can also be built as a module. If so, the -++ module will be called i2c-jz47xx. -++ -+ config I2C_ALI1535 -+ tristate "ALI 1535" -+ depends on PCI -+diff -urN linux-2.6.24.7.old/drivers/i2c/busses/Makefile linux-2.6.24.7/drivers/i2c/busses/Makefile -+--- linux-2.6.24.7.old/drivers/i2c/busses/Makefile 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/i2c/busses/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -2,6 +2,7 @@ -+ # Makefile for the i2c bus drivers. -+ # -+ -++obj-$(CONFIG_I2C_JZ47XX) += i2c-jz47xx.o -+ obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o -+ obj-$(CONFIG_I2C_ALI1563) += i2c-ali1563.o -+ obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o -+diff -urN linux-2.6.24.7.old/drivers/i2c/busses/i2c-jz47xx.c linux-2.6.24.7/drivers/i2c/busses/i2c-jz47xx.c -+--- linux-2.6.24.7.old/drivers/i2c/busses/i2c-jz47xx.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/i2c/busses/i2c-jz47xx.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,330 @@ -++/* -++ * i2c_jz47xx.c -++ * I2C adapter for the INGENIC I2C bus access. -++ * -++ * Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include -++#include "i2c-jz47xx.h" -++ -++/* I2C protocol */ -++#define I2C_READ 1 -++#define I2C_WRITE 0 -++ -++#define TIMEOUT 1000 -++unsigned short sub_addr = 0; -++int addr_val = 0; -++struct jz_i2c { -++ spinlock_t lock; -++ wait_queue_head_t wait; -++ struct i2c_msg *msg; -++ unsigned int msg_num; -++ unsigned int slave_addr; -++ struct i2c_adapter adap; -++ struct clk *clk; -++}; -++ -++/* -++ * I2C bus protocol basic routines -++ */ -++static int i2c_put_data(unsigned char data) -++{ -++ unsigned int timeout = TIMEOUT*10; -++ -++ __i2c_write(data); -++ __i2c_set_drf(); -++ while (__i2c_check_drf() != 0); -++ while (!__i2c_transmit_ended()); -++ while (!__i2c_received_ack() && timeout) -++ timeout--; -++ -++ if (timeout) -++ return 0; -++ else -++ return -ETIMEDOUT; -++} -++ -++static int i2c_get_data(unsigned char *data, int ack) -++{ -++ int timeout = TIMEOUT*10; -++ -++ if (!ack) -++ __i2c_send_nack(); -++ else -++ __i2c_send_ack(); -++ -++ while (__i2c_check_drf() == 0 && timeout) -++ timeout--; -++ -++ if (timeout) { -++ if (!ack) -++ __i2c_send_stop(); -++ *data = __i2c_read(); -++ __i2c_clear_drf(); -++ return 0; -++ } else -++ return -ETIMEDOUT; -++} -++ -++/* -++ * I2C interface -++ */ -++void i2c_jz_setclk(unsigned int i2cclk) -++{ -++ __i2c_set_clk(jz_clocks.extalclk, i2cclk); -++} -++ -++static int xfer_read(unsigned char device, struct i2c_adapter *adap, unsigned char *buf, int length) -++{ -++ int cnt = length; -++ int timeout = 5; -++ -++ device = (0xa << 3) | ((sub_addr & 0x0700) >> 8); -++ sub_addr = sub_addr & 0xff; -++ -++L_try_again: -++ -++ if (timeout < 0) -++ goto L_timeout; -++ -++ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -++ -++ if (addr_val) { -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -++ goto device_werr; -++ if (i2c_put_data(sub_addr) < 0) -++ goto address_err; -++ } -++ __i2c_send_start(); -++ -++ if (i2c_put_data((device << 1) | I2C_READ ) < 0) -++ goto device_rerr; -++ -++ __i2c_send_ack(); /* Master sends ACK for continue reading */ -++ __i2c_send_start(); -++ -++ while (cnt) { -++ if (cnt == 1) { -++ if (i2c_get_data(buf, 0) < 0) -++ break; -++ } else { -++ if (i2c_get_data(buf, 1) < 0) -++ break; -++ } -++ cnt--; -++ buf++; -++ } -++ addr_val = 0; -++ return length - cnt; -++ device_rerr: -++ device_werr: -++ address_err: -++ timeout --; -++ __i2c_send_stop(); -++ goto L_try_again; -++ -++L_timeout: -++ __i2c_send_stop(); -++ printk("Read I2C device 0x%2x failed.\n", device); -++ return -ENODEV; -++} -++ -++static int xfer_write(unsigned char device, struct i2c_adapter *adap, unsigned char *buf, int length) -++{ -++ int cnt = length; -++ int cnt_in_pg; -++ int timeout = 5; -++ unsigned char *tmpbuf; -++ unsigned char tmpaddr; -++ -++ device = (0xa << 3) | ((sub_addr & 0x0700) >> 8); -++ sub_addr = sub_addr & 0xff; -++ -++ __i2c_send_nack(); /* Master does not send ACK, slave sends it */ -++ -++ W_try_again: -++ if (timeout < 0) -++ goto W_timeout; -++ -++ cnt = length; -++ tmpbuf = (unsigned char *)buf; -++ tmpaddr = device; -++ start_write_page: -++ cnt_in_pg = 0; -++ __i2c_send_start(); -++ if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0) -++ goto device_err; -++ if (addr_val) { -++ if (i2c_put_data(sub_addr) < 0) -++ goto address_err; -++ } -++ while (cnt) { -++ if (++cnt_in_pg > 8) { -++ __i2c_send_stop(); -++ mdelay(1); -++ sub_addr += 8; -++ goto start_write_page; -++ } -++ if (i2c_put_data(*tmpbuf) < 0) -++ break; -++ cnt--; -++ tmpbuf++; -++ } -++ __i2c_send_stop(); -++ addr_val = 0; -++ return length - cnt; -++ device_err: -++ address_err: -++ timeout--; -++ __i2c_send_stop(); -++ goto W_try_again; -++ -++W_timeout: -++ printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device); -++ __i2c_send_stop(); -++ return -ENODEV; -++} -++ -++static int i2c_jz_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num) -++{ -++ int ret, i; -++ -++ dev_dbg(&adap->dev, "jz47xx_xfer: processing %d messages:\n", num); -++ for (i = 0; i < num; i++) { -++ dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i, -++ pmsg->flags & I2C_M_RD ? "read" : "writ", -++ pmsg->len, pmsg->len > 1 ? "s" : "", -++ pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr); -++ if (pmsg->len && pmsg->buf) { /* sanity check */ -++ if (pmsg->flags & I2C_M_RD) -++ ret = xfer_read(pmsg->addr, adap, pmsg->buf, pmsg->len); -++ else -++ ret = xfer_write(pmsg->addr, adap, pmsg->buf, pmsg->len); -++ -++ if (ret) -++ return ret; -++ /* Wait until transfer is finished */ -++ } -++ dev_dbg(&adap->dev, "transfer complete\n"); -++ pmsg++; /* next message */ -++ } -++ return i; -++} -++ -++static u32 i2c_jz_functionality(struct i2c_adapter *adap) -++{ -++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -++} -++ -++static const struct i2c_algorithm i2c_jz_algorithm = { -++ .master_xfer = i2c_jz_xfer, -++ .functionality = i2c_jz_functionality, -++}; -++ -++static int i2c_jz_probe(struct platform_device *dev) -++{ -++ struct jz_i2c *i2c; -++ struct i2c_jz_platform_data *plat = dev->dev.platform_data; -++ int ret; -++ -++ __i2c_set_clk(jz_clocks.extalclk, 10000); /* default 10 KHz */ -++ __i2c_enable(); -++ -++ i2c = kzalloc(sizeof(struct jz_i2c), GFP_KERNEL); -++ if (!i2c) { -++ printk("There is no enough memory\n"); -++ ret = -ENOMEM; -++ goto emalloc; -++ } -++ -++ i2c->adap.owner = THIS_MODULE; -++ i2c->adap.algo = &i2c_jz_algorithm; -++ i2c->adap.retries = 5; -++ spin_lock_init(&i2c->lock); -++ init_waitqueue_head(&i2c->wait); -++ sprintf(i2c->adap.name, "jz_i2c-i2c.%u", dev->id); -++ i2c->adap.algo_data = i2c; -++ i2c->adap.dev.parent = &dev->dev; -++ -++ if (plat) { -++ i2c->adap.class = plat->class; -++ } -++ -++ /* -++ * If "dev->id" is negative we consider it as zero. -++ * The reason to do so is to avoid sysfs names that only make -++ * sense when there are multiple adapters. -++ */ -++ i2c->adap.nr = dev->id != -1 ? dev->id : 0; -++ /* ret = i2c_add_adapter(&i2c->adap); */ -++ ret = i2c_add_numbered_adapter(&i2c->adap); -++ if (ret < 0) { -++ printk(KERN_INFO "I2C: Failed to add bus\n"); -++ goto eadapt; -++ } -++ -++ platform_set_drvdata(dev, i2c); -++ dev_info(&dev->dev, "JZ47xx i2c bus driver.\n"); -++ return 0; -++eadapt: -++ __i2c_disable(); -++emalloc: -++ return ret; -++} -++ -++static int i2c_jz_remove(struct platform_device *dev) -++{ -++ struct i2c_adapter *adapter = platform_get_drvdata(dev); -++ int rc; -++ -++ rc = i2c_del_adapter(adapter); -++ platform_set_drvdata(dev, NULL); -++ return rc; -++} -++ -++static struct platform_driver i2c_jz_driver = { -++ .probe = i2c_jz_probe, -++ .remove = i2c_jz_remove, -++ .driver = { -++ .name = "jz_i2c", -++ }, -++}; -++ -++static int __init i2c_adap_jz_init(void) -++{ -++ return platform_driver_register(&i2c_jz_driver); -++} -++ -++static void __exit i2c_adap_jz_exit(void) -++{ -++ return platform_driver_unregister(&i2c_jz_driver); -++} -++ -++MODULE_LICENSE("GPL"); -++ -++module_init(i2c_adap_jz_init); -++module_exit(i2c_adap_jz_exit); -+diff -urN linux-2.6.24.7.old/drivers/i2c/busses/i2c-jz47xx.h linux-2.6.24.7/drivers/i2c/busses/i2c-jz47xx.h -+--- linux-2.6.24.7.old/drivers/i2c/busses/i2c-jz47xx.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/i2c/busses/i2c-jz47xx.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,20 @@ -++/* -++ * i2c_jz47xx.h -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++#ifndef _I2C_JZ_H_ -++#define _I2C_JZ_H_ -++ -++struct i2c_slave_client; -++ -++struct i2c_jz_platform_data { -++ unsigned int slave_addr; -++ struct i2c_slave_client *slave; -++ unsigned int class; -++}; -++ -++extern void jz_set_i2c_info(struct i2c_jz_platform_data *info); -++#endif -+diff -urN linux-2.6.24.7.old/drivers/i2c/i2c-dev.c linux-2.6.24.7/drivers/i2c/i2c-dev.c -+--- linux-2.6.24.7.old/drivers/i2c/i2c-dev.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/i2c/i2c-dev.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -36,8 +36,9 @@ -+ #include -+ #include -+ -++extern unsigned short sub_addr; -++extern int addr_val; -+ static struct i2c_driver i2cdev_driver; -+- -+ /* -+ * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a -+ * slave (i2c_client) with which messages will be exchanged. It's coupled -+@@ -422,6 +423,14 @@ -+ case I2C_TIMEOUT: -+ client->adapter->timeout = arg; -+ break; -++ case I2C_SET_SUB_ADDRESS: -++ addr_val = 1; -++ sub_addr = arg; -++ break; -++ case I2C_SET_CLOCK: -++ i2c_jz_setclk(arg); -++ break; -++ -+ default: -+ /* NOTE: returning a fault code here could cause trouble -+ * in buggy userspace code. Some old kernel bugs returned -+diff -urN linux-2.6.24.7.old/drivers/input/keyboard/Kconfig linux-2.6.24.7/drivers/input/keyboard/Kconfig -+--- linux-2.6.24.7.old/drivers/input/keyboard/Kconfig 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/input/keyboard/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -259,9 +259,27 @@ -+ To compile this driver as a module, choose M here: the -+ module will be called aaed2000_kbd. -+ -++config KEYBOARD_JZ -++ tristate "JZ keypad support" -++ depends on JZSOC -++ help -++ Enable Y here to support JZ keypad. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called jz-keypad. -++ -++config 5x5_KEYBOARD_JZ -++ tristate "JZ 5x5 keypad support" -++ depends on JZSOC -++ help -++ Enable Y here to support JZ keypad. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called jz-keypad. -++ -+ config KEYBOARD_GPIO -+- tristate "GPIO Buttons" -+- depends on GENERIC_GPIO -++ tristate "JZ GPIO Buttons support" -++# depends on GENERIC_GPIO -+ help -+ This driver implements support for buttons connected -+ to GPIO pins of various CPUs (and some other chips). -+@@ -272,7 +290,7 @@ -+ with configuration data saying which GPIOs are used. -+ -+ To compile this driver as a module, choose M here: the -+- module will be called gpio-keys. -++ module will be called gpio_keys. -+ -+ config KEYBOARD_MAPLE -+ tristate "Maple bus keyboard" -+diff -urN linux-2.6.24.7.old/drivers/input/keyboard/Makefile linux-2.6.24.7/drivers/input/keyboard/Makefile -+--- linux-2.6.24.7.old/drivers/input/keyboard/Makefile 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/input/keyboard/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -19,6 +19,8 @@ -+ obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o -+ obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o -+ obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o -++obj-$(CONFIG_KEYBOARD_JZ) += jz_keypad.o -++obj-$(CONFIG_5x5_KEYBOARD_JZ) += jz_keypad_5x5.o -+ obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o -+ obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o -+ obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o -+diff -urN linux-2.6.24.7.old/drivers/input/keyboard/gpio_keys.c linux-2.6.24.7/drivers/input/keyboard/gpio_keys.c -+--- linux-2.6.24.7.old/drivers/input/keyboard/gpio_keys.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/input/keyboard/gpio_keys.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -1,7 +1,13 @@ -+ /* -+- * Driver for keys on GPIO lines capable of generating interrupts. -++ * linux/drivers/input/keyboard/gpio_keys.c -+ * -+- * Copyright 2005 Phil Blundell -++ * JZ GPIO Buttons driver for JZ4740 PAVO -++ * -++ * User applications can access to this device via /dev/input/eventX. -++ * -++ * Copyright (c) 2005 - 2008 Ingenic Semiconductor Inc. -++ * -++ * Author: Richard -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+@@ -23,26 +29,131 @@ -+ #include -+ #include -+ #include -+- -+ #include -++#include -++ -++ -++#define SCAN_INTERVAL (10) -++ -++/* -++ * GPIO Buttons -++ */ -++#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) -++static struct gpio_keys_button pavo_buttons[] = { -++ { -++ .gpio = 96, -++ .code = KEY_1, -++ .desc = "Button 0", -++ .active_low = 1, -++ }, -++ { -++ .gpio = 97, -++ .code = KEY_2, -++ .desc = "Button 1", -++ .active_low = 1, -++ }, -++ { -++ .gpio = 98, -++ .code = KEY_3, -++ .desc = "Button 2", -++ .active_low = 1, -++ }, -++ { -++ .gpio = 99, -++ .code = KEY_4, -++ .desc = "Button 3", -++ .active_low = 1, -++ } -++}; -++ -++static struct timer_list button_timer; -++static spinlock_t gpio_lock; -++static int button_no; -++ -++static struct gpio_keys_platform_data pavo_button_data = { -++ .buttons = pavo_buttons, -++ .nbuttons = ARRAY_SIZE(pavo_buttons), -++}; -++ -++static struct platform_device pavo_button_device = { -++ .name = "gpio-keys", -++ .id = -1, -++ .num_resources = 0, -++ .dev = { -++ .platform_data = &pavo_button_data, -++ } -++}; -++ -++static void __init pavo_add_device_buttons(void) -++{ -++ __gpio_as_input(96); -++ __gpio_as_irq_fall_edge(96); -++ -++ __gpio_as_input(97); -++ __gpio_as_irq_fall_edge(97); -++ -++ __gpio_as_input(98); -++ __gpio_as_irq_fall_edge(98); -++ -++ __gpio_as_input(99); -++ __gpio_as_irq_fall_edge(99); -++ -++ platform_device_register(&pavo_button_device); -++} -++#else -++static void __init pavo_add_device_buttons(void) {} -++#endif -++ -++static void __init pavo_board_init(void) -++{ -++ /* Push Buttons */ -++ pavo_add_device_buttons(); -++} -++ -++static void button_timer_callback(unsigned long data) -++{ -++ unsigned long flags; -++ int gpio = pavo_buttons[button_no].gpio; -++ int code = pavo_buttons[button_no].code; -++ struct platform_device *pdev = (struct platform_device *)data; -++ struct input_dev *input = platform_get_drvdata(pdev); -++ int state; -++ -++ spin_lock_irqsave(&gpio_lock, flags); -++ state = __gpio_get_pin(gpio); -++ -++ if (state == 0) { -++ /* press down */ -++ input_report_key(input, code, 1); -++ input_sync(input); -++ mod_timer(&button_timer, jiffies + SCAN_INTERVAL); -++ } else { -++ /* up */ -++ input_report_key(input, code, 0); -++ input_sync(input); -++ udelay(1000); -++ __gpio_as_irq_fall_edge(gpio); -++ } -++ spin_unlock_irqrestore(&gpio_lock, flags); -++} -+ -+ static irqreturn_t gpio_keys_isr(int irq, void *dev_id) -+ { -+ int i; -+ struct platform_device *pdev = dev_id; -+ struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; -+- struct input_dev *input = platform_get_drvdata(pdev); -+ -++ __gpio_ack_irq(irq - IRQ_GPIO_0); -+ for (i = 0; i < pdata->nbuttons; i++) { -+ struct gpio_keys_button *button = &pdata->buttons[i]; -+ int gpio = button->gpio; -+ -+- if (irq == gpio_to_irq(gpio)) { -+- unsigned int type = button->type ?: EV_KEY; -+- int state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low; -+- -+- input_event(input, type, button->code, !!state); -+- input_sync(input); -++ if (irq == (gpio + IRQ_GPIO_0) ) { -++ /* start timer */ -++ __gpio_as_input(gpio); -++ button_no = i; -++ mod_timer(&button_timer, jiffies + 2 * SCAN_INTERVAL); -++ break; -+ } -+ } -+ -+@@ -62,7 +173,7 @@ -+ -+ platform_set_drvdata(pdev, input); -+ -+- input->evbit[0] = BIT_MASK(EV_KEY); -++ spin_lock_init(&gpio_lock); -+ -+ input->name = pdev->name; -+ input->phys = "gpio-keys/input0"; -+@@ -72,56 +183,42 @@ -+ input->id.vendor = 0x0001; -+ input->id.product = 0x0001; -+ input->id.version = 0x0100; -++ input->evbit[0] = BIT(EV_KEY) | BIT(EV_SYN) | BIT(EV_REP); -+ -+ for (i = 0; i < pdata->nbuttons; i++) { -+ struct gpio_keys_button *button = &pdata->buttons[i]; -+ int irq; -+ unsigned int type = button->type ?: EV_KEY; -+ -+- error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); -+- if (error < 0) { -+- pr_err("gpio-keys: failed to request GPIO %d," -+- " error %d\n", button->gpio, error); -+- goto fail; -+- } -+- -+- error = gpio_direction_input(button->gpio); -+- if (error < 0) { -+- pr_err("gpio-keys: failed to configure input" -+- " direction for GPIO %d, error %d\n", -+- button->gpio, error); -+- gpio_free(button->gpio); -+- goto fail; -+- } -+- -+- irq = gpio_to_irq(button->gpio); -++ irq = IRQ_GPIO_0 + button->gpio; -+ if (irq < 0) { -+ error = irq; -+ pr_err("gpio-keys: Unable to get irq number" -+ " for GPIO %d, error %d\n", -+ button->gpio, error); -+- gpio_free(button->gpio); -+ goto fail; -+ } -+ -+ error = request_irq(irq, gpio_keys_isr, -+- IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING | -+- IRQF_TRIGGER_FALLING, -++ IRQF_SAMPLE_RANDOM | IRQF_DISABLED, -+ button->desc ? button->desc : "gpio_keys", -+ pdev); -+ if (error) { -+ pr_err("gpio-keys: Unable to claim irq %d; error %d\n", -+ irq, error); -+- gpio_free(button->gpio); -+ goto fail; -+ } -+ -+ if (button->wakeup) -+ wakeup = 1; -+- -+ input_set_capability(input, type, button->code); -+ } -+ -++ /* Init timer */ -++ init_timer(&button_timer); -++ button_timer.data = (unsigned long)&pavo_button_device; -++ button_timer.function = button_timer_callback; -++ -+ error = input_register_device(input); -+ if (error) { -+ pr_err("gpio-keys: Unable to register input device, " -+@@ -135,8 +232,7 @@ -+ -+ fail: -+ while (--i >= 0) { -+- free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev); -+- gpio_free(pdata->buttons[i].gpio); -++ free_irq(pdata->buttons[i].gpio + IRQ_GPIO_0 , pdev); -+ } -+ -+ platform_set_drvdata(pdev, NULL); -+@@ -154,9 +250,8 @@ -+ device_init_wakeup(&pdev->dev, 0); -+ -+ for (i = 0; i < pdata->nbuttons; i++) { -+- int irq = gpio_to_irq(pdata->buttons[i].gpio); -++ int irq = pdata->buttons[i].gpio + IRQ_GPIO_0; -+ free_irq(irq, pdev); -+- gpio_free(pdata->buttons[i].gpio); -+ } -+ -+ input_unregister_device(input); -+@@ -175,7 +270,7 @@ -+ for (i = 0; i < pdata->nbuttons; i++) { -+ struct gpio_keys_button *button = &pdata->buttons[i]; -+ if (button->wakeup) { -+- int irq = gpio_to_irq(button->gpio); -++ int irq = button->gpio + IRQ_GPIO_0; -+ enable_irq_wake(irq); -+ } -+ } -+@@ -193,7 +288,7 @@ -+ for (i = 0; i < pdata->nbuttons; i++) { -+ struct gpio_keys_button *button = &pdata->buttons[i]; -+ if (button->wakeup) { -+- int irq = gpio_to_irq(button->gpio); -++ int irq = button->gpio + IRQ_GPIO_0; -+ disable_irq_wake(irq); -+ } -+ } -+@@ -218,11 +313,13 @@ -+ -+ static int __init gpio_keys_init(void) -+ { -++ pavo_board_init(); -+ return platform_driver_register(&gpio_keys_device_driver); -+ } -+ -+ static void __exit gpio_keys_exit(void) -+ { -++ platform_device_unregister(&pavo_button_device); -+ platform_driver_unregister(&gpio_keys_device_driver); -+ } -+ -+diff -urN linux-2.6.24.7.old/drivers/input/keyboard/jz_keypad.c linux-2.6.24.7/drivers/input/keyboard/jz_keypad.c -+--- linux-2.6.24.7.old/drivers/input/keyboard/jz_keypad.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/input/keyboard/jz_keypad.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,357 @@ -++/* -++ * linux/drivers/input/keyboard/jz_keypad.c -++ * -++ * JZ Keypad Driver -++ * -++ * Copyright (c) 2005 - 2008 Ingenic Semiconductor Inc. -++ * -++ * Author: Richard -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ */ -++ -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++ -++#include -++ -++#define KB_ROWS 3 -++#define KB_COLS 3 -++ -++#define SCAN_INTERVAL (10) -++ -++static unsigned short col[KB_COLS] = {85,87,91}; -++static unsigned short row[KB_ROWS] = {60,61,62}; -++static unsigned short s0[KB_COLS]; -++static unsigned short s1[KB_COLS]={7,7,7}; -++static unsigned short precol,prerow; -++ -++static const unsigned int jz_kbd_keycode[KB_COLS * KB_ROWS] = { -++ KEY_1, KEY_4, KEY_7, -++ KEY_2, KEY_5, 0, -++ KEY_3, KEY_6, 0, -++}; -++ -++struct jz_kbd { -++ unsigned int keycode[ARRAY_SIZE(jz_kbd_keycode)]; -++ struct input_dev *input; -++ char phys[32]; -++ -++ spinlock_t lock; -++ struct timer_list timer; -++ -++ unsigned int suspended; -++ unsigned long suspend_jiffies; -++}; -++ -++static struct jz_kbd g_jz_kbd; -++ -++static inline void jz_scan_kbd(unsigned short *s) -++{ -++ int i; -++ -++ if (!s) -++ return; -++ -++ for (i = 0; i < KB_COLS; i++) { -++ -++ __gpio_as_input(85); /* row */ -++ __gpio_as_input(87); /* row */ -++ __gpio_as_input(91); /* row */ -++ -++ __gpio_as_input(60); /* col */ -++ __gpio_as_input(61); /* col */ -++ __gpio_as_input(62); /* col */ -++ -++ __gpio_clear_pin(col[i]); -++ __gpio_as_output(col[i]); -++ -++ udelay(1000); -++ s[i]=(__gpio_get_pin(60) << 0) | (__gpio_get_pin(61) << 1) | -++ (__gpio_get_pin(62) << 2); -++ } -++} -++ -++static void jz_kbd_scankeyboard(struct jz_kbd *kbd_data) -++{ -++ unsigned int row,col; -++ unsigned long flags; -++ unsigned int num_pressed; -++ -++ if (kbd_data->suspended) -++ return; -++ -++ spin_lock_irqsave(&kbd_data->lock, flags); -++ -++ num_pressed = 0; -++ jz_scan_kbd(s0); -++ -++ /* look for key if pressed down on not, col & row */ -++ if (s0[0] == 7 && s0[1] == 7 && s0[2] == 7) { -++ if (s1[0] != 7 || s1[1] != 7 || s1[2] != 7) { -++ /* up */ -++ input_report_key(kbd_data->input, kbd_data->keycode[prerow * KB_COLS + precol], 0); -++ input_sync(kbd_data->input); -++ } -++ precol = prerow = -1; -++ s1[0] = s1[1] = s1[2] = 7; -++ spin_unlock_irqrestore(&kbd_data->lock, flags); -++ return; -++ } -++ -++ if (s0[0] == 6 && s0[1] == 7 && s0[2] == 7) { -++ row = 0;//K7 -++ col = 2; -++ goto find_row_col; -++ } -++ if (s0[0] == 7 && s0[1] == 3 && s0[2] == 7) { -++ row = 2;//k6 -++ col = 1; -++ goto find_row_col; -++ } -++ if (s0[0] == 7 && s0[1] == 5 && s0[2] == 7) { -++ row = 1;//k5 -++ col = 1; -++ goto find_row_col; -++ } -++ if (s0[0] == 7 && s0[1] == 6 && s0[2] == 7) { -++ row = 0;//k4 -++ col = 1; -++ goto find_row_col; -++ } -++ if (s0[0] == 7 && s0[1] == 7 && s0[2] == 3) { -++ row = 2;//k3 -++ col = 0; -++ goto find_row_col; -++ } -++ if (s0[0] == 7 && s0[1] == 7 && s0[2] == 5) { -++ row = 1;//k2 -++ col = 0; -++ goto find_row_col; -++ } -++ if (s0[0] == 7 && s0[1] == 7 && s0[2] == 6) { -++ row = 0;//k1 -++ col = 0; -++ goto find_row_col; -++ } -++ /* 2 or 3 buttons are pressed */ -++ s0[0] = s0[1] = s0[2] = 7; -++ s1[0] = s1[1] = s1[2] = 7; -++ prerow = precol = -1; -++ spin_unlock_irqrestore(&kbd_data->lock, flags); -++ return; -++find_row_col: -++ if (s1[0] == 7 && s1[1] == 7 && s1[2] == 7) { -++ /* down */ -++ input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + col], 1); -++ input_sync(kbd_data->input); -++ s1[0] = s0[0]; -++ s1[1] = s0[1]; -++ s1[2] = s0[2]; -++ -++ precol = col; -++ prerow = row; -++ spin_unlock_irqrestore(&kbd_data->lock, flags); -++ return; -++ } -++ if (s1[0] != 7 || s1[1] != 7 || s1[2] != 7) { -++ /* is the same as the preview key */ -++ if (s0[0] == s1[0] && s0[1] == s1[1] && s0[2] == s1[2]) { -++ input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + col], 1); -++ input_sync(kbd_data->input); -++ s1[0] = s0[0]; -++ s1[1] = s0[1]; -++ s1[2] = s0[2]; -++ -++ precol = col; -++ prerow = row; -++ spin_unlock_irqrestore(&kbd_data->lock, flags); -++ return; -++ } else { -++ /* the preview key is up and other key is down */ -++ if (s0[0] != s1[0] || s0[1] != s1[1] || s0[2] != s1[2]) { -++ input_report_key(kbd_data->input, kbd_data->keycode[prerow * KB_COLS + precol], 0); -++ input_sync(kbd_data->input); -++ input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + col], 1); -++ input_sync(kbd_data->input); -++ s1[0] = s0[0]; -++ s1[1] = s0[1]; -++ s1[2] = s0[2]; -++ precol = col; -++ prerow = row; -++ spin_unlock_irqrestore(&kbd_data->lock, flags); -++ return; -++ } -++ } -++ } -++} -++ -++static void jz_kbd_timer_callback(unsigned long data) -++{ -++ jz_kbd_scankeyboard(&g_jz_kbd); -++ mod_timer(&g_jz_kbd.timer, jiffies + SCAN_INTERVAL); -++} -++ -++#ifdef CONFIG_PM -++static int jz_kbd_suspend(struct platform_device *dev, pm_message_t state) -++{ -++ struct jz_kbd *jz_kbd = platform_get_drvdata(dev); -++ jz_kbd->suspended = 1; -++ -++ return 0; -++} -++ -++static int jz_kbd_resume(struct platform_device *dev) -++{ -++ struct jz_kbd *jz_kbd = platform_get_drvdata(dev); -++ -++ jz_kbd->suspend_jiffies = jiffies; -++ jz_kbd->suspended = 0; -++ -++ return 0; -++} -++#else -++#define jz_kbd_suspend NULL -++#define jz_kbd_resume NULL -++#endif -++ -++static int __init jz_kbd_probe(struct platform_device *dev) -++{ -++ struct input_dev *input_dev; -++ int i, error; -++ -++ input_dev = input_allocate_device(); -++ if (!input_dev) -++ return -ENOMEM; -++ -++ platform_set_drvdata(dev, &g_jz_kbd); -++ -++ strcpy(g_jz_kbd.phys, "input/kbd0"); -++ -++ spin_lock_init(&g_jz_kbd.lock); -++ -++ g_jz_kbd.suspend_jiffies = jiffies; -++ g_jz_kbd.input = input_dev; -++ -++ input_dev->private = &g_jz_kbd; -++ input_dev->name = "JZ Keypad"; -++ input_dev->phys = g_jz_kbd.phys; -++ input_dev->cdev.dev = &dev->dev; -++ -++ input_dev->id.bustype = BUS_PARPORT; -++ input_dev->id.vendor = 0x0001; -++ input_dev->id.product = 0x0001; -++ input_dev->id.version = 0x0100; -++ -++ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_SYN); -++ input_dev->keycode = g_jz_kbd.keycode; /* keycode array address */ -++ input_dev->keycodesize = sizeof(unsigned int); -++ input_dev->keycodemax = ARRAY_SIZE(jz_kbd_keycode); -++ -++ memcpy(g_jz_kbd.keycode, jz_kbd_keycode, sizeof(g_jz_kbd.keycode)); -++ -++ for (i = 0; i < ARRAY_SIZE(jz_kbd_keycode); i++) -++ set_bit(g_jz_kbd.keycode[i], input_dev->keybit); -++ -++ //clear_bit(0, input_dev->keybit); -++ -++ __gpio_as_input(85); -++ __gpio_as_input(87); -++ __gpio_as_input(91); -++ -++#if 0 -++ __gpio_as_input(60); -++ __gpio_as_input(61); -++ __gpio_as_input(62); -++#endif -++ -++ /* Init Keyboard rescan timer */ -++ init_timer(&g_jz_kbd.timer); -++ g_jz_kbd.timer.function = jz_kbd_timer_callback; -++ g_jz_kbd.timer.data = (unsigned long)&g_jz_kbd; -++ mod_timer(&g_jz_kbd.timer, jiffies + SCAN_INTERVAL); -++ -++ error = input_register_device(input_dev); -++ if (error) { -++ pr_err("gpio-keys: Unable to register input device, " -++ "error: %d\n", error); -++ } -++ printk("input: JZ Keypad Registered\n"); -++ -++ return 0; -++} -++ -++static int jz_kbd_remove(struct platform_device *dev) -++{ -++ struct jz_kbd *jz_kbd = platform_get_drvdata(dev); -++ -++ del_timer_sync(&jz_kbd->timer); -++ -++ __gpio_as_input(85); -++ __gpio_as_input(87); -++ __gpio_as_input(91); -++ -++ /* These pins is conficting with cs8900a's CS RD WE pins on JZ4740-PAVO board */ -++ __gpio_as_input(60); -++ __gpio_as_input(61); -++ __gpio_as_input(62); -++ -++ input_unregister_device(jz_kbd->input); -++ -++ return 0; -++} -++ -++static struct platform_driver jz_kbd_driver = { -++ .probe = jz_kbd_probe, -++ .remove = jz_kbd_remove, -++ .suspend = jz_kbd_suspend, -++ .resume = jz_kbd_resume, -++ .driver = { -++ .name = "jz-keypad", -++ }, -++}; -++ -++/* -++ * Jz Keyboard Device -++ */ -++static struct platform_device jzkbd_device = { -++ .name = "jz-keypad", -++ .id = -1, -++}; -++ -++static int __init jz_kbd_init(void) -++{ -++ platform_device_register(&jzkbd_device); -++ return platform_driver_register(&jz_kbd_driver); -++} -++ -++static void __exit jz_kbd_exit(void) -++{ -++ platform_device_unregister(&jzkbd_device); -++ platform_driver_unregister(&jz_kbd_driver); -++} -++ -++module_init(jz_kbd_init); -++module_exit(jz_kbd_exit); -++ -++MODULE_AUTHOR("Richard"); -++MODULE_DESCRIPTION("JZ keypad driver"); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/drivers/input/keyboard/jz_keypad_5x5.c linux-2.6.24.7/drivers/input/keyboard/jz_keypad_5x5.c -+--- linux-2.6.24.7.old/drivers/input/keyboard/jz_keypad_5x5.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/input/keyboard/jz_keypad_5x5.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,329 @@ -++/* -++ * JZ Keypad ( 5 x 5 ) Driver -++ * -++ * Copyright (c) 2005 - 2008 Ingenic Semiconductor Inc. -++ * -++ * Author: Jason 20090210 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ */ -++ -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#define KB_ROWS 5 -++#define KB_COLS 5 -++ -++#define SCAN_INTERVAL (10) -++ -++#define ROW_KEYBIT_MASK 0xFFE0 -++ -++#define SET_GPIOS_AS_INPUT() \ -++do { \ -++ unsigned short i; \ -++ \ -++ for (i = 0; i < KB_ROWS; i++) { \ -++ __gpio_as_input(jz_row_gpios[i]); \ -++ __gpio_as_input(jz_col_gpios[i]); \ -++ } \ -++} while (0) -++ -++ -++#define GET_ROW_GPIO_PINS() \ -++({ \ -++ unsigned short _pins = 0, i; \ -++ for (i = 0; \ -++ i < KB_ROWS; \ -++ _pins |= __gpio_get_pin(jz_row_gpios[i]) << i, i++) \ -++ ; \ -++ _pins; \ -++}) -++ -++#define CHECK_IF_KEY_PRESSED(s) \ -++({ \ -++ unsigned short i; \ -++ for (i = 0; i < KB_COLS && s[i] == 0x1F ; i++) \ -++ ; \ -++ i != KB_ROWS; \ -++}) -++ -++#define CLEAN_SCAN_RESULT(s) \ -++do { \ -++ unsigned short i; \ -++ for (i = 0; i < KB_COLS; s[i++] = 0x1F) \ -++ ; \ -++} while (0) -++ -++ -++static const unsigned short jz_col_gpios[KB_ROWS] = {76, 75, 74, 73, 72}; -++static const unsigned short jz_row_gpios[KB_COLS] = {181, 182, 79, 78, 77}; -++ -++static const unsigned int jz_kbd_keycode[KB_ROWS * KB_COLS] = { -++ KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, -++ KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, -++ KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, -++ KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, -++ KEY_LEFTSHIFT, KEY_CAPSLOCK, KEY_SPACE, KEY_BACKSPACE, KEY_Y -++}; -++ -++struct jz_kbd { -++ unsigned int keycode[ARRAY_SIZE(jz_kbd_keycode)]; -++ struct input_dev *input; -++ char phys[32]; -++ -++ spinlock_t lock; -++ struct timer_list timer; -++ -++ unsigned int suspended; -++ unsigned long suspend_jiffies; -++}; -++static struct jz_kbd g_jz_kbd; -++ -++static unsigned short scan_result[KB_COLS]; -++static unsigned short pre_scan_result[KB_COLS] = {0x1F, 0x1F, 0x1F, 0x1F, 0x1F}; -++static unsigned short pre_col, pre_row; -++ -++/** -++ * Scan keypad by reading GPIO pins. -++ */ -++static inline void jz_do_scan(unsigned short *s) -++{ -++ unsigned short i; -++ -++ if (!s) -++ return ; -++ -++ for (i = 0; i < KB_COLS; i++) { -++ -++ SET_GPIOS_AS_INPUT(); -++ __gpio_clear_pin(jz_col_gpios[i]); -++ __gpio_as_output(jz_col_gpios[i]); -++ -++ udelay(1000); -++ -++ s[i] = GET_ROW_GPIO_PINS(); -++ } -++} -++ -++/** -++ * Call scan function and handle 'GPIO event'(like key down, key up), -++ * and report it to upper layer of input subsystem ... if necessary -++ */ -++static void jz_kbd_scan(struct jz_kbd *kbd_data) -++{ -++ unsigned short row, col, i; -++ unsigned long flags; -++ -++ if (kbd_data->suspended) -++ return; -++ -++ spin_lock_irqsave(&kbd_data->lock, flags); -++ -++ jz_do_scan(scan_result); -++ -++ /* check if any key was pressed or not */ -++ if (!CHECK_IF_KEY_PRESSED(scan_result)) { -++ -++ /* key up */ -++ if (CHECK_IF_KEY_PRESSED(pre_scan_result)) { -++ input_report_key(kbd_data->input, kbd_data->keycode[pre_row * KB_COLS + pre_col], 0); -++ input_sync(kbd_data->input); -++ } -++ pre_col = pre_row = 0xFFFF; -++ CLEAN_SCAN_RESULT(pre_scan_result); -++ -++ spin_unlock_irqrestore(&kbd_data->lock, flags); -++ return; -++ } -++ -++ /* find the key */ -++ for (row = 0; row < KB_ROWS; row++) { -++ for (i = scan_result[row], col = 0; col < KB_COLS; col++) { -++ if ( !(i & 0x01) ) -++ break; -++ i >>= 1; -++ } -++ if (col != KB_COLS) -++ break; -++ } -++ -++ //printk("[DRIVER] row = %d, col = %d, key code: 0x%02X\n", row, col, kbd_data->keycode[row * KB_COLS + col]); -++ -++ /* the same as the preview one || new key */ -++ if ( (col == pre_col && row == pre_row) -++ || (pre_col == 0xFFFF && pre_row == 0xFFFF) ) { -++ -++ input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + col], 1); -++ input_sync(kbd_data->input); -++ -++ } else { -++ /* the preview key is up and other key is down */ -++ input_report_key(kbd_data->input, kbd_data->keycode[pre_row * KB_COLS + col], 0); -++ input_sync(kbd_data->input); -++ input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + col], 1); -++ input_sync(kbd_data->input); -++ } -++ -++ for (i = 0; i < KB_ROWS; i++) { -++ pre_scan_result[i] = scan_result[i]; -++ } -++ -++ pre_col = col; -++ pre_row = row; -++ -++ spin_unlock_irqrestore(&kbd_data->lock, flags); -++ -++ return; -++} -++ -++static void jz_kbd_timer_callback(unsigned long data) -++{ -++ jz_kbd_scan(&g_jz_kbd); -++ mod_timer(&g_jz_kbd.timer, jiffies + SCAN_INTERVAL); -++} -++ -++#ifdef CONFIG_PM -++static int jz_kbd_suspend(struct platform_device *dev, pm_message_t state) -++{ -++ struct jz_kbd *jz_kbd = platform_get_drvdata(dev); -++ jz_kbd->suspended = 1; -++ -++ return 0; -++} -++ -++static int jz_kbd_resume(struct platform_device *dev) -++{ -++ struct jz_kbd *jz_kbd = platform_get_drvdata(dev); -++ -++ jz_kbd->suspend_jiffies = jiffies; -++ jz_kbd->suspended = 0; -++ -++ return 0; -++} -++ -++#else -++#define jz_kbd_suspend NULL -++#define jz_kbd_resume NULL -++#endif -++ -++/** -++ * Driver init -++ */ -++static int __init jz_kbd_probe(struct platform_device *dev) -++{ -++ struct input_dev *input_dev; -++ int i, error; -++ -++ input_dev = input_allocate_device(); -++ if (!input_dev) -++ return -ENOMEM; -++ -++ platform_set_drvdata(dev, &g_jz_kbd); -++ -++ strcpy(g_jz_kbd.phys, "input/kbd0"); -++ -++ spin_lock_init(&g_jz_kbd.lock); -++ -++ g_jz_kbd.suspend_jiffies = jiffies; -++ g_jz_kbd.input = input_dev; -++ -++ input_dev->private = &g_jz_kbd; -++ input_dev->name = "JZ 5x5 Keypad"; -++ input_dev->phys = g_jz_kbd.phys; -++ input_dev->cdev.dev = &dev->dev; -++ -++ input_dev->id.bustype = BUS_PARPORT; -++ input_dev->id.vendor = 0x0001; -++ input_dev->id.product = 0x0001; -++ input_dev->id.version = 0x0100; -++ -++ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_SYN); -++ input_dev->keycode = g_jz_kbd.keycode; -++ input_dev->keycodesize = sizeof(unsigned int); -++ input_dev->keycodemax = ARRAY_SIZE(jz_kbd_keycode); -++ -++ memcpy(g_jz_kbd.keycode, jz_kbd_keycode, sizeof(g_jz_kbd.keycode)); -++ -++ for ( i = 0; i < ARRAY_SIZE(jz_kbd_keycode); i++) -++ set_bit(g_jz_kbd.keycode[i], input_dev->keybit); -++ -++ init_timer(&g_jz_kbd.timer); -++ g_jz_kbd.timer.function = jz_kbd_timer_callback; -++ g_jz_kbd.timer.data = (unsigned long)&g_jz_kbd; -++ mod_timer(&g_jz_kbd.timer, jiffies + SCAN_INTERVAL); -++ -++ error = input_register_device(input_dev); -++ if (error) { -++ pr_err("gpio-keys: Unable to register input device, " -++ "error: %d\n", error); -++ } -++ printk("input: JZ 5x5 Keypad Registered.\n"); -++ -++ return 0; -++} -++ -++static int jz_kbd_remove(struct platform_device *dev) -++{ -++ struct jz_kbd *kbd = platform_get_drvdata(dev); -++ -++ del_timer_sync(&kbd->timer); -++ -++ SET_GPIOS_AS_INPUT(); -++ -++ input_unregister_device(kbd->input); -++ -++ return 0; -++} -++ -++static struct platform_driver jz_kbd_driver = { -++ .probe = jz_kbd_probe, -++ .remove = jz_kbd_remove, -++ .suspend= jz_kbd_suspend, -++ .resume = jz_kbd_resume, -++ .driver = { -++ .name = "jz-5x5-keypad", -++ }, -++}; -++ -++static struct platform_device jzkbd_device = { -++ .name = "jz-5x5-keypad", -++ .id = -1, -++}; -++ -++static int __init jz_kbd_init(void) -++{ -++ platform_device_register(&jzkbd_device); -++ return platform_driver_register(&jz_kbd_driver); -++} -++ -++static void __exit jz_kbd_exit(void) -++{ -++ platform_device_unregister(&jzkbd_device); -++ platform_driver_unregister(&jz_kbd_driver); -++} -++ -++module_init(jz_kbd_init); -++module_exit(jz_kbd_exit); -++ -++MODULE_AUTHOR("Jason "); -++MODULE_DESCRIPTION("JZ 5x5 keypad driver"); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/drivers/media/video/Kconfig linux-2.6.24.7/drivers/media/video/Kconfig -+--- linux-2.6.24.7.old/drivers/media/video/Kconfig 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/media/video/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -514,6 +514,15 @@ -+ Say Y here to build in support for the Vino video input system found -+ on SGI Indy machines. -+ -++config VIDEO_JZ_CIM -++ tristate 'JzSOC Camera Interface Module (CIM) support' -++ depends on VIDEO_V4L2 -++ select VIDEO_JZ_SENSOR -++ -++config VIDEO_JZ_SENSOR -++ tristate "Jz generic camera sensor driver" -++ depends on VIDEO_JZ_CIM -++ -+ config VIDEO_STRADIS -+ tristate "Stradis 4:2:2 MPEG-2 video driver (EXPERIMENTAL)" -+ depends on EXPERIMENTAL && PCI && VIDEO_V4L1 && VIRT_TO_BUS -+diff -urN linux-2.6.24.7.old/drivers/media/video/Makefile linux-2.6.24.7/drivers/media/video/Makefile -+--- linux-2.6.24.7.old/drivers/media/video/Makefile 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/media/video/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -15,6 +15,9 @@ -+ obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o -+ endif -+ -++obj-$(CONFIG_VIDEO_JZ_CIM) += jz_cim.o -++obj-$(CONFIG_VIDEO_JZ_SENSOR) += jz_sensor.o -++ -+ obj-$(CONFIG_VIDEO_BT848) += bt8xx/ -+ obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o -+ obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o -+diff -urN linux-2.6.24.7.old/drivers/media/video/jz_cim.c linux-2.6.24.7/drivers/media/video/jz_cim.c -+--- linux-2.6.24.7.old/drivers/media/video/jz_cim.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/media/video/jz_cim.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,622 @@ -++/* -++ * linux/drivers/char/jzchar/cim.c -++ * -++ * Camera Interface Module (CIM) driver for JzSOC -++ * This driver is independent of the camera sensor -++ * -++ * Copyright (C) 2005 JunZheng semiconductor -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software Foundation, -++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++//#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++ -++#define CIM_NAME "cim" -++ -++MODULE_AUTHOR("Jianli Wei"); -++MODULE_DESCRIPTION("JzSOC Camera Interface Module driver"); -++MODULE_LICENSE("GPL"); -++ -++#undef DEBUG -++//#define DEBUG -++#ifdef DEBUG -++#define dprintk(x...) printk(x) -++#else -++#define dprintk(x...) -++#endif -++/* -++ * Define the Max Image Size -++ */ -++#define MAX_IMAGE_WIDTH 2048 -++#define MAX_IMAGE_HEIGHT 2048 -++#define MAX_IMAGE_BPP 16 -++#define MAX_FRAME_SIZE (MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * MAX_IMAGE_BPP / 8) -++#define CIM_RAM_ADDR (CIM_BASE + 0x1000) -++ -++typedef struct -++{ -++ u32 width; -++ u32 height; -++ u32 bpp; -++} img_param_t; -++ -++typedef struct -++{ -++ u32 cfg; -++ u32 ctrl; -++ u32 mclk; -++} cim_config_t; -++ -++/* -++ * IOCTL_XXX commands -++ */ -++#define IOCTL_SET_IMG_PARAM 0 // arg type: img_param_t * -++#define IOCTL_CIM_CONFIG 1 // arg type: cim_config_t * -++#define IOCTL_STOP_CIM 2 // arg type: void -++#define IOCTL_GET_IMG_PARAM 3 // arg type: img_param_t * -++#define IOCTL_GET_CIM_CONFIG 4 // arg type: cim_config_t * -++#define IOCTL_TEST_CIM_RAM 5 // no arg type * -++ -++/* -++ * CIM DMA descriptor -++ */ -++struct cim_desc { -++ u32 nextdesc; /* Physical address of next desc */ -++ u32 framebuf; /* Physical address of frame buffer */ -++ u32 frameid; /* Frame ID */ -++ u32 dmacmd; /* DMA command */ -++ u32 pagenum; -++}; -++ -++/* -++ * CIM device structure -++ */ -++struct cim_device { -++ struct video_device *jz_cim; -++ unsigned char *framebuf; -++ unsigned int frame_size; -++ unsigned int page_order; -++ wait_queue_head_t wait_queue; -++ struct cim_desc *frame_desc __attribute__ ((aligned (16))); -++}; -++ -++/* global*/ -++static struct cim_device *cim_dev; -++ -++/*========================================================================== -++ * CIM init routines -++ *========================================================================*/ -++#if defined(CONFIG_SOC_JZ4750) -++static void cim_image_area(img_param_t *c) { -++ /*set the image data area start 0, 0, lines_per_frame and pixels_per_line*/ -++ REG_CIM_SIZE = 0; -++ REG_CIM_OFFSET = 0; -++ if (REG_CIM_CTRL & CIM_CTRL_SIZEEN_MASK) { -++ REG_CIM_SIZE = (c->height << CIM_SIZE_LPF_BIT) | (c->width << CIM_SIZE_PPL_BIT); -++ REG_CIM_OFFSET = (0 << CIM_OFFSET_V_BIT) | (0 << CIM_OFFSET_H_BIT); -++// REG_CIM_OFFSET = (100 << CIM_OFFSET_V_BIT) | (50 << CIM_OFFSET_H_BIT); -++ } -++} -++#endif -++ -++static void cim_config(cim_config_t *c) -++{ -++ REG_CIM_CFG = c->cfg; -++ REG_CIM_CTRL = c->ctrl; -++ -++ /*Set the master clock output*/ -++#if defined(CONFIG_SOC_JZ4730) -++ __cim_set_master_clk(__cpm_get_sclk(), c->mclk); -++#elif defined(CONFIG_SOC_JZ4740) -++ __cim_set_master_clk(__cpm_get_hclk(), c->mclk); -++#elif defined(CONFIG_SOC_JZ4750) -++ __cim_set_master_clk(__cpm_get_hclk(), c->mclk); -++#else -++ __cim_set_master_clk(__cpm_get_hclk(), c->mclk); -++#endif -++ /* Enable sof, eof and stop interrupts*/ -++ __cim_enable_sof_intr(); -++ __cim_enable_eof_intr(); -++ __cim_enable_stop_intr(); -++} -++ -++/*========================================================================== -++ * CIM start/stop operations -++ *========================================================================*/ -++static int cim_start_dma(char *ubuf) -++{ -++ struct cim_desc *jz_frame_desc; -++ int cim_frame_size = 0; -++ jz_frame_desc = cim_dev->frame_desc; -++ dprintk("framedesc = %x\n", (u32) jz_frame_desc); -++ __cim_disable(); -++ dprintk("__cim_disable\n"); -++ __cim_set_da(virt_to_phys(cim_dev->frame_desc)); -++ __cim_clear_state(); // clear state register -++ __cim_reset_rxfifo(); // resetting rxfifo -++ __cim_unreset_rxfifo(); -++ __cim_enable_dma(); // enable dma -++ __cim_enable(); -++ -++ dprintk("__cim_enable\n"); -++// while(1) { -++// mdelay(10); -++// dprintk("REG_CIM_DA = 0x%08x\n", REG_CIM_DA); -++// dprintk("REG_CIM_FA = 0x%08x\n", REG_CIM_FA); -++// dprintk("REG_CIM_FID = 0x%08x\n", REG_CIM_FID); -++// dprintk("REG_CIM_CMD = 0x%08x\n", REG_CIM_CMD); -++// dprintk("REG_CIM_CFG = 0x%08x\n", REG_CIM_CFG); -++// dprintk("REG_CIM_STATE = 0x%08x\n", REG_CIM_STATE); -++// dprintk("REG_CIM_CTRL = 0x%08x\n", REG_CIM_CTRL); -++// dprintk("REG_CIM_SIZE = 0x%08x\n", REG_CIM_SIZE); -++// dprintk("REG_CIM_OFFSET = 0x%08x\n", REG_CIM_OFFSET); -++// mdelay(100); -++// } -++ // wait for interrupts -++ interruptible_sleep_on(&cim_dev->wait_queue); -++ dprintk("interruptible_sleep_on\n"); -++ dprintk("REG_CIM_DA = 0x%08x\n", REG_CIM_DA); -++ dprintk("REG_CIM_FA = 0x%08x\n", REG_CIM_FA); -++ dprintk("REG_CIM_FID = 0x%08x\n", REG_CIM_FID); -++ dprintk("REG_CIM_CMD = 0x%08x\n", REG_CIM_CMD); -++ dprintk("REG_CIM_CFG = 0x%08x\n", REG_CIM_CFG); -++ dprintk("REG_CIM_STATE = 0x%08x\n", REG_CIM_STATE); -++ dprintk("REG_CIM_CTRL = 0x%08x\n", REG_CIM_CTRL); -++ dprintk("REG_CIM_SIZE = 0x%08x\n", REG_CIM_SIZE); -++ dprintk("REG_CIM_OFFSET = 0x%08x\n", REG_CIM_OFFSET); -++ dprintk("REG_CIM_CMD_3 = %x\n", REG_CIM_CMD); -++ dprintk("REG_CIM_FA = %x\n", REG_CIM_FA); -++ /* copy frame data to user buffer */ -++ jz_frame_desc = cim_dev->frame_desc; -++ -++ while(jz_frame_desc != NULL) -++ { -++ dprintk("ubuf = %x, framebuf = %x,frame_size= %d\n", (u32)ubuf,(u32) jz_frame_desc->framebuf, jz_frame_desc->dmacmd & 0xffffff); -++ memcpy(ubuf, phys_to_virt(jz_frame_desc->framebuf), ((jz_frame_desc->dmacmd & CIM_CMD_LEN_MASK) * 4)); -++ ubuf += (jz_frame_desc->dmacmd & CIM_CMD_LEN_MASK) * 4; -++ cim_frame_size += (jz_frame_desc->dmacmd & CIM_CMD_LEN_MASK) * 4; -++ jz_frame_desc = (struct cim_desc *)phys_to_virt(jz_frame_desc->nextdesc); -++ } -++ return cim_dev->frame_size; -++} -++static void cim_stop(void) -++{ -++ __cim_disable(); -++ __cim_clear_state(); -++} -++ -++/*========================================================================== -++ * Framebuffer allocation and destroy -++ *========================================================================*/ -++static void cim_fb_destroy(void) -++{ -++ int pages; -++ struct cim_desc *jz_frame_desc, *p_desc; -++ if (cim_dev->frame_desc == NULL) { -++ printk("Original memory is NULL\n"); -++ return; -++ } -++ jz_frame_desc = cim_dev->frame_desc; -++ while (jz_frame_desc != NULL) { -++ dprintk("framebuf = %x,thisdesc = %x,frame_size= %d\n", (u32) jz_frame_desc->framebuf, (unsigned int)jz_frame_desc, (jz_frame_desc->dmacmd & 0xffffff) * 4); -++ p_desc = (struct cim_desc *)phys_to_virt(jz_frame_desc->nextdesc); -++ pages = jz_frame_desc->pagenum; -++ dprintk("page_order = %d\n", pages); -++ free_pages((unsigned long)phys_to_virt(jz_frame_desc->framebuf), pages); -++ kfree(jz_frame_desc); -++ jz_frame_desc = p_desc; -++ } -++ cim_dev->frame_desc = NULL; -++} -++ -++static struct cim_desc *get_desc_list(int page_order) -++{ -++ int num, page_nums = 0; -++ unsigned char *p_buf; -++ struct cim_desc *desc_list_head __attribute__ ((aligned (16))); -++ struct cim_desc *desc_list_tail __attribute__ ((aligned (16))); -++ struct cim_desc *p_desc; -++// num = page_order - 1; -++ num = page_order; -++ desc_list_head = desc_list_tail = NULL; -++ -++ while(page_nums < (1 << page_order)) { -++ p_desc = (struct cim_desc *)kmalloc(sizeof(struct cim_desc), GFP_KERNEL); -++ if (NULL == p_desc) -++ return NULL; -++ //return -ENOMEM; -++ cim_realloc_pages: -++ p_buf = (unsigned char *)__get_free_pages(GFP_KERNEL, num); -++ if ( !(p_buf) && num != 0) { -++ num --; -++ goto cim_realloc_pages; -++ } -++ else if ( !(p_buf) && num == 0) { -++ printk("No memory can be alloc!\n"); -++ //return -ENOMEM; -++ return NULL; -++ } -++ else { -++ if (desc_list_head == NULL) { -++ dprintk("Page_list_head\n"); -++ desc_list_head = p_desc; -++ } -++ -++ else -++ desc_list_tail->nextdesc = virt_to_phys(p_desc); -++ -++ desc_list_tail = p_desc; -++ desc_list_tail->framebuf = virt_to_phys(p_buf); -++ dprintk("framebuf addr is 0x%08x\n", (u32)desc_list_tail->framebuf); -++ dprintk("frame_desc addr is 0x%08x\n",(u32)virt_to_phys(desc_list_tail)); -++ -++ desc_list_tail->frameid = 0x52052018; -++ desc_list_tail->pagenum = num; -++ if ((page_nums + (1<< num)) < (1 << page_order)) { -++ desc_list_tail->dmacmd = ((1 << num) * 4096) >> 2 ; -++ } -++ else -++ desc_list_tail->dmacmd = -++ (cim_dev->frame_size - page_nums * 4096) >> 2 ; -++ dprintk("the desc_list_tail->dmacmd is 0x%08x\n", desc_list_tail->dmacmd); -++ page_nums += (1 << num); -++ dprintk("the pages_num is %d\n", page_nums); -++ } -++ } -++ -++ desc_list_tail->nextdesc = virt_to_phys(NULL); -++ /* stop after capturing a frame */ -++ desc_list_tail->dmacmd |= (CIM_CMD_STOP | CIM_CMD_EOFINT); -++ dprintk("the desc_list_tail->dmacmd is 0x%08x\n", desc_list_tail->dmacmd); -++ -++ return desc_list_head; -++} -++ -++static int cim_fb_alloc(int img_width, int img_height, int img_bpp) -++{ -++#if defined(CONFIG_SOC_JZ4750) -++ if ((REG_CIM_CFG & (CIM_CFG_DF_MASK | CIM_CFG_BYPASS_MASK)) == 0) -++ cim_dev->frame_size = img_width * (img_height-1) * (img_bpp/8); -++ else -++ cim_dev->frame_size = img_width * img_height * (img_bpp/8); -++#else -++ cim_dev->frame_size = img_width * img_height * (img_bpp/8); -++#endif -++ cim_dev->page_order = get_order(cim_dev->frame_size); -++ dprintk("cim_dev->page_order=%d\n", cim_dev->page_order); -++ /* frame buffer ?? need large mem ??*/ -++ cim_dev->frame_desc = get_desc_list(cim_dev->page_order); -++ if (cim_dev->frame_desc == NULL) -++ return -ENOMEM; -++ dma_cache_wback((unsigned long)(cim_dev->frame_desc), 16); -++ return 0; -++} -++ -++/*========================================================================== -++ * File operations -++ *========================================================================*/ -++ -++static int cim_open(struct inode *inode, struct file *filp); -++static int cim_release(struct inode *inode, struct file *filp); -++static ssize_t cim_read(struct file *filp, char *buf, size_t size, loff_t *l); -++static ssize_t cim_write(struct file *filp, const char *buf, size_t size, loff_t *l); -++static int cim_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -++static int cim_mmap(struct file *file, struct vm_area_struct *vma); -++ -++static struct file_operations cim_fops = -++{ -++ open: cim_open, -++ release: cim_release, -++ read: cim_read, -++ write: cim_write, -++ ioctl: cim_ioctl, -++ compat_ioctl: v4l_compat_ioctl32, -++ mmap: cim_mmap -++}; -++ -++static struct video_device jz_v4l_device = { -++ .name = "jz cim", -++ //.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | -++ // VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY -++ .fops = &cim_fops, -++ .minor = -1, -++ .owner = THIS_MODULE, -++ .release = video_device_release, -++}; -++ -++static int cim_open(struct inode *inode, struct file *filp) -++{ -++ -++ try_module_get(THIS_MODULE); -++ return 0; -++} -++ -++static int cim_release(struct inode *inode, struct file *filp) -++{ -++ cim_fb_destroy(); -++ cim_stop(); -++ -++ module_put(THIS_MODULE); -++ return 0; -++} -++ -++static ssize_t cim_read(struct file *filp, char *buf, size_t size, loff_t *l) -++{ -++ if (size < cim_dev->frame_size) -++ return -EINVAL; -++ dprintk("read cim\n"); -++ return cim_start_dma(buf); -++} -++ -++static ssize_t cim_write(struct file *filp, const char *buf, size_t size, loff_t *l) -++{ -++ printk("cim error: write is not implemented\n"); -++ return -1; -++} -++ -++static int cim_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -++{ -++ void __user *argp = (void __user *)arg; -++ switch (cmd) { -++ case IOCTL_GET_IMG_PARAM: -++ { -++ img_param_t i; -++ return copy_to_user(argp, &i, sizeof(img_param_t)) ? -EFAULT : 0; -++ } -++ case IOCTL_SET_IMG_PARAM: -++ { -++ img_param_t i; -++ int img_width, img_height, img_bpp; -++ if (copy_from_user((void *)&i, (void *)arg, sizeof(img_param_t))) -++ return -EFAULT; -++#if defined(CONFIG_SOC_JZ4750) -++ cim_image_area(&i); -++#endif -++ img_width = i.width; -++ img_height = i.height; -++ img_bpp = i.bpp; -++ dprintk("ioctl_set_cim_param\n"); -++ if ((img_width * img_height * img_bpp/8) > MAX_FRAME_SIZE){ -++ printk("ERROR! Image is too large!\n"); -++ return -EINVAL; -++ } -++ /* allocate frame buffers */ -++ if (cim_dev->frame_desc == NULL){ -++ if (cim_fb_alloc(img_width, img_height, img_bpp) < 0){ -++ printk("ERROR! Init & alloc cim fail!\n"); -++ return -ENOMEM; -++ } -++ } -++ else -++ if ((img_width * img_height * img_bpp/8) > cim_dev->frame_size){ -++ /* realloc the buffer */ -++ cim_fb_destroy(); -++ if (cim_fb_alloc(img_width, img_height, img_bpp) < 0){ -++ printk("ERRROR! Init & alloc cim fail!\n"); -++ return -ENOMEM; -++ } -++ } -++ break; -++ } -++ case IOCTL_CIM_CONFIG: -++ { -++ cim_config_t c; -++ -++ if (copy_from_user((void *)&c, (void *)arg, sizeof(cim_config_t))) -++ return -EFAULT; -++ -++ cim_config(&c); -++ -++ break; -++ } -++ case IOCTL_TEST_CIM_RAM: -++ { -++ -++ int i; -++ volatile unsigned int *ptr; -++ ptr = (volatile unsigned int *)(CIM_RAM_ADDR); -++ printk("RAM test!\n"); -++ printk("CIM_RAM_ADDR = 0x%08x\n", CIM_RAM_ADDR); -++ for (i = 0; i < 1024; ptr++, i++) -++ *ptr = i; -++ ptr = (volatile unsigned int *)(CIM_RAM_ADDR); -++ dma_cache_wback((unsigned long)CIM_RAM_ADDR,0xffc); -++ -++ for (i = 0; i < 1024; i++) { -++ if (i != *ptr) -++ printk("*ptr!=i, *ptr=%d, i=%d\n", *ptr, i); -++ if (i%32 == 0) { -++ if (i%128 == 0) -++ printk("\n"); -++ printk("*ptr=%04d, i=%04d | ", *ptr, i); -++ } -++ ptr++; -++ } -++ printk("\n"); -++ break; -++ } -++ default: -++ printk("Not supported command: 0x%x\n", cmd); -++ return -EINVAL; -++ break; -++ } -++ return 0; -++} -++ -++/* Use mmap /dev/fb can only get a non-cacheable Virtual Address. */ -++static int cim_mmap(struct file *file, struct vm_area_struct *vma) -++{ -++ unsigned long start; -++ unsigned long off; -++ u32 len; -++ -++ off = vma->vm_pgoff << PAGE_SHIFT; -++ //fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); -++ -++ /* frame buffer memory */ -++ start = cim_dev->frame_desc->framebuf; -++ len = PAGE_ALIGN((start & ~PAGE_MASK) + (cim_dev->frame_desc->dmacmd & CIM_CMD_LEN_MASK)); -++ start &= PAGE_MASK; -++ -++ if ((vma->vm_end - vma->vm_start + off) > len) -++ return -EINVAL; -++ off += start; -++ -++ vma->vm_pgoff = off >> PAGE_SHIFT; -++ vma->vm_flags |= VM_IO; -++ -++#if defined(CONFIG_MIPS32) -++ pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; -++// pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NO_WA; /* WT cachable */ -++ pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; -++#endif -++ -++ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, -++ vma->vm_end - vma->vm_start, -++ vma->vm_page_prot)) -++ vma->vm_flags |= VM_IO; -++ return -EAGAIN; -++ -++ return 0; -++} -++/*========================================================================== -++ * Interrupt handler -++ *========================================================================*/ -++ -++static irqreturn_t cim_irq_handler(int irq, void *dev_id) -++{ -++ u32 state = REG_CIM_STATE; -++ dprintk("REG_CIM_STATE = %x\n", REG_CIM_STATE); -++ dprintk("REG_CIM_CTRL = %x\n", REG_CIM_CTRL); -++#if 1 -++ if (state & CIM_STATE_RXF_OF) { -++ dprintk("OverFlow interrupt!\n"); -++ } -++#endif -++ if (state & CIM_STATE_DMA_EOF) { -++ dprintk("EOF interrupt!\n"); -++ __cim_disable_dma(); -++ __cim_disable(); -++ wake_up_interruptible(&cim_dev->wait_queue); -++ dprintk("EOF interrupt wake up!\n"); -++ } -++ -++ if (state & CIM_STATE_DMA_STOP) { -++ // Got a frame, wake up wait routine -++ __cim_disable_dma(); -++ __cim_disable(); -++ dprintk("Stop interrupt!\n"); -++ wake_up_interruptible(&cim_dev->wait_queue); -++ } -++#if 1 -++ if (state & CIM_STATE_RXF_TRIG) { -++ dprintk("Trig!\n"); -++ } -++#endif -++ -++ /* clear status flags*/ -++ REG_CIM_STATE = 0; -++ return IRQ_HANDLED; -++} -++ -++static int v4l_device_init(void) -++{ -++ cim_dev = kzalloc(sizeof(struct cim_device), GFP_KERNEL); -++ if (!cim_dev) return -ENOMEM; -++ cim_dev->jz_cim = video_device_alloc(); -++ if (!cim_dev->jz_cim) { -++ return -ENOMEM; -++ } -++ memcpy(cim_dev->jz_cim, &jz_v4l_device, sizeof(struct video_device)); -++ cim_dev->frame_desc = NULL; -++ cim_dev->frame_size = 0; -++ cim_dev->page_order = 0; -++ return 0; -++} -++/*========================================================================== -++ * Module init and exit -++ *========================================================================*/ -++ -++static int __init jz_cim_init(void) -++{ -++ struct cim_device *dev; -++ int ret; -++ /* allocate device */ -++ ret = v4l_device_init(); -++ if (ret) -++ return ret; -++ /* record device */ -++ dev = cim_dev; -++ init_waitqueue_head(&dev->wait_queue); -++ -++ ret = video_register_device(dev->jz_cim, VFL_TYPE_GRABBER, -1); -++ if (ret < 0) { -++ printk(KERN_ERR "CIM Video4Linux-device " -++ "registration failed\n"); -++ return -EINVAL; -++ } -++ -++ if (ret < 0) { -++ cim_fb_destroy(); -++ kfree(dev); -++ return ret; -++ } -++ -++ if ((ret = request_irq(IRQ_CIM, cim_irq_handler, IRQF_DISABLED, -++ CIM_NAME, dev))) { -++ printk(KERN_ERR "request_irq return error, ret=%d\n", ret); -++ cim_fb_destroy(); -++ kfree(dev); -++ printk(KERN_ERR "CIM could not get IRQ\n"); -++ return ret; -++ } -++ -++ printk("JzSOC Camera Interface Module (CIM) driver registered\n"); -++ -++ return 0; -++} -++ -++static void __exit jz_cim_exit(void) -++{ -++ free_irq(IRQ_CIM, cim_dev); -++ kfree(cim_dev); -++ video_unregister_device(cim_dev->jz_cim); -++} -++ -++module_init(jz_cim_init); -++module_exit(jz_cim_exit); -+diff -urN linux-2.6.24.7.old/drivers/media/video/jz_cim.h linux-2.6.24.7/drivers/media/video/jz_cim.h -+--- linux-2.6.24.7.old/drivers/media/video/jz_cim.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/media/video/jz_cim.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,36 @@ -++/* -++ * JzSOC CIM driver -++ * -++ * Copyright (C) 2005 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ * GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ */ -++ -++#ifndef __JZ_CIM_H__ -++#define __JZ_CIM_H__ -++ -++typedef struct -++{ -++ u32 width; -++ u32 height; -++ u32 bpp; -++} IMG_PARAM; -++ -++/* -++ * IOCTL_XXX commands -++ */ -++#define IOCTL_SET_IMG_PARAM 0 // arg type: IMG_PARAM * -++ -++#endif /* __JZ__CIM_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/media/video/jz_sensor.c linux-2.6.24.7/drivers/media/video/jz_sensor.c -+--- linux-2.6.24.7.old/drivers/media/video/jz_sensor.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/media/video/jz_sensor.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,202 @@ -++/* -++ * linux/drivers/char/jzchar/sensor.c -++ * -++ * Common CMOS Camera Sensor Driver -++ * -++ * Copyright (C) 2006 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ */ -++ -++//#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++//#include -++//#include "jz-chars.h" -++ -++#include -++#include -++#include -++ -++#include -++#include -++#include -++ -++MODULE_AUTHOR("Jianli Wei"); -++MODULE_DESCRIPTION("Common CMOS Camera Sensor Driver"); -++MODULE_LICENSE("GPL"); -++ -++/* -++ * ioctl commands -++ */ -++#define IOCTL_SET_ADDR 0 /* set i2c address */ -++#define IOCTL_SET_CLK 1 /* set i2c clock */ -++#define IOCTL_WRITE_REG 2 /* write sensor register */ -++#define IOCTL_READ_REG 3 /* read sensor register */ -++ -++/* -++ * i2c related -++ */ -++static unsigned int i2c_addr = 0x42; -++static unsigned int i2c_clk = 100000; -++ -++struct video_device *jz_sensor; -++ -++static void write_reg(u8 reg, u8 val) -++{ -++ i2c_open(); -++ i2c_setclk(i2c_clk); -++ i2c_write((i2c_addr >> 1), &val, reg, 1); -++ i2c_close(); -++} -++ -++static u8 read_reg(u8 reg) -++{ -++ u8 val; -++ -++ i2c_open(); -++ i2c_setclk(i2c_clk); -++ i2c_read((i2c_addr >> 1), &val, reg, 1); -++ i2c_close(); -++ return val; -++} -++ -++/* -++ * fops routines -++ */ -++ -++static int sensor_open(struct inode *inode, struct file *filp); -++static int sensor_release(struct inode *inode, struct file *filp); -++static ssize_t sensor_read(struct file *filp, char *buf, size_t size, loff_t *l); -++static ssize_t sensor_write(struct file *filp, const char *buf, size_t size, loff_t *l); -++static int sensor_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -++ -++static struct file_operations sensor_fops = -++{ -++ open: sensor_open, -++ release: sensor_release, -++ read: sensor_read, -++ write: sensor_write, -++ ioctl: sensor_ioctl, -++}; -++ -++static int sensor_open(struct inode *inode, struct file *filp) -++{ -++ try_module_get(THIS_MODULE); -++ return 0; -++} -++ -++static int sensor_release(struct inode *inode, struct file *filp) -++{ -++ module_put(THIS_MODULE); -++ return 0; -++} -++ -++static ssize_t sensor_read(struct file *filp, char *buf, size_t size, loff_t *l) -++{ -++ printk("sensor: read is not implemented\n"); -++ return -1; -++} -++ -++static ssize_t sensor_write(struct file *filp, const char *buf, size_t size, loff_t *l) -++{ -++ printk("sensor: write is not implemented\n"); -++ return -1; -++} -++ -++static int sensor_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -++{ -++ int ret = 0; -++ -++ switch (cmd) { -++ case IOCTL_SET_ADDR: -++ if (copy_from_user(&i2c_addr, (void *)arg, 4)) -++ return -EFAULT; -++ break; -++ case IOCTL_SET_CLK: -++ if (copy_from_user(&i2c_clk, (void *)arg, 4)) -++ return -EFAULT; -++ break; -++ case IOCTL_WRITE_REG: -++ { -++ u8 regval[2]; -++ -++ if (copy_from_user(regval, (void *)arg, 2)) -++ return -EFAULT; -++ -++ write_reg(regval[0], regval[1]); -++ break; -++ } -++ case IOCTL_READ_REG: -++ { -++ u8 reg, val; -++ -++ if (copy_from_user(®, (void *)arg, 1)) -++ return -EFAULT; -++ -++ val = read_reg(reg); -++ -++ if (copy_to_user((void *)(arg + 1), &val, 1)) -++ return -EFAULT; -++ break; -++ } -++ default: -++ printk("Not supported command: 0x%x\n", cmd); -++ return -EINVAL; -++ break; -++ } -++ return ret; -++} -++ -++static struct video_device jz_v4l_device = { -++ .name = "jz sensor", -++ //.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | -++ // VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY -++ .fops = &sensor_fops, -++ .minor = -1, -++}; -++ -++/* -++ * Module init and exit -++ */ -++ -++static int __init jz_sensor_init(void) -++{ -++ int ret; -++// cim_dev = kzalloc(sizeof(struct cim_device), GFP_KERNEL); -++ jz_sensor = video_device_alloc(); -++ memcpy(jz_sensor, &jz_v4l_device, sizeof(struct video_device)); -++ jz_sensor->release = video_device_release; -++// ret = jz_register_chrdev(SENSOR_MINOR, "sensor", &sensor_fops, NULL); -++ ret = video_register_device(jz_sensor, VFL_TYPE_GRABBER, -1); -++ if (ret < 0) { -++ return ret; -++ } -++ -++ printk("Ingenic CMOS camera sensor driver registered\n"); -++ -++ return 0; -++} -++ -++static void __exit jz_sensor_exit(void) -++{ -++// jz_unregister_chrdev(SENSOR_MINOR, "sensor"); -++ video_unregister_device(jz_sensor); -++} -++ -++module_init(jz_sensor_init); -++module_exit(jz_sensor_exit); -+diff -urN linux-2.6.24.7.old/drivers/mmc/card/block.c linux-2.6.24.7/drivers/mmc/card/block.c -+--- linux-2.6.24.7.old/drivers/mmc/card/block.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mmc/card/block.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -225,7 +225,11 @@ -+ brq.mrq.cmd = &brq.cmd; -+ brq.mrq.data = &brq.data; -+ -++#ifdef CONFIG_JZ4750_BOOT_FROM_MSC0 -++ brq.cmd.arg = req->sector + 8192; -++#else -+ brq.cmd.arg = req->sector; -++#endif -+ if (!mmc_card_blockaddr(card)) -+ brq.cmd.arg <<= 9; -+ brq.cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; -+diff -urN linux-2.6.24.7.old/drivers/mmc/core/mmc.c linux-2.6.24.7/drivers/mmc/core/mmc.c -+--- linux-2.6.24.7.old/drivers/mmc/core/mmc.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mmc/core/mmc.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -141,8 +141,13 @@ -+ -+ e = UNSTUFF_BITS(resp, 47, 3); -+ m = UNSTUFF_BITS(resp, 62, 12); -+- csd->capacity = (1 + m) << (e + 2); -+ -++#ifdef CONFIG_JZ4750_BOOT_FROM_MSC0 -++ csd->capacity = (1 + m) << (e + 2); -++ csd->capacity -= 8192; -++#else -++ csd->capacity = (1 + m) << (e + 2); -++#endif -+ csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); -+ csd->read_partial = UNSTUFF_BITS(resp, 79, 1); -+ csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); -+@@ -402,8 +407,9 @@ -+ EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4); -+ if (err) -+ goto free_card; -+- -+- mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); -++ -++ /* all mmc v4 support 8 bit mmc card */ -++ mmc_set_bus_width(card->host, MMC_BUS_WIDTH_8); -+ } -+ -+ if (!oldcard) -+diff -urN linux-2.6.24.7.old/drivers/mmc/core/sd.c linux-2.6.24.7/drivers/mmc/core/sd.c -+--- linux-2.6.24.7.old/drivers/mmc/core/sd.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mmc/core/sd.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -110,8 +110,13 @@ -+ -+ e = UNSTUFF_BITS(resp, 47, 3); -+ m = UNSTUFF_BITS(resp, 62, 12); -+- csd->capacity = (1 + m) << (e + 2); -+ -++#ifdef CONFIG_JZ4750_BOOT_FROM_MSC0 -++ csd->capacity = (1 + m) << (e + 2); -++ csd->capacity -= 8192; -++#else -++ csd->capacity = (1 + m) << (e + 2); -++#endif -+ csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); -+ csd->read_partial = UNSTUFF_BITS(resp, 79, 1); -+ csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); -+@@ -138,8 +143,13 @@ -+ csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); -+ -+ m = UNSTUFF_BITS(resp, 48, 22); -+- csd->capacity = (1 + m) << 10; -+ -++#ifdef CONFIG_JZ4750_BOOT_FROM_MSC0 -++ csd->capacity = (1 + m) << 10; -++ csd->capacity -= 8192; -++#else -++ csd->capacity = (1 + m) << 10; -++#endif -+ csd->read_blkbits = 9; -+ csd->read_partial = 0; -+ csd->write_misalign = 0; -+@@ -269,9 +279,11 @@ -+ goto out; -+ -+ if ((status[16] & 0xF) != 1) { -++#if 0 -+ printk(KERN_WARNING "%s: Problem switching card " -+ "into high-speed mode!\n", -+ mmc_hostname(card->host)); -++#endif -+ } else { -+ mmc_card_set_highspeed(card); -+ mmc_set_timing(card->host, MMC_TIMING_SD_HS); -+@@ -386,6 +398,9 @@ -+ goto free_card; -+ -+ mmc_decode_cid(card); -++ -++ /* set 24MHz clock again, why?? */ -++ mmc_set_clock(host, 24000000); -+ } -+ -+ /* -+diff -urN linux-2.6.24.7.old/drivers/mmc/host/Kconfig linux-2.6.24.7/drivers/mmc/host/Kconfig -+--- linux-2.6.24.7.old/drivers/mmc/host/Kconfig 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mmc/host/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -4,6 +4,104 @@ -+ -+ comment "MMC/SD Host Controller Drivers" -+ -++config MMC_JZ -++ tristate "JZ SD/Multimedia Card Interface support" -++ depends on SOC_JZ4730 || SOC_JZ4740 -++ help -++ This selects the Ingenic JZ4730/JZ4740 SD/Multimedia card Interface. -++ If you have abIngenic platform with a Multimedia Card slot, -++ say Y or M here. -++ -++ If unsure, say N. -++choice -++ depends on MMC_JZ -++ prompt "MMC BUS Width" -++ default JZ_MMC_BUS_4 -++ help -++ This defines the BUS Width of the Ingenic JZ4730/JZ4740 SD/Multimedia card Interface. -++ -++config JZ_MMC_BUS_1 -++ bool "1 Bit Bus" -++ help -++ 1 Bit SD/Multimedia Card Bus -++ -++config JZ_MMC_BUS_4 -++ bool "4 Bit Bus" -++ help -++ 4 Bit SD/Multimedia Card Bus -++ -++endchoice -++ -++config MSC0_JZ4750 -++ tristate "JZ4750 SD/Multimedia Card 0 Interface support" -++ depends on SOC_JZ4750 || SOC_JZ4750D -++ help -++ This selects the Ingenic JZ4750 SD/Multimedia card 0 Interface. -++ If you have a Ingenic platform with a Multimedia Card slot, -++ say Y or M here. -++ -++ If unsure, say N. -++ -++choice -++ depends on MSC0_JZ4750 -++ prompt "MSC0 BUS Width" -++ default JZ4750_MSC0_BUS_4 -++ help -++ This defines the BUS Width of the Ingenic JZ4750 SD/Multimedia card Interface. -++ -++config JZ4750_MSC0_BUS_1 -++ bool "1 Bit Bus" -++ help -++ 1 Bit SD/Multimedia Card Bus -++ -++config JZ4750_MSC0_BUS_4 -++ bool "4 Bit Bus" -++ help -++ 4 Bit SD/Multimedia Card Bus -++ -++config JZ4750_MSC0_BUS_8 -++ bool "8 Bit Bus" -++ help -++ 8 Bit Multimedia Card Bus -++ -++endchoice -++ -++config MSC1_JZ4750 -++ tristate "JZ4750 SD/Multimedia Card 1 Interface support" -++ depends on SOC_JZ4750 || SOC_JZ4750D -++ help -++ This selects the Ingenic JZ4750 SD/Multimedia card 1 Interface. -++ If you have a Ingenic platform with a Multimedia Card slot, -++ say Y or M here. -++ -++ If unsure, say N. -++ -++choice -++ depends on MSC1_JZ4750 -++ prompt "MSC1 BUS Width" -++ default JZ4750_MSC1_BUS_4 -++ help -++ This defines the BUS Width of the Ingenic JZ4750 SD/Multimedia card Interface. -++ -++config JZ4750_MSC1_BUS_1 -++ bool "1 Bit Bus" -++ help -++ 1 Bit SD/Multimedia Card Bus -++ -++config JZ4750_MSC1_BUS_4 -++ bool "4 Bit Bus" -++ help -++ 4 Bit SD/Multimedia Card Bus -++endchoice -++ -++config JZ4750_BOOT_FROM_MSC0 -++ tristate "JZ4750 Boot from SD/Multimedia Card Interface support" -++ depends on SOC_JZ4750 || SOC_JZ4750D -++ help -++ This selects boot from the Sd/Multimedia Card. -++ -++ If unsure,say N. -++ -+ config MMC_ARMMMCI -+ tristate "ARM AMBA Multimedia Card Interface support" -+ depends on ARM_AMBA -+diff -urN linux-2.6.24.7.old/drivers/mmc/host/Makefile linux-2.6.24.7/drivers/mmc/host/Makefile -+--- linux-2.6.24.7.old/drivers/mmc/host/Makefile 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mmc/host/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -6,6 +6,9 @@ -+ EXTRA_CFLAGS += -DDEBUG -+ endif -+ -++obj-$(CONFIG_MMC_JZ) += jz_mmc.o -++obj-$(CONFIG_MSC0_JZ4750) += jz4750_mmc.o -++obj-$(CONFIG_MSC1_JZ4750) += jz4750_mmc.o -+ obj-$(CONFIG_MMC_ARMMMCI) += mmci.o -+ obj-$(CONFIG_MMC_PXA) += pxamci.o -+ obj-$(CONFIG_MMC_IMX) += imxmmc.o -+diff -urN linux-2.6.24.7.old/drivers/mmc/host/jz4750_mmc.c linux-2.6.24.7/drivers/mmc/host/jz4750_mmc.c -+--- linux-2.6.24.7.old/drivers/mmc/host/jz4750_mmc.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mmc/host/jz4750_mmc.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1051 @@ -++/* -++ * linux/drivers/mmc/jz_mmc.c - JZ SD/MMC driver -++ * -++ * Copyright (C) 2005 - 2008 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include "jz4750_mmc.h" -++ -++#define DRIVER_NAME "jz-mmc" -++ -++#define USE_DMA -++ -++static int r_type = 0; -++static int rxdmachan = 0; -++static int txdmachan = 0; -++static int mmc_slot_enable = 0; -++static int auto_select_bus = MSC_4BIT_BUS; /* default 4 bit bus*/ -++ -++/* Start the MMC clock and operation */ -++static inline int jz_mmc_start_op(void) -++{ -++ REG_MSC_STRPCL(MSC_ID) = MSC_STRPCL_START_OP; -++ -++ return MMC_NO_ERROR; -++} -++ -++static inline u32 jz_mmc_calc_clkrt(int is_low, u32 rate) -++{ -++ u32 clkrt; -++ u32 clk_src = is_low ? 24000000 : 48000000; -++ -++ clkrt = 0; -++ while (rate < clk_src) { -++ clkrt++; -++ clk_src >>= 1; -++ } -++ return clkrt; -++} -++ -++/* Select the MMC clock frequency */ -++static int jz_mmc_set_clock(u32 rate) -++{ -++ int clkrt; -++ -++ /* __cpm_select_msc_clk_high will select 48M clock for MMC/SD card -++ * perhaps this will made some card with bad quality init fail,or -++ * bad stabilization. -++ */ -++ if (rate > SD_CLOCK_FAST) { -++ __cpm_select_msc_clk_high(MSC_ID,1); /* select clock source from CPM */ -++ clkrt = jz_mmc_calc_clkrt(0, rate); -++ } else { -++ __cpm_select_msc_clk(MSC_ID,1); /* select clock source from CPM */ -++ clkrt = jz_mmc_calc_clkrt(1, rate); -++ } -++ -++#ifndef CONFIG_FPGA -++ REG_MSC_CLKRT(MSC_ID) = clkrt; -++#else -++ REG_MSC_CLKRT(MSC_ID) = 7; -++#endif -++ return MMC_NO_ERROR; -++} -++ -++static void jz_mmc_enable_irq(struct jz_mmc_host *host, unsigned int mask) -++{ -++ unsigned long flags; -++ -++ spin_lock_irqsave(&host->lock, flags); -++ host->imask &= ~mask; -++ REG_MSC_IMASK(MSC_ID) = host->imask; -++ spin_unlock_irqrestore(&host->lock, flags); -++} -++ -++static void jz_mmc_disable_irq(struct jz_mmc_host *host, unsigned int mask) -++{ -++ unsigned long flags; -++ -++ spin_lock_irqsave(&host->lock, flags); -++ host->imask |= mask; -++ REG_MSC_IMASK(MSC_ID) = host->imask; -++ spin_unlock_irqrestore(&host->lock, flags); -++} -++ -++void jz_set_dma_block_size(int dmanr, int nbyte); -++ -++#ifdef USE_DMA -++static inline void -++jz_mmc_start_dma(int chan, unsigned long phyaddr, int count, int mode) -++{ -++ unsigned long flags; -++ -++ flags = claim_dma_lock(); -++ disable_dma(chan); -++ clear_dma_ff(chan); -++ jz_set_dma_block_size(chan, 32); -++ set_dma_mode(chan, mode); -++ set_dma_addr(chan, phyaddr); -++ set_dma_count(chan, count + 31); -++ enable_dma(chan); -++ release_dma_lock(flags); -++} -++ -++static irqreturn_t jz_mmc_dma_rx_callback(int irq, void *devid) -++{ -++ int chan = rxdmachan; -++ -++ disable_dma(chan); -++ if (__dmac_channel_address_error_detected(chan)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", -++ __FUNCTION__); -++ __dmac_channel_clear_address_error(chan); -++ } -++ if (__dmac_channel_transmit_end_detected(chan)) { -++ __dmac_channel_clear_transmit_end(chan); -++ } -++ return IRQ_HANDLED; -++} -++static irqreturn_t jz_mmc_dma_tx_callback(int irq, void *devid) -++{ -++ int chan = txdmachan; -++ -++ disable_dma(chan); -++ if (__dmac_channel_address_error_detected(chan)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", -++ __FUNCTION__); -++ __dmac_channel_clear_address_error(chan); -++ } -++ if (__dmac_channel_transmit_end_detected(chan)) { -++ __dmac_channel_clear_transmit_end(chan); -++ } -++ return IRQ_HANDLED; -++} -++ -++/* Prepare DMA to start data transfer from the MMC card */ -++static void jz_mmc_rx_setup_data(struct jz_mmc_host *host, -++ struct mmc_data *data) -++{ -++ unsigned int nob = data->blocks; -++ int channelrx = rxdmachan; -++ int i; -++ u32 size; -++ -++ if (data->flags & MMC_DATA_STREAM) -++ nob = 0xffff; -++ -++ REG_MSC_NOB(MSC_ID) = nob; -++ REG_MSC_BLKLEN(MSC_ID) = data->blksz; -++ size = nob * data->blksz; -++ -++ if (data->flags & MMC_DATA_READ) { -++ host->dma.dir = DMA_FROM_DEVICE; -++ } else { -++ host->dma.dir = DMA_TO_DEVICE; -++ } -++ -++ host->dma.len = -++ dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, -++ host->dma.dir); -++ -++ for (i = 0; i < host->dma.len; i++) { -++ host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]); -++ host->sg_cpu[i].dcmd = sg_dma_len(&data->sg[i]); -++ dma_cache_wback_inv((unsigned long) -++ CKSEG0ADDR(sg_dma_address(data->sg)) + -++ data->sg->offset, -++ host->sg_cpu[i].dcmd); -++ jz_mmc_start_dma(channelrx, host->sg_cpu[i].dtadr, -++ host->sg_cpu[i].dcmd, DMA_MODE_READ); -++ } -++} -++ -++/* Prepare DMA to start data transfer from the MMC card */ -++static void jz_mmc_tx_setup_data(struct jz_mmc_host *host, -++ struct mmc_data *data) -++{ -++ unsigned int nob = data->blocks; -++ int channeltx = txdmachan; -++ int i; -++ u32 size; -++ -++ if (data->flags & MMC_DATA_STREAM) -++ nob = 0xffff; -++ -++ REG_MSC_NOB(MSC_ID) = nob; -++ REG_MSC_BLKLEN(MSC_ID) = data->blksz; -++ size = nob * data->blksz; -++ -++ if (data->flags & MMC_DATA_READ) { -++ host->dma.dir = DMA_FROM_DEVICE; -++ } else { -++ host->dma.dir = DMA_TO_DEVICE; -++ } -++ -++ host->dma.len = -++ dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, -++ host->dma.dir); -++ -++ for (i = 0; i < host->dma.len; i++) { -++ host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]); -++ host->sg_cpu[i].dcmd = sg_dma_len(&data->sg[i]); -++ dma_cache_wback_inv((unsigned long) -++ CKSEG0ADDR(sg_dma_address(data->sg)) + -++ data->sg->offset, -++ host->sg_cpu[i].dcmd); -++ jz_mmc_start_dma(channeltx, host->sg_cpu[i].dtadr, -++ host->sg_cpu[i].dcmd, DMA_MODE_WRITE); -++ } -++} -++#else -++static void jz_mmc_receive_pio(struct jz_mmc_host *host) -++{ -++ -++ struct mmc_data *data = 0; -++ int sg_len = 0, max = 0, count = 0; -++ u32 *buf = 0; -++ struct scatterlist *sg; -++ unsigned int nob; -++ -++ data = host->mrq->data; -++ nob = data->blocks; -++ REG_MSC_NOB(MSC_ID) = nob; -++ REG_MSC_BLKLEN(MSC_ID) = data->blksz; -++ -++ max = host->pio.len; -++ if (host->pio.index < host->dma.len) { -++ sg = &data->sg[host->pio.index]; -++ buf = sg_virt(sg) + host->pio.offset; -++ -++ /* This is the space left inside the buffer */ -++ sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset; -++ /* Check to if we need less then the size of the sg_buffer */ -++ if (sg_len < max) max = sg_len; -++ } -++ max = max / 4; -++ for(count = 0; count < max; count++) { -++ while (REG_MSC_STAT(MSC_ID) & MSC_STAT_DATA_FIFO_EMPTY) -++ ; -++ *buf++ = REG_MSC_RXFIFO(MSC_ID); -++ } -++ host->pio.len -= count; -++ host->pio.offset += count; -++ -++ if (sg_len && count == sg_len) { -++ host->pio.index++; -++ host->pio.offset = 0; -++ } -++} -++ -++static void jz_mmc_send_pio(struct jz_mmc_host *host) -++{ -++ -++ struct mmc_data *data = 0; -++ int sg_len, max, count = 0; -++ u32 *wbuf = 0; -++ struct scatterlist *sg; -++ unsigned int nob; -++ -++ data = host->mrq->data; -++ nob = data->blocks; -++ -++ REG_MSC_NOB(MSC_ID) = nob; -++ REG_MSC_BLKLEN(MSC_ID) = data->blksz; -++ -++ /* This is the pointer to the data buffer */ -++ sg = &data->sg[host->pio.index]; -++ wbuf = sg_virt(sg) + host->pio.offset; -++ -++ /* This is the space left inside the buffer */ -++ sg_len = data->sg[host->pio.index].length - host->pio.offset; -++ -++ /* Check to if we need less then the size of the sg_buffer */ -++ max = (sg_len > host->pio.len) ? host->pio.len : sg_len; -++ max = max / 4; -++ for(count = 0; count < max; count++ ) { -++ while (REG_MSC_STAT(MSC_ID) & MSC_STAT_DATA_FIFO_FULL) -++ ; -++ REG_MSC_TXFIFO(MSC_ID) = *wbuf++; -++ } -++ -++ host->pio.len -= count; -++ host->pio.offset += count; -++ -++ if (count == sg_len) { -++ host->pio.index++; -++ host->pio.offset = 0; -++ } -++} -++ -++static int -++jz_mmc_prepare_data(struct jz_mmc_host *host, struct mmc_data *data) -++{ -++ int datalen = data->blocks * data->blksz; -++ -++ host->dma.dir = DMA_BIDIRECTIONAL; -++ host->dma.len = dma_map_sg(mmc_dev(host->mmc), data->sg, -++ data->sg_len, host->dma.dir); -++ if (host->dma.len == 0) -++ return -ETIMEDOUT; -++ -++ host->pio.index = 0; -++ host->pio.offset = 0; -++ host->pio.len = datalen; -++ return 0; -++} -++#endif -++ -++static int jz_mmc_cmd_done(struct jz_mmc_host *host, unsigned int stat); -++ -++static void jz_mmc_finish_request(struct jz_mmc_host *host, struct mmc_request *mrq) -++{ -++ host->mrq = NULL; -++ host->cmd = NULL; -++ host->data = NULL; -++ mmc_request_done(host->mmc, mrq); -++} -++ -++static void jz_mmc_start_cmd(struct jz_mmc_host *host, -++ struct mmc_command *cmd, unsigned int cmdat) -++{ -++ u32 timeout = 0x3fffff; -++ unsigned int stat; -++ struct jz_mmc_host *hst = host; -++ WARN_ON(host->cmd != NULL); -++ host->cmd = cmd; -++ -++ /* mask interrupts */ -++ REG_MSC_IMASK(MSC_ID) = 0xffff; -++ -++ /* clear status */ -++ REG_MSC_IREG(MSC_ID) = 0xffff; -++ -++ if (cmd->flags & MMC_RSP_BUSY) -++ cmdat |= MSC_CMDAT_BUSY; -++ -++#define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE)) -++ switch (RSP_TYPE(mmc_resp_type(cmd))) { -++ case RSP_TYPE(MMC_RSP_R1): /* r1,r1b, r6, r7 */ -++ cmdat |= MSC_CMDAT_RESPONSE_R1; -++ r_type = 1; -++ break; -++ case RSP_TYPE(MMC_RSP_R3): -++ cmdat |= MSC_CMDAT_RESPONSE_R3; -++ r_type = 1; -++ break; -++ case RSP_TYPE(MMC_RSP_R2): -++ cmdat |= MSC_CMDAT_RESPONSE_R2; -++ r_type = 2; -++ break; -++ default: -++ break; -++ } -++ -++ REG_MSC_CMD(MSC_ID) = cmd->opcode; -++ -++ /* Set argument */ -++#ifdef CONFIG_MSC0_JZ4750 -++#ifdef CONFIG_JZ4750_MSC0_BUS_1 -++ if (cmd->opcode == 6) { -++ /* set 1 bit sd card bus*/ -++ if (cmd->arg ==2) -++ REG_MSC_ARG(MSC_ID) = 0; -++ -++ /* set 1 bit mmc card bus*/ -++ if (cmd->arg == 0x3b70101) { -++ REG_MSC_ARG(MSC_ID) = 0x3b70001; -++ } -++ } else -++ REG_MSC_ARG(MSC_ID) = cmd->arg; -++ -++#elif defined CONFIG_JZ4750_MSC0_BUS_8 -++ if (cmd->opcode == 6) { -++ /* set 8 bit mmc card bus*/ -++ if (cmd->arg == 0x3b70101) -++ REG_MSC_ARG(MSC_ID) = 0x3b70201; -++ else -++ REG_MSC_ARG(MSC_ID) = cmd->arg; -++ -++ } else -++ REG_MSC_ARG(MSC_ID) = cmd->arg; -++#else -++ REG_MSC_ARG(MSC_ID) = cmd->arg; -++#endif /* CONFIG_JZ4750_MSC0_BUS_1 */ -++#else -++#ifdef CONFIG_JZ4750_MSC1_BUS_1 -++ if (cmd->opcode == 6) { -++ /* set 1 bit sd card bus*/ -++ if (cmd->arg ==2) -++ REG_MSC_ARG(MSC_ID) = 0; -++ -++ /* set 1 bit mmc card bus*/ -++ if (cmd->arg == 0x3b70101) { -++ REG_MSC_ARG(MSC_ID) = 0x3b70001; -++ } -++ } else -++ REG_MSC_ARG(MSC_ID) = cmd->arg; -++ -++#else -++ REG_MSC_ARG(MSC_ID) = cmd->arg; -++#endif /* CONFIG_JZ4750_MSC1_BUS_1 */ -++#endif /* CONFIG_MSC0_JZ4750*/ -++ -++ /* Set command */ -++ REG_MSC_CMDAT(MSC_ID) = cmdat; -++ -++ /* Send command */ -++ jz_mmc_start_op(); -++ -++ while (timeout-- && !(REG_MSC_STAT(MSC_ID) & MSC_STAT_END_CMD_RES)) -++ ; -++ -++ REG_MSC_IREG(MSC_ID) = MSC_IREG_END_CMD_RES; /* clear irq flag */ -++ if (cmd->opcode == 12) { -++ while (timeout-- && !(REG_MSC_IREG(MSC_ID) & MSC_IREG_PRG_DONE)) -++ ; -++ REG_MSC_IREG(MSC_ID) = MSC_IREG_PRG_DONE; /* clear status */ -++ } -++ if (!mmc_slot_enable) { -++ /* It seems that MSC can't report the MSC_STAT_TIME_OUT_RES when -++ * card was removed. We force to return here. -++ */ -++ cmd->error = -ETIMEDOUT; -++ jz_mmc_finish_request(hst, hst->mrq); -++ return; -++ } -++ -++ if (SD_IO_SEND_OP_COND == cmd->opcode) { -++ /* -++ * Don't support SDIO card currently. -++ */ -++ cmd->error = -ETIMEDOUT; -++ jz_mmc_finish_request(hst, hst->mrq); -++ return; -++ } -++ -++ /* Check for status */ -++ stat = REG_MSC_STAT(MSC_ID); -++ jz_mmc_cmd_done(hst, stat); -++ if (host->data) { -++ if (cmd->opcode == MMC_WRITE_BLOCK || cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) -++#ifdef USE_DMA -++ jz_mmc_tx_setup_data(host, host->data); -++#else -++ jz_mmc_send_pio(host); -++ else -++ jz_mmc_receive_pio(host); -++#endif -++ } -++} -++ -++static int jz_mmc_cmd_done(struct jz_mmc_host *host, unsigned int stat) -++{ -++ struct mmc_command *cmd = host->cmd; -++ int i, temp[16]; -++ u8 *buf; -++ u32 data, v, w1, w2; -++ -++ if (!cmd) -++ return 0; -++ -++ host->cmd = NULL; -++ buf = (u8 *) temp; -++ switch (r_type) { -++ case 1: -++ { -++ data = REG_MSC_RES(MSC_ID); -++ buf[0] = (data >> 8) & 0xff; -++ buf[1] = data & 0xff; -++ data = REG_MSC_RES(MSC_ID); -++ buf[2] = (data >> 8) & 0xff; -++ buf[3] = data & 0xff; -++ data = REG_MSC_RES(MSC_ID); -++ buf[4] = data & 0xff; -++ cmd->resp[0] = -++ buf[1] << 24 | buf[2] << 16 | buf[3] << 8 | -++ buf[4]; -++ break; -++ } -++ case 2: -++ { -++ data = REG_MSC_RES(MSC_ID); -++ v = data & 0xffff; -++ for (i = 0; i < 4; i++) { -++ data = REG_MSC_RES(MSC_ID); -++ w1 = data & 0xffff; -++ data = REG_MSC_RES(MSC_ID); -++ w2 = data & 0xffff; -++ cmd->resp[i] = v << 24 | w1 << 8 | w2 >> 8; -++ v = w2; -++ } -++ break; -++ } -++ case 0: -++ break; -++ } -++ if (stat & MSC_STAT_TIME_OUT_RES) { -++ printk("MSC_STAT_TIME_OUT_RES\n"); -++ cmd->error = -ETIMEDOUT; -++ } else if (stat & MSC_STAT_CRC_RES_ERR && cmd->flags & MMC_RSP_CRC) { -++ printk("MSC_STAT_CRC\n"); -++ if (cmd->opcode == MMC_ALL_SEND_CID || -++ cmd->opcode == MMC_SEND_CSD || -++ cmd->opcode == MMC_SEND_CID) { -++ /* a bogus CRC error can appear if the msb of -++ the 15 byte response is a one */ -++ if ((cmd->resp[0] & 0x80000000) == 0) -++ cmd->error = -EILSEQ; -++ } -++ } -++ /* -++ * Did I mention this is Sick. We always need to -++ * discard the upper 8 bits of the first 16-bit word. -++ */ -++ if (host->data && cmd->error == 0) -++ jz_mmc_enable_irq(host, MSC_IMASK_DATA_TRAN_DONE); -++ else -++ jz_mmc_finish_request(host, host->mrq); -++ -++ return 1; -++} -++ -++static int jz_mmc_data_done(struct jz_mmc_host *host, unsigned int stat) -++{ -++ struct mmc_data *data = host->data; -++ -++ if (!data) -++ return 0; -++ REG_MSC_IREG(MSC_ID) = MSC_IREG_DATA_TRAN_DONE; /* clear status */ -++ dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, -++ host->dma_dir); -++ if (stat & MSC_STAT_TIME_OUT_READ) { -++ printk("MMC/SD timeout, MMC_STAT 0x%x\n", stat); -++ data->error = -ETIMEDOUT; -++ } else if (REG_MSC_STAT(MSC_ID) & -++ (MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR)) { -++ printk("MMC/SD CRC error, MMC_STAT 0x%x\n", stat); -++ data->error = -EILSEQ; -++ } -++ /* -++ * There appears to be a hardware design bug here. There seems to -++ * be no way to find out how much data was transferred to the card. -++ * This means that if there was an error on any block, we mark all -++ * data blocks as being in error. -++ */ -++ if (data->error == 0) -++ data->bytes_xfered = data->blocks * data->blksz; -++ else -++ data->bytes_xfered = 0; -++ -++ jz_mmc_disable_irq(host, MSC_IMASK_DATA_TRAN_DONE); -++ host->data = NULL; -++ if (host->mrq->stop) { -++ jz_mmc_start_cmd(host, host->mrq->stop, 0); -++ } else { -++ jz_mmc_finish_request(host, host->mrq); -++ } -++ return 1; -++} -++ -++static void jz_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) -++{ -++ struct jz_mmc_host *host = mmc_priv(mmc); -++ unsigned int cmdat; -++ -++ /* Save current request for the future processing */ -++ host->mrq = mrq; -++ host->data = mrq->data; -++ cmdat = host->cmdat; -++ host->cmdat &= ~MSC_CMDAT_INIT; -++ -++ if (mrq->data) { -++ cmdat &= ~MSC_CMDAT_BUSY; -++#ifdef USE_DMA -++ if ((mrq->cmd->opcode == 51) | (mrq->cmd->opcode == 8) | (mrq->cmd->opcode == 6)) -++ -++ cmdat |= -++ MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN | -++ MSC_CMDAT_DMA_EN; -++ else { -++#ifdef CONFIG_MSC0_JZ4750 -++#ifdef CONFIG_JZ4750_MSC0_BUS_1 -++ cmdat &= ~MSC_CMDAT_BUS_WIDTH_MASK; -++ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN | -++ MSC_CMDAT_DMA_EN; -++#elif defined CONFIG_JZ4750_MSC0_BUS_4 -++ if(auto_select_bus == MSC_1BIT_BUS) { -++ cmdat &= ~MSC_CMDAT_BUS_WIDTH_MASK; -++ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN | -++ MSC_CMDAT_DMA_EN; -++ } else { -++ cmdat &= ~MSC_CMDAT_BUS_WIDTH_MASK; -++ cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT | MSC_CMDAT_DATA_EN | -++ MSC_CMDAT_DMA_EN; -++ } -++#else -++ cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_DMA_EN; -++#endif /* CONFIG_JZ4750_MSC0_BUS_1 */ -++#else -++#ifdef CONFIG_JZ4750_MSC1_BUS_1 -++ cmdat &= ~MSC_CMDAT_BUS_WIDTH_MASK; -++ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN | -++ MSC_CMDAT_DMA_EN; -++#else -++ cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_DMA_EN; -++#endif /* CONFIG_JZ4750_MSC1_BUS_1 */ -++#endif /* CONFIG_MSC0_JZ4750 */ -++ } -++ if (mrq->data->flags & MMC_DATA_WRITE) -++ cmdat |= MSC_CMDAT_WRITE; -++ -++ if (mrq->data->flags & MMC_DATA_STREAM) -++ cmdat |= MSC_CMDAT_STREAM_BLOCK; -++ if (mrq->cmd->opcode != MMC_WRITE_BLOCK -++ && mrq->cmd->opcode != MMC_WRITE_MULTIPLE_BLOCK) -++ jz_mmc_rx_setup_data(host, mrq->data); -++#else /*USE_DMA*/ -++ -++ if ((mrq->cmd->opcode == 51) | (mrq->cmd->opcode == 8) | (mrq->cmd->opcode == 6)) -++ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN; -++ else { -++#ifdef CONFIG_MSC0_JZ4750 -++#ifdef CONFIG_JZ4750_MSC0_BUS_1 -++ cmdat &= ~MSC_CMDAT_BUS_WIDTH_MASK; -++ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN; -++#elif defined CONFIG_JZ4750_MSC0_BUS_4 -++ if(auto_select_bus == MSC_1BIT_BUS) { -++ cmdat &= ~MSC_CMDAT_BUS_WIDTH_MASK; -++ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN; -++ } else { -++ cmdat &= ~MSC_CMDAT_BUS_WIDTH_MASK; -++ cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT | MSC_CMDAT_DATA_EN; -++ } -++#else -++ cmdat |= MSC_CMDAT_DATA_EN; -++#endif -++#else -++#ifdef CONFIG_JZ4750_MSC1_BUS_1 -++ cmdat &= ~MSC_CMDAT_BUS_WIDTH_MASK; -++ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN; -++#else -++ cmdat |= MSC_CMDAT_DATA_EN; -++#endif /* CONFIG_JZ4750_MSC1_BUS_1 */ -++#endif /* CONFIG_MSC0_JZ4750 */ -++ } -++ if (mrq->data->flags & MMC_DATA_WRITE) -++ cmdat |= MSC_CMDAT_WRITE; -++ -++ if (mrq->data->flags & MMC_DATA_STREAM) -++ cmdat |= MSC_CMDAT_STREAM_BLOCK; -++ jz_mmc_prepare_data(host, host->data); -++#endif /*USE_DMA*/ -++ } -++ jz_mmc_start_cmd(host, mrq->cmd, cmdat); -++} -++ -++static irqreturn_t jz_mmc_irq(int irq, void *devid) -++{ -++ struct jz_mmc_host *host = devid; -++ unsigned int ireg; -++ int handled = 0; -++ -++ ireg = REG_MSC_IREG(MSC_ID); -++ -++ if (ireg) { -++ unsigned stat = REG_MSC_STAT(MSC_ID); -++ if (ireg & MSC_IREG_DATA_TRAN_DONE) -++ handled |= jz_mmc_data_done(host, stat); -++ } -++ return IRQ_RETVAL(handled); -++} -++ -++/* Returns true if MMC slot is empty */ -++static int jz_mmc_slot_is_empty(int slot) -++{ -++ int empty; -++ -++#ifdef CONFIG_FPGA -++ return 0; -++#endif -++ -++#ifdef CONFIG_MSC1_JZ4750 -++ empty = (__msc1_card_detected(slot) == 0) ? 1 : 0; -++#else -++ empty = (__msc0_card_detected(slot) == 0) ? 1 : 0; -++ -++#endif -++ if (empty) { -++ /* wait for card insertion */ -++#ifdef CONFIG_MSC1_JZ4750 -++ __gpio_as_irq_rise_edge(MSC_HOTPLUG_PIN); -++#else -++ __gpio_as_irq_fall_edge(MSC_HOTPLUG_PIN); -++#endif -++ } else { -++ /* wait for card removal */ -++#ifdef CONFIG_MSC1_JZ4750 -++ __gpio_as_irq_fall_edge(MSC_HOTPLUG_PIN); -++#else -++ __gpio_as_irq_rise_edge(MSC_HOTPLUG_PIN); -++#endif -++ } -++ -++ return empty; -++} -++ -++static irqreturn_t jz_mmc_detect_irq(int irq, void *devid) -++{ -++ struct jz_mmc_host *host = (struct jz_mmc_host *) devid; -++ -++ auto_select_bus = MSC_4BIT_BUS; -++ if (jz_mmc_slot_is_empty(0)) { -++ mmc_slot_enable = 0; -++ mmc_detect_change(host->mmc, 50); -++ } else { -++ mmc_slot_enable = 1; -++ mmc_detect_change(host->mmc, 50); -++ } -++ return IRQ_HANDLED; -++} -++ -++static int jz_mmc_get_ro(struct mmc_host *mmc) -++{ -++ struct jz_mmc_host *host = mmc_priv(mmc); -++ -++ if (host->pdata && host->pdata->get_ro) -++ return host->pdata->get_ro(mmc_dev(mmc)); -++ /* Host doesn't support read only detection so assume writeable */ -++ return 0; -++} -++ -++/* set clock and power */ -++static void jz_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -++{ -++ struct jz_mmc_host *host = mmc_priv(mmc); -++ -++ if (ios->clock) -++ jz_mmc_set_clock(ios->clock); -++ -++ if (host->power_mode != ios->power_mode) { -++ host->power_mode = ios->power_mode; -++ -++ if (ios->power_mode == MMC_POWER_ON) -++ host->cmdat |= CMDAT_INIT; -++ } -++ -++ if (ios->bus_width == MMC_BUS_WIDTH_4) { -++ auto_select_bus = MSC_4BIT_BUS; -++ host->cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT; -++ } -++ else if (ios->bus_width == MMC_BUS_WIDTH_8) { -++ host->cmdat |= MSC_CMDAT_BUS_WIDTH_8BIT; -++ auto_select_bus = MSC_8BIT_BUS; -++ } else { -++ /* 1 bit bus*/ -++ host->cmdat &= ~MSC_CMDAT_BUS_WIDTH_8BIT; -++ auto_select_bus = MSC_1BIT_BUS; -++ } -++} -++ -++static const struct mmc_host_ops jz_mmc_ops = { -++ .request = jz_mmc_request, -++ .get_ro = jz_mmc_get_ro, -++ .set_ios = jz_mmc_set_ios, -++}; -++static int jz_mmc_pm_callback(struct pm_dev *pm_dev, -++ pm_request_t req, void *data); -++ -++static int jz_mmc_probe(struct platform_device *pdev) -++{ -++ int retval; -++ struct mmc_host *mmc; -++ struct jz_mmc_host *host = NULL; -++ int irq; -++ struct resource *r; -++ -++#ifdef CONFIG_MSC0_JZ4750 -++#ifdef CONFIG_SOC_JZ4750 -++ __gpio_as_msc0_8bit(); // for jz4750 -++#else -++ __gpio_as_msc0_4bit(); // for jz4750d -++#endif -++ __msc0_init_io(); -++ __msc0_enable_power(); -++#else -++ __gpio_as_msc1_4bit(); -++ __msc1_init_io(); -++ __msc1_enable_power(); -++#endif -++ __msc_reset(MSC_ID); -++ REG_MSC_LPM(MSC_ID) = 0x1; -++ -++ MMC_IRQ_MASK(); -++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -++ irq = platform_get_irq(pdev, 0); -++ if (!r || irq < 0) -++ return -ENXIO; -++ -++ r = request_mem_region(r->start, SZ_4K, DRIVER_NAME); -++ if (!r) -++ return -EBUSY; -++ -++ mmc = mmc_alloc_host(sizeof(struct jz_mmc_host), &pdev->dev); -++ if (!mmc) { -++ retval = -ENOMEM; -++ goto out; -++ } -++ mmc->ops = &jz_mmc_ops; -++ mmc->f_min = MMC_CLOCK_SLOW; -++ mmc->f_max = SD_CLOCK_HIGH; -++ /* -++ * We can do SG-DMA, but we don't because we never know how much -++ * data we successfully wrote to the card. -++ */ -++ mmc->max_phys_segs = NR_SG; -++ -++ mmc->max_seg_size = PAGE_SIZE * 16; -++ mmc->max_req_size = mmc->max_seg_size; -++ mmc->max_blk_size = 4095; -++ /* -++ * Block count register is 16 bits. -++ */ -++ mmc->max_blk_count = 65535; -++ host = mmc_priv(mmc); -++ host->mmc = mmc; -++ host->pdata = pdev->dev.platform_data; -++ mmc->ocr_avail = host->pdata ? -++ host->pdata->ocr_mask : MMC_VDD_32_33 | MMC_VDD_33_34; -++ host->mmc->caps = -++ MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_SD_HIGHSPEED -++ | MMC_CAP_MMC_HIGHSPEED; -++ /* -++ *MMC_CAP_4_BIT_DATA (1 << 0) The host can do 4 bit transfers -++ * -++ */ -++ host->sg_cpu = -++ dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &host->sg_dma, -++ GFP_KERNEL); -++ if (!host->sg_cpu) { -++ retval = -ENOMEM; -++ goto out; -++ } -++ spin_lock_init(&host->lock); -++ host->irq = IRQ_MSC; /* is it useful ?*/ -++ host->imask = 0xffff; -++ /* -++ * Ensure that the host controller is shut down, and setup -++ * with our defaults. -++ */ -++ retval = request_irq(IRQ_MSC, jz_mmc_irq, 0, "MMC/SD", host); -++ if (retval) { -++ printk(KERN_ERR "MMC/SD: can't request MMC/SD IRQ\n"); -++ return retval; -++ } -++ -++ jz_mmc_slot_is_empty(0); -++ /* Request card detect interrupt */ -++ -++ retval = request_irq(MSC_HOTPLUG_IRQ, jz_mmc_detect_irq, 0, //SA_INTERRUPT, -++ "MMC card detect", host); -++ if (retval) { -++ printk(KERN_ERR "MMC/SD: can't request card detect IRQ\n"); -++ goto err1; -++ } -++#ifdef USE_DMA -++ /* Request MMC Rx DMA channel */ -++ rxdmachan = -++ jz_request_dma(DMA_ID_MSC_RX, "MMC Rx", jz_mmc_dma_rx_callback, -++ 0, host); -++ if (rxdmachan < 0) { -++ printk(KERN_ERR "jz_request_dma failed for MMC Rx\n"); -++ goto err2; -++ } -++ -++ if (rxdmachan < HALF_DMA_NUM) -++ REG_DMAC_DMACR(0) |= DMAC_DMACR_FMSC; -++ else -++ REG_DMAC_DMACR(1) |= DMAC_DMACR_FMSC; -++ -++ /* Request MMC Tx DMA channel */ -++ txdmachan = -++ jz_request_dma(DMA_ID_MSC_TX, "MMC Tx", jz_mmc_dma_tx_callback, -++ 0, host); -++ if (txdmachan < 0) { -++ printk(KERN_ERR "jz_request_dma failed for MMC Tx\n"); -++ goto err3; -++ } -++ -++ if (txdmachan < HALF_DMA_NUM) -++ REG_DMAC_DMACR(0) |= DMAC_DMACR_FMSC; -++ else -++ REG_DMAC_DMACR(1) |= DMAC_DMACR_FMSC; -++ -++#endif -++ platform_set_drvdata(pdev, mmc); -++ mmc_add_host(mmc); -++#ifdef CONFIG_PM -++ /* Register MMC slot as as power-managed device */ -++ pm_register(PM_UNKNOWN_DEV, PM_SYS_UNKNOWN, jz_mmc_pm_callback); -++#endif -++ printk("JZ SD/MMC card driver registered\n"); -++ -++ /* Detect card during initialization */ -++#if defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D) -++ if (!jz_mmc_slot_is_empty(0)) { -++ mmc_slot_enable = 1; -++ mmc_detect_change(host->mmc, 0); -++ } -++#endif -++ return 0; -++ -++err1:free_irq(IRQ_MSC, &host); -++#ifdef USE_DMA -++ err2:jz_free_dma(rxdmachan); -++ err3:jz_free_dma(txdmachan); -++#endif -++out: -++ if (host) { -++ if (host->sg_cpu) -++ dma_free_coherent(&pdev->dev, PAGE_SIZE, -++ host->sg_cpu, host->sg_dma); -++ } -++ if (mmc) -++ mmc_free_host(mmc); -++ return -1; -++} -++ -++static int jz_mmc_remove(struct platform_device *pdev) -++{ -++ struct mmc_host *mmc = platform_get_drvdata(pdev); -++ long flags; -++ -++ platform_set_drvdata(pdev, NULL); -++ -++ if (mmc) { -++ struct jz_mmc_host *host = mmc_priv(mmc); -++ -++ if (host->pdata && host->pdata->exit) -++ host->pdata->exit(&pdev->dev, mmc); -++ -++ mmc_remove_host(mmc); -++ -++ local_irq_save(flags); -++ __msc0_disable_power(); -++ jz_free_dma(rxdmachan); -++ jz_free_dma(txdmachan); -++ free_irq(IRQ_MSC, host); -++ local_irq_restore(flags); -++ mmc_free_host(mmc); -++ } -++ return 0; -++} -++ -++#ifdef CONFIG_PM -++pm_message_t state; -++static int jz_mmc_suspend(struct platform_device *dev, pm_message_t state) -++{ -++ struct mmc_host *mmc = platform_get_drvdata(dev); -++ int ret = 0; -++ -++ if (mmc) -++ ret = mmc_suspend_host(mmc, state); -++ -++ return ret; -++} -++ -++static int jz_mmc_resume(struct platform_device *dev) -++{ -++ struct mmc_host *mmc = platform_get_drvdata(dev); -++ int ret = 0; -++ -++ if (mmc) -++ ret = mmc_resume_host(mmc); -++ -++ return ret; -++} -++static int jz_mmc_pm_callback(struct pm_dev *pm_dev, -++ pm_request_t req, void *data) -++{ -++ struct platform_device *pdev = (struct platform_device *)pm_dev; -++ -++ switch(req) { -++ case PM_RESUME: -++ jz_mmc_resume(pdev); -++ break; -++ case PM_SUSPEND: -++ /* state has no use */ -++ jz_mmc_suspend(pdev,state); -++ break; -++ default: -++ printk("MMC/SD: invalid PM request %d\n", req); -++ break; -++ } -++ return 0; -++} -++#else -++#define jz_mmc_suspend NULL -++#define jz_mmc_resume NULL -++#endif -++ -++static struct platform_driver jz_mmc_driver = { -++ .probe = jz_mmc_probe, -++ .remove = jz_mmc_remove, -++ .suspend = jz_mmc_suspend, -++ .resume = jz_mmc_resume, -++ .driver = { -++ .name = DRIVER_NAME, -++ }, -++}; -++ -++static int __init jz_mmc_init(void) -++{ -++ return platform_driver_register(&jz_mmc_driver); -++} -++ -++static void __exit jz_mmc_exit(void) -++{ -++ platform_driver_unregister(&jz_mmc_driver); -++} -++ -++module_init(jz_mmc_init); -++module_exit(jz_mmc_exit); -++ -++MODULE_DESCRIPTION("JZ47XX SD/Multimedia Card Interface Driver"); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/drivers/mmc/host/jz4750_mmc.h linux-2.6.24.7/drivers/mmc/host/jz4750_mmc.h -+--- linux-2.6.24.7.old/drivers/mmc/host/jz4750_mmc.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mmc/host/jz4750_mmc.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,88 @@ -++#ifndef __JZ4750_MMC_H__ -++#define __JZ4750_MMC_H__ -++ -++#define MMC_CLOCK_SLOW 400000 /* 400 kHz for initial setup */ -++#define MMC_CLOCK_FAST 20000000 /* 20 MHz for maximum for normal operation */ -++#define SD_CLOCK_FAST 24000000 /* 24 MHz for SD Cards */ -++#define SD_CLOCK_HIGH 24000000 /* 24 MHz for SD Cards */ -++#define MMC_NO_ERROR 0 -++ -++#define NR_SG 1 -++ -++#ifdef CONFIG_MSC0_JZ4750 -++#define MSC_ID 0 -++#define MSC_HOTPLUG_IRQ MSC0_HOTPLUG_IRQ -++#define IRQ_MSC IRQ_MSC0 -++#define DMA_ID_MSC_RX DMA_ID_MSC0_RX -++#define DMA_ID_MSC_TX DMA_ID_MSC0_TX -++#define MSC_HOTPLUG_PIN MSC0_HOTPLUG_PIN -++#else -++#define MSC_ID 1 -++#define MSC_HOTPLUG_IRQ MSC1_HOTPLUG_IRQ -++#define IRQ_MSC IRQ_MSC1 -++#define DMA_ID_MSC_RX DMA_ID_MSC1_RX -++#define DMA_ID_MSC_TX DMA_ID_MSC1_TX -++#define MSC_HOTPLUG_PIN MSC1_HOTPLUG_PIN -++#endif -++ -++#define MSC_1BIT_BUS 0 -++#define MSC_4BIT_BUS 1 -++#define MSC_8BIT_BUS 2 -++ -++#define SZ_4K 0x00001000 -++ -++struct jz_mmc_host { -++ struct mmc_host *mmc; -++ spinlock_t lock; -++ struct { -++ int len; -++ int dir; -++ } dma; -++ struct { -++ int index; -++ int offset; -++ int len; -++ } pio; -++ int irq; -++ unsigned int clkrt; -++ unsigned int cmdat; -++ unsigned int imask; -++ unsigned int power_mode; -++ struct jz_mmc_platform_data *pdata; -++ struct mmc_request *mrq; -++ struct mmc_command *cmd; -++ struct mmc_data *data; -++ dma_addr_t sg_dma; -++ struct jzsoc_dma_desc *sg_cpu; -++ unsigned int dma_len; -++ unsigned int dma_dir; -++}; -++ -++#define MMC_IRQ_MASK() \ -++do { \ -++ REG_MSC_IMASK(MSC_ID) = 0xffff; \ -++ REG_MSC_IREG(MSC_ID) = 0xffff; \ -++} while (0) -++ -++typedef struct jzsoc_dma_desc { -++ volatile u32 ddadr; /* Points to the next descriptor + flags */ -++ volatile u32 dsadr; /* DSADR value for the current transfer */ -++ volatile u32 dtadr; /* DTADR value for the current transfer */ -++ volatile u32 dcmd; /* DCMD value for the current transfer */ -++} jzsoc_dma_desc; -++ -++#include -++ -++struct device; -++struct mmc_host; -++ -++struct jz_mmc_platform_data { -++ unsigned int ocr_mask; /* available voltages */ -++ unsigned long detect_delay; /* delay in jiffies before detecting cards after interrupt */ -++ int (*init)(struct device *, irq_handler_t , void *); -++ int (*get_ro)(struct device *); -++ void (*setpower)(struct device *, unsigned int); -++ void (*exit)(struct device *, void *); -++}; -++ -++#endif /* __JZ4750_MMC_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mmc/host/jz_mmc.c linux-2.6.24.7/drivers/mmc/host/jz_mmc.c -+--- linux-2.6.24.7.old/drivers/mmc/host/jz_mmc.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mmc/host/jz_mmc.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1026 @@ -++/* -++ * linux/drivers/mmc/jz_mmc.c - JZ SD/MMC driver -++ * -++ * Copyright (C) 2005 - 2008 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include "jz_mmc.h" -++ -++#define DRIVER_NAME "jz-mmc" -++ -++#define NR_SG 1 -++ -++#if defined(CONFIG_SOC_JZ4725) || defined(CONFIG_SOC_JZ4720) -++#undef USE_DMA -++#else -++#define USE_DMA -++#endif -++ -++struct jz_mmc_host { -++ struct mmc_host *mmc; -++ spinlock_t lock; -++ struct { -++ int len; -++ int dir; -++ } dma; -++ struct { -++ int index; -++ int offset; -++ int len; -++ } pio; -++ int irq; -++ unsigned int clkrt; -++ unsigned int cmdat; -++ unsigned int imask; -++ unsigned int power_mode; -++ struct jz_mmc_platform_data *pdata; -++ struct mmc_request *mrq; -++ struct mmc_command *cmd; -++ struct mmc_data *data; -++ dma_addr_t sg_dma; -++ struct jzsoc_dma_desc *sg_cpu; -++ unsigned int dma_len; -++ unsigned int dma_dir; -++ struct pm_dev *pmdev; -++}; -++ -++static int r_type = 0; -++ -++#define MMC_IRQ_MASK() \ -++do { \ -++ REG_MSC_IMASK = 0xff; \ -++ REG_MSC_IREG = 0xff; \ -++} while (0) -++ -++static int rxdmachan = 0; -++static int txdmachan = 0; -++static int mmc_slot_enable = 0; -++ -++/* Stop the MMC clock and wait while it happens */ -++static inline int jz_mmc_stop_clock(void) -++{ -++ int timeout = 1000; -++ -++ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP; -++ while (timeout && (REG_MSC_STAT & MSC_STAT_CLK_EN)) { -++ timeout--; -++ if (timeout == 0) -++ return 0; -++ udelay(1); -++ } -++ return MMC_NO_ERROR; -++} -++ -++/* Start the MMC clock and operation */ -++static inline int jz_mmc_start_clock(void) -++{ -++ REG_MSC_STRPCL = -++ MSC_STRPCL_CLOCK_CONTROL_START | MSC_STRPCL_START_OP; -++ return MMC_NO_ERROR; -++} -++ -++static inline u32 jz_mmc_calc_clkrt(int is_sd, u32 rate) -++{ -++ u32 clkrt; -++ u32 clk_src = is_sd ? 24000000 : 20000000; -++ -++ clkrt = 0; -++ while (rate < clk_src) { -++ clkrt++; -++ clk_src >>= 1; -++ } -++ return clkrt; -++} -++ -++/* Select the MMC clock frequency */ -++static int jz_mmc_set_clock(u32 rate) -++{ -++ int clkrt; -++ -++ jz_mmc_stop_clock(); -++ __cpm_select_msc_clk(1); /* select clock source from CPM */ -++ clkrt = jz_mmc_calc_clkrt(1, rate); -++ REG_MSC_CLKRT = clkrt; -++ return MMC_NO_ERROR; -++} -++ -++static void jz_mmc_enable_irq(struct jz_mmc_host *host, unsigned int mask) -++{ -++ unsigned long flags; -++ spin_lock_irqsave(&host->lock, flags); -++ host->imask &= ~mask; -++ REG_MSC_IMASK = host->imask; -++ spin_unlock_irqrestore(&host->lock, flags); -++} -++ -++static void jz_mmc_disable_irq(struct jz_mmc_host *host, unsigned int mask) -++{ -++ unsigned long flags; -++ -++ spin_lock_irqsave(&host->lock, flags); -++ host->imask |= mask; -++ REG_MSC_IMASK = host->imask; -++ spin_unlock_irqrestore(&host->lock, flags); -++} -++ -++void jz_set_dma_block_size(int dmanr, int nbyte); -++ -++#ifdef USE_DMA -++static inline void -++jz_mmc_start_dma(int chan, unsigned long phyaddr, int count, int mode) -++{ -++ unsigned long flags; -++ -++ flags = claim_dma_lock(); -++ disable_dma(chan); -++ clear_dma_ff(chan); -++ jz_set_dma_block_size(chan, 32); -++ set_dma_mode(chan, mode); -++ set_dma_addr(chan, phyaddr); -++ set_dma_count(chan, count + 31); -++ enable_dma(chan); -++ release_dma_lock(flags); -++} -++ -++static irqreturn_t jz_mmc_dma_rx_callback(int irq, void *devid) -++{ -++ int chan = rxdmachan; -++ -++ disable_dma(chan); -++ if (__dmac_channel_address_error_detected(chan)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", -++ __FUNCTION__); -++ __dmac_channel_clear_address_error(chan); -++ } -++ if (__dmac_channel_transmit_end_detected(chan)) { -++ __dmac_channel_clear_transmit_end(chan); -++ } -++ return IRQ_HANDLED; -++} -++static irqreturn_t jz_mmc_dma_tx_callback(int irq, void *devid) -++{ -++ int chan = txdmachan; -++ -++ disable_dma(chan); -++ if (__dmac_channel_address_error_detected(chan)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", -++ __FUNCTION__); -++ __dmac_channel_clear_address_error(chan); -++ } -++ if (__dmac_channel_transmit_end_detected(chan)) { -++ __dmac_channel_clear_transmit_end(chan); -++ } -++ return IRQ_HANDLED; -++} -++ -++/* Prepare DMA to start data transfer from the MMC card */ -++static void jz_mmc_rx_setup_data(struct jz_mmc_host *host, -++ struct mmc_data *data) -++{ -++ unsigned int nob = data->blocks; -++ int channelrx = rxdmachan; -++ int i; -++ u32 size; -++ -++ if (data->flags & MMC_DATA_STREAM) -++ nob = 0xffff; -++ -++ REG_MSC_NOB = nob; -++ REG_MSC_BLKLEN = data->blksz; -++ size = nob * data->blksz; -++ -++ if (data->flags & MMC_DATA_READ) { -++ host->dma.dir = DMA_FROM_DEVICE; -++ } else { -++ host->dma.dir = DMA_TO_DEVICE; -++ } -++ -++ host->dma.len = -++ dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, -++ host->dma.dir); -++ -++ for (i = 0; i < host->dma.len; i++) { -++ host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]); -++ host->sg_cpu[i].dcmd = sg_dma_len(&data->sg[i]); -++ dma_cache_wback_inv((unsigned long) -++ CKSEG0ADDR(sg_dma_address(data->sg)) + -++ data->sg->offset, -++ host->sg_cpu[i].dcmd); -++ jz_mmc_start_dma(channelrx, host->sg_cpu[i].dtadr, -++ host->sg_cpu[i].dcmd, DMA_MODE_READ); -++ } -++} -++ -++/* Prepare DMA to start data transfer from the MMC card */ -++static void jz_mmc_tx_setup_data(struct jz_mmc_host *host, -++ struct mmc_data *data) -++{ -++ unsigned int nob = data->blocks; -++ int channeltx = txdmachan; -++ int i; -++ u32 size; -++ -++ if (data->flags & MMC_DATA_STREAM) -++ nob = 0xffff; -++ -++ REG_MSC_NOB = nob; -++ REG_MSC_BLKLEN = data->blksz; -++ size = nob * data->blksz; -++ -++ if (data->flags & MMC_DATA_READ) { -++ host->dma.dir = DMA_FROM_DEVICE; -++ } else { -++ host->dma.dir = DMA_TO_DEVICE; -++ } -++ -++ host->dma.len = -++ dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, -++ host->dma.dir); -++ -++ for (i = 0; i < host->dma.len; i++) { -++ host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]); -++ host->sg_cpu[i].dcmd = sg_dma_len(&data->sg[i]); -++ dma_cache_wback_inv((unsigned long) -++ CKSEG0ADDR(sg_dma_address(data->sg)) + -++ data->sg->offset, -++ host->sg_cpu[i].dcmd); -++ jz_mmc_start_dma(channeltx, host->sg_cpu[i].dtadr, -++ host->sg_cpu[i].dcmd, DMA_MODE_WRITE); -++ } -++} -++#else -++static void jz_mmc_receive_pio(struct jz_mmc_host *host) -++{ -++ -++ struct mmc_data *data = 0; -++ int sg_len = 0, max = 0, count = 0; -++ u32 *buf = 0; -++ struct scatterlist *sg; -++ unsigned int nob; -++ -++ data = host->mrq->data; -++ nob = data->blocks; -++ REG_MSC_NOB = nob; -++ REG_MSC_BLKLEN = data->blksz; -++ -++ max = host->pio.len; -++ if (host->pio.index < host->dma.len) { -++ sg = &data->sg[host->pio.index]; -++ buf = sg_virt(sg) + host->pio.offset; -++ -++ /* This is the space left inside the buffer */ -++ sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset; -++ /* Check to if we need less then the size of the sg_buffer */ -++ if (sg_len < max) max = sg_len; -++ } -++ max = max / 4; -++ for(count = 0; count < max; count++) { -++ while (REG_MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY) -++ ; -++ *buf++ = REG_MSC_RXFIFO; -++ } -++ host->pio.len -= count; -++ host->pio.offset += count; -++ -++ if (sg_len && count == sg_len) { -++ host->pio.index++; -++ host->pio.offset = 0; -++ } -++} -++ -++static void jz_mmc_send_pio(struct jz_mmc_host *host) -++{ -++ -++ struct mmc_data *data = 0; -++ int sg_len, max, count = 0; -++ u32 *wbuf = 0; -++ struct scatterlist *sg; -++ unsigned int nob; -++ -++ data = host->mrq->data; -++ nob = data->blocks; -++ -++ REG_MSC_NOB = nob; -++ REG_MSC_BLKLEN = data->blksz; -++ -++ /* This is the pointer to the data buffer */ -++ sg = &data->sg[host->pio.index]; -++ wbuf = sg_virt(sg) + host->pio.offset; -++ -++ /* This is the space left inside the buffer */ -++ sg_len = data->sg[host->pio.index].length - host->pio.offset; -++ -++ /* Check to if we need less then the size of the sg_buffer */ -++ max = (sg_len > host->pio.len) ? host->pio.len : sg_len; -++ max = max / 4; -++ for(count = 0; count < max; count++ ) { -++ while (REG_MSC_STAT & MSC_STAT_DATA_FIFO_FULL) -++ ; -++ REG_MSC_TXFIFO = *wbuf++; -++ } -++ -++ host->pio.len -= count; -++ host->pio.offset += count; -++ -++ if (count == sg_len) { -++ host->pio.index++; -++ host->pio.offset = 0; -++ } -++} -++ -++static int -++jz_mmc_prepare_data(struct jz_mmc_host *host, struct mmc_data *data) -++{ -++ int datalen = data->blocks * data->blksz; -++ -++ host->dma.dir = DMA_BIDIRECTIONAL; -++ host->dma.len = dma_map_sg(mmc_dev(host->mmc), data->sg, -++ data->sg_len, host->dma.dir); -++ if (host->dma.len == 0) -++ return -ETIMEDOUT; -++ -++ host->pio.index = 0; -++ host->pio.offset = 0; -++ host->pio.len = datalen; -++ return 0; -++} -++#endif -++ -++static int jz_mmc_cmd_done(struct jz_mmc_host *host, unsigned int stat); -++ -++static void jz_mmc_finish_request(struct jz_mmc_host *host, struct mmc_request *mrq) -++{ -++ jz_mmc_stop_clock(); -++ host->mrq = NULL; -++ host->cmd = NULL; -++ host->data = NULL; -++ mmc_request_done(host->mmc, mrq); -++} -++ -++static void jz_mmc_start_cmd(struct jz_mmc_host *host, -++ struct mmc_command *cmd, unsigned int cmdat) -++{ -++ u32 timeout = 0x3fffff; -++ unsigned int stat; -++ struct jz_mmc_host *hst = host; -++ WARN_ON(host->cmd != NULL); -++ host->cmd = cmd; -++ -++ /* stop MMC clock */ -++ jz_mmc_stop_clock(); -++ -++ /* mask interrupts */ -++ REG_MSC_IMASK = 0xff; -++ -++ /* clear status */ -++ REG_MSC_IREG = 0xff; -++ -++ if (cmd->flags & MMC_RSP_BUSY) -++ cmdat |= MSC_CMDAT_BUSY; -++ -++#define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE)) -++ switch (RSP_TYPE(mmc_resp_type(cmd))) { -++ case RSP_TYPE(MMC_RSP_R1): /* r1,r1b, r6, r7 */ -++ cmdat |= MSC_CMDAT_RESPONSE_R1; -++ r_type = 1; -++ break; -++ case RSP_TYPE(MMC_RSP_R3): -++ cmdat |= MSC_CMDAT_RESPONSE_R3; -++ r_type = 1; -++ break; -++ case RSP_TYPE(MMC_RSP_R2): -++ cmdat |= MSC_CMDAT_RESPONSE_R2; -++ r_type = 2; -++ break; -++ default: -++ break; -++ } -++ REG_MSC_CMD = cmd->opcode; -++ -++ /* Set argument */ -++#ifdef CONFIG_JZ_MMC_BUS_1 -++ if (cmd->opcode == 6) { -++ /* set 1 bit sd card bus*/ -++ if (cmd->arg ==2) -++ REG_MSC_ARG = 0; -++ -++ /* set 1 bit mmc card bus*/ -++ if (cmd->arg == 0x3b70101) -++ REG_MSC_ARG = 0x3b70001; -++ } else -++ REG_MSC_ARG = cmd->arg; -++#else -++ REG_MSC_ARG = cmd->arg; -++#endif -++ -++ /* Set command */ -++ REG_MSC_CMDAT = cmdat; -++ -++ /* Send command */ -++ jz_mmc_start_clock(); -++ -++ while (timeout-- && !(REG_MSC_STAT & MSC_STAT_END_CMD_RES)) -++ ; -++ -++ REG_MSC_IREG = MSC_IREG_END_CMD_RES; /* clear irq flag */ -++ if (cmd->opcode == 12) { -++ while (timeout-- && !(REG_MSC_IREG & MSC_IREG_PRG_DONE)) -++ ; -++ REG_MSC_IREG = MSC_IREG_PRG_DONE; /* clear status */ -++ } -++ if (!mmc_slot_enable) { -++ /* It seems that MSC can't report the MSC_STAT_TIME_OUT_RES when -++ * card was removed. We force to return here. -++ */ -++ cmd->error = -ETIMEDOUT; -++ jz_mmc_finish_request(hst, hst->mrq); -++ return; -++ } -++ -++ if (SD_IO_SEND_OP_COND == cmd->opcode) { -++ /* -++ * Don't support SDIO card currently. -++ */ -++ cmd->error = -ETIMEDOUT; -++ jz_mmc_finish_request(hst, hst->mrq); -++ return; -++ } -++ -++ /* Check for status */ -++ stat = REG_MSC_STAT; -++ jz_mmc_cmd_done(hst, stat); -++ if (host->data) { -++ if (cmd->opcode == MMC_WRITE_BLOCK || cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) -++#ifdef USE_DMA -++ jz_mmc_tx_setup_data(host, host->data); -++#else -++ jz_mmc_send_pio(host); -++ else -++ jz_mmc_receive_pio(host); -++#endif -++ } -++} -++ -++static int jz_mmc_cmd_done(struct jz_mmc_host *host, unsigned int stat) -++{ -++ struct mmc_command *cmd = host->cmd; -++ int i, temp[16]; -++ u8 *buf; -++ u32 data, v, w1, w2; -++ -++ if (!cmd) -++ return 0; -++ -++ host->cmd = NULL; -++ buf = (u8 *) temp; -++ switch (r_type) { -++ case 1: -++ { -++ data = REG_MSC_RES; -++ buf[0] = (data >> 8) & 0xff; -++ buf[1] = data & 0xff; -++ data = REG_MSC_RES; -++ buf[2] = (data >> 8) & 0xff; -++ buf[3] = data & 0xff; -++ data = REG_MSC_RES; -++ buf[4] = data & 0xff; -++ cmd->resp[0] = -++ buf[1] << 24 | buf[2] << 16 | buf[3] << 8 | -++ buf[4]; -++ break; -++ } -++ case 2: -++ { -++ data = REG_MSC_RES; -++ v = data & 0xffff; -++ for (i = 0; i < 4; i++) { -++ data = REG_MSC_RES; -++ w1 = data & 0xffff; -++ data = REG_MSC_RES; -++ w2 = data & 0xffff; -++ cmd->resp[i] = v << 24 | w1 << 8 | w2 >> 8; -++ v = w2; -++ } -++ break; -++ } -++ case 0: -++ break; -++ } -++ if (stat & MSC_STAT_TIME_OUT_RES) { -++ printk("MSC_STAT_TIME_OUT_RES\n"); -++ cmd->error = -ETIMEDOUT; -++ } else if (stat & MSC_STAT_CRC_RES_ERR && cmd->flags & MMC_RSP_CRC) { -++ printk("MSC_STAT_CRC\n"); -++ if (cmd->opcode == MMC_ALL_SEND_CID || -++ cmd->opcode == MMC_SEND_CSD || -++ cmd->opcode == MMC_SEND_CID) { -++ /* a bogus CRC error can appear if the msb of -++ the 15 byte response is a one */ -++ if ((cmd->resp[0] & 0x80000000) == 0) -++ cmd->error = -EILSEQ; -++ } -++ } -++ /* -++ * Did I mention this is Sick. We always need to -++ * discard the upper 8 bits of the first 16-bit word. -++ */ -++ if (host->data && cmd->error == 0) -++ jz_mmc_enable_irq(host, MSC_IMASK_DATA_TRAN_DONE); -++ else -++ jz_mmc_finish_request(host, host->mrq); -++ -++ return 1; -++} -++ -++static int jz_mmc_data_done(struct jz_mmc_host *host, unsigned int stat) -++{ -++ struct mmc_data *data = host->data; -++ -++ if (!data) -++ return 0; -++ REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE; /* clear status */ -++ jz_mmc_stop_clock(); -++ dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, -++ host->dma_dir); -++ if (stat & MSC_STAT_TIME_OUT_READ) { -++ printk("MMC/SD timeout, MMC_STAT 0x%x\n", stat); -++ data->error = -ETIMEDOUT; -++ } else if (REG_MSC_STAT & -++ (MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR)) { -++ printk("MMC/SD CRC error, MMC_STAT 0x%x\n", stat); -++ data->error = -EILSEQ; -++ } -++ /* -++ * There appears to be a hardware design bug here. There seems to -++ * be no way to find out how much data was transferred to the card. -++ * This means that if there was an error on any block, we mark all -++ * data blocks as being in error. -++ */ -++ if (data->error == 0) -++ data->bytes_xfered = data->blocks * data->blksz; -++ else -++ data->bytes_xfered = 0; -++ -++ jz_mmc_disable_irq(host, MSC_IMASK_DATA_TRAN_DONE); -++ host->data = NULL; -++ if (host->mrq->stop) { -++ jz_mmc_stop_clock(); -++ jz_mmc_start_cmd(host, host->mrq->stop, 0); -++ } else { -++ jz_mmc_finish_request(host, host->mrq); -++ } -++ return 1; -++} -++ -++static void jz_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) -++{ -++ struct jz_mmc_host *host = mmc_priv(mmc); -++ unsigned int cmdat; -++ -++ /* stop MMC clock */ -++ jz_mmc_stop_clock(); -++ -++ /* Save current request for the future processing */ -++ host->mrq = mrq; -++ host->data = mrq->data; -++ cmdat = host->cmdat; -++ host->cmdat &= ~MSC_CMDAT_INIT; -++ -++ if (mrq->data) { -++ cmdat &= ~MSC_CMDAT_BUSY; -++#ifdef USE_DMA -++ if ((mrq->cmd->opcode == 51) | (mrq->cmd->opcode == 8) | (mrq->cmd->opcode == 6)) -++ -++ cmdat |= -++ MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN | -++ MSC_CMDAT_DMA_EN; -++ else { -++#ifdef CONFIG_JZ_MMC_BUS_1 -++ cmdat &= ~MSC_CMDAT_BUS_WIDTH_4BIT; -++ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN | -++ MSC_CMDAT_DMA_EN; -++#else -++ cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_DMA_EN; -++#endif -++ } -++ if (mrq->data->flags & MMC_DATA_WRITE) -++ cmdat |= MSC_CMDAT_WRITE; -++ -++ if (mrq->data->flags & MMC_DATA_STREAM) -++ cmdat |= MSC_CMDAT_STREAM_BLOCK; -++ if (mrq->cmd->opcode != MMC_WRITE_BLOCK -++ && mrq->cmd->opcode != MMC_WRITE_MULTIPLE_BLOCK) -++ jz_mmc_rx_setup_data(host, mrq->data); -++#else /*USE_DMA*/ -++ -++ if ((mrq->cmd->opcode == 51) | (mrq->cmd->opcode == 8) | (mrq->cmd->opcode == 6)) -++ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN; -++ else { -++#ifdef CONFIG_JZ_MMC_BUS_1 -++ cmdat &= ~MSC_CMDAT_BUS_WIDTH_4BIT; -++ cmdat |= MSC_CMDAT_BUS_WIDTH_1BIT | MSC_CMDAT_DATA_EN; -++#else -++ cmdat |= MSC_CMDAT_DATA_EN; -++#endif -++ } -++ if (mrq->data->flags & MMC_DATA_WRITE) -++ cmdat |= MSC_CMDAT_WRITE; -++ -++ if (mrq->data->flags & MMC_DATA_STREAM) -++ cmdat |= MSC_CMDAT_STREAM_BLOCK; -++ jz_mmc_prepare_data(host, host->data); -++#endif /*USE_DMA*/ -++ } -++ jz_mmc_start_cmd(host, mrq->cmd, cmdat); -++} -++ -++static irqreturn_t jz_mmc_irq(int irq, void *devid) -++{ -++ struct jz_mmc_host *host = devid; -++ unsigned int ireg; -++ int handled = 0; -++ -++ ireg = REG_MSC_IREG; -++ -++ if (ireg) { -++ unsigned stat = REG_MSC_STAT; -++ if (ireg & MSC_IREG_DATA_TRAN_DONE) -++ handled |= jz_mmc_data_done(host, stat); -++ } -++ return IRQ_RETVAL(handled); -++} -++ -++/* Returns true if MMC slot is empty */ -++static int jz_mmc_slot_is_empty(int slot) -++{ -++ int empty; -++ -++ empty = (__msc_card_detected(slot) == 0) ? 1 : 0; -++ -++ if (empty) { -++ /* wait for card insertion */ -++#ifdef CONFIG_MIPS_JZ4740_LYRA -++ __gpio_as_irq_rise_edge(MSC_HOTPLUG_PIN); -++#else -++ __gpio_as_irq_fall_edge(MSC_HOTPLUG_PIN); -++#endif -++ } else { -++ /* wait for card removal */ -++#ifdef CONFIG_MIPS_JZ4740_LYRA -++ __gpio_as_irq_fall_edge(MSC_HOTPLUG_PIN); -++#else -++ __gpio_as_irq_rise_edge(MSC_HOTPLUG_PIN); -++#endif -++ } -++ -++ return empty; -++} -++ -++static irqreturn_t jz_mmc_detect_irq(int irq, void *devid) -++{ -++ struct jz_mmc_host *host = (struct jz_mmc_host *) devid; -++ -++ if (jz_mmc_slot_is_empty(0)) { -++ mmc_slot_enable = 0; -++ mmc_detect_change(host->mmc, 50); -++ } else { -++ mmc_slot_enable = 1; -++ mmc_detect_change(host->mmc, 50); -++ } -++ return IRQ_HANDLED; -++} -++ -++static int jz_mmc_get_ro(struct mmc_host *mmc) -++{ -++ struct jz_mmc_host *host = mmc_priv(mmc); -++ -++ if (host->pdata && host->pdata->get_ro) -++ return host->pdata->get_ro(mmc_dev(mmc)); -++ /* Host doesn't support read only detection so assume writeable */ -++ return 0; -++} -++ -++/* set clock and power */ -++static void jz_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -++{ -++ struct jz_mmc_host *host = mmc_priv(mmc); -++ -++ if (ios->clock) -++ jz_mmc_set_clock(ios->clock); -++ else -++ jz_mmc_stop_clock(); -++ -++ if (host->power_mode != ios->power_mode) { -++ host->power_mode = ios->power_mode; -++ -++ if (ios->power_mode == MMC_POWER_ON) -++ host->cmdat |= CMDAT_INIT; -++ } -++ -++ if ((ios->bus_width == MMC_BUS_WIDTH_4) || (ios->bus_width == MMC_BUS_WIDTH_8)) -++ host->cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT; -++ else -++ host->cmdat &= ~MSC_CMDAT_BUS_WIDTH_4BIT; -++} -++ -++static const struct mmc_host_ops jz_mmc_ops = { -++ .request = jz_mmc_request, -++ .get_ro = jz_mmc_get_ro, -++ .set_ios = jz_mmc_set_ios, -++}; -++static int jz_mmc_pm_callback(struct pm_dev *pm_dev, -++ pm_request_t req, void *data); -++ -++static int jz_mmc_probe(struct platform_device *pdev) -++{ -++ int retval; -++ struct mmc_host *mmc; -++ struct jz_mmc_host *host = NULL; -++ int irq; -++ struct resource *r; -++ -++ __gpio_as_msc(); -++ __msc_init_io(); -++ __msc_enable_power(); -++ -++ __msc_reset(); -++ -++ /* On reset, stop MMC clock */ -++ jz_mmc_stop_clock(); -++ -++ MMC_IRQ_MASK(); -++ -++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -++ irq = platform_get_irq(pdev, 0); -++ if (!r || irq < 0) -++ return -ENXIO; -++ -++ r = request_mem_region(r->start, SZ_4K, DRIVER_NAME); -++ if (!r) -++ return -EBUSY; -++ -++ mmc = mmc_alloc_host(sizeof(struct jz_mmc_host), &pdev->dev); -++ if (!mmc) { -++ retval = -ENOMEM; -++ goto out; -++ } -++ mmc->ops = &jz_mmc_ops; -++ mmc->f_min = MMC_CLOCK_SLOW; -++ mmc->f_max = SD_CLOCK_FAST; -++ /* -++ * We can do SG-DMA, but we don't because we never know how much -++ * data we successfully wrote to the card. -++ */ -++ mmc->max_phys_segs = NR_SG; -++ /* -++ * Our hardware DMA can handle a maximum of one page per SG entry. -++ */ -++ mmc->max_seg_size = PAGE_SIZE; -++ /* -++ * Block length register is 10 bits. -++ */ -++ mmc->max_blk_size = 1023; -++ /* -++ * Block count register is 16 bits. -++ */ -++ mmc->max_blk_count = 65535; -++ host = mmc_priv(mmc); -++ host->mmc = mmc; -++ host->pdata = pdev->dev.platform_data; -++ mmc->ocr_avail = host->pdata ? -++ host->pdata->ocr_mask : MMC_VDD_32_33 | MMC_VDD_33_34; -++ host->mmc->caps = -++ MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_SD_HIGHSPEED -++ | MMC_CAP_MMC_HIGHSPEED; -++ /* -++ *MMC_CAP_4_BIT_DATA (1 << 0) The host can do 4 bit transfers -++ * -++ */ -++ host->sg_cpu = -++ dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &host->sg_dma, -++ GFP_KERNEL); -++ if (!host->sg_cpu) { -++ retval = -ENOMEM; -++ goto out; -++ } -++ spin_lock_init(&host->lock); -++ host->irq = IRQ_MSC; -++ host->imask = 0xff; -++ /* -++ * Ensure that the host controller is shut down, and setup -++ * with our defaults. -++ */ -++ retval = request_irq(IRQ_MSC, jz_mmc_irq, 0, "MMC/SD", host); -++ if (retval) { -++ printk(KERN_ERR "MMC/SD: can't request MMC/SD IRQ\n"); -++ return retval; -++ } -++ jz_mmc_slot_is_empty(0); -++ /* Request card detect interrupt */ -++ -++ retval = request_irq(MSC_HOTPLUG_IRQ, jz_mmc_detect_irq, 0, //SA_INTERRUPT, -++ "MMC card detect", host); -++ if (retval) { -++ printk(KERN_ERR "MMC/SD: can't request card detect IRQ\n"); -++ goto err1; -++ } -++#ifdef USE_DMA -++ /* Request MMC Rx DMA channel */ -++ rxdmachan = -++ jz_request_dma(DMA_ID_MSC_RX, "MMC Rx", jz_mmc_dma_rx_callback, -++ 0, host); -++ if (rxdmachan < 0) { -++ printk(KERN_ERR "jz_request_dma failed for MMC Rx\n"); -++ goto err2; -++ } -++ -++ /* Request MMC Tx DMA channel */ -++ txdmachan = -++ jz_request_dma(DMA_ID_MSC_TX, "MMC Tx", jz_mmc_dma_tx_callback, -++ 0, host); -++ if (txdmachan < 0) { -++ printk(KERN_ERR "jz_request_dma failed for MMC Tx\n"); -++ goto err3; -++ } -++#endif -++ platform_set_drvdata(pdev, mmc); -++ mmc_add_host(mmc); -++#ifdef CONFIG_PM -++ /* Register MMC slot as as power-managed device */ -++ host->pmdev = pm_register(PM_UNKNOWN_DEV, PM_SYS_UNKNOWN, jz_mmc_pm_callback); -++ if (host->pmdev) -++ host->pmdev->data = pdev; -++#endif -++ printk("JZ SD/MMC card driver registered\n"); -++ -++ /* Detect card during initialization */ -++#ifdef CONFIG_SOC_JZ4740 -++ if (!jz_mmc_slot_is_empty(0)) { -++ mmc_slot_enable = 1; -++ mmc_detect_change(host->mmc, 0); -++ } -++#endif -++ return 0; -++ -++err1:free_irq(IRQ_MSC, &host); -++#ifdef USE_DMA -++ err2:jz_free_dma(rxdmachan); -++ err3:jz_free_dma(txdmachan); -++#endif -++out: -++ if (host) { -++ if (host->sg_cpu) -++ dma_free_coherent(&pdev->dev, PAGE_SIZE, -++ host->sg_cpu, host->sg_dma); -++ } -++ if (mmc) -++ mmc_free_host(mmc); -++ return -1; -++} -++ -++static int jz_mmc_remove(struct platform_device *pdev) -++{ -++ struct mmc_host *mmc = platform_get_drvdata(pdev); -++ long flags; -++ -++ platform_set_drvdata(pdev, NULL); -++ -++ if (mmc) { -++ struct jz_mmc_host *host = mmc_priv(mmc); -++ -++ if (host->pdata && host->pdata->exit) -++ host->pdata->exit(&pdev->dev, mmc); -++ -++ mmc_remove_host(mmc); -++ -++ local_irq_save(flags); -++ jz_mmc_stop_clock(); -++ __msc_disable_power(); -++ jz_free_dma(rxdmachan); -++ jz_free_dma(txdmachan); -++ free_irq(IRQ_MSC, host); -++ local_irq_restore(flags); -++ mmc_free_host(mmc); -++ } -++ return 0; -++} -++ -++#ifdef CONFIG_PM -++pm_message_t state; -++static int jz_mmc_suspend(struct platform_device *dev, pm_message_t state) -++{ -++ struct mmc_host *mmc = platform_get_drvdata(dev); -++ int ret = 0; -++ -++ __msc_disable_power(); -++ if (mmc) -++ ret = mmc_suspend_host(mmc, state); -++ -++ return ret; -++} -++ -++static int jz_mmc_resume(struct platform_device *dev) -++{ -++ struct mmc_host *mmc = platform_get_drvdata(dev); -++ int ret = 0; -++#if 0 -++ /*for sandisk BB0807011816D and other strange cards*/ -++ int i; -++ -++ for(i = 104; i < 110; i++) -++ __gpio_as_input(i); -++ -++ /* perhaps you should mdelay more */ -++ mdelay(1000); -++ __gpio_as_msc(); -++#endif -++ __msc_init_io(); -++ __msc_enable_power(); -++ __msc_reset(); -++ -++ if (!jz_mmc_slot_is_empty(0)) { -++ mmc_slot_enable = 1; -++ mmc_detect_change(mmc, 10); -++ } -++ -++ if (mmc) -++ ret = mmc_resume_host(mmc); -++ -++ return ret; -++} -++static int jz_mmc_pm_callback(struct pm_dev *pm_dev, -++ pm_request_t req, void *data) -++{ -++ struct platform_device *pdev = (struct platform_device *)pm_dev->data; -++ -++ switch(req) { -++ case PM_RESUME: -++ jz_mmc_resume(pdev); -++ break; -++ case PM_SUSPEND: -++ /* state has no use */ -++ jz_mmc_suspend(pdev, state); -++ break; -++ default: -++ printk("MMC/SD: invalid PM request %d\n", req); -++ break; -++ } -++ return 0; -++} -++#else -++#define jz_mmc_suspend NULL -++#define jz_mmc_resume NULL -++#endif -++ -++static struct platform_driver jz_mmc_driver = { -++ .probe = jz_mmc_probe, -++ .remove = jz_mmc_remove, -++ .suspend = jz_mmc_suspend, -++ .resume = jz_mmc_resume, -++ .driver = { -++ .name = DRIVER_NAME, -++ }, -++}; -++ -++static int __init jz_mmc_init(void) -++{ -++ return platform_driver_register(&jz_mmc_driver); -++} -++ -++static void __exit jz_mmc_exit(void) -++{ -++ platform_driver_unregister(&jz_mmc_driver); -++} -++ -++module_init(jz_mmc_init); -++module_exit(jz_mmc_exit); -++ -++MODULE_DESCRIPTION("JZ47XX SD/Multimedia Card Interface Driver"); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/drivers/mmc/host/jz_mmc.h linux-2.6.24.7/drivers/mmc/host/jz_mmc.h -+--- linux-2.6.24.7.old/drivers/mmc/host/jz_mmc.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mmc/host/jz_mmc.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,65 @@ -++#ifndef __JZ_MMC_H__ -++#define __JZ_MMC_H__ -++ -++#define MMC_CLOCK_SLOW 400000 /* 400 kHz for initial setup */ -++#define MMC_CLOCK_FAST 20000000 /* 20 MHz for maximum for normal operation */ -++#define SD_CLOCK_FAST 24000000 /* 24 MHz for SD Cards */ -++#define MMC_NO_ERROR 0 -++/* Extra MMC commands for state control */ -++/* Use negative numbers to disambiguate */ -++#define MMC_CIM_RESET -1 -++#define MMC_SET_CLOCK 100 -++ -++typedef struct jzsoc_dma_desc { -++ volatile u32 ddadr; /* Points to the next descriptor + flags */ -++ volatile u32 dsadr; /* DSADR value for the current transfer */ -++ volatile u32 dtadr; /* DTADR value for the current transfer */ -++ volatile u32 dcmd; /* DCMD value for the current transfer */ -++} jzsoc_dma_desc; -++ -++ -++ -++ -++#include -++ -++struct device; -++struct mmc_host; -++ -++struct jz_mmc_platform_data { -++ unsigned int ocr_mask; /* available voltages */ -++ unsigned long detect_delay; /* delay in jiffies before detecting cards after interrupt */ -++ int (*init)(struct device *, irq_handler_t , void *); -++ int (*get_ro)(struct device *); -++ void (*setpower)(struct device *, unsigned int); -++ void (*exit)(struct device *, void *); -++}; -++ -++//extern void pxa_set_mci_info(struct pxamci_platform_data *info); -++ -++ -++ -++#define SZ_1K 0x00000400 -++#define SZ_4K 0x00001000 -++#define SZ_8K 0x00002000 -++#define SZ_16K 0x00004000 -++#define SZ_64K 0x00010000 -++#define SZ_128K 0x00020000 -++#define SZ_256K 0x00040000 -++#define SZ_512K 0x00080000 -++ -++#define SZ_1M 0x00100000 -++#define SZ_2M 0x00200000 -++#define SZ_4M 0x00400000 -++#define SZ_8M 0x00800000 -++#define SZ_16M 0x01000000 -++#define SZ_32M 0x02000000 -++#define SZ_64M 0x04000000 -++#define SZ_128M 0x08000000 -++#define SZ_256M 0x10000000 -++#define SZ_512M 0x20000000 -++ -++#define SZ_1G 0x40000000 -++#define SZ_2G 0x80000000 -++ -++ -++#endif /* __JZ_MMC_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/Makefile linux-2.6.24.7/drivers/mtd/Makefile -+--- linux-2.6.24.7.old/drivers/mtd/Makefile 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -3,9 +3,9 @@ -+ # -+ -+ # Core functionality. -+-obj-$(CONFIG_MTD) += mtd.o -+ mtd-y := mtdcore.o mtdsuper.o -+ mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart.o -++obj-$(CONFIG_MTD) += $(mtd-y) -+ -+ obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o -+ obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o -+@@ -15,14 +15,15 @@ -+ # 'Users' - code which presents functionality to userspace. -+ obj-$(CONFIG_MTD_CHAR) += mtdchar.o -+ obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o -+-obj-$(CONFIG_MTD_BLOCK) += mtdblock.o -++#obj-$(CONFIG_MTD_BLOCK) += mtdblock.o -++obj-$(CONFIG_MTD_BLOCK) += mtdblock-jz.o -++obj-$(CONFIG_UDC_USE_LB_CACHE) += udc_cache.o -+ obj-$(CONFIG_MTD_BLOCK_RO) += mtdblock_ro.o -+ obj-$(CONFIG_FTL) += ftl.o -+ obj-$(CONFIG_NFTL) += nftl.o -+ obj-$(CONFIG_INFTL) += inftl.o -+ obj-$(CONFIG_RFD_FTL) += rfd_ftl.o -+ obj-$(CONFIG_SSFDC) += ssfdc.o -+-obj-$(CONFIG_MTD_OOPS) += mtdoops.o -+ -+ nftl-objs := nftlcore.o nftlmount.o -+ inftl-objs := inftlcore.o inftlmount.o -+@@ -30,3 +31,6 @@ -+ obj-y += chips/ maps/ devices/ nand/ onenand/ -+ -+ obj-$(CONFIG_MTD_UBI) += ubi/ -++ -++$(obj)/mtdblock-jz.o: $(obj)/mtdblock-jz.uu -++ uudecode $(obj)/mtdblock-jz.uu -o $(obj)/mtdblock-jz.o -+\ No newline at end of file -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/HEAD linux-2.6.24.7/drivers/mtd/mtd-utils/.git/HEAD -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/HEAD 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/HEAD 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++ref: refs/heads/master -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/config linux-2.6.24.7/drivers/mtd/mtd-utils/.git/config -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/config 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/config 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,11 @@ -++[core] -++ repositoryformatversion = 0 -++ filemode = true -++ bare = false -++ logallrefupdates = true -++[remote "origin"] -++ url = git://git.infradead.org/mtd-utils.git -++ fetch = +refs/heads/*:refs/remotes/origin/* -++[branch "master"] -++ remote = origin -++ merge = refs/heads/master -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/description linux-2.6.24.7/drivers/mtd/mtd-utils/.git/description -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/description 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/description 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++Unnamed repository; edit this file to name it for gitweb. -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/applypatch-msg linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/applypatch-msg -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/applypatch-msg 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/applypatch-msg 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,15 @@ -++#!/bin/sh -++# -++# An example hook script to check the commit log message taken by -++# applypatch from an e-mail message. -++# -++# The hook should exit with non-zero status after issuing an -++# appropriate message if it wants to stop the commit. The hook is -++# allowed to edit the commit message file. -++# -++# To enable this hook, make this file executable. -++ -++. git-sh-setup -++test -x "$GIT_DIR/hooks/commit-msg" && -++ exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"} -++: -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/commit-msg linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/commit-msg -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/commit-msg 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/commit-msg 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,24 @@ -++#!/bin/sh -++# -++# An example hook script to check the commit log message. -++# Called by git-commit with one argument, the name of the file -++# that has the commit message. The hook should exit with non-zero -++# status after issuing an appropriate message if it wants to stop the -++# commit. The hook is allowed to edit the commit message file. -++# -++# To enable this hook, make this file executable. -++ -++# Uncomment the below to add a Signed-off-by line to the message. -++# Doing this in a hook is a bad idea in general, but the prepare-commit-msg -++# hook is more suited to it. -++# -++# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -++# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" -++ -++# This example catches duplicate Signed-off-by lines. -++ -++test "" = "$(grep '^Signed-off-by: ' "$1" | -++ sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { -++ echo >&2 Duplicate Signed-off-by lines. -++ exit 1 -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/post-commit linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/post-commit -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/post-commit 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/post-commit 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,8 @@ -++#!/bin/sh -++# -++# An example hook script that is called after a successful -++# commit is made. -++# -++# To enable this hook, make this file executable. -++ -++: Nothing -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/post-receive linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/post-receive -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/post-receive 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/post-receive 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,16 @@ -++#!/bin/sh -++# -++# An example hook script for the post-receive event -++# -++# This script is run after receive-pack has accepted a pack and the -++# repository has been updated. It is passed arguments in through stdin -++# in the form -++# -++# For example: -++# aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master -++# -++# see contrib/hooks/ for an sample, or uncomment the next line (on debian) -++# -++ -++ -++#. /usr/share/doc/git-core/contrib/hooks/post-receive-email -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/post-update linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/post-update -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/post-update 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/post-update 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,8 @@ -++#!/bin/sh -++# -++# An example hook script to prepare a packed repository for use over -++# dumb transports. -++# -++# To enable this hook, make this file executable by "chmod +x post-update". -++ -++exec git-update-server-info -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/pre-applypatch linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/pre-applypatch -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/pre-applypatch 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/pre-applypatch 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,14 @@ -++#!/bin/sh -++# -++# An example hook script to verify what is about to be committed -++# by applypatch from an e-mail message. -++# -++# The hook should exit with non-zero status after issuing an -++# appropriate message if it wants to stop the commit. -++# -++# To enable this hook, make this file executable. -++ -++. git-sh-setup -++test -x "$GIT_DIR/hooks/pre-commit" && -++ exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"} -++: -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/pre-commit linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/pre-commit -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/pre-commit 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/pre-commit 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,70 @@ -++#!/bin/sh -++# -++# An example hook script to verify what is about to be committed. -++# Called by git-commit with no arguments. The hook should -++# exit with non-zero status after issuing an appropriate message if -++# it wants to stop the commit. -++# -++# To enable this hook, make this file executable. -++ -++# This is slightly modified from Andrew Morton's Perfect Patch. -++# Lines you introduce should not have trailing whitespace. -++# Also check for an indentation that has SP before a TAB. -++ -++if git-rev-parse --verify HEAD 2>/dev/null -++then -++ git-diff-index -p -M --cached HEAD -- -++else -++ # NEEDSWORK: we should produce a diff with an empty tree here -++ # if we want to do the same verification for the initial import. -++ : -++fi | -++perl -e ' -++ my $found_bad = 0; -++ my $filename; -++ my $reported_filename = ""; -++ my $lineno; -++ sub bad_line { -++ my ($why, $line) = @_; -++ if (!$found_bad) { -++ print STDERR "*\n"; -++ print STDERR "* You have some suspicious patch lines:\n"; -++ print STDERR "*\n"; -++ $found_bad = 1; -++ } -++ if ($reported_filename ne $filename) { -++ print STDERR "* In $filename\n"; -++ $reported_filename = $filename; -++ } -++ print STDERR "* $why (line $lineno)\n"; -++ print STDERR "$filename:$lineno:$line\n"; -++ } -++ while (<>) { -++ if (m|^diff --git a/(.*) b/\1$|) { -++ $filename = $1; -++ next; -++ } -++ if (/^@@ -\S+ \+(\d+)/) { -++ $lineno = $1 - 1; -++ next; -++ } -++ if (/^ /) { -++ $lineno++; -++ next; -++ } -++ if (s/^\+//) { -++ $lineno++; -++ chomp; -++ if (/\s$/) { -++ bad_line("trailing whitespace", $_); -++ } -++ if (/^\s* \t/) { -++ bad_line("indent SP followed by a TAB", $_); -++ } -++ if (/^([<>])\1{6} |^={7}$/) { -++ bad_line("unresolved merge conflict", $_); -++ } -++ } -++ } -++ exit($found_bad); -++' -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/pre-rebase linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/pre-rebase -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/pre-rebase 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/pre-rebase 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,150 @@ -++#!/bin/sh -++# -++# Copyright (c) 2006 Junio C Hamano -++# -++ -++publish=next -++basebranch="$1" -++if test "$#" = 2 -++then -++ topic="refs/heads/$2" -++else -++ topic=`git symbolic-ref HEAD` -++fi -++ -++case "$basebranch,$topic" in -++master,refs/heads/??/*) -++ ;; -++*) -++ exit 0 ;# we do not interrupt others. -++ ;; -++esac -++ -++# Now we are dealing with a topic branch being rebased -++# on top of master. Is it OK to rebase it? -++ -++# Is topic fully merged to master? -++not_in_master=`git-rev-list --pretty=oneline ^master "$topic"` -++if test -z "$not_in_master" -++then -++ echo >&2 "$topic is fully merged to master; better remove it." -++ exit 1 ;# we could allow it, but there is no point. -++fi -++ -++# Is topic ever merged to next? If so you should not be rebasing it. -++only_next_1=`git-rev-list ^master "^$topic" ${publish} | sort` -++only_next_2=`git-rev-list ^master ${publish} | sort` -++if test "$only_next_1" = "$only_next_2" -++then -++ not_in_topic=`git-rev-list "^$topic" master` -++ if test -z "$not_in_topic" -++ then -++ echo >&2 "$topic is already up-to-date with master" -++ exit 1 ;# we could allow it, but there is no point. -++ else -++ exit 0 -++ fi -++else -++ not_in_next=`git-rev-list --pretty=oneline ^${publish} "$topic"` -++ perl -e ' -++ my $topic = $ARGV[0]; -++ my $msg = "* $topic has commits already merged to public branch:\n"; -++ my (%not_in_next) = map { -++ /^([0-9a-f]+) /; -++ ($1 => 1); -++ } split(/\n/, $ARGV[1]); -++ for my $elem (map { -++ /^([0-9a-f]+) (.*)$/; -++ [$1 => $2]; -++ } split(/\n/, $ARGV[2])) { -++ if (!exists $not_in_next{$elem->[0]}) { -++ if ($msg) { -++ print STDERR $msg; -++ undef $msg; -++ } -++ print STDERR " $elem->[1]\n"; -++ } -++ } -++ ' "$topic" "$not_in_next" "$not_in_master" -++ exit 1 -++fi -++ -++exit 0 -++ -++################################################################ -++ -++This sample hook safeguards topic branches that have been -++published from being rewound. -++ -++The workflow assumed here is: -++ -++ * Once a topic branch forks from "master", "master" is never -++ merged into it again (either directly or indirectly). -++ -++ * Once a topic branch is fully cooked and merged into "master", -++ it is deleted. If you need to build on top of it to correct -++ earlier mistakes, a new topic branch is created by forking at -++ the tip of the "master". This is not strictly necessary, but -++ it makes it easier to keep your history simple. -++ -++ * Whenever you need to test or publish your changes to topic -++ branches, merge them into "next" branch. -++ -++The script, being an example, hardcodes the publish branch name -++to be "next", but it is trivial to make it configurable via -++$GIT_DIR/config mechanism. -++ -++With this workflow, you would want to know: -++ -++(1) ... if a topic branch has ever been merged to "next". Young -++ topic branches can have stupid mistakes you would rather -++ clean up before publishing, and things that have not been -++ merged into other branches can be easily rebased without -++ affecting other people. But once it is published, you would -++ not want to rewind it. -++ -++(2) ... if a topic branch has been fully merged to "master". -++ Then you can delete it. More importantly, you should not -++ build on top of it -- other people may already want to -++ change things related to the topic as patches against your -++ "master", so if you need further changes, it is better to -++ fork the topic (perhaps with the same name) afresh from the -++ tip of "master". -++ -++Let's look at this example: -++ -++ o---o---o---o---o---o---o---o---o---o "next" -++ / / / / -++ / a---a---b A / / -++ / / / / -++ / / c---c---c---c B / -++ / / / \ / -++ / / / b---b C \ / -++ / / / / \ / -++ ---o---o---o---o---o---o---o---o---o---o---o "master" -++ -++ -++A, B and C are topic branches. -++ -++ * A has one fix since it was merged up to "next". -++ -++ * B has finished. It has been fully merged up to "master" and "next", -++ and is ready to be deleted. -++ -++ * C has not merged to "next" at all. -++ -++We would want to allow C to be rebased, refuse A, and encourage -++B to be deleted. -++ -++To compute (1): -++ -++ git-rev-list ^master ^topic next -++ git-rev-list ^master next -++ -++ if these match, topic has not merged in next at all. -++ -++To compute (2): -++ -++ git-rev-list master..topic -++ -++ if this is empty, it is fully merged to "master". -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/prepare-commit-msg linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/prepare-commit-msg -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/prepare-commit-msg 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/prepare-commit-msg 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,36 @@ -++#!/bin/sh -++# -++# An example hook script to prepare the commit log message. -++# Called by git-commit with the name of the file that has the -++# commit message, followed by the description of the commit -++# message's source. The hook's purpose is to edit the commit -++# message file. If the hook fails with a non-zero status, -++# the commit is aborted. -++# -++# To enable this hook, make this file executable. -++ -++# This hook includes three examples. The first comments out the -++# "Conflicts:" part of a merge commit. -++# -++# The second includes the output of "git diff --name-status -r" -++# into the message, just before the "git status" output. It is -++# commented because it doesn't cope with --amend or with squashed -++# commits. -++# -++# The third example adds a Signed-off-by line to the message, that can -++# still be edited. This is rarely a good idea. -++ -++case "$2 $3" in -++ merge) -++ sed -i '/^Conflicts:/,/#/!b;s/^/# &/;s/^# #/#/' "$1" ;; -++ -++# ""|template) -++# perl -i -pe ' -++# print "\n" . `git diff --cached --name-status -r` -++# if /^#/ && $first++ == 0' "$1" ;; -++ -++ *) ;; -++esac -++ -++# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -++# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/update linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/update -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/hooks/update 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/hooks/update 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,107 @@ -++#!/bin/sh -++# -++# An example hook script to blocks unannotated tags from entering. -++# Called by git-receive-pack with arguments: refname sha1-old sha1-new -++# -++# To enable this hook, make this file executable by "chmod +x update". -++# -++# Config -++# ------ -++# hooks.allowunannotated -++# This boolean sets whether unannotated tags will be allowed into the -++# repository. By default they won't be. -++# hooks.allowdeletetag -++# This boolean sets whether deleting tags will be allowed in the -++# repository. By default they won't be. -++# hooks.allowdeletebranch -++# This boolean sets whether deleting branches will be allowed in the -++# repository. By default they won't be. -++# -++ -++# --- Command line -++refname="$1" -++oldrev="$2" -++newrev="$3" -++ -++# --- Safety check -++if [ -z "$GIT_DIR" ]; then -++ echo "Don't run this script from the command line." >&2 -++ echo " (if you want, you could supply GIT_DIR then run" >&2 -++ echo " $0 )" >&2 -++ exit 1 -++fi -++ -++if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then -++ echo "Usage: $0 " >&2 -++ exit 1 -++fi -++ -++# --- Config -++allowunannotated=$(git config --bool hooks.allowunannotated) -++allowdeletebranch=$(git config --bool hooks.allowdeletebranch) -++allowdeletetag=$(git config --bool hooks.allowdeletetag) -++ -++# check for no description -++projectdesc=$(sed -e '1q' "$GIT_DIR/description") -++if [ -z "$projectdesc" -o "$projectdesc" = "Unnamed repository; edit this file to name it for gitweb." ]; then -++ echo "*** Project description file hasn't been set" >&2 -++ exit 1 -++fi -++ -++# --- Check types -++# if $newrev is 0000...0000, it's a commit to delete a ref. -++if [ "$newrev" = "0000000000000000000000000000000000000000" ]; then -++ newrev_type=delete -++else -++ newrev_type=$(git-cat-file -t $newrev) -++fi -++ -++case "$refname","$newrev_type" in -++ refs/tags/*,commit) -++ # un-annotated tag -++ short_refname=${refname##refs/tags/} -++ if [ "$allowunannotated" != "true" ]; then -++ echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 -++ echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 -++ exit 1 -++ fi -++ ;; -++ refs/tags/*,delete) -++ # delete tag -++ if [ "$allowdeletetag" != "true" ]; then -++ echo "*** Deleting a tag is not allowed in this repository" >&2 -++ exit 1 -++ fi -++ ;; -++ refs/tags/*,tag) -++ # annotated tag -++ ;; -++ refs/heads/*,commit) -++ # branch -++ ;; -++ refs/heads/*,delete) -++ # delete branch -++ if [ "$allowdeletebranch" != "true" ]; then -++ echo "*** Deleting a branch is not allowed in this repository" >&2 -++ exit 1 -++ fi -++ ;; -++ refs/remotes/*,commit) -++ # tracking branch -++ ;; -++ refs/remotes/*,delete) -++ # delete tracking branch -++ if [ "$allowdeletebranch" != "true" ]; then -++ echo "*** Deleting a tracking branch is not allowed in this repository" >&2 -++ exit 1 -++ fi -++ ;; -++ *) -++ # Anything else (is there anything else?) -++ echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 -++ exit 1 -++ ;; -++esac -++ -++# --- Finished -++exit 0 -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/info/exclude linux-2.6.24.7/drivers/mtd/mtd-utils/.git/info/exclude -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/info/exclude 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/info/exclude 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,6 @@ -++# git-ls-files --others --exclude-from=.git/info/exclude -++# Lines that start with '#' are comments. -++# For a project mostly in C, the following would be a good set of -++# exclude patterns (uncomment them if you want to use them): -++# *.[oa] -++# *~ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/logs/HEAD linux-2.6.24.7/drivers/mtd/mtd-utils/.git/logs/HEAD -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/logs/HEAD 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/logs/HEAD 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++0000000000000000000000000000000000000000 d5f5e57b72289bb5f551a4e17be0132aa8dfb6c4 nancy 1210143725 +0800 -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/logs/refs/heads/master linux-2.6.24.7/drivers/mtd/mtd-utils/.git/logs/refs/heads/master -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/logs/refs/heads/master 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/logs/refs/heads/master 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++0000000000000000000000000000000000000000 d5f5e57b72289bb5f551a4e17be0132aa8dfb6c4 nancy 1210143725 +0800 -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/logs/refs/remotes/origin/master linux-2.6.24.7/drivers/mtd/mtd-utils/.git/logs/refs/remotes/origin/master -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/logs/refs/remotes/origin/master 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/logs/refs/remotes/origin/master 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++0000000000000000000000000000000000000000 d5f5e57b72289bb5f551a4e17be0132aa8dfb6c4 nancy 1210143724 +0800 clone: from git://git.infradead.org/mtd-utils.git -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/logs/refs/remotes/origin/origin linux-2.6.24.7/drivers/mtd/mtd-utils/.git/logs/refs/remotes/origin/origin -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/logs/refs/remotes/origin/origin 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/logs/refs/remotes/origin/origin 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++0000000000000000000000000000000000000000 7afca4241e082c23bb38a4da532cc222457ae719 nancy 1210143724 +0800 clone: from git://git.infradead.org/mtd-utils.git -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/logs/refs/remotes/origin/ubi linux-2.6.24.7/drivers/mtd/mtd-utils/.git/logs/refs/remotes/origin/ubi -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/logs/refs/remotes/origin/ubi 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/logs/refs/remotes/origin/ubi 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++0000000000000000000000000000000000000000 22f90673165489fd50c893a91051a79c1b143d2a nancy 1210143724 +0800 clone: from git://git.infradead.org/mtd-utils.git -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/objects/pack/pack-3aac9dd611b9d9b1367a74ba6217f301d746b650.keep linux-2.6.24.7/drivers/mtd/mtd-utils/.git/objects/pack/pack-3aac9dd611b9d9b1367a74ba6217f301d746b650.keep -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/objects/pack/pack-3aac9dd611b9d9b1367a74ba6217f301d746b650.keep 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/objects/pack/pack-3aac9dd611b9d9b1367a74ba6217f301d746b650.keep 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++fetch-pack 10055 on bogon -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/refs/heads/master linux-2.6.24.7/drivers/mtd/mtd-utils/.git/refs/heads/master -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/refs/heads/master 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/refs/heads/master 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++d5f5e57b72289bb5f551a4e17be0132aa8dfb6c4 -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/refs/remotes/origin/HEAD linux-2.6.24.7/drivers/mtd/mtd-utils/.git/refs/remotes/origin/HEAD -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/refs/remotes/origin/HEAD 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/refs/remotes/origin/HEAD 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++ref: refs/remotes/origin/master -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/refs/remotes/origin/master linux-2.6.24.7/drivers/mtd/mtd-utils/.git/refs/remotes/origin/master -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/refs/remotes/origin/master 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/refs/remotes/origin/master 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++d5f5e57b72289bb5f551a4e17be0132aa8dfb6c4 -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/refs/remotes/origin/origin linux-2.6.24.7/drivers/mtd/mtd-utils/.git/refs/remotes/origin/origin -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/refs/remotes/origin/origin 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/refs/remotes/origin/origin 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++7afca4241e082c23bb38a4da532cc222457ae719 -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/refs/remotes/origin/ubi linux-2.6.24.7/drivers/mtd/mtd-utils/.git/refs/remotes/origin/ubi -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.git/refs/remotes/origin/ubi 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.git/refs/remotes/origin/ubi 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++22f90673165489fd50c893a91051a79c1b143d2a -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/.gitignore linux-2.6.24.7/drivers/mtd/mtd-utils/.gitignore -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/.gitignore 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/.gitignore 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,26 @@ -++# -++# NOTE! Don't add files that are generated in specific -++# subdirectories here. Add them in the ".gitignore" file -++# in that subdirectory instead. -++# -++# Normal rules -++# -++.* -++*.o -++*.a -++*.s -++*.ko -++*.so -++*.mod.c -++*~ -++ -++# -++# Top-level generic files -++# -++ -++# -++# Generated include files -++# -++ -++# stgit generated dirs -++patches-* -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/COPYING linux-2.6.24.7/drivers/mtd/mtd-utils/COPYING -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/COPYING 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/COPYING 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,340 @@ -++ GNU GENERAL PUBLIC LICENSE -++ Version 2, June 1991 -++ -++ Copyright (C) 1989, 1991 Free Software Foundation, Inc. -++ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ Everyone is permitted to copy and distribute verbatim copies -++ of this license document, but changing it is not allowed. -++ -++ Preamble -++ -++ The licenses for most software are designed to take away your -++freedom to share and change it. By contrast, the GNU General Public -++License is intended to guarantee your freedom to share and change free -++software--to make sure the software is free for all its users. This -++General Public License applies to most of the Free Software -++Foundation's software and to any other program whose authors commit to -++using it. (Some other Free Software Foundation software is covered by -++the GNU Library General Public License instead.) You can apply it to -++your programs, too. -++ -++ When we speak of free software, we are referring to freedom, not -++price. Our General Public Licenses are designed to make sure that you -++have the freedom to distribute copies of free software (and charge for -++this service if you wish), that you receive source code or can get it -++if you want it, that you can change the software or use pieces of it -++in new free programs; and that you know you can do these things. -++ -++ To protect your rights, we need to make restrictions that forbid -++anyone to deny you these rights or to ask you to surrender the rights. -++These restrictions translate to certain responsibilities for you if you -++distribute copies of the software, or if you modify it. -++ -++ For example, if you distribute copies of such a program, whether -++gratis or for a fee, you must give the recipients all the rights that -++you have. You must make sure that they, too, receive or can get the -++source code. And you must show them these terms so they know their -++rights. -++ -++ We protect your rights with two steps: (1) copyright the software, and -++(2) offer you this license which gives you legal permission to copy, -++distribute and/or modify the software. -++ -++ Also, for each author's protection and ours, we want to make certain -++that everyone understands that there is no warranty for this free -++software. If the software is modified by someone else and passed on, we -++want its recipients to know that what they have is not the original, so -++that any problems introduced by others will not reflect on the original -++authors' reputations. -++ -++ Finally, any free program is threatened constantly by software -++patents. We wish to avoid the danger that redistributors of a free -++program will individually obtain patent licenses, in effect making the -++program proprietary. To prevent this, we have made it clear that any -++patent must be licensed for everyone's free use or not licensed at all. -++ -++ The precise terms and conditions for copying, distribution and -++modification follow. -++ -++ GNU GENERAL PUBLIC LICENSE -++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION -++ -++ 0. This License applies to any program or other work which contains -++a notice placed by the copyright holder saying it may be distributed -++under the terms of this General Public License. The "Program", below, -++refers to any such program or work, and a "work based on the Program" -++means either the Program or any derivative work under copyright law: -++that is to say, a work containing the Program or a portion of it, -++either verbatim or with modifications and/or translated into another -++language. (Hereinafter, translation is included without limitation in -++the term "modification".) Each licensee is addressed as "you". -++ -++Activities other than copying, distribution and modification are not -++covered by this License; they are outside its scope. The act of -++running the Program is not restricted, and the output from the Program -++is covered only if its contents constitute a work based on the -++Program (independent of having been made by running the Program). -++Whether that is true depends on what the Program does. -++ -++ 1. You may copy and distribute verbatim copies of the Program's -++source code as you receive it, in any medium, provided that you -++conspicuously and appropriately publish on each copy an appropriate -++copyright notice and disclaimer of warranty; keep intact all the -++notices that refer to this License and to the absence of any warranty; -++and give any other recipients of the Program a copy of this License -++along with the Program. -++ -++You may charge a fee for the physical act of transferring a copy, and -++you may at your option offer warranty protection in exchange for a fee. -++ -++ 2. You may modify your copy or copies of the Program or any portion -++of it, thus forming a work based on the Program, and copy and -++distribute such modifications or work under the terms of Section 1 -++above, provided that you also meet all of these conditions: -++ -++ a) You must cause the modified files to carry prominent notices -++ stating that you changed the files and the date of any change. -++ -++ b) You must cause any work that you distribute or publish, that in -++ whole or in part contains or is derived from the Program or any -++ part thereof, to be licensed as a whole at no charge to all third -++ parties under the terms of this License. -++ -++ c) If the modified program normally reads commands interactively -++ when run, you must cause it, when started running for such -++ interactive use in the most ordinary way, to print or display an -++ announcement including an appropriate copyright notice and a -++ notice that there is no warranty (or else, saying that you provide -++ a warranty) and that users may redistribute the program under -++ these conditions, and telling the user how to view a copy of this -++ License. (Exception: if the Program itself is interactive but -++ does not normally print such an announcement, your work based on -++ the Program is not required to print an announcement.) -++ -++These requirements apply to the modified work as a whole. If -++identifiable sections of that work are not derived from the Program, -++and can be reasonably considered independent and separate works in -++themselves, then this License, and its terms, do not apply to those -++sections when you distribute them as separate works. But when you -++distribute the same sections as part of a whole which is a work based -++on the Program, the distribution of the whole must be on the terms of -++this License, whose permissions for other licensees extend to the -++entire whole, and thus to each and every part regardless of who wrote it. -++ -++Thus, it is not the intent of this section to claim rights or contest -++your rights to work written entirely by you; rather, the intent is to -++exercise the right to control the distribution of derivative or -++collective works based on the Program. -++ -++In addition, mere aggregation of another work not based on the Program -++with the Program (or with a work based on the Program) on a volume of -++a storage or distribution medium does not bring the other work under -++the scope of this License. -++ -++ 3. You may copy and distribute the Program (or a work based on it, -++under Section 2) in object code or executable form under the terms of -++Sections 1 and 2 above provided that you also do one of the following: -++ -++ a) Accompany it with the complete corresponding machine-readable -++ source code, which must be distributed under the terms of Sections -++ 1 and 2 above on a medium customarily used for software interchange; or, -++ -++ b) Accompany it with a written offer, valid for at least three -++ years, to give any third party, for a charge no more than your -++ cost of physically performing source distribution, a complete -++ machine-readable copy of the corresponding source code, to be -++ distributed under the terms of Sections 1 and 2 above on a medium -++ customarily used for software interchange; or, -++ -++ c) Accompany it with the information you received as to the offer -++ to distribute corresponding source code. (This alternative is -++ allowed only for noncommercial distribution and only if you -++ received the program in object code or executable form with such -++ an offer, in accord with Subsection b above.) -++ -++The source code for a work means the preferred form of the work for -++making modifications to it. For an executable work, complete source -++code means all the source code for all modules it contains, plus any -++associated interface definition files, plus the scripts used to -++control compilation and installation of the executable. However, as a -++special exception, the source code distributed need not include -++anything that is normally distributed (in either source or binary -++form) with the major components (compiler, kernel, and so on) of the -++operating system on which the executable runs, unless that component -++itself accompanies the executable. -++ -++If distribution of executable or object code is made by offering -++access to copy from a designated place, then offering equivalent -++access to copy the source code from the same place counts as -++distribution of the source code, even though third parties are not -++compelled to copy the source along with the object code. -++ -++ 4. You may not copy, modify, sublicense, or distribute the Program -++except as expressly provided under this License. Any attempt -++otherwise to copy, modify, sublicense or distribute the Program is -++void, and will automatically terminate your rights under this License. -++However, parties who have received copies, or rights, from you under -++this License will not have their licenses terminated so long as such -++parties remain in full compliance. -++ -++ 5. You are not required to accept this License, since you have not -++signed it. However, nothing else grants you permission to modify or -++distribute the Program or its derivative works. These actions are -++prohibited by law if you do not accept this License. Therefore, by -++modifying or distributing the Program (or any work based on the -++Program), you indicate your acceptance of this License to do so, and -++all its terms and conditions for copying, distributing or modifying -++the Program or works based on it. -++ -++ 6. Each time you redistribute the Program (or any work based on the -++Program), the recipient automatically receives a license from the -++original licensor to copy, distribute or modify the Program subject to -++these terms and conditions. You may not impose any further -++restrictions on the recipients' exercise of the rights granted herein. -++You are not responsible for enforcing compliance by third parties to -++this License. -++ -++ 7. If, as a consequence of a court judgment or allegation of patent -++infringement or for any other reason (not limited to patent issues), -++conditions are imposed on you (whether by court order, agreement or -++otherwise) that contradict the conditions of this License, they do not -++excuse you from the conditions of this License. If you cannot -++distribute so as to satisfy simultaneously your obligations under this -++License and any other pertinent obligations, then as a consequence you -++may not distribute the Program at all. For example, if a patent -++license would not permit royalty-free redistribution of the Program by -++all those who receive copies directly or indirectly through you, then -++the only way you could satisfy both it and this License would be to -++refrain entirely from distribution of the Program. -++ -++If any portion of this section is held invalid or unenforceable under -++any particular circumstance, the balance of the section is intended to -++apply and the section as a whole is intended to apply in other -++circumstances. -++ -++It is not the purpose of this section to induce you to infringe any -++patents or other property right claims or to contest validity of any -++such claims; this section has the sole purpose of protecting the -++integrity of the free software distribution system, which is -++implemented by public license practices. Many people have made -++generous contributions to the wide range of software distributed -++through that system in reliance on consistent application of that -++system; it is up to the author/donor to decide if he or she is willing -++to distribute software through any other system and a licensee cannot -++impose that choice. -++ -++This section is intended to make thoroughly clear what is believed to -++be a consequence of the rest of this License. -++ -++ 8. If the distribution and/or use of the Program is restricted in -++certain countries either by patents or by copyrighted interfaces, the -++original copyright holder who places the Program under this License -++may add an explicit geographical distribution limitation excluding -++those countries, so that distribution is permitted only in or among -++countries not thus excluded. In such case, this License incorporates -++the limitation as if written in the body of this License. -++ -++ 9. The Free Software Foundation may publish revised and/or new versions -++of the General Public License from time to time. Such new versions will -++be similar in spirit to the present version, but may differ in detail to -++address new problems or concerns. -++ -++Each version is given a distinguishing version number. If the Program -++specifies a version number of this License which applies to it and "any -++later version", you have the option of following the terms and conditions -++either of that version or of any later version published by the Free -++Software Foundation. If the Program does not specify a version number of -++this License, you may choose any version ever published by the Free Software -++Foundation. -++ -++ 10. If you wish to incorporate parts of the Program into other free -++programs whose distribution conditions are different, write to the author -++to ask for permission. For software which is copyrighted by the Free -++Software Foundation, write to the Free Software Foundation; we sometimes -++make exceptions for this. Our decision will be guided by the two goals -++of preserving the free status of all derivatives of our free software and -++of promoting the sharing and reuse of software generally. -++ -++ NO WARRANTY -++ -++ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -++FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -++OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -++PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -++OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -++MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -++TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -++PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -++REPAIR OR CORRECTION. -++ -++ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -++WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -++REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -++INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -++OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -++TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -++YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -++PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -++POSSIBILITY OF SUCH DAMAGES. -++ -++ END OF TERMS AND CONDITIONS -++ -++ How to Apply These Terms to Your New Programs -++ -++ If you develop a new program, and you want it to be of the greatest -++possible use to the public, the best way to achieve this is to make it -++free software which everyone can redistribute and change under these terms. -++ -++ To do so, attach the following notices to the program. It is safest -++to attach them to the start of each source file to most effectively -++convey the exclusion of warranty; and each file should have at least -++the "copyright" line and a pointer to where the full notice is found. -++ -++ -++ Copyright (C) 19yy -++ -++ This program is free software; you can redistribute it and/or modify -++ it under the terms of the GNU General Public License as published by -++ the Free Software Foundation; either version 2 of the License, or -++ (at your option) any later version. -++ -++ This program is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with this program; if not, write to the Free Software -++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ -++ -++Also add information on how to contact you by electronic and paper mail. -++ -++If the program is interactive, make it output a short notice like this -++when it starts in an interactive mode: -++ -++ Gnomovision version 69, Copyright (C) 19yy name of author -++ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. -++ This is free software, and you are welcome to redistribute it -++ under certain conditions; type `show c' for details. -++ -++The hypothetical commands `show w' and `show c' should show the appropriate -++parts of the General Public License. Of course, the commands you use may -++be called something other than `show w' and `show c'; they could even be -++mouse-clicks or menu items--whatever suits your program. -++ -++You should also get your employer (if you work as a programmer) or your -++school, if any, to sign a "copyright disclaimer" for the program, if -++necessary. Here is a sample; alter the names: -++ -++ Yoyodyne, Inc., hereby disclaims all copyright interest in the program -++ `Gnomovision' (which makes passes at compilers) written by James Hacker. -++ -++ , 1 April 1989 -++ Ty Coon, President of Vice -++ -++This General Public License does not permit incorporating your program into -++proprietary programs. If your program is a subroutine library, you may -++consider it more useful to permit linking proprietary applications with the -++library. If this is what you want to do, use the GNU Library General -++Public License instead of this License. -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/MAKEDEV linux-2.6.24.7/drivers/mtd/mtd-utils/MAKEDEV -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/MAKEDEV 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/MAKEDEV 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,42 @@ -++#!/bin/bash -++ -++function mkftl () { -++ mknod /dev/ftl$1 b 44 $2 -++ for a in `seq 1 15`; do -++ mknod /dev/ftl$1$a b 44 `expr $2 + $a` -++ done -++} -++function mknftl () { -++ mknod /dev/nftl$1 b 93 $2 -++ for a in `seq 1 15`; do -++ mknod /dev/nftl$1$a b 93 `expr $2 + $a` -++ done -++} -++function mkrfd () { -++ mknod /dev/rfd$1 b 256 $2 -++ for a in `seq 1 15`; do -++ mknod /dev/rfd$1$a b 256 `expr $2 + $a` -++ done -++} -++function mkinftl () { -++ mknod /dev/inftl$1 b 96 $2 -++ for a in `seq 1 15`; do -++ mknod /dev/inftl$1$a b 96 `expr $2 + $a` -++ done -++} -++ -++M=0 -++for C in a b c d e f g h i j k l m n o p; do -++ mkftl $C $M -++ mknftl $C $M -++ mkrfd $C $M -++ mkinftl $C $M -++ let M=M+16 -++done -++ -++for a in `seq 0 16` ; do -++ mknod /dev/mtd$a c 90 `expr $a + $a` -++ mknod /dev/mtdr$a c 90 `expr $a + $a + 1` -++ mknod /dev/mtdblock$a b 31 $a -++done -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/Makefile linux-2.6.24.7/drivers/mtd/mtd-utils/Makefile -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,102 @@ -++ -++# -*- sh -*- -++ -++OPTFLAGS := -O2 -Wall -++SBINDIR=/usr/sbin -++MANDIR=/usr/share/man -++INCLUDEDIR=/usr/include -++CROSS=mipsel-linux- -++CC := $(CROSS)gcc -++CFLAGS := -I./include $(OPTFLAGS) -++ -++ifeq ($(origin CROSS),undefined) -++ BUILDDIR := . -++else -++# Remove the trailing slash to make the directory name -++ BUILDDIR := .#$(CROSS:-=) -++endif -++ -++ifeq ($(WITHOUT_XATTR), 1) -++ CFLAGS += -DWITHOUT_XATTR -++endif -++ -++#RAWTARGETS = ftl_format flash_erase flash_eraseall nanddump doc_loadbios \ -++# ftl_check mkfs.jffs2 flash_lock flash_unlock flash_info \ -++# flash_otp_info flash_otp_dump mtd_debug flashcp nandwrite nandtest \ -++# jffs2dump \ -++# nftldump nftl_format docfdisk \ -++# rfddump rfdformat \ -++# serve_image recv_image \ -++# sumtool #jffs2reader -++ -++RAWTARGETS = flash_erase flash_eraseall nanddump nanddump_vfat \ -++ flash_info \ -++ flash_otp_info flash_otp_dump nandwrite nandwrite_mlc \ -++ nandtest \ -++ sumtool #jffs2reader -++ -++TARGETS = $(foreach target,$(RAWTARGETS),$(BUILDDIR)/$(target)) -++ -++SYMLINKS = -++ -++%: %.o -++ $(CC) $(CFLAGS) $(LDFLAGS) -g -o $@ $^ -++ -++$(BUILDDIR)/%.o: %.c -++ mkdir -p $(BUILDDIR) -++ $(CC) $(CFLAGS) -g -c -o $@ $< -g -Wp,-MD,$(BUILDDIR)/.$( ${DESTDIR}/${MANDIR}/man1/mkfs.jffs2.1.gz -++ make -C $(BUILDDIR)/ubi-utils install -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/compr.c linux-2.6.24.7/drivers/mtd/mtd-utils/compr.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/compr.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/compr.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,538 @@ -++/* -++ * JFFS2 -- Journalling Flash File System, Version 2. -++ * -++ * Copyright (C) 2004 Ferenc Havasi , -++ * University of Szeged, Hungary -++ * -++ * For licensing information, see the file 'LICENCE' in this directory -++ * in the jffs2 directory. -++ */ -++ -++#include "compr.h" -++#include -++#include -++#include -++ -++#define FAVOUR_LZO_PERCENT 80 -++ -++extern int page_size; -++ -++/* LIST IMPLEMENTATION (from linux/list.h) */ -++ -++#define LIST_HEAD_INIT(name) { &(name), &(name) } -++ -++#define LIST_HEAD(name) \ -++ struct list_head name = LIST_HEAD_INIT(name) -++ -++static inline void __list_add(struct list_head *new, -++ struct list_head *prev, -++ struct list_head *next) -++{ -++ next->prev = new; -++ new->next = next; -++ new->prev = prev; -++ prev->next = new; -++} -++ -++static inline void list_add(struct list_head *new, struct list_head *head) -++{ -++ __list_add(new, head, head->next); -++} -++ -++static inline void list_add_tail(struct list_head *new, struct list_head *head) -++{ -++ __list_add(new, head->prev, head); -++} -++ -++static inline void __list_del(struct list_head *prev, struct list_head *next) -++{ -++ next->prev = prev; -++ prev->next = next; -++} -++ -++static inline void list_del(struct list_head *entry) -++{ -++ __list_del(entry->prev, entry->next); -++ entry->next = (void *) 0; -++ entry->prev = (void *) 0; -++} -++ -++#define list_entry(ptr, type, member) \ -++ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) -++ -++#define list_for_each_entry(pos, head, member) \ -++ for (pos = list_entry((head)->next, typeof(*pos), member); \ -++ &pos->member != (head); \ -++ pos = list_entry(pos->member.next, typeof(*pos), member)) -++ -++ -++/* Available compressors are on this list */ -++static LIST_HEAD(jffs2_compressor_list); -++ -++/* Actual compression mode */ -++static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY; -++ -++void jffs2_set_compression_mode(int mode) -++{ -++ jffs2_compression_mode = mode; -++} -++ -++int jffs2_get_compression_mode(void) -++{ -++ return jffs2_compression_mode; -++} -++ -++/* Statistics for blocks stored without compression */ -++static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0; -++ -++/* Compression test stuffs */ -++ -++static int jffs2_compression_check = 0; -++ -++static unsigned char *jffs2_compression_check_buf = NULL; -++ -++void jffs2_compression_check_set(int yesno) -++{ -++ jffs2_compression_check = yesno; -++} -++ -++int jffs2_compression_check_get(void) -++{ -++ return jffs2_compression_check; -++} -++ -++static int jffs2_error_cnt = 0; -++ -++int jffs2_compression_check_errorcnt_get(void) -++{ -++ return jffs2_error_cnt; -++} -++ -++#define JFFS2_BUFFER_FILL 0x55 -++ -++/* Called before compression (if compression_check is setted) to prepare -++ the buffer for buffer overflow test */ -++static void jffs2_decompression_test_prepare(unsigned char *buf, int size) -++{ -++ memset(buf,JFFS2_BUFFER_FILL,size+1); -++} -++ -++/* Called after compression (if compression_check is setted) to test the result */ -++static void jffs2_decompression_test(struct jffs2_compressor *compr, -++ unsigned char *data_in, unsigned char *output_buf, -++ uint32_t cdatalen, uint32_t datalen, uint32_t buf_size) -++{ -++ uint32_t i; -++ -++ /* buffer overflow test */ -++ for (i=buf_size;i>cdatalen;i--) { -++ if (output_buf[i]!=JFFS2_BUFFER_FILL) { -++ fprintf(stderr,"COMPR_ERROR: buffer overflow at %s. " -++ "(bs=%d csize=%d b[%d]=%d)\n", compr->name, -++ buf_size, cdatalen, i, (int)(output_buf[i])); -++ jffs2_error_cnt++; -++ return; -++ } -++ } -++ /* allocing temporary buffer for decompression */ -++ if (!jffs2_compression_check_buf) { -++ jffs2_compression_check_buf = malloc(page_size); -++ if (!jffs2_compression_check_buf) { -++ fprintf(stderr,"No memory for buffer allocation. Compression check disabled.\n"); -++ jffs2_compression_check = 0; -++ return; -++ } -++ } -++ /* decompressing */ -++ if (!compr->decompress) { -++ fprintf(stderr,"JFFS2 compression check: there is no decompress function at %s.\n", compr->name); -++ jffs2_error_cnt++; -++ return; -++ } -++ if (compr->decompress(output_buf,jffs2_compression_check_buf,cdatalen,datalen,NULL)) { -++ fprintf(stderr,"JFFS2 compression check: decompression failed at %s.\n", compr->name); -++ jffs2_error_cnt++; -++ } -++ /* validate decompression */ -++ else { -++ for (i=0;iname, i); -++ jffs2_error_cnt++; -++ break; -++ } -++ } -++ } -++} -++ -++/* -++ * Return 1 to use this compression -++ */ -++static int jffs2_is_best_compression(struct jffs2_compressor *this, -++ struct jffs2_compressor *best, uint32_t size, uint32_t bestsize) -++{ -++ switch (jffs2_compression_mode) { -++ case JFFS2_COMPR_MODE_SIZE: -++ if (bestsize > size) -++ return 1; -++ return 0; -++ case JFFS2_COMPR_MODE_FAVOURLZO: -++ if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > size)) -++ return 1; -++ if ((best->compr != JFFS2_COMPR_LZO) && (bestsize > size)) -++ return 1; -++ if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > (size * FAVOUR_LZO_PERCENT / 100))) -++ return 1; -++ if ((bestsize * FAVOUR_LZO_PERCENT / 100) > size) -++ return 1; -++ -++ return 0; -++ } -++ /* Shouldn't happen */ -++ return 0; -++} -++ -++/* jffs2_compress: -++ * @data: Pointer to uncompressed data -++ * @cdata: Pointer to returned pointer to buffer for compressed data -++ * @datalen: On entry, holds the amount of data available for compression. -++ * On exit, expected to hold the amount of data actually compressed. -++ * @cdatalen: On entry, holds the amount of space available for compressed -++ * data. On exit, expected to hold the actual size of the compressed -++ * data. -++ * -++ * Returns: Lower byte to be stored with data indicating compression type used. -++ * Zero is used to show that the data could not be compressed - the -++ * compressed version was actually larger than the original. -++ * Upper byte will be used later. (soon) -++ * -++ * If the cdata buffer isn't large enough to hold all the uncompressed data, -++ * jffs2_compress should compress as much as will fit, and should set -++ * *datalen accordingly to show the amount of data which were compressed. -++ */ -++uint16_t jffs2_compress( unsigned char *data_in, unsigned char **cpage_out, -++ uint32_t *datalen, uint32_t *cdatalen) -++{ -++ int ret = JFFS2_COMPR_NONE; -++ int compr_ret; -++ struct jffs2_compressor *this, *best=NULL; -++ unsigned char *output_buf = NULL, *tmp_buf; -++ uint32_t orig_slen, orig_dlen; -++ uint32_t best_slen=0, best_dlen=0; -++ -++ switch (jffs2_compression_mode) { -++ case JFFS2_COMPR_MODE_NONE: -++ break; -++ case JFFS2_COMPR_MODE_PRIORITY: -++ orig_slen = *datalen; -++ orig_dlen = *cdatalen; -++ output_buf = malloc(orig_dlen+jffs2_compression_check); -++ if (!output_buf) { -++ fprintf(stderr,"mkfs.jffs2: No memory for compressor allocation. Compression failed.\n"); -++ goto out; -++ } -++ list_for_each_entry(this, &jffs2_compressor_list, list) { -++ /* Skip decompress-only backwards-compatibility and disabled modules */ -++ if ((!this->compress)||(this->disabled)) -++ continue; -++ -++ this->usecount++; -++ -++ if (jffs2_compression_check) /*preparing output buffer for testing buffer overflow */ -++ jffs2_decompression_test_prepare(output_buf, orig_dlen); -++ -++ *datalen = orig_slen; -++ *cdatalen = orig_dlen; -++ compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL); -++ this->usecount--; -++ if (!compr_ret) { -++ ret = this->compr; -++ this->stat_compr_blocks++; -++ this->stat_compr_orig_size += *datalen; -++ this->stat_compr_new_size += *cdatalen; -++ if (jffs2_compression_check) -++ jffs2_decompression_test(this, data_in, output_buf, *cdatalen, *datalen, orig_dlen); -++ break; -++ } -++ } -++ if (ret == JFFS2_COMPR_NONE) free(output_buf); -++ break; -++ case JFFS2_COMPR_MODE_FAVOURLZO: -++ case JFFS2_COMPR_MODE_SIZE: -++ orig_slen = *datalen; -++ orig_dlen = *cdatalen; -++ list_for_each_entry(this, &jffs2_compressor_list, list) { -++ uint32_t needed_buf_size; -++ -++ if (jffs2_compression_mode == JFFS2_COMPR_MODE_FAVOURLZO) -++ needed_buf_size = orig_slen + jffs2_compression_check; -++ else -++ needed_buf_size = orig_dlen + jffs2_compression_check; -++ -++ /* Skip decompress-only backwards-compatibility and disabled modules */ -++ if ((!this->compress)||(this->disabled)) -++ continue; -++ /* Allocating memory for output buffer if necessary */ -++ if ((this->compr_buf_size < needed_buf_size) && (this->compr_buf)) { -++ free(this->compr_buf); -++ this->compr_buf_size=0; -++ this->compr_buf=NULL; -++ } -++ if (!this->compr_buf) { -++ tmp_buf = malloc(needed_buf_size); -++ if (!tmp_buf) { -++ fprintf(stderr,"mkfs.jffs2: No memory for compressor allocation. (%d bytes)\n",orig_dlen); -++ continue; -++ } -++ else { -++ this->compr_buf = tmp_buf; -++ this->compr_buf_size = orig_dlen; -++ } -++ } -++ this->usecount++; -++ if (jffs2_compression_check) /*preparing output buffer for testing buffer overflow */ -++ jffs2_decompression_test_prepare(this->compr_buf,this->compr_buf_size); -++ *datalen = orig_slen; -++ *cdatalen = orig_dlen; -++ compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL); -++ this->usecount--; -++ if (!compr_ret) { -++ if (jffs2_compression_check) -++ jffs2_decompression_test(this, data_in, this->compr_buf, *cdatalen, *datalen, this->compr_buf_size); -++ if (((!best_dlen) || jffs2_is_best_compression(this, best, *cdatalen, best_dlen)) -++ && (*cdatalen < *datalen)) { -++ best_dlen = *cdatalen; -++ best_slen = *datalen; -++ best = this; -++ } -++ } -++ } -++ if (best_dlen) { -++ *cdatalen = best_dlen; -++ *datalen = best_slen; -++ output_buf = best->compr_buf; -++ best->compr_buf = NULL; -++ best->compr_buf_size = 0; -++ best->stat_compr_blocks++; -++ best->stat_compr_orig_size += best_slen; -++ best->stat_compr_new_size += best_dlen; -++ ret = best->compr; -++ } -++ break; -++ default: -++ fprintf(stderr,"mkfs.jffs2: unknow compression mode.\n"); -++ } -++out: -++ if (ret == JFFS2_COMPR_NONE) { -++ *cpage_out = data_in; -++ *datalen = *cdatalen; -++ none_stat_compr_blocks++; -++ none_stat_compr_size += *datalen; -++ } -++ else { -++ *cpage_out = output_buf; -++ } -++ return ret; -++} -++ -++ -++int jffs2_register_compressor(struct jffs2_compressor *comp) -++{ -++ struct jffs2_compressor *this; -++ -++ if (!comp->name) { -++ fprintf(stderr,"NULL compressor name at registering JFFS2 compressor. Failed.\n"); -++ return -1; -++ } -++ comp->compr_buf_size=0; -++ comp->compr_buf=NULL; -++ comp->usecount=0; -++ comp->stat_compr_orig_size=0; -++ comp->stat_compr_new_size=0; -++ comp->stat_compr_blocks=0; -++ comp->stat_decompr_blocks=0; -++ -++ list_for_each_entry(this, &jffs2_compressor_list, list) { -++ if (this->priority < comp->priority) { -++ list_add(&comp->list, this->list.prev); -++ goto out; -++ } -++ } -++ list_add_tail(&comp->list, &jffs2_compressor_list); -++out: -++ return 0; -++} -++ -++int jffs2_unregister_compressor(struct jffs2_compressor *comp) -++{ -++ -++ if (comp->usecount) { -++ fprintf(stderr,"mkfs.jffs2: Compressor modul is in use. Unregister failed.\n"); -++ return -1; -++ } -++ list_del(&comp->list); -++ -++ return 0; -++} -++ -++#define JFFS2_STAT_BUF_SIZE 16000 -++ -++char *jffs2_list_compressors(void) -++{ -++ struct jffs2_compressor *this; -++ char *buf, *act_buf; -++ -++ act_buf = buf = malloc(JFFS2_STAT_BUF_SIZE); -++ list_for_each_entry(this, &jffs2_compressor_list, list) { -++ act_buf += sprintf(act_buf, "%10s priority:%d ", this->name, this->priority); -++ if ((this->disabled)||(!this->compress)) -++ act_buf += sprintf(act_buf,"disabled"); -++ else -++ act_buf += sprintf(act_buf,"enabled"); -++ act_buf += sprintf(act_buf,"\n"); -++ } -++ return buf; -++} -++ -++char *jffs2_stats(void) -++{ -++ struct jffs2_compressor *this; -++ char *buf, *act_buf; -++ -++ act_buf = buf = malloc(JFFS2_STAT_BUF_SIZE); -++ -++ act_buf += sprintf(act_buf,"Compression mode: "); -++ switch (jffs2_compression_mode) { -++ case JFFS2_COMPR_MODE_NONE: -++ act_buf += sprintf(act_buf,"none"); -++ break; -++ case JFFS2_COMPR_MODE_PRIORITY: -++ act_buf += sprintf(act_buf,"priority"); -++ break; -++ case JFFS2_COMPR_MODE_SIZE: -++ act_buf += sprintf(act_buf,"size"); -++ break; -++ case JFFS2_COMPR_MODE_FAVOURLZO: -++ act_buf += sprintf(act_buf, "favourlzo"); -++ break; -++ default: -++ act_buf += sprintf(act_buf,"unkown"); -++ break; -++ } -++ act_buf += sprintf(act_buf,"\nCompressors:\n"); -++ act_buf += sprintf(act_buf,"%10s ","none"); -++ act_buf += sprintf(act_buf,"compr: %d blocks (%d) decompr: %d blocks\n", none_stat_compr_blocks, -++ none_stat_compr_size, none_stat_decompr_blocks); -++ list_for_each_entry(this, &jffs2_compressor_list, list) { -++ act_buf += sprintf(act_buf,"%10s (prio:%d) ",this->name,this->priority); -++ if ((this->disabled)||(!this->compress)) -++ act_buf += sprintf(act_buf,"- "); -++ else -++ act_buf += sprintf(act_buf,"+ "); -++ act_buf += sprintf(act_buf,"compr: %d blocks (%d/%d) decompr: %d blocks ", this->stat_compr_blocks, -++ this->stat_compr_new_size, this->stat_compr_orig_size, -++ this->stat_decompr_blocks); -++ act_buf += sprintf(act_buf,"\n"); -++ } -++ return buf; -++} -++ -++int jffs2_set_compression_mode_name(const char *name) -++{ -++ if (!strcmp("none",name)) { -++ jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; -++ return 0; -++ } -++ if (!strcmp("priority",name)) { -++ jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY; -++ return 0; -++ } -++ if (!strcmp("size",name)) { -++ jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE; -++ return 0; -++ } -++ if (!strcmp("favourlzo", name)) { -++ jffs2_compression_mode = JFFS2_COMPR_MODE_FAVOURLZO; -++ return 0; -++ } -++ -++ return 1; -++} -++ -++static int jffs2_compressor_Xable(const char *name, int disabled) -++{ -++ struct jffs2_compressor *this; -++ list_for_each_entry(this, &jffs2_compressor_list, list) { -++ if (!strcmp(this->name, name)) { -++ this->disabled = disabled; -++ return 0; -++ } -++ } -++ return 1; -++} -++ -++int jffs2_enable_compressor_name(const char *name) -++{ -++ return jffs2_compressor_Xable(name, 0); -++} -++ -++int jffs2_disable_compressor_name(const char *name) -++{ -++ return jffs2_compressor_Xable(name, 1); -++} -++ -++int jffs2_set_compressor_priority(const char *name, int priority) -++{ -++ struct jffs2_compressor *this,*comp; -++ list_for_each_entry(this, &jffs2_compressor_list, list) { -++ if (!strcmp(this->name, name)) { -++ this->priority = priority; -++ comp = this; -++ goto reinsert; -++ } -++ } -++ fprintf(stderr,"mkfs.jffs2: compressor %s not found.\n",name); -++ return 1; -++reinsert: -++ /* list is sorted in the order of priority, so if -++ we change it we have to reinsert it into the -++ good place */ -++ list_del(&comp->list); -++ list_for_each_entry(this, &jffs2_compressor_list, list) { -++ if (this->priority < comp->priority) { -++ list_add(&comp->list, this->list.prev); -++ return 0; -++ } -++ } -++ list_add_tail(&comp->list, &jffs2_compressor_list); -++ return 0; -++} -++ -++ -++int jffs2_compressors_init(void) -++{ -++#ifdef CONFIG_JFFS2_ZLIB -++ jffs2_zlib_init(); -++#endif -++#ifdef CONFIG_JFFS2_RTIME -++ jffs2_rtime_init(); -++#endif -++#ifdef CONFIG_JFFS2_LZO -++ jffs2_lzo_init(); -++#endif -++ return 0; -++} -++ -++int jffs2_compressors_exit(void) -++{ -++#ifdef CONFIG_JFFS2_RTIME -++ jffs2_rtime_exit(); -++#endif -++#ifdef CONFIG_JFFS2_ZLIB -++ jffs2_zlib_exit(); -++#endif -++#ifdef CONFIG_JFFS2_LZO -++ jffs2_lzo_exit(); -++#endif -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/compr.h linux-2.6.24.7/drivers/mtd/mtd-utils/compr.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/compr.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/compr.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,119 @@ -++/* -++ * JFFS2 -- Journalling Flash File System, Version 2. -++ * -++ * Copyright (C) 2004 Ferenc Havasi , -++ * University of Szeged, Hungary -++ * -++ * For licensing information, see the file 'LICENCE' in the -++ * jffs2 directory. -++ */ -++ -++#ifndef __JFFS2_COMPR_H__ -++#define __JFFS2_COMPR_H__ -++ -++#include -++#include -++#include -++#include "linux/jffs2.h" -++ -++#define CONFIG_JFFS2_ZLIB -++#define CONFIG_JFFS2_RTIME -++#define CONFIG_JFFS2_LZO -++ -++#define JFFS2_RUBINMIPS_PRIORITY 10 -++#define JFFS2_DYNRUBIN_PRIORITY 20 -++#define JFFS2_RTIME_PRIORITY 50 -++#define JFFS2_ZLIB_PRIORITY 60 -++#define JFFS2_LZO_PRIORITY 80 -++ -++#define JFFS2_COMPR_MODE_NONE 0 -++#define JFFS2_COMPR_MODE_PRIORITY 1 -++#define JFFS2_COMPR_MODE_SIZE 2 -++#define JFFS2_COMPR_MODE_FAVOURLZO 3 -++ -++#define kmalloc(a,b) malloc(a) -++#define kfree(a) free(a) -++#ifndef GFP_KERNEL -++#define GFP_KERNEL 0 -++#endif -++ -++#define vmalloc(a) malloc(a) -++#define vfree(a) free(a) -++ -++#define printk(...) fprintf(stderr,__VA_ARGS__) -++ -++#define KERN_EMERG -++#define KERN_ALERT -++#define KERN_CRIT -++#define KERN_ERR -++#define KERN_WARNING -++#define KERN_NOTICE -++#define KERN_INFO -++#define KERN_DEBUG -++ -++struct list_head { -++ struct list_head *next, *prev; -++}; -++ -++void jffs2_set_compression_mode(int mode); -++int jffs2_get_compression_mode(void); -++int jffs2_set_compression_mode_name(const char *mode_name); -++ -++int jffs2_enable_compressor_name(const char *name); -++int jffs2_disable_compressor_name(const char *name); -++ -++int jffs2_set_compressor_priority(const char *name, int priority); -++ -++struct jffs2_compressor { -++ struct list_head list; -++ int priority; /* used by prirority comr. mode */ -++ char *name; -++ char compr; /* JFFS2_COMPR_XXX */ -++ int (*compress)(unsigned char *data_in, unsigned char *cpage_out, -++ uint32_t *srclen, uint32_t *destlen, void *model); -++ int (*decompress)(unsigned char *cdata_in, unsigned char *data_out, -++ uint32_t cdatalen, uint32_t datalen, void *model); -++ int usecount; -++ int disabled; /* if seted the compressor won't compress */ -++ unsigned char *compr_buf; /* used by size compr. mode */ -++ uint32_t compr_buf_size; /* used by size compr. mode */ -++ uint32_t stat_compr_orig_size; -++ uint32_t stat_compr_new_size; -++ uint32_t stat_compr_blocks; -++ uint32_t stat_decompr_blocks; -++}; -++ -++int jffs2_register_compressor(struct jffs2_compressor *comp); -++int jffs2_unregister_compressor(struct jffs2_compressor *comp); -++ -++int jffs2_compressors_init(void); -++int jffs2_compressors_exit(void); -++ -++uint16_t jffs2_compress(unsigned char *data_in, unsigned char **cpage_out, -++ uint32_t *datalen, uint32_t *cdatalen); -++ -++/* If it is setted, a decompress will be called after every compress */ -++void jffs2_compression_check_set(int yesno); -++int jffs2_compression_check_get(void); -++int jffs2_compression_check_errorcnt_get(void); -++ -++char *jffs2_list_compressors(void); -++char *jffs2_stats(void); -++ -++/* Compressor modules */ -++ -++/* These functions will be called by jffs2_compressors_init/exit */ -++#ifdef CONFIG_JFFS2_ZLIB -++int jffs2_zlib_init(void); -++void jffs2_zlib_exit(void); -++#endif -++#ifdef CONFIG_JFFS2_RTIME -++int jffs2_rtime_init(void); -++void jffs2_rtime_exit(void); -++#endif -++#ifdef CONFIG_JFFS2_LZO -++int jffs2_lzo_init(void); -++void jffs2_lzo_exit(void); -++#endif -++ -++#endif /* __JFFS2_COMPR_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/compr_lzo.c linux-2.6.24.7/drivers/mtd/mtd-utils/compr_lzo.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/compr_lzo.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/compr_lzo.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,120 @@ -++/* -++ * JFFS2 LZO Compression Interface. -++ * -++ * Copyright (C) 2007 Nokia Corporation. All rights reserved. -++ * -++ * Author: Richard Purdie -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include "compr.h" -++ -++extern int page_size; -++ -++static void *lzo_mem; -++static void *lzo_compress_buf; -++ -++/* -++ * Note about LZO compression. -++ * -++ * We want to use the _999_ compression routine which gives better compression -++ * rates at the expense of time. Decompression time is unaffected. We might as -++ * well use the standard lzo library routines for this but they will overflow -++ * the destination buffer since they don't check the destination size. -++ * -++ * We therefore compress to a temporary buffer and copy if it will fit. -++ * -++ */ -++static int jffs2_lzo_cmpr(unsigned char *data_in, unsigned char *cpage_out, -++ uint32_t *sourcelen, uint32_t *dstlen, void *model) -++{ -++ uint32_t compress_size; -++ int ret; -++ -++ ret = lzo1x_999_compress(data_in, *sourcelen, lzo_compress_buf, &compress_size, lzo_mem); -++ -++ if (ret != LZO_E_OK) -++ return -1; -++ -++ if (compress_size > *dstlen) -++ return -1; -++ -++ memcpy(cpage_out, lzo_compress_buf, compress_size); -++ *dstlen = compress_size; -++ -++ return 0; -++} -++ -++static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out, -++ uint32_t srclen, uint32_t destlen, void *model) -++{ -++ int ret; -++ uint32_t dl; -++ -++ ret = lzo1x_decompress_safe(data_in,srclen,cpage_out,&dl,NULL); -++ -++ if (ret != LZO_E_OK || dl != destlen) -++ return -1; -++ -++ return 0; -++} -++ -++static struct jffs2_compressor jffs2_lzo_comp = { -++ .priority = JFFS2_LZO_PRIORITY, -++ .name = "lzo", -++ .compr = JFFS2_COMPR_LZO, -++ .compress = &jffs2_lzo_cmpr, -++ .decompress = &jffs2_lzo_decompress, -++ .disabled = 1, -++}; -++ -++int jffs2_lzo_init(void) -++{ -++ int ret; -++ -++ lzo_mem = malloc(LZO1X_999_MEM_COMPRESS); -++ if (!lzo_mem) -++ return -1; -++ -++ /* Worse case LZO compression size from their FAQ */ -++ lzo_compress_buf = malloc(page_size + (page_size / 16) + 64 + 3); -++ if (!lzo_compress_buf) { -++ free(lzo_mem); -++ return -1; -++ } -++ -++ ret = jffs2_register_compressor(&jffs2_lzo_comp); -++ if (ret < 0) { -++ free(lzo_compress_buf); -++ free(lzo_mem); -++ } -++ -++ return ret; -++} -++ -++void jffs2_lzo_exit(void) -++{ -++ jffs2_unregister_compressor(&jffs2_lzo_comp); -++ free(lzo_compress_buf); -++ free(lzo_mem); -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/compr_rtime.c linux-2.6.24.7/drivers/mtd/mtd-utils/compr_rtime.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/compr_rtime.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/compr_rtime.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,119 @@ -++/* -++ * JFFS2 -- Journalling Flash File System, Version 2. -++ * -++ * Copyright (C) 2001-2003 Red Hat, Inc. -++ * -++ * Created by Arjan van de Ven -++ * -++ * For licensing information, see the file 'LICENCE' in this directory. -++ * -++ * Very simple lz77-ish encoder. -++ * -++ * Theory of operation: Both encoder and decoder have a list of "last -++ * occurrences" for every possible source-value; after sending the -++ * first source-byte, the second byte indicated the "run" length of -++ * matches -++ * -++ * The algorithm is intended to only send "whole bytes", no bit-messing. -++ * -++ */ -++ -++#include -++#include -++#include "compr.h" -++ -++/* _compress returns the compressed size, -1 if bigger */ -++static int jffs2_rtime_compress(unsigned char *data_in, unsigned char *cpage_out, -++ uint32_t *sourcelen, uint32_t *dstlen, void *model) -++{ -++ short positions[256]; -++ int outpos = 0; -++ int pos=0; -++ -++ memset(positions,0,sizeof(positions)); -++ -++ while (pos < (*sourcelen) && outpos <= (*dstlen)-2) { -++ int backpos, runlen=0; -++ unsigned char value; -++ -++ value = data_in[pos]; -++ -++ cpage_out[outpos++] = data_in[pos++]; -++ -++ backpos = positions[value]; -++ positions[value]=pos; -++ -++ while ((backpos < pos) && (pos < (*sourcelen)) && -++ (data_in[pos]==data_in[backpos++]) && (runlen<255)) { -++ pos++; -++ runlen++; -++ } -++ cpage_out[outpos++] = runlen; -++ } -++ -++ if (outpos >= pos) { -++ /* We failed */ -++ return -1; -++ } -++ -++ /* Tell the caller how much we managed to compress, and how much space it took */ -++ *sourcelen = pos; -++ *dstlen = outpos; -++ return 0; -++} -++ -++ -++static int jffs2_rtime_decompress(unsigned char *data_in, unsigned char *cpage_out, -++ uint32_t srclen, uint32_t destlen, void *model) -++{ -++ short positions[256]; -++ int outpos = 0; -++ int pos=0; -++ -++ memset(positions,0,sizeof(positions)); -++ -++ while (outpos= outpos) { -++ while(repeat) { -++ cpage_out[outpos++] = cpage_out[backoffs++]; -++ repeat--; -++ } -++ } else { -++ memcpy(&cpage_out[outpos],&cpage_out[backoffs],repeat); -++ outpos+=repeat; -++ } -++ } -++ } -++ return 0; -++} -++ -++ -++static struct jffs2_compressor jffs2_rtime_comp = { -++ .priority = JFFS2_RTIME_PRIORITY, -++ .name = "rtime", -++ .disabled = 0, -++ .compr = JFFS2_COMPR_RTIME, -++ .compress = &jffs2_rtime_compress, -++ .decompress = &jffs2_rtime_decompress, -++}; -++ -++int jffs2_rtime_init(void) -++{ -++ return jffs2_register_compressor(&jffs2_rtime_comp); -++} -++ -++void jffs2_rtime_exit(void) -++{ -++ jffs2_unregister_compressor(&jffs2_rtime_comp); -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/compr_zlib.c linux-2.6.24.7/drivers/mtd/mtd-utils/compr_zlib.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/compr_zlib.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/compr_zlib.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,145 @@ -++/* -++ * JFFS2 -- Journalling Flash File System, Version 2. -++ * -++ * Copyright (C) 2001 Red Hat, Inc. -++ * -++ * Created by David Woodhouse -++ * -++ * The original JFFS, from which the design for JFFS2 was derived, -++ * was designed and implemented by Axis Communications AB. -++ * -++ * The contents of this file are subject to the Red Hat eCos Public -++ * License Version 1.1 (the "Licence"); you may not use this file -++ * except in compliance with the Licence. You may obtain a copy of -++ * the Licence at http://www.redhat.com/ -++ * -++ * Software distributed under the Licence is distributed on an "AS IS" -++ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -++ * See the Licence for the specific language governing rights and -++ * limitations under the Licence. -++ * -++ * The Original Code is JFFS2 - Journalling Flash File System, version 2 -++ * -++ * Alternatively, the contents of this file may be used under the -++ * terms of the GNU General Public License version 2 (the "GPL"), in -++ * which case the provisions of the GPL are applicable instead of the -++ * above. If you wish to allow the use of your version of this file -++ * only under the terms of the GPL and not to allow others to use your -++ * version of this file under the RHEPL, indicate your decision by -++ * deleting the provisions above and replace them with the notice and -++ * other provisions required by the GPL. If you do not delete the -++ * provisions above, a recipient may use your version of this file -++ * under either the RHEPL or the GPL. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include "compr.h" -++ -++#define min(x,y) ((x)<(y)?(x):(y)) -++ -++/* Plan: call deflate() with avail_in == *sourcelen, -++ avail_out = *dstlen - 12 and flush == Z_FINISH. -++ If it doesn't manage to finish, call it again with -++ avail_in == 0 and avail_out set to the remaining 12 -++ bytes for it to clean up. -++Q: Is 12 bytes sufficient? -++ */ -++#define STREAM_END_SPACE 12 -++ -++int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out, -++ uint32_t *sourcelen, uint32_t *dstlen, void *model) -++{ -++ z_stream strm; -++ int ret; -++ -++ if (*dstlen <= STREAM_END_SPACE) -++ return -1; -++ -++ strm.zalloc = (void *)0; -++ strm.zfree = (void *)0; -++ -++ if (Z_OK != deflateInit(&strm, 3)) { -++ return -1; -++ } -++ strm.next_in = data_in; -++ strm.total_in = 0; -++ -++ strm.next_out = cpage_out; -++ strm.total_out = 0; -++ -++ while (strm.total_out < *dstlen - STREAM_END_SPACE && strm.total_in < *sourcelen) { -++ strm.avail_out = *dstlen - (strm.total_out + STREAM_END_SPACE); -++ strm.avail_in = min((unsigned)(*sourcelen-strm.total_in), strm.avail_out); -++ ret = deflate(&strm, Z_PARTIAL_FLUSH); -++ if (ret != Z_OK) { -++ deflateEnd(&strm); -++ return -1; -++ } -++ } -++ strm.avail_out += STREAM_END_SPACE; -++ strm.avail_in = 0; -++ ret = deflate(&strm, Z_FINISH); -++ if (ret != Z_STREAM_END) { -++ deflateEnd(&strm); -++ return -1; -++ } -++ deflateEnd(&strm); -++ -++ if (strm.total_out >= strm.total_in) -++ return -1; -++ -++ -++ *dstlen = strm.total_out; -++ *sourcelen = strm.total_in; -++ return 0; -++} -++ -++int jffs2_zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, -++ uint32_t srclen, uint32_t destlen, void *model) -++{ -++ z_stream strm; -++ int ret; -++ -++ strm.zalloc = (void *)0; -++ strm.zfree = (void *)0; -++ -++ if (Z_OK != inflateInit(&strm)) { -++ return 1; -++ } -++ strm.next_in = data_in; -++ strm.avail_in = srclen; -++ strm.total_in = 0; -++ -++ strm.next_out = cpage_out; -++ strm.avail_out = destlen; -++ strm.total_out = 0; -++ -++ while((ret = inflate(&strm, Z_FINISH)) == Z_OK) -++ ; -++ -++ inflateEnd(&strm); -++ return 0; -++} -++ -++static struct jffs2_compressor jffs2_zlib_comp = { -++ .priority = JFFS2_ZLIB_PRIORITY, -++ .name = "zlib", -++ .disabled = 0, -++ .compr = JFFS2_COMPR_ZLIB, -++ .compress = &jffs2_zlib_compress, -++ .decompress = &jffs2_zlib_decompress, -++}; -++ -++int jffs2_zlib_init(void) -++{ -++ return jffs2_register_compressor(&jffs2_zlib_comp); -++} -++ -++void jffs2_zlib_exit(void) -++{ -++ jffs2_unregister_compressor(&jffs2_zlib_comp); -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/crc32.c linux-2.6.24.7/drivers/mtd/mtd-utils/crc32.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/crc32.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/crc32.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,95 @@ -++/* -++ * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or -++ * code or tables extracted from it, as desired without restriction. -++ * -++ * First, the polynomial itself and its table of feedback terms. The -++ * polynomial is -++ * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 -++ * -++ * Note that we take it "backwards" and put the highest-order term in -++ * the lowest-order bit. The X^32 term is "implied"; the LSB is the -++ * X^31 term, etc. The X^0 term (usually shown as "+1") results in -++ * the MSB being 1 -++ * -++ * Note that the usual hardware shift register implementation, which -++ * is what we're using (we're merely optimizing it by doing eight-bit -++ * chunks at a time) shifts bits into the lowest-order term. In our -++ * implementation, that means shifting towards the right. Why do we -++ * do it this way? Because the calculated CRC must be transmitted in -++ * order from highest-order term to lowest-order term. UARTs transmit -++ * characters in order from LSB to MSB. By storing the CRC this way -++ * we hand it to the UART in the order low-byte to high-byte; the UART -++ * sends each low-bit to hight-bit; and the result is transmission bit -++ * by bit from highest- to lowest-order term without requiring any bit -++ * shuffling on our part. Reception works similarly -++ * -++ * The feedback terms table consists of 256, 32-bit entries. Notes -++ * -++ * The table can be generated at runtime if desired; code to do so -++ * is shown later. It might not be obvious, but the feedback -++ * terms simply represent the results of eight shift/xor opera -++ * tions for all combinations of data and CRC register values -++ * -++ * The values must be right-shifted by eight bits by the "updcrc -++ * logic; the shift must be unsigned (bring in zeroes). On some -++ * hardware you could probably optimize the shift in assembler by -++ * using byte-swap instructions -++ * polynomial $edb88320 -++ */ -++ -++#include -++ -++const uint32_t crc32_table[256] = { -++ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, -++ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, -++ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, -++ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, -++ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, -++ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, -++ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, -++ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, -++ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, -++ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, -++ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, -++ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, -++ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, -++ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, -++ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, -++ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, -++ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, -++ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, -++ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, -++ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, -++ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, -++ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, -++ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, -++ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, -++ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, -++ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, -++ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, -++ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, -++ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, -++ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, -++ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, -++ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, -++ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, -++ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, -++ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, -++ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, -++ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, -++ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, -++ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, -++ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, -++ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, -++ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, -++ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, -++ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, -++ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, -++ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, -++ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, -++ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, -++ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, -++ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, -++ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, -++ 0x2d02ef8dL -++}; -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/crc32.h linux-2.6.24.7/drivers/mtd/mtd-utils/crc32.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/crc32.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/crc32.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,19 @@ -++#ifndef CRC32_H -++#define CRC32_H -++ -++#include -++ -++extern const uint32_t crc32_table[256]; -++ -++/* Return a 32-bit CRC of the contents of the buffer. */ -++ -++ static inline uint32_t -++crc32(uint32_t val, const void *ss, int len) -++{ -++ const unsigned char *s = ss; -++ while (--len >= 0) -++ val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8); -++ return val; -++} -++ -++#endif -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/device_table.txt linux-2.6.24.7/drivers/mtd/mtd-utils/device_table.txt -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/device_table.txt 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/device_table.txt 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,129 @@ -++# This is a sample device table file for use with mkfs.jffs2. You can -++# do all sorts of interesting things with a device table file. For -++# example, if you want to adjust the permissions on a particular file -++# you can just add an entry like: -++# /sbin/foobar f 2755 0 0 - - - - - -++# and (assuming the file /sbin/foobar exists) it will be made setuid -++# root (regardless of what its permissions are on the host filesystem. -++# -++# Device table entries take the form of: -++# -++# where name is the file name, type can be one of: -++# f A regular file -++# d Directory -++# c Character special device file -++# b Block special device file -++# p Fifo (named pipe) -++# uid is the user id for the target file, gid is the group id for the -++# target file. The rest of the entried apply only to device special -++# file. -++ -++# When building a target filesystem, it is desirable to not have to -++# become root and then run 'mknod' a thousand times. Using a device -++# table you can create device nodes and directories "on the fly". -++# Furthermore, you can use a single table entry to create a many device -++# minors. For example, if I wanted to create /dev/hda and /dev/hda[0-15] -++# I could just use the following two table entries: -++# /dev/hda b 640 0 0 3 0 0 0 - -++# /dev/hda b 640 0 0 3 1 1 1 15 -++# -++# Have fun -++# -Erik Andersen -++# -++ -++# -++/dev d 755 0 0 - - - - - -++/dev/mem c 640 0 0 1 1 0 0 - -++/dev/kmem c 640 0 0 1 2 0 0 - -++/dev/null c 640 0 0 1 3 0 0 - -++/dev/zero c 640 0 0 1 5 0 0 - -++/dev/random c 640 0 0 1 8 0 0 - -++/dev/urandom c 640 0 0 1 9 0 0 - -++/dev/tty c 666 0 0 5 0 0 0 - -++/dev/tty c 666 0 0 4 0 0 1 6 -++/dev/console c 640 0 0 5 1 0 0 - -++/dev/ram b 640 0 0 1 1 0 0 - -++/dev/ram b 640 0 0 1 0 0 1 4 -++/dev/loop b 640 0 0 7 0 0 1 2 -++/dev/ptmx c 666 0 0 5 2 0 0 - -++#/dev/ttyS c 640 0 0 4 64 0 1 4 -++#/dev/psaux c 640 0 0 10 1 0 0 - -++#/dev/rtc c 640 0 0 10 135 0 0 - -++ -++# Adjust permissions on some normal files -++#/etc/shadow f 600 0 0 - - - - - -++#/bin/tinylogin f 4755 0 0 - - - - - -++ -++# User-mode Linux stuff -++/dev/ubda b 640 0 0 98 0 0 0 - -++/dev/ubda b 640 0 0 98 1 1 1 15 -++ -++# IDE Devices -++/dev/hda b 640 0 0 3 0 0 0 - -++/dev/hda b 640 0 0 3 1 1 1 15 -++/dev/hdb b 640 0 0 3 64 0 0 - -++/dev/hdb b 640 0 0 3 65 1 1 15 -++#/dev/hdc b 640 0 0 22 0 0 0 - -++#/dev/hdc b 640 0 0 22 1 1 1 15 -++#/dev/hdd b 640 0 0 22 64 0 0 - -++#/dev/hdd b 640 0 0 22 65 1 1 15 -++#/dev/hde b 640 0 0 33 0 0 0 - -++#/dev/hde b 640 0 0 33 1 1 1 15 -++#/dev/hdf b 640 0 0 33 64 0 0 - -++#/dev/hdf b 640 0 0 33 65 1 1 15 -++#/dev/hdg b 640 0 0 34 0 0 0 - -++#/dev/hdg b 640 0 0 34 1 1 1 15 -++#/dev/hdh b 640 0 0 34 64 0 0 - -++#/dev/hdh b 640 0 0 34 65 1 1 15 -++ -++# SCSI Devices -++#/dev/sda b 640 0 0 8 0 0 0 - -++#/dev/sda b 640 0 0 8 1 1 1 15 -++#/dev/sdb b 640 0 0 8 16 0 0 - -++#/dev/sdb b 640 0 0 8 17 1 1 15 -++#/dev/sdc b 640 0 0 8 32 0 0 - -++#/dev/sdc b 640 0 0 8 33 1 1 15 -++#/dev/sdd b 640 0 0 8 48 0 0 - -++#/dev/sdd b 640 0 0 8 49 1 1 15 -++#/dev/sde b 640 0 0 8 64 0 0 - -++#/dev/sde b 640 0 0 8 65 1 1 15 -++#/dev/sdf b 640 0 0 8 80 0 0 - -++#/dev/sdf b 640 0 0 8 81 1 1 15 -++#/dev/sdg b 640 0 0 8 96 0 0 - -++#/dev/sdg b 640 0 0 8 97 1 1 15 -++#/dev/sdh b 640 0 0 8 112 0 0 - -++#/dev/sdh b 640 0 0 8 113 1 1 15 -++#/dev/sg c 640 0 0 21 0 0 1 15 -++#/dev/scd b 640 0 0 11 0 0 1 15 -++#/dev/st c 640 0 0 9 0 0 1 8 -++#/dev/nst c 640 0 0 9 128 0 1 8 -++#/dev/st c 640 0 0 9 32 1 1 4 -++#/dev/st c 640 0 0 9 64 1 1 4 -++#/dev/st c 640 0 0 9 96 1 1 4 -++ -++# Floppy disk devices -++#/dev/fd b 640 0 0 2 0 0 1 2 -++#/dev/fd0d360 b 640 0 0 2 4 0 0 - -++#/dev/fd1d360 b 640 0 0 2 5 0 0 - -++#/dev/fd0h1200 b 640 0 0 2 8 0 0 - -++#/dev/fd1h1200 b 640 0 0 2 9 0 0 - -++#/dev/fd0u1440 b 640 0 0 2 28 0 0 - -++#/dev/fd1u1440 b 640 0 0 2 29 0 0 - -++#/dev/fd0u2880 b 640 0 0 2 32 0 0 - -++#/dev/fd1u2880 b 640 0 0 2 33 0 0 - -++ -++# All the proprietary cdrom devices in the world -++#/dev/aztcd b 640 0 0 29 0 0 0 - -++#/dev/bpcd b 640 0 0 41 0 0 0 - -++#/dev/capi20 c 640 0 0 68 0 0 1 2 -++#/dev/cdu31a b 640 0 0 15 0 0 0 - -++#/dev/cdu535 b 640 0 0 24 0 0 0 - -++#/dev/cm206cd b 640 0 0 32 0 0 0 - -++#/dev/sjcd b 640 0 0 18 0 0 0 - -++#/dev/sonycd b 640 0 0 15 0 0 0 - -++#/dev/gscd b 640 0 0 16 0 0 0 - -++#/dev/sbpcd b 640 0 0 25 0 0 0 - -++#/dev/sbpcd b 640 0 0 25 0 0 1 4 -++#/dev/mcd b 640 0 0 23 0 0 0 - -++#/dev/optcd b 640 0 0 17 0 0 0 - -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/doc_loadbios.c linux-2.6.24.7/drivers/mtd/mtd-utils/doc_loadbios.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/doc_loadbios.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/doc_loadbios.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,148 @@ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++ -++unsigned char databuf[512]; -++ -++int main(int argc,char **argv) -++{ -++ mtd_info_t meminfo; -++ int ifd,ofd; -++ struct stat statbuf; -++ erase_info_t erase; -++ unsigned long retlen, ofs, iplsize, ipltailsize; -++ unsigned char *iplbuf; -++ iplbuf = NULL; -++ -++ if (argc < 3) { -++ fprintf(stderr,"You must specify a device," -++ " the source firmware file and the offset\n"); -++ return 1; -++ } -++ -++ // Open and size the device -++ if ((ofd = open(argv[1],O_RDWR)) < 0) { -++ perror("Open flash device"); -++ return 1; -++ } -++ -++ if ((ifd = open(argv[2], O_RDONLY)) < 0) { -++ perror("Open firmware file\n"); -++ close(ofd); -++ return 1; -++ } -++ -++ if (fstat(ifd, &statbuf) != 0) { -++ perror("Stat firmware file"); -++ goto error; -++ } -++ -++#if 0 -++ if (statbuf.st_size > 65536) { -++ printf("Firmware too large (%ld bytes)\n",statbuf.st_size); -++ goto error; -++ } -++#endif -++ -++ if (ioctl(ofd,MEMGETINFO,&meminfo) != 0) { -++ perror("ioctl(MEMGETINFO)"); -++ goto error; -++ } -++ -++ iplsize = (ipltailsize = 0); -++ if (argc >= 4) { -++ /* DoC Millennium has IPL in the first 1K of flash memory */ -++ /* You may want to specify the offset 1024 to store -++ the firmware next to IPL. */ -++ iplsize = strtoul(argv[3], NULL, 0); -++ ipltailsize = iplsize % meminfo.erasesize; -++ } -++ -++ if (lseek(ofd, iplsize - ipltailsize, SEEK_SET) < 0) { -++ perror("lseek"); -++ goto error; -++ } -++ -++ if (ipltailsize) { -++ iplbuf = malloc(ipltailsize); -++ if (iplbuf == NULL) { -++ fprintf(stderr, "Not enough memory for IPL tail buffer of" -++ " %lu bytes\n", (unsigned long) ipltailsize); -++ goto error; -++ } -++ printf("Reading IPL%s area of length %lu at offset %lu\n", -++ (iplsize - ipltailsize) ? " tail" : "", -++ (long unsigned) ipltailsize, -++ (long unsigned) (iplsize - ipltailsize)); -++ if (read(ofd, iplbuf, ipltailsize) != ipltailsize) { -++ perror("read"); -++ goto error; -++ } -++ } -++ -++ erase.length = meminfo.erasesize; -++ -++ for (ofs = iplsize - ipltailsize ; -++ ofs < iplsize + statbuf.st_size ; -++ ofs += meminfo.erasesize) { -++ erase.start = ofs; -++ printf("Performing Flash Erase of length %lu at offset %lu\n", -++ (long unsigned) erase.length, (long unsigned) erase.start); -++ -++ if (ioctl(ofd,MEMERASE,&erase) != 0) { -++ perror("ioctl(MEMERASE)"); -++ goto error; -++ } -++ } -++ -++ if (lseek(ofd, iplsize - ipltailsize, SEEK_SET) < 0) { -++ perror("lseek"); -++ goto error; -++ } -++ -++ if (ipltailsize) { -++ printf("Writing IPL%s area of length %lu at offset %lu\n", -++ (iplsize - ipltailsize) ? " tail" : "", -++ (long unsigned) ipltailsize, -++ (long unsigned) (iplsize - ipltailsize)); -++ if (write(ofd, iplbuf, ipltailsize) != ipltailsize) { -++ perror("write"); -++ goto error; -++ } -++ } -++ -++ printf("Writing the firmware of length %lu at %lu... ", -++ (unsigned long) statbuf.st_size, -++ (unsigned long) iplsize); -++ do { -++ retlen = read(ifd, databuf, 512); -++ if (retlen < 512) -++ memset(databuf+retlen, 0xff, 512-retlen); -++ if (write(ofd, databuf, 512) != 512) { -++ perror("write"); -++ goto error; -++ } -++ } while (retlen == 512); -++ printf("Done.\n"); -++ -++ if (iplbuf != NULL) -++ free(iplbuf); -++ close(ifd); -++ close(ofd); -++ return 0; -++ -++error: -++ if (iplbuf != NULL) -++ free(iplbuf); -++ close(ifd); -++ close(ofd); -++ return 1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/docfdisk.c linux-2.6.24.7/drivers/mtd/mtd-utils/docfdisk.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/docfdisk.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/docfdisk.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,317 @@ -++/* -++ * docfdisk.c: Modify INFTL partition tables -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ * GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ */ -++ -++#define _XOPEN_SOURCE 500 /* for pread/pwrite */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++unsigned char *buf; -++ -++mtd_info_t meminfo; -++erase_info_t erase; -++int fd; -++struct INFTLMediaHeader *mh; -++ -++#define MAXSCAN 10 -++ -++void show_header(int mhoffs) { -++ int i, unitsize, numunits, bmbits, numpart; -++ int start, end, num, nextunit; -++ unsigned int flags; -++ struct INFTLPartition *ip; -++ -++ bmbits = le32_to_cpu(mh->BlockMultiplierBits); -++ printf(" bootRecordID = %s\n" -++ " NoOfBootImageBlocks = %d\n" -++ " NoOfBinaryPartitions = %d\n" -++ " NoOfBDTLPartitions = %d\n" -++ " BlockMultiplierBits = %d\n" -++ " FormatFlags = %d\n" -++ " OsakVersion = %d.%d.%d.%d\n" -++ " PercentUsed = %d\n", -++ mh->bootRecordID, le32_to_cpu(mh->NoOfBootImageBlocks), -++ le32_to_cpu(mh->NoOfBinaryPartitions), -++ le32_to_cpu(mh->NoOfBDTLPartitions), -++ bmbits, -++ le32_to_cpu(mh->FormatFlags), -++ ((unsigned char *) &mh->OsakVersion)[0] & 0xf, -++ ((unsigned char *) &mh->OsakVersion)[1] & 0xf, -++ ((unsigned char *) &mh->OsakVersion)[2] & 0xf, -++ ((unsigned char *) &mh->OsakVersion)[3] & 0xf, -++ le32_to_cpu(mh->PercentUsed)); -++ -++ numpart = le32_to_cpu(mh->NoOfBinaryPartitions) + -++ le32_to_cpu(mh->NoOfBDTLPartitions); -++ unitsize = meminfo.erasesize >> bmbits; -++ numunits = meminfo.size / unitsize; -++ nextunit = mhoffs / unitsize; -++ nextunit++; -++ printf("Unitsize is %d bytes. Device has %d units.\n", -++ unitsize, numunits); -++ if (numunits > 32768) { -++ printf("WARNING: More than 32768 units! Unexpectedly small BlockMultiplierBits.\n"); -++ } -++ if (bmbits && (numunits <= 16384)) { -++ printf("NOTICE: Unexpectedly large BlockMultiplierBits.\n"); -++ } -++ for (i = 0; i < 4; i++) { -++ ip = &(mh->Partitions[i]); -++ flags = le32_to_cpu(ip->flags); -++ start = le32_to_cpu(ip->firstUnit); -++ end = le32_to_cpu(ip->lastUnit); -++ num = le32_to_cpu(ip->virtualUnits); -++ if (start < nextunit) { -++ printf("ERROR: Overlapping or misordered partitions!\n"); -++ } -++ if (start > nextunit) { -++ printf(" Unpartitioned space: %d bytes\n" -++ " virtualUnits = %d\n" -++ " firstUnit = %d\n" -++ " lastUnit = %d\n", -++ (start - nextunit) * unitsize, start - nextunit, -++ nextunit, start - 1); -++ } -++ if (flags & INFTL_BINARY) -++ printf(" Partition %d (BDK):", i+1); -++ else -++ printf(" Partition %d (BDTL):", i+1); -++ printf(" %d bytes\n" -++ " virtualUnits = %d\n" -++ " firstUnit = %d\n" -++ " lastUnit = %d\n" -++ " flags = 0x%x\n" -++ " spareUnits = %d\n", -++ num * unitsize, num, start, end, -++ le32_to_cpu(ip->flags), le32_to_cpu(ip->spareUnits)); -++ if (num > (1 + end - start)) { -++ printf("ERROR: virtualUnits not consistent with first/lastUnit!\n"); -++ } -++ end++; -++ if (end > nextunit) -++ nextunit = end; -++ if (flags & INFTL_LAST) -++ break; -++ } -++ if (i >= 4) { -++ printf("Odd. Last partition was not marked with INFTL_LAST.\n"); -++ i--; -++ } -++ if ((i+1) != numpart) { -++ printf("ERROR: Number of partitions != (NoOfBinaryPartitions + NoOfBDTLPartitions)\n"); -++ } -++ if (nextunit > numunits) { -++ printf("ERROR: Partitions appear to extend beyond end of device!\n"); -++ } -++ if (nextunit < numunits) { -++ printf(" Unpartitioned space: %d bytes\n" -++ " virtualUnits = %d\n" -++ " firstUnit = %d\n" -++ " lastUnit = %d\n", -++ (numunits - nextunit) * unitsize, numunits - nextunit, -++ nextunit, numunits - 1); -++ } -++} -++ -++ -++int main(int argc, char **argv) -++{ -++ int ret, i, mhblock, unitsize, block; -++ unsigned int nblocks[4], npart; -++ unsigned int totblocks; -++ struct INFTLPartition *ip; -++ unsigned char *oobbuf; -++ struct mtd_oob_buf oob; -++ char line[20]; -++ int mhoffs; -++ struct INFTLMediaHeader *mh2; -++ -++ if (argc < 2) { -++ printf( -++ "Usage: %s [ [ [ [ 4) { -++ printf("Max 4 partitions allowed.\n"); -++ return 1; -++ } -++ -++ for (i = 0; i < npart; i++) { -++ nblocks[i] = strtoul(argv[2+i], NULL, 0); -++ if (i && !nblocks[i-1]) { -++ printf("No sizes allowed after 0\n"); -++ return 1; -++ } -++ } -++ -++ // Open and size the device -++ if ((fd = open(argv[1], O_RDWR)) < 0) { -++ perror("Open flash device"); -++ return 1; -++ } -++ -++ if (ioctl(fd, MEMGETINFO, &meminfo) != 0) { -++ perror("ioctl(MEMGETINFO)"); -++ return 1; -++ } -++ -++ printf("Device size is %d bytes. Erasesize is %d bytes.\n", -++ meminfo.size, meminfo.erasesize); -++ -++ buf = malloc(meminfo.erasesize); -++ oobbuf = malloc((meminfo.erasesize / meminfo.writesize) * meminfo.oobsize); -++ if (!buf || !oobbuf) { -++ printf("Can't malloc block buffer\n"); -++ return 1; -++ } -++ oob.length = meminfo.oobsize; -++ -++ mh = (struct INFTLMediaHeader *) buf; -++ -++ for (mhblock = 0; mhblock < MAXSCAN; mhblock++) { -++ if ((ret = pread(fd, buf, meminfo.erasesize, mhblock * meminfo.erasesize)) < 0) { -++ if (errno == EBADMSG) { -++ printf("ECC error at eraseblock %d\n", mhblock); -++ continue; -++ } -++ perror("Read eraseblock"); -++ return 1; -++ } -++ if (ret != meminfo.erasesize) { -++ printf("Short read!\n"); -++ return 1; -++ } -++ if (!strcmp("BNAND", mh->bootRecordID)) break; -++ } -++ if (mhblock >= MAXSCAN) { -++ printf("Unable to find INFTL Media Header\n"); -++ return 1; -++ } -++ printf("Found INFTL Media Header at block %d:\n", mhblock); -++ mhoffs = mhblock * meminfo.erasesize; -++ -++ oob.ptr = oobbuf; -++ oob.start = mhoffs; -++ for (i = 0; i < meminfo.erasesize; i += meminfo.writesize) { -++ if (ioctl(fd, MEMREADOOB, &oob)) { -++ perror("ioctl(MEMREADOOB)"); -++ return 1; -++ } -++ oob.start += meminfo.writesize; -++ oob.ptr += meminfo.oobsize; -++ } -++ -++ show_header(mhoffs); -++ -++ if (!npart) -++ return 0; -++ -++ printf("\n" -++ "-------------------------------------------------------------------------\n"); -++ -++ unitsize = meminfo.erasesize >> le32_to_cpu(mh->BlockMultiplierBits); -++ totblocks = meminfo.size / unitsize; -++ block = mhoffs / unitsize; -++ block++; -++ -++ mh->NoOfBDTLPartitions = 0; -++ mh->NoOfBinaryPartitions = npart; -++ -++ for (i = 0; i < npart; i++) { -++ ip = &(mh->Partitions[i]); -++ ip->firstUnit = cpu_to_le32(block); -++ if (!nblocks[i]) -++ nblocks[i] = totblocks - block; -++ ip->virtualUnits = cpu_to_le32(nblocks[i]); -++ block += nblocks[i]; -++ ip->lastUnit = cpu_to_le32(block-1); -++ ip->spareUnits = 0; -++ ip->flags = cpu_to_le32(INFTL_BINARY); -++ } -++ if (block > totblocks) { -++ printf("Requested partitions extend beyond end of device.\n"); -++ return 1; -++ } -++ ip->flags = cpu_to_le32(INFTL_BINARY | INFTL_LAST); -++ -++ /* update the spare as well */ -++ mh2 = (struct INFTLMediaHeader *) (buf + 4096); -++ memcpy((void *) mh2, (void *) mh, sizeof(struct INFTLMediaHeader)); -++ -++ printf("\nProposed new Media Header:\n"); -++ show_header(mhoffs); -++ -++ printf("\nReady to update device. Type 'yes' to proceed, anything else to abort: "); -++ fgets(line, sizeof(line), stdin); -++ if (strcmp("yes\n", line)) -++ return 0; -++ printf("Updating MediaHeader...\n"); -++ -++ erase.start = mhoffs; -++ erase.length = meminfo.erasesize; -++ if (ioctl(fd, MEMERASE, &erase)) { -++ perror("ioctl(MEMERASE)"); -++ printf("Your MediaHeader may be hosed. UHOH!\n"); -++ return 1; -++ } -++ -++ oob.ptr = oobbuf; -++ oob.start = mhoffs; -++ for (i = 0; i < meminfo.erasesize; i += meminfo.writesize) { -++ memset(oob.ptr, 0xff, 6); // clear ECC. -++ if (ioctl(fd, MEMWRITEOOB, &oob)) { -++ perror("ioctl(MEMWRITEOOB)"); -++ printf("Your MediaHeader may be hosed. UHOH!\n"); -++ return 1; -++ } -++ if ((ret = pwrite(fd, buf, meminfo.writesize, oob.start)) < 0) { -++ perror("Write page"); -++ printf("Your MediaHeader may be hosed. UHOH!\n"); -++ return 1; -++ } -++ if (ret != meminfo.writesize) { -++ printf("Short write!\n"); -++ printf("Your MediaHeader may be hosed. UHOH!\n"); -++ return 1; -++ } -++ -++ oob.start += meminfo.writesize; -++ oob.ptr += meminfo.oobsize; -++ buf += meminfo.writesize; -++ } -++ -++ printf("Success. REBOOT or unload the diskonchip module to update partitions!\n"); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/feature-removal-schedule.txt linux-2.6.24.7/drivers/mtd/mtd-utils/feature-removal-schedule.txt -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/feature-removal-schedule.txt 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/feature-removal-schedule.txt 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,9 @@ -++The following is a list of files and features that are going to be -++removed in the mtd-utils source tree. Every entry should contain what -++exactly is going away, why it is happening, and who is going to be doing -++the work. When the feature is removed from the utils, it should also -++be removed from this file. -++ -++--------------------------- -++ -++--------------------------- -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/fec.c linux-2.6.24.7/drivers/mtd/mtd-utils/fec.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/fec.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/fec.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,917 @@ -++/* -++ * fec.c -- forward error correction based on Vandermonde matrices -++ * 980624 -++ * (C) 1997-98 Luigi Rizzo (luigi@iet.unipi.it) -++ * -++ * Portions derived from code by Phil Karn (karn@ka9q.ampr.org), -++ * Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari -++ * Thirumoorthy (harit@spectra.eng.hawaii.edu), Aug 1995 -++ * -++ * Redistribution and use in source and binary forms, with or without -++ * modification, are permitted provided that the following conditions -++ * are met: -++ * -++ * 1. Redistributions of source code must retain the above copyright -++ * notice, this list of conditions and the following disclaimer. -++ * 2. Redistributions in binary form must reproduce the above -++ * copyright notice, this list of conditions and the following -++ * disclaimer in the documentation and/or other materials -++ * provided with the distribution. -++ * -++ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND -++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -++ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -++ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS -++ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -++ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -++ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR -++ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -++ * OF SUCH DAMAGE. -++ */ -++ -++/* -++ * The following parameter defines how many bits are used for -++ * field elements. The code supports any value from 2 to 16 -++ * but fastest operation is achieved with 8 bit elements -++ * This is the only parameter you may want to change. -++ */ -++#ifndef GF_BITS -++#define GF_BITS 8 /* code over GF(2**GF_BITS) - change to suit */ -++#endif -++ -++#include -++#include -++#include -++ -++/* -++ * compatibility stuff -++ */ -++#ifdef MSDOS /* but also for others, e.g. sun... */ -++#define NEED_BCOPY -++#define bcmp(a,b,n) memcmp(a,b,n) -++#endif -++ -++#ifdef NEED_BCOPY -++#define bcopy(s, d, siz) memcpy((d), (s), (siz)) -++#define bzero(d, siz) memset((d), '\0', (siz)) -++#endif -++ -++/* -++ * stuff used for testing purposes only -++ */ -++ -++#ifdef TEST -++#define DEB(x) -++#define DDB(x) x -++#define DEBUG 0 /* minimal debugging */ -++#ifdef MSDOS -++#include -++struct timeval { -++ unsigned long ticks; -++}; -++#define gettimeofday(x, dummy) { (x)->ticks = clock() ; } -++#define DIFF_T(a,b) (1+ 1000000*(a.ticks - b.ticks) / CLOCKS_PER_SEC ) -++typedef unsigned long u_long ; -++typedef unsigned short u_short ; -++#else /* typically, unix systems */ -++#include -++#define DIFF_T(a,b) \ -++ (1+ 1000000*(a.tv_sec - b.tv_sec) + (a.tv_usec - b.tv_usec) ) -++#endif -++ -++#define TICK(t) \ -++ {struct timeval x ; \ -++ gettimeofday(&x, NULL) ; \ -++ t = x.tv_usec + 1000000* (x.tv_sec & 0xff ) ; \ -++ } -++#define TOCK(t) \ -++ { u_long t1 ; TICK(t1) ; \ -++ if (t1 < t) t = 256000000 + t1 - t ; \ -++ else t = t1 - t ; \ -++ if (t == 0) t = 1 ;} -++ -++u_long ticks[10]; /* vars for timekeeping */ -++#else -++#define DEB(x) -++#define DDB(x) -++#define TICK(x) -++#define TOCK(x) -++#endif /* TEST */ -++ -++/* -++ * You should not need to change anything beyond this point. -++ * The first part of the file implements linear algebra in GF. -++ * -++ * gf is the type used to store an element of the Galois Field. -++ * Must constain at least GF_BITS bits. -++ * -++ * Note: unsigned char will work up to GF(256) but int seems to run -++ * faster on the Pentium. We use int whenever have to deal with an -++ * index, since they are generally faster. -++ */ -++#if (GF_BITS < 2 && GF_BITS >16) -++#error "GF_BITS must be 2 .. 16" -++#endif -++#if (GF_BITS <= 8) -++typedef unsigned char gf; -++#else -++typedef unsigned short gf; -++#endif -++ -++#define GF_SIZE ((1 << GF_BITS) - 1) /* powers of \alpha */ -++ -++/* -++ * Primitive polynomials - see Lin & Costello, Appendix A, -++ * and Lee & Messerschmitt, p. 453. -++ */ -++static char *allPp[] = { /* GF_BITS polynomial */ -++ NULL, /* 0 no code */ -++ NULL, /* 1 no code */ -++ "111", /* 2 1+x+x^2 */ -++ "1101", /* 3 1+x+x^3 */ -++ "11001", /* 4 1+x+x^4 */ -++ "101001", /* 5 1+x^2+x^5 */ -++ "1100001", /* 6 1+x+x^6 */ -++ "10010001", /* 7 1 + x^3 + x^7 */ -++ "101110001", /* 8 1+x^2+x^3+x^4+x^8 */ -++ "1000100001", /* 9 1+x^4+x^9 */ -++ "10010000001", /* 10 1+x^3+x^10 */ -++ "101000000001", /* 11 1+x^2+x^11 */ -++ "1100101000001", /* 12 1+x+x^4+x^6+x^12 */ -++ "11011000000001", /* 13 1+x+x^3+x^4+x^13 */ -++ "110000100010001", /* 14 1+x+x^6+x^10+x^14 */ -++ "1100000000000001", /* 15 1+x+x^15 */ -++ "11010000000010001" /* 16 1+x+x^3+x^12+x^16 */ -++}; -++ -++ -++/* -++ * To speed up computations, we have tables for logarithm, exponent -++ * and inverse of a number. If GF_BITS <= 8, we use a table for -++ * multiplication as well (it takes 64K, no big deal even on a PDA, -++ * especially because it can be pre-initialized an put into a ROM!), -++ * otherwhise we use a table of logarithms. -++ * In any case the macro gf_mul(x,y) takes care of multiplications. -++ */ -++ -++static gf gf_exp[2*GF_SIZE]; /* index->poly form conversion table */ -++static int gf_log[GF_SIZE + 1]; /* Poly->index form conversion table */ -++static gf inverse[GF_SIZE+1]; /* inverse of field elem. */ -++ /* inv[\alpha**i]=\alpha**(GF_SIZE-i-1) */ -++ -++/* -++ * modnn(x) computes x % GF_SIZE, where GF_SIZE is 2**GF_BITS - 1, -++ * without a slow divide. -++ */ -++static inline gf -++modnn(int x) -++{ -++ while (x >= GF_SIZE) { -++ x -= GF_SIZE; -++ x = (x >> GF_BITS) + (x & GF_SIZE); -++ } -++ return x; -++} -++ -++#define SWAP(a,b,t) {t tmp; tmp=a; a=b; b=tmp;} -++ -++/* -++ * gf_mul(x,y) multiplies two numbers. If GF_BITS<=8, it is much -++ * faster to use a multiplication table. -++ * -++ * USE_GF_MULC, GF_MULC0(c) and GF_ADDMULC(x) can be used when multiplying -++ * many numbers by the same constant. In this case the first -++ * call sets the constant, and others perform the multiplications. -++ * A value related to the multiplication is held in a local variable -++ * declared with USE_GF_MULC . See usage in addmul1(). -++ */ -++#if (GF_BITS <= 8) -++static gf gf_mul_table[GF_SIZE + 1][GF_SIZE + 1]; -++ -++#define gf_mul(x,y) gf_mul_table[x][y] -++ -++#define USE_GF_MULC register gf * __gf_mulc_ -++#define GF_MULC0(c) __gf_mulc_ = gf_mul_table[c] -++#define GF_ADDMULC(dst, x) dst ^= __gf_mulc_[x] -++ -++static void -++init_mul_table() -++{ -++ int i, j; -++ for (i=0; i< GF_SIZE+1; i++) -++ for (j=0; j< GF_SIZE+1; j++) -++ gf_mul_table[i][j] = gf_exp[modnn(gf_log[i] + gf_log[j]) ] ; -++ -++ for (j=0; j< GF_SIZE+1; j++) -++ gf_mul_table[0][j] = gf_mul_table[j][0] = 0; -++} -++#else /* GF_BITS > 8 */ -++static inline gf -++gf_mul(x,y) -++{ -++ if ( (x) == 0 || (y)==0 ) return 0; -++ -++ return gf_exp[gf_log[x] + gf_log[y] ] ; -++} -++#define init_mul_table() -++ -++#define USE_GF_MULC register gf * __gf_mulc_ -++#define GF_MULC0(c) __gf_mulc_ = &gf_exp[ gf_log[c] ] -++#define GF_ADDMULC(dst, x) { if (x) dst ^= __gf_mulc_[ gf_log[x] ] ; } -++#endif -++ -++/* -++ * Generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m] -++ * Lookup tables: -++ * index->polynomial form gf_exp[] contains j= \alpha^i; -++ * polynomial form -> index form gf_log[ j = \alpha^i ] = i -++ * \alpha=x is the primitive element of GF(2^m) -++ * -++ * For efficiency, gf_exp[] has size 2*GF_SIZE, so that a simple -++ * multiplication of two numbers can be resolved without calling modnn -++ */ -++ -++/* -++ * i use malloc so many times, it is easier to put checks all in -++ * one place. -++ */ -++static void * -++my_malloc(int sz, char *err_string) -++{ -++ void *p = malloc( sz ); -++ if (p == NULL) { -++ fprintf(stderr, "-- malloc failure allocating %s\n", err_string); -++ exit(1) ; -++ } -++ return p ; -++} -++ -++#define NEW_GF_MATRIX(rows, cols) \ -++ (gf *)my_malloc(rows * cols * sizeof(gf), " ## __LINE__ ## " ) -++ -++/* -++ * initialize the data structures used for computations in GF. -++ */ -++static void -++generate_gf(void) -++{ -++ int i; -++ gf mask; -++ char *Pp = allPp[GF_BITS] ; -++ -++ mask = 1; /* x ** 0 = 1 */ -++ gf_exp[GF_BITS] = 0; /* will be updated at the end of the 1st loop */ -++ /* -++ * first, generate the (polynomial representation of) powers of \alpha, -++ * which are stored in gf_exp[i] = \alpha ** i . -++ * At the same time build gf_log[gf_exp[i]] = i . -++ * The first GF_BITS powers are simply bits shifted to the left. -++ */ -++ for (i = 0; i < GF_BITS; i++, mask <<= 1 ) { -++ gf_exp[i] = mask; -++ gf_log[gf_exp[i]] = i; -++ /* -++ * If Pp[i] == 1 then \alpha ** i occurs in poly-repr -++ * gf_exp[GF_BITS] = \alpha ** GF_BITS -++ */ -++ if ( Pp[i] == '1' ) -++ gf_exp[GF_BITS] ^= mask; -++ } -++ /* -++ * now gf_exp[GF_BITS] = \alpha ** GF_BITS is complete, so can als -++ * compute its inverse. -++ */ -++ gf_log[gf_exp[GF_BITS]] = GF_BITS; -++ /* -++ * Poly-repr of \alpha ** (i+1) is given by poly-repr of -++ * \alpha ** i shifted left one-bit and accounting for any -++ * \alpha ** GF_BITS term that may occur when poly-repr of -++ * \alpha ** i is shifted. -++ */ -++ mask = 1 << (GF_BITS - 1 ) ; -++ for (i = GF_BITS + 1; i < GF_SIZE; i++) { -++ if (gf_exp[i - 1] >= mask) -++ gf_exp[i] = gf_exp[GF_BITS] ^ ((gf_exp[i - 1] ^ mask) << 1); -++ else -++ gf_exp[i] = gf_exp[i - 1] << 1; -++ gf_log[gf_exp[i]] = i; -++ } -++ /* -++ * log(0) is not defined, so use a special value -++ */ -++ gf_log[0] = GF_SIZE ; -++ /* set the extended gf_exp values for fast multiply */ -++ for (i = 0 ; i < GF_SIZE ; i++) -++ gf_exp[i + GF_SIZE] = gf_exp[i] ; -++ -++ /* -++ * again special cases. 0 has no inverse. This used to -++ * be initialized to GF_SIZE, but it should make no difference -++ * since noone is supposed to read from here. -++ */ -++ inverse[0] = 0 ; -++ inverse[1] = 1; -++ for (i=2; i<=GF_SIZE; i++) -++ inverse[i] = gf_exp[GF_SIZE-gf_log[i]]; -++} -++ -++/* -++ * Various linear algebra operations that i use often. -++ */ -++ -++/* -++ * addmul() computes dst[] = dst[] + c * src[] -++ * This is used often, so better optimize it! Currently the loop is -++ * unrolled 16 times, a good value for 486 and pentium-class machines. -++ * The case c=0 is also optimized, whereas c=1 is not. These -++ * calls are unfrequent in my typical apps so I did not bother. -++ * -++ * Note that gcc on -++ */ -++#define addmul(dst, src, c, sz) \ -++ if (c != 0) addmul1(dst, src, c, sz) -++ -++#define UNROLL 16 /* 1, 4, 8, 16 */ -++static void -++addmul1(gf *dst1, gf *src1, gf c, int sz) -++{ -++ USE_GF_MULC ; -++ register gf *dst = dst1, *src = src1 ; -++ gf *lim = &dst[sz - UNROLL + 1] ; -++ -++ GF_MULC0(c) ; -++ -++#if (UNROLL > 1) /* unrolling by 8/16 is quite effective on the pentium */ -++ for (; dst < lim ; dst += UNROLL, src += UNROLL ) { -++ GF_ADDMULC( dst[0] , src[0] ); -++ GF_ADDMULC( dst[1] , src[1] ); -++ GF_ADDMULC( dst[2] , src[2] ); -++ GF_ADDMULC( dst[3] , src[3] ); -++#if (UNROLL > 4) -++ GF_ADDMULC( dst[4] , src[4] ); -++ GF_ADDMULC( dst[5] , src[5] ); -++ GF_ADDMULC( dst[6] , src[6] ); -++ GF_ADDMULC( dst[7] , src[7] ); -++#endif -++#if (UNROLL > 8) -++ GF_ADDMULC( dst[8] , src[8] ); -++ GF_ADDMULC( dst[9] , src[9] ); -++ GF_ADDMULC( dst[10] , src[10] ); -++ GF_ADDMULC( dst[11] , src[11] ); -++ GF_ADDMULC( dst[12] , src[12] ); -++ GF_ADDMULC( dst[13] , src[13] ); -++ GF_ADDMULC( dst[14] , src[14] ); -++ GF_ADDMULC( dst[15] , src[15] ); -++#endif -++ } -++#endif -++ lim += UNROLL - 1 ; -++ for (; dst < lim; dst++, src++ ) /* final components */ -++ GF_ADDMULC( *dst , *src ); -++} -++ -++/* -++ * computes C = AB where A is n*k, B is k*m, C is n*m -++ */ -++static void -++matmul(gf *a, gf *b, gf *c, int n, int k, int m) -++{ -++ int row, col, i ; -++ -++ for (row = 0; row < n ; row++) { -++ for (col = 0; col < m ; col++) { -++ gf *pa = &a[ row * k ]; -++ gf *pb = &b[ col ]; -++ gf acc = 0 ; -++ for (i = 0; i < k ; i++, pa++, pb += m ) -++ acc ^= gf_mul( *pa, *pb ) ; -++ c[ row * m + col ] = acc ; -++ } -++ } -++} -++ -++#ifdef DEBUG -++/* -++ * returns 1 if the square matrix is identiy -++ * (only for test) -++ */ -++static int -++is_identity(gf *m, int k) -++{ -++ int row, col ; -++ for (row=0; row 1) { -++ fprintf(stderr, "singular matrix\n"); -++ goto fail ; -++ } -++ } -++ } -++ } -++ if (icol == -1) { -++ fprintf(stderr, "XXX pivot not found!\n"); -++ goto fail ; -++ } -++found_piv: -++ ++(ipiv[icol]) ; -++ /* -++ * swap rows irow and icol, so afterwards the diagonal -++ * element will be correct. Rarely done, not worth -++ * optimizing. -++ */ -++ if (irow != icol) { -++ for (ix = 0 ; ix < k ; ix++ ) { -++ SWAP( src[irow*k + ix], src[icol*k + ix], gf) ; -++ } -++ } -++ indxr[col] = irow ; -++ indxc[col] = icol ; -++ pivot_row = &src[icol*k] ; -++ c = pivot_row[icol] ; -++ if (c == 0) { -++ fprintf(stderr, "singular matrix 2\n"); -++ goto fail ; -++ } -++ if (c != 1 ) { /* otherwhise this is a NOP */ -++ /* -++ * this is done often , but optimizing is not so -++ * fruitful, at least in the obvious ways (unrolling) -++ */ -++ DEB( pivswaps++ ; ) -++ c = inverse[ c ] ; -++ pivot_row[icol] = 1 ; -++ for (ix = 0 ; ix < k ; ix++ ) -++ pivot_row[ix] = gf_mul(c, pivot_row[ix] ); -++ } -++ /* -++ * from all rows, remove multiples of the selected row -++ * to zero the relevant entry (in fact, the entry is not zero -++ * because we know it must be zero). -++ * (Here, if we know that the pivot_row is the identity, -++ * we can optimize the addmul). -++ */ -++ id_row[icol] = 1; -++ if (bcmp(pivot_row, id_row, k*sizeof(gf)) != 0) { -++ for (p = src, ix = 0 ; ix < k ; ix++, p += k ) { -++ if (ix != icol) { -++ c = p[icol] ; -++ p[icol] = 0 ; -++ addmul(p, pivot_row, c, k ); -++ } -++ } -++ } -++ id_row[icol] = 0; -++ } /* done all columns */ -++ for (col = k-1 ; col >= 0 ; col-- ) { -++ if (indxr[col] <0 || indxr[col] >= k) -++ fprintf(stderr, "AARGH, indxr[col] %d\n", indxr[col]); -++ else if (indxc[col] <0 || indxc[col] >= k) -++ fprintf(stderr, "AARGH, indxc[col] %d\n", indxc[col]); -++ else -++ if (indxr[col] != indxc[col] ) { -++ for (row = 0 ; row < k ; row++ ) { -++ SWAP( src[row*k + indxr[col]], src[row*k + indxc[col]], gf) ; -++ } -++ } -++ } -++ error = 0 ; -++fail: -++ free(indxc); -++ free(indxr); -++ free(ipiv); -++ free(id_row); -++ free(temp_row); -++ return error ; -++} -++ -++/* -++ * fast code for inverting a vandermonde matrix. -++ * XXX NOTE: It assumes that the matrix -++ * is not singular and _IS_ a vandermonde matrix. Only uses -++ * the second column of the matrix, containing the p_i's. -++ * -++ * Algorithm borrowed from "Numerical recipes in C" -- sec.2.8, but -++ * largely revised for my purposes. -++ * p = coefficients of the matrix (p_i) -++ * q = values of the polynomial (known) -++ */ -++ -++int -++invert_vdm(gf *src, int k) -++{ -++ int i, j, row, col ; -++ gf *b, *c, *p; -++ gf t, xx ; -++ -++ if (k == 1) /* degenerate case, matrix must be p^0 = 1 */ -++ return 0 ; -++ /* -++ * c holds the coefficient of P(x) = Prod (x - p_i), i=0..k-1 -++ * b holds the coefficient for the matrix inversion -++ */ -++ c = NEW_GF_MATRIX(1, k); -++ b = NEW_GF_MATRIX(1, k); -++ -++ p = NEW_GF_MATRIX(1, k); -++ -++ for ( j=1, i = 0 ; i < k ; i++, j+=k ) { -++ c[i] = 0 ; -++ p[i] = src[j] ; /* p[i] */ -++ } -++ /* -++ * construct coeffs. recursively. We know c[k] = 1 (implicit) -++ * and start P_0 = x - p_0, then at each stage multiply by -++ * x - p_i generating P_i = x P_{i-1} - p_i P_{i-1} -++ * After k steps we are done. -++ */ -++ c[k-1] = p[0] ; /* really -p(0), but x = -x in GF(2^m) */ -++ for (i = 1 ; i < k ; i++ ) { -++ gf p_i = p[i] ; /* see above comment */ -++ for (j = k-1 - ( i - 1 ) ; j < k-1 ; j++ ) -++ c[j] ^= gf_mul( p_i, c[j+1] ) ; -++ c[k-1] ^= p_i ; -++ } -++ -++ for (row = 0 ; row < k ; row++ ) { -++ /* -++ * synthetic division etc. -++ */ -++ xx = p[row] ; -++ t = 1 ; -++ b[k-1] = 1 ; /* this is in fact c[k] */ -++ for (i = k-2 ; i >= 0 ; i-- ) { -++ b[i] = c[i+1] ^ gf_mul(xx, b[i+1]) ; -++ t = gf_mul(xx, t) ^ b[i] ; -++ } -++ for (col = 0 ; col < k ; col++ ) -++ src[col*k + row] = gf_mul(inverse[t], b[col] ); -++ } -++ free(c) ; -++ free(b) ; -++ free(p) ; -++ return 0 ; -++} -++ -++static int fec_initialized = 0 ; -++static void -++init_fec() -++{ -++ TICK(ticks[0]); -++ generate_gf(); -++ TOCK(ticks[0]); -++ DDB(fprintf(stderr, "generate_gf took %ldus\n", ticks[0]);) -++ TICK(ticks[0]); -++ init_mul_table(); -++ TOCK(ticks[0]); -++ DDB(fprintf(stderr, "init_mul_table took %ldus\n", ticks[0]);) -++ fec_initialized = 1 ; -++} -++ -++/* -++ * This section contains the proper FEC encoding/decoding routines. -++ * The encoding matrix is computed starting with a Vandermonde matrix, -++ * and then transforming it into a systematic matrix. -++ */ -++ -++#define FEC_MAGIC 0xFECC0DEC -++ -++struct fec_parms { -++ u_long magic ; -++ int k, n ; /* parameters of the code */ -++ gf *enc_matrix ; -++} ; -++ -++void -++fec_free(struct fec_parms *p) -++{ -++ if (p==NULL || -++ p->magic != ( ( (FEC_MAGIC ^ p->k) ^ p->n) ^ (int)(p->enc_matrix)) ) { -++ fprintf(stderr, "bad parameters to fec_free\n"); -++ return ; -++ } -++ free(p->enc_matrix); -++ free(p); -++} -++ -++/* -++ * create a new encoder, returning a descriptor. This contains k,n and -++ * the encoding matrix. -++ */ -++struct fec_parms * -++fec_new(int k, int n) -++{ -++ int row, col ; -++ gf *p, *tmp_m ; -++ -++ struct fec_parms *retval ; -++ -++ if (fec_initialized == 0) -++ init_fec(); -++ -++ if (k > GF_SIZE + 1 || n > GF_SIZE + 1 || k > n ) { -++ fprintf(stderr, "Invalid parameters k %d n %d GF_SIZE %d\n", -++ k, n, GF_SIZE ); -++ return NULL ; -++ } -++ retval = my_malloc(sizeof(struct fec_parms), "new_code"); -++ retval->k = k ; -++ retval->n = n ; -++ retval->enc_matrix = NEW_GF_MATRIX(n, k); -++ retval->magic = ( ( FEC_MAGIC ^ k) ^ n) ^ (int)(retval->enc_matrix) ; -++ tmp_m = NEW_GF_MATRIX(n, k); -++ /* -++ * fill the matrix with powers of field elements, starting from 0. -++ * The first row is special, cannot be computed with exp. table. -++ */ -++ tmp_m[0] = 1 ; -++ for (col = 1; col < k ; col++) -++ tmp_m[col] = 0 ; -++ for (p = tmp_m + k, row = 0; row < n-1 ; row++, p += k) { -++ for ( col = 0 ; col < k ; col ++ ) -++ p[col] = gf_exp[modnn(row*col)]; -++ } -++ -++ /* -++ * quick code to build systematic matrix: invert the top -++ * k*k vandermonde matrix, multiply right the bottom n-k rows -++ * by the inverse, and construct the identity matrix at the top. -++ */ -++ TICK(ticks[3]); -++ invert_vdm(tmp_m, k); /* much faster than invert_mat */ -++ matmul(tmp_m + k*k, tmp_m, retval->enc_matrix + k*k, n - k, k, k); -++ /* -++ * the upper matrix is I so do not bother with a slow multiply -++ */ -++ bzero(retval->enc_matrix, k*k*sizeof(gf) ); -++ for (p = retval->enc_matrix, col = 0 ; col < k ; col++, p += k+1 ) -++ *p = 1 ; -++ free(tmp_m); -++ TOCK(ticks[3]); -++ -++ DDB(fprintf(stderr, "--- %ld us to build encoding matrix\n", -++ ticks[3]);) -++ DEB(pr_matrix(retval->enc_matrix, n, k, "encoding_matrix");) -++ return retval ; -++} -++ -++/* -++ * fec_encode accepts as input pointers to n data packets of size sz, -++ * and produces as output a packet pointed to by fec, computed -++ * with index "index". -++ */ -++void -++fec_encode(struct fec_parms *code, gf *src[], gf *fec, int index, int sz) -++{ -++ int i, k = code->k ; -++ gf *p ; -++ -++ if (GF_BITS > 8) -++ sz /= 2 ; -++ -++ if (index < k) -++ bcopy(src[index], fec, sz*sizeof(gf) ) ; -++ else if (index < code->n) { -++ p = &(code->enc_matrix[index*k] ); -++ bzero(fec, sz*sizeof(gf)); -++ for (i = 0; i < k ; i++) -++ addmul(fec, src[i], p[i], sz ) ; -++ } else -++ fprintf(stderr, "Invalid index %d (max %d)\n", -++ index, code->n - 1 ); -++} -++ -++void fec_encode_linear(struct fec_parms *code, gf *src, gf *fec, int index, int sz) -++{ -++ int i, k = code->k ; -++ gf *p ; -++ -++ if (GF_BITS > 8) -++ sz /= 2 ; -++ -++ if (index < k) -++ bcopy(src + (index * sz), fec, sz*sizeof(gf) ) ; -++ else if (index < code->n) { -++ p = &(code->enc_matrix[index*k] ); -++ bzero(fec, sz*sizeof(gf)); -++ for (i = 0; i < k ; i++) -++ addmul(fec, src + (i * sz), p[i], sz ) ; -++ } else -++ fprintf(stderr, "Invalid index %d (max %d)\n", -++ index, code->n - 1 ); -++} -++/* -++ * shuffle move src packets in their position -++ */ -++static int -++shuffle(gf *pkt[], int index[], int k) -++{ -++ int i; -++ -++ for ( i = 0 ; i < k ; ) { -++ if (index[i] >= k || index[i] == i) -++ i++ ; -++ else { -++ /* -++ * put pkt in the right position (first check for conflicts). -++ */ -++ int c = index[i] ; -++ -++ if (index[c] == c) { -++ DEB(fprintf(stderr, "\nshuffle, error at %d\n", i);) -++ return 1 ; -++ } -++ SWAP(index[i], index[c], int) ; -++ SWAP(pkt[i], pkt[c], gf *) ; -++ } -++ } -++ DEB( /* just test that it works... */ -++ for ( i = 0 ; i < k ; i++ ) { -++ if (index[i] < k && index[i] != i) { -++ fprintf(stderr, "shuffle: after\n"); -++ for (i=0; ik ; -++ gf *p, *matrix = NEW_GF_MATRIX(k, k); -++ -++ TICK(ticks[9]); -++ for (i = 0, p = matrix ; i < k ; i++, p += k ) { -++#if 1 /* this is simply an optimization, not very useful indeed */ -++ if (index[i] < k) { -++ bzero(p, k*sizeof(gf) ); -++ p[i] = 1 ; -++ } else -++#endif -++ if (index[i] < code->n ) -++ bcopy( &(code->enc_matrix[index[i]*k]), p, k*sizeof(gf) ); -++ else { -++ fprintf(stderr, "decode: invalid index %d (max %d)\n", -++ index[i], code->n - 1 ); -++ free(matrix) ; -++ return NULL ; -++ } -++ } -++ TICK(ticks[9]); -++ if (invert_mat(matrix, k)) { -++ free(matrix); -++ matrix = NULL ; -++ } -++ TOCK(ticks[9]); -++ return matrix ; -++} -++ -++/* -++ * fec_decode receives as input a vector of packets, the indexes of -++ * packets, and produces the correct vector as output. -++ * -++ * Input: -++ * code: pointer to code descriptor -++ * pkt: pointers to received packets. They are modified -++ * to store the output packets (in place) -++ * index: pointer to packet indexes (modified) -++ * sz: size of each packet -++ */ -++int -++fec_decode(struct fec_parms *code, gf *pkt[], int index[], int sz) -++{ -++ gf *m_dec ; -++ gf **new_pkt ; -++ int row, col , k = code->k ; -++ -++ if (GF_BITS > 8) -++ sz /= 2 ; -++ -++ if (shuffle(pkt, index, k)) /* error if true */ -++ return 1 ; -++ m_dec = build_decode_matrix(code, pkt, index); -++ -++ if (m_dec == NULL) -++ return 1 ; /* error */ -++ /* -++ * do the actual decoding -++ */ -++ new_pkt = my_malloc (k * sizeof (gf * ), "new pkt pointers" ); -++ for (row = 0 ; row < k ; row++ ) { -++ if (index[row] >= k) { -++ new_pkt[row] = my_malloc (sz * sizeof (gf), "new pkt buffer" ); -++ bzero(new_pkt[row], sz * sizeof(gf) ) ; -++ for (col = 0 ; col < k ; col++ ) -++ addmul(new_pkt[row], pkt[col], m_dec[row*k + col], sz) ; -++ } -++ } -++ /* -++ * move pkts to their final destination -++ */ -++ for (row = 0 ; row < k ; row++ ) { -++ if (index[row] >= k) { -++ bcopy(new_pkt[row], pkt[row], sz*sizeof(gf)); -++ free(new_pkt[row]); -++ } -++ } -++ free(new_pkt); -++ free(m_dec); -++ -++ return 0; -++} -++ -++/*********** end of FEC code -- beginning of test code ************/ -++ -++#if (TEST || DEBUG) -++void -++test_gf() -++{ -++ int i ; -++ /* -++ * test gf tables. Sufficiently tested... -++ */ -++ for (i=0; i<= GF_SIZE; i++) { -++ if (gf_exp[gf_log[i]] != i) -++ fprintf(stderr, "bad exp/log i %d log %d exp(log) %d\n", -++ i, gf_log[i], gf_exp[gf_log[i]]); -++ -++ if (i != 0 && gf_mul(i, inverse[i]) != 1) -++ fprintf(stderr, "bad mul/inv i %d inv %d i*inv(i) %d\n", -++ i, inverse[i], gf_mul(i, inverse[i]) ); -++ if (gf_mul(0,i) != 0) -++ fprintf(stderr, "bad mul table 0,%d\n",i); -++ if (gf_mul(i,0) != 0) -++ fprintf(stderr, "bad mul table %d,0\n",i); -++ } -++} -++#endif /* TEST */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/fectest.c linux-2.6.24.7/drivers/mtd/mtd-utils/fectest.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/fectest.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/fectest.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,92 @@ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "mcast_image.h" -++#include "crc32.h" -++ -++#define ERASE_SIZE 131072 -++//#define PKT_SIZE 1400 -++#define NR_PKTS ((ERASE_SIZE + PKT_SIZE - 1) / PKT_SIZE) -++#define DROPS 8 -++ -++int main(void) -++{ -++ int i, j; -++ unsigned char buf[NR_PKTS * PKT_SIZE]; -++ unsigned char pktbuf[(NR_PKTS + DROPS) * PKT_SIZE]; -++ struct fec_parms *fec; -++ unsigned char *srcs[NR_PKTS]; -++ unsigned char *pkt[NR_PKTS + DROPS]; -++ int pktnr[NR_PKTS + DROPS]; -++ struct timeval then, now; -++ -++ srand(3453); -++ for (i=0; i < sizeof(buf); i++) -++ if (i < ERASE_SIZE) -++ buf[i] = rand(); -++ else -++ buf[i] = 0; -++ -++ for (i=0; i < NR_PKTS + DROPS; i++) -++ srcs[i] = buf + (i * PKT_SIZE); -++ -++ for (i=0; i < NR_PKTS + DROPS; i++) { -++ pkt[i] = malloc(PKT_SIZE); -++ pktnr[i] = -1; -++ } -++ fec = fec_new(NR_PKTS, NR_PKTS + DROPS); -++ if (!fec) { -++ printf("fec_init() failed\n"); -++ exit(1); -++ } -++ j = 0; -++ for (i=0; i < NR_PKTS + DROPS; i++) { -++#if 1 -++ if (i == 27 || i == 40 || i == 44 || i == 45 || i == 56 ) -++ continue; -++#endif -++ if (i == 69 || i == 93 || i == 103) -++ continue; -++ fec_encode(fec, srcs, pkt[j], i, PKT_SIZE); -++ pktnr[j] = i; -++ j++; -++ } -++ gettimeofday(&then, NULL); -++ if (fec_decode(fec, pkt, pktnr, PKT_SIZE)) { -++ printf("Decode failed\n"); -++ exit(1); -++ } -++ -++ for (i=0; i < NR_PKTS; i++) -++ memcpy(pktbuf + (i*PKT_SIZE), pkt[i], PKT_SIZE); -++ gettimeofday(&now, NULL); -++ now.tv_sec -= then.tv_sec; -++ now.tv_usec -= then.tv_usec; -++ if (now.tv_usec < 0) { -++ now.tv_usec += 1000000; -++ now.tv_sec--; -++ } -++ -++ if (memcmp(pktbuf, buf, ERASE_SIZE)) { -++ int fd; -++ printf("Compare failed\n"); -++ fd = open("before", O_WRONLY|O_TRUNC|O_CREAT, 0644); -++ if (fd >= 0) -++ write(fd, buf, ERASE_SIZE); -++ close(fd); -++ fd = open("after", O_WRONLY|O_TRUNC|O_CREAT, 0644); -++ if (fd >= 0) -++ write(fd, pktbuf, ERASE_SIZE); -++ -++ exit(1); -++ } -++ -++ printf("Decoded in %ld.%06lds\n", now.tv_sec, now.tv_usec); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_erase.c linux-2.6.24.7/drivers/mtd/mtd-utils/flash_erase.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_erase.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/flash_erase.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,189 @@ -++/* -++ * flash_erase.c -- erase parts of a MTD device -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++int region_erase(int Fd, int start, int count, int unlock, int regcount) -++{ -++ int i, j; -++ region_info_t * reginfo; -++ -++ reginfo = calloc(regcount, sizeof(region_info_t)); -++ -++ for(i = 0; i < regcount; i++) -++ { -++ reginfo[i].regionindex = i; -++ if(ioctl(Fd,MEMGETREGIONINFO,&(reginfo[i])) != 0) -++ return 8; -++ else -++ printf("Region %d is at %d of %d sector and with sector " -++ "size %x\n", i, reginfo[i].offset, reginfo[i].numblocks, -++ reginfo[i].erasesize); -++ } -++ -++ // We have all the information about the chip we need. -++ -++ for(i = 0; i < regcount; i++) -++ { //Loop through the regions -++ region_info_t * r = &(reginfo[i]); -++ -++ if((start >= reginfo[i].offset) && -++ (start < (r->offset + r->numblocks*r->erasesize))) -++ break; -++ } -++ -++ if(i >= regcount) -++ { -++ printf("Starting offset %x not within chip.\n", start); -++ return 8; -++ } -++ -++ //We are now positioned within region i of the chip, so start erasing -++ //count sectors from there. -++ -++ for(j = 0; (j < count)&&(i < regcount); j++) -++ { -++ erase_info_t erase; -++ region_info_t * r = &(reginfo[i]); -++ -++ erase.start = start; -++ erase.length = r->erasesize; -++ -++ if(unlock != 0) -++ { //Unlock the sector first. -++ if(ioctl(Fd, MEMUNLOCK, &erase) != 0) -++ { -++ perror("\nMTD Unlock failure"); -++ close(Fd); -++ return 8; -++ } -++ } -++ printf("\rPerforming Flash Erase of length 0x%llx at offset 0x%llx", -++ erase.length, erase.start); -++ fflush(stdout); -++ if(ioctl(Fd, MEMERASE, &erase) != 0) -++ { -++ perror("\nMTD Erase failure"); -++ close(Fd); -++ return 8; -++ } -++ -++ -++ start += erase.length; -++ if(start >= (r->offset + r->numblocks*r->erasesize)) -++ { //We finished region i so move to region i+1 -++ printf("\nMoving to region %d\n", i+1); -++ i++; -++ } -++ } -++ -++ printf(" done\n"); -++ -++ return 0; -++} -++ -++int non_region_erase(int Fd, int start, int count, int unlock) -++{ -++ mtd_info_t meminfo; -++ -++ if (ioctl(Fd,MEMGETINFO,&meminfo) == 0) -++ { -++ erase_info_t erase; -++ -++ erase.start = start; -++ -++ erase.length = meminfo.erasesize; -++ -++ for (; count > 0; count--) { -++ printf("\rPerforming Flash Erase of length 0x%llx at offset 0x%llx", -++ erase.length, erase.start); -++ fflush(stdout); -++ -++ if(unlock != 0) -++ { -++ //Unlock the sector first. -++ printf("\rPerforming Flash unlock at offset 0x%llx",erase.start); -++ if(ioctl(Fd, MEMUNLOCK, &erase) != 0) -++ { -++ perror("\nMTD Unlock failure"); -++ close(Fd); -++ return 8; -++ } -++ } -++ -++ if (ioctl(Fd,MEMERASE,&erase) != 0) -++ { -++ perror("\nMTD Erase failure"); -++ close(Fd); -++ return 8; -++ } -++ erase.start += meminfo.erasesize; -++ } -++ printf(" done\n"); -++ } -++ return 0; -++} -++ -++int main(int argc,char *argv[]) -++{ -++ int regcount; -++ int Fd; -++ int start; -++ int count; -++ int unlock; -++ int res = 0; -++ -++ if (1 >= argc || !strcmp(argv[1], "-h") || !strcmp (argv[1], "--help") ) { -++ printf("Usage: flash_erase MTD-device [start] [cnt (# erase blocks)] [lock]\n" -++ " flash_erase -h | --help\n") ; -++ return 16 ; -++ } -++ -++ if (argc > 2) -++ start = strtol(argv[2], NULL, 0); -++ else -++ start = 0; -++ -++ if (argc > 3) -++ count = strtol(argv[3], NULL, 0); -++ else -++ count = 1; -++ -++ if(argc > 4) -++ unlock = strtol(argv[4], NULL, 0); -++ else -++ unlock = 0; -++ -++ -++ // Open and size the device -++ if ((Fd = open(argv[1],O_RDWR)) < 0) -++ { -++ fprintf(stderr,"File open error\n"); -++ return 8; -++ } -++ -++ printf("Erase Total %d Units\n", count); -++ -++ if (ioctl(Fd,MEMGETREGIONCOUNT,®count) == 0) -++ { -++ if(regcount == 0) -++ { -++ res = non_region_erase(Fd, start, count, unlock); -++ } -++ else -++ { -++ res = region_erase(Fd, start, count, unlock, regcount); -++ } -++ } -++ -++ return res; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_eraseall.c linux-2.6.24.7/drivers/mtd/mtd-utils/flash_eraseall.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_eraseall.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/flash_eraseall.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,286 @@ -++/* eraseall.c -- erase the whole of a MTD device -++ -++ Copyright (C) 2000 Arcom Control System Ltd -++ -++ Renamed to flash_eraseall.c -++ -++ This program is free software; you can redistribute it and/or modify -++ it under the terms of the GNU General Public License as published by -++ the Free Software Foundation; either version 2 of the License, or -++ (at your option) any later version. -++ -++ This program is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with this program; if not, write to the Free Software -++ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "crc32.h" -++ -++#include -++#include -++ -++#define PROGRAM "flash_eraseall" -++#define VERSION "$Revision: 1.1.1.1 $" -++ -++static const char *exe_name; -++static const char *mtd_device; -++static int quiet; /* true -- don't output progress */ -++static int jffs2; // format for jffs2 usage -++ -++static void process_options (int argc, char *argv[]); -++static void display_help (void); -++static void display_version (void); -++static struct jffs2_unknown_node cleanmarker; -++int target_endian = __BYTE_ORDER; -++ -++int main (int argc, char *argv[]) -++{ -++ mtd_info_t meminfo; -++ int fd, clmpos = 0, clmlen = 8; -++ erase_info_t erase; -++ int isNAND, bbtest = 1; -++ -++ process_options(argc, argv); -++ -++ -++ if ((fd = open(mtd_device, O_RDWR)) < 0) { -++ fprintf(stderr, "%s: %s: %s\n", exe_name, mtd_device, strerror(errno)); -++ exit(1); -++ } -++ -++ -++ if (ioctl(fd, MEMGETINFO, &meminfo) != 0) { -++ fprintf(stderr, "%s: %s: unable to get MTD device info\n", exe_name, mtd_device); -++ exit(1); -++ } -++ -++ erase.length = meminfo.erasesize; -++ isNAND = meminfo.type == MTD_NANDFLASH ? 1 : 0; -++ -++ if (jffs2) { -++ cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK); -++ cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER); -++ if (!isNAND) -++ cleanmarker.totlen = cpu_to_je32 (sizeof (struct jffs2_unknown_node)); -++ else { -++ struct nand_oobinfo oobinfo; -++ -++ if (ioctl(fd, MEMGETOOBSEL, &oobinfo) != 0) { -++ fprintf(stderr, "%s: %s: unable to get NAND oobinfo\n", exe_name, mtd_device); -++ exit(1); -++ } -++ -++ /* Check for autoplacement */ -++ if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) { -++ /* Get the position of the free bytes */ -++ if (!oobinfo.oobfree[0][1]) { -++ fprintf (stderr, " Eeep. Autoplacement selected and no empty space in oob\n"); -++ exit(1); -++ } -++ clmpos = oobinfo.oobfree[0][0]; -++ clmlen = oobinfo.oobfree[0][1]; -++ if (clmlen > 8) -++ clmlen = 8; -++ } else { -++ /* Legacy mode */ -++ switch (meminfo.oobsize) { -++ case 8: -++ clmpos = 6; -++ clmlen = 2; -++ break; -++ case 16: -++ clmpos = 8; -++ clmlen = 8; -++ break; -++ case 64: -++ clmpos = 16; -++ clmlen = 8; -++ break; -++ } -++ } -++ cleanmarker.totlen = cpu_to_je32(8); -++ } -++ cleanmarker.hdr_crc = cpu_to_je32 (crc32 (0, &cleanmarker, sizeof (struct jffs2_unknown_node) - 4)); -++ } -++ -++ for (erase.start = 0; erase.start < meminfo.size; erase.start += meminfo.erasesize) { -++ if (bbtest) { -++ unsigned long long offset = erase.start; -++ int ret = ioctl(fd, MEMGETBADBLOCK, &offset); -++ if (ret > 0) { -++ if (!quiet) -++ printf ("\nSkipping bad block at 0x%09llx\n", erase.start); -++ continue; -++ } else if (ret < 0) { -++ if (errno == EOPNOTSUPP) { -++ bbtest = 0; -++ if (isNAND) { -++ fprintf(stderr, "%s: %s: Bad block check not available\n", exe_name, mtd_device); -++ exit(1); -++ } -++ } else { -++ fprintf(stderr, "\n%s: %s: MTD get bad block failed: %s\n", exe_name, mtd_device, strerror(errno)); -++ exit(1); -++ } -++ } -++ } -++ -++ if (!quiet) { -++ printf -++ ("\rErasing %d Kibyte @ %llx -- %2u %% complete.", -++ meminfo.erasesize / 1024, erase.start, -++ (unsigned long long) -++ erase.start * 100 / meminfo.size); -++ } -++ fflush(stdout); -++ -++ if (ioctl(fd, MEMERASE, &erase) != 0) { -++ fprintf(stderr, "\n%s: %s: MTD Erase failure: %s\n", exe_name, mtd_device, strerror(errno)); -++ continue; -++ } -++ -++ /* format for JFFS2 ? */ -++ if (!jffs2) -++ continue; -++ -++ /* write cleanmarker */ -++ if (isNAND) { -++ struct mtd_oob_buf oob; -++ oob.ptr = (unsigned char *) &cleanmarker; -++ oob.start = erase.start + clmpos; -++ oob.length = clmlen; -++ if (ioctl (fd, MEMWRITEOOB, &oob) != 0) { -++ fprintf(stderr, "\n%s: %s: MTD writeoob failure: %s\n", exe_name, mtd_device, strerror(errno)); -++ continue; -++ } -++ } else { -++ if (lseek (fd, erase.start, SEEK_SET) < 0) { -++ fprintf(stderr, "\n%s: %s: MTD lseek failure: %s\n", exe_name, mtd_device, strerror(errno)); -++ continue; -++ } -++ if (write (fd , &cleanmarker, sizeof (cleanmarker)) != sizeof (cleanmarker)) { -++ fprintf(stderr, "\n%s: %s: MTD write failure: %s\n", exe_name, mtd_device, strerror(errno)); -++ continue; -++ } -++ } -++ if (!quiet) -++ printf (" Cleanmarker written at %x.", erase.start); -++ } -++ if (!quiet) -++ printf("\n"); -++ -++ return 0; -++} -++ -++ -++void process_options (int argc, char *argv[]) -++{ -++ int error = 0; -++ -++ exe_name = argv[0]; -++ -++ for (;;) { -++ int option_index = 0; -++ static const char *short_options = "jq"; -++ static const struct option long_options[] = { -++ {"help", no_argument, 0, 0}, -++ {"version", no_argument, 0, 0}, -++ {"jffs2", no_argument, 0, 'j'}, -++ {"quiet", no_argument, 0, 'q'}, -++ {"silent", no_argument, 0, 'q'}, -++ -++ {0, 0, 0, 0}, -++ }; -++ -++ int c = getopt_long(argc, argv, short_options, -++ long_options, &option_index); -++ if (c == EOF) { -++ break; -++ } -++ -++ switch (c) { -++ case 0: -++ switch (option_index) { -++ case 0: -++ display_help(); -++ break; -++ case 1: -++ display_version(); -++ break; -++ } -++ break; -++ case 'q': -++ quiet = 1; -++ break; -++ case 'j': -++ jffs2 = 1; -++ break; -++ case '?': -++ error = 1; -++ break; -++ } -++ } -++ if (optind == argc) { -++ fprintf(stderr, "%s: no MTD device specified\n", exe_name); -++ error = 1; -++ } -++ if (error) { -++ fprintf(stderr, "Try `%s --help' for more information.\n", -++ exe_name); -++ exit(1); -++ } -++ -++ mtd_device = argv[optind]; -++} -++ -++ -++void display_help (void) -++{ -++ printf("Usage: %s [OPTION] MTD_DEVICE\n" -++ "Erases all of the specified MTD device.\n" -++ "\n" -++ " -j, --jffs2 format the device for jffs2\n" -++ " -q, --quiet don't display progress messages\n" -++ " --silent same as --quiet\n" -++ " --help display this help and exit\n" -++ " --version output version information and exit\n", -++ exe_name); -++ exit(0); -++} -++ -++ -++void display_version (void) -++{ -++ printf(PROGRAM " " VERSION "\n" -++ "\n" -++ "Copyright (C) 2000 Arcom Control Systems Ltd\n" -++ "\n" -++ PROGRAM " comes with NO WARRANTY\n" -++ "to the extent permitted by law.\n" -++ "\n" -++ "You may redistribute copies of " PROGRAM "\n" -++ "under the terms of the GNU General Public Licence.\n" -++ "See the file `COPYING' for more information.\n"); -++ exit(0); -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_info.c linux-2.6.24.7/drivers/mtd/mtd-utils/flash_info.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_info.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/flash_info.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,55 @@ -++/* -++ * flash_info.c -- print info about a MTD device -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++ -++int main(int argc,char *argv[]) -++{ -++ int regcount; -++ int Fd; -++ -++ if (1 >= argc) -++ { -++ fprintf(stderr,"Usage: flash_info device\n"); -++ return 16; -++ } -++ -++ // Open and size the device -++ if ((Fd = open(argv[1],O_RDONLY)) < 0) -++ { -++ fprintf(stderr,"File open error\n"); -++ return 8; -++ } -++ -++ if (ioctl(Fd,MEMGETREGIONCOUNT,®count) == 0) -++ { -++ int i; -++ region_info_t reginfo; -++ printf("Device %s has %d erase regions\n", argv[1], regcount); -++ for (i = 0; i < regcount; i++) -++ { -++ reginfo.regionindex = i; -++ if(ioctl(Fd, MEMGETREGIONINFO, ®info) == 0) -++ { -++ printf("Region %d is at 0x%x with size 0x%x and " -++ "has 0x%x blocks\n", i, reginfo.offset, -++ reginfo.erasesize, reginfo.numblocks); -++ } -++ else -++ { -++ printf("Strange can not read region %d from a %d region device\n", -++ i, regcount); -++ } -++ } -++ } -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_lock.c linux-2.6.24.7/drivers/mtd/mtd-utils/flash_lock.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_lock.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/flash_lock.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,84 @@ -++/* -++ * FILE flash_lock.c -++ * -++ * This utility locks one or more sectors of flash device. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++ -++int main(int argc, char *argv[]) -++{ -++ int fd; -++ struct mtd_info_user mtdInfo; -++ struct erase_info_user mtdLockInfo; -++ int num_sectors; -++ int ofs; -++ -++ /* -++ * Parse command line options -++ */ -++ if(argc != 4) -++ { -++ fprintf(stderr, "USAGE: %s \n", argv[0]); -++ exit(1); -++ } -++ else if(strncmp(argv[1], "/dev/mtd", 8) != 0) -++ { -++ fprintf(stderr, "'%s' is not a MTD device. Must specify mtd device: /dev/mtd?\n", argv[1]); -++ exit(1); -++ } -++ -++ fd = open(argv[1], O_RDWR); -++ if(fd < 0) -++ { -++ fprintf(stderr, "Could not open mtd device: %s\n", argv[1]); -++ exit(1); -++ } -++ -++ if(ioctl(fd, MEMGETINFO, &mtdInfo)) -++ { -++ fprintf(stderr, "Could not get MTD device info from %s\n", argv[1]); -++ close(fd); -++ exit(1); -++ } -++ sscanf(argv[2], "%x",&ofs); -++ sscanf(argv[3], "%d",&num_sectors); -++ if(ofs > mtdInfo.size - mtdInfo.erasesize) -++ { -++ fprintf(stderr, "%x is beyond device size %x\n",ofs,(unsigned int)(mtdInfo.size - mtdInfo.erasesize)); -++ exit(1); -++ } -++ -++ if (num_sectors == -1) { -++ num_sectors = mtdInfo.size/mtdInfo.erasesize; -++ } -++ else { -++ if(num_sectors > mtdInfo.size/mtdInfo.erasesize) -++ { -++ fprintf(stderr, "%d are too many sectors, device only has %d\n",num_sectors,(int)(mtdInfo.size/mtdInfo.erasesize)); -++ exit(1); -++ } -++ } -++ -++ mtdLockInfo.start = ofs; -++ mtdLockInfo.length = num_sectors * mtdInfo.erasesize; -++ if(ioctl(fd, MEMLOCK, &mtdLockInfo)) -++ { -++ fprintf(stderr, "Could not lock MTD device: %s\n", argv[1]); -++ close(fd); -++ exit(1); -++ } -++ -++ return 0; -++} -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_otp_dump.c linux-2.6.24.7/drivers/mtd/mtd-utils/flash_otp_dump.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_otp_dump.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/flash_otp_dump.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,54 @@ -++/* -++ * flash_otp_dump.c -- display One-Time-Programm data -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++ -++int main(int argc,char *argv[]) -++{ -++ int fd, val, i, offset, ret; -++ unsigned char buf[16]; -++ -++ if (argc != 3 || (strcmp(argv[1], "-f") && strcmp(argv[1], "-u"))) { -++ fprintf(stderr,"Usage: %s [ -f | -u ] \n", argv[0]); -++ return EINVAL; -++ } -++ -++ fd = open(argv[2], O_RDONLY); -++ if (fd < 0) { -++ perror(argv[2]); -++ return errno; -++ } -++ -++ val = argv[1][1] == 'f' ? MTD_OTP_FACTORY : MTD_OTP_USER; -++ ret = ioctl(fd, OTPSELECT, &val); -++ if (ret < 0) { -++ perror("OTPSELECT"); -++ return errno; -++ } -++ -++ printf("OTP %s data for %s\n", -++ argv[1][1] == 'f' ? "factory" : "user", argv[2]); -++ offset = 0; -++ while ((ret = read(fd, buf, sizeof(buf)))) { -++ if (ret < 0) { -++ perror("read()"); -++ return errno; -++ } -++ printf("0x%04x:", offset); -++ for (i = 0; i < ret; i++) -++ printf(" %02x", buf[i]); -++ printf("\n"); -++ offset += ret; -++ } -++ -++ close(fd); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_otp_info.c linux-2.6.24.7/drivers/mtd/mtd-utils/flash_otp_info.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_otp_info.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/flash_otp_info.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,63 @@ -++/* -++ * flash_otp_info.c -- print info about One-Time-Programm data -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++ -++int main(int argc,char *argv[]) -++{ -++ int fd, val, i, ret; -++ -++ if (argc != 3 || (strcmp(argv[1], "-f") && strcmp(argv[1], "-u"))) { -++ fprintf(stderr,"Usage: %s [ -f | -u ] \n", argv[0]); -++ return EINVAL; -++ } -++ -++ fd = open(argv[2], O_RDONLY); -++ if (fd < 0) { -++ perror(argv[2]); -++ return errno; -++ } -++ -++ val = argv[1][1] == 'f' ? MTD_OTP_FACTORY : MTD_OTP_USER; -++ ret = ioctl(fd, OTPSELECT, &val); -++ if (ret < 0) { -++ perror("OTPSELECT"); -++ return errno; -++ } -++ -++ ret = ioctl(fd, OTPGETREGIONCOUNT, &val); -++ if (ret < 0) { -++ perror("OTPGETREGIONCOUNT"); -++ return errno; -++ } -++ -++ printf("Number of OTP %s blocks on %s: %d\n", -++ argv[1][1] == 'f' ? "factory" : "user", argv[2], val); -++ -++ if (val > 0) { -++ struct otp_info info[val]; -++ -++ ret = ioctl(fd, OTPGETREGIONINFO, &info); -++ if (ret < 0) { -++ perror("OTPGETREGIONCOUNT"); -++ return errno; -++ } -++ -++ for (i = 0; i < val; i++) -++ printf("block %2d: offset = 0x%04x " -++ "size = %2d bytes %s\n", -++ i, info[i].start, info[i].length, -++ info[i].locked ? "[locked]" : "[unlocked]"); -++ } -++ -++ close(fd); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_otp_lock.c linux-2.6.24.7/drivers/mtd/mtd-utils/flash_otp_lock.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_otp_lock.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/flash_otp_lock.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,70 @@ -++/* -++ * flash_otp_lock.c -- lock area of One-Time-Program data -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++ -++int main(int argc,char *argv[]) -++{ -++ int fd, val, ret, offset, size; -++ char *p, buf[8]; -++ -++ if (argc != 5 || strcmp(argv[1], "-u")) { -++ fprintf(stderr, "Usage: %s -u \n", argv[0]); -++ fprintf(stderr, "offset and size must match on OTP region boundaries\n"); -++ fprintf(stderr, "CAUTION! ONCE LOCKED, OTP REGIONS CAN'T BE UNLOCKED!\n"); -++ return EINVAL; -++ } -++ -++ fd = open(argv[2], O_WRONLY); -++ if (fd < 0) { -++ perror(argv[2]); -++ return errno; -++ } -++ -++ val = MTD_OTP_USER; -++ ret = ioctl(fd, OTPSELECT, &val); -++ if (ret < 0) { -++ perror("OTPSELECT"); -++ return errno; -++ } -++ -++ offset = strtoul(argv[3], &p, 0); -++ if (argv[3][0] == 0 || *p != 0) { -++ fprintf(stderr, "%s: bad offset value\n", argv[0]); -++ return ERANGE; -++ } -++ -++ size = strtoul(argv[4], &p, 0); -++ if (argv[4][0] == 0 || *p != 0) { -++ fprintf(stderr, "%s: bad size value\n", argv[0]); -++ return ERANGE; -++ } -++ -++ printf("About to lock OTP user data on %s from 0x%x to 0x%x\n", -++ argv[2], offset, offset + size); -++ printf("Are you sure (yes|no)? "); -++ if (fgets(buf, sizeof(buf), stdin) && strcmp(buf, "yes\n") == 0) { -++ struct otp_info info; -++ info.start = offset; -++ info.length = size; -++ ret = ioctl(fd, OTPLOCK, &info); -++ if (ret < 0) { -++ perror("OTPLOCK"); -++ return errno; -++ } -++ printf("Done.\n"); -++ } else { -++ printf("Aborted\n"); -++ } -++ -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_otp_write.c linux-2.6.24.7/drivers/mtd/mtd-utils/flash_otp_write.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_otp_write.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/flash_otp_write.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,96 @@ -++/* -++ * flash_otp_write.c -- write One-Time-Program data -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++ -++int main(int argc,char *argv[]) -++{ -++ int fd, val, ret, size, wrote, len; -++ mtd_info_t mtdInfo; -++ off_t offset; -++ char *p, buf[2048]; -++ -++ if (argc != 4 || strcmp(argv[1], "-u")) { -++ fprintf(stderr, "Usage: %s -u \n", argv[0]); -++ fprintf(stderr, "the raw data to write should be provided on stdin\n"); -++ fprintf(stderr, "CAUTION! ONCE SET TO 0, OTP DATA BITS CAN'T BE ERASED!\n"); -++ return EINVAL; -++ } -++ -++ fd = open(argv[2], O_WRONLY); -++ if (fd < 0) { -++ perror(argv[2]); -++ return errno; -++ } -++ -++ val = MTD_OTP_USER; -++ ret = ioctl(fd, OTPSELECT, &val); -++ if (ret < 0) { -++ perror("OTPSELECT"); -++ return errno; -++ } -++ -++ if (ioctl(fd, MEMGETINFO, &mtdInfo)) { -++ perror("MEMGETINFO"); -++ return errno; -++ } -++ -++ offset = strtoul(argv[3], &p, 0); -++ if (argv[3][0] == 0 || *p != 0) { -++ fprintf(stderr, "%s: bad offset value\n", argv[0]); -++ return ERANGE; -++ } -++ -++ if (lseek(fd, offset, SEEK_SET) == (off_t)-1) { -++ perror("lseek()"); -++ return errno; -++ } -++ -++ printf("Writing OTP user data on %s at offset 0x%lx\n", argv[2], offset); -++ -++ if (mtdInfo.type == MTD_NANDFLASH) -++ len = mtdInfo.writesize; -++ else -++ len = 256; -++ -++ wrote = 0; -++ while ((size = read(0, buf, len))) { -++ if (size < 0) { -++ perror("read()"); -++ return errno; -++ } -++ p = buf; -++ while (size > 0) { -++ if (mtdInfo.type == MTD_NANDFLASH) { -++ /* Fill remain buffers with 0xff */ -++ memset(buf + size, 0xff, mtdInfo.writesize - size); -++ size = mtdInfo.writesize; -++ } -++ ret = write(fd, p, size); -++ if (ret < 0) { -++ perror("write()"); -++ return errno; -++ } -++ if (ret == 0) { -++ printf("write() returned 0 after writing %d bytes\n", wrote); -++ return 0; -++ } -++ p += ret; -++ wrote += ret; -++ size -= ret; -++ } -++ } -++ -++ printf("Wrote %d bytes of OTP user data\n", wrote); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_unlock.c linux-2.6.24.7/drivers/mtd/mtd-utils/flash_unlock.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/flash_unlock.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/flash_unlock.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,64 @@ -++/* -++ * FILE flash_unlock.c -++ * -++ * This utility unlock all sectors of flash device. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++ -++int main(int argc, char *argv[]) -++{ -++ int fd; -++ struct mtd_info_user mtdInfo; -++ struct erase_info_user mtdLockInfo; -++ -++ /* -++ * Parse command line options -++ */ -++ if(argc != 2) -++ { -++ fprintf(stderr, "USAGE: %s \n", argv[0]); -++ exit(1); -++ } -++ else if(strncmp(argv[1], "/dev/mtd", 8) != 0) -++ { -++ fprintf(stderr, "'%s' is not a MTD device. Must specify mtd device: /dev/mtd?\n", argv[1]); -++ exit(1); -++ } -++ -++ fd = open(argv[1], O_RDWR); -++ if(fd < 0) -++ { -++ fprintf(stderr, "Could not open mtd device: %s\n", argv[1]); -++ exit(1); -++ } -++ -++ if(ioctl(fd, MEMGETINFO, &mtdInfo)) -++ { -++ fprintf(stderr, "Could not get MTD device info from %s\n", argv[1]); -++ close(fd); -++ exit(1); -++ } -++ -++ mtdLockInfo.start = 0; -++ mtdLockInfo.length = mtdInfo.size; -++ if(ioctl(fd, MEMUNLOCK, &mtdLockInfo)) -++ { -++ fprintf(stderr, "Could not unlock MTD device: %s\n", argv[1]); -++ close(fd); -++ exit(1); -++ } -++ -++ return 0; -++} -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/flashcp.c linux-2.6.24.7/drivers/mtd/mtd-utils/flashcp.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/flashcp.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/flashcp.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,389 @@ -++/* -++ * Copyright (c) 2d3D, Inc. -++ * Written by Abraham vd Merwe -++ * All rights reserved. -++ * -++ * Renamed to flashcp.c to avoid conflicts with fcp from fsh package -++ * -++ * Redistribution and use in source and binary forms, with or without -++ * modification, are permitted provided that the following conditions -++ * are met: -++ * 1. Redistributions of source code must retain the above copyright -++ * notice, this list of conditions and the following disclaimer. -++ * 2. Redistributions in binary form must reproduce the above copyright -++ * notice, this list of conditions and the following disclaimer in the -++ * documentation and/or other materials provided with the distribution. -++ * 3. Neither the name of the author nor the names of other contributors -++ * may be used to endorse or promote products derived from this software -++ * without specific prior written permission. -++ * -++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -++ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++typedef int bool; -++#define true 1 -++#define false 0 -++ -++#define EXIT_FAILURE 1 -++#define EXIT_SUCCESS 0 -++ -++/* for debugging purposes only */ -++#ifdef DEBUG -++#undef DEBUG -++#define DEBUG(fmt,args...) { log_printf (LOG_ERROR,"%d: ",__LINE__); log_printf (LOG_ERROR,fmt,## args); } -++#else -++#undef DEBUG -++#define DEBUG(fmt,args...) -++#endif -++ -++#define KB(x) ((x) / 1024) -++#define PERCENTAGE(x,total) (((x) * 100) / (total)) -++ -++/* size of read/write buffer */ -++#define BUFSIZE (10 * 1024) -++ -++/* cmd-line flags */ -++#define FLAG_NONE 0x00 -++#define FLAG_VERBOSE 0x01 -++#define FLAG_HELP 0x02 -++#define FLAG_FILENAME 0x04 -++#define FLAG_DEVICE 0x08 -++ -++/* error levels */ -++#define LOG_NORMAL 1 -++#define LOG_ERROR 2 -++ -++static void log_printf (int level,const char *fmt, ...) -++{ -++ FILE *fp = level == LOG_NORMAL ? stdout : stderr; -++ va_list ap; -++ va_start (ap,fmt); -++ vfprintf (fp,fmt,ap); -++ va_end (ap); -++ fflush (fp); -++} -++ -++static void showusage (const char *progname,bool error) -++{ -++ int level = error ? LOG_ERROR : LOG_NORMAL; -++ -++ log_printf (level, -++ "\n" -++ "Flash Copy - Written by Abraham van der Merwe \n" -++ "\n" -++ "usage: %s [ -v | --verbose ] \n" -++ " %s -h | --help\n" -++ "\n" -++ " -h | --help Show this help message\n" -++ " -v | --verbose Show progress reports\n" -++ " File which you want to copy to flash\n" -++ " Flash device to write to (e.g. /dev/mtd0, /dev/mtd1, etc.)\n" -++ "\n", -++ progname,progname); -++ -++ exit (error ? EXIT_FAILURE : EXIT_SUCCESS); -++} -++ -++static int safe_open (const char *pathname,int flags) -++{ -++ int fd; -++ -++ fd = open (pathname,flags); -++ if (fd < 0) -++ { -++ log_printf (LOG_ERROR,"While trying to open %s",pathname); -++ if (flags & O_RDWR) -++ log_printf (LOG_ERROR," for read/write access"); -++ else if (flags & O_RDONLY) -++ log_printf (LOG_ERROR," for read access"); -++ else if (flags & O_WRONLY) -++ log_printf (LOG_ERROR," for write access"); -++ log_printf (LOG_ERROR,": %m\n"); -++ exit (EXIT_FAILURE); -++ } -++ -++ return (fd); -++} -++ -++static void safe_read (int fd,const char *filename,void *buf,size_t count,bool verbose) -++{ -++ ssize_t result; -++ -++ result = read (fd,buf,count); -++ if (count != result) -++ { -++ if (verbose) log_printf (LOG_NORMAL,"\n"); -++ if (result < 0) -++ { -++ log_printf (LOG_ERROR,"While reading data from %s: %m\n",filename); -++ exit (EXIT_FAILURE); -++ } -++ log_printf (LOG_ERROR,"Short read count returned while reading from %s\n",filename); -++ exit (EXIT_FAILURE); -++ } -++} -++ -++static void safe_rewind (int fd,const char *filename) -++{ -++ if (lseek (fd,0L,SEEK_SET) < 0) -++ { -++ log_printf (LOG_ERROR,"While seeking to start of %s: %m\n",filename); -++ exit (EXIT_FAILURE); -++ } -++} -++ -++/******************************************************************************/ -++ -++static int dev_fd = -1,fil_fd = -1; -++ -++static void cleanup (void) -++{ -++ if (dev_fd > 0) close (dev_fd); -++ if (fil_fd > 0) close (fil_fd); -++} -++ -++int main (int argc,char *argv[]) -++{ -++ const char *progname,*filename = NULL,*device = NULL; -++ int i,flags = FLAG_NONE; -++ ssize_t result; -++ size_t size,written; -++ struct mtd_info_user mtd; -++ struct erase_info_user erase; -++ struct stat filestat; -++ unsigned char src[BUFSIZE],dest[BUFSIZE]; -++ -++ (progname = strrchr (argv[0],'/')) ? progname++ : (progname = argv[0]); -++ -++ /********************* -++ * parse cmd-line -++ *****************/ -++ -++ for (;;) { -++ int option_index = 0; -++ static const char *short_options = "hv"; -++ static const struct option long_options[] = { -++ {"help", no_argument, 0, 'h'}, -++ {"verbose", no_argument, 0, 'v'}, -++ {0, 0, 0, 0}, -++ }; -++ -++ int c = getopt_long(argc, argv, short_options, -++ long_options, &option_index); -++ if (c == EOF) { -++ break; -++ } -++ -++ switch (c) { -++ case 'h': -++ flags |= FLAG_HELP; -++ DEBUG("Got FLAG_HELP\n"); -++ break; -++ case 'v': -++ flags |= FLAG_VERBOSE; -++ DEBUG("Got FLAG_VERBOSE\n"); -++ break; -++ default: -++ DEBUG("Unknown parameter: %s\n",argv[option_index]); -++ showusage (progname,true); -++ } -++ } -++ if (optind+2 == argc) { -++ flags |= FLAG_FILENAME; -++ filename = argv[optind]; -++ DEBUG("Got filename: %s\n",filename); -++ -++ flags |= FLAG_DEVICE; -++ device = argv[optind+1]; -++ DEBUG("Got device: %s\n",device); -++ } -++ -++ if (flags & FLAG_HELP || progname == NULL || device == NULL) -++ showusage (progname,flags != FLAG_HELP); -++ -++ atexit (cleanup); -++ -++ /* get some info about the flash device */ -++ dev_fd = safe_open (device,O_SYNC | O_RDWR); -++ if (ioctl (dev_fd,MEMGETINFO,&mtd) < 0) -++ { -++ DEBUG("ioctl(): %m\n"); -++ log_printf (LOG_ERROR,"This doesn't seem to be a valid MTD flash device!\n"); -++ exit (EXIT_FAILURE); -++ } -++ -++ /* get some info about the file we want to copy */ -++ fil_fd = safe_open (filename,O_RDONLY); -++ if (fstat (fil_fd,&filestat) < 0) -++ { -++ log_printf (LOG_ERROR,"While trying to get the file status of %s: %m\n",filename); -++ exit (EXIT_FAILURE); -++ } -++ -++ /* does it fit into the device/partition? */ -++ if (filestat.st_size > mtd.size) -++ { -++ log_printf (LOG_ERROR,"%s won't fit into %s!\n",filename,device); -++ exit (EXIT_FAILURE); -++ } -++ -++ /***************************************************** -++ * erase enough blocks so that we can write the file * -++ *****************************************************/ -++ -++#warning "Check for smaller erase regions" -++ -++ erase.start = 0; -++ erase.length = filestat.st_size & ~(mtd.erasesize - 1); -++ if (filestat.st_size % mtd.erasesize) erase.length += mtd.erasesize; -++ if (flags & FLAG_VERBOSE) -++ { -++ /* if the user wants verbose output, erase 1 block at a time and show him/her what's going on */ -++ int blocks = erase.length / mtd.erasesize; -++ erase.length = mtd.erasesize; -++ log_printf (LOG_NORMAL,"Erasing blocks: 0/%d (0%%)",blocks); -++ for (i = 1; i <= blocks; i++) -++ { -++ log_printf (LOG_NORMAL,"\rErasing blocks: %d/%d (%d%%)",i,blocks,PERCENTAGE (i,blocks)); -++ if (ioctl (dev_fd,MEMERASE,&erase) < 0) -++ { -++ log_printf (LOG_NORMAL,"\n"); -++ log_printf (LOG_ERROR, -++ "While erasing blocks 0x%.8x-0x%.8x on %s: %m\n", -++ (unsigned int) erase.start,(unsigned int) (erase.start + erase.length),device); -++ exit (EXIT_FAILURE); -++ } -++ erase.start += mtd.erasesize; -++ } -++ log_printf (LOG_NORMAL,"\rErasing blocks: %d/%d (100%%)\n",blocks,blocks); -++ } -++ else -++ { -++ /* if not, erase the whole chunk in one shot */ -++ if (ioctl (dev_fd,MEMERASE,&erase) < 0) -++ { -++ log_printf (LOG_ERROR, -++ "While erasing blocks from 0x%.8x-0x%.8x on %s: %m\n", -++ (unsigned int) erase.start,(unsigned int) (erase.start + erase.length),device); -++ exit (EXIT_FAILURE); -++ } -++ } -++ DEBUG("Erased %u / %luk bytes\n",erase.length,filestat.st_size); -++ -++ /********************************** -++ * write the entire file to flash * -++ **********************************/ -++ -++ if (flags & FLAG_VERBOSE) log_printf (LOG_NORMAL,"Writing data: 0k/%luk (0%%)",KB (filestat.st_size)); -++ size = filestat.st_size; -++ i = BUFSIZE; -++ written = 0; -++ while (size) -++ { -++ if (size < BUFSIZE) i = size; -++ if (flags & FLAG_VERBOSE) -++ log_printf (LOG_NORMAL,"\rWriting data: %dk/%luk (%lu%%)", -++ KB (written + i), -++ KB (filestat.st_size), -++ PERCENTAGE (written + i,filestat.st_size)); -++ -++ /* read from filename */ -++ safe_read (fil_fd,filename,src,i,flags & FLAG_VERBOSE); -++ -++ /* write to device */ -++ result = write (dev_fd,src,i); -++ if (i != result) -++ { -++ if (flags & FLAG_VERBOSE) log_printf (LOG_NORMAL,"\n"); -++ if (result < 0) -++ { -++ log_printf (LOG_ERROR, -++ "While writing data to 0x%.8x-0x%.8x on %s: %m\n", -++ written,written + i,device); -++ exit (EXIT_FAILURE); -++ } -++ log_printf (LOG_ERROR, -++ "Short write count returned while writing to x%.8x-0x%.8x on %s: %d/%lu bytes written to flash\n", -++ written,written + i,device,written + result,filestat.st_size); -++ exit (EXIT_FAILURE); -++ } -++ -++ written += i; -++ size -= i; -++ } -++ if (flags & FLAG_VERBOSE) -++ log_printf (LOG_NORMAL, -++ "\rWriting data: %luk/%luk (100%%)\n", -++ KB (filestat.st_size), -++ KB (filestat.st_size)); -++ DEBUG("Wrote %d / %luk bytes\n",written,filestat.st_size); -++ -++ /********************************** -++ * verify that flash == file data * -++ **********************************/ -++ -++ safe_rewind (fil_fd,filename); -++ safe_rewind (dev_fd,device); -++ size = filestat.st_size; -++ i = BUFSIZE; -++ written = 0; -++ if (flags & FLAG_VERBOSE) log_printf (LOG_NORMAL,"Verifying data: 0k/%luk (0%%)",KB (filestat.st_size)); -++ while (size) -++ { -++ if (size < BUFSIZE) i = size; -++ if (flags & FLAG_VERBOSE) -++ log_printf (LOG_NORMAL, -++ "\rVerifying data: %dk/%luk (%lu%%)", -++ KB (written + i), -++ KB (filestat.st_size), -++ PERCENTAGE (written + i,filestat.st_size)); -++ -++ /* read from filename */ -++ safe_read (fil_fd,filename,src,i,flags & FLAG_VERBOSE); -++ -++ /* read from device */ -++ safe_read (dev_fd,device,dest,i,flags & FLAG_VERBOSE); -++ -++ /* compare buffers */ -++ if (memcmp (src,dest,i)) -++ { -++ log_printf (LOG_ERROR, -++ "File does not seem to match flash data. First mismatch at 0x%.8x-0x%.8x\n", -++ written,written + i); -++ exit (EXIT_FAILURE); -++ } -++ -++ written += i; -++ size -= i; -++ } -++ if (flags & FLAG_VERBOSE) -++ log_printf (LOG_NORMAL, -++ "\rVerifying data: %luk/%luk (100%%)\n", -++ KB (filestat.st_size), -++ KB (filestat.st_size)); -++ DEBUG("Verified %d / %luk bytes\n",written,filestat.st_size); -++ -++ exit (EXIT_SUCCESS); -++} -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ftl_check.c linux-2.6.24.7/drivers/mtd/mtd-utils/ftl_check.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ftl_check.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ftl_check.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,232 @@ -++/* Ported to MTD system. -++ * Based on: -++ */ -++/*====================================================================== -++ -++ Utility to create an FTL partition in a memory region -++ -++ ftl_check.c 1.10 1999/10/25 20:01:35 -++ -++ The contents of this file are subject to the Mozilla Public -++ License Version 1.1 (the "License"); you may not use this file -++ except in compliance with the License. You may obtain a copy of -++ the License at http://www.mozilla.org/MPL/ -++ -++ Software distributed under the License is distributed on an "AS -++ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -++ implied. See the License for the specific language governing -++ rights and limitations under the License. -++ -++ The initial developer of the original code is David A. Hinds -++ . Portions created by David A. Hinds -++ are Copyright (C) 1999 David A. Hinds. All Rights Reserved. -++ -++ Alternatively, the contents of this file may be used under the -++ terms of the GNU Public License version 2 (the "GPL"), in which -++ case the provisions of the GPL are applicable instead of the -++ above. If you wish to allow the use of your version of this file -++ only under the terms of the GPL and not to allow others to use -++ your version of this file under the MPL, indicate your decision -++ by deleting the provisions above and replace them with the notice -++ and other provisions required by the GPL. If you do not delete -++ the provisions above, a recipient may use your version of this -++ file under either the MPL or the GPL. -++ -++ ======================================================================*/ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#include -++#include -++ -++#if __BYTE_ORDER == __LITTLE_ENDIAN -++# define TO_LE32(x) (x) -++# define TO_LE16(x) (x) -++#elif __BYTE_ORDER == __BIG_ENDIAN -++# define TO_LE32(x) (bswap_32(x)) -++# define TO_LE16(x) (bswap_16(x)) -++#else -++# error cannot detect endianess -++#endif -++ -++#define FROM_LE32(x) TO_LE32(x) -++#define FROM_LE16(x) TO_LE16(x) -++ -++/*====================================================================*/ -++ -++static void print_size(u_int s) -++{ -++ if ((s > 0x100000) && ((s % 0x100000) == 0)) -++ printf("%d mb", s / 0x100000); -++ else if ((s > 0x400) && ((s % 0x400) == 0)) -++ printf("%d kb", s / 0x400); -++ else -++ printf("%d bytes", s); -++} -++ -++/*====================================================================*/ -++ -++static void check_partition(int fd, int verbose) -++{ -++ mtd_info_t mtd; -++ erase_unit_header_t hdr, hdr2; -++ u_int i, j, nbam, *bam; -++ int control, data, free, deleted; -++ -++ /* Get partition size, block size */ -++ if (ioctl(fd, MEMGETINFO, &mtd) != 0) { -++ perror("get info failed"); -++ return; -++ } -++ -++ printf("Memory region info:\n"); -++ printf(" Region size = "); -++ print_size(mtd.size); -++ printf(" Erase block size = "); -++ print_size(mtd.erasesize); -++ printf("\n\n"); -++ -++ for (i = 0; i < mtd.size/mtd.erasesize; i++) { -++ if (lseek(fd, (i * mtd.erasesize), SEEK_SET) == -1) { -++ perror("seek failed"); -++ break; -++ } -++ read(fd, &hdr, sizeof(hdr)); -++ if ((FROM_LE32(hdr.FormattedSize) > 0) && -++ (FROM_LE32(hdr.FormattedSize) <= mtd.size) && -++ (FROM_LE16(hdr.NumEraseUnits) > 0) && -++ (FROM_LE16(hdr.NumEraseUnits) <= mtd.size/mtd.erasesize)) -++ break; -++ } -++ if (i == mtd.size/mtd.erasesize) { -++ fprintf(stderr, "No valid erase unit headers!\n"); -++ return; -++ } -++ -++ printf("Partition header:\n"); -++ printf(" Formatted size = "); -++ print_size(FROM_LE32(hdr.FormattedSize)); -++ printf(", erase units = %d, transfer units = %d\n", -++ FROM_LE16(hdr.NumEraseUnits), hdr.NumTransferUnits); -++ printf(" Erase unit size = "); -++ print_size(1 << hdr.EraseUnitSize); -++ printf(", virtual block size = "); -++ print_size(1 << hdr.BlockSize); -++ printf("\n"); -++ -++ /* Create basic block allocation table for control blocks */ -++ nbam = (mtd.erasesize >> hdr.BlockSize); -++ bam = malloc(nbam * sizeof(u_int)); -++ -++ for (i = 0; i < FROM_LE16(hdr.NumEraseUnits); i++) { -++ if (lseek(fd, (i << hdr.EraseUnitSize), SEEK_SET) == -1) { -++ perror("seek failed"); -++ break; -++ } -++ if (read(fd, &hdr2, sizeof(hdr2)) == -1) { -++ perror("read failed"); -++ break; -++ } -++ printf("\nErase unit %d:\n", i); -++ if ((hdr2.FormattedSize != hdr.FormattedSize) || -++ (hdr2.NumEraseUnits != hdr.NumEraseUnits) || -++ (hdr2.SerialNumber != hdr.SerialNumber)) -++ printf(" Erase unit header is corrupt.\n"); -++ else if (FROM_LE16(hdr2.LogicalEUN) == 0xffff) -++ printf(" Transfer unit, erase count = %d\n", FROM_LE32(hdr2.EraseCount)); -++ else { -++ printf(" Logical unit %d, erase count = %d\n", -++ FROM_LE16(hdr2.LogicalEUN), FROM_LE32(hdr2.EraseCount)); -++ if (lseek(fd, (i << hdr.EraseUnitSize)+FROM_LE32(hdr.BAMOffset), -++ SEEK_SET) == -1) { -++ perror("seek failed"); -++ break; -++ } -++ if (read(fd, bam, nbam * sizeof(u_int)) == -1) { -++ perror("read failed"); -++ break; -++ } -++ free = deleted = control = data = 0; -++ for (j = 0; j < nbam; j++) { -++ if (BLOCK_FREE(FROM_LE32(bam[j]))) -++ free++; -++ else if (BLOCK_DELETED(FROM_LE32(bam[j]))) -++ deleted++; -++ else switch (BLOCK_TYPE(FROM_LE32(bam[j]))) { -++ case BLOCK_CONTROL: control++; break; -++ case BLOCK_DATA: data++; break; -++ default: break; -++ } -++ } -++ printf(" Block allocation: %d control, %d data, %d free," -++ " %d deleted\n", control, data, free, deleted); -++ } -++ } -++} /* format_partition */ -++ -++/* Show usage information */ -++void showusage(char *pname) -++{ -++ fprintf(stderr, "usage: %s [-v] device\n", pname); -++ fprintf(stderr, "-v verbose messages\n"); -++} -++ -++/*====================================================================*/ -++ -++int main(int argc, char *argv[]) -++{ -++ int verbose; -++ int optch, errflg, fd; -++ struct stat buf; -++ -++ errflg = 0; -++ verbose = 0; -++ while ((optch = getopt(argc, argv, "vh")) != -1) { -++ switch (optch) { -++ case 'h': -++ errflg = 1; break; -++ case 'v': -++ verbose = 1; break; -++ default: -++ errflg = -1; break; -++ } -++ } -++ if (errflg || (optind != argc-1)) { -++ showusage(argv[0]); -++ exit(errflg > 0 ? 0 : EXIT_FAILURE); -++ } -++ -++ if (stat(argv[optind], &buf) != 0) { -++ perror("status check failed"); -++ exit(EXIT_FAILURE); -++ } -++ if (!(buf.st_mode & S_IFCHR)) { -++ fprintf(stderr, "%s is not a character special device\n", -++ argv[optind]); -++ exit(EXIT_FAILURE); -++ } -++ fd = open(argv[optind], O_RDONLY); -++ if (fd == -1) { -++ perror("open failed"); -++ exit(EXIT_FAILURE); -++ } -++ -++ check_partition(fd, verbose); -++ close(fd); -++ -++ exit(EXIT_SUCCESS); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ftl_format.c linux-2.6.24.7/drivers/mtd/mtd-utils/ftl_format.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ftl_format.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ftl_format.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,342 @@ -++/* Ported to MTD system. -++ * Based on: -++ */ -++/*====================================================================== -++ -++ Utility to create an FTL partition in a memory region -++ -++ ftl_format.c 1.13 1999/10/25 20:01:35 -++ -++ The contents of this file are subject to the Mozilla Public -++ License Version 1.1 (the "License"); you may not use this file -++ except in compliance with the License. You may obtain a copy of -++ the License at http://www.mozilla.org/MPL/ -++ -++ Software distributed under the License is distributed on an "AS -++ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -++ implied. See the License for the specific language governing -++ rights and limitations under the License. -++ -++ The initial developer of the original code is David A. Hinds -++ . Portions created by David A. Hinds -++ are Copyright (C) 1999 David A. Hinds. All Rights Reserved. -++ -++ Alternatively, the contents of this file may be used under the -++ terms of the GNU Public License version 2 (the "GPL"), in which -++ case the provisions of the GPL are applicable instead of the -++ above. If you wish to allow the use of your version of this file -++ only under the terms of the GPL and not to allow others to use -++ your version of this file under the MPL, indicate your decision -++ by deleting the provisions above and replace them with the notice -++ and other provisions required by the GPL. If you do not delete -++ the provisions above, a recipient may use your version of this -++ file under either the MPL or the GPL. -++ -++ ======================================================================*/ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#include -++#include -++ -++#if __BYTE_ORDER == __LITTLE_ENDIAN -++# define TO_LE32(x) (x) -++# define TO_LE16(x) (x) -++#elif __BYTE_ORDER == __BIG_ENDIAN -++# define TO_LE32(x) (bswap_32(x)) -++# define TO_LE16(x) (bswap_16(x)) -++#else -++# error cannot detect endianess -++#endif -++ -++#define FROM_LE32(x) TO_LE32(x) -++#define FROM_LE16(x) TO_LE16(x) -++ -++/*====================================================================*/ -++ -++static void print_size(u_int s) -++{ -++ if ((s > 0x100000) && ((s % 0x100000) == 0)) -++ printf("%d mb", s / 0x100000); -++ else if ((s > 0x400) && ((s % 0x400) == 0)) -++ printf("%d kb", s / 0x400); -++ else -++ printf("%d bytes", s); -++} -++ -++/*====================================================================*/ -++ -++static const char LinkTarget[] = { -++ 0x13, 0x03, 'C', 'I', 'S' -++}; -++static const char DataOrg[] = { -++ 0x46, 0x39, 0x00, 'F', 'T', 'L', '1', '0', '0', 0x00 -++}; -++ -++static void build_header(erase_unit_header_t *hdr, u_int RegionSize, -++ u_int BlockSize, u_int Spare, int Reserve, -++ u_int BootSize) -++{ -++ u_int i, BootUnits, nbam, __FormattedSize; -++ -++ /* Default everything to the erased state */ -++ memset(hdr, 0xff, sizeof(*hdr)); -++ memcpy(hdr->LinkTargetTuple, LinkTarget, 5); -++ memcpy(hdr->DataOrgTuple, DataOrg, 10); -++ hdr->EndTuple[0] = hdr->EndTuple[1] = 0xff; -++ BootSize = (BootSize + (BlockSize-1)) & ~(BlockSize-1); -++ BootUnits = BootSize / BlockSize; -++ -++ /* We only support 512-byte blocks */ -++ hdr->BlockSize = 9; -++ hdr->EraseUnitSize = 0; -++ for (i = BlockSize; i > 1; i >>= 1) -++ hdr->EraseUnitSize++; -++ hdr->EraseCount = TO_LE32(0); -++ hdr->FirstPhysicalEUN = TO_LE16(BootUnits); -++ hdr->NumEraseUnits = TO_LE16((RegionSize - BootSize) >> hdr->EraseUnitSize); -++ hdr->NumTransferUnits = Spare; -++ __FormattedSize = RegionSize - ((Spare + BootUnits) << hdr->EraseUnitSize); -++ /* Leave a little bit of space between the CIS and BAM */ -++ hdr->BAMOffset = TO_LE32(0x80); -++ /* Adjust size to account for BAM space */ -++ nbam = ((1 << (hdr->EraseUnitSize - hdr->BlockSize)) * sizeof(u_int) -++ + FROM_LE32(hdr->BAMOffset) + (1 << hdr->BlockSize) - 1) >> hdr->BlockSize; -++ -++ __FormattedSize -= -++ (FROM_LE16(hdr->NumEraseUnits) - Spare) * (nbam << hdr->BlockSize); -++ __FormattedSize -= ((__FormattedSize * Reserve / 100) & ~0xfff); -++ -++ hdr->FormattedSize = TO_LE32(__FormattedSize); -++ -++ /* hdr->FirstVMAddress defaults to erased state */ -++ hdr->NumVMPages = TO_LE16(0); -++ hdr->Flags = 0; -++ /* hdr->Code defaults to erased state */ -++ hdr->SerialNumber = TO_LE32(time(NULL)); -++ /* hdr->AltEUHOffset defaults to erased state */ -++ -++} /* build_header */ -++ -++/*====================================================================*/ -++ -++static int format_partition(int fd, int quiet, int interrogate, -++ u_int spare, int reserve, u_int bootsize) -++{ -++ mtd_info_t mtd; -++ erase_info_t erase; -++ erase_unit_header_t hdr; -++ u_int step, lun, i, nbam, *bam; -++ -++ /* Get partition size, block size */ -++ if (ioctl(fd, MEMGETINFO, &mtd) != 0) { -++ perror("get info failed"); -++ return -1; -++ } -++ -++#if 0 -++ /* Intel Series 100 Flash: skip first block */ -++ if ((region.JedecMfr == 0x89) && (region.JedecInfo == 0xaa) && -++ (bootsize == 0)) { -++ if (!quiet) -++ printf("Skipping first block to protect CIS info...\n"); -++ bootsize = 1; -++ } -++#endif -++ -++ /* Create header */ -++ build_header(&hdr, mtd.size, mtd.erasesize, -++ spare, reserve, bootsize); -++ -++ if (!quiet) { -++ printf("Partition size = "); -++ print_size(mtd.size); -++ printf(", erase unit size = "); -++ print_size(mtd.erasesize); -++ printf(", %d transfer units\n", spare); -++ if (bootsize != 0) { -++ print_size(FROM_LE16(hdr.FirstPhysicalEUN) << hdr.EraseUnitSize); -++ printf(" allocated for boot image\n"); -++ } -++ printf("Reserved %d%%, formatted size = ", reserve); -++ print_size(FROM_LE32(hdr.FormattedSize)); -++ printf("\n"); -++ fflush(stdout); -++ } -++ -++ if (interrogate) { -++ char str[3]; -++ printf("This will destroy all data on the target device. " -++ "Confirm (y/n): "); -++ if (fgets(str, 3, stdin) == NULL) -++ return -1; -++ if ((strcmp(str, "y\n") != 0) && (strcmp(str, "Y\n") != 0)) -++ return -1; -++ } -++ -++ /* Create basic block allocation table for control blocks */ -++ nbam = ((mtd.erasesize >> hdr.BlockSize) * sizeof(u_int) -++ + FROM_LE32(hdr.BAMOffset) + (1 << hdr.BlockSize) - 1) >> hdr.BlockSize; -++ bam = malloc(nbam * sizeof(u_int)); -++ for (i = 0; i < nbam; i++) -++ bam[i] = TO_LE32(BLOCK_CONTROL); -++ -++ /* Erase partition */ -++ if (!quiet) { -++ printf("Erasing all blocks...\n"); -++ fflush(stdout); -++ } -++ erase.length = mtd.erasesize; -++ erase.start = mtd.erasesize * FROM_LE16(hdr.FirstPhysicalEUN); -++ for (i = 0; i < FROM_LE16(hdr.NumEraseUnits); i++) { -++ if (ioctl(fd, MEMERASE, &erase) < 0) { -++ if (!quiet) { -++ putchar('\n'); -++ fflush(stdout); -++ } -++ perror("block erase failed"); -++ return -1; -++ } -++ erase.start += erase.length; -++ if (!quiet) { -++ if (mtd.size <= 0x800000) { -++ if (erase.start % 0x100000) { -++ if (!(erase.start % 0x20000)) putchar('-'); -++ } -++ else putchar('+'); -++ } -++ else { -++ if (erase.start % 0x800000) { -++ if (!(erase.start % 0x100000)) putchar('+'); -++ } -++ else putchar('*'); -++ } -++ fflush(stdout); -++ } -++ } -++ if (!quiet) putchar('\n'); -++ -++ /* Prepare erase units */ -++ if (!quiet) { -++ printf("Writing erase unit headers...\n"); -++ fflush(stdout); -++ } -++ lun = 0; -++ /* Distribute transfer units over the entire region */ -++ step = (spare) ? (FROM_LE16(hdr.NumEraseUnits)/spare) : (FROM_LE16(hdr.NumEraseUnits)+1); -++ for (i = 0; i < FROM_LE16(hdr.NumEraseUnits); i++) { -++ u_int ofs = (i + FROM_LE16(hdr.FirstPhysicalEUN)) << hdr.EraseUnitSize; -++ if (lseek(fd, ofs, SEEK_SET) == -1) { -++ perror("seek failed"); -++ break; -++ } -++ /* Is this a transfer unit? */ -++ if (((i+1) % step) == 0) -++ hdr.LogicalEUN = TO_LE16(0xffff); -++ else { -++ hdr.LogicalEUN = TO_LE16(lun); -++ lun++; -++ } -++ if (write(fd, &hdr, sizeof(hdr)) == -1) { -++ perror("write failed"); -++ break; -++ } -++ if (lseek(fd, ofs + FROM_LE32(hdr.BAMOffset), SEEK_SET) == -1) { -++ perror("seek failed"); -++ break; -++ } -++ if (write(fd, bam, nbam * sizeof(u_int)) == -1) { -++ perror("write failed"); -++ break; -++ } -++ } -++ if (i < FROM_LE16(hdr.NumEraseUnits)) -++ return -1; -++ else -++ return 0; -++} /* format_partition */ -++ -++/*====================================================================*/ -++ -++int main(int argc, char *argv[]) -++{ -++ int quiet, interrogate, reserve; -++ int optch, errflg, fd, ret; -++ u_int spare, bootsize; -++ char *s; -++ extern char *optarg; -++ struct stat buf; -++ -++ quiet = 0; -++ interrogate = 0; -++ spare = 1; -++ reserve = 5; -++ errflg = 0; -++ bootsize = 0; -++ -++ while ((optch = getopt(argc, argv, "qir:s:b:")) != -1) { -++ switch (optch) { -++ case 'q': -++ quiet = 1; break; -++ case 'i': -++ interrogate = 1; break; -++ case 's': -++ spare = strtoul(optarg, NULL, 0); break; -++ case 'r': -++ reserve = strtoul(optarg, NULL, 0); break; -++ case 'b': -++ bootsize = strtoul(optarg, &s, 0); -++ if ((*s == 'k') || (*s == 'K')) -++ bootsize *= 1024; -++ break; -++ default: -++ errflg = 1; break; -++ } -++ } -++ if (errflg || (optind != argc-1)) { -++ fprintf(stderr, "usage: %s [-q] [-i] [-s spare-blocks]" -++ " [-r reserve-percent] [-b bootsize] device\n", argv[0]); -++ exit(EXIT_FAILURE); -++ } -++ -++ if (stat(argv[optind], &buf) != 0) { -++ perror("status check failed"); -++ exit(EXIT_FAILURE); -++ } -++ if (!(buf.st_mode & S_IFCHR)) { -++ fprintf(stderr, "%s is not a character special device\n", -++ argv[optind]); -++ exit(EXIT_FAILURE); -++ } -++ fd = open(argv[optind], O_RDWR); -++ if (fd == -1) { -++ perror("open failed"); -++ exit(EXIT_FAILURE); -++ } -++ -++ ret = format_partition(fd, quiet, interrogate, spare, reserve, -++ bootsize); -++ if (!quiet) { -++ if (ret) -++ printf("format failed.\n"); -++ else -++ printf("format successful.\n"); -++ } -++ close(fd); -++ -++ exit((ret) ? EXIT_FAILURE : EXIT_SUCCESS); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/linux/jffs2.h linux-2.6.24.7/drivers/mtd/mtd-utils/include/linux/jffs2.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/linux/jffs2.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/include/linux/jffs2.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,218 @@ -++/* -++ * JFFS2 -- Journalling Flash File System, Version 2. -++ * -++ * Copyright (C) 2001-2003 Red Hat, Inc. -++ * -++ * Created by David Woodhouse -++ * -++ * For licensing information, see the file 'LICENCE' in the -++ * jffs2 directory. -++ * -++ * $Id: jffs2.h,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ -++ * -++ */ -++ -++#ifndef __LINUX_JFFS2_H__ -++#define __LINUX_JFFS2_H__ -++ -++/* You must include something which defines the C99 uintXX_t types. -++ We don't do it from here because this file is used in too many -++ different environments. */ -++ -++#define JFFS2_SUPER_MAGIC 0x72b6 -++ -++/* Values we may expect to find in the 'magic' field */ -++#define JFFS2_OLD_MAGIC_BITMASK 0x1984 -++#define JFFS2_MAGIC_BITMASK 0x1985 -++#define KSAMTIB_CIGAM_2SFFJ 0x8519 /* For detecting wrong-endian fs */ -++#define JFFS2_EMPTY_BITMASK 0xffff -++#define JFFS2_DIRTY_BITMASK 0x0000 -++ -++/* Summary node MAGIC marker */ -++#define JFFS2_SUM_MAGIC 0x02851885 -++ -++/* We only allow a single char for length, and 0xFF is empty flash so -++ we don't want it confused with a real length. Hence max 254. -++*/ -++#define JFFS2_MAX_NAME_LEN 254 -++ -++/* How small can we sensibly write nodes? */ -++#define JFFS2_MIN_DATA_LEN 128 -++ -++#define JFFS2_COMPR_NONE 0x00 -++#define JFFS2_COMPR_ZERO 0x01 -++#define JFFS2_COMPR_RTIME 0x02 -++#define JFFS2_COMPR_RUBINMIPS 0x03 -++#define JFFS2_COMPR_COPY 0x04 -++#define JFFS2_COMPR_DYNRUBIN 0x05 -++#define JFFS2_COMPR_ZLIB 0x06 -++#define JFFS2_COMPR_LZO 0x07 -++/* Compatibility flags. */ -++#define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */ -++#define JFFS2_NODE_ACCURATE 0x2000 -++/* INCOMPAT: Fail to mount the filesystem */ -++#define JFFS2_FEATURE_INCOMPAT 0xc000 -++/* ROCOMPAT: Mount read-only */ -++#define JFFS2_FEATURE_ROCOMPAT 0x8000 -++/* RWCOMPAT_COPY: Mount read/write, and copy the node when it's GC'd */ -++#define JFFS2_FEATURE_RWCOMPAT_COPY 0x4000 -++/* RWCOMPAT_DELETE: Mount read/write, and delete the node when it's GC'd */ -++#define JFFS2_FEATURE_RWCOMPAT_DELETE 0x0000 -++ -++#define JFFS2_NODETYPE_DIRENT (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 1) -++#define JFFS2_NODETYPE_INODE (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 2) -++#define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) -++#define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4) -++ -++#define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6) -++ -++#define JFFS2_NODETYPE_XATTR (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 8) -++#define JFFS2_NODETYPE_XREF (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 9) -++ -++/* XATTR Related */ -++#define JFFS2_XPREFIX_USER 1 /* for "user." */ -++#define JFFS2_XPREFIX_SECURITY 2 /* for "security." */ -++#define JFFS2_XPREFIX_ACL_ACCESS 3 /* for "system.posix_acl_access" */ -++#define JFFS2_XPREFIX_ACL_DEFAULT 4 /* for "system.posix_acl_default" */ -++#define JFFS2_XPREFIX_TRUSTED 5 /* for "trusted.*" */ -++ -++#define JFFS2_ACL_VERSION 0x0001 -++ -++// Maybe later... -++//#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) -++//#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4) -++ -++ -++#define JFFS2_INO_FLAG_PREREAD 1 /* Do read_inode() for this one at -++ mount time, don't wait for it to -++ happen later */ -++#define JFFS2_INO_FLAG_USERCOMPR 2 /* User has requested a specific -++ compression type */ -++ -++ -++/* These can go once we've made sure we've caught all uses without -++ byteswapping */ -++ -++typedef struct { -++ uint32_t v32; -++} __attribute__((packed)) jint32_t; -++ -++typedef struct { -++ uint32_t m; -++} __attribute__((packed)) jmode_t; -++ -++typedef struct { -++ uint16_t v16; -++} __attribute__((packed)) jint16_t; -++ -++struct jffs2_unknown_node -++{ -++ /* All start like this */ -++ jint16_t magic; -++ jint16_t nodetype; -++ jint32_t totlen; /* So we can skip over nodes we don't grok */ -++ jint32_t hdr_crc; -++} __attribute__((packed)); -++ -++struct jffs2_raw_dirent -++{ -++ jint16_t magic; -++ jint16_t nodetype; /* == JFFS2_NODETYPE_DIRENT */ -++ jint32_t totlen; -++ jint32_t hdr_crc; -++ jint32_t pino; -++ jint32_t version; -++ jint32_t ino; /* == zero for unlink */ -++ jint32_t mctime; -++ uint8_t nsize; -++ uint8_t type; -++ uint8_t unused[2]; -++ jint32_t node_crc; -++ jint32_t name_crc; -++ uint8_t name[0]; -++} __attribute__((packed)); -++ -++/* The JFFS2 raw inode structure: Used for storage on physical media. */ -++/* The uid, gid, atime, mtime and ctime members could be longer, but -++ are left like this for space efficiency. If and when people decide -++ they really need them extended, it's simple enough to add support for -++ a new type of raw node. -++*/ -++struct jffs2_raw_inode -++{ -++ jint16_t magic; /* A constant magic number. */ -++ jint16_t nodetype; /* == JFFS2_NODETYPE_INODE */ -++ jint32_t totlen; /* Total length of this node (inc data, etc.) */ -++ jint32_t hdr_crc; -++ jint32_t ino; /* Inode number. */ -++ jint32_t version; /* Version number. */ -++ jmode_t mode; /* The file's type or mode. */ -++ jint16_t uid; /* The file's owner. */ -++ jint16_t gid; /* The file's group. */ -++ jint32_t isize; /* Total resultant size of this inode (used for truncations) */ -++ jint32_t atime; /* Last access time. */ -++ jint32_t mtime; /* Last modification time. */ -++ jint32_t ctime; /* Change time. */ -++ jint32_t offset; /* Where to begin to write. */ -++ jint32_t csize; /* (Compressed) data size */ -++ jint32_t dsize; /* Size of the node's data. (after decompression) */ -++ uint8_t compr; /* Compression algorithm used */ -++ uint8_t usercompr; /* Compression algorithm requested by the user */ -++ jint16_t flags; /* See JFFS2_INO_FLAG_* */ -++ jint32_t data_crc; /* CRC for the (compressed) data. */ -++ jint32_t node_crc; /* CRC for the raw inode (excluding data) */ -++ uint8_t data[0]; -++} __attribute__((packed)); -++ -++struct jffs2_raw_xattr { -++ jint16_t magic; -++ jint16_t nodetype; /* = JFFS2_NODETYPE_XATTR */ -++ jint32_t totlen; -++ jint32_t hdr_crc; -++ jint32_t xid; /* XATTR identifier number */ -++ jint32_t version; -++ uint8_t xprefix; -++ uint8_t name_len; -++ jint16_t value_len; -++ jint32_t data_crc; -++ jint32_t node_crc; -++ uint8_t data[0]; -++} __attribute__((packed)); -++ -++struct jffs2_raw_xref -++{ -++ jint16_t magic; -++ jint16_t nodetype; /* = JFFS2_NODETYPE_XREF */ -++ jint32_t totlen; -++ jint32_t hdr_crc; -++ jint32_t ino; /* inode number */ -++ jint32_t xid; /* XATTR identifier number */ -++ jint32_t xseqno; /* xref sequencial number */ -++ jint32_t node_crc; -++} __attribute__((packed)); -++ -++struct jffs2_raw_summary -++{ -++ jint16_t magic; -++ jint16_t nodetype; /* = JFFS2_NODETYPE_SUMMARY */ -++ jint32_t totlen; -++ jint32_t hdr_crc; -++ jint32_t sum_num; /* number of sum entries*/ -++ jint32_t cln_mkr; /* clean marker size, 0 = no cleanmarker */ -++ jint32_t padded; /* sum of the size of padding nodes */ -++ jint32_t sum_crc; /* summary information crc */ -++ jint32_t node_crc; /* node crc */ -++ jint32_t sum[0]; /* inode summary info */ -++} __attribute__((packed)); -++ -++union jffs2_node_union -++{ -++ struct jffs2_raw_inode i; -++ struct jffs2_raw_dirent d; -++ struct jffs2_raw_xattr x; -++ struct jffs2_raw_xref r; -++ struct jffs2_raw_summary s; -++ struct jffs2_unknown_node u; -++}; -++ -++#endif /* __LINUX_JFFS2_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd/ftl-user.h linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd/ftl-user.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd/ftl-user.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd/ftl-user.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,76 @@ -++/* -++ * $Id: ftl-user.h,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ -++ * -++ * Derived from (and probably identical to): -++ * ftl.h 1.7 1999/10/25 20:23:17 -++ * -++ * The contents of this file are subject to the Mozilla Public License -++ * Version 1.1 (the "License"); you may not use this file except in -++ * compliance with the License. You may obtain a copy of the License -++ * at http://www.mozilla.org/MPL/ -++ * -++ * Software distributed under the License is distributed on an "AS IS" -++ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -++ * the License for the specific language governing rights and -++ * limitations under the License. -++ * -++ * The initial developer of the original code is David A. Hinds -++ * . Portions created by David A. Hinds -++ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. -++ * -++ * Alternatively, the contents of this file may be used under the -++ * terms of the GNU General Public License version 2 (the "GPL"), in -++ * which case the provisions of the GPL are applicable instead of the -++ * above. If you wish to allow the use of your version of this file -++ * only under the terms of the GPL and not to allow others to use -++ * your version of this file under the MPL, indicate your decision by -++ * deleting the provisions above and replace them with the notice and -++ * other provisions required by the GPL. If you do not delete the -++ * provisions above, a recipient may use your version of this file -++ * under either the MPL or the GPL. -++ */ -++ -++#ifndef __MTD_FTL_USER_H__ -++#define __MTD_FTL_USER_H__ -++ -++typedef struct erase_unit_header_t { -++ u_int8_t LinkTargetTuple[5]; -++ u_int8_t DataOrgTuple[10]; -++ u_int8_t NumTransferUnits; -++ u_int32_t EraseCount; -++ u_int16_t LogicalEUN; -++ u_int8_t BlockSize; -++ u_int8_t EraseUnitSize; -++ u_int16_t FirstPhysicalEUN; -++ u_int16_t NumEraseUnits; -++ u_int32_t FormattedSize; -++ u_int32_t FirstVMAddress; -++ u_int16_t NumVMPages; -++ u_int8_t Flags; -++ u_int8_t Code; -++ u_int32_t SerialNumber; -++ u_int32_t AltEUHOffset; -++ u_int32_t BAMOffset; -++ u_int8_t Reserved[12]; -++ u_int8_t EndTuple[2]; -++} erase_unit_header_t; -++ -++/* Flags in erase_unit_header_t */ -++#define HIDDEN_AREA 0x01 -++#define REVERSE_POLARITY 0x02 -++#define DOUBLE_BAI 0x04 -++ -++/* Definitions for block allocation information */ -++ -++#define BLOCK_FREE(b) ((b) == 0xffffffff) -++#define BLOCK_DELETED(b) (((b) == 0) || ((b) == 0xfffffffe)) -++ -++#define BLOCK_TYPE(b) ((b) & 0x7f) -++#define BLOCK_ADDRESS(b) ((b) & ~0x7f) -++#define BLOCK_NUMBER(b) ((b) >> 9) -++#define BLOCK_CONTROL 0x30 -++#define BLOCK_DATA 0x40 -++#define BLOCK_REPLACEMENT 0x60 -++#define BLOCK_BAD 0x70 -++ -++#endif /* __MTD_FTL_USER_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd/inftl-user.h linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd/inftl-user.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd/inftl-user.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd/inftl-user.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,91 @@ -++/* -++ * $Id: inftl-user.h,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ -++ * -++ * Parts of INFTL headers shared with userspace -++ * -++ */ -++ -++#ifndef __MTD_INFTL_USER_H__ -++#define __MTD_INFTL_USER_H__ -++ -++#define OSAK_VERSION 0x5120 -++#define PERCENTUSED 98 -++ -++#define SECTORSIZE 512 -++ -++/* Block Control Information */ -++ -++struct inftl_bci { -++ uint8_t ECCsig[6]; -++ uint8_t Status; -++ uint8_t Status1; -++} __attribute__((packed)); -++ -++struct inftl_unithead1 { -++ uint16_t virtualUnitNo; -++ uint16_t prevUnitNo; -++ uint8_t ANAC; -++ uint8_t NACs; -++ uint8_t parityPerField; -++ uint8_t discarded; -++} __attribute__((packed)); -++ -++struct inftl_unithead2 { -++ uint8_t parityPerField; -++ uint8_t ANAC; -++ uint16_t prevUnitNo; -++ uint16_t virtualUnitNo; -++ uint8_t NACs; -++ uint8_t discarded; -++} __attribute__((packed)); -++ -++struct inftl_unittail { -++ uint8_t Reserved[4]; -++ uint16_t EraseMark; -++ uint16_t EraseMark1; -++} __attribute__((packed)); -++ -++union inftl_uci { -++ struct inftl_unithead1 a; -++ struct inftl_unithead2 b; -++ struct inftl_unittail c; -++}; -++ -++struct inftl_oob { -++ struct inftl_bci b; -++ union inftl_uci u; -++}; -++ -++ -++/* INFTL Media Header */ -++ -++struct INFTLPartition { -++ __u32 virtualUnits; -++ __u32 firstUnit; -++ __u32 lastUnit; -++ __u32 flags; -++ __u32 spareUnits; -++ __u32 Reserved0; -++ __u32 Reserved1; -++} __attribute__((packed)); -++ -++struct INFTLMediaHeader { -++ char bootRecordID[8]; -++ __u32 NoOfBootImageBlocks; -++ __u32 NoOfBinaryPartitions; -++ __u32 NoOfBDTLPartitions; -++ __u32 BlockMultiplierBits; -++ __u32 FormatFlags; -++ __u32 OsakVersion; -++ __u32 PercentUsed; -++ struct INFTLPartition Partitions[4]; -++} __attribute__((packed)); -++ -++/* Partition flag types */ -++#define INFTL_BINARY 0x20000000 -++#define INFTL_BDTL 0x40000000 -++#define INFTL_LAST 0x80000000 -++ -++#endif /* __MTD_INFTL_USER_H__ */ -++ -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd/jffs2-user.h linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd/jffs2-user.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd/jffs2-user.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd/jffs2-user.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,82 @@ -++/* -++ * $Id: jffs2-user.h,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ -++ * -++ * JFFS2 definitions for use in user space only -++ */ -++ -++#ifndef __JFFS2_USER_H__ -++#define __JFFS2_USER_H__ -++ -++/* This file is blessed for inclusion by userspace */ -++#include -++#include -++#include -++ -++#undef cpu_to_je16 -++#undef cpu_to_je32 -++#undef cpu_to_jemode -++#undef je16_to_cpu -++#undef je32_to_cpu -++#undef jemode_to_cpu -++ -++extern int target_endian; -++ -++#define t16(x) ({ uint16_t __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_16(__b); }) -++#define t32(x) ({ uint32_t __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_32(__b); }) -++ -++#define cpu_to_je16(x) ((jint16_t){t16(x)}) -++#define cpu_to_je32(x) ((jint32_t){t32(x)}) -++#define cpu_to_jemode(x) ((jmode_t){t32(x)}) -++ -++#define je16_to_cpu(x) (t16((x).v16)) -++#define je32_to_cpu(x) (t32((x).v32)) -++#define jemode_to_cpu(x) (t32((x).m)) -++ -++#define le16_to_cpu(x) (__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_16(x)) -++#define le32_to_cpu(x) (__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_32(x)) -++#define cpu_to_le16(x) (__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_16(x)) -++#define cpu_to_le32(x) (__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_32(x)) -++ -++/* XATTR/POSIX-ACL related definition */ -++/* Namespaces copied from xattr.h and posix_acl_xattr.h */ -++#define XATTR_USER_PREFIX "user." -++#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1) -++#define XATTR_SECURITY_PREFIX "security." -++#define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1) -++#define POSIX_ACL_XATTR_ACCESS "system.posix_acl_access" -++#define POSIX_ACL_XATTR_ACCESS_LEN (sizeof (POSIX_ACL_XATTR_ACCESS) - 1) -++#define POSIX_ACL_XATTR_DEFAULT "system.posix_acl_default" -++#define POSIX_ACL_XATTR_DEFAULT_LEN (sizeof (POSIX_ACL_XATTR_DEFAULT) - 1) -++#define XATTR_TRUSTED_PREFIX "trusted." -++#define XATTR_TRUSTED_PREFIX_LEN (sizeof (XATTR_TRUSTED_PREFIX) - 1) -++ -++struct jffs2_acl_entry { -++ jint16_t e_tag; -++ jint16_t e_perm; -++ jint32_t e_id; -++}; -++ -++struct jffs2_acl_entry_short { -++ jint16_t e_tag; -++ jint16_t e_perm; -++}; -++ -++struct jffs2_acl_header { -++ jint32_t a_version; -++}; -++ -++/* copied from include/linux/posix_acl_xattr.h */ -++#define POSIX_ACL_XATTR_VERSION 0x0002 -++ -++struct posix_acl_xattr_entry { -++ uint16_t e_tag; -++ uint16_t e_perm; -++ uint32_t e_id; -++}; -++ -++struct posix_acl_xattr_header { -++ uint32_t a_version; -++ struct posix_acl_xattr_entry a_entries[0]; -++}; -++ -++#endif /* __JFFS2_USER_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd/mtd-abi.h linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd/mtd-abi.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd/mtd-abi.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd/mtd-abi.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,170 @@ -++/* -++ * $Id: mtd-abi.h,v 1.1.1.1 2008-10-30 14:29:21 lhhuang Exp $ -++ * -++ * Portions of MTD ABI definition which are shared by kernel and user space -++ */ -++ -++#ifndef __MTD_ABI_H__ -++#define __MTD_ABI_H__ -++ -++#ifndef __KERNEL__ /* Urgh. The whole point of splitting this out into -++ separate files was to avoid #ifdef __KERNEL__ */ -++#define __user -++#endif -++ -++typedef unsigned long long size_mtd_t; -++typedef unsigned long long loff_mtd_t; -++ -++struct erase_info_user { -++ uint64_t start; -++ uint64_t length; -++}; -++ -++struct mtd_oob_buf { -++ uint32_t start; -++ uint32_t length; -++ unsigned char __user *ptr; -++}; -++ -++struct mtd_page_buf { -++ uint32_t start; //page start address -++ uint32_t ooblength; -++ uint32_t datlength; -++ unsigned char __user *oobptr; -++ unsigned char __user *datptr; -++}; -++ -++#define MTD_ABSENT 0 -++#define MTD_RAM 1 -++#define MTD_ROM 2 -++#define MTD_NORFLASH 3 -++#define MTD_NANDFLASH 4 -++#define MTD_DATAFLASH 6 -++#define MTD_UBIVOLUME 7 -++ -++#define MTD_WRITEABLE 0x400 /* Device is writeable */ -++#define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */ -++#define MTD_NO_ERASE 0x1000 /* No erase necessary */ -++#define MTD_STUPID_LOCK 0x2000 /* Always locked after reset */ -++ -++// Some common devices / combinations of capabilities -++#define MTD_CAP_ROM 0 -++#define MTD_CAP_RAM (MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_NO_ERASE) -++#define MTD_CAP_NORFLASH (MTD_WRITEABLE | MTD_BIT_WRITEABLE) -++#define MTD_CAP_NANDFLASH (MTD_WRITEABLE) -++ -++/* ECC byte placement */ -++#define MTD_NANDECC_OFF 0 // Switch off ECC (Not recommended) -++#define MTD_NANDECC_PLACE 1 // Use the given placement in the structure (YAFFS1 legacy mode) -++#define MTD_NANDECC_AUTOPLACE 2 // Use the default placement scheme -++#define MTD_NANDECC_PLACEONLY 3 // Use the given placement in the structure (Do not store ecc result on read) -++#define MTD_NANDECC_AUTOPL_USR 4 // Use the given autoplacement scheme rather than using the default -++ -++/* OTP mode selection */ -++#define MTD_OTP_OFF 0 -++#define MTD_OTP_FACTORY 1 -++#define MTD_OTP_USER 2 -++ -++struct mtd_info_user { -++ uint8_t type; -++ uint32_t flags; -++ uint64_t size; // Total size of the MTD -++ uint32_t erasesize; -++ uint32_t writesize; -++ uint32_t oobsize; // Amount of OOB data per block (e.g. 16) -++ /* The below two fields are obsolete and broken, do not use them -++ * (TODO: remove at some point) */ -++ uint32_t ecctype; -++ uint32_t eccsize; -++}; -++ -++struct region_info_user { -++ uint64_t offset; /* At which this region starts, -++ * from the beginning of the MTD */ -++ uint32_t erasesize; /* For this region */ -++ uint32_t numblocks; /* Number of blocks in this region */ -++ uint32_t regionindex; -++}; -++ -++struct otp_info { -++ uint32_t start; -++ uint32_t length; -++ uint32_t locked; -++}; -++ -++#define MEMGETINFO _IOR('M', 1, struct mtd_info_user) -++#define MEMERASE _IOW('M', 2, struct erase_info_user) -++#define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf) -++#define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf) -++#define MEMLOCK _IOW('M', 5, struct erase_info_user) -++#define MEMUNLOCK _IOW('M', 6, struct erase_info_user) -++#define MEMGETREGIONCOUNT _IOR('M', 7, int) -++#define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user) -++#define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo) -++#define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo) -++#define MEMGETBADBLOCK _IOW('M', 11, loff_mtd_t) -++#define MEMSETBADBLOCK _IOW('M', 12, loff_mtd_t) -++#define OTPSELECT _IOR('M', 13, int) -++#define OTPGETREGIONCOUNT _IOW('M', 14, int) -++#define OTPGETREGIONINFO _IOW('M', 15, struct otp_info) -++#define OTPLOCK _IOR('M', 16, struct otp_info) -++#define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout) -++#define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats) -++#define MTDFILEMODE _IO('M', 19) -++#define MEMWRITEPAGE _IOWR('M', 20, struct mtd_page_buf) -++ -++/* -++ * Obsolete legacy interface. Keep it in order not to break userspace -++ * interfaces -++ */ -++struct nand_oobinfo { -++ uint32_t useecc; -++ uint32_t eccbytes; -++ uint32_t oobfree[8][2]; -++ uint32_t eccpos[104]; /* more fields(13*8) are required for -++ * 8-bit BCH ECC and 4KB pagesize nand, by Regen */ -++}; -++ -++struct nand_oobfree { -++ uint32_t offset; -++ uint32_t length; -++}; -++ -++#define MTD_MAX_OOBFREE_ENTRIES 8 -++/* -++ * ECC layout control structure. Exported to userspace for -++ * diagnosis and to allow creation of raw images -++ */ -++struct nand_ecclayout { -++ uint32_t eccbytes; -++ uint32_t eccpos[128]; -++ uint32_t oobavail; -++ struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; -++}; -++ -++/** -++ * struct mtd_ecc_stats - error correction stats -++ * -++ * @corrected: number of corrected bits -++ * @failed: number of uncorrectable errors -++ * @badblocks: number of bad blocks in this partition -++ * @bbtblocks: number of blocks reserved for bad block tables -++ */ -++struct mtd_ecc_stats { -++ uint32_t corrected; -++ uint32_t failed; -++ uint32_t badblocks; -++ uint32_t bbtblocks; -++}; -++ -++/* -++ * Read/write file modes for access to MTD -++ */ -++enum mtd_file_modes { -++ MTD_MODE_NORMAL = MTD_OTP_OFF, -++ MTD_MODE_OTP_FACTORY = MTD_OTP_FACTORY, -++ MTD_MODE_OTP_USER = MTD_OTP_USER, -++ MTD_MODE_RAW, -++}; -++ -++#endif /* __MTD_ABI_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd/mtd-user.h linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd/mtd-user.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd/mtd-user.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd/mtd-user.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,21 @@ -++/* -++ * $Id: mtd-user.h,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ -++ * -++ * MTD ABI header for use by user space only. -++ */ -++ -++#ifndef __MTD_USER_H__ -++#define __MTD_USER_H__ -++ -++#include -++ -++/* This file is blessed for inclusion by userspace */ -++#include -++ -++typedef struct mtd_info_user mtd_info_t; -++typedef struct erase_info_user erase_info_t; -++typedef struct region_info_user region_info_t; -++typedef struct nand_oobinfo nand_oobinfo_t; -++typedef struct nand_ecclayout nand_ecclayout_t; -++ -++#endif /* __MTD_USER_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd/nftl-user.h linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd/nftl-user.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd/nftl-user.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd/nftl-user.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,76 @@ -++/* -++ * $Id: nftl-user.h,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ -++ * -++ * Parts of NFTL headers shared with userspace -++ * -++ */ -++ -++#ifndef __MTD_NFTL_USER_H__ -++#define __MTD_NFTL_USER_H__ -++ -++/* Block Control Information */ -++ -++struct nftl_bci { -++ unsigned char ECCSig[6]; -++ uint8_t Status; -++ uint8_t Status1; -++}__attribute__((packed)); -++ -++/* Unit Control Information */ -++ -++struct nftl_uci0 { -++ uint16_t VirtUnitNum; -++ uint16_t ReplUnitNum; -++ uint16_t SpareVirtUnitNum; -++ uint16_t SpareReplUnitNum; -++} __attribute__((packed)); -++ -++struct nftl_uci1 { -++ uint32_t WearInfo; -++ uint16_t EraseMark; -++ uint16_t EraseMark1; -++} __attribute__((packed)); -++ -++struct nftl_uci2 { -++ uint16_t FoldMark; -++ uint16_t FoldMark1; -++ uint32_t unused; -++} __attribute__((packed)); -++ -++union nftl_uci { -++ struct nftl_uci0 a; -++ struct nftl_uci1 b; -++ struct nftl_uci2 c; -++}; -++ -++struct nftl_oob { -++ struct nftl_bci b; -++ union nftl_uci u; -++}; -++ -++/* NFTL Media Header */ -++ -++struct NFTLMediaHeader { -++ char DataOrgID[6]; -++ uint16_t NumEraseUnits; -++ uint16_t FirstPhysicalEUN; -++ uint32_t FormattedSize; -++ unsigned char UnitSizeFactor; -++} __attribute__((packed)); -++ -++#define MAX_ERASE_ZONES (8192 - 512) -++ -++#define ERASE_MARK 0x3c69 -++#define SECTOR_FREE 0xff -++#define SECTOR_USED 0x55 -++#define SECTOR_IGNORE 0x11 -++#define SECTOR_DELETED 0x00 -++ -++#define FOLD_MARK_IN_PROGRESS 0x5555 -++ -++#define ZONE_GOOD 0xff -++#define ZONE_BAD_ORIGINAL 0 -++#define ZONE_BAD_MARKED 7 -++ -++ -++#endif /* __MTD_NFTL_USER_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd/ubi-header.h linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd/ubi-header.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd/ubi-header.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd/ubi-header.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,372 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Thomas Gleixner -++ * Frank Haverkamp -++ * Oliver Lohmann -++ * Andreas Arnez -++ */ -++ -++/* -++ * This file defines the layout of UBI headers and all the other UBI on-flash -++ * data structures. May be included by user-space. -++ */ -++ -++#ifndef __UBI_HEADER_H__ -++#define __UBI_HEADER_H__ -++ -++#include -++ -++/* The version of UBI images supported by this implementation */ -++#define UBI_VERSION 1 -++ -++/* The highest erase counter value supported by this implementation */ -++#define UBI_MAX_ERASECOUNTER 0x7FFFFFFF -++ -++/* The initial CRC32 value used when calculating CRC checksums */ -++#define UBI_CRC32_INIT 0xFFFFFFFFU -++ -++/* Erase counter header magic number (ASCII "UBI#") */ -++#define UBI_EC_HDR_MAGIC 0x55424923 -++/* Volume identifier header magic number (ASCII "UBI!") */ -++#define UBI_VID_HDR_MAGIC 0x55424921 -++ -++/* -++ * Volume type constants used in the volume identifier header. -++ * -++ * @UBI_VID_DYNAMIC: dynamic volume -++ * @UBI_VID_STATIC: static volume -++ */ -++enum { -++ UBI_VID_DYNAMIC = 1, -++ UBI_VID_STATIC = 2 -++}; -++ -++/* -++ * Volume flags used in the volume table record. -++ * -++ * @UBI_VTBL_AUTORESIZE_FLG: auto-resize this volume -++ * -++ * %UBI_VTBL_AUTORESIZE_FLG flag can be set only for one volume in the volume -++ * table. UBI automatically re-sizes the volume which has this flag and makes -++ * the volume to be of largest possible size. This means that if after the -++ * initialization UBI finds out that there are available physical eraseblocks -++ * present on the device, it automatically appends all of them to the volume -++ * (the physical eraseblocks reserved for bad eraseblocks handling and other -++ * reserved physical eraseblocks are not taken). So, if there is a volume with -++ * the %UBI_VTBL_AUTORESIZE_FLG flag set, the amount of available logical -++ * eraseblocks will be zero after UBI is loaded, because all of them will be -++ * reserved for this volume. Note, the %UBI_VTBL_AUTORESIZE_FLG bit is cleared -++ * after the volume had been initialized. -++ * -++ * The auto-resize feature is useful for device production purposes. For -++ * example, different NAND flash chips may have different amount of initial bad -++ * eraseblocks, depending of particular chip instance. Manufacturers of NAND -++ * chips usually guarantee that the amount of initial bad eraseblocks does not -++ * exceed certain percent, e.g. 2%. When one creates an UBI image which will be -++ * flashed to the end devices in production, he does not know the exact amount -++ * of good physical eraseblocks the NAND chip on the device will have, but this -++ * number is required to calculate the volume sized and put them to the volume -++ * table of the UBI image. In this case, one of the volumes (e.g., the one -++ * which will store the root file system) is marked as "auto-resizable", and -++ * UBI will adjust its size on the first boot if needed. -++ * -++ * Note, first UBI reserves some amount of physical eraseblocks for bad -++ * eraseblock handling, and then re-sizes the volume, not vice-versa. This -++ * means that the pool of reserved physical eraseblocks will always be present. -++ */ -++enum { -++ UBI_VTBL_AUTORESIZE_FLG = 0x01, -++}; -++ -++/* -++ * Compatibility constants used by internal volumes. -++ * -++ * @UBI_COMPAT_DELETE: delete this internal volume before anything is written -++ * to the flash -++ * @UBI_COMPAT_RO: attach this device in read-only mode -++ * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its -++ * physical eraseblocks, don't allow the wear-leveling unit to move them -++ * @UBI_COMPAT_REJECT: reject this UBI image -++ */ -++enum { -++ UBI_COMPAT_DELETE = 1, -++ UBI_COMPAT_RO = 2, -++ UBI_COMPAT_PRESERVE = 4, -++ UBI_COMPAT_REJECT = 5 -++}; -++ -++/* Sizes of UBI headers */ -++#define UBI_EC_HDR_SIZE sizeof(struct ubi_ec_hdr) -++#define UBI_VID_HDR_SIZE sizeof(struct ubi_vid_hdr) -++ -++/* Sizes of UBI headers without the ending CRC */ -++#define UBI_EC_HDR_SIZE_CRC (UBI_EC_HDR_SIZE - sizeof(uint32_t)) -++#define UBI_VID_HDR_SIZE_CRC (UBI_VID_HDR_SIZE - sizeof(uint32_t)) -++ -++/** -++ * struct ubi_ec_hdr - UBI erase counter header. -++ * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC) -++ * @version: version of UBI implementation which is supposed to accept this -++ * UBI image -++ * @padding1: reserved for future, zeroes -++ * @ec: the erase counter -++ * @vid_hdr_offset: where the VID header starts -++ * @data_offset: where the user data start -++ * @padding2: reserved for future, zeroes -++ * @hdr_crc: erase counter header CRC checksum -++ * -++ * The erase counter header takes 64 bytes and has a plenty of unused space for -++ * future usage. The unused fields are zeroed. The @version field is used to -++ * indicate the version of UBI implementation which is supposed to be able to -++ * work with this UBI image. If @version is greater then the current UBI -++ * version, the image is rejected. This may be useful in future if something -++ * is changed radically. This field is duplicated in the volume identifier -++ * header. -++ * -++ * The @vid_hdr_offset and @data_offset fields contain the offset of the the -++ * volume identifier header and user data, relative to the beginning of the -++ * physical eraseblock. These values have to be the same for all physical -++ * eraseblocks. -++ */ -++struct ubi_ec_hdr { -++ uint32_t magic; -++ uint8_t version; -++ uint8_t padding1[3]; -++ uint64_t ec; /* Warning: the current limit is 31-bit anyway! */ -++ uint32_t vid_hdr_offset; -++ uint32_t data_offset; -++ uint8_t padding2[36]; -++ uint32_t hdr_crc; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubi_vid_hdr - on-flash UBI volume identifier header. -++ * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC) -++ * @version: UBI implementation version which is supposed to accept this UBI -++ * image (%UBI_VERSION) -++ * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC) -++ * @copy_flag: if this logical eraseblock was copied from another physical -++ * eraseblock (for wear-leveling reasons) -++ * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE, -++ * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT) -++ * @vol_id: ID of this volume -++ * @lnum: logical eraseblock number -++ * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be -++ * removed, kept only for not breaking older UBI users) -++ * @data_size: how many bytes of data this logical eraseblock contains -++ * @used_ebs: total number of used logical eraseblocks in this volume -++ * @data_pad: how many bytes at the end of this physical eraseblock are not -++ * used -++ * @data_crc: CRC checksum of the data stored in this logical eraseblock -++ * @padding1: reserved for future, zeroes -++ * @sqnum: sequence number -++ * @padding2: reserved for future, zeroes -++ * @hdr_crc: volume identifier header CRC checksum -++ * -++ * The @sqnum is the value of the global sequence counter at the time when this -++ * VID header was created. The global sequence counter is incremented each time -++ * UBI writes a new VID header to the flash, i.e. when it maps a logical -++ * eraseblock to a new physical eraseblock. The global sequence counter is an -++ * unsigned 64-bit integer and we assume it never overflows. The @sqnum -++ * (sequence number) is used to distinguish between older and newer versions of -++ * logical eraseblocks. -++ * -++ * There are 2 situations when there may be more then one physical eraseblock -++ * corresponding to the same logical eraseblock, i.e., having the same @vol_id -++ * and @lnum values in the volume identifier header. Suppose we have a logical -++ * eraseblock L and it is mapped to the physical eraseblock P. -++ * -++ * 1. Because UBI may erase physical eraseblocks asynchronously, the following -++ * situation is possible: L is asynchronously erased, so P is scheduled for -++ * erasure, then L is written to,i.e. mapped to another physical eraseblock P1, -++ * so P1 is written to, then an unclean reboot happens. Result - there are 2 -++ * physical eraseblocks P and P1 corresponding to the same logical eraseblock -++ * L. But P1 has greater sequence number, so UBI picks P1 when it attaches the -++ * flash. -++ * -++ * 2. From time to time UBI moves logical eraseblocks to other physical -++ * eraseblocks for wear-leveling reasons. If, for example, UBI moves L from P -++ * to P1, and an unclean reboot happens before P is physically erased, there -++ * are two physical eraseblocks P and P1 corresponding to L and UBI has to -++ * select one of them when the flash is attached. The @sqnum field says which -++ * PEB is the original (obviously P will have lower @sqnum) and the copy. But -++ * it is not enough to select the physical eraseblock with the higher sequence -++ * number, because the unclean reboot could have happen in the middle of the -++ * copying process, so the data in P is corrupted. It is also not enough to -++ * just select the physical eraseblock with lower sequence number, because the -++ * data there may be old (consider a case if more data was added to P1 after -++ * the copying). Moreover, the unclean reboot may happen when the erasure of P -++ * was just started, so it result in unstable P, which is "mostly" OK, but -++ * still has unstable bits. -++ * -++ * UBI uses the @copy_flag field to indicate that this logical eraseblock is a -++ * copy. UBI also calculates data CRC when the data is moved and stores it at -++ * the @data_crc field of the copy (P1). So when UBI needs to pick one physical -++ * eraseblock of two (P or P1), the @copy_flag of the newer one (P1) is -++ * examined. If it is cleared, the situation* is simple and the newer one is -++ * picked. If it is set, the data CRC of the copy (P1) is examined. If the CRC -++ * checksum is correct, this physical eraseblock is selected (P1). Otherwise -++ * the older one (P) is selected. -++ * -++ * Note, there is an obsolete @leb_ver field which was used instead of @sqnum -++ * in the past. But it is not used anymore and we keep it in order to be able -++ * to deal with old UBI images. It will be removed at some point. -++ * -++ * There are 2 sorts of volumes in UBI: user volumes and internal volumes. -++ * Internal volumes are not seen from outside and are used for various internal -++ * UBI purposes. In this implementation there is only one internal volume - the -++ * layout volume. Internal volumes are the main mechanism of UBI extensions. -++ * For example, in future one may introduce a journal internal volume. Internal -++ * volumes have their own reserved range of IDs. -++ * -++ * The @compat field is only used for internal volumes and contains the "degree -++ * of their compatibility". It is always zero for user volumes. This field -++ * provides a mechanism to introduce UBI extensions and to be still compatible -++ * with older UBI binaries. For example, if someone introduced a journal in -++ * future, he would probably use %UBI_COMPAT_DELETE compatibility for the -++ * journal volume. And in this case, older UBI binaries, which know nothing -++ * about the journal volume, would just delete this volume and work perfectly -++ * fine. This is similar to what Ext2fs does when it is fed by an Ext3fs image -++ * - it just ignores the Ext3fs journal. -++ * -++ * The @data_crc field contains the CRC checksum of the contents of the logical -++ * eraseblock if this is a static volume. In case of dynamic volumes, it does -++ * not contain the CRC checksum as a rule. The only exception is when the -++ * data of the physical eraseblock was moved by the wear-leveling unit, then -++ * the wear-leveling unit calculates the data CRC and stores it in the -++ * @data_crc field. And of course, the @copy_flag is %in this case. -++ * -++ * The @data_size field is used only for static volumes because UBI has to know -++ * how many bytes of data are stored in this eraseblock. For dynamic volumes, -++ * this field usually contains zero. The only exception is when the data of the -++ * physical eraseblock was moved to another physical eraseblock for -++ * wear-leveling reasons. In this case, UBI calculates CRC checksum of the -++ * contents and uses both @data_crc and @data_size fields. In this case, the -++ * @data_size field contains data size. -++ * -++ * The @used_ebs field is used only for static volumes and indicates how many -++ * eraseblocks the data of the volume takes. For dynamic volumes this field is -++ * not used and always contains zero. -++ * -++ * The @data_pad is calculated when volumes are created using the alignment -++ * parameter. So, effectively, the @data_pad field reduces the size of logical -++ * eraseblocks of this volume. This is very handy when one uses block-oriented -++ * software (say, cramfs) on top of the UBI volume. -++ */ -++struct ubi_vid_hdr { -++ uint32_t magic; -++ uint8_t version; -++ uint8_t vol_type; -++ uint8_t copy_flag; -++ uint8_t compat; -++ uint32_t vol_id; -++ uint32_t lnum; -++ uint32_t leb_ver; /* obsolete, to be removed, don't use */ -++ uint32_t data_size; -++ uint32_t used_ebs; -++ uint32_t data_pad; -++ uint32_t data_crc; -++ uint8_t padding1[4]; -++ uint64_t sqnum; -++ uint8_t padding2[12]; -++ uint32_t hdr_crc; -++} __attribute__ ((packed)); -++ -++/* Internal UBI volumes count */ -++#define UBI_INT_VOL_COUNT 1 -++ -++/* -++ * Starting ID of internal volumes. There is reserved room for 4096 internal -++ * volumes. -++ */ -++#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096) -++ -++/* The layout volume contains the volume table */ -++ -++#define UBI_LAYOUT_VOLUME_ID UBI_INTERNAL_VOL_START -++#define UBI_LAYOUT_VOLUME_TYPE UBI_VID_DYNAMIC -++#define UBI_LAYOUT_VOLUME_ALIGN 1 -++#define UBI_LAYOUT_VOLUME_EBS 2 -++#define UBI_LAYOUT_VOLUME_NAME "layout volume" -++#define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT -++ -++/* The maximum number of volumes per one UBI device */ -++#define UBI_MAX_VOLUMES 128 -++ -++/* The maximum volume name length */ -++#define UBI_VOL_NAME_MAX 127 -++ -++/* Size of the volume table record */ -++#define UBI_VTBL_RECORD_SIZE sizeof(struct ubi_vtbl_record) -++ -++/* Size of the volume table record without the ending CRC */ -++#define UBI_VTBL_RECORD_SIZE_CRC (UBI_VTBL_RECORD_SIZE - sizeof(uint32_t)) -++ -++/** -++ * struct ubi_vtbl_record - a record in the volume table. -++ * @reserved_pebs: how many physical eraseblocks are reserved for this volume -++ * @alignment: volume alignment -++ * @data_pad: how many bytes are unused at the end of the each physical -++ * eraseblock to satisfy the requested alignment -++ * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) -++ * @upd_marker: if volume update was started but not finished -++ * @name_len: volume name length -++ * @name: the volume name -++ * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG) -++ * @padding: reserved, zeroes -++ * @crc: a CRC32 checksum of the record -++ * -++ * The volume table records are stored in the volume table, which is stored in -++ * the layout volume. The layout volume consists of 2 logical eraseblock, each -++ * of which contains a copy of the volume table (i.e., the volume table is -++ * duplicated). The volume table is an array of &struct ubi_vtbl_record -++ * objects indexed by the volume ID. -++ * -++ * If the size of the logical eraseblock is large enough to fit -++ * %UBI_MAX_VOLUMES records, the volume table contains %UBI_MAX_VOLUMES -++ * records. Otherwise, it contains as many records as it can fit (i.e., size of -++ * logical eraseblock divided by sizeof(struct ubi_vtbl_record)). -++ * -++ * The @upd_marker flag is used to implement volume update. It is set to %1 -++ * before update and set to %0 after the update. So if the update operation was -++ * interrupted, UBI knows that the volume is corrupted. -++ * -++ * The @alignment field is specified when the volume is created and cannot be -++ * later changed. It may be useful, for example, when a block-oriented file -++ * system works on top of UBI. The @data_pad field is calculated using the -++ * logical eraseblock size and @alignment. The alignment must be multiple to the -++ * minimal flash I/O unit. If @alignment is 1, all the available space of -++ * the physical eraseblocks is used. -++ * -++ * Empty records contain all zeroes and the CRC checksum of those zeroes. -++ */ -++struct ubi_vtbl_record { -++ uint32_t reserved_pebs; -++ uint32_t alignment; -++ uint32_t data_pad; -++ uint8_t vol_type; -++ uint8_t upd_marker; -++ uint16_t name_len; -++ uint8_t name[UBI_VOL_NAME_MAX+1]; -++ uint8_t flags; -++ uint8_t padding[23]; -++ uint32_t crc; -++} __attribute__ ((packed)); -++ -++#endif /* !__UBI_HEADER_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd/ubi-user.h linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd/ubi-user.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd/ubi-user.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd/ubi-user.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,284 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ * -++ * Author: Artem Bityutskiy (Битюцкий Ðртём) -++ */ -++ -++#ifndef __UBI_USER_H__ -++#define __UBI_USER_H__ -++ -++#ifndef __KERNEL__ /* Urgh. The whole point of splitting this out into -++ separate files was to avoid #ifdef __KERNEL__ */ -++#define __user -++#endif -++/* -++ * UBI device creation (the same as MTD device attachment) -++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -++ * -++ * MTD devices may be attached using %UBI_IOCATT ioctl command of the UBI -++ * control device. The caller has to properly fill and pass -++ * &struct ubi_attach_req object - UBI will attach the MTD device specified in -++ * the request and return the newly created UBI device number as the ioctl -++ * return value. -++ * -++ * UBI device deletion (the same as MTD device detachment) -++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -++ * -++ * An UBI device maybe deleted with %UBI_IOCDET ioctl command of the UBI -++ * control device. -++ * -++ * UBI volume creation -++ * ~~~~~~~~~~~~~~~~~~~ -++ * -++ * UBI volumes are created via the %UBI_IOCMKVOL IOCTL command of UBI character -++ * device. A &struct ubi_mkvol_req object has to be properly filled and a -++ * pointer to it has to be passed to the IOCTL. -++ * -++ * UBI volume deletion -++ * ~~~~~~~~~~~~~~~~~~~ -++ * -++ * To delete a volume, the %UBI_IOCRMVOL IOCTL command of the UBI character -++ * device should be used. A pointer to the 32-bit volume ID hast to be passed -++ * to the IOCTL. -++ * -++ * UBI volume re-size -++ * ~~~~~~~~~~~~~~~~~~ -++ * -++ * To re-size a volume, the %UBI_IOCRSVOL IOCTL command of the UBI character -++ * device should be used. A &struct ubi_rsvol_req object has to be properly -++ * filled and a pointer to it has to be passed to the IOCTL. -++ * -++ * UBI volume update -++ * ~~~~~~~~~~~~~~~~~ -++ * -++ * Volume update should be done via the %UBI_IOCVOLUP IOCTL command of the -++ * corresponding UBI volume character device. A pointer to a 64-bit update -++ * size should be passed to the IOCTL. After this, UBI expects user to write -++ * this number of bytes to the volume character device. The update is finished -++ * when the claimed number of bytes is passed. So, the volume update sequence -++ * is something like: -++ * -++ * fd = open("/dev/my_volume"); -++ * ioctl(fd, UBI_IOCVOLUP, &image_size); -++ * write(fd, buf, image_size); -++ * close(fd); -++ * -++ * Atomic eraseblock change -++ * ~~~~~~~~~~~~~~~~~~~~~~~~ -++ * -++ * Atomic eraseblock change operation is done via the %UBI_IOCEBCH IOCTL -++ * command of the corresponding UBI volume character device. A pointer to -++ * &struct ubi_leb_change_req has to be passed to the IOCTL. Then the user is -++ * expected to write the requested amount of bytes. This is similar to the -++ * "volume update" IOCTL. -++ */ -++ -++/* -++ * When a new UBI volume or UBI device is created, users may either specify the -++ * volume/device number they want to create or to let UBI automatically assign -++ * the number using these constants. -++ */ -++#define UBI_VOL_NUM_AUTO (-1) -++#define UBI_DEV_NUM_AUTO (-1) -++ -++/* Maximum volume name length */ -++#define UBI_MAX_VOLUME_NAME 127 -++ -++/* IOCTL commands of UBI character devices */ -++ -++#define UBI_IOC_MAGIC 'o' -++ -++/* Create an UBI volume */ -++#define UBI_IOCMKVOL _IOW(UBI_IOC_MAGIC, 0, struct ubi_mkvol_req) -++/* Remove an UBI volume */ -++#define UBI_IOCRMVOL _IOW(UBI_IOC_MAGIC, 1, int32_t) -++/* Re-size an UBI volume */ -++#define UBI_IOCRSVOL _IOW(UBI_IOC_MAGIC, 2, struct ubi_rsvol_req) -++ -++/* IOCTL commands of the UBI control character device */ -++ -++#define UBI_CTRL_IOC_MAGIC 'o' -++ -++/* Attach an MTD device */ -++#define UBI_IOCATT _IOW(UBI_CTRL_IOC_MAGIC, 64, struct ubi_attach_req) -++/* Detach an MTD device */ -++#define UBI_IOCDET _IOW(UBI_CTRL_IOC_MAGIC, 65, int32_t) -++ -++/* IOCTL commands of UBI volume character devices */ -++ -++#define UBI_VOL_IOC_MAGIC 'O' -++ -++/* Start UBI volume update */ -++#define UBI_IOCVOLUP _IOW(UBI_VOL_IOC_MAGIC, 0, int64_t) -++/* An eraseblock erasure command, used for debugging, disabled by default */ -++#define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 1, int32_t) -++/* An atomic eraseblock change command */ -++#define UBI_IOCEBCH _IOW(UBI_VOL_IOC_MAGIC, 2, int32_t) -++/* Start UBI leb read */ -++#define UBI_IOCLEBREAD _IOWR(UBI_VOL_IOC_MAGIC, 3, struct ubi_leb) -++ -++/* Maximum MTD device name length supported by UBI */ -++#define MAX_UBI_MTD_NAME_LEN 127 -++ -++/* -++ * UBI data type hint constants. -++ * -++ * UBI_LONGTERM: long-term data -++ * UBI_SHORTTERM: short-term data -++ * UBI_UNKNOWN: data persistence is unknown -++ * -++ * These constants are used when data is written to UBI volumes in order to -++ * help the UBI wear-leveling unit to find more appropriate physical -++ * eraseblocks. -++ */ -++enum { -++ UBI_LONGTERM = 1, -++ UBI_SHORTTERM = 2, -++ UBI_UNKNOWN = 3, -++}; -++ -++/* -++ * UBI volume type constants. -++ * -++ * @UBI_DYNAMIC_VOLUME: dynamic volume -++ * @UBI_STATIC_VOLUME: static volume -++ */ -++enum { -++ UBI_DYNAMIC_VOLUME = 3, -++ UBI_STATIC_VOLUME = 4, -++}; -++ -++/** -++ * struct ubi_attach_req - attach MTD device request. -++ * @ubi_num: UBI device number to create -++ * @mtd_num: MTD device number to attach -++ * @vid_hdr_offset: VID header offset (use defaults if %0) -++ * @padding: reserved for future, not used, has to be zeroed -++ * -++ * This data structure is used to specify MTD device UBI has to attach and the -++ * parameters it has to use. The number which should be assigned to the new UBI -++ * device is passed in @ubi_num. UBI may automatically assign the number if -++ * @UBI_DEV_NUM_AUTO is passed. In this case, the device number is returned in -++ * @ubi_num. -++ * -++ * Most applications should pass %0 in @vid_hdr_offset to make UBI use default -++ * offset of the VID header within physical eraseblocks. The default offset is -++ * the next min. I/O unit after the EC header. For example, it will be offset -++ * 512 in case of a 512 bytes page NAND flash with no sub-page support. Or -++ * it will be 512 in case of a 2KiB page NAND flash with 4 512-byte sub-pages. -++ * -++ * But in rare cases, if this optimizes things, the VID header may be placed to -++ * a different offset. For example, the boot-loader might do things faster if the -++ * VID header sits at the end of the first 2KiB NAND page with 4 sub-pages. As -++ * the boot-loader would not normally need to read EC headers (unless it needs -++ * UBI in RW mode), it might be faster to calculate ECC. This is weird example, -++ * but it real-life example. So, in this example, @vid_hdr_offer would be -++ * 2KiB-64 bytes = 1984. Note, that this position is not even 512-bytes -++ * aligned, which is OK, as UBI is clever enough to realize this is 4th sub-page -++ * of the first page and add needed padding. -++ */ -++struct ubi_attach_req { -++ int32_t ubi_num; -++ int32_t mtd_num; -++ int32_t vid_hdr_offset; -++ uint8_t padding[12]; -++}; -++ -++/** -++ * struct ubi_mkvol_req - volume description data structure used in -++ * volume creation requests. -++ * @vol_id: volume number -++ * @alignment: volume alignment -++ * @bytes: volume size in bytes -++ * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) -++ * @padding1: reserved for future, not used, has to be zeroed -++ * @name_len: volume name length -++ * @padding2: reserved for future, not used, has to be zeroed -++ * @name: volume name -++ * -++ * This structure is used by user-space programs when creating new volumes. The -++ * @used_bytes field is only necessary when creating static volumes. -++ * -++ * The @alignment field specifies the required alignment of the volume logical -++ * eraseblock. This means, that the size of logical eraseblocks will be aligned -++ * to this number, i.e., -++ * (UBI device logical eraseblock size) mod (@alignment) = 0. -++ * -++ * To put it differently, the logical eraseblock of this volume may be slightly -++ * shortened in order to make it properly aligned. The alignment has to be -++ * multiple of the flash minimal input/output unit, or %1 to utilize the entire -++ * available space of logical eraseblocks. -++ * -++ * The @alignment field may be useful, for example, when one wants to maintain -++ * a block device on top of an UBI volume. In this case, it is desirable to fit -++ * an integer number of blocks in logical eraseblocks of this UBI volume. With -++ * alignment it is possible to update this volume using plane UBI volume image -++ * BLOBs, without caring about how to properly align them. -++ */ -++struct ubi_mkvol_req { -++ int32_t vol_id; -++ int32_t alignment; -++ int64_t bytes; -++ int8_t vol_type; -++ int8_t padding1; -++ int16_t name_len; -++ int8_t padding2[4]; -++ char name[UBI_MAX_VOLUME_NAME + 1]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubi_rsvol_req - a data structure used in volume re-size requests. -++ * @vol_id: ID of the volume to re-size -++ * @bytes: new size of the volume in bytes -++ * -++ * Re-sizing is possible for both dynamic and static volumes. But while dynamic -++ * volumes may be re-sized arbitrarily, static volumes cannot be made to be -++ * smaller then the number of bytes they bear. To arbitrarily shrink a static -++ * volume, it must be wiped out first (by means of volume update operation with -++ * zero number of bytes). -++ */ -++struct ubi_rsvol_req { -++ int64_t bytes; -++ int32_t vol_id; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubi_leb_change_req - a data structure used in atomic logical -++ * eraseblock change requests. -++ * @lnum: logical eraseblock number to change -++ * @bytes: how many bytes will be written to the logical eraseblock -++ * @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN) -++ * @padding: reserved for future, not used, has to be zeroed -++ */ -++struct ubi_leb_change_req { -++ int32_t lnum; -++ int32_t bytes; -++ uint8_t dtype; -++ uint8_t padding[7]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubi_leb - a data structure describe LEB. -++ * @lnum: logical eraseblock number to dump -++ * @lebbuf: LEB data buffer -++ */ -++struct ubi_leb{ -++ unsigned int lnum; -++ char __user *buf; -++}; -++ -++#endif /* __UBI_USER_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd_swab.h linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd_swab.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/include/mtd_swab.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/include/mtd_swab.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,51 @@ -++#ifndef MTD_SWAB_H -++#define MTD_SWAB_H -++ -++#include -++ -++#define swab16(x) \ -++ ((uint16_t)( \ -++ (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \ -++ (((uint16_t)(x) & (uint16_t)0xff00U) >> 8) )) -++#define swab32(x) \ -++ ((uint32_t)( \ -++ (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \ -++ (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \ -++ (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \ -++ (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24) )) -++ -++#define swab64(x) \ -++ ((uint64_t)( \ -++ (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \ -++ (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \ -++ (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \ -++ (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \ -++ (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \ -++ (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \ -++ (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \ -++ (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56) )) -++ -++ -++#if __BYTE_ORDER == __BIG_ENDIAN -++#define cpu_to_le16(x) ({ uint16_t _x = x; swab16(_x); }) -++#define cpu_to_le32(x) ({ uint32_t _x = x; swab32(_x); }) -++#define cpu_to_le64(x) ({ uint64_t _x = x; swab64(_x); }) -++#define cpu_to_be16(x) (x) -++#define cpu_to_be32(x) (x) -++#define cpu_to_be64(x) (x) -++#else -++#define cpu_to_le16(x) (x) -++#define cpu_to_le32(x) (x) -++#define cpu_to_le64(x) (x) -++#define cpu_to_be16(x) ({ uint16_t _x = x; swab16(_x); }) -++#define cpu_to_be32(x) ({ uint32_t _x = x; swab32(_x); }) -++#define cpu_to_be64(x) ({ uint64_t _x = x; swab64(_x); }) -++#endif -++#define le16_to_cpu(x) cpu_to_le16(x) -++#define be16_to_cpu(x) cpu_to_be16(x) -++#define le32_to_cpu(x) cpu_to_le32(x) -++#define be32_to_cpu(x) cpu_to_be32(x) -++#define le64_to_cpu(x) cpu_to_le64(x) -++#define be64_to_cpu(x) cpu_to_be64(x) -++ -++#endif -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/jffs-dump.c linux-2.6.24.7/drivers/mtd/mtd-utils/jffs-dump.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/jffs-dump.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/jffs-dump.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,359 @@ -++/* -++ * Dump JFFS filesystem. -++ * Useful when it buggers up. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#define BLOCK_SIZE 1024 -++#define JFFS_MAGIC 0x34383931 /* "1984" */ -++#define JFFS_MAX_NAME_LEN 256 -++#define JFFS_MIN_INO 1 -++#define JFFS_TRACE_INDENT 4 -++#define JFFS_ALIGN_SIZE 4 -++#define MAX_CHUNK_SIZE 32768 -++ -++/* How many padding bytes should be inserted between two chunks of data -++ on the flash? */ -++#define JFFS_GET_PAD_BYTES(size) ((JFFS_ALIGN_SIZE \ -++ - ((uint32_t)(size) % JFFS_ALIGN_SIZE)) \ -++ % JFFS_ALIGN_SIZE) -++ -++#define JFFS_EMPTY_BITMASK 0xffffffff -++#define JFFS_MAGIC_BITMASK 0x34383931 -++#define JFFS_DIRTY_BITMASK 0x00000000 -++ -++#define min(x,y) (x) > (y) ? (y) : (x) -++ -++struct jffs_raw_inode -++{ -++ uint32_t magic; /* A constant magic number. */ -++ uint32_t ino; /* Inode number. */ -++ uint32_t pino; /* Parent's inode number. */ -++ uint32_t version; /* Version number. */ -++ uint32_t mode; /* file_type, mode */ -++ uint16_t uid; -++ uint16_t gid; -++ uint32_t atime; -++ uint32_t mtime; -++ uint32_t ctime; -++ uint32_t offset; /* Where to begin to write. */ -++ uint32_t dsize; /* Size of the file data. */ -++ uint32_t rsize; /* How much are going to be replaced? */ -++ uint8_t nsize; /* Name length. */ -++ uint8_t nlink; /* Number of links. */ -++ uint8_t spare : 6; /* For future use. */ -++ uint8_t rename : 1; /* Is this a special rename? */ -++ uint8_t deleted : 1; /* Has this file been deleted? */ -++ uint8_t accurate; /* The inode is obsolete if accurate == 0. */ -++ uint32_t dchksum; /* Checksum for the data. */ -++ uint16_t nchksum; /* Checksum for the name. */ -++ uint16_t chksum; /* Checksum for the raw_inode. */ -++}; -++ -++ -++struct jffs_file -++{ -++ struct jffs_raw_inode inode; -++ char *name; -++ unsigned char *data; -++}; -++ -++ -++char *root_directory_name = NULL; -++int fs_pos = 0; -++int verbose = 0; -++ -++#define ENDIAN_HOST 0 -++#define ENDIAN_BIG 1 -++#define ENDIAN_LITTLE 2 -++int endian = ENDIAN_HOST; -++ -++static uint32_t jffs_checksum(void *data, int size); -++void jffs_print_trace(const char *path, int depth); -++int make_root_dir(FILE *fs, int first_ino, const char *root_dir_path, -++ int depth); -++void write_file(struct jffs_file *f, FILE *fs, struct stat st); -++void read_data(struct jffs_file *f, const char *path, int offset); -++int mkfs(FILE *fs, const char *path, int ino, int parent, int depth); -++ -++ -++ static uint32_t -++jffs_checksum(void *data, int size) -++{ -++ uint32_t sum = 0; -++ uint8_t *ptr = (uint8_t *)data; -++ -++ while (size-- > 0) -++ { -++ sum += *ptr++; -++ } -++ -++ return sum; -++} -++ -++ -++ void -++jffs_print_trace(const char *path, int depth) -++{ -++ int path_len = strlen(path); -++ int out_pos = depth * JFFS_TRACE_INDENT; -++ int pos = path_len - 1; -++ char *out = (char *)alloca(depth * JFFS_TRACE_INDENT + path_len + 1); -++ -++ if (verbose >= 2) -++ { -++ fprintf(stderr, "jffs_print_trace(): path: \"%s\"\n", path); -++ } -++ -++ if (!out) { -++ fprintf(stderr, "jffs_print_trace(): Allocation failed.\n"); -++ fprintf(stderr, " path: \"%s\"\n", path); -++ fprintf(stderr, "depth: %d\n", depth); -++ exit(1); -++ } -++ -++ memset(out, ' ', depth * JFFS_TRACE_INDENT); -++ -++ if (path[pos] == '/') -++ { -++ pos--; -++ } -++ while (path[pos] && (path[pos] != '/')) -++ { -++ pos--; -++ } -++ for (pos++; path[pos] && (path[pos] != '/'); pos++) -++ { -++ out[out_pos++] = path[pos]; -++ } -++ out[out_pos] = '\0'; -++ fprintf(stderr, "%s\n", out); -++} -++ -++ -++/* Print the contents of a raw inode. */ -++ void -++jffs_print_raw_inode(struct jffs_raw_inode *raw_inode) -++{ -++ fprintf(stdout, "jffs_raw_inode: inode number: %u, version %u\n", raw_inode->ino, raw_inode->version); -++ fprintf(stdout, "{\n"); -++ fprintf(stdout, " 0x%08x, /* magic */\n", raw_inode->magic); -++ fprintf(stdout, " 0x%08x, /* ino */\n", raw_inode->ino); -++ fprintf(stdout, " 0x%08x, /* pino */\n", raw_inode->pino); -++ fprintf(stdout, " 0x%08x, /* version */\n", raw_inode->version); -++ fprintf(stdout, " 0x%08x, /* mode */\n", raw_inode->mode); -++ fprintf(stdout, " 0x%04x, /* uid */\n", raw_inode->uid); -++ fprintf(stdout, " 0x%04x, /* gid */\n", raw_inode->gid); -++ fprintf(stdout, " 0x%08x, /* atime */\n", raw_inode->atime); -++ fprintf(stdout, " 0x%08x, /* mtime */\n", raw_inode->mtime); -++ fprintf(stdout, " 0x%08x, /* ctime */\n", raw_inode->ctime); -++ fprintf(stdout, " 0x%08x, /* offset */\n", raw_inode->offset); -++ fprintf(stdout, " 0x%08x, /* dsize */\n", raw_inode->dsize); -++ fprintf(stdout, " 0x%08x, /* rsize */\n", raw_inode->rsize); -++ fprintf(stdout, " 0x%02x, /* nsize */\n", raw_inode->nsize); -++ fprintf(stdout, " 0x%02x, /* nlink */\n", raw_inode->nlink); -++ fprintf(stdout, " 0x%02x, /* spare */\n", -++ raw_inode->spare); -++ fprintf(stdout, " %u, /* rename */\n", -++ raw_inode->rename); -++ fprintf(stdout, " %u, /* deleted */\n", -++ raw_inode->deleted); -++ fprintf(stdout, " 0x%02x, /* accurate */\n", -++ raw_inode->accurate); -++ fprintf(stdout, " 0x%08x, /* dchksum */\n", raw_inode->dchksum); -++ fprintf(stdout, " 0x%04x, /* nchksum */\n", raw_inode->nchksum); -++ fprintf(stdout, " 0x%04x, /* chksum */\n", raw_inode->chksum); -++ fprintf(stdout, "}\n"); -++} -++ -++static void write_val32(uint32_t *adr, uint32_t val) -++{ -++ switch(endian) { -++ case ENDIAN_HOST: -++ *adr = val; -++ break; -++ case ENDIAN_LITTLE: -++ *adr = __cpu_to_le32(val); -++ break; -++ case ENDIAN_BIG: -++ *adr = __cpu_to_be32(val); -++ break; -++ } -++} -++ -++static void write_val16(uint16_t *adr, uint16_t val) -++{ -++ switch(endian) { -++ case ENDIAN_HOST: -++ *adr = val; -++ break; -++ case ENDIAN_LITTLE: -++ *adr = __cpu_to_le16(val); -++ break; -++ case ENDIAN_BIG: -++ *adr = __cpu_to_be16(val); -++ break; -++ } -++} -++ -++static uint32_t read_val32(uint32_t *adr) -++{ -++ uint32_t val; -++ -++ switch(endian) { -++ case ENDIAN_HOST: -++ val = *adr; -++ break; -++ case ENDIAN_LITTLE: -++ val = __le32_to_cpu(*adr); -++ break; -++ case ENDIAN_BIG: -++ val = __be32_to_cpu(*adr); -++ break; -++ } -++ return val; -++} -++ -++static uint16_t read_val16(uint16_t *adr) -++{ -++ uint16_t val; -++ -++ switch(endian) { -++ case ENDIAN_HOST: -++ val = *adr; -++ break; -++ case ENDIAN_LITTLE: -++ val = __le16_to_cpu(*adr); -++ break; -++ case ENDIAN_BIG: -++ val = __be16_to_cpu(*adr); -++ break; -++ } -++ return val; -++} -++ -++ int -++main(int argc, char **argv) -++{ -++ int fs; -++ struct stat sb; -++ uint32_t wordbuf; -++ off_t pos = 0; -++ off_t end; -++ struct jffs_raw_inode ino; -++ unsigned char namebuf[4096]; -++ int myino = -1; -++ -++ if (argc < 2) { -++ printf("no filesystem given\n"); -++ exit(1); -++ } -++ -++ fs = open(argv[1], O_RDONLY); -++ if (fs < 0) { -++ perror("open"); -++ exit(1); -++ } -++ -++ if (argc > 2) { -++ myino = atol(argv[2]); -++ printf("Printing ino #%d\n" , myino); -++ } -++ -++ if (fstat(fs, &sb) < 0) { -++ perror("stat"); -++ close(fs); -++ exit(1); -++ } -++ end = sb.st_size; -++ -++ while (pos < end) { -++ if (pread(fs, &wordbuf, 4, pos) < 0) { -++ perror("pread"); -++ exit(1); -++ } -++ -++ switch(wordbuf) { -++ case JFFS_EMPTY_BITMASK: -++ // printf("0xff started at 0x%lx\n", pos); -++ for (; pos < end && wordbuf == JFFS_EMPTY_BITMASK; pos += 4) { -++ if (pread(fs, &wordbuf, 4, pos) < 0) { -++ perror("pread"); -++ exit(1); -++ } -++ } -++ if (pos < end) -++ pos -= 4; -++ // printf("0xff ended at 0x%lx\n", pos); -++ continue; -++ -++ case JFFS_DIRTY_BITMASK: -++ // printf("0x00 started at 0x%lx\n", pos); -++ for (; pos < end && wordbuf == JFFS_DIRTY_BITMASK; pos += 4) { -++ if (pread(fs, &wordbuf, 4, pos) < 0) { -++ perror("pread"); -++ exit(1); -++ } -++ } -++ if (pos < end) -++ pos -=4; -++ // printf("0x00 ended at 0x%lx\n", pos); -++ continue; -++ -++ default: -++ printf("Argh. Dirty memory at 0x%lx\n", pos); -++ // file_hexdump(fs, pos, 128); -++ for (pos += 4; pos < end; pos += 4) { -++ if (pread(fs, &wordbuf, 4, pos) < 0) { -++ perror("pread"); -++ exit(1); -++ } -++ if (wordbuf == JFFS_MAGIC_BITMASK) -++ break; -++ } -++ -++ case JFFS_MAGIC_BITMASK: -++ if (pread(fs, &ino, sizeof(ino), pos) < 0) { -++ perror("pread"); -++ exit(1); -++ } -++ if (myino == -1 || ino.ino == myino) { -++ printf("Magic found at 0x%lx\n", pos); -++ jffs_print_raw_inode(&ino); -++ } -++ pos += sizeof(ino); -++ -++ if (myino == -1 || ino.ino == myino) { -++ if (ino.nsize) { -++ if (pread(fs, namebuf, min(ino.nsize, 4095), pos) < 0) { -++ perror("pread"); -++ exit(1); -++ } -++ if (ino.nsize < 4095) -++ namebuf[ino.nsize] = 0; -++ else -++ namebuf[4095] = 0; -++ printf("Name: \"%s\"\n", namebuf); -++ } else { -++ printf("No Name\n"); -++ } -++ } -++ pos += (ino.nsize + 3) & ~3; -++ -++ pos += (ino.dsize + 3) & ~3; -++ } -++ -++ -++ -++ } -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/jffs2dump.c linux-2.6.24.7/drivers/mtd/mtd-utils/jffs2dump.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/jffs2dump.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/jffs2dump.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,690 @@ -++/* -++ * dumpjffs2.c -++ * -++ * Copyright (C) 2003 Thomas Gleixner (tglx@linutronix.de) -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ * Overview: -++ * This utility dumps the contents of a binary JFFS2 image -++ * -++ * -++ * Bug/ToDo: -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "crc32.h" -++#include "summary.h" -++ -++#define PROGRAM "jffs2dump" -++#define VERSION "$Revision: 1.1.1.1 $" -++ -++#define PAD(x) (((x)+3)&~3) -++ -++/* For outputting a byte-swapped version of the input image. */ -++#define cnv_e32(x) ((jint32_t){bswap_32(x.v32)}) -++#define cnv_e16(x) ((jint16_t){bswap_16(x.v16)}) -++ -++#define t32_backwards(x) ({ uint32_t __b = (x); (target_endian==__BYTE_ORDER)?bswap_32(__b):__b; }) -++#define cpu_to_e32(x) ((jint32_t){t32_backwards(x)}) -++ -++// Global variables -++long imglen; // length of image -++char *data; // image data -++ -++void display_help (void) -++{ -++ printf("Usage: dumpjffs2 [OPTION] INPUTFILE\n" -++ "Dumps the contents of a binary JFFS2 image.\n" -++ "\n" -++ " --help display this help and exit\n" -++ " --version output version information and exit\n" -++ "-b --bigendian image is big endian\n" -++ "-l --littleendian image is little endian\n" -++ "-c --content dump image contents\n" -++ "-e fname --endianconvert=fname convert image endianness, output to file fname\n" -++ "-r --recalccrc recalc name and data crc on endian conversion\n" -++ "-d len --datsize=len size of data chunks, when oob data in binary image (NAND only)\n" -++ "-o len --oobsize=len size of oob data chunk in binary image (NAND only)\n" -++ "-v --verbose verbose output\n"); -++ exit(0); -++} -++ -++void display_version (void) -++{ -++ printf(PROGRAM " " VERSION "\n" -++ "\n" -++ "Copyright (C) 2003 Thomas Gleixner \n" -++ "\n" -++ PROGRAM " comes with NO WARRANTY\n" -++ "to the extent permitted by law.\n" -++ "\n" -++ "You may redistribute copies of " PROGRAM "\n" -++ "under the terms of the GNU General Public Licence.\n" -++ "See the file `COPYING' for more information.\n"); -++ exit(0); -++} -++ -++// Option variables -++ -++int verbose; // verbose output -++char *img; // filename of image -++int dumpcontent; // dump image content -++int target_endian = __BYTE_ORDER; // image endianess -++int convertendian; // convert endianness -++int recalccrc; // recalc name and data crc's on endian conversion -++char cnvfile[256]; // filename for conversion output -++int datsize; // Size of data chunks, when oob data is inside the binary image -++int oobsize; // Size of oob chunks, when oob data is inside the binary image -++ -++void process_options (int argc, char *argv[]) -++{ -++ int error = 0; -++ -++ for (;;) { -++ int option_index = 0; -++ static const char *short_options = "blce:rd:o:v"; -++ static const struct option long_options[] = { -++ {"help", no_argument, 0, 0}, -++ {"version", no_argument, 0, 0}, -++ {"bigendian", no_argument, 0, 'b'}, -++ {"littleendian", no_argument, 0, 'l'}, -++ {"content", no_argument, 0, 'c'}, -++ {"endianconvert", required_argument, 0, 'e'}, -++ {"datsize", required_argument, 0, 'd'}, -++ {"oobsize", required_argument, 0, 'o'}, -++ {"recalccrc", required_argument, 0, 'r'}, -++ {"verbose", no_argument, 0, 'v'}, -++ {0, 0, 0, 0}, -++ }; -++ -++ int c = getopt_long(argc, argv, short_options, -++ long_options, &option_index); -++ if (c == EOF) { -++ break; -++ } -++ -++ switch (c) { -++ case 0: -++ switch (option_index) { -++ case 0: -++ display_help(); -++ break; -++ case 1: -++ display_version(); -++ break; -++ } -++ break; -++ case 'v': -++ verbose = 1; -++ break; -++ case 'b': -++ target_endian = __BIG_ENDIAN; -++ break; -++ case 'l': -++ target_endian = __LITTLE_ENDIAN; -++ break; -++ case 'c': -++ dumpcontent = 1; -++ break; -++ case 'd': -++ datsize = atoi(optarg); -++ break; -++ case 'o': -++ oobsize = atoi(optarg); -++ break; -++ case 'e': -++ convertendian = 1; -++ strcpy (cnvfile, optarg); -++ break; -++ case 'r': -++ recalccrc = 1; -++ break; -++ case '?': -++ error = 1; -++ break; -++ } -++ } -++ -++ if ((argc - optind) != 1 || error) -++ display_help (); -++ -++ img = argv[optind]; -++} -++ -++ -++/* -++ * Dump image contents -++ */ -++void do_dumpcontent (void) -++{ -++ char *p = data, *p_free_begin; -++ union jffs2_node_union *node; -++ int empty = 0, dirty = 0; -++ char name[256]; -++ uint32_t crc; -++ uint16_t type; -++ int bitchbitmask = 0; -++ int obsolete; -++ -++ p_free_begin = NULL; -++ while ( p < (data + imglen)) { -++ node = (union jffs2_node_union*) p; -++ -++ /* Skip empty space */ -++ if (!p_free_begin) -++ p_free_begin = p; -++ if (je16_to_cpu (node->u.magic) == 0xFFFF && je16_to_cpu (node->u.nodetype) == 0xFFFF) { -++ p += 4; -++ empty += 4; -++ continue; -++ } -++ -++ if (p != p_free_begin) -++ printf("Empty space found from 0x%08x to 0x%08x\n", p_free_begin-data, p-data); -++ p_free_begin = NULL; -++ -++ if (je16_to_cpu (node->u.magic) != JFFS2_MAGIC_BITMASK) { -++ if (!bitchbitmask++) -++ printf ("Wrong bitmask at 0x%08x, 0x%04x\n", p - data, je16_to_cpu (node->u.magic)); -++ p += 4; -++ dirty += 4; -++ continue; -++ } -++ bitchbitmask = 0; -++ -++ type = je16_to_cpu(node->u.nodetype); -++ if ((type & JFFS2_NODE_ACCURATE) != JFFS2_NODE_ACCURATE) { -++ obsolete = 1; -++ type |= JFFS2_NODE_ACCURATE; -++ } else -++ obsolete = 0; -++ /* Set accurate for CRC check */ -++ node->u.nodetype = cpu_to_je16(type); -++ -++ crc = crc32 (0, node, sizeof (struct jffs2_unknown_node) - 4); -++ if (crc != je32_to_cpu (node->u.hdr_crc)) { -++ printf ("Wrong hdr_crc at 0x%08x, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->u.hdr_crc), crc); -++ p += 4; -++ dirty += 4; -++ continue; -++ } -++ -++ switch(je16_to_cpu(node->u.nodetype)) { -++ -++ case JFFS2_NODETYPE_INODE: -++ printf ("%8s Inode node at 0x%08x, totlen 0x%08x, #ino %5d, version %5d, isize %8d, csize %8d, dsize %8d, offset %8d\n", -++ obsolete ? "Obsolete" : "", -++ p - data, je32_to_cpu (node->i.totlen), je32_to_cpu (node->i.ino), -++ je32_to_cpu ( node->i.version), je32_to_cpu (node->i.isize), -++ je32_to_cpu (node->i.csize), je32_to_cpu (node->i.dsize), je32_to_cpu (node->i.offset)); -++ -++ crc = crc32 (0, node, sizeof (struct jffs2_raw_inode) - 8); -++ if (crc != je32_to_cpu (node->i.node_crc)) { -++ printf ("Wrong node_crc at 0x%08x, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->i.node_crc), crc); -++ p += PAD(je32_to_cpu (node->i.totlen)); -++ dirty += PAD(je32_to_cpu (node->i.totlen));; -++ continue; -++ } -++ -++ crc = crc32(0, p + sizeof (struct jffs2_raw_inode), je32_to_cpu(node->i.csize)); -++ if (crc != je32_to_cpu(node->i.data_crc)) { -++ printf ("Wrong data_crc at 0x%08x, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->i.data_crc), crc); -++ p += PAD(je32_to_cpu (node->i.totlen)); -++ dirty += PAD(je32_to_cpu (node->i.totlen));; -++ continue; -++ } -++ -++ p += PAD(je32_to_cpu (node->i.totlen)); -++ break; -++ -++ case JFFS2_NODETYPE_DIRENT: -++ memcpy (name, node->d.name, node->d.nsize); -++ name [node->d.nsize] = 0x0; -++ printf ("%8s Dirent node at 0x%08x, totlen 0x%08x, #pino %5d, version %5d, #ino %8d, nsize %8d, name %s\n", -++ obsolete ? "Obsolete" : "", -++ p - data, je32_to_cpu (node->d.totlen), je32_to_cpu (node->d.pino), -++ je32_to_cpu ( node->d.version), je32_to_cpu (node->d.ino), -++ node->d.nsize, name); -++ -++ crc = crc32 (0, node, sizeof (struct jffs2_raw_dirent) - 8); -++ if (crc != je32_to_cpu (node->d.node_crc)) { -++ printf ("Wrong node_crc at 0x%08x, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->d.node_crc), crc); -++ p += PAD(je32_to_cpu (node->d.totlen)); -++ dirty += PAD(je32_to_cpu (node->d.totlen));; -++ continue; -++ } -++ -++ crc = crc32(0, p + sizeof (struct jffs2_raw_dirent), node->d.nsize); -++ if (crc != je32_to_cpu(node->d.name_crc)) { -++ printf ("Wrong name_crc at 0x%08x, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->d.name_crc), crc); -++ p += PAD(je32_to_cpu (node->d.totlen)); -++ dirty += PAD(je32_to_cpu (node->d.totlen));; -++ continue; -++ } -++ -++ p += PAD(je32_to_cpu (node->d.totlen)); -++ break; -++ -++ case JFFS2_NODETYPE_SUMMARY: { -++ -++ int i; -++ struct jffs2_sum_marker * sm; -++ -++ printf("%8s Inode Sum node at 0x%08x, totlen 0x%08x, sum_num %5d, cleanmarker size %5d\n", -++ obsolete ? "Obsolete" : "", -++ p - data, -++ je32_to_cpu (node->s.totlen), -++ je32_to_cpu (node->s.sum_num), -++ je32_to_cpu (node->s.cln_mkr)); -++ -++ crc = crc32 (0, node, sizeof (struct jffs2_raw_summary) - 8); -++ if (crc != je32_to_cpu (node->s.node_crc)) { -++ printf ("Wrong node_crc at 0x%08x, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->s.node_crc), crc); -++ p += PAD(je32_to_cpu (node->s.totlen)); -++ dirty += PAD(je32_to_cpu (node->s.totlen));; -++ continue; -++ } -++ -++ crc = crc32(0, p + sizeof (struct jffs2_raw_summary), je32_to_cpu (node->s.totlen) - sizeof(struct jffs2_raw_summary)); -++ if (crc != je32_to_cpu(node->s.sum_crc)) { -++ printf ("Wrong data_crc at 0x%08x, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->s.sum_crc), crc); -++ p += PAD(je32_to_cpu (node->s.totlen)); -++ dirty += PAD(je32_to_cpu (node->s.totlen));; -++ continue; -++ } -++ -++ if (verbose) { -++ void *sp; -++ sp = (p + sizeof(struct jffs2_raw_summary)); -++ -++ for(i=0; is.sum_num); i++) { -++ -++ switch(je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { -++ case JFFS2_NODETYPE_INODE : { -++ -++ struct jffs2_sum_inode_flash *spi; -++ spi = sp; -++ -++ printf ("%14s #ino %5d, version %5d, offset 0x%08x, totlen 0x%08x\n", -++ "", -++ je32_to_cpu (spi->inode), -++ je32_to_cpu (spi->version), -++ je32_to_cpu (spi->offset), -++ je32_to_cpu (spi->totlen)); -++ -++ sp += JFFS2_SUMMARY_INODE_SIZE; -++ break; -++ } -++ -++ case JFFS2_NODETYPE_DIRENT : { -++ -++ char name[255]; -++ struct jffs2_sum_dirent_flash *spd; -++ spd = sp; -++ -++ memcpy(name,spd->name,spd->nsize); -++ name [spd->nsize] = 0x0; -++ -++ printf ("%14s dirent offset 0x%08x, totlen 0x%08x, #pino %5d, version %5d, #ino %8d, nsize %8d, name %s \n", -++ "", -++ je32_to_cpu (spd->offset), -++ je32_to_cpu (spd->totlen), -++ je32_to_cpu (spd->pino), -++ je32_to_cpu (spd->version), -++ je32_to_cpu (spd->ino), -++ spd->nsize, -++ name); -++ -++ sp += JFFS2_SUMMARY_DIRENT_SIZE(spd->nsize); -++ break; -++ } -++ -++ default : -++ printf("Unknown summary node!\n"); -++ break; -++ } -++ } -++ -++ sm = (struct jffs2_sum_marker *) ((char *)p + je32_to_cpu(node->s.totlen) - sizeof(struct jffs2_sum_marker)); -++ -++ printf("%14s Sum Node Offset 0x%08x, Magic 0x%08x, Padded size 0x%08x\n", -++ "", -++ je32_to_cpu(sm->offset), -++ je32_to_cpu(sm->magic), -++ je32_to_cpu(node->s.padded)); -++ } -++ -++ p += PAD(je32_to_cpu (node->s.totlen)); -++ break; -++ } -++ -++ case JFFS2_NODETYPE_CLEANMARKER: -++ if (verbose) { -++ printf ("%8s Cleanmarker at 0x%08x, totlen 0x%08x\n", -++ obsolete ? "Obsolete" : "", -++ p - data, je32_to_cpu (node->u.totlen)); -++ } -++ p += PAD(je32_to_cpu (node->u.totlen)); -++ break; -++ -++ case JFFS2_NODETYPE_PADDING: -++ if (verbose) { -++ printf ("%8s Padding node at 0x%08x, totlen 0x%08x\n", -++ obsolete ? "Obsolete" : "", -++ p - data, je32_to_cpu (node->u.totlen)); -++ } -++ p += PAD(je32_to_cpu (node->u.totlen)); -++ break; -++ -++ case 0xffff: -++ p += 4; -++ empty += 4; -++ break; -++ -++ default: -++ if (verbose) { -++ printf ("%8s Unknown node at 0x%08x, totlen 0x%08x\n", -++ obsolete ? "Obsolete" : "", -++ p - data, je32_to_cpu (node->u.totlen)); -++ } -++ p += PAD(je32_to_cpu (node->u.totlen)); -++ dirty += PAD(je32_to_cpu (node->u.totlen)); -++ -++ } -++ } -++ -++ if (verbose) -++ printf ("Empty space: %d, dirty space: %d\n", empty, dirty); -++} -++ -++/* -++ * Convert endianess -++ */ -++void do_endianconvert (void) -++{ -++ char *p = data; -++ union jffs2_node_union *node, newnode; -++ int fd, len; -++ jint32_t mode; -++ uint32_t crc; -++ -++ fd = open (cnvfile, O_WRONLY | O_CREAT, 0644); -++ if (fd < 0) { -++ fprintf (stderr, "Cannot open / create file: %s\n", cnvfile); -++ return; -++ } -++ -++ while ( p < (data + imglen)) { -++ node = (union jffs2_node_union*) p; -++ -++ /* Skip empty space */ -++ if (je16_to_cpu (node->u.magic) == 0xFFFF && je16_to_cpu (node->u.nodetype) == 0xFFFF) { -++ write (fd, p, 4); -++ p += 4; -++ continue; -++ } -++ -++ if (je16_to_cpu (node->u.magic) != JFFS2_MAGIC_BITMASK) { -++ printf ("Wrong bitmask at 0x%08x, 0x%04x\n", p - data, je16_to_cpu (node->u.magic)); -++ newnode.u.magic = cnv_e16 (node->u.magic); -++ newnode.u.nodetype = cnv_e16 (node->u.nodetype); -++ write (fd, &newnode, 4); -++ p += 4; -++ continue; -++ } -++ -++ crc = crc32 (0, node, sizeof (struct jffs2_unknown_node) - 4); -++ if (crc != je32_to_cpu (node->u.hdr_crc)) { -++ printf ("Wrong hdr_crc at 0x%08x, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->u.hdr_crc), crc); -++ } -++ -++ switch(je16_to_cpu(node->u.nodetype)) { -++ -++ case JFFS2_NODETYPE_INODE: -++ -++ newnode.i.magic = cnv_e16 (node->i.magic); -++ newnode.i.nodetype = cnv_e16 (node->i.nodetype); -++ newnode.i.totlen = cnv_e32 (node->i.totlen); -++ newnode.i.hdr_crc = cpu_to_e32 (crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - 4)); -++ newnode.i.ino = cnv_e32 (node->i.ino); -++ newnode.i.version = cnv_e32 (node->i.version); -++ mode.v32 = node->i.mode.m; -++ mode = cnv_e32 (mode); -++ newnode.i.mode.m = mode.v32; -++ newnode.i.uid = cnv_e16 (node->i.uid); -++ newnode.i.gid = cnv_e16 (node->i.gid); -++ newnode.i.isize = cnv_e32 (node->i.isize); -++ newnode.i.atime = cnv_e32 (node->i.atime); -++ newnode.i.mtime = cnv_e32 (node->i.mtime); -++ newnode.i.ctime = cnv_e32 (node->i.ctime); -++ newnode.i.offset = cnv_e32 (node->i.offset); -++ newnode.i.csize = cnv_e32 (node->i.csize); -++ newnode.i.dsize = cnv_e32 (node->i.dsize); -++ newnode.i.compr = node->i.compr; -++ newnode.i.usercompr = node->i.usercompr; -++ newnode.i.flags = cnv_e16 (node->i.flags); -++ if (recalccrc) { -++ len = je32_to_cpu(node->i.csize); -++ newnode.i.data_crc = cpu_to_e32 ( crc32(0, p + sizeof (struct jffs2_raw_inode), len)); -++ } else -++ newnode.i.data_crc = cnv_e32 (node->i.data_crc); -++ -++ newnode.i.node_crc = cpu_to_e32 (crc32 (0, &newnode, sizeof (struct jffs2_raw_inode) - 8)); -++ -++ write (fd, &newnode, sizeof (struct jffs2_raw_inode)); -++ write (fd, p + sizeof (struct jffs2_raw_inode), PAD (je32_to_cpu (node->i.totlen) - sizeof (struct jffs2_raw_inode))); -++ -++ p += PAD(je32_to_cpu (node->i.totlen)); -++ break; -++ -++ case JFFS2_NODETYPE_DIRENT: -++ newnode.d.magic = cnv_e16 (node->d.magic); -++ newnode.d.nodetype = cnv_e16 (node->d.nodetype); -++ newnode.d.totlen = cnv_e32 (node->d.totlen); -++ newnode.d.hdr_crc = cpu_to_e32 (crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - 4)); -++ newnode.d.pino = cnv_e32 (node->d.pino); -++ newnode.d.version = cnv_e32 (node->d.version); -++ newnode.d.ino = cnv_e32 (node->d.ino); -++ newnode.d.mctime = cnv_e32 (node->d.mctime); -++ newnode.d.nsize = node->d.nsize; -++ newnode.d.type = node->d.type; -++ newnode.d.unused[0] = node->d.unused[0]; -++ newnode.d.unused[1] = node->d.unused[1]; -++ newnode.d.node_crc = cpu_to_e32 (crc32 (0, &newnode, sizeof (struct jffs2_raw_dirent) - 8)); -++ if (recalccrc) -++ newnode.d.name_crc = cpu_to_e32 ( crc32(0, p + sizeof (struct jffs2_raw_dirent), node->d.nsize)); -++ else -++ newnode.d.name_crc = cnv_e32 (node->d.name_crc); -++ -++ write (fd, &newnode, sizeof (struct jffs2_raw_dirent)); -++ write (fd, p + sizeof (struct jffs2_raw_dirent), PAD (je32_to_cpu (node->d.totlen) - sizeof (struct jffs2_raw_dirent))); -++ p += PAD(je32_to_cpu (node->d.totlen)); -++ break; -++ -++ case JFFS2_NODETYPE_CLEANMARKER: -++ case JFFS2_NODETYPE_PADDING: -++ newnode.u.magic = cnv_e16 (node->u.magic); -++ newnode.u.nodetype = cnv_e16 (node->u.nodetype); -++ newnode.u.totlen = cnv_e32 (node->u.totlen); -++ newnode.u.hdr_crc = cpu_to_e32 (crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - 4)); -++ -++ write (fd, &newnode, sizeof (struct jffs2_unknown_node)); -++ len = PAD(je32_to_cpu (node->u.totlen) - sizeof (struct jffs2_unknown_node)); -++ if (len > 0) -++ write (fd, p + sizeof (struct jffs2_unknown_node), len); -++ -++ p += PAD(je32_to_cpu (node->u.totlen)); -++ break; -++ -++ case JFFS2_NODETYPE_SUMMARY : { -++ struct jffs2_sum_marker *sm_ptr; -++ int i,sum_len; -++ int counter = 0; -++ -++ newnode.s.magic = cnv_e16 (node->s.magic); -++ newnode.s.nodetype = cnv_e16 (node->s.nodetype); -++ newnode.s.totlen = cnv_e32 (node->s.totlen); -++ newnode.s.hdr_crc = cpu_to_e32 (crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - 4)); -++ newnode.s.sum_num = cnv_e32 (node->s.sum_num); -++ newnode.s.cln_mkr = cnv_e32 (node->s.cln_mkr); -++ newnode.s.padded = cnv_e32 (node->s.padded); -++ -++ newnode.s.node_crc = cpu_to_e32 (crc32 (0, &newnode, sizeof (struct jffs2_raw_summary) - 8)); -++ -++ // summary header -++ p += sizeof (struct jffs2_raw_summary); -++ -++ // summary data -++ sum_len = je32_to_cpu (node->s.totlen) - sizeof (struct jffs2_raw_summary) - sizeof (struct jffs2_sum_marker); -++ -++ for (i=0; is.sum_num); i++) { -++ union jffs2_sum_flash *fl_ptr; -++ -++ fl_ptr = (union jffs2_sum_flash *) p; -++ -++ switch (je16_to_cpu (fl_ptr->u.nodetype)) { -++ case JFFS2_NODETYPE_INODE: -++ -++ fl_ptr->i.nodetype = cnv_e16 (fl_ptr->i.nodetype); -++ fl_ptr->i.inode = cnv_e32 (fl_ptr->i.inode); -++ fl_ptr->i.version = cnv_e32 (fl_ptr->i.version); -++ fl_ptr->i.offset = cnv_e32 (fl_ptr->i.offset); -++ fl_ptr->i.totlen = cnv_e32 (fl_ptr->i.totlen); -++ p += sizeof (struct jffs2_sum_inode_flash); -++ counter += sizeof (struct jffs2_sum_inode_flash); -++ break; -++ -++ case JFFS2_NODETYPE_DIRENT: -++ fl_ptr->d.nodetype = cnv_e16 (fl_ptr->d.nodetype); -++ fl_ptr->d.totlen = cnv_e32 (fl_ptr->d.totlen); -++ fl_ptr->d.offset = cnv_e32 (fl_ptr->d.offset); -++ fl_ptr->d.pino = cnv_e32 (fl_ptr->d.pino); -++ fl_ptr->d.version = cnv_e32 (fl_ptr->d.version); -++ fl_ptr->d.ino = cnv_e32 (fl_ptr->d.ino); -++ p += sizeof (struct jffs2_sum_dirent_flash) + fl_ptr->d.nsize; -++ counter += sizeof (struct jffs2_sum_dirent_flash) + fl_ptr->d.nsize; -++ break; -++ -++ default : -++ printf("Unknown node in summary information!!! nodetype(%x)\n", je16_to_cpu (fl_ptr->u.nodetype)); -++ exit(EXIT_FAILURE); -++ break; -++ } -++ -++ } -++ -++ //pad -++ p += sum_len - counter; -++ -++ // summary marker -++ sm_ptr = (struct jffs2_sum_marker *) p; -++ sm_ptr->offset = cnv_e32 (sm_ptr->offset); -++ sm_ptr->magic = cnv_e32 (sm_ptr->magic); -++ p += sizeof (struct jffs2_sum_marker); -++ -++ // generate new crc on sum data -++ newnode.s.sum_crc = cpu_to_e32 ( crc32(0, ((char *) node) + sizeof (struct jffs2_raw_summary), -++ je32_to_cpu (node->s.totlen) - sizeof (struct jffs2_raw_summary))); -++ -++ // write out new node header -++ write(fd, &newnode, sizeof (struct jffs2_raw_summary)); -++ // write out new summary data -++ write(fd, &node->s.sum, sum_len + sizeof (struct jffs2_sum_marker)); -++ -++ break; -++ } -++ -++ case 0xffff: -++ write (fd, p, 4); -++ p += 4; -++ break; -++ -++ default: -++ printf ("Unknown node type: 0x%04x at 0x%08x, totlen 0x%08x\n", je16_to_cpu (node->u.nodetype), p - data, je32_to_cpu (node->u.totlen)); -++ p += PAD(je32_to_cpu (node->u.totlen)); -++ -++ } -++ } -++ -++ close (fd); -++ -++} -++ -++/* -++ * Main program -++ */ -++int main(int argc, char **argv) -++{ -++ int fd; -++ -++ process_options(argc, argv); -++ -++ /* Open the input file */ -++ if ((fd = open(img, O_RDONLY)) == -1) { -++ perror("open input file"); -++ exit(1); -++ } -++ -++ // get image length -++ imglen = lseek(fd, 0, SEEK_END); -++ lseek (fd, 0, SEEK_SET); -++ -++ data = malloc (imglen); -++ if (!data) { -++ perror("out of memory"); -++ close (fd); -++ exit(1); -++ } -++ -++ if (datsize && oobsize) { -++ int idx = 0; -++ long len = imglen; -++ uint8_t oob[oobsize]; -++ printf ("Peeling data out of combined data/oob image\n"); -++ while (len) { -++ // read image data -++ read (fd, &data[idx], datsize); -++ read (fd, oob, oobsize); -++ idx += datsize; -++ imglen -= oobsize; -++ len -= datsize + oobsize; -++ } -++ -++ } else { -++ // read image data -++ read (fd, data, imglen); -++ } -++ // Close the input file -++ close(fd); -++ -++ if (dumpcontent) -++ do_dumpcontent (); -++ -++ if (convertendian) -++ do_endianconvert (); -++ -++ // free memory -++ free (data); -++ -++ // Return happy -++ exit (0); -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/jffs2reader.c linux-2.6.24.7/drivers/mtd/mtd-utils/jffs2reader.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/jffs2reader.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/jffs2reader.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,939 @@ -++/* vi: set sw=4 ts=4: */ -++/* -++ * jffs2reader v0.0.18 A jffs2 image reader -++ * -++ * Copyright (c) 2001 Jari Kirma -++ * -++ * This software is provided 'as-is', without any express or implied -++ * warranty. In no event will the author be held liable for any damages -++ * arising from the use of this software. -++ * -++ * Permission is granted to anyone to use this software for any -++ * purpose, including commercial applications, and to alter it and -++ * redistribute it freely, subject to the following restrictions: -++ * -++ * 1. The origin of this software must not be misrepresented; you must -++ * not claim that you wrote the original software. If you use this -++ * software in a product, an acknowledgment in the product -++ * documentation would be appreciated but is not required. -++ * -++ * 2. Altered source versions must be plainly marked as such, and must -++ * not be misrepresented as being the original software. -++ * -++ * 3. This notice may not be removed or altered from any source -++ * distribution. -++ * -++ * -++ ********* -++ * This code was altered September 2001 -++ * Changes are Copyright (c) Erik Andersen -++ * -++ * In compliance with (2) above, this is hereby marked as an altered -++ * version of this software. It has been altered as follows: -++ * *) Listing a directory now mimics the behavior of 'ls -l' -++ * *) Support for recursive listing has been added -++ * *) Without options, does a recursive 'ls' on the whole filesystem -++ * *) option parsing now uses getopt() -++ * *) Now uses printf, and error messages go to stderr. -++ * *) The copyright notice has been cleaned up and reformatted -++ * *) The code has been reformatted -++ * *) Several twisty code paths have been fixed so I can understand them. -++ * -Erik, 1 September 2001 -++ * -++ * *) Made it show major/minor numbers for device nodes -++ * *) Made it show symlink targets -++ * -Erik, 13 September 2001 -++ */ -++ -++ -++/* -++TODO: -++ -++- Add CRC checking code to places marked with XXX. -++- Add support for other node compression types. -++ -++- Test with real life images. -++- Maybe port into bootloader. -++ */ -++ -++/* -++BUGS: -++ -++- Doesn't check CRC checksums. -++ */ -++ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#define SCRATCH_SIZE (5*1024*1024) -++ -++#ifndef MAJOR -++/* FIXME: I am using illicit insider knowledge of -++ * kernel major/minor representation... */ -++#define MAJOR(dev) (((dev)>>8)&0xff) -++#define MINOR(dev) ((dev)&0xff) -++#endif -++ -++ -++#define DIRENT_INO(dirent) ((dirent)!=NULL?(dirent)->ino:0) -++#define DIRENT_PINO(dirent) ((dirent)!=NULL?(dirent)->pino:0) -++ -++struct dir { -++ struct dir *next; -++ uint8_t type; -++ uint8_t nsize; -++ uint32_t ino; -++ char name[256]; -++}; -++ -++void putblock(char *, size_t, size_t *, struct jffs2_raw_inode *); -++struct dir *putdir(struct dir *, struct jffs2_raw_dirent *); -++void printdir(char *o, size_t size, struct dir *d, char *path, -++ int recurse); -++void freedir(struct dir *); -++ -++struct jffs2_raw_inode *find_raw_inode(char *o, size_t size, uint32_t ino); -++struct jffs2_raw_dirent *resolvedirent(char *, size_t, uint32_t, uint32_t, -++ char *, uint8_t); -++struct jffs2_raw_dirent *resolvename(char *, size_t, uint32_t, char *, uint8_t); -++struct jffs2_raw_dirent *resolveinode(char *, size_t, uint32_t); -++ -++struct jffs2_raw_dirent *resolvepath0(char *, size_t, uint32_t, char *, -++ uint32_t *, int); -++struct jffs2_raw_dirent *resolvepath(char *, size_t, uint32_t, char *, -++ uint32_t *); -++ -++void lsdir(char *, size_t, char *, int); -++void catfile(char *, size_t, char *, char *, size_t, size_t *); -++ -++int main(int, char **); -++ -++/* writes file node into buffer, to the proper position. */ -++/* reading all valid nodes in version order reconstructs the file. */ -++ -++/* -++ b - buffer -++ bsize - buffer size -++ rsize - result size -++ n - node -++ */ -++ -++void putblock(char *b, size_t bsize, size_t * rsize, -++ struct jffs2_raw_inode *n) -++{ -++ uLongf dlen = n->dsize; -++ -++ if (n->isize > bsize || (n->offset + dlen) > bsize) { -++ fprintf(stderr, "File does not fit into buffer!\n"); -++ exit(EXIT_FAILURE); -++ } -++ -++ if (*rsize < n->isize) -++ bzero(b + *rsize, n->isize - *rsize); -++ -++ switch (n->compr) { -++ case JFFS2_COMPR_ZLIB: -++ uncompress((Bytef *) b + n->offset, &dlen, -++ (Bytef *) ((char *) n) + sizeof(struct jffs2_raw_inode), -++ (uLongf) n->csize); -++ break; -++ -++ case JFFS2_COMPR_NONE: -++ memcpy(b + n->offset, -++ ((char *) n) + sizeof(struct jffs2_raw_inode), dlen); -++ break; -++ -++ case JFFS2_COMPR_ZERO: -++ bzero(b + n->offset, dlen); -++ break; -++ -++ /* [DYN]RUBIN support required! */ -++ -++ default: -++ fprintf(stderr, "Unsupported compression method!\n"); -++ exit(EXIT_FAILURE); -++ } -++ -++ *rsize = n->isize; -++} -++ -++/* adds/removes directory node into dir struct. */ -++/* reading all valid nodes in version order reconstructs the directory. */ -++ -++/* -++ dd - directory struct being processed -++ n - node -++ -++ return value: directory struct value replacing dd -++ */ -++ -++struct dir *putdir(struct dir *dd, struct jffs2_raw_dirent *n) -++{ -++ struct dir *o, *d, *p; -++ -++ o = dd; -++ -++ if (n->ino) { -++ if (dd == NULL) { -++ d = malloc(sizeof(struct dir)); -++ d->type = n->type; -++ memcpy(d->name, n->name, n->nsize); -++ d->nsize = n->nsize; -++ d->ino = n->ino; -++ d->next = NULL; -++ -++ return d; -++ } -++ -++ while (1) { -++ if (n->nsize == dd->nsize && -++ !memcmp(n->name, dd->name, n->nsize)) { -++ dd->type = n->type; -++ dd->ino = n->ino; -++ -++ return o; -++ } -++ -++ if (dd->next == NULL) { -++ dd->next = malloc(sizeof(struct dir)); -++ dd->next->type = n->type; -++ memcpy(dd->next->name, n->name, n->nsize); -++ dd->next->nsize = n->nsize; -++ dd->next->ino = n->ino; -++ dd->next->next = NULL; -++ -++ return o; -++ } -++ -++ dd = dd->next; -++ } -++ } else { -++ if (dd == NULL) -++ return NULL; -++ -++ if (n->nsize == dd->nsize && !memcmp(n->name, dd->name, n->nsize)) { -++ d = dd->next; -++ free(dd); -++ return d; -++ } -++ -++ while (1) { -++ p = dd; -++ dd = dd->next; -++ -++ if (dd == NULL) -++ return o; -++ -++ if (n->nsize == dd->nsize && -++ !memcmp(n->name, dd->name, n->nsize)) { -++ p->next = dd->next; -++ free(dd); -++ -++ return o; -++ } -++ } -++ } -++} -++ -++ -++#define TYPEINDEX(mode) (((mode) >> 12) & 0x0f) -++#define TYPECHAR(mode) ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)]) -++ -++/* The special bits. If set, display SMODE0/1 instead of MODE0/1 */ -++static const mode_t SBIT[] = { -++ 0, 0, S_ISUID, -++ 0, 0, S_ISGID, -++ 0, 0, S_ISVTX -++}; -++ -++/* The 9 mode bits to test */ -++static const mode_t MBIT[] = { -++ S_IRUSR, S_IWUSR, S_IXUSR, -++ S_IRGRP, S_IWGRP, S_IXGRP, -++ S_IROTH, S_IWOTH, S_IXOTH -++}; -++ -++static const char MODE1[] = "rwxrwxrwx"; -++static const char MODE0[] = "---------"; -++static const char SMODE1[] = "..s..s..t"; -++static const char SMODE0[] = "..S..S..T"; -++ -++/* -++ * Return the standard ls-like mode string from a file mode. -++ * This is static and so is overwritten on each call. -++ */ -++const char *mode_string(int mode) -++{ -++ static char buf[12]; -++ -++ int i; -++ -++ buf[0] = TYPECHAR(mode); -++ for (i = 0; i < 9; i++) { -++ if (mode & SBIT[i]) -++ buf[i + 1] = (mode & MBIT[i]) ? SMODE1[i] : SMODE0[i]; -++ else -++ buf[i + 1] = (mode & MBIT[i]) ? MODE1[i] : MODE0[i]; -++ } -++ return buf; -++} -++ -++/* prints contents of directory structure */ -++ -++/* -++ d - dir struct -++ */ -++ -++void printdir(char *o, size_t size, struct dir *d, char *path, int recurse) -++{ -++ char m; -++ char *filetime; -++ time_t age; -++ struct jffs2_raw_inode *ri; -++ -++ if (!path) -++ return; -++ if (strlen(path) == 1 && *path == '/') -++ path++; -++ -++ while (d != NULL) { -++ switch (d->type) { -++ case DT_REG: -++ m = ' '; -++ break; -++ -++ case DT_FIFO: -++ m = '|'; -++ break; -++ -++ case DT_CHR: -++ m = ' '; -++ break; -++ -++ case DT_BLK: -++ m = ' '; -++ break; -++ -++ case DT_DIR: -++ m = '/'; -++ break; -++ -++ case DT_LNK: -++ m = ' '; -++ break; -++ -++ case DT_SOCK: -++ m = '='; -++ break; -++ -++ default: -++ m = '?'; -++ } -++ ri = find_raw_inode(o, size, d->ino); -++ if (!ri) { -++ fprintf(stderr, "bug: raw_inode missing!\n"); -++ d = d->next; -++ continue; -++ } -++ -++ filetime = ctime((const time_t *) &(ri->ctime)); -++ age = time(NULL) - ri->ctime; -++ printf("%s %-4d %-8d %-8d ", mode_string(ri->mode), -++ 1, ri->uid, ri->gid); -++ if ( d->type==DT_BLK || d->type==DT_CHR ) { -++ dev_t rdev; -++ size_t devsize; -++ putblock((char*)&rdev, sizeof(rdev), &devsize, ri); -++ printf("%4d, %3d ", (int)MAJOR(rdev), (int)MINOR(rdev)); -++ } else { -++ printf("%9ld ", (long)ri->dsize); -++ } -++ d->name[d->nsize]='\0'; -++ if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) { -++ /* hh:mm if less than 6 months old */ -++ printf("%6.6s %5.5s %s/%s%c", filetime + 4, filetime + 11, path, d->name, m); -++ } else { -++ printf("%6.6s %4.4s %s/%s%c", filetime + 4, filetime + 20, path, d->name, m); -++ } -++ if (d->type == DT_LNK) { -++ char symbuf[1024]; -++ size_t symsize; -++ putblock(symbuf, sizeof(symbuf), &symsize, ri); -++ symbuf[symsize] = 0; -++ printf(" -> %s", symbuf); -++ } -++ printf("\n"); -++ -++ if (d->type == DT_DIR && recurse) { -++ char *tmp; -++ tmp = malloc(BUFSIZ); -++ if (!tmp) { -++ fprintf(stderr, "memory exhausted\n"); -++ exit(EXIT_FAILURE); -++ } -++ sprintf(tmp, "%s/%s", path, d->name); -++ lsdir(o, size, tmp, recurse); /* Go recursive */ -++ free(tmp); -++ } -++ -++ d = d->next; -++ } -++} -++ -++/* frees memory used by directory structure */ -++ -++/* -++ d - dir struct -++ */ -++ -++void freedir(struct dir *d) -++{ -++ struct dir *t; -++ -++ while (d != NULL) { -++ t = d->next; -++ free(d); -++ d = t; -++ } -++} -++ -++/* collects directory/file nodes in version order. */ -++ -++/* -++ f - file flag. -++ if zero, collect file, compare ino to inode -++ otherwise, collect directory, compare ino to parent inode -++ o - filesystem image pointer -++ size - size of filesystem image -++ ino - inode to compare against. see f. -++ -++ return value: a jffs2_raw_inode that corresponds the the specified -++ inode, or NULL -++ */ -++ -++struct jffs2_raw_inode *find_raw_inode(char *o, size_t size, uint32_t ino) -++{ -++ /* aligned! */ -++ union jffs2_node_union *n; -++ union jffs2_node_union *e = (union jffs2_node_union *) (o + size); -++ union jffs2_node_union *lr; /* last block position */ -++ union jffs2_node_union *mp = NULL; /* minimum position */ -++ -++ uint32_t vmin, vmint, vmaxt, vmax, vcur, v; -++ -++ vmin = 0; /* next to read */ -++ vmax = ~((uint32_t) 0); /* last to read */ -++ vmint = ~((uint32_t) 0); -++ vmaxt = 0; /* found maximum */ -++ vcur = 0; /* XXX what is smallest version number used? */ -++ /* too low version number can easily result excess log rereading */ -++ -++ n = (union jffs2_node_union *) o; -++ lr = n; -++ -++ do { -++ while (n < e && n->u.magic != JFFS2_MAGIC_BITMASK) -++ ((char *) n) += 4; -++ -++ if (n < e && n->u.magic == JFFS2_MAGIC_BITMASK) { -++ if (n->u.nodetype == JFFS2_NODETYPE_INODE && -++ n->i.ino == ino && (v = n->i.version) > vcur) { -++ /* XXX crc check */ -++ -++ if (vmaxt < v) -++ vmaxt = v; -++ if (vmint > v) { -++ vmint = v; -++ mp = n; -++ } -++ -++ if (v == (vcur + 1)) -++ return (&(n->i)); -++ } -++ -++ ((char *) n) += ((n->u.totlen + 3) & ~3); -++ } else -++ n = (union jffs2_node_union *) o; /* we're at the end, rewind to the beginning */ -++ -++ if (lr == n) { /* whole loop since last read */ -++ vmax = vmaxt; -++ vmin = vmint; -++ vmint = ~((uint32_t) 0); -++ -++ if (vcur < vmax && vcur < vmin) -++ return (&(mp->i)); -++ } -++ } while (vcur < vmax); -++ -++ return NULL; -++} -++ -++/* collects dir struct for selected inode */ -++ -++/* -++ o - filesystem image pointer -++ size - size of filesystem image -++ pino - inode of the specified directory -++ d - input directory structure -++ -++ return value: result directory structure, replaces d. -++ */ -++ -++struct dir *collectdir(char *o, size_t size, uint32_t ino, struct dir *d) -++{ -++ /* aligned! */ -++ union jffs2_node_union *n; -++ union jffs2_node_union *e = (union jffs2_node_union *) (o + size); -++ union jffs2_node_union *lr; /* last block position */ -++ union jffs2_node_union *mp = NULL; /* minimum position */ -++ -++ uint32_t vmin, vmint, vmaxt, vmax, vcur, v; -++ -++ vmin = 0; /* next to read */ -++ vmax = ~((uint32_t) 0); /* last to read */ -++ vmint = ~((uint32_t) 0); -++ vmaxt = 0; /* found maximum */ -++ vcur = 0; /* XXX what is smallest version number used? */ -++ /* too low version number can easily result excess log rereading */ -++ -++ n = (union jffs2_node_union *) o; -++ lr = n; -++ -++ do { -++ while (n < e && n->u.magic != JFFS2_MAGIC_BITMASK) -++ ((char *) n) += 4; -++ -++ if (n < e && n->u.magic == JFFS2_MAGIC_BITMASK) { -++ if (n->u.nodetype == JFFS2_NODETYPE_DIRENT && -++ n->d.pino == ino && (v = n->d.version) > vcur) { -++ /* XXX crc check */ -++ -++ if (vmaxt < v) -++ vmaxt = v; -++ if (vmint > v) { -++ vmint = v; -++ mp = n; -++ } -++ -++ if (v == (vcur + 1)) { -++ d = putdir(d, &(n->d)); -++ -++ lr = n; -++ vcur++; -++ vmint = ~((uint32_t) 0); -++ } -++ } -++ -++ ((char *) n) += ((n->u.totlen + 3) & ~3); -++ } else -++ n = (union jffs2_node_union *) o; /* we're at the end, rewind to the beginning */ -++ -++ if (lr == n) { /* whole loop since last read */ -++ vmax = vmaxt; -++ vmin = vmint; -++ vmint = ~((uint32_t) 0); -++ -++ if (vcur < vmax && vcur < vmin) { -++ d = putdir(d, &(mp->d)); -++ -++ lr = n = -++ (union jffs2_node_union *) (((char *) mp) + -++ ((mp->u.totlen + 3) & ~3)); -++ -++ vcur = vmin; -++ } -++ } -++ } while (vcur < vmax); -++ -++ return d; -++} -++ -++ -++ -++/* resolve dirent based on criteria */ -++ -++/* -++ o - filesystem image pointer -++ size - size of filesystem image -++ ino - if zero, ignore, -++ otherwise compare against dirent inode -++ pino - if zero, ingore, -++ otherwise compare against parent inode -++ and use name and nsize as extra criteria -++ name - name of wanted dirent, used if pino!=0 -++ nsize - length of name of wanted dirent, used if pino!=0 -++ -++ return value: pointer to relevant dirent structure in -++ filesystem image or NULL -++ */ -++ -++struct jffs2_raw_dirent *resolvedirent(char *o, size_t size, -++ uint32_t ino, uint32_t pino, -++ char *name, uint8_t nsize) -++{ -++ /* aligned! */ -++ union jffs2_node_union *n; -++ union jffs2_node_union *e = (union jffs2_node_union *) (o + size); -++ -++ struct jffs2_raw_dirent *dd = NULL; -++ -++ uint32_t vmax, v; -++ -++ if (!pino && ino <= 1) -++ return dd; -++ -++ vmax = 0; -++ -++ n = (union jffs2_node_union *) o; -++ -++ do { -++ while (n < e && n->u.magic != JFFS2_MAGIC_BITMASK) -++ ((char *) n) += 4; -++ -++ if (n < e && n->u.magic == JFFS2_MAGIC_BITMASK) { -++ if (n->u.nodetype == JFFS2_NODETYPE_DIRENT && -++ (!ino || n->d.ino == ino) && -++ (v = n->d.version) > vmax && -++ (!pino || (n->d.pino == pino && -++ nsize == n->d.nsize && -++ !memcmp(name, n->d.name, nsize)))) { -++ /* XXX crc check */ -++ -++ if (vmax < v) { -++ vmax = v; -++ dd = &(n->d); -++ } -++ } -++ -++ ((char *) n) += ((n->u.totlen + 3) & ~3); -++ } else -++ return dd; -++ } while (1); -++} -++ -++/* resolve name under certain parent inode to dirent */ -++ -++/* -++ o - filesystem image pointer -++ size - size of filesystem image -++ pino - requested parent inode -++ name - name of wanted dirent -++ nsize - length of name of wanted dirent -++ -++ return value: pointer to relevant dirent structure in -++ filesystem image or NULL -++ */ -++ -++struct jffs2_raw_dirent *resolvename(char *o, size_t size, uint32_t pino, -++ char *name, uint8_t nsize) -++{ -++ return resolvedirent(o, size, 0, pino, name, nsize); -++} -++ -++/* resolve inode to dirent */ -++ -++/* -++ o - filesystem image pointer -++ size - size of filesystem image -++ ino - compare against dirent inode -++ -++ return value: pointer to relevant dirent structure in -++ filesystem image or NULL -++ */ -++ -++struct jffs2_raw_dirent *resolveinode(char *o, size_t size, uint32_t ino) -++{ -++ return resolvedirent(o, size, ino, 0, NULL, 0); -++} -++ -++/* resolve slash-style path into dirent and inode. -++ slash as first byte marks absolute path (root=inode 1). -++ . and .. are resolved properly, and symlinks are followed. -++ */ -++ -++/* -++ o - filesystem image pointer -++ size - size of filesystem image -++ ino - root inode, used if path is relative -++ p - path to be resolved -++ inos - result inode, zero if failure -++ recc - recursion count, to detect symlink loops -++ -++ return value: pointer to dirent struct in file system image. -++ note that root directory doesn't have dirent struct -++ (return value is NULL), but it has inode (*inos=1) -++ */ -++ -++struct jffs2_raw_dirent *resolvepath0(char *o, size_t size, uint32_t ino, -++ char *p, uint32_t * inos, int recc) -++{ -++ struct jffs2_raw_dirent *dir = NULL; -++ -++ int d = 1; -++ uint32_t tino; -++ -++ char *next; -++ -++ char *path, *pp; -++ -++ char symbuf[1024]; -++ size_t symsize; -++ -++ if (recc > 16) { -++ /* probably symlink loop */ -++ *inos = 0; -++ return NULL; -++ } -++ -++ pp = path = strdup(p); -++ -++ if (*path == '/') { -++ path++; -++ ino = 1; -++ } -++ -++ if (ino > 1) { -++ dir = resolveinode(o, size, ino); -++ -++ ino = DIRENT_INO(dir); -++ } -++ -++ next = path - 1; -++ -++ while (ino && next != NULL && next[1] != 0 && d) { -++ path = next + 1; -++ next = strchr(path, '/'); -++ -++ if (next != NULL) -++ *next = 0; -++ -++ if (*path == '.' && path[1] == 0) -++ continue; -++ if (*path == '.' && path[1] == '.' && path[2] == 0) { -++ if (DIRENT_PINO(dir) == 1) { -++ ino = 1; -++ dir = NULL; -++ } else { -++ dir = resolveinode(o, size, DIRENT_PINO(dir)); -++ ino = DIRENT_INO(dir); -++ } -++ -++ continue; -++ } -++ -++ dir = resolvename(o, size, ino, path, (uint8_t) strlen(path)); -++ -++ if (DIRENT_INO(dir) == 0 || -++ (next != NULL && -++ !(dir->type == DT_DIR || dir->type == DT_LNK))) { -++ free(pp); -++ -++ *inos = 0; -++ -++ return NULL; -++ } -++ -++ if (dir->type == DT_LNK) { -++ struct jffs2_raw_inode *ri; -++ ri = find_raw_inode(o, size, DIRENT_INO(dir)); -++ putblock(symbuf, sizeof(symbuf), &symsize, ri); -++ symbuf[symsize] = 0; -++ -++ tino = ino; -++ ino = 0; -++ -++ dir = resolvepath0(o, size, tino, symbuf, &ino, ++recc); -++ -++ if (dir != NULL && next != NULL && -++ !(dir->type == DT_DIR || dir->type == DT_LNK)) { -++ free(pp); -++ -++ *inos = 0; -++ return NULL; -++ } -++ } -++ if (dir != NULL) -++ ino = DIRENT_INO(dir); -++ } -++ -++ free(pp); -++ -++ *inos = ino; -++ -++ return dir; -++} -++ -++/* resolve slash-style path into dirent and inode. -++ slash as first byte marks absolute path (root=inode 1). -++ . and .. are resolved properly, and symlinks are followed. -++ */ -++ -++/* -++ o - filesystem image pointer -++ size - size of filesystem image -++ ino - root inode, used if path is relative -++ p - path to be resolved -++ inos - result inode, zero if failure -++ -++ return value: pointer to dirent struct in file system image. -++ note that root directory doesn't have dirent struct -++ (return value is NULL), but it has inode (*inos=1) -++ */ -++ -++struct jffs2_raw_dirent *resolvepath(char *o, size_t size, uint32_t ino, -++ char *p, uint32_t * inos) -++{ -++ return resolvepath0(o, size, ino, p, inos, 0); -++} -++ -++/* lists files on directory specified by path */ -++ -++/* -++ o - filesystem image pointer -++ size - size of filesystem image -++ p - path to be resolved -++ */ -++ -++void lsdir(char *o, size_t size, char *path, int recurse) -++{ -++ struct jffs2_raw_dirent *dd; -++ struct dir *d = NULL; -++ -++ uint32_t ino; -++ -++ dd = resolvepath(o, size, 1, path, &ino); -++ -++ if (ino == 0 || -++ (dd == NULL && ino == 0) || (dd != NULL && dd->type != DT_DIR)) { -++ fprintf(stderr, "jffs2reader: %s: No such file or directory\n", -++ path); -++ exit(EXIT_FAILURE); -++ } -++ -++ d = collectdir(o, size, ino, d); -++ printdir(o, size, d, path, recurse); -++ freedir(d); -++} -++ -++/* writes file specified by path to the buffer */ -++ -++/* -++ o - filesystem image pointer -++ size - size of filesystem image -++ p - path to be resolved -++ b - file buffer -++ bsize - file buffer size -++ rsize - file result size -++ */ -++ -++void catfile(char *o, size_t size, char *path, char *b, size_t bsize, -++ size_t * rsize) -++{ -++ struct jffs2_raw_dirent *dd; -++ struct jffs2_raw_inode *ri; -++ uint32_t ino; -++ -++ dd = resolvepath(o, size, 1, path, &ino); -++ -++ if (ino == 0) { -++ fprintf(stderr, "%s: No such file or directory\n", path); -++ exit(EXIT_FAILURE); -++ } -++ -++ if (dd == NULL || dd->type != DT_REG) { -++ fprintf(stderr, "%s: Not a regular file\n", path); -++ exit(EXIT_FAILURE); -++ } -++ -++ ri = find_raw_inode(o, size, ino); -++ putblock(b, bsize, rsize, ri); -++ -++ write(1, b, *rsize); -++} -++ -++/* usage example */ -++ -++int main(int argc, char **argv) -++{ -++ int fd, opt, recurse = 0; -++ struct stat st; -++ -++ char *scratch, *dir = NULL, *file = NULL; -++ size_t ssize = 0; -++ -++ char *buf; -++ -++ while ((opt = getopt(argc, argv, "rd:f:")) > 0) { -++ switch (opt) { -++ case 'd': -++ dir = optarg; -++ break; -++ case 'f': -++ file = optarg; -++ break; -++ case 'r': -++ recurse++; -++ break; -++ default: -++ fprintf(stderr, -++ "Usage: jffs2reader [-d|-f] < path > \n"); -++ exit(EXIT_FAILURE); -++ } -++ } -++ -++ fd = open(argv[optind], O_RDONLY); -++ if (fd == -1) { -++ fprintf(stderr, "%s: %s\n", argv[optind], strerror(errno)); -++ exit(2); -++ } -++ -++ if (fstat(fd, &st)) { -++ fprintf(stderr, "%s: %s\n", argv[optind], strerror(errno)); -++ exit(3); -++ } -++ -++ buf = malloc((size_t) st.st_size); -++ if (buf == NULL) { -++ fprintf(stderr, "%s: memory exhausted\n", argv[optind]); -++ exit(4); -++ } -++ -++ if (read(fd, buf, st.st_size) != (ssize_t) st.st_size) { -++ fprintf(stderr, "%s: %s\n", argv[optind], strerror(errno)); -++ exit(5); -++ } -++ -++ if (dir) -++ lsdir(buf, st.st_size, dir, recurse); -++ -++ if (file) { -++ scratch = malloc(SCRATCH_SIZE); -++ if (scratch == NULL) { -++ fprintf(stderr, "%s: memory exhausted\n", argv[optind]); -++ exit(6); -++ } -++ -++ catfile(buf, st.st_size, file, scratch, SCRATCH_SIZE, &ssize); -++ free(scratch); -++ } -++ -++ if (!dir && !file) -++ lsdir(buf, st.st_size, "/", 1); -++ -++ -++ free(buf); -++ exit(EXIT_SUCCESS); -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/load_nandsim.sh linux-2.6.24.7/drivers/mtd/mtd-utils/load_nandsim.sh -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/load_nandsim.sh 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/load_nandsim.sh 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,123 @@ -++#!/bin/bash -++ -++# -++# This script inserts NAND simulator module to emulate NAND flash of specified -++# size. -++# -++# Author: Artem Bityutskiy -++# -++ -++# Check if nandsim module is loaded -++function nandsim_loaded() -++{ -++ local NANDSIM=`lsmod | grep nandsim` -++ if [ -n "$NANDSIM" ]; then -++ return 1 -++ fi -++ return 0 -++} -++ -++nandsim_loaded -++if (( $? != 0 )); then -++ echo "Error: nandsim is already loaded" -++ exit 1 -++fi -++ -++if (( $# < 1 )); then -++ echo "Load NAND simulator to simulate flash of a specified size." -++ echo "" -++ echo "Usage: ./load_nandsim.sh " -++ echo " " -++ echo "" -++ echo "Only the first parameter is mandatory. Default eraseblock size" -++ echo "is 16KiB, default NAND page size is 512 bytes." -++ echo "" -++ echo "Only the following combinations are supported:" -++ echo "--------------------------------------------------" -++ echo "| size (MiB) | EB size (KiB) | Page size (bytes) |" -++ echo "--------------------------------------------------" -++ echo "| 16 | 16 | 512 |" -++ echo "| 32 | 16 | 512 |" -++ echo "| 64 | 16 | 512 |" -++ echo "| 128 | 16 | 512 |" -++ echo "| 256 | 16 | 512 |" -++ echo "| 64 | 64 | 2048 |" -++ echo "| 64 | 128 | 2048 |" -++ echo "| 64 | 256 | 2048 |" -++ echo "| 64 | 512 | 2048 |" -++ echo "| 128 | 64 | 2048 |" -++ echo "| 128 | 128 | 2048 |" -++ echo "| 128 | 256 | 2048 |" -++ echo "| 128 | 512 | 2048 |" -++ echo "| 256 | 64 | 2048 |" -++ echo "| 256 | 128 | 2048 |" -++ echo "| 256 | 256 | 2048 |" -++ echo "| 256 | 512 | 2048 |" -++ echo "| 512 | 64 | 2048 |" -++ echo "| 512 | 128 | 2048 |" -++ echo "| 512 | 256 | 2048 |" -++ echo "| 512 | 512 | 2048 |" -++ echo "| 1024 | 64 | 2048 |" -++ echo "| 1024 | 128 | 2048 |" -++ echo "| 1024 | 256 | 2048 |" -++ echo "| 1024 | 512 | 2048 |" -++ echo "--------------------------------------------------" -++ exit 1 -++fi -++ -++SZ=$1 -++EBSZ=$2 -++PGSZ=$3 -++if [[ $# == '1' ]]; then -++ EBSZ=16 -++ PGSZ=512 -++elif [[ $# == '2' ]]; then -++ PGSZ=512 -++fi -++ -++if (( $PGSZ == 512 && $EBSZ != 16 )); then -++ echo "Error: only 16KiB eraseblocks are possible in case of 512 bytes page" -++ exit 1 -++fi -++ -++if (( $PGSZ == 512 )); then -++ case $SZ in -++ 16) modprobe nandsim first_id_byte=0x20 second_id_byte=0x33 ;; -++ 32) modprobe nandsim first_id_byte=0x20 second_id_byte=0x35 ;; -++ 64) modprobe nandsim first_id_byte=0x20 second_id_byte=0x36 ;; -++ 128) modprobe nandsim first_id_byte=0x20 second_id_byte=0x78 ;; -++ 256) modprobe nandsim first_id_byte=0x20 second_id_byte=0x71 ;; -++ *) echo "Flash size ${SZ}MiB is not supported, try 16, 32, 64 or 256" -++ exit 1 ;; -++ esac -++elif (( $PGSZ == 2048 )); then -++ case $EBSZ in -++ 64) FOURTH=0x05 ;; -++ 128) FOURTH=0x15 ;; -++ 256) FOURTH=0x25 ;; -++ 512) FOURTH=0x35 ;; -++ *) echo "Eraseblock ${EBSZ}KiB is not supported" -++ exit 1 -++ esac -++ -++ case $SZ in -++ 64) modprobe nandsim first_id_byte=0x20 second_id_byte=0xa2 third_id_byte=0x00 fourth_id_byte=$FOURTH ;; -++ 128) modprobe nandsim first_id_byte=0xec second_id_byte=0xa1 third_id_byte=0x00 fourth_id_byte=$FOURTH ;; -++ 256) modprobe nandsim first_id_byte=0x20 second_id_byte=0xaa third_id_byte=0x00 fourth_id_byte=$FOURTH ;; -++ 512) modprobe nandsim first_id_byte=0x20 second_id_byte=0xac third_id_byte=0x00 fourth_id_byte=$FOURTH ;; -++ 1024) modprobe nandsim first_id_byte=0xec second_id_byte=0xd3 third_id_byte=0x51 fourth_id_byte=$FOURTH ;; -++ *) echo "Unable to emulate ${SZ}MiB flash with ${EBSZ}KiB eraseblock" -++ exit 1 -++ esac -++else -++ echo "Error: bad NAND page size ${PGSZ}KiB, it has to be either 512 or 2048" -++ exit 1 -++fi -++ -++if (( $? != 0 )); then -++ echo "Error: cannot load nandsim" -++ exit 1 -++fi -++ -++echo "Loaded NAND simulator (${SZ}MiB, ${EBSZ}KiB eraseblock, $PGSZ bytes NAND page)" -++exit 0 -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/mcast_image.h linux-2.6.24.7/drivers/mtd/mtd-utils/mcast_image.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/mcast_image.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/mcast_image.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,54 @@ -++#include -++ -++#define PKT_SIZE 2820 -++ -++struct image_pkt_hdr { -++ uint32_t resend; -++ uint32_t totcrc; -++ uint32_t nr_blocks; -++ uint32_t blocksize; -++ uint32_t block_crc; -++ uint32_t block_nr; -++ uint32_t pkt_sequence; -++ uint16_t pkt_nr; -++ uint16_t nr_pkts; -++ uint32_t thislen; -++ uint32_t thiscrc; -++}; -++ -++struct image_pkt { -++ struct image_pkt_hdr hdr; -++ unsigned char data[PKT_SIZE]; -++}; -++ -++struct fec_parms; -++ -++/* k - number of actual data packets -++ * n - total number of packets including data and redundant packets -++ * (actual packet size isn't relevant here) */ -++struct fec_parms *fec_new(int k, int n); -++void fec_free(struct fec_parms *p); -++ -++/* src - array of (n) pointers to data packets -++ * fec - buffer for packet to be generated -++ * index - index of packet to be generated (0 <= index < n) -++ * sz - data packet size -++ * -++ * _linear version just takes a pointer to the raw data; no -++ * mucking about with packet pointers. -++ */ -++void fec_encode(struct fec_parms *code, unsigned char *src[], -++ unsigned char *fec, int index, int sz); -++void fec_encode_linear(struct fec_parms *code, unsigned char *src, -++ unsigned char *fec, int index, int sz); -++ -++/* data - array of (k) pointers to data packets, in arbitrary order (see i) -++ * i - indices of (data) packets -++ * sz - data packet size -++ * -++ * Will never fail as long as you give it (k) individual data packets. -++ * Will re-order the (data) pointers but not the indices -- data packets -++ * are ordered on return. -++ */ -++int fec_decode(struct fec_parms *code, unsigned char *data[], -++ int i[], int sz); -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/mkfs.jffs2.1 linux-2.6.24.7/drivers/mtd/mtd-utils/mkfs.jffs2.1 -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/mkfs.jffs2.1 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/mkfs.jffs2.1 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,259 @@ -++.TH MKFS.JFFS2 1 -++.SH NAME -++mkfs.jffs2 \- Create a JFFS2 file system image from directory -++.SH SYNOPSIS -++.B mkfs.jffs2 -++[ -++.B -p,--pad[=SIZE] -++] -++[ -++.B -r,-d,--root -++.I directory -++] -++[ -++.B -s,--pagesize=SIZE -++] -++[ -++.B -e,--eraseblock=SIZE -++] -++[ -++.B -c,--cleanmarker=SIZE -++] -++[ -++.B -n,--no-cleanmarkers -++] -++[ -++.B -o,--output -++.I image.jffs2 -++] -++[ -++.B -l,--little-endian -++] -++[ -++.B -b,--big-endian -++] -++[ -++.B -D,--devtable=FILE -++] -++[ -++.B -f,--faketime -++] -++[ -++.B -q,--squash -++] -++[ -++.B -U,--squash-uids -++] -++[ -++.B -P,--squash-perms -++] -++[ -++.B --with-xattr -++] -++[ -++.B --with-selinux -++] -++[ -++.B --with-posix-acl -++] -++[ -++.B -m,--compression-mode=MODE -++] -++[ -++.B -x,--disable-compressor=NAME -++] -++[ -++.B -X,--enable-compressor=NAME -++] -++[ -++.B -y,--compressor-priority=PRIORITY:NAME -++] -++[ -++.B -L,--list-compressors -++] -++[ -++.B -t,--test-compression -++] -++[ -++.B -h,--help -++] -++[ -++.B -v,--verbose -++] -++[ -++.B -V,--version -++] -++[ -++.B -i,--incremental -++.I image.jffs2 -++] -++ -++.SH DESCRIPTION -++The program -++.B mkfs.jffs2 -++creates a JFFS2 (Second Journalling Flash File System) file system -++image and writes the resulting image to the file specified by the -++.B -o -++option or by default to the standard output, unless the standard -++output is a terminal device in which case mkfs.jffs2 will abort. -++ -++The file system image is created using the files and directories -++contained in the directory specified by the option -++.B -r -++or the present directory, if the -++.B -r -++option is not specified. -++ -++Each block of the files to be placed into the file system image -++are compressed using one of the avaiable compressors depending -++on the selected compression mode. -++ -++File systems are created with the same endianness as the host, -++unless the -++.B -b -++or -++.B -l -++options are specified. JFFS2 driver in the 2.4 Linux kernel only -++supported images having the same endianness as the CPU. As of 2.5.48, -++the kernel can be changed with a #define to accept images of the -++non-native endianness. Full bi-endian support in the kernel is not -++planned. -++ -++It is unlikely that JFFS2 images are useful except in conjuction -++with the MTD (Memory Technology Device) drivers in the Linux -++kernel, since the JFFS2 file system driver in the kernel requires -++MTD devices. -++.SH OPTIONS -++Options that take SIZE arguments can be specified as either -++decimal (e.g., 65536), octal (0200000), or hexidecimal (0x1000). -++.TP -++.B -p, --pad[=SIZE] -++Pad output to SIZE bytes with 0xFF. If SIZE is not specified, -++the output is padded to the end of the final erase block. -++.TP -++.B -r, -d, --root=DIR -++Build file system from directory DIR. The default is the current -++directory. -++.TP -++.B -s, --pagesize=SIZE -++Use page size SIZE. The default is 4 KiB. This size is the -++maximum size of a data node. -++.TP -++.B -e, --eraseblock=SIZE -++Use erase block size SIZE. The default is 64 KiB. If you use a erase -++block size different than the erase block size of the target MTD -++device, JFFS2 may not perform optimally. If the SIZE specified is -++below 4096, the units are assumed to be KiB. -++.TP -++.B -c, --cleanmarker=SIZE -++Write \'CLEANMARKER\' nodes with the size specified. It is not -++normally appropriate to specify a size other than the default 12 -++bytes. -++.TP -++.B -n, --no-cleanmarkers -++Do not write \'CLEANMARKER\' nodes to the beginning of each erase -++block. This option can be useful for creating JFFS2 images for -++use on NAND flash, and for creating images which are to be used -++on a variety of hardware with differing eraseblock sizes. -++.TP -++.B -o, --output=FILE -++Write JFFS2 image to file FILE. Default is the standard output. -++.TP -++.B -l, --little-endian -++Create a little-endian JFFS2 image. Default is to make an image -++with the same endianness as the host. -++.TP -++.B -b, --big-endian -++Create a big-endian JFFS2 image. Default is to make an image -++with the same endianness as the host. -++.TP -++.B -D, --devtable=FILE -++Use the named FILE as a device table file, for including devices and -++changing permissions in the created image when the user does not have -++appropriate permissions to create them on the file system used as -++source. -++.TP -++.B -f, --faketime -++Change all file timestamps to \'0\' for regression testing. -++.TP -++.B -q, --squash -++Squash permissions and owners, making all files be owned by root and -++removing write permission for \'group\' and \'other\'. -++.TP -++.B -U, --squash-uids -++Squash owners making all files be owned by root. -++.TP -++.B -P, --squash-perms -++Squash permissions, removing write permission for \'group\' and \'other\'. -++.TP -++.B --with-xattr -++Enables xattr, stuff all xattr entries into jffs2 image file. -++.TP -++.B --with-selinux -++Enables xattr, stuff only SELinux Labels into jffs2 image file. -++.TP -++.B --with-posix-acl -++Enable xattr, stuff only POSIX ACL entries into jffs2 image file. -++.TP -++.B -m, --compression-mode=MODE -++Set the default compression mode. The default mode is -++.B priority -++which tries the compressors in a predefinied order and chooses the first -++successful one. The alternatives are: -++.B none -++(mkfs will not compress) and -++.B size -++(mkfs will try all compressor and chooses the one which have the smallest result). -++.TP -++.B -x, --disable-compressor=NAME -++Disable a compressor. Use -++.B -L -++to see the list of the avaiable compressors and their default states. -++.TP -++.B -X, --enable-compressor=NAME -++Enable a compressor. Use -++.B -L -++to see the list of the avaiable compressors and their default states. -++.TP -++.B -y, --compressor-priority=PRIORITY:NAME -++Set the priority of a compressor. Use -++.B -L -++to see the list of the avaiable compressors and their default priority. -++Priorities are used by priority compression mode. -++.TP -++.B -L, --list-compressors -++Show the list of the avaiable compressors and their states. -++.TP -++.B -t, --test-compression -++Call decompress after every compress - and compare the result with the original data -, and -++some other check. -++.TP -++.B -h, --help -++Display help text. -++.TP -++.B -v, --verbose -++Verbose operation. -++.TP -++.B -V, --version -++Display version information. -++.TP -++.B -i, --incremental=FILE -++Generate an appendage image for FILE. If FILE is written to flash and flash -++is appended with the output, then it seems as if it was one thing. -++ -++.SH BUGS -++JFFS2 limits device major and minor numbers to 8 bits each. Some -++consider this a bug. -++ -++.B mkfs.jffs2 -++does not properly handle hard links in the input directory structure. -++Currently, hard linked files will be expanded to multiple identical -++files in the output image. -++.SH AUTHORS -++David Woodhouse -++.br -++Manual page written by David Schleef -++.SH SEE ALSO -++.BR mkfs (8), -++.BR mkfs.jffs (1), -++.BR fakeroot (1) -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/mkfs.jffs2.c linux-2.6.24.7/drivers/mtd/mtd-utils/mkfs.jffs2.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/mkfs.jffs2.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/mkfs.jffs2.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1902 @@ -++/* vi: set sw=4 ts=4: */ -++/* -++ * Build a JFFS2 image in a file, from a given directory tree. -++ * -++ * Copyright 2001, 2002 Red Hat, Inc. -++ * 2001 David A. Schleef -++ * 2002 Axis Communications AB -++ * 2001, 2002 Erik Andersen -++ * 2004 University of Szeged, Hungary -++ * 2006 KaiGai Kohei -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ * GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ * -++ * Cross-endian support added by David Schleef . -++ * -++ * Major architectural rewrite by Erik Andersen -++ * to allow support for making hard links (though hard links support is -++ * not yet implemented), and for munging file permissions and ownership -++ * on the fly using --faketime, --squash, --devtable. And I plugged a -++ * few memory leaks, adjusted the error handling and fixed some little -++ * nits here and there. -++ * -++ * I also added a sample device table file. See device_table.txt -++ * -Erik, September 2001 -++ * -++ * Cleanmarkers support added by Axis Communications AB -++ * -++ * Rewritten again. Cleanly separated host and target filsystem -++ * activities (mainly so I can reuse all the host handling stuff as I -++ * rewrite other mkfs utils). Added a verbose option to list types -++ * and attributes as files are added to the file system. Major cleanup -++ * and scrubbing of the code so it can be read, understood, and -++ * modified by mere mortals. -++ * -++ * -Erik, November 2002 -++ */ -++ -++#define _GNU_SOURCE -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#ifndef WITHOUT_XATTR -++#include -++#include -++#endif -++#include -++#define crc32 __complete_crap -++#include -++#undef crc32 -++#include "crc32.h" -++#include "rbtree.h" -++ -++/* Do not use the weird XPG version of basename */ -++#undef basename -++ -++//#define DMALLOC -++//#define mkfs_debug_msg error_msg -++#define mkfs_debug_msg(a...) { } -++#define min(x,y) ({ typeof((x)) _x = (x); typeof((y)) _y = (y); (_x>_y)?_y:_x; }) -++ -++#define PAD(x) (((x)+3)&~3) -++ -++struct filesystem_entry { -++ char *name; /* Name of this directory (think basename) */ -++ char *path; /* Path of this directory (think dirname) */ -++ char *fullname; /* Full name of this directory (i.e. path+name) */ -++ char *hostname; /* Full path to this file on the host filesystem */ -++ uint32_t ino; /* Inode number of this file in JFFS2 */ -++ struct stat sb; /* Stores directory permissions and whatnot */ -++ char *link; /* Target a symlink points to. */ -++ struct filesystem_entry *parent; /* Parent directory */ -++ struct filesystem_entry *prev; /* Only relevant to non-directories */ -++ struct filesystem_entry *next; /* Only relevant to non-directories */ -++ struct filesystem_entry *files; /* Only relevant to directories */ -++ struct rb_node hardlink_rb; -++}; -++ -++struct rb_root hardlinks; -++static int out_fd = -1; -++static int in_fd = -1; -++static char default_rootdir[] = "."; -++static char *rootdir = default_rootdir; -++static int verbose = 0; -++static int squash_uids = 0; -++static int squash_perms = 0; -++static int fake_times = 0; -++int target_endian = __BYTE_ORDER; -++static const char *const app_name = "mkfs.jffs2"; -++static const char *const memory_exhausted = "memory exhausted"; -++ -++uint32_t find_hardlink(struct filesystem_entry *e) -++{ -++ struct filesystem_entry *f; -++ struct rb_node **n = &hardlinks.rb_node; -++ struct rb_node *parent = NULL; -++ -++ while (*n) { -++ parent = *n; -++ f = rb_entry(parent, struct filesystem_entry, hardlink_rb); -++ -++ if ((f->sb.st_dev < e->sb.st_dev) || -++ (f->sb.st_dev == e->sb.st_dev && -++ f->sb.st_ino < e->sb.st_ino)) -++ n = &parent->rb_left; -++ else if ((f->sb.st_dev > e->sb.st_dev) || -++ (f->sb.st_dev == e->sb.st_dev && -++ f->sb.st_ino > e->sb.st_ino)) { -++ n = &parent->rb_right; -++ } else -++ return f->ino; -++ } -++ -++ rb_link_node(&e->hardlink_rb, parent, n); -++ rb_insert_color(&e->hardlink_rb, &hardlinks); -++ return 0; -++} -++ -++static void verror_msg(const char *s, va_list p) -++{ -++ fflush(stdout); -++ fprintf(stderr, "%s: ", app_name); -++ vfprintf(stderr, s, p); -++} -++static void error_msg(const char *s, ...) -++{ -++ va_list p; -++ -++ va_start(p, s); -++ verror_msg(s, p); -++ va_end(p); -++ putc('\n', stderr); -++} -++ -++static void error_msg_and_die(const char *s, ...) -++{ -++ va_list p; -++ -++ va_start(p, s); -++ verror_msg(s, p); -++ va_end(p); -++ putc('\n', stderr); -++ exit(EXIT_FAILURE); -++} -++ -++static void vperror_msg(const char *s, va_list p) -++{ -++ int err = errno; -++ -++ if (s == 0) -++ s = ""; -++ verror_msg(s, p); -++ if (*s) -++ s = ": "; -++ fprintf(stderr, "%s%s\n", s, strerror(err)); -++} -++ -++static void perror_msg(const char *s, ...) -++{ -++ va_list p; -++ -++ va_start(p, s); -++ vperror_msg(s, p); -++ va_end(p); -++} -++ -++static void perror_msg_and_die(const char *s, ...) -++{ -++ va_list p; -++ -++ va_start(p, s); -++ vperror_msg(s, p); -++ va_end(p); -++ exit(EXIT_FAILURE); -++} -++ -++#ifndef DMALLOC -++extern void *xmalloc(size_t size) -++{ -++ void *ptr = malloc(size); -++ -++ if (ptr == NULL && size != 0) -++ error_msg_and_die(memory_exhausted); -++ return ptr; -++} -++ -++extern void *xcalloc(size_t nmemb, size_t size) -++{ -++ void *ptr = calloc(nmemb, size); -++ -++ if (ptr == NULL && nmemb != 0 && size != 0) -++ error_msg_and_die(memory_exhausted); -++ return ptr; -++} -++ -++extern void *xrealloc(void *ptr, size_t size) -++{ -++ ptr = realloc(ptr, size); -++ if (ptr == NULL && size != 0) -++ error_msg_and_die(memory_exhausted); -++ return ptr; -++} -++ -++extern char *xstrdup(const char *s) -++{ -++ char *t; -++ -++ if (s == NULL) -++ return NULL; -++ t = strdup(s); -++ if (t == NULL) -++ error_msg_and_die(memory_exhausted); -++ return t; -++} -++#endif -++ -++extern char *xreadlink(const char *path) -++{ -++ static const int GROWBY = 80; /* how large we will grow strings by */ -++ -++ char *buf = NULL; -++ int bufsize = 0, readsize = 0; -++ -++ do { -++ buf = xrealloc(buf, bufsize += GROWBY); -++ readsize = readlink(path, buf, bufsize); /* 1st try */ -++ if (readsize == -1) { -++ perror_msg("%s:%s", app_name, path); -++ return NULL; -++ } -++ } -++ while (bufsize < readsize + 1); -++ -++ buf[readsize] = '\0'; -++ -++ return buf; -++} -++static FILE *xfopen(const char *path, const char *mode) -++{ -++ FILE *fp; -++ if ((fp = fopen(path, mode)) == NULL) -++ perror_msg_and_die("%s", path); -++ return fp; -++} -++ -++static struct filesystem_entry *find_filesystem_entry( -++ struct filesystem_entry *dir, char *fullname, uint32_t type) -++{ -++ struct filesystem_entry *e = dir; -++ -++ if (S_ISDIR(dir->sb.st_mode)) { -++ e = dir->files; -++ } -++ while (e) { -++ /* Only bother to do the expensive strcmp on matching file types */ -++ if (type == (e->sb.st_mode & S_IFMT)) { -++ if (S_ISDIR(e->sb.st_mode)) { -++ int len = strlen(e->fullname); -++ -++ /* Check if we are a parent of the correct path */ -++ if (strncmp(e->fullname, fullname, len) == 0) { -++ /* Is this an _exact_ match? */ -++ if (strcmp(fullname, e->fullname) == 0) { -++ return (e); -++ } -++ /* Looks like we found a parent of the correct path */ -++ if (fullname[len] == '/') { -++ if (e->files) { -++ return (find_filesystem_entry (e, fullname, type)); -++ } else { -++ return NULL; -++ } -++ } -++ } -++ } else { -++ if (strcmp(fullname, e->fullname) == 0) { -++ return (e); -++ } -++ } -++ } -++ e = e->next; -++ } -++ return (NULL); -++} -++ -++static struct filesystem_entry *add_host_filesystem_entry( -++ char *name, char *path, unsigned long uid, unsigned long gid, -++ unsigned long mode, dev_t rdev, struct filesystem_entry *parent) -++{ -++ int status; -++ char *tmp; -++ struct stat sb; -++ time_t timestamp = time(NULL); -++ struct filesystem_entry *entry; -++ -++ memset(&sb, 0, sizeof(struct stat)); -++ status = lstat(path, &sb); -++ -++ if (status >= 0) { -++ /* It is ok for some types of files to not exit on disk (such as -++ * device nodes), but if they _do_ exist the specified mode had -++ * better match the actual file or strange things will happen.... */ -++ if ((mode & S_IFMT) != (sb.st_mode & S_IFMT)) { -++ error_msg_and_die ("%s: file type does not match specified type!", path); -++ } -++ timestamp = sb.st_mtime; -++ } else { -++ /* If this is a regular file, it _must_ exist on disk */ -++ if ((mode & S_IFMT) == S_IFREG) { -++ error_msg_and_die("%s: does not exist!", path); -++ } -++ } -++ -++ /* Squash all permissions so files are owned by root, all -++ * timestamps are _right now_, and file permissions -++ * have group and other write removed */ -++ if (squash_uids) { -++ uid = gid = 0; -++ } -++ if (squash_perms) { -++ if (!S_ISLNK(mode)) { -++ mode &= ~(S_IWGRP | S_IWOTH); -++ mode &= ~(S_ISUID | S_ISGID); -++ } -++ } -++ if (fake_times) { -++ timestamp = 0; -++ } -++ -++ entry = xcalloc(1, sizeof(struct filesystem_entry)); -++ -++ entry->hostname = xstrdup(path); -++ entry->fullname = xstrdup(name); -++ tmp = xstrdup(name); -++ entry->name = xstrdup(basename(tmp)); -++ free(tmp); -++ tmp = xstrdup(name); -++ entry->path = xstrdup(dirname(tmp)); -++ free(tmp); -++ -++ entry->sb.st_ino = sb.st_ino; -++ entry->sb.st_dev = sb.st_dev; -++ entry->sb.st_nlink = sb.st_nlink; -++ -++ entry->sb.st_uid = uid; -++ entry->sb.st_gid = gid; -++ entry->sb.st_mode = mode; -++ entry->sb.st_rdev = rdev; -++ entry->sb.st_atime = entry->sb.st_ctime = -++ entry->sb.st_mtime = timestamp; -++ if (S_ISREG(mode)) { -++ entry->sb.st_size = sb.st_size; -++ } -++ if (S_ISLNK(mode)) { -++ entry->link = xreadlink(path); -++ entry->sb.st_size = strlen(entry->link); -++ } -++ -++ /* This happens only for root */ -++ if (!parent) -++ return (entry); -++ -++ /* Hook the file into the parent directory */ -++ entry->parent = parent; -++ if (!parent->files) { -++ parent->files = entry; -++ } else { -++ struct filesystem_entry *prev; -++ for (prev = parent->files; prev->next; prev = prev->next); -++ prev->next = entry; -++ entry->prev = prev; -++ } -++ -++ return (entry); -++} -++ -++static struct filesystem_entry *recursive_add_host_directory( -++ struct filesystem_entry *parent, char *targetpath, char *hostpath) -++{ -++ int i, n; -++ struct stat sb; -++ char *hpath, *tpath; -++ struct dirent *dp, **namelist; -++ struct filesystem_entry *entry; -++ -++ -++ if (lstat(hostpath, &sb)) { -++ perror_msg_and_die("%s", hostpath); -++ } -++ -++ entry = add_host_filesystem_entry(targetpath, hostpath, -++ sb.st_uid, sb.st_gid, sb.st_mode, 0, parent); -++ -++ n = scandir(hostpath, &namelist, 0, alphasort); -++ if (n < 0) { -++ perror_msg_and_die("opening directory %s", hostpath); -++ } -++ -++ for (i=0; id_name[0] == '.' && (dp->d_name[1] == 0 || -++ (dp->d_name[1] == '.' && dp->d_name[2] == 0))) -++ { -++ free(dp); -++ continue; -++ } -++ -++ asprintf(&hpath, "%s/%s", hostpath, dp->d_name); -++ if (lstat(hpath, &sb)) { -++ perror_msg_and_die("%s", hpath); -++ } -++ if (strcmp(targetpath, "/") == 0) { -++ asprintf(&tpath, "%s%s", targetpath, dp->d_name); -++ } else { -++ asprintf(&tpath, "%s/%s", targetpath, dp->d_name); -++ } -++ -++ switch (sb.st_mode & S_IFMT) { -++ case S_IFDIR: -++ recursive_add_host_directory(entry, tpath, hpath); -++ break; -++ -++ case S_IFREG: -++ case S_IFSOCK: -++ case S_IFIFO: -++ case S_IFLNK: -++ case S_IFCHR: -++ case S_IFBLK: -++ add_host_filesystem_entry(tpath, hpath, sb.st_uid, -++ sb.st_gid, sb.st_mode, sb.st_rdev, entry); -++ break; -++ -++ default: -++ error_msg("Unknown file type %o for %s", sb.st_mode, hpath); -++ break; -++ } -++ free(dp); -++ free(hpath); -++ free(tpath); -++ } -++ free(namelist); -++ return (entry); -++} -++ -++/* the GNU C library has a wonderful scanf("%as", string) which will -++ allocate the string with the right size, good to avoid buffer overruns. -++ the following macros use it if available or use a hacky workaround... -++ */ -++ -++#ifdef __GNUC__ -++#define SCANF_PREFIX "a" -++#define SCANF_STRING(s) (&s) -++#define GETCWD_SIZE 0 -++#else -++#define SCANF_PREFIX "511" -++#define SCANF_STRING(s) (s = malloc(512)) -++#define GETCWD_SIZE -1 -++inline int snprintf(char *str, size_t n, const char *fmt, ...) -++{ -++ int ret; -++ va_list ap; -++ -++ va_start(ap, fmt); -++ ret = vsprintf(str, fmt, ap); -++ va_end(ap); -++ return ret; -++} -++#endif -++ -++/* device table entries take the form of: -++ -++ /dev/mem c 640 0 0 1 1 0 0 - -++ -++ type can be one of: -++ f A regular file -++ d Directory -++ c Character special device file -++ b Block special device file -++ p Fifo (named pipe) -++ -++ I don't bother with symlinks (permissions are irrelevant), hard -++ links (special cases of regular files), or sockets (why bother). -++ -++ Regular files must exist in the target root directory. If a char, -++ block, fifo, or directory does not exist, it will be created. -++ */ -++static int interpret_table_entry(struct filesystem_entry *root, char *line) -++{ -++ char *hostpath; -++ char type, *name = NULL, *tmp, *dir; -++ unsigned long mode = 0755, uid = 0, gid = 0, major = 0, minor = 0; -++ unsigned long start = 0, increment = 1, count = 0; -++ struct filesystem_entry *parent, *entry; -++ -++ if (sscanf (line, "%" SCANF_PREFIX "s %c %lo %lu %lu %lu %lu %lu %lu %lu", -++ SCANF_STRING(name), &type, &mode, &uid, &gid, &major, &minor, -++ &start, &increment, &count) < 0) -++ { -++ return 1; -++ } -++ -++ if (!strcmp(name, "/")) { -++ error_msg_and_die("Device table entries require absolute paths"); -++ } -++ -++ asprintf(&hostpath, "%s%s", rootdir, name); -++ -++ /* Check if this file already exists... */ -++ switch (type) { -++ case 'd': -++ mode |= S_IFDIR; -++ break; -++ case 'f': -++ mode |= S_IFREG; -++ break; -++ case 'p': -++ mode |= S_IFIFO; -++ break; -++ case 'c': -++ mode |= S_IFCHR; -++ break; -++ case 'b': -++ mode |= S_IFBLK; -++ break; -++ default: -++ error_msg_and_die("Unsupported file type"); -++ } -++ entry = find_filesystem_entry(root, name, mode); -++ if (entry) { -++ /* Ok, we just need to fixup the existing entry -++ * and we will be all done... */ -++ entry->sb.st_uid = uid; -++ entry->sb.st_gid = gid; -++ entry->sb.st_mode = mode; -++ if (major && minor) { -++ entry->sb.st_rdev = makedev(major, minor); -++ } -++ } else { -++ /* If parent is NULL (happens with device table entries), -++ * try and find our parent now) */ -++ tmp = strdup(name); -++ dir = dirname(tmp); -++ parent = find_filesystem_entry(root, dir, S_IFDIR); -++ free(tmp); -++ if (parent == NULL) { -++ error_msg ("skipping device_table entry '%s': no parent directory!", name); -++ free(name); -++ free(hostpath); -++ return 1; -++ } -++ -++ switch (type) { -++ case 'd': -++ add_host_filesystem_entry(name, hostpath, uid, gid, mode, 0, parent); -++ break; -++ case 'f': -++ add_host_filesystem_entry(name, hostpath, uid, gid, mode, 0, parent); -++ break; -++ case 'p': -++ add_host_filesystem_entry(name, hostpath, uid, gid, mode, 0, parent); -++ break; -++ case 'c': -++ case 'b': -++ if (count > 0) { -++ dev_t rdev; -++ unsigned long i; -++ char *dname, *hpath; -++ -++ for (i = start; i < count; i++) { -++ asprintf(&dname, "%s%lu", name, i); -++ asprintf(&hpath, "%s/%s%lu", rootdir, name, i); -++ rdev = makedev(major, minor + (i * increment - start)); -++ add_host_filesystem_entry(dname, hpath, uid, gid, -++ mode, rdev, parent); -++ free(dname); -++ free(hpath); -++ } -++ } else { -++ dev_t rdev = makedev(major, minor); -++ add_host_filesystem_entry(name, hostpath, uid, gid, -++ mode, rdev, parent); -++ } -++ break; -++ default: -++ error_msg_and_die("Unsupported file type"); -++ } -++ } -++ free(name); -++ free(hostpath); -++ return 0; -++} -++ -++static int parse_device_table(struct filesystem_entry *root, FILE * file) -++{ -++ char *line; -++ int status = 0; -++ size_t length = 0; -++ -++ /* Turn off squash, since we must ensure that values -++ * entered via the device table are not squashed */ -++ squash_uids = 0; -++ squash_perms = 0; -++ -++ /* Looks ok so far. The general plan now is to read in one -++ * line at a time, check for leading comment delimiters ('#'), -++ * then try and parse the line as a device table. If we fail -++ * to parse things, try and help the poor fool to fix their -++ * device table with a useful error msg... */ -++ line = NULL; -++ while (getline(&line, &length, file) != -1) { -++ /* First trim off any whitespace */ -++ int len = strlen(line); -++ -++ /* trim trailing whitespace */ -++ while (len > 0 && isspace(line[len - 1])) -++ line[--len] = '\0'; -++ /* trim leading whitespace */ -++ memmove(line, &line[strspn(line, " \n\r\t\v")], len); -++ -++ /* How long are we after trimming? */ -++ len = strlen(line); -++ -++ /* If this is NOT a comment line, try to interpret it */ -++ if (len && *line != '#') { -++ if (interpret_table_entry(root, line)) -++ status = 1; -++ } -++ -++ free(line); -++ line = NULL; -++ } -++ fclose(file); -++ -++ return status; -++} -++ -++static void cleanup(struct filesystem_entry *dir) -++{ -++ struct filesystem_entry *e, *prev; -++ -++ e = dir->files; -++ while (e) { -++ if (e->name) -++ free(e->name); -++ if (e->path) -++ free(e->path); -++ if (e->fullname) -++ free(e->fullname); -++ e->next = NULL; -++ e->name = NULL; -++ e->path = NULL; -++ e->fullname = NULL; -++ e->prev = NULL; -++ prev = e; -++ if (S_ISDIR(e->sb.st_mode)) { -++ cleanup(e); -++ } -++ e = e->next; -++ free(prev); -++ } -++} -++ -++/* Here is where we do the actual creation of the file system */ -++#include "mtd/jffs2-user.h" -++ -++#define JFFS2_MAX_FILE_SIZE 0xFFFFFFFF -++#ifndef JFFS2_MAX_SYMLINK_LEN -++#define JFFS2_MAX_SYMLINK_LEN 254 -++#endif -++ -++static uint32_t ino = 0; -++static uint8_t *file_buffer = NULL; /* file buffer contains the actual erase block*/ -++static int out_ofs = 0; -++static int erase_block_size = 65536; -++static int pad_fs_size = 0; -++static int add_cleanmarkers = 1; -++static struct jffs2_unknown_node cleanmarker; -++static int cleanmarker_size = sizeof(cleanmarker); -++static unsigned char ffbuf[16] = -++{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -++ 0xff, 0xff, 0xff, 0xff, 0xff -++}; -++ -++/* We set this at start of main() using sysconf(), -1 means we don't know */ -++/* When building an fs for non-native systems, use --pagesize=SIZE option */ -++int page_size = -1; -++ -++#include "compr.h" -++ -++static void full_write(int fd, const void *buf, int len) -++{ -++ int ret; -++ -++ while (len > 0) { -++ ret = write(fd, buf, len); -++ -++ if (ret < 0) -++ perror_msg_and_die("write"); -++ -++ if (ret == 0) -++ perror_msg_and_die("write returned zero"); -++ -++ len -= ret; -++ buf += ret; -++ out_ofs += ret; -++ } -++} -++ -++static void padblock(void) -++{ -++ while (out_ofs % erase_block_size) { -++ full_write(out_fd, ffbuf, min(sizeof(ffbuf), -++ erase_block_size - (out_ofs % erase_block_size))); -++ } -++} -++ -++static void pad(int req) -++{ -++ while (req) { -++ if (req > sizeof(ffbuf)) { -++ full_write(out_fd, ffbuf, sizeof(ffbuf)); -++ req -= sizeof(ffbuf); -++ } else { -++ full_write(out_fd, ffbuf, req); -++ req = 0; -++ } -++ } -++} -++ -++static inline void padword(void) -++{ -++ if (out_ofs % 4) { -++ full_write(out_fd, ffbuf, 4 - (out_ofs % 4)); -++ } -++} -++ -++static inline void pad_block_if_less_than(int req) -++{ -++ if (add_cleanmarkers) { -++ if ((out_ofs % erase_block_size) == 0) { -++ full_write(out_fd, &cleanmarker, sizeof(cleanmarker)); -++ pad(cleanmarker_size - sizeof(cleanmarker)); -++ padword(); -++ } -++ } -++ if ((out_ofs % erase_block_size) + req > erase_block_size) { -++ padblock(); -++ } -++ if (add_cleanmarkers) { -++ if ((out_ofs % erase_block_size) == 0) { -++ full_write(out_fd, &cleanmarker, sizeof(cleanmarker)); -++ pad(cleanmarker_size - sizeof(cleanmarker)); -++ padword(); -++ } -++ } -++} -++ -++static void write_dirent(struct filesystem_entry *e) -++{ -++ char *name = e->name; -++ struct jffs2_raw_dirent rd; -++ struct stat *statbuf = &(e->sb); -++ static uint32_t version = 0; -++ -++ memset(&rd, 0, sizeof(rd)); -++ -++ rd.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -++ rd.nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); -++ rd.totlen = cpu_to_je32(sizeof(rd) + strlen(name)); -++ rd.hdr_crc = cpu_to_je32(crc32(0, &rd, -++ sizeof(struct jffs2_unknown_node) - 4)); -++ rd.pino = cpu_to_je32((e->parent) ? e->parent->ino : 1); -++ rd.version = cpu_to_je32(version++); -++ rd.ino = cpu_to_je32(e->ino); -++ rd.mctime = cpu_to_je32(statbuf->st_mtime); -++ rd.nsize = strlen(name); -++ rd.type = IFTODT(statbuf->st_mode); -++ //rd.unused[0] = 0; -++ //rd.unused[1] = 0; -++ rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd) - 8)); -++ rd.name_crc = cpu_to_je32(crc32(0, name, strlen(name))); -++ -++ pad_block_if_less_than(sizeof(rd) + rd.nsize); -++ full_write(out_fd, &rd, sizeof(rd)); -++ full_write(out_fd, name, rd.nsize); -++ padword(); -++} -++ -++static unsigned int write_regular_file(struct filesystem_entry *e) -++{ -++ int fd, len; -++ uint32_t ver; -++ unsigned int offset; -++ unsigned char *buf, *cbuf, *wbuf; -++ struct jffs2_raw_inode ri; -++ struct stat *statbuf; -++ unsigned int totcomp = 0; -++ -++ statbuf = &(e->sb); -++ if (statbuf->st_size >= JFFS2_MAX_FILE_SIZE) { -++ error_msg("Skipping file \"%s\" too large.", e->path); -++ return -1; -++ } -++ fd = open(e->hostname, O_RDONLY); -++ if (fd == -1) { -++ perror_msg_and_die("%s: open file", e->hostname); -++ } -++ -++ e->ino = ++ino; -++ mkfs_debug_msg("writing file '%s' ino=%lu parent_ino=%lu", -++ e->name, (unsigned long) e->ino, -++ (unsigned long) e->parent->ino); -++ write_dirent(e); -++ -++ buf = xmalloc(page_size); -++ cbuf = NULL; -++ -++ ver = 0; -++ offset = 0; -++ -++ memset(&ri, 0, sizeof(ri)); -++ ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -++ ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -++ -++ ri.ino = cpu_to_je32(e->ino); -++ ri.mode = cpu_to_jemode(statbuf->st_mode); -++ ri.uid = cpu_to_je16(statbuf->st_uid); -++ ri.gid = cpu_to_je16(statbuf->st_gid); -++ ri.atime = cpu_to_je32(statbuf->st_atime); -++ ri.ctime = cpu_to_je32(statbuf->st_ctime); -++ ri.mtime = cpu_to_je32(statbuf->st_mtime); -++ ri.isize = cpu_to_je32(statbuf->st_size); -++ -++ while ((len = read(fd, buf, page_size))) { -++ unsigned char *tbuf = buf; -++ -++ if (len < 0) { -++ perror_msg_and_die("read"); -++ } -++ -++ while (len) { -++ uint32_t dsize, space; -++ uint16_t compression; -++ -++ pad_block_if_less_than(sizeof(ri) + JFFS2_MIN_DATA_LEN); -++ -++ dsize = len; -++ space = -++ erase_block_size - (out_ofs % erase_block_size) - -++ sizeof(ri); -++ if (space > dsize) -++ space = dsize; -++ -++ compression = jffs2_compress(tbuf, &cbuf, &dsize, &space); -++ -++ ri.compr = compression & 0xff; -++ ri.usercompr = (compression >> 8) & 0xff; -++ -++ if (ri.compr) { -++ wbuf = cbuf; -++ } else { -++ wbuf = tbuf; -++ dsize = space; -++ } -++ -++ ri.totlen = cpu_to_je32(sizeof(ri) + space); -++ ri.hdr_crc = cpu_to_je32(crc32(0, -++ &ri, sizeof(struct jffs2_unknown_node) - 4)); -++ -++ ri.version = cpu_to_je32(++ver); -++ ri.offset = cpu_to_je32(offset); -++ ri.csize = cpu_to_je32(space); -++ ri.dsize = cpu_to_je32(dsize); -++ ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri) - 8)); -++ ri.data_crc = cpu_to_je32(crc32(0, wbuf, space)); -++ -++ full_write(out_fd, &ri, sizeof(ri)); -++ totcomp += sizeof(ri); -++ full_write(out_fd, wbuf, space); -++ totcomp += space; -++ padword(); -++ -++ if (tbuf != cbuf) { -++ free(cbuf); -++ cbuf = NULL; -++ } -++ -++ tbuf += dsize; -++ len -= dsize; -++ offset += dsize; -++ -++ } -++ } -++ if (!je32_to_cpu(ri.version)) { -++ /* Was empty file */ -++ pad_block_if_less_than(sizeof(ri)); -++ -++ ri.version = cpu_to_je32(++ver); -++ ri.totlen = cpu_to_je32(sizeof(ri)); -++ ri.hdr_crc = cpu_to_je32(crc32(0, -++ &ri, sizeof(struct jffs2_unknown_node) - 4)); -++ ri.csize = cpu_to_je32(0); -++ ri.dsize = cpu_to_je32(0); -++ ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri) - 8)); -++ -++ full_write(out_fd, &ri, sizeof(ri)); -++ padword(); -++ } -++ free(buf); -++ close(fd); -++ return totcomp; -++} -++ -++static void write_symlink(struct filesystem_entry *e) -++{ -++ int len; -++ struct stat *statbuf; -++ struct jffs2_raw_inode ri; -++ -++ statbuf = &(e->sb); -++ e->ino = ++ino; -++ mkfs_debug_msg("writing symlink '%s' ino=%lu parent_ino=%lu", -++ e->name, (unsigned long) e->ino, -++ (unsigned long) e->parent->ino); -++ write_dirent(e); -++ -++ len = strlen(e->link); -++ if (len > JFFS2_MAX_SYMLINK_LEN) { -++ error_msg("symlink too large. Truncated to %d chars.", -++ JFFS2_MAX_SYMLINK_LEN); -++ len = JFFS2_MAX_SYMLINK_LEN; -++ } -++ -++ memset(&ri, 0, sizeof(ri)); -++ -++ ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -++ ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -++ ri.totlen = cpu_to_je32(sizeof(ri) + len); -++ ri.hdr_crc = cpu_to_je32(crc32(0, -++ &ri, sizeof(struct jffs2_unknown_node) - 4)); -++ -++ ri.ino = cpu_to_je32(e->ino); -++ ri.mode = cpu_to_jemode(statbuf->st_mode); -++ ri.uid = cpu_to_je16(statbuf->st_uid); -++ ri.gid = cpu_to_je16(statbuf->st_gid); -++ ri.atime = cpu_to_je32(statbuf->st_atime); -++ ri.ctime = cpu_to_je32(statbuf->st_ctime); -++ ri.mtime = cpu_to_je32(statbuf->st_mtime); -++ ri.isize = cpu_to_je32(statbuf->st_size); -++ ri.version = cpu_to_je32(1); -++ ri.csize = cpu_to_je32(len); -++ ri.dsize = cpu_to_je32(len); -++ ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri) - 8)); -++ ri.data_crc = cpu_to_je32(crc32(0, e->link, len)); -++ -++ pad_block_if_less_than(sizeof(ri) + len); -++ full_write(out_fd, &ri, sizeof(ri)); -++ full_write(out_fd, e->link, len); -++ padword(); -++} -++ -++static void write_pipe(struct filesystem_entry *e) -++{ -++ struct stat *statbuf; -++ struct jffs2_raw_inode ri; -++ -++ statbuf = &(e->sb); -++ e->ino = ++ino; -++ if (S_ISDIR(statbuf->st_mode)) { -++ mkfs_debug_msg("writing dir '%s' ino=%lu parent_ino=%lu", -++ e->name, (unsigned long) e->ino, -++ (unsigned long) (e->parent) ? e->parent->ino : 1); -++ } -++ write_dirent(e); -++ -++ memset(&ri, 0, sizeof(ri)); -++ -++ ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -++ ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -++ ri.totlen = cpu_to_je32(sizeof(ri)); -++ ri.hdr_crc = cpu_to_je32(crc32(0, -++ &ri, sizeof(struct jffs2_unknown_node) - 4)); -++ -++ ri.ino = cpu_to_je32(e->ino); -++ ri.mode = cpu_to_jemode(statbuf->st_mode); -++ ri.uid = cpu_to_je16(statbuf->st_uid); -++ ri.gid = cpu_to_je16(statbuf->st_gid); -++ ri.atime = cpu_to_je32(statbuf->st_atime); -++ ri.ctime = cpu_to_je32(statbuf->st_ctime); -++ ri.mtime = cpu_to_je32(statbuf->st_mtime); -++ ri.isize = cpu_to_je32(0); -++ ri.version = cpu_to_je32(1); -++ ri.csize = cpu_to_je32(0); -++ ri.dsize = cpu_to_je32(0); -++ ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri) - 8)); -++ ri.data_crc = cpu_to_je32(0); -++ -++ pad_block_if_less_than(sizeof(ri)); -++ full_write(out_fd, &ri, sizeof(ri)); -++ padword(); -++} -++ -++static void write_special_file(struct filesystem_entry *e) -++{ -++ jint16_t kdev; -++ struct stat *statbuf; -++ struct jffs2_raw_inode ri; -++ -++ statbuf = &(e->sb); -++ e->ino = ++ino; -++ write_dirent(e); -++ -++ kdev = cpu_to_je16((major(statbuf->st_rdev) << 8) + -++ minor(statbuf->st_rdev)); -++ -++ memset(&ri, 0, sizeof(ri)); -++ -++ ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -++ ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); -++ ri.totlen = cpu_to_je32(sizeof(ri) + sizeof(kdev)); -++ ri.hdr_crc = cpu_to_je32(crc32(0, -++ &ri, sizeof(struct jffs2_unknown_node) - 4)); -++ -++ ri.ino = cpu_to_je32(e->ino); -++ ri.mode = cpu_to_jemode(statbuf->st_mode); -++ ri.uid = cpu_to_je16(statbuf->st_uid); -++ ri.gid = cpu_to_je16(statbuf->st_gid); -++ ri.atime = cpu_to_je32(statbuf->st_atime); -++ ri.ctime = cpu_to_je32(statbuf->st_ctime); -++ ri.mtime = cpu_to_je32(statbuf->st_mtime); -++ ri.isize = cpu_to_je32(statbuf->st_size); -++ ri.version = cpu_to_je32(1); -++ ri.csize = cpu_to_je32(sizeof(kdev)); -++ ri.dsize = cpu_to_je32(sizeof(kdev)); -++ ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri) - 8)); -++ ri.data_crc = cpu_to_je32(crc32(0, &kdev, sizeof(kdev))); -++ -++ pad_block_if_less_than(sizeof(ri) + sizeof(kdev)); -++ full_write(out_fd, &ri, sizeof(ri)); -++ full_write(out_fd, &kdev, sizeof(kdev)); -++ padword(); -++} -++ -++#ifndef WITHOUT_XATTR -++typedef struct xattr_entry { -++ struct xattr_entry *next; -++ uint32_t xid; -++ int xprefix; -++ char *xname; -++ char *xvalue; -++ int name_len; -++ int value_len; -++} xattr_entry_t; -++ -++#define XATTR_BUFFER_SIZE (64 * 1024) /* 64KB */ -++static uint32_t enable_xattr = 0; -++static uint32_t highest_xid = 0; -++static uint32_t highest_xseqno = 0; -++ -++static struct { -++ int xprefix; -++ char *string; -++ int length; -++} xprefix_tbl[] = { -++ { JFFS2_XPREFIX_USER, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN }, -++ { JFFS2_XPREFIX_SECURITY, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN }, -++ { JFFS2_XPREFIX_ACL_ACCESS, POSIX_ACL_XATTR_ACCESS, POSIX_ACL_XATTR_ACCESS_LEN }, -++ { JFFS2_XPREFIX_ACL_DEFAULT, POSIX_ACL_XATTR_DEFAULT, POSIX_ACL_XATTR_DEFAULT_LEN }, -++ { JFFS2_XPREFIX_TRUSTED, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN }, -++ { 0, NULL, 0 } -++}; -++ -++static void formalize_posix_acl(void *xvalue, int *value_len) -++{ -++ struct posix_acl_xattr_header *pacl_header; -++ struct posix_acl_xattr_entry *pent, *plim; -++ struct jffs2_acl_header *jacl_header; -++ struct jffs2_acl_entry *jent; -++ struct jffs2_acl_entry_short *jent_s; -++ char buffer[XATTR_BUFFER_SIZE]; -++ int offset = 0; -++ -++ pacl_header = xvalue;; -++ pent = pacl_header->a_entries; -++ plim = xvalue + *value_len; -++ -++ jacl_header = (struct jffs2_acl_header *)buffer; -++ offset += sizeof(struct jffs2_acl_header); -++ jacl_header->a_version = cpu_to_je32(JFFS2_ACL_VERSION); -++ -++ while (pent < plim) { -++ switch(le16_to_cpu(pent->e_tag)) { -++ case ACL_USER_OBJ: -++ case ACL_GROUP_OBJ: -++ case ACL_MASK: -++ case ACL_OTHER: -++ jent_s = (struct jffs2_acl_entry_short *)(buffer + offset); -++ offset += sizeof(struct jffs2_acl_entry_short); -++ jent_s->e_tag = cpu_to_je16(le16_to_cpu(pent->e_tag)); -++ jent_s->e_perm = cpu_to_je16(le16_to_cpu(pent->e_perm)); -++ break; -++ case ACL_USER: -++ case ACL_GROUP: -++ jent = (struct jffs2_acl_entry *)(buffer + offset); -++ offset += sizeof(struct jffs2_acl_entry); -++ jent->e_tag = cpu_to_je16(le16_to_cpu(pent->e_tag)); -++ jent->e_perm = cpu_to_je16(le16_to_cpu(pent->e_perm)); -++ jent->e_id = cpu_to_je32(le32_to_cpu(pent->e_id)); -++ break; -++ default: -++ printf("%04x : Unknown XATTR entry tag.\n", le16_to_cpu(pent->e_tag)); -++ exit(1); -++ } -++ pent++; -++ } -++ if (offset > *value_len) { -++ printf("Length of JFFS2 ACL expression(%u) is longer than general one(%u).\n", -++ offset, *value_len); -++ exit(1); -++ } -++ memcpy(xvalue, buffer, offset); -++ *value_len = offset; -++} -++ -++static xattr_entry_t *create_xattr_entry(int xprefix, char *xname, char *xvalue, int value_len) -++{ -++ xattr_entry_t *xe; -++ struct jffs2_raw_xattr rx; -++ int name_len; -++ -++ /* create xattr entry */ -++ name_len = strlen(xname); -++ xe = xcalloc(1, sizeof(xattr_entry_t) + name_len + 1 + value_len); -++ xe->next = NULL; -++ xe->xid = ++highest_xid; -++ xe->xprefix = xprefix; -++ xe->xname = ((char *)xe) + sizeof(xattr_entry_t); -++ xe->xvalue = xe->xname + name_len + 1; -++ xe->name_len = name_len; -++ xe->value_len = value_len; -++ strcpy(xe->xname, xname); -++ memcpy(xe->xvalue, xvalue, value_len); -++ -++ /* write xattr node */ -++ memset(&rx, 0, sizeof(rx)); -++ rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -++ rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR); -++ rx.totlen = cpu_to_je32(PAD(sizeof(rx) + xe->name_len + 1 + xe->value_len)); -++ rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4)); -++ -++ rx.xid = cpu_to_je32(xe->xid); -++ rx.version = cpu_to_je32(1); /* initial version */ -++ rx.xprefix = xprefix; -++ rx.name_len = xe->name_len; -++ rx.value_len = cpu_to_je16(xe->value_len); -++ rx.data_crc = cpu_to_je32(crc32(0, xe->xname, xe->name_len + 1 + xe->value_len)); -++ rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(rx) - 4)); -++ -++ pad_block_if_less_than(sizeof(rx) + xe->name_len + 1 + xe->value_len); -++ full_write(out_fd, &rx, sizeof(rx)); -++ full_write(out_fd, xe->xname, xe->name_len + 1 + xe->value_len); -++ padword(); -++ -++ return xe; -++} -++ -++#define XATTRENTRY_HASHSIZE 57 -++static xattr_entry_t *find_xattr_entry(int xprefix, char *xname, char *xvalue, int value_len) -++{ -++ static xattr_entry_t **xentry_hash = NULL; -++ xattr_entry_t *xe; -++ int index, name_len; -++ -++ /* create hash table */ -++ if (!xentry_hash) -++ xentry_hash = xcalloc(1, sizeof(xe) * XATTRENTRY_HASHSIZE); -++ -++ if (xprefix == JFFS2_XPREFIX_ACL_ACCESS -++ || xprefix == JFFS2_XPREFIX_ACL_DEFAULT) -++ formalize_posix_acl(xvalue, &value_len); -++ -++ name_len = strlen(xname); -++ index = (crc32(0, xname, name_len) ^ crc32(0, xvalue, value_len)) % XATTRENTRY_HASHSIZE; -++ for (xe = xentry_hash[index]; xe; xe = xe->next) { -++ if (xe->xprefix == xprefix -++ && xe->value_len == value_len -++ && !strcmp(xe->xname, xname) -++ && !memcmp(xe->xvalue, xvalue, value_len)) -++ break; -++ } -++ if (!xe) { -++ xe = create_xattr_entry(xprefix, xname, xvalue, value_len); -++ xe->next = xentry_hash[index]; -++ xentry_hash[index] = xe; -++ } -++ return xe; -++} -++ -++static void write_xattr_entry(struct filesystem_entry *e) -++{ -++ struct jffs2_raw_xref ref; -++ struct xattr_entry *xe; -++ char xlist[XATTR_BUFFER_SIZE], xvalue[XATTR_BUFFER_SIZE]; -++ char *xname, *prefix_str; -++ int i, xprefix, prefix_len; -++ int list_sz, offset, name_len, value_len; -++ -++ if (!enable_xattr) -++ return; -++ -++ list_sz = llistxattr(e->hostname, xlist, XATTR_BUFFER_SIZE); -++ if (list_sz < 0) { -++ if (verbose) -++ printf("llistxattr('%s') = %d : %s\n", -++ e->hostname, errno, strerror(errno)); -++ return; -++ } -++ -++ for (offset = 0; offset < list_sz; offset += name_len) { -++ xname = xlist + offset; -++ name_len = strlen(xname) + 1; -++ -++ for (i = 0; (xprefix = xprefix_tbl[i].xprefix); i++) { -++ prefix_str = xprefix_tbl[i].string; -++ prefix_len = xprefix_tbl[i].length; -++ if (prefix_str[prefix_len - 1] == '.') { -++ if (!strncmp(xname, prefix_str, prefix_len - 1)) -++ break; -++ } else { -++ if (!strcmp(xname, prefix_str)) -++ break; -++ } -++ } -++ if (!xprefix) { -++ if (verbose) -++ printf("%s: xattr '%s' is not supported.\n", -++ e->hostname, xname); -++ continue; -++ } -++ if ((enable_xattr & (1 << xprefix)) == 0) -++ continue; -++ -++ value_len = lgetxattr(e->hostname, xname, xvalue, XATTR_BUFFER_SIZE); -++ if (value_len < 0) { -++ if (verbose) -++ printf("lgetxattr('%s', '%s') = %d : %s\n", -++ e->hostname, xname, errno, strerror(errno)); -++ continue; -++ } -++ xe = find_xattr_entry(xprefix, xname + prefix_len, xvalue, value_len); -++ if (!xe) { -++ if (verbose) -++ printf("%s : xattr '%s' was ignored.\n", -++ e->hostname, xname); -++ continue; -++ } -++ -++ memset(&ref, 0, sizeof(ref)); -++ ref.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -++ ref.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF); -++ ref.totlen = cpu_to_je32(sizeof(ref)); -++ ref.hdr_crc = cpu_to_je32(crc32(0, &ref, sizeof(struct jffs2_unknown_node) - 4)); -++ ref.ino = cpu_to_je32(e->ino); -++ ref.xid = cpu_to_je32(xe->xid); -++ ref.xseqno = cpu_to_je32(highest_xseqno += 2); -++ ref.node_crc = cpu_to_je32(crc32(0, &ref, sizeof(ref) - 4)); -++ -++ pad_block_if_less_than(sizeof(ref)); -++ full_write(out_fd, &ref, sizeof(ref)); -++ padword(); -++ } -++} -++ -++#else /* WITHOUT_XATTR */ -++#define write_xattr_entry(x) -++#endif -++ -++static void recursive_populate_directory(struct filesystem_entry *dir) -++{ -++ struct filesystem_entry *e; -++ unsigned int wrote; -++ -++ if (verbose) { -++ printf("%s\n", dir->fullname); -++ } -++ write_xattr_entry(dir); /* for '/' */ -++ -++ e = dir->files; -++ while (e) { -++ if (e->sb.st_nlink >= 1 && -++ (e->ino = find_hardlink(e))) { -++ -++ write_dirent(e); -++ if (verbose) { -++ printf("\tL %04o %9lu %5d:%-3d %s\n", -++ e->sb.st_mode & ~S_IFMT, (unsigned long) e->ino, -++ (int) (e->sb.st_uid), (int) (e->sb.st_gid), -++ e->name); -++ } -++ } else switch (e->sb.st_mode & S_IFMT) { -++ case S_IFDIR: -++ if (verbose) { -++ printf("\td %04o %9lu %5d:%-3d %s\n", -++ e->sb.st_mode & ~S_IFMT, e->sb.st_size, -++ (int) (e->sb.st_uid), (int) (e->sb.st_gid), -++ e->name); -++ } -++ write_pipe(e); -++ write_xattr_entry(e); -++ break; -++ case S_IFSOCK: -++ if (verbose) { -++ printf("\ts %04o %9lu %5d:%-3d %s\n", -++ e->sb.st_mode & ~S_IFMT, e->sb.st_size, -++ (int) e->sb.st_uid, (int) e->sb.st_gid, e->name); -++ } -++ write_pipe(e); -++ write_xattr_entry(e); -++ break; -++ case S_IFIFO: -++ if (verbose) { -++ printf("\tp %04o %9lu %5d:%-3d %s\n", -++ e->sb.st_mode & ~S_IFMT, e->sb.st_size, -++ (int) e->sb.st_uid, (int) e->sb.st_gid, e->name); -++ } -++ write_pipe(e); -++ write_xattr_entry(e); -++ break; -++ case S_IFCHR: -++ if (verbose) { -++ printf("\tc %04o %4d,%4d %5d:%-3d %s\n", -++ e->sb.st_mode & ~S_IFMT, major(e->sb.st_rdev), -++ minor(e->sb.st_rdev), (int) e->sb.st_uid, -++ (int) e->sb.st_gid, e->name); -++ } -++ write_special_file(e); -++ write_xattr_entry(e); -++ break; -++ case S_IFBLK: -++ if (verbose) { -++ printf("\tb %04o %4d,%4d %5d:%-3d %s\n", -++ e->sb.st_mode & ~S_IFMT, major(e->sb.st_rdev), -++ minor(e->sb.st_rdev), (int) e->sb.st_uid, -++ (int) e->sb.st_gid, e->name); -++ } -++ write_special_file(e); -++ write_xattr_entry(e); -++ break; -++ case S_IFLNK: -++ if (verbose) { -++ printf("\tl %04o %9lu %5d:%-3d %s -> %s\n", -++ e->sb.st_mode & ~S_IFMT, e->sb.st_size, -++ (int) e->sb.st_uid, (int) e->sb.st_gid, e->name, -++ e->link); -++ } -++ write_symlink(e); -++ write_xattr_entry(e); -++ break; -++ case S_IFREG: -++ wrote = write_regular_file(e); -++ write_xattr_entry(e); -++ if (verbose) { -++ printf("\tf %04o %9lu (%9u) %5d:%-3d %s\n", -++ e->sb.st_mode & ~S_IFMT, e->sb.st_size, wrote, -++ (int) e->sb.st_uid, (int) e->sb.st_gid, e->name); -++ } -++ break; -++ default: -++ error_msg("Unknown mode %o for %s", e->sb.st_mode, -++ e->fullname); -++ break; -++ } -++ e = e->next; -++ } -++ -++ e = dir->files; -++ while (e) { -++ if (S_ISDIR(e->sb.st_mode)) { -++ if (e->files) { -++ recursive_populate_directory(e); -++ } else if (verbose) { -++ printf("%s\n", e->fullname); -++ } -++ } -++ e = e->next; -++ } -++} -++ -++static void create_target_filesystem(struct filesystem_entry *root) -++{ -++ cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -++ cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); -++ cleanmarker.totlen = cpu_to_je32(cleanmarker_size); -++ cleanmarker.hdr_crc = cpu_to_je32(crc32(0, &cleanmarker, sizeof(struct jffs2_unknown_node)-4)); -++ -++ if (ino == 0) -++ ino = 1; -++ -++ root->ino = 1; -++ recursive_populate_directory(root); -++ -++ if (pad_fs_size == -1) { -++ padblock(); -++ } else { -++ if (pad_fs_size && add_cleanmarkers){ -++ padblock(); -++ while (out_ofs < pad_fs_size) { -++ full_write(out_fd, &cleanmarker, sizeof(cleanmarker)); -++ pad(cleanmarker_size - sizeof(cleanmarker)); -++ padblock(); -++ } -++ } else { -++ while (out_ofs < pad_fs_size) { -++ full_write(out_fd, ffbuf, min(sizeof(ffbuf), pad_fs_size - out_ofs)); -++ } -++ -++ } -++ } -++} -++ -++static struct option long_options[] = { -++ {"pad", 2, NULL, 'p'}, -++ {"root", 1, NULL, 'r'}, -++ {"pagesize", 1, NULL, 's'}, -++ {"eraseblock", 1, NULL, 'e'}, -++ {"output", 1, NULL, 'o'}, -++ {"help", 0, NULL, 'h'}, -++ {"verbose", 0, NULL, 'v'}, -++ {"version", 0, NULL, 'V'}, -++ {"big-endian", 0, NULL, 'b'}, -++ {"little-endian", 0, NULL, 'l'}, -++ {"no-cleanmarkers", 0, NULL, 'n'}, -++ {"cleanmarker", 1, NULL, 'c'}, -++ {"squash", 0, NULL, 'q'}, -++ {"squash-uids", 0, NULL, 'U'}, -++ {"squash-perms", 0, NULL, 'P'}, -++ {"faketime", 0, NULL, 'f'}, -++ {"devtable", 1, NULL, 'D'}, -++ {"compression-mode", 1, NULL, 'm'}, -++ {"disable-compressor", 1, NULL, 'x'}, -++ {"test-compression", 0, NULL, 't'}, -++ {"compressor-priority", 1, NULL, 'y'}, -++ {"incremental", 1, NULL, 'i'}, -++#ifndef WITHOUT_XATTR -++ {"with-xattr", 0, NULL, 1000 }, -++ {"with-selinux", 0, NULL, 1001 }, -++ {"with-posix-acl", 0, NULL, 1002 }, -++#endif -++ {NULL, 0, NULL, 0} -++}; -++ -++static char *helptext = -++"Usage: mkfs.jffs2 [OPTIONS]\n" -++"Make a JFFS2 file system image from an existing directory tree\n\n" -++"Options:\n" -++" -p, --pad[=SIZE] Pad output to SIZE bytes with 0xFF. If SIZE is\n" -++" not specified, the output is padded to the end of\n" -++" the final erase block\n" -++" -r, -d, --root=DIR Build file system from directory DIR (default: cwd)\n" -++" -s, --pagesize=SIZE Use page size (max data node size) SIZE (default: 4KiB)\n" -++" -e, --eraseblock=SIZE Use erase block size SIZE (default: 64KiB)\n" -++" -c, --cleanmarker=SIZE Size of cleanmarker (default 12)\n" -++" -m, --compr-mode=MODE Select compression mode (default: priortiry)\n" -++" -x, --disable-compressor=COMPRESSOR_NAME\n" -++" Disable a compressor\n" -++" -X, --enable-compressor=COMPRESSOR_NAME\n" -++" Enable a compressor\n" -++" -y, --compressor-priority=PRIORITY:COMPRESSOR_NAME\n" -++" Set the priority of a compressor\n" -++" -L, --list-compressors Show the list of the avaiable compressors\n" -++" -t, --test-compression Call decompress and compare with the original (for test)\n" -++" -n, --no-cleanmarkers Don't add a cleanmarker to every eraseblock\n" -++" -o, --output=FILE Output to FILE (default: stdout)\n" -++" -l, --little-endian Create a little-endian filesystem\n" -++" -b, --big-endian Create a big-endian filesystem\n" -++" -D, --devtable=FILE Use the named FILE as a device table file\n" -++" -f, --faketime Change all file times to '0' for regression testing\n" -++" -q, --squash Squash permissions and owners making all files be owned by root\n" -++" -U, --squash-uids Squash owners making all files be owned by root\n" -++" -P, --squash-perms Squash permissions on all files\n" -++#ifndef WITHOUT_XATTR -++" --with-xattr stuff all xattr entries into image\n" -++" --with-selinux stuff only SELinux Labels into jffs2 image\n" -++" --with-posix-acl stuff only POSIX ACL entries into jffs2 image\n" -++#endif -++" -h, --help Display this help text\n" -++" -v, --verbose Verbose operation\n" -++" -V, --version Display version information\n" -++" -i, --incremental=FILE Parse FILE and generate appendage output for it\n\n"; -++ -++static char *revtext = "1.60"; -++ -++int load_next_block() { -++ -++ int ret; -++ ret = read(in_fd, file_buffer, erase_block_size); -++ -++ if(verbose) -++ printf("Load next block : %d bytes read\n",ret); -++ -++ return ret; -++} -++ -++void process_buffer(int inp_size) { -++ uint8_t *p = file_buffer; -++ union jffs2_node_union *node; -++ uint16_t type; -++ int bitchbitmask = 0; -++ int obsolete; -++ -++ char name[256]; -++ -++ while ( p < (file_buffer + inp_size)) { -++ -++ node = (union jffs2_node_union *) p; -++ -++ /* Skip empty space */ -++ if (je16_to_cpu (node->u.magic) == 0xFFFF && je16_to_cpu (node->u.nodetype) == 0xFFFF) { -++ p += 4; -++ continue; -++ } -++ -++ if (je16_to_cpu (node->u.magic) != JFFS2_MAGIC_BITMASK) { -++ if (!bitchbitmask++) -++ printf ("Wrong bitmask at 0x%08x, 0x%04x\n", p - file_buffer, je16_to_cpu (node->u.magic)); -++ p += 4; -++ continue; -++ } -++ -++ bitchbitmask = 0; -++ -++ type = je16_to_cpu(node->u.nodetype); -++ if ((type & JFFS2_NODE_ACCURATE) != JFFS2_NODE_ACCURATE) { -++ obsolete = 1; -++ type |= JFFS2_NODE_ACCURATE; -++ } else -++ obsolete = 0; -++ -++ node->u.nodetype = cpu_to_je16(type); -++ -++ switch(je16_to_cpu(node->u.nodetype)) { -++ -++ case JFFS2_NODETYPE_INODE: -++ if(verbose) -++ printf ("%8s Inode node at 0x%08x, totlen 0x%08x, #ino %5d, version %5d, isize %8d, csize %8d, dsize %8d, offset %8d\n", -++ obsolete ? "Obsolete" : "", -++ p - file_buffer, je32_to_cpu (node->i.totlen), je32_to_cpu (node->i.ino), -++ je32_to_cpu ( node->i.version), je32_to_cpu (node->i.isize), -++ je32_to_cpu (node->i.csize), je32_to_cpu (node->i.dsize), je32_to_cpu (node->i.offset)); -++ -++ if ( je32_to_cpu (node->i.ino) > ino ) -++ ino = je32_to_cpu (node->i.ino); -++ -++ p += PAD(je32_to_cpu (node->i.totlen)); -++ break; -++ -++ case JFFS2_NODETYPE_DIRENT: -++ memcpy (name, node->d.name, node->d.nsize); -++ name [node->d.nsize] = 0x0; -++ -++ if(verbose) -++ printf ("%8s Dirent node at 0x%08x, totlen 0x%08x, #pino %5d, version %5d, #ino %8d, nsize %8d, name %s\n", -++ obsolete ? "Obsolete" : "", -++ p - file_buffer, je32_to_cpu (node->d.totlen), je32_to_cpu (node->d.pino), -++ je32_to_cpu ( node->d.version), je32_to_cpu (node->d.ino), -++ node->d.nsize, name); -++ -++ p += PAD(je32_to_cpu (node->d.totlen)); -++ break; -++ -++ case JFFS2_NODETYPE_CLEANMARKER: -++ if (verbose) { -++ printf ("%8s Cleanmarker at 0x%08x, totlen 0x%08x\n", -++ obsolete ? "Obsolete" : "", -++ p - file_buffer, je32_to_cpu (node->u.totlen)); -++ } -++ -++ p += PAD(je32_to_cpu (node->u.totlen)); -++ break; -++ -++ case JFFS2_NODETYPE_PADDING: -++ if (verbose) { -++ printf ("%8s Padding node at 0x%08x, totlen 0x%08x\n", -++ obsolete ? "Obsolete" : "", -++ p - file_buffer, je32_to_cpu (node->u.totlen)); -++ } -++ -++ p += PAD(je32_to_cpu (node->u.totlen)); -++ break; -++ -++ case 0xffff: -++ p += 4; -++ break; -++ -++ default: -++ if (verbose) { -++ printf ("%8s Unknown node at 0x%08x, totlen 0x%08x\n", -++ obsolete ? "Obsolete" : "", -++ p - file_buffer, je32_to_cpu (node->u.totlen)); -++ } -++ -++ p += PAD(je32_to_cpu (node->u.totlen)); -++ } -++ } -++} -++ -++void parse_image(){ -++ int ret; -++ -++ file_buffer = malloc(erase_block_size); -++ -++ if (!file_buffer) { -++ perror("out of memory"); -++ close (in_fd); -++ close (out_fd); -++ exit(1); -++ } -++ -++ while ((ret = load_next_block())) { -++ process_buffer(ret); -++ } -++ -++ if (file_buffer) -++ free(file_buffer); -++ -++ close(in_fd); -++} -++ -++int main(int argc, char **argv) -++{ -++ int c, opt; -++ char *cwd; -++ struct stat sb; -++ FILE *devtable = NULL; -++ struct filesystem_entry *root; -++ char *compr_name = NULL; -++ int compr_prior = -1; -++ int warn_page_size = 0; -++ -++ page_size = sysconf(_SC_PAGESIZE); -++ if (page_size < 0) /* System doesn't know so ... */ -++ page_size = 4096; /* ... we make an educated guess */ -++ if (page_size != 4096) -++ warn_page_size = 1; /* warn user if page size not 4096 */ -++ -++ jffs2_compressors_init(); -++ -++ while ((opt = getopt_long(argc, argv, -++ "D:d:r:s:o:qUPfh?vVe:lbp::nc:m:x:X:Lty:i:", long_options, &c)) >= 0) -++ { -++ switch (opt) { -++ case 'D': -++ devtable = xfopen(optarg, "r"); -++ if (fstat(fileno(devtable), &sb) < 0) -++ perror_msg_and_die(optarg); -++ if (sb.st_size < 10) -++ error_msg_and_die("%s: not a proper device table file", optarg); -++ break; -++ -++ case 'r': -++ case 'd': /* for compatibility with mkfs.jffs, genext2fs, etc... */ -++ if (rootdir != default_rootdir) { -++ error_msg_and_die("root directory specified more than once"); -++ } -++ rootdir = xstrdup(optarg); -++ break; -++ -++ case 's': -++ page_size = strtol(optarg, NULL, 0); -++ warn_page_size = 0; /* set by user, so don't need to warn */ -++ break; -++ -++ case 'o': -++ if (out_fd != -1) { -++ error_msg_and_die("output filename specified more than once"); -++ } -++ out_fd = open(optarg, O_CREAT | O_TRUNC | O_RDWR, 0644); -++ if (out_fd == -1) { -++ perror_msg_and_die("open output file"); -++ } -++ break; -++ -++ case 'q': -++ squash_uids = 1; -++ squash_perms = 1; -++ break; -++ -++ case 'U': -++ squash_uids = 1; -++ break; -++ -++ case 'P': -++ squash_perms = 1; -++ break; -++ -++ case 'f': -++ fake_times = 1; -++ break; -++ -++ case 'h': -++ case '?': -++ error_msg_and_die(helptext); -++ -++ case 'v': -++ verbose = 1; -++ break; -++ -++ case 'V': -++ error_msg_and_die("revision %s\n", revtext); -++ -++ case 'e': { -++ char *next; -++ unsigned units = 0; -++ erase_block_size = strtol(optarg, &next, 0); -++ if (!erase_block_size) -++ error_msg_and_die("Unrecognisable erase size\n"); -++ -++ if (*next) { -++ if (!strcmp(next, "KiB")) { -++ units = 1024; -++ } else if (!strcmp(next, "MiB")) { -++ units = 1024 * 1024; -++ } else { -++ error_msg_and_die("Unknown units in erasesize\n"); -++ } -++ } else { -++ if (erase_block_size < 0x1000) -++ units = 1024; -++ else -++ units = 1; -++ } -++ erase_block_size *= units; -++ -++ /* If it's less than 8KiB, they're not allowed */ -++ if (erase_block_size < 0x2000) { -++ fprintf(stderr, "Erase size 0x%x too small. Increasing to 8KiB minimum\n", -++ erase_block_size); -++ erase_block_size = 0x2000; -++ } -++ break; -++ } -++ -++ case 'l': -++ target_endian = __LITTLE_ENDIAN; -++ break; -++ -++ case 'b': -++ target_endian = __BIG_ENDIAN; -++ break; -++ -++ case 'p': -++ if (optarg) -++ pad_fs_size = strtol(optarg, NULL, 0); -++ else -++ pad_fs_size = -1; -++ break; -++ case 'n': -++ add_cleanmarkers = 0; -++ break; -++ case 'c': -++ cleanmarker_size = strtol(optarg, NULL, 0); -++ if (cleanmarker_size < sizeof(cleanmarker)) { -++ error_msg_and_die("cleanmarker size must be >= 12"); -++ } -++ if (cleanmarker_size >= erase_block_size) { -++ error_msg_and_die("cleanmarker size must be < eraseblock size"); -++ } -++ break; -++ case 'm': -++ if (jffs2_set_compression_mode_name(optarg)) { -++ error_msg_and_die("Unknown compression mode %s", optarg); -++ } -++ break; -++ case 'x': -++ if (jffs2_disable_compressor_name(optarg)) { -++ error_msg_and_die("Unknown compressor name %s",optarg); -++ } -++ break; -++ case 'X': -++ if (jffs2_enable_compressor_name(optarg)) { -++ error_msg_and_die("Unknown compressor name %s",optarg); -++ } -++ break; -++ case 'L': -++ error_msg_and_die("\n%s",jffs2_list_compressors()); -++ break; -++ case 't': -++ jffs2_compression_check_set(1); -++ break; -++ case 'y': -++ compr_name = malloc(strlen(optarg)); -++ sscanf(optarg,"%d:%s",&compr_prior,compr_name); -++ if ((compr_prior>=0)&&(compr_name)) { -++ if (jffs2_set_compressor_priority(compr_name, compr_prior)) -++ exit(EXIT_FAILURE); -++ } -++ else { -++ error_msg_and_die("Cannot parse %s",optarg); -++ } -++ free(compr_name); -++ break; -++ case 'i': -++ if (in_fd != -1) { -++ error_msg_and_die("(incremental) filename specified more than once"); -++ } -++ in_fd = open(optarg, O_RDONLY); -++ if (in_fd == -1) { -++ perror_msg_and_die("cannot open (incremental) file"); -++ } -++ break; -++#ifndef WITHOUT_XATTR -++ case 1000: /* --with-xattr */ -++ enable_xattr |= (1 << JFFS2_XPREFIX_USER) -++ | (1 << JFFS2_XPREFIX_SECURITY) -++ | (1 << JFFS2_XPREFIX_ACL_ACCESS) -++ | (1 << JFFS2_XPREFIX_ACL_DEFAULT) -++ | (1 << JFFS2_XPREFIX_TRUSTED); -++ break; -++ case 1001: /* --with-selinux */ -++ enable_xattr |= (1 << JFFS2_XPREFIX_SECURITY); -++ break; -++ case 1002: /* --with-posix-acl */ -++ enable_xattr |= (1 << JFFS2_XPREFIX_ACL_ACCESS) -++ | (1 << JFFS2_XPREFIX_ACL_DEFAULT); -++ break; -++#endif -++ } -++ } -++ if (warn_page_size) { -++ error_msg("Page size for this system is by default %d", page_size); -++ error_msg("Use the --pagesize=SIZE option if this is not what you want"); -++ } -++ if (out_fd == -1) { -++ if (isatty(1)) { -++ error_msg_and_die(helptext); -++ } -++ out_fd = 1; -++ } -++ if (lstat(rootdir, &sb)) { -++ perror_msg_and_die("%s", rootdir); -++ } -++ if (chdir(rootdir)) -++ perror_msg_and_die("%s", rootdir); -++ -++ if (!(cwd = getcwd(0, GETCWD_SIZE))) -++ perror_msg_and_die("getcwd failed"); -++ -++ if(in_fd != -1) -++ parse_image(); -++ -++ root = recursive_add_host_directory(NULL, "/", cwd); -++ -++ if (devtable) -++ parse_device_table(root, devtable); -++ -++ create_target_filesystem(root); -++ -++ cleanup(root); -++ -++ if (rootdir != default_rootdir) -++ free(rootdir); -++ -++ close(out_fd); -++ -++ if (verbose) { -++ char *s = jffs2_stats(); -++ fprintf(stderr,"\n\n%s",s); -++ free(s); -++ } -++ if ((verbose)||(jffs2_compression_check_get()&&(jffs2_compression_check_errorcnt_get()))) { -++ fprintf(stderr,"Compression errors: %d\n",jffs2_compression_check_errorcnt_get()); -++ } -++ -++ jffs2_compressors_exit(); -++ -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/mtd-utils.spec linux-2.6.24.7/drivers/mtd/mtd-utils/mtd-utils.spec -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/mtd-utils.spec 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/mtd-utils.spec 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,40 @@ -++Summary: Tools for maintaining Memory Technology Devices -++Name: mtd-utils -++Version: 1.0 -++Release: 1 -++License: GPL -++Group: Applications/System -++URL: http://www.linux-mtd.infradead.org/ -++Source0: %{name}-%{version}.tar.gz -++BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root -++ -++%description -++This package contains tools for erasing and formatting flash devices, -++including JFFS2, M-Systems DiskOnChip devices, etc. -++ -++%prep -++%setup -q -++ -++%build -++make -C util -++ -++%install -++rm -rf $RPM_BUILD_ROOT -++make DESTDIR=$RPM_BUILD_ROOT -C util install -++ -++%clean -++rm -rf $RPM_BUILD_ROOT -++ -++ -++%files -++%defattr(-,root,root,-) -++/usr/sbin -++/usr/man/man1/mkfs.jffs2.1.gz -++/usr/include/mtd -++%doc -++ -++ -++%changelog -++* Wed May 5 2004 - 1.0 -++- Initial build. -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/mtd_debug.c linux-2.6.24.7/drivers/mtd/mtd-utils/mtd_debug.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/mtd_debug.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/mtd_debug.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,418 @@ -++/* -++ * Copyright (c) 2d3D, Inc. -++ * Written by Abraham vd Merwe -++ * All rights reserved. -++ * -++ * Redistribution and use in source and binary forms, with or without -++ * modification, are permitted provided that the following conditions -++ * are met: -++ * 1. Redistributions of source code must retain the above copyright -++ * notice, this list of conditions and the following disclaimer. -++ * 2. Redistributions in binary form must reproduce the above copyright -++ * notice, this list of conditions and the following disclaimer in the -++ * documentation and/or other materials provided with the distribution. -++ * 3. Neither the name of the author nor the names of other contributors -++ * may be used to endorse or promote products derived from this software -++ * without specific prior written permission. -++ * -++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -++ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++/* -++ * MEMGETINFO -++ */ -++static int getmeminfo (int fd,struct mtd_info_user *mtd) -++{ -++ return (ioctl (fd,MEMGETINFO,mtd)); -++} -++ -++/* -++ * MEMERASE -++ */ -++static int memerase (int fd,struct erase_info_user *erase) -++{ -++ return (ioctl (fd,MEMERASE,erase)); -++} -++ -++/* -++ * MEMGETREGIONCOUNT -++ * MEMGETREGIONINFO -++ */ -++static int getregions (int fd,struct region_info_user *regions,int *n) -++{ -++ int i,err; -++ err = ioctl (fd,MEMGETREGIONCOUNT,n); -++ if (err) return (err); -++ for (i = 0; i < *n; i++) -++ { -++ regions[i].regionindex = i; -++ err = ioctl (fd,MEMGETREGIONINFO,®ions[i]); -++ if (err) return (err); -++ } -++ return (0); -++} -++ -++int erase_flash (int fd,u_int32_t offset,u_int32_t bytes) -++{ -++ int err; -++ struct erase_info_user erase; -++ erase.start = offset; -++ erase.length = bytes; -++ err = memerase (fd,&erase); -++ if (err < 0) -++ { -++ perror ("MEMERASE"); -++ return (1); -++ } -++ fprintf (stderr,"Erased %d bytes from address 0x%.8x in flash\n",bytes,offset); -++ return (0); -++} -++ -++void printsize (u_int32_t x) -++{ -++ int i; -++ static const char *flags = "KMGT"; -++ printf ("%u ",x); -++ for (i = 0; x >= 1024 && flags[i] != '\0'; i++) x /= 1024; -++ i--; -++ if (i >= 0) printf ("(%u%c)",x,flags[i]); -++} -++ -++int flash_to_file (int fd,u_int32_t offset,size_t len,const char *filename) -++{ -++ u_int8_t *buf = NULL; -++ int outfd,err; -++ int size = len * sizeof (u_int8_t); -++ int n = len; -++ -++ if (offset != lseek (fd,offset,SEEK_SET)) -++ { -++ perror ("lseek()"); -++ goto err0; -++ } -++ outfd = creat (filename,O_WRONLY); -++ if (outfd < 0) -++ { -++ perror ("creat()"); -++ goto err1; -++ } -++ -++retry: -++ if ((buf = (u_int8_t *) malloc (size)) == NULL) -++ { -++#define BUF_SIZE (64 * 1024 * sizeof (u_int8_t)) -++ fprintf (stderr, "%s: malloc(%#x)\n", __FUNCTION__, size); -++ if (size != BUF_SIZE) { -++ size = BUF_SIZE; -++ fprintf (stderr, "%s: trying buffer size %#x\n", __FUNCTION__, size); -++ goto retry; -++ } -++ perror ("malloc()"); -++ goto err0; -++ } -++ do { -++ if (n <= size) -++ size = n; -++ err = read (fd,buf,size); -++ if (err < 0) -++ { -++ fprintf (stderr, "%s: read, size %#x, n %#x\n", __FUNCTION__, size, n); -++ perror ("read()"); -++ goto err2; -++ } -++ err = write (outfd,buf,size); -++ if (err < 0) -++ { -++ fprintf (stderr, "%s: write, size %#x, n %#x\n", __FUNCTION__, size, n); -++ perror ("write()"); -++ goto err2; -++ } -++ if (err != size) -++ { -++ fprintf (stderr,"Couldn't copy entire buffer to %s. (%d/%d bytes copied)\n",filename,err,size); -++ goto err2; -++ } -++ n -= size; -++ } while (n > 0); -++ -++ if (buf != NULL) -++ free (buf); -++ close (outfd); -++ printf ("Copied %d bytes from address 0x%.8x in flash to %s\n",len,offset,filename); -++ return (0); -++ -++err2: -++ close (outfd); -++err1: -++ if (buf != NULL) -++ free (buf); -++err0: -++ return (1); -++} -++ -++int file_to_flash (int fd,u_int32_t offset,u_int32_t len,const char *filename) -++{ -++ u_int8_t *buf = NULL; -++ FILE *fp; -++ int err; -++ int size = len * sizeof (u_int8_t); -++ int n = len; -++ -++ if (offset != lseek (fd,offset,SEEK_SET)) -++ { -++ perror ("lseek()"); -++ return (1); -++ } -++ if ((fp = fopen (filename,"r")) == NULL) -++ { -++ perror ("fopen()"); -++ return (1); -++ } -++retry: -++ if ((buf = (u_int8_t *) malloc (size)) == NULL) -++ { -++ fprintf (stderr, "%s: malloc(%#x) failed\n", __FUNCTION__, size); -++ if (size != BUF_SIZE) { -++ size = BUF_SIZE; -++ fprintf (stderr, "%s: trying buffer size %#x\n", __FUNCTION__, size); -++ goto retry; -++ } -++ perror ("malloc()"); -++ fclose (fp); -++ return (1); -++ } -++ do { -++ if (n <= size) -++ size = n; -++ if (fread (buf,size,1,fp) != 1 || ferror (fp)) -++ { -++ fprintf (stderr, "%s: fread, size %#x, n %#x\n", __FUNCTION__, size, n); -++ perror ("fread()"); -++ free (buf); -++ fclose (fp); -++ return (1); -++ } -++ err = write (fd,buf,size); -++ if (err < 0) -++ { -++ fprintf (stderr, "%s: write, size %#x, n %#x\n", __FUNCTION__, size, n); -++ perror ("write()"); -++ free (buf); -++ fclose (fp); -++ return (1); -++ } -++ n -= size; -++ } while (n > 0); -++ -++ if (buf != NULL) -++ free (buf); -++ fclose (fp); -++ printf ("Copied %d bytes from %s to address 0x%.8x in flash\n",len,filename,offset); -++ return (0); -++} -++ -++int showinfo (int fd) -++{ -++ int i,err,n; -++ struct mtd_info_user mtd; -++ static struct region_info_user region[1024]; -++ -++ err = getmeminfo (fd,&mtd); -++ if (err < 0) -++ { -++ perror ("MEMGETINFO"); -++ return (1); -++ } -++ -++ err = getregions (fd,region,&n); -++ if (err < 0) -++ { -++ perror ("MEMGETREGIONCOUNT"); -++ return (1); -++ } -++ -++ printf ("mtd.type = "); -++ switch (mtd.type) -++ { -++ case MTD_ABSENT: -++ printf ("MTD_ABSENT"); -++ break; -++ case MTD_RAM: -++ printf ("MTD_RAM"); -++ break; -++ case MTD_ROM: -++ printf ("MTD_ROM"); -++ break; -++ case MTD_NORFLASH: -++ printf ("MTD_NORFLASH"); -++ break; -++ case MTD_NANDFLASH: -++ printf ("MTD_NANDFLASH"); -++ break; -++ case MTD_DATAFLASH: -++ printf ("MTD_DATAFLASH"); -++ break; -++ case MTD_UBIVOLUME: -++ printf ("MTD_UBIVOLUME"); -++ default: -++ printf ("(unknown type - new MTD API maybe?)"); -++ } -++ -++ printf ("\nmtd.flags = "); -++ if (mtd.flags == MTD_CAP_ROM) -++ printf ("MTD_CAP_ROM"); -++ else if (mtd.flags == MTD_CAP_RAM) -++ printf ("MTD_CAP_RAM"); -++ else if (mtd.flags == MTD_CAP_NORFLASH) -++ printf ("MTD_CAP_NORFLASH"); -++ else if (mtd.flags == MTD_CAP_NANDFLASH) -++ printf ("MTD_CAP_NANDFLASH"); -++ else if (mtd.flags == MTD_WRITEABLE) -++ printf ("MTD_WRITEABLE"); -++ else -++ { -++ int first = 1; -++ static struct -++ { -++ const char *name; -++ int value; -++ } flags[] = -++ { -++ { "MTD_WRITEABLE", MTD_WRITEABLE }, -++ { "MTD_BIT_WRITEABLE", MTD_BIT_WRITEABLE }, -++ { "MTD_NO_ERASE", MTD_NO_ERASE }, -++ { "MTD_STUPID_LOCK", MTD_STUPID_LOCK }, -++ { NULL, -1 } -++ }; -++ for (i = 0; flags[i].name != NULL; i++) -++ if (mtd.flags & flags[i].value) -++ { -++ if (first) -++ { -++ printf (flags[i].name); -++ first = 0; -++ } -++ else printf (" | %s",flags[i].name); -++ } -++ } -++ -++ printf ("\nmtd.size = "); -++ printsize (mtd.size); -++ -++ printf ("\nmtd.erasesize = "); -++ printsize (mtd.erasesize); -++ -++ printf ("\nmtd.writesize = "); -++ printsize (mtd.writesize); -++ -++ printf ("\nmtd.oobsize = "); -++ printsize (mtd.oobsize); -++ -++ printf ("\n" -++ "regions = %d\n" -++ "\n", -++ n); -++ -++ for (i = 0; i < n; i++) -++ { -++ printf ("region[%d].offset = 0x%.8x\n" -++ "region[%d].erasesize = ", -++ i,region[i].offset,i); -++ printsize (region[i].erasesize); -++ printf ("\nregion[%d].numblocks = %d\n" -++ "region[%d].regionindex = %d\n", -++ i,region[i].numblocks, -++ i,region[i].regionindex); -++ } -++ return (0); -++} -++ -++void showusage (const char *progname) -++{ -++ fprintf (stderr, -++ "usage: %s info \n" -++ " %s read \n" -++ " %s write \n" -++ " %s erase \n", -++ progname, -++ progname, -++ progname, -++ progname); -++ exit (1); -++} -++ -++#define OPT_INFO 1 -++#define OPT_READ 2 -++#define OPT_WRITE 3 -++#define OPT_ERASE 4 -++ -++int main (int argc,char *argv[]) -++{ -++ const char *progname; -++ int err = 0,fd,option = OPT_INFO; -++ int open_flag; -++ (progname = strrchr (argv[0],'/')) ? progname++ : (progname = argv[0]); -++ -++ /* parse command-line options */ -++ if (argc == 3 && !strcmp (argv[1],"info")) -++ option = OPT_INFO; -++ else if (argc == 6 && !strcmp (argv[1],"read")) -++ option = OPT_READ; -++ else if (argc == 6 && !strcmp (argv[1],"write")) -++ option = OPT_WRITE; -++ else if (argc == 5 && !strcmp (argv[1],"erase")) -++ option = OPT_ERASE; -++ else -++ showusage (progname); -++ -++ /* open device */ -++ open_flag = (option==OPT_INFO || option==OPT_READ) ? O_RDONLY : O_RDWR; -++ if ((fd = open (argv[2],O_SYNC | open_flag)) < 0) -++ { -++ perror ("open()"); -++ exit (1); -++ } -++ -++ switch (option) -++ { -++ case OPT_INFO: -++ showinfo (fd); -++ break; -++ case OPT_READ: -++ err = flash_to_file (fd,strtol (argv[3],NULL,0),strtol (argv[4],NULL,0),argv[5]); -++ break; -++ case OPT_WRITE: -++ err = file_to_flash (fd,strtol (argv[3],NULL,0),strtol (argv[4],NULL,0),argv[5]); -++ break; -++ case OPT_ERASE: -++ err = erase_flash (fd,strtol (argv[3],NULL,0),strtol (argv[4],NULL,0)); -++ break; -++ } -++ -++ /* close device */ -++ if (close (fd) < 0) -++ perror ("close()"); -++ -++ exit (err); -++} -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/nanddump.c linux-2.6.24.7/drivers/mtd/mtd-utils/nanddump.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/nanddump.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/nanddump.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,403 @@ -++/* -++ * nanddump.c -++ * -++ * Copyright (C) 2000 David Woodhouse (dwmw2@infradead.org) -++ * Steven J. Hill (sjhill@realitydiluted.com) -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ * Overview: -++ * This utility dumps the contents of raw NAND chips or NAND -++ * chips contained in DoC devices. -++ */ -++ -++#define _GNU_SOURCE -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#define PROGRAM "nanddump" -++#define VERSION "$Revision: 1.1.1.1 $" -++ -++struct nand_oobinfo none_oobinfo = { -++ .useecc = MTD_NANDECC_OFF, -++}; -++ -++void display_help (void) -++{ -++ printf("Usage: nanddump [OPTIONS] MTD-device\n" -++ "Dumps the contents of a nand mtd partition.\n" -++ "\n" -++ " --help display this help and exit\n" -++ " --version output version information and exit\n" -++ "-f file --file=file dump to file\n" -++ "-i --ignoreerrors ignore errors\n" -++ "-l length --length=length length\n" -++ "-n --noecc read without error correction\n" -++ "-o --omitoob omit oob data\n" -++ "-b --omitbad omit bad blocks from the dump\n" -++ "-p --prettyprint print nice (hexdump)\n" -++ "-s addr --startaddress=addr start address\n"); -++ exit(0); -++} -++ -++void display_version (void) -++{ -++ printf(PROGRAM " " VERSION "\n" -++ "\n" -++ PROGRAM " comes with NO WARRANTY\n" -++ "to the extent permitted by law.\n" -++ "\n" -++ "You may redistribute copies of " PROGRAM "\n" -++ "under the terms of the GNU General Public Licence.\n" -++ "See the file `COPYING' for more information.\n"); -++ exit(0); -++} -++ -++// Option variables -++ -++int ignoreerrors; // ignore errors -++int pretty_print; // print nice in ascii -++int noecc; // don't error correct -++int omitoob; // omit oob data -++unsigned long start_addr; // start address -++unsigned long length; // dump length -++char *mtddev; // mtd device name -++char *dumpfile; // dump file name -++int omitbad; -++ -++void process_options (int argc, char *argv[]) -++{ -++ int error = 0; -++ -++ for (;;) { -++ int option_index = 0; -++ static const char *short_options = "bs:f:il:opn"; -++ static const struct option long_options[] = { -++ {"help", no_argument, 0, 0}, -++ {"version", no_argument, 0, 0}, -++ {"file", required_argument, 0, 'f'}, -++ {"ignoreerrors", no_argument, 0, 'i'}, -++ {"prettyprint", no_argument, 0, 'p'}, -++ {"omitoob", no_argument, 0, 'o'}, -++ {"omitbad", no_argument, 0, 'b'}, -++ {"startaddress", required_argument, 0, 's'}, -++ {"length", required_argument, 0, 'l'}, -++ {"noecc", no_argument, 0, 'n'}, -++ {0, 0, 0, 0}, -++ }; -++ -++ int c = getopt_long(argc, argv, short_options, -++ long_options, &option_index); -++ if (c == EOF) { -++ break; -++ } -++ -++ switch (c) { -++ case 0: -++ switch (option_index) { -++ case 0: -++ display_help(); -++ break; -++ case 1: -++ display_version(); -++ break; -++ } -++ break; -++ case 'b': -++ omitbad = 1; -++ break; -++ case 's': -++ start_addr = strtol(optarg, NULL, 0); -++ break; -++ case 'f': -++ if (!(dumpfile = strdup(optarg))) { -++ perror("stddup"); -++ exit(1); -++ } -++ break; -++ case 'i': -++ ignoreerrors = 1; -++ break; -++ case 'l': -++ length = strtol(optarg, NULL, 0); -++ break; -++ case 'o': -++ omitoob = 1; -++ break; -++ case 'p': -++ pretty_print = 1; -++ break; -++ case 'n': -++ noecc = 1; -++ break; -++ case '?': -++ error = 1; -++ break; -++ } -++ } -++ -++ if ((argc - optind) != 1 || error) -++ display_help (); -++ -++ mtddev = argv[optind]; -++} -++ -++/* -++ * Buffers for reading data from flash -++ */ -++unsigned char readbuf[8192]; -++unsigned char oobbuf[256]; -++ -++/* -++ * Main program -++ */ -++int main(int argc, char **argv) -++{ -++ unsigned long ofs, end_addr = 0; -++ unsigned long long blockstart = 1; -++ int ret, i, fd, ofd, bs, badblock = 0; -++ struct mtd_oob_buf oob = {0, 16, oobbuf}; -++ mtd_info_t meminfo; -++ char pretty_buf[80]; -++ int oobinfochanged = 0 ; -++ struct nand_oobinfo old_oobinfo; -++ struct mtd_ecc_stats stat1, stat2; -++ int eccstats = 0; -++ -++ process_options(argc, argv); -++ -++ /* Open MTD device */ -++ if ((fd = open(mtddev, O_RDONLY)) == -1) { -++ perror("open flash"); -++ exit (1); -++ } -++ -++ /* Fill in MTD device capability structure */ -++ if (ioctl(fd, MEMGETINFO, &meminfo) != 0) { -++ perror("MEMGETINFO"); -++ close(fd); -++ exit (1); -++ } -++ -++ /* Make sure device page sizes are valid */ -++ if (!(meminfo.oobsize == 256 && meminfo.writesize == 8192) && -++ !(meminfo.oobsize == 128 && meminfo.writesize == 4096) && -++ !(meminfo.oobsize == 64 && meminfo.writesize == 2048) && -++ !(meminfo.oobsize == 32 && meminfo.writesize == 1024) && -++ !(meminfo.oobsize == 16 && meminfo.writesize == 512) && -++ !(meminfo.oobsize == 8 && meminfo.writesize == 256)) { -++ fprintf(stderr, "Unknown flash (not normal NAND)\n"); -++ close(fd); -++ exit(1); -++ } -++ /* Read the real oob length */ -++ oob.length = meminfo.oobsize; -++ -++ if (noecc) { -++ ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW); -++ if (ret == 0) { -++ oobinfochanged = 2; -++ } else { -++ switch (errno) { -++ case ENOTTY: -++ if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) { -++ perror ("MEMGETOOBSEL"); -++ close (fd); -++ exit (1); -++ } -++ if (ioctl (fd, MEMSETOOBSEL, &none_oobinfo) != 0) { -++ perror ("MEMSETOOBSEL"); -++ close (fd); -++ exit (1); -++ } -++ oobinfochanged = 1; -++ break; -++ default: -++ perror ("MTDFILEMODE"); -++ close (fd); -++ exit (1); -++ } -++ } -++ } else { -++ -++ /* check if we can read ecc stats */ -++ if (!ioctl(fd, ECCGETSTATS, &stat1)) { -++ eccstats = 1; -++ fprintf(stderr, "ECC failed: %d\n", stat1.failed); -++ fprintf(stderr, "ECC corrected: %d\n", stat1.corrected); -++ fprintf(stderr, "Number of bad blocks: %d\n", stat1.badblocks); -++ fprintf(stderr, "Number of bbt blocks: %d\n", stat1.bbtblocks); -++ } else -++ perror("No ECC status information available"); -++ } -++ -++ /* Open output file for writing. If file name is "-", write to standard -++ * output. */ -++ if (!dumpfile) { -++ ofd = STDOUT_FILENO; -++ } else if ((ofd = open(dumpfile, O_WRONLY | O_TRUNC | O_CREAT, 0644))== -1) { -++ perror ("open outfile"); -++ close(fd); -++ exit(1); -++ } -++ -++ /* Initialize start/end addresses and block size */ -++ if (length) -++ end_addr = start_addr + length; -++ if (!length || end_addr > meminfo.size) -++ end_addr = meminfo.size; -++ -++ bs = meminfo.writesize; -++ -++ /* Print informative message */ -++ fprintf(stderr, "Block size %u, page size %u, OOB size %u\n", -++ meminfo.erasesize, meminfo.writesize, meminfo.oobsize); -++ fprintf(stderr, -++ "Dumping data starting at 0x%08x and ending at 0x%08x...\n", -++ (unsigned int) start_addr, (unsigned int) end_addr); -++ -++ /* Dump the flash contents */ -++ for (ofs = start_addr; ofs < end_addr ; ofs+=bs) { -++ -++ // new eraseblock , check for bad block -++ if (blockstart != (ofs & (~meminfo.erasesize + 1))) { -++ blockstart = ofs & (~meminfo.erasesize + 1); -++ if ((badblock = ioctl(fd, MEMGETBADBLOCK, &blockstart)) < 0) { -++ perror("ioctl(MEMGETBADBLOCK)"); -++ goto closeall; -++ } -++ } -++ -++ if (badblock) { -++ if (omitbad) -++ continue; -++ memset (readbuf, 0xff, bs); -++ } else { -++ /* Read page data and exit on failure */ -++ if (pread(fd, readbuf, bs, ofs) != bs) { -++ perror("pread"); -++ goto closeall; -++ } -++ } -++ -++ /* ECC stats available ? */ -++ if (eccstats) { -++ if (ioctl(fd, ECCGETSTATS, &stat2)) { -++ perror("ioctl(ECCGETSTATS)"); -++ goto closeall; -++ } -++ if (stat1.failed != stat2.failed) -++ fprintf(stderr, "ECC: %d uncorrectable bitflip(s)" -++ " at offset 0x%08lx\n", -++ stat2.failed - stat1.failed, ofs); -++ if (stat1.corrected != stat2.corrected) -++ fprintf(stderr, "ECC: %d corrected bitflip(s) at" -++ " offset 0x%08lx\n", -++ stat2.corrected - stat1.corrected, ofs); -++ stat1 = stat2; -++ } -++ -++ /* Write out page data */ -++ if (pretty_print) { -++ for (i = 0; i < bs; i += 16) { -++ sprintf(pretty_buf, -++ "0x%08x: %02x %02x %02x %02x %02x %02x %02x " -++ "%02x %02x %02x %02x %02x %02x %02x %02x %02x\n", -++ (unsigned int) (ofs + i), readbuf[i], -++ readbuf[i+1], readbuf[i+2], -++ readbuf[i+3], readbuf[i+4], -++ readbuf[i+5], readbuf[i+6], -++ readbuf[i+7], readbuf[i+8], -++ readbuf[i+9], readbuf[i+10], -++ readbuf[i+11], readbuf[i+12], -++ readbuf[i+13], readbuf[i+14], -++ readbuf[i+15]); -++ write(ofd, pretty_buf, 60); -++ } -++ } else -++ write(ofd, readbuf, bs); -++ -++ -++ -++ if (omitoob) -++ continue; -++ -++ if (badblock) { -++ memset (readbuf, 0xff, meminfo.oobsize); -++ } else { -++ /* Read OOB data and exit on failure */ -++ oob.start = ofs; -++ if (ioctl(fd, MEMREADOOB, &oob) != 0) { -++ perror("ioctl(MEMREADOOB)"); -++ goto closeall; -++ } -++ } -++ -++ /* Write out OOB data */ -++ if (pretty_print) { -++ if (meminfo.oobsize < 16) { -++ sprintf(pretty_buf, " OOB Data: %02x %02x %02x %02x %02x %02x " -++ "%02x %02x\n", -++ oobbuf[0], oobbuf[1], oobbuf[2], -++ oobbuf[3], oobbuf[4], oobbuf[5], -++ oobbuf[6], oobbuf[7]); -++ write(ofd, pretty_buf, 48); -++ continue; -++ } -++ -++ for (i = 0; i < meminfo.oobsize; i += 16) { -++ sprintf(pretty_buf, " OOB Data: %02x %02x %02x %02x %02x %02x " -++ "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", -++ oobbuf[i], oobbuf[i+1], oobbuf[i+2], -++ oobbuf[i+3], oobbuf[i+4], oobbuf[i+5], -++ oobbuf[i+6], oobbuf[i+7], oobbuf[i+8], -++ oobbuf[i+9], oobbuf[i+10], oobbuf[i+11], -++ oobbuf[i+12], oobbuf[i+13], oobbuf[i+14], -++ oobbuf[i+15]); -++ write(ofd, pretty_buf, 60); -++ } -++ } else -++ write(ofd, oobbuf, meminfo.oobsize); -++ } -++ -++ /* reset oobinfo */ -++ if (oobinfochanged == 1) { -++ if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) { -++ perror ("MEMSETOOBSEL"); -++ close(fd); -++ close(ofd); -++ return 1; -++ } -++ } -++ /* Close the output file and MTD device */ -++ close(fd); -++ close(ofd); -++ -++ /* Exit happy */ -++ return 0; -++ -++closeall: -++ /* The new mode change is per file descriptor ! */ -++ if (oobinfochanged == 1) { -++ if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) { -++ perror ("MEMSETOOBSEL"); -++ } -++ } -++ close(fd); -++ close(ofd); -++ exit(1); -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/nanddump_vfat.c linux-2.6.24.7/drivers/mtd/mtd-utils/nanddump_vfat.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/nanddump_vfat.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/nanddump_vfat.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,365 @@ -++/* -++ * nanddump.c -++ * -++ * Copyright (C) 2000 David Woodhouse (dwmw2@infradead.org) -++ * Steven J. Hill (sjhill@realitydiluted.com) -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ * Overview: -++ * This utility dumps the contents of raw NAND chips or NAND -++ * chips contained in DoC devices. -++ */ -++ -++#define _GNU_SOURCE -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#define PROGRAM "nanddump" -++#define VERSION "$Revision: 1.1.1.1 $" -++ -++struct nand_oobinfo none_oobinfo = { -++ .useecc = MTD_NANDECC_OFF, -++}; -++ -++void display_help (void) -++{ -++ printf("Usage: nanddump [OPTIONS] MTD-device\n" -++ "Dumps the contents of a nand mtd partition.\n" -++ "\n" -++ " --help display this help and exit\n" -++ " --version output version information and exit\n" -++ "-f file --file=file dump to file\n" -++ "-i --ignoreerrors ignore errors\n" -++ "-l length --length=length length\n" -++ "-n --noecc read without error correction\n" -++ "-o --omitoob omit oob data\n" -++ "-b --omitbad omit bad blocks from the dump\n" -++ "-p --prettyprint print nice (hexdump)\n" -++ "-s addr --startaddress=addr start address\n"); -++ exit(0); -++} -++ -++void display_version (void) -++{ -++ printf(PROGRAM " " VERSION "\n" -++ "\n" -++ PROGRAM " comes with NO WARRANTY\n" -++ "to the extent permitted by law.\n" -++ "\n" -++ "You may redistribute copies of " PROGRAM "\n" -++ "under the terms of the GNU General Public Licence.\n" -++ "See the file `COPYING' for more information.\n"); -++ exit(0); -++} -++ -++// Option variables -++ -++int ignoreerrors; // ignore errors -++int pretty_print; // print nice in ascii -++int noecc; // don't error correct -++int omitoob; // omit oob data -++unsigned long start_addr; // start address -++unsigned long length; // dump length -++char *mtddev; // mtd device name -++char *dumpfile; // dump file name -++int omitbad; -++ -++void process_options (int argc, char *argv[]) -++{ -++ int error = 0; -++ -++ for (;;) { -++ int option_index = 0; -++ static const char *short_options = "bs:f:il:opn"; -++ static const struct option long_options[] = { -++ {"help", no_argument, 0, 0}, -++ {"version", no_argument, 0, 0}, -++ {"file", required_argument, 0, 'f'}, -++ {"ignoreerrors", no_argument, 0, 'i'}, -++ {"prettyprint", no_argument, 0, 'p'}, -++ {"omitoob", no_argument, 0, 'o'}, -++ {"omitbad", no_argument, 0, 'b'}, -++ {"startaddress", required_argument, 0, 's'}, -++ {"length", required_argument, 0, 'l'}, -++ {"noecc", no_argument, 0, 'n'}, -++ {0, 0, 0, 0}, -++ }; -++ -++ int c = getopt_long(argc, argv, short_options, -++ long_options, &option_index); -++ if (c == EOF) { -++ break; -++ } -++ -++ switch (c) { -++ case 0: -++ switch (option_index) { -++ case 0: -++ display_help(); -++ break; -++ case 1: -++ display_version(); -++ break; -++ } -++ break; -++ case 'b': -++ omitbad = 1; -++ break; -++ case 's': -++ start_addr = strtol(optarg, NULL, 0); -++ break; -++ case 'f': -++ if (!(dumpfile = strdup(optarg))) { -++ perror("stddup"); -++ exit(1); -++ } -++ break; -++ case 'i': -++ ignoreerrors = 1; -++ break; -++ case 'l': -++ length = strtol(optarg, NULL, 0); -++ break; -++ case 'o': -++ omitoob = 1; -++ break; -++ case 'p': -++ pretty_print = 1; -++ break; -++ case 'n': -++ noecc = 1; -++ break; -++ case '?': -++ error = 1; -++ break; -++ } -++ } -++ -++ if ((argc - optind) != 1 || error) -++ display_help (); -++ -++ mtddev = argv[optind]; -++} -++ -++/* -++ * Buffers for reading data from flash -++ */ -++unsigned char readbuf[8192]; -++unsigned char oobbuf[256]; -++ -++/* -++ * Main program -++ */ -++int main(int argc, char **argv) -++{ -++ unsigned long ofs, end_addr = 0; -++ unsigned long long blockstart = 1; -++ int ret, fd, ofd, bs, badblock = 0; -++ struct mtd_oob_buf oob = {0, 16, oobbuf}; -++ mtd_info_t meminfo; -++ int oobinfochanged = 0 ; -++ struct nand_oobinfo old_oobinfo; -++ struct mtd_ecc_stats stat1, stat2; -++ int eccstats = 0; -++ -++ process_options(argc, argv); -++ -++ /* Open MTD device */ -++ if ((fd = open(mtddev, O_RDONLY)) == -1) { -++ perror("open flash"); -++ exit (1); -++ } -++ -++ /* Fill in MTD device capability structure */ -++ if (ioctl(fd, MEMGETINFO, &meminfo) != 0) { -++ perror("MEMGETINFO"); -++ close(fd); -++ exit (1); -++ } -++ -++ /* Make sure device page sizes are valid */ -++ if (!(meminfo.oobsize == 256 && meminfo.writesize == 8192) && -++ !(meminfo.oobsize == 128 && meminfo.writesize == 4096) && -++ !(meminfo.oobsize == 64 && meminfo.writesize == 2048) && -++ !(meminfo.oobsize == 32 && meminfo.writesize == 1024) && -++ !(meminfo.oobsize == 16 && meminfo.writesize == 512) && -++ !(meminfo.oobsize == 8 && meminfo.writesize == 256)) { -++ fprintf(stderr, "Unknown flash (not normal NAND)\n"); -++ close(fd); -++ exit(1); -++ } -++ /* Read the real oob length */ -++ oob.length = meminfo.oobsize; -++ -++ if (noecc) { -++ ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW); -++ if (ret == 0) { -++ oobinfochanged = 2; -++ } else { -++ switch (errno) { -++ case ENOTTY: -++ if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) { -++ perror ("MEMGETOOBSEL"); -++ close (fd); -++ exit (1); -++ } -++ if (ioctl (fd, MEMSETOOBSEL, &none_oobinfo) != 0) { -++ perror ("MEMSETOOBSEL"); -++ close (fd); -++ exit (1); -++ } -++ oobinfochanged = 1; -++ break; -++ default: -++ perror ("MTDFILEMODE"); -++ close (fd); -++ exit (1); -++ } -++ } -++ } else { -++ -++ /* check if we can read ecc stats */ -++ if (!ioctl(fd, ECCGETSTATS, &stat1)) { -++ eccstats = 1; -++ fprintf(stderr, "ECC failed: %d\n", stat1.failed); -++ fprintf(stderr, "ECC corrected: %d\n", stat1.corrected); -++ fprintf(stderr, "Number of bad blocks: %d\n", stat1.badblocks); -++ fprintf(stderr, "Number of bbt blocks: %d\n", stat1.bbtblocks); -++ } else -++ perror("No ECC status information available"); -++ } -++ -++ /* Open output file for writing. If file name is "-", write to standard -++ * output. */ -++ if (!dumpfile) { -++ ofd = STDOUT_FILENO; -++ } else if ((ofd = open(dumpfile, O_WRONLY | O_TRUNC | O_CREAT, 0644))== -1) { -++ perror ("open outfile"); -++ close(fd); -++ exit(1); -++ } -++ -++ /* Initialize start/end addresses and block size */ -++ if (length) -++ end_addr = start_addr + length; -++ if (!length || end_addr > meminfo.size) -++ end_addr = meminfo.size; -++ -++ bs = meminfo.writesize; -++ -++ /* Print informative message */ -++ fprintf(stderr, "Block size %u, page size %u, OOB size %u\n", -++ meminfo.erasesize, meminfo.writesize, meminfo.oobsize); -++ fprintf(stderr, -++ "Dumping data starting at 0x%08x and ending at 0x%08x...\n", -++ (unsigned int) start_addr, (unsigned int) end_addr); -++ -++ /* Dump the flash contents */ -++ for (ofs = start_addr; ofs < end_addr ; ofs+=bs) { -++ -++ // new eraseblock , check for bad block -++ if (blockstart != (ofs & (~meminfo.erasesize + 1))) { -++ blockstart = ofs & (~meminfo.erasesize + 1); -++ if ((badblock = ioctl(fd, MEMGETBADBLOCK, &blockstart)) < 0) { -++ perror("ioctl(MEMGETBADBLOCK)"); -++ goto closeall; -++ } -++ } -++ -++ if (badblock) { -++ //skip bad block; -++ ofs += meminfo.erasesize - bs; -++ continue; -++ } else { -++ /* Read page data and exit on failure */ -++ if (pread(fd, readbuf, bs, ofs) != bs) { -++ perror("pread"); -++ goto closeall; -++ } -++ } -++ -++ /* ECC stats available ? */ -++ if (eccstats) { -++ if (ioctl(fd, ECCGETSTATS, &stat2)) { -++ perror("ioctl(ECCGETSTATS)"); -++ goto closeall; -++ } -++ if (stat1.failed != stat2.failed) -++ fprintf(stderr, "ECC: %d uncorrectable bitflip(s)" -++ " at offset 0x%08lx\n", -++ stat2.failed - stat1.failed, ofs); -++ if (stat1.corrected != stat2.corrected) -++ fprintf(stderr, "ECC: %d corrected bitflip(s) at" -++ " offset 0x%08lx\n", -++ stat2.corrected - stat1.corrected, ofs); -++ stat1 = stat2; -++ } -++ -++ if (badblock) { -++ memset (readbuf, 0xff, meminfo.oobsize); -++ } else { -++ /* Read OOB data and exit on failure */ -++ oob.start = ofs; -++ if (ioctl(fd, MEMREADOOB, &oob) != 0) { -++ perror("ioctl(MEMREADOOB)"); -++ goto closeall; -++ } -++ if(oobbuf[2]==0xff && oobbuf[3]==0xff && oobbuf[4]==0xff && oobbuf[5]==0xff){ -++ //skip free block; -++ ofs += meminfo.erasesize - bs; -++ continue; -++ } -++ } -++ -++ /* Write out page data */ -++ write(ofd, readbuf, bs); -++ -++ if (omitoob) -++ continue; -++ -++ /* Write out OOB data */ -++ write(ofd, oobbuf, meminfo.oobsize); -++ } -++ -++ /* reset oobinfo */ -++ if (oobinfochanged == 1) { -++ if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) { -++ perror ("MEMSETOOBSEL"); -++ close(fd); -++ close(ofd); -++ return 1; -++ } -++ } -++ /* Close the output file and MTD device */ -++ close(fd); -++ close(ofd); -++ -++ /* Exit happy */ -++ return 0; -++ -++closeall: -++ /* The new mode change is per file descriptor ! */ -++ if (oobinfochanged == 1) { -++ if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) { -++ perror ("MEMSETOOBSEL"); -++ } -++ } -++ close(fd); -++ close(ofd); -++ exit(1); -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/nandtest.c linux-2.6.24.7/drivers/mtd/mtd-utils/nandtest.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/nandtest.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/nandtest.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,284 @@ -++#define _GNU_SOURCE -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include "mtd/mtd-user.h" -++ -++void usage(void) -++{ -++ fprintf(stderr, "usage: nandtest [OPTIONS] \n\n" -++ " -h, --help Display this help output\n" -++ " -m, --markbad Mark blocks bad if they appear so\n" -++ " -s, --seed Supply random seed\n" -++ " -p, --passes Number of passes\n" -++ " -o, --offset Start offset on flash\n" -++ " -l, --length Length of flash to test\n" -++ " -k, --keep Restore existing contents after test\n" -++ "Warning: it is just used for SLC NAND!\n"); -++ -++ exit(1); -++} -++ -++struct mtd_info_user meminfo; -++struct mtd_ecc_stats oldstats, newstats; -++int fd; -++int markbad=0; -++int seed; -++ -++int erase_and_write(loff_mtd_t ofs, unsigned char *data, unsigned char *rbuf) -++{ -++ struct erase_info_user er; -++ ssize_t len; -++ int i; -++ -++ printf("\r%09llx: erasing... ", (loff_mtd_t)ofs); -++ fflush(stdout); -++ -++ er.start = ofs; -++ er.length = meminfo.erasesize; -++ -++ if (ioctl(fd, MEMERASE, &er)) { -++ perror("MEMERASE"); -++ if (markbad) { -++ printf("Mark block bad at %09llx\n", (loff_mtd_t)ofs); -++ ioctl(fd, MEMSETBADBLOCK, &ofs); -++ } -++ return 1; -++ } -++ -++ printf("\r%09llx: writing...", (loff_mtd_t)ofs); -++ fflush(stdout); -++ -++ len = pwrite(fd, data, meminfo.erasesize, ofs); -++ if (len < 0) { -++ printf("\n"); -++ perror("write"); -++ if (markbad) { -++ printf("Mark block bad at %09llx\n", (loff_mtd_t)ofs); -++ ioctl(fd, MEMSETBADBLOCK, &ofs); -++ } -++ return 1; -++ } -++ if (len < meminfo.erasesize) { -++ printf("\n"); -++ fprintf(stderr, "Short write (%d bytes)\n", len); -++ exit(1); -++ } -++ -++ printf("\r%09llx: reading...", (loff_mtd_t)ofs); -++ fflush(stdout); -++ -++ len = pread(fd, rbuf, meminfo.erasesize, ofs); -++ if (len < meminfo.erasesize) { -++ printf("\n"); -++ if (len) -++ fprintf(stderr, "Short read (%d bytes)\n", len); -++ else -++ perror("read"); -++ exit(1); -++ } -++ -++ if (ioctl(fd, ECCGETSTATS, &newstats)) { -++ printf("\n"); -++ perror("ECCGETSTATS"); -++ close(fd); -++ exit(1); -++ } -++ -++ if (newstats.corrected > oldstats.corrected) { -++ printf("\nECC corrected at %09llx\n", (loff_mtd_t) ofs); -++ oldstats.corrected = newstats.corrected; -++ } -++ if (newstats.failed > oldstats.failed) { -++ printf("\nECC failed at %09llx\n", (loff_mtd_t) ofs); -++ oldstats.corrected = newstats.corrected; -++ } -++ if (len < meminfo.erasesize) -++ exit(1); -++ -++ printf("\r%09llx: checking...", (loff_mtd_t)ofs); -++ fflush(stdout); -++ -++ if (memcmp(data, rbuf, meminfo.erasesize)) { -++ printf("\n"); -++ fprintf(stderr, "compare failed. seed %d\n", seed); -++ for (i=0; i meminfo.size) { -++ fprintf(stderr, "Length %09llx + offset %09llx exceeds device size %09llx\n", -++ length, offset, meminfo.size); -++ exit(1); -++ } -++ -++ wbuf = malloc(meminfo.erasesize * 3); -++ if (!wbuf) { -++ fprintf(stderr, "Could not allocate %d bytes for buffer\n", -++ meminfo.erasesize * 2); -++ exit(1); -++ } -++ rbuf = wbuf + meminfo.erasesize; -++ kbuf = rbuf + meminfo.erasesize; -++ -++ if (ioctl(fd, ECCGETSTATS, &oldstats)) { -++ perror("ECCGETSTATS"); -++ close(fd); -++ exit(1); -++ } -++ -++ printf("ECC corrections: %d\n", oldstats.corrected); -++ printf("ECC failures : %d\n", oldstats.failed); -++ printf("Bad blocks : %d\n", oldstats.badblocks); -++ printf("BBT blocks : %d\n", oldstats.bbtblocks); -++ -++ for (pass = 0; pass < nr_passes; pass++) { -++ loff_mtd_t test_ofs; -++ -++ for (test_ofs = offset; test_ofs < offset+length; test_ofs += meminfo.erasesize) { -++ ssize_t len; -++ -++ seed = rand(); -++ srand(seed); -++ -++ if (ioctl(fd, MEMGETBADBLOCK, &test_ofs)) { -++ printf("\rBad block at 0x%09llx\n", test_ofs); -++ continue; -++ } -++ -++ for (i=0; i -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include "mtd/mtd-user.h" -++ -++#define PROGRAM "nandwrite" -++#define VERSION "$Revision: 1.1.1.1 $" -++ -++#define MAX_PAGE_SIZE 4096 -++#define MAX_OOB_SIZE 128 -++ -++/* -++ * Buffer array used for writing data -++ */ -++unsigned char writebuf[MAX_PAGE_SIZE]; -++unsigned char oobbuf[MAX_OOB_SIZE]; -++unsigned char oobreadbuf[MAX_OOB_SIZE]; -++ -++// oob layouts to pass into the kernel as default -++struct nand_oobinfo none_oobinfo = { -++ .useecc = MTD_NANDECC_OFF, -++}; -++ -++struct nand_oobinfo jffs2_oobinfo = { -++ .useecc = MTD_NANDECC_PLACE, -++ .eccbytes = 6, -++ .eccpos = { 0, 1, 2, 3, 6, 7 } -++}; -++ -++struct nand_oobinfo yaffs_oobinfo = { -++ .useecc = MTD_NANDECC_PLACE, -++ .eccbytes = 6, -++ .eccpos = { 8, 9, 10, 13, 14, 15} -++}; -++ -++struct nand_oobinfo autoplace_oobinfo = { -++ .useecc = MTD_NANDECC_AUTOPLACE -++}; -++ -++void display_help (void) -++{ -++ printf("Usage: nandwrite [OPTION] MTD_DEVICE INPUTFILE\n" -++ "Writes to the specified MTD device.\n" -++ "\n" -++ " -a, --autoplace Use auto oob layout\n" -++ " -j, --jffs2 force jffs2 oob layout (legacy support)\n" -++ " -y, --yaffs force yaffs oob layout (legacy support)\n" -++ " -f, --forcelegacy force legacy support on autoplacement enabled mtd device\n" -++ " -m, --markbad mark blocks bad if write fails\n" -++ " -n, --noecc write without ecc\n" -++ " -o, --oob image contains oob data\n" -++ " -s addr, --start=addr set start address (default is 0)\n" -++ " -p, --pad pad to page size\n" -++ " -b, --blockalign=1|2|4 set multiple of eraseblocks to align to\n" -++ " -q, --quiet don't display progress messages\n" -++ " --help display this help and exit\n" -++ " --version output version information and exit\n"); -++ exit(0); -++} -++ -++void display_version (void) -++{ -++ printf(PROGRAM " " VERSION "\n" -++ "\n" -++ "Copyright (C) 2003 Thomas Gleixner \n" -++ "\n" -++ PROGRAM " comes with NO WARRANTY\n" -++ "to the extent permitted by law.\n" -++ "\n" -++ "You may redistribute copies of " PROGRAM "\n" -++ "under the terms of the GNU General Public Licence.\n" -++ "See the file `COPYING' for more information.\n"); -++ exit(0); -++} -++ -++char *mtd_device, *img; -++int mtdoffset = 0; -++int quiet = 0; -++int writeoob = 0; -++int markbad = 0; -++int autoplace = 0; -++int forcejffs2 = 0; -++int forceyaffs = 0; -++int forcelegacy = 0; -++int noecc = 0; -++int pad = 0; -++int blockalign = 1; /*default to using 16K block size */ -++ -++void process_options (int argc, char *argv[]) -++{ -++ int error = 0; -++ -++ for (;;) { -++ int option_index = 0; -++ static const char *short_options = "ab:fjmnopqs:y"; -++ static const struct option long_options[] = { -++ {"help", no_argument, 0, 0}, -++ {"version", no_argument, 0, 0}, -++ {"autoplace", no_argument, 0, 'a'}, -++ {"blockalign", required_argument, 0, 'b'}, -++ {"forcelegacy", no_argument, 0, 'f'}, -++ {"jffs2", no_argument, 0, 'j'}, -++ {"markbad", no_argument, 0, 'm'}, -++ {"noecc", no_argument, 0, 'n'}, -++ {"oob", no_argument, 0, 'o'}, -++ {"pad", no_argument, 0, 'p'}, -++ {"quiet", no_argument, 0, 'q'}, -++ {"start", required_argument, 0, 's'}, -++ {"yaffs", no_argument, 0, 'y'}, -++ {0, 0, 0, 0}, -++ }; -++ -++ int c = getopt_long(argc, argv, short_options, -++ long_options, &option_index); -++ if (c == EOF) { -++ break; -++ } -++ -++ switch (c) { -++ case 0: -++ switch (option_index) { -++ case 0: -++ display_help(); -++ break; -++ case 1: -++ display_version(); -++ break; -++ } -++ break; -++ case 'q': -++ quiet = 1; -++ break; -++ case 'a': -++ autoplace = 1; -++ break; -++ case 'j': -++ forcejffs2 = 1; -++ break; -++ case 'y': -++ forceyaffs = 1; -++ break; -++ case 'f': -++ forcelegacy = 1; -++ break; -++ case 'n': -++ noecc = 1; -++ break; -++ case 'm': -++ markbad = 1; -++ break; -++ case 'o': -++ writeoob = 1; -++ break; -++ case 'p': -++ pad = 1; -++ break; -++ case 's': -++ mtdoffset = strtol (optarg, NULL, 0); -++ break; -++ case 'b': -++ blockalign = atoi (optarg); -++ break; -++ case '?': -++ error = 1; -++ break; -++ } -++ } -++ -++ if ((argc - optind) != 2 || error) -++ display_help (); -++ -++ mtd_device = argv[optind++]; -++ img = argv[optind]; -++} -++ -++/* -++ * Main program -++ */ -++int main(int argc, char **argv) -++{ -++ int cnt, fd, ifd, imglen = 0, pagelen, baderaseblock, blockstart = -1; -++ struct mtd_info_user meminfo; -++ struct mtd_oob_buf oob; -++ loff_mtd_t offs; -++ int ret, readlen; -++ int oobinfochanged = 0; -++ struct nand_oobinfo old_oobinfo; -++ -++ printf("Warning: nandwrite_mlc instead of nandwrite is used for MLC NAND!\n"); -++ -++ process_options(argc, argv); -++ -++ memset(oobbuf, 0xff, sizeof(oobbuf)); -++ -++ if (pad && writeoob) { -++ fprintf(stderr, "Can't pad when oob data is present.\n"); -++ exit(1); -++ } -++ -++ /* Open the device */ -++ if ((fd = open(mtd_device, O_RDWR)) == -1) { -++ perror("open flash"); -++ exit(1); -++ } -++ -++ /* Fill in MTD device capability structure */ -++ if (ioctl(fd, MEMGETINFO, &meminfo) != 0) { -++ perror("MEMGETINFO"); -++ close(fd); -++ exit(1); -++ } -++ -++ /* Set erasesize to specified number of blocks - to match jffs2 -++ * (virtual) block size */ -++ meminfo.erasesize *= blockalign; -++ -++ /* Make sure device page sizes are valid */ -++ if (!(meminfo.oobsize == 16 && meminfo.writesize == 512) && -++ !(meminfo.oobsize == 8 && meminfo.writesize == 256) && -++ !(meminfo.oobsize == 64 && meminfo.writesize == 2048) && -++ !(meminfo.oobsize == 128 && meminfo.writesize == 4096)) { -++ fprintf(stderr, "Unknown flash (not normal NAND)\n"); -++ close(fd); -++ exit(1); -++ } -++ -++ if (autoplace) { -++ /* Read the current oob info */ -++ if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) { -++ perror ("MEMGETOOBSEL"); -++ close (fd); -++ exit (1); -++ } -++ -++ // autoplace ECC ? -++ if (autoplace && (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE)) { -++ -++ if (ioctl (fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) { -++ perror ("MEMSETOOBSEL"); -++ close (fd); -++ exit (1); -++ } -++ oobinfochanged = 1; -++ } -++ } -++ -++ if (noecc) { -++ ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW); -++ if (ret == 0) { -++ oobinfochanged = 2; -++ } else { -++ switch (errno) { -++ case ENOTTY: -++ if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) { -++ perror ("MEMGETOOBSEL"); -++ close (fd); -++ exit (1); -++ } -++ if (ioctl (fd, MEMSETOOBSEL, &none_oobinfo) != 0) { -++ perror ("MEMSETOOBSEL"); -++ close (fd); -++ exit (1); -++ } -++ oobinfochanged = 1; -++ break; -++ default: -++ perror ("MTDFILEMODE"); -++ close (fd); -++ exit (1); -++ } -++ } -++ } -++ -++ /* -++ * force oob layout for jffs2 or yaffs ? -++ * Legacy support -++ */ -++ if (forcejffs2 || forceyaffs) { -++ struct nand_oobinfo *oobsel = forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo; -++ -++ if (autoplace) { -++ fprintf(stderr, "Autoplacement is not possible for legacy -j/-y options\n"); -++ goto restoreoob; -++ } -++ if ((old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) && !forcelegacy) { -++ fprintf(stderr, "Use -f option to enforce legacy placement on autoplacement enabled mtd device\n"); -++ goto restoreoob; -++ } -++ if (meminfo.oobsize == 8) { -++ if (forceyaffs) { -++ fprintf (stderr, "YAFSS cannot operate on 256 Byte page size"); -++ goto restoreoob; -++ } -++ /* Adjust number of ecc bytes */ -++ jffs2_oobinfo.eccbytes = 3; -++ } -++ -++ if (ioctl (fd, MEMSETOOBSEL, oobsel) != 0) { -++ perror ("MEMSETOOBSEL"); -++ goto restoreoob; -++ } -++ } -++ -++ oob.length = meminfo.oobsize; -++ oob.ptr = noecc ? oobreadbuf : oobbuf; -++ -++ /* Open the input file */ -++ if ((ifd = open(img, O_RDONLY)) == -1) { -++ perror("open input file"); -++ goto restoreoob; -++ } -++ -++ // get image length -++ imglen = lseek(ifd, 0, SEEK_END); -++ lseek (ifd, 0, SEEK_SET); -++ -++ pagelen = meminfo.writesize + ((writeoob == 1) ? meminfo.oobsize : 0); -++ -++ // Check, if file is pagealigned -++ if ((!pad) && ((imglen % pagelen) != 0)) { -++ fprintf (stderr, "Input file is not page aligned\n"); -++ goto closeall; -++ } -++ -++ // Check, if length fits into device -++ if ( ((imglen / pagelen) * meminfo.writesize) > (meminfo.size - mtdoffset)) { -++ fprintf (stderr, "Image %d bytes, NAND page %d bytes, OOB area %u bytes, device size %llu bytes\n", -++ imglen, pagelen, meminfo.writesize, meminfo.size); -++ perror ("Input file does not fit into device"); -++ goto closeall; -++ } -++ -++ /* Get data from input and write to the device */ -++ while (imglen && (mtdoffset < meminfo.size)) { -++ // new eraseblock , check for bad block(s) -++ // Stay in the loop to be sure if the mtdoffset changes because -++ // of a bad block, that the next block that will be written to -++ // is also checked. Thus avoiding errors if the block(s) after the -++ // skipped block(s) is also bad (number of blocks depending on -++ // the blockalign -++ while (blockstart != (mtdoffset & (~meminfo.erasesize + 1))) { -++ blockstart = mtdoffset & (~meminfo.erasesize + 1); -++ offs = blockstart; -++ baderaseblock = 0; -++ if (!quiet) -++ fprintf (stdout, "Writing data to block %x\n", blockstart); -++ -++ /* Check all the blocks in an erase block for bad blocks */ -++ do { -++ if ((ret = ioctl(fd, MEMGETBADBLOCK, &offs)) < 0) { -++ perror("ioctl(MEMGETBADBLOCK)"); -++ goto closeall; -++ } -++ -++ if (ret == 1) { -++ baderaseblock = 1; -++ if (!quiet) -++ fprintf (stderr, "Bad block at %x, %u block(s) " -++ "from %x will be skipped\n", -++ (int) offs, blockalign, blockstart); -++ } -++ -++ if (baderaseblock) { -++ mtdoffset = blockstart + meminfo.erasesize; -++ } -++ offs += meminfo.erasesize / blockalign ; -++ } while ( offs < blockstart + meminfo.erasesize ); -++ -++ } -++ -++ readlen = meminfo.writesize; -++ if (pad && (imglen < readlen)) -++ { -++ readlen = imglen; -++ memset(writebuf + readlen, 0xff, meminfo.writesize - readlen); -++ } -++ -++ /* Read Page Data from input file */ -++ if ((cnt = read(ifd, writebuf, readlen)) != readlen) { -++ if (cnt == 0) // EOF -++ break; -++ perror ("File I/O error on input file"); -++ goto closeall; -++ } -++ -++ if (writeoob) { -++ /* Read OOB data from input file, exit on failure */ -++ if ((cnt = read(ifd, oobreadbuf, meminfo.oobsize)) != meminfo.oobsize) { -++ perror ("File I/O error on input file"); -++ goto closeall; -++ } -++ if (!noecc) { -++ int i, start, len; -++ /* -++ * We use autoplacement and have the oobinfo with the autoplacement -++ * information from the kernel available -++ * -++ * Modified to support out of order oobfree segments, -++ * such as the layout used by diskonchip.c -++ */ -++ if (!oobinfochanged && (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE)) { -++ for (i = 0;old_oobinfo.oobfree[i][1]; i++) { -++ /* Set the reserved bytes to 0xff */ -++ start = old_oobinfo.oobfree[i][0]; -++ len = old_oobinfo.oobfree[i][1]; -++ memcpy(oobbuf + start, -++ oobreadbuf + start, -++ len); -++ } -++ } else { -++ /* Set at least the ecc byte positions to 0xff */ -++ start = old_oobinfo.eccbytes; -++ len = meminfo.oobsize - start; -++ memcpy(oobbuf + start, -++ oobreadbuf + start, -++ len); -++ } -++ } -++ /* Write OOB data first, as ecc will be placed in there*/ -++ oob.start = mtdoffset; -++ if (ioctl(fd, MEMWRITEOOB, &oob) != 0) { -++ perror ("ioctl(MEMWRITEOOB)"); -++ goto closeall; -++ } -++ imglen -= meminfo.oobsize; -++ } -++ -++ /* Write out the Page data */ -++ if (pwrite(fd, writebuf, meminfo.writesize, mtdoffset) != meminfo.writesize) { -++ int rewind_blocks; -++ off_t rewind_bytes; -++ erase_info_t erase; -++ -++ perror ("pwrite"); -++ /* Must rewind to blockstart if we can */ -++ rewind_blocks = (mtdoffset - blockstart) / meminfo.writesize; /* Not including the one we just attempted */ -++ rewind_bytes = (rewind_blocks * meminfo.writesize) + readlen; -++ if (writeoob) -++ rewind_bytes += (rewind_blocks + 1) * meminfo.oobsize; -++ if (lseek(ifd, -rewind_bytes, SEEK_CUR) == -1) { -++ perror("lseek"); -++ fprintf(stderr, "Failed to seek backwards to recover from write error\n"); -++ goto closeall; -++ } -++ erase.start = blockstart; -++ erase.length = meminfo.erasesize; -++ fprintf(stderr, "Erasing failed write from 0x%09llx-0x%09llx\n", -++ erase.start, erase.start+erase.length-1); -++ if (ioctl(fd, MEMERASE, &erase) != 0) { -++ perror("MEMERASE"); -++ goto closeall; -++ } -++ -++ if (markbad) { -++ loff_mtd_t bad_addr = mtdoffset & (~(meminfo.erasesize / blockalign) + 1); -++ fprintf(stderr, "Marking block at %09llx bad\n", (long long)bad_addr); -++ if (ioctl(fd, MEMSETBADBLOCK, &bad_addr)) { -++ perror("MEMSETBADBLOCK"); -++ /* But continue anyway */ -++ } -++ } -++ mtdoffset = blockstart + meminfo.erasesize; -++ imglen += rewind_blocks * meminfo.writesize; -++ -++ continue; -++ } -++ imglen -= readlen; -++ mtdoffset += meminfo.writesize; -++ } -++ -++closeall: -++ close(ifd); -++ -++restoreoob: -++ if (oobinfochanged == 1) { -++ if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) { -++ perror ("MEMSETOOBSEL"); -++ close (fd); -++ exit (1); -++ } -++ } -++ -++ close(fd); -++ -++ if (imglen > 0) { -++ perror ("Data was only partially written due to error\n"); -++ exit (1); -++ } -++ -++ /* Return happy */ -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/nandwrite_mlc.c linux-2.6.24.7/drivers/mtd/mtd-utils/nandwrite_mlc.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/nandwrite_mlc.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/nandwrite_mlc.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,446 @@ -++/* -++ * nandwrite.c -++ * -++ * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) -++ * 2003 Thomas Gleixner (tglx@linutronix.de) -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ * Overview: -++ * This utility writes a binary image directly to a NAND flash -++ * chip or NAND chips contained in DoC devices. This is the -++ * "inverse operation" of nanddump. -++ * -++ * tglx: Major rewrite to handle bad blocks, write data with or without ECC -++ * write oob data only on request -++ * -++ * Bug/ToDo: -++ */ -++ -++#define _GNU_SOURCE -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include "mtd/mtd-user.h" -++ -++#define PROGRAM "nandwrite" -++#define VERSION "$Revision: 1.1.1.1 $" -++ -++#define MAX_PAGE_SIZE 8192 -++#define MAX_OOB_SIZE 256 -++/* -++ * Buffer array used for writing data -++ */ -++unsigned char writebuf[MAX_PAGE_SIZE]; -++unsigned char oobreadbuf[MAX_OOB_SIZE]; -++ -++// oob layouts to pass into the kernel as default -++struct nand_oobinfo none_oobinfo = { -++ .useecc = MTD_NANDECC_OFF, -++}; -++ -++struct nand_oobinfo jffs2_oobinfo = { -++ .useecc = MTD_NANDECC_PLACE, -++ .eccbytes = 6, -++ .eccpos = { 0, 1, 2, 3, 6, 7 } -++}; -++ -++struct nand_oobinfo yaffs_oobinfo = { -++ .useecc = MTD_NANDECC_PLACE, -++ .eccbytes = 6, -++ .eccpos = { 8, 9, 10, 13, 14, 15} -++}; -++ -++struct nand_oobinfo autoplace_oobinfo = { -++ .useecc = MTD_NANDECC_AUTOPLACE, -++ .eccbytes = 36 -++}; -++ -++void display_help (void) -++{ -++ printf("Usage: nandwrite [OPTION] MTD_DEVICE INPUTFILE\n" -++ "Writes to the specified MTD device.\n" -++ "\n" -++ " -a, --autoplace Use auto oob layout\n" -++ " -j, --jffs2 force jffs2 oob layout (legacy support)\n" -++ " -y, --yaffs force yaffs oob layout (legacy support)\n" -++ " -f, --forcelegacy force legacy support on autoplacement enabled mtd device\n" -++ " -m, --markbad mark blocks bad if write fails\n" -++ " -n, --noecc write without ecc\n" -++ " -o, --oob image contains oob data\n" -++ " -s addr, --start=addr set start address (default is 0)\n" -++ " -p, --pad pad to page size\n" -++ " -b, --blockalign=1|2|4 set multiple of eraseblocks to align to\n" -++ " -q, --quiet don't display progress messages\n" -++ " --help display this help and exit\n" -++ " --version output version information and exit\n"); -++ exit(0); -++} -++ -++void display_version (void) -++{ -++ printf(PROGRAM " " VERSION "\n" -++ "\n" -++ "Copyright (C) 2003 Thomas Gleixner \n" -++ "\n" -++ PROGRAM " comes with NO WARRANTY\n" -++ "to the extent permitted by law.\n" -++ "\n" -++ "You may redistribute copies of " PROGRAM "\n" -++ "under the terms of the GNU General Public Licence.\n" -++ "See the file `COPYING' for more information.\n"); -++ exit(0); -++} -++ -++char *mtd_device, *img; -++unsigned long long mtdoffset = 0; -++int quiet = 0; -++int writeoob = 0; -++int markbad = 1; -++int autoplace = 0; -++int forcejffs2 = 0; -++int forceyaffs = 0; -++int forcelegacy = 0; -++int noecc = 0; -++int pad = 0; -++int blockalign = 1; /*default to using 16K block size */ -++ -++void process_options (int argc, char *argv[]) -++{ -++ int error = 0; -++ -++ for (;;) { -++ int option_index = 0; -++ static const char *short_options = "ab:fjmnopqs:y"; -++ static const struct option long_options[] = { -++ {"help", no_argument, 0, 0}, -++ {"version", no_argument, 0, 0}, -++ {"autoplace", no_argument, 0, 'a'}, -++ {"blockalign", required_argument, 0, 'b'}, -++ {"forcelegacy", no_argument, 0, 'f'}, -++ {"jffs2", no_argument, 0, 'j'}, -++ {"markbad", no_argument, 0, 'm'}, -++ {"noecc", no_argument, 0, 'n'}, -++ {"oob", no_argument, 0, 'o'}, -++ {"pad", no_argument, 0, 'p'}, -++ {"quiet", no_argument, 0, 'q'}, -++ {"start", required_argument, 0, 's'}, -++ {"yaffs", no_argument, 0, 'y'}, -++ {0, 0, 0, 0}, -++ }; -++ -++ int c = getopt_long(argc, argv, short_options, -++ long_options, &option_index); -++ if (c == EOF) { -++ break; -++ } -++ -++ switch (c) { -++ case 0: -++ switch (option_index) { -++ case 0: -++ display_help(); -++ break; -++ case 1: -++ display_version(); -++ break; -++ } -++ break; -++ case 'q': -++ quiet = 1; -++ break; -++ case 'a': -++ autoplace = 1; -++ break; -++ case 'j': -++ forcejffs2 = 1; -++ break; -++ case 'y': -++ forceyaffs = 1; -++ break; -++ case 'f': -++ forcelegacy = 1; -++ break; -++ case 'n': -++ noecc = 1; -++ break; -++ case 'm': -++ markbad = 1; -++ break; -++ case 'o': -++ writeoob = 1; -++ break; -++ case 'p': -++ pad = 1; -++ break; -++ case 's': -++ mtdoffset = strtol (optarg, NULL, 0); -++ break; -++ case 'b': -++ blockalign = atoi (optarg); -++ break; -++ case '?': -++ error = 1; -++ break; -++ } -++ } -++ -++ if ((argc - optind) != 2 || error) -++ display_help (); -++ -++ mtd_device = argv[optind++]; -++ img = argv[optind]; -++} -++ -++/* -++ * Main program -++ */ -++int main(int argc, char **argv) -++{ -++ int cnt, fd, ifd, imglen = 0, pagelen, baderaseblock, blockstart = -1; -++ struct mtd_info_user meminfo; -++ struct mtd_page_buf oob; -++ loff_mtd_t offs; -++ int ret, readlen; -++ int oobinfochanged = 0; -++ struct nand_oobinfo old_oobinfo; -++ int i; -++ -++ process_options(argc, argv); -++ -++ if (pad && writeoob) { -++ fprintf(stderr, "Can't pad when oob data is present.\n"); -++ exit(1); -++ } -++ -++ /* Open the device */ -++ if ((fd = open(mtd_device, O_RDWR)) == -1) { -++ perror("open flash"); -++ exit(1); -++ } -++ -++ /* Fill in MTD device capability structure */ -++ if (ioctl(fd, MEMGETINFO, &meminfo) != 0) { -++ perror("MEMGETINFO"); -++ close(fd); -++ exit(1); -++ } -++ -++ /* Set erasesize to specified number of blocks - to match jffs2 -++ * (virtual) block size */ -++ meminfo.erasesize *= blockalign; -++ -++ /* Make sure device page sizes are valid */ -++ if (!(meminfo.oobsize == 16 && meminfo.writesize == 512) && -++ !(meminfo.oobsize == 8 && meminfo.writesize == 256) && -++ !(meminfo.oobsize == 64 && meminfo.writesize == 2048) && -++ !(meminfo.oobsize == 128 && meminfo.writesize == 4096) && -++ !(meminfo.oobsize == 256 && meminfo.writesize == 8192)) { -++ fprintf(stderr, "Unknown flash (not normal NAND)\n"); -++ close(fd); -++ exit(1); -++ } -++ -++ if (autoplace) { -++ /* Read the current oob info */ -++ if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) { -++ perror ("MEMGETOOBSEL"); -++ close (fd); -++ exit (1); -++ } -++ -++ // autoplace ECC ? -++ if (autoplace && (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE)) { -++ -++ if (ioctl (fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) { -++ perror ("MEMSETOOBSEL"); -++ close (fd); -++ exit (1); -++ } -++ oobinfochanged = 1; -++ } -++ } -++ -++ memset(oobreadbuf, 0xff, MAX_OOB_SIZE); -++ -++ if (autoplace) { -++ oob.ooblength = meminfo.oobsize-old_oobinfo.eccbytes; /* Get ooblength from kernel */ -++ printf("oobsize=%d eccbytes=%d\n", meminfo.oobsize, old_oobinfo.eccbytes); -++ } else { -++ oob.ooblength = meminfo.oobsize-autoplace_oobinfo.eccbytes; -++ printf("oobsize=%d eccbytes=%d\n", meminfo.oobsize, autoplace_oobinfo.eccbytes); -++ } -++ -++ oob.oobptr = oobreadbuf; -++ oob.datptr = writebuf; -++ -++ /* Open the input file */ -++ if ((ifd = open(img, O_RDONLY)) == -1) { -++ perror("open input file"); -++ goto restoreoob; -++ } -++ -++ // get image length -++ imglen = lseek(ifd, 0, SEEK_END); -++ lseek (ifd, 0, SEEK_SET); -++ -++ pagelen = meminfo.writesize + ((writeoob == 1) ? meminfo.oobsize : 0); -++ -++ // Check, if file is pagealigned -++ if ((!pad) && ((imglen % pagelen) != 0)) { -++ fprintf (stderr, "Input file is not page aligned\n"); -++ goto closeall; -++ } -++ -++ // Check, if length fits into device -++ if ( ((imglen / pagelen) * meminfo.writesize) > (meminfo.size - mtdoffset)) { -++ fprintf (stderr, "Image %d bytes, NAND page %d bytes, OOB area %u bytes, device size %lld bytes\n", -++ imglen, pagelen, meminfo.writesize, meminfo.size); -++ perror ("Input file does not fit into device"); -++ goto closeall; -++ } -++ -++ /* Get data from input and write to the device */ -++ while (imglen && (mtdoffset < meminfo.size)) { -++ // new eraseblock , check for bad block(s) -++ // Stay in the loop to be sure if the mtdoffset changes because -++ // of a bad block, that the next block that will be written to -++ // is also checked. Thus avoiding errors if the block(s) after the -++ // skipped block(s) is also bad (number of blocks depending on -++ // the blockalign -++ while (blockstart != (mtdoffset & (~meminfo.erasesize + 1))) { -++ blockstart = mtdoffset & (~meminfo.erasesize + 1); -++ offs = blockstart; -++ baderaseblock = 0; -++ i=0; -++ if (!quiet) -++ fprintf (stdout, "Writing data to block 0x%x\n", blockstart); -++ -++ /* Check all the blocks in an erase block for bad blocks */ -++ do { -++ if ((ret = ioctl(fd, MEMGETBADBLOCK, &offs)) < 0) { -++ perror("ioctl(MEMGETBADBLOCK)"); -++ goto closeall; -++ } -++ if (ret == 1) { -++ baderaseblock = 1; -++ if (!quiet) -++ fprintf (stderr, "Bad block at 0x%llx, %u block(s) " -++ "from 0x%x will be skipped\n", -++ offs, blockalign, blockstart); -++ } -++ -++ if (baderaseblock) { -++ mtdoffset = blockstart + meminfo.erasesize; -++ } -++ offs += meminfo.erasesize / blockalign ; -++ } while ( offs < blockstart + meminfo.erasesize ); -++ -++ } -++ -++ readlen = meminfo.writesize; -++ if (pad && (imglen < readlen)) -++ { -++ readlen = imglen; -++ memset(writebuf + readlen, 0xff, meminfo.writesize - readlen); -++ } -++ -++ /* Read Page Data from input file */ -++ if ((cnt = read(ifd, writebuf, readlen)) != readlen) { -++ if (cnt == 0) // EOF -++ break; -++ perror ("File I/O error 1 on input file"); -++ goto closeall; -++ } -++ -++ /* Read OOB data from input file, exit on failure */ -++ if(writeoob) { -++ if ((cnt = read(ifd, oobreadbuf, meminfo.oobsize)) != meminfo.oobsize) { -++ perror ("File I/O error 2 on input file"); -++ goto closeall; -++ } -++ } -++ oob.start = mtdoffset; -++ -++ // write a page include its oob to nand -++ ioctl(fd, MEMWRITEPAGE, &oob); -++ if(oob.datlength != meminfo.writesize){ -++ perror ("ioctl(MEMWRITEPAGE)"); -++ -++ int rewind_blocks; -++ off_t rewind_bytes; -++ erase_info_t erase; -++ -++ /* Must rewind to blockstart if we can */ -++ rewind_blocks = (mtdoffset - blockstart) / meminfo.writesize; /* Not including the one we just attempted */ -++ rewind_bytes = (rewind_blocks * meminfo.writesize) + readlen; -++ if (writeoob) -++ rewind_bytes += (rewind_blocks + 1) * meminfo.oobsize; -++ if (lseek(ifd, -rewind_bytes, SEEK_CUR) == -1) { -++ perror("lseek"); -++ fprintf(stderr, "Failed to seek backwards to recover from write error\n"); -++ goto closeall; -++ } -++ erase.start = blockstart; -++ erase.length = meminfo.erasesize; -++ fprintf(stderr, "Erasing failed write from 0x%09llx-0x%09llx\n", -++ erase.start, erase.start+erase.length-1); -++ if (ioctl(fd, MEMERASE, &erase) != 0) { -++ perror("MEMERASE"); -++ goto closeall; -++ } -++ -++ if (markbad) { -++ loff_mtd_t bad_addr = mtdoffset & (~(meminfo.erasesize / blockalign) + 1); -++ fprintf(stderr, "Marking block at %09llx bad\n", (long long)bad_addr); -++ if (ioctl(fd, MEMSETBADBLOCK, &bad_addr)) { -++ perror("MEMSETBADBLOCK"); -++ /* But continue anyway */ -++ } -++ } -++ mtdoffset = blockstart + meminfo.erasesize; -++ imglen += rewind_blocks * meminfo.writesize; -++ -++ continue; -++ } -++ if(writeoob) -++ imglen -= meminfo.oobsize; -++ imglen -= readlen; -++ mtdoffset += meminfo.writesize; -++ } -++ -++closeall: -++ close(ifd); -++ -++restoreoob: -++ if (oobinfochanged == 1) { -++ if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) { -++ perror ("MEMSETOOBSEL"); -++ close (fd); -++ exit (1); -++ } -++ } -++ -++ close(fd); -++ -++ if (imglen > 0) { -++ perror ("Data was only partially written due to error\n"); -++ exit (1); -++ } -++ -++ /* Return happy */ -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/nftl_format.c linux-2.6.24.7/drivers/mtd/mtd-utils/nftl_format.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/nftl_format.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/nftl_format.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,419 @@ -++/* -++ * nftl_format.c: Creating a NFTL/INFTL partition on an MTD device -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ * GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ * -++ * ToDo: -++ * 1. UnitSizeFactor != 0xFF cases -++ * 2. test, test, and test !!! -++ */ -++ -++#define _XOPEN_SOURCE 500 /* for pread/pwrite */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++ -++unsigned char BadUnitTable[MAX_ERASE_ZONES]; -++unsigned char *readbuf; -++unsigned char *writebuf[4]; -++ -++mtd_info_t meminfo; -++erase_info_t erase; -++int fd; -++struct NFTLMediaHeader *NFTLhdr; -++struct INFTLMediaHeader *INFTLhdr; -++ -++static int do_oobcheck = 1; -++static int do_rwecheck = 1; -++ -++static unsigned char check_block_1(unsigned long block) -++{ -++ unsigned char oobbuf[16]; -++ struct mtd_oob_buf oob = { 0, 16, oobbuf }; -++ -++ oob.start = block * meminfo.erasesize; -++ if (ioctl(fd, MEMREADOOB, &oob)) -++ return ZONE_BAD_ORIGINAL; -++ -++ if(oobbuf[5] == 0) -++ return ZONE_BAD_ORIGINAL; -++ -++ oob.start = block * meminfo.erasesize + 512 /* FIXME */; -++ if (ioctl(fd, MEMREADOOB, &oob)) -++ return ZONE_BAD_ORIGINAL; -++ -++ if(oobbuf[5] == 0) -++ return ZONE_BAD_ORIGINAL; -++ -++ return ZONE_GOOD; -++} -++ -++static unsigned char check_block_2(unsigned long block) -++{ -++ unsigned long ofs = block * meminfo.erasesize; -++ unsigned long blockofs; -++ -++ /* Erase test */ -++ erase.start = ofs; -++ -++ for (blockofs = 0; blockofs < meminfo.erasesize; blockofs += 512) { -++ pread(fd, readbuf, 512, ofs + blockofs); -++ if (memcmp(readbuf, writebuf[0], 512)) { -++ /* Block wasn't 0xff after erase */ -++ printf(": Block not 0xff after erase\n"); -++ return ZONE_BAD_ORIGINAL; -++ } -++ -++ pwrite(fd, writebuf[1], 512, blockofs + ofs); -++ pread(fd, readbuf, 512, blockofs + ofs); -++ if (memcmp(readbuf, writebuf[1], 512)) { -++ printf(": Block not zero after clearing\n"); -++ return ZONE_BAD_ORIGINAL; -++ } -++ } -++ -++ /* Write test */ -++ if (ioctl(fd, MEMERASE, &erase) != 0) { -++ printf(": Second erase failed (%s)\n", strerror(errno)); -++ return ZONE_BAD_ORIGINAL; -++ } -++ for (blockofs = 0; blockofs < meminfo.erasesize; blockofs += 512) { -++ pwrite(fd, writebuf[2], 512, blockofs + ofs); -++ pread(fd, readbuf, 512, blockofs + ofs); -++ if (memcmp(readbuf, writebuf[2], 512)) { -++ printf(": Block not 0x5a after writing\n"); -++ return ZONE_BAD_ORIGINAL; -++ } -++ } -++ -++ if (ioctl(fd, MEMERASE, &erase) != 0) { -++ printf(": Third erase failed (%s)\n", strerror(errno)); -++ return ZONE_BAD_ORIGINAL; -++ } -++ for (blockofs = 0; blockofs < meminfo.erasesize; blockofs += 512) { -++ pwrite(fd, writebuf[3], 512, blockofs + ofs); -++ pread(fd, readbuf, 512, blockofs + ofs); -++ if (memcmp(readbuf, writebuf[3], 512)) { -++ printf(": Block not 0xa5 after writing\n"); -++ return ZONE_BAD_ORIGINAL; -++ } -++ } -++ if (ioctl(fd, MEMERASE, &erase) != 0) { -++ printf(": Fourth erase failed (%s)\n", strerror(errno)); -++ return ZONE_BAD_ORIGINAL; -++ } -++ return ZONE_GOOD; -++} -++ -++static unsigned char erase_block(unsigned long block) -++{ -++ unsigned char status; -++ int ret; -++ -++ status = (do_oobcheck) ? check_block_1(block) : ZONE_GOOD; -++ erase.start = block * meminfo.erasesize; -++ -++ if (status != ZONE_GOOD) { -++ printf("\rSkipping bad zone (factory marked) #%ld @ 0x%x\n", block, erase.start); -++ fflush(stdout); -++ return status; -++ } -++ -++ printf("\r\t Erasing Zone #%ld @ 0x%x", block, erase.start); -++ fflush(stdout); -++ -++ if ((ret=ioctl(fd, MEMERASE, &erase)) != 0) { -++ printf(": Erase failed (%s)\n", strerror(errno)); -++ return ZONE_BAD_ORIGINAL; -++ } -++ -++ if (do_rwecheck) { -++ printf("\r\tChecking Zone #%ld @ 0x%x", block, erase.start); -++ fflush(stdout); -++ status = check_block_2(block); -++ if (status != ZONE_GOOD) { -++ printf("\rSkipping bad zone (RWE test failed) #%ld @ 0x%x\n", block, erase.start); -++ fflush(stdout); -++ } -++ } -++ return status; -++} -++ -++static int checkbbt(void) -++{ -++ unsigned char bbt[512]; -++ unsigned char bits; -++ int i, addr; -++ -++ if (pread(fd, bbt, 512, 0x800) < 0) { -++ printf("nftl_format: failed to read BBT, errno=%d\n", errno); -++ return (-1); -++ } -++ -++ -++ for (i = 0; (i < 512); i++) { -++ addr = i / 4; -++ bits = 0x3 << ((i % 4) * 2); -++ if ((bbt[addr] & bits) == 0) { -++ BadUnitTable[i] = ZONE_BAD_ORIGINAL; -++ } -++ } -++ -++ return (0); -++} -++ -++void usage(int rc) -++{ -++ fprintf(stderr, "Usage: nftl_format [-ib] [ []]\n"); -++ exit(rc); -++} -++ -++int main(int argc, char **argv) -++{ -++ unsigned long startofs = 0, part_size = 0; -++ unsigned long ezones = 0, ezone = 0, bad_zones = 0; -++ unsigned char unit_factor = 0xFF; -++ long MediaUnit1 = -1, MediaUnit2 = -1; -++ long MediaUnitOff1 = 0, MediaUnitOff2 = 0; -++ unsigned char oobbuf[16]; -++ struct mtd_oob_buf oob = {0, 16, oobbuf}; -++ char *mtddevice, *nftl; -++ int c, do_inftl = 0, do_bbt = 0; -++ -++ -++ printf("version 1.24 2005/11/07 11:15:13 gleixner\n"); -++ -++ if (argc < 2) -++ usage(1); -++ -++ nftl = "NFTL"; -++ -++ while ((c = getopt(argc, argv, "?hib")) > 0) { -++ switch (c) { -++ case 'i': -++ nftl = "INFTL"; -++ do_inftl = 1; -++ break; -++ case 'b': -++ do_bbt = 1; -++ break; -++ case 'h': -++ case '?': -++ usage(0); -++ break; -++ default: -++ usage(1); -++ break; -++ } -++ } -++ -++ mtddevice = argv[optind++]; -++ if (argc > optind) { -++ startofs = strtoul(argv[optind++], NULL, 0); -++ } -++ if (argc > optind) { -++ part_size = strtoul(argv[optind++], NULL, 0); -++ } -++ -++ // Open and size the device -++ if ((fd = open(mtddevice, O_RDWR)) < 0) { -++ perror("Open flash device"); -++ return 1; -++ } -++ -++ if (ioctl(fd, MEMGETINFO, &meminfo) != 0) { -++ perror("ioctl(MEMGETINFO)"); -++ close(fd); -++ return 1; -++ } -++ -++ switch (meminfo.erasesize) { -++ case 0x1000: -++ case 0x2000: -++ case 0x4000: -++ case 0x8000: -++ break; -++ default: -++ printf("Unrecognized Erase size, 0x%x - I'm confused\n", -++ meminfo.erasesize); -++ close(fd); -++ return 1; -++ } -++ writebuf[0] = malloc(meminfo.erasesize * 5); -++ if (!writebuf[0]) { -++ printf("Malloc failed\n"); -++ close(fd); -++ return 1; -++ } -++ writebuf[1] = writebuf[0] + meminfo.erasesize; -++ writebuf[2] = writebuf[1] + meminfo.erasesize; -++ writebuf[3] = writebuf[2] + meminfo.erasesize; -++ readbuf = writebuf[3] + meminfo.erasesize; -++ memset(writebuf[0], 0xff, meminfo.erasesize); -++ memset(writebuf[1], 0x00, meminfo.erasesize); -++ memset(writebuf[2], 0x5a, meminfo.erasesize); -++ memset(writebuf[3], 0xa5, meminfo.erasesize); -++ memset(BadUnitTable, ZONE_GOOD, MAX_ERASE_ZONES); -++ -++ if (part_size == 0 || (part_size > meminfo.size - startofs)) -++ /* the user doest not or incorrectly specify NFTL partition size */ -++ part_size = meminfo.size - startofs; -++ -++ erase.length = meminfo.erasesize; -++ ezones = part_size / meminfo.erasesize; -++ -++ if (ezones > MAX_ERASE_ZONES) { -++ /* Ought to change the UnitSizeFactor. But later. */ -++ part_size = meminfo.erasesize * MAX_ERASE_ZONES; -++ ezones = MAX_ERASE_ZONES; -++ unit_factor = 0xFF; -++ } -++ -++ /* If using device BBT then parse that now */ -++ if (do_bbt) { -++ checkbbt(); -++ do_oobcheck = 0; -++ do_rwecheck = 0; -++ } -++ -++ /* Phase 1. Erasing and checking each erase zones in the NFTL partition. -++ N.B. Erase Zones not used by the NFTL partition are untouched and marked ZONE_GOOD */ -++ printf("Phase 1. Checking and erasing Erase Zones from 0x%08lx to 0x%08lx\n", -++ startofs, startofs + part_size); -++ for (ezone = startofs / meminfo.erasesize; -++ ezone < (ezones + startofs / meminfo.erasesize); ezone++) { -++ if (BadUnitTable[ezone] != ZONE_GOOD) -++ continue; -++ if ((BadUnitTable[ezone] = erase_block(ezone)) == ZONE_GOOD) { -++ if (MediaUnit1 == -1) { -++ MediaUnit1 = ezone; -++ } else if (MediaUnit2 == -1) { -++ MediaUnit2 = ezone; -++ } -++ } else { -++ bad_zones++; -++ } -++ } -++ printf("\n"); -++ -++ /* N.B. from dump of M-System original chips, NumEraseUnits counts the 2 Erase Unit used -++ by MediaHeader and the FirstPhysicalEUN starts from the MediaHeader */ -++ if (do_inftl) { -++ unsigned long maxzones, pezstart, pezend, numvunits; -++ -++ INFTLhdr = (struct INFTLMediaHeader *) (writebuf[0]); -++ strcpy(INFTLhdr->bootRecordID, "BNAND"); -++ INFTLhdr->NoOfBootImageBlocks = cpu_to_le32(0); -++ INFTLhdr->NoOfBinaryPartitions = cpu_to_le32(0); -++ INFTLhdr->NoOfBDTLPartitions = cpu_to_le32(1); -++ INFTLhdr->BlockMultiplierBits = cpu_to_le32(0); -++ INFTLhdr->FormatFlags = cpu_to_le32(0); -++ INFTLhdr->OsakVersion = cpu_to_le32(OSAK_VERSION); -++ INFTLhdr->PercentUsed = cpu_to_le32(PERCENTUSED); -++ /* -++ * Calculate number of virtual units we will have to work -++ * with. I am calculating out the known bad units here, not -++ * sure if that is what M-Systems do... -++ */ -++ MediaUnit2 = MediaUnit1; -++ MediaUnitOff2 = 4096; -++ maxzones = meminfo.size / meminfo.erasesize; -++ pezstart = startofs / meminfo.erasesize + 1; -++ pezend = startofs / meminfo.erasesize + ezones - 1; -++ numvunits = (ezones - 2) * PERCENTUSED / 100; -++ for (ezone = pezstart; ezone < maxzones; ezone++) { -++ if (BadUnitTable[ezone] != ZONE_GOOD) { -++ if (numvunits > 1) -++ numvunits--; -++ } -++ } -++ -++ INFTLhdr->Partitions[0].virtualUnits = cpu_to_le32(numvunits); -++ INFTLhdr->Partitions[0].firstUnit = cpu_to_le32(pezstart); -++ INFTLhdr->Partitions[0].lastUnit = cpu_to_le32(pezend); -++ INFTLhdr->Partitions[0].flags = cpu_to_le32(INFTL_BDTL); -++ INFTLhdr->Partitions[0].spareUnits = cpu_to_le32(0); -++ INFTLhdr->Partitions[0].Reserved0 = INFTLhdr->Partitions[0].firstUnit; -++ INFTLhdr->Partitions[0].Reserved1 = cpu_to_le32(0); -++ -++ } else { -++ -++ NFTLhdr = (struct NFTLMediaHeader *) (writebuf[0]); -++ strcpy(NFTLhdr->DataOrgID, "ANAND"); -++ NFTLhdr->NumEraseUnits = cpu_to_le16(part_size / meminfo.erasesize); -++ NFTLhdr->FirstPhysicalEUN = cpu_to_le16(MediaUnit1); -++ /* N.B. we reserve 2 more Erase Units for "folding" of Virtual Unit Chain */ -++ NFTLhdr->FormattedSize = cpu_to_le32(part_size - ( (5+bad_zones) * meminfo.erasesize)); -++ NFTLhdr->UnitSizeFactor = unit_factor; -++ } -++ -++ /* Phase 2. Writing NFTL Media Headers and Bad Unit Table */ -++ printf("Phase 2.a Writing %s Media Header and Bad Unit Table\n", nftl); -++ pwrite(fd, writebuf[0], 512, MediaUnit1 * meminfo.erasesize + MediaUnitOff1); -++ for (ezone = 0; ezone < (meminfo.size / meminfo.erasesize); ezone += 512) { -++ pwrite(fd, BadUnitTable + ezone, 512, -++ (MediaUnit1 * meminfo.erasesize) + 512 * (1 + ezone / 512)); -++ } -++ -++#if 0 -++ printf(" MediaHeader contents:\n"); -++ printf(" NumEraseUnits: %d\n", le16_to_cpu(NFTLhdr->NumEraseUnits)); -++ printf(" FirstPhysicalEUN: %d\n", le16_to_cpu(NFTLhdr->FirstPhysicalEUN)); -++ printf(" FormattedSize: %d (%d sectors)\n", le32_to_cpu(NFTLhdr->FormattedSize), -++ le32_to_cpu(NFTLhdr->FormattedSize)/512); -++#endif -++ printf("Phase 2.b Writing Spare %s Media Header and Spare Bad Unit Table\n", nftl); -++ pwrite(fd, writebuf[0], 512, MediaUnit2 * meminfo.erasesize + MediaUnitOff2); -++ for (ezone = 0; ezone < (meminfo.size / meminfo.erasesize); ezone += 512) { -++ pwrite(fd, BadUnitTable + ezone, 512, -++ (MediaUnit2 * meminfo.erasesize + MediaUnitOff2) + 512 * (1 + ezone / 512)); -++ } -++ -++ /* UCI #1 for newly erased Erase Unit */ -++ memset(oobbuf, 0xff, 16); -++ oobbuf[11] = oobbuf[10] = oobbuf[9] = 0; -++ oobbuf[8] = (do_inftl) ? 0x00 : 0x03; -++ oobbuf[12] = oobbuf[14] = 0x69; -++ oobbuf[13] = oobbuf[15] = 0x3c; -++ -++ /* N.B. The Media Header and Bad Erase Unit Table are considered as Free Erase Unit -++ by M-System i.e. their Virtual Unit Number == 0xFFFF in the Unit Control Information #0, -++ but their Block Status is BLOCK_USED (0x5555) in their Block Control Information */ -++ /* Phase 3. Writing Unit Control Information for each Erase Unit */ -++ printf("Phase 3. Writing Unit Control Information to each Erase Unit\n"); -++ for (ezone = MediaUnit1; ezone < (ezones + startofs / meminfo.erasesize); ezone++) { -++ /* write UCI #1 to each Erase Unit */ -++ if (BadUnitTable[ezone] != ZONE_GOOD) -++ continue; -++ oob.start = (ezone * meminfo.erasesize) + 512 + (do_inftl * 512); -++ if (ioctl(fd, MEMWRITEOOB, &oob)) -++ printf("MEMWRITEOOB at %lx: %s\n", (unsigned long)oob.start, strerror(errno)); -++ } -++ -++ exit(0); -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/nftldump.c linux-2.6.24.7/drivers/mtd/mtd-utils/nftldump.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/nftldump.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/nftldump.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,281 @@ -++/* -++ * nftldump.c: Dumping the content of NFTL partitions on a "Physical Disk" -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ * GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ * -++ * ToDo: -++ * 1. UnitSizeFactor != 0xFF cases -++ * 2. test, test, and test !!! -++ */ -++ -++#define _XOPEN_SOURCE 500 /* For pread */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++ -++static struct NFTLMediaHeader MedHead[2]; -++static mtd_info_t meminfo; -++ -++static struct nftl_oob oobbuf; -++static struct mtd_oob_buf oob = {0, 16, (unsigned char *)&oobbuf}; -++ -++static int fd, ofd = -1;; -++static int NumMedHeads; -++ -++static unsigned char BadUnitTable[MAX_ERASE_ZONES]; -++ -++#if __BYTE_ORDER == __LITTLE_ENDIAN -++#define SWAP16(x) do { ; } while(0) -++#define SWAP32(x) do { ; } while(0) -++#else -++#define SWAP16(x) do { x = swab16(x); } while(0) -++#define SWAP32(x) do { x = swab32(x); } while(0) -++#endif -++ -++/* VUCtable, store the Erase Unit Number of the first Erase Unit in the chain */ -++static unsigned short *VUCtable; -++ -++/* FixMe: make this dynamic allocated */ -++#define ERASESIZE 0x2000 -++#define NUMVUNITS ((40*1024*1024) / ERASESIZE) -++static union nftl_uci UCItable[NUMVUNITS][3]; -++ -++static unsigned short nextEUN(unsigned short curEUN) -++{ -++ return UCItable[curEUN][0].a.ReplUnitNum; -++} -++ -++static unsigned int find_media_headers(void) -++{ -++ int i; -++ static unsigned long ofs = 0; -++ -++ NumMedHeads = 0; -++ while (ofs < meminfo.size) { -++ pread(fd, &MedHead[NumMedHeads], sizeof(struct NFTLMediaHeader), ofs); -++ if (!strncmp(MedHead[NumMedHeads].DataOrgID, "ANAND", 6)) { -++ SWAP16(MedHead[NumMedHeads].NumEraseUnits); -++ SWAP16(MedHead[NumMedHeads].FirstPhysicalEUN); -++ SWAP32(MedHead[NumMedHeads].FormattedSize); -++ -++ if (NumMedHeads == 0) { -++ printf("NFTL Media Header found at offset 0x%08lx:\n", ofs); -++ printf("NumEraseUnits: %d\n", -++ MedHead[NumMedHeads].NumEraseUnits); -++ printf("FirstPhysicalEUN: %d\n", -++ MedHead[NumMedHeads].FirstPhysicalEUN); -++ printf("Formatted Size: %d\n", -++ MedHead[NumMedHeads].FormattedSize); -++ printf("UnitSizeFactor: 0x%x\n", -++ MedHead[NumMedHeads].UnitSizeFactor); -++ -++ /* read BadUnitTable, I don't know why pread() does not work for -++ larger (7680 bytes) chunks */ -++ for (i = 0; i < MAX_ERASE_ZONES; i += 512) -++ pread(fd, &BadUnitTable[i], 512, ofs + 512 + i); -++ } else -++ printf("Second NFTL Media Header found at offset 0x%08lx\n",ofs); -++ NumMedHeads++; -++ } -++ -++ ofs += meminfo.erasesize; -++ if (NumMedHeads == 2) { -++ if (strncmp((char *)&MedHead[0], (char *)&MedHead[1], sizeof(struct NFTLMediaHeader)) != 0) { -++ printf("warning: NFTL Media Header is not consistent with " -++ "Spare NFTL Media Header\n"); -++ } -++ break; -++ } -++ } -++ -++ /* allocate Virtual Unit Chain table for this NFTL partition */ -++ VUCtable = calloc(MedHead[0].NumEraseUnits, sizeof(unsigned short)); -++ return NumMedHeads; -++} -++ -++static void dump_erase_units(void) -++{ -++ int i, j; -++ unsigned long ofs; -++ -++ for (i = MedHead[0].FirstPhysicalEUN; i < MedHead[0].FirstPhysicalEUN + -++ MedHead[0].NumEraseUnits; i++) { -++ /* For each Erase Unit */ -++ ofs = i * meminfo.erasesize; -++ -++ /* read the Unit Control Information */ -++ for (j = 0; j < 3; j++) { -++ oob.start = ofs + (j * 512); -++ if (ioctl(fd, MEMREADOOB, &oob)) -++ printf("MEMREADOOB at %lx: %s\n", -++ (unsigned long) oob.start, strerror(errno)); -++ memcpy(&UCItable[i][j], &oobbuf.u, 8); -++ } -++ if (UCItable[i][1].b.EraseMark != cpu_to_le16(0x3c69)) { -++ printf("EraseMark not present in unit %d: %x\n", -++ i, UCItable[i][1].b.EraseMark); -++ } else { -++ /* a properly formatted unit */ -++ SWAP16(UCItable[i][0].a.VirtUnitNum); -++ SWAP16(UCItable[i][0].a.ReplUnitNum); -++ SWAP16(UCItable[i][0].a.SpareVirtUnitNum); -++ SWAP16(UCItable[i][0].a.SpareReplUnitNum); -++ SWAP32(UCItable[i][1].b.WearInfo); -++ SWAP16(UCItable[i][1].b.EraseMark); -++ SWAP16(UCItable[i][1].b.EraseMark1); -++ SWAP16(UCItable[i][2].c.FoldMark); -++ SWAP16(UCItable[i][2].c.FoldMark1); -++ -++ if (!(UCItable[i][0].a.VirtUnitNum & 0x8000)) { -++ /* If this is the first in a chain, store the EUN in the VUC table */ -++ if (VUCtable[UCItable[i][0].a.VirtUnitNum & 0x7fff]) { -++ printf("Duplicate start of chain for VUC %d: " -++ "Unit %d replaces Unit %d\n", -++ UCItable[i][0].a.VirtUnitNum & 0x7fff, -++ i, VUCtable[UCItable[i][0].a.VirtUnitNum & 0x7fff]); -++ } -++ VUCtable[UCItable[i][0].a.VirtUnitNum & 0x7fff] = i; -++ } -++ } -++ -++ switch (BadUnitTable[i]) { -++ case ZONE_BAD_ORIGINAL: -++ printf("Unit %d is marked as ZONE_BAD_ORIGINAL\n", i); -++ continue; -++ case ZONE_BAD_MARKED: -++ printf("Unit %d is marked as ZONE_BAD_MARKED\n", i); -++ continue; -++ } -++ -++ /* ZONE_GOOD */ -++ if (UCItable[i][0].a.VirtUnitNum == 0xffff) -++ printf("Unit %d is free\n", i); -++ else -++ printf("Unit %d is in chain %d and %s a replacement\n", i, -++ UCItable[i][0].a.VirtUnitNum & 0x7fff, -++ UCItable[i][0].a.VirtUnitNum & 0x8000 ? "is" : "is not"); -++ } -++} -++ -++static void dump_virtual_units(void) -++{ -++ int i, j; -++ char readbuf[512]; -++ -++ for (i = 0; i < (MedHead[0].FormattedSize / meminfo.erasesize); i++) { -++ unsigned short curEUN = VUCtable[i]; -++ -++ printf("Virtual Unit #%d: ", i); -++ if (!curEUN) { -++ printf("Not present\n"); -++ continue; -++ } -++ printf("%d", curEUN); -++ -++ /* walk through the Virtual Unit Chain */ -++ while ((curEUN = nextEUN(curEUN)) != 0xffff) { -++ printf(", %d", curEUN & 0x7fff); -++ } -++ printf("\n"); -++ -++ if (ofd != -1) { -++ /* Actually write out the data */ -++ for (j = 0; j < meminfo.erasesize / 512; j++) { -++ /* For each sector in the block */ -++ unsigned short lastgoodEUN = 0xffff, thisEUN = VUCtable[i]; -++ unsigned int status; -++ -++ if (thisEUN == 0xffff) thisEUN = 0; -++ -++ while (thisEUN && (thisEUN & 0x7fff) != 0x7fff) { -++ oob.start = (thisEUN * ERASESIZE) + (j * 512); -++ ioctl(fd, MEMREADOOB, &oob); -++ status = oobbuf.b.Status | oobbuf.b.Status1; -++ -++ switch (status) { -++ case SECTOR_FREE: -++ /* This is still free. Don't look any more */ -++ thisEUN = 0; -++ break; -++ -++ case SECTOR_USED: -++ /* SECTOR_USED. This is a good one. */ -++ lastgoodEUN = thisEUN; -++ break; -++ } -++ -++ /* Find the next erase unit in this chain, if any */ -++ if (thisEUN) -++ thisEUN = nextEUN(thisEUN) & 0x7fff; -++ } -++ -++ if (lastgoodEUN == 0xffff) -++ memset(readbuf, 0, 512); -++ else -++ pread(fd, readbuf, 512, -++ (lastgoodEUN * ERASESIZE) + (j * 512)); -++ -++ write(ofd, readbuf, 512); -++ } -++ -++ } -++ } -++} -++ -++int main(int argc, char **argv) -++{ -++ if (argc < 2) { -++ printf("Usage: %s []\n", argv[0]); -++ exit(1); -++ } -++ fd = open(argv[1], O_RDONLY); -++ if (fd == -1) { -++ perror("open flash"); -++ exit (1); -++ } -++ -++ if (argc > 2) { -++ ofd = open(argv[2], O_WRONLY | O_TRUNC | O_CREAT, 0644); -++ if (ofd == -1) -++ perror ("open outfile"); -++ } -++ -++ /* get size information of the MTD device */ -++ if (ioctl(fd, MEMGETINFO, &meminfo) != 0) { -++ perror("ioctl(MEMGETINFO)"); -++ close(fd); -++ return 1; -++ } -++ -++ while (find_media_headers() != 0) { -++ dump_erase_units(); -++ dump_virtual_units(); -++ free(VUCtable); -++ } -++ -++ exit(0); -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/rbtree.c linux-2.6.24.7/drivers/mtd/mtd-utils/rbtree.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/rbtree.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/rbtree.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,390 @@ -++/* -++ Red Black Trees -++ (C) 1999 Andrea Arcangeli -++ (C) 2002 David Woodhouse -++ -++ This program is free software; you can redistribute it and/or modify -++ it under the terms of the GNU General Public License as published by -++ the Free Software Foundation; either version 2 of the License, or -++ (at your option) any later version. -++ -++ This program is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with this program; if not, write to the Free Software -++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ -++ linux/lib/rbtree.c -++*/ -++ -++#include -++#include "rbtree.h" -++ -++static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) -++{ -++ struct rb_node *right = node->rb_right; -++ struct rb_node *parent = rb_parent(node); -++ -++ if ((node->rb_right = right->rb_left)) -++ rb_set_parent(right->rb_left, node); -++ right->rb_left = node; -++ -++ rb_set_parent(right, parent); -++ -++ if (parent) -++ { -++ if (node == parent->rb_left) -++ parent->rb_left = right; -++ else -++ parent->rb_right = right; -++ } -++ else -++ root->rb_node = right; -++ rb_set_parent(node, right); -++} -++ -++static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) -++{ -++ struct rb_node *left = node->rb_left; -++ struct rb_node *parent = rb_parent(node); -++ -++ if ((node->rb_left = left->rb_right)) -++ rb_set_parent(left->rb_right, node); -++ left->rb_right = node; -++ -++ rb_set_parent(left, parent); -++ -++ if (parent) -++ { -++ if (node == parent->rb_right) -++ parent->rb_right = left; -++ else -++ parent->rb_left = left; -++ } -++ else -++ root->rb_node = left; -++ rb_set_parent(node, left); -++} -++ -++void rb_insert_color(struct rb_node *node, struct rb_root *root) -++{ -++ struct rb_node *parent, *gparent; -++ -++ while ((parent = rb_parent(node)) && rb_is_red(parent)) -++ { -++ gparent = rb_parent(parent); -++ -++ if (parent == gparent->rb_left) -++ { -++ { -++ register struct rb_node *uncle = gparent->rb_right; -++ if (uncle && rb_is_red(uncle)) -++ { -++ rb_set_black(uncle); -++ rb_set_black(parent); -++ rb_set_red(gparent); -++ node = gparent; -++ continue; -++ } -++ } -++ -++ if (parent->rb_right == node) -++ { -++ register struct rb_node *tmp; -++ __rb_rotate_left(parent, root); -++ tmp = parent; -++ parent = node; -++ node = tmp; -++ } -++ -++ rb_set_black(parent); -++ rb_set_red(gparent); -++ __rb_rotate_right(gparent, root); -++ } else { -++ { -++ register struct rb_node *uncle = gparent->rb_left; -++ if (uncle && rb_is_red(uncle)) -++ { -++ rb_set_black(uncle); -++ rb_set_black(parent); -++ rb_set_red(gparent); -++ node = gparent; -++ continue; -++ } -++ } -++ -++ if (parent->rb_left == node) -++ { -++ register struct rb_node *tmp; -++ __rb_rotate_right(parent, root); -++ tmp = parent; -++ parent = node; -++ node = tmp; -++ } -++ -++ rb_set_black(parent); -++ rb_set_red(gparent); -++ __rb_rotate_left(gparent, root); -++ } -++ } -++ -++ rb_set_black(root->rb_node); -++} -++ -++static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, -++ struct rb_root *root) -++{ -++ struct rb_node *other; -++ -++ while ((!node || rb_is_black(node)) && node != root->rb_node) -++ { -++ if (parent->rb_left == node) -++ { -++ other = parent->rb_right; -++ if (rb_is_red(other)) -++ { -++ rb_set_black(other); -++ rb_set_red(parent); -++ __rb_rotate_left(parent, root); -++ other = parent->rb_right; -++ } -++ if ((!other->rb_left || rb_is_black(other->rb_left)) && -++ (!other->rb_right || rb_is_black(other->rb_right))) -++ { -++ rb_set_red(other); -++ node = parent; -++ parent = rb_parent(node); -++ } -++ else -++ { -++ if (!other->rb_right || rb_is_black(other->rb_right)) -++ { -++ struct rb_node *o_left; -++ if ((o_left = other->rb_left)) -++ rb_set_black(o_left); -++ rb_set_red(other); -++ __rb_rotate_right(other, root); -++ other = parent->rb_right; -++ } -++ rb_set_color(other, rb_color(parent)); -++ rb_set_black(parent); -++ if (other->rb_right) -++ rb_set_black(other->rb_right); -++ __rb_rotate_left(parent, root); -++ node = root->rb_node; -++ break; -++ } -++ } -++ else -++ { -++ other = parent->rb_left; -++ if (rb_is_red(other)) -++ { -++ rb_set_black(other); -++ rb_set_red(parent); -++ __rb_rotate_right(parent, root); -++ other = parent->rb_left; -++ } -++ if ((!other->rb_left || rb_is_black(other->rb_left)) && -++ (!other->rb_right || rb_is_black(other->rb_right))) -++ { -++ rb_set_red(other); -++ node = parent; -++ parent = rb_parent(node); -++ } -++ else -++ { -++ if (!other->rb_left || rb_is_black(other->rb_left)) -++ { -++ register struct rb_node *o_right; -++ if ((o_right = other->rb_right)) -++ rb_set_black(o_right); -++ rb_set_red(other); -++ __rb_rotate_left(other, root); -++ other = parent->rb_left; -++ } -++ rb_set_color(other, rb_color(parent)); -++ rb_set_black(parent); -++ if (other->rb_left) -++ rb_set_black(other->rb_left); -++ __rb_rotate_right(parent, root); -++ node = root->rb_node; -++ break; -++ } -++ } -++ } -++ if (node) -++ rb_set_black(node); -++} -++ -++void rb_erase(struct rb_node *node, struct rb_root *root) -++{ -++ struct rb_node *child, *parent; -++ int color; -++ -++ if (!node->rb_left) -++ child = node->rb_right; -++ else if (!node->rb_right) -++ child = node->rb_left; -++ else -++ { -++ struct rb_node *old = node, *left; -++ -++ node = node->rb_right; -++ while ((left = node->rb_left) != NULL) -++ node = left; -++ child = node->rb_right; -++ parent = rb_parent(node); -++ color = rb_color(node); -++ -++ if (child) -++ rb_set_parent(child, parent); -++ if (parent == old) { -++ parent->rb_right = child; -++ parent = node; -++ } else -++ parent->rb_left = child; -++ -++ node->rb_parent_color = old->rb_parent_color; -++ node->rb_right = old->rb_right; -++ node->rb_left = old->rb_left; -++ -++ if (rb_parent(old)) -++ { -++ if (rb_parent(old)->rb_left == old) -++ rb_parent(old)->rb_left = node; -++ else -++ rb_parent(old)->rb_right = node; -++ } else -++ root->rb_node = node; -++ -++ rb_set_parent(old->rb_left, node); -++ if (old->rb_right) -++ rb_set_parent(old->rb_right, node); -++ goto color; -++ } -++ -++ parent = rb_parent(node); -++ color = rb_color(node); -++ -++ if (child) -++ rb_set_parent(child, parent); -++ if (parent) -++ { -++ if (parent->rb_left == node) -++ parent->rb_left = child; -++ else -++ parent->rb_right = child; -++ } -++ else -++ root->rb_node = child; -++ -++ color: -++ if (color == RB_BLACK) -++ __rb_erase_color(child, parent, root); -++} -++ -++/* -++ * This function returns the first node (in sort order) of the tree. -++ */ -++struct rb_node *rb_first(struct rb_root *root) -++{ -++ struct rb_node *n; -++ -++ n = root->rb_node; -++ if (!n) -++ return NULL; -++ while (n->rb_left) -++ n = n->rb_left; -++ return n; -++} -++ -++struct rb_node *rb_last(struct rb_root *root) -++{ -++ struct rb_node *n; -++ -++ n = root->rb_node; -++ if (!n) -++ return NULL; -++ while (n->rb_right) -++ n = n->rb_right; -++ return n; -++} -++ -++struct rb_node *rb_next(struct rb_node *node) -++{ -++ struct rb_node *parent; -++ -++ if (rb_parent(node) == node) -++ return NULL; -++ -++ /* If we have a right-hand child, go down and then left as far -++ as we can. */ -++ if (node->rb_right) { -++ node = node->rb_right; -++ while (node->rb_left) -++ node=node->rb_left; -++ return node; -++ } -++ -++ /* No right-hand children. Everything down and left is -++ smaller than us, so any 'next' node must be in the general -++ direction of our parent. Go up the tree; any time the -++ ancestor is a right-hand child of its parent, keep going -++ up. First time it's a left-hand child of its parent, said -++ parent is our 'next' node. */ -++ while ((parent = rb_parent(node)) && node == parent->rb_right) -++ node = parent; -++ -++ return parent; -++} -++ -++struct rb_node *rb_prev(struct rb_node *node) -++{ -++ struct rb_node *parent; -++ -++ if (rb_parent(node) == node) -++ return NULL; -++ -++ /* If we have a left-hand child, go down and then right as far -++ as we can. */ -++ if (node->rb_left) { -++ node = node->rb_left; -++ while (node->rb_right) -++ node=node->rb_right; -++ return node; -++ } -++ -++ /* No left-hand children. Go up till we find an ancestor which -++ is a right-hand child of its parent */ -++ while ((parent = rb_parent(node)) && node == parent->rb_left) -++ node = parent; -++ -++ return parent; -++} -++ -++void rb_replace_node(struct rb_node *victim, struct rb_node *new, -++ struct rb_root *root) -++{ -++ struct rb_node *parent = rb_parent(victim); -++ -++ /* Set the surrounding nodes to point to the replacement */ -++ if (parent) { -++ if (victim == parent->rb_left) -++ parent->rb_left = new; -++ else -++ parent->rb_right = new; -++ } else { -++ root->rb_node = new; -++ } -++ if (victim->rb_left) -++ rb_set_parent(victim->rb_left, new); -++ if (victim->rb_right) -++ rb_set_parent(victim->rb_right, new); -++ -++ /* Copy the pointers/colour from the victim to the replacement */ -++ *new = *victim; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/rbtree.h linux-2.6.24.7/drivers/mtd/mtd-utils/rbtree.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/rbtree.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/rbtree.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,168 @@ -++/* -++ Red Black Trees -++ (C) 1999 Andrea Arcangeli -++ -++ This program is free software; you can redistribute it and/or modify -++ it under the terms of the GNU General Public License as published by -++ the Free Software Foundation; either version 2 of the License, or -++ (at your option) any later version. -++ -++ This program is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with this program; if not, write to the Free Software -++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ -++ linux/include/linux/rbtree.h -++ -++ To use rbtrees you'll have to implement your own insert and search cores. -++ This will avoid us to use callbacks and to drop drammatically performances. -++ I know it's not the cleaner way, but in C (not in C++) to get -++ performances and genericity... -++ -++ Some example of insert and search follows here. The search is a plain -++ normal search over an ordered tree. The insert instead must be implemented -++ int two steps: as first thing the code must insert the element in -++ order as a red leaf in the tree, then the support library function -++ rb_insert_color() must be called. Such function will do the -++ not trivial work to rebalance the rbtree if necessary. -++ -++----------------------------------------------------------------------- -++static inline struct page * rb_search_page_cache(struct inode * inode, -++ unsigned long offset) -++{ -++ struct rb_node * n = inode->i_rb_page_cache.rb_node; -++ struct page * page; -++ -++ while (n) -++ { -++ page = rb_entry(n, struct page, rb_page_cache); -++ -++ if (offset < page->offset) -++ n = n->rb_left; -++ else if (offset > page->offset) -++ n = n->rb_right; -++ else -++ return page; -++ } -++ return NULL; -++} -++ -++static inline struct page * __rb_insert_page_cache(struct inode * inode, -++ unsigned long offset, -++ struct rb_node * node) -++{ -++ struct rb_node ** p = &inode->i_rb_page_cache.rb_node; -++ struct rb_node * parent = NULL; -++ struct page * page; -++ -++ while (*p) -++ { -++ parent = *p; -++ page = rb_entry(parent, struct page, rb_page_cache); -++ -++ if (offset < page->offset) -++ p = &(*p)->rb_left; -++ else if (offset > page->offset) -++ p = &(*p)->rb_right; -++ else -++ return page; -++ } -++ -++ rb_link_node(node, parent, p); -++ -++ return NULL; -++} -++ -++static inline struct page * rb_insert_page_cache(struct inode * inode, -++ unsigned long offset, -++ struct rb_node * node) -++{ -++ struct page * ret; -++ if ((ret = __rb_insert_page_cache(inode, offset, node))) -++ goto out; -++ rb_insert_color(node, &inode->i_rb_page_cache); -++ out: -++ return ret; -++} -++----------------------------------------------------------------------- -++*/ -++ -++#ifndef _LINUX_RBTREE_H -++#define _LINUX_RBTREE_H -++ -++#include -++#include -++ -++struct rb_node -++{ -++ unsigned long rb_parent_color; -++#define RB_RED 0 -++#define RB_BLACK 1 -++ struct rb_node *rb_right; -++ struct rb_node *rb_left; -++} __attribute__((aligned(sizeof(long)))); -++ /* The alignment might seem pointless, but allegedly CRIS needs it */ -++ -++struct rb_root -++{ -++ struct rb_node *rb_node; -++}; -++ -++ -++#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) -++#define rb_color(r) ((r)->rb_parent_color & 1) -++#define rb_is_red(r) (!rb_color(r)) -++#define rb_is_black(r) rb_color(r) -++#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) -++#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) -++ -++static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) -++{ -++ rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p; -++} -++static inline void rb_set_color(struct rb_node *rb, int color) -++{ -++ rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; -++} -++ -++#define RB_ROOT (struct rb_root) { NULL, } -++ -++#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) -++ -++#define container_of(ptr, type, member) ({ \ -++ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ -++ (type *)( (char *)__mptr - offsetof(type,member) );}) -++ -++#define rb_entry(ptr, type, member) container_of(ptr, type, member) -++ -++#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) -++#define RB_EMPTY_NODE(node) (rb_parent(node) == node) -++#define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) -++ -++extern void rb_insert_color(struct rb_node *, struct rb_root *); -++extern void rb_erase(struct rb_node *, struct rb_root *); -++ -++/* Find logical next and previous nodes in a tree */ -++extern struct rb_node *rb_next(struct rb_node *); -++extern struct rb_node *rb_prev(struct rb_node *); -++extern struct rb_node *rb_first(struct rb_root *); -++extern struct rb_node *rb_last(struct rb_root *); -++ -++/* Fast replacement of a single node without remove/rebalance/add/rebalance */ -++extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, -++ struct rb_root *root); -++ -++static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, -++ struct rb_node ** rb_link) -++{ -++ node->rb_parent_color = (unsigned long )parent; -++ node->rb_left = node->rb_right = NULL; -++ -++ *rb_link = node; -++} -++ -++#endif /* _LINUX_RBTREE_H */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/recv_image.c linux-2.6.24.7/drivers/mtd/mtd-utils/recv_image.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/recv_image.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/recv_image.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,484 @@ -++ -++#define _XOPEN_SOURCE 500 -++#define _USE_MISC -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "crc32.h" -++#include "mtd/mtd-user.h" -++#include "mcast_image.h" -++ -++#define min(x,y) ( (x)>(y)?(y):(x) ) -++ -++#define WBUF_SIZE 4096 -++struct eraseblock { -++ uint32_t flash_offset; -++ unsigned char wbuf[WBUF_SIZE]; -++ int wbuf_ofs; -++ int nr_pkts; -++ int *pkt_indices; -++ uint32_t crc; -++}; -++ -++int main(int argc, char **argv) -++{ -++ struct addrinfo *ai; -++ struct addrinfo hints; -++ struct addrinfo *runp; -++ int ret; -++ int sock; -++ size_t len; -++ int flfd; -++ struct mtd_info_user meminfo; -++ unsigned char *eb_buf, *decode_buf, **src_pkts; -++ int nr_blocks = 0; -++ int pkts_per_block; -++ int block_nr = -1; -++ uint32_t image_crc; -++ int total_pkts = 0; -++ int ignored_pkts = 0; -++ loff_t mtdoffset = 0; -++ int badcrcs = 0; -++ int duplicates = 0; -++ int file_mode = 0; -++ struct fec_parms *fec; -++ int i; -++ struct eraseblock *eraseblocks = NULL; -++ uint32_t start_seq; -++ struct timeval start, now; -++ unsigned long fec_time = 0, flash_time = 0, crc_time = 0, -++ rflash_time = 0, erase_time = 0, net_time = 0; -++ -++ if (argc != 4) { -++ fprintf(stderr, "usage: %s \n", -++ (strrchr(argv[0], '/')?:argv[0]-1)+1); -++ exit(1); -++ } -++ /* Open the device */ -++ flfd = open(argv[3], O_RDWR); -++ -++ if (flfd >= 0) { -++ /* Fill in MTD device capability structure */ -++ if (ioctl(flfd, MEMGETINFO, &meminfo) != 0) { -++ perror("MEMGETINFO"); -++ close(flfd); -++ flfd = -1; -++ } else { -++ printf("Receive to MTD device %s with erasesize %d\n", -++ argv[3], meminfo.erasesize); -++ } -++ } -++ if (flfd == -1) { -++ /* Try again, as if it's a file */ -++ flfd = open(argv[3], O_CREAT|O_TRUNC|O_RDWR, 0644); -++ if (flfd < 0) { -++ perror("open"); -++ exit(1); -++ } -++ meminfo.erasesize = 131072; -++ file_mode = 1; -++ printf("Receive to file %s with (assumed) erasesize %d\n", -++ argv[3], meminfo.erasesize); -++ } -++ -++ pkts_per_block = (meminfo.erasesize + PKT_SIZE - 1) / PKT_SIZE; -++ -++ eb_buf = malloc(pkts_per_block * PKT_SIZE); -++ decode_buf = malloc(pkts_per_block * PKT_SIZE); -++ if (!eb_buf && !decode_buf) { -++ fprintf(stderr, "No memory for eraseblock buffer\n"); -++ exit(1); -++ } -++ src_pkts = malloc(sizeof(unsigned char *) * pkts_per_block); -++ if (!src_pkts) { -++ fprintf(stderr, "No memory for decode packet pointers\n"); -++ exit(1); -++ } -++ -++ memset(&hints, 0, sizeof(hints)); -++ hints.ai_flags = AI_ADDRCONFIG; -++ hints.ai_socktype = SOCK_DGRAM; -++ -++ ret = getaddrinfo(argv[1], argv[2], &hints, &ai); -++ if (ret) { -++ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret)); -++ exit(1); -++ } -++ runp = ai; -++ for (runp = ai; runp; runp = runp->ai_next) { -++ sock = socket(runp->ai_family, runp->ai_socktype, -++ runp->ai_protocol); -++ if (sock == -1) { -++ perror("socket"); -++ continue; -++ } -++ if (runp->ai_family == AF_INET && -++ IN_MULTICAST( ntohl(((struct sockaddr_in *)runp->ai_addr)->sin_addr.s_addr))) { -++ struct ip_mreq rq; -++ rq.imr_multiaddr = ((struct sockaddr_in *)runp->ai_addr)->sin_addr; -++ rq.imr_interface.s_addr = INADDR_ANY; -++ if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &rq, sizeof(rq))) { -++ perror("IP_ADD_MEMBERSHIP"); -++ close(sock); -++ continue; -++ } -++ -++ } else if (runp->ai_family == AF_INET6 && -++ ((struct sockaddr_in6 *)runp->ai_addr)->sin6_addr.s6_addr[0] == 0xff) { -++ struct ipv6_mreq rq; -++ rq.ipv6mr_multiaddr = ((struct sockaddr_in6 *)runp->ai_addr)->sin6_addr; -++ rq.ipv6mr_interface = 0; -++ if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &rq, sizeof(rq))) { -++ perror("IPV6_ADD_MEMBERSHIP"); -++ close(sock); -++ continue; -++ } -++ } -++ if (bind(sock, runp->ai_addr, runp->ai_addrlen)) { -++ perror("bind"); -++ close(sock); -++ continue; -++ } -++ break; -++ } -++ if (!runp) -++ exit(1); -++ -++ while (1) { -++ struct image_pkt thispkt; -++ -++ len = read(sock, &thispkt, sizeof(thispkt)); -++ -++ if (len < 0) { -++ perror("read socket"); -++ break; -++ } -++ if (len < sizeof(thispkt)) { -++ fprintf(stderr, "Wrong length %d bytes (expected %d)\n", -++ len, sizeof(thispkt)); -++ continue; -++ } -++ if (!eraseblocks) { -++ image_crc = thispkt.hdr.totcrc; -++ start_seq = ntohl(thispkt.hdr.pkt_sequence); -++ -++ if (meminfo.erasesize != ntohl(thispkt.hdr.blocksize)) { -++ fprintf(stderr, "Erasesize mismatch (0x%x not 0x%x)\n", -++ ntohl(thispkt.hdr.blocksize), meminfo.erasesize); -++ exit(1); -++ } -++ nr_blocks = ntohl(thispkt.hdr.nr_blocks); -++ -++ fec = fec_new(pkts_per_block, ntohs(thispkt.hdr.nr_pkts)); -++ -++ eraseblocks = malloc(nr_blocks * sizeof(*eraseblocks)); -++ if (!eraseblocks) { -++ fprintf(stderr, "No memory for block map\n"); -++ exit(1); -++ } -++ for (i = 0; i < nr_blocks; i++) { -++ eraseblocks[i].pkt_indices = malloc(sizeof(int) * pkts_per_block); -++ if (!eraseblocks[i].pkt_indices) { -++ fprintf(stderr, "Failed to allocate packet indices\n"); -++ exit(1); -++ } -++ eraseblocks[i].nr_pkts = 0; -++ if (!file_mode) { -++ if (mtdoffset >= meminfo.size) { -++ fprintf(stderr, "Run out of space on flash\n"); -++ exit(1); -++ } -++#if 1 /* Deliberately use bad blocks... test write failures */ -++ while (ioctl(flfd, MEMGETBADBLOCK, &mtdoffset) > 0) { -++ printf("Skipping flash bad block at %08x\n", (uint32_t)mtdoffset); -++ mtdoffset += meminfo.erasesize; -++ } -++#endif -++ } -++ eraseblocks[i].flash_offset = mtdoffset; -++ mtdoffset += meminfo.erasesize; -++ eraseblocks[i].wbuf_ofs = 0; -++ } -++ gettimeofday(&start, NULL); -++ } -++ if (image_crc != thispkt.hdr.totcrc) { -++ fprintf(stderr, "\nImage CRC changed from 0x%x to 0x%x. Aborting\n", -++ ntohl(image_crc), ntohl(thispkt.hdr.totcrc)); -++ exit(1); -++ } -++ -++ block_nr = ntohl(thispkt.hdr.block_nr); -++ if (block_nr >= nr_blocks) { -++ fprintf(stderr, "\nErroneous block_nr %d (> %d)\n", -++ block_nr, nr_blocks); -++ exit(1); -++ } -++ for (i=0; i= pkts_per_block) { -++ /* We have a block which we didn't really need */ -++ eraseblocks[block_nr].nr_pkts++; -++ ignored_pkts++; -++ continue; -++ } -++ -++ if (crc32(-1, thispkt.data, PKT_SIZE) != ntohl(thispkt.hdr.thiscrc)) { -++ printf("\nDiscard %08x pkt %d with bad CRC (%08x not %08x)\n", -++ block_nr * meminfo.erasesize, ntohs(thispkt.hdr.pkt_nr), -++ crc32(-1, thispkt.data, PKT_SIZE), -++ ntohl(thispkt.hdr.thiscrc)); -++ badcrcs++; -++ continue; -++ } -++ pkt_again: -++ eraseblocks[block_nr].pkt_indices[eraseblocks[block_nr].nr_pkts++] = -++ ntohs(thispkt.hdr.pkt_nr); -++ total_pkts++; -++ if (!(total_pkts % 50) || total_pkts == pkts_per_block * nr_blocks) { -++ uint32_t pkts_sent = ntohl(thispkt.hdr.pkt_sequence) - start_seq + 1; -++ long time_msec; -++ gettimeofday(&now, NULL); -++ -++ time_msec = ((now.tv_usec - start.tv_usec) / 1000) + -++ (now.tv_sec - start.tv_sec) * 1000; -++ -++ printf("\rReceived %d/%d (%d%%) in %lds @%ldKiB/s, %d lost (%d%%), %d dup/xs ", -++ total_pkts, nr_blocks * pkts_per_block, -++ total_pkts * 100 / nr_blocks / pkts_per_block, -++ time_msec / 1000, -++ total_pkts * PKT_SIZE / 1024 * 1000 / time_msec, -++ pkts_sent - total_pkts - duplicates - ignored_pkts, -++ (pkts_sent - total_pkts - duplicates - ignored_pkts) * 100 / pkts_sent, -++ duplicates + ignored_pkts); -++ fflush(stdout); -++ } -++ -++ if (eraseblocks[block_nr].wbuf_ofs + PKT_SIZE < WBUF_SIZE) { -++ /* New packet doesn't full the wbuf */ -++ memcpy(eraseblocks[block_nr].wbuf + eraseblocks[block_nr].wbuf_ofs, -++ thispkt.data, PKT_SIZE); -++ eraseblocks[block_nr].wbuf_ofs += PKT_SIZE; -++ } else { -++ int fits = WBUF_SIZE - eraseblocks[block_nr].wbuf_ofs; -++ ssize_t wrotelen; -++ static int faked = 1; -++ -++ memcpy(eraseblocks[block_nr].wbuf + eraseblocks[block_nr].wbuf_ofs, -++ thispkt.data, fits); -++ wrotelen = pwrite(flfd, eraseblocks[block_nr].wbuf, WBUF_SIZE, -++ eraseblocks[block_nr].flash_offset); -++ -++ if (wrotelen < WBUF_SIZE || (block_nr == 5 && eraseblocks[block_nr].nr_pkts == 5 && !faked)) { -++ faked = 1; -++ if (wrotelen < 0) -++ perror("\npacket write"); -++ else -++ fprintf(stderr, "\nshort write of packet wbuf\n"); -++ -++ if (!file_mode) { -++ struct erase_info_user erase; -++ /* FIXME: Perhaps we should store pkt crcs and try -++ to recover data from the offending eraseblock */ -++ -++ /* We have increased nr_pkts but not yet flash_offset */ -++ erase.start = eraseblocks[block_nr].flash_offset & -++ ~(meminfo.erasesize - 1); -++ erase.length = meminfo.erasesize; -++ -++ printf("Will erase at %08lx len %08lx (bad write was at %08lx)\n", -++ erase.start, erase.length, eraseblocks[block_nr].flash_offset); -++ if (ioctl(flfd, MEMERASE, &erase)) { -++ perror("MEMERASE"); -++ exit(1); -++ } -++ if (mtdoffset >= meminfo.size) { -++ fprintf(stderr, "Run out of space on flash\n"); -++ exit(1); -++ } -++ while (ioctl(flfd, MEMGETBADBLOCK, &mtdoffset) > 0) { -++ printf("Skipping flash bad block at %08x\n", (uint32_t)mtdoffset); -++ mtdoffset += meminfo.erasesize; -++ if (mtdoffset >= meminfo.size) { -++ fprintf(stderr, "Run out of space on flash\n"); -++ exit(1); -++ } -++ } -++ eraseblocks[block_nr].flash_offset = mtdoffset; -++ printf("Block #%d will now be at %08lx\n", block_nr, (long)mtdoffset); -++ total_pkts -= eraseblocks[block_nr].nr_pkts; -++ eraseblocks[block_nr].nr_pkts = 0; -++ eraseblocks[block_nr].wbuf_ofs = 0; -++ mtdoffset += meminfo.erasesize; -++ goto pkt_again; -++ } -++ else /* Usually nothing we can do in file mode */ -++ exit(1); -++ } -++ eraseblocks[block_nr].flash_offset += WBUF_SIZE; -++ /* Copy the remainder into the wbuf */ -++ memcpy(eraseblocks[block_nr].wbuf, &thispkt.data[fits], PKT_SIZE - fits); -++ eraseblocks[block_nr].wbuf_ofs = PKT_SIZE - fits; -++ } -++ -++ if (eraseblocks[block_nr].nr_pkts == pkts_per_block) { -++ eraseblocks[block_nr].crc = ntohl(thispkt.hdr.block_crc); -++ -++ if (total_pkts == nr_blocks * pkts_per_block) -++ break; -++ } -++ } -++ printf("\n"); -++ gettimeofday(&now, NULL); -++ net_time = (now.tv_usec - start.tv_usec) / 1000; -++ net_time += (now.tv_sec - start.tv_sec) * 1000; -++ close(sock); -++ for (block_nr = 0; block_nr < nr_blocks; block_nr++) { -++ ssize_t rwlen; -++ gettimeofday(&start, NULL); -++ eraseblocks[block_nr].flash_offset -= meminfo.erasesize; -++ rwlen = pread(flfd, eb_buf, meminfo.erasesize, eraseblocks[block_nr].flash_offset); -++ -++ gettimeofday(&now, NULL); -++ rflash_time += (now.tv_usec - start.tv_usec) / 1000; -++ rflash_time += (now.tv_sec - start.tv_sec) * 1000; -++ if (rwlen < 0) { -++ perror("read"); -++ /* Argh. Perhaps we could go back and try again, but if the flash is -++ going to fail to read back what we write to it, and the whole point -++ in this program is to write to it, what's the point? */ -++ fprintf(stderr, "Packets we wrote to flash seem to be unreadable. Aborting\n"); -++ exit(1); -++ } -++ -++ memcpy(eb_buf + meminfo.erasesize, eraseblocks[block_nr].wbuf, -++ eraseblocks[block_nr].wbuf_ofs); -++ -++ for (i=0; i < pkts_per_block; i++) -++ src_pkts[i] = &eb_buf[i * PKT_SIZE]; -++ -++ gettimeofday(&start, NULL); -++ if (fec_decode(fec, src_pkts, eraseblocks[block_nr].pkt_indices, PKT_SIZE)) { -++ /* Eep. This cannot happen */ -++ printf("The world is broken. fec_decode() returned error\n"); -++ exit(1); -++ } -++ gettimeofday(&now, NULL); -++ fec_time += (now.tv_usec - start.tv_usec) / 1000; -++ fec_time += (now.tv_sec - start.tv_sec) * 1000; -++ -++ for (i=0; i < pkts_per_block; i++) -++ memcpy(&decode_buf[i*PKT_SIZE], src_pkts[i], PKT_SIZE); -++ -++ /* Paranoia */ -++ gettimeofday(&start, NULL); -++ if (crc32(-1, decode_buf, meminfo.erasesize) != eraseblocks[block_nr].crc) { -++ printf("\nCRC mismatch for block #%d: want %08x got %08x\n", -++ block_nr, eraseblocks[block_nr].crc, -++ crc32(-1, decode_buf, meminfo.erasesize)); -++ exit(1); -++ } -++ gettimeofday(&now, NULL); -++ crc_time += (now.tv_usec - start.tv_usec) / 1000; -++ crc_time += (now.tv_sec - start.tv_sec) * 1000; -++ start = now; -++ -++ if (!file_mode) { -++ struct erase_info_user erase; -++ -++ erase.start = eraseblocks[block_nr].flash_offset; -++ erase.length = meminfo.erasesize; -++ -++ printf("\rErasing block at %08x...", erase.start); -++ -++ if (ioctl(flfd, MEMERASE, &erase)) { -++ perror("MEMERASE"); -++ /* This block has dirty data on it. If the erase failed, we're screwed */ -++ fprintf(stderr, "Erase to clean FEC data from flash failed. Aborting\n"); -++ exit(1); -++ } -++ gettimeofday(&now, NULL); -++ erase_time += (now.tv_usec - start.tv_usec) / 1000; -++ erase_time += (now.tv_sec - start.tv_sec) * 1000; -++ start = now; -++ } -++ else printf("\r"); -++ write_again: -++ rwlen = pwrite(flfd, decode_buf, meminfo.erasesize, eraseblocks[block_nr].flash_offset); -++ if (rwlen < meminfo.erasesize) { -++ if (rwlen < 0) { -++ perror("\ndecoded data write"); -++ } else -++ fprintf(stderr, "\nshort write of decoded data\n"); -++ -++ if (!file_mode) { -++ struct erase_info_user erase; -++ erase.start = eraseblocks[block_nr].flash_offset; -++ erase.length = meminfo.erasesize; -++ -++ printf("Erasing failed block at %08x\n", -++ eraseblocks[block_nr].flash_offset); -++ -++ if (ioctl(flfd, MEMERASE, &erase)) { -++ perror("MEMERASE"); -++ exit(1); -++ } -++ if (mtdoffset >= meminfo.size) { -++ fprintf(stderr, "Run out of space on flash\n"); -++ exit(1); -++ } -++ while (ioctl(flfd, MEMGETBADBLOCK, &mtdoffset) > 0) { -++ printf("Skipping flash bad block at %08x\n", (uint32_t)mtdoffset); -++ mtdoffset += meminfo.erasesize; -++ if (mtdoffset >= meminfo.size) { -++ fprintf(stderr, "Run out of space on flash\n"); -++ exit(1); -++ } -++ } -++ printf("Will try again at %08lx...", (long)mtdoffset); -++ eraseblocks[block_nr].flash_offset = mtdoffset; -++ -++ goto write_again; -++ } -++ else /* Usually nothing we can do in file mode */ -++ exit(1); -++ } -++ gettimeofday(&now, NULL); -++ flash_time += (now.tv_usec - start.tv_usec) / 1000; -++ flash_time += (now.tv_sec - start.tv_sec) * 1000; -++ -++ printf("wrote image block %08x (%d pkts) ", -++ block_nr * meminfo.erasesize, eraseblocks[block_nr].nr_pkts); -++ fflush(stdout); -++ } -++ close(flfd); -++ printf("Net rx %ld.%03lds\n", net_time / 1000, net_time % 1000); -++ printf("flash rd %ld.%03lds\n", rflash_time / 1000, rflash_time % 1000); -++ printf("FEC time %ld.%03lds\n", fec_time / 1000, fec_time % 1000); -++ printf("CRC time %ld.%03lds\n", crc_time / 1000, crc_time % 1000); -++ printf("flash wr %ld.%03lds\n", flash_time / 1000, flash_time % 1000); -++ printf("flash er %ld.%03lds\n", erase_time / 1000, erase_time % 1000); -++ -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/rfddump.c linux-2.6.24.7/drivers/mtd/mtd-utils/rfddump.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/rfddump.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/rfddump.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,336 @@ -++/* -++ * rfddump.c -++ * -++ * Copyright (C) 2005 Sean Young -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ */ -++ -++#define _XOPEN_SOURCE 500 /* For pread */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++ -++/* next is an array of mapping for each corresponding sector */ -++#define RFD_MAGIC 0x9193 -++#define HEADER_MAP_OFFSET 3 -++#define SECTOR_DELETED 0x0000 -++#define SECTOR_ZERO 0xfffe -++#define SECTOR_FREE 0xffff -++ -++#define SECTOR_SIZE 512 -++ -++#define SECTORS_PER_TRACK 63 -++ -++ -++struct rfd { -++ int block_size; -++ int block_count; -++ int header_sectors; -++ int data_sectors; -++ int header_size; -++ uint16_t *header; -++ int sector_count; -++ int *sector_map; -++ const char *mtd_filename; -++ const char *out_filename; -++ int verbose; -++}; -++ -++#define PROGRAM "rfddump" -++#define VERSION "$Revision 1.0 $" -++ -++void display_help(void) -++{ -++ printf("Usage: " PROGRAM " [OPTIONS] MTD-device filename\n" -++ "Dumps the contents of a resident flash disk\n" -++ "\n" -++ "-h --help display this help and exit\n" -++ "-V --version output version information and exit\n" -++ "-v --verbose Be verbose\n" -++ "-b size --blocksize Block size (defaults to erase unit)\n"); -++ exit(0); -++} -++ -++void display_version(void) -++{ -++ printf(PROGRAM " " VERSION "\n" -++ "\n" -++ "This is free software; see the source for copying conditions. There is NO\n" -++ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"); -++ -++ exit(0); -++} -++ -++void process_options(int argc, char *argv[], struct rfd *rfd) -++{ -++ int error = 0; -++ -++ rfd->block_size = 0; -++ rfd->verbose = 0; -++ -++ for (;;) { -++ int option_index = 0; -++ static const char *short_options = "hvVb:"; -++ static const struct option long_options[] = { -++ { "help", no_argument, 0, 'h' }, -++ { "version", no_argument, 0, 'V', }, -++ { "blocksize", required_argument, 0, 'b' }, -++ { "verbose", no_argument, 0, 'v' }, -++ { NULL, 0, 0, 0 } -++ }; -++ -++ int c = getopt_long(argc, argv, short_options, -++ long_options, &option_index); -++ if (c == EOF) -++ break; -++ -++ switch (c) { -++ case 'h': -++ display_help(); -++ break; -++ case 'V': -++ display_version(); -++ break; -++ case 'v': -++ rfd->verbose = 1; -++ break; -++ case 'b': -++ rfd->block_size = atoi(optarg); -++ break; -++ case '?': -++ error = 1; -++ break; -++ } -++ } -++ -++ if ((argc - optind) != 2 || error) -++ display_help(); -++ -++ rfd->mtd_filename = argv[optind]; -++ rfd->out_filename = argv[optind + 1]; -++} -++ -++int build_block_map(struct rfd *rfd, int fd, int block) -++{ -++ int i; -++ int sectors; -++ -++ if (pread(fd, rfd->header, rfd->header_size, block * rfd->block_size) -++ != rfd->header_size) { -++ return -1; -++ } -++ -++ if (le16_to_cpu(rfd->header[0]) != RFD_MAGIC) { -++ if (rfd->verbose) -++ printf("Block #%02d: Magic missing\n", block); -++ -++ return 0; -++ } -++ -++ sectors = 0; -++ for (i=0; idata_sectors; i++) { -++ uint16_t entry = le16_to_cpu(rfd->header[i + HEADER_MAP_OFFSET]); -++ -++ if (entry == SECTOR_FREE || entry == SECTOR_DELETED) -++ continue; -++ -++ if (entry == SECTOR_ZERO) -++ entry = 0; -++ -++ if (entry >= rfd->sector_count) { -++ fprintf(stderr, "%s: warning: sector %d out of range\n", -++ rfd->mtd_filename, entry); -++ continue; -++ } -++ -++ if (rfd->sector_map[entry] != -1) { -++ fprintf(stderr, "%s: warning: more than one entry " -++ "for sector %d\n", rfd->mtd_filename, entry); -++ continue; -++ } -++ -++ rfd->sector_map[entry] = rfd->block_size * block + -++ (i + rfd->header_sectors) * SECTOR_SIZE; -++ sectors++; -++ } -++ -++ if (rfd->verbose) -++ printf("Block #%02d: %d sectors\n", block, sectors); -++ -++ return 1; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int fd, sectors_per_block; -++ mtd_info_t mtd_info; -++ struct rfd rfd; -++ int i, blocks_found; -++ int out_fd = 0; -++ uint8_t sector[512]; -++ int blank, rc, cylinders; -++ -++ process_options(argc, argv, &rfd); -++ -++ fd = open(rfd.mtd_filename, O_RDONLY); -++ if (fd == -1) { -++ perror(rfd.mtd_filename); -++ return 1; -++ } -++ -++ if (rfd.block_size == 0) { -++ if (ioctl(fd, MEMGETINFO, &mtd_info)) { -++ perror(rfd.mtd_filename); -++ close(fd); -++ return 1; -++ } -++ -++ if (mtd_info.type != MTD_NORFLASH) { -++ fprintf(stderr, "%s: wrong type\n", rfd.mtd_filename); -++ close(fd); -++ return 2; -++ } -++ -++ sectors_per_block = mtd_info.erasesize / SECTOR_SIZE; -++ -++ rfd.block_size = mtd_info.erasesize; -++ rfd.block_count = mtd_info.size / mtd_info.erasesize; -++ } else { -++ struct stat st; -++ -++ if (fstat(fd, &st) == -1) { -++ perror(rfd.mtd_filename); -++ close(fd); -++ return 1; -++ } -++ -++ if (st.st_size % SECTOR_SIZE) -++ fprintf(stderr, "%s: warning: not a multiple of sectors (512 bytes)\n", rfd.mtd_filename); -++ -++ sectors_per_block = rfd.block_size / SECTOR_SIZE; -++ -++ if (st.st_size % rfd.block_size) -++ fprintf(stderr, "%s: warning: not a multiple of block size\n", rfd.mtd_filename); -++ -++ rfd.block_count = st.st_size / rfd.block_size; -++ -++ if (!rfd.block_count) { -++ fprintf(stderr, "%s: not large enough for one block\n", rfd.mtd_filename); -++ close(fd); -++ return 2; -++ } -++ } -++ -++ rfd.header_sectors = -++ ((HEADER_MAP_OFFSET + sectors_per_block) * -++ sizeof(uint16_t) + SECTOR_SIZE - 1) / SECTOR_SIZE; -++ rfd.data_sectors = sectors_per_block - rfd.header_sectors; -++ cylinders = ((rfd.block_count - 1) * rfd.data_sectors - 1) -++ / SECTORS_PER_TRACK; -++ rfd.sector_count = cylinders * SECTORS_PER_TRACK; -++ rfd.header_size = -++ (HEADER_MAP_OFFSET + rfd.data_sectors) * sizeof(uint16_t); -++ -++ rfd.header = malloc(rfd.header_size); -++ if (!rfd.header) { -++ perror(PROGRAM); -++ close(fd); -++ return 2; -++ } -++ rfd.sector_map = malloc(rfd.sector_count * sizeof(int)); -++ if (!rfd.sector_map) { -++ perror(PROGRAM); -++ close(fd); -++ free(rfd.sector_map); -++ return 2; -++ } -++ -++ rfd.mtd_filename = rfd.mtd_filename; -++ -++ for (i=0; i 0) -++ blocks_found++; -++ if (rc < 0) -++ goto err; -++ } -++ -++ if (!blocks_found) { -++ fprintf(stderr, "%s: no RFD blocks found\n", rfd.mtd_filename); -++ goto err; -++ } -++ -++ for (i=0; i -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This is very easy: just erase all the blocks and put the magic at -++ * the beginning of each block. -++ */ -++ -++#define _XOPEN_SOURCE 500 /* For pread/pwrite */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#define PROGRAM "rfdformat" -++#define VERSION "$Revision 1.0 $" -++ -++void display_help(void) -++{ -++ printf("Usage: " PROGRAM " [OPTIONS] MTD-device\n" -++ "Formats NOR flash for resident flash disk\n" -++ "\n" -++ "-h --help display this help and exit\n" -++ "-V --version output version information and exit\n"); -++ exit(0); -++} -++ -++void display_version(void) -++{ -++ printf(PROGRAM " " VERSION "\n" -++ "\n" -++ "This is free software; see the source for copying conditions. There is NO\n" -++ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"); -++ -++ exit(0); -++} -++ -++void process_options(int argc, char *argv[], const char **mtd_filename) -++{ -++ int error = 0; -++ -++ for (;;) { -++ int option_index = 0; -++ static const char *short_options = "hV"; -++ static const struct option long_options[] = { -++ { "help", no_argument, 0, 'h' }, -++ { "version", no_argument, 0, 'V', }, -++ { NULL, 0, 0, 0 } -++ }; -++ -++ int c = getopt_long(argc, argv, short_options, -++ long_options, &option_index); -++ if (c == EOF) -++ break; -++ -++ switch (c) { -++ case 'h': -++ display_help(); -++ break; -++ case 'V': -++ display_version(); -++ break; -++ case '?': -++ error = 1; -++ break; -++ } -++ } -++ -++ if ((argc - optind) != 1 || error) -++ display_help(); -++ -++ *mtd_filename = argv[optind]; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ static const uint8_t magic[] = { 0x93, 0x91 }; -++ int fd, block_count, i; -++ struct mtd_info_user mtd_info; -++ char buf[512]; -++ const char *mtd_filename; -++ -++ process_options(argc, argv, &mtd_filename); -++ -++ fd = open(mtd_filename, O_RDWR); -++ if (fd == -1) { -++ perror(mtd_filename); -++ return 1; -++ } -++ -++ if (ioctl(fd, MEMGETINFO, &mtd_info)) { -++ perror(mtd_filename); -++ close(fd); -++ return 1; -++ } -++ -++ if (mtd_info.type != MTD_NORFLASH) { -++ fprintf(stderr, "%s: not NOR flash\n", mtd_filename); -++ close(fd); -++ return 2; -++ } -++ -++ if (mtd_info.size > 32*1024*1024) { -++ fprintf(stderr, "%s: flash larger than 32MiB not supported\n", -++ mtd_filename); -++ close(fd); -++ return 2; -++ } -++ -++ block_count = mtd_info.size / mtd_info.erasesize; -++ -++ if (block_count < 2) { -++ fprintf(stderr, "%s: at least two erase units required\n", -++ mtd_filename); -++ close(fd); -++ return 2; -++ } -++ -++ for (i=0; i -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "crc32.h" -++#include "mcast_image.h" -++ -++int tx_rate = 80000; -++int pkt_delay; -++ -++#undef RANDOMDROP -++ -++int main(int argc, char **argv) -++{ -++ struct addrinfo *ai; -++ struct addrinfo hints; -++ struct addrinfo *runp; -++ int ret; -++ int sock; -++ struct image_pkt pktbuf; -++ int rfd; -++ struct stat st; -++ int writeerrors = 0; -++ uint32_t erasesize; -++ unsigned char *image, *blockptr = NULL; -++ uint32_t block_nr, pkt_nr; -++ int nr_blocks; -++ struct timeval then, now, nextpkt; -++ long time_msecs; -++ int pkts_per_block; -++ int total_pkts_per_block; -++ struct fec_parms *fec; -++ unsigned char *last_block; -++ uint32_t *block_crcs; -++ long tosleep; -++ uint32_t sequence = 0; -++ -++ if (argc == 6) { -++ tx_rate = atol(argv[5]) * 1024; -++ if (tx_rate < PKT_SIZE || tx_rate > 20000000) { -++ fprintf(stderr, "Bogus TX rate %d KiB/s\n", tx_rate); -++ exit(1); -++ } -++ argc = 5; -++ } -++ if (argc != 5) { -++ fprintf(stderr, "usage: %s []\n", -++ (strrchr(argv[0], '/')?:argv[0]-1)+1); -++ exit(1); -++ } -++ pkt_delay = (sizeof(pktbuf) * 1000000) / tx_rate; -++ printf("Inter-packet delay (avg): %dµs\n", pkt_delay); -++ printf("Transmit rate: %d KiB/s\n", tx_rate / 1024); -++ -++ erasesize = atol(argv[4]); -++ if (!erasesize) { -++ fprintf(stderr, "erasesize cannot be zero\n"); -++ exit(1); -++ } -++ -++ pkts_per_block = (erasesize + PKT_SIZE - 1) / PKT_SIZE; -++ total_pkts_per_block = pkts_per_block * 3 / 2; -++ -++ /* We have to pad it with zeroes, so can't use it in-place */ -++ last_block = malloc(pkts_per_block * PKT_SIZE); -++ if (!last_block) { -++ fprintf(stderr, "Failed to allocate last-block buffer\n"); -++ exit(1); -++ } -++ -++ fec = fec_new(pkts_per_block, total_pkts_per_block); -++ if (!fec) { -++ fprintf(stderr, "Error initialising FEC\n"); -++ exit(1); -++ } -++ -++ memset(&hints, 0, sizeof(hints)); -++ hints.ai_flags = AI_ADDRCONFIG; -++ hints.ai_socktype = SOCK_DGRAM; -++ -++ ret = getaddrinfo(argv[1], argv[2], &hints, &ai); -++ if (ret) { -++ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret)); -++ exit(1); -++ } -++ runp = ai; -++ for (runp = ai; runp; runp = runp->ai_next) { -++ sock = socket(runp->ai_family, runp->ai_socktype, -++ runp->ai_protocol); -++ if (sock == -1) { -++ perror("socket"); -++ continue; -++ } -++ if (connect(sock, runp->ai_addr, runp->ai_addrlen) == 0) -++ break; -++ perror("connect"); -++ close(sock); -++ } -++ if (!runp) -++ exit(1); -++ -++ rfd = open(argv[3], O_RDONLY); -++ if (rfd < 0) { -++ perror("open"); -++ exit(1); -++ } -++ -++ if (fstat(rfd, &st)) { -++ perror("fstat"); -++ exit(1); -++ } -++ -++ if (st.st_size % erasesize) { -++ fprintf(stderr, "Image size %ld bytes is not a multiple of erasesize %d bytes\n", -++ st.st_size, erasesize); -++ exit(1); -++ } -++ image = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, rfd, 0); -++ if (image == MAP_FAILED) { -++ perror("mmap"); -++ exit(1); -++ } -++ -++ nr_blocks = st.st_size / erasesize; -++ -++ block_crcs = malloc(nr_blocks * sizeof(uint32_t)); -++ if (!block_crcs) { -++ fprintf(stderr, "Failed to allocate memory for CRCs\n"); -++ exit(1); -++ } -++ -++ memcpy(last_block, image + (nr_blocks - 1) * erasesize, erasesize); -++ memset(last_block + erasesize, 0, (PKT_SIZE * pkts_per_block) - erasesize); -++ -++ printf("Checking CRC...."); -++ fflush(stdout); -++ -++ pktbuf.hdr.resend = 0; -++ pktbuf.hdr.totcrc = htonl(crc32(-1, image, st.st_size)); -++ pktbuf.hdr.nr_blocks = htonl(nr_blocks); -++ pktbuf.hdr.blocksize = htonl(erasesize); -++ pktbuf.hdr.thislen = htonl(PKT_SIZE); -++ pktbuf.hdr.nr_pkts = htons(total_pkts_per_block); -++ -++ printf("%08x\n", ntohl(pktbuf.hdr.totcrc)); -++ printf("Checking block CRCs...."); -++ fflush(stdout); -++ for (block_nr=0; block_nr < nr_blocks; block_nr++) { -++ printf("\rChecking block CRCS.... %d/%d", -++ block_nr + 1, nr_blocks); -++ fflush(stdout); -++ block_crcs[block_nr] = crc32(-1, image + (block_nr * erasesize), erasesize); -++ } -++ -++ printf("\nImage size %ld KiB (0x%08lx). %d blocks at %d pkts/block\n" -++ "Estimated transmit time per cycle: %ds\n", -++ (long)st.st_size / 1024, (long) st.st_size, -++ nr_blocks, pkts_per_block, -++ nr_blocks * pkts_per_block * pkt_delay / 1000000); -++ gettimeofday(&then, NULL); -++ nextpkt = then; -++ -++#ifdef RANDOMDROP -++ srand((unsigned)then.tv_usec); -++ printf("Random seed %u\n", (unsigned)then.tv_usec); -++#endif -++ while (1) for (pkt_nr=0; pkt_nr < total_pkts_per_block; pkt_nr++) { -++ -++ if (blockptr && pkt_nr == 0) { -++ unsigned long amt_sent = total_pkts_per_block * nr_blocks * sizeof(pktbuf); -++ gettimeofday(&now, NULL); -++ -++ time_msecs = (now.tv_sec - then.tv_sec) * 1000; -++ time_msecs += ((int)(now.tv_usec - then.tv_usec)) / 1000; -++ printf("\n%ld KiB sent in %ldms (%ld KiB/s)\n", -++ amt_sent / 1024, time_msecs, -++ amt_sent / 1024 * 1000 / time_msecs); -++ then = now; -++ } -++ -++ for (block_nr = 0; block_nr < nr_blocks; block_nr++) { -++ -++ int actualpkt; -++ -++ /* Calculating the redundant FEC blocks is expensive; -++ the first $pkts_per_block are cheap enough though -++ because they're just copies. So alternate between -++ simple and complex stuff, so that we don't start -++ to choke and fail to keep up with the expected -++ bitrate in the second half of the sequence */ -++ if (block_nr & 1) -++ actualpkt = pkt_nr; -++ else -++ actualpkt = total_pkts_per_block - 1 - pkt_nr; -++ -++ blockptr = image + (erasesize * block_nr); -++ if (block_nr == nr_blocks - 1) -++ blockptr = last_block; -++ -++ fec_encode_linear(fec, blockptr, pktbuf.data, actualpkt, PKT_SIZE); -++ -++ pktbuf.hdr.thiscrc = htonl(crc32(-1, pktbuf.data, PKT_SIZE)); -++ pktbuf.hdr.block_crc = htonl(block_crcs[block_nr]); -++ pktbuf.hdr.block_nr = htonl(block_nr); -++ pktbuf.hdr.pkt_nr = htons(actualpkt); -++ pktbuf.hdr.pkt_sequence = htonl(sequence++); -++ -++ printf("\rSending data block %08x packet %3d/%d", -++ block_nr * erasesize, -++ pkt_nr, total_pkts_per_block); -++ -++ if (pkt_nr && !block_nr) { -++ unsigned long amt_sent = pkt_nr * nr_blocks * sizeof(pktbuf); -++ -++ gettimeofday(&now, NULL); -++ -++ time_msecs = (now.tv_sec - then.tv_sec) * 1000; -++ time_msecs += ((int)(now.tv_usec - then.tv_usec)) / 1000; -++ printf(" (%ld KiB/s) ", -++ amt_sent / 1024 * 1000 / time_msecs); -++ } -++ -++ fflush(stdout); -++ -++#ifdef RANDOMDROP -++ if ((rand() % 1000) < 20) { -++ printf("\nDropping packet %d of block %08x\n", pkt_nr+1, block_nr * erasesize); -++ continue; -++ } -++#endif -++ gettimeofday(&now, NULL); -++#if 1 -++ tosleep = nextpkt.tv_usec - now.tv_usec + -++ (1000000 * (nextpkt.tv_sec - now.tv_sec)); -++ -++ /* We need hrtimers for this to actually work */ -++ if (tosleep > 0) { -++ struct timespec req; -++ -++ req.tv_nsec = (tosleep % 1000000) * 1000; -++ req.tv_sec = tosleep / 1000000; -++ -++ nanosleep(&req, NULL); -++ } -++#else -++ while (now.tv_sec < nextpkt.tv_sec || -++ (now.tv_sec == nextpkt.tv_sec && -++ now.tv_usec < nextpkt.tv_usec)) { -++ gettimeofday(&now, NULL); -++ } -++#endif -++ nextpkt.tv_usec += pkt_delay; -++ if (nextpkt.tv_usec >= 1000000) { -++ nextpkt.tv_sec += nextpkt.tv_usec / 1000000; -++ nextpkt.tv_usec %= 1000000; -++ } -++ -++ /* If the time for the next packet has already -++ passed (by some margin), then we've lost time -++ Adjust our expected timings accordingly. If -++ we're only a little way behind, don't slip yet */ -++ if (now.tv_usec > (now.tv_usec + (5 * pkt_delay) + -++ 1000000 * (nextpkt.tv_sec - now.tv_sec))) { -++ nextpkt = now; -++ } -++ -++ if (write(sock, &pktbuf, sizeof(pktbuf)) < 0) { -++ perror("write"); -++ writeerrors++; -++ if (writeerrors > 10) { -++ fprintf(stderr, "Too many consecutive write errors\n"); -++ exit(1); -++ } -++ } else -++ writeerrors = 0; -++ -++ -++ -++ } -++ } -++ munmap(image, st.st_size); -++ close(rfd); -++ close(sock); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/summary.h linux-2.6.24.7/drivers/mtd/mtd-utils/summary.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/summary.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/summary.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,178 @@ -++/* -++ * JFFS2 -- Journalling Flash File System, Version 2. -++ * -++ * Copyright (C) 2004 Ferenc Havasi , -++ * Zoltan Sogor , -++ * Patrik Kluba , -++ * University of Szeged, Hungary -++ * -++ * For licensing information, see the file 'LICENCE' in this directory. -++ */ -++ -++#ifndef JFFS2_SUMMARY_H -++#define JFFS2_SUMMARY_H -++ -++#include -++#include -++ -++#define DIRTY_SPACE(x) do { typeof(x) _x = (x); \ -++ c->free_size -= _x; c->dirty_size += _x; \ -++ jeb->free_size -= _x ; jeb->dirty_size += _x; \ -++}while(0) -++#define USED_SPACE(x) do { typeof(x) _x = (x); \ -++ c->free_size -= _x; c->used_size += _x; \ -++ jeb->free_size -= _x ; jeb->used_size += _x; \ -++}while(0) -++#define WASTED_SPACE(x) do { typeof(x) _x = (x); \ -++ c->free_size -= _x; c->wasted_size += _x; \ -++ jeb->free_size -= _x ; jeb->wasted_size += _x; \ -++}while(0) -++#define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \ -++ c->free_size -= _x; c->unchecked_size += _x; \ -++ jeb->free_size -= _x ; jeb->unchecked_size += _x; \ -++}while(0) -++ -++#define BLK_STATE_ALLFF 0 -++#define BLK_STATE_CLEAN 1 -++#define BLK_STATE_PARTDIRTY 2 -++#define BLK_STATE_CLEANMARKER 3 -++#define BLK_STATE_ALLDIRTY 4 -++#define BLK_STATE_BADBLOCK 5 -++ -++#define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff -++#define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash)) -++#define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x)) -++#define JFFS2_SUMMARY_XATTR_SIZE (sizeof(struct jffs2_sum_xattr_flash)) -++#define JFFS2_SUMMARY_XREF_SIZE (sizeof(struct jffs2_sum_xref_flash)) -++ -++/* Summary structures used on flash */ -++ -++struct jffs2_sum_unknown_flash -++{ -++ jint16_t nodetype; /* node type */ -++} __attribute__((packed)); -++ -++struct jffs2_sum_inode_flash -++{ -++ jint16_t nodetype; /* node type */ -++ jint32_t inode; /* inode number */ -++ jint32_t version; /* inode version */ -++ jint32_t offset; /* offset on jeb */ -++ jint32_t totlen; /* record length */ -++} __attribute__((packed)); -++ -++struct jffs2_sum_dirent_flash -++{ -++ jint16_t nodetype; /* == JFFS_NODETYPE_DIRENT */ -++ jint32_t totlen; /* record length */ -++ jint32_t offset; /* ofset on jeb */ -++ jint32_t pino; /* parent inode */ -++ jint32_t version; /* dirent version */ -++ jint32_t ino; /* == zero for unlink */ -++ uint8_t nsize; /* dirent name size */ -++ uint8_t type; /* dirent type */ -++ uint8_t name[0]; /* dirent name */ -++} __attribute__((packed)); -++ -++struct jffs2_sum_xattr_flash -++{ -++ jint16_t nodetype; /* == JFFS2_NODETYPE_XATR */ -++ jint32_t xid; /* xattr identifier */ -++ jint32_t version; /* version number */ -++ jint32_t offset; /* offset on jeb */ -++ jint32_t totlen; /* node length */ -++} __attribute__((packed)); -++ -++struct jffs2_sum_xref_flash -++{ -++ jint16_t nodetype; /* == JFFS2_NODETYPE_XREF */ -++ jint32_t offset; /* offset on jeb */ -++} __attribute__((packed)); -++ -++union jffs2_sum_flash -++{ -++ struct jffs2_sum_unknown_flash u; -++ struct jffs2_sum_inode_flash i; -++ struct jffs2_sum_dirent_flash d; -++ struct jffs2_sum_xattr_flash x; -++ struct jffs2_sum_xref_flash r; -++}; -++ -++/* Summary structures used in the memory */ -++ -++struct jffs2_sum_unknown_mem -++{ -++ union jffs2_sum_mem *next; -++ jint16_t nodetype; /* node type */ -++} __attribute__((packed)); -++ -++struct jffs2_sum_inode_mem -++{ -++ union jffs2_sum_mem *next; -++ jint16_t nodetype; /* node type */ -++ jint32_t inode; /* inode number */ -++ jint32_t version; /* inode version */ -++ jint32_t offset; /* offset on jeb */ -++ jint32_t totlen; /* record length */ -++} __attribute__((packed)); -++ -++struct jffs2_sum_dirent_mem -++{ -++ union jffs2_sum_mem *next; -++ jint16_t nodetype; /* == JFFS_NODETYPE_DIRENT */ -++ jint32_t totlen; /* record length */ -++ jint32_t offset; /* ofset on jeb */ -++ jint32_t pino; /* parent inode */ -++ jint32_t version; /* dirent version */ -++ jint32_t ino; /* == zero for unlink */ -++ uint8_t nsize; /* dirent name size */ -++ uint8_t type; /* dirent type */ -++ uint8_t name[0]; /* dirent name */ -++} __attribute__((packed)); -++ -++struct jffs2_sum_xattr_mem -++{ -++ union jffs2_sum_mem *next; -++ jint16_t nodetype; -++ jint32_t xid; -++ jint32_t version; -++ jint32_t offset; -++ jint32_t totlen; -++} __attribute__((packed)); -++ -++struct jffs2_sum_xref_mem -++{ -++ union jffs2_sum_mem *next; -++ jint16_t nodetype; -++ jint32_t offset; -++} __attribute__((packed)); -++ -++union jffs2_sum_mem -++{ -++ struct jffs2_sum_unknown_mem u; -++ struct jffs2_sum_inode_mem i; -++ struct jffs2_sum_dirent_mem d; -++ struct jffs2_sum_xattr_mem x; -++ struct jffs2_sum_xref_mem r; -++}; -++ -++struct jffs2_summary -++{ -++ uint32_t sum_size; -++ uint32_t sum_num; -++ uint32_t sum_padded; -++ union jffs2_sum_mem *sum_list_head; -++ union jffs2_sum_mem *sum_list_tail; -++}; -++ -++/* Summary marker is stored at the end of every sumarized erase block */ -++ -++struct jffs2_sum_marker -++{ -++ jint32_t offset; /* offset of the summary node in the jeb */ -++ jint32_t magic; /* == JFFS2_SUM_MAGIC */ -++}; -++ -++#define JFFS2_SUMMARY_FRAME_SIZE (sizeof(struct jffs2_raw_summary) + sizeof(struct jffs2_sum_marker)) -++ -++#endif -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/sumtool.c linux-2.6.24.7/drivers/mtd/mtd-utils/sumtool.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/sumtool.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/sumtool.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,951 @@ -++/* -++ * sumtool.c -++ * -++ * Copyright (C) 2004 Zoltan Sogor , -++ * Ferenc Havasi -++ * University of Szeged, Hungary -++ * 2006 KaiGai Kohei -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * as published by the Free Software Foundation; either version 2 -++ * of the License, or (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ * GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -++ * -++ * Overview: -++ * This is a utility insert summary information into JFFS2 image for -++ * faster mount time -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "crc32.h" -++#include "summary.h" -++ -++#define PAD(x) (((x)+3)&~3) -++ -++static const char *const app_name = "sumtool"; -++ -++static struct jffs2_summary *sum_collected = NULL; -++ -++static int verbose = 0; -++static int padto = 0; /* pad the output with 0xFF to the end of the final eraseblock */ -++static int add_cleanmarkers = 1; /* add cleanmarker to output */ -++static int use_input_cleanmarker_size = 1; /* use input file's cleanmarker size (default) */ -++static int found_cleanmarkers = 0; /* cleanmarker found in input file */ -++static struct jffs2_unknown_node cleanmarker; -++static int cleanmarker_size = sizeof(cleanmarker); -++static const char *short_options = "o:i:e:hvVblnc:p"; -++static int erase_block_size = 65536; -++static int out_fd = -1; -++static int in_fd = -1; -++ -++static uint8_t *data_buffer = NULL; /* buffer for inodes */ -++static unsigned int data_ofs = 0; /* inode buffer offset */ -++ -++static uint8_t *file_buffer = NULL; /* file buffer contains the actual erase block*/ -++static unsigned int file_ofs = 0; /* position in the buffer */ -++ -++int target_endian = __BYTE_ORDER; -++ -++static struct option long_options[] = { -++ {"output", 1, NULL, 'o'}, -++ {"input", 1, NULL, 'i'}, -++ {"eraseblock", 1, NULL, 'e'}, -++ {"help", 0, NULL, 'h'}, -++ {"verbose", 0, NULL, 'v'}, -++ {"version", 0, NULL, 'V'}, -++ {"bigendian", 0, NULL, 'b'}, -++ {"littleendian", 0, NULL, 'l'}, -++ {"no-cleanmarkers", 0, NULL, 'n'}, -++ {"cleanmarker", 1, NULL, 'c'}, -++ {"pad", 0, NULL, 'p'}, -++ {NULL, 0, NULL, 0} -++}; -++ -++static char *helptext = -++"Usage: sumtool [OPTIONS] -i inputfile -o outputfile\n\n" -++"Convert the input JFFS2 image to a summarized JFFS2 image\n" -++"Summary makes mounting faster - if summary support enabled in your kernel\n\n" -++"Options:\n" -++" -e, --eraseblock=SIZE Use erase block size SIZE (default: 64KiB)\n" -++" (usually 16KiB on NAND)\n" -++" -c, --cleanmarker=SIZE Size of cleanmarker (default 12).\n" -++" (usually 16 bytes on NAND, and will be set to\n" -++" this value if left at the default 12). Will be\n" -++" stored in OOB after each physical page composing\n" -++" a physical eraseblock.\n" -++" -n, --no-cleanmarkers Don't add a cleanmarker to every eraseblock\n" -++" -o, --output=FILE Output to FILE \n" -++" -i, --input=FILE Input from FILE \n" -++" -b, --bigendian Image is big endian\n" -++" -l --littleendian Image is little endian\n" -++" -h, --help Display this help text\n" -++" -v, --verbose Verbose operation\n" -++" -V, --version Display version information\n" -++" -p, --pad Pad the OUTPUT with 0xFF to the end of the final\n" -++" eraseblock\n\n"; -++ -++ -++static char *revtext = "$Revision: 1.1.1.1 $"; -++ -++static unsigned char ffbuf[16] = { -++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -++}; -++ -++static void verror_msg(const char *s, va_list p) -++{ -++ fflush(stdout); -++ fprintf(stderr, "%s: ", app_name); -++ vfprintf(stderr, s, p); -++} -++ -++static void error_msg_and_die(const char *s, ...) -++{ -++ va_list p; -++ -++ va_start(p, s); -++ verror_msg(s, p); -++ va_end(p); -++ putc('\n', stderr); -++ exit(EXIT_FAILURE); -++} -++ -++static void vperror_msg(const char *s, va_list p) -++{ -++ int err = errno; -++ -++ if (s == 0) -++ s = ""; -++ verror_msg(s, p); -++ if (*s) -++ s = ": "; -++ fprintf(stderr, "%s%s\n", s, strerror(err)); -++} -++ -++static void perror_msg_and_die(const char *s, ...) -++{ -++ va_list p; -++ -++ va_start(p, s); -++ vperror_msg(s, p); -++ va_end(p); -++ exit(EXIT_FAILURE); -++} -++ -++ -++ -++static void full_write(void *target_buff, const void *buf, int len); -++ -++void setup_cleanmarker() -++{ -++ cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -++ cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); -++ cleanmarker.totlen = cpu_to_je32(cleanmarker_size); -++ cleanmarker.hdr_crc = cpu_to_je32(crc32(0, &cleanmarker, sizeof(struct jffs2_unknown_node)-4)); -++} -++ -++void process_options (int argc, char **argv) -++{ -++ int opt,c; -++ -++ while ((opt = getopt_long(argc, argv, short_options, long_options, &c)) >= 0) { -++ switch (opt) { -++ case 'o': -++ if (out_fd != -1) -++ error_msg_and_die("output filename specified more than once"); -++ out_fd = open(optarg, O_CREAT | O_TRUNC | O_RDWR, 0644); -++ if (out_fd == -1) -++ perror_msg_and_die("open output file"); -++ break; -++ -++ case 'i': -++ if (in_fd != -1) -++ error_msg_and_die("input filename specified more than once"); -++ in_fd = open(optarg, O_RDONLY); -++ if (in_fd == -1) -++ perror_msg_and_die("open input file"); -++ break; -++ case 'b': -++ target_endian = __BIG_ENDIAN; -++ break; -++ case 'l': -++ target_endian = __LITTLE_ENDIAN; -++ break; -++ case 'h': -++ case '?': -++ error_msg_and_die(helptext); -++ case 'v': -++ verbose = 1; -++ break; -++ -++ case 'V': -++ error_msg_and_die("revision %.*s\n", -++ (int) strlen(revtext) - 13, revtext + 11); -++ -++ case 'e': { -++ char *next; -++ unsigned units = 0; -++ erase_block_size = strtol(optarg, &next, 0); -++ if (!erase_block_size) -++ error_msg_and_die("Unrecognisable erase size\n"); -++ -++ if (*next) { -++ if (!strcmp(next, "KiB")) { -++ units = 1024; -++ } else if (!strcmp(next, "MiB")) { -++ units = 1024 * 1024; -++ } else { -++ error_msg_and_die("Unknown units in erasesize\n"); -++ } -++ } else { -++ if (erase_block_size < 0x1000) -++ units = 1024; -++ else -++ units = 1; -++ } -++ erase_block_size *= units; -++ -++ /* If it's less than 8KiB, they're not allowed */ -++ if (erase_block_size < 0x2000) { -++ fprintf(stderr, "Erase size 0x%x too small. Increasing to 8KiB minimum\n", -++ erase_block_size); -++ erase_block_size = 0x2000; -++ } -++ break; -++ } -++ -++ case 'n': -++ add_cleanmarkers = 0; -++ break; -++ case 'c': -++ cleanmarker_size = strtol(optarg, NULL, 0); -++ -++ if (cleanmarker_size < sizeof(cleanmarker)) { -++ error_msg_and_die("cleanmarker size must be >= 12"); -++ } -++ if (cleanmarker_size >= erase_block_size) { -++ error_msg_and_die("cleanmarker size must be < eraseblock size"); -++ } -++ -++ use_input_cleanmarker_size = 0; -++ found_cleanmarkers = 1; -++ setup_cleanmarker(); -++ -++ break; -++ case 'p': -++ padto = 1; -++ break; -++ } -++ } -++} -++ -++ -++void init_buffers() -++{ -++ data_buffer = malloc(erase_block_size); -++ -++ if (!data_buffer) { -++ perror("out of memory"); -++ close (in_fd); -++ close (out_fd); -++ exit(1); -++ } -++ -++ file_buffer = malloc(erase_block_size); -++ -++ if (!file_buffer) { -++ perror("out of memory"); -++ close (in_fd); -++ close (out_fd); -++ exit(1); -++ } -++} -++ -++void init_sumlist() -++{ -++ sum_collected = (struct jffs2_summary *) malloc (sizeof(struct jffs2_summary)); -++ -++ if (!sum_collected) -++ error_msg_and_die("Can't allocate memory for jffs2_summary!\n"); -++ -++ memset(sum_collected, 0, sizeof(struct jffs2_summary)); -++} -++ -++void clean_buffers() -++{ -++ if (data_buffer) -++ free(data_buffer); -++ if (file_buffer) -++ free(file_buffer); -++} -++ -++void clean_sumlist() -++{ -++ union jffs2_sum_mem *temp; -++ -++ if (sum_collected) { -++ -++ while (sum_collected->sum_list_head) { -++ temp = sum_collected->sum_list_head; -++ sum_collected->sum_list_head = sum_collected->sum_list_head->u.next; -++ free(temp); -++ sum_collected->sum_num--; -++ } -++ -++ if (sum_collected->sum_num != 0) -++ printf("Ooops, something wrong happened! sum_num != 0, but sum_list = null ???"); -++ -++ free(sum_collected); -++ } -++} -++ -++int load_next_block() -++{ -++ int ret; -++ ret = read(in_fd, file_buffer, erase_block_size); -++ file_ofs = 0; -++ -++ if (verbose) -++ printf("Load next block : %d bytes read\n",ret); -++ -++ return ret; -++} -++ -++void write_buff_to_file() -++{ -++ int ret; -++ int len = data_ofs; -++ -++ uint8_t *buf = NULL; -++ -++ buf = data_buffer; -++ while (len > 0) { -++ ret = write(out_fd, buf, len); -++ -++ if (ret < 0) -++ perror_msg_and_die("write"); -++ -++ if (ret == 0) -++ perror_msg_and_die("write returned zero"); -++ -++ len -= ret; -++ buf += ret; -++ } -++ -++ data_ofs = 0; -++} -++ -++void dump_sum_records() -++{ -++ -++ struct jffs2_raw_summary isum; -++ struct jffs2_sum_marker *sm; -++ union jffs2_sum_mem *temp; -++ jint32_t offset; -++ jint32_t *tpage; -++ void *wpage; -++ int datasize, infosize, padsize; -++ jint32_t magic = cpu_to_je32(JFFS2_SUM_MAGIC); -++ -++ if (!sum_collected->sum_num || !sum_collected->sum_list_head) -++ return; -++ -++ datasize = sum_collected->sum_size + sizeof(struct jffs2_sum_marker); -++ infosize = sizeof(struct jffs2_raw_summary) + datasize; -++ padsize = erase_block_size - data_ofs - infosize; -++ infosize += padsize; datasize += padsize; -++ offset = cpu_to_je32(data_ofs); -++ -++ tpage = (jint32_t *) malloc(datasize); -++ -++ if(!tpage) -++ error_msg_and_die("Can't allocate memory to dump summary information!\n"); -++ -++ memset(tpage, 0xff, datasize); -++ memset(&isum, 0, sizeof(isum)); -++ -++ isum.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); -++ isum.nodetype = cpu_to_je16(JFFS2_NODETYPE_SUMMARY); -++ isum.totlen = cpu_to_je32(infosize); -++ isum.hdr_crc = cpu_to_je32(crc32(0, &isum, sizeof(struct jffs2_unknown_node) - 4)); -++ isum.padded = cpu_to_je32(0); -++ -++ if (add_cleanmarkers && found_cleanmarkers) { -++ isum.cln_mkr = cpu_to_je32(cleanmarker_size); -++ } else { -++ isum.cln_mkr = cpu_to_je32(0); -++ } -++ -++ isum.sum_num = cpu_to_je32(sum_collected->sum_num); -++ wpage = tpage; -++ -++ while (sum_collected->sum_num) { -++ switch(je16_to_cpu(sum_collected->sum_list_head->u.nodetype)) { -++ -++ case JFFS2_NODETYPE_INODE : { -++ struct jffs2_sum_inode_flash *sino_ptr = wpage; -++ -++ sino_ptr->nodetype = sum_collected->sum_list_head->i.nodetype; -++ sino_ptr->inode = sum_collected->sum_list_head->i.inode; -++ sino_ptr->version = sum_collected->sum_list_head->i.version; -++ sino_ptr->offset = sum_collected->sum_list_head->i.offset; -++ sino_ptr->totlen = sum_collected->sum_list_head->i.totlen; -++ -++ wpage += JFFS2_SUMMARY_INODE_SIZE; -++ break; -++ } -++ -++ case JFFS2_NODETYPE_DIRENT : { -++ struct jffs2_sum_dirent_flash *sdrnt_ptr = wpage; -++ -++ sdrnt_ptr->nodetype = sum_collected->sum_list_head->d.nodetype; -++ sdrnt_ptr->totlen = sum_collected->sum_list_head->d.totlen; -++ sdrnt_ptr->offset = sum_collected->sum_list_head->d.offset; -++ sdrnt_ptr->pino = sum_collected->sum_list_head->d.pino; -++ sdrnt_ptr->version = sum_collected->sum_list_head->d.version; -++ sdrnt_ptr->ino = sum_collected->sum_list_head->d.ino; -++ sdrnt_ptr->nsize = sum_collected->sum_list_head->d.nsize; -++ sdrnt_ptr->type = sum_collected->sum_list_head->d.type; -++ -++ memcpy(sdrnt_ptr->name, sum_collected->sum_list_head->d.name, -++ sum_collected->sum_list_head->d.nsize); -++ -++ wpage += JFFS2_SUMMARY_DIRENT_SIZE(sum_collected->sum_list_head->d.nsize); -++ break; -++ } -++ -++ case JFFS2_NODETYPE_XATTR: { -++ struct jffs2_sum_xattr_flash *sxattr_ptr = wpage; -++ -++ sxattr_ptr->nodetype = sum_collected->sum_list_head->x.nodetype; -++ sxattr_ptr->xid = sum_collected->sum_list_head->x.xid; -++ sxattr_ptr->version = sum_collected->sum_list_head->x.version; -++ sxattr_ptr->offset = sum_collected->sum_list_head->x.offset; -++ sxattr_ptr->totlen = sum_collected->sum_list_head->x.totlen; -++ -++ wpage += JFFS2_SUMMARY_XATTR_SIZE; -++ break; -++ } -++ -++ case JFFS2_NODETYPE_XREF: { -++ struct jffs2_sum_xref_flash *sxref_ptr = wpage; -++ -++ sxref_ptr->nodetype = sum_collected->sum_list_head->r.nodetype; -++ sxref_ptr->offset = sum_collected->sum_list_head->r.offset; -++ -++ wpage += JFFS2_SUMMARY_XREF_SIZE; -++ break; -++ } -++ -++ default : { -++ printf("Unknown node type!\n"); -++ } -++ } -++ -++ temp = sum_collected->sum_list_head; -++ sum_collected->sum_list_head = sum_collected->sum_list_head->u.next; -++ free(temp); -++ -++ sum_collected->sum_num--; -++ } -++ -++ sum_collected->sum_size = 0; -++ sum_collected->sum_num = 0; -++ sum_collected->sum_list_tail = NULL; -++ -++ wpage += padsize; -++ -++ sm = wpage; -++ sm->offset = offset; -++ sm->magic = magic; -++ -++ isum.sum_crc = cpu_to_je32(crc32(0, tpage, datasize)); -++ isum.node_crc = cpu_to_je32(crc32(0, &isum, sizeof(isum) - 8)); -++ -++ full_write(data_buffer + data_ofs, &isum, sizeof(isum)); -++ full_write(data_buffer + data_ofs, tpage, datasize); -++ -++ free(tpage); -++} -++ -++static void full_write(void *target_buff, const void *buf, int len) -++{ -++ memcpy(target_buff, buf, len); -++ data_ofs += len; -++} -++ -++static void pad(int req) -++{ -++ while (req) { -++ if (req > sizeof(ffbuf)) { -++ full_write(data_buffer + data_ofs, ffbuf, sizeof(ffbuf)); -++ req -= sizeof(ffbuf); -++ } else { -++ full_write(data_buffer + data_ofs, ffbuf, req); -++ req = 0; -++ } -++ } -++} -++ -++static inline void padword() -++{ -++ if (data_ofs % 4) -++ full_write(data_buffer + data_ofs, ffbuf, 4 - (data_ofs % 4)); -++} -++ -++ -++static inline void pad_block_if_less_than(int req,int plus) -++{ -++ -++ int datasize = req + plus + sum_collected->sum_size + sizeof(struct jffs2_raw_summary) + 8; -++ datasize += (4 - (datasize % 4)) % 4; -++ -++ if (data_ofs + req > erase_block_size - datasize) { -++ dump_sum_records(); -++ write_buff_to_file(); -++ } -++ -++ if (add_cleanmarkers && found_cleanmarkers) { -++ if (!data_ofs) { -++ full_write(data_buffer, &cleanmarker, sizeof(cleanmarker)); -++ pad(cleanmarker_size - sizeof(cleanmarker)); -++ padword(); -++ } -++ } -++} -++ -++void flush_buffers() -++{ -++ -++ if ((add_cleanmarkers == 1) && (found_cleanmarkers == 1)) { /* CLEANMARKER */ -++ if (data_ofs != cleanmarker_size) { /* INODE BUFFER */ -++ -++ int datasize = sum_collected->sum_size + sizeof(struct jffs2_raw_summary) + 8; -++ datasize += (4 - (datasize % 4)) % 4; -++ -++ /* If we have a full inode buffer, then write out inode and summary data */ -++ if (data_ofs + sizeof(struct jffs2_raw_inode) + 2*JFFS2_MIN_DATA_LEN > erase_block_size - datasize) { -++ dump_sum_records(); -++ write_buff_to_file(); -++ } else { /* else just write out inode data */ -++ if (padto) -++ pad(erase_block_size - data_ofs); -++ write_buff_to_file(); -++ } -++ } -++ } else { /* NO CLEANMARKER */ -++ if (data_ofs != 0) { /* INODE BUFFER */ -++ -++ int datasize = sum_collected->sum_size + sizeof(struct jffs2_raw_summary) + 8; -++ datasize += (4 - (datasize % 4)) % 4; -++ -++ /* If we have a full inode buffer, then write out inode and summary data */ -++ if (data_ofs + sizeof(struct jffs2_raw_inode) + 2*JFFS2_MIN_DATA_LEN > erase_block_size - datasize) { -++ dump_sum_records(); -++ write_buff_to_file(); -++ } else { /* Else just write out inode data */ -++ if(padto) -++ pad(erase_block_size - data_ofs); -++ write_buff_to_file(); -++ } -++ } -++ } -++} -++ -++int add_sum_mem(union jffs2_sum_mem *item) -++{ -++ -++ if (!sum_collected->sum_list_head) -++ sum_collected->sum_list_head = (union jffs2_sum_mem *) item; -++ if (sum_collected->sum_list_tail) -++ sum_collected->sum_list_tail->u.next = (union jffs2_sum_mem *) item; -++ sum_collected->sum_list_tail = (union jffs2_sum_mem *) item; -++ -++ switch (je16_to_cpu(item->u.nodetype)) { -++ case JFFS2_NODETYPE_INODE: -++ sum_collected->sum_size += JFFS2_SUMMARY_INODE_SIZE; -++ sum_collected->sum_num++; -++ break; -++ -++ case JFFS2_NODETYPE_DIRENT: -++ sum_collected->sum_size += JFFS2_SUMMARY_DIRENT_SIZE(item->d.nsize); -++ sum_collected->sum_num++; -++ break; -++ -++ case JFFS2_NODETYPE_XATTR: -++ sum_collected->sum_size += JFFS2_SUMMARY_XATTR_SIZE; -++ sum_collected->sum_num++; -++ break; -++ -++ case JFFS2_NODETYPE_XREF: -++ sum_collected->sum_size += JFFS2_SUMMARY_XREF_SIZE; -++ sum_collected->sum_num++; -++ break; -++ -++ default: -++ error_msg_and_die("__jffs2_add_sum_mem(): UNKNOWN node type %d\n", je16_to_cpu(item->u.nodetype)); -++ } -++ return 0; -++} -++ -++void add_sum_inode_mem(union jffs2_node_union *node) -++{ -++ struct jffs2_sum_inode_mem *temp = (struct jffs2_sum_inode_mem *) malloc(sizeof(struct jffs2_sum_inode_mem)); -++ -++ if (!temp) -++ error_msg_and_die("Can't allocate memory for summary information!\n"); -++ -++ temp->nodetype = node->i.nodetype; -++ temp->inode = node->i.ino; -++ temp->version = node->i.version; -++ temp->offset = cpu_to_je32(data_ofs); -++ temp->totlen = node->i.totlen; -++ temp->next = NULL; -++ -++ add_sum_mem((union jffs2_sum_mem *) temp); -++} -++ -++void add_sum_dirent_mem(union jffs2_node_union *node) -++{ -++ struct jffs2_sum_dirent_mem *temp = (struct jffs2_sum_dirent_mem *) -++ malloc(sizeof(struct jffs2_sum_dirent_mem) + node->d.nsize); -++ -++ if (!temp) -++ error_msg_and_die("Can't allocate memory for summary information!\n"); -++ -++ temp->nodetype = node->d.nodetype; -++ temp->totlen = node->d.totlen; -++ temp->offset = cpu_to_je32(data_ofs); -++ temp->pino = node->d.pino; -++ temp->version = node->d.version; -++ temp->ino = node->d.ino; -++ temp->nsize = node->d.nsize; -++ temp->type = node->d.type; -++ temp->next = NULL; -++ -++ memcpy(temp->name,node->d.name,node->d.nsize); -++ add_sum_mem((union jffs2_sum_mem *) temp); -++} -++ -++void add_sum_xattr_mem(union jffs2_node_union *node) -++{ -++ struct jffs2_sum_xattr_mem *temp = (struct jffs2_sum_xattr_mem *) -++ malloc(sizeof(struct jffs2_sum_xattr_mem)); -++ if (!temp) -++ error_msg_and_die("Can't allocate memory for summary information!\n"); -++ -++ temp->nodetype = node->x.nodetype; -++ temp->xid = node->x.xid; -++ temp->version = node->x.version; -++ temp->offset = cpu_to_je32(data_ofs); -++ temp->totlen = node->x.totlen; -++ temp->next = NULL; -++ -++ add_sum_mem((union jffs2_sum_mem *) temp); -++} -++ -++void add_sum_xref_mem(union jffs2_node_union *node) -++{ -++ struct jffs2_sum_xref_mem *temp = (struct jffs2_sum_xref_mem *) -++ malloc(sizeof(struct jffs2_sum_xref_mem)); -++ if (!temp) -++ error_msg_and_die("Can't allocate memory for summary information!\n"); -++ -++ temp->nodetype = node->r.nodetype; -++ temp->offset = cpu_to_je32(data_ofs); -++ temp->next = NULL; -++ -++ add_sum_mem((union jffs2_sum_mem *) temp); -++} -++ -++void write_dirent_to_buff(union jffs2_node_union *node) -++{ -++ pad_block_if_less_than(je32_to_cpu (node->d.totlen),JFFS2_SUMMARY_DIRENT_SIZE(node->d.nsize)); -++ add_sum_dirent_mem(node); -++ full_write(data_buffer + data_ofs, &(node->d), je32_to_cpu (node->d.totlen)); -++ padword(); -++} -++ -++ -++void write_inode_to_buff(union jffs2_node_union *node) -++{ -++ pad_block_if_less_than(je32_to_cpu (node->i.totlen),JFFS2_SUMMARY_INODE_SIZE); -++ add_sum_inode_mem(node); /* Add inode summary mem to summary list */ -++ full_write(data_buffer + data_ofs, &(node->i), je32_to_cpu (node->i.totlen)); /* Write out the inode to inode_buffer */ -++ padword(); -++} -++ -++void write_xattr_to_buff(union jffs2_node_union *node) -++{ -++ pad_block_if_less_than(je32_to_cpu(node->x.totlen), JFFS2_SUMMARY_XATTR_SIZE); -++ add_sum_xattr_mem(node); /* Add xdatum summary mem to summary list */ -++ full_write(data_buffer + data_ofs, &(node->x), je32_to_cpu(node->x.totlen)); -++ padword(); -++} -++ -++void write_xref_to_buff(union jffs2_node_union *node) -++{ -++ pad_block_if_less_than(je32_to_cpu(node->r.totlen), JFFS2_SUMMARY_XREF_SIZE); -++ add_sum_xref_mem(node); /* Add xref summary mem to summary list */ -++ full_write(data_buffer + data_ofs, &(node->r), je32_to_cpu(node->r.totlen)); -++ padword(); -++} -++ -++void create_summed_image(int inp_size) -++{ -++ uint8_t *p = file_buffer; -++ union jffs2_node_union *node; -++ uint32_t crc, length; -++ uint16_t type; -++ int bitchbitmask = 0; -++ int obsolete; -++ char name[256]; -++ -++ while ( p < (file_buffer + inp_size)) { -++ -++ node = (union jffs2_node_union *) p; -++ -++ /* Skip empty space */ -++ if (je16_to_cpu (node->u.magic) == 0xFFFF && je16_to_cpu (node->u.nodetype) == 0xFFFF) { -++ p += 4; -++ continue; -++ } -++ -++ if (je16_to_cpu (node->u.magic) != JFFS2_MAGIC_BITMASK) { -++ if (!bitchbitmask++) -++ printf ("Wrong bitmask at 0x%08x, 0x%04x\n", p - file_buffer, je16_to_cpu (node->u.magic)); -++ p += 4; -++ continue; -++ } -++ -++ bitchbitmask = 0; -++ -++ type = je16_to_cpu(node->u.nodetype); -++ if ((type & JFFS2_NODE_ACCURATE) != JFFS2_NODE_ACCURATE) { -++ obsolete = 1; -++ type |= JFFS2_NODE_ACCURATE; -++ } else { -++ obsolete = 0; -++ } -++ -++ node->u.nodetype = cpu_to_je16(type); -++ -++ crc = crc32 (0, node, sizeof (struct jffs2_unknown_node) - 4); -++ if (crc != je32_to_cpu (node->u.hdr_crc)) { -++ printf ("Wrong hdr_crc at 0x%08x, 0x%08x instead of 0x%08x\n", p - file_buffer, je32_to_cpu (node->u.hdr_crc), crc); -++ p += 4; -++ continue; -++ } -++ -++ switch(je16_to_cpu(node->u.nodetype)) { -++ case JFFS2_NODETYPE_INODE: -++ if (verbose) -++ printf ("%8s Inode node at 0x%08x, totlen 0x%08x, #ino %5d, version %5d, isize %8d, csize %8d, dsize %8d, offset %8d\n", -++ obsolete ? "Obsolete" : "", -++ p - file_buffer, je32_to_cpu (node->i.totlen), je32_to_cpu (node->i.ino), -++ je32_to_cpu ( node->i.version), je32_to_cpu (node->i.isize), -++ je32_to_cpu (node->i.csize), je32_to_cpu (node->i.dsize), je32_to_cpu (node->i.offset)); -++ -++ crc = crc32 (0, node, sizeof (struct jffs2_raw_inode) - 8); -++ if (crc != je32_to_cpu (node->i.node_crc)) { -++ printf ("Wrong node_crc at 0x%08x, 0x%08x instead of 0x%08x\n", p - file_buffer, je32_to_cpu (node->i.node_crc), crc); -++ p += PAD(je32_to_cpu (node->i.totlen)); -++ continue; -++ } -++ -++ crc = crc32(0, p + sizeof (struct jffs2_raw_inode), je32_to_cpu(node->i.csize)); -++ if (crc != je32_to_cpu(node->i.data_crc)) { -++ printf ("Wrong data_crc at 0x%08x, 0x%08x instead of 0x%08x\n", p - file_buffer, je32_to_cpu (node->i.data_crc), crc); -++ p += PAD(je32_to_cpu (node->i.totlen)); -++ continue; -++ } -++ -++ write_inode_to_buff(node); -++ -++ p += PAD(je32_to_cpu (node->i.totlen)); -++ break; -++ -++ case JFFS2_NODETYPE_DIRENT: -++ memcpy (name, node->d.name, node->d.nsize); -++ name [node->d.nsize] = 0x0; -++ -++ if (verbose) -++ printf ("%8s Dirent node at 0x%08x, totlen 0x%08x, #pino %5d, version %5d, #ino %8d, nsize %8d, name %s\n", -++ obsolete ? "Obsolete" : "", -++ p - file_buffer, je32_to_cpu (node->d.totlen), je32_to_cpu (node->d.pino), -++ je32_to_cpu ( node->d.version), je32_to_cpu (node->d.ino), -++ node->d.nsize, name); -++ -++ crc = crc32 (0, node, sizeof (struct jffs2_raw_dirent) - 8); -++ if (crc != je32_to_cpu (node->d.node_crc)) { -++ printf ("Wrong node_crc at 0x%08x, 0x%08x instead of 0x%08x\n", p - file_buffer, je32_to_cpu (node->d.node_crc), crc); -++ p += PAD(je32_to_cpu (node->d.totlen)); -++ continue; -++ } -++ -++ crc = crc32(0, p + sizeof (struct jffs2_raw_dirent), node->d.nsize); -++ if (crc != je32_to_cpu(node->d.name_crc)) { -++ printf ("Wrong name_crc at 0x%08x, 0x%08x instead of 0x%08x\n", p - file_buffer, je32_to_cpu (node->d.name_crc), crc); -++ p += PAD(je32_to_cpu (node->d.totlen)); -++ continue; -++ } -++ -++ write_dirent_to_buff(node); -++ -++ p += PAD(je32_to_cpu (node->d.totlen)); -++ break; -++ -++ case JFFS2_NODETYPE_XATTR: -++ if (je32_to_cpu(node->x.node_crc) == 0xffffffff) -++ obsolete = 1; -++ if (verbose) -++ printf("%8s Xdatum node at 0x%08x, totlen 0x%08x, " -++ "#xid %5u, version %5u\n", -++ obsolete ? "Obsolete" : "", -++ p - file_buffer, je32_to_cpu (node->x.totlen), -++ je32_to_cpu(node->x.xid), je32_to_cpu(node->x.version)); -++ crc = crc32(0, node, sizeof (struct jffs2_raw_xattr) - 4); -++ if (crc != je32_to_cpu(node->x.node_crc)) { -++ printf("Wrong node_crc at 0x%08x, 0x%08x instead of 0x%08x\n", -++ p - file_buffer, je32_to_cpu(node->x.node_crc), crc); -++ p += PAD(je32_to_cpu (node->x.totlen)); -++ continue; -++ } -++ length = node->x.name_len + 1 + je16_to_cpu(node->x.value_len); -++ crc = crc32(0, node->x.data, length); -++ if (crc != je32_to_cpu(node->x.data_crc)) { -++ printf("Wrong data_crc at 0x%08x, 0x%08x instead of 0x%08x\n", -++ p - file_buffer, je32_to_cpu(node->x.data_crc), crc); -++ p += PAD(je32_to_cpu (node->x.totlen)); -++ continue; -++ } -++ -++ write_xattr_to_buff(node); -++ p += PAD(je32_to_cpu (node->x.totlen)); -++ break; -++ -++ case JFFS2_NODETYPE_XREF: -++ if (je32_to_cpu(node->r.node_crc) == 0xffffffff) -++ obsolete = 1; -++ if (verbose) -++ printf("%8s Xref node at 0x%08x, totlen 0x%08x, " -++ "#ino %5u, xid %5u\n", -++ obsolete ? "Obsolete" : "", -++ p - file_buffer, je32_to_cpu(node->r.totlen), -++ je32_to_cpu(node->r.ino), je32_to_cpu(node->r.xid)); -++ crc = crc32(0, node, sizeof (struct jffs2_raw_xref) - 4); -++ if (crc != je32_to_cpu(node->r.node_crc)) { -++ printf("Wrong node_crc at 0x%08x, 0x%08x instead of 0x%08x\n", -++ p - file_buffer, je32_to_cpu(node->r.node_crc), crc); -++ p += PAD(je32_to_cpu (node->r.totlen)); -++ continue; -++ } -++ -++ write_xref_to_buff(node); -++ p += PAD(je32_to_cpu (node->r.totlen)); -++ break; -++ -++ case JFFS2_NODETYPE_CLEANMARKER: -++ if (verbose) { -++ printf ("%8s Cleanmarker at 0x%08x, totlen 0x%08x\n", -++ obsolete ? "Obsolete" : "", -++ p - file_buffer, je32_to_cpu (node->u.totlen)); -++ } -++ -++ if (!found_cleanmarkers) { -++ found_cleanmarkers = 1; -++ -++ if (add_cleanmarkers == 1 && use_input_cleanmarker_size == 1){ -++ cleanmarker_size = je32_to_cpu (node->u.totlen); -++ setup_cleanmarker(); -++ } -++ } -++ -++ p += PAD(je32_to_cpu (node->u.totlen)); -++ break; -++ -++ case JFFS2_NODETYPE_PADDING: -++ if (verbose) { -++ printf ("%8s Padding node at 0x%08x, totlen 0x%08x\n", -++ obsolete ? "Obsolete" : "", -++ p - file_buffer, je32_to_cpu (node->u.totlen)); -++ } -++ p += PAD(je32_to_cpu (node->u.totlen)); -++ break; -++ -++ case 0xffff: -++ p += 4; -++ break; -++ -++ default: -++ if (verbose) { -++ printf ("%8s Unknown node at 0x%08x, totlen 0x%08x\n", -++ obsolete ? "Obsolete" : "", -++ p - file_buffer, je32_to_cpu (node->u.totlen)); -++ } -++ -++ p += PAD(je32_to_cpu (node->u.totlen)); -++ } -++ } -++} -++ -++int main(int argc, char **argv) -++{ -++ int ret; -++ -++ process_options(argc,argv); -++ -++ if ((in_fd == -1) || (out_fd == -1)) { -++ if(in_fd != -1) -++ close(in_fd); -++ if(out_fd != -1) -++ close(out_fd); -++ fprintf(stderr,helptext); -++ error_msg_and_die("You must specify input and output files!\n"); -++ } -++ -++ init_buffers(); -++ init_sumlist(); -++ -++ while ((ret = load_next_block())) { -++ create_summed_image(ret); -++ } -++ -++ flush_buffers(); -++ clean_buffers(); -++ clean_sumlist(); -++ -++ if (in_fd != -1) -++ close(in_fd); -++ if (out_fd != -1) -++ close(out_fd); -++ -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/checkfs/Makefile linux-2.6.24.7/drivers/mtd/mtd-utils/tests/checkfs/Makefile -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/checkfs/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/checkfs/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,14 @@ -++ -++all: checkfs makefiles -++ -++checkfs: checkfs.c Makefile common.h comm.o -++ gcc -g -Wall checkfs.c comm.o -o checkfs -++ -++comm.o: comm.c Makefile -++ gcc -g -Wall -c comm.c -o comm.o -++ -++makefiles: makefiles.c Makefile common.h -++ gcc -g -Wall makefiles.c -o makefiles -++ -++clean: -++ rm -f makefiles checkfs *~ *.o -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/checkfs/README linux-2.6.24.7/drivers/mtd/mtd-utils/tests/checkfs/README -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/checkfs/README 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/checkfs/README 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,173 @@ -++$Id: README,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ -++$Log: not supported by cvs2svn $ -++Revision 1.2 2001/06/21 23:07:06 dwmw2 -++Initial import to MTD CVS -++ -++Revision 1.1 2001/06/11 19:34:40 vipin -++Added README file to dir. -++ -++ -++This is the README file for the "checkfs" power fail test program. -++By: Vipin Malik -++ -++NOTE: This program requires an external "power cycling box" -++connected to one of the com ports of the system under test. -++This power cycling box should wait for a random amount of time -++after it receives a "ok to power me down" message over the -++serial port, and then yank power to the system under test. -++(The box that I rigged up tested with waits anywhere from -++0 to ~40 seconds). -++ -++ -++It should then restore power after a few seconds and wait for the -++message again. -++ -++ -++ABOUT: -++ -++This program's primary purpose it to test the reliiability -++of various file systems under Linux. -++ -++SETUP: -++ -++You need to setup the file system you want to test and run the -++"makefiles" program ONCE. This creates a set of files that are -++required by the "checkfs" program. -++ -++Also copy the "checkfs" executable program to the same dir. -++ -++Then you need to make sure that the program "checkfs" is called -++automatically on startup. You can customise the operation of -++the "checkfs" program by passing it various cmd line arguments. -++run "checkfs -?" for more details. -++ -++****NOTE******* -++Make sure that you call the checkfs program only after you have -++mounted the file system you want to test (this is obvious), but -++also after you have run any "scan" utilities to check for and -++fix any file systems errors. The e2fsck is one utility for the -++ext2 file system. For an automated setup you of course need to -++provide these scan programs to run in standalone mode (-f -y -++flags for e2fsck for example). -++ -++File systems like JFFS and JFFS2 do not have any such external -++utilities and you may call "checkfs" right after you have mounted -++the respective file system under test. -++ -++There are two ways you can mount the file system under test: -++ -++1. Mount your root fs on a "standard" fs like ext2 and then -++mount the file system under test (which may be ext2 on another -++partition or device) and then run "checkfs" on this mounted -++partition OR -++ -++2. Make your fs AND device that you have put this fs as your -++root fs and run "checkfs" on the root device (i.e. "/"). -++You can of course still run checkfs under a separate dir -++under your "/" root dir. -++ -++I have found the second method to be a particularly stringent -++arrangement (and thus preferred when you are trying to break -++something). -++ -++Using this arrangement I was able to find that JFFS clobbered -++some "sister" files on the root fs even though "checkfs" would -++run fine through all its own check files. -++ -++(I found this out when one of the clobbered sister file happened -++to be /bin/bash. The system refused to run rc.local thus -++preventing my "checkfs" program from being launched :) -++ -++"checkfs": -++ -++The "formatting" reliability of the fs as well as the file data integrity -++of files on the fs can be checked using this program. -++ -++"formatiing" reliability can only be checked via an indirect method. -++If there is severe formatting reliability issues with the file system, -++it will most likely cause other system failures that will prevent this -++program from running successfully on a power up. This will prevent -++a "ok to power me down" message from going out to the power cycling -++black box and prevent power being turned off again. -++ -++File data reliability is checked more directly. A fixed number of -++files are created in the current dir (using the program "makefiles"). -++ -++Each file has a random number of bytes in it (set by using the -++-s cmd line flag). The number of "ints" in the file is stored as the -++first "int" in it (note: 0 length files are not allowed). Each file -++is then filled with random data and a 16 bit CRC appended at the end. -++ -++When "checkfs" is run, it runs through all files (with predetermined -++file names)- one at a time- and checks for the number of "int's" -++in it as well as the ending CRC. -++ -++The program exits if the numbers of files that are corrupt are greater -++that a user specified parameter (set by using the -e cmd line flag). -++ -++If the number of corrupt files is less than this parameter, the corrupt -++files are repaired and operation resumes as explained below. -++ -++The idea behind allowing a user specified amount of corrupt files is as -++follows: -++ -++If you are testing for "formatting" reliability of a fs, and for -++the data reliability of "other" files present of the fs, use -e 1. -++"other" files are defined as sister files on the fs, not being written to -++by the "checkfs" test program. -++ -++As mentioned, in this case you would set -e 1, or allow at most 1 file -++to be corrupt each time after a power fail. This would be the file -++that was probably being written to when power failed (and CRC was not -++updated to reflect the new data being written). You would check file -++systems like ext2 etc. with such a configuration. -++(As you have no hope that these file systems provide for either your -++new data or old data to be present in the file if power failed during -++the write. This is called "roll back and recover".) -++ -++With JFFS2 I tested for such "roll back and recover" file data reliability -++by setting -e 0 and making sure that all writes to the file being -++updated are done in a *single* write(). -++ -++This is how I found that JFFS2 (yet) does NOT support this functionality. -++(There was a great debate if this was a bug or a feature that was lacking -++or even an issue at all. See the mtd archives for more details). -++ -++In other words, JFFS2 will partially update a file on FLASH even before -++the write() command has completed, thus leaving part old data part new -++data in your file if power failed in the middle of a write(). -++ -++This is bad functionality if you are updating a binary structure or a -++CRC protected file (as in our case). -++ -++ -++If All Files Check Out OK: -++ -++On the startup scan, if there are less errors than specified by the "-e flag" -++a "ok to power me down message" is sent via the specified com port. -++ -++The actual format of this message will depend on the format expected -++by the power cycling box that will receive this message. One may customise -++the actual message that goes out in the "do_pwr_dn)" routine in "comm.c". -++ -++This file is called with an open file descriptor to the comm port that -++this message needs to go out over and the count of the current power -++cycle (in case your power cycling box can display/log this count). -++ -++After this message has been sent out, the checkfs program goes into -++a while(1) loop of writing new data (with CRC), one at a time, into -++all the "check files" in the dir. -++ -++Its life comes to a sudden end when power is asynchronously pulled from -++under its feet (by your external power cycling box). -++ -++It comes back to life when power is restored and the system boots and -++checkfs is called from the rc.local script file. -++ -++The cycle then repeats till a problem is detected, at which point -++the "ok to power me down" message is not sent and the cycle stops -++waiting for the user to examine the system. -++ -++ -++ -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/checkfs/checkfs.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/checkfs/checkfs.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/checkfs/checkfs.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/checkfs/checkfs.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,695 @@ -++/* -++ -++ * Copyright Daniel Industries. -++ * -++ * Created by: Vipin Malik (vipin.malik@daniel.com) -++ * -++ * This code is released under the GPL version 2. See the file COPYING -++ * for more details. -++ * -++ * Software distributed under the Licence is distributed on an "AS IS" -++ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -++ * See the Licence for the specific language governing rights and -++ * limitations under the Licence. -++ -++ This program opens files in progression (file00001, file00002 etc), -++ upto MAX_NUM_FILES and checks their CRC. If a file is not found or the -++ CRC does not match it stops it's operation. -++ -++ Everything is logged in a logfile called './logfile'. -++ -++ If everything is ok this program sends a signal, via com1, to the remote -++ power control box to power cycle this computer. -++ -++ This program then proceeds to create new files file0....file -++ in a endless loop and checksum each before closing them. -++ -++ STRUCTURE OF THE FILES: -++ The fist int is the size of the file in bytes. -++ The last 2 bytes are the CRC for the entire file. -++ There is random data in between. -++ -++ The files are opened in the current dir. -++ -++ $Id: checkfs.c,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ -++ $Log: not supported by cvs2svn $ -++ Revision 1.8 2005/11/07 11:15:17 gleixner -++ [MTD / JFFS2] Clean up trailing white spaces -++ -++ Revision 1.7 2001/06/21 23:04:17 dwmw2 -++ Initial import to MTD CVS -++ -++ Revision 1.6 2001/06/08 22:26:05 vipin -++ Split the modbus comm part of the program (that sends the ok to pwr me down -++ message) into another file "comm.c" -++ -++ Revision 1.5 2001/06/08 21:29:56 vipin -++ fixed small issue with write() checking for < 0 instead of < (bytes to be written). -++ Now it does the latter (as it should). -++ -++ Revision 1.4 2001/05/11 22:29:40 vipin -++ Added a test to check and err out if the first int in file (which tells us -++ how many bytes there are in the file) is zero. This will prevent a corrupt -++ file with zero's in it from passing the crc test. -++ -++ Revision 1.3 2001/05/11 21:33:54 vipin -++ Changed to use write() rather than fwrite() when creating new file. Additionally, -++ and more important, it now does a single write() for the entire data. This will -++ enable us to use this program to test for power fail *data* reliability when -++ writing over an existing file, specially on powr fail "safe" file systems as -++ jffs/jffs2. Also added a new cmdline parameter "-e" that specifies the max # of -++ errors that can be tolerated. This should be set to ZERO to test for the above, -++ as old data should be reliabily maintained if the newer write never "took" before -++ power failed. If the write did succeed, then the newer data will have its own -++ CRC in place when it gets checked => hence no error. In theory at least! -++ -++ -++ Revision 1.2 2001/05/11 19:27:33 vipin -++ Added cmd line args to change serial port, and specify max size of -++ random files created. Some cleanup. Added -Wall to Makefile. -++ -++ Revision 1.1 2001/05/11 16:06:28 vipin -++ Importing checkfs (the power fail test program) into CVS. This was -++ originally done for NEWS. NEWS had a lot of version, this is -++ based off the last one done for NEWS. The "makefiles" program -++ is run once initially to create the files in the current dir. -++ "checkfs" is then run on every powerup to check consistancy -++ of the files. See checkfs.c for more details. -++ -++ -++*/ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "common.h" -++ -++ -++ -++extern int do_pwr_dn(int fd, int cycleCnt); -++ -++#define CMDLINE_PORT "-p" -++#define CMDLINE_MAXFILEBYTES "-s" -++#define CMDLINE_MAXERROR "-e" -++#define CMDLINE_HELPSHORT "-?" -++#define CMDLINE_HELPLONG "--help" -++ -++ -++int CycleCount; -++ -++char SerialDevice[255] = "/dev/ttyS0"; /* default, can be changed -++ through cmd line. */ -++ -++#define MAX_INTS_ALLOW 100000 /* max # of int's in the file written. -++ Statis limit to size struct. */ -++float FileSizeMax = 1024.0; /*= (file size in bytes), MUST be float*/ -++ -++int MaxErrAllowed = 1; /* default, can ge changed thru cmd line*/ -++ -++ -++/* Needed for CRC generation/checking */ -++static const unsigned short crc_ccitt_table[] = { -++ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, -++ 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, -++ 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, -++ 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, -++ 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, -++ 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, -++ 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, -++ 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, -++ 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, -++ 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, -++ 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, -++ 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, -++ 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, -++ 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, -++ 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, -++ 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, -++ 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, -++ 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, -++ 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, -++ 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, -++ 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, -++ 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, -++ 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, -++ 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, -++ 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, -++ 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, -++ 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, -++ 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, -++ 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, -++ 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, -++ 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, -++ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -++}; -++ -++ -++/* -++ Set's up the Linux serial port. Must be passed string to device to -++ open. Parameters are fixed to 9600,e,1 -++ -++ [A possible enhancement to this program would be to pass these -++ parameters via the command line.] -++ -++ Returns file descriptor to open port. Use this fd to write to port -++ and close it later, when done. -++*/ -++int setupSerial (const char *dev) { -++ int i, fd; -++ struct termios tios; -++ -++ fd = open(dev,O_RDWR | O_NDELAY ); -++ if (fd < 0) { -++ fprintf(stderr, "%s: %s\n", dev, sys_errlist[errno]); -++ exit(1); -++ } -++ if (tcgetattr(fd, &tios) < 0) { -++ fprintf(stderr,"Could not get terminal attributes: %s",sys_errlist[errno]); -++ exit(1); -++ } -++ -++ tios.c_cflag = -++ CS7 | -++ CREAD | // Enable Receiver -++ HUPCL | // Hangup after close -++ CLOCAL | // Ignore modem control lines -++ PARENB; // Enable parity (even by default) -++ -++ -++ -++ tios.c_iflag = IGNBRK; // Ignore break -++ tios.c_oflag = 0; -++ tios.c_lflag = 0; -++ for(i = 0; i < NCCS; i++) { -++ tios.c_cc[i] = '\0'; // no special characters -++ } -++ tios.c_cc[VMIN] = 1; -++ tios.c_cc[VTIME] = 0; -++ -++ cfsetospeed (&tios, B9600); -++ cfsetispeed (&tios, B9600); -++ -++ if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { -++ fprintf(stderr,"Could not set attributes: ,%s",sys_errlist[errno]); -++ exit(1); -++ } -++ return fd; -++} -++ -++ -++ -++ -++ -++//A portion of this code was taken from the AX.25 HDLC packet driver -++//in LINUX. Once I test and have a better understanding of what -++//it is doing, it will be better commented. -++ -++//For now one can speculate that the CRC routine always expects the -++//CRC to calculate out to 0xf0b8 (the hardcoded value at the end) -++//and returns TRUE if it is and FALSE if it doesn't. -++//Why don't people document better!!!! -++int check_crc_ccitt(char *filename) -++{ -++ FILE *fp; -++ FILE *logfp; -++ unsigned short crc = 0xffff; -++ int len; -++ char dataByte; -++ int retry; -++ char done; -++ -++ fp = fopen(filename,"rb"); -++ if(!fp){ -++ logfp = fopen("logfile","a"); /*open for appending only.*/ -++ fprintf(logfp, "Verify checksum:Error! Cannot open filename passed for verify checksum: %s\n",filename); -++ fclose(logfp); -++ return FALSE; -++ } -++ -++ -++ /*the first int contains an int that is the length of the file in long.*/ -++ if(fread(&len, sizeof(int), 1, fp) != 1){ -++ logfp = fopen("logfile","a"); /*open for appending only.*/ -++ fprintf(logfp, "verify checksum:Error reading from file: %s\n", filename); -++ fclose(fp); -++ fclose(logfp); -++ return FALSE; -++ } -++ -++ /* printf("Checking %i bytes for CRC in \"%s\".\n", len, filename); */ -++ -++ /* Make sure that we did not read 0 as the number of bytes in file. This -++ check prevents a corrupt file with zero's in it from passing the -++ CRC test. A good file will always have some data in it. */ -++ if(len == 0) -++ { -++ -++ logfp = fopen("logfile","a"); /*open for appending only.*/ -++ fprintf(logfp, "verify checksum: first int claims there are 0 data in file. Error!: %s\n", filename); -++ fclose(fp); -++ fclose(logfp); -++ return FALSE; -++ } -++ -++ -++ rewind(fp); -++ len+=2; /*the file has two extra bytes at the end, it's checksum. Those -++ two MUST also be included in the checksum calculation. -++ */ -++ -++ for (;len>0;len--){ -++ retry=5; /*retry 5 times*/ -++ done = FALSE; -++ while(!done){ -++ if(fread(&dataByte, sizeof(char), 1, fp) != 1){ -++ retry--; -++ }else{ -++ done = TRUE; -++ } -++ if(retry == 0){ -++ done = TRUE; -++ } -++ } -++ if(!retry){ -++ logfp = fopen("logfile","a"); /*open for appending only.*/ -++ fprintf(logfp, "Unexpected end of file: %s\n", filename); -++ fprintf(logfp, "...bytes left to be read %i.\n",len); -++ fclose(logfp); -++ fclose(fp); -++ return FALSE; -++ } -++ crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ dataByte) & 0xff]; -++ } -++ fclose(fp); -++ if( (crc & 0xffff) != 0xf0b8){ -++ /*printf("The CRC of read file:%x\n", crc); */ -++ return FALSE; -++ } -++ return TRUE; -++}/*end check_crc_ccitt() */ -++ -++ -++ -++/* -++ Sends "OK to power me down" message to the remote -++ power cycling box, via the serial port. -++ Also updates the num power cycle count in a local -++ file. -++ This file "./cycleCnt" must be present. This is -++ initially (and once) created by the separate "makefiles.c" -++ program. -++*/ -++void send_pwrdn_ok(void){ -++ -++ int fd; -++ FILE *cyclefp; -++ int cycle_fd; -++ -++ cyclefp = fopen("cycleCnt","rb"); -++ if(!cyclefp){ -++ printf("expecting file \"cycleCnt\". Cannot continue.\n"); -++ exit(1); -++ } -++ if(fread(&CycleCount, sizeof(CycleCount),1,cyclefp) != 1){ -++ fprintf(stderr, "Error! Unexpected end of file cycleCnt.\n"); -++ exit(1); -++ } -++ fclose(cyclefp); -++ -++ CycleCount++; -++ -++ /*now write this puppy back*/ -++ cyclefp = fopen("cycleCnt","wb"); -++ cycle_fd = fileno(cyclefp); -++ if(!cyclefp){ -++ fprintf(stderr, "Error! cannot open file for write:\"cycleCnt\". Cannot continue.\n"); -++ exit(1); -++ } -++ if(fwrite(&CycleCount, sizeof(CycleCount), 1,cyclefp) !=1){ -++ fprintf(stderr, "Error writing to file cycleCnt. Cannot continue.\n"); -++ exit(1); -++ } -++ if(fdatasync(cycle_fd)){ -++ fprintf(stderr, "Error! cannot sync file buffer with disk.\n"); -++ exit(1); -++ } -++ -++ fclose(cyclefp); -++ (void)sync(); -++ -++ printf("\n\n Sending Power down command to the remote box.\n"); -++ fd = setupSerial(SerialDevice); -++ -++ if(do_pwr_dn(fd, CycleCount) < 0) -++ { -++ fprintf(stderr, "Error sending power down command.\n"); -++ exit(1); -++ } -++ -++ close(fd); -++}//end send_pwrnd_ok() -++ -++ -++ -++ -++/* -++ Appends 16bit CRC at the end of numBytes long buffer. -++ Make sure buf, extends at least 2 bytes beyond. -++ */ -++void appendChecksum(char *buf, int numBytes){ -++ -++ unsigned short crc = 0xffff; -++ int index = 0; -++ -++ /* printf("Added CRC (2 bytes) to %i bytes.\n", numBytes); */ -++ -++ for (; numBytes > 0; numBytes--){ -++ -++ crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ buf[index++]) & 0xff]; -++ } -++ crc ^= 0xffff; -++ /*printf("The CRC: %x\n\n", crc);*/ -++ -++ buf[index++] = crc; -++ buf[index++] = crc >> 8; -++ -++ -++ -++}/*end checksum()*/ -++ -++ -++ -++ -++ -++/* -++ This guy make a new "random data file" with the filename -++ passed to it. This file is checksummed with the checksum -++ stored at the end. The first "int" in the file is the -++ number of int's in it (this is needed to know how much -++ data to read and checksum later). -++*/ -++void make_new_file(char *filename){ -++ -++ -++ int dfd; /* data file descriptor */ -++ int rand_data; -++ int data_size; -++ int temp_size; -++ int dataIndex = 0; -++ int err; -++ -++ -++ struct { -++ int sizeInBytes; /* must be int */ -++ int dataInt[MAX_INTS_ALLOW+1]; /* how many int's can we write? */ -++ }__attribute((packed)) dataBuf; -++ -++ -++ fprintf(stderr, "Creating File:%s. ", filename); -++ -++ if((dfd = open(filename, O_RDWR | O_CREAT | O_SYNC)) <= 0) -++ { -++ printf("Error! Cannot open file: %s\n",filename); -++ perror("Error"); -++ exit(1); -++ } -++ -++ /*now write a bunch of random binary data to the file*/ -++ /*first figure out how much data to write. That is random also.*/ -++ -++ /*file should not be less than 5 ints long. (so that we have decent length files, -++ that's all)*/ -++ while( -++ ((data_size = (int)(1+(int)((FileSizeMax/sizeof(int))*rand()/(RAND_MAX+1.0)))) < 5) -++ ); -++ -++ /* printf("Writing %i ints to the file.\n", data_size); */ -++ -++ temp_size = data_size * sizeof(int); -++ -++ /* Make sure that all data is written in one go! This is important to -++ check for reliability of file systems like JFFS/JFFS that purport to -++ have "reliable" writes during powre fail. -++ */ -++ -++ dataBuf.sizeInBytes = temp_size; -++ -++ data_size--; /*one alrady written*/ -++ dataIndex = 0; -++ -++ while(data_size--){ -++ rand_data = (int)(1 + (int)(10000.0*rand()/(RAND_MAX+1.0))); -++ -++ dataBuf.dataInt[dataIndex++] = rand_data; -++ -++ } -++ -++ /*now calculate the file checksum and append it to the end*/ -++ appendChecksum((char *)&dataBuf, dataBuf.sizeInBytes); -++ -++ /* Don't forget to increase the size of data written by the 2 chars of CRC at end. -++ These 2 bytes are NOT included in the sizeInBytes field. */ -++ if((err = write(dfd, (void *)&dataBuf, dataBuf.sizeInBytes + sizeof(short))) < -++ (dataBuf.sizeInBytes + sizeof(short)) -++ ) -++ { -++ printf("Error writing data buffer to file. Written %i bytes rather than %i bytes.", -++ err, dataBuf.sizeInBytes); -++ perror("Error"); -++ exit(1); -++ } -++ -++ /* Now that the data is (hopefully) safely written. I can truncate the file to the new -++ length so that I can reclaim any unused space, if the older file was larger. -++ */ -++ if(ftruncate(dfd, dataBuf.sizeInBytes + sizeof(short)) < 0) -++ { -++ perror("Error: Unable to truncate file."); -++ exit(1); -++ } -++ -++ -++ close(dfd); -++ -++ -++}//end make_new_file() -++ -++ -++ -++/* -++ Show's help on stdout -++ */ -++void printHelp(char **argv) -++{ -++ printf("Usage:%s \n", argv[0]); -++ printf("%s : Set com port to send ok to pwr dn msg on\n", -++ CMDLINE_PORT); -++ printf("%s : Set Max size in bytes of each file to be created.\n", -++ CMDLINE_MAXFILEBYTES); -++ printf("%s : Set Max errors allowed when checking all files for CRC on start.\n", -++ CMDLINE_MAXERROR); -++ printf("%s or %s: This Help screen.\n", CMDLINE_HELPSHORT, -++ CMDLINE_HELPLONG); -++ -++}/* end printHelp()*/ -++ -++ -++ -++void processCmdLine(int argc, char **argv) -++{ -++ -++ int cnt; -++ -++ /* skip past name of this program, process rest */ -++ for(cnt = 1; cnt < argc; cnt++) -++ { -++ if(strcmp(argv[cnt], CMDLINE_PORT) == 0) -++ { -++ strncpy(SerialDevice, argv[++cnt], sizeof(SerialDevice)); -++ continue; -++ }else -++ if(strcmp(argv[cnt], CMDLINE_MAXFILEBYTES) == 0) -++ { -++ FileSizeMax = (float)atoi(argv[++cnt]); -++ if(FileSizeMax > (MAX_INTS_ALLOW*sizeof(int))) -++ { -++ printf("Max file size allowd is %i.\n", -++ MAX_INTS_ALLOW*sizeof(int)); -++ exit(0); -++ } -++ -++ continue; -++ }else -++ if(strcmp(argv[cnt], CMDLINE_HELPSHORT) == 0) -++ { -++ printHelp(argv); -++ exit(0); -++ -++ }else -++ if(strcmp(argv[cnt], CMDLINE_HELPLONG) == 0) -++ { -++ printHelp(argv); -++ exit(0); -++ }else -++ -++ if(strcmp(argv[cnt], CMDLINE_MAXERROR) == 0) -++ { -++ MaxErrAllowed = atoi(argv[++cnt]); -++ } -++ else -++ { -++ printf("Unknown cmd line option:%s\n", argv[cnt]); -++ printHelp(argv); -++ exit(0); -++ -++ } -++ } -++ -++ -++}/* end processCmdLine() */ -++ -++ -++ -++ -++ -++int main(int argc, char **argv){ -++ -++ FILE *logfp; -++ int log_fd; -++ char filename[30]; -++ short filenameCounter = 0; -++ unsigned short counter; -++ unsigned short numberFiles; -++ char error = FALSE; -++ short errorCnt = 0; -++ time_t timep; -++ char * time_string; -++ unsigned int seed; -++ -++ -++ numberFiles = MAX_NUM_FILES; -++ -++ if(argc >= 1) -++ { -++ processCmdLine(argc, argv); -++ } -++ -++ -++ /* -++ First open MAX_NUM_FILES and make sure that the checksum is ok. -++ Also make an intry into the logfile. -++ */ -++ /* timestamp! */ -++ time(&timep); -++ time_string = (char *)ctime((time_t *)&timep); -++ -++ /*start a new check, make a log entry and continue*/ -++ logfp = fopen("logfile","a"); /*open for appending only.*/ -++ log_fd = fileno(logfp); -++ fprintf(logfp,"%s", time_string); -++ fprintf(logfp,"Starting new check.\n"); -++ if(fdatasync(log_fd) == -1){ -++ fprintf(stderr,"Error! Cannot sync file data with disk.\n"); -++ exit(1); -++ } -++ -++ fclose(logfp); -++ (void)sync(); -++ -++ /* -++ Now check all random data files in this dir. -++ */ -++ for(counter=0;counter MaxErrAllowed){ -++ logfp = fopen("logfile","a"); /*open for appending only.*/ -++ log_fd = fileno(logfp); -++ fprintf(logfp,"\nMax Error count exceed. Stopping!\n"); -++ if(fdatasync(log_fd) == -1){ -++ fprintf(stderr,"Error! Cannot sync file data with disk.\n"); -++ exit(1); -++ } -++ fclose(logfp); -++ (void)sync(); -++ -++ fprintf(stderr, "Too many errors. See \"logfile\".\n"); -++ exit(1); -++ }/* if too many errors */ -++ -++ /*we have decided to continue, however first repair this file -++ so that we do not cumulate errors across power cycles.*/ -++ make_new_file(filename); -++ } -++ }//for -++ -++ /*all files checked, make a log entry and continue*/ -++ logfp = fopen("logfile","a"); /*open for appending only.*/ -++ log_fd = fileno(logfp); -++ fprintf(logfp,"All files checked. Total errors found: %i\n\n", errorCnt); -++ if(fdatasync(log_fd)){ -++ fprintf(stderr, "Error! cannot sync file buffer with disk.\n"); -++ exit(1); -++ } -++ -++ fclose(logfp); -++ (void)sync(); -++ -++ /*now send a message to the remote power box and have it start a random -++ pwer down timer after which power will be killed to this unit. -++ */ -++ send_pwrdn_ok(); -++ -++ /*now go into a forever loop of writing to files and CRC'ing them on -++ a continious basis.*/ -++ -++ /*start from a random file #*/ -++ /*seed rand based on the current time*/ -++ seed = (unsigned int)time(NULL); -++ srand(seed); -++ -++ filenameCounter=(int)(1+(int)((float)(MAX_NUM_FILES-1)*rand()/(RAND_MAX+1.0))); -++ -++ while(1){ -++ -++ for(;filenameCounter -++#include -++#include -++ -++ -++ -++/* -++ This is the routine that forms and -++ sends the "ok to pwr me down" message -++ to the remote power cycling "black box". -++ -++ */ -++int do_pwr_dn(int fd, int cycleCnt) -++{ -++ -++ char buf[200]; -++ -++ sprintf(buf, "ok to power me down!\nCount = %i\n", cycleCnt); -++ -++ if(write(fd, buf, strlen(buf)) < strlen(buf)) -++ { -++ perror("write error"); -++ return -1; -++ } -++ -++ return 0; -++} -++ -++ -++ -++ -++ -++ -++ -++ -++ -++ -++ -++ -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/checkfs/common.h linux-2.6.24.7/drivers/mtd/mtd-utils/tests/checkfs/common.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/checkfs/common.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/checkfs/common.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,7 @@ -++/* $Id: common.h,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ */ -++//this .h file is common to both the file creation utility and -++//the file checking utility. -++#define TRUE 1 -++#define FALSE 0 -++ -++#define MAX_NUM_FILES 100 -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/checkfs/makefiles.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/checkfs/makefiles.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/checkfs/makefiles.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/checkfs/makefiles.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,264 @@ -++/* -++ -++ * Copyright Daniel Industries. -++ -++ * Created by: Vipin Malik (vipin.malik@daniel.com) -++ * -++ * This is GPL code. See the file COPYING for more details -++ * -++ * Software distributed under the Licence is distributed on an "AS IS" -++ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. -++ * See the Licence for the specific language governing rights and -++ * limitations under the Licence. -++ -++ * $Id: makefiles.c,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ -++ -++This program creates MAX_NUM_FILES files (file00001, file00002 etc) and -++fills them with random numbers till they are a random length. Then it checksums -++the files (with the checksum as the last two bytes) and closes the file. -++ -++The fist int is the size of the file in bytes. -++ -++It then opens another file and the process continues. -++ -++The files are opened in the current dir. -++ -++*/ -++#include -++#include -++#include -++#include -++#include -++#include "common.h" -++ -++#define FILESIZE_MAX 20000.0 /* for each file in sizeof(int). Must be a float # -++ Hence, 20000.0 = 20000*4 = 80KB max file size -++ */ -++ -++static const unsigned short crc_ccitt_table[] = { -++ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, -++ 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, -++ 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, -++ 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, -++ 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, -++ 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, -++ 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, -++ 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, -++ 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, -++ 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, -++ 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, -++ 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, -++ 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, -++ 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, -++ 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, -++ 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, -++ 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, -++ 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, -++ 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, -++ 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, -++ 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, -++ 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, -++ 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, -++ 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, -++ 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, -++ 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, -++ 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, -++ 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, -++ 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, -++ 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, -++ 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, -++ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -++}; -++ -++//This code was taken from the AX.25 HDLC packet driver -++//in LINUX. Once I test and have a better understanding of what -++//it is doing, it will be better commented. -++ -++//For now one can speculate that the CRC routine always expects the -++//CRC to calculate out to 0xf0b8 (the hardcoded value at the end) -++//and returns TRUE if it is and FALSE if it doesn't. -++//Why don't people document better!!!! -++void check_crc_ccitt(char *filename) -++{ -++ FILE *fp; -++ unsigned short crc = 0xffff; -++ int len; -++ char dataByte; -++ int retry; -++ -++ fp = fopen(filename,"rb"); -++ if(!fp){ -++ printf("Verify checksum:Error! Cannot open filename passed for verify checksum: %s\n",filename); -++ exit(1); -++ } -++ /*the first int contains an int that is the length of the file in long.*/ -++ if(fread(&len, sizeof(int), 1, fp) != 1){ -++ printf("verify checksum:Error reading from file: %s", filename); -++ fclose(fp); -++ exit(1); -++ } -++ rewind(fp); -++ len+=2; /*the file has two extra bytes at the end, it's checksum. Those -++ two MUST also be included in the checksum calculation. -++ */ -++ -++ for (;len>0;len--){ -++ retry=5; /*retry 5 times*/ -++ while(!fread(&dataByte, sizeof(char), 1, fp) && retry--); -++ if(!retry){ -++ printf("Unexpected error reading from file: %s\n", filename); -++ printf("...bytes left to be read %i.\n\n",len); -++ fclose(fp); -++ exit(1); -++ } -++ crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ dataByte) & 0xff]; -++ } -++ fclose(fp); -++ if( (crc & 0xffff) != 0xf0b8){ -++ printf("Verify checksum: Error in file %s.\n\n",filename); -++ exit(1); -++ } -++}//end check_crc_ccitt() -++ -++ -++ -++/*this routine opens a file 'filename' and checksumn's the entire -++ contents, and then appends the checksum at the end of the file, -++ closes the file and returns. -++*/ -++void checksum(char *filename){ -++ -++ FILE *fp; -++ unsigned short crc = 0xffff; -++ int len; -++ char dataByte; -++ int retry; -++ -++ fp = fopen(filename,"rb"); -++ if(!fp){ -++ printf("Error! Cannot open filename passed for checksum: %s\n",filename); -++ exit(1); -++ } -++ /*the first int contains an int that is the length of the file in longs.*/ -++ if(fread(&len, sizeof(int), 1, fp) != 1){ -++ printf("Error reading from file: %s", filename); -++ fclose(fp); -++ exit(1); -++ } -++ printf("Calculating checksum on %i bytes.\n",len); -++ rewind(fp); /*the # of bytes int is also included in the checksum.*/ -++ -++ for (;len>0;len--){ -++ retry=5; /*retry 5 times*/ -++ while(!fread(&dataByte, sizeof(char), 1, fp) && retry--); -++ if(!retry){ -++ printf("Unexpected error reading from file: %s\n", filename); -++ printf("...bytes left to be read %i.\n\n",len); -++ fclose(fp); -++ exit(1); -++ } -++ crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ dataByte) & 0xff]; -++ } -++ crc ^= 0xffff; -++ printf("The CRC: %x\n\n", crc); -++ -++ /*the CRC has been calculated. now close the file and open it in append mode*/ -++ fclose(fp); -++ -++ fp = fopen(filename,"ab"); /*open in append mode. CRC goes at the end.*/ -++ if(!fp){ -++ printf("Error! Cannot open filename to update checksum: %s\n",filename); -++ exit(1); -++ } -++ if(fwrite(&crc, sizeof(crc), 1, fp) != 1){ -++ printf("error! unable to update the file for checksum.\n"); -++ fclose(fp); -++ exit(1); -++ } -++ fflush(fp); -++ fclose(fp); -++ -++ -++}/*end checksum()*/ -++ -++ -++ -++int main(void){ -++ -++ FILE *fp, *cyclefp; -++ int cycleCount; -++ int rand_data; -++ int data_size; -++ int temp_size; -++ char filename[30]; -++ short filenameCounter = 0; -++ unsigned short counter; -++ unsigned short numberFiles; -++ -++ numberFiles = MAX_NUM_FILES; -++ -++ for(counter=0;counter -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "tests.h" -++ -++/* Structures to store data written to the test file system, -++ so that we can check whether the file system is correct. */ -++ -++struct write_info /* Record of random data written into a file */ -++{ -++ struct write_info *next; -++ off_t offset; /* Where in the file the data was written */ -++ size_t size; /* Number of bytes written */ -++ unsigned random_seed; /* Seed for rand() to create random data */ -++ off_t random_offset; /* Call rand() this number of times first */ -++}; -++ -++struct file_info /* Each file has one of these */ -++{ -++ char *name; -++ struct dir_info *parent; /* Parent directory */ -++ struct write_info *writes; /* Record accumulated writes to the file */ -++ struct write_info *raw_writes; -++ /* Record in order all writes to the file */ -++ struct fd_info *fds; /* All open file descriptors for this file */ -++ off_t length; -++ int deleted; /* File has been deleted but is still open */ -++ int no_space_error; /* File has incurred a ENOSPC error */ -++}; -++ -++struct dir_info /* Each directory has one of these */ -++{ -++ char *name; -++ struct dir_info *parent; /* Parent directory or null -++ for our top directory */ -++ unsigned number_of_entries; -++ struct dir_entry_info *first; -++}; -++ -++struct dir_entry_info /* Each entry in a directory has one of these */ -++{ -++ struct dir_entry_info *next; -++ char type; /* f => file, d=> dir */ -++ int checked; /* Temporary flag used when checking */ -++ union entry_ -++ { -++ struct file_info *file; -++ struct dir_info *dir; -++ } entry; -++}; -++ -++struct fd_info /* We keep a number of files open */ -++{ -++ struct fd_info *next; -++ struct file_info *file; -++ int fd; -++}; -++ -++struct open_file_info /* We keep a list of open files */ -++{ -++ struct open_file_info *next; -++ struct fd_info *fdi; -++}; -++ -++static struct dir_info *top_dir = NULL; /* Our top directory */ -++ -++static struct open_file_info *open_files = NULL; /* We keep a list of -++ open files */ -++static size_t open_files_count = 0; -++ -++static int grow = 1; /* Should we try to grow files and directories */ -++static int shrink = 0; /* Should we try to shrink files and directories */ -++static int full = 0; /* Flag that the file system is full */ -++static uint64_t operation_count = 0; /* Number of operations used to fill -++ up the file system */ -++static uint64_t initial_free_space = 0; /* Free space on file system when -++ test starts */ -++static unsigned log10_initial_free_space = 0; /* log10 of initial_free_space */ -++ -++static char *copy_string(const char *s) -++{ -++ char *str; -++ -++ if (!s) -++ return NULL; -++ str = (char *) malloc(strlen(s) + 1); -++ CHECK(str != NULL); -++ strcpy(str, s); -++ return str; -++} -++ -++static char *cat_strings(const char *a, const char *b) -++{ -++ char *str; -++ size_t sz; -++ -++ if (a && !b) -++ return copy_string(a); -++ if (b && !a) -++ return copy_string(b); -++ if (!a && !b) -++ return NULL; -++ sz = strlen(a) + strlen(b) + 1; -++ str = (char *) malloc(sz); -++ CHECK(str != NULL); -++ strcpy(str, a); -++ strcat(str, b); -++ return str; -++} -++ -++static char *cat_paths(const char *a, const char *b) -++{ -++ char *str; -++ size_t sz; -++ int as, bs; -++ size_t na, nb; -++ -++ if (a && !b) -++ return copy_string(a); -++ if (b && !a) -++ return copy_string(b); -++ if (!a && !b) -++ return NULL; -++ -++ as = 0; -++ bs = 0; -++ na = strlen(a); -++ nb = strlen(b); -++ if (na && a[na - 1] == '/') -++ as = 1; -++ if (nb && b[0] == '/') -++ bs = 1; -++ if ((as && !bs) || (!as && bs)) -++ return cat_strings(a, b); -++ if (as && bs) -++ return cat_strings(a, b + 1); -++ -++ sz = na + nb + 2; -++ str = (char *) malloc(sz); -++ CHECK(str != NULL); -++ strcpy(str, a); -++ strcat(str, "/"); -++ strcat(str, b); -++ return str; -++} -++ -++static char *dir_path(struct dir_info *parent, const char *name) -++{ -++ char *parent_path; -++ char *path; -++ -++ if (!parent) -++ return cat_paths(tests_file_system_mount_dir, name); -++ parent_path = dir_path(parent->parent, parent->name); -++ path = cat_paths(parent_path, name); -++ free(parent_path); -++ return path; -++} -++ -++static struct dir_entry_info *dir_entry_new(void) -++{ -++ struct dir_entry_info *entry; -++ size_t sz; -++ -++ sz = sizeof(struct dir_entry_info); -++ entry = (struct dir_entry_info *) malloc(sz); -++ CHECK(entry != NULL); -++ memset(entry, 0, sz); -++ return entry; -++} -++ -++static void open_file_add(struct fd_info *fdi) -++{ -++ struct open_file_info *ofi; -++ size_t sz; -++ -++ sz = sizeof(struct open_file_info); -++ ofi = (struct open_file_info *) malloc(sz); -++ CHECK(ofi != NULL); -++ memset(ofi, 0, sz); -++ ofi->next = open_files; -++ ofi->fdi = fdi; -++ open_files = ofi; -++ open_files_count += 1; -++} -++ -++static void open_file_remove(struct fd_info *fdi) -++{ -++ struct open_file_info *ofi; -++ struct open_file_info **prev; -++ -++ prev = &open_files; -++ for (ofi = open_files; ofi; ofi = ofi->next) { -++ if (ofi->fdi == fdi) { -++ *prev = ofi->next; -++ free(ofi); -++ open_files_count -= 1; -++ return; -++ } -++ prev = &ofi->next; -++ } -++ CHECK(0); /* We are trying to remove something that is not there */ -++} -++ -++static struct fd_info *fd_new(struct file_info *file, int fd) -++{ -++ struct fd_info *fdi; -++ size_t sz; -++ -++ sz = sizeof(struct fd_info); -++ fdi = (struct fd_info *) malloc(sz); -++ CHECK(fdi != NULL); -++ memset(fdi, 0, sz); -++ fdi->next = file->fds; -++ fdi->file = file; -++ fdi->fd = fd; -++ file->fds = fdi; -++ open_file_add(fdi); -++ return fdi; -++} -++ -++static struct dir_info *dir_new(struct dir_info *parent, const char *name) -++{ -++ struct dir_info *dir; -++ size_t sz; -++ char *path; -++ -++ path = dir_path(parent, name); -++ if (mkdir(path, 0777) == -1) { -++ CHECK(errno == ENOSPC); -++ full = 1; -++ free(path); -++ return NULL; -++ } -++ free(path); -++ -++ sz = sizeof(struct dir_info); -++ dir = (struct dir_info *) malloc(sz); -++ CHECK(dir != NULL); -++ memset(dir, 0, sz); -++ dir->name = copy_string(name); -++ dir->parent = parent; -++ if (parent) { -++ struct dir_entry_info *entry; -++ -++ entry = dir_entry_new(); -++ entry->type = 'd'; -++ entry->entry.dir = dir; -++ entry->next = parent->first; -++ parent->first = entry; -++ parent->number_of_entries += 1; -++ } -++ return dir; -++} -++ -++static void file_delete(struct file_info *file); -++ -++static void dir_remove(struct dir_info *dir) -++{ -++ char *path; -++ struct dir_entry_info *entry; -++ struct dir_entry_info **prev; -++ int found; -++ -++ /* Remove directory contents */ -++ while (dir->first) { -++ struct dir_entry_info *entry; -++ -++ entry = dir->first; -++ if (entry->type == 'd') -++ dir_remove(entry->entry.dir); -++ else if (entry->type == 'f') -++ file_delete(entry->entry.file); -++ else -++ CHECK(0); /* Invalid struct dir_entry_info */ -++ } -++ /* Remove entry from parent directory */ -++ found = 0; -++ prev = &dir->parent->first; -++ for (entry = dir->parent->first; entry; entry = entry->next) { -++ if (entry->type == 'd' && entry->entry.dir == dir) { -++ dir->parent->number_of_entries -= 1; -++ *prev = entry->next; -++ free(entry); -++ found = 1; -++ break; -++ } -++ prev = &entry->next; -++ } -++ CHECK(found); /* Check the file is in the parent directory */ -++ /* Remove directory itself */ -++ path = dir_path(dir->parent, dir->name); -++ CHECK(rmdir(path) != -1); -++} -++ -++static struct file_info *file_new(struct dir_info *parent, const char *name) -++{ -++ struct file_info *file = NULL; -++ char *path; -++ mode_t mode; -++ int fd; -++ size_t sz; -++ struct dir_entry_info *entry; -++ -++ CHECK(parent != NULL); -++ -++ path = dir_path(parent, name); -++ mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; -++ fd = open(path, O_CREAT | O_EXCL | O_RDWR, mode); -++ if (fd == -1) { -++ CHECK(errno == ENOSPC); -++ free(path); -++ full = 1; -++ return NULL; -++ } -++ free(path); -++ -++ sz = sizeof(struct file_info); -++ file = (struct file_info *) malloc(sz); -++ CHECK(file != NULL); -++ memset(file, 0, sz); -++ file->name = copy_string(name); -++ file->parent = parent; -++ -++ fd_new(file, fd); -++ -++ entry = dir_entry_new(); -++ entry->type = 'f'; -++ entry->entry.file = file; -++ entry->next = parent->first; -++ parent->first = entry; -++ parent->number_of_entries += 1; -++ -++ return file; -++} -++ -++static void file_delete(struct file_info *file) -++{ -++ char *path; -++ struct dir_entry_info *entry; -++ struct dir_entry_info **prev; -++ int found; -++ -++ /* Remove file entry from parent directory */ -++ found = 0; -++ prev = &file->parent->first; -++ for (entry = file->parent->first; entry; entry = entry->next) { -++ if (entry->type == 'f' && entry->entry.file == file) { -++ file->parent->number_of_entries -= 1; -++ *prev = entry->next; -++ free(entry); -++ found = 1; -++ break; -++ } -++ prev = &entry->next; -++ } -++ CHECK(found); /* Check the file is in the parent directory */ -++ -++ /* Delete the file */ -++ path = dir_path(file->parent, file->name); -++ CHECK(unlink(path) != -1); -++ free(path); -++ -++ /* Free struct file_info if file is not open */ -++ if (!file->fds) { -++ struct write_info *w, *next; -++ -++ free(file->name); -++ w = file->writes; -++ while (w) { -++ next = w->next; -++ free(w); -++ w = next; -++ } -++ free(file); -++ } else -++ file->deleted = 1; -++} -++ -++static void file_info_display(struct file_info *file) -++{ -++ struct write_info *w; -++ unsigned wcnt; -++ -++ fprintf(stderr, "File Info:\n"); -++ fprintf(stderr, " Name: %s\n", file->name); -++ fprintf(stderr, " Directory: %s\n", file->parent->name); -++ fprintf(stderr, " Length: %u\n", (unsigned) file->length); -++ fprintf(stderr, " File was open: %s\n", -++ (file->fds == NULL) ? "false" : "true"); -++ fprintf(stderr, " File was deleted: %s\n", -++ (file->deleted == 0) ? "false" : "true"); -++ fprintf(stderr, " File was out of space: %s\n", -++ (file->no_space_error == 0) ? "false" : "true"); -++ fprintf(stderr, " Write Info:\n"); -++ wcnt = 0; -++ w = file->writes; -++ while (w) { -++ fprintf(stderr, " Offset: %u Size: %u Seed: %u" -++ " R.Off: %u\n", -++ (unsigned) w->offset, -++ (unsigned) w->size, -++ (unsigned) w->random_seed, -++ (unsigned) w->random_offset); -++ wcnt += 1; -++ w = w->next; -++ } -++ fprintf(stderr, " %u writes\n", wcnt); -++ fprintf(stderr, " ============================================\n"); -++ fprintf(stderr, " Raw Write Info:\n"); -++ wcnt = 0; -++ w = file->raw_writes; -++ while (w) { -++ fprintf(stderr, " Offset: %u Size: %u Seed: %u" -++ " R.Off: %u\n", -++ (unsigned) w->offset, -++ (unsigned) w->size, -++ (unsigned) w->random_seed, -++ (unsigned) w->random_offset); -++ wcnt += 1; -++ w = w->next; -++ } -++ fprintf(stderr, " %u writes\n", wcnt); -++ fprintf(stderr, " ============================================\n"); -++} -++ -++static struct fd_info *file_open(struct file_info *file) -++{ -++ int fd; -++ char *path; -++ -++ path = dir_path(file->parent, file->name); -++ fd = open(path, O_RDWR); -++ CHECK(fd != -1); -++ free(path); -++ return fd_new(file, fd); -++} -++ -++#define BUFFER_SIZE 32768 -++ -++static size_t file_write_data( struct file_info *file, -++ int fd, -++ off_t offset, -++ size_t size, -++ unsigned seed) -++{ -++ size_t remains, actual, block; -++ ssize_t written; -++ char buf[BUFFER_SIZE]; -++ -++ srand(seed); -++ CHECK(lseek(fd, offset, SEEK_SET) != (off_t) -1); -++ remains = size; -++ actual = 0; -++ written = BUFFER_SIZE; -++ while (remains) { -++ /* Fill up buffer with random data */ -++ if (written < BUFFER_SIZE) -++ memmove(buf, buf + written, BUFFER_SIZE - written); -++ else -++ written = 0; -++ for (; written < BUFFER_SIZE; ++written) -++ buf[written] = rand(); -++ /* Write a block of data */ -++ if (remains > BUFFER_SIZE) -++ block = BUFFER_SIZE; -++ else -++ block = remains; -++ written = write(fd, buf, block); -++ if (written < 0) { -++ CHECK(errno == ENOSPC); /* File system full */ -++ full = 1; -++ file->no_space_error = 1; -++ break; -++ } -++ remains -= written; -++ actual += written; -++ } -++ return actual; -++} -++ -++static void file_write_info(struct file_info *file, -++ off_t offset, -++ size_t size, -++ unsigned seed) -++{ -++ struct write_info *new_write, *w, **prev, *tmp; -++ int inserted; -++ size_t sz; -++ off_t end, chg; -++ -++ /* Create struct write_info */ -++ sz = sizeof(struct write_info); -++ new_write = (struct write_info *) malloc(sz); -++ CHECK(new_write != NULL); -++ memset(new_write, 0, sz); -++ new_write->offset = offset; -++ new_write->size = size; -++ new_write->random_seed = seed; -++ -++ w = (struct write_info *) malloc(sz); -++ CHECK(w != NULL); -++ memset(w, 0, sz); -++ w->next = file->raw_writes; -++ w->offset = offset; -++ w->size = size; -++ w->random_seed = seed; -++ file->raw_writes = w; -++ -++ /* Insert it into file->writes */ -++ inserted = 0; -++ end = offset + size; -++ w = file->writes; -++ prev = &file->writes; -++ while (w) { -++ if (w->offset >= end) { -++ /* w comes after new_write, so insert before it */ -++ new_write->next = w; -++ *prev = new_write; -++ inserted = 1; -++ break; -++ } -++ /* w does not come after new_write */ -++ if (w->offset + w->size > offset) { -++ /* w overlaps new_write */ -++ if (w->offset < offset) { -++ /* w begins before new_write begins */ -++ if (w->offset + w->size <= end) -++ /* w ends before new_write ends */ -++ w->size = offset - w->offset; -++ else { -++ /* w ends after new_write ends */ -++ /* Split w */ -++ tmp = (struct write_info *) malloc(sz); -++ CHECK(tmp != NULL); -++ *tmp = *w; -++ chg = end - tmp->offset; -++ tmp->offset += chg; -++ tmp->random_offset += chg; -++ tmp->size -= chg; -++ w->size = offset - w->offset; -++ /* Insert new struct write_info */ -++ w->next = new_write; -++ new_write->next = tmp; -++ inserted = 1; -++ break; -++ } -++ } else { -++ /* w begins after new_write begins */ -++ if (w->offset + w->size <= end) { -++ /* w is completely overlapped, -++ so remove it */ -++ *prev = w->next; -++ tmp = w; -++ w = w->next; -++ free(tmp); -++ continue; -++ } -++ /* w ends after new_write ends */ -++ chg = end - w->offset; -++ w->offset += chg; -++ w->random_offset += chg; -++ w->size -= chg; -++ continue; -++ } -++ } -++ prev = &w->next; -++ w = w->next; -++ } -++ if (!inserted) -++ *prev = new_write; -++ /* Update file length */ -++ if (end > file->length) -++ file->length = end; -++} -++ -++/* Randomly select offset and and size to write in a file */ -++static void get_offset_and_size(struct file_info *file, -++ off_t *offset, -++ size_t *size) -++{ -++ size_t r, n; -++ -++ r = tests_random_no(100); -++ if (r == 0 && grow) -++ /* 1 time in 100, when growing, write off the end of the file */ -++ *offset = file->length + tests_random_no(10000000); -++ else if (r < 4) -++ /* 3 (or 4) times in 100, write at the beginning of file */ -++ *offset = 0; -++ else if (r < 52 || !grow) -++ /* 48 times in 100, write into the file */ -++ *offset = tests_random_no(file->length); -++ else -++ /* 48 times in 100, write at the end of the file */ -++ *offset = file->length; -++ /* Distribute the size logarithmically */ -++ if (tests_random_no(1000) == 0) -++ r = tests_random_no(log10_initial_free_space + 2); -++ else -++ r = tests_random_no(log10_initial_free_space); -++ n = 1; -++ while (r--) -++ n *= 10; -++ *size = tests_random_no(n); -++ if (!grow && *offset + *size > file->length) -++ *size = file->length - *offset; -++ if (*size == 0) -++ *size = 1; -++} -++ -++static void file_truncate_info(struct file_info *file, size_t new_length); -++static void file_close(struct fd_info *fdi); -++ -++static int file_ftruncate(struct file_info *file, int fd, off_t new_length) -++{ -++ if (ftruncate(fd, new_length) == -1) { -++ CHECK(errno = ENOSPC); -++ file->no_space_error = 1; -++ /* Delete errored files */ -++ if (!file->deleted) { -++ struct fd_info *fdi; -++ -++ fdi = file->fds; -++ while (fdi) { -++ file_close(fdi); -++ fdi = file->fds; -++ } -++ file_delete(file); -++ } -++ return 0; -++ } -++ return 1; -++} -++ -++static void file_write(struct file_info *file, int fd) -++{ -++ off_t offset; -++ size_t size, actual; -++ unsigned seed; -++ int truncate = 0; -++ -++ get_offset_and_size(file, &offset, &size); -++ seed = tests_random_no(10000000); -++ actual = file_write_data(file, fd, offset, size, seed); -++ -++ if (offset + actual <= file->length && shrink) -++ /* 1 time in 100, when shrinking -++ truncate after the write */ -++ if (tests_random_no(100) == 0) -++ truncate = 1; -++ -++ if (actual != 0) -++ file_write_info(file, offset, actual, seed); -++ -++ /* Delete errored files */ -++ if (file->no_space_error) { -++ if (!file->deleted) { -++ struct fd_info *fdi; -++ -++ fdi = file->fds; -++ while (fdi) { -++ file_close(fdi); -++ fdi = file->fds; -++ } -++ file_delete(file); -++ } -++ return; -++ } -++ -++ if (truncate) { -++ size_t new_length = offset + actual; -++ if (file_ftruncate(file, fd, new_length)) -++ file_truncate_info(file, new_length); -++ } -++} -++ -++static void file_write_file(struct file_info *file) -++{ -++ int fd; -++ char *path; -++ -++ path = dir_path(file->parent, file->name); -++ fd = open(path, O_WRONLY); -++ CHECK(fd != -1); -++ file_write(file, fd); -++ CHECK(close(fd) != -1); -++ free(path); -++} -++ -++static void file_truncate_info(struct file_info *file, size_t new_length) -++{ -++ struct write_info *w, **prev, *tmp; -++ -++ /* Remove / truncate file->writes */ -++ w = file->writes; -++ prev = &file->writes; -++ while (w) { -++ if (w->offset >= new_length) { -++ /* w comes after eof, so remove it */ -++ *prev = w->next; -++ tmp = w; -++ w = w->next; -++ free(tmp); -++ continue; -++ } -++ if (w->offset + w->size > new_length) -++ w->size = new_length - w->offset; -++ prev = &w->next; -++ w = w->next; -++ } -++ /* Update file length */ -++ file->length = new_length; -++} -++ -++static void file_truncate(struct file_info *file, int fd) -++{ -++ size_t new_length; -++ -++ new_length = tests_random_no(file->length); -++ -++ if (file_ftruncate(file, fd, new_length)) -++ file_truncate_info(file, new_length); -++} -++ -++static void file_truncate_file(struct file_info *file) -++{ -++ int fd; -++ char *path; -++ -++ path = dir_path(file->parent, file->name); -++ fd = open(path, O_WRONLY); -++ CHECK(fd != -1); -++ file_truncate(file, fd); -++ CHECK(close(fd) != -1); -++ free(path); -++} -++ -++static void file_close(struct fd_info *fdi) -++{ -++ struct file_info *file; -++ struct fd_info *fdp; -++ struct fd_info **prev; -++ -++ /* Close file */ -++ CHECK(close(fdi->fd) != -1); -++ /* Remove struct fd_info */ -++ open_file_remove(fdi); -++ file = fdi->file; -++ prev = &file->fds; -++ for (fdp = file->fds; fdp; fdp = fdp->next) { -++ if (fdp == fdi) { -++ *prev = fdi->next; -++ free(fdi); -++ if (file->deleted && !file->fds) { -++ /* Closing deleted file */ -++ struct write_info *w, *next; -++ -++ w = file->writes; -++ while (w) { -++ next = w->next; -++ free(w); -++ w = next; -++ } -++ free(file->name); -++ free(file); -++ } -++ return; -++ } -++ prev = &fdp->next; -++ } -++ CHECK(0); /* Didn't find struct fd_info */ -++} -++ -++static void file_rewrite_data(int fd, struct write_info *w, char *buf) -++{ -++ size_t remains, block; -++ ssize_t written; -++ off_t r; -++ -++ srand(w->random_seed); -++ for (r = 0; r < w->random_offset; ++r) -++ rand(); -++ CHECK(lseek(fd, w->offset, SEEK_SET) != (off_t) -1); -++ remains = w->size; -++ written = BUFFER_SIZE; -++ while (remains) { -++ /* Fill up buffer with random data */ -++ if (written < BUFFER_SIZE) -++ memmove(buf, buf + written, BUFFER_SIZE - written); -++ else -++ written = 0; -++ for (; written < BUFFER_SIZE; ++written) -++ buf[written] = rand(); -++ /* Write a block of data */ -++ if (remains > BUFFER_SIZE) -++ block = BUFFER_SIZE; -++ else -++ block = remains; -++ written = write(fd, buf, block); -++ CHECK(written == block); -++ remains -= written; -++ } -++} -++ -++static void save_file(int fd, struct file_info *file) -++{ -++ int w_fd; -++ struct write_info *w; -++ char buf[BUFFER_SIZE]; -++ char name[256]; -++ -++ /* Open file to save contents to */ -++ strcpy(name, "/tmp/"); -++ strcat(name, file->name); -++ strcat(name, ".integ.sav.read"); -++ fprintf(stderr, "Saving %s\n", name); -++ w_fd = open(name, O_CREAT | O_WRONLY, 0777); -++ CHECK(w_fd != -1); -++ -++ /* Start at the beginning */ -++ CHECK(lseek(fd, 0, SEEK_SET) != (off_t) -1); -++ -++ for (;;) { -++ ssize_t r = read(fd, buf, BUFFER_SIZE); -++ CHECK(r != -1); -++ if (!r) -++ break; -++ CHECK(write(w_fd, buf, r) == r); -++ } -++ CHECK(close(w_fd) != -1); -++ -++ /* Open file to save contents to */ -++ strcpy(name, "/tmp/"); -++ strcat(name, file->name); -++ strcat(name, ".integ.sav.written"); -++ fprintf(stderr, "Saving %s\n", name); -++ w_fd = open(name, O_CREAT | O_WRONLY, 0777); -++ CHECK(w_fd != -1); -++ -++ for (w = file->writes; w; w = w->next) -++ file_rewrite_data(w_fd, w, buf); -++ -++ CHECK(close(w_fd) != -1); -++} -++ -++static void file_check_hole( struct file_info *file, -++ int fd, off_t offset, -++ size_t size) -++{ -++ size_t remains, block, i; -++ char buf[BUFFER_SIZE]; -++ -++ CHECK(lseek(fd, offset, SEEK_SET) != (off_t) -1); -++ remains = size; -++ while (remains) { -++ if (remains > BUFFER_SIZE) -++ block = BUFFER_SIZE; -++ else -++ block = remains; -++ CHECK(read(fd, buf, block) == block); -++ for (i = 0; i < block; ++i) { -++ if (buf[i] != 0) { -++ fprintf(stderr, "file_check_hole failed at %u " -++ "checking hole at %u size %u\n", -++ (unsigned) (size - remains + i), -++ (unsigned) offset, -++ (unsigned) size); -++ file_info_display(file); -++ save_file(fd, file); -++ } -++ CHECK(buf[i] == 0); -++ } -++ remains -= block; -++ } -++} -++ -++static void file_check_data( struct file_info *file, -++ int fd, -++ struct write_info *w) -++{ -++ size_t remains, block, i; -++ off_t r; -++ char buf[BUFFER_SIZE]; -++ -++ srand(w->random_seed); -++ for (r = 0; r < w->random_offset; ++r) -++ rand(); -++ CHECK(lseek(fd, w->offset, SEEK_SET) != (off_t) -1); -++ remains = w->size; -++ while (remains) { -++ if (remains > BUFFER_SIZE) -++ block = BUFFER_SIZE; -++ else -++ block = remains; -++ CHECK(read(fd, buf, block) == block); -++ for (i = 0; i < block; ++i) { -++ char c = (char) rand(); -++ if (buf[i] != c) { -++ fprintf(stderr, "file_check_data failed at %u " -++ "checking data at %u size %u\n", -++ (unsigned) (w->size - remains + i), -++ (unsigned) w->offset, -++ (unsigned) w->size); -++ file_info_display(file); -++ save_file(fd, file); -++ } -++ CHECK(buf[i] == c); -++ } -++ remains -= block; -++ } -++} -++ -++static void file_check(struct file_info *file, int fd) -++{ -++ int open_and_close = 0; -++ char *path = NULL; -++ off_t pos; -++ struct write_info *w; -++ -++ /* Do not check files that have errored */ -++ if (file->no_space_error) -++ return; -++ if (fd == -1) -++ open_and_close = 1; -++ if (open_and_close) { -++ /* Open file */ -++ path = dir_path(file->parent, file->name); -++ fd = open(path, O_RDONLY); -++ CHECK(fd != -1); -++ } -++ /* Check length */ -++ pos = lseek(fd, 0, SEEK_END); -++ if (pos != file->length) { -++ fprintf(stderr, "file_check failed checking length " -++ "expected %u actual %u\n", -++ (unsigned) file->length, -++ (unsigned) pos); -++ file_info_display(file); -++ save_file(fd, file); -++ } -++ CHECK(pos == file->length); -++ /* Check each write */ -++ pos = 0; -++ for (w = file->writes; w; w = w->next) { -++ if (w->offset > pos) -++ file_check_hole(file, fd, pos, w->offset - pos); -++ file_check_data(file, fd, w); -++ pos = w->offset + w->size; -++ } -++ if (file->length > pos) -++ file_check_hole(file, fd, pos, file->length - pos); -++ if (open_and_close) { -++ CHECK(close(fd) != -1); -++ free(path); -++ } -++} -++ -++static const char *dir_entry_name(const struct dir_entry_info *entry) -++{ -++ CHECK(entry != NULL); -++ if (entry->type == 'd') -++ return entry->entry.dir->name; -++ else if (entry->type == 'f') -++ return entry->entry.file->name; -++ else { -++ CHECK(0); -++ return NULL; -++ } -++} -++ -++static int search_comp(const void *pa, const void *pb) -++{ -++ const struct dirent *a = (const struct dirent *) pa; -++ const struct dir_entry_info *b = * (const struct dir_entry_info **) pb; -++ return strcmp(a->d_name, dir_entry_name(b)); -++} -++ -++static void dir_entry_check(struct dir_entry_info **entry_array, -++ size_t number_of_entries, -++ struct dirent *ent) -++{ -++ struct dir_entry_info **found; -++ struct dir_entry_info *entry; -++ size_t sz; -++ -++ sz = sizeof(struct dir_entry_info *); -++ found = bsearch(ent, entry_array, number_of_entries, sz, search_comp); -++ CHECK(found != NULL); -++ entry = *found; -++ CHECK(!entry->checked); -++ entry->checked = 1; -++} -++ -++static int sort_comp(const void *pa, const void *pb) -++{ -++ const struct dir_entry_info *a = * (const struct dir_entry_info **) pa; -++ const struct dir_entry_info *b = * (const struct dir_entry_info **) pb; -++ return strcmp(dir_entry_name(a), dir_entry_name(b)); -++} -++ -++static void dir_check(struct dir_info *dir) -++{ -++ struct dir_entry_info **entry_array, **p; -++ size_t sz, n; -++ struct dir_entry_info *entry; -++ DIR *d; -++ struct dirent *ent; -++ unsigned checked = 0; -++ char *path; -++ -++ /* Create an array of entries */ -++ sz = sizeof(struct dir_entry_info *); -++ n = dir->number_of_entries; -++ entry_array = (struct dir_entry_info **) malloc(sz * n); -++ CHECK(entry_array != NULL); -++ -++ entry = dir->first; -++ p = entry_array; -++ while (entry) { -++ *p++ = entry; -++ entry->checked = 0; -++ entry = entry->next; -++ } -++ -++ /* Sort it by name */ -++ qsort(entry_array, n, sz, sort_comp); -++ -++ /* Go through directory on file system checking entries match */ -++ path = dir_path(dir->parent, dir->name); -++ d = opendir(path); -++ CHECK(d != NULL); -++ for (;;) { -++ errno = 0; -++ ent = readdir(d); -++ if (ent) { -++ if (strcmp(".",ent->d_name) != 0 && -++ strcmp("..",ent->d_name) != 0) { -++ dir_entry_check(entry_array, n, ent); -++ checked += 1; -++ } -++ } else { -++ CHECK(errno == 0); -++ break; -++ } -++ } -++ CHECK(closedir(d) != -1); -++ CHECK(checked == dir->number_of_entries); -++ free(path); -++ -++ /* Now check each entry */ -++ entry = dir->first; -++ while (entry) { -++ if (entry->type == 'd') -++ dir_check(entry->entry.dir); -++ else if (entry->type == 'f') -++ file_check(entry->entry.file, -1); -++ else -++ CHECK(0); -++ entry = entry->next; -++ } -++ -++ free(entry_array); -++} -++ -++static void check_deleted_files(void) -++{ -++ struct open_file_info *ofi; -++ -++ for (ofi = open_files; ofi; ofi = ofi->next) -++ if (ofi->fdi->file->deleted) -++ file_check(ofi->fdi->file, ofi->fdi->fd); -++} -++ -++static void close_open_files(void) -++{ -++ struct open_file_info *ofi; -++ -++ for (ofi = open_files; ofi; ofi = open_files) -++ file_close(ofi->fdi); -++} -++ -++static char *make_name(struct dir_info *dir) -++{ -++ static char name[256]; -++ struct dir_entry_info *entry; -++ int found; -++ -++ do { -++ found = 0; -++ sprintf(name, "%u", (unsigned) tests_random_no(1000000)); -++ for (entry = dir->first; entry; entry = entry->next) { -++ if (strcmp(dir_entry_name(entry), name) == 0) { -++ found = 1; -++ break; -++ } -++ } -++ } while (found); -++ return name; -++} -++ -++static void operate_on_dir(struct dir_info *dir); -++static void operate_on_file(struct file_info *file); -++ -++/* Randomly select something to do with a directory entry */ -++static void operate_on_entry(struct dir_entry_info *entry) -++{ -++ /* If shrinking, 1 time in 50, remove a directory */ -++ if (entry->type == 'd') { -++ if (shrink && tests_random_no(50) == 0) { -++ dir_remove(entry->entry.dir); -++ return; -++ } -++ operate_on_dir(entry->entry.dir); -++ } -++ /* If shrinking, 1 time in 10, remove a file */ -++ if (entry->type == 'f') { -++ if (shrink && tests_random_no(10) == 0) { -++ file_delete(entry->entry.file); -++ return; -++ } -++ operate_on_file(entry->entry.file); -++ } -++} -++ -++/* Randomly select something to do with a directory */ -++static void operate_on_dir(struct dir_info *dir) -++{ -++ size_t r; -++ struct dir_entry_info *entry; -++ -++ r = tests_random_no(12); -++ if (r == 0 && grow) -++ /* When growing, 1 time in 12 create a file */ -++ file_new(dir, make_name(dir)); -++ else if (r == 1 && grow) -++ /* When growing, 1 time in 12 create a directory */ -++ dir_new(dir, make_name(dir)); -++ else { -++ /* Otherwise randomly select an entry to operate on */ -++ r = tests_random_no(dir->number_of_entries); -++ entry = dir->first; -++ while (entry && r) { -++ entry = entry->next; -++ --r; -++ } -++ if (entry) -++ operate_on_entry(entry); -++ } -++} -++ -++/* Randomly select something to do with a file */ -++static void operate_on_file(struct file_info *file) -++{ -++ /* Try to keep at least 10 files open */ -++ if (open_files_count < 10) { -++ file_open(file); -++ return; -++ } -++ /* Try to keep about 20 files open */ -++ if (open_files_count < 20 && tests_random_no(2) == 0) { -++ file_open(file); -++ return; -++ } -++ /* Try to keep up to 40 files open */ -++ if (open_files_count < 40 && tests_random_no(20) == 0) { -++ file_open(file); -++ return; -++ } -++ /* Occasionly truncate */ -++ if (shrink && tests_random_no(100) == 0) { -++ file_truncate_file(file); -++ return; -++ } -++ /* Mostly just write */ -++ file_write_file(file); -++} -++ -++/* Randomly select something to do with an open file */ -++static void operate_on_open_file(struct fd_info *fdi) -++{ -++ size_t r; -++ -++ r = tests_random_no(1000); -++ if (shrink && r == 0) -++ file_truncate(fdi->file, fdi->fd); -++ else if (r < 21) -++ file_close(fdi); -++ else if (shrink && r < 121 && !fdi->file->deleted) -++ file_delete(fdi->file); -++ else -++ file_write(fdi->file, fdi->fd); -++} -++ -++/* Select an open file at random */ -++static void operate_on_an_open_file(void) -++{ -++ size_t r; -++ struct open_file_info *ofi; -++ -++ /* Close any open files that have errored */ -++ ofi = open_files; -++ while (ofi) { -++ if (ofi->fdi->file->no_space_error) { -++ struct fd_info *fdi; -++ -++ fdi = ofi->fdi; -++ ofi = ofi->next; -++ file_close(fdi); -++ } else -++ ofi = ofi->next; -++ } -++ r = tests_random_no(open_files_count); -++ for (ofi = open_files; ofi; ofi = ofi->next, --r) -++ if (!r) { -++ operate_on_open_file(ofi->fdi); -++ return; -++ } -++} -++ -++static void do_an_operation(void) -++{ -++ /* Half the time operate on already open files */ -++ if (tests_random_no(100) < 50) -++ operate_on_dir(top_dir); -++ else -++ operate_on_an_open_file(); -++} -++ -++static void create_test_data(void) -++{ -++ uint64_t i; -++ -++ grow = 1; -++ shrink = 0; -++ full = 0; -++ operation_count = 0; -++ while (!full) { -++ do_an_operation(); -++ ++operation_count; -++ } -++ grow = 0; -++ shrink = 1; -++ /* Drop to less than 90% full */ -++ for (;;) { -++ uint64_t free; -++ uint64_t total; -++ for (i = 0; i < 10; ++i) -++ do_an_operation(); -++ free = tests_get_free_space(); -++ total = tests_get_total_space(); -++ if ((free * 100) / total >= 10) -++ break; -++ } -++ grow = 0; -++ shrink = 0; -++ full = 0; -++ for (i = 0; i < operation_count * 2; ++i) -++ do_an_operation(); -++} -++ -++static void update_test_data(void) -++{ -++ uint64_t i; -++ -++ grow = 1; -++ shrink = 0; -++ full = 0; -++ while (!full) -++ do_an_operation(); -++ grow = 0; -++ shrink = 1; -++ /* Drop to less than 50% full */ -++ for (;;) { -++ uint64_t free; -++ uint64_t total; -++ for (i = 0; i < 10; ++i) -++ do_an_operation(); -++ free = tests_get_free_space(); -++ total = tests_get_total_space(); -++ if ((free * 100) / total >= 50) -++ break; -++ } -++ grow = 0; -++ shrink = 0; -++ full = 0; -++ for (i = 0; i < operation_count * 2; ++i) -++ do_an_operation(); -++} -++ -++void integck(void) -++{ -++ pid_t pid; -++ int64_t rpt; -++ uint64_t z; -++ char dir_name[256]; -++ -++ /* Make our top directory */ -++ pid = getpid(); -++ printf("pid is %u\n", (unsigned) pid); -++ tests_cat_pid(dir_name, "integck_test_dir_", pid); -++ if (chdir(dir_name) != -1) { -++ /* Remove it if it is already there */ -++ tests_clear_dir("."); -++ CHECK(chdir("..") != -1); -++ CHECK(rmdir(dir_name) != -1); -++ } -++ initial_free_space = tests_get_free_space(); -++ log10_initial_free_space = 0; -++ for (z = initial_free_space; z >= 10; z /= 10) -++ ++log10_initial_free_space; -++ top_dir = dir_new(NULL, dir_name); -++ -++ if (!top_dir) -++ return; -++ -++ srand(pid); -++ -++ create_test_data(); -++ -++ if (!tests_fs_is_rootfs()) { -++ close_open_files(); -++ tests_remount(); /* Requires root access */ -++ } -++ -++ /* Check everything */ -++ dir_check(top_dir); -++ check_deleted_files(); -++ -++ for (rpt = 0; tests_repeat_parameter == 0 || -++ rpt < tests_repeat_parameter; ++rpt) { -++ update_test_data(); -++ -++ if (!tests_fs_is_rootfs()) { -++ close_open_files(); -++ tests_remount(); /* Requires root access */ -++ } -++ -++ /* Check everything */ -++ dir_check(top_dir); -++ check_deleted_files(); -++ } -++ -++ /* Tidy up by removing everything */ -++ close_open_files(); -++ tests_clear_dir(dir_name); -++ CHECK(rmdir(dir_name) != -1); -++} -++ -++/* Title of this test */ -++ -++const char *integck_get_title(void) -++{ -++ return "Test file system integrity"; -++} -++ -++/* Description of this test */ -++ -++const char *integck_get_description(void) -++{ -++ return -++ "Create a directory named integck_test_dir_pid " \ -++ "where pid is the process id. " \ -++ "Randomly create and delete files and directories. " \ -++ "Randomly write to and truncate files. " \ -++ "Un-mount and re-mount test file " \ -++ "system (if it is not the root file system ). " \ -++ "Check data. Make more random changes. " \ -++ "Un-mount and re-mount again. Check again. " \ -++ "Repeat some number of times. " -++ "The repeat count is set by the -n or --repeat option, " \ -++ "otherwise it defaults to 1. " \ -++ "A repeat count of zero repeats forever."; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int run_test; -++ -++ /* Set default test repetition */ -++ tests_repeat_parameter = 1; -++ -++ /* Handle common arguments */ -++ run_test = tests_get_args(argc, argv, integck_get_title(), -++ integck_get_description(), "n"); -++ if (!run_test) -++ return 1; -++ /* Change directory to the file system and check it is ok for testing */ -++ tests_check_test_file_system(); -++ /* Do the actual test */ -++ integck(); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/lib/Makefile linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/lib/Makefile -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/lib/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/lib/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,18 @@ -++ -++ifeq ($(origin CC),default) -++CC = gcc -++endif -++ -++CFLAGS := $(CFLAGS) -Wall -g -O2 -++ -++LDFLAGS := $(LDFLAGS) -++ -++all: tests.o -++ -++tests.o: tests.h -++ -++clean: -++ rm -f *.o -++ -++tests: -++ echo -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/lib/tests.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/lib/tests.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/lib/tests.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/lib/tests.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1091 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "tests.h" -++ -++char *tests_file_system_mount_dir = TESTS_DEFAULT_FILE_SYSTEM_MOUNT_DIR; -++ -++char *tests_file_system_type = TESTS_DEFAULT_FILE_SYSTEM_TYPE; -++ -++int tests_ok_to_sync = 0; /* Whether to use fsync */ -++ -++/* General purpose test parameter to specify some aspect of test size. -++ May be used by different tests in different ways or not at all. -++ Set by the -z or --size option. */ -++int64_t tests_size_parameter = 0; -++ -++/* General purpose test parameter to specify some aspect of test repetition. -++ May be used by different tests in different ways or not at all. -++ Set by the -n, --repeat options. */ -++int64_t tests_repeat_parameter = 0; -++ -++/* General purpose test parameter to specify some aspect of test sleeping. -++ May be used by different tests in different ways or not at all. -++ Set by the -p, --sleep options. */ -++int64_t tests_sleep_parameter = 0; -++ -++/* Program name from argv[0] */ -++char *program_name = "unknown"; -++ -++/* General purpose test parameter to specify a file should be unlinked. -++ May be used by different tests in different ways or not at all. */ -++int tests_unlink_flag = 0; -++ -++/* General purpose test parameter to specify a file should be closed. -++ May be used by different tests in different ways or not at all. */ -++int tests_close_flag = 0; -++ -++/* General purpose test parameter to specify a file should be deleted. -++ May be used by different tests in different ways or not at all. */ -++int tests_delete_flag = 0; -++ -++/* General purpose test parameter to specify a file have a hole. -++ May be used by different tests in different ways or not at all. */ -++int tests_hole_flag = 0; -++ -++/* Whether it is ok to test on the root file system */ -++static int rootok = 0; -++ -++/* Function invoked by the CHECK macro */ -++void tests_test(int test,const char *msg,const char *file,unsigned line) -++{ -++ int eno; -++ time_t t; -++ -++ if (test) -++ return; -++ eno = errno; -++ time(&t); -++ fprintf(stderr, "Test failed: %s on %s" -++ "Test failed: %s in %s at line %u\n", -++ program_name, ctime(&t), msg, file, line); -++ if (eno) { -++ fprintf(stderr,"errno = %d\n",eno); -++ fprintf(stderr,"strerror = %s\n",strerror(eno)); -++ } -++ exit(1); -++} -++ -++static int is_zero(const char *p) -++{ -++ for (;*p;++p) -++ if (*p != '0') -++ return 0; -++ return 1; -++} -++ -++static void fold(const char *text, int width) -++{ -++ int pos, bpos = 0; -++ const char *p; -++ char line[1024]; -++ -++ if (width > 1023) { -++ printf("%s\n", text); -++ return; -++ } -++ p = text; -++ pos = 0; -++ while (p[pos]) { -++ while (!isspace(p[pos])) { -++ line[pos] = p[pos]; -++ if (!p[pos]) -++ break; -++ ++pos; -++ if (pos == width) { -++ line[pos] = '\0'; -++ printf("%s\n", line); -++ p += pos; -++ pos = 0; -++ } -++ } -++ while (pos < width) { -++ line[pos] = p[pos]; -++ if (!p[pos]) { -++ bpos = pos; -++ break; -++ } -++ if (isspace(p[pos])) -++ bpos = pos; -++ ++pos; -++ } -++ line[bpos] = '\0'; -++ printf("%s\n", line); -++ p += bpos; -++ pos = 0; -++ while (p[pos] && isspace(p[pos])) -++ ++p; -++ } -++} -++ -++/* Handle common program options */ -++int tests_get_args(int argc, -++ char *argv[], -++ const char *title, -++ const char *desc, -++ const char *opts) -++{ -++ int run_test = 0; -++ int display_help = 0; -++ int display_title = 0; -++ int display_description = 0; -++ int i; -++ char *s; -++ -++ program_name = argv[0]; -++ -++ s = getenv("TEST_FILE_SYSTEM_MOUNT_DIR"); -++ if (s) -++ tests_file_system_mount_dir = strdup(s); -++ s = getenv("TEST_FILE_SYSTEM_TYPE"); -++ if (s) -++ tests_file_system_type = strdup(s); -++ -++ run_test = 1; -++ rootok = 1; -++ for (i = 1; i < argc; ++i) { -++ if (strcmp(argv[i], "--help") == 0 || -++ strcmp(argv[i], "-h") == 0) -++ display_help = 1; -++ else if (strcmp(argv[i], "--title") == 0 || -++ strcmp(argv[i], "-t") == 0) -++ display_title = 1; -++ else if (strcmp(argv[i], "--description") == 0 || -++ strcmp(argv[i], "-d") == 0) -++ display_description = 1; -++ else if (strcmp(argv[i], "--sync") == 0 || -++ strcmp(argv[i], "-s") == 0) -++ tests_ok_to_sync = 1; -++ else if (strncmp(argv[i], "--size", 6) == 0 || -++ strncmp(argv[i], "-z", 2) == 0) { -++ int64_t n; -++ char *p; -++ if (i+1 < argc && !isdigit(argv[i][strlen(argv[i])-1])) -++ ++i; -++ p = argv[i]; -++ while (*p && !isdigit(*p)) -++ ++p; -++ n = atoll(p); -++ if (n) -++ tests_size_parameter = n; -++ else { -++ int all_zero = 1; -++ for (; all_zero && *p; ++p) -++ if (*p != '0') -++ all_zero = 0; -++ if (all_zero) -++ tests_size_parameter = 0; -++ else -++ display_help = 1; -++ } -++ } else if (strncmp(argv[i], "--repeat", 8) == 0 || -++ strncmp(argv[i], "-n", 2) == 0) { -++ int64_t n; -++ char *p; -++ if (i+1 < argc && !isdigit(argv[i][strlen(argv[i])-1])) -++ ++i; -++ p = argv[i]; -++ while (*p && !isdigit(*p)) -++ ++p; -++ n = atoll(p); -++ if (n || is_zero(p)) -++ tests_repeat_parameter = n; -++ else -++ display_help = 1; -++ } else if (strncmp(argv[i], "--sleep", 7) == 0 || -++ strncmp(argv[i], "-p", 2) == 0) { -++ int64_t n; -++ char *p; -++ if (i+1 < argc && !isdigit(argv[i][strlen(argv[i])-1])) -++ ++i; -++ p = argv[i]; -++ while (*p && !isdigit(*p)) -++ ++p; -++ n = atoll(p); -++ if (n || is_zero(p)) -++ tests_sleep_parameter = n; -++ else -++ display_help = 1; -++ } else if (strcmp(argv[i], "--unlink") == 0 || -++ strcmp(argv[i], "-u") == 0) -++ tests_unlink_flag = 1; -++ else if (strcmp(argv[i], "--hole") == 0 || -++ strcmp(argv[i], "-o") == 0) -++ tests_hole_flag = 1; -++ else if (strcmp(argv[i], "--close") == 0 || -++ strcmp(argv[i], "-c") == 0) -++ tests_close_flag = 1; -++ else if (strcmp(argv[i], "--delete") == 0 || -++ strcmp(argv[i], "-e") == 0) -++ tests_delete_flag = 1; -++ else -++ display_help = 1; -++ } -++ -++ if (display_help) { -++ run_test = 0; -++ display_title = 0; -++ display_description = 0; -++ if (!opts) -++ opts = ""; -++ printf("File System Test Program\n\n"); -++ printf("Test Title: %s\n\n", title); -++ printf("Usage is: %s [ options ]\n",argv[0]); -++ printf(" Options are:\n"); -++ printf(" -h, --help "); -++ printf("Display this help\n"); -++ printf(" -t, --title "); -++ printf("Display the test title\n"); -++ printf(" -d, --description "); -++ printf("Display the test description\n"); -++ if (strchr(opts, 's')) { -++ printf(" -s, --sync "); -++ printf("Make use of fsync\n"); -++ } -++ if (strchr(opts, 'z')) { -++ printf(" -z, --size "); -++ printf("Set size parameter\n"); -++ } -++ if (strchr(opts, 'n')) { -++ printf(" -n, --repeat "); -++ printf("Set repeat parameter\n"); -++ } -++ if (strchr(opts, 'p')) { -++ printf(" -p, --sleep "); -++ printf("Set sleep parameter\n"); -++ } -++ if (strchr(opts, 'u')) { -++ printf(" -u, --unlink "); -++ printf("Unlink file\n"); -++ } -++ if (strchr(opts, 'o')) { -++ printf(" -o, --hole "); -++ printf("Create a hole in a file\n"); -++ } -++ if (strchr(opts, 'c')) { -++ printf(" -c, --close "); -++ printf("Close file\n"); -++ } -++ if (strchr(opts, 'e')) { -++ printf(" -e, --delete "); -++ printf("Delete file\n"); -++ } -++ printf("\nBy default, testing is done in directory "); -++ printf("/mnt/test_file_system. To change this\nuse "); -++ printf("environmental variable "); -++ printf("TEST_FILE_SYSTEM_MOUNT_DIR. By default, "); -++ printf("the file\nsystem tested is jffs2. To change this "); -++ printf("set TEST_FILE_SYSTEM_TYPE.\n\n"); -++ printf("Test Description:\n"); -++ fold(desc, 80); -++ } else { -++ if (display_title) -++ printf("%s\n", title); -++ if (display_description) -++ printf("%s\n", desc); -++ if (display_title || display_description) -++ if (argc == 2 || (argc == 3 && -++ display_title && -++ display_description)) -++ run_test = 0; -++ } -++ return run_test; -++} -++ -++/* Return the number of files (or directories) in the given directory */ -++unsigned tests_count_files_in_dir(const char *dir_name) -++{ -++ DIR *dir; -++ struct dirent *entry; -++ unsigned count = 0; -++ -++ dir = opendir(dir_name); -++ CHECK(dir != NULL); -++ for (;;) { -++ errno = 0; -++ entry = readdir(dir); -++ if (entry) { -++ if (strcmp(".",entry->d_name) != 0 && -++ strcmp("..",entry->d_name) != 0) -++ ++count; -++ } else { -++ CHECK(errno == 0); -++ break; -++ } -++ } -++ CHECK(closedir(dir) != -1); -++ return count; -++} -++ -++/* Change to the file system mount directory, check that it is empty, -++ matches the file system type, and is not the root file system */ -++void tests_check_test_file_system(void) -++{ -++ struct statfs fs_info; -++ struct stat f_info; -++ struct stat root_f_info; -++ -++ if (chdir(tests_file_system_mount_dir) == -1 || -++ statfs(tests_file_system_mount_dir, &fs_info) == -1) { -++ fprintf(stderr, "Invalid test file system mount directory:" -++ " %s\n", tests_file_system_mount_dir); -++ fprintf(stderr, "Use environment variable " -++ "TEST_FILE_SYSTEM_MOUNT_DIR\n"); -++ CHECK(0); -++ } -++ if (strcmp(tests_file_system_type, "jffs2") == 0 && -++ fs_info.f_type != JFFS2_SUPER_MAGIC) { -++ fprintf(stderr, "File system type is not jffs2\n"); -++ CHECK(0); -++ } -++ /* Check that the test file system is not the root file system */ -++ if (!rootok) { -++ CHECK(stat(tests_file_system_mount_dir, &f_info) != -1); -++ CHECK(stat("/", &root_f_info) != -1); -++ CHECK(f_info.st_dev != root_f_info.st_dev); -++ } -++} -++ -++/* Get the free space for the file system of the current directory */ -++uint64_t tests_get_free_space(void) -++{ -++ struct statvfs fs_info; -++ -++ CHECK(statvfs(tests_file_system_mount_dir, &fs_info) != -1); -++ return (uint64_t) fs_info.f_bavail * (uint64_t) fs_info.f_frsize; -++} -++ -++/* Get the total space for the file system of the current directory */ -++uint64_t tests_get_total_space(void) -++{ -++ struct statvfs fs_info; -++ -++ CHECK(statvfs(tests_file_system_mount_dir, &fs_info) != -1); -++ return (uint64_t) fs_info.f_blocks * (uint64_t) fs_info.f_frsize; -++} -++ -++#define WRITE_BUFFER_SIZE 32768 -++ -++static char write_buffer[WRITE_BUFFER_SIZE]; -++ -++static void init_write_buffer() -++{ -++ static int init = 0; -++ -++ if (!init) { -++ int i, d; -++ uint64_t u; -++ -++ u = RAND_MAX; -++ u += 1; -++ u /= 256; -++ d = (int) u; -++ srand(1); -++ for (i = 0; i < WRITE_BUFFER_SIZE; ++i) -++ write_buffer[i] = rand() / d; -++ init = 1; -++ } -++} -++ -++/* Write size random bytes into file descriptor fd at the current position, -++ returning the number of bytes actually written */ -++uint64_t tests_fill_file(int fd, uint64_t size) -++{ -++ ssize_t written; -++ size_t sz; -++ unsigned start = 0, length; -++ uint64_t remains; -++ uint64_t actual_size = 0; -++ -++ init_write_buffer(); -++ remains = size; -++ while (remains > 0) { -++ length = WRITE_BUFFER_SIZE - start; -++ if (remains > length) -++ sz = length; -++ else -++ sz = (size_t) remains; -++ written = write(fd, write_buffer + start, sz); -++ if (written <= 0) { -++ CHECK(errno == ENOSPC); /* File system full */ -++ errno = 0; -++ break; -++ } -++ remains -= written; -++ actual_size += written; -++ if (written == sz) -++ start = 0; -++ else -++ start += written; -++ } -++ tests_maybe_sync(fd); -++ return actual_size; -++} -++ -++/* Write size random bytes into file descriptor fd at offset, -++ returning the number of bytes actually written */ -++uint64_t tests_write_filled_file(int fd, off_t offset, uint64_t size) -++{ -++ ssize_t written; -++ size_t sz; -++ unsigned start = 0, length; -++ uint64_t remains; -++ uint64_t actual_size = 0; -++ -++ CHECK(lseek(fd, offset, SEEK_SET) == offset); -++ -++ init_write_buffer(); -++ remains = size; -++ start = offset % WRITE_BUFFER_SIZE; -++ while (remains > 0) { -++ length = WRITE_BUFFER_SIZE - start; -++ if (remains > length) -++ sz = length; -++ else -++ sz = (size_t) remains; -++ written = write(fd, write_buffer + start, sz); -++ if (written <= 0) { -++ CHECK(errno == ENOSPC); /* File system full */ -++ errno = 0; -++ break; -++ } -++ remains -= written; -++ actual_size += written; -++ if (written == sz) -++ start = 0; -++ else -++ start += written; -++ } -++ tests_maybe_sync(fd); -++ return actual_size; -++} -++ -++/* Check that a file written using tests_fill_file() and/or -++ tests_write_filled_file() and/or tests_create_file() -++ contains the expected random data */ -++void tests_check_filled_file_fd(int fd) -++{ -++ ssize_t sz; -++ char buf[WRITE_BUFFER_SIZE]; -++ -++ CHECK(lseek(fd, 0, SEEK_SET) == 0); -++ do { -++ sz = read(fd, buf, WRITE_BUFFER_SIZE); -++ CHECK(sz >= 0); -++ CHECK(memcmp(buf, write_buffer, sz) == 0); -++ } while (sz); -++} -++ -++/* Check that a file written using tests_fill_file() and/or -++ tests_write_filled_file() and/or tests_create_file() -++ contains the expected random data */ -++void tests_check_filled_file(const char *file_name) -++{ -++ int fd; -++ -++ fd = open(file_name, O_RDONLY); -++ CHECK(fd != -1); -++ tests_check_filled_file_fd(fd); -++ CHECK(close(fd) != -1); -++} -++ -++void tests_sync_directory(const char *file_name) -++{ -++ char *path; -++ char *dir; -++ int fd; -++ -++ if (!tests_ok_to_sync) -++ return; -++ -++ path = strdup(file_name); -++ dir = dirname(path); -++ fd = open(dir,O_RDONLY | tests_maybe_sync_flag()); -++ CHECK(fd != -1); -++ CHECK(fsync(fd) != -1); -++ CHECK(close(fd) != -1); -++ free(path); -++} -++ -++/* Delete a file */ -++void tests_delete_file(const char *file_name) -++{ -++ CHECK(unlink(file_name) != -1); -++ tests_sync_directory(file_name); -++} -++ -++/* Create a file of size file_size */ -++uint64_t tests_create_file(const char *file_name, uint64_t file_size) -++{ -++ int fd; -++ int flags; -++ mode_t mode; -++ uint64_t actual_size; /* Less than size if the file system is full */ -++ -++ flags = O_CREAT | O_TRUNC | O_WRONLY | tests_maybe_sync_flag(); -++ mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; -++ fd = open(file_name, flags, mode); -++ if (fd == -1 && errno == ENOSPC) { -++ errno = 0; -++ return 0; /* File system full */ -++ } -++ CHECK(fd != -1); -++ actual_size = tests_fill_file(fd, file_size); -++ CHECK(close(fd) != -1); -++ if (file_size != 0 && actual_size == 0) -++ tests_delete_file(file_name); -++ else -++ tests_sync_directory(file_name); -++ return actual_size; -++} -++ -++/* Calculate: free_space * numerator / denominator */ -++uint64_t tests_get_big_file_size(unsigned numerator, unsigned denominator) -++{ -++ if (denominator == 0) -++ denominator = 1; -++ if (numerator > denominator) -++ numerator = denominator; -++ return numerator * (tests_get_free_space() / denominator); -++} -++ -++/* Create file "fragment_n" where n is the file_number, and unlink it */ -++int tests_create_orphan(unsigned file_number) -++{ -++ int fd; -++ int flags; -++ mode_t mode; -++ char file_name[256]; -++ -++ sprintf(file_name, "fragment_%u", file_number); -++ flags = O_CREAT | O_TRUNC | O_RDWR | tests_maybe_sync_flag(); -++ mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; -++ fd = open(file_name, flags, mode); -++ if (fd == -1 && (errno == ENOSPC || errno == EMFILE)) -++ return fd; /* File system full or too many open files */ -++ CHECK(fd != -1); -++ tests_sync_directory(file_name); -++ CHECK(unlink(file_name) != -1); -++ return fd; -++} -++ -++/* Write size bytes at offset to the file "fragment_n" where n is the -++ file_number and file_number also determines the random data written -++ i.e. seed for random numbers */ -++unsigned tests_write_fragment_file(unsigned file_number, -++ int fd, -++ off_t offset, -++ unsigned size) -++{ -++ int i, d; -++ uint64_t u; -++ ssize_t written; -++ off_t pos; -++ char buf[WRITE_BUFFER_SIZE]; -++ -++ if (size > WRITE_BUFFER_SIZE) -++ size = WRITE_BUFFER_SIZE; -++ -++ pos = lseek(fd, 0, SEEK_END); -++ CHECK(pos != (off_t) -1); -++ if (offset > pos) -++ offset = pos; -++ -++ pos = lseek(fd, offset, SEEK_SET); -++ CHECK(pos != (off_t) -1); -++ CHECK(pos == offset); -++ -++ srand(file_number); -++ while (offset--) -++ rand(); -++ -++ u = RAND_MAX; -++ u += 1; -++ u /= 256; -++ d = (int) u; -++ for (i = 0; i < size; ++i) -++ buf[i] = rand() / d; -++ -++ written = write(fd, buf, size); -++ if (written <= 0) { -++ CHECK(errno == ENOSPC); /* File system full */ -++ errno = 0; -++ written = 0; -++ } -++ tests_maybe_sync(fd); -++ return (unsigned) written; -++} -++ -++/* Write size bytes to the end of file descriptor fd using file_number -++ to determine the random data written i.e. seed for random numbers */ -++unsigned tests_fill_fragment_file(unsigned file_number, int fd, unsigned size) -++{ -++ off_t offset; -++ -++ offset = lseek(fd, 0, SEEK_END); -++ CHECK(offset != (off_t) -1); -++ -++ return tests_write_fragment_file(file_number, fd, offset, size); -++} -++ -++/* Write size bytes to the end of file "fragment_n" where n is the file_number -++ and file_number also determines the random data written -++ i.e. seed for random numbers */ -++unsigned tests_append_to_fragment_file(unsigned file_number, -++ unsigned size, -++ int create) -++{ -++ int fd; -++ int flags; -++ mode_t mode; -++ unsigned actual_growth; -++ char file_name[256]; -++ -++ sprintf(file_name, "fragment_%u", file_number); -++ if (create) -++ flags = O_CREAT | O_EXCL | O_WRONLY | tests_maybe_sync_flag(); -++ else -++ flags = O_WRONLY | tests_maybe_sync_flag(); -++ mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; -++ fd = open(file_name, flags, mode); -++ if (fd == -1 && errno == ENOSPC) { -++ errno = 0; -++ return 0; /* File system full */ -++ } -++ CHECK(fd != -1); -++ actual_growth = tests_fill_fragment_file(file_number, fd, size); -++ CHECK(close(fd) != -1); -++ if (create && !actual_growth) -++ tests_delete_fragment_file(file_number); -++ return actual_growth; -++} -++ -++/* Write size bytes at offset to the file "fragment_n" where n is the -++ file_number and file_number also determines the random data written -++ i.e. seed for random numbers */ -++unsigned tests_overwite_fragment_file( unsigned file_number, -++ off_t offset, -++ unsigned size) -++{ -++ int fd; -++ unsigned actual_size; -++ char file_name[256]; -++ -++ sprintf(file_name, "fragment_%u", file_number); -++ fd = open(file_name, O_RDWR | tests_maybe_sync_flag()); -++ if (fd == -1 && errno == ENOSPC) { -++ errno = 0; -++ return 0; /* File system full */ -++ } -++ CHECK(fd != -1); -++ actual_size = tests_write_fragment_file(file_number, -++ fd, offset, size); -++ CHECK(close(fd) != -1); -++ return actual_size; -++} -++ -++/* Delete file "fragment_n" where n is the file_number */ -++void tests_delete_fragment_file(unsigned file_number) -++{ -++ char file_name[256]; -++ -++ sprintf(file_name, "fragment_%u", file_number); -++ tests_delete_file(file_name); -++} -++ -++/* Check the random data in file "fragment_n" is what is expected */ -++void tests_check_fragment_file_fd(unsigned file_number, int fd) -++{ -++ ssize_t sz, i; -++ int d; -++ uint64_t u; -++ char buf[8192]; -++ -++ CHECK(lseek(fd, 0, SEEK_SET) == 0); -++ srand(file_number); -++ u = RAND_MAX; -++ u += 1; -++ u /= 256; -++ d = (int) u; -++ for (;;) { -++ sz = read(fd, buf, 8192); -++ if (sz == 0) -++ break; -++ CHECK(sz >= 0); -++ for (i = 0; i < sz; ++i) -++ CHECK(buf[i] == (char) (rand() / d)); -++ } -++} -++ -++/* Check the random data in file "fragment_n" is what is expected */ -++void tests_check_fragment_file(unsigned file_number) -++{ -++ int fd; -++ ssize_t sz, i; -++ int d; -++ uint64_t u; -++ char file_name[256]; -++ char buf[8192]; -++ -++ sprintf(file_name, "fragment_%u", file_number); -++ fd = open(file_name, O_RDONLY); -++ CHECK(fd != -1); -++ srand(file_number); -++ u = RAND_MAX; -++ u += 1; -++ u /= 256; -++ d = (int) u; -++ for (;;) { -++ sz = read(fd, buf, 8192); -++ if (sz == 0) -++ break; -++ CHECK(sz >= 0); -++ for (i = 0; i < sz; ++i) -++ CHECK(buf[i] == (char) (rand() / d)); -++ } -++ CHECK(close(fd) != -1); -++} -++ -++/* Central point to decide whether to use fsync */ -++void tests_maybe_sync(int fd) -++{ -++ if (tests_ok_to_sync) -++ CHECK(fsync(fd) != -1); -++} -++ -++/* Return O_SYNC if ok to sync otherwise return 0 */ -++int tests_maybe_sync_flag(void) -++{ -++ if (tests_ok_to_sync) -++ return O_SYNC; -++ return 0; -++} -++ -++/* Return random number from 0 to n - 1 */ -++size_t tests_random_no(size_t n) -++{ -++ uint64_t a, b; -++ -++ if (!n) -++ return 0; -++ if (n - 1 <= RAND_MAX) { -++ a = rand(); -++ b = RAND_MAX; -++ b += 1; -++ } else { -++ const uint64_t u = 1 + (uint64_t) RAND_MAX; -++ a = rand(); -++ a *= u; -++ a += rand(); -++ b = u * u; -++ CHECK(n <= b); -++ } -++ if (RAND_MAX <= UINT32_MAX && n <= UINT32_MAX) -++ return a * n / b; -++ else /*if (RAND_MAX <= UINT64_MAX && n <= UINT64_MAX)*/ { -++ uint64_t x, y; -++ if (a < n) { -++ x = a; -++ y = n; -++ } else { -++ x = n; -++ y = a; -++ } -++ return (x * (y / b)) + ((x * (y % b)) / b); -++ } -++} -++ -++/* Make a directory empty */ -++void tests_clear_dir(const char *dir_name) -++{ -++ DIR *dir; -++ struct dirent *entry; -++ char buf[4096]; -++ -++ dir = opendir(dir_name); -++ CHECK(dir != NULL); -++ CHECK(getcwd(buf, 4096) != NULL); -++ CHECK(chdir(dir_name) != -1); -++ for (;;) { -++ errno = 0; -++ entry = readdir(dir); -++ if (entry) { -++ if (strcmp(".",entry->d_name) != 0 && -++ strcmp("..",entry->d_name) != 0) { -++ if (entry->d_type == DT_DIR) { -++ tests_clear_dir(entry->d_name); -++ CHECK(rmdir(entry->d_name) != -1); -++ } else -++ CHECK(unlink(entry->d_name) != -1); -++ } -++ } else { -++ CHECK(errno == 0); -++ break; -++ } -++ } -++ CHECK(chdir(buf) != -1); -++ CHECK(closedir(dir) != -1); -++} -++ -++/* Create an empty sub-directory or small file in the current directory */ -++int64_t tests_create_entry(char *return_name) -++{ -++ int fd; -++ char name[256]; -++ -++ for (;;) { -++ sprintf(name, "%u", (unsigned) tests_random_no(10000000)); -++ fd = open(name, O_RDONLY); -++ if (fd == -1) -++ break; -++ close(fd); -++ } -++ if (return_name) -++ strcpy(return_name, name); -++ if (tests_random_no(2)) { -++ return tests_create_file(name, tests_random_no(4096)); -++ } else { -++ if (mkdir(name, 0777) == -1) { -++ CHECK(errno == ENOSPC); -++ errno = 0; -++ return 0; -++ } -++ return TESTS_EMPTY_DIR_SIZE; -++ } -++} -++ -++/* Remove a random file of empty sub-directory from the current directory */ -++int64_t tests_remove_entry(void) -++{ -++ DIR *dir; -++ struct dirent *entry; -++ unsigned count = 0, pos; -++ int64_t result = 0; -++ -++ dir = opendir("."); -++ CHECK(dir != NULL); -++ for (;;) { -++ errno = 0; -++ entry = readdir(dir); -++ if (entry) { -++ if (strcmp(".",entry->d_name) != 0 && -++ strcmp("..",entry->d_name) != 0) -++ ++count; -++ } else { -++ CHECK(errno == 0); -++ break; -++ } -++ } -++ pos = tests_random_no(count); -++ count = 0; -++ rewinddir(dir); -++ for (;;) { -++ errno = 0; -++ entry = readdir(dir); -++ if (!entry) { -++ CHECK(errno == 0); -++ break; -++ } -++ if (strcmp(".",entry->d_name) != 0 && -++ strcmp("..",entry->d_name) != 0) { -++ if (count == pos) { -++ if (entry->d_type == DT_DIR) { -++ tests_clear_dir(entry->d_name); -++ CHECK(rmdir(entry->d_name) != -1); -++ result = TESTS_EMPTY_DIR_SIZE; -++ } else { -++ struct stat st; -++ CHECK(stat(entry->d_name, &st) != -1); -++ result = st.st_size; -++ CHECK(unlink(entry->d_name) != -1); -++ } -++ } -++ ++count; -++ } -++ } -++ CHECK(closedir(dir) != -1); -++ return result; -++} -++ -++/* Read mount information from /proc/mounts or /etc/mtab */ -++int tests_get_mount_info(struct mntent *info) -++{ -++ FILE *f; -++ struct mntent *entry; -++ int found = 0; -++ -++ f = fopen("/proc/mounts", "rb"); -++ if (!f) -++ f = fopen("/etc/mtab", "rb"); -++ CHECK(f != NULL); -++ while (!found) { -++ entry = getmntent(f); -++ if (entry) { -++ if (strcmp(entry->mnt_dir, -++ tests_file_system_mount_dir) == 0) { -++ found = 1; -++ *info = *entry; -++ } -++ } else -++ break; -++ } -++ CHECK(fclose(f) == 0); -++ return found; -++} -++ -++/* Un-mount and re-mount test file system */ -++void tests_remount(void) -++{ -++ struct mntent mount_info; -++ char *source; -++ char *target; -++ char *filesystemtype; -++ unsigned long mountflags; -++ void *data; -++ char cwd[4096]; -++ -++ CHECK(tests_get_mount_info(&mount_info)); -++ -++ if (strcmp(mount_info.mnt_dir,"/") == 0) -++ return; -++ -++ CHECK(getcwd(cwd, 4096) != NULL); -++ CHECK(chdir("/") != -1); -++ -++ CHECK(umount(tests_file_system_mount_dir) != -1); -++ -++ source = mount_info.mnt_fsname; -++ target = tests_file_system_mount_dir; -++ filesystemtype = tests_file_system_type; -++ mountflags = 0; -++ data = NULL; -++ -++ CHECK(mount(source, target, filesystemtype, mountflags, data) != -1); -++ -++ CHECK(chdir(cwd) != -1); -++} -++ -++/* Check whether the test file system is also the root file system */ -++int tests_fs_is_rootfs(void) -++{ -++ struct stat f_info; -++ struct stat root_f_info; -++ -++ CHECK(stat(tests_file_system_mount_dir, &f_info) != -1); -++ CHECK(stat("/", &root_f_info) != -1); -++ if (f_info.st_dev == root_f_info.st_dev) -++ return 1; -++ else -++ return 0; -++} -++ -++/* Try to make a directory empty */ -++void tests_try_to_clear_dir(const char *dir_name) -++{ -++ DIR *dir; -++ struct dirent *entry; -++ char buf[4096]; -++ -++ dir = opendir(dir_name); -++ if (dir == NULL) -++ return; -++ if (getcwd(buf, 4096) == NULL || chdir(dir_name) == -1) { -++ closedir(dir); -++ return; -++ } -++ for (;;) { -++ errno = 0; -++ entry = readdir(dir); -++ if (entry) { -++ if (strcmp(".",entry->d_name) != 0 && -++ strcmp("..",entry->d_name) != 0) { -++ if (entry->d_type == DT_DIR) { -++ tests_try_to_clear_dir(entry->d_name); -++ rmdir(entry->d_name); -++ } else -++ unlink(entry->d_name); -++ } -++ } else { -++ CHECK(errno == 0); -++ break; -++ } -++ } -++ chdir(buf); -++ closedir(dir); -++} -++ -++/* Check whether the test file system is also the current file system */ -++int tests_fs_is_currfs(void) -++{ -++ struct stat f_info; -++ struct stat curr_f_info; -++ -++ CHECK(stat(tests_file_system_mount_dir, &f_info) != -1); -++ CHECK(stat(".", &curr_f_info) != -1); -++ if (f_info.st_dev == curr_f_info.st_dev) -++ return 1; -++ else -++ return 0; -++} -++ -++#define PID_BUF_SIZE 64 -++ -++/* Concatenate a pid to a string in a signal safe way */ -++void tests_cat_pid(char *buf, const char *name, pid_t pid) -++{ -++ char *p; -++ unsigned x; -++ const char digits[] = "0123456789"; -++ char pid_buf[PID_BUF_SIZE]; -++ -++ x = (unsigned) pid; -++ p = pid_buf + PID_BUF_SIZE; -++ *--p = '\0'; -++ if (x) -++ while (x) { -++ *--p = digits[x % 10]; -++ x /= 10; -++ } -++ else -++ *--p = '0'; -++ buf[0] = '\0'; -++ strcat(buf, name); -++ strcat(buf, p); -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/lib/tests.h linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/lib/tests.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/lib/tests.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/lib/tests.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,199 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#ifndef included_tests_tests_h__ -++#define included_tests_tests_h__ -++ -++#include -++ -++/* Main macro for testing */ -++#define CHECK(x) tests_test((x),__func__,__FILE__,__LINE__) -++ -++/* The default directory in which tests are conducted */ -++#define TESTS_DEFAULT_FILE_SYSTEM_MOUNT_DIR "/mnt/test_file_system" -++ -++/* The default file system type to test */ -++#define TESTS_DEFAULT_FILE_SYSTEM_TYPE "jffs2" -++ -++/* Estimated size of an empty directory */ -++#define TESTS_EMPTY_DIR_SIZE 128 -++ -++/* Function invoked by the CHECK macro */ -++void tests_test(int test,const char *msg,const char *file,unsigned line); -++ -++/* Handle common program options */ -++int tests_get_args(int argc, -++ char *argv[], -++ const char *title, -++ const char *desc, -++ const char *opts); -++ -++/* Return the number of files (or directories) in the given directory */ -++unsigned tests_count_files_in_dir(const char *dir_name); -++ -++/* Change to the file system mount directory, check that it is empty, -++ matches the file system type, and is not the root file system */ -++void tests_check_test_file_system(void); -++ -++/* Get the free space for the file system of the current directory */ -++uint64_t tests_get_free_space(void); -++ -++/* Get the total space for the file system of the current directory */ -++uint64_t tests_get_total_space(void); -++ -++/* Write size random bytes into file descriptor fd at the current position, -++ returning the number of bytes actually written */ -++uint64_t tests_fill_file(int fd, uint64_t size); -++ -++/* Write size random bytes into file descriptor fd at offset, -++ returning the number of bytes actually written */ -++uint64_t tests_write_filled_file(int fd, off_t offset, uint64_t size); -++ -++/* Check that a file written using tests_fill_file() and/or -++ tests_write_filled_file() and/or tests_create_file() -++ contains the expected random data */ -++void tests_check_filled_file_fd(int fd); -++ -++/* Check that a file written using tests_fill_file() and/or -++ tests_write_filled_file() and/or tests_create_file() -++ contains the expected random data */ -++void tests_check_filled_file(const char *file_name); -++ -++/* Delete a file */ -++void tests_delete_file(const char *file_name); -++ -++/* Create a file of size file_size */ -++uint64_t tests_create_file(const char *file_name, uint64_t file_size); -++ -++/* Calculate: free_space * numerator / denominator */ -++uint64_t tests_get_big_file_size(unsigned numerator, unsigned denominator); -++ -++/* Create file "fragment_n" where n is the file_number, and unlink it */ -++int tests_create_orphan(unsigned file_number); -++ -++/* Write size bytes at offset to the file "fragment_n" where n is the -++ file_number and file_number also determines the random data written -++ i.e. seed for random numbers */ -++unsigned tests_write_fragment_file(unsigned file_number, -++ int fd, -++ off_t offset, -++ unsigned size); -++ -++/* Write size bytes to the end of file descriptor fd using file_number -++ to determine the random data written i.e. seed for random numbers */ -++unsigned tests_fill_fragment_file(unsigned file_number, -++ int fd, -++ unsigned size); -++ -++/* Write size bytes to the end of file "fragment_n" where n is the file_number -++ and file_number also determines the random data written -++ i.e. seed for random numbers */ -++unsigned tests_append_to_fragment_file(unsigned file_number, -++ unsigned size, -++ int create); -++ -++/* Write size bytes at offset to the file "fragment_n" where n is the -++ file_number and file_number also determines the random data written -++ i.e. seed for random numbers */ -++unsigned tests_overwite_fragment_file( unsigned file_number, -++ off_t offset, -++ unsigned size); -++ -++/* Delete file "fragment_n" where n is the file_number */ -++void tests_delete_fragment_file(unsigned file_number); -++ -++/* Check the random data in file "fragment_n" is what is expected */ -++void tests_check_fragment_file_fd(unsigned file_number, int fd); -++ -++/* Check the random data in file "fragment_n" is what is expected */ -++void tests_check_fragment_file(unsigned file_number); -++ -++/* Central point to decide whether to use fsync */ -++void tests_maybe_sync(int fd); -++ -++/* Return O_SYNC if ok to sync otherwise return 0 */ -++int tests_maybe_sync_flag(void); -++ -++/* Return random number from 0 to n - 1 */ -++size_t tests_random_no(size_t n); -++ -++/* Make a directory empty */ -++void tests_clear_dir(const char *dir_name); -++ -++/* Create an empty sub-directory or small file in the current directory */ -++int64_t tests_create_entry(char *return_name); -++ -++/* Remove a random file of empty sub-directory from the current directory */ -++int64_t tests_remove_entry(void); -++ -++/* Un-mount and re-mount test file system */ -++void tests_remount(void); -++ -++/* Check whether the test file system is also the root file system */ -++int tests_fs_is_rootfs(void); -++ -++/* Try to make a directory empty */ -++void tests_try_to_clear_dir(const char *dir_name); -++ -++/* Check whether the test file system is also the current file system */ -++int tests_fs_is_currfs(void); -++ -++/* Concatenate a pid to a string in a signal safe way */ -++void tests_cat_pid(char *buf, const char *name, pid_t pid); -++ -++extern char *tests_file_system_mount_dir; -++ -++extern char *tests_file_system_type; -++ -++/* General purpose test parameter to specify some aspect of test size. -++ May be used by different tests in different ways. -++ Set by the -z, --size options. */ -++extern int64_t tests_size_parameter; -++ -++/* General purpose test parameter to specify some aspect of test repetition. -++ May be used by different tests in different ways. -++ Set by the -n, --repeat options. */ -++extern int64_t tests_repeat_parameter; -++ -++/* General purpose test parameter to specify some aspect of test sleeping. -++ May be used by different tests in different ways. -++ Set by the -p, --sleep options. */ -++extern int64_t tests_sleep_parameter; -++ -++/* General purpose test parameter to specify a file should be unlinked. -++ May be used by different tests in different ways or not at all. */ -++extern int tests_unlink_flag; -++ -++/* General purpose test parameter to specify a file should be closed. -++ May be used by different tests in different ways or not at all. */ -++extern int tests_close_flag; -++ -++/* General purpose test parameter to specify a file should be deleted. -++ May be used by different tests in different ways or not at all. */ -++extern int tests_delete_flag; -++ -++/* General purpose test parameter to specify a file have a hole. -++ May be used by different tests in different ways or not at all. */ -++extern int tests_hole_flag; -++ -++/* Program name from argv[0] */ -++extern char *program_name; -++ -++#endif -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/run_all.sh linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/run_all.sh -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/run_all.sh 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/run_all.sh 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,49 @@ -++#!/bin/sh -++ -++TEST_DIR=$TEST_FILE_SYSTEM_MOUNT_DIR -++if test -z "$TEST_DIR"; -++then -++ TEST_DIR="/mnt/test_file_system" -++fi -++ -++rm -rf ${TEST_DIR}/* -++ -++./simple/test_1 || exit 1 -++ -++rm -rf ${TEST_DIR}/* -++ -++./simple/test_2 || exit 1 -++ -++rm -rf ${TEST_DIR}/* -++ -++./integrity/integck || exit 1 -++ -++rm -rf ${TEST_DIR}/* -++ -++./stress/atoms/rndrm00 -z0 || exit 1 -++ -++rm -rf ${TEST_DIR}/* -++ -++./stress/atoms/rmdir00 -z0 || exit 1 -++ -++rm -rf ${TEST_DIR}/* -++ -++./stress/atoms/stress_1 -z10000000 -e || exit 1 -++ -++rm -rf ${TEST_DIR}/* -++ -++./stress/atoms/stress_2 -z10000000 || exit 1 -++ -++rm -rf ${TEST_DIR}/* -++ -++./stress/atoms/stress_3 -z1000000000 -e || exit 1 -++ -++rm -rf ${TEST_DIR}/* -++ -++cd stress || exit 1 -++ -++./stress00.sh 3600 || exit 1 -++ -++./stress01.sh 3600 || exit 1 -++ -++cd .. || exit 1 -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/simple/Makefile linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/simple/Makefile -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/simple/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/simple/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,28 @@ -++ -++ifeq ($(origin CC),default) -++CC = gcc -++endif -++ -++CFLAGS := $(CFLAGS) -Wall -g -O2 -I../lib -++ -++LDFLAGS := $(LDFLAGS) -++ -++TARGETS = test_1 \ -++ test_2 \ -++ ftrunc \ -++ orph -++ -++all: $(TARGETS) -++ -++$(TARGETS): ../lib/tests.o -++ -++../lib/tests.o: ../lib/tests.h -++ -++clean: -++ rm -f *.o $(TARGETS) -++ -++tests: all -++ ./test_1 --sync -++ ./test_2 --sync -++ ./ftrunc -++ ./orph --sync -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/simple/ftrunc.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/simple/ftrunc.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/simple/ftrunc.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/simple/ftrunc.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,111 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "tests.h" -++ -++#define WRITE_BUFFER_SIZE 32768 -++ -++void ftrunc(void) -++{ -++ int fd, i; -++ pid_t pid; -++ ssize_t written; -++ int64_t remains; -++ size_t block; -++ char *file_name; -++ off_t actual; -++ char buf[WRITE_BUFFER_SIZE]; -++ -++ file_name = "ftrunc_test_file"; -++ fd = open(file_name, O_CREAT | O_WRONLY, -++ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); -++ CHECK(fd != -1); -++ pid = getpid(); -++ srand(pid); -++ for (i = 0; i < WRITE_BUFFER_SIZE;++i) -++ buf[i] = rand(); -++ remains = tests_size_parameter; -++ actual = 0; -++ while (remains > 0) { -++ if (remains > WRITE_BUFFER_SIZE) -++ block = WRITE_BUFFER_SIZE; -++ else -++ block = remains; -++ written = write(fd, buf, block); -++ if (written <= 0) { -++ CHECK(errno == ENOSPC); /* File system full */ -++ errno = 0; -++ break; -++ } -++ remains -= written; -++ actual += written; -++ } -++ CHECK(ftruncate(fd, (actual ? actual - 1 : actual)) != -1); -++ CHECK(close(fd) != -1); -++ CHECK(unlink(file_name) != -1); -++} -++ -++/* Title of this test */ -++ -++const char *ftrunc_get_title(void) -++{ -++ return "Truncate a large test file"; -++} -++ -++/* Description of this test */ -++ -++const char *ftrunc_get_description(void) -++{ -++ return -++ "Create a file named ftrunc_test_file. " \ -++ "Truncate the file to reduce its length by 1. " \ -++ "Then remove the truncated file. " -++ "The size is given by the -z or --size option, " \ -++ "otherwise it defaults to 1000000."; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int run_test; -++ -++ /* Set default test file size */ -++ tests_size_parameter = 1000000; -++ -++ /* Handle common arguments */ -++ run_test = tests_get_args(argc, argv, ftrunc_get_title(), -++ ftrunc_get_description(), "z"); -++ if (!run_test) -++ return 1; -++ /* Change directory to the file system and check it is ok for testing */ -++ tests_check_test_file_system(); -++ /* Do the actual test */ -++ ftrunc(); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/simple/orph.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/simple/orph.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/simple/orph.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/simple/orph.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,184 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "tests.h" -++ -++#define MAX_ORPHANS 1000000 -++ -++void orph(void) -++{ -++ pid_t pid; -++ unsigned i, j, k, n; -++ int fd, done, full; -++ int64_t repeat; -++ ssize_t sz; -++ char dir_name[256]; -++ int fds[MAX_ORPHANS]; -++ -++ /* Create a directory to test in */ -++ pid = getpid(); -++ tests_cat_pid(dir_name, "orph_test_dir_", pid); -++ if (chdir(dir_name) == -1) -++ CHECK(mkdir(dir_name, 0777) != -1); -++ CHECK(chdir(dir_name) != -1); -++ -++ repeat = tests_repeat_parameter; -++ for (;;) { -++ full = 0; -++ done = 0; -++ n = 0; -++ while (n + 100 < MAX_ORPHANS && !done) { -++ /* Make 100 more orphans */ -++ for (i = 0; i < 100; i++) { -++ fd = tests_create_orphan(n + i); -++ if (fd < 0) { -++ done = 1; -++ if (errno == ENOSPC) -++ full = 1; -++ else if (errno != EMFILE) -++ CHECK(0); -++ errno = 0; -++ break; -++ } -++ fds[n + i] = fd; -++ } -++ if (!full) { -++ /* Write to orphans just created */ -++ k = i; -++ for (i = 0; i < k; i++) { -++ if (tests_write_fragment_file(n + i, -++ fds[n+i], -++ 0, 1000) -++ != 1000) { -++ /* -++ * Out of space, so close -++ * remaining files -++ */ -++ for (j = i; j < k; j++) -++ CHECK(close(fds[n + j]) -++ != -1); -++ done = 1; -++ break; -++ } -++ } -++ } -++ if (!done) -++ CHECK(tests_count_files_in_dir(".") == 0); -++ n += i; -++ } -++ /* Check the data in the files */ -++ for (i = 0; i < n; i++) -++ tests_check_fragment_file_fd(i, fds[i]); -++ if (!full && n) { -++ /* Ensure the file system is full */ -++ n -= 1; -++ do { -++ sz = write(fds[n], fds, 4096); -++ if (sz == -1 && errno == ENOSPC) { -++ errno = 0; -++ break; -++ } -++ CHECK(sz >= 0); -++ } while (sz == 4096); -++ CHECK(close(fds[n]) != -1); -++ } -++ /* Check the data in the files */ -++ for (i = 0; i < n; i++) -++ tests_check_fragment_file_fd(i, fds[i]); -++ /* Sleep */ -++ if (tests_sleep_parameter > 0) { -++ unsigned us = tests_sleep_parameter * 1000; -++ unsigned rand_divisor = RAND_MAX / us; -++ unsigned s = (us / 2) + (rand() / rand_divisor); -++ usleep(s); -++ } -++ /* Close orphans */ -++ for (i = 0; i < n; i++) -++ CHECK(close(fds[i]) != -1); -++ /* Break if repeat count exceeded */ -++ if (tests_repeat_parameter > 0 && --repeat <= 0) -++ break; -++ } -++ CHECK(tests_count_files_in_dir(".") == 0); -++ CHECK(chdir("..") != -1); -++ CHECK(rmdir(dir_name) != -1); -++} -++ -++/* Title of this test */ -++ -++const char *orph_get_title(void) -++{ -++ return "Create many open unlinked files"; -++} -++ -++/* Description of this test */ -++ -++const char *orph_get_description(void) -++{ -++ return -++ "Create a directory named orph_test_dir_pid, where " \ -++ "pid is the process id. Within that directory, " \ -++ "create files and keep them open and unlink them. " \ -++ "Create as many files as possible until the file system is " \ -++ "full or the maximum allowed open files is reached. " \ -++ "If a sleep value is specified, the process sleeps. " \ -++ "The sleep value is given by the -p or --sleep option, " \ -++ "otherwise it defaults to 0. " \ -++ "Sleep is specified in milliseconds. " \ -++ "Then close the files. " \ -++ "If a repeat count is specified, then the task repeats " \ -++ "that number of times. " \ -++ "The repeat count is given by the -n or --repeat option, " \ -++ "otherwise it defaults to 1. " \ -++ "A repeat count of zero repeats forever. " \ -++ "Finally remove the directory."; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int run_test; -++ -++ /* Set default test repetition */ -++ tests_repeat_parameter = 1; -++ -++ /* Set default test sleep */ -++ tests_sleep_parameter = 0; -++ -++ /* Handle common arguments */ -++ run_test = tests_get_args(argc, argv, orph_get_title(), -++ orph_get_description(), "nps"); -++ if (!run_test) -++ return 1; -++ /* Change directory to the file system and check it is ok for testing */ -++ tests_check_test_file_system(); -++ /* Do the actual test */ -++ orph(); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/simple/test_1.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/simple/test_1.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/simple/test_1.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/simple/test_1.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,150 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "tests.h" -++ -++void test_1(void) -++{ -++ int fd; -++ pid_t pid; -++ uint64_t i; -++ uint64_t block; -++ uint64_t actual_size; -++ char name[256]; -++ char old[16]; -++ char buf[16]; -++ off_t old_len; -++ char dir_name[256]; -++ -++ /* Create a directory to test in */ -++ pid = getpid(); -++ tests_cat_pid(dir_name, "test_1_test_dir_", pid); -++ if (chdir(dir_name) == -1) -++ CHECK(mkdir(dir_name, 0777) != -1); -++ CHECK(chdir(dir_name) != -1); -++ /* Create a file that fills half the free space on the file system */ -++ tests_create_file("big_file", tests_get_big_file_size(1,2)); -++ CHECK(tests_count_files_in_dir(".") == 1); -++ fd = open("big_file", O_RDWR | tests_maybe_sync_flag()); -++ CHECK(fd != -1); -++ CHECK(read(fd, old, 5) == 5); -++ CHECK(lseek(fd, 0, SEEK_SET) != (off_t) -1); -++ CHECK(write(fd,"start", 5) == 5); -++ CHECK(lseek(fd,0,SEEK_END) != (off_t) -1); -++ CHECK(write(fd, "end", 3) == 3); -++ tests_maybe_sync(fd); -++ /* Delete the file while it is still open */ -++ tests_delete_file("big_file"); -++ CHECK(tests_count_files_in_dir(".") == 0); -++ /* Create files to file up the file system */ -++ for (block = 1000000, i = 1; ; block /= 10) { -++ while (i != 0) { -++ sprintf(name, "fill_up_%llu", i); -++ actual_size = tests_create_file(name, block); -++ if (actual_size != 0) -++ ++i; -++ if (actual_size != block) -++ break; -++ } -++ if (block == 1) -++ break; -++ } -++ /* Check the big file */ -++ CHECK(lseek(fd, 0, SEEK_SET) != (off_t) -1); -++ CHECK(read(fd, buf, 5) == 5); -++ CHECK(strncmp(buf, "start", 5) == 0); -++ CHECK(lseek(fd, -3, SEEK_END) != (off_t) -1); -++ CHECK(read(fd, buf, 3) == 3); -++ CHECK(strncmp(buf, "end", 3) == 0); -++ /* Check the other files and delete them */ -++ i -= 1; -++ CHECK(tests_count_files_in_dir(".") == i); -++ for (; i > 0; --i) { -++ sprintf(name, "fill_up_%llu", i); -++ tests_check_filled_file(name); -++ tests_delete_file(name); -++ } -++ CHECK(tests_count_files_in_dir(".") == 0); -++ /* Check the big file again */ -++ CHECK(lseek(fd, 0, SEEK_SET) != (off_t) -1); -++ CHECK(read(fd, buf, 5) == 5); -++ CHECK(strncmp(buf, "start", 5) == 0); -++ CHECK(lseek(fd, -3, SEEK_END) != (off_t) -1); -++ CHECK(read(fd, buf, 3) == 3); -++ CHECK(strncmp(buf, "end", 3) == 0); -++ CHECK(lseek(fd, 0, SEEK_SET) != (off_t) -1); -++ CHECK(write(fd,old, 5) == 5); -++ old_len = lseek(fd, -3, SEEK_END); -++ CHECK(old_len != (off_t) -1); -++ CHECK(ftruncate(fd,old_len) != -1); -++ tests_check_filled_file_fd(fd); -++ /* Close the big file*/ -++ CHECK(close(fd) != -1); -++ CHECK(tests_count_files_in_dir(".") == 0); -++ CHECK(chdir("..") != -1); -++ CHECK(rmdir(dir_name) != -1); -++} -++ -++/* Title of this test */ -++ -++const char *test_1_get_title(void) -++{ -++ return "Fill file system while holding deleted big file descriptor"; -++} -++ -++/* Description of this test */ -++ -++const char *test_1_get_description(void) -++{ -++ return -++ "Create a directory named test_1_test_dir_pid, where " \ -++ "pid is the process id. Within that directory, " \ -++ "create a big file (approx. half the file system in size), " \ -++ "open it, and unlink it. " \ -++ "Create many smaller files until the file system is full. " \ -++ "Check the big file is ok. " \ -++ "Delete all the smaller files. " \ -++ "Check the big file again. " \ -++ "Finally delete the big file and directory."; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int run_test; -++ -++ /* Handle common arguments */ -++ run_test = tests_get_args(argc, argv, test_1_get_title(), -++ test_1_get_description(), "s"); -++ if (!run_test) -++ return 1; -++ /* Change directory to the file system and check it is ok for testing */ -++ tests_check_test_file_system(); -++ /* Do the actual test */ -++ test_1(); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/simple/test_2.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/simple/test_2.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/simple/test_2.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/simple/test_2.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,201 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "tests.h" -++ -++void test_2(void) -++{ -++ pid_t pid; -++ int create, full; -++ unsigned i, number_of_files; -++ unsigned growth; -++ unsigned size; -++ uint64_t big_file_size; -++ int fd; -++ off_t offset; -++ char dir_name[256]; -++ -++ /* Create a directory to test in */ -++ pid = getpid(); -++ tests_cat_pid(dir_name, "test_2_test_dir_", pid); -++ if (chdir(dir_name) == -1) -++ CHECK(mkdir(dir_name, 0777) != -1); -++ CHECK(chdir(dir_name) != -1); -++ /* Create up to 1000 files appending 400 bytes at a time to each file */ -++ /* until the file system is full.*/ -++ create = 1; -++ full = 0; -++ number_of_files = 1000; -++ while (!full) { -++ for (i = 0; i < number_of_files; ++i) { -++ growth = tests_append_to_fragment_file(i, 400, create); -++ if (!growth) { -++ full = 1; -++ if (create) -++ number_of_files = i; -++ break; -++ } -++ } -++ create = 0; -++ } -++ /* Check the files */ -++ CHECK(tests_count_files_in_dir(".") == number_of_files); -++ for (i = 0; i < number_of_files; ++i) -++ tests_check_fragment_file(i); -++ /* Delete half of them */ -++ for (i = 1; i < number_of_files; i += 2) -++ tests_delete_fragment_file(i); -++ /* Check them again */ -++ CHECK(tests_count_files_in_dir(".") == (number_of_files + 1) / 2); -++ for (i = 0; i < number_of_files; i += 2) -++ tests_check_fragment_file(i); -++ CHECK(tests_count_files_in_dir(".") == (number_of_files + 1) / 2); -++ /* Create a big file that fills two thirds of the free space */ -++ big_file_size = tests_get_big_file_size(2,3); -++ /* Check the big file */ -++ tests_create_file("big_file", big_file_size); -++ CHECK(tests_count_files_in_dir(".") == 1 + (number_of_files + 1) / 2); -++ tests_check_filled_file("big_file"); -++ /* Open the big file */ -++ fd = open("big_file",O_RDWR | tests_maybe_sync_flag()); -++ CHECK(fd != -1); -++ /* Delete the big file while it is still open */ -++ tests_delete_file("big_file"); -++ /* Check the big file again */ -++ CHECK(tests_count_files_in_dir(".") == (number_of_files + 1) / 2); -++ tests_check_filled_file_fd(fd); -++ -++ /* Write parts of the files and check them */ -++ -++ offset = 100; /* Offset to write at, in the small files */ -++ size = 200; /* Number of bytes to write at the offset */ -++ -++ for (i = 0; i < number_of_files; i += 2) -++ tests_overwite_fragment_file(i, offset, size); -++ /* Rewrite the big file entirely */ -++ tests_write_filled_file(fd, 0, big_file_size); -++ for (i = 0; i < number_of_files; i += 2) -++ tests_check_fragment_file(i); -++ tests_check_filled_file_fd(fd); -++ -++ offset = 300; /* Offset to write at, in the small files */ -++ size = 400; /* Number of bytes to write at the offset */ -++ -++ for (i = 0; i < number_of_files; i += 2) -++ tests_overwite_fragment_file(i, offset, size); -++ /* Rewrite the big file entirely */ -++ tests_write_filled_file(fd, 0, big_file_size); -++ for (i = 0; i < number_of_files; i += 2) -++ tests_check_fragment_file(i); -++ tests_check_filled_file_fd(fd); -++ -++ offset = 110; /* Offset to write at, in the small files */ -++ size = 10; /* Number of bytes to write at the offset */ -++ -++ for (i = 0; i < number_of_files; i += 2) -++ tests_overwite_fragment_file(i, offset, size); -++ /* Rewrite the big file entirely */ -++ tests_write_filled_file(fd, 0, big_file_size); -++ for (i = 0; i < number_of_files; i += 2) -++ tests_check_fragment_file(i); -++ tests_check_filled_file_fd(fd); -++ -++ offset = 10; /* Offset to write at, in the small files */ -++ size = 1000; /* Number of bytes to write at the offset */ -++ -++ for (i = 0; i < number_of_files; i += 2) -++ tests_overwite_fragment_file(i, offset, size); -++ /* Rewrite the big file entirely */ -++ tests_write_filled_file(fd, 0, big_file_size); -++ for (i = 0; i < number_of_files; i += 2) -++ tests_check_fragment_file(i); -++ tests_check_filled_file_fd(fd); -++ -++ offset = 0; /* Offset to write at, in the small files */ -++ size = 100000; /* Number of bytes to write at the offset */ -++ -++ for (i = 0; i < number_of_files; i += 2) -++ tests_overwite_fragment_file(i, offset, size); -++ /* Rewrite the big file entirely */ -++ tests_write_filled_file(fd, 0, big_file_size); -++ for (i = 0; i < number_of_files; i += 2) -++ tests_check_fragment_file(i); -++ tests_check_filled_file_fd(fd); -++ -++ /* Close the big file*/ -++ CHECK(close(fd) != -1); -++ /* Check the small files */ -++ CHECK(tests_count_files_in_dir(".") == (number_of_files + 1) / 2); -++ for (i = 0; i < number_of_files; i += 2) -++ tests_check_fragment_file(i); -++ /* Delete the small files */ -++ for (i = 0; i < number_of_files; i += 2) -++ tests_delete_fragment_file(i); -++ CHECK(tests_count_files_in_dir(".") == 0); -++ CHECK(chdir("..") != -1); -++ CHECK(rmdir(dir_name) != -1); -++} -++ -++/* Title of this test */ -++ -++const char *test_2_get_title(void) -++{ -++ return "Repeated write many small files and one big deleted file"; -++} -++ -++/* Description of this test */ -++ -++const char *test_2_get_description(void) -++{ -++ return -++ "Create a directory named test_2_test_dir_pid, where " \ -++ "pid is the process id. Within that directory, " \ -++ "create about 1000 files. Append 400 bytes to each until " \ -++ "the file system is full. Then delete half of them. Then " \ -++ "create a big file that uses about 2/3 of the remaining free " \ -++ "space. Get a file descriptor for the big file, and delete " \ -++ "the big file. Then repeatedly write to the small files " \ -++ "and the big file. " \ -++ "Finally delete the big file and directory."; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int run_test; -++ -++ /* Handle common arguments */ -++ run_test = tests_get_args(argc, argv, test_2_get_title(), -++ test_2_get_description(), "s"); -++ if (!run_test) -++ return 1; -++ /* Change directory to the file system and check it is ok for testing */ -++ tests_check_test_file_system(); -++ /* Do the actual test */ -++ test_2(); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/Makefile linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/Makefile -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,11 @@ -++ -++SUBDIRS = atoms -++ -++all tests: $(SUBDIRS) -++ -++clean: $(SUBDIRS) -++ rm -rf run_pdf_test_file_* -++ -++.PHONY: $(SUBDIRS) -++$(SUBDIRS): -++ $(MAKE) -C $@ $(MAKECMDGOALS) -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/Makefile linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/Makefile -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,40 @@ -++ -++ifeq ($(origin CC),default) -++CC = gcc -++endif -++ -++CFLAGS := $(CFLAGS) -Wall -g -O2 -I../../lib -++ -++LDFLAGS := $(LDFLAGS) -++ -++TARGETS = stress_1 \ -++ stress_2 \ -++ stress_3 \ -++ pdfrun \ -++ rndwrite00 \ -++ fwrite00 \ -++ rmdir00 \ -++ rndrm00 \ -++ rndrm99 \ -++ gcd_hupper -++ -++all: $(TARGETS) -++ -++$(TARGETS): ../../lib/tests.o -++ -++../lib/tests.o: ../../lib/tests.h -++ -++clean: -++ rm -f *.o $(TARGETS) run_pdf_test_file -++ -++tests: all -++ ./stress_1 -e -++ ./stress_2 -++ ./stress_3 -e -++ ./pdfrun -++ ./rndwrite00 -e -++ ./fwrite00 -++ ./rmdir00 -++ ./rndrm00 -++ ./rndrm99 -++ ./gcd_hupper -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/fwrite00.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/fwrite00.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/fwrite00.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/fwrite00.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,209 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "tests.h" -++ -++#define WRITE_BUFFER_SIZE 32768 -++ -++#define HOLE_BLOCK_SIZE 10000000 -++ -++void filestress00(void) -++{ -++ int fd, i, deleted; -++ pid_t pid; -++ ssize_t written; -++ int64_t remains; -++ int64_t repeat; -++ size_t block; -++ char file_name[256]; -++ char buf[WRITE_BUFFER_SIZE]; -++ -++ fd = -1; -++ deleted = 1; -++ pid = getpid(); -++ tests_cat_pid(file_name, "filestress00_test_file_", pid); -++ srand(pid); -++ repeat = tests_repeat_parameter; -++ for (;;) { -++ /* Open the file */ -++ if (fd == -1) { -++ fd = open(file_name, O_CREAT | O_WRONLY, -++ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); -++ CHECK(fd != -1); -++ deleted = 0; -++ if (tests_unlink_flag) { -++ CHECK(unlink(file_name) != -1); -++ deleted = 1; -++ } -++ } -++ /* Get a different set of random data */ -++ for (i = 0; i < WRITE_BUFFER_SIZE;++i) -++ buf[i] = rand(); -++ if (tests_hole_flag) { -++ /* Make a hole */ -++ CHECK(lseek(fd, tests_size_parameter, SEEK_SET) != -1); -++ written = write(fd, "!", 1); -++ if (written <= 0) { -++ /* File system full */ -++ CHECK(errno == ENOSPC); -++ errno = 0; -++ } -++ CHECK(lseek(fd, 0, SEEK_SET) != -1); -++ /* Write at set points into the hole */ -++ remains = tests_size_parameter; -++ while (remains > HOLE_BLOCK_SIZE) { -++ CHECK(lseek(fd, HOLE_BLOCK_SIZE, -++ SEEK_CUR) != -1); -++ written = write(fd, "!", 1); -++ remains -= HOLE_BLOCK_SIZE; -++ if (written <= 0) { -++ /* File system full */ -++ CHECK(errno == ENOSPC); -++ errno = 0; -++ break; -++ } -++ } -++ } else { -++ /* Write data into the file */ -++ CHECK(lseek(fd, 0, SEEK_SET) != -1); -++ remains = tests_size_parameter; -++ while (remains > 0) { -++ if (remains > WRITE_BUFFER_SIZE) -++ block = WRITE_BUFFER_SIZE; -++ else -++ block = remains; -++ written = write(fd, buf, block); -++ if (written <= 0) { -++ /* File system full */ -++ CHECK(errno == ENOSPC); -++ errno = 0; -++ break; -++ } -++ remains -= written; -++ } -++ } -++ /* Break if repeat count exceeded */ -++ if (tests_repeat_parameter > 0 && --repeat <= 0) -++ break; -++ /* Close if tests_close_flag */ -++ if (tests_close_flag) { -++ CHECK(close(fd) != -1); -++ fd = -1; -++ } -++ /* Sleep */ -++ if (tests_sleep_parameter > 0) { -++ unsigned us = tests_sleep_parameter * 1000; -++ unsigned rand_divisor = RAND_MAX / us; -++ unsigned s = (us / 2) + (rand() / rand_divisor); -++ usleep(s); -++ } -++ /* Delete if tests_delete flag */ -++ if (!deleted && tests_delete_flag) { -++ CHECK(unlink(file_name) != -1); -++ deleted = 1; -++ } -++ } -++ CHECK(close(fd) != -1); -++ /* Sleep */ -++ if (tests_sleep_parameter > 0) { -++ unsigned us = tests_sleep_parameter * 1000; -++ unsigned rand_divisor = RAND_MAX / us; -++ unsigned s = (us / 2) + (rand() / rand_divisor); -++ usleep(s); -++ } -++ /* Tidy up */ -++ if (!deleted) -++ CHECK(unlink(file_name) != -1); -++} -++ -++/* Title of this test */ -++ -++const char *filestress00_get_title(void) -++{ -++ return "File stress test 00"; -++} -++ -++/* Description of this test */ -++ -++const char *filestress00_get_description(void) -++{ -++ return -++ "Create a file named filestress00_test_file_pid, where " \ -++ "pid is the process id. If the unlink option " \ -++ "(-u or --unlink) is specified, " \ -++ "unlink the file while holding the open file descriptor. " \ -++ "If the hole option (-o or --hole) is specified, " \ -++ "write a single character at the end of the file, creating a " \ -++ "hole. " \ -++ "Write a single character in the hole every 10 million " \ -++ "bytes. " \ -++ "If the hole option is not specified, then the file is " \ -++ "filled with random data. " \ -++ "If the close option (-c or --close) is specified the file " \ -++ "is closed. " \ -++ "If a sleep value is specified, the process sleeps. " \ -++ "If the delete option (-e or --delete) is specified, then " \ -++ "the file is deleted. " \ -++ "If a repeat count is specified, then the task repeats " \ -++ "that number of times. " \ -++ "The repeat count is given by the -n or --repeat option, " \ -++ "otherwise it defaults to 1. " \ -++ "A repeat count of zero repeats forever. " \ -++ "The file size is given by the -z or --size option, " \ -++ "otherwise it defaults to 1000000. " \ -++ "The sleep value is given by the -p or --sleep option, " \ -++ "otherwise it defaults to 0. " \ -++ "Sleep is specified in milliseconds."; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int run_test; -++ -++ /* Set default test file size */ -++ tests_size_parameter = 1000000; -++ -++ /* Set default test repetition */ -++ tests_repeat_parameter = 1; -++ -++ /* Set default test sleep */ -++ tests_sleep_parameter = 0; -++ -++ /* Handle common arguments */ -++ run_test = tests_get_args(argc, argv, filestress00_get_title(), -++ filestress00_get_description(), "znpuoce"); -++ if (!run_test) -++ return 1; -++ /* Change directory to the file system and check it is ok for testing */ -++ tests_check_test_file_system(); -++ /* Do the actual test */ -++ filestress00(); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/gcd_hupper.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/gcd_hupper.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/gcd_hupper.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/gcd_hupper.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,259 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "tests.h" -++ -++#define MAX_NAME_SIZE 1024 -++ -++struct gcd_pid -++{ -++ struct gcd_pid *next; -++ int pid; -++ char *name; -++ int mtd_index; -++}; -++ -++struct gcd_pid *gcd_pid_list = NULL; -++ -++int add_gcd_pid(const char *number) -++{ -++ int pid; -++ FILE *f; -++ char file_name[MAX_NAME_SIZE]; -++ char program_name[MAX_NAME_SIZE]; -++ -++ pid = atoi(number); -++ if (pid <= 0) -++ return 0; -++ snprintf(file_name, MAX_NAME_SIZE, "/proc/%s/stat", number); -++ f = fopen(file_name, "r"); -++ if (f == NULL) -++ return 0; -++ if (fscanf(f, "%d %s", &pid, program_name) != 2) { -++ fclose(f); -++ return 0; -++ } -++ if (strncmp(program_name, "(jffs2_gcd_mtd", 14) != 0) -++ pid = 0; -++ if (pid) { -++ size_t sz; -++ struct gcd_pid *g; -++ -++ sz = sizeof(struct gcd_pid); -++ g = (struct gcd_pid *) malloc(sz); -++ g->pid = pid; -++ g->name = (char *) malloc(strlen(program_name) + 1); -++ if (g->name) -++ strcpy(g->name, program_name); -++ else -++ exit(1); -++ g->mtd_index = atoi(program_name + 14); -++ g->next = gcd_pid_list; -++ gcd_pid_list = g; -++ } -++ fclose(f); -++ return pid; -++} -++ -++int get_pid_list(void) -++{ -++ DIR *dir; -++ struct dirent *entry; -++ -++ dir = opendir("/proc"); -++ if (dir == NULL) -++ return 1; -++ for (;;) { -++ entry = readdir(dir); -++ if (entry) { -++ if (strcmp(".",entry->d_name) != 0 && -++ strcmp("..",entry->d_name) != 0) -++ add_gcd_pid(entry->d_name); -++ } else -++ break; -++ } -++ closedir(dir); -++ return 0; -++} -++ -++int parse_index_number(const char *name) -++{ -++ const char *p, *q; -++ int all_zero; -++ int index; -++ -++ p = name; -++ while (*p && !isdigit(*p)) -++ ++p; -++ if (!*p) -++ return -1; -++ all_zero = 1; -++ for (q = p; *q; ++q) { -++ if (!isdigit(*q)) -++ return -1; -++ if (*q != '0') -++ all_zero = 0; -++ } -++ if (all_zero) -++ return 0; -++ index = atoi(p); -++ if (index <= 0) -++ return -1; -++ return index; -++} -++ -++int get_mtd_index(void) -++{ -++ FILE *f; -++ struct mntent *entry; -++ struct stat f_info; -++ struct stat curr_f_info; -++ int found; -++ int mtd_index = -1; -++ -++ if (stat(tests_file_system_mount_dir, &f_info) == -1) -++ return -1; -++ f = fopen("/proc/mounts", "rb"); -++ if (!f) -++ f = fopen("/etc/mtab", "rb"); -++ if (f == NULL) -++ return -1; -++ found = 0; -++ for (;;) { -++ entry = getmntent(f); -++ if (!entry) -++ break; -++ if (stat(entry->mnt_dir, &curr_f_info) == -1) -++ continue; -++ if (f_info.st_dev == curr_f_info.st_dev) { -++ int i; -++ -++ i = parse_index_number(entry->mnt_fsname); -++ if (i != -1) { -++ if (found && i != mtd_index) -++ return -1; -++ found = 1; -++ mtd_index = i; -++ } -++ } -++ } -++ fclose(f); -++ return mtd_index; -++} -++ -++int get_gcd_pid() -++{ -++ struct gcd_pid *g; -++ int mtd_index; -++ -++ if (get_pid_list()) -++ return 0; -++ mtd_index = get_mtd_index(); -++ if (mtd_index == -1) -++ return 0; -++ for (g = gcd_pid_list; g; g = g->next) -++ if (g->mtd_index == mtd_index) -++ return g->pid; -++ return 0; -++} -++ -++void gcd_hupper(void) -++{ -++ int64_t repeat; -++ int pid; -++ -++ pid = get_gcd_pid(); -++ CHECK(pid != 0); -++ repeat = tests_repeat_parameter; -++ for (;;) { -++ CHECK(kill(pid, SIGHUP) != -1); -++ /* Break if repeat count exceeded */ -++ if (tests_repeat_parameter > 0 && --repeat <= 0) -++ break; -++ /* Sleep */ -++ if (tests_sleep_parameter > 0) { -++ unsigned us = tests_sleep_parameter * 1000; -++ unsigned rand_divisor = RAND_MAX / us; -++ unsigned s = (us / 2) + (rand() / rand_divisor); -++ usleep(s); -++ } -++ } -++} -++ -++/* Title of this test */ -++ -++const char *gcd_hupper_get_title(void) -++{ -++ return "Send HUP signals to gcd"; -++} -++ -++/* Description of this test */ -++ -++const char *gcd_hupper_get_description(void) -++{ -++ return -++ "Determine the PID of the gcd process. " \ -++ "Send it SIGHUP (may require root privileges). " \ -++ "If a sleep value is specified, the process sleeps. " \ -++ "If a repeat count is specified, then the task repeats " \ -++ "that number of times. " \ -++ "The repeat count is given by the -n or --repeat option, " \ -++ "otherwise it defaults to 1. " \ -++ "A repeat count of zero repeats forever. " \ -++ "The sleep value is given by the -p or --sleep option, " \ -++ "otherwise it defaults to 1. " -++ "Sleep is specified in milliseconds."; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int run_test; -++ -++ /* Set default test repetition */ -++ tests_repeat_parameter = 1; -++ -++ /* Set default test sleep */ -++ tests_sleep_parameter = 1; -++ -++ /* Handle common arguments */ -++ run_test = tests_get_args(argc, argv, gcd_hupper_get_title(), -++ gcd_hupper_get_description(), "np"); -++ if (!run_test) -++ return 1; -++ /* Change directory to the file system and check it is ok for testing */ -++ tests_check_test_file_system(); -++ /* Do the actual test */ -++ gcd_hupper(); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/pdfrun.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/pdfrun.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/pdfrun.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/pdfrun.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,143 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "tests.h" -++ -++#define WRITE_BUFFER_SIZE 32768 -++ -++void adjust_size(void) -++{ -++ char dummy[1024]; -++ unsigned long total_memory; -++ FILE *f; -++ -++ total_memory = 0; -++ f = fopen("/proc/meminfo", "r"); -++ fscanf(f, "%s %lu", dummy, &total_memory); -++ fclose(f); -++ if (total_memory > 0 && tests_size_parameter > total_memory / 2) -++ tests_size_parameter = total_memory / 2; -++} -++ -++void run_pdf(void) -++{ -++ int fd, i; -++ pid_t pid; -++ int64_t repeat; -++ ssize_t written; -++ int64_t remains; -++ size_t block; -++ char file_name[256]; -++ char buf[WRITE_BUFFER_SIZE]; -++ -++ if (tests_fs_is_currfs()) -++ return; -++ adjust_size(); -++ pid = getpid(); -++ tests_cat_pid(file_name, "run_pdf_test_file_", pid); -++ fd = open(file_name, O_CREAT | O_WRONLY, -++ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); -++ CHECK(fd != -1); -++ pid = getpid(); -++ srand(pid); -++ repeat = tests_repeat_parameter; -++ for (;;) { -++ for (i = 0; i < WRITE_BUFFER_SIZE;++i) -++ buf[i] = rand(); -++ remains = tests_size_parameter; -++ while (remains > 0) { -++ if (remains > WRITE_BUFFER_SIZE) -++ block = WRITE_BUFFER_SIZE; -++ else -++ block = remains; -++ written = write(fd, buf, block); -++ if (written <= 0) { -++ CHECK(errno == ENOSPC); /* File system full */ -++ errno = 0; -++ break; -++ } -++ remains -= written; -++ } -++ /* Break if repeat count exceeded */ -++ if (tests_repeat_parameter > 0 && --repeat <= 0) -++ break; -++ CHECK(lseek(fd, 0, SEEK_SET) == 0); -++ } -++ CHECK(close(fd) != -1); -++ CHECK(unlink(file_name) != -1); -++} -++ -++/* Title of this test */ -++ -++const char *run_pdf_get_title(void) -++{ -++ return "Create / overwrite a large file in the current directory"; -++} -++ -++/* Description of this test */ -++ -++const char *run_pdf_get_description(void) -++{ -++ return -++ "Create a file named run_pdf_test_file_pid, " \ -++ "where pid is the process id. The file is created " \ -++ "in the current directory, " \ -++ "if the current directory is NOT on the test " \ -++ "file system, otherwise no action is taken. " \ -++ "If a repeat count is specified, then the task repeats " \ -++ "that number of times. " \ -++ "The repeat count is given by the -n or --repeat option, " \ -++ "otherwise it defaults to 1. " \ -++ "A repeat count of zero repeats forever. " \ -++ "The size is given by the -z or --size option, " \ -++ "otherwise it defaults to 1000000. " \ -++ "The size is adjusted so that it is not more than " \ -++ "half the size of total memory."; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int run_test; -++ -++ /* Set default test file size */ -++ tests_size_parameter = 1000000; -++ -++ /* Set default test repetition */ -++ tests_repeat_parameter = 1; -++ -++ /* Handle common arguments */ -++ run_test = tests_get_args(argc, argv, run_pdf_get_title(), -++ run_pdf_get_description(), "zn"); -++ if (!run_test) -++ return 1; -++ /* Do the actual test */ -++ run_pdf(); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/rmdir00.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/rmdir00.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/rmdir00.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/rmdir00.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,133 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "tests.h" -++ -++void rmdir00(void) -++{ -++ int64_t repeat; -++ int64_t size, this_size; -++ pid_t pid; -++ char dir_name[256]; -++ -++ /* Create a directory to test in */ -++ pid = getpid(); -++ tests_cat_pid(dir_name, "rmdir00_test_dir_", pid); -++ if (chdir(dir_name) == -1) -++ CHECK(mkdir(dir_name, 0777) != -1); -++ CHECK(chdir(dir_name) != -1); -++ /* Repeat loop */ -++ repeat = tests_repeat_parameter; -++ size = 0; -++ for (;;) { -++ /* Remove everything in the directory */ -++ tests_clear_dir("."); -++ /* Fill with sub-dirs and small files */ -++ do { -++ this_size = tests_create_entry(NULL); -++ if (!this_size) -++ break; -++ size += this_size; -++ } while (this_size && -++ (tests_size_parameter == 0 || -++ size < tests_size_parameter)); -++ /* Break if repeat count exceeded */ -++ if (tests_repeat_parameter > 0 && --repeat <= 0) -++ break; -++ /* Sleep */ -++ if (tests_sleep_parameter > 0) { -++ unsigned us = tests_sleep_parameter * 1000; -++ unsigned rand_divisor = RAND_MAX / us; -++ unsigned s = (us / 2) + (rand() / rand_divisor); -++ usleep(s); -++ } -++ } -++ /* Tidy up by removing everything */ -++ tests_clear_dir("."); -++ CHECK(chdir("..") != -1); -++ CHECK(rmdir(dir_name) != -1); -++} -++ -++/* Title of this test */ -++ -++const char *rmdir00_get_title(void) -++{ -++ return "Create and remove directories and files"; -++} -++ -++/* Description of this test */ -++ -++const char *rmdir00_get_description(void) -++{ -++ return -++ "Create a directory named rmdir00_test_dir_pid, where " \ -++ "pid is the process id. Within that directory, create " \ -++ "a number of sub-directories and small files. " \ -++ "The total size of all sub-directories and files " \ -++ "is specified by the size parameter. " \ -++ "The size parameter is given by the -z or --size option, " \ -++ "otherwise it defaults to 1000000. " \ -++ "A size of zero fills the file system until there is no " -++ "space left. " \ -++ "The task repeats, sleeping in between each iteration, " \ -++ "and then removing the sub-directories and files created " \ -++ "during the last iteration. " \ -++ "The repeat count is set by the -n or --repeat option, " \ -++ "otherwise it defaults to 1. " \ -++ "A repeat count of zero repeats forever. " \ -++ "The sleep value is given by the -p or --sleep option, " \ -++ "otherwise it defaults to 0. " -++ "Sleep is specified in milliseconds."; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int run_test; -++ -++ /* Set default test size */ -++ tests_size_parameter = 1000000; -++ -++ /* Set default test repetition */ -++ tests_repeat_parameter = 1; -++ -++ /* Set default test sleep */ -++ tests_sleep_parameter = 0; -++ -++ /* Handle common arguments */ -++ run_test = tests_get_args(argc, argv, rmdir00_get_title(), -++ rmdir00_get_description(), "znp"); -++ if (!run_test) -++ return 1; -++ /* Change directory to the file system and check it is ok for testing */ -++ tests_check_test_file_system(); -++ /* Do the actual test */ -++ rmdir00(); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/rndrm00.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/rndrm00.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/rndrm00.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/rndrm00.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,157 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "tests.h" -++ -++void rndrm00(void) -++{ -++ int64_t repeat; -++ int64_t size, this_size; -++ pid_t pid; -++ char dir_name[256]; -++ -++ /* Create a directory to test in */ -++ pid = getpid(); -++ tests_cat_pid(dir_name, "rndrm00_test_dir_", pid); -++ if (chdir(dir_name) == -1) -++ CHECK(mkdir(dir_name, 0777) != -1); -++ CHECK(chdir(dir_name) != -1); -++ /* Repeat loop */ -++ repeat = tests_repeat_parameter; -++ size = 0; -++ for (;;) { -++ /* Create and remove sub-dirs and small files, */ -++ /* but tending to grow */ -++ do { -++ if (tests_random_no(3)) { -++ this_size = tests_create_entry(NULL); -++ if (!this_size) -++ break; -++ size += this_size; -++ } else { -++ this_size = tests_remove_entry(); -++ size -= this_size; -++ if (size < 0) -++ size = 0; -++ if (!this_size) -++ this_size = 1; -++ } -++ } while (this_size && -++ (tests_size_parameter == 0 || -++ size < tests_size_parameter)); -++ /* Create and remove sub-dirs and small files, but */ -++ /* but tending to shrink */ -++ do { -++ if (!tests_random_no(3)) { -++ this_size = tests_create_entry(NULL); -++ size += this_size; -++ } else { -++ this_size = tests_remove_entry(); -++ size -= this_size; -++ if (size < 0) -++ size = 0; -++ } -++ } while ((tests_size_parameter != 0 && -++ size > tests_size_parameter / 10) || -++ (tests_size_parameter == 0 && size > 100000)); -++ /* Break if repeat count exceeded */ -++ if (tests_repeat_parameter > 0 && --repeat <= 0) -++ break; -++ /* Sleep */ -++ if (tests_sleep_parameter > 0) { -++ unsigned us = tests_sleep_parameter * 1000; -++ unsigned rand_divisor = RAND_MAX / us; -++ unsigned s = (us / 2) + (rand() / rand_divisor); -++ usleep(s); -++ } -++ } -++ /* Tidy up by removing everything */ -++ tests_clear_dir("."); -++ CHECK(chdir("..") != -1); -++ CHECK(rmdir(dir_name) != -1); -++} -++ -++/* Title of this test */ -++ -++const char *rndrm00_get_title(void) -++{ -++ return "Randomly create and remove directories and files"; -++} -++ -++/* Description of this test */ -++ -++const char *rndrm00_get_description(void) -++{ -++ return -++ "Create a directory named rndrm00_test_dir_pid, where " \ -++ "pid is the process id. Within that directory, " \ -++ "randomly create and remove " \ -++ "a number of sub-directories and small files, " \ -++ "but do more creates than removes. " \ -++ "When the total size of all sub-directories and files " \ -++ "is greater than the size specified by the size parameter, " \ -++ "start to do more removes than creates. " \ -++ "The size parameter is given by the -z or --size option, " \ -++ "otherwise it defaults to 1000000. " \ -++ "A size of zero fills the file system until there is no " -++ "space left. " \ -++ "The task repeats, sleeping in between each iteration. " \ -++ "The repeat count is set by the -n or --repeat option, " \ -++ "otherwise it defaults to 1. " \ -++ "A repeat count of zero repeats forever. " \ -++ "The sleep value is given by the -p or --sleep option, " \ -++ "otherwise it defaults to 0. " -++ "Sleep is specified in milliseconds."; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int run_test; -++ -++ /* Set default test size */ -++ tests_size_parameter = 1000000; -++ -++ /* Set default test repetition */ -++ tests_repeat_parameter = 1; -++ -++ /* Set default test sleep */ -++ tests_sleep_parameter = 0; -++ -++ /* Handle common arguments */ -++ run_test = tests_get_args(argc, argv, rndrm00_get_title(), -++ rndrm00_get_description(), "znp"); -++ if (!run_test) -++ return 1; -++ /* Change directory to the file system and check it is ok for testing */ -++ tests_check_test_file_system(); -++ /* Do the actual test */ -++ rndrm00(); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/rndrm99.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/rndrm99.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/rndrm99.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/rndrm99.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,431 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "tests.h" -++ -++uint32_t files_created = 0; -++uint32_t files_removed = 0; -++uint32_t dirs_created = 0; -++uint32_t dirs_removed = 0; -++int64_t *size_ptr = 0; -++ -++void display_stats(void) -++{ -++ printf( "\nrndrm99 stats:\n" -++ "\tNumber of files created = %u\n" -++ "\tNumber of files deleted = %u\n" -++ "\tNumber of directories created = %u\n" -++ "\tNumber of directories deleted = %u\n" -++ "\tCurrent net size of creates and deletes = %lld\n", -++ (unsigned) files_created, -++ (unsigned) files_removed, -++ (unsigned) dirs_created, -++ (unsigned) dirs_removed, -++ (long long) (size_ptr ? *size_ptr : 0)); -++ fflush(stdout); -++} -++ -++struct timeval tv_before; -++struct timeval tv_after; -++ -++void before(void) -++{ -++ CHECK(gettimeofday(&tv_before, NULL) != -1); -++} -++ -++void after(const char *msg) -++{ -++ time_t diff; -++ CHECK(gettimeofday(&tv_after, NULL) != -1); -++ diff = tv_after.tv_sec - tv_before.tv_sec; -++ if (diff >= 8) { -++ printf("\nrndrm99: the following fn took more than 8 seconds: %s (took %u secs)\n",msg,(unsigned) diff); -++ fflush(stdout); -++ display_stats(); -++ } -++} -++ -++#define WRITE_BUFFER_SIZE 32768 -++ -++static char write_buffer[WRITE_BUFFER_SIZE]; -++ -++static void init_write_buffer() -++{ -++ static int init = 0; -++ -++ if (!init) { -++ int i, d; -++ uint64_t u; -++ -++ u = RAND_MAX; -++ u += 1; -++ u /= 256; -++ d = (int) u; -++ srand(1); -++ for (i = 0; i < WRITE_BUFFER_SIZE; ++i) -++ write_buffer[i] = rand() / d; -++ init = 1; -++ } -++} -++ -++/* Write size random bytes into file descriptor fd at the current position, -++ returning the number of bytes actually written */ -++uint64_t fill_file(int fd, uint64_t size) -++{ -++ ssize_t written; -++ size_t sz; -++ unsigned start = 0, length; -++ uint64_t remains; -++ uint64_t actual_size = 0; -++ -++ init_write_buffer(); -++ remains = size; -++ while (remains > 0) { -++ length = WRITE_BUFFER_SIZE - start; -++ if (remains > length) -++ sz = length; -++ else -++ sz = (size_t) remains; -++ before(); -++ written = write(fd, write_buffer + start, sz); -++ if (written <= 0) { -++ CHECK(errno == ENOSPC); /* File system full */ -++ errno = 0; -++ after("write"); -++ fprintf(stderr,"\nrndrm99: write failed with ENOSPC\n");fflush(stderr); -++ display_stats(); -++ break; -++ } -++ after("write"); -++ remains -= written; -++ actual_size += written; -++ if ((size_t) written == sz) -++ start = 0; -++ else -++ start += written; -++ } -++ return actual_size; -++} -++ -++/* Create a file of size file_size */ -++uint64_t create_file(const char *file_name, uint64_t file_size) -++{ -++ int fd; -++ int flags; -++ mode_t mode; -++ uint64_t actual_size; /* Less than size if the file system is full */ -++ -++ flags = O_CREAT | O_TRUNC | O_WRONLY; -++ mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; -++ before(); -++ fd = open(file_name, flags, mode); -++ if (fd == -1 && errno == ENOSPC) { -++ errno = 0; -++ after("open"); -++ fprintf(stderr,"\nrndrm99: open failed with ENOSPC\n");fflush(stderr); -++ display_stats(); -++ return 0; /* File system full */ -++ } -++ CHECK(fd != -1); -++ after("open"); -++ actual_size = fill_file(fd, file_size); -++ before(); -++ CHECK(close(fd) != -1); -++ after("close"); -++ if (file_size != 0 && actual_size == 0) { -++ printf("\nrndrm99: unlinking zero size file\n");fflush(stdout); -++ before(); -++ CHECK(unlink(file_name) != -1); -++ after("unlink (create_file)"); -++ } -++ return actual_size; -++} -++ -++/* Create an empty sub-directory or small file in the current directory */ -++int64_t create_entry(char *return_name) -++{ -++ int fd; -++ char name[256]; -++ int64_t res; -++ -++ for (;;) { -++ sprintf(name, "%u", (unsigned) tests_random_no(10000000)); -++ before(); -++ fd = open(name, O_RDONLY); -++ after("open (create_entry)"); -++ if (fd == -1) -++ break; -++ before(); -++ close(fd); -++ after("close (create_entry)"); -++ } -++ if (return_name) -++ strcpy(return_name, name); -++ if (tests_random_no(2)) { -++ res = create_file(name, tests_random_no(4096)); -++ if (res > 0) -++ files_created += 1; -++ return res; -++ } else { -++ before(); -++ if (mkdir(name, 0777) == -1) { -++ CHECK(errno == ENOSPC); -++ after("mkdir"); -++ errno = 0; -++ fprintf(stderr,"\nrndrm99: mkdir failed with ENOSPC\n");fflush(stderr); -++ display_stats(); -++ return 0; -++ } -++ after("mkdir"); -++ dirs_created += 1; -++ return TESTS_EMPTY_DIR_SIZE; -++ } -++} -++ -++/* Remove a random file of empty sub-directory from the current directory */ -++int64_t remove_entry(void) -++{ -++ DIR *dir; -++ struct dirent *entry; -++ unsigned count = 0, pos; -++ int64_t result = 0; -++ -++ before(); -++ dir = opendir("."); -++ CHECK(dir != NULL); -++ after("opendir"); -++ for (;;) { -++ errno = 0; -++ before(); -++ entry = readdir(dir); -++ if (entry) { -++ after("readdir 1"); -++ if (strcmp(".",entry->d_name) != 0 && -++ strcmp("..",entry->d_name) != 0) -++ ++count; -++ } else { -++ CHECK(errno == 0); -++ after("readdir 1"); -++ break; -++ } -++ } -++ pos = tests_random_no(count); -++ count = 0; -++ before(); -++ rewinddir(dir); -++ after("rewinddir"); -++ for (;;) { -++ errno = 0; -++ before(); -++ entry = readdir(dir); -++ if (!entry) { -++ CHECK(errno == 0); -++ after("readdir 2"); -++ break; -++ } -++ after("readdir 2"); -++ if (strcmp(".",entry->d_name) != 0 && -++ strcmp("..",entry->d_name) != 0) { -++ if (count == pos) { -++ if (entry->d_type == DT_DIR) { -++ before(); -++ tests_clear_dir(entry->d_name); -++ after("tests_clear_dir"); -++ before(); -++ CHECK(rmdir(entry->d_name) != -1); -++ after("rmdir"); -++ result = TESTS_EMPTY_DIR_SIZE; -++ dirs_removed += 1; -++ } else { -++ struct stat st; -++ before(); -++ CHECK(stat(entry->d_name, &st) != -1); -++ after("stat"); -++ result = st.st_size; -++ before(); -++ CHECK(unlink(entry->d_name) != -1); -++ after("unlink"); -++ files_removed += 1; -++ } -++ } -++ ++count; -++ } -++ } -++ before(); -++ CHECK(closedir(dir) != -1); -++ after("closedir"); -++ return result; -++} -++ -++void rndrm99(void) -++{ -++ int64_t repeat, loop_cnt; -++ int64_t size, this_size; -++ pid_t pid; -++ char dir_name[256]; -++ -++ size_ptr = &size; -++ /* Create a directory to test in */ -++ pid = getpid(); -++ tests_cat_pid(dir_name, "rndrm99_test_dir_", pid); -++ if (chdir(dir_name) == -1) -++ CHECK(mkdir(dir_name, 0777) != -1); -++ CHECK(chdir(dir_name) != -1); -++ /* Repeat loop */ -++ repeat = tests_repeat_parameter; -++ size = 0; -++ for (;;) { -++ /* Create and remove sub-dirs and small files, */ -++ /* but tending to grow */ -++ printf("\nrndrm99: growing\n");fflush(stdout); -++ loop_cnt = 0; -++ do { -++ if (loop_cnt++ % 2000 == 0) -++ display_stats(); -++ if (tests_random_no(3)) { -++ this_size = create_entry(NULL); -++ if (!this_size) -++ break; -++ size += this_size; -++ } else { -++ this_size = remove_entry(); -++ size -= this_size; -++ if (size < 0) -++ size = 0; -++ if (!this_size) -++ this_size = 1; -++ } -++ } while (this_size && -++ (tests_size_parameter == 0 || -++ size < tests_size_parameter)); -++ /* Create and remove sub-dirs and small files, but */ -++ /* but tending to shrink */ -++ printf("\nrndrm99: shrinking\n");fflush(stdout); -++ loop_cnt = 0; -++ do { -++ if (loop_cnt++ % 2000 == 0) -++ display_stats(); -++ if (!tests_random_no(3)) { -++ this_size = create_entry(NULL); -++ size += this_size; -++ } else { -++ this_size = remove_entry(); -++ size -= this_size; -++ if (size < 0) -++ size = 0; -++ } -++ } while ((tests_size_parameter != 0 && -++ size > tests_size_parameter / 10) || -++ (tests_size_parameter == 0 && size > 100000)); -++ /* Break if repeat count exceeded */ -++ if (tests_repeat_parameter > 0 && --repeat <= 0) -++ break; -++ /* Sleep */ -++ if (tests_sleep_parameter > 0) { -++ unsigned us = tests_sleep_parameter * 1000; -++ unsigned rand_divisor = RAND_MAX / us; -++ unsigned s = (us / 2) + (rand() / rand_divisor); -++ printf("\nrndrm99: sleeping\n");fflush(stdout); -++ usleep(s); -++ } -++ } -++ printf("\nrndrm99: tidying\n");fflush(stdout); -++ display_stats(); -++ /* Tidy up by removing everything */ -++ tests_clear_dir("."); -++ CHECK(chdir("..") != -1); -++ CHECK(rmdir(dir_name) != -1); -++ size_ptr = 0; -++} -++ -++/* Title of this test */ -++ -++const char *rndrm99_get_title(void) -++{ -++ return "Randomly create and remove directories and files"; -++} -++ -++/* Description of this test */ -++ -++const char *rndrm99_get_description(void) -++{ -++ return -++ "Create a directory named rndrm99_test_dir_pid, where " \ -++ "pid is the process id. Within that directory, " \ -++ "randomly create and remove " \ -++ "a number of sub-directories and small files, " \ -++ "but do more creates than removes. " \ -++ "When the total size of all sub-directories and files " \ -++ "is greater than the size specified by the size parameter, " \ -++ "start to do more removes than creates. " \ -++ "The size parameter is given by the -z or --size option, " \ -++ "otherwise it defaults to 1000000. " \ -++ "A size of zero fills the file system until there is no " -++ "space left. " \ -++ "The task repeats, sleeping in between each iteration. " \ -++ "The repeat count is set by the -n or --repeat option, " \ -++ "otherwise it defaults to 1. " \ -++ "A repeat count of zero repeats forever. " \ -++ "The sleep value is given by the -p or --sleep option, " \ -++ "otherwise it defaults to 0. " -++ "Sleep is specified in milliseconds."; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int run_test; -++ -++ /* Set default test size */ -++ tests_size_parameter = 1000000; -++ -++ /* Set default test repetition */ -++ tests_repeat_parameter = 1; -++ -++ /* Set default test sleep */ -++ tests_sleep_parameter = 0; -++ -++ /* Handle common arguments */ -++ run_test = tests_get_args(argc, argv, rndrm99_get_title(), -++ rndrm99_get_description(), "znp"); -++ if (!run_test) -++ return 1; -++ /* Change directory to the file system and check it is ok for testing */ -++ tests_check_test_file_system(); -++ /* Do the actual test */ -++ rndrm99(); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/rndwrite00.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/rndwrite00.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/rndwrite00.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/rndwrite00.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,201 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "tests.h" -++ -++#define BLOCK_SIZE 32768 -++#define BUFFER_SIZE 32768 -++ -++static void check_file(int fd, char *data, size_t length) -++{ -++ size_t n, i; -++ char buf[BUFFER_SIZE]; -++ -++ CHECK(lseek(fd, 0, SEEK_SET) != -1); -++ n = 0; -++ for (;;) { -++ i = read(fd, buf, BUFFER_SIZE); -++ CHECK(i >= 0); -++ if (i == 0) -++ break; -++ CHECK(memcmp(buf, data + n, i) == 0); -++ n += i; -++ } -++ CHECK(n == length); -++} -++ -++void rndwrite00(void) -++{ -++ int fd; -++ pid_t pid; -++ ssize_t written; -++ size_t remains; -++ size_t block; -++ size_t actual_size; -++ size_t check_every; -++ char *data, *p, *q; -++ off_t offset; -++ size_t size; -++ int64_t repeat; -++ char file_name[256]; -++ char buf[4096]; -++ -++ /* Create file */ -++ pid = getpid(); -++ tests_cat_pid(file_name, "rndwrite00_test_file_", pid); -++ fd = open(file_name, O_CREAT | O_RDWR | O_TRUNC, -++ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); -++ CHECK(fd != -1); -++ /* Allocate memory to hold file data */ -++ CHECK(tests_size_parameter > 0); -++ CHECK(tests_size_parameter <= SIZE_MAX); -++ data = (char *) malloc(tests_size_parameter); -++ CHECK(data != NULL); -++ /* Fill with random data */ -++ srand(pid); -++ for (p = data, q = data + tests_size_parameter; p != q; ++p) -++ *p = rand(); -++ /* Write to file */ -++ p = data; -++ remains = tests_size_parameter; -++ while (remains > 0) { -++ if (remains > BLOCK_SIZE) -++ block = BLOCK_SIZE; -++ else -++ block = remains; -++ written = write(fd, p, block); -++ if (written <= 0) { -++ CHECK(errno == ENOSPC); /* File system full */ -++ errno = 0; -++ break; -++ } -++ remains -= written; -++ p += written; -++ } -++ actual_size = p - data; -++ /* Repeating bit */ -++ repeat = tests_repeat_parameter; -++ check_every = actual_size / 8192; -++ for (;;) { -++ offset = tests_random_no(actual_size); -++ size = tests_random_no(4096); -++ /* Don't change the file size */ -++ if (offset + size > actual_size) -++ size = actual_size - offset; -++ if (!size) -++ continue; -++ for (p = buf, q = p + size; p != q; ++p) -++ *p = rand(); -++ CHECK(lseek(fd, offset, SEEK_SET) != -1); -++ written = write(fd, buf, size); -++ if (written <= 0) { -++ CHECK(errno == ENOSPC); /* File system full */ -++ errno = 0; -++ } else -++ memcpy(data + offset, buf, written); -++ /* Break if repeat count exceeded */ -++ if (tests_repeat_parameter > 0 && --repeat <= 0) -++ break; -++ if (repeat % check_every == 0) -++ check_file(fd, data, actual_size); -++ /* Sleep */ -++ if (tests_sleep_parameter > 0) { -++ unsigned us = tests_sleep_parameter * 1000; -++ unsigned rand_divisor = RAND_MAX / us; -++ unsigned s = (us / 2) + (rand() / rand_divisor); -++ usleep(s); -++ } -++ } -++ /* Check and close file */ -++ check_file(fd, data, actual_size); -++ CHECK(close(fd) != -1); -++ if (tests_delete_flag) -++ CHECK(unlink(file_name) != -1); -++} -++ -++/* Title of this test */ -++ -++const char *rndwrite00_get_title(void) -++{ -++ return "Randomly write a large test file"; -++} -++ -++/* Description of this test */ -++ -++const char *rndwrite00_get_description(void) -++{ -++ return -++ "Create a file named rndwrite00_test_file_pid, where " \ -++ "pid is the process id. " \ -++ "The file is filled with random data. " \ -++ "The size of the file is given by the -z or --size option, " \ -++ "otherwise it defaults to 1000000. " \ -++ "Then a randomly sized block of random data is written at a " \ -++ "random location in the file. "\ -++ "The block size is always in the range 1 to 4095. " \ -++ "If a sleep value is specified, the process sleeps. " \ -++ "The number of writes is given by the repeat count. " \ -++ "The repeat count is set by the -n or --repeat option, " \ -++ "otherwise it defaults to 10000. " \ -++ "A repeat count of zero repeats forever. " \ -++ "The sleep value is given by the -p or --sleep option, " \ -++ "otherwise it defaults to 0. " -++ "Sleep is specified in milliseconds. " \ -++ "Periodically the data in the file is checked with a copy " \ -++ "held in memory. " \ -++ "If the delete option is specified the file is finally " \ -++ "deleted."; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int run_test; -++ -++ /* Set default test file size */ -++ tests_size_parameter = 1000000; -++ -++ /* Set default test repetition */ -++ tests_repeat_parameter = 10000; -++ -++ /* Set default test sleep */ -++ tests_sleep_parameter = 0; -++ -++ /* Handle common arguments */ -++ run_test = tests_get_args(argc, argv, rndwrite00_get_title(), -++ rndwrite00_get_description(), "zne"); -++ if (!run_test) -++ return 1; -++ /* Change directory to the file system and check it is ok for testing */ -++ tests_check_test_file_system(); -++ /* Do the actual test */ -++ rndwrite00(); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/stress_1.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/stress_1.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/stress_1.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/stress_1.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,109 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "tests.h" -++ -++#define WRITE_BUFFER_SIZE 32768 -++ -++void stress_1(void) -++{ -++ int fd, i; -++ pid_t pid; -++ ssize_t written; -++ int64_t remains; -++ size_t block; -++ char file_name[256]; -++ char buf[WRITE_BUFFER_SIZE]; -++ -++ pid = getpid(); -++ tests_cat_pid(file_name, "stress_1_test_file_", pid); -++ fd = open(file_name, O_CREAT | O_WRONLY, -++ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); -++ CHECK(fd != -1); -++ srand(pid); -++ for (i = 0; i < WRITE_BUFFER_SIZE;++i) -++ buf[i] = rand(); -++ remains = tests_size_parameter; -++ while (remains > 0) { -++ if (remains > WRITE_BUFFER_SIZE) -++ block = WRITE_BUFFER_SIZE; -++ else -++ block = remains; -++ written = write(fd, buf, block); -++ if (written <= 0) { -++ CHECK(errno == ENOSPC); /* File system full */ -++ errno = 0; -++ break; -++ } -++ remains -= written; -++ } -++ CHECK(close(fd) != -1); -++ if (tests_delete_flag) -++ CHECK(unlink(file_name) != -1); -++} -++ -++/* Title of this test */ -++ -++const char *stress_1_get_title(void) -++{ -++ return "Create / overwrite a large file"; -++} -++ -++/* Description of this test */ -++ -++const char *stress_1_get_description(void) -++{ -++ return -++ "Create a file named stress_1_test_file_pid, " \ -++ "where pid is the process id. " \ -++ "The size is given by the -z or --size option, " \ -++ "otherwise it defaults to 1000000. " \ -++ "The file will be deleted if the delete option " \ -++ "is specified. "; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int run_test; -++ -++ /* Set default test file size */ -++ tests_size_parameter = 1000000; -++ -++ /* Handle common arguments */ -++ run_test = tests_get_args(argc, argv, stress_1_get_title(), -++ stress_1_get_description(), "ze"); -++ if (!run_test) -++ return 1; -++ /* Change directory to the file system and check it is ok for testing */ -++ tests_check_test_file_system(); -++ /* Do the actual test */ -++ stress_1(); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/stress_2.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/stress_2.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/stress_2.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/stress_2.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,120 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "tests.h" -++ -++#define WRITE_BUFFER_SIZE 32768 -++ -++void stress_2(void) -++{ -++ int fd, i; -++ pid_t pid; -++ ssize_t written; -++ int64_t remains; -++ int64_t repeat; -++ size_t block; -++ char *file_name; -++ char buf[WRITE_BUFFER_SIZE]; -++ -++ file_name = "stress_2_test_file"; -++ fd = open(file_name, O_CREAT | O_WRONLY, -++ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); -++ CHECK(fd != -1); -++ CHECK(unlink(file_name) != -1); -++ pid = getpid(); -++ srand(pid); -++ repeat = tests_repeat_parameter; -++ for (;;) { -++ for (i = 0; i < WRITE_BUFFER_SIZE;++i) -++ buf[i] = rand(); -++ CHECK(lseek(fd, 0, SEEK_SET) != -1); -++ remains = tests_size_parameter; -++ while (remains > 0) { -++ if (remains > WRITE_BUFFER_SIZE) -++ block = WRITE_BUFFER_SIZE; -++ else -++ block = remains; -++ written = write(fd, buf, block); -++ if (written <= 0) { -++ CHECK(errno == ENOSPC); /* File system full */ -++ errno = 0; -++ break; -++ } -++ remains -= written; -++ } -++ if (tests_repeat_parameter > 0 && --repeat <= 0) -++ break; -++ } -++ CHECK(close(fd) != -1); -++} -++ -++/* Title of this test */ -++ -++const char *stress_2_get_title(void) -++{ -++ return "Create / overwrite a large deleted file"; -++} -++ -++/* Description of this test */ -++ -++const char *stress_2_get_description(void) -++{ -++ return -++ "Create a file named stress_2_test_file. " \ -++ "Open it, delete it while holding the open file descriptor, " \ -++ "then fill it with random data. " \ -++ "Repeated re-write the file some number of times. " \ -++ "The repeat count is given by the -n or --repeat option, " \ -++ "otherwise it defaults to 10. " \ -++ "The file size is given by the -z or --size option, " \ -++ "otherwise it defaults to 1000000."; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int run_test; -++ -++ /* Set default test file size */ -++ tests_size_parameter = 1000000; -++ -++ /* Set default test repetition */ -++ tests_repeat_parameter = 10; -++ -++ /* Handle common arguments */ -++ run_test = tests_get_args(argc, argv, stress_2_get_title(), -++ stress_2_get_description(), "zn"); -++ if (!run_test) -++ return 1; -++ /* Change directory to the file system and check it is ok for testing */ -++ tests_check_test_file_system(); -++ /* Do the actual test */ -++ stress_2(); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/stress_3.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/stress_3.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/stress_3.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/atoms/stress_3.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,122 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "tests.h" -++ -++#define WRITE_BUFFER_SIZE 32768 -++ -++void stress_3(void) -++{ -++ int fd, i; -++ pid_t pid; -++ ssize_t written; -++ int64_t remains; -++ size_t block; -++ char file_name[256]; -++ char buf[WRITE_BUFFER_SIZE]; -++ -++ pid = getpid(); -++ tests_cat_pid(file_name, "stress_3_test_file_", pid); -++ fd = open(file_name, O_CREAT | O_WRONLY, -++ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); -++ CHECK(fd != -1); -++ pid = getpid(); -++ srand(pid); -++ for (i = 0; i < WRITE_BUFFER_SIZE;++i) -++ buf[i] = rand(); -++ CHECK(lseek(fd, tests_size_parameter, SEEK_SET) != -1); -++ CHECK(write(fd, "!", 1) == 1); -++ CHECK(lseek(fd, 0, SEEK_SET) != -1); -++ remains = tests_size_parameter; -++ while (remains > 0) { -++ if (remains > WRITE_BUFFER_SIZE) -++ block = WRITE_BUFFER_SIZE; -++ else -++ block = remains; -++ written = write(fd, buf, block); -++ if (written <= 0) { -++ CHECK(errno == ENOSPC); /* File system full */ -++ errno = 0; -++ break; -++ } -++ remains -= written; -++ } -++ if (ftruncate(fd, 0) == -1) { -++ CHECK(errno == ENOSPC); /* File system full */ -++ errno = 0; -++ } -++ CHECK(close(fd) != -1); -++ if (tests_delete_flag) -++ CHECK(unlink(file_name) != -1); -++} -++ -++/* Title of this test */ -++ -++const char *stress_3_get_title(void) -++{ -++ return "Create a file with a large hole and fill it"; -++} -++ -++/* Description of this test */ -++ -++const char *stress_3_get_description(void) -++{ -++ return -++ "Create a file named stress_3_test_file_pid, " \ -++ "where pid is the process id. " \ -++ "Write a single character past the end of the file, " \ -++ "based on the specified file size, " \ -++ "which creates a hole in the file. " -++ "Fill the hole with random data. " \ -++ "Then truncate the file length to zero. " \ -++ "The size is given by the -z or --size option, " \ -++ "otherwise it defaults to 1000000. " \ -++ "The file will be deleted if the delete option " \ -++ "is specified."; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int run_test; -++ -++ /* Set default test file size */ -++ tests_size_parameter = 1000000; -++ -++ /* Handle common arguments */ -++ run_test = tests_get_args(argc, argv, stress_3_get_title(), -++ stress_3_get_description(), "ze"); -++ if (!run_test) -++ return 1; -++ /* Change directory to the file system and check it is ok for testing */ -++ tests_check_test_file_system(); -++ /* Do the actual test */ -++ stress_3(); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/stress00.sh linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/stress00.sh -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/stress00.sh 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/stress00.sh 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,52 @@ -++#!/bin/sh -++ -++TEST_DIR=$TEST_FILE_SYSTEM_MOUNT_DIR -++if test -z "$TEST_DIR"; -++then -++ TEST_DIR="/mnt/test_file_system" -++fi -++ -++FREESPACE=`../utils/free_space "$TEST_DIR"` -++ -++if test -z "$FREESPACE"; -++then -++ echo "Failed to determine free space" -++ exit 1 -++fi -++ -++if test -n "$1"; -++then -++ DURATION="-d$1"; -++else -++ DURATION=""; -++fi -++ -++FWRITE00=atoms/fwrite00 -++RNDWR=atoms/rndwrite00 -++GCHUP=atoms/gcd_hupper -++PDFLUSH=atoms/pdfrun -++FSIZE=$(( $FREESPACE/15 )); -++ -++../utils/fstest_monitor $DURATION \ -++"$FWRITE00 -z $FSIZE -n0 -p 20" \ -++"$FWRITE00 -z $FSIZE -n0 -p 10 -s" \ -++"$FWRITE00 -z $FSIZE -n0 -p 20 -u" \ -++"$FWRITE00 -z $FSIZE -n0 -p 70 -o" \ -++"$FWRITE00 -z $FSIZE -n0 -p 15 -s -o -u" \ -++"$FWRITE00 -z $FSIZE -n0 -p 10 -u -c" \ -++"$FWRITE00 -z $FSIZE -n0 -p 10 -u -o -c" \ -++"$FWRITE00 -z $FSIZE -n0 -p 10 -o -c" \ -++"$FWRITE00 -z $FSIZE -n0 -p 100 -o -u" \ -++"$FWRITE00 -z $FSIZE -n0 -p 100 -s -o -u -c" \ -++"$FWRITE00 -z $FSIZE -n0 -p 100 -o -u" \ -++"$FWRITE00 -z $FSIZE -n0 -p 100 -u" \ -++"$FWRITE00 -z $FSIZE -n0 -p 100 -s -o" \ -++"$RNDWR -z $FSIZE -n0 -p 10 -e" \ -++"$RNDWR -z $FSIZE -n0 -p 100 -e" \ -++"$PDFLUSH -z 1073741824 -n0" -++ -++STATUS=$? -++ -++rm -rf ${TEST_DIR}/* -++ -++exit $STATUS -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/stress01.sh linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/stress01.sh -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/stress/stress01.sh 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/stress/stress01.sh 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,40 @@ -++#!/bin/sh -++ -++TEST_DIR=$TEST_FILE_SYSTEM_MOUNT_DIR -++if test -z "$TEST_DIR"; -++then -++ TEST_DIR="/mnt/test_file_system" -++fi -++ -++FREESPACE=`../utils/free_space "$TEST_DIR"` -++ -++if test -z "$FREESPACE"; -++then -++ echo "Failed to determine free space" -++ exit 1 -++fi -++ -++if test -n "$1"; -++then -++ DURATION="-d$1"; -++else -++ DURATION=""; -++fi -++ -++FWRITE00=atoms/fwrite00 -++RNDWR=atoms/rndwrite00 -++PDFLUSH=atoms/pdfrun -++FSIZE=$(( $FREESPACE/15 )); -++ -++../utils/fstest_monitor $DURATION \ -++"$FWRITE00 -z $FSIZE -n0 -p 300" \ -++"$FWRITE00 -z $FSIZE -n0 -u" \ -++"$FWRITE00 -z $FSIZE -n0 -u -c" \ -++"$FWRITE00 -z $FSIZE -n0 -s -o" \ -++"$RNDWR -z $FSIZE -n0 -e" -++ -++STATUS=$? -++ -++rm -rf ${TEST_DIR}/* -++ -++exit $STATUS -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/utils/Makefile linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/utils/Makefile -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/utils/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/utils/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,19 @@ -++ -++ifeq ($(origin CC),default) -++CC = gcc -++endif -++ -++CFLAGS := $(CFLAGS) -Wall -g -O2 -I../lib -++ -++LDFLAGS := $(LDFLAGS) -++ -++TARGETS = fstest_monitor free_space -++ -++all: $(TARGETS) -++ -++clean: -++ rm -f *.o $(TARGETS) -++ -++tests: all -++ ./fstest_monitor -++ ./free_space > /dev/null -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/utils/free_space.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/utils/free_space.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/utils/free_space.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/utils/free_space.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,56 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++ -++int main(int argc, char *argv[]) -++{ -++ char *dir_name = "."; -++ uint64_t free_space; -++ struct statvfs fs_info; -++ -++ if (argc > 1) { -++ if (strncmp(argv[1], "--help", 6) == 0 || -++ strncmp(argv[1], "-h", 2) == 0) { -++ printf( "Usage is: " -++ "free_space [directory]\n" -++ "\n" -++ "Display the free space of the file system " -++ "of the directory given\n" -++ "or the current directory if no " -++ "directory is given.\nThe value output is " -++ "in bytes.\n" -++ ); -++ return 1; -++ } -++ dir_name = argv[1]; -++ } -++ if (statvfs(dir_name, &fs_info) == -1) -++ return 1; -++ -++ free_space = (uint64_t) fs_info.f_bavail * (uint64_t) fs_info.f_frsize; -++ -++ printf("%llu\n", (unsigned long long) free_space); -++ -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/utils/fstest_monitor.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/utils/fstest_monitor.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/fs-tests/utils/fstest_monitor.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/fs-tests/utils/fstest_monitor.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,281 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but -++ * WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -++ * 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++struct child_info { -++ struct child_info *next; -++ pid_t pid; -++ int terminated; -++ int killed; -++ int gone; -++}; -++ -++struct child_info *children = 0; -++ -++void kill_children(void) -++{ -++ struct child_info *child; -++ -++ child = children; -++ while (child) { -++ if (!child->gone) { -++ if (!child->terminated) { -++ child->terminated = 1; -++ kill(child->pid, SIGTERM); -++ } /*else if (!child->killed) { -++ child->killed = 1; -++ kill(child->pid, SIGKILL); -++ }*/ -++ } -++ child = child->next; -++ } -++} -++ -++void add_child(pid_t child_pid) -++{ -++ struct child_info *child; -++ size_t sz; -++ -++ sz = sizeof(struct child_info); -++ child = (struct child_info *) malloc(sz); -++ memset(child, 0, sz); -++ child->pid = child_pid; -++ child->next = children; -++ children = child; -++} -++ -++void mark_child_gone(pid_t child_pid) -++{ -++ struct child_info *child; -++ -++ child = children; -++ while (child) { -++ if (child->pid == child_pid) { -++ child->gone = 1; -++ break; -++ } -++ child = child->next; -++ } -++} -++ -++int have_children(void) -++{ -++ struct child_info *child; -++ -++ child = children; -++ while (child) { -++ if (!child->gone) -++ return 1; -++ child = child->next; -++ } -++ return 0; -++} -++ -++int parse_command_line(char *cmdline, int *pargc, char ***pargv) -++{ -++ char **tmp; -++ char *p, *v, *q; -++ size_t sz; -++ int argc = 0; -++ int state = 0; -++ char *argv[1024]; -++ -++ if (!cmdline) -++ return 1; -++ q = v = (char *) malloc(strlen(cmdline) + 1024); -++ if (!v) -++ return 1; -++ p = cmdline; -++ for (;;) { -++ char c = *p++; -++ if (!c) { -++ *v++ = 0; -++ break; -++ } -++ switch (state) { -++ case 0: /* Between args */ -++ if (isspace(c)) -++ break; -++ argv[argc++] = v; -++ if (c == '"') { -++ state = 2; -++ break; -++ } else if (c == '\'') { -++ state = 3; -++ break; -++ } -++ state = 1; -++ case 1: /* Not quoted */ -++ if (c == '\\') { -++ if (*p) -++ *v++ = *p; -++ } else if (isspace(c)) { -++ *v++ = 0; -++ state = 0; -++ } else -++ *v++ = c; -++ break; -++ case 2: /* Double quoted */ -++ if (c == '\\' && *p == '"') { -++ *v++ = '"'; -++ ++p; -++ } else if (c == '"') { -++ *v++ = 0; -++ state = 0; -++ } else -++ *v++ = c; -++ break; -++ case 3: /* Single quoted */ -++ if (c == '\'') { -++ *v++ = 0; -++ state = 0; -++ } else -++ *v++ = c; -++ break; -++ } -++ } -++ argv[argc] = 0; -++ sz = sizeof(char *) * (argc + 1); -++ tmp = (char **) malloc(sz); -++ if (!tmp) { -++ free(q); -++ return 1; -++ } -++ if (argc == 0) -++ free(q); -++ memcpy(tmp, argv, sz); -++ *pargc = argc; -++ *pargv = tmp; -++ return 0; -++} -++ -++void signal_handler(int signum) -++{ -++ kill_children(); -++} -++ -++int result = 0; -++int alarm_gone_off = 0; -++ -++void alarm_handler(int signum) -++{ -++ if (!result) -++ alarm_gone_off = 1; -++ kill_children(); -++} -++ -++int main(int argc, char *argv[], char **env) -++{ -++ int p; -++ pid_t child_pid; -++ int status; -++ int duration = 0; -++ -++ p = 1; -++ if (argc > 1) { -++ if (strncmp(argv[p], "--help", 6) == 0 || -++ strncmp(argv[p], "-h", 2) == 0) { -++ printf( "Usage is: " -++ "fstest_monitor options programs...\n" -++ " Options are:\n" -++ " -h, --help " -++ "This help message\n" -++ " -d, --duration arg " -++ "Stop after arg seconds\n" -++ "\n" -++ "Run programs and wait for them." -++ " If duration is specified,\n" -++ "kill all programs" -++ " after that number of seconds have elapsed.\n" -++ "Example: " -++ "fstest_monitor \"/bin/ls -l\" /bin/date\n" -++ ); -++ return 1; -++ } -++ if (strncmp(argv[p], "--duration", 10) == 0 || -++ strncmp(argv[p], "-d", 2) == 0) { -++ char *s; -++ if (p+1 < argc && !isdigit(argv[p][strlen(argv[p])-1])) -++ ++p; -++ s = argv[p]; -++ while (*s && !isdigit(*s)) -++ ++s; -++ duration = atoi(s); -++ ++p; -++ } -++ } -++ -++ signal(SIGTERM, signal_handler); -++ signal(SIGINT, signal_handler); -++ for (; p < argc; ++p) { -++ child_pid = fork(); -++ if (child_pid) { -++ /* Parent */ -++ if (child_pid == (pid_t) -1) { -++ kill_children(); -++ result = 1; -++ break; -++ } -++ add_child(child_pid); -++ } else { -++ /* Child */ -++ int cargc; -++ char **cargv; -++ -++ if (parse_command_line(argv[p], &cargc, &cargv)) -++ return 1; -++ execve(cargv[0], cargv, env); -++ return 1; -++ } -++ } -++ if (!result && duration > 0) { -++ signal(SIGALRM, alarm_handler); -++ alarm(duration); -++ } -++ while (have_children()) { -++ status = 0; -++ child_pid = wait(&status); -++ if (child_pid == (pid_t) -1) { -++ if (errno == EINTR) -++ continue; -++ kill_children(); -++ return 1; -++ } -++ mark_child_gone(child_pid); -++ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { -++ result = 1; -++ kill_children(); -++ } -++ } -++ -++ if (alarm_gone_off) -++ return 0; -++ -++ return result; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/jittertest/COPYING linux-2.6.24.7/drivers/mtd/mtd-utils/tests/jittertest/COPYING -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/jittertest/COPYING 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/jittertest/COPYING 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,340 @@ -++ GNU GENERAL PUBLIC LICENSE -++ Version 2, June 1991 -++ -++ Copyright (C) 1989, 1991 Free Software Foundation, Inc. -++ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ Everyone is permitted to copy and distribute verbatim copies -++ of this license document, but changing it is not allowed. -++ -++ Preamble -++ -++ The licenses for most software are designed to take away your -++freedom to share and change it. By contrast, the GNU General Public -++License is intended to guarantee your freedom to share and change free -++software--to make sure the software is free for all its users. This -++General Public License applies to most of the Free Software -++Foundation's software and to any other program whose authors commit to -++using it. (Some other Free Software Foundation software is covered by -++the GNU Library General Public License instead.) You can apply it to -++your programs, too. -++ -++ When we speak of free software, we are referring to freedom, not -++price. Our General Public Licenses are designed to make sure that you -++have the freedom to distribute copies of free software (and charge for -++this service if you wish), that you receive source code or can get it -++if you want it, that you can change the software or use pieces of it -++in new free programs; and that you know you can do these things. -++ -++ To protect your rights, we need to make restrictions that forbid -++anyone to deny you these rights or to ask you to surrender the rights. -++These restrictions translate to certain responsibilities for you if you -++distribute copies of the software, or if you modify it. -++ -++ For example, if you distribute copies of such a program, whether -++gratis or for a fee, you must give the recipients all the rights that -++you have. You must make sure that they, too, receive or can get the -++source code. And you must show them these terms so they know their -++rights. -++ -++ We protect your rights with two steps: (1) copyright the software, and -++(2) offer you this license which gives you legal permission to copy, -++distribute and/or modify the software. -++ -++ Also, for each author's protection and ours, we want to make certain -++that everyone understands that there is no warranty for this free -++software. If the software is modified by someone else and passed on, we -++want its recipients to know that what they have is not the original, so -++that any problems introduced by others will not reflect on the original -++authors' reputations. -++ -++ Finally, any free program is threatened constantly by software -++patents. We wish to avoid the danger that redistributors of a free -++program will individually obtain patent licenses, in effect making the -++program proprietary. To prevent this, we have made it clear that any -++patent must be licensed for everyone's free use or not licensed at all. -++ -++ The precise terms and conditions for copying, distribution and -++modification follow. -++ -++ GNU GENERAL PUBLIC LICENSE -++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION -++ -++ 0. This License applies to any program or other work which contains -++a notice placed by the copyright holder saying it may be distributed -++under the terms of this General Public License. The "Program", below, -++refers to any such program or work, and a "work based on the Program" -++means either the Program or any derivative work under copyright law: -++that is to say, a work containing the Program or a portion of it, -++either verbatim or with modifications and/or translated into another -++language. (Hereinafter, translation is included without limitation in -++the term "modification".) Each licensee is addressed as "you". -++ -++Activities other than copying, distribution and modification are not -++covered by this License; they are outside its scope. The act of -++running the Program is not restricted, and the output from the Program -++is covered only if its contents constitute a work based on the -++Program (independent of having been made by running the Program). -++Whether that is true depends on what the Program does. -++ -++ 1. You may copy and distribute verbatim copies of the Program's -++source code as you receive it, in any medium, provided that you -++conspicuously and appropriately publish on each copy an appropriate -++copyright notice and disclaimer of warranty; keep intact all the -++notices that refer to this License and to the absence of any warranty; -++and give any other recipients of the Program a copy of this License -++along with the Program. -++ -++You may charge a fee for the physical act of transferring a copy, and -++you may at your option offer warranty protection in exchange for a fee. -++ -++ 2. You may modify your copy or copies of the Program or any portion -++of it, thus forming a work based on the Program, and copy and -++distribute such modifications or work under the terms of Section 1 -++above, provided that you also meet all of these conditions: -++ -++ a) You must cause the modified files to carry prominent notices -++ stating that you changed the files and the date of any change. -++ -++ b) You must cause any work that you distribute or publish, that in -++ whole or in part contains or is derived from the Program or any -++ part thereof, to be licensed as a whole at no charge to all third -++ parties under the terms of this License. -++ -++ c) If the modified program normally reads commands interactively -++ when run, you must cause it, when started running for such -++ interactive use in the most ordinary way, to print or display an -++ announcement including an appropriate copyright notice and a -++ notice that there is no warranty (or else, saying that you provide -++ a warranty) and that users may redistribute the program under -++ these conditions, and telling the user how to view a copy of this -++ License. (Exception: if the Program itself is interactive but -++ does not normally print such an announcement, your work based on -++ the Program is not required to print an announcement.) -++ -++These requirements apply to the modified work as a whole. If -++identifiable sections of that work are not derived from the Program, -++and can be reasonably considered independent and separate works in -++themselves, then this License, and its terms, do not apply to those -++sections when you distribute them as separate works. But when you -++distribute the same sections as part of a whole which is a work based -++on the Program, the distribution of the whole must be on the terms of -++this License, whose permissions for other licensees extend to the -++entire whole, and thus to each and every part regardless of who wrote it. -++ -++Thus, it is not the intent of this section to claim rights or contest -++your rights to work written entirely by you; rather, the intent is to -++exercise the right to control the distribution of derivative or -++collective works based on the Program. -++ -++In addition, mere aggregation of another work not based on the Program -++with the Program (or with a work based on the Program) on a volume of -++a storage or distribution medium does not bring the other work under -++the scope of this License. -++ -++ 3. You may copy and distribute the Program (or a work based on it, -++under Section 2) in object code or executable form under the terms of -++Sections 1 and 2 above provided that you also do one of the following: -++ -++ a) Accompany it with the complete corresponding machine-readable -++ source code, which must be distributed under the terms of Sections -++ 1 and 2 above on a medium customarily used for software interchange; or, -++ -++ b) Accompany it with a written offer, valid for at least three -++ years, to give any third party, for a charge no more than your -++ cost of physically performing source distribution, a complete -++ machine-readable copy of the corresponding source code, to be -++ distributed under the terms of Sections 1 and 2 above on a medium -++ customarily used for software interchange; or, -++ -++ c) Accompany it with the information you received as to the offer -++ to distribute corresponding source code. (This alternative is -++ allowed only for noncommercial distribution and only if you -++ received the program in object code or executable form with such -++ an offer, in accord with Subsection b above.) -++ -++The source code for a work means the preferred form of the work for -++making modifications to it. For an executable work, complete source -++code means all the source code for all modules it contains, plus any -++associated interface definition files, plus the scripts used to -++control compilation and installation of the executable. However, as a -++special exception, the source code distributed need not include -++anything that is normally distributed (in either source or binary -++form) with the major components (compiler, kernel, and so on) of the -++operating system on which the executable runs, unless that component -++itself accompanies the executable. -++ -++If distribution of executable or object code is made by offering -++access to copy from a designated place, then offering equivalent -++access to copy the source code from the same place counts as -++distribution of the source code, even though third parties are not -++compelled to copy the source along with the object code. -++ -++ 4. You may not copy, modify, sublicense, or distribute the Program -++except as expressly provided under this License. Any attempt -++otherwise to copy, modify, sublicense or distribute the Program is -++void, and will automatically terminate your rights under this License. -++However, parties who have received copies, or rights, from you under -++this License will not have their licenses terminated so long as such -++parties remain in full compliance. -++ -++ 5. You are not required to accept this License, since you have not -++signed it. However, nothing else grants you permission to modify or -++distribute the Program or its derivative works. These actions are -++prohibited by law if you do not accept this License. Therefore, by -++modifying or distributing the Program (or any work based on the -++Program), you indicate your acceptance of this License to do so, and -++all its terms and conditions for copying, distributing or modifying -++the Program or works based on it. -++ -++ 6. Each time you redistribute the Program (or any work based on the -++Program), the recipient automatically receives a license from the -++original licensor to copy, distribute or modify the Program subject to -++these terms and conditions. You may not impose any further -++restrictions on the recipients' exercise of the rights granted herein. -++You are not responsible for enforcing compliance by third parties to -++this License. -++ -++ 7. If, as a consequence of a court judgment or allegation of patent -++infringement or for any other reason (not limited to patent issues), -++conditions are imposed on you (whether by court order, agreement or -++otherwise) that contradict the conditions of this License, they do not -++excuse you from the conditions of this License. If you cannot -++distribute so as to satisfy simultaneously your obligations under this -++License and any other pertinent obligations, then as a consequence you -++may not distribute the Program at all. For example, if a patent -++license would not permit royalty-free redistribution of the Program by -++all those who receive copies directly or indirectly through you, then -++the only way you could satisfy both it and this License would be to -++refrain entirely from distribution of the Program. -++ -++If any portion of this section is held invalid or unenforceable under -++any particular circumstance, the balance of the section is intended to -++apply and the section as a whole is intended to apply in other -++circumstances. -++ -++It is not the purpose of this section to induce you to infringe any -++patents or other property right claims or to contest validity of any -++such claims; this section has the sole purpose of protecting the -++integrity of the free software distribution system, which is -++implemented by public license practices. Many people have made -++generous contributions to the wide range of software distributed -++through that system in reliance on consistent application of that -++system; it is up to the author/donor to decide if he or she is willing -++to distribute software through any other system and a licensee cannot -++impose that choice. -++ -++This section is intended to make thoroughly clear what is believed to -++be a consequence of the rest of this License. -++ -++ 8. If the distribution and/or use of the Program is restricted in -++certain countries either by patents or by copyrighted interfaces, the -++original copyright holder who places the Program under this License -++may add an explicit geographical distribution limitation excluding -++those countries, so that distribution is permitted only in or among -++countries not thus excluded. In such case, this License incorporates -++the limitation as if written in the body of this License. -++ -++ 9. The Free Software Foundation may publish revised and/or new versions -++of the General Public License from time to time. Such new versions will -++be similar in spirit to the present version, but may differ in detail to -++address new problems or concerns. -++ -++Each version is given a distinguishing version number. If the Program -++specifies a version number of this License which applies to it and "any -++later version", you have the option of following the terms and conditions -++either of that version or of any later version published by the Free -++Software Foundation. If the Program does not specify a version number of -++this License, you may choose any version ever published by the Free Software -++Foundation. -++ -++ 10. If you wish to incorporate parts of the Program into other free -++programs whose distribution conditions are different, write to the author -++to ask for permission. For software which is copyrighted by the Free -++Software Foundation, write to the Free Software Foundation; we sometimes -++make exceptions for this. Our decision will be guided by the two goals -++of preserving the free status of all derivatives of our free software and -++of promoting the sharing and reuse of software generally. -++ -++ NO WARRANTY -++ -++ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -++FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -++OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -++PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -++OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -++MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -++TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -++PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -++REPAIR OR CORRECTION. -++ -++ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -++WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -++REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -++INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -++OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -++TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -++YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -++PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -++POSSIBILITY OF SUCH DAMAGES. -++ -++ END OF TERMS AND CONDITIONS -++ -++ How to Apply These Terms to Your New Programs -++ -++ If you develop a new program, and you want it to be of the greatest -++possible use to the public, the best way to achieve this is to make it -++free software which everyone can redistribute and change under these terms. -++ -++ To do so, attach the following notices to the program. It is safest -++to attach them to the start of each source file to most effectively -++convey the exclusion of warranty; and each file should have at least -++the "copyright" line and a pointer to where the full notice is found. -++ -++ -++ Copyright (C) 19yy -++ -++ This program is free software; you can redistribute it and/or modify -++ it under the terms of the GNU General Public License as published by -++ the Free Software Foundation; either version 2 of the License, or -++ (at your option) any later version. -++ -++ This program is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with this program; if not, write to the Free Software -++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ -++ -++Also add information on how to contact you by electronic and paper mail. -++ -++If the program is interactive, make it output a short notice like this -++when it starts in an interactive mode: -++ -++ Gnomovision version 69, Copyright (C) 19yy name of author -++ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. -++ This is free software, and you are welcome to redistribute it -++ under certain conditions; type `show c' for details. -++ -++The hypothetical commands `show w' and `show c' should show the appropriate -++parts of the General Public License. Of course, the commands you use may -++be called something other than `show w' and `show c'; they could even be -++mouse-clicks or menu items--whatever suits your program. -++ -++You should also get your employer (if you work as a programmer) or your -++school, if any, to sign a "copyright disclaimer" for the program, if -++necessary. Here is a sample; alter the names: -++ -++ Yoyodyne, Inc., hereby disclaims all copyright interest in the program -++ `Gnomovision' (which makes passes at compilers) written by James Hacker. -++ -++ , 1 April 1989 -++ Ty Coon, President of Vice -++ -++This General Public License does not permit incorporating your program into -++proprietary programs. If your program is a subroutine library, you may -++consider it more useful to permit linking proprietary applications with the -++library. If this is what you want to do, use the GNU Library General -++Public License instead of this License. -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/jittertest/JitterTest.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/jittertest/JitterTest.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/jittertest/JitterTest.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/jittertest/JitterTest.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1044 @@ -++/*********************************************************************** -++ * -++ * Copyright: Daniel Measurement and Control, Inc. -++ * 9753 Pine Lake Drive -++ * Houston, TX 77055 -++ * -++ * Created by: Vipin Malik and Gail Murray -++ * Released under GPL by permission of Daniel Industries. -++ * -++ * This software is licensed under the GPL version 2. Plese see the file -++ * COPYING for details on the license. -++ * -++ * NO WARRANTY: Absolutely no claims of warranty or fitness of purpose -++ * are made in this software. Please use at your own risk. -++ * -++ * Filename: JitterTest.c -++ * -++ * Description: Program to be used to measure wake jitter. -++ * See README file for more info. -++ * -++ * -++ * Revision History: -++ * $Id: JitterTest.c,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ -++ * $Log: not supported by cvs2svn $ -++ * Revision 1.13 2005/11/07 11:15:20 gleixner -++ * [MTD / JFFS2] Clean up trailing white spaces -++ * -++ * Revision 1.12 2001/08/10 19:23:11 vipin -++ * Ready to be released under GPL! Added proper headers etc. -++ * -++ * Revision 1.11 2001/07/09 15:35:50 vipin -++ * Couple of new features:1. The program runs by default as a "regular" -++ * (SCHED_OTHER) task by default, unless the -p n cmd line parameter is -++ * specified. It then runs as SCHED_RR at that priority. -++ * 2. Added ability to send SIGSTOP/SIGCONT to a specified PID. This -++ * would presumably be the PID of the JFFS2 GC task. SIGSTOP is sent -++ * before writing to the fs, and a SIGCONT after the write is done. -++ * 3. The "pad" data now written to the file on the "fs under test" is -++ * random, not sequential as previously. -++ * -++ * Revision 1.10 2001/06/27 19:14:24 vipin -++ * Now console file to log at can be specified from cmd line. This can enable -++ * you to run two instances of the program- one logging to the /dev/console -++ * and another to a regular file (if you want the data) or /dev/null if you don't. -++ * -++ * Revision 1.9 2001/06/25 20:21:31 vipin -++ * This is the latest version, NOT the one last checked in! -++ * -++ * Revision 1.7 2001/06/18 22:36:19 vipin -++ * Fix minor typo that excluded '\n' from msg on console. -++ * -++ * Revision 1.6 2001/06/18 21:17:50 vipin -++ * Added option to specify the amount of data written to outfile each period. -++ * The regular info is written, but is then padded to the requested size. -++ * This will enable testing of different sized writes to JFFS fs. -++ * -++ * Revision 1.5 2001/06/08 19:36:23 vipin -++ * All write() are now checked for return err code. -++ * -++ * Revision 1.4 2001/06/06 23:10:31 vipin -++ * Added README file. -++ * In JitterTest.c: Changed operation of periodic timer to one shot. The timer is now -++ * reset when the task wakes. This way every "jitter" is from the last time and -++ * jitters from previous times are not accumulated and screw aroud with our display. -++ * -++ * All jitter is now +ve. (as it should be). Also added a "read file" functionality -++ * to test for jitter in task if we have to read from JFFS fs. -++ * The program now also prints data to console- where it can be logged, interspersed with -++ * other "interesting" printk's from the kernel and drivers (flash sector erases etc.) -++ * -++ * Revision 1.3 2001/03/01 19:20:39 gmurray -++ * Add priority scheduling. Shortened name of default output file. -++ * Changed default interrupt period. Output delta time and jitter -++ * instead of time of day. -++ * -++ * Revision 1.2 2001/02/28 16:20:19 vipin -++ * Added version control Id and log fields. -++ * -++ ***********************************************************************/ -++/*************************** Included Files ***************************/ -++#include /* fopen, printf, fprintf, fclose */ -++#include /* strcpy, strcmp */ -++#include /* exit, atol, atoi */ -++#include /* setitimer, settimeofday, gettimeofday */ -++#include /* signal */ -++#include /* sched_setscheduler, sched_get_priority_min,*/ -++/* sched_get_priority_max */ -++#include /* gettimeofday, sleep */ -++#include -++#include -++#include -++#include -++ -++ -++ -++/**************************** Enumerations ****************************/ -++enum timerActions -++ { -++ ONESHOT, -++ AUTORESETTING -++ }; -++ -++ -++ -++/****************************** Constants *****************************/ -++/* Exit error codes */ -++#define EXIT_FILE_OPEN_ERR (1) /* error opening output file*/ -++#define EXIT_REG_SIGALRM_ERR (2) /* error registering SIGALRM*/ -++#define EXIT_REG_SIGINT_ERR (3) /* error registering SIGINT */ -++#define EXIT_INV_INT_PERIOD (4) /* error invalid int. period*/ -++#define EXIT_MIN_PRIORITY_ERR (5) /* error, minimum priority */ -++#define EXIT_MAX_PRIORITY_ERR (6) /* error, maximum priority */ -++#define EXIT_INV_SCHED_PRIORITY (7) /* error, invalid priority */ -++#define EXIT_SET_SCHEDULER_ERR (8) /* error, set scheduler */ -++#define EXIT_PREV_TIME_OF_DAY_ERR (9) /* error, init. prev. */ -++/* time of day */ -++ -++#define MAX_FILE_NAME_LEN (32) /* maximum file name length */ -++ -++#define STRINGS_EQUAL ((int) 0) /* strcmp value if equal */ -++ -++#define MIN_INT_PERIOD_MILLISEC ( 5L) /* minimum interrupt period */ -++#define MAX_INT_PERIOD_MILLISEC (5000L) /* maximum interrupt period */ -++#define DEF_INT_PERIOD_MILLISEC ( 10L) /* default interrupt period */ -++ -++#define READ_FILE_MESSAGE "This is a junk file. Must contain at least 1 byte though!\n" -++ -++/* The user can specify that the program pad out the write file to -++ a given number of bytes. But a minimum number needs to be written. This -++ will contain the jitter info. -++*/ -++#define MIN_WRITE_BYTES 30 -++#define DEFAULT_WRITE_BYTES 30 -++#define MAX_WRITE_BYTES 4096 -++ -++/* used for gen a printable ascii random # between spc and '~' */ -++#define MIN_ASCII 32 /* can be char*/ -++#define MAX_ASCII 126.0 /* needs to be float. See man rand() */ -++ -++/*---------------------------------------------------------------------- -++ * It appears that the preprocessor can't handle multi-line #if -++ * statements. Thus, the check on the default is divided into two -++ * #if statements. -++ *---------------------------------------------------------------------*/ -++#if (DEF_INT_PERIOD_MILLISEC < MIN_INT_PERIOD_MILLISEC) -++#error *** Invalid default interrupt period. *** -++#endif -++ -++#if (DEF_INT_PERIOD_MILLISEC > MAX_INT_PERIOD_MILLISEC) -++#error *** Invalid default interrupt period. *** -++#endif -++ -++ -++#define TRUE 1 /* Boolean true value */ -++#define FALSE 0 -++ -++/* Time conversion constants. */ -++#define MILLISEC_PER_SEC (1000L) /* milliseconds per second */ -++#define MICROSEC_PER_MILLISEC (1000L) /* microsecs per millisec */ -++#define MICROSEC_PER_SEC (1000000L) /* microsecs per second */ -++ -++#define PRIORITY_POLICY ((int) SCHED_RR) /* If specified iwth "-p" */ -++ -++ -++ -++/************************** Module Variables **************************/ -++/* version identifier (value supplied by CVS)*/ -++static const char Version[] = "$Id: JitterTest.c,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $"; -++ -++static char OutFileName[MAX_FILE_NAME_LEN+1]; /* output file name */ -++static char LogFile[MAX_FILE_NAME_LEN+1] = "/dev/console"; /* default */ -++static char ReadFile[MAX_FILE_NAME_LEN+1]; /* This file is read. Should -++ contain at least 1 byte */ -++ -++static int WriteBytes = DEFAULT_WRITE_BYTES; /* pad out file to these many bytes. */ -++static int Fd1; /* fd where the above buffer if o/p */ -++static int Cfd; /* fd to console (or file specified) */ -++static int Fd2; /* fd for the ReadFile */ -++static int DoRead = FALSE; /* should we attempt to ReadFile?*/ -++static long InterruptPeriodMilliSec; /* interrupt period, millisec */ -++static int MinPriority; /* minimum scheduler priority */ -++static int MaxPriority; /* maximum scheduler priority */ -++static int RequestedPriority; /* requested priority */ -++static struct itimerval ITimer; /* interrupt timer structure */ -++static struct timeval PrevTimeVal; /* previous time structure */ -++static struct timeval CurrTimeVal; /* current time structure */ -++static long LastMaxDiff = 0; /* keeps track of worst jitter encountered */ -++ -++static int GrabKProfile = FALSE; /* To help determine system bottle necks -++ this parameter can be set. This causes -++ the /proc/profile file to be read and -++ stored in unique filenames in current -++ dir, and indication to be o/p on the -++ /dev/console also. -++ */ -++static long ProfileTriggerMSecs = 15000l; /* Jitter time in seconds that triggers -++ a snapshot of the profile to be taken -++ -++ */ -++static int SignalGCTask = FALSE; /* should be signal SIGSTOP/SIGCONT to gc task?*/ -++static int GCTaskPID; -++ -++static int RunAsRTTask = FALSE; /* default action unless priority is -++ specified on cmd line */ -++ -++ -++/********************* Local Function Prototypes **********************/ -++void HandleCmdLineArgs(int argc, char *argv[]); -++void SetFileName(char * pFileName); -++void SetInterruptPeriod(char * pASCIIInterruptPeriodMilliSec); -++void SetSchedulerPriority(char * pASCIISchedulerPriority); -++ -++void PrintVersionInfo(void); -++void PrintHelpInfo(void); -++ -++int Write(int fd, void *buf, size_t bytes, int lineNo); -++ -++void InitITimer(struct itimerval * pITimer, int action); -++ -++/* For catching timer interrupts (SIGALRM). */ -++void AlarmHandler(int sigNum); -++ -++/* For catching Ctrl+C SIGINT. */ -++void SignalHandler(int sigNum); -++ -++ -++ -++/*********************************************************************** -++ * main function -++ * return: exit code -++ ***********************************************************************/ -++int main( -++ int argc, -++ char *argv[]) -++{ -++ struct sched_param schedParam; -++ -++ int mypri; -++ char tmpBuf[200]; -++ -++ -++ strcpy(OutFileName,"jitter.dat"); -++ InterruptPeriodMilliSec = MIN_INT_PERIOD_MILLISEC; -++ -++ /* Get the minimum and maximum priorities. */ -++ MinPriority = sched_get_priority_min(PRIORITY_POLICY); -++ MaxPriority = sched_get_priority_max(PRIORITY_POLICY); -++ if (MinPriority == -1) { -++ printf("\n*** Unable to get minimum priority. ***\n"); -++ exit(EXIT_MIN_PRIORITY_ERR); -++ } -++ if (MaxPriority == -1) { -++ printf("\n*** Unable to get maximum priority. ***\n"); -++ exit(EXIT_MAX_PRIORITY_ERR); -++ } -++ -++ /* Set requested priority to minimum value as default. */ -++ RequestedPriority = MinPriority; -++ -++ HandleCmdLineArgs(argc, argv); -++ -++ if(mlockall(MCL_CURRENT|MCL_FUTURE) < 0){ -++ printf("Could not lock task into memory. Bye\n"); -++ perror("Error"); -++ } -++ -++ if(RunAsRTTask){ -++ -++ /* Set the priority. */ -++ schedParam.sched_priority = RequestedPriority; -++ if (sched_setscheduler( -++ 0, -++ PRIORITY_POLICY, -++ &schedParam) != (int) 0) { -++ printf("Exiting: Unsuccessful sched_setscheduler.\n"); -++ close(Fd1); -++ exit(EXIT_SET_SCHEDULER_ERR); -++ } -++ -++ -++ /* Double check as I have some doubts that it's really -++ running at realtime priority! */ -++ if((mypri = sched_getscheduler(0)) != RequestedPriority) -++ { -++ printf("Not running with request priority %i. running with priority %i instead!\n", -++ RequestedPriority, mypri); -++ }else -++ { -++ printf("Running with %i priority. Good!\n", mypri); -++ } -++ -++ } -++ -++ /*------------------------- Initializations --------------------------*/ -++ if((Fd1 = open(OutFileName, O_RDWR|O_CREAT|O_SYNC)) <= 0) -++ { -++ perror("Cannot open outfile for write:"); -++ exit(1); -++ } -++ -++ /* If a request is made to read from a specified file, then create that -++ file and fill with junk data so that there is something there to read. -++ */ -++ if(DoRead) -++ { -++ -++ if((Fd2 = open(ReadFile, O_RDWR|O_CREAT|O_SYNC|O_TRUNC)) <= 0) -++ { -++ perror("cannot open read file:"); -++ exit(1); -++ }else -++ { -++ -++ /* Don't really care how much we write here */ -++ if(write(Fd2, READ_FILE_MESSAGE, strlen(READ_FILE_MESSAGE)) < 0) -++ { -++ perror("Problems writing to readfile:"); -++ exit(1); -++ } -++ lseek(Fd2, 0, SEEK_SET); /* position back to byte #0 */ -++ } -++ } -++ -++ -++ -++ /* Also log output to console. This way we can capture it -++ on a serial console to a log file. -++ */ -++ if((Cfd = open(LogFile, O_WRONLY|O_SYNC)) <= 0) -++ { -++ perror("cannot open o/p logfile:"); -++ exit(1); -++ } -++ -++ -++ /* Set-up handler for periodic interrupt. */ -++ if (signal(SIGALRM, &AlarmHandler) == SIG_ERR) { -++ printf("Couldn't register signal handler for SIGALRM.\n"); -++ sprintf(tmpBuf, -++ "Couldn't register signal handler for SIGALRM.\n"); -++ Write(Fd1, tmpBuf, strlen(tmpBuf), __LINE__); -++ -++ close(Fd1); -++ exit(EXIT_REG_SIGALRM_ERR); -++ } -++ -++ /* Set-up handler for Ctrl+C to exit the program. */ -++ if (signal(SIGINT, &SignalHandler) == SIG_ERR) { -++ printf("Couldn't register signal handler for SIGINT.\n"); -++ sprintf(tmpBuf, -++ "Couldn't register signal handler for SIGINT.\n"); -++ Write(Fd1, tmpBuf, strlen(tmpBuf), __LINE__); -++ -++ close(Fd1); -++ exit(EXIT_REG_SIGINT_ERR); -++ } -++ -++ printf("Press Ctrl+C to exit the program.\n"); -++ printf("Output File: %s\n", OutFileName); -++ printf("Scheduler priority: %d\n", RequestedPriority); -++ sprintf(tmpBuf, "\nScheduler priority: %d\n", -++ RequestedPriority); -++ Write(Fd1, tmpBuf, strlen(tmpBuf), __LINE__); -++ -++ Write(Cfd, tmpBuf, strlen(tmpBuf), __LINE__); -++ -++ printf("Interrupt period: %ld milliseconds\n", -++ InterruptPeriodMilliSec); -++ sprintf(tmpBuf, "Interrupt period: %ld milliseconds\n", -++ InterruptPeriodMilliSec); -++ -++ Write(Fd1, tmpBuf, strlen(tmpBuf), __LINE__); -++ -++ Write(Cfd, tmpBuf, strlen(tmpBuf), __LINE__); -++ -++ -++ fflush(0); -++ -++ -++ -++ /* Initialize the periodic timer. */ -++ InitITimer(&ITimer, ONESHOT); -++ -++ /* Initialize "previous" time. */ -++ if (gettimeofday(&PrevTimeVal, NULL) != (int) 0) { -++ printf("Exiting - "); -++ printf("Unable to initialize previous time of day.\n"); -++ sprintf(tmpBuf, "Exiting - "); -++ Write(Fd1, tmpBuf, strlen(tmpBuf), __LINE__); -++ -++ sprintf(tmpBuf, -++ "Unable to initialize previous time of day.\n"); -++ -++ Write(Fd1, tmpBuf, strlen(tmpBuf), __LINE__); -++ -++ } -++ -++ /* Start the periodic timer. */ -++ setitimer(ITIMER_REAL, &ITimer, NULL); -++ -++ -++ while(TRUE) { /* Intentional infinite loop. */ -++ /* Sleep for one second. */ -++ sleep((unsigned int) 1); -++ } -++ -++ /* Just in case. File should be closed in SignalHandler. */ -++ close(Fd1); -++ close(Cfd); -++ -++ return 0; -++} -++ -++ -++ -++ -++/*********************************************************************** -++ * SignalHandler -++ * This is a handler for the SIGINT signal. It is assumed that the -++ * SIGINT is due to the user pressing Ctrl+C to halt the program. -++ * output: N/A -++ ***********************************************************************/ -++void SignalHandler( -++ int sigNum) -++{ -++ -++ char tmpBuf[200]; -++ -++ /* Note sigNum not used. */ -++ printf("Ctrl+C detected. Worst Jitter time was:%fms.\nJitterTest exiting.\n", -++ (float)LastMaxDiff/1000.0); -++ -++ sprintf(tmpBuf, -++ "\nCtrl+C detected. Worst Jitter time was:%fms\nJitterTest exiting.\n", -++ (float)LastMaxDiff/1000.0); -++ Write(Fd1, tmpBuf, strlen(tmpBuf), __LINE__); -++ -++ Write(Cfd, tmpBuf, strlen(tmpBuf), __LINE__); -++ -++ close(Fd1); -++ close(Cfd); -++ exit(0); -++} -++ -++ -++ -++ -++ -++/* -++ A snapshot of the /proc/profile needs to be taken. -++ This is stored as a new file every time, and the -++ stats reset by doing a (any) write to the /proc/profile -++ file. -++ */ -++void doGrabKProfile(int jitterusec, char *fileName) -++{ -++ int fdSnapshot; -++ int fdProfile; -++ int readBytes; -++ char readBuf[4096]; -++ -++ if((fdSnapshot = open(fileName, O_WRONLY | O_CREAT)) <= 0) -++ { -++ fprintf(stderr, "Could not open file %s.\n", fileName); -++ perror("Error:"); -++ return; -++ } -++ -++ if((fdProfile = open("/proc/profile", O_RDWR)) <= 0) -++ { -++ fprintf(stderr, "Could not open file /proc/profile. Make sure you booted with profile=2\n"); -++ close(fdSnapshot); -++ return; -++ } -++ -++ while((readBytes = read(fdProfile, readBuf, sizeof(readBuf))) > 0) -++ { -++ write(fdSnapshot, readBuf, readBytes); -++ } -++ -++ close(fdSnapshot); -++ -++ if(write(fdProfile, readBuf, 1) != 1) -++ { -++ perror("Could Not clear profile by writing to /proc/profile:"); -++ } -++ -++ close(fdProfile); -++ -++ -++ -++}/* end doGrabKProfile()*/ -++ -++ -++/* -++ Call this routine to clear the kernel profiling buffer /proc/profile -++*/ -++void clearProfileBuf(void){ -++ -++ -++ int fdProfile; -++ char readBuf[10]; -++ -++ -++ if((fdProfile = open("/proc/profile", O_RDWR)) <= 0) -++ { -++ fprintf(stderr, "Could not open file /proc/profile. Make sure you booted with profile=2\n"); -++ return; -++ } -++ -++ -++ if(write(fdProfile, readBuf, 1) != 1) -++ { -++ perror("Could Not clear profile by writing to /proc/profile:"); -++ } -++ -++ close(fdProfile); -++ -++ -++}/* end clearProfileBuf() */ -++ -++ -++ -++ -++ -++/*********************************************************************** -++ * AlarmHandler -++ * This is a handler for the SIGALRM signal (due to the periodic -++ * timer interrupt). It prints the time (seconds) to -++ * the output file. -++ * output: N/A -++ ***********************************************************************/ -++void AlarmHandler( -++ int sigNum) /* signal number (not used) */ -++{ -++ -++ long timeDiffusec; /* diff time in micro seconds */ -++ long intervalusec; -++ -++ -++ char tmpBuf[MAX_WRITE_BYTES]; -++ int cntr; -++ char padChar; -++ -++ static int profileFileNo = 0; -++ char profileFileName[150]; -++ -++ static int seedStarter = 0; /* carries over rand info to next time -++ where time() will be the same as this time -++ if invoked < 1sec apart. -++ */ -++ -++ if (gettimeofday(&CurrTimeVal, NULL) == (int) 0) { -++ -++ /*---------------------------------------------------------------- -++ * Compute the elapsed time between the current and previous -++ * time of day values and store the result. -++ * -++ * Print the elapsed time to the output file. -++ *---------------------------------------------------------------*/ -++ -++ timeDiffusec = (long)(((((long long)CurrTimeVal.tv_sec) * 1000000L) + CurrTimeVal.tv_usec) - -++ (((long long)PrevTimeVal.tv_sec * 1000000L) + PrevTimeVal.tv_usec)); -++ -++ sprintf(tmpBuf," %f ms ", (float)timeDiffusec/1000.0); -++ -++ intervalusec = InterruptPeriodMilliSec * 1000L; -++ -++ timeDiffusec = timeDiffusec - intervalusec; -++ -++ sprintf(&tmpBuf[strlen(tmpBuf)]," %f ms", (float)timeDiffusec/1000.0); -++ -++ -++ /* should we send a SIGSTOP/SIGCONT to the specified PID? */ -++ if(SignalGCTask){ -++ -++ if(kill(GCTaskPID, SIGSTOP) < 0){ -++ -++ perror("error:"); -++ } -++ } -++ -++ -++ /* Store some historical #'s */ -++ if(abs(timeDiffusec) > LastMaxDiff) -++ { -++ LastMaxDiff = abs(timeDiffusec); -++ sprintf(&tmpBuf[strlen(tmpBuf)],"!"); -++ -++ if((GrabKProfile == TRUE) && (ProfileTriggerMSecs < (abs(timeDiffusec)/1000))) -++ { -++ sprintf(profileFileName, "JitterTest.profilesnap-%i", profileFileNo); -++ -++ /* go and grab the kernel performance profile. */ -++ doGrabKProfile(timeDiffusec, profileFileName); -++ profileFileNo++; /* unique name next time */ -++ -++ /* Say so on the console so that a marker gets put in the console log */ -++ sprintf(&tmpBuf[strlen(tmpBuf)],"", -++ profileFileName); -++ -++ } -++ -++ } -++ -++ -++ -++ -++ sprintf(&tmpBuf[strlen(tmpBuf)],"\n"); /* CR for the data going out of the console */ -++ -++ Write(Cfd, tmpBuf, strlen(tmpBuf), __LINE__); -++ -++ -++ /* The "-1" below takes out the '\n' at the end that we appended for the msg printed on -++ the console.*/ -++ sprintf(&tmpBuf[strlen(tmpBuf)-1]," PadBytes:"); -++ -++ /* Now pad the output file if requested by user. */ -++ if(WriteBytes > MIN_WRITE_BYTES) -++ { -++ -++ /* start from a new place every time */ -++ srand(time(NULL) + seedStarter); -++ -++ /* already written MIN_WRITE_BYTES by now */ -++ for(cntr = strlen(tmpBuf); cntr < WriteBytes - 1 ; cntr++) /* "-1" adj for '\n' at end */ -++ { -++ /* don't accept any # < 'SPACE' */ -++ padChar = (char)(MIN_ASCII+(int)((MAX_ASCII-(float)MIN_ASCII)*rand()/(RAND_MAX+1.0))); -++ -++ -++ /* -++ padChar = (cntr % (126-33)) + 33; -++ */ -++ -++ tmpBuf[cntr] = padChar; -++ } -++ -++ seedStarter = tmpBuf[cntr-1]; /* save for next time */ -++ -++ tmpBuf[cntr] = '\n'; /* CR for the data going into the outfile. */ -++ tmpBuf[cntr+1] = '\0'; /* NULL terminate the string */ -++ } -++ -++ /* write out the entire line to the output file. */ -++ Write(Fd1, tmpBuf, strlen(tmpBuf), __LINE__); -++ -++ -++ /* Read a byte from the specified file */ -++ if(DoRead) -++ { -++ -++ read(Fd2, tmpBuf, 1); -++ lseek(Fd2, 0, SEEK_SET); /* back to start */ -++ } -++ -++ -++ /* Start the periodic timer again. */ -++ setitimer(ITIMER_REAL, &ITimer, NULL); -++ -++ -++ /* Update previous time with current time. */ -++ PrevTimeVal.tv_sec = CurrTimeVal.tv_sec; -++ PrevTimeVal.tv_usec = CurrTimeVal.tv_usec; -++ } -++ -++ else { -++ sprintf(tmpBuf, "gettimeofday error \n"); -++ Write(Fd1, tmpBuf, strlen(tmpBuf), __LINE__); -++ -++ printf("gettimeofday error \n"); -++ } -++ -++ /* now clear the profiling buffer */ -++ if(GrabKProfile == TRUE){ -++ -++ clearProfileBuf(); -++ } -++ -++ /* should we send a SIGSTOP/SIGCONT to the specified PID? */ -++ if(SignalGCTask){ -++ -++ if(kill(GCTaskPID, SIGCONT) < 0){ -++ -++ perror("error:"); -++ } -++ } -++ -++ -++ return; -++} -++ -++ -++ -++/*********************************************************************** -++ * InitITimer -++ * This function initializes the 'struct itimerval' structure whose -++ * address is passed to interrupt every InterruptPeriodMilliSec. -++ * output: N/A -++ ***********************************************************************/ -++void InitITimer( -++ struct itimerval * pITimer, /* pointer to interrupt timer struct*/ -++ int action) /* ONESHOT or autosetting? */ -++{ -++ long seconds; /* seconds portion of int. period */ -++ long microSeconds; /* microsec. portion of int. period */ -++ -++ /*-------------------------------------------------------------------- -++ * Divide the desired interrupt period into its seconds and -++ * microseconds components. -++ *-------------------------------------------------------------------*/ -++ if (InterruptPeriodMilliSec < MILLISEC_PER_SEC) { -++ seconds = 0L; -++ microSeconds = InterruptPeriodMilliSec * MICROSEC_PER_MILLISEC; -++ } -++ else { -++ seconds = InterruptPeriodMilliSec / MILLISEC_PER_SEC; -++ microSeconds = -++ (InterruptPeriodMilliSec - (seconds * MILLISEC_PER_SEC)) * -++ MICROSEC_PER_MILLISEC; -++ } -++ -++ /* Initialize the interrupt period structure. */ -++ pITimer->it_value.tv_sec = seconds; -++ pITimer->it_value.tv_usec = microSeconds; -++ -++ if(action == ONESHOT) -++ { -++ /* This will (should) prevent the timer from restarting itself */ -++ pITimer->it_interval.tv_sec = 0; -++ pITimer->it_interval.tv_usec = 0; -++ }else -++ { -++ pITimer->it_interval.tv_sec = seconds; -++ pITimer->it_interval.tv_usec = microSeconds; -++ -++ } -++ -++ return; -++} -++ -++ -++/*********************************************************************** -++ * HandleCmdLineArgs -++ * This function handles the command line arguments. -++ * output: stack size -++ ***********************************************************************/ -++void HandleCmdLineArgs( -++ int argc, /* number of command-line arguments */ -++ char *argv[]) /* ptrs to command-line arguments */ -++{ -++ int argNum; /* argument number */ -++ -++ if (argc > (int) 1) { -++ -++ for (argNum = (int) 1; argNum < argc; argNum++) { -++ -++ /* The command line contains an argument. */ -++ -++ if ((strcmp(argv[argNum],"--version") == STRINGS_EQUAL) || -++ (strcmp(argv[argNum],"-v") == STRINGS_EQUAL)) { -++ /* Print version information and exit. */ -++ PrintVersionInfo(); -++ exit(0); -++ } -++ -++ else if ((strcmp(argv[argNum],"--help") == STRINGS_EQUAL) || -++ (strcmp(argv[argNum],"-h") == STRINGS_EQUAL) || -++ (strcmp(argv[argNum],"-?") == STRINGS_EQUAL)) { -++ /* Print help information and exit. */ -++ PrintHelpInfo(); -++ exit(0); -++ } -++ -++ else if ((strcmp(argv[argNum],"--file") == STRINGS_EQUAL) || -++ (strcmp(argv[argNum],"-f") == STRINGS_EQUAL)) { -++ /* Set the name of the output file. */ -++ ++argNum; -++ if (argNum < argc) { -++ SetFileName(argv[argNum]); -++ } -++ else { -++ printf("*** Output file name not specified. ***\n"); -++ printf("Default output file name will be used.\n"); -++ } -++ } -++ -++ else if ((strcmp(argv[argNum],"--time") == STRINGS_EQUAL) || -++ (strcmp(argv[argNum],"-t") == STRINGS_EQUAL)) { -++ /* Set the interrupt period. */ -++ ++argNum; -++ if (argNum < argc) { -++ SetInterruptPeriod(argv[argNum]); -++ } -++ else { -++ printf("*** Interrupt period not specified. ***\n"); -++ printf("Default interrupt period will be used.\n"); -++ } -++ -++ } -++ -++ else if ((strcmp(argv[argNum],"--priority") == -++ STRINGS_EQUAL) || -++ (strcmp(argv[argNum],"-p") == STRINGS_EQUAL)) { -++ /* Set the scheduler priority. */ -++ ++argNum; -++ if (argNum < argc) { -++ SetSchedulerPriority(argv[argNum]); -++ } -++ else { -++ printf("*** Scheduler priority not specified. ***\n"); -++ printf("Default scheduler priority will be used.\n"); -++ } -++ -++ } -++ -++ else if ((strcmp(argv[argNum],"--readfile") == -++ STRINGS_EQUAL) || -++ (strcmp(argv[argNum],"-r") == STRINGS_EQUAL)) { -++ /* Set the file to read*/ -++ ++argNum; -++ -++ strncpy(ReadFile, argv[argNum], sizeof(ReadFile)); -++ DoRead = TRUE; -++ } -++ -++ else if ((strcmp(argv[argNum],"--write_bytes") == -++ STRINGS_EQUAL) || -++ (strcmp(argv[argNum],"-w") == STRINGS_EQUAL)) { -++ /* Set the file to read*/ -++ ++argNum; -++ -++ WriteBytes = atoi(argv[argNum]); -++ -++ if(WriteBytes < MIN_WRITE_BYTES) -++ { -++ printf("Writing less than %i bytes is not allowed. Bye.\n", -++ MIN_WRITE_BYTES); -++ exit(0); -++ } -++ -++ -++ } -++ -++ else if ((strcmp(argv[argNum],"--consolefile") == -++ STRINGS_EQUAL) || -++ (strcmp(argv[argNum],"-c") == STRINGS_EQUAL)) { -++ /* Set the file to log console log on. */ -++ ++argNum; -++ -++ strncpy(LogFile, argv[argNum], sizeof(LogFile)); -++ } -++ -++ else if ((strcmp(argv[argNum],"--grab_kprofile") == -++ STRINGS_EQUAL)) -++ { -++ /* We will read the /proc/profile file on configurable timeout */ -++ GrabKProfile = TRUE; -++ -++ ++argNum; -++ -++ /* If the jittter is > this #, then the profile is grabbed. */ -++ ProfileTriggerMSecs = (long) atoi(argv[argNum]); -++ -++ if(ProfileTriggerMSecs <= 0){ -++ -++ printf("Illegal value for profile trigger threshold.\n"); -++ exit(0); -++ } -++ } -++ -++ else if ((strcmp(argv[argNum],"--siggc") == -++ STRINGS_EQUAL)) -++ { -++ /* We will SIGSTOP/SIGCONT the specified pid */ -++ SignalGCTask = TRUE; -++ -++ ++argNum; -++ -++ GCTaskPID = atoi(argv[argNum]); -++ -++ if(ProfileTriggerMSecs <= 0){ -++ -++ printf("Illegal value for JFFS(2) GC task pid.\n"); -++ exit(0); -++ } -++ } -++ -++ -++ else { -++ /* Unknown argument. Print help information and exit. */ -++ printf("Invalid option %s\n", argv[argNum]); -++ printf("Try 'JitterTest --help' for more information.\n"); -++ exit(0); -++ } -++ } -++ } -++ -++ return; -++} -++ -++ -++/*********************************************************************** -++ * SetFileName -++ * This function sets the output file name. -++ * output: N/A -++ ***********************************************************************/ -++void SetFileName( -++ char * pFileName) /* ptr to desired output file name */ -++{ -++ size_t fileNameLen; /* file name length (bytes) */ -++ -++ /* Check file name length. */ -++ fileNameLen = strlen(pFileName); -++ if (fileNameLen > (size_t) MAX_FILE_NAME_LEN) { -++ printf("File name %s exceeds maximum length %d.\n", -++ pFileName, MAX_FILE_NAME_LEN); -++ exit(0); -++ } -++ -++ /* File name length is OK so save the file name. */ -++ strcpy(OutFileName, pFileName); -++ -++ return; -++} -++ -++ -++/*********************************************************************** -++ * SetInterruptPeriod -++ * This function sets the interrupt period. -++ * output: N/A -++ ***********************************************************************/ -++void SetInterruptPeriod( -++ char * /* ptr to desired interrupt period */ -++ pASCIIInterruptPeriodMilliSec) -++{ -++ long period; /* interrupt period */ -++ -++ period = atol(pASCIIInterruptPeriodMilliSec); -++ if ((period < MIN_INT_PERIOD_MILLISEC) || -++ (period > MAX_INT_PERIOD_MILLISEC)) { -++ printf("Invalid interrupt period: %ld ms.\n", period); -++ exit(EXIT_INV_INT_PERIOD); -++ } -++ else { -++ InterruptPeriodMilliSec = period; -++ } -++ return; -++} -++ -++ -++/*********************************************************************** -++ * SetSchedulerPriority -++ * This function sets the desired scheduler priority. -++ * output: N/A -++ ***********************************************************************/ -++void SetSchedulerPriority( -++ char * pASCIISchedulerPriority) /* ptr to desired scheduler priority*/ -++{ -++ int priority; /* desired scheduler priority value */ -++ -++ priority = atoi(pASCIISchedulerPriority); -++ if ((priority < MinPriority) || -++ (priority > MaxPriority)) { -++ printf("Scheduler priority %d outside of range [%d, %d]\n", -++ priority, MinPriority, MaxPriority); -++ exit(EXIT_INV_SCHED_PRIORITY); -++ } -++ else { -++ RequestedPriority = priority; -++ RunAsRTTask = TRUE; /* We shall run as a POSIX real time task */ -++ } -++ return; -++} -++ -++ -++/*********************************************************************** -++ * PrintVersionInfo -++ * This function prints version information. -++ * output: N/A -++ ***********************************************************************/ -++void PrintVersionInfo(void) -++{ -++ printf("JitterTest version %s\n", Version); -++ printf("Copyright (c) 2001, Daniel Industries, Inc.\n"); -++ return; -++} -++ -++ -++/*********************************************************************** -++ * PrintHelpInfo -++ * This function prints help information. -++ * output: N/A -++ ***********************************************************************/ -++void PrintHelpInfo(void) -++{ -++ printf("Usage: JitterTest [options]\n"); -++ printf(" *** Requires root privileges. ***\n"); -++ printf("Option:\n"); -++ printf(" [-h, --help, -?] Print this message and exit.\n"); -++ printf(" [-v, --version] "); -++ printf( "Print the version number of JitterTest and exit.\n"); -++ printf(" [-f FILE, --file FILE] Set output file name to FILE. Typically you would put this on the fs under test\n"); -++ printf(" [-c FILE, --consolefile] Set device or file to write the console log to.\n\tTypically you would set this to /dev/console and save it on another computer.\n"); -++ printf(" [-w BYTES, --write_bytes BYTES Write BYTES to FILE each period.\n"); -++ printf(" [-r FILE, --readfile FILE] Also read 1 byte every cycle from FILE. FILE will be created and filled with data.\n"); -++ printf(" [-t , --time ] "); -++ printf( "Set interrupt period to milliseconds.\n"); -++ printf(" "); -++ printf( "Range: [%ld, %ld] milliseconds.\n", -++ MIN_INT_PERIOD_MILLISEC, MAX_INT_PERIOD_MILLISEC); -++ printf(" [-p , --priority ] "); -++ printf( "Set scheduler priority to .\n"); -++ printf(" "); -++ printf( "Range: [%d, %d] (higher number = higher priority)\n", -++ MinPriority, MaxPriority); -++ printf(" [--grab_kprofile ] Read the /proc/profile if jitter is > THRESHOLD and store in file.\n"); -++ printf(" [--siggc ] Before writing to fs send SIGSTOP to PID. After write send SIGCONT\n"); -++ return; -++ -++} -++ -++ -++/* A common write that checks for write errors and exits. Pass it __LINE__ for lineNo */ -++int Write(int fd, void *buf, size_t bytes, int lineNo) -++{ -++ -++ int err; -++ -++ err = write(fd, buf, bytes); -++ -++ if(err < bytes) -++ { -++ -++ printf("Write Error at line %i! Wanted to write %i bytes, but wrote only %i bytes.\n", -++ lineNo, bytes, err); -++ perror("Write did not complete. Error. Bye:"); /* show error from errno. */ -++ exit(1); -++ -++ } -++ -++ return err; -++ -++}/* end Write*/ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/jittertest/Makefile linux-2.6.24.7/drivers/mtd/mtd-utils/tests/jittertest/Makefile -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/jittertest/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/jittertest/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,46 @@ -++CC=gcc -++# uncomment following for performance -++CCFLAGS=-O3 -Wall -m486 -fomit-frame-pointer -++ -++# uncomment following for debugging. Uncomment either this or the one above. Not both. -++# CCFLAGS=-Wall -g -++ -++ -++all: JitterTest plotJittervsFill -++ -++JitterTest: JitterTest.c Makefile -++ gcc $(CCFLAGS) -lm JitterTest.c -o JitterTest -++ -++plotJittervsFill: plotJittervsFill.c Makefile -++ gcc $(CCFLAGS) plotJittervsFill.c -o plotJittervsFill -++ -++clean: -++ rm -rf *~ -++ rm -rf core -++ rm -rf *.o -++ rm -rf JitterTest -++ -++ -++dep: -++ makedepend -I./ *.c -++# DO NOT DELETE -++ -++JitterTest.o: /usr/include/stdio.h /usr/include/features.h -++JitterTest.o: /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h -++JitterTest.o: /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stddef.h -++JitterTest.o: /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stdarg.h -++JitterTest.o: /usr/include/bits/types.h /usr/include/libio.h -++JitterTest.o: /usr/include/_G_config.h /usr/include/bits/stdio_lim.h -++JitterTest.o: /usr/include/string.h /usr/include/stdlib.h -++JitterTest.o: /usr/include/sys/types.h /usr/include/time.h -++JitterTest.o: /usr/include/endian.h /usr/include/bits/endian.h -++JitterTest.o: /usr/include/sys/select.h /usr/include/bits/select.h -++JitterTest.o: /usr/include/bits/sigset.h /usr/include/sys/sysmacros.h -++JitterTest.o: /usr/include/alloca.h /usr/include/sys/time.h -++JitterTest.o: /usr/include/bits/time.h /usr/include/signal.h -++JitterTest.o: /usr/include/bits/signum.h /usr/include/bits/siginfo.h -++JitterTest.o: /usr/include/bits/sigaction.h /usr/include/bits/sigcontext.h -++JitterTest.o: /usr/include/asm/sigcontext.h /usr/include/bits/sigstack.h -++JitterTest.o: /usr/include/sched.h /usr/include/bits/sched.h -++JitterTest.o: /usr/include/unistd.h /usr/include/bits/posix_opt.h -++JitterTest.o: /usr/include/bits/confname.h /usr/include/getopt.h -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/jittertest/README linux-2.6.24.7/drivers/mtd/mtd-utils/tests/jittertest/README -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/jittertest/README 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/jittertest/README 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,197 @@ -++$Id: README,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ -++ -++This is the README file for the JitterTest (and friends) -++program. -++ -++This program is used to measure what the jitter of a -++real time task would be under "standard" Linux. -++ -++More particularly, what is the effect of running -++a real time task under Linux with background -++JFFS file system activity. -++ -++The jitter is measured in milli seconds (ms) from -++the expected time of arrival of a signal from a -++periodic timer (set by the task) to when the -++task actually gets the signal. -++ -++This jitter is then stored in a file specified -++(or the default output file "jitter.dat"). -++ -++The data may also be sent out to the console by -++writing to /dev/console (See help options. This is -++highly desirable specially if you have redirected -++your console to the serial port and are storing it -++as a minicom log on another computer for later analysis -++using some tools provided here). -++ -++This is particularly useful if you have a serial -++console and are outputting "interesting" info -++from inside some kernel task or driver. -++(or something as simple as a "df" program running -++periodically and redirecting o/p to the console). -++ -++One "interesting" thing that I have measured -++is the effect of FLASH chip erases on the jitter -++of a real time task. -++ -++One can do that by putting a printk at the -++beginning of the flash erase routine in the MTD -++flash chip driver. -++ -++Now you will get jitter data interspersed with -++flash sector erase events. Other printk's can also -++be placed at suspected jitter causing locations in -++the system. -++ -++ -++ -++EXECUTING THE PROGRAM "JitterTest" -++ -++You may specify a file to be read by the -++program every time it wakes up (every cycle). -++This file is created and filled with some junk -++data. The purpose of this is to test the jitter -++of the program if it were reading from- say -++a JFFS (Journaling Flash File System) file system. -++ -++By specifying the complete paths of the read and write -++(o/p) files you can test the jitter a POSIX type -++real time task will experience under Linux, under -++various conditions. -++ -++These can be as follows: -++ -++1. O/P file on ram file system, no i/p file. -++ -++ In this case you would presumably generate other -++"typical" background activity for your system and -++examine the worst case jitter experienced by -++a task that is neither reading nor writing to -++a file system. -++ -++Other cases could be: -++ -++2. O/P to ram fs, I/P from JFFS (type) fs: -++ -++ This is specially useful to test the proper -++operation of erase suspend type of operation -++in JFFS file systems (with an MTD layer that -++supports it). -++ -++ In this test you would generate some background -++write/erase type activity that would generate -++chip erases. Since this program is reading from -++the same file system, you contrast the latencies -++with those obtained with writes going to the same -++fs. -++ -++3. Both read and writes to (or just write to) JFFS -++file system: -++ -++ Here you would test for latencies experienced by -++a program if it were writing (and optionally also -++reading) from a JFFS fs. -++ -++ -++ -++ -++Grabing a kernel profile: -++ -++This program can also conditionally grab a kernel profile. -++Specify --grab_kprofile on the cmd line as well as -++a "threshold" parameter (see help options by -?). -++ -++Any jitter greater than this "threshold" will cause the -++program to read the /proc/profile file and dump it in -++a local file with increasing file numbers. It will also -++output the filename at that time to the console file specified. -++This will allow you to corelate later in time the various profiles -++with data in your console file and what was going on at that time. -++ -++These profile files may then be later examined by running them through -++ksymoops. -++ -++Make sure you specify "profile=2" on the kernel command line -++when you boot the kernel if you want to use this functionality. -++ -++ -++ -++Signalling the JFFS[2] GC task: -++ -++You can also force this program to send a SIGSTOP/SIGCONT to the -++JFFS (or JFFS2) gc task by specifing --siggc on the cmd line. -++ -++This will let you investigate the effect of forcing the gc task to -++wake up and do its thing when you are not writing to the fs and to -++force it to sleep when you want to write to the fs. -++ -++These are just various tools to investigate the possibility of -++achieving minimal read/write latency when using JFFS[2]. -++ -++You need to manually do a "ps aux" and look up the PID of the gc -++thread and provide it to the program. -++ -++ -++ -++ -++EXECUTING THE PROGRAM "plotJittervsFill" -++ -++This program is a post processing tool that will extract the jitter -++times as printed by the JitterTest program in its console log file -++as well as the data printed by the "df" command. -++ -++This "df" data happens to be in the console log because you will -++run the shell file fillJffs2.sh on a console when you are doing -++your jitter test. -++ -++This shell script copies a specified file to another specified file -++every programmable seconds. It also does a "df" and redirects output -++to /dev/console where it is mixed with the output from JitterTest. -++ -++All this console data is stored on another computer, as all this data -++is being outputted to the serial port as you have redirected the console -++to the serial port (that is the only guaranteed way to not loose any -++console log or printk data). -++ -++You can then run this saved console log through this program and it -++will output a very nice text file with the %fill in one col and -++corrosponding jitter values in the second. gnuplot then does a -++beautifull plot of this resulting file showing you graphically the -++jitters encountered at different fill % of your JFFS[2] fs. -++ -++ -++ -++OTHER COMMENTS: -++ -++Use the "-w BYTES" cmd line parameter to simulate your test case. -++Not everyone has the same requirements. Someone may want to measure -++the jitter of JFFS2 with 500 bytes being written every 500ms. Others -++may want to measure the system performance writing 2048 bytes every -++5 seconds. -++ -++RUNNING MULTIPLE INSTANCES: -++ -++Things get real interesting when you run multiple instances of this -++program *at the same time*. -++ -++You could have one version running as a real time task (by specifing -++the priority with the -p cmd line parameter), not interacting with -++any fs or at the very least not reading and writing to JFFS[2]. -++ -++At the same time you could have another version running as a regular -++task (by not specifing any priority) but reading and writing to JFFS[2]. -++ -++This way you can easily measure the blocking performance of the real time -++task while another non-real time task interacts with JFFS[2] in the back ground. -++ -++You get the idea. -++ -++ -++WATCH OUT! -++ -++Be particularly careful of running this program as a real time task AND -++writing to JFFS[2]. Any blocks will cause your whole system to block till -++any garbage collect initiated by writes by this task complete. I have measured -++these blocks to be of the order of 40-50 seconds on a reasonably powerful -++32 bit embedded system. -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/jittertest/filljffs2.sh linux-2.6.24.7/drivers/mtd/mtd-utils/tests/jittertest/filljffs2.sh -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/jittertest/filljffs2.sh 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/jittertest/filljffs2.sh 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,16 @@ -++#!/bin/bash -++ -++# Pass following cmd line: -++# 1st - file to copy -++# 2nd - file to copy to -++# 3rd - time to sleep between copies -++ -++while [ $(( 1 )) -gt $(( 0 )) ] -++do -++ cp $1 $2 -++ rm $2 -++ df |grep mtd > /dev/console -++ echo "sleeping $3" -++ sleep $3 -++done -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/jittertest/plotJittervsFill.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/jittertest/plotJittervsFill.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/jittertest/plotJittervsFill.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/jittertest/plotJittervsFill.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,312 @@ -++/* -++ *********************************************************************** -++ * -++ * Copyright: Daniel Measurement and Control, Inc. -++ * 9753 Pine Lake Drive -++ * Houston, TX 77055 -++ * -++ * Created by: Vipin Malik -++ * Released under GPL by permission of Daniel Industries. -++ * -++ * This software is licensed under the GPL version 2. Plese see the file -++ * COPYING for details on the license. -++ * -++ * NO WARRANTY: Absolutely no claims of warranty or fitness of purpose -++ * are made in this software. Please use at your own risk. -++ * -++ File: plotJittervsFill.c -++ By: Vipin Malik -++ -++ About: This program reads in a jitter log file as created -++ by the JitterTest.c program and extracts all the jitters -++ in the file that are greater than a threshold specified -++ as a parameter on the cmd line. It also extracts the -++ amount of disk space at (form the "df" out that should also -++ be present in the log file) after the jitter extracted. -++ -++ It writes the data to the stderr (where you may redirect it). -++ It is suitable for plotting, as the data is written as -++ COL1=UsedSpace COL2=Jitter -++ -++ $Id: plotJittervsFill.c,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ -++ $Log: not supported by cvs2svn $ -++ Revision 1.6 2005/11/07 11:15:21 gleixner -++ [MTD / JFFS2] Clean up trailing white spaces -++ -++ Revision 1.5 2001/08/10 19:23:11 vipin -++ Ready to be released under GPL! Added proper headers etc. -++ -++ Revision 1.4 2001/07/02 22:25:40 vipin -++ Fixed couple of minor cosmetic typos. -++ -++ Revision 1.3 2001/07/02 14:46:46 vipin -++ Added a debug option where it o/p's line numbers to debug funky values. -++ -++ Revision 1.2 2001/06/26 19:48:57 vipin -++ Now prints out jitter values found at end of log file, after which -++ no new "df" disk usage values were encountered. The last "df" disk usage -++ encountered is printed for these orphaned values. -++ -++ Revision 1.1 2001/06/25 19:13:55 vipin -++ Added new file- plotJittervsFill.c- that mines the data log file -++ outputed from the fillFlash.sh script file and JitterTest.c file -++ and produces output suitable to be plotted. -++ This output plot may be examined to see visually the relationship -++ of the Jitter vs disk usage of the fs under test. -++ -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++static char Version_string[] = "$Id: plotJittervsFill.c,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $"; -++static char LogFile[250] = "InputLogFile.log"; -++ -++static int JitterThreshold_ms = 1000; -++static int Debug = 0; /* Debug level. Each "-d" on the cmd line increases the level */ -++ -++#define TRUE 1 -++#define FALSE 0 -++ -++#define MIN_JITTER_THRESHOLD 1 /* ms minimum jitter threshold */ -++ -++void PrintHelpInfo(void) -++{ -++ printf("Usage: plotJittervsFill [options] -f [--file] -t [--jitter_threshold] \n"); -++ printf("[options]:\n-v [--version] Print version and exit\n"); -++ printf("-d Debug. Prints input file line number for each data point picked up.\n"); -++ printf("-h [--help] [-?] Print this help screen and exit.\n"); -++} -++ -++ -++ -++/*********************************************************************** -++ * HandleCmdLineArgs -++ * This function handles the command line arguments. -++ * output: stack size -++ ***********************************************************************/ -++void HandleCmdLineArgs( -++ int argc, /* number of command-line arguments */ -++ char *argv[]) /* ptrs to command-line arguments */ -++{ -++ int argNum; /* argument number */ -++ -++ if (argc > (int) 1) { -++ -++ for (argNum = (int) 1; argNum < argc; argNum++) { -++ -++ /* The command line contains an argument. */ -++ -++ if ((strcmp(argv[argNum],"--version") == 0) || -++ (strcmp(argv[argNum],"-v") == 0)) { -++ /* Print version information and exit. */ -++ printf("%s\n", Version_string); -++ exit(0); -++ } -++ -++ else if ((strcmp(argv[argNum],"--help") == 0) || -++ (strcmp(argv[argNum],"-h") == 0) || -++ (strcmp(argv[argNum],"-?") == 0)) { -++ /* Print help information and exit. */ -++ PrintHelpInfo(); -++ exit(0); -++ } -++ -++ else if ((strcmp(argv[argNum],"--file") == 0) || -++ (strcmp(argv[argNum],"-f") == 0)) { -++ /* Set the name of the output file. */ -++ ++argNum; -++ if (argNum < argc) { -++ strncpy(LogFile, argv[argNum], sizeof(LogFile)); -++ } -++ else { -++ printf("*** Input file name not specified. ***\n"); -++ exit(0); -++ } -++ } -++ -++ else if ((strcmp(argv[argNum],"--jitter_threshold") == 0) || -++ (strcmp(argv[argNum],"-t") == 0)) { -++ /* Set the file to read*/ -++ ++argNum; -++ -++ JitterThreshold_ms = atoi(argv[argNum]); -++ -++ if(JitterThreshold_ms < MIN_JITTER_THRESHOLD) -++ { -++ printf("A jitter threshold less than %i ms is not allowed. Bye.\n", -++ MIN_JITTER_THRESHOLD); -++ exit(0); -++ } -++ } -++ -++ else if ((strcmp(argv[argNum],"-d") == 0)) -++ { -++ /* Increment debug level */ -++ -++ Debug++; -++ } -++ -++ else { -++ /* Unknown argument. Print help information and exit. */ -++ printf("Invalid option %s\n", argv[argNum]); -++ printf("Try 'plotJittervsFill --help' for more information.\n"); -++ exit(0); -++ } -++ } -++ } -++ -++ return; -++} -++ -++ -++ -++ -++ -++int main( -++ int argc, -++ char *argv[]) -++{ -++ -++ char lineBuf[1024]; /* how long a single line be? */ -++ int converted; -++ int lineNo = 0; -++ int cnt; -++ -++ FILE *fp; -++ -++ int junkInt1, junkInt2, junkInt3; -++ float junkFloat1; -++ float jitter_ms; -++ -++#define MAX_SAVE_BUFFER 1000 /* How many values will be picked up while searching for -++ a % disk full line (i.e. before they can be printed out) -++ */ -++ int saveJitter[MAX_SAVE_BUFFER]; /* lets us record multiple jitter values that exceed -++ our threshold till we find a "df" field- which is when -++ we can o/p all these values. -++ */ -++ int dataLineNo[MAX_SAVE_BUFFER]; /* The saved line #'s for the above. Printed if debug specified. */ -++ -++ int saveJitterCnt = 0; -++ int lookFor_df = FALSE; -++ int dfPercent = -1; /* will be >= 0 if at least one found. The init value is a flag. */ -++ -++ char junkStr1[500], junkStr2[500]; -++ -++ HandleCmdLineArgs(argc, argv); -++ -++ if((fp = fopen(LogFile, "r")) == NULL) -++ { -++ printf("Unable to open input log file %s for read.\b", LogFile); -++ perror("Error:"); -++ exit(1); -++ } -++ -++ -++ -++ while(fgets(lineBuf, sizeof(lineBuf), fp) != NULL) -++ { -++ lineNo++; -++ -++ -++ /* Are we looking for a "df" o/p line? (to see how full -++ the flash is?)*/ -++ -++ /* is there a "%" in this line? */ -++ if((strstr(lineBuf, "%") != NULL) && (lookFor_df)) -++ { -++ converted = sscanf(lineBuf, "%s %i %i %i %i\n", -++ junkStr1, &junkInt1, &junkInt2, &junkInt3, &dfPercent); -++ if(converted < 5) -++ { -++ printf("Line %i contains \"%%\", but expected fileds not found. Skipping.\n", lineNo); -++ }else -++ { -++ /* Now print out the saved jitter values (in col2) with this dfPercent value as the col1. */ -++ for(cnt = 0; cnt < saveJitterCnt; cnt++) -++ { -++ if(Debug) -++ { -++ fprintf(stderr, "%i\t%i\t%i\n", (int)dataLineNo[cnt], -++ dfPercent, (int)saveJitter[cnt]); -++ }else -++ { -++ fprintf(stderr, "%i\t%i\n", dfPercent, (int)saveJitter[cnt]); -++ } -++ -++ -++ } -++ -++ saveJitterCnt = 0; /* all flushed. Reset for next saves. */ -++ lookFor_df = FALSE; -++ } -++ -++ } -++ -++ -++ /* is there a "ms" in this line?*/ -++ if(strstr(lineBuf, "ms") == NULL) -++ { -++ continue; -++ } -++ -++ /* grab the ms jitter value */ -++ converted = sscanf(lineBuf, "%f %s %f %s\n", &junkFloat1, junkStr1, &jitter_ms, junkStr2); -++ if(converted < 4) -++ { -++ printf("Line %i contains \"ms\", but expected fileds not found. Converted %i, Skipping.", -++ lineNo, converted); -++ printf("1=%i, 2=%s.\n", junkInt1, junkStr1); -++ continue; /* not our jitter line*/ -++ } -++ -++ /* Is the jitter value > threshold value? */ -++ if(abs(jitter_ms) > JitterThreshold_ms) -++ { -++ /* Found a jitter line that matches our crietrion. -++ Now set flag to be on the look out for the next -++ "df" output so that we can see how full the flash is. -++ */ -++ -++ if(saveJitterCnt < MAX_SAVE_BUFFER) -++ { -++ saveJitter[saveJitterCnt] = (int)abs(jitter_ms); /* why keep the (ms) jitter in float */ -++ dataLineNo[saveJitterCnt] = lineNo; -++ saveJitterCnt++; -++ lookFor_df = TRUE; -++ } -++ else -++ { -++ printf("Oops! I've run out of buffer space before I found a %% use line. Dropping itter value. Increase MAX_SAVE_BUFFER and recompile.\n"); -++ } -++ -++ -++ } -++ -++ } -++ -++ -++ /* Now print out any saved jitter values that were not printed out because we did not find -++ and "df" after these were picked up. Only print if a "df" disk usage was ever found. -++ */ -++ if(lookFor_df && (dfPercent >= 0)) -++ { -++ /* Now print out the saved jitter values (in col2) with this dfPercent value as the col1. */ -++ for(cnt = 0; cnt < saveJitterCnt; cnt++) -++ { -++ fprintf(stderr, "%i\t%i\n", dfPercent, (int)saveJitter[cnt]); -++ } -++ } -++ -++ return 0; -++ -++ -++}/* end main() */ -++ -++ -++ -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/Makefile linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/Makefile -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,48 @@ -++LIBUBI_PATH=../../ubi-utils/new-utils/ -++LIBUBI_SRC_PATH=../../ubi-utils/new-utils/src/ -++LIBUBI_HEADER_PATH=../../ubi-utils/new-utils/include -++UBI_HEADERS_PATH=../../include/ -++UBIUTILS_PATH=../../ubi-utils/new-utils/ -++ -++CC := $(CROSS)gcc -++ -++TESTS=io_update volrefcnt integ io_paral io_read io_basic \ -++ mkvol_basic mkvol_bad mkvol_paral rsvol -++ -++HELPER_NAMES=ubiupdatevol -++HELPERS=$(addprefix helpers/, $(HELPER_NAMES)) -++ -++# Because of implicite rules we use make treats .o files as intermediate, thus -++# it removes the. If you want to prevent the removal, uncomment the below -++#.SECONDARY: $(addsuffix .o, $(TESTS)) $(addsuffix .o, $(HELPERS)) -++ -++CFLAGS += -Wall -I$(LIBUBI_HEADER_PATH) -I $(UBI_HEADERS_PATH) -L. -O2 -++ -++all: ubi-utils libubi $(TESTS) $(HELPERS) -++ -++# Compile ubilib with the udevsettle hack -++libubi: $(LIBUBI_SRC_PATH)/libubi.c $(LIBUBI_HEADER_PATH)/libubi.h $(LIBUBI_SRC_PATH)/libubi_int.h -++ $(CC) $(CFLAGS) -I $(LIBUBI_SRC_PATH) -I../../include -DUDEV_SETTLE_HACK -c $(LIBUBI_SRC_PATH)/libubi.c -o libubi.o -++ ar cr libubi.a libubi.o -++ -++# The below cancels existing implicite rule to make programs from .c files, -++# in order to force make using our rule defined below -++%: %.c -++ -++# The below is the rule to get an .o file from a .c file -++%.o: %.c -++ $(CC) $(CFLAGS) $< -c -o $@ -++ -++# And the below is the rule to get final test executable from its .o and common.o -++%: %.o common.o -++ $(CC) $(CFLAGS) $^ -lubi -o $@ -++ -++# *paral tests require libpthread, thus the below rule for them -++%paral: %paral.o common.o -++ $(CC) $(CFLAGS) $^ -lubi -lpthread -o $@ -++ -++ubi-utils: -++ make -C $(UBIUTILS_PATH) -++ -++clean: -++ rm -f $(TESTS) $(addsuffix .o, $(TESTS)) libubi.* $(HELPERS) $(addsuffix .o, $(HELPERS)) -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/README.udev linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/README.udev -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/README.udev 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/README.udev 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,25 @@ -++There is a problem with udev: when a volume is created, there is a delay -++before corresponding /dev/ubiX_Y device node is created by udev, so some -++tests fail because of this. The symptom is error messages like -++"cannot open /dev/ubi0_0". -++ -++One possible solution of this problem is to pre-create UBI device and volume -++nodes. There is even a script which may be used for this in ubi-utils/scripts/. -++But this is not enough because udev will still remove and re-create the nodes -++and tests will still fail. So you need to stop removing device nodes using -++the following udev rule: -++ -++ KERNEL=="ubi*_*", ACTION=="remove", OPTIONS+="ignore_device" -++ -++In our Ubuntu distribution we put that to new file: -++/etc/udev/rules.d/50-local.rules -++ -++Another possibility is to call udevsettle utility in libubi after the volume -++has been created See src/libubi.c - the call is compiled in only if -++UDEV_SETTLE_HACK is defined. This is anyway an ugly hack, but works, although -++makes the tests slower. Suggestions are welcome. -++ -++So, if you have udevsettel unility in your system, you do not have to do -++anyting, and the tests should work, because we compile libubi with -++UDEV_SETTLE_HACK. Otherwise, you should remove -D UDEV_SETTLE_HACK -++from the makefile and pre-create UBI device nodes. -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/common.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/common.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/common.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/common.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,336 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem B. Bityutskiy -++ * -++ * The stuff which is common for many tests. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "libubi.h" -++#include "common.h" -++ -++/** -++ * __initial_check - check that common prerequisites which are required to run -++ * tests. -++ * -++ * @test test name -++ * @argc count of command-line arguments -++ * @argv command-line arguments -++ * -++ * This function returns %0 if all is fine and test may be run and %-1 if not. -++ */ -++int __initial_check(const char *test, int argc, char * const argv[]) -++{ -++ libubi_t libubi; -++ struct ubi_dev_info dev_info; -++ -++ /* -++ * All tests require UBI character device name as the first parameter, -++ * check this. -++ */ -++ if (argc < 2) { -++ __err_msg(test, __FUNCTION__, __LINE__, -++ "UBI character device node is not specified"); -++ return -1; -++ } -++ -++ libubi = libubi_open(); -++ if (libubi == NULL) { -++ __failed(test, __FUNCTION__, __LINE__, "libubi_open"); -++ return -1; -++ } -++ -++ if (ubi_get_dev_info(libubi, argv[1], &dev_info)) { -++ __failed(test, __FUNCTION__, __LINE__, "ubi_get_dev_info"); -++ goto close; -++ } -++ -++ if (dev_info.avail_lebs < MIN_AVAIL_EBS) { -++ __err_msg(test, __FUNCTION__, __LINE__, -++ "insufficient available eraseblocks %d on UBI " -++ "device, required %d", -++ dev_info.avail_lebs, MIN_AVAIL_EBS); -++ goto close; -++ } -++ -++ if (dev_info.vol_count != 0) { -++ __err_msg(test, __FUNCTION__, __LINE__, -++ "device %s is not empty", argv[1]); -++ goto close; -++ } -++ -++ libubi_close(libubi); -++ return 0; -++ -++close: -++ libubi_close(libubi); -++ return -1; -++} -++ -++/** -++ * __err_msg - print a message to stderr. -++ * -++ * @test test name -++ * @func function name -++ * @line line number -++ * @fmt format string -++ */ -++void __err_msg(const char *test, const char *func, int line, -++ const char *fmt, ...) -++{ -++ va_list args; -++ -++ fprintf(stderr, "[%s] %s():%d: ", test, func, line); -++ va_start(args, fmt); -++ vfprintf(stderr, fmt, args); -++ fprintf(stderr, "\n"); -++ va_end(args); -++} -++ -++/** -++ * __failed - print function fail message. -++ * -++ * @test test name -++ * @func calling function name -++ * @line line number -++ * @failed failed function name -++ */ -++void __failed(const char *test, const char *func, int line, -++ const char *failed) -++{ -++ fprintf(stderr, "[%s] %s():%d: function %s() failed with error %d (%s)\n", -++ test, func, line, failed, errno, strerror(errno)); -++} -++ -++/** -++ * __check_volume - check volume information. -++ * -++ * @libubi libubi descriptor -++ * @dev_info UBI device description -++ * @test test name -++ * @func function name -++ * @line line number -++ * @vol_id ID of existing volume to check -++ * @req volume creation request to compare with -++ * -++ * This function checks if a volume created using @req request has exactly the -++ * requested characteristics. Returns 0 in case of success and %-1 in case of -++ * error. -++ */ -++int __check_volume(libubi_t libubi, struct ubi_dev_info *dev_info, -++ const char *test, const char *func, int line, int vol_id, -++ const struct ubi_mkvol_request *req) -++{ -++ int ret; -++ struct ubi_vol_info vol_info; -++ int leb_size; -++ long long rsvd_bytes; -++ -++ ret = ubi_get_vol_info1(libubi, dev_info->dev_num, vol_id, &vol_info); -++ if (ret) { -++ __failed(test, func, line, "ubi_get_vol_info"); -++ return -1; -++ } -++ -++ if (req->alignment != vol_info.alignment) { -++ __err_msg(test, func, line, -++ "bad alignment: requested %d, got %d", -++ req->alignment, vol_info.alignment); -++ return -1; -++ } -++ if (req->vol_type != vol_info.type) { -++ __err_msg(test, func, line, "bad type: requested %d, got %d", -++ req->vol_type, vol_info.type); -++ return -1; -++ } -++ if (strlen(req->name) != strlen(vol_info.name) || -++ strcmp(req->name, vol_info.name) != 0) { -++ __err_msg(test, func, line, -++ "bad name: requested \"%s\", got \"%s\"", -++ req->name, vol_info.name); -++ return -1; -++ } -++ if (vol_info.corrupted) { -++ __err_msg(test, func, line, "corrupted new volume"); -++ return -1; -++ } -++ -++ leb_size = dev_info->leb_size - (dev_info->leb_size % req->alignment); -++ if (leb_size != vol_info.leb_size) { -++ __err_msg(test, func, line, -++ "bad usable LEB size %d, should be %d", -++ vol_info.leb_size, leb_size); -++ return -1; -++ } -++ -++ rsvd_bytes = req->bytes; -++ if (rsvd_bytes % leb_size) -++ rsvd_bytes += leb_size - (rsvd_bytes % leb_size); -++ -++ if (rsvd_bytes != vol_info.rsvd_bytes) { -++ __err_msg(test, func, line, -++ "bad reserved bytes %lld, should be %lld", -++ vol_info.rsvd_bytes, rsvd_bytes); -++ return -1; -++ } -++ -++ return 0; -++} -++ -++/** -++ * __check_vol_patt - check that volume contains certain data -++ * -++ * @libubi libubi descriptor -++ * @dev_info UBI device description -++ * @test test name -++ * @func function name -++ * @line line number -++ * @node volume character device node -++ * @byte data pattern to check -++ * -++ * This function returns %0 if the volume contains only @byte bytes, and %-1 if -++ * not. -++ */ -++int __check_vol_patt(libubi_t libubi, struct ubi_dev_info *dev_info, -++ const char *test, const char *func, int line, -++ const char *node, uint8_t byte) -++{ -++ int ret, fd; -++ long long bytes = 0; -++ struct ubi_vol_info vol_info; -++ unsigned char buf[512]; -++ -++ fd = open(node, O_RDONLY); -++ if (fd == -1) { -++ __failed(test, func, line, "open"); -++ __err_msg(test, func, line, "cannot open \"%s\"\n", node); -++ return -1; -++ } -++ -++ ret = ubi_get_vol_info(libubi, node, &vol_info); -++ if (ret) { -++ __failed(test, func, line, "ubi_get_vol_info"); -++ goto close; -++ } -++ -++ while (bytes < vol_info.data_bytes) { -++ int i; -++ -++ memset(buf, ~byte, 512); -++ ret = read(fd, buf, 512); -++ if (ret == -1) { -++ __failed(test, func, line, "read"); -++ __err_msg(test, func, line, "bytes = %lld, ret = %d", -++ bytes, ret); -++ goto close; -++ } -++ -++ if (ret == 0 && bytes + ret < vol_info.data_bytes) { -++ __err_msg(test, func, line, -++ "EOF, but read only %lld bytes of %lld", -++ bytes + ret, vol_info.data_bytes); -++ goto close; -++ } -++ -++ for (i = 0; i < ret; i++) -++ if (buf[i] != byte) { -++ __err_msg(test, func, line, -++ "byte at %lld is not %#x but %#x", -++ bytes + i, byte, (int)buf[i]); -++ goto close; -++ } -++ -++ bytes += ret; -++ } -++ -++ close(fd); -++ return 0; -++ -++close: -++ close(fd); -++ return -1; -++} -++ -++/** -++ * __update_vol_patt - update volume using a certain byte pattern -++ * -++ * @libubi libubi descriptor -++ * @dev_info UBI device description -++ * @test test name -++ * @func function name -++ * @line line number -++ * @node volume character device node -++ * @byte data pattern to check -++ * -++ * This function returns %0 in case of success, and %-1 if in case of failure. -++ */ -++int __update_vol_patt(libubi_t libubi, const char *test, const char *func, -++ int line, const char *node, long long bytes, uint8_t byte) -++{ -++ int ret, fd; -++ long long written = 0; -++ unsigned char buf[512]; -++ -++ fd = open(node, O_RDWR); -++ if (fd == -1) { -++ __failed(test, func, line, "open"); -++ __err_msg(test, func, line, "cannot open \"%s\"\n", node); -++ return -1; -++ } -++ -++ if (ubi_update_start(libubi, fd, bytes)) { -++ __failed(test, func, line, "ubi_update_start"); -++ __err_msg(test, func, line, "bytes = %lld", bytes); -++ goto close; -++ } -++ -++ memset(buf, byte, 512); -++ -++ while (written != bytes) { -++ ret = write(fd, buf, 512); -++ if (ret == -1) { -++ __failed(test, func, line, "write"); -++ __err_msg(test, func, line, "written = %lld, ret = %d", -++ written, ret); -++ goto close; -++ } -++ written += ret; -++ -++ if (written > bytes) { -++ __err_msg(test, func, line, "update length %lld bytes, " -++ "but %lld bytes are already written", -++ bytes, written); -++ goto close; -++ } -++ } -++ -++ close(fd); -++ return 0; -++ -++close: -++ close(fd); -++ return -1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/common.h linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/common.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/common.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/common.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,103 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem B. Bityutskiy -++ * -++ * The stuff which is common for many tests. -++ */ -++ -++#ifndef __COMMON_H__ -++#define __COMMON_H__ -++ -++#include -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++#define UBI_VOLUME_PATTERN "/dev/ubi%d_%d" -++#define MIN_AVAIL_EBS 5 -++#define PAGE_SIZE 4096 -++ -++#define min(a, b) ((a) < (b) ? (a) : (b)) -++ -++#define err_msg(fmt, ...) \ -++ __err_msg(TESTNAME, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__) -++ -++#define failed(name) \ -++ __failed(TESTNAME, __FUNCTION__, __LINE__, name) -++ -++#define initial_check(argc, argv) \ -++ __initial_check(TESTNAME, argc, argv) -++ -++#define check_volume(vol_id, req) \ -++ __check_volume(libubi, &dev_info, TESTNAME, __FUNCTION__, \ -++ __LINE__, vol_id, req) -++ -++#define check_vol_patt(node, byte) \ -++ __check_vol_patt(libubi, &dev_info, TESTNAME, __FUNCTION__, __LINE__, \ -++ node, byte) -++ -++#define update_vol_patt(node, bytes, byte) \ -++ __update_vol_patt(libubi, TESTNAME, __FUNCTION__, __LINE__, \ -++ node, bytes, byte) -++ -++#define check_failed(ret, error, func, fmt, ...) ({ \ -++ int __ret; \ -++ \ -++ if (!ret) { \ -++ err_msg("%s() returned success but should have failed", func); \ -++ err_msg(fmt, ##__VA_ARGS__); \ -++ __ret = -1; \ -++ } \ -++ if (errno != (error)) { \ -++ err_msg("%s failed with error %d (%s), expected %d (%s)", \ -++ func, errno, strerror(errno), error, strerror(error)); \ -++ err_msg(fmt, ##__VA_ARGS__); \ -++ __ret = -1; \ -++ } \ -++ __ret = 0; \ -++}) -++ -++/* Alignments to test, @s is eraseblock size */ -++#define ALIGNMENTS(s) \ -++ {3, 5, 27, 666, 512, 1024, 2048, (s)/2-3, (s)/2-2, (s)/2-1, (s)/2+1, \ -++ (s)/2+2, (s)/2+3, (s)/3-3, (s)/3-2, (s)/3-1, (s)/3+1, (s)/3+2, \ -++ (s)/3+3, (s)/4-3, (s)/4-2, (s)/4-1, (s)/4+1, (s)/4+2, (s)/4+3, \ -++ (s)/5-3, (s)/5-2, (s)/5-1, (s)/5+1, (s)/5+2, (s)/5+3, (s)-17, (s)-9, \ -++ (s)-8, (s)-6, (s)-4, (s)-1, (s)}; -++ -++extern void __err_msg(const char *test, const char *func, int line, -++ const char *fmt, ...); -++void __failed(const char *test, const char *func, int line, -++ const char *failed); -++int __initial_check(const char *test, int argc, char * const argv[]); -++int __check_volume(libubi_t libubi, struct ubi_dev_info *dev_info, -++ const char *test, const char *func, int line, int vol_id, -++ const struct ubi_mkvol_request *req); -++int __check_vol_patt(libubi_t libubi, struct ubi_dev_info *dev_info, -++ const char *test, const char *func, int line, -++ const char *node, uint8_t byte); -++int __update_vol_patt(libubi_t libubi, const char *test, const char *func, -++ int line, const char *node, long long bytes, -++ uint8_t byte); -++ -++#ifdef __cplusplus -++} -++#endif -++ -++#endif /* !__COMMON_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/integ.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/integ.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/integ.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/integ.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,783 @@ -++#define _LARGEFILE64_SOURCE -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#include "libubi.h" -++ -++struct erase_block_info; -++struct volume_info; -++struct ubi_device_info; -++ -++struct write_info -++{ -++ struct write_info *next; -++ struct erase_block_info *erase_block; -++ int offset_within_block; /* Offset within erase block */ -++ off64_t offset; /* Offset within volume */ -++ int size; -++ int random_seed; -++}; -++ -++struct erase_block_info -++{ -++ struct volume_info *volume; -++ int block_number; -++ off64_t offset; /* Offset within volume */ -++ off64_t top_of_data; -++ int touched; /* Have we done anything at all with this erase block */ -++ int erased; /* This erased block is currently erased */ -++ struct write_info *writes; -++}; -++ -++struct volume_fd -++{ -++ struct volume_fd *next; -++ struct volume_info *volume; -++ int fd; -++}; -++ -++struct volume_info -++{ -++ struct volume_info *next; -++ struct ubi_device_info *ubi_device; -++ struct volume_fd *fds; -++ struct erase_block_info *erase_blocks; -++ const char *device_file_name; -++ struct ubi_vol_info info; -++}; -++ -++struct ubi_device_info -++{ -++ struct volume_info *volumes; -++ const char *device_file_name; -++ struct ubi_dev_info info; -++}; -++ -++struct open_volume_fd -++{ -++ struct open_volume_fd *next; -++ struct volume_fd *vol_fd; -++}; -++ -++#define MAX_UBI_DEVICES 64 -++ -++static libubi_t libubi; -++ -++static struct ubi_info info; -++static struct ubi_device_info ubi_array[MAX_UBI_DEVICES]; -++ -++static uint64_t total_written = 0; -++static uint64_t total_space = 0; -++ -++static struct open_volume_fd *open_volumes; -++static size_t open_volume_count = 0; -++ -++static const char *ubi_module_load_string; -++ -++static unsigned char *write_buffer = NULL; -++static unsigned char *read_buffer = NULL; -++ -++static long long max_ebs_per_vol = 0; /* max number of ebs per vol (zero => no max) */ -++ -++static unsigned long next_seed = 1; -++ -++static unsigned get_next_seed() -++{ -++ next_seed = next_seed * 1103515245 + 12345; -++ return ((unsigned) (next_seed / 65536) % 32768); -++} -++ -++static void error_exit(const char *msg) -++{ -++ int eno = errno; -++ fprintf(stderr,"UBI Integrity Test Error: %s\n",msg); -++ if (eno) { -++ fprintf(stderr, "errno = %d\n", eno); -++ fprintf(stderr, "strerror = %s\n", strerror(eno)); -++ } -++ exit(1); -++} -++ -++static void *allocate(size_t n) -++{ -++ void *p = malloc(n); -++ if (!p) -++ error_exit("Memory allocation failure"); -++ memset(p, 0, n); -++ return p; -++} -++ -++static unsigned get_random_number(unsigned n) -++{ -++ uint64_t r, b; -++ -++ if (n < 1) -++ return 0; -++ r = rand(); -++ r *= n; -++ b = RAND_MAX; -++ b += 1; -++ r /= b; -++ return r; -++} -++ -++static struct volume_fd *open_volume(struct volume_info *vol) -++{ -++ struct volume_fd *s; -++ struct open_volume_fd *ofd; -++ int fd; -++ -++ if (vol->fds) { -++ /* If already open dup it */ -++ fd = dup(vol->fds->fd); -++ if (fd == -1) -++ error_exit("Failed to dup volume device file des"); -++ } else { -++ fd = open(vol->device_file_name, O_RDWR | O_LARGEFILE); -++ if (fd == -1) -++ error_exit("Failed to open volume device file"); -++ } -++ s = allocate(sizeof(*s)); -++ s->fd = fd; -++ s->volume = vol; -++ s->next = vol->fds; -++ vol->fds = s; -++ /* Add to open volumes list */ -++ ofd = allocate(sizeof(*ofd)); -++ ofd->vol_fd = s; -++ ofd->next = open_volumes; -++ open_volumes = ofd; -++ open_volume_count += 1; -++ return 0; -++} -++ -++static void close_volume(struct volume_fd *vol_fd) -++{ -++ struct volume_fd *vfd, *vfd_last; -++ struct open_volume_fd *ofd, *ofd_last; -++ int fd = vol_fd->fd; -++ -++ /* Remove from open volumes list */ -++ ofd_last = NULL; -++ ofd = open_volumes; -++ while (ofd) { -++ if (ofd->vol_fd == vol_fd) { -++ if (ofd_last) -++ ofd_last->next = ofd->next; -++ else -++ open_volumes = ofd->next; -++ free(ofd); -++ open_volume_count -= 1; -++ break; -++ } -++ ofd_last = ofd; -++ ofd = ofd->next; -++ } -++ /* Remove from volume fd list */ -++ vfd_last = NULL; -++ vfd = vol_fd->volume->fds; -++ while (vfd) { -++ if (vfd == vol_fd) { -++ if (vfd_last) -++ vfd_last->next = vfd->next; -++ else -++ vol_fd->volume->fds = vfd->next; -++ free(vfd); -++ break; -++ } -++ vfd_last = vfd; -++ vfd = vfd->next; -++ } -++ /* Close volume device file */ -++ if (close(fd) == -1) -++ error_exit("Failed to close volume file descriptor"); -++} -++ -++static void set_random_data(unsigned seed, unsigned char *buf, int size) -++{ -++ int i; -++ unsigned r; -++ -++ r = rand(); -++ srand(seed); -++ for (i = 0; i < size; ++i) -++ buf[i] = rand(); -++ srand(r); -++} -++ -++#if 0 -++static void print_write_info(struct write_info *w) -++{ -++ printf("Offset: %lld Size:%d Seed:%u\n", w->offset, w->size, w->random_seed); -++ fflush(stdout); -++} -++#endif -++ -++static void check_erase_block(struct erase_block_info *erase_block, int fd) -++{ -++ struct write_info *w; -++ off64_t gap_end; -++ int leb_size = erase_block->volume->info.leb_size; -++ ssize_t bytes_read; -++ -++ w = erase_block->writes; -++ gap_end = erase_block->offset + leb_size; -++ while (w) { -++ if (w->offset + w->size < gap_end) { -++ /* There is a gap. Check all 0xff */ -++ off64_t gap_start = w->offset + w->size; -++ size_t size = gap_end - gap_start; -++ if (lseek64(fd, gap_start, SEEK_SET) != gap_start) -++ error_exit("lseek64 failed"); -++ memset(read_buffer, 0 , size); -++ errno = 0; -++ bytes_read = read(fd, read_buffer, size); -++ if (bytes_read != size) -++ error_exit("read failed in gap"); -++ while (size) -++ if (read_buffer[--size] != 0xff) { -++ fprintf(stderr, "block no. = %d\n" , erase_block->block_number); -++ fprintf(stderr, "offset = %lld\n" , (long long) gap_start); -++ fprintf(stderr, "size = %ld\n" , (long) bytes_read); -++ error_exit("verify 0xff failed"); -++ } -++ } -++ if (lseek64(fd, w->offset, SEEK_SET) != w->offset) -++ error_exit("lseek64 failed"); -++ memset(read_buffer, 0 , w->size); -++ errno = 0; -++ bytes_read = read(fd, read_buffer, w->size); -++ if (bytes_read != w->size) { -++ fprintf(stderr, "offset = %lld\n" , (long long) w->offset); -++ fprintf(stderr, "size = %ld\n" , (long) w->size); -++ fprintf(stderr, "bytes_read = %ld\n" , (long) bytes_read); -++ error_exit("read failed"); -++ } -++ set_random_data(w->random_seed, write_buffer, w->size); -++ if (memcmp(read_buffer, write_buffer, w->size)) -++ error_exit("verify failed"); -++ gap_end = w->offset; -++ w = w->next; -++ } -++ if (gap_end > erase_block->offset) { -++ /* Check all 0xff */ -++ off64_t gap_start = erase_block->offset; -++ size_t size = gap_end - gap_start; -++ if (lseek64(fd, gap_start, SEEK_SET) != gap_start) -++ error_exit("lseek64 failed"); -++ memset(read_buffer, 0 , size); -++ errno = 0; -++ bytes_read = read(fd, read_buffer, size); -++ if (bytes_read != size) -++ error_exit("read failed in gap"); -++ while (size) -++ if (read_buffer[--size] != 0xff) { -++ fprintf(stderr, "block no. = %d\n" , erase_block->block_number); -++ fprintf(stderr, "offset = %lld\n" , (long long) gap_start); -++ fprintf(stderr, "size = %ld\n" , (long) bytes_read); -++ error_exit("verify 0xff failed!"); -++ } -++ } -++} -++ -++static int write_to_erase_block(struct erase_block_info *erase_block, int fd) -++{ -++ int page_size = erase_block->volume->ubi_device->info.min_io_size; -++ int leb_size = erase_block->volume->info.leb_size; -++ int next_offset = 0; -++ int space, size; -++ off64_t offset; -++ unsigned seed; -++ struct write_info *w; -++ -++ if (erase_block->writes) -++ next_offset = erase_block->writes->offset_within_block + erase_block->writes->size; -++ space = leb_size - next_offset; -++ if (space <= 0) -++ return 0; /* No space */ -++ if (!get_random_number(10)) { -++ /* 1 time in 10 leave a gap */ -++ next_offset += get_random_number(space); -++ next_offset = (next_offset / page_size) * page_size; -++ space = leb_size - next_offset; -++ } -++ if (get_random_number(2)) -++ size = 1 * page_size; -++ else if (get_random_number(2)) -++ size = 2 * page_size; -++ else if (get_random_number(2)) -++ size = 3 * page_size; -++ else if (get_random_number(2)) -++ size = 4 * page_size; -++ else { -++ if (get_random_number(4)) -++ size = get_random_number(space); -++ else -++ size = space; -++ size = (size / page_size) * page_size; -++ } -++ if (size == 0 || size > space) -++ size = page_size; -++ if (next_offset + size > leb_size) -++ error_exit("internal error"); -++ offset = erase_block->offset + next_offset; -++ if (offset < erase_block->top_of_data) -++ error_exit("internal error!"); -++ if (lseek64(fd, offset, SEEK_SET) != offset) -++ error_exit("lseek64 failed"); -++ /* Do write */ -++ seed = get_next_seed(); -++ if (!seed) -++ seed = 1; -++ set_random_data(seed, write_buffer, size); -++ if (write(fd, write_buffer, size) != size) -++ error_exit("write failed"); -++ erase_block->top_of_data = offset + size; -++ /* Make write info and add to eb */ -++ w = allocate(sizeof(*w)); -++ w->offset_within_block = next_offset; -++ w->offset = offset; -++ w->size = size; -++ w->random_seed = seed; -++ w->next = erase_block->writes; -++ erase_block->writes = w; -++ erase_block->touched = 1; -++ erase_block->erased = 0; -++ total_written += size; -++ return 1; -++} -++ -++static void erase_erase_block(struct erase_block_info *erase_block, int fd) -++{ -++ struct write_info *w; -++ uint32_t eb_no; -++ int res; -++ -++ eb_no = erase_block->block_number; -++ res = ioctl(fd, UBI_IOCEBER, &eb_no); -++ if (res) -++ error_exit("Failed to erase an erase block"); -++ /* Remove writes from this eb */ -++ while (erase_block->writes) { -++ w = erase_block->writes; -++ erase_block->writes = erase_block->writes->next; -++ free(w); -++ } -++ erase_block->erased = 1; -++ erase_block->touched = 1; -++ erase_block->top_of_data = erase_block->offset; -++} -++ -++static void operate_on_erase_block(struct erase_block_info *erase_block, int fd) -++{ -++ /* -++ Possible operations: -++ read from it and verify -++ write to it -++ erase it -++ */ -++ int work_done = 1; -++ static int no_work_done_count = 0; -++ -++ if (!get_random_number(10) && no_work_done_count <= 5) { -++ check_erase_block(erase_block, fd); -++ work_done = 0; -++ } else if (get_random_number(100)) { -++ if (!write_to_erase_block(erase_block, fd)) { -++ /* The erase block was full */ -++ if (get_random_number(2) || no_work_done_count > 5) -++ erase_erase_block(erase_block, fd); -++ else -++ work_done = 0; -++ } -++ } else -++ erase_erase_block(erase_block, fd); -++ if (work_done) -++ no_work_done_count = 0; -++ else -++ no_work_done_count += 1; -++} -++ -++static void operate_on_open_volume(struct volume_fd *vol_fd) -++{ -++ /* -++ Possible operations: -++ operate on an erase block -++ close volume -++ */ -++ if (get_random_number(100) == 0) -++ close_volume(vol_fd); -++ else { -++ /* Pick an erase block at random */ -++ int eb_no = get_random_number(vol_fd->volume->info.rsvd_lebs); -++ operate_on_erase_block(&vol_fd->volume->erase_blocks[eb_no], vol_fd->fd); -++ } -++} -++ -++static void operate_on_volume(struct volume_info *vol) -++{ -++ /* -++ Possible operations: -++ open it -++ resize it (must close fd's first) <- TODO -++ delete it (must close fd's first) <- TODO -++ */ -++ open_volume(vol); -++} -++ -++static int ubi_major(const char *device_file_name) -++{ -++ struct stat buf; -++ static int maj = 0; -++ -++ if (maj) -++ return maj; -++ if (stat(device_file_name, &buf) == -1) -++ error_exit("Failed to stat ubi device file"); -++ maj = major(buf.st_rdev); -++ return maj; -++} -++ -++static void operate_on_ubi_device(struct ubi_device_info *ubi_device) -++{ -++ /* -++ TODO: -++ Possible operations: -++ create a new volume -++ operate on existing volume -++ */ -++ /* -++ Simplified operation (i.e. only have 1 volume): -++ If there are no volumes create 1 volumne -++ Then operate on the volume -++ */ -++ if (ubi_device->info.vol_count == 0) { -++ /* Create the one-and-only volume we will use */ -++ char dev_name[1024]; -++ int i, n, maj, fd; -++ struct volume_info *s; -++ struct ubi_mkvol_request req; -++ -++ req.vol_id = UBI_VOL_NUM_AUTO; -++ req.alignment = 1; /* TODO: What is this? */ -++ req.bytes = ubi_device->info.leb_size * max_ebs_per_vol; -++ if (req.bytes == 0 || req.bytes > ubi_device->info.avail_bytes) -++ req.bytes = ubi_device->info.avail_bytes; -++ req.vol_type = UBI_DYNAMIC_VOLUME; -++ req.name = "integ-test-vol"; -++ if (ubi_mkvol(libubi, ubi_device->device_file_name, &req)) -++ error_exit("ubi_mkvol failed"); -++ s = allocate(sizeof(*s)); -++ s->ubi_device = ubi_device; -++ if (ubi_get_vol_info1(libubi, ubi_device->info.dev_num, req.vol_id, &s->info)) -++ error_exit("ubi_get_vol_info failed"); -++ n = s->info.rsvd_lebs; -++ s->erase_blocks = allocate(sizeof(struct erase_block_info) * n); -++ for (i = 0; i < n; ++i) { -++ s->erase_blocks[i].volume = s; -++ s->erase_blocks[i].block_number = i; -++ s->erase_blocks[i].offset = i * (off64_t) s->info.leb_size; -++ s->erase_blocks[i].top_of_data = s->erase_blocks[i].offset; -++ } -++ /* FIXME: Correctly get device file name */ -++ sprintf(dev_name, "%s_%d", ubi_device->device_file_name, req.vol_id); -++ s->device_file_name = strdup(dev_name); -++ ubi_device->volumes = s; -++ ubi_device->info.vol_count += 1; -++ sleep(1); -++ fd = open(s->device_file_name, O_RDONLY); -++ if (fd == -1) { -++ /* FIXME: Correctly make node */ -++ maj = ubi_major(ubi_device->device_file_name); -++ sprintf(dev_name, "mknod %s c %d %d", s->device_file_name, maj, req.vol_id + 1); -++ system(dev_name); -++ } else if (close(fd) == -1) -++ error_exit("Failed to close volume device file"); -++ } -++ operate_on_volume(ubi_device->volumes); -++} -++ -++static void do_an_operation(void) -++{ -++ int too_few = (open_volume_count < info.dev_count * 3); -++ int too_many = (open_volume_count > info.dev_count * 5); -++ -++ if (too_many || (!too_few && get_random_number(1000) > 0)) { -++ /* Operate on an open volume */ -++ size_t pos; -++ struct open_volume_fd *ofd; -++ pos = get_random_number(open_volume_count); -++ for (ofd = open_volumes; pos && ofd && ofd->next; --pos) -++ ofd = ofd->next; -++ operate_on_open_volume(ofd->vol_fd); -++ } else if (info.dev_count > 0) { -++ /* Operate on a ubi device */ -++ size_t ubi_pos = 0; -++ if (info.dev_count > 1) -++ ubi_pos = get_random_number(info.dev_count - 1); -++ operate_on_ubi_device(&ubi_array[ubi_pos]); -++ } else -++ error_exit("Internal error"); -++} -++ -++static void get_ubi_devices_info(void) -++{ -++ int i, ubi_pos = 0; -++ char dev_name[1024]; -++ size_t buf_size = 1024 * 128; -++ -++ if (ubi_get_info(libubi, &info)) -++ error_exit("ubi_get_info failed"); -++ if (info.dev_count > MAX_UBI_DEVICES) -++ error_exit("Too many ubi devices"); -++ for (i = info.lowest_dev_num; i <= info.highest_dev_num; ++i) { -++ struct ubi_device_info *s; -++ s = &ubi_array[ubi_pos++]; -++ if (ubi_get_dev_info1(libubi, i, &s->info)) -++ error_exit("ubi_get_dev_info1 failed"); -++ if (s->info.vol_count) -++ error_exit("There are existing volumes"); -++ /* FIXME: Correctly get device file name */ -++ sprintf(dev_name, "/dev/ubi%d", i); -++ s->device_file_name = strdup(dev_name); -++ if (buf_size < s->info.leb_size) -++ buf_size = s->info.leb_size; -++ if (max_ebs_per_vol && s->info.leb_size * max_ebs_per_vol < s->info.avail_bytes) -++ total_space += s->info.leb_size * max_ebs_per_vol; -++ else -++ total_space += s->info.avail_bytes; -++ } -++ write_buffer = allocate(buf_size); -++ read_buffer = allocate(buf_size); -++} -++ -++static void load_ubi(void) -++{ -++ system("rmmod ubi"); -++ if (system(ubi_module_load_string) != 0) -++ error_exit("Failed to load UBI module"); -++ sleep(1); -++} -++ -++static void do_some_operations(void) -++{ -++ unsigned i = 0; -++ total_written = 0; -++ printf("Total space: %llu\n", (unsigned long long) total_space); -++ while (total_written < total_space * 3) { -++ do_an_operation(); -++ if (i++ % 10000 == 0) -++ printf("Total written: %llu\n", (unsigned long long) total_written); -++ } -++ printf("Total written: %llu\n", (unsigned long long) total_written); -++} -++ -++static void reload_ubi(void) -++{ -++ /* Remove module */ -++ if (system("rmmod ubi") != 0) -++ error_exit("Failed to remove UBI module"); -++ /* Install module */ -++ if (system(ubi_module_load_string) != 0) -++ error_exit("Failed to load UBI module"); -++ sleep(1); -++} -++ -++static void check_volume(struct volume_info *vol) -++{ -++ struct erase_block_info *eb = vol->erase_blocks; -++ int pos; -++ int fd; -++ -++ fd = open(vol->device_file_name, O_RDWR | O_LARGEFILE); -++ if (fd == -1) -++ error_exit("Failed to open volume device file"); -++ for (pos = 0; pos < vol->info.rsvd_lebs; ++pos) -++ check_erase_block(eb++, fd); -++ if (close(fd) == -1) -++ error_exit("Failed to close volume device file"); -++} -++ -++static void check_ubi_device(struct ubi_device_info *ubi_device) -++{ -++ struct volume_info *vol; -++ -++ vol = ubi_device->volumes; -++ while (vol) { -++ check_volume(vol); -++ vol = vol->next; -++ } -++} -++ -++static void check_ubi(void) -++{ -++ int i; -++ -++ for (i = 0; i < info.dev_count; ++i) -++ check_ubi_device(&ubi_array[i]); -++} -++ -++static int is_all_digits(const char *s) -++{ -++ const char *digits = "0123456789"; -++ if (!s || !*s) -++ return 0; -++ for (;*s;++s) -++ if (!strchr(digits,*s)) -++ return 0; -++ return 1; -++} -++ -++static int get_short_arg(int *pos,const char *name,long long *result,int argc,char *argv[]) -++{ -++ const char *p = NULL; -++ int i = *pos; -++ size_t n = strlen(name); -++ -++ if (strlen(argv[i]) > n) -++ p = argv[i] + n; -++ else if (++i < argc) -++ p = argv[i]; -++ if (!is_all_digits(p)) -++ return 1; -++ *result = atoll(p); -++ *pos = i; -++ return 0; -++} -++ -++static int get_long_arg(int *pos,const char *name,long long *result,int argc,char *argv[]) -++{ -++ const char *p = NULL; -++ int i = *pos; -++ size_t n = strlen(name); -++ -++ if (strlen(argv[i]) > n) -++ p = argv[i] + n; -++ else if (++i < argc) -++ p = argv[i]; -++ if (p && *p == '=') { -++ p += 1; -++ if (!*p && ++i < argc) -++ p = argv[i]; -++ } -++ if (!is_all_digits(p)) -++ return 1; -++ *result = atoll(p); -++ *pos = i; -++ return 0; -++} -++ -++static int remove_all_volumes(void) -++{ -++ int i; -++ -++ for (i = 0; i < info.dev_count; ++i) { -++ struct ubi_device_info *ubi_device = &ubi_array[i]; -++ struct volume_info *vol; -++ vol = ubi_device->volumes; -++ while (vol) { -++ int res = ubi_rmvol(libubi, -++ ubi_device->device_file_name, -++ vol->info.vol_id); -++ if (res) -++ return res; -++ vol = vol->next; -++ } -++ } -++ return 0; -++} -++ -++int main(int argc,char *argv[]) -++{ -++ int i; -++ long long r, repeat = 1; -++ int initial_seed = 1, args_ok = 1; -++ -++ printf("UBI Integrity Test\n"); -++ -++ /* Get arguments */ -++ ubi_module_load_string = 0; -++ for (i = 1; i < argc; ++i) { -++ if (strncmp(argv[i], "-h", 2) == 0) -++ args_ok = 0; -++ else if (strncmp(argv[i], "--help", 6) == 0) -++ args_ok = 0; -++ else if (strncmp(argv[i], "-n", 2) == 0) { -++ if (get_short_arg(&i, "-n", &repeat, argc, argv)) -++ args_ok = 0; -++ } else if (strncmp(argv[i], "--repeat", 8) == 0) { -++ if (get_long_arg(&i, "--repeat", &repeat, argc, argv)) -++ args_ok = 0; -++ } else if (strncmp(argv[i], "-m", 2) == 0) { -++ if (get_short_arg(&i,"-m", &max_ebs_per_vol, argc, argv)) -++ args_ok = 0; -++ } else if (strncmp(argv[i], "--maxebs", 8) == 0) { -++ if (get_long_arg(&i, "--maxebs", &max_ebs_per_vol, argc, argv)) -++ args_ok = 0; -++ } else if (!ubi_module_load_string) -++ ubi_module_load_string = argv[i]; -++ else -++ args_ok = 0; -++ } -++ if (!args_ok || !ubi_module_load_string) { -++ fprintf(stderr, "Usage is: ubi_integ [] \n"); -++ fprintf(stderr, " Options: \n"); -++ fprintf(stderr, " -h, --help Help\n"); -++ fprintf(stderr, " -n arg, --repeat=arg Repeat test arg times\n"); -++ fprintf(stderr, " -m arg, --maxebs=arg Max no. of erase blocks\n"); -++ return 1; -++ } -++ -++ initial_seed = getpid(); -++ printf("Initial seed = %u\n", (unsigned) initial_seed); -++ next_seed = initial_seed; -++ srand(initial_seed); -++ load_ubi(); -++ -++ libubi = libubi_open(); -++ if (!libubi) -++ error_exit("Failed to open libubi"); -++ -++ get_ubi_devices_info(); -++ -++ r = 0; -++ while (repeat == 0 || r++ < repeat) { -++ printf("Cycle %lld\n", r); -++ do_some_operations(); -++ -++ /* Close all volumes */ -++ while (open_volumes) -++ close_volume(open_volumes->vol_fd); -++ -++ check_ubi(); -++ -++ libubi_close(libubi); -++ -++ reload_ubi(); -++ -++ libubi = libubi_open(); -++ if (!libubi) -++ error_exit("Failed to open libubi"); -++ -++ check_ubi(); -++ } -++ -++ if (remove_all_volumes()) -++ error_exit("Failed to remove all volumes"); -++ -++ libubi_close(libubi); -++ -++ printf("UBI Integrity Test completed ok\n"); -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/io_basic.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/io_basic.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/io_basic.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/io_basic.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,179 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem B. Bityutskiy -++ * -++ * Test basic UBI volume I/O capabilities. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "libubi.h" -++#define TESTNAME "io_basic" -++#include "common.h" -++ -++static libubi_t libubi; -++static struct ubi_dev_info dev_info; -++const char *node; -++ -++/** -++ * test_basic - check basic volume read and update capabilities. -++ * -++ * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) -++ * -++ * Thus function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int test_basic(int type) -++{ -++ struct ubi_mkvol_request req; -++ const char *name = TESTNAME ":test_basic()"; -++ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100]; -++ -++ req.vol_id = UBI_VOL_NUM_AUTO; -++ req.alignment = 1; -++ req.bytes = dev_info.avail_bytes; -++ req.vol_type = type; -++ req.name = name; -++ -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ return -1; -++ } -++ -++ sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num, req.vol_id); -++ -++ /* Make sure newly created volume contains only 0xFF bytes */ -++ if (check_vol_patt(vol_node, 0xFF)) -++ goto remove; -++ -++ /* Write 0xA5 bytes to the volume */ -++ if (update_vol_patt(vol_node, dev_info.avail_bytes, 0xA5)) -++ goto remove; -++ if (check_vol_patt(vol_node, 0xA5)) -++ goto remove; -++ -++ if (ubi_rmvol(libubi, node, req.vol_id)) { -++ failed("ubi_rmvol"); -++ return -1; -++ } -++ -++ return 0; -++ -++remove: -++ ubi_rmvol(libubi, node, req.vol_id); -++ return -1; -++} -++ -++/** -++ * test_aligned - test volume alignment feature. -++ * -++ * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) -++ * -++ * Thus function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int test_aligned(int type) -++{ -++ int i, ebsz; -++ struct ubi_mkvol_request req; -++ const char *name = TESTNAME ":test_aligned()"; -++ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100]; -++ int alignments[] = ALIGNMENTS(dev_info.leb_size); -++ -++ req.vol_type = type; -++ req.name = name; -++ -++ for (i = 0; i < sizeof(alignments)/sizeof(int); i++) { -++ req.vol_id = UBI_VOL_NUM_AUTO; -++ -++ req.alignment = alignments[i]; -++ req.alignment -= req.alignment % dev_info.min_io_size; -++ if (req.alignment == 0) -++ req.alignment = dev_info.min_io_size; -++ -++ ebsz = dev_info.leb_size - dev_info.leb_size % req.alignment; -++ req.bytes = MIN_AVAIL_EBS * ebsz; -++ -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ return -1; -++ } -++ -++ sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num, req.vol_id); -++ -++ /* Make sure newly created volume contains only 0xFF bytes */ -++ if (check_vol_patt(vol_node, 0xFF)) -++ goto remove; -++ -++ /* Write 0xA5 bytes to the volume */ -++ if (update_vol_patt(vol_node, req.bytes, 0xA5)) -++ goto remove; -++ if (check_vol_patt(vol_node, 0xA5)) -++ goto remove; -++ -++ if (ubi_rmvol(libubi, node, req.vol_id)) { -++ failed("ubi_rmvol"); -++ return -1; -++ } -++ } -++ -++ return 0; -++ -++remove: -++ ubi_rmvol(libubi, node, req.vol_id); -++ return -1; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ if (initial_check(argc, argv)) -++ return 1; -++ -++ node = argv[1]; -++ -++ libubi = libubi_open(); -++ if (libubi == NULL) { -++ failed("libubi_open"); -++ return 1; -++ } -++ -++ if (ubi_get_dev_info(libubi, node, &dev_info)) { -++ failed("ubi_get_dev_info"); -++ goto close; -++ } -++ -++ if (test_basic(UBI_DYNAMIC_VOLUME)) -++ goto close; -++ if (test_basic(UBI_STATIC_VOLUME)) -++ goto close; -++ if (test_aligned(UBI_DYNAMIC_VOLUME)) -++ goto close; -++ if (test_aligned(UBI_STATIC_VOLUME)) -++ goto close; -++ -++ libubi_close(libubi); -++ return 0; -++ -++close: -++ libubi_close(libubi); -++ return 1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/io_paral.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/io_paral.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/io_paral.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/io_paral.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,249 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem B. Bityutskiy -++ * -++ * This test does a lot of I/O to volumes in parallel. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "libubi.h" -++#define TESTNAME "io_paral" -++#include "common.h" -++ -++#define THREADS_NUM 3 -++#define ITERATIONS 10 -++ -++static libubi_t libubi; -++static struct ubi_dev_info dev_info; -++const char *node; -++static int iterations = ITERATIONS; -++int total_bytes; -++ -++static long long memory_limit(void) -++{ -++ long long result = 0; -++ FILE *f; -++ -++ f = fopen("/proc/meminfo", "r"); -++ if (!f) -++ return 0; -++ fscanf(f, "%*s %lld", &result); -++ fclose(f); -++ return result * 1024 / 4; -++} -++ -++/** -++ * the_thread - the testing thread. -++ * -++ * @ptr thread number -++ */ -++static void * the_thread(void *ptr) -++{ -++ int fd, iter = iterations, vol_id = (int)ptr; -++ unsigned char *wbuf, *rbuf; -++ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100]; -++ -++ wbuf = malloc(total_bytes); -++ rbuf = malloc(total_bytes); -++ if (!wbuf || !rbuf) { -++ failed("malloc"); -++ goto free; -++ } -++ -++ sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num, vol_id); -++ -++ while (iter--) { -++ int i, ret, written = 0, rd = 0; -++ int bytes = (random() % (total_bytes - 1)) + 1; -++ -++ fd = open(vol_node, O_RDWR); -++ if (fd == -1) { -++ failed("open"); -++ err_msg("cannot open \"%s\"\n", node); -++ goto free; -++ } -++ -++ for (i = 0; i < bytes; i++) -++ wbuf[i] = random() % 255; -++ memset(rbuf, '\0', bytes); -++ -++ do { -++ ret = ubi_update_start(libubi, fd, bytes); -++ if (ret && errno != EBUSY) { -++ failed("ubi_update_start"); -++ err_msg("vol_id %d", vol_id); -++ goto close; -++ } -++ } while (ret); -++ -++ while (written < bytes) { -++ int to_write = random() % (bytes - written); -++ -++ if (to_write == 0) -++ to_write = 1; -++ -++ ret = write(fd, wbuf, to_write); -++ if (ret != to_write) { -++ failed("write"); -++ err_msg("failed to write %d bytes at offset %d " -++ "of volume %d", to_write, written, -++ vol_id); -++ err_msg("update: %d bytes", bytes); -++ goto close; -++ } -++ -++ written += to_write; -++ } -++ -++ close(fd); -++ -++ fd = open(vol_node, O_RDONLY); -++ if (fd == -1) { -++ failed("open"); -++ err_msg("cannot open \"%s\"\n", node); -++ goto free; -++ } -++ -++ /* read data back and check */ -++ while (rd < bytes) { -++ int to_read = random() % (bytes - rd); -++ -++ if (to_read == 0) -++ to_read = 1; -++ -++ ret = read(fd, rbuf, to_read); -++ if (ret != to_read) { -++ failed("read"); -++ err_msg("failed to read %d bytes at offset %d " -++ "of volume %d", to_read, rd, vol_id); -++ goto close; -++ } -++ -++ rd += to_read; -++ } -++ -++ close(fd); -++ -++ } -++ -++ free(wbuf); -++ free(rbuf); -++ return NULL; -++ -++close: -++ close(fd); -++free: -++ free(wbuf); -++ free(rbuf); -++ return NULL; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ int i, ret; -++ pthread_t threads[THREADS_NUM]; -++ struct ubi_mkvol_request req; -++ long long mem_limit; -++ -++ if (initial_check(argc, argv)) -++ return 1; -++ -++ node = argv[1]; -++ -++ libubi = libubi_open(); -++ if (libubi == NULL) { -++ failed("libubi_open"); -++ return 1; -++ } -++ -++ if (ubi_get_dev_info(libubi, node, &dev_info)) { -++ failed("ubi_get_dev_info"); -++ goto close; -++ } -++ -++ req.alignment = 1; -++ mem_limit = memory_limit(); -++ if (mem_limit && mem_limit < dev_info.avail_bytes) -++ total_bytes = req.bytes = -++ (mem_limit / dev_info.leb_size / THREADS_NUM) -++ * dev_info.leb_size; -++ else -++ total_bytes = req.bytes = -++ ((dev_info.avail_lebs - 3) / THREADS_NUM) -++ * dev_info.leb_size; -++ for (i = 0; i < THREADS_NUM; i++) { -++ char name[100]; -++ -++ req.vol_id = i; -++ sprintf(name, TESTNAME":%d", i); -++ req.name = name; -++ req.vol_type = (i & 1) ? UBI_STATIC_VOLUME : UBI_DYNAMIC_VOLUME; -++ -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ goto remove; -++ } -++ } -++ -++ /* Create one volume with static data to make WL work more */ -++ req.vol_id = THREADS_NUM; -++ req.name = TESTNAME ":static"; -++ req.vol_type = UBI_DYNAMIC_VOLUME; -++ req.bytes = 3*dev_info.leb_size; -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ goto remove; -++ } -++ -++ for (i = 0; i < THREADS_NUM; i++) { -++ ret = pthread_create(&threads[i], NULL, &the_thread, (void*)i); -++ if (ret) { -++ failed("pthread_create"); -++ goto remove; -++ } -++ } -++ -++ for (i = 0; i < THREADS_NUM; i++) -++ pthread_join(threads[i], NULL); -++ -++ for (i = 0; i <= THREADS_NUM; i++) { -++ if (ubi_rmvol(libubi, node, i)) { -++ failed("ubi_rmvol"); -++ goto remove; -++ } -++ } -++ -++ libubi_close(libubi); -++ return 0; -++ -++remove: -++ for (i = 0; i <= THREADS_NUM; i++) -++ ubi_rmvol(libubi, node, i); -++ -++close: -++ libubi_close(libubi); -++ return 1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/io_read.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/io_read.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/io_read.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/io_read.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,388 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem B. Bityutskiy -++ * -++ * Test UBI volume read. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "libubi.h" -++#define TESTNAME "io_basic" -++#include "common.h" -++ -++static libubi_t libubi; -++static struct ubi_dev_info dev_info; -++const char *node; -++static int fd; -++ -++/* Data lengthes to test, @io - minimal I/O unit size, @s - eraseblock size */ -++#define LENGTHES(io, s) \ -++ {1, (io), (io)+1, 2*(io), 3*(io)-1, 3*(io), \ -++ PAGE_SIZE-1, PAGE_SIZE-(io), 2*PAGE_SIZE, 2*PAGE_SIZE-(io), \ -++ (s)/2-1, (s)/2, (s)/2+1, (s)-1, (s), (s)+1, 2*(s)-(io), 2*(s), \ -++ 2*(s)+(io), 3*(s), 3*(s)+(io)}; -++ -++/* -++ * Offsets to test, @io - minimal I/O unit size, @s - eraseblock size, @sz - -++ * volume size. -++ */ -++#define OFFSETS(io, s, sz) \ -++ {0, (io)-1, (io), (io)+1, 2*(io)-1, 2*(io), 3*(io)-1, 3*(io), \ -++ PAGE_SIZE-1, PAGE_SIZE-(io), 2*PAGE_SIZE, 2*PAGE_SIZE-(io), \ -++ (s)/2-1, (s)/2, (s)/2+1, (s)-1, (s), (s)+1, 2*(s)-(io), 2*(s), \ -++ 2*(s)+(io), 3*(s), (sz)-(s)-1, (sz)-(io)-1, (sz)-PAGE_SIZE-1}; -++ -++/** -++ * test_static - test static volume-specific features. -++ * -++ * Thus function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int test_static(void) -++{ -++ struct ubi_mkvol_request req; -++ const char *name = TESTNAME ":io_basic()"; -++ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100]; -++ struct ubi_vol_info vol_info; -++ int fd, ret; -++ char buf[20]; -++ -++ req.vol_id = UBI_VOL_NUM_AUTO; -++ req.alignment = 1; -++ req.bytes = dev_info.avail_bytes; -++ req.vol_type = UBI_STATIC_VOLUME; -++ req.name = name; -++ -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ return -1; -++ } -++ -++ sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num, req.vol_id); -++ -++ fd = open(vol_node, O_RDWR); -++ if (fd == -1) { -++ failed("open"); -++ err_msg("cannot open \"%s\"\n", node); -++ goto remove; -++ } -++ -++ if (ubi_get_vol_info(libubi, vol_node, &vol_info)) { -++ failed("ubi_get_vol_info"); -++ goto close; -++ } -++ -++ /* Make sure new static volume contains no data */ -++ if (vol_info.data_bytes != 0) { -++ err_msg("data_bytes = %lld, not zero", vol_info.data_bytes); -++ goto close; -++ } -++ -++ /* Ensure read returns EOF */ -++ ret = read(fd, buf, 1); -++ if (ret < 0) { -++ failed("read"); -++ goto close; -++ } -++ if (ret != 0) { -++ err_msg("read data from free static volume"); -++ goto close; -++ } -++ -++ if (ubi_update_start(libubi, fd, 10)) { -++ failed("ubi_update_start"); -++ goto close; -++ } -++ -++ ret = write(fd, buf, 10); -++ if (ret < 0) { -++ failed("write"); -++ goto close; -++ } -++ if (ret != 10) { -++ err_msg("written %d bytes", ret); -++ goto close; -++ } -++ -++ if (lseek(fd, 0, SEEK_SET) != 0) { -++ failed("seek"); -++ goto close; -++ } -++ ret = read(fd, buf, 20); -++ if (ret < 0) { -++ failed("read"); -++ goto close; -++ } -++ if (ret != 10) { -++ err_msg("read %d bytes", ret); -++ goto close; -++ } -++ -++ close(fd); -++ if (ubi_rmvol(libubi, node, req.vol_id)) { -++ failed("ubi_rmvol"); -++ return -1; -++ } -++ -++ return 0; -++ -++close: -++ close(fd); -++remove: -++ ubi_rmvol(libubi, node, req.vol_id); -++ return -1; -++} -++ -++/* -++ * A helper function for test_read2(). -++ */ -++static int test_read3(const struct ubi_vol_info *vol_info, int len, off_t off) -++{ -++ int i, len1; -++ unsigned char ck_buf[len], buf[len]; -++ off_t new_off; -++ -++ if (off + len > vol_info->data_bytes) -++ len1 = vol_info->data_bytes - off; -++ else -++ len1 = len; -++ -++ if (lseek(fd, off, SEEK_SET) != off) { -++ failed("seek"); -++ err_msg("len = %d", len); -++ return -1; -++ } -++ if (read(fd, buf, len) != len1) { -++ failed("read"); -++ err_msg("len = %d", len); -++ return -1; -++ } -++ -++ new_off = lseek(fd, 0, SEEK_CUR); -++ if (new_off != off + len1) { -++ if (new_off == -1) -++ failed("lseek"); -++ else -++ err_msg("read %d bytes from %lld, but resulting " -++ "offset is %lld", len1, (long long) off, (long long) new_off); -++ return -1; -++ } -++ -++ for (i = 0; i < len1; i++) -++ ck_buf[i] = (unsigned char)(off + i); -++ -++ if (memcmp(buf, ck_buf, len1)) { -++ err_msg("incorrect data read from offset %lld", -++ (long long)off); -++ err_msg("len = %d", len); -++ return -1; -++ } -++ -++ return 0; -++} -++ -++/* -++ * A helper function for test_read1(). -++ */ -++static int test_read2(const struct ubi_vol_info *vol_info, int len) -++{ -++ int i; -++ off_t offsets[] = OFFSETS(dev_info.min_io_size, vol_info->leb_size, -++ vol_info->data_bytes); -++ -++ for (i = 0; i < sizeof(offsets)/sizeof(off_t); i++) { -++ if (test_read3(vol_info, len, offsets[i])) { -++ err_msg("offset = %d", offsets[i]); -++ return -1; -++ } -++ } -++ -++ return 0; -++} -++ -++/* -++ * A helper function for test_read(). -++ */ -++static int test_read1(struct ubi_vol_info *vol_info) -++{ -++ int i, written = 0; -++ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100]; -++ int lengthes[] = LENGTHES(dev_info.min_io_size, vol_info->leb_size); -++ -++ sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num, -++ vol_info->vol_id); -++ -++ fd = open(vol_node, O_RDWR); -++ if (fd == -1) { -++ failed("open"); -++ err_msg("cannot open \"%s\"\n", node); -++ return -1; -++ } -++ -++ /* Write some pattern to the volume */ -++ if (ubi_update_start(libubi, fd, vol_info->rsvd_bytes)) { -++ failed("ubi_update_start"); -++ err_msg("bytes = %lld", vol_info->rsvd_bytes); -++ goto close; -++ } -++ -++ while (written < vol_info->rsvd_bytes) { -++ int i, ret; -++ unsigned char buf[512]; -++ -++ for (i = 0; i < 512; i++) -++ buf[i] = (unsigned char)(written + i); -++ -++ ret = write(fd, buf, 512); -++ if (ret == -1) { -++ failed("write"); -++ err_msg("written = %d, ret = %d", written, ret); -++ goto close; -++ } -++ written += ret; -++ } -++ -++ close(fd); -++ -++ if (ubi_get_vol_info(libubi, vol_node, vol_info)) { -++ failed("ubi_get_vol_info"); -++ return -1; -++ } -++ -++ fd = open(vol_node, O_RDONLY); -++ if (fd == -1) { -++ failed("open"); -++ err_msg("cannot open \"%s\"\n", node); -++ return -1; -++ } -++ -++ for (i = 0; i < sizeof(lengthes)/sizeof(int); i++) { -++ if (test_read2(vol_info, lengthes[i])) { -++ err_msg("length = %d", lengthes[i]); -++ goto close; -++ } -++ } -++ -++ close(fd); -++ return 0; -++ -++close: -++ close(fd); -++ return -1; -++} -++ -++/** -++ * test_read - test UBI volume reading from different offsets. -++ * -++ * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) -++ * -++ * Thus function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int test_read(int type) -++{ -++ const char *name = TESTNAME ":test_read()"; -++ int alignments[] = ALIGNMENTS(dev_info.leb_size); -++ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100]; -++ struct ubi_mkvol_request req; -++ int i; -++ -++ for (i = 0; i < sizeof(alignments)/sizeof(int); i++) { -++ int leb_size; -++ struct ubi_vol_info vol_info; -++ -++ req.vol_id = UBI_VOL_NUM_AUTO; -++ req.vol_type = type; -++ req.name = name; -++ -++ req.alignment = alignments[i]; -++ req.alignment -= req.alignment % dev_info.min_io_size; -++ if (req.alignment == 0) -++ req.alignment = dev_info.min_io_size; -++ -++ leb_size = dev_info.leb_size - dev_info.leb_size % req.alignment; -++ req.bytes = MIN_AVAIL_EBS * leb_size; -++ -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ return -1; -++ } -++ -++ sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num, -++ req.vol_id); -++ -++ if (ubi_get_vol_info(libubi, vol_node, &vol_info)) { -++ failed("ubi_get_vol_info"); -++ goto remove; -++ } -++ -++ if (test_read1(&vol_info)) { -++ err_msg("alignment = %d", req.alignment); -++ goto remove; -++ } -++ -++ if (ubi_rmvol(libubi, node, req.vol_id)) { -++ failed("ubi_rmvol"); -++ return -1; -++ } -++ } -++ -++ return 0; -++ -++remove: -++ ubi_rmvol(libubi, node, req.vol_id); -++ return -1; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ if (initial_check(argc, argv)) -++ return 1; -++ -++ node = argv[1]; -++ -++ libubi = libubi_open(); -++ if (libubi == NULL) { -++ failed("libubi_open"); -++ return 1; -++ } -++ -++ if (ubi_get_dev_info(libubi, node, &dev_info)) { -++ failed("ubi_get_dev_info"); -++ goto close; -++ } -++ -++ if (test_static()) -++ goto close; -++ if (test_read(UBI_DYNAMIC_VOLUME)) -++ goto close; -++ if (test_read(UBI_STATIC_VOLUME)) -++ goto close; -++ -++ libubi_close(libubi); -++ return 0; -++ -++close: -++ libubi_close(libubi); -++ return 1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/io_update.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/io_update.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/io_update.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/io_update.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,298 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem B. Bityutskiy -++ * -++ * Test UBI volume update and atomic LEB change -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#define TESTNAME "io_update" -++#include "common.h" -++ -++static libubi_t libubi; -++static struct ubi_dev_info dev_info; -++const char *node; -++ -++#define SEQUENCES(io, s) { \ -++ {3*(s)-(io)-1, 1}, \ -++ {512}, \ -++ {666}, \ -++ {2048}, \ -++ {(io), (io), PAGE_SIZE}, \ -++ {(io)+1, (io)+1, PAGE_SIZE}, \ -++ {PAGE_SIZE}, \ -++ {PAGE_SIZE-1}, \ -++ {PAGE_SIZE+(io)}, \ -++ {(s)}, \ -++ {(s)-1}, \ -++ {(s)+1}, \ -++ {(io), (s)+1}, \ -++ {(s)+(io), PAGE_SIZE}, \ -++ {2*(s), PAGE_SIZE}, \ -++ {PAGE_SIZE, 2*(s), 1}, \ -++ {PAGE_SIZE, 2*(s)}, \ -++ {2*(s)-1, 2*(s)-1}, \ -++ {3*(s), PAGE_SIZE + 1}, \ -++ {1, PAGE_SIZE}, \ -++ {(io), (s)} \ -++} -++ -++#define SEQ_SZ 21 -++ -++/* -++ * test_update1 - helper function for test_update(). -++ */ -++static int test_update1(struct ubi_vol_info *vol_info, int leb_change) -++{ -++ long long total_len = leb_change ? vol_info->leb_size -++ : vol_info->rsvd_bytes; -++ int sequences[SEQ_SZ][3] = SEQUENCES(dev_info.min_io_size, -++ leb_change ? dev_info.min_io_size * 2 -++ : vol_info->leb_size); -++ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100]; -++ unsigned char buf[total_len]; -++ int fd, i, j; -++ -++ sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num, -++ vol_info->vol_id); -++ -++ fd = open(vol_node, O_RDWR); -++ if (fd == -1) { -++ failed("open"); -++ err_msg("cannot open \"%s\"\n", node); -++ return -1; -++ } -++ -++ for (i = 0; i < SEQ_SZ; i++) { -++ int ret, stop = 0, len = 0; -++ off_t off = 0; -++ long long test_len; -++ unsigned char buf1[total_len]; -++ -++ /* -++ * test_len is LEB size (if we test atomic LEB change) or -++ * volume size (if we test update). For better test coverage, -++ * use a little smaller LEB change/update length. -++ */ -++ test_len = total_len - (rand() % (total_len / 10)); -++ -++ if (leb_change) { -++ if (ubi_leb_change_start(libubi, fd, 0, test_len, -++ UBI_SHORTTERM)) { -++ failed("ubi_update_start"); -++ goto close; -++ } -++ } else { -++ if (ubi_update_start(libubi, fd, test_len)) { -++ failed("ubi_update_start"); -++ goto close; -++ } -++ } -++ -++ for (j = 0; off < test_len; j++) { -++ int n, rnd_len, l; -++ -++ if (!stop) { -++ if (sequences[i][j] != 0) -++ l = len = sequences[i][j]; -++ else -++ stop = 1; -++ } -++ -++ /* -++ * Fill some part of the write buffer with random data, -++ * and the other part with 0xFFs to test how UBI -++ * stripes 0xFFs multiple of I/O unit size. -++ */ -++ if (off + l > test_len) -++ l = test_len - off; -++ rnd_len = rand() % (l + 1); -++ for (n = 0; n < rnd_len; n++) -++ buf[off + n] = (unsigned char)rand(); -++ memset(buf + off + rnd_len, 0xFF, l - rnd_len); -++ -++ /* -++ * Deliberately pass len instead of l (len may be -++ * greater then l if this is the last chunk) because -++ * UBI have to read only l bytes anyway. -++ */ -++ ret = write(fd, buf + off, len); -++ if (ret < 0) { -++ failed("write"); -++ err_msg("failed to write %d bytes at offset " -++ "%lld", len, (long long)off); -++ goto close; -++ } -++ len = l; -++ if (ret != len) { -++ err_msg("failed to write %d bytes at offset " -++ "%lld, wrote %d", len, (long long)off, ret); -++ goto close; -++ } -++ off += len; -++ } -++ -++ /* Check data */ -++ if ((ret = lseek(fd, SEEK_SET, 0)) != 0) { -++ failed("lseek"); -++ err_msg("cannot seek to 0"); -++ goto close; -++ } -++ -++ memset(buf1, 0x01, test_len); -++ -++ if (vol_info->type == UBI_STATIC_VOLUME) -++ /* -++ * Static volume must not let use read more then it -++ * contains. -++ */ -++ ret = read(fd, buf1, test_len + 100); -++ else -++ ret = read(fd, buf1, test_len); -++ if (ret < 0) { -++ failed("read"); -++ err_msg("failed to read %d bytes", test_len); -++ goto close; -++ } -++ if (ret != test_len) { -++ err_msg("failed to read %d bytes, read %d", test_len, ret); -++ goto close; -++ } -++ if (memcmp(buf, buf1, test_len)) { -++ err_msg("data corruption"); -++ goto close; -++ } -++ } -++ -++ close(fd); -++ return 0; -++ -++close: -++ close(fd); -++ return -1; -++} -++ -++/** -++ * test_update - check volume update and atomic LEB change capabilities. -++ * -++ * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) -++ * -++ * This function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int test_update(int type) -++{ -++ struct ubi_mkvol_request req; -++ const char *name = TESTNAME ":io_update()"; -++ int alignments[] = ALIGNMENTS(dev_info.leb_size); -++ struct ubi_vol_info vol_info; -++ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100]; -++ int i; -++ -++ for (i = 0; i < sizeof(alignments)/sizeof(int); i++) { -++ int leb_size; -++ -++ req.vol_id = UBI_VOL_NUM_AUTO; -++ req.vol_type = type; -++ req.name = name; -++ -++ req.alignment = alignments[i]; -++ req.alignment -= req.alignment % dev_info.min_io_size; -++ if (req.alignment == 0) -++ req.alignment = dev_info.min_io_size; -++ -++ leb_size = dev_info.leb_size - dev_info.leb_size % req.alignment; -++ req.bytes = MIN_AVAIL_EBS * leb_size; -++ -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ return -1; -++ } -++ -++ sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num, -++ req.vol_id); -++ if (ubi_get_vol_info(libubi, vol_node, &vol_info)) { -++ failed("ubi_get_vol_info"); -++ goto remove; -++ } -++ -++ if (test_update1(&vol_info, 0)) { -++ err_msg("alignment = %d", req.alignment); -++ goto remove; -++ } -++ -++ if (vol_info.type != UBI_STATIC_VOLUME) { -++ if (test_update1(&vol_info, 1)) { -++ err_msg("alignment = %d", req.alignment); -++ goto remove; -++ } -++ } -++ -++ if (ubi_rmvol(libubi, node, req.vol_id)) { -++ failed("ubi_rmvol"); -++ return -1; -++ } -++ } -++ -++ return 0; -++ -++remove: -++ ubi_rmvol(libubi, node, req.vol_id); -++ return -1; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ if (initial_check(argc, argv)) -++ return 1; -++ -++ node = argv[1]; -++ -++ libubi = libubi_open(); -++ if (libubi == NULL) { -++ failed("libubi_open"); -++ return 1; -++ } -++ -++ if (ubi_get_dev_info(libubi, node, &dev_info)) { -++ failed("ubi_get_dev_info"); -++ goto close; -++ } -++ -++ if (test_update(UBI_DYNAMIC_VOLUME)) -++ goto close; -++ if (test_update(UBI_STATIC_VOLUME)) -++ goto close; -++ -++ libubi_close(libubi); -++ return 0; -++ -++close: -++ libubi_close(libubi); -++ return 1; -++} -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/mkvol_bad.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/mkvol_bad.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/mkvol_bad.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/mkvol_bad.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,301 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem B. Bityutskiy -++ * -++ * Test UBI volume creation and deletion ioctl()s with bad input and in case of -++ * incorrect usage. -++ */ -++ -++#include -++#include -++#include -++#include "libubi.h" -++#define TESTNAME "mkvol_bad" -++#include "common.h" -++ -++static libubi_t libubi; -++static struct ubi_dev_info dev_info; -++const char *node; -++ -++/** -++ * test_mkvol - test that UBI mkvol ioctl rejects bad input parameters. -++ * -++ * This function returns %0 if the test passed and %-1 if not. -++ */ -++static int test_mkvol(void) -++{ -++ int ret, i; -++ struct ubi_mkvol_request req; -++ const char *name = TESTNAME ":test_mkvol()"; -++ -++ req.alignment = 1; -++ req.bytes = dev_info.avail_bytes; -++ req.vol_type = UBI_DYNAMIC_VOLUME; -++ req.name = name; -++ -++ /* Bad volume ID */ -++ req.vol_id = -2; -++ ret = ubi_mkvol(libubi, node, &req); -++ if (check_failed(ret, EINVAL, "ubi_mkvol", "vol_id = %d", req.vol_id)) -++ return -1; -++ -++ req.vol_id = dev_info.max_vol_count; -++ ret = ubi_mkvol(libubi, node, &req); -++ if (check_failed(ret, EINVAL, "ubi_mkvol", "vol_id = %d", req.vol_id)) -++ return -1; -++ -++ /* Bad alignment */ -++ req.vol_id = 0; -++ req.alignment = 0; -++ ret = ubi_mkvol(libubi, node, &req); -++ if (check_failed(ret, EINVAL, "ubi_mkvol", "alignment = %d", -++ req.alignment)) -++ return -1; -++ -++ req.alignment = -1; -++ ret = ubi_mkvol(libubi, node, &req); -++ if (check_failed(ret, EINVAL, "ubi_mkvol", "alignment = %d", -++ req.alignment)) -++ return -1; -++ -++ req.alignment = dev_info.leb_size + 1; -++ ret = ubi_mkvol(libubi, node, &req); -++ if (check_failed(ret, EINVAL, "ubi_mkvol", "alignment = %d", -++ req.alignment)) -++ return -1; -++ -++ if (dev_info.min_io_size > 1) { -++ req.alignment = dev_info.min_io_size + 1; -++ ret = ubi_mkvol(libubi, node, &req); -++ if (check_failed(ret, EINVAL, "ubi_mkvol", "alignment = %d", -++ req.alignment)) -++ return -1; -++ } -++ -++ /* Bad bytes */ -++ req.alignment = 1; -++ req.bytes = -1; -++ ret = ubi_mkvol(libubi, node, &req); -++ if (check_failed(ret, EINVAL, "ubi_mkvol", "bytes = %lld", req.bytes)) -++ return -1; -++ -++ req.bytes = 0; -++ ret = ubi_mkvol(libubi, node, &req); -++ if (check_failed(ret, EINVAL, "ubi_mkvol", "bytes = %lld", req.bytes)) -++ return -1; -++ -++ req.bytes = dev_info.avail_bytes + 1; -++ ret = ubi_mkvol(libubi, node, &req); -++ if (check_failed(ret, ENOSPC, "ubi_mkvol", "bytes = %lld", req.bytes)) -++ return -1; -++ -++ req.alignment = dev_info.leb_size - dev_info.min_io_size; -++ req.bytes = (dev_info.leb_size - dev_info.leb_size % req.alignment) * -++ dev_info.avail_lebs + 1; -++ ret = ubi_mkvol(libubi, node, &req); -++ if (check_failed(ret, ENOSPC, "ubi_mkvol", "bytes = %lld", req.bytes)) -++ return -1; -++ -++ /* Bad vol_type */ -++ req.alignment = 1; -++ req.bytes = dev_info.leb_size; -++ req.vol_type = UBI_DYNAMIC_VOLUME + UBI_STATIC_VOLUME; -++ ret = ubi_mkvol(libubi, node, &req); -++ if (check_failed(ret, EINVAL, "ubi_mkvol", "vol_type = %d", -++ req.vol_type)) -++ return -1; -++ -++ req.vol_type = UBI_DYNAMIC_VOLUME; -++ -++ /* Too long name */ -++ { -++ char name[UBI_VOL_NAME_MAX + 5]; -++ -++ memset(name, 'x', UBI_VOL_NAME_MAX + 1); -++ name[UBI_VOL_NAME_MAX + 1] = '\0'; -++ -++ req.name = name; -++ ret = ubi_mkvol(libubi, node, &req); -++ if (check_failed(ret, EINVAL, "ubi_mkvol", "name_len = %d", -++ UBI_VOL_NAME_MAX + 1)) -++ return -1; -++ } -++ -++ /* Try to create 2 volumes with the same ID and name */ -++ req.name = name; -++ req.vol_id = 0; -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ return -1; -++ } -++ -++ ret = ubi_mkvol(libubi, node, &req); -++ if (check_failed(ret, EEXIST, "ubi_mkvol", -++ "volume with ID 0 created twice")) -++ return -1; -++ -++ req.vol_id = 1; -++ ret = ubi_mkvol(libubi, node, &req); -++ if (check_failed(ret, EEXIST, "ubi_mkvol", -++ "volume with name \"%s\" created twice", name)) -++ return -1; -++ -++ if (ubi_rmvol(libubi, node, 0)) { -++ failed("ubi_rmvol"); -++ return -1; -++ } -++ -++ /* Try to use too much space */ -++ req.vol_id = 0; -++ req.bytes = dev_info.avail_bytes; -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ return -1; -++ } -++ -++ req.bytes = 1; -++ req.vol_id = 1; -++ ret = ubi_mkvol(libubi, node, &req); -++ if (check_failed(ret, EEXIST, "ubi_mkvol", -++ "created volume of maximum size %lld, but still " -++ "can create more volumes", dev_info.avail_bytes)) -++ return -1; -++ -++ if (ubi_rmvol(libubi, node, 0)) { -++ failed("ubi_rmvol"); -++ return -1; -++ } -++ -++ /* Try to create too many volumes */ -++ for (i = 0; i < dev_info.max_vol_count; i++) { -++ char nm[strlen(name) + 50]; -++ -++ req.vol_id = UBI_VOL_NUM_AUTO; -++ req.alignment = 1; -++ req.bytes = 1; -++ req.vol_type = UBI_STATIC_VOLUME; -++ -++ sprintf(nm, "%s:%d", name, i); -++ req.name = nm; -++ -++ if (ubi_mkvol(libubi, node, &req)) { -++ /* -++ * Note, because of gluebi we may be unable to create -++ * dev_info.max_vol_count devices (MTD restrictions). -++ */ -++ if (errno == ENFILE) -++ break; -++ failed("ubi_mkvol"); -++ err_msg("vol_id %d", i); -++ goto remove; -++ } -++ } -++ -++ for (i = 0; i < dev_info.max_vol_count + 1; i++) -++ ubi_rmvol(libubi, node, i); -++ -++ return 0; -++ -++remove: -++ for (i = 0; i < dev_info.max_vol_count + 1; i++) -++ ubi_rmvol(libubi, node, i); -++ return -1; -++} -++ -++/** -++ * test_rmvol - test that UBI rmvol ioctl rejects bad input parameters. -++ * -++ * This function returns %0 if the test passed and %-1 if not. -++ */ -++static int test_rmvol(void) -++{ -++ int ret; -++ struct ubi_mkvol_request req; -++ const char *name = TESTNAME ":test_rmvol()"; -++ -++ /* Bad vol_id */ -++ ret = ubi_rmvol(libubi, node, -1); -++ if (check_failed(ret, EINVAL, "ubi_rmvol", "vol_id = -1")) -++ return -1; -++ -++ ret = ubi_rmvol(libubi, node, dev_info.max_vol_count); -++ if (check_failed(ret, EINVAL, "ubi_rmvol", "vol_id = %d", -++ dev_info.max_vol_count)) -++ return -1; -++ -++ /* Try to remove non-existing volume */ -++ ret = ubi_rmvol(libubi, node, 0); -++ if (check_failed(ret, ENODEV, "ubi_rmvol", -++ "removed non-existing volume 0")) -++ return -1; -++ -++ /* Try to remove volume twice */ -++ req.vol_id = UBI_VOL_NUM_AUTO; -++ req.alignment = 1; -++ req.bytes = dev_info.avail_bytes; -++ req.vol_type = UBI_DYNAMIC_VOLUME; -++ req.name = name; -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ return -1; -++ } -++ -++ if (ubi_rmvol(libubi, node, req.vol_id)) { -++ failed("ubi_rmvol"); -++ return -1; -++ } -++ -++ ret = ubi_rmvol(libubi, node, req.vol_id); -++ if (check_failed(ret, ENODEV, "ubi_rmvol", "volume %d removed twice", -++ req.vol_id)) -++ return -1; -++ -++ return 0; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ if (initial_check(argc, argv)) -++ return 1; -++ -++ node = argv[1]; -++ -++ libubi = libubi_open(); -++ if (libubi == NULL) { -++ failed("libubi_open"); -++ return 1; -++ } -++ -++ if (ubi_get_dev_info(libubi, node, &dev_info)) { -++ failed("ubi_get_dev_info"); -++ goto close; -++ } -++ -++ if (test_mkvol()) -++ goto close; -++ -++ if (test_rmvol()) -++ goto close; -++ -++ libubi_close(libubi); -++ return 0; -++ -++close: -++ libubi_close(libubi); -++ return 1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/mkvol_basic.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/mkvol_basic.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/mkvol_basic.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/mkvol_basic.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,250 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem B. Bityutskiy -++ * -++ * Test test checks basic volume creation and deletion capabilities. -++ */ -++ -++#include -++#include -++#include -++#include "libubi.h" -++#define TESTNAME "mkvol_basic" -++#include "common.h" -++ -++static libubi_t libubi; -++static struct ubi_dev_info dev_info; -++const char *node; -++ -++/** -++ * mkvol_alignment - create volumes with different alignments. -++ * -++ * Thus function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int mkvol_alignment(void) -++{ -++ struct ubi_mkvol_request req; -++ int i, vol_id, ebsz; -++ const char *name = TESTNAME ":mkvol_alignment()"; -++ int alignments[] = ALIGNMENTS(dev_info.leb_size); -++ -++ for (i = 0; i < sizeof(alignments)/sizeof(int); i++) { -++ req.vol_id = UBI_VOL_NUM_AUTO; -++ -++ /* Alignment should actually be multiple of min. I/O size */ -++ req.alignment = alignments[i]; -++ req.alignment -= req.alignment % dev_info.min_io_size; -++ if (req.alignment == 0) -++ req.alignment = dev_info.min_io_size; -++ -++ /* Bear in mind alignment reduces EB size */ -++ ebsz = dev_info.leb_size - dev_info.leb_size % req.alignment; -++ req.bytes = dev_info.avail_lebs * ebsz; -++ -++ req.vol_type = UBI_DYNAMIC_VOLUME; -++ req.name = name; -++ -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ err_msg("alignment %d", req.alignment); -++ return -1; -++ } -++ -++ vol_id = req.vol_id; -++ if (check_volume(vol_id, &req)) -++ goto remove; -++ -++ if (ubi_rmvol(libubi, node, vol_id)) { -++ failed("ubi_rmvol"); -++ return -1; -++ } -++ } -++ -++ return 0; -++ -++remove: -++ ubi_rmvol(libubi, node, vol_id); -++ return -1; -++} -++ -++/** -++ * mkvol_basic - simple test that checks basic volume creation capability. -++ * -++ * Thus function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int mkvol_basic(void) -++{ -++ struct ubi_mkvol_request req; -++ struct ubi_vol_info vol_info; -++ int vol_id, ret; -++ const char *name = TESTNAME ":mkvol_basic()"; -++ -++ /* Create dynamic volume of maximum size */ -++ req.vol_id = UBI_VOL_NUM_AUTO; -++ req.alignment = 1; -++ req.bytes = dev_info.avail_bytes; -++ req.vol_type = UBI_DYNAMIC_VOLUME; -++ req.name = name; -++ -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ return -1; -++ } -++ -++ vol_id = req.vol_id; -++ if (check_volume(vol_id, &req)) -++ goto remove; -++ -++ if (ubi_rmvol(libubi, node, vol_id)) { -++ failed("ubi_rmvol"); -++ return -1; -++ } -++ -++ /* Create static volume of maximum size */ -++ req.vol_id = UBI_VOL_NUM_AUTO; -++ req.alignment = 1; -++ req.bytes = dev_info.avail_bytes; -++ req.vol_type = UBI_STATIC_VOLUME; -++ req.name = name; -++ -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ return -1; -++ } -++ -++ vol_id = req.vol_id; -++ if (check_volume(vol_id, &req)) -++ goto remove; -++ -++ if (ubi_rmvol(libubi, node, vol_id)) { -++ failed("ubi_rmvol"); -++ return -1; -++ } -++ -++ /* Make sure volume does not exist */ -++ ret = ubi_get_vol_info1(libubi, dev_info.dev_num, vol_id, &vol_info); -++ if (ret == 0) { -++ err_msg("removed volume %d exists", vol_id); -++ goto remove; -++ } -++ -++ return 0; -++ -++remove: -++ ubi_rmvol(libubi, node, vol_id); -++ return -1; -++} -++ -++/** -++ * mkvol_multiple - test multiple volumes creation -++ * -++ * Thus function returns %0 if the test passed and %-1 if not. -++ */ -++static int mkvol_multiple(void) -++{ -++ struct ubi_mkvol_request req; -++ int i, ret, max = dev_info.max_vol_count; -++ const char *name = TESTNAME ":mkvol_multiple()"; -++ -++ /* Create maximum number of volumes */ -++ for (i = 0; i < max; i++) { -++ char nm[strlen(name) + 50]; -++ -++ req.vol_id = UBI_VOL_NUM_AUTO; -++ req.alignment = 1; -++ req.bytes = 1; -++ req.vol_type = UBI_STATIC_VOLUME; -++ -++ sprintf(nm, "%s:%d", name, i); -++ req.name = nm; -++ -++ if (ubi_mkvol(libubi, node, &req)) { -++ if (errno == ENFILE) { -++ max = i; -++ break; -++ } -++ failed("ubi_mkvol"); -++ err_msg("vol_id %d", i); -++ goto remove; -++ } -++ -++ if (check_volume(req.vol_id, &req)) { -++ err_msg("vol_id %d", i); -++ goto remove; -++ } -++ } -++ -++ for (i = 0; i < max; i++) { -++ struct ubi_vol_info vol_info; -++ -++ if (ubi_rmvol(libubi, node, i)) { -++ failed("ubi_rmvol"); -++ return -1; -++ } -++ -++ /* Make sure volume does not exist */ -++ ret = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info); -++ if (ret == 0) { -++ err_msg("removed volume %d exists", i); -++ goto remove; -++ } -++ } -++ -++ return 0; -++ -++remove: -++ for (i = 0; i < dev_info.max_vol_count + 1; i++) -++ ubi_rmvol(libubi, node, i); -++ return -1; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ if (initial_check(argc, argv)) -++ return 1; -++ -++ node = argv[1]; -++ -++ libubi = libubi_open(); -++ if (libubi == NULL) { -++ failed("libubi_open"); -++ return 1; -++ } -++ -++ if (ubi_get_dev_info(libubi, node, &dev_info)) { -++ failed("ubi_get_dev_info"); -++ goto close; -++ } -++ -++ if (mkvol_basic()) -++ goto close; -++ -++ if (mkvol_alignment()) -++ goto close; -++ -++ if (mkvol_multiple()) -++ goto close; -++ -++ libubi_close(libubi); -++ return 0; -++ -++close: -++ libubi_close(libubi); -++ return 1; -++} -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/mkvol_paral.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/mkvol_paral.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/mkvol_paral.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/mkvol_paral.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,110 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem B. Bityutskiy -++ * -++ * This test creates and deletes volumes in parallel. -++ */ -++ -++#include -++#include -++#include -++#include -++#include "libubi.h" -++#define TESTNAME "mkvol_paral" -++#include "common.h" -++ -++#define THREADS_NUM 4 -++#define ITERATIONS 500 -++ -++static libubi_t libubi; -++static struct ubi_dev_info dev_info; -++const char *node; -++static int iterations = ITERATIONS; -++ -++/** -++ * the_thread - the testing thread. -++ * -++ * @ptr thread number -++ */ -++static void * the_thread(void *ptr) -++{ -++ int n = (int)ptr, iter = iterations; -++ struct ubi_mkvol_request req; -++ const char *name = TESTNAME ":the_thread()"; -++ char nm[strlen(name) + 50]; -++ -++ req.alignment = 1; -++ req.bytes = dev_info.avail_bytes/ITERATIONS; -++ req.vol_type = UBI_DYNAMIC_VOLUME; -++ sprintf(nm, "%s:%d", name, n); -++ req.name = nm; -++ -++ while (iter--) { -++ req.vol_id = UBI_VOL_NUM_AUTO; -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ return NULL; -++ } -++ if (ubi_rmvol(libubi, node, req.vol_id)) { -++ failed("ubi_rmvol"); -++ return NULL; -++ } -++ } -++ -++ return NULL; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ int i, ret; -++ pthread_t threads[THREADS_NUM]; -++ -++ if (initial_check(argc, argv)) -++ return 1; -++ -++ node = argv[1]; -++ -++ libubi = libubi_open(); -++ if (libubi == NULL) { -++ failed("libubi_open"); -++ return 1; -++ } -++ -++ if (ubi_get_dev_info(libubi, node, &dev_info)) { -++ failed("ubi_get_dev_info"); -++ goto close; -++ } -++ -++ for (i = 0; i < THREADS_NUM; i++) { -++ ret = pthread_create(&threads[i], NULL, &the_thread, (void*)i); -++ if (ret) { -++ failed("pthread_create"); -++ goto close; -++ } -++ } -++ -++ for (i = 0; i < THREADS_NUM; i++) -++ pthread_join(threads[i], NULL); -++ -++ libubi_close(libubi); -++ return 0; -++ -++close: -++ libubi_close(libubi); -++ return 1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/rsvol.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/rsvol.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/rsvol.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/rsvol.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,305 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem B. Bityutskiy -++ * -++ * Tes UBI volume re-size. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "libubi.h" -++#define TESTNAME "rsvol" -++#include "common.h" -++ -++static libubi_t libubi; -++static struct ubi_dev_info dev_info; -++const char *node; -++ -++/** -++ * test_basic - check volume re-size capability. -++ * -++ * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) -++ * -++ * Thus function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int test_basic(int type) -++{ -++ struct ubi_mkvol_request req; -++ const char *name = TESTNAME ":test_basic()"; -++ -++ req.vol_id = UBI_VOL_NUM_AUTO; -++ req.alignment = 1; -++ req.bytes = MIN_AVAIL_EBS * dev_info.leb_size; -++ req.vol_type = type; -++ req.name = name; -++ -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ return -1; -++ } -++ -++ req.bytes = dev_info.leb_size; -++ if (ubi_rsvol(libubi, node, req.vol_id, req.bytes)) { -++ failed("ubi_rsvol"); -++ goto remove; -++ } -++ -++ if (check_volume(req.vol_id, &req)) -++ goto remove; -++ -++ req.bytes = (MIN_AVAIL_EBS + 1) * dev_info.leb_size; -++ if (ubi_rsvol(libubi, node, req.vol_id, req.bytes)) { -++ failed("ubi_rsvol"); -++ goto remove; -++ } -++ -++ if (check_volume(req.vol_id, &req)) -++ goto remove; -++ -++ req.bytes -= 1; -++ if (ubi_rsvol(libubi, node, req.vol_id, req.bytes)) { -++ failed("ubi_rsvol"); -++ goto remove; -++ } -++ -++ if (check_volume(req.vol_id, &req)) -++ goto remove; -++ -++ if (ubi_rmvol(libubi, node, req.vol_id)) { -++ failed("ubi_rmvol"); -++ return -1; -++ } -++ -++ return 0; -++ -++remove: -++ ubi_rmvol(libubi, node, req.vol_id); -++ return -1; -++} -++ -++/* -++ * Helper function for test_rsvol(). -++ */ -++static int test_rsvol1(struct ubi_vol_info *vol_info) -++{ -++ long long bytes; -++ struct ubi_vol_info vol_info1; -++ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100]; -++ unsigned char buf[vol_info->rsvd_bytes]; -++ int fd, i, ret; -++ -++ /* Make the volume smaller and check basic volume I/O */ -++ bytes = vol_info->rsvd_bytes - vol_info->leb_size; -++ if (ubi_rsvol(libubi, node, vol_info->vol_id, bytes - 1)) { -++ failed("ubi_rsvol"); -++ return -1; -++ } -++ -++ if (ubi_get_vol_info1(libubi, vol_info->dev_num, vol_info->vol_id, -++ &vol_info1)) { -++ failed("ubi_get_vol_info"); -++ return -1; -++ } -++ -++ if (vol_info1.rsvd_bytes != bytes) { -++ err_msg("rsvd_bytes %lld, must be %lld", -++ vol_info1.rsvd_bytes, bytes); -++ return -1; -++ } -++ -++ if (vol_info1.rsvd_lebs != vol_info->rsvd_lebs - 1) { -++ err_msg("rsvd_lebs %d, must be %d", -++ vol_info1.rsvd_lebs, vol_info->rsvd_lebs - 1); -++ return -1; -++ } -++ -++ /* Write data to the volume */ -++ sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num, -++ vol_info->vol_id); -++ -++ fd = open(vol_node, O_RDWR); -++ if (fd == -1) { -++ failed("open"); -++ err_msg("cannot open \"%s\"\n", vol_node); -++ return -1; -++ } -++ -++ bytes = vol_info->rsvd_bytes - vol_info->leb_size - 1; -++ if (ubi_update_start(libubi, fd, bytes)) { -++ failed("ubi_update_start"); -++ goto close; -++ } -++ -++ for (i = 0; i < bytes; i++) -++ buf[i] = (unsigned char)i; -++ -++ ret = write(fd, buf, bytes); -++ if (ret != bytes) { -++ failed("write"); -++ goto close; -++ } -++ -++ close(fd); -++ -++ if (ubi_rsvol(libubi, node, vol_info->vol_id, bytes)) { -++ failed("ubi_rsvol"); -++ return -1; -++ } -++ -++ if (ubi_rsvol(libubi, node, vol_info->vol_id, -++ vol_info->leb_size * dev_info.avail_lebs)) { -++ failed("ubi_rsvol"); -++ return -1; -++ } -++ -++ fd = open(vol_node, O_RDWR); -++ if (fd == -1) { -++ failed("open"); -++ err_msg("cannot open \"%s\"\n", vol_node); -++ return -1; -++ } -++ -++ /* Read data back */ -++ if (lseek(fd, 0, SEEK_SET) != 0) { -++ failed("seek"); -++ goto close; -++ } -++ memset(buf, 0, bytes); -++ ret = read(fd, buf, bytes); -++ if (ret != bytes) { -++ failed("read"); -++ goto close; -++ } -++ -++ for (i = 0; i < bytes; i++) { -++ if (buf[i] != (unsigned char)i) { -++ err_msg("bad data"); -++ goto close; -++ } -++ } -++ -++ close(fd); -++ return 0; -++ -++close: -++ close(fd); -++ return -1; -++} -++ -++/** -++ * test_rsvol - test UBI volume re-size. -++ * -++ * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) -++ * -++ * Thus function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int test_rsvol(int type) -++{ -++ const char *name = TESTNAME "test_rsvol:()"; -++ int alignments[] = ALIGNMENTS(dev_info.leb_size); -++ char vol_node[strlen(UBI_VOLUME_PATTERN) + 100]; -++ struct ubi_mkvol_request req; -++ int i; -++ -++ for (i = 0; i < sizeof(alignments)/sizeof(int); i++) { -++ int leb_size; -++ struct ubi_vol_info vol_info; -++ -++ req.vol_id = UBI_VOL_NUM_AUTO; -++ req.vol_type = type; -++ req.name = name; -++ -++ req.alignment = alignments[i]; -++ req.alignment -= req.alignment % dev_info.min_io_size; -++ if (req.alignment == 0) -++ req.alignment = dev_info.min_io_size; -++ -++ leb_size = dev_info.leb_size - dev_info.leb_size % req.alignment; -++ req.bytes = MIN_AVAIL_EBS * leb_size; -++ -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ return -1; -++ } -++ -++ sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num, -++ req.vol_id); -++ -++ if (ubi_get_vol_info(libubi, vol_node, &vol_info)) { -++ failed("ubi_get_vol_info"); -++ goto remove; -++ } -++ -++ if (test_rsvol1(&vol_info)) { -++ err_msg("alignment = %d", req.alignment); -++ goto remove; -++ } -++ -++ if (ubi_rmvol(libubi, node, req.vol_id)) { -++ failed("ubi_rmvol"); -++ return -1; -++ } -++ } -++ -++ return 0; -++ -++remove: -++ ubi_rmvol(libubi, node, req.vol_id); -++ return -1; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ if (initial_check(argc, argv)) -++ return 1; -++ -++ node = argv[1]; -++ -++ libubi = libubi_open(); -++ if (libubi == NULL) { -++ failed("libubi_open"); -++ return 1; -++ } -++ -++ if (ubi_get_dev_info(libubi, node, &dev_info)) { -++ failed("ubi_get_dev_info"); -++ goto close; -++ } -++ -++ if (test_basic(UBI_DYNAMIC_VOLUME)) -++ goto close; -++ if (test_basic(UBI_STATIC_VOLUME)) -++ goto close; -++ if (test_rsvol(UBI_DYNAMIC_VOLUME)) -++ goto close; -++ if (test_rsvol(UBI_STATIC_VOLUME)) -++ goto close; -++ -++ libubi_close(libubi); -++ return 0; -++ -++close: -++ libubi_close(libubi); -++ return 1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/runtests.sh linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/runtests.sh -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/runtests.sh 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/runtests.sh 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,39 @@ -++#!/bin/sh -++ -++ubidev="$1" -++tests="mkvol_basic mkvol_bad mkvol_paral rsvol io_basic io_read io_update -++io_paral volrefcnt" -++ -++if test -z "$ubidev"; -++then -++ echo "Usage:" -++ echo "$0 " -++ exit 1 -++fi -++ -++ubiname=`echo $ubidev | cut -d/ -f3` -++ -++major=`cat /sys/class/ubi/$ubiname/dev | cut -d: -f1` -++ -++for minor in `seq 0 4`; do -++ if test ! -e ${ubidev}_${minor} ; -++ then -++ mknod ${ubidev}_${minor} c $major $(($minor + 1)) -++ fi -++done -++ -++if ! test -c "$ubidev"; -++then -++ echo "Error: $ubidev is not character device" -++ exit 1 -++fi -++ -++for t in `echo $tests`; -++do -++ echo "Running $t $ubidev" -++ "./$t" "$ubidev" || exit 1 -++done -++ -++echo SUCCESS -++ -++exit 0 -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/volrefcnt.c linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/volrefcnt.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/tests/ubi-tests/volrefcnt.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/tests/ubi-tests/volrefcnt.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,122 @@ -++/* -++ * Copyright (c) Nokia Corporation, 2007 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem B. Bityutskiy -++ * -++ * Test volume reference counting - create a volume, open a sysfs file -++ * belonging to the volume, delete the volume but do not close the file, make -++ * sure the file cannot be read, close the file, make sure the volume -++ * disappeard, make sure its sysfs subtree disappeared. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include "libubi.h" -++#define TESTNAME "rmvol" -++#include "common.h" -++ -++#define SYSFS_FILE "/sys/class/ubi/ubi%d_%d/usable_eb_size" -++ -++int main(int argc, char * const argv[]) -++{ -++ int ret, fd; -++ char fname[sizeof(SYSFS_FILE) + 20]; -++ const char *node; -++ libubi_t libubi; -++ struct ubi_dev_info dev_info; -++ struct ubi_mkvol_request req; -++ char tmp[100]; -++ -++ if (initial_check(argc, argv)) -++ return 1; -++ -++ node = argv[1]; -++ -++ libubi = libubi_open(); -++ if (libubi == NULL) { -++ failed("libubi_open"); -++ return 1; -++ } -++ -++ if (ubi_get_dev_info(libubi, node, &dev_info)) { -++ failed("ubi_get_dev_info"); -++ goto out_libubi; -++ } -++ -++ /* Create a small dynamic volume */ -++ req.vol_id = UBI_VOL_NUM_AUTO; -++ req.alignment = dev_info.min_io_size; -++ req.bytes = dev_info.leb_size; -++ req.vol_type = UBI_DYNAMIC_VOLUME; -++ req.name = "rmvol"; -++ -++ if (ubi_mkvol(libubi, node, &req)) { -++ failed("ubi_mkvol"); -++ goto out_libubi; -++ } -++ -++ /* Open volume-related sysfs file */ -++ sprintf(fname, SYSFS_FILE, dev_info.dev_num, req.vol_id); -++ fd = open(fname, O_RDONLY); -++ if (fd == -1) { -++ err_msg("cannot open %s", fname); -++ failed("open"); -++ goto out_rmvol; -++ } -++ -++ /* Remove the volume, but do not close the file */ -++ if (ubi_rmvol(libubi, node, req.vol_id)) { -++ failed("ubi_rmvol"); -++ perror("ubi_rmvol"); -++ goto out_close; -++ } -++ -++ /* Try to read from the file, this should fail */ -++ ret = read(fd, tmp, 100); -++ if (ret != -1) { -++ err_msg("read returned %d, expected -1", ret); -++ failed("read"); -++ goto out_close; -++ } -++ -++ /* Close the file and try to open it again, should fail */ -++ close(fd); -++ fd = open(fname, O_RDONLY); -++ if (fd != -1) { -++ err_msg("opened %s again, open returned %d, expected -1", -++ fname, fd); -++ failed("open"); -++ goto out_libubi; -++ } -++ -++ libubi_close(libubi); -++ return 0; -++ -++out_rmvol: -++ ubi_rmvol(libubi, node, req.vol_id); -++out_libubi: -++ libubi_close(libubi); -++ return 1; -++ -++out_close: -++ close(fd); -++ libubi_close(libubi); -++ return 1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/Makefile linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/Makefile -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,85 @@ -++# -++# Makefile for ubi-utils -++# -++ -++OPTFLAGS := -O2 -g -Wall -++KERNELHDR := ../include -++DESTDIR := /usr/local -++SBINDIR=/usr/sbin -++MANDIR=/usr/share/man -++INCLUDEDIR=/usr/include -++ -++CROSS=mipsel-linux- -++CC := $(CROSS)gcc -++CFLAGS := -I./inc -I./src -I$(KERNELHDR) $(OPTFLAGS) -Werror \ -++ -Wwrite-strings -W -std=gnu99 -DPACKAGE_VERSION=\"1.0\" -++ -++PERLPROGS = mkpfi ubicrc32.pl -++ -++NTARGETS = ubiattach ubicrc32 ubidetach ubimkvol ubinfo ubinize \ -++ ubirmvol ubiupdatevol -++TARGETS = pfiflash pddcustomize ubimirror bin2nand nand2bin ubigen \ -++ mkbootenv unubi pfi2bin $(NTARGETS) -++ -++vpath %.c ./src -++ -++%: %.o -++ $(CC) $(LDFLAGS) -g -o $@ $^ -++ -++%.o: %.c -++ $(CC) $(CFLAGS) -g -c -o $@ $< -g -Wp,-MD,.$(shell basename $<).dep -++ -++all: $(TARGETS) -++ make -C new-utils -++ -++IGNORE=${wildcard .*.c.dep} -++-include ${IGNORE} -++ -++$(NTARGETS): -++ make -C new-utils $@ -++ mv new-utils/$@ $@ -++ -++clean: -++ rm -rf *.o $(TARGETS) .*.c.dep -++ make -C new-utils clean -++ -++pddcustomize: pddcustomize.o error.o libubimirror.o bootenv.o hashmap.o \ -++ libubi.o crc32.o -++ $(CC) $(LDFLAGS) -o $@ $^ -++ -++pfiflash: pfiflash.o libpfiflash.o list.o reader.o error.o libubimirror.o \ -++ bootenv.o hashmap.o pfi.o libubi.o crc32.o -++ $(CC) $(LDFLAGS) -o $@ $^ -++ -++ubimirror: ubimirror.o error.o libubimirror.o bootenv.o hashmap.o \ -++ libubi.o crc32.o -++ $(CC) $(LDFLAGS) -o $@ $^ -++ -++nand2bin: nand2bin.o nandecc.o nandcorr.o -++ $(CC) $(LDFLAGS) -o $@ $^ -++ -++bin2nand: bin2nand.o error.o nandecc.o -++ $(CC) $(LDFLAGS) -o $@ $^ -++ -++ubigen: ubigen.o libubigen.o crc32.o -++ $(CC) $(LDFLAGS) -o $@ $^ -++ -++mkbootenv: mkbootenv.o bootenv.o hashmap.o error.o crc32.o -++ $(CC) $(LDFLAGS) -o $@ $^ -++ -++unubi: unubi.o crc32.o unubi_analyze.o eb_chain.o -++ $(CC) $(LDFLAGS) -o $@ $^ -++ -++pfi2bin: pfi2bin.o peb.o error.o list.o crc32.o libubigen.o bootenv.o \ -++ hashmap.o reader.o pfi.o -++ $(CC) $(LDFLAGS) -o $@ $^ -++ -++install: ${TARGETS} -++ mkdir -p ${DESTDIR}/${SBINDIR} -++ install -m0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/ -++ (cd perl && install ${PERLPROGS} ${DESTDIR}/${SBINDIR}/) -++ -++uninstall: -++ for file in ${TARGETS} ${PERLPROGS}; do \ -++ $(RM) ${DESTDIR}/${SBINDIR}/$$file; \ -++ done -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/README linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/README -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/README 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/README 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,236 @@ -++README -++====== -++ -++The programs and libraries in this directory provide a tool-chain to -++generate binary data for embedded systems which can be flashed either -++by a hardware flash programmer, e.g. JTAG debugger, or on the target -++system directly using pfiflash, or ubimkvol, ubirmvol, ubiwritevol. -++ -++The latter is the case when there is already Linux running which has -++build in UBI support. -++ -++Authors: Oliver Lohmann -++ Frank Haverkamp -++ Andreas Arnez -++ -++mkpfi - tool for flash content generation in PFI -++ format -++pfi2bin - conversion tool to transfer a PFI file into a -++ binary image -++pfiflash - tool to update the embedded systems flash using -++ pfi files created by mkpfi -++libbootenv - library for boot-parameter processing -++libpfi - library for partial flash image (PFI) creation -++ and handling -++ubigen - tool to create binary UBI images e.g. for a -++ jtag flashing tool -++nandimg - tool to add OOB data to binary images intended -++ for NAND flash systems -++ubilib - UBI library -++ -++!!! NOTICE !!! -++If you execute ./configure in the top_level directory the helper Makefile -++gets overwritten. Thats actually no problem, but be aware of that. -++ -++1. Build Process -++ -++1.1 Build, install and forget -++ o Build all and everything -++ $make all (takes a while, builds ppc and x86 binaries/libs) -++ o Installation: -++ $make install -++ o Uninstallation: -++ $make uninstall -++ -++ o x86 only would be: -++ $make x86 && make install_x86 -++ -++1.2 Usage for a developer -++ -++ 1.2.1 The build process in detail -++ -++ o If you've checked out the sources from the CVS repository you'll find a -++ directory setup like this: -++ -++ flashutils/ -++ -rw-r--r-- 1 olli olli 1.3K Mar 14 11:53 Makefile -++ -rw-r--r-- 1 olli olli 1.9K Mar 14 10:50 Makefile.am -++ -rwxr-xr-x 1 olli olli 265 Mar 9 00:47 bootstrap -++ -rw-r--r-- 1 olli olli 1.1K Mar 9 16:55 configure.ac -++ drwxr-xr-x 2 olli olli 4.0K Mar 9 00:28 doc -++ drwxr-xr-x 2 olli olli 4.0K Mar 14 11:56 inc -++ drwxr-xr-x 2 olli olli 4.0K Mar 14 11:56 lib -++ drwxr-xr-x 17 olli olli 4.0K Mar 13 16:50 src -++ -++ o To generate the initial build templates you have to call the bootstrap -++ script: -++ $ ./bootstrap -++ o Create a directory for the target platform -++ $ mkdir build_x86 -++ o Descend into the directory and call the top-level configure script -++ with the desired options. -++ $ cd build_x86 -++ $ ../configure --prefix=/usr/local [...] -++ o Now you'll find a directory structure like this: -++ -++ flashutils/build_x86/ -++ -rw-r--r-- 1 olli olli 47K Mar 14 13:33 Makefile -++ -rw-r--r-- 1 olli olli 33K Mar 14 13:33 config.log -++ -rwxr-xr-x 1 olli olli 38K Mar 14 13:33 config.status -++ drwxr-xr-x 2 olli olli 4.0K Mar 14 13:33 inc -++ drwxr-xr-x 3 olli olli 4.0K Mar 14 13:33 lib -++ -rwxr-xr-x 1 olli olli 202K Mar 14 13:33 libtool -++ -++ o The config.guess script can be used to update the Makefiles in the -++ target directory after a change of the top-level template files -++ (i.e. the Makefile.in files). -++ $ ./config.guess -++ o To compile everything for this platform just invoke make in -++ flashutils/build_x86: -++ $ make -++ or from toplevel: -++ $ make -C ./build_x86 -++ o The build process creates a new directory "bin": -++ flashutils/build_x86/ -++ [...] -++ drwxr-xr-x 3 olli olli 4.0K Mar 14 13:41 bin -++ [...] -++ -++ This directory contains all binary files which will be installed -++ by make install, e.g.: -++ -++ flashutils/build_x86/bin/ -++ -rwxr-xr-x 1 olli olli 7.2K Mar 14 13:41 bin2nand -++ -rwxr-xr-x 1 olli olli 15K Mar 14 13:41 mkbootenv -++ -rwxr-xr-x 1 olli olli 16K Mar 14 13:41 pddcustomize -++ -rwxr-xr-x 1 olli olli 36K Mar 14 13:41 pfi2bin -++ -rwxr-xr-x 1 olli olli 6.8K Mar 14 13:41 pfiflash -++ -rwxr-xr-x 1 olli olli 5.0K Mar 14 13:41 ubicrc32 -++ -rwxr-xr-x 1 olli olli 13K Mar 14 13:41 ubigen -++ -rwxr-xr-x 1 olli olli 6.3K Mar 14 13:41 ubimirror -++ -++ -++ 1.2.2 Modifying and Adding Sources -++ -++ o There is a dedicated directory which contains all source code -++ of the flashutils package, e.g.: -++ -++ flashutils/src/ -++ drwxr-xr-x 2 olli olli 4.0K Mar 13 11:42 libbootenv -++ drwxr-xr-x 2 olli olli 4.0K Mar 13 11:42 liberror -++ drwxr-xr-x 2 olli olli 4.0K Mar 13 16:48 mkpfi -++ drwxr-xr-x 2 olli olli 4.0K Mar 13 16:12 pddcustomize -++ -++ -++ -++ The prefix "lib" is used to mark directories as part of a convenience -++ library. Binaries have no special prefix. -++ -++ o How to add sources? -++ -++ Just create a new directory at flashutils/src/, e.g.: -++ -++ For a binary: -++ $ mkdir rider -++ $ cd rider -++ $ vi rider.c -++ /* do sth with that file... */ -++ -++ For a convenience library (as well as for "normal libs") -++ $ mkdir libworld -++ $ cd libworld -++ $ vi world.c -++ /* do sth with that file... */ -++ -++ o How to register sources in the build process (for binaries)? -++ -++ You have to register your sources at the top-level automake Makefile: -++ -++ In directory flashutils/ -++ $ vi Makefile.am -++ -++ Binaries have to be registered at "bin_PROGRAMS", e.g.: -++ bin_PROGRAMS = bin/pddcustomize \ -++ bin/rider -++ -++ Add the rule how the binary is assembled, e.g.: -++ bin_pddcustomize_SOURCES = \ -++ $(top_srcdir)/src/pddcustomize/pddcustomize.c -++ bin_pddcustomize_LDADD = \ -++ $(top_builddir)/lib/libbootenv.la \ -++ $(top_builddir)/lib/liberror.la -++ -++ bin_rider_SOURCES = \ -++ $(top_srcdir)/src/rider/rider.c -++ -++ This example reflects a simple build process for "rider". "rider" -++ is built without any other dependencies or convenience libraries. -++ The example for pddcustomize is a bit more complicated. -++ "_LDADD" adds some convenience libraris into the link process of -++ "pddcustomize". Imagine, that your "rider" has common code -++ with "dragon_bin" which is held in a library called "libworld". -++ The build rules would like like the following: -++ -++ bin_rider_SOURCES = \ -++ $(top_srcdir)/src/rider/rider.c -++ bin_rider_LDADD = \ -++ $(top_builddir)/lib/libworld.la -++ -++ bin_dragon_SOURCES = \ -++ $(top_srcdir)/src/dragon_bin/dragon_bin.c -++ bin_dragon_LDADD = \ -++ $(top_builddir)/lib/libworld.la -++ -++ Don't forget to add "dragon" to "bin_PROGRAMS"! -++ Don't forget to set the build rule for the "libworld" itself! -++ This is documented in the next section. -++ -++ -++ o How to register sources in the build process (for libraries)? -++ -++ Until now we didn't care about the build process of "libworld". -++ Libraries are handled special in this build process because -++ they are handled as "modules", i.e. they are able to be built -++ without building the binaries in the same step. Additionally, -++ it is possible to assemble complex libraries out of simple ones. -++ That especially makes sense if you want to export (install) a -++ library on a system which uses some common code and makes -++ some adoptions for usability and presents a comfortable interface to -++ the user (see libpfiflash in the sources for an example). -++ -++ o Registering "libworld" as convenience library. -++ -++ Instead of editing the "Makefile.am" in "flashtools/", we have to -++ edit now the "Makefile.am" in "flashtools/lib/": -++ -++ noinst_LTLIBRARIES = libworld.la -++ -++ libworld_la_SOURCES = $(top_srcdir)/src/libworld/world.c -++ -++ o Registering "libworld" as library which gets installed. -++ -++ lib_LTLIBRARIES = libworld.la -++ libworld_la_SOURCES = $(top_srcdir)/src/libworld/world.c -++ libworld_la_LDFLAGS = -no-undefined -version-info 0:0:0 -++ -++ o Header files -++ -++ All header files are stored at "flashutils/inc", regardless -++ if convenience library or not. -++ -++ If you want to export headers you have to specify this in the Makefile.am -++ located at "flashutils/inc", e.g. (this should not be done -++ for convenience libraries): -++ -++ nobase_include_HEADERS = world.h -++ -++ -++ -++Appendix -++ -++A.1. FAQ -++ -++ Q How to call configure to setup a cross-platform build? -++ A $ ./configure --build=i686-pc-linux-gnu --host=ppc-linux \ -++ --prefix=/opt/.../ppcnf/crossroot/ \ -++ --exec-prefix=/opt/..../ppcnf/crossroot/usr -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/UBI.TXT linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/UBI.TXT -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/UBI.TXT 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/UBI.TXT 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,108 @@ -++UBI - Unsorted Block Images -++ -++UBI (Latin: "where?") manages multiple logical volumes on a single -++flash device, specifically supporting NAND flash devices. UBI provides -++a flexible partitioning concept which still allows for wear-levelling -++across the whole flash device. -++ -++In a sense, UBI may be compared to the Logical Volume Manager -++(LVM). Whereas LVM maps logical sector numbers to physical HDD sector -++numbers, UBI maps logical eraseblocks to physical eraseblocks. -++ -++More information may be found in the UBI design documentation: -++ubidesign.pdf. Which can be found here: -++http://www.linux-mtd.infradead.org/doc/ubi.html -++ -++Partitioning/Re-partitioning -++ -++ An UBI volume occupies a certain number of erase blocks. This is -++ limited by a configured maximum volume size, which could also be -++ viewed as the partition size. Each individual UBI volume's size can -++ be changed independently of the other UBI volumes, provided that the -++ sum of all volume sizes doesn't exceed a certain limit. -++ -++ UBI supports dynamic volumes and static volumes. Static volumes are -++ read-only and their contents are protected by CRC check sums. -++ -++Bad eraseblocks handling -++ -++ UBI transparently handles bad eraseblocks. When a physical -++ eraseblock becomes bad, it is substituted by a good physical -++ eraseblock, and the user does not even notice this. -++ -++Scrubbing -++ -++ On a NAND flash bit flips can occur on any write operation, -++ sometimes also on read. If bit flips persist on the device, at first -++ they can still be corrected by ECC, but once they accumulate, -++ correction will become impossible. Thus it is best to actively scrub -++ the affected eraseblock, by first copying it to a free eraseblock -++ and then erasing the original. The UBI layer performs this type of -++ scrubbing under the covers, transparently to the UBI volume users. -++ -++Erase Counts -++ -++ UBI maintains an erase count header per eraseblock. This frees -++ higher-level layers (like file systems) from doing this and allows -++ for centralized erase count management instead. The erase counts are -++ used by the wear-levelling algorithm in the UBI layer. The algorithm -++ itself is exchangeable. -++ -++Booting from NAND -++ -++ For booting directly from NAND flash the hardware must at least be -++ capable of fetching and executing a small portion of the NAND -++ flash. Some NAND flash controllers have this kind of support. They -++ usually limit the window to a few kilobytes in erase block 0. This -++ "initial program loader" (IPL) must then contain sufficient logic to -++ load and execute the next boot phase. -++ -++ Due to bad eraseblocks, which may be randomly scattered over the -++ flash device, it is problematic to store the "secondary program -++ loader" (SPL) statically. Also, due to bit-flips it may become -++ corrupted over time. UBI allows to solve this problem gracefully by -++ storing the SPL in a small static UBI volume. -++ -++UBI volumes vs. static partitions -++ -++ UBI volumes are still very similar to static MTD partitions: -++ -++ * both consist of eraseblocks (logical eraseblocks in case of UBI -++ volumes, and physical eraseblocks in case of static partitions; -++ * both support three basic operations - read, write, erase. -++ -++ But UBI volumes have the following advantages over traditional -++ static MTD partitions: -++ -++ * there are no eraseblock wear-leveling constraints in case of UBI -++ volumes, so the user should not care about this; -++ * there are no bit-flips and bad eraseblocks in case of UBI volumes. -++ -++ So, UBI volumes may be considered as flash devices with relaxed -++ restrictions. -++ -++Where can it be found? -++ -++ Documentation, kernel code and applications can be found in the MTD -++ gits. -++ -++What are the applications for? -++ -++ The applications help to create binary flash images for two -++ purposes: pfi files (partial flash images) for in-system update of -++ UBI volumes, and plain binary images, with or without OOB data in -++ case of NAND, for a manufacturing step. Furthermore some tools -++ are/and will be created that allow flash content analysis after a -++ system has crashed. -++ -++Who did UBI? -++ -++ The original ideas, where UBI is based on, were developed by Andreas -++ Arnez, Frank Haverkamp and Thomas Gleixner. Josh W. Boyer and -++ some others were involved too. The implementation of the kernel -++ layer was done by Artem B. Bityutskiy. The user-space applications -++ and tools were written by Oliver Lohmann with contributions from -++ Frank Haverkamp, Andreas Arnez, and Artem. Joern Engel contributed a -++ patch which modifies JFFS2 so that it can be run on a UBI -++ volume. Thomas Gleixner did modifications to the NAND layer and also -++ some to JFFS2 to make it work. -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/doc/unubi.roff linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/doc/unubi.roff -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/doc/unubi.roff 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/doc/unubi.roff 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,123 @@ -++.TH UNUBI 1 "NOVEMBER 2006" FSP "FSP Flashutils" -++.SH NAME -++unubi \- extract volumes/eraseblocks from a raw\-UBI image -++.SH SYNOPSIS -++\fBunubi [\-aevEV] [\-d \fIout\-dir\fB] [\-r \fIvolume\-id\fB] -++[\-b \fIblock\-size\fB] \fIimage\-file -++.SH DESCRIPTION -++.PP -++\fBunubi\fR reads an image file containing blocks of UBI headers and data -++(such as produced from \fBnand2bin\fR) and rebuilds the volumes within. -++The default operation (when no flags are given) is to rebuild all valid -++volumes found in the image. \fBunubi\fR can also read straight from the -++onboard MTD device (ex. /dev/mtdblock/NAND). -++.SH OPTIONS -++.IP "\-a, \-\-analyze" -++When flagged, analysis files are generated within the output directory. These -++may include tables and or graphs detailing statistics gathered from the -++eraseblock data. Files are prefixed `analysis_'. -++ -++See \fBANALYSIS\fR. -++.IP "\-b, \-\-blocksize \fIblock\-size\fR" -++Specify in bytes the \fIimage\-file\fR eraseblock size. Sizes may be -++postfixed with `KiB' or `MiB' to indicate mebibytes or kibibytes -++respectively. Default is 128KiB. -++.IP "\-d, \-\-dir \fIoutput\-dir\fR" -++Specify the output directory. If no directory is specified, the default -++is `unubi_\fIimage\-file\fR' within the curent working directory. If the -++attempt to create the output directory fails, -++.B unubi -++will try to create it in /tmp before aborting. -++.IP "\-e, \-\-eb\-split" -++When flagged, images are created for each eraseblock in \fIimage\-file\fR -++regardless of its validity. Each image is the complete eraseblock, including -++headers and any space to the end of the eraseblock after where the data may -++end. -++ -++Invalid images are named `ebEEEE', where EEEE is the physical index of the -++eraseblock in the image. Valid images are named `ebEEEE_VVV_NNN_RRR' where -++VVV is the known volume ID, NNN is the logical number and RRR is the version -++of the eraseblock data. Note that the version number is in hexadecimal. -++ -++Invalid images may also contain this postfix, if the data in the header -++could be valid (ie. the header contains a resonable volume ID, but the -++header and/or data CRCs are not valid). If this is the case, images are named -++`ebEEEE_VVV_NNN_RRR.reason', so as to distinguish known values from -++non\-definite ones. -++ -++See \fBREASON SUFFIXES\fR. -++.IP "\-r, \-\-rebuild \fIvolume\-id\fR" -++Specify a volume to rebuild. Can be used successively to specify -++several volumes to be rebuilt. -++ -++Images are named `volumeVVV' where VVV is the volume ID. For each missing -++eraseblock, an error message will be printed. -++.IP "\-v, \-\-vol\-split" -++When flagged, images are created for each valid eraseblock in -++\fIimage\-file\fR. Since a vaild eraseblock will have a defined data start and -++data length, only this range will make up the image. -++ -++Images are named `volVVV_NNN_RRR_EEEE', where, for the data in the eraseblock, -++VVV is the volume ID, NNN is the logical number, RRR is the version and EEEE -++is the phyisical index of the eraseblock in the image. -++.IP "\-V, \-\-vol\-split!" -++Same as above, only all images are the complete eraseblock (including headers, -++and raw data, even past the point where the data is supposed to end). -++Overrides \-v when both \-v and \-V are flagged. -++.SH ANALYSIS -++The following files will be generated during the analysis: -++.IP "analysis_ec_hdr.data" -++A space delimited table with these two columns for each eraseblock: the -++eraseblock's index or physical position in the image, and the eraseblock's -++erase count. The third column contains the erase count data sorted. -++.IP "analysis_vid_hdr.data" -++A space delimited table with these four colums for each eraseblock: the -++volume ID, the volume logical number, the leb version, and the data size. -++In addition there are a normalized column representing the volume ID and -++volume logical number, a normalized column representing the leb version, and -++a normalized column representing the data_size. These normalized columns are -++used to better draw the the gnuplot image. -++.IP "analysis_ec_hdr.plot" -++A gnuplot script for quickly viewing a sample output from the respective .data -++file. -++.IP "analysis_vid_hdr.plot" -++A gnuplot script for quickly viewing a sample output from the respective .data -++file. -++.SH REASONS SUFFIXES -++When \-\-eb\-split produces possibly invalid, though usable, eraseblocks, the -++known reason suffixes are: -++.IP ".ec_magic" -++The erase counter header did not contain a valid magic field. -++.IP ".ec_hdr_crc" -++The erase counter header did not contain a vaild header CRC field. -++.IP ".vid_magic" -++The volume ID header did not contain a valid magic field. -++.IP ".vid_hdr_crc" -++The volume ID header did not contain a valid header CRC field. -++.IP ".data_crc" -++The volume ID header did not contain a valid data CRC field. -++.SH EXAMPLES -++To extract and rebuild all valid volumes from demo.img (note the output -++directory will be /home/user/unubi_demo.img): -++.sp 1 -++.RS -++.B /home/user# unubi demo.img -++.sp 1 -++.RE -++To analyze demo.img as well as extract and rebuild volume 7: -++.sp 1 -++.RS -++.B /home/user# unubi \-a \-r 7 demo.img -++.sp 1 -++.RE -++To split demo.img into raw images for each eraseblock into the folder -++/var/eraseblocks: -++.sp 1 -++.RS -++.B /home/user# unubi \-e \-d /var/eraseblocks demo.img -++.SH AUTHORS -++Frank Haverkamp -++.sp 0 -++Drake Dowsett -++.SH CONTACT -++Andreas Arnez -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/inc/libubi.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/inc/libubi.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/inc/libubi.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/inc/libubi.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,268 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem B. Bityutskiy -++ * -++ * UBI (Unsorted Block Images) library. -++ */ -++ -++#ifndef __LIBUBI_H__ -++#define __LIBUBI_H__ -++ -++#include -++#include -++#include -++#include -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++/* UBI version libubi is made for */ -++#define LIBUBI_UBI_VERSION 1 -++ -++/* UBI library descriptor */ -++typedef void * libubi_t; -++ -++/** -++ * struct ubi_mkvol_request - volume creation request. -++ * */ -++struct ubi_mkvol_request -++{ -++ int vol_id; -++ int alignment; -++ long long bytes; -++ int vol_type; -++ const char *name; -++}; -++ -++/** -++ * struct ubi_info - general UBI information. -++ * -++ * @dev_count count of UBI devices in system -++ * @lowest_dev_num lowest UBI device number -++ * @highest_dev_num highest UBI device number -++ * @version UBI version -++ */ -++struct ubi_info -++{ -++ int dev_count; -++ int lowest_dev_num; -++ int highest_dev_num; -++ int version; -++}; -++ -++/** -++ * struct ubi_dev_info - UBI device information. -++ * -++ * @vol_count count of volumes on this UBI device -++ * @lowest_vol_num lowest volume number -++ * @highest_vol_num highest volume number -++ * @total_ebs total number of eraseblocks on this UBI device -++ * @avail_ebs how many eraseblocks are not used and available for new -++ * volumes -++ * @total_bytes @total_ebs * @eb_size -++ * @avail_bytes @avail_ebs * @eb_size -++ * @bad_count count of bad eraseblocks -++ * @eb_size size of UBI eraseblock -++ * @max_ec current highest erase counter value -++ * @bad_rsvd how many physical eraseblocks of the underlying flash -++ * device are reserved for bad eraseblocks handling -++ * @max_vol_count maximum count of volumes on this UBI device -++ * @min_io_size minimum input/output size of the UBI device -++ */ -++struct ubi_dev_info -++{ -++ int dev_num; -++ int vol_count; -++ int lowest_vol_num; -++ int highest_vol_num; -++ int total_ebs; -++ int avail_ebs; -++ long long total_bytes; -++ long long avail_bytes; -++ int bad_count; -++ int eb_size; -++ long long max_ec; -++ int bad_rsvd; -++ int max_vol_count; -++ int min_io_size; -++}; -++ -++/** -++ * struct ubi_vol_info - UBI volume information. -++ * -++ * @dev_num UBI device number the volume resides on -++ * @vol_id ID of this volume -++ * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) -++ * @alignment alignemnt of this volume -++ * @data_bytes how many data bytes are stored on this volume (equivalent to -++ * @rsvd_bytes for dynamic volumes) -++ * @rsvd_bytes how many bytes are reserved for this volume -++ * @rsvd_ebs how many eraseblocks are reserved for this volume -++ * @eb_size logical eraseblock size of this volume (may be less then -++ * device's logical eraseblock size due to alignment) -++ * @corrupted the volume is corrupted if this flag is not zero -++ * @name volume name (null-terminated) -++ */ -++struct ubi_vol_info -++{ -++ int dev_num; -++ int vol_id; -++ int type; -++ int alignment; -++ long long data_bytes; -++ long long rsvd_bytes; -++ int rsvd_ebs; -++ int eb_size; -++ int corrupted; -++ char name[UBI_VOL_NAME_MAX + 1]; -++}; -++ -++/** -++ * libubi_open - open UBI library. -++ * -++ * This function initializes and opens the UBI library and returns UBI library -++ * descriptor in case of success and %NULL in case of failure. -++ */ -++libubi_t libubi_open(void); -++ -++/** -++ * libubi_close - close UBI library -++ * -++ * @desc UBI library descriptor -++ */ -++void libubi_close(libubi_t desc); -++ -++/** -++ * ubi_get_info - get general UBI information. -++ * -++ * @info pointer to the &struct ubi_info object to fill -++ * @desc UBI library descriptor -++ * -++ * This function fills the passed @info object with general UBI information and -++ * returns %0 in case of success and %-1 in case of failure. -++ */ -++int ubi_get_info(libubi_t desc, struct ubi_info *info); -++ -++/** -++ * ubi_mkvol - create an UBI volume. -++ * -++ * @desc UBI library descriptor -++ * @node name of the UBI character device to create a volume at -++ * @req UBI volume creation request (defined at ) -++ * -++ * This function creates a UBI volume as described at @req and returns %0 in -++ * case of success and %-1 in case of failure. The assigned volume ID is -++ * returned in @req->vol_id. -++ */ -++int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req); -++ -++/** -++ * ubi_rmvol - remove a UBI volume. -++ * -++ * @desc UBI library descriptor -++ * @node name of the UBI character device to remove a volume from -++ * @vol_id ID of the volume to remove -++ * -++ * This function removes volume @vol_id from UBI device @node and returns %0 in -++ * case of success and %-1 in case of failure. -++ */ -++int ubi_rmvol(libubi_t desc, const char *node, int vol_id); -++ -++/** -++ * ubi_rsvol - re-size UBI volume. -++ * -++ * @desc UBI library descriptor -++ * @node name of the UBI character device owning the volume which should be -++ * re-sized -++ * @vol_id volume ID to re-size -++ * @bytes new volume size in bytes -++ * -++ * This function returns %0 in case of success and %-1 in case of error. -++ */ -++int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes); -++ -++/** -++ * ubi_get_dev_info - get UBI device information. -++ * -++ * @desc UBI library descriptor -++ * @node name of the UBI character device to fetch information about -++ * @info pointer to the &struct ubi_dev_info object to fill -++ * -++ * This function fills the passed @info object with UBI device information and -++ * returns %0 in case of success and %-1 in case of failure. -++ */ -++int ubi_get_dev_info(libubi_t desc, const char *node, -++ struct ubi_dev_info *info); -++ -++/** -++ * ubi_get_dev_info1 - get UBI device information. -++ * -++ * @desc UBI library descriptor -++ * @dev_num UBI device number to fetch information about -++ * @info pointer to the &struct ubi_dev_info object to fill -++ * -++ * This function is identical to 'ubi_get_dev_info()' except that it accepts UBI -++ * device number, not UBI character device. -++ */ -++int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info); -++ -++/** -++ * ubi_get_vol_info - get UBI volume information. -++ * -++ * @desc UBI library descriptor -++ * @node name of the UBI volume character device to fetch information about -++ * @info pointer to the &struct ubi_vol_info object to fill -++ * -++ * This function fills the passed @info object with UBI volume information and -++ * returns %0 in case of success and %-1 in case of failure. -++ */ -++int ubi_get_vol_info(libubi_t desc, const char *node, -++ struct ubi_vol_info *info); -++ -++/** -++ * ubi_get_vol_info1 - get UBI volume information. -++ * -++ * @desc UBI library descriptor -++ * @dev_num UBI device number -++ * @vol_id ID of the UBI volume to fetch information about -++ * @info pointer to the &struct ubi_vol_info object to fill -++ * -++ * This function is identical to 'ubi_get_vol_info()' except that it accepts UBI -++ * volume number, not UBI volume character device. -++ */ -++int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id, -++ struct ubi_vol_info *info); -++ -++/** -++ * ubi_update_start - start UBI volume update. -++ * -++ * @desc UBI library descriptor -++ * @fd volume character devie file descriptor -++ * @bytes how many bytes will be written to the volume -++ * -++ * This function initiates UBI volume update and returns %0 in case of success -++ * and %-1 in case of error. -++ */ -++int ubi_update_start(libubi_t desc, int fd, long long bytes); -++ -++#ifdef __cplusplus -++} -++#endif -++ -++#endif /* !__LIBUBI_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/lib/Makefile.am linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/lib/Makefile.am -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/lib/Makefile.am 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/lib/Makefile.am 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,58 @@ -++AUTOMAKE_OPTIONS = foreign -++INCLUDES=-I$(top_srcdir)/inc -I$(top_srcdir)/../../kernel/include -++ -++# ----------------------------------------------------------------------------- -++# all export libs which shall be generated -++lib_LTLIBRARIES = libubi.la \ -++ libpfiflash.la -++ -++# ----------------------------------------------------------------------------- -++# all convinence libs which shall be generated -++noinst_LTLIBRARIES = libcrc32.la \ -++ libubigen.la \ -++ liberror.la \ -++ liblist.la \ -++ libbootenv.la \ -++ libpfi.la \ -++ libpeb.la \ -++ libreader.la \ -++ libubimirror.la -++ -++# ----------------------------------------------------------------------------- -++# exported libs -++libpfiflash_la_SOURCES = $(top_srcdir)/src/libpfiflash/pfiflash.c -++libpfiflash_la_LDFLAGS = -no-undefined -version-info 1:0:0 -++libpfiflash_la_LIBADD = libreader.la \ -++ libubimirror.la \ -++ libubi.la -++ -++libubi_la_SOURCES = $(top_srcdir)/src/libubi/libubi.c \ -++ $(top_srcdir)/src/libubi/libubi_sysfs.c -++libubi_la_LDFLAGS = -no-undefined -version-info 1:0:0 -++ -++# ----------------------------------------------------------------------------- -++# complex convinence libs, beware for double includes. -++libreader_la_SOURCES = $(top_srcdir)/src/libreader/reader.c -++libreader_la_LIBADD = libpfi.la \ -++ liblist.la \ -++ libpeb.la \ -++ libbootenv.la -++ -++libubigen_la_SOURCES = $(top_srcdir)/src/libubigen/ubigen.c -++libubigen_la_LIBADD = libcrc32.la -++ -++libbootenv_la_SOURCES = $(top_srcdir)/src/libbootenv/bootenv.c \ -++ $(top_srcdir)/src/libbootenv/hashmap.c -++libbootenv_la_LIBADD = libcrc32.la -++ -++libubimirror_la_SOURCES = $(top_srcdir)/src/libubimirror/ubimirror.c -++libubimirror_la_LIBADD = libubi.la -++ -++ -++# ----------------------------------------------------------------------------- -++# simple convinence libs -++libcrc32_la_SOURCES = $(top_srcdir)/src/libcrc32/crc32.c -++liberror_la_SOURCES = $(top_srcdir)/src/liberror/error.c -++liblist_la_SOURCES = $(top_srcdir)/src/liblist/list.c -++libpeb_la_SOURCES = $(top_srcdir)/src/libpeb/peb.c -++libpfi_la_SOURCES = $(top_srcdir)/src/libpfi/pfi.c -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/LICENSE.libiniparser linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/LICENSE.libiniparser -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/LICENSE.libiniparser 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/LICENSE.libiniparser 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,21 @@ -++Copyright (c) 2000-2007 by Nicolas Devillard. -++MIT License -++ -++Permission is hereby granted, free of charge, to any person obtaining a -++copy of this software and associated documentation files (the "Software"), -++to deal in the Software without restriction, including without limitation -++the rights to use, copy, modify, merge, publish, distribute, sublicense, -++and/or sell copies of the Software, and to permit persons to whom the -++Software is furnished to do so, subject to the following conditions: -++ -++The above copyright notice and this permission notice shall be included in -++all copies or substantial portions of the Software. -++ -++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -++AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -++FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -++DEALINGS IN THE SOFTWARE. -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/Makefile linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/Makefile -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,81 @@ -++# -++# Makefile for ubi-utils -++# -++ -++OPTFLAGS := -O2 -Wall -++KERNELHDR := ../../include -++#DESTDIR := /usr/local -++DESTDIR := /nfsroot/user/yrtan -++SBINDIR=/usr/sbin -++MANDIR=/usr/man -++INCLUDEDIR=/usr/include -++CROSS=mipsel-linux- -++CC := $(CROSS)gcc -++CFLAGS := -Iinclude -Isrc -I$(KERNELHDR) $(OPTFLAGS) -Werror -Wall -++ -++LIBS = libubi libmtd libubigen libiniparser libscan -++UTILS = ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \ -++ ubidetach ubiformat ubidumpvol ubicrcvol \ -++ ubinize ubicrcsf ubirefimg -++vpath %.c src -++ -++all: $(UTILS) -++ -++# The below cancels existing implicite rule to make programs from .c files, -++# in order to force make using our rule defined below -++%: %.c -++ -++# The below is the rule to get an .o file from a .c file -++%.o: %.c -++ $(CC) $(CFLAGS) $< -c -o $@ -++ -++# And the below is the rule to get final executable from its .o and common.o -++%: libubi.a %.o common.o -++ $(CC) $(CFLAGS) $(filter %.o, $^) -L. -lubi -o $@ -++ -++ubicrcsf: ubicrcsf.o crc32.o -++ $(CC) $(CFLAGS) -o $@ $^ -++ -++ubicrcvol: ubicrcvol.o common.o crc32.o libubi.a -++ $(CC) $(CFLAGS) $(filter %.o, $^) -L. -lubi -o $@ -++ -++ubicrc32: ubicrc32.o crc32.o -++ $(CC) $(CFLAGS) -o $@ $^ -++ -++ubinize: ubinize.o common.o crc32.o libiniparser.a libubigen.a -++ $(CC) $(CFLAGS) $(filter %.o, $^) -L. -liniparser -lubigen -o $@ -++ -++ubiformat: ubiformat.o common.o crc32.o libmtd.a libscan.a libubi.a libubigen.a -++ $(CC) $(CFLAGS) $(filter %.o, $^) -L. -lmtd -lscan -lubi -lubigen -o $@ -++ -++libubi.a: libubi.o -++ $(AR) crv $@ $^ -++ ranlib $@ -++ -++libmtd.a: libmtd.o -++ $(AR) crv $@ $^ -++ ranlib $@ -++ -++libubigen.a: libubigen.o -++ $(AR) crv $@ $^ -++ ranlib $@ -++ -++libiniparser.a: libiniparser.o dictionary.o -++ $(AR) crv $@ $^ -++ ranlib $@ -++ -++libscan.a: libscan.o crc32.o -++ $(AR) crv $@ $^ -++ ranlib $@ -++ -++clean: -++ rm -rf *.o $(addsuffix .a, $(LIBS)) $(UTILS) .*.c.dep -++ -++install: ${UTILS} -++ mkdir -p ${DESTDIR}/${SBINDIR} -++ install -m0755 ${UTILS} ${DESTDIR}/${SBINDIR}/ -++ -++uninstall: -++ for file in ${UTILS}; do \ -++ $(RM) ${DESTDIR}/${SBINDIR}/$$file; \ -++ done -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/README linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/README -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/README 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/README 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,55 @@ -++This directory contains a new UBI toolchain which is intended to replace -++the old one. All utilities support "-h" option which prints sufficient -++usage information. See the MTD web-site for more information. -++ -++Motivation for new tool-chain. -++ -++I was doing very active UBI development and had to add new features like -++dynamic UBI devices and auto-resize feature. Because of the mess in the -++the old tools I basically could not figure out how to upgrade them. In -++my humble oppinion, they are unmaintainable. The original authors did not -++show enthusiasm when I mailed them and asked to clean-up the tool-chain -++[1]. Thus, I re-implemented them, but I did borrow things from the old -++tool-chain and preserved copyrights and author names. -++ -++I really did try to clean-up the old tool chain, but gave up (see git -++history for confirmation). So, -++ -++1. I found the source codes very difficult to navigate and read, especially -++ those related to pdd, pfi, and bootenv. Try to do this yourself - they -++ are a puzzle. -++2. I foud the concept of PFI needlesly complecated - PFI file is nothing -++ else but the initial configuration .ini file + the contents of the -++ UBI volumes packed into one file, but with some changes of the .ini file's -++ format. The PFI file format is not very nice and it is difficult to parse, -++ especially because the PFI headers do not tell you data star and end for -++ each data chunk, and you have to do additional parsing. -++ -++ So basically, you have .ini file + images, then you transfer this to pfi, -++ which does not add any other information. For .ini you have libraries -++ which may parse them, for pfi - not. Then you have to parse this pfi -++ which adds unneeded and complex code. This all needs lists, hashmaps, -++ and so on - for no reason. -++3. I found the command line options of the utilities to be inconsistent. -++ This is OK when you script your single task and do not touch it anymore. -++ But when you have to use the utilities while developing and testing, -++ It is difficult to remember their inconsistent options. -++4. I found it wrong to add development options to user utilities like -++ "broken update". End users should not see them. -++5. I did not find any consistent style and convention inside which -++ irritated me. -++6. I found it weird to introduce needless "logging infrastructure" instead -++ of just re-directing stdout and stderr to another file. -++7. I found the tool to be rather IBM-setup oriented. For example, the VID -++ header position was hard-coded. Some utilities were just weird, like -++ mkbootenv, which changed some ethernet addresses mentioned in a -++ configuration file. -++8. Finally, it was very difficult to realize what is pfi and pdd, what for, -++ why I need this transiant pfi file when I just want to create an UBI -++ image. There was zero documentation. -++ -++And so on. -++ -++Feb 19, 2008, Artem Bityutskiy. -++ -++[1]. http://lists.infradead.org/pipermail/linux-mtd/2007-December/020134.html -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libiniparser.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libiniparser.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libiniparser.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libiniparser.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,280 @@ -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @file iniparser.h -++ @author N. Devillard -++ @date Sep 2007 -++ @version 3.0 -++ @brief Parser for ini files. -++*/ -++/*--------------------------------------------------------------------------*/ -++ -++/* -++ $Id: libiniparser.h,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ -++ $Revision: 1.1.1.1 $ -++*/ -++ -++#ifndef _INIPARSER_H_ -++#define _INIPARSER_H_ -++ -++/*--------------------------------------------------------------------------- -++ Includes -++ ---------------------------------------------------------------------------*/ -++ -++#include -++#include -++#include -++ -++/* -++ * The following #include is necessary on many Unixes but not Linux. -++ * It is not needed for Windows platforms. -++ * Uncomment it if needed. -++ */ -++/* #include */ -++ -++#include "dictionary.h" -++ -++/*--------------------------------------------------------------------------- -++ Macros -++ ---------------------------------------------------------------------------*/ -++/** For backwards compatibility only */ -++#define iniparser_getstr(d, k) iniparser_getstring(d, k, NULL) -++#define iniparser_setstr iniparser_setstring -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Get number of sections in a dictionary -++ @param d Dictionary to examine -++ @return int Number of sections found in dictionary -++ -++ This function returns the number of sections found in a dictionary. -++ The test to recognize sections is done on the string stored in the -++ dictionary: a section name is given as "section" whereas a key is -++ stored as "section:key", thus the test looks for entries that do not -++ contain a colon. -++ -++ This clearly fails in the case a section name contains a colon, but -++ this should simply be avoided. -++ -++ This function returns -1 in case of error. -++ */ -++/*--------------------------------------------------------------------------*/ -++ -++int iniparser_getnsec(dictionary * d); -++ -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Get name for section n in a dictionary. -++ @param d Dictionary to examine -++ @param n Section number (from 0 to nsec-1). -++ @return Pointer to char string -++ -++ This function locates the n-th section in a dictionary and returns -++ its name as a pointer to a string statically allocated inside the -++ dictionary. Do not free or modify the returned string! -++ -++ This function returns NULL in case of error. -++ */ -++/*--------------------------------------------------------------------------*/ -++ -++char * iniparser_getsecname(dictionary * d, int n); -++ -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Save a dictionary to a loadable ini file -++ @param d Dictionary to dump -++ @param f Opened file pointer to dump to -++ @return void -++ -++ This function dumps a given dictionary into a loadable ini file. -++ It is Ok to specify @c stderr or @c stdout as output files. -++ */ -++/*--------------------------------------------------------------------------*/ -++ -++void iniparser_dump_ini(dictionary * d, FILE * f); -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Dump a dictionary to an opened file pointer. -++ @param d Dictionary to dump. -++ @param f Opened file pointer to dump to. -++ @return void -++ -++ This function prints out the contents of a dictionary, one element by -++ line, onto the provided file pointer. It is OK to specify @c stderr -++ or @c stdout as output files. This function is meant for debugging -++ purposes mostly. -++ */ -++/*--------------------------------------------------------------------------*/ -++void iniparser_dump(dictionary * d, FILE * f); -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Get the string associated to a key -++ @param d Dictionary to search -++ @param key Key string to look for -++ @param def Default value to return if key not found. -++ @return pointer to statically allocated character string -++ -++ This function queries a dictionary for a key. A key as read from an -++ ini file is given as "section:key". If the key cannot be found, -++ the pointer passed as 'def' is returned. -++ The returned char pointer is pointing to a string allocated in -++ the dictionary, do not free or modify it. -++ */ -++/*--------------------------------------------------------------------------*/ -++char * iniparser_getstring(dictionary * d, const char * key, char * def); -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Get the string associated to a key, convert to an int -++ @param d Dictionary to search -++ @param key Key string to look for -++ @param notfound Value to return in case of error -++ @return integer -++ -++ This function queries a dictionary for a key. A key as read from an -++ ini file is given as "section:key". If the key cannot be found, -++ the notfound value is returned. -++ -++ Supported values for integers include the usual C notation -++ so decimal, octal (starting with 0) and hexadecimal (starting with 0x) -++ are supported. Examples: -++ -++ - "42" -> 42 -++ - "042" -> 34 (octal -> decimal) -++ - "0x42" -> 66 (hexa -> decimal) -++ -++ Warning: the conversion may overflow in various ways. Conversion is -++ totally outsourced to strtol(), see the associated man page for overflow -++ handling. -++ -++ Credits: Thanks to A. Becker for suggesting strtol() -++ */ -++/*--------------------------------------------------------------------------*/ -++int iniparser_getint(dictionary * d, const char * key, int notfound); -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Get the string associated to a key, convert to a double -++ @param d Dictionary to search -++ @param key Key string to look for -++ @param notfound Value to return in case of error -++ @return double -++ -++ This function queries a dictionary for a key. A key as read from an -++ ini file is given as "section:key". If the key cannot be found, -++ the notfound value is returned. -++ */ -++/*--------------------------------------------------------------------------*/ -++double iniparser_getdouble(dictionary * d, char * key, double notfound); -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Get the string associated to a key, convert to a boolean -++ @param d Dictionary to search -++ @param key Key string to look for -++ @param notfound Value to return in case of error -++ @return integer -++ -++ This function queries a dictionary for a key. A key as read from an -++ ini file is given as "section:key". If the key cannot be found, -++ the notfound value is returned. -++ -++ A true boolean is found if one of the following is matched: -++ -++ - A string starting with 'y' -++ - A string starting with 'Y' -++ - A string starting with 't' -++ - A string starting with 'T' -++ - A string starting with '1' -++ -++ A false boolean is found if one of the following is matched: -++ -++ - A string starting with 'n' -++ - A string starting with 'N' -++ - A string starting with 'f' -++ - A string starting with 'F' -++ - A string starting with '0' -++ -++ The notfound value returned if no boolean is identified, does not -++ necessarily have to be 0 or 1. -++ */ -++/*--------------------------------------------------------------------------*/ -++int iniparser_getboolean(dictionary * d, const char * key, int notfound); -++ -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Set an entry in a dictionary. -++ @param ini Dictionary to modify. -++ @param entry Entry to modify (entry name) -++ @param val New value to associate to the entry. -++ @return int 0 if Ok, -1 otherwise. -++ -++ If the given entry can be found in the dictionary, it is modified to -++ contain the provided value. If it cannot be found, -1 is returned. -++ It is Ok to set val to NULL. -++ */ -++/*--------------------------------------------------------------------------*/ -++int iniparser_setstring(dictionary * ini, char * entry, char * val); -++ -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Delete an entry in a dictionary -++ @param ini Dictionary to modify -++ @param entry Entry to delete (entry name) -++ @return void -++ -++ If the given entry can be found, it is deleted from the dictionary. -++ */ -++/*--------------------------------------------------------------------------*/ -++void iniparser_unset(dictionary * ini, char * entry); -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Finds out if a given entry exists in a dictionary -++ @param ini Dictionary to search -++ @param entry Name of the entry to look for -++ @return integer 1 if entry exists, 0 otherwise -++ -++ Finds out if a given entry exists in the dictionary. Since sections -++ are stored as keys with NULL associated values, this is the only way -++ of querying for the presence of sections in a dictionary. -++ */ -++/*--------------------------------------------------------------------------*/ -++int iniparser_find_entry(dictionary * ini, char * entry) ; -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Parse an ini file and return an allocated dictionary object -++ @param ininame Name of the ini file to read. -++ @return Pointer to newly allocated dictionary -++ -++ This is the parser for ini files. This function is called, providing -++ the name of the file to be read. It returns a dictionary object that -++ should not be accessed directly, but through accessor functions -++ instead. -++ -++ The returned dictionary must be freed using iniparser_freedict(). -++ */ -++/*--------------------------------------------------------------------------*/ -++dictionary * iniparser_load(const char * ininame); -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Free all memory associated to an ini dictionary -++ @param d Dictionary to free -++ @return void -++ -++ Free all memory associated to an ini dictionary. -++ It is mandatory to call this function before the dictionary object -++ gets out of the current context. -++ */ -++/*--------------------------------------------------------------------------*/ -++void iniparser_freedict(dictionary * d); -++ -++#endif -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libmtd.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libmtd.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libmtd.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libmtd.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,73 @@ -++/* -++ * Copyright (C) 2008 Nokia Corporation -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem Bityutskiy -++ * -++ * MTD library. -++ */ -++ -++#ifndef __LIBMTD_H__ -++#define __LIBMTD_H__ -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++/** -++ * struct mtd_info - information about an MTD device. -++ * @num: MTD device number -++ * @major: major number of corresponding character device -++ * @minor: minor number of corresponding character device -++ * @type: flash type (constants like %MTD_NANDFLASH defined in mtd-abi.h) -++ * @type_str: static R/O flash type string -++ * @size: device size in bytes -++ * @eb_cnt: count of eraseblocks -++ * @eb_size: eraseblock size -++ * @min_io_size: minimum input/output unit size -++ * @subpage_size: sub-page size (not set by 'mtd_get_info()'!!!) -++ * @rdonly: non-zero if the device is read-only -++ * @allows_bb: non-zero if the MTD device may have bad eraseblocks -++ * @fd: descriptor of the opened MTD character device node -++ */ -++struct mtd_info -++{ -++ int num; -++ int major; -++ int minor; -++ int type; -++ const char *type_str; -++ long long size; -++ int eb_cnt; -++ int eb_size; -++ int min_io_size; -++ int subpage_size; -++ unsigned int rdonly:1; -++ unsigned int allows_bb:1; -++ int fd; -++}; -++ -++int mtd_get_info(const char *node, struct mtd_info *mtd); -++int mtd_erase(const struct mtd_info *mtd, int eb); -++int mtd_is_bad(const struct mtd_info *mtd, int eb); -++int mtd_read(const struct mtd_info *mtd, int eb, int offs, void *buf, int len); -++int mtd_write(const struct mtd_info *mtd, int eb, int offs, void *buf, int len); -++ -++#ifdef __cplusplus -++} -++#endif -++ -++#endif /* __LIBMTD_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libscan.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libscan.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libscan.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libscan.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,112 @@ -++/* -++ * Copyright (C) 2008 Nokia Corporation -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem Bityutskiy -++ * -++ * UBI scanning library. -++ */ -++ -++#ifndef __LIBSCAN_H__ -++#define __LIBSCAN_H__ -++ -++#include -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++/* -++ * If an eraseblock does not contain an erase counter, this value is used -++ * instead of the erase counter. -++ */ -++#define NO_EC 0xFFFFFFFF -++ -++/* -++ * If an eraseblock contains a corrupted erase counter, this value is used -++ * instead of the erase counter. -++ */ -++#define CORRUPT_EC 0xFFFFFFFE -++ -++/* -++ * If an eraseblock does not contain an erase counter, one of these values is -++ * used. -++ * -++ * @EB_EMPTY: the eraseblock appeared to be empty -++ * @EB_CORRUPTED: the eraseblock contains corrupted erase counter header -++ * @EB_ALIEN: the eraseblock contains some non-UBI data -++ * @EC_MAX: maximum allowed erase counter value -++ */ -++enum -++{ -++ EB_EMPTY = 0xFFFFFFFF, -++ EB_CORRUPTED = 0xFFFFFFFE, -++ EB_ALIEN = 0xFFFFFFFD, -++ EB_BAD = 0xFFFFFFFC, -++ EC_MAX = UBI_MAX_ERASECOUNTER, -++}; -++ -++/** -++ * struct ubi_scan_info - UBI scanning information. -++ * @ec: erase counters or eraseblock status for all eraseblocks -++ * @mean_ec: mean erase counter -++ * @ok_cnt: count of eraseblock with correct erase counter header -++ * @empty_cnt: count of supposedly eraseblocks -++ * @corrupted_cnt: count of eraseblocks with corrupted erase counter header -++ * @alien_cnt: count of eraseblock containing non-ubi data -++ * @bad_cnt: count of bad eraseblocks -++ * @bad_cnt: count of non-bad eraseblocks -++ * @vid_hdr_offs: volume ID header offset from the found EC headers (%-1 means -++ * undefined) -++ * @data_offs: data offset from the found EC headers (%-1 means undefined) -++ */ -++struct ubi_scan_info -++{ -++ uint32_t *ec; -++ long long mean_ec; -++ int ok_cnt; -++ int empty_cnt; -++ int corrupted_cnt; -++ int alien_cnt; -++ int bad_cnt; -++ int good_cnt; -++ int vid_hdr_offs; -++ int data_offs; -++}; -++ -++struct mtd_info; -++ -++/** -++ * ubi_scan - scan an MTD device. -++ * @mtd: information about the MTD device to scan -++ * @info: the result of the scanning is returned here -++ * @verbose: verbose mode: %0 - be silent, %1 - output progress information, -++ * 2 - debugging output mode -++ */ -++int ubi_scan(struct mtd_info *mtd, struct ubi_scan_info **info, int verbose); -++ -++/** -++ * ubi_scan_free - free scanning information. -++ * @si: scanning information to free -++ */ -++void ubi_scan_free(struct ubi_scan_info *si); -++ -++#ifdef __cplusplus -++} -++#endif -++ -++#endif /* __LIBSCAN_H__ */ -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libubi.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libubi.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libubi.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libubi.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,382 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem Bityutskiy -++ * -++ * UBI (Unsorted Block Images) library. -++ */ -++ -++#ifndef __LIBUBI_H__ -++#define __LIBUBI_H__ -++ -++#include -++#include -++#include -++#include -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++/* UBI version libubi is made for */ -++#define LIBUBI_UBI_VERSION 1 -++ -++/* UBI library descriptor */ -++typedef void * libubi_t; -++ -++/** -++ * struct ubi_attach_request - MTD device attachement request. -++ * @dev_num: number to assigne to the newly created UBI device -++ * (%UBI_DEV_NUM_AUTO should be used to automatically assign the -++ * number) -++ * @mtd_num: MTD device number to attach -++ * @vid_hdr_offset: VID header offset (%0 means default offset and this is what -++ * most of the users want) -++ */ -++struct ubi_attach_request -++{ -++ int dev_num; -++ int mtd_num; -++ int vid_hdr_offset; -++}; -++ -++/** -++ * struct ubi_mkvol_request - volume creation request. -++ * @vol_id: ID to assign to the new volume (%UBI_VOL_NUM_AUTO should be used to -++ * automatically assign ID) -++ * @alignment: volume alignment -++ * @bytes: volume size in bytes -++ * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) -++ * @name: volume name -++ */ -++struct ubi_mkvol_request -++{ -++ int vol_id; -++ int alignment; -++ long long bytes; -++ int vol_type; -++ const char *name; -++}; -++ -++/** -++ * struct ubi_info - general UBI information. -++ * @dev_count: count of UBI devices in system -++ * @lowest_dev_num: lowest UBI device number -++ * @highest_dev_num: highest UBI device number -++ * @version: UBI version -++ * @ctrl_major: major number of the UBI control device -++ * @ctrl_minor: minor number of the UBI control device -++ */ -++struct ubi_info -++{ -++ int dev_count; -++ int lowest_dev_num; -++ int highest_dev_num; -++ int version; -++ int ctrl_major; -++ int ctrl_minor; -++}; -++ -++/** -++ * struct ubi_dev_info - UBI device information. -++ * @vol_count: count of volumes on this UBI device -++ * @lowest_vol_num: lowest volume number -++ * @highest_vol_num: highest volume number -++ * @major: major number of corresponding character device -++ * @minor: minor number of corresponding character device -++ * @total_lebs: total number of logical eraseblocks on this UBI device -++ * @avail_lebs: how many logical eraseblocks are not used and available for new -++ * volumes -++ * @total_bytes: @total_lebs * @leb_size -++ * @avail_bytes: @avail_lebs * @leb_size -++ * @bad_count: count of bad physical eraseblocks -++ * @leb_size: logical eraseblock size -++ * @max_ec: current highest erase counter value -++ * @bad_rsvd: how many physical eraseblocks of the underlying flash device are -++ * reserved for bad eraseblocks handling -++ * @max_vol_count: maximum possible number of volumes on this UBI device -++ * @min_io_size: minimum input/output unit size of the UBI device -++ */ -++struct ubi_dev_info -++{ -++ int dev_num; -++ int vol_count; -++ int lowest_vol_num; -++ int highest_vol_num; -++ int major; -++ int minor; -++ int total_lebs; -++ int avail_lebs; -++ long long total_bytes; -++ long long avail_bytes; -++ int bad_count; -++ int leb_size; -++ long long max_ec; -++ int bad_rsvd; -++ int max_vol_count; -++ int min_io_size; -++}; -++ -++/** -++ * struct ubi_vol_info - UBI volume information. -++ * @dev_num: UBI device number the volume resides on -++ * @vol_id: ID of this volume -++ * @major: major number of corresponding volume character device -++ * @minor: minor number of corresponding volume character device -++ * @dev_major: major number of corresponding UBI device character device -++ * @dev_minor: minor number of corresponding UBI device character device -++ * @type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) -++ * @alignment: alignemnt of this volume -++ * @data_bytes: how many data bytes are stored on this volume (equivalent to -++ * @rsvd_bytes for dynamic volumes) -++ * @rsvd_bytes: how many bytes are reserved for this volume -++ * @rsvd_lebs: how many logical eraseblocks are reserved for this volume -++ * @leb_size: logical eraseblock size of this volume (may be less then -++ * device's logical eraseblock size due to alignment) -++ * @corrupted: non-zero if the volume is corrupted -++ * @name: volume name (null-terminated) -++ */ -++struct ubi_vol_info -++{ -++ int dev_num; -++ int vol_id; -++ int major; -++ int minor; -++ int dev_major; -++ int dev_minor; -++ int type; -++ int alignment; -++ long long data_bytes; -++ long long rsvd_bytes; -++ int rsvd_lebs; -++ int leb_size; -++ int corrupted; -++ char name[UBI_VOL_NAME_MAX + 1]; -++}; -++ -++/** -++ * libubi_open - open UBI library. -++ * @required: if non-zero, libubi will print an error messages if this UBI is -++ * not present in the system -++ * -++ * This function initializes and opens the UBI library and returns UBI library -++ * descriptor in case of success and %NULL in case of failure. -++ */ -++libubi_t libubi_open(int required); -++ -++/** -++ * libubi_close - close UBI library. -++ * @desc UBI library descriptor -++ */ -++void libubi_close(libubi_t desc); -++ -++/** -++ * ubi_get_info - get general UBI information. -++ * @desc: UBI library descriptor -++ * @info: pointer to the &struct ubi_info object to fill -++ * -++ * This function fills the passed @info object with general UBI information and -++ * returns %0 in case of success and %-1 in case of failure. -++ */ -++int ubi_get_info(libubi_t desc, struct ubi_info *info); -++ -++/** -++ * mtd_num2ubi_dev - find UBI device by attached MTD device. -++ * @@desc: UBI library descriptor -++ * @mtd_num: MTD device number -++ * @dev_num: UBI device number is returned here -++ * -++ * This function finds UBI device to which MTD device @mtd_num is attached. -++ * Returns %0 if the UBI device was found and %-1 if not. -++ */ -++int mtd_num2ubi_dev(libubi_t desc, int mtd_num, int *dev_num); -++ -++/** -++ * ubi_attach_mtd - attach MTD device to UBI. -++ * @desc: UBI library descriptor -++ * @node: name of the UBI control character device node -++ * @req: MTD attach request. -++ * -++ * This function creates a new UBI device by attaching an MTD device as -++ * described by @req. Returns %0 in case of success and %-1 in case of failure. -++ * The newly created UBI device number is returned in @req->dev_num. -++ */ -++int ubi_attach_mtd(libubi_t desc, const char *node, -++ struct ubi_attach_request *req); -++ -++/** -++ * ubi_detach_mtd - detach an MTD device. -++ * @desc: UBI library descriptor -++ * @node: name of the UBI control character device node -++ * @mtd_num: MTD device number to detach -++ * -++ * This function detaches MTD device number @mtd_num from UBI, which means the -++ * corresponding UBI device is removed. Returns zero in case of success and %-1 -++ * in case of failure. -++ */ -++int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num); -++ -++/** -++ * ubi_remove_dev - remove an UBI device. -++ * @desc: UBI library descriptor -++ * @node: name of the UBI control character device node -++ * @ubi_dev: UBI device number to remove -++ * -++ * This function removes UBI device number @ubi_dev and returns zero in case of -++ * success and %-1 in case of failure. -++ */ -++int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev); -++ -++/** -++ * ubi_mkvol - create an UBI volume. -++ * @desc: UBI library descriptor -++ * @node: name of the UBI character device to create a volume at -++ * @req: UBI volume creation request -++ * -++ * This function creates a UBI volume as described at @req and returns %0 in -++ * case of success and %-1 in case of failure. The assigned volume ID is -++ * returned in @req->vol_id. -++ */ -++int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req); -++ -++/** -++ * ubi_rmvol - remove a UBI volume. -++ * @desc: UBI library descriptor -++ * @node: name of the UBI character device to remove a volume from -++ * @vol_id: ID of the volume to remove -++ * -++ * This function removes volume @vol_id from UBI device @node and returns %0 in -++ * case of success and %-1 in case of failure. -++ */ -++int ubi_rmvol(libubi_t desc, const char *node, int vol_id); -++ -++/** -++ * ubi_rsvol - re-size UBI volume. -++ * @desc: UBI library descriptor -++ * @node: name of the UBI character device owning the volume which should be -++ * re-sized -++ * @vol_id: volume ID to re-size -++ * @bytes: new volume size in bytes -++ * -++ * This function returns %0 in case of success and %-1 in case of error. -++ */ -++int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes); -++ -++/** -++ * ubi_node_type - test UBI node type. -++ * @desc: UBI library descriptor -++ * @node: the node to test -++ * -++ * This function tests whether @node is a UBI device or volume node and returns -++ * %1 if this is an UBI device node, %2 if this is a volume node, and %-1 if -++ * this is not an UBI node or if an error occurred (the latter is indicated by -++ * a non-zero errno). -++ */ -++int ubi_node_type(libubi_t desc, const char *node); -++ -++/** -++ * ubi_get_dev_info - get UBI device information. -++ * @desc: UBI library descriptor -++ * @node: name of the UBI character device to fetch information about -++ * @info: pointer to the &struct ubi_dev_info object to fill -++ * -++ * This function fills the passed @info object with UBI device information and -++ * returns %0 in case of success and %-1 in case of failure. -++ */ -++int ubi_get_dev_info(libubi_t desc, const char *node, -++ struct ubi_dev_info *info); -++ -++/** -++ * ubi_get_dev_info1 - get UBI device information. -++ * @desc: UBI library descriptor -++ * @dev_num: UBI device number to fetch information about -++ * @info: pointer to the &struct ubi_dev_info object to fill -++ * -++ * This function is identical to 'ubi_get_dev_info()' except that it accepts UBI -++ * device number, not UBI character device. -++ */ -++int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info); -++ -++/** -++ * ubi_get_vol_info - get UBI volume information. -++ * @desc: UBI library descriptor -++ * @node: name of the UBI volume character device to fetch information about -++ * @info: pointer to the &struct ubi_vol_info object to fill -++ * -++ * This function fills the passed @info object with UBI volume information and -++ * returns %0 in case of success and %-1 in case of failure. -++ */ -++int ubi_get_vol_info(libubi_t desc, const char *node, -++ struct ubi_vol_info *info); -++ -++/** -++ * ubi_get_vol_info1 - get UBI volume information. -++ * @desc: UBI library descriptor -++ * @dev_num: UBI device number -++ * @vol_id: ID of the UBI volume to fetch information about -++ * @info: pointer to the &struct ubi_vol_info object to fill -++ * -++ * This function is identical to 'ubi_get_vol_info()' except that it accepts UBI -++ * volume number, not UBI volume character device. -++ */ -++int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id, -++ struct ubi_vol_info *info); -++ -++/** -++ * ubi_update_start - start UBI volume update. -++ * @desc: UBI library descriptor -++ * @fd: volume character devie file descriptor -++ * @bytes: how many bytes will be written to the volume -++ * -++ * This function initiates UBI volume update and returns %0 in case of success -++ * and %-1 in case of error. The caller is assumed to write @bytes data to the -++ * volume @fd afterwards. -++ */ -++int ubi_update_start(libubi_t desc, int fd, long long bytes); -++ -++ -++/** -++ * ubi_leb_read_start -++ * @fd: volume character devie file descriptor -++ * @leb: structure pointer for volume dump request -++ * -++ * This function call "UBI_IOCLEBREAD" ioctl. -++ * return %1 means the LEB is not mapped, no need to dump -++ * return %0 LEB read done successful -++ * return any others error -++ */ -++int ubi_leb_read_start(int fd, struct ubi_leb *leb); -++ -++/** -++ * ubi_leb_change_start - start atomic LEB change. -++ * @desc: UBI library descriptor -++ * @fd: volume character devie file descriptor -++ * @lnum: LEB number to change -++ * @bytes: how many bytes of new data will be written to the LEB -++ * @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN) -++ * -++ * This function initiates atomic LEB change operation and returns %0 in case -++ * of success and %-1 in case of error. he caller is assumed to write @bytes -++ * data to the volume @fd afterwards. -++ */ -++int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype); -++ -++#ifdef __cplusplus -++} -++#endif -++ -++#endif /* !__LIBUBI_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libubigen.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libubigen.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libubigen.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/include/libubigen.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,110 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * Copyright (C) 2008 Nokia Corporation -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * Authors: Frank Haverkamp -++ * Artem Bityutskiy -++ */ -++ -++#ifndef __LIBUBIGEN_H__ -++#define __LIBUBIGEN_H__ -++ -++#include -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++/** -++ * struct ubigen_info - libubigen information. -++ * @leb_size: logical eraseblock size -++ * @peb_size: size of the physical eraseblock -++ * @min_io_size: minimum input/output unit size -++ * @vid_hdr_offs: offset of the VID header -++ * @data_offs: data offset -++ * @ubi_ver: UBI version -++ * @vtbl_size: volume table size -++ * @max_volumes: maximum amount of volumes -++ */ -++struct ubigen_info -++{ -++ int leb_size; -++ int peb_size; -++ int min_io_size; -++ int vid_hdr_offs; -++ int data_offs; -++ int ubi_ver; -++ int vtbl_size; -++ int max_volumes; -++}; -++ -++/** -++ * struct ubigen_vol_info - information about a volume. -++ * @id: volume id -++ * @type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC) -++ * @alignment: volume alignment -++ * @data_pad: how many bytes are unused at the end of the each physical -++ * eraseblock to satisfy the requested alignment -++ * @usable_leb_size: LEB size accessible for volume users -++ * @name: volume name -++ * @name_len: volume name length -++ * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE, -++ * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT) -++ * @used_ebs: total number of used logical eraseblocks in this volume (relevant -++ * for static volumes only) -++ * @bytes: size of the volume contents in bytes (relevant for static volumes -++ * only) -++ * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG) -++ */ -++struct ubigen_vol_info -++{ -++ int id; -++ int type; -++ int alignment; -++ int data_pad; -++ int usable_leb_size; -++ const char *name; -++ int name_len; -++ int compat; -++ int used_ebs; -++ long long bytes; -++ uint8_t flags; -++}; -++ -++void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size, -++ int subpage_size, int vid_hdr_offs, int ubi_ver); -++struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui); -++void ubigen_init_ec_hdr(const struct ubigen_info *ui, -++ struct ubi_ec_hdr *hdr, long long ec); -++int ubigen_get_vtbl_size(const struct ubigen_info *ui); -++int ubigen_add_volume(const struct ubigen_info *ui, -++ const struct ubigen_vol_info *vi, -++ struct ubi_vtbl_record *vtbl); -++int ubigen_write_volume(const struct ubigen_info *ui, -++ const struct ubigen_vol_info *vi, long long ec, -++ long long bytes, int in, int out); -++int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2, -++ long long ec1, long long ec2, -++ struct ubi_vtbl_record *vtbl, int fd); -++ -++#ifdef __cplusplus -++} -++#endif -++ -++#endif /* !__LIBUBIGEN_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/common.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/common.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/common.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/common.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,194 @@ -++/* -++ * Copyright (C) 2007, 2008 Nokia Corporation -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * This file contains various common stuff used by UBI utilities. -++ * -++ * Authors: Artem Bityutskiy -++ * Adrian Hunter -++ */ -++ -++#include -++#include -++#include -++#include -++ -++/** -++ * get_multiplier - convert size specifier to an integer multiplier. -++ * @str: the size specifier string -++ * -++ * This function parses the @str size specifier, which may be one of -++ * 'KiB', 'MiB', or 'GiB' into an integer multiplier. Returns positive -++ * size multiplier in case of success and %-1 in case of failure. -++ */ -++static int get_multiplier(const char *str) -++{ -++ if (!str) -++ return 1; -++ -++ /* Remove spaces before the specifier */ -++ while (*str == ' ' || *str == '\t') -++ str += 1; -++ -++ if (!strcmp(str, "KiB")) -++ return 1024; -++ if (!strcmp(str, "MiB")) -++ return 1024 * 1024; -++ if (!strcmp(str, "GiB")) -++ return 1024 * 1024 * 1024; -++ -++ /* Handle deprecated stuff */ -++ if (!strcmp(str, "KB") || !strcmp(str, "Kib") || !strcmp(str, "kib") || -++ !strcmp(str, "kiB")) { -++ fprintf(stderr, "Warning: use \"KiB\" instead of \"%s\" to " -++ "specify Kilobytes - support will be removed\n", str); -++ return 1024; -++ } -++ if (!strcmp(str, "MB") || !strcmp(str, "Mib") || !strcmp(str, "mb")) { -++ fprintf(stderr, "Warning: use \"MiB\" instead of \"%s\", " -++ "this support will be removed\n", str); -++ return 1024*1024; -++ } -++ if (!strcmp(str, "GB") || !strcmp(str, "Gib") || !strcmp(str, "gb")) { -++ fprintf(stderr, "Warning: use \"GiB\" instead of \"%s\", " -++ "this support will be removed\n", str); -++ return 1024*1024*1024; -++ } -++ -++ return -1; -++} -++ -++/** -++ * ubiutils_get_bytes - convert a string containing amount of bytes into an -++ * integer -++ * @str: string to convert -++ * -++ * This function parses @str which may have one of 'KiB', 'MiB', or 'GiB' -++ * size specifiers. Returns positive amount of bytes in case of success and %-1 -++ * in case of failure. -++ */ -++long long ubiutils_get_bytes(const char *str) -++{ -++ char *endp; -++ long long bytes = strtoull(str, &endp, 0); -++ -++ if (endp == str || bytes < 0) { -++ fprintf(stderr, "incorrect amount of bytes: \"%s\"\n", str); -++ return -1; -++ } -++ -++ if (*endp != '\0') { -++ int mult = get_multiplier(endp); -++ -++ if (mult == -1) { -++ fprintf(stderr, "bad size specifier: \"%s\" - " -++ "should be 'KiB', 'MiB' or 'GiB'\n", endp); -++ return -1; -++ } -++ bytes *= mult; -++ } -++ -++ return bytes; -++} -++ -++/** -++ * ubiutils_print_bytes - print bytes. -++ * @bytes: variable to print -++ * @bracket: whether brackets have to be put or not -++ * -++ * This is a helper function which prints amount of bytes in a human-readable -++ * form, i.e., it prints the exact amount of bytes following by the approximate -++ * amount of Kilobytes, Megabytes, or Gigabytes, depending on how big @bytes -++ * is. -++ */ -++void ubiutils_print_bytes(long long bytes, int bracket) -++{ -++ const char *p; -++ -++ if (bracket) -++ p = " ("; -++ else -++ p = ", "; -++ -++ printf("%lld bytes", bytes); -++ -++ if (bytes > 1024 * 1024 * 1024) -++ printf("%s%.1f GiB", p, (double)bytes / (1024 * 1024 * 1024)); -++ else if (bytes > 1024 * 1024) -++ printf("%s%.1f MiB", p, (double)bytes / (1024 * 1024)); -++ else if (bytes > 1024 && bytes != 0) -++ printf("%s%.1f KiB", p, (double)bytes / 1024); -++ else -++ return; -++ -++ if (bracket) -++ printf(")"); -++} -++ -++/** -++ * ubiutils_print_text - print text and fold it. -++ * @stream: file stream to print to -++ * @text: text to print -++ * @width: maximum allowed text width -++ * -++ * Print text and fold it so that each line would not have more then @width -++ * characters. -++ */ -++void ubiutils_print_text(FILE *stream, const char *text, int width) -++{ -++ int pos, bpos = 0; -++ const char *p; -++ char line[1024]; -++ -++ if (width > 1023) { -++ fprintf(stream, "%s\n", text); -++ return; -++ } -++ p = text; -++ pos = 0; -++ while (p[pos]) { -++ while (!isspace(p[pos])) { -++ line[pos] = p[pos]; -++ if (!p[pos]) -++ break; -++ ++pos; -++ if (pos == width) { -++ line[pos] = '\0'; -++ fprintf(stream, "%s\n", line); -++ p += pos; -++ pos = 0; -++ } -++ } -++ while (pos < width) { -++ line[pos] = p[pos]; -++ if (!p[pos]) { -++ bpos = pos; -++ break; -++ } -++ if (isspace(p[pos])) -++ bpos = pos; -++ ++pos; -++ } -++ line[bpos] = '\0'; -++ fprintf(stream, "%s\n", line); -++ p += bpos; -++ pos = 0; -++ while (p[pos] && isspace(p[pos])) -++ ++p; -++ } -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/common.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/common.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/common.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/common.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,84 @@ -++/* -++ * Copyright (c) Artem Bityutskiy, 2007, 2008 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++#ifndef __UBI_UTILS_COMMON_H__ -++#define __UBI_UTILS_COMMON_H__ -++ -++#include -++#include -++#include -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++#define MIN(a ,b) ((a) < (b) ? (a) : (b)) -++#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -++ -++/* Verbose messages */ -++#define verbose(verbose, fmt, ...) do { \ -++ if (verbose) \ -++ printf(PROGRAM_NAME ": " fmt "\n", ##__VA_ARGS__); \ -++} while(0) -++ -++/* Normal messages */ -++#define normsg(fmt, ...) do { \ -++ printf(PROGRAM_NAME ": " fmt "\n", ##__VA_ARGS__); \ -++} while(0) -++#define normsg_cont(fmt, ...) do { \ -++ printf(PROGRAM_NAME ": " fmt, ##__VA_ARGS__); \ -++} while(0) -++#define normsg_cont(fmt, ...) do { \ -++ printf(PROGRAM_NAME ": " fmt, ##__VA_ARGS__); \ -++} while(0) -++ -++/* Error messages */ -++#define errmsg(fmt, ...) ({ \ -++ fprintf(stderr, PROGRAM_NAME ": error!: " fmt "\n", ##__VA_ARGS__); \ -++ -1; \ -++}) -++ -++/* System error messages */ -++#define sys_errmsg(fmt, ...) ({ \ -++ int _err = errno, _i; \ -++ fprintf(stderr, PROGRAM_NAME ": error!: " fmt "\n", ##__VA_ARGS__); \ -++ for (_i = 0; _i < sizeof(PROGRAM_NAME) + 1; _i++) \ -++ fprintf(stderr, " "); \ -++ fprintf(stderr, "error %d (%s)\n", _err, strerror(_err)); \ -++ -1; \ -++}) -++ -++/* Warnings */ -++#define warnmsg(fmt, ...) do { \ -++ fprintf(stderr, PROGRAM_NAME ": warning!: " fmt "\n", ##__VA_ARGS__); \ -++} while(0) -++ -++static inline int is_power_of_2(unsigned long long n) -++{ -++ return (n != 0 && ((n & (n - 1)) == 0)); -++} -++ -++long long ubiutils_get_bytes(const char *str); -++void ubiutils_print_bytes(long long bytes, int bracket); -++void ubiutils_print_text(FILE *stream, const char *txt, int len); -++ -++#ifdef __cplusplus -++} -++#endif -++ -++#endif /* !__UBI_UTILS_COMMON_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/crc32.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/crc32.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/crc32.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/crc32.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,95 @@ -++/* -++ * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or -++ * code or tables extracted from it, as desired without restriction. -++ * -++ * First, the polynomial itself and its table of feedback terms. The -++ * polynomial is -++ * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 -++ * -++ * Note that we take it "backwards" and put the highest-order term in -++ * the lowest-order bit. The X^32 term is "implied"; the LSB is the -++ * X^31 term, etc. The X^0 term (usually shown as "+1") results in -++ * the MSB being 1 -++ * -++ * Note that the usual hardware shift register implementation, which -++ * is what we're using (we're merely optimizing it by doing eight-bit -++ * chunks at a time) shifts bits into the lowest-order term. In our -++ * implementation, that means shifting towards the right. Why do we -++ * do it this way? Because the calculated CRC must be transmitted in -++ * order from highest-order term to lowest-order term. UARTs transmit -++ * characters in order from LSB to MSB. By storing the CRC this way -++ * we hand it to the UART in the order low-byte to high-byte; the UART -++ * sends each low-bit to hight-bit; and the result is transmission bit -++ * by bit from highest- to lowest-order term without requiring any bit -++ * shuffling on our part. Reception works similarly -++ * -++ * The feedback terms table consists of 256, 32-bit entries. Notes -++ * -++ * The table can be generated at runtime if desired; code to do so -++ * is shown later. It might not be obvious, but the feedback -++ * terms simply represent the results of eight shift/xor opera -++ * tions for all combinations of data and CRC register values -++ * -++ * The values must be right-shifted by eight bits by the "updcrc -++ * logic; the shift must be unsigned (bring in zeroes). On some -++ * hardware you could probably optimize the shift in assembler by -++ * using byte-swap instructions -++ * polynomial $edb88320 -++ */ -++ -++#include -++ -++const uint32_t crc32_table[256] = { -++ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, -++ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, -++ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, -++ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, -++ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, -++ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, -++ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, -++ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, -++ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, -++ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, -++ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, -++ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, -++ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, -++ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, -++ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, -++ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, -++ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, -++ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, -++ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, -++ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, -++ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, -++ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, -++ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, -++ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, -++ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, -++ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, -++ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, -++ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, -++ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, -++ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, -++ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, -++ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, -++ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, -++ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, -++ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, -++ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, -++ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, -++ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, -++ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, -++ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, -++ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, -++ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, -++ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, -++ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, -++ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, -++ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, -++ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, -++ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, -++ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, -++ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, -++ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, -++ 0x2d02ef8dL -++}; -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/crc32.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/crc32.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/crc32.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/crc32.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,19 @@ -++#ifndef CRC32_H -++#define CRC32_H -++ -++#include -++ -++extern const uint32_t crc32_table[256]; -++ -++/* Return a 32-bit CRC of the contents of the buffer. */ -++ -++ static inline uint32_t -++crc32(uint32_t val, const void *ss, int len) -++{ -++ const unsigned char *s = ss; -++ while (--len >= 0) -++ val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8); -++ return val; -++} -++ -++#endif -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/dictionary.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/dictionary.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/dictionary.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/dictionary.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,405 @@ -++/*-------------------------------------------------------------------------*/ -++/** -++ @file dictionary.c -++ @author N. Devillard -++ @date Sep 2007 -++ @version $Revision: 1.1.1.1 $ -++ @brief Implements a dictionary for string variables. -++ -++ This module implements a simple dictionary object, i.e. a list -++ of string/string associations. This object is useful to store e.g. -++ informations retrieved from a configuration file (ini files). -++*/ -++/*--------------------------------------------------------------------------*/ -++ -++/* -++ $Id: dictionary.c,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ -++ $Revision: 1.1.1.1 $ -++*/ -++/*--------------------------------------------------------------------------- -++ Includes -++ ---------------------------------------------------------------------------*/ -++#include "dictionary.h" -++ -++#include -++#include -++#include -++#include -++ -++/** Maximum value size for integers and doubles. */ -++#define MAXVALSZ 1024 -++ -++/** Minimal allocated number of entries in a dictionary */ -++#define DICTMINSZ 128 -++ -++/** Invalid key token */ -++#define DICT_INVALID_KEY ((char*)-1) -++ -++/*--------------------------------------------------------------------------- -++ Private functions -++ ---------------------------------------------------------------------------*/ -++ -++/* Doubles the allocated size associated to a pointer */ -++/* 'size' is the current allocated size. */ -++static void * mem_double(void * ptr, int size) -++{ -++ void * newptr ; -++ -++ newptr = calloc(2*size, 1); -++ if (newptr==NULL) { -++ return NULL ; -++ } -++ memcpy(newptr, ptr, size); -++ free(ptr); -++ return newptr ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Duplicate a string -++ @param s String to duplicate -++ @return Pointer to a newly allocated string, to be freed with free() -++ -++ This is a replacement for strdup(). This implementation is provided -++ for systems that do not have it. -++ */ -++/*--------------------------------------------------------------------------*/ -++static char * xstrdup(char * s) -++{ -++ char * t ; -++ if (!s) -++ return NULL ; -++ t = malloc(strlen(s)+1) ; -++ if (t) { -++ strcpy(t,s); -++ } -++ return t ; -++} -++ -++/*--------------------------------------------------------------------------- -++ Function codes -++ ---------------------------------------------------------------------------*/ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Compute the hash key for a string. -++ @param key Character string to use for key. -++ @return 1 unsigned int on at least 32 bits. -++ -++ This hash function has been taken from an Article in Dr Dobbs Journal. -++ This is normally a collision-free function, distributing keys evenly. -++ The key is stored anyway in the struct so that collision can be avoided -++ by comparing the key itself in last resort. -++ */ -++/*--------------------------------------------------------------------------*/ -++unsigned dictionary_hash(char * key) -++{ -++ int len ; -++ unsigned hash ; -++ int i ; -++ -++ len = strlen(key); -++ for (hash=0, i=0 ; i>6) ; -++ } -++ hash += (hash <<3); -++ hash ^= (hash >>11); -++ hash += (hash <<15); -++ return hash ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Create a new dictionary object. -++ @param size Optional initial size of the dictionary. -++ @return 1 newly allocated dictionary objet. -++ -++ This function allocates a new dictionary object of given size and returns -++ it. If you do not know in advance (roughly) the number of entries in the -++ dictionary, give size=0. -++ */ -++/*--------------------------------------------------------------------------*/ -++dictionary * dictionary_new(int size) -++{ -++ dictionary * d ; -++ -++ /* If no size was specified, allocate space for DICTMINSZ */ -++ if (sizesize = size ; -++ d->val = (char **)calloc(size, sizeof(char*)); -++ d->key = (char **)calloc(size, sizeof(char*)); -++ d->hash = (unsigned int *)calloc(size, sizeof(unsigned)); -++ return d ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Delete a dictionary object -++ @param d dictionary object to deallocate. -++ @return void -++ -++ Deallocate a dictionary object and all memory associated to it. -++ */ -++/*--------------------------------------------------------------------------*/ -++void dictionary_del(dictionary * d) -++{ -++ int i ; -++ -++ if (d==NULL) return ; -++ for (i=0 ; isize ; i++) { -++ if (d->key[i]!=NULL) -++ free(d->key[i]); -++ if (d->val[i]!=NULL) -++ free(d->val[i]); -++ } -++ free(d->val); -++ free(d->key); -++ free(d->hash); -++ free(d); -++ return ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Get a value from a dictionary. -++ @param d dictionary object to search. -++ @param key Key to look for in the dictionary. -++ @param def Default value to return if key not found. -++ @return 1 pointer to internally allocated character string. -++ -++ This function locates a key in a dictionary and returns a pointer to its -++ value, or the passed 'def' pointer if no such key can be found in -++ dictionary. The returned character pointer points to data internal to the -++ dictionary object, you should not try to free it or modify it. -++ */ -++/*--------------------------------------------------------------------------*/ -++char * dictionary_get(dictionary * d, char * key, char * def) -++{ -++ unsigned hash ; -++ int i ; -++ -++ hash = dictionary_hash(key); -++ for (i=0 ; isize ; i++) { -++ if (d->key[i]==NULL) -++ continue ; -++ /* Compare hash */ -++ if (hash==d->hash[i]) { -++ /* Compare string, to avoid hash collisions */ -++ if (!strcmp(key, d->key[i])) { -++ return d->val[i] ; -++ } -++ } -++ } -++ return def ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Set a value in a dictionary. -++ @param d dictionary object to modify. -++ @param key Key to modify or add. -++ @param val Value to add. -++ @return int 0 if Ok, anything else otherwise -++ -++ If the given key is found in the dictionary, the associated value is -++ replaced by the provided one. If the key cannot be found in the -++ dictionary, it is added to it. -++ -++ It is Ok to provide a NULL value for val, but NULL values for the dictionary -++ or the key are considered as errors: the function will return immediately -++ in such a case. -++ -++ Notice that if you dictionary_set a variable to NULL, a call to -++ dictionary_get will return a NULL value: the variable will be found, and -++ its value (NULL) is returned. In other words, setting the variable -++ content to NULL is equivalent to deleting the variable from the -++ dictionary. It is not possible (in this implementation) to have a key in -++ the dictionary without value. -++ -++ This function returns non-zero in case of failure. -++ */ -++/*--------------------------------------------------------------------------*/ -++int dictionary_set(dictionary * d, char * key, char * val) -++{ -++ int i ; -++ unsigned hash ; -++ -++ if (d==NULL || key==NULL) return -1 ; -++ -++ /* Compute hash for this key */ -++ hash = dictionary_hash(key) ; -++ /* Find if value is already in dictionary */ -++ if (d->n>0) { -++ for (i=0 ; isize ; i++) { -++ if (d->key[i]==NULL) -++ continue ; -++ if (hash==d->hash[i]) { /* Same hash value */ -++ if (!strcmp(key, d->key[i])) { /* Same key */ -++ /* Found a value: modify and return */ -++ if (d->val[i]!=NULL) -++ free(d->val[i]); -++ d->val[i] = val ? xstrdup(val) : NULL ; -++ /* Value has been modified: return */ -++ return 0 ; -++ } -++ } -++ } -++ } -++ /* Add a new value */ -++ /* See if dictionary needs to grow */ -++ if (d->n==d->size) { -++ -++ /* Reached maximum size: reallocate dictionary */ -++ d->val = (char **)mem_double(d->val, d->size * sizeof(char*)) ; -++ d->key = (char **)mem_double(d->key, d->size * sizeof(char*)) ; -++ d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ; -++ if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) { -++ /* Cannot grow dictionary */ -++ return -1 ; -++ } -++ /* Double size */ -++ d->size *= 2 ; -++ } -++ -++ /* Insert key in the first empty slot */ -++ for (i=0 ; isize ; i++) { -++ if (d->key[i]==NULL) { -++ /* Add key here */ -++ break ; -++ } -++ } -++ /* Copy key */ -++ d->key[i] = xstrdup(key); -++ d->val[i] = val ? xstrdup(val) : NULL ; -++ d->hash[i] = hash; -++ d->n ++ ; -++ return 0 ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Delete a key in a dictionary -++ @param d dictionary object to modify. -++ @param key Key to remove. -++ @return void -++ -++ This function deletes a key in a dictionary. Nothing is done if the -++ key cannot be found. -++ */ -++/*--------------------------------------------------------------------------*/ -++void dictionary_unset(dictionary * d, char * key) -++{ -++ unsigned hash ; -++ int i ; -++ -++ if (key == NULL) { -++ return; -++ } -++ -++ hash = dictionary_hash(key); -++ for (i=0 ; isize ; i++) { -++ if (d->key[i]==NULL) -++ continue ; -++ /* Compare hash */ -++ if (hash==d->hash[i]) { -++ /* Compare string, to avoid hash collisions */ -++ if (!strcmp(key, d->key[i])) { -++ /* Found key */ -++ break ; -++ } -++ } -++ } -++ if (i>=d->size) -++ /* Key not found */ -++ return ; -++ -++ free(d->key[i]); -++ d->key[i] = NULL ; -++ if (d->val[i]!=NULL) { -++ free(d->val[i]); -++ d->val[i] = NULL ; -++ } -++ d->hash[i] = 0 ; -++ d->n -- ; -++ return ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Dump a dictionary to an opened file pointer. -++ @param d Dictionary to dump -++ @param f Opened file pointer. -++ @return void -++ -++ Dumps a dictionary onto an opened file pointer. Key pairs are printed out -++ as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as -++ output file pointers. -++ */ -++/*--------------------------------------------------------------------------*/ -++void dictionary_dump(dictionary * d, FILE * out) -++{ -++ int i ; -++ -++ if (d==NULL || out==NULL) return ; -++ if (d->n<1) { -++ fprintf(out, "empty dictionary\n"); -++ return ; -++ } -++ for (i=0 ; isize ; i++) { -++ if (d->key[i]) { -++ fprintf(out, "%20s\t[%s]\n", -++ d->key[i], -++ d->val[i] ? d->val[i] : "UNDEF"); -++ } -++ } -++ return ; -++} -++ -++ -++/* Test code */ -++#ifdef TESTDIC -++#define NVALS 20000 -++int main(int argc, char *argv[]) -++{ -++ dictionary * d ; -++ char * val ; -++ int i ; -++ char cval[90] ; -++ -++ /* Allocate dictionary */ -++ printf("allocating...\n"); -++ d = dictionary_new(0); -++ -++ /* Set values in dictionary */ -++ printf("setting %d values...\n", NVALS); -++ for (i=0 ; in != 0) { -++ printf("error deleting values\n"); -++ } -++ printf("deallocating...\n"); -++ dictionary_del(d); -++ return 0 ; -++} -++#endif -++/* vim: set ts=4 et sw=4 tw=75 */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/dictionary.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/dictionary.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/dictionary.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/dictionary.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,174 @@ -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @file dictionary.h -++ @author N. Devillard -++ @date Sep 2007 -++ @version $Revision: 1.1.1.1 $ -++ @brief Implements a dictionary for string variables. -++ -++ This module implements a simple dictionary object, i.e. a list -++ of string/string associations. This object is useful to store e.g. -++ informations retrieved from a configuration file (ini files). -++*/ -++/*--------------------------------------------------------------------------*/ -++ -++/* -++ $Id: dictionary.h,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ -++ $Author: yrtan $ -++ $Date: 2008-05-13 07:15:32 $ -++ $Revision: 1.1.1.1 $ -++*/ -++ -++#ifndef _DICTIONARY_H_ -++#define _DICTIONARY_H_ -++ -++/*--------------------------------------------------------------------------- -++ Includes -++ ---------------------------------------------------------------------------*/ -++ -++#include -++#include -++#include -++#include -++ -++/*--------------------------------------------------------------------------- -++ New types -++ ---------------------------------------------------------------------------*/ -++ -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Dictionary object -++ -++ This object contains a list of string/string associations. Each -++ association is identified by a unique string key. Looking up values -++ in the dictionary is speeded up by the use of a (hopefully collision-free) -++ hash function. -++ */ -++/*-------------------------------------------------------------------------*/ -++typedef struct _dictionary_ { -++ int n ; /** Number of entries in dictionary */ -++ int size ; /** Storage size */ -++ char ** val ; /** List of string values */ -++ char ** key ; /** List of string keys */ -++ unsigned * hash ; /** List of hash values for keys */ -++} dictionary ; -++ -++ -++/*--------------------------------------------------------------------------- -++ Function prototypes -++ ---------------------------------------------------------------------------*/ -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Compute the hash key for a string. -++ @param key Character string to use for key. -++ @return 1 unsigned int on at least 32 bits. -++ -++ This hash function has been taken from an Article in Dr Dobbs Journal. -++ This is normally a collision-free function, distributing keys evenly. -++ The key is stored anyway in the struct so that collision can be avoided -++ by comparing the key itself in last resort. -++ */ -++/*--------------------------------------------------------------------------*/ -++unsigned dictionary_hash(char * key); -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Create a new dictionary object. -++ @param size Optional initial size of the dictionary. -++ @return 1 newly allocated dictionary objet. -++ -++ This function allocates a new dictionary object of given size and returns -++ it. If you do not know in advance (roughly) the number of entries in the -++ dictionary, give size=0. -++ */ -++/*--------------------------------------------------------------------------*/ -++dictionary * dictionary_new(int size); -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Delete a dictionary object -++ @param d dictionary object to deallocate. -++ @return void -++ -++ Deallocate a dictionary object and all memory associated to it. -++ */ -++/*--------------------------------------------------------------------------*/ -++void dictionary_del(dictionary * vd); -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Get a value from a dictionary. -++ @param d dictionary object to search. -++ @param key Key to look for in the dictionary. -++ @param def Default value to return if key not found. -++ @return 1 pointer to internally allocated character string. -++ -++ This function locates a key in a dictionary and returns a pointer to its -++ value, or the passed 'def' pointer if no such key can be found in -++ dictionary. The returned character pointer points to data internal to the -++ dictionary object, you should not try to free it or modify it. -++ */ -++/*--------------------------------------------------------------------------*/ -++char * dictionary_get(dictionary * d, char * key, char * def); -++ -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Set a value in a dictionary. -++ @param d dictionary object to modify. -++ @param key Key to modify or add. -++ @param val Value to add. -++ @return int 0 if Ok, anything else otherwise -++ -++ If the given key is found in the dictionary, the associated value is -++ replaced by the provided one. If the key cannot be found in the -++ dictionary, it is added to it. -++ -++ It is Ok to provide a NULL value for val, but NULL values for the dictionary -++ or the key are considered as errors: the function will return immediately -++ in such a case. -++ -++ Notice that if you dictionary_set a variable to NULL, a call to -++ dictionary_get will return a NULL value: the variable will be found, and -++ its value (NULL) is returned. In other words, setting the variable -++ content to NULL is equivalent to deleting the variable from the -++ dictionary. It is not possible (in this implementation) to have a key in -++ the dictionary without value. -++ -++ This function returns non-zero in case of failure. -++ */ -++/*--------------------------------------------------------------------------*/ -++int dictionary_set(dictionary * vd, char * key, char * val); -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Delete a key in a dictionary -++ @param d dictionary object to modify. -++ @param key Key to remove. -++ @return void -++ -++ This function deletes a key in a dictionary. Nothing is done if the -++ key cannot be found. -++ */ -++/*--------------------------------------------------------------------------*/ -++void dictionary_unset(dictionary * d, char * key); -++ -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Dump a dictionary to an opened file pointer. -++ @param d Dictionary to dump -++ @param f Opened file pointer. -++ @return void -++ -++ Dumps a dictionary onto an opened file pointer. Key pairs are printed out -++ as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as -++ output file pointers. -++ */ -++/*--------------------------------------------------------------------------*/ -++void dictionary_dump(dictionary * d, FILE * out); -++ -++#endif -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libiniparser.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libiniparser.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libiniparser.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libiniparser.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,646 @@ -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @file iniparser.c -++ @author N. Devillard -++ @date Sep 2007 -++ @version 3.0 -++ @brief Parser for ini files. -++*/ -++/*--------------------------------------------------------------------------*/ -++/* -++ $Id: libiniparser.c,v 1.1.1.1 2008-05-13 07:15:32 yrtan Exp $ -++ $Revision: 1.1.1.1 $ -++ $Date: 2008-05-13 07:15:32 $ -++*/ -++/*---------------------------- Includes ------------------------------------*/ -++#include -++#include -++ -++/*---------------------------- Defines -------------------------------------*/ -++#define ASCIILINESZ (1024) -++#define INI_INVALID_KEY ((char*)-1) -++ -++/*--------------------------------------------------------------------------- -++ Private to this module -++ ---------------------------------------------------------------------------*/ -++/** -++ * This enum stores the status for each parsed line (internal use only). -++ */ -++typedef enum _line_status_ { -++ LINE_UNPROCESSED, -++ LINE_ERROR, -++ LINE_EMPTY, -++ LINE_COMMENT, -++ LINE_SECTION, -++ LINE_VALUE -++} line_status ; -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Convert a string to lowercase. -++ @param s String to convert. -++ @return ptr to statically allocated string. -++ -++ This function returns a pointer to a statically allocated string -++ containing a lowercased version of the input string. Do not free -++ or modify the returned string! Since the returned string is statically -++ allocated, it will be modified at each function call (not re-entrant). -++ */ -++/*--------------------------------------------------------------------------*/ -++static char * strlwc(const char * s) -++{ -++ static char l[ASCIILINESZ+1]; -++ int i ; -++ -++ if (s==NULL) return NULL ; -++ memset(l, 0, ASCIILINESZ+1); -++ i=0 ; -++ while (s[i] && i l) { -++ if (!isspace((int)*(last-1))) -++ break ; -++ last -- ; -++ } -++ *last = (char)0; -++ return (char*)l ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Get number of sections in a dictionary -++ @param d Dictionary to examine -++ @return int Number of sections found in dictionary -++ -++ This function returns the number of sections found in a dictionary. -++ The test to recognize sections is done on the string stored in the -++ dictionary: a section name is given as "section" whereas a key is -++ stored as "section:key", thus the test looks for entries that do not -++ contain a colon. -++ -++ This clearly fails in the case a section name contains a colon, but -++ this should simply be avoided. -++ -++ This function returns -1 in case of error. -++ */ -++/*--------------------------------------------------------------------------*/ -++int iniparser_getnsec(dictionary * d) -++{ -++ int i ; -++ int nsec ; -++ -++ if (d==NULL) return -1 ; -++ nsec=0 ; -++ for (i=0 ; isize ; i++) { -++ if (d->key[i]==NULL) -++ continue ; -++ if (strchr(d->key[i], ':')==NULL) { -++ nsec ++ ; -++ } -++ } -++ return nsec ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Get name for section n in a dictionary. -++ @param d Dictionary to examine -++ @param n Section number (from 0 to nsec-1). -++ @return Pointer to char string -++ -++ This function locates the n-th section in a dictionary and returns -++ its name as a pointer to a string statically allocated inside the -++ dictionary. Do not free or modify the returned string! -++ -++ This function returns NULL in case of error. -++ */ -++/*--------------------------------------------------------------------------*/ -++char * iniparser_getsecname(dictionary * d, int n) -++{ -++ int i ; -++ int foundsec ; -++ -++ if (d==NULL || n<0) return NULL ; -++ foundsec=0 ; -++ for (i=0 ; isize ; i++) { -++ if (d->key[i]==NULL) -++ continue ; -++ if (strchr(d->key[i], ':')==NULL) { -++ foundsec++ ; -++ if (foundsec>n) -++ break ; -++ } -++ } -++ if (foundsec<=n) { -++ return NULL ; -++ } -++ return d->key[i] ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Dump a dictionary to an opened file pointer. -++ @param d Dictionary to dump. -++ @param f Opened file pointer to dump to. -++ @return void -++ -++ This function prints out the contents of a dictionary, one element by -++ line, onto the provided file pointer. It is OK to specify @c stderr -++ or @c stdout as output files. This function is meant for debugging -++ purposes mostly. -++ */ -++/*--------------------------------------------------------------------------*/ -++void iniparser_dump(dictionary * d, FILE * f) -++{ -++ int i ; -++ -++ if (d==NULL || f==NULL) return ; -++ for (i=0 ; isize ; i++) { -++ if (d->key[i]==NULL) -++ continue ; -++ if (d->val[i]!=NULL) { -++ fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]); -++ } else { -++ fprintf(f, "[%s]=UNDEF\n", d->key[i]); -++ } -++ } -++ return ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Save a dictionary to a loadable ini file -++ @param d Dictionary to dump -++ @param f Opened file pointer to dump to -++ @return void -++ -++ This function dumps a given dictionary into a loadable ini file. -++ It is Ok to specify @c stderr or @c stdout as output files. -++ */ -++/*--------------------------------------------------------------------------*/ -++void iniparser_dump_ini(dictionary * d, FILE * f) -++{ -++ int i, j ; -++ char keym[ASCIILINESZ+1]; -++ int nsec ; -++ char * secname ; -++ int seclen ; -++ -++ if (d==NULL || f==NULL) return ; -++ -++ nsec = iniparser_getnsec(d); -++ if (nsec<1) { -++ /* No section in file: dump all keys as they are */ -++ for (i=0 ; isize ; i++) { -++ if (d->key[i]==NULL) -++ continue ; -++ fprintf(f, "%s = %s\n", d->key[i], d->val[i]); -++ } -++ return ; -++ } -++ for (i=0 ; isize ; j++) { -++ if (d->key[j]==NULL) -++ continue ; -++ if (!strncmp(d->key[j], keym, seclen+1)) { -++ fprintf(f, -++ "%-30s = %s\n", -++ d->key[j]+seclen+1, -++ d->val[j] ? d->val[j] : ""); -++ } -++ } -++ } -++ fprintf(f, "\n"); -++ return ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Get the string associated to a key -++ @param d Dictionary to search -++ @param key Key string to look for -++ @param def Default value to return if key not found. -++ @return pointer to statically allocated character string -++ -++ This function queries a dictionary for a key. A key as read from an -++ ini file is given as "section:key". If the key cannot be found, -++ the pointer passed as 'def' is returned. -++ The returned char pointer is pointing to a string allocated in -++ the dictionary, do not free or modify it. -++ */ -++/*--------------------------------------------------------------------------*/ -++char * iniparser_getstring(dictionary * d, const char * key, char * def) -++{ -++ char * lc_key ; -++ char * sval ; -++ -++ if (d==NULL || key==NULL) -++ return def ; -++ -++ lc_key = strlwc(key); -++ sval = dictionary_get(d, lc_key, def); -++ return sval ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Get the string associated to a key, convert to an int -++ @param d Dictionary to search -++ @param key Key string to look for -++ @param notfound Value to return in case of error -++ @return integer -++ -++ This function queries a dictionary for a key. A key as read from an -++ ini file is given as "section:key". If the key cannot be found, -++ the notfound value is returned. -++ -++ Supported values for integers include the usual C notation -++ so decimal, octal (starting with 0) and hexadecimal (starting with 0x) -++ are supported. Examples: -++ -++ "42" -> 42 -++ "042" -> 34 (octal -> decimal) -++ "0x42" -> 66 (hexa -> decimal) -++ -++ Warning: the conversion may overflow in various ways. Conversion is -++ totally outsourced to strtol(), see the associated man page for overflow -++ handling. -++ -++ Credits: Thanks to A. Becker for suggesting strtol() -++ */ -++/*--------------------------------------------------------------------------*/ -++int iniparser_getint(dictionary * d, const char * key, int notfound) -++{ -++ char * str ; -++ -++ str = iniparser_getstring(d, key, INI_INVALID_KEY); -++ if (str==INI_INVALID_KEY) return notfound ; -++ return (int)strtol(str, NULL, 0); -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Get the string associated to a key, convert to a double -++ @param d Dictionary to search -++ @param key Key string to look for -++ @param notfound Value to return in case of error -++ @return double -++ -++ This function queries a dictionary for a key. A key as read from an -++ ini file is given as "section:key". If the key cannot be found, -++ the notfound value is returned. -++ */ -++/*--------------------------------------------------------------------------*/ -++double iniparser_getdouble(dictionary * d, char * key, double notfound) -++{ -++ char * str ; -++ -++ str = iniparser_getstring(d, key, INI_INVALID_KEY); -++ if (str==INI_INVALID_KEY) return notfound ; -++ return atof(str); -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Get the string associated to a key, convert to a boolean -++ @param d Dictionary to search -++ @param key Key string to look for -++ @param notfound Value to return in case of error -++ @return integer -++ -++ This function queries a dictionary for a key. A key as read from an -++ ini file is given as "section:key". If the key cannot be found, -++ the notfound value is returned. -++ -++ A true boolean is found if one of the following is matched: -++ -++ - A string starting with 'y' -++ - A string starting with 'Y' -++ - A string starting with 't' -++ - A string starting with 'T' -++ - A string starting with '1' -++ -++ A false boolean is found if one of the following is matched: -++ -++ - A string starting with 'n' -++ - A string starting with 'N' -++ - A string starting with 'f' -++ - A string starting with 'F' -++ - A string starting with '0' -++ -++ The notfound value returned if no boolean is identified, does not -++ necessarily have to be 0 or 1. -++ */ -++/*--------------------------------------------------------------------------*/ -++int iniparser_getboolean(dictionary * d, const char * key, int notfound) -++{ -++ char * c ; -++ int ret ; -++ -++ c = iniparser_getstring(d, key, INI_INVALID_KEY); -++ if (c==INI_INVALID_KEY) return notfound ; -++ if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') { -++ ret = 1 ; -++ } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') { -++ ret = 0 ; -++ } else { -++ ret = notfound ; -++ } -++ return ret; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Finds out if a given entry exists in a dictionary -++ @param ini Dictionary to search -++ @param entry Name of the entry to look for -++ @return integer 1 if entry exists, 0 otherwise -++ -++ Finds out if a given entry exists in the dictionary. Since sections -++ are stored as keys with NULL associated values, this is the only way -++ of querying for the presence of sections in a dictionary. -++ */ -++/*--------------------------------------------------------------------------*/ -++int iniparser_find_entry( -++ dictionary * ini, -++ char * entry -++) -++{ -++ int found=0 ; -++ if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) { -++ found = 1 ; -++ } -++ return found ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Set an entry in a dictionary. -++ @param ini Dictionary to modify. -++ @param entry Entry to modify (entry name) -++ @param val New value to associate to the entry. -++ @return int 0 if Ok, -1 otherwise. -++ -++ If the given entry can be found in the dictionary, it is modified to -++ contain the provided value. If it cannot be found, -1 is returned. -++ It is Ok to set val to NULL. -++ */ -++/*--------------------------------------------------------------------------*/ -++int iniparser_set(dictionary * ini, char * entry, char * val) -++{ -++ return dictionary_set(ini, strlwc(entry), val) ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Delete an entry in a dictionary -++ @param ini Dictionary to modify -++ @param entry Entry to delete (entry name) -++ @return void -++ -++ If the given entry can be found, it is deleted from the dictionary. -++ */ -++/*--------------------------------------------------------------------------*/ -++void iniparser_unset(dictionary * ini, char * entry) -++{ -++ dictionary_unset(ini, strlwc(entry)); -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Load a single line from an INI file -++ @param input_line Input line, may be concatenated multi-line input -++ @param section Output space to store section -++ @param key Output space to store key -++ @param value Output space to store value -++ @return line_status value -++ */ -++/*--------------------------------------------------------------------------*/ -++static line_status iniparser_line( -++ char * input_line, -++ char * section, -++ char * key, -++ char * value) -++{ -++ line_status sta ; -++ char line[ASCIILINESZ+1]; -++ int len ; -++ -++ strcpy(line, strstrip(input_line)); -++ len = (int)strlen(line); -++ -++ sta = LINE_UNPROCESSED ; -++ if (len<1) { -++ /* Empty line */ -++ sta = LINE_EMPTY ; -++ } else if (line[0]=='#') { -++ /* Comment line */ -++ sta = LINE_COMMENT ; -++ } else if (line[0]=='[' && line[len-1]==']') { -++ /* Section name */ -++ sscanf(line, "[%[^]]", section); -++ strcpy(section, strstrip(section)); -++ strcpy(section, strlwc(section)); -++ sta = LINE_SECTION ; -++ } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2 -++ || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2 -++ || sscanf (line, "%[^=] = %[^;#]", key, value) == 2) { -++ /* Usual key=value, with or without comments */ -++ strcpy(key, strstrip(key)); -++ strcpy(key, strlwc(key)); -++ strcpy(value, strstrip(value)); -++ /* -++ * sscanf cannot handle '' or "" as empty values -++ * this is done here -++ */ -++ if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) { -++ value[0]=0 ; -++ } -++ sta = LINE_VALUE ; -++ } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2 -++ || sscanf(line, "%[^=] %[=]", key, value) == 2) { -++ /* -++ * Special cases: -++ * key= -++ * key=; -++ * key=# -++ */ -++ strcpy(key, strstrip(key)); -++ strcpy(key, strlwc(key)); -++ value[0]=0 ; -++ sta = LINE_VALUE ; -++ } else { -++ /* Generate syntax error */ -++ sta = LINE_ERROR ; -++ } -++ return sta ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Parse an ini file and return an allocated dictionary object -++ @param ininame Name of the ini file to read. -++ @return Pointer to newly allocated dictionary -++ -++ This is the parser for ini files. This function is called, providing -++ the name of the file to be read. It returns a dictionary object that -++ should not be accessed directly, but through accessor functions -++ instead. -++ -++ The returned dictionary must be freed using iniparser_freedict(). -++ */ -++/*--------------------------------------------------------------------------*/ -++dictionary * iniparser_load(const char * ininame) -++{ -++ FILE * in ; -++ -++ char line [ASCIILINESZ+1] ; -++ char section [ASCIILINESZ+1] ; -++ char key [ASCIILINESZ+1] ; -++ char tmp [ASCIILINESZ+1] ; -++ char val [ASCIILINESZ+1] ; -++ -++ int last=0 ; -++ int len ; -++ int lineno=0 ; -++ int errs=0; -++ -++ dictionary * dict ; -++ -++ if ((in=fopen(ininame, "r"))==NULL) { -++ fprintf(stderr, "iniparser: cannot open %s\n", ininame); -++ return NULL ; -++ } -++ -++ dict = dictionary_new(0) ; -++ if (!dict) { -++ fclose(in); -++ return NULL ; -++ } -++ -++ memset(line, 0, ASCIILINESZ); -++ memset(section, 0, ASCIILINESZ); -++ memset(key, 0, ASCIILINESZ); -++ memset(val, 0, ASCIILINESZ); -++ last=0 ; -++ -++ while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) { -++ lineno++ ; -++ len = (int)strlen(line)-1; -++ /* Safety check against buffer overflows */ -++ if (line[len]!='\n') { -++ fprintf(stderr, -++ "iniparser: input line too long in %s (%d)\n", -++ ininame, -++ lineno); -++ dictionary_del(dict); -++ fclose(in); -++ return NULL ; -++ } -++ /* Get rid of \n and spaces at end of line */ -++ while ((len>=0) && -++ ((line[len]=='\n') || (isspace(line[len])))) { -++ line[len]=0 ; -++ len-- ; -++ } -++ /* Detect multi-line */ -++ if (line[len]=='\\') { -++ /* Multi-line value */ -++ last=len ; -++ continue ; -++ } else { -++ last=0 ; -++ } -++ switch (iniparser_line(line, section, key, val)) { -++ case LINE_EMPTY: -++ case LINE_COMMENT: -++ break ; -++ -++ case LINE_SECTION: -++ errs = dictionary_set(dict, section, NULL); -++ break ; -++ -++ case LINE_VALUE: -++ sprintf(tmp, "%s:%s", section, key); -++ errs = dictionary_set(dict, tmp, val) ; -++ break ; -++ -++ case LINE_ERROR: -++ fprintf(stderr, "iniparser: syntax error in %s (%d):\n", -++ ininame, -++ lineno); -++ fprintf(stderr, "-> %s\n", line); -++ errs++ ; -++ break; -++ -++ default: -++ break ; -++ } -++ memset(line, 0, ASCIILINESZ); -++ last=0; -++ if (errs<0) { -++ fprintf(stderr, "iniparser: memory allocation failure\n"); -++ break ; -++ } -++ } -++ if (errs) { -++ dictionary_del(dict); -++ dict = NULL ; -++ } -++ fclose(in); -++ return dict ; -++} -++ -++/*-------------------------------------------------------------------------*/ -++/** -++ @brief Free all memory associated to an ini dictionary -++ @param d Dictionary to free -++ @return void -++ -++ Free all memory associated to an ini dictionary. -++ It is mandatory to call this function before the dictionary object -++ gets out of the current context. -++ */ -++/*--------------------------------------------------------------------------*/ -++void iniparser_freedict(dictionary * d) -++{ -++ dictionary_del(d); -++} -++ -++/* vim: set ts=4 et sw=4 tw=75 */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libmtd.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libmtd.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libmtd.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libmtd.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,314 @@ -++/* -++ * Copyright (C) 2008 Nokia Corporation -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem Bityutskiy -++ * -++ * MTD library. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include "common.h" -++ -++#define PROGRAM_NAME "libmtd" -++#define MTD_DEV_MAJOR 90 -++ -++/** -++ * mtd_get_info - get information about an MTD device. -++ * @node: name of the MTD device node -++ * @mtd: the MTD device information is returned here -++ * -++ * This function gets information about MTD device defined by the @node device -++ * node file and saves this information in the @mtd object. Returns %0 in case -++ * of success and %-1 in case of failure. -++ */ -++int mtd_get_info(const char *node, struct mtd_info *mtd) -++{ -++ struct stat st; -++ struct mtd_info_user ui; -++ int ret; -++ loff_t offs = 0; -++ -++ if (stat(node, &st)) -++ return sys_errmsg("cannot open \"%s\"", node); -++ -++ if (!S_ISCHR(st.st_mode)) { -++ errno = EINVAL; -++ return errmsg("\"%s\" is not a character device", node); -++ } -++ -++ mtd->major = major(st.st_rdev); -++ mtd->minor = minor(st.st_rdev); -++ -++ if (mtd->major != MTD_DEV_MAJOR) { -++ errno = EINVAL; -++ return errmsg("\"%s\" has major number %d, MTD devices have " -++ "major %d", node, mtd->major, MTD_DEV_MAJOR); -++ } -++ -++ mtd->num = mtd->minor / 2; -++ mtd->rdonly = mtd->minor & 1; -++ -++ mtd->fd = open(node, O_RDWR); -++ if (mtd->fd == -1) -++ return sys_errmsg("cannot open \"%s\"", node); -++ -++ if (ioctl(mtd->fd, MEMGETINFO, &ui)) { -++ sys_errmsg("MEMGETINFO ioctl request failed"); -++ goto out_close; -++ } -++ -++ ret = ioctl(mtd->fd, MEMGETBADBLOCK, &offs); -++ if (ret == -1) { -++ if (errno != EOPNOTSUPP) { -++ sys_errmsg("MEMGETBADBLOCK ioctl failed"); -++ goto out_close; -++ } -++ errno = 0; -++ mtd->allows_bb = 0; -++ } else -++ mtd->allows_bb = 1; -++ -++ mtd->type = ui.type; -++ mtd->size = ui.size; -++ mtd->eb_size = ui.erasesize; -++ mtd->min_io_size = ui.writesize; -++ -++ if (mtd->min_io_size <= 0) { -++ errmsg("mtd%d (%s) has insane min. I/O unit size %d", -++ mtd->num, node, mtd->min_io_size); -++ goto out_close; -++ } -++ if (mtd->eb_size <= 0 || mtd->eb_size < mtd->min_io_size) { -++ errmsg("mtd%d (%s) has insane eraseblock size %d", -++ mtd->num, node, mtd->eb_size); -++ goto out_close; -++ } -++ if (mtd->size <= 0 || mtd->size < mtd->eb_size) { -++ errmsg("mtd%d (%s) has insane size %lld", -++ mtd->num, node, mtd->size); -++ goto out_close; -++ } -++ mtd->eb_cnt = mtd->size / mtd->eb_size; -++ -++ switch(mtd->type) { -++ case MTD_ABSENT: -++ errmsg("mtd%d (%s) is removable and is not present", -++ mtd->num, node); -++ goto out_close; -++ case MTD_RAM: -++ mtd->type_str = "RAM-based"; -++ break; -++ case MTD_ROM: -++ mtd->type_str = "ROM"; -++ break; -++ case MTD_NORFLASH: -++ mtd->type_str = "NOR"; -++ break; -++ case MTD_NANDFLASH: -++ mtd->type_str = "NAND"; -++ break; -++ case MTD_DATAFLASH: -++ mtd->type_str = "DataFlash"; -++ break; -++ case MTD_UBIVOLUME: -++ mtd->type_str = "UBI-emulated MTD"; -++ break; -++ default: -++ mtd->type_str = "Unknown flash type"; -++ break; -++ } -++ -++ if (!(ui.flags & MTD_WRITEABLE)) -++ mtd->rdonly = 1; -++ -++ return 0; -++ -++out_close: -++ close(mtd->fd); -++ return -1; -++} -++ -++/** -++ * mtd_erase - erase an eraseblock. -++ * @mtd: MTD device description object -++ * @eb: eraseblock to erase -++ * -++ * This function erases the eraseblock and returns %0 in case of success and -++ * %-1 in case of failure. -++ */ -++int mtd_erase(const struct mtd_info *mtd, int eb) -++{ -++ struct erase_info_user ei; -++ -++ ei.start = eb * mtd->eb_size;; -++ ei.length = mtd->eb_size; -++ return ioctl(mtd->fd, MEMERASE, &ei); -++} -++ -++/** -++ * mtd_is_bad - check if eraseblock is bad. -++ * @mtd: MTD device description object -++ * @eb: eraseblock to check -++ * -++ * This function checks if eraseblock @eb is bad. Returns %0 if not, %1 if yes, -++ * and %-1 in case of failure. -++ */ -++int mtd_is_bad(const struct mtd_info *mtd, int eb) -++{ -++ int ret; -++ loff_t seek; -++ -++ if (eb < 0 || eb >= mtd->eb_cnt) { -++ errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks", -++ eb, mtd->num, mtd->eb_cnt); -++ errno = EINVAL; -++ return -1; -++ } -++ -++ if (!mtd->allows_bb) -++ return 0; -++ -++ seek = eb * mtd->eb_size; -++ ret = ioctl(mtd->fd, MEMGETBADBLOCK, &seek); -++ if (ret == -1) { -++ sys_errmsg("MEMGETBADBLOCK ioctl failed for " -++ "eraseblock %d (mtd%d)", eb, mtd->num); -++ return -1; -++ } -++ -++ return ret; -++} -++ -++/** -++ * mtd_read - read data from an MTD device. -++ * @mtd: MTD device description object -++ * @eb: eraseblock to read from -++ * @offs: offset withing the eraseblock to read from -++ * @buf: buffer to read data to -++ * @len: how many bytes to read -++ * -++ * This function reads @len bytes of data from eraseblock @eb and offset @offs -++ * of the MTD device defined by @mtd and stores the read data at buffer @buf. -++ * Returns %0 in case of success and %-1 in case of failure. -++ */ -++int mtd_read(const struct mtd_info *mtd, int eb, int offs, void *buf, int len) -++{ -++ int ret, rd = 0; -++ off_t seek; -++ -++ if (eb < 0 || eb >= mtd->eb_cnt) { -++ errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks", -++ eb, mtd->num, mtd->eb_cnt); -++ errno = EINVAL; -++ return -1; -++ } -++ if (offs < 0 || offs + len > mtd->eb_size) { -++ errmsg("bad offset %d or length %d, mtd%d eraseblock size is %d", -++ offs, len, mtd->num, mtd->eb_size); -++ errno = EINVAL; -++ return -1; -++ } -++ -++ /* Seek to the beginning of the eraseblock */ -++ seek = eb * mtd->eb_size + offs; -++ if (lseek(mtd->fd, seek, SEEK_SET) != seek) { -++ sys_errmsg("cannot seek mtd%d to offset %llu", -++ mtd->num, (unsigned long long)seek); -++ return -1; -++ } -++ -++ while (rd < len) { -++ ret = read(mtd->fd, buf, len); -++ if (ret < 0) { -++ sys_errmsg("cannot read %d bytes from mtd%d (eraseblock %d, offset %d)", -++ len, mtd->num, eb, offs); -++ return -1; -++ } -++ rd += ret; -++ } -++ -++ return 0; -++} -++ -++/** -++ * mtd_write - write data to an MTD device. -++ * @mtd: MTD device description object -++ * @eb: eraseblock to write to -++ * @offs: offset withing the eraseblock to write to -++ * @buf: buffer to write -++ * @len: how many bytes to write -++ * -++ * This function writes @len bytes of data to eraseblock @eb and offset @offs -++ * of the MTD device defined by @mtd. Returns %0 in case of success and %-1 in -++ * case of failure. -++ */ -++int mtd_write(const struct mtd_info *mtd, int eb, int offs, void *buf, int len) -++{ -++ int ret; -++ off_t seek; -++ -++ if (eb < 0 || eb >= mtd->eb_cnt) { -++ errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks", -++ eb, mtd->num, mtd->eb_cnt); -++ errno = EINVAL; -++ return -1; -++ } -++ if (offs < 0 || offs + len > mtd->eb_size) { -++ errmsg("bad offset %d or length %d, mtd%d eraseblock size is %d", -++ offs, len, mtd->num, mtd->eb_size); -++ errno = EINVAL; -++ return -1; -++ } -++#if 0 -++ if (offs % mtd->subpage_size) { -++ errmsg("write offset %d is not aligned to mtd%d min. I/O size %d", -++ offs, mtd->num, mtd->subpage_size); -++ errno = EINVAL; -++ return -1; -++ } -++ if (len % mtd->subpage_size) { -++ errmsg("write length %d is not aligned to mtd%d min. I/O size %d", -++ len, mtd->num, mtd->subpage_size); -++ errno = EINVAL; -++ return -1; -++ } -++#endif -++ -++ /* Seek to the beginning of the eraseblock */ -++ seek = eb * mtd->eb_size + offs; -++ if (lseek(mtd->fd, seek, SEEK_SET) != seek) { -++ sys_errmsg("cannot seek mtd%d to offset %llu", -++ mtd->num, (unsigned long long)seek); -++ return -1; -++ } -++ -++ ret = write(mtd->fd, buf, len); -++ if (ret != len) { -++ sys_errmsg("cannot write %d bytes to mtd%d (eraseblock %d, offset %d)", -++ len, mtd->num, eb, offs); -++ return -1; -++ } -++ -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libscan.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libscan.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libscan.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libscan.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,225 @@ -++/* -++ * Copyright (C) 2008 Nokia Corporation -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem Bityutskiy -++ * -++ * UBI scanning library. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include "common.h" -++#include "crc32.h" -++ -++#define PROGRAM_NAME "libscan" -++ -++static int all_ff(const void *buf, int len) -++{ -++ int i; -++ const uint8_t *p = buf; -++ -++ for (i = 0; i < len; i++) -++ if (p[i] != 0xFF) -++ return 0; -++ return 1; -++} -++ -++int ubi_scan(struct mtd_info *mtd, struct ubi_scan_info **info, int verbose) -++{ -++ int eb, v = (verbose == 2), pr = (verbose == 1); -++ struct ubi_scan_info *si; -++ unsigned long long sum = 0; -++ -++ si = calloc(1, sizeof(struct ubi_scan_info)); -++ if (!si) -++ return sys_errmsg("cannot allocate %zd bytes of memory", -++ sizeof(struct ubi_scan_info)); -++ -++ si->ec = calloc(mtd->eb_cnt, sizeof(uint32_t)); -++ if (!si->ec) { -++ sys_errmsg("cannot allocate %zd bytes of memory", -++ sizeof(struct ubi_scan_info)); -++ goto out_si; -++ } -++ -++ si->vid_hdr_offs = si->data_offs = -1; -++ -++ verbose(v, "start scanning eraseblocks 0-%d", mtd->eb_cnt); -++ for (eb = 0; eb < mtd->eb_cnt; eb++) { -++ int ret; -++ uint32_t crc; -++ struct ubi_ec_hdr hdr; -++ unsigned long long ec; -++ -++ if (v) { -++ normsg_cont("scanning eraseblock %d", eb); -++ fflush(stdout); -++ } -++ if (pr) { -++ printf("\r" PROGRAM_NAME ": scanning eraseblock %d -- %2lld %% complete ", -++ eb, (long long)(eb + 1) * 100 / mtd->eb_cnt); -++ fflush(stdout); -++ } -++ -++ ret = mtd_is_bad(mtd, eb); -++ if (ret == -1) -++ goto out_ec; -++ if (ret) { -++ si->bad_cnt += 1; -++ si->ec[eb] = EB_BAD; -++ if (v) -++ printf(": bad\n"); -++ continue; -++ } -++ -++ ret = mtd_read(mtd, eb, 0, &hdr, sizeof(struct ubi_ec_hdr));; -++ if (ret < 0) -++ goto out_ec; -++ -++ /* Check the EC header */ -++ if (be32_to_cpu(hdr.magic) != UBI_EC_HDR_MAGIC) { -++ if (all_ff(&hdr, sizeof(struct ubi_ec_hdr))) { -++ si->empty_cnt += 1; -++ si->ec[eb] = EB_EMPTY; -++ if (v) -++ printf(": empty\n"); -++ } else { -++ si->alien_cnt += 1; -++ si->ec[eb] = EB_ALIEN; -++ if (v) -++ printf(": alien\n"); -++ } -++ continue; -++ } -++ -++ crc = crc32(UBI_CRC32_INIT, &hdr, UBI_EC_HDR_SIZE_CRC); -++ if (be32_to_cpu(hdr.hdr_crc) != crc) { -++ si->corrupted_cnt += 1; -++ si->ec[eb] = EB_CORRUPTED; -++ if (v) -++ printf(": bad CRC %#08x, should be %#08x\n", -++ crc, be32_to_cpu(hdr.hdr_crc)); -++ continue; -++ } -++ -++ ec = be64_to_cpu(hdr.ec); -++ if (ec > EC_MAX) { -++ if (pr) -++ printf("\n"); -++ errmsg("erase counter in EB %d is %llu, while this " -++ "program expects them to be less than %u", -++ eb, ec, EC_MAX); -++ goto out_ec; -++ } -++ -++ if (si->vid_hdr_offs == -1) { -++ si->vid_hdr_offs = be32_to_cpu(hdr.vid_hdr_offset); -++ si->data_offs = be32_to_cpu(hdr.data_offset); -++ if (si->data_offs % mtd->min_io_size) { -++ if (pr) -++ printf("\n"); -++ if (v) -++ printf(": corrupted because of the below\n"); -++ warnmsg("bad data offset %d at eraseblock %d (n" -++ "of multiple of min. I/O unit size %d)", -++ si->data_offs, eb, mtd->min_io_size); -++ warnmsg("treat eraseblock %d as corrupted", eb); -++ si->corrupted_cnt += 1; -++ si->ec[eb] = EB_CORRUPTED; -++ continue; -++ -++ } -++ } else { -++ if (be32_to_cpu(hdr.vid_hdr_offset) != si->vid_hdr_offs) { -++ if (pr) -++ printf("\n"); -++ if (v) -++ printf(": corrupted because of the below\n"); -++ warnmsg("inconsistent VID header offset: was " -++ "%d, but is %d in eraseblock %d", -++ si->vid_hdr_offs, -++ be32_to_cpu(hdr.vid_hdr_offset), eb); -++ warnmsg("treat eraseblock %d as corrupted", eb); -++ si->corrupted_cnt += 1; -++ si->ec[eb] = EB_CORRUPTED; -++ continue; -++ } -++ if (be32_to_cpu(hdr.data_offset) != si->data_offs) { -++ if (pr) -++ printf("\n"); -++ if (v) -++ printf(": corrupted because of the below\n"); -++ warnmsg("inconsistent data offset: was %d, but" -++ " is %d in eraseblock %d", -++ si->data_offs, -++ be32_to_cpu(hdr.data_offset), eb); -++ warnmsg("treat eraseblock %d as corrupted", eb); -++ si->corrupted_cnt += 1; -++ si->ec[eb] = EB_CORRUPTED; -++ continue; -++ } -++ } -++ -++ si->ok_cnt += 1; -++ si->ec[eb] = ec; -++ if (v) -++ printf(": OK, erase counter %u\n", si->ec[eb]); -++ } -++ -++ if (si->ok_cnt != 0) { -++ /* Calculate mean erase counter */ -++ for (eb = 0; eb < mtd->eb_cnt; eb++) { -++ if (si->ec[eb] > EC_MAX) -++ continue; -++ sum += si->ec[eb]; -++ } -++ si->mean_ec = sum / si->ok_cnt; -++ } -++ -++ si->good_cnt = mtd->eb_cnt - si->bad_cnt; -++ verbose(v, "finished, mean EC %lld, %d OK, %d corrupted, %d empty, %d " -++ "alien, bad %d", si->mean_ec, si->ok_cnt, si->corrupted_cnt, -++ si->empty_cnt, si->alien_cnt, si->bad_cnt); -++ -++ *info = si; -++ if (pr) -++ printf("\n"); -++ return 0; -++ -++out_ec: -++ free(si->ec); -++out_si: -++ free(si); -++ *info = NULL; -++ return -1; -++} -++ -++void ubi_scan_free(struct ubi_scan_info *si) -++{ -++ free(si->ec); -++ free(si); -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libubi.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libubi.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libubi.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libubi.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1154 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem Bityutskiy -++ * -++ * UBI (Unsorted Block Images) library. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "libubi.h" -++#include "libubi_int.h" -++#include "common.h" -++ -++#define PROGRAM_NAME "libubi" -++ -++/** -++ * mkpath - compose full path from 2 given components. -++ * @path: the first component -++ * @name: the second component -++ * -++ * This function returns the resulting path in case of success and %NULL in -++ * case of failure. -++ */ -++static char *mkpath(const char *path, const char *name) -++{ -++ char *n; -++ int len1 = strlen(path); -++ int len2 = strlen(name); -++ -++ n = malloc(len1 + len2 + 2); -++ if (!n) { -++ sys_errmsg("cannot allocate %d bytes", len1 + len2 + 2); -++ return NULL; -++ } -++ -++ memcpy(n, path, len1); -++ if (n[len1 - 1] != '/') -++ n[len1++] = '/'; -++ -++ memcpy(n + len1, name, len2 + 1); -++ return n; -++} -++ -++/** -++ * read_positive_ll - read a positive 'long long' value from a file. -++ * @file: the file to read from -++ * @value: the result is stored here -++ * -++ * This function reads file @file and interprets its contents as a positive -++ * 'long long' integer. If this is not true, it fails with %EINVAL error code. -++ * Returns %0 in case of success and %-1 in case of failure. -++ */ -++static int read_positive_ll(const char *file, long long *value) -++{ -++ int fd, rd; -++ char buf[50]; -++ -++ fd = open(file, O_RDONLY); -++ if (fd == -1) -++ return -1; -++ -++ rd = read(fd, buf, 50); -++ if (rd == -1) { -++ sys_errmsg("cannot read \"%s\"", file); -++ goto out_error; -++ } -++ if (rd == 50) { -++ errmsg("contents of \"%s\" is too long", file); -++ errno = EINVAL; -++ goto out_error; -++ } -++ -++ if (sscanf(buf, "%lld\n", value) != 1) { -++ /* This must be a UBI bug */ -++ errmsg("cannot read integer from \"%s\"\n", file); -++ errno = EINVAL; -++ goto out_error; -++ } -++ -++ if (*value < 0) { -++ errmsg("negative value %lld in \"%s\"", *value, file); -++ errno = EINVAL; -++ goto out_error; -++ } -++ -++ if (close(fd)) -++ return sys_errmsg("close failed on \"%s\"", file); -++ -++ return 0; -++ -++out_error: -++ close(fd); -++ return -1; -++} -++ -++/** -++ * read_positive_int - read a positive 'int' value from a file. -++ * @file: the file to read from -++ * @value: the result is stored here -++ * -++ * This function is the same as 'read_positive_ll()', but it reads an 'int' -++ * value, not 'long long'. -++ */ -++static int read_positive_int(const char *file, int *value) -++{ -++ long long res; -++ -++ if (read_positive_ll(file, &res)) -++ return -1; -++ -++ /* Make sure the value is not too big */ -++ if (res > INT_MAX) { -++ errmsg("value %lld read from file \"%s\" is out of range", -++ res, file); -++ errno = EINVAL; -++ return -1; -++ } -++ -++ *value = res; -++ return 0; -++} -++ -++/** -++ * read_data - read data from a file. -++ * @file: the file to read from -++ * @buf: the buffer to read to -++ * @buf_len: buffer length -++ * -++ * This function returns number of read bytes in case of success and %-1 in -++ * case of failure. Note, if the file contains more then @buf_len bytes of -++ * date, this function fails with %EINVAL error code. -++ */ -++static int read_data(const char *file, void *buf, int buf_len) -++{ -++ int fd, rd, tmp, tmp1; -++ -++ fd = open(file, O_RDONLY); -++ if (fd == -1) -++ return -1; -++ -++ rd = read(fd, buf, buf_len); -++ if (rd == -1) { -++ sys_errmsg("cannot read \"%s\"", file); -++ goto out_error; -++ } -++ -++ /* Make sure all data is read */ -++ tmp1 = read(fd, &tmp, 1); -++ if (tmp1 == 1) { -++ sys_errmsg("cannot read \"%s\"", file); -++ goto out_error; -++ } -++ if (tmp1) { -++ errmsg("file \"%s\" contains too much data (> %d bytes)", -++ file, buf_len); -++ errno = EINVAL; -++ goto out_error; -++ } -++ -++ if (close(fd)) { -++ sys_errmsg("close failed on \"%s\"", file); -++ return -1; -++ } -++ -++ return rd; -++ -++out_error: -++ close(fd); -++ return -1; -++} -++ -++/** -++ * read_major - read major and minor numbers from a file. -++ * @file: name of the file to read from -++ * @major: major number is returned here -++ * @minor: minor number is returned here -++ * -++ * This function returns % in case of succes, and %-1 in case of failure. -++ */ -++static int read_major(const char *file, int *major, int *minor) -++{ -++ int ret; -++ char buf[50]; -++ -++ ret = read_data(file, buf, 50); -++ if (ret < 0) -++ return ret; -++ -++ ret = sscanf(buf, "%d:%d\n", major, minor); -++ if (ret != 2) { -++ errno = EINVAL; -++ return errmsg("\"%s\" does not have major:minor format", file); -++ } -++ -++ if (*major < 0 || *minor < 0) { -++ errno = EINVAL; -++ return errmsg("bad major:minor %d:%d in \"%s\"", -++ *major, *minor, file); -++ } -++ -++ return 0; -++} -++ -++/** -++ * dev_read_int - read a positive 'int' value from an UBI device sysfs file. -++ * @patt: file pattern to read from -++ * @dev_num: UBI device number -++ * @value: the result is stored here -++ * -++ * This function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int dev_read_int(const char *patt, int dev_num, int *value) -++{ -++ char file[strlen(patt) + 50]; -++ -++ sprintf(file, patt, dev_num); -++ return read_positive_int(file, value); -++} -++ -++/** -++ * vol_read_int - read a positive 'int' value from an UBI volume sysfs file. -++ * @patt: file pattern to read from -++ * @dev_num: UBI device number -++ * @vol_id: volume ID -++ * @value: the result is stored here -++ * -++ * This function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value) -++{ -++ char file[strlen(patt) + 100]; -++ -++ sprintf(file, patt, dev_num, vol_id); -++ return read_positive_int(file, value); -++} -++ -++/** -++ * dev_read_ll - read a positive 'long long' value from an UBI device sysfs file. -++ * @patt: file pattern to read from -++ * @dev_num: UBI device number -++ * @value: the result is stored here -++ * -++ * This function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int dev_read_ll(const char *patt, int dev_num, long long *value) -++{ -++ char file[strlen(patt) + 50]; -++ -++ sprintf(file, patt, dev_num); -++ return read_positive_ll(file, value); -++} -++ -++/** -++ * vol_read_ll - read a positive 'long long' value from an UBI volume sysfs file. -++ * @patt: file pattern to read from -++ * @dev_num: UBI device number -++ * @vol_id: volume ID -++ * @value: the result is stored here -++ * -++ * This function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int vol_read_ll(const char *patt, int dev_num, int vol_id, -++ long long *value) -++{ -++ char file[strlen(patt) + 100]; -++ -++ sprintf(file, patt, dev_num, vol_id); -++ return read_positive_ll(file, value); -++} -++ -++/** -++ * vol_read_data - read data from an UBI volume's sysfs file. -++ * @patt: file pattern to read from -++ * @dev_num: UBI device number -++ * @vol_id: volume ID -++ * @buf: buffer to read to -++ * @buf_len: buffer length -++ * -++ * This function returns number of read bytes in case of success and %-1 in -++ * case of failure. -++ */ -++static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf, -++ int buf_len) -++{ -++ char file[strlen(patt) + 100]; -++ -++ sprintf(file, patt, dev_num, vol_id); -++ return read_data(file, buf, buf_len); -++} -++ -++/** -++ * dev_get_major - get major and minor numbers of an UBI device. -++ * @lib: libubi descriptor -++ * @dev_num: UBI device number -++ * @major: major number is returned here -++ * @minor: minor number is returned here -++ * -++ * This function returns zero in case of succes and %-1 in case of failure. -++ */ -++static int dev_get_major(struct libubi *lib, int dev_num, int *major, int *minor) -++{ -++ char file[strlen(lib->dev_dev) + 50]; -++ -++ sprintf(file, lib->dev_dev, dev_num); -++ return read_major(file, major, minor); -++} -++ -++/** -++ * vol_get_major - get major and minor numbers of an UBI volume. -++ * @lib: libubi descriptor -++ * @dev_num: UBI device number -++ * @vol_id: volume ID -++ * @major: major number is returned here -++ * @minor: minor number is returned here -++ * -++ * This function returns zero in case of succes and %-1 in case of failure. -++ */ -++static int vol_get_major(struct libubi *lib, int dev_num, int vol_id, -++ int *major, int *minor) -++{ -++ char file[strlen(lib->vol_dev) + 100]; -++ -++ sprintf(file, lib->vol_dev, dev_num, vol_id); -++ return read_major(file, major, minor); -++} -++ -++/** -++ * vol_node2nums - find UBI device number and volume ID by volume device node -++ * file. -++ * @lib: UBI library descriptor -++ * @node: UBI character device node name -++ * @dev_num: UBI device number is returned here -++ * @vol_id: volume ID is returned hers -++ * -++ * This function returns zero in case of succes and %-1 in case of failure. -++ */ -++static int vol_node2nums(struct libubi *lib, const char *node, int *dev_num, -++ int *vol_id) -++{ -++ struct stat st; -++ struct ubi_info info; -++ int i, fd, major, minor; -++ char file[strlen(lib->ubi_vol) + 100]; -++ -++ if (lstat(node, &st)) -++ return -1; -++ -++ if (!S_ISCHR(st.st_mode)) { -++ errno = EINVAL; -++ return errmsg("\"%s\" is not a character device", node); -++ } -++ -++ major = major(st.st_rdev); -++ minor = minor(st.st_rdev); -++ -++ if (minor == 0) { -++ errno = EINVAL; -++ return errmsg("\"%s\" is not a volume character device", node); -++ } -++ -++ if (ubi_get_info((libubi_t *)lib, &info)) -++ return -1; -++ -++ for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { -++ int major1, minor1, ret; -++ -++ ret = dev_get_major(lib, i, &major1, &minor1); -++ if (ret) { -++ if (errno == ENOENT) -++ continue; -++ return -1; -++ } -++ -++ if (major1 == major) -++ break; -++ } -++ -++ if (i > info.highest_dev_num) { -++ errno = ENODEV; -++ return -1; -++ } -++ -++ /* Make sure this UBI volume exists */ -++ sprintf(file, lib->ubi_vol, i, minor - 1); -++ fd = open(file, O_RDONLY); -++ if (fd == -1) { -++ errno = ENODEV; -++ return -1; -++ } -++ -++ *dev_num = i; -++ *vol_id = minor - 1; -++ errno = 0; -++ return 0; -++} -++ -++/** -++ * dev_node2num - find UBI device number by its character device node. -++ * @lib: UBI library descriptor -++ * @node: UBI character device node name -++ * -++ * This function returns positive UBI device number in case of success and %-1 -++ * in case of failure. -++ */ -++static int dev_node2num(struct libubi *lib, const char *node, int *dev_num) -++{ -++ struct stat stat; -++ struct ubi_info info; -++ int i, major, minor; -++ -++ if (lstat(node, &stat)) -++ return -1; -++ -++ if (!S_ISCHR(stat.st_mode)) { -++ errno = EINVAL; -++ return errmsg("\"%s\" is not a character device", node); -++ } -++ -++ major = major(stat.st_rdev); -++ minor = minor(stat.st_rdev); -++ -++ if (minor != 0) { -++ errno = EINVAL; -++ return errmsg("\"%s\" is not an UBI character device", node); -++ } -++ -++ if (ubi_get_info((libubi_t *)lib, &info)) -++ return -1; -++ -++ for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { -++ int major1, minor1, ret; -++ -++ ret = dev_get_major(lib, i, &major1, &minor1); -++ if (ret) { -++ if (errno == ENOENT) -++ continue; -++ return -1; -++ } -++ -++ if (major1 == major) { -++ if (minor1 != 0) { -++ errmsg("UBI character device minor number is " -++ "%d, but must be 0", minor1); -++ errno = EINVAL; -++ return -1; -++ } -++ errno = 0; -++ *dev_num = i; -++ return 0; -++ } -++ } -++ -++ errno = ENODEV; -++ return -1; -++} -++ -++int mtd_num2ubi_dev(libubi_t desc, int mtd_num, int *dev_num) -++{ -++ struct ubi_info info; -++ int i, ret, mtd_num1; -++ struct libubi *lib = desc; -++ -++ if (ubi_get_info(desc, &info)) -++ return -1; -++ -++ for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { -++ ret = dev_read_int(lib->dev_mtd_num, i, &mtd_num1); -++ if (ret) { -++ if (errno == ENOENT) -++ continue; -++ return -1; -++ } -++ -++ if (mtd_num1 == mtd_num) { -++ errno = 0; -++ *dev_num = i; -++ return 0; -++ } -++ } -++ -++ errno = 0; -++ return -1; -++} -++ -++libubi_t libubi_open(int required) -++{ -++ int fd, version; -++ struct libubi *lib; -++ -++ lib = calloc(1, sizeof(struct libubi)); -++ if (!lib) -++ return NULL; -++ -++ /* TODO: this must be discovered instead */ -++ lib->sysfs = strdup("/sys"); -++ if (!lib->sysfs) -++ goto out_error; -++ -++ lib->sysfs_ctrl = mkpath(lib->sysfs, SYSFS_CTRL); -++ if (!lib->sysfs_ctrl) -++ goto out_error; -++ -++ lib->ctrl_dev = mkpath(lib->sysfs_ctrl, CTRL_DEV); -++ if (!lib->ctrl_dev) -++ goto out_error; -++ -++ lib->sysfs_ubi = mkpath(lib->sysfs, SYSFS_UBI); -++ if (!lib->sysfs_ubi) -++ goto out_error; -++ -++ /* Make sure UBI is present */ -++ fd = open(lib->sysfs_ubi, O_RDONLY); -++ if (fd == -1) { -++ if (required) -++ errmsg("cannot open \"%s\", UBI does not seem to " -++ "exist in system", lib->sysfs_ubi); -++ goto out_error; -++ } -++ -++ if (close(fd)) { -++ sys_errmsg("close failed on \"%s\"", lib->sysfs_ubi); -++ goto out_error; -++ } -++ -++ lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT); -++ if (!lib->ubi_dev) -++ goto out_error; -++ -++ lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER); -++ if (!lib->ubi_version) -++ goto out_error; -++ -++ lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV); -++ if (!lib->dev_dev) -++ goto out_error; -++ -++ lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS); -++ if (!lib->dev_avail_ebs) -++ goto out_error; -++ -++ lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS); -++ if (!lib->dev_total_ebs) -++ goto out_error; -++ -++ lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT); -++ if (!lib->dev_bad_count) -++ goto out_error; -++ -++ lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE); -++ if (!lib->dev_eb_size) -++ goto out_error; -++ -++ lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC); -++ if (!lib->dev_max_ec) -++ goto out_error; -++ -++ lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD); -++ if (!lib->dev_bad_rsvd) -++ goto out_error; -++ -++ lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS); -++ if (!lib->dev_max_vols) -++ goto out_error; -++ -++ lib->dev_min_io_size = mkpath(lib->ubi_dev, DEV_MIN_IO_SIZE); -++ if (!lib->dev_min_io_size) -++ goto out_error; -++ -++ lib->dev_mtd_num = mkpath(lib->ubi_dev, DEV_MTD_NUM); -++ if (!lib->dev_mtd_num) -++ goto out_error; -++ -++ lib->ubi_vol = mkpath(lib->sysfs_ubi, UBI_VOL_NAME_PATT); -++ if (!lib->ubi_vol) -++ goto out_error; -++ -++ lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE); -++ if (!lib->vol_type) -++ goto out_error; -++ -++ lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV); -++ if (!lib->vol_dev) -++ goto out_error; -++ -++ lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT); -++ if (!lib->vol_alignment) -++ goto out_error; -++ -++ lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES); -++ if (!lib->vol_data_bytes) -++ goto out_error; -++ -++ lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS); -++ if (!lib->vol_rsvd_ebs) -++ goto out_error; -++ -++ lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE); -++ if (!lib->vol_eb_size) -++ goto out_error; -++ -++ lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED); -++ if (!lib->vol_corrupted) -++ goto out_error; -++ -++ lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME); -++ if (!lib->vol_name) -++ goto out_error; -++ -++ if (read_positive_int(lib->ubi_version, &version)) -++ goto out_error; -++ if (version != LIBUBI_UBI_VERSION) { -++ errmsg("this library was made for UBI version %d, but UBI " -++ "version %d is detected\n", LIBUBI_UBI_VERSION, version); -++ goto out_error; -++ } -++ -++ return lib; -++ -++out_error: -++ libubi_close((libubi_t)lib); -++ return NULL; -++} -++ -++void libubi_close(libubi_t desc) -++{ -++ struct libubi *lib = (struct libubi *)desc; -++ -++ free(lib->vol_name); -++ free(lib->vol_corrupted); -++ free(lib->vol_eb_size); -++ free(lib->vol_rsvd_ebs); -++ free(lib->vol_data_bytes); -++ free(lib->vol_alignment); -++ free(lib->vol_dev); -++ free(lib->vol_type); -++ free(lib->ubi_vol); -++ free(lib->dev_mtd_num); -++ free(lib->dev_min_io_size); -++ free(lib->dev_max_vols); -++ free(lib->dev_bad_rsvd); -++ free(lib->dev_max_ec); -++ free(lib->dev_eb_size); -++ free(lib->dev_bad_count); -++ free(lib->dev_total_ebs); -++ free(lib->dev_avail_ebs); -++ free(lib->dev_dev); -++ free(lib->ubi_version); -++ free(lib->ubi_dev); -++ free(lib->sysfs_ubi); -++ free(lib->ctrl_dev); -++ free(lib->sysfs_ctrl); -++ free(lib->sysfs); -++ free(lib); -++} -++ -++int ubi_attach_mtd(libubi_t desc, const char *node, -++ struct ubi_attach_request *req) -++{ -++ int fd, ret; -++ struct ubi_attach_req r; -++ -++ memset(&r, sizeof(struct ubi_attach_req), '\0'); -++ -++ desc = desc; -++ r.ubi_num = req->dev_num; -++ r.mtd_num = req->mtd_num; -++ r.vid_hdr_offset = req->vid_hdr_offset; -++ -++ fd = open(node, O_RDONLY); -++ if (fd == -1) -++ return -1; -++ -++ ret = ioctl(fd, UBI_IOCATT, &r); -++ close(fd); -++ if (ret == -1) -++ return -1; -++ -++ req->dev_num = r.ubi_num; -++ -++#ifdef UDEV_SETTLE_HACK -++ if (system("udevsettle") == -1) -++ return -1; -++ if (system("udevsettle") == -1) -++ return -1; -++#endif -++ -++ return ret; -++} -++ -++int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num) -++{ -++ int ret, ubi_dev; -++ -++ ret = mtd_num2ubi_dev(desc, mtd_num, &ubi_dev); -++ if (ret == -1) { -++ errno = ENODEV; -++ return ret; -++ } -++ -++ return ubi_remove_dev(desc, node, ubi_dev); -++} -++ -++int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev) -++{ -++ int fd, ret; -++ -++ desc = desc; -++ -++ fd = open(node, O_RDONLY); -++ if (fd == -1) -++ return -1; -++ ret = ioctl(fd, UBI_IOCDET, &ubi_dev); -++ if (ret == -1) -++ goto out_close; -++ -++#ifdef UDEV_SETTLE_HACK -++ if (system("udevsettle") == -1) -++ return -1; -++#endif -++ -++out_close: -++ close(fd); -++ return ret; -++} -++ -++int ubi_node_type(libubi_t desc, const char *node) -++{ -++ struct stat st; -++ struct ubi_info info; -++ int i, fd, major, minor; -++ struct libubi *lib = (struct libubi *)desc; -++ char file[strlen(lib->ubi_vol) + 100]; -++ -++ if (lstat(node, &st)) -++ return -1; -++ -++ if (!S_ISCHR(st.st_mode)) { -++ errno = EINVAL; -++ return -1; -++ } -++ -++ major = major(st.st_rdev); -++ minor = minor(st.st_rdev); -++ -++ if (ubi_get_info((libubi_t *)lib, &info)) -++ return -1; -++ -++ for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { -++ int major1, minor1, ret; -++ -++ ret = dev_get_major(lib, i, &major1, &minor1); -++ if (ret) { -++ if (errno == ENOENT) -++ continue; -++ return -1; -++ } -++ -++ if (major1 == major) -++ break; -++ } -++ -++ if (i > info.highest_dev_num) { -++ /* -++ * The character device node does not correspond to any -++ * existing UBI device or volume, but we do not want to return -++ * any error number in this case, to indicate the fact that it -++ * could be a UBI device/volume, but it doesn't. -++ */ -++ errno = 0; -++ return -1; -++ } -++ -++ if (minor == 0) -++ return 1; -++ -++ /* This is supposdely an UBI volume device node */ -++ sprintf(file, lib->ubi_vol, i, minor - 1); -++ fd = open(file, O_RDONLY); -++ if (fd == -1) { -++ errno = 0; -++ return -1; -++ } -++ -++ return 2; -++} -++ -++int ubi_get_info(libubi_t desc, struct ubi_info *info) -++{ -++ DIR *sysfs_ubi; -++ struct dirent *dirent; -++ struct libubi *lib = (struct libubi *)desc; -++ -++ memset(info, '\0', sizeof(struct ubi_info)); -++ -++ if (read_major(lib->ctrl_dev, &info->ctrl_major, &info->ctrl_minor)) { -++ /* -++ * Older UBI versions did not have control device, so we do not -++ * panic here for compatibility reasons. May be few years later -++ * we could return -1 here, but for now just set major:minor to -++ * -1. -++ */ -++ info->ctrl_major = info->ctrl_minor = -1; -++ } -++ -++ /* -++ * We have to scan the UBI sysfs directory to identify how many UBI -++ * devices are present. -++ */ -++ sysfs_ubi = opendir(lib->sysfs_ubi); -++ if (!sysfs_ubi) -++ return sys_errmsg("cannot open %s", lib->sysfs_ubi); -++ -++ info->lowest_dev_num = INT_MAX; -++ while (1) { -++ int dev_num, ret; -++ char tmp_buf[256]; -++ -++ errno = 0; -++ dirent = readdir(sysfs_ubi); -++ if (!dirent) -++ break; -++ -++ if (strlen(dirent->d_name) > 256) { -++ errmsg("invalid entry in %s: \"%s\"", -++ lib->sysfs_ubi, dirent->d_name); -++ goto out_close; -++ } -++ -++ ret = sscanf(dirent->d_name, UBI_DEV_NAME_PATT"%s", -++ &dev_num, tmp_buf); -++ if (ret == 1) { -++ info->dev_count += 1; -++ if (dev_num > info->highest_dev_num) -++ info->highest_dev_num = dev_num; -++ if (dev_num < info->lowest_dev_num) -++ info->lowest_dev_num = dev_num; -++ } -++ } -++ -++ if (!dirent && errno) { -++ sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi); -++ goto out_close; -++ } -++ -++ if (closedir(sysfs_ubi)) -++ return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi); -++ -++ if (info->lowest_dev_num == INT_MAX) -++ info->lowest_dev_num = 0; -++ -++ if (read_positive_int(lib->ubi_version, &info->version)) -++ return -1; -++ -++ return 0; -++ -++out_close: -++ closedir(sysfs_ubi); -++ return -1; -++} -++ -++int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req) -++{ -++ int fd, ret; -++ struct ubi_mkvol_req r; -++ size_t n; -++ -++ memset(&r, sizeof(struct ubi_mkvol_req), '\0'); -++ -++ desc = desc; -++ r.vol_id = req->vol_id; -++ r.alignment = req->alignment; -++ r.bytes = req->bytes; -++ r.vol_type = req->vol_type; -++ -++ n = strlen(req->name); -++ if (n > UBI_MAX_VOLUME_NAME) -++ return -1; -++ -++ strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1); -++ r.name_len = n; -++ -++ fd = open(node, O_RDONLY); -++ if (fd == -1) -++ return -1; -++ -++ ret = ioctl(fd, UBI_IOCMKVOL, &r); -++ if (ret == -1) -++ goto out_close; -++ -++ req->vol_id = r.vol_id; -++ -++#ifdef UDEV_SETTLE_HACK -++ if (system("udevsettle") == -1) -++ return -1; -++#endif -++ -++out_close: -++ close(fd); -++ return ret; -++} -++ -++int ubi_rmvol(libubi_t desc, const char *node, int vol_id) -++{ -++ int fd, ret; -++ -++ desc = desc; -++ fd = open(node, O_RDONLY); -++ if (fd == -1) -++ return -1; -++ -++ ret = ioctl(fd, UBI_IOCRMVOL, &vol_id); -++ if (ret == -1) -++ goto out_close; -++ -++#ifdef UDEV_SETTLE_HACK -++ if (system("udevsettle") == -1) -++ return -1; -++#endif -++ -++out_close: -++ close(fd); -++ return ret; -++} -++ -++int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes) -++{ -++ int fd, ret; -++ struct ubi_rsvol_req req; -++ -++ desc = desc; -++ fd = open(node, O_RDONLY); -++ if (fd == -1) -++ return -1; -++ -++ req.bytes = bytes; -++ req.vol_id = vol_id; -++ -++ ret = ioctl(fd, UBI_IOCRSVOL, &req); -++ close(fd); -++ return ret; -++} -++ -++int ubi_update_start(libubi_t desc, int fd, long long bytes) -++{ -++ desc = desc; -++ if (ioctl(fd, UBI_IOCVOLUP, &bytes)) -++ return -1; -++ return 0; -++} -++ -++int ubi_leb_read_start(int fd, struct ubi_leb *leb) -++{ -++ return ioctl(fd, UBI_IOCLEBREAD, leb); -++} -++ -++int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype) -++{ -++ struct ubi_leb_change_req req; -++ -++ desc = desc; -++ memset(&req, 0, sizeof(struct ubi_leb_change_req)); -++ req.lnum = lnum; -++ req.bytes = bytes; -++ req.dtype = dtype; -++ -++ if (ioctl(fd, UBI_IOCEBCH, &req)) -++ return -1; -++ return 0; -++} -++ -++int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info) -++{ -++ DIR *sysfs_ubi; -++ struct dirent *dirent; -++ struct libubi *lib = (struct libubi *)desc; -++ -++ memset(info, '\0', sizeof(struct ubi_dev_info)); -++ info->dev_num = dev_num; -++ -++ sysfs_ubi = opendir(lib->sysfs_ubi); -++ if (!sysfs_ubi) -++ return -1; -++ -++ info->lowest_vol_num = INT_MAX; -++ -++ while (1) { -++ int vol_id, ret, devno; -++ char tmp_buf[256]; -++ -++ errno = 0; -++ dirent = readdir(sysfs_ubi); -++ if (!dirent) -++ break; -++ -++ if (strlen(dirent->d_name) > 256) { -++ errmsg("invalid entry in %s: \"%s\"", -++ lib->sysfs_ubi, dirent->d_name); -++ goto out_close; -++ } -++ -++ ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT"%s", &devno, &vol_id, tmp_buf); -++ if (ret == 2 && devno == dev_num) { -++ info->vol_count += 1; -++ if (vol_id > info->highest_vol_num) -++ info->highest_vol_num = vol_id; -++ if (vol_id < info->lowest_vol_num) -++ info->lowest_vol_num = vol_id; -++ } -++ } -++ -++ if (!dirent && errno) { -++ sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi); -++ goto out_close; -++ } -++ -++ if (closedir(sysfs_ubi)) -++ return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi); -++ -++ if (info->lowest_vol_num == INT_MAX) -++ info->lowest_vol_num = 0; -++ -++ if (dev_get_major(lib, dev_num, &info->major, &info->minor)) -++ return -1; -++ -++ if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_lebs)) -++ return -1; -++ if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_lebs)) -++ return -1; -++ if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count)) -++ return -1; -++ if (dev_read_int(lib->dev_eb_size, dev_num, &info->leb_size)) -++ return -1; -++ if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd)) -++ return -1; -++ if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec)) -++ return -1; -++ if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count)) -++ return -1; -++ if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size)) -++ return -1; -++ -++ info->avail_bytes = info->avail_lebs * info->leb_size; -++ info->total_bytes = info->total_lebs * info->leb_size; -++ -++ return 0; -++ -++out_close: -++ closedir(sysfs_ubi); -++ return -1; -++} -++ -++int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info) -++{ -++ int dev_num; -++ struct libubi *lib = (struct libubi *)desc; -++ -++ if (dev_node2num(lib, node, &dev_num)) -++ return -1; -++ -++ return ubi_get_dev_info1(desc, dev_num, info); -++} -++ -++int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id, -++ struct ubi_vol_info *info) -++{ -++ int ret; -++ struct libubi *lib = (struct libubi *)desc; -++ char buf[50]; -++ -++ memset(info, '\0', sizeof(struct ubi_vol_info)); -++ info->dev_num = dev_num; -++ info->vol_id = vol_id; -++ -++ if (dev_get_major(lib, dev_num, &info->dev_major, &info->dev_minor)) -++ return -1; -++ if (vol_get_major(lib, dev_num, vol_id, &info->major, &info->minor)) -++ return -1; -++ -++ ret = vol_read_data(lib->vol_type, dev_num, vol_id, buf, 50); -++ if (ret < 0) -++ return -1; -++ -++ if (strncmp(buf, "static\n", ret) == 0) -++ info->type = UBI_STATIC_VOLUME; -++ else if (strncmp(buf, "dynamic\n", ret) == 0) -++ info->type = UBI_DYNAMIC_VOLUME; -++ else { -++ errmsg("bad value at \"%s\"", buf); -++ errno = EINVAL; -++ return -1; -++ } -++ -++ ret = vol_read_int(lib->vol_alignment, dev_num, vol_id, -++ &info->alignment); -++ if (ret) -++ return -1; -++ ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id, -++ &info->data_bytes); -++ if (ret) -++ return -1; -++ ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_lebs); -++ if (ret) -++ return -1; -++ ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->leb_size); -++ if (ret) -++ return -1; -++ ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id, -++ &info->corrupted); -++ if (ret) -++ return -1; -++ info->rsvd_bytes = info->leb_size * info->rsvd_lebs; -++ -++ ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name, -++ UBI_VOL_NAME_MAX + 2); -++ if (ret < 0) -++ return -1; -++ -++ info->name[ret - 1] = '\0'; -++ return 0; -++} -++ -++int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info) -++{ -++ int vol_id, dev_num; -++ struct libubi *lib = (struct libubi *)desc; -++ -++ if (vol_node2nums(lib, node, &dev_num, &vol_id)) -++ return -1; -++ -++ return ubi_get_vol_info1(desc, dev_num, vol_id, info); -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libubi_int.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libubi_int.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libubi_int.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libubi_int.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,133 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem Bityutskiy -++ * -++ * UBI (Unsorted Block Images) library. -++ */ -++ -++#ifndef __LIBUBI_INT_H__ -++#define __LIBUBI_INT_H__ -++ -++#include -++#include -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++/* -++ * The below are pre-define UBI file and directory names. -++ * -++ * Note, older kernels put 'ubiX_Y' directories straight to '/sys/class/ubi/'. -++ * New kernels puts 'ubiX_Y' directories to '/sys/class/ubi/ubiX/', which is -++ * saner. And for compatibility reasons it also puts symlinks to 'ubiX_Y' -++ * directories to '/sys/class/ubi/'. For now libubi assumes old layout. -++ */ -++ -++#define SYSFS_UBI "class/ubi" -++#define SYSFS_CTRL "class/misc/ubi_ctrl/" -++ -++#define CTRL_DEV "dev" -++ -++#define UBI_VER "version" -++#define UBI_DEV_NAME_PATT "ubi%d" -++ -++#define DEV_DEV "dev" -++#define DEV_AVAIL_EBS "avail_eraseblocks" -++#define DEV_TOTAL_EBS "total_eraseblocks" -++#define DEV_BAD_COUNT "bad_peb_count" -++#define DEV_EB_SIZE "eraseblock_size" -++#define DEV_MAX_EC "max_ec" -++#define DEV_MAX_RSVD "reserved_for_bad" -++#define DEV_MAX_VOLS "max_vol_count" -++#define DEV_MIN_IO_SIZE "min_io_size" -++#define DEV_MTD_NUM "mtd_num" -++ -++#define UBI_VOL_NAME_PATT "ubi%d_%d" -++#define VOL_TYPE "type" -++#define VOL_DEV "dev" -++#define VOL_ALIGNMENT "alignment" -++#define VOL_DATA_BYTES "data_bytes" -++#define VOL_RSVD_EBS "reserved_ebs" -++#define VOL_EB_SIZE "usable_eb_size" -++#define VOL_CORRUPTED "corrupted" -++#define VOL_NAME "name" -++ -++/** -++ * libubi - UBI library description data structure. -++ * @sysfs: sysfs file system path -++ * @sysfs_ctrl: UBI control device directory in sysfs -++ * @ctrl_dev: UBI control device major/minor numbers sysfs file -++ * @sysfs_ubi: UBI directory in sysfs -++ * @ubi_dev: UBI device sysfs directory pattern -++ * @ubi_version: UBI version file sysfs path -++ * @dev_dev: UBI device major/minor numbers file pattern -++ * @dev_avail_ebs: count of available eraseblocks sysfs path pattern -++ * @dev_total_ebs: total eraseblocks count sysfs path pattern -++ * @dev_bad_count: count of bad eraseblocks sysfs path pattern -++ * @dev_eb_size: size of UBI device's eraseblocks sysfs path pattern -++ * @dev_max_ec: maximum erase counter sysfs path pattern -++ * @dev_bad_rsvd: count of physical eraseblock reserved for bad eraseblocks -++ * handling -++ * @dev_max_vols: maximum volumes number count sysfs path pattern -++ * @dev_min_io_size: minimum I/O unit size sysfs path pattern -++ * @ubi_vol: UBI volume sysfs directory pattern -++ * @vol_type: volume type sysfs path pattern -++ * @vol_dev: volume major/minor numbers file pattern -++ * @vol_alignment: volume alignment sysfs path pattern -++ * @vol_data_bytes: volume data size sysfs path pattern -++ * @vol_rsvd_ebs: volume reserved size sysfs path pattern -++ * @vol_eb_size: volume eraseblock size sysfs path pattern -++ * @vol_corrupted: volume corruption flag sysfs path pattern -++ * @vol_name: volume name sysfs path pattern -++ */ -++struct libubi -++{ -++ char *sysfs; -++ char *sysfs_ctrl; -++ char *ctrl_dev; -++ char *sysfs_ubi; -++ char *ubi_dev; -++ char *ubi_version; -++ char *dev_dev; -++ char *dev_avail_ebs; -++ char *dev_total_ebs; -++ char *dev_bad_count; -++ char *dev_eb_size; -++ char *dev_max_ec; -++ char *dev_bad_rsvd; -++ char *dev_max_vols; -++ char *dev_min_io_size; -++ char *dev_mtd_num; -++ char *ubi_vol; -++ char *vol_type; -++ char *vol_dev; -++ char *vol_alignment; -++ char *vol_data_bytes; -++ char *vol_rsvd_ebs; -++ char *vol_eb_size; -++ char *vol_corrupted; -++ char *vol_name; -++ char *vol_max_count; -++}; -++ -++#ifdef __cplusplus -++} -++#endif -++ -++#endif /* !__LIBUBI_INT_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libubigen.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libubigen.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libubigen.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/libubigen.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,335 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * Copyright (C) 2008 Nokia Corporation -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * Generating UBI images. -++ * -++ * Authors: Oliver Lohmann -++ * Artem Bityutskiy -++ */ -++ -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include "crc32.h" -++#include "common.h" -++ -++#define PROGRAM_NAME "libubigen" -++ -++/** -++ * ubigen_info_init - initialize libubigen. -++ * @ui: libubigen information -++ * @peb_size: flash physical eraseblock size -++ * @min_io_size: flash minimum input/output unit size -++ * @subpage_size: flash sub-page, if present (has to be equivalent to -++ * @min_io_size if does not exist) -++ * @vid_hdr_offs: offset of the VID header -++ * @ubi_ver: UBI version -++ */ -++void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size, -++ int subpage_size, int vid_hdr_offs, int ubi_ver) -++{ -++ if (!vid_hdr_offs) { -++ vid_hdr_offs = UBI_EC_HDR_SIZE + subpage_size - 1; -++ vid_hdr_offs /= subpage_size; -++ vid_hdr_offs *= subpage_size; -++ } -++ -++ ui->peb_size = peb_size; -++ ui->min_io_size = min_io_size; -++ ui->vid_hdr_offs = vid_hdr_offs; -++ ui->data_offs = vid_hdr_offs + UBI_VID_HDR_SIZE + min_io_size - 1; -++ ui->data_offs /= min_io_size; -++ ui->data_offs *= min_io_size; -++ ui->leb_size = peb_size - ui->data_offs; -++ ui->ubi_ver = ubi_ver; -++ -++ ui->max_volumes = ui->leb_size / UBI_VTBL_RECORD_SIZE; -++ if (ui->max_volumes > UBI_MAX_VOLUMES) -++ ui->max_volumes = UBI_MAX_VOLUMES; -++ ui->vtbl_size = ui->max_volumes * UBI_VTBL_RECORD_SIZE; -++} -++ -++/** -++ * ubigen_create_empty_vtbl - creates empty volume table. -++ * -++ * This function creates an empty volume table and returns a pointer to it in -++ * case of success and %NULL in case of failure. The returned object has to be -++ * freed with 'free()' call. -++ */ -++struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui) -++{ -++ struct ubi_vtbl_record *vtbl; -++ int i; -++ -++ vtbl = calloc(1, ui->vtbl_size); -++ if (!vtbl) { -++ sys_errmsg("cannot allocate %d bytes of memory", ui->vtbl_size); -++ return NULL; -++ } -++ -++ for (i = 0; i < ui->max_volumes; i++) { -++ uint32_t crc = crc32(UBI_CRC32_INIT, &vtbl[i], -++ UBI_VTBL_RECORD_SIZE_CRC); -++ vtbl[i].crc = cpu_to_be32(crc); -++ } -++ -++ return vtbl; -++} -++ -++/** -++ * ubigen_add_volume - add a volume to the volume table. -++ * @ui: libubigen information -++ * @vi: volume information -++ * @vtbl: volume table to add to -++ * -++ * This function adds volume described by input parameters to the volume table -++ * @vtbl. -++ */ -++int ubigen_add_volume(const struct ubigen_info *ui, -++ const struct ubigen_vol_info *vi, -++ struct ubi_vtbl_record *vtbl) -++{ -++ struct ubi_vtbl_record *vtbl_rec = &vtbl[vi->id]; -++ uint32_t tmp; -++ -++ if (vi->id >= ui->max_volumes) -++ return errmsg("too high volume id %d, max. volumes is %d", -++ vi->id, ui->max_volumes); -++ -++ if (vi->alignment >= ui->leb_size) -++ return errmsg("too large alignment %d, max is %d (LEB size)", -++ vi->alignment, ui->leb_size); -++ -++ memset(vtbl_rec, '\0', sizeof(struct ubi_vtbl_record)); -++ tmp = (vi->bytes + ui->leb_size - 1) / ui->leb_size; -++ vtbl_rec->reserved_pebs = cpu_to_be32(tmp); -++ vtbl_rec->alignment = cpu_to_be32(vi->alignment); -++ vtbl_rec->vol_type = vi->type; -++ tmp = ui->leb_size % vi->alignment; -++ vtbl_rec->data_pad = cpu_to_be32(tmp); -++ vtbl_rec->flags = vi->flags; -++ -++ memcpy(vtbl_rec->name, vi->name, vi->name_len); -++ vtbl_rec->name[vi->name_len] = '\0'; -++ vtbl_rec->name_len = cpu_to_be16(vi->name_len); -++ -++ tmp = crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC); -++ vtbl_rec->crc = cpu_to_be32(tmp); -++ return 0; -++} -++ -++/** -++ * ubigen_init_ec_hdr - initialize EC header. -++ * @ui: libubigen information -++ * @hdr: the EC header to initialize -++ * @ec: erase counter value -++ */ -++void ubigen_init_ec_hdr(const struct ubigen_info *ui, -++ struct ubi_ec_hdr *hdr, long long ec) -++{ -++ uint32_t crc; -++ -++ memset(hdr, '\0', sizeof(struct ubi_ec_hdr)); -++ -++ hdr->magic = cpu_to_be32(UBI_EC_HDR_MAGIC); -++ hdr->version = ui->ubi_ver; -++ hdr->ec = cpu_to_be64(ec); -++ hdr->vid_hdr_offset = cpu_to_be32(ui->vid_hdr_offs); -++ -++ hdr->data_offset = cpu_to_be32(ui->data_offs); -++ -++ crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC); -++ hdr->hdr_crc = cpu_to_be32(crc); -++} -++ -++/** -++ * init_vid_hdr - initialize VID header. -++ * @ui: libubigen information -++ * @vi: volume information -++ * @hdr: the VID header to initialize -++ * @lnum: logical eraseblock number -++ * @data: the contents of the LEB (static volumes only) -++ * @data_size: amount of data in this LEB (static volumes only) -++ * -++ * Note, @used_ebs, @data and @data_size are ignored in case of dynamic -++ * volumes. -++ */ -++static void init_vid_hdr(const struct ubigen_info *ui, -++ const struct ubigen_vol_info *vi, -++ struct ubi_vid_hdr *hdr, int lnum, -++ const void *data, int data_size) -++{ -++ uint32_t crc; -++ -++ memset(hdr, '\0', sizeof(struct ubi_vid_hdr)); -++ -++ hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC); -++ hdr->version = ui->ubi_ver; -++ hdr->vol_type = vi->type; -++ hdr->vol_id = cpu_to_be32(vi->id); -++ hdr->lnum = cpu_to_be32(lnum); -++ hdr->data_pad = cpu_to_be32(vi->data_pad); -++ hdr->compat = vi->compat; -++ -++ if (vi->type == UBI_VID_STATIC) { -++ hdr->data_size = cpu_to_be32(data_size); -++ hdr->used_ebs = cpu_to_be32(vi->used_ebs); -++ crc = crc32(UBI_CRC32_INIT, data, data_size); -++ hdr->data_crc = cpu_to_be32(crc); -++ } -++ -++ crc = crc32(UBI_CRC32_INIT, hdr, UBI_VID_HDR_SIZE_CRC); -++ hdr->hdr_crc = cpu_to_be32(crc); -++} -++ -++/** -++ * ubigen_write_volume - write UBI volume. -++ * @ui: libubigen information -++ * @vi: volume information -++ * @ec: erase coutner value to put to EC headers -++ * @bytes: volume size in bytes -++ * @in: input file descriptor (has to be properly seeked) -++ * @out: output file descriptor -++ * -++ * This function reads the contents of the volume from the input file @in and -++ * writes the UBI volume to the output file @out. Returns zero on success and -++ * %-1 on failure. -++ */ -++int ubigen_write_volume(const struct ubigen_info *ui, -++ const struct ubigen_vol_info *vi, long long ec, -++ long long bytes, int in, int out) -++{ -++ int len = vi->usable_leb_size, rd, lnum = 0; -++ char inbuf[ui->leb_size+sizeof(unsigned int)], outbuf[ui->peb_size]; -++ -++ if (vi->id >= ui->max_volumes) -++ return errmsg("too high volume id %d, max. volumes is %d", -++ vi->id, ui->max_volumes); -++ -++ if (vi->alignment >= ui->leb_size) -++ return errmsg("too large alignment %d, max is %d (LEB size)", -++ vi->alignment, ui->leb_size); -++ -++ memset(outbuf, 0xFF, ui->data_offs); -++ ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec); -++ -++ while (bytes) { -++ int l; -++ struct ubi_vid_hdr *vid_hdr; -++ -++ if (bytes < len) -++ len = bytes; -++ bytes -= len; -++ -++ l = len; -++ do { -++ rd = read(in, inbuf + len - l, sizeof(unsigned int)); -++ if (rd != sizeof(unsigned int)) -++ return sys_errmsg("cannot read leb lnum from the input file"); -++ -++ rd = read(in, inbuf + len - l + sizeof(unsigned int), l); -++ if (rd != l) -++ return sys_errmsg("cannot read %d bytes from the input file", l); -++ -++ l -= rd; -++ } while (l); -++ -++ vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]); -++ lnum = ((unsigned int *)inbuf)[0]; -++ init_vid_hdr(ui, vi, vid_hdr, lnum, inbuf+sizeof(unsigned int), len); -++ -++ memcpy(outbuf + ui->data_offs, inbuf+sizeof(unsigned int), len); -++ memset(outbuf + ui->data_offs + len, 0xFF, -++ ui->peb_size - ui->data_offs - len); -++ -++ if (write(out, outbuf, ui->peb_size) != ui->peb_size) -++ return sys_errmsg("cannot write %d bytes to the output file", ui->peb_size); -++ -++// lnum += 1; -++ } -++ -++ return 0; -++} -++ -++/** -++ * ubigen_write_layout_vol - write UBI layout volume -++ * @ui: libubigen information -++ * @peb1: physical eraseblock number to write the first volume table copy -++ * @peb2: physical eraseblock number to write the second volume table copy -++ * @ec1: erase counter value for @peb1 -++ * @ec2: erase counter value for @peb1 -++ * @vtbl: volume table -++ * @fd: output file descriptor seeked to the proper position -++ * -++ * This function creates the UBI layout volume which contains 2 copies of the -++ * volume table. Returns zero in case of success and %-1 in case of failure. -++ */ -++int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2, -++ long long ec1, long long ec2, -++ struct ubi_vtbl_record *vtbl, int fd) -++{ -++ int ret; -++ struct ubigen_vol_info vi; -++ char outbuf[ui->peb_size]; -++ struct ubi_vid_hdr *vid_hdr; -++ off_t seek; -++ -++ vi.bytes = ui->leb_size * UBI_LAYOUT_VOLUME_EBS; -++ vi.id = UBI_LAYOUT_VOLUME_ID; -++ vi.alignment = UBI_LAYOUT_VOLUME_ALIGN; -++ vi.data_pad = ui->leb_size % UBI_LAYOUT_VOLUME_ALIGN; -++ vi.usable_leb_size = ui->leb_size - vi.data_pad; -++ vi.data_pad = ui->leb_size - vi.usable_leb_size; -++ vi.type = UBI_LAYOUT_VOLUME_TYPE; -++ vi.name = UBI_LAYOUT_VOLUME_NAME; -++ vi.name_len = strlen(UBI_LAYOUT_VOLUME_NAME); -++ vi.compat = UBI_LAYOUT_VOLUME_COMPAT; -++ -++ memset(outbuf, 0xFF, ui->data_offs); -++ vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]); -++ memcpy(outbuf + ui->data_offs, vtbl, ui->vtbl_size); -++ memset(outbuf + ui->data_offs + ui->vtbl_size, 0xFF, -++ ui->peb_size - ui->data_offs - ui->vtbl_size); -++ -++ seek = peb1 * ui->peb_size; -++ if (lseek(fd, seek, SEEK_SET) != seek) -++ return sys_errmsg("cannot seek output file"); -++ ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec1); -++ init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0); -++ ret = write(fd, outbuf, ui->peb_size); -++ if (ret != ui->peb_size) -++ return sys_errmsg("cannot write %d bytes", ui->peb_size); -++ -++ seek = peb2 * ui->peb_size; -++ if (lseek(fd, seek, SEEK_SET) != seek) -++ return sys_errmsg("cannot seek output file"); -++ ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec2); -++ init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0); -++ ret = write(fd, outbuf, ui->peb_size); -++ if (ret != ui->peb_size) -++ return sys_errmsg("cannot write %d bytes", ui->peb_size); -++ -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubiattach.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubiattach.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubiattach.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubiattach.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,205 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ */ -++ -++/* -++ * An utility to attach MTD devices to UBI. -++ * -++ * Author: Artem Bityutskiy -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include "common.h" -++ -++#define PROGRAM_VERSION "1.0" -++#define PROGRAM_NAME "ubiattach" -++ -++/* The variables below are set by command line arguments */ -++struct args { -++ int devn; -++ int mtdn; -++ int vidoffs; -++ const char *node; -++}; -++ -++static struct args args = { -++ .devn = UBI_DEV_NUM_AUTO, -++ .mtdn = -1, -++ .vidoffs = 0, -++ .node = NULL, -++}; -++ -++static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION -++ " - a tool to attach MTD device to UBI."; -++ -++static const char *optionsstr = -++"-d, --devn= the number to assign to the newly created UBI device\n" -++" (the number is assigned automatically if this is not\n" -++" specified\n" -++"-m, --mtdn= MTD device number to attach\n" -++"-O, --vid-hdr-offset VID header offset (do not specify this unless you\n" -++" really know what you do and the optimal defaults will\n" -++" be used)\n" -++"-h, --help print help message\n" -++"-V, --version print program version"; -++ -++static const char *usage = -++"Usage: " PROGRAM_NAME " [-m ] [-d ]\n" -++"\t\t[--mtdn=] [--devn ]\n" -++"Example 1: " PROGRAM_NAME " /dev/ubi_ctrl -m 0 - attach MTD device 0 (mtd0) to UBI\n" -++"Example 2: " PROGRAM_NAME " /dev/ubi_ctrl -m 0 -d 3 - attach MTD device 0 (mtd0) to UBI and\n" -++" and create UBI device number 3 (ubi3)"; -++ -++static const struct option long_options[] = { -++ { .name = "devn", .has_arg = 1, .flag = NULL, .val = 'd' }, -++ { .name = "mtdn", .has_arg = 1, .flag = NULL, .val = 'm' }, -++ { .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ { NULL, 0, NULL, 0}, -++}; -++ -++static int parse_opt(int argc, char * const argv[]) -++{ -++ while (1) { -++ int key; -++ char *endp; -++ -++ key = getopt_long(argc, argv, "m:d:O:hV", long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ case 'd': -++ args.devn = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.devn < 0) -++ return errmsg("bad UBI device number: \"%s\"", optarg); -++ -++ break; -++ -++ case 'm': -++ args.mtdn = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.mtdn < 0) -++ return errmsg("bad MTD device number: \"%s\"", optarg); -++ -++ break; -++ -++ case 'O': -++ args.vidoffs = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.vidoffs <= 0) -++ return errmsg("bad VID header offset: \"%s\"", optarg); -++ -++ break; -++ -++ case 'h': -++ fprintf(stderr, "%s\n\n", doc); -++ fprintf(stderr, "%s\n\n", usage); -++ fprintf(stderr, "%s\n", optionsstr); -++ exit(EXIT_SUCCESS); -++ -++ case 'V': -++ fprintf(stderr, "%s\n", PROGRAM_VERSION); -++ exit(EXIT_SUCCESS); -++ -++ case ':': -++ return errmsg("parameter is missing"); -++ -++ default: -++ fprintf(stderr, "Use -h for help\n"); -++ return -1; -++ } -++ } -++ -++ if (optind == argc) -++ return errmsg("UBI control device name was not specified (use -h for help)"); -++ else if (optind != argc - 1) -++ return errmsg("more then one UBI control device specified (use -h for help)"); -++ -++ if (args.mtdn == -1) -++ return errmsg("MTD device number was not specified (use -h for help)"); -++ -++ args.node = argv[optind]; -++ return 0; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ int err; -++ libubi_t libubi; -++ struct ubi_info ubi_info; -++ struct ubi_dev_info dev_info; -++ struct ubi_attach_request req; -++ -++ err = parse_opt(argc, argv); -++ if (err) -++ return -1; -++ -++ libubi = libubi_open(1); -++ if (libubi == NULL) -++ return sys_errmsg("cannot open libubi"); -++ -++ /* -++ * Make sure the kernel is fresh enough and this feature is supported. -++ */ -++ err = ubi_get_info(libubi, &ubi_info); -++ if (err) { -++ sys_errmsg("cannot get UBI information"); -++ goto out_libubi; -++ } -++ -++ if (ubi_info.ctrl_major == -1) { -++ errmsg("MTD attach/detach feature is not supported by your kernel"); -++ goto out_libubi; -++ } -++ -++ req.dev_num = args.devn; -++ req.mtd_num = args.mtdn; -++ req.vid_hdr_offset = args.vidoffs; -++ -++ err = ubi_attach_mtd(libubi, args.node, &req); -++ if (err) { -++ sys_errmsg("cannot attach mtd%d", args.mtdn); -++ goto out_libubi; -++ } -++ -++ /* Print some information about the new UBI device */ -++ err = ubi_get_dev_info1(libubi, req.dev_num, &dev_info); -++ if (err) { -++ sys_errmsg("cannot get information about newly created UBI device"); -++ goto out_libubi; -++ } -++ -++ printf("UBI device number %d, total %d LEBs (", dev_info.dev_num, dev_info.total_lebs); -++ ubiutils_print_bytes(dev_info.total_bytes, 0); -++ printf("), available %d LEBs (", dev_info.avail_lebs); -++ ubiutils_print_bytes(dev_info.avail_bytes, 0); -++ printf("), LEB size "); -++ ubiutils_print_bytes(dev_info.leb_size, 1); -++ printf("\n"); -++ -++ libubi_close(libubi); -++ return 0; -++ -++out_libubi: -++ libubi_close(libubi); -++ return -1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubicrc32.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubicrc32.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubicrc32.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubicrc32.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,124 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * Calculate CRC32 with UBI start value (0xFFFFFFFF) for a given binary image. -++ * -++ * Author: Oliver Lohmann -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "crc32.h" -++#include "common.h" -++ -++#define BUFSIZE 4096 -++ -++#define PROGRAM_VERSION "1.0" -++#define PROGRAM_NAME "ubicrc32" -++ -++static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION -++ " - a tool to calculate CRC32 with UBI start value (0xFFFFFFFF)"; -++ -++static const char *optionsstr = -++"-h, --help print help message\n" -++"-V, --version print program version"; -++ -++static const char *usage = -++"Usage: " PROGRAM_NAME " [-h] [--help]"; -++ -++static const struct option long_options[] = { -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ { NULL, 0, NULL, 0}, -++}; -++ -++static int parse_opt(int argc, char * const argv[]) -++{ -++ while (1) { -++ int key; -++ -++ key = getopt_long(argc, argv, "hV", long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ case 'h': -++ fprintf(stderr, "%s\n\n", doc); -++ fprintf(stderr, "%s\n\n", usage); -++ fprintf(stderr, "%s\n", optionsstr); -++ exit(EXIT_SUCCESS); -++ -++ case 'V': -++ fprintf(stderr, "%s\n", PROGRAM_VERSION); -++ exit(EXIT_SUCCESS); -++ -++ case ':': -++ return errmsg("parameter is missing"); -++ -++ default: -++ fprintf(stderr, "Use -h for help\n"); -++ return -1; -++ } -++ } -++ -++ return 0; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ int err = 0; -++ uint32_t crc = UBI_CRC32_INIT; -++ char buf[BUFSIZE]; -++ FILE *fp; -++ -++ if (argc > 1) { -++ fp = fopen(argv[1], "r"); -++ if (!fp) -++ return sys_errmsg("cannot open \"%s\"", argv[1]); -++ } else -++ fp = stdin; -++ -++ err = parse_opt(argc, argv); -++ if (err) -++ return err; -++ -++ while (!feof(fp)) { -++ size_t read; -++ -++ read = fread(buf, 1, BUFSIZE, fp); -++ if (ferror(fp)) { -++ sys_errmsg("cannot read input file"); -++ err = -1; -++ goto out_close; -++ } -++ crc = crc32(crc, buf, read); -++ } -++ -++ printf("0x%08x\n", crc); -++ -++out_close: -++ if (fp != stdin) -++ fclose(fp); -++ return err; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubicrcsf.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubicrcsf.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubicrcsf.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubicrcsf.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,94 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * An utility to generate input file CRC -++ * -++ * Authors: Yurong Tan (Nancy) -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include "common.h" -++#include "crc32.h" -++ -++#define PROGRAM_VERSION "1.1" -++#define PROGRAM_NAME "ubicrcsf" -++#define UBI_LEB_SIZE 258048 -++#define BUF_SIZE (UBI_LEB_SIZE + sizeof(unsigned int)) -++ -++/* -++ * usage: $ubicrcsf ubifs.img -++ */ -++int main(int argc, char * const argv[]) -++{ -++ int err, ifd, tmp, i; -++ int crc_sum = 0; -++ struct stat st; -++ char *buf=NULL; -++ -++ buf = malloc(BUF_SIZE); -++ if(buf==NULL){ -++ printf("no mem\n"); -++ goto out_free; -++ } -++ -++ err = stat(argv[1], &st); -++ if (err < 0) { -++ printf("stat failed on \"%s\"", argv[1]); -++ goto out_free; -++ } -++ -++ ifd = open(argv[1], O_RDONLY); -++ if (ifd == -1) { -++ printf("cannot open \"%s\"", argv[1]); -++ goto out_close; -++ } -++ -++ tmp = st.st_size/BUF_SIZE; -++ -++ for( i=0; i< tmp; i++ ){ -++ err = read(ifd, buf, BUF_SIZE); -++ if (err != BUF_SIZE) { -++ printf("read error\n"); -++ goto out_close; -++ } -++ crc_sum = crc32(crc_sum, &buf[sizeof(unsigned int)], UBI_LEB_SIZE); -++ } -++ -++ printf("CRC sum: %d\n",crc_sum); -++ free(buf); -++ close(ifd); -++ return 0; -++out_close: -++ close(ifd); -++out_free: -++ free(buf); -++ return -1; -++} -++ -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubicrcvol.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubicrcvol.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubicrcvol.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubicrcvol.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,221 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * An utility to update UBI volumes. -++ * -++ * Authors: Frank Haverkamp -++ * Joshua W. Boyer -++ * Artem Bityutskiy -++ * Yurong Tan (Nancy) -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include "common.h" -++#include "crc32.h" -++ -++#define PROGRAM_VERSION "1.1" -++#define PROGRAM_NAME "ubicrcfatvol" -++ -++struct args { -++ const char *node; -++ long long size; -++ int devn; -++ char dev_name[256]; -++}; -++ -++static struct args args = { -++ .devn = -1, -++}; -++ -++static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION -++ " - a tool to read UBI volumes data and generate CRC."; -++ -++static const char *optionsstr = -++"-h, --help print help message\n" -++"-V, --version print program version\n\n" -++"-s, --read size\n" -++; -++ -++static const char *usage = -++"Usage: " PROGRAM_NAME " [-s] [-h] [-V] [--help]\n" -++"\t\t\t[--version] \n\n" -++ "Example 1: " PROGRAM_NAME " /dev/ubi0_1 \n"; -++ -++struct option long_options[] = { -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ /* Deprecated -d and -B options */ -++ { .name = "size", .has_arg = 1, .flag = NULL, .val = 's' }, -++ { NULL, 0, NULL, 0} -++}; -++ -++static int parse_opt(int argc, char * const argv[]) -++{ -++ while (1) { -++ int key; -++ -++ key = getopt_long(argc, argv, "n:sh?Vd:", long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ -++ case 'h': -++ case '?': -++ fprintf(stderr, "%s\n\n", doc); -++ fprintf(stderr, "%s\n\n", usage); -++ fprintf(stderr, "%s\n", optionsstr); -++ exit(EXIT_SUCCESS); -++ -++ case 's': -++ args.size = ubiutils_get_bytes(optarg); -++ if (args.size <= 0) -++ return errmsg("bad read size: \"%s\"", optarg); -++ break; -++ -++ case 'V': -++ fprintf(stderr, "%s\n", PROGRAM_VERSION); -++ exit(EXIT_SUCCESS); -++ -++ case ':': -++ return errmsg("parameter is missing"); -++ -++ default: -++ fprintf(stderr, "Use -h for help\n"); -++ return -1; -++ } -++ } -++ -++ /* Handle deprecated -d option */ -++ if (args.devn != -1) { -++ sprintf(args.dev_name, "/dev/ubi%d", args.devn); -++ args.node = args.dev_name; -++ } else { -++ if (optind == argc) -++ return errmsg("UBI device name was not specified (use -h for help)"); -++ else if (optind != argc - 1) -++ return errmsg("specify UBI device name and image file name as first 2 " -++ "parameters (use -h for help)"); -++ } -++ -++ args.node = argv[optind]; -++ -++ return 0; -++} -++ -++static int crc_volume(libubi_t libubi, struct ubi_vol_info *vol_info) -++{ -++ int fd; -++ struct ubi_leb leb; -++ int i, tmp; -++ int crc_sum = 0; -++ -++ leb.buf = malloc(vol_info->leb_size); -++ if (!leb.buf) -++ return errmsg("cannot allocate %d bytes of memory", vol_info->leb_size); -++ -++ fd = open(args.node, O_RDONLY); -++ if (fd == -1) { -++ sys_errmsg("cannot open UBI volume \"%s\"", args.node); -++ goto out_free; -++ } -++ -++ for(i=0; i < vol_info->rsvd_lebs ; i++){ -++ leb.lnum = i; -++ tmp = ubi_leb_read_start(fd, &leb); -++ if(tmp == 1) -++ continue; -++ else if(tmp == 0){ -++ crc_sum = crc32(crc_sum, leb.buf, vol_info->leb_size); -++ }else{ -++ printf("LEB %d read error\n", i); -++ goto out_close; -++ } -++ } -++ -++ close(fd); -++ free(leb.buf); -++ printf("CRC sum: %d\n",crc_sum); -++ return 0; -++ goto out_close; -++out_close: -++ close(fd); -++out_free: -++ free(leb.buf); -++ return -1; -++} -++ -++ -++int main(int argc, char * const argv[]) -++{ -++ int err; -++ libubi_t libubi; -++ struct ubi_vol_info vol_info; -++ -++ err = parse_opt(argc, argv); -++ if (err) -++ return -1; -++ -++ libubi = libubi_open(1); -++ if (libubi == NULL) { -++ sys_errmsg("cannot open libubi"); -++ goto out_libubi; -++ } -++ -++ err = ubi_node_type(libubi, args.node); -++ if (err == 1) { -++ errmsg("\"%s\" is an UBI device node, not an UBI volume node", -++ args.node); -++ goto out_libubi; -++ } else if (err < 0) { -++ errmsg("\"%s\" is not an UBI volume node", args.node); -++ goto out_libubi; -++ } -++ -++ err = ubi_get_vol_info(libubi, args.node, &vol_info); -++ if (err) { -++ sys_errmsg("cannot get information about UBI volume \"%s\"", -++ args.node); -++ goto out_libubi; -++ } -++ -++ err = crc_volume(libubi, &vol_info); -++ if (err) -++ goto out_libubi; -++ -++ libubi_close(libubi); -++ return 0; -++ -++out_libubi: -++ libubi_close(libubi); -++ return -1; -++ -++} -++ -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubidetach.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubidetach.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubidetach.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubidetach.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,181 @@ -++/* -++ * Copyright (C) 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ */ -++ -++/* -++ * An utility to delete UBI devices (detach MTD devices from UBI). -++ * -++ * Author: Artem Bityutskiy -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include "common.h" -++ -++#define PROGRAM_VERSION "1.0" -++#define PROGRAM_NAME "ubidetach" -++ -++/* The variables below are set by command line arguments */ -++struct args { -++ int devn; -++ int mtdn; -++ const char *node; -++}; -++ -++static struct args args = { -++ .devn = UBI_DEV_NUM_AUTO, -++ .mtdn = -1, -++ .node = NULL, -++}; -++ -++static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION -++" - a tool to remove UBI devices (detach MTD devices from UBI)"; -++ -++static const char *optionsstr = -++"-d, --devn= UBI device number to delete\n" -++"-m, --mtdn= or altrnatively, MTD device number to detach -\n" -++" this will delete corresponding UBI device\n" -++"-h, --help print help message\n" -++"-V, --version print program version"; -++ -++static const char *usage = -++"Usage: " PROGRAM_NAME " [-d ] [-m ]\n" -++"\t\t[--devn ] [--mtdn=]\n" -++"Example 1: " PROGRAM_NAME " /dev/ubi_ctrl -d 2 - delete UBI device 2 (ubi2)\n" -++"Example 2: " PROGRAM_NAME " /dev/ubi_ctrl -m 0 - detach MTD device 0 (mtd0)"; -++ -++static const struct option long_options[] = { -++ { .name = "devn", .has_arg = 1, .flag = NULL, .val = 'd' }, -++ { .name = "mtdn", .has_arg = 1, .flag = NULL, .val = 'm' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ { NULL, 0, NULL, 0}, -++}; -++ -++static int parse_opt(int argc, char * const argv[]) -++{ -++ while (1) { -++ int key; -++ char *endp; -++ -++ key = getopt_long(argc, argv, "m:d:hV", long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ case 'd': -++ args.devn = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.devn < 0) -++ return errmsg("bad UBI device number: \"%s\"", optarg); -++ -++ break; -++ -++ case 'm': -++ args.mtdn = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.mtdn < 0) -++ return errmsg("bad MTD device number: \"%s\"", optarg); -++ -++ break; -++ -++ case 'h': -++ fprintf(stderr, "%s\n\n", doc); -++ fprintf(stderr, "%s\n\n", usage); -++ fprintf(stderr, "%s\n", optionsstr); -++ exit(EXIT_SUCCESS); -++ -++ case 'V': -++ fprintf(stderr, "%s\n", PROGRAM_VERSION); -++ exit(EXIT_SUCCESS); -++ -++ case ':': -++ return errmsg("parameter is missing"); -++ -++ default: -++ fprintf(stderr, "Use -h for help\n"); -++ return -1; -++ } -++ } -++ -++ if (optind == argc) -++ return errmsg("UBI control device name was not specified (use -h for help)"); -++ else if (optind != argc - 1) -++ return errmsg("more then one UBI control device specified (use -h for help)"); -++ -++ if (args.mtdn == -1 && args.devn == -1) -++ return errmsg("neither MTD nor UBI devices were specified (use -h for help)"); -++ -++ if (args.mtdn != -1 && args.devn != -1) -++ return errmsg("specify either MTD or UBI device (use -h for help)"); -++ -++ args.node = argv[optind]; -++ return 0; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ int err; -++ libubi_t libubi; -++ struct ubi_info ubi_info; -++ -++ err = parse_opt(argc, argv); -++ if (err) -++ return -1; -++ -++ libubi = libubi_open(1); -++ if (libubi == NULL) -++ return sys_errmsg("cannot open libubi"); -++ -++ /* -++ * Make sure the kernel is fresh enough and this feature is supported. -++ */ -++ err = ubi_get_info(libubi, &ubi_info); -++ if (err) { -++ sys_errmsg("cannot get UBI information"); -++ goto out_libubi; -++ } -++ -++ if (ubi_info.ctrl_major == -1) { -++ errmsg("MTD detach/detach feature is not supported by your kernel"); -++ goto out_libubi; -++ } -++ -++ if (args.devn != -1) { -++ err = ubi_remove_dev(libubi, args.node, args.devn); -++ if (err) { -++ sys_errmsg("cannot remove ubi%d", args.devn); -++ goto out_libubi; -++ } -++ } else { -++ err = ubi_detach_mtd(libubi, args.node, args.mtdn); -++ if (err) { -++ sys_errmsg("cannot detach mtd%d", args.mtdn); -++ goto out_libubi; -++ } -++ } -++ -++ libubi_close(libubi); -++ return 0; -++ -++out_libubi: -++ libubi_close(libubi); -++ return -1; -++} -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubidumpvol.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubidumpvol.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubidumpvol.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubidumpvol.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,264 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * An utility to update UBI volumes. -++ * -++ * Authors: Frank Haverkamp -++ * Joshua W. Boyer -++ * Artem Bityutskiy -++ * Yurong Tan (Nancy) -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include "common.h" -++ -++#define PROGRAM_VERSION "1.1" -++#define PROGRAM_NAME "ubidumpvol" -++ -++struct args { -++ int truncate; -++ const char *node; -++ const char *img; -++ /* For deprecated -d and -B options handling */ -++ int devn; -++ char dev_name[256]; -++ int broken_update; -++}; -++ -++static struct args args = { -++ .devn = -1, -++}; -++ -++static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION -++ " - a tool to write data to UBI volumes."; -++ -++static const char *optionsstr = -++"-n, --vol_id= ID of UBI volume to update\n" -++"-t, --truncate truncate volume (wipe it out)\n" -++"-h, --help print help message\n" -++"-V, --version print program version\n\n" -++"The following are compatibility options which are deprecated, do not use them\n" -++"-d, --devn= UBI device number - may be used instead of the UBI\n" -++" device node name in which case the utility assumes\n" -++" that the device node is \"/dev/ubi\"\n" -++"-B, --broken-update broken update, this is for testing"; -++ -++static const char *usage = -++"Usage: " PROGRAM_NAME " [-t] [-h] [-V] [--truncate] [--help]\n" -++"\t\t\t[--version] \n\n" -++ "Example 1: " PROGRAM_NAME " /dev/ubi0_1 fs.img - dump UBI volume /dev/ubi0_1 to file \"fs.img\" \n"; -++ -++struct option long_options[] = { -++ { .name = "truncate", .has_arg = 0, .flag = NULL, .val = 't' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ /* Deprecated -d and -B options */ -++ { .name = "devn", .has_arg = 1, .flag = NULL, .val = 'd' }, -++ { .name = "broken-update", .has_arg = 1, .flag = NULL, .val = 'B' }, -++ { NULL, 0, NULL, 0} -++}; -++ -++static int parse_opt(int argc, char * const argv[]) -++{ -++ while (1) { -++ int key; -++ -++ key = getopt_long(argc, argv, "n:th?Vd:", long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ case 't': -++ args.truncate = 1; -++ break; -++ -++ case 'h': -++ case '?': -++ fprintf(stderr, "%s\n\n", doc); -++ fprintf(stderr, "%s\n\n", usage); -++ fprintf(stderr, "%s\n", optionsstr); -++ exit(EXIT_SUCCESS); -++ -++ case 'd': -++ { -++ char *endp; -++ -++ /* Handle deprecated -d option */ -++ warnmsg("-d is depricated and will be removed, do not use it"); -++ args.devn = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.devn < 0) -++ return errmsg("bad UBI device number: " "\"%s\"", optarg); -++ break; -++ } -++ -++ case 'B': -++ /* Handle deprecated -B option */ -++ warnmsg("-B is depricated and will be removed, do not use it"); -++ args.broken_update = 1; -++ break; -++ -++ case 'V': -++ fprintf(stderr, "%s\n", PROGRAM_VERSION); -++ exit(EXIT_SUCCESS); -++ -++ case ':': -++ return errmsg("parameter is missing"); -++ -++ default: -++ fprintf(stderr, "Use -h for help\n"); -++ return -1; -++ } -++ } -++ -++ /* Handle deprecated -d option */ -++ if (args.devn != -1) { -++ sprintf(args.dev_name, "/dev/ubi%d", args.devn); -++ args.node = args.dev_name; -++ } else { -++ if (optind == argc) -++ return errmsg("UBI device name was not specified (use -h for help)"); -++ else if (optind != argc - 2) -++ return errmsg("specify UBI device name and image file name as first 2 " -++ "parameters (use -h for help)"); -++ } -++ -++ args.node = argv[optind]; -++ args.img = argv[optind + 1]; -++ -++ return 0; -++} -++ -++static int dump_volume(libubi_t libubi, struct ubi_vol_info *vol_info) -++{ -++ int err, fd, ifd; -++ struct ubi_leb leb; -++ int i, tmp; -++ -++ leb.buf = malloc(vol_info->leb_size); -++ if (!leb.buf) -++ return errmsg("cannot allocate %d bytes of memory", vol_info->leb_size); -++ -++ fd = open(args.node, O_RDONLY); -++ if (fd == -1) { -++ sys_errmsg("cannot open UBI volume \"%s\"", args.node); -++ goto out_free; -++ } -++ -++ ifd = open(args.img, O_WRONLY | O_TRUNC | O_CREAT, 0644); -++ if (ifd == -1) { -++ sys_errmsg("cannot open \"%s\"", args.img); -++ goto out_close1; -++ } -++ -++ for(i=0; i < vol_info->rsvd_lebs; i++){ -++ leb.lnum = i; -++ tmp = ubi_leb_read_start(fd, &leb); -++ if(tmp == 1) -++ continue; -++ else if(tmp == 0){ -++ // write lnum -++ err = write(ifd, (char *)&leb.lnum, sizeof(leb.lnum)); -++ if (err != sizeof(leb.lnum)){ -++ perror("Image file write error\n"); -++ goto out_close; -++ } -++ // write LEB data -++ err = write(ifd, leb.buf, vol_info->leb_size); -++ if (err != vol_info->leb_size){ -++ perror("Image file write error\n"); -++ goto out_close; -++ } -++ }else{ -++ printf("LEB %d read error\n", i); -++ goto out_close; -++ } -++ } -++ -++ close(ifd); -++ close(fd); -++ free(leb.buf); -++ printf("Dump Volume succeed\n"); -++ return 0; -++ goto out_close; -++out_close: -++ close(ifd); -++out_close1: -++ close(fd); -++out_free: -++ free(leb.buf); -++ return -1; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ int err; -++ libubi_t libubi; -++ struct ubi_vol_info vol_info; -++ -++ err = parse_opt(argc, argv); -++ if (err) -++ return -1; -++ -++ if (!args.img && !args.truncate) -++ return errmsg("incorrect arguments, use -h for help"); -++ -++ libubi = libubi_open(1); -++ if (libubi == NULL) { -++ sys_errmsg("cannot open libubi"); -++ goto out_libubi; -++ } -++ -++ err = ubi_node_type(libubi, args.node); -++ if (err == 1) { -++ errmsg("\"%s\" is an UBI device node, not an UBI volume node", -++ args.node); -++ goto out_libubi; -++ } else if (err < 0) { -++ errmsg("\"%s\" is not an UBI volume node", args.node); -++ goto out_libubi; -++ } -++ -++ err = ubi_get_vol_info(libubi, args.node, &vol_info); -++ if (err) { -++ sys_errmsg("cannot get information about UBI volume \"%s\"", -++ args.node); -++ goto out_libubi; -++ } -++ -++ err = dump_volume(libubi, &vol_info); -++ if (err) -++ goto out_libubi; -++ -++ libubi_close(libubi); -++ return 0; -++ -++out_libubi: -++ libubi_close(libubi); -++ return -1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubiformat.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubiformat.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubiformat.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubiformat.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,712 @@ -++/* -++ * Copyright (C) 2008 Nokia Corporation -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * An utility to format MTD devices into UBI and flash UBI images. -++ * -++ * Author: Artem Bityutskiy -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include "crc32.h" -++#include "common.h" -++ -++#define PROGRAM_VERSION "1.0" -++#define PROGRAM_NAME "ubiformat" -++ -++/* The variables below are set by command line arguments */ -++struct args { -++ unsigned int yes:1; -++ unsigned int quiet:1; -++ unsigned int verbose:1; -++ unsigned int override_ec:1; -++ unsigned int novtbl:1; -++ int subpage_size; -++ int vid_hdr_offs; -++ int ubi_ver; -++ long long ec; -++ const char *image; -++ const char *node; -++}; -++ -++static struct args args = -++{ -++ .ubi_ver = 1, -++}; -++ -++static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION -++ " - a tool to format MTD devices and flash UBI images"; -++ -++static const char *optionsstr = -++"-s, --sub-page-size= minimum input/output unit used for UBI\n" -++" headers, e.g. sub-page size in case of NAND\n" -++" flash (equivalent to the minimum input/output\n" -++" unit size by default)\n" -++"-O, --vid-hdr-offset= offset if the VID header from start of the\n" -++" physical eraseblock (default is the next\n" -++" minimum I/O unit or sub-page after the EC\n" -++" header)\n" -++"-n, --no-volume-table only erase all eraseblock and preserve erase\n" -++" counters, do not write empty volume table\n" -++"-f, --flash-image= flash image file\n" -++"-e, --erase-counter= use as the erase counter value for all\n" -++" eraseblocks\n" -++"-y, --yes assume the answer is \"yes\" for all question\n" -++" this program would otherwise ask\n" -++"-q, --quiet suppress progress percentage information\n" -++"-v, --verbose be verbose\n" -++"-x, --ubi-ver= UBI version number to put to EC headers\n" -++" (default is 1)\n" -++"-h, -?, --help print help message\n" -++"-V, --version print program version\n"; -++ -++static const char *usage = -++"Usage: " PROGRAM_NAME " [-h] [-V] [-y] [-q] [-v]\n" -++"\t\t\t[-x ] [-E ] [-s ] [-O ] [-n]\n" -++"\t\t\t[--help] [--version] [--yes] [--verbose] [--quiet]\n" -++"\t\t\t[--ec=] [--vid-hdr-offset=]\n" -++"\t\t\t[--ubi-ver=] [--no-volume-table]\n\n" -++ -++"Example 1: " PROGRAM_NAME " /dev/mtd0 -y - format MTD device number 0 and do\n" -++" not ask questions.\n" -++"Example 2: " PROGRAM_NAME " /dev/mtd0 -q -e 0 - format MTD device number 0,\n" -++" be quiet and force erase counter value 0."; -++ -++static const struct option long_options[] = { -++ { .name = "sub-page-size", .has_arg = 1, .flag = NULL, .val = 's' }, -++ { .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' }, -++ { .name = "no-volume-table", .has_arg = 0, .flag = NULL, .val = 'n' }, -++ { .name = "flash-image", .has_arg = 0, .flag = NULL, .val = 'f' }, -++ { .name = "yes", .has_arg = 0, .flag = NULL, .val = 'y' }, -++ { .name = "erase-counter", .has_arg = 1, .flag = NULL, .val = 'e' }, -++ { .name = "quiet", .has_arg = 0, .flag = NULL, .val = 'q' }, -++ { .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' }, -++ { .name = "ubi-ver", .has_arg = 1, .flag = NULL, .val = 'x' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ { NULL, 0, NULL, 0}, -++}; -++ -++static int parse_opt(int argc, char * const argv[]) -++{ -++ while (1) { -++ int key; -++ char *endp; -++ -++ key = getopt_long(argc, argv, "nh?Vyqve:x:s:O:f:", long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ case 's': -++ args.subpage_size = ubiutils_get_bytes(optarg); -++ if (args.subpage_size <= 0) -++ return errmsg("bad sub-page size: \"%s\"", optarg); -++ if (!is_power_of_2(args.subpage_size)) -++ return errmsg("sub-page size should be power of 2"); -++ break; -++ -++ case 'O': -++ args.vid_hdr_offs = strtoul(optarg, &endp, 0); -++ if (args.vid_hdr_offs <= 0 || *endp != '\0' || endp == optarg) -++ return errmsg("bad VID header offset: \"%s\"", optarg); -++ break; -++ -++ case 'e': -++ args.ec = strtoull(optarg, &endp, 0); -++ if (args.ec <= 0 || *endp != '\0' || endp == optarg) -++ return errmsg("bad erase counter value: \"%s\"", optarg); -++ if (args.ec >= EC_MAX) -++ return errmsg("too high erase %llu, counter, max is %u", args.ec, EC_MAX); -++ args.override_ec = 1; -++ break; -++ -++ case 'f': -++ args.image = optarg; -++ break; -++ -++ case 'n': -++ args.novtbl = 1; -++ break; -++ -++ case 'y': -++ args.yes = 1; -++ break; -++ -++ case 'q': -++ args.quiet = 1; -++ break; -++ -++ case 'x': -++ args.ubi_ver = strtoul(optarg, &endp, 0); -++ if (args.ubi_ver < 0 || *endp != '\0' || endp == optarg) -++ return errmsg("bad UBI version: \"%s\"", optarg); -++ break; -++ -++ case 'v': -++ args.verbose = 1; -++ break; -++ -++ case 'V': -++ fprintf(stderr, "%s\n", PROGRAM_VERSION); -++ exit(EXIT_SUCCESS); -++ -++ case 'h': -++ case '?': -++ fprintf(stderr, "%s\n\n", doc); -++ fprintf(stderr, "%s\n\n", usage); -++ fprintf(stderr, "%s\n", optionsstr); -++ exit(EXIT_SUCCESS); -++ -++ case ':': -++ return errmsg("parameter is missing"); -++ -++ default: -++ fprintf(stderr, "Use -h for help\n"); -++ return -1; -++ } -++ } -++ -++ if (args.quiet && args.verbose) -++ return errmsg("using \"-q\" and \"-v\" at the same time does not make sense"); -++ -++ if (optind == argc) -++ return errmsg("MTD device name was not specified (use -h for help)"); -++ else if (optind != argc - 1) -++ return errmsg("more then one MTD device specified (use -h for help)"); -++ -++ if (args.image && args.novtbl) -++ return errmsg("-n cannot be used together with -f"); -++ -++ args.node = argv[optind]; -++ return 0; -++} -++ -++static int want_exit(void) -++{ -++ char buf[4]; -++ -++ while (1) { -++ normsg_cont("continue? (yes/no) "); -++ scanf("%3s", buf); -++ if (!strncmp(buf, "yes", 3) || !strncmp(buf, "y", 1)) -++ return 0; -++ if (!strncmp(buf, "no", 2) || !strncmp(buf, "n", 1)) -++ return 1; -++ } -++} -++ -++static int answer_is_yes(void) -++{ -++ char buf[4]; -++ -++ while (1) { -++ scanf("%3s", buf); -++ if (!strncmp(buf, "yes", 3) || !strncmp(buf, "y", 1)) -++ return 1; -++ if (!strncmp(buf, "no", 2) || !strncmp(buf, "n", 1)) -++ return 0; -++ } -++} -++ -++static void print_bad_eraseblocks(const struct mtd_info *mtd, -++ const struct ubi_scan_info *si) -++{ -++ int first = 1, eb; -++ -++ if (si->bad_cnt == 0) -++ return; -++ -++ normsg_cont("bad eraseblocks: "); -++ for (eb = 0; eb < mtd->eb_cnt; eb++) { -++ if (si->ec[eb] != EB_BAD) -++ continue; -++ if (first) { -++ printf("%d", eb); -++ first = 0; -++ } else -++ printf(", %d", eb); -++ } -++ printf("\n"); -++} -++ -++static int change_ec(struct ubi_ec_hdr *hdr, long long ec) -++{ -++ uint32_t crc; -++ -++ /* Check the EC header */ -++ if (be32_to_cpu(hdr->magic) != UBI_EC_HDR_MAGIC) -++ return errmsg("mad UBI magic %#08x, should be %#08x", -++ be32_to_cpu(hdr->magic), UBI_EC_HDR_MAGIC); -++ -++ crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC); -++ if (be32_to_cpu(hdr->hdr_crc) != crc) -++ return errmsg("bad CRC %#08x, should be %#08x\n", -++ crc, be32_to_cpu(hdr->hdr_crc)); -++ -++ hdr->ec = cpu_to_be64(ec); -++ crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC); -++ hdr->hdr_crc = cpu_to_be32(crc); -++ -++ return 0; -++} -++ -++static int drop_ffs(const struct mtd_info *mtd, const void *buf, int len) -++{ -++ int i; -++ -++ for (i = len - 1; i >= 0; i--) -++ if (((const uint8_t *)buf)[i] != 0xFF) -++ break; -++ -++ /* The resulting length must be aligned to the minimum flash I/O size */ -++ len = i + 1; -++ len = (len + mtd->min_io_size - 1) / mtd->min_io_size; -++ len *= mtd->min_io_size; -++ return len; -++} -++ -++static int flash_image(const struct mtd_info *mtd, const struct ubigen_info *ui, -++ struct ubi_scan_info *si) -++{ -++ int fd, img_ebs, eb, written_ebs = 0, divisor; -++ struct stat st; -++ -++ if (stat(args.image, &st)) -++ return sys_errmsg("cannot open \"%s\"", args.image); -++ -++ img_ebs = st.st_size / mtd->eb_size; -++ if (img_ebs > si->good_cnt) -++ return sys_errmsg("file \"%s\" is too large (%lld bytes)", -++ args.image, (long long)st.st_size); -++ -++ if (st.st_size % mtd->eb_size) -++ return sys_errmsg("file \"%s\" (size %lld bytes) is not multiple of eraseblock size (%d bytes)", -++ args.image, (long long)st.st_size, mtd->eb_size); -++ -++ fd = open(args.image, O_RDONLY); -++ if (fd == -1) -++ return sys_errmsg("cannot open \"%s\"", args.image); -++ -++ verbose(args.verbose, "will write %d eraseblocks", img_ebs); -++ divisor = img_ebs; -++ for (eb = 0; eb < mtd->eb_cnt; eb++) { -++ int err, new_len; -++ char buf[mtd->eb_size]; -++ long long ec; -++ -++ if (!args.quiet && !args.verbose) { -++ printf("\r" PROGRAM_NAME ": flashing eraseblock %d -- %2lld %% complete ", -++ eb, (long long)(eb + 1) * 100 / divisor); -++ fflush(stdout); -++ } -++ -++ if (si->ec[eb] == EB_BAD) { -++ divisor += 1; -++ continue; -++ } -++ -++ if (args.verbose) { -++ normsg_cont("eraseblock %d: erase", eb); -++ fflush(stdout); -++ } -++ -++ err = mtd_erase(mtd, eb); -++ if (err) { -++ sys_errmsg("failed to erase eraseblock %d", eb); -++ goto out_close; -++ } -++ -++ if (read(fd, buf, mtd->eb_size) != mtd->eb_size) { -++ sys_errmsg("failed to read eraseblock %d from \"%s\"", -++ written_ebs, args.image); -++ goto out_close; -++ } -++ -++ -++ if (si->ec[eb] <= EC_MAX) -++ ec = si->ec[eb] + 1; -++ else if (!args.override_ec) -++ ec = si->mean_ec; -++ else -++ ec = args.ec; -++ -++ if (args.verbose) { -++ printf(", change EC to %lld", ec); -++ fflush(stdout); -++ } -++ -++ err = change_ec((struct ubi_ec_hdr *)buf, ec); -++ if (err) { -++ errmsg("bad EC header at eraseblock %d of \"%s\"", -++ written_ebs, args.image); -++ goto out_close; -++ } -++ -++ if (args.verbose) { -++ printf(", write data\n"); -++ fflush(stdout); -++ } -++ -++ new_len = drop_ffs(mtd, buf, mtd->eb_size); -++ -++ err = mtd_write(mtd, eb, 0, buf, new_len); -++ if (err) { -++ sys_errmsg("cannot write eraseblock %d", eb); -++ goto out_close; -++ } -++ if (++written_ebs >= img_ebs) -++ break; -++ } -++ -++ if (!args.quiet && !args.verbose) -++ printf("\n"); -++ close(fd); -++ return eb + 1; -++ -++out_close: -++ close(fd); -++ return -1; -++} -++ -++static int format(const struct mtd_info *mtd, const struct ubigen_info *ui, -++ const struct ubi_scan_info *si, int start_eb, int novtbl) -++{ -++ int eb, err, write_size; -++ struct ubi_ec_hdr *hdr; -++ struct ubi_vtbl_record *vtbl; -++ int eb1 = -1, eb2 = -1; -++ long long ec1 = -1, ec2 = -1; -++ -++ write_size = UBI_EC_HDR_SIZE + mtd->subpage_size - 1; -++ write_size /= mtd->subpage_size; -++ write_size *= mtd->subpage_size; -++ hdr = malloc(write_size); -++ if (!hdr) -++ return sys_errmsg("cannot allocate %d bytes of memory", write_size); -++ -++ memset(hdr, 0xFF, write_size); -++ -++ for (eb = start_eb; eb < mtd->eb_cnt; eb++) { -++ long long ec; -++ -++ if (!args.quiet && !args.verbose) { -++ printf("\r" PROGRAM_NAME ": formatting eraseblock %d -- %2lld %% complete ", -++ eb, (long long)(eb + 1 - start_eb) * 100 / (mtd->eb_cnt - start_eb)); -++ fflush(stdout); -++ } -++ -++ if (si->ec[eb] == EB_BAD) -++ continue; -++ -++ if (si->ec[eb] <= EC_MAX) -++ ec = si->ec[eb] + 1; -++ else if (!args.override_ec) -++ ec = si->mean_ec; -++ else -++ ec = args.ec; -++ ubigen_init_ec_hdr(ui, hdr, ec); -++ -++ if (args.verbose) { -++ normsg_cont("eraseblock %d: erase", eb); -++ fflush(stdout); -++ } -++ -++ err = mtd_erase(mtd, eb); -++ if (err) { -++ sys_errmsg("failed to erase eraseblock %d", eb); -++ goto out_free; -++ } -++ -++ if ((eb1 == -1 || eb2 == -1) && !novtbl) { -++ if (eb1 == -1) { -++ eb1 = eb; -++ ec1 = ec; -++ } else if (eb2 == -1) { -++ eb2 = eb; -++ ec2 = ec; -++ } -++ if (args.verbose) -++ printf(", do not write EC, leave for vtbl\n"); -++ continue; -++ } -++ -++ if (args.verbose) { -++ printf(", write EC %lld\n", ec); -++ fflush(stdout); -++ } -++ -++ err = mtd_write(mtd, eb, 0, hdr, write_size); -++ if (err) { -++ sys_errmsg("cannot write EC header (%d bytes buffer) to eraseblock %d", -++ write_size, eb); -++ if (args.subpage_size != mtd->min_io_size) -++ normsg("may be %d is incorrect?", args.subpage_size); -++ goto out_free; -++ } -++ } -++ -++ if (!args.quiet && !args.verbose) -++ printf("\n"); -++ -++ if (!novtbl) { -++ if (eb1 == -1 || eb2 == -1) { -++ errmsg("no eraseblocks for volume table"); -++ goto out_free; -++ } -++ -++ verbose(args.verbose, "write volume table to eraseblocks %d and %d", eb1, eb2); -++ vtbl = ubigen_create_empty_vtbl(ui); -++ if (!vtbl) -++ goto out_free; -++ -++ err = ubigen_write_layout_vol(ui, eb1, eb2, ec1, ec2, vtbl, mtd->fd); -++ free(vtbl); -++ if (err) { -++ errmsg("cannot write layout volume"); -++ goto out_free; -++ } -++ } -++ -++ free(hdr); -++ return 0; -++ -++out_free: -++ free(hdr); -++ return -1; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ int err, verbose; -++ struct mtd_info mtd; -++ libubi_t libubi; -++ struct ubigen_info ui; -++ struct ubi_scan_info *si; -++ -++ err = parse_opt(argc, argv); -++ if (err) -++ return -1; -++ -++ err = mtd_get_info(args.node, &mtd); -++ if (err) -++ return errmsg("cannot get information about \"%s\"", args.node); -++ -++ if (args.subpage_size == 0) -++ args.subpage_size = mtd.min_io_size; -++ else { -++ if (args.subpage_size > mtd.min_io_size) { -++ errmsg("sub-page cannot be larger than min. I/O unit"); -++ goto out_close; -++ } -++ -++ if (mtd.min_io_size % args.subpage_size) { -++ errmsg("min. I/O unit size should be multiple of sub-page size"); -++ goto out_close; -++ } -++ } -++ -++ /* Validate VID header offset if it was specified */ -++ if (args.vid_hdr_offs != 0) { -++ if (args.vid_hdr_offs % 8) { -++ errmsg("VID header offset has to be multiple of min. I/O unit size"); -++ goto out_close; -++ } -++ if (args.vid_hdr_offs + UBI_VID_HDR_SIZE > mtd.eb_size) { -++ errmsg("bad VID header offset"); -++ goto out_close; -++ } -++ } -++ -++ /* -++ * Because of MTD interface limitations 'mtd_get_info()' cannot get -++ * sub-page so we force the user to pass it via the command line. Let's -++ * hope the user passed us something sane. -++ */ -++ mtd.subpage_size = args.subpage_size; -++ -++ if (mtd.rdonly) { -++ errmsg("mtd%d (%s) is a read-only device", mtd.num, args.node); -++ goto out_close; -++ } -++ -++ /* Make sure this MTD device is not attached to UBI */ -++ libubi = libubi_open(0); -++ if (libubi) { -++ int ubi_dev_num; -++ -++ err = mtd_num2ubi_dev(libubi, mtd.num, &ubi_dev_num); -++ libubi_close(libubi); -++ if (!err) { -++ errmsg("please, first detach mtd%d (%s) from ubi%d", -++ mtd.num, args.node, ubi_dev_num); -++ goto out_close; -++ } -++ } -++ -++ if (!args.quiet) { -++ normsg_cont("mtd%d (%s), size ", mtd.num, mtd.type_str); -++ ubiutils_print_bytes(mtd.size, 1); -++ printf(", %d eraseblocks of ", mtd.eb_size); -++ ubiutils_print_bytes(mtd.eb_size, 1); -++ printf(", min. I/O size %d bytes\n", mtd.min_io_size); -++ } -++ -++ if (args.quiet) -++ verbose = 0; -++ else if (args.verbose) -++ verbose = 2; -++ else -++ verbose = 1; -++ err = ubi_scan(&mtd, &si, verbose); -++ if (err) { -++ errmsg("failed to scan mtd%d (%s)", mtd.num, args.node); -++ goto out_close; -++ } -++ -++ if (si->good_cnt == 0) { -++ errmsg("all %d eraseblocks are bad", si->bad_cnt); -++ goto out_free; -++ } -++ -++ if (si->good_cnt < 2 && (!args.novtbl || args.image)) { -++ errmsg("too few non-bad eraseblocks (%d) on mtd%d", si->good_cnt, mtd.num); -++ goto out_free; -++ } -++ -++ if (!args.quiet) { -++ if (si->ok_cnt) -++ normsg("%d eraseblocks have valid erase counter, mean value is %lld", -++ si->ok_cnt, si->mean_ec); -++ if (si->empty_cnt) -++ normsg("%d eraseblocks are supposedly empty", si->empty_cnt); -++ if (si->corrupted_cnt) -++ normsg("%d corrupted erase counters", si->corrupted_cnt); -++ print_bad_eraseblocks(&mtd, si); -++ } -++ -++ if (si->alien_cnt) { -++ if (!args.yes || !args.quiet) -++ warnmsg("%d of %d eraseblocks contain non-ubifs data", -++ si->alien_cnt, si->good_cnt); -++ if (!args.yes && want_exit()) { -++ if (args.yes && !args.quiet) -++ printf("yes\n"); -++ goto out_free; -++ } -++ } -++ -++ if (!args.override_ec && si->empty_cnt < si->good_cnt) { -++ int percent = ((double)si->ok_cnt)/si->good_cnt * 100; -++ -++ /* -++ * Make sure the majority of eraseblocks have valid -++ * erase counters. -++ */ -++ if (percent < 50) { -++ if (!args.yes || !args.quiet) -++ warnmsg("only %d of %d eraseblocks have valid erase counter", -++ si->ok_cnt, si->good_cnt); -++ normsg("erase counter 0 will be used for all eraseblocks"); -++ normsg("note, arbitrary erase counter value may be specified using -e option"); -++ if (!args.yes && want_exit()) { -++ if (args.yes && !args.quiet) -++ printf("yes\n"); -++ goto out_free; -++ } -++ args.ec = 0; -++ args.override_ec = 1; -++ } else if (percent < 95) { -++ if (!args.yes || !args.quiet) -++ warnmsg("only %d of %d eraseblocks have valid erase counter", -++ si->ok_cnt, si->good_cnt); -++ normsg("mean erase counter %lld will be used for the rest of eraseblock", -++ si->mean_ec); -++ if (!args.yes && want_exit()) { -++ if (args.yes && !args.quiet) -++ printf("yes\n"); -++ goto out_free; -++ } -++ args.ec = si->mean_ec; -++ args.override_ec = 1; -++ } -++ } -++ -++ if (!args.quiet && args.override_ec) -++ normsg("use erase counter %lld for all eraseblocks", args.ec); -++ -++ ubigen_info_init(&ui, mtd.eb_size, mtd.min_io_size, args.subpage_size, -++ args.vid_hdr_offs, args.ubi_ver); -++ -++ if (si->vid_hdr_offs != -1 && ui.vid_hdr_offs != si->vid_hdr_offs) { -++ /* -++ * Hmm, what we read from flash and what we calculated using -++ * min. I/O unit size and sub-page size differs. -++ */ -++ if (!args.yes || !args.quiet) { -++ warnmsg("VID header and data offsets on flash are %d and %d, " -++ "which is different to calculated offsets %d and %d", -++ si->vid_hdr_offs, si->data_offs, ui.vid_hdr_offs, -++ ui.data_offs); -++ normsg_cont("use old offsets %d and %d? (yes/no) ", -++ si->vid_hdr_offs, si->data_offs); -++ } -++ if (args.yes || answer_is_yes()) { -++ if (args.yes && !args.quiet) -++ printf("yes\n"); -++ ui.vid_hdr_offs = si->vid_hdr_offs; -++ ui.data_offs = si->data_offs; -++ } -++ } -++ -++ if (args.image) { -++ err = flash_image(&mtd, &ui, si); -++ if (err < 0) -++ goto out_free; -++ -++ err = format(&mtd, &ui, si, err, 1); -++ if (err) -++ goto out_free; -++ } else { -++ err = format(&mtd, &ui, si, 0, args.novtbl); -++ if (err) -++ goto out_free; -++ } -++ -++ ubi_scan_free(si); -++ close(mtd.fd); -++ return 0; -++ -++out_free: -++ ubi_scan_free(si); -++out_close: -++ close(mtd.fd); -++ return -1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubimkvol.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubimkvol.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubimkvol.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubimkvol.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,310 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * An utility to create UBI volumes. -++ * -++ * Authors: Artem Bityutskiy -++ * Frank Haverkamp -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include "common.h" -++ -++#define PROGRAM_VERSION "1.0" -++#define PROGRAM_NAME "ubimkvol" -++ -++/* The variables below are set by command line arguments */ -++struct args { -++ int vol_id; -++ int vol_type; -++ long long bytes; -++ int lebs; -++ int alignment; -++ const char *name; -++ int nlen; -++ const char *node; -++ int maxavs; -++ /* For deprecated -d option handling */ -++ int devn; -++ char dev_name[256]; -++}; -++ -++static struct args args = { -++ .vol_type = UBI_DYNAMIC_VOLUME, -++ .bytes = -1, -++ .lebs = -1, -++ .alignment = 1, -++ .vol_id = UBI_VOL_NUM_AUTO, -++ .devn = -1, -++}; -++ -++static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION -++ " - a tool to create UBI volumes."; -++ -++static const char *optionsstr = -++"-a, --alignment= volume alignment (default is 1)\n" -++"-n, --vol_id= UBI volume ID, if not specified, the volume ID\n" -++" will be assigned automatically\n" -++"-N, --name= volume name\n" -++"-s, --size= volume size volume size in bytes, kilobytes (KiB)\n" -++" or megabytes (MiB)\n" -++"-S, --lebs= alternative way to give volume size in logical\n" -++" eraseblocks\n" -++"-m, --maxavsize set volume size to maximum available size\n" -++"-t, --type= volume type (dynamic, static), default is dynamic\n" -++"-h, -?, --help print help message\n" -++"-V, --version print program version\n\n" -++"The following is a compatibility option which is deprecated, do not use it\n" -++"-d, --devn= UBI device number - may be used instead of the UBI\n" -++" device node name in which case the utility assumes\n" -++" that the device node is \"/dev/ubi\""; -++ -++ -++static const char *usage = -++"Usage: " PROGRAM_NAME " [-h] [-a ] [-n ] [-N ]\n" -++"\t\t\t[-s ] [-S ] [-t ] [-V] [-m]\n" -++"\t\t\t[--alignment=][--vol_id=] [--name=]\n" -++"\t\t\t[--size=] [--lebs=] [--type=] [--help]\n" -++"\t\t\t[--version] [--maxavsize]\n\n" -++"Example: " PROGRAM_NAME "/dev/ubi0 -s 20MiB -N config_data - create a 20 Megabytes volume\n" -++" named \"config_data\" on UBI device /dev/ubi0."; -++ -++static const struct option long_options[] = { -++ { .name = "alignment", .has_arg = 1, .flag = NULL, .val = 'a' }, -++ { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' }, -++ { .name = "name", .has_arg = 1, .flag = NULL, .val = 'N' }, -++ { .name = "size", .has_arg = 1, .flag = NULL, .val = 's' }, -++ { .name = "lebs", .has_arg = 1, .flag = NULL, .val = 'S' }, -++ { .name = "type", .has_arg = 1, .flag = NULL, .val = 't' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ { .name = "maxavsize", .has_arg = 0, .flag = NULL, .val = 'm' }, -++ /* Deprecated -d option */ -++ { .name = "devn", .has_arg = 1, .flag = NULL, .val = 'd' }, -++ { NULL, 0, NULL, 0}, -++}; -++ -++static int param_sanity_check(void) -++{ -++ int len; -++ -++ if (args.bytes == -1 && !args.maxavs && args.lebs == -1) -++ return errmsg("volume size was not specified (use -h for help)"); -++ -++ if ((args.bytes != -1 && (args.maxavs || args.lebs != -1)) || -++ (args.lebs != -1 && (args.maxavs || args.bytes != -1)) || -++ (args.maxavs && (args.bytes != -1 || args.lebs != -1))) -++ return errmsg("size specified with more then one option"); -++ -++ if (args.name == NULL) -++ return errmsg("volume name was not specified (use -h for help)"); -++ -++ len = strlen(args.name); -++ if (len > UBI_MAX_VOLUME_NAME) -++ return errmsg("too long name (%d symbols), max is %d", len, UBI_MAX_VOLUME_NAME); -++ -++ return 0; -++} -++ -++static int parse_opt(int argc, char * const argv[]) -++{ -++ while (1) { -++ int key; -++ char *endp; -++ -++ key = getopt_long(argc, argv, "a:n:N:s:S:t:h?Vmd:", long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ case 't': -++ if (!strcmp(optarg, "dynamic")) -++ args.vol_type = UBI_DYNAMIC_VOLUME; -++ else if (!strcmp(optarg, "static")) -++ args.vol_type = UBI_STATIC_VOLUME; -++ else -++ return errmsg("bad volume type: \"%s\"", optarg); -++ break; -++ -++ case 's': -++ args.bytes = ubiutils_get_bytes(optarg); -++ if (args.bytes <= 0) -++ return errmsg("bad volume size: \"%s\"", optarg); -++ break; -++ -++ case 'S': -++ args.lebs = strtoull(optarg, &endp, 0); -++ if (endp == optarg || args.lebs <= 0 || *endp != '\0') -++ return errmsg("bad LEB count: \"%s\"", optarg); -++ break; -++ -++ case 'a': -++ args.alignment = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.alignment <= 0) -++ return errmsg("bad volume alignment: \"%s\"", optarg); -++ break; -++ -++ case 'n': -++ args.vol_id = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.vol_id < 0) -++ return errmsg("bad volume ID: " "\"%s\"", optarg); -++ break; -++ -++ case 'd': -++ /* Handle deprecated -d option */ -++ warnmsg("-d is depricated and will be removed, do not use it"); -++ args.devn = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.devn < 0) -++ return errmsg("bad UBI device number: " "\"%s\"", optarg); -++ break; -++ -++ case 'N': -++ args.name = optarg; -++ args.nlen = strlen(args.name); -++ break; -++ -++ case 'h': -++ case '?': -++ fprintf(stderr, "%s\n\n", doc); -++ fprintf(stderr, "%s\n\n", usage); -++ fprintf(stderr, "%s\n", optionsstr); -++ exit(EXIT_SUCCESS); -++ -++ case 'V': -++ fprintf(stderr, "%s\n", PROGRAM_VERSION); -++ exit(EXIT_SUCCESS); -++ -++ case 'm': -++ args.maxavs = 1; -++ break; -++ -++ case ':': -++ return errmsg("parameter is missing"); -++ -++ default: -++ fprintf(stderr, "Use -h for help\n"); -++ return -1; -++ } -++ } -++ -++ /* Handle deprecated -d option */ -++ if (args.devn != -1) { -++ sprintf(args.dev_name, "/dev/ubi%d", args.devn); -++ args.node = args.dev_name; -++ } else { -++ if (optind == argc) -++ return errmsg("UBI device name was not specified (use -h for help)"); -++ else if (optind != argc - 1) -++ return errmsg("more then one UBI device specified (use -h for help)"); -++ -++ args.node = argv[optind]; -++ } -++ -++ if (param_sanity_check()) -++ return -1; -++ -++ return 0; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ int err; -++ libubi_t libubi; -++ struct ubi_dev_info dev_info; -++ struct ubi_vol_info vol_info; -++ struct ubi_mkvol_request req; -++ -++ err = parse_opt(argc, argv); -++ if (err) -++ return err; -++ -++ libubi = libubi_open(1); -++ if (!libubi) -++ return sys_errmsg("cannot open libubi"); -++ -++ err = ubi_node_type(libubi, args.node); -++ if (err == 2) { -++ errmsg("\"%s\" is an UBI volume node, not an UBI device node", -++ args.node); -++ goto out_libubi; -++ } else if (err < 0) { -++ errmsg("\"%s\" is not an UBI device node", args.node); -++ goto out_libubi; -++ } -++ -++ err = ubi_get_dev_info(libubi, args.node, &dev_info); -++ if (err) { -++ sys_errmsg("cannot get information about UBI device \"%s\"", -++ args.node); -++ goto out_libubi; -++ } -++ -++ if (args.maxavs) { -++ args.bytes = dev_info.avail_bytes; -++ printf("Set volume size to %lld\n", args.bytes); -++ } -++ -++ if (args.lebs != -1) { -++ args.bytes = dev_info.leb_size; -++ args.bytes -= dev_info.leb_size % args.alignment; -++ args.bytes *= args.lebs; -++ } -++ -++ req.vol_id = args.vol_id; -++ req.alignment = args.alignment; -++ req.bytes = args.bytes; -++ req.vol_type = args.vol_type; -++ req.name = args.name; -++ -++ err = ubi_mkvol(libubi, args.node, &req); -++ if (err < 0) { -++ sys_errmsg("cannot UBI create volume"); -++ goto out_libubi; -++ } -++ -++ args.vol_id = req.vol_id; -++ -++ /* Print information about the created device */ -++ err = ubi_get_vol_info1(libubi, dev_info.dev_num, args.vol_id, &vol_info); -++ if (err) { -++ sys_errmsg("cannot get information about newly created UBI volume"); -++ goto out_libubi; -++ } -++ -++ printf("Volume ID %d, size %d LEBs (", vol_info.vol_id, vol_info.rsvd_lebs); -++ ubiutils_print_bytes(vol_info.rsvd_bytes, 0); -++ printf("), LEB size "); -++ ubiutils_print_bytes(vol_info.leb_size, 1); -++ printf(", %s, name \"%s\", alignment %d\n", -++ req.vol_type == UBI_DYNAMIC_VOLUME ? "dynamic" : "static", -++ vol_info.name, vol_info.alignment); -++ -++ libubi_close(libubi); -++ return 0; -++ -++out_libubi: -++ libubi_close(libubi); -++ return -1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubinfo.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubinfo.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubinfo.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubinfo.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,409 @@ -++/* -++ * Copyright (C) 2007, 2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ */ -++ -++/* -++ * An utility to get UBI information. -++ * -++ * Author: Artem Bityutskiy -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include "common.h" -++ -++#define PROGRAM_VERSION "1.0" -++#define PROGRAM_NAME "ubinfo" -++ -++/* The variables below are set by command line arguments */ -++struct args { -++ int devn; -++ int vol_id; -++ int all; -++ const char *node; -++}; -++ -++static struct args args = { -++ .vol_id = -1, -++ .devn = -1, -++ .all = 0, -++ .node = NULL, -++}; -++ -++static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION -++ " - a tool to print UBI information."; -++ -++static const char *optionsstr = -++"-d, --devn= UBI device number to get information about\n" -++"-n, --vol_id= ID of UBI volume to print information about\n" -++"-a, --all print information about all devices and volumes,\n" -++" or about all volumes if the UBI device was\n" -++" specified\n" -++"-h, --help print help message\n" -++"-V, --version print program version"; -++ -++static const char *usage = -++"Usage 1: " PROGRAM_NAME " [-d ] [-n ] [-a] [-h] [-V] [--vol_id=]\n" -++"\t\t[--devn ] [--all] [--help] [--version]\n" -++"Usage 2: " PROGRAM_NAME " [-a] [-h] [-V] [--all] [--help] [--version]\n" -++"Usage 3: " PROGRAM_NAME " [-h] [-V] [--help] [--version]\n\n" -++"Example 1: " PROGRAM_NAME " - (no arguments) print general UBI information\n" -++"Example 2: " PROGRAM_NAME " -d 1 - print information about UBI device number 1\n" -++"Example 3: " PROGRAM_NAME " /dev/ubi0 -a - print information about all volumes of UBI\n" -++" device /dev/ubi0\n" -++"Example 4: " PROGRAM_NAME " /dev/ubi1_0 - print information about UBI volume /dev/ubi1_0\n" -++"Example 5: " PROGRAM_NAME " -a - print all information\n"; -++ -++static const struct option long_options[] = { -++ { .name = "devn", .has_arg = 1, .flag = NULL, .val = 'd' }, -++ { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' }, -++ { .name = "all", .has_arg = 0, .flag = NULL, .val = 'a' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ { NULL, 0, NULL, 0}, -++}; -++ -++static int parse_opt(int argc, char * const argv[]) -++{ -++ while (1) { -++ int key; -++ char *endp; -++ -++ key = getopt_long(argc, argv, "an:d:hV", long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ case 'a': -++ args.all = 1; -++ break; -++ -++ case 'n': -++ args.vol_id = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.vol_id < 0) -++ return errmsg("bad volume ID: " "\"%s\"", optarg); -++ break; -++ -++ case 'd': -++ args.devn = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.devn < 0) -++ return errmsg("bad UBI device number: \"%s\"", optarg); -++ -++ break; -++ -++ case 'h': -++ fprintf(stderr, "%s\n\n", doc); -++ fprintf(stderr, "%s\n\n", usage); -++ fprintf(stderr, "%s\n", optionsstr); -++ exit(EXIT_SUCCESS); -++ -++ case 'V': -++ fprintf(stderr, "%s\n", PROGRAM_VERSION); -++ exit(EXIT_SUCCESS); -++ -++ case ':': -++ return errmsg("parameter is missing"); -++ -++ default: -++ fprintf(stderr, "Use -h for help\n"); -++ return -1; -++ } -++ } -++ -++ if (optind == argc - 1) -++ args.node = argv[optind]; -++ else if (optind < argc) -++ return errmsg("more then one UBI devices specified (use -h for help)"); -++ -++ return 0; -++} -++ -++static int translate_dev(libubi_t libubi, const char *node) -++{ -++ int err; -++ -++ err = ubi_node_type(libubi, node); -++ if (err == -1) { -++ if (errno) -++ return errmsg("unrecognized device node \"%s\"", node); -++ return errmsg("\"%s\" does not correspond to any UBI device or volume", node); -++ } -++ -++ if (err == 1) { -++ struct ubi_dev_info dev_info; -++ -++ err = ubi_get_dev_info(libubi, node, &dev_info); -++ if (err) -++ return sys_errmsg("cannot get information about UBI device \"%s\"", node); -++ -++ args.devn = dev_info.dev_num; -++ } else { -++ struct ubi_vol_info vol_info; -++ -++ err = ubi_get_vol_info(libubi, node, &vol_info); -++ if (err) -++ return sys_errmsg("cannot get information about UBI volume \"%s\"", node); -++ -++ if (args.vol_id != -1) -++ return errmsg("both volume character device node (\"%s\") and " -++ "volume ID (%d) are specify, use only one of them" -++ "(use -h for help)", node, args.vol_id); -++ -++ args.devn = vol_info.dev_num; -++ args.vol_id = vol_info.vol_id; -++ } -++ -++ return 0; -++} -++ -++static int print_vol_info(libubi_t libubi, int dev_num, int vol_id) -++{ -++ int err; -++ struct ubi_vol_info vol_info; -++ -++ err = ubi_get_vol_info1(libubi, dev_num, vol_id, &vol_info); -++ if (err) -++ return sys_errmsg("cannot get information about UBI volume %d on ubi%d", -++ vol_id, dev_num); -++ -++ printf("Volume ID: %d (on ubi%d)\n", vol_info.vol_id, vol_info.dev_num); -++ printf("Type: %s\n", -++ vol_info.type == UBI_DYNAMIC_VOLUME ? "dynamic" : "static"); -++ printf("Alignment: %d\n", vol_info.alignment); -++ -++ printf("Size: %d LEBs (", vol_info.rsvd_lebs); -++ ubiutils_print_bytes(vol_info.rsvd_bytes, 0); -++ printf(")\n"); -++ -++ if (vol_info.type == UBI_STATIC_VOLUME) { -++ printf("Data bytes: "); -++ ubiutils_print_bytes(vol_info.data_bytes, 1); -++ } -++ printf("State: %s\n", vol_info.corrupted ? "corrupted" : "OK"); -++ printf("Name: %s\n", vol_info.name); -++ printf("Character device major/minor: %d:%d\n", -++ vol_info.major, vol_info.minor); -++ -++ return 0; -++} -++ -++static int print_dev_info(libubi_t libubi, int dev_num, int all) -++{ -++ int i, err, first = 1; -++ struct ubi_dev_info dev_info; -++ struct ubi_vol_info vol_info; -++ -++ err = ubi_get_dev_info1(libubi, dev_num, &dev_info); -++ if (err) -++ return sys_errmsg("cannot get information about UBI device %d", dev_num); -++ -++ printf("ubi%d:\n", dev_info.dev_num); -++ printf("Volumes count: %d\n", dev_info.vol_count); -++ printf("Logical eraseblock size: %d\n", dev_info.leb_size); -++ -++ printf("Total amount of logical eraseblocks: %d (", dev_info.total_lebs); -++ ubiutils_print_bytes(dev_info.total_bytes, 0); -++ printf(")\n"); -++ -++ printf("Amount of available logical eraseblocks: %d (", dev_info.avail_lebs); -++ ubiutils_print_bytes(dev_info.avail_bytes, 0); -++ printf(")\n"); -++ -++ printf("Maximum count of volumes %d\n", dev_info.max_vol_count); -++ printf("Count of bad physical eraseblocks: %d\n", dev_info.bad_count); -++ printf("Count of reserved physical eraseblocks: %d\n", dev_info.bad_rsvd); -++ printf("Current maximum erase counter value: %lld\n", dev_info.max_ec); -++ printf("Minimum input/output unit size: %d bytes\n", dev_info.min_io_size); -++ printf("Character device major/minor: %d:%d\n", -++ dev_info.major, dev_info.minor); -++ -++ if (dev_info.vol_count == 0) -++ return 0; -++ -++ printf("Present volumes: "); -++ for (i = dev_info.lowest_vol_num; -++ i <= dev_info.highest_vol_num; i++) { -++ err = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info); -++ if (err == -1) { -++ if (errno == ENOENT) -++ continue; -++ -++ return sys_errmsg("libubi failed to probe volume %d on ubi%d", -++ i, dev_info.dev_num); -++ } -++ -++ if (!first) -++ printf(", %d", i); -++ else { -++ printf("%d", i); -++ first = 0; -++ } -++ } -++ printf("\n"); -++ -++ if (!all) -++ return 0; -++ -++ first = 1; -++ printf("\n"); -++ -++ for (i = dev_info.lowest_vol_num; -++ i <= dev_info.highest_vol_num; i++) { -++ if(!first) -++ printf("-----------------------------------\n"); -++ err = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info); -++ if (err == -1) { -++ if (errno == ENOENT) -++ continue; -++ -++ return sys_errmsg("libubi failed to probe volume %d on ubi%d", -++ i, dev_info.dev_num); -++ } -++ first = 0; -++ -++ err = print_vol_info(libubi, dev_info.dev_num, i); -++ if (err) -++ return err; -++ } -++ -++ return 0; -++} -++ -++static int print_general_info(libubi_t libubi, int all) -++{ -++ int i, err, first = 1; -++ struct ubi_info ubi_info; -++ struct ubi_dev_info dev_info; -++ -++ err = ubi_get_info(libubi, &ubi_info); -++ if (err) -++ return sys_errmsg("cannot get UBI information"); -++ -++ printf("UBI version: %d\n", ubi_info.version); -++ printf("Count of UBI devices: %d\n", ubi_info.dev_count); -++ if (ubi_info.ctrl_major != -1) -++ printf("UBI control device major/minor: %d:%d\n", -++ ubi_info.ctrl_major, ubi_info.ctrl_minor); -++ else -++ printf("UBI control device is not supported by this kernel\n"); -++ -++ if (ubi_info.dev_count == 0) -++ return 0; -++ -++ printf("Present UBI devices: "); -++ for (i = ubi_info.lowest_dev_num; -++ i <= ubi_info.highest_dev_num; i++) { -++ err = ubi_get_dev_info1(libubi, i, &dev_info); -++ if (err == -1) { -++ if (errno == ENOENT) -++ continue; -++ -++ return sys_errmsg("libubi failed to probe UBI device %d", i); -++ } -++ -++ if (!first) -++ printf(", ubi%d", i); -++ else { -++ printf("ubi%d", i); -++ first = 0; -++ } -++ } -++ printf("\n"); -++ -++ if (!all) -++ return 0; -++ -++ first = 1; -++ printf("\n"); -++ -++ for (i = ubi_info.lowest_dev_num; -++ i <= ubi_info.highest_dev_num; i++) { -++ if(!first) -++ printf("\n===================================\n\n"); -++ err = ubi_get_dev_info1(libubi, i, &dev_info); -++ if (err == -1) { -++ if (errno == ENOENT) -++ continue; -++ -++ return sys_errmsg("libubi failed to probe UBI device %d", i); -++ } -++ first = 0; -++ -++ err = print_dev_info(libubi, i, all); -++ if (err) -++ return err; -++ } -++ return 0; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ int err; -++ libubi_t libubi; -++ -++ err = parse_opt(argc, argv); -++ if (err) -++ return -1; -++ -++ if (!args.node && args.devn != -1) -++ return errmsg("specify either device number or node file (use -h for help)"); -++ -++ libubi = libubi_open(1); -++ if (libubi == NULL) -++ return sys_errmsg("cannot open libubi"); -++ -++ if (args.node) { -++ /* -++ * A character device was specified, translate this into UBI -++ * device number and volume ID. -++ */ -++ err = translate_dev(libubi, args.node); -++ if (err) -++ goto out_libubi; -++ } -++ -++ if (args.vol_id != -1 && args.devn == -1) { -++ errmsg("volume ID is specified, but UBI device number is not " -++ "(use -h for help)\n"); -++ goto out_libubi; -++ } -++ -++ if (args.devn != -1 && args.vol_id != -1) { -++ print_vol_info(libubi, args.devn, args.vol_id); -++ goto out; -++ } -++ -++ if (args.devn == -1 && args.vol_id == -1) -++ err = print_general_info(libubi, args.all); -++ else if (args.devn != -1 && args.vol_id == -1) -++ err = print_dev_info(libubi, args.devn, args.all); -++ -++ if (err) -++ goto out_libubi; -++ -++out: -++ libubi_close(libubi); -++ return 0; -++ -++out_libubi: -++ libubi_close(libubi); -++ return -1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubinize.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubinize.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubinize.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubinize.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,582 @@ -++/* -++ * Copyright (C) 2008 Nokia Corporation -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * Generate UBI images. -++ * -++ * Authors: Artem Bityutskiy -++ * Oliver Lohmann -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include "common.h" -++ -++#define PROGRAM_VERSION "1.0" -++#define PROGRAM_NAME "ubinize" -++ -++static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION -++" - a tool to generate UBI images. An UBI image may contain one or more UBI " -++"volumes which have to be defined in the input configuration ini-file. The " -++"ini file defines all the UBI volumes - their characteristics and the and the " -++"contents, but it does not define the characteristics of the flash the UBI " -++"image is generated for. Instead, the flash characteristics are defined via " -++"the command-line options. Note, if not sure about some of the command-line " -++"parameters, do not specify them and let the utility to use default values."; -++ -++static const char *optionsstr = -++"-o, --output= output file name\n" -++"-p, --peb-size= size of the physical eraseblock of the flash\n" -++" this UBI image is created for in bytes,\n" -++" kilobytes (KiB), or megabytes (MiB)\n" -++" (mandatory parameter)\n" -++"-m, --min-io-size= minimum input/output unit size of the flash\n" -++" in bytes\n" -++"-s, --sub-page-size= minimum input/output unit used for UBI\n" -++" headers, e.g. sub-page size in case of NAND\n" -++" flash (equivalent to the minimum input/output\n" -++" unit size by default)\n" -++"-O, --vid-hdr-offset= offset if the VID header from start of the\n" -++" physical eraseblock (default is the next\n" -++" minimum I/O unit or sub-page after the EC\n" -++" header)\n" -++"-e, --erase-counter= the erase counter value to put to EC headers\n" -++" (default is 0)\n" -++"-x, --ubi-ver= UBI version number to put to EC headers\n" -++" (default is 1)\n" -++"-v, --verbose be verbose\n" -++"-h, --help print help message\n" -++"-V, --version print program version"; -++ -++static const char *usage = -++"Usage: " PROGRAM_NAME " [-o filename] [-h] [-V] [--output=] [--help]\n" -++"\t\t[--version] ini-file\n" -++"Example: " PROGRAM_NAME " -o ubi.img cfg.ini - create UBI image 'ubi.img' as\n" -++" described by configuration file 'cfg.ini'"; -++ -++static const char *ini_doc = "INI-file format.\n" -++"The input configuration ini-file describes all the volumes which have to\n" -++"be included to the output UBI image. Each volume is described in its own\n" -++"section which may be named arbitrarily. The section consists on\n" -++"\"key=value\" pairs, for example:\n\n" -++"[jffs2-volume]\n" -++"mode=ubi\n" -++"image=../jffs2.img\n" -++"vol_id=1\n" -++"vol_size=30MiB\n" -++"vol_type=dynamic\n" -++"vol_name=jffs2_volume\n" -++"vol_flags=autoresize\n" -++"vol_alignment=1\n\n" -++"This example configuration file tells the utility to create an UBI image\n" -++"with one volume with ID 1, volume size 30MiB, the volume is dynamic, has\n" -++"name \"jffs2_volume\", \"autoresize\" volume flag, and alignment 1. The\n" -++"\"image=../jffs2.img\" line tells the utility to take the contents of the\n" -++"volume from the \"../jffs2.img\" file. The size of the image file has to be\n" -++"less or equivalent to the volume size (30MiB). The \"mode=ubi\" line is\n" -++"mandatory and just tells that the section describes an UBI volume - other\n" -++"section modes may be added in the future.\n" -++"Notes:\n" -++" * size in vol_size might be specified kilobytes (KiB), megabytes (MiB),\n" -++" gigabytes (GiB) or bytes (no modifier);\n" -++" * if \"vol_size\" key is absent, the volume size is assumed to be\n" -++" equivalent to the size of the image file (defined by \"image\" key);\n" -++" * if the \"image\" is absent, the volume is assumed to be empty;\n" -++" * volume alignment must not be greater than the logical eraseblock size;\n" -++" * one ini file may contain arbitrary number of sections, the utility will\n" -++" put all the volumes which are described by these section to the output\n" -++" UBI image file."; -++ -++struct option long_options[] = { -++ { .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' }, -++ { .name = "peb-size", .has_arg = 1, .flag = NULL, .val = 'p' }, -++ { .name = "min-io-size", .has_arg = 1, .flag = NULL, .val = 'm' }, -++ { .name = "sub-page-size", .has_arg = 1, .flag = NULL, .val = 's' }, -++ { .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' }, -++ { .name = "erase-counter", .has_arg = 1, .flag = NULL, .val = 'e' }, -++ { .name = "ubi-ver", .has_arg = 1, .flag = NULL, .val = 'x' }, -++ { .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ { NULL, 0, NULL, 0} -++}; -++ -++struct args { -++ const char *f_in; -++ const char *f_out; -++ int out_fd; -++ int peb_size; -++ int min_io_size; -++ int subpage_size; -++ int vid_hdr_offs; -++ int ec; -++ int ubi_ver; -++ int verbose; -++ dictionary *dict; -++}; -++ -++static struct args args = { -++ .peb_size = -1, -++ .min_io_size = -1, -++ .subpage_size = -1, -++ .ubi_ver = 1, -++}; -++ -++static int parse_opt(int argc, char * const argv[]) -++{ -++ while (1) { -++ int key; -++ char *endp; -++ -++ key = getopt_long(argc, argv, "o:p:m:s:O:e:x:vhV", long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ case 'o': -++ args.out_fd = open(optarg, O_CREAT | O_TRUNC | O_WRONLY, -++ S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP | S_IROTH); -++ if (args.out_fd == -1) -++ return sys_errmsg("cannot open file \"%s\"", optarg); -++ args.f_out = optarg; -++ break; -++ -++ case 'p': -++ args.peb_size = ubiutils_get_bytes(optarg); -++ if (args.peb_size <= 0) -++ return errmsg("bad physical eraseblock size: \"%s\"", optarg); -++ break; -++ -++ case 'm': -++ args.min_io_size = ubiutils_get_bytes(optarg); -++ if (args.min_io_size <= 0) -++ return errmsg("bad min. I/O unit size: \"%s\"", optarg); -++ if (!is_power_of_2(args.min_io_size)) -++ return errmsg("min. I/O unit size should be power of 2"); -++ break; -++ -++ case 's': -++ args.subpage_size = ubiutils_get_bytes(optarg); -++ if (args.subpage_size <= 0) -++ return errmsg("bad sub-page size: \"%s\"", optarg); -++ if (!is_power_of_2(args.subpage_size)) -++ return errmsg("sub-page size should be power of 2"); -++ break; -++ -++ case 'O': -++ args.vid_hdr_offs = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.vid_hdr_offs < 0) -++ return errmsg("bad VID header offset: \"%s\"", optarg); -++ break; -++ -++ case 'e': -++ args.ec = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.ec < 0) -++ return errmsg("bad erase counter value: \"%s\"", optarg); -++ break; -++ -++ case 'x': -++ args.ubi_ver = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.ubi_ver < 0) -++ return errmsg("bad UBI version: \"%s\"", optarg); -++ break; -++ -++ case 'v': -++ args.verbose = 1; -++ break; -++ -++ case 'h': -++ ubiutils_print_text(stderr, doc, 80); -++ fprintf(stderr, "\n%s\n\n", ini_doc); -++ fprintf(stderr, "%s\n", usage); -++ fprintf(stderr, "%s\n", optionsstr); -++ exit(EXIT_SUCCESS); -++ -++ case 'V': -++ fprintf(stderr, "%s\n", PROGRAM_VERSION); -++ exit(EXIT_SUCCESS); -++ -++ default: -++ fprintf(stderr, "Use -h for help\n"); -++ return -1; -++ } -++ } -++ -++ if (optind == argc) -++ return errmsg("input configuration file was not specified (use -h for help)"); -++ -++ if (optind != argc - 1) -++ return errmsg("more then one configuration file was specified (use -h for help)"); -++ -++ args.f_in = argv[optind]; -++ -++ if (args.peb_size < 0) -++ return errmsg("physical eraseblock size was not specified (use -h for help)"); -++ -++ if (args.peb_size > 1024*1024) -++ return errmsg("too high physical eraseblock size %d", args.peb_size); -++ -++ if (args.min_io_size < 0) -++ return errmsg("min. I/O unit size was not specified (use -h for help)"); -++ -++ if (args.subpage_size < 0) -++ args.subpage_size = args.min_io_size; -++ -++ if (args.subpage_size > args.min_io_size) -++ return errmsg("sub-page cannot be larger then min. I/O unit"); -++ -++ if (args.peb_size % args.min_io_size) -++ return errmsg("physical eraseblock should be multiple of min. I/O units"); -++ -++ if (args.min_io_size % args.subpage_size) -++ return errmsg("min. I/O unit size should be multiple of sub-page size"); -++ -++ if (!args.f_out) -++ return errmsg("output file was not specified (use -h for help)"); -++ -++ if (args.vid_hdr_offs) { -++ if (args.vid_hdr_offs + UBI_VID_HDR_SIZE >= args.peb_size) -++ return errmsg("bad VID header position"); -++ if (args.vid_hdr_offs % 8) -++ return errmsg("VID header offset has to be multiple of min. I/O unit size"); -++ } -++ -++ return 0; -++} -++ -++static int read_section(const char *sname, struct ubigen_vol_info *vi, -++ const char **img) -++{ -++ char buf[256]; -++ const char *p; -++ -++ *img = NULL; -++ -++ if (strlen(sname) > 128) -++ return errmsg("too long section name \"%s\"", sname); -++ -++ /* Make sure mode is UBI, otherwise ignore this section */ -++ sprintf(buf, "%s:mode", sname); -++ p = iniparser_getstring(args.dict, buf, NULL); -++ if (!p) { -++ errmsg("\"mode\" key not found in section \"%s\"", sname); -++ errmsg("the \"mode\" key is mandatory and has to be " -++ "\"mode=ubi\" if the section describes an UBI volume"); -++ return -1; -++ } -++ -++ /* If mode is not UBI, skip this section */ -++ if (strcmp(p, "ubi")) { -++ verbose(args.verbose, "skip non-ubi section \"%s\"", sname); -++ return 1; -++ } -++ -++ verbose(args.verbose, "mode=ubi, keep parsing"); -++ -++ /* Fetch the name of the volume image file */ -++ sprintf(buf, "%s:image", sname); -++ p = iniparser_getstring(args.dict, buf, NULL); -++ if (p) -++ *img = p; -++ -++ /* Fetch volume id */ -++ sprintf(buf, "%s:vol_id", sname); -++ vi->id = iniparser_getint(args.dict, buf, -1); -++ if (vi->id == -1) -++ return errmsg("\"vol_id\" key not found in section \"%s\"", sname); -++ -++ if (vi->id < 0) -++ return errmsg("negative volume ID %d", vi->id); -++ -++ if (vi->id >= UBI_MAX_VOLUMES) -++ return errmsg("too high volume ID %d, max. is %d", vi->id, UBI_MAX_VOLUMES); -++ -++ verbose(args.verbose, "volume ID: %d", vi->id); -++ -++ /* Fetch volume size */ -++ sprintf(buf, "%s:vol_size", sname); -++ p = iniparser_getstring(args.dict, buf, NULL); -++ if (p) { -++ vi->bytes = ubiutils_get_bytes(p); -++ if (vi->bytes <= 0) -++ return errmsg("bad \"vol_size\" key: \"%s\"", p); -++ -++ verbose(args.verbose, "volume size: %lld bytes", vi->bytes); -++ } else { -++ struct stat st; -++ -++ if (!*img) -++ return errmsg("neither image file (\"image=\") nor volume size (\"vol_size=\") specified"); -++ -++ if (stat(*img, &st)) -++ return sys_errmsg("cannot stat \"%s\"", *img); -++ -++ vi->bytes = st.st_size; -++ -++ if (vi->bytes == 0) -++ return errmsg("file \"%s\" referred from section \"%s\" is empty", *img, sname); -++ -++ normsg_cont("volume size was not specified in section \"%s\", assume ", sname); -++ ubiutils_print_bytes(vi->bytes, 1); -++ printf("\n"); -++ } -++ -++ /* Fetch volume type */ -++ sprintf(buf, "%s:vol_type", sname); -++ p = iniparser_getstring(args.dict, buf, NULL); -++ if (!p) { -++ normsg("volume type was not specified in " -++ "section \"%s\", assume \"dynamic\"\n", sname); -++ vi->type = UBI_VID_DYNAMIC; -++ } else { -++ if (!strcmp(p, "static")) -++ vi->type = UBI_VID_STATIC; -++ else if (!strcmp(p, "dynamic")) -++ vi->type = UBI_VID_DYNAMIC; -++ else -++ return errmsg("invalid volume type \"%s\"", p); -++ } -++ -++ verbose(args.verbose, "volume type: %s", -++ vi->type == UBI_VID_DYNAMIC ? "dynamic" : "static"); -++ -++ /* Fetch volume name */ -++ sprintf(buf, "%s:vol_name", sname); -++ p = iniparser_getstring(args.dict, buf, NULL); -++ if (!p) -++ return errmsg("\"vol_name\" key not found in section \"%s\"", sname); -++ -++ vi->name = p; -++ vi->name_len = strlen(p); -++ if (vi->name_len > UBI_VOL_NAME_MAX) -++ return errmsg("too long volume name in section \"%s\", max. is %d characters", -++ vi->name, UBI_VOL_NAME_MAX); -++ -++ verbose(args.verbose, "volume name: %s", p); -++ -++ /* Fetch volume alignment */ -++ sprintf(buf, "%s:vol_alignment", sname); -++ vi->alignment = iniparser_getint(args.dict, buf, -1); -++ if (vi->alignment == -1) { -++ normsg("volume alignment was not specified in section " -++ "\"%s\", assume 1", sname); -++ vi->alignment = 1; -++ } else if (vi->id < 0) -++ return errmsg("negative volume alignement %d", vi->alignment); -++ -++ verbose(args.verbose, "volume alignment: %d", vi->alignment); -++ -++ /* Fetch volume flags */ -++ sprintf(buf, "%s:vol_flags", sname); -++ p = iniparser_getstring(args.dict, buf, NULL); -++ if (p) { -++ if (!strcmp(p, "autoresize")) { -++ verbose(args.verbose, "autoresize flags found"); -++ vi->flags |= UBI_VTBL_AUTORESIZE_FLG; -++ } else { -++ return errmsg("unknown flags \"%s\" in section \"%s\"", p, sname); -++ } -++ } -++ -++ return 0; -++} -++ -++static void init_vol_info(const struct ubigen_info *ui, -++ struct ubigen_vol_info *vi) -++{ -++ vi->data_pad = ui->leb_size % vi->alignment; -++ vi->usable_leb_size = ui->leb_size - vi->data_pad; -++ vi->used_ebs = (vi->bytes + vi->usable_leb_size - 1) / vi->usable_leb_size; -++ vi->compat = 0; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ int err = -1, sects, i, volumes, autoresize_was_already = 0; -++ struct ubigen_info ui; -++ struct ubi_vtbl_record *vtbl; -++ off_t seek; -++ int tmp; -++ -++ err = parse_opt(argc, argv); -++ if (err) -++ return -1; -++ -++ ubigen_info_init(&ui, args.peb_size, args.min_io_size, -++ args.subpage_size, args.vid_hdr_offs, -++ args.ubi_ver); -++ -++ verbose(args.verbose, "LEB size: %d", ui.leb_size); -++ verbose(args.verbose, "PEB size: %d", ui.peb_size); -++ verbose(args.verbose, "min. I/O size: %d", ui.min_io_size); -++ verbose(args.verbose, "sub-page size: %d", ui.min_io_size); -++ verbose(args.verbose, "VID offset: %d", ui.vid_hdr_offs); -++ verbose(args.verbose, "data offset: %d", ui.data_offs); -++ -++ vtbl = ubigen_create_empty_vtbl(&ui); -++ if (!vtbl) -++ goto out; -++ -++ args.dict = iniparser_load(args.f_in); -++ if (!args.dict) { -++ errmsg("cannot load the input ini file \"%s\"", args.f_in); -++ goto out_vtbl; -++ } -++ -++ verbose(args.verbose, "loaded the ini-file \"%s\"", args.f_in); -++ -++ /* Each section describes one volume */ -++ sects = iniparser_getnsec(args.dict); -++ if (sects == -1) { -++ errmsg("ini-file parsing error (iniparser_getnsec)"); -++ goto out_dict; -++ } -++ -++ verbose(args.verbose, "count of sections: %d", sects); -++ if (sects == 0) { -++ errmsg("no sections found the ini-file \"%s\"", args.f_in); -++ goto out_dict; -++ } -++ -++ /* -++ * Skip 2 PEBs at the beginning of the file for the volume table which -++ * will be written later. -++ */ -++ seek = ui.peb_size * 2; -++ if (lseek(args.out_fd, seek, SEEK_SET) != seek) { -++ sys_errmsg("cannot seek file \"%s\"", args.f_out); -++ goto out_dict; -++ } -++ -++ for (i = 0; i < sects; i++) { -++ const char *sname = iniparser_getsecname(args.dict, i); -++ struct ubigen_vol_info vi; -++ const char *img = NULL; -++ struct stat st; -++ int fd; -++ -++ if (!sname) { -++ errmsg("ini-file parsing error (iniparser_getsecname)"); -++ goto out_dict; -++ } -++ -++ if (args.verbose) -++ printf("\n"); -++ verbose(args.verbose, "parsing section \"%s\"", sname); -++ -++ err = read_section(sname, &vi, &img); -++ if (err == -1) -++ goto out_dict; -++ if (!err) -++ volumes += 1; -++ init_vol_info(&ui, &vi); -++ -++ if (vi.id >= ui.max_volumes) -++ return errmsg("too high volume ID %d, max. is %d", -++ vi.id, ui.max_volumes); -++ -++ verbose(args.verbose, "adding volume %d", vi.id); -++ -++ /* Make sure only one volume has auto-resize flag */ -++ if (vi.flags & UBI_VTBL_AUTORESIZE_FLG) { -++ if (autoresize_was_already) -++ return errmsg("only one volume is allowed " -++ "to have auto-resize flag"); -++ autoresize_was_already = 1; -++ } -++ -++ err = ubigen_add_volume(&ui, &vi, vtbl); -++ if (err) { -++ errmsg("cannot add volume for section \"%s\"", sname); -++ goto out_dict; -++ } -++ -++ if (!img) -++ continue; -++ -++ if (stat(img, &st)) { -++ sys_errmsg("cannot stat \"%s\"", img); -++ goto out_dict; -++ } -++ -++ /* -++ * Make sure the image size is not larger then the volume size. -++ */ -++ tmp = (st.st_size / (ui.leb_size + sizeof(unsigned int))) * sizeof(unsigned int); -++ if (st.st_size - tmp> vi.bytes) { -++ errmsg("error in section \"%s\": size of the image file \"%s\" " -++ "is %lld, which is larger then the volume size %lld", -++ sname, img, (long long)st.st_size, vi.bytes); -++ goto out_dict; -++ } -++ -++ fd = open(img, O_RDONLY); -++ if (fd == -1) { -++ sys_errmsg("cannot open \"%s\"", img); -++ goto out_dict; -++ } -++ -++ verbose(args.verbose, "writing volume %d", vi.id); -++ verbose(args.verbose, "image file: %s", img); -++ -++ err = ubigen_write_volume(&ui, &vi, args.ec, st.st_size-tmp, fd, args.out_fd); -++ close(fd); -++ if (err) { -++ errmsg("cannot write volume for section \"%s\"", sname); -++ goto out_dict; -++ } -++ -++ if (args.verbose) -++ printf("\n"); -++ } -++ -++ verbose(args.verbose, "writing layout volume"); -++ -++ err = ubigen_write_layout_vol(&ui, 0, 1, args.ec, args.ec, vtbl, args.out_fd); -++ if (err) { -++ errmsg("cannot write layout volume"); -++ goto out_dict; -++ } -++ -++ verbose(args.verbose, "done"); -++ -++ iniparser_freedict(args.dict); -++ free(vtbl); -++ close(args.out_fd); -++ return 0; -++ -++out_dict: -++ iniparser_freedict(args.dict); -++out_vtbl: -++ free(vtbl); -++out: -++ close(args.out_fd); -++ remove(args.f_out); -++ return err; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubirefimg.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubirefimg.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubirefimg.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubirefimg.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,99 @@ -++/* -++ * An utility to reformat the image file generated by mkfs.ubifs -++ * -++ * Authors: Yurong Tan (Nancy) -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++ -++#define PROGRAM_VERSION "1.1" -++#define PROGRAM_NAME "ubirefimg" -++#define UBI_LEB_SIZE 258048 -++ -++/* -++ * sourcefile usually generated by mkfs.ubifs. -++ * usage: #ubirefimg sourcefile outputfile -++ */ -++int main(int argc, char * const argv[]) -++{ -++ int err, ifd, ofd, i, j, tmp; -++ struct stat st; -++ unsigned char *buf=NULL; -++ -++ buf = malloc(UBI_LEB_SIZE); -++ if(buf==NULL){ -++ printf("no mem\n"); -++ goto out_free; -++ } -++ -++ err = stat(argv[1], &st); -++ if (err < 0) { -++ printf("stat failed on \"%s\"", argv[1]); -++ goto out_free; -++ } -++ -++ ifd = open(argv[1], O_RDONLY); -++ if (ifd == -1) { -++ printf("cannot open \"%s\"", argv[1]); -++ goto out_close; -++ } -++ -++ ofd = open(argv[2], O_WRONLY | O_TRUNC | O_CREAT, 0644); -++ if (ofd == -1) { -++ printf("cannot create \"%s\"", argv[2]); -++ goto out_close; -++ } -++ -++ tmp = st.st_size/UBI_LEB_SIZE; -++ -++ for( i=0; i< tmp; i++ ){ -++ err = read(ifd, buf, UBI_LEB_SIZE); -++ if (err != UBI_LEB_SIZE) { -++ printf("read error\n"); -++ goto out_close1; -++ } -++ for(j=0; j -++ * Frank Haverkamp -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include "common.h" -++ -++#define PROGRAM_VERSION "1.0" -++#define PROGRAM_NAME "ubirmvol" -++ -++/* The variables below are set by command line arguments */ -++struct args { -++ int vol_id; -++ const char *node; -++ /* For deprecated -d option handling */ -++ int devn; -++ char dev_name[256]; -++}; -++ -++static struct args args = { -++ .vol_id = -1, -++ .devn = -1, -++}; -++ -++static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION -++ " - a tool to remove UBI volumes."; -++ -++static const char *optionsstr = -++"-n, --vol_id= volume ID to remove\n" -++"-h, -?, --help print help message\n" -++"-V, --version print program version\n\n" -++"The following is a compatibility option which is deprecated, do not use it\n" -++"-d, --devn= UBI device number - may be used instead of the UBI\n" -++" device node name in which case the utility assumes\n" -++" that the device node is \"/dev/ubi\""; -++ -++static const char *usage = -++"Usage: " PROGRAM_NAME " [-n ] [--vol_id=] [-h] [--help]\n\n" -++"Example: " PROGRAM_NAME "/dev/ubi0 -n 1 - remove UBI volume 1 from UBI device corresponding\n" -++" to the node file /dev/ubi0."; -++ -++static const struct option long_options[] = { -++ { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ /* Deprecated -d option */ -++ { .name = "devn", .has_arg = 1, .flag = NULL, .val = 'd' }, -++ { NULL, 0, NULL, 0}, -++}; -++ -++static int param_sanity_check(void) -++{ -++ if (args.vol_id == -1) { -++ errmsg("volume ID is was not specified"); -++ return -1; -++ } -++ -++ return 0; -++} -++ -++static int parse_opt(int argc, char * const argv[]) -++{ -++ while (1) { -++ int key; -++ char *endp; -++ -++ key = getopt_long(argc, argv, "n:h?Vd:", long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ -++ case 'n': -++ args.vol_id = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.vol_id < 0) { -++ errmsg("bad volume ID: " "\"%s\"", optarg); -++ return -1; -++ } -++ break; -++ -++ case 'h': -++ case '?': -++ fprintf(stderr, "%s\n\n", doc); -++ fprintf(stderr, "%s\n\n", usage); -++ fprintf(stderr, "%s\n", optionsstr); -++ exit(EXIT_SUCCESS); -++ -++ case 'd': -++ /* Handle deprecated -d option */ -++ warnmsg("-d is depricated and will be removed, do not use it"); -++ args.devn = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.devn < 0) -++ return errmsg("bad UBI device number: " "\"%s\"", optarg); -++ break; -++ -++ case 'V': -++ fprintf(stderr, "%s\n", PROGRAM_VERSION); -++ exit(EXIT_SUCCESS); -++ -++ case ':': -++ errmsg("parameter is missing"); -++ return -1; -++ -++ default: -++ fprintf(stderr, "Use -h for help\n"); -++ return -1; -++ } -++ } -++ -++ /* Handle deprecated -d option */ -++ if (args.devn != -1) { -++ sprintf(args.dev_name, "/dev/ubi%d", args.devn); -++ args.node = args.dev_name; -++ } else { -++ if (optind == argc) { -++ errmsg("UBI device name was not specified (use -h for help)"); -++ return -1; -++ } else if (optind != argc - 1) { -++ errmsg("more then one UBI device specified (use -h for help)"); -++ return -1; -++ } -++ -++ args.node = argv[optind]; -++ } -++ -++ -++ if (param_sanity_check()) -++ return -1; -++ -++ return 0; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ int err; -++ libubi_t libubi; -++ -++ err = parse_opt(argc, argv); -++ if (err) -++ return -1; -++ -++ libubi = libubi_open(1); -++ if (libubi == NULL) -++ return sys_errmsg("cannot open libubi"); -++ -++ err = ubi_node_type(libubi, args.node); -++ if (err == 2) { -++ errmsg("\"%s\" is an UBI volume node, not an UBI device node", -++ args.node); -++ goto out_libubi; -++ } else if (err < 0) { -++ errmsg("\"%s\" is not an UBI device node", args.node); -++ goto out_libubi; -++ } -++ -++ err = ubi_rmvol(libubi, args.node, args.vol_id); -++ if (err) { -++ sys_errmsg("cannot UBI remove volume"); -++ goto out_libubi; -++ } -++ -++ libubi_close(libubi); -++ return 0; -++ -++out_libubi: -++ libubi_close(libubi); -++ return -1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubiupdatevol.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubiupdatevol.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubiupdatevol.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/new-utils/src/ubiupdatevol.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,335 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * An utility to update UBI volumes. -++ * -++ * Authors: Frank Haverkamp -++ * Joshua W. Boyer -++ * Artem Bityutskiy -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include "common.h" -++ -++#define PROGRAM_VERSION "1.1" -++#define PROGRAM_NAME "ubiupdatevol" -++ -++struct args { -++ int truncate; -++ const char *node; -++ const char *img; -++ /* For deprecated -d and -B options handling */ -++ int devn; -++ char dev_name[256]; -++ int broken_update; -++}; -++ -++static struct args args = { -++ .devn = -1, -++}; -++ -++static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION -++ " - a tool to write data to UBI volumes."; -++ -++static const char *optionsstr = -++"-n, --vol_id= ID of UBI volume to update\n" -++"-t, --truncate truncate volume (wipe it out)\n" -++"-h, --help print help message\n" -++"-V, --version print program version\n\n" -++"The following are compatibility options which are deprecated, do not use them\n" -++"-d, --devn= UBI device number - may be used instead of the UBI\n" -++" device node name in which case the utility assumes\n" -++" that the device node is \"/dev/ubi\"\n" -++"-B, --broken-update broken update, this is for testing"; -++ -++static const char *usage = -++"Usage: " PROGRAM_NAME " [-t] [-h] [-V] [--truncate] [--help]\n" -++"\t\t\t[--version] \n\n" -++"Example 1: " PROGRAM_NAME " /dev/ubi0_1 fs.img - write file \"fs.img\" to UBI volume /dev/ubi0_1\n" -++"Example 2: " PROGRAM_NAME " /dev/ubi0_1 -t - wipe out UBI volume /dev/ubi0_1"; -++ -++struct option long_options[] = { -++ { .name = "truncate", .has_arg = 0, .flag = NULL, .val = 't' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ /* Deprecated -d and -B options */ -++ { .name = "devn", .has_arg = 1, .flag = NULL, .val = 'd' }, -++ { .name = "broken-update", .has_arg = 1, .flag = NULL, .val = 'B' }, -++ { NULL, 0, NULL, 0} -++}; -++ -++static int parse_opt(int argc, char * const argv[]) -++{ -++ while (1) { -++ int key; -++ -++ key = getopt_long(argc, argv, "n:th?Vd:", long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ case 't': -++ args.truncate = 1; -++ break; -++ -++ case 'h': -++ case '?': -++ fprintf(stderr, "%s\n\n", doc); -++ fprintf(stderr, "%s\n\n", usage); -++ fprintf(stderr, "%s\n", optionsstr); -++ exit(EXIT_SUCCESS); -++ -++ case 'd': -++ { -++ char *endp; -++ -++ /* Handle deprecated -d option */ -++ warnmsg("-d is depricated and will be removed, do not use it"); -++ args.devn = strtoul(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || args.devn < 0) -++ return errmsg("bad UBI device number: " "\"%s\"", optarg); -++ break; -++ } -++ -++ case 'B': -++ /* Handle deprecated -B option */ -++ warnmsg("-B is depricated and will be removed, do not use it"); -++ args.broken_update = 1; -++ break; -++ -++ case 'V': -++ fprintf(stderr, "%s\n", PROGRAM_VERSION); -++ exit(EXIT_SUCCESS); -++ -++ case ':': -++ return errmsg("parameter is missing"); -++ -++ default: -++ fprintf(stderr, "Use -h for help\n"); -++ return -1; -++ } -++ } -++ -++ /* Handle deprecated -d option */ -++ if (args.devn != -1) { -++ sprintf(args.dev_name, "/dev/ubi%d", args.devn); -++ args.node = args.dev_name; -++ } else { -++ if (optind == argc) -++ return errmsg("UBI device name was not specified (use -h for help)"); -++ else if (optind != argc - 2 && !args.truncate) -++ return errmsg("specify UBI device name and image file name as first 2 " -++ "parameters (use -h for help)"); -++ } -++ -++ args.node = argv[optind]; -++ args.img = argv[optind + 1]; -++ -++ return 0; -++} -++ -++static int truncate_volume(libubi_t libubi) -++{ -++ int err, fd; -++ -++ fd = open(args.node, O_RDWR); -++ if (fd == -1) -++ return sys_errmsg("cannot open \"%s\"", args.node); -++ -++ err = ubi_update_start(libubi, fd, 0); -++ if (err) { -++ sys_errmsg("cannot truncate volume \"%s\"", args.node); -++ close(fd); -++ return -1; -++ } -++ -++ close(fd); -++ return 0; -++} -++ -++static int ubi_write(int fd, const void *buf, int len) -++{ -++ int ret; -++ -++ while (len) { -++ ret = write(fd, buf, len); -++ if (ret < 0) { -++ if (errno == EINTR) { -++ warnmsg("do not interrupt me!"); -++ continue; -++ } -++ return sys_errmsg("cannot write %d bytes to volume \"%s\"", -++ len, args.node); -++ } -++ -++ if (ret == 0) -++ return errmsg("cannot write %d bytes to volume \"%s\"", len, args.node); -++ -++ len -= ret; -++ buf += ret; -++ } -++ -++ return 0; -++} -++ -++static int update_volume(libubi_t libubi, struct ubi_vol_info *vol_info) -++{ -++ int err, fd, ifd; -++ long long bytes, tmp; -++ struct stat st; -++ char *buf; -++ -++ buf = malloc(vol_info->leb_size+sizeof(unsigned int)); -++ if (!buf) -++ return errmsg("cannot allocate %d bytes of memory", vol_info->leb_size); -++ -++ err = stat(args.img, &st); -++ if (err < 0) { -++ errmsg("stat failed on \"%s\"", args.img); -++ goto out_free; -++ } -++ -++ bytes = st.st_size; -++ tmp = bytes / (vol_info->leb_size + sizeof(unsigned int)) * sizeof(unsigned int); -++ bytes -= tmp; -++ if (bytes > vol_info->rsvd_bytes ) { -++ errmsg("\"%s\" (size %lld) will not fit volume \"%s\" (size %lld)", -++ args.img, bytes, args.node, vol_info->rsvd_bytes); -++ goto out_free; -++ } -++ -++ /* A hack to handle deprecated -B option */ -++ if (args.broken_update) -++ bytes = 1; -++ -++ fd = open(args.node, O_RDWR); -++ if (fd == -1) { -++ sys_errmsg("cannot open UBI volume \"%s\"", args.node); -++ goto out_free; -++ } -++ -++ ifd = open(args.img, O_RDONLY); -++ if (ifd == -1) { -++ sys_errmsg("cannot open \"%s\"", args.img); -++ goto out_close1; -++ } -++ -++ err = ubi_update_start(libubi, fd, bytes); -++ if (err) { -++ sys_errmsg("cannot start volume \"%s\" update", args.node); -++ goto out_close; -++ } -++ -++ bytes += tmp; -++ while (bytes) { -++ int tocopy = vol_info->leb_size + sizeof(unsigned int) ; -++ -++ if (tocopy > bytes) -++ tocopy = bytes; -++ -++ err = read(ifd, buf, tocopy); -++ if (err != tocopy) { -++ if (errno == EINTR) { -++ warnmsg("do not interrupt me!"); -++ continue; -++ } else { -++ sys_errmsg("cannot read %d bytes from \"%s\"", -++ tocopy, args.img); -++ goto out_close; -++ } -++ } -++ -++ err = ubi_write(fd, buf, tocopy-sizeof(unsigned int)); -++ if (err) -++ goto out_close; -++ -++ bytes -= tocopy; -++ } -++ -++ close(ifd); -++ close(fd); -++ free(buf); -++ return 0; -++ -++out_close: -++ close(ifd); -++out_close1: -++ close(fd); -++out_free: -++ free(buf); -++ return -1; -++} -++ -++int main(int argc, char * const argv[]) -++{ -++ int err; -++ libubi_t libubi; -++ struct ubi_vol_info vol_info; -++ -++ err = parse_opt(argc, argv); -++ if (err) -++ return -1; -++ -++ libubi = libubi_open(1); -++ if (libubi == NULL) { -++ sys_errmsg("cannot open libubi"); -++ goto out_libubi; -++ } -++ -++ err = ubi_node_type(libubi, args.node); -++ if (err == 1) { -++ errmsg("\"%s\" is an UBI device node, not an UBI volume node", -++ args.node); -++ goto out_libubi; -++ } else if (err < 0) { -++ errmsg("\"%s\" is not an UBI volume node", args.node); -++ goto out_libubi; -++ } -++ -++ err = ubi_get_vol_info(libubi, args.node, &vol_info); -++ if (err) { -++ sys_errmsg("cannot get information about UBI volume \"%s\"", -++ args.node); -++ goto out_libubi; -++ } -++ -++ if (args.truncate) -++ err = truncate_volume(libubi); -++ else -++ err = update_volume(libubi, &vol_info); -++ if (err) -++ goto out_libubi; -++ -++ libubi_close(libubi); -++ return 0; -++ -++out_libubi: -++ libubi_close(libubi); -++ return -1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/perl/f128_nand_sample.cfg linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/perl/f128_nand_sample.cfg -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/perl/f128_nand_sample.cfg 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/perl/f128_nand_sample.cfg 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,38 @@ -++[targets] -++complete=ipl,spl,bootenv,kernel,rootfs -++bootcode=spl,bootenv -++ -++# Build sections -++[ipl] -++image=ipl.bin -++raw_starts=0x00000000 -++raw_total_size=128kiB -++ -++[spl] -++image=u-boot.bin -++ubi_ids=2,3 -++ubi_size=2MiB -++ubi_type=static -++ubi_names=spl_0,spl_1 -++ -++[bootenv] -++bootenv_file=bootenv_complete.txt -++ubi_ids=4,5 -++ubi_size=128kiB -++ubi_type=static -++ubi_names=bootenv_0,bootenv_1 -++ -++[kernel] -++image=vmlinux.bin -++ubi_ids=6,7 -++ubi_size=6MiB -++ubi_type=static -++ubi_names=kernel_0,kernel_1 -++ -++[rootfs] -++image=rootfs.bin -++ubi_ids=8,9 -++ubi_alignment=2kiB -++ubi_size=16MiB -++ubi_type=dynamic -++ubi_names=rootfs_0,rootfs_1 -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/perl/f64_nor_sample.cfg linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/perl/f64_nor_sample.cfg -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/perl/f64_nor_sample.cfg 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/perl/f64_nor_sample.cfg 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,39 @@ -++[targets] -++complete=ipl,spl,bootenv,kernel,rootfs -++bootcode=spl,bootenv -++rootfs=rootfs -++ -++# Build sections -++[ipl] -++image=ipl.bin -++raw_starts=0x02FE0000, 0x03FE0000 -++raw_total_size=128kiB -++ -++[spl] -++image=u-boot.bin -++ubi_ids=2,3 -++ubi_size=2MiB -++ubi_type=static -++ubi_names=spl_0,spl_1 -++ -++[bootenv] -++bootenv_file=bootenv_complete.txt -++ubi_ids=4,5 -++ubi_size=128kiB -++ubi_type=static -++ubi_names=bootenv_0,bootenv_1 -++ -++[kernel] -++image=vmlinux.bin -++ubi_ids=6,7 -++ubi_size=6MiB -++ubi_type=static -++ubi_names=kernel_0,kernel_1 -++ -++[rootfs] -++image=rootfs.bin -++ubi_ids=8,9 -++ubi_alignment=2kiB -++ubi_size=16128kiB -++ubi_type=dynamic -++ubi_names=rootfs_0,rootfs_1 -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/perl/mkpfi linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/perl/mkpfi -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/perl/mkpfi 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/perl/mkpfi 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,723 @@ -++#!/usr/bin/perl -++# -++# Copyright (c) International Business Machines Corp., 2006 -++# -++# This program is free software; you can redistribute it and/or modify -++# it under the terms of the GNU General Public License as published by -++# the Free Software Foundation; either version 2 of the License, or -++# (at your option) any later version. -++# -++# This program is distributed in the hope that it will be useful, -++# but WITHOUT ANY WARRANTY; without even the implied warranty of -++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++# the GNU General Public License for more details. -++# -++# You should have received a copy of the GNU General Public License -++# along with this program; if not, write to the Free Software -++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++# -++ -++# -++# mkpfi -++# -++# This perl program is assembles PFI files from a config file. -++# -++# Author: Oliver Lohmann (oliloh@de.ibm.com) -++# -++use warnings; -++use strict; -++use lib "/usr/lib/perl5"; # Please change this path as you need it, or -++ # make a proposal how this could be done -++ # nicer. -++use Getopt::Long; -++use Pod::Usage; -++use Config::IniFiles; -++use File::Temp; -++ -++# ---------------------------------------------------------------------------- -++# Versions -++our $version : unique = "0.1"; -++our $pfi_version : unique = "0x1"; -++ -++# ---------------------------------------------------------------------------- -++# Globals -++my $verbose = 0; -++my $cfg; -++ -++my %opts = (); -++my %files = (config => ""); -++my @tmp_files; -++ -++my %tools = (ubicrc32 => "ubicrc32"); -++ -++# ---------------------------------------------------------------------------- -++# Processing the input sections -++# -++# The idea is to combine each section entry with a function -++# in order to allow some kind of preprocessing for the values -++# before they are written into the PFI file. -++# This is especially useful to be more verbose and -++# user-friendly in the layout file. -++# -++# All key-function hashes are applied after the general -++# validation of the configuration file. -++# If any mandatory key is missing in a section the user -++# will be informed and the PFI creation process is aborted. -++# -++# Default keys will be checked for their presence inside the config -++# file. If they are missing, they will be generated with appr. values. -++ -++# Mandatory keys for UBI volumes. -++my %ubi_keys = ("ubi_ids" => \&check_id_list, -++ "ubi_size" => \&replace_num, -++ "ubi_type" => \&replace_type, -++ "ubi_names" => \&remove_spaces, -++ "ubi_alignment" => \&replace_num); -++ -++# Mandatory keys for RAW sections. -++my %raw_keys = ("raw_starts" => \&expand_starts, -++ "raw_total_size" => \&replace_num); -++ -++# Common default keys for documentation and control purposes. -++my %common_keys = ("flags" => \&replace_num, -++ "label" => \&do_nothing); -++ -++# Define any defaults here. Values which maintained in this default -++# region need not to be specified by the user explicitly. -++my %def_ubi_keys = ("ubi_alignment" => [\&set_default, "0x1"]); -++my %def_raw_keys = (); -++my %def_common_keys = ("flags" => [\&set_default, "0x0"], -++ "label" => [\&generate_label, ""]); -++ -++# ---------------------------------------------------------------------------- -++# Input keys, actually the path to the input data. -++ -++my %input_keys = ("image" => \&do_nothing); -++ -++# Placeholder keys allow the replacement via a special -++# purpose function. E.g. the bootenv_file key will be used -++# to generate bootenv binary data from an text file and -++# replace the bootenv_file key with an image key to handle it -++# in the same way in the further creation process. -++my %input_placeholder_keys = ("bootenv_file" => \&create_bootenv_image); -++ -++# ---------------------------------------------------------------------------- -++# Helper -++ -++# @brief Get current time string. -++sub get_date { -++ my $tmp = scalar localtime; -++ $tmp =~ s/ /_/g; -++ return $tmp; -++} -++ -++# @brief Print an info message to stdout. -++sub INFO($) { -++ my $str = shift; -++ -++ if (!$verbose) { -++ return; -++ } -++ -++ print STDOUT $str; -++} -++ -++# @brief Print an error message to stderr. -++sub ERR($) { -++ my $str = shift; -++ print STDERR $str; -++} -++ -++# @brief Print a warning message to stderr. -++sub WARN($) { -++ my $str = shift; -++ print STDERR $str; -++} -++ -++sub parse_command_line($) { -++ my $opt = shift; -++ my $result = GetOptions( "help" => \$$opt{'help'}, -++ "man" => \$$opt{'man'}, -++ "config=s" => \$$opt{'config'}, -++ "verbose" => \$$opt{'verbose'}, -++ ) or pod2usage(2); -++ pod2usage(1) if defined ($$opt{help}); -++ pod2usage(-verbose => 2) if defined ($$opt{man}); -++ -++ $verbose = $$opt{verbose} if defined $$opt{verbose}; -++ -++ if (!defined $$opt{config}) { -++ ERR("[ ERROR: No config file specified. Aborting...\n"); -++ exit 1; -++ } -++ -++} -++ -++# @brief Check if all needed tools are in PATH. -++sub check_tools { -++ my $err = 0; -++ my $key; -++ -++ foreach $key (keys %tools) { -++ if (`which $tools{$key}` eq "") { -++ ERR("\n") if ($err == 0); -++ ERR("! Please add the tool \'$tools{$key}\' " . -++ "to your path!\n"); -++ $err = 1; -++ } -++ } -++ die "[ ERROR: Did not find all needed tools!\n" if $err; -++} -++ -++sub open_cfg_file($) { -++ my $fname = shift; -++ my $res = new Config::IniFiles( -file => $fname ); -++ -++ die "[ ERROR: Cannot load your config file!\n" if (!defined $res); -++ return $res; -++} -++ -++sub set_default($$$$) { -++ my ($cfg, $section, $parameter, $def_value) = @_; -++ $cfg->newval($section, $parameter, $def_value); -++ return; -++} -++ -++sub generate_label($$$$) { -++ my ($cfg, $section, $parameter, $def_value) = @_; -++ my $new_label = $def_value . $section; -++ $new_label .= "_" . get_date; -++ $cfg->newval($section, $parameter, $new_label); -++ return; -++} -++ -++# @brief Converts any num to a unified hex string, i.e the resulting value -++# always starts with "0x" and is aligned to 8 hexdigits. -++# @return Returns 0 on success, otherwise an error occured. -++# -++sub any_num_to_hex($$) { -++ my $val = shift; -++ my $res = shift; -++ -++ # M(iB) -++ if ($val =~ m/([0-9]+)[Mm][i]?[Bb]?/g) { -++ $$res = sprintf("0x%08x", $1 * 1024 * 1024); -++ } -++ # k(iB) -++ elsif ($val =~ m/([0-9]+)[kK][i]?[Bb]?/g) { -++ $$res = sprintf("0x%08x", $1 * 1024); -++ } -++ # hex -++ elsif ($val =~ m/0x?([0-9a-fA-F]+)/g) { -++ $$res = sprintf("0x%08x", hex $1); -++ } -++ # decimal -++ elsif ($val =~ m/^([0-9]+)$/g) { -++ $$res = sprintf("0x%08x", $1); -++ } -++ else { -++ $$res = ""; -++ return -1; -++ } -++ -++ return 0; -++} -++ -++sub remove_spaces($$$) { -++ my ($cfg, $section, $parameter) = @_; -++ my ($start, @starts, @new_starts); -++ my $val = $cfg->val($section, $parameter); -++ my $res; -++ -++ $val =~ s/ //g; # spaces -++ $cfg->newval($section, $parameter, $val); -++} -++ -++sub expand_starts($$$) { -++ my ($cfg, $section, $parameter) = @_; -++ my ($start, @starts, @new_starts); -++ my $val = $cfg->val($section, $parameter); -++ my $res; -++ -++ $val =~ s/ //g; # spaces -++ @starts = split(/,/, $val); -++ -++ foreach $start (@starts) { -++ if (any_num_to_hex($start, \$res) != 0) { -++ ERR("[ ERROR: [$section]\n"); -++ ERR("[ Expecting a list of numeric " . -++ "values for parameter: $parameter\n"); -++ exit 1; -++ } -++ push (@new_starts, $res); -++ } -++ $res = join(',', @starts); -++ -++ $cfg->newval($section, $parameter, $res); -++} -++ -++sub check_id_list($$$) { -++ my ($cfg, $section, $parameter) = @_; -++ my $val = $cfg->val($section, $parameter); -++ my $res; -++ -++ if (!($val =~ m/^[0-9]+[,0-9]*/)) { -++ ERR("[ ERROR: Syntax error in 'ubi_ids' in " . -++ "section '$section': $val\n"); -++ ERR("[ Aborting... "); -++ exit 1; -++ } -++} -++ -++sub replace_type($$$) { -++ my ($cfg, $section, $parameter) = @_; -++ my $val = $cfg->val($section, $parameter); -++ my $res; -++ -++ $res = lc($val); -++ grep {$res eq $_} ('static', 'dynamic') -++ or die "[ ERROR: Unknown UBI Volume Type in " . -++ "section '$section': $val\n"; -++ -++ $cfg->newval($section, $parameter, $res); -++} -++ -++ -++sub replace_num($$$) { -++ my ($cfg, $section, $parameter) = @_; -++ my $val = $cfg->val($section, $parameter); -++ my $res = ""; -++ -++ if (any_num_to_hex($val, \$res) != 0) { -++ ERR("[ ERROR: [$section]\n"); -++ ERR("[ Expecting a numeric value " . -++ "for parameter: $parameter\n"); -++ exit 1; -++ } -++ $cfg->newval($section, $parameter, $res); -++} -++ -++sub do_nothing($$$) { -++ my ($cfg, $section, $parameter) = @_; -++ return; -++} -++ -++sub bootenv_sanity_check($) { -++ my $env = shift; # hash array containing bootenv -++ my %pdd = (); -++ -++ defined($$env{'pdd'}) or return "'pdd' not defined"; -++ foreach (split /,/, $$env{'pdd'}) { -++ defined($$env{$_}) or return "undefined '$_' in pdd"; -++ $pdd{$_} = 1; -++ } -++ -++ defined $$env{'pdd_preserve'} or -++ return ""; -++ foreach (split /,/, $$env{'pdd_preserve'}) { -++ defined($pdd{$_}) -++ or return "pdd_preserve field '$_' not in pdd"; -++ } -++ return ""; -++} -++ -++sub create_bootenv_image($$$) { -++ my ($cfg, $section, $parameter) = @_; -++ my $txt_fn = $cfg->val($section, "bootenv_file"); -++ my $in; -++ -++ my %value = (); -++ my @key = (); -++ -++ open $in, "<", $txt_fn -++ or die "[ ERROR: can't open bootenv file '$txt_fn'.\n"; -++ while (<$in>) { -++ next if (/^\s*(\#.*)?$/); # Skip comments/whitespace. -++ -++ if (/^(\S+?)\+\=(.*)$/) { -++ defined($value{$1}) or -++ die "$txt_fn:$.: error: appending to" . -++ " non-existent '$1'\n"; -++ $value{$1} .= $2; -++ } elsif (/^(\S+?)\=(.*)$/) { -++ not defined($value{$1}) or -++ die "$txt_fn:$.: error: trying to" . -++ " redefine '$1'\n"; -++ push @key, $1; -++ $value{$1} = $2; -++ } else { -++ die "$txt_fn:$.: error: unrecognized syntax\n"; -++ } -++ } -++ close $in; -++ -++ $_ = &bootenv_sanity_check(\%value) -++ and die "$txt_fn: error: $_\n"; -++ -++ my $tmp_file = new File::Temp(); -++ push (@tmp_files, $tmp_file); -++ -++ foreach (@key) { -++ print $tmp_file "$_=", $value{$_}, "\0"; -++ } -++ close $tmp_file; -++ -++ $cfg->newval($section, "image", $tmp_file-> filename); -++} -++ -++sub process_keys($$$) { -++ my ($cfg, $section, $keys) = @_; -++ my @parameters = $cfg->Parameters($section); -++ my $i; -++ -++ for ($i = 0 ; $i < scalar(@parameters) ; $i++ ) { -++ if (defined($$keys{$parameters[$i]})) { -++ $$keys{$parameters[$i]}->($cfg, $section, -++ $parameters[$i]); -++ } -++ } -++ -++} -++ -++sub is_in_keylist($$) { -++ my ($key, $keys) = @_; -++ my $i; -++ -++ for ($i = 0; $i < scalar(@$keys); $i++) { -++ if ($$keys[$i] eq $key) { -++ return 1; -++ } -++ } -++ -++ return 0; -++} -++ -++sub check_default_keys($$$) { -++ my ($cfg, $section, $keys) = @_; -++ my @parameters = $cfg->Parameters($section); -++ my $key; -++ -++ foreach $key (keys %$keys) { -++ if (!is_in_keylist($key, \@parameters)) { -++ $$keys{$key}[0]-> -++ ($cfg, $section, $key, $$keys{$key}[1]); -++ } -++ } -++ -++} -++ -++ -++ -++sub check_keys($$$) { -++ my ($cfg, $section, $keys) = @_; -++ my @parameters = $cfg->Parameters($section); -++ my ($i, $key, $err); -++ -++ $err = 0; -++ for ($i = 0 ; $i < scalar(@$keys) ; $i++ ) { -++ if (!is_in_keylist($$keys[$i], \@parameters)) { -++ ERR("[ ERROR: [$section]\n") if $err == 0; -++ $err = 1; -++ ERR("[ Missing key '$$keys[$i]'\n"); -++ } -++ } -++ -++ if ($err) { -++ ERR("[ Aborting...\n"); -++ exit 1; -++ } -++} -++ -++sub push_pfi_data($$$$$) { -++ my ($cfg, $section, $pfi_infos, $keys, $mode) = @_; -++ my ($tmp, $i, $hdr); -++ -++ my %pfi_info = (); -++ $pfi_info{'mode'} = $mode; -++ $pfi_info{'image'} = $cfg->val($section, "image"); -++ -++ # Build the PFI header -++ $hdr = sprintf("PFI!\n"); -++ $hdr .= sprintf("version=0x%08x\n", hex $pfi_version); -++ $hdr .= sprintf("mode=$mode\n"); -++ -++ # calculate the size of the binary data part -++ $tmp = -s $cfg->val($section, "image"); -++ if (!defined $tmp) { -++ ERR("[ ERROR: [$section]\n"); -++ ERR("[ Missing input image: " -++ . $cfg->val($section, "image") . "\n"); -++ exit 1; -++ } -++ # Check for the image to fit into the given space -++ my $quota; -++ if ($mode eq 'raw') { -++ $quota = oct $cfg->val($section, "raw_total_size"); -++ } elsif ($mode eq 'ubi') { -++ $quota = oct $cfg->val($section, "ubi_size"); -++ } -++ $tmp <= $quota -++ or die "[ERROR: image file too big: " . -++ $cfg->val($section, "image") . "\n"; -++ $pfi_info{'size'} = $tmp; -++ -++ $hdr .= sprintf("size=0x%08x\n", $tmp); -++ -++ my $img_file = $cfg->val($section, "image"); -++ my $crc32 = `$tools{'ubicrc32'} $img_file 2>&1`; -++ if (any_num_to_hex($crc32, \$tmp) != 0) { -++ die "[ ERROR: $tools{'ubicrc32'} returned with errors"; -++ } -++ $hdr .= sprintf("crc=$tmp\n"); -++ -++ -++ # Process all remaining keys -++ for ($i = 0; $i < scalar (@$keys); $i++) { -++ if ($$keys[$i] eq "image") { # special case image input file -++ if (! -e ($tmp = $cfg->val($section, "image"))) { -++ ERR("[ ERROR: [$section]\n"); -++ ERR("[ Cannot find input file $tmp\n"); -++ exit 1; -++ } -++ next; -++ } -++ $hdr .= sprintf("%s=%s\n", $$keys[$i], -++ $cfg->val($section, $$keys[$i])); -++ } -++ -++ $hdr .= sprintf("\n"); # end marker for PFI-header -++ -++ $pfi_info{'header'} = $hdr; -++ -++ # store in the header list -++ push @$pfi_infos, \%pfi_info; -++} -++ -++sub process_section($$$$$$) { -++ my ($cfg, $section, $pfi_infos, $custom_keys, -++ $def_custom_keys, $mode) = @_; -++ my @keys = (keys %common_keys, keys %$custom_keys); -++ my @complete_keys = (@keys, keys %input_keys); -++ -++ # set defaults if necessary -++ check_default_keys($cfg, $section, $def_custom_keys); -++ check_default_keys($cfg, $section, \%def_common_keys); -++ -++ # check for placeholders... -++ process_keys($cfg, $section, \%input_placeholder_keys); -++ -++ # VALIDATE layout.cfg entries -++ check_keys($cfg, $section, \@complete_keys); -++ -++ # execute linked functions (if any) -++ process_keys($cfg, $section, \%common_keys); -++ process_keys($cfg, $section, $custom_keys); -++ -++ push_pfi_data($cfg, $section, $pfi_infos, \@keys, $mode); -++} -++ -++sub get_section_info($$) { -++ my ($cfg, $section) = @_; -++ my @parameters = $cfg->Parameters($section); -++ my ($ubi, $raw, $i, @res); -++ -++ $ubi = $raw = 0; -++ for ($i = 0 ; $i < scalar(@parameters) ; $i++ ) { -++ if ($parameters[$i] =~ m/ubi_/gi) { -++ $ubi = 1; -++ @res = (\%ubi_keys, \%def_ubi_keys, "ubi"); -++ } -++ if ($parameters[$i] =~ m/raw_/gi) { -++ $raw = 1; -++ @res = (\%raw_keys, \%def_raw_keys, "raw"); -++ } -++ } -++ -++ if (($ubi + $raw) != 1) { # double definition in section -++ ERR("[ ERROR: Layout error in section '$section'\n"); -++ exit 1; -++ } -++ -++ return @res; -++} -++ -++sub mk_target_list($$) { -++ my $val = shift; -++ my $tmp = shift; -++ my $complete = 0; -++ -++ if ($val =~ m/\((.*)\)/g) { -++ $val = $1; -++ $complete = 1; -++ } -++ $val =~ s/ //g; # spaces -++ -++ @$tmp = split(/,/, $val); -++ -++ return $complete; -++} -++ -++sub copy_bytes($$$) { -++ my ($in, $out, $to_copy) = @_; -++ -++ while ($to_copy) { -++ my $buf; -++ my $bufsize = 1024*1024; -++ -++ $bufsize < $to_copy or $bufsize = $to_copy; -++ read($in, $buf, $bufsize) == $bufsize -++ or die "[ ERROR: Image file shrunk during operation\n"; -++ print $out $buf; -++ $to_copy -= $bufsize; -++ } -++} -++ -++sub write_target($$) { -++ my ($pfi_infos, $target) = @_; -++ my ($pfi_info); -++ -++ INFO("[ Writting target pfi file: '$target.pfi'...\n"); -++ if (-e "$target.pfi") { -++ WARN("! Replaced old pfi...\n"); -++ `rm -f $target.pfi`; -++ } -++ open(FILE, ">", "$target.pfi") -++ or die "[ ERROR: Cannot create output file: $target.pfi\n"; -++ binmode(FILE); -++ -++ # @FIXME sort by mode (first raw, then ubi) -++ # Currently this ordering is based on a string comparism. :-) -++ @$pfi_infos = sort {(lc $$a{'mode'}) cmp (lc $$b{'mode'})} @$pfi_infos; -++ -++ # Print all headers first -++ foreach $pfi_info (@$pfi_infos) { -++ print FILE $$pfi_info{'header'}; -++ -++ } -++ # Print the linked data sections -++ print FILE "DATA\n"; -++ foreach $pfi_info (@$pfi_infos) { -++ open(IMAGE, "<", $$pfi_info{'image'}) -++ or die "[ ERROR: Cannot open input image: " . -++ "$$pfi_info{'image'}" . "\n"; -++ binmode(IMAGE); -++ ©_bytes(\*IMAGE, \*FILE, $$pfi_info{'size'}); -++ close(IMAGE) or die "[ ERROR: Cannot close input image: " . -++ "$$pfi_info{'image'}" . "\n"; -++ } -++ close(FILE) or die "[ ERROR: Cannot close output file: $target.pfi\n"; -++} -++ -++sub process_config($) { -++ my $cfg = shift; -++ my @sections = $cfg->Sections; -++ my ($i, $j, $keylist, $def_keylist, $mode, $tmp, -++ @tlist, $complete,@pfi_infos); -++ -++ my @parameters = $cfg->Parameters("targets") or -++ die "[ ERROR: Config file has no 'targets' section!\n"; -++ -++ for ($i = 0 ; $i < scalar(@parameters) ; $i++ ) { -++ INFO("[ Processing target '$parameters[$i]'...\n"); -++ @pfi_infos = (); -++ -++ # get a list of subtargets -++ $complete = mk_target_list($cfg->val("targets", -++ $parameters[$i]), \@tlist); -++ # build all subtargets -++ for ($j = 0 ; $j < scalar(@tlist) ; $j++ ) { -++ ($keylist, $def_keylist, $mode) -++ = get_section_info($cfg, $tlist[$j]); -++ process_section($cfg, $tlist[$j], -++ \@pfi_infos, -++ $keylist, $def_keylist, $mode); -++ } -++ -++ write_target(\@pfi_infos, $parameters[$i]); -++ } -++ -++ INFO("[ Success.\n"); -++ -++ -++} -++ -++sub clear_files() { -++ # @FIXME: -++ # Works implicitly and Fedora seems to have removed -++ # the cleanup call. Thus for now, inactive. -++ # File::Temp::cleanup(); -++} -++ -++require 5.008_000; # Tested with version 5.8.0. -++select STDOUT; $| = 1; # make STDOUT output unbuffered -++select STDERR; $| = 1; # make STDERR output unbuffered -++ -++parse_command_line(\%opts); -++check_tools; -++$cfg = open_cfg_file($opts{config}); -++process_config($cfg); -++clear_files; -++ -++__END__ -++ -++ -++=head1 NAME -++ -++mkpfi - Using GetOpt::Long, Pod::Usage, Config::IniFiles -++ -++ -++=head1 SYNOPSIS -++ -++mkpfi [OPTIONS ...] -++ -++ -++ OPTION -++ -++ [--config] [--help] [--man] -++ -++ -++=head1 ABSTRACT -++ -++Perl script for generating pdd pfi files from given config files. -++ -++=head1 OPTIONS -++ -++=over -++ -++=item B<--help> -++ -++Print out brief help message. -++ -++=item B<--usage> -++ -++Print usage. -++ -++=item B<--config> -++ -++Config input file. -++ -++=item B<--man> -++ -++Print manual page, same as 'perldoc mkpfi'. -++ -++=item B<--verbose> -++ -++Be verbose! -++ -++=back -++ -++=head1 BUGS -++ -++Report via MTD mailing list -++ -++ -++=head1 SEE ALSO -++ -++http://www.linux-mtd.infradead.org/ -++ -++ -++=head1 AUTHOR -++ -++Oliver Lohmann (oliloh@de.ibm.com) -++ -++=cut -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/perl/ubicrc32.pl linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/perl/ubicrc32.pl -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/perl/ubicrc32.pl 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/perl/ubicrc32.pl 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,74 @@ -++#!/usr/bin/perl -w -++ -++# Subroutine crc32(): Calculates the CRC on a given string. -++ -++{ -++ my @table = (); -++ -++ # @brief Calculate CRC32 for a given string. -++ sub crc32 -++ { -++ unless (@table) { -++ # Initialize the CRC table -++ my $poly = 0xEDB88320; -++ @table = (); -++ -++ for my $i (0..255) { -++ my $c = $i; -++ -++ for my $j (0..7) { -++ $c = ($c & 1) ? (($c >> 1) ^ $poly) : ($c >> 1); -++ } -++ $table[$i] = $c; -++ } -++ } -++ my $s = shift; # string to calculate the CRC for -++ my $crc = shift; # CRC start value -++ -++ defined($crc) -++ or $crc = 0xffffffff; # Default CRC start value -++ -++ for (my $i = 0; $i < length($s); $i++) { -++ $crc = $table[($crc ^ ord(substr($s, $i, 1))) & 0xff] -++ ^ ($crc >> 8); -++ } -++ return $crc; -++ } -++} -++ -++sub crc32_on_file -++{ -++ my $file = shift; -++ -++ my $crc32 = crc32(''); -++ my $buf = ''; -++ my $ret = 0; -++ -++ while ($ret = read($file, $buf, 8192)) { -++ $crc32 = crc32($buf, $crc32); -++ } -++ defined($ret) -++ or return undef; -++ printf("0x%x\n", $crc32); -++} -++ -++ -++# Main routine: Calculate the CRCs on the given files and print the -++# results. -++ -++{ -++ if (@ARGV) { -++ while (my $path = shift) { -++ my $file; -++ open $file, "<", $path -++ or die "Error opening '$path'.\n"; -++ -++ &crc32_on_file($file) -++ or die "Error reading from '$path'.\n"; -++ close $file; -++ } -++ } else { -++ &crc32_on_file(\*STDIN) -++ or die "Error reading from stdin.\n"; -++ } -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/Makefile linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/Makefile -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,75 @@ -++# -++# Makefile -++# -++# Testcase for UBI pfi update. -++# -++# Author: Frank Haverkamp -++# -++ -++card = test -++mkpfi_cfg = test.cfg -++ -++# -++# Some default values you might want to overwrite. Try it if you need -++# it and add more if needed. Note that no real sanity checking is done -++# on those values. If you do it wrong your card has no valid PDD data. -++# -++ -++PATH := $(PATH):/opt/ppc/usr/bin:../perl:.. -++ -++dd = dd -++sed = sed -++bin2nand = bin2nand -++ubigen = ubigen -++mkpfi = mkpfi -v -++pfi2bin = pfi2bin -v -++ -++vmlinux_bin ?= test_vmlinux.bin -++rootfs_bin ?= test_rootfs.bin -++spl_bin ?= test_u-boot.bin -++pdd_txt ?= pdd.txt -++ -++flashtype ?= nand -++pagesize ?= 2048 -++ -++compl ?= $(card)_complete -++compl_pfi ?= $(compl).pfi -++compl_img ?= $(compl).img -++ -++compl_nand2048_mif=$(compl).$(flashtype)$(pagesize).mif -++compl_nand2048_img=$(compl).$(flashtype)$(pagesize).img -++ -++all: $(compl_pfi) $(compl_nand2048_mif) -++ -++$(compl_pfi): $(vmlinux_bin) $(rootfs_bin) $(spl_bin) -++ $(mkpfi) -c $(mkpfi_cfg) -++ -++# Binary data and out of band data (OOB) -++# -++$(compl_nand2048_mif): $(compl_img) -++ $(bin2nand) -p $(pagesize) -o $(compl_nand2048_mif) $< -++ -++# Binary data only -++# -++$(compl_img): $(compl_pfi) -++ $(pfi2bin) -j $(pdd_txt) -o $@ $< -++ -++# -++# Default data -++# -++# If the binary data is not available in the current working directory -++# we try to create symlinks to our test data. -++# -++$(vmlinux_bin) $(rootfs_bin) $(spl_bin): -++ @echo -++ @echo "No $@ found, will use defaults !" -++ @echo -++ @echo "OR press CTRL-C to provide your own $@" && \ -++ sleep 1 && \ -++ $(dd) if=/dev/urandom of=$@ bs=1M count=1 -++ -++clean: -++ $(RM) *.pfi *~ -++ -++distclean: clean -++ $(RM) *.bin *.mif *.oob *.img -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/README linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/README -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/README 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/README 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,11 @@ -++README -++====== -++ -++This procedure creates a test pfi which should be flashed to our -++system with pfiflash. The testcase should read the data back and -++compare with the original. -++ -++We should try not forget to run these tests before we release -++a new version of UBI. -++ -++Frank -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/TODO linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/TODO -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/TODO 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/TODO 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,5 @@ -++TODO -++==== -++ -++ * Range checking is broken, reserving 2M and offering 3M binary data -++ ... works!? No! -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/bin2nand2bin_test.sh linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/bin2nand2bin_test.sh -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/bin2nand2bin_test.sh 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/bin2nand2bin_test.sh 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,184 @@ -++#!/bin/sh -++# -++# Testcase for nand2bin and bin2nand. Generate testdata and inject -++# biterrors. Convert data back and compare with original data. -++# -++# Conversion: -++# bin -> bin2nand -> mif -> nand2bin -> img -++# -++ -++inject_biterror=./scripts/inject_biterror.pl -++ -++pagesize=2048 -++oobsize=64 -++ -++# Create test data -++dd if=/dev/urandom of=testblock.bin bs=131072 count=1 -++ -++echo "Test conversion without bitflips ..." -++ -++echo -n "Convert bin to mif ... " -++bin2nand --pagesize=${pagesize} -o testblock.mif testblock.bin -++if [ $? -ne "0" ]; then -++ echo "failed!" -++ exit 1 -++else -++ echo "ok" -++fi -++ -++echo -n "Convert mif to bin ... " -++nand2bin --pagesize=${pagesize} -o testblock.img testblock.mif -++if [ $? -ne "0" ]; then -++ echo "failed!" -++ exit 1 -++else -++ echo "ok" -++fi -++ -++echo -n "Comparing data ... " -++diff testblock.bin testblock.img -++if [ $? -ne "0" ]; then -++ echo "failed!" -++ exit 1 -++else -++ echo "ok" -++fi -++ -++echo "Test conversion with uncorrectable ECC erors ..." -++echo -n "Inject biterror at offset $ioffs ... " -++${inject_biterror} --offset=0 --bitmask=0x81 \ -++ --input=testblock.mif \ -++ --output=testblock_bitflip.mif -++if [ $? -ne "0" ]; then -++ echo "failed!" -++ exit 1 -++else -++ echo "ok" -++fi -++ -++echo "Convert mif to bin ... " -++rm testblock.img -++nand2bin --correct-ecc --pagesize=${pagesize} -o testblock.img \ -++ testblock_bitflip.mif -++if [ $? -ne "0" ]; then -++ echo "failed!" -++ exit 1 -++else -++ echo "ok" -++fi -++ -++echo -n "Comparing data, must fail due to uncorrectable ECC ... " -++diff testblock.bin testblock.img -++if [ $? -ne "0" ]; then -++ echo "ok" # Must fail! -++else -++ echo "failed!" -++ exit 1 -++fi -++ -++echo "Test bitflips in data ... " -++for offs in `seq 0 255` ; do -++ -++ cp testblock.mif testblock_bitflip.mif -++ -++ for xoffs in 0 256 512 768 ; do -++ let ioffs=$offs+$xoffs -++ -++ cp testblock_bitflip.mif testblock_bitflip_tmp.mif -++ echo -n "Inject biterror at offset $ioffs ... " -++ ${inject_biterror} --offset=${ioffs} --bitmask=0x01 \ -++ --input=testblock_bitflip_tmp.mif \ -++ --output=testblock_bitflip.mif -++ if [ $? -ne "0" ]; then -++ echo "failed!" -++ exit 1 -++ else -++ echo "ok" -++ fi -++ done -++ -++ echo "Convert mif to bin ... " -++ rm testblock.img -++ nand2bin --correct-ecc --pagesize=${pagesize} -o testblock.img \ -++ testblock_bitflip.mif -++ if [ $? -ne "0" ]; then -++ echo "failed!" -++ exit 1 -++ else -++ echo "ok" -++ fi -++ -++ echo -n "Comparing data ... " -++ diff testblock.bin testblock.img -++ if [ $? -ne "0" ]; then -++ hexdump testblock.bin > testblock.bin.txt -++ hexdump testblock.img > testblock.img.txt -++ echo "Use tkdiff testblock.bin.txt testblock.img.txt to compare" -++ echo "failed!" -++ exit 1 -++ else -++ echo "ok" -++ fi -++ -++ # Without correction -++ echo "Convert mif to bin ... " -++ rm testblock.img -++ nand2bin --pagesize=${pagesize} -o testblock.img \ -++ testblock_bitflip.mif -++ if [ $? -ne "0" ]; then -++ echo "failed!" -++ exit 1 -++ else -++ echo "ok" -++ fi -++ -++ echo -n "Comparing data must differ, correction is disabled ... " -++ diff testblock.bin testblock.img -++ if [ $? -ne "0" ]; then -++ echo "ok" # must fail -++ else -++ echo "failed!" -++ exit 1 -++ fi -++done -++ -++echo "Test bitflips in OOB data ... " -++for offs in `seq 0 $oobsize` ; do -++ -++ let ioffs=$pagesize+$offs -++ -++ echo -n "Inject biterror at offset $ioffs ... " -++ ${inject_biterror} --offset=${ioffs} --bitmask=0x01 \ -++ --input=testblock.mif \ -++ --output=testblock_bitflip.mif -++ if [ $? -ne "0" ]; then -++ echo "failed!" -++ exit 1 -++ else -++ echo "ok" -++ fi -++ -++ echo "Convert mif to bin ... " -++ rm testblock.img -++ nand2bin --correct-ecc --pagesize=${pagesize} -o testblock.img \ -++ testblock_bitflip.mif -++ if [ $? -ne "0" ]; then -++ echo "failed!" -++ exit 1 -++ else -++ echo "ok" -++ fi -++ -++ echo -n "Comparing data ... " -++ diff testblock.bin testblock.img -++ if [ $? -ne "0" ]; then -++ hexdump testblock.bin > testblock.bin.txt -++ hexdump testblock.img > testblock.img.txt -++ echo "Use tkdiff testblock.bin.txt testblock.img.txt to compare" -++ echo "failed!" -++ exit 1 -++ else -++ echo "ok" -++ fi -++done -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/inject_biterror.pl linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/inject_biterror.pl -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/inject_biterror.pl 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/inject_biterror.pl 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,94 @@ -++#!/usr/bin/perl -w -++# -++# 2007 Frank Haverkamp -++# -++# Program for bit-error injection. I am sure that perl experts do it -++# in 1 line. Please let me know how it is done right ;-). -++# -++ -++use strict; -++use warnings; -++use Getopt::Long; -++use Pod::Usage; -++ -++my $i; -++my $help; -++my $result; -++my $offset = 0; -++my $bitmask = 0x01; -++my $in = "input.mif"; -++my $out = "output.mif"; -++ -++$result = GetOptions ("offset=i" => \$offset, # numeric -++ "bitmask=o" => \$bitmask, # numeric -++ "input=s" => \$in, # string -++ "output=s" => \$out, # string -++ "help|?" => \$help) or pod2usage(2); -++ -++pod2usage(1) if $help; -++ -++my $buf; -++ -++open(my $in_fh, "<", $in) -++ or die "Cannot open file $in: $!"; -++binmode $in_fh; -++ -++open(my $out_fh, ">", $out) or -++ die "Cannot open file $out: $!"; -++binmode $out_fh; -++ -++$i = 0; -++while (sysread($in_fh, $buf, 1)) { -++ -++ $buf = pack('C', unpack('C', $buf) ^ $bitmask) if ($i == $offset); -++ syswrite($out_fh, $buf, 1) or -++ die "Cannot write to offset $offset: $!"; -++ $i++; -++} -++ -++close $in_fh; -++close $out_fh; -++ -++__END__ -++ -++=head1 NAME -++ -++inject_biterrors.pl -++ -++=head1 SYNOPSIS -++ -++inject_biterror.pl [options] -++ -++=head1 OPTIONS -++ -++=over 8 -++ -++=item B<--help> -++ -++Print a brief help message and exits. -++ -++=item B<--offset>=I -++ -++Byte-offset where bit-error should be injected. -++ -++=item B<--bitmask>=I -++ -++Bit-mask where to inject errors in the byte. -++ -++=item B<--input>=I -++ -++Input file. -++ -++=item B<--output>=I -++ -++Output file. -++ -++=back -++ -++=head1 DESCRIPTION -++ -++B will read the given input file and inject -++biterrors at the I specified. The location of the biterrors -++are defined by the I parameter. -++ -++=cut -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/jffs2_test.sh linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/jffs2_test.sh -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/jffs2_test.sh 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/jffs2_test.sh 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,91 @@ -++#!/bin/sh -++# -++# Testcase for JFFS2 verification. We do not want to see any -++# kernel errors occuring when this is executed. -++# -++# -++# To have a standardized output I define the following function to be -++# used when a test was ok or when it failed. -++# -++failed () -++{ -++ echo "FAILED" -++} -++ -++passed () -++{ -++ echo "PASSED" -++} -++ -++# -++# Print sucess message. Consider to exit with zero as return code. -++# -++exit_success () -++{ -++ echo "SUCCESS" -++ exit 0 -++} -++ -++# -++# Print failure message. Consider to exit with non zero return code. -++# -++exit_failure () -++{ -++ echo "FAILED" -++ exit 1 -++} -++ -++echo "***********************************************************************" -++echo "* jffs2 testing ... *" -++echo "***********************************************************************" -++ -++ulimit -c unlimited -++ -++for i in `seq 5000`; do -++ echo "Testing $i byte (dd if=/dev/urandom of=foo bs=$i count=1) ... " -++ dd if=/dev/urandom of=test.bin bs=$i count=1; -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ echo "Copy to different file ... " -++ dd if=test.bin of=new.bin bs=$i count=1; -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ echo "Comparing files ... " -++ cmp test.bin new.bin -++ dd if=test.bin of=new.bin bs=$i count=1; -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++done -++ -++for i in `seq 5000`; do -++ echo "Testing $i byte (dd if=/dev/urandom of=foo bs=$i count=1) ... " -++ dd if=/dev/urandom of=foo bs=$i count=1; -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++done -++ -++for i in `seq 5000`; do -++ echo "Testing $i byte (dd if=/dev/zero of=foo bs=$i count=1) ... " -++ dd if=/dev/zero of=foo bs=$i count=1; -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++done -++ -++echo "***********************************************************************" -++echo "* Congratulations, no errors found! *" -++echo "* Have fun with your cool JFFS2 using system! *" -++echo "***********************************************************************" -++ -++exit_success -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/mkdevs.pl linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/mkdevs.pl -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/mkdevs.pl 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/mkdevs.pl 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,32 @@ -++#!/usr/bin/perl -w -++ -++# -++# Author: Artem B. Bityutskiy -++# -++# A small scrip which creates UBI device nodes in /dev. UBI allocates -++# major number dynamically, so the script looks at /proc/devices to find -++# out UBI's major number. -++# -++ -++ -++my $proc = '/proc/devices'; -++my $regexp = '(\d+) (ubi\d+)$'; -++ -++ -++open FILE, "<", $proc or die "Cannot open $proc file: $!\n"; -++my @file = ; -++close FILE; -++ -++foreach (@file) { -++ next if not m/$regexp/g; -++ print "found $2\n"; -++ -++ system("rm -rf /dev/$2"); -++ system("mknod /dev/$2 c $1 0"); -++ -++ for (my $i = 0; $i < 128; $i += 1) { -++ system("rm -rf /dev/$2_$i"); -++ my $j = $i + 1; -++ system("mknod /dev/$2_$i c $1 $j"); -++ } -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/pdd.txt linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/pdd.txt -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/pdd.txt 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/pdd.txt 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,16 @@ -++pdd=flash_type,flash_size,flash_eraseblock_size,flash_page_size,card_serialnumber,card_type,ethaddr,eth1addr,eth0,eth1,total,card_hardwarelevel -++pdd_preserve=ethaddr,eth1addr,card_serialnumber -++# To be personalized -++ethaddr=00:04:34:56:78:9A -++eth1addr=00:04:34:56:78:9B -++card_serialnumber=SN0 -++# Static for this card type -++total=102M -++card_type=nand_driven_testcard -++card_hardwarelevel=0 -++eth0=bcm5222,eth0,0 -++eth1=bcm5222,eth0,1 -++flash_type=NAND -++flash_size=0x08000000 -++flash_eraseblock_size=0x00020000 -++flash_page_size=0x00000800 -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/run_all.sh linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/run_all.sh -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/run_all.sh 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/run_all.sh 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,101 @@ -++#!/bin/sh -++ -++exit_success () -++{ -++ echo "UBI Utils Test Scripts - SUCCESS!" -++ exit 0 -++} -++ -++exit_failure () -++{ -++ echo $1 -++ echo "UBI Utils Test Scripts - FAILED!" -++ exit 1 -++} -++ -++echo UBI Utils Test Scripts -++ -++devno=$1 -++logfile=temp-test-log.txt -++ -++if test -z "$devno"; -++then -++ echo "Usage is $0 " -++ exit 1 -++fi -++ -++cwd=`pwd` || exit_failure "pwd failed" -++ -++log="${cwd}/${logfile}" -++ -++PATH=$PATH:$cwd:.. -++ -++cat /dev/null > $log || exit_failure "Failed to create $log" -++ -++echo "Setting up for jffs2_test.sh" | tee -a $log -++ -++avail=`cat /sys/class/ubi/ubi${devno}/avail_eraseblocks` -++size=`cat /sys/class/ubi/ubi${devno}/eraseblock_size` -++ -++bytes=`expr $avail \* $size` -++ -++ubimkvol -d$devno -s$bytes -n0 -Njtstvol || exit_failure "ubimkvol failed" -++ -++mkdir -p /mnt/test_file_system || exit_failure "mkdir failed" -++ -++mtd=`cat /proc/mtd | grep jtstvol | cut -d: -f1` -++ -++if test -z "$mtd"; -++then -++ exit_failure "mtd device not found" -++fi -++ -++mount -t jffs2 $mtd /mnt/test_file_system || exit_failure "mount failed" -++ -++cd /mnt/test_file_system || exit_failure "cd failed" -++ -++echo Running jffs2_test.sh | tee -a $log -++ -++jffs2_test.sh >> $log 2>&1 || exit_failure "jffs2_test.sh failed" -++ -++rm -f * -++ -++cd $cwd || exit_failure "cd failed" -++ -++umount /mnt/test_file_system || exit_failure "umount failed" -++ -++ubirmvol -d$devno -n0 || exit_failure "ubirmvol failed" -++ -++major=`cat /sys/class/ubi/ubi${devno}/dev | cut -d: -f1` -++ -++for minor in `seq 0 32`; do -++ if test ! -e /dev/ubi${devno}_$minor ; -++ then -++ mknod /dev/ubi${devno}_$minor c $major $(($minor + 1)) -++ fi -++done -++ -++rm -f testdata.bin readdata.bin -++ -++echo Running ubi_jffs2_test.sh | tee -a $log -++ -++ubi_jffs2_test.sh >> $log 2>&1 || exit_failure "ubi_jffs2_test.sh failed" -++ -++echo Running ubi_test.sh | tee -a $log -++ -++ubi_test.sh >> $log 2>&1 || exit_failure "ubi_test.sh failed" -++ -++for minor in `seq 0 32`; do -++ if test -e /sys/class/ubi/ubi${devno}/$minor; -++ then -++ ubirmvol -d$devno -n$minor || exit_failure "ubirmvol failed" -++ fi -++done -++ -++echo Running ubi_tools_test.sh | tee -a $log -++ -++ubi_tools_test.sh >> $log 2>&1 || exit_failure "ubi_tools_test failed" -++ -++rm -f $log -++ -++exit_success -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/test.cfg linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/test.cfg -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/test.cfg 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/test.cfg 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,23 @@ -++[targets] -++test_complete=spl,kernel,rootfs -++ -++[spl] -++image=test_u-boot.bin -++ubi_ids=10,11 -++ubi_size=1MiB -++ubi_type=static -++ubi_names=test_spl_0,test_spl_1 -++ -++[kernel] -++image=test_vmlinux.bin -++ubi_ids=12,13 -++ubi_size=2MiB -++ubi_type=static -++ubi_names=test_kernel_0,test_kernel_1 -++ -++[rootfs] -++image=test_rootfs.bin -++ubi_ids=14,15 -++ubi_size=2MiB -++ubi_type=dynamic -++ubi_names=test_rootfs_0,test_rootfs_1 -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/ubi_jffs2_test.sh linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/ubi_jffs2_test.sh -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/ubi_jffs2_test.sh 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/ubi_jffs2_test.sh 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,411 @@ -++#!/bin/sh -++# -++# UBI Volume creation/deletion/write/read and JFFS2 on top of UBI -++# testcases. -++# -++# Written in shell language to reduce dependencies to more sophisticated -++# interpreters, which may not be available on some stupid platforms. -++# -++# Author: Frank Haverkamp -++# -++# 1.0 Initial version -++# 1.1 Added fixup for delayed device node creation by udev -++# This points to a problem in the tools, mabe in the desing -++# Tue Oct 31 14:14:54 CET 2006 -++# -++ -++VERSION="1.1" -++ -++export PATH=$PATH:/bin:~/bin:/usr/local/bin:/home/dedekind/work/prj/ubi/tools/flashutils/bin/ -++ -++ITERATIONS=250 -++ALIGNMENT=2048 -++ -++UBIMKVOL="ubimkvol -a $ALIGNMENT" -++UBIRMVOL=ubirmvol -++UBIUPDATEVOL=ubiupdatevol -++ -++SIZE_512K=524288 -++SIZE_1M=1310720 -++ -++MINVOL=10 -++MAXVOL=12 -++ -++TLOG=/dev/null -++ -++# -++# To have a standardized output I define the following function to be -++# used when a test was ok or when it failed. -++# -++failed () -++{ -++ echo "FAILED" -++} -++ -++passed () -++{ -++ echo "PASSED" -++} -++ -++# -++# Print sucess message. Consider to exit with zero as return code. -++# -++exit_success () -++{ -++ echo "SUCCESS" -++ exit 0 -++} -++ -++# -++# Print failure message. Consider to exit with non zero return code. -++# -++exit_failure () -++{ -++ echo "FAILED" -++ exit 1 -++} -++ -++############################################################################### -++# -++# START -++# -++############################################################################### -++ -++fix_sysfs_issue () -++{ -++ echo "*** Fixing the sysfs issue with the /dev nodes ... " -++ -++ minor=0 -++ major=`grep ubi0 /proc/devices | sed -e 's/\(.*\) ubi0/\1/'` -++ -++ rm -rf /dev/ubi0 -++ mknod /dev/ubi0 c $major 0 -++ -++ for minor in `seq $MINVOL $MAXVOL`; do -++ echo " -> mknod /dev/ubi0_$minor c $major $(($minor + 1))" -++ rm -rf /dev/ubi0_$minor -++ mknod /dev/ubi0_$minor c $major $(($minor + 1)) -++ done -++ passed -++} -++ -++# -++# FIXME Udev needs some time until the device nodes are created. -++# This will cause trouble if after ubimkvol an update attempt -++# is started immediately, since the device node is not yet -++# available. We should either fix the tools with inotify or -++# other ideas or figure out a different way to solve the problem -++# e.g. to use ubi0 and make the volume device nodes obsolete... -++# -++udev_wait () -++{ -++ echo -n "FIXME Waiting for udev to create/delete device node " -++ grep 2\.6\.5 /proc/version > /dev/null -++ if [ $? -eq "0" ]; then -++ for i in `seq 0 5`; do -++ sleep 1; echo -n "."; -++ done -++ echo " ok" -++ fi -++} -++ -++# delete_volume - Delete a volume. If it does not exist, do not try -++# to delete it. -++# @id: volume id -++# -++delete_volume () -++{ -++ volume=$1 -++ -++ ### FIXME broken sysfs!!!! -++ if [ -e /sys/class/ubi/$volume -o \ -++ -e /sys/class/ubi/ubi0/$volume -o \ -++ -e /sys/class/ubi/ubi0_$volume ]; then -++ -++ echo "*** Truncate volume if it exists ... " -++ echo " $UBIUPDATEVOL -d0 -n$volume -t" -++ $UBIUPDATEVOL -d0 -n$volume -t -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ echo -n "*** Delete volume if it exists ... " -++ $UBIRMVOL -d0 -n$volume -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ # udev_wait -++ fi -++} -++ -++# writevol_test - Tests volume creation and writing data to it. -++# -++# @volume: Volume number -++# @size: Size of random data to write -++# @type: Volume type static or dynamic -++# -++writevol_test () -++{ -++ volume=$1 -++ size=$2 -++ type=$3 -++ -++ echo "*** Write volume test with size $size" -++ -++### Make sure that volume exist, delete existing volume, create new -++ -++ delete_volume $volume -++ -++ echo "*** Try to create volume" -++ echo " $UBIMKVOL -d0 -n$volume -t$type -NNEW$volume -s $size ... " -++ $UBIMKVOL -d0 -n$volume -t$type -N"NEW$volume" -s $size -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ udev_wait -++ -++### Try to create same volume again -++ echo -n "*** Try to create some volume again, this must fail ... " -++ $UBIMKVOL -d0 -n$volume -t$type -N"NEW$volume" -s $size -++ if [ $? -eq "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++### Now create test data, write it, read it, compare it -++ echo -n "*** Create test data ... " -++ dd if=/dev/urandom of=testdata.bin bs=$size count=1 -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ echo "*** Now writing data to volume ... " -++ echo " $UBIUPDATEVOL -d0 -n$volume testdata.bin" -++ ls -l testdata.bin -++ $UBIUPDATEVOL -d0 -n$volume testdata.bin -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ echo "*** Download data with dd bs=1 ... " -++ dd if=/dev/ubi0_$volume of=readdata.bin bs=$size count=1 -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ echo -n "*** Comparing data ... " -++ cmp readdata.bin testdata.bin -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ echo -n "*** Now truncate volume ... " -++ $UBIUPDATEVOL -d0 -n$volume -t -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++} -++ -++jffs2_torture () -++{ -++ cat /dev/null > TLOG -++ -++ echo "*** Torture test ... " -++ -++ for i in `seq $iterations`; do -++ dd if=/dev/urandom of=test.bin bs=$i count=1 2>> $TLOG -++ if [ $? -ne "0" ] ; then -++ echo "Testing $i byte (dd if=/dev/urandom of=foo bs=$i count=1) ... " -++ exit_failure -++ fi -++ #passed -++ -++ dd if=test.bin of=new.bin bs=$i count=1 2>> $TLOG -++ if [ $? -ne "0" ] ; then -++ echo "dd if=test.bin of=new.bin bs=$i count=1 2>> $TLOG" -++ exit_failure -++ fi -++ #passed -++ -++ #echo "Comparing files ... " -++ cmp test.bin new.bin -++ dd if=test.bin of=new.bin bs=$i count=1 2>> $TLOG -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ #passed -++ #echo -n "." -++ done -++ -++ echo -n "step0:ok " -++ -++ for i in `seq $iterations`; do -++ dd if=/dev/urandom of=foo bs=$i count=1 2>> $TLOG -++ if [ $? -ne "0" ] ; then -++ echo "Testing $i byte (dd if=/dev/urandom of=foo bs=$i count=1) ... " -++ exit_failure -++ fi -++ #passed -++ done -++ -++ echo -n "step1:ok " -++ -++ for i in `seq $iterations`; do -++ dd if=/dev/zero of=foo bs=1 count=$i 2>> $TLOG -++ if [ $? -ne "0" ] ; then -++ echo "Testing $i byte (dd if=/dev/zero of=foo bs=1 count=$i) ... " -++ exit_failure -++ fi -++ #passed -++ done -++ -++ echo -n "step2:ok " -++ -++ for i in `seq $iterations`; do -++ dd if=/dev/zero of=foo bs=$i count=16 2>> $TLOG -++ if [ $? -ne "0" ] ; then -++ echo "Testing $i byte (dd if=/dev/zero of=foo bs=$i count=1024) ... " -++ exit_failure -++ fi -++ #passed -++ done -++ -++ echo -n "step3:ok " -++ -++ passed -++} -++ -++# writevol_test - Tests volume creation and writing data to it. -++# -++# @volume: Volume number -++# @size: Size of random data to write -++# @type: Volume type static or dynamic -++# -++jffs2_test () -++{ -++ name=$1 -++ iterations=$2 -++ directory=`pwd` -++ -++ ### Setup -++ ulimit -c unlimited -++ -++ echo -n "*** Create directory /mnt/$name ... " -++ mkdir -p /mnt/$name -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ echo -n "*** mount -t jffs2 mtd:$name /mnt/$name ... " -++ mount -t jffs2 mtd:$name /mnt/$name -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ echo -n "*** change directory ... " -++ cd /mnt/$name -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ ls -++ echo "*** list directory ... " -++ ls -la -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ ### Torture -++ echo -n "*** touch I_WAS_HERE ... " -++ touch I_WAS_HERE -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ jffs2_torture -++ -++ echo "*** list directory ... " -++ ls -la -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ ### Cleanup -++ echo -n "*** go back ... " -++ cd $directory -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ ### Still mounted, ubiupdatevol must fail! -++ -++ echo -n "*** $UBIUPDATEVOL -d0 -n$volume -t must fail! ..." -++ $UBIUPDATEVOL -d0 -n$volume -t -++ if [ $? -eq "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ echo -n "*** umount /mnt/$name ... " -++ umount /mnt/$name -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ return -++} -++ -++echo "***********************************************************************" -++echo "* UBI JFFS2 Testing starts now ... *" -++echo "* Good luck! *" -++echo "***********************************************************************" -++echo "VERSION: $VERSION" -++ -++# Set to zero if not running on example hardware -++grep ubi /proc/devices > /dev/null -++if [ $? -ne "0" ]; then -++ echo "No UBI found in /proc/devices! I am broken!" -++ exit_failure -++fi -++ -++# Set to zero if not running on example hardware -++grep 1142 /proc/cpuinfo > /dev/null -++if [ $? -eq "0" ]; then -++ echo "Running on example hardware" -++ mount -o remount,rw / / -++ sleep 1 -++ fix_sysfs_issue -++else -++ echo "Running on Artems hardware" -++fi -++ -++for volume in `seq $MINVOL $MAXVOL`; do -++ echo -n "************ VOLUME $volume NEW$volume " -++ echo "******************************************" -++ writevol_test $volume $SIZE_1M dynamic -++ jffs2_test NEW$volume $ITERATIONS -++ delete_volume $volume -++done -++ -++echo "***********************************************************************" -++echo "* Congratulations, no errors found! *" -++echo "* Have fun with your cool UBI system! *" -++echo "***********************************************************************" -++ -++exit_success -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/ubi_test.sh linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/ubi_test.sh -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/ubi_test.sh 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/ubi_test.sh 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,328 @@ -++#!/bin/sh -++# -++# UBI Volume creation/deletion/write/read test script -++# -++# Written in shell language to reduce dependencies to more sophisticated -++# interpreters, which may not be available on some stupid platforms. -++# -++# Author: Frank Haverkamp -++# -++# 1.0 Initial version -++# 1.1 Use ubiupdatevol instead of ubiwritevol -++# -++ -++VERSION="1.1" -++ -++export PATH=$PATH:~/bin:/usr/local/bin:/home/dedekind/work/prj/ubi/tools/flashutils/bin/ -++ -++UBIMKVOL=ubimkvol -++UBIRMVOL=ubirmvol -++UBIUPDATEVOL=ubiupdatevol -++ -++# 128 KiB 131072 -++# 256 KiB 262144 -++# 512 KiB 524288 -++ -++SIZE_512K=524288 -++SIZE_1M=1310720 -++ -++SELF=$0 -++MINVOL=10 -++MAXVOL=12 -++ -++# -++# To have a standardized output I define the following function to be -++# used when a test was ok or when it failed. -++# -++failed () -++{ -++ echo "FAILED" -++} -++ -++passed () -++{ -++ echo "PASSED" -++} -++ -++# -++# Print sucess message. Consider to exit with zero as return code. -++# -++exit_success () -++{ -++ echo "SUCCESS" -++ exit 0 -++} -++ -++# -++# Print failure message. Consider to exit with non zero return code. -++# -++exit_failure () -++{ -++ echo "FAILED" -++ exit 1 -++} -++ -++############################################################################### -++# -++# START -++# -++############################################################################### -++ -++fix_sysfs_issue () -++{ -++ echo -n "*** Fixing the sysfs issue with the /dev nodes ... " -++ -++ minor=0 -++ major=`grep ubi0 /proc/devices | sed -e 's/\(.*\) ubi0/\1/'` -++ -++ rm -rf /dev/ubi0 -++ mknod /dev/ubi0 c $major 0 -++ -++ for minor in `seq 0 $MAXVOL`; do -++ ### echo " mknod /dev/ubi0_$minor c $major $(($minor + 1))" -++ rm -rf /dev/ubi0_$minor -++ mknod /dev/ubi0_$minor c $major $(($minor + 1)) -++ done -++ passed -++} -++ -++# delete_volume - Delete a volume. If it does not exist, do not try -++# to delete it. -++# @id: volume id -++# -++delete_volume () -++{ -++ volume=$1 -++ -++ ### FIXME broken sysfs!!!! -++ if [ -e /sys/class/ubi/$volume -o -e /sys/class/ubi/ubi0/$volume -o -e /sys/class/ubi/ubi0_$volume ]; then -++ -++ echo -n "*** Truncate volume if it exists ... " -++ $UBIUPDATEVOL -d0 -n$volume -t -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ echo -n "*** Delete volume if it exists ... " -++ $UBIRMVOL -d0 -n$volume -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ fi -++} -++ -++mkvol_rmvol_test () -++{ -++ type=$1 -++ -++### Test if volume delete on non-existing volumes fails nicely -++ -++ for i in `seq $MINVOL $MAXVOL`; do -++ echo "*** Delete if exist or not $i ... " -++ -++ delete_volume $i -++ passed -++ done -++ -++### Now deleting volumes must fail -++ -++ for i in `seq $MINVOL $MAXVOL`; do -++ echo "*** Trying to delete non existing UBI Volume $i ... " -++ -++ $UBIRMVOL -d0 -n$i -++ if [ $? -eq "0" ] ; then -++ exit_failure -++ fi -++ passed -++ done -++ -++### Test if volume creation works ok -++ -++ for i in `seq $MINVOL $MAXVOL`; do -++ echo "*** Creating UBI Volume $i ... " -++ echo " $UBIMKVOL -d0 -n$i -t$type -NNEW$i -s $SIZE_512K" -++ -++ $UBIMKVOL -d0 -n$i -t$type -N"NEW$i" -s $SIZE_512K -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ done -++ -++### Now deleting volumes must be ok -++ -++ for i in `seq $MINVOL $MAXVOL`; do -++ echo "*** Trying to delete UBI Volume $i ... " -++ -++ $UBIRMVOL -d0 -n$i -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ done -++ -++### Now allocate too large volume -++ -++ echo -n "*** Try to create too large volume" -++ $UBIMKVOL -d0 -n$MINVOL -t$type -N"NEW$MINVOL" -s 800000000 -++ if [ $? -eq "0" ] ; then -++ exit_failure -++ fi -++ passed -++} -++ -++# writevol_test - Tests volume creation and writing data to it. -++# -++# @size: Size of random data to write -++# @type: Volume type static or dynamic -++# -++writevol_test () -++{ -++ size=$1 -++ type=$2 -++ -++ echo "*** Write volume test with size $size" -++ -++### Make sure that volume exist, delete existing volume, create new -++ -++ delete_volume $MINVOL -++ -++ echo -n "*** Try to create volume ... " -++ $UBIMKVOL -d0 -n$MINVOL -t$type -N"NEW$MINVOL" -s $SIZE_1M -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++### Try to create same volume again -++ echo -n "*** Try to create some volume again, this must fail ... " -++ $UBIMKVOL -d0 -n$MINVOL -t$type -N"NEW$MINVOL" -s $SIZE_1M -++ if [ $? -eq "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++### Now create test data, write it, read it, compare it -++ echo -n "*** Create test data ... " -++ dd if=/dev/urandom of=testdata.bin bs=$size count=1 -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ echo "*** Now writing data to volume ... " -++ # sleep 5 -++ ls -l testdata.bin -++ echo " $UBIUPDATEVOL -d0 -n$MINVOL testdata.bin" -++ $UBIUPDATEVOL -d0 -n$MINVOL testdata.bin -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ if [ $type = "static" ] ; then -++ echo "*** Download data with cat ... " -++ cat /dev/ubi0_$MINVOL > readdata.bin -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ else -++ echo "*** Download data with dd bs=1 ... " -++ dd if=/dev/ubi0_$MINVOL of=readdata.bin bs=$size count=1 -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ # Size 1 does not work with this test ... -++ # -++ #echo "*** Download data with dd bs=$size ... " -++ #dd if=/dev/ubi0_$MINVOL of=readdata2.bin bs=$size count=1 -++ #if [ $? -ne "0" ] ; then -++ # exit_failure -++ #fi -++ #passed -++ -++ #echo -n "*** Comparing data (1) ... " -++ #cmp readdata.bin readdata2.bin -++ #if [ $? -ne "0" ] ; then -++ # exit_failure -++ #fi -++ #passed -++ fi -++ -++ echo -n "*** Comparing data ... " -++ cmp readdata.bin testdata.bin -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++} -++ -++echo "***********************************************************************" -++echo "* UBI Testing starts now ... *" -++echo "* Good luck! *" -++echo "***********************************************************************" -++ -++# Set to zero if not running on example hardware -++grep ubi /proc/devices > /dev/null -++if [ $? -ne "0" ]; then -++ echo "No UBI found in /proc/devices! I am broken!" -++ exit_failure -++fi -++ -++# Set to zero if not running on example hardware -++grep 1142 /proc/cpuinfo > /dev/null -++if [ $? -eq "0" ]; then -++ echo "Running on example hardware" -++ mount -o remount,rw / / -++ sleep 1 -++ fix_sysfs_issue -++else -++ echo "Running on Artems hardware" -++fi -++ -++echo "***********************************************************************" -++echo "* mkvol/rmvol testing for static volumes ... *" -++echo "***********************************************************************" -++ -++mkvol_rmvol_test static -++ -++echo "***********************************************************************" -++echo "* mkvol/rmvol testing for dynamic volumes ... *" -++echo "***********************************************************************" -++ -++mkvol_rmvol_test dynamic -++ -++echo "***********************************************************************" -++echo "* write to static volumes ... *" -++echo "***********************************************************************" -++ -++# 10 Erase blocks = (128 KiB - 64 * 2) * 10 -++# = 1309440 bytes -++# 128 KiB 131072 -++# 256 KiB 262144 -++# 512 KiB 524288 -++ -++for size in 262144 131073 131072 2048 1 4096 12800 31313 ; do -++ writevol_test $size static -++done -++ -++echo "***********************************************************************" -++echo "* write to dynamic volumes ... *" -++echo "***********************************************************************" -++echo "VERSION: $VERSION" -++ -++for size in 131073 131072 2048 1 4096 12800 31313 262144 ; do -++ writevol_test $size dynamic -++done -++ -++echo "***********************************************************************" -++echo "* Congratulations, no errors found! *" -++echo "* Have fun with your cool UBI system! *" -++echo "***********************************************************************" -++ -++exit_success -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/ubi_tools_test.sh linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/ubi_tools_test.sh -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/ubi_tools_test.sh 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/ubi_tools_test.sh 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,252 @@ -++#!/bin/sh -++# -++# UBI Volume creation/deletion/write/read test script. -++# Uses our flash update tools and the associated toolchain for flash -++# image creation. -++# -++# Written in shell language to reduce dependencies to more sophisticated -++# interpreters, which may not be available on some stupid platforms. -++# -++# Author: Frank Haverkamp -++# -++# 1.0 Initial version -++# -++ -++VERSION="1.0" -++ -++export PATH=$PATH:~/bin:/usr/local/bin:/home/dedekind/work/prj/ubi/tools/flashutils/bin/ -++ -++UBIMKVOL=ubimkvol -++UBIRMVOL=ubirmvol -++UBIWRITEVOL=ubiupdatevol -++PFIFLASH=pfiflash -++CMP=cmp -++ -++MAXVOL=32 -++ -++test_pfi=test_complete.pfi -++real_pfi=example_complete.pfi -++ -++# 128 KiB 131072 -++# 256 KiB 262144 -++# 512 KiB 524288 -++ -++# -++# To have a standardized output I define the following function to be -++# used when a test was ok or when it failed. -++# -++failed () -++{ -++ echo "FAILED" -++} -++ -++passed () -++{ -++ echo "PASSED" -++} -++ -++# -++# Print sucess message. Consider to exit with zero as return code. -++# -++exit_success () -++{ -++ echo "SUCCESS" -++ exit 0 -++} -++ -++# -++# Print failure message. Consider to exit with non zero return code. -++# -++exit_failure () -++{ -++ echo "FAILED" -++ exit 1 -++} -++ -++############################################################################### -++# -++# START -++# -++############################################################################### -++ -++fix_sysfs_issue () -++{ -++ echo -n "*** Fixing the sysfs issue with the /dev nodes ... " -++ -++ minor=0 -++ major=`grep ubi0 /proc/devices | sed -e 's/\(.*\) ubi0/\1/'` -++ -++ rm -rf /dev/ubi0 -++ mknod /dev/ubi0 c $major 0 -++ -++ for minor in `seq 0 $MAXVOL`; do -++ ### echo " mknod /dev/ubi0_$minor c $major $(($minor + 1))" -++ rm -rf /dev/ubi0_$minor -++ mknod /dev/ubi0_$minor c $major $(($minor + 1)) -++ done -++ passed -++} -++ -++# delete_volume - Delete a volume. If it does not exist, do not try -++# to delete it. -++# @id: volume id -++# -++delete_volume () -++{ -++ volume=$1 -++ -++ ### FIXME broken sysfs!!!! -++ if [ -e /sys/class/ubi/$volume -o -e /sys/class/ubi/ubi0/$volume -o -e /sys/class/ubi/ubi0_$volume ]; then -++ -++ echo -n "*** Truncate volume if it exists ... " -++ $UBIWRITEVOL -d0 -n$volume -t -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ -++ echo -n "*** Delete volume if it exists ... " -++ $UBIRMVOL -d0 -n$volume -++ if [ $? -ne "0" ] ; then -++ exit_failure -++ fi -++ passed -++ fi -++} -++ -++echo "***********************************************************************" -++echo "* UBI Tools Testing starts now ... *" -++echo "* Good luck! *" -++echo "***********************************************************************" -++ -++# Set to zero if not running on example hardware -++grep ubi /proc/devices > /dev/null -++if [ $? -ne "0" ]; then -++ echo "No UBI found in /proc/devices! I am broken!" -++ exit_failure -++fi -++ -++# Set to zero if not running on example hardware -++grep 1142 /proc/cpuinfo > /dev/null -++if [ $? -eq "0" ]; then -++ echo "Running on example hardware" -++ mount -o remount,rw / / -++ sleep 1 -++ fix_sysfs_issue -++else -++ echo "Running on other hardware" -++fi -++ -++### Test basic stuff -++pfiflash_basic () -++{ -++ echo "Calling pfiflash with test-data ... " -++ echo " $PFIFLASH $test_pfi" -++ $PFIFLASH $test_pfi -++ if [ $? -ne "0" ]; then -++ echo "Uhhh something went wrong!" -++ exit_failure -++ fi -++ passed -++ -++ echo "Testing if data is correct 10 and 11 ... " -++ $CMP /dev/ubi0_10 /dev/ubi0_11 -++ if [ $? -ne "0" ]; then -++ echo "Mirrored volumes not equal!" -++ exit_failure -++ fi -++ passed -++ -++ echo "Comparing against original data ... " -++ $CMP /dev/ubi0_10 test_u-boot.bin -++ if [ $? -ne "0" ]; then -++ echo "Compared volume not equal!" -++ exit_failure -++ fi -++ passed -++ -++ echo "Testing if data is correct 12 and 13 ... " -++ $CMP /dev/ubi0_12 /dev/ubi0_13 -++ if [ $? -ne "0" ]; then -++ echo "Mirrored volumes not equal!" -++ exit_failure -++ fi -++ passed -++ -++ echo "Comparing against original data ... " -++ $CMP /dev/ubi0_12 test_vmlinux.bin -++ if [ $? -ne "0" ]; then -++ echo "Compared volume not equal!" -++ exit_failure -++ fi -++ passed -++ -++ echo "Testing if data is correct 14 and 15 ... " -++ $CMP /dev/ubi0_14 /dev/ubi0_15 -++ if [ $? -ne "0" ]; then -++ echo "Mirrored volumes not equal!" -++ exit_failure -++ fi -++ passed -++} -++ -++### Test each and everything -++pfiflash_advanced () -++{ -++ if [ -e example_complete.pfi ]; then -++ echo "Calling pfiflash with real data ... " -++ $PFIFLASH -p overwrite --complete example_complete.pfi -++ if [ $? -ne "0" ]; then -++ echo "Uhhh something went wrong!" -++ exit_failure -++ fi -++ passed -++ -++ echo "Testing if data is correct 2 and 3 ... " -++ $CMP /dev/ubi0_2 /dev/ubi0_3 -++ if [ $? -ne "0" ]; then -++ echo "Mirrored volumes not equal!" -++ exit_failure -++ fi -++ passed -++ -++ echo "Comparing against original data ... " -++ $CMP /dev/ubi0_2 u-boot.bin -++ if [ $? -ne "0" ]; then -++ echo "Compared volume not equal!" -++ exit_failure -++ fi -++ passed -++ -++ echo "Testing if data is correct 6 and 7 ... " -++ $CMP /dev/ubi0_6 /dev/ubi0_7 -++ if [ $? -ne "0" ]; then -++ echo "Mirrored volumes not equal!" -++ exit_failure -++ fi -++ passed -++ -++ echo "Comparing against original data ... " -++ $CMP /dev/ubi0_6 vmlinux.bin -++ if [ $? -ne "0" ]; then -++ echo "Compared volume not equal!" -++ exit_failure -++ fi -++ passed -++ fi -++} -++ -++echo "***********************************************************************" -++echo "* Testing pfiflash ... *" -++echo "***********************************************************************" -++echo "VERSION: $VERSION" -++ -++pfiflash_basic -++pfiflash_advanced -++ -++echo "***********************************************************************" -++echo "* Congratulations, no errors found! *" -++echo "* Have fun with your cool UBI system! *" -++echo "***********************************************************************" -++ -++exit_success -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/unubi_test.sh linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/unubi_test.sh -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/scripts/unubi_test.sh 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/scripts/unubi_test.sh 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,105 @@ -++#!/bin/sh -++# -++# Use raw NAND data, extract UBI image and apply tool to it. -++# Test basic functionality. -++# -++# 2007 Frank Haverkamp -++# -++ -++version=1.1 -++ -++image=data.mif -++oob=oob.bin -++data=data.bin -++pagesize=2048 -++volmax=31 -++datadir=unubi_data -++ -++# general arguments e.g. debug enablement -++# unubi_args="-D" -++ -++echo "------------------------------------------------------------------------" -++echo "Testcase: ${0} Version: ${version}" -++echo "------------------------------------------------------------------------" -++echo "Testing nand2bin ..." -++echo " Input: ${image}" -++echo " Data: ${data}" -++echo " OOB: ${oob}" -++echo " Pagesize: ${pagesize}" -++nand2bin --pagesize ${pagesize} -o ${data} -O ${oob} ${image} -++echo -++ -++echo "------------------------------------------------------------------------" -++echo "Testing unubi ..." -++echo "------------------------------------------------------------------------" -++unubi --version -++echo -++ -++echo "------------------------------------------------------------------------" -++echo "Trying to extract first ${volmax} volumes ..." -++echo "------------------------------------------------------------------------" -++mkdir -p ${datadir}/volumes -++for v in `seq 0 ${volmax}` ; do -++ unubi ${unubi_args} -r${v} -d${datadir}/volumes ${data} -++ echo -n "." -++done -++echo "ok" -++ls -l ${datadir}/volumes -++echo -++ -++echo "------------------------------------------------------------------------" -++echo "Extracting graphics ..." -++echo "------------------------------------------------------------------------" -++unubi -a -d${datadir} ${data} -++echo "Use gnuplot to display:" -++ls ${datadir}/*.plot -++ls ${datadir}/*.data -++echo -++ -++echo "------------------------------------------------------------------------" -++echo "eb-split" -++echo "------------------------------------------------------------------------" -++unubi -e -d${datadir}/eb-split ${data} -++ls -l ${datadir}/eb-split -++echo -++ -++echo "------------------------------------------------------------------------" -++echo "vol-split" -++echo "------------------------------------------------------------------------" -++unubi -v -d${datadir}/vol-split ${data} -++ls -l ${datadir}/vol-split -++echo -++echo "The generated images contain only the data (126KiB in our " -++echo "case) not including the UBI erase count and volume info " -++echo "header. For dynamic volumes the data should be the full " -++echo "126KiB. Unubi cannot know how much of the data is valid. " -++echo -++ -++echo "------------------------------------------------------------------------" -++echo "!vol-split" -++echo "------------------------------------------------------------------------" -++unubi -V -d${datadir}/vol-split! ${data} -++ls -l ${datadir}/vol-split\! -++echo -++echo "The generated images contain the full block data of 128KiB " -++echo "including the UBI erase count and volume information header." -++echo -++ -++echo "------------------------------------------------------------------------" -++echo "Extracting volume info table ..." -++echo "------------------------------------------------------------------------" -++unubi -i -d${datadir} ${data} -++echo "I strongly hope that empty ubi blocks are filled with 0xff! " -++echo -++ -++echo "------------------------------------------------------------------------" -++echo "Table 0" -++echo "------------------------------------------------------------------------" -++cat ${datadir}/vol_info_table0 -++echo -++ -++echo "------------------------------------------------------------------------" -++echo "Table 1" -++echo "------------------------------------------------------------------------" -++cat ${datadir}/vol_info_table1 -++echo -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/bin2nand.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/bin2nand.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/bin2nand.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/bin2nand.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,344 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2007 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ */ -++ -++/* -++ * Create a flashable NAND image from a binary image -++ * -++ * History: -++ * 1.0 Initial release (tglx) -++ * 1.1 Understands hex and dec input parameters (tglx) -++ * 1.2 Generates separated OOB data, if needed. (oloh) -++ * 1.3 Padds data/oob to a given size. (oloh) -++ * 1.4 Removed argp because we want to use uClibc. -++ * 1.5 Minor cleanup -++ * 1.6 written variable not initialized (-j did not work) (haver) -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "error.h" -++#include "config.h" -++#include "nandecc.h" -++ -++#define PROGRAM_VERSION "1.6" -++ -++#define CHECK_ENDP(option, endp) do { \ -++ if (*endp) { \ -++ fprintf(stderr, \ -++ "Parse error option \'%s\'. " \ -++ "No correct numeric value.\n" \ -++ , option); \ -++ exit(EXIT_FAILURE); \ -++ } \ -++} while(0) -++ -++typedef enum action_t { -++ ACT_NORMAL = 0x00000001, -++} action_t; -++ -++#define PAGESIZE 2048 -++#define PADDING 0 /* 0 means, do not adjust anything */ -++#define BUFSIZE 4096 -++ -++static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" -++ "bin2nand - a tool for adding OOB information to a " -++ "binary input file.\n"; -++ -++static const char *optionsstr = -++" -c, --copyright Print copyright informatoin.\n" -++" -j, --padding= Padding in Byte/Mi/ki. Default = no padding\n" -++" -p, --pagesize= Pagesize in Byte/Mi/ki. Default = 2048\n" -++" -o, --output= Output filename. Interleaved Data/OOB if\n" -++" output-oob not specified.\n" -++" -q, --output-oob= Write OOB data in separate file.\n" -++" -?, --help Give this help list\n" -++" --usage Give a short usage message\n" -++" -V, --version Print program version\n"; -++ -++static const char *usage = -++"Usage: bin2nand [-c?V] [-j ] [-p ] [-o ] [-q ]\n" -++" [--copyright] [--padding=] [--pagesize=]\n" -++" [--output=] [--output-oob=] [--help] [--usage]\n" -++" [--version]\n"; -++ -++struct option long_options[] = { -++ { .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' }, -++ { .name = "padding", .has_arg = 1, .flag = NULL, .val = 'j' }, -++ { .name = "pagesize", .has_arg = 1, .flag = NULL, .val = 'p' }, -++ { .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' }, -++ { .name = "output-oob", .has_arg = 1, .flag = NULL, .val = 'q' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, -++ { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ { NULL, 0, NULL, 0} -++}; -++ -++static const char copyright [] __attribute__((unused)) = -++ "Copyright IBM Corp. 2006"; -++ -++typedef struct myargs { -++ action_t action; -++ -++ size_t pagesize; -++ size_t padding; -++ -++ FILE* fp_in; -++ char *file_out_data; /* Either: Data and OOB interleaved -++ or plain data */ -++ char *file_out_oob; /* OOB Data only. */ -++ -++ /* special stuff needed to get additional arguments */ -++ char *arg1; -++ char **options; /* [STRING...] */ -++} myargs; -++ -++ -++static int ustrtoull(const char *cp, char **endp, unsigned int base) -++{ -++ unsigned long long res = strtoull(cp, endp, base); -++ -++ switch (**endp) { -++ case 'G': -++ res *= 1024; -++ case 'M': -++ res *= 1024; -++ case 'k': -++ case 'K': -++ res *= 1024; -++ /* "Ki", "ki", "Mi" or "Gi" are to be used. */ -++ if ((*endp)[1] == 'i') -++ (*endp) += 2; -++ } -++ return res; -++} -++ -++static int -++parse_opt(int argc, char **argv, myargs *args) -++{ -++ char* endp; -++ -++ while (1) { -++ int key; -++ -++ key = getopt_long(argc, argv, "cj:p:o:q:?V", long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ case 'p': /* pagesize */ -++ args->pagesize = (size_t) -++ ustrtoull(optarg, &endp, 0); -++ CHECK_ENDP("p", endp); -++ break; -++ case 'j': /* padding */ -++ args->padding = (size_t) -++ ustrtoull(optarg, &endp, 0); -++ CHECK_ENDP("j", endp); -++ break; -++ case 'o': /* output */ -++ args->file_out_data = optarg; -++ break; -++ case 'q': /* output oob */ -++ args->file_out_oob = optarg; -++ break; -++ case '?': /* help */ -++ printf("%s", doc); -++ printf("%s", optionsstr); -++ exit(0); -++ break; -++ case 'V': -++ printf("%s\n", PROGRAM_VERSION); -++ exit(0); -++ break; -++ case 'c': -++ printf("%s\n", copyright); -++ exit(0); -++ default: -++ printf("%s", usage); -++ exit(-1); -++ } -++ } -++ -++ if (optind < argc) { -++ args->fp_in = fopen(argv[optind++], "rb"); -++ if ((args->fp_in) == NULL) { -++ err_quit("Cannot open file %s for input\n", -++ argv[optind++]); -++ } -++ } -++ -++ return 0; -++} -++ -++static int -++process_page(uint8_t* buf, size_t pagesize, -++ FILE *fp_data, FILE* fp_oob, size_t* written) -++{ -++ int eccpoi, oobsize; -++ size_t i; -++ uint8_t oobbuf[64]; -++ -++ memset(oobbuf, 0xff, sizeof(oobbuf)); -++ -++ switch(pagesize) { -++ case 2048: oobsize = 64; eccpoi = 64 / 2; break; -++ case 512: oobsize = 16; eccpoi = 16 / 2; break; -++ default: -++ err_msg("Unsupported page size: %d\n", pagesize); -++ return -EINVAL; -++ } -++ -++ for (i = 0; i < pagesize; i += 256, eccpoi += 3) { -++ oobbuf[eccpoi++] = 0x0; -++ /* Calculate ECC */ -++ nand_calculate_ecc(&buf[i], &oobbuf[eccpoi]); -++ } -++ -++ /* write data */ -++ *written += fwrite(buf, 1, pagesize, fp_data); -++ -++ /* either separate oob or interleave with data */ -++ if (fp_oob) { -++ i = fwrite(oobbuf, 1, oobsize, fp_oob); -++ if (ferror(fp_oob)) { -++ err_msg("IO error\n"); -++ return -EIO; -++ } -++ } -++ else { -++ i = fwrite(oobbuf, 1, oobsize, fp_data); -++ if (ferror(fp_data)) { -++ err_msg("IO error\n"); -++ return -EIO; -++ } -++ } -++ -++ return 0; -++} -++ -++int main (int argc, char** argv) -++{ -++ int rc = -1; -++ int res = 0; -++ size_t written = 0, read; -++ myargs args = { -++ .action = ACT_NORMAL, -++ .pagesize = PAGESIZE, -++ .padding = PADDING, -++ .fp_in = NULL, -++ .file_out_data = NULL, -++ .file_out_oob = NULL, -++ }; -++ -++ FILE* fp_out_data = stdout; -++ FILE* fp_out_oob = NULL; -++ -++ parse_opt(argc, argv, &args); -++ -++ uint8_t* buf = calloc(1, BUFSIZE); -++ if (!buf) { -++ err_quit("Cannot allocate page buffer.\n"); -++ } -++ -++ if (!args.fp_in) { -++ err_msg("No input image specified!\n"); -++ goto err; -++ } -++ -++ if (args.file_out_data) { -++ fp_out_data = fopen(args.file_out_data, "wb"); -++ if (fp_out_data == NULL) { -++ err_sys("Cannot open file %s for output\n", -++ args.file_out_data); -++ goto err; -++ } -++ } -++ -++ if (args.file_out_oob) { -++ fp_out_oob = fopen(args.file_out_oob, "wb"); -++ if (fp_out_oob == NULL) { -++ err_sys("Cannot open file %s for output\n", -++ args.file_out_oob); -++ goto err; -++ } -++ } -++ -++ -++ while(1) { -++ read = fread(buf, 1, args.pagesize, args.fp_in); -++ if (feof(args.fp_in) && read == 0) -++ break; -++ -++ if (read < args.pagesize) { -++ err_msg("Image not page aligned\n"); -++ goto err; -++ } -++ -++ if (ferror(args.fp_in)) { -++ err_msg("Read error\n"); -++ goto err; -++ } -++ -++ res = process_page(buf, args.pagesize, fp_out_data, -++ fp_out_oob, &written); -++ if (res != 0) -++ goto err; -++ } -++ -++ while (written < args.padding) { -++ memset(buf, 0xff, args.pagesize); -++ res = process_page(buf, args.pagesize, fp_out_data, -++ fp_out_oob, &written); -++ if (res != 0) -++ goto err; -++ } -++ -++ rc = 0; -++err: -++ free(buf); -++ -++ if (args.fp_in) -++ fclose(args.fp_in); -++ -++ if (fp_out_oob) -++ fclose(fp_out_oob); -++ -++ if (fp_out_data && fp_out_data != stdout) -++ fclose(fp_out_data); -++ -++ if (rc != 0) { -++ err_msg("Error during conversion. rc: %d\n", rc); -++ if (args.file_out_data) -++ remove(args.file_out_data); -++ if (args.file_out_oob) -++ remove(args.file_out_oob); -++ } -++ return rc; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/bootenv.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/bootenv.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/bootenv.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/bootenv.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1032 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2008 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "hashmap.h" -++#include "error.h" -++ -++#include -++#include "crc32.h" -++ -++#define ubi_unused __attribute__((unused)) -++ -++#define BOOTENV_MAXLINE 512 /* max line size of a bootenv.txt file */ -++ -++/* Structures */ -++struct bootenv { -++ hashmap_t map; ///< Pointer to hashmap which holds data structure. -++}; -++ -++struct bootenv_list { -++ hashmap_t head; ///< Pointer to list which holds the data structure. -++}; -++ -++/** -++ * @brief Remove the '\n' from a given line. -++ * @param line Input/Output line. -++ * @param size Size of the line. -++ * @param fp File Pointer. -++ * @return 0 -++ * @return or error -++ */ -++static int -++remove_lf(char *line, size_t size, FILE* fp) -++{ -++ size_t i; -++ -++ for (i = 0; i < size; i++) { -++ if (line[i] == '\n') { -++ line[i] = '\0'; -++ return 0; -++ } -++ } -++ -++ if (!feof(fp)) { -++ return BOOTENV_EINVAL; -++ } -++ -++ return 0; -++} -++ -++/** -++ * @brief Determine if a line contains only WS. -++ * @param line The line to process. -++ * @param size Size of input line. -++ * @return 1 Yes, only WS. -++ * @return 0 No, contains data. -++ */ -++static int -++is_ws(const char *line, size_t size) -++{ -++ size_t i = 0; -++ -++ while (i < size) { -++ switch (line[i]) { -++ case '\n': -++ return 1; -++ case '#': -++ return 1; -++ case ' ': -++ i++; -++ continue; -++ case '\t': -++ i++; -++ continue; -++ default: /* any other char -> no cmnt */ -++ return 0; -++ } -++ } -++ -++ return 0; -++} -++ -++ -++/* ------------------------------------------------------------------------- */ -++ -++/** -++ * @brief Build a list from a comma seperated value string. -++ * @param list Pointer to hashmap structure which shall store -++ * the list. -++ * @param value Comma seperated value string. -++ * @return 0 -++ * @return or error. -++ */ -++static int -++build_list_definition(hashmap_t list, const char *value) -++{ -++ int rc = 0; -++ char *str = NULL; -++ char *ptr = NULL; -++ size_t len, i, j; -++ -++ /* str: val1,val2 , val4,...,valN */ -++ len = strlen(value); -++ str = (char*) malloc((len+1) * sizeof(char)); -++ -++ /* 1. reformat string: remove spaces */ -++ for (i = 0, j = 0; i < len; i++) { -++ if (value[i] == ' ') -++ continue; -++ -++ str[j] = value[i]; -++ j++; -++ } -++ str[j] = '\0'; -++ -++ /* str: val1,val2,val4,...,valN\0*/ -++ /* 2. replace ',' seperator with '\0' */ -++ len = strlen(str); -++ for (i = 0; i < len; i++) { -++ if (str[i] == ',') { -++ str[i] = '\0'; -++ } -++ } -++ -++ /* str: val1\0val2\0val4\0...\0valN\0*/ -++ /* 3. insert definitions into a hash map, using it like a list */ -++ i = j = 0; -++ ptr = str; -++ while (((i = strlen(ptr)) > 0) && (j < len)) { -++ rc = hashmap_add(list, ptr, ""); -++ if (rc != 0) { -++ free(str); -++ return rc; -++ } -++ j += i+1; -++ if (j < len) -++ ptr += i+1; -++ } -++ -++ free(str); -++ return rc; -++} -++ -++/** -++ * @brief Extract a key value pair and add it to a hashmap -++ * @param str Input string which contains a key value pair. -++ * @param env The updated handle which contains the new pair. -++ * @return 0 -++ * @return or error -++ * @note The input string format is: "key=value" -++ */ -++static int -++extract_pair(const char *str, bootenv_t env) -++{ -++ int rc = 0; -++ char *key = NULL; -++ char *val = NULL; -++ -++ key = strdup(str); -++ if (key == NULL) -++ return -ENOMEM; -++ -++ val = strstr(key, "="); -++ if (val == NULL) { -++ rc = BOOTENV_EBADENTRY; -++ goto err; -++ } -++ -++ *val = '\0'; /* split strings */ -++ val++; -++ -++ rc = bootenv_set(env, key, val); -++ -++ err: -++ free(key); -++ return rc; -++} -++ -++int -++bootenv_destroy(bootenv_t* env) -++{ -++ int rc = 0; -++ -++ if (env == NULL || *env == NULL) -++ return -EINVAL; -++ -++ bootenv_t tmp = *env; -++ -++ rc = hashmap_free(tmp->map); -++ if (rc != 0) -++ return rc; -++ -++ free(tmp); -++ return rc; -++} -++ -++int -++bootenv_create(bootenv_t* env) -++{ -++ bootenv_t res; -++ res = (bootenv_t) calloc(1, sizeof(struct bootenv)); -++ -++ if (res == NULL) -++ return -ENOMEM; -++ -++ res->map = hashmap_new(); -++ -++ if (res->map == NULL) { -++ free(res); -++ return -ENOMEM; -++ } -++ -++ *env = res; -++ -++ return 0; -++} -++ -++ -++/** -++ * @brief Read a formatted buffer and scan it for valid bootenv -++ * key/value pairs. Add those pairs into a hashmap. -++ * @param env Hashmap which shall be used to hold the data. -++ * @param buf Formatted buffer. -++ * @param size Size of the buffer. -++ * @return 0 -++ * @return or error -++ */ -++static int -++rd_buffer(bootenv_t env, const char *buf, size_t size) -++{ -++ const char *curr = buf; /* ptr to current key/value pair */ -++ uint32_t i, j; /* current length, chars processed */ -++ -++ if (buf[size - 1] != '\0') /* must end in '\0' */ -++ return BOOTENV_EFMT; -++ -++ for (j = 0; j < size; j += i, curr += i) { -++ /* strlen returns the size of the string upto -++ but not including the null terminator; -++ adding 1 to account for '\0' */ -++ i = strlen(curr) + 1; -++ -++ if (i == 1) -++ return 0; /* no string found */ -++ -++ if (extract_pair(curr, env) != 0) -++ return BOOTENV_EINVAL; -++ } -++ -++ return 0; -++} -++ -++ -++int -++bootenv_read_crc(FILE* fp, bootenv_t env, size_t size, uint32_t* ret_crc) -++{ -++ int rc; -++ char *buf = NULL; -++ size_t i = 0; -++ uint32_t crc32_table[256]; -++ -++ if ((fp == NULL) || (env == NULL)) -++ return -EINVAL; -++ -++ /* allocate temp buffer */ -++ buf = (char*) calloc(1, size * sizeof(char)); -++ if (buf == NULL) -++ return -ENOMEM; -++ -++ /* FIXME Andreas, please review this I removed size-1 and -++ * replaced it by just size, I saw the kernel image starting -++ * with a 0x0060.... and not with the 0x60.... what it should -++ * be. Is this a tools problem or is it a problem here where -++ * fp is moved not to the right place due to the former size-1 -++ * here. -++ */ -++ while((i < size) && (!feof(fp))) { -++ int c = fgetc(fp); -++ if (c == EOF) { -++ /* FIXME isn't this dangerous, to update -++ the boot envs with incomplete data? */ -++ buf[i++] = '\0'; -++ break; /* we have enough */ -++ } -++ if (ferror(fp)) { -++ rc = -EIO; -++ goto err; -++ } -++ -++ buf[i++] = (char)c; -++ } -++ -++ /* calculate crc to return */ -++ if (ret_crc != NULL) { -++ init_crc32_table(crc32_table); -++ *ret_crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, size); -++ } -++ -++ /* transfer to hashmap */ -++ rc = rd_buffer(env, buf, size); -++ -++err: -++ free(buf); -++ return rc; -++} -++ -++ -++/** -++ * If we have a single file containing the boot-parameter size should -++ * be specified either as the size of the file or as BOOTENV_MAXSIZE. -++ * If the bootparameter are in the middle of a file we need the exact -++ * length of the data. -++ */ -++int -++bootenv_read(FILE* fp, bootenv_t env, size_t size) -++{ -++ return bootenv_read_crc(fp, env, size, NULL); -++} -++ -++ -++int -++bootenv_read_txt(FILE* fp, bootenv_t env) -++{ -++ int rc = 0; -++ char *buf = NULL; -++ char *line = NULL; -++ char *lstart = NULL; -++ char *curr = NULL; -++ size_t len; -++ size_t size; -++ -++ if ((fp == NULL) || (env == NULL)) -++ return -EINVAL; -++ -++ size = BOOTENV_MAXSIZE; -++ -++ /* allocate temp buffers */ -++ buf = (char*) calloc(1, size * sizeof(char)); -++ lstart = line = (char*) calloc(1, size * sizeof(char)); -++ if ((buf == NULL) || (line == NULL)) { -++ rc = -ENOMEM; -++ goto err; -++ } -++ -++ curr = buf; -++ while ((line = fgets(line, size, fp)) != NULL) { -++ if (is_ws(line, size)) { -++ continue; -++ } -++ rc = remove_lf(line, BOOTENV_MAXSIZE, fp); -++ if (rc != 0) { -++ goto err; -++ } -++ -++ /* copy new line to binary buffer */ -++ len = strlen(line); -++ if (len > size) { -++ rc = -EFBIG; -++ goto err; -++ } -++ size -= len; /* track remaining space */ -++ -++ memcpy(curr, line, len); -++ curr += len + 1; /* for \0 seperator */ -++ } -++ -++ rc = rd_buffer(env, buf, BOOTENV_MAXSIZE); -++err: -++ if (buf != NULL) -++ free(buf); -++ if (lstart != NULL) -++ free(lstart); -++ return rc; -++} -++ -++static int -++fill_output_buffer(bootenv_t env, char *buf, size_t buf_size_max ubi_unused, -++ size_t *written) -++{ -++ int rc = 0; -++ size_t keys_size, i; -++ size_t wr = 0; -++ const char **keys = NULL; -++ const char *val = NULL; -++ -++ rc = bootenv_get_key_vector(env, &keys_size, 1, &keys); -++ if (rc != 0) -++ goto err; -++ -++ for (i = 0; i < keys_size; i++) { -++ if (wr > BOOTENV_MAXSIZE) { -++ rc = -ENOSPC; -++ goto err; -++ } -++ -++ rc = bootenv_get(env, keys[i], &val); -++ if (rc != 0) -++ goto err; -++ -++ wr += snprintf(buf + wr, BOOTENV_MAXSIZE - wr, -++ "%s=%s", keys[i], val); -++ wr++; /* for \0 */ -++ } -++ -++ *written = wr; -++ -++err: -++ if (keys != NULL) -++ free(keys); -++ -++ return rc; -++} -++ -++int -++bootenv_write_crc(FILE* fp, bootenv_t env, uint32_t* ret_crc) -++{ -++ int rc = 0; -++ size_t size = 0; -++ char *buf = NULL; -++ uint32_t crc32_table[256]; -++ -++ if ((fp == NULL) || (env == NULL)) -++ return -EINVAL; -++ -++ buf = (char*) calloc(1, BOOTENV_MAXSIZE * sizeof(char)); -++ if (buf == NULL) -++ return -ENOMEM; -++ -++ -++ rc = fill_output_buffer(env, buf, BOOTENV_MAXSIZE, &size); -++ if (rc != 0) -++ goto err; -++ -++ /* calculate crc to return */ -++ if (ret_crc != NULL) { -++ init_crc32_table(crc32_table); -++ *ret_crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, size); -++ } -++ -++ if (fwrite(buf, size, 1, fp) != 1) { -++ rc = -EIO; -++ goto err; -++ } -++ -++err: -++ if (buf != NULL) -++ free(buf); -++ return rc; -++} -++ -++int -++bootenv_write(FILE* fp, bootenv_t env) -++{ -++ return bootenv_write_crc(fp, env, NULL); -++} -++ -++int -++bootenv_compare(bootenv_t first, bootenv_t second) -++{ -++ int rc; -++ size_t written_first, written_second; -++ char *buf_first, *buf_second; -++ -++ if (first == NULL || second == NULL) -++ return -EINVAL; -++ -++ buf_first = malloc(BOOTENV_MAXSIZE); -++ if (!buf_first) -++ return -ENOMEM; -++ buf_second = malloc(BOOTENV_MAXSIZE); -++ if (!buf_second) { -++ rc = -ENOMEM; -++ goto err; -++ } -++ -++ rc = fill_output_buffer(first, buf_first, BOOTENV_MAXSIZE, -++ &written_first); -++ if (rc < 0) -++ goto err; -++ rc = fill_output_buffer(second, buf_second, BOOTENV_MAXSIZE, -++ &written_second); -++ if (rc < 0) -++ goto err; -++ -++ if (written_first != written_second) { -++ rc = 1; -++ goto err; -++ } -++ -++ rc = memcmp(buf_first, buf_second, written_first); -++ if (rc != 0) { -++ rc = 2; -++ goto err; -++ } -++ -++err: -++ if (buf_first) -++ free(buf_first); -++ if (buf_second) -++ free(buf_second); -++ -++ return rc; -++} -++ -++int -++bootenv_size(bootenv_t env, size_t *size) -++{ -++ int rc = 0; -++ char *buf = NULL; -++ -++ if (env == NULL) -++ return -EINVAL; -++ -++ buf = (char*) calloc(1, BOOTENV_MAXSIZE * sizeof(char)); -++ if (buf == NULL) -++ return -ENOMEM; -++ -++ rc = fill_output_buffer(env, buf, BOOTENV_MAXSIZE, size); -++ if (rc != 0) -++ goto err; -++ -++err: -++ if (buf != NULL) -++ free(buf); -++ return rc; -++} -++ -++int -++bootenv_write_txt(FILE* fp, bootenv_t env) -++{ -++ int rc = 0; -++ size_t size, wr, i; -++ const char **keys = NULL; -++ const char *key = NULL; -++ const char *val = NULL; -++ -++ if ((fp == NULL) || (env == NULL)) -++ return -EINVAL; -++ -++ rc = bootenv_get_key_vector(env, &size, 1, &keys); -++ if (rc != 0) -++ goto err; -++ -++ for (i = 0; i < size; i++) { -++ key = keys[i]; -++ rc = bootenv_get(env, key, &val); -++ if (rc != 0) -++ goto err; -++ -++ wr = fprintf(fp, "%s=%s\n", key, val); -++ if (wr != strlen(key) + strlen(val) + 2) { -++ rc = -EIO; -++ goto err; -++ } -++ } -++ -++err: -++ if (keys != NULL) -++ free(keys); -++ return rc; -++} -++ -++int -++bootenv_valid(bootenv_t env ubi_unused) -++{ -++ /* @FIXME No sanity check implemented. */ -++ return 0; -++} -++ -++int -++bootenv_copy_bootenv(bootenv_t in, bootenv_t *out) -++{ -++ int rc = 0; -++ const char *tmp = NULL; -++ const char **keys = NULL; -++ size_t vec_size, i; -++ -++ if ((in == NULL) || (out == NULL)) -++ return -EINVAL; -++ -++ /* purge output var for sure... */ -++ rc = bootenv_destroy(out); -++ if (rc != 0) -++ return rc; -++ -++ /* create the new map */ -++ rc = bootenv_create(out); -++ if (rc != 0) -++ goto err; -++ -++ /* get the key list from the input map */ -++ rc = bootenv_get_key_vector(in, &vec_size, 0, &keys); -++ if (rc != 0) -++ goto err; -++ -++ if (vec_size != hashmap_size(in->map)) { -++ rc = BOOTENV_ECOPY; -++ goto err; -++ } -++ -++ /* make a deep copy of the hashmap */ -++ for (i = 0; i < vec_size; i++) { -++ rc = bootenv_get(in, keys[i], &tmp); -++ if (rc != 0) -++ goto err; -++ -++ rc = bootenv_set(*out, keys[i], tmp); -++ if (rc != 0) -++ goto err; -++ } -++ -++err: -++ if (keys != NULL) -++ free(keys); -++ -++ return rc; -++} -++ -++/* ------------------------------------------------------------------------- */ -++ -++ -++int -++bootenv_pdd_keep(bootenv_t env_old, bootenv_t env_new, bootenv_t *env_res, -++ int *warnings, char *err_buf ubi_unused, -++ size_t err_buf_size ubi_unused) -++{ -++ bootenv_list_t l_old = NULL; -++ bootenv_list_t l_new = NULL; -++ const char *pdd_old = NULL; -++ const char *pdd_new = NULL; -++ const char *tmp = NULL; -++ const char **vec_old = NULL; -++ const char **vec_new = NULL; -++ const char **pdd_up_vec = NULL; -++ size_t vec_old_size, vec_new_size, pdd_up_vec_size, i; -++ int rc = 0; -++ -++ if ((env_old == NULL) || (env_new == NULL) || (env_res == NULL)) -++ return -EINVAL; -++ -++ /* get the pdd strings, e.g.: -++ * pdd_old=a,b,c -++ * pdd_new=a,c,d,e */ -++ rc = bootenv_get(env_old, "pdd", &pdd_old); -++ if (rc != 0) -++ goto err; -++ rc = bootenv_get(env_new, "pdd", &pdd_new); -++ if (rc != 0) -++ goto err; -++ -++ /* put it into a list and then convert it to an vector */ -++ rc = bootenv_list_create(&l_old); -++ if (rc != 0) -++ goto err; -++ rc = bootenv_list_create(&l_new); -++ if (rc != 0) -++ goto err; -++ -++ rc = bootenv_list_import(l_old, pdd_old); -++ if (rc != 0) -++ goto err; -++ -++ rc = bootenv_list_import(l_new, pdd_new); -++ if (rc != 0) -++ goto err; -++ -++ rc = bootenv_list_to_vector(l_old, &vec_old_size, &vec_old); -++ if (rc != 0) -++ goto err; -++ -++ rc = bootenv_list_to_vector(l_new, &vec_new_size, &vec_new); -++ if (rc != 0) -++ goto err; -++ -++ rc = bootenv_copy_bootenv(env_new, env_res); -++ if (rc != 0) -++ goto err; -++ -++ /* calculate the update vector between the old and new pdd */ -++ pdd_up_vec = hashmap_get_update_key_vector(vec_old, vec_old_size, -++ vec_new, vec_new_size, &pdd_up_vec_size); -++ -++ if (pdd_up_vec == NULL) { -++ rc = -ENOMEM; -++ goto err; -++ } -++ -++ if (pdd_up_vec_size != 0) { -++ /* need to warn the user about the unset of -++ * some pdd/bootenv values */ -++ *warnings = BOOTENV_WPDD_STRING_DIFFERS; -++ -++ /* remove all entries in the new bootenv load */ -++ for (i = 0; i < pdd_up_vec_size; i++) { -++ bootenv_unset(*env_res, pdd_up_vec[i]); -++ } -++ } -++ -++ /* generate the keep array and copy old pdd values to new bootenv */ -++ for (i = 0; i < vec_old_size; i++) { -++ rc = bootenv_get(env_old, vec_old[i], &tmp); -++ if (rc != 0) { -++ rc = BOOTENV_EPDDINVAL; -++ goto err; -++ } -++ rc = bootenv_set(*env_res, vec_old[i], tmp); -++ if (rc != 0) { -++ goto err; -++ } -++ } -++ /* put the old pdd string into the result map */ -++ rc = bootenv_set(*env_res, "pdd", pdd_old); -++ if (rc != 0) { -++ goto err; -++ } -++ -++ -++err: -++ if (vec_old != NULL) -++ free(vec_old); -++ if (vec_new != NULL) -++ free(vec_new); -++ if (pdd_up_vec != NULL) -++ free(pdd_up_vec); -++ -++ bootenv_list_destroy(&l_old); -++ bootenv_list_destroy(&l_new); -++ return rc; -++} -++ -++ -++int -++bootenv_pdd_overwrite(bootenv_t env_old, bootenv_t env_new, -++ bootenv_t *env_res, int *warnings ubi_unused, -++ char *err_buf ubi_unused, size_t err_buf_size ubi_unused) -++{ -++ if ((env_old == NULL) || (env_new == NULL) || (env_res == NULL)) -++ return -EINVAL; -++ -++ return bootenv_copy_bootenv(env_new, env_res); -++} -++ -++int -++bootenv_pdd_merge(bootenv_t env_old, bootenv_t env_new, bootenv_t *env_res, -++ int *warnings ubi_unused, char *err_buf, size_t err_buf_size) -++{ -++ if ((env_old == NULL) || (env_new == NULL) || (env_res == NULL)) -++ return -EINVAL; -++ -++ snprintf(err_buf, err_buf_size, "The PDD merge operation is not " -++ "implemented. Contact: "); -++ -++ return BOOTENV_ENOTIMPL; -++} -++ -++/* ------------------------------------------------------------------------- */ -++ -++int -++bootenv_get(bootenv_t env, const char *key, const char **value) -++{ -++ if (env == NULL) -++ return -EINVAL; -++ -++ *value = hashmap_lookup(env->map, key); -++ if (*value == NULL) -++ return BOOTENV_ENOTFOUND; -++ -++ return 0; -++} -++ -++int -++bootenv_get_num(bootenv_t env, const char *key, uint32_t *value) -++{ -++ char *endptr = NULL; -++ const char *str; -++ -++ if (env == NULL) -++ return 0; -++ -++ str = hashmap_lookup(env->map, key); -++ if (!str) -++ return -EINVAL; -++ -++ *value = strtoul(str, &endptr, 0); -++ -++ if (*endptr == '\0') { -++ return 0; -++ } -++ -++ return -EINVAL; -++} -++ -++int -++bootenv_set(bootenv_t env, const char *key, const char *value) -++{ -++ if (env == NULL) -++ return -EINVAL; -++ -++ return hashmap_add(env->map, key, value); -++} -++ -++int -++bootenv_unset(bootenv_t env, const char *key) -++{ -++ if (env == NULL) -++ return -EINVAL; -++ -++ return hashmap_remove(env->map, key); -++} -++ -++int -++bootenv_get_key_vector(bootenv_t env, size_t* size, int sort, -++ const char ***vector) -++{ -++ if ((env == NULL) || (size == NULL)) -++ return -EINVAL; -++ -++ *vector = hashmap_get_key_vector(env->map, size, sort); -++ -++ if (*vector == NULL) -++ return -EINVAL; -++ -++ return 0; -++} -++ -++int -++bootenv_dump(bootenv_t env) -++{ -++ if (env == NULL) -++ return -EINVAL; -++ -++ return hashmap_dump(env->map); -++} -++ -++int -++bootenv_list_create(bootenv_list_t *list) -++{ -++ bootenv_list_t res; -++ res = (bootenv_list_t) calloc(1, sizeof(struct bootenv_list)); -++ -++ if (res == NULL) -++ return -ENOMEM; -++ -++ res->head = hashmap_new(); -++ -++ if (res->head == NULL) { -++ free(res); -++ return -ENOMEM; -++ } -++ -++ *list = res; -++ return 0; -++} -++ -++int -++bootenv_list_destroy(bootenv_list_t *list) -++{ -++ int rc = 0; -++ -++ if (list == NULL) -++ return -EINVAL; -++ -++ bootenv_list_t tmp = *list; -++ if (tmp == 0) -++ return 0; -++ -++ rc = hashmap_free(tmp->head); -++ if (rc != 0) -++ return rc; -++ -++ free(tmp); -++ *list = NULL; -++ return 0; -++} -++ -++int -++bootenv_list_import(bootenv_list_t list, const char *str) -++{ -++ if (list == NULL) -++ return -EINVAL; -++ -++ return build_list_definition(list->head, str); -++} -++ -++int -++bootenv_list_export(bootenv_list_t list, char **string) -++{ -++ size_t size, i, j, bufsize, tmp, rc = 0; -++ const char **items; -++ -++ if (list == NULL) -++ return -EINVAL; -++ -++ bufsize = BOOTENV_MAXLINE; -++ char *res = (char*) malloc(bufsize * sizeof(char)); -++ if (res == NULL) -++ return -ENOMEM; -++ -++ rc = bootenv_list_to_vector(list, &size, &items); -++ if (rc != 0) { -++ goto err; -++ } -++ -++ j = 0; -++ for (i = 0; i < size; i++) { -++ tmp = strlen(items[i]); -++ if (j >= bufsize) { -++ bufsize += BOOTENV_MAXLINE; -++ res = (char*) realloc(res, bufsize * sizeof(char)); -++ if (res == NULL) { -++ rc = -ENOMEM; -++ goto err; -++ } -++ } -++ memcpy(res + j, items[i], tmp); -++ j += tmp; -++ if (i < (size - 1)) { -++ res[j] = ','; -++ j++; -++ } -++ } -++ j++; -++ res[j] = '\0'; -++ free(items); -++ *string = res; -++ return 0; -++err: -++ free(items); -++ return rc; -++} -++ -++int -++bootenv_list_add(bootenv_list_t list, const char *item) -++{ -++ if ((list == NULL) || (item == NULL)) -++ return -EINVAL; -++ -++ return hashmap_add(list->head, item, ""); -++} -++ -++int -++bootenv_list_remove(bootenv_list_t list, const char *item) -++{ -++ if ((list == NULL) || (item == NULL)) -++ return -EINVAL; -++ -++ return hashmap_remove(list->head, item); -++} -++ -++int -++bootenv_list_is_in(bootenv_list_t list, const char *item) -++{ -++ if ((list == NULL) || (item == NULL)) -++ return -EINVAL; -++ -++ return hashmap_lookup(list->head, item) != NULL ? 1 : 0; -++} -++ -++int -++bootenv_list_to_vector(bootenv_list_t list, size_t *size, const char ***vector) -++{ -++ if ((list == NULL) || (size == NULL)) -++ return -EINVAL; -++ -++ *vector = hashmap_get_key_vector(list->head, size, 1); -++ if (*vector == NULL) -++ return -ENOMEM; -++ -++ return 0; -++} -++ -++int -++bootenv_list_to_num_vector(bootenv_list_t list, size_t *size, -++ uint32_t **vector) -++{ -++ int rc = 0; -++ size_t i; -++ uint32_t* res = NULL; -++ char *endptr = NULL; -++ const char **a = NULL; -++ -++ rc = bootenv_list_to_vector(list, size, &a); -++ if (rc != 0) -++ goto err; -++ -++ res = (uint32_t*) malloc (*size * sizeof(uint32_t)); -++ if (!res) -++ goto err; -++ -++ for (i = 0; i < *size; i++) { -++ res[i] = strtoul(a[i], &endptr, 0); -++ if (*endptr != '\0') -++ goto err; -++ } -++ -++ if (a) -++ free(a); -++ *vector = res; -++ return 0; -++ -++err: -++ if (a) -++ free(a); -++ if (res) -++ free(res); -++ return rc; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/bootenv.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/bootenv.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/bootenv.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/bootenv.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,434 @@ -++#ifndef __BOOTENV_H__ -++#define __BOOTENV_H__ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++#include /* FILE */ -++#include -++#include -++ -++/* DOXYGEN DOCUMENTATION */ -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++/** -++ * @file bootenv.h -++ * @author oliloh@de.ibm.com -++ * @version 1.3 -++ * -++ * 1.3 Some renaming -++ */ -++ -++/** -++ * @mainpage Usage -++ * -++ * @section intro Introduction -++ * This library provides all functionality to handle with the so-called -++ * platform description data (PDD) and the bootparameters defined in -++ * U-Boot. It is able to apply the defined PDD operations in PDD update -++ * scenarios. For more information about the PDD and bootparameter -++ * environment "bootenv" confer the PDD documentation. -++ * -++ * @section ret Return codes -++ * This library defines some return codes which will be delivered classified -++ * as warnings or errors. See the "Defines" section for details and numeric -++ * values. -++ * -++ * @section benv Bootenv format description -++ * There are two different input formats: -++ * - text files -++ * - binary files -++ * -++ * @subsection txt Text Files -++ * Text files have to be specified like: -++ * @verbatim key1=value1,value2,value7\n key2=value55,value1\n key4=value1\n@endverbatim -++ * -++ * @subsection bin Binary files -++ * Binary files have to be specified like: -++ * @verbatimkey1=value1,value2,value7\0key2=value55,value1\0... @endverbatim -++ * You can confer the U-Boot documentation for more details. -++ * -++ * @section benvlists Bootenv lists format description. -++ * Values referenced in the preceeding subsection can be -++ * defined like lists: -++ * @verbatim value1,value2,value3 @endverbatim -++ * There are some situation where a conversion of a comma -++ * seperated list can be useful, e.g. to get a list -++ * of defined PDD entries. -++ */ -++ -++#define BOOTENV_MAXSIZE (1024 * 100) /* max 100kiB space for bootenv */ -++ -++/** -++ * @def BOOTENV_ECRC -++ * @brief Given binary file is to large. -++ * @def BOOTENV_EFMT -++ * @brief Given bootenv section has an invalid format -++ * @def BOOTENV_EBADENTRY -++ * @brief Bad entry in the bootenv section. -++ * @def BOOTENV_EINVAL -++ * @brief Invalid bootenv defintion. -++ * @def BOOTENV_ENOPDD -++ * @brief Given bootenv sectoin has no PDD defintion string (pdd=...). -++ * @def BOOTENV_EPDDINVAL -++ * @brief Given bootenv section has an invalid PDD defintion. -++ * @def BOOTENV_ENOTIMPL -++ * @brief Functionality not implemented. -++ * @def BOOTENV_ECOPY -++ * @brief Bootenv memory copy error -++ * @def BOOTENV_ENOTFOUND -++ * @brief Given key has has no value. -++ * @def BOOTENV_EMAX -++ * @brief Highest error value. -++ */ -++#define BOOTENV_ETOOBIG 1 -++#define BOOTENV_EFMT 2 -++#define BOOTENV_EBADENTRY 3 -++#define BOOTENV_EINVAL 4 -++#define BOOTENV_ENOPDD 5 -++#define BOOTENV_EPDDINVAL 6 -++#define BOOTENV_ENOTIMPL 7 -++#define BOOTENV_ECOPY 8 -++#define BOOTENV_ENOTFOUND 9 -++#define BOOTENV_EMAX 10 -++ -++/** -++ * @def BOOTENV_W -++ * @brief A warning which is handled internally as an error -++ * but can be recovered by manual effort. -++ * @def BOOTENV_WPDD_STRING_DIFFERS -++ * @brief The PDD strings of old and new PDD differ and -++ * can cause update problems, because new PDD values -++ * are removed from the bootenv section completely. -++ */ -++#define BOOTENV_W 20 -++#define BOOTENV_WPDD_STRING_DIFFERS 21 -++#define BOOTENV_WMAX 22 /* highest warning value */ -++ -++ -++typedef struct bootenv *bootenv_t; -++ /**< A bootenv library handle. */ -++ -++typedef struct bootenv_list *bootenv_list_t; -++ /**< A handle for a value list. */ -++ -++typedef int(*pdd_func_t)(bootenv_t, bootenv_t, bootenv_t*, -++ int*, char*, size_t); -++ -++ -++/** -++ * @brief Get a new handle. -++ * @return 0 -++ * @return or error -++ * */ -++int bootenv_create(bootenv_t *env); -++ -++/** -++ * @brief Cleanup structure. -++ * @param env Bootenv structure which shall be destroyed. -++ * @return 0 -++ * @return or error -++ */ -++int bootenv_destroy(bootenv_t *env); -++ -++/** -++ * @brief Copy a bootenv handle. -++ * @param in The input bootenv. -++ * @param out The copied output bootenv. Discards old data. -++ * @return 0 -++ * @return or error -++ */ -++int bootenv_copy_bootenv(bootenv_t in, bootenv_t *out); -++ -++/** -++ * @brief Looks for a value inside the bootenv data. -++ * @param env Handle to a bootenv structure. -++ * @param key The key. -++ * @return NULL key not found -++ * @return !NULL ptr to value -++ */ -++int bootenv_get(bootenv_t env, const char *key, const char **value); -++ -++ -++/** -++ * @brief Looks for a value inside the bootenv data and converts it to num. -++ * @param env Handle to a bootenv structure. -++ * @param key The key. -++ * @param value A pointer to the resulting numerical value -++ * @return NULL key not found -++ * @return !NULL ptr to value -++ */ -++int bootenv_get_num(bootenv_t env, const char *key, uint32_t *value); -++ -++/** -++ * @brief Set a bootenv value by key. -++ * @param env Handle to a bootenv structure. -++ * @param key Key. -++ * @param value Value to set. -++ * @return 0 -++ * @return or error -++ */ -++int bootenv_set(bootenv_t env, const char *key, const char *value); -++ -++/** -++ * @brief Remove the given key (and its value) from a bootenv structure. -++ * @param env Handle to a bootenv structure. -++ * @param key Key. -++ * @return 0 -++ * @return or error -++ */ -++int bootenv_unset(bootenv_t env, const char *key); -++ -++ -++/** -++ * @brief Get a vector of all keys which are currently set -++ * within a bootenv handle. -++ * @param env Handle to a bootenv structure. -++ * @param size The size of the allocated array structure. -++ * @param sort Flag, if set the vector is sorted ascending. -++ * @return NULL on error. -++ * @return !NULL a pointer to the first element the allocated vector. -++ * @warning Free the allocate memory yourself! -++ */ -++int bootenv_get_key_vector(bootenv_t env, size_t *size, int sort, -++ const char ***vector); -++ -++/** -++ * @brief Calculate the size in bytes which are necessary to write the -++ * current bootenv section in a *binary file. -++ * @param env bootenv handle. -++ * @param size The size in bytes of the bootenv handle. -++ * @return 0 -++ * @return or ERROR. -++ */ -++int bootenv_size(bootenv_t env, size_t *size); -++ -++/** -++ * @brief Read a binary bootenv file. -++ * @param fp File pointer to input stream. -++ * @param env bootenv handle. -++ * @param size maximum data size. -++ * @return 0 -++ * @return or ERROR. -++ */ -++int bootenv_read(FILE* fp, bootenv_t env, size_t size); -++ -++/** -++ * @param ret_crc return value of crc of read data -++ */ -++int bootenv_read_crc(FILE* fp, bootenv_t env, size_t size, uint32_t *ret_crc); -++ -++/** -++ * @brief Read bootenv data from an text/ascii file. -++ * @param fp File pointer to ascii PDD file. -++ * @param env bootenv handle -++ * @return 0 -++ * @return or ERROR. -++ */ -++int bootenv_read_txt(FILE* fp, bootenv_t env); -++ -++/** -++ * @brief Write a bootenv structure to the given location (binary). -++ * @param fp Filepointer to binary file. -++ * @param env Bootenv structure which shall be written. -++ * @return 0 -++ * @return or error -++ */ -++int bootenv_write(FILE* fp, bootenv_t env); -++ -++/** -++ * @param ret_crc return value of crc of read data -++ */ -++int bootenv_write_crc(FILE* fp, bootenv_t env, uint32_t* ret_crc); -++ -++/** -++ * @brief Write a bootenv structure to the given location (text). -++ * @param fp Filepointer to text file. -++ * @param env Bootenv structure which shall be written. -++ * @return 0 -++ * @return or error -++ */ -++int bootenv_write_txt(FILE* fp, bootenv_t env); -++ -++/** -++ * @brief Compare bootenvs using memcmp(). -++ * @param first First bootenv. -++ * @param second Second bootenv. -++ * @return 0 if bootenvs are equal -++ * @return < 0 if error -++ * @return > 0 if unequal -++ */ -++int bootenv_compare(bootenv_t first, bootenv_t second); -++ -++/** -++ * @brief Prototype for a PDD handling funtion -++ */ -++ -++/** -++ * @brief The PDD keep operation. -++ * @param env_old The old bootenv structure. -++ * @param env_new The new bootenv structure. -++ * @param env_res The result of PDD keep. -++ * @param warnings A flag which marks any warnings. -++ * @return 0 -++ * @return or error -++ * @note For a complete documentation about the algorithm confer the -++ * PDD documentation. -++ */ -++int bootenv_pdd_keep(bootenv_t env_old, bootenv_t env_new, -++ bootenv_t *env_res, int *warnings, -++ char *err_buf, size_t err_buf_size); -++ -++ -++/** -++ * @brief The PDD merge operation. -++ * @param env_old The old bootenv structure. -++ * @param env_new The new bootenv structure. -++ * @param env_res The result of merge-pdd. -++ * @param warnings A flag which marks any warnings. -++ * @return 0 -++ * @return or error -++ * @note For a complete documentation about the algorithm confer the -++ * PDD documentation. -++ */ -++int bootenv_pdd_merge(bootenv_t env_old, bootenv_t env_new, -++ bootenv_t *env_res, int *warnings, -++ char *err_buf, size_t err_buf_size); -++ -++/** -++ * @brief The PDD overwrite operation. -++ * @param env_old The old bootenv structure. -++ * @param env_new The new bootenv structure. -++ * @param env_res The result of overwrite-pdd. -++ * @param warnings A flag which marks any warnings. -++ * @return 0 -++ * @return or error -++ * @note For a complete documentation about the algorithm confer the -++ * PDD documentation. -++ */ -++int bootenv_pdd_overwrite(bootenv_t env_new, -++ bootenv_t env_old, bootenv_t *env_res, int *warnings, -++ char *err_buf, size_t err_buf_size); -++ -++/** -++ * @brief Dump a bootenv structure to stdout. (Debug) -++ * @param env Handle to a bootenv structure. -++ * @return 0 -++ * @return or error -++ */ -++int bootenv_dump(bootenv_t env); -++ -++/** -++ * @brief Validate a bootenv structure. -++ * @param env Handle to a bootenv structure. -++ * @return 0 -++ * @return or error -++ */ -++int bootenv_valid(bootenv_t env); -++ -++/** -++ * @brief Create a new bootenv list structure. -++ * @return NULL on error -++ * @return or a new list handle. -++ * @note This structure is used to store values in a list. -++ * A useful addition when handling PDD strings. -++ */ -++int bootenv_list_create(bootenv_list_t *list); -++ -++/** -++ * @brief Destroy a bootenv list structure -++ * @param list Handle to a bootenv list structure. -++ * @return 0 -++ * @return or error -++ */ -++int bootenv_list_destroy(bootenv_list_t *list); -++ -++/** -++ * @brief Import a list from a comma seperated string -++ * @param list Handle to a bootenv list structure. -++ * @param str Comma seperated string list. -++ * @return 0 -++ * @return or error -++ */ -++int bootenv_list_import(bootenv_list_t list, const char *str); -++ -++/** -++ * @brief Export a list to a string of comma seperated values. -++ * @param list Handle to a bootenv list structure. -++ * @return NULL one error -++ * @return or pointer to a newly allocated string. -++ * @warning Free the allocated memory by yourself! -++ */ -++int bootenv_list_export(bootenv_list_t list, char **string); -++ -++/** -++ * @brief Add an item to the list. -++ * @param list A handle of a list structure. -++ * @param item An item. -++ * @return 0 -++ * @return or error -++ */ -++int bootenv_list_add(bootenv_list_t list, const char *item); -++ -++/** -++ * @brief Remove an item from the list. -++ * @param list A handle of a list structure. -++ * @param item An item. -++ * @return 0 -++ * @return or error -++ */ -++int bootenv_list_remove(bootenv_list_t list, const char *item); -++ -++/** -++ * @brief Check if a given item is in a given list. -++ * @param list A handle of a list structure. -++ * @param item An item. -++ * @return 1 Item is in list. -++ * @return 0 Item is not in list. -++ */ -++int bootenv_list_is_in(bootenv_list_t list, const char *item); -++ -++ -++/** -++ * @brief Convert a list into a vector of all values inside the list. -++ * @param list Handle to a bootenv structure. -++ * @param size The size of the allocated vector structure. -++ * @return 0 -++ * @return or error -++ * @warning Free the allocate memory yourself! -++ */ -++int bootenv_list_to_vector(bootenv_list_t list, size_t *size, -++ const char ***vector); -++ -++/** -++ * @brief Convert a list into a vector of all values inside the list. -++ * @param list Handle to a bootenv structure. -++ * @param size The size of the allocated vector structure. -++ * @return 0 -++ * @return or error -++ * @warning Free the allocate memory yourself! -++ */ -++int bootenv_list_to_num_vector(bootenv_list_t list, size_t *size, -++ uint32_t **vector); -++ -++#ifdef __cplusplus -++} -++#endif -++#endif /*__BOOTENV_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/config.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/config.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/config.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/config.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,28 @@ -++#ifndef __CONFIG_H__ -++#define __CONFIG_H__ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Frank Haverkamp -++ */ -++ -++#define PACKAGE_BUGREPORT \ -++ "haver@vnet.ibm.com, dedekind@linutronix.de, or tglx@linutronix.de" -++ -++#define ubi_unused __attribute__((unused)) -++ -++#endif -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/crc32.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/crc32.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/crc32.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/crc32.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,83 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Thomas Gleixner -++ */ -++ -++/* -++ * CRC32 functions -++ * -++ * Can be compiled as seperate object, but is included into the ipl source -++ * so gcc can inline the functions. We optimize for size so the omission of -++ * the function frame is helpful. -++ * -++ */ -++ -++#include -++#include -++ -++/* CRC polynomial */ -++#define CRC_POLY 0xEDB88320 -++ -++/** -++ * init_crc32_table - Initialize crc table -++ * -++ * @table: pointer to the CRC table which must be initialized -++ * -++ * Create CRC32 table for given polynomial. The table is created with -++ * the lowest order term in the highest order bit. So the x^32 term -++ * has to implied in the crc calculation function. -++ */ -++void init_crc32_table(uint32_t *table) -++{ -++ uint32_t crc; -++ int i, j; -++ -++ for (i = 0; i < 256; i++) { -++ crc = i; -++ for (j = 8; j > 0; j--) { -++ if (crc & 1) -++ crc = (crc >> 1) ^ CRC_POLY; -++ else -++ crc >>= 1; -++ } -++ table[i] = crc; -++ } -++} -++ -++/** -++ * clc_crc32 - Calculate CRC32 over a buffer -++ * -++ * @table: pointer to the CRC table -++ * @crc: initial crc value -++ * @buf: pointer to the buffer -++ * @len: number of bytes to calc -++ * -++ * Returns the updated crc value. -++ * -++ * The algorithm resembles a hardware shift register, but calculates 8 -++ * bit at once. -++ */ -++uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf, -++ int len) -++{ -++ const unsigned char *p = buf; -++ -++ while(--len >= 0) -++ crc = table[(crc ^ *p++) & 0xff] ^ (crc >> 8); -++ return crc; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/crc32.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/crc32.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/crc32.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/crc32.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,36 @@ -++#ifndef __CRC32_H__ -++#define __CRC32_H__ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * Author: Thomas Gleixner -++ * -++ * CRC32 functions -++ * -++ * Can be compiled as seperate object, but is included into the ipl source -++ * so gcc can inline the functions. We optimize for size so the omission of -++ * the function frame is helpful. -++ * -++ */ -++#include -++ -++void init_crc32_table(uint32_t *table); -++uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf, int len); -++ -++#endif /* __CRC32_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/eb_chain.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/eb_chain.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/eb_chain.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/eb_chain.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,281 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006, 2007 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * Author: Drake Dowsett, dowsett@de.ibm.com -++ * Contact: Andreas Arnez, arnez@de.ibm.com -++ */ -++ -++/* see eb_chain.h */ -++ -++#include -++#include -++#include -++#include -++#include "unubi_analyze.h" -++#include "crc32.h" -++ -++#define COPY(dst, src) \ -++ do { \ -++ dst = malloc(sizeof(*dst)); \ -++ if (dst == NULL) \ -++ return -ENOMEM; \ -++ memcpy(dst, src, sizeof(*dst)); \ -++ } while (0) -++ -++ -++/** -++ * inserts an eb_info into the chain starting at head, then searching -++ * linearly for the correct position; -++ * new should contain valid vid and ec headers and the data_crc should -++ * already have been checked before insertion, otherwise the chain -++ * could be have un an undesired manner; -++ * returns -ENOMEM if alloc fails, otherwise SHOULD always return 0, -++ * if not, the code reached the last line and returned -EAGAIN, -++ * meaning there is a bug or a case not being handled here; -++ **/ -++int -++eb_chain_insert(struct eb_info **head, struct eb_info *new) -++{ -++ uint32_t vol, num, ver; -++ uint32_t new_vol, new_num, new_ver; -++ struct eb_info *prev, *cur, *hist, *ins; -++ struct eb_info **prev_ptr; -++ -++ if ((head == NULL) || (new == NULL)) -++ return 0; -++ -++ if (*head == NULL) { -++ COPY(*head, new); -++ (*head)->next = NULL; -++ return 0; -++ } -++ -++ new_vol = be32_to_cpu(new->vid.vol_id); -++ new_num = be32_to_cpu(new->vid.lnum); -++ new_ver = be32_to_cpu(new->vid.leb_ver); -++ -++ /** TRAVERSE HORIZONTALY **/ -++ -++ cur = *head; -++ prev = NULL; -++ -++ /* traverse until vol_id/lnum align */ -++ vol = be32_to_cpu(cur->vid.vol_id); -++ num = be32_to_cpu(cur->vid.lnum); -++ while ((new_vol > vol) || ((new_vol == vol) && (new_num > num))) { -++ /* insert new at end of chain */ -++ if (cur->next == NULL) { -++ COPY(ins, new); -++ ins->next = NULL; -++ cur->next = ins; -++ return 0; -++ } -++ -++ prev = cur; -++ cur = cur->next; -++ vol = be32_to_cpu(cur->vid.vol_id); -++ num = be32_to_cpu(cur->vid.lnum); -++ } -++ -++ if (prev == NULL) -++ prev_ptr = head; -++ else -++ prev_ptr = &(prev->next); -++ -++ /* insert new into the middle of chain */ -++ if ((new_vol != vol) || (new_num != num)) { -++ COPY(ins, new); -++ ins->next = cur; -++ *prev_ptr = ins; -++ return 0; -++ } -++ -++ /** TRAVERSE VERTICALY **/ -++ -++ hist = cur; -++ prev = NULL; -++ -++ /* traverse until versions align */ -++ ver = be32_to_cpu(cur->vid.leb_ver); -++ while (new_ver < ver) { -++ /* insert new at bottom of history */ -++ if (hist->older == NULL) { -++ COPY(ins, new); -++ ins->next = NULL; -++ ins->older = NULL; -++ hist->older = ins; -++ return 0; -++ } -++ -++ prev = hist; -++ hist = hist->older; -++ ver = be32_to_cpu(hist->vid.leb_ver); -++ } -++ -++ if (prev == NULL) { -++ /* replace active version */ -++ COPY(ins, new); -++ ins->next = hist->next; -++ *prev_ptr = ins; -++ -++ /* place cur in vertical histroy */ -++ ins->older = hist; -++ hist->next = NULL; -++ return 0; -++ } -++ -++ /* insert between versions, beneath active version */ -++ COPY(ins, new); -++ ins->next = NULL; -++ ins->older = prev->older; -++ prev->older = ins; -++ return 0; -++} -++ -++ -++/** -++ * sets the pointer at pos to the position of the first entry in the chain -++ * with of vol_id and, if given, with the same lnum as *lnum; -++ * if there is no entry in the chain, then *pos is NULL on return; -++ * always returns 0; -++ **/ -++int -++eb_chain_position(struct eb_info **head, uint32_t vol_id, uint32_t *lnum, -++ struct eb_info **pos) -++{ -++ uint32_t vol, num; -++ struct eb_info *cur; -++ -++ if ((head == NULL) || (*head == NULL) || (pos == NULL)) -++ return 0; -++ -++ *pos = NULL; -++ -++ cur = *head; -++ while (cur != NULL) { -++ vol = be32_to_cpu(cur->vid.vol_id); -++ num = be32_to_cpu(cur->vid.lnum); -++ -++ if ((vol_id == vol) && ((lnum == NULL) || (*lnum == num))) { -++ *pos = cur; -++ return 0; -++ } -++ -++ cur = cur->next; -++ } -++ -++ return 0; -++} -++ -++ -++/** -++ * prints to stream, the vol_id, lnum and leb_ver for each entry in the -++ * chain, starting at head; -++ * this is intended for debuging purposes; -++ * always returns 0; -++ * -++ * FIXME I do not like the double list traversion ... -++ **/ -++int -++eb_chain_print(FILE* stream, struct eb_info *head) -++{ -++ struct eb_info *cur; -++ -++ if (stream == NULL) -++ stream = stdout; -++ -++ if (head == NULL) { -++ fprintf(stream, "EMPTY\n"); -++ return 0; -++ } -++ /* 012345678012345678012345678012301230123 0123 01234567 0123457 01234567*/ -++ fprintf(stream, "VOL_ID LNUM LEB_VER EC VID DAT PBLK PADDR DSIZE EC\n"); -++ cur = head; -++ while (cur != NULL) { -++ struct eb_info *hist; -++ -++ fprintf(stream, "%08x %-8u %08x %-4s%-4s", -++ be32_to_cpu(cur->vid.vol_id), -++ be32_to_cpu(cur->vid.lnum), -++ be32_to_cpu(cur->vid.leb_ver), -++ cur->ec_crc_ok ? "ok":"bad", -++ cur->vid_crc_ok ? "ok":"bad"); -++ if (cur->vid.vol_type == UBI_VID_STATIC) -++ fprintf(stream, "%-4s", cur->data_crc_ok ? "ok":"bad"); -++ else fprintf(stream, "%-4s", cur->data_crc_ok ? "ok":"ign"); -++ fprintf(stream, " %-4d %08x %-8u %-8llu\n", cur->phys_block, -++ cur->phys_addr, be32_to_cpu(cur->vid.data_size), -++ (unsigned long long)be64_to_cpu(cur->ec.ec)); -++ -++ hist = cur->older; -++ while (hist != NULL) { -++ fprintf(stream, "%08x %-8u %08x %-4s%-4s", -++ be32_to_cpu(hist->vid.vol_id), -++ be32_to_cpu(hist->vid.lnum), -++ be32_to_cpu(hist->vid.leb_ver), -++ hist->ec_crc_ok ? "ok":"bad", -++ hist->vid_crc_ok ? "ok":"bad"); -++ if (hist->vid.vol_type == UBI_VID_STATIC) -++ fprintf(stream, "%-4s", hist->data_crc_ok ? "ok":"bad"); -++ else fprintf(stream, "%-4s", hist->data_crc_ok ? "ok":"ign"); -++ fprintf(stream, " %-4d %08x %-8u %-8llu (*)\n", -++ hist->phys_block, hist->phys_addr, -++ be32_to_cpu(hist->vid.data_size), -++ (unsigned long long)be64_to_cpu(hist->ec.ec)); -++ -++ hist = hist->older; -++ } -++ cur = cur->next; -++ } -++ -++ return 0; -++} -++ -++ -++/** -++ * frees the memory of the entire chain, starting at head; -++ * head will be NULL on return; -++ * always returns 0; -++ **/ -++int -++eb_chain_destroy(struct eb_info **head) -++{ -++ if (head == NULL) -++ return 0; -++ -++ while (*head != NULL) { -++ struct eb_info *cur; -++ struct eb_info *hist; -++ -++ cur = *head; -++ *head = (*head)->next; -++ -++ hist = cur->older; -++ while (hist != NULL) { -++ struct eb_info *temp; -++ -++ temp = hist; -++ hist = hist->older; -++ free(temp); -++ } -++ free(cur); -++ } -++ return 0; -++} -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/error.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/error.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/error.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/error.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,240 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include "error.h" -++ -++#define MAXLINE 4096 -++#define MAXWIDTH 80 -++ -++static FILE *logfp = NULL; -++ -++static void err_doit(int, int, const char *, va_list); -++ -++int -++read_procfile(FILE *fp_out, const char *procfile) -++{ -++ FILE *fp; -++ -++ if (!fp_out) -++ return -ENXIO; -++ -++ fp = fopen(procfile, "r"); -++ if (!fp) -++ return -ENOENT; -++ -++ while(!feof(fp)) { -++ int c = fgetc(fp); -++ -++ if (c == EOF) -++ return 0; -++ -++ if (putc(c, fp_out) == EOF) -++ return -EIO; -++ -++ if (ferror(fp)) -++ return -EIO; -++ } -++ return fclose(fp); -++} -++ -++void -++error_initlog(const char *logfile) -++{ -++ if (!logfile) -++ return; -++ -++ logfp = fopen(logfile, "a+"); -++ read_procfile(logfp, "/proc/cpuinfo"); -++} -++ -++void -++info_msg(const char *fmt, ...) -++{ -++ FILE* fpout; -++ char buf[MAXLINE + 1]; -++ va_list ap; -++ int n; -++ -++ fpout = stdout; -++ -++ va_start(ap, fmt); -++ vsnprintf(buf, MAXLINE, fmt, ap); -++ n = strlen(buf); -++ strcat(buf, "\n"); -++ -++ fputs(buf, fpout); -++ fflush(fpout); -++ if (fpout != stdout) -++ fclose(fpout); -++ -++ va_end(ap); -++ return; -++} -++ -++void -++__err_ret(const char *fmt, ...) -++{ -++ va_list ap; -++ -++ va_start(ap, fmt); -++ err_doit(1, LOG_INFO, fmt, ap); -++ va_end(ap); -++ return; -++} -++ -++void -++__err_sys(const char *fmt, ...) -++{ -++ va_list ap; -++ -++ va_start(ap, fmt); -++ err_doit(1, LOG_ERR, fmt, ap); -++ va_end(ap); -++ exit(EXIT_FAILURE); -++} -++ -++ -++void -++__err_msg(const char *fmt, ...) -++{ -++ va_list ap; -++ -++ va_start(ap, fmt); -++ err_doit(0, LOG_INFO, fmt, ap); -++ va_end(ap); -++ -++ return; -++} -++ -++void -++__err_quit(const char *fmt, ...) -++{ -++ va_list ap; -++ -++ va_start(ap, fmt); -++ err_doit(0, LOG_ERR, fmt, ap); -++ va_end(ap); -++ exit(EXIT_FAILURE); -++} -++ -++void -++__err_dump(const char *fmt, ...) -++{ -++ va_list ap; -++ -++ va_start(ap, fmt); -++ err_doit(1, LOG_ERR, fmt, ap); -++ va_end(ap); -++ abort(); /* dump core and terminate */ -++ exit(EXIT_FAILURE); /* shouldn't get here */ -++} -++ -++/** -++ * If a logfile is used we must not print on stderr and stdout -++ * anymore. Since pfilfash might be used in a server context, it is -++ * even dangerous to write to those descriptors. -++ */ -++static void -++err_doit(int errnoflag, int level __attribute__((unused)), -++ const char *fmt, va_list ap) -++{ -++ FILE* fpout; -++ int errno_save, n; -++ char buf[MAXLINE + 1]; -++ fpout = stderr; -++ -++ errno_save = errno; /* value caller might want printed */ -++ -++ vsnprintf(buf, MAXLINE, fmt, ap); /* safe */ -++ -++ n = strlen(buf); -++ -++ if (errnoflag) -++ snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save)); -++ strcat(buf, "\n"); -++ -++ if (logfp) { -++ fputs(buf, logfp); -++ fflush(logfp); -++ return; /* exit when logging completes */ -++ } -++ -++ if (fpout == stderr) { -++ /* perform line wrap when outputting to stderr */ -++ int word_len, post_len, chars; -++ char *buf_ptr; -++ const char *frmt = "%*s%n %n"; -++ -++ chars = 0; -++ buf_ptr = buf; -++ while (sscanf(buf_ptr, frmt, &word_len, &post_len) != EOF) { -++ int i; -++ char word[word_len + 1]; -++ char post[post_len + 1]; -++ -++ strncpy(word, buf_ptr, word_len); -++ word[word_len] = '\0'; -++ buf_ptr += word_len; -++ post_len -= word_len; -++ -++ if (chars + word_len > MAXWIDTH) { -++ fputc('\n', fpout); -++ chars = 0; -++ } -++ fputs(word, fpout); -++ chars += word_len; -++ -++ if (post_len > 0) { -++ strncpy(post, buf_ptr, post_len); -++ post[post_len] = '\0'; -++ buf_ptr += post_len; -++ } -++ for (i = 0; i < post_len; i++) { -++ int inc = 1, chars_new; -++ -++ if (post[i] == '\t') -++ inc = 8; -++ if (post[i] == '\n') { -++ inc = 0; -++ chars_new = 0; -++ } else -++ chars_new = chars + inc; -++ -++ if (chars_new > MAXWIDTH) { -++ fputc('\n', fpout); -++ chars_new = inc; -++ } -++ fputc(post[i], fpout); -++ chars = chars_new; -++ } -++ } -++ } -++ else -++ fputs(buf, fpout); -++ fflush(fpout); -++ if (fpout != stderr) -++ fclose(fpout); -++ -++ return; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/error.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/error.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/error.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/error.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,84 @@ -++#ifndef __ERROR_H__ -++#define __ERROR_H__ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++#include -++ -++void error_initlog(const char *logfile); -++int read_procfile(FILE *fp_out, const char *procfile); -++ -++void __err_ret(const char *fmt, ...); -++void __err_sys(const char *fmt, ...); -++void __err_msg(const char *fmt, ...); -++void __err_quit(const char *fmt, ...); -++void __err_dump(const char *fmt, ...); -++ -++void info_msg(const char *fmt, ...); -++ -++#ifdef DEBUG -++#define __loc_msg(str) do { \ -++ __err_msg("[%s. FILE: %s FUNC: %s LINE: %d]\n", \ -++ str, __FILE__, __FUNCTION__, __LINE__); \ -++} while (0) -++#else -++#define __loc_msg(str) -++#endif -++ -++ -++#define err_dump(fmt, ...) do { \ -++ __loc_msg("ErrDump"); \ -++ __err_dump(fmt, ##__VA_ARGS__); \ -++} while (0) -++ -++#define err_quit(fmt, ...) do { \ -++ __loc_msg("ErrQuit"); \ -++ __err_quit(fmt, ##__VA_ARGS__); \ -++} while (0) -++ -++ -++#define err_ret(fmt, ...) do { \ -++ __loc_msg("ErrRet"); \ -++ __err_ret(fmt, ##__VA_ARGS__); \ -++} while (0) -++ -++#define err_sys(fmt, ...) do { \ -++ __loc_msg("ErrSys"); \ -++ __err_sys(fmt, ##__VA_ARGS__); \ -++} while (0) -++ -++#define err_msg(fmt, ...) do { \ -++ __loc_msg("ErrMsg"); \ -++ __err_msg(fmt, ##__VA_ARGS__); \ -++} while (0) -++ -++#define log_msg(fmt, ...) do { \ -++ /* __loc_msg("LogMsg"); */ \ -++ __err_msg(fmt, ##__VA_ARGS__); \ -++} while (0) -++ -++#ifdef DEBUG -++#define dbg_msg(fmt, ...) do { \ -++ __loc_msg("DbgMsg"); \ -++ __err_msg(fmt, ##__VA_ARGS__); \ -++} while (0) -++#else -++#define dbg_msg(fmt, ...) do {} while (0) -++#endif -++ -++#endif /* __ERROR_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/example_ubi.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/example_ubi.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/example_ubi.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/example_ubi.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,28 @@ -++#ifndef __EXAMPLE_UBI_H__ -++#define __EXAMPLE_UBI_H__ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/** -++ * Defaults for our cards. -++ */ -++#define EXAMPLE_UBI_DEVICE 0 -++#define EXAMPLE_BOOTENV_VOL_ID_1 4 -++#define EXAMPLE_BOOTENV_VOL_ID_2 5 -++ -++#endif /* __EXAMPLE_UBI_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/hashmap.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/hashmap.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/hashmap.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/hashmap.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,412 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ */ -++ -++#include -++#include -++#include -++#include -++#include "error.h" -++#include "hashmap.h" -++#define DEFAULT_BUCKETS 4096 -++ -++#if 0 -++#define INFO_MSG(fmt...) do { \ -++ info_msg(fmt); \ -++} while (0) -++#else -++#define INFO_MSG(fmt...) -++#endif -++ -++struct hashentry { -++ char* key; /* key '0' term. str */ -++ char* value; /* payload '0' term. str */ -++ -++ hashentry_t next; -++}; -++ -++struct hashmap { -++ size_t entries; /* current #entries */ -++ size_t maxsize; /* no. of hash buckets */ -++ hashentry_t* data; /* array of buckets */ -++}; -++ -++static int -++is_empty(hashentry_t l) -++{ -++ return l == NULL ? 1 : 0; -++} -++ -++hashmap_t -++hashmap_new(void) -++{ -++ hashmap_t res; -++ res = (hashmap_t) calloc(1, sizeof(struct hashmap)); -++ -++ if (res == NULL) -++ return NULL; -++ -++ res->maxsize = DEFAULT_BUCKETS; -++ res->entries = 0; -++ -++ res->data = (hashentry_t*) -++ calloc(1, res->maxsize * sizeof(struct hashentry)); -++ -++ if (res->data == NULL) -++ return NULL; -++ -++ return res; -++} -++ -++static hashentry_t -++new_entry(const char* key, const char* value) -++{ -++ hashentry_t res; -++ -++ res = (hashentry_t) calloc(1, sizeof(struct hashentry)); -++ -++ if (res == NULL) -++ return NULL; -++ -++ /* allocate key and value and copy them */ -++ res->key = strdup(key); -++ if (res->key == NULL) { -++ free(res); -++ return NULL; -++ } -++ -++ res->value = strdup(value); -++ if (res->value == NULL) { -++ free(res->key); -++ free(res); -++ return NULL; -++ } -++ -++ res->next = NULL; -++ -++ return res; -++} -++ -++static hashentry_t -++free_entry(hashentry_t e) -++{ -++ if (!is_empty(e)) { -++ if(e->key != NULL) { -++ free(e->key); -++ } -++ if(e->value != NULL) -++ free(e->value); -++ free(e); -++ } -++ -++ return NULL; -++} -++ -++static hashentry_t -++remove_entry(hashentry_t l, const char* key, size_t* entries) -++{ -++ hashentry_t lnext; -++ if (is_empty(l)) -++ return NULL; -++ -++ if(strcmp(l->key,key) == 0) { -++ lnext = l->next; -++ l = free_entry(l); -++ (*entries)--; -++ return lnext; -++ } -++ -++ l->next = remove_entry(l->next, key, entries); -++ -++ return l; -++} -++ -++static hashentry_t -++insert_entry(hashentry_t l, hashentry_t e, size_t* entries) -++{ -++ if (is_empty(l)) { -++ (*entries)++; -++ return e; -++ } -++ -++ /* check for update */ -++ if (strcmp(l->key, e->key) == 0) { -++ e->next = l->next; -++ l = free_entry(l); -++ return e; -++ } -++ -++ l->next = insert_entry(l->next, e, entries); -++ return l; -++} -++ -++static hashentry_t -++remove_all(hashentry_t l, size_t* entries) -++{ -++ hashentry_t lnext; -++ if (is_empty(l)) -++ return NULL; -++ -++ lnext = l->next; -++ free_entry(l); -++ (*entries)--; -++ -++ return remove_all(lnext, entries); -++} -++ -++static const char* -++value_lookup(hashentry_t l, const char* key) -++{ -++ if (is_empty(l)) -++ return NULL; -++ -++ if (strcmp(l->key, key) == 0) -++ return l->value; -++ -++ return value_lookup(l->next, key); -++} -++ -++static void -++print_all(hashentry_t l) -++{ -++ if (is_empty(l)) { -++ printf("\n"); -++ return; -++ } -++ -++ printf("%s=%s", l->key, l->value); -++ if (!is_empty(l->next)) { -++ printf(","); -++ } -++ -++ print_all(l->next); -++} -++ -++static void -++keys_to_array(hashentry_t l, const char** a, size_t* i) -++{ -++ if (is_empty(l)) -++ return; -++ -++ a[*i] = l->key; -++ (*i)++; -++ -++ keys_to_array(l->next, a, i); -++} -++ -++uint32_t -++hash_str(const char* str, uint32_t mapsize) -++{ -++ uint32_t hash = 0; -++ uint32_t x = 0; -++ uint32_t i = 0; -++ size_t len = strlen(str); -++ -++ for(i = 0; i < len; str++, i++) { -++ hash = (hash << 4) + (*str); -++ if((x = hash & 0xF0000000L) != 0) { -++ hash ^= (x >> 24); -++ hash &= ~x; -++ } -++ } -++ -++ return (hash & 0x7FFFFFFF) % mapsize; -++} -++ -++ -++int -++hashmap_is_empty(hashmap_t map) -++{ -++ if (map == NULL) -++ return -EINVAL; -++ -++ return map->entries > 0 ? 1 : 0; -++} -++ -++const char* -++hashmap_lookup(hashmap_t map, const char* key) -++{ -++ uint32_t i; -++ -++ if ((map == NULL) || (key == NULL)) -++ return NULL; -++ -++ i = hash_str(key, map->maxsize); -++ -++ return value_lookup(map->data[i], key); -++} -++ -++int -++hashmap_add(hashmap_t map, const char* key, const char* value) -++{ -++ uint32_t i; -++ hashentry_t entry; -++ -++ if ((map == NULL) || (key == NULL) || (value == NULL)) -++ return -EINVAL; -++ -++ i = hash_str(key, map->maxsize); -++ entry = new_entry(key, value); -++ if (entry == NULL) -++ return -ENOMEM; -++ -++ map->data[i] = insert_entry(map->data[i], -++ entry, &map->entries); -++ -++ INFO_MSG("HASH_ADD: chain[%d] key:%s val:%s",i, key, value); -++ return 0; -++} -++ -++int -++hashmap_remove(hashmap_t map, const char* key) -++{ -++ uint32_t i; -++ -++ if ((map == NULL) || (key == NULL)) -++ return -EINVAL; -++ -++ i = hash_str(key, map->maxsize); -++ map->data[i] = remove_entry(map->data[i], key, &map->entries); -++ -++ return 0; -++} -++ -++size_t -++hashmap_size(hashmap_t map) -++{ -++ if (map != NULL) -++ return map->entries; -++ else -++ return 0; -++} -++ -++int -++hashmap_free(hashmap_t map) -++{ -++ size_t i; -++ -++ if (map == NULL) -++ return -EINVAL; -++ -++ /* "children" first */ -++ for(i = 0; i < map->maxsize; i++) { -++ map->data[i] = remove_all(map->data[i], &map->entries); -++ } -++ free(map->data); -++ free(map); -++ -++ return 0; -++} -++ -++int -++hashmap_dump(hashmap_t map) -++{ -++ size_t i; -++ if (map == NULL) -++ return -EINVAL; -++ -++ for(i = 0; i < map->maxsize; i++) { -++ if (map->data[i] != NULL) { -++ printf("[%zd]: ", i); -++ print_all(map->data[i]); -++ } -++ } -++ -++ return 0; -++} -++ -++static const char** -++sort_key_vector(const char** a, size_t size) -++{ -++ /* uses bubblesort */ -++ size_t i, j; -++ const char* tmp; -++ -++ if (size <= 0) -++ return a; -++ -++ for (i = size - 1; i > 0; i--) { -++ for (j = 0; j < i; j++) { -++ if (strcmp(a[j], a[j+1]) > 0) { -++ tmp = a[j]; -++ a[j] = a[j+1]; -++ a[j+1] = tmp; -++ } -++ } -++ } -++ return a; -++} -++ -++const char** -++hashmap_get_key_vector(hashmap_t map, size_t* size, int sort) -++{ -++ const char** res; -++ size_t i, j; -++ *size = map->entries; -++ -++ res = (const char**) malloc(*size * sizeof(char*)); -++ if (res == NULL) -++ return NULL; -++ -++ j = 0; -++ for(i=0; i < map->maxsize; i++) { -++ keys_to_array(map->data[i], res, &j); -++ } -++ -++ if (sort) -++ res = sort_key_vector(res, *size); -++ -++ return res; -++} -++ -++int -++hashmap_key_is_in_vector(const char** vec, size_t size, const char* key) -++{ -++ size_t i; -++ for (i = 0; i < size; i++) { -++ if (strcmp(vec[i], key) == 0) /* found */ -++ return 1; -++ } -++ -++ return 0; -++} -++ -++const char** -++hashmap_get_update_key_vector(const char** vec1, size_t vec1_size, -++ const char** vec2, size_t vec2_size, size_t* res_size) -++{ -++ const char** res; -++ size_t i, j; -++ -++ *res_size = vec2_size; -++ -++ res = (const char**) malloc(*res_size * sizeof(char*)); -++ if (res == NULL) -++ return NULL; -++ -++ /* get all keys from vec2 which are not set in vec1 */ -++ j = 0; -++ for (i = 0; i < vec2_size; i++) { -++ if (!hashmap_key_is_in_vector(vec1, vec1_size, vec2[i])) -++ res[j++] = vec2[i]; -++ } -++ -++ *res_size = j; -++ return res; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/hashmap.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/hashmap.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/hashmap.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/hashmap.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,49 @@ -++#ifndef __HASHMAP_H__ -++#define __HASHMAP_H__ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ */ -++ -++#include -++#include -++ -++typedef struct hashentry *hashentry_t; -++typedef struct hashmap *hashmap_t; -++ -++hashmap_t hashmap_new(void); -++int hashmap_free(hashmap_t map); -++ -++int hashmap_add(hashmap_t map, const char* key, const char* value); -++int hashmap_update(hashmap_t map, const char* key, const char* value); -++int hashmap_remove(hashmap_t map, const char* key); -++const char* hashmap_lookup(hashmap_t map, const char* key); -++ -++const char** hashmap_get_key_vector(hashmap_t map, size_t* size, int sort); -++int hashmap_key_is_in_vector(const char** vec, size_t size, const char* key); -++const char** hashmap_get_update_key_vector(const char** vec1, size_t vec1_size, -++ const char** vec2, size_t vec2_size, size_t* res_size); -++ -++int hashmap_dump(hashmap_t map); -++ -++int hashmap_is_empty(hashmap_t map); -++size_t hashmap_size(hashmap_t map); -++ -++uint32_t hash_str(const char* str, uint32_t mapsize); -++ -++#endif /* __HASHMAP_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/libpfiflash.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/libpfiflash.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/libpfiflash.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/libpfiflash.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1325 @@ -++/* -++ * Copyright International Business Machines Corp., 2006, 2007 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * Authors: Oliver Lohmann -++ * Drake Dowsett -++ * Contact: Andreas Arnez -++ */ -++ -++/* TODO Compare data before writing it. This implies that the volume -++ * parameters are compared first: size, alignment, name, type, ..., -++ * this is the same, compare the data. Volume deletion is deffered -++ * until the difference has been found out. -++ */ -++ -++#include -++#include -++#include -++#include -++#define __USE_GNU -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#include /* FIXME Is this ok here? */ -++#include -++ -++#include "pfiflash_error.h" -++#include "ubimirror.h" -++#include "error.h" -++#include "reader.h" -++#include "example_ubi.h" -++#include "bootenv.h" -++ -++/* ubi-header.h and crc32.h needed for CRC checking */ -++#include /* FIXME Is this ok here? */ -++#include "crc32.h" -++ -++#define ubi_unused __attribute__((unused)) -++ -++#define COMPARE_BUFFER_SIZE 2048 -++ -++#define DEFAULT_DEV_PATTERN "/dev/ubi%d" -++#define DEFAULT_VOL_PATTERN "/dev/ubi%d_%d" -++ -++static const char copyright [] ubi_unused = -++ "Copyright International Business Machines Corp., 2006, 2007"; -++ -++/* simply clear buffer, then write into front of it */ -++#define EBUF(fmt...) \ -++ snprintf(err_buf, err_buf_size, fmt); -++ -++/* make a history of buffer and then prepend something in front */ -++#define EBUF_PREPEND(fmt) \ -++ do { \ -++ int EBUF_HISTORY_LENGTH = strlen(err_buf); \ -++ char EBUF_HISTORY[EBUF_HISTORY_LENGTH + 1]; \ -++ strncpy(EBUF_HISTORY, err_buf, EBUF_HISTORY_LENGTH + 1);\ -++ EBUF(fmt ": %s", EBUF_HISTORY); \ -++ } while (0) -++ -++/* An array of PDD function pointers indexed by the algorithm. */ -++static pdd_func_t pdd_funcs[PDD_HANDLING_NUM] = -++ { -++ &bootenv_pdd_keep, -++ &bootenv_pdd_merge, -++ &bootenv_pdd_overwrite -++ }; -++ -++typedef enum ubi_update_process_t { -++ UBI_REMOVE = 0, -++ UBI_WRITE, -++ UBI_COMPARE, -++} ubi_update_process_t; -++ -++ -++/** -++ * skip_raw_volumes - reads data from pfi to advance fp past raw block -++ * @pfi: fp to pfi data -++ * @pfi_raws: header information -++ * -++ * Error handling): -++ * when early EOF in pfi data -++ * - returns -PFIFLASH_ERR_EOF, err_buf matches text to err -++ * when file I/O error -++ * - returns -PFIFLASH_ERR_FIO, err_buf matches text to err -++ **/ -++static int -++skip_raw_volumes(FILE* pfi, list_t pfi_raws, -++ char* err_buf, size_t err_buf_size) -++{ -++ int rc; -++ void *i; -++ list_t ptr; -++ -++ if (is_empty(pfi_raws)) -++ return 0; -++ -++ rc = 0; -++ foreach(i, ptr, pfi_raws) { -++ size_t j; -++ pfi_raw_t raw; -++ -++ raw = (pfi_raw_t)i; -++ for(j = 0; j < raw->data_size; j++) { -++ int c; -++ -++ c = fgetc(pfi); -++ if (c == EOF) -++ rc = -PFIFLASH_ERR_EOF; -++ else if (ferror(pfi)) -++ rc = -PFIFLASH_ERR_FIO; -++ -++ if (rc != 0) -++ goto err; -++ } -++ } -++ -++ err: -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ return rc; -++} -++ -++ -++/** -++ * my_ubi_mkvol - wraps the ubi_mkvol functions and impl. bootenv update hook -++ * @devno: UBI device number. -++ * @s: Current seqnum. -++ * @u: Information about the UBI volume from the PFI. -++ * -++ * Error handling: -++ * when UBI system couldn't be opened -++ * - returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err -++ * when UBI system couldn't create a volume -++ * - returns -PFIFLASH_ERR_UBI_MKVOL, err_buf matches text to err -++ **/ -++static int -++my_ubi_mkvol(int devno, int s, pfi_ubi_t u, -++ char *err_buf, size_t err_buf_size) -++{ -++ int rc, type; -++ char path[PATH_MAX]; -++ libubi_t ulib; -++ struct ubi_mkvol_request req; -++ -++ rc = 0; -++ ulib = NULL; -++ -++ log_msg("[ ubimkvol id=%d, size=%d, data_size=%d, type=%d, " -++ "alig=%d, nlen=%d, name=%s", -++ u->ids[s], u->size, u->data_size, u->type, u->alignment, -++ strnlen(u->names[s], PFI_UBI_VOL_NAME_LEN), u->names[s]); -++ -++ ulib = libubi_open(); -++ if (ulib == NULL) { -++ rc = -PFIFLASH_ERR_UBI_OPEN; -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } -++ -++ switch (u->type) { -++ case pfi_ubi_static: -++ type = UBI_STATIC_VOLUME; break; -++ case pfi_ubi_dynamic: -++ default: -++ type = UBI_DYNAMIC_VOLUME; -++ } -++ -++ snprintf(path, PATH_MAX, DEFAULT_DEV_PATTERN, devno); -++ -++ req.vol_id = u->ids[s]; -++ req.alignment = u->alignment; -++ req.bytes = u->size; -++ req.vol_type = type; -++ req.name = u->names[s]; -++ -++ rc = ubi_mkvol(ulib, path, &req); -++ if (rc != 0) { -++ rc = -PFIFLASH_ERR_UBI_MKVOL; -++ EBUF(PFIFLASH_ERRSTR[-rc], u->ids[s]); -++ goto err; -++ } -++ -++ err: -++ if (ulib != NULL) -++ libubi_close(ulib); -++ -++ return rc; -++} -++ -++ -++/** -++ * my_ubi_rmvol - a wrapper around the UBI library function ubi_rmvol -++ * @devno UBI device number -++ * @id UBI volume id to remove -++ * -++ * If the volume does not exist, the function will return success. -++ * -++ * Error handling: -++ * when UBI system couldn't be opened -++ * - returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err -++ * when UBI system couldn't update (truncate) a volume -++ * - returns -PFIFLASH_ERR_UBI_VOL_UPDATE, err_buf matches text to err -++ * when UBI system couldn't remove a volume -++ * - returns -PFIFLASH_ERR_UBI_RMVOL, err_buf matches text to err -++ **/ -++static int -++my_ubi_rmvol(int devno, uint32_t id, -++ char *err_buf, size_t err_buf_size) -++{ -++ int rc, fd; -++ char path[PATH_MAX]; -++ libubi_t ulib; -++ -++ rc = 0; -++ ulib = NULL; -++ -++ log_msg("[ ubirmvol id=%d", id); -++ -++ ulib = libubi_open(); -++ if (ulib == NULL) { -++ rc = -PFIFLASH_ERR_UBI_OPEN; -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } -++ -++ snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id); -++ -++ /* truncate whether it exist or not */ -++ fd = open(path, O_RDWR); -++ if (fd < 0) { -++ libubi_close(ulib); -++ return 0; /* not existent, return 0 */ -++ } -++ -++ rc = ubi_update_start(ulib, fd, 0); -++ close(fd); -++ if (rc < 0) { -++ rc = -PFIFLASH_ERR_UBI_VOL_UPDATE; -++ EBUF(PFIFLASH_ERRSTR[-rc], id); -++ goto err; /* if EBUSY than empty device, continue */ -++ } -++ -++ snprintf(path, PATH_MAX, DEFAULT_DEV_PATTERN, devno); -++ -++ rc = ubi_rmvol(ulib, path, id); -++ if (rc != 0) { -++#ifdef DEBUG -++ int rc_old = rc; -++ dbg_msg("Remove UBI volume %d returned with error: %d " -++ "errno=%d", id, rc_old, errno); -++#endif -++ -++ rc = -PFIFLASH_ERR_UBI_RMVOL; -++ EBUF(PFIFLASH_ERRSTR[-rc], id); -++ -++ /* TODO Define a ubi_rmvol return value which says -++ * sth like EUBI_NOSUCHDEV. In this case, a failed -++ * operation is acceptable. Everything else has to be -++ * classified as real error. But talk to Andreas Arnez -++ * before defining something odd... -++ */ -++ /* if ((errno == EINVAL) || (errno == ENODEV)) -++ return 0; */ /* currently it is EINVAL or ENODEV */ -++ -++ goto err; -++ } -++ -++ err: -++ if (ulib != NULL) -++ libubi_close(ulib); -++ -++ return rc; -++} -++ -++ -++/** -++ * read_bootenv_volume - reads the current bootenv data from id into be_old -++ * @devno UBI device number -++ * @id UBI volume id to remove -++ * @bootenv_old to hold old boot_env data -++ * -++ * Error handling: -++ * when UBI system couldn't be opened -++ * - returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err -++ * when UBI system couldn't open a volume to read -++ * - returns -PFIFLASH_ERR_UBI_VOL_FOPEN, err_buf matches text to err -++ * when couldn't read bootenv data -++ * - returns -PFIFLASH_ERR_BOOTENV_READ, err_buf matches text to err -++ **/ -++static int -++read_bootenv_volume(int devno, uint32_t id, bootenv_t bootenv_old, -++ char *err_buf, size_t err_buf_size) -++{ -++ int rc; -++ FILE* fp_in; -++ char path[PATH_MAX]; -++ libubi_t ulib; -++ -++ rc = 0; -++ fp_in = NULL; -++ ulib = NULL; -++ -++ ulib = libubi_open(); -++ if (ulib == NULL) { -++ rc = -PFIFLASH_ERR_UBI_OPEN; -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } -++ -++ snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id); -++ -++ fp_in = fopen(path, "r"); -++ if (!fp_in) { -++ rc = -PFIFLASH_ERR_UBI_VOL_FOPEN; -++ EBUF(PFIFLASH_ERRSTR[-rc], id); -++ goto err; -++ } -++ -++ log_msg("[ reading old bootenvs ..."); -++ -++ /* Save old bootenvs for reference */ -++ rc = bootenv_read(fp_in, bootenv_old, BOOTENV_MAXSIZE); -++ if (rc != 0) { -++ rc = -PFIFLASH_ERR_BOOTENV_READ; -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } -++ -++ err: -++ if (fp_in) -++ fclose(fp_in); -++ if (ulib) -++ libubi_close(ulib); -++ -++ return rc; -++} -++ -++ -++/** -++ * write_bootenv_volume - writes data from PFI file int to bootenv UBI volume -++ * @devno UBI device number -++ * @id UBI volume id -++ * @bootend_old old PDD data from machine -++ * @pdd_f function to handle PDD with -++ * @fp_in new pdd data contained in PFI -++ * @fp_in_size data size of new pdd data in PFI -++ * @pfi_crc crc value from PFI header -++ * -++ * Error handling: -++ * when UBI system couldn't be opened -++ * - returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err -++ * when bootenv can't be created -++ * - returns -PFIFLASH_ERR_BOOTENV_CREATE, err_buf matches text to err -++ * when bootenv can't be read -++ * - returns -PFIFLASH_ERR_BOOTENV_READ, err_buf matches text to err -++ * when PDD handling function returns and error -++ * - passes rc and err_buf data -++ * when CRC check fails -++ * - returns -PFIFLASH_ERR_CRC_CHECK, err_buf matches text to err -++ * when bootenv can't be resized -++ * - returns -PFIFLASH_ERR_BOOTENV_SIZE, err_buf matches text to err -++ * when UBI system couldn't open a volume -++ * - returns -PFIFLASH_ERR_UBI_VOL_FOPEN, err_buf matches text to err -++ * when couldn't write bootenv data -++ * - returns -PFIFLASH_ERR_BOOTENV_WRITE, err_buf matches text to err -++ **/ -++static int -++write_bootenv_volume(int devno, uint32_t id, bootenv_t bootenv_old, -++ pdd_func_t pdd_f, FILE* fp_in, size_t fp_in_size, -++ uint32_t pfi_crc, -++ char *err_buf, size_t err_buf_size) -++{ -++ int rc, warnings, fd_out; -++ uint32_t crc; -++ char path[PATH_MAX]; -++ size_t update_size; -++ FILE *fp_out; -++ bootenv_t bootenv_new, bootenv_res; -++ libubi_t ulib; -++ -++ rc = 0; -++ warnings = 0; -++ crc = 0; -++ update_size = 0; -++ fp_out = NULL; -++ bootenv_new = NULL; -++ bootenv_res = NULL; -++ ulib = NULL; -++ -++ log_msg("[ ubiupdatevol bootenv id=%d, fp_in=%p", id, fp_in); -++ -++ /* Workflow: -++ * 1. Apply PDD operation and get the size of the returning -++ * bootenv_res section. Without the correct size it wouldn't -++ * be possible to call UBI update vol. -++ * 2. Call UBI update vol -++ * 3. Get FILE* to vol dev -++ * 4. Write to FILE* -++ */ -++ -++ ulib = libubi_open(); -++ if (ulib == NULL) { -++ rc = -PFIFLASH_ERR_UBI_OPEN; -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } -++ -++ rc = bootenv_create(&bootenv_new); -++ if (rc != 0) { -++ rc = -PFIFLASH_ERR_BOOTENV_CREATE; -++ EBUF(PFIFLASH_ERRSTR[-rc], " 'new'"); -++ goto err; -++ } -++ -++ rc = bootenv_create(&bootenv_res); -++ if (rc != 0) { -++ rc = -PFIFLASH_ERR_BOOTENV_CREATE; -++ EBUF(PFIFLASH_ERRSTR[-rc], " 'res'"); -++ goto err; -++ } -++ -++ rc = bootenv_read_crc(fp_in, bootenv_new, fp_in_size, &crc); -++ if (rc != 0) { -++ rc = -PFIFLASH_ERR_BOOTENV_READ; -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } else if (crc != pfi_crc) { -++ rc = -PFIFLASH_ERR_CRC_CHECK; -++ EBUF(PFIFLASH_ERRSTR[-rc], pfi_crc, crc); -++ goto err; -++ } -++ -++ rc = pdd_f(bootenv_old, bootenv_new, &bootenv_res, &warnings, -++ err_buf, err_buf_size); -++ if (rc != 0) { -++ EBUF_PREPEND("handling PDD"); -++ goto err; -++ } -++ else if (warnings) -++ /* TODO do something with warnings */ -++ dbg_msg("A warning in the PDD operation occured: %d", -++ warnings); -++ -++ rc = bootenv_size(bootenv_res, &update_size); -++ if (rc != 0) { -++ rc = -PFIFLASH_ERR_BOOTENV_SIZE; -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } -++ -++ snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id); -++ -++ fd_out = open(path, O_RDWR); -++ if (fd_out < 0) { -++ rc = -PFIFLASH_ERR_UBI_VOL_FOPEN; -++ EBUF(PFIFLASH_ERRSTR[-rc], id); -++ goto err; -++ } -++ fp_out = fdopen(fd_out, "r+"); -++ if (!fp_out) { -++ rc = -PFIFLASH_ERR_UBI_VOL_FOPEN; -++ EBUF(PFIFLASH_ERRSTR[-rc], id); -++ goto err; -++ } -++ rc = ubi_update_start(ulib, fd_out, update_size); -++ if (rc < 0) { -++ rc = -PFIFLASH_ERR_UBI_VOL_UPDATE; -++ EBUF(PFIFLASH_ERRSTR[-rc], id); -++ goto err; -++ } -++ -++ rc = bootenv_write(fp_out, bootenv_res); -++ if (rc != 0) { -++ rc = -PFIFLASH_ERR_BOOTENV_WRITE; -++ EBUF(PFIFLASH_ERRSTR[-rc], devno, id); -++ goto err; -++ } -++ -++ err: -++ if (ulib != NULL) -++ libubi_close(ulib); -++ if (bootenv_new != NULL) -++ bootenv_destroy(&bootenv_new); -++ if (bootenv_res != NULL) -++ bootenv_destroy(&bootenv_res); -++ if (fp_out) -++ fclose(fp_out); -++ -++ return rc; -++} -++ -++ -++/** -++ * write_normal_volume - writes data from PFI file int to regular UBI volume -++ * @devno UBI device number -++ * @id UBI volume id -++ * @update_size size of data stream -++ * @fp_in PFI data file pointer -++ * @pfi_crc CRC data from PFI header -++ * -++ * Error handling: -++ * when UBI system couldn't be opened -++ * - returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err -++ * when UBI system couldn't open a volume -++ * - returns -PFIFLASH_ERR_UBI_VOL_FOPEN, err_buf matches text to err -++ * when unexpected EOF is encountered -++ * - returns -PFIFLASH_ERR_EOF, err_buf matches text to err -++ * when file I/O error -++ * - returns -PFIFLASH_ERR_FIO, err_buf matches text to err -++ * when CRC check fails -++ * - retruns -PFIFLASH_ERR_CRC_CHECK, err_buf matches text to err -++ **/ -++static int -++write_normal_volume(int devno, uint32_t id, size_t update_size, FILE* fp_in, -++ uint32_t pfi_crc, -++ char *err_buf, size_t err_buf_size) -++{ -++ int rc, fd_out; -++ uint32_t crc, crc32_table[256]; -++ char path[PATH_MAX]; -++ size_t bytes_left; -++ FILE* fp_out; -++ libubi_t ulib; -++ -++ rc = 0; -++ crc = UBI_CRC32_INIT; -++ bytes_left = update_size; -++ fp_out = NULL; -++ ulib = NULL; -++ -++ log_msg("[ ubiupdatevol id=%d, update_size=%d fp_in=%p", -++ id, update_size, fp_in); -++ -++ ulib = libubi_open(); -++ if (ulib == NULL) { -++ rc = -PFIFLASH_ERR_UBI_OPEN; -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } -++ -++ snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id); -++ -++ fd_out = open(path, O_RDWR); -++ if (fd_out < 0) { -++ rc = -PFIFLASH_ERR_UBI_VOL_FOPEN; -++ EBUF(PFIFLASH_ERRSTR[-rc], id); -++ goto err; -++ } -++ fp_out = fdopen(fd_out, "r+"); -++ if (!fp_out) { -++ rc = -PFIFLASH_ERR_UBI_VOL_FOPEN; -++ EBUF(PFIFLASH_ERRSTR[-rc], id); -++ goto err; -++ } -++ rc = ubi_update_start(ulib, fd_out, update_size); -++ if (rc < 0) { -++ rc = -PFIFLASH_ERR_UBI_VOL_UPDATE; -++ EBUF(PFIFLASH_ERRSTR[-rc], id); -++ goto err; -++ } -++ -++ init_crc32_table(crc32_table); -++ while (bytes_left) { -++ char buf[1024]; -++ size_t to_rw = sizeof buf > bytes_left ? -++ bytes_left : sizeof buf; -++ if (fread(buf, 1, to_rw, fp_in) != to_rw) { -++ rc = -PFIFLASH_ERR_EOF; -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } -++ crc = clc_crc32(crc32_table, crc, buf, to_rw); -++ if (fwrite(buf, 1, to_rw, fp_out) != to_rw) { -++ rc = -PFIFLASH_ERR_FIO; -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } -++ bytes_left -= to_rw; -++ } -++ -++ if (crc != pfi_crc) { -++ rc = -PFIFLASH_ERR_CRC_CHECK; -++ EBUF(PFIFLASH_ERRSTR[-rc], pfi_crc, crc); -++ goto err; -++ } -++ -++ err: -++ if (fp_out) -++ fclose(fp_out); -++ if (ulib) -++ libubi_close(ulib); -++ -++ return rc; -++} -++ -++static int compare_bootenv(FILE *fp_pfi, FILE **fp_flash, uint32_t ids_size, -++ uint32_t data_size, pdd_func_t pdd_f, char *err_buf, -++ size_t err_buf_size) -++{ -++ int rc, warnings = 0; -++ unsigned int i; -++ bootenv_t bootenv_pfi, bootenv_res = NULL, bootenv_flash = NULL; -++ -++ rc = bootenv_create(&bootenv_pfi); -++ if (rc != 0) { -++ rc = -PFIFLASH_ERR_BOOTENV_CREATE; -++ goto err; -++ } -++ -++ rc = bootenv_create(&bootenv_res); -++ if (rc != 0) { -++ rc = -PFIFLASH_ERR_BOOTENV_CREATE; -++ goto err; -++ } -++ -++ rc = bootenv_read(fp_pfi, bootenv_pfi, data_size); -++ if (rc != 0) { -++ rc = -PFIFLASH_ERR_BOOTENV_READ; -++ goto err; -++ } -++ -++ for (i = 0; i < ids_size; i++) { -++ rc = bootenv_create(&bootenv_flash); -++ if (rc != 0) { -++ rc = -PFIFLASH_ERR_BOOTENV_CREATE; -++ goto err; -++ } -++ -++ rc = bootenv_read(fp_flash[i], bootenv_flash, BOOTENV_MAXSIZE); -++ if (rc != 0) { -++ rc = -PFIFLASH_ERR_BOOTENV_READ; -++ goto err; -++ } -++ -++ rc = pdd_f(bootenv_flash, bootenv_pfi, &bootenv_res, -++ &warnings, err_buf, err_buf_size); -++ if (rc != 0) { -++ rc = -PFIFLASH_ERR_PDD_UNKNOWN; -++ goto err; -++ } -++ -++ rc = bootenv_compare(bootenv_flash, bootenv_res); -++ if (rc > 0) { -++ rc = -PFIFLASH_CMP_DIFF; -++ goto err; -++ } else if (rc < 0) { -++ rc = -PFIFLASH_ERR_COMPARE; -++ goto err; -++ } -++ -++ bootenv_destroy(&bootenv_flash); -++ bootenv_flash = NULL; -++ } -++ -++err: -++ if (bootenv_pfi) -++ bootenv_destroy(&bootenv_pfi); -++ if (bootenv_res) -++ bootenv_destroy(&bootenv_res); -++ if (bootenv_flash) -++ bootenv_destroy(&bootenv_flash); -++ -++ return rc; -++} -++ -++static int compare_data(FILE *fp_pfi, FILE **fp_flash, uint32_t ids_size, -++ uint32_t bytes_left) -++{ -++ unsigned int i; -++ size_t read_bytes, rc = 0; -++ char buf_pfi[COMPARE_BUFFER_SIZE]; -++ char *buf_flash[ids_size]; -++ -++ for (i = 0; i < ids_size; i++) { -++ buf_flash[i] = malloc(COMPARE_BUFFER_SIZE); -++ if (!buf_flash[i]) -++ return -PFIFLASH_ERR_COMPARE; -++ } -++ -++ while (bytes_left) { -++ if (bytes_left > COMPARE_BUFFER_SIZE) -++ read_bytes = COMPARE_BUFFER_SIZE; -++ else -++ read_bytes = bytes_left; -++ -++ rc = fread(buf_pfi, 1, read_bytes, fp_pfi); -++ if (rc != read_bytes) { -++ rc = -PFIFLASH_ERR_COMPARE; -++ goto err; -++ } -++ -++ for (i = 0; i < ids_size; i++) { -++ rc = fread(buf_flash[i], 1, read_bytes, fp_flash[i]); -++ if (rc != read_bytes) { -++ rc = -PFIFLASH_CMP_DIFF; -++ goto err; -++ } -++ -++ rc = memcmp(buf_pfi, buf_flash[i], read_bytes); -++ if (rc != 0) { -++ rc = -PFIFLASH_CMP_DIFF; -++ goto err; -++ } -++ } -++ -++ bytes_left -= read_bytes; -++ } -++ -++err: -++ for (i = 0; i < ids_size; i++) -++ free(buf_flash[i]); -++ -++ return rc; -++} -++ -++static int compare_volumes(int devno, pfi_ubi_t u, FILE *fp_pfi, -++ pdd_func_t pdd_f, char *err_buf, size_t err_buf_size) -++{ -++ int rc, is_bootenv = 0; -++ unsigned int i; -++ char path[PATH_MAX]; -++ libubi_t ulib = NULL; -++ FILE *fp_flash[u->ids_size]; -++ -++ ulib = libubi_open(); -++ if (ulib == NULL) { -++ rc = -PFIFLASH_ERR_UBI_OPEN; -++ goto err; -++ } -++ -++ for (i = 0; i < u->ids_size; i++) { -++ if (u->ids[i] == EXAMPLE_BOOTENV_VOL_ID_1 || -++ u->ids[i] == EXAMPLE_BOOTENV_VOL_ID_2) -++ is_bootenv = 1; -++ -++ snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, u->ids[i]); -++ -++ fp_flash[i] = fopen(path, "r"); -++ if (fp_flash[i] == NULL) { -++ rc = -PFIFLASH_ERR_UBI_OPEN; -++ goto err; -++ } -++ } -++ -++ if (is_bootenv) -++ rc = compare_bootenv(fp_pfi, fp_flash, u->ids_size, -++ u->data_size, pdd_f, err_buf, err_buf_size); -++ else -++ rc = compare_data(fp_pfi, fp_flash, u->ids_size, u->data_size); -++ -++err: -++ if (rc < 0) -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ -++ for (i = 0; i < u->ids_size; i++) -++ fclose(fp_flash[i]); -++ if (ulib) -++ libubi_close(ulib); -++ -++ return rc; -++} -++ -++static int -++erase_mtd_region(FILE* file_p, int start, int length) -++{ -++ int rc, fd; -++ erase_info_t erase; -++ mtd_info_t mtdinfo; -++ loff_t offset = start; -++ loff_t end = offset + length; -++ -++ fd = fileno(file_p); -++ if (fd < 0) -++ return -PFIFLASH_ERR_MTD_ERASE; -++ -++ rc = ioctl(fd, MEMGETINFO, &mtdinfo); -++ if (rc) -++ return -PFIFLASH_ERR_MTD_ERASE; -++ -++ /* check for bad blocks in case of NAND flash */ -++ if (mtdinfo.type == MTD_NANDFLASH) { -++ while (offset < end) { -++ rc = ioctl(fd, MEMGETBADBLOCK, &offset); -++ if (rc > 0) { -++ return -PFIFLASH_ERR_MTD_ERASE; -++ } -++ -++ offset += mtdinfo.erasesize; -++ } -++ } -++ -++ erase.start = start; -++ erase.length = length; -++ -++ rc = ioctl(fd, MEMERASE, &erase); -++ if (rc) { -++ return -PFIFLASH_ERR_MTD_ERASE; -++ } -++ -++ return rc; -++} -++ -++/** -++ * process_raw_volumes - writes the raw sections of the PFI data -++ * @pfi PFI data file pointer -++ * @pfi_raws list of PFI raw headers -++ * @rawdev device to use to write raw data -++ * -++ * Error handling: -++ * when early EOF in PFI data -++ * - returns -PFIFLASH_ERR_EOF, err_buf matches text to err -++ * when file I/O error -++ * - returns -PFIFLASH_ERR_FIO, err_buf matches text to err -++ * when CRC check fails -++ * - returns -PFIFLASH_ERR_CRC_CHECK, err_buf matches text to err -++ * when opening MTD device fails -++ * - reutrns -PFIFLASH_ERR_MTD_OPEN, err_buf matches text to err -++ * when closing MTD device fails -++ * - returns -PFIFLASH_ERR_MTD_CLOSE, err_buf matches text to err -++ **/ -++static int -++process_raw_volumes(FILE* pfi, list_t pfi_raws, const char* rawdev, -++ char* err_buf, size_t err_buf_size) -++{ -++ int rc; -++ char *pfi_data; -++ void *i; -++ uint32_t crc, crc32_table[256]; -++ size_t j, k; -++ FILE* mtd = NULL; -++ list_t ptr; -++ -++ if (is_empty(pfi_raws)) -++ return 0; -++ -++ if (rawdev == NULL) -++ return 0; -++ -++ rc = 0; -++ -++ pfi_data = NULL; -++ -++ log_msg("[ rawupdate dev=%s", rawdev); -++ -++ crc = UBI_CRC32_INIT; -++ init_crc32_table(crc32_table); -++ -++ /* most likely only one element in list, but just in case */ -++ foreach(i, ptr, pfi_raws) { -++ pfi_raw_t r = (pfi_raw_t)i; -++ -++ /* read in pfi data */ -++ if (pfi_data != NULL) -++ free(pfi_data); -++ pfi_data = malloc(r->data_size * sizeof(char)); -++ for (j = 0; j < r->data_size; j++) { -++ int c = fgetc(pfi); -++ if (c == EOF) { -++ rc = -PFIFLASH_ERR_EOF; -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } else if (ferror(pfi)) { -++ rc = -PFIFLASH_ERR_FIO; -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } -++ pfi_data[j] = (char)c; -++ } -++ crc = clc_crc32(crc32_table, crc, pfi_data, r->data_size); -++ -++ /* check crc */ -++ if (crc != r->crc) { -++ rc = -PFIFLASH_ERR_CRC_CHECK; -++ EBUF(PFIFLASH_ERRSTR[-rc], r->crc, crc); -++ goto err; -++ } -++ -++ /* open device */ -++ mtd = fopen(rawdev, "r+"); -++ if (mtd == NULL) { -++ rc = -PFIFLASH_ERR_MTD_OPEN; -++ EBUF(PFIFLASH_ERRSTR[-rc], rawdev); -++ goto err; -++ } -++ -++ for (j = 0; j < r->starts_size; j++) { -++ rc = erase_mtd_region(mtd, r->starts[j], r->data_size); -++ if (rc) { -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } -++ -++ fseek(mtd, r->starts[j], SEEK_SET); -++ for (k = 0; k < r->data_size; k++) { -++ int c = fputc((int)pfi_data[k], mtd); -++ if (c == EOF) { -++ fclose(mtd); -++ rc = -PFIFLASH_ERR_EOF; -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } -++ if ((char)c != pfi_data[k]) { -++ fclose(mtd); -++ rc = -1; -++ goto err; -++ } -++ } -++ } -++ rc = fclose(mtd); -++ mtd = NULL; -++ if (rc != 0) { -++ rc = -PFIFLASH_ERR_MTD_CLOSE; -++ EBUF(PFIFLASH_ERRSTR[-rc], rawdev); -++ goto err; -++ } -++ } -++ -++ err: -++ if (mtd != NULL) -++ fclose(mtd); -++ if (pfi_data != NULL) -++ free(pfi_data); -++ return rc; -++} -++ -++ -++/** -++ * erase_unmapped_ubi_volumes - skip volumes provided by PFI file, clear rest -++ * @devno UBI device number -++ * @pfi_ubis list of UBI header data -++ * -++ * Error handling: -++ * when UBI id is out of bounds -++ * - returns -PFIFLASH_ERR_UBI_VID_OOB, err_buf matches text to err -++ * when UBI volume can't be removed -++ * - passes rc, prepends err_buf with contextual aid -++ **/ -++static int -++erase_unmapped_ubi_volumes(int devno, list_t pfi_ubis, -++ char *err_buf, size_t err_buf_size) -++{ -++ int rc; -++ uint8_t ubi_volumes[PFI_UBI_MAX_VOLUMES]; -++ size_t i; -++ list_t ptr; -++ pfi_ubi_t u; -++ -++ rc = 0; -++ -++ for (i = 0; i < PFI_UBI_MAX_VOLUMES; i++) -++ ubi_volumes[i] = 1; -++ -++ foreach(u, ptr, pfi_ubis) { -++ /* iterate over each vol_id */ -++ for(i = 0; i < u->ids_size; i++) { -++ if (u->ids[i] >= PFI_UBI_MAX_VOLUMES) { -++ rc = -PFIFLASH_ERR_UBI_VID_OOB; -++ EBUF(PFIFLASH_ERRSTR[-rc], u->ids[i]); -++ goto err; -++ } -++ /* remove from removal list */ -++ ubi_volumes[u->ids[i]] = 0; -++ } -++ } -++ -++ for (i = 0; i < PFI_UBI_MAX_VOLUMES; i++) { -++ if (ubi_volumes[i]) { -++ rc = my_ubi_rmvol(devno, i, err_buf, err_buf_size); -++ if (rc != 0) { -++ EBUF_PREPEND("remove volume failed"); -++ goto err; -++ } -++ } -++ } -++ -++ err: -++ return rc; -++} -++ -++ -++/** -++ * process_ubi_volumes - delegate tasks regarding UBI volumes -++ * @pfi PFI data file pointer -++ * @seqnum sequence number -++ * @pfi_ubis list of UBI header data -++ * @bootenv_old storage for current system PDD -++ * @pdd_f function to handle PDD -++ * @ubi_update_process whether reading or writing -++ * -++ * Error handling: -++ * when and unknown ubi_update_process is given -++ * - returns -PFIFLASH_ERR_UBI_UNKNOWN, err_buf matches text to err -++ * otherwise -++ * - passes rc and err_buf -++ **/ -++static int -++process_ubi_volumes(FILE* pfi, int seqnum, list_t pfi_ubis, -++ bootenv_t bootenv_old, pdd_func_t pdd_f, -++ ubi_update_process_t ubi_update_process, -++ char *err_buf, size_t err_buf_size) -++{ -++ int rc; -++ pfi_ubi_t u; -++ list_t ptr; -++ -++ rc = 0; -++ -++ foreach(u, ptr, pfi_ubis) { -++ int s = seqnum; -++ -++ if (s > ((int)u->ids_size - 1)) -++ s = 0; /* per default use the first */ -++ u->curr_seqnum = s; -++ -++ switch (ubi_update_process) { -++ case UBI_REMOVE: -++ /* TODO are all these "EXAMPLE" vars okay? */ -++ if ((u->ids[s] == EXAMPLE_BOOTENV_VOL_ID_1) || -++ (u->ids[s] == EXAMPLE_BOOTENV_VOL_ID_2)) { -++ rc = read_bootenv_volume(EXAMPLE_UBI_DEVICE, -++ u->ids[s], bootenv_old, -++ err_buf, err_buf_size); -++ /* it's okay if there is no bootenv -++ * we're going to write one */ -++ if ((rc == -PFIFLASH_ERR_UBI_VOL_FOPEN) || -++ (rc == -PFIFLASH_ERR_BOOTENV_READ)) -++ rc = 0; -++ if (rc != 0) -++ goto err; -++ } -++ -++ rc = my_ubi_rmvol(EXAMPLE_UBI_DEVICE, u->ids[s], -++ err_buf, err_buf_size); -++ if (rc != 0) -++ goto err; -++ -++ break; -++ case UBI_WRITE: -++ rc = my_ubi_mkvol(EXAMPLE_UBI_DEVICE, s, u, -++ err_buf, err_buf_size); -++ if (rc != 0) { -++ EBUF_PREPEND("creating volume"); -++ goto err; -++ } -++ -++ if ((u->ids[s] == EXAMPLE_BOOTENV_VOL_ID_1) || -++ (u->ids[s] == EXAMPLE_BOOTENV_VOL_ID_2)) { -++ rc = write_bootenv_volume(EXAMPLE_UBI_DEVICE, -++ u->ids[s], -++ bootenv_old, pdd_f, -++ pfi, -++ u->data_size, -++ u->crc, -++ err_buf, -++ err_buf_size); -++ if (rc != 0) -++ EBUF_PREPEND("bootenv volume"); -++ } else { -++ rc = write_normal_volume(EXAMPLE_UBI_DEVICE, -++ u->ids[s], -++ u->data_size, pfi, -++ u->crc, -++ err_buf, -++ err_buf_size); -++ if (rc != 0) -++ EBUF_PREPEND("normal volume"); -++ } -++ if (rc != 0) -++ goto err; -++ -++ break; -++ case UBI_COMPARE: -++ rc = compare_volumes(EXAMPLE_UBI_DEVICE, u, pfi, pdd_f, -++ err_buf, err_buf_size); -++ if (rc != 0) { -++ EBUF_PREPEND("compare volume"); -++ goto err; -++ } -++ -++ break; -++ default: -++ rc = -PFIFLASH_ERR_UBI_UNKNOWN; -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } -++ } -++ -++ err: -++ return rc; -++} -++ -++ -++/** -++ * mirror_ubi_volumes - mirror redundant pairs of volumes -++ * @devno UBI device number -++ * @pfi_ubis list of PFI header data -++ * -++ * Error handling: -++ * when UBI system couldn't be opened -++ * - returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err -++ **/ -++static int -++mirror_ubi_volumes(uint32_t devno, list_t pfi_ubis, -++ char *err_buf, size_t err_buf_size) -++{ -++ int rc; -++ uint32_t j; -++ list_t ptr; -++ pfi_ubi_t i; -++ libubi_t ulib; -++ -++ rc = 0; -++ ulib = NULL; -++ -++ log_msg("[ mirror ..."); -++ -++ ulib = libubi_open(); -++ if (ulib == NULL) { -++ rc = -PFIFLASH_ERR_UBI_OPEN; -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } -++ -++ /** -++ * Execute all mirror operations on redundant groups. -++ * Create a volume within a redundant group if it does -++ * not exist already (this is a precondition of -++ * ubimirror). -++ */ -++ foreach(i, ptr, pfi_ubis) { -++ for (j = 0; j < i->ids_size; j++) { -++ /* skip self-match */ -++ if (i->ids[j] == i->ids[i->curr_seqnum]) -++ continue; -++ -++ rc = my_ubi_rmvol(devno, i->ids[j], -++ err_buf, err_buf_size); -++ if (rc != 0) -++ goto err; -++ -++ rc = my_ubi_mkvol(devno, j, i, -++ err_buf, err_buf_size); -++ if (rc != 0) -++ goto err; -++ } -++ } -++ -++ foreach(i, ptr, pfi_ubis) { -++ rc = ubimirror(devno, i->curr_seqnum, i->ids, i->ids_size, -++ err_buf, err_buf_size); -++ if (rc != 0) -++ goto err; -++ } -++ -++ -++ err: -++ if (ulib != NULL) -++ libubi_close(ulib); -++ -++ return rc; -++} -++ -++ -++/** -++ * pfiflash_with_options - exposed func to flash memory with a PFI file -++ * @pfi PFI data file pointer -++ * @complete flag to erase unmapped volumes -++ * @seqnum sequence number -++ * @compare flag to compare -++ * @pdd_handling method to handle pdd (keep, merge, overwrite...) -++ * -++ * Error handling: -++ * when bootenv can't be created -++ * - returns -PFIFLASH_ERR_BOOTENV_CREATE, err_buf matches text to err -++ * when PFI headers can't be read, or -++ * when fail to skip raw sections, or -++ * when error occurs while processing raw volumes, or -++ * when fail to erase unmapped UBI vols, or -++ * when error occurs while processing UBI volumes, or -++ * when error occurs while mirroring UBI volumes -++ * - passes rc, prepends err_buf with contextual aid -++ **/ -++int -++pfiflash_with_options(FILE* pfi, int complete, int seqnum, int compare, -++ pdd_handling_t pdd_handling, const char* rawdev, -++ char *err_buf, size_t err_buf_size) -++{ -++ int rc; -++ bootenv_t bootenv; -++ pdd_func_t pdd_f; -++ -++ if (pfi == NULL) -++ return -EINVAL; -++ -++ rc = 0; -++ pdd_f = NULL; -++ -++ /* If the user didnt specify a seqnum we start per default -++ * with the index 0 */ -++ int curr_seqnum = seqnum < 0 ? 0 : seqnum; -++ -++ list_t pfi_raws = mk_empty(); /* list of raw sections from a pfi */ -++ list_t pfi_ubis = mk_empty(); /* list of ubi sections from a pfi */ -++ -++ rc = bootenv_create(&bootenv); -++ if (rc != 0) { -++ rc = -PFIFLASH_ERR_BOOTENV_CREATE; -++ EBUF(PFIFLASH_ERRSTR[-rc], ""); -++ goto err; -++ } -++ -++ rc = read_pfi_headers(&pfi_raws, &pfi_ubis, pfi, err_buf, err_buf_size); -++ if (rc != 0) { -++ EBUF_PREPEND("reading PFI header"); -++ goto err; -++ } -++ -++ if (rawdev == NULL || compare) -++ rc = skip_raw_volumes(pfi, pfi_raws, err_buf, err_buf_size); -++ else -++ rc = process_raw_volumes(pfi, pfi_raws, rawdev, err_buf, -++ err_buf_size); -++ if (rc != 0) { -++ EBUF_PREPEND("handling raw section"); -++ goto err; -++ } -++ -++ if (complete && !compare) { -++ rc = erase_unmapped_ubi_volumes(EXAMPLE_UBI_DEVICE, pfi_ubis, -++ err_buf, err_buf_size); -++ if (rc != 0) { -++ EBUF_PREPEND("deleting unmapped UBI volumes"); -++ goto err; -++ } -++ } -++ -++ if (((int)pdd_handling >= 0) && -++ (pdd_handling < PDD_HANDLING_NUM)) -++ pdd_f = pdd_funcs[pdd_handling]; -++ else { -++ rc = -PFIFLASH_ERR_PDD_UNKNOWN; -++ EBUF(PFIFLASH_ERRSTR[-rc]); -++ goto err; -++ } -++ -++ if (!compare) { -++ rc = process_ubi_volumes(pfi, curr_seqnum, pfi_ubis, bootenv, -++ pdd_f, UBI_REMOVE, err_buf, err_buf_size); -++ if (rc != 0) { -++ EBUF_PREPEND("removing UBI volumes"); -++ goto err; -++ } -++ -++ rc = process_ubi_volumes(pfi, curr_seqnum, pfi_ubis, bootenv, -++ pdd_f, UBI_WRITE, err_buf, err_buf_size); -++ if (rc != 0) { -++ EBUF_PREPEND("writing UBI volumes"); -++ goto err; -++ } -++ -++ if (seqnum < 0) { /* mirror redundant pairs */ -++ rc = mirror_ubi_volumes(EXAMPLE_UBI_DEVICE, pfi_ubis, -++ err_buf, err_buf_size); -++ if (rc != 0) { -++ EBUF_PREPEND("mirroring UBI volumes"); -++ goto err; -++ } -++ } -++ } else { -++ /* only compare volumes, don't alter the content */ -++ rc = process_ubi_volumes(pfi, curr_seqnum, pfi_ubis, bootenv, -++ pdd_f, UBI_COMPARE, err_buf, err_buf_size); -++ -++ if (rc == -PFIFLASH_CMP_DIFF) -++ /* update is necessary, return positive value */ -++ rc = 1; -++ -++ if (rc < 0) { -++ EBUF_PREPEND("comparing UBI volumes"); -++ goto err; -++ } -++ } -++ -++ err: -++ pfi_raws = remove_all((free_func_t)&free_pfi_raw, pfi_raws); -++ pfi_ubis = remove_all((free_func_t)&free_pfi_ubi, pfi_ubis); -++ bootenv_destroy(&bootenv); -++ return rc; -++} -++ -++ -++/** -++ * pfiflash - passes to pfiflash_with_options -++ * @pfi PFI data file pointer -++ * @complete flag to erase unmapped volumes -++ * @seqnum sequence number -++ * @pdd_handling method to handle pdd (keep, merge, overwrite...) -++ **/ -++int -++pfiflash(FILE* pfi, int complete, int seqnum, pdd_handling_t pdd_handling, -++ char *err_buf, size_t err_buf_size) -++{ -++ return pfiflash_with_options(pfi, complete, seqnum, 0, pdd_handling, -++ NULL, err_buf, err_buf_size); -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/libubi.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/libubi.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/libubi.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/libubi.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,915 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem B. Bityutskiy -++ * -++ * UBI (Unsorted Block Images) library. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "libubi.h" -++#include "libubi_int.h" -++ -++libubi_t libubi_open(void) -++{ -++ int fd, version; -++ struct libubi *lib; -++ -++ lib = calloc(1, sizeof(struct libubi)); -++ if (!lib) -++ return NULL; -++ -++ /* TODO: this must be discovered instead */ -++ lib->sysfs = strdup("/sys"); -++ if (!lib->sysfs) -++ goto error; -++ -++ lib->sysfs_ubi = mkpath(lib->sysfs, SYSFS_UBI); -++ if (!lib->sysfs_ubi) -++ goto error; -++ -++ /* Make sure UBI is present */ -++ fd = open(lib->sysfs_ubi, O_RDONLY); -++ if (fd == -1) -++ goto error; -++ close(fd); -++ -++ lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT); -++ if (!lib->ubi_dev) -++ goto error; -++ -++ lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER); -++ if (!lib->ubi_version) -++ goto error; -++ -++ lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV); -++ if (!lib->dev_dev) -++ goto error; -++ -++ lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS); -++ if (!lib->dev_avail_ebs) -++ goto error; -++ -++ lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS); -++ if (!lib->dev_total_ebs) -++ goto error; -++ -++ lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT); -++ if (!lib->dev_bad_count) -++ goto error; -++ -++ lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE); -++ if (!lib->dev_eb_size) -++ goto error; -++ -++ lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC); -++ if (!lib->dev_max_ec) -++ goto error; -++ -++ lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD); -++ if (!lib->dev_bad_rsvd) -++ goto error; -++ -++ lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS); -++ if (!lib->dev_max_vols) -++ goto error; -++ -++ lib->dev_min_io_size = mkpath(lib->ubi_dev, DEV_MIN_IO_SIZE); -++ if (!lib->dev_min_io_size) -++ goto error; -++ -++ lib->ubi_vol = mkpath(lib->sysfs_ubi, UBI_VOL_NAME_PATT); -++ if (!lib->ubi_vol) -++ goto error; -++ -++ lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE); -++ if (!lib->vol_type) -++ goto error; -++ -++ lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV); -++ if (!lib->vol_dev) -++ goto error; -++ -++ lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT); -++ if (!lib->vol_alignment) -++ goto error; -++ -++ lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES); -++ if (!lib->vol_data_bytes) -++ goto error; -++ -++ lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS); -++ if (!lib->vol_rsvd_ebs) -++ goto error; -++ -++ lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE); -++ if (!lib->vol_eb_size) -++ goto error; -++ -++ lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED); -++ if (!lib->vol_corrupted) -++ goto error; -++ -++ lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME); -++ if (!lib->vol_name) -++ goto error; -++ -++ if (read_int(lib->ubi_version, &version)) -++ goto error; -++ if (version != LIBUBI_UBI_VERSION) { -++ fprintf(stderr, "LIBUBI: this library was made for UBI version " -++ "%d, but UBI version %d is detected\n", -++ LIBUBI_UBI_VERSION, version); -++ goto error; -++ } -++ -++ return lib; -++ -++error: -++ free(lib->vol_corrupted); -++ free(lib->vol_eb_size); -++ free(lib->vol_rsvd_ebs); -++ free(lib->vol_data_bytes); -++ free(lib->vol_alignment); -++ free(lib->vol_dev); -++ free(lib->vol_type); -++ free(lib->ubi_vol); -++ free(lib->dev_min_io_size); -++ free(lib->dev_max_vols); -++ free(lib->dev_bad_rsvd); -++ free(lib->dev_max_ec); -++ free(lib->dev_eb_size); -++ free(lib->dev_bad_count); -++ free(lib->dev_total_ebs); -++ free(lib->dev_avail_ebs); -++ free(lib->dev_dev); -++ free(lib->ubi_version); -++ free(lib->ubi_dev); -++ free(lib->sysfs_ubi); -++ free(lib->sysfs); -++ free(lib); -++ return NULL; -++} -++ -++void libubi_close(libubi_t desc) -++{ -++ struct libubi *lib = (struct libubi *)desc; -++ -++ free(lib->vol_name); -++ free(lib->vol_corrupted); -++ free(lib->vol_eb_size); -++ free(lib->vol_rsvd_ebs); -++ free(lib->vol_data_bytes); -++ free(lib->vol_alignment); -++ free(lib->vol_dev); -++ free(lib->vol_type); -++ free(lib->ubi_vol); -++ free(lib->dev_min_io_size); -++ free(lib->dev_max_vols); -++ free(lib->dev_bad_rsvd); -++ free(lib->dev_max_ec); -++ free(lib->dev_eb_size); -++ free(lib->dev_bad_count); -++ free(lib->dev_total_ebs); -++ free(lib->dev_avail_ebs); -++ free(lib->dev_dev); -++ free(lib->ubi_version); -++ free(lib->ubi_dev); -++ free(lib->sysfs_ubi); -++ free(lib->sysfs); -++ free(lib); -++} -++ -++int ubi_get_info(libubi_t desc, struct ubi_info *info) -++{ -++ DIR *sysfs_ubi; -++ struct dirent *dirent; -++ struct libubi *lib = (struct libubi *)desc; -++ -++ memset(info, '\0', sizeof(struct ubi_info)); -++ -++ /* -++ * We have to scan the UBI sysfs directory to identify how many UBI -++ * devices are present. -++ */ -++ sysfs_ubi = opendir(lib->sysfs_ubi); -++ if (!sysfs_ubi) -++ return -1; -++ -++ info->lowest_dev_num = INT_MAX; -++ while ((dirent = readdir(sysfs_ubi))) { -++ char *name = &dirent->d_name[0]; -++ int dev_num, ret; -++ -++ ret = sscanf(name, UBI_DEV_NAME_PATT, &dev_num); -++ if (ret == 1) { -++ info->dev_count += 1; -++ if (dev_num > info->highest_dev_num) -++ info->highest_dev_num = dev_num; -++ if (dev_num < info->lowest_dev_num) -++ info->lowest_dev_num = dev_num; -++ } -++ } -++ -++ if (info->lowest_dev_num == INT_MAX) -++ info->lowest_dev_num = 0; -++ -++ if (read_int(lib->ubi_version, &info->version)) -++ goto close; -++ -++ return closedir(sysfs_ubi); -++ -++close: -++ closedir(sysfs_ubi); -++ return -1; -++} -++ -++int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req) -++{ -++ int fd, ret; -++ struct ubi_mkvol_req r; -++ size_t n; -++ -++ desc = desc; -++ r.vol_id = req->vol_id; -++ r.alignment = req->alignment; -++ r.bytes = req->bytes; -++ r.vol_type = req->vol_type; -++ -++ n = strlen(req->name); -++ if (n > UBI_MAX_VOLUME_NAME) -++ return -1; -++ -++ strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1); -++ r.name_len = n; -++ -++ fd = open(node, O_RDONLY); -++ if (fd == -1) -++ return -1; -++ -++ ret = ioctl(fd, UBI_IOCMKVOL, &r); -++ if (!ret) -++ req->vol_id = r.vol_id; -++ -++ close(fd); -++ return ret; -++} -++ -++int ubi_rmvol(libubi_t desc, const char *node, int vol_id) -++{ -++ int fd, ret; -++ -++ desc = desc; -++ fd = open(node, O_RDONLY); -++ if (fd == -1) -++ return -1; -++ -++ ret = ioctl(fd, UBI_IOCRMVOL, &vol_id); -++ close(fd); -++ return ret; -++} -++ -++int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes) -++{ -++ int fd, ret; -++ struct ubi_rsvol_req req; -++ -++ desc = desc; -++ fd = open(node, O_RDONLY); -++ if (fd == -1) -++ return -1; -++ -++ req.bytes = bytes; -++ req.vol_id = vol_id; -++ -++ ret = ioctl(fd, UBI_IOCRSVOL, &req); -++ close(fd); -++ return ret; -++} -++ -++int ubi_update_start(libubi_t desc, int fd, long long bytes) -++{ -++ desc = desc; -++ if (ioctl(fd, UBI_IOCVOLUP, &bytes)) -++ return -1; -++ return 0; -++} -++ -++int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info) -++{ -++ int dev_num; -++ struct libubi *lib = (struct libubi *)desc; -++ -++ dev_num = find_dev_num(lib, node); -++ if (dev_num == -1) -++ return -1; -++ -++ return ubi_get_dev_info1(desc, dev_num, info); -++} -++ -++int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info) -++{ -++ DIR *sysfs_ubi; -++ struct dirent *dirent; -++ struct libubi *lib = (struct libubi *)desc; -++ -++ memset(info, '\0', sizeof(struct ubi_dev_info)); -++ info->dev_num = dev_num; -++ -++ sysfs_ubi = opendir(lib->sysfs_ubi); -++ if (!sysfs_ubi) -++ return -1; -++ -++ info->lowest_vol_num = INT_MAX; -++ while ((dirent = readdir(sysfs_ubi))) { -++ char *name = &dirent->d_name[0]; -++ int vol_id, ret, devno; -++ -++ ret = sscanf(name, UBI_VOL_NAME_PATT, &devno, &vol_id); -++ if (ret == 2 && devno == dev_num) { -++ info->vol_count += 1; -++ if (vol_id > info->highest_vol_num) -++ info->highest_vol_num = vol_id; -++ if (vol_id < info->lowest_vol_num) -++ info->lowest_vol_num = vol_id; -++ } -++ } -++ -++ closedir(sysfs_ubi); -++ -++ if (info->lowest_vol_num == INT_MAX) -++ info->lowest_vol_num = 0; -++ -++ if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_ebs)) -++ return -1; -++ if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_ebs)) -++ return -1; -++ if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count)) -++ return -1; -++ if (dev_read_int(lib->dev_eb_size, dev_num, &info->eb_size)) -++ return -1; -++ if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd)) -++ return -1; -++ if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec)) -++ return -1; -++ if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count)) -++ return -1; -++ if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size)) -++ return -1; -++ -++ info->avail_bytes = info->avail_ebs * info->eb_size; -++ info->total_bytes = info->total_ebs * info->eb_size; -++ -++ return 0; -++} -++ -++int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info) -++{ -++ int vol_id, dev_num; -++ struct libubi *lib = (struct libubi *)desc; -++ -++ dev_num = find_dev_num_vol(lib, node); -++ if (dev_num == -1) -++ return -1; -++ -++ vol_id = find_vol_num(lib, dev_num, node); -++ if (vol_id == -1) -++ return -1; -++ -++ return ubi_get_vol_info1(desc, dev_num, vol_id, info); -++} -++ -++int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id, -++ struct ubi_vol_info *info) -++{ -++ int ret; -++ struct libubi *lib = (struct libubi *)desc; -++ char buf[50]; -++ -++ memset(info, '\0', sizeof(struct ubi_vol_info)); -++ info->dev_num = dev_num; -++ info->vol_id = vol_id; -++ -++ ret = vol_read_data(lib->vol_type, dev_num, vol_id, &buf[0], 50); -++ if (ret < 0) -++ return -1; -++ -++ if (strncmp(&buf[0], "static\n", ret) == 0) -++ info->type = UBI_STATIC_VOLUME; -++ else if (strncmp(&buf[0], "dynamic\n", ret) == 0) -++ info->type = UBI_DYNAMIC_VOLUME; -++ else { -++ fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); -++ errno = EINVAL; -++ return -1; -++ } -++ -++ ret = vol_read_int(lib->vol_alignment, dev_num, vol_id, -++ &info->alignment); -++ if (ret) -++ return -1; -++ ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id, -++ &info->data_bytes); -++ if (ret) -++ return -1; -++ ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_ebs); -++ if (ret) -++ return -1; -++ ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->eb_size); -++ if (ret) -++ return -1; -++ ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id, -++ &info->corrupted); -++ if (ret) -++ return -1; -++ info->rsvd_bytes = info->eb_size * info->rsvd_ebs; -++ -++ ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name, -++ UBI_VOL_NAME_MAX + 2); -++ if (ret < 0) -++ return -1; -++ -++ info->name[ret - 1] = '\0'; -++ return 0; -++} -++ -++/** -++ * read_int - read an 'int' value from a file. -++ * -++ * @file the file to read from -++ * @value the result is stored here -++ * -++ * This function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int read_int(const char *file, int *value) -++{ -++ int fd, rd; -++ char buf[50]; -++ -++ fd = open(file, O_RDONLY); -++ if (fd == -1) -++ return -1; -++ -++ rd = read(fd, &buf[0], 50); -++ if (rd == -1) -++ goto error; -++ -++ if (sscanf(&buf[0], "%d\n", value) != 1) { -++ /* This must be a UBI bug */ -++ fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); -++ errno = EINVAL; -++ goto error; -++ } -++ -++ close(fd); -++ return 0; -++ -++error: -++ close(fd); -++ return -1; -++} -++ -++/** -++ * dev_read_int - read an 'int' value from an UBI device's sysfs file. -++ * -++ * @patt the file pattern to read from -++ * @dev_num UBI device number -++ * @value the result is stored here -++ * -++ * This function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int dev_read_int(const char *patt, int dev_num, int *value) -++{ -++ int fd, rd; -++ char buf[50]; -++ char file[strlen(patt) + 50]; -++ -++ sprintf(&file[0], patt, dev_num); -++ fd = open(&file[0], O_RDONLY); -++ if (fd == -1) -++ return -1; -++ -++ rd = read(fd, &buf[0], 50); -++ if (rd == -1) -++ goto error; -++ -++ if (sscanf(&buf[0], "%d\n", value) != 1) { -++ /* This must be a UBI bug */ -++ fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); -++ errno = EINVAL; -++ goto error; -++ } -++ -++ close(fd); -++ return 0; -++ -++error: -++ close(fd); -++ return -1; -++} -++ -++/** -++ * dev_read_ll - read a 'long long' value from an UBI device's sysfs file. -++ * -++ * @patt the file pattern to read from -++ * @dev_num UBI device number -++ * @value the result is stored here -++ * -++ * This function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int dev_read_ll(const char *patt, int dev_num, long long *value) -++{ -++ int fd, rd; -++ char buf[50]; -++ char file[strlen(patt) + 50]; -++ -++ sprintf(&file[0], patt, dev_num); -++ fd = open(&file[0], O_RDONLY); -++ if (fd == -1) -++ return -1; -++ -++ rd = read(fd, &buf[0], 50); -++ if (rd == -1) -++ goto error; -++ -++ if (sscanf(&buf[0], "%lld\n", value) != 1) { -++ /* This must be a UBI bug */ -++ fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); -++ errno = EINVAL; -++ goto error; -++ } -++ -++ close(fd); -++ return 0; -++ -++error: -++ close(fd); -++ return -1; -++} -++ -++/** -++ * dev_read_data - read data from an UBI device's sysfs file. -++ * -++ * @patt the file pattern to read from -++ * @dev_num UBI device number -++ * @buf buffer to read data to -++ * @buf_len buffer length -++ * -++ * This function returns number of read bytes in case of success and %-1 in -++ * case of failure. -++ */ -++static int dev_read_data(const char *patt, int dev_num, void *buf, int buf_len) -++{ -++ int fd, rd; -++ char file[strlen(patt) + 50]; -++ -++ sprintf(&file[0], patt, dev_num); -++ fd = open(&file[0], O_RDONLY); -++ if (fd == -1) -++ return -1; -++ -++ rd = read(fd, buf, buf_len); -++ if (rd == -1) { -++ close(fd); -++ return -1; -++ } -++ -++ close(fd); -++ return rd; -++} -++ -++/** -++ * vol_read_int - read an 'int' value from an UBI volume's sysfs file. -++ * -++ * @patt the file pattern to read from -++ * @dev_num UBI device number -++ * @vol_id volume identifier -++ * @value the result is stored here -++ * -++ * This function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value) -++{ -++ int fd, rd; -++ char buf[50]; -++ char file[strlen(patt) + 100]; -++ -++ sprintf(&file[0], patt, dev_num, vol_id); -++ fd = open(&file[0], O_RDONLY); -++ if (fd == -1) -++ return -1; -++ -++ rd = read(fd, &buf[0], 50); -++ if (rd == -1) -++ goto error; -++ -++ if (sscanf(&buf[0], "%d\n", value) != 1) { -++ /* This must be a UBI bug */ -++ fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); -++ errno = EINVAL; -++ goto error; -++ } -++ -++ close(fd); -++ return 0; -++ -++error: -++ close(fd); -++ return -1; -++} -++ -++/** -++ * vol_read_ll - read a 'long long' value from an UBI volume's sysfs file. -++ * -++ * @patt the file pattern to read from -++ * @dev_num UBI device number -++ * @vol_id volume identifier -++ * @value the result is stored here -++ * -++ * This function returns %0 in case of success and %-1 in case of failure. -++ */ -++static int vol_read_ll(const char *patt, int dev_num, int vol_id, -++ long long *value) -++{ -++ int fd, rd; -++ char buf[50]; -++ char file[strlen(patt) + 100]; -++ -++ sprintf(&file[0], patt, dev_num, vol_id); -++ fd = open(&file[0], O_RDONLY); -++ if (fd == -1) -++ return -1; -++ -++ rd = read(fd, &buf[0], 50); -++ if (rd == -1) -++ goto error; -++ -++ if (sscanf(&buf[0], "%lld\n", value) != 1) { -++ /* This must be a UBI bug */ -++ fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); -++ errno = EINVAL; -++ goto error; -++ } -++ -++ close(fd); -++ return 0; -++ -++error: -++ close(fd); -++ return -1; -++} -++ -++/** -++ * vol_read_data - read data from an UBI volume's sysfs file. -++ * -++ * @patt the file pattern to read from -++ * @dev_num UBI device number -++ * @vol_id volume identifier -++ * @buf buffer to read to -++ * @buf_len buffer length -++ * -++ * This function returns number of read bytes in case of success and %-1 in -++ * case of failure. -++ */ -++static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf, -++ int buf_len) -++{ -++ int fd, rd; -++ char file[strlen(patt) + 100]; -++ -++ sprintf(&file[0], patt, dev_num, vol_id); -++ fd = open(&file[0], O_RDONLY); -++ if (fd == -1) -++ return -1; -++ -++ rd = read(fd, buf, buf_len); -++ if (rd == -1) { -++ close(fd); -++ return -1; -++ } -++ -++ close(fd); -++ return rd; -++} -++ -++/** -++ * mkpath - compose full path from 2 given components. -++ * -++ * @path first component -++ * @name second component -++ * -++ * This function returns the resulting path in case of success and %NULL in -++ * case of failure. -++ */ -++static char *mkpath(const char *path, const char *name) -++{ -++ char *n; -++ int len1 = strlen(path); -++ int len2 = strlen(name); -++ -++ n = malloc(len1 + len2 + 2); -++ if (!n) -++ return NULL; -++ -++ memcpy(n, path, len1); -++ if (n[len1 - 1] != '/') -++ n[len1++] = '/'; -++ -++ memcpy(n + len1, name, len2 + 1); -++ return n; -++} -++ -++/** -++ * find_dev_num - find UBI device number by its character device node. -++ * -++ * @lib UBI library descriptor -++ * @node UBI character device node name -++ * -++ * This function returns positive UBI device number in case of success and %-1 -++ * in case of failure. -++ */ -++static int find_dev_num(struct libubi *lib, const char *node) -++{ -++ struct stat stat; -++ struct ubi_info info; -++ int i, major, minor; -++ -++ if (lstat(node, &stat)) -++ return -1; -++ -++ if (!S_ISCHR(stat.st_mode)) { -++ errno = EINVAL; -++ return -1; -++ } -++ -++ major = major(stat.st_rdev); -++ minor = minor(stat.st_rdev); -++ -++ if (minor != 0) { -++ errno = -EINVAL; -++ return -1; -++ } -++ -++ if (ubi_get_info((libubi_t *)lib, &info)) -++ return -1; -++ -++ for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { -++ int major1, minor1, ret; -++ char buf[50]; -++ -++ ret = dev_read_data(lib->dev_dev, i, &buf[0], 50); -++ if (ret < 0) -++ return -1; -++ -++ ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1); -++ if (ret != 2) { -++ fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); -++ errno = EINVAL; -++ return -1; -++ } -++ -++ if (minor1 == minor && major1 == major) -++ return i; -++ } -++ -++ errno = ENOENT; -++ return -1; -++} -++ -++/** -++ * find_dev_num_vol - find UBI device number by volume character device node. -++ * -++ * @lib UBI library descriptor -++ * @node UBI character device node name -++ * -++ * This function returns positive UBI device number in case of success and %-1 -++ * in case of failure. -++ */ -++static int find_dev_num_vol(struct libubi *lib, const char *node) -++{ -++ struct stat stat; -++ struct ubi_info info; -++ int i, major; -++ -++ if (lstat(node, &stat)) -++ return -1; -++ -++ if (!S_ISCHR(stat.st_mode)) { -++ errno = EINVAL; -++ return -1; -++ } -++ -++ major = major(stat.st_rdev); -++ -++ if (minor(stat.st_rdev) == 0) { -++ errno = -EINVAL; -++ return -1; -++ } -++ -++ if (ubi_get_info((libubi_t *)lib, &info)) -++ return -1; -++ -++ for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { -++ int major1, minor1, ret; -++ char buf[50]; -++ -++ ret = dev_read_data(lib->dev_dev, i, &buf[0], 50); -++ if (ret < 0) -++ return -1; -++ -++ ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1); -++ if (ret != 2) { -++ fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); -++ errno = EINVAL; -++ return -1; -++ } -++ -++ if (major1 == major) -++ return i; -++ } -++ -++ errno = ENOENT; -++ return -1; -++} -++ -++/** -++ * find_vol_num - find UBI volume number by its character device node. -++ * -++ * @lib UBI library descriptor -++ * @dev_num UBI device number -++ * @node UBI volume character device node name -++ * -++ * This function returns positive UBI volume number in case of success and %-1 -++ * in case of failure. -++ */ -++static int find_vol_num(struct libubi *lib, int dev_num, const char *node) -++{ -++ struct stat stat; -++ struct ubi_dev_info info; -++ int i, major, minor; -++ -++ if (lstat(node, &stat)) -++ return -1; -++ -++ if (!S_ISCHR(stat.st_mode)) { -++ errno = EINVAL; -++ return -1; -++ } -++ -++ major = major(stat.st_rdev); -++ minor = minor(stat.st_rdev); -++ -++ if (minor == 0) { -++ errno = -EINVAL; -++ return -1; -++ } -++ -++ if (ubi_get_dev_info1((libubi_t *)lib, dev_num, &info)) -++ return -1; -++ -++ for (i = info.lowest_vol_num; i <= info.highest_vol_num; i++) { -++ int major1, minor1, ret; -++ char buf[50]; -++ -++ ret = vol_read_data(lib->vol_dev, dev_num, i, &buf[0], 50); -++ if (ret < 0) -++ return -1; -++ -++ ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1); -++ if (ret != 2) { -++ fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); -++ errno = EINVAL; -++ return -1; -++ } -++ -++ if (minor1 == minor && major1 == major) -++ return i; -++ } -++ -++ errno = ENOENT; -++ return -1; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/libubi_int.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/libubi_int.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/libubi_int.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/libubi_int.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,129 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Artem B. Bityutskiy -++ * -++ * UBI (Unsorted Block Images) library. -++ */ -++ -++#ifndef __LIBUBI_INT_H__ -++#define __LIBUBI_INT_H__ -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++/* -++ * UBI heavily makes use of the sysfs file system to interact with users-pace. -++ * The below are pre-define UBI file and directory names. -++ */ -++ -++#define SYSFS_UBI "class/ubi" -++#define UBI_DEV_NAME_PATT "ubi%d" -++#define UBI_VER "version" -++#define DEV_DEV "dev" -++#define UBI_VOL_NAME_PATT "ubi%d_%d" -++#define DEV_AVAIL_EBS "avail_eraseblocks" -++#define DEV_TOTAL_EBS "total_eraseblocks" -++#define DEV_BAD_COUNT "bad_peb_count" -++#define DEV_EB_SIZE "eraseblock_size" -++#define DEV_MAX_EC "max_ec" -++#define DEV_MAX_RSVD "reserved_for_bad" -++#define DEV_MAX_VOLS "max_vol_count" -++#define DEV_MIN_IO_SIZE "min_io_size" -++#define VOL_TYPE "type" -++#define VOL_DEV "dev" -++#define VOL_ALIGNMENT "alignment" -++#define VOL_DATA_BYTES "data_bytes" -++#define VOL_RSVD_EBS "reserved_ebs" -++#define VOL_EB_SIZE "usable_eb_size" -++#define VOL_CORRUPTED "corrupted" -++#define VOL_NAME "name" -++ -++/** -++ * libubi - UBI library description data structure. -++ * -++ * @sysfs sysfs file system path -++ * @sysfs_ubi UBI directory in sysfs -++ * @ubi_dev UBI device sysfs directory pattern -++ * @ubi_version UBI version file sysfs path -++ * @dev_dev UBI device's major/minor numbers file pattern -++ * @dev_avail_ebs count of available eraseblocks sysfs path pattern -++ * @dev_total_ebs total eraseblocks count sysfs path pattern -++ * @dev_bad_count count of bad eraseblocks sysfs path pattern -++ * @dev_eb_size size of UBI device's eraseblocks sysfs path pattern -++ * @dev_max_ec maximum erase counter sysfs path pattern -++ * @dev_bad_rsvd count of physical eraseblock reserved for bad eraseblocks -++ * handling -++ * @dev_max_vols maximum volumes number count sysfs path pattern -++ * @dev_min_io_size minimum I/O unit size sysfs path pattern -++ * @ubi_vol UBI volume sysfs directory pattern -++ * @vol_type volume type sysfs path pattern -++ * @vol_dev volume's major/minor numbers file pattern -++ * @vol_alignment volume alignment sysfs path pattern -++ * @vol_data_bytes volume data size sysfs path pattern -++ * @vol_rsvd_ebs volume reserved size sysfs path pattern -++ * @vol_eb_size volume eraseblock size sysfs path pattern -++ * @vol_corrupted volume corruption flag sysfs path pattern -++ * @vol_name volume name sysfs path pattern -++ */ -++struct libubi -++{ -++ char *sysfs; -++ char *sysfs_ubi; -++ char *ubi_dev; -++ char *ubi_version; -++ char *dev_dev; -++ char *dev_avail_ebs; -++ char *dev_total_ebs; -++ char *dev_bad_count; -++ char *dev_eb_size; -++ char *dev_max_ec; -++ char *dev_bad_rsvd; -++ char *dev_max_vols; -++ char *dev_min_io_size; -++ char *ubi_vol; -++ char *vol_type; -++ char *vol_dev; -++ char *vol_alignment; -++ char *vol_data_bytes; -++ char *vol_rsvd_ebs; -++ char *vol_eb_size; -++ char *vol_corrupted; -++ char *vol_name; -++ char *vol_max_count; -++}; -++ -++static int read_int(const char *file, int *value); -++static int dev_read_int(const char *patt, int dev_num, int *value); -++static int dev_read_ll(const char *patt, int dev_num, long long *value); -++static int dev_read_data(const char *patt, int dev_num, void *buf, int buf_len); -++static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value); -++static int vol_read_ll(const char *patt, int dev_num, int vol_id, -++ long long *value); -++static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf, -++ int buf_len); -++static char *mkpath(const char *path, const char *name); -++static int find_dev_num(struct libubi *lib, const char *node); -++static int find_dev_num_vol(struct libubi *lib, const char *node); -++static int find_vol_num(struct libubi *lib, int dev_num, const char *node); -++ -++#ifdef __cplusplus -++} -++#endif -++ -++#endif /* !__LIBUBI_INT_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/libubigen.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/libubigen.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/libubigen.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/libubigen.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,487 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ * -++ * Add UBI headers to binary data. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "config.h" -++#include "ubigen.h" -++#include "crc32.h" -++ -++#define UBI_NAME_SIZE 256 -++#define DEFAULT_VID_OFFSET ((DEFAULT_PAGESIZE) - (UBI_VID_HDR_SIZE)) -++#define MIN(a,b) ((a) < (b) ? (a) : (b)) -++ -++static uint32_t crc32_table[256]; -++ -++struct ubi_info { -++ struct ubi_vid_hdr* v; /* Volume ID header */ -++ struct ubi_ec_hdr* ec; /* Erase count header */ -++ -++ FILE* fp_in; /* Input Stream */ -++ FILE* fp_out; /* Output stream */ -++ -++ size_t eb_size; /* Physical EB size in bytes */ -++ size_t leb_size; /* Size of a logical EB in a physical EB */ -++ size_t leb_total; /* Total input size in logical EB */ -++ size_t alignment; /* Block alignment */ -++ size_t data_pad; /* Size of padding in each physical EB */ -++ -++ size_t bytes_total; /* Total input size in bytes */ -++ size_t bytes_read; /* Nymber of read bytes (total) */ -++ -++ uint32_t blks_written; /* Number of written logical EB */ -++ -++ uint8_t* buf; /* Allocated buffer */ -++ uint8_t* ptr_ec_hdr; /* Pointer to EC hdr in buf */ -++ uint8_t* ptr_vid_hdr; /* Pointer to VID hdr in buf */ -++ uint8_t* ptr_data; /* Pointer to data region in buf */ -++}; -++ -++ -++static uint32_t -++byte_to_blk(uint64_t byte, uint32_t eb_size) -++{ -++ return (byte % eb_size) == 0 -++ ? (byte / eb_size) -++ : (byte / eb_size) + 1; -++} -++ -++static int -++validate_ubi_info(ubi_info_t u) -++{ -++ if ((u->v->vol_type != UBI_VID_DYNAMIC) && -++ (u->v->vol_type != UBI_VID_STATIC)) { -++ return EUBIGEN_INVALID_TYPE; -++ } -++ -++ if (be32_to_cpu(u->ec->vid_hdr_offset) < UBI_VID_HDR_SIZE) { -++ return EUBIGEN_INVALID_HDR_OFFSET; -++ } -++ -++ return 0; -++} -++ -++static int -++skip_blks(ubi_info_t u, uint32_t blks) -++{ -++ uint32_t i; -++ size_t read = 0, to_read = 0; -++ -++ /* Step to a maximum of leb_total - 1 to keep the -++ restrictions. */ -++ for (i = 0; i < MIN(blks, u->leb_total-1); i++) { -++ /* Read in data */ -++ to_read = MIN(u->leb_size, -++ (u->bytes_total - u->bytes_read)); -++ read = fread(u->ptr_data, 1, to_read, u->fp_in); -++ if (read != to_read) { -++ return -EIO; -++ } -++ u->bytes_read += read; -++ u->blks_written++; -++ } -++ -++ return 0; -++} -++ -++static void -++clear_buf(ubi_info_t u) -++{ -++ memset(u->buf, 0xff, u->eb_size); -++} -++ -++static void -++write_ec_hdr(ubi_info_t u) -++{ -++ memcpy(u->ptr_ec_hdr, u->ec, UBI_EC_HDR_SIZE); -++} -++ -++static int -++fill_data_buffer_from_file(ubi_info_t u, size_t* read) -++{ -++ size_t to_read = 0; -++ -++ if (u-> fp_in == NULL) -++ return -EIO; -++ -++ to_read = MIN(u->leb_size, (u->bytes_total - u->bytes_read)); -++ *read = fread(u->ptr_data, 1, to_read, u->fp_in); -++ if (*read != to_read) { -++ return -EIO; -++ } -++ return 0; -++} -++ -++static void -++add_static_info(ubi_info_t u, size_t data_size, ubigen_action_t action) -++{ -++ uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT, -++ u->ptr_data, data_size); -++ -++ u->v->data_size = cpu_to_be32(data_size); -++ u->v->data_crc = cpu_to_be32(crc); -++ -++ if (action & BROKEN_DATA_CRC) { -++ u->v->data_crc = -++ cpu_to_be32(be32_to_cpu(u->v->data_crc) + 1); -++ } -++ if (action & BROKEN_DATA_SIZE) { -++ u->v->data_size = -++ cpu_to_be32(be32_to_cpu(u->v->data_size) + 1); -++ } -++} -++ -++static void -++write_vid_hdr(ubi_info_t u, ubigen_action_t action) -++{ -++ uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT, -++ u->v, UBI_VID_HDR_SIZE_CRC); -++ /* Write VID header */ -++ u->v->hdr_crc = cpu_to_be32(crc); -++ if (action & BROKEN_HDR_CRC) { -++ u->v->hdr_crc = cpu_to_be32(be32_to_cpu(u->v->hdr_crc) + 1); -++ } -++ memcpy(u->ptr_vid_hdr, u->v, UBI_VID_HDR_SIZE); -++} -++ -++static int -++write_to_output_stream(ubi_info_t u) -++{ -++ size_t written; -++ -++ written = fwrite(u->buf, 1, u->eb_size, u->fp_out); -++ if (written != u->eb_size) { -++ return -EIO; -++ } -++ return 0; -++} -++ -++int -++ubigen_write_leb(ubi_info_t u, ubigen_action_t action) -++{ -++ int rc = 0; -++ size_t read = 0; -++ -++ clear_buf(u); -++ write_ec_hdr(u); -++ -++ rc = fill_data_buffer_from_file(u, &read); -++ if (rc != 0) -++ return rc; -++ -++ if (u->v->vol_type == UBI_VID_STATIC) { -++ add_static_info(u, read, action); -++ } -++ -++ u->v->lnum = cpu_to_be32(u->blks_written); -++ -++ if (action & MARK_AS_UPDATE) { -++ u->v->copy_flag = (u->v->copy_flag)++; -++ } -++ -++ write_vid_hdr(u, action); -++ rc = write_to_output_stream(u); -++ if (rc != 0) -++ return rc; -++ -++ /* Update current handle */ -++ u->bytes_read += read; -++ u->blks_written++; -++ return 0; -++} -++ -++int -++ubigen_write_complete(ubi_info_t u) -++{ -++ size_t i; -++ int rc = 0; -++ -++ for (i = 0; i < u->leb_total; i++) { -++ rc = ubigen_write_leb(u, NO_ERROR); -++ if (rc != 0) -++ return rc; -++ } -++ -++ return 0; -++} -++ -++int -++ubigen_write_broken_update(ubi_info_t u, uint32_t blk) -++{ -++ int rc = 0; -++ -++ rc = skip_blks(u, blk); -++ if (rc != 0) -++ return rc; -++ -++ rc = ubigen_write_leb(u, MARK_AS_UPDATE | BROKEN_DATA_CRC); -++ if (rc != 0) -++ return rc; -++ -++ -++ return 0; -++} -++ -++void -++dump_info(ubi_info_t u ubi_unused) -++{ -++#ifdef DEBUG -++ int err = 0; -++ if (!u) { -++ fprintf(stderr, ""); -++ return; -++ } -++ if (!u->ec) { -++ fprintf(stderr, ""); -++ err = 1; -++ } -++ if (!u->v) { -++ fprintf(stderr, ""); -++ err = 1; -++ } -++ if (err) return; -++ -++ fprintf(stderr, "ubi volume\n"); -++ fprintf(stderr, "version : %8d\n", u->v->version); -++ fprintf(stderr, "vol_id : %8d\n", be32_to_cpu(u->v->vol_id)); -++ fprintf(stderr, "vol_type : %8s\n", -++ u->v->vol_type == UBI_VID_STATIC ? -++ "static" : "dynamic"); -++ fprintf(stderr, "used_ebs : %8d\n", -++ be32_to_cpu(u->v->used_ebs)); -++ fprintf(stderr, "eb_size : 0x%08x\n", u->eb_size); -++ fprintf(stderr, "leb_size : 0x%08x\n", u->leb_size); -++ fprintf(stderr, "data_pad : 0x%08x\n", -++ be32_to_cpu(u->v->data_pad)); -++ fprintf(stderr, "leb_total : %8d\n", u->leb_total); -++ fprintf(stderr, "header offs : 0x%08x\n", -++ be32_to_cpu(u->ec->vid_hdr_offset)); -++ fprintf(stderr, "bytes_total : %8d\n", u->bytes_total); -++ fprintf(stderr, " + in MiB : %8.2f M\n", -++ ((float)(u->bytes_total)) / 1024 / 1024); -++ fprintf(stderr, "-------------------------------\n\n"); -++#else -++ return; -++#endif -++} -++ -++int -++ubigen_destroy(ubi_info_t *u) -++{ -++ if (u == NULL) -++ return -EINVAL; -++ -++ ubi_info_t tmp = *u; -++ -++ if (tmp) { -++ if (tmp->v) -++ free(tmp->v); -++ if (tmp->ec) -++ free(tmp->ec); -++ if (tmp->buf) -++ free(tmp->buf); -++ free(tmp); -++ } -++ *u = NULL; -++ return 0; -++} -++ -++void -++ubigen_init(void) -++{ -++ init_crc32_table(crc32_table); -++} -++ -++int -++ubigen_create(ubi_info_t* u, uint32_t vol_id, uint8_t vol_type, -++ uint32_t eb_size, uint64_t ec, uint32_t alignment, -++ uint8_t version, uint32_t vid_hdr_offset, uint8_t compat_flag, -++ size_t data_size, FILE* fp_in, FILE* fp_out) -++{ -++ int rc = 0; -++ ubi_info_t res = NULL; -++ uint32_t crc; -++ uint32_t data_offset; -++ -++ if (alignment == 0) { -++ rc = EUBIGEN_INVALID_ALIGNMENT; -++ goto ubigen_create_err; -++ } -++ if ((fp_in == NULL) || (fp_out == NULL)) { -++ rc = -EINVAL; -++ goto ubigen_create_err; -++ } -++ -++ res = (ubi_info_t) calloc(1, sizeof(struct ubi_info)); -++ if (res == NULL) { -++ rc = -ENOMEM; -++ goto ubigen_create_err; -++ } -++ -++ res->v = (struct ubi_vid_hdr*) calloc(1, sizeof(struct ubi_vid_hdr)); -++ if (res->v == NULL) { -++ rc = -ENOMEM; -++ goto ubigen_create_err; -++ } -++ -++ res->ec = (struct ubi_ec_hdr*) calloc(1, sizeof(struct ubi_ec_hdr)); -++ if (res->ec == NULL) { -++ rc = -ENOMEM; -++ goto ubigen_create_err; -++ } -++ -++ /* data which is needed in the general process */ -++ vid_hdr_offset = vid_hdr_offset ? vid_hdr_offset : DEFAULT_VID_OFFSET; -++ data_offset = vid_hdr_offset + UBI_VID_HDR_SIZE; -++ res->bytes_total = data_size; -++ res->eb_size = eb_size ? eb_size : DEFAULT_BLOCKSIZE; -++ res->data_pad = (res->eb_size - data_offset) % alignment; -++ res->leb_size = res->eb_size - data_offset - res->data_pad; -++ res->leb_total = byte_to_blk(data_size, res->leb_size); -++ res->alignment = alignment; -++ -++ if ((res->eb_size < (vid_hdr_offset + UBI_VID_HDR_SIZE))) { -++ rc = EUBIGEN_TOO_SMALL_EB; -++ goto ubigen_create_err; -++ } -++ res->fp_in = fp_in; -++ res->fp_out = fp_out; -++ -++ /* vid hdr data which doesn't change */ -++ res->v->magic = cpu_to_be32(UBI_VID_HDR_MAGIC); -++ res->v->version = version ? version : UBI_VERSION; -++ res->v->vol_type = vol_type; -++ res->v->vol_id = cpu_to_be32(vol_id); -++ res->v->compat = compat_flag; -++ res->v->data_pad = cpu_to_be32(res->data_pad); -++ -++ /* static only: used_ebs */ -++ if (res->v->vol_type == UBI_VID_STATIC) { -++ res->v->used_ebs = cpu_to_be32(byte_to_blk -++ (res->bytes_total, -++ res->leb_size)); -++ } -++ -++ /* ec hdr (fixed, doesn't change) */ -++ res->ec->magic = cpu_to_be32(UBI_EC_HDR_MAGIC); -++ res->ec->version = version ? version : UBI_VERSION; -++ res->ec->ec = cpu_to_be64(ec); -++ res->ec->vid_hdr_offset = cpu_to_be32(vid_hdr_offset); -++ -++ res->ec->data_offset = cpu_to_be32(data_offset); -++ -++ crc = clc_crc32(crc32_table, UBI_CRC32_INIT, res->ec, -++ UBI_EC_HDR_SIZE_CRC); -++ res->ec->hdr_crc = cpu_to_be32(crc); -++ -++ /* prepare a read buffer */ -++ res->buf = (uint8_t*) malloc (res->eb_size * sizeof(uint8_t)); -++ if (res->buf == NULL) { -++ rc = -ENOMEM; -++ goto ubigen_create_err; -++ } -++ -++ /* point to distinct regions within the buffer */ -++ res->ptr_ec_hdr = res->buf; -++ res->ptr_vid_hdr = res->buf + be32_to_cpu(res->ec->vid_hdr_offset); -++ res->ptr_data = res->buf + be32_to_cpu(res->ec->vid_hdr_offset) -++ + UBI_VID_HDR_SIZE; -++ -++ rc = validate_ubi_info(res); -++ if (rc != 0) { -++ fprintf(stderr, "Volume validation failed: %d\n", rc); -++ goto ubigen_create_err; -++ } -++ -++ dump_info(res); -++ *u = res; -++ return rc; -++ -++ ubigen_create_err: -++ if (res) { -++ if (res->v) -++ free(res->v); -++ if (res->ec) -++ free(res->ec); -++ if (res->buf) -++ free(res->buf); -++ free(res); -++ } -++ *u = NULL; -++ return rc; -++} -++ -++int -++ubigen_get_leb_size(ubi_info_t u, size_t* size) -++{ -++ if (u == NULL) -++ return -EINVAL; -++ -++ *size = u->leb_size; -++ return 0; -++} -++ -++ -++int -++ubigen_get_leb_total(ubi_info_t u, size_t* total) -++{ -++ if (u == NULL) -++ return -EINVAL; -++ -++ *total = u->leb_total; -++ return 0; -++} -++ -++int -++ubigen_set_lvol_rec(ubi_info_t u, size_t reserved_bytes, -++ const char* vol_name, struct ubi_vtbl_record *lvol_rec) -++{ -++ uint32_t crc; -++ -++ if ((u == NULL) || (vol_name == NULL)) -++ return -EINVAL; -++ -++ memset(lvol_rec, 0x0, UBI_VTBL_RECORD_SIZE); -++ -++ lvol_rec->reserved_pebs = -++ cpu_to_be32(byte_to_blk(reserved_bytes, u->leb_size)); -++ lvol_rec->alignment = cpu_to_be32(u->alignment); -++ lvol_rec->data_pad = u->v->data_pad; -++ lvol_rec->vol_type = u->v->vol_type; -++ -++ lvol_rec->name_len = -++ cpu_to_be16((uint16_t)strlen((const char*)vol_name)); -++ -++ memcpy(lvol_rec->name, vol_name, UBI_VOL_NAME_MAX + 1); -++ -++ crc = clc_crc32(crc32_table, UBI_CRC32_INIT, -++ lvol_rec, UBI_VTBL_RECORD_SIZE_CRC); -++ lvol_rec->crc = cpu_to_be32(crc); -++ -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/libubimirror.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/libubimirror.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/libubimirror.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/libubimirror.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,237 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include "ubimirror.h" -++ -++#define COMPARE_BUF_SIZE (128 * 1024) -++ -++#define DEFAULT_DEV_PATTERN "/dev/ubi%d" -++#define DEFAULT_VOL_PATTERN "/dev/ubi%d_%d" -++ -++#define EBUF(fmt...) do { \ -++ snprintf(err_buf, err_buf_size, fmt); \ -++} while (0) -++ -++enum { -++ compare_error = -1, -++ seek_error = -2, -++ write_error = -3, -++ read_error = -4, -++ update_error = -5, -++ ubi_error = -6, -++ open_error = -7, -++ close_error = -8, -++ compare_equal = 0, -++ compare_different = 1 -++}; -++ -++/* -++ * Read len number of bytes from fd. -++ * Return 0 on EOF, -1 on error. -++ */ -++static ssize_t fill_buffer(int fd, unsigned char *buf, ssize_t len) -++{ -++ ssize_t got, have = 0; -++ -++ do { -++ got = read(fd, buf + have, len - have); -++ if (got == -1 && errno != EINTR) -++ return -1; -++ have += got; -++ } while (got > 0 && have < len); -++ return have; -++} -++ -++/* -++ * Write len number of bytes to fd. -++ * Return bytes written (>= 0), -1 on error. -++ */ -++static ssize_t flush_buffer(int fd, unsigned char *buf, ssize_t len) -++{ -++ ssize_t done, have = 0; -++ -++ do { -++ done = write(fd, buf + have, len - have); -++ if (done == -1 && errno != EINTR) -++ return -1; -++ have += done; -++ } while (done > 0 && have < len); -++ return have; -++} -++ -++/* -++ * Compare two files. Return 0, 1, or -1, depending on whether the -++ * files are equal, different, or an error occured. -++ * Return compare-different when target volume can not be read. Might be -++ * an interrupted volume update and then the target device returns -EIO but -++ * can be updated. -++ * -++ * fd_a is source -++ * fd_b is destination -++ */ -++static int compare_files(int fd_a, int fd_b) -++{ -++ unsigned char buf_a[COMPARE_BUF_SIZE], buf_b[COMPARE_BUF_SIZE]; -++ ssize_t len_a, len_b; -++ int rc; -++ -++ for (;;) { -++ len_a = fill_buffer(fd_a, buf_a, sizeof(buf_a)); -++ if (len_a == -1) { -++ rc = compare_error; -++ break; -++ } -++ len_b = fill_buffer(fd_b, buf_b, sizeof(buf_b)); -++ if (len_b == -1) { -++ rc = compare_different; -++ break; -++ } -++ if (len_a != len_b) { -++ rc = compare_different; -++ break; -++ } -++ if (len_a == 0) { /* Size on both files equal and EOF */ -++ rc = compare_equal; -++ break; -++ } -++ if (memcmp(buf_a, buf_b, len_a) != 0 ) { -++ rc = compare_different; -++ break; -++ } -++ } -++ /* Position both files at the beginning */ -++ if (lseek(fd_a, 0, SEEK_SET) == -1 || -++ lseek(fd_b, 0, SEEK_SET) == -1) -++ rc = seek_error; -++ return rc; -++} -++ -++int vol_get_used_bytes(int vol_fd, unsigned long long *bytes) -++{ -++ off_t res; -++ -++ res = lseek(vol_fd, 0, SEEK_END); -++ if (res == (off_t)-1) -++ return -1; -++ *bytes = (unsigned long long) res; -++ res = lseek(vol_fd, 0, SEEK_SET); -++ return res == (off_t)-1 ? -1 : 0; -++} -++ -++static int copy_files(libubi_t ulib, int fd_in, int fd_out) -++{ -++ unsigned char buf_a[COMPARE_BUF_SIZE]; -++ ssize_t len_a, len_b; -++ unsigned long long update_size, copied; -++ -++ if (vol_get_used_bytes(fd_in, &update_size) == -1 || -++ ubi_update_start(ulib, fd_out, update_size) == -1) -++ return update_error; -++ for (copied = 0; copied < update_size; copied += len_b ) { -++ len_a = fill_buffer(fd_in, buf_a, sizeof(buf_a)); -++ if (len_a == -1) -++ return read_error; -++ if (len_a == 0) /* Reach EOF */ -++ return 0; -++ len_b = flush_buffer(fd_out, buf_a, len_a); -++ if (len_b != len_a) -++ return write_error; -++ } -++ return 0; -++} -++ -++int ubimirror(uint32_t devno, int seqnum, uint32_t *ids, ssize_t ids_size, -++ char *err_buf, size_t err_buf_size) -++{ -++ int rc = 0; -++ uint32_t src_id; -++ char path[PATH_MAX]; -++ libubi_t ulib; -++ int fd_in = -1, i = 0, fd_out = -1; -++ -++ if (ids_size == 0) -++ return 0; -++ else { -++ if ((seqnum < 0) || (seqnum > (ids_size - 1))) { -++ EBUF("volume id %d out of range", seqnum); -++ return EUBIMIRROR_NO_SRC; -++ } -++ src_id = ids[seqnum]; -++ } -++ -++ ulib = libubi_open(); -++ if (ulib == NULL) -++ return ubi_error; -++ -++ snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, src_id); -++ -++ fd_in = open(path, O_RDONLY); -++ if (fd_in == -1) { -++ EBUF("open error source volume %d", ids[i]); -++ rc = open_error; -++ goto err; -++ } -++ -++ for (i = 0; i < ids_size; i++) { -++ if (ids[i] == src_id) /* skip self-mirror */ -++ continue; -++ -++ snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, ids[i]); -++ -++ fd_out = open(path, O_RDWR); -++ if (fd_out < 0){ -++ EBUF("open error destination volume %d", ids[i]); -++ rc = open_error; -++ goto err; -++ } -++ rc = compare_files(fd_in, fd_out); -++ if (rc < 0) { -++ EBUF("compare error volume %d and %d", src_id, ids[i]); -++ goto err; -++ } else if (rc == compare_different) { -++ rc = copy_files(ulib, fd_in, fd_out); -++ if (rc != 0) { -++ EBUF("mirror error volume %d to %d", src_id, -++ ids[i]); -++ goto err; -++ } -++ } -++ if ((rc = close(fd_out)) == -1) { -++ EBUF("close error volume %d", ids[i]); -++ rc = close_error; -++ goto err; -++ } else -++ fd_out = -1; -++ } -++err: -++ if (fd_out != -1) -++ close(fd_out); -++ if (fd_in != -1) -++ close(fd_in); -++ if (ulib != NULL) -++ libubi_close(ulib); -++ return rc; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/list.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/list.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/list.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/list.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,149 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ */ -++ -++#include -++#include -++#include -++ -++#include "list.h" -++ -++list_t -++mk_empty(void) -++{ -++ return (list_t) NULL; -++} -++ -++int -++is_empty(list_t l) -++{ -++ return l == NULL; -++} -++ -++info_t -++head(list_t l) -++{ -++ assert(!is_empty(l)); -++ return l->info; -++} -++ -++list_t -++tail(list_t l) -++{ -++ assert(!is_empty(l)); -++ return l->next; -++} -++ -++list_t -++remove_head(list_t l) -++{ -++ list_t res; -++ assert(!is_empty(l)); -++ -++ res = l->next; -++ free(l); -++ return res; -++} -++ -++list_t -++cons(info_t e, list_t l) -++{ -++ list_t res = malloc(sizeof(*l)); -++ if (!res) -++ return NULL; -++ res->info = e; -++ res->next = l; -++ -++ return res; -++} -++ -++list_t -++prepend_elem(info_t e, list_t l) -++{ -++ return cons(e,l); -++} -++ -++list_t -++append_elem(info_t e, list_t l) -++{ -++ if (is_empty(l)) { -++ return cons(e,l); -++ } -++ l->next = append_elem(e, l->next); -++ -++ return l; -++} -++ -++list_t -++insert_sorted(cmp_func_t cmp, info_t e, list_t l) -++{ -++ if (is_empty(l)) -++ return cons(e, l); -++ -++ switch (cmp(e, l->info)) { -++ case -1: -++ case 0: -++ return l; -++ break; -++ case 1: -++ l->next = insert_sorted(cmp, e, l); -++ break; -++ default: -++ break; -++ } -++ -++ /* never reached */ -++ return NULL; -++} -++ -++list_t -++remove_all(free_func_t free_func, list_t l) -++{ -++ if (is_empty(l)) -++ return l; -++ list_t lnext = l->next; -++ -++ if (free_func && l->info) { -++ free_func(&(l->info)); -++ } -++ free(l); -++ -++ return remove_all(free_func, lnext); -++} -++ -++ -++info_t -++is_in(cmp_func_t cmp, info_t e, list_t l) -++{ -++ return -++ (is_empty(l)) -++ ? NULL -++ : (cmp(e, l->info)) == 0 ? l->info : is_in(cmp, e, l->next); -++} -++ -++ -++void -++apply(process_func_t process_func, list_t l) -++{ -++ list_t ptr; -++ void *i; -++ foreach(i, ptr, l) { -++ process_func(i); -++ } -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/list.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/list.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/list.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/list.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,56 @@ -++#ifndef __LIST_H__ -++#define __LIST_H__ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ */ -++ -++#include -++ -++#define foreach(elem, ptr, list) \ -++ for (elem = list != NULL ? (typeof(elem)) head(list) \ -++ : NULL, ptr = list; \ -++ ptr != NULL; \ -++ ptr = tail(ptr), \ -++ elem = (typeof(elem)) ptr ? head(ptr) : NULL) -++ -++typedef struct node* list_t; -++typedef void* info_t; -++typedef int (*free_func_t)(info_t*); -++typedef int (*cmp_func_t)(info_t, info_t); -++typedef void (*process_func_t)(info_t); -++ -++struct node { -++ list_t next; -++ info_t info; -++}; -++ -++list_t mk_empty(void); -++int is_empty(list_t l); -++info_t is_in(cmp_func_t cmp, info_t e, list_t l); -++info_t head(list_t l); -++list_t tail(list_t l); -++list_t remove_head(list_t l); -++list_t cons(info_t e, list_t l); -++list_t prepend_elem(info_t e, list_t); -++list_t append_elem(info_t e, list_t); -++list_t remove_all(free_func_t free_func, list_t l); -++list_t insert_sorted(cmp_func_t cmp_func, info_t e, list_t l); -++void apply(process_func_t process_func, list_t l); -++ -++#endif /* __LIST_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/mkbootenv.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/mkbootenv.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/mkbootenv.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/mkbootenv.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,168 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ * -++ * Create boot-parameter/pdd data from an ASCII-text input file. -++ * -++ * 1.2 Removed argp because we want to use uClibc. -++ * 1.3 Minor cleanup -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "config.h" -++#include "bootenv.h" -++#include "error.h" -++ -++#define PROGRAM_VERSION "1.3" -++ -++static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" -++ "mkbootenv - processes bootenv text files and convertes " -++ "them into a binary format.\n"; -++ -++static const char copyright [] __attribute__((unused)) = -++ "Copyright (c) International Business Machines Corp., 2006"; -++ -++static const char *optionsstr = -++" -c, --copyright Print copyright informatoin.\n" -++" -o, --output= Write the output data to instead of\n" -++" stdout.\n" -++" -?, --help Give this help list\n" -++" --usage Give a short usage message\n" -++" -V, --version Print program version\n"; -++ -++static const char *usage = -++"Usage: mkbootenv [-c?V] [-o ] [--copyright] [--output=]\n" -++" [--help] [--usage] [--version] [bootenv-txt-file]\n"; -++ -++struct option long_options[] = { -++ { .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' }, -++ { .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, -++ { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ { NULL, 0, NULL, 0} -++}; -++ -++typedef struct myargs { -++ FILE* fp_in; -++ FILE* fp_out; -++ -++ char *arg1; -++ char **options; /* [STRING...] */ -++} myargs; -++ -++static int -++parse_opt(int argc, char **argv, myargs *args) -++{ -++ while (1) { -++ int key; -++ -++ key = getopt_long(argc, argv, "co:?V", long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ case 'c': -++ fprintf(stderr, "%s\n", copyright); -++ exit(0); -++ break; -++ case 'o': -++ args->fp_out = fopen(optarg, "wb"); -++ if ((args->fp_out) == NULL) { -++ fprintf(stderr, "Cannot open file %s " -++ "for output\n", optarg); -++ exit(1); -++ } -++ break; -++ case '?': /* help */ -++ printf("%s", doc); -++ printf("%s", optionsstr); -++ printf("\nReport bugs to %s\n", -++ PACKAGE_BUGREPORT); -++ exit(0); -++ break; -++ case 'V': -++ printf("%s\n", PROGRAM_VERSION); -++ exit(0); -++ break; -++ default: -++ printf("%s", usage); -++ exit(-1); -++ } -++ } -++ -++ if (optind < argc) { -++ args->fp_in = fopen(argv[optind++], "rb"); -++ if ((args->fp_in) == NULL) { -++ fprintf(stderr, "Cannot open file %s for input\n", -++ argv[optind]); -++ exit(1); -++ } -++ } -++ -++ return 0; -++} -++ -++int -++main(int argc, char **argv) { -++ int rc = 0; -++ bootenv_t env; -++ -++ myargs args = { -++ .fp_in = stdin, -++ .fp_out = stdout, -++ .arg1 = NULL, -++ .options = NULL, -++ }; -++ -++ parse_opt(argc, argv, &args); -++ -++ rc = bootenv_create(&env); -++ if (rc != 0) { -++ err_msg("Cannot create bootenv handle."); -++ goto err; -++ } -++ rc = bootenv_read_txt(args.fp_in, env); -++ if (rc != 0) { -++ err_msg("Cannot read bootenv from input file."); -++ goto err; -++ } -++ rc = bootenv_write(args.fp_out, env); -++ if (rc != 0) { -++ err_msg("Cannot write bootenv to output file."); -++ goto err; -++ } -++ -++ if (args.fp_in != stdin) { -++ fclose(args.fp_in); -++ } -++ if (args.fp_out != stdout) { -++ fclose(args.fp_out); -++ } -++ -++err: -++ bootenv_destroy(&env); -++ return rc; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/nand2bin.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/nand2bin.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/nand2bin.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/nand2bin.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,493 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006, 2007 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Frank Haverkamp -++ * -++ * An utility to decompose NAND images and strip OOB off. Not yet finished ... -++ * -++ * 1.2 Removed argp because we want to use uClibc. -++ * 1.3 Minor cleanup -++ * 1.4 Fixed OOB output file -++ * 1.5 Added verbose output and option to set blocksize. -++ * Added split block mode for more convenient analysis. -++ * 1.6 Fixed ECC error detection and correction. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "config.h" -++#include "nandecc.h" -++ -++#define PROGRAM_VERSION "1.6" -++ -++#define MAXPATH 1024 -++#define MIN(x,y) ((x)<(y)?(x):(y)) -++ -++struct args { -++ const char *oob_file; -++ const char *output_file; -++ size_t pagesize; -++ size_t blocksize; -++ int split_blocks; -++ size_t in_len; /* size of input file */ -++ int correct_ecc; -++ -++ /* special stuff needed to get additional arguments */ -++ char *arg1; -++ char **options; /* [STRING...] */ -++}; -++ -++static struct args myargs = { -++ .output_file = "data.bin", -++ .oob_file = "oob.bin", -++ .pagesize = 2048, -++ .blocksize = 128 * 1024, -++ .in_len = 0, -++ .split_blocks = 0, -++ .correct_ecc = 0, -++ .arg1 = NULL, -++ .options = NULL, -++}; -++ -++static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" -++ "nand2bin - split data and OOB.\n"; -++ -++static const char *optionsstr = -++" -o, --output= Data output file\n" -++" -O, --oob= OOB output file\n" -++" -p, --pagesize= NAND pagesize\n" -++" -b, --blocksize= NAND blocksize\n" -++" -s, --split-blocks generate binaries for each block\n" -++" -e, --correct-ecc Correct data according to ECC info\n" -++" -v, --verbose verbose output\n" -++" -?, --help Give this help list\n" -++" --usage Give a short usage message\n"; -++ -++static const char *usage = -++"Usage: nand2bin [-?] [-o ] [-O ] [-p ]\n" -++" [--output=] [--oob=] [--pagesize=] [--help]\n" -++" [--usage] input.mif\n"; -++ -++static int verbose = 0; -++ -++static struct option long_options[] = { -++ { .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' }, -++ { .name = "oob", .has_arg = 1, .flag = NULL, .val = 'O' }, -++ { .name = "pagesize", .has_arg = 1, .flag = NULL, .val = 'p' }, -++ { .name = "blocksize", .has_arg = 1, .flag = NULL, .val = 'b' }, -++ { .name = "split-blocks", .has_arg = 0, .flag = NULL, .val = 's' }, -++ { .name = "correct-ecc", .has_arg = 0, .flag = NULL, .val = 'e' }, -++ { .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, -++ { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, -++ { NULL, 0, NULL, 0} -++}; -++ -++/* -++ * str_to_num - Convert string into number and cope with endings like -++ * k, K, kib, KiB for kilobyte -++ * m, M, mib, MiB for megabyte -++ */ -++static uint32_t str_to_num(char *str) -++{ -++ char *s = str; -++ ulong num = strtoul(s, &s, 0); -++ -++ if (*s != '\0') { -++ if (strcmp(s, "KiB") == 0) -++ num *= 1024; -++ else if (strcmp(s, "MiB") == 0) -++ num *= 1024*1024; -++ else { -++ fprintf(stderr, "WARNING: Wrong number format " -++ "\"%s\", check your paramters!\n", str); -++ } -++ } -++ return num; -++} -++ -++/* -++ * @brief Parse the arguments passed into the test case. -++ * -++ * @param argc The number of arguments -++ * @param argv The argument list -++ * @param args Pointer to program args structure -++ * -++ * @return error -++ * -++ */ -++static int parse_opt(int argc, char **argv, struct args *args) -++{ -++ while (1) { -++ int key; -++ -++ key = getopt_long(argc, argv, "b:eo:O:p:sv?", long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ case 'p': /* --pagesize */ -++ args->pagesize = str_to_num(optarg); -++ break; -++ -++ case 'b': /* --blocksize */ -++ args->blocksize = str_to_num(optarg); -++ break; -++ -++ case 'v': /* --verbose */ -++ verbose++; -++ break; -++ -++ case 's': /* --split-blocks */ -++ args->split_blocks = 1; -++ break; -++ -++ case 'e': /* --correct-ecc */ -++ args->correct_ecc = 1; -++ break; -++ -++ case 'o': /* --output= */ -++ args->output_file = optarg; -++ break; -++ -++ case 'O': /* --oob= */ -++ args->oob_file = optarg; -++ break; -++ -++ case '?': /* help */ -++ printf("Usage: nand2bin [OPTION...] input.mif\n"); -++ printf("%s", doc); -++ printf("%s", optionsstr); -++ printf("\nReport bugs to %s\n", -++ PACKAGE_BUGREPORT); -++ exit(0); -++ break; -++ -++ case 'V': -++ printf("%s\n", PROGRAM_VERSION); -++ exit(0); -++ break; -++ -++ default: -++ printf("%s", usage); -++ exit(-1); -++ } -++ } -++ -++ if (optind < argc) -++ args->arg1 = argv[optind++]; -++ -++ return 0; -++} -++ -++static int calc_oobsize(size_t pagesize) -++{ -++ switch (pagesize) { -++ case 512: return 16; -++ case 2048: return 64; -++ default: -++ exit(EXIT_FAILURE); -++ } -++ return 0; -++} -++ -++static inline void hexdump(FILE *fp, const uint8_t *buf, ssize_t size) -++{ -++ int k; -++ -++ for (k = 0; k < size; k++) { -++ fprintf(fp, "%02x ", buf[k]); -++ if ((k & 15) == 15) -++ fprintf(fp, "\n"); -++ } -++} -++ -++static int process_page(uint8_t* buf, uint8_t *oobbuf, size_t pagesize) -++{ -++ int eccpoi, oobsize; -++ size_t i; -++ -++ switch (pagesize) { -++ case 2048: oobsize = 64; eccpoi = 64 / 2; break; -++ case 512: oobsize = 16; eccpoi = 16 / 2; break; -++ default: -++ fprintf(stderr, "Unsupported page size: %zd\n", pagesize); -++ return -EINVAL; -++ } -++ memset(oobbuf, 0xff, oobsize); -++ -++ for (i = 0; i < pagesize; i += 256, eccpoi += 3) { -++ oobbuf[eccpoi++] = 0x0; -++ /* Calculate ECC */ -++ nand_calculate_ecc(&buf[i], &oobbuf[eccpoi]); -++ } -++ return 0; -++} -++ -++static int bad_marker_offs_in_oob(int pagesize) -++{ -++ switch (pagesize) { -++ case 2048: return 0; -++ case 512: return 5; -++ } -++ return -EINVAL; -++} -++ -++static int decompose_image(struct args *args, FILE *in_fp, -++ FILE *bin_fp, FILE *oob_fp) -++{ -++ int read, rc, page = 0; -++ size_t oobsize = calc_oobsize(args->pagesize); -++ uint8_t *buf = malloc(args->pagesize); -++ uint8_t *oob = malloc(oobsize); -++ uint8_t *calc_oob = malloc(oobsize); -++ uint8_t *calc_buf = malloc(args->pagesize); -++ uint8_t *page_buf; -++ int pages_per_block = args->blocksize / args->pagesize; -++ int eccpoi = 0, eccpoi_start; -++ unsigned int i; -++ int badpos = bad_marker_offs_in_oob(args->pagesize); -++ -++ switch (args->pagesize) { -++ case 2048: eccpoi_start = 64 / 2; break; -++ case 512: eccpoi_start = 16 / 2; break; -++ default: exit(EXIT_FAILURE); -++ } -++ -++ if (!buf) -++ exit(EXIT_FAILURE); -++ if (!oob) -++ exit(EXIT_FAILURE); -++ if (!calc_oob) -++ exit(EXIT_FAILURE); -++ if (!calc_buf) -++ exit(EXIT_FAILURE); -++ -++ while (!feof(in_fp)) { -++ /* read page by page */ -++ read = fread(buf, 1, args->pagesize, in_fp); -++ if (ferror(in_fp)) { -++ fprintf(stderr, "I/O Error."); -++ exit(EXIT_FAILURE); -++ } -++ if (read != (ssize_t)args->pagesize) -++ break; -++ -++ read = fread(oob, 1, oobsize, in_fp); -++ if (ferror(in_fp)) { -++ fprintf(stderr, "I/O Error."); -++ exit(EXIT_FAILURE); -++ } -++ -++ page_buf = buf; /* default is unmodified data */ -++ -++ if ((page == 0 || page == 1) && (oob[badpos] != 0xff)) { -++ if (verbose) -++ printf("Block %d is bad\n", -++ page / pages_per_block); -++ goto write_data; -++ } -++ if (args->correct_ecc) -++ page_buf = calc_buf; -++ -++ process_page(buf, calc_oob, args->pagesize); -++ memcpy(calc_buf, buf, args->pagesize); -++ -++ /* -++ * Our oob format uses only the last 3 bytes out of 4. -++ * The first byte is 0x00 when the ECC is generated by -++ * our toolset and 0xff when generated by Linux. This -++ * is to be fixed when we want nand2bin work for other -++ * ECC layouts too. -++ */ -++ for (i = 0, eccpoi = eccpoi_start; i < args->pagesize; -++ i += 256, eccpoi += 4) -++ oob[eccpoi] = calc_oob[eccpoi] = 0xff; -++ -++ if (verbose && memcmp(oob, calc_oob, oobsize) != 0) { -++ printf("\nECC compare mismatch found at block %d page %d!\n", -++ page / pages_per_block, page % pages_per_block); -++ -++ printf("Read out OOB Data:\n"); -++ hexdump(stdout, oob, oobsize); -++ -++ printf("Calculated OOB Data:\n"); -++ hexdump(stdout, calc_oob, oobsize); -++ } -++ -++ /* Do correction on subpage base */ -++ for (i = 0, eccpoi = eccpoi_start; i < args->pagesize; -++ i += 256, eccpoi += 4) { -++ rc = nand_correct_data(calc_buf + i, &oob[eccpoi + 1], -++ &calc_oob[eccpoi + 1]); -++ -++ if (rc == -1) -++ fprintf(stdout, "Uncorrectable ECC error at " -++ "block %d page %d/%d\n", -++ page / pages_per_block, -++ page % pages_per_block, i / 256); -++ else if (rc > 0) -++ fprintf(stdout, "Correctable ECC error at " -++ "block %d page %d/%d\n", -++ page / pages_per_block, -++ page % pages_per_block, i / 256); -++ } -++ -++ write_data: -++ rc = fwrite(page_buf, 1, args->pagesize, bin_fp); -++ if (ferror(bin_fp)) { -++ fprintf(stderr, "I/O Error."); -++ exit(EXIT_FAILURE); -++ } -++ rc = fwrite(oob, 1, oobsize, oob_fp); -++ if (ferror(bin_fp)) { -++ fprintf(stderr, "I/O Error."); -++ exit(EXIT_FAILURE); -++ } -++ -++ page++; -++ } -++ free(calc_buf); -++ free(calc_oob); -++ free(oob); -++ free(buf); -++ return 0; -++} -++ -++static int split_blocks(struct args *args, FILE *in_fp) -++{ -++ uint8_t *buf; -++ size_t oobsize = calc_oobsize(args->pagesize); -++ int pages_per_block = args->blocksize / args->pagesize; -++ int block_len = pages_per_block * (args->pagesize + oobsize); -++ int blocks = args->in_len / block_len; -++ char bname[256] = { 0, }; -++ int badpos = bad_marker_offs_in_oob(args->pagesize); -++ int bad_blocks = 0, i, bad_block = 0; -++ ssize_t rc; -++ FILE *b; -++ -++ buf = malloc(block_len); -++ if (!buf) { -++ perror("Not enough memory"); -++ exit(EXIT_FAILURE); -++ } -++ -++ for (i = 0; i < blocks; i++) { -++ rc = fread(buf, 1, block_len, in_fp); -++ if (rc != block_len) { -++ fprintf(stderr, "cannot read enough data!\n"); -++ exit(EXIT_FAILURE); -++ } -++ -++ /* do block analysis */ -++ bad_block = 0; -++ if ((buf[args->pagesize + badpos] != 0xff) || -++ (buf[2 * args->pagesize + oobsize + badpos] != 0xff)) { -++ bad_blocks++; -++ bad_block = 1; -++ } -++ if ((verbose && bad_block) || (verbose > 1)) { -++ printf("-- (block %d oob of page 0 and 1)\n", i); -++ hexdump(stdout, buf + args->pagesize, oobsize); -++ printf("--\n"); -++ hexdump(stdout, buf + 2 * args->pagesize + -++ oobsize, oobsize); -++ } -++ -++ /* write complete block out */ -++ snprintf(bname, sizeof(bname) - 1, "%s.%d", args->arg1, i); -++ b = fopen(bname, "w+"); -++ if (!b) { -++ perror("Cannot open file"); -++ exit(EXIT_FAILURE); -++ } -++ rc = fwrite(buf, 1, block_len, b); -++ if (rc != block_len) { -++ fprintf(stderr, "could not write all data!\n"); -++ exit(EXIT_FAILURE); -++ } -++ fclose(b); -++ } -++ -++ free(buf); -++ if (bad_blocks || verbose) -++ fprintf(stderr, "%d blocks, %d bad blocks\n", -++ blocks, bad_blocks); -++ return 0; -++} -++ -++int -++main(int argc, char *argv[]) -++{ -++ FILE *in, *bin = NULL, *oob = NULL; -++ struct stat file_info; -++ -++ parse_opt(argc, argv, &myargs); -++ -++ if (!myargs.arg1) { -++ fprintf(stderr, "Please specify input file!\n"); -++ exit(EXIT_FAILURE); -++ } -++ -++ if (lstat(myargs.arg1, &file_info) != 0) { -++ perror("Cannot fetch file size from input file.\n"); -++ exit(EXIT_FAILURE); -++ } -++ myargs.in_len = file_info.st_size; -++ -++ in = fopen(myargs.arg1, "r"); -++ if (!in) { -++ perror("Cannot open file"); -++ exit(EXIT_FAILURE); -++ } -++ -++ if (myargs.split_blocks) { -++ split_blocks(&myargs, in); -++ goto out; -++ } -++ -++ bin = fopen(myargs.output_file, "w+"); -++ if (!bin) { -++ perror("Cannot open file"); -++ exit(EXIT_FAILURE); -++ } -++ oob = fopen(myargs.oob_file, "w+"); -++ if (!oob) { -++ perror("Cannot open file"); -++ exit(EXIT_FAILURE); -++ } -++ decompose_image(&myargs, in, bin, oob); -++ -++ out: -++ if (in) fclose(in); -++ if (bin) fclose(bin); -++ if (oob) fclose(oob); -++ exit(EXIT_SUCCESS); -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/nandcorr.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/nandcorr.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/nandcorr.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/nandcorr.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,95 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * ECC algorithm for NAND FLASH. Detects and corrects 1 bit errors in -++ * a 256 bytes of data. -++ * -++ * Reimplement by Thomas Gleixner after staring long enough at the -++ * mess in drivers/mtd/nand/nandecc.c -++ * -++ */ -++ -++#include "nandecc.h" -++ -++static int countbits(uint32_t byte) -++{ -++ int res = 0; -++ -++ for (;byte; byte >>= 1) -++ res += byte & 0x01; -++ return res; -++} -++ -++/** -++ * @dat: data which should be corrected -++ * @read_ecc: ecc information read from flash -++ * @calc_ecc: calculated ecc information from the data -++ * @return: number of corrected bytes -++ * or -1 when no correction is possible -++ */ -++int nand_correct_data(uint8_t *dat, const uint8_t *read_ecc, -++ const uint8_t *calc_ecc) -++{ -++ uint8_t s0, s1, s2; -++ -++ /* -++ * Do error detection -++ * -++ * Be careful, the index magic is due to a pointer to a -++ * uint32_t. -++ */ -++ s0 = calc_ecc[0] ^ read_ecc[0]; -++ s1 = calc_ecc[1] ^ read_ecc[1]; -++ s2 = calc_ecc[2] ^ read_ecc[2]; -++ -++ if ((s0 | s1 | s2) == 0) -++ return 0; -++ -++ /* Check for a single bit error */ -++ if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 && -++ ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 && -++ ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) { -++ -++ uint32_t byteoffs, bitnum; -++ -++ byteoffs = (s1 << 0) & 0x80; -++ byteoffs |= (s1 << 1) & 0x40; -++ byteoffs |= (s1 << 2) & 0x20; -++ byteoffs |= (s1 << 3) & 0x10; -++ -++ byteoffs |= (s0 >> 4) & 0x08; -++ byteoffs |= (s0 >> 3) & 0x04; -++ byteoffs |= (s0 >> 2) & 0x02; -++ byteoffs |= (s0 >> 1) & 0x01; -++ -++ bitnum = (s2 >> 5) & 0x04; -++ bitnum |= (s2 >> 4) & 0x02; -++ bitnum |= (s2 >> 3) & 0x01; -++ -++ dat[byteoffs] ^= (1 << bitnum); -++ -++ return 1; -++ } -++ -++ if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1) -++ return 1; -++ -++ return -1; -++} -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/nandecc.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/nandecc.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/nandecc.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/nandecc.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,159 @@ -++/* -++ * This file contains an ECC algorithm from Toshiba that detects and -++ * corrects 1 bit errors in a 256 byte block of data. -++ * -++ * drivers/mtd/nand/nand_ecc.c -++ * -++ * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com) -++ * Toshiba America Electronics Components, Inc. -++ * -++ * This file is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 or (at your option) any -++ * later version. -++ * -++ * This file is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -++ * for more details. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this file; if not, write to the Free Software Foundation, Inc., -++ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -++ * -++ * As a special exception, if other files instantiate templates or use -++ * macros or inline functions from these files, or you compile these -++ * files and link them with other works to produce a work based on these -++ * files, these files do not by themselves cause the resulting work to be -++ * covered by the GNU General Public License. However the source code for -++ * these files must still be made available in accordance with section (3) -++ * of the GNU General Public License. -++ * -++ * This exception does not invalidate any other reasons why a work based on -++ * this file might be covered by the GNU General Public License. -++ */ -++ -++#include "nandecc.h" -++ -++/* -++ * Pre-calculated 256-way 1 byte column parity -++ */ -++static const uint8_t nand_ecc_precalc_table[] = { -++ 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, -++ 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, -++ 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, -++ 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, -++ 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, -++ 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, -++ 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, -++ 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, -++ 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, -++ 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, -++ 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, -++ 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, -++ 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, -++ 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, -++ 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, -++ 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, -++ 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, -++ 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, -++ 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, -++ 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, -++ 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, -++ 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, -++ 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, -++ 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, -++ 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, -++ 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, -++ 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, -++ 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, -++ 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, -++ 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, -++ 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, -++ 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00 -++}; -++ -++/** -++ * nand_trans_result - [GENERIC] create non-inverted ECC -++ * @reg2: line parity reg 2 -++ * @reg3: line parity reg 3 -++ * @ecc_code: ecc -++ * -++ * Creates non-inverted ECC code from line parity -++ */ -++static void nand_trans_result(uint8_t reg2, uint8_t reg3, -++ uint8_t *ecc_code) -++{ -++ uint8_t a, b, i, tmp1, tmp2; -++ -++ /* Initialize variables */ -++ a = b = 0x80; -++ tmp1 = tmp2 = 0; -++ -++ /* Calculate first ECC byte */ -++ for (i = 0; i < 4; i++) { -++ if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */ -++ tmp1 |= b; -++ b >>= 1; -++ if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */ -++ tmp1 |= b; -++ b >>= 1; -++ a >>= 1; -++ } -++ -++ /* Calculate second ECC byte */ -++ b = 0x80; -++ for (i = 0; i < 4; i++) { -++ if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */ -++ tmp2 |= b; -++ b >>= 1; -++ if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */ -++ tmp2 |= b; -++ b >>= 1; -++ a >>= 1; -++ } -++ -++ /* Store two of the ECC bytes */ -++ ecc_code[1] = tmp1; -++ ecc_code[0] = tmp2; -++} -++ -++/** -++ * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for -++ * 256 byte block -++ * -++ * @dat: raw data -++ * @ecc_code: buffer for ECC -++ */ -++int nand_calculate_ecc(const uint8_t *dat, uint8_t *ecc_code) -++{ -++ uint8_t idx, reg1, reg2, reg3; -++ int j; -++ -++ /* Initialize variables */ -++ reg1 = reg2 = reg3 = 0; -++ ecc_code[0] = ecc_code[1] = ecc_code[2] = 0; -++ -++ /* Build up column parity */ -++ for(j = 0; j < 256; j++) { -++ -++ /* Get CP0 - CP5 from table */ -++ idx = nand_ecc_precalc_table[dat[j]]; -++ reg1 ^= (idx & 0x3f); -++ -++ /* All bit XOR = 1 ? */ -++ if (idx & 0x40) { -++ reg3 ^= (uint8_t) j; -++ reg2 ^= ~((uint8_t) j); -++ } -++ } -++ -++ /* Create non-inverted ECC code from line parity */ -++ nand_trans_result(reg2, reg3, ecc_code); -++ -++ /* Calculate final ECC code */ -++ ecc_code[0] = ~ecc_code[0]; -++ ecc_code[1] = ~ecc_code[1]; -++ ecc_code[2] = ((~reg1) << 2) | 0x03; -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/nandecc.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/nandecc.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/nandecc.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/nandecc.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,29 @@ -++#ifndef _NAND_ECC_H -++#define _NAND_ECC_H -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * NAND ecc functions -++ */ -++ -++#include -++ -++int nand_calculate_ecc(const uint8_t *dat, uint8_t *ecc_code); -++int nand_correct_data(uint8_t *dat, const uint8_t *read_ecc, -++ const uint8_t *calc_ecc); -++ -++#endif -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/pddcustomize.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/pddcustomize.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/pddcustomize.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/pddcustomize.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,516 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2008 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ * -++ * PDD (platform description data) contains a set of system specific -++ * boot-parameters. Some of those parameters need to be handled -++ * special on updates, e.g. the MAC addresses. They must also be kept -++ * if the system is updated and one must be able to modify them when -++ * the system has booted the first time. This tool is intended to do -++ * PDD modification. -++ * -++ * 1.3 Removed argp because we want to use uClibc. -++ * 1.4 Minor cleanups -++ * 1.5 Migrated to new libubi -++ * 1.6 Fixed broken volume update -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "config.h" -++#include "bootenv.h" -++#include "error.h" -++#include "example_ubi.h" -++#include "libubi.h" -++#include "ubimirror.h" -++ -++#define PROGRAM_VERSION "1.6" -++ -++#define DEFAULT_DEV_PATTERN "/dev/ubi%d" -++#define DEFAULT_VOL_PATTERN "/dev/ubi%d_%d" -++ -++typedef enum action_t { -++ ACT_NORMAL = 0, -++ ACT_LIST, -++ ACT_ARGP_ABORT, -++ ACT_ARGP_ERR, -++} action_t; -++ -++#define ABORT_ARGP do { \ -++ args->action = ACT_ARGP_ABORT; \ -++} while (0) -++ -++#define ERR_ARGP do { \ -++ args->action = ACT_ARGP_ERR; \ -++} while (0) -++ -++static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" -++ "pddcustomize - customize bootenv and pdd values.\n"; -++ -++static const char *optionsstr = -++" -b, --both Mirror updated PDD to redundand copy.\n" -++" -c, --copyright Print copyright information.\n" -++" -i, --input= Binary input file. For debug purposes.\n" -++" -l, --list List card bootenv/pdd values.\n" -++" -o, --output= Binary output file. For debug purposes.\n" -++" -s, --side= The side/seqnum to update.\n" -++" -x, --host use x86 platform for debugging.\n" -++" -?, --help Give this help list\n" -++" --usage Give a short usage message\n" -++" -V, --version Print program version\n"; -++ -++static const char *usage = -++"Usage: pddcustomize [-bclx?V] [-i ] [-o ] [-s ]\n" -++" [--both] [--copyright] [--input=] [--list]\n" -++" [--output=] [--side=] [--host] [--help] [--usage]\n" -++" [--version] [key=value] [...]\n"; -++ -++struct option long_options[] = { -++ { .name = "both", .has_arg = 0, .flag = NULL, .val = 'b' }, -++ { .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' }, -++ { .name = "input", .has_arg = 1, .flag = NULL, .val = 'i' }, -++ { .name = "list", .has_arg = 0, .flag = NULL, .val = 'l' }, -++ { .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' }, -++ { .name = "side", .has_arg = 1, .flag = NULL, .val = 's' }, -++ { .name = "host", .has_arg = 0, .flag = NULL, .val = 'x' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, -++ { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ { NULL, 0, NULL, 0} -++}; -++ -++static const char copyright [] __attribute__((unused)) = -++ "Copyright IBM Corp 2006"; -++ -++typedef struct myargs { -++ action_t action; -++ const char* file_in; -++ const char* file_out; -++ int both; -++ int side; -++ int x86; /* X86 host, use files for testing */ -++ bootenv_t env_in; -++ -++ char *arg1; -++ char **options; /* [STRING...] */ -++} myargs; -++ -++static int -++get_update_side(const char* str) -++{ -++ uint32_t i = strtoul(str, NULL, 0); -++ -++ if ((i != 0) && (i != 1)) { -++ return -1; -++ } -++ -++ return i; -++} -++ -++static int -++extract_pair(bootenv_t env, const char* str) -++{ -++ int rc = 0; -++ char* key; -++ char* val; -++ -++ key = strdup(str); -++ if (key == NULL) -++ return -ENOMEM; -++ -++ val = strstr(key, "="); -++ if (val == NULL) { -++ err_msg("Wrong argument: %s\n" -++ "Expecting key=value pair.\n", str); -++ rc = -1; -++ goto err; -++ } -++ -++ *val = '\0'; /* split strings */ -++ val++; -++ rc = bootenv_set(env, key, val); -++ -++err: -++ free(key); -++ return rc; -++} -++ -++static int -++parse_opt(int argc, char **argv, myargs *args) -++{ -++ int rc = 0; -++ -++ while (1) { -++ int key; -++ -++ key = getopt_long(argc, argv, "clbxs:i:o:?V", -++ long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ case 'c': -++ err_msg("%s\n", copyright); -++ ABORT_ARGP; -++ break; -++ case 'l': -++ args->action = ACT_LIST; -++ break; -++ case 'b': -++ args->both = 1; -++ break; -++ case 'x': -++ args->x86 = 1; -++ break; -++ case 's': -++ args->side = get_update_side(optarg); -++ if (args->side < 0) { -++ err_msg("Unsupported seqnum: %d.\n" -++ "Supported seqnums are " -++ "'0' and '1'\n", -++ args->side, optarg); -++ ERR_ARGP; -++ } -++ break; -++ case 'i': -++ args->file_in = optarg; -++ break; -++ case 'o': -++ args->file_out = optarg; -++ break; -++ case '?': /* help */ -++ err_msg("Usage: pddcustomize [OPTION...] " -++ "[key=value] [...]"); -++ err_msg("%s", doc); -++ err_msg("%s", optionsstr); -++ err_msg("\nReport bugs to %s", -++ PACKAGE_BUGREPORT); -++ exit(0); -++ break; -++ case 'V': -++ err_msg("%s", PROGRAM_VERSION); -++ exit(0); -++ break; -++ default: -++ err_msg("%s", usage); -++ exit(-1); -++ } -++ } -++ -++ if (optind < argc) { -++ rc = extract_pair(args->env_in, argv[optind++]); -++ if (rc != 0) -++ ERR_ARGP; -++ } -++ -++ return 0; -++} -++ -++static int -++list_bootenv(bootenv_t env) -++{ -++ int rc = 0; -++ rc = bootenv_write_txt(stdout, env); -++ if (rc != 0) { -++ err_msg("Cannot list bootenv/pdd. rc: %d\n", rc); -++ goto err; -++ } -++err: -++ return rc; -++} -++ -++static int -++process_key_value(bootenv_t env_in, bootenv_t env) -++{ -++ int rc = 0; -++ size_t size, i; -++ const char* tmp; -++ const char** key_vec = NULL; -++ -++ rc = bootenv_get_key_vector(env_in, &size, 0, &key_vec); -++ if (rc != 0) -++ goto err; -++ -++ for (i = 0; i < size; i++) { -++ rc = bootenv_get(env_in, key_vec[i], &tmp); -++ if (rc != 0) { -++ err_msg("Cannot read value to input key: %s. rc: %d\n", -++ key_vec[i], rc); -++ goto err; -++ } -++ rc = bootenv_set(env, key_vec[i], tmp); -++ if (rc != 0) { -++ err_msg("Cannot set value key: %s. rc: %d\n", -++ key_vec[i], rc); -++ goto err; -++ } -++ } -++ -++err: -++ if (key_vec != NULL) -++ free(key_vec); -++ return rc; -++} -++ -++static int -++read_bootenv(const char* file, bootenv_t env) -++{ -++ int rc = 0; -++ FILE* fp_in = NULL; -++ -++ fp_in = fopen(file, "rb"); -++ if (fp_in == NULL) { -++ err_msg("Cannot open file: %s\n", file); -++ return -EIO; -++ } -++ -++ rc = bootenv_read(fp_in, env, BOOTENV_MAXSIZE); -++ if (rc != 0) { -++ err_msg("Cannot read bootenv from file %s. rc: %d\n", -++ file, rc); -++ goto err; -++ } -++ -++err: -++ fclose(fp_in); -++ return rc; -++} -++ -++/* -++ * Read bootenv from ubi volume -++ */ -++static int -++ubi_read_bootenv(uint32_t devno, uint32_t id, bootenv_t env) -++{ -++ libubi_t ulib; -++ int rc = 0; -++ char path[PATH_MAX]; -++ FILE* fp_in = NULL; -++ -++ ulib = libubi_open(); -++ if (ulib == NULL) { -++ err_msg("Cannot allocate ubi structure\n"); -++ return -1; -++ } -++ -++ snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id); -++ -++ fp_in = fopen(path, "r"); -++ if (fp_in == NULL) { -++ err_msg("Cannot open volume:%d number:%d\n", devno, id); -++ goto err; -++ } -++ -++ rc = bootenv_read(fp_in, env, BOOTENV_MAXSIZE); -++ if (rc != 0) { -++ err_msg("Cannot read volume:%d number:%d\n", devno, id); -++ goto err; -++ } -++ -++err: -++ if (fp_in) -++ fclose(fp_in); -++ libubi_close(ulib); -++ return rc; -++} -++ -++static int -++write_bootenv(const char* file, bootenv_t env) -++{ -++ int rc = 0; -++ FILE* fp_out; -++ -++ fp_out = fopen(file, "wb"); -++ if (fp_out == NULL) { -++ err_msg("Cannot open file: %s\n", file); -++ return -EIO; -++ } -++ -++ rc = bootenv_write(fp_out, env); -++ if (rc != 0) { -++ err_msg("Cannot write bootenv to file %s. rc: %d\n", file, rc); -++ goto err; -++ } -++ -++err: -++ fclose(fp_out); -++ return rc; -++} -++ -++/* -++ * Read bootenv from ubi volume -++ */ -++static int -++ubi_write_bootenv(uint32_t devno, uint32_t id, bootenv_t env) -++{ -++ libubi_t ulib; -++ int rc = 0; -++ char path[PATH_MAX]; -++ FILE* fp_out = NULL; -++ size_t nbytes; -++ -++ rc = bootenv_size(env, &nbytes); -++ if (rc) { -++ err_msg("Cannot determine size of bootenv structure\n"); -++ return rc; -++ } -++ ulib = libubi_open(); -++ if (ulib == NULL) { -++ err_msg("Cannot allocate ubi structure\n"); -++ return rc; -++ } -++ -++ snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id); -++ -++ fp_out = fopen(path, "r+"); -++ if (fp_out == NULL) { -++ err_msg("Cannot fopen volume:%d number:%d\n", devno, id); -++ rc = -EBADF; -++ goto err; -++ } -++ -++ rc = ubi_update_start(ulib, fileno(fp_out), nbytes); -++ if (rc != 0) { -++ err_msg("Cannot start update for %s\n", path); -++ goto err; -++ } -++ -++ rc = bootenv_write(fp_out, env); -++ if (rc != 0) { -++ err_msg("Cannot write bootenv to volume %d number:%d\n", -++ devno, id); -++ goto err; -++ } -++err: -++ if( fp_out ) -++ fclose(fp_out); -++ libubi_close(ulib); -++ return rc; -++} -++ -++static int -++do_mirror(int volno) -++{ -++ char errbuf[1024]; -++ uint32_t ids[2]; -++ int rc; -++ int src_volno_idx = 0; -++ -++ ids[0] = EXAMPLE_BOOTENV_VOL_ID_1; -++ ids[1] = EXAMPLE_BOOTENV_VOL_ID_2; -++ -++ if (volno == EXAMPLE_BOOTENV_VOL_ID_2) -++ src_volno_idx = 1; -++ -++ rc = ubimirror(EXAMPLE_UBI_DEVICE, src_volno_idx, ids, 2, errbuf, -++ sizeof errbuf); -++ if( rc ) -++ err_msg(errbuf); -++ return rc; -++} -++ -++int -++main(int argc, char **argv) { -++ int rc = 0; -++ bootenv_t env = NULL; -++ uint32_t boot_volno; -++ myargs args = { -++ .action = ACT_NORMAL, -++ .file_in = NULL, -++ .file_out = NULL, -++ .side = -1, -++ .x86 = 0, -++ .both = 0, -++ .env_in = NULL, -++ -++ .arg1 = NULL, -++ .options = NULL, -++ }; -++ -++ rc = bootenv_create(&env); -++ if (rc != 0) { -++ err_msg("Cannot create bootenv handle. rc: %d", rc); -++ goto err; -++ } -++ -++ rc = bootenv_create(&(args.env_in)); -++ if (rc != 0) { -++ err_msg("Cannot create bootenv handle. rc: %d", rc); -++ goto err; -++ } -++ -++ parse_opt(argc, argv, &args); -++ if (args.action == ACT_ARGP_ERR) { -++ rc = -1; -++ goto err; -++ } -++ if (args.action == ACT_ARGP_ABORT) { -++ rc = 0; -++ goto out; -++ } -++ -++ if ((args.side == 0) || (args.side == -1)) -++ boot_volno = EXAMPLE_BOOTENV_VOL_ID_1; -++ else -++ boot_volno = EXAMPLE_BOOTENV_VOL_ID_2; -++ -++ if( args.x86 ) -++ rc = read_bootenv(args.file_in, env); -++ else -++ rc = ubi_read_bootenv(EXAMPLE_UBI_DEVICE, boot_volno, env); -++ if (rc != 0) { -++ goto err; -++ } -++ -++ if (args.action == ACT_LIST) { -++ rc = list_bootenv(env); -++ if (rc != 0) { -++ goto err; -++ } -++ goto out; -++ } -++ -++ rc = process_key_value(args.env_in, env); -++ if (rc != 0) { -++ goto err; -++ } -++ -++ if( args.x86 ) -++ rc = write_bootenv(args.file_in, env); -++ else -++ rc = ubi_write_bootenv(EXAMPLE_UBI_DEVICE, boot_volno, env); -++ if (rc != 0) -++ goto err; -++ -++ if( args.both ) /* No side specified, update both */ -++ rc = do_mirror(boot_volno); -++ -++ out: -++ err: -++ bootenv_destroy(&env); -++ bootenv_destroy(&(args.env_in)); -++ return rc; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/peb.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/peb.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/peb.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/peb.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,116 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "peb.h" -++ -++int -++peb_cmp(peb_t eb_1, peb_t eb_2) -++{ -++ assert(eb_1); -++ assert(eb_2); -++ -++ return eb_1->num == eb_2->num ? 0 -++ : eb_1->num > eb_2->num ? 1 : -1; -++} -++ -++int -++peb_new(uint32_t eb_num, uint32_t eb_size, peb_t *peb) -++{ -++ int rc = 0; -++ -++ peb_t res = (peb_t) malloc(sizeof(struct peb)); -++ if (!res) { -++ rc = -ENOMEM; -++ goto err; -++ } -++ -++ res->num = eb_num; -++ res->size = eb_size; -++ res->data = (uint8_t*) malloc(res->size * sizeof(uint8_t)); -++ if (!res->data) { -++ rc = -ENOMEM; -++ goto err; -++ } -++ memset(res->data, 0xff, res->size); -++ -++ *peb = res; -++ return 0; -++err: -++ if (res) { -++ if (res->data) -++ free(res->data); -++ free(res); -++ } -++ *peb = NULL; -++ return rc; -++} -++ -++int -++peb_fill(peb_t peb, uint8_t* buf, size_t buf_size) -++{ -++ if (!peb) -++ return -EINVAL; -++ -++ if (buf_size > peb->size) -++ return -EINVAL; -++ -++ memcpy(peb->data, buf, buf_size); -++ return 0; -++} -++ -++int -++peb_write(FILE* fp_out, peb_t peb) -++{ -++ size_t written = 0; -++ -++ if (peb == NULL) -++ return -EINVAL; -++ -++ written = fwrite(peb->data, 1, peb->size, fp_out); -++ -++ if (written != peb->size) -++ return -EIO; -++ -++ return 0; -++} -++ -++int -++peb_free(peb_t* peb) -++{ -++ peb_t tmp = *peb; -++ if (tmp) { -++ if (tmp->data) -++ free(tmp->data); -++ free(tmp); -++ } -++ *peb = NULL; -++ -++ return 0; -++} -++ -++void peb_dump(FILE* fp_out, peb_t peb) -++{ -++ fprintf(fp_out, "num: %08d\tsize: 0x%08x\n", peb->num, peb->size); -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/peb.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/peb.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/peb.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/peb.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,41 @@ -++#ifndef __RAW_BLOCK_H__ -++#define __RAW_BLOCK_H__ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ */ -++ -++#include -++#include -++ -++typedef struct peb *peb_t; -++struct peb { -++ uint32_t num; /* Physical eraseblock number -++ * in the RAW file. */ -++ uint32_t size; /* Data Size (equals physical -++ * erase block size) */ -++ uint8_t* data; /* Data buffer */ -++}; -++ -++int peb_new(uint32_t peb_num, uint32_t peb_size, peb_t* peb); -++int peb_free(peb_t* peb); -++int peb_cmp(peb_t peb_1, peb_t peb_2); -++int peb_write(FILE* fp_out, peb_t peb); -++void peb_dump(FILE* fp_out, peb_t peb); -++ -++#endif /* __RAW_BLOCK_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/pfi.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/pfi.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/pfi.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/pfi.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,458 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * @file pfi.c -++ * -++ * @author Oliver Lohmann -++ * Andreas Arnez -++ * Joern Engel -++ * Frank Haverkamp -++ * -++ * @brief libpfi holds all code to create and process pfi files. -++ * -++ * Wed Feb 8 11:38:22 CET 2006: Initial creation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "pfi.h" -++ -++#define PFI_MAGIC "PFI!\n" -++#define PFI_DATA "DATA\n" /* The same size as PFI_MAGIC */ -++#define PFI_MAGIC_LEN 5 -++ -++static const char copyright [] __attribute__((unused)) = -++ "Copyright (c) International Business Machines Corp., 2006"; -++ -++enum key_id { -++ /* version 1 */ -++ key_version, /* must be index position 0! */ -++ key_mode, -++ key_size, -++ key_crc, -++ key_label, -++ key_flags, -++ key_ubi_ids, -++ key_ubi_size, -++ key_ubi_type, -++ key_ubi_names, -++ key_ubi_alignment, -++ key_raw_starts, -++ key_raw_total_size, -++ num_keys, -++}; -++ -++struct pfi_header { -++ char defined[num_keys]; /* reserve all possible keys even if -++ version does not require this. */ -++ int mode_no; /* current mode no. -> can only increase */ -++ union { -++ char *str; -++ uint32_t num; -++ } value[num_keys]; -++}; -++ -++ -++#define PFI_MANDATORY 0x0001 -++#define PFI_STRING 0x0002 -++#define PFI_LISTVALUE 0x0004 /* comma seperated list of nums */ -++#define PFI_MANDATORY_UBI 0x0008 -++#define PFI_MANDATORY_RAW 0x0010 -++ -++struct key_descriptor { -++ enum key_id id; -++ const char *name; -++ uint32_t flags; -++}; -++ -++static const struct key_descriptor key_desc_v1[] = { -++ { key_version, "version", PFI_MANDATORY }, -++ { key_mode, "mode", PFI_MANDATORY | PFI_STRING }, -++ { key_size, "size", PFI_MANDATORY }, -++ { key_crc, "crc", PFI_MANDATORY }, -++ { key_label, "label", PFI_MANDATORY | PFI_STRING }, -++ { key_flags, "flags", PFI_MANDATORY }, -++ { key_ubi_ids, "ubi_ids", PFI_MANDATORY_UBI | PFI_STRING }, -++ { key_ubi_size, "ubi_size", PFI_MANDATORY_UBI }, -++ { key_ubi_type, "ubi_type", PFI_MANDATORY_UBI | PFI_STRING }, -++ { key_ubi_names, "ubi_names", PFI_MANDATORY_UBI | PFI_STRING }, -++ { key_ubi_alignment, "ubi_alignment", PFI_MANDATORY_UBI }, -++ { key_raw_starts, "raw_starts", PFI_MANDATORY_RAW | PFI_STRING }, -++ { key_raw_total_size, "raw_total_size", PFI_MANDATORY_RAW }, -++}; -++ -++static const struct key_descriptor *key_descriptors[] = { -++ NULL, -++ key_desc_v1, /* version 1 */ -++}; -++ -++static const int key_descriptors_max[] = { -++ 0, /* version 0 */ -++ sizeof(key_desc_v1)/sizeof(struct key_descriptor), /* version 1 */ -++}; -++ -++#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -++ -++static const char* modes[] = {"raw", "ubi"}; /* order isn't arbitrary! */ -++ -++/* latest version contains all possible keys */ -++static const struct key_descriptor *key_desc = key_desc_v1; -++ -++#define PFI_IS_UBI(mode) \ -++ (((mode) != NULL) && (strcmp("ubi", (mode)) == 0)) -++ -++#define PFI_IS_RAW(mode) \ -++ (((mode) != NULL) && (strcmp("raw", (mode)) == 0)) -++ -++/** -++ * @return <0 On Error. -++ * >=0 Mode no. -++ */ -++static int -++get_mode_no(const char* mode) -++{ -++ int i; -++ -++ for (i = 0; i < (int)ARRAY_SIZE(modes); i++) -++ if (strcmp(mode, modes[i]) == 0) -++ return i; -++ return -1; -++} -++ -++static int -++find_key_by_name (const char *name) -++{ -++ int i; -++ -++ for (i = 0; i < num_keys; i++) { -++ if (strcmp(name, key_desc[i].name) == 0) -++ return i; -++ } -++ return -1; -++} -++ -++static int -++check_valid (pfi_header head) -++{ -++ int i; -++ int max_keys; -++ uint32_t version; -++ const char *mode; -++ const struct key_descriptor *desc; -++ uint32_t to_check = PFI_MANDATORY; -++ -++ /* -++ * For the validity check the list of possible keys depends on -++ * the version of the PFI file used. -++ */ -++ version = head->value[key_version].num; -++ if (version > PFI_HDRVERSION) -++ return PFI_ENOHEADER; -++ -++ max_keys = key_descriptors_max[version]; -++ desc = key_descriptors[version]; -++ -++ if (!desc) -++ return PFI_ENOVERSION; -++ -++ mode = head->value[key_mode].str; -++ if (PFI_IS_UBI(mode)) { -++ to_check |= PFI_MANDATORY_UBI; -++ } -++ else if (PFI_IS_RAW(mode)) { -++ to_check |= PFI_MANDATORY_RAW; -++ } -++ else { /* neither UBI nor RAW == ERR */ -++ return PFI_EINSUFF; -++ } -++ -++ for (i = 0; i < max_keys; i++) { -++ if ((desc[i].flags & to_check) && !head->defined[i]) { -++ fprintf(stderr, "libpfi: %s missing\n", desc[i].name); -++ return PFI_EINSUFF; -++ } -++ } -++ -++ return 0; -++} -++ -++int pfi_header_init (pfi_header *head) -++{ -++ int i; -++ pfi_header self = (pfi_header) malloc(sizeof(*self)); -++ -++ *head = self; -++ if (self == NULL) -++ return PFI_ENOMEM; -++ -++ /* initialize maximum number of possible keys */ -++ for (i = 0; i < num_keys; i++) { -++ memset(self, 0, sizeof(*self)); -++ self->defined[i] = 0; -++ } -++ -++ return 0; -++} -++ -++int pfi_header_destroy (pfi_header *head) -++{ -++ int i; -++ pfi_header self = *head; -++ -++ for (i = 0; i < num_keys; i++) { -++ if (self->defined[i] && (key_desc[i].flags & PFI_STRING) && -++ self->value[i].str) { -++ free(self->value[i].str); -++ } -++ } -++ free(*head); -++ *head = NULL; -++ return 0; -++} -++ -++int pfi_header_setnumber (pfi_header head, -++ const char *key, uint32_t value) -++{ -++ int key_id = find_key_by_name(key); -++ -++ if (key_id < 0) -++ return PFI_EUNDEF; -++ -++ if (key_desc[key_id].flags & PFI_STRING) -++ return PFI_EBADTYPE; -++ -++ head->value[key_id].num = value; -++ head->defined[key_id] = 1; -++ return 0; -++} -++ -++int pfi_header_setvalue (pfi_header head, -++ const char *key, const char *value) -++{ -++ int key_id = find_key_by_name(key); -++ -++ if (value == NULL) -++ return PFI_EINSUFF; -++ -++ if ((key_id < 0) || (key_id >= num_keys)) -++ return PFI_EUNDEF; -++ -++ if (key_desc[key_id].flags & PFI_STRING) { -++ /* -++ * The value is a string. Copy to a newly allocated -++ * buffer. Delete the old value, if already set. -++ */ -++ size_t len = strlen(value) + 1; -++ char *old_str = NULL; -++ char *str; -++ -++ old_str = head->value[key_id].str; -++ if (old_str != NULL) -++ free(old_str); -++ -++ str = head->value[key_id].str = (char *) malloc(len); -++ if (str == NULL) -++ return PFI_ENOMEM; -++ -++ strcpy(str, value); -++ } else { -++ int len; -++ int ret; -++ /* FIXME: here we assume that the value is always -++ given in hex and starts with '0x'. */ -++ ret = sscanf(value, "0x%x%n", &head->value[key_id].num, &len); -++ if (ret < 1 || value[len] != '\0') -++ return PFI_EBADTYPE; -++ } -++ head->defined[key_id] = 1; -++ return 0; -++} -++ -++int pfi_header_getnumber (pfi_header head, -++ const char *key, uint32_t *value) -++{ -++ int key_id = find_key_by_name(key); -++ -++ if (key_id < 0) -++ return PFI_EUNDEF; -++ -++ if (key_desc[key_id].flags & PFI_STRING) -++ return PFI_EBADTYPE; -++ -++ if (!head->defined[key_id]) -++ return PFI_EUNDEF; -++ -++ *value = head->value[key_id].num; -++ return 0; -++} -++ -++int pfi_header_getstring (pfi_header head, -++ const char *key, char *value, size_t size) -++{ -++ int key_id = find_key_by_name(key); -++ -++ if (key_id < 0) -++ return PFI_EUNDEF; -++ -++ if (!(key_desc[key_id].flags & PFI_STRING)) -++ return PFI_EBADTYPE; -++ -++ if (!head->defined[key_id]) -++ return PFI_EUNDEF; -++ -++ strncpy(value, head->value[key_id].str, size-1); -++ value[size-1] = '\0'; -++ return 0; -++} -++ -++int pfi_header_write (FILE *out, pfi_header head) -++{ -++ int i; -++ int ret; -++ -++ pfi_header_setnumber(head, "version", PFI_HDRVERSION); -++ -++ if ((ret = check_valid(head)) != 0) -++ return ret; -++ -++ /* OK. Now write the header. */ -++ -++ ret = fwrite(PFI_MAGIC, 1, PFI_MAGIC_LEN, out); -++ if (ret < PFI_MAGIC_LEN) -++ return ret; -++ -++ -++ for (i = 0; i < num_keys; i++) { -++ if (!head->defined[i]) -++ continue; -++ -++ ret = fprintf(out, "%s=", key_desc[i].name); -++ if (ret < 0) -++ return PFI_EFILE; -++ -++ if (key_desc[i].flags & PFI_STRING) { -++ ret = fprintf(out, "%s", head->value[i].str); -++ if (ret < 0) -++ return PFI_EFILE; -++ } else { -++ ret = fprintf(out, "0x%8x", head->value[i].num); -++ if (ret < 0) -++ return PFI_EFILE; -++ -++ } -++ ret = fprintf(out, "\n"); -++ if (ret < 0) -++ return PFI_EFILE; -++ } -++ ret = fprintf(out, "\n"); -++ if (ret < 0) -++ return PFI_EFILE; -++ -++ ret = fflush(out); -++ if (ret != 0) -++ return PFI_EFILE; -++ -++ return 0; -++} -++ -++int pfi_header_read (FILE *in, pfi_header head) -++{ -++ char magic[PFI_MAGIC_LEN]; -++ char mode[PFI_KEYWORD_LEN]; -++ char buf[256]; -++ -++ if (PFI_MAGIC_LEN != fread(magic, 1, PFI_MAGIC_LEN, in)) -++ return PFI_EFILE; -++ if (memcmp(magic, PFI_MAGIC, PFI_MAGIC_LEN) != 0) { -++ if (memcmp(magic, PFI_DATA, PFI_MAGIC_LEN) == 0) { -++ return PFI_DATA_START; -++ } -++ return PFI_ENOHEADER; -++ } -++ -++ while (fgets(buf, sizeof(buf), in) != NULL && buf[0] != '\n') { -++ char *value; -++ char *end; -++ value = strchr(buf, '='); -++ if (value == NULL) -++ return PFI_ENOHEADER; -++ -++ *value = '\0'; -++ value++; -++ end = strchr(value, '\n'); -++ if (end) -++ *end = '\0'; -++ -++ if (pfi_header_setvalue(head, buf, value)) -++ return PFI_ENOHEADER; -++ } -++ -++ if (check_valid(head) != 0) -++ return PFI_ENOHEADER; -++ -++ /* set current mode no. in head */ -++ pfi_header_getstring(head, "mode", mode, PFI_KEYWORD_LEN); -++ if (head->mode_no > get_mode_no(mode)) { -++ return PFI_EMODE; -++ } -++ head->mode_no = get_mode_no(mode); -++ return 0; -++} -++ -++int pfi_header_dump (FILE *out, pfi_header head __attribute__((__unused__))) -++{ -++ fprintf(out, "Sorry not implemented yet. Write mail to " -++ "Andreas Arnez and complain!\n"); -++ return 0; -++} -++ -++int pfi_read (FILE *in, pfi_read_func func, void *priv_data) -++{ -++ int rc; -++ pfi_header header; -++ -++ rc = pfi_header_init (&header); -++ if (0 != rc) -++ return rc; -++ if (!func) -++ return PFI_EINVAL; -++ -++ while ((0 == rc) && !feof(in)) { -++ /* -++ * Read header and check consistency of the fields. -++ */ -++ rc = pfi_header_read( in, header ); -++ if (0 != rc) -++ break; -++ if (func) { -++ rc = func(in, header, priv_data); -++ if (rc != 0) -++ break; -++ } -++ } -++ -++ pfi_header_destroy(&header); -++ return rc; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/pfi.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/pfi.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/pfi.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/pfi.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,244 @@ -++#ifndef __pfi_h -++#define __pfi_h -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/** -++ * @file pfi.h -++ * -++ * @author Oliver Lohmann -++ * Andreas Arnez -++ * Joern Engel -++ * Frank Haverkamp -++ * -++ * @brief libpfi will hold all code to create and process pfi -++ * images. Definitions made in this file are equaly usable for the -++ * development host and the target system. -++ * -++ * @note This header additionally holds the official definitions for -++ * the pfi headers. -++ */ -++ -++#include /* FILE */ -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++/* Definitions. */ -++ -++#define PFI_HDRVERSION 1 /* current header version */ -++ -++#define PFI_ENOVERSION 1 /* unknown version */ -++#define PFI_ENOHEADER 2 /* not a pfi header */ -++#define PFI_EINSUFF 3 /* insufficient information */ -++#define PFI_EUNDEF 4 /* key not defined */ -++#define PFI_ENOMEM 5 /* out of memory */ -++#define PFI_EBADTYPE 6 /* bad data type */ -++#define PFI_EFILE 7 /* file I/O error: see errno */ -++#define PFI_EFILEINVAL 8 /* file format not valid */ -++#define PFI_EINVAL 9 /* invalid parameter */ -++#define PFI_ERANGE 10 /* invalid range */ -++#define PFI_EMODE 11 /* expecting other mode in this header */ -++#define PFI_DATA_START 12 /* data section starts */ -++#define PFI_EMAX 13 /* should be always larger as the largest -++ error code */ -++ -++#define PFI_LABEL_LEN 64 /* This is the maximum length for a -++ PFI header label */ -++#define PFI_KEYWORD_LEN 32 /* This is the maximum length for an -++ entry in the mode and type fields */ -++ -++#define PFI_UBI_MAX_VOLUMES 128 -++#define PFI_UBI_VOL_NAME_LEN 127 -++ -++/** -++ * @brief The pfi header allows to set flags which influence the flashing -++ * behaviour. -++ */ -++#define PFI_FLAG_PROTECTED 0x00000001 -++ -++ -++/** -++ * @brief Handle to pfi header. Used in most of the functions associated -++ * with pfi file handling. -++ */ -++typedef struct pfi_header *pfi_header; -++ -++ -++/** -++ * @brief Initialize a pfi header object. -++ * -++ * @param head Pointer to handle. This function allocates memory -++ * for this data structure. -++ * @return 0 on success, otherwise: -++ * PFI_ENOMEM : no memory available for the handle. -++ */ -++int pfi_header_init (pfi_header *head); -++ -++ -++/** -++ * @brief Destroy a pfi header object. -++ * -++ * @param head handle. head is invalid after calling this function. -++ * @return 0 always. -++ */ -++int pfi_header_destroy (pfi_header *head); -++ -++ -++/** -++ * @brief Add a key/value pair to a pfi header object. -++ * -++ * @param head handle. -++ * @param key pointer to key string. Must be 0 terminated. -++ * @param value pointer to value string. Must be 0 terminated. -++ * @return 0 on success, otherwise: -++ * PFI_EUNDEF : key was not found. -++ * PFI_ENOMEM : no memory available for the handle. -++ * PFI_EBADTYPE : value is not an hex string. This happens -++ * when the key stores an integer and the -++ * new value is not convertable e.g. not in -++ * 0xXXXXXXXX format. -++ */ -++int pfi_header_setvalue (pfi_header head, -++ const char *key, const char *value); -++ -++ -++/** -++ * @brief Add a key/value pair to a pfi header object. Provide the -++ * value as a number. -++ * -++ * @param head handle. -++ * @param key pointer to key string. Must be 0 terminated. -++ * @param value value to set. -++ * @return 0 on success, otherwise: -++ * PFI_EUNDEF : key was not found. -++ * PFI_EBADTYPE : value is not a string. This happens -++ * when the key stores a string. -++ */ -++int pfi_header_setnumber (pfi_header head, -++ const char *key, uint32_t value); -++ -++ -++/** -++ * @brief For a given key, return the numerical value stored in a -++ * pfi header object. -++ * -++ * @param head handle. -++ * @param key pointer to key string. Must be 0 terminated. -++ * @param value pointer to value. -++ * @return 0 on success, otherwise: -++ * PFI_EUNDEF : key was not found. -++ * PFI_EBADTYPE : stored value is not an integer but a string. -++ */ -++int pfi_header_getnumber (pfi_header head, -++ const char *key, uint32_t *value); -++ -++ -++static inline uint32_t -++pfi_getnumber(pfi_header head, const char *key) -++{ -++ uint32_t value; -++ pfi_header_getnumber(head, key, &value); -++ return value; -++} -++ -++/** -++ * @brief For a given key, return the string value stored in a pfi -++ * header object. -++ * -++ * @param head handle. -++ * @param key pointer to key string. Must be 0 terminated. -++ * @param value pointer to value string. Memory must be allocated by the user. -++ * @return 0 on success, otherwise: -++ * PFI_EUNDEF : key was not found. -++ * PFI_EBADTYPE : stored value is not a string but an integer. -++ */ -++int pfi_header_getstring (pfi_header head, -++ const char *key, char *value, size_t size); -++ -++ -++/** -++ * @brief Write a pfi header object into a given file. -++ * -++ * @param out output stream. -++ * @param head handle. -++ * @return 0 on success, error values otherwise: -++ * PFI_EINSUFF : not all mandatory fields are filled. -++ * PFI_ENOHEADER : wrong header version or magic number. -++ * -E* : see . -++ */ -++int pfi_header_write (FILE *out, pfi_header head); -++ -++ -++/** -++ * @brief Read a pfi header object from a given file. -++ * -++ * @param in input stream. -++ * @param head handle. -++ * @return 0 on success, error values otherwise: -++ * PFI_ENOVERSION: unknown header version. -++ * PFI_EFILE : cannot read enough data. -++ * PFI_ENOHEADER : wrong header version or magic number. -++ * -E* : see . -++ * -++ * If the header verification returned success the user can assume that -++ * all mandatory fields for a particular version are accessible. Checking -++ * the return code when calling the get-function for those keys is not -++ * required in those cases. For optional fields the checking must still be -++ * done. -++ */ -++int pfi_header_read (FILE *in, pfi_header head); -++ -++ -++/** -++ * @brief Display a pfi header in human-readable form. -++ * -++ * @param out output stream. -++ * @param head handle. -++ * @return always 0. -++ * -++ * @note Prints out that it is not implemented and whom you should -++ * contact if you need it urgently!. -++ */ -++int pfi_header_dump (FILE *out, pfi_header head); -++ -++ -++/* -++ * @brief Iterates over a stream of pfi files. The iterator function -++ * must advance the file pointer in FILE *in to the next pfi -++ * header. Function exists on feof(in). -++ * -++ * @param in input file descriptor, must be open and valid. -++ * @param func iterator function called when pfi header could be -++ * read and was validated. The function must return 0 on -++ * success. -++ * @return See pfi_header_init and pfi_header_read. -++ * PFI_EINVAL : func is not valid -++ * 0 ok. -++ */ -++typedef int (* pfi_read_func)(FILE *in, pfi_header hdr, void *priv_data); -++ -++int pfi_read (FILE *in, pfi_read_func func, void *priv_data); -++ -++ -++#ifdef __cplusplus -++} -++#endif -++ -++#endif /* __pfi_h */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/pfi2bin.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/pfi2bin.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/pfi2bin.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/pfi2bin.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,682 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ * -++ * Convert a PFI file (partial flash image) into a plain binary file. -++ * This tool can be used to prepare the data to be burned into flash -++ * chips in a manufacturing step where the flashes are written before -++ * being soldered onto the hardware. For NAND images another step is -++ * required to add the right OOB data to the binary image. -++ * -++ * 1.3 Removed argp because we want to use uClibc. -++ * 1.4 Minor cleanups -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++ -++#include "config.h" -++#include "list.h" -++#include "error.h" -++#include "reader.h" -++#include "peb.h" -++#include "crc32.h" -++ -++#define PROGRAM_VERSION "1.4" -++ -++#define MAX_FNAME 255 -++#define DEFAULT_ERASE_COUNT 0 /* Hmmm.... Perhaps */ -++#define ERR_BUF_SIZE 1024 -++ -++#define MIN(a,b) ((a) < (b) ? (a) : (b)) -++ -++static uint32_t crc32_table[256]; -++static char err_buf[ERR_BUF_SIZE]; -++ -++/* -++ * Data used to buffer raw blocks which have to be -++ * located at a specific point inside the generated RAW file -++ */ -++ -++typedef enum action_t { -++ ACT_NOTHING = 0x00000000, -++ ACT_RAW = 0x00000001, -++} action_t; -++ -++static const char copyright [] __attribute__((unused)) = -++ "(c) Copyright IBM Corp 2006\n"; -++ -++static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" -++ "pfi2bin - a tool to convert PFI files into binary images.\n"; -++ -++static const char *optionsstr = -++" Common settings:\n" -++" -c, --copyright\n" -++" -v, --verbose Print more information.\n" -++"\n" -++" Input:\n" -++" -j, --platform=pdd-file PDD information which contains the card settings.\n" -++"\n" -++" Output:\n" -++" -o, --output=filename Outputfile, default: stdout.\n" -++"\n" -++" -?, --help Give this help list\n" -++" --usage Give a short usage message\n" -++" -V, --version Print program version\n"; -++ -++static const char *usage = -++"Usage: pfi2bin [-cv?V] [-j pdd-file] [-o filename] [--copyright]\n" -++" [--verbose] [--platform=pdd-file] [--output=filename] [--help]\n" -++" [--usage] [--version] pfifile\n"; -++ -++struct option long_options[] = { -++ { .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' }, -++ { .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' }, -++ { .name = "platform", .has_arg = 1, .flag = NULL, .val = 'j' }, -++ { .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, -++ { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ { NULL, 0, NULL, 0} -++}; -++ -++typedef struct io { -++ FILE* fp_pdd; /* a FilePointer to the PDD data */ -++ FILE* fp_pfi; /* a FilePointer to the PFI input stream */ -++ FILE* fp_out; /* a FilePointer to the output stream */ -++} *io_t; -++ -++typedef struct myargs { -++ /* common settings */ -++ action_t action; -++ int verbose; -++ const char *f_in_pfi; -++ const char *f_in_pdd; -++ const char *f_out; -++ -++ /* special stuff needed to get additional arguments */ -++ char *arg1; -++ char **options; /* [STRING...] */ -++} myargs; -++ -++static int -++parse_opt(int argc, char **argv, myargs *args) -++{ -++ while (1) { -++ int key; -++ -++ key = getopt_long(argc, argv, "cvj:o:?V", long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ /* common settings */ -++ case 'v': /* --verbose= */ -++ args->verbose = 1; -++ break; -++ -++ case 'c': /* --copyright */ -++ fprintf(stderr, "%s\n", copyright); -++ exit(0); -++ break; -++ -++ case 'j': /* --platform */ -++ args->f_in_pdd = optarg; -++ break; -++ -++ case 'o': /* --output */ -++ args->f_out = optarg; -++ break; -++ -++ case '?': /* help */ -++ printf("pfi2bin [OPTION...] pfifile\n"); -++ printf("%s", doc); -++ printf("%s", optionsstr); -++ printf("\nReport bugs to %s\n", -++ PACKAGE_BUGREPORT); -++ exit(0); -++ break; -++ -++ case 'V': -++ printf("%s\n", PROGRAM_VERSION); -++ exit(0); -++ break; -++ -++ default: -++ printf("%s", usage); -++ exit(-1); -++ } -++ } -++ -++ if (optind < argc) -++ args->f_in_pfi = argv[optind++]; -++ -++ return 0; -++} -++ -++ -++static size_t -++byte_to_blk(size_t byte, size_t blk_size) -++{ -++ return (byte % blk_size) == 0 -++ ? byte / blk_size -++ : byte / blk_size + 1; -++} -++ -++ -++ -++ -++/** -++ * @precondition IO: File stream points to first byte of RAW data. -++ * @postcondition IO: File stream points to first byte of next -++ * or EOF. -++ */ -++static int -++memorize_raw_eb(pfi_raw_t pfi_raw, pdd_data_t pdd, list_t *raw_pebs, -++ io_t io) -++{ -++ int rc = 0; -++ uint32_t i; -++ -++ size_t read, to_read, eb_num; -++ size_t bytes_left; -++ list_t pebs = *raw_pebs; -++ peb_t peb = NULL; -++ -++ long old_file_pos = ftell(io->fp_pfi); -++ for (i = 0; i < pfi_raw->starts_size; i++) { -++ bytes_left = pfi_raw->data_size; -++ rc = fseek(io->fp_pfi, old_file_pos, SEEK_SET); -++ if (rc != 0) -++ goto err; -++ -++ eb_num = byte_to_blk(pfi_raw->starts[i], pdd->eb_size); -++ while (bytes_left) { -++ to_read = MIN(bytes_left, pdd->eb_size); -++ rc = peb_new(eb_num++, pdd->eb_size, &peb); -++ if (rc != 0) -++ goto err; -++ read = fread(peb->data, 1, to_read, io->fp_pfi); -++ if (read != to_read) { -++ rc = -EIO; -++ goto err; -++ } -++ pebs = append_elem(peb, pebs); -++ bytes_left -= read; -++ } -++ -++ } -++ *raw_pebs = pebs; -++ return 0; -++err: -++ pebs = remove_all((free_func_t)&peb_free, pebs); -++ return rc; -++} -++ -++static int -++convert_ubi_volume(pfi_ubi_t ubi, pdd_data_t pdd, list_t raw_pebs, -++ struct ubi_vtbl_record *vol_tab, -++ size_t *ebs_written, io_t io) -++{ -++ int rc = 0; -++ uint32_t i, j; -++ peb_t raw_peb; -++ peb_t cmp_peb; -++ ubi_info_t u; -++ size_t leb_total = 0; -++ uint8_t vol_type; -++ -++ switch (ubi->type) { -++ case pfi_ubi_static: -++ vol_type = UBI_VID_STATIC; break; -++ case pfi_ubi_dynamic: -++ vol_type = UBI_VID_DYNAMIC; break; -++ default: -++ vol_type = UBI_VID_DYNAMIC; -++ } -++ -++ rc = peb_new(0, 0, &cmp_peb); -++ if (rc != 0) -++ goto err; -++ -++ long old_file_pos = ftell(io->fp_pfi); -++ for (i = 0; i < ubi->ids_size; i++) { -++ rc = fseek(io->fp_pfi, old_file_pos, SEEK_SET); -++ if (rc != 0) -++ goto err; -++ rc = ubigen_create(&u, ubi->ids[i], vol_type, -++ pdd->eb_size, DEFAULT_ERASE_COUNT, -++ ubi->alignment, UBI_VERSION, -++ pdd->vid_hdr_offset, 0, ubi->data_size, -++ io->fp_pfi, io->fp_out); -++ if (rc != 0) -++ goto err; -++ -++ rc = ubigen_get_leb_total(u, &leb_total); -++ if (rc != 0) -++ goto err; -++ -++ j = 0; -++ while(j < leb_total) { -++ cmp_peb->num = *ebs_written; -++ raw_peb = is_in((cmp_func_t)peb_cmp, cmp_peb, -++ raw_pebs); -++ if (raw_peb) { -++ rc = peb_write(io->fp_out, raw_peb); -++ } -++ else { -++ rc = ubigen_write_leb(u, NO_ERROR); -++ j++; -++ } -++ if (rc != 0) -++ goto err; -++ (*ebs_written)++; -++ } -++ /* memorize volume table entry */ -++ rc = ubigen_set_lvol_rec(u, ubi->size, -++ ubi->names[i], -++ (void*) &vol_tab[ubi->ids[i]]); -++ if (rc != 0) -++ goto err; -++ ubigen_destroy(&u); -++ } -++ -++ peb_free(&cmp_peb); -++ return 0; -++ -++err: -++ peb_free(&cmp_peb); -++ ubigen_destroy(&u); -++ return rc; -++} -++ -++ -++static FILE* -++my_fmemopen (void *buf, size_t size, const char *opentype) -++{ -++ FILE* f; -++ size_t ret; -++ -++ assert(strcmp(opentype, "r") == 0); -++ -++ f = tmpfile(); -++ ret = fwrite(buf, 1, size, f); -++ rewind(f); -++ -++ return f; -++} -++ -++/** -++ * @brief Builds a UBI volume table from a volume entry list. -++ * @return 0 On success. -++ * else Error. -++ */ -++static int -++write_ubi_volume_table(pdd_data_t pdd, list_t raw_pebs, -++ struct ubi_vtbl_record *vol_tab, size_t vol_tab_size, -++ size_t *ebs_written, io_t io) -++{ -++ int rc = 0; -++ ubi_info_t u; -++ peb_t raw_peb; -++ peb_t cmp_peb; -++ size_t leb_size, leb_total, j = 0; -++ uint8_t *ptr = NULL; -++ FILE* fp_leb = NULL; -++ int vt_slots; -++ size_t vol_tab_size_limit; -++ -++ rc = peb_new(0, 0, &cmp_peb); -++ if (rc != 0) -++ goto err; -++ -++ /* @FIXME: Artem creates one volume with 2 LEBs. -++ * IMO 2 volumes would be more convenient. In order -++ * to get 2 reserved LEBs from ubigen, I have to -++ * introduce this stupid mechanism. Until no final -++ * decision of the VTAB structure is made... Good enough. -++ */ -++ rc = ubigen_create(&u, UBI_LAYOUT_VOLUME_ID, UBI_VID_DYNAMIC, -++ pdd->eb_size, DEFAULT_ERASE_COUNT, -++ 1, UBI_VERSION, -++ pdd->vid_hdr_offset, UBI_COMPAT_REJECT, -++ vol_tab_size, stdin, io->fp_out); -++ /* @FIXME stdin for fp_in is a hack */ -++ if (rc != 0) -++ goto err; -++ rc = ubigen_get_leb_size(u, &leb_size); -++ if (rc != 0) -++ goto err; -++ ubigen_destroy(&u); -++ -++ /* -++ * The number of supported volumes is restricted by the eraseblock size -++ * and by the UBI_MAX_VOLUMES constant. -++ */ -++ vt_slots = leb_size / UBI_VTBL_RECORD_SIZE; -++ if (vt_slots > UBI_MAX_VOLUMES) -++ vt_slots = UBI_MAX_VOLUMES; -++ vol_tab_size_limit = vt_slots * UBI_VTBL_RECORD_SIZE; -++ -++ ptr = (uint8_t*) malloc(leb_size * sizeof(uint8_t)); -++ if (ptr == NULL) -++ goto err; -++ -++ memset(ptr, 0xff, leb_size); -++ memcpy(ptr, vol_tab, vol_tab_size_limit); -++ fp_leb = my_fmemopen(ptr, leb_size, "r"); -++ -++ rc = ubigen_create(&u, UBI_LAYOUT_VOLUME_ID, UBI_VID_DYNAMIC, -++ pdd->eb_size, DEFAULT_ERASE_COUNT, -++ 1, UBI_VERSION, pdd->vid_hdr_offset, -++ UBI_COMPAT_REJECT, leb_size * UBI_LAYOUT_VOLUME_EBS, -++ fp_leb, io->fp_out); -++ if (rc != 0) -++ goto err; -++ rc = ubigen_get_leb_total(u, &leb_total); -++ if (rc != 0) -++ goto err; -++ -++ long old_file_pos = ftell(fp_leb); -++ while(j < leb_total) { -++ rc = fseek(fp_leb, old_file_pos, SEEK_SET); -++ if (rc != 0) -++ goto err; -++ -++ cmp_peb->num = *ebs_written; -++ raw_peb = is_in((cmp_func_t)peb_cmp, cmp_peb, -++ raw_pebs); -++ if (raw_peb) { -++ rc = peb_write(io->fp_out, raw_peb); -++ } -++ else { -++ rc = ubigen_write_leb(u, NO_ERROR); -++ j++; -++ } -++ -++ if (rc != 0) -++ goto err; -++ (*ebs_written)++; -++ } -++ -++err: -++ free(ptr); -++ peb_free(&cmp_peb); -++ ubigen_destroy(&u); -++ fclose(fp_leb); -++ return rc; -++} -++ -++static int -++write_remaining_raw_ebs(pdd_data_t pdd, list_t raw_blocks, size_t *ebs_written, -++ FILE* fp_out) -++{ -++ int rc = 0; -++ uint32_t j, delta; -++ list_t ptr; -++ peb_t empty_eb, peb; -++ -++ /* create an empty 0xff EB (for padding) */ -++ rc = peb_new(0, pdd->eb_size, &empty_eb); -++ -++ foreach(peb, ptr, raw_blocks) { -++ if (peb->num < *ebs_written) { -++ continue; /* omit blocks which -++ are already passed */ -++ } -++ -++ if (peb->num < *ebs_written) { -++ err_msg("eb_num: %d\n", peb->num); -++ err_msg("Bug: This should never happen. %d %s", -++ __LINE__, __FILE__); -++ goto err; -++ } -++ -++ delta = peb->num - *ebs_written; -++ if (((delta + *ebs_written) * pdd->eb_size) > pdd->flash_size) { -++ err_msg("RAW block outside of flash_size."); -++ goto err; -++ } -++ for (j = 0; j < delta; j++) { -++ rc = peb_write(fp_out, empty_eb); -++ if (rc != 0) -++ goto err; -++ (*ebs_written)++; -++ } -++ rc = peb_write(fp_out, peb); -++ if (rc != 0) -++ goto err; -++ (*ebs_written)++; -++ } -++ -++err: -++ peb_free(&empty_eb); -++ return rc; -++} -++ -++static int -++init_vol_tab(struct ubi_vtbl_record **vol_tab, size_t *vol_tab_size) -++{ -++ uint32_t crc; -++ size_t i; -++ struct ubi_vtbl_record* res = NULL; -++ -++ *vol_tab_size = UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE; -++ -++ res = (struct ubi_vtbl_record*) calloc(1, *vol_tab_size); -++ if (vol_tab == NULL) { -++ return -ENOMEM; -++ } -++ -++ for (i = 0; i < UBI_MAX_VOLUMES; i++) { -++ crc = clc_crc32(crc32_table, UBI_CRC32_INIT, -++ &(res[i]), UBI_VTBL_RECORD_SIZE_CRC); -++ res[i].crc = cpu_to_be32(crc); -++ } -++ -++ *vol_tab = res; -++ return 0; -++} -++ -++static int -++create_raw(io_t io) -++{ -++ int rc = 0; -++ size_t ebs_written = 0; /* eraseblocks written already... */ -++ size_t vol_tab_size; -++ list_t ptr; -++ -++ list_t pfi_raws = mk_empty(); /* list of raw sections from a pfi */ -++ list_t pfi_ubis = mk_empty(); /* list of ubi sections from a pfi */ -++ list_t raw_pebs = mk_empty(); /* list of raw eraseblocks */ -++ -++ struct ubi_vtbl_record *vol_tab = NULL; -++ pdd_data_t pdd = NULL; -++ -++ rc = init_vol_tab (&vol_tab, &vol_tab_size); -++ if (rc != 0) { -++ err_msg("Cannot initialize volume table."); -++ goto err; -++ } -++ -++ rc = read_pdd_data(io->fp_pdd, &pdd, -++ err_buf, ERR_BUF_SIZE); -++ if (rc != 0) { -++ err_msg("Cannot read necessary pdd_data: %s rc: %d", -++ err_buf, rc); -++ goto err; -++ } -++ -++ rc = read_pfi_headers(&pfi_raws, &pfi_ubis, io->fp_pfi, -++ err_buf, ERR_BUF_SIZE); -++ if (rc != 0) { -++ err_msg("Cannot read pfi header: %s rc: %d", -++ err_buf, rc); -++ goto err; -++ } -++ -++ pfi_raw_t pfi_raw; -++ foreach(pfi_raw, ptr, pfi_raws) { -++ rc = memorize_raw_eb(pfi_raw, pdd, &raw_pebs, -++ io); -++ if (rc != 0) { -++ err_msg("Cannot create raw_block in mem. rc: %d\n", -++ rc); -++ goto err; -++ } -++ } -++ -++ pfi_ubi_t pfi_ubi; -++ foreach(pfi_ubi, ptr, pfi_ubis) { -++ rc = convert_ubi_volume(pfi_ubi, pdd, raw_pebs, -++ vol_tab, &ebs_written, io); -++ if (rc != 0) { -++ err_msg("Cannot convert UBI volume. rc: %d\n", rc); -++ goto err; -++ } -++ } -++ -++ rc = write_ubi_volume_table(pdd, raw_pebs, vol_tab, vol_tab_size, -++ &ebs_written, io); -++ if (rc != 0) { -++ err_msg("Cannot write UBI volume table. rc: %d\n", rc); -++ goto err; -++ } -++ -++ rc = write_remaining_raw_ebs(pdd, raw_pebs, &ebs_written, io->fp_out); -++ if (rc != 0) -++ goto err; -++ -++ if (io->fp_out != stdout) -++ info_msg("Physical eraseblocks written: %8d\n", ebs_written); -++err: -++ free(vol_tab); -++ pfi_raws = remove_all((free_func_t)&free_pfi_raw, pfi_raws); -++ pfi_ubis = remove_all((free_func_t)&free_pfi_ubi, pfi_ubis); -++ raw_pebs = remove_all((free_func_t)&peb_free, raw_pebs); -++ free_pdd_data(&pdd); -++ return rc; -++} -++ -++ -++/* ------------------------------------------------------------------------- */ -++static void -++open_io_handle(myargs *args, io_t io) -++{ -++ /* set PDD input */ -++ io->fp_pdd = fopen(args->f_in_pdd, "r"); -++ if (io->fp_pdd == NULL) { -++ err_sys("Cannot open: %s", args->f_in_pdd); -++ } -++ -++ /* set PFI input */ -++ io->fp_pfi = fopen(args->f_in_pfi, "r"); -++ if (io->fp_pfi == NULL) { -++ err_sys("Cannot open PFI input file: %s", args->f_in_pfi); -++ } -++ -++ /* set output prefix */ -++ if (strcmp(args->f_out,"") == 0) -++ io->fp_out = stdout; -++ else { -++ io->fp_out = fopen(args->f_out, "wb"); -++ if (io->fp_out == NULL) { -++ err_sys("Cannot open output file: %s", args->f_out); -++ } -++ } -++} -++ -++static void -++close_io_handle(io_t io) -++{ -++ if (fclose(io->fp_pdd) != 0) { -++ err_sys("Cannot close PDD file."); -++ } -++ if (fclose(io->fp_pfi) != 0) { -++ err_sys("Cannot close PFI file."); -++ } -++ if (io->fp_out != stdout) { -++ if (fclose(io->fp_out) != 0) { -++ err_sys("Cannot close output file."); -++ } -++ } -++ -++ io->fp_pdd = NULL; -++ io->fp_pfi = NULL; -++ io->fp_out = NULL; -++} -++ -++int -++main(int argc, char *argv[]) -++{ -++ int rc = 0; -++ -++ ubigen_init(); -++ init_crc32_table(crc32_table); -++ -++ struct io io = {NULL, NULL, NULL}; -++ myargs args = { -++ .action = ACT_RAW, -++ .verbose = 0, -++ -++ .f_in_pfi = "", -++ .f_in_pdd = "", -++ .f_out = "", -++ -++ /* arguments */ -++ .arg1 = NULL, -++ .options = NULL, -++ }; -++ -++ /* parse arguments */ -++ parse_opt(argc, argv, &args); -++ -++ if (strcmp(args.f_in_pfi, "") == 0) { -++ err_quit("No PFI input file specified!"); -++ } -++ -++ if (strcmp(args.f_in_pdd, "") == 0) { -++ err_quit("No PDD input file specified!"); -++ } -++ -++ open_io_handle(&args, &io); -++ -++ info_msg("[ Creating RAW..."); -++ rc = create_raw(&io); -++ if (rc != 0) { -++ err_msg("Creating RAW failed."); -++ goto err; -++ } -++ -++err: -++ close_io_handle(&io); -++ if (rc != 0) { -++ remove(args.f_out); -++ } -++ -++ return rc; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/pfiflash.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/pfiflash.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/pfiflash.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/pfiflash.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,264 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ * Frank Haverkamp -++ * -++ * Process a PFI (partial flash image) and write the data to the -++ * specified UBI volumes. This tool is intended to be used for system -++ * update using PFI files. -++ * -++ * 1.1 fixed output to stderr and stdout in logfile mode. -++ * 1.2 updated. -++ * 1.3 removed argp parsing to be able to use uClib. -++ * 1.4 Minor cleanups. -++ * 1.5 Forgot to delete raw block before updating it. -++ * 1.6 Migrated to new libubi. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#undef DEBUG -++#include "error.h" -++#include "config.h" -++ -++#define PROGRAM_VERSION "1.6" -++ -++static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" -++ "pfiflash - a tool for updating a controller with PFI files.\n"; -++ -++static const char *optionsstr = -++" Standard options:\n" -++" -c, --copyright Print copyright information.\n" -++" -l, --logfile= Write a logfile to .\n" -++" -v, --verbose Be verbose during program execution.\n" -++"\n" -++" Process options:\n" -++" -C, --complete Execute a complete system update. Updates both\n" -++" sides.\n" -++" -p, --pdd-update= Specify the pdd-update algorithm. is either\n" -++" 'keep', 'merge' or 'overwrite'.\n" -++" -r, --raw-flash= Flash the raw data. Use the specified mtd device.\n" -++" -s, --side= Select the side which shall be updated.\n" -++" -x, --compare Only compare on-flash and pfi data, print info if\n" -++" an update is neccessary and return appropriate\n" -++" error code.\n" -++"\n" -++" -?, --help Give this help list\n" -++" --usage Give a short usage message\n" -++" -V, --version Print program version\n"; -++ -++static const char *usage = -++"Usage: pfiflash [-cvC?V] [-l ] [-p ] [-r ] [-s ]\n" -++" [--copyright] [--logfile=] [--verbose] [--complete]\n" -++" [--pdd-update=] [--raw-flash=] [--side=]\n" -++" [--compare] [--help] [--usage] [--version] [pfifile]\n"; -++ -++static const char copyright [] __attribute__((unused)) = -++ "Copyright IBM Corp 2006"; -++ -++struct option long_options[] = { -++ { .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' }, -++ { .name = "logfile", .has_arg = 1, .flag = NULL, .val = 'l' }, -++ { .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' }, -++ { .name = "complete", .has_arg = 0, .flag = NULL, .val = 'C' }, -++ { .name = "pdd-update", .has_arg = 1, .flag = NULL, .val = 'p' }, -++ { .name = "raw-flash", .has_arg = 1, .flag = NULL, .val = 'r' }, -++ { .name = "side", .has_arg = 1, .flag = NULL, .val = 's' }, -++ { .name = "compare", .has_arg = 0, .flag = NULL, .val = 'x' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, -++ { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ { NULL, 0, NULL, 0} -++}; -++ -++typedef struct myargs { -++ int verbose; -++ const char *logfile; -++ const char *raw_dev; -++ -++ pdd_handling_t pdd_handling; -++ int seqnum; -++ int compare; -++ int complete; -++ -++ FILE* fp_in; -++ -++ /* special stuff needed to get additional arguments */ -++ char *arg1; -++ char **options; /* [STRING...] */ -++} myargs; -++ -++static pdd_handling_t -++get_pdd_handling(const char* str) -++{ -++ if (strcmp(str, "keep") == 0) { -++ return PDD_KEEP; -++ } -++ if (strcmp(str, "merge") == 0) { -++ return PDD_MERGE; -++ } -++ if (strcmp(str, "overwrite") == 0) { -++ return PDD_OVERWRITE; -++ } -++ -++ return -1; -++} -++ -++static int -++get_update_seqnum(const char* str) -++{ -++ uint32_t i = strtoul(str, NULL, 0); -++ -++ if ((i != 0) && (i != 1)) { -++ return -1; -++ } -++ -++ return i; -++} -++ -++ -++static int -++parse_opt(int argc, char **argv, myargs *args) -++{ -++ while (1) { -++ int key; -++ -++ key = getopt_long(argc, argv, "cl:vCp:r:s:x?V", -++ long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ /* standard options */ -++ case 'c': -++ err_msg("%s\n", copyright); -++ exit(0); -++ break; -++ case 'v': -++ args->verbose = 1; -++ break; -++ case 'l': -++ args->logfile = optarg; -++ break; -++ /* process options */ -++ case 'C': -++ args->complete = 1; -++ break; -++ case 'p': -++ args->pdd_handling = get_pdd_handling(optarg); -++ if ((int)args->pdd_handling < 0) { -++ err_quit("Unknown PDD handling: %s.\n" -++ "Please use either " -++ "'keep', 'merge' or" -++ "'overwrite'.\n'"); -++ } -++ break; -++ case 's': -++ args->seqnum = get_update_seqnum(optarg); -++ if (args->seqnum < 0) { -++ err_quit("Unsupported side: %s.\n" -++ "Supported sides are '0' " -++ "and '1'\n", optarg); -++ } -++ break; -++ case 'x': -++ args->compare = 1; -++ break; -++ case 'r': -++ args->raw_dev = optarg; -++ break; -++ case '?': /* help */ -++ err_msg("Usage: pfiflash [OPTION...] [pfifile]"); -++ err_msg("%s", doc); -++ err_msg("%s", optionsstr); -++ err_msg("\nReport bugs to %s\n", -++ PACKAGE_BUGREPORT); -++ exit(0); -++ break; -++ case 'V': -++ err_msg("%s", PROGRAM_VERSION); -++ exit(0); -++ break; -++ default: -++ err_msg("%s", usage); -++ exit(-1); -++ -++ } -++ } -++ -++ if (optind < argc) { -++ args->fp_in = fopen(argv[optind++], "r"); -++ if ((args->fp_in) == NULL) { -++ err_sys("Cannot open PFI file %s for input", -++ argv[optind]); -++ } -++ } -++ -++ return 0; -++} -++ -++int main (int argc, char** argv) -++{ -++ int rc = 0; -++ char err_buf[PFIFLASH_MAX_ERR_BUF_SIZE]; -++ memset(err_buf, '\0', PFIFLASH_MAX_ERR_BUF_SIZE); -++ -++ myargs args = { -++ .verbose = 0, -++ .seqnum = -1, -++ .compare = 0, -++ .complete = 0, -++ .logfile = NULL, /* "/tmp/pfiflash.log", */ -++ .pdd_handling = PDD_KEEP, -++ .fp_in = stdin, -++ .raw_dev = NULL, -++ }; -++ -++ parse_opt(argc, argv, &args); -++ error_initlog(args.logfile); -++ -++ if (!args.fp_in) { -++ rc = -1; -++ snprintf(err_buf, PFIFLASH_MAX_ERR_BUF_SIZE, -++ "No PFI input file specified!\n"); -++ goto err; -++ } -++ -++ rc = pfiflash_with_options(args.fp_in, args.complete, args.seqnum, -++ args.compare, args.pdd_handling, args.raw_dev, err_buf, -++ PFIFLASH_MAX_ERR_BUF_SIZE); -++ if (rc < 0) { -++ goto err_fp; -++ } -++ -++ err_fp: -++ if (args.fp_in != stdin) -++ fclose(args.fp_in); -++ err: -++ if (rc != 0) -++ err_msg("pfiflash: %s\nrc: %d\n", err_buf, rc); -++ return rc; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/pfiflash.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/pfiflash.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/pfiflash.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/pfiflash.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,76 @@ -++#ifndef __PFIFLASH_H__ -++#define __PFIFLASH_H__ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/** -++ * -++ * @file pfi.h -++ * -++ * @author Oliver Lohmann -++ * -++ * @brief The pfiflash library offers an interface for using the -++ * pfiflash * utility. -++ */ -++ -++#include /* FILE */ -++ -++#define PFIFLASH_MAX_ERR_BUF_SIZE 1024 -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++typedef enum pdd_handling_t -++{ -++ PDD_KEEP = 0, -++ PDD_MERGE, -++ PDD_OVERWRITE, -++ PDD_HANDLING_NUM, /* always the last item */ -++} pdd_handling_t; /**< Possible PDD handle algorithms. */ -++ -++/** -++ * @brief Flashes a PFI file to UBI Device 0. -++ * @param complete [0|1] Do a complete system update. -++ * @param seqnum Index in a redundant group. -++ * @param compare [0|1] Compare contents. -++ * @param pdd_handling The PDD handling algorithm. -++ * @param rawdev Device to use for raw flashing -++ * @param err_buf An error buffer. -++ * @param err_buf_size Size of the error buffer. -++ */ -++int pfiflash_with_options(FILE* pfi, int complete, int seqnum, int compare, -++ pdd_handling_t pdd_handling, const char* rawdev, -++ char *err_buf, size_t err_buf_size); -++ -++/** -++ * @brief Flashes a PFI file to UBI Device 0. -++ * @param complete [0|1] Do a complete system update. -++ * @param seqnum Index in a redundant group. -++ * @param pdd_handling The PDD handling algorithm. -++ * @param err_buf An error buffer. -++ * @param err_buf_size Size of the error buffer. -++ */ -++int pfiflash(FILE* pfi, int complete, int seqnum, pdd_handling_t pdd_handling, -++ char *err_buf, size_t err_buf_size); -++ -++#ifdef __cplusplus -++} -++#endif -++ -++#endif /* __PFIFLASH_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/pfiflash_error.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/pfiflash_error.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/pfiflash_error.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/pfiflash_error.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,75 @@ -++#ifndef __PFIFLASH_ERROR_H__ -++#define __PFIFLASH_ERROR_H__ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * Author: Drake Dowsett -++ * Contact: Andreas Arnez -++ */ -++ -++enum pfiflash_err { -++ PFIFLASH_ERR_EOF = 1, -++ PFIFLASH_ERR_FIO, -++ PFIFLASH_ERR_UBI_OPEN, -++ PFIFLASH_ERR_UBI_CLOSE, -++ PFIFLASH_ERR_UBI_MKVOL, -++ PFIFLASH_ERR_UBI_RMVOL, -++ PFIFLASH_ERR_UBI_VOL_UPDATE, -++ PFIFLASH_ERR_UBI_VOL_FOPEN, -++ PFIFLASH_ERR_UBI_UNKNOWN, -++ PFIFLASH_ERR_UBI_VID_OOB, -++ PFIFLASH_ERR_BOOTENV_CREATE, -++ PFIFLASH_ERR_BOOTENV_READ, -++ PFIFLASH_ERR_BOOTENV_SIZE, -++ PFIFLASH_ERR_BOOTENV_WRITE, -++ PFIFLASH_ERR_PDD_UNKNOWN, -++ PFIFLASH_ERR_MTD_OPEN, -++ PFIFLASH_ERR_MTD_CLOSE, -++ PFIFLASH_ERR_CRC_CHECK, -++ PFIFLASH_ERR_MTD_ERASE, -++ PFIFLASH_ERR_COMPARE, -++ PFIFLASH_CMP_DIFF -++}; -++ -++const char *const PFIFLASH_ERRSTR[] = { -++ "", -++ "unexpected EOF", -++ "file I/O error", -++ "couldn't open UBI", -++ "couldn't close UBI", -++ "couldn't make UBI volume %d", -++ "couldn't remove UBI volume %d", -++ "couldn't update UBI volume %d", -++ "couldn't open UBI volume %d", -++ "unknown UBI operation", -++ "PFI data contains out of bounds UBI id %d", -++ "couldn't create bootenv%s", -++ "couldn't read bootenv", -++ "couldn't resize bootenv", -++ "couldn't write bootenv on ubi%d_%d", -++ "unknown PDD handling algorithm", -++ "couldn't open MTD device %s", -++ "couldn't close MTD device %s", -++ "CRC check failed: given=0x%08x, calculated=0x%08x", -++ "couldn't erase raw mtd region", -++ "couldn't compare volumes", -++ "on-flash data differ from pfi data, update is neccessary" -++}; -++ -++#endif /* __PFIFLASH_ERROR_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/reader.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/reader.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/reader.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/reader.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,482 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ * -++ * Read in PFI (partial flash image) data and store it into internal -++ * data structures for further processing. Take also care about -++ * special handling if the data contains PDD (platform description -++ * data/boot-parameters). -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include "bootenv.h" -++#include "reader.h" -++ -++#define __unused __attribute__((unused)) -++ -++/* @FIXME hard coded offsets right now - get them from Artem? */ -++#define NAND2048_DEFAULT_VID_HDR_OFF 1984 -++#define NAND512_DEFAULT_VID_HDR_OFF 448 -++#define NOR_DEFAULT_VID_HDR_OFF 64 -++ -++#define EBUF_PFI(fmt...) \ -++ do { int i = snprintf(err_buf, err_buf_size, "%s\n", label); \ -++ snprintf(err_buf + i, err_buf_size - i, fmt); \ -++ } while (0) -++ -++#define EBUF(fmt...) \ -++ do { snprintf(err_buf, err_buf_size, fmt); } while (0) -++ -++ -++int -++read_pdd_data(FILE* fp_pdd, pdd_data_t* pdd_data, -++ char* err_buf, size_t err_buf_size) -++{ -++ int rc = 0; -++ bootenv_t pdd = NULL; -++ pdd_data_t res = NULL; -++ const char* value; -++ -++ res = (pdd_data_t) malloc(sizeof(struct pdd_data)); -++ if (!res) { -++ rc = -ENOMEM; -++ goto err; -++ } -++ rc = bootenv_create(&pdd); -++ if (rc != 0) { -++ goto err; -++ } -++ rc = bootenv_read_txt(fp_pdd, pdd); -++ if (rc != 0) { -++ goto err; -++ } -++ rc = bootenv_get(pdd, "flash_type", &value); -++ if (rc != 0) { -++ goto err; -++ } -++ -++ if (strcmp(value, "NAND") == 0) { -++ -++ rc = bootenv_get_num(pdd, "flash_page_size", -++ &(res->flash_page_size)); -++ if (rc != 0) { -++ EBUF("Cannot read 'flash_page_size' from pdd."); -++ goto err; -++ } -++ res->flash_type = NAND_FLASH; -++ -++ switch (res->flash_page_size) { -++ case 512: -++ res->vid_hdr_offset = NAND512_DEFAULT_VID_HDR_OFF; -++ break; -++ case 2048: -++ res->vid_hdr_offset = NAND2048_DEFAULT_VID_HDR_OFF; -++ break; -++ default: -++ EBUF("Unsupported 'flash_page_size' %d.", -++ res->flash_page_size); -++ goto err; -++ } -++ } -++ else if (strcmp(value, "NOR") == 0){ -++ res->flash_type = NOR_FLASH; -++ res->vid_hdr_offset = NOR_DEFAULT_VID_HDR_OFF; -++ } -++ else { -++ snprintf(err_buf, err_buf_size, -++ "Unkown flash type: %s", value); -++ goto err; -++ } -++ -++ rc = bootenv_get_num(pdd, "flash_eraseblock_size", -++ &(res->eb_size)); -++ if (rc != 0) { -++ EBUF("Cannot read 'flash_eraseblock_size' from pdd."); -++ goto err; -++ } -++ -++ rc = bootenv_get_num(pdd, "flash_size", -++ &(res->flash_size)); -++ if (rc != 0) { -++ EBUF("Cannot read 'flash_size' from pdd."); -++ goto err; -++ } -++ -++ goto out; -++ err: -++ if (res) { -++ free(res); -++ res = NULL; -++ } -++ out: -++ bootenv_destroy(&pdd); -++ *pdd_data = res; -++ return rc; -++} -++ -++int -++read_pfi_raw(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_raw_t* pfi_raw, -++ const char* label, char* err_buf, size_t err_buf_size) -++{ -++ int rc = 0; -++ char tmp_str[PFI_KEYWORD_LEN]; -++ bootenv_list_t raw_start_list = NULL; -++ pfi_raw_t res; -++ size_t size; -++ -++ res = (pfi_raw_t) malloc(sizeof(struct pfi_raw)); -++ if (!res) -++ return -ENOMEM; -++ -++ rc = pfi_header_getnumber(pfi_hd, "size", &(res->data_size)); -++ if (rc != 0) { -++ EBUF_PFI("Cannot read 'size' from PFI."); -++ goto err; -++ } -++ -++ rc = pfi_header_getnumber(pfi_hd, "crc", &(res->crc)); -++ if (rc != 0) { -++ EBUF_PFI("Cannot read 'crc' from PFI."); -++ goto err; -++ } -++ -++ rc = pfi_header_getstring(pfi_hd, "raw_starts", -++ tmp_str, PFI_KEYWORD_LEN); -++ if (rc != 0) { -++ EBUF_PFI("Cannot read 'raw_starts' from PFI."); -++ goto err; -++ } -++ -++ rc = bootenv_list_create(&raw_start_list); -++ if (rc != 0) { -++ goto err; -++ } -++ -++ rc = bootenv_list_import(raw_start_list, tmp_str); -++ if (rc != 0) { -++ EBUF_PFI("Cannot translate PFI value: %s", tmp_str); -++ goto err; -++ } -++ -++ rc = bootenv_list_to_num_vector(raw_start_list, -++ &size, &(res->starts)); -++ res->starts_size = size; -++ -++ if (rc != 0) { -++ EBUF_PFI("Cannot create numeric value array: %s", tmp_str); -++ goto err; -++ } -++ -++ goto out; -++ -++ err: -++ if (res) { -++ free(res); -++ res = NULL; -++ } -++ out: -++ bootenv_list_destroy(&raw_start_list); -++ *pfi_raw = res; -++ return rc; -++} -++ -++int -++read_pfi_ubi(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_ubi_t* pfi_ubi, -++ const char *label, char* err_buf, size_t err_buf_size) -++{ -++ int rc = 0; -++ const char** tmp_names = NULL; -++ char tmp_str[PFI_KEYWORD_LEN]; -++ bootenv_list_t ubi_id_list = NULL; -++ bootenv_list_t ubi_name_list = NULL; -++ pfi_ubi_t res; -++ uint32_t i; -++ size_t size; -++ -++ res = (pfi_ubi_t) calloc(1, sizeof(struct pfi_ubi)); -++ if (!res) -++ return -ENOMEM; -++ -++ rc = pfi_header_getnumber(pfi_hd, "size", &(res->data_size)); -++ if (rc != 0) { -++ EBUF_PFI("Cannot read 'size' from PFI."); -++ goto err; -++ } -++ -++ rc = pfi_header_getnumber(pfi_hd, "crc", &(res->crc)); -++ if (rc != 0) { -++ EBUF_PFI("Cannot read 'crc' from PFI."); -++ goto err; -++ } -++ -++ rc = pfi_header_getstring(pfi_hd, "ubi_ids", tmp_str, PFI_KEYWORD_LEN); -++ if (rc != 0) { -++ EBUF_PFI("Cannot read 'ubi_ids' from PFI."); -++ goto err; -++ } -++ -++ rc = bootenv_list_create(&ubi_id_list); -++ if (rc != 0) { -++ goto err; -++ } -++ rc = bootenv_list_create(&ubi_name_list); -++ if (rc != 0) { -++ goto err; -++ } -++ -++ rc = bootenv_list_import(ubi_id_list, tmp_str); -++ if (rc != 0) { -++ EBUF_PFI("Cannot translate PFI value: %s", tmp_str); -++ goto err; -++ } -++ -++ rc = bootenv_list_to_num_vector(ubi_id_list, &size, -++ &(res->ids)); -++ res->ids_size = size; -++ if (rc != 0) { -++ EBUF_PFI("Cannot create numeric value array: %s", tmp_str); -++ goto err; -++ } -++ -++ if (res->ids_size == 0) { -++ rc = -1; -++ EBUF_PFI("Sanity check failed: No ubi_ids specified."); -++ goto err; -++ } -++ -++ rc = pfi_header_getstring(pfi_hd, "ubi_type", -++ tmp_str, PFI_KEYWORD_LEN); -++ if (rc != 0) { -++ EBUF_PFI("Cannot read 'ubi_type' from PFI."); -++ goto err; -++ } -++ if (strcmp(tmp_str, "static") == 0) -++ res->type = pfi_ubi_static; -++ else if (strcmp(tmp_str, "dynamic") == 0) -++ res->type = pfi_ubi_dynamic; -++ else { -++ EBUF_PFI("Unknown ubi_type in PFI."); -++ goto err; -++ } -++ -++ rc = pfi_header_getnumber(pfi_hd, "ubi_alignment", &(res->alignment)); -++ if (rc != 0) { -++ EBUF_PFI("Cannot read 'ubi_alignment' from PFI."); -++ goto err; -++ } -++ -++ rc = pfi_header_getnumber(pfi_hd, "ubi_size", &(res->size)); -++ if (rc != 0) { -++ EBUF_PFI("Cannot read 'ubi_size' from PFI."); -++ goto err; -++ } -++ -++ rc = pfi_header_getstring(pfi_hd, "ubi_names", -++ tmp_str, PFI_KEYWORD_LEN); -++ if (rc != 0) { -++ EBUF_PFI("Cannot read 'ubi_names' from PFI."); -++ goto err; -++ } -++ -++ rc = bootenv_list_import(ubi_name_list, tmp_str); -++ if (rc != 0) { -++ EBUF_PFI("Cannot translate PFI value: %s", tmp_str); -++ goto err; -++ } -++ rc = bootenv_list_to_vector(ubi_name_list, &size, -++ &(tmp_names)); -++ res->names_size = size; -++ if (rc != 0) { -++ EBUF_PFI("Cannot create string array: %s", tmp_str); -++ goto err; -++ } -++ -++ if (res->names_size != res->ids_size) { -++ EBUF_PFI("Sanity check failed: ubi_ids list does not match " -++ "sizeof ubi_names list."); -++ rc = -1; -++ } -++ -++ /* copy tmp_names to own structure */ -++ res->names = (char**) calloc(1, res->names_size * sizeof (char*)); -++ if (res->names == NULL) -++ goto err; -++ -++ for (i = 0; i < res->names_size; i++) { -++ res->names[i] = calloc(PFI_UBI_VOL_NAME_LEN + 1, sizeof(char)); -++ if (res->names[i] == NULL) -++ goto err; -++ strncpy(res->names[i], tmp_names[i], PFI_UBI_VOL_NAME_LEN + 1); -++ } -++ -++ goto out; -++ -++ err: -++ if (res) { -++ if (res->names) { -++ for (i = 0; i < res->names_size; i++) { -++ if (res->names[i]) { -++ free(res->names[i]); -++ } -++ } -++ free(res->names); -++ } -++ if (res->ids) { -++ free(res->ids); -++ } -++ free(res); -++ res = NULL; -++ } -++ -++ out: -++ bootenv_list_destroy(&ubi_id_list); -++ bootenv_list_destroy(&ubi_name_list); -++ if (tmp_names != NULL) -++ free(tmp_names); -++ *pfi_ubi = res; -++ return rc; -++} -++ -++ -++int -++free_pdd_data(pdd_data_t* pdd_data) -++{ -++ if (*pdd_data) { -++ free(*pdd_data); -++ } -++ *pdd_data = NULL; -++ -++ return 0; -++} -++ -++int -++free_pfi_raw(pfi_raw_t* pfi_raw) -++{ -++ pfi_raw_t tmp = *pfi_raw; -++ if (tmp) { -++ if (tmp->starts) -++ free(tmp->starts); -++ free(tmp); -++ } -++ *pfi_raw = NULL; -++ -++ return 0; -++} -++ -++int -++free_pfi_ubi(pfi_ubi_t* pfi_ubi) -++{ -++ size_t i; -++ pfi_ubi_t tmp = *pfi_ubi; -++ if (tmp) { -++ if (tmp->ids) -++ free(tmp->ids); -++ if (tmp->names) { -++ for (i = 0; i < tmp->names_size; i++) { -++ if (tmp->names[i]) { -++ free(tmp->names[i]); -++ } -++ } -++ free(tmp->names); -++ } -++ free(tmp); -++ } -++ *pfi_ubi = NULL; -++ -++ return 0; -++} -++ -++ -++int -++read_pfi_headers(list_t *pfi_raws, list_t *pfi_ubis, FILE* fp_pfi, -++ char* err_buf, size_t err_buf_size) -++{ -++ int rc = 0; -++ char mode[PFI_KEYWORD_LEN]; -++ char label[PFI_LABEL_LEN]; -++ -++ *pfi_raws = mk_empty(); pfi_raw_t raw = NULL; -++ *pfi_ubis = mk_empty(); pfi_ubi_t ubi = NULL; -++ pfi_header pfi_header = NULL; -++ -++ /* read all headers from PFI and store them in lists */ -++ rc = pfi_header_init(&pfi_header); -++ if (rc != 0) { -++ EBUF("Cannot initialize pfi header."); -++ goto err; -++ } -++ while ((rc == 0) && !feof(fp_pfi)) { -++ rc = pfi_header_read(fp_pfi, pfi_header); -++ if (rc != 0) { -++ if (rc == PFI_DATA_START) { -++ rc = 0; -++ break; /* data section starts, -++ all headers read */ -++ } -++ else { -++ goto err; -++ } -++ } -++ rc = pfi_header_getstring(pfi_header, "label", label, -++ PFI_LABEL_LEN); -++ if (rc != 0) { -++ EBUF("Cannot read 'label' from PFI."); -++ goto err; -++ } -++ rc = pfi_header_getstring(pfi_header, "mode", mode, -++ PFI_KEYWORD_LEN); -++ if (rc != 0) { -++ EBUF("Cannot read 'mode' from PFI."); -++ goto err; -++ } -++ if (strcmp(mode, "ubi") == 0) { -++ rc = read_pfi_ubi(pfi_header, fp_pfi, &ubi, label, -++ err_buf, err_buf_size); -++ if (rc != 0) { -++ goto err; -++ } -++ *pfi_ubis = append_elem(ubi, *pfi_ubis); -++ } -++ else if (strcmp(mode, "raw") == 0) { -++ rc = read_pfi_raw(pfi_header, fp_pfi, &raw, label, -++ err_buf, err_buf_size); -++ if (rc != 0) { -++ goto err; -++ } -++ *pfi_raws = append_elem(raw, *pfi_raws); -++ } -++ else { -++ EBUF("Recvieved unknown mode from PFI: %s", mode); -++ goto err; -++ } -++ } -++ goto out; -++ -++ err: -++ *pfi_raws = remove_all((free_func_t)&free_pfi_raw, *pfi_raws); -++ *pfi_ubis = remove_all((free_func_t)&free_pfi_ubi, *pfi_ubis); -++ out: -++ pfi_header_destroy(&pfi_header); -++ return rc; -++ -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/reader.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/reader.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/reader.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/reader.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,87 @@ -++#ifndef __READER_H__ -++#define __READER_H__ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ * -++ * Read Platform Description Data (PDD). -++ */ -++ -++#include -++#include -++ -++#include "pfi.h" -++#include "bootenv.h" -++#include "list.h" -++ -++typedef enum flash_type_t { -++ NAND_FLASH = 0, -++ NOR_FLASH, -++} flash_type_t; -++ -++typedef struct pdd_data *pdd_data_t; -++typedef struct pfi_raw *pfi_raw_t; -++typedef struct pfi_ubi *pfi_ubi_t; -++ -++struct pdd_data { -++ uint32_t flash_size; -++ uint32_t flash_page_size; -++ uint32_t eb_size; -++ uint32_t vid_hdr_offset; -++ flash_type_t flash_type; -++}; -++ -++struct pfi_raw { -++ uint32_t data_size; -++ uint32_t *starts; -++ uint32_t starts_size; -++ uint32_t crc; -++}; -++ -++struct pfi_ubi { -++ uint32_t data_size; -++ uint32_t alignment; -++ uint32_t *ids; -++ uint32_t ids_size; -++ char **names; -++ uint32_t names_size; -++ uint32_t size; -++ enum { pfi_ubi_dynamic, pfi_ubi_static } type; -++ int curr_seqnum; /* specifies the seqnum taken in an update, -++ default: 0 (used by pfiflash, ubimirror) */ -++ uint32_t crc; -++}; -++ -++int read_pdd_data(FILE* fp_pdd, pdd_data_t *pdd_data, -++ char *err_buf, size_t err_buf_size); -++int read_pfi_raw(pfi_header pfi_hd, FILE* fp_pfi, pfi_raw_t *pfi_raw, -++ const char *label, char *err_buf, size_t err_buf_size); -++int read_pfi_ubi(pfi_header pfi_hd, FILE* fp_pfi, pfi_ubi_t *pfi_ubi, -++ const char *label, char *err_buf, size_t err_buf_size); -++ -++/** -++ * @brief Reads all pfi headers into list structures, separated by -++ * RAW and UBI sections. -++ */ -++int read_pfi_headers(list_t *pfi_raws, list_t *pfi_ubis, FILE* fp_pfi, -++ char* err_buf, size_t err_buf_size); -++int free_pdd_data(pdd_data_t *pdd_data); -++int free_pfi_raw(pfi_raw_t *raw_pfi); -++int free_pfi_ubi(pfi_ubi_t *pfi_ubi); -++ -++#endif /* __READER_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/ubigen.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/ubigen.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/ubigen.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/ubigen.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,359 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ * -++ * Tool to add UBI headers to binary images. -++ * -++ * 1.0 Initial version -++ * 1.1 Different CRC32 start value -++ * 1.2 Removed argp because we want to use uClibc. -++ * 1.3 Minor cleanups -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "ubigen.h" -++#include "config.h" -++ -++#define PROGRAM_VERSION "1.3" -++ -++typedef enum action_t { -++ ACT_NORMAL = 0x00000001, -++ ACT_BROKEN_UPDATE = 0x00000002, -++} action_t; -++ -++static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" -++ "ubigen - a tool for adding UBI information to a binary input file.\n"; -++ -++static const char *optionsstr = -++" Common settings:\n" -++" -c, --copyright Print copyright information.\n" -++" -d, --debug\n" -++" -v, --verbose Print more progress information.\n" -++"\n" -++" UBI Settings:\n" -++" -A, --alignment= Set the alignment size to (default 1).\n" -++" Values can be specified as bytes, 'ki' or 'Mi'.\n" -++" -B, --blocksize= Set the eraseblock size to (default 128\n" -++" KiB).\n" -++" Values can be specified as bytes, 'ki' or 'Mi'.\n" -++" -E, --erasecount= Set the erase count to (default 0)\n" -++" -I, --id= The UBI volume id.\n" -++" -O, --offset= Offset from start of an erase block to the UBI\n" -++" volume header.\n" -++" -T, --type= The UBI volume type:\n" -++" 1 = dynamic, 2 = static\n" -++" -X, --setver= Set UBI version number to (default 1)\n" -++"\n" -++" Input/Output:\n" -++" -i, --infile= Read input from file.\n" -++" -o, --outfile= Write output to file (default is stdout).\n" -++"\n" -++" Special options:\n" -++" -U, --broken-update= Create an ubi image which simulates a broken\n" -++" update.\n" -++" specifies the logical eraseblock number to\n" -++" update.\n" -++"\n" -++" -?, --help Give this help list\n" -++" --usage Give a short usage message\n" -++" -V, --version Print program version\n"; -++ -++static const char *usage = -++"Usage: ubigen [-cdv?V] [-A ] [-B ] [-E ] [-I ]\n" -++" [-O ] [-T ] [-X ] [-i ] [-o ]\n" -++" [-U ] [--copyright] [--debug] [--verbose] [--alignment=]\n" -++" [--blocksize=] [--erasecount=] [--id=]\n" -++" [--offset=] [--type=] [--setver=]\n" -++" [--infile=] [--outfile=]\n" -++" [--broken-update=] [--help] [--usage] [--version]\n"; -++ -++struct option long_options[] = { -++ { .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' }, -++ { .name = "debug", .has_arg = 0, .flag = NULL, .val = 'd' }, -++ { .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' }, -++ { .name = "alignment", .has_arg = 1, .flag = NULL, .val = 'A' }, -++ { .name = "blocksize", .has_arg = 1, .flag = NULL, .val = 'B' }, -++ { .name = "erasecount", .has_arg = 1, .flag = NULL, .val = 'E' }, -++ { .name = "id", .has_arg = 1, .flag = NULL, .val = 'I' }, -++ { .name = "offset", .has_arg = 1, .flag = NULL, .val = 'O' }, -++ { .name = "type", .has_arg = 1, .flag = NULL, .val = 'T' }, -++ { .name = "setver", .has_arg = 1, .flag = NULL, .val = 'X' }, -++ { .name = "infile", .has_arg = 1, .flag = NULL, .val = 'i' }, -++ { .name = "outfile", .has_arg = 1, .flag = NULL, .val = 'o' }, -++ { .name = "broken-update", .has_arg = 1, .flag = NULL, .val = 'U' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, -++ { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ { NULL, 0, NULL, 0} -++}; -++ -++static const char copyright [] __attribute__((unused)) = -++ "Copyright IBM Corp 2006"; -++ -++#define CHECK_ENDP(option, endp) do { \ -++ if (*endp) { \ -++ fprintf(stderr, \ -++ "Parse error option \'%s\'. " \ -++ "No correct numeric value.\n" \ -++ , option); \ -++ exit(EXIT_FAILURE); \ -++ } \ -++} while(0) -++ -++typedef struct myargs { -++ /* common settings */ -++ action_t action; -++ int verbose; -++ -++ int32_t id; -++ uint8_t type; -++ uint32_t eb_size; -++ uint64_t ec; -++ uint8_t version; -++ uint32_t hdr_offset; -++ uint32_t update_block; -++ uint32_t alignment; -++ -++ FILE* fp_in; -++ FILE* fp_out; -++ -++ /* special stuff needed to get additional arguments */ -++ char *arg1; -++ char **options; /* [STRING...] */ -++} myargs; -++ -++ -++static int ustrtoul(const char *cp, char **endp, unsigned int base) -++{ -++ unsigned long result = strtoul(cp, endp, base); -++ -++ switch (**endp) { -++ case 'G': -++ result *= 1024; -++ case 'M': -++ result *= 1024; -++ case 'k': -++ case 'K': -++ result *= 1024; -++ /* "Ki", "ki", "Mi" or "Gi" are to be used. */ -++ if ((*endp)[1] == 'i') -++ (*endp) += 2; -++ } -++ return result; -++} -++ -++static int -++parse_opt(int argc, char **argv, myargs *args) -++{ -++ int err = 0; -++ char* endp; -++ -++ while (1) { -++ int key; -++ -++ key = getopt_long(argc, argv, "cdvA:B:E:I:O:T:X:i:o:U:?V", -++ long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ case 'c': -++ fprintf(stderr, "%s\n", copyright); -++ exit(0); -++ break; -++ case 'o': /* output */ -++ args->fp_out = fopen(optarg, "wb"); -++ if ((args->fp_out) == NULL) { -++ fprintf(stderr, "Cannot open file %s " -++ "for output\n", optarg); -++ exit(1); -++ } -++ break; -++ case 'i': /* input */ -++ args->fp_in = fopen(optarg, "rb"); -++ if ((args->fp_in) == NULL) { -++ fprintf(stderr, "Cannot open file %s " -++ "for input\n", optarg); -++ exit(1); -++ } -++ break; -++ case 'v': /* verbose */ -++ args->verbose = 1; -++ break; -++ -++ case 'B': /* eb_size */ -++ args->eb_size = -++ (uint32_t)ustrtoul(optarg, &endp, 0); -++ CHECK_ENDP("B", endp); -++ break; -++ case 'E': /* erasecount */ -++ args->ec = (uint64_t)strtoul(optarg, &endp, 0); -++ CHECK_ENDP("E", endp); -++ break; -++ case 'I': /* id */ -++ args->id = (uint16_t)strtoul(optarg, &endp, 0); -++ CHECK_ENDP("I", endp); -++ break; -++ case 'T': /* type */ -++ args->type = -++ (uint16_t)strtoul(optarg, &endp, 0); -++ CHECK_ENDP("T", endp); -++ break; -++ case 'X': /* versionnr */ -++ args->version = -++ (uint8_t)strtoul(optarg, &endp, 0); -++ CHECK_ENDP("X", endp); -++ break; -++ case 'O': /* offset for volume hdr */ -++ args->hdr_offset = -++ (uint32_t) strtoul(optarg, &endp, 0); -++ CHECK_ENDP("O", endp); -++ break; -++ -++ case 'U': /* broken update */ -++ args->action = ACT_BROKEN_UPDATE; -++ args->update_block = -++ (uint32_t) strtoul(optarg, &endp, 0); -++ CHECK_ENDP("U", endp); -++ break; -++ -++ case '?': /* help */ -++ fprintf(stderr, "Usage: ubigen [OPTION...]\n"); -++ fprintf(stderr, "%s", doc); -++ fprintf(stderr, "%s", optionsstr); -++ fprintf(stderr, "\nReport bugs to %s\n", -++ PACKAGE_BUGREPORT); -++ exit(0); -++ break; -++ -++ case 'V': -++ fprintf(stderr, "%s\n", PROGRAM_VERSION); -++ exit(0); -++ break; -++ -++ default: -++ fprintf(stderr, "%s", usage); -++ exit(-1); -++ } -++ } -++ -++ if (optind < argc) { -++ if (!args->fp_in) { -++ args->fp_in = fopen(argv[optind++], "rb"); -++ if ((args->fp_in) == NULL) { -++ fprintf(stderr, "Cannot open file %s for " -++ "input\n", argv[optind]); -++ exit(1); -++ } -++ } -++ } -++ if (args->id < 0) { -++ err = 1; -++ fprintf(stderr, -++ "Please specify an UBI Volume ID.\n"); -++ } -++ if (args->type == 0) { -++ err = 1; -++ fprintf(stderr, -++ "Please specify an UBI Volume type.\n"); -++ } -++ if (err) { -++ fprintf(stderr, "%s", usage); -++ exit(1); -++ } -++ -++ return 0; -++} -++ -++ -++int -++main(int argc, char **argv) -++{ -++ int rc = 0; -++ ubi_info_t u; -++ struct stat file_info; -++ off_t input_len = 0; /* only used in static volumes */ -++ -++ myargs args = { -++ .action = ACT_NORMAL, -++ .verbose = 0, -++ -++ .id = -1, -++ .type = 0, -++ .eb_size = 0, -++ .update_block = 0, -++ .ec = 0, -++ .version = 0, -++ .hdr_offset = (DEFAULT_PAGESIZE) - (UBI_VID_HDR_SIZE), -++ .alignment = 1, -++ -++ .fp_in = NULL, -++ .fp_out = stdout, -++ /* arguments */ -++ .arg1 = NULL, -++ .options = NULL, -++ }; -++ -++ ubigen_init(); /* Init CRC32 table in ubigen */ -++ -++ /* parse arguments */ -++ parse_opt(argc, argv, &args); -++ -++ if (fstat(fileno(args.fp_in), &file_info) != 0) { -++ fprintf(stderr, "Cannot fetch file size " -++ "from input file.\n"); -++ } -++ input_len = file_info.st_size; -++ -++ rc = ubigen_create(&u, (uint32_t)args.id, args.type, -++ args.eb_size, args.ec, args.alignment, -++ args.version, args.hdr_offset, 0 ,input_len, -++ args.fp_in, args.fp_out); -++ -++ if (rc != 0) { -++ fprintf(stderr, "Cannot create UBI info handler rc: %d\n", rc); -++ exit(EXIT_FAILURE); -++ } -++ -++ if (!args.fp_in || !args.fp_out) { -++ fprintf(stderr, "Input/Output error.\n"); -++ exit(EXIT_FAILURE); -++ -++ } -++ -++ if (args.action & ACT_NORMAL) { -++ rc = ubigen_write_complete(u); -++ } -++ else if (args.action & ACT_BROKEN_UPDATE) { -++ rc = ubigen_write_broken_update(u, args.update_block); -++ } -++ if (rc != 0) { -++ fprintf(stderr, "Error converting input data.\n"); -++ exit(EXIT_FAILURE); -++ } -++ -++ rc = ubigen_destroy(&u); -++ return rc; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/ubigen.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/ubigen.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/ubigen.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/ubigen.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,149 @@ -++#ifndef __UBIGEN_H__ -++#define __UBIGEN_H__ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Frank Haverkamp -++ * -++ * An utility to update UBI volumes. -++ */ -++ -++#include /* FILE */ -++#include -++#include -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++#define DEFAULT_BLOCKSIZE (128 * 1024) -++#define DEFAULT_PAGESIZE (2*1024) -++ -++#define EUBIGEN_INVALID_TYPE 1 -++#define EUBIGEN_INVALID_HDR_OFFSET 2 -++#define EUBIGEN_INVALID_ALIGNMENT 3 -++#define EUBIGEN_TOO_SMALL_EB 4 -++#define EUBIGEN_MAX_ERROR 5 -++ -++ -++typedef enum action { -++ NO_ERROR = 0x00000000, -++ BROKEN_HDR_CRC = 0x00000001, -++ BROKEN_DATA_CRC = 0x00000002, -++ BROKEN_DATA_SIZE = 0x00000004, -++ BROKEN_OMIT_BLK = 0x00000008, -++ MARK_AS_UPDATE = 0x00000010, -++} ubigen_action_t; -++ -++typedef struct ubi_info *ubi_info_t; -++ -++/** -++ * @brief Initialize the internal CRC32 table. -++ * @note Necessary because of the used crc32 function in UBI. -++ * A usage of CRC32, from e.g. zlib will fail. -++ */ -++void ubigen_init(void); -++ -++/** -++ * @brief Create an ubigen handle. -++ * @param ... -++ * @return 0 On sucess. -++ * else Error. -++ * @note This parameterlist is ugly. But we have to use -++ * two big structs and meta information internally, -++ * filling them would be even uglier. -++ */ -++int ubigen_create(ubi_info_t *u, uint32_t vol_id, uint8_t vol_type, -++ uint32_t eb_size, uint64_t ec, uint32_t alignment, -++ uint8_t version, uint32_t vid_hdr_offset, -++ uint8_t compat_flag, size_t data_size, -++ FILE* fp_in, FILE* fp_out); -++ -++/** -++ * @brief Destroy an ubigen handle. -++ * @param u Handle to free. -++ * @return 0 On success. -++ * else Error. -++ */ -++int ubigen_destroy(ubi_info_t *u); -++ -++/** -++ * @brief Get number of total logical EBs, necessary for the -++ * complete storage of data in the handle. -++ * @param u The handle. -++ * @return 0 On success. -++ * else Error. -++ */ -++int ubigen_get_leb_total(ubi_info_t u, size_t* total); -++ -++/** -++ * @brief Get the size in bytes of one logical EB in the handle. -++ * @param u The handle. -++ * @return 0 On success. -++ * else Error. -++ */ -++int ubigen_get_leb_size(ubi_info_t u, size_t* size); -++ -++ -++/** -++ * @brief Write a logical EB (fits exactly into 1 physical EB). -++ * @param u Handle which holds all necessary data. -++ * @param action Additional operations which shall be applied on this -++ * logical eraseblock. Mostly injecting artifical errors. -++ * @return 0 On success. -++ * else Error. -++ */ -++int ubigen_write_leb(ubi_info_t u, ubigen_action_t action); -++ -++/** -++ * @brief Write a complete array of logical eraseblocks at once. -++ * @param u Handle which holds all necessary data. -++ * @return 0 On success. -++ * else Error. -++ */ -++int ubigen_write_complete(ubi_info_t u); -++ -++/** -++ * @brief Write a single block which is extracted from the -++ * binary input data. -++ * @param u Handle which holds all necessary data. -++ * @param blk Logical eraseblock which shall hold a inc. copy entry -++ * and a bad data crc. -++ * @return 0 On success. -++ * else Error. -++ */ -++int ubigen_write_broken_update(ubi_info_t u, uint32_t blk); -++ -++/** -++ * @brief Use the current ubi_info data and some additional data -++ * to set an UBI volume table entry from it. -++ * @param u Handle which holds some of the necessary data. -++ * @param res_bytes Number of reserved bytes which is stored in the volume -++ * table entry. -++ * @param name A string which shall be used as a volume label. -++ * @param lvol_r A pointer to a volume table entry. -++ * @return 0 On success. -++ * else Error. -++ */ -++int ubigen_set_lvol_rec(ubi_info_t u, size_t reserved_bytes, -++ const char* name, struct ubi_vtbl_record *lvol_rec); -++ -++#ifdef __cplusplus -++} -++#endif -++ -++#endif /* __UBIGEN_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/ubimirror.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/ubimirror.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/ubimirror.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/ubimirror.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,213 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ * -++ * 1.2 Removed argp because we want to use uClibc. -++ * 1.3 Minor cleanups -++ * 1.4 Migrated to new libubi -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "config.h" -++#include "error.h" -++#include "example_ubi.h" -++#include "ubimirror.h" -++ -++#define PROGRAM_VERSION "1.4" -++ -++typedef enum action_t { -++ ACT_NORMAL = 0, -++ ACT_ARGP_ABORT, -++ ACT_ARGP_ERR, -++} action_t; -++ -++#define ABORT_ARGP do { \ -++ args->action = ACT_ARGP_ABORT; \ -++} while (0) -++ -++#define ERR_ARGP do { \ -++ args->action = ACT_ARGP_ERR; \ -++} while (0) -++ -++#define VOL_ARGS_MAX 2 -++ -++static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" -++ "ubimirror - mirrors ubi volumes.\n"; -++ -++static const char *optionsstr = -++" -c, --copyright Print copyright information.\n" -++" -s, --side= Use the side as source.\n" -++" -?, --help Give this help list\n" -++" --usage Give a short usage message\n" -++" -V, --version Print program version\n"; -++ -++static const char *usage = -++"Usage: ubimirror [-c?V] [-s ] [--copyright] [--side=]\n" -++" [--help] [--usage] [--version] \n"; -++ -++static const char copyright [] __attribute__((unused)) = -++ "(C) IBM Coorporation 2007"; -++ -++struct option long_options[] = { -++ { .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' }, -++ { .name = "side", .has_arg = 1, .flag = NULL, .val = 's' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, -++ { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, -++ { NULL, 0, NULL, 0} -++}; -++ -++typedef struct myargs { -++ action_t action; -++ int side; -++ int vol_no; /* index of current volume */ -++ /* @FIXME replace by bootenv_list, makes live easier */ -++ /* @FIXME remove the constraint of two entries in the array */ -++ const char* vol[VOL_ARGS_MAX]; /* comma separated list of src/dst -++ volumes */ -++ char *arg1; -++ char **options; /* [STRING...] */ -++} myargs; -++ -++static int -++get_update_side(const char* str) -++{ -++ uint32_t i = strtoul(str, NULL, 0); -++ -++ if ((i != 0) && (i != 1)) { -++ return -1; -++ } -++ return i; -++} -++ -++ -++static int -++parse_opt(int argc, char **argv, myargs *args) -++{ -++ while (1) { -++ int key; -++ -++ key = getopt_long(argc, argv, "cs:?V", long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ case 'c': -++ err_msg("%s", copyright); -++ ABORT_ARGP; -++ break; -++ case 's': -++ args->side = get_update_side(optarg); -++ if (args->side < 0) { -++ err_msg("Unsupported seqnum: %s.\n" -++ "Supported seqnums are '0' " -++ "and '1'\n", optarg); -++ ERR_ARGP; -++ } -++ break; -++ case '?': /* help */ -++ err_msg("Usage: ubimirror [OPTION...] " -++ " \n"); -++ err_msg("%s", doc); -++ err_msg("%s", optionsstr); -++ err_msg("\nReport bugs to %s\n", -++ PACKAGE_BUGREPORT); -++ exit(0); -++ break; -++ case 'V': -++ err_msg("%s", PROGRAM_VERSION); -++ exit(0); -++ break; -++ default: -++ err_msg("%s", usage); -++ exit(-1); -++ } -++ } -++ -++ while (optind < argc) { -++ /* only two entries allowed */ -++ if (args->vol_no >= VOL_ARGS_MAX) { -++ err_msg("%s", usage); -++ ERR_ARGP; -++ } -++ args->vol[(args->vol_no)++] = argv[optind++]; -++ } -++ -++ return 0; -++} -++ -++ -++int -++main(int argc, char **argv) { -++ int rc = 0; -++ unsigned int ids[VOL_ARGS_MAX]; -++ char err_buf[1024]; -++ -++ myargs args = { -++ .action = ACT_NORMAL, -++ .side = -1, -++ .vol_no = 0, -++ .vol = {"", ""}, -++ .options = NULL, -++ }; -++ -++ parse_opt(argc, argv, &args); -++ if (args.action == ACT_ARGP_ERR) { -++ rc = 127; -++ goto err; -++ } -++ if (args.action == ACT_ARGP_ABORT) { -++ rc = 126; -++ goto out; -++ } -++ if (args.vol_no < VOL_ARGS_MAX) { -++ fprintf(stderr, "missing volume number for %s\n", -++ args.vol_no == 0 ? "source and target" : "target"); -++ rc = 125; -++ goto out; -++ } -++ for( rc = 0; rc < args.vol_no; ++rc){ -++ char *endp; -++ ids[rc] = strtoul(args.vol[rc], &endp, 0); -++ if( *endp != '\0' ){ -++ fprintf(stderr, "invalid volume number %s\n", -++ args.vol[rc]); -++ rc = 125; -++ goto out; -++ } -++ } -++ rc = ubimirror(EXAMPLE_UBI_DEVICE, args.side, ids, args.vol_no, -++ err_buf, sizeof(err_buf)); -++ if( rc ){ -++ err_buf[sizeof err_buf - 1] = '\0'; -++ fprintf(stderr, err_buf); -++ if( rc < 0 ) -++ rc = -rc; -++ } -++ out: -++ err: -++ return rc; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/ubimirror.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/ubimirror.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/ubimirror.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/ubimirror.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,66 @@ -++#ifndef __UBIMIRROR_H__ -++#define __UBIMIRROR_H__ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ * -++ * Author: Oliver Lohmann -++ * -++ * An utility to mirror UBI volumes. -++ */ -++ -++#include -++ -++/** -++ * @def EUBIMIRROR_SRC_EQ_DST -++ * @brief Given source volume is also in the set of destination volumes. -++ */ -++#define EUBIMIRROR_SRC_EQ_DST 20 -++ -++/** -++ * @def EUBIMIRROR_NO_SRC -++ * @brief The given source volume does not exist. -++ */ -++#define EUBIMIRROR_NO_SRC 21 -++ -++/** -++ * @def EUBIMIRROR_NO_DST -++ * @brief One of the given destination volumes does not exist. -++ */ -++#define EUBIMIRROR_NO_DST 22 -++ -++/** -++ * @brief Mirrors UBI devices from a source device (specified by seqnum) -++ * to n target devices. -++ * @param devno Device number used by the UBI operations. -++ * @param seqnum An index into ids (defines the src_id). -++ * @param ids An array of ids. -++ * @param ids_size The number of entries in the ids array. -++ * @param err_buf A buffer to store verbose error messages. -++ * @param err_buf_size The size of the error buffer. -++ * -++ * @note A seqnum of value < 0 defaults to a seqnum of 0. -++ * @note A seqnum exceeding the range of ids_size defaults to 0. -++ * @note An empty ids list results in a empty stmt. -++ * @pre The UBI volume which shall be used as source volume exists. -++ * @pre The UBI volumes which are defined as destination volumes exist. -++ * @post The content of the UBI volume which was defined as source volume -++ * equals the content of the volumes which were defined as destination. -++ */ -++int ubimirror(uint32_t devno, int seqnum, uint32_t* ids, ssize_t ids_size, -++ char *err_buf, size_t err_buf_size); -++ -++#endif /* __UBIMIRROR_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/unubi.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/unubi.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/unubi.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/unubi.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1024 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006, 2007 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * Authors: Drake Dowsett, dowsett@de.ibm.com -++ * Frank Haverkamp, haver@vnet.ibm.com -++ * -++ * 1.2 Removed argp because we want to use uClibc. -++ * 1.3 Minor cleanups. -++ * 1.4 Meanwhile Drake had done a lot of changes, syncing those. -++ * 1.5 Bugfixes, simplifications -++ */ -++ -++/* -++ * unubi reads an image file containing blocks of UBI headers and data -++ * (such as produced from nand2bin) and rebuilds the volumes within. The -++ * default operation (when no flags are given) is to rebuild all valid -++ * volumes found in the image. unubi can also read straight from the -++ * onboard MTD device (ex. /dev/mtdblock/NAND). -++ */ -++ -++/* TODO: consideration for dynamic vs. static volumes */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "crc32.h" -++#include "unubi_analyze.h" -++ -++#define EXEC "unubi" -++#define CONTACT "haver@vnet.ibm.com" -++#define VERSION "1.5" -++ -++static char doc[] = "\nVersion: " VERSION "\n"; -++static int debug = 0; -++ -++static const char *optionsstr = -++"Extract volumes and/or analysis information from an UBI data file.\n" -++"When no parameters are flagged or given, the default operation is\n" -++"to rebuild all valid complete UBI volumes found within the image.\n" -++"\n" -++" OPERATIONS\n" -++" -a, --analyze Analyze image and create gnuplot graphs\n" -++" -i, --info-table Extract volume information tables\n" -++" -r, --rebuild= Extract and rebuild volume\n" -++"\n" -++" OPTIONS\n" -++" -b, --blocksize= Specify size of eraseblocks in image in bytes\n" -++" (default 128KiB)\n" -++" -d, --dir= Specify output directory\n" -++" -D, --debug Enable debug output\n" -++" -s, --headersize= Specify size reserved for metadata in eraseblock\n" -++ " in bytes (default 2048 Byte)\n" -++ /* the -s option might be insufficient when using different vid -++ offset than what we used when writing this tool ... Better would -++ probably be --vid-hdr-offset or alike */ -++"\n" -++" ADVANCED\n" -++" -e, --eb-split Generate individual eraseblock images (all\n" -++" eraseblocks)\n" -++" -v, --vol-split Generate individual eraseblock images (valid\n" -++" eraseblocks only)\n" -++" -V, --vol-split! Raw split by eraseblock (valid eraseblocks only)\n" -++"\n" -++" -?, --help Give this help list\n" -++" --usage Give a short usage message\n" -++" --version Print program version\n" -++"\n"; -++ -++static const char *usage = -++"Usage: unubi [-aievV?] [-r ] [-b ] [-d ]\n" -++" [-s ] [--analyze] [--info-table]\n" -++" [--rebuild=] [--blocksize=]\n" -++" [--dir=] [--headersize=] [--eb-split]\n" -++" [--vol-split] [--vol-split!] [--help] [--usage] [--version]\n" -++" image-file\n"; -++ -++#define ERR_MSG(fmt...) \ -++ fprintf(stderr, EXEC ": " fmt) -++ -++#define SPLIT_DATA 1 -++#define SPLIT_RAW 2 -++ -++#define DIR_FMT "unubi_%s" -++#define KIB 1024 -++#define MIB (KIB * KIB) -++#define MAXPATH KIB -++ -++/* filenames */ -++#define FN_INVAL "%s/eb%04u%s" /* invalid eraseblock */ -++#define FN_NSURE "%s/eb%04u_%03u_%03u_%03x%s" /* unsure eraseblock */ -++#define FN_VALID "%s/eb%04u_%03u_%03u_%03x%s" /* valid eraseblock */ -++#define FN_VOLSP "%s/vol%03u_%03u_%03u_%04zu" /* split volume */ -++#define FN_VOLWH "%s/volume%03u" /* whole volume */ -++#define FN_VITBL "%s/vol_info_table%zu" /* vol info table */ -++ -++static uint32_t crc32_table[256]; -++ -++/* struct args: -++ * bsize int, blocksize of image blocks -++ * hsize int, eraseblock header size -++ * analyze flag, when non-zero produce analysis -++ * eb_split flag, when non-zero output eb#### -++ * note: SPLIT_DATA vs. SPLIT_RAW -++ * vol_split flag, when non-zero output vol###_#### -++ * note: SPLIT_DATA vs. SPLIT_RAW -++ * odir_path string, directory to place volumes in -++ * img_path string, file to read as ubi image -++ * vols int array of size UBI_MAX_VOLUMES, where a 1 can be -++ * written for each --rebuild flag in the index specified -++ * then the array can be counted and collapsed using -++ * count_set() and collapse() -++ */ -++struct args { -++ int analyze; -++ int itable; -++ uint32_t *vols; -++ -++ size_t vid_hdr_offset; -++ size_t data_offset; -++ size_t bsize; /* FIXME replace by vid_hdr/data offs? */ -++ size_t hsize; -++ -++ char *odir_path; -++ int eb_split; -++ int vol_split; -++ char *img_path; -++ -++ char **options; -++}; -++ -++struct option long_options[] = { -++ { .name = "rebuild", .has_arg = 1, .flag = NULL, .val = 'r' }, -++ { .name = "dir", .has_arg = 1, .flag = NULL, .val = 'd' }, -++ { .name = "analyze", .has_arg = 0, .flag = NULL, .val = 'a' }, -++ { .name = "blocksize", .has_arg = 1, .flag = NULL, .val = 'b' }, -++ { .name = "eb-split", .has_arg = 0, .flag = NULL, .val = 'e' }, -++ { .name = "vol-split", .has_arg = 0, .flag = NULL, .val = 'v' }, -++ { .name = "vol-split!", .has_arg = 0, .flag = NULL, .val = 'e' }, -++ { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, -++ { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, -++ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'J' }, -++ { NULL, 0, NULL, 0} -++}; -++ -++/** -++ * parses out a numerical value from a string of numbers followed by: -++ * k, K, kib, KiB for kibibyte -++ * m, M, mib, MiB for mebibyte -++ **/ -++static uint32_t -++str_to_num(char *str) -++{ -++ char *s; -++ ulong num; -++ -++ s = str; -++ num = strtoul(s, &s, 0); -++ -++ if (*s != '\0') { -++ if ((strcmp(s, "KiB") == 0) || (strcmp(s, "K") == 0) || -++ (strcmp(s, "kib") == 0) || (strcmp(s, "k") == 0)) -++ num *= KIB; -++ else if ((strcmp(s, "MiB") == 0) || (strcmp(s, "M") == 0) || -++ (strcmp(s, "mib") == 0) || (strcmp(s, "m") == 0)) -++ num *= MIB; -++ else -++ ERR_MSG("couldn't parse '%s', assuming %lu\n", -++ s, num); -++ } -++ return num; -++} -++ -++static int -++parse_opt(int argc, char **argv, struct args *args) -++{ -++ uint32_t i; -++ -++ while (1) { -++ int key; -++ -++ key = getopt_long(argc, argv, "ab:s:d:Deir:vV?J", -++ long_options, NULL); -++ if (key == -1) -++ break; -++ -++ switch (key) { -++ case 'a': /* --analyze */ -++ args->analyze = 1; -++ break; -++ case 'b': /* --block-size= */ -++ args->bsize = str_to_num(optarg); -++ break; -++ case 's': /* --header-size= */ -++ args->hsize = str_to_num(optarg); -++ break; -++ case 'd': /* --dir= */ -++ args->odir_path = optarg; -++ break; -++ case 'D': /* --debug */ -++ /* I wanted to use -v but that was already -++ used ... */ -++ debug = 1; -++ break; -++ case 'e': /* --eb-split */ -++ args->eb_split = SPLIT_RAW; -++ break; -++ case 'i': /* --info-table */ -++ args->itable = 1; -++ break; -++ case 'r': /* --rebuild= */ -++ i = str_to_num(optarg); -++ if (i < UBI_MAX_VOLUMES) -++ args->vols[str_to_num(optarg)] = 1; -++ else { -++ ERR_MSG("volume-id out of bounds\n"); -++ return -1; -++ } -++ break; -++ case 'v': /* --vol-split */ -++ if (args->vol_split != SPLIT_RAW) -++ args->vol_split = SPLIT_DATA; -++ break; -++ case 'V': /* --vol-split! */ -++ args->vol_split = SPLIT_RAW; -++ break; -++ case '?': /* help */ -++ fprintf(stderr, "Usage: unubi [OPTION...] " -++ "image-file\n%s%s\nReport bugs to %s\n", -++ doc, optionsstr, CONTACT); -++ exit(0); -++ break; -++ case 'J': -++ fprintf(stderr, "%s\n", VERSION); -++ exit(0); -++ break; -++ default: -++ fprintf(stderr, "%s", usage); -++ exit(-1); -++ } -++ } -++ -++ /* FIXME I suppose hsize should be replaced! */ -++ args->vid_hdr_offset = args->hsize - UBI_VID_HDR_SIZE; -++ args->data_offset = args->hsize; -++ -++ if (optind < argc) -++ args->img_path = argv[optind++]; -++ return 0; -++} -++ -++ -++/** -++ * counts the number of indicies which are flagged in full_array; -++ * full_array is an array of flags (1/0); -++ **/ -++static size_t -++count_set(uint32_t *full_array, size_t full_len) -++{ -++ size_t count, i; -++ -++ if (full_array == NULL) -++ return 0; -++ -++ for (i = 0, count = 0; i < full_len; i++) -++ if (full_array[i] != 0) -++ count++; -++ -++ return count; -++} -++ -++ -++/** -++ * generates coll_array from full_array; -++ * full_array is an array of flags (1/0); -++ * coll_array is an array of the indicies in full_array which are flagged (1); -++ **/ -++static size_t -++collapse(uint32_t *full_array, size_t full_len, -++ uint32_t *coll_array, size_t coll_len) -++{ -++ size_t i, j; -++ -++ if ((full_array == NULL) || (coll_array == NULL)) -++ return 0; -++ -++ for (i = 0, j = 0; (i < full_len) && (j < coll_len); i++) -++ if (full_array[i] != 0) { -++ coll_array[j] = i; -++ j++; -++ } -++ -++ return j; -++} -++ -++/** -++ * data_crc: save the FILE* position, calculate the crc over a span, -++ * reset the position -++ * returns non-zero when EOF encountered -++ **/ -++static int -++data_crc(FILE* fpin, size_t length, uint32_t *ret_crc) -++{ -++ int rc; -++ size_t i; -++ char buf[length]; -++ uint32_t crc; -++ fpos_t start; -++ -++ rc = fgetpos(fpin, &start); -++ if (rc < 0) -++ return -1; -++ -++ for (i = 0; i < length; i++) { -++ int c = fgetc(fpin); -++ if (c == EOF) { -++ ERR_MSG("unexpected EOF\n"); -++ return -1; -++ } -++ buf[i] = (char)c; -++ } -++ -++ rc = fsetpos(fpin, &start); -++ if (rc < 0) -++ return -1; -++ -++ crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, length); -++ *ret_crc = crc; -++ return 0; -++} -++ -++ -++/** -++ * reads data of size len from fpin and writes it to path -++ **/ -++static int -++extract_data(FILE* fpin, size_t len, const char *path) -++{ -++ int rc; -++ size_t i; -++ FILE* fpout; -++ -++ rc = 0; -++ fpout = NULL; -++ -++ fpout = fopen(path, "wb"); -++ if (fpout == NULL) { -++ ERR_MSG("couldn't open file for writing: %s\n", path); -++ rc = -1; -++ goto err; -++ } -++ -++ for (i = 0; i < len; i++) { -++ int c = fgetc(fpin); -++ if (c == EOF) { -++ ERR_MSG("unexpected EOF while writing: %s\n", path); -++ rc = -2; -++ goto err; -++ } -++ c = fputc(c, fpout); -++ if (c == EOF) { -++ ERR_MSG("couldn't write: %s\n", path); -++ rc = -3; -++ goto err; -++ } -++ } -++ -++ err: -++ if (fpout != NULL) -++ fclose(fpout); -++ return rc; -++} -++ -++ -++/** -++ * extract volume information table from block. saves and reloads fpin -++ * position -++ * returns -1 when a fpos set or get fails, otherwise <= -2 on other -++ * failure and 0 on success -++ **/ -++static int -++extract_itable(FILE *fpin, struct eb_info *cur, size_t bsize, size_t num, -++ const char *path) -++{ -++ char filename[MAXPATH + 1]; -++ int rc; -++ size_t i, max; -++ fpos_t temp; -++ FILE* fpout = NULL; -++ struct ubi_vtbl_record rec; -++ -++ if (fpin == NULL || cur == NULL || path == NULL) -++ return -2; -++ -++ /* remember position */ -++ rc = fgetpos(fpin, &temp); -++ if (rc < 0) -++ return -1; -++ -++ /* jump to top of eraseblock, skip to data section */ -++ fsetpos(fpin, &cur->eb_top); -++ if (rc < 0) -++ return -1; -++ fseek(fpin, be32_to_cpu(cur->ec.data_offset), SEEK_CUR); -++ -++ /* prepare output file */ -++ if (be32_to_cpu(cur->vid.vol_id) != UBI_LAYOUT_VOLUME_ID) -++ return -2; -++ memset(filename, 0, MAXPATH + 1); -++ snprintf(filename, MAXPATH, FN_VITBL, path, num); -++ fpout = fopen(filename, "w"); -++ if (fpout == NULL) -++ return -2; -++ -++ /* loop through entries */ -++ fprintf(fpout, -++ "index\trpebs\talign\ttype\tcrc\t\tname\n"); -++ max = bsize - be32_to_cpu(cur->ec.data_offset); -++ for (i = 0; i < (max / sizeof(rec)); i++) { -++ int blank = 1; -++ char *ptr, *base; -++ char name[UBI_VOL_NAME_MAX + 1]; -++ const char *type = "unknown\0"; -++ uint32_t crc; -++ -++ /* read record */ -++ rc = fread(&rec, 1, sizeof(rec), fpin); -++ if (rc == 0) -++ break; -++ if (rc != sizeof(rec)) { -++ ERR_MSG("reading volume information " -++ "table record failed\n"); -++ rc = -3; -++ goto exit; -++ } -++ -++ /* check crc */ -++ crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &rec, -++ UBI_VTBL_RECORD_SIZE_CRC); -++ if (crc != be32_to_cpu(rec.crc)) -++ continue; -++ -++ /* check for empty */ -++ base = (char *)&rec; -++ ptr = base; -++ while (blank && -++ ((unsigned)(ptr - base) < UBI_VTBL_RECORD_SIZE_CRC)) { -++ if (*ptr != 0) -++ blank = 0; -++ ptr++; -++ } -++ -++ if (blank) -++ continue; -++ -++ /* prep type string */ -++ if (rec.vol_type == UBI_VID_DYNAMIC) -++ type = "dynamic\0"; -++ else if (rec.vol_type == UBI_VID_STATIC) -++ type = "static\0"; -++ -++ /* prep name string */ -++ rec.name[be16_to_cpu(rec.name_len)] = '\0'; -++ sprintf(name, "%s", rec.name); -++ -++ /* print record line to fpout */ -++ fprintf(fpout, "%zu\t%u\t%u\t%s\t0x%08x\t%s\n", -++ i, -++ be32_to_cpu(rec.reserved_pebs), -++ be32_to_cpu(rec.alignment), -++ type, -++ be32_to_cpu(rec.crc), -++ name); -++ } -++ -++ exit: -++ /* reset position */ -++ if (fsetpos(fpin, &temp) < 0) -++ rc = -1; -++ -++ if (fpout != NULL) -++ fclose(fpout); -++ -++ return rc; -++} -++ -++ -++/** -++ * using eb chain, tries to rebuild the data of volume at vol_id, or for all -++ * the known volumes, if vol_id is NULL; -++ **/ -++static int -++rebuild_volume(FILE * fpin, uint32_t *vol_id, struct eb_info **head, -++ const char *path, size_t block_size, size_t header_size) -++{ -++ char filename[MAXPATH]; -++ int rc; -++ uint32_t vol, num, data_size; -++ FILE* fpout; -++ struct eb_info *cur; -++ -++ rc = 0; -++ -++ if ((fpin == NULL) || (head == NULL) || (*head == NULL)) -++ return 0; -++ -++ /* when vol_id is null, then do all */ -++ if (vol_id == NULL) { -++ cur = *head; -++ vol = be32_to_cpu(cur->vid.vol_id); -++ } else { -++ vol = *vol_id; -++ eb_chain_position(head, vol, NULL, &cur); -++ if (cur == NULL) { -++ if (debug) -++ ERR_MSG("no valid volume %d was found\n", vol); -++ return -1; -++ } -++ } -++ -++ num = 0; -++ snprintf(filename, MAXPATH, FN_VOLWH, path, vol); -++ fpout = fopen(filename, "wb"); -++ if (fpout == NULL) { -++ ERR_MSG("couldn't open file for writing: %s\n", filename); -++ return -1; -++ } -++ -++ while (cur != NULL) { -++ size_t i; -++ -++ if (be32_to_cpu(cur->vid.vol_id) != vol) { -++ /* close out file */ -++ fclose(fpout); -++ -++ /* only stay around if that was the only volume */ -++ if (vol_id != NULL) -++ goto out; -++ -++ /* begin with next */ -++ vol = be32_to_cpu(cur->vid.vol_id); -++ num = 0; -++ snprintf(filename, MAXPATH, FN_VOLWH, path, vol); -++ fpout = fopen(filename, "wb"); -++ if (fpout == NULL) { -++ ERR_MSG("couldn't open file for writing: %s\n", -++ filename); -++ return -1; -++ } -++ } -++ -++ while (num < be32_to_cpu(cur->vid.lnum)) { -++ /* FIXME haver: I hope an empty block is -++ written out so that the binary has no holes -++ ... */ -++ if (debug) -++ ERR_MSG("missing valid block %d for volume %d\n", -++ num, vol); -++ num++; -++ } -++ -++ rc = fsetpos(fpin, &(cur->eb_top)); -++ if (rc < 0) -++ goto out; -++ fseek(fpin, be32_to_cpu(cur->ec.data_offset), SEEK_CUR); -++ -++ if (cur->vid.vol_type == UBI_VID_DYNAMIC) -++ /* FIXME It might be that alignment has influence */ -++ data_size = block_size - header_size; -++ else -++ data_size = be32_to_cpu(cur->vid.data_size); -++ -++ for (i = 0; i < data_size; i++) { -++ int c = fgetc(fpin); -++ if (c == EOF) { -++ ERR_MSG("unexpected EOF while writing: %s\n", -++ filename); -++ rc = -2; -++ goto out; -++ } -++ c = fputc(c, fpout); -++ if (c == EOF) { -++ ERR_MSG("couldn't write: %s\n", filename); -++ rc = -3; -++ goto out; -++ } -++ } -++ -++ cur = cur->next; -++ num++; -++ } -++ -++ out: -++ if (vol_id == NULL) -++ fclose(fpout); -++ return rc; -++} -++ -++ -++/** -++ * traverses FILE* trying to load complete, valid and accurate header data -++ * into the eb chain; -++ **/ -++static int -++unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a) -++{ -++ char filename[MAXPATH + 1]; -++ char reason[MAXPATH + 1]; -++ int rc; -++ size_t i, count, itable_num; -++ /* relations: -++ * cur ~ head -++ * next ~ first */ -++ struct eb_info *head, *cur, *first, *next; -++ struct eb_info **next_ptr; -++ -++ rc = 0; -++ count = 0; -++ itable_num = 0; -++ head = NULL; -++ first = NULL; -++ next = NULL; -++ cur = malloc(sizeof(*cur)); -++ if (cur == NULL) { -++ ERR_MSG("out of memory\n"); -++ rc = -ENOMEM; -++ goto err; -++ } -++ memset(cur, 0, sizeof(*cur)); -++ -++ fgetpos(fpin, &(cur->eb_top)); -++ while (1) { -++ const char *raw_path; -++ uint32_t crc; -++ -++ cur->phys_addr = ftell(fpin); -++ cur->phys_block = cur->phys_addr / a->bsize; -++ cur->data_crc_ok = 0; -++ cur->ec_crc_ok = 0; -++ cur->vid_crc_ok = 0; -++ -++ memset(filename, 0, MAXPATH + 1); -++ memset(reason, 0, MAXPATH + 1); -++ -++ /* in case of an incomplete ec header */ -++ raw_path = FN_INVAL; -++ -++ /* read erasecounter header */ -++ rc = fread(&cur->ec, 1, sizeof(cur->ec), fpin); -++ if (rc == 0) -++ goto out; /* EOF */ -++ if (rc != sizeof(cur->ec)) { -++ ERR_MSG("reading ec-hdr failed\n"); -++ rc = -1; -++ goto err; -++ } -++ -++ /* check erasecounter header magic */ -++ if (be32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC) { -++ snprintf(reason, MAXPATH, ".invalid.ec_magic"); -++ goto invalid; -++ } -++ -++ /* check erasecounter header crc */ -++ crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &(cur->ec), -++ UBI_EC_HDR_SIZE_CRC); -++ if (be32_to_cpu(cur->ec.hdr_crc) != crc) { -++ snprintf(reason, MAXPATH, ".invalid.ec_hdr_crc"); -++ goto invalid; -++ } -++ -++ /* read volume id header */ -++ rc = fsetpos(fpin, &(cur->eb_top)); -++ if (rc != 0) -++ goto err; -++ fseek(fpin, be32_to_cpu(cur->ec.vid_hdr_offset), SEEK_CUR); -++ rc = fread(&cur->vid, 1, sizeof(cur->vid), fpin); -++ if (rc == 0) -++ goto out; /* EOF */ -++ if (rc != sizeof(cur->vid)) { -++ ERR_MSG("reading vid-hdr failed\n"); -++ rc = -1; -++ goto err; -++ } -++ -++ /* if the magic number is 0xFFFFFFFF, then it's very likely -++ * that the volume is empty */ -++ if (be32_to_cpu(cur->vid.magic) == 0xffffffff) { -++ snprintf(reason, MAXPATH, ".empty"); -++ goto invalid; -++ } -++ -++ /* vol_id should be in bounds */ -++ if ((be32_to_cpu(cur->vid.vol_id) >= UBI_MAX_VOLUMES) && -++ (be32_to_cpu(cur->vid.vol_id) < -++ UBI_INTERNAL_VOL_START)) { -++ snprintf(reason, MAXPATH, ".invalid"); -++ goto invalid; -++ } else -++ raw_path = FN_NSURE; -++ -++ /* check volume id header magic */ -++ if (be32_to_cpu(cur->vid.magic) != UBI_VID_HDR_MAGIC) { -++ snprintf(reason, MAXPATH, ".invalid.vid_magic"); -++ goto invalid; -++ } -++ cur->ec_crc_ok = 1; -++ -++ /* check volume id header crc */ -++ crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &(cur->vid), -++ UBI_VID_HDR_SIZE_CRC); -++ if (be32_to_cpu(cur->vid.hdr_crc) != crc) { -++ snprintf(reason, MAXPATH, ".invalid.vid_hdr_crc"); -++ goto invalid; -++ } -++ cur->vid_crc_ok = 1; -++ -++ /* check data crc, but only for a static volume */ -++ if (cur->vid.vol_type == UBI_VID_STATIC) { -++ rc = data_crc(fpin, be32_to_cpu(cur->vid.data_size), -++ &crc); -++ if (rc < 0) -++ goto err; -++ if (be32_to_cpu(cur->vid.data_crc) != crc) { -++ snprintf(reason, MAXPATH, ".invalid.data_crc"); -++ goto invalid; -++ } -++ cur->data_crc_ok = 1; -++ } -++ -++ /* enlist this vol, it's valid */ -++ raw_path = FN_VALID; -++ cur->linear = count; -++ rc = eb_chain_insert(&head, cur); -++ if (rc < 0) { -++ if (rc == -ENOMEM) { -++ ERR_MSG("out of memory\n"); -++ goto err; -++ } -++ ERR_MSG("unknown and unexpected error, please contact " -++ CONTACT "\n"); -++ goto err; -++ } -++ -++ /* extract info-table */ -++ if (a->itable && -++ (be32_to_cpu(cur->vid.vol_id) == UBI_LAYOUT_VOLUME_ID)) { -++ extract_itable(fpin, cur, a->bsize, -++ itable_num, a->odir_path); -++ itable_num++; -++ } -++ -++ /* split volumes */ -++ if (a->vol_split) { -++ size_t size = 0; -++ -++ rc = fsetpos(fpin, &(cur->eb_top)); -++ if (rc != 0) -++ goto err; -++ -++ /* -++ * FIXME For dynamic UBI volumes we must write -++ * the maximum available data. The -++ * vid.data_size field is not used in this -++ * case. The dynamic volume user is -++ * responsible for the content. -++ */ -++ if (a->vol_split == SPLIT_DATA) { -++ /* Write only data section */ -++ if (cur->vid.vol_type == UBI_VID_DYNAMIC) { -++ /* FIXME Formular is not -++ always right ... */ -++ size = a->bsize - a->hsize; -++ } else -++ size = be32_to_cpu(cur->vid.data_size); -++ -++ fseek(fpin, -++ be32_to_cpu(cur->ec.data_offset), -++ SEEK_CUR); -++ } -++ else if (a->vol_split == SPLIT_RAW) -++ /* write entire eraseblock */ -++ size = a->bsize; -++ -++ snprintf(filename, MAXPATH, FN_VOLSP, -++ a->odir_path, -++ be32_to_cpu(cur->vid.vol_id), -++ be32_to_cpu(cur->vid.lnum), -++ be32_to_cpu(cur->vid.leb_ver), count); -++ rc = extract_data(fpin, size, filename); -++ if (rc < 0) -++ goto err; -++ } -++ -++ invalid: -++ /* split eraseblocks */ -++ if (a->eb_split) { -++ /* jump to top of block */ -++ rc = fsetpos(fpin, &(cur->eb_top)); -++ if (rc != 0) -++ goto err; -++ -++ if (strcmp(raw_path, FN_INVAL) == 0) -++ snprintf(filename, MAXPATH, raw_path, -++ a->odir_path, count, reason); -++ else -++ snprintf(filename, MAXPATH, raw_path, -++ a->odir_path, -++ count, -++ be32_to_cpu(cur->vid.vol_id), -++ be32_to_cpu(cur->vid.lnum), -++ be32_to_cpu(cur->vid.leb_ver), -++ reason); -++ -++ rc = extract_data(fpin, a->bsize, filename); -++ if (rc < 0) -++ goto err; -++ } -++ -++ /* append to simple linked list */ -++ if (first == NULL) -++ next_ptr = &first; -++ else -++ next_ptr = &next->next; -++ -++ *next_ptr = malloc(sizeof(**next_ptr)); -++ if (*next_ptr == NULL) { -++ ERR_MSG("out of memory\n"); -++ rc = -ENOMEM; -++ goto err; -++ } -++ memset(*next_ptr, 0, sizeof(**next_ptr)); -++ -++ next = *next_ptr; -++ memcpy(next, cur, sizeof(*next)); -++ next->next = NULL; -++ -++ count++; -++ rc = fsetpos(fpin, &(cur->eb_top)); -++ if (rc != 0) -++ goto err; -++ fseek(fpin, a->bsize, SEEK_CUR); -++ memset(cur, 0, sizeof(*cur)); -++ -++ fgetpos(fpin, &(cur->eb_top)); -++ } -++ -++ out: -++ for (i = 0; i < vc; i++) { -++ rc = rebuild_volume(fpin, &vols[i], &head, a->odir_path, -++ a->bsize, a->hsize); -++ if (rc < 0) -++ goto err; -++ } -++ -++ /* if there were no volumes specified, rebuild them all, -++ * UNLESS eb_ or vol_ split or analyze was specified */ -++ if ((vc == 0) && (!a->eb_split) && (!a->vol_split) && -++ (!a->analyze) && (!a->itable)) { -++ rc = rebuild_volume(fpin, NULL, &head, a->odir_path, a->bsize, -++ a->hsize); -++ if (rc < 0) -++ goto err; -++ } -++ -++ err: -++ free(cur); -++ -++ if (a->analyze) { -++ char fname[PATH_MAX]; -++ FILE *fp; -++ -++ unubi_analyze(&head, first, a->odir_path); -++ -++ /* prepare output files */ -++ memset(fname, 0, PATH_MAX + 1); -++ snprintf(fname, PATH_MAX, "%s/%s", a->odir_path, FN_EH_STAT); -++ fp = fopen(fname, "w"); -++ if (fp != NULL) { -++ eb_chain_print(fp, head); -++ fclose(fp); -++ } -++ } -++ eb_chain_destroy(&head); -++ eb_chain_destroy(&first); -++ -++ return rc; -++} -++ -++ -++/** -++ * handles command line arguments, then calls unubi_volumes -++ **/ -++int -++main(int argc, char *argv[]) -++{ -++ int rc, free_a_odir; -++ size_t vols_len; -++ uint32_t *vols; -++ FILE* fpin; -++ struct args a; -++ -++ rc = 0; -++ free_a_odir = 0; -++ vols_len = 0; -++ vols = NULL; -++ fpin = NULL; -++ init_crc32_table(crc32_table); -++ -++ /* setup struct args a */ -++ memset(&a, 0, sizeof(a)); -++ a.bsize = 128 * KIB; -++ a.hsize = 2 * KIB; -++ a.vols = malloc(sizeof(*a.vols) * UBI_MAX_VOLUMES); -++ if (a.vols == NULL) { -++ ERR_MSG("out of memory\n"); -++ rc = ENOMEM; -++ goto err; -++ } -++ memset(a.vols, 0, sizeof(*a.vols) * UBI_MAX_VOLUMES); -++ -++ /* parse args and check for validity */ -++ parse_opt(argc, argv, &a); -++ if (a.img_path == NULL) { -++ ERR_MSG("no image file specified\n"); -++ rc = EINVAL; -++ goto err; -++ } -++ else if (a.odir_path == NULL) { -++ char *ptr; -++ int len; -++ -++ ptr = strrchr(a.img_path, '/'); -++ if (ptr == NULL) -++ ptr = a.img_path; -++ else -++ ptr++; -++ -++ len = strlen(DIR_FMT) + strlen(ptr); -++ free_a_odir = 1; -++ a.odir_path = malloc(sizeof(*a.odir_path) * len); -++ if (a.odir_path == NULL) { -++ ERR_MSG("out of memory\n"); -++ rc = ENOMEM; -++ goto err; -++ } -++ snprintf(a.odir_path, len, DIR_FMT, ptr); -++ } -++ -++ fpin = fopen(a.img_path, "rb"); -++ if (fpin == NULL) { -++ ERR_MSG("couldn't open file for reading: " -++ "%s\n", a.img_path); -++ rc = EINVAL; -++ goto err; -++ } -++ -++ rc = mkdir(a.odir_path, 0777); -++ if ((rc < 0) && (errno != EEXIST)) { -++ ERR_MSG("couldn't create ouput directory: " -++ "%s\n", a.odir_path); -++ rc = -rc; -++ goto err; -++ } -++ -++ /* fill in vols array */ -++ vols_len = count_set(a.vols, UBI_MAX_VOLUMES); -++ if (vols_len > 0) { -++ vols = malloc(sizeof(*vols) * vols_len); -++ if (vols == NULL) { -++ ERR_MSG("out of memory\n"); -++ rc = ENOMEM; -++ goto err; -++ } -++ collapse(a.vols, UBI_MAX_VOLUMES, vols, vols_len); -++ } -++ -++ /* unubi volumes */ -++ rc = unubi_volumes(fpin, vols, vols_len, &a); -++ if (rc < 0) { -++ /* ERR_MSG("error encountered while working on image file: " -++ "%s\n", a.img_path); */ -++ rc = -rc; -++ goto err; -++ } -++ -++ err: -++ free(a.vols); -++ if (free_a_odir != 0) -++ free(a.odir_path); -++ if (fpin != NULL) -++ fclose(fpin); -++ if (vols_len > 0) -++ free(vols); -++ return rc; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/unubi_analyze.c linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/unubi_analyze.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/unubi_analyze.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/unubi_analyze.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,463 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006, 2007 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * Authors: Drake Dowsett, dowsett@de.ibm.com -++ * Contact: Andreas Arnez, arnez@de.ibm.com -++ * -++ * unubi uses the following functions to generate analysis output based on -++ * the header information in a raw-UBI image -++ */ -++ -++/* -++ * TODO: use OOB data to check for eraseblock validity in NAND images -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "unubi_analyze.h" -++#include "crc32.h" -++ -++#define EC_X_INT 50 -++ -++/** -++ * intcmp - function needed by qsort to order integers -++ **/ -++int intcmp(const void *a, const void *b) -++{ -++ int A = *(int *)a; -++ int B = *(int *)b; -++ return A - B; -++} -++ -++int longcmp(const void *a, const void *b) -++{ -++ long long A = *(long long *)a; -++ long long B = *(long long *)b; -++ return A - B; -++} -++ -++ -++/** -++ * unubi_analyze_group_index - finds the normalized index in an array -++ * item: look for this item in the array -++ * array: array to search through -++ * size: length of the array -++ * array should be sorted for this algorithm to perform properly; -++ * if the item is not found returns -1, otherwise return value is the -++ * index in the array (note this contricts the array size to 2^32-1); -++ **/ -++int -++norm_index(uint32_t item, uint32_t *array, size_t length) -++{ -++ size_t i, index; -++ -++ for (index = 0, i = 0; i < length; i++) { -++ if ((i != 0) && (array[i] != array[i - 1])) -++ index++; -++ -++ if (item == array[i]) -++ return index; -++ } -++ -++ return -1; -++} -++ -++ -++/** -++ * unubi_analyze_ec_hdr - generate data table and plot script -++ * first: head of simple linked list -++ * path: folder to write into -++ * generates a data file containing the eraseblock index in the image -++ * and the erase counter found in its ec header; -++ * if the crc check fails, the line is commented out in the data file; -++ * also generates a simple gnuplot sript for quickly viewing one -++ * display of the data file; -++ **/ -++int -++unubi_analyze_ec_hdr(struct eb_info *first, const char *path) -++{ -++ char filename[PATH_MAX + 1]; -++ size_t count, eraseblocks; -++ uint32_t crc, crc32_table[256]; -++ uint64_t *erase_counts; -++ FILE* fpdata; -++ FILE* fpplot; -++ struct eb_info *cur; -++ -++ if (first == NULL) -++ return -1; -++ -++ /* crc check still needed for `first' linked list */ -++ init_crc32_table(crc32_table); -++ -++ /* prepare output files */ -++ memset(filename, 0, PATH_MAX + 1); -++ snprintf(filename, PATH_MAX, "%s/%s", path, FN_EH_DATA); -++ fpdata = fopen(filename, "w"); -++ if (fpdata == NULL) -++ return -1; -++ -++ memset(filename, 0, PATH_MAX + 1); -++ snprintf(filename, PATH_MAX, "%s/%s", path, FN_EH_PLOT); -++ fpplot = fopen(filename, "w"); -++ if (fpplot == NULL) { -++ fclose(fpdata); -++ return -1; -++ } -++ -++ /* make executable */ -++ chmod(filename, 0755); -++ -++ /* first run: count elements */ -++ count = 0; -++ cur = first; -++ while (cur != NULL) { -++ cur = cur->next; -++ count++; -++ } -++ eraseblocks = count; -++ -++ erase_counts = malloc(eraseblocks * sizeof(*erase_counts)); -++ if (!erase_counts) { -++ perror("out of memory"); -++ exit(EXIT_FAILURE); -++ } -++ -++ memset(erase_counts, 0, eraseblocks * sizeof(*erase_counts)); -++ -++ /* second run: populate array to sort */ -++ count = 0; -++ cur = first; -++ while (cur != NULL) { -++ erase_counts[count] = be64_to_cpu(cur->ec.ec); -++ cur = cur->next; -++ count++; -++ } -++ qsort(erase_counts, eraseblocks, sizeof(*erase_counts), -++ (void *)longcmp); -++ -++ /* third run: generate data file */ -++ count = 0; -++ cur = first; -++ fprintf(fpdata, "# eraseblock_no actual_erase_count " -++ "sorted_erase_count\n"); -++ while (cur != NULL) { -++ crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &cur->ec, -++ UBI_EC_HDR_SIZE_CRC); -++ -++ if ((be32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC) || -++ (crc != be32_to_cpu(cur->ec.hdr_crc))) -++ fprintf(fpdata, "# "); -++ -++ fprintf(fpdata, "%zu %llu %llu", count, -++ (unsigned long long)be64_to_cpu(cur->ec.ec), -++ (unsigned long long)erase_counts[count]); -++ -++ if (be32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC) -++ fprintf(fpdata, " ## bad magic: %08x", -++ be32_to_cpu(cur->ec.magic)); -++ -++ if (crc != be32_to_cpu(cur->ec.hdr_crc)) -++ fprintf(fpdata, " ## CRC mismatch: given=%08x, " -++ "calc=%08x", be32_to_cpu(cur->ec.hdr_crc), -++ crc); -++ -++ fprintf(fpdata, "\n"); -++ -++ cur = cur->next; -++ count++; -++ } -++ fclose(fpdata); -++ -++ fprintf(fpplot, "#!/usr/bin/gnuplot -persist\n"); -++ fprintf(fpplot, "set xlabel \"eraseblock\"\n"); -++ -++ /* fourth run: generate plot file xtics */ -++ count = 0; -++ cur = first; -++ fprintf(fpplot, "set xtics ("); -++ while (cur != NULL) { -++ if ((count % EC_X_INT) == 0) { -++ if (count > 0) -++ fprintf(fpplot, ", "); -++ fprintf(fpplot, "%zd", count); -++ } -++ -++ cur = cur->next; -++ count++; -++ } -++ fprintf(fpplot, ")\n"); -++ -++ fprintf(fpplot, "set ylabel \"erase count\"\n"); -++ fprintf(fpplot, "set xrange [-1:%zu]\n", eraseblocks + 1); -++ fprintf(fpplot, "# set yrange [-1:%llu]\n", -++ (unsigned long long)erase_counts[eraseblocks - 1] + 1); -++ fprintf(fpplot, "plot \"%s\" u 1:2 t \"unsorted: %s\" with boxes\n", -++ FN_EH_DATA, FN_EH_DATA); -++ fprintf(fpplot, "# replot \"%s\" u 1:3 t \"sorted: %s\" with lines\n", -++ FN_EH_DATA, FN_EH_DATA); -++ fprintf(fpplot, "pause -1 \"press ENTER\"\n"); -++ -++ fclose(fpplot); -++ -++ return 0; -++} -++ -++ -++/** -++ * unubi_analyze_vid_hdr - generate data table and plot script -++ * head: head of complex linked list (eb_chain) -++ * path: folder to write into -++ * generates a data file containing the volume id, logical number, leb version, -++ * and data size from the vid header; -++ * all eraseblocks listed in the eb_chain are valid (checked in unubi); -++ * also generates a simple gnuplot sript for quickly viewing one -++ * display of the data file; -++ **/ -++int -++unubi_analyze_vid_hdr(struct eb_info **head, const char *path) -++{ -++ char filename[PATH_MAX + 1]; -++ int rc, y1, y2; -++ size_t count, step, breadth; -++ uint32_t *leb_versions, *data_sizes; -++ FILE* fpdata; -++ FILE* fpplot; -++ struct eb_info *cur; -++ -++ if (head == NULL || *head == NULL) -++ return -1; -++ -++ rc = 0; -++ fpdata = NULL; -++ fpplot = NULL; -++ data_sizes = NULL; -++ leb_versions = NULL; -++ -++ /* prepare output files */ -++ memset(filename, 0, PATH_MAX + 1); -++ snprintf(filename, PATH_MAX, "%s/%s", path, FN_VH_DATA); -++ fpdata = fopen(filename, "w"); -++ if (fpdata == NULL) { -++ rc = -1; -++ goto exit; -++ } -++ -++ memset(filename, 0, PATH_MAX + 1); -++ snprintf(filename, PATH_MAX, "%s/%s", path, FN_VH_PLOT); -++ fpplot = fopen(filename, "w"); -++ if (fpplot == NULL) { -++ rc = -1; -++ goto exit; -++ } -++ -++ /* make executable */ -++ chmod(filename, 0755); -++ -++ /* first run: count elements */ -++ count = 0; -++ cur = *head; -++ while (cur != NULL) { -++ cur = cur->next; -++ count++; -++ } -++ breadth = count; -++ -++ leb_versions = malloc(breadth * sizeof(uint32_t)); -++ if (leb_versions == NULL) { -++ rc = -1; -++ goto exit; -++ } -++ memset(leb_versions, 0, breadth * sizeof(uint32_t)); -++ -++ data_sizes = malloc(breadth * sizeof(uint32_t)); -++ if (data_sizes == NULL) { -++ rc = -1; -++ goto exit; -++ } -++ memset(data_sizes, 0, breadth * sizeof(*data_sizes)); -++ -++ /* second run: populate arrays to sort */ -++ count = 0; -++ cur = *head; -++ while (cur != NULL) { -++ leb_versions[count] = be32_to_cpu(cur->vid.leb_ver); -++ data_sizes[count] = be32_to_cpu(cur->vid.data_size); -++ cur = cur->next; -++ count++; -++ } -++ qsort(leb_versions, breadth, sizeof(*leb_versions), (void *)intcmp); -++ qsort(data_sizes, breadth, sizeof(*data_sizes), (void *)intcmp); -++ -++ /* third run: generate data file */ -++ count = 0; -++ cur = *head; -++ fprintf(fpdata, "# x_axis vol_id lnum y1_axis leb_ver " -++ "y2_axis data_size\n"); -++ while (cur != NULL) { -++ y1 = norm_index(be32_to_cpu(cur->vid.leb_ver), leb_versions, -++ breadth); -++ y2 = norm_index(be32_to_cpu(cur->vid.data_size), data_sizes, -++ breadth); -++ -++ if ((y1 == -1) || (y2 == -1)) { -++ rc = -1; -++ goto exit; -++ } -++ -++ fprintf(fpdata, "%zu %u %u %u %u %u %u\n", -++ count, -++ be32_to_cpu(cur->vid.vol_id), -++ be32_to_cpu(cur->vid.lnum), -++ y1, -++ be32_to_cpu(cur->vid.leb_ver), -++ y2, -++ be32_to_cpu(cur->vid.data_size)); -++ cur = cur->next; -++ count++; -++ } -++ -++ fprintf(fpplot, "#!/usr/bin/gnuplot -persist\n"); -++ fprintf(fpplot, "set xlabel \"volume\"\n"); -++ -++ /* fourth run: generate plot file xtics */ -++ count = 0; -++ step = 0; -++ cur = *head; -++ fprintf(fpplot, "set xtics ("); -++ while (cur != NULL) { -++ if (count > 0) -++ fprintf(fpplot, ", "); -++ if (step != be32_to_cpu(cur->vid.vol_id)) { -++ step = be32_to_cpu(cur->vid.vol_id); -++ fprintf(fpplot, "\"%zd\" %zd 0", step, count); -++ } -++ else -++ fprintf(fpplot, "\"%d\" %zd 1", -++ be32_to_cpu(cur->vid.lnum), count); -++ cur = cur->next; -++ count++; -++ } -++ fprintf(fpplot, ")\n"); -++ fprintf(fpplot, "set nox2tics\n"); -++ -++ /* fifth run: generate plot file ytics */ -++ count = 0; -++ cur = *head; -++ fprintf(fpplot, "set ylabel \"leb version\"\n"); -++ fprintf(fpplot, "set ytics ("); -++ while (cur->next != NULL) { -++ y1 = norm_index(be32_to_cpu(cur->vid.leb_ver), leb_versions, -++ breadth); -++ -++ if (y1 == -1) { -++ rc = -1; -++ goto exit; -++ } -++ -++ if (count > 0) -++ fprintf(fpplot, ", "); -++ -++ fprintf(fpplot, "\"%u\" %u", be32_to_cpu(cur->vid.leb_ver), -++ y1); -++ -++ cur = cur->next; -++ count++; -++ } -++ fprintf(fpplot, ")\n"); -++ -++ /* sixth run: generate plot file y2tics */ -++ count = 0; -++ cur = *head; -++ fprintf(fpplot, "set y2label \"data size\"\n"); -++ fprintf(fpplot, "set y2tics ("); -++ while (cur != NULL) { -++ y2 = norm_index(be32_to_cpu(cur->vid.data_size), -++ data_sizes, breadth); -++ -++ if (y2 == -1) { -++ rc = -1; -++ goto exit; -++ } -++ -++ if (count > 0) -++ fprintf(fpplot, ", "); -++ -++ fprintf(fpplot, "\"%u\" %u", be32_to_cpu(cur->vid.data_size), -++ y2); -++ -++ cur = cur->next; -++ count++; -++ } -++ fprintf(fpplot, ")\n"); -++ -++ y1 = norm_index(leb_versions[breadth - 1], leb_versions, breadth); -++ y2 = norm_index(data_sizes[breadth - 1], data_sizes, breadth); -++ fprintf(fpplot, "set xrange [-1:%zu]\n", count + 1); -++ fprintf(fpplot, "set yrange [-1:%u]\n", y1 + 1); -++ fprintf(fpplot, "set y2range [-1:%u]\n", y2 + 1); -++ fprintf(fpplot, "plot \"%s\" u 1:4 t \"leb version: %s\" " -++ "axes x1y1 with lp\n", FN_VH_DATA, FN_VH_DATA); -++ fprintf(fpplot, "replot \"%s\" u 1:6 t \"data size: %s\" " -++ "axes x1y2 with lp\n", FN_VH_DATA, FN_VH_DATA); -++ fprintf(fpplot, "pause -1 \"press ENTER\"\n"); -++ -++ exit: -++ if (fpdata != NULL) -++ fclose(fpdata); -++ if (fpplot != NULL) -++ fclose(fpplot); -++ if (data_sizes != NULL) -++ free(data_sizes); -++ if (leb_versions != NULL) -++ free(leb_versions); -++ -++ return rc; -++} -++ -++ -++/** -++ * unubi_analyze - run all analyses -++ * head: eb_chain head -++ * first: simple linked list of eraseblock headers (use .next) -++ * path: directory (without trailing slash) to output to -++ * returns 0 upon successful completion, or -1 otherwise -++ **/ -++int -++unubi_analyze(struct eb_info **head, struct eb_info *first, const char *path) -++{ -++ int ec_rc, vid_rc; -++ -++ if (path == NULL) -++ return -1; -++ -++ ec_rc = unubi_analyze_ec_hdr(first, path); -++ vid_rc = unubi_analyze_vid_hdr(head, path); -++ if (ec_rc < 0 || vid_rc < 0) -++ return -1; -++ -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/unubi_analyze.h linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/unubi_analyze.h -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/src/unubi_analyze.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/src/unubi_analyze.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,87 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006, 2007 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++#ifndef __UNUBI_ANALYZE_H__ -++#define __UNUBI_ANALYZE_H__ -++ -++/* -++ * Author: Drake Dowsett -++ * Contact: Andreas Arnez (arnez@de.ibm.com) -++ * -++ * Eraseblock Chain -++ * -++ * A linked list structure to order eraseblocks by volume and logical number -++ * and to update by version number. Doesn't contain actual eraseblock data -++ * but rather the erasecounter and volume id headers as well as a position -++ * indicator. -++ * -++ * Diagram Example: -++ * -++ * [V1.0v0]->[V1.1v2]->[V1.2v1]->[V2.0v2]->[V2.1v0]->[V2.2v1]->NULL -++ * | | | | | | -++ * NULL [V1.1v1] [V1.2v0] [V2.0v1] NULL [V2.2v0] -++ * | | | | -++ * [V1.1v0] NULL [V2.0v0] NULL -++ * | | -++ * NULL NULL -++ * -++ * [VA.BvC] represents the eb_info for the eraseblock with the vol_id A, -++ * lnum B and leb_ver C -++ * -> represents the `next' pointer -++ * | represents the `older' pointer -++ */ -++ -++#include -++#include -++#include -++ -++#define FN_EH_STAT "analysis_blocks.txt" -++#define FN_EH_DATA "analysis_ec_hdr.data" -++#define FN_EH_PLOT "analysis_ec_hdr.plot" -++#define FN_VH_DATA "analysis_vid_hdr.data" -++#define FN_VH_PLOT "analysis_vid_hdr.plot" -++ -++struct eb_info { -++ struct ubi_ec_hdr ec; -++ struct ubi_vid_hdr vid; -++ -++ fpos_t eb_top; -++ uint32_t linear; -++ int ec_crc_ok; -++ int vid_crc_ok; -++ int data_crc_ok; -++ uint32_t phys_addr; -++ int phys_block; -++ -++ struct eb_info *next; -++ struct eb_info *older; -++}; -++ -++int eb_chain_insert(struct eb_info **head, struct eb_info *item); -++ -++int eb_chain_position(struct eb_info **head, uint32_t vol_id, uint32_t *lnum, -++ struct eb_info **pos); -++ -++int eb_chain_print(FILE *stream, struct eb_info *head); -++ -++int eb_chain_destroy(struct eb_info **head); -++ -++int unubi_analyze(struct eb_info **head, struct eb_info *first, -++ const char *path); -++ -++#endif /* __UNUBI_ANALYZE_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/testcases.txt linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/testcases.txt -+--- linux-2.6.24.7.old/drivers/mtd/mtd-utils/ubi-utils/testcases.txt 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtd-utils/ubi-utils/testcases.txt 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,9 @@ -++1. Start some large update, but write there byte-by-byte -++ -++2. start update for N bytes, write N-x bytes, then write y bytes, y>x. -++ You have to see that at the last write only x bytes were written, -++ but y-x bytes were not. we may vary x a bit. good number would be -++ 1, 128, 128Ki-128... -++ -++3. Try to start update for x bytes, write x bytes, then try to write more. -++ Check that it is impossible to write more. -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtd_blkdevs.c linux-2.6.24.7/drivers/mtd/mtd_blkdevs.c -+--- linux-2.6.24.7.old/drivers/mtd/mtd_blkdevs.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/mtd_blkdevs.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -278,7 +278,7 @@ -+ -+ /* 2.5 has capacity in units of 512 bytes while still -+ having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */ -+- set_capacity(gd, (new->size * tr->blksize) >> 9); -++ set_capacity(gd, ((u_int64_t)new->size * tr->blksize) >> 9); -+ -+ gd->private_data = new; -+ new->blkcore_priv = gd; -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtdblock-jz.uu linux-2.6.24.7/drivers/mtd/mtdblock-jz.uu -+--- linux-2.6.24.7.old/drivers/mtd/mtdblock-jz.uu 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtdblock-jz.uu 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,535 @@ -++begin 644 mtdblock-jz.o -++M?T5,1@$!`0````````````$`"``!```````````````T-0```1``4#0````` -++M`"@`(P`@`````````````````#P`@XR`*`4`'`!BC.K_!"0A**(```"CC/]_ -++M`CS__T(T`P!A!"008@```,*L(2````@`X`,A$(````"#C```HHP``(*L"`#@ -++M`P``HZS8_[TG(3B@`"``M*\AH(``)`"(CAP`LZ\AF,``0#`'`,`0!P"`(`<` -++M*AAF`B0`OZ\8`+*O%`"QKQ``L*\@`(F.`0#*)"$02`!$`&`4(2"(````@XP` -++M`$*,`"D#```A`@"`&`,`@!`"`",@@@`C**,`(2")`"$HJ0```(*,``"CC"L0 -++M8@`U`$`0(8C``(`0!P"`(`H`(9`"`8`8$0`J$&H"(2"(``\`0!0A&&@```"" -++MC```8XP`(0(``"D#`(`0`@"`&`,`(R""`",HHP`A((D`(2BI````@HP``*., -++M*Q!B``N(0@$?`"<2@(`1`"&`$`$``$*.```#C@`A`@``*0,`@!`"`(`8`P`C -++M(((`(RBC`"$H)0$A("0!"`"$)`X```P(`*4D(2!``@X```PA*``"(3@@`D`P -++M!P`D`(B.P!`'`(`@!P`J&&8"(`")C@$`RB0A$$@`OO]@$"$@B``V```((8C@ -++M`"0`OX\@`+2/'`"SCQ@`LH\4`+&/$`"PCP@`X`,H`+TGR/^])RP`MZ\T`+^O -++M,`"^KR@`MJ\D`+6O(`"TKQP`LZ\8`+*O%`"QKQ``L*\\`)6,`!$%`"``M(Z` -++M*`4`(Q!%`"$05``(`%*,``"GCB0`OHXJ$$<"*0!`$"&X0`(`$1(`@"@2`",P -++M10`A&(8"#`!DC```8HPK$((`(`!`$`P`TR2=```(([#R`"``HHXA$&("#`!$ -++MC```0XPK&(,`%P!@$`P`/*`"VCR0`M8\@`+2/'`"SCQ@` -++MLH\4`+&/$`"PCP@`X`,X`+TG```#/`@`X`/8`&*,```#/`@`X`/<`&*,Z/^] -++M)Q``L*\4`+^O````#"&`@``A(``"%`"_CQ``L(\````(&`"])^#_O2<0`+"O -++M(8"@`!0`L:\A*```(8B```@`!B08`+^O````#"$@``($``,D$``")`$``J(` -++M``.B(``CCB$0``""&0,``@`#IA@`OX\4`+&/$`"PCP@`X`,@`+TGX/^])QP` -++MOZ\4`+&O&`"RKQ``L*\``(*,(8B``*@`0XP4`%*,4`!DC%0`<(P!``@D(X`$ -++M`@2`"`+__Q`R)``DCD*2$@`(`":N!``EKB$P``(,`">N+``HKO__4C(````, -++M(2@```(P$G(H`"2.'`"_CQ@`LH\4`+&/$`"PCR$H```````((`"])XC_O2=P -++M`+^O;`"WKV@`MJ]D`+6O8`"TKUP`LZ]8`+*O5`"QKU``L*\\`(.,``"3C``` -++M:(RH`'*.`0`")0(`0B@@`&>,5`!&CE``1(X9`$`4)`!CC",0Q``!`!0D!!!4 -++M`/__0C`A,&``__]5)"$@```8`+8G```7/`0`T(P!`(0D@!`0```9$``C&&(` -++M(8CC``0`(I(!`$,P`@!",`,`0!0$`,8D$`!@%`````#R_X@4`````/3_`R1P -++M`+^/;`"WCV@`MH]D`+6/8`"TCUP`LX]8`+*/5`"QCU``L(\A$&``"`#@`W@` -++MO2<``+"L(2#``B$H```````,.``&),P`Y28,``(D(1@```(`!"0P`**O-`"C -++MKT@`I:\8`+2O0`"DKU0`2([#'Q``)S`(`$(X$`!0`$2.!CC'``08`P$@``8Q -++M!!`0`248XP`+&$8`!""5``L0!@`A,$0`PR\$`!``MJ\K0,(`(3AE`$@`8HXA -++M.`O>`"VKW0`M:]P`+2O;`"SKV@`LJ]D`+&O8`"PKP```CP,`)&,)`!"C!P` -++MD(Q7`$`0J``SCAT``A(```(\*`!")(8"``@!``0D&``#$@```````$.,`0"$ -++M)/O_8!0$`$(D```#/```8HP?`$`0```2/```8B0$`$*,#`!`$``````7``(2 -++M```"/`@`0B29`@`(`0`$)!0``Q(``!(\``!#C`$`A"3[_V`4!`!")"$0``"$ -++M`+^/@`"^CWP`MX]X`+:/=`"UCW``M(]L`+./:`"RCV0`L8]@`+"/"`#@`X@` -++MO2.)R`&`$`8"0`$&(,`!B#'`"4@9``@`,@P!BC)``L@J``A$(("```$K@`` -++M0XPC$(,`"``#K@\`0!P$``*N```$/`````P``(0D```%C@@`!HX```0\```` -++M#```A"0```0\````#```A"0```2.__^")`0``JX$``*.#``$KM"`!32`(`(` -++M````#!```JX```2.'``"K@`1!`"`(`0`(R!$``````S0``4D```$CB```JZ` -++M(`0`!`"$)`````S0``4D(1A``!P``HY;_T`0)``#KB```HX5_T`0]/\")!/_ -++M8!`AD```4`"@KR&8```\`+"N```1CB&P0`(J$%$"5`!`$%@`LJ]"*!(`(8@` -++M`%P`I:]4`**/7`"ECU0`1(P8`*,G$`"CKR<8!``&&&4`!#B3`"``A3`E.&<` -++M!#"2`$@`XHX+.,4`(2#@`@GX0``+,`4````"/,P`1"3,`$.,!`""C`8`8A`! -++M`#$F````#``````J$"("Y_]`%%0`HH\@``*.4`"ECP$``R0A$*(`!`!#H``` -++M`CS,`$(D"`!#C/__`B1F`&(04`"DCR```HXA$((```!#K"0``XZ`$!(`(1!# -++M``0`5JQ0`*6/(``#C@$`PB8A&*,`"`!BK%0`HH]<`*6/5`!$C(``XHXG&`0` -++M!AAE``0XDP`@`(4P!#"2`"4X9P`+.,4````#/`LP!0`A(.`""?A``,P`<8Q# -++M`$`06`"FCU@`I8\K`@`,(2"@`@$`0B8K(%(`(1B3`%``I(\AD$``#`"$)"&8 -++M8`"/`P`(4`"DK\(7$0`\`+*.(1!1`$.``@`@`%:."```&B0`4XXA*``"(2!` -++M`O__$"83```,(3`@`OO_`!8A*``"`@`B*AL`0!2`$!$`(8!3``$`%R0$`',F -++M```#C@``8HX`*0,``"$"`(`8`P"`$`(`(R""`",HHP`A(,0"(2C%`@@`A"0. -++M```,"`"E)/__,28A*``"#@``#"$@8`(A($`"`0`%)!,```PA,"`"ZO\W%OS_ -++M$";__P,D3`#")P0`HZXA$(("```#/```5:S8`'6L``"DC@```CR=`@`(W`!$ -++MK"$H(`+N`0`,(2"@`M\#``@!`$(F(``"CB$0H@#``P`(``!`K'C_O2=\`+.O -++M>`"RKW``L*\<`*"O(`"@KX``OZ]T`+&O&`"@KR0`H*\H`*"O``"#CP```CP0 -++M`+,G``!")"&`@``<`*.O(`"BKR$@8`(AD*``````#*@`$8X```(\*!9")&`` -++MHJ\P`+"O5``GCL,?$@`G*`<`0B`2``8@I``$,.,`)3#$`#P`IJ]4`"2.$``% -++MC@00D@`@`.`"RCW0`L8]P`+"/"`#@`X@`O2<````,```` -++M`"$@8`(````,(2@@`B$0``*``+^/?`"SCW@`LH]T`+&/<`"PCP@`X`.(`+TG -++MX/^])QP`OZ\8`+*O%`"QKQ``L*\D`*6O``"0C`0`A8PAD(``OP$`#*@`$8XD -++M`*6/*P(`#"$@0`(D`*6/)@0`#"$@``(```4\```$/```I20F`$`4``"$)%0` -++M)(XD`**/(`"%,"$P0`##/P(`0A@"`"<0!``&&$,`!#B'`"4X9P`$,(8`A``" -++MC@LXQ0`A(``""?A```LP!0`A($`""`$`#"0`I2<```0\```%/```A"0#`$`0 -++M``"E)`````P`````!`!%CB0`IH_N`0`,(2!``B0`HH\<`+^/&`"RCQ0`L8\0 -++M`+"/"`#@`R``O2<````,)`"FCYD$``A4`"2.@/^])W``MJ]\`+^O>`"^KW0` -++MMZ]L`+6O:`"TKV0`LZ]@`+*O7`"QKU@`L*^``*2O``"3C#P`@HRH`'6.$`!D -++MCH0`I:\@`$*,T``%)%``HJ]4`+&.````#%``L(ZD`$`0(;!``!@`I"/<`"VCVP`M8]H`+2/9`"SCV``LH]<`+&/6`"PCP@` -++MX`.``+TG9`4`"```A"1\`+^/>`"^CW0`MX]P`+:/;`"UCV@`M(]D`+./8`"R -++MCUP`L8]8`+"/]/\")`@`X`.``+TG-`"$C`,`!20!``8D````""$X```@_[TG -++MT`"VK[P`L:_<`+^OV`"^K]0`MZ_,`+6OR`"TK\0`LZ_``+*ON`"PKP``@HP! -++M`!$DK`"BKZ@`0XP\`(6,J`"CKU0`8HQ0`&.,(`"EC",00P`$$%$`__]","&P -++M@``L`(2,I`"EKZ``HJ\X`,6.#@"`%)P`I:_<`+^/V`"^C]0`MX_0`+:/S`"U -++MC\@`M(_$`+./P`"RC[P`L8^X`+"/(1````@`X`/@`+TG&`"D)R$H```````, -++M.``&)*P`J(\8`+&O%``$C0P``B0``-6.,`"BKP```CP@`*2O(1@```(`!"3, -++M`$(D-`"CKT``I*\D`*"O2`"BKZ@`HXX4`**.E`"CKS@`Q(Z4`*6/F`"DKT(2 -++M`@#__UC@(0T'/__Q`FC`"BK[``L*^(`*"O -++MB`"CCR0`PH[__W,P(1!3````0Y"B`&`0E`"DCQ$`X!("$'=RD`"BKY``HX\H -++M`,*.(2!#````@Y`,`6`0E`"EC_\%``@AD`````!"D`@!0!"4`*6/`0!")O__ -++M4C#Z__(6(1"2`+``HX^(`*2/__]B,`$`A"0!`$(DX?]$%(@`I*\(`->.(8@` -++M`(`@%P``&1<`I`"ECR.09``A@+(`!``"D@0`0C!D`$`0`````/G_(`:D`*6/ -++M``#4CCP`QXZH`)..`0`1)%``8XY4`&*.4`"D)R,00P`$$%$`(2@``#@`!B0@ -++M`/",````#/__7C!0`+&O```(/!0`AXX```@E#``")```!(UH`**O```"/"$8 -++M``#_``4D6`"GK\P`0B0"``O7`"@KP````R``**O!`## -++MC@``!#S,`(.L!`#"CLP`A20A@%`"!`"BK````XZ9`,`;"`"CK"&`X`+#CQ<` -++M(9```$D&``A"J!<`D@#2$P````!4`&>.4`!HCB_T`4__\1)*P`I(\F!``,(2C@`B&(0``` -++M``*.(2#``@$`0B0```*N=```#"$HX`*4_R$&(2C@`H($``PA(,`"```$/``` -++M!3PA,.`"``"$)`@`PJX``*4D````#"$X0``(`->.@"`7``X&``@`&1<`C`"E -++MCU``AXPA$+,`(1@``$(H`@`G(`<`!BB%``2(XP`@`.8P!(#B`"6(L0`+B`8" -++MIP8`"`N`!@!(`$*.`0!")`4`0R@F`&`02`!"KI0`J(]0``>-(`#"C@08\P`A -++M$$,`?`"BKU``HB<0`**O2`"BCB$P``(A."`""?A``"$@H`(``!0\```$/``` -++MA"0``(4F(3#``Q<`0!`A.&`"```#/$@`8HPAD&``````#!``HJ\,`,.."`#" -++MC@``!#S>_V(4``"$)`````P`````2`!"C@$`0B0%`$,HW/]@%$@`0JX```0\ -++M``"$)```A28````,(3#``P``!#RP`*./2`"`K(@`I(___V(P`0"$)`$`0B03 -++M_T04B`"DKPL&``@(`->.````#`````"!`$`0H`"BCW\`0!@"$%=P(8!``*`` -++MHH_F!@`((9`"`GD`$A(`````J`"CCYP`I8]0`&2,&`"H)Q``J*\G$`0`K`"H -++MCT(8$``A.```1`"EKP880P`$.(<`(`"%,`0PD``E.&<`2``"C0LXQ0`A(``! -++M"?A```LP!0`!`!`FZ/]`$"&(0``A*.`"@@0`#"$@P`(AN$``@"`"```9`@`. -++M!@`("`#"KB&0``",`*B/4`"FC"$0:`(A&```0B@"`"<@!@`&*(4`!(C#`"`` -++MQS`$@,(`)8BQ``N(!P(9!P`("X`'`$0`@HX!`$(D!0!#*"(`8!!$`(*NF`"B -++MCU``HR=\`**O$`"CKT@`HHXA,``"(3@@`@GX0``A(*`"```%/```"#P``*0D -++M(3#``P``!248`$`0(3A@`@```SQ$`&*,(:!@``````P0`**O#`##C@@`PHX` -++M``4\XO]B%```I"0````,`````$0`@HX!`$(D!0!#*.#_8!1$`(*N```$/``` -++M"#P``(0D```%)0````PA,,`#```#/"L05P((`$`41`!@K`0&``BP`*./`0!" -++M)O__4C`K&%<"NOY@$+``HX\H`,*.D`"DCY@`J(\A$((`(1!2````0Y!`.A(` -++M(2@'`?+_8!0``@8DE`"BCU``1(P@`,*.!""3`"$@AP`````,(2""`$<'``@! -++M`$(F#`#0C@@`PHX8``(24`"D)P``T8X\`,*.(2@``#@`!B0@`%*,````#*@` -++M,XX,``(D`0`&)&@`HJ\```(\4`"FKR$8```"``8DS`!")"$@(`(A*``";`"C -++MKW@`IJ\F!``,@`"BKR(`0!````,\``#"C@$`$"2H`$.,%`!1C%``9(Q4`&*, -++M0HH1`",01``$@%``__\0,B0`Q(XA,``"__\Q,BP`P*X````,(2@```(P$7(H -++M`,2.````#"$H``#<`+^/V`"^C]0`MX_0`+:/S`"UC\@`M(_$`+./P`"RC[P` -++ML8^X`+"/(1````@`X`/@`+TG``!C)```9(S_``4D````#`P`!B2`&!```!$0 -++M`",00P`A$$("``!#C```!#P!`&,DS`"$)```0ZP(`(.L5`!DCE``I2O -++M=`"UKW``M*]L`+.O:`"RKV``L*^$`+^O@`"^KW@`MJ]D`+&O``"1C"&@@``4 -++M`"*.J``VCD(2`@#__T0P&P"D`/0!@``!`!OD`"FKQ*H``!)`*,2$(`` -++M`!@`OB>Q"``((`"W)P````P`````&P!R`O0!0`(!``(D(`"BKQ0`(XX8`**/ -++M,`"'CC0`A8XH`*.O(2`@`BP`H*\0,````AA"/>`"VCW0`M8]P`+2/;`"SCV@`LH]D -++M`+&/8`"PCR$0```(`.`#B`"])P(8D'`H`(*.6`"DCR$08@`A$$0```!#D"H` -++M8!`@`+,G0!($`"``@XX$*+``(2BB`"$HHP`````,(2#@`(0`OX^``+Z/?`"W -++MCW@`MH]T`+6/<`"TCVP`LX]H`+*/9`"QCV``L(\A$```"`#@`X@`O2. -++M-`"0KE@`I(^0`*:/0"H$`)0`I(\````,(2BG`(0`OX^``+Z/?`"WCW@`MH]T -++M`+6/<`"TCVP`LX]H`+*/9`"QCV``L(\A$```"`#@`X@`O2"5X("T^ -++M($Y53$P*`&1R:79EF]N95]P -++M='(@:7,@;G5L;`H```!Z;VYE7W!T"`*`````"5S.B!W"`*`````"5S.B!F:6QL -++M7V)L;V-K,2!P:'ES7V)L;V-K.B5D+'!A9V4Z)60L7-?8FQO -++M8VL*````)7,Z(')E861I;F<@97)R;W(@=VAE;B!M;V1I9GEI;F<@<&AY"5X(&5R87-I -++M;F<@9F%I;&5D+"!M87)K960@8F%D+"!A;F0@9FEN9"!N97<@8FQO8VL@,'@E -++M>`H`````)7,Z('!H>7-?8FQO8VL@,'@E>"!P````!T````?````]`4`````#X#X____```````` -++M```H````'0```!\```#\!@``````@/C___\``````````!@````=````'P`` -++M`+@'``````>`_/___P``````````(````!T````?````K`@``````X#X____ -++M```````````@````'0```!\```"X"0````#_P/S___\``````````(@````= -++M````'P```)@0``````^`^/___P``````````B````!T````?````"!(````` -++M!X#\____```````````@````'0```!\````$$P````#_P/S___\````````` -++M`(`````=````'P```"@6`````````````````````````````!T````?```` -++M````````````````````````````````'0```!\```````````#_P/S___\` -++M`````````.`````=````'P```/@>``````.`^/___P``````````(````!T` -++M```?````;!\`````#X#X____```````````H````'0```!\````````````# -++M@/C___\``````````"`````=````'P```'@A`````/_`_/___P`````````` -++MB````!T````?`````````````8#\____```````````8````'0```!\```!4 -++M)0`````````````````````````````=````'P```'@E`````/^`^/___P`` -++M````````0````!T````?`````````````(#X____```````````8````'0`` -++M`!\```"D)P`````````````````````````````=````'P````!'0T,Z("A' -++M3E4I(#0N,2XR```N6UT86)?9W!L -++M`"YR96Q?7VMC"\``"0```````````````0````````` -++MVP````D```````````````Q)```P````(0```!<````$````"````.L````! -++M`````P````````"<+P``&P```````````````0````````#V````"`````,` -++M````````P"\``/```````````````!``````````^P````@````#```0```` -++M`,`O```````````````````$``````````4!```!``````````````#`+P`` -++M0`0`````````````!``````````!`0``"0``````````````/$D``!`!```A -++M````'`````0````(````"@$```$````````````````T```````````````` -++M```!`````````!@!```!````````````````-```$@```````````````0`` -++M```````1`````P``````````````$C0``"$!``````````````$````````` -++M`0````(``````````````$Q*``"0"@``(@```(8````$````$`````D````# -++M``````````````#<5```@`@``````````````0````````!H`0``!`$``'0! -++M```$`0``J`$```0!``!0`@``!`$``*@"```$`0``M`(```0!``#\`@``!1H` -++M``0#```&&@``"`,```4:```0`P``!AH``"`#```$J```-`,```2+``!<`P`` -++M!)D``/0#```$F0``&`0```29```4!0``!)D``!P%```&&@``F`4```8:``#L -++M!0``!`$```P&```%HP``%`8```:C``````0!0```9X``!$%```!)<``+`2```%:```2!0```9H``!P%``` -++M!`$``(`4```%>0``A!0```9Y```\%```!6@``(P4```&:```D!0```27``"H -++M%```!`$``+@4```$`0``Z!0```0!```H%0``!`$``(@5```%>@``C!4```9Z -++M``"4%0``!)<``'P4```%:```F!4```9H``"@%0``!`$``*@5```$`0``L!4` -++M``2+``#L%0``!`$``/04```%>P``\!4```9[```T%@``!(X``/`6```$F0`` -++M$!<```4:```@%P``!AH``'07```$F0``Z!<```0!``",&```!)D``)@8```% -++M?```H!@```9\``"P&```!1H``,`8```&&@``V!@```29``#D&```!1H``.@8 -++M```&&@``E`0```4:``#P&```!AH``!09```$`0``D!D```0!``"8&0``!7T` -++M`*09```&?0``K!0```5H``"H&0``!F@``+`9```$EP``Y!D```0!````&@`` -++M!`$``!`:```$`0``&!H```5^```D&@``!GX``)P9```%:```+!H```9H```P -++M&@``!)<``$`:```$`0``>!H```0!``"`&@``!AH``)`:```&&@``S!H```5_ -++M``#0&@``!G\``!P:```%:```U!H```9H``#D&@``!1H``.@:```&&@``\!H` -++M``27````&P``!8````@;```&@```#!L```27```4&P``!AH``"0;```&&@`` -++M*!L```6!```L&P``!H$``,@:```%:```,!L```9H```T&P``!)<``#P;```% -++M&@``1!L```8:``!@&P``!`$``&@;```$E0``B!L```0!``#X&P``!`$```P< -++M```$`0``2!P```0!``!0'```!AH``&`<```&&@``B!P```6"``"0'```!H(` -++M`(P<```%:```F!P```9H``"D'```!1H``*@<```&&@``L!P```27``#`'``` -++M!8```,@<```&@```S!P```27``#4'```!AH``.0<```&&@``Z!P```6!``#P -++M'```!H$``.P<```%:```]!P```9H``#X'```!)<````=```%&@``#!T```8: -++M```0'0``!`$``&@=```$B@`````$F0``+!X```29``#@'0``!7P``&@>```&?``` -++M=!X```29``"0'@``!1H``)@>```&&@``Z!X```0!``#P'@``!`$```P?```% -++M&@``$!\```8:```D'P``!)8``"P?```$G@``-!\```2=``"$'P``!1H``(@? -++M```&&@``G!\```0!``"8'P``!1H``*`?```&&@``N!\```4:``"\'P``!AH` -++M`,0?```&&@``W!\```0!``#8'P``!1H``.`?```&&@``&"````4:```@(``` -++M!AH``#0@```$E@``/"````2>``!$(```!)T``'0@```$BP``?"````2+``"$ -++M(```!(L``(P@```$BP``E"````2+``"<(```!(L``*0@```$BP``K"````2+ -++M``"T(```!(L``+P@```$BP``Z"````4:``#L(```!AH``/@@```%@P``_"`` -++M``:#````(0``!)<``/0@```%#P``!"$```8/```((0``!`$``"@A```$E@`` -++M,"$```2>```X(0``!)T```PB```$`0``%"(```29``"4(@``!6@``*`B```& -++M:```F"(```6$``"D(@``!H0``)PB```%#P``K"(```8/``"P(@``!)<``+PB -++M```$`0``S"(```0!``#L(@``!)D``%PC```$B@``L",```2*``#T(P``!)D` -++M`(@D```$B@``S"0```0!``#4)```!`$``-PD```$E@``Y"0```2>``#L)``` -++M!)T``/0D```%:````"4```9H``#X)```!80```0E```&A```""4```27``#\ -++M)```!0\```PE```&#P``%"4```0!```<)0``!`$``#@E```$`0``6"4```4: -++M``!@)0``!AH``'`E```$`0``^"4```0!```4)@``!`$``"`F```$`0``/"8` -++M``0!``!,)@``!`$``)0F```$B@``V"8```26``#@)@``!)X``.@F```$G0`` -++M]"8```0!````)P``!`$```PG```%A0``+"8```6%```4)P``!H4``!@G```$ -++MEP``$"<```5H```<)P``!F@``"`G```$`0``+"<```26```T)P``!)X``#PG -++M```$G0``2"<```0!``!@)P``!`$``&@G```%A0``;"<```:%``!P)P``!)<` -++M`%0G```%:```="<```9H``!X)P``!`$``(PG```$`0``J"<```4:``"P)P`` -++M!AH``,`G```$`0``$`````4:```4````!AH``"`````%&@``*`````8:```P -++M````!*```%@````%&@``8`````8:``!H````!*```)0````$FP``D`````41 -++M``"8````!A$```0````$D0````````41```(````!A$````````"&@`````` -++M``*4```$`````A````@````"H0``#`````(0```0`````HD``!0````"$``` -++M&`````*0```<`````A```"`````"B```)`````(0`````````J4```0````" -++MI@``"`````*?```,`````HT``!`````"AP````````((```4`````@$``!@` -++M```"`0``'`````(!```@`````@$``"0````"`0``*`````(!```L`````@$` -++M`#`````"`0````````(%`````````@,````````"&0``!`````(#```,```` -++M`AD``!`````"`P``&`````(9```<`````@,````````"`0``(`````(!``!` -++M`````@$``&`````"`0``@`````*)``"@`````J$``,`````"`P``X`````(# -++M`````0```@,``"`!```"`P``0`$```(!``!@`0```@$``(`!```"`0``H`$` -++M``(!``#``0```@$``.`!```"`0````(```(!```@`@```@$``$`"```"`0`` -++M8`(```(!``"``@```@$``*`"```"`0``P`(```(!``#@`@```@4````#```" -++MG@``(`,```(!``!``P```@$``&`#```"E```@`,```(!``"@`P```H@``,`# -++M```"`0``X`,```(!````!````I```"`$```"`0`````````````````````` -++M``````````````````,``0`````````````````#``(````````````````` -++M`P`#``````````````````,`!``````````````````#``4````````````` -++M`````P`&``````````````````,`!P`````````````````#``@````````` -++M`````````P`)``````````````````,`"@`````````````````#``L````` -++M`````````````P`,``````````````````,`#0`````````````````#``X` -++M`````````````````P`/``````````````````,`$``````````````````# -++M`!$``````````````````P`2``````````````````,`$P`````````````` -++M```#`!0``````````````````P`5``````````````````,`%@`````````` -++M```````#`!<``````````````````P`8``````````````````,`&0`````` -++M```````````#`!H``````````````````P`;``````````````````,`'``` -++M```````````````#`!T``````````````````P`>``````````````````,` -++M'P`````````````````#`"```````````````````P`A```````````````` -++M``,`(@`!```````````````$`/'_#P`````````X`````@`!`"H````X```` -++M%`````(``0`X````3````(0!```"``$`3````-`!```L`0```@`!`&4```#8 -++M````!`````$`&@!R````W`````0````!`!H`?``````````@`````@`#`(P` -++M``!`````!`````$`&@"6````(````#@````"``,`I````"`````@`````0`: -++M`*T```!8````.`````(``P"Z`````````"`````!`!H`P@```)`````,```` -++M`@`#`-``````````3`````$`$0#<````%`,``"@````"``$`\````#P#``!< -++M`````@`!```!``"8`P``B`````(``0`;`0``(`0``-0!```"``$`-`$``,P` -++M```,`````0`:`#T!``#T!0``"`$```(``0!.`0``_`8``+P````"``$`<`$` -++M`+@'``#T`````@`!`)`!```D````(`````$`#P"?`0``K`@```P!```"``$` -++MP0$``+@)``#@!@```@`!`,\!``#@````!`````$`&@#:`0``3````(`````! -++M`!H`X@$``!0````.`````0`/`/$!``````````````$`&P#]`0``F!```'`! -++M```"``$`"0(``"@6```4`````@`!`!@"```($@``_`````(``0`X`@``!!,` -++M`"0#```"``$`5P(````````,`````@`%`&@"``!(````!`````$`&@!Z`@`` -++M1`````0````!`!H`C`(``/@>``!T`````@`!`)L"``!L'P``I`$```(``0"L -++M`@```````!$````!``\`NP(``'@A``"L`P```@`!`,H"``!$````#P````$` -++M#P#9`@``5"4``"0````"``$`ZP(``'@E```(`@```@`!`/L"``"D)P``)``` -++M``(``0`.`P````````0````!`!,`*@,````````$`````0`5`$0#```````` -++M#`````$`%P!<`P````````H````!`!D`>`,```P````,`````0`7`(X#```* -++M````"0````$`&0"H`P``&`````P````!`!<`O0,``!,````(`````0`9`-8# -++M````````"`````$`"P#P`P```````!`````!`!``"@0````````$`````0`- -++M`"0$```(````"`````$`"P`Z!```$`````P````!`!``4`0```0````$```` -++M`0`-`&8$```0````"`````$`"P!_!```'`````\````!`!``F`0```@````$ -++M`````0`-`+$$```8````"`````$`"P#2!```+````!<````!`!``\P0```P` -++M```$`````0`-`!0%```@````"`````$`"P`T!0``1````!8````!`!``5`4` -++M`!`````$`````0`-`'0%````````````````"`!Y!0``+`````````````@` -++M?@4``$@````````````(`(,%``!@````````````"`"(!0``=``````````` -++M``@`C04``)0````````````(`)(%``#4````````````"`"7!0``,`$````` -++M``````@`G`4```P!```````````(`*$%``!(`0``````````"`"F!0``8`$` -++M``````````@`K`4``'@!```````````(`+(%``"D`0``````````"`"X!0`` -++M[`$```````````@`O@4``#`"```````````(`,0%``!,`@``````````"`#* -++M!0``>`(```````````@`T`4``)P"```````````(`-8%``#,`@`````````` -++M"`#BYC`&UT9&)L;V-K7V%D9')E0!M=&1B;&]C:U]L:69E=&EM95]R97-O0!?7V9U;F-?7RXQ-3,T.0!M -++M=&1B;&]C:U]B;&]C:U]I;F9O7VUA<%]B861?8FQO8VL`;71D8FQO8VM?;W!E -++M;@!M=&1B;&M?:61X`&UT9&)L:W,`7U]F=6YC7U\N,38Q.#,`7U]K97DN,38P -++M-3,`97)A&ET8V%L;%]C;&5A;G5P7VUT9&)L;V-K`%]?:6YI=&-A;&Q? -++M:6YI=%]M=&1B;&]C:S8`7U]S971U<%]M=&1B;&ML;V=?6UT86)?=61C7V9L=7-H -++M7V-A8VAE`%]?:W-T6UT86)?=61C7V=E=%]M=&0`7U]K6UT86)? -++M=61C7V=E=%]M=&1B;&L`7U]K6UT86)?=61C7VUT9&)L;V-K7W=R -++M:71E6UT86)?=61C7VUT -++M9&)L;V-K7W)E861S96-T`%]?:W-T%]L;V-K`'!R:6YT:P!?7VUU=&5X7VEN:70` -++M;65M -+ * (C) 1999-2003 David Woodhouse -+@@ -15,7 +15,7 @@ -+ #include -+ #include -+ #include -+- -++#include -+ #include -+ #include -+ #include -+@@ -361,12 +361,27 @@ -+ kfree(dev); -+ } -+ -++ -++static int mtdblock_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) -++{ -++ struct gendisk *gd = dev->blkcore_priv; -++ memset(geo, 0, sizeof(*geo)); -++ geo->heads = 4; -++ geo->sectors = 16; -++ geo->cylinders = dev->size/(4*16); -++ -++ printk("cylinders: %x \n", geo->cylinders); -++ printk("sects: %x\n", dev->size); -++ return 0; -++} -++ -+ static struct mtd_blktrans_ops mtdblock_tr = { -+ .name = "mtdblock", -+ .major = 31, -+ .part_bits = 0, -+ .blksize = 512, -+ .open = mtdblock_open, -++ .getgeo = mtdblock_getgeo, -+ .flush = mtdblock_flush, -+ .release = mtdblock_release, -+ .readsect = mtdblock_readsect, -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtdchar.c linux-2.6.24.7/drivers/mtd/mtdchar.c -+--- linux-2.6.24.7.old/drivers/mtd/mtdchar.c 2009-04-12 18:05:07.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/mtdchar.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ /* -+- * $Id: mtdchar.c,v 1.76 2005/11/07 11:14:20 gleixner Exp $ -++ * $Id: mtdchar.c,v 1.1.1.1 2008-03-28 04:29:21 jlwei Exp $ -+ * -+ * Character-device access to raw MTD devices. -+ * -+@@ -7,7 +7,6 @@ -+ -+ #include -+ #include -+-#include -+ #include -+ #include -+ #include -+@@ -83,8 +82,6 @@ -+ return -EINVAL; -+ } -+ -+- -+- -+ static int mtd_open(struct inode *inode, struct file *file) -+ { -+ int minor = iminor(inode); -+@@ -137,8 +134,7 @@ -+ -+ DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n"); -+ -+- /* Only sync if opened RW */ -+- if ((file->f_mode & 2) && mtd->sync) -++ if (mtd->sync) -+ mtd->sync(mtd); -+ -+ put_mtd_device(mtd); -+@@ -157,7 +153,7 @@ -+ { -+ struct mtd_file_info *mfi = file->private_data; -+ struct mtd_info *mtd = mfi->mtd; -+- size_t retlen=0; -++ size_mtd_t retlen=0; -+ size_t total_retlen=0; -+ int ret=0; -+ int len; -+@@ -251,7 +247,7 @@ -+ struct mtd_file_info *mfi = file->private_data; -+ struct mtd_info *mtd = mfi->mtd; -+ char *kbuf; -+- size_t retlen; -++ size_mtd_t retlen; -+ size_t total_retlen=0; -+ int ret=0; -+ int len; -+@@ -536,7 +532,7 @@ -+ { -+ struct mtd_oob_buf buf; -+ struct mtd_oob_ops ops; -+- -++ -+ if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf))) -+ return -EFAULT; -+ -+@@ -576,6 +572,73 @@ -+ break; -+ } -+ -++ case MEMWRITEPAGE: -++ { -++ struct mtd_page_buf buf; -++ struct mtd_oob_ops ops; -++ -++ memset(&ops, 0, sizeof(ops)); -++#if 1 -++ if(!(file->f_mode & 2)) -++ return -EPERM; -++#endif -++ -++ if (copy_from_user(&buf, argp, sizeof(struct mtd_page_buf))) -++ return -EFAULT; -++ -++ if (buf.ooblength > mtd->oobsize) -++ return -EINVAL; -++ -++ if (!mtd->write_oob) -++ ret = -EOPNOTSUPP; -++ else -++ ret = access_ok(VERIFY_READ, buf.oobptr, -++ buf.ooblength) ? 0 : EFAULT; -++ -++ if (ret) -++ return ret; -++ -++ ops.len = mtd->writesize; -++ ops.ooblen = buf.ooblength; -++ ops.ooboffs = buf.start & (mtd->oobsize - 1); -++ ops.mode = MTD_OOB_PLACE; -++ -++ if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) -++ return -EINVAL; -++ -++ /* alloc memory and copy oob data from user mode to kernel mode */ -++ ops.oobbuf = kmalloc(buf.ooblength, GFP_KERNEL); -++ if (!ops.oobbuf) -++ return -ENOMEM; -++ -++ if (copy_from_user(ops.oobbuf, buf.oobptr, buf.ooblength)) { -++ kfree(ops.oobbuf); -++ return -EFAULT; -++ } -++ -++ /* alloc memory and copy page data from user mode to kernel mode */ -++ ops.datbuf = kmalloc(mtd->writesize, GFP_KERNEL); -++ if (!ops.datbuf) -++ return -ENOMEM; -++ -++ if (copy_from_user(ops.datbuf, buf.datptr, mtd->writesize)) { -++ kfree(ops.datbuf); -++ return -EFAULT; -++ } -++ -++ buf.start &= ~(mtd->oobsize - 1); -++ ret = mtd->write_oob(mtd, buf.start, &ops); -++ -++ if (copy_to_user(argp + 2*sizeof(uint32_t), &ops.retlen, -++ sizeof(uint32_t))) -++ ret = -EFAULT; -++ -++ kfree(ops.oobbuf); -++ kfree(ops.datbuf); -++ break; -++ } -++ -++ -+ case MEMLOCK: -+ { -+ struct erase_info_user info; -+@@ -627,9 +690,9 @@ -+ -+ case MEMGETBADBLOCK: -+ { -+- loff_t offs; -++ loff_mtd_t offs; -+ -+- if (copy_from_user(&offs, argp, sizeof(loff_t))) -++ if (copy_from_user(&offs, argp, sizeof(loff_mtd_t))) -+ return -EFAULT; -+ if (!mtd->block_isbad) -+ ret = -EOPNOTSUPP; -+@@ -640,9 +703,9 @@ -+ -+ case MEMSETBADBLOCK: -+ { -+- loff_t offs; -++ loff_mtd_t offs; -+ -+- if (copy_from_user(&offs, argp, sizeof(loff_t))) -++ if (copy_from_user(&offs, argp, sizeof(loff_mtd_t))) -+ return -EFAULT; -+ if (!mtd->block_markbad) -+ ret = -EOPNOTSUPP; -+@@ -764,9 +827,9 @@ -+ #endif -+ -+ default: -++ printk("line : %d\n", __LINE__); -+ ret = -ENOTTY; -+ } -+- -+ return ret; -+ } /* memory_ioctl */ -+ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtdchar.c.orig linux-2.6.24.7/drivers/mtd/mtdchar.c.orig -+--- linux-2.6.24.7.old/drivers/mtd/mtdchar.c.orig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/mtdchar.c.orig 2009-04-12 18:01:55.000000000 +0200 -+@@ -0,0 +1,816 @@ -++/* -++ * $Id: mtdchar.c,v 1.76 2005/11/07 11:14:20 gleixner Exp $ -++ * -++ * Character-device access to raw MTD devices. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++ -++#include -++ -++static struct class *mtd_class; -++ -++static void mtd_notify_add(struct mtd_info* mtd) -++{ -++ if (!mtd) -++ return; -++ -++ class_device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2), -++ NULL, "mtd%d", mtd->index); -++ -++ class_device_create(mtd_class, NULL, -++ MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1), -++ NULL, "mtd%dro", mtd->index); -++} -++ -++static void mtd_notify_remove(struct mtd_info* mtd) -++{ -++ if (!mtd) -++ return; -++ -++ class_device_destroy(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2)); -++ class_device_destroy(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1)); -++} -++ -++static struct mtd_notifier notifier = { -++ .add = mtd_notify_add, -++ .remove = mtd_notify_remove, -++}; -++ -++/* -++ * Data structure to hold the pointer to the mtd device as well -++ * as mode information ofr various use cases. -++ */ -++struct mtd_file_info { -++ struct mtd_info *mtd; -++ enum mtd_file_modes mode; -++}; -++ -++static loff_t mtd_lseek (struct file *file, loff_t offset, int orig) -++{ -++ struct mtd_file_info *mfi = file->private_data; -++ struct mtd_info *mtd = mfi->mtd; -++ -++ switch (orig) { -++ case SEEK_SET: -++ break; -++ case SEEK_CUR: -++ offset += file->f_pos; -++ break; -++ case SEEK_END: -++ offset += mtd->size; -++ break; -++ default: -++ return -EINVAL; -++ } -++ -++ if (offset >= 0 && offset <= mtd->size) -++ return file->f_pos = offset; -++ -++ return -EINVAL; -++} -++ -++ -++ -++static int mtd_open(struct inode *inode, struct file *file) -++{ -++ int minor = iminor(inode); -++ int devnum = minor >> 1; -++ struct mtd_info *mtd; -++ struct mtd_file_info *mfi; -++ -++ DEBUG(MTD_DEBUG_LEVEL0, "MTD_open\n"); -++ -++ if (devnum >= MAX_MTD_DEVICES) -++ return -ENODEV; -++ -++ /* You can't open the RO devices RW */ -++ if ((file->f_mode & 2) && (minor & 1)) -++ return -EACCES; -++ -++ mtd = get_mtd_device(NULL, devnum); -++ -++ if (IS_ERR(mtd)) -++ return PTR_ERR(mtd); -++ -++ if (MTD_ABSENT == mtd->type) { -++ put_mtd_device(mtd); -++ return -ENODEV; -++ } -++ -++ /* You can't open it RW if it's not a writeable device */ -++ if ((file->f_mode & 2) && !(mtd->flags & MTD_WRITEABLE)) { -++ put_mtd_device(mtd); -++ return -EACCES; -++ } -++ -++ mfi = kzalloc(sizeof(*mfi), GFP_KERNEL); -++ if (!mfi) { -++ put_mtd_device(mtd); -++ return -ENOMEM; -++ } -++ mfi->mtd = mtd; -++ file->private_data = mfi; -++ -++ return 0; -++} /* mtd_open */ -++ -++/*====================================================================*/ -++ -++static int mtd_close(struct inode *inode, struct file *file) -++{ -++ struct mtd_file_info *mfi = file->private_data; -++ struct mtd_info *mtd = mfi->mtd; -++ -++ DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n"); -++ -++ /* Only sync if opened RW */ -++ if ((file->f_mode & 2) && mtd->sync) -++ mtd->sync(mtd); -++ -++ put_mtd_device(mtd); -++ file->private_data = NULL; -++ kfree(mfi); -++ -++ return 0; -++} /* mtd_close */ -++ -++/* FIXME: This _really_ needs to die. In 2.5, we should lock the -++ userspace buffer down and use it directly with readv/writev. -++*/ -++#define MAX_KMALLOC_SIZE 0x20000 -++ -++static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos) -++{ -++ struct mtd_file_info *mfi = file->private_data; -++ struct mtd_info *mtd = mfi->mtd; -++ size_t retlen=0; -++ size_t total_retlen=0; -++ int ret=0; -++ int len; -++ char *kbuf; -++ -++ DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n"); -++ -++ if (*ppos + count > mtd->size) -++ count = mtd->size - *ppos; -++ -++ if (!count) -++ return 0; -++ -++ /* FIXME: Use kiovec in 2.5 to lock down the user's buffers -++ and pass them directly to the MTD functions */ -++ -++ if (count > MAX_KMALLOC_SIZE) -++ kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL); -++ else -++ kbuf=kmalloc(count, GFP_KERNEL); -++ -++ if (!kbuf) -++ return -ENOMEM; -++ -++ while (count) { -++ -++ if (count > MAX_KMALLOC_SIZE) -++ len = MAX_KMALLOC_SIZE; -++ else -++ len = count; -++ -++ switch (mfi->mode) { -++ case MTD_MODE_OTP_FACTORY: -++ ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf); -++ break; -++ case MTD_MODE_OTP_USER: -++ ret = mtd->read_user_prot_reg(mtd, *ppos, len, &retlen, kbuf); -++ break; -++ case MTD_MODE_RAW: -++ { -++ struct mtd_oob_ops ops; -++ -++ ops.mode = MTD_OOB_RAW; -++ ops.datbuf = kbuf; -++ ops.oobbuf = NULL; -++ ops.len = len; -++ -++ ret = mtd->read_oob(mtd, *ppos, &ops); -++ retlen = ops.retlen; -++ break; -++ } -++ default: -++ ret = mtd->read(mtd, *ppos, len, &retlen, kbuf); -++ } -++ /* Nand returns -EBADMSG on ecc errors, but it returns -++ * the data. For our userspace tools it is important -++ * to dump areas with ecc errors ! -++ * For kernel internal usage it also might return -EUCLEAN -++ * to signal the caller that a bitflip has occured and has -++ * been corrected by the ECC algorithm. -++ * Userspace software which accesses NAND this way -++ * must be aware of the fact that it deals with NAND -++ */ -++ if (!ret || (ret == -EUCLEAN) || (ret == -EBADMSG)) { -++ *ppos += retlen; -++ if (copy_to_user(buf, kbuf, retlen)) { -++ kfree(kbuf); -++ return -EFAULT; -++ } -++ else -++ total_retlen += retlen; -++ -++ count -= retlen; -++ buf += retlen; -++ if (retlen == 0) -++ count = 0; -++ } -++ else { -++ kfree(kbuf); -++ return ret; -++ } -++ -++ } -++ -++ kfree(kbuf); -++ return total_retlen; -++} /* mtd_read */ -++ -++static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count,loff_t *ppos) -++{ -++ struct mtd_file_info *mfi = file->private_data; -++ struct mtd_info *mtd = mfi->mtd; -++ char *kbuf; -++ size_t retlen; -++ size_t total_retlen=0; -++ int ret=0; -++ int len; -++ -++ DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n"); -++ -++ if (*ppos == mtd->size) -++ return -ENOSPC; -++ -++ if (*ppos + count > mtd->size) -++ count = mtd->size - *ppos; -++ -++ if (!count) -++ return 0; -++ -++ if (count > MAX_KMALLOC_SIZE) -++ kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL); -++ else -++ kbuf=kmalloc(count, GFP_KERNEL); -++ -++ if (!kbuf) -++ return -ENOMEM; -++ -++ while (count) { -++ -++ if (count > MAX_KMALLOC_SIZE) -++ len = MAX_KMALLOC_SIZE; -++ else -++ len = count; -++ -++ if (copy_from_user(kbuf, buf, len)) { -++ kfree(kbuf); -++ return -EFAULT; -++ } -++ -++ switch (mfi->mode) { -++ case MTD_MODE_OTP_FACTORY: -++ ret = -EROFS; -++ break; -++ case MTD_MODE_OTP_USER: -++ if (!mtd->write_user_prot_reg) { -++ ret = -EOPNOTSUPP; -++ break; -++ } -++ ret = mtd->write_user_prot_reg(mtd, *ppos, len, &retlen, kbuf); -++ break; -++ -++ case MTD_MODE_RAW: -++ { -++ struct mtd_oob_ops ops; -++ -++ ops.mode = MTD_OOB_RAW; -++ ops.datbuf = kbuf; -++ ops.oobbuf = NULL; -++ ops.len = len; -++ -++ ret = mtd->write_oob(mtd, *ppos, &ops); -++ retlen = ops.retlen; -++ break; -++ } -++ -++ default: -++ ret = (*(mtd->write))(mtd, *ppos, len, &retlen, kbuf); -++ } -++ if (!ret) { -++ *ppos += retlen; -++ total_retlen += retlen; -++ count -= retlen; -++ buf += retlen; -++ } -++ else { -++ kfree(kbuf); -++ return ret; -++ } -++ } -++ -++ kfree(kbuf); -++ return total_retlen; -++} /* mtd_write */ -++ -++/*====================================================================== -++ -++ IOCTL calls for getting device parameters. -++ -++======================================================================*/ -++static void mtdchar_erase_callback (struct erase_info *instr) -++{ -++ wake_up((wait_queue_head_t *)instr->priv); -++} -++ -++#if defined(CONFIG_MTD_OTP) || defined(CONFIG_MTD_ONENAND_OTP) -++static int otp_select_filemode(struct mtd_file_info *mfi, int mode) -++{ -++ struct mtd_info *mtd = mfi->mtd; -++ int ret = 0; -++ -++ switch (mode) { -++ case MTD_OTP_FACTORY: -++ if (!mtd->read_fact_prot_reg) -++ ret = -EOPNOTSUPP; -++ else -++ mfi->mode = MTD_MODE_OTP_FACTORY; -++ break; -++ case MTD_OTP_USER: -++ if (!mtd->read_fact_prot_reg) -++ ret = -EOPNOTSUPP; -++ else -++ mfi->mode = MTD_MODE_OTP_USER; -++ break; -++ default: -++ ret = -EINVAL; -++ case MTD_OTP_OFF: -++ break; -++ } -++ return ret; -++} -++#else -++# define otp_select_filemode(f,m) -EOPNOTSUPP -++#endif -++ -++static int mtd_ioctl(struct inode *inode, struct file *file, -++ u_int cmd, u_long arg) -++{ -++ struct mtd_file_info *mfi = file->private_data; -++ struct mtd_info *mtd = mfi->mtd; -++ void __user *argp = (void __user *)arg; -++ int ret = 0; -++ u_long size; -++ struct mtd_info_user info; -++ -++ DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n"); -++ -++ size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; -++ if (cmd & IOC_IN) { -++ if (!access_ok(VERIFY_READ, argp, size)) -++ return -EFAULT; -++ } -++ if (cmd & IOC_OUT) { -++ if (!access_ok(VERIFY_WRITE, argp, size)) -++ return -EFAULT; -++ } -++ -++ switch (cmd) { -++ case MEMGETREGIONCOUNT: -++ if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int))) -++ return -EFAULT; -++ break; -++ -++ case MEMGETREGIONINFO: -++ { -++ struct region_info_user ur; -++ -++ if (copy_from_user(&ur, argp, sizeof(struct region_info_user))) -++ return -EFAULT; -++ -++ if (ur.regionindex >= mtd->numeraseregions) -++ return -EINVAL; -++ if (copy_to_user(argp, &(mtd->eraseregions[ur.regionindex]), -++ sizeof(struct mtd_erase_region_info))) -++ return -EFAULT; -++ break; -++ } -++ -++ case MEMGETINFO: -++ info.type = mtd->type; -++ info.flags = mtd->flags; -++ info.size = mtd->size; -++ info.erasesize = mtd->erasesize; -++ info.writesize = mtd->writesize; -++ info.oobsize = mtd->oobsize; -++ /* The below fields are obsolete */ -++ info.ecctype = -1; -++ info.eccsize = 0; -++ if (copy_to_user(argp, &info, sizeof(struct mtd_info_user))) -++ return -EFAULT; -++ break; -++ -++ case MEMERASE: -++ { -++ struct erase_info *erase; -++ -++ if(!(file->f_mode & 2)) -++ return -EPERM; -++ -++ erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL); -++ if (!erase) -++ ret = -ENOMEM; -++ else { -++ wait_queue_head_t waitq; -++ DECLARE_WAITQUEUE(wait, current); -++ -++ init_waitqueue_head(&waitq); -++ -++ if (copy_from_user(&erase->addr, argp, -++ sizeof(struct erase_info_user))) { -++ kfree(erase); -++ return -EFAULT; -++ } -++ erase->mtd = mtd; -++ erase->callback = mtdchar_erase_callback; -++ erase->priv = (unsigned long)&waitq; -++ -++ /* -++ FIXME: Allow INTERRUPTIBLE. Which means -++ not having the wait_queue head on the stack. -++ -++ If the wq_head is on the stack, and we -++ leave because we got interrupted, then the -++ wq_head is no longer there when the -++ callback routine tries to wake us up. -++ */ -++ ret = mtd->erase(mtd, erase); -++ if (!ret) { -++ set_current_state(TASK_UNINTERRUPTIBLE); -++ add_wait_queue(&waitq, &wait); -++ if (erase->state != MTD_ERASE_DONE && -++ erase->state != MTD_ERASE_FAILED) -++ schedule(); -++ remove_wait_queue(&waitq, &wait); -++ set_current_state(TASK_RUNNING); -++ -++ ret = (erase->state == MTD_ERASE_FAILED)?-EIO:0; -++ } -++ kfree(erase); -++ } -++ break; -++ } -++ -++ case MEMWRITEOOB: -++ { -++ struct mtd_oob_buf buf; -++ struct mtd_oob_ops ops; -++ -++ if(!(file->f_mode & 2)) -++ return -EPERM; -++ -++ if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf))) -++ return -EFAULT; -++ -++ if (buf.length > 4096) -++ return -EINVAL; -++ -++ if (!mtd->write_oob) -++ ret = -EOPNOTSUPP; -++ else -++ ret = access_ok(VERIFY_READ, buf.ptr, -++ buf.length) ? 0 : EFAULT; -++ -++ if (ret) -++ return ret; -++ -++ ops.ooblen = buf.length; -++ ops.ooboffs = buf.start & (mtd->oobsize - 1); -++ ops.datbuf = NULL; -++ ops.mode = MTD_OOB_PLACE; -++ -++ if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) -++ return -EINVAL; -++ -++ ops.oobbuf = kmalloc(buf.length, GFP_KERNEL); -++ if (!ops.oobbuf) -++ return -ENOMEM; -++ -++ if (copy_from_user(ops.oobbuf, buf.ptr, buf.length)) { -++ kfree(ops.oobbuf); -++ return -EFAULT; -++ } -++ -++ buf.start &= ~(mtd->oobsize - 1); -++ ret = mtd->write_oob(mtd, buf.start, &ops); -++ -++ if (copy_to_user(argp + sizeof(uint32_t), &ops.oobretlen, -++ sizeof(uint32_t))) -++ ret = -EFAULT; -++ -++ kfree(ops.oobbuf); -++ break; -++ -++ } -++ -++ case MEMREADOOB: -++ { -++ struct mtd_oob_buf buf; -++ struct mtd_oob_ops ops; -++ -++ if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf))) -++ return -EFAULT; -++ -++ if (buf.length > 4096) -++ return -EINVAL; -++ -++ if (!mtd->read_oob) -++ ret = -EOPNOTSUPP; -++ else -++ ret = access_ok(VERIFY_WRITE, buf.ptr, -++ buf.length) ? 0 : -EFAULT; -++ if (ret) -++ return ret; -++ -++ ops.ooblen = buf.length; -++ ops.ooboffs = buf.start & (mtd->oobsize - 1); -++ ops.datbuf = NULL; -++ ops.mode = MTD_OOB_PLACE; -++ -++ if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) -++ return -EINVAL; -++ -++ ops.oobbuf = kmalloc(buf.length, GFP_KERNEL); -++ if (!ops.oobbuf) -++ return -ENOMEM; -++ -++ buf.start &= ~(mtd->oobsize - 1); -++ ret = mtd->read_oob(mtd, buf.start, &ops); -++ -++ if (put_user(ops.oobretlen, (uint32_t __user *)argp)) -++ ret = -EFAULT; -++ else if (ops.oobretlen && copy_to_user(buf.ptr, ops.oobbuf, -++ ops.oobretlen)) -++ ret = -EFAULT; -++ -++ kfree(ops.oobbuf); -++ break; -++ } -++ -++ case MEMLOCK: -++ { -++ struct erase_info_user info; -++ -++ if (copy_from_user(&info, argp, sizeof(info))) -++ return -EFAULT; -++ -++ if (!mtd->lock) -++ ret = -EOPNOTSUPP; -++ else -++ ret = mtd->lock(mtd, info.start, info.length); -++ break; -++ } -++ -++ case MEMUNLOCK: -++ { -++ struct erase_info_user info; -++ -++ if (copy_from_user(&info, argp, sizeof(info))) -++ return -EFAULT; -++ -++ if (!mtd->unlock) -++ ret = -EOPNOTSUPP; -++ else -++ ret = mtd->unlock(mtd, info.start, info.length); -++ break; -++ } -++ -++ /* Legacy interface */ -++ case MEMGETOOBSEL: -++ { -++ struct nand_oobinfo oi; -++ -++ if (!mtd->ecclayout) -++ return -EOPNOTSUPP; -++ if (mtd->ecclayout->eccbytes > ARRAY_SIZE(oi.eccpos)) -++ return -EINVAL; -++ -++ oi.useecc = MTD_NANDECC_AUTOPLACE; -++ memcpy(&oi.eccpos, mtd->ecclayout->eccpos, sizeof(oi.eccpos)); -++ memcpy(&oi.oobfree, mtd->ecclayout->oobfree, -++ sizeof(oi.oobfree)); -++ oi.eccbytes = mtd->ecclayout->eccbytes; -++ -++ if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo))) -++ return -EFAULT; -++ break; -++ } -++ -++ case MEMGETBADBLOCK: -++ { -++ loff_t offs; -++ -++ if (copy_from_user(&offs, argp, sizeof(loff_t))) -++ return -EFAULT; -++ if (!mtd->block_isbad) -++ ret = -EOPNOTSUPP; -++ else -++ return mtd->block_isbad(mtd, offs); -++ break; -++ } -++ -++ case MEMSETBADBLOCK: -++ { -++ loff_t offs; -++ -++ if (copy_from_user(&offs, argp, sizeof(loff_t))) -++ return -EFAULT; -++ if (!mtd->block_markbad) -++ ret = -EOPNOTSUPP; -++ else -++ return mtd->block_markbad(mtd, offs); -++ break; -++ } -++ -++#if defined(CONFIG_MTD_OTP) || defined(CONFIG_MTD_ONENAND_OTP) -++ case OTPSELECT: -++ { -++ int mode; -++ if (copy_from_user(&mode, argp, sizeof(int))) -++ return -EFAULT; -++ -++ mfi->mode = MTD_MODE_NORMAL; -++ -++ ret = otp_select_filemode(mfi, mode); -++ -++ file->f_pos = 0; -++ break; -++ } -++ -++ case OTPGETREGIONCOUNT: -++ case OTPGETREGIONINFO: -++ { -++ struct otp_info *buf = kmalloc(4096, GFP_KERNEL); -++ if (!buf) -++ return -ENOMEM; -++ ret = -EOPNOTSUPP; -++ switch (mfi->mode) { -++ case MTD_MODE_OTP_FACTORY: -++ if (mtd->get_fact_prot_info) -++ ret = mtd->get_fact_prot_info(mtd, buf, 4096); -++ break; -++ case MTD_MODE_OTP_USER: -++ if (mtd->get_user_prot_info) -++ ret = mtd->get_user_prot_info(mtd, buf, 4096); -++ break; -++ default: -++ break; -++ } -++ if (ret >= 0) { -++ if (cmd == OTPGETREGIONCOUNT) { -++ int nbr = ret / sizeof(struct otp_info); -++ ret = copy_to_user(argp, &nbr, sizeof(int)); -++ } else -++ ret = copy_to_user(argp, buf, ret); -++ if (ret) -++ ret = -EFAULT; -++ } -++ kfree(buf); -++ break; -++ } -++ -++ case OTPLOCK: -++ { -++ struct otp_info info; -++ -++ if (mfi->mode != MTD_MODE_OTP_USER) -++ return -EINVAL; -++ if (copy_from_user(&info, argp, sizeof(info))) -++ return -EFAULT; -++ if (!mtd->lock_user_prot_reg) -++ return -EOPNOTSUPP; -++ ret = mtd->lock_user_prot_reg(mtd, info.start, info.length); -++ break; -++ } -++#endif -++ -++ case ECCGETLAYOUT: -++ { -++ if (!mtd->ecclayout) -++ return -EOPNOTSUPP; -++ -++ if (copy_to_user(argp, mtd->ecclayout, -++ sizeof(struct nand_ecclayout))) -++ return -EFAULT; -++ break; -++ } -++ -++ case ECCGETSTATS: -++ { -++ if (copy_to_user(argp, &mtd->ecc_stats, -++ sizeof(struct mtd_ecc_stats))) -++ return -EFAULT; -++ break; -++ } -++ -++ case MTDFILEMODE: -++ { -++ mfi->mode = 0; -++ -++ switch(arg) { -++ case MTD_MODE_OTP_FACTORY: -++ case MTD_MODE_OTP_USER: -++ ret = otp_select_filemode(mfi, arg); -++ break; -++ -++ case MTD_MODE_RAW: -++ if (!mtd->read_oob || !mtd->write_oob) -++ return -EOPNOTSUPP; -++ mfi->mode = arg; -++ -++ case MTD_MODE_NORMAL: -++ break; -++ default: -++ ret = -EINVAL; -++ } -++ file->f_pos = 0; -++ break; -++ } -++#ifdef CONFIG_MTD_PARTITIONS -++ case MTDREFRESH: -++ { -++ ret = refresh_mtd_partitions(mtd); -++ break; -++ } -++#endif -++ -++ default: -++ ret = -ENOTTY; -++ } -++ -++ return ret; -++} /* memory_ioctl */ -++ -++static const struct file_operations mtd_fops = { -++ .owner = THIS_MODULE, -++ .llseek = mtd_lseek, -++ .read = mtd_read, -++ .write = mtd_write, -++ .ioctl = mtd_ioctl, -++ .open = mtd_open, -++ .release = mtd_close, -++}; -++ -++static int __init init_mtdchar(void) -++{ -++ if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) { -++ printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", -++ MTD_CHAR_MAJOR); -++ return -EAGAIN; -++ } -++ -++ mtd_class = class_create(THIS_MODULE, "mtd"); -++ -++ if (IS_ERR(mtd_class)) { -++ printk(KERN_ERR "Error creating mtd class.\n"); -++ unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); -++ return PTR_ERR(mtd_class); -++ } -++ -++ register_mtd_user(¬ifier); -++ return 0; -++} -++ -++static void __exit cleanup_mtdchar(void) -++{ -++ unregister_mtd_user(¬ifier); -++ class_destroy(mtd_class); -++ unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); -++} -++ -++module_init(init_mtdchar); -++module_exit(cleanup_mtdchar); -++ -++ -++MODULE_LICENSE("GPL"); -++MODULE_AUTHOR("David Woodhouse "); -++MODULE_DESCRIPTION("Direct character-device access to MTD devices"); -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtdcore.c linux-2.6.24.7/drivers/mtd/mtdcore.c -+--- linux-2.6.24.7.old/drivers/mtd/mtdcore.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/mtdcore.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -303,10 +303,10 @@ -+ */ -+ -+ int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, -+- unsigned long count, loff_t to, size_t *retlen) -++ unsigned long count, loff_mtd_t to, size_mtd_t *retlen) -+ { -+ unsigned long i; -+- size_t totlen = 0, thislen; -++ size_mtd_t totlen = 0, thislen; -+ int ret = 0; -+ -+ if(!mtd->write) { -+@@ -350,7 +350,7 @@ -+ if (!this) -+ return 0; -+ -+- return sprintf(buf, "mtd%d: %8.8x %8.8x \"%s\"\n", i, this->size, -++ return sprintf(buf, "mtd%d: %09llx %8.8x \"%s\"\n", i, this->size, -+ this->erasesize, this->name); -+ } -+ -+diff -urN linux-2.6.24.7.old/drivers/mtd/mtdpart.c linux-2.6.24.7/drivers/mtd/mtdpart.c -+--- linux-2.6.24.7.old/drivers/mtd/mtdpart.c 2009-04-12 18:05:07.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/mtdpart.c 2009-04-12 18:38:31.000000000 +0200 -+@@ -30,7 +30,7 @@ -+ struct mtd_part { -+ struct mtd_info mtd; -+ struct mtd_info *master; -+- u_int32_t offset; -++ u_int64_t offset; -+ int index; -+ struct list_head list; -+ int registered; -+@@ -48,8 +48,8 @@ -+ * to the _real_ device. -+ */ -+ -+-static int part_read (struct mtd_info *mtd, loff_t from, size_t len, -+- size_t *retlen, u_char *buf) -++static int part_read (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, -++ size_mtd_t *retlen, u_char *buf) -+ { -+ struct mtd_part *part = PART(mtd); -+ int res; -+@@ -69,8 +69,8 @@ -+ return res; -+ } -+ -+-static int part_point (struct mtd_info *mtd, loff_t from, size_t len, -+- size_t *retlen, u_char **buf) -++static int part_point (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, -++ size_mtd_t *retlen, u_char **buf) -+ { -+ struct mtd_part *part = PART(mtd); -+ if (from >= mtd->size) -+@@ -81,14 +81,14 @@ -+ len, retlen, buf); -+ } -+ -+-static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) -++static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_mtd_t from, size_mtd_t len) -+ { -+ struct mtd_part *part = PART(mtd); -+ -+ part->master->unpoint (part->master, addr, from + part->offset, len); -+ } -+ -+-static int part_read_oob(struct mtd_info *mtd, loff_t from, -++static int part_read_oob(struct mtd_info *mtd, loff_mtd_t from, -+ struct mtd_oob_ops *ops) -+ { -+ struct mtd_part *part = PART(mtd); -+@@ -109,8 +109,8 @@ -+ return res; -+ } -+ -+-static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, -+- size_t *retlen, u_char *buf) -++static int part_read_user_prot_reg (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, -++ size_mtd_t *retlen, u_char *buf) -+ { -+ struct mtd_part *part = PART(mtd); -+ return part->master->read_user_prot_reg (part->master, from, -+@@ -118,14 +118,14 @@ -+ } -+ -+ static int part_get_user_prot_info (struct mtd_info *mtd, -+- struct otp_info *buf, size_t len) -++ struct otp_info *buf, size_mtd_t len) -+ { -+ struct mtd_part *part = PART(mtd); -+ return part->master->get_user_prot_info (part->master, buf, len); -+ } -+ -+-static int part_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, -+- size_t *retlen, u_char *buf) -++static int part_read_fact_prot_reg (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, -++ size_mtd_t *retlen, u_char *buf) -+ { -+ struct mtd_part *part = PART(mtd); -+ return part->master->read_fact_prot_reg (part->master, from, -+@@ -133,14 +133,14 @@ -+ } -+ -+ static int part_get_fact_prot_info (struct mtd_info *mtd, -+- struct otp_info *buf, size_t len) -++ struct otp_info *buf, size_mtd_t len) -+ { -+ struct mtd_part *part = PART(mtd); -+ return part->master->get_fact_prot_info (part->master, buf, len); -+ } -+ -+-static int part_write (struct mtd_info *mtd, loff_t to, size_t len, -+- size_t *retlen, const u_char *buf) -++static int part_write (struct mtd_info *mtd, loff_mtd_t to, size_mtd_t len, -++ size_mtd_t *retlen, const u_char *buf) -+ { -+ struct mtd_part *part = PART(mtd); -+ if (!(mtd->flags & MTD_WRITEABLE)) -+@@ -153,7 +153,7 @@ -+ len, retlen, buf); -+ } -+ -+-static int part_write_oob(struct mtd_info *mtd, loff_t to, -++static int part_write_oob(struct mtd_info *mtd, loff_mtd_t to, -+ struct mtd_oob_ops *ops) -+ { -+ struct mtd_part *part = PART(mtd); -+@@ -168,22 +168,22 @@ -+ return part->master->write_oob(part->master, to + part->offset, ops); -+ } -+ -+-static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, -+- size_t *retlen, u_char *buf) -++static int part_write_user_prot_reg (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, -++ size_mtd_t *retlen, u_char *buf) -+ { -+ struct mtd_part *part = PART(mtd); -+ return part->master->write_user_prot_reg (part->master, from, -+ len, retlen, buf); -+ } -+ -+-static int part_lock_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len) -++static int part_lock_user_prot_reg (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len) -+ { -+ struct mtd_part *part = PART(mtd); -+ return part->master->lock_user_prot_reg (part->master, from, len); -+ } -+ -+ static int part_writev (struct mtd_info *mtd, const struct kvec *vecs, -+- unsigned long count, loff_t to, size_t *retlen) -++ unsigned long count, loff_mtd_t to, size_mtd_t *retlen) -+ { -+ struct mtd_part *part = PART(mtd); -+ if (!(mtd->flags & MTD_WRITEABLE)) -+@@ -224,7 +224,7 @@ -+ } -+ EXPORT_SYMBOL_GPL(mtd_erase_callback); -+ -+-static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len) -++static int part_lock (struct mtd_info *mtd, loff_mtd_t ofs, size_mtd_t len) -+ { -+ struct mtd_part *part = PART(mtd); -+ if ((len + ofs) > mtd->size) -+@@ -232,7 +232,7 @@ -+ return part->master->lock(part->master, ofs + part->offset, len); -+ } -+ -+-static int part_unlock (struct mtd_info *mtd, loff_t ofs, size_t len) -++static int part_unlock (struct mtd_info *mtd, loff_mtd_t ofs, size_mtd_t len) -+ { -+ struct mtd_part *part = PART(mtd); -+ if ((len + ofs) > mtd->size) -+@@ -258,7 +258,7 @@ -+ part->master->resume(part->master); -+ } -+ -+-static int part_block_isbad (struct mtd_info *mtd, loff_t ofs) -++static int part_block_isbad (struct mtd_info *mtd, loff_mtd_t ofs) -+ { -+ struct mtd_part *part = PART(mtd); -+ if (ofs >= mtd->size) -+@@ -267,7 +267,7 @@ -+ return part->master->block_isbad(part->master, ofs); -+ } -+ -+-static int part_block_markbad (struct mtd_info *mtd, loff_t ofs) -++static int part_block_markbad (struct mtd_info *mtd, loff_mtd_t ofs) -+ { -+ struct mtd_part *part = PART(mtd); -+ int res; -+diff -urN linux-2.6.24.7.old/drivers/mtd/nand/Kconfig linux-2.6.24.7/drivers/mtd/nand/Kconfig -+--- linux-2.6.24.7.old/drivers/mtd/nand/Kconfig 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/nand/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ # drivers/mtd/nand/Kconfig -+-# $Id: Kconfig,v 1.35 2005/11/07 11:14:30 gleixner Exp $ -++# $Id: Kconfig,v 1.3 2008-07-04 08:05:48 lhhuang Exp $ -+ -+ menuconfig MTD_NAND -+ tristate "NAND Device Support" -+@@ -306,4 +306,127 @@ -+ These two (and possibly other) Alauda-based cardreaders for -+ SmartMedia and xD allow raw flash access. -+ -++config MTD_NAND_JZ4730 -++ tristate "Support NAND Flash device on Jz4730 board" -++ depends on SOC_JZ4730 -++ help -++ Support NAND Flash device on Jz4730 board -++ -++config MTD_NAND_JZ4740 -++ tristate "Support NAND Flash device on Jz4740 board" -++ depends on SOC_JZ4740 -++ help -++ Support NAND Flash device on Jz4740 board -++ -++config MTD_NAND_JZ4750 -++ tristate "Support NAND Flash device on Jz4750 board" -++ depends on SOC_JZ4750 || SOC_JZ4750D -++ help -++ Support NAND Flash device on Jz4750 board -++ -++config MTD_NAND_CS2 -++ depends on MTD_NAND_JZ4740 || MTD_NAND_JZ4750 -++ bool 'Use NAND on CS2_N of JZSOC' -++ default n -++ -++config MTD_NAND_CS3 -++ depends on MTD_NAND_JZ4740 || MTD_NAND_JZ4750 -++ bool 'Use NAND on CS3_N of JZSOC' -++ default n -++ -++config MTD_NAND_CS4 -++ depends on MTD_NAND_JZ4740 || MTD_NAND_JZ4750 -++ bool 'Use NAND on CS4_N of JZSOC' -++ default n -++ -++config MTD_NAND_MULTI_PLANE -++ depends on MTD_NAND_JZ4730 || MTD_NAND_JZ4740 || MTD_NAND_JZ4750 -++ bool 'Use multiple planes if the NAND supports' -++ default y -++ help -++ It is just supported on jz4740 now. -++ -++if MTD_NAND_JZ4740 || MTD_NAND_JZ4730 || MTD_NAND_JZ4750 -++choice -++ prompt "ECC type" -++ default CONFIG_MTD_SW_HM_ECC -++ -++config MTD_HW_HM_ECC -++ depends on MTD_NAND_JZ4740 || MTD_NAND_JZ4730 -++ bool 'Select hardware HM ECC' -++ -++config MTD_SW_HM_ECC -++ bool 'Select software HM ECC' -++ -++config MTD_HW_RS_ECC -++ depends on MTD_NAND_JZ4740 -++ bool 'Select hardware RS ECC' -++ -++config MTD_HW_BCH_ECC -++ depends on MTD_NAND_JZ4750 -++ bool 'Select hardware BCH ECC' -++endchoice -++ -++choice -++ prompt "4 bit or 8 bit BCH ecc" -++ depends on MTD_HW_BCH_ECC -++ default CONFIG_MTD_HW_BCH_4BIT -++ -++config MTD_HW_BCH_4BIT -++ bool '4 bit' -++ -++config MTD_HW_BCH_8BIT -++ bool '8 bit' -++ -++endchoice -++ -++config MTD_NAND_DMA -++ depends on MTD_HW_BCH_ECC -++ bool 'Use DMA mode' -++ help -++ This enables using DMA for reading and writing NAND flash, if not selected, -++ then CPU mode is used. -++ -++config MTD_NAND_DMABUF -++ depends on MTD_NAND_DMA -++ bool 'use DMA buffer in NAND driver' -++ help -++ It's better to say NO. If saying yes, DMA buffers will be allocated for -++ NAND reading and writing in NAND driver instead of upper layer. It's -++ slower. Just usable on CS1_N now. By saying NO, upper buffers will be -++ used as DMA buffer. It's faster, but kmalloc instead of vmalloc is required. -++endif -++ -++config MTD_MTDBLOCK_WRITE_VERIFY_ENABLE -++ bool "MTDBLOCK write verify enable" -++ default n -++ help -++ This will enable the write verification, which will read back data to check -++ after doing a write opetaion. -++ -++ It will be used by the JZ mtdblock driver (mtdblock-jz.c). -++ -++config MTD_OOB_COPIES -++ int "how many copies of the fs info in the oob area" -++ default 3 -++ range 0 128 -++ depends on MTD -++ help -++ This defines the copies of the fs info in the oob area inside a block. -++ Value ranges from 0 to (pages_per_block - 1). -++ -++ It will be used by the JZ mtdblock driver (mtdblock-jz.c). -++ -++config MTD_BADBLOCK_FLAG_PAGE -++ int "which page inside a block will store the badblock mark" -++ default 0 -++ range 0 127 -++ depends on MTD -++ help -++ This defines which page of a block will store the badblock mark. -++ Value ranges from 0 to (pages_per_block - 1). -++ -++ Old SLC NANDs store the badblock mark in the first page of a block, but -++ most modern MLC NANDs store it in the last page of a block. -++ -+ endif # MTD_NAND -+diff -urN linux-2.6.24.7.old/drivers/mtd/nand/Makefile linux-2.6.24.7/drivers/mtd/nand/Makefile -+--- linux-2.6.24.7.old/drivers/mtd/nand/Makefile 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/nand/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -1,7 +1,7 @@ -+ # -+ # linux/drivers/nand/Makefile -+ # -+-# $Id: Makefile.common,v 1.15 2004/11/26 12:28:22 dedekind Exp $ -++# $Id: Makefile,v 1.2 2008-07-04 08:07:45 lhhuang Exp $ -+ -+ obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o -+ obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o -+@@ -29,5 +29,8 @@ -+ obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o -+ obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o -+ obj-$(CONFIG_MTD_ALAUDA) += alauda.o -++obj-$(CONFIG_MTD_NAND_JZ4730) += jz4730_nand.o -++obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o -++obj-$(CONFIG_MTD_NAND_JZ4750) += jz4750_nand.o -+ -+ nand-objs := nand_base.o nand_bbt.o -+diff -urN linux-2.6.24.7.old/drivers/mtd/nand/jz4730_nand.c linux-2.6.24.7/drivers/mtd/nand/jz4730_nand.c -+--- linux-2.6.24.7.old/drivers/mtd/nand/jz4730_nand.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/nand/jz4730_nand.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,367 @@ -++/* -++ * linux/drivers/mtd/nand/jz4730_nand.c -++ * -++ * Copyright (c) 2005 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Ingenic JZ4730 NAND driver -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ */ -++ -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#define NAND_DATA_PORT 0xB4000000 /* read-write area */ -++#define __nand_ecc() (REG_EMC_NFECC & 0x00ffffff) -++#define __nand_ecc_enable() (REG_EMC_NFCSR |= EMC_NFCSR_ECCE | EMC_NFCSR_ERST) -++#define __nand_ecc_disable() (REG_EMC_NFCSR &= ~EMC_NFCSR_ECCE) -++ -++/* -++ * MTD structure for JzSOC board -++ */ -++static struct mtd_info *jz_mtd = NULL; -++ -++/* -++ * Define partitions for flash devices -++ */ -++#ifdef CONFIG_JZ4730_PMP -++static struct mtd_partition partition_info[] = { -++ { name: "NAND BOOT partition", -++ offset: 0 * 0x100000, -++ size: 4 * 0x100000 }, -++ { name: "NAND KERNEL partition", -++ offset: 4 * 0x100000, -++ size: 4 * 0x100000 }, -++ { name: "NAND ROOTFS partition", -++ offset: 8 * 0x100000, -++ size: 56 * 0x100000 }, -++ { name: "NAND SSFDC partition", -++ offset: 64 * 0x100000, -++ size: 64 * 0x100000 }, -++}; -++ -++/* Define max reserved bad blocks for each partition. -++ * This is used by the mtdblock-jz.c NAND FTL driver only. -++ * -++ * The NAND FTL driver reserves some good blocks which can't be -++ * seen by the upper layer. When the bad block number of a partition -++ * exceeds the max reserved blocks, then there is no more reserved -++ * good blocks to be used by the NAND FTL driver when another bad -++ * block generated. -++ */ -++static int partition_reserved_badblocks[]= { -++ 2, /* reserved blocks of mtd0 */ -++ 2, /* reserved blocks of mtd1 */ -++ 10, /* reserved blocks of mtd2 */ -++ 10}; /* reserved blocks of mtd3 */ -++#elif CONFIG_JZ4730_PMPV1 -++static struct mtd_partition partition_info[] = { -++ { name: "NAND ROOTFS partition", -++ offset: 3 * 0x100000, -++ size: (32-3) * 0x100000 }, -++ { name: "NAND DATAFS partition", -++ offset: 32 * 0x100000, -++ size: 32 * 0x100000 }, -++}; -++static int partition_reserved_badblocks[]={ -++ 10, -++ 10}; -++#else -++static struct mtd_partition partition_info[] = { -++ { name: "NAND ROOTFS partition", -++ offset: 3 * 0x100000, -++ size: (128-3) * 0x100000 }, -++}; -++static int partition_reserved_badblocks[]={ -++ 20}; -++#endif -++ -++/*------------------------------------------------------------------------- -++ * Following three functions are exported and used by the mtdblock-jz.c -++ * NAND FTL driver only. -++ */ -++ -++unsigned short get_mtdblock_write_verify_enable(void) -++{ -++#ifdef CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE -++ return 1; -++#endif -++ return 0; -++} -++EXPORT_SYMBOL(get_mtdblock_write_verify_enable); -++ -++unsigned short get_mtdblock_oob_copies(void) -++{ -++ return CONFIG_MTD_OOB_COPIES; -++} -++EXPORT_SYMBOL(get_mtdblock_oob_copies); -++ -++int *get_jz_badblock_table(void) -++{ -++ return partition_reserved_badblocks; -++} -++EXPORT_SYMBOL(get_jz_badblock_table); -++ -++/*-------------------------------------------------------------------------*/ -++ -++static void jz_hwcontrol(struct mtd_info *mtd, int dat, -++ unsigned int ctrl) -++{ -++ struct nand_chip *this = (struct nand_chip *)(mtd->priv); -++ unsigned int nandaddr = (unsigned int)this->IO_ADDR_W; -++ -++ if (ctrl & NAND_CTRL_CHANGE) { -++ if ( ctrl & NAND_ALE ) -++ nandaddr = (unsigned int)((unsigned long)(this->IO_ADDR_W) | 0x00080000); -++ else -++ nandaddr = (unsigned int)((unsigned long)(this->IO_ADDR_W) & ~0x00080000); -++ -++ if ( ctrl & NAND_CLE ) -++ nandaddr = nandaddr | 0x00040000; -++ else -++ nandaddr = nandaddr & ~0x00040000; -++ if ( ctrl & NAND_NCE ) -++ REG_EMC_NFCSR |= EMC_NFCSR_FCE; -++ else -++ REG_EMC_NFCSR &= ~EMC_NFCSR_FCE; -++ } -++ -++ this->IO_ADDR_W = (void __iomem *)nandaddr; -++ if (dat != NAND_CMD_NONE) -++ writeb(dat , this->IO_ADDR_W); -++ -++} -++ -++static int jz_device_ready(struct mtd_info *mtd) -++{ -++ int ready; -++ ready = (REG_EMC_NFCSR & EMC_NFCSR_RB) ? 1 : 0; -++ return ready; -++} -++ -++/* -++ * EMC setup -++ */ -++static void jz_device_setup(void) -++{ -++ /* Set NFE bit */ -++ REG_EMC_NFCSR |= EMC_NFCSR_NFE; -++} -++ -++static void jzsoc_nand_enable_hwecc(struct mtd_info* mtd, int mode) -++{ -++ __nand_ecc_enable(); -++} -++ -++static int jzsoc_nand_calculate_ecc(struct mtd_info* mtd, const u_char* dat, -++ u_char* ecc_code) -++{ -++ unsigned int calc_ecc; -++ unsigned char *tmp; -++ -++ __nand_ecc_disable(); -++ -++ calc_ecc = ~(__nand_ecc()) | 0x00030000; -++ -++ tmp = (unsigned char *)&calc_ecc; -++ -++ ecc_code[0] = tmp[1]; -++ ecc_code[1] = tmp[0]; -++ ecc_code[2] = tmp[2]; -++ -++ return 0; -++} -++ -++/* ECC handling functions */ -++ -++static int jzsoc_nand_correct_data(struct mtd_info *mtd, u_char *dat, -++ u_char *read_ecc, u_char *calc_ecc) -++{ -++ u_char a, b, c, d1, d2, d3, add, bit, i; -++ -++ /* Do error detection */ -++ d1 = calc_ecc[0] ^ read_ecc[0]; -++ d2 = calc_ecc[1] ^ read_ecc[1]; -++ d3 = calc_ecc[2] ^ read_ecc[2]; -++ -++ if ((d1 | d2 | d3) == 0) { -++ /* No errors */ -++ return 0; -++ } -++ else { -++ a = (d1 ^ (d1 >> 1)) & 0x55; -++ b = (d2 ^ (d2 >> 1)) & 0x55; -++ c = (d3 ^ (d3 >> 1)) & 0x54; -++ -++ /* Found and will correct single bit error in the data */ -++ if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { -++ c = 0x80; -++ add = 0; -++ a = 0x80; -++ for (i=0; i<4; i++) { -++ if (d1 & c) -++ add |= a; -++ c >>= 2; -++ a >>= 1; -++ } -++ c = 0x80; -++ for (i=0; i<4; i++) { -++ if (d2 & c) -++ add |= a; -++ c >>= 2; -++ a >>= 1; -++ } -++ bit = 0; -++ b = 0x04; -++ c = 0x80; -++ for (i=0; i<3; i++) { -++ if (d3 & c) -++ bit |= b; -++ c >>= 2; -++ b >>= 1; -++ } -++ b = 0x01; -++ a = dat[add]; -++ a ^= (b << bit); -++ dat[add] = a; -++ return 0; -++ } -++ else { -++ i = 0; -++ while (d1) { -++ if (d1 & 0x01) -++ ++i; -++ d1 >>= 1; -++ } -++ while (d2) { -++ if (d2 & 0x01) -++ ++i; -++ d2 >>= 1; -++ } -++ while (d3) { -++ if (d3 & 0x01) -++ ++i; -++ d3 >>= 1; -++ } -++ if (i == 1) { -++ /* ECC Code Error Correction */ -++ read_ecc[0] = calc_ecc[0]; -++ read_ecc[1] = calc_ecc[1]; -++ read_ecc[2] = calc_ecc[2]; -++ return 0; -++ } -++ else { -++ /* Uncorrectable Error */ -++ printk("uncorrectable ECC error\n"); -++ return -1; -++ } -++ } -++ } -++ -++ /* Should never happen */ -++ return -1; -++} -++ -++ -++/* -++ * Main initialization routine -++ */ -++int __init jznand_init(void) -++{ -++ struct nand_chip *this; -++ int nr_partitions; -++ -++ /* Allocate memory for MTD device structure and private data */ -++ jz_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), -++ GFP_KERNEL); -++ if (!jz_mtd) { -++ printk ("Unable to allocate JzSOC NAND MTD device structure.\n"); -++ return -ENOMEM; -++ } -++ -++ /* Get pointer to private data */ -++ this = (struct nand_chip *) (&jz_mtd[1]); -++ -++ /* Initialize structures */ -++ memset((char *) jz_mtd, 0, sizeof(struct mtd_info)); -++ memset((char *) this, 0, sizeof(struct nand_chip)); -++ -++ /* Link the private data with the MTD structure */ -++ jz_mtd->priv = this; -++ -++ /* Set & initialize NAND Flash controller */ -++ jz_device_setup(); -++ -++ /* Set address of NAND IO lines */ -++ this->IO_ADDR_R = (void __iomem *) NAND_DATA_PORT; -++ this->IO_ADDR_W = (void __iomem *) NAND_DATA_PORT; -++ this->cmd_ctrl = jz_hwcontrol; -++ this->dev_ready = jz_device_ready; -++ -++#ifdef CONFIG_MTD_HW_HM_ECC -++ this->ecc.calculate = jzsoc_nand_calculate_ecc; -++ this->ecc.correct = jzsoc_nand_correct_data; -++ this->ecc.hwctl = jzsoc_nand_enable_hwecc; -++ this->ecc.mode = NAND_ECC_HW; -++ this->ecc.size = 256; -++ this->ecc.bytes = 3; -++ -++#endif -++ -++#ifdef CONFIG_MTD_SW_HM_ECC -++ this->eccmode = NAND_ECC_SOFT; -++#endif -++ -++ /* 20 us command delay time */ -++ this->chip_delay = 20; -++ -++ /* Scan to find existance of the device */ -++ if (nand_scan(jz_mtd, 1)) { -++ kfree (jz_mtd); -++ return -ENXIO; -++ } -++ -++ /* Register the partitions */ -++ nr_partitions = sizeof(partition_info) / sizeof(struct mtd_partition); -++ printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nr_partitions, jz_mtd->name); -++ add_mtd_partitions(jz_mtd, partition_info, nr_partitions); -++ -++ return 0; -++} -++module_init(jznand_init); -++ -++/* -++ * Clean up routine -++ */ -++#ifdef MODULE -++static void __exit jznand_cleanup(void) -++{ -++ struct nand_chip *this = (struct nand_chip *) &jz_mtd[1]; -++ -++ /* Unregister partitions */ -++ del_mtd_partitions(jz_mtd); -++ -++ /* Unregister the device */ -++ del_mtd_device (jz_mtd); -++ -++ /* Free internal data buffers */ -++ kfree (this->data_buf); -++ -++ /* Free the MTD device structure */ -++ kfree (jz_mtd); -++} -++module_exit(jznand_cleanup); -++#endif -+diff -urN linux-2.6.24.7.old/drivers/mtd/nand/jz4740_nand.c linux-2.6.24.7/drivers/mtd/nand/jz4740_nand.c -+--- linux-2.6.24.7.old/drivers/mtd/nand/jz4740_nand.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/nand/jz4740_nand.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1037 @@ -++/* -++ * linux/drivers/mtd/nand/jz4740_nand.c -++ * -++ * Copyright (c) 2005 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Ingenic JZ4740 NAND driver -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#define NAND_DATA_PORT1 0xB8000000 /* read-write area in static bank 1 */ -++#define NAND_DATA_PORT2 0xB4000000 /* read-write area in static bank 2 */ -++#define NAND_DATA_PORT3 0xAC000000 /* read-write area in static bank 3 */ -++#define NAND_DATA_PORT4 0xA8000000 /* read-write area in static bank 4 */ -++ -++#define PAR_SIZE 9 -++ -++#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1) -++#define __nand_disable() (REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1) -++ -++#define __nand_ecc_enable() (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST ) -++#define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE) -++ -++#define __nand_select_hm_ecc() (REG_EMC_NFECR &= ~EMC_NFECR_RS ) -++#define __nand_select_rs_ecc() (REG_EMC_NFECR |= EMC_NFECR_RS) -++ -++#define __nand_read_hm_ecc() (REG_EMC_NFECC & 0x00ffffff) -++ -++#define __nand_rs_ecc_encoding() (REG_EMC_NFECR |= EMC_NFECR_RS_ENCODING) -++#define __nand_rs_ecc_decoding() (REG_EMC_NFECR &= ~EMC_NFECR_RS_ENCODING) -++#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF)) -++#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF)) -++ -++/* -++ * MTD structure for JzSOC board -++ */ -++static struct mtd_info *jz_mtd = NULL; -++extern struct mtd_info *jz_mtd1; -++extern char all_use_planes; -++extern int global_page; /* for two-plane operations */ -++ -++/* -++ * Define partitions for flash devices -++ */ -++#ifdef CONFIG_JZ4740_PAVO -++static struct mtd_partition partition_info[] = { -++ { name: "NAND BOOT partition", -++ offset: 0 * 0x100000, -++ size: 4 * 0x100000, -++ use_planes: 0 }, -++ { name: "NAND KERNEL partition", -++ offset: 4 * 0x100000, -++ size: 4 * 0x100000, -++ use_planes: 0 }, -++ { name: "NAND ROOTFS partition", -++ offset: 8 * 0x100000, -++ size: 120 * 0x100000, -++ use_planes: 0 }, -++ { name: "NAND DATA1 partition", -++ offset: 128 * 0x100000, -++ size: 128 * 0x100000, -++ use_planes: 1 }, -++ { name: "NAND DATA2 partition", -++ offset: 256 * 0x100000, -++ size: 256 * 0x100000, -++ use_planes: 1 }, -++ { name: "NAND VFAT partition", -++ offset: 512 * 0x100000, -++ size: 512 * 0x100000, -++ use_planes: 1 }, -++}; -++ -++ -++/* Define max reserved bad blocks for each partition. -++ * This is used by the mtdblock-jz.c NAND FTL driver only. -++ * -++ * The NAND FTL driver reserves some good blocks which can't be -++ * seen by the upper layer. When the bad block number of a partition -++ * exceeds the max reserved blocks, then there is no more reserved -++ * good blocks to be used by the NAND FTL driver when another bad -++ * block generated. -++ */ -++static int partition_reserved_badblocks[] = { -++ 2, /* reserved blocks of mtd0 */ -++ 2, /* reserved blocks of mtd1 */ -++ 10, /* reserved blocks of mtd2 */ -++ 10, /* reserved blocks of mtd3 */ -++ 20, /* reserved blocks of mtd4 */ -++ 20}; /* reserved blocks of mtd5 */ -++#endif /* CONFIG_JZ4740_PAVO */ -++ -++#ifdef CONFIG_JZ4740_LEO -++static struct mtd_partition partition_info[] = { -++ { name: "NAND BOOT partition", -++ offset: 0 * 0x100000, -++ size: 4 * 0x100000 }, -++ { name: "NAND KERNEL partition", -++ offset: 4 * 0x100000, -++ size: 4 * 0x100000 }, -++ { name: "NAND ROOTFS partition", -++ offset: 8 * 0x100000, -++ size: 56 * 0x100000 }, -++ { name: "NAND VFAT partition", -++ offset: 64 * 0x100000, -++ size: 64 * 0x100000 }, -++}; -++static int partition_reserved_badblocks[] = { -++ 2, /* reserved blocks of mtd0 */ -++ 2, /* reserved blocks of mtd1 */ -++ 10, /* reserved blocks of mtd2 */ -++ 10}; /* reserved blocks of mtd3 */ -++#endif /* CONFIG_JZ4740_LEO */ -++ -++#ifdef CONFIG_JZ4740_LYRA -++static struct mtd_partition partition_info[] = { -++ { name: "NAND BOOT partition", -++ offset: 0 * 0x100000, -++ size: 4 * 0x100000 }, -++ { name: "NAND KERNEL partition", -++ offset: 4 * 0x100000, -++ size: 4 * 0x100000 }, -++ { name: "NAND ROOTFS partition", -++ offset: 8 * 0x100000, -++ size: 120 * 0x100000 }, -++ { name: "NAND DATA1 partition", -++ offset: 128 * 0x100000, -++ size: 128 * 0x100000 }, -++ { name: "NAND DATA2 partition", -++ offset: 256 * 0x100000, -++ size: 256 * 0x100000 }, -++ { name: "NAND VFAT partition", -++ offset: 512 * 0x100000, -++ size: 512 * 0x100000 }, -++}; -++ -++/* Define max reserved bad blocks for each partition. -++ * This is used by the mtdblock-jz.c NAND FTL driver only. -++ * -++ * The NAND FTL driver reserves some good blocks which can't be -++ * seen by the upper layer. When the bad block number of a partition -++ * exceeds the max reserved blocks, then there is no more reserved -++ * good blocks to be used by the NAND FTL driver when another bad -++ * block generated. -++ */ -++static int partition_reserved_badblocks[] = { -++ 2, /* reserved blocks of mtd0 */ -++ 2, /* reserved blocks of mtd1 */ -++ 10, /* reserved blocks of mtd2 */ -++ 10, /* reserved blocks of mtd3 */ -++ 20, /* reserved blocks of mtd4 */ -++ 20}; /* reserved blocks of mtd5 */ -++#endif /* CONFIG_JZ4740_LYRA */ -++ -++#ifdef CONFIG_JZ4725_DIPPER -++static struct mtd_partition partition_info[] = { -++ { name: "NAND BOOT partition", -++ offset: 0 * 0x100000, -++ size: 4 * 0x100000 }, -++ { name: "NAND KERNEL partition", -++ offset: 4 * 0x100000, -++ size: 4 * 0x100000 }, -++ { name: "NAND ROOTFS partition", -++ offset: 8 * 0x100000, -++ size: 56 * 0x100000 }, -++ { name: "NAND VFAT partition", -++ offset: 64 * 0x100000, -++ size: 64 * 0x100000 }, -++}; -++ -++/* Define max reserved bad blocks for each partition. -++ * This is used by the mtdblock-jz.c NAND FTL driver only. -++ * -++ * The NAND FTL driver reserves some good blocks which can't be -++ * seen by the upper layer. When the bad block number of a partition -++ * exceeds the max reserved blocks, then there is no more reserved -++ * good blocks to be used by the NAND FTL driver when another bad -++ * block generated. -++ */ -++static int partition_reserved_badblocks[] = { -++ 2, /* reserved blocks of mtd0 */ -++ 2, /* reserved blocks of mtd1 */ -++ 10, /* reserved blocks of mtd2 */ -++ 10}; /* reserved blocks of mtd3 */ -++#endif /* CONFIG_JZ4740_DIPPER */ -++ -++#ifdef CONFIG_JZ4720_VIRGO -++static struct mtd_partition partition_info[] = { -++ { name: "NAND BOOT partition", -++ offset: 0 * 0x100000, -++ size: 4 * 0x100000 }, -++ { name: "NAND KERNEL partition", -++ offset: 4 * 0x100000, -++ size: 4 * 0x100000 }, -++ { name: "NAND ROOTFS partition", -++ offset: 8 * 0x100000, -++ size: 120 * 0x100000 }, -++ { name: "NAND DATA1 partition", -++ offset: 128 * 0x100000, -++ size: 128 * 0x100000 }, -++ { name: "NAND DATA2 partition", -++ offset: 256 * 0x100000, -++ size: 256 * 0x100000 }, -++ { name: "NAND VFAT partition", -++ offset: 512 * 0x100000, -++ size: 512 * 0x100000 }, -++}; -++ -++ -++/* Define max reserved bad blocks for each partition. -++ * This is used by the mtdblock-jz.c NAND FTL driver only. -++ * -++ * The NAND FTL driver reserves some good blocks which can't be -++ * seen by the upper layer. When the bad block number of a partition -++ * exceeds the max reserved blocks, then there is no more reserved -++ * good blocks to be used by the NAND FTL driver when another bad -++ * block generated. -++ */ -++static int partition_reserved_badblocks[] = { -++ 2, /* reserved blocks of mtd0 */ -++ 2, /* reserved blocks of mtd1 */ -++ 10, /* reserved blocks of mtd2 */ -++ 10, /* reserved blocks of mtd3 */ -++ 20, /* reserved blocks of mtd4 */ -++ 20}; /* reserved blocks of mtd5 */ -++#endif /* CONFIG_JZ4720_VIRGO */ -++/*------------------------------------------------------------------------- -++ * Following three functions are exported and used by the mtdblock-jz.c -++ * NAND FTL driver only. -++ */ -++ -++unsigned short get_mtdblock_write_verify_enable(void) -++{ -++#ifdef CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE -++ return 1; -++#endif -++ return 0; -++} -++EXPORT_SYMBOL(get_mtdblock_write_verify_enable); -++ -++unsigned short get_mtdblock_oob_copies(void) -++{ -++ return CONFIG_MTD_OOB_COPIES; -++} -++EXPORT_SYMBOL(get_mtdblock_oob_copies); -++ -++int *get_jz_badblock_table(void) -++{ -++ return partition_reserved_badblocks; -++} -++EXPORT_SYMBOL(get_jz_badblock_table); -++ -++/*-------------------------------------------------------------------------*/ -++ -++static void jz_hwcontrol(struct mtd_info *mtd, int dat, -++ unsigned int ctrl) -++{ -++ struct nand_chip *this = (struct nand_chip *)(mtd->priv); -++ unsigned int nandaddr = (unsigned int)this->IO_ADDR_W; -++ extern u8 nand_nce; /* in nand_base.c, indicates which chip select is used for current nand chip */ -++ -++ if (ctrl & NAND_CTRL_CHANGE) { -++ if (ctrl & NAND_NCE) { -++ switch (nand_nce) { -++ case NAND_NCE1: -++ this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT1; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; -++ REG_EMC_NFCSR |= EMC_NFCSR_NFCE1; -++ break; -++ case NAND_NCE2: -++ this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT2; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; -++ REG_EMC_NFCSR |= EMC_NFCSR_NFCE2; -++ break; -++ case NAND_NCE3: -++ this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT3; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; -++ REG_EMC_NFCSR |= EMC_NFCSR_NFCE3; -++ break; -++ case NAND_NCE4: -++ this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT4; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; -++ REG_EMC_NFCSR |= EMC_NFCSR_NFCE4; -++ break; -++ default: -++ printk("error: no nand_nce 0x%x\n",nand_nce); -++ break; -++ } -++ } else { -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; -++ } -++ -++ if ( ctrl & NAND_ALE ) -++ nandaddr = (unsigned int)((unsigned long)(this->IO_ADDR_W) | 0x00010000); -++ else -++ nandaddr = (unsigned int)((unsigned long)(this->IO_ADDR_W) & ~0x00010000); -++ -++ if ( ctrl & NAND_CLE ) -++ nandaddr = nandaddr | 0x00008000; -++ else -++ nandaddr = nandaddr & ~0x00008000; -++ } -++ -++ this->IO_ADDR_W = (void __iomem *)nandaddr; -++ if (dat != NAND_CMD_NONE) -++ writeb(dat, this->IO_ADDR_W); -++} -++ -++static int jz_device_ready(struct mtd_info *mtd) -++{ -++ int ready, wait = 10; -++ while (wait--); -++ ready = __gpio_get_pin(94); -++ return ready; -++} -++ -++/* -++ * EMC setup -++ */ -++static void jz_device_setup(void) -++{ -++// PORT 0: -++// ... -++// PORT 1: -++// PIN/BIT N FUNC0 FUNC1 -++// 25 CS1# - -++// 26 CS2# - -++// 27 CS3# - -++// 28 CS4# - -++#define GPIO_CS2_N (32+26) -++#define GPIO_CS3_N (32+27) -++#define GPIO_CS4_N (32+28) -++#define SMCR_VAL 0x0d221200 -++ -++ /* Set NFE bit */ -++ REG_EMC_NFCSR |= EMC_NFCSR_NFE1; -++ /* Read/Write timings */ -++ REG_EMC_SMCR1 = SMCR_VAL; -++ -++#if defined(CONFIG_MTD_NAND_CS2) -++ /* Set CS2# pin as function 0 */ -++ __gpio_as_func0(GPIO_CS2_N); -++ REG_EMC_NFCSR |= EMC_NFCSR_NFE2; -++ REG_EMC_SMCR2 = SMCR_VAL; -++#endif -++ -++#if defined(CONFIG_MTD_NAND_CS3) -++ __gpio_as_func0(GPIO_CS3_N); -++ REG_EMC_NFCSR |= EMC_NFCSR_NFE3; -++ REG_EMC_SMCR3 = SMCR_VAL; -++#endif -++ -++#if defined(CONFIG_MTD_NAND_CS4) -++ __gpio_as_func0(GPIO_CS4_N); -++ REG_EMC_NFCSR |= EMC_NFCSR_NFE4; -++ REG_EMC_SMCR4 = SMCR_VAL; -++#endif -++} -++ -++#ifdef CONFIG_MTD_HW_HM_ECC -++ -++static int jzsoc_nand_calculate_hm_ecc(struct mtd_info* mtd, -++ const u_char* dat, u_char* ecc_code) -++{ -++ unsigned int calc_ecc; -++ unsigned char *tmp; -++ -++ __nand_ecc_disable(); -++ -++ calc_ecc = ~(__nand_read_hm_ecc()) | 0x00030000; -++ -++ tmp = (unsigned char *)&calc_ecc; -++ //adjust eccbytes order for compatible with software ecc -++ ecc_code[0] = tmp[1]; -++ ecc_code[1] = tmp[0]; -++ ecc_code[2] = tmp[2]; -++ -++ return 0; -++} -++ -++static void jzsoc_nand_enable_hm_hwecc(struct mtd_info* mtd, int mode) -++{ -++ __nand_ecc_enable(); -++ __nand_select_hm_ecc(); -++} -++ -++static int jzsoc_nand_hm_correct_data(struct mtd_info *mtd, u_char *dat, -++ u_char *read_ecc, u_char *calc_ecc) -++{ -++ u_char a, b, c, d1, d2, d3, add, bit, i; -++ -++ /* Do error detection */ -++ d1 = calc_ecc[0] ^ read_ecc[0]; -++ d2 = calc_ecc[1] ^ read_ecc[1]; -++ d3 = calc_ecc[2] ^ read_ecc[2]; -++ -++ if ((d1 | d2 | d3) == 0) { -++ /* No errors */ -++ return 0; -++ } -++ else { -++ a = (d1 ^ (d1 >> 1)) & 0x55; -++ b = (d2 ^ (d2 >> 1)) & 0x55; -++ c = (d3 ^ (d3 >> 1)) & 0x54; -++ -++ /* Found and will correct single bit error in the data */ -++ if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { -++ c = 0x80; -++ add = 0; -++ a = 0x80; -++ for (i=0; i<4; i++) { -++ if (d1 & c) -++ add |= a; -++ c >>= 2; -++ a >>= 1; -++ } -++ c = 0x80; -++ for (i=0; i<4; i++) { -++ if (d2 & c) -++ add |= a; -++ c >>= 2; -++ a >>= 1; -++ } -++ bit = 0; -++ b = 0x04; -++ c = 0x80; -++ for (i=0; i<3; i++) { -++ if (d3 & c) -++ bit |= b; -++ c >>= 2; -++ b >>= 1; -++ } -++ b = 0x01; -++ a = dat[add]; -++ a ^= (b << bit); -++ dat[add] = a; -++ return 0; -++ } -++ else { -++ i = 0; -++ while (d1) { -++ if (d1 & 0x01) -++ ++i; -++ d1 >>= 1; -++ } -++ while (d2) { -++ if (d2 & 0x01) -++ ++i; -++ d2 >>= 1; -++ } -++ while (d3) { -++ if (d3 & 0x01) -++ ++i; -++ d3 >>= 1; -++ } -++ if (i == 1) { -++ /* ECC Code Error Correction */ -++ read_ecc[0] = calc_ecc[0]; -++ read_ecc[1] = calc_ecc[1]; -++ read_ecc[2] = calc_ecc[2]; -++ return 0; -++ } -++ else { -++ /* Uncorrectable Error */ -++ printk("NAND: uncorrectable ECC error\n"); -++ return -1; -++ } -++ } -++ } -++ -++ /* Should never happen */ -++ return -1; -++} -++ -++#endif /* CONFIG_MTD_HW_HM_ECC */ -++ -++#ifdef CONFIG_MTD_HW_RS_ECC -++ -++static void jzsoc_nand_enable_rs_hwecc(struct mtd_info* mtd, int mode) -++{ -++ REG_EMC_NFINTS = 0x0; -++ __nand_ecc_enable(); -++ __nand_select_rs_ecc(); -++ -++ if (mode == NAND_ECC_READ) -++ __nand_rs_ecc_decoding(); -++ -++ if (mode == NAND_ECC_WRITE) -++ __nand_rs_ecc_encoding(); -++} -++ -++static void jzsoc_rs_correct(unsigned char *dat, int idx, int mask) -++{ -++ int i; -++ -++ idx--; -++ -++ i = idx + (idx >> 3); -++ if (i >= 512) -++ return; -++ -++ mask <<= (idx & 0x7); -++ -++ dat[i] ^= mask & 0xff; -++ if (i < 511) -++ dat[i+1] ^= (mask >> 8) & 0xff; -++} -++ -++/* -++ * calc_ecc points to oob_buf for us -++ */ -++static int jzsoc_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat, -++ u_char *read_ecc, u_char *calc_ecc) -++{ -++ volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0; -++ short k; -++ u32 stat; -++ -++ /* Set PAR values */ -++ for (k = 0; k < PAR_SIZE; k++) { -++ *paraddr++ = read_ecc[k]; -++ } -++ -++ /* Set PRDY */ -++ REG_EMC_NFECR |= EMC_NFECR_PRDY; -++ -++ /* Wait for completion */ -++ __nand_ecc_decode_sync(); -++ __nand_ecc_disable(); -++ -++ /* Check decoding */ -++ stat = REG_EMC_NFINTS; -++ -++ if (stat & EMC_NFINTS_ERR) { -++ /* Error occurred */ -++ if (stat & EMC_NFINTS_UNCOR) { -++ printk("NAND: Uncorrectable ECC error\n"); -++ return -1; -++ } else { -++ u32 errcnt = (stat & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT; -++ switch (errcnt) { -++ case 4: -++ jzsoc_rs_correct(dat, (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT); -++ /* FALL-THROUGH */ -++ case 3: -++ jzsoc_rs_correct(dat, (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT); -++ /* FALL-THROUGH */ -++ case 2: -++ jzsoc_rs_correct(dat, (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT); -++ /* FALL-THROUGH */ -++ case 1: -++ jzsoc_rs_correct(dat, (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT); -++ return 0; -++ default: -++ break; -++ } -++ } -++ } -++ -++ return 0; -++} -++ -++static int jzsoc_nand_calculate_rs_ecc(struct mtd_info* mtd, const u_char* dat, -++ u_char* ecc_code) -++{ -++ volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0; -++ short i; -++ -++ __nand_ecc_encode_sync(); -++ __nand_ecc_disable(); -++ -++ for(i = 0; i < PAR_SIZE; i++) { -++ ecc_code[i] = *paraddr++; -++ } -++ -++ return 0; -++} -++ -++#endif /* CONFIG_MTD_HW_RS_ECC */ -++ -++/* Nand optimized functions */ -++static int dma_chan; -++static unsigned int dma_src_phys_addr, dma_dst_phys_addr; -++extern int jz_request_dma(int dev_id, const char *dev_str, -++ irqreturn_t (*irqhandler)(int, void *), -++ unsigned long irqflags, void *irq_dev_id); -++ -++static void dma_setup(void) -++{ -++ /* Request DMA channel and setup irq handler */ -++ dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", NULL, IRQF_DISABLED, NULL); -++ if (dma_chan < 0) { -++ printk("Setup irq for nand failed!\n"); -++ return; -++ } else -++ printk("Nand DMA request channel %d.\n",dma_chan); -++} -++ -++static void jz4740_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) -++{ -++ int i; -++ struct nand_chip *chip = mtd->priv; -++ -++ if ((len <= 32) || (len & 0xf) || ((u32)buf >= (u32)high_memory)) -++ { -++ for (i = 0; i < len; i++) -++ buf[i] = readb(chip->IO_ADDR_R); -++ } else { -++ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; -++ dma_src_phys_addr = CPHYSADDR(chip->IO_ADDR_R); -++ dma_dst_phys_addr = CPHYSADDR(buf); -++ dma_cache_inv((u32)buf, len); -++ REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr; -++ REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr; -++ REG_DMAC_DTCR(dma_chan) = len / 16; -++ REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_DAI | DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE; -++ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; -++ REG_DMAC_DMACR = DMAC_DMACR_DMAE; /* global DMA enable bit */ -++ -++ while(!(REG_DMAC_DCCSR(dma_chan) & DMAC_DCCSR_TT)); -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ __dmac_channel_clear_transmit_end(dma_chan); -++ } -++} -++ -++static void jz4740_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) -++{ -++ int i; -++ struct nand_chip *chip = mtd->priv; -++ -++ if ((len <= 32) || (len & 0xf) || ((u32)buf >= (u32)high_memory)) -++ { -++ for (i = 0; i < len; i++) -++ writeb(buf[i], chip->IO_ADDR_W); -++ } else { -++ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO; -++ dma_dst_phys_addr = CPHYSADDR(chip->IO_ADDR_R); -++ dma_src_phys_addr = CPHYSADDR(buf); -++ dma_cache_wback((unsigned long)buf, len); -++ REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr; -++ REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr; -++ REG_DMAC_DTCR(dma_chan) = len / 16; -++ REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | DMAC_DCMD_DS_16BYTE ; -++ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN; -++ REG_DMAC_DMACR = DMAC_DMACR_DMAE; /* global DMA enable bit */ -++ -++ while(!(REG_DMAC_DCCSR(dma_chan) & DMAC_DCCSR_TT)); -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ __dmac_channel_clear_transmit_end(dma_chan); -++ } -++} -++ -++static int nand_read_page_hwecc_rs_planes(struct mtd_info *mtd, struct nand_chip *chip, -++ uint8_t *buf) -++{ -++ int i, eccsize = chip->ecc.size; -++ int eccbytes = chip->ecc.bytes; -++ int eccsteps = chip->ecc.steps >> 1; -++ uint8_t *p; -++ uint8_t *ecc_calc = chip->buffers->ecccalc; -++ uint8_t *ecc_code = chip->buffers->ecccode; -++ uint32_t *eccpos = chip->ecc.layout->eccpos; -++ uint32_t page; -++ uint8_t flag = 0; -++ int oobsize = mtd->oobsize >> 1; -++ int ppb = mtd->erasesize / mtd->writesize; -++ int ecctotal = chip->ecc.total >> 1; -++ -++ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -++ -++ /* Read first page */ -++ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); -++ chip->read_buf(mtd, chip->oob_poi, oobsize); -++ for (i = 0; i < ecctotal; i++) { -++ ecc_code[i] = chip->oob_poi[eccpos[i]]; -++ if (ecc_code[i] != 0xff) flag = 1; -++ } -++ -++ p = buf; -++ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0x00, -1); -++ for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { -++ int stat; -++ if (flag) { -++ chip->ecc.hwctl(mtd, NAND_ECC_READ); -++ chip->read_buf(mtd, p, eccsize); -++ stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); -++ if (stat < 0) -++ mtd->ecc_stats.failed++; -++ else -++ mtd->ecc_stats.corrected += stat; -++ } -++ else { -++ chip->ecc.hwctl(mtd, NAND_ECC_READ); -++ chip->read_buf(mtd, p, eccsize); -++ } -++ } -++ /* Read second page */ -++ page += ppb; -++ flag = 0; -++ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); -++ chip->read_buf(mtd, chip->oob_poi + oobsize, oobsize); -++ for (i = 0; i < ecctotal; i++) { -++ ecc_code[i] = chip->oob_poi[oobsize + eccpos[i]]; -++ if (ecc_code[i] != 0xff) flag = 1; -++ } -++ -++ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0x00, -1); -++ eccsteps = chip->ecc.steps >> 1; -++ for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { -++ int stat; -++ if (flag) { -++ chip->ecc.hwctl(mtd, NAND_ECC_READ); -++ chip->read_buf(mtd, p, eccsize); -++ stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); -++ if (stat < 0) -++ mtd->ecc_stats.failed++; -++ else -++ mtd->ecc_stats.corrected += stat; -++ } -++ else { -++ chip->ecc.hwctl(mtd, NAND_ECC_READ); -++ chip->read_buf(mtd, p, eccsize); -++ } -++ } -++ -++ return 0; -++} -++ -++static int nand_read_oob_std_planes(struct mtd_info *mtd, struct nand_chip *chip, -++ int global_page, int sndcmd) -++{ -++ int page; -++ int oobsize = mtd->oobsize >> 1; -++ int ppb = mtd->erasesize / mtd->writesize; -++ -++ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -++ -++ /* Read first page OOB */ -++ if (sndcmd) { -++ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); -++ } -++ chip->read_buf(mtd, chip->oob_poi, oobsize); -++ /* Read second page OOB */ -++ page += ppb; -++ if (sndcmd) { -++ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); -++ sndcmd = 0; -++ } -++ chip->read_buf(mtd, chip->oob_poi+oobsize, oobsize); -++ return 0; -++} -++ -++static int nand_write_oob_std_planes(struct mtd_info *mtd, struct nand_chip *chip, -++ int global_page) -++{ -++ int status = 0,page; -++ int pagesize = mtd->writesize >> 1; -++ int oobsize = mtd->oobsize >> 1; -++ int ppb = mtd->erasesize / mtd->writesize; -++ const uint8_t *buf = chip->oob_poi; -++ -++ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -++ -++ /* send cmd 0x80, the MSB should be valid if realplane is 4 */ -++ if (chip->realplanenum == 2) -++ chip->cmdfunc(mtd, 0x80, pagesize, 0x00); -++ else -++ chip->cmdfunc(mtd, 0x80, pagesize, page & (1 << (chip->chip_shift - chip->page_shift))); -++ -++ chip->write_buf(mtd, buf, oobsize); -++ /* Send first command to program the OOB data */ -++ chip->cmdfunc(mtd, 0x11, -1, -1); -++ ndelay(100); -++ status = chip->waitfunc(mtd, chip); -++ -++ page += ppb; -++ buf += oobsize; -++ chip->cmdfunc(mtd, 0x81, pagesize, page); -++ chip->write_buf(mtd, buf, oobsize); -++ /* Send command to program the OOB data */ -++ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); -++ /* Wait long R/B */ -++ ndelay(100); -++ status = chip->waitfunc(mtd, chip); -++ -++ return status & NAND_STATUS_FAIL ? -EIO : 0; -++} -++ -++static void nand_write_page_hwecc_planes(struct mtd_info *mtd, struct nand_chip *chip, -++ const uint8_t *buf) -++{ -++ int i, eccsize = chip->ecc.size; -++ int eccbytes = chip->ecc.bytes; -++ int eccsteps = chip->ecc.steps >> 1; -++ uint8_t *ecc_calc = chip->buffers->ecccalc; -++ uint8_t *p = (uint8_t *)buf; -++ uint32_t *eccpos = chip->ecc.layout->eccpos; -++ int oobsize = mtd->oobsize >> 1; -++ int ppb = mtd->erasesize / mtd->writesize; -++ int ecctotal = chip->ecc.total >> 1; -++ int page; -++ -++ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -++ -++ /* send cmd 0x80, the MSB should be valid if realplane is 4 */ -++ if (chip->realplanenum == 2) -++ chip->cmdfunc(mtd, 0x80, 0x00, 0x00); -++ else -++ chip->cmdfunc(mtd, 0x80, 0x00, page & (1 << (chip->chip_shift - chip->page_shift))); -++ -++ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { -++ chip->ecc.hwctl(mtd, NAND_ECC_WRITE); -++ chip->write_buf(mtd, p, eccsize); -++ chip->ecc.calculate(mtd, p, &ecc_calc[i]); -++ } -++ for (i = 0; i < ecctotal; i++) -++ chip->oob_poi[eccpos[i]] = ecc_calc[i]; -++ -++ chip->write_buf(mtd, chip->oob_poi, oobsize); -++ -++ chip->cmdfunc(mtd, 0x11, -1, -1); /* send cmd 0x11 */ -++ ndelay(100); -++ while(!chip->dev_ready(mtd)); -++ -++ page += ppb; -++ chip->cmdfunc(mtd, 0x81, 0x00, page); /* send cmd 0x81 */ -++ eccsteps = chip->ecc.steps >> 1; -++ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { -++ chip->ecc.hwctl(mtd, NAND_ECC_WRITE); -++ chip->write_buf(mtd, p, eccsize); -++ chip->ecc.calculate(mtd, p, &ecc_calc[i]); -++ } -++ -++ for (i = 0; i < ecctotal; i++) -++ chip->oob_poi[eccpos[i]] = ecc_calc[i]; -++ -++ chip->write_buf(mtd, chip->oob_poi, oobsize); -++} -++ -++static void single_erase_cmd_planes(struct mtd_info *mtd, int global_page) -++{ -++ struct nand_chip *chip = mtd->priv; -++ -++ /* Send commands to erase a block */ -++ int page; -++ int ppb = mtd->erasesize / mtd->writesize; -++ -++ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -++ -++ /* send cmd 0x60, the MSB should be valid if realplane is 4 */ -++ if (chip->realplanenum == 2) -++ chip->cmdfunc(mtd, 0x60, -1, 0x00); -++ else -++ chip->cmdfunc(mtd, 0x60, -1, page & (1 << (chip->chip_shift - chip->page_shift))); -++ -++ page += ppb; -++ chip->cmdfunc(mtd, 0x60, -1, page & (~(ppb-1))); /* send cmd 0x60 */ -++ -++ chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); /* send cmd 0xd0 */ -++ /* Do not need wait R/B or check status */ -++} -++ -++/* -++ * Main initialization routine -++ */ -++int __init jznand_init(void) -++{ -++ struct nand_chip *this; -++ int nr_partitions, ret, i; -++ -++ /* Allocate memory for MTD device structure and private data */ -++ jz_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), -++ GFP_KERNEL); -++ if (!jz_mtd) { -++ printk ("Unable to allocate JzSOC NAND MTD device structure.\n"); -++ return -ENOMEM; -++ } -++ -++ jz_mtd1 = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), -++ GFP_KERNEL); -++ if (!jz_mtd1) { -++ printk ("Unable to allocate JzSOC NAND MTD device structure 1.\n"); -++ kfree(jz_mtd); -++ return -ENOMEM; -++ } -++ -++ /* Get pointer to private data */ -++ this = (struct nand_chip *) (&jz_mtd[1]); -++ -++ /* Initialize structures */ -++ memset((char *) jz_mtd, 0, sizeof(struct mtd_info)); -++ memset((char *) this, 0, sizeof(struct nand_chip)); -++ -++ /* Link the private data with the MTD structure */ -++ jz_mtd->priv = this; -++ -++ /* Set & initialize NAND Flash controller */ -++ jz_device_setup(); -++ -++ /* Set address of NAND IO lines */ -++ this->IO_ADDR_R = (void __iomem *) NAND_DATA_PORT1; -++ this->IO_ADDR_W = (void __iomem *) NAND_DATA_PORT1; -++ this->cmd_ctrl = jz_hwcontrol; -++ this->dev_ready = jz_device_ready; -++ -++#ifdef CONFIG_MTD_HW_HM_ECC -++ this->ecc.calculate = jzsoc_nand_calculate_hm_ecc; -++ this->ecc.correct = jzsoc_nand_hm_correct_data; -++ this->ecc.hwctl = jzsoc_nand_enable_hm_hwecc; -++ this->ecc.mode = NAND_ECC_HW; -++ this->ecc.size = 256; -++ this->ecc.bytes = 3; -++ -++#endif -++ -++#ifdef CONFIG_MTD_HW_RS_ECC -++ this->ecc.calculate = jzsoc_nand_calculate_rs_ecc; -++ this->ecc.correct = jzsoc_nand_rs_correct_data; -++ this->ecc.hwctl = jzsoc_nand_enable_rs_hwecc; -++ this->ecc.mode = NAND_ECC_HW; -++ this->ecc.size = 512; -++ this->ecc.bytes = 9; -++#endif -++ -++#ifdef CONFIG_MTD_SW_HM_ECC -++ this->ecc.mode = NAND_ECC_SOFT; -++#endif -++ /* 20 us command delay time */ -++ this->chip_delay = 20; -++ -++ dma_setup(); -++ -++ /* Scan to find existance of the device */ -++ ret = nand_scan_ident(jz_mtd, NAND_MAX_CHIPS); -++ if (!ret) { -++ if (this->planenum == 2) { -++ /* reset nand functions */ -++ this->erase_cmd = single_erase_cmd_planes; -++ this->ecc.read_page = nand_read_page_hwecc_rs_planes; //Muti planes read -++ this->ecc.write_page = nand_write_page_hwecc_planes; -++ this->ecc.read_oob = nand_read_oob_std_planes; -++ this->ecc.write_oob = nand_write_oob_std_planes; -++ this->write_buf = jz4740_nand_write_buf; -++ this->read_buf = jz4740_nand_read_buf; -++ -++ printk(KERN_INFO "Nand using two-plane mode, " -++ "and resized to writesize:%d oobsize:%d blocksize:0x%x \n", -++ jz_mtd->writesize, jz_mtd->oobsize, jz_mtd->erasesize); -++ } else -++ return -ENXIO; -++ } -++ -++ /* Determine whether all the partitions will use multiple planes if supported */ -++ nr_partitions = sizeof(partition_info) / sizeof(struct mtd_partition); -++ all_use_planes = 1; -++ for (i = 0; i < nr_partitions; i++) { -++ all_use_planes &= partition_info[i].use_planes; -++ } -++ -++ if (!ret) -++ ret = nand_scan_tail(jz_mtd); -++ -++ if (ret){ -++ kfree (jz_mtd1); -++ kfree (jz_mtd); -++ return -ENXIO; -++ } -++ -++ /* Register the partitions */ -++ printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nr_partitions, jz_mtd->name); -++ -++ if ((this->planenum == 2) && !all_use_planes) { -++ for (i = 0; i < nr_partitions; i++) { -++ if (partition_info[i].use_planes) -++ add_mtd_partitions(jz_mtd, &partition_info[i], 1); -++ else -++ add_mtd_partitions(jz_mtd1, &partition_info[i], 1); -++ } -++ } else { -++ kfree(jz_mtd1); -++ add_mtd_partitions(jz_mtd, partition_info, nr_partitions); -++ } -++ return 0; -++} -++module_init(jznand_init); -++ -++/* -++ * Clean up routine -++ */ -++#ifdef MODULE -++static void __exit jznand_cleanup(void) -++{ -++ struct nand_chip *this = (struct nand_chip *) &jz_mtd[1]; -++ -++ /* Unregister partitions */ -++ del_mtd_partitions(jz_mtd); -++ -++ /* Unregister the device */ -++ del_mtd_device (jz_mtd); -++ -++ /* Free internal data buffers */ -++ kfree (this->data_buf); -++ -++ /* Free the MTD device structure */ -++ if ((this->planenum == 2) && !all_use_planes) -++ kfree (jz_mtd1); -++ kfree (jz_mtd); -++} -++module_exit(jznand_cleanup); -++#endif -+diff -urN linux-2.6.24.7.old/drivers/mtd/nand/jz4750_nand.c linux-2.6.24.7/drivers/mtd/nand/jz4750_nand.c -+--- linux-2.6.24.7.old/drivers/mtd/nand/jz4750_nand.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/nand/jz4750_nand.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1746 @@ -++/* -++ * linux/drivers/mtd/nand/jz4750_nand.c -++ * -++ * JZ4750 NAND driver -++ * -++ * Copyright (c) 2005 - 2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ */ -++ -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++/* 32bit instead of 16byte burst is used by DMA to read or -++ write NAND and BCH avoiding grabbing bus for too long */ -++#define DMAC_DCMD_DS_NAND DMAC_DCMD_DS_32BIT -++#define DIV_DS_NAND 4 -++ -++#define DMAC_DCMD_DS_BCH DMAC_DCMD_DS_32BIT -++#define DIV_DS_BCH 4 -++ -++#define DEBUG1 0 -++#if DEBUG1 -++#define dprintk(n,x...) printk(n,##x) -++#else -++#define dprintk(n,x...) -++#endif -++ -++#if defined(CONFIG_MTD_HW_BCH_8BIT) -++#define __ECC_ENCODING __ecc_encoding_8bit -++#define __ECC_DECODING __ecc_decoding_8bit -++#define ERRS_SIZE 5 /* 5 words */ -++#else -++#define __ECC_ENCODING __ecc_encoding_4bit -++#define __ECC_DECODING __ecc_decoding_4bit -++#define ERRS_SIZE 3 /* 3 words */ -++#endif -++ -++#define NAND_DATA_PORT1 0xB8000000 /* read-write area in static bank 1 */ -++#define NAND_DATA_PORT2 0xB4000000 /* read-write area in static bank 2 */ -++#define NAND_DATA_PORT3 0xAC000000 /* read-write area in static bank 3 */ -++#define NAND_DATA_PORT4 0xA8000000 /* read-write area in static bank 4 */ -++ -++#define NAND_ADDR_OFFSET0 0x00010000 /* address port offset for share mode */ -++#define NAND_CMD_OFFSET0 0x00008000 /* command port offset for share mode */ -++#define NAND_ADDR_OFFSET1 0x00000010 /* address port offset for unshare mode */ -++#define NAND_CMD_OFFSET1 0x00000008 /* command port offset for unshare mode */ -++ -++#if defined(CONFIG_MTD_NAND_DMA) -++#define USE_IRQ 1 -++enum { -++ NAND_NONE, -++ NAND_PROG, -++ NAND_READ -++}; -++static volatile u8 nand_status; -++static volatile int dma_ack = 0; -++static volatile int dma_ack1 = 0; -++static char nand_dma_chan; /* automatically select a free channel */ -++static char bch_dma_chan = 0; /* fixed to channel 0 */ -++static u32 *errs; -++static jz_dma_desc_8word *dma_desc_enc, *dma_desc_enc1, *dma_desc_dec, *dma_desc_dec1, *dma_desc_dec2, -++ *dma_desc_nand_prog, *dma_desc_nand_read; -++static u32 *pval_nand_ddr; -++static u8 *pval_nand_cmd_pgprog; /* for sending 0x11 or 0x10 when programing*/ -++#if defined(CONFIG_MTD_NAND_DMABUF) -++u8 *prog_buf, *read_buf; -++#endif -++DECLARE_WAIT_QUEUE_HEAD(nand_prog_wait_queue); -++DECLARE_WAIT_QUEUE_HEAD(nand_read_wait_queue); -++#endif -++ -++struct buf_be_corrected { -++ u8 *data; -++ u8 *oob; -++}; -++ -++static u32 addr_offset; -++static u32 cmd_offset; -++ -++extern int global_page; /* for two-plane operations */ -++ -++/* -++ * MTD structure for JzSOC board -++ */ -++static struct mtd_info *jz_mtd = NULL; -++extern struct mtd_info *jz_mtd1; -++extern char all_use_planes; -++ -++/* -++ * Define partitions for flash devices -++ */ -++#if defined(CONFIG_JZ4750_FUWA) || defined(CONFIG_JZ4750D_FUWA1) -++static struct mtd_partition partition_info[] = { -++ {name:"NAND BOOT partition", -++ offset:0 * 0x100000, -++ size:4 * 0x100000, -++ use_planes: 0}, -++ {name:"NAND KERNEL partition", -++ offset:4 * 0x100000, -++ size:4 * 0x100000, -++ use_planes: 0}, -++ {name:"NAND ROOTFS partition", -++ offset:8 * 0x100000, -++ size:120 * 0x100000, -++ use_planes: 1}, -++ {name:"NAND DATA1 partition", -++ offset:128 * 0x100000, -++ size:128 * 0x100000, -++ use_planes: 1}, -++ {name:"NAND DATA2 partition", -++ offset:256 * 0x100000, -++ size:256 * 0x100000, -++ use_planes: 1}, -++ {name:"NAND VFAT partition", -++ offset:512 * 0x100000, -++ size:512 * 0x100000, -++ use_planes: 1}, -++}; -++ -++/* Define max reserved bad blocks for each partition. -++ * This is used by the mtdblock-jz.c NAND FTL driver only. -++ * -++ * The NAND FTL driver reserves some good blocks which can't be -++ * seen by the upper layer. When the bad block number of a partition -++ * exceeds the max reserved blocks, then there is no more reserved -++ * good blocks to be used by the NAND FTL driver when another bad -++ * block generated. -++ */ -++static int partition_reserved_badblocks[] = { -++ 2, /* reserved blocks of mtd0 */ -++ 2, /* reserved blocks of mtd1 */ -++ 10, /* reserved blocks of mtd2 */ -++ 10, /* reserved blocks of mtd3 */ -++ 20, /* reserved blocks of mtd4 */ -++ 20 -++}; /* reserved blocks of mtd5 */ -++#endif /* CONFIG_JZ4750_FUWA or CONFIG_JZ4750_APUS */ -++ -++#if defined(CONFIG_JZ4750_APUS) -++static struct mtd_partition partition_info[] = { -++ {name:"NAND BOOT partition", -++ offset:0 * 0x100000, -++ size:4 * 0x100000, -++ use_planes: 0}, -++ {name:"NAND KERNEL partition", -++ offset:4 * 0x100000, -++ size:4 * 0x100000, -++ use_planes: 0}, -++ {name:"NAND ROOTFS partition", -++ offset:8 * 0x100000, -++ size:504 * 0x100000, -++ use_planes: 0}, -++ {name:"NAND VFAT partition", -++ offset:512 * 0x100000, -++ size:512 * 0x100000, -++ use_planes: 1}, -++}; -++ -++ -++/* Define max reserved bad blocks for each partition. -++ * This is used by the mtdblock-jz.c NAND FTL driver only. -++ * -++ * The NAND FTL driver reserves some good blocks which can't be -++ * seen by the upper layer. When the bad block number of a partition -++ * exceeds the max reserved blocks, then there is no more reserved -++ * good blocks to be used by the NAND FTL driver when another bad -++ * block generated. -++ */ -++static int partition_reserved_badblocks[] = { -++ 2, /* reserved blocks of mtd0 */ -++ 2, /* reserved blocks of mtd1 */ -++ 10, /* reserved blocks of mtd2 */ -++ 10, /* reserved blocks of mtd3 */ -++}; -++#endif /* CONFIG_JZ4750_FUWA or CONFIG_JZ4750_APUS */ -++ -++/*------------------------------------------------------------------------- -++ * Following three functions are exported and used by the mtdblock-jz.c -++ * NAND FTL driver only. -++ */ -++ -++unsigned short get_mtdblock_write_verify_enable(void) -++{ -++#ifdef CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE -++ return 1; -++#endif -++ return 0; -++} -++ -++EXPORT_SYMBOL(get_mtdblock_write_verify_enable); -++ -++unsigned short get_mtdblock_oob_copies(void) -++{ -++ return CONFIG_MTD_OOB_COPIES; -++} -++ -++EXPORT_SYMBOL(get_mtdblock_oob_copies); -++ -++int *get_jz_badblock_table(void) -++{ -++ return partition_reserved_badblocks; -++} -++ -++EXPORT_SYMBOL(get_jz_badblock_table); -++ -++/*-------------------------------------------------------------------------*/ -++ -++static void jz_hwcontrol(struct mtd_info *mtd, int dat, u32 ctrl) -++{ -++ struct nand_chip *this = (struct nand_chip *)(mtd->priv); -++ u32 nandaddr = (u32)this->IO_ADDR_W; -++ extern u8 nand_nce; /* defined in nand_base.c, indicates which chip select is used for current nand chip */ -++ -++ if (ctrl & NAND_CTRL_CHANGE) { -++ if (ctrl & NAND_NCE) { -++ switch (nand_nce) { -++ case NAND_NCE1: -++ this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT1; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; -++ REG_EMC_NFCSR |= EMC_NFCSR_NFCE1; -++ break; -++ case NAND_NCE2: -++ this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT2; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; -++ REG_EMC_NFCSR |= EMC_NFCSR_NFCE2; -++ break; -++ case NAND_NCE3: -++ this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT3; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; -++ REG_EMC_NFCSR |= EMC_NFCSR_NFCE3; -++ break; -++ case NAND_NCE4: -++ this->IO_ADDR_W = this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT4; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; -++ REG_EMC_NFCSR |= EMC_NFCSR_NFCE4; -++ break; -++ default: -++ printk("error: no nand_nce 0x%x\n",nand_nce); -++ break; -++ } -++ } else { -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE2; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE3; -++ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE4; -++ } -++ -++ if (ctrl & NAND_ALE) -++ nandaddr = (u32)((u32)(this->IO_ADDR_W) | addr_offset); -++ else -++ nandaddr = (u32)((u32)(this->IO_ADDR_W) & ~addr_offset); -++ if (ctrl & NAND_CLE) -++ nandaddr = (u32)(nandaddr | cmd_offset); -++ else -++ nandaddr = (u32)(nandaddr & ~cmd_offset); -++ } -++ -++ this->IO_ADDR_W = (void __iomem *)nandaddr; -++ if (dat != NAND_CMD_NONE) { -++ writeb(dat, this->IO_ADDR_W); -++ /* printk("write cmd:0x%x to 0x%x\n",dat,(u32)this->IO_ADDR_W); */ -++ } -++} -++ -++static int jz_device_ready(struct mtd_info *mtd) -++{ -++ int ready, wait = 10; -++ while (wait--); -++ ready = __gpio_get_pin(91); -++ return ready; -++} -++ -++/* -++ * EMC setup -++ */ -++static void jz_device_setup(void) -++{ -++// PORT 0: -++// PORT 1: -++// PORT 2: -++// PIN/BIT N FUNC0 FUNC1 -++// 21 CS1# - -++// 22 CS2# - -++// 23 CS3# - -++// 24 CS4# - -++#define GPIO_CS2_N (32*2+22) -++#define GPIO_CS3_N (32*2+23) -++#define GPIO_CS4_N (32*2+24) -++#define SMCR_VAL 0x0d444400 -++ -++ __gpio_as_nand_8bit(1); -++ /* Set NFE bit */ -++ REG_EMC_NFCSR |= EMC_NFCSR_NFE1; -++ /* Read/Write timings */ -++ REG_EMC_SMCR1 = SMCR_VAL; -++ -++#if defined(CONFIG_MTD_NAND_CS2) -++ __gpio_as_func0(GPIO_CS2_N); -++ /* Set NFE bit */ -++ REG_EMC_NFCSR |= EMC_NFCSR_NFE2; -++ /* Read/Write timings */ -++ REG_EMC_SMCR2 = SMCR_VAL; -++#endif -++ -++#if defined(CONFIG_MTD_NAND_CS3) -++ __gpio_as_func0(GPIO_CS3_N); -++ /* Set NFE bit */ -++ REG_EMC_NFCSR |= EMC_NFCSR_NFE3; -++ /* Read/Write timings */ -++ REG_EMC_SMCR3 = SMCR_VAL; -++#endif -++ -++#if defined(CONFIG_MTD_NAND_CS4) -++ __gpio_as_func0(GPIO_CS4_N); -++ /* Set NFE bit */ -++ REG_EMC_NFCSR |= EMC_NFCSR_NFE4; -++ /* Read/Write timings */ -++ REG_EMC_SMCR4 = SMCR_VAL; -++#endif -++} -++ -++#ifdef CONFIG_MTD_HW_BCH_ECC -++ -++static void jzsoc_nand_enable_bch_hwecc(struct mtd_info *mtd, int mode) -++{ -++ struct nand_chip *this = (struct nand_chip *)(mtd->priv); -++ int eccsize = this->ecc.size; -++ int eccbytes = this->ecc.bytes; -++ int eccsteps = this->ecc.steps / this->planenum; -++ int oob_per_eccsize = this->ecc.layout->eccpos[0] / eccsteps; -++ -++ REG_BCH_INTS = 0xffffffff; -++ if (mode == NAND_ECC_READ) { -++ __ECC_DECODING(); -++ __ecc_cnt_dec(eccsize + oob_per_eccsize + eccbytes); -++#if defined(CONFIG_MTD_NAND_DMA) -++ __ecc_dma_enable(); -++#endif -++ } -++ -++ if (mode == NAND_ECC_WRITE) { -++ __ECC_ENCODING(); -++ __ecc_cnt_enc(eccsize + oob_per_eccsize); -++#if defined(CONFIG_MTD_NAND_DMA) -++ __ecc_dma_enable(); -++#endif -++ } -++} -++ -++/** -++ * bch_correct -++ * @dat: data to be corrected -++ * @idx: the index of error bit in an eccsize -++ */ -++static void bch_correct(struct mtd_info *mtd, u8 * dat, int idx) -++{ -++ struct nand_chip *this = (struct nand_chip *)(mtd->priv); -++ int eccsize = this->ecc.size; -++ int eccsteps = this->ecc.steps / this->planenum; -++ int ecc_pos = this->ecc.layout->eccpos[0]; -++ int oob_per_eccsize = ecc_pos / eccsteps; -++ int i, bit; /* the 'bit' of i byte is error */ -++ -++ i = (idx - 1) >> 3; -++ bit = (idx - 1) & 0x7; -++ -++ dprintk("error:i=%d, bit=%d\n",i,bit); -++ -++ if (i < eccsize){ -++ ((struct buf_be_corrected *)dat)->data[i] ^= (1 << bit); -++ } else if (i < eccsize + oob_per_eccsize) { -++ ((struct buf_be_corrected *)dat)->oob[i-eccsize] ^= (1 << bit); -++ } -++} -++ -++#if defined(CONFIG_MTD_NAND_DMA) -++ -++/** -++ * jzsoc_nand_bch_correct_data -++ * @mtd: mtd info structure -++ * @dat: data to be corrected -++ * @errs0: pointer to the dma target buffer of bch decoding which stores BHINTS and -++ * BHERR0~3(8-bit BCH) or BHERR0~1(4-bit BCH) -++ * @calc_ecc: no used -++ */ -++static int jzsoc_nand_bch_correct_data(struct mtd_info *mtd, u_char * dat, u_char * errs0, u_char * calc_ecc) -++{ -++ u32 stat; -++ u32 *errs = (u32 *)errs0; -++ -++ if (REG_DMAC_DCCSR(0) & DMAC_DCCSR_BERR) { -++ stat = errs[0]; -++ dprintk("stat=%x err0:%x err1:%x \n", stat, errs[1], errs[2]); -++ -++ if (stat & BCH_INTS_ERR) { -++ if (stat & BCH_INTS_UNCOR) { -++ printk("NAND: Uncorrectable ECC error\n"); -++ return -1; -++ } else { -++ u32 errcnt = (stat & BCH_INTS_ERRC_MASK) >> BCH_INTS_ERRC_BIT; -++ switch (errcnt) { -++#if defined(CONFIG_MTD_HW_BCH_8BIT) -++ case 8: -++ bch_correct(mtd, dat, (errs[4] & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); -++ case 7: -++ bch_correct(mtd, dat, (errs[4] & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -++ case 6: -++ bch_correct(mtd, dat, (errs[3] & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); -++ case 5: -++ bch_correct(mtd, dat, (errs[3] & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -++#endif -++ case 4: -++ bch_correct(mtd, dat, (errs[2] & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); -++ case 3: -++ bch_correct(mtd, dat, (errs[2] & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -++ case 2: -++ bch_correct(mtd, dat, (errs[1] & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); -++ case 1: -++ bch_correct(mtd, dat, (errs[1] & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -++ default: -++ break; -++ } -++ } -++ } -++ } -++ -++ return 0; -++} -++ -++#else /* cpu mode */ -++ -++/** -++ * jzsoc_nand_bch_correct_data -++ * @mtd: mtd info structure -++ * @dat: data to be corrected -++ * @read_ecc: pointer to ecc buffer calculated when nand writing -++ * @calc_ecc: no used -++ */ -++static int jzsoc_nand_bch_correct_data(struct mtd_info *mtd, u_char * dat, u_char * read_ecc, u_char * calc_ecc) -++{ -++ struct nand_chip *this = (struct nand_chip *)(mtd->priv); -++ int eccsize = this->ecc.size; -++ int eccbytes = this->ecc.bytes; -++ int eccsteps = this->ecc.steps / this->planenum; -++ int ecc_pos = this->ecc.layout->eccpos[0]; -++ int oob_per_eccsize = ecc_pos / eccsteps; -++ short k; -++ u32 stat; -++ -++ /* Write data to REG_BCH_DR */ -++ for (k = 0; k < eccsize; k++) { -++ REG_BCH_DR = ((struct buf_be_corrected *)dat)->data[k]; -++ } -++ /* Write oob to REG_BCH_DR */ -++ for (k = 0; k < oob_per_eccsize; k++) { -++ REG_BCH_DR = ((struct buf_be_corrected *)dat)->oob[k]; -++ } -++ /* Write parities to REG_BCH_DR */ -++ for (k = 0; k < eccbytes; k++) { -++ REG_BCH_DR = read_ecc[k]; -++ } -++ -++ /* Wait for completion */ -++ __ecc_decode_sync(); -++ __ecc_disable(); -++ -++ /* Check decoding */ -++ stat = REG_BCH_INTS; -++ -++ if (stat & BCH_INTS_ERR) { -++ /* Error occurred */ -++ if (stat & BCH_INTS_UNCOR) { -++ printk("NAND: Uncorrectable ECC error--\n"); -++ return -1; -++ } else { -++ u32 errcnt = (stat & BCH_INTS_ERRC_MASK) >> BCH_INTS_ERRC_BIT; -++ switch (errcnt) { -++#if defined(CONFIG_MTD_HW_BCH_8BIT) -++ case 8: -++ bch_correct(mtd, dat, (REG_BCH_ERR3 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); -++ /* FALL-THROUGH */ -++ case 7: -++ bch_correct(mtd, dat, (REG_BCH_ERR3 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -++ /* FALL-THROUGH */ -++ case 6: -++ bch_correct(mtd, dat, (REG_BCH_ERR2 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); -++ /* FALL-THROUGH */ -++ case 5: -++ bch_correct(mtd, dat, (REG_BCH_ERR2 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -++ /* FALL-THROUGH */ -++#endif -++ case 4: -++ bch_correct(mtd, dat, (REG_BCH_ERR1 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); -++ /* FALL-THROUGH */ -++ case 3: -++ bch_correct(mtd, dat, (REG_BCH_ERR1 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -++ /* FALL-THROUGH */ -++ case 2: -++ bch_correct(mtd, dat, (REG_BCH_ERR0 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT); -++ /* FALL-THROUGH */ -++ case 1: -++ bch_correct(mtd, dat, (REG_BCH_ERR0 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT); -++ return 0; -++ default: -++ break; -++ } -++ } -++ } -++ -++ return 0; -++} -++#endif /* CONFIG_MTD_NAND_DMA */ -++ -++static int jzsoc_nand_calculate_bch_ecc(struct mtd_info *mtd, const u_char * dat, u_char * ecc_code) -++{ -++ struct nand_chip *this = (struct nand_chip *)(mtd->priv); -++ int eccsize = this->ecc.size; -++ int eccbytes = this->ecc.bytes; -++ int eccsteps = this->ecc.steps / this->planenum; -++ int ecc_pos = this->ecc.layout->eccpos[0]; -++ int oob_per_eccsize = ecc_pos / eccsteps; -++ volatile u8 *paraddr = (volatile u8 *)BCH_PAR0; -++ short i; -++ -++ /* Write data to REG_BCH_DR */ -++ for (i = 0; i < eccsize; i++) { -++ REG_BCH_DR = ((struct buf_be_corrected *)dat)->data[i]; -++ } -++ /* Write oob to REG_BCH_DR */ -++ for (i = 0; i < oob_per_eccsize; i++) { -++ REG_BCH_DR = ((struct buf_be_corrected *)dat)->oob[i]; -++ } -++ __ecc_encode_sync(); -++ __ecc_disable(); -++ -++ for (i = 0; i < eccbytes; i++) { -++ ecc_code[i] = *paraddr++; -++ } -++ -++ return 0; -++} -++ -++#if defined(CONFIG_MTD_NAND_DMA) -++ -++/** -++ * nand_write_page_hwecc_bch - [REPLACABLE] hardware ecc based page write function -++ * @mtd: mtd info structure -++ * @chip: nand chip info structure -++ * @buf: data buffer -++ */ -++static void nand_write_page_hwecc_bch0(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t * buf, u8 cmd_pgprog) -++{ -++ int eccsize = chip->ecc.size; -++ int eccsteps = chip->ecc.steps / chip->planenum; -++ int eccbytes = chip->ecc.bytes; -++ int ecc_pos = chip->ecc.layout->eccpos[0]; -++ int oob_per_eccsize = ecc_pos / eccsteps; -++ int pagesize = mtd->writesize / chip->planenum; -++ int oobsize = mtd->oobsize / chip->planenum; -++ int i, err, timeout; -++ const u8 *databuf; -++ u8 *oobbuf; -++ jz_dma_desc_8word *desc; -++ -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ memcpy(prog_buf, buf, pagesize); -++ memcpy(prog_buf + pagesize, chip->oob_poi, oobsize); -++ dma_cache_wback_inv((u32)prog_buf, pagesize + oobsize); -++#else -++ databuf = buf; -++ oobbuf = chip->oob_poi; -++ -++ /* descriptors for encoding data blocks */ -++ desc = dma_desc_enc; -++ for (i = 0; i < eccsteps; i++) { -++ desc->dsadr = CPHYSADDR((u32)databuf) + i * eccsize; /* DMA source address */ -++ desc->dtadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA target address */ -++ dprintk("dma_desc_enc:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -++ desc->ddadr); -++ desc++; -++ } -++ -++ /* descriptors for encoding oob blocks */ -++ desc = dma_desc_enc1; -++ for (i = 0; i < eccsteps; i++) { -++ desc->dsadr = CPHYSADDR((u32)oobbuf) + oob_per_eccsize * i; /* DMA source address, 28/4 = 7bytes */ -++ desc->dtadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA target address */ -++ dprintk("dma_desc_enc1:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -++ desc->ddadr); -++ desc++; -++ } -++ -++ /* descriptor for nand programing data block */ -++ desc = dma_desc_nand_prog; -++ desc->dsadr = CPHYSADDR((u32)databuf); /* DMA source address */ -++ desc->dtadr = CPHYSADDR((u32)chip->IO_ADDR_W); /* It will be changed when using multiply chip select */ -++ dprintk("dma_desc_nand_prog:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -++ desc->ddadr); -++ -++ /* descriptor for nand programing oob block */ -++ desc++; -++ desc->dsadr = CPHYSADDR((u32)oobbuf); /* DMA source address */ -++ desc->dtadr = CPHYSADDR((u32)chip->IO_ADDR_W); /* It will be changed when using multiply chip select */ -++ dprintk("dma_desc_oob_prog:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -++ desc->ddadr); -++ -++ /* descriptor for __nand_cmd(CMD_PGPROG) */ -++ desc++; -++ *pval_nand_cmd_pgprog = cmd_pgprog; -++ desc->dsadr = CPHYSADDR((u32)pval_nand_cmd_pgprog); -++ desc->dtadr = CPHYSADDR((u32)chip->IO_ADDR_R | cmd_offset); /* DMA target address: cmdport */ -++ if (cmd_pgprog == 0x10) -++ desc->dcmd |= DMAC_DCMD_LINK; /* __nand_sync() by a DMA descriptor */ -++ else if (cmd_pgprog == 0x11) -++ desc->dcmd &= ~DMAC_DCMD_LINK; /* __nand_sync() by polling */ -++ -++ dma_cache_wback_inv((u32)dma_desc_enc, (eccsteps * 2 + 2 + 1) * (sizeof(jz_dma_desc_8word))); -++ dma_cache_wback_inv((u32)databuf, pagesize); -++ dma_cache_wback_inv((u32)oobbuf, oobsize); -++ /* 4*6: pval_nand_ddr, pval_nand_dcs, pval_bch_ddr, pval_bch_dcs, dummy, pval_nand_cmd_pgprog */ -++ dma_cache_wback_inv((u32)pval_nand_ddr, 4 * 8); /* 8 words, a cache line */ -++#endif -++ -++ REG_DMAC_DCCSR(bch_dma_chan) = 0; -++ REG_DMAC_DCCSR(nand_dma_chan) = 0; -++ -++ /* Setup DMA descriptor address */ -++ REG_DMAC_DDA(bch_dma_chan) = CPHYSADDR((u32)dma_desc_enc); -++ REG_DMAC_DDA(nand_dma_chan) = CPHYSADDR((u32)dma_desc_nand_prog); -++ -++ /* Setup request source */ -++ REG_DMAC_DRSR(bch_dma_chan) = DMAC_DRSR_RS_BCH_ENC; -++ REG_DMAC_DRSR(nand_dma_chan) = DMAC_DRSR_RS_AUTO; -++ -++ /* Setup DMA channel control/status register */ -++ REG_DMAC_DCCSR(bch_dma_chan) = DMAC_DCCSR_DES8 | DMAC_DCCSR_EN; /* descriptor transfer, clear status, start channel */ -++ -++ /* Enable DMA */ -++ REG_DMAC_DMACR(0) |= DMAC_DMACR_DMAE; -++ REG_DMAC_DMACR(nand_dma_chan/HALF_DMA_NUM) |= DMAC_DMACR_DMAE; -++ -++ /* Enable BCH encoding */ -++ chip->ecc.hwctl(mtd, NAND_ECC_WRITE); -++ -++ dma_ack1 = 0; -++ nand_status = NAND_PROG; -++ -++ /* DMA doorbell set -- start DMA now ... */ -++ __dmac_channel_set_doorbell(bch_dma_chan); -++ -++#if USE_IRQ -++ if (cmd_pgprog == 0x10) { -++ dprintk("nand prog before wake up\n"); -++ err = wait_event_interruptible_timeout(nand_prog_wait_queue, dma_ack1, 3 * HZ); -++ nand_status = NAND_NONE; -++ dprintk("nand prog after wake up\n"); -++ if (!err) { -++ printk("*** NAND WRITE, Warning, wait event 3s timeout!\n"); -++ dump_jz_dma_channel(0); -++ dump_jz_dma_channel(nand_dma_chan); -++ printk("REG_BCH_CR=%x REG_BCH_CNT=0x%x REG_BCH_INTS=%x\n", REG_BCH_CR, REG_BCH_CNT, REG_BCH_INTS); -++ } -++ dprintk("timeout remain = %d\n", err); -++ } else if (cmd_pgprog == 0x11) { -++ timeout = 100000; -++ while ((!__dmac_channel_transmit_end_detected(nand_dma_chan)) && (timeout--)); -++ if (timeout <= 0) -++ printk("two-plane prog 0x11 timeout!\n"); -++ } -++#else -++ timeout = 100000; -++ while ((!__dmac_channel_transmit_end_detected(nand_dma_chan)) && (timeout--)); -++ while(!chip->dev_ready(mtd)); -++ if (timeout <= 0) -++ printk("not use irq, prog timeout!\n"); -++#endif -++} -++ -++static void nand_write_page_hwecc_bch(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t * buf) -++{ -++ nand_write_page_hwecc_bch0(mtd, chip, buf, 0x10); -++} -++ -++static void nand_write_page_hwecc_bch_planes(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t * buf) -++{ -++ int page; -++ int pagesize = mtd->writesize >> 1; -++ int ppb = mtd->erasesize / mtd->writesize; -++ -++ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -++ -++ /* send cmd 0x80, the MSB should be valid if realplane is 4 */ -++ if (chip->realplanenum == 2) -++ chip->cmdfunc(mtd, 0x80, 0x00, 0x00); -++ else -++ chip->cmdfunc(mtd, 0x80, 0x00, page & (1 << (chip->chip_shift - chip->page_shift))); -++ -++ nand_write_page_hwecc_bch0(mtd, chip, buf, 0x11); -++ chip->cmdfunc(mtd, 0x81, 0x00, page + ppb); -++ nand_write_page_hwecc_bch0(mtd, chip, buf + pagesize, 0x10); -++} -++ -++#else /* nand write in cpu mode */ -++ -++static void nand_write_page_hwecc_bch(struct mtd_info *mtd, struct nand_chip *chip, -++ const uint8_t *buf) -++{ -++ int i, eccsize = chip->ecc.size; -++ int eccbytes = chip->ecc.bytes; -++ int eccsteps = chip->ecc.steps / chip->planenum; -++ int oob_per_eccsize = chip->ecc.layout->eccpos[0] / eccsteps; -++ int oobsize = mtd->oobsize / chip->planenum; -++ int ecctotal = chip->ecc.total / chip->planenum; -++ uint8_t *p = (uint8_t *)buf; -++ uint8_t *ecc_calc = chip->buffers->ecccalc; -++ uint32_t *eccpos = chip->ecc.layout->eccpos; -++ static struct buf_be_corrected buf_calc0; -++ struct buf_be_corrected *buf_calc = &buf_calc0; -++ -++ for (i = 0; i < eccsteps; i++, p += eccsize) { -++ buf_calc->data = (u8 *)buf + eccsize * i; -++ buf_calc->oob = chip->oob_poi + oob_per_eccsize * i; -++ chip->ecc.hwctl(mtd, NAND_ECC_WRITE); -++ chip->ecc.calculate(mtd, (u8 *)buf_calc, &ecc_calc[eccbytes*i]); -++ chip->write_buf(mtd, p, eccsize); -++ } -++ -++ for (i = 0; i < ecctotal; i++) -++ chip->oob_poi[eccpos[i]] = ecc_calc[i]; -++ -++ chip->write_buf(mtd, chip->oob_poi, oobsize); -++} -++ -++/* nand write using two-plane mode */ -++static void nand_write_page_hwecc_bch_planes(struct mtd_info *mtd, struct nand_chip *chip, -++ const uint8_t *buf) -++{ -++ int pagesize = mtd->writesize >> 1; -++ int ppb = mtd->erasesize / mtd->writesize; -++ int page; -++ -++ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -++ -++ /* send cmd 0x80, the MSB should be valid if realplane is 4 */ -++ if (chip->realplanenum == 2) -++ chip->cmdfunc(mtd, 0x80, 0x00, 0x00); -++ else -++ chip->cmdfunc(mtd, 0x80, 0x00, page & (1 << (chip->chip_shift - chip->page_shift))); -++ -++ nand_write_page_hwecc_bch(mtd, chip, buf); -++ -++ chip->cmdfunc(mtd, 0x11, -1, -1); /* send cmd 0x11 */ -++ ndelay(100); -++ while(!chip->dev_ready(mtd)); -++ -++ chip->cmdfunc(mtd, 0x81, 0x00, page + ppb); /* send cmd 0x81 */ -++ nand_write_page_hwecc_bch(mtd, chip, buf + pagesize); -++} -++#endif /* CONFIG_MTD_NAND_DMA */ -++ -++/** -++ * nand_read_page_hwecc_bch - [REPLACABLE] hardware ecc based page read function -++ * @mtd: mtd info structure -++ * @chip: nand chip info structure -++ * @buf: buffer to store read data -++ * -++ * Not for syndrome calculating ecc controllers which need a special oob layout -++ */ -++#if defined(CONFIG_MTD_NAND_DMA) -++static int nand_read_page_hwecc_bch0(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf, u32 page) -++{ -++ int i, eccsize = chip->ecc.size; -++ int eccsteps = chip->ecc.steps / chip->planenum; -++ int eccbytes = chip->ecc.bytes; -++ int ecc_pos = chip->ecc.layout->eccpos[0]; -++ int oob_per_eccsize = ecc_pos / eccsteps; -++ int pagesize = mtd->writesize / chip->planenum; -++ int oobsize = mtd->oobsize / chip->planenum; -++ u8 *databuf, *oobbuf; -++ jz_dma_desc_8word *desc; -++ int err; -++ u32 addrport, cmdport; -++ static struct buf_be_corrected buf_correct0; -++ -++ addrport = (u32)(chip->IO_ADDR_R) | addr_offset; -++ cmdport = (u32)(chip->IO_ADDR_R) | cmd_offset; -++ -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ databuf = read_buf; -++ oobbuf = read_buf + pagesize; -++ -++ dma_cache_inv((u32)read_buf, pagesize + oobsize); // databuf should be invalidated. -++ memset(errs, 0, eccsteps * ERRS_SIZE * 4); -++ dma_cache_wback_inv((u32)errs, eccsteps * ERRS_SIZE * 4); -++#else -++ -++ databuf = buf; -++ oobbuf = chip->oob_poi; -++ -++ /* descriptor for nand reading data block */ -++ desc = dma_desc_nand_read; -++ desc->dsadr = CPHYSADDR((u32)chip->IO_ADDR_R); /* It will be changed when using multiply chip select */ -++ desc->dtadr = CPHYSADDR((u32)databuf); /* DMA target address */ -++ -++ dprintk("desc_nand_read:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -++ desc->ddadr); -++ -++ /* descriptor for nand reading oob block */ -++ desc++; -++ desc->dsadr = CPHYSADDR((u32)chip->IO_ADDR_R); /* It will be changed when using multiply chip select */ -++ desc->dtadr = CPHYSADDR((u32)oobbuf); /* DMA target address */ -++ dprintk("desc_oob_read:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -++ desc->ddadr); -++ -++ /* descriptors for data to be written to bch */ -++ desc = dma_desc_dec; -++ for (i = 0; i < eccsteps; i++) { -++ desc->dsadr = CPHYSADDR((u32)databuf) + i * eccsize; /* DMA source address */ -++ dprintk("dma_desc_dec:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -++ desc->ddadr); -++ desc++; -++ } -++ -++ /* descriptors for oob to be written to bch */ -++ desc = dma_desc_dec1; -++ for (i = 0; i < eccsteps; i++) { -++ desc->dsadr = CPHYSADDR((u32)oobbuf) + oob_per_eccsize * i; /* DMA source address */ -++ dprintk("dma_desc_dec1:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -++ desc->ddadr); -++ desc++; -++ } -++ -++ /* descriptors for parities to be written to bch */ -++ desc = dma_desc_dec2; -++ for (i = 0; i < eccsteps; i++) { -++ desc->dsadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA source address */ -++ dprintk("dma_desc_dec2:desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -++ desc->ddadr); -++ desc++; -++ } -++ -++ dma_cache_wback_inv((u32)dma_desc_nand_read, (2 + eccsteps * 3) * (sizeof(jz_dma_desc_8word))); -++ -++ memset(errs, 0, eccsteps * ERRS_SIZE * 4); -++ dma_cache_inv((u32)databuf, pagesize); // databuf should be invalidated. -++ dma_cache_inv((u32)oobbuf, oobsize); // oobbuf should be invalidated too -++ dma_cache_wback_inv((u32)errs, eccsteps * ERRS_SIZE * 4); -++#endif -++ REG_DMAC_DCCSR(bch_dma_chan) = 0; -++ REG_DMAC_DCCSR(nand_dma_chan) = 0; -++ -++ /* Setup DMA descriptor address */ -++ REG_DMAC_DDA(nand_dma_chan) = CPHYSADDR((u32)dma_desc_nand_read); -++ REG_DMAC_DDA(bch_dma_chan) = CPHYSADDR((u32)dma_desc_dec); -++ -++ /* Setup request source */ -++ REG_DMAC_DRSR(nand_dma_chan) = DMAC_DRSR_RS_NAND; -++ REG_DMAC_DRSR(bch_dma_chan) = DMAC_DRSR_RS_BCH_DEC; -++ -++ /* Enable DMA */ -++ REG_DMAC_DMACR(0) |= DMAC_DMACR_DMAE; -++ REG_DMAC_DMACR(nand_dma_chan/HALF_DMA_NUM) |= DMAC_DMACR_DMAE; -++ -++ /* Enable BCH decoding */ -++ chip->ecc.hwctl(mtd, NAND_ECC_READ); -++ -++ dma_ack = 0; -++ nand_status = NAND_READ; -++ /* DMA doorbell set -- start nand DMA now ... */ -++ __dmac_channel_set_doorbell(nand_dma_chan); -++ -++ /* Setup DMA channel control/status register */ -++ REG_DMAC_DCCSR(nand_dma_chan) = DMAC_DCCSR_DES8 | DMAC_DCCSR_EN; -++ -++#define __nand_cmd(n) (REG8(cmdport) = (n)) -++#define __nand_addr(n) (REG8(addrport) = (n)) -++ -++ __nand_cmd(NAND_CMD_READ0); -++ -++ __nand_addr(0); -++ if (pagesize != 512) -++ __nand_addr(0); -++ -++ __nand_addr(page & 0xff); -++ __nand_addr((page >> 8) & 0xff); -++ -++ /* One more address cycle for the devices whose number of page address bits > 16 */ -++ if (((chip->chipsize >> chip->page_shift) >> 16) - 1 > 0) -++ __nand_addr((page >> 16) & 0xff); -++ -++ if (pagesize != 512) -++ __nand_cmd(NAND_CMD_READSTART); -++ -++#if USE_IRQ -++ do { -++ err = wait_event_interruptible_timeout(nand_read_wait_queue, dma_ack, 3 * HZ); -++ }while(err == -ERESTARTSYS); -++ nand_status = NAND_NONE; -++ -++ if (!err) { -++ printk("*** NAND READ, Warning, wait event 3s timeout!\n"); -++ dump_jz_dma_channel(0); -++ dump_jz_dma_channel(nand_dma_chan); -++ printk("REG_BCH_CR=%x REG_BCH_CNT=0x%x REG_BCH_INTS=%x\n", REG_BCH_CR, REG_BCH_CNT, REG_BCH_INTS); -++ printk("databuf[0]=%x\n", databuf[0]); -++ } -++ dprintk("timeout remain = %d\n", err); -++#else -++ int timeout; -++ timeout = 100000; -++ while ((!__dmac_channel_transmit_end_detected(bch_dma_chan)) && (timeout--)); -++ if (timeout <= 0) { -++ printk("not use irq, NAND READ timeout!\n"); -++ } -++#endif -++ -++ for (i = 0; i < eccsteps; i++) { -++ int stat; -++ struct buf_be_corrected *buf_correct = &buf_correct0; -++ -++ buf_correct->data = databuf + eccsize * i; -++ buf_correct->oob = oobbuf + oob_per_eccsize * i; -++ -++ stat = chip->ecc.correct(mtd, (u8 *)buf_correct, (u8 *)&errs[i * ERRS_SIZE], NULL); -++ if (stat < 0) -++ mtd->ecc_stats.failed++; -++ else -++ mtd->ecc_stats.corrected += stat; -++ } -++ -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ memcpy(buf, read_buf, pagesize); -++ memcpy(chip->oob_poi, read_buf + pagesize, oobsize); -++#endif -++ return 0; -++} -++ -++static int nand_read_page_hwecc_bch(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf) -++{ -++ u32 page = global_page; -++ -++ nand_read_page_hwecc_bch0(mtd, chip, buf, page); -++ return 0; -++} -++ -++static int nand_read_page_hwecc_bch_planes(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf) -++{ -++ u32 page; -++ int pagesize = mtd->writesize >> 1; -++ int ppb = mtd->erasesize / mtd->writesize; -++ -++ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -++ -++ /* read 1st page */ -++ nand_read_page_hwecc_bch0(mtd, chip, buf, page); -++ -++ /* read 2nd page */ -++ nand_read_page_hwecc_bch0(mtd, chip, buf + pagesize, page + ppb); -++ return 0; -++} -++ -++#else /* nand read in cpu mode */ -++ -++static int nand_read_page_hwecc_bch(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf) -++{ -++ int i, eccsize = chip->ecc.size; -++ int eccbytes = chip->ecc.bytes; -++ int eccsteps = chip->ecc.steps / chip->planenum; -++ int ecc_pos = chip->ecc.layout->eccpos[0]; -++ int oob_per_eccsize = ecc_pos / eccsteps; -++ uint8_t *ecc_calc = chip->buffers->ecccalc; -++ uint8_t *ecc_code = chip->buffers->ecccode; -++ uint32_t *eccpos = chip->ecc.layout->eccpos; -++ int pagesize = mtd->writesize / chip->planenum; -++ int oobsize = mtd->oobsize / chip->planenum; -++ int ecctotal = chip->ecc.total / chip->planenum; -++ static struct buf_be_corrected buf_correct0; -++ -++ chip->read_buf(mtd, buf, pagesize); -++ chip->read_buf(mtd, chip->oob_poi, oobsize); -++ -++ for (i = 0; i < ecctotal; i++) { -++ ecc_code[i] = chip->oob_poi[eccpos[i]]; -++ } -++ -++ for (i = 0; i < eccsteps; i++) { -++ int stat; -++ struct buf_be_corrected *buf_correct = &buf_correct0; -++ -++ buf_correct->data = buf + eccsize * i; -++ buf_correct->oob = chip->oob_poi + oob_per_eccsize * i; -++ -++ chip->ecc.hwctl(mtd, NAND_ECC_READ); -++ stat = chip->ecc.correct(mtd, (u8 *)buf_correct, &ecc_code[eccbytes*i], &ecc_calc[eccbytes*i]); -++ if (stat < 0) -++ mtd->ecc_stats.failed++; -++ else -++ mtd->ecc_stats.corrected += stat; -++ } -++ -++ return 0; -++} -++ -++static int nand_read_page_hwecc_bch_planes(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf) -++{ -++ int pagesize = mtd->writesize >> 1; -++ int ppb = mtd->erasesize / mtd->writesize; -++ uint32_t page; -++ -++ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -++ -++ /* Read first page */ -++ chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); -++ nand_read_page_hwecc_bch(mtd, chip, buf); -++ -++ /* Read 2nd page */ -++ chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page + ppb); -++ nand_read_page_hwecc_bch(mtd, chip, buf+pagesize); -++ return 0; -++} -++#endif /* CONFIG_MTD_NAND_DMA */ -++ -++#endif /* CONFIG_MTD_HW_BCH_ECC */ -++ -++/* read oob using two-plane mode */ -++static int nand_read_oob_std_planes(struct mtd_info *mtd, struct nand_chip *chip, -++ int global_page, int sndcmd) -++{ -++ int page; -++ int oobsize = mtd->oobsize >> 1; -++ int ppb = mtd->erasesize / mtd->writesize; -++ -++ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -++ -++ /* Read first page OOB */ -++ if (sndcmd) { -++ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); -++ } -++ chip->read_buf(mtd, chip->oob_poi, oobsize); -++ /* Read second page OOB */ -++ page += ppb; -++ if (sndcmd) { -++ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); -++ sndcmd = 0; -++ } -++ chip->read_buf(mtd, chip->oob_poi+oobsize, oobsize); -++ return 0; -++} -++ -++/* write oob using two-plane mode */ -++static int nand_write_oob_std_planes(struct mtd_info *mtd, struct nand_chip *chip, -++ int global_page) -++{ -++ int status = 0, page; -++ const uint8_t *buf = chip->oob_poi; -++ int pagesize = mtd->writesize >> 1; -++ int oobsize = mtd->oobsize >> 1; -++ int ppb = mtd->erasesize / mtd->writesize; -++ -++ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -++ -++ /* send cmd 0x80, the MSB should be valid if realplane is 4 */ -++ if (chip->realplanenum == 2) -++ chip->cmdfunc(mtd, 0x80, pagesize, 0x00); -++ else -++ chip->cmdfunc(mtd, 0x80, pagesize, page & (1 << (chip->chip_shift - chip->page_shift))); -++ -++ chip->write_buf(mtd, buf, oobsize); -++ /* Send first command to program the OOB data */ -++ chip->cmdfunc(mtd, 0x11, -1, -1); -++ ndelay(100); -++ status = chip->waitfunc(mtd, chip); -++ -++ page += ppb; -++ buf += oobsize; -++ chip->cmdfunc(mtd, 0x81, pagesize, page); -++ chip->write_buf(mtd, buf, oobsize); -++ /* Send command to program the OOB data */ -++ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); -++ /* Wait long R/B */ -++ ndelay(100); -++ status = chip->waitfunc(mtd, chip); -++ -++ return status & NAND_STATUS_FAIL ? -EIO : 0; -++} -++ -++/* nand erase using two-plane mode */ -++static void single_erase_cmd_planes(struct mtd_info *mtd, int global_page) -++{ -++ struct nand_chip *chip = mtd->priv; -++ int page, ppb = mtd->erasesize / mtd->writesize; -++ -++ page = (global_page / ppb) * ppb + global_page; /* = global_page%ppb + (global_page/ppb)*ppb*2 */ -++ -++ /* send cmd 0x60, the MSB should be valid if realplane is 4 */ -++ if (chip->realplanenum == 2) -++ chip->cmdfunc(mtd, 0x60, -1, 0x00); -++ else -++ chip->cmdfunc(mtd, 0x60, -1, page & (1 << (chip->chip_shift - chip->page_shift))); -++ -++ page += ppb; -++ chip->cmdfunc(mtd, 0x60, -1, page & (~(ppb-1))); /* send cmd 0x60 */ -++ -++ chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); /* send cmd 0xd0 */ -++ /* Do not need wait R/B or check status */ -++} -++ -++#if defined(CONFIG_MTD_NAND_DMA) -++ -++#if USE_IRQ -++static irqreturn_t nand_dma_irq(int irq, void *dev_id) -++{ -++ u8 dma_chan; -++ volatile int wakeup = 0; -++ -++ dma_chan = irq - IRQ_DMA_0; -++ -++ dprintk("jz4750_dma_irq %d, channel %d\n", irq, dma_chan); -++ -++ if (__dmac_channel_transmit_halt_detected(dma_chan)) { -++ __dmac_channel_clear_transmit_halt(dma_chan); -++ wakeup = 1; -++ printk("DMA HALT\n"); -++ } -++ -++ if (__dmac_channel_address_error_detected(dma_chan)) { -++ -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ __dmac_channel_clear_address_error(dma_chan); -++ -++ REG_DMAC_DSAR(dma_chan) = 0; /* reset source address register */ -++ REG_DMAC_DTAR(dma_chan) = 0; /* reset destination address register */ -++ -++ /* clear address error in DMACR */ -++ REG_DMAC_DMACR((dma_chan / HALF_DMA_NUM)) &= ~(1 << 2); -++ wakeup = 1; -++ printk("DMA address error!\n"); -++ } -++ -++ if (__dmac_channel_descriptor_invalid_detected(dma_chan)) { -++ __dmac_channel_clear_descriptor_invalid(dma_chan); -++ wakeup = 1; -++ printk("DMA DESC INVALID\n"); -++ } -++#if 1 -++ -++ while (!__dmac_channel_transmit_end_detected(dma_chan)); -++ -++ if (__dmac_channel_count_terminated_detected(dma_chan)) { -++ dprintk("DMA CT\n"); -++ __dmac_channel_clear_count_terminated(dma_chan); -++ wakeup = 0; -++ } -++#endif -++ -++ if (__dmac_channel_transmit_end_detected(dma_chan)) { -++ dprintk("DMA TT\n"); -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ __dmac_channel_clear_transmit_end(dma_chan); -++ wakeup = 1; -++ } -++ -++ if (wakeup) { -++ dprintk("ack %d irq , wake up dma_chan %d nand_status %d\n", dma_ack, dma_chan, nand_status); -++ /* wakeup wait event */ -++ if ((dma_chan == nand_dma_chan) && (nand_status == NAND_PROG)) { -++ dprintk("nand prog dma irq, wake up----\n"); -++ dma_ack1 = 1; -++ wake_up_interruptible(&nand_prog_wait_queue); -++ } -++ -++ if ((dma_chan == bch_dma_chan) && (nand_status == NAND_READ)) { -++ dprintk("nand read irq, wake up----\n"); -++ dma_ack = 1; -++ wake_up_interruptible(&nand_read_wait_queue); -++ } -++ wakeup = 0; -++ } -++ -++ return IRQ_HANDLED; -++} -++#endif /* USE_IRQ */ -++ -++static int jz4750_nand_dma_init(struct mtd_info *mtd) -++{ -++ struct nand_chip *chip = mtd->priv; -++ int eccsize = chip->ecc.size; -++ int eccsteps = chip->ecc.steps / chip->planenum; -++ int eccbytes = chip->ecc.bytes; -++ int ecc_pos = chip->ecc.layout->eccpos[0]; -++ int oob_per_eccsize = ecc_pos / eccsteps; -++ int pagesize = mtd->writesize / chip->planenum; -++ int oobsize = mtd->oobsize / chip->planenum; -++ int i, err; -++ jz_dma_desc_8word *desc, *dma_desc_bch_ddr, *dma_desc_nand_ddr, *dma_desc_nand_cmd_pgprog; -++ u32 *pval_nand_dcs, *pval_bch_ddr, *pval_bch_dcs, *dummy; -++ u32 next; -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ u8 *oobbuf; -++#endif -++ -++#if USE_IRQ -++ if ((nand_dma_chan = jz_request_dma(DMA_ID_NAND, "nand read or write", nand_dma_irq, IRQF_DISABLED, NULL)) < 0) { -++ printk("can't reqeust DMA nand channel.\n"); -++ return 0; -++ } -++ dprintk("nand dma channel:%d----\n", nand_dma_chan); -++ -++ if ((err = request_irq(IRQ_DMA_0 + bch_dma_chan, nand_dma_irq, IRQF_DISABLED, "bch_dma", NULL))) { -++ printk("bch_dma irq request err\n"); -++ return 0; -++ } -++#else -++ if ((nand_dma_chan = jz_request_dma(DMA_ID_NAND, "nand read or write", NULL, IRQF_DISABLED, NULL)) < 0) { -++ printk("can't reqeust DMA nand channel.\n"); -++ return 0; -++ } -++ dprintk("nand dma channel:%d----\n", nand_dma_chan); -++#endif -++ -++ __dmac_channel_enable_clk(nand_dma_chan); -++ __dmac_channel_enable_clk(bch_dma_chan); -++ -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ if (pagesize < 4096) { -++ read_buf = prog_buf = (u8 *) __get_free_page(GFP_KERNEL); -++ } else { -++ read_buf = prog_buf = (u8 *) __get_free_pages(GFP_KERNEL, 1); -++ } -++ if (!read_buf) -++ return -ENOMEM; -++#endif -++ /* space for the error reports of bch decoding((4 * 5 * eccsteps) bytes), and the space for the value -++ * of ddr and dcs of channel 0 and channel nand_dma_chan (4 * (2 + 2) bytes) */ -++ errs = (u32 *)kmalloc(4 * (2 + 2 + 5 * eccsteps), GFP_KERNEL); -++ if (!errs) -++ return -ENOMEM; -++ -++ pval_nand_ddr = errs + 5 * eccsteps; -++ pval_nand_dcs = pval_nand_ddr + 1; -++ pval_bch_ddr = pval_nand_dcs + 1; -++ pval_bch_dcs = pval_bch_ddr + 1; -++ /* space for nand prog waiting target, the content is useless */ -++ dummy = pval_bch_dcs + 1; -++ /* space to store CMD_PGPROG(0x10) or 0x11 */ -++ pval_nand_cmd_pgprog = (u8 *)(dummy + 1); -++ -++ /* desc can't across 4KB boundary, as desc base address is fixed */ -++ /* space of descriptors for nand reading data and oob blocks */ -++ dma_desc_nand_read = (jz_dma_desc_8word *) __get_free_page(GFP_KERNEL); -++ if (!dma_desc_nand_read) -++ return -ENOMEM; -++ -++ /* space of descriptors for bch decoding */ -++ dma_desc_dec = dma_desc_nand_read + 2; -++ dma_desc_dec1 = dma_desc_dec + eccsteps; -++ dma_desc_dec2 = dma_desc_dec + eccsteps * 2; -++ -++ /* space of descriptors for notifying bch channel */ -++ dma_desc_bch_ddr = dma_desc_dec2 + eccsteps; -++ -++ /* space of descriptors for bch encoding */ -++ dma_desc_enc = dma_desc_bch_ddr + 2; -++ dma_desc_enc1 = dma_desc_enc + eccsteps; -++ -++ /* space of descriptors for nand programing data and oob blocks */ -++ dma_desc_nand_prog = dma_desc_enc1 + eccsteps; -++ -++ /* space of descriptors for nand prog waiting, including pgprog and sync */ -++ dma_desc_nand_cmd_pgprog = dma_desc_nand_prog + 2; -++ -++ /* space of descriptors for notifying nand channel, including ddr and dcsr */ -++ dma_desc_nand_ddr = dma_desc_nand_cmd_pgprog + 2; -++ -++/************************************* -++ * Setup of nand programing descriptors -++ *************************************/ -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ oobbuf = prog_buf + pagesize; -++#endif -++ /* set descriptor for encoding data blocks */ -++ desc = dma_desc_enc; -++ for (i = 0; i < eccsteps; i++) { -++ next = (CPHYSADDR((u32)dma_desc_enc1) + i * (sizeof(jz_dma_desc_8word))) >> 4; -++ -++ desc->dcmd = -++ DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | -++ DMAC_DCMD_DS_BCH | DMAC_DCMD_LINK; -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ desc->dsadr = CPHYSADDR((u32)prog_buf) + i * eccsize; /* DMA source address */ -++ desc->dtadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA target address */ -++#endif -++ desc->ddadr = (next << 24) + eccsize / DIV_DS_BCH; /* size: eccsize bytes */ -++ desc->dreqt = DMAC_DRSR_RS_BCH_ENC; -++ dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); -++ desc++; -++ } -++ -++ /* set descriptor for encoding oob blocks */ -++ desc = dma_desc_enc1; -++ for (i = 0; i < eccsteps; i++) { -++ next = (CPHYSADDR((u32)dma_desc_enc) + (i + 1) * (sizeof(jz_dma_desc_8word))) >> 4; -++ -++ desc->dcmd = -++ DMAC_DCMD_BLAST | DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | -++ DMAC_DCMD_DWDH_8 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_LINK; -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ desc->dsadr = CPHYSADDR((u32)oobbuf) + oob_per_eccsize * i; /* DMA source address, 28/4 = 7bytes */ -++ desc->dtadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA target address */ -++#endif -++ desc->ddadr = (next << 24) + (oob_per_eccsize + 3) / 4; /* size: 7 bytes -> 2 words */ -++ desc->dreqt = DMAC_DRSR_RS_BCH_ENC; -++ dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); -++ desc++; -++ } -++ -++ next = (CPHYSADDR((u32)dma_desc_nand_ddr)) >> 4; -++ desc--; -++ desc->ddadr = (next << 24) + (oob_per_eccsize + 3) / 4; -++ -++ /* set the descriptor to set door bell of nand_dma_chan for programing nand */ -++ desc = dma_desc_nand_ddr; -++ *pval_nand_ddr = 1 << (nand_dma_chan - nand_dma_chan / HALF_DMA_NUM * HALF_DMA_NUM); -++ next = (CPHYSADDR((u32)dma_desc_nand_ddr) + sizeof(jz_dma_desc_8word)) >> 4; -++ desc->dcmd = DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_LINK; -++ desc->dsadr = CPHYSADDR((u32)pval_nand_ddr); /* DMA source address */ -++ desc->dtadr = CPHYSADDR(DMAC_DMADBSR(nand_dma_chan / HALF_DMA_NUM)); /* nand_dma_chan's descriptor addres register */ -++ desc->ddadr = (next << 24) + 1; /* size: 1 word */ -++ desc->dreqt = DMAC_DRSR_RS_AUTO; -++ dprintk("*pval_nand_ddr=0x%x\n", *pval_nand_ddr); -++ -++ /* set the descriptor to write dccsr of nand_dma_chan for programing nand, dccsr should be set at last */ -++ desc++; -++ *pval_nand_dcs = DMAC_DCCSR_DES8 | DMAC_DCCSR_EN; /* set value for writing ddr to enable channel nand_dma_chan */ -++ desc->dcmd = DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT; -++ desc->dsadr = CPHYSADDR((u32)pval_nand_dcs); /* DMA source address */ -++ desc->dtadr = CPHYSADDR(DMAC_DCCSR(nand_dma_chan)); /* address of dma door bell set register */ -++ desc->ddadr = (0 << 24) + 1; /* size: 1 word */ -++ desc->dreqt = DMAC_DRSR_RS_AUTO; -++ dprintk("*pval_nand_dcs=0x%x\n", *pval_nand_dcs); -++ -++ /* set descriptor for nand programing data block */ -++ desc = dma_desc_nand_prog; -++ next = (CPHYSADDR((u32)dma_desc_nand_prog) + sizeof(jz_dma_desc_8word)) >> 4; -++ desc->dcmd = -++ DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | -++ DMAC_DCMD_DS_NAND | DMAC_DCMD_LINK; -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ desc->dsadr = CPHYSADDR((u32)prog_buf); /* DMA source address */ -++#endif -++ desc->dtadr = CPHYSADDR((u32)(chip->IO_ADDR_W)); /* DMA target address */ -++ desc->ddadr = (next << 24) + pagesize / DIV_DS_NAND; /* size: eccsize bytes */ -++ desc->dreqt = DMAC_DRSR_RS_AUTO; -++ dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); -++ -++ /* set descriptor for nand programing oob block */ -++ desc++; -++ next = (CPHYSADDR((u32)dma_desc_nand_cmd_pgprog)) >> 4; -++ desc->dcmd = -++ DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | -++ DMAC_DCMD_DS_NAND | DMAC_DCMD_LINK; -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ desc->dsadr = CPHYSADDR((u32)oobbuf); /* DMA source address */ -++#endif -++ desc->dtadr = CPHYSADDR((u32)(chip->IO_ADDR_W)); /* DMA target address: dataport */ -++ desc->ddadr = (next << 24) + oobsize / DIV_DS_NAND; /* size: eccsize bytes */ -++ desc->dreqt = DMAC_DRSR_RS_AUTO; -++ dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); -++ -++ /* set descriptor for __nand_cmd(CMD_PGPROG) */ -++ desc = dma_desc_nand_cmd_pgprog; -++ *pval_nand_cmd_pgprog = NAND_CMD_PAGEPROG; -++ next = (CPHYSADDR((u32)dma_desc_nand_cmd_pgprog) + sizeof(jz_dma_desc_8word)) >> 4; -++ desc->dcmd = -++ DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_8 | DMAC_DCMD_DS_8BIT | DMAC_DCMD_LINK; -++ desc->dsadr = CPHYSADDR((u32)pval_nand_cmd_pgprog); /* DMA source address */ -++ desc->dtadr = CPHYSADDR((u32)chip->IO_ADDR_R | cmd_offset); /* DMA target address: cmdport */ -++ desc->ddadr = (next << 24) + 1; /* size: 1 byte */ -++ desc->dreqt = DMAC_DRSR_RS_AUTO; -++ dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); -++ -++ /* set descriptor for __nand_sync() */ -++ desc++; -++#if USE_IRQ -++ desc->dcmd = -++ DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_TIE; -++#else -++ desc->dcmd = -++ DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT; -++#endif -++ desc->dsadr = CPHYSADDR((u32)pval_nand_ddr); /* DMA source address */ -++ desc->dtadr = CPHYSADDR((u32)dummy); /* DMA target address, the content is useless */ -++ desc->ddadr = (0 << 24) + 1; /* size: 1 word */ -++ desc->dreqt = DMAC_DRSR_RS_NAND; -++ dprintk("1cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); -++ -++ /* eccsteps*2 + 2 + 2 + 2: -++ dma_desc_enc + dma_desc_enc1 + dma_desc_nand_prog(oob) + dma_desc_nand_ddr(csr) -++ + dma_desc_nand_cmd_pgprog(sync) */ -++ dma_cache_wback_inv((u32)dma_desc_enc, (eccsteps * 2 + 2 + 2 + 2) * (sizeof(jz_dma_desc_8word))); -++ /* 4*6: pval_nand_ddr, pval_nand_dcs, pval_bch_ddr, pval_bch_dcs, dummy, pval_nand_cmd_pgprog */ -++ dma_cache_wback_inv((u32)pval_nand_ddr, 4 * 8); /* 8 words, a cache line */ -++ -++/************************************* -++ * Setup of nand reading descriptors -++ *************************************/ -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ oobbuf = read_buf + pagesize; -++#endif -++ /* set descriptor for nand reading data block */ -++ desc = dma_desc_nand_read; -++ next = (CPHYSADDR((u32)dma_desc_nand_read) + sizeof(jz_dma_desc_8word)) >> 4; -++ desc->dcmd = -++ DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | -++ DMAC_DCMD_DS_NAND | DMAC_DCMD_LINK; -++ desc->dsadr = CPHYSADDR((u32)(chip->IO_ADDR_R)); /* DMA source address */ -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ desc->dtadr = CPHYSADDR((u32)read_buf); /* DMA target address */ -++#endif -++ desc->ddadr = (next << 24) + pagesize / DIV_DS_NAND; /* size: eccsize bytes */ -++ desc->dreqt = DMAC_DRSR_RS_NAND; -++ dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); -++ -++ /* set descriptor for nand reading oob block */ -++ desc++; -++ next = (CPHYSADDR((u32)dma_desc_bch_ddr)) >> 4; -++ desc->dcmd = -++ DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | -++ DMAC_DCMD_DS_NAND | DMAC_DCMD_LINK; -++ desc->dsadr = CPHYSADDR((u32)(chip->IO_ADDR_R)); /* DMA source address */ -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ desc->dtadr = CPHYSADDR((u32)oobbuf); /* DMA target address */ -++#endif -++ desc->ddadr = (next << 24) + oobsize / DIV_DS_NAND; /* size: eccsize bytes */ -++ desc->dreqt = DMAC_DRSR_RS_AUTO; -++ dprintk("cmd:%x sadr:%x tadr:%x dadr:%x\n", desc->dcmd, desc->dsadr, desc->dtadr, desc->ddadr); -++ -++ /* set the descriptor to set door bell for bch */ -++ desc = dma_desc_bch_ddr; -++ *pval_bch_ddr = DMAC_DMADBSR_DBS0; // set value for writing ddr to enable channel 0 -++ next = (CPHYSADDR((u32)dma_desc_bch_ddr) + sizeof(jz_dma_desc_8word)) >> 4; -++ desc->dcmd = DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_LINK; -++ desc->dsadr = CPHYSADDR((u32)pval_bch_ddr); /* DMA source address */ -++ desc->dtadr = CPHYSADDR(DMAC_DMADBSR(0)); /* channel 1's descriptor addres register */ -++ desc->ddadr = (next << 24) + 1; /* size: 1 word */ -++ desc->dreqt = DMAC_DRSR_RS_AUTO; -++ -++ /* set descriptor for writing dcsr */ -++ desc++; -++ *pval_bch_dcs = DMAC_DCCSR_DES8 | DMAC_DCCSR_EN; // set value for writing ddr to enable channel 1 -++ desc->dcmd = DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT; -++ desc->dsadr = CPHYSADDR((u32)pval_bch_dcs); /* DMA source address */ -++ desc->dtadr = CPHYSADDR(DMAC_DCCSR(bch_dma_chan)); /* address of dma door bell set register */ -++ desc->ddadr = (0 << 24) + 1; /* size: 1 word */ -++ desc->dreqt = DMAC_DRSR_RS_AUTO; -++ -++ /* descriptors for data to be written to bch */ -++ desc = dma_desc_dec; -++ for (i = 0; i < eccsteps; i++) { -++ next = CPHYSADDR((u32)dma_desc_dec1 + i * (sizeof(jz_dma_desc_8word))) >> 4; -++ -++ desc->dcmd = -++ DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | -++ DMAC_DCMD_DS_BCH | DMAC_DCMD_LINK; -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ desc->dsadr = CPHYSADDR((u32)read_buf) + i * eccsize; /* DMA source address */ -++#endif -++ desc->dtadr = CPHYSADDR((u32)errs) + i * 4 * ERRS_SIZE; /* DMA target address */ -++ desc->ddadr = (next << 24) + eccsize / DIV_DS_BCH; /* size: eccsize bytes */ -++ desc->dreqt = DMAC_DRSR_RS_BCH_DEC; -++ dprintk("desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -++ desc->ddadr); -++ desc++; -++ } -++ -++ /* descriptors for oob to be written to bch */ -++ desc = dma_desc_dec1; -++ for (i = 0; i < eccsteps; i++) { -++ next = CPHYSADDR((u32)dma_desc_dec2 + i * (sizeof(jz_dma_desc_8word))) >> 4; -++ -++ desc->dcmd = -++ DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | -++ DMAC_DCMD_DS_8BIT | DMAC_DCMD_LINK; -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ desc->dsadr = CPHYSADDR((u32)oobbuf) + oob_per_eccsize * i; /* DMA source address */ -++#endif -++ desc->dtadr = CPHYSADDR((u32)errs) + i * 4 * ERRS_SIZE; /* DMA target address */ -++ desc->ddadr = (next << 24) + oob_per_eccsize; /* size: 7 bytes */ -++ desc->dreqt = DMAC_DRSR_RS_BCH_DEC; -++ dprintk("desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -++ desc->ddadr); -++ desc++; -++ } -++ -++ /* descriptors for parities to be written to bch */ -++ desc = dma_desc_dec2; -++ for (i = 0; i < eccsteps; i++) { -++ next = (CPHYSADDR((u32)dma_desc_dec) + (i + 1) * (sizeof(jz_dma_desc_8word))) >> 4; -++ -++ desc->dcmd = -++ DMAC_DCMD_BLAST | DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_8 | -++ DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_BCH | DMAC_DCMD_LINK; -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ desc->dsadr = CPHYSADDR((u32)oobbuf) + ecc_pos + i * eccbytes; /* DMA source address */ -++#endif -++ desc->dtadr = CPHYSADDR((u32)errs) + i * 4 * ERRS_SIZE; /* DMA target address */ -++ desc->ddadr = (next << 24) + (eccbytes + 15) / DIV_DS_BCH; /* size: eccbytes bytes */ -++ desc->dreqt = DMAC_DRSR_RS_BCH_DEC; -++ dprintk("desc:%x cmd:%x sadr:%x tadr:%x dadr:%x\n", (u32)desc, desc->dcmd, desc->dsadr, desc->dtadr, -++ desc->ddadr); -++ desc++; -++ } -++ desc--; -++ desc->dcmd &= ~DMAC_DCMD_LINK; -++#if USE_IRQ -++ desc->dcmd |= DMAC_DCMD_TIE; -++#endif -++ -++ dma_cache_wback_inv((u32)dma_desc_nand_read, (2 + 2 + eccsteps * 3) * (sizeof(jz_dma_desc_8word))); -++ dma_cache_wback_inv((u32)pval_bch_ddr, 4 * 2); /* two words */ -++ -++ return 0; -++} -++ -++#endif /* CONFIG_MTD_NAND_DMA */ -++/* -++ * Main initialization routine -++ */ -++int __init jznand_init(void) -++{ -++ struct nand_chip *this; -++ int nr_partitions, ret, i; -++ -++ printk(KERN_INFO "JZ NAND init"); -++#if defined(CONFIG_MTD_NAND_DMA) -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ printk(KERN_INFO " DMA mode, using DMA buffer in NAND driver.\n"); -++#else -++ printk(KERN_INFO " DMA mode, using DMA buffer in upper layer.\n"); -++#endif -++#else -++ printk(KERN_INFO " CPU mode.\n"); -++#endif -++ -++ -++ /* Allocate memory for MTD device structure and private data */ -++ jz_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); -++ if (!jz_mtd) { -++ printk("Unable to allocate JzSOC NAND MTD device structure.\n"); -++ return -ENOMEM; -++ } -++ -++ /* Allocate memory for NAND when using only one plane */ -++ jz_mtd1 = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL); -++ if (!jz_mtd1) { -++ printk ("Unable to allocate JzSOC NAND MTD device structure 1.\n"); -++ kfree(jz_mtd); -++ return -ENOMEM; -++ } -++ -++ /* Get pointer to private data */ -++ this = (struct nand_chip *)(&jz_mtd[1]); -++ -++ /* Initialize structures */ -++ memset((char *)jz_mtd, 0, sizeof(struct mtd_info)); -++ memset((char *)this, 0, sizeof(struct nand_chip)); -++ -++ /* Link the private data with the MTD structure */ -++ jz_mtd->priv = this; -++ -++ if (is_share_mode()) { -++ addr_offset = NAND_ADDR_OFFSET0; -++ cmd_offset = NAND_CMD_OFFSET0; -++ } else { -++ addr_offset = NAND_ADDR_OFFSET1; -++ cmd_offset = NAND_CMD_OFFSET1; -++ } -++ -++ /* Set & initialize NAND Flash controller */ -++ jz_device_setup(); -++ -++ /* Set address of NAND IO lines to static bank1 by default */ -++ this->IO_ADDR_R = (void __iomem *)NAND_DATA_PORT1; -++ this->IO_ADDR_W = (void __iomem *)NAND_DATA_PORT1; -++ this->cmd_ctrl = jz_hwcontrol; -++ this->dev_ready = jz_device_ready; -++ -++#ifdef CONFIG_MTD_HW_BCH_ECC -++ this->ecc.calculate = jzsoc_nand_calculate_bch_ecc; -++ this->ecc.correct = jzsoc_nand_bch_correct_data; -++ this->ecc.hwctl = jzsoc_nand_enable_bch_hwecc; -++ this->ecc.mode = NAND_ECC_HW; -++ this->ecc.size = 512; -++ this->ecc.read_page = nand_read_page_hwecc_bch; -++ this->ecc.write_page = nand_write_page_hwecc_bch; -++#if defined(CONFIG_MTD_HW_BCH_8BIT) -++ this->ecc.bytes = 13; -++#else -++ this->ecc.bytes = 7; -++#endif -++#endif -++ -++#ifdef CONFIG_MTD_SW_HM_ECC -++ this->ecc.mode = NAND_ECC_SOFT; -++#endif -++ /* 20 us command delay time */ -++ this->chip_delay = 20; -++ /* Scan to find existance of the device */ -++ ret = nand_scan_ident(jz_mtd, NAND_MAX_CHIPS); -++ -++ if (!ret) { -++ if (this->planenum == 2) { -++ /* reset nand functions */ -++ this->erase_cmd = single_erase_cmd_planes; -++ this->ecc.read_page = nand_read_page_hwecc_bch_planes; -++ this->ecc.write_page = nand_write_page_hwecc_bch_planes; -++ this->ecc.read_oob = nand_read_oob_std_planes; -++ this->ecc.write_oob = nand_write_oob_std_planes; -++ -++ printk(KERN_INFO "Nand using two-plane mode, " -++ "and resized to writesize:%d oobsize:%d blocksize:0x%x \n", -++ jz_mtd->writesize, jz_mtd->oobsize, jz_mtd->erasesize); -++ } -++ } -++ -++ /* Determine whether all the partitions will use multiple planes if supported */ -++ nr_partitions = sizeof(partition_info) / sizeof(struct mtd_partition); -++ all_use_planes = 1; -++ for (i = 0; i < nr_partitions; i++) { -++ all_use_planes &= partition_info[i].use_planes; -++ } -++ -++ if (!ret) -++ ret = nand_scan_tail(jz_mtd); -++ -++ if (ret){ -++ kfree (jz_mtd1); -++ kfree (jz_mtd); -++ return -ENXIO; -++ } -++ -++#if defined(CONFIG_MTD_NAND_DMA) -++ jz4750_nand_dma_init(jz_mtd); -++#endif -++ -++ ((struct nand_chip *) (&jz_mtd1[1]))->ecc.read_page = nand_read_page_hwecc_bch; -++ ((struct nand_chip *) (&jz_mtd1[1]))->ecc.write_page = nand_write_page_hwecc_bch; -++ -++ /* Register the partitions */ -++ printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nr_partitions, jz_mtd->name); -++ -++ if ((this->planenum == 2) && !all_use_planes) { -++ for (i = 0; i < nr_partitions; i++) { -++ if (partition_info[i].use_planes) -++ add_mtd_partitions(jz_mtd, &partition_info[i], 1); -++ else -++ add_mtd_partitions(jz_mtd1, &partition_info[i], 1); -++ } -++ } else { -++ kfree(jz_mtd1); -++ add_mtd_partitions(jz_mtd, partition_info, nr_partitions); -++ } -++ return 0; -++} -++ -++module_init(jznand_init); -++ -++/* -++ * Clean up routine -++ */ -++#ifdef MODULE -++ -++#if defined(CONFIG_MTD_NAND_DMA) -++static int jz4750_nand_dma_exit(struct mtd_info *mtd) -++{ -++ int pagesize = mtd->writesize / chip->planenum; -++ -++#if USE_IRQ -++ free_irq(IRQ_DMA_0 + nand_dma_chan, NULL); -++ free_irq(IRQ_DMA_0 + bch_dma_chan, NULL); -++#endif -++ -++ /* space for the error reports of bch decoding((4 * 5 * eccsteps) bytes), -++ * and the space for the value of ddr and dcs of channel 0 and channel -++ * nand_dma_chan (4 * (2 + 2) bytes) */ -++ kfree(errs); -++ -++ /* space for dma_desc_nand_read contains dma_desc_nand_prog, -++ * dma_desc_enc and dma_desc_dec */ -++ free_page((u32)dma_desc_nand_read); -++ -++#if defined(CONFIG_MTD_NAND_DMABUF) -++ if (pagesize < 4096) { -++ free_page((u32)prog_buf); -++ } else { -++ free_pages((u32)prog_buf, 1); -++ } -++#endif -++ -++ return 0; -++} -++#endif -++ -++static void __exit jznand_cleanup(void) -++{ -++#if defined(CONFIG_MTD_NAND_DMA) -++ jz4750_nand_dma_exit(jz_mtd); -++#endif -++ -++ /* Unregister partitions */ -++ del_mtd_partitions(jz_mtd); -++ -++ /* Unregister the device */ -++ del_mtd_device(jz_mtd); -++ -++ /* Free the MTD device structure */ -++ if ((this->planenum == 2) && !all_use_planes) -++ kfree (jz_mtd1); -++ kfree(jz_mtd); -++} -++ -++module_exit(jznand_cleanup); -++#endif -+diff -urN linux-2.6.24.7.old/drivers/mtd/nand/nand_base.c linux-2.6.24.7/drivers/mtd/nand/nand_base.c -+--- linux-2.6.24.7.old/drivers/mtd/nand/nand_base.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/nand/nand_base.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -52,6 +52,16 @@ -+ #include -+ #endif -+ -++#include -++ -++u8 nand_nce; /* indicates which chip select on JZSOC is used for -++ current nand chip */ -++int global_page; /* page index of large page used for nand with multiple planes */ -++ -++struct mtd_info *jz_mtd1 = NULL; /* for 1 plane operation */ -++char all_use_planes = 1; /* indicates whether multiple planes operation is used -++ by all partitions if multiple planes is supported by NAND */ -++ -+ /* Define default oob placement schemes for large and small page devices */ -+ static struct nand_ecclayout nand_oob_8 = { -+ .eccbytes = 3, -+@@ -72,6 +82,20 @@ -+ }; -+ -+ static struct nand_ecclayout nand_oob_64 = { -++#if defined(CONFIG_MTD_HW_RS_ECC) || defined(CONFIG_MTD_HW_BCH_ECC) -++/* Reed-Solomon ECC or BCH ECC */ -++ .eccbytes = 36, -++ .eccpos = { -++ 28, 29, 30, 31, -++ 32, 33, 34, 35, 36, 37, 38, 39, -++ 40, 41, 42, 43, 44, 45, 46, 47, -++ 48, 49, 50, 51, 52, 53, 54, 55, -++ 56, 57, 58, 59, 60, 61, 62, 63}, -++ .oobfree = { -++ {.offset = 2, -++ . length = 26}} -++#else -++/* HW&SW Hamming ECC */ -+ .eccbytes = 24, -+ .eccpos = { -+ 40, 41, 42, 43, 44, 45, 46, 47, -+@@ -80,12 +104,85 @@ -+ .oobfree = { -+ {.offset = 2, -+ .length = 38}} -++#endif -++}; -++ -++static struct nand_ecclayout nand_oob_128 = { -++#if defined(CONFIG_MTD_HW_RS_ECC) -++/* Reed-Solomon ECC */ -++ .eccbytes = 72, -++ .eccpos = { -++ 56, 57, 58, 59, 60, 61, 62, 63, -++ 64, 65, 66, 67, 68, 69, 70, 71, -++ 72, 73, 74, 75, 76, 77, 78, 79, -++ 80, 81, 82, 83, 84, 85, 86, 87, -++ 88, 89, 90, 91, 92, 93, 94, 95, -++ 96, 97, 98, 99, 100, 101, 102, 103, -++ 104, 105, 106, 107, 108, 109, 110, 111, -++ 112, 113, 114, 115, 116, 117, 118, 119, -++ 120, 121, 122, 123, 124, 125, 126, 127}, -++ .oobfree = { -++ {.offset = 2, -++ . length = 54}} -++ -++#elif defined(CONFIG_MTD_HW_BCH_ECC) -++#if !defined(CONFIG_MTD_HW_BCH_8BIT) -++/* 4-bit BCH ECC */ -++ .eccbytes = 56, -++ .eccpos = { -++ 72, 73, 74, 75, 76, 77, 78, 79, -++ 80, 81, 82, 83, 84, 85, 86, 87, -++ 88, 89, 90, 91, 92, 93, 94, 95, -++ 96, 97, 98, 99, 100, 101, 102, 103, -++ 104, 105, 106, 107, 108, 109, 110, 111, -++ 112, 113, 114, 115, 116, 117, 118, 119, -++ 120, 121, 122, 123, 124, 125, 126, 127}, -++ .oobfree = { -++ {.offset = 2, -++ . length = 70}} -++ -++#else -++/* 8-bit BCH ECC */ -++ .eccbytes = 104, -++ .eccpos = { -++ 24, 25, 26, 27, 28, 29, 30, 31, -++ 32, 33, 34, 35, 36, 37, 38, 39, -++ 40, 41, 42, 43, 44, 45, 46, 47, -++ 48, 49, 50, 51, 52, 53, 54, 55, -++ 56, 57, 58, 59, 60, 61, 62, 63, -++ 64, 65, 66, 67, 68, 69, 70, 71, -++ 72, 73, 74, 75, 76, 77, 78, 79, -++ 80, 81, 82, 83, 84, 85, 86, 87, -++ 88, 89, 90, 91, 92, 93, 94, 95, -++ 96, 97, 98, 99, 100, 101, 102, 103 -++ 104, 105, 106, 107, 108, 109, 110, 111, -++ 112, 113, 114, 115, 116, 117, 118, 119, -++ 120, 121, 122, 123, 124, 125, 126, 127}, -++ .oobfree = { -++ {.offset = 2, -++ . length = 22}} -++ -++#endif -++#else -++/* HW&SW Hamming ECC */ -++ .eccbytes = 48, -++ .eccpos = { -++ 80, 81, 82, 83, 84, 85, 86, 87, -++ 88, 89, 90, 91, 92, 93, 94, 95, -++ 96, 97, 98, 99, 100, 101, 102, 103, -++ 104, 105, 106, 107, 108, 109, 110, 111, -++ 112, 113, 114, 115, 116, 117, 118, 119, -++ 120, 121, 122, 123, 124, 125, 126, 127}, -++ .oobfree = { -++ {.offset = 2, -++ .length = 78}} -++#endif -+ }; -+ -+ static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, -+ int new_state); -+ -+-static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, -++static int nand_do_write_oob(struct mtd_info *mtd, loff_mtd_t to, -+ struct mtd_oob_ops *ops); -+ -+ /* -+@@ -95,6 +192,35 @@ -+ DEFINE_LED_TRIGGER(nand_led_trigger); -+ -+ /** -++ * ffs_ll - find first bit set in a 64bit word. -++ * @word: The word to search -++ */ -++static inline int ffs_ll(u64 word) -++{ -++ u32 low = word & 0xffffffff; -++ u32 high = word >> 32; -++ int i; -++ -++ for(i = 0; i < 32; i++) { -++ if (low & 0x1) -++ break; -++ low >>= 1; -++ } -++ if (i == 32) { -++ for(i = 0; i < 32; i++) { -++ if (high & 0x1) -++ break; -++ high >>= 1; -++ } -++ i += 32; -++ } -++ if (i == 64) -++ return 0; -++ else -++ return (i+1); -++} -++ -++/** -+ * nand_release_device - [GENERIC] release chip -+ * @mtd: MTD device structure -+ * -+@@ -169,6 +295,20 @@ -+ chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); -+ break; -+ case 0: -++ nand_nce = NAND_NCE1; -++ chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); -++ break; -++ case 1: -++ nand_nce = NAND_NCE2; -++ chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); -++ break; -++ case 2: -++ nand_nce = NAND_NCE3; -++ chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); -++ break; -++ case 3: -++ nand_nce = NAND_NCE4; -++ chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); -+ break; -+ -+ default: -+@@ -298,13 +438,19 @@ -+ * -+ * Check, if the block is bad. -+ */ -+-static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) -++static int nand_block_bad(struct mtd_info *mtd, loff_mtd_t ofs, int getchip) -+ { -+- int page, chipnr, res = 0; -++ int page, page1 = 0, chipnr, res = 0; -+ struct nand_chip *chip = mtd->priv; -+ u16 bad; -+ -+- page = (int)(ofs >> chip->page_shift) & chip->pagemask; -++ if (chip->planenum > 1) { -++ page = ((int)(ofs >> chip->page_shift) * chip->planenum + CONFIG_MTD_BADBLOCK_FLAG_PAGE); -++ page1 = page + mtd->erasesize / mtd->writesize; -++ page &= chip->pagemask; -++ page1 &= chip->pagemask; -++ } else -++ page = ((int)(ofs >> chip->page_shift) + CONFIG_MTD_BADBLOCK_FLAG_PAGE) & chip->pagemask; -+ -+ if (getchip) { -+ chipnr = (int)(ofs >> chip->chip_shift); -+@@ -327,6 +473,11 @@ -+ chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, page); -+ if (chip->read_byte(mtd) != 0xff) -+ res = 1; -++ if (chip->planenum > 1) { -++ chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, page1); -++ if (chip->read_byte(mtd) != 0xff) -++ res = 1; -++ } -+ } -+ -+ if (getchip) -+@@ -343,7 +494,7 @@ -+ * This is the default implementation, which can be overridden by -+ * a hardware specific driver. -+ */ -+-static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) -++static int nand_default_block_markbad(struct mtd_info *mtd, loff_mtd_t ofs) -+ { -+ struct nand_chip *chip = mtd->priv; -+ uint8_t buf[2] = { 0, 0 }; -+@@ -363,6 +514,7 @@ -+ */ -+ nand_get_device(chip, mtd, FL_WRITING); -+ ofs += mtd->oobsize; -++ ofs += (CONFIG_MTD_BADBLOCK_FLAG_PAGE << chip->page_shift); -+ chip->ops.len = chip->ops.ooblen = 2; -+ chip->ops.datbuf = NULL; -+ chip->ops.oobbuf = buf; -+@@ -402,7 +554,7 @@ -+ * Check, if the block is bad. Either by reading the bad block table or -+ * calling of the scan function. -+ */ -+-static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, -++static int nand_block_checkbad(struct mtd_info *mtd, loff_mtd_t ofs, int getchip, -+ int allowbbt) -+ { -+ struct nand_chip *chip = mtd->priv; -+@@ -554,7 +706,10 @@ -+ -+ /* Emulate NAND_CMD_READOOB */ -+ if (command == NAND_CMD_READOOB) { -+- column += mtd->writesize; -++ if (chip->planenum > 1) -++ column += (mtd->writesize / chip->planenum); -++ else -++ column += mtd->writesize; -+ command = NAND_CMD_READ0; -+ } -+ -+@@ -600,6 +755,8 @@ -+ case NAND_CMD_RNDIN: -+ case NAND_CMD_STATUS: -+ case NAND_CMD_DEPLETE1: -++ case 0x81: /* for two-plane page program */ -++ case 0x11: /* for two-plane page program */ -+ return; -+ -+ /* -+@@ -675,7 +832,6 @@ -+ spin_lock(lock); -+ -+ /* Hardware controller shared among independend devices */ -+- /* Hardware controller shared among independend devices */ -+ if (!chip->controller->active) -+ chip->controller->active = chip; -+ -+@@ -797,6 +953,7 @@ -+ return 0; -+ } -+ -++#ifndef CONFIG_MTD_HW_RS_ECC /* HW&SW Hamming ECC */ -+ /** -+ * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function -+ * @mtd: mtd info structure -+@@ -841,6 +998,63 @@ -+ return 0; -+ } -+ -++#else /* CONFIG_MTD_HW_RS_ECC */ -++ -++/** -++ * nand_read_page_hwecc_rs - [REPLACABLE] hardware rs ecc based page read function -++ * @mtd: mtd info structure -++ * @chip: nand chip info structure -++ * @buf: buffer to store read data -++ * -++ * Not for syndrome calculating ecc controllers which need a special oob layout -++ */ -++static int nand_read_page_hwecc_rs(struct mtd_info *mtd, struct nand_chip *chip, -++ uint8_t *buf) -++{ -++ int i, eccsize = chip->ecc.size; -++ int eccbytes = chip->ecc.bytes; -++ int eccsteps = chip->ecc.steps; -++ uint8_t *p = buf; -++ uint8_t *ecc_calc = chip->buffers->ecccalc; -++ uint8_t *ecc_code = chip->buffers->ecccode; -++ uint32_t *eccpos = chip->ecc.layout->eccpos; -++ uint32_t page; -++ uint8_t flag = 0; -++ -++ page = (buf[3]<<24) + (buf[2]<<16) + (buf[1]<<8) + buf[0]; -++ -++ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); -++ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); -++ for (i = 0; i < chip->ecc.total; i++) { -++ ecc_code[i] = chip->oob_poi[eccpos[i]]; -++ if (ecc_code[i] != 0xff) flag = 1; -++ } -++ -++ eccsteps = chip->ecc.steps; -++ p = buf; -++ -++ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0x00, -1); -++ for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { -++ int stat; -++ if (flag) { -++ chip->ecc.hwctl(mtd, NAND_ECC_READ); -++ chip->read_buf(mtd, p, eccsize); -++ stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); -++ if (stat < 0) -++ mtd->ecc_stats.failed++; -++ else -++ mtd->ecc_stats.corrected += stat; -++ } -++ else { -++ chip->ecc.hwctl(mtd, NAND_ECC_READ); -++ chip->read_buf(mtd, p, eccsize); -++ } -++ } -++ return 0; -++} -++ -++#endif /* CONFIG_MTD_HW_RS_ECC */ -++ -+ /** -+ * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read -+ * @mtd: mtd info structure -+@@ -903,7 +1117,7 @@ -+ * @len: size of oob to transfer -+ */ -+ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, -+- struct mtd_oob_ops *ops, size_t len) -++ struct mtd_oob_ops *ops, size_mtd_t len) -+ { -+ switch(ops->mode) { -+ -+@@ -915,7 +1129,7 @@ -+ case MTD_OOB_AUTO: { -+ struct nand_oobfree *free = chip->ecc.layout->oobfree; -+ uint32_t boffs = 0, roffs = ops->ooboffs; -+- size_t bytes = 0; -++ size_mtd_t bytes = 0; -+ -+ for(; free->length && len; free++, len -= bytes) { -+ /* Read request not from offset 0 ? */ -+@@ -925,11 +1139,11 @@ -+ continue; -+ } -+ boffs = free->offset + roffs; -+- bytes = min_t(size_t, len, -++ bytes = min_t(size_mtd_t, len, -+ (free->length - roffs)); -+ roffs = 0; -+ } else { -+- bytes = min_t(size_t, len, free->length); -++ bytes = min_t(size_mtd_t, len, free->length); -+ boffs = free->offset; -+ } -+ memcpy(oob, chip->oob_poi + boffs, bytes); -+@@ -952,7 +1166,7 @@ -+ * -+ * Internal function. Called with chip held. -+ */ -+-static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, -++static int nand_do_read_ops(struct mtd_info *mtd, loff_mtd_t from, -+ struct mtd_oob_ops *ops) -+ { -+ int chipnr, page, realpage, col, bytes, aligned; -+@@ -986,10 +1200,18 @@ -+ if (realpage != chip->pagebuf || oob) { -+ bufpoi = aligned ? buf : chip->buffers->databuf; -+ -++ global_page = page; -++#if defined(CONFIG_MTD_HW_RS_ECC) || defined(CONFIG_MTD_NAND_DMA) -++ bufpoi[0] = (uint8_t)page; -++ bufpoi[1] = (uint8_t)(page >> 8); -++ bufpoi[2] = (uint8_t)(page >> 16); -++ bufpoi[3] = (uint8_t)(page >> 24); -++#else -+ if (likely(sndcmd)) { -+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); -+ sndcmd = 0; -+ } -++#endif -+ -+ /* Now read the page into the buffer */ -+ if (unlikely(ops->mode == MTD_OOB_RAW)) -+@@ -1065,7 +1287,7 @@ -+ sndcmd = 1; -+ } -+ -+- ops->retlen = ops->len - (size_t) readlen; -++ ops->retlen = ops->len - (size_mtd_t) readlen; -+ if (oob) -+ ops->oobretlen = ops->ooblen - oobreadlen; -+ -+@@ -1088,8 +1310,8 @@ -+ * -+ * Get hold of the chip and call nand_do_read -+ */ -+-static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, -+- size_t *retlen, uint8_t *buf) -++static int nand_read(struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, -++ size_mtd_t *retlen, uint8_t *buf) -+ { -+ struct nand_chip *chip = mtd->priv; -+ int ret; -+@@ -1262,7 +1484,7 @@ -+ * -+ * NAND read out-of-band data from the spare area -+ */ -+-static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, -++static int nand_do_read_oob(struct mtd_info *mtd, loff_mtd_t from, -+ struct mtd_oob_ops *ops) -+ { -+ int page, realpage, chipnr, sndcmd = 1; -+@@ -1355,7 +1577,7 @@ -+ * -+ * NAND read data and/or out-of-band data -+ */ -+-static int nand_read_oob(struct mtd_info *mtd, loff_t from, -++static int nand_read_oob(struct mtd_info *mtd, loff_mtd_t from, -+ struct mtd_oob_ops *ops) -+ { -+ struct nand_chip *chip = mtd->priv; -+@@ -1518,12 +1740,17 @@ -+ { -+ int status; -+ -+- chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); -+- -+- if (unlikely(raw)) -+- chip->ecc.write_page_raw(mtd, chip, buf); -+- else -++ global_page = page; -++ if (chip->planenum > 1) -+ chip->ecc.write_page(mtd, chip, buf); -++ else { -++ chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); -++ -++ if (unlikely(raw)) -++ chip->ecc.write_page_raw(mtd, chip, buf); -++ else -++ chip->ecc.write_page(mtd, chip, buf); -++ } -+ -+ /* -+ * Cached progamming disabled for now, Not sure if its worth the -+@@ -1532,9 +1759,17 @@ -+ cached = 0; -+ -+ if (!cached || !(chip->options & NAND_CACHEPRG)) { -+- -+- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); -++/* -++* __nand_cmd(CMD_PAGEPROG) and __nand_sync() have been done by DMA for jz4750 and -++* later chip, status should still be read by "status = chip->waitfunc(mtd, chip)" -++*/ -++#if defined(CONFIG_SOC_JZ4730) || defined(CONFIG_SOC_JZ4740) || \ -++ (!defined(CONFIG_SOC_JZ4730) && !defined(CONFIG_SOC_JZ4740) \ -++ && !defined(CONFIG_MTD_NAND_DMA)) -++ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); -++#endif -+ status = chip->waitfunc(mtd, chip); -++ -+ /* -+ * See if operation failed and additional status checks are -+ * available -+@@ -1569,7 +1804,7 @@ -+ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, -+ struct mtd_oob_ops *ops) -+ { -+- size_t len = ops->ooblen; -++ size_mtd_t len = ops->ooblen; -+ -+ switch(ops->mode) { -+ -+@@ -1581,7 +1816,7 @@ -+ case MTD_OOB_AUTO: { -+ struct nand_oobfree *free = chip->ecc.layout->oobfree; -+ uint32_t boffs = 0, woffs = ops->ooboffs; -+- size_t bytes = 0; -++ size_mtd_t bytes = 0; -+ -+ for(; free->length && len; free++, len -= bytes) { -+ /* Write request not from offset 0 ? */ -+@@ -1591,11 +1826,11 @@ -+ continue; -+ } -+ boffs = free->offset + woffs; -+- bytes = min_t(size_t, len, -++ bytes = min_t(size_mtd_t, len, -+ (free->length - woffs)); -+ woffs = 0; -+ } else { -+- bytes = min_t(size_t, len, free->length); -++ bytes = min_t(size_mtd_t, len, free->length); -+ boffs = free->offset; -+ } -+ memcpy(chip->oob_poi + boffs, oob, bytes); -+@@ -1619,7 +1854,7 @@ -+ * -+ * NAND write with ECC -+ */ -+-static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, -++static int nand_do_write_ops(struct mtd_info *mtd, loff_mtd_t to, -+ struct mtd_oob_ops *ops) -+ { -+ int chipnr, realpage, page, blockmask, column; -+@@ -1722,8 +1957,8 @@ -+ * -+ * NAND write with ECC -+ */ -+-static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, -+- size_t *retlen, const uint8_t *buf) -++static int nand_write(struct mtd_info *mtd, loff_mtd_t to, size_mtd_t len, -++ size_mtd_t *retlen, const uint8_t *buf) -+ { -+ struct nand_chip *chip = mtd->priv; -+ int ret; -+@@ -1757,7 +1992,7 @@ -+ * -+ * NAND write out-of-band -+ */ -+-static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, -++static int nand_do_write_oob(struct mtd_info *mtd, loff_mtd_t to, -+ struct mtd_oob_ops *ops) -+ { -+ int chipnr, page, status, len; -+@@ -1835,7 +2070,7 @@ -+ * @to: offset to write to -+ * @ops: oob operation description structure -+ */ -+-static int nand_write_oob(struct mtd_info *mtd, loff_t to, -++static int nand_write_oob(struct mtd_info *mtd, loff_mtd_t to, -+ struct mtd_oob_ops *ops) -+ { -+ struct nand_chip *chip = mtd->priv; -+@@ -1999,7 +2234,7 @@ -+ /* -+ * heck if we have a bad block, we do not erase bad blocks ! -+ */ -+- if (nand_block_checkbad(mtd, ((loff_t) page) << -++ if (nand_block_checkbad(mtd, ((loff_mtd_t) page) << -+ chip->page_shift, 0, allowbbt)) { -+ printk(KERN_WARNING "nand_erase: attempt to erase a " -+ "bad block at page 0x%08x\n", page); -+@@ -2121,7 +2356,7 @@ -+ * @mtd: MTD device structure -+ * @offs: offset relative to mtd start -+ */ -+-static int nand_block_isbad(struct mtd_info *mtd, loff_t offs) -++static int nand_block_isbad(struct mtd_info *mtd, loff_mtd_t offs) -+ { -+ /* Check for invalid offset */ -+ if (offs > mtd->size) -+@@ -2135,7 +2370,7 @@ -+ * @mtd: MTD device structure -+ * @ofs: offset relative to mtd start -+ */ -+-static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) -++static int nand_block_markbad(struct mtd_info *mtd, loff_mtd_t ofs) -+ { -+ struct nand_chip *chip = mtd->priv; -+ int ret; -+@@ -2274,7 +2509,21 @@ -+ extid >>= 2; -+ /* Get buswidth information */ -+ busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; -++ /* The 5th id byte */ -++#if defined(CONFIG_MTD_NAND_MULTI_PLANE) -++ extid = chip->read_byte(mtd); -++ chip->realplanenum = 1 << ((extid & 0x0c) >> 2); -++#else -++ chip->realplanenum = 1; -++#endif -+ -++ if (chip->realplanenum > 1) { /* use muti planes mode */ -++ chip->planenum = 2; -++ mtd->writesize *= 2; /* two pages as one page */ -++ mtd->oobsize *= 2; -++ mtd->erasesize *= 2; /* two blocks as one block */ -++ } else -++ chip->planenum = 1; -+ } else { -+ /* -+ * Old devices have chip data hardcoded in the device id table -+@@ -2312,7 +2561,7 @@ -+ -+ chip->bbt_erase_shift = chip->phys_erase_shift = -+ ffs(mtd->erasesize) - 1; -+- chip->chip_shift = ffs(chip->chipsize) - 1; -++ chip->chip_shift = ffs_ll(chip->chipsize) - 1; -+ -+ /* Set the bad block position */ -+ chip->badblockpos = mtd->writesize > 512 ? -+@@ -2344,8 +2593,8 @@ -+ chip->cmdfunc = nand_command_lp; -+ -+ printk(KERN_INFO "NAND device: Manufacturer ID:" -+- " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id, -+- nand_manuf_ids[maf_idx].name, type->name); -++ " 0x%02x, Chip ID: 0x%02x (%s %s) planenum:%d\n", *maf_id, dev_id, -++ nand_manuf_ids[maf_idx].name, type->name, chip->realplanenum); -+ -+ return type; -+ } -+@@ -2412,7 +2661,7 @@ -+ */ -+ int nand_scan_tail(struct mtd_info *mtd) -+ { -+- int i; -++ int i, res; -+ struct nand_chip *chip = mtd->priv; -+ -+ if (!(chip->options & NAND_OWN_BUFFERS)) -+@@ -2437,6 +2686,16 @@ -+ case 64: -+ chip->ecc.layout = &nand_oob_64; -+ break; -++ case 128: -++ if (chip->planenum > 1) -++ chip->ecc.layout = &nand_oob_64; -++ else -++ chip->ecc.layout = &nand_oob_128; -++ break; -++ case 256: -++ if (chip->planenum > 1) -++ chip->ecc.layout = &nand_oob_128; -++ break; -+ default: -+ printk(KERN_WARNING "No oob scheme defined for " -+ "oobsize %d\n", mtd->oobsize); -+@@ -2459,8 +2718,13 @@ -+ switch (chip->ecc.mode) { -+ case NAND_ECC_HW: -+ /* Use standard hwecc read page function ? */ -+- if (!chip->ecc.read_page) -++ if (!chip->ecc.read_page) { -++#ifndef CONFIG_MTD_HW_RS_ECC -+ chip->ecc.read_page = nand_read_page_hwecc; -++#else -++ chip->ecc.read_page = nand_read_page_hwecc_rs; -++#endif -++ } -+ if (!chip->ecc.write_page) -+ chip->ecc.write_page = nand_write_page_hwecc; -+ if (!chip->ecc.read_oob) -+@@ -2593,8 +2857,58 @@ -+ if (chip->options & NAND_SKIP_BBTSCAN) -+ return 0; -+ -+- /* Build bad block table */ -+- return chip->scan_bbt(mtd); -++ /* Create jz_mtd1 for one plane operation if the NAND support multiple -++ planes operation, because some partitions will only use one plane. */ -++ if ((chip->planenum == 2) && !all_use_planes) { -++ int i, len, numblocks; -++ struct nand_chip *this = (struct nand_chip *) (&jz_mtd1[1]); -++ -++ memcpy(jz_mtd1, mtd, sizeof(*mtd)); -++ jz_mtd1->priv = this; -++ memcpy(this, chip, sizeof(*chip)); -++ -++ this->planenum = 1; -++ jz_mtd1->writesize >>= 1; -++ jz_mtd1->oobsize >>= 1; -++ jz_mtd1->erasesize >>= 1; -++ this->page_shift = chip->page_shift - 1; -++ this->pagemask = (this->chipsize >> this->page_shift) - 1; -++ this->bbt_erase_shift = this->phys_erase_shift = -++ chip->phys_erase_shift - 1; -++ this->ecc.steps >>= 1; -++ this->ecc.total = this->ecc.steps * this->ecc.bytes; -++ this->subpagesize = jz_mtd1->writesize; -++ -++ this->erase_cmd = single_erase_cmd; -++#if defined(CONFIG_MTD_HW_RS_ECC) -++ this->ecc.read_page = nand_read_page_hwecc_rs; -++ this->ecc.write_page = nand_write_page_hwecc; -++#endif -++ this->ecc.read_oob = nand_read_oob_std; -++ this->ecc.write_oob = nand_write_oob_std; -++ this->write_buf = nand_write_buf; -++ this->read_buf = nand_read_buf; -++ -++ /* Firstly, build bad block table as one plane */ -++ res = this->scan_bbt(jz_mtd1); -++ -++ /* Secondly, build bad block table as 2 plane based on bbt of jz_mtd1 */ -++ numblocks = chip->chipsize >> (chip->bbt_erase_shift - 1); /* = (real numblocks * 2) */ -++ len = mtd->size >> (chip->bbt_erase_shift + 2); -++ chip->bbt = kzalloc(len, GFP_KERNEL); -++ -++#define isbad_2plane(block) (((this->bbt[(block) >> 3] >> ((block) & 0x06)) \ -++ | (this->bbt[((block)+2) >> 3] >> (((block)+2) & 0x06))) & 0x03) -++ -++ for (i = 0; i < numblocks; i += 2) { -++ if (isbad_2plane(2*i)) -++ chip->bbt[i >> 3] |= 0x03 << (i & 0x6); -++ } -++ } else { -++ res = chip->scan_bbt(mtd); -++ } -++ -++ return res; -+ } -+ -+ /* module_text_address() isn't exported, and it's mostly a pointless -+diff -urN linux-2.6.24.7.old/drivers/mtd/nand/nand_bbt.c linux-2.6.24.7/drivers/mtd/nand/nand_bbt.c -+--- linux-2.6.24.7.old/drivers/mtd/nand/nand_bbt.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/nand/nand_bbt.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -6,7 +6,7 @@ -+ * -+ * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) -+ * -+- * $Id: nand_bbt.c,v 1.36 2005/11/07 11:14:30 gleixner Exp $ -++ * $Id: nand_bbt.c,v 1.1.1.1 2008-03-28 04:29:21 jlwei Exp $ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+@@ -147,15 +147,15 @@ -+ { -+ int res, i, j, act = 0; -+ struct nand_chip *this = mtd->priv; -+- size_t retlen, len, totlen; -+- loff_t from; -++ size_mtd_t retlen, len, totlen; -++ loff_mtd_t from; -+ uint8_t msk = (uint8_t) ((1 << bits) - 1); -+ -+ totlen = (num * bits) >> 3; -+- from = ((loff_t) page) << this->page_shift; -++ from = ((loff_mtd_t) page) << this->page_shift; -+ -+ while (totlen) { -+- len = min(totlen, (size_t) (1 << this->bbt_erase_shift)); -++ len = min(totlen, (size_mtd_t) (1 << this->bbt_erase_shift)); -+ res = mtd->read(mtd, from, len, &retlen, buf); -+ if (res < 0) { -+ if (retlen != len) { -+@@ -235,8 +235,8 @@ -+ /* -+ * Scan read raw data from flash -+ */ -+-static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs, -+- size_t len) -++static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_mtd_t offs, -++ size_mtd_t len) -+ { -+ struct mtd_oob_ops ops; -+ -+@@ -253,7 +253,7 @@ -+ /* -+ * Scan write data with oob to flash -+ */ -+-static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len, -++static int scan_write_bbt(struct mtd_info *mtd, loff_mtd_t offs, size_mtd_t len, -+ uint8_t *buf, uint8_t *oob) -+ { -+ struct mtd_oob_ops ops; -+@@ -308,7 +308,7 @@ -+ * Scan a given block full -+ */ -+ static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd, -+- loff_t offs, uint8_t *buf, size_t readlen, -++ loff_mtd_t offs, uint8_t *buf, size_mtd_t readlen, -+ int scanlen, int len) -+ { -+ int ret, j; -+@@ -328,7 +328,7 @@ -+ * Scan a given block partially -+ */ -+ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, -+- loff_t offs, uint8_t *buf, int len) -++ loff_mtd_t offs, uint8_t *buf, int len) -+ { -+ struct mtd_oob_ops ops; -+ int j, ret; -+@@ -374,8 +374,8 @@ -+ struct nand_chip *this = mtd->priv; -+ int i, numblocks, len, scanlen; -+ int startblock; -+- loff_t from; -+- size_t readlen; -++ loff_mtd_t from; -++ size_mtd_t readlen; -+ -+ printk(KERN_INFO "Scanning device for bad blocks\n"); -+ -+@@ -403,7 +403,7 @@ -+ * below as it makes shifting and masking less painful */ -+ numblocks = mtd->size >> (this->bbt_erase_shift - 1); -+ startblock = 0; -+- from = 0; -++ from = (CONFIG_MTD_BADBLOCK_FLAG_PAGE << this->page_shift); //from = 0; -+ } else { -+ if (chip >= this->numchips) { -+ printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n", -+@@ -413,7 +413,7 @@ -+ numblocks = this->chipsize >> (this->bbt_erase_shift - 1); -+ startblock = chip * numblocks; -+ numblocks += startblock; -+- from = startblock << (this->bbt_erase_shift - 1); -++ from = (startblock << (this->bbt_erase_shift - 1)) + (CONFIG_MTD_BADBLOCK_FLAG_PAGE << this->page_shift); //from = startblock << (this->bbt_erase_shift - 1); -+ } -+ -+ for (i = startblock; i < numblocks;) { -+@@ -430,8 +430,8 @@ -+ -+ if (ret) { -+ this->bbt[i >> 3] |= 0x03 << (i & 0x6); -+- printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n", -+- i >> 1, (unsigned int)from); -++ printk(KERN_WARNING "Bad eraseblock %d at 0x%09llx\n", -++ i >> 1, (unsigned long long)from); -+ mtd->ecc_stats.badblocks++; -+ } -+ -+@@ -497,7 +497,7 @@ -+ for (block = 0; block < td->maxblocks; block++) { -+ -+ int actblock = startblock + dir * block; -+- loff_t offs = actblock << this->bbt_erase_shift; -++ loff_mtd_t offs = actblock << this->bbt_erase_shift; -+ -+ /* Read first page */ -+ scan_read_raw(mtd, buf, offs, mtd->writesize); -+@@ -567,8 +567,8 @@ -+ int nrchips, bbtoffs, pageoffs, ooboffs; -+ uint8_t msk[4]; -+ uint8_t rcode = td->reserved_block_code; -+- size_t retlen, len = 0; -+- loff_t to; -++ size_mtd_t retlen, len = 0; -++ loff_mtd_t to; -+ struct mtd_oob_ops ops; -+ -+ ops.ooblen = mtd->oobsize; -+@@ -655,12 +655,12 @@ -+ -+ bbtoffs = chip * (numblocks >> 2); -+ -+- to = ((loff_t) page) << this->page_shift; -++ to = ((loff_mtd_t) page) << this->page_shift; -+ -+ /* Must we save the block contents ? */ -+ if (td->options & NAND_BBT_SAVECONTENT) { -+ /* Make it block aligned */ -+- to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1)); -++ to &= ~((loff_mtd_t) ((1 << this->bbt_erase_shift) - 1)); -+ len = 1 << this->bbt_erase_shift; -+ res = mtd->read(mtd, to, len, &retlen, buf); -+ if (res < 0) { -+@@ -685,12 +685,12 @@ -+ pageoffs = page - (int)(to >> this->page_shift); -+ offs = pageoffs << this->page_shift; -+ /* Preset the bbt area with 0xff */ -+- memset(&buf[offs], 0xff, (size_t) (numblocks >> sft)); -++ memset(&buf[offs], 0xff, (size_mtd_t) (numblocks >> sft)); -+ ooboffs = len + (pageoffs * mtd->oobsize); -+ -+ } else { -+ /* Calc length */ -+- len = (size_t) (numblocks >> sft); -++ len = (size_mtd_t) (numblocks >> sft); -+ /* Make it page aligned ! */ -+ len = (len + (mtd->writesize - 1)) & -+ ~(mtd->writesize - 1); -+@@ -1017,7 +1017,7 @@ -+ * -+ * The function updates the bad block table(s) -+ */ -+-int nand_update_bbt(struct mtd_info *mtd, loff_t offs) -++int nand_update_bbt(struct mtd_info *mtd, loff_mtd_t offs) -+ { -+ struct nand_chip *this = mtd->priv; -+ int len, res = 0, writeops = 0; -+@@ -1193,7 +1193,7 @@ -+ * @allowbbt: allow access to bad block table region -+ * -+ */ -+-int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) -++int nand_isbad_bbt(struct mtd_info *mtd, loff_mtd_t offs, int allowbbt) -+ { -+ struct nand_chip *this = mtd->priv; -+ int block; -+diff -urN linux-2.6.24.7.old/drivers/mtd/nand/nand_ids.c linux-2.6.24.7/drivers/mtd/nand/nand_ids.c -+--- linux-2.6.24.7.old/drivers/mtd/nand/nand_ids.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/nand/nand_ids.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -111,6 +111,9 @@ -+ {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, LP_OPTIONS16}, -+ {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16}, -+ -++ /* 32 Gigabit */ -++ {"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 4096, 0, LP_OPTIONS}, -++ -+ /* -+ * Renesas AND 1 Gigabit. Those chips do not support extended id and -+ * have a strange page/block layout ! The chosen minimum erasesize is -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/Kconfig linux-2.6.24.7/drivers/mtd/ubi/Kconfig -+--- linux-2.6.24.7.old/drivers/mtd/ubi/Kconfig 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -55,4 +55,18 @@ -+ this if no legacy software will be used. -+ -+ source "drivers/mtd/ubi/Kconfig.debug" -++ -++config MTD_UBI_BLKDEVS -++ tristate "Common interface to block layer for UBI 'translation layers'" -++ depends on BLOCK -++ default n -++ -++config MTD_UBI_BLOCK -++ tristate "Emulate block devices" -++ default n -++ depends on MTD_UBI_BLKDEVS -++ help -++ This option enables Block layer emulation on top of UBI volumes: for -++ each UBI volumes an block device is created. This is handy to make -++ traditional filesystem (like ext2, VFAT) work on top of UBI. -+ endmenu -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/Makefile linux-2.6.24.7/drivers/mtd/ubi/Makefile -+--- linux-2.6.24.7.old/drivers/mtd/ubi/Makefile 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -5,3 +5,6 @@ -+ -+ ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o -+ ubi-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o -++ -++obj-$(CONFIG_MTD_UBI_BLKDEVS) += bdev.o -++obj-$(CONFIG_MTD_UBI_BLOCK) += ubiblk.o -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/bdev.c linux-2.6.24.7/drivers/mtd/ubi/bdev.c -+--- linux-2.6.24.7.old/drivers/mtd/ubi/bdev.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/ubi/bdev.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,432 @@ -++/* -++ * -++ * (C) 2003 David Woodhouse -++ * -++ * Interface to Linux 2.5 block layer for UBI 'translation layers'. -++ * -++ * 2008 Yurong Tan : -++ * borrow from mtd_blkdevs.c for building block device layer on top of UBI -++ * -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "ubi.h" -++#include "ubiblk.h" -++ -++static LIST_HEAD(blktrans_majors); -++extern struct mutex vol_table_mutex; -++extern struct ubi_volume *vol_table[]; -++ -++extern void register_vol_user (struct vol_notifier *new); -++extern int unregister_vol_user (struct vol_notifier *old); -++extern int ubi_major2num(int major); -++ -++struct ubi_blkcore_priv { -++ struct task_struct *thread; -++ struct request_queue *rq; -++ spinlock_t queue_lock; -++}; -++ -++static int do_blktrans_request(struct ubi_blktrans_ops *tr, -++ struct ubi_blktrans_dev *dev, -++ struct request *req) -++{ -++ unsigned long block, nsect; -++ char *buf; -++ -++ block = req->sector << 9 >> tr->blkshift; -++ nsect = req->current_nr_sectors << 9 >> tr->blkshift; -++ buf = req->buffer; -++ -++ if (!blk_fs_request(req)) -++ return 0; -++ -++ if (req->sector + req->current_nr_sectors > get_capacity(req->rq_disk)) -++ return 0; -++ -++ switch(rq_data_dir(req)) { -++ case READ: -++ for (; nsect > 0; nsect--, block++, buf += tr->blksize) -++ if (tr->readsect(dev, block, buf)) -++ return 0; -++ return 1; -++ -++ case WRITE: -++ if (!tr->writesect) -++ return 0; -++ -++ for (; nsect > 0; nsect--, block++, buf += tr->blksize) -++ if (tr->writesect(dev, block, buf)) -++ return 0; -++ return 1; -++ -++ default: -++ printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req)); -++ return 0; -++ } -++} -++ -++static int ubi_blktrans_thread(void *arg) -++{ -++ struct ubi_blktrans_ops *tr = arg; -++ struct request_queue *rq = tr->blkcore_priv->rq; -++ -++ /* we might get involved when memory gets low, so use PF_MEMALLOC */ -++ current->flags |= PF_MEMALLOC; -++ -++ spin_lock_irq(rq->queue_lock); -++ while (!kthread_should_stop()) { -++ struct request *req; -++ struct ubi_blktrans_dev *dev; -++ int res = 0; -++ -++ req = elv_next_request(rq); -++ -++ if (!req) { -++ set_current_state(TASK_INTERRUPTIBLE); -++ spin_unlock_irq(rq->queue_lock); -++ schedule(); -++ spin_lock_irq(rq->queue_lock); -++ continue; -++ } -++ dev = req->rq_disk->private_data; -++ tr = dev->tr; -++ -++ spin_unlock_irq(rq->queue_lock); -++ mutex_lock(&dev->lock); -++ res = do_blktrans_request(tr, dev, req); -++ mutex_unlock(&dev->lock); -++ spin_lock_irq(rq->queue_lock); -++ -++ end_request(req, res); -++ } -++ spin_unlock_irq(rq->queue_lock); -++ -++ return 0; -++} -++ -++static void ubi_blktrans_request(struct request_queue *rq) -++{ -++ struct ubi_blktrans_ops *tr = rq->queuedata; -++ wake_up_process(tr->blkcore_priv->thread); -++} -++ -++static int blktrans_open(struct inode *i, struct file *f) -++{ -++ struct ubi_blktrans_dev *dev; -++ struct ubi_blktrans_ops *tr; -++ int ret =0; -++ -++ dev = i->i_bdev->bd_disk->private_data; -++ tr = dev->tr; -++ -++ if (!try_module_get(tr->owner)) -++ goto out_tr; -++ -++ if(!tr->open) -++ return -1; -++ else -++ ret = tr->open(i,f); -++ -++ return ret; -++out_tr: -++ module_put(tr->owner); -++ return -1; -++} -++ -++static int blktrans_release(struct inode *i, struct file *f) -++{ -++ struct ubi_blktrans_dev *dev; -++ struct ubi_blktrans_ops *tr; -++ struct ubi_volume_desc *desc; -++ int ret = 0; -++ -++ dev = i->i_bdev->bd_disk->private_data; -++ tr = dev->tr; -++ desc = dev->uv; -++ -++ if (tr->release) -++ ret = tr->release(dev); -++ -++ module_put(tr->owner); -++ return ret; -++} -++ -++static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo) -++{ -++ struct ubi_blktrans_dev *dev = bdev->bd_disk->private_data; -++ -++ if (dev->tr->getgeo) -++ return dev->tr->getgeo(dev, geo); -++ return -ENOTTY; -++} -++ -++static int blktrans_ioctl(struct inode *inode, struct file *file, -++ unsigned int cmd, unsigned long arg) -++{ -++ struct ubi_blktrans_dev *dev = inode->i_bdev->bd_disk->private_data; -++ struct ubi_blktrans_ops *tr = dev->tr; -++ -++ switch (cmd) { -++ case BLKFLSBUF: -++ if (tr->flush) -++ return tr->flush(dev); -++ /* The core code did the work, we had nothing to do. */ -++ return 0; -++ default: -++ return -ENOTTY; -++ } -++} -++ -++struct block_device_operations ubi_blktrans_ops = { -++ .owner = THIS_MODULE, -++ .open = blktrans_open, -++ .release = blktrans_release, -++ .ioctl = blktrans_ioctl, -++ .getgeo = blktrans_getgeo, -++}; -++ -++int add_ubi_blktrans_dev(struct ubi_blktrans_dev *new) -++{ -++ struct ubi_blktrans_ops *tr = new->tr; -++ struct list_head *this; -++ int last_devnum = -1; -++ struct gendisk *gd; -++ -++ if (mutex_trylock(&vol_table_mutex)) { -++ mutex_unlock(&vol_table_mutex); -++ BUG(); -++ } -++ -++ list_for_each(this, &tr->devs) { -++ struct ubi_blktrans_dev *d = list_entry(this, struct ubi_blktrans_dev, list); -++ if (new->devnum == -1) { -++ /* Use first free number */ -++ if (d->devnum != last_devnum+1) { -++ /* Found a free devnum. Plug it in here */ -++ new->devnum = last_devnum+1; -++ list_add_tail(&new->list, &d->list); -++ goto added; -++ } -++ } else if (d->devnum == new->devnum) { -++ /* Required number taken */ -++ return -EBUSY; -++ } else if (d->devnum > new->devnum) { -++ /* Required number was free */ -++ list_add_tail(&new->list, &d->list); -++ goto added; -++ } -++ last_devnum = d->devnum; -++ } -++ if (new->devnum == -1) -++ new->devnum = last_devnum+1; -++ -++ if ((new->devnum << tr->part_bits) > 256) { -++ return -EBUSY; -++ } -++ -++ mutex_init(&new->lock); -++ list_add_tail(&new->list, &tr->devs); -++ added: -++ if (!tr->writesect) -++ new->readonly = 1; -++ -++ gd = alloc_disk(1 << tr->part_bits); -++ if (!gd) { -++ list_del(&new->list); -++ return -ENOMEM; -++ } -++ gd->major = tr->major; -++ gd->first_minor = (new->devnum) << tr->part_bits; -++ gd->fops = &ubi_blktrans_ops; -++ -++ if (tr->part_bits) -++ if (new->devnum < 26) -++ snprintf(gd->disk_name, sizeof(gd->disk_name), -++ "%s%c", tr->name, 'a' + new->devnum); -++ else -++ snprintf(gd->disk_name, sizeof(gd->disk_name), -++ "%s%c%c", tr->name, -++ 'a' - 1 + new->devnum / 26, -++ 'a' + new->devnum % 26); -++ else -++ snprintf(gd->disk_name, sizeof(gd->disk_name), -++ "%s%d", tr->name, new->devnum); -++ -++ /* 2.5 has capacity in units of 512 bytes while still -++ having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */ -++ set_capacity(gd, (new->size * tr->blksize) >> 9); -++ -++ gd->private_data = new; -++ new->blkcore_priv = gd; -++ gd->queue = tr->blkcore_priv->rq; -++ -++ if (new->readonly) -++ set_disk_ro(gd, 1); -++ -++ add_disk(gd); -++ -++ return 0; -++} -++ -++int del_ubi_blktrans_dev(struct ubi_blktrans_dev *old) -++{ -++ if (mutex_trylock(&vol_table_mutex)) { -++ mutex_unlock(&vol_table_mutex); -++ BUG(); -++ } -++ -++ list_del(&old->list); -++ -++ del_gendisk(old->blkcore_priv); -++ put_disk(old->blkcore_priv); -++ -++ return 0; -++} -++ -++static void blktrans_notify_remove(struct ubi_volume *vol) -++{ -++ struct list_head *this, *this2, *next; -++ -++ list_for_each(this, &blktrans_majors) { -++ struct ubi_blktrans_ops *tr = list_entry(this, struct ubi_blktrans_ops, list); -++ -++ list_for_each_safe(this2, next, &tr->devs) { -++ struct ubi_blktrans_dev *dev = list_entry(this2, struct ubi_blktrans_dev, list); -++ -++ if (dev->uv->vol == vol) -++ tr->remove_vol(dev); -++ } -++ } -++} -++ -++static void blktrans_notify_add(struct ubi_volume *vol) -++{ -++ struct list_head *this; -++ -++ list_for_each(this, &blktrans_majors) { -++ struct ubi_blktrans_ops *tr = list_entry(this, struct ubi_blktrans_ops, list); -++ -++ tr->add_vol(tr,vol); -++ } -++ -++} -++ -++static struct vol_notifier blktrans_notifier = { -++ .add = blktrans_notify_add, -++ .remove = blktrans_notify_remove, -++}; -++ -++ -++int register_ubi_blktrans(struct ubi_blktrans_ops *tr) -++{ -++ int i; -++ -++ /* Register the notifier if/when the first device type is -++ registered, to prevent the link/init ordering from fucking -++ us over. */ -++ if (!blktrans_notifier.list.next) -++ register_vol_user(&blktrans_notifier); -++ -++ tr->blkcore_priv = kzalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL); -++ if (!tr->blkcore_priv) -++ return -ENOMEM; -++ -++ mutex_lock(&vol_table_mutex); -++ tr->major = register_blkdev(0, tr->name); -++ spin_lock_init(&tr->blkcore_priv->queue_lock); -++ -++ tr->blkcore_priv->rq = blk_init_queue(ubi_blktrans_request, &tr->blkcore_priv->queue_lock); -++ if (!tr->blkcore_priv->rq) { -++ unregister_blkdev(tr->major, tr->name); -++ kfree(tr->blkcore_priv); -++ mutex_unlock(&vol_table_mutex); -++ return -ENOMEM; -++ } -++ -++ tr->blkcore_priv->rq->queuedata = tr; -++ blk_queue_hardsect_size(tr->blkcore_priv->rq, tr->blksize); -++ tr->blkshift = ffs(tr->blksize) - 1; -++ -++ tr->blkcore_priv->thread = kthread_run(ubi_blktrans_thread, tr, -++ "%sd", tr->name); -++ if (IS_ERR(tr->blkcore_priv->thread)) { -++ blk_cleanup_queue(tr->blkcore_priv->rq); -++ unregister_blkdev(tr->major, tr->name); -++ kfree(tr->blkcore_priv); -++ mutex_unlock(&vol_table_mutex); -++ return PTR_ERR(tr->blkcore_priv->thread); -++ } -++ -++ INIT_LIST_HEAD(&tr->devs); -++ list_add(&tr->list, &blktrans_majors); -++ -++ for (i=0; iadd_vol(tr, vol_table[i]); -++ } -++ -++ mutex_unlock(&vol_table_mutex); -++ return 0; -++} -++ -++int deregister_ubi_blktrans(struct ubi_blktrans_ops *tr) -++{ -++ struct list_head *this, *next; -++ -++ mutex_lock(&vol_table_mutex); -++ -++ /* Clean up the kernel thread */ -++ kthread_stop(tr->blkcore_priv->thread); -++ -++ /* Remove it from the list of active majors */ -++ list_del(&tr->list); -++ -++ list_for_each_safe(this, next, &tr->devs) { -++ struct ubi_blktrans_dev *dev = list_entry(this, struct ubi_blktrans_dev, list); -++ tr->remove_vol(dev); -++ } -++ -++ blk_cleanup_queue(tr->blkcore_priv->rq); -++ unregister_blkdev(tr->major, tr->name); -++ -++ mutex_unlock(&vol_table_mutex); -++ -++ kfree(tr->blkcore_priv); -++ -++ BUG_ON(!list_empty(&tr->devs)); -++ return 0; -++} -++ -++static void __exit ubi_blktrans_exit(void) -++{ -++ /* No race here -- if someone's currently in register_ubi_blktrans -++ we're screwed anyway. */ -++ if (blktrans_notifier.list.next) -++ unregister_vol_user(&blktrans_notifier); -++} -++ -++ -++module_exit(ubi_blktrans_exit); -++ -++EXPORT_SYMBOL_GPL(register_ubi_blktrans); -++EXPORT_SYMBOL_GPL(deregister_ubi_blktrans); -++EXPORT_SYMBOL_GPL(add_ubi_blktrans_dev); -++EXPORT_SYMBOL_GPL(del_ubi_blktrans_dev); -++ -++MODULE_AUTHOR("David Woodhouse , Yurong Tan "); -++MODULE_LICENSE("GPL"); -++MODULE_DESCRIPTION("Common interface to block layer for UBI 'translation layers'"); -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/build.c linux-2.6.24.7/drivers/mtd/ubi/build.c -+--- linux-2.6.24.7.old/drivers/mtd/ubi/build.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/build.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -18,14 +18,20 @@ -+ * -+ * Author: Artem Bityutskiy (Битюцкий Ðртём), -+ * Frank Haverkamp -++ * Yurong tan(Nancy) -+ */ -+ -+ /* -+- * This file includes UBI initialization and building of UBI devices. At the -+- * moment UBI devices may only be added while UBI is initialized, but dynamic -+- * device add/remove functionality is planned. Also, at the moment we only -+- * attach UBI devices by scanning, which will become a bottleneck when flashes -+- * reach certain large size. Then one may improve UBI and add other methods. -++ * This file includes UBI initialization and building of UBI devices. -++ * -++ * When UBI is initialized, it attaches all the MTD devices specified as the -++ * module load parameters or the kernel boot parameters. If MTD devices were -++ * specified, UBI does not attach any MTD device, but it is possible to do -++ * later using the "UBI control device". -++ * -++ * At the moment we only attach UBI devices by scanning, which will become a -++ * bottleneck when flashes reach certain large size. Then one may improve UBI -++ * and add other methods, although it does not seem to be easy to do. -+ */ -+ -+ #include -+@@ -33,23 +39,130 @@ -+ #include -+ #include -+ #include -++#include -+ #include -++#include -+ #include "ubi.h" -+ -+ /* Maximum length of the 'mtd=' parameter */ -+ #define MTD_PARAM_LEN_MAX 64 -+ -++/* add by Nancy begin */ -++DEFINE_MUTEX(vol_table_mutex); -++struct ubi_volume *vol_table[UBI_MAX_VOLUMES]; -++ -++EXPORT_SYMBOL_GPL(vol_table_mutex); -++EXPORT_SYMBOL_GPL(vol_table); -++ -++static LIST_HEAD(vol_notifiers); -++ -++int add_vol_device(struct ubi_volume *vol) -++{ -++ mutex_lock(&vol_table_mutex); -++ if (!vol_table[vol->vol_id]) { -++ -++ struct list_head *this; -++ vol_table[vol->vol_id] = vol; -++ /* No need to get a refcount on the module containing -++ the notifier, since we hold the vol_table_mutex */ -++ list_for_each(this, &vol_notifiers) { -++ struct vol_notifier *not = list_entry(this, struct vol_notifier, list); -++ not->add(vol); -++ } -++ mutex_unlock(&vol_table_mutex); -++ /* We _know_ we aren't being removed, because -++ our caller is still holding us here. So none -++ of this try_ nonsense, and no bitching about it -++ either. :) */ -++ return 0; -++ } -++ mutex_unlock(&vol_table_mutex); -++ return 1; -++} -++ -++int del_vol_device (struct ubi_volume *vol) -++{ -++ int ret; -++ struct list_head *this; -++ -++ mutex_lock(&vol_table_mutex); -++ if (vol_table[vol->vol_id] != vol) { -++ ret = -ENODEV; -++ } else if (vol->readers ||vol->writers || vol->exclusive) { -++ printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count 0\n", -++ vol->vol_id, vol->name); -++ ret = -EBUSY; -++ } else { -++ /* No need to get a refcount on the module containing -++ the notifier, since we hold the vol_table_mutex */ -++ list_for_each(this, &vol_notifiers) { -++ struct vol_notifier *not = list_entry(this, struct vol_notifier, list); -++ not->remove(vol); -++ } -++ -++ vol_table[vol->vol_id] = NULL; -++ module_put(THIS_MODULE); -++ ret = 0; -++ } -++ mutex_unlock(&vol_table_mutex); -++ return ret; -++} -++ -++void register_vol_user(struct vol_notifier *new) -++{ -++ int i; -++ -++ mutex_lock(&vol_table_mutex); -++ list_add(&new->list, &vol_notifiers); -++ __module_get(THIS_MODULE); -++ -++ for (i=0; i< UBI_MAX_VOLUMES; i++) -++ if (vol_table[i]) -++ new->add(vol_table[i]); -++ -++ mutex_unlock(&vol_table_mutex); -++} -++ -++int unregister_vol_user(struct vol_notifier *old) -++{ -++ int i; -++ -++ mutex_lock(&vol_table_mutex); -++ module_put(THIS_MODULE); -++ -++ for (i=0; i< UBI_MAX_VOLUMES; i++) -++ if (vol_table[i]) -++ old->remove(vol_table[i]); -++ -++ list_del(&old->list); -++ mutex_unlock(&vol_table_mutex); -++ return 0; -++} -++ -++static int bdev_init(struct ubi_device *ubi){ -++ int i; -++ for(i=0; ivtbl_slots; i++) -++ if(ubi->volumes[i]) -++ add_vol_device(ubi->volumes[i]); -++ return 0; -++} -++ -++EXPORT_SYMBOL_GPL(add_vol_device); -++EXPORT_SYMBOL_GPL(del_vol_device); -++EXPORT_SYMBOL_GPL(register_vol_user); -++EXPORT_SYMBOL_GPL(unregister_vol_user); -++/* add by Nancy end*/ -++ -++ -+ /** -+ * struct mtd_dev_param - MTD device parameter description data structure. -+ * @name: MTD device name or number string -+ * @vid_hdr_offs: VID header offset -+- * @data_offs: data offset -+ */ -+ struct mtd_dev_param -+ { -+ char name[MTD_PARAM_LEN_MAX]; -+ int vid_hdr_offs; -+- int data_offs; -+ }; -+ -+ /* Numbers of elements set in the @mtd_dev_param array */ -+@@ -58,14 +171,28 @@ -+ /* MTD devices specification parameters */ -+ static struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES]; -+ -+-/* Number of UBI devices in system */ -+-int ubi_devices_cnt; -++/* Root UBI "class" object (corresponds to '//class/ubi/') */ -++struct class *ubi_class; -++ -++/* Slab cache for wear-leveling entries */ -++struct kmem_cache *ubi_wl_entry_slab; -++ -++/* UBI control character device */ -++static struct miscdevice ubi_ctrl_cdev = { -++ .minor = MISC_DYNAMIC_MINOR, -++ .name = "ubi_ctrl", -++ .fops = &ubi_ctrl_cdev_operations, -++}; -+ -+ /* All UBI devices in system */ -+-struct ubi_device *ubi_devices[UBI_MAX_DEVICES]; -++static struct ubi_device *ubi_devices[UBI_MAX_DEVICES]; -+ -+-/* Root UBI "class" object (corresponds to '//class/ubi/') */ -+-struct class *ubi_class; -++/* Serializes UBI devices creations and removals */ -++DEFINE_MUTEX(ubi_devices_mutex); -++ -++/* Protects @ubi_devices and @ubi->ref_count */ -++static DEFINE_SPINLOCK(ubi_devices_lock); -++EXPORT_SYMBOL_GPL(ubi_devices_lock); -+ -+ /* "Show" method for files in '//class/ubi/' */ -+ static ssize_t ubi_version_show(struct class *class, char *buf) -+@@ -101,38 +228,152 @@ -+ __ATTR(min_io_size, S_IRUGO, dev_attribute_show, NULL); -+ static struct device_attribute dev_bgt_enabled = -+ __ATTR(bgt_enabled, S_IRUGO, dev_attribute_show, NULL); -++static struct device_attribute dev_mtd_num = -++ __ATTR(mtd_num, S_IRUGO, dev_attribute_show, NULL); -++ -++/** -++ * ubi_get_device - get UBI device. -++ * @ubi_num: UBI device number -++ * -++ * This function returns UBI device description object for UBI device number -++ * @ubi_num, or %NULL if the device does not exist. This function increases the -++ * device reference count to prevent removal of the device. In other words, the -++ * device cannot be removed if its reference count is not zero. -++ */ -++struct ubi_device *ubi_get_device(int ubi_num) -++{ -++ struct ubi_device *ubi; -++ -++ spin_lock(&ubi_devices_lock); -++ ubi = ubi_devices[ubi_num]; -++ if (ubi) { -++ ubi_assert(ubi->ref_count >= 0); -++ ubi->ref_count += 1; -++ get_device(&ubi->dev); -++ } -++ spin_unlock(&ubi_devices_lock); -++ -++ return ubi; -++} -++ -++/** -++ * ubi_put_device - drop an UBI device reference. -++ * @ubi: UBI device description object -++ */ -++void ubi_put_device(struct ubi_device *ubi) -++{ -++ spin_lock(&ubi_devices_lock); -++ ubi->ref_count -= 1; -++ put_device(&ubi->dev); -++ spin_unlock(&ubi_devices_lock); -++} -++ -++/** -++ * ubi_get_by_major - get UBI device description object by character device -++ * major number. -++ * @major: major number -++ * -++ * This function is similar to 'ubi_get_device()', but it searches the device -++ * by its major number. -++ */ -++struct ubi_device *ubi_get_by_major(int major) -++{ -++ int i; -++ struct ubi_device *ubi; -++ -++ spin_lock(&ubi_devices_lock); -++ for (i = 0; i < UBI_MAX_DEVICES; i++) { -++ ubi = ubi_devices[i]; -++ if (ubi && MAJOR(ubi->cdev.dev) == major) { -++ ubi_assert(ubi->ref_count >= 0); -++ ubi->ref_count += 1; -++ get_device(&ubi->dev); -++ spin_unlock(&ubi_devices_lock); -++ return ubi; -++ } -++ } -++ spin_unlock(&ubi_devices_lock); -++ -++ return NULL; -++} -++ -++/** -++ * ubi_major2num - get UBI device number by character device major number. -++ * @major: major number -++ * -++ * This function searches UBI device number object by its major number. If UBI -++ * device was not found, this function returns -ENODEV, otherwise the UBI device -++ * number is returned. -++ */ -++int ubi_major2num(int major) -++{ -++ int i, ubi_num = -ENODEV; -++ -++ spin_lock(&ubi_devices_lock); -++ for (i = 0; i < UBI_MAX_DEVICES; i++) { -++ struct ubi_device *ubi = ubi_devices[i]; -++ -++ if ( (ubi && MAJOR(ubi->cdev.dev) == major) || -++ (ubi && ubi->bdev_major == major)) { -++ ubi_num = ubi->ubi_num; -++ break; -++ } -++ } -++ spin_unlock(&ubi_devices_lock); -++ -++ return ubi_num; -++} -++EXPORT_SYMBOL_GPL(ubi_major2num); -+ -+ /* "Show" method for files in '//class/ubi/ubiX/' */ -+ static ssize_t dev_attribute_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+ { -+- const struct ubi_device *ubi; -++ ssize_t ret; -++ struct ubi_device *ubi; -+ -++ /* -++ * The below code looks weird, but it actually makes sense. We get the -++ * UBI device reference from the contained 'struct ubi_device'. But it -++ * is unclear if the device was removed or not yet. Indeed, if the -++ * device was removed before we increased its reference count, -++ * 'ubi_get_device()' will return -ENODEV and we fail. -++ * -++ * Remember, 'struct ubi_device' is freed in the release function, so -++ * we still can use 'ubi->ubi_num'. -++ */ -+ ubi = container_of(dev, struct ubi_device, dev); -++ ubi = ubi_get_device(ubi->ubi_num); -++ if (!ubi) -++ return -ENODEV; -++ -+ if (attr == &dev_eraseblock_size) -+- return sprintf(buf, "%d\n", ubi->leb_size); -++ ret = sprintf(buf, "%d\n", ubi->leb_size); -+ else if (attr == &dev_avail_eraseblocks) -+- return sprintf(buf, "%d\n", ubi->avail_pebs); -++ ret = sprintf(buf, "%d\n", ubi->avail_pebs); -+ else if (attr == &dev_total_eraseblocks) -+- return sprintf(buf, "%d\n", ubi->good_peb_count); -++ ret = sprintf(buf, "%d\n", ubi->good_peb_count); -+ else if (attr == &dev_volumes_count) -+- return sprintf(buf, "%d\n", ubi->vol_count); -++ ret = sprintf(buf, "%d\n", ubi->vol_count - UBI_INT_VOL_COUNT); -+ else if (attr == &dev_max_ec) -+- return sprintf(buf, "%d\n", ubi->max_ec); -++ ret = sprintf(buf, "%d\n", ubi->max_ec); -+ else if (attr == &dev_reserved_for_bad) -+- return sprintf(buf, "%d\n", ubi->beb_rsvd_pebs); -++ ret = sprintf(buf, "%d\n", ubi->beb_rsvd_pebs); -+ else if (attr == &dev_bad_peb_count) -+- return sprintf(buf, "%d\n", ubi->bad_peb_count); -++ ret = sprintf(buf, "%d\n", ubi->bad_peb_count); -+ else if (attr == &dev_max_vol_count) -+- return sprintf(buf, "%d\n", ubi->vtbl_slots); -++ ret = sprintf(buf, "%d\n", ubi->vtbl_slots); -+ else if (attr == &dev_min_io_size) -+- return sprintf(buf, "%d\n", ubi->min_io_size); -++ ret = sprintf(buf, "%d\n", ubi->min_io_size); -+ else if (attr == &dev_bgt_enabled) -+- return sprintf(buf, "%d\n", ubi->thread_enabled); -++ ret = sprintf(buf, "%d\n", ubi->thread_enabled); -++ else if (attr == &dev_mtd_num) -++ ret = sprintf(buf, "%d\n", ubi->mtd->index); -+ else -+- BUG(); -++ ret = -EINVAL; -+ -+- return 0; -++ ubi_put_device(ubi); -++ return ret; -+ } -+ -+ /* Fake "release" method for UBI devices */ -+@@ -150,68 +391,44 @@ -+ int err; -+ -+ ubi->dev.release = dev_release; -+- ubi->dev.devt = MKDEV(ubi->major, 0); -++ ubi->dev.devt = ubi->cdev.dev; -+ ubi->dev.class = ubi_class; -+ sprintf(&ubi->dev.bus_id[0], UBI_NAME_STR"%d", ubi->ubi_num); -+ err = device_register(&ubi->dev); -+ if (err) -+- goto out; -++ return err; -+ -+ err = device_create_file(&ubi->dev, &dev_eraseblock_size); -+ if (err) -+- goto out_unregister; -++ return err; -+ err = device_create_file(&ubi->dev, &dev_avail_eraseblocks); -+ if (err) -+- goto out_eraseblock_size; -++ return err; -+ err = device_create_file(&ubi->dev, &dev_total_eraseblocks); -+ if (err) -+- goto out_avail_eraseblocks; -++ return err; -+ err = device_create_file(&ubi->dev, &dev_volumes_count); -+ if (err) -+- goto out_total_eraseblocks; -++ return err; -+ err = device_create_file(&ubi->dev, &dev_max_ec); -+ if (err) -+- goto out_volumes_count; -++ return err; -+ err = device_create_file(&ubi->dev, &dev_reserved_for_bad); -+ if (err) -+- goto out_volumes_max_ec; -++ return err; -+ err = device_create_file(&ubi->dev, &dev_bad_peb_count); -+ if (err) -+- goto out_reserved_for_bad; -++ return err; -+ err = device_create_file(&ubi->dev, &dev_max_vol_count); -+ if (err) -+- goto out_bad_peb_count; -++ return err; -+ err = device_create_file(&ubi->dev, &dev_min_io_size); -+ if (err) -+- goto out_max_vol_count; -++ return err; -+ err = device_create_file(&ubi->dev, &dev_bgt_enabled); -+ if (err) -+- goto out_min_io_size; -+- -+- return 0; -+- -+-out_min_io_size: -+- device_remove_file(&ubi->dev, &dev_min_io_size); -+-out_max_vol_count: -+- device_remove_file(&ubi->dev, &dev_max_vol_count); -+-out_bad_peb_count: -+- device_remove_file(&ubi->dev, &dev_bad_peb_count); -+-out_reserved_for_bad: -+- device_remove_file(&ubi->dev, &dev_reserved_for_bad); -+-out_volumes_max_ec: -+- device_remove_file(&ubi->dev, &dev_max_ec); -+-out_volumes_count: -+- device_remove_file(&ubi->dev, &dev_volumes_count); -+-out_total_eraseblocks: -+- device_remove_file(&ubi->dev, &dev_total_eraseblocks); -+-out_avail_eraseblocks: -+- device_remove_file(&ubi->dev, &dev_avail_eraseblocks); -+-out_eraseblock_size: -+- device_remove_file(&ubi->dev, &dev_eraseblock_size); -+-out_unregister: -+- device_unregister(&ubi->dev); -+-out: -+- ubi_err("failed to initialize sysfs for %s", ubi->ubi_name); -++ return err; -++ err = device_create_file(&ubi->dev, &dev_mtd_num); -+ return err; -+ } -+ -+@@ -221,6 +438,7 @@ -+ */ -+ static void ubi_sysfs_close(struct ubi_device *ubi) -+ { -++ device_remove_file(&ubi->dev, &dev_mtd_num); -+ device_remove_file(&ubi->dev, &dev_bgt_enabled); -+ device_remove_file(&ubi->dev, &dev_min_io_size); -+ device_remove_file(&ubi->dev, &dev_max_vol_count); -+@@ -244,7 +462,7 @@ -+ -+ for (i = 0; i < ubi->vtbl_slots; i++) -+ if (ubi->volumes[i]) -+- ubi_free_volume(ubi, i); -++ ubi_free_volume(ubi, ubi->volumes[i]); -+ } -+ -+ /** -+@@ -259,9 +477,6 @@ -+ int i, err; -+ dev_t dev; -+ -+- mutex_init(&ubi->vtbl_mutex); -+- spin_lock_init(&ubi->volumes_lock); -+- -+ sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); -+ -+ /* -+@@ -278,39 +493,40 @@ -+ return err; -+ } -+ -++ ubi_assert(MINOR(dev) == 0); -+ cdev_init(&ubi->cdev, &ubi_cdev_operations); -+- ubi->major = MAJOR(dev); -+- dbg_msg("%s major is %u", ubi->ubi_name, ubi->major); -++ dbg_msg("%s major is %u", ubi->ubi_name, MAJOR(dev)); -+ ubi->cdev.owner = THIS_MODULE; -+ -+- dev = MKDEV(ubi->major, 0); -+ err = cdev_add(&ubi->cdev, dev, 1); -+ if (err) { -+- ubi_err("cannot add character device %s", ubi->ubi_name); -++ ubi_err("cannot add character device"); -+ goto out_unreg; -+ } -+ -+ err = ubi_sysfs_init(ubi); -+ if (err) -+- goto out_cdev; -++ goto out_sysfs; -+ -+ for (i = 0; i < ubi->vtbl_slots; i++) -+ if (ubi->volumes[i]) { -+- err = ubi_add_volume(ubi, i); -+- if (err) -++ err = ubi_add_volume(ubi, ubi->volumes[i]); -++ if (err) { -++ ubi_err("cannot add volume %d", i); -+ goto out_volumes; -++ } -+ } -+ -+ return 0; -+ -+ out_volumes: -+ kill_volumes(ubi); -++out_sysfs: -+ ubi_sysfs_close(ubi); -+-out_cdev: -+ cdev_del(&ubi->cdev); -+ out_unreg: -+- unregister_chrdev_region(MKDEV(ubi->major, 0), -+- ubi->vtbl_slots + 1); -++ unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); -++ ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err); -+ return err; -+ } -+ -+@@ -323,7 +539,7 @@ -+ kill_volumes(ubi); -+ ubi_sysfs_close(ubi); -+ cdev_del(&ubi->cdev); -+- unregister_chrdev_region(MKDEV(ubi->major, 0), ubi->vtbl_slots + 1); -++ unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); -+ } -+ -+ /** -+@@ -370,7 +586,11 @@ -+ out_wl: -+ ubi_wl_close(ubi); -+ out_vtbl: -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(ubi->vtbl); -++#else -+ vfree(ubi->vtbl); -++#endif -+ out_si: -+ ubi_scan_destroy_si(si); -+ return err; -+@@ -384,15 +604,21 @@ -+ * assumed: -+ * o EC header is always at offset zero - this cannot be changed; -+ * o VID header starts just after the EC header at the closest address -+- * aligned to @io->@hdrs_min_io_size; -++ * aligned to @io->hdrs_min_io_size; -+ * o data starts just after the VID header at the closest address aligned to -+- * @io->@min_io_size -++ * @io->min_io_size -+ * -+ * This function returns zero in case of success and a negative error code in -+ * case of failure. -+ */ -+ static int io_init(struct ubi_device *ubi) -+ { -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ printk("kmalloc instead of vmalloc is used.\n"); -++#else -++ printk("vmalloc is used.\n"); -++#endif -++ -+ if (ubi->mtd->numeraseregions != 0) { -+ /* -+ * Some flashes have several erase regions. Different regions -+@@ -407,13 +633,18 @@ -+ return -EINVAL; -+ } -+ -++ if (ubi->vid_hdr_offset < 0) -++ return -EINVAL; -++ -+ /* -+ * Note, in this implementation we support MTD devices with 0x7FFFFFFF -+ * physical eraseblocks maximum. -+ */ -+ -+ ubi->peb_size = ubi->mtd->erasesize; -+- ubi->peb_count = ubi->mtd->size / ubi->mtd->erasesize; -++// ubi->peb_count = ubi->mtd->size / ubi->mtd->erasesize; -++ ubi->peb_count = ubi->mtd->size >> (ffs(ubi->mtd->erasesize) - 1); -++ -+ ubi->flash_size = ubi->mtd->size; -+ -+ if (ubi->mtd->block_isbad && ubi->mtd->block_markbad) -+@@ -424,7 +655,8 @@ -+ -+ /* Make sure minimal I/O unit is power of 2 */ -+ if (!is_power_of_2(ubi->min_io_size)) { -+- ubi_err("bad min. I/O unit"); -++ ubi_err("min. I/O unit (%d) is not power of 2", -++ ubi->min_io_size); -+ return -EINVAL; -+ } -+ -+@@ -453,10 +685,8 @@ -+ } -+ -+ /* Similar for the data offset */ -+- if (ubi->leb_start == 0) { -+- ubi->leb_start = ubi->vid_hdr_offset + ubi->vid_hdr_alsize; -+- ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size); -+- } -++ ubi->leb_start = ubi->vid_hdr_offset + UBI_EC_HDR_SIZE; -++ ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size); -+ -+ dbg_msg("vid_hdr_offset %d", ubi->vid_hdr_offset); -+ dbg_msg("vid_hdr_aloffset %d", ubi->vid_hdr_aloffset); -+@@ -499,8 +729,16 @@ -+ ubi->ro_mode = 1; -+ } -+ -+- dbg_msg("leb_size %d", ubi->leb_size); -+- dbg_msg("ro_mode %d", ubi->ro_mode); -++ ubi_msg("physical eraseblock size: %d bytes (%d KiB)", -++ ubi->peb_size, ubi->peb_size >> 10); -++ ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size); -++ ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size); -++ if (ubi->hdrs_min_io_size != ubi->min_io_size) -++ ubi_msg("sub-page size: %d", -++ ubi->hdrs_min_io_size); -++ ubi_msg("VID header offset: %d (aligned %d)", -++ ubi->vid_hdr_offset, ubi->vid_hdr_aloffset); -++ ubi_msg("data offset: %d", ubi->leb_start); -+ -+ /* -+ * Note, ideally, we have to initialize ubi->bad_peb_count here. But -+@@ -514,87 +752,171 @@ -+ } -+ -+ /** -+- * attach_mtd_dev - attach an MTD device. -+- * @mtd_dev: MTD device name or number string -+- * @vid_hdr_offset: VID header offset -+- * @data_offset: data offset -++ * autoresize - re-size the volume which has the "auto-resize" flag set. -++ * @ubi: UBI device description object -++ * @vol_id: ID of the volume to re-size -+ * -+- * This function attaches an MTD device to UBI. It first treats @mtd_dev as the -+- * MTD device name, and tries to open it by this name. If it is unable to open, -+- * it tries to convert @mtd_dev to an integer and open the MTD device by its -+- * number. Returns zero in case of success and a negative error code in case of -+- * failure. -++ * This function re-sizes the volume marked by the @UBI_VTBL_AUTORESIZE_FLG in -++ * the volume table to the largest possible size. See comments in ubi-header.h -++ * for more description of the flag. Returns zero in case of success and a -++ * negative error code in case of failure. -+ */ -+-static int attach_mtd_dev(const char *mtd_dev, int vid_hdr_offset, -+- int data_offset) -++static int autoresize(struct ubi_device *ubi, int vol_id) -+ { -+- struct ubi_device *ubi; -+- struct mtd_info *mtd; -+- int i, err; -++ struct ubi_volume_desc desc; -++ struct ubi_volume *vol = ubi->volumes[vol_id]; -++ int err, old_reserved_pebs = vol->reserved_pebs; -+ -+- mtd = get_mtd_device_nm(mtd_dev); -+- if (IS_ERR(mtd)) { -+- int mtd_num; -+- char *endp; -++ /* -++ * Clear the auto-resize flag in the volume in-memory copy of the -++ * volume table, and 'ubi_resize_volume()' will propogate this change -++ * to the flash. -++ */ -++ ubi->vtbl[vol_id].flags &= ~UBI_VTBL_AUTORESIZE_FLG; -+ -+- if (PTR_ERR(mtd) != -ENODEV) -+- return PTR_ERR(mtd); -++ if (ubi->avail_pebs == 0) { -++ struct ubi_vtbl_record vtbl_rec; -+ -+ /* -+- * Probably this is not MTD device name but MTD device number - -+- * check this out. -++ * No avalilable PEBs to re-size the volume, clear the flag on -++ * flash and exit. -+ */ -+- mtd_num = simple_strtoul(mtd_dev, &endp, 0); -+- if (*endp != '\0' || mtd_dev == endp) { -+- ubi_err("incorrect MTD device: \"%s\"", mtd_dev); -+- return -ENODEV; -+- } -+- -+- mtd = get_mtd_device(NULL, mtd_num); -+- if (IS_ERR(mtd)) -+- return PTR_ERR(mtd); -++ memcpy(&vtbl_rec, &ubi->vtbl[vol_id], -++ sizeof(struct ubi_vtbl_record)); -++ err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); -++ if (err) -++ ubi_err("cannot clean auto-resize flag for volume %d", -++ vol_id); -++ } else { -++ desc.vol = vol; -++ err = ubi_resize_volume(&desc, -++ old_reserved_pebs + ubi->avail_pebs); -++ if (err) -++ ubi_err("cannot auto-resize volume %d", vol_id); -+ } -+ -+- /* Check if we already have the same MTD device attached */ -+- for (i = 0; i < ubi_devices_cnt; i++) -+- if (ubi_devices[i]->mtd->index == mtd->index) { -+- ubi_err("mtd%d is already attached to ubi%d", -++ if (err) -++ return err; -++ -++ ubi_msg("volume %d (\"%s\") re-sized from %d to %d LEBs", vol_id, -++ vol->name, old_reserved_pebs, vol->reserved_pebs); -++ return 0; -++} -++ -++/** -++ * ubi_attach_mtd_dev - attach an MTD device. -++ * @mtd_dev: MTD device description object -++ * @ubi_num: number to assign to the new UBI device -++ * @vid_hdr_offset: VID header offset -++ * -++ * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number -++ * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in -++ * which case this function finds a vacant device nubert and assings it -++ * automatically. Returns the new UBI device number in case of success and a -++ * negative error code in case of failure. -++ * -++ * Note, the invocations of this function has to be serialized by the -++ * @ubi_devices_mutex. -++ */ -++int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) -++{ -++ struct ubi_device *ubi; -++ int i, err; -++ -++ /* -++ * Check if we already have the same MTD device attached. -++ * -++ * Note, this function assumes that UBI devices creations and deletions -++ * are serialized, so it does not take the &ubi_devices_lock. -++ */ -++ for (i = 0; i < UBI_MAX_DEVICES; i++) { -++ ubi = ubi_devices[i]; -++ if (ubi && mtd->index == ubi->mtd->index) { -++ dbg_err("mtd%d is already attached to ubi%d", -+ mtd->index, i); -+- err = -EINVAL; -+- goto out_mtd; -++ return -EEXIST; -+ } -++ } -+ -+- ubi = ubi_devices[ubi_devices_cnt] = kzalloc(sizeof(struct ubi_device), -+- GFP_KERNEL); -+- if (!ubi) { -+- err = -ENOMEM; -+- goto out_mtd; -++ /* -++ * Make sure this MTD device is not emulated on top of an UBI volume -++ * already. Well, generally this recursion works fine, but there are -++ * different problems like the UBI module takes a reference to itself -++ * by attaching (and thus, opening) the emulated MTD device. This -++ * results in inability to unload the module. And in general it makes -++ * no sense to attach emulated MTD devices, so we prohibit this. -++ */ -++ if (mtd->type == MTD_UBIVOLUME) { -++ ubi_err("refuse attaching mtd%d - it is already emulated on " -++ "top of UBI", mtd->index); -++ return -EINVAL; -+ } -+ -+- ubi->ubi_num = ubi_devices_cnt; -+- ubi->mtd = mtd; -++ if (ubi_num == UBI_DEV_NUM_AUTO) { -++ /* Search for an empty slot in the @ubi_devices array */ -++ for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) -++ if (!ubi_devices[ubi_num]) -++ break; -++ if (ubi_num == UBI_MAX_DEVICES) { -++ dbg_err("only %d UBI devices may be created", UBI_MAX_DEVICES); -++ return -ENFILE; -++ } -++ } else { -++ if (ubi_num >= UBI_MAX_DEVICES) -++ return -EINVAL; -++ -++ /* Make sure ubi_num is not busy */ -++ if (ubi_devices[ubi_num]) { -++ dbg_err("ubi%d already exists", ubi_num); -++ return -EEXIST; -++ } -++ } -+ -+- dbg_msg("attaching mtd%d to ubi%d: VID header offset %d data offset %d", -+- ubi->mtd->index, ubi_devices_cnt, vid_hdr_offset, data_offset); -++ ubi = kzalloc(sizeof(struct ubi_device), GFP_KERNEL); -++ if (!ubi) -++ return -ENOMEM; -+ -++ ubi->mtd = mtd; -++ ubi->ubi_num = ubi_num; -+ ubi->vid_hdr_offset = vid_hdr_offset; -+- ubi->leb_start = data_offset; -++ ubi->autoresize_vol_id = -1; -++ -++ mutex_init(&ubi->buf_mutex); -++ mutex_init(&ubi->ckvol_mutex); -++ mutex_init(&ubi->volumes_mutex); -++ spin_lock_init(&ubi->volumes_lock); -++ -++ dbg_msg("attaching mtd%d to ubi%d: VID header offset %d", -++ mtd->index, ubi_num, vid_hdr_offset); -+ err = io_init(ubi); -+ if (err) -+ goto out_free; -+ -+- mutex_init(&ubi->buf_mutex); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ ubi->peb_buf1 = kmalloc(ubi->peb_size, GFP_KERNEL); -++#else -+ ubi->peb_buf1 = vmalloc(ubi->peb_size); -++#endif -++ -+ if (!ubi->peb_buf1) -+ goto out_free; -+ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ ubi->peb_buf2 = kmalloc(ubi->peb_size, GFP_KERNEL); -++#else -+ ubi->peb_buf2 = vmalloc(ubi->peb_size); -++#endif -+ if (!ubi->peb_buf2) -+ goto out_free; -+ -+ #ifdef CONFIG_MTD_UBI_DEBUG -+ mutex_init(&ubi->dbg_buf_mutex); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ ubi->dbg_peb_buf = kmalloc(ubi->peb_size, GFP_KERNEL); -++#else -+ ubi->dbg_peb_buf = vmalloc(ubi->peb_size); -++#endif -++ -+ if (!ubi->dbg_peb_buf) -+ goto out_free; -+ #endif -+@@ -605,22 +927,33 @@ -+ goto out_free; -+ } -+ -++ if (ubi->autoresize_vol_id != -1) { -++ err = autoresize(ubi, ubi->autoresize_vol_id); -++ if (err) -++ goto out_detach; -++ } -++ -+ err = uif_init(ubi); -+ if (err) -+ goto out_detach; -+ -+- ubi_msg("attached mtd%d to ubi%d", ubi->mtd->index, ubi_devices_cnt); -+- ubi_msg("MTD device name: \"%s\"", ubi->mtd->name); -++ err = bdev_init(ubi); -++ if(err) -++ goto out_detach; -++ -++ ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name); -++ if (IS_ERR(ubi->bgt_thread)) { -++ err = PTR_ERR(ubi->bgt_thread); -++ ubi_err("cannot spawn \"%s\", error %d", ubi->bgt_name, -++ err); -++ goto out_uif; -++ } -++ -++ ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num); -++ ubi_msg("MTD device name: \"%s\"", mtd->name); -+ ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20); -+- ubi_msg("physical eraseblock size: %d bytes (%d KiB)", -+- ubi->peb_size, ubi->peb_size >> 10); -+- ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size); -+ ubi_msg("number of good PEBs: %d", ubi->good_peb_count); -+ ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count); -+- ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size); -+- ubi_msg("VID header offset: %d (aligned %d)", -+- ubi->vid_hdr_offset, ubi->vid_hdr_aloffset); -+- ubi_msg("data offset: %d", ubi->leb_start); -+ ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots); -+ ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD); -+ ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT); -+@@ -638,50 +971,141 @@ -+ wake_up_process(ubi->bgt_thread); -+ } -+ -+- ubi_devices_cnt += 1; -+- return 0; -++ ubi_devices[ubi_num] = ubi; -++ return ubi_num; -+ -++out_uif: -++ uif_close(ubi); -+ out_detach: -+ ubi_eba_close(ubi); -+ ubi_wl_close(ubi); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(ubi->vtbl); -++#else -+ vfree(ubi->vtbl); -++#endif -+ out_free: -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(ubi->peb_buf1); -++ kfree(ubi->peb_buf2); -++#else -+ vfree(ubi->peb_buf1); -+ vfree(ubi->peb_buf2); -++#endif -+ #ifdef CONFIG_MTD_UBI_DEBUG -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(ubi->dbg_peb_buf); -++#else -+ vfree(ubi->dbg_peb_buf); -+ #endif -++#endif -+ kfree(ubi); -+-out_mtd: -+- put_mtd_device(mtd); -+- ubi_devices[ubi_devices_cnt] = NULL; -+ return err; -+ } -+ -+ /** -+- * detach_mtd_dev - detach an MTD device. -+- * @ubi: UBI device description object -++ * ubi_detach_mtd_dev - detach an MTD device. -++ * @ubi_num: UBI device number to detach from -++ * @anyway: detach MTD even if device reference count is not zero -++ * -++ * This function destroys an UBI device number @ubi_num and detaches the -++ * underlying MTD device. Returns zero in case of success and %-EBUSY if the -++ * UBI device is busy and cannot be destroyed, and %-EINVAL if it does not -++ * exist. -++ * -++ * Note, the invocations of this function has to be serialized by the -++ * @ubi_devices_mutex. -+ */ -+-static void detach_mtd_dev(struct ubi_device *ubi) -++int ubi_detach_mtd_dev(int ubi_num, int anyway) -+ { -+- int ubi_num = ubi->ubi_num, mtd_num = ubi->mtd->index; -++ struct ubi_device *ubi; -++ -++ if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) -++ return -EINVAL; -++ -++ spin_lock(&ubi_devices_lock); -++ ubi = ubi_devices[ubi_num]; -++ if (!ubi) { -++ spin_unlock(&ubi_devices_lock); -++ return -EINVAL; -++ } -+ -++ if (ubi->ref_count) { -++ if (!anyway) { -++ spin_unlock(&ubi_devices_lock); -++ return -EBUSY; -++ } -++ /* This may only happen if there is a bug */ -++ ubi_err("%s reference count %d, destroy anyway", -++ ubi->ubi_name, ubi->ref_count); -++ } -++ ubi_devices[ubi_num] = NULL; -++ spin_unlock(&ubi_devices_lock); -++ -++ ubi_assert(ubi_num == ubi->ubi_num); -+ dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num); -++ -++ /* -++ * Before freeing anything, we have to stop the background thread to -++ * prevent it from doing anything on this device while we are freeing. -++ */ -++ if (ubi->bgt_thread) -++ kthread_stop(ubi->bgt_thread); -++ -+ uif_close(ubi); -+ ubi_eba_close(ubi); -+ ubi_wl_close(ubi); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(ubi->vtbl); -++#else -+ vfree(ubi->vtbl); -++#endif -+ put_mtd_device(ubi->mtd); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(ubi->peb_buf1); -++ kfree(ubi->peb_buf2); -++#else -+ vfree(ubi->peb_buf1); -+ vfree(ubi->peb_buf2); -++#endif -+ #ifdef CONFIG_MTD_UBI_DEBUG -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(ubi->dbg_peb_buf); -++#else -+ vfree(ubi->dbg_peb_buf); -+ #endif -+- kfree(ubi_devices[ubi_num]); -+- ubi_devices[ubi_num] = NULL; -+- ubi_devices_cnt -= 1; -+- ubi_assert(ubi_devices_cnt >= 0); -+- ubi_msg("mtd%d is detached from ubi%d", mtd_num, ubi_num); -++#endif -++ ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num); -++ kfree(ubi); -++ return 0; -++} -++ -++/** -++ * find_mtd_device - open an MTD device by its name or number. -++ * @mtd_dev: name or number of the device -++ * -++ * This function tries to open and MTD device described by @mtd_dev string, -++ * which is first treated as an ASCII number, and if it is not true, it is -++ * treated as MTD device name. Returns MTD device description object in case of -++ * success and a negative error code in case of failure. -++ */ -++static struct mtd_info * __init open_mtd_device(const char *mtd_dev) -++{ -++ struct mtd_info *mtd; -++ int mtd_num; -++ char *endp; -++ -++ mtd_num = simple_strtoul(mtd_dev, &endp, 0); -++ if (*endp != '\0' || mtd_dev == endp) { -++ /* -++ * This does not look like an ASCII integer, probably this is -++ * MTD device name. -++ */ -++ mtd = get_mtd_device_nm(mtd_dev); -++ } else -++ mtd = get_mtd_device(NULL, mtd_num); -++ -++ return mtd; -+ } -+ -+ static int __init ubi_init(void) -+@@ -693,47 +1117,94 @@ -+ BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64); -+ -+ if (mtd_devs > UBI_MAX_DEVICES) { -+- printk("UBI error: too many MTD devices, maximum is %d\n", -+- UBI_MAX_DEVICES); -++ ubi_err("too many MTD devices, maximum is %d", UBI_MAX_DEVICES); -+ return -EINVAL; -+ } -+ -++ /* Create base sysfs directory and sysfs files */ -+ ubi_class = class_create(THIS_MODULE, UBI_NAME_STR); -+- if (IS_ERR(ubi_class)) -+- return PTR_ERR(ubi_class); -++ if (IS_ERR(ubi_class)) { -++ err = PTR_ERR(ubi_class); -++ ubi_err("cannot create UBI class"); -++ goto out; -++ } -+ -+ err = class_create_file(ubi_class, &ubi_version); -+- if (err) -++ if (err) { -++ ubi_err("cannot create sysfs file"); -+ goto out_class; -++ } -++ -++ err = misc_register(&ubi_ctrl_cdev); -++ if (err) { -++ ubi_err("cannot register device"); -++ goto out_version; -++ } -++ -++ ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", -++ sizeof(struct ubi_wl_entry), -++ 0, 0, NULL); -++ if (!ubi_wl_entry_slab) -++ goto out_dev_unreg; -+ -+ /* Attach MTD devices */ -+ for (i = 0; i < mtd_devs; i++) { -+ struct mtd_dev_param *p = &mtd_dev_param[i]; -++ struct mtd_info *mtd; -+ -+ cond_resched(); -+- err = attach_mtd_dev(p->name, p->vid_hdr_offs, p->data_offs); -+- if (err) -++ -++ mtd = open_mtd_device(p->name); -++ if (IS_ERR(mtd)) { -++ err = PTR_ERR(mtd); -++ goto out_detach; -++ } -++ -++ mutex_lock(&ubi_devices_mutex); -++ err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, -++ p->vid_hdr_offs); -++ mutex_unlock(&ubi_devices_mutex); -++ if (err < 0) { -++ put_mtd_device(mtd); -++ ubi_err("cannot attach mtd%d", mtd->index); -+ goto out_detach; -++ } -+ } -+ -+ return 0; -+ -+ out_detach: -+ for (k = 0; k < i; k++) -+- detach_mtd_dev(ubi_devices[k]); -++ if (ubi_devices[k]) { -++ mutex_lock(&ubi_devices_mutex); -++ ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1); -++ mutex_unlock(&ubi_devices_mutex); -++ } -++ kmem_cache_destroy(ubi_wl_entry_slab); -++out_dev_unreg: -++ misc_deregister(&ubi_ctrl_cdev); -++out_version: -+ class_remove_file(ubi_class, &ubi_version); -+ out_class: -+ class_destroy(ubi_class); -++out: -++ ubi_err("UBI error: cannot initialize UBI, error %d", err); -+ return err; -+ } -+ module_init(ubi_init); -+ -+ static void __exit ubi_exit(void) -+ { -+- int i, n = ubi_devices_cnt; -++ int i; -+ -+- for (i = 0; i < n; i++) -+- detach_mtd_dev(ubi_devices[i]); -++ for (i = 0; i < UBI_MAX_DEVICES; i++) -++ if (ubi_devices[i]) { -++ mutex_lock(&ubi_devices_mutex); -++ ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1); -++ mutex_unlock(&ubi_devices_mutex); -++ } -++ kmem_cache_destroy(ubi_wl_entry_slab); -++ misc_deregister(&ubi_ctrl_cdev); -+ class_remove_file(ubi_class, &ubi_version); -+ class_destroy(ubi_class); -+ } -+@@ -754,7 +1225,8 @@ -+ -+ result = simple_strtoul(str, &endp, 0); -+ if (str == endp || result < 0) { -+- printk("UBI error: incorrect bytes count: \"%s\"\n", str); -++ printk(KERN_ERR "UBI error: incorrect bytes count: \"%s\"\n", -++ str); -+ return -EINVAL; -+ } -+ -+@@ -764,15 +1236,14 @@ -+ case 'M': -+ result *= 1024; -+ case 'K': -+- case 'k': -+ result *= 1024; -+- if (endp[1] == 'i' && (endp[2] == '\0' || -+- endp[2] == 'B' || endp[2] == 'b')) -++ if (endp[1] == 'i' && endp[2] == 'B') -+ endp += 2; -+ case '\0': -+ break; -+ default: -+- printk("UBI error: incorrect bytes count: \"%s\"\n", str); -++ printk(KERN_ERR "UBI error: incorrect bytes count: \"%s\"\n", -++ str); -+ return -EINVAL; -+ } -+ -+@@ -793,23 +1264,27 @@ -+ struct mtd_dev_param *p; -+ char buf[MTD_PARAM_LEN_MAX]; -+ char *pbuf = &buf[0]; -+- char *tokens[3] = {NULL, NULL, NULL}; -++ char *tokens[2] = {NULL, NULL}; -++ -++ if (!val) -++ return -EINVAL; -+ -+ if (mtd_devs == UBI_MAX_DEVICES) { -+- printk("UBI error: too many parameters, max. is %d\n", -++ printk(KERN_ERR "UBI error: too many parameters, max. is %d\n", -+ UBI_MAX_DEVICES); -+ return -EINVAL; -+ } -+ -+ len = strnlen(val, MTD_PARAM_LEN_MAX); -+ if (len == MTD_PARAM_LEN_MAX) { -+- printk("UBI error: parameter \"%s\" is too long, max. is %d\n", -+- val, MTD_PARAM_LEN_MAX); -++ printk(KERN_ERR "UBI error: parameter \"%s\" is too long, " -++ "max. is %d\n", val, MTD_PARAM_LEN_MAX); -+ return -EINVAL; -+ } -+ -+ if (len == 0) { -+- printk("UBI warning: empty 'mtd=' parameter - ignored\n"); -++ printk(KERN_WARNING "UBI warning: empty 'mtd=' parameter - " -++ "ignored\n"); -+ return 0; -+ } -+ -+@@ -819,11 +1294,12 @@ -+ if (buf[len - 1] == '\n') -+ buf[len - 1] = '\0'; -+ -+- for (i = 0; i < 3; i++) -++ for (i = 0; i < 2; i++) -+ tokens[i] = strsep(&pbuf, ","); -+ -+ if (pbuf) { -+- printk("UBI error: too many arguments at \"%s\"\n", val); -++ printk(KERN_ERR "UBI error: too many arguments at \"%s\"\n", -++ val); -+ return -EINVAL; -+ } -+ -+@@ -832,13 +1308,9 @@ -+ -+ if (tokens[1]) -+ p->vid_hdr_offs = bytes_str_to_int(tokens[1]); -+- if (tokens[2]) -+- p->data_offs = bytes_str_to_int(tokens[2]); -+ -+ if (p->vid_hdr_offs < 0) -+ return p->vid_hdr_offs; -+- if (p->data_offs < 0) -+- return p->data_offs; -+ -+ mtd_devs += 1; -+ return 0; -+@@ -846,16 +1318,15 @@ -+ -+ module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 000); -+ MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: " -+- "mtd=[,,]. " -++ "mtd=[,].\n" -+ "Multiple \"mtd\" parameters may be specified.\n" -+- "MTD devices may be specified by their number or name. " -+- "Optional \"vid_hdr_offs\" and \"data_offs\" parameters " -+- "specify UBI VID header position and data starting " -+- "position to be used by UBI.\n" -+- "Example: mtd=content,1984,2048 mtd=4 - attach MTD device" -+- "with name content using VID header offset 1984 and data " -+- "start 2048, and MTD device number 4 using default " -+- "offsets"); -++ "MTD devices may be specified by their number or name.\n" -++ "Optional \"vid_hdr_offs\" parameter specifies UBI VID " -++ "header position and data starting position to be used " -++ "by UBI.\n" -++ "Example: mtd=content,1984 mtd=4 - attach MTD device" -++ "with name \"content\" using VID header offset 1984, and " -++ "MTD device number 4 with default VID header offset."); -+ -+ MODULE_VERSION(__stringify(UBI_VERSION)); -+ MODULE_DESCRIPTION("UBI - Unsorted Block Images"); -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/cdev.c linux-2.6.24.7/drivers/mtd/ubi/cdev.c -+--- linux-2.6.24.7.old/drivers/mtd/ubi/cdev.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/cdev.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -28,6 +28,11 @@ -+ * -+ * Major and minor numbers are assigned dynamically to both UBI and volume -+ * character devices. -++ * -++ * Well, there is the third kind of character devices - the UBI control -++ * character device, which allows to manipulate by UBI devices - create and -++ * delete them. In other words, it is used for attaching and detaching MTD -++ * devices. -+ */ -+ -+ #include -+@@ -39,34 +44,6 @@ -+ #include -+ #include "ubi.h" -+ -+-/* -+- * Maximum sequence numbers of UBI and volume character device IOCTLs (direct -+- * logical eraseblock erase is a debug-only feature). -+- */ -+-#define UBI_CDEV_IOC_MAX_SEQ 2 -+-#ifndef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO -+-#define VOL_CDEV_IOC_MAX_SEQ 1 -+-#else -+-#define VOL_CDEV_IOC_MAX_SEQ 2 -+-#endif -+- -+-/** -+- * major_to_device - get UBI device object by character device major number. -+- * @major: major number -+- * -+- * This function returns a pointer to the UBI device object. -+- */ -+-static struct ubi_device *major_to_device(int major) -+-{ -+- int i; -+- -+- for (i = 0; i < ubi_devices_cnt; i++) -+- if (ubi_devices[i] && ubi_devices[i]->major == major) -+- return ubi_devices[i]; -+- BUG(); -+- return NULL; -+-} -+- -+ /** -+ * get_exclusive - get exclusive access to an UBI volume. -+ * @desc: volume descriptor -+@@ -124,9 +101,11 @@ -+ static int vol_cdev_open(struct inode *inode, struct file *file) -+ { -+ struct ubi_volume_desc *desc; -+- const struct ubi_device *ubi = major_to_device(imajor(inode)); -+- int vol_id = iminor(inode) - 1; -+- int mode; -++ int vol_id = iminor(inode) - 1, mode, ubi_num; -++ -++ ubi_num = ubi_major2num(imajor(inode)); -++ if (ubi_num < 0) -++ return ubi_num; -+ -+ if (file->f_mode & FMODE_WRITE) -+ mode = UBI_READWRITE; -+@@ -135,7 +114,7 @@ -+ -+ dbg_msg("open volume %d, mode %d", vol_id, mode); -+ -+- desc = ubi_open_volume(ubi->ubi_num, vol_id, mode); -++ desc = ubi_open_volume(ubi_num, vol_id, mode); -+ if (IS_ERR(desc)) -+ return PTR_ERR(desc); -+ -+@@ -153,8 +132,23 @@ -+ if (vol->updating) { -+ ubi_warn("update of volume %d not finished, volume is damaged", -+ vol->vol_id); -++ ubi_assert(!vol->changing_leb); -+ vol->updating = 0; -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(vol->upd_buf); -++#else -+ vfree(vol->upd_buf); -++#endif -++ } else if (vol->changing_leb) { -++ dbg_msg("only %lld of %lld bytes received for atomic LEB change" -++ " for volume %d:%d, cancel", vol->upd_received, -++ vol->upd_bytes, vol->ubi->ubi_num, vol->vol_id); -++ vol->changing_leb = 0; -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(vol->upd_buf); -++#else -++ vfree(vol->upd_buf); -++#endif -+ } -+ -+ ubi_close_volume(desc); -+@@ -205,13 +199,13 @@ -+ struct ubi_volume_desc *desc = file->private_data; -+ struct ubi_volume *vol = desc->vol; -+ struct ubi_device *ubi = vol->ubi; -+- int err, lnum, off, len, vol_id = desc->vol->vol_id, tbuf_size; -++ int err, lnum, off, len, tbuf_size; -+ size_t count_save = count; -+ void *tbuf; -+ uint64_t tmp; -+ -+ dbg_msg("read %zd bytes from offset %lld of volume %d", -+- count, *offp, vol_id); -++ count, *offp, vol->vol_id); -+ -+ if (vol->updating) { -+ dbg_err("updating"); -+@@ -225,7 +219,7 @@ -+ return 0; -+ -+ if (vol->corrupted) -+- dbg_msg("read from corrupted volume %d", vol_id); -++ dbg_msg("read from corrupted volume %d", vol->vol_id); -+ -+ if (*offp + count > vol->used_bytes) -+ count_save = count = vol->used_bytes - *offp; -+@@ -233,7 +227,11 @@ -+ tbuf_size = vol->usable_leb_size; -+ if (count < tbuf_size) -+ tbuf_size = ALIGN(count, ubi->min_io_size); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ tbuf = kmalloc(tbuf_size, GFP_KERNEL); -++#else -+ tbuf = vmalloc(tbuf_size); -++#endif -+ if (!tbuf) -+ return -ENOMEM; -+ -+@@ -249,7 +247,7 @@ -+ if (off + len >= vol->usable_leb_size) -+ len = vol->usable_leb_size - off; -+ -+- err = ubi_eba_read_leb(ubi, vol_id, lnum, tbuf, off, len, 0); -++ err = ubi_eba_read_leb(ubi, vol, lnum, tbuf, off, len, 0); -+ if (err) -+ break; -+ -+@@ -272,7 +270,11 @@ -+ len = count > tbuf_size ? tbuf_size : count; -+ } while (count); -+ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(tbuf); -++#else -+ vfree(tbuf); -++#endif -+ return err ? err : count_save - count; -+ } -+ -+@@ -289,13 +291,13 @@ -+ struct ubi_volume_desc *desc = file->private_data; -+ struct ubi_volume *vol = desc->vol; -+ struct ubi_device *ubi = vol->ubi; -+- int lnum, off, len, tbuf_size, vol_id = vol->vol_id, err = 0; -++ int lnum, off, len, tbuf_size, err = 0; -+ size_t count_save = count; -+ char *tbuf; -+ uint64_t tmp; -+ -+ dbg_msg("requested: write %zd bytes to offset %lld of volume %u", -+- count, *offp, desc->vol->vol_id); -++ count, *offp, vol->vol_id); -+ -+ if (vol->vol_type == UBI_STATIC_VOLUME) -+ return -EROFS; -+@@ -321,7 +323,12 @@ -+ tbuf_size = vol->usable_leb_size; -+ if (count < tbuf_size) -+ tbuf_size = ALIGN(count, ubi->min_io_size); -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ tbuf = kmalloc(tbuf_size, GFP_KERNEL); -++#else -+ tbuf = vmalloc(tbuf_size); -++#endif -+ if (!tbuf) -+ return -ENOMEM; -+ -+@@ -339,7 +346,7 @@ -+ break; -+ } -+ -+- err = ubi_eba_write_leb(ubi, vol_id, lnum, tbuf, off, len, -++ err = ubi_eba_write_leb(ubi, vol, lnum, tbuf, off, len, -+ UBI_UNKNOWN); -+ if (err) -+ break; -+@@ -356,7 +363,11 @@ -+ len = count > tbuf_size ? tbuf_size : count; -+ } -+ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(tbuf); -++#else -+ vfree(tbuf); -++#endif -+ return err ? err : count_save - count; -+ } -+ -+@@ -372,22 +383,32 @@ -+ struct ubi_volume *vol = desc->vol; -+ struct ubi_device *ubi = vol->ubi; -+ -+- if (!vol->updating) -++ if (!vol->updating && !vol->changing_leb) -+ return vol_cdev_direct_write(file, buf, count, offp); -+ -+- err = ubi_more_update_data(ubi, vol->vol_id, buf, count); -++ if (vol->updating) -++ err = ubi_more_update_data(ubi, vol, buf, count); -++ else -++ err = ubi_more_leb_change_data(ubi, vol, buf, count); -++ -+ if (err < 0) { -+- ubi_err("cannot write %zd bytes of update data", count); -++ ubi_err("cannot accept more %zd bytes of data, error %d", -++ count, err); -+ return err; -+ } -+ -+ if (err) { -+ /* -+- * Update is finished, @err contains number of actually written -+- * bytes now. -++ * The operation is finished, @err contains number of actually -++ * written bytes. -+ */ -+ count = err; -+ -++ if (vol->changing_leb) { -++ revoke_exclusive(desc, UBI_READWRITE); -++ return count; -++ } -++ -+ err = ubi_check_volume(ubi, vol->vol_id); -+ if (err < 0) -+ return err; -+@@ -402,7 +423,6 @@ -+ revoke_exclusive(desc, UBI_READWRITE); -+ } -+ -+- *offp += count; -+ return count; -+ } -+ -+@@ -416,6 +436,47 @@ -+ void __user *argp = (void __user *)arg; -+ -+ switch (cmd) { -++ /* LEB read command */ -++ case UBI_IOCLEBREAD: -++ { -++ struct ubi_leb leb; -++ int pnum; -++ char *lebbuf; -++ -++ if (copy_from_user(&leb, argp, sizeof(struct ubi_leb))){ -++ err = -EFAULT; -++ break; -++ } -++ -++ pnum = vol->eba_tbl[leb.lnum]; -++ if (pnum < 0) { -++ //the LEB is clean, no need dump -++ err = 1; -++ break; -++ } -++ -++ lebbuf = kmalloc(vol->ubi->leb_size, GFP_KERNEL); -++ if (!lebbuf){ -++ err = -ENOMEM; -++ break; -++ } -++ -++ err= ubi_eba_read_leb(ubi, vol, leb.lnum, lebbuf, 0, vol->ubi->leb_size, 0); -++ if (err){ -++ kfree(lebbuf); -++ break; -++ } -++ -++ err = copy_to_user(leb.buf, lebbuf, vol->ubi->leb_size); -++ if (err) { -++ kfree(lebbuf); -++ err = -EFAULT; -++ break; -++ } -++ kfree(lebbuf); -++ break; -++ } -++ -+ /* Volume update command */ -+ case UBI_IOCVOLUP: -+ { -+@@ -447,11 +508,46 @@ -+ if (err < 0) -+ break; -+ -+- err = ubi_start_update(ubi, vol->vol_id, bytes); -++ err = ubi_start_update(ubi, vol, bytes); -+ if (bytes == 0) -+ revoke_exclusive(desc, UBI_READWRITE); -++ break; -++ } -++ -++ /* Atomic logical eraseblock change command */ -++ case UBI_IOCEBCH: -++ { -++ struct ubi_leb_change_req req; -++ -++ err = copy_from_user(&req, argp, -++ sizeof(struct ubi_leb_change_req)); -++ if (err) { -++ err = -EFAULT; -++ break; -++ } -++ -++ if (desc->mode == UBI_READONLY || -++ vol->vol_type == UBI_STATIC_VOLUME) { -++ err = -EROFS; -++ break; -++ } -++ -++ /* Validate the request */ -++ err = -EINVAL; -++ if (req.lnum < 0 || req.lnum >= vol->reserved_pebs || -++ req.bytes < 0 || req.lnum >= vol->usable_leb_size) -++ break; -++ if (req.dtype != UBI_LONGTERM && req.dtype != UBI_SHORTTERM && -++ req.dtype != UBI_UNKNOWN) -++ break; -+ -+- file->f_pos = 0; -++ err = get_exclusive(desc); -++ if (err < 0) -++ break; -++ -++ err = ubi_start_leb_change(ubi, vol, &req); -++ if (req.bytes == 0) -++ revoke_exclusive(desc, UBI_READWRITE); -+ break; -+ } -+ -+@@ -467,7 +563,8 @@ -+ break; -+ } -+ -+- if (desc->mode == UBI_READONLY) { -++ if (desc->mode == UBI_READONLY || -++ vol->vol_type == UBI_STATIC_VOLUME) { -+ err = -EROFS; -+ break; -+ } -+@@ -477,13 +574,8 @@ -+ break; -+ } -+ -+- if (vol->vol_type != UBI_DYNAMIC_VOLUME) { -+- err = -EROFS; -+- break; -+- } -+- -+ dbg_msg("erase LEB %d:%d", vol->vol_id, lnum); -+- err = ubi_eba_unmap_leb(ubi, vol->vol_id, lnum); -++ err = ubi_eba_unmap_leb(ubi, vol, lnum); -+ if (err) -+ break; -+ -+@@ -580,9 +672,9 @@ -+ if (!capable(CAP_SYS_RESOURCE)) -+ return -EPERM; -+ -+- ubi = major_to_device(imajor(inode)); -+- if (IS_ERR(ubi)) -+- return PTR_ERR(ubi); -++ ubi = ubi_get_by_major(imajor(inode)); -++ if (!ubi) -++ return -ENODEV; -+ -+ switch (cmd) { -+ /* Create volume command */ -+@@ -591,8 +683,7 @@ -+ struct ubi_mkvol_req req; -+ -+ dbg_msg("create volume"); -+- err = copy_from_user(&req, argp, -+- sizeof(struct ubi_mkvol_req)); -++ err = copy_from_user(&req, argp, sizeof(struct ubi_mkvol_req)); -+ if (err) { -+ err = -EFAULT; -+ break; -+@@ -604,7 +695,9 @@ -+ -+ req.name[req.name_len] = '\0'; -+ -++ mutex_lock(&ubi->volumes_mutex); -+ err = ubi_create_volume(ubi, &req); -++ mutex_unlock(&ubi->volumes_mutex); -+ if (err) -+ break; -+ -+@@ -633,10 +726,16 @@ -+ break; -+ } -+ -++ mutex_lock(&ubi->volumes_mutex); -+ err = ubi_remove_volume(desc); -+- if (err) -+- ubi_close_volume(desc); -++ mutex_unlock(&ubi->volumes_mutex); -+ -++ /* -++ * The volume is deleted (unless an error occurred), and the -++ * 'struct ubi_volume' object will be freed when -++ * 'ubi_close_volume()' will call 'put_device()'. -++ */ -++ ubi_close_volume(desc); -+ break; -+ } -+ -+@@ -648,8 +747,7 @@ -+ struct ubi_rsvol_req req; -+ -+ dbg_msg("re-size volume"); -+- err = copy_from_user(&req, argp, -+- sizeof(struct ubi_rsvol_req)); -++ err = copy_from_user(&req, argp, sizeof(struct ubi_rsvol_req)); -+ if (err) { -+ err = -EFAULT; -+ break; -+@@ -669,7 +767,9 @@ -+ pebs = !!do_div(tmp, desc->vol->usable_leb_size); -+ pebs += tmp; -+ -++ mutex_lock(&ubi->volumes_mutex); -+ err = ubi_resize_volume(desc, pebs); -++ mutex_unlock(&ubi->volumes_mutex); -+ ubi_close_volume(desc); -+ break; -+ } -+@@ -679,9 +779,93 @@ -+ break; -+ } -+ -++ ubi_put_device(ubi); -++ return err; -++} -++ -++static int ctrl_cdev_ioctl(struct inode *inode, struct file *file, -++ unsigned int cmd, unsigned long arg) -++{ -++ int err = 0; -++ void __user *argp = (void __user *)arg; -++ -++ if (!capable(CAP_SYS_RESOURCE)) -++ return -EPERM; -++ -++ switch (cmd) { -++ /* Attach an MTD device command */ -++ case UBI_IOCATT: -++ { -++ struct ubi_attach_req req; -++ struct mtd_info *mtd; -++ -++ dbg_msg("attach MTD device"); -++ err = copy_from_user(&req, argp, sizeof(struct ubi_attach_req)); -++ if (err) { -++ err = -EFAULT; -++ break; -++ } -++ -++ if (req.mtd_num < 0 || -++ (req.ubi_num < 0 && req.ubi_num != UBI_DEV_NUM_AUTO)) { -++ err = -EINVAL; -++ break; -++ } -++ -++ mtd = get_mtd_device(NULL, req.mtd_num); -++ if (IS_ERR(mtd)) { -++ err = PTR_ERR(mtd); -++ break; -++ } -++ -++ /* -++ * Note, further request verification is done by -++ * 'ubi_attach_mtd_dev()'. -++ */ -++ mutex_lock(&ubi_devices_mutex); -++ err = ubi_attach_mtd_dev(mtd, req.ubi_num, req.vid_hdr_offset); -++ mutex_unlock(&ubi_devices_mutex); -++ if (err < 0) -++ put_mtd_device(mtd); -++ else -++ /* @err contains UBI device number */ -++ err = put_user(err, (__user int32_t *)argp); -++ -++ break; -++ } -++ -++ /* Detach an MTD device command */ -++ case UBI_IOCDET: -++ { -++ int ubi_num; -++ -++ dbg_msg("dettach MTD device"); -++ err = get_user(ubi_num, (__user int32_t *)argp); -++ if (err) { -++ err = -EFAULT; -++ break; -++ } -++ -++ mutex_lock(&ubi_devices_mutex); -++ err = ubi_detach_mtd_dev(ubi_num, 0); -++ mutex_unlock(&ubi_devices_mutex); -++ break; -++ } -++ -++ default: -++ err = -ENOTTY; -++ break; -++ } -++ -+ return err; -+ } -+ -++/* UBI control character device operations */ -++struct file_operations ubi_ctrl_cdev_operations = { -++ .ioctl = ctrl_cdev_ioctl, -++ .owner = THIS_MODULE, -++}; -++ -+ /* UBI character device operations */ -+ struct file_operations ubi_cdev_operations = { -+ .owner = THIS_MODULE, -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/debug.h linux-2.6.24.7/drivers/mtd/ubi/debug.h -+--- linux-2.6.24.7.old/drivers/mtd/ubi/debug.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/debug.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -39,8 +39,9 @@ -+ -+ #ifdef CONFIG_MTD_UBI_DEBUG_MSG -+ /* Generic debugging message */ -+-#define dbg_msg(fmt, ...) \ -+- printk(KERN_DEBUG "UBI DBG: %s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__) -++#define dbg_msg(fmt, ...) \ -++ printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \ -++ current->pid, __FUNCTION__, ##__VA_ARGS__) -+ -+ #define ubi_dbg_dump_stack() dump_stack() -+ -+@@ -76,38 +77,32 @@ -+ -+ #ifdef CONFIG_MTD_UBI_DEBUG_MSG_EBA -+ /* Messages from the eraseblock association unit */ -+-#define dbg_eba(fmt, ...) \ -+- printk(KERN_DEBUG "UBI DBG eba: %s: " fmt "\n", __FUNCTION__, \ -+- ##__VA_ARGS__) -++#define dbg_eba(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -+ #else -+ #define dbg_eba(fmt, ...) ({}) -+ #endif -+ -+ #ifdef CONFIG_MTD_UBI_DEBUG_MSG_WL -+ /* Messages from the wear-leveling unit */ -+-#define dbg_wl(fmt, ...) \ -+- printk(KERN_DEBUG "UBI DBG wl: %s: " fmt "\n", __FUNCTION__, \ -+- ##__VA_ARGS__) -++#define dbg_wl(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -+ #else -+ #define dbg_wl(fmt, ...) ({}) -+ #endif -+ -+ #ifdef CONFIG_MTD_UBI_DEBUG_MSG_IO -+ /* Messages from the input/output unit */ -+-#define dbg_io(fmt, ...) \ -+- printk(KERN_DEBUG "UBI DBG io: %s: " fmt "\n", __FUNCTION__, \ -+- ##__VA_ARGS__) -++#define dbg_io(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -+ #else -+ #define dbg_io(fmt, ...) ({}) -+ #endif -+ -+ #ifdef CONFIG_MTD_UBI_DEBUG_MSG_BLD -+ /* Initialization and build messages */ -+-#define dbg_bld(fmt, ...) \ -+- printk(KERN_DEBUG "UBI DBG bld: %s: " fmt "\n", __FUNCTION__, \ -+- ##__VA_ARGS__) -++#define dbg_bld(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -++#define UBI_IO_DEBUG 1 -+ #else -+ #define dbg_bld(fmt, ...) ({}) -++#define UBI_IO_DEBUG 0 -+ #endif -+ -+ #ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/eba.c linux-2.6.24.7/drivers/mtd/ubi/eba.c -+--- linux-2.6.24.7.old/drivers/mtd/ubi/eba.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/eba.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -31,7 +31,7 @@ -+ * logical eraseblock it is locked for reading or writing. The per-logical -+ * eraseblock locking is implemented by means of the lock tree. The lock tree -+ * is an RB-tree which refers all the currently locked logical eraseblocks. The -+- * lock tree elements are &struct ltree_entry objects. They are indexed by -++ * lock tree elements are &struct ubi_ltree_entry objects. They are indexed by -+ * (@vol_id, @lnum) pairs. -+ * -+ * EBA also maintains the global sequence counter which is incremented each -+@@ -45,34 +45,11 @@ -+ #include -+ #include -+ #include "ubi.h" -+- -++#include "ubiblk.h" -+ /* Number of physical eraseblocks reserved for atomic LEB change operation */ -+ #define EBA_RESERVED_PEBS 1 -+ -+ /** -+- * struct ltree_entry - an entry in the lock tree. -+- * @rb: links RB-tree nodes -+- * @vol_id: volume ID of the locked logical eraseblock -+- * @lnum: locked logical eraseblock number -+- * @users: how many tasks are using this logical eraseblock or wait for it -+- * @mutex: read/write mutex to implement read/write access serialization to -+- * the (@vol_id, @lnum) logical eraseblock -+- * -+- * When a logical eraseblock is being locked - corresponding &struct ltree_entry -+- * object is inserted to the lock tree (@ubi->ltree). -+- */ -+-struct ltree_entry { -+- struct rb_node rb; -+- int vol_id; -+- int lnum; -+- int users; -+- struct rw_semaphore mutex; -+-}; -+- -+-/* Slab cache for lock-tree entries */ -+-static struct kmem_cache *ltree_slab; -+- -+-/** -+ * next_sqnum - get next sequence number. -+ * @ubi: UBI device description object -+ * -+@@ -101,7 +78,7 @@ -+ */ -+ static int ubi_get_compat(const struct ubi_device *ubi, int vol_id) -+ { -+- if (vol_id == UBI_LAYOUT_VOL_ID) -++ if (vol_id == UBI_LAYOUT_VOLUME_ID) -+ return UBI_LAYOUT_VOLUME_COMPAT; -+ return 0; -+ } -+@@ -112,20 +89,20 @@ -+ * @vol_id: volume ID -+ * @lnum: logical eraseblock number -+ * -+- * This function returns a pointer to the corresponding &struct ltree_entry -++ * This function returns a pointer to the corresponding &struct ubi_ltree_entry -+ * object if the logical eraseblock is locked and %NULL if it is not. -+ * @ubi->ltree_lock has to be locked. -+ */ -+-static struct ltree_entry *ltree_lookup(struct ubi_device *ubi, int vol_id, -+- int lnum) -++static struct ubi_ltree_entry *ltree_lookup(struct ubi_device *ubi, int vol_id, -++ int lnum) -+ { -+ struct rb_node *p; -+ -+ p = ubi->ltree.rb_node; -+ while (p) { -+- struct ltree_entry *le; -++ struct ubi_ltree_entry *le; -+ -+- le = rb_entry(p, struct ltree_entry, rb); -++ le = rb_entry(p, struct ubi_ltree_entry, rb); -+ -+ if (vol_id < le->vol_id) -+ p = p->rb_left; -+@@ -155,15 +132,17 @@ -+ * Returns pointer to the lock tree entry or %-ENOMEM if memory allocation -+ * failed. -+ */ -+-static struct ltree_entry *ltree_add_entry(struct ubi_device *ubi, int vol_id, -+- int lnum) -++static struct ubi_ltree_entry *ltree_add_entry(struct ubi_device *ubi, -++ int vol_id, int lnum) -+ { -+- struct ltree_entry *le, *le1, *le_free; -++ struct ubi_ltree_entry *le, *le1, *le_free; -+ -+- le = kmem_cache_alloc(ltree_slab, GFP_NOFS); -++ le = kmalloc(sizeof(struct ubi_ltree_entry), GFP_NOFS); -+ if (!le) -+ return ERR_PTR(-ENOMEM); -+ -++ le->users = 0; -++ init_rwsem(&le->mutex); -+ le->vol_id = vol_id; -+ le->lnum = lnum; -+ -+@@ -189,7 +168,7 @@ -+ p = &ubi->ltree.rb_node; -+ while (*p) { -+ parent = *p; -+- le1 = rb_entry(parent, struct ltree_entry, rb); -++ le1 = rb_entry(parent, struct ubi_ltree_entry, rb); -+ -+ if (vol_id < le1->vol_id) -+ p = &(*p)->rb_left; -+@@ -211,7 +190,7 @@ -+ spin_unlock(&ubi->ltree_lock); -+ -+ if (le_free) -+- kmem_cache_free(ltree_slab, le_free); -++ kfree(le_free); -+ -+ return le; -+ } -+@@ -227,7 +206,7 @@ -+ */ -+ static int leb_read_lock(struct ubi_device *ubi, int vol_id, int lnum) -+ { -+- struct ltree_entry *le; -++ struct ubi_ltree_entry *le; -+ -+ le = ltree_add_entry(ubi, vol_id, lnum); -+ if (IS_ERR(le)) -+@@ -245,7 +224,7 @@ -+ static void leb_read_unlock(struct ubi_device *ubi, int vol_id, int lnum) -+ { -+ int free = 0; -+- struct ltree_entry *le; -++ struct ubi_ltree_entry *le; -+ -+ spin_lock(&ubi->ltree_lock); -+ le = ltree_lookup(ubi, vol_id, lnum); -+@@ -259,7 +238,7 @@ -+ -+ up_read(&le->mutex); -+ if (free) -+- kmem_cache_free(ltree_slab, le); -++ kfree(le); -+ } -+ -+ /** -+@@ -273,7 +252,7 @@ -+ */ -+ static int leb_write_lock(struct ubi_device *ubi, int vol_id, int lnum) -+ { -+- struct ltree_entry *le; -++ struct ubi_ltree_entry *le; -+ -+ le = ltree_add_entry(ubi, vol_id, lnum); -+ if (IS_ERR(le)) -+@@ -283,6 +262,44 @@ -+ } -+ -+ /** -++ * leb_write_lock - lock logical eraseblock for writing. -++ * @ubi: UBI device description object -++ * @vol_id: volume ID -++ * @lnum: logical eraseblock number -++ * -++ * This function locks a logical eraseblock for writing if there is no -++ * contention and does nothing if there is contention. Returns %0 in case of -++ * success, %1 in case of contention, and and a negative error code in case of -++ * failure. -++ */ -++static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) -++{ -++ int free; -++ struct ubi_ltree_entry *le; -++ -++ le = ltree_add_entry(ubi, vol_id, lnum); -++ if (IS_ERR(le)) -++ return PTR_ERR(le); -++ if (down_write_trylock(&le->mutex)) -++ return 0; -++ -++ /* Contention, cancel */ -++ spin_lock(&ubi->ltree_lock); -++ le->users -= 1; -++ ubi_assert(le->users >= 0); -++ if (le->users == 0) { -++ rb_erase(&le->rb, &ubi->ltree); -++ free = 1; -++ } else -++ free = 0; -++ spin_unlock(&ubi->ltree_lock); -++ if (free) -++ kfree(le); -++ -++ return 1; -++} -++ -++/** -+ * leb_write_unlock - unlock logical eraseblock. -+ * @ubi: UBI device description object -+ * @vol_id: volume ID -+@@ -291,7 +308,7 @@ -+ static void leb_write_unlock(struct ubi_device *ubi, int vol_id, int lnum) -+ { -+ int free; -+- struct ltree_entry *le; -++ struct ubi_ltree_entry *le; -+ -+ spin_lock(&ubi->ltree_lock); -+ le = ltree_lookup(ubi, vol_id, lnum); -+@@ -306,23 +323,23 @@ -+ -+ up_write(&le->mutex); -+ if (free) -+- kmem_cache_free(ltree_slab, le); -++ kfree(le); -+ } -+ -+ /** -+ * ubi_eba_unmap_leb - un-map logical eraseblock. -+ * @ubi: UBI device description object -+- * @vol_id: volume ID -++ * @vol: volume description object -+ * @lnum: logical eraseblock number -+ * -+ * This function un-maps logical eraseblock @lnum and schedules corresponding -+ * physical eraseblock for erasure. Returns zero in case of success and a -+ * negative error code in case of failure. -+ */ -+-int ubi_eba_unmap_leb(struct ubi_device *ubi, int vol_id, int lnum) -++int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol, -++ int lnum) -+ { -+- int idx = vol_id2idx(ubi, vol_id), err, pnum; -+- struct ubi_volume *vol = ubi->volumes[idx]; -++ int err, pnum, vol_id = vol->vol_id; -+ -+ if (ubi->ro_mode) -+ return -EROFS; -+@@ -349,7 +366,7 @@ -+ /** -+ * ubi_eba_read_leb - read data. -+ * @ubi: UBI device description object -+- * @vol_id: volume ID -++ * @vol: volume description object -+ * @lnum: logical eraseblock number -+ * @buf: buffer to store the read data -+ * @offset: offset from where to read -+@@ -365,12 +382,11 @@ -+ * returned for any volume type if an ECC error was detected by the MTD device -+ * driver. Other negative error cored may be returned in case of other errors. -+ */ -+-int ubi_eba_read_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf, -+- int offset, int len, int check) -++int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, -++ void *buf, int offset, int len, int check) -+ { -+- int err, pnum, scrub = 0, idx = vol_id2idx(ubi, vol_id); -++ int err, pnum, scrub = 0, vol_id = vol->vol_id; -+ struct ubi_vid_hdr *vid_hdr; -+- struct ubi_volume *vol = ubi->volumes[idx]; -+ uint32_t uninitialized_var(crc); -+ -+ err = leb_read_lock(ubi, vol_id, lnum); -+@@ -578,7 +594,7 @@ -+ /** -+ * ubi_eba_write_leb - write data to dynamic volume. -+ * @ubi: UBI device description object -+- * @vol_id: volume ID -++ * @vol: volume description object -+ * @lnum: logical eraseblock number -+ * @buf: the data to write -+ * @offset: offset within the logical eraseblock where to write -+@@ -586,15 +602,14 @@ -+ * @dtype: data type -+ * -+ * This function writes data to logical eraseblock @lnum of a dynamic volume -+- * @vol_id. Returns zero in case of success and a negative error code in case -++ * @vol. Returns zero in case of success and a negative error code in case -+ * of failure. In case of error, it is possible that something was still -+ * written to the flash media, but may be some garbage. -+ */ -+-int ubi_eba_write_leb(struct ubi_device *ubi, int vol_id, int lnum, -++int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, -+ const void *buf, int offset, int len, int dtype) -+ { -+- int idx = vol_id2idx(ubi, vol_id), err, pnum, tries = 0; -+- struct ubi_volume *vol = ubi->volumes[idx]; -++ int err, pnum, tries = 0, vol_id = vol->vol_id; -+ struct ubi_vid_hdr *vid_hdr; -+ -+ if (ubi->ro_mode) -+@@ -613,7 +628,8 @@ -+ if (err) { -+ ubi_warn("failed to write data to PEB %d", pnum); -+ if (err == -EIO && ubi->bad_allowed) -+- err = recover_peb(ubi, pnum, vol_id, lnum, buf, offset, len); -++ err = recover_peb(ubi, pnum, vol_id, lnum, buf, -++ offset, len); -+ if (err) -+ ubi_ro_mode(ubi); -+ } -+@@ -656,11 +672,14 @@ -+ goto write_error; -+ } -+ -+- err = ubi_io_write_data(ubi, buf, pnum, offset, len); -+- if (err) { -+- ubi_warn("failed to write %d bytes at offset %d of LEB %d:%d, " -+- "PEB %d", len, offset, vol_id, lnum, pnum); -+- goto write_error; -++ if (len) { -++ err = ubi_io_write_data(ubi, buf, pnum, offset, len); -++ if (err) { -++ ubi_warn("failed to write %d bytes at offset %d of " -++ "LEB %d:%d, PEB %d", len, offset, vol_id, -++ lnum, pnum); -++ goto write_error; -++ } -+ } -+ -+ vol->eba_tbl[lnum] = pnum; -+@@ -698,7 +717,7 @@ -+ /** -+ * ubi_eba_write_leb_st - write data to static volume. -+ * @ubi: UBI device description object -+- * @vol_id: volume ID -++ * @vol: volume description object -+ * @lnum: logical eraseblock number -+ * @buf: data to write -+ * @len: how many bytes to write -+@@ -706,7 +725,7 @@ -+ * @used_ebs: how many logical eraseblocks will this volume contain -+ * -+ * This function writes data to logical eraseblock @lnum of static volume -+- * @vol_id. The @used_ebs argument should contain total number of logical -++ * @vol. The @used_ebs argument should contain total number of logical -+ * eraseblock in this static volume. -+ * -+ * When writing to the last logical eraseblock, the @len argument doesn't have -+@@ -718,12 +737,11 @@ -+ * volumes. This function returns zero in case of success and a negative error -+ * code in case of failure. -+ */ -+-int ubi_eba_write_leb_st(struct ubi_device *ubi, int vol_id, int lnum, -+- const void *buf, int len, int dtype, int used_ebs) -++int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, -++ int lnum, const void *buf, int len, int dtype, -++ int used_ebs) -+ { -+- int err, pnum, tries = 0, data_size = len; -+- int idx = vol_id2idx(ubi, vol_id); -+- struct ubi_volume *vol = ubi->volumes[idx]; -++ int err, pnum, tries = 0, data_size = len, vol_id = vol->vol_id; -+ struct ubi_vid_hdr *vid_hdr; -+ uint32_t crc; -+ -+@@ -819,7 +837,7 @@ -+ /* -+ * ubi_eba_atomic_leb_change - change logical eraseblock atomically. -+ * @ubi: UBI device description object -+- * @vol_id: volume ID -++ * @vol: volume description object -+ * @lnum: logical eraseblock number -+ * @buf: data to write -+ * @len: how many bytes to write -+@@ -834,17 +852,27 @@ -+ * UBI reserves one LEB for the "atomic LEB change" operation, so only one -+ * LEB change may be done at a time. This is ensured by @ubi->alc_mutex. -+ */ -+-int ubi_eba_atomic_leb_change(struct ubi_device *ubi, int vol_id, int lnum, -+- const void *buf, int len, int dtype) -++int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, -++ int lnum, const void *buf, int len, int dtype) -+ { -+- int err, pnum, tries = 0, idx = vol_id2idx(ubi, vol_id); -+- struct ubi_volume *vol = ubi->volumes[idx]; -++ int err, pnum, tries = 0, vol_id = vol->vol_id; -+ struct ubi_vid_hdr *vid_hdr; -+ uint32_t crc; -+ -+ if (ubi->ro_mode) -+ return -EROFS; -+ -++ if (len == 0) { -++ /* -++ * Special case when data length is zero. In this case the LEB -++ * has to be unmapped and mapped somewhere else. -++ */ -++ err = ubi_eba_unmap_leb(ubi, vol, lnum); -++ if (err) -++ return err; -++ return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0, dtype); -++ } -++ -+ vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); -+ if (!vid_hdr) -+ return -ENOMEM; -+@@ -928,20 +956,6 @@ -+ } -+ -+ /** -+- * ltree_entry_ctor - lock tree entries slab cache constructor. -+- * @obj: the lock-tree entry to construct -+- * @cache: the lock tree entry slab cache -+- * @flags: constructor flags -+- */ -+-static void ltree_entry_ctor(struct kmem_cache *cache, void *obj) -+-{ -+- struct ltree_entry *le = obj; -+- -+- le->users = 0; -+- init_rwsem(&le->mutex); -+-} -+- -+-/** -+ * ubi_eba_copy_leb - copy logical eraseblock. -+ * @ubi: UBI device description object -+ * @from: physical eraseblock number from where to copy -+@@ -950,14 +964,16 @@ -+ * -+ * This function copies logical eraseblock from physical eraseblock @from to -+ * physical eraseblock @to. The @vid_hdr buffer may be changed by this -+- * function. Returns zero in case of success, %UBI_IO_BITFLIPS if the operation -+- * was canceled because bit-flips were detected at the target PEB, and a -+- * negative error code in case of failure. -++ * function. Returns: -++ * o %0 in case of success; -++ * o %1 if the operation was canceled and should be tried later (e.g., -++ * because a bit-flip was detected at the target PEB); -++ * o %2 if the volume is being deleted and this LEB should not be moved. -+ */ -+ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, -+ struct ubi_vid_hdr *vid_hdr) -+ { -+- int err, vol_id, lnum, data_size, aldata_size, pnum, idx; -++ int err, vol_id, lnum, data_size, aldata_size, idx; -+ struct ubi_volume *vol; -+ uint32_t crc; -+ -+@@ -973,51 +989,67 @@ -+ data_size = aldata_size = -+ ubi->leb_size - be32_to_cpu(vid_hdr->data_pad); -+ -+- /* -+- * We do not want anybody to write to this logical eraseblock while we -+- * are moving it, so we lock it. -+- */ -+- err = leb_write_lock(ubi, vol_id, lnum); -+- if (err) -+- return err; -+- -+- mutex_lock(&ubi->buf_mutex); -+- -+- /* -+- * But the logical eraseblock might have been put by this time. -+- * Cancel if it is true. -+- */ -+ idx = vol_id2idx(ubi, vol_id); -+- -++ spin_lock(&ubi->volumes_lock); -+ /* -+- * We may race with volume deletion/re-size, so we have to hold -+- * @ubi->volumes_lock. -++ * Note, we may race with volume deletion, which means that the volume -++ * this logical eraseblock belongs to might be being deleted. Since the -++ * volume deletion unmaps all the volume's logical eraseblocks, it will -++ * be locked in 'ubi_wl_put_peb()' and wait for the WL worker to finish. -+ */ -+- spin_lock(&ubi->volumes_lock); -+ vol = ubi->volumes[idx]; -+ if (!vol) { -+- dbg_eba("volume %d was removed meanwhile", vol_id); -++ /* No need to do further work, cancel */ -++ dbg_eba("volume %d is being removed, cancel", vol_id); -+ spin_unlock(&ubi->volumes_lock); -+- goto out_unlock; -++ return 2; -+ } -++ spin_unlock(&ubi->volumes_lock); -+ -+- pnum = vol->eba_tbl[lnum]; -+- if (pnum != from) { -+- dbg_eba("LEB %d:%d is no longer mapped to PEB %d, mapped to " -+- "PEB %d, cancel", vol_id, lnum, from, pnum); -+- spin_unlock(&ubi->volumes_lock); -+- goto out_unlock; -++ /* -++ * We do not want anybody to write to this logical eraseblock while we -++ * are moving it, so lock it. -++ * -++ * Note, we are using non-waiting locking here, because we cannot sleep -++ * on the LEB, since it may cause deadlocks. Indeed, imagine a task is -++ * unmapping the LEB which is mapped to the PEB we are going to move -++ * (@from). This task locks the LEB and goes sleep in the -++ * 'ubi_wl_put_peb()' function on the @ubi->move_mutex. In turn, we are -++ * holding @ubi->move_mutex and go sleep on the LEB lock. So, if the -++ * LEB is already locked, we just do not move it and return %1. -++ */ -++ err = leb_write_trylock(ubi, vol_id, lnum); -++ if (err) { -++ dbg_eba("contention on LEB %d:%d, cancel", vol_id, lnum); -++ return err; -+ } -+- spin_unlock(&ubi->volumes_lock); -+ -+- /* OK, now the LEB is locked and we can safely start moving it */ -++ /* -++ * The LEB might have been put meanwhile, and the task which put it is -++ * probably waiting on @ubi->move_mutex. No need to continue the work, -++ * cancel it. -++ */ -++ if (vol->eba_tbl[lnum] != from) { -++ dbg_eba("LEB %d:%d is no longer mapped to PEB %d, mapped to " -++ "PEB %d, cancel", vol_id, lnum, from, -++ vol->eba_tbl[lnum]); -++ err = 1; -++ goto out_unlock_leb; -++ } -+ -++ /* -++ * OK, now the LEB is locked and we can safely start moving iy. Since -++ * this function utilizes thie @ubi->peb1_buf buffer which is shared -++ * with some other functions, so lock the buffer by taking the -++ * @ubi->buf_mutex. -++ */ -++ mutex_lock(&ubi->buf_mutex); -+ dbg_eba("read %d bytes of data", aldata_size); -+ err = ubi_io_read_data(ubi, ubi->peb_buf1, from, 0, aldata_size); -+ if (err && err != UBI_IO_BITFLIPS) { -+ ubi_warn("error %d while reading data from PEB %d", -+ err, from); -+- goto out_unlock; -++ goto out_unlock_buf; -+ } -+ -+ /* -+@@ -1053,7 +1085,7 @@ -+ -+ err = ubi_io_write_vid_hdr(ubi, to, vid_hdr); -+ if (err) -+- goto out_unlock; -++ goto out_unlock_buf; -+ -+ cond_resched(); -+ -+@@ -1062,13 +1094,15 @@ -+ if (err) { -+ if (err != UBI_IO_BITFLIPS) -+ ubi_warn("cannot read VID header back from PEB %d", to); -+- goto out_unlock; -++ else -++ err = 1; -++ goto out_unlock_buf; -+ } -+ -+ if (data_size > 0) { -+ err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size); -+ if (err) -+- goto out_unlock; -++ goto out_unlock_buf; -+ -+ cond_resched(); -+ -+@@ -1082,7 +1116,9 @@ -+ if (err != UBI_IO_BITFLIPS) -+ ubi_warn("cannot read data back from PEB %d", -+ to); -+- goto out_unlock; -++ else -++ err = 1; -++ goto out_unlock_buf; -+ } -+ -+ cond_resched(); -+@@ -1090,15 +1126,16 @@ -+ if (memcmp(ubi->peb_buf1, ubi->peb_buf2, aldata_size)) { -+ ubi_warn("read data back from PEB %d - it is different", -+ to); -+- goto out_unlock; -++ goto out_unlock_buf; -+ } -+ } -+ -+ ubi_assert(vol->eba_tbl[lnum] == from); -+ vol->eba_tbl[lnum] = to; -+ -+-out_unlock: -++out_unlock_buf: -+ mutex_unlock(&ubi->buf_mutex); -++out_unlock_leb: -+ leb_write_unlock(ubi, vol_id, lnum); -+ return err; -+ } -+@@ -1125,14 +1162,6 @@ -+ mutex_init(&ubi->alc_mutex); -+ ubi->ltree = RB_ROOT; -+ -+- if (ubi_devices_cnt == 0) { -+- ltree_slab = kmem_cache_create("ubi_ltree_slab", -+- sizeof(struct ltree_entry), 0, -+- 0, <ree_entry_ctor); -+- if (!ltree_slab) -+- return -ENOMEM; -+- } -+- -+ ubi->global_sqnum = si->max_sqnum + 1; -+ num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT; -+ -+@@ -1168,6 +1197,15 @@ -+ } -+ } -+ -++ if (ubi->avail_pebs < EBA_RESERVED_PEBS) { -++ ubi_err("no enough physical eraseblocks (%d, need %d)", -++ ubi->avail_pebs, EBA_RESERVED_PEBS); -++ err = -ENOSPC; -++ goto out_free; -++ } -++ ubi->avail_pebs -= EBA_RESERVED_PEBS; -++ ubi->rsvd_pebs += EBA_RESERVED_PEBS; -++ -+ if (ubi->bad_allowed) { -+ ubi_calculate_reserved(ubi); -+ -+@@ -1184,15 +1222,6 @@ -+ ubi->rsvd_pebs += ubi->beb_rsvd_pebs; -+ } -+ -+- if (ubi->avail_pebs < EBA_RESERVED_PEBS) { -+- ubi_err("no enough physical eraseblocks (%d, need %d)", -+- ubi->avail_pebs, EBA_RESERVED_PEBS); -+- err = -ENOSPC; -+- goto out_free; -+- } -+- ubi->avail_pebs -= EBA_RESERVED_PEBS; -+- ubi->rsvd_pebs += EBA_RESERVED_PEBS; -+- -+ dbg_eba("EBA unit is initialized"); -+ return 0; -+ -+@@ -1202,8 +1231,6 @@ -+ continue; -+ kfree(ubi->volumes[i]->eba_tbl); -+ } -+- if (ubi_devices_cnt == 0) -+- kmem_cache_destroy(ltree_slab); -+ return err; -+ } -+ -+@@ -1222,6 +1249,141 @@ -+ continue; -+ kfree(ubi->volumes[i]->eba_tbl); -+ } -+- if (ubi_devices_cnt == 1) -+- kmem_cache_destroy(ltree_slab); -+ } -++ -++/* add by Nancy begin */ -++ -++static int ubiblk_fill_writecache(struct ubiblk_dev *ubiblk) -++{ -++ struct ubi_volume_desc *uv = ubiblk->uv; -++ struct ubi_device *ubi = uv->vol->ubi; -++ int ppb = ubi->leb_size / ubi->min_io_size; -++ unsigned short subpage_shift = 9; -++ unsigned short spp = ubi->min_io_size >> subpage_shift; -++ unsigned short page_shift = ffs(ubi->min_io_size) - 1; -++ unsigned short sectors_in_page_shift = ffs(ubi->min_io_size / 512) - 1; -++ unsigned short page, sector; -++ char page_buf[ubi->min_io_size]; -++ -++ if (!page_buf) -++ return -ENOMEM; -++ -++ for (page = 0; page < ppb; page++) { -++ if ( !ubiblk->page_sts[page]) { -++ ubi_leb_read(uv, ubiblk->vbw, -++ &ubiblk->write_cache[page<min_io_size, 0); -++ }else{ -++ for(sector = 0; sector < spp; sector++) -++ if( !ubiblk->subpage_sts[(page<vbw, -++ page_buf, -++ page<min_io_size, 0); -++ for(sector = 0; sector < spp; sector++) -++ if(!ubiblk->subpage_sts[(page<write_cache[ \ -++ (page<vol_id; -++ struct ubi_vid_hdr *vid_hdr; -++ uint32_t crc; -++ -++ if (ubi->ro_mode) -++ return -EROFS; -++ -++ vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); -++ if (!vid_hdr) -++ return -ENOMEM; -++ -++ ubiblk_fill_writecache(ubiblk); -++ mutex_lock(&ubi->alc_mutex); -++ err = leb_write_lock(ubi, vol_id, lnum); -++ if (err) -++ goto out_mutex; -++ -++ vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi)); -++ vid_hdr->vol_id = cpu_to_be32(vol_id); -++ vid_hdr->lnum = cpu_to_be32(lnum); -++ vid_hdr->compat = ubi_get_compat(ubi, vol_id); -++ vid_hdr->data_pad = cpu_to_be32(vol->data_pad); -++ -++ crc = crc32(UBI_CRC32_INIT, buf, len); -++ vid_hdr->vol_type = UBI_VID_DYNAMIC; -++ vid_hdr->data_size = cpu_to_be32(len); -++ vid_hdr->copy_flag = 1; -++ vid_hdr->data_crc = cpu_to_be32(crc); -++ -++retry: -++ pnum = ubi_wl_get_peb(ubi, dtype); -++ if (pnum < 0) { -++ err = pnum; -++ goto out_leb_unlock; -++ } -++ -++ dbg_eba("change LEB %d:%d, PEB %d, write VID hdr to PEB %d", -++ vol_id, lnum, vol->eba_tbl[lnum], pnum); -++ -++ err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr); -++ if (err) { -++ ubi_warn("failed to write VID header to LEB %d:%d, PEB %d", -++ vol_id, lnum, pnum); -++ goto write_error; -++ } -++ -++ err = ubi_io_write_data(ubi, buf, pnum, 0, len); -++ if (err) { -++ ubi_warn("failed to write %d bytes of data to PEB %d", -++ len, pnum); -++ goto write_error; -++ } -++ if (vol->eba_tbl[lnum] >= 0) { -++ err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 0); -++ if (err) -++ goto out_leb_unlock; -++ } -++ -++ vol->eba_tbl[lnum] = pnum; -++ -++out_leb_unlock: -++ leb_write_unlock(ubi, vol_id, lnum); -++out_mutex: -++ mutex_unlock(&ubi->alc_mutex); -++ ubi_free_vid_hdr(ubi, vid_hdr); -++ return err; -++ -++write_error: -++ if (err != -EIO || !ubi->bad_allowed) { -++ /* -++ * This flash device does not admit of bad eraseblocks or -++ * something nasty and unexpected happened. Switch to read-only -++ * mode just in case. -++ */ -++ ubi_ro_mode(ubi); -++ goto out_leb_unlock; -++ } -++ -++ err = ubi_wl_put_peb(ubi, pnum, 1); -++ if (err || ++tries > UBI_IO_RETRIES) { -++ ubi_ro_mode(ubi); -++ goto out_leb_unlock; -++ } -++ -++ vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi)); -++ ubi_msg("try another PEB"); -++ goto retry; -++} -++ -++/* add by Nancy end*/ -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/gluebi.c linux-2.6.24.7/drivers/mtd/ubi/gluebi.c -+--- linux-2.6.24.7.old/drivers/mtd/ubi/gluebi.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/gluebi.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -103,15 +103,15 @@ -+ * This function returns zero in case of success and a negative error code in -+ * case of failure. -+ */ -+-static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len, -+- size_t *retlen, unsigned char *buf) -++static int gluebi_read(struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, -++ size_mtd_t *retlen, unsigned char *buf) -+ { -+ int err = 0, lnum, offs, total_read; -+ struct ubi_volume *vol; -+ struct ubi_device *ubi; -+ uint64_t tmp = from; -+ -+- dbg_msg("read %zd bytes from offset %lld", len, from); -++ dbg_msg("read %lld bytes from offset %lld", len, from); -+ -+ if (len < 0 || from < 0 || from + len > mtd->size) -+ return -EINVAL; -+@@ -129,8 +129,7 @@ -+ if (to_read > total_read) -+ to_read = total_read; -+ -+- err = ubi_eba_read_leb(ubi, vol->vol_id, lnum, buf, offs, -+- to_read, 0); -++ err = ubi_eba_read_leb(ubi, vol, lnum, buf, offs, to_read, 0); -+ if (err) -+ break; -+ -+@@ -155,15 +154,15 @@ -+ * This function returns zero in case of success and a negative error code in -+ * case of failure. -+ */ -+-static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len, -+- size_t *retlen, const u_char *buf) -++static int gluebi_write(struct mtd_info *mtd, loff_mtd_t to, size_mtd_t len, -++ size_mtd_t *retlen, const u_char *buf) -+ { -+ int err = 0, lnum, offs, total_written; -+ struct ubi_volume *vol; -+ struct ubi_device *ubi; -+ uint64_t tmp = to; -+ -+- dbg_msg("write %zd bytes to offset %lld", len, to); -++ dbg_msg("write %lld bytes to offset %lld", len, to); -+ -+ if (len < 0 || to < 0 || len + to > mtd->size) -+ return -EINVAL; -+@@ -177,7 +176,7 @@ -+ offs = do_div(tmp, mtd->erasesize); -+ lnum = tmp; -+ -+- if (len % mtd->writesize || offs % mtd->writesize) -++ if ((u32)len % mtd->writesize || offs % mtd->writesize) -+ return -EINVAL; -+ -+ total_written = len; -+@@ -187,8 +186,8 @@ -+ if (to_write > total_written) -+ to_write = total_written; -+ -+- err = ubi_eba_write_leb(ubi, vol->vol_id, lnum, buf, offs, -+- to_write, UBI_UNKNOWN); -++ err = ubi_eba_write_leb(ubi, vol, lnum, buf, offs, to_write, -++ UBI_UNKNOWN); -+ if (err) -+ break; -+ -+@@ -216,7 +215,7 @@ -+ struct ubi_volume *vol; -+ struct ubi_device *ubi; -+ -+- dbg_msg("erase %u bytes at offset %u", instr->len, instr->addr); -++ dbg_msg("erase %llu bytes at offset %llu", instr->len, instr->addr); -+ -+ if (instr->addr < 0 || instr->addr > mtd->size - mtd->erasesize) -+ return -EINVAL; -+@@ -224,11 +223,11 @@ -+ if (instr->len < 0 || instr->addr + instr->len > mtd->size) -+ return -EINVAL; -+ -+- if (instr->addr % mtd->writesize || instr->len % mtd->writesize) -++ if ((u32)instr->addr % mtd->writesize || (u32)instr->len % mtd->writesize) -+ return -EINVAL; -+ -+- lnum = instr->addr / mtd->erasesize; -+- count = instr->len / mtd->erasesize; -++ lnum = instr->addr >> (ffs(mtd->erasesize)-1); -++ count = instr->len >> (ffs(mtd->erasesize)-1); -+ -+ vol = container_of(mtd, struct ubi_volume, gluebi_mtd); -+ ubi = vol->ubi; -+@@ -237,7 +236,7 @@ -+ return -EROFS; -+ -+ for (i = 0; i < count; i++) { -+- err = ubi_eba_unmap_leb(ubi, vol->vol_id, lnum + i); -++ err = ubi_eba_unmap_leb(ubi, vol, lnum + i); -+ if (err) -+ goto out_err; -+ } -+@@ -292,11 +291,12 @@ -+ /* -+ * In case of dynamic volume, MTD device size is just volume size. In -+ * case of a static volume the size is equivalent to the amount of data -+- * bytes, which is zero at this moment and will be changed after volume -+- * update. -++ * bytes. -+ */ -+ if (vol->vol_type == UBI_DYNAMIC_VOLUME) -+ mtd->size = vol->usable_leb_size * vol->reserved_pebs; -++ else -++ mtd->size = vol->used_bytes; -+ -+ if (add_mtd_device(mtd)) { -+ ubi_err("cannot not add MTD device\n"); -+@@ -304,7 +304,7 @@ -+ return -ENFILE; -+ } -+ -+- dbg_msg("added mtd%d (\"%s\"), size %u, EB size %u", -++ dbg_msg("added mtd%d (\"%s\"), size %llu, EB size %u", -+ mtd->index, mtd->name, mtd->size, mtd->erasesize); -+ return 0; -+ } -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/io.c linux-2.6.24.7/drivers/mtd/ubi/io.c -+--- linux-2.6.24.7.old/drivers/mtd/ubi/io.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/io.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -135,8 +135,8 @@ -+ int len) -+ { -+ int err, retries = 0; -+- size_t read; -+- loff_t addr; -++ size_mtd_t read; -++ loff_mtd_t addr; -+ -+ dbg_io("read %d bytes from PEB %d:%d", len, pnum, offset); -+ -+@@ -148,7 +148,7 @@ -+ if (err) -+ return err > 0 ? -EINVAL : err; -+ -+- addr = (loff_t)pnum * ubi->peb_size + offset; -++ addr = (loff_mtd_t)pnum * ubi->peb_size + offset; -+ retry: -+ err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf); -+ if (err) { -+@@ -164,15 +164,25 @@ -+ -+ if (read != len && retries++ < UBI_IO_RETRIES) { -+ dbg_io("error %d while reading %d bytes from PEB %d:%d, " -+- "read only %zd bytes, retry", -++ "read only %lld bytes, retry", -+ err, len, pnum, offset, read); -+ yield(); -+ goto retry; -+ } -+ -+ ubi_err("error %d while reading %d bytes from PEB %d:%d, " -+- "read %zd bytes", err, len, pnum, offset, read); -++ "read %lld bytes", err, len, pnum, offset, read); -+ ubi_dbg_dump_stack(); -++ -++ /* -++ * The driver should never return -EBADMSG if it failed to read -++ * all the requested data. But some buggy drivers might do -++ * this, so we change it to -EIO. -++ */ -++ if (read != len && err == -EBADMSG) { -++ ubi_assert(0); -++ err = -EIO; -++ } -+ } else { -+ ubi_assert(len == read); -+ -+@@ -206,8 +216,8 @@ -+ int len) -+ { -+ int err; -+- size_t written; -+- loff_t addr; -++ size_mtd_t written; -++ loff_mtd_t addr; -+ -+ dbg_io("write %d bytes to PEB %d:%d", len, pnum, offset); -+ -+@@ -252,11 +262,11 @@ -+ return -EIO; -+ } -+ -+- addr = (loff_t)pnum * ubi->peb_size + offset; -++ addr = (loff_mtd_t)pnum * ubi->peb_size + offset; -+ err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf); -+ if (err) { -+ ubi_err("error %d while writing %d bytes to PEB %d:%d, written" -+- " %zd bytes", err, len, pnum, offset, written); -++ " %lld bytes", err, len, pnum, offset, written); -+ ubi_dbg_dump_stack(); -+ } else -+ ubi_assert(written == len); -+@@ -298,7 +308,7 @@ -+ memset(&ei, 0, sizeof(struct erase_info)); -+ -+ ei.mtd = ubi->mtd; -+- ei.addr = (loff_t)pnum * ubi->peb_size; -++ ei.addr = (loff_mtd_t)pnum * ubi->peb_size; -+ ei.len = ubi->peb_size; -+ ei.callback = erase_callback; -+ ei.priv = (unsigned long)&wq; -+@@ -501,7 +511,7 @@ -+ if (ubi->bad_allowed) { -+ int ret; -+ -+- ret = mtd->block_isbad(mtd, (loff_t)pnum * ubi->peb_size); -++ ret = mtd->block_isbad(mtd, (loff_mtd_t)pnum * ubi->peb_size); -+ if (ret < 0) -+ ubi_err("error %d while checking if PEB %d is bad", -+ ret, pnum); -+@@ -536,7 +546,7 @@ -+ if (!ubi->bad_allowed) -+ return 0; -+ -+- err = mtd->block_markbad(mtd, (loff_t)pnum * ubi->peb_size); -++ err = mtd->block_markbad(mtd, (loff_mtd_t)pnum * ubi->peb_size); -+ if (err) -+ ubi_err("cannot mark PEB %d bad, error %d", pnum, err); -+ return err; -+@@ -621,6 +631,8 @@ -+ -+ dbg_io("read EC header from PEB %d", pnum); -+ ubi_assert(pnum >= 0 && pnum < ubi->peb_count); -++ if (UBI_IO_DEBUG) -++ verbose = 1; -+ -+ err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE); -+ if (err) { -+@@ -894,6 +906,8 @@ -+ -+ dbg_io("read VID header from PEB %d", pnum); -+ ubi_assert(pnum >= 0 && pnum < ubi->peb_count); -++ if (UBI_IO_DEBUG) -++ verbose = 1; -+ -+ p = (char *)vid_hdr - ubi->vid_hdr_shift; -+ err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, -+@@ -1218,15 +1232,15 @@ -+ static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, -+ int len) -+ { -+- size_t read; -++ size_mtd_t read; -+ int err; -+- loff_t addr = (loff_t)pnum * ubi->peb_size + offset; -++ loff_mtd_t addr = (loff_mtd_t)pnum * ubi->peb_size + offset; -+ -+ mutex_lock(&ubi->dbg_buf_mutex); -+ err = ubi->mtd->read(ubi->mtd, addr, len, &read, ubi->dbg_peb_buf); -+ if (err && err != -EUCLEAN) { -+ ubi_err("error %d while reading %d bytes from PEB %d:%d, " -+- "read %zd bytes", err, len, pnum, offset, read); -++ "read %lld bytes", err, len, pnum, offset, read); -+ goto error; -+ } -+ -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/kapi.c linux-2.6.24.7/drivers/mtd/ubi/kapi.c -+--- linux-2.6.24.7.old/drivers/mtd/ubi/kapi.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/kapi.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -24,29 +24,36 @@ -+ #include -+ #include -+ #include "ubi.h" -++#include "ubiblk.h" -+ -++extern int ubiblk_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, -++ int lnum, void *buf, int len, int dtype, struct ubiblk_dev *ubiblk); -+ /** -+ * ubi_get_device_info - get information about UBI device. -+ * @ubi_num: UBI device number -+ * @di: the information is stored here -+ * -+- * This function returns %0 in case of success and a %-ENODEV if there is no -+- * such UBI device. -++ * This function returns %0 in case of success, %-EINVAL if the UBI device -++ * number is invalid, and %-ENODEV if there is no such UBI device. -+ */ -+ int ubi_get_device_info(int ubi_num, struct ubi_device_info *di) -+ { -+- const struct ubi_device *ubi; -++ struct ubi_device *ubi; -++ -++ if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) -++ return -EINVAL; -+ -+- if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES || -+- !ubi_devices[ubi_num]) -++ ubi = ubi_get_device(ubi_num); -++ if (!ubi) -+ return -ENODEV; -+ -+- ubi = ubi_devices[ubi_num]; -+ di->ubi_num = ubi->ubi_num; -+ di->leb_size = ubi->leb_size; -+ di->min_io_size = ubi->min_io_size; -+ di->ro_mode = ubi->ro_mode; -+- di->cdev = MKDEV(ubi->major, 0); -++ di->cdev = ubi->cdev.dev; -++ -++ ubi_put_device(ubi); -+ return 0; -+ } -+ EXPORT_SYMBOL_GPL(ubi_get_device_info); -+@@ -73,7 +80,7 @@ -+ vi->usable_leb_size = vol->usable_leb_size; -+ vi->name_len = vol->name_len; -+ vi->name = vol->name; -+- vi->cdev = MKDEV(ubi->major, vi->vol_id + 1); -++ vi->cdev = vol->cdev.dev; -+ } -+ EXPORT_SYMBOL_GPL(ubi_get_volume_info); -+ -+@@ -104,37 +111,39 @@ -+ -+ dbg_msg("open device %d volume %d, mode %d", ubi_num, vol_id, mode); -+ -+- err = -ENODEV; -+- if (ubi_num < 0) -+- return ERR_PTR(err); -+- -+- ubi = ubi_devices[ubi_num]; -+- -+- if (!try_module_get(THIS_MODULE)) -+- return ERR_PTR(err); -+- -+- if (ubi_num >= UBI_MAX_DEVICES || !ubi) -+- goto out_put; -++ if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) -++ return ERR_PTR(-EINVAL); -+ -+- err = -EINVAL; -+- if (vol_id < 0 || vol_id >= ubi->vtbl_slots) -+- goto out_put; -+ if (mode != UBI_READONLY && mode != UBI_READWRITE && -+ mode != UBI_EXCLUSIVE) -+- goto out_put; -++ return ERR_PTR(-EINVAL); -++ -++ /* -++ * First of all, we have to get the UBI device to prevent its removal. -++ */ -++ ubi = ubi_get_device(ubi_num); -++ if (!ubi) -++ return ERR_PTR(-ENODEV); -++ -++ if (vol_id < 0 || vol_id >= ubi->vtbl_slots) { -++ err = -EINVAL; -++ goto out_put_ubi; -++ } -+ -+ desc = kmalloc(sizeof(struct ubi_volume_desc), GFP_KERNEL); -+ if (!desc) { -+ err = -ENOMEM; -+- goto out_put; -++ goto out_put_ubi; -+ } -+ -++ err = -ENODEV; -++ if (!try_module_get(THIS_MODULE)) -++ goto out_free; -++ -+ spin_lock(&ubi->volumes_lock); -+ vol = ubi->volumes[vol_id]; -+- if (!vol) { -+- err = -ENODEV; -++ if (!vol) -+ goto out_unlock; -+- } -+ -+ err = -EBUSY; -+ switch (mode) { -+@@ -156,21 +165,19 @@ -+ vol->exclusive = 1; -+ break; -+ } -++ get_device(&vol->dev); -++ vol->ref_count += 1; -+ spin_unlock(&ubi->volumes_lock); -+ -+ desc->vol = vol; -+ desc->mode = mode; -+ -+- /* -+- * To prevent simultaneous checks of the same volume we use @vtbl_mutex, -+- * although it is not the purpose it was introduced for. -+- */ -+- mutex_lock(&ubi->vtbl_mutex); -++ mutex_lock(&ubi->ckvol_mutex); -+ if (!vol->checked) { -+ /* This is the first open - check the volume */ -+ err = ubi_check_volume(ubi, vol_id); -+ if (err < 0) { -+- mutex_unlock(&ubi->vtbl_mutex); -++ mutex_unlock(&ubi->ckvol_mutex); -+ ubi_close_volume(desc); -+ return ERR_PTR(err); -+ } -+@@ -181,14 +188,17 @@ -+ } -+ vol->checked = 1; -+ } -+- mutex_unlock(&ubi->vtbl_mutex); -++ mutex_unlock(&ubi->ckvol_mutex); -++ -+ return desc; -+ -+ out_unlock: -+ spin_unlock(&ubi->volumes_lock); -+- kfree(desc); -+-out_put: -+ module_put(THIS_MODULE); -++out_free: -++ kfree(desc); -++out_put_ubi: -++ ubi_put_device(ubi); -+ return ERR_PTR(err); -+ } -+ EXPORT_SYMBOL_GPL(ubi_open_volume); -+@@ -205,8 +215,8 @@ -+ int mode) -+ { -+ int i, vol_id = -1, len; -+- struct ubi_volume_desc *ret; -+ struct ubi_device *ubi; -++ struct ubi_volume_desc *ret; -+ -+ dbg_msg("open volume %s, mode %d", name, mode); -+ -+@@ -217,14 +227,12 @@ -+ if (len > UBI_VOL_NAME_MAX) -+ return ERR_PTR(-EINVAL); -+ -+- ret = ERR_PTR(-ENODEV); -+- if (!try_module_get(THIS_MODULE)) -+- return ret; -+- -+- if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES || !ubi_devices[ubi_num]) -+- goto out_put; -++ if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) -++ return ERR_PTR(-EINVAL); -+ -+- ubi = ubi_devices[ubi_num]; -++ ubi = ubi_get_device(ubi_num); -++ if (!ubi) -++ return ERR_PTR(-ENODEV); -+ -+ spin_lock(&ubi->volumes_lock); -+ /* Walk all volumes of this UBI device */ -+@@ -238,13 +246,16 @@ -+ } -+ spin_unlock(&ubi->volumes_lock); -+ -+- if (vol_id < 0) -+- goto out_put; -+- -+- ret = ubi_open_volume(ubi_num, vol_id, mode); -++ if (vol_id >= 0) -++ ret = ubi_open_volume(ubi_num, vol_id, mode); -++ else -++ ret = ERR_PTR(-ENODEV); -+ -+-out_put: -+- module_put(THIS_MODULE); -++ /* -++ * We should put the UBI device even in case of success, because -++ * 'ubi_open_volume()' took a reference as well. -++ */ -++ ubi_put_device(ubi); -+ return ret; -+ } -+ EXPORT_SYMBOL_GPL(ubi_open_volume_nm); -+@@ -256,10 +267,11 @@ -+ void ubi_close_volume(struct ubi_volume_desc *desc) -+ { -+ struct ubi_volume *vol = desc->vol; -++ struct ubi_device *ubi = vol->ubi; -+ -+ dbg_msg("close volume %d, mode %d", vol->vol_id, desc->mode); -+ -+- spin_lock(&vol->ubi->volumes_lock); -++ spin_lock(&ubi->volumes_lock); -+ switch (desc->mode) { -+ case UBI_READONLY: -+ vol->readers -= 1; -+@@ -270,9 +282,12 @@ -+ case UBI_EXCLUSIVE: -+ vol->exclusive = 0; -+ } -+- spin_unlock(&vol->ubi->volumes_lock); -++ vol->ref_count -= 1; -++ spin_unlock(&ubi->volumes_lock); -+ -+ kfree(desc); -++ put_device(&vol->dev); -++ ubi_put_device(ubi); -+ module_put(THIS_MODULE); -+ } -+ EXPORT_SYMBOL_GPL(ubi_close_volume); -+@@ -332,7 +347,7 @@ -+ if (len == 0) -+ return 0; -+ -+- err = ubi_eba_read_leb(ubi, vol_id, lnum, buf, offset, len, check); -++ err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check); -+ if (err && err == -EBADMSG && vol->vol_type == UBI_STATIC_VOLUME) { -+ ubi_warn("mark volume %d as corrupted", vol_id); -+ vol->corrupted = 1; -+@@ -399,7 +414,7 @@ -+ if (len == 0) -+ return 0; -+ -+- return ubi_eba_write_leb(ubi, vol_id, lnum, buf, offset, len, dtype); -++ return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len, dtype); -+ } -+ EXPORT_SYMBOL_GPL(ubi_leb_write); -+ -+@@ -448,7 +463,7 @@ -+ if (len == 0) -+ return 0; -+ -+- return ubi_eba_atomic_leb_change(ubi, vol_id, lnum, buf, len, dtype); -++ return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len, dtype); -+ } -+ EXPORT_SYMBOL_GPL(ubi_leb_change); -+ -+@@ -468,9 +483,9 @@ -+ { -+ struct ubi_volume *vol = desc->vol; -+ struct ubi_device *ubi = vol->ubi; -+- int err, vol_id = vol->vol_id; -++ int err; -+ -+- dbg_msg("erase LEB %d:%d", vol_id, lnum); -++ dbg_msg("erase LEB %d:%d", vol->vol_id, lnum); -+ -+ if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) -+ return -EROFS; -+@@ -481,7 +496,7 @@ -+ if (vol->upd_marker) -+ return -EBADF; -+ -+- err = ubi_eba_unmap_leb(ubi, vol_id, lnum); -++ err = ubi_eba_unmap_leb(ubi, vol, lnum); -+ if (err) -+ return err; -+ -+@@ -529,9 +544,8 @@ -+ { -+ struct ubi_volume *vol = desc->vol; -+ struct ubi_device *ubi = vol->ubi; -+- int vol_id = vol->vol_id; -+ -+- dbg_msg("unmap LEB %d:%d", vol_id, lnum); -++ dbg_msg("unmap LEB %d:%d", vol->vol_id, lnum); -+ -+ if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) -+ return -EROFS; -+@@ -542,11 +556,55 @@ -+ if (vol->upd_marker) -+ return -EBADF; -+ -+- return ubi_eba_unmap_leb(ubi, vol_id, lnum); -++ return ubi_eba_unmap_leb(ubi, vol, lnum); -+ } -+ EXPORT_SYMBOL_GPL(ubi_leb_unmap); -+ -+ /** -++ * ubi_leb_map - map logical erasblock to a physical eraseblock. -++ * @desc: volume descriptor -++ * @lnum: logical eraseblock number -++ * @dtype: expected data type -++ * -++ * This function maps an un-mapped logical eraseblock @lnum to a physical -++ * eraseblock. This means, that after a successfull invocation of this -++ * function the logical eraseblock @lnum will be empty (contain only %0xFF -++ * bytes) and be mapped to a physical eraseblock, even if an unclean reboot -++ * happens. -++ * -++ * This function returns zero in case of success, %-EBADF if the volume is -++ * damaged because of an interrupted update, %-EBADMSG if the logical -++ * eraseblock is already mapped, and other negative error codes in case of -++ * other failures. -++ */ -++int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype) -++{ -++ struct ubi_volume *vol = desc->vol; -++ struct ubi_device *ubi = vol->ubi; -++ -++ dbg_msg("unmap LEB %d:%d", vol->vol_id, lnum); -++ -++ if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) -++ return -EROFS; -++ -++ if (lnum < 0 || lnum >= vol->reserved_pebs) -++ return -EINVAL; -++ -++ if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM && -++ dtype != UBI_UNKNOWN) -++ return -EINVAL; -++ -++ if (vol->upd_marker) -++ return -EBADF; -++ -++ if (vol->eba_tbl[lnum] >= 0) -++ return -EBADMSG; -++ -++ return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0, dtype); -++} -++EXPORT_SYMBOL_GPL(ubi_leb_map); -++ -++/** -+ * ubi_is_mapped - check if logical eraseblock is mapped. -+ * @desc: volume descriptor -+ * @lnum: logical eraseblock number -+@@ -577,3 +635,138 @@ -+ return vol->eba_tbl[lnum] >= 0; -+ } -+ EXPORT_SYMBOL_GPL(ubi_is_mapped); -++ -++/* add by Nancy start */ -++ -++int ubiblk_leb_change(struct ubiblk_dev *ubiblk) -++{ -++ struct ubi_volume *vol = ubiblk->uv->vol; -++ struct ubi_device *ubi = vol->ubi; -++ int vol_id = vol->vol_id; -++ -++ struct ubi_volume_desc *desc = ubiblk->uv; -++ int lnum = ubiblk->vbw; -++ int len = ubi->leb_size; -++ int dtype = UBI_UNKNOWN; -++ void *buf = ubiblk->write_cache; -++ -++ dbg_msg("atomically write %d bytes to LEB %d:%d", len, vol_id, lnum); -++ -++ if (vol_id < 0 || vol_id >= ubi->vtbl_slots) -++ return -EINVAL; -++ -++ if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) -++ return -EROFS; -++ -++ if (lnum < 0 || lnum >= vol->reserved_pebs || len < 0 || -++ len > vol->usable_leb_size || len % ubi->min_io_size) -++ return -EINVAL; -++ -++ if (vol->upd_marker) -++ return -EBADF; -++ -++ if (len == 0) -++ return 0; -++ -++ return ubiblk_eba_atomic_leb_change(ubi, vol, lnum, buf, len, dtype, ubiblk); -++} -++EXPORT_SYMBOL_GPL(ubiblk_leb_change); -++ -++ -++void ubi_open_blkdev(int ubi_num, int vol_id, int mode) -++{ -++ int err; -++ struct ubi_device *ubi; -++ struct ubi_volume *vol; -++ -++ dbg_msg("open device %d volume %d, mode %d", ubi_num, vol_id, mode); -++ -++ if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) -++ return; -++ -++ if (mode != UBI_READONLY && mode != UBI_READWRITE && -++ mode != UBI_EXCLUSIVE) -++ return; -++ /* -++ * First of all, we have to get the UBI device to prevent its removal. -++ */ -++ ubi = ubi_get_device(ubi_num); -++ if (!ubi) -++ return; -++ -++ if (vol_id < 0 || vol_id >= ubi->vtbl_slots) { -++ err = -EINVAL; -++ goto out_put_ubi; -++ } -++ -++ err = -ENODEV; -++ if (!try_module_get(THIS_MODULE)) -++ goto out_put_ubi; -++ -++ spin_lock(&ubi->volumes_lock); -++ vol = ubi->volumes[vol_id]; -++ if (!vol) -++ goto out_unlock; -++ -++ err = -EBUSY; -++ switch (mode) { -++ case UBI_READONLY: -++ if (vol->exclusive) -++ goto out_unlock; -++ vol->readers += 1; -++ break; -++ -++ case UBI_READWRITE: -++ if (vol->exclusive || vol->writers > 0) -++ goto out_unlock; -++ vol->writers += 1; -++ break; -++ -++ case UBI_EXCLUSIVE: -++ if (vol->exclusive || vol->writers || vol->readers) -++ goto out_unlock; -++ vol->exclusive = 1; -++ break; -++ } -++ get_device(&vol->dev); -++ vol->ref_count += 1; -++ spin_unlock(&ubi->volumes_lock); -++ return; -++ -++out_unlock: -++ spin_unlock(&ubi->volumes_lock); -++ module_put(THIS_MODULE); -++out_put_ubi: -++ ubi_put_device(ubi); -++ return; -++} -++EXPORT_SYMBOL_GPL(ubi_open_blkdev); -++ -++ -++void ubi_close_blkdev(struct ubi_volume_desc *desc) -++{ -++ struct ubi_volume *vol = desc->vol; -++ struct ubi_device *ubi = vol->ubi; -++ -++ dbg_msg("close volume %d, mode %d", vol->vol_id, desc->mode); -++ -++ spin_lock(&ubi->volumes_lock); -++ switch (desc->mode) { -++ case UBI_READONLY: -++ vol->readers -= 1; -++ break; -++ case UBI_READWRITE: -++ vol->writers -= 1; -++ break; -++ case UBI_EXCLUSIVE: -++ vol->exclusive = 0; -++ } -++ vol->ref_count -= 1; -++ spin_unlock(&ubi->volumes_lock); -++ put_device(&vol->dev); -++ ubi_put_device(ubi); -++ module_put(THIS_MODULE); -++} -++EXPORT_SYMBOL_GPL(ubi_close_blkdev); -++/* add by Nancy end */ -++ -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/misc.c linux-2.6.24.7/drivers/mtd/ubi/misc.c -+--- linux-2.6.24.7.old/drivers/mtd/ubi/misc.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/misc.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -67,7 +67,12 @@ -+ if (vol->vol_type != UBI_STATIC_VOLUME) -+ return 0; -+ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ buf = kmalloc(vol->usable_leb_size, GFP_KERNEL); -++#else -+ buf = vmalloc(vol->usable_leb_size); -++#endif -++ -+ if (!buf) -+ return -ENOMEM; -+ -+@@ -79,7 +84,7 @@ -+ else -+ size = vol->usable_leb_size; -+ -+- err = ubi_eba_read_leb(ubi, vol_id, i, buf, 0, size, 1); -++ err = ubi_eba_read_leb(ubi, vol, i, buf, 0, size, 1); -+ if (err) { -+ if (err == -EBADMSG) -+ err = 1; -+@@ -87,7 +92,11 @@ -+ } -+ } -+ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(buf); -++#else -+ vfree(buf); -++#endif -+ return err; -+ } -+ -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/scan.c linux-2.6.24.7/drivers/mtd/ubi/scan.c -+--- linux-2.6.24.7.old/drivers/mtd/ubi/scan.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/scan.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -42,6 +42,7 @@ -+ -+ #include -+ #include -++#include -+ #include "ubi.h" -+ -+ #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID -+@@ -92,27 +93,6 @@ -+ } -+ -+ /** -+- * commit_to_mean_value - commit intermediate results to the final mean erase -+- * counter value. -+- * @si: scanning information -+- * -+- * This is a helper function which calculates partial mean erase counter mean -+- * value and adds it to the resulting mean value. As we can work only in -+- * integer arithmetic and we want to calculate the mean value of erase counter -+- * accurately, we first sum erase counter values in @si->ec_sum variable and -+- * count these components in @si->ec_count. If this temporary @si->ec_sum is -+- * going to overflow, we calculate the partial mean value -+- * (@si->ec_sum/@si->ec_count) and add it to @si->mean_ec. -+- */ -+-static void commit_to_mean_value(struct ubi_scan_info *si) -+-{ -+- si->ec_sum /= si->ec_count; -+- if (si->ec_sum % si->ec_count >= si->ec_count / 2) -+- si->mean_ec += 1; -+- si->mean_ec += si->ec_sum; -+-} -+- -+-/** -+ * validate_vid_hdr - check that volume identifier header is correct and -+ * consistent. -+ * @vid_hdr: the volume identifier header to check -+@@ -286,9 +266,14 @@ -+ * FIXME: but this is anyway obsolete and will be removed at -+ * some point. -+ */ -+- -+ dbg_bld("using old crappy leb_ver stuff"); -+ -++ if (v1 == v2) { -++ ubi_err("PEB %d and PEB %d have the same version %lld", -++ seb->pnum, pnum, v1); -++ return -EINVAL; -++ } -++ -+ abs = v1 - v2; -+ if (abs < 0) -+ abs = -abs; -+@@ -353,7 +338,11 @@ -+ /* Read the data of the copy and check the CRC */ -+ -+ len = be32_to_cpu(vid_hdr->data_size); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ buf = kmalloc(len, GFP_KERNEL); -++#else -+ buf = vmalloc(len); -++#endif -+ if (!buf) { -+ err = -ENOMEM; -+ goto out_free_vidh; -+@@ -376,7 +365,11 @@ -+ bitflips = !!err; -+ } -+ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(buf); -++#else -+ vfree(buf); -++#endif -+ ubi_free_vid_hdr(ubi, vh); -+ -+ if (second_is_newer) -+@@ -387,10 +380,14 @@ -+ return second_is_newer | (bitflips << 1) | (corrupted << 2); -+ -+ out_free_buf: -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(buf); -++#else -+ vfree(buf); -++#endif -++ -+ out_free_vidh: -+ ubi_free_vid_hdr(ubi, vh); -+- ubi_assert(err < 0); -+ return err; -+ } -+ -+@@ -769,7 +766,7 @@ -+ */ -+ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum) -+ { -+- long long ec; -++ long long uninitialized_var(ec); -+ int err, bitflips = 0, vol_id, ec_corr = 0; -+ -+ dbg_bld("scan PEB %d", pnum); -+@@ -854,7 +851,7 @@ -+ } -+ -+ vol_id = be32_to_cpu(vidh->vol_id); -+- if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOL_ID) { -++ if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOLUME_ID) { -+ int lnum = be32_to_cpu(vidh->lnum); -+ -+ /* Unsupported internal volume */ -+@@ -897,15 +894,8 @@ -+ -+ adjust_mean_ec: -+ if (!ec_corr) { -+- if (si->ec_sum + ec < ec) { -+- commit_to_mean_value(si); -+- si->ec_sum = 0; -+- si->ec_count = 0; -+- } else { -+- si->ec_sum += ec; -+- si->ec_count += 1; -+- } -+- -++ si->ec_sum += ec; -++ si->ec_count += 1; -+ if (ec > si->max_ec) -+ si->max_ec = ec; -+ if (ec < si->min_ec) -+@@ -961,9 +951,11 @@ -+ -+ dbg_msg("scanning is finished"); -+ -+- /* Finish mean erase counter calculations */ -+- if (si->ec_count) -+- commit_to_mean_value(si); -++ /* Calculate mean erase counter */ -++ if (si->ec_count) { -++ do_div(si->ec_sum, si->ec_count); -++ si->mean_ec = si->ec_sum; -++ } -+ -+ if (si->is_empty) -+ ubi_msg("empty MTD device detected"); -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/scan.h linux-2.6.24.7/drivers/mtd/ubi/scan.h -+--- linux-2.6.24.7.old/drivers/mtd/ubi/scan.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/scan.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -124,7 +124,7 @@ -+ int max_ec; -+ unsigned long long max_sqnum; -+ int mean_ec; -+- int ec_sum; -++ uint64_t ec_sum; -+ int ec_count; -+ }; -+ -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/ubi-media.h linux-2.6.24.7/drivers/mtd/ubi/ubi-media.h -+--- linux-2.6.24.7.old/drivers/mtd/ubi/ubi-media.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/ubi/ubi-media.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,372 @@ -++/* -++ * Copyright (c) International Business Machines Corp., 2006 -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -++ * the GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Thomas Gleixner -++ * Frank Haverkamp -++ * Oliver Lohmann -++ * Andreas Arnez -++ */ -++ -++/* -++ * This file defines the layout of UBI headers and all the other UBI on-flash -++ * data structures. -++ */ -++ -++#ifndef __UBI_MEDIA_H__ -++#define __UBI_MEDIA_H__ -++ -++#include -++ -++/* The version of UBI images supported by this implementation */ -++#define UBI_VERSION 1 -++ -++/* The highest erase counter value supported by this implementation */ -++#define UBI_MAX_ERASECOUNTER 0x7FFFFFFF -++ -++/* The initial CRC32 value used when calculating CRC checksums */ -++#define UBI_CRC32_INIT 0xFFFFFFFFU -++ -++/* Erase counter header magic number (ASCII "UBI#") */ -++#define UBI_EC_HDR_MAGIC 0x55424923 -++/* Volume identifier header magic number (ASCII "UBI!") */ -++#define UBI_VID_HDR_MAGIC 0x55424921 -++ -++/* -++ * Volume type constants used in the volume identifier header. -++ * -++ * @UBI_VID_DYNAMIC: dynamic volume -++ * @UBI_VID_STATIC: static volume -++ */ -++enum { -++ UBI_VID_DYNAMIC = 1, -++ UBI_VID_STATIC = 2 -++}; -++ -++/* -++ * Volume flags used in the volume table record. -++ * -++ * @UBI_VTBL_AUTORESIZE_FLG: auto-resize this volume -++ * -++ * %UBI_VTBL_AUTORESIZE_FLG flag can be set only for one volume in the volume -++ * table. UBI automatically re-sizes the volume which has this flag and makes -++ * the volume to be of largest possible size. This means that if after the -++ * initialization UBI finds out that there are available physical eraseblocks -++ * present on the device, it automatically appends all of them to the volume -++ * (the physical eraseblocks reserved for bad eraseblocks handling and other -++ * reserved physical eraseblocks are not taken). So, if there is a volume with -++ * the %UBI_VTBL_AUTORESIZE_FLG flag set, the amount of available logical -++ * eraseblocks will be zero after UBI is loaded, because all of them will be -++ * reserved for this volume. Note, the %UBI_VTBL_AUTORESIZE_FLG bit is cleared -++ * after the volume had been initialized. -++ * -++ * The auto-resize feature is useful for device production purposes. For -++ * example, different NAND flash chips may have different amount of initial bad -++ * eraseblocks, depending of particular chip instance. Manufacturers of NAND -++ * chips usually guarantee that the amount of initial bad eraseblocks does not -++ * exceed certain percent, e.g. 2%. When one creates an UBI image which will be -++ * flashed to the end devices in production, he does not know the exact amount -++ * of good physical eraseblocks the NAND chip on the device will have, but this -++ * number is required to calculate the volume sized and put them to the volume -++ * table of the UBI image. In this case, one of the volumes (e.g., the one -++ * which will store the root file system) is marked as "auto-resizable", and -++ * UBI will adjust its size on the first boot if needed. -++ * -++ * Note, first UBI reserves some amount of physical eraseblocks for bad -++ * eraseblock handling, and then re-sizes the volume, not vice-versa. This -++ * means that the pool of reserved physical eraseblocks will always be present. -++ */ -++enum { -++ UBI_VTBL_AUTORESIZE_FLG = 0x01, -++}; -++ -++/* -++ * Compatibility constants used by internal volumes. -++ * -++ * @UBI_COMPAT_DELETE: delete this internal volume before anything is written -++ * to the flash -++ * @UBI_COMPAT_RO: attach this device in read-only mode -++ * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its -++ * physical eraseblocks, don't allow the wear-leveling unit to move them -++ * @UBI_COMPAT_REJECT: reject this UBI image -++ */ -++enum { -++ UBI_COMPAT_DELETE = 1, -++ UBI_COMPAT_RO = 2, -++ UBI_COMPAT_PRESERVE = 4, -++ UBI_COMPAT_REJECT = 5 -++}; -++ -++/* Sizes of UBI headers */ -++#define UBI_EC_HDR_SIZE sizeof(struct ubi_ec_hdr) -++#define UBI_VID_HDR_SIZE sizeof(struct ubi_vid_hdr) -++ -++/* Sizes of UBI headers without the ending CRC */ -++#define UBI_EC_HDR_SIZE_CRC (UBI_EC_HDR_SIZE - sizeof(__be32)) -++#define UBI_VID_HDR_SIZE_CRC (UBI_VID_HDR_SIZE - sizeof(__be32)) -++ -++/** -++ * struct ubi_ec_hdr - UBI erase counter header. -++ * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC) -++ * @version: version of UBI implementation which is supposed to accept this -++ * UBI image -++ * @padding1: reserved for future, zeroes -++ * @ec: the erase counter -++ * @vid_hdr_offset: where the VID header starts -++ * @data_offset: where the user data start -++ * @padding2: reserved for future, zeroes -++ * @hdr_crc: erase counter header CRC checksum -++ * -++ * The erase counter header takes 64 bytes and has a plenty of unused space for -++ * future usage. The unused fields are zeroed. The @version field is used to -++ * indicate the version of UBI implementation which is supposed to be able to -++ * work with this UBI image. If @version is greater then the current UBI -++ * version, the image is rejected. This may be useful in future if something -++ * is changed radically. This field is duplicated in the volume identifier -++ * header. -++ * -++ * The @vid_hdr_offset and @data_offset fields contain the offset of the the -++ * volume identifier header and user data, relative to the beginning of the -++ * physical eraseblock. These values have to be the same for all physical -++ * eraseblocks. -++ */ -++struct ubi_ec_hdr { -++ __be32 magic; -++ __u8 version; -++ __u8 padding1[3]; -++ __be64 ec; /* Warning: the current limit is 31-bit anyway! */ -++ __be32 vid_hdr_offset; -++ __be32 data_offset; -++ __u8 padding2[36]; -++ __be32 hdr_crc; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubi_vid_hdr - on-flash UBI volume identifier header. -++ * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC) -++ * @version: UBI implementation version which is supposed to accept this UBI -++ * image (%UBI_VERSION) -++ * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC) -++ * @copy_flag: if this logical eraseblock was copied from another physical -++ * eraseblock (for wear-leveling reasons) -++ * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE, -++ * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT) -++ * @vol_id: ID of this volume -++ * @lnum: logical eraseblock number -++ * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be -++ * removed, kept only for not breaking older UBI users) -++ * @data_size: how many bytes of data this logical eraseblock contains -++ * @used_ebs: total number of used logical eraseblocks in this volume -++ * @data_pad: how many bytes at the end of this physical eraseblock are not -++ * used -++ * @data_crc: CRC checksum of the data stored in this logical eraseblock -++ * @padding1: reserved for future, zeroes -++ * @sqnum: sequence number -++ * @padding2: reserved for future, zeroes -++ * @hdr_crc: volume identifier header CRC checksum -++ * -++ * The @sqnum is the value of the global sequence counter at the time when this -++ * VID header was created. The global sequence counter is incremented each time -++ * UBI writes a new VID header to the flash, i.e. when it maps a logical -++ * eraseblock to a new physical eraseblock. The global sequence counter is an -++ * unsigned 64-bit integer and we assume it never overflows. The @sqnum -++ * (sequence number) is used to distinguish between older and newer versions of -++ * logical eraseblocks. -++ * -++ * There are 2 situations when there may be more then one physical eraseblock -++ * corresponding to the same logical eraseblock, i.e., having the same @vol_id -++ * and @lnum values in the volume identifier header. Suppose we have a logical -++ * eraseblock L and it is mapped to the physical eraseblock P. -++ * -++ * 1. Because UBI may erase physical eraseblocks asynchronously, the following -++ * situation is possible: L is asynchronously erased, so P is scheduled for -++ * erasure, then L is written to,i.e. mapped to another physical eraseblock P1, -++ * so P1 is written to, then an unclean reboot happens. Result - there are 2 -++ * physical eraseblocks P and P1 corresponding to the same logical eraseblock -++ * L. But P1 has greater sequence number, so UBI picks P1 when it attaches the -++ * flash. -++ * -++ * 2. From time to time UBI moves logical eraseblocks to other physical -++ * eraseblocks for wear-leveling reasons. If, for example, UBI moves L from P -++ * to P1, and an unclean reboot happens before P is physically erased, there -++ * are two physical eraseblocks P and P1 corresponding to L and UBI has to -++ * select one of them when the flash is attached. The @sqnum field says which -++ * PEB is the original (obviously P will have lower @sqnum) and the copy. But -++ * it is not enough to select the physical eraseblock with the higher sequence -++ * number, because the unclean reboot could have happen in the middle of the -++ * copying process, so the data in P is corrupted. It is also not enough to -++ * just select the physical eraseblock with lower sequence number, because the -++ * data there may be old (consider a case if more data was added to P1 after -++ * the copying). Moreover, the unclean reboot may happen when the erasure of P -++ * was just started, so it result in unstable P, which is "mostly" OK, but -++ * still has unstable bits. -++ * -++ * UBI uses the @copy_flag field to indicate that this logical eraseblock is a -++ * copy. UBI also calculates data CRC when the data is moved and stores it at -++ * the @data_crc field of the copy (P1). So when UBI needs to pick one physical -++ * eraseblock of two (P or P1), the @copy_flag of the newer one (P1) is -++ * examined. If it is cleared, the situation* is simple and the newer one is -++ * picked. If it is set, the data CRC of the copy (P1) is examined. If the CRC -++ * checksum is correct, this physical eraseblock is selected (P1). Otherwise -++ * the older one (P) is selected. -++ * -++ * Note, there is an obsolete @leb_ver field which was used instead of @sqnum -++ * in the past. But it is not used anymore and we keep it in order to be able -++ * to deal with old UBI images. It will be removed at some point. -++ * -++ * There are 2 sorts of volumes in UBI: user volumes and internal volumes. -++ * Internal volumes are not seen from outside and are used for various internal -++ * UBI purposes. In this implementation there is only one internal volume - the -++ * layout volume. Internal volumes are the main mechanism of UBI extensions. -++ * For example, in future one may introduce a journal internal volume. Internal -++ * volumes have their own reserved range of IDs. -++ * -++ * The @compat field is only used for internal volumes and contains the "degree -++ * of their compatibility". It is always zero for user volumes. This field -++ * provides a mechanism to introduce UBI extensions and to be still compatible -++ * with older UBI binaries. For example, if someone introduced a journal in -++ * future, he would probably use %UBI_COMPAT_DELETE compatibility for the -++ * journal volume. And in this case, older UBI binaries, which know nothing -++ * about the journal volume, would just delete this volume and work perfectly -++ * fine. This is similar to what Ext2fs does when it is fed by an Ext3fs image -++ * - it just ignores the Ext3fs journal. -++ * -++ * The @data_crc field contains the CRC checksum of the contents of the logical -++ * eraseblock if this is a static volume. In case of dynamic volumes, it does -++ * not contain the CRC checksum as a rule. The only exception is when the -++ * data of the physical eraseblock was moved by the wear-leveling unit, then -++ * the wear-leveling unit calculates the data CRC and stores it in the -++ * @data_crc field. And of course, the @copy_flag is %in this case. -++ * -++ * The @data_size field is used only for static volumes because UBI has to know -++ * how many bytes of data are stored in this eraseblock. For dynamic volumes, -++ * this field usually contains zero. The only exception is when the data of the -++ * physical eraseblock was moved to another physical eraseblock for -++ * wear-leveling reasons. In this case, UBI calculates CRC checksum of the -++ * contents and uses both @data_crc and @data_size fields. In this case, the -++ * @data_size field contains data size. -++ * -++ * The @used_ebs field is used only for static volumes and indicates how many -++ * eraseblocks the data of the volume takes. For dynamic volumes this field is -++ * not used and always contains zero. -++ * -++ * The @data_pad is calculated when volumes are created using the alignment -++ * parameter. So, effectively, the @data_pad field reduces the size of logical -++ * eraseblocks of this volume. This is very handy when one uses block-oriented -++ * software (say, cramfs) on top of the UBI volume. -++ */ -++struct ubi_vid_hdr { -++ __be32 magic; -++ __u8 version; -++ __u8 vol_type; -++ __u8 copy_flag; -++ __u8 compat; -++ __be32 vol_id; -++ __be32 lnum; -++ __be32 leb_ver; /* obsolete, to be removed, don't use */ -++ __be32 data_size; -++ __be32 used_ebs; -++ __be32 data_pad; -++ __be32 data_crc; -++ __u8 padding1[4]; -++ __be64 sqnum; -++ __u8 padding2[12]; -++ __be32 hdr_crc; -++} __attribute__ ((packed)); -++ -++/* Internal UBI volumes count */ -++#define UBI_INT_VOL_COUNT 1 -++ -++/* -++ * Starting ID of internal volumes. There is reserved room for 4096 internal -++ * volumes. -++ */ -++#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096) -++ -++/* The layout volume contains the volume table */ -++ -++#define UBI_LAYOUT_VOLUME_ID UBI_INTERNAL_VOL_START -++#define UBI_LAYOUT_VOLUME_TYPE UBI_VID_DYNAMIC -++#define UBI_LAYOUT_VOLUME_ALIGN 1 -++#define UBI_LAYOUT_VOLUME_EBS 2 -++#define UBI_LAYOUT_VOLUME_NAME "layout volume" -++#define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT -++ -++/* The maximum number of volumes per one UBI device */ -++#define UBI_MAX_VOLUMES 128 -++ -++/* The maximum volume name length */ -++#define UBI_VOL_NAME_MAX 127 -++ -++/* Size of the volume table record */ -++#define UBI_VTBL_RECORD_SIZE sizeof(struct ubi_vtbl_record) -++ -++/* Size of the volume table record without the ending CRC */ -++#define UBI_VTBL_RECORD_SIZE_CRC (UBI_VTBL_RECORD_SIZE - sizeof(__be32)) -++ -++/** -++ * struct ubi_vtbl_record - a record in the volume table. -++ * @reserved_pebs: how many physical eraseblocks are reserved for this volume -++ * @alignment: volume alignment -++ * @data_pad: how many bytes are unused at the end of the each physical -++ * eraseblock to satisfy the requested alignment -++ * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) -++ * @upd_marker: if volume update was started but not finished -++ * @name_len: volume name length -++ * @name: the volume name -++ * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG) -++ * @padding: reserved, zeroes -++ * @crc: a CRC32 checksum of the record -++ * -++ * The volume table records are stored in the volume table, which is stored in -++ * the layout volume. The layout volume consists of 2 logical eraseblock, each -++ * of which contains a copy of the volume table (i.e., the volume table is -++ * duplicated). The volume table is an array of &struct ubi_vtbl_record -++ * objects indexed by the volume ID. -++ * -++ * If the size of the logical eraseblock is large enough to fit -++ * %UBI_MAX_VOLUMES records, the volume table contains %UBI_MAX_VOLUMES -++ * records. Otherwise, it contains as many records as it can fit (i.e., size of -++ * logical eraseblock divided by sizeof(struct ubi_vtbl_record)). -++ * -++ * The @upd_marker flag is used to implement volume update. It is set to %1 -++ * before update and set to %0 after the update. So if the update operation was -++ * interrupted, UBI knows that the volume is corrupted. -++ * -++ * The @alignment field is specified when the volume is created and cannot be -++ * later changed. It may be useful, for example, when a block-oriented file -++ * system works on top of UBI. The @data_pad field is calculated using the -++ * logical eraseblock size and @alignment. The alignment must be multiple to the -++ * minimal flash I/O unit. If @alignment is 1, all the available space of -++ * the physical eraseblocks is used. -++ * -++ * Empty records contain all zeroes and the CRC checksum of those zeroes. -++ */ -++struct ubi_vtbl_record { -++ __be32 reserved_pebs; -++ __be32 alignment; -++ __be32 data_pad; -++ __u8 vol_type; -++ __u8 upd_marker; -++ __be16 name_len; -++ __u8 name[UBI_VOL_NAME_MAX+1]; -++ __u8 flags; -++ __u8 padding[23]; -++ __be32 crc; -++} __attribute__ ((packed)); -++ -++#endif /* !__UBI_MEDIA_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/ubi.h linux-2.6.24.7/drivers/mtd/ubi/ubi.h -+--- linux-2.6.24.7.old/drivers/mtd/ubi/ubi.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/ubi.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -37,10 +37,9 @@ -+ #include -+ #include -+ #include -+- -+-#include -+ #include -+ -++#include "ubi-media.h" -+ #include "scan.h" -+ #include "debug.h" -+ -+@@ -94,8 +93,43 @@ -+ UBI_IO_BITFLIPS -+ }; -+ -+-extern int ubi_devices_cnt; -+-extern struct ubi_device *ubi_devices[]; -++/** -++ * struct ubi_wl_entry - wear-leveling entry. -++ * @rb: link in the corresponding RB-tree -++ * @ec: erase counter -++ * @pnum: physical eraseblock number -++ * -++ * This data structure is used in the WL unit. Each physical eraseblock has a -++ * corresponding &struct wl_entry object which may be kept in different -++ * RB-trees. See WL unit for details. -++ */ -++struct ubi_wl_entry { -++ struct rb_node rb; -++ int ec; -++ int pnum; -++}; -++ -++/** -++ * struct ubi_ltree_entry - an entry in the lock tree. -++ * @rb: links RB-tree nodes -++ * @vol_id: volume ID of the locked logical eraseblock -++ * @lnum: locked logical eraseblock number -++ * @users: how many tasks are using this logical eraseblock or wait for it -++ * @mutex: read/write mutex to implement read/write access serialization to -++ * the (@vol_id, @lnum) logical eraseblock -++ * -++ * This data structure is used in the EBA unit to implement per-LEB locking. -++ * When a logical eraseblock is being locked - corresponding -++ * &struct ubi_ltree_entry object is inserted to the lock tree (@ubi->ltree). -++ * See EBA unit for details. -++ */ -++struct ubi_ltree_entry { -++ struct rb_node rb; -++ int vol_id; -++ int lnum; -++ int users; -++ struct rw_semaphore mutex; -++}; -+ -+ struct ubi_volume_desc; -+ -+@@ -105,11 +139,10 @@ -+ * @cdev: character device object to create character device -+ * @ubi: reference to the UBI device description object -+ * @vol_id: volume ID -++ * @ref_count: volume reference count -+ * @readers: number of users holding this volume in read-only mode -+ * @writers: number of users holding this volume in read-write mode -+ * @exclusive: whether somebody holds this volume in exclusive mode -+- * @removed: if the volume was removed -+- * @checked: if this static volume was checked -+ * -+ * @reserved_pebs: how many physical eraseblocks are reserved for this volume -+ * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) -+@@ -117,21 +150,30 @@ -+ * @used_ebs: how many logical eraseblocks in this volume contain data -+ * @last_eb_bytes: how many bytes are stored in the last logical eraseblock -+ * @used_bytes: how many bytes of data this volume contains -+- * @upd_marker: non-zero if the update marker is set for this volume -+- * @corrupted: non-zero if the volume is corrupted (static volumes only) -+ * @alignment: volume alignment -+ * @data_pad: how many bytes are not used at the end of physical eraseblocks to -+- * satisfy the requested alignment -++ * satisfy the requested alignment -+ * @name_len: volume name length -+ * @name: volume name -+ * -+- * @updating: whether the volume is being updated -+ * @upd_ebs: how many eraseblocks are expected to be updated -+- * @upd_bytes: how many bytes are expected to be received -+- * @upd_received: how many update bytes were already received -+- * @upd_buf: update buffer which is used to collect update data -++ * @ch_lnum: LEB number which is being changing by the atomic LEB change -++ * operation -++ * @ch_dtype: data persistency type which is being changing by the atomic LEB -++ * change operation -++ * @upd_bytes: how many bytes are expected to be received for volume update or -++ * atomic LEB change -++ * @upd_received: how many bytes were already received for volume update or -++ * atomic LEB change -++ * @upd_buf: update buffer which is used to collect update data or data for -++ * atomic LEB change -+ * -+ * @eba_tbl: EBA table of this volume (LEB->PEB mapping) -++ * @checked: %1 if this static volume was checked -++ * @corrupted: %1 if the volume is corrupted (static volumes only) -++ * @upd_marker: %1 if the update marker is set for this volume -++ * @updating: %1 if the volume is being updated -++ * @changing_leb: %1 if the atomic LEB change ioctl command is in progress -+ * -+ * @gluebi_desc: gluebi UBI volume descriptor -+ * @gluebi_refcount: reference count of the gluebi MTD device -+@@ -150,11 +192,10 @@ -+ struct cdev cdev; -+ struct ubi_device *ubi; -+ int vol_id; -++ int ref_count; -+ int readers; -+ int writers; -+ int exclusive; -+- int removed; -+- int checked; -+ -+ int reserved_pebs; -+ int vol_type; -+@@ -162,29 +203,45 @@ -+ int used_ebs; -+ int last_eb_bytes; -+ long long used_bytes; -+- int upd_marker; -+- int corrupted; -+ int alignment; -+ int data_pad; -+ int name_len; -+ char name[UBI_VOL_NAME_MAX+1]; -+ -+- int updating; -+ int upd_ebs; -++ int ch_lnum; -++ int ch_dtype; -+ long long upd_bytes; -+ long long upd_received; -+ void *upd_buf; -+ -+ int *eba_tbl; -++ unsigned int checked:1; -++ unsigned int corrupted:1; -++ unsigned int upd_marker:1; -++ unsigned int updating:1; -++ unsigned int changing_leb:1; -+ -+ #ifdef CONFIG_MTD_UBI_GLUEBI -+- /* Gluebi-related stuff may be compiled out */ -++ /* -++ * Gluebi-related stuff may be compiled out. -++ * TODO: this should not be built into UBI but should be a separate -++ * ubimtd driver which works on top of UBI and emulates MTD devices. -++ */ -+ struct ubi_volume_desc *gluebi_desc; -+ int gluebi_refcount; -+ struct mtd_info gluebi_mtd; -+ #endif -++ int bdev_mode; //add by Nancy -+ }; -+ -++struct vol_notifier { -++ void (*add)(struct ubi_volume *vol); -++ void (*remove)(struct ubi_volume *vol); -++ struct list_head list; -++}; -++ -++ -+ /** -+ * struct ubi_volume_desc - descriptor of the UBI volume returned when it is -+ * opened. -+@@ -200,28 +257,31 @@ -+ -+ /** -+ * struct ubi_device - UBI device description structure -+- * @dev: class device object to use the the Linux device model -++ * @dev: UBI device object to use the the Linux device model -+ * @cdev: character device object to create character device -+ * @ubi_num: UBI device number -+ * @ubi_name: UBI device name -+- * @major: character device major number -+ * @vol_count: number of volumes in this UBI device -+ * @volumes: volumes of this UBI device -+ * @volumes_lock: protects @volumes, @rsvd_pebs, @avail_pebs, beb_rsvd_pebs, -+- * @beb_rsvd_level, @bad_peb_count, @good_peb_count, @vol_count, @vol->readers, -+- * @vol->writers, @vol->exclusive, @vol->removed, @vol->mapping and -+- * @vol->eba_tbl. -++ * @beb_rsvd_level, @bad_peb_count, @good_peb_count, @vol_count, -++ * @vol->readers, @vol->writers, @vol->exclusive, -++ * @vol->ref_count, @vol->mapping and @vol->eba_tbl. -++ * @ref_count: count of references on the UBI device -+ * -+ * @rsvd_pebs: count of reserved physical eraseblocks -+ * @avail_pebs: count of available physical eraseblocks -+ * @beb_rsvd_pebs: how many physical eraseblocks are reserved for bad PEB -+- * handling -++ * handling -+ * @beb_rsvd_level: normal level of PEBs reserved for bad PEB handling -+ * -++ * @autoresize_vol_id: ID of the volume which has to be auto-resized at the end -++ * of UBI ititializetion -+ * @vtbl_slots: how many slots are available in the volume table -+ * @vtbl_size: size of the volume table in bytes -+ * @vtbl: in-RAM volume table copy -+- * @vtbl_mutex: protects on-flash volume table -++ * @volumes_mutex: protects on-flash volume table and serializes volume -++ * changes, like creation, deletion, update, resize -+ * -+ * @max_ec: current highest erase counter value -+ * @mean_ec: current mean erase counter value -+@@ -238,15 +298,15 @@ -+ * @prot.pnum: protection tree indexed by physical eraseblock numbers -+ * @prot.aec: protection tree indexed by absolute erase counter value -+ * @wl_lock: protects the @used, @free, @prot, @lookuptbl, @abs_ec, @move_from, -+- * @move_to, @move_to_put @erase_pending, @wl_scheduled, and @works -+- * fields -++ * @move_to, @move_to_put @erase_pending, @wl_scheduled, and @works -++ * fields -++ * @move_mutex: serializes eraseblock moves -+ * @wl_scheduled: non-zero if the wear-leveling was scheduled -+ * @lookuptbl: a table to quickly find a &struct ubi_wl_entry object for any -+- * physical eraseblock -++ * physical eraseblock -+ * @abs_ec: absolute erase counter -+ * @move_from: physical eraseblock from where the data is being moved -+ * @move_to: physical eraseblock where the data is being moved to -+- * @move_from_put: if the "from" PEB was put -+ * @move_to_put: if the "to" PEB was put -+ * @works: list of pending works -+ * @works_count: count of pending works -+@@ -273,36 +333,39 @@ -+ * @hdrs_min_io_size -+ * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset -+ * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or -+- * not -++ * not -+ * @mtd: MTD device descriptor -+ * -+ * @peb_buf1: a buffer of PEB size used for different purposes -+ * @peb_buf2: another buffer of PEB size used for different purposes -+ * @buf_mutex: proptects @peb_buf1 and @peb_buf2 -+- * @dbg_peb_buf: buffer of PEB size used for debugging -++ * @dbg_peb_buf: buffer of PEB size used for debugging -+ * @dbg_buf_mutex: proptects @dbg_peb_buf -+ */ -+ struct ubi_device { -+ struct cdev cdev; -++ int bdev_major; //add by Nancy -+ struct device dev; -+ int ubi_num; -+ char ubi_name[sizeof(UBI_NAME_STR)+5]; -+- int major; -+ int vol_count; -+ struct ubi_volume *volumes[UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT]; -+ spinlock_t volumes_lock; -++ int ref_count; -+ -+ int rsvd_pebs; -+ int avail_pebs; -+ int beb_rsvd_pebs; -+ int beb_rsvd_level; -+ -++ int autoresize_vol_id; -+ int vtbl_slots; -+ int vtbl_size; -+ struct ubi_vtbl_record *vtbl; -+- struct mutex vtbl_mutex; -++ struct mutex volumes_mutex; -+ -+ int max_ec; -++ /* TODO: mean_ec is not updated run-time, fix */ -+ int mean_ec; -+ -+ /* EBA unit's stuff */ -+@@ -320,12 +383,13 @@ -+ struct rb_root aec; -+ } prot; -+ spinlock_t wl_lock; -++ struct mutex move_mutex; -++ struct rw_semaphore work_sem; -+ int wl_scheduled; -+ struct ubi_wl_entry **lookuptbl; -+ unsigned long long abs_ec; -+ struct ubi_wl_entry *move_from; -+ struct ubi_wl_entry *move_to; -+- int move_from_put; -+ int move_to_put; -+ struct list_head works; -+ int works_count; -+@@ -355,15 +419,19 @@ -+ void *peb_buf1; -+ void *peb_buf2; -+ struct mutex buf_mutex; -++ struct mutex ckvol_mutex; -+ #ifdef CONFIG_MTD_UBI_DEBUG -+ void *dbg_peb_buf; -+ struct mutex dbg_buf_mutex; -+ #endif -+ }; -+ -++extern struct kmem_cache *ubi_wl_entry_slab; -++extern struct file_operations ubi_ctrl_cdev_operations; -+ extern struct file_operations ubi_cdev_operations; -+ extern struct file_operations ubi_vol_cdev_operations; -+ extern struct class *ubi_class; -++extern struct mutex ubi_devices_mutex; -+ -+ /* vtbl.c */ -+ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, -+@@ -374,13 +442,18 @@ -+ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req); -+ int ubi_remove_volume(struct ubi_volume_desc *desc); -+ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs); -+-int ubi_add_volume(struct ubi_device *ubi, int vol_id); -+-void ubi_free_volume(struct ubi_device *ubi, int vol_id); -++int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol); -++void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol); -+ -+ /* upd.c */ -+-int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes); -+-int ubi_more_update_data(struct ubi_device *ubi, int vol_id, -++int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, -++ long long bytes); -++int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, -+ const void __user *buf, int count); -++int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, -++ const struct ubi_leb_change_req *req); -++int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol, -++ const void __user *buf, int count); -+ -+ /* misc.c */ -+ int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf, int length); -+@@ -399,16 +472,17 @@ -+ #endif -+ -+ /* eba.c */ -+-int ubi_eba_unmap_leb(struct ubi_device *ubi, int vol_id, int lnum); -+-int ubi_eba_read_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf, -+- int offset, int len, int check); -+-int ubi_eba_write_leb(struct ubi_device *ubi, int vol_id, int lnum, -++int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol, -++ int lnum); -++int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, -++ void *buf, int offset, int len, int check); -++int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, -+ const void *buf, int offset, int len, int dtype); -+-int ubi_eba_write_leb_st(struct ubi_device *ubi, int vol_id, int lnum, -+- const void *buf, int len, int dtype, -++int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, -++ int lnum, const void *buf, int len, int dtype, -+ int used_ebs); -+-int ubi_eba_atomic_leb_change(struct ubi_device *ubi, int vol_id, int lnum, -+- const void *buf, int len, int dtype); -++int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, -++ int lnum, const void *buf, int len, int dtype); -+ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, -+ struct ubi_vid_hdr *vid_hdr); -+ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si); -+@@ -421,6 +495,7 @@ -+ int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum); -+ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si); -+ void ubi_wl_close(struct ubi_device *ubi); -++int ubi_thread(void *u); -+ -+ /* io.c */ -+ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, -+@@ -438,6 +513,14 @@ -+ struct ubi_vid_hdr *vid_hdr, int verbose); -+ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, -+ struct ubi_vid_hdr *vid_hdr); -++ -++/* build.c */ -++int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset); -++int ubi_detach_mtd_dev(int ubi_num, int anyway); -++struct ubi_device *ubi_get_device(int ubi_num); -++void ubi_put_device(struct ubi_device *ubi); -++struct ubi_device *ubi_get_by_major(int major); -++int ubi_major2num(int major); -+ -+ /* -+ * ubi_rb_for_each_entry - walk an RB-tree. -+@@ -523,8 +606,10 @@ -+ */ -+ static inline void ubi_ro_mode(struct ubi_device *ubi) -+ { -+- ubi->ro_mode = 1; -+- ubi_warn("switch to read-only mode"); -++ if (!ubi->ro_mode) { -++ ubi->ro_mode = 1; -++ ubi_warn("switch to read-only mode"); -++ } -+ } -+ -+ /** -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/ubiblk.c linux-2.6.24.7/drivers/mtd/ubi/ubiblk.c -+--- linux-2.6.24.7.old/drivers/mtd/ubi/ubiblk.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/ubi/ubiblk.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,359 @@ -++/* -++ * Direct UBI block device access -++ * -++ * (C) 2000-2003 Nicolas Pitre -++ * (C) 1999-2003 David Woodhouse -++ * (C) 2008 Yurong Tan : -++ * borrow mtdblock.c to work on top of UBI -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "ubi.h" -++#include "ubiblk.h" -++ -++#define UBIBLK_UNMAPPED 0 -++#define UBIBLK_SECTOR_SIZE 512 -++ -++extern void ubi_open_blkdev(int ubi_num, int vol_id, int mode); -++extern void ubi_close_blkdev(struct ubi_volume_desc *desc); -++static void ubiblk_setup_writecache(struct ubiblk_dev *ubiblk, int virt_block); -++static int ubiblk_flush_writecache(struct ubiblk_dev *ubiblk); -++extern int ubiblk_leb_change(struct ubiblk_dev *ubiblk); -++ -++struct ubiblk_dev *ubiblks[UBI_MAX_VOLUMES]; -++static unsigned short subpage_shift; -++ -++static int ubiblk_flush_writecache(struct ubiblk_dev *ubiblk) -++{ -++ if (STATE_UNUSED == ubiblk->write_cache_state) -++ return 0; -++ ubiblk_leb_change(ubiblk); -++ ubiblk->write_cache_state = STATE_UNUSED; -++ -++ return 0; -++} -++ -++static void ubiblk_setup_writecache(struct ubiblk_dev *ubiblk, int virt_block) -++{ -++ struct ubi_volume_desc *uv = ubiblk->uv; -++ struct ubi_device *ubi = uv->vol->ubi; -++ int ppb = ubi->leb_size / ubi->min_io_size; -++ unsigned short spp = ubi->min_io_size >> subpage_shift; -++ -++ ubiblk->vbw = virt_block; -++ ubiblk->write_cache_state = STATE_USED; -++ -++ memset(ubiblk->page_sts, 0, ppb); -++ memset(ubiblk->subpage_sts, 0, ppb*spp); -++} -++ -++static int do_cached_write (struct ubiblk_dev *ubiblk, unsigned long sector, -++ int len, const char *buf) -++{ -++ struct ubi_volume_desc *uv = ubiblk->uv; -++ struct ubi_device *ubi = uv->vol->ubi; -++ int ppb = ubi->leb_size / ubi->min_io_size; -++ unsigned short sectors_per_page = ubi->min_io_size / len; -++ unsigned short sectors_in_page_shift = ffs(sectors_per_page) - 1; -++ unsigned short page_shift = ffs(ubi->min_io_size) - 1; -++ unsigned short virt_block, page, subpage; -++ unsigned long virt_page; -++ -++ virt_page = sector / sectors_per_page; -++ subpage = sector % sectors_per_page; -++ virt_block = virt_page / ppb; -++ page = virt_page % ppb; -++ -++ if(ubi_is_mapped(uv, virt_block) == UBIBLK_UNMAPPED ){ -++ mutex_lock(&ubiblk->cache_mutex); -++ ubiblk_flush_writecache(ubiblk); -++ mutex_unlock(&ubiblk->cache_mutex); -++ -++ ubiblk_setup_writecache(ubiblk, virt_block); -++ } else { -++ if ( STATE_USED == ubiblk->write_cache_state ) { -++ if ( ubiblk->vbw != virt_block) { -++ // Commit before we start a new cache. -++ mutex_lock(&ubiblk->cache_mutex); -++ ubiblk_flush_writecache(ubiblk); -++ mutex_unlock(&ubiblk->cache_mutex); -++ -++ ubiblk_setup_writecache(ubiblk, virt_block); -++ } else { -++ //printk("cache hit: 0x%x\n", virt_page); -++ } -++ } else { -++// printk("with existing mapping\n"); -++ ubiblk_setup_writecache(ubiblk, virt_block); -++ } -++ } -++ ubiblk->page_sts[page] = 1; -++ ubiblk->subpage_sts[(page<write_cache[(page<uv; -++ int ppb = uv->vol->ubi->leb_size / uv->vol->ubi->min_io_size; -++ unsigned short sectors_per_page = uv->vol->ubi->min_io_size >> 9; -++ unsigned short page_shift = ffs(uv->vol->ubi->min_io_size) - 1; -++ unsigned short virt_block, page, page_offset; -++ unsigned long virt_page; -++ -++ virt_page = sector / sectors_per_page; -++ page_offset = sector % sectors_per_page; -++ virt_block = virt_page / ppb; -++ page = virt_page % ppb; -++ -++ if(ubiblk->vbw == virt_block){ -++ mutex_lock(&ubiblk->cache_mutex); -++ ubiblk_flush_writecache(ubiblk); -++ mutex_unlock(&ubiblk->cache_mutex); -++ } -++ -++ if ( ubi_is_mapped( uv, virt_block) == UBIBLK_UNMAPPED){ -++ /* In a Flash Memory device, there might be a logical block that is -++ * not allcated to a physical block due to the block not being used. -++ * All data returned should be set to 0xFF when accessing this logical -++ * block. -++ */ -++ -++ //printk("address translate fail\n"); -++ memset(buf, 0xFF, UBIBLK_SECTOR_SIZE); -++ } else { -++ -++ if( ubiblk->vbr != virt_block ||ubiblk->read_cache_state == STATE_UNUSED ){ -++ ubiblk->vbr = virt_block; -++ ubi_leb_read(uv, virt_block, ubiblk->read_cache, 0, uv->vol->usable_leb_size, 0); -++ ubiblk->read_cache_state = STATE_USED; -++ } -++ memcpy(buf, &ubiblk->read_cache[(page<devnum]; -++ return do_cached_read(ubiblk, block, UBIBLK_SECTOR_SIZE, buf); -++} -++ -++static int ubiblk_writesect(struct ubi_blktrans_dev *dev, -++ unsigned long block, char *buf) -++{ -++ struct ubiblk_dev *ubiblk = ubiblks[dev->devnum]; -++ return do_cached_write(ubiblk, block, UBIBLK_SECTOR_SIZE, buf); -++} -++ -++static int ubiblk_init_vol(int dev, struct ubi_volume_desc *uv) -++{ -++ struct ubiblk_dev *ubiblk; -++ struct ubi_device *ubi = uv->vol->ubi; -++ int ppb = ubi->leb_size / ubi->min_io_size; -++ unsigned short spp = ubi->min_io_size >> subpage_shift; -++ -++ ubiblk = kmalloc(sizeof(struct ubiblk_dev), GFP_KERNEL); -++ if (!ubiblk) -++ return -ENOMEM; -++ -++ memset(ubiblk, 0, sizeof(*ubiblk)); -++ -++ ubiblk->count = 1; -++ ubiblk->uv = uv; -++ mutex_init (&ubiblk->cache_mutex); -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ ubiblk->write_cache = kmalloc(ubiblk->uv->vol->usable_leb_size, GFP_KERNEL); -++ ubiblk->read_cache = kmalloc(ubiblk->uv->vol->usable_leb_size, GFP_KERNEL); -++ ubiblk->page_sts = kmalloc(ppb, GFP_KERNEL); -++ ubiblk->subpage_sts = kmalloc(ppb*spp, GFP_KERNEL); -++#else -++ ubiblk->write_cache = vmalloc(ubiblk->uv->vol->usable_leb_size); -++ ubiblk->read_cache = vmalloc(ubiblk->uv->vol->usable_leb_size); -++ ubiblk->page_sts = vmalloc(ppb); -++ ubiblk->subpage_sts = vmalloc(ppb*spp); -++#endif -++ -++ if(!ubiblk->write_cache || -++ !ubiblk->read_cache || -++ !ubiblk->page_sts || -++ !ubiblk->subpage_sts) -++ return -ENOMEM; -++ -++ ubiblk->write_cache_state = STATE_UNUSED; -++ ubiblk->read_cache_state = STATE_UNUSED; -++ -++ ubiblks[dev] = ubiblk; -++ DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); -++ return 0; -++} -++ -++static int ubiblk_open(struct inode *i, struct file *f ) -++{ -++ struct ubi_volume_desc *desc; -++ struct ubi_blktrans_dev *dev; -++ int ubi_num = ubi_major2num(imajor(i)); -++ int vol_id = iminor(i); -++ int mode; -++ int ret = 0; -++ -++ if (f->f_mode & FMODE_WRITE) -++ mode = UBI_READWRITE; -++ else -++ mode = UBI_READONLY; -++ -++ dev = i->i_bdev->bd_disk->private_data; -++ if (ubiblks[dev->devnum]) { -++ ubiblks[dev->devnum]->count++; -++ ubi_open_blkdev(ubi_num, vol_id, mode); -++ printk("%s: increase use count\n",__FUNCTION__); -++ return 0; -++ } -++ -++ desc = ubi_open_volume(ubi_num, vol_id, mode); -++ if (IS_ERR(desc)) -++ return PTR_ERR(desc); -++ -++ desc->vol->bdev_mode = mode; -++ dev->uv = desc; -++ -++ subpage_shift = ffs(UBIBLK_SECTOR_SIZE)-1; -++ ret = ubiblk_init_vol(dev->devnum, desc); -++ return ret; -++} -++ -++static int ubiblk_release(struct ubi_blktrans_dev *ubd) -++{ -++ int dev = ubd->devnum; -++ struct ubiblk_dev *ubiblk = ubiblks[dev]; -++ struct ubi_device *ubi = ubiblk->uv->vol->ubi; -++ -++ mutex_lock(&ubiblk->cache_mutex); -++ ubiblk_flush_writecache(ubiblk); -++ mutex_unlock(&ubiblk->cache_mutex); -++ -++ ubiblk->count --; -++ if (!ubiblk->count) { -++ /* It was the last usage. Free the device */ -++ ubiblks[dev] = NULL; -++ -++ if (ubi->mtd->sync) -++ ubi->mtd->sync(ubi->mtd); -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(ubiblk->write_cache); -++ kfree(ubiblk->read_cache); -++#else -++ vfree(ubiblk->write_cache); -++ vfree(ubiblk->read_cache); -++#endif -++ kfree(ubiblk); -++ -++ ubi_close_volume(ubiblk->uv); -++ return 0; -++ } -++ else{ -++ printk("%s: decrease use count\n",__FUNCTION__); -++ ubi_close_blkdev(ubiblk->uv); -++ return 0; -++ } -++ return 1; -++} -++static int ubiblk_flush(struct ubi_blktrans_dev *dev) -++{ -++ struct ubiblk_dev *ubiblk = ubiblks[dev->devnum]; -++ struct ubi_device *ubi = ubiblk->uv->vol->ubi; -++ -++ mutex_lock(&ubiblk->cache_mutex); -++ ubiblk_flush_writecache(ubiblk); -++ mutex_unlock(&ubiblk->cache_mutex); -++ -++ if (ubi->mtd->sync) -++ ubi->mtd->sync(ubi->mtd); -++ return 0; -++} -++ -++void ubiblk_add_vol_dev(struct ubi_blktrans_ops *tr, struct ubi_volume *vol) -++{ -++ struct ubi_blktrans_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL); -++ if (!dev) -++ return; -++ -++ dev->devnum = vol->vol_id; -++ dev->size = vol->used_bytes >> 9; -++ dev->tr = tr; -++ -++ if (vol->bdev_mode == UBI_READONLY) -++ dev->readonly = 1; -++ -++ vol->ubi->bdev_major = tr->major; -++ -++ add_ubi_blktrans_dev(dev); -++} -++ -++void ubiblk_remove_vol_dev(struct ubi_blktrans_dev *dev) -++{ -++ del_ubi_blktrans_dev(dev); -++ kfree(dev); -++} -++ -++static int ubiblk_getgeo(struct ubi_blktrans_dev *dev, struct hd_geometry *geo) -++{ -++ memset(geo, 0, sizeof(*geo)); -++ geo->heads = 4; -++ geo->sectors = 16; -++ geo->cylinders = dev->size/(4*16); -++ return 0; -++} -++ -++static struct ubi_blktrans_ops ubiblk_tr = { -++ .name = "ubiblock", -++ .major = 0, -++ .part_bits = 0, -++ .blksize = UBIBLK_SECTOR_SIZE, -++ .open = ubiblk_open, -++ .release = ubiblk_release, -++ .readsect = ubiblk_readsect, -++ .writesect = ubiblk_writesect, -++ .getgeo = ubiblk_getgeo, -++ .flush = ubiblk_flush, -++ .add_vol = ubiblk_add_vol_dev, -++ .remove_vol = ubiblk_remove_vol_dev, -++ .owner = THIS_MODULE, -++}; -++ -++static int __init init_ubiblock(void) -++{ -++ return register_ubi_blktrans(&ubiblk_tr); -++} -++ -++static void __exit cleanup_ubiblock(void) -++{ -++ deregister_ubi_blktrans(&ubiblk_tr); -++} -++ -++module_init(init_ubiblock); -++module_exit(cleanup_ubiblock); -++ -++MODULE_LICENSE("GPL"); -++MODULE_AUTHOR("Nicolas Pitre , Yurong Tan "); -++MODULE_DESCRIPTION("Caching read/erase/writeback block device emulation access to UBI volumes"); -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/ubiblk.h linux-2.6.24.7/drivers/mtd/ubi/ubiblk.h -+--- linux-2.6.24.7.old/drivers/mtd/ubi/ubiblk.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/ubi/ubiblk.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,85 @@ -++/* -++ * (C) 2003 David Woodhouse -++ * (C) 2008 Yurong Tan : borrow from MTD blktrans.h for UBI used -++ * Interface to Linux block layer for UBI 'translation layers'. -++ */ -++ -++#ifndef __UBI_TRANS_H__ -++#define __UBI_TRANS_H__ -++ -++#include -++#include -++#include "ubi.h" -++ -++struct hd_geometry; -++struct ubi_volume_desc; -++struct ubi_blktrans_ops; -++struct file; -++struct inode; -++ -++struct ubiblk_dev { -++ struct ubi_volume_desc *uv; -++ int count; -++ struct mutex cache_mutex; -++ unsigned short vbw; //virt block number of write cache -++ unsigned short vbr; //virt block number of read cache -++ -++ unsigned char *write_cache; -++ unsigned char *page_sts; -++ unsigned char *subpage_sts; -++ -++ unsigned char *read_cache; -++ enum { STATE_UNUSED, STATE_USED } read_cache_state, write_cache_state; -++}; -++ -++struct ubi_blktrans_dev { -++ struct ubi_blktrans_ops *tr; -++ struct list_head list; -++ struct ubi_volume_desc *uv; -++ struct mutex lock; -++ int devnum; -++ unsigned long size; -++ int readonly; -++ void *blkcore_priv; /* gendisk in 2.5, devfs_handle in 2.4 */ -++}; -++ -++struct blkcore_priv; /* Differs for 2.4 and 2.5 kernels; private */ -++ -++struct ubi_blktrans_ops { -++ char *name; -++ int major; -++ int part_bits; -++ int blksize; -++ int blkshift; -++ -++ /* Access functions */ -++ int (*readsect)(struct ubi_blktrans_dev *dev, -++ unsigned long block, char *buffer); -++ int (*writesect)(struct ubi_blktrans_dev *dev, -++ unsigned long block, char *buffer); -++ -++ /* Block layer ioctls */ -++ int (*getgeo)(struct ubi_blktrans_dev *dev, struct hd_geometry *geo); -++ int (*flush)(struct ubi_blktrans_dev *dev); -++ -++ /* Called with mtd_table_mutex held; no race with add/remove */ -++ int (*open)(struct inode *i, struct file *f); -++ int (*release)(struct ubi_blktrans_dev *dev); -++ -++ /* Called on {de,}registration and on subsequent addition/removal -++ of devices, with mtd_table_mutex held. */ -++ void (*add_vol)(struct ubi_blktrans_ops *tr, struct ubi_volume *vol); -++ void (*remove_vol)(struct ubi_blktrans_dev *dev); -++ -++ struct list_head devs; -++ struct list_head list; -++ struct module *owner; -++ -++ struct ubi_blkcore_priv *blkcore_priv; -++}; -++ -++extern int add_ubi_blktrans_dev(struct ubi_blktrans_dev *new); -++extern int del_ubi_blktrans_dev(struct ubi_blktrans_dev *old); -++extern int register_ubi_blktrans(struct ubi_blktrans_ops *tr); -++extern int deregister_ubi_blktrans(struct ubi_blktrans_ops *tr); -++#endif /* __UBI_TRANS_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/upd.c linux-2.6.24.7/drivers/mtd/ubi/upd.c -+--- linux-2.6.24.7.old/drivers/mtd/ubi/upd.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/upd.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -22,7 +22,8 @@ -+ */ -+ -+ /* -+- * This file contains implementation of the volume update functionality. -++ * This file contains implementation of the volume update and atomic LEB change -++ * functionality. -+ * -+ * The update operation is based on the per-volume update marker which is -+ * stored in the volume table. The update marker is set before the update -+@@ -45,29 +46,31 @@ -+ /** -+ * set_update_marker - set update marker. -+ * @ubi: UBI device description object -+- * @vol_id: volume ID -++ * @vol: volume description object -+ * -+- * This function sets the update marker flag for volume @vol_id. Returns zero -++ * This function sets the update marker flag for volume @vol. Returns zero -+ * in case of success and a negative error code in case of failure. -+ */ -+-static int set_update_marker(struct ubi_device *ubi, int vol_id) -++static int set_update_marker(struct ubi_device *ubi, struct ubi_volume *vol) -+ { -+ int err; -+ struct ubi_vtbl_record vtbl_rec; -+- struct ubi_volume *vol = ubi->volumes[vol_id]; -+ -+- dbg_msg("set update marker for volume %d", vol_id); -++ dbg_msg("set update marker for volume %d", vol->vol_id); -+ -+ if (vol->upd_marker) { -+- ubi_assert(ubi->vtbl[vol_id].upd_marker); -++ ubi_assert(ubi->vtbl[vol->vol_id].upd_marker); -+ dbg_msg("already set"); -+ return 0; -+ } -+ -+- memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record)); -++ memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id], -++ sizeof(struct ubi_vtbl_record)); -+ vtbl_rec.upd_marker = 1; -+ -+- err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); -++ mutex_lock(&ubi->volumes_mutex); -++ err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec); -++ mutex_unlock(&ubi->volumes_mutex); -+ vol->upd_marker = 1; -+ return err; -+ } -+@@ -75,23 +78,24 @@ -+ /** -+ * clear_update_marker - clear update marker. -+ * @ubi: UBI device description object -+- * @vol_id: volume ID -++ * @vol: volume description object -+ * @bytes: new data size in bytes -+ * -+- * This function clears the update marker for volume @vol_id, sets new volume -++ * This function clears the update marker for volume @vol, sets new volume -+ * data size and clears the "corrupted" flag (static volumes only). Returns -+ * zero in case of success and a negative error code in case of failure. -+ */ -+-static int clear_update_marker(struct ubi_device *ubi, int vol_id, long long bytes) -++static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol, -++ long long bytes) -+ { -+ int err; -+ uint64_t tmp; -+ struct ubi_vtbl_record vtbl_rec; -+- struct ubi_volume *vol = ubi->volumes[vol_id]; -+ -+- dbg_msg("clear update marker for volume %d", vol_id); -++ dbg_msg("clear update marker for volume %d", vol->vol_id); -+ -+- memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record)); -++ memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id], -++ sizeof(struct ubi_vtbl_record)); -+ ubi_assert(vol->upd_marker && vtbl_rec.upd_marker); -+ vtbl_rec.upd_marker = 0; -+ -+@@ -106,7 +110,9 @@ -+ vol->last_eb_bytes = vol->usable_leb_size; -+ } -+ -+- err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); -++ mutex_lock(&ubi->volumes_mutex); -++ err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec); -++ mutex_unlock(&ubi->volumes_mutex); -+ vol->upd_marker = 0; -+ return err; -+ } -+@@ -114,35 +120,36 @@ -+ /** -+ * ubi_start_update - start volume update. -+ * @ubi: UBI device description object -+- * @vol_id: volume ID -++ * @vol: volume description object -+ * @bytes: update bytes -+ * -+ * This function starts volume update operation. If @bytes is zero, the volume -+ * is just wiped out. Returns zero in case of success and a negative error code -+ * in case of failure. -+ */ -+-int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes) -++int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, -++ long long bytes) -+ { -+ int i, err; -+ uint64_t tmp; -+- struct ubi_volume *vol = ubi->volumes[vol_id]; -+ -+- dbg_msg("start update of volume %d, %llu bytes", vol_id, bytes); -++ dbg_msg("start update of volume %d, %llu bytes", vol->vol_id, bytes); -++ ubi_assert(!vol->updating && !vol->changing_leb); -+ vol->updating = 1; -+ -+- err = set_update_marker(ubi, vol_id); -++ err = set_update_marker(ubi, vol); -+ if (err) -+ return err; -+ -+ /* Before updating - wipe out the volume */ -+ for (i = 0; i < vol->reserved_pebs; i++) { -+- err = ubi_eba_unmap_leb(ubi, vol_id, i); -++ err = ubi_eba_unmap_leb(ubi, vol, i); -+ if (err) -+ return err; -+ } -+ -+ if (bytes == 0) { -+- err = clear_update_marker(ubi, vol_id, 0); -++ err = clear_update_marker(ubi, vol, 0); -+ if (err) -+ return err; -+ err = ubi_wl_flush(ubi); -+@@ -150,7 +157,11 @@ -+ vol->updating = 0; -+ } -+ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ vol->upd_buf = kmalloc(ubi->leb_size, GFP_KERNEL); -++#else -+ vol->upd_buf = vmalloc(ubi->leb_size); -++#endif -+ if (!vol->upd_buf) -+ return -ENOMEM; -+ -+@@ -163,9 +174,46 @@ -+ } -+ -+ /** -++ * ubi_start_leb_change - start atomic LEB change. -++ * @ubi: UBI device description object -++ * @vol: volume description object -++ * @req: operation request -++ * -++ * This function starts atomic LEB change operation. Returns zero in case of -++ * success and a negative error code in case of failure. -++ */ -++int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, -++ const struct ubi_leb_change_req *req) -++{ -++ ubi_assert(!vol->updating && !vol->changing_leb); -++ -++ dbg_msg("start changing LEB %d:%d, %u bytes", -++ vol->vol_id, req->lnum, req->bytes); -++ if (req->bytes == 0) -++ return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0, -++ req->dtype); -++ -++ vol->upd_bytes = req->bytes; -++ vol->upd_received = 0; -++ vol->changing_leb = 1; -++ vol->ch_lnum = req->lnum; -++ vol->ch_dtype = req->dtype; -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ vol->upd_buf = kmalloc(req->bytes, GFP_KERNEL); -++#else -++ vol->upd_buf = vmalloc(req->bytes); -++#endif -++ if (!vol->upd_buf) -++ return -ENOMEM; -++ -++ return 0; -++} -++ -++/** -+ * write_leb - write update data. -+ * @ubi: UBI device description object -+- * @vol_id: volume ID -++ * @vol: volume description object -+ * @lnum: logical eraseblock number -+ * @buf: data to write -+ * @len: data size -+@@ -191,26 +239,22 @@ -+ * This function returns zero in case of success and a negative error code in -+ * case of failure. -+ */ -+-static int write_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf, -+- int len, int used_ebs) -++static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, -++ void *buf, int len, int used_ebs) -+ { -+- int err, l; -+- struct ubi_volume *vol = ubi->volumes[vol_id]; -++ int err; -+ -+ if (vol->vol_type == UBI_DYNAMIC_VOLUME) { -+- l = ALIGN(len, ubi->min_io_size); -+- memset(buf + len, 0xFF, l - len); -++ len = ALIGN(len, ubi->min_io_size); -++ memset(buf + len, 0xFF, len - len); -+ -+- l = ubi_calc_data_len(ubi, buf, l); -+- if (l == 0) { -++ len = ubi_calc_data_len(ubi, buf, len); -++ if (len == 0) { -+ dbg_msg("all %d bytes contain 0xFF - skip", len); -+ return 0; -+ } -+- if (len != l) -+- dbg_msg("skip last %d bytes (0xFF)", len - l); -+ -+- err = ubi_eba_write_leb(ubi, vol_id, lnum, buf, 0, l, -+- UBI_UNKNOWN); -++ err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len, UBI_UNKNOWN); -+ } else { -+ /* -+ * When writing static volume, and this is the last logical -+@@ -222,7 +266,7 @@ -+ * contain zeros, not random trash. -+ */ -+ memset(buf + len, 0, vol->usable_leb_size - len); -+- err = ubi_eba_write_leb_st(ubi, vol_id, lnum, buf, len, -++ err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len, -+ UBI_UNKNOWN, used_ebs); -+ } -+ -+@@ -236,16 +280,15 @@ -+ * @count: how much bytes to write -+ * -+ * This function writes more data to the volume which is being updated. It may -+- * be called arbitrary number of times until all of the update data arrive. -+- * This function returns %0 in case of success, number of bytes written during -+- * the last call if the whole volume update was successfully finished, and a -++ * be called arbitrary number of times until all the update data arriveis. This -++ * function returns %0 in case of success, number of bytes written during the -++ * last call if the whole volume update has been successfully finished, and a -+ * negative error code in case of failure. -+ */ -+-int ubi_more_update_data(struct ubi_device *ubi, int vol_id, -++int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, -+ const void __user *buf, int count) -+ { -+ uint64_t tmp; -+- struct ubi_volume *vol = ubi->volumes[vol_id]; -+ int lnum, offs, err = 0, len, to_write = count; -+ -+ dbg_msg("write %d of %lld bytes, %lld already passed", -+@@ -290,8 +333,8 @@ -+ * is the last chunk, it's time to flush the buffer. -+ */ -+ ubi_assert(flush_len <= vol->usable_leb_size); -+- err = write_leb(ubi, vol_id, lnum, vol->upd_buf, -+- flush_len, vol->upd_ebs); -++ err = write_leb(ubi, vol, lnum, vol->upd_buf, flush_len, -++ vol->upd_ebs); -+ if (err) -+ return err; -+ } -+@@ -312,37 +355,102 @@ -+ else -+ len = count; -+ -+- err = copy_from_user(vol->upd_buf, buf, len); -++ err= copy_from_user(&lnum, buf, sizeof(lnum)); -++ if (err) -++ return -EFAULT; -++ err = copy_from_user(vol->upd_buf, &(((char*)buf)[sizeof(unsigned int)]), len); -+ if (err) -+ return -EFAULT; -+ -+ if (len == vol->usable_leb_size || -+ vol->upd_received + len == vol->upd_bytes) { -+- err = write_leb(ubi, vol_id, lnum, vol->upd_buf, len, -+- vol->upd_ebs); -++ err = write_leb(ubi, vol, lnum, vol->upd_buf, -++ len, vol->upd_ebs); -+ if (err) -+ break; -+ } -+ -+ vol->upd_received += len; -+ count -= len; -+- lnum += 1; -++// lnum += 1; -+ buf += len; -+ } -+ -+ ubi_assert(vol->upd_received <= vol->upd_bytes); -+ if (vol->upd_received == vol->upd_bytes) { -+ /* The update is finished, clear the update marker */ -+- err = clear_update_marker(ubi, vol_id, vol->upd_bytes); -++ err = clear_update_marker(ubi, vol, vol->upd_bytes); -+ if (err) -+ return err; -+ err = ubi_wl_flush(ubi); -+ if (err == 0) { -++ vol->updating = 0; -+ err = to_write; -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(vol->upd_buf); -++#else -+ vfree(vol->upd_buf); -+- vol->updating = 0; -++#endif -+ } -+ } -+ -+ return err; -+ } -++ -++/** -++ * ubi_more_leb_change_data - accept more data for atomic LEB change. -++ * @vol: volume description object -++ * @buf: write data (user-space memory buffer) -++ * @count: how much bytes to write -++ * -++ * This function accepts more data to the volume which is being under the -++ * "atomic LEB change" operation. It may be called arbitrary number of times -++ * until all data arrives. This function returns %0 in case of success, number -++ * of bytes written during the last call if the whole "atomic LEB change" -++ * operation has been successfully finished, and a negative error code in case -++ * of failure. -++ */ -++int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol, -++ const void __user *buf, int count) -++{ -++ int err; -++ -++ dbg_msg("write %d of %lld bytes, %lld already passed", -++ count, vol->upd_bytes, vol->upd_received); -++ -++ if (ubi->ro_mode) -++ return -EROFS; -++ -++ if (vol->upd_received + count > vol->upd_bytes) -++ count = vol->upd_bytes - vol->upd_received; -++ -++ err = copy_from_user(vol->upd_buf + vol->upd_received, buf, count); -++ if (err) -++ return -EFAULT; -++ -++ vol->upd_received += count; -++ -++ if (vol->upd_received == vol->upd_bytes) { -++ int len = ALIGN((int)vol->upd_bytes, ubi->min_io_size); -++ -++ memset(vol->upd_buf + vol->upd_bytes, 0xFF, len - vol->upd_bytes); -++ len = ubi_calc_data_len(ubi, vol->upd_buf, len); -++ err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum, -++ vol->upd_buf, len, UBI_UNKNOWN); -++ if (err) -++ return err; -++ } -++ -++ ubi_assert(vol->upd_received <= vol->upd_bytes); -++ if (vol->upd_received == vol->upd_bytes) { -++ vol->changing_leb = 0; -++ err = count; -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(vol->upd_buf); -++#else -++ vfree(vol->upd_buf); -++#endif -++ } -++ -++ return err; -++} -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/vmt.c linux-2.6.24.7/drivers/mtd/ubi/vmt.c -+--- linux-2.6.24.7.old/drivers/mtd/ubi/vmt.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/vmt.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -63,21 +63,30 @@ -+ * B. process 2 removes volume Y; -+ * C. process 1 starts reading the //class/ubi/ubiX_Y/reserved_ebs file; -+ * -+- * What we want to do in a situation like that is to return error when the file -+- * is read. This is done by means of the 'removed' flag and the 'vol_lock' of -+- * the UBI volume description object. -++ * In this situation, this function will return %-ENODEV because it will find -++ * out that the volume was removed from the @ubi->volumes array. -+ */ -+ static ssize_t vol_attribute_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+ { -+ int ret; -+ struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); -++ struct ubi_device *ubi; -+ -+- spin_lock(&vol->ubi->volumes_lock); -+- if (vol->removed) { -+- spin_unlock(&vol->ubi->volumes_lock); -++ ubi = ubi_get_device(vol->ubi->ubi_num); -++ if (!ubi) -++ return -ENODEV; -++ -++ spin_lock(&ubi->volumes_lock); -++ if (!ubi->volumes[vol->vol_id]) { -++ spin_unlock(&ubi->volumes_lock); -++ ubi_put_device(ubi); -+ return -ENODEV; -+ } -++ /* Take a reference to prevent volume removal */ -++ vol->ref_count += 1; -++ spin_unlock(&ubi->volumes_lock); -++ -+ if (attr == &attr_vol_reserved_ebs) -+ ret = sprintf(buf, "%d\n", vol->reserved_pebs); -+ else if (attr == &attr_vol_type) { -+@@ -94,15 +103,22 @@ -+ ret = sprintf(buf, "%d\n", vol->corrupted); -+ else if (attr == &attr_vol_alignment) -+ ret = sprintf(buf, "%d\n", vol->alignment); -+- else if (attr == &attr_vol_usable_eb_size) { -++ else if (attr == &attr_vol_usable_eb_size) -+ ret = sprintf(buf, "%d\n", vol->usable_leb_size); -+- } else if (attr == &attr_vol_data_bytes) -++ else if (attr == &attr_vol_data_bytes) -+ ret = sprintf(buf, "%lld\n", vol->used_bytes); -+ else if (attr == &attr_vol_upd_marker) -+ ret = sprintf(buf, "%d\n", vol->upd_marker); -+ else -+- BUG(); -+- spin_unlock(&vol->ubi->volumes_lock); -++ /* This must be a bug */ -++ ret = -EINVAL; -++ -++ /* We've done the operation, drop volume and UBI device references */ -++ spin_lock(&ubi->volumes_lock); -++ vol->ref_count -= 1; -++ ubi_assert(vol->ref_count >= 0); -++ spin_unlock(&ubi->volumes_lock); -++ ubi_put_device(ubi); -+ return ret; -+ } -+ -+@@ -110,7 +126,7 @@ -+ static void vol_release(struct device *dev) -+ { -+ struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); -+- ubi_assert(vol->removed); -++ -+ kfree(vol); -+ } -+ -+@@ -152,9 +168,7 @@ -+ if (err) -+ return err; -+ err = device_create_file(&vol->dev, &attr_vol_upd_marker); -+- if (err) -+- return err; -+- return 0; -++ return err; -+ } -+ -+ /** -+@@ -180,16 +194,18 @@ -+ * @req: volume creation request -+ * -+ * This function creates volume described by @req. If @req->vol_id id -+- * %UBI_VOL_NUM_AUTO, this function automatically assigne ID to the new volume -++ * %UBI_VOL_NUM_AUTO, this function automatically assign ID to the new volume -+ * and saves it in @req->vol_id. Returns zero in case of success and a negative -+- * error code in case of failure. -++ * error code in case of failure. Note, the caller has to have the -++ * @ubi->volumes_mutex locked. -+ */ -+ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) -+ { -+- int i, err, vol_id = req->vol_id; -++ int i, err, vol_id = req->vol_id, dont_free = 0; -+ struct ubi_volume *vol; -+ struct ubi_vtbl_record vtbl_rec; -+ uint64_t bytes; -++ dev_t dev; -+ -+ if (ubi->ro_mode) -+ return -EROFS; -+@@ -199,7 +215,6 @@ -+ return -ENOMEM; -+ -+ spin_lock(&ubi->volumes_lock); -+- -+ if (vol_id == UBI_VOL_NUM_AUTO) { -+ /* Find unused volume ID */ -+ dbg_msg("search for vacant volume ID"); -+@@ -252,6 +267,7 @@ -+ } -+ ubi->avail_pebs -= vol->reserved_pebs; -+ ubi->rsvd_pebs += vol->reserved_pebs; -++ spin_unlock(&ubi->volumes_lock); -+ -+ vol->vol_id = vol_id; -+ vol->alignment = req->alignment; -+@@ -259,10 +275,7 @@ -+ vol->vol_type = req->vol_type; -+ vol->name_len = req->name_len; -+ memcpy(vol->name, req->name, vol->name_len + 1); -+- vol->exclusive = 1; -+ vol->ubi = ubi; -+- ubi->volumes[vol_id] = vol; -+- spin_unlock(&ubi->volumes_lock); -+ -+ /* -+ * Finish all pending erases because there may be some LEBs belonging -+@@ -299,9 +312,10 @@ -+ /* Register character device for the volume */ -+ cdev_init(&vol->cdev, &ubi_vol_cdev_operations); -+ vol->cdev.owner = THIS_MODULE; -+- err = cdev_add(&vol->cdev, MKDEV(ubi->major, vol_id + 1), 1); -++ dev = MKDEV(MAJOR(ubi->cdev.dev), vol_id + 1); -++ err = cdev_add(&vol->cdev, dev, 1); -+ if (err) { -+- ubi_err("cannot add character device for volume %d", vol_id); -++ ubi_err("cannot add character device"); -+ goto out_mapping; -+ } -+ -+@@ -311,12 +325,15 @@ -+ -+ vol->dev.release = vol_release; -+ vol->dev.parent = &ubi->dev; -+- vol->dev.devt = MKDEV(ubi->major, vol->vol_id + 1); -++ vol->dev.devt = dev; -+ vol->dev.class = ubi_class; -++ -+ sprintf(&vol->dev.bus_id[0], "%s_%d", ubi->ubi_name, vol->vol_id); -+ err = device_register(&vol->dev); -+- if (err) -++ if (err) { -++ ubi_err("cannot register device"); -+ goto out_gluebi; -++ } -+ -+ err = volume_sysfs_init(ubi, vol); -+ if (err) -+@@ -339,15 +356,29 @@ -+ goto out_sysfs; -+ -+ spin_lock(&ubi->volumes_lock); -++ ubi->volumes[vol_id] = vol; -+ ubi->vol_count += 1; -+- vol->exclusive = 0; -+ spin_unlock(&ubi->volumes_lock); -+ -+ paranoid_check_volumes(ubi); -+ return 0; -+ -++out_sysfs: -++ /* -++ * We have registered our device, we should not free the volume* -++ * description object in this function in case of an error - it is -++ * freed by the release function. -++ * -++ * Get device reference to prevent the release function from being -++ * called just after sysfs has been closed. -++ */ -++ dont_free = 1; -++ get_device(&vol->dev); -++ volume_sysfs_close(vol); -+ out_gluebi: -+- err = ubi_destroy_gluebi(vol); -++ if (ubi_destroy_gluebi(vol)) -++ dbg_err("cannot destroy gluebi for volume %d:%d", -++ ubi->ubi_num, vol_id); -+ out_cdev: -+ cdev_del(&vol->cdev); -+ out_mapping: -+@@ -356,26 +387,13 @@ -+ spin_lock(&ubi->volumes_lock); -+ ubi->rsvd_pebs -= vol->reserved_pebs; -+ ubi->avail_pebs += vol->reserved_pebs; -+- ubi->volumes[vol_id] = NULL; -+ out_unlock: -+ spin_unlock(&ubi->volumes_lock); -+- kfree(vol); -+- return err; -+- -+- /* -+- * We are registered, so @vol is destroyed in the release function and -+- * we have to de-initialize differently. -+- */ -+-out_sysfs: -+- err = ubi_destroy_gluebi(vol); -+- cdev_del(&vol->cdev); -+- kfree(vol->eba_tbl); -+- spin_lock(&ubi->volumes_lock); -+- ubi->rsvd_pebs -= vol->reserved_pebs; -+- ubi->avail_pebs += vol->reserved_pebs; -+- ubi->volumes[vol_id] = NULL; -+- spin_unlock(&ubi->volumes_lock); -+- volume_sysfs_close(vol); -++ if (dont_free) -++ put_device(&vol->dev); -++ else -++ kfree(vol); -++ ubi_err("cannot create volume %d, error %d", vol_id, err); -+ return err; -+ } -+ -+@@ -385,7 +403,8 @@ -+ * -+ * This function removes volume described by @desc. The volume has to be opened -+ * in "exclusive" mode. Returns zero in case of success and a negative error -+- * code in case of failure. -++ * code in case of failure. The caller has to have the @ubi->volumes_mutex -++ * locked. -+ */ -+ int ubi_remove_volume(struct ubi_volume_desc *desc) -+ { -+@@ -400,30 +419,36 @@ -+ if (ubi->ro_mode) -+ return -EROFS; -+ -++ spin_lock(&ubi->volumes_lock); -++ if (vol->ref_count > 1) { -++ /* -++ * The volume is busy, probably someone is reading one of its -++ * sysfs files. -++ */ -++ err = -EBUSY; -++ goto out_unlock; -++ } -++ ubi->volumes[vol_id] = NULL; -++ spin_unlock(&ubi->volumes_lock); -++ -+ err = ubi_destroy_gluebi(vol); -+ if (err) -+- return err; -++ goto out_err; -+ -+ err = ubi_change_vtbl_record(ubi, vol_id, NULL); -+ if (err) -+- return err; -++ goto out_err; -+ -+ for (i = 0; i < vol->reserved_pebs; i++) { -+- err = ubi_eba_unmap_leb(ubi, vol_id, i); -++ err = ubi_eba_unmap_leb(ubi, vol, i); -+ if (err) -+- return err; -++ goto out_err; -+ } -+ -+- spin_lock(&ubi->volumes_lock); -+- vol->removed = 1; -+- ubi->volumes[vol_id] = NULL; -+- spin_unlock(&ubi->volumes_lock); -+- -+ kfree(vol->eba_tbl); -+ vol->eba_tbl = NULL; -+ cdev_del(&vol->cdev); -+ volume_sysfs_close(vol); -+- kfree(desc); -+ -+ spin_lock(&ubi->volumes_lock); -+ ubi->rsvd_pebs -= reserved_pebs; -+@@ -441,8 +466,15 @@ -+ spin_unlock(&ubi->volumes_lock); -+ -+ paranoid_check_volumes(ubi); -+- module_put(THIS_MODULE); -+ return 0; -++ -++out_err: -++ ubi_err("cannot remove volume %d, error %d", vol_id, err); -++ spin_lock(&ubi->volumes_lock); -++ ubi->volumes[vol_id] = vol; -++out_unlock: -++ spin_unlock(&ubi->volumes_lock); -++ return err; -+ } -+ -+ /** -+@@ -450,8 +482,9 @@ -+ * @desc: volume descriptor -+ * @reserved_pebs: new size in physical eraseblocks -+ * -+- * This function returns zero in case of success, and a negative error code in -+- * case of failure. -++ * This function re-sizes the volume and returns zero in case of success, and a -++ * negative error code in case of failure. The caller has to have the -++ * @ubi->volumes_mutex locked. -+ */ -+ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) -+ { -+@@ -466,8 +499,6 @@ -+ -+ dbg_msg("re-size volume %d to from %d to %d PEBs", -+ vol_id, vol->reserved_pebs, reserved_pebs); -+- ubi_assert(desc->mode == UBI_EXCLUSIVE); -+- ubi_assert(vol == ubi->volumes[vol_id]); -+ -+ if (vol->vol_type == UBI_STATIC_VOLUME && -+ reserved_pebs < vol->used_ebs) { -+@@ -487,6 +518,14 @@ -+ for (i = 0; i < reserved_pebs; i++) -+ new_mapping[i] = UBI_LEB_UNMAPPED; -+ -++ spin_lock(&ubi->volumes_lock); -++ if (vol->ref_count > 1) { -++ spin_unlock(&ubi->volumes_lock); -++ err = -EBUSY; -++ goto out_free; -++ } -++ spin_unlock(&ubi->volumes_lock); -++ -+ /* Reserve physical eraseblocks */ -+ pebs = reserved_pebs - vol->reserved_pebs; -+ if (pebs > 0) { -+@@ -516,7 +555,7 @@ -+ -+ if (pebs < 0) { -+ for (i = 0; i < -pebs; i++) { -+- err = ubi_eba_unmap_leb(ubi, vol_id, reserved_pebs + i); -++ err = ubi_eba_unmap_leb(ubi, vol, reserved_pebs + i); -+ if (err) -+ goto out_acc; -+ } -+@@ -565,27 +604,28 @@ -+ /** -+ * ubi_add_volume - add volume. -+ * @ubi: UBI device description object -+- * @vol_id: volume ID -++ * @vol: volume description object -+ * -+- * This function adds an existin volume and initializes all its data -+- * structures. Returnes zero in case of success and a negative error code in -++ * This function adds an existing volume and initializes all its data -++ * structures. Returns zero in case of success and a negative error code in -+ * case of failure. -+ */ -+-int ubi_add_volume(struct ubi_device *ubi, int vol_id) -++int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol) -+ { -+- int err; -+- struct ubi_volume *vol = ubi->volumes[vol_id]; -++ int err, vol_id = vol->vol_id; -++ dev_t dev; -+ -+ dbg_msg("add volume %d", vol_id); -+ ubi_dbg_dump_vol_info(vol); -+- ubi_assert(vol); -+ -+ /* Register character device for the volume */ -+ cdev_init(&vol->cdev, &ubi_vol_cdev_operations); -+ vol->cdev.owner = THIS_MODULE; -+- err = cdev_add(&vol->cdev, MKDEV(ubi->major, vol->vol_id + 1), 1); -++ dev = MKDEV(MAJOR(ubi->cdev.dev), vol->vol_id + 1); -++ err = cdev_add(&vol->cdev, dev, 1); -+ if (err) { -+- ubi_err("cannot add character device for volume %d", vol_id); -++ ubi_err("cannot add character device for volume %d, error %d", -++ vol_id, err); -+ return err; -+ } -+ -+@@ -595,7 +635,7 @@ -+ -+ vol->dev.release = vol_release; -+ vol->dev.parent = &ubi->dev; -+- vol->dev.devt = MKDEV(ubi->major, vol->vol_id + 1); -++ vol->dev.devt = dev; -+ vol->dev.class = ubi_class; -+ sprintf(&vol->dev.bus_id[0], "%s_%d", ubi->ubi_name, vol->vol_id); -+ err = device_register(&vol->dev); -+@@ -623,22 +663,19 @@ -+ /** -+ * ubi_free_volume - free volume. -+ * @ubi: UBI device description object -+- * @vol_id: volume ID -++ * @vol: volume description object -+ * -+- * This function frees all resources for volume @vol_id but does not remove it. -++ * This function frees all resources for volume @vol but does not remove it. -+ * Used only when the UBI device is detached. -+ */ -+-void ubi_free_volume(struct ubi_device *ubi, int vol_id) -++void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol) -+ { -+ int err; -+- struct ubi_volume *vol = ubi->volumes[vol_id]; -+ -+- dbg_msg("free volume %d", vol_id); -+- ubi_assert(vol); -++ dbg_msg("free volume %d", vol->vol_id); -+ -+- vol->removed = 1; -++ ubi->volumes[vol->vol_id] = NULL; -+ err = ubi_destroy_gluebi(vol); -+- ubi->volumes[vol_id] = NULL; -+ cdev_del(&vol->cdev); -+ volume_sysfs_close(vol); -+ } -+@@ -708,11 +745,6 @@ -+ goto fail; -+ } -+ -+- if (vol->upd_marker != 0 && vol->upd_marker != 1) { -+- ubi_err("bad upd_marker"); -+- goto fail; -+- } -+- -+ if (vol->upd_marker && vol->corrupted) { -+ dbg_err("update marker and corrupted simultaneously"); -+ goto fail; -+@@ -747,7 +779,7 @@ -+ -+ n = (long long)vol->used_ebs * vol->usable_leb_size; -+ if (vol->vol_type == UBI_DYNAMIC_VOLUME) { -+- if (vol->corrupted != 0) { -++ if (vol->corrupted) { -+ ubi_err("corrupted dynamic volume"); -+ goto fail; -+ } -+@@ -764,10 +796,6 @@ -+ goto fail; -+ } -+ } else { -+- if (vol->corrupted != 0 && vol->corrupted != 1) { -+- ubi_err("bad corrupted"); -+- goto fail; -+- } -+ if (vol->used_ebs < 0 || vol->used_ebs > vol->reserved_pebs) { -+ ubi_err("bad used_ebs"); -+ goto fail; -+@@ -820,9 +848,7 @@ -+ { -+ int i; -+ -+- mutex_lock(&ubi->vtbl_mutex); -+ for (i = 0; i < ubi->vtbl_slots; i++) -+ paranoid_check_volume(ubi, i); -+- mutex_unlock(&ubi->vtbl_mutex); -+ } -+ #endif -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/vtbl.c linux-2.6.24.7/drivers/mtd/ubi/vtbl.c -+--- linux-2.6.24.7.old/drivers/mtd/ubi/vtbl.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/vtbl.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -86,8 +86,10 @@ -+ { -+ int i, err; -+ uint32_t crc; -++ struct ubi_volume *layout_vol; -+ -+ ubi_assert(idx >= 0 && idx < ubi->vtbl_slots); -++ layout_vol = ubi->volumes[vol_id2idx(ubi, UBI_LAYOUT_VOLUME_ID)]; -+ -+ if (!vtbl_rec) -+ vtbl_rec = &empty_vtbl_record; -+@@ -96,31 +98,25 @@ -+ vtbl_rec->crc = cpu_to_be32(crc); -+ } -+ -+- mutex_lock(&ubi->vtbl_mutex); -+ memcpy(&ubi->vtbl[idx], vtbl_rec, sizeof(struct ubi_vtbl_record)); -+ for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) { -+- err = ubi_eba_unmap_leb(ubi, UBI_LAYOUT_VOL_ID, i); -+- if (err) { -+- mutex_unlock(&ubi->vtbl_mutex); -++ err = ubi_eba_unmap_leb(ubi, layout_vol, i); -++ if (err) -+ return err; -+- } -+- err = ubi_eba_write_leb(ubi, UBI_LAYOUT_VOL_ID, i, ubi->vtbl, 0, -++ -++ err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0, -+ ubi->vtbl_size, UBI_LONGTERM); -+- if (err) { -+- mutex_unlock(&ubi->vtbl_mutex); -++ if (err) -+ return err; -+- } -+ } -+ -+ paranoid_vtbl_check(ubi); -+- mutex_unlock(&ubi->vtbl_mutex); -+- return ubi_wl_flush(ubi); -++ return 0; -+ } -+ -+ /** -+- * vol_til_check - check if volume table is not corrupted and contains sensible -+- * data. -+- * -++ * vtbl_check - check if volume table is not corrupted and contains sensible -++ * data. -+ * @ubi: UBI device description object -+ * @vtbl: volume table -+ * -+@@ -273,7 +269,7 @@ -+ * this volume table copy was found during scanning. It has to be wiped -+ * out. -+ */ -+- sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOL_ID); -++ sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOLUME_ID); -+ if (sv) -+ old_seb = ubi_scan_find_seb(sv, copy); -+ -+@@ -285,7 +281,7 @@ -+ } -+ -+ vid_hdr->vol_type = UBI_VID_DYNAMIC; -+- vid_hdr->vol_id = cpu_to_be32(UBI_LAYOUT_VOL_ID); -++ vid_hdr->vol_id = cpu_to_be32(UBI_LAYOUT_VOLUME_ID); -+ vid_hdr->compat = UBI_LAYOUT_VOLUME_COMPAT; -+ vid_hdr->data_size = vid_hdr->used_ebs = -+ vid_hdr->data_pad = cpu_to_be32(0); -+@@ -378,7 +374,11 @@ -+ -+ /* Read both LEB 0 and LEB 1 into memory */ -+ ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) { -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ leb[seb->lnum] = kmalloc(ubi->vtbl_size, GFP_KERNEL); -++#else -+ leb[seb->lnum] = vmalloc(ubi->vtbl_size); -++#endif -+ if (!leb[seb->lnum]) { -+ err = -ENOMEM; -+ goto out_free; -+@@ -414,7 +414,11 @@ -+ } -+ -+ /* Both LEB 1 and LEB 2 are OK and consistent */ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(leb[1]); -++#else -+ vfree(leb[1]); -++#endif -+ return leb[0]; -+ } else { -+ /* LEB 0 is corrupted or does not exist */ -+@@ -434,14 +438,23 @@ -+ if (err) -+ goto out_free; -+ ubi_msg("volume table was restored"); -+- -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(leb[0]); -++#else -+ vfree(leb[0]); -++#endif -+ return leb[1]; -+ } -+ -+ out_free: -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(leb[0]); -++ kfree(leb[1]); -++#else -+ vfree(leb[0]); -+ vfree(leb[1]); -++#endif -++ -+ return ERR_PTR(err); -+ } -+ -+@@ -459,7 +472,11 @@ -+ int i; -+ struct ubi_vtbl_record *vtbl; -+ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ vtbl = kmalloc(ubi->vtbl_size, GFP_KERNEL); -++#else -+ vtbl = vmalloc(ubi->vtbl_size); -++#endif -+ if (!vtbl) -+ return ERR_PTR(-ENOMEM); -+ memset(vtbl, 0, ubi->vtbl_size); -+@@ -472,7 +489,11 @@ -+ -+ err = create_vtbl(ubi, si, i, vtbl); -+ if (err) { -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(vtbl); -++#else -+ vfree(vtbl); -++#endif -+ return ERR_PTR(err); -+ } -+ } -+@@ -518,6 +539,18 @@ -+ vol->name[vol->name_len] = '\0'; -+ vol->vol_id = i; -+ -++ if (vtbl[i].flags & UBI_VTBL_AUTORESIZE_FLG) { -++ /* Auto re-size flag may be set only for one volume */ -++ if (ubi->autoresize_vol_id != -1) { -++ ubi_err("more then one auto-resize volume (%d " -++ "and %d)", ubi->autoresize_vol_id, i); -++ kfree(vol); -++ return -EINVAL; -++ } -++ -++ ubi->autoresize_vol_id = i; -++ } -++ -+ ubi_assert(!ubi->volumes[i]); -+ ubi->volumes[i] = vol; -+ ubi->vol_count += 1; -+@@ -568,6 +601,7 @@ -+ vol->last_eb_bytes = sv->last_data_size; -+ } -+ -++ /* And add the layout volume */ -+ vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL); -+ if (!vol) -+ return -ENOMEM; -+@@ -582,7 +616,8 @@ -+ vol->last_eb_bytes = vol->reserved_pebs; -+ vol->used_bytes = -+ (long long)vol->used_ebs * (ubi->leb_size - vol->data_pad); -+- vol->vol_id = UBI_LAYOUT_VOL_ID; -++ vol->vol_id = UBI_LAYOUT_VOLUME_ID; -++ vol->ref_count = 1; -+ -+ ubi_assert(!ubi->volumes[i]); -+ ubi->volumes[vol_id2idx(ubi, vol->vol_id)] = vol; -+@@ -734,7 +769,7 @@ -+ ubi->vtbl_size = ubi->vtbl_slots * UBI_VTBL_RECORD_SIZE; -+ ubi->vtbl_size = ALIGN(ubi->vtbl_size, ubi->min_io_size); -+ -+- sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOL_ID); -++ sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOLUME_ID); -+ if (!sv) { -+ /* -+ * No logical eraseblocks belonging to the layout volume were -+@@ -786,7 +821,11 @@ -+ return 0; -+ -+ out_free: -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(ubi->vtbl); -++#else -+ vfree(ubi->vtbl); -++#endif -+ for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) -+ if (ubi->volumes[i]) { -+ kfree(ubi->volumes[i]); -+diff -urN linux-2.6.24.7.old/drivers/mtd/ubi/wl.c linux-2.6.24.7/drivers/mtd/ubi/wl.c -+--- linux-2.6.24.7.old/drivers/mtd/ubi/wl.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/mtd/ubi/wl.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -117,21 +117,6 @@ -+ #define WL_MAX_FAILURES 32 -+ -+ /** -+- * struct ubi_wl_entry - wear-leveling entry. -+- * @rb: link in the corresponding RB-tree -+- * @ec: erase counter -+- * @pnum: physical eraseblock number -+- * -+- * Each physical eraseblock has a corresponding &struct wl_entry object which -+- * may be kept in different RB-trees. -+- */ -+-struct ubi_wl_entry { -+- struct rb_node rb; -+- int ec; -+- int pnum; -+-}; -+- -+-/** -+ * struct ubi_wl_prot_entry - PEB protection entry. -+ * @rb_pnum: link in the @wl->prot.pnum RB-tree -+ * @rb_aec: link in the @wl->prot.aec RB-tree -+@@ -216,9 +201,6 @@ -+ #define paranoid_check_in_wl_tree(e, root) -+ #endif -+ -+-/* Slab cache for wear-leveling entries */ -+-static struct kmem_cache *wl_entries_slab; -+- -+ /** -+ * wl_tree_add - add a wear-leveling entry to a WL RB-tree. -+ * @e: the wear-leveling entry to add -+@@ -267,15 +249,26 @@ -+ int err; -+ struct ubi_work *wrk; -+ -+- spin_lock(&ubi->wl_lock); -++ cond_resched(); -+ -++ /* -++ * @ubi->work_sem is used to synchronize with the workers. Workers take -++ * it in read mode, so many of them may be doing works at a time. But -++ * the queue flush code has to be sure the whole queue of works is -++ * done, and it takes the mutex in write mode. -++ */ -++ down_read(&ubi->work_sem); -++ spin_lock(&ubi->wl_lock); -+ if (list_empty(&ubi->works)) { -+ spin_unlock(&ubi->wl_lock); -++ up_read(&ubi->work_sem); -+ return 0; -+ } -+ -+ wrk = list_entry(ubi->works.next, struct ubi_work, list); -+ list_del(&wrk->list); -++ ubi->works_count -= 1; -++ ubi_assert(ubi->works_count >= 0); -+ spin_unlock(&ubi->wl_lock); -+ -+ /* -+@@ -286,11 +279,8 @@ -+ err = wrk->func(ubi, wrk, 0); -+ if (err) -+ ubi_err("work failed with error code %d", err); -++ up_read(&ubi->work_sem); -+ -+- spin_lock(&ubi->wl_lock); -+- ubi->works_count -= 1; -+- ubi_assert(ubi->works_count >= 0); -+- spin_unlock(&ubi->wl_lock); -+ return err; -+ } -+ -+@@ -549,8 +539,12 @@ -+ * prot_tree_del - remove a physical eraseblock from the protection trees -+ * @ubi: UBI device description object -+ * @pnum: the physical eraseblock to remove -++ * -++ * This function returns PEB @pnum from the protection trees and returns zero -++ * in case of success and %-ENODEV if the PEB was not found in the protection -++ * trees. -+ */ -+-static void prot_tree_del(struct ubi_device *ubi, int pnum) -++static int prot_tree_del(struct ubi_device *ubi, int pnum) -+ { -+ struct rb_node *p; -+ struct ubi_wl_prot_entry *pe = NULL; -+@@ -561,7 +555,7 @@ -+ pe = rb_entry(p, struct ubi_wl_prot_entry, rb_pnum); -+ -+ if (pnum == pe->e->pnum) -+- break; -++ goto found; -+ -+ if (pnum < pe->e->pnum) -+ p = p->rb_left; -+@@ -569,10 +563,14 @@ -+ p = p->rb_right; -+ } -+ -++ return -ENODEV; -++ -++found: -+ ubi_assert(pe->e->pnum == pnum); -+ rb_erase(&pe->rb_aec, &ubi->prot.aec); -+ rb_erase(&pe->rb_pnum, &ubi->prot.pnum); -+ kfree(pe); -++ return 0; -+ } -+ -+ /** -+@@ -744,7 +742,8 @@ -+ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, -+ int cancel) -+ { -+- int err, put = 0; -++ int err, put = 0, scrubbing = 0, protect = 0; -++ struct ubi_wl_prot_entry *uninitialized_var(pe); -+ struct ubi_wl_entry *e1, *e2; -+ struct ubi_vid_hdr *vid_hdr; -+ -+@@ -757,21 +756,17 @@ -+ if (!vid_hdr) -+ return -ENOMEM; -+ -++ mutex_lock(&ubi->move_mutex); -+ spin_lock(&ubi->wl_lock); -++ ubi_assert(!ubi->move_from && !ubi->move_to); -++ ubi_assert(!ubi->move_to_put); -+ -+- /* -+- * Only one WL worker at a time is supported at this implementation, so -+- * make sure a PEB is not being moved already. -+- */ -+- if (ubi->move_to || !ubi->free.rb_node || -++ if (!ubi->free.rb_node || -+ (!ubi->used.rb_node && !ubi->scrub.rb_node)) { -+ /* -+- * Only one WL worker at a time is supported at this -+- * implementation, so if a LEB is already being moved, cancel. -+- * -+- * No free physical eraseblocks? Well, we cancel wear-leveling -+- * then. It will be triggered again when a free physical -+- * eraseblock appears. -++ * No free physical eraseblocks? Well, they must be waiting in -++ * the queue to be erased. Cancel movement - it will be -++ * triggered again when a free physical eraseblock appears. -+ * -+ * No used physical eraseblocks? They must be temporarily -+ * protected from being moved. They will be moved to the -+@@ -780,10 +775,7 @@ -+ */ -+ dbg_wl("cancel WL, a list is empty: free %d, used %d", -+ !ubi->free.rb_node, !ubi->used.rb_node); -+- ubi->wl_scheduled = 0; -+- spin_unlock(&ubi->wl_lock); -+- ubi_free_vid_hdr(ubi, vid_hdr); -+- return 0; -++ goto out_cancel; -+ } -+ -+ if (!ubi->scrub.rb_node) { -+@@ -798,27 +790,24 @@ -+ if (!(e2->ec - e1->ec >= UBI_WL_THRESHOLD)) { -+ dbg_wl("no WL needed: min used EC %d, max free EC %d", -+ e1->ec, e2->ec); -+- ubi->wl_scheduled = 0; -+- spin_unlock(&ubi->wl_lock); -+- ubi_free_vid_hdr(ubi, vid_hdr); -+- return 0; -++ goto out_cancel; -+ } -+ paranoid_check_in_wl_tree(e1, &ubi->used); -+ rb_erase(&e1->rb, &ubi->used); -+ dbg_wl("move PEB %d EC %d to PEB %d EC %d", -+ e1->pnum, e1->ec, e2->pnum, e2->ec); -+ } else { -++ /* Perform scrubbing */ -++ scrubbing = 1; -+ e1 = rb_entry(rb_first(&ubi->scrub), struct ubi_wl_entry, rb); -+ e2 = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF); -+ paranoid_check_in_wl_tree(e1, &ubi->scrub); -+- rb_erase(&e1->rb, &ubi->scrub); -++ rb_erase(&e1->rb, &ubi->scrub); -+ dbg_wl("scrub PEB %d to PEB %d", e1->pnum, e2->pnum); -+ } -+ -+ paranoid_check_in_wl_tree(e2, &ubi->free); -+ rb_erase(&e2->rb, &ubi->free); -+- ubi_assert(!ubi->move_from && !ubi->move_to); -+- ubi_assert(!ubi->move_to_put && !ubi->move_from_put); -+ ubi->move_from = e1; -+ ubi->move_to = e2; -+ spin_unlock(&ubi->wl_lock); -+@@ -828,6 +817,10 @@ -+ * We so far do not know which logical eraseblock our physical -+ * eraseblock (@e1) belongs to. We have to read the volume identifier -+ * header first. -++ * -++ * Note, we are protected from this PEB being unmapped and erased. The -++ * 'ubi_wl_put_peb()' would wait for moving to be finished if the PEB -++ * which is being moved was unmapped. -+ */ -+ -+ err = ubi_io_read_vid_hdr(ubi, e1->pnum, vid_hdr, 0); -+@@ -842,32 +835,51 @@ -+ * likely have the VID header in place. -+ */ -+ dbg_wl("PEB %d has no VID header", e1->pnum); -+- err = 0; -+- } else { -+- ubi_err("error %d while reading VID header from PEB %d", -+- err, e1->pnum); -+- if (err > 0) -+- err = -EIO; -++ goto out_not_moved; -+ } -+- goto error; -++ -++ ubi_err("error %d while reading VID header from PEB %d", -++ err, e1->pnum); -++ if (err > 0) -++ err = -EIO; -++ goto out_error; -+ } -+ -+ err = ubi_eba_copy_leb(ubi, e1->pnum, e2->pnum, vid_hdr); -+ if (err) { -+- if (err == UBI_IO_BITFLIPS) -+- err = 0; -+- goto error; -++ -++ if (err < 0) -++ goto out_error; -++ if (err == 1) -++ goto out_not_moved; -++ -++ /* -++ * For some reason the LEB was not moved - it might be because -++ * the volume is being deleted. We should prevent this PEB from -++ * being selected for wear-levelling movement for some "time", -++ * so put it to the protection tree. -++ */ -++ -++ dbg_wl("cancelled moving PEB %d", e1->pnum); -++ pe = kmalloc(sizeof(struct ubi_wl_prot_entry), GFP_NOFS); -++ if (!pe) { -++ err = -ENOMEM; -++ goto out_error; -++ } -++ -++ protect = 1; -+ } -+ -+ ubi_free_vid_hdr(ubi, vid_hdr); -+ spin_lock(&ubi->wl_lock); -++ if (protect) -++ prot_tree_add(ubi, e1, pe, protect); -+ if (!ubi->move_to_put) -+ wl_tree_add(e2, &ubi->used); -+ else -+ put = 1; -+ ubi->move_from = ubi->move_to = NULL; -+- ubi->move_from_put = ubi->move_to_put = 0; -+- ubi->wl_scheduled = 0; -++ ubi->move_to_put = ubi->wl_scheduled = 0; -+ spin_unlock(&ubi->wl_lock); -+ -+ if (put) { -+@@ -877,62 +889,67 @@ -+ */ -+ dbg_wl("PEB %d was put meanwhile, erase", e2->pnum); -+ err = schedule_erase(ubi, e2, 0); -+- if (err) { -+- kmem_cache_free(wl_entries_slab, e2); -+- ubi_ro_mode(ubi); -+- } -++ if (err) -++ goto out_error; -+ } -+ -+- err = schedule_erase(ubi, e1, 0); -+- if (err) { -+- kmem_cache_free(wl_entries_slab, e1); -+- ubi_ro_mode(ubi); -++ if (!protect) { -++ err = schedule_erase(ubi, e1, 0); -++ if (err) -++ goto out_error; -+ } -+ -++ -+ dbg_wl("done"); -+- return err; -++ mutex_unlock(&ubi->move_mutex); -++ return 0; -+ -+ /* -+- * Some error occurred. @e1 was not changed, so return it back. @e2 -+- * might be changed, schedule it for erasure. -++ * For some reasons the LEB was not moved, might be an error, might be -++ * something else. @e1 was not changed, so return it back. @e2 might -++ * be changed, schedule it for erasure. -+ */ -+-error: -+- if (err) -+- dbg_wl("error %d occurred, cancel operation", err); -+- ubi_assert(err <= 0); -+- -++out_not_moved: -+ ubi_free_vid_hdr(ubi, vid_hdr); -+ spin_lock(&ubi->wl_lock); -+- ubi->wl_scheduled = 0; -+- if (ubi->move_from_put) -+- put = 1; -++ if (scrubbing) -++ wl_tree_add(e1, &ubi->scrub); -+ else -+ wl_tree_add(e1, &ubi->used); -+ ubi->move_from = ubi->move_to = NULL; -+- ubi->move_from_put = ubi->move_to_put = 0; -++ ubi->move_to_put = ubi->wl_scheduled = 0; -+ spin_unlock(&ubi->wl_lock); -+ -+- if (put) { -+- /* -+- * Well, the target PEB was put meanwhile, schedule it for -+- * erasure. -+- */ -+- dbg_wl("PEB %d was put meanwhile, erase", e1->pnum); -+- err = schedule_erase(ubi, e1, 0); -+- if (err) { -+- kmem_cache_free(wl_entries_slab, e1); -+- ubi_ro_mode(ubi); -+- } -+- } -+- -+ err = schedule_erase(ubi, e2, 0); -+- if (err) { -+- kmem_cache_free(wl_entries_slab, e2); -+- ubi_ro_mode(ubi); -+- } -++ if (err) -++ goto out_error; -++ -++ mutex_unlock(&ubi->move_mutex); -++ return 0; -++ -++out_error: -++ ubi_err("error %d while moving PEB %d to PEB %d", -++ err, e1->pnum, e2->pnum); -++ -++ ubi_free_vid_hdr(ubi, vid_hdr); -++ spin_lock(&ubi->wl_lock); -++ ubi->move_from = ubi->move_to = NULL; -++ ubi->move_to_put = ubi->wl_scheduled = 0; -++ spin_unlock(&ubi->wl_lock); -+ -+- yield(); -++ kmem_cache_free(ubi_wl_entry_slab, e1); -++ kmem_cache_free(ubi_wl_entry_slab, e2); -++ ubi_ro_mode(ubi); -++ -++ mutex_unlock(&ubi->move_mutex); -+ return err; -++ -++out_cancel: -++ ubi->wl_scheduled = 0; -++ spin_unlock(&ubi->wl_lock); -++ mutex_unlock(&ubi->move_mutex); -++ ubi_free_vid_hdr(ubi, vid_hdr); -++ return 0; -+ } -+ -+ /** -+@@ -1020,7 +1037,7 @@ -+ if (cancel) { -+ dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec); -+ kfree(wl_wrk); -+- kmem_cache_free(wl_entries_slab, e); -++ kmem_cache_free(ubi_wl_entry_slab, e); -+ return 0; -+ } -+ -+@@ -1049,7 +1066,7 @@ -+ -+ ubi_err("failed to erase PEB %d, error %d", pnum, err); -+ kfree(wl_wrk); -+- kmem_cache_free(wl_entries_slab, e); -++ kmem_cache_free(ubi_wl_entry_slab, e); -+ -+ if (err == -EINTR || err == -ENOMEM || err == -EAGAIN || -+ err == -EBUSY) { -+@@ -1119,8 +1136,7 @@ -+ } -+ -+ /** -+- * ubi_wl_put_peb - return a physical eraseblock to the wear-leveling -+- * unit. -++ * ubi_wl_put_peb - return a physical eraseblock to the wear-leveling unit. -+ * @ubi: UBI device description object -+ * @pnum: physical eraseblock to return -+ * @torture: if this physical eraseblock has to be tortured -+@@ -1128,7 +1144,7 @@ -+ * This function is called to return physical eraseblock @pnum to the pool of -+ * free physical eraseblocks. The @torture flag has to be set if an I/O error -+ * occurred to this @pnum and it has to be tested. This function returns zero -+- * in case of success and a negative error code in case of failure. -++ * in case of success, and a negative error code in case of failure. -+ */ -+ int ubi_wl_put_peb(struct ubi_device *ubi, int pnum, int torture) -+ { -+@@ -1139,8 +1155,8 @@ -+ ubi_assert(pnum >= 0); -+ ubi_assert(pnum < ubi->peb_count); -+ -++retry: -+ spin_lock(&ubi->wl_lock); -+- -+ e = ubi->lookuptbl[pnum]; -+ if (e == ubi->move_from) { -+ /* -+@@ -1148,17 +1164,22 @@ -+ * be moved. It will be scheduled for erasure in the -+ * wear-leveling worker. -+ */ -+- dbg_wl("PEB %d is being moved", pnum); -+- ubi_assert(!ubi->move_from_put); -+- ubi->move_from_put = 1; -++ dbg_wl("PEB %d is being moved, wait", pnum); -+ spin_unlock(&ubi->wl_lock); -+- return 0; -++ -++ /* Wait for the WL worker by taking the @ubi->move_mutex */ -++ mutex_lock(&ubi->move_mutex); -++ mutex_unlock(&ubi->move_mutex); -++ goto retry; -+ } else if (e == ubi->move_to) { -+ /* -+ * User is putting the physical eraseblock which was selected -+ * as the target the data is moved to. It may happen if the EBA -+- * unit already re-mapped the LEB but the WL unit did has not -+- * put the PEB to the "used" tree. -++ * unit already re-mapped the LEB in 'ubi_eba_copy_leb()' but -++ * the WL unit has not put the PEB to the "used" tree yet, but -++ * it is about to do this. So we just set a flag which will -++ * tell the WL worker that the PEB is not needed anymore and -++ * should be scheduled for erasure. -+ */ -+ dbg_wl("PEB %d is the target of data moving", pnum); -+ ubi_assert(!ubi->move_to_put); -+@@ -1172,8 +1193,15 @@ -+ } else if (in_wl_tree(e, &ubi->scrub)) { -+ paranoid_check_in_wl_tree(e, &ubi->scrub); -+ rb_erase(&e->rb, &ubi->scrub); -+- } else -+- prot_tree_del(ubi, e->pnum); -++ } else { -++ err = prot_tree_del(ubi, e->pnum); -++ if (err) { -++ ubi_err("PEB %d not found", pnum); -++ ubi_ro_mode(ubi); -++ spin_unlock(&ubi->wl_lock); -++ return err; -++ } -++ } -+ } -+ spin_unlock(&ubi->wl_lock); -+ -+@@ -1227,8 +1255,17 @@ -+ if (in_wl_tree(e, &ubi->used)) { -+ paranoid_check_in_wl_tree(e, &ubi->used); -+ rb_erase(&e->rb, &ubi->used); -+- } else -+- prot_tree_del(ubi, pnum); -++ } else { -++ int err; -++ -++ err = prot_tree_del(ubi, e->pnum); -++ if (err) { -++ ubi_err("PEB %d not found", pnum); -++ ubi_ro_mode(ubi); -++ spin_unlock(&ubi->wl_lock); -++ return err; -++ } -++ } -+ -+ wl_tree_add(e, &ubi->scrub); -+ spin_unlock(&ubi->wl_lock); -+@@ -1249,17 +1286,32 @@ -+ */ -+ int ubi_wl_flush(struct ubi_device *ubi) -+ { -+- int err, pending_count; -+- -+- pending_count = ubi->works_count; -+- -+- dbg_wl("flush (%d pending works)", pending_count); -++ int err; -+ -+ /* -+ * Erase while the pending works queue is not empty, but not more then -+ * the number of currently pending works. -+ */ -+- while (pending_count-- > 0) { -++ dbg_wl("flush (%d pending works)", ubi->works_count); -++ while (ubi->works_count) { -++ err = do_work(ubi); -++ if (err) -++ return err; -++ } -++ -++ /* -++ * Make sure all the works which have been done in parallel are -++ * finished. -++ */ -++ down_write(&ubi->work_sem); -++ up_write(&ubi->work_sem); -++ -++ /* -++ * And in case last was the WL worker and it cancelled the LEB -++ * movement, flush again. -++ */ -++ while (ubi->works_count) { -++ dbg_wl("flush more (%d pending works)", ubi->works_count); -+ err = do_work(ubi); -+ if (err) -+ return err; -+@@ -1294,7 +1346,7 @@ -+ rb->rb_right = NULL; -+ } -+ -+- kmem_cache_free(wl_entries_slab, e); -++ kmem_cache_free(ubi_wl_entry_slab, e); -+ } -+ } -+ } -+@@ -1303,7 +1355,7 @@ -+ * ubi_thread - UBI background thread. -+ * @u: the UBI device description object pointer -+ */ -+-static int ubi_thread(void *u) -++int ubi_thread(void *u) -+ { -+ int failures = 0; -+ struct ubi_device *ubi = u; -+@@ -1394,36 +1446,22 @@ -+ ubi->used = ubi->free = ubi->scrub = RB_ROOT; -+ ubi->prot.pnum = ubi->prot.aec = RB_ROOT; -+ spin_lock_init(&ubi->wl_lock); -++ mutex_init(&ubi->move_mutex); -++ init_rwsem(&ubi->work_sem); -+ ubi->max_ec = si->max_ec; -+ INIT_LIST_HEAD(&ubi->works); -+ -+ sprintf(ubi->bgt_name, UBI_BGT_NAME_PATTERN, ubi->ubi_num); -+ -+- ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name); -+- if (IS_ERR(ubi->bgt_thread)) { -+- err = PTR_ERR(ubi->bgt_thread); -+- ubi_err("cannot spawn \"%s\", error %d", ubi->bgt_name, -+- err); -+- return err; -+- } -+- -+- if (ubi_devices_cnt == 0) { -+- wl_entries_slab = kmem_cache_create("ubi_wl_entry_slab", -+- sizeof(struct ubi_wl_entry), -+- 0, 0, NULL); -+- if (!wl_entries_slab) -+- return -ENOMEM; -+- } -+- -+ err = -ENOMEM; -+ ubi->lookuptbl = kzalloc(ubi->peb_count * sizeof(void *), GFP_KERNEL); -+ if (!ubi->lookuptbl) -+- goto out_free; -++ return err; -+ -+ list_for_each_entry_safe(seb, tmp, &si->erase, u.list) { -+ cond_resched(); -+ -+- e = kmem_cache_alloc(wl_entries_slab, GFP_KERNEL); -++ e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); -+ if (!e) -+ goto out_free; -+ -+@@ -1431,7 +1469,7 @@ -+ e->ec = seb->ec; -+ ubi->lookuptbl[e->pnum] = e; -+ if (schedule_erase(ubi, e, 0)) { -+- kmem_cache_free(wl_entries_slab, e); -++ kmem_cache_free(ubi_wl_entry_slab, e); -+ goto out_free; -+ } -+ } -+@@ -1439,7 +1477,7 @@ -+ list_for_each_entry(seb, &si->free, u.list) { -+ cond_resched(); -+ -+- e = kmem_cache_alloc(wl_entries_slab, GFP_KERNEL); -++ e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); -+ if (!e) -+ goto out_free; -+ -+@@ -1453,7 +1491,7 @@ -+ list_for_each_entry(seb, &si->corr, u.list) { -+ cond_resched(); -+ -+- e = kmem_cache_alloc(wl_entries_slab, GFP_KERNEL); -++ e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); -+ if (!e) -+ goto out_free; -+ -+@@ -1461,7 +1499,7 @@ -+ e->ec = seb->ec; -+ ubi->lookuptbl[e->pnum] = e; -+ if (schedule_erase(ubi, e, 0)) { -+- kmem_cache_free(wl_entries_slab, e); -++ kmem_cache_free(ubi_wl_entry_slab, e); -+ goto out_free; -+ } -+ } -+@@ -1470,7 +1508,7 @@ -+ ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) { -+ cond_resched(); -+ -+- e = kmem_cache_alloc(wl_entries_slab, GFP_KERNEL); -++ e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); -+ if (!e) -+ goto out_free; -+ -+@@ -1510,8 +1548,6 @@ -+ tree_destroy(&ubi->free); -+ tree_destroy(&ubi->scrub); -+ kfree(ubi->lookuptbl); -+- if (ubi_devices_cnt == 0) -+- kmem_cache_destroy(wl_entries_slab); -+ return err; -+ } -+ -+@@ -1541,7 +1577,7 @@ -+ rb->rb_right = NULL; -+ } -+ -+- kmem_cache_free(wl_entries_slab, pe->e); -++ kmem_cache_free(ubi_wl_entry_slab, pe->e); -+ kfree(pe); -+ } -+ } -+@@ -1553,10 +1589,6 @@ -+ */ -+ void ubi_wl_close(struct ubi_device *ubi) -+ { -+- dbg_wl("disable \"%s\"", ubi->bgt_name); -+- if (ubi->bgt_thread) -+- kthread_stop(ubi->bgt_thread); -+- -+ dbg_wl("close the UBI wear-leveling unit"); -+ -+ cancel_pending(ubi); -+@@ -1565,8 +1597,6 @@ -+ tree_destroy(&ubi->free); -+ tree_destroy(&ubi->scrub); -+ kfree(ubi->lookuptbl); -+- if (ubi_devices_cnt == 1) -+- kmem_cache_destroy(wl_entries_slab); -+ } -+ -+ #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID -+diff -urN linux-2.6.24.7.old/drivers/mtd/udc_cache.c linux-2.6.24.7/drivers/mtd/udc_cache.c -+--- linux-2.6.24.7.old/drivers/mtd/udc_cache.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/mtd/udc_cache.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,531 @@ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#define CACHE_MAX_NUM 256 -++#define SECTOR_SIZE 512 -++ -++//#define UDC_CACHE_DEBUG -++ -++#ifdef UDC_CACHE_DEBUG -++#define dprintk(a...) printk(a) -++#else -++#define dprintk(a...) while(0){} -++#endif -++ -++typedef struct { -++ unsigned short CacheState; -++ unsigned short UseCount; -++ unsigned short CacheChange; -++ unsigned short CacheReserve; -++ unsigned int BlockId; -++ unsigned char *aBlockData; -++} SSFDC__LB_CACHE; -++ -++#define FREE_CACHE 0 -++#define PREWRITE_CACHE 2 -++#define OFTEN_USE_CACHE 3 -++#define SECTOR_SHIFT 9 -++ -++#define CACHE_TO_UNCATCH(x) ((unsigned int)x | 0xa0000000) -++static unsigned int __aBlockData[SECTOR_SIZE * CACHE_MAX_NUM / 4] __attribute__ ((aligned (32))); -++static SSFDC__LB_CACHE ssfdc_cache[CACHE_MAX_NUM]; -++static unsigned short Cur_CacheCount = 0; -++int FlushDataState = 0; -++static struct mtdblk_dev *g_udc_mtdblk; -++static struct mtd_info *g_udc_mtd; -++ -++extern int udc_mtdblock_readsect(struct mtdblk_dev *, unsigned long, char *, int); -++extern int udc_mtdblock_writesect(struct mtdblk_dev *, unsigned long, char *); -++extern struct mtdblk_dev *udc_get_mtdblk(void); -++extern struct mtd_info *udc_get_mtd(void); -++extern void udc_flush_cache(struct mtdblk_dev *mtdblk); -++ -++#define _NAND_LB_Write(pCache) udc_mtdblock_writesect(g_udc_mtdblk, pCache->BlockId,pCache->aBlockData) -++#define _NAND_LB_Read(Sector,pBuffer) udc_mtdblock_readsect(g_udc_mtdblk, Sector, pBuffer, SECTOR_SIZE); -++ -++#define DMA_ENABLE 0 -++ -++#if DMA_ENABLE -++#define DMA_CHANNEL 5 -++#define PHYSADDR(x) virt_to_phys((void *)x) -++#else -++#define lb_memcpy memcpy -++#endif -++ -++#if DMA_ENABLE -++static void lb_memcpy(void *target,void* source,unsigned int len) -++{ -++ int ch = DMA_CHANNEL; -++ if(((unsigned int)source < 0xa0000000) && len) -++ dma_cache_wback_inv((unsigned long)source, len); -++ if(((unsigned int)target < 0xa0000000) && len) -++ dma_cache_wback_inv((unsigned long)target, len); -++ -++ REG_DMAC_DSAR(ch) = PHYSADDR((unsigned long)source); -++ REG_DMAC_DTAR(ch) = PHYSADDR((unsigned long)target); -++ REG_DMAC_DTCR(ch) = len / 32; -++ REG_DMAC_DRSR(ch) = DMAC_DRSR_RS_AUTO; -++ REG_DMAC_DCMD(ch) = DMAC_DCMD_SAI| DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32|DMAC_DCMD_DS_32BYTE; -++ REG_DMAC_DCCSR(ch) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; -++ while ( REG_DMAC_DTCR(ch) ); -++} -++#endif -++ -++static void _NAND_LB_InitCache(void) -++{ -++ int i; -++ SSFDC__LB_CACHE *pCache = ssfdc_cache; -++#if DMA_ENABLE -++ unsigned char * ptr = (unsigned char *)CACHE_TO_UNCATCH(__aBlockData); -++#else -++ unsigned char * ptr = (unsigned char *)(__aBlockData); -++#endif -++ for(i = 0;i < CACHE_MAX_NUM;i++) -++ { -++ pCache->CacheState = FREE_CACHE; -++ pCache->UseCount = 0; -++ pCache->CacheChange = 0; -++ pCache->aBlockData = ptr; -++ ptr+=SECTOR_SIZE; -++ pCache++; -++ } -++ Cur_CacheCount = 0; -++} -++ -++static SSFDC__LB_CACHE * _NAND_LB_GetFreeCache(void) -++{ -++ int ret = 0; -++ SSFDC__LB_CACHE *pCacheInfo = &ssfdc_cache[Cur_CacheCount]; -++ while(1) -++ { -++ if(ret >= CACHE_MAX_NUM) -++ return 0; -++ if(pCacheInfo >= &ssfdc_cache[CACHE_MAX_NUM]) -++ { -++ pCacheInfo = ssfdc_cache; -++ Cur_CacheCount = 0; -++ } -++ -++ if(pCacheInfo->CacheState == FREE_CACHE) -++ { -++ return pCacheInfo; -++ } -++ pCacheInfo++; -++ Cur_CacheCount++; -++ ret++; -++ } -++ return 0; -++} -++ -++static void _NAND_LB_CloseCACHES(unsigned int sectorstart,unsigned int sectorend) -++{ -++ unsigned int i; -++ SSFDC__LB_CACHE *pCache = ssfdc_cache; -++ for( i = 0;i < CACHE_MAX_NUM;i++){ -++ if((pCache->CacheState != FREE_CACHE) && (pCache->BlockId >= sectorstart) && (pCache->BlockId < sectorend)){ -++ pCache->CacheChange = 0; -++ pCache->CacheState = FREE_CACHE; -++ pCache->UseCount = 0; -++ } -++ pCache++; -++ } -++} -++ -++static void _NAND_LB_FLUSHCACHES(unsigned int sectorstart,unsigned int sectorend) -++{ -++ unsigned int i; -++ SSFDC__LB_CACHE *pCache = ssfdc_cache; -++ for( i = 0;i < CACHE_MAX_NUM;i++){ -++ if((pCache->CacheState != FREE_CACHE) && (pCache->BlockId >= sectorstart) && (pCache->BlockId < sectorend)){ -++ if(pCache->CacheChange) -++ _NAND_LB_Write(pCache); -++ pCache->CacheChange = 0; -++ pCache->CacheState = FREE_CACHE; -++ pCache->UseCount = 0; -++ } -++ pCache++; -++ -++ } -++} -++ -++inline static int Get_NAND_CacheFreeCount(void) -++{ -++ SSFDC__LB_CACHE *pCache = ssfdc_cache; -++ SSFDC__LB_CACHE *pEndCache = &ssfdc_cache[CACHE_MAX_NUM]; -++ unsigned int count = 0; -++ while(pCache < pEndCache) -++ { -++ if(pCache->CacheState == FREE_CACHE) -++ count++; -++ pCache++; -++ } -++ return count; -++ -++} -++ -++static unsigned int _NAND_LB_PreWiteToNand(SSFDC__LB_CACHE *pCache,unsigned short *count,unsigned int update) -++{ -++ SSFDC__LB_CACHE *pWriteCache; -++ SSFDC__LB_CACHE *pEndCache = &ssfdc_cache[CACHE_MAX_NUM]; -++ unsigned int sector = -1; -++ unsigned int flag; -++ while(1) -++ { -++ sector = -1; -++ flag = 0; -++ pWriteCache = ssfdc_cache; -++ while(pWriteCache < pEndCache) -++ { -++ if(pWriteCache->CacheState == update) //PREWRITE_CACHE -++ { -++ if(pWriteCache->BlockId < sector) -++ { -++ sector = pWriteCache->BlockId; -++ pCache = pWriteCache; -++ } -++ }else -++ flag++; -++ pWriteCache++; -++ } -++ -++ if(flag < CACHE_MAX_NUM) -++ { -++ if(pCache->CacheChange) -++ { -++ _NAND_LB_Write(pCache); -++ pCache->CacheChange = 0; -++ } -++ pCache->CacheState = FREE_CACHE; -++ pCache->UseCount = 0; -++ (*count)++; -++ }else -++ break; -++ } -++ return 0; -++} -++ -++static void _NAND_LB_OftenToNand(SSFDC__LB_CACHE *pCache,unsigned short *count,unsigned int update) -++{ -++ SSFDC__LB_CACHE *pWriteCache = pCache; -++ SSFDC__LB_CACHE *pOldCache = pCache; -++ SSFDC__LB_CACHE *pEndCache = &ssfdc_cache[CACHE_MAX_NUM]; -++ -++ dprintk("%s!\n",__FUNCTION__); -++ while(pCache) -++ { -++ if(pCache->CacheState == OFTEN_USE_CACHE) -++ { -++ if(pWriteCache->CacheState != OFTEN_USE_CACHE) -++ pWriteCache = pCache; -++ else if(pWriteCache->UseCount > pCache->UseCount) -++ { -++ pWriteCache = pCache; -++ } -++ } -++ pCache++; -++ if(pCache >= pEndCache) -++ break; -++ } -++ if(pWriteCache->CacheState == OFTEN_USE_CACHE) -++ { -++ (*count)++; -++ if(pWriteCache->CacheChange) -++ _NAND_LB_Write(pWriteCache); -++ pWriteCache->CacheState = FREE_CACHE; -++ -++ pWriteCache->UseCount = 0; -++ pWriteCache->CacheChange = 0; -++ if(update != -1) -++ update--; -++ if(update != 0) -++ _NAND_LB_OftenToNand(pOldCache,count,update); -++ } -++} -++ -++static int _NAND_LB_FreeCache(unsigned int update) -++{ -++ unsigned short freecount = 0,totalfree = 0; -++ -++ freecount = 0; -++ _NAND_LB_PreWiteToNand(ssfdc_cache,&freecount,PREWRITE_CACHE); -++ -++ totalfree += freecount; -++ dprintk("free count = %d\n",freecount); -++ if(freecount == 0) -++ { -++ freecount = 0; -++ _NAND_LB_PreWiteToNand(ssfdc_cache,&freecount,OFTEN_USE_CACHE); -++ totalfree += freecount; -++ update = 0; -++ } -++ if(update) -++ { -++ if(Get_NAND_CacheFreeCount() < CACHE_MAX_NUM * 1 / 4) // because fat is 4 sector -++ { -++ freecount = 0; -++ _NAND_LB_PreWiteToNand(ssfdc_cache,&freecount,OFTEN_USE_CACHE); -++ totalfree += freecount; -++ } -++ } -++ -++ dprintk("Free = %d\r\n",totalfree); -++ return totalfree; -++} -++ -++static int _NAND_LB_GetFromCache(unsigned int Sector, void *pBuffer) { -++ -++ SSFDC__LB_CACHE *pCache = &ssfdc_cache[Cur_CacheCount]; -++ SSFDC__LB_CACHE *pUseCache = 0; -++ unsigned short i; -++ dprintk("sector = %x pBuffer = %x\n",Sector,pBuffer); -++ if(pCache >= &ssfdc_cache[CACHE_MAX_NUM]) -++ pCache = ssfdc_cache; -++ -++ i = 0; -++ while (1) { -++ if(pCache->CacheState != FREE_CACHE) -++ { -++ if (Sector == pCache->BlockId) { -++ dprintk("Cache is use = %d\r\n",pCache->BlockId); -++ pUseCache = pCache; -++ pCache->UseCount++; -++ if(pCache->UseCount == 0) -++ pCache->UseCount = -1; -++ pCache->CacheState = OFTEN_USE_CACHE; -++ } -++ } -++ pCache--; -++ if(pCache < ssfdc_cache) -++ pCache = &ssfdc_cache[CACHE_MAX_NUM - 1]; -++ -++ i++; -++ if (i >= CACHE_MAX_NUM) { -++ break; /* Sector not in cache */ -++ } -++ } -++ if (pUseCache) { -++ dprintk("From Cache %d\r\n",Sector); -++ lb_memcpy(pBuffer, pUseCache->aBlockData, SECTOR_SIZE); -++ return 0; -++ } -++ return -1; -++} -++ -++static void _NAND_LB_ClearCache(void) { -++ -++ unsigned short freecount = 0; -++ dprintk("Clear Cache\r\n"); -++ -++ _NAND_LB_PreWiteToNand(ssfdc_cache,&freecount,PREWRITE_CACHE); -++ _NAND_LB_PreWiteToNand(ssfdc_cache,&freecount,OFTEN_USE_CACHE); -++} -++ -++static void _NAND_LB_CopyToCache(unsigned int Sector, void *pBuffer,unsigned short rw) -++{ -++ SSFDC__LB_CACHE *pCache = _NAND_LB_GetFreeCache(); -++ dprintk("Copy to Cache = 0x%08x 0x%08x\r\n",pCache,ssfdc_cache); -++ -++ if(!pCache) -++ { -++ _NAND_LB_FreeCache(rw); -++ -++ pCache = _NAND_LB_GetFreeCache(); -++ } -++ pCache->BlockId = Sector; -++ pCache->CacheState = PREWRITE_CACHE; -++ pCache->UseCount = 0; -++ pCache->CacheChange = rw; -++ -++ lb_memcpy(pCache->aBlockData,pBuffer,SECTOR_SIZE); -++} -++ -++ -++static int _NAND_LB_UpdateInCache(unsigned int Sector, void *pBuffer) { -++ short i,ret = 0; -++ i = Cur_CacheCount; -++ if(Cur_CacheCount > CACHE_MAX_NUM) -++ i = 0; -++ while(1) -++ { -++ if(ret >= CACHE_MAX_NUM) -++ return -1; -++ if(ssfdc_cache[i].CacheState != FREE_CACHE) -++ { -++ -++ if(ssfdc_cache[i].BlockId == Sector) -++ { -++ dprintk("UpdateInCache = %d\r\n",Sector); -++ ssfdc_cache[i].CacheState = OFTEN_USE_CACHE; -++ ssfdc_cache[i].UseCount++; -++ ssfdc_cache[i].CacheChange = 1; -++ lb_memcpy(ssfdc_cache[i].aBlockData,pBuffer,SECTOR_SIZE); -++ return 0; -++ } -++ } -++ i--; -++ if(i < 0) -++ i = CACHE_MAX_NUM - 1; -++ ret++; -++ } -++ return -1; -++} -++ -++static int NAND_LB_MultiRead(unsigned int Sector, void *pBuffer,unsigned int SectorCount) -++{ -++ int i,ret,end; -++ void *p; -++ -++ dprintk("NAND_LB_MultiRead = %d %d \n",Sector,SectorCount); -++ end = Sector + SectorCount; -++ _NAND_LB_FLUSHCACHES(Sector,end); -++ -++ p = pBuffer; -++ for (i = Sector; i < end; i ++) -++ { -++ ret = udc_mtdblock_readsect(g_udc_mtdblk, i, p, SECTOR_SIZE); -++ p += SECTOR_SIZE; -++ } -++ return ret; -++} -++ -++static int NAND_LB_Read(unsigned int Sector, void *pBuffer) -++{ -++ int x; -++#if DMA_ENABLE -++ unsigned char *ptr = (unsigned char *)CACHE_TO_UNCATCH(pBuffer); -++ dma_cache_wback_inv(pBuffer,SECTOR_SIZE); -++#else -++ unsigned char *ptr = (unsigned char *)pBuffer; -++#endif -++ dprintk("LB_Read = %d \n",Sector); -++ if(_NAND_LB_GetFromCache(Sector,ptr)) -++ { -++ x = _NAND_LB_Read(Sector,ptr); -++ _NAND_LB_CopyToCache(Sector,ptr,0); -++ } -++ return 512; -++} -++ -++static int NAND_LB_MultiWrite(unsigned int Sector, void *pBuffer,unsigned int SectorCount) -++{ -++ int i,ret; -++ unsigned char *p; -++ -++ _NAND_LB_CloseCACHES(Sector,Sector + SectorCount); -++ p = (unsigned char *)pBuffer; -++ for (i = Sector; i < Sector + SectorCount; i ++) -++ { -++ ret = udc_mtdblock_writesect(g_udc_mtdblk, i, p); -++ p += 512; -++ } -++ return ret; -++} -++ -++static int NAND_LB_Write(unsigned int Sector, void *pBuffer) -++{ -++#if DMA_ENABLE -++ unsigned char *ptr = (unsigned char *)CACHE_TO_UNCATCH(pBuffer); -++ dma_cache_wback_inv(pBuffer,SECTOR_SIZE); -++#else -++ unsigned char *ptr = (unsigned char *)pBuffer; -++#endif -++ dprintk("LB_Write = %x %x\r\n",Sector,pBuffer); -++ if(_NAND_LB_UpdateInCache(Sector,ptr)) -++ { -++ _NAND_LB_CopyToCache(Sector,ptr,1); -++ } -++ return 512; -++} -++/********************************************************************* -++* -++* Global functions -++* -++***********************************************************************/ -++ -++int NAND_LB_Init(void) -++{ -++ dprintk("UDC CACHE Init \n"); -++ _NAND_LB_InitCache(); -++ g_udc_mtdblk = udc_get_mtdblk(); -++ g_udc_mtd = udc_get_mtd(); -++ return 0; -++} -++ -++int NAND_LB_FLASHCACHE(void) -++{ -++ dprintk("Flush lb cache !\n"); -++ _NAND_LB_ClearCache(); -++// dprintk("Flush mtd cache !\n"); -++// udc_flush_cache(g_udc_mtdblk); -++ return 0; -++} -++ -++int NAND_MTD_FLASHCACHE(void) -++{ -++ dprintk("Flush mtd cache !\n"); -++ udc_flush_cache(g_udc_mtdblk); -++ return 0; -++} -++ -++int udc_read(unsigned int offset, unsigned int len, unsigned char *buf) -++{ -++ unsigned long block,sector,i; -++ -++ block = offset >> SECTOR_SHIFT; -++ sector = len >> SECTOR_SHIFT; -++ dprintk("read dev = ia:%x, s:%d c:%d\r\n",buf,block,sector); -++ -++ if (sector <= 8) -++ { -++ for(i = 0;i < sector; i++) -++ { -++ NAND_LB_Read(block + i,(void *)(buf)); -++ buf += 512; -++ } -++ } -++ else -++ NAND_LB_MultiRead(block, buf, sector); -++ -++ return len; -++} -++ -++int udc_write(unsigned int offset, unsigned int len, unsigned char *buf) -++{ -++ unsigned long block,sector,i; -++ -++ block = offset >> SECTOR_SHIFT; -++ sector = len >> SECTOR_SHIFT; -++ dprintk("write dev s:%d c:%d\r\n",block,sector); -++ -++ if(sector <= 8) -++ { -++ for(i = 0;i < sector; i++) -++ { -++ NAND_LB_Write(block + i,(void *)(buf)); -++ buf += 512; -++ FlushDataState = 1; -++ } -++ }else -++ NAND_LB_MultiWrite(block,(void *)(buf),sector); -++ -++ return len; -++} -++ -++EXPORT_SYMBOL_GPL(udc_write); -++EXPORT_SYMBOL_GPL(udc_read); -++EXPORT_SYMBOL_GPL(NAND_LB_Init); -++EXPORT_SYMBOL_GPL(NAND_LB_FLASHCACHE); -++EXPORT_SYMBOL_GPL(FlushDataState); -++EXPORT_SYMBOL_GPL(NAND_MTD_FLASHCACHE); -+diff -urN linux-2.6.24.7.old/drivers/net/Kconfig linux-2.6.24.7/drivers/net/Kconfig -+--- linux-2.6.24.7.old/drivers/net/Kconfig 2009-04-12 18:05:07.000000000 +0200 -++++ linux-2.6.24.7/drivers/net/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -333,6 +333,24 @@ -+ or internal device. It is safe to say Y or M here even if your -+ ethernet card lack MII. -+ -++config JZ_ETH -++ tristate "JZ4730/JZ5730 On-Chip Ethernet support" -++ depends on NET_ETHERNET && (SOC_JZ4730 || SOC_JZ5730 || JZ_FPGA) -++ help -++ Say Y for support of JZ4730/JZ5730 On-Chip Ethernet interface. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called jz_eth. -++ -++config JZCS8900 -++ tristate "JZ CS8900A Ethernet support" -++ depends on NET_ETHERNET && (SOC_JZ4740 || SOC_JZ4750) -++ help -++ Say Y for support of JZ CS8900A Ethernet interface. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called jzcs8900a. -++ -+ config MACB -+ tristate "Atmel MACB support" -+ depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 -+diff -urN linux-2.6.24.7.old/drivers/net/Kconfig.orig linux-2.6.24.7/drivers/net/Kconfig.orig -+--- linux-2.6.24.7.old/drivers/net/Kconfig.orig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/net/Kconfig.orig 2009-04-12 18:01:55.000000000 +0200 -+@@ -0,0 +1,3192 @@ -++ -++# -++# Network device configuration -++# -++ -++menuconfig NETDEVICES -++ default y if UML -++ depends on NET -++ bool "Network device support" -++ ---help--- -++ You can say N here if you don't intend to connect your Linux box to -++ any other computer at all. -++ -++ You'll have to say Y if your computer contains a network card that -++ you want to use under Linux. If you are going to run SLIP or PPP over -++ telephone line or null modem cable you need say Y here. Connecting -++ two machines with parallel ports using PLIP needs this, as well as -++ AX.25/KISS for sending Internet traffic over amateur radio links. -++ -++ See also "The Linux Network Administrator's Guide" by Olaf Kirch and -++ Terry Dawson. Available at . -++ -++ If unsure, say Y. -++ -++# All the following symbols are dependent on NETDEVICES - do not repeat -++# that for each of the symbols. -++if NETDEVICES -++ -++config NETDEVICES_MULTIQUEUE -++ bool "Netdevice multiple hardware queue support" -++ ---help--- -++ Say Y here if you want to allow the network stack to use multiple -++ hardware TX queues on an ethernet device. -++ -++ Most people will say N here. -++ -++config IFB -++ tristate "Intermediate Functional Block support" -++ depends on NET_CLS_ACT -++ ---help--- -++ This is an intermediate driver that allows sharing of -++ resources. -++ To compile this driver as a module, choose M here: the module -++ will be called ifb. If you want to use more than one ifb -++ device at a time, you need to compile this driver as a module. -++ Instead of 'ifb', the devices will then be called 'ifb0', -++ 'ifb1' etc. -++ Look at the iproute2 documentation directory for usage etc -++ -++config DUMMY -++ tristate "Dummy net driver support" -++ ---help--- -++ This is essentially a bit-bucket device (i.e. traffic you send to -++ this device is consigned into oblivion) with a configurable IP -++ address. It is most commonly used in order to make your currently -++ inactive SLIP address seem like a real address for local programs. -++ If you use SLIP or PPP, you might want to say Y here. Since this -++ thing often comes in handy, the default is Y. It won't enlarge your -++ kernel either. What a deal. Read about it in the Network -++ Administrator's Guide, available from -++ . -++ -++ To compile this driver as a module, choose M here: the module -++ will be called dummy. If you want to use more than one dummy -++ device at a time, you need to compile this driver as a module. -++ Instead of 'dummy', the devices will then be called 'dummy0', -++ 'dummy1' etc. -++ -++config BONDING -++ tristate "Bonding driver support" -++ depends on INET -++ ---help--- -++ Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet -++ Channels together. This is called 'Etherchannel' by Cisco, -++ 'Trunking' by Sun, 802.3ad by the IEEE, and 'Bonding' in Linux. -++ -++ The driver supports multiple bonding modes to allow for both high -++ performance and high availability operation. -++ -++ Refer to for more -++ information. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called bonding. -++ -++config MACVLAN -++ tristate "MAC-VLAN support (EXPERIMENTAL)" -++ depends on EXPERIMENTAL -++ ---help--- -++ This allows one to create virtual interfaces that map packets to -++ or from specific MAC addresses to a particular interface. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called macvlan. -++ -++config EQUALIZER -++ tristate "EQL (serial line load balancing) support" -++ ---help--- -++ If you have two serial connections to some other computer (this -++ usually requires two modems and two telephone lines) and you use -++ SLIP (the protocol for sending Internet traffic over telephone -++ lines) or PPP (a better SLIP) on them, you can make them behave like -++ one double speed connection using this driver. Naturally, this has -++ to be supported at the other end as well, either with a similar EQL -++ Linux driver or with a Livingston Portmaster 2e. -++ -++ Say Y if you want this and read -++ . You may also want to read -++ section 6.2 of the NET-3-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here: the module -++ will be called eql. If unsure, say N. -++ -++config IMQ -++ tristate "IMQ (intermediate queueing device) support" -++ depends on NETDEVICES && NETFILTER -++ ---help--- -++ The IMQ device(s) is used as placeholder for QoS queueing -++ disciplines. Every packet entering/leaving the IP stack can be -++ directed through the IMQ device where it's enqueued/dequeued to the -++ attached qdisc. This allows you to treat network devices as classes -++ and distribute bandwidth among them. Iptables is used to specify -++ through which IMQ device, if any, packets travel. -++ -++ More information at: http://www.linuximq.net/ -++ -++ To compile this driver as a module, choose M here: the module -++ will be called imq. If unsure, say N. -++ -++choice -++ prompt "IMQ behavior (PRE/POSTROUTING)" -++ depends on IMQ -++ default IMQ_BEHAVIOR_BB -++ help -++ -++ This settings defines how IMQ behaves in respect to its -++ hooking in PREROUTING and POSTROUTING. -++ -++ IMQ can work in any of the following ways: -++ -++ PREROUTING | POSTROUTING -++ -----------------|------------------- -++ #1 After NAT | After NAT -++ #2 After NAT | Before NAT -++ #3 Before NAT | After NAT -++ #4 Before NAT | Before NAT -++ -++ The default behavior is to hook before NAT on PREROUTING -++ and after NAT on POSTROUTING (#3). -++ -++ This settings are specially usefull when trying to use IMQ -++ to shape NATed clients. -++ -++ More information can be found at: www.linuximq.net -++ -++ If not sure leave the default settings alone. -++ -++config IMQ_BEHAVIOR_AA -++ bool "IMQ AA" -++ help -++ This settings defines how IMQ behaves in respect to its -++ hooking in PREROUTING and POSTROUTING. -++ -++ Choosing this option will make IMQ hook like this: -++ -++ PREROUTING: After NAT -++ POSTROUTING: After NAT -++ -++ More information can be found at: www.linuximq.net -++ -++ If not sure leave the default settings alone. -++ -++config IMQ_BEHAVIOR_AB -++ bool "IMQ AB" -++ help -++ This settings defines how IMQ behaves in respect to its -++ hooking in PREROUTING and POSTROUTING. -++ -++ Choosing this option will make IMQ hook like this: -++ -++ PREROUTING: After NAT -++ POSTROUTING: Before NAT -++ -++ More information can be found at: www.linuximq.net -++ -++ If not sure leave the default settings alone. -++ -++config IMQ_BEHAVIOR_BA -++ bool "IMQ BA" -++ help -++ This settings defines how IMQ behaves in respect to its -++ hooking in PREROUTING and POSTROUTING. -++ -++ Choosing this option will make IMQ hook like this: -++ -++ PREROUTING: Before NAT -++ POSTROUTING: After NAT -++ -++ More information can be found at: www.linuximq.net -++ -++ If not sure leave the default settings alone. -++ -++config IMQ_BEHAVIOR_BB -++ bool "IMQ BB" -++ help -++ This settings defines how IMQ behaves in respect to its -++ hooking in PREROUTING and POSTROUTING. -++ -++ Choosing this option will make IMQ hook like this: -++ -++ PREROUTING: Before NAT -++ POSTROUTING: Before NAT -++ -++ More information can be found at: www.linuximq.net -++ -++ If not sure leave the default settings alone. -++ -++endchoice -++ -++config IMQ_NUM_DEVS -++ -++ int "Number of IMQ devices" -++ range 2 16 -++ depends on IMQ -++ default "16" -++ help -++ -++ This settings defines how many IMQ devices will be -++ created. -++ -++ The default value is 16. -++ -++ More information can be found at: www.linuximq.net -++ -++ If not sure leave the default settings alone. -++ -++config TUN -++ tristate "Universal TUN/TAP device driver support" -++ select CRC32 -++ ---help--- -++ TUN/TAP provides packet reception and transmission for user space -++ programs. It can be viewed as a simple Point-to-Point or Ethernet -++ device, which instead of receiving packets from a physical media, -++ receives them from user space program and instead of sending packets -++ via physical media writes them to the user space program. -++ -++ When a program opens /dev/net/tun, driver creates and registers -++ corresponding net device tunX or tapX. After a program closed above -++ devices, driver will automatically delete tunXX or tapXX device and -++ all routes corresponding to it. -++ -++ Please read for more -++ information. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called tun. -++ -++ If you don't know what to use this for, you don't need it. -++ -++config VETH -++ tristate "Virtual ethernet pair device" -++ ---help--- -++ This device is a local ethernet tunnel. Devices are created in pairs. -++ When one end receives the packet it appears on its pair and vice -++ versa. -++ -++config NET_SB1000 -++ tristate "General Instruments Surfboard 1000" -++ depends on PNP -++ ---help--- -++ This is a driver for the General Instrument (also known as -++ NextLevel) SURFboard 1000 internal -++ cable modem. This is an ISA card which is used by a number of cable -++ TV companies to provide cable modem access. It's a one-way -++ downstream-only cable modem, meaning that your upstream net link is -++ provided by your regular phone modem. -++ -++ At present this driver only compiles as a module, so say M here if -++ you have this card. The module will be called sb1000. Then read -++ for information on how -++ to use this module, as it needs special ppp scripts for establishing -++ a connection. Further documentation and the necessary scripts can be -++ found at: -++ -++ -++ -++ -++ -++ If you don't have this card, of course say N. -++ -++source "drivers/net/arcnet/Kconfig" -++ -++source "drivers/net/phy/Kconfig" -++ -++# -++# Ethernet -++# -++ -++menuconfig NET_ETHERNET -++ bool "Ethernet (10 or 100Mbit)" -++ depends on !UML -++ ---help--- -++ Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common -++ type of Local Area Network (LAN) in universities and companies. -++ -++ Common varieties of Ethernet are: 10BASE-2 or Thinnet (10 Mbps over -++ coaxial cable, linking computers in a chain), 10BASE-T or twisted -++ pair (10 Mbps over twisted pair cable, linking computers to central -++ hubs), 10BASE-F (10 Mbps over optical fiber links, using hubs), -++ 100BASE-TX (100 Mbps over two twisted pair cables, using hubs), -++ 100BASE-T4 (100 Mbps over 4 standard voice-grade twisted pair -++ cables, using hubs), 100BASE-FX (100 Mbps over optical fiber links) -++ [the 100BASE varieties are also known as Fast Ethernet], and Gigabit -++ Ethernet (1 Gbps over optical fiber or short copper links). -++ -++ If your Linux machine will be connected to an Ethernet and you have -++ an Ethernet network interface card (NIC) installed in your computer, -++ say Y here and read the Ethernet-HOWTO, available from -++ . You will then also have -++ to say Y to the driver for your particular NIC. -++ -++ Note that the answer to this question won't directly affect the -++ kernel: saying N will just cause the configurator to skip all -++ the questions about Ethernet network cards. If unsure, say N. -++ -++if NET_ETHERNET -++ -++config MII -++ tristate "Generic Media Independent Interface device support" -++ help -++ Most ethernet controllers have MII transceiver either as an external -++ or internal device. It is safe to say Y or M here even if your -++ ethernet card lack MII. -++ -++config MACB -++ tristate "Atmel MACB support" -++ depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 -++ select PHYLIB -++ help -++ The Atmel MACB ethernet interface is found on many AT32 and AT91 -++ parts. Say Y to include support for the MACB chip. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called macb. -++ -++source "drivers/net/arm/Kconfig" -++ -++config AX88796 -++ tristate "ASIX AX88796 NE2000 clone support" -++ depends on ARM || MIPS || SUPERH -++ select CRC32 -++ select MII -++ help -++ AX88796 driver, using platform bus to provide -++ chip detection and resources -++ -++config AX88796_93CX6 -++ bool "ASIX AX88796 external 93CX6 eeprom support" -++ depends on AX88796 -++ select EEPROM_93CX6 -++ help -++ Select this if your platform comes with an external 93CX6 eeprom. -++ -++config MACE -++ tristate "MACE (Power Mac ethernet) support" -++ depends on PPC_PMAC && PPC32 -++ select CRC32 -++ help -++ Power Macintoshes and clones with Ethernet built-in on the -++ motherboard will usually use a MACE (Medium Access Control for -++ Ethernet) interface. Say Y to include support for the MACE chip. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called mace. -++ -++config MACE_AAUI_PORT -++ bool "Use AAUI port instead of TP by default" -++ depends on MACE -++ help -++ Some Apple machines (notably the Apple Network Server) which use the -++ MACE ethernet chip have an Apple AUI port (small 15-pin connector), -++ instead of an 8-pin RJ45 connector for twisted-pair ethernet. Say -++ Y here if you have such a machine. If unsure, say N. -++ The driver will default to AAUI on ANS anyway, and if you use it as -++ a module, you can provide the port_aaui=0|1 to force the driver. -++ -++config BMAC -++ tristate "BMAC (G3 ethernet) support" -++ depends on PPC_PMAC && PPC32 -++ select CRC32 -++ help -++ Say Y for support of BMAC Ethernet interfaces. These are used on G3 -++ computers. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called bmac. -++ -++config ARIADNE -++ tristate "Ariadne support" -++ depends on ZORRO -++ help -++ If you have a Village Tronic Ariadne Ethernet adapter, say Y. -++ Otherwise, say N. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called ariadne. -++ -++config A2065 -++ tristate "A2065 support" -++ depends on ZORRO -++ select CRC32 -++ help -++ If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise, -++ say N. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called a2065. -++ -++config HYDRA -++ tristate "Hydra support" -++ depends on ZORRO -++ select CRC32 -++ help -++ If you have a Hydra Ethernet adapter, say Y. Otherwise, say N. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called hydra. -++ -++config ZORRO8390 -++ tristate "Zorro NS8390-based Ethernet support" -++ depends on ZORRO -++ select CRC32 -++ help -++ This driver is for Zorro Ethernet cards using an NS8390-compatible -++ chipset, like the Village Tronic Ariadne II and the Individual -++ Computers X-Surf Ethernet cards. If you have such a card, say Y. -++ Otherwise, say N. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called zorro8390. -++ -++config APNE -++ tristate "PCMCIA NE2000 support" -++ depends on AMIGA_PCMCIA -++ select CRC32 -++ help -++ If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise, -++ say N. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called apne. -++ -++config APOLLO_ELPLUS -++ tristate "Apollo 3c505 support" -++ depends on APOLLO -++ help -++ Say Y or M here if your Apollo has a 3Com 3c505 ISA Ethernet card. -++ If you don't have one made for Apollos, you can use one from a PC, -++ except that your Apollo won't be able to boot from it (because the -++ code in the ROM will be for a PC). -++ -++config MAC8390 -++ bool "Macintosh NS 8390 based ethernet cards" -++ depends on MAC -++ select CRC32 -++ help -++ If you want to include a driver to support Nubus or LC-PDS -++ Ethernet cards using an NS8390 chipset or its equivalent, say Y -++ and read the Ethernet-HOWTO, available from -++ . -++ -++config MAC89x0 -++ tristate "Macintosh CS89x0 based ethernet cards" -++ depends on MAC -++ ---help--- -++ Support for CS89x0 chipset based Ethernet cards. If you have a -++ Nubus or LC-PDS network (Ethernet) card of this type, say Y and -++ read the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. This module will -++ be called mac89x0. -++ -++config MACSONIC -++ tristate "Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)" -++ depends on MAC -++ ---help--- -++ Support for NatSemi SONIC based Ethernet devices. This includes -++ the onboard Ethernet in many Quadras as well as some LC-PDS, -++ a few Nubus and all known Comm Slot Ethernet cards. If you have -++ one of these say Y and read the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. This module will -++ be called macsonic. -++ -++config MACMACE -++ bool "Macintosh (AV) onboard MACE ethernet" -++ depends on MAC -++ select CRC32 -++ help -++ Support for the onboard AMD 79C940 MACE Ethernet controller used in -++ the 660AV and 840AV Macintosh. If you have one of these Macintoshes -++ say Y and read the Ethernet-HOWTO, available from -++ . -++ -++config MVME147_NET -++ tristate "MVME147 (Lance) Ethernet support" -++ depends on MVME147 -++ select CRC32 -++ help -++ Support for the on-board Ethernet interface on the Motorola MVME147 -++ single-board computer. Say Y here to include the -++ driver for this chip in your kernel. -++ To compile this driver as a module, choose M here. -++ -++config MVME16x_NET -++ tristate "MVME16x Ethernet support" -++ depends on MVME16x -++ help -++ This is the driver for the Ethernet interface on the Motorola -++ MVME162, 166, 167, 172 and 177 boards. Say Y here to include the -++ driver for this chip in your kernel. -++ To compile this driver as a module, choose M here. -++ -++config BVME6000_NET -++ tristate "BVME6000 Ethernet support" -++ depends on BVME6000 -++ help -++ This is the driver for the Ethernet interface on BVME4000 and -++ BVME6000 VME boards. Say Y here to include the driver for this chip -++ in your kernel. -++ To compile this driver as a module, choose M here. -++ -++config ATARILANCE -++ tristate "Atari Lance support" -++ depends on ATARI -++ help -++ Say Y to include support for several Atari Ethernet adapters based -++ on the AMD Lance chipset: RieblCard (with or without battery), or -++ PAMCard VME (also the version by Rhotron, with different addresses). -++ -++config SUN3LANCE -++ tristate "Sun3/Sun3x on-board LANCE support" -++ depends on SUN3 || SUN3X -++ help -++ Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80) -++ featured an AMD Lance 10Mbit Ethernet controller on board; say Y -++ here to compile in the Linux driver for this and enable Ethernet. -++ General Linux information on the Sun 3 and 3x series (now -++ discontinued) is at -++ . -++ -++ If you're not building a kernel for a Sun 3, say N. -++ -++config SUN3_82586 -++ bool "Sun3 on-board Intel 82586 support" -++ depends on SUN3 -++ help -++ This driver enables support for the on-board Intel 82586 based -++ Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards. Note -++ that this driver does not support 82586-based adapters on additional -++ VME boards. -++ -++config HPLANCE -++ bool "HP on-board LANCE support" -++ depends on DIO -++ select CRC32 -++ help -++ If you want to use the builtin "LANCE" Ethernet controller on an -++ HP300 machine, say Y here. -++ -++config LASI_82596 -++ tristate "Lasi ethernet" -++ depends on GSC -++ help -++ Say Y here to support the builtin Intel 82596 ethernet controller -++ found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet. -++ -++config SNI_82596 -++ tristate "SNI RM ethernet" -++ depends on NET_ETHERNET && SNI_RM -++ help -++ Say Y here to support the on-board Intel 82596 ethernet controller -++ built into SNI RM machines. -++ -++config MIPS_JAZZ_SONIC -++ tristate "MIPS JAZZ onboard SONIC Ethernet support" -++ depends on MACH_JAZZ -++ help -++ This is the driver for the onboard card of MIPS Magnum 4000, -++ Acer PICA, Olivetti M700-10 and a few other identical OEM systems. -++ -++config MIPS_AU1X00_ENET -++ bool "MIPS AU1000 Ethernet support" -++ depends on SOC_AU1X00 -++ select PHYLIB -++ select CRC32 -++ help -++ If you have an Alchemy Semi AU1X00 based system -++ say Y. Otherwise, say N. -++ -++config SGI_IOC3_ETH -++ bool "SGI IOC3 Ethernet" -++ depends on PCI && SGI_IP27 -++ select CRC32 -++ select MII -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++config MIPS_SIM_NET -++ tristate "MIPS simulator Network device" -++ depends on MIPS_SIM -++ help -++ The MIPSNET device is a simple Ethernet network device which is -++ emulated by the MIPS Simulator. -++ If you are not using a MIPSsim or are unsure, say N. -++ -++config SGI_O2MACE_ETH -++ tristate "SGI O2 MACE Fast Ethernet support" -++ depends on SGI_IP32=y -++ -++config STNIC -++ tristate "National DP83902AV support" -++ depends on SUPERH -++ select CRC32 -++ help -++ Support for cards based on the National Semiconductor DP83902AV -++ ST-NIC Serial Network Interface Controller for Twisted Pair. This -++ is a 10Mbit/sec Ethernet controller. Product overview and specs at -++ . -++ -++ If unsure, say N. -++ -++config SUNLANCE -++ tristate "Sun LANCE support" -++ depends on SBUS -++ select CRC32 -++ help -++ This driver supports the "le" interface present on all 32-bit Sparc -++ systems, on some older Ultra systems and as an Sbus option. These -++ cards are based on the AMD Lance chipset, which is better known -++ via the NE2100 cards. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called sunlance. -++ -++config HAPPYMEAL -++ tristate "Sun Happy Meal 10/100baseT support" -++ depends on SBUS || PCI -++ select CRC32 -++ help -++ This driver supports the "hme" interface present on most Ultra -++ systems and as an option on older Sbus systems. This driver supports -++ both PCI and Sbus devices. This driver also supports the "qfe" quad -++ 100baseT device available in both PCI and Sbus configurations. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called sunhme. -++ -++config SUNBMAC -++ tristate "Sun BigMAC 10/100baseT support (EXPERIMENTAL)" -++ depends on SBUS && EXPERIMENTAL -++ select CRC32 -++ help -++ This driver supports the "be" interface available as an Sbus option. -++ This is Sun's older 100baseT Ethernet device. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called sunbmac. -++ -++config SUNQE -++ tristate "Sun QuadEthernet support" -++ depends on SBUS -++ select CRC32 -++ help -++ This driver supports the "qe" 10baseT Ethernet device, available as -++ an Sbus option. Note that this is not the same as Quad FastEthernet -++ "qfe" which is supported by the Happy Meal driver instead. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called sunqe. -++ -++config SUNGEM -++ tristate "Sun GEM support" -++ depends on PCI -++ select CRC32 -++ help -++ Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also -++ . -++ -++config CASSINI -++ tristate "Sun Cassini support" -++ depends on PCI -++ select CRC32 -++ help -++ Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also -++ -++ -++config SUNVNET -++ tristate "Sun Virtual Network support" -++ depends on SUN_LDOMS -++ help -++ Support for virtual network devices under Sun Logical Domains. -++ -++config NET_VENDOR_3COM -++ bool "3COM cards" -++ depends on ISA || EISA || MCA || PCI -++ help -++ If you have a network (Ethernet) card belonging to this class, say Y -++ and read the Ethernet-HOWTO, available from -++ . -++ -++ Note that the answer to this question doesn't directly affect the -++ kernel: saying N will just cause the configurator to skip all -++ the questions about 3COM cards. If you say Y, you will be asked for -++ your specific card in the following questions. -++ -++config EL1 -++ tristate "3c501 \"EtherLink\" support" -++ depends on NET_VENDOR_3COM && ISA -++ ---help--- -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . Also, consider buying a -++ new card, since the 3c501 is slow, broken, and obsolete: you will -++ have problems. Some people suggest to ping ("man ping") a nearby -++ machine every minute ("man cron") when using this card. -++ -++ To compile this driver as a module, choose M here. The module -++ will be called 3c501. -++ -++config EL2 -++ tristate "3c503 \"EtherLink II\" support" -++ depends on NET_VENDOR_3COM && ISA -++ select CRC32 -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called 3c503. -++ -++config ELPLUS -++ tristate "3c505 \"EtherLink Plus\" support" -++ depends on NET_VENDOR_3COM && ISA && ISA_DMA_API -++ ---help--- -++ Information about this network (Ethernet) card can be found in -++ . If you have a card of -++ this type, say Y and read the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called 3c505. -++ -++config EL16 -++ tristate "3c507 \"EtherLink 16\" support (EXPERIMENTAL)" -++ depends on NET_VENDOR_3COM && ISA && EXPERIMENTAL -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called 3c507. -++ -++config EL3 -++ tristate "3c509/3c529 (MCA)/3c579 \"EtherLink III\" support" -++ depends on NET_VENDOR_3COM && (ISA || EISA || MCA) -++ ---help--- -++ If you have a network (Ethernet) card belonging to the 3Com -++ EtherLinkIII series, say Y and read the Ethernet-HOWTO, available -++ from . -++ -++ If your card is not working you may need to use the DOS -++ setup disk to disable Plug & Play mode, and to select the default -++ media type. -++ -++ To compile this driver as a module, choose M here. The module -++ will be called 3c509. -++ -++config 3C515 -++ tristate "3c515 ISA \"Fast EtherLink\"" -++ depends on NET_VENDOR_3COM && (ISA || EISA) && ISA_DMA_API -++ help -++ If you have a 3Com ISA EtherLink XL "Corkscrew" 3c515 Fast Ethernet -++ network card, say Y and read the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called 3c515. -++ -++config ELMC -++ tristate "3c523 \"EtherLink/MC\" support" -++ depends on NET_VENDOR_3COM && MCA_LEGACY -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called 3c523. -++ -++config ELMC_II -++ tristate "3c527 \"EtherLink/MC 32\" support (EXPERIMENTAL)" -++ depends on NET_VENDOR_3COM && MCA && MCA_LEGACY -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called 3c527. -++ -++config VORTEX -++ tristate "3c590/3c900 series (592/595/597) \"Vortex/Boomerang\" support" -++ depends on NET_VENDOR_3COM && (PCI || EISA) -++ select MII -++ ---help--- -++ This option enables driver support for a large number of 10Mbps and -++ 10/100Mbps EISA, PCI and PCMCIA 3Com network cards: -++ -++ "Vortex" (Fast EtherLink 3c590/3c592/3c595/3c597) EISA and PCI -++ "Boomerang" (EtherLink XL 3c900 or 3c905) PCI -++ "Cyclone" (3c540/3c900/3c905/3c980/3c575/3c656) PCI and Cardbus -++ "Tornado" (3c905) PCI -++ "Hurricane" (3c555/3cSOHO) PCI -++ -++ If you have such a card, say Y and read the Ethernet-HOWTO, -++ available from . More -++ specific information is in -++ and in the comments at -++ the beginning of . -++ -++ To compile this support as a module, choose M here. -++ -++config TYPHOON -++ tristate "3cr990 series \"Typhoon\" support" -++ depends on NET_VENDOR_3COM && PCI -++ select CRC32 -++ ---help--- -++ This option enables driver support for the 3cr990 series of cards: -++ -++ 3C990-TX, 3CR990-TX-95, 3CR990-TX-97, 3CR990-FX-95, 3CR990-FX-97, -++ 3CR990SVR, 3CR990SVR95, 3CR990SVR97, 3CR990-FX-95 Server, -++ 3CR990-FX-97 Server, 3C990B-TX-M, 3C990BSVR -++ -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called typhoon. -++ -++config LANCE -++ tristate "AMD LANCE and PCnet (AT1500 and NE2100) support" -++ depends on ISA && ISA_DMA_API -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . Some LinkSys cards are -++ of this type. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called lance. This is recommended. -++ -++config NET_VENDOR_SMC -++ bool "Western Digital/SMC cards" -++ depends on ISA || MCA || EISA || MAC -++ help -++ If you have a network (Ethernet) card belonging to this class, say Y -++ and read the Ethernet-HOWTO, available from -++ . -++ -++ Note that the answer to this question doesn't directly affect the -++ kernel: saying N will just cause the configurator to skip all -++ the questions about Western Digital cards. If you say Y, you will be -++ asked for your specific card in the following questions. -++ -++config WD80x3 -++ tristate "WD80*3 support" -++ depends on NET_VENDOR_SMC && ISA -++ select CRC32 -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called wd. -++ -++config ULTRAMCA -++ tristate "SMC Ultra MCA support" -++ depends on NET_VENDOR_SMC && MCA -++ select CRC32 -++ help -++ If you have a network (Ethernet) card of this type and are running -++ an MCA based system (PS/2), say Y and read the Ethernet-HOWTO, -++ available from . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called smc-mca. -++ -++config ULTRA -++ tristate "SMC Ultra support" -++ depends on NET_VENDOR_SMC && ISA -++ select CRC32 -++ ---help--- -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ Important: There have been many reports that, with some motherboards -++ mixing an SMC Ultra and an Adaptec AHA154x SCSI card (or compatible, -++ such as some BusLogic models) causes corruption problems with many -++ operating systems. The Linux smc-ultra driver has a work-around for -++ this but keep it in mind if you have such a SCSI card and have -++ problems. -++ -++ To compile this driver as a module, choose M here. The module -++ will be called smc-ultra. -++ -++config ULTRA32 -++ tristate "SMC Ultra32 EISA support" -++ depends on NET_VENDOR_SMC && EISA -++ select CRC32 -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called smc-ultra32. -++ -++config BFIN_MAC -++ tristate "Blackfin 536/537 on-chip mac support" -++ depends on NET_ETHERNET && (BF537 || BF536) && (!BF537_PORT_H) -++ select CRC32 -++ select MII -++ select PHYLIB -++ select BFIN_MAC_USE_L1 if DMA_UNCACHED_NONE -++ help -++ This is the driver for blackfin on-chip mac device. Say Y if you want it -++ compiled into the kernel. This driver is also available as a module -++ ( = code which can be inserted in and removed from the running kernel -++ whenever you want). The module will be called bfin_mac. -++ -++config BFIN_MAC_USE_L1 -++ bool "Use L1 memory for rx/tx packets" -++ depends on BFIN_MAC && BF537 -++ default y -++ help -++ To get maximum network performance, you should use L1 memory as rx/tx buffers. -++ Say N here if you want to reserve L1 memory for other uses. -++ -++config BFIN_TX_DESC_NUM -++ int "Number of transmit buffer packets" -++ depends on BFIN_MAC -++ range 6 10 if BFIN_MAC_USE_L1 -++ range 10 100 -++ default "10" -++ help -++ Set the number of buffer packets used in driver. -++ -++config BFIN_RX_DESC_NUM -++ int "Number of receive buffer packets" -++ depends on BFIN_MAC -++ range 20 100 if BFIN_MAC_USE_L1 -++ range 20 800 -++ default "20" -++ help -++ Set the number of buffer packets used in driver. -++ -++config BFIN_MAC_RMII -++ bool "RMII PHY Interface (EXPERIMENTAL)" -++ depends on BFIN_MAC && EXPERIMENTAL -++ default n -++ help -++ Use Reduced PHY MII Interface -++ -++config SMC9194 -++ tristate "SMC 9194 support" -++ depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN) -++ select CRC32 -++ ---help--- -++ This is support for the SMC9xxx based Ethernet cards. Choose this -++ option if you have a DELL laptop with the docking station, or -++ another SMC9192/9194 based chipset. Say Y if you want it compiled -++ into the kernel, and read the file -++ and the Ethernet-HOWTO, -++ available from . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called smc9194. -++ -++config SMC91X -++ tristate "SMC 91C9x/91C1xxx support" -++ select CRC32 -++ select MII -++ depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BLACKFIN -++ help -++ This is a driver for SMC's 91x series of Ethernet chipsets, -++ including the SMC91C94 and the SMC91C111. Say Y if you want it -++ compiled into the kernel, and read the file -++ and the Ethernet-HOWTO, -++ available from . -++ -++ This driver is also available as a module ( = code which can be -++ inserted in and removed from the running kernel whenever you want). -++ The module will be called smc91x. If you want to compile it as a -++ module, say M here and read . -++ -++config NET_NETX -++ tristate "NetX Ethernet support" -++ select MII -++ depends on ARCH_NETX -++ help -++ This is support for the Hilscher netX builtin Ethernet ports -++ -++ To compile this driver as a module, choose M here. The module -++ will be called netx-eth. -++ -++config DM9000 -++ tristate "DM9000 support" -++ depends on ARM || BLACKFIN || MIPS -++ select CRC32 -++ select MII -++ ---help--- -++ Support for DM9000 chipset. -++ -++ To compile this driver as a module, choose M here. The module -++ will be called dm9000. -++ -++config SMC911X -++ tristate "SMSC LAN911[5678] support" -++ select CRC32 -++ select MII -++ depends on ARCH_PXA || SH_MAGIC_PANEL_R2 -++ help -++ This is a driver for SMSC's LAN911x series of Ethernet chipsets -++ including the new LAN9115, LAN9116, LAN9117, and LAN9118. -++ Say Y if you want it compiled into the kernel, -++ and read the Ethernet-HOWTO, available from -++ . -++ -++ This driver is also available as a module. The module will be -++ called smc911x. If you want to compile it as a module, say M -++ here and read -++ -++config NET_VENDOR_RACAL -++ bool "Racal-Interlan (Micom) NI cards" -++ depends on ISA -++ help -++ If you have a network (Ethernet) card belonging to this class, such -++ as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO, -++ available from . -++ -++ Note that the answer to this question doesn't directly affect the -++ kernel: saying N will just cause the configurator to skip all -++ the questions about NI cards. If you say Y, you will be asked for -++ your specific card in the following questions. -++ -++config NI5010 -++ tristate "NI5010 support (EXPERIMENTAL)" -++ depends on NET_VENDOR_RACAL && ISA && EXPERIMENTAL && BROKEN_ON_SMP -++ ---help--- -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . Note that this is still -++ experimental code. -++ -++ To compile this driver as a module, choose M here. The module -++ will be called ni5010. -++ -++config NI52 -++ tristate "NI5210 support" -++ depends on NET_VENDOR_RACAL && ISA -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called ni52. -++ -++config NI65 -++ tristate "NI6510 support" -++ depends on NET_VENDOR_RACAL && ISA && ISA_DMA_API -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called ni65. -++ -++source "drivers/net/tulip/Kconfig" -++ -++config AT1700 -++ tristate "AT1700/1720 support (EXPERIMENTAL)" -++ depends on (ISA || MCA_LEGACY) && EXPERIMENTAL -++ select CRC32 -++ ---help--- -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called at1700. -++ -++config DEPCA -++ tristate "DEPCA, DE10x, DE200, DE201, DE202, DE422 support" -++ depends on ISA || EISA || MCA -++ select CRC32 -++ ---help--- -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ as well as -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called depca. -++ -++config HP100 -++ tristate "HP 10/100VG PCLAN (ISA, EISA, PCI) support" -++ depends on ISA || EISA || PCI -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called hp100. -++ -++config NET_ISA -++ bool "Other ISA cards" -++ depends on ISA -++ ---help--- -++ If your network (Ethernet) card hasn't been mentioned yet and its -++ bus system (that's the way the cards talks to the other components -++ of your computer) is ISA (as opposed to EISA, VLB or PCI), say Y. -++ Make sure you know the name of your card. Read the Ethernet-HOWTO, -++ available from . -++ -++ If unsure, say Y. -++ -++ Note that the answer to this question doesn't directly affect the -++ kernel: saying N will just cause the configurator to skip all -++ the remaining ISA network card questions. If you say Y, you will be -++ asked for your specific card in the following questions. -++ -++config E2100 -++ tristate "Cabletron E21xx support" -++ depends on NET_ISA -++ select CRC32 -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called e2100. -++ -++config EWRK3 -++ tristate "EtherWORKS 3 (DE203, DE204, DE205) support" -++ depends on NET_ISA -++ select CRC32 -++ ---help--- -++ This driver supports the DE203, DE204 and DE205 network (Ethernet) -++ cards. If this is for you, say Y and read -++ in the kernel source as -++ well as the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called ewrk3. -++ -++config EEXPRESS -++ tristate "EtherExpress 16 support" -++ depends on NET_ISA -++ ---help--- -++ If you have an EtherExpress16 network (Ethernet) card, say Y and -++ read the Ethernet-HOWTO, available from -++ . Note that the Intel -++ EtherExpress16 card used to be regarded as a very poor choice -++ because the driver was very unreliable. We now have a new driver -++ that should do better. -++ -++ To compile this driver as a module, choose M here. The module -++ will be called eexpress. -++ -++config EEXPRESS_PRO -++ tristate "EtherExpressPro support/EtherExpress 10 (i82595) support" -++ depends on NET_ISA -++ ---help--- -++ If you have a network (Ethernet) card of this type, say Y. This -++ driver supports Intel i82595{FX,TX} based boards. Note however -++ that the EtherExpress PRO/100 Ethernet card has its own separate -++ driver. Please read the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called eepro. -++ -++config HPLAN_PLUS -++ tristate "HP PCLAN+ (27247B and 27252A) support" -++ depends on NET_ISA -++ select CRC32 -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called hp-plus. -++ -++config HPLAN -++ tristate "HP PCLAN (27245 and other 27xxx series) support" -++ depends on NET_ISA -++ select CRC32 -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called hp. -++ -++config LP486E -++ tristate "LP486E on board Ethernet" -++ depends on NET_ISA -++ help -++ Say Y here to support the 82596-based on-board Ethernet controller -++ for the Panther motherboard, which is one of the two shipped in the -++ Intel Professional Workstation. -++ -++config ETH16I -++ tristate "ICL EtherTeam 16i/32 support" -++ depends on NET_ISA -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called eth16i. -++ -++config NE2000 -++ tristate "NE2000/NE1000 support" -++ depends on NET_ISA || (Q40 && m) || M32R || TOSHIBA_RBTX4927 || TOSHIBA_RBTX4938 -++ select CRC32 -++ ---help--- -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . Many Ethernet cards -++ without a specific driver are compatible with NE2000. -++ -++ If you have a PCI NE2000 card however, say N here and Y to "PCI -++ NE2000 and clone support" under "EISA, VLB, PCI and on board -++ controllers" below. If you have a NE2000 card and are running on -++ an MCA system (a bus system used on some IBM PS/2 computers and -++ laptops), say N here and Y to "NE/2 (ne2000 MCA version) support", -++ below. -++ -++ To compile this driver as a module, choose M here. The module -++ will be called ne. -++ -++config ZNET -++ tristate "Zenith Z-Note support (EXPERIMENTAL)" -++ depends on NET_ISA && EXPERIMENTAL && ISA_DMA_API -++ help -++ The Zenith Z-Note notebook computer has a built-in network -++ (Ethernet) card, and this is the Linux driver for it. Note that the -++ IBM Thinkpad 300 is compatible with the Z-Note and is also supported -++ by this driver. Read the Ethernet-HOWTO, available from -++ . -++ -++config SEEQ8005 -++ tristate "SEEQ8005 support (EXPERIMENTAL)" -++ depends on NET_ISA && EXPERIMENTAL -++ help -++ This is a driver for the SEEQ 8005 network (Ethernet) card. If this -++ is for you, read the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called seeq8005. -++ -++config NE2_MCA -++ tristate "NE/2 (ne2000 MCA version) support" -++ depends on MCA_LEGACY -++ select CRC32 -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called ne2. -++ -++config IBMLANA -++ tristate "IBM LAN Adapter/A support" -++ depends on MCA && MCA_LEGACY -++ ---help--- -++ This is a Micro Channel Ethernet adapter. You need to set -++ CONFIG_MCA to use this driver. It is both available as an in-kernel -++ driver and as a module. -++ -++ To compile this driver as a module, choose M here. The only -++ currently supported card is the IBM LAN Adapter/A for Ethernet. It -++ will both support 16K and 32K memory windows, however a 32K window -++ gives a better security against packet losses. Usage of multiple -++ boards with this driver should be possible, but has not been tested -++ up to now due to lack of hardware. -++ -++config IBMVETH -++ tristate "IBM LAN Virtual Ethernet support" -++ depends on PPC_PSERIES -++ ---help--- -++ This driver supports virtual ethernet adapters on newer IBM iSeries -++ and pSeries systems. -++ -++ To compile this driver as a module, choose M here. The module will -++ be called ibmveth. -++ -++source "drivers/net/ibm_emac/Kconfig" -++source "drivers/net/ibm_newemac/Kconfig" -++ -++config NET_PCI -++ bool "EISA, VLB, PCI and on board controllers" -++ depends on ISA || EISA || PCI -++ help -++ This is another class of network cards which attach directly to the -++ bus. If you have one of those, say Y and read the Ethernet-HOWTO, -++ available from . -++ -++ Note that the answer to this question doesn't directly affect the -++ kernel: saying N will just cause the configurator to skip all -++ the questions about this class of network cards. If you say Y, you -++ will be asked for your specific card in the following questions. If -++ you are unsure, say Y. -++ -++config PCNET32 -++ tristate "AMD PCnet32 PCI support" -++ depends on NET_PCI && PCI -++ select CRC32 -++ select MII -++ help -++ If you have a PCnet32 or PCnetPCI based network (Ethernet) card, -++ answer Y here and read the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called pcnet32. -++ -++config PCNET32_NAPI -++ bool "Use RX polling (NAPI)" -++ depends on PCNET32 -++ help -++ NAPI is a new driver API designed to reduce CPU and interrupt load -++ when the driver is receiving lots of packets from the card. It is -++ still somewhat experimental and thus not yet enabled by default. -++ -++ If your estimated Rx load is 10kpps or more, or if the card will be -++ deployed on potentially unfriendly networks (e.g. in a firewall), -++ then say Y here. -++ -++ If in doubt, say N. -++ -++config AMD8111_ETH -++ tristate "AMD 8111 (new PCI lance) support" -++ depends on NET_PCI && PCI -++ select CRC32 -++ select MII -++ help -++ If you have an AMD 8111-based PCI lance ethernet card, -++ answer Y here and read the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called amd8111e. -++ -++config AMD8111E_NAPI -++ bool "Use RX polling (NAPI)" -++ depends on AMD8111_ETH -++ help -++ NAPI is a new driver API designed to reduce CPU and interrupt load -++ when the driver is receiving lots of packets from the card. It is -++ still somewhat experimental and thus not yet enabled by default. -++ -++ If your estimated Rx load is 10kpps or more, or if the card will be -++ deployed on potentially unfriendly networks (e.g. in a firewall), -++ then say Y here. -++ -++ If in doubt, say N. -++ -++config ADAPTEC_STARFIRE -++ tristate "Adaptec Starfire/DuraLAN support" -++ depends on NET_PCI && PCI -++ select CRC32 -++ select MII -++ help -++ Say Y here if you have an Adaptec Starfire (or DuraLAN) PCI network -++ adapter. The DuraLAN chip is used on the 64 bit PCI boards from -++ Adaptec e.g. the ANA-6922A. The older 32 bit boards use the tulip -++ driver. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called starfire. This is recommended. -++ -++config ADAPTEC_STARFIRE_NAPI -++ bool "Use Rx Polling (NAPI) (EXPERIMENTAL)" -++ depends on ADAPTEC_STARFIRE && EXPERIMENTAL -++ help -++ NAPI is a new driver API designed to reduce CPU and interrupt load -++ when the driver is receiving lots of packets from the card. It is -++ still somewhat experimental and thus not yet enabled by default. -++ -++ If your estimated Rx load is 10kpps or more, or if the card will be -++ deployed on potentially unfriendly networks (e.g. in a firewall), -++ then say Y here. -++ -++ If in doubt, say N. -++ -++config AC3200 -++ tristate "Ansel Communications EISA 3200 support (EXPERIMENTAL)" -++ depends on NET_PCI && (ISA || EISA) && EXPERIMENTAL -++ select CRC32 -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called ac3200. -++ -++config APRICOT -++ tristate "Apricot Xen-II on board Ethernet" -++ depends on NET_PCI && ISA -++ help -++ If you have a network (Ethernet) controller of this type, say Y and -++ read the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called apricot. -++ -++config B44 -++ tristate "Broadcom 440x/47xx ethernet support" -++ depends on SSB_POSSIBLE -++ select SSB -++ select MII -++ help -++ If you have a network (Ethernet) controller of this type, say Y -++ or M and read the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called b44. -++ -++# Auto-select SSB PCI-HOST support, if possible -++config B44_PCI_AUTOSELECT -++ bool -++ depends on B44 && SSB_PCIHOST_POSSIBLE -++ select SSB_PCIHOST -++ default y -++ -++# Auto-select SSB PCICORE driver, if possible -++config B44_PCICORE_AUTOSELECT -++ bool -++ depends on B44 && SSB_DRIVER_PCICORE_POSSIBLE -++ select SSB_DRIVER_PCICORE -++ default y -++ -++config B44_PCI -++ bool -++ depends on B44_PCI_AUTOSELECT && B44_PCICORE_AUTOSELECT -++ default y -++ -++config FORCEDETH -++ tristate "nForce Ethernet support" -++ depends on NET_PCI && PCI -++ help -++ If you have a network (Ethernet) controller of this type, say Y and -++ read the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called forcedeth. -++ -++config FORCEDETH_NAPI -++ bool "Use Rx Polling (NAPI) (EXPERIMENTAL)" -++ depends on FORCEDETH && EXPERIMENTAL -++ help -++ NAPI is a new driver API designed to reduce CPU and interrupt load -++ when the driver is receiving lots of packets from the card. It is -++ still somewhat experimental and thus not yet enabled by default. -++ -++ If your estimated Rx load is 10kpps or more, or if the card will be -++ deployed on potentially unfriendly networks (e.g. in a firewall), -++ then say Y here. -++ -++ If in doubt, say N. -++ -++config CS89x0 -++ tristate "CS89x0 support" -++ depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X) -++ ---help--- -++ Support for CS89x0 chipset based Ethernet cards. If you have a -++ network (Ethernet) card of this type, say Y and read the -++ Ethernet-HOWTO, available from -++ as well as -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called cs89x0. -++ -++config TC35815 -++ tristate "TOSHIBA TC35815 Ethernet support" -++ depends on NET_PCI && PCI && MIPS -++ select MII -++ -++config EEPRO100 -++ tristate "EtherExpressPro/100 support (eepro100, original Becker driver)" -++ depends on NET_PCI && PCI -++ select MII -++ help -++ If you have an Intel EtherExpress PRO/100 PCI network (Ethernet) -++ card, say Y and read the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called eepro100. -++ -++ -++config E100 -++ tristate "Intel(R) PRO/100+ support" -++ depends on NET_PCI && PCI -++ select MII -++ ---help--- -++ This driver supports Intel(R) PRO/100 family of adapters. -++ To verify that your adapter is supported, find the board ID number -++ on the adapter. Look for a label that has a barcode and a number -++ in the format 123456-001 (six digits hyphen three digits). -++ -++ Use the above information and the Adapter & Driver ID Guide at: -++ -++ -++ -++ to identify the adapter. -++ -++ For the latest Intel PRO/100 network driver for Linux, see: -++ -++ -++ -++ More specific information on configuring the driver is in -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called e100. -++ -++config LNE390 -++ tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)" -++ depends on NET_PCI && EISA && EXPERIMENTAL -++ select CRC32 -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called lne390. -++ -++config FEALNX -++ tristate "Myson MTD-8xx PCI Ethernet support" -++ depends on NET_PCI && PCI -++ select CRC32 -++ select MII -++ help -++ Say Y here to support the Mysom MTD-800 family of PCI-based Ethernet -++ cards. Specifications and data at -++ . -++ -++config NATSEMI -++ tristate "National Semiconductor DP8381x series PCI Ethernet support" -++ depends on NET_PCI && PCI -++ select CRC32 -++ help -++ This driver is for the National Semiconductor DP83810 series, -++ which is used in cards from PureData, NetGear, Linksys -++ and others, including the 83815 chip. -++ More specific information and updates are available from -++ . -++ -++config NE2K_PCI -++ tristate "PCI NE2000 and clones support (see help)" -++ depends on NET_PCI && PCI -++ select CRC32 -++ ---help--- -++ This driver is for NE2000 compatible PCI cards. It will not work -++ with ISA NE2000 cards (they have their own driver, "NE2000/NE1000 -++ support" below). If you have a PCI NE2000 network (Ethernet) card, -++ say Y and read the Ethernet-HOWTO, available from -++ . -++ -++ This driver also works for the following NE2000 clone cards: -++ RealTek RTL-8029 Winbond 89C940 Compex RL2000 KTI ET32P2 -++ NetVin NV5000SC Via 86C926 SureCom NE34 Winbond -++ Holtek HT80232 Holtek HT80229 -++ -++ To compile this driver as a module, choose M here. The module -++ will be called ne2k-pci. -++ -++config NE3210 -++ tristate "Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)" -++ depends on NET_PCI && EISA && EXPERIMENTAL -++ select CRC32 -++ ---help--- -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . Note that this driver -++ will NOT WORK for NE3200 cards as they are completely different. -++ -++ To compile this driver as a module, choose M here. The module -++ will be called ne3210. -++ -++config ES3210 -++ tristate "Racal-Interlan EISA ES3210 support (EXPERIMENTAL)" -++ depends on NET_PCI && EISA && EXPERIMENTAL -++ select CRC32 -++ help -++ If you have a network (Ethernet) card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called es3210. -++ -++config 8139CP -++ tristate "RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support (EXPERIMENTAL)" -++ depends on NET_PCI && PCI && EXPERIMENTAL -++ select CRC32 -++ select MII -++ help -++ This is a driver for the Fast Ethernet PCI network cards based on -++ the RTL8139C+ chips. If you have one of those, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here: the module -++ will be called 8139cp. This is recommended. -++ -++config 8139TOO -++ tristate "RealTek RTL-8129/8130/8139 PCI Fast Ethernet Adapter support" -++ depends on NET_PCI && PCI -++ select CRC32 -++ select MII -++ ---help--- -++ This is a driver for the Fast Ethernet PCI network cards based on -++ the RTL 8129/8130/8139 chips. If you have one of those, say Y and -++ read the Ethernet-HOWTO . -++ -++ To compile this driver as a module, choose M here: the module -++ will be called 8139too. This is recommended. -++ -++config 8139TOO_PIO -++ bool "Use PIO instead of MMIO" -++ default y -++ depends on 8139TOO -++ help -++ This instructs the driver to use programmed I/O ports (PIO) instead -++ of PCI shared memory (MMIO). This can possibly solve some problems -++ in case your mainboard has memory consistency issues. If unsure, -++ say N. -++ -++config 8139TOO_TUNE_TWISTER -++ bool "Support for uncommon RTL-8139 rev. K (automatic channel equalization)" -++ depends on 8139TOO -++ help -++ This implements a function which might come in handy in case you -++ are using low quality on long cabling. It is required for RealTek -++ RTL-8139 revision K boards, and totally unused otherwise. It tries -++ to match the transceiver to the cable characteristics. This is -++ experimental since hardly documented by the manufacturer. -++ If unsure, say Y. -++ -++config 8139TOO_8129 -++ bool "Support for older RTL-8129/8130 boards" -++ depends on 8139TOO -++ help -++ This enables support for the older and uncommon RTL-8129 and -++ RTL-8130 chips, which support MII via an external transceiver, -++ instead of an internal one. Disabling this option will save some -++ memory by making the code size smaller. If unsure, say Y. -++ -++config 8139_OLD_RX_RESET -++ bool "Use older RX-reset method" -++ depends on 8139TOO -++ help -++ The 8139too driver was recently updated to contain a more rapid -++ reset sequence, in the face of severe receive errors. This "new" -++ RX-reset method should be adequate for all boards. But if you -++ experience problems, you can enable this option to restore the -++ old RX-reset behavior. If unsure, say N. -++ -++config SIS900 -++ tristate "SiS 900/7016 PCI Fast Ethernet Adapter support" -++ depends on NET_PCI && PCI -++ select CRC32 -++ select MII -++ ---help--- -++ This is a driver for the Fast Ethernet PCI network cards based on -++ the SiS 900 and SiS 7016 chips. The SiS 900 core is also embedded in -++ SiS 630 and SiS 540 chipsets. -++ -++ This driver also supports AMD 79C901 HomePNA so that you can use -++ your phone line as a network cable. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called sis900. This is recommended. -++ -++config EPIC100 -++ tristate "SMC EtherPower II" -++ depends on NET_PCI && PCI -++ select CRC32 -++ select MII -++ help -++ This driver is for the SMC EtherPower II 9432 PCI Ethernet NIC, -++ which is based on the SMC83c17x (EPIC/100). -++ More specific information and updates are available from -++ . -++ -++config SUNDANCE -++ tristate "Sundance Alta support" -++ depends on NET_PCI && PCI -++ select CRC32 -++ select MII -++ help -++ This driver is for the Sundance "Alta" chip. -++ More specific information and updates are available from -++ . -++ -++config SUNDANCE_MMIO -++ bool "Use MMIO instead of PIO" -++ depends on SUNDANCE -++ help -++ Enable memory-mapped I/O for interaction with Sundance NIC registers. -++ Do NOT enable this by default, PIO (enabled when MMIO is disabled) -++ is known to solve bugs on certain chips. -++ -++ If unsure, say N. -++ -++config TLAN -++ tristate "TI ThunderLAN support" -++ depends on NET_PCI && (PCI || EISA) && !64BIT -++ ---help--- -++ If you have a PCI Ethernet network card based on the ThunderLAN chip -++ which is supported by this driver, say Y and read the -++ Ethernet-HOWTO, available from -++ . -++ -++ Devices currently supported by this driver are Compaq Netelligent, -++ Compaq NetFlex and Olicom cards. Please read the file -++ for more details. -++ -++ To compile this driver as a module, choose M here. The module -++ will be called tlan. -++ -++ Please email feedback to . -++ -++config VIA_RHINE -++ tristate "VIA Rhine support" -++ depends on NET_PCI && PCI -++ select CRC32 -++ select MII -++ help -++ If you have a VIA "Rhine" based network card (Rhine-I (VT86C100A), -++ Rhine-II (VT6102), or Rhine-III (VT6105)), say Y here. Rhine-type -++ Ethernet functions can also be found integrated on South Bridges -++ (e.g. VT8235). -++ -++ To compile this driver as a module, choose M here. The module -++ will be called via-rhine. -++ -++config VIA_RHINE_MMIO -++ bool "Use MMIO instead of PIO" -++ depends on VIA_RHINE -++ help -++ This instructs the driver to use PCI shared memory (MMIO) instead of -++ programmed I/O ports (PIO). Enabling this gives an improvement in -++ processing time in parts of the driver. -++ -++ If unsure, say Y. -++ -++config VIA_RHINE_NAPI -++ bool "Use Rx Polling (NAPI)" -++ depends on VIA_RHINE -++ help -++ NAPI is a new driver API designed to reduce CPU and interrupt load -++ when the driver is receiving lots of packets from the card. -++ -++ If your estimated Rx load is 10kpps or more, or if the card will be -++ deployed on potentially unfriendly networks (e.g. in a firewall), -++ then say Y here. -++ -++config LAN_SAA9730 -++ bool "Philips SAA9730 Ethernet support" -++ depends on NET_PCI && PCI && MIPS_ATLAS -++ help -++ The SAA9730 is a combined multimedia and peripheral controller used -++ in thin clients, Internet access terminals, and diskless -++ workstations. -++ See . -++ -++config SC92031 -++ tristate "Silan SC92031 PCI Fast Ethernet Adapter driver (EXPERIMENTAL)" -++ depends on NET_PCI && PCI && EXPERIMENTAL -++ select CRC32 -++ ---help--- -++ This is a driver for the Fast Ethernet PCI network cards based on -++ the Silan SC92031 chip (sometimes also called Rsltek 8139D). If you -++ have one of these, say Y here. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called sc92031. This is recommended. -++ -++config CPMAC -++ tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)" -++ depends on NET_ETHERNET && EXPERIMENTAL && AR7 -++ select PHYLIB -++ select FIXED_PHY -++ select FIXED_MII_100_FDX -++ help -++ TI AR7 CPMAC Ethernet support -++ -++config NET_POCKET -++ bool "Pocket and portable adapters" -++ depends on PARPORT -++ ---help--- -++ Cute little network (Ethernet) devices which attach to the parallel -++ port ("pocket adapters"), commonly used with laptops. If you have -++ one of those, say Y and read the Ethernet-HOWTO, available from -++ . -++ -++ If you want to plug a network (or some other) card into the PCMCIA -++ (or PC-card) slot of your laptop instead (PCMCIA is the standard for -++ credit card size extension cards used by all modern laptops), you -++ need the pcmcia-cs package (location contained in the file -++ ) and you can say N here. -++ -++ Laptop users should read the Linux Laptop home page at -++ or -++ Tuxmobil - Linux on Mobile Computers at . -++ -++ Note that the answer to this question doesn't directly affect the -++ kernel: saying N will just cause the configurator to skip all -++ the questions about this class of network devices. If you say Y, you -++ will be asked for your specific device in the following questions. -++ -++config ATP -++ tristate "AT-LAN-TEC/RealTek pocket adapter support" -++ depends on NET_POCKET && PARPORT && X86 -++ select CRC32 -++ ---help--- -++ This is a network (Ethernet) device which attaches to your parallel -++ port. Read as well as the Ethernet-HOWTO, -++ available from , if you -++ want to use this. If you intend to use this driver, you should have -++ said N to the "Parallel printer support", because the two drivers -++ don't like each other. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called atp. -++ -++config DE600 -++ tristate "D-Link DE600 pocket adapter support" -++ depends on NET_POCKET && PARPORT -++ ---help--- -++ This is a network (Ethernet) device which attaches to your parallel -++ port. Read as well as the -++ Ethernet-HOWTO, available from -++ , if you want to use -++ this. It is possible to have several devices share a single parallel -++ port and it is safe to compile the corresponding drivers into the -++ kernel. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called de600. -++ -++config DE620 -++ tristate "D-Link DE620 pocket adapter support" -++ depends on NET_POCKET && PARPORT -++ ---help--- -++ This is a network (Ethernet) device which attaches to your parallel -++ port. Read as well as the -++ Ethernet-HOWTO, available from -++ , if you want to use -++ this. It is possible to have several devices share a single parallel -++ port and it is safe to compile the corresponding drivers into the -++ kernel. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called de620. -++ -++config SGISEEQ -++ tristate "SGI Seeq ethernet controller support" -++ depends on SGI_IP22 -++ help -++ Say Y here if you have an Seeq based Ethernet network card. This is -++ used in many Silicon Graphics machines. -++ -++config DECLANCE -++ tristate "DEC LANCE ethernet controller support" -++ depends on MACH_DECSTATION -++ select CRC32 -++ help -++ This driver is for the series of Ethernet controllers produced by -++ DEC (now Compaq) based on the AMD Lance chipset, including the -++ DEPCA series. (This chipset is better known via the NE2100 cards.) -++ -++config 68360_ENET -++ bool "Motorola 68360 ethernet controller" -++ depends on M68360 -++ help -++ Say Y here if you want to use the built-in ethernet controller of -++ the Motorola 68360 processor. -++ -++config FEC -++ bool "FEC ethernet controller (of ColdFire CPUs)" -++ depends on M523x || M527x || M5272 || M528x || M520x -++ help -++ Say Y here if you want to use the built-in 10/100 Fast ethernet -++ controller on some Motorola ColdFire processors. -++ -++config FEC2 -++ bool "Second FEC ethernet controller (on some ColdFire CPUs)" -++ depends on FEC -++ help -++ Say Y here if you want to use the second built-in 10/100 Fast -++ ethernet controller on some Motorola ColdFire processors. -++ -++config FEC_MPC52xx -++ tristate "MPC52xx FEC driver" -++ depends on PPC_MERGE && PPC_MPC52xx && PPC_BESTCOMM_FEC -++ select CRC32 -++ select PHYLIB -++ ---help--- -++ This option enables support for the MPC5200's on-chip -++ Fast Ethernet Controller -++ If compiled as module, it will be called 'fec_mpc52xx.ko'. -++ -++config FEC_MPC52xx_MDIO -++ bool "MPC52xx FEC MDIO bus driver" -++ depends on FEC_MPC52xx -++ default y -++ ---help--- -++ The MPC5200's FEC can connect to the Ethernet either with -++ an external MII PHY chip or 10 Mbps 7-wire interface -++ (Motorola? industry standard). -++ If your board uses an external PHY connected to FEC, enable this. -++ If not sure, enable. -++ If compiled as module, it will be called 'fec_mpc52xx_phy.ko'. -++ -++config NE_H8300 -++ tristate "NE2000 compatible support for H8/300" -++ depends on H8300 -++ help -++ Say Y here if you want to use the NE2000 compatible -++ controller on the Renesas H8/300 processor. -++ -++source "drivers/net/fec_8xx/Kconfig" -++source "drivers/net/fs_enet/Kconfig" -++ -++endif # NET_ETHERNET -++ -++# -++# Gigabit Ethernet -++# -++ -++menuconfig NETDEV_1000 -++ bool "Ethernet (1000 Mbit)" -++ depends on !UML -++ default y -++ ---help--- -++ Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common -++ type of Local Area Network (LAN) in universities and companies. -++ -++ Say Y here to get to see options for Gigabit Ethernet drivers. -++ This option alone does not add any kernel code. -++ Note that drivers supporting both 100 and 1000 MBit may be listed -++ under "Ethernet (10 or 100MBit)" instead. -++ -++ If you say N, all options in this submenu will be skipped and disabled. -++ -++if NETDEV_1000 -++ -++config ACENIC -++ tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support" -++ depends on PCI -++ ---help--- -++ Say Y here if you have an Alteon AceNIC, 3Com 3C985(B), NetGear -++ GA620, SGI Gigabit or Farallon PN9000-SX PCI Gigabit Ethernet -++ adapter. The driver allows for using the Jumbo Frame option (9000 -++ bytes/frame) however it requires that your switches can handle this -++ as well. To enable Jumbo Frames, add `mtu 9000' to your ifconfig -++ line. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called acenic. -++ -++config ACENIC_OMIT_TIGON_I -++ bool "Omit support for old Tigon I based AceNICs" -++ depends on ACENIC -++ help -++ Say Y here if you only have Tigon II based AceNICs and want to leave -++ out support for the older Tigon I based cards which are no longer -++ being sold (ie. the original Alteon AceNIC and 3Com 3C985 (non B -++ version)). This will reduce the size of the driver object by -++ app. 100KB. If you are not sure whether your card is a Tigon I or a -++ Tigon II, say N here. -++ -++ The safe and default value for this is N. -++ -++config DL2K -++ tristate "DL2000/TC902x-based Gigabit Ethernet support" -++ depends on PCI -++ select CRC32 -++ help -++ This driver supports DL2000/TC902x-based Gigabit ethernet cards, -++ which includes -++ D-Link DGE-550T Gigabit Ethernet Adapter. -++ D-Link DL2000-based Gigabit Ethernet Adapter. -++ Sundance/Tamarack TC902x Gigabit Ethernet Adapter. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called dl2k. -++ -++config E1000 -++ tristate "Intel(R) PRO/1000 Gigabit Ethernet support" -++ depends on PCI -++ ---help--- -++ This driver supports Intel(R) PRO/1000 gigabit ethernet family of -++ adapters. For more information on how to identify your adapter, go -++ to the Adapter & Driver ID Guide at: -++ -++ -++ -++ For general information and support, go to the Intel support -++ website at: -++ -++ -++ -++ More specific information on configuring the driver is in -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called e1000. -++ -++config E1000_NAPI -++ bool "Use Rx Polling (NAPI)" -++ depends on E1000 -++ help -++ NAPI is a new driver API designed to reduce CPU and interrupt load -++ when the driver is receiving lots of packets from the card. It is -++ still somewhat experimental and thus not yet enabled by default. -++ -++ If your estimated Rx load is 10kpps or more, or if the card will be -++ deployed on potentially unfriendly networks (e.g. in a firewall), -++ then say Y here. -++ -++ If in doubt, say N. -++ -++config E1000_DISABLE_PACKET_SPLIT -++ bool "Disable Packet Split for PCI express adapters" -++ depends on E1000 -++ help -++ Say Y here if you want to use the legacy receive path for PCI express -++ hardware. -++ -++ If in doubt, say N. -++ -++config E1000E -++ tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support" -++ depends on PCI -++ ---help--- -++ This driver supports the PCI-Express Intel(R) PRO/1000 gigabit -++ ethernet family of adapters. For PCI or PCI-X e1000 adapters, -++ use the regular e1000 driver For more information on how to -++ identify your adapter, go to the Adapter & Driver ID Guide at: -++ -++ -++ -++ For general information and support, go to the Intel support -++ website at: -++ -++ -++ -++ To compile this driver as a module, choose M here. The module -++ will be called e1000e. -++ -++config IP1000 -++ tristate "IP1000 Gigabit Ethernet support" -++ depends on PCI && EXPERIMENTAL -++ select MII -++ ---help--- -++ This driver supports IP1000 gigabit Ethernet cards. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called ipg. This is recommended. -++ -++source "drivers/net/ixp2000/Kconfig" -++ -++config MYRI_SBUS -++ tristate "MyriCOM Gigabit Ethernet support" -++ depends on SBUS -++ help -++ This driver supports MyriCOM Sbus gigabit Ethernet cards. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called myri_sbus. This is recommended. -++ -++config NS83820 -++ tristate "National Semiconductor DP83820 support" -++ depends on PCI -++ help -++ This is a driver for the National Semiconductor DP83820 series -++ of gigabit ethernet MACs. Cards using this chipset include -++ the D-Link DGE-500T, PureData's PDP8023Z-TG, SMC's SMC9462TX, -++ SOHO-GA2000T, SOHO-GA2500T. The driver supports the use of -++ zero copy. -++ -++config HAMACHI -++ tristate "Packet Engines Hamachi GNIC-II support" -++ depends on PCI -++ select MII -++ help -++ If you have a Gigabit Ethernet card of this type, say Y and read -++ the Ethernet-HOWTO, available from -++ . -++ -++ To compile this driver as a module, choose M here. The module will be -++ called hamachi. -++ -++config YELLOWFIN -++ tristate "Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)" -++ depends on PCI && EXPERIMENTAL -++ select CRC32 -++ ---help--- -++ Say Y here if you have a Packet Engines G-NIC PCI Gigabit Ethernet -++ adapter or the SYM53C885 Ethernet controller. The Gigabit adapter is -++ used by the Beowulf Linux cluster project. See -++ for more -++ information about this driver in particular and Beowulf in general. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called yellowfin. This is recommended. -++ -++config R8169 -++ tristate "Realtek 8169 gigabit ethernet support" -++ depends on PCI -++ select CRC32 -++ ---help--- -++ Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called r8169. This is recommended. -++ -++config R8169_NAPI -++ bool "Use Rx Polling (NAPI) (EXPERIMENTAL)" -++ depends on R8169 && EXPERIMENTAL -++ help -++ NAPI is a new driver API designed to reduce CPU and interrupt load -++ when the driver is receiving lots of packets from the card. It is -++ still somewhat experimental and thus not yet enabled by default. -++ -++ If your estimated Rx load is 10kpps or more, or if the card will be -++ deployed on potentially unfriendly networks (e.g. in a firewall), -++ then say Y here. -++ -++ If in doubt, say N. -++ -++config R8169_VLAN -++ bool "VLAN support" -++ depends on R8169 && VLAN_8021Q -++ ---help--- -++ Say Y here for the r8169 driver to support the functions required -++ by the kernel 802.1Q code. -++ -++ If in doubt, say Y. -++ -++config SB1250_MAC -++ tristate "SB1250 Gigabit Ethernet support" -++ depends on SIBYTE_SB1xxx_SOC -++ select PHYLIB -++ ---help--- -++ This driver supports Gigabit Ethernet interfaces based on the -++ Broadcom SiByte family of System-On-a-Chip parts. They include -++ the BCM1120, BCM1125, BCM1125H, BCM1250, BCM1255, BCM1280, BCM1455 -++ and BCM1480 chips. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called sb1250-mac. -++ -++config SIS190 -++ tristate "SiS190/SiS191 gigabit ethernet support" -++ depends on PCI -++ select CRC32 -++ select MII -++ ---help--- -++ Say Y here if you have a SiS 190 PCI Fast Ethernet adapter or -++ a SiS 191 PCI Gigabit Ethernet adapter. Both are expected to -++ appear in lan on motherboard designs which are based on SiS 965 -++ and SiS 966 south bridge. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called sis190. This is recommended. -++ -++config SKGE -++ tristate "New SysKonnect GigaEthernet support" -++ depends on PCI -++ select CRC32 -++ ---help--- -++ This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx -++ and related Gigabit Ethernet adapters. It is a new smaller driver -++ with better performance and more complete ethtool support. -++ -++ It does not support the link failover and network management -++ features that "portable" vendor supplied sk98lin driver does. -++ -++ This driver supports adapters based on the original Yukon chipset: -++ Marvell 88E8001, Belkin F5D5005, CNet GigaCard, DLink DGE-530T, -++ Linksys EG1032/EG1064, 3Com 3C940/3C940B, SysKonnect SK-9871/9872. -++ -++ It does not support the newer Yukon2 chipset: a separate driver, -++ sky2, is provided for Yukon2-based adapters. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called skge. This is recommended. -++ -++config SKGE_DEBUG -++ bool "Debugging interface" -++ depends on SKGE && DEBUG_FS -++ help -++ This option adds the ability to dump driver state for debugging. -++ The file debugfs/skge/ethX displays the state of the internal -++ transmit and receive rings. -++ -++ If unsure, say N. -++ -++config SKY2 -++ tristate "SysKonnect Yukon2 support" -++ depends on PCI -++ select CRC32 -++ ---help--- -++ This driver supports Gigabit Ethernet adapters based on the -++ Marvell Yukon 2 chipset: -++ Marvell 88E8021/88E8022/88E8035/88E8036/88E8038/88E8050/88E8052/ -++ 88E8053/88E8055/88E8061/88E8062, SysKonnect SK-9E21D/SK-9S21 -++ -++ There is companion driver for the older Marvell Yukon and -++ Genesis based adapters: skge. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called sky2. This is recommended. -++ -++config SKY2_DEBUG -++ bool "Debugging interface" -++ depends on SKY2 && DEBUG_FS -++ help -++ This option adds the ability to dump driver state for debugging. -++ The file debugfs/sky2/ethX displays the state of the internal -++ transmit and receive rings. -++ -++ If unsure, say N. -++ -++config SK98LIN -++ tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support (DEPRECATED)" -++ depends on PCI -++ ---help--- -++ Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx -++ compliant Gigabit Ethernet Adapter. -++ -++ This driver supports the original Yukon chipset. This driver is -++ deprecated and will be removed from the kernel in the near future, -++ it has been replaced by the skge driver. skge is cleaner and -++ seems to work better. -++ -++ This driver does not support the newer Yukon2 chipset. A separate -++ driver, sky2, is provided to support Yukon2-based adapters. -++ -++ The following adapters are supported by this driver: -++ - 3Com 3C940 Gigabit LOM Ethernet Adapter -++ - 3Com 3C941 Gigabit LOM Ethernet Adapter -++ - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter -++ - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter -++ - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter -++ - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter -++ - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter -++ - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter -++ - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter -++ - Allied Telesyn AT-2971T Gigabit Ethernet Adapter -++ - Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45 -++ - EG1032 v2 Instant Gigabit Network Adapter -++ - EG1064 v2 Instant Gigabit Network Adapter -++ - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit) -++ - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Albatron) -++ - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus) -++ - Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS) -++ - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Epox) -++ - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn) -++ - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte) -++ - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill) -++ - Marvell 88E8050 Gigabit LOM Ethernet Adapter (Intel) -++ - Marvell RDK-8001 Adapter -++ - Marvell RDK-8002 Adapter -++ - Marvell RDK-8003 Adapter -++ - Marvell RDK-8004 Adapter -++ - Marvell RDK-8006 Adapter -++ - Marvell RDK-8007 Adapter -++ - Marvell RDK-8008 Adapter -++ - Marvell RDK-8009 Adapter -++ - Marvell RDK-8010 Adapter -++ - Marvell RDK-8011 Adapter -++ - Marvell RDK-8012 Adapter -++ - Marvell RDK-8052 Adapter -++ - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit) -++ - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit) -++ - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L) -++ - SK-9521 10/100/1000Base-T Adapter -++ - SK-9521 V2.0 10/100/1000Base-T Adapter -++ - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T) -++ - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter -++ - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link) -++ - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX) -++ - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter -++ - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link) -++ - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX) -++ - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter -++ - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link) -++ - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter -++ - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition) -++ - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter -++ - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link) -++ - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX) -++ - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter -++ - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) -++ - SMC EZ Card 1000 (SMC9452TXV.2) -++ -++ The adapters support Jumbo Frames. -++ The dual link adapters support link-failover and dual port features. -++ Both Marvell Yukon and SysKonnect SK-98xx/SK-95xx adapters support -++ the scatter-gather functionality with sendfile(). Please refer to -++ for more information about -++ optional driver parameters. -++ Questions concerning this driver may be addressed to: -++ -++ -++ If you want to compile this driver as a module ( = code which can be -++ inserted in and removed from the running kernel whenever you want), -++ say M here and read . The module will -++ be called sk98lin. This is recommended. -++ -++config VIA_VELOCITY -++ tristate "VIA Velocity support" -++ depends on PCI -++ select CRC32 -++ select CRC_CCITT -++ select MII -++ help -++ If you have a VIA "Velocity" based network card say Y here. -++ -++ To compile this driver as a module, choose M here. The module -++ will be called via-velocity. -++ -++config TIGON3 -++ tristate "Broadcom Tigon3 support" -++ depends on PCI -++ help -++ This driver supports Broadcom Tigon3 based gigabit Ethernet cards. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called tg3. This is recommended. -++ -++config BNX2 -++ tristate "Broadcom NetXtremeII support" -++ depends on PCI -++ select CRC32 -++ select ZLIB_INFLATE -++ help -++ This driver supports Broadcom NetXtremeII gigabit Ethernet cards. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called bnx2. This is recommended. -++ -++config SPIDER_NET -++ tristate "Spider Gigabit Ethernet driver" -++ depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB) -++ select FW_LOADER -++ help -++ This driver supports the Gigabit Ethernet chips present on the -++ Cell Processor-Based Blades from IBM. -++ -++config TSI108_ETH -++ tristate "Tundra TSI108 gigabit Ethernet support" -++ depends on TSI108_BRIDGE -++ help -++ This driver supports Tundra TSI108 gigabit Ethernet ports. -++ To compile this driver as a module, choose M here: the module -++ will be called tsi108_eth. -++ -++config GELIC_NET -++ tristate "PS3 Gigabit Ethernet driver" -++ depends on PPC_PS3 -++ help -++ This driver supports the network device on the PS3 game -++ console. This driver has built-in support for Ethernet. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called ps3_gelic. -++ -++config GIANFAR -++ tristate "Gianfar Ethernet" -++ depends on 85xx || 83xx || PPC_86xx -++ select PHYLIB -++ select CRC32 -++ help -++ This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx, -++ and MPC86xx family of chips, and the FEC on the 8540. -++ -++config GFAR_NAPI -++ bool "Use Rx Polling (NAPI)" -++ depends on GIANFAR -++ -++config UCC_GETH -++ tristate "Freescale QE Gigabit Ethernet" -++ depends on QUICC_ENGINE -++ select PHYLIB -++ help -++ This driver supports the Gigabit Ethernet mode of the QUICC Engine, -++ which is available on some Freescale SOCs. -++ -++config UGETH_NAPI -++ bool "Use Rx Polling (NAPI)" -++ depends on UCC_GETH -++ -++config UGETH_MAGIC_PACKET -++ bool "Magic Packet detection support" -++ depends on UCC_GETH -++ -++config UGETH_FILTERING -++ bool "Mac address filtering support" -++ depends on UCC_GETH -++ -++config UGETH_TX_ON_DEMAND -++ bool "Transmit on Demand support" -++ depends on UCC_GETH -++ -++config MV643XX_ETH -++ tristate "Marvell Discovery (643XX) and Orion ethernet support" -++ depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || ARCH_ORION -++ select MII -++ help -++ This driver supports the gigabit ethernet MACs in the -++ Marvell Discovery PPC/MIPS chipset family (MV643XX) and -++ in the Marvell Orion ARM SoC family. -++ -++ Some boards that use the Discovery chipset are the Momenco -++ Ocelot C and Jaguar ATX and Pegasos II. -++ -++config QLA3XXX -++ tristate "QLogic QLA3XXX Network Driver Support" -++ depends on PCI -++ help -++ This driver supports QLogic ISP3XXX gigabit Ethernet cards. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called qla3xxx. -++ -++config ATL1 -++ tristate "Attansic L1 Gigabit Ethernet support (EXPERIMENTAL)" -++ depends on PCI && EXPERIMENTAL -++ select CRC32 -++ select MII -++ help -++ This driver supports the Attansic L1 gigabit ethernet adapter. -++ -++ To compile this driver as a module, choose M here. The module -++ will be called atl1. -++ -++endif # NETDEV_1000 -++ -++# -++# 10 Gigabit Ethernet -++# -++ -++menuconfig NETDEV_10000 -++ bool "Ethernet (10000 Mbit)" -++ depends on !UML -++ default y -++ ---help--- -++ Say Y here to get to see options for 10 Gigabit Ethernet drivers. -++ This option alone does not add any kernel code. -++ -++ If you say N, all options in this submenu will be skipped and disabled. -++ -++if NETDEV_10000 -++ -++config CHELSIO_T1 -++ tristate "Chelsio 10Gb Ethernet support" -++ depends on PCI -++ select CRC32 -++ help -++ This driver supports Chelsio gigabit and 10-gigabit -++ Ethernet cards. More information about adapter features and -++ performance tuning is in . -++ -++ For general information about Chelsio and our products, visit -++ our website at . -++ -++ For customer support, please visit our customer support page at -++ . -++ -++ Please send feedback to . -++ -++ To compile this driver as a module, choose M here: the module -++ will be called cxgb. -++ -++config CHELSIO_T1_1G -++ bool "Chelsio gigabit Ethernet support" -++ depends on CHELSIO_T1 -++ help -++ Enables support for Chelsio's gigabit Ethernet PCI cards. If you -++ are using only 10G cards say 'N' here. -++ -++config CHELSIO_T1_NAPI -++ bool "Use Rx Polling (NAPI)" -++ depends on CHELSIO_T1 -++ default y -++ help -++ NAPI is a driver API designed to reduce CPU and interrupt load -++ when the driver is receiving lots of packets from the card. -++ -++config CHELSIO_T3 -++ tristate "Chelsio Communications T3 10Gb Ethernet support" -++ depends on PCI -++ select FW_LOADER -++ help -++ This driver supports Chelsio T3-based gigabit and 10Gb Ethernet -++ adapters. -++ -++ For general information about Chelsio and our products, visit -++ our website at . -++ -++ For customer support, please visit our customer support page at -++ . -++ -++ Please send feedback to . -++ -++ To compile this driver as a module, choose M here: the module -++ will be called cxgb3. -++ -++config EHEA -++ tristate "eHEA Ethernet support" -++ depends on IBMEBUS && INET -++ select INET_LRO -++ ---help--- -++ This driver supports the IBM pSeries eHEA ethernet adapter. -++ -++ To compile the driver as a module, choose M here. The module -++ will be called ehea. -++ -++config IXGBE -++ tristate "Intel(R) 10GbE PCI Express adapters support" -++ depends on PCI -++ ---help--- -++ This driver supports Intel(R) 10GbE PCI Express family of -++ adapters. For more information on how to identify your adapter, go -++ to the Adapter & Driver ID Guide at: -++ -++ -++ -++ For general information and support, go to the Intel support -++ website at: -++ -++ -++ -++ To compile this driver as a module, choose M here. The module -++ will be called ixgbe. -++ -++config IXGB -++ tristate "Intel(R) PRO/10GbE support" -++ depends on PCI -++ ---help--- -++ This driver supports Intel(R) PRO/10GbE family of adapters for -++ PCI-X type cards. For PCI-E type cards, use the "ixgbe" driver -++ instead. For more information on how to identify your adapter, go -++ to the Adapter & Driver ID Guide at: -++ -++ -++ -++ For general information and support, go to the Intel support -++ website at: -++ -++ -++ -++ More specific information on configuring the driver is in -++ . -++ -++ To compile this driver as a module, choose M here. The module -++ will be called ixgb. -++ -++config IXGB_NAPI -++ bool "Use Rx Polling (NAPI) (EXPERIMENTAL)" -++ depends on IXGB && EXPERIMENTAL -++ help -++ NAPI is a new driver API designed to reduce CPU and interrupt load -++ when the driver is receiving lots of packets from the card. It is -++ still somewhat experimental and thus not yet enabled by default. -++ -++ If your estimated Rx load is 10kpps or more, or if the card will be -++ deployed on potentially unfriendly networks (e.g. in a firewall), -++ then say Y here. -++ -++ If in doubt, say N. -++ -++config S2IO -++ tristate "S2IO 10Gbe XFrame NIC" -++ depends on PCI -++ ---help--- -++ This driver supports the 10Gbe XFrame NIC of S2IO. -++ More specific information on configuring the driver is in -++ . -++ -++config S2IO_NAPI -++ bool "Use Rx Polling (NAPI) (EXPERIMENTAL)" -++ depends on S2IO && EXPERIMENTAL -++ help -++ NAPI is a new driver API designed to reduce CPU and interrupt load -++ when the driver is receiving lots of packets from the card. It is -++ still somewhat experimental and thus not yet enabled by default. -++ -++ If your estimated Rx load is 10kpps or more, or if the card will be -++ deployed on potentially unfriendly networks (e.g. in a firewall), -++ then say Y here. -++ -++ If in doubt, say N. -++ -++config MYRI10GE -++ tristate "Myricom Myri-10G Ethernet support" -++ depends on PCI && INET -++ select FW_LOADER -++ select CRC32 -++ select INET_LRO -++ ---help--- -++ This driver supports Myricom Myri-10G Dual Protocol interface in -++ Ethernet mode. If the eeprom on your board is not recent enough, -++ you will need a newer firmware image. -++ You may get this image or more information, at: -++ -++ -++ -++ To compile this driver as a module, choose M here. The module -++ will be called myri10ge. -++ -++config NETXEN_NIC -++ tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC" -++ depends on PCI -++ help -++ This enables the support for NetXen's Gigabit Ethernet card. -++ -++config NIU -++ tristate "Sun Neptune 10Gbit Ethernet support" -++ depends on PCI -++ help -++ This enables support for cards based upon Sun's -++ Neptune chipset. -++ -++config PASEMI_MAC -++ tristate "PA Semi 1/10Gbit MAC" -++ depends on PPC64 && PCI -++ select PHYLIB -++ help -++ This driver supports the on-chip 1/10Gbit Ethernet controller on -++ PA Semi's PWRficient line of chips. -++ -++config MLX4_CORE -++ tristate -++ depends on PCI -++ default n -++ -++config MLX4_DEBUG -++ bool "Verbose debugging output" if (MLX4_CORE && EMBEDDED) -++ depends on MLX4_CORE -++ default y -++ ---help--- -++ This option causes debugging code to be compiled into the -++ mlx4_core driver. The output can be turned on via the -++ debug_level module parameter (which can also be set after -++ the driver is loaded through sysfs). -++ -++config TEHUTI -++ tristate "Tehuti Networks 10G Ethernet" -++ depends on PCI -++ help -++ Tehuti Networks 10G Ethernet NIC -++ -++endif # NETDEV_10000 -++ -++source "drivers/net/tokenring/Kconfig" -++ -++source "drivers/net/wireless/Kconfig" -++ -++source "drivers/net/usb/Kconfig" -++ -++source "drivers/net/pcmcia/Kconfig" -++ -++source "drivers/net/wan/Kconfig" -++ -++source "drivers/atm/Kconfig" -++ -++source "drivers/s390/net/Kconfig" -++ -++config XEN_NETDEV_FRONTEND -++ tristate "Xen network device frontend driver" -++ depends on XEN -++ default y -++ help -++ The network device frontend driver allows the kernel to -++ access network devices exported exported by a virtual -++ machine containing a physical network device driver. The -++ frontend driver is intended for unprivileged guest domains; -++ if you are compiling a kernel for a Xen guest, you almost -++ certainly want to enable this. -++ -++config ISERIES_VETH -++ tristate "iSeries Virtual Ethernet driver support" -++ depends on PPC_ISERIES -++ -++config RIONET -++ tristate "RapidIO Ethernet over messaging driver support" -++ depends on RAPIDIO -++ -++config RIONET_TX_SIZE -++ int "Number of outbound queue entries" -++ depends on RIONET -++ default "128" -++ -++config RIONET_RX_SIZE -++ int "Number of inbound queue entries" -++ depends on RIONET -++ default "128" -++ -++config FDDI -++ bool "FDDI driver support" -++ depends on (PCI || EISA || TC) -++ help -++ Fiber Distributed Data Interface is a high speed local area network -++ design; essentially a replacement for high speed Ethernet. FDDI can -++ run over copper or fiber. If you are connected to such a network and -++ want a driver for the FDDI card in your computer, say Y here (and -++ then also Y to the driver for your FDDI card, below). Most people -++ will say N. -++ -++config DEFXX -++ tristate "Digital DEFTA/DEFEA/DEFPA adapter support" -++ depends on FDDI && (PCI || EISA || TC) -++ ---help--- -++ This is support for the DIGITAL series of TURBOchannel (DEFTA), -++ EISA (DEFEA) and PCI (DEFPA) controllers which can connect you -++ to a local FDDI network. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called defxx. If unsure, say N. -++ -++config DEFXX_MMIO -++ bool -++ prompt "Use MMIO instead of PIO" if PCI || EISA -++ depends on DEFXX -++ default n if PCI || EISA -++ default y -++ ---help--- -++ This instructs the driver to use EISA or PCI memory-mapped I/O -++ (MMIO) as appropriate instead of programmed I/O ports (PIO). -++ Enabling this gives an improvement in processing time in parts -++ of the driver, but it may cause problems with EISA (DEFEA) -++ adapters. TURBOchannel does not have the concept of I/O ports, -++ so MMIO is always used for these (DEFTA) adapters. -++ -++ If unsure, say N. -++ -++config SKFP -++ tristate "SysKonnect FDDI PCI support" -++ depends on FDDI && PCI -++ select BITREVERSE -++ ---help--- -++ Say Y here if you have a SysKonnect FDDI PCI adapter. -++ The following adapters are supported by this driver: -++ - SK-5521 (SK-NET FDDI-UP) -++ - SK-5522 (SK-NET FDDI-UP DAS) -++ - SK-5541 (SK-NET FDDI-FP) -++ - SK-5543 (SK-NET FDDI-LP) -++ - SK-5544 (SK-NET FDDI-LP DAS) -++ - SK-5821 (SK-NET FDDI-UP64) -++ - SK-5822 (SK-NET FDDI-UP64 DAS) -++ - SK-5841 (SK-NET FDDI-FP64) -++ - SK-5843 (SK-NET FDDI-LP64) -++ - SK-5844 (SK-NET FDDI-LP64 DAS) -++ - Netelligent 100 FDDI DAS Fibre SC -++ - Netelligent 100 FDDI SAS Fibre SC -++ - Netelligent 100 FDDI DAS UTP -++ - Netelligent 100 FDDI SAS UTP -++ - Netelligent 100 FDDI SAS Fibre MIC -++ -++ Read for information about -++ the driver. -++ -++ Questions concerning this driver can be addressed to: -++ -++ -++ To compile this driver as a module, choose M here: the module -++ will be called skfp. This is recommended. -++ -++config HIPPI -++ bool "HIPPI driver support (EXPERIMENTAL)" -++ depends on EXPERIMENTAL && INET && PCI -++ help -++ HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and -++ 1600Mbit/sec dual-simplex switched or point-to-point network. HIPPI -++ can run over copper (25m) or fiber (300m on multi-mode or 10km on -++ single-mode). HIPPI networks are commonly used for clusters and to -++ connect to super computers. If you are connected to a HIPPI network -++ and have a HIPPI network card in your computer that you want to use -++ under Linux, say Y here (you must also remember to enable the driver -++ for your HIPPI card below). Most people will say N here. -++ -++config ROADRUNNER -++ tristate "Essential RoadRunner HIPPI PCI adapter support (EXPERIMENTAL)" -++ depends on HIPPI && PCI -++ help -++ Say Y here if this is your PCI HIPPI network card. -++ -++ To compile this driver as a module, choose M here: the module -++ will be called rrunner. If unsure, say N. -++ -++config ROADRUNNER_LARGE_RINGS -++ bool "Use large TX/RX rings (EXPERIMENTAL)" -++ depends on ROADRUNNER -++ help -++ If you say Y here, the RoadRunner driver will preallocate up to 2 MB -++ of additional memory to allow for fastest operation, both for -++ transmitting and receiving. This memory cannot be used by any other -++ kernel code or by user space programs. Say Y here only if you have -++ the memory. -++ -++config PLIP -++ tristate "PLIP (parallel port) support" -++ depends on PARPORT -++ ---help--- -++ PLIP (Parallel Line Internet Protocol) is used to create a -++ reasonably fast mini network consisting of two (or, rarely, more) -++ local machines. A PLIP link from a Linux box is a popular means to -++ install a Linux distribution on a machine which doesn't have a -++ CD-ROM drive (a minimal system has to be transferred with floppies -++ first). The kernels on both machines need to have this PLIP option -++ enabled for this to work. -++ -++ The PLIP driver has two modes, mode 0 and mode 1. The parallel -++ ports (the connectors at the computers with 25 holes) are connected -++ with "null printer" or "Turbo Laplink" cables which can transmit 4 -++ bits at a time (mode 0) or with special PLIP cables, to be used on -++ bidirectional parallel ports only, which can transmit 8 bits at a -++ time (mode 1); you can find the wiring of these cables in -++ . The cables can be up to -++ 15m long. Mode 0 works also if one of the machines runs DOS/Windows -++ and has some PLIP software installed, e.g. the Crynwr PLIP packet -++ driver () -++ and winsock or NCSA's telnet. -++ -++ If you want to use PLIP, say Y and read the PLIP mini-HOWTO as well -++ as the NET-3-HOWTO, both available from -++ . Note that the PLIP -++ protocol has been changed and this PLIP driver won't work together -++ with the PLIP support in Linux versions 1.0.x. This option enlarges -++ your kernel by about 8 KB. -++ -++ To compile this driver as a module, choose M here. The module -++ will be called plip. If unsure, say Y or M, in case you buy -++ a laptop later. -++ -++config PPP -++ tristate "PPP (point-to-point protocol) support" -++ select SLHC -++ ---help--- -++ PPP (Point to Point Protocol) is a newer and better SLIP. It serves -++ the same purpose: sending Internet traffic over telephone (and other -++ serial) lines. Ask your access provider if they support it, because -++ otherwise you can't use it; most Internet access providers these -++ days support PPP rather than SLIP. -++ -++ To use PPP, you need an additional program called pppd as described -++ in the PPP-HOWTO, available at -++ . Make sure that you have -++ the version of pppd recommended in . -++ The PPP option enlarges your kernel by about 16 KB. -++ -++ There are actually two versions of PPP: the traditional PPP for -++ asynchronous lines, such as regular analog phone lines, and -++ synchronous PPP which can be used over digital ISDN lines for -++ example. If you want to use PPP over phone lines or other -++ asynchronous serial lines, you need to say Y (or M) here and also to -++ the next option, "PPP support for async serial ports". For PPP over -++ synchronous lines, you should say Y (or M) here and to "Support -++ synchronous PPP", below. -++ -++ If you said Y to "Version information on all symbols" above, then -++ you cannot compile the PPP driver into the kernel; you can then only -++ compile it as a module. To compile this driver as a module, choose M -++ here. The module will be called ppp_generic. -++ -++config PPP_MULTILINK -++ bool "PPP multilink support (EXPERIMENTAL)" -++ depends on PPP && EXPERIMENTAL -++ help -++ PPP multilink is a protocol (defined in RFC 1990) which allows you -++ to combine several (logical or physical) lines into one logical PPP -++ connection, so that you can utilize your full bandwidth. -++ -++ This has to be supported at the other end as well and you need a -++ version of the pppd daemon which understands the multilink protocol. -++ -++ If unsure, say N. -++ -++config PPP_FILTER -++ bool "PPP filtering" -++ depends on PPP -++ help -++ Say Y here if you want to be able to filter the packets passing over -++ PPP interfaces. This allows you to control which packets count as -++ activity (i.e. which packets will reset the idle timer or bring up -++ a demand-dialed link) and which packets are to be dropped entirely. -++ You need to say Y here if you wish to use the pass-filter and -++ active-filter options to pppd. -++ -++ If unsure, say N. -++ -++config PPP_ASYNC -++ tristate "PPP support for async serial ports" -++ depends on PPP -++ select CRC_CCITT -++ ---help--- -++ Say Y (or M) here if you want to be able to use PPP over standard -++ asynchronous serial ports, such as COM1 or COM2 on a PC. If you use -++ a modem (not a synchronous or ISDN modem) to contact your ISP, you -++ need this option. -++ -++ To compile this driver as a module, choose M here. -++ -++ If unsure, say Y. -++ -++config PPP_SYNC_TTY -++ tristate "PPP support for sync tty ports" -++ depends on PPP -++ help -++ Say Y (or M) here if you want to be able to use PPP over synchronous -++ (HDLC) tty devices, such as the SyncLink adapter. These devices -++ are often used for high-speed leased lines like T1/E1. -++ -++ To compile this driver as a module, choose M here. -++ -++config PPP_DEFLATE -++ tristate "PPP Deflate compression" -++ depends on PPP -++ select ZLIB_INFLATE -++ select ZLIB_DEFLATE -++ ---help--- -++ Support for the Deflate compression method for PPP, which uses the -++ Deflate algorithm (the same algorithm that gzip uses) to compress -++ each PPP packet before it is sent over the wire. The machine at the -++ other end of the PPP link (usually your ISP) has to support the -++ Deflate compression method as well for this to be useful. Even if -++ they don't support it, it is safe to say Y here. -++ -++ To compile this driver as a module, choose M here. -++ -++config PPP_BSDCOMP -++ tristate "PPP BSD-Compress compression" -++ depends on PPP -++ ---help--- -++ Support for the BSD-Compress compression method for PPP, which uses -++ the LZW compression method to compress each PPP packet before it is -++ sent over the wire. The machine at the other end of the PPP link -++ (usually your ISP) has to support the BSD-Compress compression -++ method as well for this to be useful. Even if they don't support it, -++ it is safe to say Y here. -++ -++ The PPP Deflate compression method ("PPP Deflate compression", -++ above) is preferable to BSD-Compress, because it compresses better -++ and is patent-free. -++ -++ Note that the BSD compression code will always be compiled as a -++ module; it is called bsd_comp and will show up in the directory -++ modules once you have said "make modules". If unsure, say N. -++ -++config PPP_MPPE -++ tristate "PPP MPPE compression (encryption) (EXPERIMENTAL)" -++ depends on PPP && EXPERIMENTAL -++ select CRYPTO -++ select CRYPTO_SHA1 -++ select CRYPTO_ARC4 -++ select CRYPTO_ECB -++ ---help--- -++ Support for the MPPE Encryption protocol, as employed by the -++ Microsoft Point-to-Point Tunneling Protocol. -++ -++ See http://pptpclient.sourceforge.net/ for information on -++ configuring PPTP clients and servers to utilize this method. -++ -++config PPPOE -++ tristate "PPP over Ethernet (EXPERIMENTAL)" -++ depends on EXPERIMENTAL && PPP -++ help -++ Support for PPP over Ethernet. -++ -++ This driver requires the latest version of pppd from the CVS -++ repository at cvs.samba.org. Alternatively, see the -++ RoaringPenguin package () -++ which contains instruction on how to use this driver (under -++ the heading "Kernel mode PPPoE"). -++ -++config PPPOATM -++ tristate "PPP over ATM" -++ depends on ATM && PPP -++ help -++ Support PPP (Point to Point Protocol) encapsulated in ATM frames. -++ This implementation does not yet comply with section 8 of RFC2364, -++ which can lead to bad results if the ATM peer loses state and -++ changes its encapsulation unilaterally. -++ -++config PPPOL2TP -++ tristate "PPP over L2TP (EXPERIMENTAL)" -++ depends on EXPERIMENTAL && PPP && INET -++ help -++ Support for PPP-over-L2TP socket family. L2TP is a protocol -++ used by ISPs and enterprises to tunnel PPP traffic over UDP -++ tunnels. L2TP is replacing PPTP for VPN uses. -++ -++ This kernel component handles only L2TP data packets: a -++ userland daemon handles L2TP the control protocol (tunnel -++ and session setup). One such daemon is OpenL2TP -++ (http://openl2tp.sourceforge.net/). -++ -++config SLIP -++ tristate "SLIP (serial line) support" -++ ---help--- -++ Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to -++ connect to your Internet service provider or to connect to some -++ other local Unix box or if you want to configure your Linux box as a -++ Slip/CSlip server for other people to dial in. SLIP (Serial Line -++ Internet Protocol) is a protocol used to send Internet traffic over -++ serial connections such as telephone lines or null modem cables; -++ nowadays, the protocol PPP is more commonly used for this same -++ purpose. -++ -++ Normally, your access provider has to support SLIP in order for you -++ to be able to use it, but there is now a SLIP emulator called SLiRP -++ around (available from -++ ) which -++ allows you to use SLIP over a regular dial up shell connection. If -++ you plan to use SLiRP, make sure to say Y to CSLIP, below. The -++ NET-3-HOWTO, available from -++ , explains how to -++ configure SLIP. Note that you don't need this option if you just -++ want to run term (term is a program which gives you almost full -++ Internet connectivity if you have a regular dial up shell account on -++ some Internet connected Unix computer. Read -++ ). SLIP -++ support will enlarge your kernel by about 4 KB. If unsure, say N. -++ -++ To compile this driver as a module, choose M here. The module -++ will be called slip. -++ -++config SLIP_COMPRESSED -++ bool "CSLIP compressed headers" -++ depends on SLIP -++ select SLHC -++ ---help--- -++ This protocol is faster than SLIP because it uses compression on the -++ TCP/IP headers (not on the data itself), but it has to be supported -++ on both ends. Ask your access provider if you are not sure and -++ answer Y, just in case. You will still be able to use plain SLIP. If -++ you plan to use SLiRP, the SLIP emulator (available from -++ ) which -++ allows you to use SLIP over a regular dial up shell connection, you -++ definitely want to say Y here. The NET-3-HOWTO, available from -++ , explains how to configure -++ CSLIP. This won't enlarge your kernel. -++ -++config SLHC -++ tristate -++ help -++ This option enables Van Jacobsen serial line header compression -++ routines. -++ -++config SLIP_SMART -++ bool "Keepalive and linefill" -++ depends on SLIP -++ help -++ Adds additional capabilities to the SLIP driver to support the -++ RELCOM line fill and keepalive monitoring. Ideal on poor quality -++ analogue lines. -++ -++config SLIP_MODE_SLIP6 -++ bool "Six bit SLIP encapsulation" -++ depends on SLIP -++ help -++ Just occasionally you may need to run IP over hostile serial -++ networks that don't pass all control characters or are only seven -++ bit. Saying Y here adds an extra mode you can use with SLIP: -++ "slip6". In this mode, SLIP will only send normal ASCII symbols over -++ the serial device. Naturally, this has to be supported at the other -++ end of the link as well. It's good enough, for example, to run IP -++ over the async ports of a Camtec JNT Pad. If unsure, say N. -++ -++config NET_FC -++ bool "Fibre Channel driver support" -++ depends on SCSI && PCI -++ help -++ Fibre Channel is a high speed serial protocol mainly used to connect -++ large storage devices to the computer; it is compatible with and -++ intended to replace SCSI. -++ -++ If you intend to use Fibre Channel, you need to have a Fibre channel -++ adaptor card in your computer; say Y here and to the driver for your -++ adaptor below. You also should have said Y to "SCSI support" and -++ "SCSI generic support". -++ -++config SHAPER -++ tristate "Traffic Shaper (OBSOLETE)" -++ depends on EXPERIMENTAL -++ ---help--- -++ The traffic shaper is a virtual network device that allows you to -++ limit the rate of outgoing data flow over some other network device. -++ The traffic that you want to slow down can then be routed through -++ these virtual devices. See -++ for more information. -++ -++ An alternative to this traffic shaper are traffic schedulers which -++ you'll get if you say Y to "QoS and/or fair queuing" in -++ "Networking options". -++ -++ To compile this driver as a module, choose M here: the module -++ will be called shaper. If unsure, say N. -++ -++config NETCONSOLE -++ tristate "Network console logging support (EXPERIMENTAL)" -++ depends on EXPERIMENTAL -++ ---help--- -++ If you want to log kernel messages over the network, enable this. -++ See for details. -++ -++config NETCONSOLE_DYNAMIC -++ bool "Dynamic reconfiguration of logging targets (EXPERIMENTAL)" -++ depends on NETCONSOLE && SYSFS && EXPERIMENTAL -++ select CONFIGFS_FS -++ help -++ This option enables the ability to dynamically reconfigure target -++ parameters (interface, IP addresses, port numbers, MAC addresses) -++ at runtime through a userspace interface exported using configfs. -++ See for details. -++ -++config NETPOLL -++ def_bool NETCONSOLE -++ -++config NETPOLL_TRAP -++ bool "Netpoll traffic trapping" -++ default n -++ depends on NETPOLL -++ -++config NET_POLL_CONTROLLER -++ def_bool NETPOLL -++ -++config VIRTIO_NET -++ tristate "Virtio network driver (EXPERIMENTAL)" -++ depends on EXPERIMENTAL && VIRTIO -++ ---help--- -++ This is the virtual network driver for lguest. Say Y or M. -++ -++endif # NETDEVICES -+diff -urN linux-2.6.24.7.old/drivers/net/Makefile linux-2.6.24.7/drivers/net/Makefile -+--- linux-2.6.24.7.old/drivers/net/Makefile 2009-04-12 18:05:07.000000000 +0200 -++++ linux-2.6.24.7/drivers/net/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -84,6 +84,8 @@ -+ obj-$(CONFIG_MII) += mii.o -+ obj-$(CONFIG_PHYLIB) += phy/ -+ -++obj-$(CONFIG_JZ_ETH) += jz_eth.o -++obj-$(CONFIG_JZCS8900) += jzcs8900a.o -+ obj-$(CONFIG_SUNDANCE) += sundance.o -+ obj-$(CONFIG_HAMACHI) += hamachi.o -+ obj-$(CONFIG_NET) += Space.o loopback.o -+diff -urN linux-2.6.24.7.old/drivers/net/jz_eth.c linux-2.6.24.7/drivers/net/jz_eth.c -+--- linux-2.6.24.7.old/drivers/net/jz_eth.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/net/jz_eth.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1290 @@ -++/* -++ * linux/drivers/net/jz_eth.c -++ * -++ * Jz4730/Jz5730 On-Chip ethernet driver. -++ * -++ * Copyright (C) 2005 - 2007 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "jz_eth.h" -++ -++#define P2ADDR(a) (((unsigned long)(a) & 0x1fffffff) | 0xa0000000) -++#define P1ADDR(a) (((unsigned long)(a) & 0x1fffffff) | 0x80000000) -++ -++//#define DEBUG -++#ifdef DEBUG -++# define DBPRINTK(fmt,args...) printk(KERN_DEBUG fmt,##args) -++#else -++# define DBPRINTK(fmt,args...) do {} while(0) -++#endif -++ -++#define errprintk(fmt,args...) printk(KERN_ERR fmt,##args); -++#define infoprintk(fmt,args...) printk(KERN_INFO fmt,##args); -++ -++#define DRV_NAME "jz_eth" -++#define DRV_VERSION "1.2" -++#define DRV_AUTHOR "Peter Wei " -++#define DRV_DESC "JzSOC On-chip Ethernet driver" -++ -++MODULE_AUTHOR(DRV_AUTHOR); -++MODULE_DESCRIPTION(DRV_DESC); -++MODULE_LICENSE("GPL"); -++ -++/* -++ * Local variables -++ */ -++static struct net_device *netdev; -++static char * hwaddr = NULL; -++static int debug = -1; -++static struct mii_if_info mii_info; -++ -++MODULE_PARM_DESC(debug, "i"); -++MODULE_PARM_DESC(hwaddr,"s"); -++ -++/* -++ * Local routines -++ */ -++static irqreturn_t jz_eth_interrupt(int irq, void *dev_id); -++ -++static int link_check_thread (void *data); -++ -++/* -++ * Get MAC address -++ */ -++ -++#define I2C_DEVICE 0x57 -++#define MAC_OFFSET 64 -++ -++extern void i2c_open(void); -++extern void i2c_close(void); -++extern int i2c_read(unsigned char device, unsigned char *buf, -++ unsigned char address, int count); -++ -++static inline unsigned char str2hexnum(unsigned char c) -++{ -++ if (c >= '0' && c <= '9') -++ return c - '0'; -++ if (c >= 'a' && c <= 'f') -++ return c - 'a' + 10; -++ if (c >= 'A' && c <= 'F') -++ return c - 'A' + 10; -++ return 0; /* foo */ -++} -++ -++static inline void str2eaddr(unsigned char *ea, unsigned char *str) -++{ -++ int i; -++ -++ for (i = 0; i < 6; i++) { -++ unsigned char num; -++ -++ if((*str == '.') || (*str == ':')) -++ str++; -++ num = str2hexnum(*str++) << 4; -++ num |= (str2hexnum(*str++)); -++ ea[i] = num; -++ } -++} -++ -++static int ethaddr_cmd = 0; -++static unsigned char ethaddr_hex[6]; -++ -++static int __init ethernet_addr_setup(char *str) -++{ -++ if (!str) { -++ printk("ethaddr not set in command line\n"); -++ return -1; -++ } -++ ethaddr_cmd = 1; -++ str2eaddr(ethaddr_hex, str); -++ -++ return 0; -++} -++ -++__setup("ethaddr=", ethernet_addr_setup); -++ -++static int get_mac_address(struct net_device *dev) -++{ -++ int i; -++ unsigned char flag0=0; -++ unsigned char flag1=0xff; -++ -++ dev->dev_addr[0] = 0xff; -++ if (hwaddr != NULL) { -++ /* insmod jz-ethc.o hwaddr=00:ef:a3:c1:00:10 */ -++ str2eaddr(dev->dev_addr, hwaddr); -++ } else if (ethaddr_cmd) { -++ /* linux command line: ethaddr=00:ef:a3:c1:00:10 */ -++ for (i=0; i<6; i++) -++ dev->dev_addr[i] = ethaddr_hex[i]; -++ } else { -++#if 0 -++ /* mac address in eeprom: byte 0x40-0x45 */ -++ i2c_open(); -++ i2c_read(I2C_DEVICE, dev->dev_addr, MAC_OFFSET, 6); -++ i2c_close(); -++#endif -++ } -++ -++ /* check whether valid MAC address */ -++ for (i=0; i<6; i++) { -++ flag0 |= dev->dev_addr[i]; -++ flag1 &= dev->dev_addr[i]; -++ } -++ if ((dev->dev_addr[0] & 0xC0) || (flag0 == 0) || (flag1 == 0xff)) { -++ printk("WARNING: There is not MAC address, use default ..\n"); -++ dev->dev_addr[0] = 0x00; -++ dev->dev_addr[1] = 0xef; -++ dev->dev_addr[2] = 0xa3; -++ dev->dev_addr[3] = 0xc1; -++ dev->dev_addr[4] = 0x00; -++ dev->dev_addr[5] = 0x10; -++ dev->dev_addr[5] = 0x03; -++ } -++ return 0; -++} -++ -++/*---------------------------------------------------------------------*/ -++ -++static u32 jz_eth_curr_mode(struct net_device *dev); -++ -++/* -++ * Ethernet START/STOP routines -++ */ -++#define START_ETH { \ -++ s32 val; \ -++ val = readl(DMA_OMR); \ -++ val |= OMR_ST | OMR_SR; \ -++ writel(val, DMA_OMR); \ -++} -++ -++#define STOP_ETH { \ -++ s32 val; \ -++ val = readl(DMA_OMR); \ -++ val &= ~(OMR_ST|OMR_SR); \ -++ writel(val, DMA_OMR); \ -++} -++ -++/* -++ * Link check routines -++ */ -++static void start_check(struct net_device *dev) -++{ -++ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -++ -++ np->thread_die = 0; -++ init_waitqueue_head(&np->thr_wait); -++ init_completion (&np->thr_exited); -++ np->thr_pid = kernel_thread (link_check_thread,(void *)dev, -++ CLONE_FS | CLONE_FILES); -++ if (np->thr_pid < 0) -++ errprintk("%s: unable to start kernel thread\n",dev->name); -++} -++ -++static int close_check(struct net_device *dev) -++{ -++ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -++ int ret = 0; -++ -++ if (np->thr_pid >= 0) { -++ np->thread_die = 1; -++ wmb(); -++ ret = kill_proc (np->thr_pid, SIGTERM, 1); -++ if (ret) { -++ errprintk("%s: unable to signal thread\n", dev->name); -++ return 1; -++ } -++ wait_for_completion (&np->thr_exited); -++ } -++ return 0; -++} -++ -++static int link_check_thread(void *data) -++{ -++ struct net_device *dev=(struct net_device *)data; -++ struct jz_eth_private *np = (struct jz_eth_private *)netdev->priv; -++ unsigned char current_link; -++ unsigned long timeout; -++ -++ daemonize("%s", dev->name); -++ spin_lock_irq(¤t->sighand->siglock); -++ sigemptyset(¤t->blocked); -++ recalc_sigpending(); -++ spin_unlock_irq(¤t->sighand->siglock); -++ -++ strncpy (current->comm, dev->name, sizeof(current->comm) - 1); -++ current->comm[sizeof(current->comm) - 1] = '\0'; -++ -++ while (1) { -++ timeout = 3*HZ; -++ do { -++ timeout = interruptible_sleep_on_timeout (&np->thr_wait, timeout); -++ /* make swsusp happy with our thread */ -++// if (current->flags & PF_FREEZE) -++// refrigerator(PF_FREEZE); -++ } while (!signal_pending (current) && (timeout > 0)); -++ -++ if (signal_pending (current)) { -++ spin_lock_irq(¤t->sighand->siglock); -++ flush_signals(current); -++ spin_unlock_irq(¤t->sighand->siglock); -++ } -++ -++ if (np->thread_die) -++ break; -++ -++ current_link=mii_link_ok(&mii_info); -++ if (np->link_state!=current_link) { -++ if (current_link) { -++ infoprintk("%s: Ethernet Link OK!\n",dev->name); -++ jz_eth_curr_mode(dev); -++ netif_carrier_on(dev); -++ } -++ else { -++ errprintk("%s: Ethernet Link offline!\n",dev->name); -++ netif_carrier_off(dev); -++ } -++ } -++ np->link_state=current_link; -++ -++ } -++ complete_and_exit (&np->thr_exited, 0); -++} -++ -++#ifdef DEBUG -++/* -++ * Display ethernet packet header -++ * This routine is used for test function -++ */ -++static void eth_dbg_rx(struct sk_buff *skb, int len) -++{ -++ -++ int i, j; -++ -++ printk("R: %02x:%02x:%02x:%02x:%02x:%02x <- %02x:%02x:%02x:%02x:%02x:%02x len/SAP:%02x%02x [%d]\n", -++ (u8)skb->data[0], -++ (u8)skb->data[1], -++ (u8)skb->data[2], -++ (u8)skb->data[3], -++ (u8)skb->data[4], -++ (u8)skb->data[5], -++ (u8)skb->data[6], -++ (u8)skb->data[7], -++ (u8)skb->data[8], -++ (u8)skb->data[9], -++ (u8)skb->data[10], -++ (u8)skb->data[11], -++ (u8)skb->data[12], -++ (u8)skb->data[13], -++ len); -++ for (j=0; len>0; j+=16, len-=16) { -++ printk(" %03x: ",j); -++ for (i=0; i<16 && idata[i+j]); -++ } -++ printk("\n"); -++ } -++ return; -++ } -++#endif -++ -++/* -++ * Reset ethernet device -++ */ -++static inline void jz_eth_reset(void) -++{ -++ u32 i; -++ i = readl(DMA_BMR); -++ writel(i | BMR_SWR, DMA_BMR); -++ for(i = 0; i < 1000; i++) { -++ if(!(readl(DMA_BMR) & BMR_SWR)) break; -++ mdelay(1); -++ } -++} -++ -++/* -++ * MII operation routines -++ */ -++static inline void mii_wait(void) -++{ -++ int i; -++ for(i = 0; i < 10000; i++) { -++ if(!(readl(MAC_MIIA) & 0x1)) -++ break; -++ mdelay(1); -++ } -++ if (i >= 10000) -++ printk("MII wait timeout : %d.\n", i); -++} -++ -++static int mdio_read(struct net_device *dev,int phy_id, int location) -++{ -++ u32 mii_cmd = (phy_id << 11) | (location << 6) | 1; -++ int retval = 0; -++ -++ writel(mii_cmd, MAC_MIIA); -++ mii_wait(); -++ retval = readl(MAC_MIID) & 0x0000ffff; -++ -++ return retval; -++ -++} -++ -++static void mdio_write(struct net_device *dev,int phy_id, int location, int data) -++{ -++ u32 mii_cmd = (phy_id << 11) | (location << 6) | 0x2 | 1; -++ -++ writel(mii_cmd, MAC_MIIA); -++ writel(data & 0x0000ffff, MAC_MIID); -++ mii_wait(); -++} -++ -++ -++/* -++ * Search MII phy -++ */ -++static int jz_search_mii_phy(struct net_device *dev) -++{ -++ -++ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -++ int phy, phy_idx = 0; -++ -++ np->valid_phy = 0xff; -++ for (phy = 0; phy < 32; phy++) { -++ int mii_status = mdio_read(dev,phy, 1); -++ if (mii_status != 0xffff && mii_status != 0x0000) { -++ np->phys[phy_idx] = phy; -++ np->ecmds[phy_idx].speed=SPEED_100; -++ np->ecmds[phy_idx].duplex=DUPLEX_FULL; -++ np->ecmds[phy_idx].port=PORT_MII; -++ np->ecmds[phy_idx].transceiver=XCVR_INTERNAL; -++ np->ecmds[phy_idx].phy_address=np->phys[phy_idx]; -++ np->ecmds[phy_idx].autoneg=AUTONEG_ENABLE; -++ np->ecmds[phy_idx].advertising=(ADVERTISED_10baseT_Half | -++ ADVERTISED_10baseT_Full | -++ ADVERTISED_100baseT_Half | -++ ADVERTISED_100baseT_Full); -++ phy_idx++; -++ } -++ } -++ if (phy_idx == 1) { -++ np->valid_phy = np->phys[0]; -++ np->phy_type = 0; -++ } -++ if (phy_idx != 0) { -++ phy = np->valid_phy; -++ np->advertising = mdio_read(dev,phy, 4); -++ } -++ return phy_idx; -++} -++ -++/* -++ * CRC calc for Destination Address for gets hashtable index -++ */ -++ -++#define POLYNOMIAL 0x04c11db7UL -++static u16 jz_hashtable_index(u8 *addr) -++{ -++#if 1 -++ u32 crc = 0xffffffff, msb; -++ int i, j; -++ u32 byte; -++ for (i = 0; i < 6; i++) { -++ byte = *addr++; -++ for (j = 0; j < 8; j++) { -++ msb = crc >> 31; -++ crc <<= 1; -++ if (msb ^ (byte & 1)) crc ^= POLYNOMIAL; -++ byte >>= 1; -++ } -++ } -++ return ((int)(crc >> 26)); -++#endif -++#if 0 -++ int crc = -1; -++ int length=6; -++ int bit; -++ unsigned char current_octet; -++ while (--length >= 0) { -++ current_octet = *addr++; -++ for (bit = 0; bit < 8; bit++, current_octet >>= 1) -++ crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ? -++ POLYNOMIAL : 0); -++ } -++ return ((int)(crc >> 26)); -++#endif -++} -++ -++/* -++ * Multicast filter and config multicast hash table -++ */ -++#define MULTICAST_FILTER_LIMIT 64 -++ -++static void jz_set_multicast_list(struct net_device *dev) -++{ -++ int i, hash_index; -++ u32 mcr, hash_h, hash_l, hash_bit; -++ -++ mcr = readl(MAC_MCR); -++ mcr &= ~(MCR_PR | MCR_PM | MCR_HP); -++ -++ if (dev->flags & IFF_PROMISC) { -++ /* Accept any kinds of packets */ -++ mcr |= MCR_PR; -++ hash_h = 0xffffffff; -++ hash_l = 0xffffffff; -++ DBPRINTK("%s: enter promisc mode!\n",dev->name); -++ } -++ else if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > MULTICAST_FILTER_LIMIT)){ -++ /* Accept all multicast packets */ -++ mcr |= MCR_PM; -++ hash_h = 0xffffffff; -++ hash_l = 0xffffffff; -++ DBPRINTK("%s: enter allmulticast mode! %d \n",dev->name,dev->mc_count); -++ } -++ else if (dev->flags & IFF_MULTICAST) -++ { -++ /* Update multicast hash table */ -++ struct dev_mc_list *mclist; -++ hash_h = readl(MAC_HTH); -++ hash_l = readl(MAC_HTL); -++ for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; -++ i++, mclist = mclist->next) -++ { -++ hash_index = jz_hashtable_index(mclist->dmi_addr); -++ hash_bit=0x00000001; -++ hash_bit <<= (hash_index & 0x1f); -++ if (hash_index > 0x1f) -++ hash_h |= hash_bit; -++ else -++ hash_l |= hash_bit; -++ DBPRINTK("----------------------------\n"); -++#ifdef DEBUG -++ int j; -++ for (j=0;jdmi_addrlen;j++) -++ printk("%2.2x:",mclist->dmi_addr[j]); -++ printk("\n"); -++#endif -++ DBPRINTK("dmi.addrlen => %d\n",mclist->dmi_addrlen); -++ DBPRINTK("dmi.users => %d\n",mclist->dmi_users); -++ DBPRINTK("dmi.gusers => %d\n",mclist->dmi_users); -++ } -++ writel(hash_h,MAC_HTH); -++ writel(hash_l,MAC_HTL); -++ mcr |= MCR_HP; -++ DBPRINTK("This is multicast hash table high bits [%4.4x]\n",readl(MAC_HTH)); -++ DBPRINTK("This is multicast hash table low bits [%4.4x]\n",readl(MAC_HTL)); -++ DBPRINTK("%s: enter multicast mode!\n",dev->name); -++ } -++ writel(mcr,MAC_MCR); -++} -++ -++static inline int jz_phy_reset(struct net_device *dev) -++{ -++ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -++ unsigned int mii_reg0; -++ unsigned int count; -++ -++ mii_reg0 = mdio_read(dev,np->valid_phy,MII_BMCR); -++ mii_reg0 |=MII_CR_RST; -++ mdio_write(dev,np->valid_phy,MII_BMCR,mii_reg0); //reset phy -++ for ( count = 0; count < 1000; count++) { -++ mdelay(1); -++ mii_reg0 = mdio_read(dev,np->valid_phy,MII_BMCR); -++ if (!(mii_reg0 & MII_CR_RST)) break; //reset completed -++ } -++ if (count>=100) -++ return 1; //phy error -++ else -++ return 0; -++} -++ -++/* -++ * Show all mii registers - this routine is used for test -++ */ -++#ifdef DEBUG -++static void mii_db_out(struct net_device *dev) -++{ -++ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -++ unsigned int mii_test; -++ -++ mii_test = mdio_read(dev,np->valid_phy,MII_BMCR); -++ DBPRINTK("BMCR ====> 0x%4.4x \n",mii_test); -++ -++ mii_test = mdio_read(dev,np->valid_phy,MII_BMSR); -++ DBPRINTK("BMSR ====> 0x%4.4x \n",mii_test); -++ -++ mii_test = mdio_read(dev,np->valid_phy,MII_ANAR); -++ DBPRINTK("ANAR ====> 0x%4.4x \n",mii_test); -++ -++ mii_test = mdio_read(dev,np->valid_phy,MII_ANLPAR); -++ DBPRINTK("ANLPAR ====> 0x%4.4x \n",mii_test); -++ -++ mii_test = mdio_read(dev,np->valid_phy,16); -++ DBPRINTK("REG16 ====> 0x%4.4x \n",mii_test); -++ -++ mii_test = mdio_read(dev,np->valid_phy,17); -++ DBPRINTK("REG17 ====> 0x%4.4x \n",mii_test); -++} -++#endif -++ -++/* -++ * Start Auto-Negotiation function for PHY -++ */ -++static int jz_autonet_complete(struct net_device *dev) -++{ -++ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -++ int count; -++ u32 mii_reg1, timeout = 3000; -++ -++ for (count = 0; count < timeout; count++) { -++ mdelay(1); -++ mii_reg1 = mdio_read(dev,np->valid_phy,MII_BMSR); -++ if (mii_reg1 & 0x0020) break; -++ } -++ //mii_db_out(dev); //for debug to display all register of MII -++ if (count >= timeout) -++ return 1; //auto negotiation error -++ else -++ return 0; -++} -++ -++/* -++ * Get current mode of eth phy -++ */ -++static u32 jz_eth_curr_mode(struct net_device *dev) -++{ -++ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -++ unsigned int mii_reg17; -++ u32 flag = 0; -++ -++ mii_reg17 = mdio_read(dev,np->valid_phy,MII_DSCSR); -++ np->media = mii_reg17>>12; -++ if (np->media==8) { -++ infoprintk("%s: Current Operation Mode is [100M Full Duplex]",dev->name); -++ flag = 0; -++ np->full_duplex=1; -++ } -++ if (np->media==4) { -++ infoprintk("%s: Current Operation Mode is [100M Half Duplex]",dev->name); -++ flag = 0; -++ np->full_duplex=0; -++ } -++ if (np->media==2) { -++ infoprintk("%s: Current Operation Mode is [10M Full Duplex]",dev->name); -++ flag = OMR_TTM; -++ np->full_duplex=1; -++ } -++ if (np->media==1) { -++ infoprintk("%s: Current Operation Mode is [10M Half Duplex]",dev->name); -++ flag = OMR_TTM; -++ np->full_duplex=0; -++ } -++ printk("\n"); -++ return flag; -++} -++ -++/* -++ * Ethernet device hardware init -++ * This routine initializes the ethernet device hardware and PHY -++ */ -++static int jz_init_hw(struct net_device *dev) -++{ -++ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -++ struct ethtool_cmd ecmd; -++ u32 mcr, omr; -++ u32 sts, flag = 0; -++ int i; -++ -++ jz_eth_reset(); -++ STOP_ETH; -++#if 0 -++ /* mii operation */ -++ if (jz_phy_reset(dev)) { -++ errprintk("PHY device do not reset!\n"); -++ return -EPERM; // return operation not permitted -++ } -++#endif -++ /* Set MAC address */ -++ writel(le32_to_cpu(*(unsigned long *)&dev->dev_addr[0]), MAC_MAL); -++ writel(le32_to_cpu(*(unsigned long *)&dev->dev_addr[4]), MAC_MAH); -++ printk("%s: JZ On-Chip ethernet (MAC ", dev->name); -++ for (i = 0; i < 5; i++) { -++ printk("%2.2x:", dev->dev_addr[i]); -++ } -++ printk("%2.2x, IRQ %d)\n", dev->dev_addr[i], dev->irq); -++ -++ np->mii_phy_cnt = jz_search_mii_phy(dev); -++ printk("%s: Found %d PHY on JZ MAC\n", dev->name, np->mii_phy_cnt); -++ -++ mii_info.phy_id = np->valid_phy; -++ mii_info.dev = dev; -++ mii_info.mdio_read = &mdio_read; -++ mii_info.mdio_write = &mdio_write; -++ -++ ecmd.speed = SPEED_100; -++ ecmd.duplex = DUPLEX_FULL; -++ ecmd.port = PORT_MII; -++ ecmd.transceiver = XCVR_INTERNAL; -++ ecmd.phy_address = np->valid_phy; -++ ecmd.autoneg = AUTONEG_ENABLE; -++ -++ mii_ethtool_sset(&mii_info,&ecmd); -++ if (jz_autonet_complete(dev)) -++ errprintk("%s: Ethernet Module AutoNegotiation failed\n",dev->name); -++ mii_ethtool_gset(&mii_info,&ecmd); -++ -++ infoprintk("%s: Provide Modes: ",dev->name); -++ for (i = 0; i < 5;i++) -++ if (ecmd.advertising & (1<full_duplex) -++ mcr |= MCR_FDX; -++ mcr |= MCR_BFD | MCR_TE | MCR_RE | MCR_OWD|MCR_HBD; -++ writel(mcr, MAC_MCR); -++// mcr &= (readl(MAC_MCR) & ~(MCR_PM | MCR_PR | MCR_IF | MCR_HO | MCR_HP)); -++// mcr &= 0xffdf; -++// mcr |= 0x0020; -++// writel(mcr, MAC_MCR); -++ -++ /* Set base address of TX and RX descriptors */ -++ writel(np->dma_rx_ring, DMA_RRBA); -++ writel(np->dma_tx_ring, DMA_TRBA); -++ -++ START_ETH; -++ -++ /* set interrupt mask */ -++ writel(IMR_DEFAULT | IMR_ENABLE, DMA_IMR); -++ -++ /* Reset any pending (stale) interrupts */ -++ sts = readl(DMA_STS); -++ writel(sts, DMA_STS); -++ -++ return 0; -++} -++ -++static int jz_eth_open(struct net_device *dev) -++{ -++ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -++ int retval, i; -++ -++ retval = request_irq(dev->irq, jz_eth_interrupt, 0, dev->name, dev); -++ if (retval) { -++ errprintk("%s: unable to get IRQ %d .\n", dev->name, dev->irq); -++ return -EAGAIN; -++ } -++ -++ for (i = 0; i < NUM_RX_DESCS; i++) { -++ np->rx_ring[i].status = cpu_to_le32(R_OWN); -++ np->rx_ring[i].desc1 = cpu_to_le32(RX_BUF_SIZE | RD_RCH); -++ np->rx_ring[i].buf1_addr = cpu_to_le32(np->dma_rx_buf + i*RX_BUF_SIZE); -++ np->rx_ring[i].next_addr = cpu_to_le32(np->dma_rx_ring + (i+1) * sizeof (jz_desc_t)); -++ } -++ np->rx_ring[NUM_RX_DESCS - 1].next_addr = cpu_to_le32(np->dma_rx_ring); -++ -++ for (i = 0; i < NUM_TX_DESCS; i++) { -++ np->tx_ring[i].status = cpu_to_le32(0); -++ np->tx_ring[i].desc1 = cpu_to_le32(TD_TCH); -++ np->tx_ring[i].buf1_addr = 0; -++ np->tx_ring[i].next_addr = cpu_to_le32(np->dma_tx_ring + (i+1) * sizeof (jz_desc_t)); -++ } -++ np->tx_ring[NUM_TX_DESCS - 1].next_addr = cpu_to_le32(np->dma_tx_ring); -++ -++ np->rx_head = 0; -++ np->tx_head = np->tx_tail = 0; -++ -++ jz_init_hw(dev); -++ -++ dev->trans_start = jiffies; -++ netif_start_queue(dev); -++ start_check(dev); -++ -++ return 0; -++} -++ -++static int jz_eth_close(struct net_device *dev) -++{ -++ netif_stop_queue(dev); -++ close_check(dev); -++ STOP_ETH; -++ free_irq(dev->irq, dev); -++ return 0; -++} -++ -++/* -++ * Get the current statistics. -++ * This may be called with the device open or closed. -++ */ -++static struct net_device_stats * jz_eth_get_stats(struct net_device *dev) -++{ -++ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -++ int tmp; -++ -++ tmp = readl(DMA_MFC); // After read clear to zero -++ np->stats.rx_missed_errors += (tmp & MFC_CNT2) + ((tmp & MFC_CNT1) >> 16); -++ -++ return &np->stats; -++} -++ -++/* -++ * ethtool routines -++ */ -++static int jz_ethtool_ioctl(struct net_device *dev, void *useraddr) -++{ -++ struct jz_eth_private *np = dev->priv; -++ u32 ethcmd; -++ -++ /* dev_ioctl() in ../../net/core/dev.c has already checked -++ capable(CAP_NET_ADMIN), so don't bother with that here. */ -++ -++ if (get_user(ethcmd, (u32 *)useraddr)) -++ return -EFAULT; -++ -++ switch (ethcmd) { -++ -++ case ETHTOOL_GDRVINFO: { -++ struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; -++ strcpy (info.driver, DRV_NAME); -++ strcpy (info.version, DRV_VERSION); -++ strcpy (info.bus_info, "OCS"); -++ if (copy_to_user (useraddr, &info, sizeof (info))) -++ return -EFAULT; -++ return 0; -++ } -++ -++ /* get settings */ -++ case ETHTOOL_GSET: { -++ struct ethtool_cmd ecmd = { ETHTOOL_GSET }; -++ spin_lock_irq(&np->lock); -++ mii_ethtool_gset(&mii_info, &ecmd); -++ spin_unlock_irq(&np->lock); -++ if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) -++ return -EFAULT; -++ return 0; -++ } -++ /* set settings */ -++ case ETHTOOL_SSET: { -++ int r; -++ struct ethtool_cmd ecmd; -++ if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) -++ return -EFAULT; -++ spin_lock_irq(&np->lock); -++ r = mii_ethtool_sset(&mii_info, &ecmd); -++ spin_unlock_irq(&np->lock); -++ return r; -++ } -++ /* restart autonegotiation */ -++ case ETHTOOL_NWAY_RST: { -++ return mii_nway_restart(&mii_info); -++ } -++ /* get link status */ -++ case ETHTOOL_GLINK: { -++ struct ethtool_value edata = {ETHTOOL_GLINK}; -++ edata.data = mii_link_ok(&mii_info); -++ if (copy_to_user(useraddr, &edata, sizeof(edata))) -++ return -EFAULT; -++ return 0; -++ } -++ -++ /* get message-level */ -++ case ETHTOOL_GMSGLVL: { -++ struct ethtool_value edata = {ETHTOOL_GMSGLVL}; -++ edata.data = debug; -++ if (copy_to_user(useraddr, &edata, sizeof(edata))) -++ return -EFAULT; -++ return 0; -++ } -++ /* set message-level */ -++ case ETHTOOL_SMSGLVL: { -++ struct ethtool_value edata; -++ if (copy_from_user(&edata, useraddr, sizeof(edata))) -++ return -EFAULT; -++ debug = edata.data; -++ return 0; -++ } -++ -++ -++ default: -++ break; -++ } -++ -++ return -EOPNOTSUPP; -++ -++} -++ -++/* -++ * Config device -++ */ -++static int jz_eth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -++{ -++ struct jz_eth_private *np =(struct jz_eth_private *)dev->priv; -++ struct mii_ioctl_data *data, rdata; -++ -++ switch (cmd) { -++ case SIOCETHTOOL: -++ return jz_ethtool_ioctl(dev, (void *) rq->ifr_data); -++ case SIOCGMIIPHY: -++ case SIOCDEVPRIVATE: -++ data = (struct mii_ioctl_data *)&rq->ifr_data; -++ data->phy_id = np->valid_phy; -++ case SIOCGMIIREG: -++ case SIOCDEVPRIVATE+1: -++ data = (struct mii_ioctl_data *)&rq->ifr_data; -++ data->val_out = mdio_read(dev,np->valid_phy, data->reg_num & 0x1f); -++ return 0; -++ case SIOCSMIIREG: -++ case SIOCDEVPRIVATE+2: -++ data = (struct mii_ioctl_data *)&rq->ifr_data; -++ if (!capable(CAP_NET_ADMIN)) -++ return -EPERM; -++ mdio_write(dev,np->valid_phy, data->reg_num & 0x1f, data->val_in); -++ return 0; -++ case READ_COMMAND: -++ data = (struct mii_ioctl_data *)rq->ifr_data; -++ if (copy_from_user(&rdata,data,sizeof(rdata))) -++ return -EFAULT; -++ rdata.val_out = mdio_read(dev,rdata.phy_id, rdata.reg_num & 0x1f); -++ if (copy_to_user(data,&rdata,sizeof(rdata))) -++ return -EFAULT; -++ return 0; -++ case WRITE_COMMAND: -++ if (np->phy_type==1) { -++ data = (struct mii_ioctl_data *)rq->ifr_data; -++ if (!capable(CAP_NET_ADMIN)) -++ return -EPERM; -++ if (copy_from_user(&rdata,data,sizeof(rdata))) -++ return -EFAULT; -++ mdio_write(dev,rdata.phy_id, rdata.reg_num & 0x1f, rdata.val_in); -++ } -++ return 0; -++ case GETDRIVERINFO: -++ if (np->phy_type==1) { -++ data = (struct mii_ioctl_data *)rq->ifr_data; -++ if (copy_from_user(&rdata,data,sizeof(rdata))) -++ return -EFAULT; -++ rdata.val_in = 0x1; -++ rdata.val_out = 0x00d0; -++ if (copy_to_user(data,&rdata,sizeof(rdata))) -++ return -EFAULT; -++ } -++ return 0; -++ default: -++ return -EOPNOTSUPP; -++ } -++ return 0; -++} -++ -++/* -++ * Received one packet -++ */ -++static void eth_rxready(struct net_device *dev) -++{ -++ struct jz_eth_private *np = (struct jz_eth_private*)dev->priv; -++ struct sk_buff *skb; -++ unsigned char *pkt_ptr; -++ u32 pkt_len; -++ u32 status; -++ -++ status = le32_to_cpu(np->rx_ring[np->rx_head].status); -++ while (!(status & R_OWN)) { /* owner bit = 0 */ -++ if (status & RD_ES) { /* error summary */ -++ np->stats.rx_errors++; /* Update the error stats. */ -++ if (status & (RD_RF | RD_TL)) -++ np->stats.rx_frame_errors++; -++ if (status & RD_CE) -++ np->stats.rx_crc_errors++; -++ if (status & RD_TL) -++ np->stats.rx_length_errors++; -++ } else { -++ pkt_ptr = bus_to_virt(le32_to_cpu(np->rx_ring[np->rx_head].buf1_addr)); -++ pkt_len = ((status & RD_FL) >> 16) - 4; -++ -++ skb = dev_alloc_skb(pkt_len + 2); -++ if (skb == NULL) { -++ printk("%s: Memory squeeze, dropping.\n", -++ dev->name); -++ np->stats.rx_dropped++; -++ break; -++ } -++ skb->dev = dev; -++ skb_reserve(skb, 2); /* 16 byte align */ -++ -++ //pkt_ptr = P1ADDR(pkt_ptr); -++ //dma_cache_inv(pkt_ptr, pkt_len); -++ memcpy(skb->data, pkt_ptr, pkt_len); -++ skb_put(skb, pkt_len); -++ -++ //eth_dbg_rx(skb, pkt_len); -++ skb->protocol = eth_type_trans(skb,dev); -++ netif_rx(skb); /* pass the packet to upper layers */ -++ dev->last_rx = jiffies; -++ np->stats.rx_packets++; -++ np->stats.rx_bytes += pkt_len; -++ } -++ np->rx_ring[np->rx_head].status = cpu_to_le32(R_OWN); -++ -++ np->rx_head ++; -++ if (np->rx_head >= NUM_RX_DESCS) -++ np->rx_head = 0; -++ status = le32_to_cpu(np->rx_ring[np->rx_head].status); -++ } -++} -++ -++/* -++ * Tx timeout routine -++ */ -++static void jz_eth_tx_timeout(struct net_device *dev) -++{ -++ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -++ -++ jz_init_hw(dev); -++ np->stats.tx_errors ++; -++ netif_wake_queue(dev); -++} -++ -++/* -++ * One packet was transmitted -++ */ -++static void eth_txdone(struct net_device *dev) -++{ -++ struct jz_eth_private *np = (struct jz_eth_private*)dev->priv; -++ int tx_tail = np->tx_tail; -++ -++ while (tx_tail != np->tx_head) { -++ int entry = tx_tail % NUM_TX_DESCS; -++ s32 status = le32_to_cpu(np->tx_ring[entry].status); -++ if(status < 0) break; -++ if (status & TD_ES ) { /* Error summary */ -++ np->stats.tx_errors++; -++ if (status & TD_NC) np->stats.tx_carrier_errors++; -++ if (status & TD_LC) np->stats.tx_window_errors++; -++ if (status & TD_UF) np->stats.tx_fifo_errors++; -++ if (status & TD_DE) np->stats.tx_aborted_errors++; -++ if (np->tx_head != np->tx_tail) -++ writel(1, DMA_TPD); /* Restart a stalled TX */ -++ } else -++ np->stats.tx_packets++; -++ /* Update the collision counter */ -++ np->stats.collisions += ((status & TD_EC) ? 16 : ((status & TD_CC) >> 3)); -++ /* Free the original skb */ -++ if (np->tx_skb[entry]) { -++ dev_kfree_skb_irq(np->tx_skb[entry]); -++ np->tx_skb[entry] = 0; -++ } -++ tx_tail++; -++ } -++ if (np->tx_full && (tx_tail + NUM_TX_DESCS > np->tx_head + 1)) { -++ /* The ring is no longer full */ -++ np->tx_full = 0; -++ netif_start_queue(dev); -++ } -++ np->tx_tail = tx_tail; -++} -++ -++/* -++ * Update the tx descriptor -++ */ -++static void load_tx_packet(struct net_device *dev, char *buf, u32 flags, struct sk_buff *skb) -++{ -++ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -++ int entry = np->tx_head % NUM_TX_DESCS; -++ -++ np->tx_ring[entry].buf1_addr = cpu_to_le32(virt_to_bus(buf)); -++ np->tx_ring[entry].desc1 &= cpu_to_le32((TD_TER | TD_TCH)); -++ np->tx_ring[entry].desc1 |= cpu_to_le32(flags); -++ np->tx_ring[entry].status = cpu_to_le32(T_OWN); -++ np->tx_skb[entry] = skb; -++} -++ -++/* -++ * Transmit one packet -++ */ -++static int jz_eth_send_packet(struct sk_buff *skb, struct net_device *dev) -++{ -++ struct jz_eth_private *np = (struct jz_eth_private *)dev->priv; -++ u32 length; -++ -++ if (np->tx_full) { -++ return 0; -++ } -++#ifdef CONFIG_FPGA -++ mdelay(10); -++#else -++ udelay(500); /* FIXME: can we remove this delay ? */ -++#endif -++ length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; -++ dma_cache_wback((unsigned long)skb->data, length); -++ load_tx_packet(dev, (char *)skb->data, TD_IC | TD_LS | TD_FS | length, skb); -++ spin_lock_irq(&np->lock); -++ np->tx_head ++; -++ np->stats.tx_bytes += length; -++ writel(1, DMA_TPD); /* Start the TX */ -++ dev->trans_start = jiffies; /* for timeout */ -++ if (np->tx_tail + NUM_TX_DESCS > np->tx_head + 1) { -++ np->tx_full = 0; -++ } -++ else { -++ np->tx_full = 1; -++ netif_stop_queue(dev); -++ } -++ spin_unlock_irq(&np->lock); -++ -++ return 0; -++} -++ -++/* -++ * Interrupt service routine -++ */ -++static irqreturn_t jz_eth_interrupt(int irq, void *dev_id) -++{ -++ struct net_device *dev = (struct net_device *)dev_id; -++ struct jz_eth_private *np = dev->priv; -++ u32 sts; -++ int i; -++ -++ spin_lock(&np->lock); -++ -++ writel((readl(DMA_IMR) & ~IMR_ENABLE), DMA_IMR); /* Disable interrupt */ -++ -++ for (i = 0; i < 100; i++) { -++ sts = readl(DMA_STS); -++ writel(sts, DMA_STS); /* clear status */ -++ -++ if (!(sts & IMR_DEFAULT)) break; -++ -++ if (sts & (DMA_INT_RI | DMA_INT_RU)) /* Rx IRQ */ -++ eth_rxready(dev); -++ if (sts & (DMA_INT_TI | DMA_INT_TU)) /* Tx IRQ */ -++ eth_txdone(dev); -++ -++ /* check error conditions */ -++ if (sts & DMA_INT_FB){ /* fatal bus error */ -++ STOP_ETH; -++ errprintk("%s: Fatal bus error occurred, sts=%#8x, device stopped.\n",dev->name, sts); -++ break; -++ } -++ -++ if (sts & DMA_INT_UN) { /* Transmit underrun */ -++ u32 omr; -++ omr = readl(DMA_OMR); -++ if (!(omr & OMR_SF)) { -++ omr &= ~(OMR_ST | OMR_SR); -++ writel(omr, DMA_OMR); -++ while (readl(DMA_STS) & STS_TS); /* wait for stop */ -++ if ((omr & OMR_TR) < OMR_TR) { /* ? */ -++ omr += TR_24; -++ } else { -++ omr |= OMR_SF; -++ } -++ writel(omr | OMR_ST | OMR_SR, DMA_OMR); -++ } -++ } -++ } -++ -++ writel(readl(DMA_IMR) | IMR_ENABLE, DMA_IMR); /* enable interrupt */ -++ -++ spin_unlock(&np->lock); -++ -++ return IRQ_HANDLED; -++} -++ -++#if 0 //def CONFIG_PM -++/* -++ * Suspend the ETH interface. -++ */ -++static int jz_eth_suspend(struct net_device *dev, int state) -++{ -++ struct jz_eth_private *jep = (struct jz_eth_private *)dev->priv; -++ unsigned long flags, tmp; -++ -++ printk("ETH suspend.\n"); -++ -++ if (!netif_running(dev)) { -++ return 0; -++ } -++ -++ netif_device_detach(dev); -++ -++ spin_lock_irqsave(&jep->lock, flags); -++ -++ /* Disable interrupts, stop Tx and Rx. */ -++ REG32(DMA_IMR) = 0; -++ STOP_ETH; -++ -++ /* Update the error counts. */ -++ tmp = REG32(DMA_MFC); -++ jep->stats.rx_missed_errors += (tmp & 0x1ffff); -++ jep->stats.rx_fifo_errors += ((tmp >> 17) & 0x7ff); -++ -++ spin_unlock_irqrestore(&jep->lock, flags); -++ -++ return 0; -++} -++ -++/* -++ * Resume the ETH interface. -++ */ -++static int jz_eth_resume(struct net_device *dev) -++{ -++ printk("ETH resume.\n"); -++ -++ if (!netif_running(dev)) -++ return 0; -++ -++ jz_init_hw(dev); -++ -++ netif_device_attach(dev); -++ jz_eth_tx_timeout(dev); -++ netif_wake_queue(dev); -++ -++ return 0; -++} -++ -++static int jz_eth_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) -++{ -++ int ret; -++ -++ if (!dev->data) -++ return -EINVAL; -++ -++ switch (rqst) { -++ case PM_SUSPEND: -++ ret = jz_eth_suspend((struct net_device *)dev->data, -++ (int)data); -++ break; -++ -++ case PM_RESUME: -++ ret = jz_eth_resume((struct net_device *)dev->data); -++ break; -++ -++ default: -++ ret = -EINVAL; -++ break; -++ } -++ -++ return ret; -++} -++ -++#endif /* CONFIG_PM */ -++ -++static int __init jz_eth_init(void) -++{ -++ struct net_device *dev; -++ struct jz_eth_private *np; -++ int err; -++ -++ dev = alloc_etherdev(sizeof(struct jz_eth_private)); -++ if (!dev) { -++ printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME); -++ return -ENOMEM; -++ } -++ netdev = dev; -++ -++ np = (struct jz_eth_private *)P2ADDR(dev->priv); -++ dev->priv = np; -++ memset(np, 0, sizeof(struct jz_eth_private)); -++ -++ np->vaddr_rx_buf = (u32)dma_alloc_noncoherent(NULL, NUM_RX_DESCS*RX_BUF_SIZE, -++ &np->dma_rx_buf, 0); -++ -++ if (!np->vaddr_rx_buf) { -++ printk(KERN_ERR "%s: Cannot alloc dma buffers\n", DRV_NAME); -++ unregister_netdev(dev); -++ free_netdev(dev); -++ return -ENOMEM; -++ } -++ -++ np->dma_rx_ring = virt_to_bus(np->rx_ring); -++ np->dma_tx_ring = virt_to_bus(np->tx_ring); -++ np->full_duplex = 1; -++ np->link_state = 1; -++ -++ spin_lock_init(&np->lock); -++ -++ ether_setup(dev); -++ dev->irq = IRQ_ETH; -++ dev->open = jz_eth_open; -++ dev->stop = jz_eth_close; -++ dev->hard_start_xmit = jz_eth_send_packet; -++ dev->get_stats = jz_eth_get_stats; -++ dev->set_multicast_list = jz_set_multicast_list; -++ dev->do_ioctl = jz_eth_ioctl; -++ dev->tx_timeout = jz_eth_tx_timeout; -++ dev->watchdog_timeo = ETH_TX_TIMEOUT; -++ -++ /* configure MAC address */ -++ get_mac_address(dev); -++ -++ if ((err = register_netdev(dev)) != 0) { -++ printk(KERN_ERR "%s: Cannot register net device, error %d\n", -++ DRV_NAME, err); -++ free_netdev(dev); -++ return -ENOMEM; -++ } -++ -++//#ifdef 0 //CONFIG_PM -++// np->pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, jz_eth_pm_callback); -++// if (np->pmdev) -++// np->pmdev->data = dev; -++//#endif -++ -++ return 0; -++} -++ -++static void __exit jz_eth_exit(void) -++{ -++ struct net_device *dev = netdev; -++ struct jz_eth_private *np = dev->priv; -++ -++ unregister_netdev(dev); -++ dma_free_noncoherent(NULL, NUM_RX_DESCS * RX_BUF_SIZE, -++ (void *)np->vaddr_rx_buf, np->dma_rx_buf); -++ free_netdev(dev); -++} -++ -++module_init(jz_eth_init); -++module_exit(jz_eth_exit); -+diff -urN linux-2.6.24.7.old/drivers/net/jz_eth.h linux-2.6.24.7/drivers/net/jz_eth.h -+--- linux-2.6.24.7.old/drivers/net/jz_eth.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/net/jz_eth.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,403 @@ -++/* -++ * linux/drivers/net/jz_eth.h -++ * -++ * Jz4730/Jz5730 On-Chip ethernet driver. -++ * -++ * Copyright (C) 2005 - 2007 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ */ -++#ifndef __JZ_ETH_H__ -++#define __JZ_ETH_H__ -++ -++/* DMA control and status registers */ -++#define DMA_BMR (ETH_BASE + 0x1000) // Bus mode -++#define DMA_TPD (ETH_BASE + 0x1004) // Transmit poll demand register -++#define DMA_RPD (ETH_BASE + 0x1008) // Receieve poll demand register -++#define DMA_RRBA (ETH_BASE + 0x100C) // Receieve descriptor base address -++#define DMA_TRBA (ETH_BASE + 0x1010) // Transmit descriptor base address -++#define DMA_STS (ETH_BASE + 0x1014) // Status register -++#define DMA_OMR (ETH_BASE + 0x1018) // Command register -++#define DMA_IMR (ETH_BASE + 0x101C) -++#define DMA_MFC (ETH_BASE + 0x1020) -++ -++/* DMA CSR8-CSR19 reserved */ -++#define DMA_CTA (ETH_BASE + 0x1050) -++#define DMA_CRA (ETH_BASE + 0x1054) -++ -++/* Mac control and status registers */ -++#define MAC_MCR (ETH_BASE + 0x0000) -++#define MAC_MAH (ETH_BASE + 0x0004) -++#define MAC_MAL (ETH_BASE + 0x0008) -++#define MAC_HTH (ETH_BASE + 0x000C) -++#define MAC_HTL (ETH_BASE + 0x0010) -++#define MAC_MIIA (ETH_BASE + 0x0014) -++#define MAC_MIID (ETH_BASE + 0x0018) -++#define MAC_FCR (ETH_BASE + 0x001C) -++#define MAC_VTR1 (ETH_BASE + 0x0020) -++#define MAC_VTR2 (ETH_BASE + 0x0024) -++ -++/* -++ * Bus Mode Register (DMA_BMR) -++ */ -++#define BMR_PBL 0x00003f00 /* Programmable Burst Length */ -++#define BMR_DSL 0x0000007c /* Descriptor Skip Length */ -++#define BMR_BAR 0x00000002 /* Bus ARbitration */ -++#define BMR_SWR 0x00000001 /* Software Reset */ -++ -++#define PBL_0 0x00000000 /* DMA burst length = amount in RX FIFO */ -++#define PBL_1 0x00000100 /* 1 longword DMA burst length */ -++#define PBL_2 0x00000200 /* 2 longwords DMA burst length */ -++#define PBL_4 0x00000400 /* 4 longwords DMA burst length */ -++#define PBL_8 0x00000800 /* 8 longwords DMA burst length */ -++#define PBL_16 0x00001000 /* 16 longwords DMA burst length */ -++#define PBL_32 0x00002000 /* 32 longwords DMA burst length */ -++ -++#define DSL_0 0x00000000 /* 0 longword / descriptor */ -++#define DSL_1 0x00000004 /* 1 longword / descriptor */ -++#define DSL_2 0x00000008 /* 2 longwords / descriptor */ -++#define DSL_4 0x00000010 /* 4 longwords / descriptor */ -++#define DSL_8 0x00000020 /* 8 longwords / descriptor */ -++#define DSL_16 0x00000040 /* 16 longwords / descriptor */ -++#define DSL_32 0x00000080 /* 32 longwords / descriptor */ -++ -++/* -++ * Status Register (DMA_STS) -++ */ -++#define STS_BE 0x03800000 /* Bus Error Bits */ -++#define STS_TS 0x00700000 /* Transmit Process State */ -++#define STS_RS 0x000e0000 /* Receive Process State */ -++ -++#define TS_STOP 0x00000000 /* Stopped */ -++#define TS_FTD 0x00100000 /* Running Fetch Transmit Descriptor */ -++#define TS_WEOT 0x00200000 /* Running Wait for End Of Transmission */ -++#define TS_QDAT 0x00300000 /* Running Queue skb data into TX FIFO */ -++#define TS_RES 0x00400000 /* Reserved */ -++#define TS_SPKT 0x00500000 /* Reserved */ -++#define TS_SUSP 0x00600000 /* Suspended */ -++#define TS_CLTD 0x00700000 /* Running Close Transmit Descriptor */ -++ -++#define RS_STOP 0x00000000 /* Stopped */ -++#define RS_FRD 0x00020000 /* Running Fetch Receive Descriptor */ -++#define RS_CEOR 0x00040000 /* Running Check for End of Receive Packet */ -++#define RS_WFRP 0x00060000 /* Running Wait for Receive Packet */ -++#define RS_SUSP 0x00080000 /* Suspended */ -++#define RS_CLRD 0x000a0000 /* Running Close Receive Descriptor */ -++#define RS_FLUSH 0x000c0000 /* Running Flush RX FIFO */ -++#define RS_QRFS 0x000e0000 /* Running Queue RX FIFO into RX Skb */ -++ -++/* -++ * Operation Mode Register (DMA_OMR) -++ */ -++#define OMR_TTM 0x00400000 /* Transmit Threshold Mode */ -++#define OMR_SF 0x00200000 /* Store and Forward */ -++#define OMR_TR 0x0000c000 /* Threshold Control Bits */ -++#define OMR_ST 0x00002000 /* Start/Stop Transmission Command */ -++#define OMR_OSF 0x00000004 /* Operate on Second Frame */ -++#define OMR_SR 0x00000002 /* Start/Stop Receive */ -++ -++#define TR_18 0x00000000 /* Threshold set to 18 (32) bytes */ -++#define TR_24 0x00004000 /* Threshold set to 24 (64) bytes */ -++#define TR_32 0x00008000 /* Threshold set to 32 (128) bytes */ -++#define TR_40 0x0000c000 /* Threshold set to 40 (256) bytes */ -++ -++/* -++ * Missed Frames Counters (DMA_MFC) -++ */ -++//#define MFC_CNT1 0xffff0000 /* Missed Frames Counter Bits by application */ -++#define MFC_CNT1 0x0ffe0000 /* Missed Frames Counter Bits by application */ -++#define MFC_CNT2 0x0000ffff /* Missed Frames Counter Bits by controller */ -++ -++/* -++ * Mac control Register (MAC_MCR) -++ */ -++#define MCR_RA 0x80000000 /* Receive All */ -++#define MCR_HBD 0x10000000 /* HeartBeat Disable */ -++#define MCR_PS 0x08000000 /* Port Select */ -++#define MCR_OWD 0x00800000 /* Receive own Disable */ -++#define MCR_OM 0x00600000 /* Operating(loopback) Mode */ -++#define MCR_FDX 0x00100000 /* Full Duplex Mode */ -++#define MCR_PM 0x00080000 /* Pass All Multicast */ -++#define MCR_PR 0x00040000 /* Promiscuous Mode */ -++#define MCR_IF 0x00020000 /* Inverse Filtering */ -++#define MCR_PB 0x00010000 /* Pass Bad Frames */ -++#define MCR_HO 0x00008000 /* Hash Only Filtering Mode */ -++#define MCR_HP 0x00002000 /* Hash/Perfect Receive Filtering Mode */ -++#define MCR_FC 0x00001000 /* Late Collision control */ -++#define MCR_BFD 0x00000800 /* Boardcast frame Disable */ -++#define MCR_RED 0x00000400 /* Retry Disable */ -++#define MCR_APS 0x00000100 /* Automatic pad stripping */ -++#define MCR_BL 0x000000c0 /* Back off Limit */ -++#define MCR_DC 0x00000020 /* Deferral check */ -++#define MCR_TE 0x00000008 /* Transmitter enable */ -++#define MCR_RE 0x00000004 /* Receiver enable */ -++ -++#define MCR_MII_10 ( OMR_TTM | MCR_PS) -++#define MCR_MII_100 ( MCR_HBD | MCR_PS) -++ -++/* Flow control Register (MAC_FCR) */ -++#define FCR_PT 0xffff0000 /* Pause time */ -++#define FCR_PCF 0x00000004 /* Pass control frames */ -++#define FCR_FCE 0x00000002 /* Flow control enable */ -++#define FCR_FCB 0x00000001 /* Flow control busy */ -++ -++ -++/* Constants for the interrupt mask and -++ * interrupt status registers. (DMA_SIS and DMA_IMR) -++ */ -++#define DMA_INT_NI 0x00010000 // Normal interrupt summary -++#define DMA_INT_AI 0x00008000 // Abnormal interrupt summary -++#define DMA_INT_ER 0x00004000 // Early receive interrupt -++#define DMA_INT_FB 0x00002000 // Fatal bus error -++#define DMA_INT_ET 0x00000400 // Early transmit interrupt -++#define DMA_INT_RW 0x00000200 // Receive watchdog timeout -++#define DMA_INT_RS 0x00000100 // Receive stop -++#define DMA_INT_RU 0x00000080 // Receive buffer unavailble -++#define DMA_INT_RI 0x00000040 // Receive interrupt -++#define DMA_INT_UN 0x00000020 // Underflow -++#define DMA_INT_TJ 0x00000008 // Transmit jabber timeout -++#define DMA_INT_TU 0x00000004 // Transmit buffer unavailble -++#define DMA_INT_TS 0x00000002 // Transmit stop -++#define DMA_INT_TI 0x00000001 // Transmit interrupt -++ -++/* -++ * Receive Descriptor Bit Summary -++ */ -++#define R_OWN 0x80000000 /* Own Bit */ -++#define RD_FF 0x40000000 /* Filtering Fail */ -++#define RD_FL 0x3fff0000 /* Frame Length */ -++#define RD_ES 0x00008000 /* Error Summary */ -++#define RD_DE 0x00004000 /* Descriptor Error */ -++#define RD_LE 0x00001000 /* Length Error */ -++#define RD_RF 0x00000800 /* Runt Frame */ -++#define RD_MF 0x00000400 /* Multicast Frame */ -++#define RD_FS 0x00000200 /* First Descriptor */ -++#define RD_LS 0x00000100 /* Last Descriptor */ -++#define RD_TL 0x00000080 /* Frame Too Long */ -++#define RD_CS 0x00000040 /* Collision Seen */ -++#define RD_FT 0x00000020 /* Frame Type */ -++#define RD_RJ 0x00000010 /* Receive Watchdog timeout*/ -++#define RD_RE 0x00000008 /* Report on MII Error */ -++#define RD_DB 0x00000004 /* Dribbling Bit */ -++#define RD_CE 0x00000002 /* CRC Error */ -++ -++#define RD_RER 0x02000000 /* Receive End Of Ring */ -++#define RD_RCH 0x01000000 /* Second Address Chained */ -++#define RD_RBS2 0x003ff800 /* Buffer 2 Size */ -++#define RD_RBS1 0x000007ff /* Buffer 1 Size */ -++ -++/* -++ * Transmit Descriptor Bit Summary -++ */ -++#define T_OWN 0x80000000 /* Own Bit */ -++#define TD_ES 0x00008000 /* Frame Aborted (error summary)*/ -++#define TD_LO 0x00000800 /* Loss Of Carrier */ -++#define TD_NC 0x00000400 /* No Carrier */ -++#define TD_LC 0x00000200 /* Late Collision */ -++#define TD_EC 0x00000100 /* Excessive Collisions */ -++#define TD_HF 0x00000080 /* Heartbeat Fail */ -++#define TD_CC 0x0000003c /* Collision Counter */ -++#define TD_UF 0x00000002 /* Underflow Error */ -++#define TD_DE 0x00000001 /* Deferred */ -++ -++#define TD_IC 0x80000000 /* Interrupt On Completion */ -++#define TD_LS 0x40000000 /* Last Segment */ -++#define TD_FS 0x20000000 /* First Segment */ -++#define TD_FT1 0x10000000 /* Filtering Type */ -++#define TD_SET 0x08000000 /* Setup Packet */ -++#define TD_AC 0x04000000 /* Add CRC Disable */ -++#define TD_TER 0x02000000 /* Transmit End Of Ring */ -++#define TD_TCH 0x01000000 /* Second Address Chained */ -++#define TD_DPD 0x00800000 /* Disabled Padding */ -++#define TD_FT0 0x00400000 /* Filtering Type */ -++#define TD_TBS2 0x003ff800 /* Buffer 2 Size */ -++#define TD_TBS1 0x000007ff /* Buffer 1 Size */ -++ -++#define PERFECT_F 0x00000000 -++#define HASH_F TD_FT0 -++#define INVERSE_F TD_FT1 -++#define HASH_O_F (TD_FT1 | TD_F0) -++ -++/* -++ * Constant setting -++ */ -++ -++#define IMR_DEFAULT ( DMA_INT_TI | DMA_INT_RI | \ -++ DMA_INT_TS | DMA_INT_RS | \ -++ DMA_INT_TU | DMA_INT_RU | \ -++ DMA_INT_FB ) -++ -++#define IMR_ENABLE (DMA_INT_NI | DMA_INT_AI) -++ -++#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -++#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ -++ -++#define HASH_TABLE_LEN 512 /* Bits */ -++#define HASH_BITS 0x01ff /* 9 LS bits */ -++ -++#define SETUP_FRAME_LEN 192 /* Bytes */ -++#define IMPERF_PA_OFFSET 156 /* Bytes */ -++ -++/* -++ * Address Filtering Modes -++ */ -++#define PERFECT 0 /* 16 perfect physical addresses */ -++#define HASH_PERF 1 /* 1 perfect, 512 multicast addresses */ -++#define PERFECT_REJ 2 /* Reject 16 perfect physical addresses */ -++#define ALL_HASH 3 /* Hashes all physical & multicast addrs */ -++ -++#define ALL 0 /* Clear out all the setup frame */ -++#define PHYS_ADDR_ONLY 1 /* Update the physical address only */ -++ -++/* MII register */ -++#define MII_BMCR 0x00 /* MII Basic Mode Control Register */ -++#define MII_BMSR 0x01 /* MII Basic Mode Status Register */ -++#define MII_ID1 0x02 /* PHY Identifier Register 1 */ -++#define MII_ID2 0x03 /* PHY Identifier Register 2 */ -++#define MII_ANAR 0x04 /* Auto Negotiation Advertisement Register */ -++#define MII_ANLPAR 0x05 /* Auto Negotiation Link Partner Ability */ -++#define MII_ANER 0x06 /* Auto Negotiation Expansion */ -++#define MII_DSCR 0x10 /* Davicom Specified Configration Register */ -++#define MII_DSCSR 0x11 /* Davicom Specified Configration/Status Register */ -++#define MII_10BTCSR 0x12 /* 10base-T Specified Configration/Status Register */ -++ -++ -++#define MII_PREAMBLE 0xffffffff /* MII Management Preamble */ -++#define MII_TEST 0xaaaaaaaa /* MII Test Signal */ -++#define MII_STRD 0x06 /* Start of Frame+Op Code: use low nibble */ -++#define MII_STWR 0x0a /* Start of Frame+Op Code: use low nibble */ -++ -++/* -++ * MII Management Control Register -++ */ -++#define MII_CR_RST 0x8000 /* RESET the PHY chip */ -++#define MII_CR_LPBK 0x4000 /* Loopback enable */ -++#define MII_CR_SPD 0x2000 /* 0: 10Mb/s; 1: 100Mb/s */ -++#define MII_CR_ASSE 0x1000 /* Auto Speed Select Enable */ -++#define MII_CR_PD 0x0800 /* Power Down */ -++#define MII_CR_ISOL 0x0400 /* Isolate Mode */ -++#define MII_CR_RAN 0x0200 /* Restart Auto Negotiation */ -++#define MII_CR_FDM 0x0100 /* Full Duplex Mode */ -++#define MII_CR_CTE 0x0080 /* Collision Test Enable */ -++ -++/* -++ * MII Management Status Register -++ */ -++#define MII_SR_T4C 0x8000 /* 100BASE-T4 capable */ -++#define MII_SR_TXFD 0x4000 /* 100BASE-TX Full Duplex capable */ -++#define MII_SR_TXHD 0x2000 /* 100BASE-TX Half Duplex capable */ -++#define MII_SR_TFD 0x1000 /* 10BASE-T Full Duplex capable */ -++#define MII_SR_THD 0x0800 /* 10BASE-T Half Duplex capable */ -++#define MII_SR_ASSC 0x0020 /* Auto Speed Selection Complete*/ -++#define MII_SR_RFD 0x0010 /* Remote Fault Detected */ -++#define MII_SR_ANC 0x0008 /* Auto Negotiation capable */ -++#define MII_SR_LKS 0x0004 /* Link Status */ -++#define MII_SR_JABD 0x0002 /* Jabber Detect */ -++#define MII_SR_XC 0x0001 /* Extended Capabilities */ -++ -++/* -++ * MII Management Auto Negotiation Advertisement Register -++ */ -++#define MII_ANA_TAF 0x03e0 /* Technology Ability Field */ -++#define MII_ANA_T4AM 0x0200 /* T4 Technology Ability Mask */ -++#define MII_ANA_TXAM 0x0180 /* TX Technology Ability Mask */ -++#define MII_ANA_FDAM 0x0140 /* Full Duplex Technology Ability Mask */ -++#define MII_ANA_HDAM 0x02a0 /* Half Duplex Technology Ability Mask */ -++#define MII_ANA_100M 0x0380 /* 100Mb Technology Ability Mask */ -++#define MII_ANA_10M 0x0060 /* 10Mb Technology Ability Mask */ -++#define MII_ANA_CSMA 0x0001 /* CSMA-CD Capable */ -++ -++/* -++ * MII Management Auto Negotiation Remote End Register -++ */ -++#define MII_ANLPA_NP 0x8000 /* Next Page (Enable) */ -++#define MII_ANLPA_ACK 0x4000 /* Remote Acknowledge */ -++#define MII_ANLPA_RF 0x2000 /* Remote Fault */ -++#define MII_ANLPA_TAF 0x03e0 /* Technology Ability Field */ -++#define MII_ANLPA_T4AM 0x0200 /* T4 Technology Ability Mask */ -++#define MII_ANLPA_TXAM 0x0180 /* TX Technology Ability Mask */ -++#define MII_ANLPA_FDAM 0x0140 /* Full Duplex Technology Ability Mask */ -++#define MII_ANLPA_HDAM 0x02a0 /* Half Duplex Technology Ability Mask */ -++#define MII_ANLPA_100M 0x0380 /* 100Mb Technology Ability Mask */ -++#define MII_ANLPA_10M 0x0060 /* 10Mb Technology Ability Mask */ -++#define MII_ANLPA_CSMA 0x0001 /* CSMA-CD Capable */ -++ -++/* -++ * MII Management DAVICOM Specified Configuration And Status Register -++ */ -++#define MII_DSCSR_100FDX 0x8000 /* 100M Full Duplex Operation Mode */ -++#define MII_DSCSR_100HDX 0x4000 /* 100M Half Duplex Operation Mode */ -++#define MII_DSCSR_10FDX 0x2000 /* 10M Full Duplex Operation Mode */ -++#define MII_DSCSR_10HDX 0x1000 /* 10M Half Duplex Operation Mode */ -++#define MII_DSCSR_ANMB 0x000f /* Auto-Negotiation Monitor Bits */ -++ -++ -++/* -++ * Used by IOCTL -++ */ -++#define READ_COMMAND (SIOCDEVPRIVATE+4) -++#define WRITE_COMMAND (SIOCDEVPRIVATE+5) -++#define GETDRIVERINFO (SIOCDEVPRIVATE+6) -++ -++/* -++ * Device data and structure -++ */ -++ -++#define ETH_TX_TIMEOUT (6*HZ) -++ -++#define RX_BUF_SIZE 1536 -++ -++#define NUM_RX_DESCS 32 -++#define NUM_TX_DESCS 16 -++ -++static const char *media_types[] = { -++ "10BaseT-HD ", "10BaseT-FD ","100baseTx-HD ", -++ "100baseTx-FD", "100baseT4", 0 -++}; -++ -++typedef struct { -++ unsigned int status; -++ unsigned int desc1; -++ unsigned int buf1_addr; -++ unsigned int next_addr; -++} jz_desc_t; -++ -++struct jz_eth_private { -++ jz_desc_t tx_ring[NUM_TX_DESCS]; /* transmit descriptors */ -++ jz_desc_t rx_ring[NUM_RX_DESCS]; /* receive descriptors */ -++ dma_addr_t dma_tx_ring; /* bus address of tx ring */ -++ dma_addr_t dma_rx_ring; /* bus address of rx ring */ -++ dma_addr_t dma_rx_buf; /* DMA address of rx buffer */ -++ unsigned int vaddr_rx_buf; /* virtual address of rx buffer */ -++ -++ unsigned int rx_head; /* first rx descriptor */ -++ unsigned int tx_head; /* first tx descriptor */ -++ unsigned int tx_tail; /* last unacked transmit packet */ -++ unsigned int tx_full; /* transmit buffers are full */ -++ struct sk_buff *tx_skb[NUM_TX_DESCS]; /* skbuffs for packets to transmit */ -++ -++ struct net_device_stats stats; -++ spinlock_t lock; -++ -++ int media; /* Media (eg TP), mode (eg 100B)*/ -++ int full_duplex; /* Current duplex setting. */ -++ int link_state; -++ char phys[32]; /* List of attached PHY devices */ -++ char valid_phy; /* Current linked phy-id with MAC */ -++ int mii_phy_cnt; -++ int phy_type; /* 1-RTL8309,0-DVCOM */ -++ struct ethtool_cmd ecmds[32]; -++ u16 advertising; /* NWay media advertisement */ -++ -++ pid_t thr_pid; /* Link cheak thread ID */ -++ int thread_die; -++ struct completion thr_exited; -++ wait_queue_head_t thr_wait; -++ -++ struct pm_dev *pmdev; -++}; -++ -++#endif /* __JZ_ETH_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/net/jzcs8900a.c linux-2.6.24.7/drivers/net/jzcs8900a.c -+--- linux-2.6.24.7.old/drivers/net/jzcs8900a.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/net/jzcs8900a.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,649 @@ -++ -++/* -++ * linux/drivers/net/jzcs8900a.c -++ * -++ * Author: Lucifer -++ * -++ * A Cirrus Logic CS8900A driver for Linux -++ * based on the cs89x0 driver written by Russell Nelson, -++ * Donald Becker, and others. -++ * -++ * This source code is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ */ -++ -++/* -++ * At the moment the driver does not support memory mode operation. -++ * It is trivial to implement this, but not worth the effort. -++ */ -++ -++/* -++ * TODO: -++ * -++ * 1. If !ready in send_start(), queue buffer and send it in interrupt handler -++ * when we receive a BufEvent with Rdy4Tx, send it again. dangerous! -++ * 2. how do we prevent interrupt handler destroying integrity of get_stats()? -++ * 3. Change reset code to check status. -++ * 4. Implement set_mac_address and remove fake mac address -++ * 5. Link status detection stuff -++ * 6. Write utility to write EEPROM, do self testing, etc. -++ * 7. Implement DMA routines (I need a board w/ DMA support for that) -++ * 8. Power management -++ * 9. Add support for multiple ethernet chips -++ * 10. Add support for other cs89xx chips (need hardware for that) -++ */ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include "jzcs8900a.h" -++ -++#define FULL_DUPLEX -++#define INT_PIN 0 -++#ifdef CONFIG_SOC_JZ4740 -++#define CIRRUS_DEFAULT_IO 0xa8000000 -++#define CIRRUS_DEFAULT_IRQ 107 -++ -++#elif CONFIG_SOC_JZ4750 -++#define CIRRUS_DEFAULT_IO 0xac000000 -++ -++#ifdef CONFIG_JZ4750_FUWA -++#define CIRRUS_DEFAULT_IRQ (32*4+20+48) -++#else -++#define CIRRUS_DEFAULT_IRQ (32*2 +6+48) -++#endif -++ -++ -++#endif -++ -++typedef struct { -++ struct net_device_stats stats; -++ u16 txlen; -++} cirrus_t; -++ -++static int ethaddr_cmd = 0; -++static unsigned char ethaddr_hex[6]; -++static struct net_device *dev; -++ -++/* -++ * I/O routines -++ */ -++static void gpio_init_cs8900(void) -++{ -++#ifdef CONFIG_SOC_JZ4740 -++ __gpio_as_func0(60); //CS4# -++ __gpio_as_func0(61); //RD# -++ __gpio_as_func0(62); //WR# -++ __gpio_as_irq_high_level(59); //irq -++ __gpio_disable_pull(59); //disable pull -++ REG_EMC_SMCR4 |= (1 << 6); //16bit -++#elif CONFIG_SOC_JZ4750 -++ __gpio_as_func0(32*2+23); //CS3# -++ __gpio_as_func0(32*2+25); //RD# -++ __gpio_as_func0(32*2+26); //WR# -++ -++#ifdef CONFIG_JZ4750_FUWA -++ __gpio_as_irq_high_level(32*4+20); //irq -++ __gpio_disable_pull(32*4+20); //disable pull -++#else -++ __gpio_as_irq_high_level(32*2 +6); //irq -++ __gpio_disable_pull(32*2 +6); //disable pull -++#endif -++ -++ REG_EMC_SMCR3 |= (1 << 6); //16bit -++#endif -++ udelay(1); -++} -++ -++static inline u16 cirrus_read (struct net_device *dev,u16 reg) -++{ -++ outw (reg,dev->base_addr + PP_Address); -++ return (inw (dev->base_addr + PP_Data)); -++} -++ -++static inline void cirrus_write (struct net_device *dev,u16 reg,u16 value) -++{ -++ outw (reg,dev->base_addr + PP_Address); -++ outw (value,dev->base_addr + PP_Data); -++} -++ -++static inline void cirrus_set (struct net_device *dev,u16 reg,u16 value) -++{ -++ cirrus_write (dev,reg,cirrus_read (dev,reg) | value); -++} -++ -++static inline void cirrus_clear (struct net_device *dev,u16 reg,u16 value) -++{ -++ cirrus_write (dev,reg,cirrus_read (dev,reg) & ~value); -++} -++ -++static inline void cirrus_frame_read (struct net_device *dev,struct sk_buff *skb,u16 length) -++{ -++ insw (dev->base_addr,skb_put (skb,length),(length + 1) / 2); -++} -++ -++static inline void cirrus_frame_write (struct net_device *dev,struct sk_buff *skb) -++{ -++ outsw (dev->base_addr,skb->data,(skb->len + 1) / 2); -++} -++ -++/* -++ * Debugging functions -++ */ -++ -++#ifdef DEBUG -++static inline int printable (int c) -++{ -++ return ((c >= 32 && c <= 126) || -++ (c >= 174 && c <= 223) || -++ (c >= 242 && c <= 243) || -++ (c >= 252 && c <= 253)); -++} -++ -++static void dump16 (struct net_device *dev,const u8 *s,size_t len) -++{ -++ int i; -++ char str[128]; -++ -++ if (!len) return; -++ -++ *str = '\0'; -++ -++ for (i = 0; i < len; i++) { -++ if (i && !(i % 4)) strcat (str," "); -++ sprintf (str,"%s%.2x ",str,s[i]); -++ } -++ -++ for ( ; i < 16; i++) { -++ if (i && !(i % 4)) strcat (str," "); -++ strcat (str," "); -++ } -++ -++ strcat (str," "); -++ for (i = 0; i < len; i++) sprintf (str,"%s%c",str,printable (s[i]) ? s[i] : '.'); -++ -++ printk (KERN_DEBUG "%s: %s\n",dev->name,str); -++} -++ -++static void hexdump (struct net_device *dev,const void *ptr,size_t size) -++{ -++ const u8 *s = (u8 *) ptr; -++ int i; -++ for (i = 0; i < size / 16; i++, s += 16) dump16 (dev,s,16); -++ dump16 (dev,s,size % 16); -++} -++ -++static void dump_packet (struct net_device *dev,struct sk_buff *skb,const char *type) -++{ -++ printk (KERN_INFO "%s: %s %d byte frame %.2x:%.2x:%.2x:%.2x:%.2x:%.2x to %.2x:%.2x:%.2x:%.2x:%.2x:%.2x type %.4x\n", -++ dev->name, -++ type, -++ skb->len, -++ skb->data[0],skb->data[1],skb->data[2],skb->data[3],skb->data[4],skb->data[5], -++ skb->data[6],skb->data[7],skb->data[8],skb->data[9],skb->data[10],skb->data[11], -++ (skb->data[12] << 8) | skb->data[13]); -++ if (skb->len < 0x100) hexdump (dev,skb->data,skb->len); -++} -++#endif /* #ifdef DEBUG */ -++ -++/* -++ * Driver functions -++ */ -++ -++static void cirrus_receive (struct net_device *dev) -++{ -++ cirrus_t *priv = (cirrus_t *) dev->priv; -++ struct sk_buff *skb; -++ u16 status,length; -++ -++ status = cirrus_read (dev,PP_RxStatus); -++ length = cirrus_read (dev,PP_RxLength); -++ -++ if (!(status & RxOK)) { -++ priv->stats.rx_errors++; -++ if ((status & (Runt | Extradata))) priv->stats.rx_length_errors++; -++ if ((status & CRCerror)) priv->stats.rx_crc_errors++; -++ return; -++ } -++ -++ if ((skb = dev_alloc_skb (length + 4)) == NULL) { -++ priv->stats.rx_dropped++; -++ return; -++ } -++ -++ skb->dev = dev; -++ skb_reserve (skb,2); -++ -++ cirrus_frame_read (dev,skb,length); -++ skb->protocol = eth_type_trans (skb,dev); -++ -++ netif_rx (skb); -++ dev->last_rx = jiffies; -++ -++ priv->stats.rx_packets++; -++ priv->stats.rx_bytes += length; -++} -++ -++static int cirrus_send_start (struct sk_buff *skb,struct net_device *dev) -++{ -++ cirrus_t *priv = (cirrus_t *) dev->priv; -++ u16 status; -++ -++ mdelay(10); -++ netif_stop_queue (dev); -++ -++ cirrus_write (dev,PP_TxCMD,TxStart (After5)); -++ cirrus_write (dev,PP_TxLength,skb->len); -++ -++ status = cirrus_read (dev,PP_BusST); -++ -++ if ((status & TxBidErr)) { -++ printk (KERN_WARNING "%s: Invalid frame size %d!\n",dev->name,skb->len); -++ priv->stats.tx_errors++; -++ priv->stats.tx_aborted_errors++; -++ priv->txlen = 0; -++ return (1); -++ } -++ -++ if (!(status & Rdy4TxNOW)) { -++ //printk (KERN_WARNING "%s: Transmit buffer not free!\n",dev->name); -++ priv->stats.tx_errors++; -++ priv->txlen = 0; -++ /* FIXME: store skb and send it in interrupt handler */ -++ return (1); -++ } -++ -++ cirrus_frame_write (dev,skb); -++ dev->trans_start = jiffies; -++ -++ dev_kfree_skb (skb); -++ -++ priv->txlen = skb->len; -++ -++ return (0); -++} -++ -++static irqreturn_t cirrus_interrupt(int irq, void *id) -++{ -++ struct net_device *dev = (struct net_device *) id; -++ cirrus_t *priv; -++ u16 status; -++ -++ if (dev->priv == NULL) { -++ return IRQ_NONE; -++ } -++ -++ priv = (cirrus_t *) dev->priv; -++ -++ while ((status = cirrus_read (dev,PP_ISQ))) { -++ switch (RegNum (status)) { -++ case RxEvent: -++ cirrus_receive (dev); -++ break; -++ -++ case TxEvent: -++ priv->stats.collisions += ColCount (cirrus_read (dev,PP_TxCOL)); -++ if (!(RegContent (status) & TxOK)) { -++ priv->stats.tx_errors++; -++ if ((RegContent (status) & Out_of_window)) priv->stats.tx_window_errors++; -++ if ((RegContent (status) & Jabber)) priv->stats.tx_aborted_errors++; -++ break; -++ } else if (priv->txlen) { -++ priv->stats.tx_packets++; -++ priv->stats.tx_bytes += priv->txlen; -++ } -++ priv->txlen = 0; -++ netif_wake_queue (dev); -++ break; -++ -++ case BufEvent: -++ if ((RegContent (status) & RxMiss)) { -++ u16 missed = MissCount (cirrus_read (dev,PP_RxMISS)); -++ priv->stats.rx_errors += missed; -++ priv->stats.rx_missed_errors += missed; -++ } -++ if ((RegContent (status) & TxUnderrun)) { -++ priv->stats.tx_errors++; -++ priv->stats.tx_fifo_errors++; -++ } -++ /* FIXME: if Rdy4Tx, transmit last sent packet (if any) */ -++ priv->txlen = 0; -++ netif_wake_queue (dev); -++ break; -++ -++ case TxCOL: -++ priv->stats.collisions += ColCount (cirrus_read (dev,PP_TxCOL)); -++ break; -++ -++ case RxMISS: -++ status = MissCount (cirrus_read (dev,PP_RxMISS)); -++ priv->stats.rx_errors += status; -++ priv->stats.rx_missed_errors += status; -++ break; -++ default: -++ return IRQ_HANDLED; -++ } -++ } -++ -++ return IRQ_HANDLED; -++} -++ -++static void cirrus_transmit_timeout (struct net_device *dev) -++{ -++ cirrus_t *priv = (cirrus_t *) dev->priv; -++ priv->stats.tx_errors++; -++ priv->stats.tx_heartbeat_errors++; -++ priv->txlen = 0; -++ netif_wake_queue (dev); -++} -++ -++static int cirrus_start (struct net_device *dev) -++{ -++ int result; -++ -++ /* valid ethernet address? */ -++ if (!is_valid_ether_addr(dev->dev_addr)) { -++ printk(KERN_ERR "%s: invalid ethernet MAC address\n",dev->name); -++ return (-EINVAL); -++ } -++ -++ /* install interrupt handler */ -++ if ((result = request_irq (dev->irq, &cirrus_interrupt, IRQF_DISABLED, dev->name, dev)) < 0) { -++ printk (KERN_ERR "%s: could not register interrupt %d\n",dev->name,dev->irq); -++ return (result); -++ } -++ -++ /* enable the ethernet controller */ -++ cirrus_set (dev,PP_RxCFG,RxOKiE | BufferCRC | CRCerroriE | RuntiE | ExtradataiE); -++ cirrus_set (dev,PP_RxCTL,RxOKA | IndividualA | BroadcastA); -++ cirrus_set (dev,PP_TxCFG,TxOKiE | Out_of_windowiE | JabberiE); -++ cirrus_set (dev,PP_BufCFG,Rdy4TxiE | RxMissiE | TxUnderruniE | TxColOvfiE | MissOvfloiE); -++ cirrus_set (dev,PP_LineCTL,SerRxON | SerTxON); -++ cirrus_set (dev,PP_BusCTL,EnableRQ); -++ -++#ifdef FULL_DUPLEX -++ cirrus_set (dev,PP_TestCTL,FDX); -++#endif /* #ifdef FULL_DUPLEX */ -++ -++ /* start the queue */ -++ netif_start_queue (dev); -++ __gpio_unmask_irq(59); -++ -++ //MOD_INC_USE_COUNT; -++ return (0); -++} -++ -++static int cirrus_stop (struct net_device *dev) -++{ -++ /* disable ethernet controller */ -++ cirrus_write (dev,PP_BusCTL,0); -++ cirrus_write (dev,PP_TestCTL,0); -++ cirrus_write (dev,PP_SelfCTL,0); -++ cirrus_write (dev,PP_LineCTL,0); -++ cirrus_write (dev,PP_BufCFG,0); -++ cirrus_write (dev,PP_TxCFG,0); -++ cirrus_write (dev,PP_RxCTL,0); -++ cirrus_write (dev,PP_RxCFG,0); -++ -++ /* uninstall interrupt handler */ -++ free_irq (dev->irq,dev); -++ -++ /* stop the queue */ -++ netif_stop_queue (dev); -++ -++ //MOD_DEC_USE_COUNT; -++ -++ return (0); -++} -++ -++static int cirrus_set_mac_address (struct net_device *dev, void *p) -++{ -++ struct sockaddr *addr = (struct sockaddr *)p; -++ int i; -++ -++ if (netif_running(dev)) -++ return -EBUSY; -++ -++ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); -++ -++ /* configure MAC address */ -++ for (i = 0; i < ETH_ALEN; i += 2) -++ cirrus_write (dev,PP_IA + i,dev->dev_addr[i] | (dev->dev_addr[i + 1] << 8)); -++ -++ return 0; -++} -++ -++static struct net_device_stats *cirrus_get_stats (struct net_device *dev) -++{ -++ cirrus_t *priv = (cirrus_t *) dev->priv; -++ return (&priv->stats); -++} -++ -++static void cirrus_set_receive_mode (struct net_device *dev) -++{ -++ if ((dev->flags & IFF_PROMISC)) -++ cirrus_set (dev,PP_RxCTL,PromiscuousA); -++ else -++ cirrus_clear (dev,PP_RxCTL,PromiscuousA); -++ -++ if ((dev->flags & IFF_ALLMULTI) && dev->mc_list) -++ cirrus_set (dev,PP_RxCTL,MulticastA); -++ else -++ cirrus_clear (dev,PP_RxCTL,MulticastA); -++} -++ -++/* -++ * Architecture dependant code -++ */ -++ -++/* -++ * Driver initialization routines -++ */ -++ -++int __init cirrus_probe(void) -++{ -++ static cirrus_t priv; -++ int i; -++ u16 value; -++ -++ printk ("Jz CS8900A driver for Linux (V0.02)\n"); -++ -++ /* Init hardware for PAVO board */ -++ gpio_init_cs8900(); -++ -++ /* Allocate ethernet device */ -++ dev = alloc_etherdev(sizeof(struct net_device)); -++ -++ memset (&priv,0,sizeof (cirrus_t)); -++ -++ ether_setup (dev); -++ -++ dev->open = cirrus_start; -++ dev->stop = cirrus_stop; -++ dev->hard_start_xmit = cirrus_send_start; -++ dev->get_stats = cirrus_get_stats; -++ dev->set_multicast_list = cirrus_set_receive_mode; -++ dev->set_mac_address = cirrus_set_mac_address; -++ dev->tx_timeout = cirrus_transmit_timeout; -++ dev->watchdog_timeo = HZ; -++ -++ if (ethaddr_cmd==1) -++ { -++ dev->dev_addr[0] = ethaddr_hex[0]; -++ dev->dev_addr[1] = ethaddr_hex[1]; -++ dev->dev_addr[2] = ethaddr_hex[2]; -++ dev->dev_addr[3] = ethaddr_hex[3]; -++ dev->dev_addr[4] = ethaddr_hex[4]; -++ dev->dev_addr[5] = ethaddr_hex[5]; -++ } -++ else //default mac address 00:2a:cc:2a:af:fe -++ { -++ dev->dev_addr[0] = 0x00; -++ dev->dev_addr[1] = 0x62; -++ dev->dev_addr[2] = 0x9c; -++ dev->dev_addr[3] = 0x61; -++ dev->dev_addr[4] = 0xcf; -++ dev->dev_addr[5] = 0x16; -++ } -++ dev->if_port = IF_PORT_10BASET; -++ dev->priv = (void *) &priv; -++ -++ dev->base_addr = CIRRUS_DEFAULT_IO; -++ dev->irq = CIRRUS_DEFAULT_IRQ; -++ -++ -++ /* module parameters override everything */ -++ if (!dev->base_addr) { -++ printk (KERN_ERR -++ "%s: No default I/O base address defined. Use io=... or\n" -++ "%s: define CIRRUS_DEFAULT_IO for your platform\n", -++ dev->name,dev->name); -++ return (-EINVAL); -++ } -++ -++ if (!dev->irq) { -++ printk (KERN_ERR -++ "%s: No default IRQ number defined. Use irq=... or\n" -++ "%s: define CIRRUS_DEFAULT_IRQ for your platform\n", -++ dev->name,dev->name); -++ return (-EINVAL); -++ } -++#if 0 -++ if ((result = check_region (dev->base_addr,16))) { -++ printk (KERN_ERR "%s: can't get I/O port address 0x%lx\n",dev->name,dev->base_addr); -++ return (result); -++ } -++#endif -++ if (!request_region (dev->base_addr,16,dev->name)) -++ return -EBUSY; -++#if 0 -++ /* verify EISA registration number for Cirrus Logic */ -++ if ((value = cirrus_read (dev,PP_ProductID)) != EISA_REG_CODE) { -++ printk (KERN_ERR "%s: incorrect signature 0x%.4x\n",dev->name,value); -++ return (-ENXIO); -++ } -++#endif -++ -++ /* verify chip version */ -++ value = cirrus_read (dev,PP_ProductID + 2); -++ if (VERSION (value) != CS8900A) { -++ printk (KERN_ERR "%s: unknown chip version 0x%.8x\n",dev->name,VERSION (value)); -++ return (-ENXIO); -++ } -++ printk (KERN_INFO "%s: CS8900A rev %c detected\n",dev->name,'B' + REVISION (value) - REV_B); -++ -++ /* setup interrupt number */ -++ cirrus_write (dev,PP_IntNum,INT_PIN); -++ -++ /* configure MAC address */ -++ for (i = 0; i < ETH_ALEN; i += 2) -++ { -++ //printk(" %x",dev->dev_addr[i] | (dev->dev_addr[i + 1] << 8)); -++ cirrus_write (dev,PP_IA + i,dev->dev_addr[i] | (dev->dev_addr[i + 1] << 8)); -++ } -++ -++ if (register_netdev(dev) != 0) { -++ printk(KERN_ERR " Cannot register net device\n"); -++ free_netdev(dev); -++ return -ENOMEM; -++ } -++ -++ return (0); -++} -++ -++static inline unsigned char str2hexnum(unsigned char c) -++{ -++ if(c >= '0' && c <= '9') -++ return c - '0'; -++ if(c >= 'a' && c <= 'f') -++ return c - 'a' + 10; -++ if(c >= 'A' && c <= 'F') -++ return c - 'A' + 10; -++ return 0; /* foo */ -++} -++ -++static inline void str2eaddr(unsigned char *ea, unsigned char *str) -++{ -++ int i; -++ -++ for(i = 0; i < 6; i++) { -++ unsigned char num; -++ -++ if((*str == '.') || (*str == ':')) -++ str++; -++ num = str2hexnum(*str++) << 4; -++ num |= (str2hexnum(*str++)); -++ ea[i] = num; -++ } -++} -++ -++static int __init ethernet_addr_setup(char *str) -++{ -++ if (!str) { -++ printk("ethaddr not set in command line\n"); -++ return -1; -++ } -++ ethaddr_cmd = 1; -++ str2eaddr(ethaddr_hex, str); -++ return 0; -++} -++ -++__setup("ethaddr=", ethernet_addr_setup); -++ -++//EXPORT_NO_SYMBOLS; -++ -++MODULE_AUTHOR ("Lucifer "); -++MODULE_DESCRIPTION ("Jz CS8900A driver for Linux (V0.02)"); -++MODULE_LICENSE ("GPL"); -++ -++//#ifdef MODULE -++ -++ -++#if 0 -++static int io = 0; -++static int irq = 0; -++ -++module_param(io, int, 0); -++MODULE_PARM_DESC (io,"I/O Base Address"); -++//MODULE_PARM (io,"i"); -++ -++module_param(irq, int, 0); -++MODULE_PARM_DESC (irq,"IRQ Number"); -++//MODULE_PARM (irq,"i"); -++#endif -++ -++static int __init jzcs8900_init(void) -++{ -++ if (cirrus_probe()) { -++ printk(KERN_WARNING "jzcs8900: No cs8900a found\n"); -++ } -++ -++ return 0; -++} -++ -++static void __exit jzcs8900_exit(void) -++{ -++ release_region(dev->base_addr,16); -++ unregister_netdev(dev); -++ free_netdev(dev); -++} -++ -++module_init(jzcs8900_init); -++module_exit(jzcs8900_exit); -+diff -urN linux-2.6.24.7.old/drivers/net/jzcs8900a.h linux-2.6.24.7/drivers/net/jzcs8900a.h -+--- linux-2.6.24.7.old/drivers/net/jzcs8900a.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/net/jzcs8900a.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,235 @@ -++#ifndef JZCS8900A_H -++#define JZCS8900A_H -++ -++/* -++ * linux/drivers/net/jzcs8900a.h -++ * -++ * Author: Lucifer -++ * -++ * A Cirrus Logic CS8900A driver for Linux -++ * based on the cs89x0 driver written by Russell Nelson, -++ * Donald Becker, and others. -++ * -++ * This source code is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU General Public License -++ * version 2 as published by the Free Software Foundation. -++ */ -++ -++/* -++ * Ports -++ */ -++ -++#define PP_Address 0x0a /* PacketPage Pointer Port (Section 4.10.10) */ -++#define PP_Data 0x0c /* PacketPage Data Port (Section 4.10.10) */ -++ -++/* -++ * Registers -++ */ -++ -++#define PP_ProductID 0x0000 /* Section 4.3.1 Product Identification Code */ -++#define PP_MemBase 0x002c /* Section 4.9.2 Memory Base Address Register */ -++#define PP_IntNum 0x0022 /* Section 3.2.3 Interrupt Number */ -++#define PP_EEPROMCommand 0x0040 /* Section 4.3.11 EEPROM Command */ -++#define PP_EEPROMData 0x0042 /* Section 4.3.12 EEPROM Data */ -++#define PP_RxCFG 0x0102 /* Section 4.4.6 Receiver Configuration */ -++#define PP_RxCTL 0x0104 /* Section 4.4.8 Receiver Control */ -++#define PP_TxCFG 0x0106 /* Section 4.4.9 Transmit Configuration */ -++#define PP_BufCFG 0x010a /* Section 4.4.12 Buffer Configuration */ -++#define PP_LineCTL 0x0112 /* Section 4.4.16 Line Control */ -++#define PP_SelfCTL 0x0114 /* Section 4.4.18 Self Control */ -++#define PP_BusCTL 0x0116 /* Section 4.4.20 Bus Control */ -++#define PP_TestCTL 0x0118 /* Section 4.4.22 Test Control */ -++#define PP_ISQ 0x0120 /* Section 4.4.5 Interrupt Status Queue */ -++#define PP_TxEvent 0x0128 /* Section 4.4.10 Transmitter Event */ -++#define PP_BufEvent 0x012c /* Section 4.4.13 Buffer Event */ -++#define PP_RxMISS 0x0130 /* Section 4.4.14 Receiver Miss Counter */ -++#define PP_TxCOL 0x0132 /* Section 4.4.15 Transmit Collision Counter */ -++#define PP_SelfST 0x0136 /* Section 4.4.19 Self Status */ -++#define PP_BusST 0x0138 /* Section 4.4.21 Bus Status */ -++#define PP_TxCMD 0x0144 /* Section 4.4.11 Transmit Command */ -++#define PP_TxLength 0x0146 /* Section 4.5.2 Transmit Length */ -++#define PP_IA 0x0158 /* Section 4.6.2 Individual Address (IEEE Address) */ -++#define PP_RxStatus 0x0400 /* Section 4.7.1 Receive Status */ -++#define PP_RxLength 0x0402 /* Section 4.7.1 Receive Length (in bytes) */ -++#define PP_RxFrame 0x0404 /* Section 4.7.2 Receive Frame Location */ -++#define PP_TxFrame 0x0a00 /* Section 4.7.2 Transmit Frame Location */ -++ -++/* -++ * Values -++ */ -++ -++/* PP_IntNum */ -++#define INTRQ0 0x0000 -++#define INTRQ1 0x0001 -++#define INTRQ2 0x0002 -++#define INTRQ3 0x0003 -++ -++/* PP_ProductID */ -++#define EISA_REG_CODE 0x630e -++#define REVISION(x) (((x) & 0x1f00) >> 8) -++#define VERSION(x) ((x) & ~0x1f00) -++ -++#define CS8900A 0x0000 -++#define REV_B 7 -++#define REV_C 8 -++#define REV_D 9 -++ -++/* PP_RxCFG */ -++#define Skip_1 0x0040 -++#define StreamE 0x0080 -++#define RxOKiE 0x0100 -++#define RxDMAonly 0x0200 -++#define AutoRxDMAE 0x0400 -++#define BufferCRC 0x0800 -++#define CRCerroriE 0x1000 -++#define RuntiE 0x2000 -++#define ExtradataiE 0x4000 -++ -++/* PP_RxCTL */ -++#define IAHashA 0x0040 -++#define PromiscuousA 0x0080 -++#define RxOKA 0x0100 -++#define MulticastA 0x0200 -++#define IndividualA 0x0400 -++#define BroadcastA 0x0800 -++#define CRCerrorA 0x1000 -++#define RuntA 0x2000 -++#define ExtradataA 0x4000 -++ -++/* PP_TxCFG */ -++#define Loss_of_CRSiE 0x0040 -++#define SQErroriE 0x0080 -++#define TxOKiE 0x0100 -++#define Out_of_windowiE 0x0200 -++#define JabberiE 0x0400 -++#define AnycolliE 0x0800 -++#define T16colliE 0x8000 -++ -++/* PP_BufCFG */ -++#define SWint_X 0x0040 -++#define RxDMAiE 0x0080 -++#define Rdy4TxiE 0x0100 -++#define TxUnderruniE 0x0200 -++#define RxMissiE 0x0400 -++#define Rx128iE 0x0800 -++#define TxColOvfiE 0x1000 -++#define MissOvfloiE 0x2000 -++#define RxDestiE 0x8000 -++ -++/* PP_LineCTL */ -++#define SerRxON 0x0040 -++#define SerTxON 0x0080 -++#define AUIonly 0x0100 -++#define AutoAUI_10BT 0x0200 -++#define ModBackoffE 0x0800 -++#define PolarityDis 0x1000 -++#define L2_partDefDis 0x2000 -++#define LoRxSquelch 0x4000 -++ -++/* PP_SelfCTL */ -++#define RESET 0x0040 -++#define SWSuspend 0x0100 -++#define HWSleepE 0x0200 -++#define HWStandbyE 0x0400 -++#define HC0E 0x1000 -++#define HC1E 0x2000 -++#define HCB0 0x4000 -++#define HCB1 0x8000 -++ -++/* PP_BusCTL */ -++#define ResetRxDMA 0x0040 -++#define DMAextend 0x0100 -++#define UseSA 0x0200 -++#define MemoryE 0x0400 -++#define DMABurst 0x0800 -++#define IOCHRDYE 0x1000 -++#define RxDMAsize 0x2000 -++#define EnableRQ 0x8000 -++ -++/* PP_TestCTL */ -++#define DisableLT 0x0080 -++#define ENDECloop 0x0200 -++#define AUIloop 0x0400 -++#define DisableBackoff 0x0800 -++#define FDX 0x4000 -++ -++/* PP_ISQ */ -++#define RegNum(x) ((x) & 0x3f) -++#define RegContent(x) ((x) & ~0x3d) -++ -++#define RxEvent 0x0004 -++#define TxEvent 0x0008 -++#define BufEvent 0x000c -++#define RxMISS 0x0010 -++#define TxCOL 0x0012 -++ -++/* PP_RxStatus */ -++#define IAHash 0x0040 -++#define Dribblebits 0x0080 -++#define RxOK 0x0100 -++#define Hashed 0x0200 -++#define IndividualAdr 0x0400 -++#define Broadcast 0x0800 -++#define CRCerror 0x1000 -++#define Runt 0x2000 -++#define Extradata 0x4000 -++ -++#define HashTableIndex(x) ((x) >> 0xa) -++ -++/* PP_TxCMD */ -++#define After5 0 -++#define After381 1 -++#define After1021 2 -++#define AfterAll 3 -++#define TxStart(x) ((x) << 6) -++ -++#define Force 0x0100 -++#define Onecoll 0x0200 -++#define InhibitCRC 0x1000 -++#define TxPadDis 0x2000 -++ -++/* PP_BusST */ -++#define TxBidErr 0x0080 -++#define Rdy4TxNOW 0x0100 -++ -++/* PP_TxEvent */ -++#define Loss_of_CRS 0x0040 -++#define SQEerror 0x0080 -++#define TxOK 0x0100 -++#define Out_of_window 0x0200 -++#define Jabber 0x0400 -++#define T16coll 0x8000 -++ -++#define TX_collisions(x) (((x) >> 0xb) & ~0x8000) -++ -++/* PP_BufEvent */ -++#define SWint 0x0040 -++#define RxDMAFrame 0x0080 -++#define Rdy4Tx 0x0100 -++#define TxUnderrun 0x0200 -++#define RxMiss 0x0400 -++#define Rx128 0x0800 -++#define RxDest 0x8000 -++ -++/* PP_RxMISS */ -++#define MissCount(x) ((x) >> 6) -++ -++/* PP_TxCOL */ -++#define ColCount(x) ((x) >> 6) -++ -++/* PP_SelfST */ -++#define T3VActive 0x0040 -++#define INITD 0x0080 -++#define SIBUSY 0x0100 -++#define EEPROMpresent 0x0200 -++#define EEPROMOK 0x0400 -++#define ELpresent 0x0800 -++#define EEsize 0x1000 -++ -++/* PP_EEPROMCommand */ -++#define EEWriteRegister 0x0100 -++#define EEReadRegister 0x0200 -++#define EEEraseRegister 0x0300 -++#define ELSEL 0x0400 -++ -++#endif /* #ifndef CIRRUS_H */ -+diff -urN linux-2.6.24.7.old/drivers/pnp/Kconfig linux-2.6.24.7/drivers/pnp/Kconfig -+--- linux-2.6.24.7.old/drivers/pnp/Kconfig 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/pnp/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -5,7 +5,7 @@ -+ menuconfig PNP -+ bool "Plug and Play support" -+ depends on HAS_IOMEM -+- depends on ISA || ACPI -++# depends on ISA || ACPI -+ ---help--- -+ Plug and Play (PnP) is a standard for peripherals which allows those -+ peripherals to be configured by software, e.g. assign IRQ's or other -+diff -urN linux-2.6.24.7.old/drivers/pnp/core.c linux-2.6.24.7/drivers/pnp/core.c -+--- linux-2.6.24.7.old/drivers/pnp/core.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/pnp/core.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -74,6 +74,8 @@ -+ return device_register(&protocol->dev); -+ } -+ -++EXPORT_SYMBOL(pnp_register_protocol); -++ -+ /** -+ * pnp_protocol_unregister - removes a pnp protocol from the pnp layer -+ * @protocol: pointer to the corresponding pnp_protocol structure -+@@ -86,6 +88,8 @@ -+ device_unregister(&protocol->dev); -+ } -+ -++EXPORT_SYMBOL(pnp_unregister_protocol); -++ -+ static void pnp_free_ids(struct pnp_dev *dev) -+ { -+ struct pnp_id *id; -+@@ -166,6 +170,8 @@ -+ return 0; -+ } -+ -++EXPORT_SYMBOL(pnp_add_device); -++ -+ void __pnp_remove_device(struct pnp_dev *dev) -+ { -+ spin_lock(&pnp_lock); -+@@ -175,6 +181,21 @@ -+ device_unregister(&dev->dev); -+ } -+ -++/** -++ * pnp_remove_device - removes a pnp device from the pnp layer -++ * @dev: pointer to dev to add -++ * -++ * this function will free all mem used by dev -++ */ -++void pnp_remove_device(struct pnp_dev *dev) -++{ -++ if (!dev || dev->card) -++ return; -++ __pnp_remove_device(dev); -++} -++ -++EXPORT_SYMBOL(pnp_remove_device); -++ -+ static int __init pnp_init(void) -+ { -+ printk(KERN_INFO "Linux Plug and Play Support v0.97 (c) Adam Belay\n"); -+diff -urN linux-2.6.24.7.old/drivers/pnp/driver.c linux-2.6.24.7/drivers/pnp/driver.c -+--- linux-2.6.24.7.old/drivers/pnp/driver.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/pnp/driver.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -246,3 +246,4 @@ -+ EXPORT_SYMBOL(pnp_unregister_driver); -+ EXPORT_SYMBOL(pnp_device_attach); -+ EXPORT_SYMBOL(pnp_device_detach); -++EXPORT_SYMBOL(pnp_add_id); -+diff -urN linux-2.6.24.7.old/drivers/pnp/resource.c linux-2.6.24.7/drivers/pnp/resource.c -+--- linux-2.6.24.7.old/drivers/pnp/resource.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/pnp/resource.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -404,6 +404,10 @@ -+ -+ int pnp_check_dma(struct pnp_dev *dev, int idx) -+ { -++ printk("*********** %s, %s, line[%d]: Fix me, this should update in the future *********\n", -++ __FILE__, __FUNCTION__, __LINE__); -++ return 0; /* should be update in the future. Wolfgang ???*/ -++ -+ #ifndef CONFIG_IA64 -+ int tmp; -+ struct pnp_dev *tdev; -+diff -urN linux-2.6.24.7.old/drivers/serial/8250.c linux-2.6.24.7/drivers/serial/8250.c -+--- linux-2.6.24.7.old/drivers/serial/8250.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/serial/8250.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -12,7 +12,7 @@ -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+- * $Id: 8250.c,v 1.90 2002/07/28 10:03:27 rmk Exp $ -++ * $Id: 8250.c,v 1.5 2008-07-14 06:40:28 lhhuang Exp $ -+ * -+ * A note about mapbase / membase -+ * -+@@ -181,7 +181,7 @@ -+ [PORT_16550A] = { -+ .name = "16550A", -+ .fifo_size = 16, -+- .tx_loadsz = 16, -++ .tx_loadsz = 8, -+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, -+ .flags = UART_CAP_FIFO, -+ }, -+@@ -400,6 +400,10 @@ -+ break; -+ -+ case UPIO_MEM: -++#if defined(CONFIG_JZSOC) -++ if (offset == (UART_FCR << up->port.regshift)) -++ value |= 0x10; /* set FCR.UUE */ -++#endif -+ writeb(value, up->port.membase + offset); -+ break; -+ -+@@ -1981,6 +1985,83 @@ -+ serial_unlink_irq_chain(up); -+ } -+ -++#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) -++static unsigned short quot1[3] = {0}; /* quot[0]:baud_div, quot[1]:umr, quot[2]:uacr */ -++static unsigned short * serial8250_get_divisor(struct uart_port *port, unsigned int baud) -++{ -++ int err, sum, i, j; -++ int a[12], b[12]; -++ unsigned short div, umr, uacr; -++ unsigned short umr_best, div_best, uacr_best; -++ long long t0, t1, t2, t3; -++ -++ sum = 0; -++ umr_best = div_best = uacr_best = 0; -++ div = 1; -++ -++ if ((port->uartclk % (16 * baud)) == 0) { -++ quot1[0] = port->uartclk / (16 * baud); -++ quot1[1] = 16; -++ quot1[2] = 0; -++ return quot1; -++ } -++ -++ while (1) { -++ umr = port->uartclk / (baud * div); -++ if (umr > 32) { -++ div++; -++ continue; -++ } -++ if (umr < 4) { -++ break; -++ } -++ for (i = 0; i < 12; i++) { -++ a[i] = umr; -++ b[i] = 0; -++ sum = 0; -++ for (j = 0; j <= i; j++) { -++ sum += a[j]; -++ } -++ -++ /* the precision could be 1/2^(36) due to the value of t0 */ -++ t0 = 0x1000000000LL; -++ t1 = (i + 1) * t0; -++ t2 = (sum * div) * t0; -++ t3 = div * t0; -++ do_div(t1, baud); -++ do_div(t2, port->uartclk); -++ do_div(t3, (2 * port->uartclk)); -++ err = t1 - t2 - t3; -++ -++ if (err > 0) { -++ a[i] += 1; -++ b[i] = 1; -++ } -++ } -++ -++ uacr = 0; -++ for (i = 0; i < 12; i++) { -++ if (b[i] == 1) { -++ uacr |= 1 << i; -++ } -++ } -++ -++ /* the best value of umr should be near 16, and the value of uacr should better be smaller */ -++ if (abs(umr - 16) < abs(umr_best - 16) || (abs(umr - 16) == abs(umr_best - 16) && uacr_best > uacr)) { -++ div_best = div; -++ umr_best = umr; -++ uacr_best = uacr; -++ } -++ div++; -++ } -++ -++ quot1[0] = div_best; -++ quot1[1] = umr_best; -++ quot1[2] = uacr_best; -++ -++ return quot1; -++} -++#else -+ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud) -+ { -+ unsigned int quot; -+@@ -2000,6 +2081,7 @@ -+ -+ return quot; -+ } -++#endif -+ -+ static void -+ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, -+@@ -2009,6 +2091,9 @@ -+ unsigned char cval, fcr = 0; -+ unsigned long flags; -+ unsigned int baud, quot; -++#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) -++ unsigned short *quot1; -++#endif -+ -+ switch (termios->c_cflag & CSIZE) { -+ case CS5: -+@@ -2041,7 +2126,12 @@ -+ * Ask the core to calculate the divisor for us. -+ */ -+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); -++#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) -++ quot1 = serial8250_get_divisor(port, baud); -++ quot = quot1[0]; /* not usefull, just let gcc happy */ -++#else -+ quot = serial8250_get_divisor(port, baud); -++#endif -+ -+ /* -+ * Oxford Semi 952 rev B workaround -+@@ -2119,6 +2209,10 @@ -+ if (up->capabilities & UART_CAP_UUE) -+ up->ier |= UART_IER_UUE | UART_IER_RTOIE; -+ -++#ifdef CONFIG_JZSOC -++ up->ier |= UART_IER_RTOIE; /* Set this flag, or very slow */ -++#endif -++ -+ serial_out(up, UART_IER, up->ier); -+ -+ if (up->capabilities & UART_CAP_EFR) { -+@@ -2153,7 +2247,15 @@ -+ serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ -+ } -+ -++#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) -++#define UART_UMR 9 -++#define UART_UACR 10 -++ serial_dl_write(up, quot1[0]); -++ serial_outp(up, UART_UMR, quot1[1]); -++ serial_outp(up, UART_UACR, quot1[2]); -++#else -+ serial_dl_write(up, quot); -++#endif -+ -+ /* -+ * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR -+@@ -2866,7 +2968,7 @@ -+ if (nr_uarts > UART_NR) -+ nr_uarts = UART_NR; -+ -+- printk(KERN_INFO "Serial: 8250/16550 driver $Revision: 1.90 $ " -++ printk(KERN_INFO "Serial: 8250/16550 driver $Revision: 1.5 $ " -+ "%d ports, IRQ sharing %sabled\n", nr_uarts, -+ share_irqs ? "en" : "dis"); -+ -+@@ -2927,7 +3029,7 @@ -+ EXPORT_SYMBOL(serial8250_resume_port); -+ -+ MODULE_LICENSE("GPL"); -+-MODULE_DESCRIPTION("Generic 8250/16x50 serial driver $Revision: 1.90 $"); -++MODULE_DESCRIPTION("Generic 8250/16x50 serial driver $Revision: 1.5 $"); -+ -+ module_param(share_irqs, uint, 0644); -+ MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices" -+diff -urN linux-2.6.24.7.old/drivers/usb/Kconfig linux-2.6.24.7/drivers/usb/Kconfig -+--- linux-2.6.24.7.old/drivers/usb/Kconfig 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/usb/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -41,6 +41,7 @@ -+ default y if PPC_MPC52xx -+ # MIPS: -+ default y if SOC_AU1X00 -++ default y if JZSOC -+ # more: -+ default PCI -+ -+diff -urN linux-2.6.24.7.old/drivers/usb/core/hub.c linux-2.6.24.7/drivers/usb/core/hub.c -+--- linux-2.6.24.7.old/drivers/usb/core/hub.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/usb/core/hub.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -2484,11 +2484,35 @@ -+ struct device *hub_dev = hub->intfdev; -+ u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); -+ int status, i; -+- -++#ifdef CONFIG_JZSOC -++ static char jzhub = 1; /* the hub first to be initialized is jzsoc on-chip hub */ -++#endif -++ -+ dev_dbg (hub_dev, -+ "port %d, status %04x, change %04x, %s\n", -+ port1, portstatus, portchange, portspeed (portstatus)); -+ -++#ifdef CONFIG_SOC_JZ4730 -++ /* -++ * On Jz4730, we assume that the first USB port was used as device. -++ * If not, please comment next lines. -++ */ -++ if ((port1 == 1) && (jzhub)) { -++ jzhub = 0; -++ return; -++ } -++#endif -++ -++#if defined(CONFIG_SOC_JZ4740) || defined(CONFIG_SOC_JZ4750) -++ /* -++ * On Jz4740 and Jz4750, the second USB port was used as device. -++ */ -++ if ((port1 == 2) && (jzhub)) { -++ jzhub = 0; -++ return; -++ } -++#endif -++ -+ if (hub->has_indicators) { -+ set_port_led(hub, port1, HUB_LED_AUTO); -+ hub->indicator[port1-1] = INDICATOR_AUTO; -+diff -urN linux-2.6.24.7.old/drivers/usb/gadget/Kconfig linux-2.6.24.7/drivers/usb/gadget/Kconfig -+--- linux-2.6.24.7.old/drivers/usb/gadget/Kconfig 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/usb/gadget/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -93,6 +93,47 @@ -+ Many controller drivers are platform-specific; these -+ often need board-specific hooks. -+ -++config USB_GADGET_JZ4740 -++ boolean "JZ4740 UDC" -++ depends on SOC_JZ4740 -++ select USB_GADGET_DUALSPEED -++ help -++ Select this to support the Ingenic JZ4740 processor -++ high speed USB device controller. -++ -++config USB_JZ4740 -++ tristate -++ depends on USB_GADGET_JZ4740 -++ default USB_GADGET -++ select USB_GADGET_SELECTED -++ -++config USB_GADGET_JZ4750 -++ boolean "JZ4750 UDC" -++ depends on SOC_JZ4750 -++ select USB_GADGET_DUALSPEED -++ help -++ Select this to support the Ingenic JZ4750 processor -++ high speed USB device controller. -++ -++config USB_JZ4750 -++ tristate -++ depends on USB_GADGET_JZ4750 -++ default USB_GADGET -++ select USB_GADGET_SELECTED -++ -++config USB_GADGET_JZ4730 -++ boolean "JZ4730 UDC" -++ depends on SOC_JZ4730 -++ help -++ Select this to support the Ingenic JZ4730 processor -++ full speed USB device controller. -++ -++config USB_JZ4730 -++ tristate -++ depends on USB_GADGET_JZ4730 -++ default USB_GADGET -++ select USB_GADGET_SELECTED -++ -+ config USB_GADGET_AMD5536UDC -+ boolean "AMD5536 UDC" -+ depends on PCI -+@@ -509,6 +550,14 @@ -+ behavior of USB Mass Storage hosts. Not needed for -+ normal operation. -+ -++config UDC_USE_LB_CACHE -++ bool "enable lb cache" -++ depends on USB_FILE_STORAGE && (SOC_JZ4740 || SOC_JZ4750) -++ default y -++ help -++ say "y" to enable lb cache and UDC work in faster speed. -++ say "n" to disable lb cache and UDC work in normal speed. -++ -+ config USB_G_SERIAL -+ tristate "Serial Gadget (with CDC ACM support)" -+ help -+diff -urN linux-2.6.24.7.old/drivers/usb/gadget/Makefile linux-2.6.24.7/drivers/usb/gadget/Makefile -+--- linux-2.6.24.7.old/drivers/usb/gadget/Makefile 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/usb/gadget/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -17,6 +17,9 @@ -+ obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o -+ obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o -+ obj-$(CONFIG_USB_M66592) += m66592-udc.o -++obj-$(CONFIG_USB_JZ4740) += jz4740_udc.o -++obj-$(CONFIG_USB_JZ4730) += jz4730_udc.o -++obj-$(CONFIG_USB_JZ4750) += jz4740_udc.o -+ -+ # -+ # USB gadget drivers -+diff -urN linux-2.6.24.7.old/drivers/usb/gadget/file_storage.c linux-2.6.24.7/drivers/usb/gadget/file_storage.c -+--- linux-2.6.24.7.old/drivers/usb/gadget/file_storage.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/usb/gadget/file_storage.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -274,6 +274,18 @@ -+ -+ -+ /*-------------------------------------------------------------------------*/ -++#if defined(CONFIG_UDC_USE_LB_CACHE) -++#define GHOST -++#endif -++ -++#ifdef GHOST -++extern unsigned long udc_read(unsigned int offset, unsigned int len, unsigned char *); -++extern unsigned long udc_write(unsigned int offset, unsigned int len, unsigned char *); -++extern int NAND_LB_Init(void); -++extern int NAND_LB_FLASHCACHE(void); -++extern int NAND_MTD_FLASHCACHE(void); -++extern int FlushDataState; -++#endif -+ -+ #ifdef DEBUG -+ #define LDBG(lun,fmt,args...) \ -+@@ -349,8 +361,8 @@ -+ } mod_data = { // Default values -+ .transport_parm = "BBB", -+ .protocol_parm = "SCSI", -+- .removable = 0, -+- .can_stall = 1, -++ .removable = 1, -++ .can_stall = 0, -+ .vendor = DRIVER_VENDOR_ID, -+ .product = DRIVER_PRODUCT_ID, -+ .release = 0xffff, // Use controller chip type -+@@ -810,6 +822,7 @@ -+ #define STRING_SERIAL 3 -+ #define STRING_CONFIG 4 -+ #define STRING_INTERFACE 5 -++#define STRING_MS_OS 0xee -+ -+ /* There is only one configuration. */ -+ #define CONFIG_VALUE 1 -+@@ -997,6 +1010,7 @@ -+ {STRING_SERIAL, serial}, -+ {STRING_CONFIG, "Self-powered"}, -+ {STRING_INTERFACE, "Mass Storage"}, -++ {STRING_MS_OS, "Microsoft"}, -+ {} -+ }; -+ -+@@ -1618,9 +1632,14 @@ -+ -+ /* Perform the read */ -+ file_offset_tmp = file_offset; -++#ifdef GHOST -++ nread = udc_read(file_offset_tmp, amount, bh->buf); -++#else -+ nread = vfs_read(curlun->filp, -+ (char __user *) bh->buf, -+ amount, &file_offset_tmp); -++#endif -++ -+ VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, -+ (unsigned long long) file_offset, -+ (int) nread); -+@@ -1799,9 +1818,13 @@ -+ -+ /* Perform the write */ -+ file_offset_tmp = file_offset; -++#ifdef GHOST -++ nwritten = udc_write(file_offset_tmp, amount, bh->buf); -++#else -+ nwritten = vfs_write(curlun->filp, -+ (char __user *) bh->buf, -+ amount, &file_offset_tmp); -++#endif -+ VLDBG(curlun, "file write %u @ %llu -> %d\n", amount, -+ (unsigned long long) file_offset, -+ (int) nwritten); -+@@ -1976,9 +1999,19 @@ -+ -+ /* Perform the read */ -+ file_offset_tmp = file_offset; -++#ifdef GHOST -++ nread = udc_read(file_offset_tmp, amount, bh->buf); -++#else -+ nread = vfs_read(curlun->filp, -+ (char __user *) bh->buf, -+ amount, &file_offset_tmp); -++#endif -++ -++#if 0 -++ nread = vfs_read(curlun->filp, -++ (char __user *) bh->buf, -++ amount, &file_offset_tmp); -++#endif -+ VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, -+ (unsigned long long) file_offset, -+ (int) nread); -+@@ -2013,7 +2046,7 @@ -+ { -+ u8 *buf = (u8 *) bh->buf; -+ -+- static char vendor_id[] = "Linux "; -++ static char vendor_id[] = "Ingenic "; -+ static char product_id[] = "File-Stor Gadget"; -+ -+ if (!fsg->curlun) { // Unsupported LUNs are okay -+@@ -2857,6 +2890,15 @@ -+ reply = check_command(fsg, 6, DATA_DIR_NONE, -+ 0, 1, -+ "TEST UNIT READY"); -++#ifdef GHOST -++ if( FlushDataState >= 1) -++ FlushDataState++; -++ if(FlushDataState > 6) -++ { -++ NAND_LB_FLASHCACHE(); -++ FlushDataState = 0; -++ } -++#endif -+ break; -+ -+ /* Although optional, this command is used by MS-Windows. We -+@@ -3404,6 +3446,13 @@ -+ -+ /* The main loop */ -+ while (fsg->state != FSG_STATE_TERMINATED) { -++#ifdef GHOST -++ if ((fsg->atomic_bitflags & SUSPENDED)) -++ { -++ NAND_LB_FLASHCACHE(); -++ NAND_MTD_FLASHCACHE(); -++ } -++#endif -+ if (exception_in_progress(fsg) || signal_pending(current)) { -+ handle_exception(fsg); -+ continue; -+@@ -3525,6 +3574,9 @@ -+ curlun->num_sectors = num_sectors; -+ LDBG(curlun, "open backing file: %s\n", filename); -+ rc = 0; -++#ifdef GHOST -++ NAND_LB_Init(); -++#endif -+ -+ out: -+ filp_close(filp, current->files); -+diff -urN linux-2.6.24.7.old/drivers/usb/gadget/gadget_chips.h linux-2.6.24.7/drivers/usb/gadget/gadget_chips.h -+--- linux-2.6.24.7.old/drivers/usb/gadget/gadget_chips.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/usb/gadget/gadget_chips.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -11,6 +11,18 @@ -+ * Some are available on 2.4 kernels; several are available, but not -+ * yet pushed in the 2.6 mainline tree. -+ */ -++#ifdef CONFIG_USB_GADGET_JZ4740 -++#define gadget_is_jz4740(g) !strcmp("jz4740_udc", (g)->name) -++#else -++#define gadget_is_jz4740(g) 0 -++#endif -++ -++#ifdef CONFIG_USB_GADGET_JZ4730 -++#define gadget_is_jz4730(g) !strcmp("jz4730_udc", (g)->name) -++#else -++#define gadget_is_jz4730(g) 0 -++#endif -++ -+ #ifdef CONFIG_USB_GADGET_NET2280 -+ #define gadget_is_net2280(g) !strcmp("net2280", (g)->name) -+ #else -+@@ -212,5 +224,9 @@ -+ return 0x20; -+ else if (gadget_is_m66592(gadget)) -+ return 0x21; -++ else if (gadget_is_jz4730(gadget)) -++ return 0x22; -++ else if (gadget_is_jz4740(gadget)) -++ return 0x23; -+ return -ENOENT; -+ } -+diff -urN linux-2.6.24.7.old/drivers/usb/gadget/jz4730_udc.c linux-2.6.24.7/drivers/usb/gadget/jz4730_udc.c -+--- linux-2.6.24.7.old/drivers/usb/gadget/jz4730_udc.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/usb/gadget/jz4730_udc.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1403 @@ -++/* -++ * JZ4730 USB Device Controller driver -++ * -++ * This file is licensed under the terms of the GNU General Public -++ * License version 2. This program is licensed "as is" without any -++ * warranty of any kind, whether express or implied. -++ */ -++ -++/* -++ * This device has ep0 and six bulk/interrupt/iso endpoints. -++ * -++ * - Endpoint numbering is fixed: ep0, ep1in-int, ep2in-bulk, ep3in-bulk, -++ * ep4in-iso, ep5out-bulk, ep6out-bulk, ep7out-iso. -++ * - Gadget drivers can choose ep maxpacket (8/16/32/64). -++ * - Just PIO mode currently. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#include "jz4730_udc.h" -++ -++//#define DEBUG(fmt,args...) printk(KERN_DEBUG fmt , ## args) -++//#define DEBUG_EP0(fmt,args...) printk(KERN_DEBUG fmt , ## args) -++ -++#ifndef DEBUG -++# define DEBUG(fmt,args...) do {} while(0) -++#endif -++#ifndef DEBUG_EP0 -++# define DEBUG_EP0(fmt,args...) do {} while(0) -++#endif -++ -++#define DRIVER_DESC "JZ4730 USB Device Controller" -++#define DRIVER_VERSION "20 Sep 2007" -++ -++static const char driver_name [] = "jz4730_udc"; -++static const char driver_desc [] = DRIVER_DESC; -++ -++static unsigned int udc_debug = 0; /* 0: normal mode, 1: test udc cable type mode */ -++ -++module_param(udc_debug, int, 0); -++MODULE_PARM_DESC(udc_debug, "test udc cable type"); -++ -++#ifdef CONFIG_JZ_UDC_HOTPLUG -++extern int jz_udc_active; /* 0: No actions; 1: Have actions */ -++#endif -++ -++/* -++ * Local declarations. -++ */ -++static void nuke(struct jz4730_ep *, int status); -++static inline void pio_irq_enable(struct jz4730_ep *ep); -++static inline void pio_irq_disable(struct jz4730_ep *ep); -++static void jz4730_udc_release (struct device *dev) {} -++/*-------------------------------------------------------------------------*/ -++ -++static int jz4730_ep_enable(struct usb_ep *_ep, -++ const struct usb_endpoint_descriptor *desc) -++{ -++ struct jz4730_udc *dev; -++ struct jz4730_ep *ep; -++ unsigned long flags; -++ u32 max; -++ -++ ep = container_of(_ep, struct jz4730_ep, ep); -++ if (!_ep || !desc || ep->desc -++ || desc->bDescriptorType != USB_DT_ENDPOINT) -++ return -EINVAL; -++ dev = ep->dev; -++ if (ep == &dev->ep[0]) -++ return -EINVAL; -++ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) -++ return -ESHUTDOWN; -++ if (ep->index != (desc->bEndpointAddress & 0x0f)) -++ return -EINVAL; -++ -++ switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { -++ case USB_ENDPOINT_XFER_BULK: -++ case USB_ENDPOINT_XFER_INT: -++ break; -++ default: -++ return -EINVAL; -++ } -++ -++// max = le16_to_cpu(get_unaligned(&desc->wMaxPacketSize)); -++ max = 64; -++ ep->is_in = (USB_DIR_IN & desc->bEndpointAddress) != 0; -++ -++ spin_lock_irqsave(&ep->dev->lock, flags); -++ -++ ep->stopped = 0; -++ ep->desc = desc; -++ ep->ep.maxpacket = max; -++ -++ spin_unlock_irqrestore(&ep->dev->lock, flags); -++ -++ DEBUG("enable %s %s maxpacket %u\n", ep->ep.name, -++ ep->is_in ? "IN" : "OUT", max); -++ -++ return 0; -++} -++ -++static int jz4730_ep_disable(struct usb_ep *_ep) -++{ -++ struct jz4730_ep *ep; -++ struct jz4730_udc *dev; -++ unsigned long flags; -++ -++ ep = container_of(_ep, struct jz4730_ep, ep); -++ if (!_ep || !ep->desc) -++ return -ENODEV; -++ dev = ep->dev; -++ if (dev->ep0state == EP0_SUSPEND) -++ return -EBUSY; -++ -++ DEBUG("disable %s\n", _ep->name); -++ -++ spin_lock_irqsave(&dev->lock, flags); -++ -++ /* Nuke all pending requests */ -++ nuke(ep, -ESHUTDOWN); -++ -++ /* Disable ep IRQ */ -++ pio_irq_disable(ep); -++ -++ ep->desc = 0; -++ ep->stopped = 1; -++ -++ spin_unlock_irqrestore(&dev->lock, flags); -++ -++ return 0; -++} -++ -++static struct usb_request *jz4730_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) -++{ -++ struct jz4730_request *req; -++ -++ req = kzalloc(sizeof *req, gfp_flags); -++ if (!req) -++ return 0; -++ -++ INIT_LIST_HEAD(&req->queue); -++ return &req->req; -++} -++ -++static void jz4730_free_request(struct usb_ep *_ep, struct usb_request *_req) -++{ -++ struct jz4730_request *req; -++ -++ req = container_of(_req, struct jz4730_request, req); -++ WARN_ON(!list_empty(&req->queue)); -++ kfree(req); -++} -++ -++static void *jz4730_alloc_buffer(struct usb_ep *_ep, unsigned bytes, -++ dma_addr_t *dma, gfp_t gfp_flags) -++{ -++ void *retval; -++ -++ retval = kmalloc(bytes, gfp_flags & ~(__GFP_DMA | __GFP_HIGHMEM)); -++ if (retval) -++ *dma = virt_to_phys(retval); -++ return retval; -++} -++ -++static void jz4730_free_buffer(struct usb_ep *_ep, void *buf, -++ dma_addr_t dma, unsigned bytes) -++{ -++ kfree(buf); -++} -++ -++/* -++ * done - retire a request; caller blocked irqs -++ */ -++static void done(struct jz4730_ep *ep, struct jz4730_request *req, int status) -++{ -++ struct jz4730_udc *dev; -++ unsigned stopped = ep->stopped; -++ -++ list_del_init(&req->queue); -++ -++ if (likely(req->req.status == -EINPROGRESS)) -++ req->req.status = status; -++ else -++ status = req->req.status; -++ -++ if (status && status != -ESHUTDOWN) -++ DEBUG("complete %s req %p stat %d len %u/%u\n", -++ ep->ep.name, &req->req, status, -++ req->req.actual, req->req.length); -++ -++ dev = ep->dev; -++ -++ /* don't modify queue heads during completion callback */ -++ ep->stopped = 1; -++ spin_unlock(&dev->lock); -++ req->req.complete(&ep->ep, &req->req); -++ spin_lock(&dev->lock); -++ ep->stopped = stopped; -++} -++ -++/*-------------------------------------------------------------------------*/ -++ -++static __inline__ int write_packet(struct jz4730_ep *ep, -++ struct jz4730_request *req, int max) -++{ -++ u8 *buf; -++ int length, nlong, nbyte; -++ volatile u32 *fifo = (volatile u32 *)ep->fifo; -++ -++ buf = req->req.buf + req->req.actual; -++ prefetch(buf); -++ -++ length = req->req.length - req->req.actual; -++ length = min(length, max); -++ req->req.actual += length; -++ -++ DEBUG("Write %d (max %d), fifo %p\n", length, max, fifo); -++ -++ if (!length) { -++ /* Send ZLP */ -++ writel(0, (unsigned int *)UDC_TXZLP); -++ writel(0x12345678, (unsigned int *)fifo); -++ } -++ else { -++ nlong = length >> 2; -++ nbyte = length & 0x3; -++ while (nlong--) { -++ *fifo = *((u32 *)buf); -++ buf += 4; -++ } -++ while (nbyte--) { -++ *((volatile u8 *)fifo) = *buf++; -++ } -++ } -++ -++ writel(0, (unsigned int *)UDC_TXCONFIRM); -++ -++ return length; -++} -++ -++static __inline__ int read_packet(struct jz4730_ep *ep, -++ struct jz4730_request *req, int count) -++{ -++ u8 *buf; -++ int length, nlong, nbyte; -++ volatile u32 *fifo = (volatile u32 *)ep->fifo; -++ -++ buf = req->req.buf + req->req.actual; -++ prefetchw(buf); -++ -++ length = req->req.length - req->req.actual; -++ length = min(length, count); -++ req->req.actual += length; -++ -++ DEBUG("Read %d, fifo %p\n", length, fifo); -++ -++ nlong = length >> 2; -++ nbyte = length & 0x3; -++ while (nlong--) { -++ *((u32 *)buf) = *fifo; -++ buf += 4; -++ } -++ if (nbyte) { -++ u32 data = *fifo; -++ while (nbyte--) { -++ *buf++ = data & 0x0ff; -++ data >>= 8; -++ } -++ } -++ -++ REG32(UDC_RXCONFIRM); -++ -++ return length; -++} -++ -++/** Write request to FIFO (max write == maxp size) -++ * Return: 0 = still running, 1 = completed, negative = errno -++ */ -++static int write_fifo(struct jz4730_ep *ep, struct jz4730_request *req) -++{ -++ u32 max, count; -++ int is_last; -++ -++ max = ep->ep.maxpacket; -++ -++ count = write_packet(ep, req, max); -++ -++ /* last packet often short (sometimes a zlp, especially on ep0) */ -++ if (unlikely(count != max)) { -++ is_last = 1; -++ } else { -++ if (likely(req->req.length != req->req.actual) -++ || req->req.zero) -++ is_last = 0; -++ else -++ is_last = 1; -++ } -++ -++ DEBUG("write %s (%d)(IN) %d bytes%s req %p %d/%d is_last %d\n", -++ ep->ep.name, ep->index, count, -++ (count != ep->ep.maxpacket) ? " (short)" : "", -++ req, req->req.actual, req->req.length, is_last); -++ -++ /* requests complete when all IN data is in the FIFO, -++ * or sometimes later, if a zlp was needed. -++ */ -++ if (is_last) { -++ done(ep, req, 0); -++ return 1; -++ } -++ -++ return 0; -++} -++ -++/** Read to request from FIFO (max read == bytes in fifo) -++ * Return: 0 = still running, 1 = completed, negative = errno -++ */ -++static int read_fifo(struct jz4730_ep *ep, struct jz4730_request *req, u32 count) -++{ -++ int is_short; -++ -++ is_short = (count < ep->ep.maxpacket); -++ -++ count = read_packet(ep, req, count); -++ -++ DEBUG("read %s %u bytes%s OUT req %p %u/%u is_short %d\n", -++ ep->ep.name, count, (count < ep->ep.maxpacket) ? "(short)" : "", -++ req, req->req.actual, req->req.length, is_short); -++ -++ /* completion */ -++ if (is_short || req->req.actual == req->req.length) { -++ done(ep, req, 0); -++ return 1; -++ } -++ -++ /* finished that packet. the next one may be waiting... */ -++ return 0; -++} -++ -++static inline void pio_irq_enable(struct jz4730_ep *ep) -++{ -++ switch (ep->index) { -++ case 0: -++ REG_UDC_EPIntMR &= ~0x1; -++ break; -++ case 1: -++ case 2: -++ case 3: -++ case 4: -++ REG_UDC_EPIntMR &= ~(1 << ep->index); -++ break; -++ case 5: -++ case 6: -++ case 7: -++ REG_UDC_EPIntMR &= ~(1 << (ep->index + 16)); -++ break; -++ } -++} -++ -++static inline void pio_irq_disable(struct jz4730_ep *ep) -++{ -++ switch (ep->index) { -++ case 0: -++ REG_UDC_EPIntMR |= 0x1; -++ break; -++ case 1: -++ case 2: -++ case 3: -++ case 4: -++ REG_UDC_EPIntMR |= (1 << ep->index); -++ break; -++ case 5: -++ case 6: -++ case 7: -++ REG_UDC_EPIntMR |= (1 << (ep->index + 16)); -++ break; -++ } -++} -++ -++/*-------------------------------------------------------------------------*/ -++ -++static int -++jz4730_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) -++{ -++ struct jz4730_request *req; -++ struct jz4730_ep *ep; -++ struct jz4730_udc *dev; -++ unsigned long flags; -++ int status; -++ -++ /* always require a cpu-view buffer so pio works */ -++ req = container_of(_req, struct jz4730_request, req); -++ if (unlikely(!_req || !_req->complete -++ || !_req->buf || !list_empty(&req->queue))) -++ return -EINVAL; -++ ep = container_of(_ep, struct jz4730_ep, ep); -++ if (unlikely(!_ep || (!ep->desc && ep->index != 0))) -++ return -EINVAL; -++ dev = ep->dev; -++ if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) -++ return -ESHUTDOWN; -++ -++ DEBUG("%s queue req %p, len %u buf %p\n", -++ _ep->name, _req, _req->length, _req->buf); -++ -++ spin_lock_irqsave(&dev->lock, flags); -++ -++ _req->status = -EINPROGRESS; -++ _req->actual = 0; -++ -++ /* for ep0 IN without premature status, zlp is required and -++ * writing EOP starts the status stage (OUT). -++ */ -++ if (unlikely(ep->index == 0 && ep->is_in)) -++ _req->zero = 1; -++ -++ /* kickstart this i/o queue? */ -++ status = 0; -++ if (list_empty(&ep->queue) && likely(!ep->stopped)) { -++ if (unlikely(ep->index == 0)) { -++ pio_irq_enable(ep); -++ if (ep->irq_pending || -++ (REG_UDC_EPIntR & UDC_EPIntR_OUTEP0)) { -++ u32 stats, count; -++ -++ stats = REG_UDC_EP0OutSR; -++ if (stats & UDC_EPSR_OUT_RCVDATA) { -++ ep->irq_pending = 0; -++ REG_UDC_EP0OutSR &= ~UDC_EPSR_OUT_MASK; -++ if (REG_UDC_EPIntR & UDC_EPIntR_OUTEP0) -++ REG_UDC_EPIntR = UDC_EPIntR_OUTEP0; -++ -++ count = OUT_COUNT(stats); -++ if (read_fifo(ep, req, count) == 1) -++ req = 0; -++ } -++ } -++ -++ } else if (ep->is_in) { -++ /* EP1 ~ EP4 */ -++ if (ep->irq_pending || -++ (REG_UDC_EPIntR & UDC_EPIntR_INEP2)) { -++ if (REG_UDC_EP2InSR & UDC_EPSR_IN) { -++ ep->irq_pending = 0; -++ REG_UDC_EP2InSR &= ~UDC_EPSR_IN; -++ if (REG_UDC_EPIntR & UDC_EPIntR_INEP2) -++ REG_UDC_EPIntR = UDC_EPIntR_INEP2; -++ -++ if (write_fifo(ep, req) == 1) -++ req = 0; -++ } -++ } -++ pio_irq_enable(ep); -++ } else { -++ /* EP5 ~ EP7 */ -++ pio_irq_enable(ep); -++ -++ if (ep->irq_pending || -++ (REG_UDC_EPIntR & UDC_EPIntR_OUTEP5)) { -++ u32 stats, count; -++ -++ stats = REG_UDC_EP5OutSR; -++ if (stats & UDC_EPSR_OUT_RCVDATA) { -++ ep->irq_pending = 0; -++ REG_UDC_EP5OutSR &= ~UDC_EPSR_OUT_MASK; -++ if (REG_UDC_EPIntR & UDC_EPIntR_OUTEP5) -++ REG_UDC_EPIntR = UDC_EPIntR_OUTEP5; -++ -++ count = OUT_COUNT(stats); -++ if (read_fifo(ep, req, count) == 1) -++ req = 0; -++ } -++ } -++ } -++ } -++ -++ /* pio or dma irq handler advances the queue. */ -++ if (likely(req != 0)) { -++ list_add_tail(&req->queue, &ep->queue); -++ } -++ -++ spin_unlock_irqrestore(&dev->lock, flags); -++ -++ return status; -++} -++ -++/* dequeue ALL requests */ -++static void nuke(struct jz4730_ep *ep, int status) -++{ -++ struct jz4730_request *req; -++ -++ if (list_empty(&ep->queue)) -++ return; -++ while (!list_empty(&ep->queue)) { -++ req = list_entry(ep->queue.next, struct jz4730_request, queue); -++ done(ep, req, status); -++ } -++} -++ -++/* dequeue JUST ONE request */ -++static int jz4730_dequeue(struct usb_ep *_ep, struct usb_request *_req) -++{ -++ struct jz4730_request *req; -++ struct jz4730_ep *ep; -++ struct jz4730_udc *dev; -++ unsigned long flags; -++ int stopped; -++ -++ ep = container_of(_ep, struct jz4730_ep, ep); -++ if (!_ep || !_req || (!ep->desc && ep->index != 0)) -++ return -EINVAL; -++ dev = ep->dev; -++ if (!dev->driver) -++ return -ESHUTDOWN; -++ -++ DEBUG("%s %s %p\n", __FUNCTION__, _ep->name,_req); -++ -++ spin_lock_irqsave(&dev->lock, flags); -++ stopped = ep->stopped; -++ ep->stopped = 1; -++ -++ /* make sure it's actually queued on this endpoint */ -++ list_for_each_entry (req, &ep->queue, queue) { -++ if (&req->req == _req) -++ break; -++ } -++ if (&req->req != _req) { -++ spin_unlock_irqrestore (&dev->lock, flags); -++ return -EINVAL; -++ } -++ -++ /* queue head may be partially complete. */ -++ if (ep->queue.next == &req->queue) { -++ done (ep, req, -ECONNRESET); -++ req = 0; -++ } -++ -++ if (req) -++ done (ep, req, -ECONNRESET); -++ ep->stopped = stopped; -++ -++ spin_unlock_irqrestore (&ep->dev->lock, flags); -++ return req ? 0 : -EOPNOTSUPP; -++} -++ -++/*-------------------------------------------------------------------------*/ -++ -++static void jz4730_clear_halt(struct jz4730_ep *ep) -++{ -++ if (ep->stopped) { -++ ep->stopped = 0; -++ } -++} -++ -++static int jz4730_set_halt(struct usb_ep *_ep, int value) -++{ -++ struct jz4730_ep *ep; -++ unsigned long flags; -++ int retval = 0; -++ -++ if (!_ep) -++ return -ENODEV; -++ ep = container_of (_ep, struct jz4730_ep, ep); -++ if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN) -++ return -ESHUTDOWN; -++ if (ep->desc /* not ep0 */ && (ep->desc->bmAttributes & 0x03) -++ == USB_ENDPOINT_XFER_ISOC) -++ return -EINVAL; -++ -++ if (ep->index == 0) { -++ if (value) { -++ ep->dev->ep0state = EP0_STALL; -++ ep->dev->ep[0].stopped = 1; -++ } else -++ return -EINVAL; -++ -++ /* don't change EPxSTATUS_EP_INVALID to READY */ -++ } else if (!ep->desc) { -++ DEBUG("%s %s inactive?\n", __FUNCTION__, ep->ep.name); -++ return -EINVAL; -++ } -++ -++ spin_lock_irqsave(&ep->dev->lock, flags); -++ -++ if (!list_empty(&ep->queue)) -++ retval = -EAGAIN; -++ else if (!value) -++ jz4730_clear_halt(ep); -++ else { -++ ep->stopped = 1; -++ } -++ -++ spin_unlock_irqrestore(&ep->dev->lock, flags); -++ return retval; -++} -++ -++static int jz4730_fifo_status(struct usb_ep *_ep) -++{ -++ struct jz4730_ep *ep; -++ u32 size = 0; -++ -++ if (!_ep) -++ return -ENODEV; -++ ep = container_of(_ep, struct jz4730_ep, ep); -++ -++ /* size is only reported sanely for OUT */ -++ if (ep->is_in) -++ return -EOPNOTSUPP; -++ -++ return size; -++} -++ -++static void jz4730_fifo_flush(struct usb_ep *_ep) -++{ -++ struct jz4730_ep *ep; -++ -++ if (!_ep) -++ return; -++ ep = container_of(_ep, struct jz4730_ep, ep); -++ -++ /* don't change EPxSTATUS_EP_INVALID to READY */ -++ if (!ep->desc && ep->index != 0) { -++ return; -++ } -++} -++ -++static struct usb_ep_ops jz4730_ep_ops = { -++ .enable = jz4730_ep_enable, -++ .disable = jz4730_ep_disable, -++ -++ .alloc_request = jz4730_alloc_request, -++ .free_request = jz4730_free_request, -++#if 0 -++ .alloc_buffer = jz4730_alloc_buffer, -++ .free_buffer = jz4730_free_buffer, -++#endif -++ .queue = jz4730_queue, -++ .dequeue = jz4730_dequeue, -++ -++ .set_halt = jz4730_set_halt, -++ .fifo_status = jz4730_fifo_status, -++ .fifo_flush = jz4730_fifo_flush, -++}; -++ -++/*-------------------------------------------------------------------------*/ -++ -++static int jz4730_get_frame(struct usb_gadget *_gadget) -++{ -++ return -EOPNOTSUPP; -++} -++ -++static const struct usb_gadget_ops jz4730_ops = { -++ .get_frame = jz4730_get_frame, -++ // no remote wakeup -++ // not selfpowered -++}; -++ -++/*-------------------------------------------------------------------------*/ -++ -++static void udc_reinit(struct jz4730_udc *dev) -++{ -++ static char *names [] = { "ep0", "ep1in-int", "ep2in-bulk", "ep3in-bulk", -++ "ep4in-iso", "ep5out-bulk", "ep6out-bulk", -++ "ep7out-iso" }; -++ int i; -++ -++ INIT_LIST_HEAD (&dev->gadget.ep_list); -++ dev->gadget.ep0 = &dev->ep[0].ep; -++ dev->gadget.speed = USB_SPEED_UNKNOWN; -++ dev->ep0state = EP0_DISCONNECT; -++ -++ for (i = 0; i < MAX_EP_NUM; i++) { -++ struct jz4730_ep *ep = &dev->ep[i]; -++ -++ ep->index = i; -++ ep->ep.name = names[i]; -++ ep->fifo = ep_fifo[i]; -++ ep->ep.maxpacket = 64; -++ -++ ep->ep.ops = &jz4730_ep_ops; -++ list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list); -++ ep->dev = dev; -++ INIT_LIST_HEAD(&ep->queue); -++ -++ ep->desc = 0; -++ ep->stopped = 1; -++ ep->irq_pending = 0; -++ } -++ -++ dev->ep[0].ep.maxpacket = MAX_EP0_SIZE; -++ list_del_init(&dev->ep[0].ep.ep_list); -++} -++ -++/* Reset udc registers */ -++static void udc_reset(struct jz4730_udc *dev) -++{ -++ REG_UDC_DevIntMR = 0x32; /* Enable RESET and SC interrupts */ -++ REG_UDC_EPIntMR = 0x0; /* Enable all EP interrupts */ -++ REG_UDC_DevCFGR = 0x17; -++ REG_UDC_DevCR = 0x0; -++ -++ REG_UDC_EP0InCR = (0 << 4) | (1 << 1); -++ REG_UDC_EP0InCR = (0 << 4); -++ REG_UDC_EP1InCR = (3 << 4) | (1 << 1); -++ REG_UDC_EP1InCR = (3 << 4); -++ REG_UDC_EP2InCR = (2 << 4) | (1 << 1); -++ REG_UDC_EP2InCR = (2 << 4); -++ REG_UDC_EP3InCR = (2 << 4) | (1 << 1); -++ REG_UDC_EP3InCR = (2 << 4); -++ REG_UDC_EP4InCR = (1 << 4) | (1 << 1); -++ REG_UDC_EP4InCR = (1 << 4); -++ -++ REG_UDC_EP0OutCR = (0 << 4); -++ REG_UDC_EP5OutCR = (2 << 4); -++ REG_UDC_EP6OutCR = (2 << 4); -++ REG_UDC_EP7OutCR = (1 << 4); -++ -++ REG_UDC_EP0InSR = 0; -++ REG_UDC_EP1InSR = 0; -++ REG_UDC_EP2InSR = 0; -++ REG_UDC_EP3InSR = 0; -++ REG_UDC_EP4InSR = 0; -++ REG_UDC_EP5OutSR = 0; -++ REG_UDC_EP6OutSR = 0; -++ REG_UDC_EP7OutSR = 0; -++ -++ REG_UDC_EP0InBSR = MAX_EP0_SIZE/4; -++ REG_UDC_EP1InBSR = MAX_EP1_SIZE/4; -++ REG_UDC_EP2InBSR = MAX_EP2_SIZE/4; -++ REG_UDC_EP3InBSR = MAX_EP3_SIZE/4; -++ REG_UDC_EP4InBSR = MAX_EP4_SIZE/4; -++ -++ REG_UDC_EP0InMPSR = MAX_EP0_SIZE; -++ REG_UDC_EP1InMPSR = MAX_EP1_SIZE; -++ REG_UDC_EP2InMPSR = MAX_EP2_SIZE; -++ REG_UDC_EP3InMPSR = MAX_EP3_SIZE; -++ REG_UDC_EP4InMPSR = MAX_EP4_SIZE; -++ -++ REG_UDC_EP0OutMPSR = MAX_EP0_SIZE; -++ REG_UDC_EP5OutMPSR = MAX_EP5_SIZE; -++ REG_UDC_EP6OutMPSR = MAX_EP6_SIZE; -++ REG_UDC_EP7OutMPSR = MAX_EP7_SIZE; -++ -++ REG_UDC_EP0InfR = (MAX_EP0_SIZE << 19) | (0 << 15) | (0 << 11) | (0x1 << 7) | (0 << 5) | (0 << 4) | (0 << 0); -++ REG_UDC_EP1InfR = (MAX_EP1_SIZE << 19) | (0 << 15) | (0 << 11) | (0x1 << 7) | (3 << 5) | (1 << 4) | (1 << 0); -++ REG_UDC_EP2InfR = (MAX_EP2_SIZE << 19) | (0 << 15) | (0 << 11) | (0x1 << 7) | (2 << 5) | (1 << 4) | (2 << 0); -++ REG_UDC_EP3InfR = (MAX_EP3_SIZE << 19) | (0 << 15) | (0 << 11) | (0x1 << 7) | (2 << 5) | (1 << 4) | (3 << 0); -++ REG_UDC_EP4InfR = (MAX_EP4_SIZE << 19) | (0 << 15) | (0 << 11) | (0x1 << 7) | (1 << 5) | (1 << 4) | (4 << 0); -++ REG_UDC_EP5InfR = (MAX_EP5_SIZE << 19) | (0 << 15) | (0 << 11) | (0x1 << 7) | (2 << 5) | (0 << 4) | (5 << 0); -++ REG_UDC_EP6InfR = (MAX_EP6_SIZE << 19) | (0 << 15) | (0 << 11) | (0x1 << 7) | (2 << 5) | (0 << 4) | (6 << 0); -++ REG_UDC_EP7InfR = (MAX_EP7_SIZE << 19) | (0 << 15) | (0 << 11) | (0x1 << 7) | (1 << 5) | (0 << 4) | (7 << 0); -++ -++ REG_UDC_STCMAR = 0xffff; -++} -++ -++static void ep0_start(struct jz4730_udc *dev) -++{ -++ udc_reset(dev); -++ udc_reinit(dev); -++ -++ /* expect ep0 requests when the host drops reset */ -++ dev->gadget.speed = USB_SPEED_FULL; -++ dev->ep0state = EP0_IDLE; -++} -++ -++static void udc_enable(struct jz4730_udc *dev) -++{ -++ /* Enable udc and enable all interrupts */ -++ __intc_unmask_irq(IRQ_UDC); -++ __harb_usb0_udc(); -++ -++ /* start enumeration now, or after power detect irq */ -++ ep0_start(dev); -++} -++ -++/*-------------------------------------------------------------------------*/ -++ -++/* keeping it simple: -++ * - one bus driver, initted first; -++ * - one function driver, initted second -++ */ -++ -++static struct jz4730_udc *the_controller; -++ -++/* when a driver is successfully registered, it will receive -++ * control requests including set_configuration(), which enables -++ * non-control requests. then usb traffic follows until a -++ * disconnect is reported. then a host may connect again, or -++ * the driver might get unbound. -++ */ -++int usb_gadget_register_driver(struct usb_gadget_driver *driver) -++{ -++ struct jz4730_udc *dev = the_controller; -++ int retval; -++ -++ if (!driver -++// || driver->speed != USB_SPEED_FULL -++ || !driver->bind -++ || !driver->unbind -++ || !driver->disconnect -++ || !driver->setup) -++ { -++ printk("\n -EINVAL"); -++ return -EINVAL; -++ } -++ if (!dev) -++ return -ENODEV; -++ -++ if (dev->driver) -++ return -EBUSY; -++ -++ /* hook up the driver */ -++ dev->driver = driver; -++ retval = driver->bind(&dev->gadget); -++ if (retval) { -++ DEBUG("bind to driver %s --> error %d\n", -++ driver->driver.name, retval); -++ dev->driver = 0; -++ return retval; -++ } -++ /* then enable host detection and ep0; and we're ready -++ * for set_configuration as well as eventual disconnect. -++ */ -++ udc_enable(dev); -++ -++ DEBUG("registered gadget driver '%s'\n", driver->driver.name); -++ return 0; -++} -++EXPORT_SYMBOL(usb_gadget_register_driver); -++ -++static void -++stop_activity(struct jz4730_udc *dev, struct usb_gadget_driver *driver) -++{ -++ unsigned i; -++ -++ DEBUG("%s\n", __FUNCTION__); -++ -++ if (dev->gadget.speed == USB_SPEED_UNKNOWN) -++ driver = 0; -++ -++ /* disconnect gadget driver after quiesceing hw and the driver */ -++ udc_reset (dev); -++ for (i = 0; i < MAX_EP_NUM; i++) -++ nuke(&dev->ep [i], -ESHUTDOWN); -++ if (driver) { -++ spin_unlock(&dev->lock); -++ driver->disconnect(&dev->gadget); -++ spin_lock(&dev->lock); -++ } -++ -++ if (dev->driver) -++ udc_enable(dev); -++} -++ -++int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) -++{ -++ struct jz4730_udc *dev = the_controller; -++ unsigned long flags; -++ -++ /* disable UDC irq */ -++ __intc_mask_irq(IRQ_UDC); -++ __harb_usb0_uhc(); -++ -++ if (!dev) -++ return -ENODEV; -++ if (!driver || driver != dev->driver) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&dev->lock, flags); -++ dev->driver = 0; -++ stop_activity(dev, driver); -++ spin_unlock_irqrestore(&dev->lock, flags); -++ -++ driver->unbind(&dev->gadget); -++ -++ DEBUG("unregistered driver '%s'\n", driver->driver.name); -++ return 0; -++} -++EXPORT_SYMBOL(usb_gadget_unregister_driver); -++ -++static void jz4730_epn_out(struct jz4730_udc *dev, int ep_idx, u32 count) -++{ -++ struct jz4730_request *req; -++ struct jz4730_ep *ep = &dev->ep[ep_idx]; -++ -++ req = list_entry(ep->queue.next, struct jz4730_request, queue); -++ read_fifo(ep, req, count); -++} -++ -++static void jz4730_epn_in(struct jz4730_udc *dev, int ep_idx) -++{ -++ struct jz4730_request *req; -++ struct jz4730_ep *ep = &dev->ep[ep_idx]; -++ -++ req = list_entry(ep->queue.next, struct jz4730_request, queue); -++ write_fifo(ep, req); -++} -++ -++/****************************************************************/ -++/* End Point 0 related functions */ -++/****************************************************************/ -++ -++/* return: 0 = still running, 1 = completed, negative = errno */ -++static int write_fifo_ep0(struct jz4730_ep *ep, struct jz4730_request *req) -++{ -++ u32 max, count; -++ int is_last; -++ -++ max = ep->ep.maxpacket; -++ -++ count = write_packet(ep, req, max); -++ -++ /* last packet is usually short (or a zlp) */ -++ if (unlikely(count != max)) -++ is_last = 1; -++ else { -++ if (likely(req->req.length != req->req.actual) || req->req.zero) -++ is_last = 0; -++ else -++ is_last = 1; -++ } -++ -++ DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __FUNCTION__, -++ ep->ep.name, count, -++ is_last ? "/L" : "", req->req.length - req->req.actual, req); -++ -++ /* requests complete when all IN data is in the FIFO */ -++ if (is_last) { -++ done(ep, req, 0); -++ return 1; -++ } -++ -++ return 0; -++} -++ -++/* -++ * Simulate a USB_REQ_SET_CONFIGURATION to the function driver, -++ * this is required to enable the endpoints of the function driver. -++ * UDC should let software have the chance to handle this standard -++ * request, unfortunately UDC can't do that. -++ */ -++static void psudo_set_config(void) -++{ -++ struct jz4730_udc *dev = (struct jz4730_udc *) the_controller; -++ struct usb_ctrlrequest ctrl; -++ int tmp; -++ -++ /* SETUP packet */ -++ ctrl.bRequestType = 0x00; -++ ctrl.bRequest = USB_REQ_SET_CONFIGURATION; -++ ctrl.wValue = 1; -++ ctrl.wIndex = 0; -++ ctrl.wLength = 0; -++ -++ nuke(&dev->ep[0], 0); -++ dev->ep[0].stopped = 0; -++ -++ if (likely(ctrl.bRequestType & USB_DIR_IN)) { -++ dev->ep[0].is_in = 1; -++ dev->ep0state = EP0_IN; -++ } else { -++ dev->ep[0].is_in = 0; -++ dev->ep0state = EP0_OUT; -++ } -++ -++ /* delegate everything to the gadget driver. -++ * it may respond after this irq handler returns. -++ */ -++ spin_unlock (&dev->lock); -++ tmp = dev->driver->setup(&dev->gadget, &ctrl); -++ spin_lock (&dev->lock); -++ if (unlikely(tmp < 0)) { -++ DEBUG_EP0("req %02x.%02x protocol STALL; err %d\n", -++ ctrl.bRequestType, ctrl.bRequest, tmp); -++ dev->ep[0].stopped = 1; -++ dev->ep0state = EP0_STALL; -++ } -++} -++ -++/* -++ * Read 8 bytes setup packet from EP0 RX buffer -++ */ -++static void read_setup_packet(u8 *buf) -++{ -++ u32 *tmp = (u32 *)buf; -++ -++ *tmp++ = readl((unsigned int *)RXFIFO); -++ *tmp++ = readl((unsigned int *)RXFIFO); -++ -++ REG32(UDC_RXCONFIRM); -++} -++ -++static void jz4730_ep0_setup(struct jz4730_udc *dev) -++{ -++ struct jz4730_ep *ep = &dev->ep[0]; -++ struct usb_ctrlrequest ctrl; -++ int tmp; -++ -++ /* read control req from fifo (8 bytes) */ -++ read_setup_packet((unsigned char *) &ctrl); -++ -++ DEBUG_EP0("SETUP %02x.%02x v%04x i%04x l%04x\n", -++ ctrl.bRequestType, ctrl.bRequest, -++ ctrl.wValue, ctrl.wIndex, ctrl.wLength); -++ -++ /* Set direction of EP0 */ -++ if (likely(ctrl.bRequestType & USB_DIR_IN)) { -++ ep->is_in = 1; -++ dev->ep0state = EP0_IN; -++ } else { -++ ep->is_in = 0; -++ dev->ep0state = EP0_OUT; -++ } -++ -++ /* Nuke all previous transfers */ -++ nuke(ep, 0); -++ ep->stopped = 0; -++ -++ /* delegate everything to the gadget driver. -++ * it may respond after this irq handler returns. -++ */ -++ if (likely((u32)dev->driver)) { -++ /* device-2-host (IN) or no data setup command, process immediately */ -++ spin_unlock(&dev->lock); -++ tmp = dev->driver->setup(&dev->gadget, &ctrl); -++ spin_lock(&dev->lock); -++ -++ if (unlikely(tmp < 0)) { -++ /* setup processing failed, force stall */ -++ DEBUG_EP0("req %02x.%02x protocol STALL; err %d\n", -++ ctrl.bRequestType, ctrl.bRequest, tmp); -++ dev->ep0state = EP0_STALL; -++ } -++ } -++} -++ -++static int jz4730_ep0_in(struct jz4730_udc *dev) -++{ -++ struct jz4730_request *req; -++ struct jz4730_ep *ep = &dev->ep[0]; -++ int ret; -++ -++ if (list_empty(&ep->queue)) -++ req = 0; -++ else -++ req = list_entry(ep->queue.next, struct jz4730_request, queue); -++ -++ if (!req) { -++ DEBUG_EP0("%s: NULL REQ\n", __FUNCTION__); -++ return 0; -++ } -++ -++ ret = write_fifo_ep0(ep, req); -++ -++ return ret; -++} -++ -++static void jz4730_ep0_out(struct jz4730_udc *dev) -++{ -++ u32 epsr; -++ struct jz4730_ep *ep = &dev->ep[0]; -++ -++ epsr = REG_UDC_EP0OutSR; -++ REG_UDC_EP0OutSR &= ~UDC_EPSR_OUT_MASK; -++ -++ if (epsr & UDC_EPSR_OUT_RCVSETUP) { -++ jz4730_ep0_setup(dev); -++ } -++ else if (epsr & UDC_EPSR_OUT_RCVDATA) { -++ u32 count = __udc_ep0out_packet_size(); -++ if (count == 0) { -++ readl((unsigned int *)UDC_RXCONFIRM); // ack zero packet -++ } -++ else { -++ /* EP0 OUT Data */ -++ if (list_empty(&ep->queue)) { -++ ep->irq_pending = 1; -++ pio_irq_disable(ep); -++ } -++ else -++ jz4730_epn_out(dev, 0, count); -++ -++ } -++ } -++} -++ -++static void handle_reset_irq(struct jz4730_udc *dev) -++{ -++ int i; -++ -++ /* clear any status */ -++ REG_UDC_EPIntR = 0xffffffff; -++ REG_UDC_DevIntR = 0xffffffff; -++ -++ /* reset udc */ -++ udc_reset(dev); -++ -++ /* reset driver status */ -++ for (i = 0; i < MAX_EP_NUM; i++) { -++ struct jz4730_ep *ep = &dev->ep[i]; -++ -++ ep->irq_pending = 0; -++// nuke(ep, 0); -++ nuke(ep, -ESHUTDOWN); -++ } -++} -++ -++static irqreturn_t jz4730_udc_irq(int irq, void *_dev) -++{ -++ struct jz4730_udc *dev = _dev; -++ struct jz4730_ep *ep; -++ -++ u32 intr_dev, intr_ep, stats, count; -++ -++ spin_lock(&dev->lock); -++ -++ intr_dev = REG_UDC_DevIntR; -++ intr_ep = REG_UDC_EPIntR; -++ -++ DEBUG("*** udc irq intr_dev=0x%x intr_ep=0x%x\n", intr_dev, intr_ep); -++ -++ if (!intr_dev && !intr_ep) { -++ spin_unlock(&dev->lock); -++ return IRQ_HANDLED; -++ } -++ -++ if (udc_debug) { -++#ifdef CONFIG_JZ_UDC_HOTPLUG -++ jz_udc_active = 1; -++#endif -++ REG_UDC_DevIntR = intr_dev; -++ REG_UDC_EPIntR = intr_ep; -++ __harb_usb0_uhc(); -++ __intc_mask_irq(IRQ_UDC); -++ spin_unlock(&dev->lock); -++ return IRQ_HANDLED; -++ } -++ -++ if (intr_dev) { -++ if (intr_dev & UDC_DevIntR_SC) { -++ psudo_set_config(); -++ udelay(100); -++ } -++ -++ if (intr_dev & UDC_DevIntR_UR) { -++#ifdef CONFIG_JZ_UDC_HOTPLUG -++ jz_udc_active = 1; -++#endif -++ handle_reset_irq(dev); -++ } -++ -++ REG_UDC_DevIntR = intr_dev; -++ } -++ -++ if (intr_ep & UDC_EPIntR_OUTEP0) { -++ REG_UDC_EPIntR = UDC_EPIntR_OUTEP0; -++ jz4730_ep0_out(dev); -++ } -++ -++ if (intr_ep & UDC_EPIntR_INEP0) { -++ ep = &dev->ep[0]; -++ if (list_empty(&ep->queue)) { -++ pio_irq_disable(ep); -++ } -++ else { -++ stats = REG_UDC_EP0InSR; -++ if (stats & UDC_EPSR_IN) { -++ REG_UDC_EPIntR = UDC_EPIntR_INEP0; -++ REG_UDC_EP0InSR &= ~UDC_EPSR_IN; -++ -++ jz4730_ep0_in(dev); -++ } -++ } -++ } -++ -++ if (intr_ep & UDC_EPIntR_OUTEP5) { -++ REG_UDC_EPIntR = UDC_EPIntR_OUTEP5; -++ ep = &dev->ep[5]; -++ if (list_empty(&ep->queue)) { -++ ep->irq_pending = 1; -++ pio_irq_disable(ep); -++ } -++ else { -++ stats = REG_UDC_EP5OutSR; -++ if (stats & UDC_EPSR_OUT_RCVDATA) { -++ REG_UDC_EP5OutSR &= ~UDC_EPSR_OUT_MASK; -++ -++ count = OUT_COUNT(stats); -++ jz4730_epn_out(dev, 5, count); -++ } -++ } -++ } -++ -++ if (intr_ep & UDC_EPIntR_INEP2) { -++ ep = &dev->ep[2]; -++ if (list_empty(&ep->queue)) { -++ ep->irq_pending = 1; -++ pio_irq_disable(ep); -++ } -++ else { -++ stats = REG_UDC_EP2InSR; -++ if (stats & UDC_EPSR_IN) { -++ REG_UDC_EP2InSR &= ~UDC_EPSR_IN; -++ jz4730_epn_in(dev, 2); -++ } -++ } -++ -++ REG_UDC_EPIntR = UDC_EPIntR_INEP2; -++ } -++ -++ if (intr_ep & UDC_EPIntR_INEP1) { -++ ep = &dev->ep[1]; -++ if (list_empty(&ep->queue)) { -++ ep->irq_pending = 1; -++ pio_irq_disable(ep); -++ } -++ else { -++ stats = REG_UDC_EP1InSR; -++ if (stats & UDC_EPSR_IN) { -++ REG_UDC_EP1InSR &= ~UDC_EPSR_IN; -++ jz4730_epn_in(dev, 1); -++ } -++ } -++ -++ REG_UDC_EPIntR = UDC_EPIntR_INEP1; -++ } -++ -++ spin_unlock(&dev->lock); -++ return IRQ_HANDLED; -++} -++ -++/*-------------------------------------------------------------------------*/ -++ -++static struct jz4730_udc udc_dev = { -++ .usb_address = 0, -++ -++ .gadget = { -++ .ops = &jz4730_ops, -++ .ep0 = &udc_dev.ep[0].ep, -++ .name = driver_name, -++ .dev = { -++ .bus_id = "gadget", -++ }, -++ }, -++ /* control endpoint no need to init here!*/ -++ /* control endpoint */ -++}; -++ -++ -++/* tear down the binding between this driver and the pci device */ -++static int jz4730_udc_remove(struct platform_device *pdev) -++{ -++ struct jz4730_udc *dev = platform_get_drvdata(pdev); -++ -++ if (dev->driver) -++ return -EBUSY; -++ -++ /* USB port0 as UHC */ -++ __harb_usb0_uhc(); -++ -++ /* reset udc */ -++ udc_reset(dev); -++ -++ /* clear any status */ -++ REG_UDC_EPIntR = 0xffffffff; -++ REG_UDC_DevIntR = 0xffffffff; -++ -++ /* disable all UDC interrupts */ -++ REG_UDC_DevIntMR = 0xffffffff; -++ REG_UDC_EPIntMR = 0xffffffff; -++ -++ free_irq(IRQ_UDC, dev); -++ platform_set_drvdata(pdev, 0); -++ device_unregister(&dev->gadget.dev); -++ the_controller = 0; -++ -++ return 0; -++} -++ -++static int jz4730_udc_probe(struct platform_device *pdev) -++{ -++ struct jz4730_udc *dev = &udc_dev; -++ int retval,rc; -++ -++ /* if you want to support more than one controller in a system, -++ * usb_gadget_driver_{register,unregister}() must change. -++ */ -++ if (the_controller) { -++ printk("Check the_controller: %s\n", driver_name); -++ return -EBUSY; -++ } -++ -++ spin_lock_init(&dev->lock); -++ device_initialize(&dev->gadget.dev); -++ dev->gadget.dev.parent = &pdev->dev; //if no,can only insmod once!! -++ dev->gadget.dev.release = jz4730_udc_release; -++ rc = device_register (&dev->gadget.dev); -++ if (rc < 0) -++ return rc; -++ platform_set_drvdata(pdev, dev); -++ -++ /* -++ * Note: we just mask INTC irq but allow UDC irq. -++ * This avoid that we miss any UDC irqs. -++ */ -++ -++ /* To avoid any UDC irqs here, we call cli() first */ -++// cli(); -++ -++ /* disable INTC irq */ -++ __intc_mask_irq(IRQ_UDC); -++ -++ /* init to known state, then setup irqs */ -++ udc_reset(dev); -++ udc_reinit(dev); -++ -++ /* request UDC irq */ -++ if (request_irq(IRQ_UDC, jz4730_udc_irq, IRQF_DISABLED, // SA_INTERRUPT, -++ driver_name, dev) != 0) { -++ printk(KERN_INFO "request UDC interrupt %d failed\n", IRQ_UDC); -++ retval = -EBUSY; -++ goto done; -++ } -++ -++ /* disable INTC irq again since request_irq has enabled it */ -++ __intc_mask_irq(IRQ_UDC); -++ __intc_ack_irq(IRQ_UDC); -++ -++ /* Re-enable irqs */ -++// sti(); -++ -++ printk(KERN_INFO "%s\n", driver_desc); -++ printk(KERN_INFO "version: " DRIVER_VERSION "\n"); -++ -++ /* done */ -++ the_controller = dev; -++ -++ return 0; -++ -++done: -++ if (dev) -++ jz4730_udc_remove (pdev); -++ return retval; -++} -++ -++static struct platform_driver udc_driver = { -++ .probe = jz4730_udc_probe, -++ .remove = jz4730_udc_remove, -++ .suspend = NULL, -++ .resume = NULL, -++ .driver = { -++ .name = (char *) driver_name, -++ .owner = THIS_MODULE, -++ }, -++}; -++static struct platform_device the_udc_pdev = { -++ .name = (char *) driver_name, -++ .id = -1, -++ .dev = { -++ .release = jz4730_udc_release, -++ }, -++}; -++ -++/*-------------------------------------------------------------------------*/ -++ -++static int __init udc_init (void) -++{ -++ platform_driver_register(&udc_driver); -++ return platform_device_register (&the_udc_pdev); -++} -++ -++static void __exit udc_exit (void) -++{ -++ platform_driver_unregister(&udc_driver); -++ platform_device_unregister(&the_udc_pdev); -++} -++ -++module_init(udc_init); -++module_exit(udc_exit); -++ -++MODULE_DESCRIPTION(DRIVER_DESC); -++MODULE_AUTHOR("Wei Jianli "); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/drivers/usb/gadget/jz4730_udc.h linux-2.6.24.7/drivers/usb/gadget/jz4730_udc.h -+--- linux-2.6.24.7.old/drivers/usb/gadget/jz4730_udc.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/usb/gadget/jz4730_udc.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,107 @@ -++/* -++ * JZ4730 USB Device Controller driver -++ * -++ * Copyright (C) 2005 by Wei Jianli -++ * -++ * This file is licensed under the terms of the GNU General Public -++ * License version 2. This program is licensed "as is" without any -++ * warranty of any kind, whether express or implied. -++ */ -++ -++#ifndef __JZ4730_UDC_H__ -++#define __JZ4730_UDC_H__ -++ -++/* DRIVER DATA STRUCTURES and UTILITIES */ -++#define MAX_EP_NUM 8 /* Number of endpoints on this UDC */ -++ -++#define MAX_EP0_SIZE 32 -++#define MAX_EP1_SIZE 64 -++#define MAX_EP2_SIZE 64 -++#define MAX_EP3_SIZE 64 -++#define MAX_EP4_SIZE 64 -++#define MAX_EP5_SIZE 64 -++#define MAX_EP6_SIZE 64 -++#define MAX_EP7_SIZE 64 -++ -++// UDC FIFO -++#define RXFIFO (UDC_RXFIFO) /* EP0 OUT, EP5-7 OUT */ -++#define TXFIFOEP0 (UDC_TXFIFOEP0) /* EP0 IN */ -++#define TXFIFOEP1 (TXFIFOEP0 + MAX_EP0_SIZE) /* EP1 IN */ -++#define TXFIFOEP2 (TXFIFOEP1 + MAX_EP1_SIZE) /* EP2 IN */ -++#define TXFIFOEP3 (TXFIFOEP2 + MAX_EP2_SIZE) /* EP3 IN */ -++#define TXFIFOEP4 (TXFIFOEP3 + MAX_EP3_SIZE) /* EP4 IN */ -++ -++static u32 ep_fifo[MAX_EP_NUM] = {TXFIFOEP0, TXFIFOEP1, TXFIFOEP2, -++ TXFIFOEP3, TXFIFOEP4, RXFIFO, RXFIFO, -++ RXFIFO}; -++ -++#define OUT_COUNT(stats) \ -++ ((stats&UDC_EPSR_RXPKTSIZE_MASK)>>UDC_EPSR_RXPKTSIZE_BIT) -++ -++struct jz4730_ep { -++ struct usb_ep ep; -++ struct jz4730_udc *dev; -++ -++ u8 index; -++ u8 is_in; -++ u8 stopped; -++ u8 irq_pending; -++ u32 fifo; -++ -++ struct list_head queue; -++ const struct usb_endpoint_descriptor *desc; -++}; -++ -++struct jz4730_request { -++ struct usb_request req; -++ struct list_head queue; -++}; -++ -++enum ep0state { -++ EP0_DISCONNECT, /* no host */ -++ EP0_IDLE, /* between STATUS ack and SETUP report */ -++ EP0_IN, EP0_OUT, /* data stage */ -++ EP0_STATUS, /* status stage */ -++ EP0_STALL, /* data or status stages */ -++ EP0_SUSPEND, /* usb suspend */ -++}; -++ -++struct jz4730_udc { -++ struct usb_gadget gadget; -++ struct usb_gadget_driver *driver; -++ spinlock_t lock; -++ -++ struct jz4730_ep ep[MAX_EP_NUM]; -++ enum ep0state ep0state; -++ unsigned char usb_address; -++}; -++ -++/*-------------------------------------------------------------------------*/ -++ -++/* 2.5 stuff that's sometimes missing in 2.4 */ -++ -++#ifndef container_of -++#define container_of list_entry -++#endif -++ -++#ifndef likely -++#define likely(x) (x) -++#define unlikely(x) (x) -++#endif -++ -++#ifndef BUG_ON -++#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0) -++#endif -++ -++#ifndef WARN_ON -++#define WARN_ON(x) do { } while (0) -++#endif -++ -++#ifndef IRQ_NONE -++typedef void irqreturn_t; -++#define IRQ_NONE -++#define IRQ_HANDLED -++#define IRQ_RETVAL(x) -++#endif -++ -++#endif /* __JZ4730_UDC_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/usb/gadget/jz4740_udc.c linux-2.6.24.7/drivers/usb/gadget/jz4740_udc.c -+--- linux-2.6.24.7.old/drivers/usb/gadget/jz4740_udc.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/usb/gadget/jz4740_udc.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,2251 @@ -++/* -++ * linux/drivers/usb/gadget/jz4740_udc.c -++ * -++ * Ingenic JZ4740 on-chip high speed USB device controller -++ * -++ * Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ */ -++ -++/* -++ * This device has ep0, two bulk-in/interrupt-in endpoints, and one bulk-out endpoint. -++ * -++ * - Endpoint numbering is fixed: ep0, ep1in-int, ep2in-bulk, ep1out-bulk. -++ * - DMA works with bulk-in (channel 1) and bulk-out (channel 2) endpoints. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include "jz4740_udc.h" -++ -++//#define DEBUG(fmt,args...) printk(KERN_DEBUG fmt , ## args) -++//#define DEBUG(fmt,args...) printk(fmt , ## args) -++//#define DEBUG_EP0(fmt,args...) printk(fmt , ## args) -++//#define DEBUG_SETUP(fmt,args...) printk(fmt , ## args) -++ -++#ifndef DEBUG -++# define DEBUG(fmt,args...) do {} while(0) -++#endif -++#ifndef DEBUG_EP0 -++# define NO_STATES -++# define DEBUG_EP0(fmt,args...) do {} while(0) -++#endif -++#ifndef DEBUG_SETUP -++# define DEBUG_SETUP(fmt,args...) do {} while(0) -++#endif -++ -++static unsigned int udc_debug = 0; /* 0: normal mode, 1: test udc cable type mode */ -++ -++module_param(udc_debug, int, 0); -++MODULE_PARM_DESC(udc_debug, "test udc cable or power type"); -++ -++static unsigned int use_dma = 1; /* 1: use DMA, 0: use PIO */ -++ -++module_param(use_dma, int, 0); -++MODULE_PARM_DESC(use_dma, "DMA mode enable flag"); -++ -++#ifdef CONFIG_JZ_UDC_HOTPLUG -++extern int jz_udc_active; /* 0: No actions; 1: Have actions */ -++#endif -++ -++/* -++ * Local definintions. -++ */ -++ -++#define DRIVER_VERSION "13-Mar-2008" -++#define DRIVER_DESC "JZ4740 USB Device Controller" -++ -++static const char gadget_name [] = "jz4740_udc"; -++ -++struct jz4740_udc *the_controller; -++ -++static const char driver_name [] = "jz4740_udc"; -++static const char driver_desc [] = DRIVER_DESC; -++static const char ep0name[] = "ep0"; -++ -++#ifndef NO_STATES -++static char *state_names[] = { -++ "WAIT_FOR_SETUP", -++ "DATA_STATE_XMIT", -++ "DATA_STATE_NEED_ZLP", -++ "WAIT_FOR_OUT_STATUS", -++ "DATA_STATE_RECV" -++}; -++#endif -++ -++/* -++ * Local declarations. -++ */ -++static int jz4740_ep_enable(struct usb_ep *_ep, -++ const struct usb_endpoint_descriptor *desc); -++static int jz4740_ep_disable(struct usb_ep *_ep); -++static struct usb_request *jz4740_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags); -++static void jz4740_free_request(struct usb_ep *_ep, struct usb_request *_req); -++ -++static int jz4740_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags); -++static int jz4740_dequeue(struct usb_ep *_ep, struct usb_request *_req); -++static int jz4740_set_halt(struct usb_ep *_ep, int value); -++static int jz4740_fifo_status(struct usb_ep *_ep); -++static void jz4740_fifo_flush(struct usb_ep *_ep); -++ -++static void jz4740_ep0_kick(struct jz4740_udc *dev, struct jz4740_ep *ep); -++static void jz4740_handle_ep0(struct jz4740_udc *dev, u32 intr); -++ -++static void done(struct jz4740_ep *ep, struct jz4740_request *req, -++ int status); -++static void pio_irq_enable(struct jz4740_ep *ep); -++static void pio_irq_disable(struct jz4740_ep *ep); -++static void stop_activity(struct jz4740_udc *dev, -++ struct usb_gadget_driver *driver); -++static void nuke(struct jz4740_ep *ep, int status); -++static void flush(struct jz4740_ep *ep); -++static void udc_enable(struct jz4740_udc *dev); -++static void udc_set_address(struct jz4740_udc *dev, unsigned char address); -++static void jz4740_udc_release (struct device *dev) {} -++ -++extern void *dma_alloc_noncoherent(struct device *dev, size_t size, -++ dma_addr_t *dma_handle, gfp_t flag); -++extern void dma_free_noncoherent(struct device *dev, size_t size, -++ void *vaddr, dma_addr_t dma_handle); -++ -++static struct usb_ep_ops jz4740_ep_ops = { -++ .enable = jz4740_ep_enable, -++ .disable = jz4740_ep_disable, -++ -++ .alloc_request = jz4740_alloc_request, -++ .free_request = jz4740_free_request, -++ -++ .queue = jz4740_queue, -++ .dequeue = jz4740_dequeue, -++ -++ .set_halt = jz4740_set_halt, -++ .fifo_status = jz4740_fifo_status, -++ .fifo_flush = jz4740_fifo_flush, -++}; -++ -++/*-------------------------------------------------------------------------*/ -++ -++/* inline functions of register read/write/set/clear */ -++ -++static __inline__ u8 usb_readb(u32 port) -++{ -++ return *(volatile u8 *)port; -++} -++ -++static __inline__ u16 usb_readw(u32 port) -++{ -++ return *(volatile u16 *)port; -++} -++ -++static __inline__ u32 usb_readl(u32 port) -++{ -++ return *(volatile u32 *)port; -++} -++ -++static __inline__ void usb_writeb(u32 port, u8 val) -++{ -++ *(volatile u8 *)port = val; -++} -++ -++static __inline__ void usb_writew(u32 port, u16 val) -++{ -++ *(volatile u16 *)port = val; -++} -++ -++static __inline__ void usb_writel(u32 port, u32 val) -++{ -++ *(volatile u32 *)port = val; -++} -++ -++static __inline__ void usb_setb(u32 port, u8 val) -++{ -++ volatile u8 *ioport = (volatile u8 *)(port); -++ *ioport = (*ioport) | val; -++} -++ -++static __inline__ void usb_setw(u32 port, u16 val) -++{ -++ volatile u16 *ioport = (volatile u16 *)(port); -++ *ioport = (*ioport) | val; -++} -++ -++static __inline__ void usb_setl(u32 port, u32 val) -++{ -++ volatile u32 *ioport = (volatile u32 *)(port); -++ *ioport = (*ioport) | val; -++} -++ -++static __inline__ void usb_clearb(u32 port, u8 val) -++{ -++ volatile u8 *ioport = (volatile u8 *)(port); -++ *ioport = (*ioport) & ~val; -++} -++ -++static __inline__ void usb_clearw(u32 port, u16 val) -++{ -++ volatile u16 *ioport = (volatile u16 *)(port); -++ *ioport = (*ioport) & ~val; -++} -++ -++static __inline__ void usb_clearl(u32 port, u32 val) -++{ -++ volatile u32 *ioport = (volatile u32 *)(port); -++ *ioport = (*ioport) & ~val; -++} -++ -++/*-------------------------------------------------------------------------*/ -++ -++static __inline__ int write_packet(struct jz4740_ep *ep, -++ struct jz4740_request *req, int max) -++{ -++ u8 *buf; -++ int length, nlong, nbyte; -++ volatile u32 *fifo = (volatile u32 *)ep->fifo; -++ -++ buf = req->req.buf + req->req.actual; -++ prefetch(buf); -++ -++ length = req->req.length - req->req.actual; -++ length = min(length, max); -++ req->req.actual += length; -++ -++ DEBUG("Write %d (max %d), fifo %p\n", length, max, fifo); -++ -++ nlong = length >> 2; -++ nbyte = length & 0x3; -++ while (nlong--) { -++ *fifo = *((u32 *)buf); -++ buf += 4; -++ } -++ while (nbyte--) { -++ *((volatile u8 *)fifo) = *buf++; -++ } -++ -++ return length; -++} -++ -++static __inline__ int read_packet(struct jz4740_ep *ep, -++ struct jz4740_request *req, int count) -++{ -++ u8 *buf; -++ int length, nlong, nbyte; -++ volatile u32 *fifo = (volatile u32 *)ep->fifo; -++ -++ buf = req->req.buf + req->req.actual; -++ prefetchw(buf); -++ -++ length = req->req.length - req->req.actual; -++ length = min(length, count); -++ req->req.actual += length; -++ -++ DEBUG("Read %d, fifo %p\n", length, fifo); -++ -++ nlong = length >> 2; -++ nbyte = length & 0x3; -++ while (nlong--) { -++ *((u32 *)buf) = *fifo; -++ buf += 4; -++ } -++ while (nbyte--) { -++ *buf++ = *((volatile u8 *)fifo); -++ } -++ -++ return length; -++} -++ -++/*-------------------------------------------------------------------------*/ -++ -++/* -++ * udc_disable - disable USB device controller -++ */ -++static void udc_disable(struct jz4740_udc *dev) -++{ -++ DEBUG("%s, %p\n", __FUNCTION__, dev); -++ -++ udc_set_address(dev, 0); -++ -++ /* Disable interrupts */ -++ usb_writew(USB_REG_INTRINE, 0); -++ usb_writew(USB_REG_INTROUTE, 0); -++ usb_writeb(USB_REG_INTRUSBE, 0); -++ -++ /* Disable DMA */ -++ usb_writel(USB_REG_CNTL1, 0); -++ usb_writel(USB_REG_CNTL2, 0); -++ -++ /* Disconnect from usb */ -++ usb_clearb(USB_REG_POWER, USB_POWER_SOFTCONN); -++ -++ /* Disable the USB PHY */ -++#ifdef CONFIG_SOC_JZ4740 -++ REG_CPM_SCR &= ~CPM_SCR_USBPHY_ENABLE; -++#elif CONFIG_SOC_JZ4750 -++ REG_CPM_OPCR &= ~CPM_OPCR_UDCPHY_ENABLE; -++#endif -++ -++ dev->ep0state = WAIT_FOR_SETUP; -++ dev->gadget.speed = USB_SPEED_UNKNOWN; -++} -++ -++/* -++ * udc_reinit - initialize software state -++ */ -++static void udc_reinit(struct jz4740_udc *dev) -++{ -++ u32 i; -++ -++ DEBUG("%s, %p\n", __FUNCTION__, dev); -++ -++ /* device/ep0 records init */ -++ INIT_LIST_HEAD(&dev->gadget.ep_list); -++ INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); -++ dev->ep0state = WAIT_FOR_SETUP; -++ -++ for (i = 0; i < UDC_MAX_ENDPOINTS; i++) { -++ struct jz4740_ep *ep = &dev->ep[i]; -++ -++ if (i != 0) -++ list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list); -++ -++ INIT_LIST_HEAD(&ep->queue); -++ ep->desc = 0; -++ ep->stopped = 0; -++ ep->pio_irqs = 0; -++ } -++} -++ -++/* until it's enabled, this UDC should be completely invisible -++ * to any USB host. -++ */ -++static void udc_enable(struct jz4740_udc *dev) -++{ -++ int i; -++ -++ DEBUG("%s, %p\n", __FUNCTION__, dev); -++ -++ dev->gadget.speed = USB_SPEED_UNKNOWN; -++ -++ /* Flush FIFO for each */ -++ for (i = 0; i < UDC_MAX_ENDPOINTS; i++) { -++ struct jz4740_ep *ep = &dev->ep[i]; -++ -++ usb_set_index(ep_index(ep)); -++ flush(ep); -++ } -++ -++ /* Set this bit to allow the UDC entering low-power mode when -++ * there are no actions on the USB bus. -++ * UDC still works during this bit was set. -++ */ -++ __cpm_stop_udc(); -++ -++ /* Enable the USB PHY */ -++#ifdef CONFIG_SOC_JZ4740 -++ REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; -++#elif CONFIG_SOC_JZ4750 -++ REG_CPM_OPCR |= CPM_OPCR_UDCPHY_ENABLE; -++#endif -++ -++ /* Disable interrupts */ -++ usb_writew(USB_REG_INTRINE, 0); -++ usb_writew(USB_REG_INTROUTE, 0); -++ usb_writeb(USB_REG_INTRUSBE, 0); -++ -++ /* Enable interrupts */ -++ usb_setw(USB_REG_INTRINE, USB_INTR_EP0); -++ usb_setb(USB_REG_INTRUSBE, USB_INTR_RESET); -++ /* Don't enable rest of the interrupts */ -++ /* usb_setw(USB_REG_INTRINE, USB_INTR_INEP1 | USB_INTR_INEP2); -++ usb_setw(USB_REG_INTROUTE, USB_INTR_OUTEP1); */ -++ -++ /* Enable SUSPEND */ -++ /* usb_setb(USB_REG_POWER, USB_POWER_SUSPENDM); */ -++ -++ /* Enable HS Mode */ -++ usb_setb(USB_REG_POWER, USB_POWER_HSENAB); -++ -++ /* Let host detect UDC: -++ * Software must write a 1 to the PMR:USB_POWER_SOFTCONN bit to turn this -++ * transistor on and pull the USBDP pin HIGH. -++ */ -++ usb_setb(USB_REG_POWER, USB_POWER_SOFTCONN); -++} -++ -++/*-------------------------------------------------------------------------*/ -++ -++/* keeping it simple: -++ * - one bus driver, initted first; -++ * - one function driver, initted second -++ */ -++ -++/* -++ * Register entry point for the peripheral controller driver. -++ */ -++ -++int usb_gadget_register_driver(struct usb_gadget_driver *driver) -++{ -++ struct jz4740_udc *dev = the_controller; -++ int retval; -++ -++ if (!driver -++ || !driver->bind -++ || !driver->unbind || !driver->disconnect || !driver->setup) -++ { -++ printk("\n-EINVAL"); -++ return -EINVAL; -++ } -++ if (!dev) -++ { -++ printk("\n-ENODEV"); -++ return -ENODEV; -++ } -++ if (dev->driver) -++ { -++ printk("\n-ENODEV"); -++ return -EBUSY; -++ } -++ -++ /* hook up the driver */ -++ dev->driver = driver; -++ retval = driver->bind(&dev->gadget); -++ if (retval) { -++ DEBUG("%s: bind to driver %s --> error %d\n", dev->gadget.name, -++ driver->driver.name, retval); -++ dev->driver = 0; -++ return retval; -++ } -++ -++ /* then enable host detection and ep0; and we're ready -++ * for set_configuration as well as eventual disconnect. -++ */ -++ udc_enable(dev); -++ DEBUG("%s: registered gadget driver '%s'\n", dev->gadget.name, -++ driver->driver.name); -++ -++ return 0; -++} -++ -++EXPORT_SYMBOL(usb_gadget_register_driver); -++ -++ -++static void stop_activity(struct jz4740_udc *dev, -++ struct usb_gadget_driver *driver) -++{ -++ int i; -++ -++ DEBUG("%s\n", __FUNCTION__); -++ -++ /* don't disconnect drivers more than once */ -++ if (dev->gadget.speed == USB_SPEED_UNKNOWN) -++ driver = 0; -++ dev->gadget.speed = USB_SPEED_UNKNOWN; -++ -++ /* prevent new request submissions, kill any outstanding requests */ -++ for (i = 0; i < UDC_MAX_ENDPOINTS; i++) { -++ struct jz4740_ep *ep = &dev->ep[i]; -++ -++ ep->stopped = 1; -++ -++ usb_set_index(ep_index(ep)); -++ nuke(ep, -ESHUTDOWN); -++ } -++ -++ /* report disconnect; the driver is already quiesced */ -++ if (driver) { -++ spin_unlock(&dev->lock); -++ driver->disconnect(&dev->gadget); -++ spin_lock(&dev->lock); -++ } -++ -++ /* re-init driver-visible data structures */ -++ udc_reinit(dev); -++} -++ -++ -++/* -++ * Unregister entry point for the peripheral controller driver. -++ */ -++int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) -++{ -++ struct jz4740_udc *dev = the_controller; -++ unsigned long flags; -++ -++ if (!dev) -++ return -ENODEV; -++ if (!driver || driver != dev->driver) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&dev->lock, flags); -++ dev->driver = 0; -++ stop_activity(dev, driver); -++ spin_unlock_irqrestore(&dev->lock, flags); -++ -++ driver->unbind(&dev->gadget); -++ -++ udc_disable(dev); -++ -++ DEBUG("unregistered driver '%s'\n", driver->driver.name); -++ -++ return 0; -++} -++ -++EXPORT_SYMBOL(usb_gadget_unregister_driver); -++ -++/*-------------------------------------------------------------------------*/ -++ -++/* -++ * Starting DMA using mode 1 -++ */ -++static void kick_dma(struct jz4740_ep *ep, struct jz4740_request *req) -++{ -++ u32 count = req->req.length; -++ u32 physaddr = virt_to_phys((void *)req->req.buf); -++ -++ usb_set_index(ep_index(ep)); -++ if (ep_is_in(ep)) { /* Bulk-IN transfer using DMA channel 1 */ -++ ep->reg_addr = USB_REG_ADDR1; -++ -++ dma_cache_wback_inv((unsigned long)req->req.buf, count); -++ -++ pio_irq_enable(ep); -++ -++ usb_writeb(USB_REG_INCSRH, -++ USB_INCSRH_DMAREQENAB | USB_INCSRH_AUTOSET | USB_INCSRH_DMAREQMODE); -++ -++ usb_writel(USB_REG_ADDR1, physaddr); -++ usb_writel(USB_REG_COUNT1, count); -++ usb_writel(USB_REG_CNTL1, USB_CNTL_ENA | USB_CNTL_DIR_IN | USB_CNTL_MODE_1 | -++ USB_CNTL_INTR_EN | USB_CNTL_BURST_16 | USB_CNTL_EP(ep_index(ep))); -++ } -++ else { /* Bulk-OUT transfer using DMA channel 2 */ -++ ep->reg_addr = USB_REG_ADDR2; -++ -++ dma_cache_wback_inv((unsigned long)req->req.buf, count); -++ -++ pio_irq_enable(ep); -++ -++ usb_setb(USB_REG_OUTCSRH, -++ USB_OUTCSRH_DMAREQENAB | USB_OUTCSRH_AUTOCLR | USB_OUTCSRH_DMAREQMODE); -++ -++ usb_writel(USB_REG_ADDR2, physaddr); -++ usb_writel(USB_REG_COUNT2, count); -++ usb_writel(USB_REG_CNTL2, USB_CNTL_ENA | USB_CNTL_MODE_1 | -++ USB_CNTL_INTR_EN | USB_CNTL_BURST_16 | USB_CNTL_EP(ep_index(ep))); -++ } -++} -++ -++/*-------------------------------------------------------------------------*/ -++ -++/** Write request to FIFO (max write == maxp size) -++ * Return: 0 = still running, 1 = completed, negative = errno -++ * NOTE: INDEX register must be set for EP -++ */ -++static int write_fifo(struct jz4740_ep *ep, struct jz4740_request *req) -++{ -++ u32 max, csr; -++ u32 physaddr = virt_to_phys((void *)req->req.buf); -++ -++ max = le16_to_cpu(ep->desc->wMaxPacketSize); -++ -++ if (use_dma) { -++ u32 dma_count; -++ -++ /* DMA interrupt generated due to the last packet loaded into the FIFO */ -++ -++ dma_count = usb_readl(ep->reg_addr) - physaddr; -++ req->req.actual += dma_count; -++ -++ if (dma_count % max) { -++ /* If the last packet is less than MAXP, set INPKTRDY manually */ -++ usb_setb(ep->csr, USB_INCSR_INPKTRDY); -++ } -++ -++ done(ep, req, 0); -++ if (list_empty(&ep->queue)) { -++ pio_irq_disable(ep); -++ return 1; -++ } -++ else { -++ /* advance the request queue */ -++ req = list_entry(ep->queue.next, struct jz4740_request, queue); -++ kick_dma(ep, req); -++ return 0; -++ } -++ } -++ -++ /* -++ * PIO mode handling starts here ... -++ */ -++ -++ csr = usb_readb(ep->csr); -++ -++ if (!(csr & USB_INCSR_FFNOTEMPT)) { -++ unsigned count; -++ int is_last, is_short; -++ -++ count = write_packet(ep, req, max); -++ usb_setb(ep->csr, USB_INCSR_INPKTRDY); -++ -++ /* last packet is usually short (or a zlp) */ -++ if (unlikely(count != max)) -++ is_last = is_short = 1; -++ else { -++ if (likely(req->req.length != req->req.actual) -++ || req->req.zero) -++ is_last = 0; -++ else -++ is_last = 1; -++ /* interrupt/iso maxpacket may not fill the fifo */ -++ is_short = unlikely(max < ep_maxpacket(ep)); -++ } -++ -++ DEBUG("%s: wrote %s %d bytes%s%s %d left %p\n", __FUNCTION__, -++ ep->ep.name, count, -++ is_last ? "/L" : "", is_short ? "/S" : "", -++ req->req.length - req->req.actual, req); -++ -++ /* requests complete when all IN data is in the FIFO */ -++ if (is_last) { -++ done(ep, req, 0); -++ if (list_empty(&ep->queue)) { -++ pio_irq_disable(ep); -++ } -++ return 1; -++ } -++ } else { -++ DEBUG("Hmm.. %d ep FIFO is not empty!\n", ep_index(ep)); -++ } -++ -++ return 0; -++} -++ -++/** Read to request from FIFO (max read == bytes in fifo) -++ * Return: 0 = still running, 1 = completed, negative = errno -++ * NOTE: INDEX register must be set for EP -++ */ -++static int read_fifo(struct jz4740_ep *ep, struct jz4740_request *req) -++{ -++ u32 csr; -++ unsigned count, is_short; -++ u32 physaddr = virt_to_phys((void *)req->req.buf); -++ -++ if (use_dma) { -++ u32 dma_count; -++ -++ /* DMA interrupt generated due to a packet less than MAXP loaded into the FIFO */ -++ -++ dma_count = usb_readl(ep->reg_addr) - physaddr; -++ req->req.actual += dma_count; -++ -++ /* Disable interrupt and DMA */ -++ pio_irq_disable(ep); -++ usb_writel(USB_REG_CNTL2, 0); -++ -++ /* Read all bytes from this packet */ -++ count = usb_readw(USB_REG_OUTCOUNT); -++ count = read_packet(ep, req, count); -++ -++ if (count) { -++ /* If the last packet is greater than zero, clear OUTPKTRDY manually */ -++ usb_clearb(ep->csr, USB_OUTCSR_OUTPKTRDY); -++ } -++ -++ done(ep, req, 0); -++ -++ if (!list_empty(&ep->queue)) { -++ /* advance the request queue */ -++ req = list_entry(ep->queue.next, struct jz4740_request, queue); -++ kick_dma(ep, req); -++ } -++ -++ return 1; -++ } -++ -++ /* -++ * PIO mode handling starts here ... -++ */ -++ -++ /* make sure there's a packet in the FIFO. */ -++ csr = usb_readb(ep->csr); -++ if (!(csr & USB_OUTCSR_OUTPKTRDY)) { -++ DEBUG("%s: Packet NOT ready!\n", __FUNCTION__); -++ return -EINVAL; -++ } -++ -++ /* read all bytes from this packet */ -++ count = usb_readw(USB_REG_OUTCOUNT); -++ -++ is_short = (count < ep->ep.maxpacket); -++ -++ count = read_packet(ep, req, count); -++ -++ DEBUG("read %s %02x, %d bytes%s req %p %d/%d\n", -++ ep->ep.name, csr, count, -++ is_short ? "/S" : "", req, req->req.actual, req->req.length); -++ -++ /* Clear OutPktRdy */ -++ usb_clearb(ep->csr, USB_OUTCSR_OUTPKTRDY); -++ -++ /* completion */ -++ if (is_short || req->req.actual == req->req.length) { -++ done(ep, req, 0); -++ -++ if (list_empty(&ep->queue)) -++ pio_irq_disable(ep); -++ return 1; -++ } -++ -++ /* finished that packet. the next one may be waiting... */ -++ return 0; -++} -++ -++/* -++ * done - retire a request; caller blocked irqs -++ * INDEX register is preserved to keep same -++ */ -++static void done(struct jz4740_ep *ep, struct jz4740_request *req, int status) -++{ -++ unsigned int stopped = ep->stopped; -++ u32 index; -++ -++ DEBUG("%s, %p\n", __FUNCTION__, ep); -++ list_del_init(&req->queue); -++ -++ if (likely(req->req.status == -EINPROGRESS)) -++ req->req.status = status; -++ else -++ status = req->req.status; -++ -++ if (status && status != -ESHUTDOWN) -++ DEBUG("complete %s req %p stat %d len %u/%u\n", -++ ep->ep.name, &req->req, status, -++ req->req.actual, req->req.length); -++ -++ /* don't modify queue heads during completion callback */ -++ ep->stopped = 1; -++ /* Read current index (completion may modify it) */ -++ index = usb_readb(USB_REG_INDEX); -++ -++ spin_unlock(&ep->dev->lock); -++ req->req.complete(&ep->ep, &req->req); -++ spin_lock(&ep->dev->lock); -++ -++ /* Restore index */ -++ usb_set_index(index); -++ ep->stopped = stopped; -++} -++ -++/** Enable EP interrupt */ -++static void pio_irq_enable(struct jz4740_ep *ep) -++{ -++ DEBUG("%s: EP%d %s\n", __FUNCTION__, ep_index(ep), ep_is_in(ep) ? "IN": "OUT"); -++ -++ if (ep_is_in(ep)) { -++ switch (ep_index(ep)) { -++ case 1: -++ usb_setw(USB_REG_INTRINE, USB_INTR_INEP1); -++ break; -++ case 2: -++ usb_setw(USB_REG_INTRINE, USB_INTR_INEP2); -++ break; -++ default: -++ DEBUG("Unknown endpoint: %d\n", ep_index(ep)); -++ break; -++ } -++ } -++ else { -++ switch (ep_index(ep)) { -++ case 1: -++ usb_setw(USB_REG_INTROUTE, USB_INTR_OUTEP1); -++ break; -++ default: -++ DEBUG("Unknown endpoint: %d\n", ep_index(ep)); -++ break; -++ } -++ } -++} -++ -++/** Disable EP interrupt */ -++static void pio_irq_disable(struct jz4740_ep *ep) -++{ -++ DEBUG("%s: EP%d %s\n", __FUNCTION__, ep_index(ep), ep_is_in(ep) ? "IN": "OUT"); -++ -++ if (ep_is_in(ep)) { -++ switch (ep_index(ep)) { -++ case 1: -++ usb_clearw(USB_REG_INTRINE, USB_INTR_INEP1); -++ break; -++ case 2: -++ usb_clearw(USB_REG_INTRINE, USB_INTR_INEP2); -++ break; -++ default: -++ DEBUG("Unknown endpoint: %d\n", ep_index(ep)); -++ break; -++ } -++ } -++ else { -++ switch (ep_index(ep)) { -++ case 1: -++ usb_clearw(USB_REG_INTROUTE, USB_INTR_OUTEP1); -++ break; -++ default: -++ DEBUG("Unknown endpoint: %d\n", ep_index(ep)); -++ break; -++ } -++ } -++} -++ -++/* -++ * nuke - dequeue ALL requests -++ */ -++static void nuke(struct jz4740_ep *ep, int status) -++{ -++ struct jz4740_request *req; -++ -++ DEBUG("%s, %p\n", __FUNCTION__, ep); -++ -++ /* Flush FIFO */ -++ flush(ep); -++ -++ /* called with irqs blocked */ -++ while (!list_empty(&ep->queue)) { -++ req = list_entry(ep->queue.next, struct jz4740_request, queue); -++ done(ep, req, status); -++ } -++ -++ /* Disable IRQ if EP is enabled (has descriptor) */ -++ if (ep->desc) -++ pio_irq_disable(ep); -++} -++ -++/** Flush EP FIFO -++ * NOTE: INDEX register must be set before this call -++ */ -++static void flush(struct jz4740_ep *ep) -++{ -++ DEBUG("%s, %p\n", __FUNCTION__, ep); -++ -++ switch (ep->ep_type) { -++ case ep_control: -++ break; -++ -++ case ep_bulk_in: -++ case ep_interrupt: -++ usb_setb(ep->csr, USB_INCSR_FF); -++ break; -++ -++ case ep_bulk_out: -++ usb_setb(ep->csr, USB_OUTCSR_FF); -++ break; -++ } -++} -++ -++/** -++ * jz4740_in_epn - handle IN interrupt -++ */ -++static void jz4740_in_epn(struct jz4740_udc *dev, u32 ep_idx, u32 intr) -++{ -++ u32 csr; -++ struct jz4740_ep *ep = &dev->ep[ep_idx + 1]; -++ struct jz4740_request *req; -++ -++ usb_set_index(ep_index(ep)); -++ -++ csr = usb_readb(ep->csr); -++ DEBUG("%s: %d, csr %x\n", __FUNCTION__, ep_idx, csr); -++ -++ if (csr & USB_INCSR_SENTSTALL) { -++ DEBUG("USB_INCSR_SENTSTALL\n"); -++ usb_clearb(ep->csr, USB_INCSR_SENTSTALL); -++ return; -++ } -++ -++ if (!ep->desc) { -++ DEBUG("%s: NO EP DESC\n", __FUNCTION__); -++ return; -++ } -++ -++ if (list_empty(&ep->queue)) -++ req = 0; -++ else -++ req = list_entry(ep->queue.next, struct jz4740_request, queue); -++ -++ DEBUG("req: %p\n", req); -++ -++ if (!req) -++ return; -++ -++ write_fifo(ep, req); -++} -++ -++/* -++ * Bulk OUT (recv) -++ */ -++static void jz4740_out_epn(struct jz4740_udc *dev, u32 ep_idx, u32 intr) -++{ -++ struct jz4740_ep *ep = &dev->ep[ep_idx]; -++ struct jz4740_request *req; -++ -++ DEBUG("%s: %d\n", __FUNCTION__, ep_idx); -++ -++ usb_set_index(ep_index(ep)); -++ if (ep->desc) { -++ u32 csr; -++ -++ if (use_dma) { -++ /* DMA starts here ... */ -++ if (list_empty(&ep->queue)) -++ req = 0; -++ else -++ req = list_entry(ep->queue.next, struct jz4740_request, queue); -++ -++ if (req) -++ read_fifo(ep, req); -++ return; -++ } -++ -++ /* -++ * PIO mode starts here ... -++ */ -++ -++ while ((csr = usb_readb(ep->csr)) & -++ (USB_OUTCSR_OUTPKTRDY | USB_OUTCSR_SENTSTALL)) { -++ DEBUG("%s: %x\n", __FUNCTION__, csr); -++ -++ if (csr & USB_OUTCSR_SENTSTALL) { -++ DEBUG("%s: stall sent, flush fifo\n", -++ __FUNCTION__); -++ /* usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1); */ -++ flush(ep); -++ } else if (csr & USB_OUTCSR_OUTPKTRDY) { -++ if (list_empty(&ep->queue)) -++ req = 0; -++ else -++ req = -++ list_entry(ep->queue.next, -++ struct jz4740_request, -++ queue); -++ -++ if (!req) { -++ DEBUG("%s: NULL REQ %d\n", -++ __FUNCTION__, ep_idx); -++ break; -++ } else { -++ read_fifo(ep, req); -++ } -++ } -++ } -++ } else { -++ /* Throw packet away.. */ -++ printk("%s: ep %p ep_indx %d No descriptor?!?\n", __FUNCTION__, ep, ep_idx); -++ flush(ep); -++ } -++} -++ -++static int jz4740_ep_enable(struct usb_ep *_ep, -++ const struct usb_endpoint_descriptor *desc) -++{ -++ struct jz4740_ep *ep; -++ struct jz4740_udc *dev; -++ unsigned long flags; -++ u32 max, csrh = 0; -++ -++ ep = container_of(_ep, struct jz4740_ep, ep); -++ if (!_ep || !desc || ep->desc || _ep->name == ep0name -++ || desc->bDescriptorType != USB_DT_ENDPOINT -++ || ep->bEndpointAddress != desc->bEndpointAddress) { -++ DEBUG("%s, bad ep or descriptor\n", __FUNCTION__); -++ return -EINVAL; -++ } -++ -++ /* xfer types must match, except that interrupt ~= bulk */ -++ if (ep->bmAttributes != desc->bmAttributes -++ && ep->bmAttributes != USB_ENDPOINT_XFER_BULK -++ && desc->bmAttributes != USB_ENDPOINT_XFER_INT) { -++ DEBUG("%s, %s type mismatch\n", __FUNCTION__, _ep->name); -++ return -EINVAL; -++ } -++ -++ dev = ep->dev; -++ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) { -++ DEBUG("%s, bogus device state\n", __FUNCTION__); -++ return -ESHUTDOWN; -++ } -++ -++ max = le16_to_cpu(desc->wMaxPacketSize); -++ -++ /* Configure the endpoint */ -++ usb_set_index(desc->bEndpointAddress & 0x0F); -++ if (ep_is_in(ep)) { -++ usb_writew(USB_REG_INMAXP, max); -++ switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { -++ case USB_ENDPOINT_XFER_BULK: -++ case USB_ENDPOINT_XFER_INT: -++ csrh &= ~USB_INCSRH_ISO; -++ break; -++ case USB_ENDPOINT_XFER_ISOC: -++ csrh |= USB_INCSRH_ISO; -++ break; -++ } -++ usb_writeb(USB_REG_INCSRH, csrh); -++ } -++ else { -++ usb_writew(USB_REG_OUTMAXP, max); -++ switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { -++ case USB_ENDPOINT_XFER_BULK: -++ csrh &= ~USB_OUTCSRH_ISO; -++ break; -++ case USB_ENDPOINT_XFER_INT: -++ csrh &= ~USB_OUTCSRH_ISO; -++ csrh |= USB_OUTCSRH_DNYT; -++ break; -++ case USB_ENDPOINT_XFER_ISOC: -++ csrh |= USB_OUTCSRH_ISO; -++ break; -++ } -++ usb_writeb(USB_REG_OUTCSRH, csrh); -++ } -++ -++ spin_lock_irqsave(&ep->dev->lock, flags); -++ -++ ep->stopped = 0; -++ ep->desc = desc; -++ ep->pio_irqs = 0; -++ ep->ep.maxpacket = max; -++ -++ spin_unlock_irqrestore(&ep->dev->lock, flags); -++ -++ /* Reset halt state (does flush) */ -++ jz4740_set_halt(_ep, 0); -++ -++ DEBUG("%s: enabled %s\n", __FUNCTION__, _ep->name); -++ -++ return 0; -++} -++ -++/** Disable EP -++ * NOTE: Sets INDEX register -++ */ -++static int jz4740_ep_disable(struct usb_ep *_ep) -++{ -++ struct jz4740_ep *ep; -++ unsigned long flags; -++ -++ DEBUG("%s, %p\n", __FUNCTION__, _ep); -++ -++ ep = container_of(_ep, struct jz4740_ep, ep); -++ if (!_ep || !ep->desc) { -++ DEBUG("%s, %s not enabled\n", __FUNCTION__, -++ _ep ? ep->ep.name : NULL); -++ return -EINVAL; -++ } -++ -++ spin_lock_irqsave(&ep->dev->lock, flags); -++ -++ usb_set_index(ep_index(ep)); -++ -++ /* Nuke all pending requests (does flush) */ -++ nuke(ep, -ESHUTDOWN); -++ -++ /* Disable ep IRQ */ -++ pio_irq_disable(ep); -++ -++ ep->desc = 0; -++ ep->stopped = 1; -++ -++ spin_unlock_irqrestore(&ep->dev->lock, flags); -++ -++ DEBUG("%s: disabled %s\n", __FUNCTION__, _ep->name); -++ return 0; -++} -++ -++static struct usb_request *jz4740_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) -++{ -++ struct jz4740_request *req; -++ -++ DEBUG("%s, %p\n", __FUNCTION__, ep); -++ -++ req = kzalloc(sizeof(*req), gfp_flags); -++ if (!req) -++ return 0; -++ -++ INIT_LIST_HEAD(&req->queue); -++ -++ return &req->req; -++} -++ -++static void jz4740_free_request(struct usb_ep *ep, struct usb_request *_req) -++{ -++ struct jz4740_request *req; -++ -++ DEBUG("%s, %p\n", __FUNCTION__, ep); -++ -++ req = container_of(_req, struct jz4740_request, req); -++ WARN_ON(!list_empty(&req->queue)); -++ kfree(req); -++} -++ -++/*--------------------------------------------------------------------*/ -++ -++/** Queue one request -++ * Kickstart transfer if needed -++ * NOTE: Sets INDEX register -++ */ -++static int jz4740_queue(struct usb_ep *_ep, struct usb_request *_req, -++ gfp_t gfp_flags) -++{ -++ struct jz4740_request *req; -++ struct jz4740_ep *ep; -++ struct jz4740_udc *dev; -++ unsigned long flags; -++ -++ DEBUG("%s, %p\n", __FUNCTION__, _ep); -++ -++ req = container_of(_req, struct jz4740_request, req); -++ if (unlikely -++ (!_req || !_req->complete || !_req->buf -++ || !list_empty(&req->queue))) { -++ DEBUG("%s, bad params\n", __FUNCTION__); -++ return -EINVAL; -++ } -++ -++ ep = container_of(_ep, struct jz4740_ep, ep); -++ if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) { -++ DEBUG("%s, bad ep\n", __FUNCTION__); -++ return -EINVAL; -++ } -++ -++ dev = ep->dev; -++ if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) { -++ DEBUG("%s, bogus device state %p\n", __FUNCTION__, dev->driver); -++ return -ESHUTDOWN; -++ } -++ -++ DEBUG("%s queue req %p, len %d buf %p\n", _ep->name, _req, _req->length, -++ _req->buf); -++ -++ spin_lock_irqsave(&dev->lock, flags); -++ -++ _req->status = -EINPROGRESS; -++ _req->actual = 0; -++ -++ /* kickstart this i/o queue? */ -++ DEBUG("Add to %d Q %d %d\n", ep_index(ep), list_empty(&ep->queue), -++ ep->stopped); -++ if (list_empty(&ep->queue) && likely(!ep->stopped)) { -++ u32 csr; -++ -++ if (unlikely(ep_index(ep) == 0)) { -++ /* EP0 */ -++ list_add_tail(&req->queue, &ep->queue); -++ jz4740_ep0_kick(dev, ep); -++ req = 0; -++ } else if (use_dma) { -++ /* DMA */ -++ kick_dma(ep, req); -++ } -++ /* PIO */ -++ else if (ep_is_in(ep)) { -++ /* EP1 & EP2 */ -++ usb_set_index(ep_index(ep)); -++ csr = usb_readb(ep->csr); -++ pio_irq_enable(ep); -++ if (!(csr & USB_INCSR_FFNOTEMPT)) { -++ if (write_fifo(ep, req) == 1) -++ req = 0; -++ } -++ } else { -++ /* EP1 */ -++ usb_set_index(ep_index(ep)); -++ csr = usb_readb(ep->csr); -++ pio_irq_enable(ep); -++ if (csr & USB_OUTCSR_OUTPKTRDY) { -++ if (read_fifo(ep, req) == 1) -++ req = 0; -++ } -++ } -++ } -++ -++ /* pio or dma irq handler advances the queue. */ -++ if (likely(req != 0)) -++ list_add_tail(&req->queue, &ep->queue); -++ -++ spin_unlock_irqrestore(&dev->lock, flags); -++ -++ return 0; -++} -++ -++/* dequeue JUST ONE request */ -++static int jz4740_dequeue(struct usb_ep *_ep, struct usb_request *_req) -++{ -++ struct jz4740_ep *ep; -++ struct jz4740_request *req; -++ unsigned long flags; -++ -++ DEBUG("%s, %p\n", __FUNCTION__, _ep); -++ -++ ep = container_of(_ep, struct jz4740_ep, ep); -++ if (!_ep || ep->ep.name == ep0name) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&ep->dev->lock, flags); -++ -++ /* make sure it's actually queued on this endpoint */ -++ list_for_each_entry(req, &ep->queue, queue) { -++ if (&req->req == _req) -++ break; -++ } -++ if (&req->req != _req) { -++ spin_unlock_irqrestore(&ep->dev->lock, flags); -++ return -EINVAL; -++ } -++ -++ done(ep, req, -ECONNRESET); -++ -++ spin_unlock_irqrestore(&ep->dev->lock, flags); -++ return 0; -++} -++ -++/** Halt specific EP -++ * Return 0 if success -++ * NOTE: Sets INDEX register to EP ! -++ */ -++static int jz4740_set_halt(struct usb_ep *_ep, int value) -++{ -++ struct jz4740_ep *ep; -++ unsigned long flags; -++ -++ ep = container_of(_ep, struct jz4740_ep, ep); -++ if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) { -++ DEBUG("%s, bad ep\n", __FUNCTION__); -++ return -EINVAL; -++ } -++ -++ usb_set_index(ep_index(ep)); -++ -++ DEBUG("%s, ep %d, val %d\n", __FUNCTION__, ep_index(ep), value); -++ -++ spin_lock_irqsave(&ep->dev->lock, flags); -++ -++ if (ep_index(ep) == 0) { -++ /* EP0 */ -++ usb_setb(USB_REG_CSR0, USB_CSR0_SENDSTALL); -++ } else if (ep_is_in(ep)) { -++ u32 csr = usb_readb(ep->csr); -++ if (value && ((csr & USB_INCSR_FFNOTEMPT) -++ || !list_empty(&ep->queue))) { -++ /* -++ * Attempts to halt IN endpoints will fail (returning -EAGAIN) -++ * if any transfer requests are still queued, or if the controller -++ * FIFO still holds bytes that the host hasnÂ’t collected. -++ */ -++ spin_unlock_irqrestore(&ep->dev->lock, flags); -++ DEBUG -++ ("Attempt to halt IN endpoint failed (returning -EAGAIN) %d %d\n", -++ (csr & USB_INCSR_FFNOTEMPT), -++ !list_empty(&ep->queue)); -++ return -EAGAIN; -++ } -++ flush(ep); -++ if (value) { -++ usb_setb(ep->csr, USB_INCSR_SENDSTALL); -++ } -++ else { -++ usb_clearb(ep->csr, USB_INCSR_SENDSTALL); -++ usb_setb(ep->csr, USB_INCSR_CDT); -++ } -++ } else { -++ -++ flush(ep); -++ if (value) { -++ usb_setb(ep->csr, USB_OUTCSR_SENDSTALL); -++ } -++ else { -++ usb_clearb(ep->csr, USB_OUTCSR_SENDSTALL); -++ usb_setb(ep->csr, USB_OUTCSR_CDT); -++ } -++ } -++ -++ if (value) { -++ ep->stopped = 1; -++ } else { -++ ep->stopped = 0; -++ } -++ -++ spin_unlock_irqrestore(&ep->dev->lock, flags); -++ -++ DEBUG("%s %s halted\n", _ep->name, value == 0 ? "NOT" : "IS"); -++ -++ return 0; -++} -++ -++/** Return bytes in EP FIFO -++ * NOTE: Sets INDEX register to EP -++ */ -++static int jz4740_fifo_status(struct usb_ep *_ep) -++{ -++ u32 csr; -++ int count = 0; -++ struct jz4740_ep *ep; -++ -++ ep = container_of(_ep, struct jz4740_ep, ep); -++ if (!_ep) { -++ DEBUG("%s, bad ep\n", __FUNCTION__); -++ return -ENODEV; -++ } -++ -++ DEBUG("%s, %d\n", __FUNCTION__, ep_index(ep)); -++ -++ /* LPD can't report unclaimed bytes from IN fifos */ -++ if (ep_is_in(ep)) -++ return -EOPNOTSUPP; -++ -++ usb_set_index(ep_index(ep)); -++ -++ csr = usb_readb(ep->csr); -++ if (ep->dev->gadget.speed != USB_SPEED_UNKNOWN || -++ csr & 0x1) { -++ count = usb_readw(USB_REG_OUTCOUNT); -++ } -++ -++ return count; -++} -++ -++/** Flush EP FIFO -++ * NOTE: Sets INDEX register to EP -++ */ -++static void jz4740_fifo_flush(struct usb_ep *_ep) -++{ -++ struct jz4740_ep *ep; -++ -++ ep = container_of(_ep, struct jz4740_ep, ep); -++ if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) { -++ DEBUG("%s, bad ep\n", __FUNCTION__); -++ return; -++ } -++ -++ usb_set_index(ep_index(ep)); -++ flush(ep); -++} -++ -++/****************************************************************/ -++/* End Point 0 related functions */ -++/****************************************************************/ -++ -++/* return: 0 = still running, 1 = completed, negative = errno */ -++static int write_fifo_ep0(struct jz4740_ep *ep, struct jz4740_request *req) -++{ -++ u32 max; -++ unsigned count; -++ int is_last; -++ -++ max = ep_maxpacket(ep); -++ -++ count = write_packet(ep, req, max); -++ -++ /* last packet is usually short (or a zlp) */ -++ if (unlikely(count != max)) -++ is_last = 1; -++ else { -++ if (likely(req->req.length != req->req.actual) || req->req.zero) -++ is_last = 0; -++ else -++ is_last = 1; -++ } -++ -++ DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __FUNCTION__, -++ ep->ep.name, count, -++ is_last ? "/L" : "", req->req.length - req->req.actual, req); -++ -++ /* requests complete when all IN data is in the FIFO */ -++ if (is_last) { -++ done(ep, req, 0); -++ return 1; -++ } -++ -++ return 0; -++} -++ -++static __inline__ int jz4740_fifo_read(struct jz4740_ep *ep, -++ unsigned char *cp, int max) -++{ -++ int bytes; -++ int count = usb_readw(USB_REG_OUTCOUNT); -++ volatile u8 *fifo = (volatile u8 *)ep->fifo; -++ -++ if (count > max) -++ count = max; -++ bytes = count; -++ while (count--) -++ *cp++ = *fifo; -++ return bytes; -++} -++ -++static __inline__ void jz4740_fifo_write(struct jz4740_ep *ep, -++ unsigned char *cp, int count) -++{ -++ volatile u8 *fifo = (volatile u8 *)ep->fifo; -++ DEBUG_EP0("fifo_write: %d %d\n", ep_index(ep), count); -++ while (count--) -++ *fifo = *cp++; -++} -++ -++static int read_fifo_ep0(struct jz4740_ep *ep, struct jz4740_request *req) -++{ -++ u32 csr; -++ u8 *buf; -++ unsigned bufferspace, count, is_short; -++ volatile u8 *fifo = (volatile u8 *)ep->fifo; -++ -++ DEBUG_EP0("%s\n", __FUNCTION__); -++ -++ csr = usb_readb(USB_REG_CSR0); -++ if (!(csr & USB_CSR0_OUTPKTRDY)) -++ return 0; -++ -++ buf = req->req.buf + req->req.actual; -++ prefetchw(buf); -++ bufferspace = req->req.length - req->req.actual; -++ -++ /* read all bytes from this packet */ -++ if (likely(csr & USB_CSR0_OUTPKTRDY)) { -++ count = usb_readw(USB_REG_OUTCOUNT); -++ req->req.actual += min(count, bufferspace); -++ } else /* zlp */ -++ count = 0; -++ -++ is_short = (count < ep->ep.maxpacket); -++ DEBUG_EP0("read %s %02x, %d bytes%s req %p %d/%d\n", -++ ep->ep.name, csr, count, -++ is_short ? "/S" : "", req, req->req.actual, req->req.length); -++ -++ while (likely(count-- != 0)) { -++ u8 byte = (u8) (*fifo & 0xff); -++ -++ if (unlikely(bufferspace == 0)) { -++ /* this happens when the driver's buffer -++ * is smaller than what the host sent. -++ * discard the extra data. -++ */ -++ if (req->req.status != -EOVERFLOW) -++ DEBUG_EP0("%s overflow %d\n", ep->ep.name, -++ count); -++ req->req.status = -EOVERFLOW; -++ } else { -++ *buf++ = byte; -++ bufferspace--; -++ } -++ } -++ -++ /* completion */ -++ if (is_short || req->req.actual == req->req.length) { -++ done(ep, req, 0); -++ return 1; -++ } -++ -++ /* finished that packet. the next one may be waiting... */ -++ return 0; -++} -++ -++/** -++ * udc_set_address - set the USB address for this device -++ * @address: -++ * -++ * Called from control endpoint function after it decodes a set address setup packet. -++ */ -++static void udc_set_address(struct jz4740_udc *dev, unsigned char address) -++{ -++ DEBUG_EP0("%s: %d\n", __FUNCTION__, address); -++ -++ dev->usb_address = address; -++ usb_writeb(USB_REG_FADDR, address); -++} -++ -++/* -++ * DATA_STATE_RECV (USB_CSR0_OUTPKTRDY) -++ * - if error -++ * set USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND | USB_CSR0_SENDSTALL bits -++ * - else -++ * set USB_CSR0_SVDOUTPKTRDY bit -++ if last set USB_CSR0_DATAEND bit -++ */ -++static void jz4740_ep0_out(struct jz4740_udc *dev, u32 csr) -++{ -++ struct jz4740_request *req; -++ struct jz4740_ep *ep = &dev->ep[0]; -++ int ret; -++ -++ DEBUG_EP0("%s: %x\n", __FUNCTION__, csr); -++ -++ if (list_empty(&ep->queue)) -++ req = 0; -++ else -++ req = list_entry(ep->queue.next, struct jz4740_request, queue); -++ -++ if (req) { -++ if (req->req.length == 0) { -++ DEBUG_EP0("ZERO LENGTH OUT!\n"); -++/* usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); */ -++ usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY)); -++ dev->ep0state = WAIT_FOR_SETUP; -++ return; -++ } -++ ret = read_fifo_ep0(ep, req); -++ if (ret) { -++ /* Done! */ -++ DEBUG_EP0("%s: finished, waiting for status\n", -++ __FUNCTION__); -++ usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); -++ dev->ep0state = WAIT_FOR_SETUP; -++ } else { -++ /* Not done yet.. */ -++ DEBUG_EP0("%s: not finished\n", __FUNCTION__); -++ usb_setb(USB_REG_CSR0, USB_CSR0_SVDOUTPKTRDY); -++ } -++ } else { -++ DEBUG_EP0("NO REQ??!\n"); -++ } -++} -++ -++/* -++ * DATA_STATE_XMIT -++ */ -++static int jz4740_ep0_in(struct jz4740_udc *dev, u32 csr) -++{ -++ struct jz4740_request *req; -++ struct jz4740_ep *ep = &dev->ep[0]; -++ int ret, need_zlp = 0; -++ -++ DEBUG_EP0("%s: %x\n", __FUNCTION__, csr); -++ -++ if (list_empty(&ep->queue)) -++ req = 0; -++ else -++ req = list_entry(ep->queue.next, struct jz4740_request, queue); -++ -++ if (!req) { -++ DEBUG_EP0("%s: NULL REQ\n", __FUNCTION__); -++ return 0; -++ } -++ -++ if (req->req.length == 0) { -++ usb_setb(USB_REG_CSR0, (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND)); -++ dev->ep0state = WAIT_FOR_SETUP; -++ return 1; -++ } -++ -++ if (req->req.length - req->req.actual == EP0_MAXPACKETSIZE) { -++ /* Next write will end with the packet size, */ -++ /* so we need zero-length-packet */ -++ need_zlp = 1; -++ } -++ -++ ret = write_fifo_ep0(ep, req); -++ -++ if (ret == 1 && !need_zlp) { -++ /* Last packet */ -++ DEBUG_EP0("%s: finished, waiting for status\n", __FUNCTION__); -++ -++ usb_setb(USB_REG_CSR0, (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND)); -++ dev->ep0state = WAIT_FOR_SETUP; -++ } else { -++ DEBUG_EP0("%s: not finished\n", __FUNCTION__); -++ usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); -++ } -++ -++ if (need_zlp) { -++ DEBUG_EP0("%s: Need ZLP!\n", __FUNCTION__); -++ usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); -++ dev->ep0state = DATA_STATE_NEED_ZLP; -++ } -++ -++ return 1; -++} -++ -++#if 0 -++static int jz4740_handle_get_status(struct jz4740_udc *dev, -++ struct usb_ctrlrequest *ctrl) -++{ -++ struct jz4740_ep *ep0 = &dev->ep[0]; -++ struct jz4740_ep *qep; -++ int reqtype = (ctrl->bRequestType & USB_RECIP_MASK); -++ u16 val = 0; -++ -++ if (reqtype == USB_RECIP_INTERFACE) { -++ /* This is not supported. -++ * And according to the USB spec, this one does nothing.. -++ * Just return 0 -++ */ -++ DEBUG_SETUP("GET_STATUS: USB_RECIP_INTERFACE\n"); -++ } else if (reqtype == USB_RECIP_DEVICE) { -++ DEBUG_SETUP("GET_STATUS: USB_RECIP_DEVICE\n"); -++ val |= (1 << 0); /* Self powered */ -++ /*val |= (1<<1); *//* Remote wakeup */ -++ } else if (reqtype == USB_RECIP_ENDPOINT) { -++ int ep_num = (ctrl->wIndex & ~USB_DIR_IN); -++ -++ DEBUG_SETUP -++ ("GET_STATUS: USB_RECIP_ENDPOINT (%d), ctrl->wLength = %d\n", -++ ep_num, ctrl->wLength); -++ -++ if (ctrl->wLength > 2 || ep_num > 3) -++ return -EOPNOTSUPP; -++ -++ qep = &dev->ep[ep_num]; -++ if (ep_is_in(qep) != ((ctrl->wIndex & USB_DIR_IN) ? 1 : 0) -++ && ep_index(qep) != 0) { -++ return -EOPNOTSUPP; -++ } -++ -++ usb_set_index(ep_index(qep)); -++ -++ /* Return status on next IN token */ -++ switch (qep->ep_type) { -++ case ep_control: -++ val = -++ (usb_readb(qep->csr) & USB_CSR0_SENDSTALL) == -++ USB_CSR0_SENDSTALL; -++ break; -++ case ep_bulk_in: -++ case ep_interrupt: -++ val = -++ (usb_readb(qep->csr) & USB_INCSR_SENDSTALL) == -++ USB_INCSR_SENDSTALL; -++ break; -++ case ep_bulk_out: -++ val = -++ (usb_readb(qep->csr) & USB_OUTCSR_SENDSTALL) == -++ USB_OUTCSR_SENDSTALL; -++ break; -++ } -++ -++ /* Back to EP0 index */ -++ usb_set_index(0); -++ -++ DEBUG_SETUP("GET_STATUS, ep: %d (%x), val = %d\n", ep_num, -++ ctrl->wIndex, val); -++ } else { -++ DEBUG_SETUP("Unknown REQ TYPE: %d\n", reqtype); -++ return -EOPNOTSUPP; -++ } -++ -++ /* Clear "out packet ready" */ -++ usb_setb(USB_REG_CSR0, USB_CSR0_SVDOUTPKTRDY); -++ /* Put status to FIFO */ -++ jz4740_fifo_write(ep0, (u8 *) & val, sizeof(val)); -++ /* Issue "In packet ready" */ -++ usb_setb(USB_REG_CSR0, (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND)); -++ -++ return 0; -++} -++#endif -++ -++/* -++ * WAIT_FOR_SETUP (OUTPKTRDY) -++ * - read data packet from EP0 FIFO -++ * - decode command -++ * - if error -++ * set USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND | USB_CSR0_SENDSTALL bits -++ * - else -++ * set USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND bits -++ */ -++static void jz4740_ep0_setup(struct jz4740_udc *dev, u32 csr) -++{ -++ struct jz4740_ep *ep = &dev->ep[0]; -++ struct usb_ctrlrequest ctrl; -++ int i; -++ -++ DEBUG_SETUP("%s: %x\n", __FUNCTION__, csr); -++ -++ /* Nuke all previous transfers */ -++ nuke(ep, -EPROTO); -++ -++ /* read control req from fifo (8 bytes) */ -++ jz4740_fifo_read(ep, (unsigned char *)&ctrl, 8); -++ -++ DEBUG_SETUP("SETUP %02x.%02x v%04x i%04x l%04x\n", -++ ctrl.bRequestType, ctrl.bRequest, -++ ctrl.wValue, ctrl.wIndex, ctrl.wLength); -++ -++ /* Set direction of EP0 */ -++ if (likely(ctrl.bRequestType & USB_DIR_IN)) { -++ ep->bEndpointAddress |= USB_DIR_IN; -++ } else { -++ ep->bEndpointAddress &= ~USB_DIR_IN; -++ } -++ -++ /* Handle some SETUP packets ourselves */ -++ switch (ctrl.bRequest) { -++ case USB_REQ_SET_ADDRESS: -++ if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) -++ break; -++ -++ DEBUG_SETUP("USB_REQ_SET_ADDRESS (%d)\n", ctrl.wValue); -++ udc_set_address(dev, ctrl.wValue); -++ usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); -++ return; -++ -++ case USB_REQ_SET_CONFIGURATION: -++ if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) -++ break; -++ -++ DEBUG_SETUP("USB_REQ_SET_CONFIGURATION (%d)\n", ctrl.wValue); -++ usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); -++ -++ /* Enable RESUME and SUSPEND interrupts */ -++ usb_setb(USB_REG_INTRUSBE, (USB_INTR_RESUME | USB_INTR_SUSPEND)); -++ break; -++ -++ case USB_REQ_SET_INTERFACE: -++ if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) -++ break; -++ -++ DEBUG_SETUP("USB_REQ_SET_INTERFACE (%d)\n", ctrl.wValue); -++ usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); -++ break; -++ -++// case USB_REQ_GET_STATUS: -++// if (jz4740_handle_get_status(dev, &ctrl) == 0) -++// return; -++ -++ case USB_REQ_CLEAR_FEATURE: -++ case USB_REQ_SET_FEATURE: -++ if (ctrl.bRequestType == USB_RECIP_ENDPOINT) { -++ struct jz4740_ep *qep; -++ int ep_num = (ctrl.wIndex & 0x0f); -++ -++ /* Support only HALT feature */ -++ if (ctrl.wValue != 0 || ctrl.wLength != 0 -++ || ep_num > 3 || ep_num < 1) -++ break; -++ -++ qep = &dev->ep[ep_num]; -++ spin_unlock(&dev->lock); -++ if (ctrl.bRequest == USB_REQ_SET_FEATURE) { -++ DEBUG_SETUP("SET_FEATURE (%d)\n", -++ ep_num); -++ jz4740_set_halt(&qep->ep, 1); -++ } else { -++ DEBUG_SETUP("CLR_FEATURE (%d)\n", -++ ep_num); -++ jz4740_set_halt(&qep->ep, 0); -++ } -++ spin_lock(&dev->lock); -++ -++ usb_set_index(0); -++ -++ /* Reply with a ZLP on next IN token */ -++ usb_setb(USB_REG_CSR0, -++ (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND)); -++ return; -++ } -++ break; -++ -++ default: -++ break; -++ } -++ -++ /* gadget drivers see class/vendor specific requests, -++ * {SET,GET}_{INTERFACE,DESCRIPTOR,CONFIGURATION}, -++ * and more. -++ */ -++ if (likely((u32)dev->driver)) { -++ /* device-2-host (IN) or no data setup command, process immediately */ -++ spin_unlock(&dev->lock); -++ -++ i = dev->driver->setup(&dev->gadget, &ctrl); -++ spin_lock(&dev->lock); -++ -++ if (unlikely(i < 0)) { -++ /* setup processing failed, force stall */ -++ DEBUG_SETUP -++ (" --> ERROR: gadget setup FAILED (stalling), setup returned %d\n", -++ i); -++ usb_set_index(0); -++ usb_setb(USB_REG_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND | USB_CSR0_SENDSTALL)); -++ -++ /* ep->stopped = 1; */ -++ dev->ep0state = WAIT_FOR_SETUP; -++ } -++ else { -++ DEBUG_SETUP("gadget driver setup ok (%d)\n", ctrl.wLength); -++ if (!ctrl.wLength) { -++ usb_setb(USB_REG_CSR0, USB_CSR0_SVDOUTPKTRDY); -++ } -++ } -++ } -++} -++ -++/* -++ * DATA_STATE_NEED_ZLP -++ */ -++static void jz4740_ep0_in_zlp(struct jz4740_udc *dev, u32 csr) -++{ -++ DEBUG_EP0("%s: %x\n", __FUNCTION__, csr); -++ -++ usb_setb(USB_REG_CSR0, (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND)); -++ dev->ep0state = WAIT_FOR_SETUP; -++} -++ -++/* -++ * handle ep0 interrupt -++ */ -++static void jz4740_handle_ep0(struct jz4740_udc *dev, u32 intr) -++{ -++ struct jz4740_ep *ep = &dev->ep[0]; -++ u32 csr; -++ -++ /* Set index 0 */ -++ usb_set_index(0); -++ csr = usb_readb(USB_REG_CSR0); -++ -++ DEBUG_EP0("%s: csr = %x state = \n", __FUNCTION__, csr);//, state_names[dev->ep0state]); -++ -++ /* -++ * if SENT_STALL is set -++ * - clear the SENT_STALL bit -++ */ -++ if (csr & USB_CSR0_SENTSTALL) { -++ DEBUG_EP0("%s: USB_CSR0_SENTSTALL is set: %x\n", __FUNCTION__, csr); -++ usb_clearb(USB_REG_CSR0, USB_CSR0_SENDSTALL | USB_CSR0_SENTSTALL); -++ nuke(ep, -ECONNABORTED); -++ dev->ep0state = WAIT_FOR_SETUP; -++ return; -++ } -++ -++ /* -++ * if a transfer is in progress && INPKTRDY and OUTPKTRDY are clear -++ * - fill EP0 FIFO -++ * - if last packet -++ * - set IN_PKT_RDY | DATA_END -++ * - else -++ * set IN_PKT_RDY -++ */ -++ if (!(csr & (USB_CSR0_INPKTRDY | USB_CSR0_OUTPKTRDY))) { -++ DEBUG_EP0("%s: INPKTRDY and OUTPKTRDY are clear\n", -++ __FUNCTION__); -++ -++ switch (dev->ep0state) { -++ case DATA_STATE_XMIT: -++ DEBUG_EP0("continue with DATA_STATE_XMIT\n"); -++ jz4740_ep0_in(dev, csr); -++ return; -++ case DATA_STATE_NEED_ZLP: -++ DEBUG_EP0("continue with DATA_STATE_NEED_ZLP\n"); -++ jz4740_ep0_in_zlp(dev, csr); -++ return; -++ default: -++ /* Stall? */ -++// DEBUG_EP0("Odd state!! state = %s\n", -++// state_names[dev->ep0state]); -++ dev->ep0state = WAIT_FOR_SETUP; -++ /* nuke(ep, 0); */ -++ /* usb_setb(ep->csr, USB_CSR0_SENDSTALL); */ -++// break; -++ return; -++ } -++ } -++ -++ /* -++ * if SETUPEND is set -++ * - abort the last transfer -++ * - set SERVICED_SETUP_END_BIT -++ */ -++ if (csr & USB_CSR0_SETUPEND) { -++ DEBUG_EP0("%s: USB_CSR0_SETUPEND is set: %x\n", __FUNCTION__, csr); -++ -++ usb_setb(USB_REG_CSR0, USB_CSR0_SVDSETUPEND); -++ nuke(ep, 0); -++ dev->ep0state = WAIT_FOR_SETUP; -++ } -++ -++ /* -++ * if USB_CSR0_OUTPKTRDY is set -++ * - read data packet from EP0 FIFO -++ * - decode command -++ * - if error -++ * set SVDOUTPKTRDY | DATAEND | SENDSTALL bits -++ * - else -++ * set SVDOUTPKTRDY | DATAEND bits -++ */ -++ if (csr & USB_CSR0_OUTPKTRDY) { -++ -++ DEBUG_EP0("%s: EP0_OUT_PKT_RDY is set: %x\n", __FUNCTION__, -++ csr); -++ -++ switch (dev->ep0state) { -++ case WAIT_FOR_SETUP: -++ DEBUG_EP0("WAIT_FOR_SETUP\n"); -++ jz4740_ep0_setup(dev, csr); -++ break; -++ -++ case DATA_STATE_RECV: -++ DEBUG_EP0("DATA_STATE_RECV\n"); -++ jz4740_ep0_out(dev, csr); -++ break; -++ -++ default: -++ /* send stall? */ -++ DEBUG_EP0("strange state!! 2. send stall? state = %d\n", -++ dev->ep0state); -++ break; -++ } -++ } -++} -++ -++static void jz4740_ep0_kick(struct jz4740_udc *dev, struct jz4740_ep *ep) -++{ -++ u32 csr; -++ -++ usb_set_index(0); -++ csr = usb_readb(USB_REG_CSR0); -++ -++ DEBUG_EP0("%s: %x\n", __FUNCTION__, csr); -++ -++ /* Clear "out packet ready" */ -++ usb_setb(USB_REG_CSR0, USB_CSR0_SVDOUTPKTRDY); -++ -++ if (ep_is_in(ep)) { -++ dev->ep0state = DATA_STATE_XMIT; -++ jz4740_ep0_in(dev, csr); -++ } else { -++ dev->ep0state = DATA_STATE_RECV; -++ jz4740_ep0_out(dev, csr); -++ } -++} -++ -++/** Handle USB RESET interrupt -++ */ -++static void jz4740_reset_irq(struct jz4740_udc *dev) -++{ -++ dev->gadget.speed = (usb_readb(USB_REG_POWER) & USB_POWER_HSMODE) ? -++ USB_SPEED_HIGH : USB_SPEED_FULL; -++ -++ DEBUG_SETUP("%s: address = %d, speed = %s\n", __FUNCTION__, dev->usb_address, -++ (dev->gadget.speed == USB_SPEED_HIGH) ? "HIGH":"FULL" ); -++} -++ -++/* -++ * jz4740 usb device interrupt handler. -++ */ -++static irqreturn_t jz4740_udc_irq(int irq, void *_dev) -++{ -++ struct jz4740_udc *dev = _dev; -++ -++ u32 intr_usb = usb_readb(USB_REG_INTRUSB) & 0x7; /* mask SOF */ -++ u32 intr_in = usb_readw(USB_REG_INTRIN); -++ u32 intr_out = usb_readw(USB_REG_INTROUT); -++ u32 intr_dma = usb_readb(USB_REG_INTR); -++ -++ if (!intr_usb && !intr_in && !intr_out && !intr_dma) -++ return IRQ_HANDLED; -++ -++ DEBUG("intr_out = %x intr_in=%x intr_usb=%x\n", -++ intr_out, intr_in, intr_usb); -++ -++ spin_lock(&dev->lock); -++ -++ /* Check for resume from suspend mode */ -++ if ((intr_usb & USB_INTR_RESUME) && -++ (usb_readb(USB_REG_INTRUSBE) & USB_INTR_RESUME)) { -++ DEBUG("USB resume\n"); -++ } -++ -++ /* Check for system interrupts */ -++ if (intr_usb & USB_INTR_RESET) { -++ DEBUG("USB reset\n"); -++#ifdef CONFIG_JZ_UDC_HOTPLUG -++ jz_udc_active = 1; -++#endif -++ if (udc_debug) { -++ /* We have tested the cable type, disable module and -++ * disconnect from host right now. -++ */ -++ udc_disable(dev); -++ spin_unlock(&dev->lock); -++ return IRQ_HANDLED; -++ } -++ jz4740_reset_irq(dev); -++ } -++ -++ /* Check for endpoint 0 interrupt */ -++ if (intr_in & USB_INTR_EP0) { -++ DEBUG("USB_INTR_EP0 (control)\n"); -++ jz4740_handle_ep0(dev, intr_in); -++ } -++ -++ /* Check for Bulk-IN DMA interrupt */ -++ if (intr_dma & 0x1) { -++ int ep_num; -++ ep_num = (usb_readl(USB_REG_CNTL1) >> 4) & 0xf; -++ jz4740_in_epn(dev, ep_num, intr_in); -++ } -++ -++ /* Check for Bulk-OUT DMA interrupt */ -++ if (intr_dma & 0x2) { -++ int ep_num; -++ ep_num = (usb_readl(USB_REG_CNTL2) >> 4) & 0xf; -++ jz4740_out_epn(dev, ep_num, intr_out); -++ } -++ -++ /* Check for each configured endpoint interrupt */ -++ if (intr_in & USB_INTR_INEP1) { -++ DEBUG("USB_INTR_INEP1\n"); -++ jz4740_in_epn(dev, 1, intr_in); -++ } -++ -++ if (intr_in & USB_INTR_INEP2) { -++ DEBUG("USB_INTR_INEP2\n"); -++ jz4740_in_epn(dev, 2, intr_in); -++ } -++ -++ if (intr_out & USB_INTR_OUTEP1) { -++ DEBUG("USB_INTR_OUTEP1\n"); -++ jz4740_out_epn(dev, 1, intr_out); -++ } -++ -++ /* Check for suspend mode */ -++ if ((intr_usb & USB_INTR_SUSPEND) && -++ (usb_readb(USB_REG_INTRUSBE) & USB_INTR_SUSPEND)) { -++ DEBUG("USB suspend\n"); -++ dev->driver->suspend(&dev->gadget); -++ /* Host unloaded from us, can do something, such as flushing -++ the NAND block cache etc. */ -++ } -++ -++#ifdef CONFIG_JZ_UDC_HOTPLUG -++ jz_udc_active = 1; -++#endif -++ -++ spin_unlock(&dev->lock); -++ return IRQ_HANDLED; -++} -++ -++/*-------------------------------------------------------------------------*/ -++ -++static int jz4740_udc_get_frame(struct usb_gadget *_gadget) -++{ -++ DEBUG("%s, %p\n", __FUNCTION__, _gadget); -++ return usb_readw(USB_REG_FRAME); -++} -++ -++static int jz4740_udc_wakeup(struct usb_gadget *_gadget) -++{ -++ /* host may not have enabled remote wakeup */ -++ /*if ((UDCCS0 & UDCCS0_DRWF) == 0) -++ return -EHOSTUNREACH; -++ udc_set_mask_UDCCR(UDCCR_RSM); */ -++ return -ENOTSUPP; -++} -++ -++static const struct usb_gadget_ops jz4740_udc_ops = { -++ .get_frame = jz4740_udc_get_frame, -++ .wakeup = jz4740_udc_wakeup, -++ /* current versions must always be self-powered */ -++}; -++ -++/*-------------------------------------------------------------------------*/ -++ -++static struct jz4740_udc udc_dev = { -++ .usb_address = 0, -++ -++ .gadget = { -++ .ops = &jz4740_udc_ops, -++ .ep0 = &udc_dev.ep[0].ep, -++ .name = driver_name, -++ .dev = { -++ .bus_id = "gadget", -++ }, -++ }, -++ -++ /* control endpoint */ -++ .ep[0] = { -++ .ep = { -++ .name = ep0name, -++ .ops = &jz4740_ep_ops, -++ .maxpacket = EP0_MAXPACKETSIZE, -++ }, -++ .dev = &udc_dev, -++ -++ .bEndpointAddress = 0, -++ .bmAttributes = 0, -++ -++ .ep_type = ep_control, -++ .fifo = USB_FIFO_EP0, -++ .csr = USB_REG_CSR0, -++ }, -++ -++ /* bulk out endpoint */ -++ .ep[1] = { -++ .ep = { -++ .name = "ep1out-bulk", -++ .ops = &jz4740_ep_ops, -++ .maxpacket = EPBULK_MAXPACKETSIZE, -++ }, -++ .dev = &udc_dev, -++ -++ .bEndpointAddress = 1, -++ .bmAttributes = USB_ENDPOINT_XFER_BULK, -++ -++ .ep_type = ep_bulk_out, -++ .fifo = USB_FIFO_EP1, -++ .csr = USB_REG_OUTCSR, -++ }, -++ -++ /* bulk in endpoint */ -++ .ep[2] = { -++ .ep = { -++ .name = "ep1in-bulk", -++ .ops = &jz4740_ep_ops, -++ .maxpacket = EPBULK_MAXPACKETSIZE, -++ }, -++ .dev = &udc_dev, -++ -++ .bEndpointAddress = USB_DIR_IN | 1, -++ .bmAttributes = USB_ENDPOINT_XFER_BULK, -++ -++ .ep_type = ep_bulk_in, -++ .fifo = USB_FIFO_EP1, -++ .csr = USB_REG_INCSR, -++ }, -++ -++ /* interrupt in endpoint */ -++ .ep[3] = { -++ .ep = { -++ .name = "ep2in-int", -++ .ops = &jz4740_ep_ops, -++ .maxpacket = EPINTR_MAXPACKETSIZE, -++ }, -++ .dev = &udc_dev, -++ -++ .bEndpointAddress = USB_DIR_IN | 2, -++ .bmAttributes = USB_ENDPOINT_XFER_INT, -++ -++ .ep_type = ep_interrupt, -++ .fifo = USB_FIFO_EP2, -++ .csr = USB_REG_INCSR, -++ }, -++}; -++ -++static int jz4740_udc_probe(struct platform_device *pdev) -++{ -++ struct jz4740_udc *dev = &udc_dev; -++ int rc; -++ -++ DEBUG("%s\n", __FUNCTION__); -++ -++ spin_lock_init(&dev->lock); -++ the_controller = dev; -++ -++ dev->dev = &pdev->dev; -++ device_initialize(&dev->gadget.dev); -++ dev->gadget.dev.parent = &pdev->dev; -++ -++// strcpy (dum->gadget.dev.bus_id, "gadget"); -++ dev->gadget.dev.release = jz4740_udc_release; -++ if ((rc = device_register (&dev->gadget.dev)) < 0) -++ return rc; -++ platform_set_drvdata(pdev, dev); -++ -++ udc_disable(dev); -++ udc_reinit(dev); -++ -++ /* irq setup */ -++ if (request_irq(IRQ_UDC, jz4740_udc_irq, IRQF_DISABLED,//SA_SHIRQ/*|SA_SAMPLE_RANDOM*/, -++ driver_name, dev) != 0) { -++ printk(KERN_INFO "request UDC interrupt %d failed\n", IRQ_UDC); -++ return -EBUSY; -++ } -++ -++ printk(KERN_INFO "%s\n", driver_desc); -++ printk(KERN_INFO "version: " DRIVER_VERSION "\n"); -++ -++ return 0; -++} -++ -++static int jz4740_udc_remove(struct platform_device *pdev) -++{ -++ struct jz4740_udc *dev = platform_get_drvdata(pdev); -++ DEBUG("%s: %p\n", __FUNCTION__, dev); -++ -++ if (dev->driver) -++ return -EBUSY; -++ -++ udc_disable(dev); -++#ifdef UDC_PROC_FILE -++ remove_proc_entry(proc_node_name, NULL); -++#endif -++ -++ free_irq(IRQ_UDC, dev); -++ platform_set_drvdata(pdev, 0); -++ device_unregister(&dev->gadget.dev); -++ the_controller = 0; -++ -++ return 0; -++} -++ -++static struct platform_driver udc_driver = { -++ .probe = jz4740_udc_probe, -++ .remove = jz4740_udc_remove, -++ .suspend = NULL, -++ .resume = NULL, -++ .driver = { -++ .name = (char *) driver_name, -++ .owner = THIS_MODULE, -++ }, -++}; -++ -++ -++ -++static struct platform_device the_udc_pdev = { -++ .name = (char *) gadget_name, -++ .id = -1, -++ .dev = { -++ .release = jz4740_udc_release, -++ }, -++}; -++ -++ -++/*-------------------------------------------------------------------------*/ -++ -++static int __init udc_init (void) -++{ -++ platform_driver_register(&udc_driver); -++ return platform_device_register (&the_udc_pdev); -++} -++ -++static void __exit udc_exit (void) -++{ -++ platform_driver_unregister(&udc_driver); -++ platform_device_unregister(&the_udc_pdev); -++} -++ -++module_init(udc_init); -++module_exit(udc_exit); -++ -++MODULE_DESCRIPTION(DRIVER_DESC); -++MODULE_AUTHOR("Wei Jianli "); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/drivers/usb/gadget/jz4740_udc.h linux-2.6.24.7/drivers/usb/gadget/jz4740_udc.h -+--- linux-2.6.24.7.old/drivers/usb/gadget/jz4740_udc.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/usb/gadget/jz4740_udc.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,112 @@ -++/* -++ * linux/drivers/usb/gadget/jz4740_udc.h -++ * -++ * Ingenic JZ4740 on-chip high speed USB device controller -++ * -++ * Copyright (C) 2006 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ */ -++ -++#ifndef __USB_GADGET_JZ4740_H__ -++#define __USB_GADGET_JZ4740_H__ -++ -++/*-------------------------------------------------------------------------*/ -++ -++// Max packet size -++#define EP0_MAXPACKETSIZE 64 -++#define EPBULK_MAXPACKETSIZE 512 -++#define EPINTR_MAXPACKETSIZE 64 -++ -++#define UDC_MAX_ENDPOINTS 4 -++ -++/*-------------------------------------------------------------------------*/ -++ -++typedef enum ep_type { -++ ep_control, ep_bulk_in, ep_bulk_out, ep_interrupt -++} ep_type_t; -++ -++struct jz4740_ep { -++ struct usb_ep ep; -++ struct jz4740_udc *dev; -++ -++ const struct usb_endpoint_descriptor *desc; -++ struct list_head queue; -++ unsigned long pio_irqs; -++ -++ u8 stopped; -++ u8 bEndpointAddress; -++ u8 bmAttributes; -++ -++ ep_type_t ep_type; -++ u32 fifo; -++ u32 csr; -++ -++ u32 reg_addr; -++}; -++ -++struct jz4740_request { -++ struct usb_request req; -++ struct list_head queue; -++}; -++ -++enum ep0state { -++ WAIT_FOR_SETUP, /* between STATUS ack and SETUP report */ -++ DATA_STATE_XMIT, /* data tx stage */ -++ DATA_STATE_NEED_ZLP, /* data tx zlp stage */ -++ WAIT_FOR_OUT_STATUS, /* status stages */ -++ DATA_STATE_RECV, /* data rx stage */ -++}; -++ -++struct jz4740_udc { -++ struct usb_gadget gadget; -++ struct usb_gadget_driver *driver; -++ struct device *dev; -++ spinlock_t lock; -++ -++ enum ep0state ep0state; -++ struct jz4740_ep ep[UDC_MAX_ENDPOINTS]; -++ -++ unsigned char usb_address; -++}; -++ -++extern struct jz4740_udc *the_controller; -++ -++#define ep_is_in(EP) (((EP)->bEndpointAddress&USB_DIR_IN)==USB_DIR_IN) -++#define ep_maxpacket(EP) ((EP)->ep.maxpacket) -++#define ep_index(EP) ((EP)->bEndpointAddress&0xF) -++#define usb_set_index(i) (REG8(USB_REG_INDEX) = (i)) -++ -++/*-------------------------------------------------------------------------*/ -++ -++/* 2.5 stuff that's sometimes missing in 2.4 */ -++ -++#ifndef container_of -++#define container_of list_entry -++#endif -++ -++#ifndef likely -++#define likely(x) (x) -++#define unlikely(x) (x) -++#endif -++ -++#ifndef BUG_ON -++#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0) -++#endif -++ -++#ifndef WARN_ON -++#define WARN_ON(x) do { } while (0) -++#endif -++ -++#ifndef IRQ_NONE -++typedef void irqreturn_t; -++#define IRQ_NONE -++#define IRQ_HANDLED -++#define IRQ_RETVAL(x) -++#endif -++ -++#endif /* __USB_GADGET_JZ4740_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/usb/host/ohci-hcd.c linux-2.6.24.7/drivers/usb/host/ohci-hcd.c -+--- linux-2.6.24.7.old/drivers/usb/host/ohci-hcd.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/usb/host/ohci-hcd.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -977,6 +977,11 @@ -+ #define PCI_DRIVER ohci_pci_driver -+ #endif -+ -++#ifdef CONFIG_JZSOC -++#include "ohci-jz.c" -++#define PLATFORM_DRIVER ohci_hcd_jz_driver -++#endif -++ -+ #ifdef CONFIG_SA1111 -+ #include "ohci-sa1111.c" -+ #define SA1111_DRIVER ohci_hcd_sa1111_driver -+diff -urN linux-2.6.24.7.old/drivers/usb/host/ohci-jz.c linux-2.6.24.7/drivers/usb/host/ohci-jz.c -+--- linux-2.6.24.7.old/drivers/usb/host/ohci-jz.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/usb/host/ohci-jz.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,260 @@ -++/* -++ * OHCI HCD (Host Controller Driver) for USB. -++ * -++ * (C) Copyright 1999 Roman Weissgaerber -++ * (C) Copyright 2000-2002 David Brownell -++ * (C) Copyright 2002 Hewlett-Packard Company -++ * -++ * Bus Glue for Ingenic Jz47xx. -++ * -++ * Written by Christopher Hoover -++ * Based on fragments of previous driver by Rusell King et al. -++ * -++ * Modified for LH7A404 from ohci-sa1111.c -++ * by Durgesh Pattamatta -++ * Modified for AMD Alchemy Au1xxx -++ * by Matt Porter -++ * Modified for Jz47xx from ohci-au1xxx.c -++ * by Peter -++ * -++ * This file is licenced under the GPL. -++ */ -++ -++#include -++#include -++ -++#include -++ -++extern int usb_disabled(void); -++ -++/*-------------------------------------------------------------------------*/ -++ -++static void jz_start_ohc(struct platform_device *dev) -++{ -++ printk(KERN_DEBUG __FILE__ -++ ": starting JZ OHCI USB Controller\n"); -++ -++ /* enable host controller */ -++ __cpm_start_uhc(); -++ -++#ifdef CONFIG_SOC_JZ4750 -++ __cpm_enable_uhcphy(); -++#endif -++ -++ printk(KERN_DEBUG __FILE__ -++ ": Clock to USB host has been enabled \n"); -++} -++ -++static void jz_stop_ohc(struct platform_device *dev) -++{ -++ printk(KERN_DEBUG __FILE__ -++ ": stopping JZ OHCI USB Controller\n"); -++ -++#ifdef CONFIG_SOC_JZ4750 -++ __cpm_suspend_uhcphy(); -++#endif -++ -++ __cpm_stop_uhc(); -++} -++ -++ -++/*-------------------------------------------------------------------------*/ -++ -++/* configure so an HC device and id are always provided */ -++/* always called with process context; sleeping is OK */ -++ -++ -++/** -++ * usb_ohci_jz_probe - initialize Jz-based HCDs -++ * Context: !in_interrupt() -++ * -++ * Allocates basic resources for this USB host controller, and -++ * then invokes the start() method for the HCD associated with it -++ * through the hotplug entry's driver_data. -++ * -++ */ -++static int usb_ohci_jz_probe(const struct hc_driver *driver, -++ struct platform_device *dev) -++{ -++ int retval; -++ struct usb_hcd *hcd; -++ -++ if (dev->resource[1].flags != IORESOURCE_IRQ) { -++ pr_debug("resource[1] is not IORESOURCE_IRQ\n"); -++ return -ENOMEM; -++ } -++ -++ hcd = usb_create_hcd(driver, &dev->dev, "jz"); -++ if (!hcd) -++ return -ENOMEM; -++ hcd->rsrc_start = dev->resource[0].start; -++ hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; -++ -++ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { -++ pr_debug("request_mem_region failed\n"); -++ retval = -EBUSY; -++ goto err1; -++ } -++ -++ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); -++ if (!hcd->regs) { -++ pr_debug("ioremap failed\n"); -++ retval = -ENOMEM; -++ goto err2; -++ } -++ -++ jz_start_ohc(dev); -++ ohci_hcd_init(hcd_to_ohci(hcd)); -++ -++ retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED | IRQF_SHARED); -++ if (retval == 0) -++ return retval; -++ -++ jz_stop_ohc(dev); -++ iounmap(hcd->regs); -++ err2: -++ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -++ err1: -++ usb_put_hcd(hcd); -++ return retval; -++} -++ -++ -++/* may be called without controller electrically present */ -++/* may be called with controller, bus, and devices active */ -++ -++/** -++ * usb_hcd_jz_remove - shutdown processing for Jz-based HCDs -++ * @dev: USB Host Controller being removed -++ * Context: !in_interrupt() -++ * -++ * Reverses the effect of usb_hcd_jz_probe(), first invoking -++ * the HCD's stop() method. It is always called from a thread -++ * context, normally "rmmod", "apmd", or something similar. -++ * -++ */ -++static void usb_ohci_jz_remove(struct usb_hcd *hcd, struct platform_device *dev) -++{ -++ usb_remove_hcd(hcd); -++ jz_stop_ohc(dev); -++ iounmap(hcd->regs); -++ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -++ usb_put_hcd(hcd); -++} -++ -++/*-------------------------------------------------------------------------*/ -++ -++static int __devinit -++ohci_jz_start (struct usb_hcd *hcd) -++{ -++ struct ohci_hcd *ohci = hcd_to_ohci (hcd); -++ int ret; -++ -++ ohci_dbg (ohci, "ohci_jz_start, ohci:%p", ohci); -++ -++ if ((ret = ohci_init (ohci)) < 0) -++ return ret; -++ -++ if ((ret = ohci_run (ohci)) < 0) { -++ err ("can't start %s", hcd->self.bus_name); -++ ohci_stop (hcd); -++ return ret; -++ } -++ -++ return 0; -++} -++ -++/*-------------------------------------------------------------------------*/ -++ -++static const struct hc_driver ohci_jz_hc_driver = { -++ .description = hcd_name, -++ .product_desc = "JZ OHCI", -++ .hcd_priv_size = sizeof(struct ohci_hcd), -++ -++ /* -++ * generic hardware linkage -++ */ -++ .irq = ohci_irq, -++ .flags = HCD_USB11 | HCD_MEMORY, -++ -++ /* -++ * basic lifecycle operations -++ */ -++ .start = ohci_jz_start, -++ .stop = ohci_stop, -++ .shutdown = ohci_shutdown, -++ -++ /* -++ * managing i/o requests and associated device resources -++ */ -++ .urb_enqueue = ohci_urb_enqueue, -++ .urb_dequeue = ohci_urb_dequeue, -++ .endpoint_disable = ohci_endpoint_disable, -++ -++ /* -++ * scheduling support -++ */ -++ .get_frame_number = ohci_get_frame, -++ -++ /* -++ * root hub support -++ */ -++ .hub_status_data = ohci_hub_status_data, -++ .hub_control = ohci_hub_control, -++ .hub_irq_enable = ohci_rhsc_enable, -++#ifdef CONFIG_PM -++ .bus_suspend = ohci_bus_suspend, -++ .bus_resume = ohci_bus_resume, -++#endif -++ .start_port_reset = ohci_start_port_reset, -++}; -++ -++/*-------------------------------------------------------------------------*/ -++ -++static int ohci_hcd_jz_drv_probe(struct platform_device *pdev) -++{ -++ int ret; -++ -++ pr_debug ("In ohci_hcd_jz_drv_probe"); -++ -++ if (usb_disabled()) -++ return -ENODEV; -++ -++ ret = usb_ohci_jz_probe(&ohci_jz_hc_driver, pdev); -++ return ret; -++} -++ -++static int ohci_hcd_jz_drv_remove(struct platform_device *pdev) -++{ -++ struct usb_hcd *hcd = platform_get_drvdata(pdev); -++ -++ usb_ohci_jz_remove(hcd, pdev); -++ return 0; -++} -++ /*TBD*/ -++/*static int ohci_hcd_jz_drv_suspend(struct platform_device *dev) -++{ -++ struct usb_hcd *hcd = platform_get_drvdata(dev); -++ -++ return 0; -++} -++static int ohci_hcd_jz_drv_resume(struct platform_device *dev) -++{ -++ struct usb_hcd *hcd = platform_get_drvdata(dev); -++ -++ return 0; -++} -++*/ -++ -++static struct platform_driver ohci_hcd_jz_driver = { -++ .probe = ohci_hcd_jz_drv_probe, -++ .remove = ohci_hcd_jz_drv_remove, -++ .shutdown = usb_hcd_platform_shutdown, -++ /*.suspend = ohci_hcd_jz_drv_suspend, */ -++ /*.resume = ohci_hcd_jz_drv_resume, */ -++ .driver = { -++ .name = "jz-ohci", -++ .owner = THIS_MODULE, -++ }, -++}; -++ -+diff -urN linux-2.6.24.7.old/drivers/video/Kconfig linux-2.6.24.7/drivers/video/Kconfig -+--- linux-2.6.24.7.old/drivers/video/Kconfig 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/video/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -201,6 +201,222 @@ -+ comment "Frame buffer hardware drivers" -+ depends on FB -+ -++config FB_JZSOC -++ tristate "JZSOC LCD controller support" -++ depends on FB && JZSOC -++ select FB_CFB_FILLRECT -++ select FB_CFB_COPYAREA -++ select FB_CFB_IMAGEBLIT -++ ---help--- -++ JZSOC LCD Controller and Smart LCD Controller driver support. -++ -++config FB_JZ4740_SLCD -++ tristate "JZ4740 Smart LCD controller support" -++ depends on FB_JZSOC && SOC_JZ4740 -++ default n -++ ---help--- -++ This is the frame buffer device driver for the JZ4740 Smart LCD controller. -++ If select this, please set to . -++ -++choice -++ depends on FB_JZ4740_SLCD -++ prompt "SLCD Panel" -++ default JZ_SLCD_LGDP4551_8BUS -++ -++config JZ_SLCD_LGDP4551 -++ bool "LG LGDP4551 Smart LCD panel" -++ ---help--- -++ Driver for Smart LCD LGDP4551, 8-bit sytem interface, 16BPP. -++ -++config JZ_SLCD_SPFD5420A -++ bool "SPFD5420A Smart LCD panel" -++ ---help--- -++ Driver for Smart LCD SPFD5420A 18-bit sytem interface, 18BPP. -++ -++config JZ_SLCD_TRULY -++ bool "TRULY Smart LCD panel (MAX Pixels 400x240)" -++ ---help--- -++ -++endchoice -++ -++config FB_JZLCD_4730_4740 -++ tristate "JZ4730 JZ4740 LCD controller support" -++ depends on FB_JZSOC && (SOC_JZ4730 || SOC_JZ4740) -++ help -++ This is the frame buffer device driver for the JZ4730 and JZ4740 LCD controller. -++config JZLCD_FRAMEBUFFER_MAX -++ int "Default FrameBuffer num" -++ depends on FB_JZLCD_4730_4740 -++ default "1" -++ ---help--- -++ JZ LCD driver support multi-framebuffers for video applications. -++config JZLCD_FRAMEBUFFER_ROTATE_SUPPORT -++ bool "JZLCD FrameBuffer Rotate Support(For TEST)" -++ depends on FB_JZLCD_4730_4740 -++ default n -++ ---help--- -++ JZ LCD driver framebuffer rotate support. Rotate angle can be 0,90,180,270. -++ Note, this fearture is implemented by software, and will cost a lot of cpu capcity. -++ That is to say, if you select this function, you system will become slowly. -++ Rotate cost cpu about: -++ ratate angle 0'C: 0% cpu -++ ratate angle 90'C: 40% cpu -++ ratate angle 180'C: 20% cpu -++ ratate angle 270'C: 40% cpu -++ -++config JZLCD_FRAMEBUFFER_DEFAULT_ROTATE_ANGLE -++ int "FrameBuffer default rotate angle" -++ depends on JZLCD_FRAMEBUFFER_ROTATE_SUPPORT -++ default 0 -++ ---help--- -++ JZ LCD driver framebuffer angle value can be: -++ 0: 0'C -++ 1: 90'C -++ 2: 180'C -++ 3: 270'C -++config JZLCD_FRAMEBUFFER_BPP -++ int "FrameBuffer bit per pixel" -++ depends on JZLCD_FRAMEBUFFER_ROTATE_SUPPORT -++ default 32 -++ ---help--- -++ JZ LCD driver framebuffer support 8bpp, 16bpp, 32bpp -++choice -++ depends on FB_JZLCD_4730_4740 -++ prompt "LCD Panel" -++ default JZLCD_SAMSUNG_LTP400WQF01 -++ -++config JZLCD_SHARP_LQ035Q7 -++ bool "SHARP LQ035Q7 TFT panel (240x320)" -++ -++config JZLCD_SAMSUNG_LTS350Q1 -++ bool "SAMSUNG LTS350Q1 TFT panel (240x320)" -++ -++config JZLCD_SAMSUNG_LTV350QVF04 -++ bool "SAMSUNG LTV350QV_F04 TFT panel (320x240)" -++ -++config JZLCD_SAMSUNG_LTP400WQF01 -++ bool "SAMSUNG LTP400WQF01 TFT panel (480x272)(16bits)" -++ -++config JZLCD_SAMSUNG_LTP400WQF02 -++ bool "SAMSUNG LTP400WQF02 TFT panel (480x272)(18bits)" -++ -++config JZLCD_AUO_A030FL01_V1 -++ bool "AUO A030FL01_V1 TFT panel (480x272)" -++ -++config JZLCD_TRULY_TFTG320240DTSW -++ bool "TRULY TFTG320240DTSW TFT panel (320x240)" -++ -++config JZLCD_TRULY_TFTG320240DTSW_SERIAL -++ bool "TRULY TFTG320240DTSW TFT panel (320x240)(8bit-serial mode)" -++ -++config JZLCD_TRULY_TFTG240320UTSW_63W_E -++ bool "TRULY TFTG240320UTSW-63W-E TFT panel (240x320,2.5in)" -++ -++config JZLCD_FOXCONN_PT035TN01 -++ bool "FOXCONN PT035TN01 TFT panel (320x240)" -++ -++config JZLCD_INNOLUX_PT035TN01_SERIAL -++ bool "INNOLUX PT035TN01 TFT panel (320x240,3.5in)(8bit-serial mode)" -++ -++config JZLCD_TOSHIBA_LTM084P363 -++ bool "Toshiba LTM084P363 TFT panel (800x600)" -++ -++config JZLCD_HYNIX_HT10X21 -++ bool "Hynix HT10X21_300 TFT panel (1024x768)" -++ -++config JZLCD_INNOLUX_AT080TN42 -++ bool "INNOLUX AT080TN42 TFT panel (800x600)" -++ -++config JZLCD_CSTN_800x600 -++ bool "800x600 colorDSTN panel" -++ -++config JZLCD_CSTN_320x240 -++ bool "320x240 colorSTN panel" -++ -++config JZLCD_MSTN_480x320 -++ bool "480x320 monoSTN panel" -++ -++config JZLCD_MSTN_320x240 -++ bool "320x240 monoSTN panel" -++ -++config JZLCD_MSTN_240x128 -++ bool "240x128 monoSTN panel" -++ -++config JZLCD_MSTN_INVERSE -++ bool "Use an inverse color display." -++ depends on (JZLCD_MSTN_480x320 || JZLCD_MSTN_240x128) -++ -++endchoice -++ -++ -++config FB_JZ4750_TVE -++ tristate -++ depends on FB_JZSOC && SOC_JZ4750 -++ default n -++ -++config IPU_JZ4750 -++ bool "Jz4750 ipu support" -++ depends on FB_JZSOC && SOC_JZ4750 -++ ---help--- -++ Use JZ4750 IPU, if need, please select this. -++ -++config FB_JZ4750_LCD -++ tristate "JZ4750 LCD Controller support" -++ depends on FB_JZSOC && SOC_JZ4750 -++ select FB_JZ4750_TVE -++ ---help--- -++ JZ4750 LCD Controller driver. -++ JZ4750 LCD Controller support OSD function(refer jz4750_lcdc_spec.pdf).JZ4750 LCD OSD implement 2 framebuffer layers: foreground0 and foreground1. JZ4750 LCD driver support only foreground0 default. -++ -++config FB_JZ4750_LCD_USE_2LAYER_FRAMEBUFFER -++ bool "JZ4750 LCD driver 2 layers framebuffer support." -++ depends on FB_JZ4750_LCD -++ ---help--- -++ JZ4750 LCD driver support only foreground0 by default. -++ If you need both foreground0 and foreground1, please select this. -++ -++config FB_JZ4750_SLCD -++ bool -++ depends on FB_JZ4750_LCD -++ default n -++ -++choice -++ depends on FB_JZ4750_LCD -++ prompt "JZ4750 LCD Panels Support" -++ default JZ4750_LCD_SAMSUNG_LTP400WQF02 -++ ---help--- -++ Please select the lcd panel in you board -++ -++config JZ4750_LCD_SAMSUNG_LTP400WQF01 -++ bool "SAMSUNG LTP400WQF01 TFT panel (480x272)(16bits)" -++ -++config JZ4750_LCD_SAMSUNG_LTP400WQF02 -++ bool "SAMSUNG LTP400WQF02 TFT panel (480x272)(18bits)" -++ -++config JZ4750_LCD_AUO_A043FL01V2 -++ bool "AUO A043FL01V2 TFT panel (480x272)(24bits)" -++ -++config JZ4750_LCD_FOXCONN_PT035TN01 -++ bool "FOXCONN PT035TN01 TFT panel (320x240,3.5in)(18bit-parallel mode)" -++ -++config JZ4750_LCD_INNOLUX_PT035TN01_SERIAL -++ bool "INNOLUX PT035TN01 TFT panel (320x240,3.5in)(8bit-serial mode)" -++ -++config JZ4750_LCD_TOPPOLY_TD025THEA7_RGB_DELTA -++ bool "TOPPOLY_TD025THEA7 TFT panel(320x240)(serial RGB delta mode)" -++ -++config JZ4750_LCD_TRULY_TFTG320240DTSW_18BIT -++ bool "TRULY_TFTG320240DTSW TFT panel (320x240) (Parallel 18bit mode)" -++ -++config JZ4750_LCD_TRULY_TFT_GG1P0319LTSW_W -++ bool "TRULY_TFT_GG1P0319LTSW_W (240x320) (Smart LCD 16bit)" -++ -++config JZ4750_SLCD_KGM701A3_TFT_SPFD5420A -++ bool "KGM701A3_TFT_SPFD5420A (400x240) (Smart LCD 18bit)" -++ select FB_JZ4750_SLCD -++endchoice -++ -++ -+ config FB_CIRRUS -+ tristate "Cirrus Logic support" -+ depends on FB && (ZORRO || PCI) -+diff -urN linux-2.6.24.7.old/drivers/video/Makefile linux-2.6.24.7/drivers/video/Makefile -+--- linux-2.6.24.7.old/drivers/video/Makefile 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/video/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -28,6 +28,10 @@ -+ obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o -+ -+ # Hardware specific drivers go first -++obj-$(CONFIG_FB_JZLCD_4730_4740) += jzlcd.o -++obj-$(CONFIG_FB_JZ4740_SLCD) += jz4740_slcd.o -++obj-$(CONFIG_FB_JZ4750_LCD) += jz4750_lcd.o -++obj-$(CONFIG_FB_JZ4750_TVE) += jz4750_tve.o -+ obj-$(CONFIG_FB_AMIGA) += amifb.o c2p.o -+ obj-$(CONFIG_FB_ARC) += arcfb.o -+ obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o -+diff -urN linux-2.6.24.7.old/drivers/video/console/Kconfig linux-2.6.24.7/drivers/video/console/Kconfig -+--- linux-2.6.24.7.old/drivers/video/console/Kconfig 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/video/console/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -134,6 +134,14 @@ -+ -+ If unsure, select n. -+ -++config FRAMEBUFFER_CONSOLE_CURSOR_FLASH -++ bool "Framebuffer Console Cursor flash" -++ depends on FRAMEBUFFER_CONSOLE -++ help -++ Enable cursor flush for the framebuffer console. This is done -++ in software and may be significantly slower than a normally oriented -++ display. -++ -+ config FRAMEBUFFER_CONSOLE_ROTATION -+ bool "Framebuffer Console Rotation" -+ depends on FRAMEBUFFER_CONSOLE -+diff -urN linux-2.6.24.7.old/drivers/video/console/fbcon.c linux-2.6.24.7/drivers/video/console/fbcon.c -+--- linux-2.6.24.7.old/drivers/video/console/fbcon.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/video/console/fbcon.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -399,6 +399,7 @@ -+ -+ static void fb_flashcursor(struct work_struct *work) -+ { -++#ifdef CONFIG_FRAMEBUFFER_CONSOLE_CURSOR_FLASH -+ struct fb_info *info = container_of(work, struct fb_info, queue); -+ struct fbcon_ops *ops = info->fbcon_par; -+ struct display *p; -+@@ -424,6 +425,7 @@ -+ ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1), -+ get_color(vc, info, c, 0)); -+ release_console_sem(); -++#endif -+ } -+ -+ #if defined(CONFIG_ATARI) || defined(CONFIG_MAC) -+diff -urN linux-2.6.24.7.old/drivers/video/jz4740_slcd.c linux-2.6.24.7/drivers/video/jz4740_slcd.c -+--- linux-2.6.24.7.old/drivers/video/jz4740_slcd.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/video/jz4740_slcd.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1334 @@ -++/* -++ * linux/drivers/video/jzslcd.c -- Ingenic On-Chip Smart LCD frame buffer device -++ * -++ * Copyright (C) 2005-2007, Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "console/fbcon.h" -++ -++#include "jz4740_slcd.h" -++ -++#undef DEBUG -++//#define DEBUG -++#ifdef DEBUG -++#define dprintk(x...) printk(x) -++#else -++#define dprintk(x...) -++#endif -++ -++#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) -++#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) -++#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) -++#ifdef DEBUG -++#define print_dbg(f, arg...) printk("dbg::" __FILE__ ",LINE(%d): " f "\n", __LINE__, ## arg) -++#else -++#define print_dbg(f, arg...) do {} while (0) -++#endif -++ -++static jz_dma_desc slcd_palette_desc __attribute__ ((aligned (16))); -++static jz_dma_desc slcd_frame_desc __attribute__ ((aligned (16))); -++ -++static int dma_chan; -++static dma_addr_t slcd_frame_desc_phys_addr, slcd_palette_desc_phys_addr; -++ -++static unsigned char non_link_desp = 0; -++static unsigned char is_set_reg = 0; -++struct lcd_cfb_info { -++ struct fb_info fb; -++ struct display_switch *dispsw; -++ signed int currcon; -++ int func_use_count; -++ -++ struct { -++ u16 red, green, blue; -++ } palette[NR_PALETTE]; -++#ifdef CONFIG_PM -++ struct pm_dev *pm; -++#endif -++}; -++ -++struct slcd_reg_info { -++ unsigned int cmd; -++ unsigned int data; -++}; -++static struct slcd_reg_info reg_buf; -++static struct lcd_cfb_info *jzslcd_info; -++ -++struct jzfb_info { -++ unsigned int cfg; /* panel mode and pin usage etc. */ -++ unsigned int w; -++ unsigned int h; -++ unsigned int bpp; /* bit per pixel */ -++ unsigned int bus; -++ unsigned int pclk; /* pixel clk */ -++ -++}; -++ -++static struct jzfb_info jzfb = { -++#ifdef CONFIG_JZ_SLCD_LGDP4551 -++ SLCD_CFG_CS_ACTIVE_LOW | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_TYPE_PARALLEL, -++ 400, 240, 16, 8, 16000000 /*16 bpp, 8 bus*/ -++// 240, 400, 18, 8, 16000000 /*18 bpp, 8 bus*/ -++// 400, 240, 18, 8, 16000000 /*18 bpp, 8 bus*/ -++#endif -++ -++#ifdef CONFIG_JZ_SLCD_SPFD5420A -++ SLCD_CFG_CS_ACTIVE_LOW | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_TYPE_PARALLEL, -++ 400, 240, 18, 18, 16000000 /*18 bpp, 18 bus*/ -++#endif -++}; -++ -++ -++static volatile unsigned char *slcd_palette; -++static volatile unsigned char *slcd_frame; -++ -++//extern struct display fb_display[MAX_NR_CONSOLES]; -++static irqreturn_t slcd_dma_irq(int irq, void *dev_id); -++ -++ -++static void Mcupanel_RegSet(UINT32 cmd, UINT32 data) -++{ -++ switch (jzfb.bus) { -++ case 8: -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_DATA | (data&0xffff); -++ break; -++ case 9: -++ data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); -++ data = ((data << 6) & 0xfc0000) | ((data << 4) & 0xfc00) | ((data << 2) & 0xfc); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_DATA | data; -++ break; -++ case 16: -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | (cmd&0xffff); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_DATA | (data&0xffff); -++ break; -++ case 18: -++ cmd = ((cmd & 0xff) << 1) | ((cmd & 0xff00) << 2); -++ data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | cmd; -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_DATA | ((data<<6)&0xfc0000)|((data<<4)&0xfc00) | ((data<<2)&0xfc); -++ break; -++ default: -++ printk("Don't support %d bit Bus\n", jzfb.bus ); -++ break; -++ } -++} -++ -++/* Sent a command withou data */ -++static void Mcupanel_Command(UINT32 cmd) { -++ switch (jzfb.bus) { -++ case 8: -++ case 9: -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0); -++ break; -++ case 16: -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | (cmd&0xffff); -++ break; -++ case 18: -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) << 2) | ((cmd&0xff) << 1); -++ break; -++ default: -++ printk("Don't support %d bit Bus\n", jzfb.bus ); -++ break; -++ } -++} -++ -++/* Set the start address of screen, for example (0, 0) */ -++#ifdef CONFIG_JZ_SLCD_LGDP4551 -++static void Mcupanel_SetAddr(UINT16 x, UINT16 y) -++{ -++ Mcupanel_RegSet(0x20,x) ; -++ udelay(1); -++ Mcupanel_RegSet(0x21,y) ; -++ udelay(1); -++ Mcupanel_Command(0x22); -++ -++} -++#endif -++#ifdef CONFIG_JZ_SLCD_SPFD5420A -++void Mcupanel_SetAddr(u32 x, u32 y) //u32 -++{ -++ Mcupanel_RegSet(0x200,x) ; -++ udelay(1); -++ Mcupanel_RegSet(0x201,y) ; -++ udelay(1); -++ Mcupanel_Command(0x202); -++ -++} -++ -++#endif -++ -++static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) -++{ -++ chan &= 0xffff; -++ chan >>= 16 - bf->length; -++ return chan << bf->offset; -++} -++ -++static int jzfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, -++ u_int transp, struct fb_info *info) -++{ -++ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -++ unsigned short *ptr, ctmp; -++ -++ print_dbg("regno:%d,RGBt:(%d,%d,%d,%d)\t", regno, red, green, blue, transp); -++ if (regno >= NR_PALETTE) -++ return 1; -++ -++ cfb->palette[regno].red = red ; -++ cfb->palette[regno].green = green; -++ cfb->palette[regno].blue = blue; -++ if (cfb->fb.var.bits_per_pixel <= 16) { -++ red >>= 8; -++ green >>= 8; -++ blue >>= 8; -++ -++ red &= 0xff; -++ green &= 0xff; -++ blue &= 0xff; -++ } -++ switch (cfb->fb.var.bits_per_pixel) { -++ case 1: -++ case 2: -++ case 4: -++ case 8: -++ /* RGB 565 */ -++ if (((red >> 3) == 0) && ((red >> 2) != 0)) -++ red = 1 << 3; -++ if (((blue >> 3) == 0) && ((blue >> 2) != 0)) -++ blue = 1 << 3; -++ ctmp = ((red >> 3) << 11) -++ | ((green >> 2) << 5) | (blue >> 3); -++ -++ ptr = (unsigned short *)slcd_palette; -++ ptr = (unsigned short *)(((u32)ptr)|0xa0000000); -++ ptr[regno] = ctmp; -++ -++ break; -++ -++ case 15: -++ if (regno < 16) -++ ((u32 *)cfb->fb.pseudo_palette)[regno] = -++ ((red >> 3) << 10) | -++ ((green >> 3) << 5) | -++ (blue >> 3); -++ break; -++ case 16: -++ if (regno < 16) { -++ ((u32 *)cfb->fb.pseudo_palette)[regno] = -++ ((red >> 3) << 11) | -++ ((green >> 2) << 5) | -++ (blue >> 3); -++ } -++ break; -++ case 18: -++ case 24: -++ case 32: -++ if (regno < 16) -++ ((u32 *)cfb->fb.pseudo_palette)[regno] = -++ (red << 16) | -++ (green << 8) | -++ (blue << 0); -++ -++/* if (regno < 16) { -++ unsigned val; -++ val = chan_to_field(red, &cfb->fb.var.red); -++ val |= chan_to_field(green, &cfb->fb.var.green); -++ val |= chan_to_field(blue, &cfb->fb.var.blue); -++ ((u32 *)cfb->fb.pseudo_palette)[regno] = val; -++ } -++*/ -++ -++ break; -++ } -++ return 0; -++} -++ -++static int jzfb_ioctl (struct fb_info *info, unsigned int cmd, unsigned long arg ) -++{ -++ int ret = 0; -++ void __user *argp = (void __user *)arg; -++ -++ switch (cmd) { -++ case FBIOSETBACKLIGHT: -++ __slcd_set_backlight_level(arg); /* We support 8 levels here. */ -++ break; -++ case FBIODISPON: -++ __slcd_display_on(); -++ break; -++ case FBIODISPOFF: -++ __slcd_display_off(); -++ break; -++ case FBIO_REFRESH_ALWAYS: -++ dprintk("slcd_frame_desc.dcmd = 0x%08x\n", slcd_frame_desc.dcmd); -++ if (slcd_frame_desc.dcmd & DMAC_DCMD_LINK) -++ printk("The Smart LCD refreshes automatically. Option is omitted!\n"); -++ else { -++ dprintk("OPEN DMAC_DCMD_LINK \n"); -++ slcd_frame_desc.dcmd &= ~DMAC_DCMD_TIE; -++ slcd_frame_desc.dcmd |= DMAC_DCMD_LINK; -++ dma_cache_wback((unsigned long)(&slcd_frame_desc), 16); -++ REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_TIE; -++ __dmac_channel_set_doorbell(dma_chan); -++ } -++ break; -++ case FBIO_REFRESH_EVENTS: -++ dprintk("slcd_frame_desc.dcmd = 0x%08x\n", slcd_frame_desc.dcmd); -++ if (!(slcd_frame_desc.dcmd & DMAC_DCMD_LINK)) -++ printk("The Smart LCD is refreshed by envents. Option is omitted!\n"); -++ else { -++ non_link_desp = 1; -++ REG_DMAC_DCMD(dma_chan) |= DMAC_DCMD_TIE; -++ REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_LINK; -++ } -++ break; -++ case FBIO_DO_REFRESH: -++ -++ dprintk("slcd_frame_desc.dcmd = 0x%08x\n", slcd_frame_desc.dcmd); -++ if (slcd_frame_desc.dcmd & DMAC_DCMD_LINK) -++ printk("The Smart LCD can refresh automatically. Option is omitted!\n"); -++ else { -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ __dmac_channel_set_doorbell(dma_chan); -++ } -++ break; -++ case FBIO_SET_REG: -++ if (copy_from_user(®_buf, argp, sizeof(reg_buf))) -++ return -EFAULT; -++ is_set_reg = 1; -++ REG_DMAC_DCMD(dma_chan) |= DMAC_DCMD_TIE; -++ REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_LINK; -++ break; -++ default: -++ break; -++ } -++ -++ return ret; -++} -++ -++/* Use mmap /dev/fb can only get a non-cacheable Virtual Address. */ -++static int jzfb_mmap(struct fb_info *info, struct vm_area_struct *vma) -++{ -++ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -++ unsigned long start; -++ unsigned long off; -++ u32 len; -++ -++ off = vma->vm_pgoff << PAGE_SHIFT; -++ //fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); -++ -++ /* frame buffer memory */ -++ start = cfb->fb.fix.smem_start; -++ len = PAGE_ALIGN((start & ~PAGE_MASK) + cfb->fb.fix.smem_len); -++ start &= PAGE_MASK; -++ -++ if ((vma->vm_end - vma->vm_start + off) > len) -++ return -EINVAL; -++ off += start; -++ -++ vma->vm_pgoff = off >> PAGE_SHIFT; -++ vma->vm_flags |= VM_IO; -++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* Uncacheable */ -++ -++#if 1 -++ pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; -++// pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; /* Uncacheable */ -++ pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; /* Write-Through */ -++#endif -++ -++ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, -++ vma->vm_end - vma->vm_start, -++ vma->vm_page_prot)) { -++ return -EAGAIN; -++ } -++ return 0; -++} -++ -++/* checks var and eventually tweaks it to something supported, -++ * DO NOT MODIFY PAR */ -++static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -++{ -++ print_dbg("jzfb_check_var"); -++ return 0; -++} -++ -++ -++/* -++ * set the video mode according to info->var -++ */ -++static int jzfb_set_par(struct fb_info *info) -++{ -++// print_dbg("jzfb_set_par"); -++ printk("jzfb_set_par"); -++ return 0; -++} -++ -++ -++/* -++ * (Un)Blank the display. -++ * Fix me: should we use VESA value? -++ */ -++static int jzfb_blank(int blank_mode, struct fb_info *info) -++{ -++ -++ dprintk("fb_blank %d %p", blank_mode, info); -++ -++ switch (blank_mode) { -++ -++ case FB_BLANK_UNBLANK: -++ /* Turn on panel */ -++ break; -++ -++ case FB_BLANK_NORMAL: -++ case FB_BLANK_VSYNC_SUSPEND: -++ case FB_BLANK_HSYNC_SUSPEND: -++ case FB_BLANK_POWERDOWN: -++ /* Turn off panel */ -++ break; -++ default: -++ break; -++ -++ } -++ return 0; -++} -++ -++/* -++ * pan display -++ */ -++static int jzfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) -++{ -++ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -++ int dy; -++ -++ if (!var || !cfb) { -++ return -EINVAL; -++ } -++ -++ if (var->xoffset - cfb->fb.var.xoffset) { -++ /* No support for X panning for now! */ -++ return -EINVAL; -++ } -++ -++ dy = var->yoffset - cfb->fb.var.yoffset; -++ print_dbg("var.yoffset: %d", dy); -++ if (dy) { -++ -++ print_dbg("Panning screen of %d lines", dy); -++// slcd_frame_desc->databuf += (cfb->fb.fix.line_length * dy); -++// slcd_frame_desc->dsadr += (cfb->fb.fix.line_length * dy); -++ /* TODO: Wait for current frame to finished */ -++ } -++ -++ return 0; -++} -++ -++ -++/* use default function cfb_fillrect, cfb_copyarea, cfb_imageblit */ -++static struct fb_ops jzfb_ops = { -++ .owner = THIS_MODULE, -++ .fb_setcolreg = jzfb_setcolreg, -++ .fb_check_var = jzfb_check_var, -++ .fb_set_par = jzfb_set_par, -++ .fb_blank = jzfb_blank, -++ .fb_pan_display = jzfb_pan_display, -++ .fb_fillrect = cfb_fillrect, -++ .fb_copyarea = cfb_copyarea, -++ .fb_imageblit = cfb_imageblit, -++ .fb_mmap = jzfb_mmap, -++ .fb_ioctl = jzfb_ioctl, -++}; -++ -++static int jzfb_set_var(struct fb_var_screeninfo *var, int con, -++ struct fb_info *info) -++{ -++ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -++ //struct display *display; -++ int chgvar = 0; -++ -++ var->height = jzfb.h ; -++ var->width = jzfb.w ; -++ var->bits_per_pixel = jzfb.bpp; -++ -++ var->vmode = FB_VMODE_NONINTERLACED; -++ var->activate = cfb->fb.var.activate; -++ var->xres = var->width; -++ var->yres = var->height; -++ var->xres_virtual = var->width; -++ var->yres_virtual = var->height; -++ var->xoffset = 0; -++ var->yoffset = 0; -++ var->pixclock = 0; -++ var->left_margin = 0; -++ var->right_margin = 0; -++ var->upper_margin = 0; -++ var->lower_margin = 0; -++ var->hsync_len = 0; -++ var->vsync_len = 0; -++ var->sync = 0; -++ var->activate &= ~FB_ACTIVATE_TEST; -++ -++ /* -++ * CONUPDATE and SMOOTH_XPAN are equal. However, -++ * SMOOTH_XPAN is only used internally by fbcon. -++ */ -++ if (var->vmode & FB_VMODE_CONUPDATE) { -++ var->vmode |= FB_VMODE_YWRAP; -++ var->xoffset = cfb->fb.var.xoffset; -++ var->yoffset = cfb->fb.var.yoffset; -++ } -++ -++ if (var->activate & FB_ACTIVATE_TEST) -++ return 0; -++ -++ if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) -++ return -EINVAL; -++ -++ if (cfb->fb.var.xres != var->xres) -++ chgvar = 1; -++ if (cfb->fb.var.yres != var->yres) -++ chgvar = 1; -++ if (cfb->fb.var.xres_virtual != var->xres_virtual) -++ chgvar = 1; -++ if (cfb->fb.var.yres_virtual != var->yres_virtual) -++ chgvar = 1; -++ if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel) -++ chgvar = 1; -++ -++ //display = fb_display + con; -++ -++ var->red.msb_right = 0; -++ var->green.msb_right = 0; -++ var->blue.msb_right = 0; -++ -++ switch(var->bits_per_pixel){ -++ case 1: /* Mono */ -++ cfb->fb.fix.visual = FB_VISUAL_MONO01; -++ cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) / 8; -++ break; -++ case 2: /* Mono */ -++ var->red.offset = 0; -++ var->red.length = 2; -++ var->green.offset = 0; -++ var->green.length = 2; -++ var->blue.offset = 0; -++ var->blue.length = 2; -++ -++ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -++ cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) / 8; -++ break; -++ case 4: /* PSEUDOCOLOUR*/ -++ var->red.offset = 0; -++ var->red.length = 4; -++ var->green.offset = 0; -++ var->green.length = 4; -++ var->blue.offset = 0; -++ var->blue.length = 4; -++ -++ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -++ cfb->fb.fix.line_length = var->xres / 2; -++ break; -++ case 8: /* PSEUDOCOLOUR, 256 */ -++ var->red.offset = 0; -++ var->red.length = 8; -++ var->green.offset = 0; -++ var->green.length = 8; -++ var->blue.offset = 0; -++ var->blue.length = 8; -++ -++ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -++ cfb->fb.fix.line_length = var->xres ; -++ break; -++ case 15: /* DIRECTCOLOUR, 32k */ -++ var->bits_per_pixel = 15; -++ var->red.offset = 10; -++ var->red.length = 5; -++ var->green.offset = 5; -++ var->green.length = 5; -++ var->blue.offset = 0; -++ var->blue.length = 5; -++ -++ cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR; -++ cfb->fb.fix.line_length = var->xres_virtual * 2; -++ break; -++ case 16: /* DIRECTCOLOUR, 64k */ -++ var->bits_per_pixel = 16; -++ var->red.offset = 11; -++ var->red.length = 5; -++ var->green.offset = 5; -++ var->green.length = 6; -++ var->blue.offset = 0; -++ var->blue.length = 5; -++ -++ cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; -++ cfb->fb.fix.line_length = var->xres_virtual * 2; -++ break; -++ case 18: -++ case 24: -++ case 32: -++ /* DIRECTCOLOUR, 256 */ -++ var->bits_per_pixel = 32; -++ -++ var->red.offset = 16; -++ var->red.length = 8; -++ var->green.offset = 8; -++ var->green.length = 8; -++ var->blue.offset = 0; -++ var->blue.length = 8; -++ var->transp.offset = 24; -++ var->transp.length = 8; -++ -++ cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; -++ cfb->fb.fix.line_length = var->xres_virtual * 4; -++ break; -++ -++ default: /* in theory this should never happen */ -++ printk(KERN_WARNING "%s: don't support for %dbpp\n", -++ cfb->fb.fix.id, var->bits_per_pixel); -++ break; -++ } -++ -++ cfb->fb.var = *var; -++ cfb->fb.var.activate &= ~FB_ACTIVATE_ALL; -++ -++ /* -++ * If we are setting all the virtual consoles, also set the -++ * defaults used to create new consoles. -++ */ -++ fb_set_cmap(&cfb->fb.cmap, &cfb->fb); -++ dprintk("jzfb_set_var: after fb_set_cmap...\n"); -++ -++ return 0; -++} -++ -++static struct lcd_cfb_info * jzfb_alloc_fb_info(void) -++{ -++ struct lcd_cfb_info *cfb; -++ -++ cfb = kmalloc(sizeof(struct lcd_cfb_info) + sizeof(u32) * 16, GFP_KERNEL); -++ -++ if (!cfb) -++ return NULL; -++ -++ jzslcd_info = cfb; -++ -++ memset(cfb, 0, sizeof(struct lcd_cfb_info) ); -++ -++ cfb->currcon = -1; -++ -++ -++ strcpy(cfb->fb.fix.id, "jz-slcd"); -++ cfb->fb.fix.type = FB_TYPE_PACKED_PIXELS; -++ cfb->fb.fix.type_aux = 0; -++ cfb->fb.fix.xpanstep = 1; -++ cfb->fb.fix.ypanstep = 1; -++ cfb->fb.fix.ywrapstep = 0; -++ cfb->fb.fix.accel = FB_ACCEL_NONE; -++ -++ cfb->fb.var.nonstd = 0; -++ cfb->fb.var.activate = FB_ACTIVATE_NOW; -++ cfb->fb.var.height = -1; -++ cfb->fb.var.width = -1; -++ cfb->fb.var.accel_flags = FB_ACCELF_TEXT; -++ -++ cfb->fb.fbops = &jzfb_ops; -++ cfb->fb.flags = FBINFO_FLAG_DEFAULT; -++ -++ cfb->fb.pseudo_palette = (void *)(cfb + 1); -++ -++ switch (jzfb.bpp) { -++ case 1: -++ fb_alloc_cmap(&cfb->fb.cmap, 4, 0); -++ break; -++ case 2: -++ fb_alloc_cmap(&cfb->fb.cmap, 8, 0); -++ break; -++ case 4: -++ fb_alloc_cmap(&cfb->fb.cmap, 32, 0); -++ break; -++ case 8: -++ -++ default: -++ fb_alloc_cmap(&cfb->fb.cmap, 256, 0); -++ break; -++ } -++ dprintk("fb_alloc_cmap,fb.cmap.len:%d....\n", cfb->fb.cmap.len); -++ -++ return cfb; -++} -++ -++/* -++ * Map screen memory -++ */ -++static int jzfb_map_smem(struct lcd_cfb_info *cfb) -++{ -++ struct page * map = NULL; -++ unsigned char *tmp; -++ unsigned int page_shift, needroom, t; -++ -++ t = jzfb.bpp; -++ if (jzfb.bpp == 15) -++ t = 16; -++ if (jzfb.bpp == 18 || jzfb.bpp == 24) -++ t = 32; -++ needroom = ((jzfb.w * t + 7) >> 3) * jzfb.h; -++ -++ for (page_shift = 0; page_shift < 12; page_shift++) -++ if ((PAGE_SIZE << page_shift) >= needroom) -++ break; -++ -++ slcd_palette = (unsigned char *)__get_free_pages(GFP_KERNEL, 0); -++ slcd_frame = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); -++ if ((!slcd_palette) || (!slcd_frame)) -++ return -ENOMEM; -++ -++ memset((void *)slcd_palette, 0, PAGE_SIZE); -++ memset((void *)slcd_frame, 0, PAGE_SIZE << page_shift); -++ -++ map = virt_to_page(slcd_palette); -++ set_bit(PG_reserved, &map->flags); -++ -++ for (tmp=(unsigned char *)slcd_frame; -++ tmp < slcd_frame + (PAGE_SIZE << page_shift); -++ tmp += PAGE_SIZE) { -++ map = virt_to_page(tmp); -++ set_bit(PG_reserved, &map->flags); -++ } -++ -++ cfb->fb.fix.smem_start = virt_to_phys((void *)slcd_frame); -++ -++ cfb->fb.fix.smem_len = (PAGE_SIZE << page_shift); -++ -++ cfb->fb.screen_base = -++ (unsigned char *)(((unsigned int)slcd_frame & 0x1fffffff) | 0xa0000000); -++ -++ if (!cfb->fb.screen_base) { -++ printk("%s: unable to map screen memory\n", cfb->fb.fix.id); -++ return -ENOMEM; -++ } -++ -++ return 0; -++} -++ -++static void jzfb_free_fb_info(struct lcd_cfb_info *cfb) -++{ -++ if (cfb) { -++ fb_alloc_cmap(&cfb->fb.cmap, 0, 0); -++ kfree(cfb); -++ } -++} -++ -++static void jzfb_unmap_smem(struct lcd_cfb_info *cfb) -++{ -++ struct page * map = NULL; -++ unsigned char *tmp; -++ unsigned int page_shift, needroom, t; -++ -++ t = jzfb.bpp; -++ if (jzfb.bpp == 18 || jzfb.bpp == 24) -++ t = 32; -++ if (jzfb.bpp == 15) -++ t = 16; -++ needroom = ((jzfb.w * t + 7) >> 3) * jzfb.h; -++ for (page_shift = 0; page_shift < 12; page_shift++) -++ if ((PAGE_SIZE << page_shift) >= needroom) -++ break; -++ -++ if (cfb && cfb->fb.screen_base) { -++ iounmap(cfb->fb.screen_base); -++ cfb->fb.screen_base = NULL; -++ release_mem_region(cfb->fb.fix.smem_start, -++ cfb->fb.fix.smem_len); -++ } -++ -++ if (slcd_palette) { -++ map = virt_to_page(slcd_palette); -++ clear_bit(PG_reserved, &map->flags); -++ free_pages((int)slcd_palette, 0); -++ } -++ -++ if (slcd_frame) { -++ -++ for (tmp=(unsigned char *)slcd_frame; -++ tmp < slcd_frame + (PAGE_SIZE << page_shift); -++ tmp += PAGE_SIZE) { -++ map = virt_to_page(tmp); -++ clear_bit(PG_reserved, &map->flags); -++ } -++ -++ free_pages((int)slcd_frame, page_shift); -++ } -++} -++ -++static void slcd_descriptor_init(void) -++{ -++ int i; -++ int frm_size, pal_size; -++ unsigned int next; -++ unsigned int slcd_frame_src_phys_addr, slcd_palette_src_phys_addr, slcd_dma_dst_phys_addr; -++ -++ i = jzfb.bpp; -++ if (i == 18 || i == 24) -++ i = 32; -++ if (i == 15) -++ i = 16; -++ -++ switch (jzfb.bpp) { -++ case 1: -++ pal_size = 4; -++ break; -++ case 2: -++ pal_size = 8; -++ break; -++ case 4: -++ pal_size = 32; -++ break; -++ case 8: -++ default: -++ pal_size = 512; -++ } -++ -++ frm_size = jzfb.w * jzfb.h * jzfb.bpp / 8; -++ -++ /*Offset of next descriptor*/ -++ slcd_frame_desc_phys_addr = (dma_addr_t)CPHYSADDR((unsigned long)(&slcd_frame_desc)); -++ slcd_palette_desc_phys_addr = (dma_addr_t)CPHYSADDR((unsigned long)(&slcd_palette_desc)); -++ -++ /*Soure address and Target address*/ -++ slcd_palette_src_phys_addr = (unsigned int)virt_to_phys(slcd_palette); -++ slcd_frame_src_phys_addr = (unsigned int)virt_to_phys(slcd_frame); -++ slcd_dma_dst_phys_addr = (unsigned int)CPHYSADDR(SLCD_FIFO); -++ next = slcd_frame_desc_phys_addr >> 4; -++ -++ /* Prepare Palette Descriptor */ -++ slcd_palette_desc.dcmd = DMAC_DCMD_SAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 -++ | DMAC_DCMD_DWDH_16 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_TM | DMAC_DCMD_DES_V -++ | DMAC_DCMD_DES_VIE | DMAC_DCMD_LINK; -++ switch (slcd_palette_desc.dcmd & DMAC_DCMD_DS_MASK) { -++ case DMAC_DCMD_DS_32BYTE: -++ pal_size /= 32; -++ break; -++ case DMAC_DCMD_DS_16BYTE: -++ pal_size /= 16; -++ break; -++ case DMAC_DCMD_DS_32BIT: -++ pal_size /= 4; -++ break; -++ case DMAC_DCMD_DS_16BIT: -++ pal_size /= 2; -++ break; -++ case DMAC_DCMD_DS_8BIT: -++ default: -++ break; -++ } -++ -++ slcd_palette_desc.dsadr = (unsigned int)virt_to_phys(slcd_palette); /* DMA source address */ -++ slcd_palette_desc.dtadr = (unsigned int)CPHYSADDR(SLCD_FIFO); /* DMA target address */ -++ slcd_palette_desc.ddadr = (volatile unsigned int)((next << 24) | (pal_size & 0xffffff)); /* offset and size*/ -++ dma_cache_wback((unsigned long)(&slcd_palette_desc), 16); -++ -++ /*Prepare Frame Descriptor in memory*/ -++ switch (jzfb.bpp) { -++ case 8 ... 16: -++ slcd_frame_desc.dcmd = DMAC_DCMD_SAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 -++ | DMAC_DCMD_DWDH_16 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_TM | DMAC_DCMD_DES_V -++ | DMAC_DCMD_DES_VIE | DMAC_DCMD_LINK; -++ break; -++ -++ case 17 ... 32: -++ slcd_frame_desc.dcmd = DMAC_DCMD_SAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 -++ | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TM | DMAC_DCMD_DES_V -++ | DMAC_DCMD_DES_VIE | DMAC_DCMD_LINK; -++ break; -++ } -++ switch (slcd_frame_desc.dcmd & DMAC_DCMD_DS_MASK) { -++ case DMAC_DCMD_DS_32BYTE: -++ frm_size /= 32; -++ break; -++ case DMAC_DCMD_DS_16BYTE: -++ frm_size /= 16; -++ break; -++ case DMAC_DCMD_DS_32BIT: -++ frm_size /= 4; -++ break; -++ case DMAC_DCMD_DS_16BIT: -++ frm_size /= 2; -++ break; -++ case DMAC_DCMD_DS_8BIT: -++ default: -++ break; -++ } -++ -++ slcd_frame_desc.dsadr = slcd_frame_src_phys_addr; /* DMA source address */ -++ slcd_frame_desc.dtadr = slcd_dma_dst_phys_addr; /* DMA target address */ -++ slcd_frame_desc.ddadr = (volatile unsigned int)((next << 24) | (frm_size & 0xffffff)); /* offset and size*/ -++ dma_cache_wback((unsigned long)(&slcd_frame_desc), 16); -++} -++ -++void slcd_hw_init(void) -++{ -++ unsigned int val, pclk; -++ int pll_div; -++ -++ REG_LCD_CFG &= ~LCD_CFG_LCDPIN_MASK; -++ REG_LCD_CFG |= LCD_CFG_LCDPIN_SLCD; -++ -++ if ((jzfb.bpp == 18) | (jzfb.bpp == 24)) -++ jzfb.bpp = 32; -++ -++ /* Configure SLCD module for initialize smart lcd registers*/ -++ switch (jzfb.bus) { -++ case 8: -++ REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_8_x2 -++ | SLCD_CFG_CWIDTH_8BIT | SLCD_CFG_CS_ACTIVE_LOW -++ | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING -++ | SLCD_CFG_TYPE_PARALLEL; -++ __gpio_as_slcd_8bit(); -++ break; -++ case 9: -++ REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_8_x2 -++ | SLCD_CFG_CWIDTH_8BIT | SLCD_CFG_CS_ACTIVE_LOW -++ | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING -++ | SLCD_CFG_TYPE_PARALLEL; -++ __gpio_as_slcd_9bit(); -++ break; -++ case 16: -++ REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_16 -++ | SLCD_CFG_CWIDTH_16BIT | SLCD_CFG_CS_ACTIVE_LOW -++ | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING -++ | SLCD_CFG_TYPE_PARALLEL; -++ __gpio_as_slcd_16bit(); -++ break; -++ case 18: -++ REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_18 -++ | SLCD_CFG_CWIDTH_18BIT | SLCD_CFG_CS_ACTIVE_LOW -++ | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING -++ | SLCD_CFG_TYPE_PARALLEL; -++ __gpio_as_slcd_18bit(); -++ break; -++ default: -++ printk("Error: Don't support BUS %d!\n", jzfb.bus); -++ break; -++ } -++ -++ REG_SLCD_CTRL = SLCD_CTRL_DMA_EN; -++ __cpm_stop_lcd(); -++ pclk = jzfb.pclk; -++ pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source,0:pllout/2 1: pllout */ -++ pll_div = pll_div ? 1 : 2 ; -++ val = ( __cpm_get_pllout()/pll_div ) / pclk; -++ val--; -++ if ( val > 0x1ff ) { -++ printk("CPM_LPCDR too large, set it to 0x1ff\n"); -++ val = 0x1ff; -++ } -++ __cpm_set_pixdiv(val); -++ -++ REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */ -++ -++ jz_clocks.pixclk = __cpm_get_pixclk(); -++ jz_clocks.lcdclk = __cpm_get_lcdclk(); -++ printk("SLCDC: PixClock:%d LcdClock:%d\n", -++ jz_clocks.pixclk, jz_clocks.lcdclk); -++ -++ __cpm_start_lcd(); -++ udelay(1000); -++ __slcd_display_pin_init(); -++ __slcd_special_on(); -++ -++ /* Configure SLCD module for transfer data to smart lcd GRAM*/ -++ switch (jzfb.bus) { -++ case 8: -++ switch (jzfb.bpp) { -++ case 8: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -++ break; -++ case 15: -++ case 16: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x2; -++ break; -++ case 17 ... 32: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x3; -++ break; -++ default: -++ printk("The BPP %d is not supported\n", jzfb.bpp); -++ break; -++ } -++ break; -++ case 9: -++ switch (jzfb.bpp) { -++ case 8: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -++ break; -++ case 15 ... 16: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x2; -++ break; -++ case 17 ... 32: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_9_x2; -++ break; -++ default: -++ printk("The BPP %d is not supported\n", jzfb.bpp); -++ break; -++ } -++ break; -++ case 16: -++ switch (jzfb.bpp) { -++ case 8: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -++ break; -++ case 15 ... 16: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_16; -++ break; -++ case 17 ... 32: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x3; -++ break; -++ default: -++ printk("The BPP %d is not supported\n", jzfb.bpp); -++ break; -++ } -++ break; -++ case 18: -++ switch (jzfb.bpp) { -++ case 8: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -++ break; -++ case 15: -++ case 16: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_16; -++ break; -++ case 17 ... 32: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_18; -++ break; -++ default: -++ printk("The BPP %d is not supported\n", jzfb.bpp); -++ break; -++ } -++ break; -++ default: -++ printk("Error: The BUS %d is not supported\n", jzfb.bus); -++ break; -++ } -++ dprintk("SLCD_CFG=0x%x\n", REG_SLCD_CFG); -++} -++ -++static irqreturn_t slcd_dma_irq(int irq, void *dev_id) -++{ -++ -++ if (__dmac_channel_transmit_halt_detected(dma_chan)) { -++ dprintk("DMA HALT\n"); -++ __dmac_channel_clear_transmit_halt(dma_chan); -++ } -++ -++ if (__dmac_channel_address_error_detected(dma_chan)) { -++ dprintk("DMA ADDR ERROR\n"); -++ __dmac_channel_clear_address_error(dma_chan); -++ } -++ -++ if (__dmac_channel_descriptor_invalid_detected(dma_chan)) { -++ dprintk("DMA DESC INVALID\n"); -++ __dmac_channel_clear_descriptor_invalid(dma_chan); -++ } -++ -++ if (__dmac_channel_count_terminated_detected(dma_chan)) { -++ dprintk("DMA CT\n"); -++ __dmac_channel_clear_count_terminated(dma_chan); -++ if(is_set_reg){ -++ printk("Close DMAC_DCMD_LINK \n"); -++ REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_LINK; -++ } -++ if (non_link_desp) { -++ printk("Close DMAC_DCMD_LINK \n"); -++ /*Set to Non-Link Descriptor*/ -++ REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_LINK; -++ } -++ } -++ -++ if (__dmac_channel_transmit_end_detected(dma_chan)) { -++ printk("DMA TT\n"); -++ __dmac_channel_clear_transmit_end(dma_chan); -++ if (non_link_desp) { -++ slcd_frame_desc.dcmd |= DMAC_DCMD_TIE; -++ slcd_frame_desc.dcmd &= ~DMAC_DCMD_LINK; -++ dma_cache_wback((unsigned long)(&slcd_frame_desc), 16); -++ non_link_desp = 0; -++ } -++ if (is_set_reg) { -++ is_set_reg = 0; -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_DMAC_DMACR &= ~DMAC_DMACR_DMAE; /* disable DMA */ -++ REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */ -++ REG_SLCD_CTRL = 0; -++ -++ /* -++ *add operation here -++ */ -++ Mcupanel_RegSet(reg_buf.cmd, reg_buf.data); -++ Mcupanel_Command(0x0022);/*Write Data to GRAM */ -++ mdelay(100); -++ REG_SLCD_CTRL = SLCD_CTRL_DMA_EN; -++ REG_DMAC_DMACR = DMAC_DMACR_DMAE; -++ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; -++ __dmac_channel_set_doorbell(dma_chan); -++ } -++ } -++ return IRQ_HANDLED; -++} -++ -++static int slcd_dma_init(void) -++{ -++ /* Request DMA channel and setup irq handler */ -++ dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", slcd_dma_irq, 0, NULL); -++ if (dma_chan < 0) { -++ printk("Request DMA Failed\n"); -++ return -1; -++ } -++ printk("DMA channel %d is requested by SLCD!\n", dma_chan); -++ -++ /*Init the SLCD DMA and Enable*/ -++ REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_SLCD; -++ REG_DMAC_DMACR = DMAC_DMACR_DMAE; -++ REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; /*Descriptor Transfer*/ -++ -++ if (jzfb.bpp <= 8) -++ REG_DMAC_DDA(dma_chan) = slcd_palette_desc_phys_addr; -++ else -++ REG_DMAC_DDA(dma_chan) = slcd_frame_desc_phys_addr; -++ -++ /* DMA doorbell set -- start DMA now ... */ -++ __dmac_channel_set_doorbell(dma_chan); -++ return 0; -++} -++ -++#ifdef CONFIG_PM -++ -++/* -++ * Suspend the LCDC. -++ */ -++static int jzfb_suspend(void) -++{ -++ -++ __slcd_close_backlight(); -++ __dmac_disable_channel(dma_chan); -++ __slcd_dma_disable(); /* Quick Disable */ -++ __slcd_special_off(); -++ __cpm_stop_lcd(); -++ return 0; -++} -++ -++/* -++ * Resume the LCDC. -++ */ -++ -++static int jzfb_resume(void) -++{ -++ __cpm_start_lcd(); -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ switch (jzfb.bpp) { -++ case 8: -++ /* DATA 8-bit once*/ -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -++ break; -++ case 15: -++ case 16: -++ case 18: -++ case 24: -++ case 32: -++ /* DATA 8-bit twice*/ -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x2; -++ break; -++ default: -++ REG_SLCD_CFG = SLCD_CFG_DWIDTH_8_x2; -++ break; -++ } -++ __slcd_display_pin_init(); -++ __slcd_special_on(); -++ -++ if (jzfb.bpp == 32) { -++ /* DATA 8-bit three time*/ -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x3; -++ } -++ __slcd_dma_enable(); -++ udelay(100); -++ __dmac_enable_channel(dma_chan); -++ __dmac_channel_set_doorbell(dma_chan); -++ mdelay(200); -++ __slcd_set_backlight_level(80); -++ return 0; -++} -++ -++/* -++ * Power management hook. Note that we won't be called from IRQ context, -++ * unlike the blank functions above, so we may sleep. -++ */ -++static int jzslcd_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -++{ -++ int ret; -++ struct lcd_cfb_info *cfb = pm_dev->data; -++ -++ if (!cfb) return -EINVAL; -++ -++ switch (req) { -++ case PM_SUSPEND: -++ ret = jzfb_suspend(); -++ break; -++ -++ case PM_RESUME: -++ ret = jzfb_resume(); -++ break; -++ -++ default: -++ ret = -EINVAL; -++ break; -++ } -++ return ret; -++} -++#else -++#define jzfb_suspend NULL -++#define jzfb_resume NULL -++#endif /* CONFIG_PM */ -++static int __init jzslcd_fb_init(void) -++{ -++ -++ struct lcd_cfb_info *cfb; -++ int err = 0; -++ -++ /*the parameters of slcd*/ -++ cfb = jzfb_alloc_fb_info(); -++ if (!cfb) -++ goto failed; -++ -++ err = jzfb_map_smem(cfb); -++ if (err) -++ goto failed; -++ jzfb_set_var(&cfb->fb.var, -1, &cfb->fb); -++ -++ slcd_hw_init(); -++ -++ err = register_framebuffer(&cfb->fb); -++ if (err < 0) { -++ printk("jzslcd_fb_init(): slcd register framebuffer err.\n"); -++ goto failed; -++ } -++ -++ printk("fb%d: %s frame buffer device, using %dK of video memory\n", -++ cfb->fb.node, cfb->fb.fix.id, cfb->fb.fix.smem_len>>10); -++ -++ slcd_descriptor_init(); -++ err = slcd_dma_init(); -++ if (err != 0) { -++ printk("SLCD Init DMA Fail!\n"); -++ return err; -++ } -++ mdelay(100); -++ __slcd_set_backlight_level(80); -++ -++#ifdef CONFIG_PM -++ /* -++ * Note that the console registers this as well, but we want to -++ * power down the display prior to sleeping. -++ */ -++//struct pm_dev __deprecated *pm_register(pm_dev_t type, unsigned long id, pm_callback callback); -++ -++ cfb->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, jzslcd_pm_callback); -++ if (cfb->pm) -++ cfb->pm->data = cfb; -++ -++#endif -++ return 0; -++ -++failed: -++ jzfb_unmap_smem(cfb); -++ jzfb_free_fb_info(cfb); -++ -++ return err; -++} -++ -++#if 0 -++static int jzfb_remove(struct device *dev) -++{ -++ struct lcd_cfb_info *cfb = dev_get_drvdata(dev); -++ jzfb_unmap_smem(cfb); -++ jzfb_free_fb_info(cfb); -++ return 0; -++} -++#endif -++ -++#if 0 -++static struct device_driver jzfb_driver = { -++ .name = "jz-slcd", -++ .bus = &platform_bus_type, -++ .probe = jzfb_probe, -++ .remove = jzfb_remove, -++ .suspend = jzfb_suspend, -++ .resume = jzfb_resume, -++}; -++#endif -++ -++static void __exit jzslcd_fb_cleanup(void) -++{ -++ //driver_unregister(&jzfb_driver); -++ //jzfb_remove(); -++} -++ -++module_init(jzslcd_fb_init); -++module_exit(jzslcd_fb_cleanup); -++ -++MODULE_DESCRIPTION("JzSOC SLCD Controller driver"); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/drivers/video/jz4740_slcd.h linux-2.6.24.7/drivers/video/jz4740_slcd.h -+--- linux-2.6.24.7.old/drivers/video/jz4740_slcd.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/video/jz4740_slcd.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,376 @@ -++/* -++ * linux/drivers/video/jzslcd.h -- Ingenic On-Chip SLCD frame buffer device -++ * -++ * Copyright (C) 2005-2007, Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ */ -++ -++#ifndef __JZSLCD_H__ -++#define __JZSLCD_H__ -++ -++#define UINT16 unsigned short -++#define UINT32 unsigned int -++ -++#define NR_PALETTE 256 -++/* Jz LCDFB supported I/O controls. */ -++#define FBIOSETBACKLIGHT 0x4688 -++#define FBIODISPON 0x4689 -++#define FBIODISPOFF 0x468a -++#define FBIORESET 0x468b -++#define FBIOPRINT_REG 0x468c -++#define FBIO_REFRESH_ALWAYS 0x468d -++#define FBIO_REFRESH_EVENTS 0x468e -++#define FBIO_DO_REFRESH 0x468f -++#define FBIO_SET_REG 0x4690 -++ -++#ifdef CONFIG_JZ_SLCD_LGDP4551 -++#define PIN_CS_N (32*2+18) /* Chip select :SLCD_WR: GPC18 */ -++#define PIN_RESET_N (32*2+21) /* LCD reset :SLCD_RST: GPC21*/ -++#define PIN_RS_N (32*2+19) -++ -++#define __slcd_special_pin_init() \ -++do { \ -++ __gpio_as_output(PIN_CS_N); \ -++ __gpio_as_output(PIN_RESET_N); \ -++ __gpio_clear_pin(PIN_CS_N); /* Clear CS */\ -++ mdelay(100); \ -++} while(0) -++ -++#define __slcd_special_on() \ -++do { /* RESET# */ \ -++ __gpio_set_pin(PIN_RESET_N); \ -++ mdelay(10); \ -++ __gpio_clear_pin(PIN_RESET_N); \ -++ mdelay(10); \ -++ __gpio_set_pin(PIN_RESET_N); \ -++ mdelay(100); \ -++ Mcupanel_RegSet(0x0015,0x0050); \ -++ Mcupanel_RegSet(0x0011,0x0000); \ -++ Mcupanel_RegSet(0x0010,0x3628); \ -++ Mcupanel_RegSet(0x0012,0x0002); \ -++ Mcupanel_RegSet(0x0013,0x0E47); \ -++ udelay(100); \ -++ Mcupanel_RegSet(0x0012,0x0012); \ -++ udelay(100); \ -++ Mcupanel_RegSet(0x0010,0x3620); \ -++ Mcupanel_RegSet(0x0013,0x2E47); \ -++ udelay(50); \ -++ Mcupanel_RegSet(0x0030,0x0000); \ -++ Mcupanel_RegSet(0x0031,0x0502); \ -++ Mcupanel_RegSet(0x0032,0x0307); \ -++ Mcupanel_RegSet(0x0033,0x0304); \ -++ Mcupanel_RegSet(0x0034,0x0004); \ -++ Mcupanel_RegSet(0x0035,0x0401); \ -++ Mcupanel_RegSet(0x0036,0x0707); \ -++ Mcupanel_RegSet(0x0037,0x0303); \ -++ Mcupanel_RegSet(0x0038,0x1E02); \ -++ Mcupanel_RegSet(0x0039,0x1E02); \ -++ Mcupanel_RegSet(0x0001,0x0000); \ -++ Mcupanel_RegSet(0x0002,0x0300); \ -++ if (jzfb.bpp == 16) \ -++ Mcupanel_RegSet(0x0003,0x10B8); /*8-bit system interface two transfers -++ up:0x10B8 down:0x1088 left:0x1090 right:0x10a0*/ \ -++ else \ -++ if (jzfb.bpp == 32)\ -++ Mcupanel_RegSet(0x0003,0xD0B8);/*8-bit system interface three transfers,666 -++ up:0xD0B8 down:0xD088 left:0xD090 right:0xD0A0*/ \ -++ Mcupanel_RegSet(0x0008,0x0204);\ -++ Mcupanel_RegSet(0x000A,0x0008);\ -++ Mcupanel_RegSet(0x0060,0x3100);\ -++ Mcupanel_RegSet(0x0061,0x0001);\ -++ Mcupanel_RegSet(0x0090,0x0052);\ -++ Mcupanel_RegSet(0x0092,0x000F);\ -++ Mcupanel_RegSet(0x0093,0x0001);\ -++ Mcupanel_RegSet(0x009A,0x0008);\ -++ Mcupanel_RegSet(0x00A3,0x0010);\ -++ Mcupanel_RegSet(0x0050,0x0000);\ -++ Mcupanel_RegSet(0x0051,0x00EF);\ -++ Mcupanel_RegSet(0x0052,0x0000);\ -++ Mcupanel_RegSet(0x0053,0x018F);\ -++ /*===Display_On_Function=== */ \ -++ Mcupanel_RegSet(0x0007,0x0001);\ -++ Mcupanel_RegSet(0x0007,0x0021);\ -++ Mcupanel_RegSet(0x0007,0x0023);\ -++ Mcupanel_RegSet(0x0007,0x0033);\ -++ Mcupanel_RegSet(0x0007,0x0133);\ -++ Mcupanel_Command(0x0022);/*Write Data to GRAM */ \ -++ udelay(1); \ -++ Mcupanel_SetAddr(0,0); \ -++ mdelay(100); \ -++} while (0) -++ -++#define __slcd_special_off() \ -++do { \ -++} while(0) -++#endif /*CONFIG_JZ_SLCD_LGDP4551_xxBUS*/ -++ -++#ifdef CONFIG_JZ_SLCD_SPFD5420A -++ -++ //#define PIN_CS_N (32*2+18) // Chip select //GPC18; -++#define PIN_CS_N (32*2+22) // Chip select //GPC18; -++#define PIN_RESET_N (32*1+18) // LCD reset //GPB18; -++#define PIN_RS_N (32*2+19) // LCD RS //GPC19; -++#define PIN_POWER_N (32*3+0) //Power off //GPD0; -++#define PIN_FMARK_N (32*3+1) //fmark //GPD1; -++ -++#define GAMMA() \ -++do { \ -++ Mcupanel_RegSet(0x0300,0x0101); \ -++ Mcupanel_RegSet(0x0301,0x0b27); \ -++ Mcupanel_RegSet(0x0302,0x132a); \ -++ Mcupanel_RegSet(0x0303,0x2a13); \ -++ Mcupanel_RegSet(0x0304,0x270b); \ -++ Mcupanel_RegSet(0x0305,0x0101); \ -++ Mcupanel_RegSet(0x0306,0x1205); \ -++ Mcupanel_RegSet(0x0307,0x0512); \ -++ Mcupanel_RegSet(0x0308,0x0005); \ -++ Mcupanel_RegSet(0x0309,0x0003); \ -++ Mcupanel_RegSet(0x030a,0x0f04); \ -++ Mcupanel_RegSet(0x030b,0x0f00); \ -++ Mcupanel_RegSet(0x030c,0x000f); \ -++ Mcupanel_RegSet(0x030d,0x040f); \ -++ Mcupanel_RegSet(0x030e,0x0300); \ -++ Mcupanel_RegSet(0x030f,0x0500); \ -++ /*** secorrect gamma2 ***/ \ -++ Mcupanel_RegSet(0x0400,0x3500); \ -++ Mcupanel_RegSet(0x0401,0x0001); \ -++ Mcupanel_RegSet(0x0404,0x0000); \ -++ Mcupanel_RegSet(0x0500,0x0000); \ -++ Mcupanel_RegSet(0x0501,0x0000); \ -++ Mcupanel_RegSet(0x0502,0x0000); \ -++ Mcupanel_RegSet(0x0503,0x0000); \ -++ Mcupanel_RegSet(0x0504,0x0000); \ -++ Mcupanel_RegSet(0x0505,0x0000); \ -++ Mcupanel_RegSet(0x0600,0x0000); \ -++ Mcupanel_RegSet(0x0606,0x0000); \ -++ Mcupanel_RegSet(0x06f0,0x0000); \ -++ Mcupanel_RegSet(0x07f0,0x5420); \ -++ Mcupanel_RegSet(0x07f3,0x288a); \ -++ Mcupanel_RegSet(0x07f4,0x0022); \ -++ Mcupanel_RegSet(0x07f5,0x0001); \ -++ Mcupanel_RegSet(0x07f0,0x0000); \ -++} while(0) -++ -++#define __slcd_special_on() \ -++do { \ -++ __gpio_set_pin(PIN_RESET_N); \ -++ mdelay(10); \ -++ __gpio_clear_pin(PIN_RESET_N); \ -++ mdelay(10); \ -++ __gpio_set_pin(PIN_RESET_N); \ -++ mdelay(100); \ -++ if (jzfb.bus == 18) {\ -++ Mcupanel_RegSet(0x0606,0x0000); \ -++ udelay(10); \ -++ Mcupanel_RegSet(0x0007,0x0001); \ -++ udelay(10); \ -++ Mcupanel_RegSet(0x0110,0x0001); \ -++ udelay(10); \ -++ Mcupanel_RegSet(0x0100,0x17b0); \ -++ Mcupanel_RegSet(0x0101,0x0147); \ -++ Mcupanel_RegSet(0x0102,0x019d); \ -++ Mcupanel_RegSet(0x0103,0x8600); \ -++ Mcupanel_RegSet(0x0281,0x0010); \ -++ udelay(10); \ -++ Mcupanel_RegSet(0x0102,0x01bd); \ -++ udelay(10); \ -++ /************initial************/\ -++ Mcupanel_RegSet(0x0000,0x0000); \ -++ Mcupanel_RegSet(0x0001,0x0000); \ -++ Mcupanel_RegSet(0x0002,0x0400); \ -++ Mcupanel_RegSet(0x0003,0x1288); /*up:0x1288 down:0x12B8 left:0x1290 right:0x12A0*/ \ -++ Mcupanel_RegSet(0x0006,0x0000); \ -++ Mcupanel_RegSet(0x0008,0x0503); \ -++ Mcupanel_RegSet(0x0009,0x0001); \ -++ Mcupanel_RegSet(0x000b,0x0010); \ -++ Mcupanel_RegSet(0x000c,0x0000); \ -++ Mcupanel_RegSet(0x000f,0x0000); \ -++ Mcupanel_RegSet(0x0007,0x0001); \ -++ Mcupanel_RegSet(0x0010,0x0010); \ -++ Mcupanel_RegSet(0x0011,0x0202); \ -++ Mcupanel_RegSet(0x0012,0x0300); \ -++ Mcupanel_RegSet(0x0020,0x021e); \ -++ Mcupanel_RegSet(0x0021,0x0202); \ -++ Mcupanel_RegSet(0x0022,0x0100); \ -++ Mcupanel_RegSet(0x0090,0x0000); \ -++ Mcupanel_RegSet(0x0092,0x0000); \ -++ Mcupanel_RegSet(0x0100,0x16b0); \ -++ Mcupanel_RegSet(0x0101,0x0147); \ -++ Mcupanel_RegSet(0x0102,0x01bd); \ -++ Mcupanel_RegSet(0x0103,0x2c00); \ -++ Mcupanel_RegSet(0x0107,0x0000); \ -++ Mcupanel_RegSet(0x0110,0x0001); \ -++ Mcupanel_RegSet(0x0210,0x0000); \ -++ Mcupanel_RegSet(0x0211,0x00ef); \ -++ Mcupanel_RegSet(0x0212,0x0000); \ -++ Mcupanel_RegSet(0x0213,0x018f); \ -++ Mcupanel_RegSet(0x0280,0x0000); \ -++ Mcupanel_RegSet(0x0281,0x0001); \ -++ Mcupanel_RegSet(0x0282,0x0000); \ -++ GAMMA(); \ -++ Mcupanel_RegSet(0x0007,0x0173); \ -++ } else { \ -++ Mcupanel_RegSet(0x0600, 0x0001); /*soft reset*/ \ -++ mdelay(10); \ -++ Mcupanel_RegSet(0x0600, 0x0000); /*soft reset*/ \ -++ mdelay(10); \ -++ Mcupanel_RegSet(0x0606, 0x0000); /*i80-i/F Endian Control*/ \ -++ /*===User setting=== */ \ -++ Mcupanel_RegSet(0x0001, 0x0000);/* Driver Output Control-----0x0100 SM(bit10) | 0x400*/ \ -++ Mcupanel_RegSet(0x0002, 0x0100); /*LCD Driving Wave Control 0x0100 */ \ -++ if (jzfb.bpp == 16) \ -++ Mcupanel_RegSet(0x0003, 0x50A8);/*Entry Mode 0x1030*/ \ -++ else /*bpp = 18*/ \ -++ Mcupanel_RegSet(0x0003, 0x1010 | 0xC8); /*Entry Mode 0x1030*/ \ -++ /*#endif */ \ -++ Mcupanel_RegSet(0x0006, 0x0000); /*Outline Sharpening Control*/\ -++ Mcupanel_RegSet(0x0008, 0x0808); /*Sets the number of lines for front/back porch period*/\ -++ Mcupanel_RegSet(0x0009, 0x0001); /*Display Control 3 */\ -++ Mcupanel_RegSet(0x000B, 0x0010); /*Low Power Control*/\ -++ Mcupanel_RegSet(0x000C, 0x0000); /*External Display Interface Control 1 /*0x0001*/\ -++ Mcupanel_RegSet(0x000F, 0x0000); /*External Display Interface Control 2 */\ -++ Mcupanel_RegSet(0x0400, 0xB104);/*Base Image Number of Line---GS(bit15) | 0x8000*/ \ -++ Mcupanel_RegSet(0x0401, 0x0001); /*Base Image Display 0x0001*/\ -++ Mcupanel_RegSet(0x0404, 0x0000); /*Base Image Vertical Scroll Control 0x0000*/\ -++ Mcupanel_RegSet(0x0500, 0x0000); /*Partial Image 1: Display Position*/\ -++ Mcupanel_RegSet(0x0501, 0x0000); /*RAM Address (Start Line Address) */\ -++ Mcupanel_RegSet(0x0502, 0x018f); /*RAM Address (End Line Address) */ \ -++ Mcupanel_RegSet(0x0503, 0x0000); /*Partial Image 2: Display Position RAM Address*/\ -++ Mcupanel_RegSet(0x0504, 0x0000); /*RAM Address (Start Line Address) */\ -++ Mcupanel_RegSet(0x0505, 0x0000); /*RAM Address (End Line Address)*/\ -++ /*Panel interface control===*/\ -++ Mcupanel_RegSet(0x0010, 0x0011); /*Division Ratio,Clocks per Line 14 */\ -++ mdelay(10); \ -++ Mcupanel_RegSet(0x0011, 0x0202); /*Division Ratio,Clocks per Line*/\ -++ Mcupanel_RegSet(0x0012, 0x0300); /*Sets low power VCOM drive period. */\ -++ mdelay(10); \ -++ Mcupanel_RegSet(0x0020, 0x021e); /*Panel Interface Control 4 */\ -++ Mcupanel_RegSet(0x0021, 0x0202); /*Panel Interface Control 5 */\ -++ Mcupanel_RegSet(0x0022, 0x0100); /*Panel Interface Control 6*/\ -++ Mcupanel_RegSet(0x0090, 0x0000); /*Frame Marker Control */\ -++ Mcupanel_RegSet(0x0092, 0x0000); /*MDDI Sub-display Control */\ -++ /*===Gamma setting=== */\ -++ Mcupanel_RegSet(0x0300, 0x0101); /*γ Control*/\ -++ Mcupanel_RegSet(0x0301, 0x0000); /*γ Control*/\ -++ Mcupanel_RegSet(0x0302, 0x0016); /*γ Control*/\ -++ Mcupanel_RegSet(0x0303, 0x2913); /*γ Control*/\ -++ Mcupanel_RegSet(0x0304, 0x260B); /*γ Control*/\ -++ Mcupanel_RegSet(0x0305, 0x0101); /*γ Control*/\ -++ Mcupanel_RegSet(0x0306, 0x1204); /*γ Control*/\ -++ Mcupanel_RegSet(0x0307, 0x0415); /*γ Control*/\ -++ Mcupanel_RegSet(0x0308, 0x0205); /*γ Control*/\ -++ Mcupanel_RegSet(0x0309, 0x0303); /*γ Control*/\ -++ Mcupanel_RegSet(0x030a, 0x0E05); /*γ Control*/\ -++ Mcupanel_RegSet(0x030b, 0x0D01); /*γ Control*/\ -++ Mcupanel_RegSet(0x030c, 0x010D); /*γ Control*/\ -++ Mcupanel_RegSet(0x030d, 0x050E); /*γ Control*/\ -++ Mcupanel_RegSet(0x030e, 0x0303); /*γ Control*/\ -++ Mcupanel_RegSet(0x030f, 0x0502); /*γ Control*/\ -++ /*===Power on sequence===*/\ -++ Mcupanel_RegSet(0x0007, 0x0001); /*Display Control 1*/\ -++ Mcupanel_RegSet(0x0110, 0x0001); /*Power supply startup enable bit*/\ -++ Mcupanel_RegSet(0x0112, 0x0060); /*Power Control 7*/\ -++ Mcupanel_RegSet(0x0100, 0x16B0); /*Power Control 1 */\ -++ Mcupanel_RegSet(0x0101, 0x0115); /*Power Control 2*/\ -++ Mcupanel_RegSet(0x0102, 0x0119); /*Starts VLOUT3,Sets the VREG1OUT.*/\ -++ mdelay(50); \ -++ Mcupanel_RegSet(0x0103, 0x2E00); /*set the amplitude of VCOM*/\ -++ mdelay(50);\ -++ Mcupanel_RegSet(0x0282, 0x0093);/*0x008E);/*0x0093); /*VCOMH voltage*/\ -++ Mcupanel_RegSet(0x0281, 0x000A); /*Selects the factor of VREG1OUT to generate VCOMH. */\ -++ Mcupanel_RegSet(0x0102, 0x01BE); /*Starts VLOUT3,Sets the VREG1OUT.*/\ -++ mdelay(10);\ -++ /*Address */\ -++ Mcupanel_RegSet(0x0210, 0x0000); /*Window Horizontal RAM Address Start*/\ -++ Mcupanel_RegSet(0x0211, 0x00ef); /*Window Horizontal RAM Address End*/\ -++ Mcupanel_RegSet(0x0212, 0x0000); /*Window Vertical RAM Address Start*/\ -++ Mcupanel_RegSet(0x0213, 0x018f); /*Window Vertical RAM Address End */\ -++ Mcupanel_RegSet(0x0200, 0x0000); /*RAM Address Set (Horizontal Address)*/\ -++ Mcupanel_RegSet(0x0201, 0x018f); /*RAM Address Set (Vertical Address)*/ \ -++ /*===Display_On_Function===*/\ -++ Mcupanel_RegSet(0x0007, 0x0021); /*Display Control 1 */\ -++ mdelay(50); /*40*/\ -++ Mcupanel_RegSet(0x0007, 0x0061); /*Display Control 1 */\ -++ mdelay(50); /*100*/\ -++ Mcupanel_RegSet(0x0007, 0x0173); /*Display Control 1 */\ -++ mdelay(50); /*300*/\ -++ }\ -++ Mcupanel_Command(0x0202); /*Write Data to GRAM */ \ -++ udelay(10);\ -++ Mcupanel_SetAddr(0,0);\ -++ udelay(100);\ -++} while(0) -++ -++#define __slcd_special_pin_init() \ -++do { \ -++ __gpio_as_output(PIN_CS_N); \ -++ __gpio_as_output(PIN_RESET_N); \ -++ __gpio_clear_pin(PIN_CS_N); /* Clear CS */ \ -++ __gpio_as_output(PIN_POWER_N); \ -++ mdelay(100); \ -++} while(0) -++ -++#endif /*CONFIG_JZ_SLCD_SPFD5420A*/ -++ -++#ifndef __slcd_special_pin_init -++#define __slcd_special_pin_init() -++#endif -++#ifndef __slcd_special_on -++#define __slcd_special_on() -++#endif -++#ifndef __slcd_special_off -++#define __slcd_special_off() -++#endif -++ -++/* -++ * Platform specific definition -++ */ -++#if defined(CONFIG_SOC_JZ4740) -++#if defined(CONFIG_JZ4740_PAVO) -++#define GPIO_PWM 123 /* GP_D27 */ -++#define PWM_CHN 4 /* pwm channel */ -++#define PWM_FULL 101 -++/* 100 level: 0,1,...,100 */ -++#define __slcd_set_backlight_level(n)\ -++do { \ -++ __gpio_as_output(32*3+27); \ -++ __gpio_set_pin(32*3+27); \ -++} while (0) -++ -++#define __slcd_close_backlight() \ -++do { \ -++ __gpio_as_output(GPIO_PWM); \ -++ __gpio_clear_pin(GPIO_PWM); \ -++} while (0) -++ -++#else -++ -++#define __slcd_set_backlight_level(n) -++#define __slcd_close_backlight() -++ -++#endif /* #if defined(CONFIG_MIPS_JZ4740_PAVO) */ -++ -++#define __slcd_display_pin_init() \ -++do { \ -++ __slcd_special_pin_init(); \ -++} while (0) -++ -++#define __slcd_display_on() \ -++do { \ -++ __slcd_special_on(); \ -++ __slcd_set_backlight_level(80); \ -++} while (0) -++ -++#define __slcd_display_off() \ -++do { \ -++ __slcd_special_off(); \ -++ __slcd_close_backlight(); \ -++} while (0) -++ -++#endif /* CONFIG_SOC_JZ4740 */ -++#endif /*__JZSLCD_H__*/ -++ -+diff -urN linux-2.6.24.7.old/drivers/video/jz4750_lcd.c linux-2.6.24.7/drivers/video/jz4750_lcd.c -+--- linux-2.6.24.7.old/drivers/video/jz4750_lcd.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/video/jz4750_lcd.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,2139 @@ -++/* -++ * linux/drivers/video/jz4750_lcd.c -- Ingenic Jz4750 LCD frame buffer device -++ * -++ * Copyright (C) 2005-2008, Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++/* -++ * -------------------------------- -++ * NOTE: -++ * This LCD driver support TFT16 TFT32 LCD, not support STN and Special TFT LCD -++ * now. -++ * It seems not necessory to support STN and Special TFT. -++ * If it's necessary, update this driver in the future. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "console/fbcon.h" -++ -++#include "jz4750_lcd.h" -++#include "jz4750_tve.h" -++ -++#ifdef CONFIG_JZ4750_SLCD_KGM701A3_TFT_SPFD5420A -++#include "jz_kgm_spfd5420a.h" -++#endif -++ -++MODULE_DESCRIPTION("Jz4750 LCD Controller driver"); -++MODULE_AUTHOR("Wolfgang Wang, "); -++MODULE_LICENSE("GPL"); -++ -++ -++//#define DEBUG -++#undef DEBUG -++ -++#ifdef DEBUG -++#define dprintk(x...) printk(x) -++#define print_dbg(f, arg...) printk("dbg::" __FILE__ ",LINE(%d): " f "\n", __LINE__, ## arg) -++#else -++#define dprintk(x...) -++#define print_dbg(f, arg...) do {} while (0) -++#endif -++ -++#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) -++#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) -++#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) -++ -++struct lcd_cfb_info { -++ struct fb_info fb; -++ struct display_switch *dispsw; -++ signed int currcon; -++ int func_use_count; -++ -++ struct { -++ u16 red, green, blue; -++ } palette[NR_PALETTE]; -++#ifdef CONFIG_PM -++ struct pm_dev *pm; -++#endif -++}; -++ -++static struct lcd_cfb_info *jz4750fb_info; -++static struct jz4750_lcd_dma_desc *dma_desc_base; -++static struct jz4750_lcd_dma_desc *dma0_desc_palette, *dma0_desc0, *dma0_desc1, *dma1_desc0, *dma1_desc1; -++#define DMA_DESC_NUM 6 -++ -++static unsigned char *lcd_palette; -++static unsigned char *lcd_frame0; -++static unsigned char *lcd_frame1; -++ -++static struct jz4750_lcd_dma_desc *dma0_desc_cmd0, *dma0_desc_cmd; -++static unsigned char *lcd_cmdbuf ; -++ -++static void jz4750fb_set_mode( struct jz4750lcd_info * lcd_info ); -++static void jz4750fb_deep_set_mode( struct jz4750lcd_info * lcd_info ); -++ -++ -++ -++struct jz4750lcd_info jz4750_lcd_panel = { -++#if defined(CONFIG_JZ4750_LCD_SAMSUNG_LTP400WQF02) -++ .panel = { -++ .cfg = LCD_CFG_LCDPIN_LCD | LCD_CFG_RECOVER | /* Underrun recover */ -++ LCD_CFG_NEWDES | /* 8words descriptor */ -++ LCD_CFG_MODE_GENERIC_TFT | /* General TFT panel */ -++ LCD_CFG_MODE_TFT_18BIT | /* output 18bpp */ -++ LCD_CFG_HSP | /* Hsync polarity: active low */ -++ LCD_CFG_VSP, /* Vsync polarity: leading edge is falling edge */ -++ .slcd_cfg = 0, -++ .ctrl = LCD_CTRL_OFUM | LCD_CTRL_BST_16, /* 16words burst, enable out FIFO underrun irq */ -++ 480, 272, 60, 41, 10, 2, 2, 2, 2, -++ }, -++ .osd = { -++ .osd_cfg = LCD_OSDC_OSDEN | /* Use OSD mode */ -++// LCD_OSDC_ALPHAEN | /* enable alpha */ -++ LCD_OSDC_F0EN, /* enable Foreground0 */ -++ .osd_ctrl = 0, /* disable ipu, */ -++ .rgb_ctrl = 0, -++ .bgcolor = 0x000000, /* set background color Black */ -++ .colorkey0 = 0, /* disable colorkey */ -++ .colorkey1 = 0, /* disable colorkey */ -++ .alpha = 0xA0, /* alpha value */ -++ .ipu_restart = 0x80001000, /* ipu restart */ -++ .fg_change = FG_CHANGE_ALL, /* change all initially */ -++ .fg0 = {32, 0, 0, 480, 272}, /* bpp, x, y, w, h */ -++ .fg1 = {32, 0, 0, 480, 272}, /* bpp, x, y, w, h */ -++ }, -++#elif defined(CONFIG_JZ4750_LCD_AUO_A043FL01V2) -++ .panel = { -++ .cfg = LCD_CFG_LCDPIN_LCD | LCD_CFG_RECOVER | /* Underrun recover */ -++ LCD_CFG_NEWDES | /* 8words descriptor */ -++ LCD_CFG_MODE_GENERIC_TFT | /* General TFT panel */ -++ LCD_CFG_MODE_TFT_24BIT | /* output 18bpp */ -++ LCD_CFG_HSP | /* Hsync polarity: active low */ -++ LCD_CFG_VSP, /* Vsync polarity: leading edge is falling edge */ -++ .slcd_cfg = 0, -++ .ctrl = LCD_CTRL_OFUM | LCD_CTRL_BST_16, /* 16words burst, enable out FIFO underrun irq */ -++ 480, 272, 60, 41, 10, 8, 4, 4, 2, -++ }, -++ .osd = { -++ .osd_cfg = LCD_OSDC_OSDEN | /* Use OSD mode */ -++// LCD_OSDC_ALPHAEN | /* enable alpha */ -++// LCD_OSDC_F1EN | /* enable Foreground1 */ -++ LCD_OSDC_F0EN, /* enable Foreground0 */ -++ .osd_ctrl = 0, /* disable ipu, */ -++ .rgb_ctrl = 0, -++ .bgcolor = 0x000000, /* set background color Black */ -++ .colorkey0 = 0, /* disable colorkey */ -++ .colorkey1 = 0, /* disable colorkey */ -++ .alpha = 0xA0, /* alpha value */ -++ .ipu_restart = 0x80001000, /* ipu restart */ -++ .fg_change = FG_CHANGE_ALL, /* change all initially */ -++ .fg0 = {32, 0, 0, 480, 272}, /* bpp, x, y, w, h */ -++ .fg1 = {32, 0, 0, 480, 272}, /* bpp, x, y, w, h */ -++ }, -++#elif defined(CONFIG_JZ4750_LCD_TRULY_TFT_GG1P0319LTSW_W) -++ .panel = { -++// .cfg = LCD_CFG_LCDPIN_SLCD | LCD_CFG_RECOVER | /* Underrun recover*/ -++ .cfg = LCD_CFG_LCDPIN_SLCD | /* Underrun recover*/ -++ LCD_CFG_NEWDES | /* 8words descriptor */ -++ LCD_CFG_MODE_SLCD, /* TFT Smart LCD panel */ -++ .slcd_cfg = SLCD_CFG_DWIDTH_16BIT | SLCD_CFG_CWIDTH_16BIT | SLCD_CFG_CS_ACTIVE_LOW | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING | SLCD_CFG_TYPE_PARALLEL, -++ .ctrl = LCD_CTRL_OFUM | LCD_CTRL_BST_16, /* 16words burst, enable out FIFO underrun irq */ -++ 240, 320, 60, 0, 0, 0, 0, 0, 0, -++ }, -++ .osd = { -++ .osd_cfg = LCD_OSDC_OSDEN | /* Use OSD mode */ -++// LCD_OSDC_ALPHAEN | /* enable alpha */ -++// LCD_OSDC_F1EN | /* enable Foreground0 */ -++ LCD_OSDC_F0EN, /* enable Foreground0 */ -++ .osd_ctrl = 0, /* disable ipu, */ -++ .rgb_ctrl = 0, -++ .bgcolor = 0x000000, /* set background color Black */ -++ .colorkey0 = 0, /* disable colorkey */ -++ .colorkey1 = 0, /* disable colorkey */ -++ .alpha = 0xA0, /* alpha value */ -++ .ipu_restart = 0x80001000, /* ipu restart */ -++ .fg_change = FG_CHANGE_ALL, /* change all initially */ -++ .fg0 = {32, 0, 0, 240, 320}, /* bpp, x, y, w, h */ -++ .fg1 = {32, 0, 0, 240, 320}, /* bpp, x, y, w, h */ -++ }, -++ -++#elif defined(CONFIG_JZ4750_LCD_FOXCONN_PT035TN01) -++ .panel = { -++ .cfg = LCD_CFG_LCDPIN_LCD | LCD_CFG_RECOVER | /* Underrun recover */ -++ LCD_CFG_NEWDES | /* 8words descriptor */ -++ LCD_CFG_MODE_GENERIC_TFT | /* General TFT panel */ -++// LCD_CFG_MODE_TFT_18BIT | /* output 18bpp */ -++ LCD_CFG_MODE_TFT_24BIT | /* output 24bpp */ -++ LCD_CFG_HSP | /* Hsync polarity: active low */ -++ LCD_CFG_VSP | /* Vsync polarity: leading edge is falling edge */ -++ LCD_CFG_PCP, /* Pix-CLK polarity: data translations at falling edge */ -++ .slcd_cfg = 0, -++ .ctrl = LCD_CTRL_OFUM | LCD_CTRL_BST_16, /* 16words burst, enable out FIFO underrun irq */ -++ 320, 240, 80, 1, 1, 10, 50, 10, 13 -++ }, -++ .osd = { -++ .osd_cfg = LCD_OSDC_OSDEN | /* Use OSD mode */ -++// LCD_OSDC_ALPHAEN | /* enable alpha */ -++// LCD_OSDC_F1EN | /* enable Foreground1 */ -++ LCD_OSDC_F0EN, /* enable Foreground0 */ -++ .osd_ctrl = 0, /* disable ipu, */ -++ .rgb_ctrl = 0, -++ .bgcolor = 0x000000, /* set background color Black */ -++ .colorkey0 = 0, /* disable colorkey */ -++ .colorkey1 = 0, /* disable colorkey */ -++ .alpha = 0xA0, /* alpha value */ -++ .ipu_restart = 0x80001000, /* ipu restart */ -++ .fg_change = FG_CHANGE_ALL, /* change all initially */ -++ .fg0 = {32, 0, 0, 320, 240}, /* bpp, x, y, w, h */ -++ .fg1 = {32, 0, 0, 320, 240}, /* bpp, x, y, w, h */ -++ }, -++#elif defined(CONFIG_JZ4750_LCD_INNOLUX_PT035TN01_SERIAL) -++ .panel = { -++ .cfg = LCD_CFG_LCDPIN_LCD | LCD_CFG_RECOVER | /* Underrun recover */ -++ LCD_CFG_NEWDES | /* 8words descriptor */ -++ LCD_CFG_MODE_SERIAL_TFT | /* Serial TFT panel */ -++ LCD_CFG_MODE_TFT_18BIT | /* output 18bpp */ -++ LCD_CFG_HSP | /* Hsync polarity: active low */ -++ LCD_CFG_VSP | /* Vsync polarity: leading edge is falling edge */ -++ LCD_CFG_PCP, /* Pix-CLK polarity: data translations at falling edge */ -++ .slcd_cfg = 0, -++ .ctrl = LCD_CTRL_OFUM | LCD_CTRL_BST_16, /* 16words burst, enable out FIFO underrun irq */ -++ 320, 240, 60, 1, 1, 10, 50, 10, 13 -++ }, -++ .osd = { -++ .osd_cfg = LCD_OSDC_OSDEN | /* Use OSD mode */ -++// LCD_OSDC_ALPHAEN | /* enable alpha */ -++ LCD_OSDC_F0EN, /* enable Foreground0 */ -++ .osd_ctrl = 0, /* disable ipu, */ -++ .rgb_ctrl = 0, -++ .bgcolor = 0x000000, /* set background color Black */ -++ .colorkey0 = 0, /* disable colorkey */ -++ .colorkey1 = 0, /* disable colorkey */ -++ .alpha = 0xA0, /* alpha value */ -++ .ipu_restart = 0x80001000, /* ipu restart */ -++ .fg_change = FG_CHANGE_ALL, /* change all initially */ -++ .fg0 = {32, 0, 0, 320, 240}, /* bpp, x, y, w, h */ -++ .fg1 = {32, 0, 0, 320, 240}, /* bpp, x, y, w, h */ -++ }, -++#elif defined(CONFIG_JZ4750_SLCD_KGM701A3_TFT_SPFD5420A) -++ .panel = { -++// .cfg = LCD_CFG_LCDPIN_SLCD | LCD_CFG_RECOVER | /* Underrun recover*/ -++ .cfg = LCD_CFG_LCDPIN_SLCD | /* Underrun recover*/ -++// LCD_CFG_DITHER | /* dither */ -++ LCD_CFG_NEWDES | /* 8words descriptor */ -++ LCD_CFG_MODE_SLCD, /* TFT Smart LCD panel */ -++ .slcd_cfg = SLCD_CFG_DWIDTH_18BIT | SLCD_CFG_CWIDTH_18BIT | SLCD_CFG_CS_ACTIVE_LOW | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING | SLCD_CFG_TYPE_PARALLEL, -++ .ctrl = LCD_CTRL_OFUM | LCD_CTRL_BST_16, /* 16words burst, enable out FIFO underrun irq */ -++ 400, 240, 60, 0, 0, 0, 0, 0, 0, -++ }, -++ .osd = { -++ .osd_cfg = LCD_OSDC_OSDEN | /* Use OSD mode */ -++// LCD_OSDC_ALPHAEN | /* enable alpha */ -++// LCD_OSDC_ALPHAMD | /* alpha blending mode */ -++// LCD_OSDC_F1EN | /* enable Foreground1 */ -++ LCD_OSDC_F0EN, /* enable Foreground0 */ -++ .osd_ctrl = 0, /* disable ipu, */ -++ .rgb_ctrl = 0, -++ .bgcolor = 0x000000, /* set background color Black */ -++ .colorkey0 = 0, /* disable colorkey */ -++ .colorkey1 = 0, /* disable colorkey */ -++ .alpha = 0xA0, /* alpha value */ -++ .ipu_restart = 0x80001000, /* ipu restart */ -++ .fg_change = FG_CHANGE_ALL, /* change all initially */ -++ .fg0 = {32, 0, 0, 400, 240}, /* bpp, x, y, w, h */ -++ .fg1 = {32, 0, 0, 400, 240}, /* bpp, x, y, w, h */ -++ }, -++#else -++#error "Select LCD panel first!!!" -++#endif -++}; -++ -++struct jz4750lcd_info jz4750_info_tve = { -++ .panel = { -++ .cfg = LCD_CFG_TVEN | /* output to tve */ -++ LCD_CFG_NEWDES | /* 8words descriptor */ -++ LCD_CFG_RECOVER | /* underrun protect */ -++ LCD_CFG_MODE_INTER_CCIR656, /* Interlace CCIR656 mode */ -++ .ctrl = LCD_CTRL_OFUM | LCD_CTRL_BST_16, /* 16words burst */ -++ TVE_WIDTH_PAL, TVE_HEIGHT_PAL, TVE_FREQ_PAL, 0, 0, 0, 0, 0, 0, -++ }, -++ .osd = { -++ .osd_cfg = LCD_OSDC_OSDEN | /* Use OSD mode */ -++// LCD_OSDC_ALPHAEN | /* enable alpha */ -++ LCD_OSDC_F0EN, /* enable Foreground0 */ -++ .osd_ctrl = 0, /* disable ipu, */ -++ .rgb_ctrl = LCD_RGBC_YCC, /* enable RGB => YUV */ -++ .bgcolor = 0x00000000, /* set background color Black */ -++ .colorkey0 = 0, /* disable colorkey */ -++ .colorkey1 = 0, /* disable colorkey */ -++ .alpha = 0xA0, /* alpha value */ -++ .ipu_restart = 0x80000100, /* ipu restart */ -++ .fg_change = FG_CHANGE_ALL, /* change all initially */ -++ .fg0 = {32,}, /* */ -++ .fg0 = {32,}, -++ }, -++}; -++ -++ -++struct jz4750lcd_info *jz4750_lcd_info = &jz4750_lcd_panel; /* default output to lcd panel */ -++ -++#ifdef DEBUG -++static void print_lcdc_registers(void) /* debug */ -++{ -++ /* LCD Controller Resgisters */ -++ printk("REG_LCD_CFG:\t0x%08x\n", REG_LCD_CFG); -++ printk("REG_LCD_CTRL:\t0x%08x\n", REG_LCD_CTRL); -++ printk("REG_LCD_STATE:\t0x%08x\n", REG_LCD_STATE); -++ printk("REG_LCD_OSDC:\t0x%08x\n", REG_LCD_OSDC); -++ printk("REG_LCD_OSDCTRL:\t0x%08x\n", REG_LCD_OSDCTRL); -++ printk("REG_LCD_OSDS:\t0x%08x\n", REG_LCD_OSDS); -++ printk("REG_LCD_BGC:\t0x%08x\n", REG_LCD_BGC); -++ printk("REG_LCD_KEK0:\t0x%08x\n", REG_LCD_KEY0); -++ printk("REG_LCD_KEY1:\t0x%08x\n", REG_LCD_KEY1); -++ printk("REG_LCD_ALPHA:\t0x%08x\n", REG_LCD_ALPHA); -++ printk("REG_LCD_IPUR:\t0x%08x\n", REG_LCD_IPUR); -++ printk("REG_LCD_VAT:\t0x%08x\n", REG_LCD_VAT); -++ printk("REG_LCD_DAH:\t0x%08x\n", REG_LCD_DAH); -++ printk("REG_LCD_DAV:\t0x%08x\n", REG_LCD_DAV); -++ printk("REG_LCD_XYP0:\t0x%08x\n", REG_LCD_XYP0); -++ printk("REG_LCD_XYP1:\t0x%08x\n", REG_LCD_XYP1); -++ printk("REG_LCD_SIZE0:\t0x%08x\n", REG_LCD_SIZE0); -++ printk("REG_LCD_SIZE1:\t0x%08x\n", REG_LCD_SIZE1); -++ printk("REG_LCD_RGBC\t0x%08x\n", REG_LCD_RGBC); -++ printk("REG_LCD_VSYNC:\t0x%08x\n", REG_LCD_VSYNC); -++ printk("REG_LCD_HSYNC:\t0x%08x\n", REG_LCD_HSYNC); -++ printk("REG_LCD_PS:\t0x%08x\n", REG_LCD_PS); -++ printk("REG_LCD_CLS:\t0x%08x\n", REG_LCD_CLS); -++ printk("REG_LCD_SPL:\t0x%08x\n", REG_LCD_SPL); -++ printk("REG_LCD_REV:\t0x%08x\n", REG_LCD_REV); -++ printk("REG_LCD_IID:\t0x%08x\n", REG_LCD_IID); -++ printk("REG_LCD_DA0:\t0x%08x\n", REG_LCD_DA0); -++ printk("REG_LCD_SA0:\t0x%08x\n", REG_LCD_SA0); -++ printk("REG_LCD_FID0:\t0x%08x\n", REG_LCD_FID0); -++ printk("REG_LCD_CMD0:\t0x%08x\n", REG_LCD_CMD0); -++ printk("REG_LCD_OFFS0:\t0x%08x\n", REG_LCD_OFFS0); -++ printk("REG_LCD_PW0:\t0x%08x\n", REG_LCD_PW0); -++ printk("REG_LCD_CNUM0:\t0x%08x\n", REG_LCD_CNUM0); -++ printk("REG_LCD_DESSIZE0:\t0x%08x\n", REG_LCD_DESSIZE0); -++ printk("REG_LCD_DA1:\t0x%08x\n", REG_LCD_DA1); -++ printk("REG_LCD_SA1:\t0x%08x\n", REG_LCD_SA1); -++ printk("REG_LCD_FID1:\t0x%08x\n", REG_LCD_FID1); -++ printk("REG_LCD_CMD1:\t0x%08x\n", REG_LCD_CMD1); -++ printk("REG_LCD_OFFS1:\t0x%08x\n", REG_LCD_OFFS1); -++ printk("REG_LCD_PW1:\t0x%08x\n", REG_LCD_PW1); -++ printk("REG_LCD_CNUM1:\t0x%08x\n", REG_LCD_CNUM1); -++ printk("REG_LCD_DESSIZE1:\t0x%08x\n", REG_LCD_DESSIZE1); -++ printk("==================================\n"); -++ printk("REG_LCD_VSYNC:\t%d:%d\n", REG_LCD_VSYNC>>16, REG_LCD_VSYNC&0xfff); -++ printk("REG_LCD_HSYNC:\t%d:%d\n", REG_LCD_HSYNC>>16, REG_LCD_HSYNC&0xfff); -++ printk("REG_LCD_VAT:\t%d:%d\n", REG_LCD_VAT>>16, REG_LCD_VAT&0xfff); -++ printk("REG_LCD_DAH:\t%d:%d\n", REG_LCD_DAH>>16, REG_LCD_DAH&0xfff); -++ printk("REG_LCD_DAV:\t%d:%d\n", REG_LCD_DAV>>16, REG_LCD_DAV&0xfff); -++ printk("==================================\n"); -++ -++ /* Smart LCD Controller Resgisters */ -++ printk("REG_SLCD_CFG:\t0x%08x\n", REG_SLCD_CFG); -++ printk("REG_SLCD_CTRL:\t0x%08x\n", REG_SLCD_CTRL); -++ printk("REG_SLCD_STATE:\t0x%08x\n", REG_SLCD_STATE); -++ printk("==================================\n"); -++ -++ /* TVE Controller Resgisters */ -++ printk("REG_TVE_CTRL:\t0x%08x\n", REG_TVE_CTRL); -++ printk("REG_TVE_FRCFG:\t0x%08x\n", REG_TVE_FRCFG); -++ printk("REG_TVE_SLCFG1:\t0x%08x\n", REG_TVE_SLCFG1); -++ printk("REG_TVE_SLCFG2:\t0x%08x\n", REG_TVE_SLCFG2); -++ printk("REG_TVE_SLCFG3:\t0x%08x\n", REG_TVE_SLCFG3); -++ printk("REG_TVE_LTCFG1:\t0x%08x\n", REG_TVE_LTCFG1); -++ printk("REG_TVE_LTCFG2:\t0x%08x\n", REG_TVE_LTCFG2); -++ printk("REG_TVE_CFREQ:\t0x%08x\n", REG_TVE_CFREQ); -++ printk("REG_TVE_CPHASE:\t0x%08x\n", REG_TVE_CPHASE); -++ printk("REG_TVE_CBCRCFG:\t0x%08x\n", REG_TVE_CBCRCFG); -++ printk("REG_TVE_WSSCR:\t0x%08x\n", REG_TVE_WSSCR); -++ printk("REG_TVE_WSSCFG1:\t0x%08x\n", REG_TVE_WSSCFG1); -++ printk("REG_TVE_WSSCFG2:\t0x%08x\n", REG_TVE_WSSCFG2); -++ printk("REG_TVE_WSSCFG3:\t0x%08x\n", REG_TVE_WSSCFG3); -++ -++ printk("==================================\n"); -++ -++ if ( 1 ) { -++ unsigned int * pii = (unsigned int *)dma_desc_base; -++ int i, j; -++ for (j=0;j< DMA_DESC_NUM ; j++) { -++ printk("dma_desc%d(0x%08x):\n", j, (unsigned int)pii); -++ for (i =0; i<8; i++ ) { -++ printk("\t\t0x%08x\n", *pii++); -++ } -++ } -++ } -++} -++#else -++#define print_lcdc_registers() -++#endif -++ -++static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) -++{ -++ chan &= 0xffff; -++ chan >>= 16 - bf->length; -++ return chan << bf->offset; -++} -++ -++static int jz4750fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, -++ u_int transp, struct fb_info *info) -++{ -++ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -++ unsigned short *ptr, ctmp; -++ -++// print_dbg("regno:%d,RGBt:(%d,%d,%d,%d)\t", regno, red, green, blue, transp); -++ if (regno >= NR_PALETTE) -++ return 1; -++ -++ cfb->palette[regno].red = red ; -++ cfb->palette[regno].green = green; -++ cfb->palette[regno].blue = blue; -++ if (cfb->fb.var.bits_per_pixel <= 16) { -++ red >>= 8; -++ green >>= 8; -++ blue >>= 8; -++ -++ red &= 0xff; -++ green &= 0xff; -++ blue &= 0xff; -++ } -++ switch (cfb->fb.var.bits_per_pixel) { -++ case 1: -++ case 2: -++ case 4: -++ case 8: -++ if (((jz4750_lcd_info->panel.cfg & LCD_CFG_MODE_MASK) == LCD_CFG_MODE_SINGLE_MSTN ) || -++ ((jz4750_lcd_info->panel.cfg & LCD_CFG_MODE_MASK) == LCD_CFG_MODE_DUAL_MSTN )) { -++ ctmp = (77L * red + 150L * green + 29L * blue) >> 8; -++ ctmp = ((ctmp >> 3) << 11) | ((ctmp >> 2) << 5) | -++ (ctmp >> 3); -++ } else { -++ /* RGB 565 */ -++ if (((red >> 3) == 0) && ((red >> 2) != 0)) -++ red = 1 << 3; -++ if (((blue >> 3) == 0) && ((blue >> 2) != 0)) -++ blue = 1 << 3; -++ ctmp = ((red >> 3) << 11) -++ | ((green >> 2) << 5) | (blue >> 3); -++ } -++ -++ ptr = (unsigned short *)lcd_palette; -++ ptr = (unsigned short *)(((u32)ptr)|0xa0000000); -++ ptr[regno] = ctmp; -++ -++ break; -++ -++ case 15: -++ if (regno < 16) -++ ((u32 *)cfb->fb.pseudo_palette)[regno] = -++ ((red >> 3) << 10) | -++ ((green >> 3) << 5) | -++ (blue >> 3); -++ break; -++ case 16: -++ if (regno < 16) { -++ ((u32 *)cfb->fb.pseudo_palette)[regno] = -++ ((red >> 3) << 11) | -++ ((green >> 2) << 5) | -++ (blue >> 3); -++ } -++ break; -++ case 17 ... 32: -++ if (regno < 16) -++ ((u32 *)cfb->fb.pseudo_palette)[regno] = -++ (red << 16) | -++ (green << 8) | -++ (blue << 0); -++ -++/* if (regno < 16) { -++ unsigned val; -++ val = chan_to_field(red, &cfb->fb.var.red); -++ val |= chan_to_field(green, &cfb->fb.var.green); -++ val |= chan_to_field(blue, &cfb->fb.var.blue); -++ ((u32 *)cfb->fb.pseudo_palette)[regno] = val; -++ } -++*/ -++ -++ break; -++ } -++ return 0; -++} -++ -++ -++/* -++ * switch to tve mode from lcd mode -++ * mode: -++ * PANEL_MODE_TVE_PAL: switch to TVE_PAL mode -++ * PANEL_MODE_TVE_NTSC: switch to TVE_NTSC mode -++ */ -++static void jz4750lcd_info_switch_to_TVE(int mode) -++{ -++ struct jz4750lcd_info *info; -++ struct jz4750lcd_osd_t *osd_lcd; -++ int x, y, w, h; -++ -++ info = jz4750_lcd_info = &jz4750_info_tve; -++ osd_lcd = &jz4750_lcd_panel.osd; -++ -++ switch ( mode ) { -++ case PANEL_MODE_TVE_PAL: -++ info->panel.cfg |= LCD_CFG_TVEPEH; /* TVE PAL enable extra halfline signal */ -++ info->panel.w = TVE_WIDTH_PAL; -++ info->panel.h = TVE_HEIGHT_PAL; -++ info->panel.fclk = TVE_FREQ_PAL; -++ w = ( osd_lcd->fg0.w < TVE_WIDTH_PAL )? osd_lcd->fg0.w:TVE_WIDTH_PAL; -++ h = ( osd_lcd->fg0.h < TVE_HEIGHT_PAL )?osd_lcd->fg0.h:TVE_HEIGHT_PAL; -++ x = (TVE_WIDTH_PAL-w)/2; -++ y = (TVE_HEIGHT_PAL-h)/2; -++ info->osd.fg0.bpp = osd_lcd->fg0.bpp; -++ info->osd.fg0.x = x; -++ info->osd.fg0.y = y; -++ info->osd.fg0.w = w; -++ info->osd.fg0.h = h; -++ w = ( osd_lcd->fg1.w < TVE_WIDTH_PAL )? osd_lcd->fg1.w:TVE_WIDTH_PAL; -++ h = ( osd_lcd->fg1.h < TVE_HEIGHT_PAL )?osd_lcd->fg1.h:TVE_HEIGHT_PAL; -++ x = (TVE_WIDTH_PAL-w)/2; -++ y = (TVE_HEIGHT_PAL-h)/2; -++ info->osd.fg1.bpp = 32; /* use RGB888 in TVE mode*/ -++ info->osd.fg1.x = x; -++ info->osd.fg1.y = y; -++ info->osd.fg1.w = w; -++ info->osd.fg1.h = h; -++ break; -++ case PANEL_MODE_TVE_NTSC: -++ info->panel.cfg &= ~LCD_CFG_TVEPEH; /* TVE NTSC disable extra halfline signal */ -++ info->panel.w = TVE_WIDTH_NTSC; -++ info->panel.h = TVE_HEIGHT_NTSC; -++ info->panel.fclk = TVE_FREQ_NTSC; -++ w = ( osd_lcd->fg0.w < TVE_WIDTH_NTSC )? osd_lcd->fg0.w:TVE_WIDTH_NTSC; -++ h = ( osd_lcd->fg0.h < TVE_HEIGHT_NTSC)?osd_lcd->fg0.h:TVE_HEIGHT_NTSC; -++ x = (TVE_WIDTH_NTSC - w)/2; -++ y = (TVE_HEIGHT_NTSC - h)/2; -++ info->osd.fg0.bpp = osd_lcd->fg0.bpp; -++ info->osd.fg0.x = x; -++ info->osd.fg0.y = y; -++ info->osd.fg0.w = w; -++ info->osd.fg0.h = h; -++ w = ( osd_lcd->fg1.w < TVE_WIDTH_NTSC )? osd_lcd->fg1.w:TVE_WIDTH_NTSC; -++ h = ( osd_lcd->fg1.h < TVE_HEIGHT_NTSC)?osd_lcd->fg1.h:TVE_HEIGHT_NTSC; -++ x = (TVE_WIDTH_NTSC - w)/2; -++ y = (TVE_HEIGHT_NTSC - h)/2; -++ info->osd.fg1.bpp = 32; /* use RGB888 int TVE mode */ -++ info->osd.fg1.x = x; -++ info->osd.fg1.y = y; -++ info->osd.fg1.w = w; -++ info->osd.fg1.h = h; -++ break; -++ default: -++ printk("%s, %s: Unknown tve mode\n", __FILE__, __FUNCTION__); -++ } -++} -++ -++static int jz4750fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) -++{ -++ int ret = 0; -++ -++ void __user *argp = (void __user *)arg; -++ -++// struct jz4750lcd_info *lcd_info = jz4750_lcd_info; -++ -++ -++ switch (cmd) { -++ case FBIOSETBACKLIGHT: -++ __lcd_set_backlight_level(arg); /* We support 8 levels here. */ -++ break; -++ case FBIODISPON: -++ REG_LCD_STATE = 0; /* clear lcdc status */ -++ __lcd_slcd_special_on(); -++ __lcd_clr_dis(); -++ __lcd_set_ena(); /* enable lcdc */ -++ __lcd_display_on(); -++ break; -++ case FBIODISPOFF: -++ __lcd_display_off(); -++ if ( jz4750_lcd_info->panel.cfg & LCD_CFG_LCDPIN_SLCD || -++ jz4750_lcd_info->panel.cfg & LCD_CFG_TVEN ) /* */ -++ __lcd_clr_ena(); /* Smart lcd and TVE mode only support quick disable */ -++ else -++ __lcd_set_dis(); /* regular disable */ -++ break; -++ case FBIOPRINT_REG: -++ print_lcdc_registers(); -++ break; -++ case FBIO_GET_MODE: -++ print_dbg("fbio get mode\n"); -++ if (copy_to_user(argp, jz4750_lcd_info, sizeof(struct jz4750lcd_info))) -++ return -EFAULT; -++ break; -++ case FBIO_SET_MODE: -++ print_dbg("fbio set mode\n"); -++ if (copy_from_user(jz4750_lcd_info, argp, sizeof(struct jz4750lcd_info))) -++ return -EFAULT; -++ /* set mode */ -++ jz4750fb_set_mode(jz4750_lcd_info); -++ break; -++ case FBIO_DEEP_SET_MODE: -++ print_dbg("fbio deep set mode\n"); -++ if (copy_from_user(jz4750_lcd_info, argp, sizeof(struct jz4750lcd_info))) -++ return -EFAULT; -++ jz4750fb_deep_set_mode(jz4750_lcd_info); -++ break; -++ case FBIO_MODE_SWITCH: -++ print_dbg("lcd mode switch between tve and lcd, arg=%lu\n", arg); -++ switch ( arg ) { -++ case PANEL_MODE_TVE_PAL: /* switch to TVE_PAL mode */ -++ case PANEL_MODE_TVE_NTSC: /* switch to TVE_NTSC mode */ -++ jz4750lcd_info_switch_to_TVE(arg); -++ jz4750tve_init(arg); /* tve controller init */ -++ jz4750tve_enable_tve(); -++ /* turn off lcd backlight */ -++ __lcd_display_off(); -++ break; -++ case PANEL_MODE_LCD_PANEL: /* switch to LCD mode */ -++ default : -++ /* turn off TVE, turn off DACn... */ -++ jz4750tve_disable_tve(); -++ jz4750_lcd_info = &jz4750_lcd_panel; -++ /* turn on lcd backlight */ -++ __lcd_display_on(); -++ break; -++ } -++ jz4750fb_deep_set_mode(jz4750_lcd_info); -++ break; -++ case FBIO_GET_TVE_MODE: -++ print_dbg("fbio get TVE mode\n"); -++ if (copy_to_user(argp, jz4750_tve_info, sizeof(struct jz4750tve_info))) -++ return -EFAULT; -++ break; -++ case FBIO_SET_TVE_MODE: -++ print_dbg("fbio set TVE mode\n"); -++ if (copy_from_user(jz4750_tve_info, argp, sizeof(struct jz4750tve_info))) -++ return -EFAULT; -++ /* set tve mode */ -++ jz4750tve_set_tve_mode(jz4750_tve_info); -++ break; -++ default: -++ printk("%s, unknown command(0x%x)", __FILE__, cmd); -++ break; -++ } -++ -++ return ret; -++} -++ -++/* Use mmap /dev/fb can only get a non-cacheable Virtual Address. */ -++static int jz4750fb_mmap(struct fb_info *info, struct vm_area_struct *vma) -++{ -++ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -++ unsigned long start; -++ unsigned long off; -++ u32 len; -++ dprintk("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); -++ off = vma->vm_pgoff << PAGE_SHIFT; -++ //fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); -++ -++ /* frame buffer memory */ -++ start = cfb->fb.fix.smem_start; -++ len = PAGE_ALIGN((start & ~PAGE_MASK) + cfb->fb.fix.smem_len); -++ start &= PAGE_MASK; -++ -++ if ((vma->vm_end - vma->vm_start + off) > len) -++ return -EINVAL; -++ off += start; -++ -++ vma->vm_pgoff = off >> PAGE_SHIFT; -++ vma->vm_flags |= VM_IO; -++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* Uncacheable */ -++ -++#if 1 -++ pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; -++ pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; /* Uncacheable */ -++// pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; /* Write-Back */ -++#endif -++ -++ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, -++ vma->vm_end - vma->vm_start, -++ vma->vm_page_prot)) { -++ return -EAGAIN; -++ } -++ return 0; -++} -++ -++/* checks var and eventually tweaks it to something supported, -++ * DO NOT MODIFY PAR */ -++static int jz4750fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -++{ -++ printk("jz4750fb_check_var, not implement\n"); -++ return 0; -++} -++ -++ -++/* -++ * set the video mode according to info->var -++ */ -++static int jz4750fb_set_par(struct fb_info *info) -++{ -++ printk("jz4750fb_set_par, not implemented\n"); -++ return 0; -++} -++ -++ -++/* -++ * (Un)Blank the display. -++ * Fix me: should we use VESA value? -++ */ -++static int jz4750fb_blank(int blank_mode, struct fb_info *info) -++{ -++ dprintk("jz4750 fb_blank %d %p", blank_mode, info); -++ switch (blank_mode) { -++ case FB_BLANK_UNBLANK: -++ //case FB_BLANK_NORMAL: -++ /* Turn on panel */ -++ __lcd_set_ena(); -++ __lcd_display_on(); -++ break; -++ -++ case FB_BLANK_NORMAL: -++ case FB_BLANK_VSYNC_SUSPEND: -++ case FB_BLANK_HSYNC_SUSPEND: -++ case FB_BLANK_POWERDOWN: -++#if 0 -++ /* Turn off panel */ -++ __lcd_display_off(); -++ __lcd_set_dis(); -++#endif -++ break; -++ default: -++ break; -++ -++ } -++ return 0; -++} -++ -++/* -++ * pan display -++ */ -++static int jz4750fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) -++{ -++ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -++ int dy; -++ -++ if (!var || !cfb) { -++ return -EINVAL; -++ } -++ -++ if (var->xoffset - cfb->fb.var.xoffset) { -++ /* No support for X panning for now! */ -++ return -EINVAL; -++ } -++ -++ dy = var->yoffset - cfb->fb.var.yoffset; -++ print_dbg("var.yoffset: %d", dy); -++ if (dy) { -++ print_dbg("Panning screen of %d lines", dy); -++ dma0_desc0->databuf += (cfb->fb.fix.line_length * dy); -++ /* TODO: Wait for current frame to finished */ -++ } -++ -++ return 0; -++} -++ -++ -++/* use default function cfb_fillrect, cfb_copyarea, cfb_imageblit */ -++static struct fb_ops jz4750fb_ops = { -++ .owner = THIS_MODULE, -++ .fb_setcolreg = jz4750fb_setcolreg, -++ .fb_check_var = jz4750fb_check_var, -++ .fb_set_par = jz4750fb_set_par, -++ .fb_blank = jz4750fb_blank, -++ .fb_pan_display = jz4750fb_pan_display, -++ .fb_fillrect = cfb_fillrect, -++ .fb_copyarea = cfb_copyarea, -++ .fb_imageblit = cfb_imageblit, -++ .fb_mmap = jz4750fb_mmap, -++ .fb_ioctl = jz4750fb_ioctl, -++}; -++ -++static int jz4750fb_set_var(struct fb_var_screeninfo *var, int con, -++ struct fb_info *info) -++{ -++ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -++ struct jz4750lcd_info *lcd_info = jz4750_lcd_info; -++ int chgvar = 0; -++ -++ var->height = lcd_info->osd.fg0.h; /* tve mode */ -++ var->width = lcd_info->osd.fg0.w; -++ var->bits_per_pixel = lcd_info->osd.fg0.bpp; -++ -++ var->vmode = FB_VMODE_NONINTERLACED; -++ var->activate = cfb->fb.var.activate; -++ var->xres = var->width; -++ var->yres = var->height; -++ var->xres_virtual = var->width; -++ var->yres_virtual = var->height; -++ var->xoffset = 0; -++ var->yoffset = 0; -++ var->pixclock = 0; -++ var->left_margin = 0; -++ var->right_margin = 0; -++ var->upper_margin = 0; -++ var->lower_margin = 0; -++ var->hsync_len = 0; -++ var->vsync_len = 0; -++ var->sync = 0; -++ var->activate &= ~FB_ACTIVATE_TEST; -++ -++ /* -++ * CONUPDATE and SMOOTH_XPAN are equal. However, -++ * SMOOTH_XPAN is only used internally by fbcon. -++ */ -++ if (var->vmode & FB_VMODE_CONUPDATE) { -++ var->vmode |= FB_VMODE_YWRAP; -++ var->xoffset = cfb->fb.var.xoffset; -++ var->yoffset = cfb->fb.var.yoffset; -++ } -++ -++ if (var->activate & FB_ACTIVATE_TEST) -++ return 0; -++ -++ if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) -++ return -EINVAL; -++ -++ if (cfb->fb.var.xres != var->xres) -++ chgvar = 1; -++ if (cfb->fb.var.yres != var->yres) -++ chgvar = 1; -++ if (cfb->fb.var.xres_virtual != var->xres_virtual) -++ chgvar = 1; -++ if (cfb->fb.var.yres_virtual != var->yres_virtual) -++ chgvar = 1; -++ if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel) -++ chgvar = 1; -++ -++ //display = fb_display + con; -++ -++ var->red.msb_right = 0; -++ var->green.msb_right = 0; -++ var->blue.msb_right = 0; -++ -++ switch(var->bits_per_pixel){ -++ case 1: /* Mono */ -++ cfb->fb.fix.visual = FB_VISUAL_MONO01; -++ cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) / 8; -++ break; -++ case 2: /* Mono */ -++ var->red.offset = 0; -++ var->red.length = 2; -++ var->green.offset = 0; -++ var->green.length = 2; -++ var->blue.offset = 0; -++ var->blue.length = 2; -++ -++ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -++ cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) / 8; -++ break; -++ case 4: /* PSEUDOCOLOUR*/ -++ var->red.offset = 0; -++ var->red.length = 4; -++ var->green.offset = 0; -++ var->green.length = 4; -++ var->blue.offset = 0; -++ var->blue.length = 4; -++ -++ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -++ cfb->fb.fix.line_length = var->xres / 2; -++ break; -++ case 8: /* PSEUDOCOLOUR, 256 */ -++ var->red.offset = 0; -++ var->red.length = 8; -++ var->green.offset = 0; -++ var->green.length = 8; -++ var->blue.offset = 0; -++ var->blue.length = 8; -++ -++ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -++ cfb->fb.fix.line_length = var->xres ; -++ break; -++ case 15: /* DIRECTCOLOUR, 32k */ -++ var->bits_per_pixel = 15; -++ var->red.offset = 10; -++ var->red.length = 5; -++ var->green.offset = 5; -++ var->green.length = 5; -++ var->blue.offset = 0; -++ var->blue.length = 5; -++ -++ cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR; -++ cfb->fb.fix.line_length = var->xres_virtual * 2; -++ break; -++ case 16: /* DIRECTCOLOUR, 64k */ -++ var->bits_per_pixel = 16; -++ var->red.offset = 11; -++ var->red.length = 5; -++ var->green.offset = 5; -++ var->green.length = 6; -++ var->blue.offset = 0; -++ var->blue.length = 5; -++ -++ cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; -++ cfb->fb.fix.line_length = var->xres_virtual * 2; -++ break; -++ case 17 ... 32: -++ /* DIRECTCOLOUR, 256 */ -++ var->bits_per_pixel = 32; -++ -++ var->red.offset = 16; -++ var->red.length = 8; -++ var->green.offset = 8; -++ var->green.length = 8; -++ var->blue.offset = 0; -++ var->blue.length = 8; -++ var->transp.offset = 24; -++ var->transp.length = 8; -++ -++ cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; -++ cfb->fb.fix.line_length = var->xres_virtual * 4; -++ break; -++ -++ default: /* in theory this should never happen */ -++ printk(KERN_WARNING "%s: don't support for %dbpp\n", -++ cfb->fb.fix.id, var->bits_per_pixel); -++ break; -++ } -++ -++ cfb->fb.var = *var; -++ cfb->fb.var.activate &= ~FB_ACTIVATE_ALL; -++ -++ /* -++ * Update the old var. The fbcon drivers still use this. -++ * Once they are using cfb->fb.var, this can be dropped. -++ * --rmk -++ */ -++ //display->var = cfb->fb.var; -++ /* -++ * If we are setting all the virtual consoles, also set the -++ * defaults used to create new consoles. -++ */ -++ fb_set_cmap(&cfb->fb.cmap, &cfb->fb); -++ dprintk("jz4750fb_set_var: after fb_set_cmap...\n"); -++ -++ return 0; -++} -++ -++static struct lcd_cfb_info * jz4750fb_alloc_fb_info(void) -++{ -++ struct lcd_cfb_info *cfb; -++ -++ cfb = kmalloc(sizeof(struct lcd_cfb_info) + sizeof(u32) * 16, GFP_KERNEL); -++ -++ if (!cfb) -++ return NULL; -++ -++ jz4750fb_info = cfb; -++ -++ memset(cfb, 0, sizeof(struct lcd_cfb_info) ); -++ -++ cfb->currcon = -1; -++ -++ -++ strcpy(cfb->fb.fix.id, "jz-lcd"); -++ cfb->fb.fix.type = FB_TYPE_PACKED_PIXELS; -++ cfb->fb.fix.type_aux = 0; -++ cfb->fb.fix.xpanstep = 1; -++ cfb->fb.fix.ypanstep = 1; -++ cfb->fb.fix.ywrapstep = 0; -++ cfb->fb.fix.accel = FB_ACCEL_NONE; -++ -++ cfb->fb.var.nonstd = 0; -++ cfb->fb.var.activate = FB_ACTIVATE_NOW; -++ cfb->fb.var.height = -1; -++ cfb->fb.var.width = -1; -++ cfb->fb.var.accel_flags = FB_ACCELF_TEXT; -++ -++ cfb->fb.fbops = &jz4750fb_ops; -++ cfb->fb.flags = FBINFO_FLAG_DEFAULT; -++ -++ cfb->fb.pseudo_palette = (void *)(cfb + 1); -++ -++ switch (jz4750_lcd_info->osd.fg0.bpp) { -++ case 1: -++ fb_alloc_cmap(&cfb->fb.cmap, 4, 0); -++ break; -++ case 2: -++ fb_alloc_cmap(&cfb->fb.cmap, 8, 0); -++ break; -++ case 4: -++ fb_alloc_cmap(&cfb->fb.cmap, 32, 0); -++ break; -++ case 8: -++ -++ default: -++ fb_alloc_cmap(&cfb->fb.cmap, 256, 0); -++ break; -++ } -++ dprintk("fb_alloc_cmap,fb.cmap.len:%d....\n", cfb->fb.cmap.len); -++ -++ return cfb; -++} -++ -++/* -++ * Map screen memory -++ */ -++static int jz4750fb_map_smem(struct lcd_cfb_info *cfb) -++{ -++ unsigned long page; -++ unsigned int page_shift, needroom, needroom1, bpp, w, h; -++ -++ bpp = jz4750_lcd_info->osd.fg0.bpp; -++ if ( bpp == 18 || bpp == 24) -++ bpp = 32; -++ if ( bpp == 15 ) -++ bpp = 16; -++ w = jz4750_lcd_info->osd.fg0.w; -++ h = jz4750_lcd_info->osd.fg0.h; -++ needroom1 = needroom = ((w * bpp + 7) >> 3) * h; -++#if defined(CONFIG_FB_JZ4750_LCD_USE_2LAYER_FRAMEBUFFER) -++ bpp = jz4750_lcd_info->osd.fg1.bpp; -++ if ( bpp == 18 || bpp == 24) -++ bpp = 32; -++ if ( bpp == 15 ) -++ bpp = 16; -++ w = jz4750_lcd_info->osd.fg1.w; -++ h = jz4750_lcd_info->osd.fg1.h; -++ needroom += ((w * bpp + 7) >> 3) * h; -++#endif -++ -++ for (page_shift = 0; page_shift < 12; page_shift++) -++ if ((PAGE_SIZE << page_shift) >= needroom) -++ break; -++ lcd_palette = (unsigned char *)__get_free_pages(GFP_KERNEL, 0); -++ lcd_frame0 = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); -++ -++ if ((!lcd_palette) || (!lcd_frame0)) -++ return -ENOMEM; -++ memset((void *)lcd_palette, 0, PAGE_SIZE); -++ memset((void *)lcd_frame0, 0, PAGE_SIZE << page_shift); -++ -++ dma_desc_base = (struct jz4750_lcd_dma_desc *)((void*)lcd_palette + ((PALETTE_SIZE+3)/4)*4); -++ -++#if defined(CONFIG_FB_JZ4750_SLCD) -++ -++ lcd_cmdbuf = (unsigned char *)__get_free_pages(GFP_KERNEL, 0); -++ memset((void *)lcd_cmdbuf, 0, PAGE_SIZE); -++ -++ { int data, i, *ptr; -++ ptr = (unsigned int *)lcd_cmdbuf; -++ data = WR_GRAM_CMD; -++ data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); -++ for(i = 0; i < 3; i++){ -++ ptr[i] = data; -++ } -++ } -++#endif -++ -++#if defined(CONFIG_FB_JZ4750_LCD_USE_2LAYER_FRAMEBUFFER) -++ lcd_frame1 = lcd_frame0 + needroom1; -++#endif -++ -++ /* -++ * Set page reserved so that mmap will work. This is necessary -++ * since we'll be remapping normal memory. -++ */ -++ page = (unsigned long)lcd_palette; -++ SetPageReserved(virt_to_page((void*)page)); -++ -++ for (page = (unsigned long)lcd_frame0; -++ page < PAGE_ALIGN((unsigned long)lcd_frame0 + (PAGE_SIZE<fb.fix.smem_start = virt_to_phys((void *)lcd_frame0); -++ cfb->fb.fix.smem_len = (PAGE_SIZE << page_shift); /* page_shift/2 ??? */ -++ cfb->fb.screen_base = -++ (unsigned char *)(((unsigned int)lcd_frame0&0x1fffffff) | 0xa0000000); -++ -++ if (!cfb->fb.screen_base) { -++ printk("jz4750fb, %s: unable to map screen memory\n", cfb->fb.fix.id); -++ return -ENOMEM; -++ } -++ -++ return 0; -++} -++ -++static void jz4750fb_free_fb_info(struct lcd_cfb_info *cfb) -++{ -++ if (cfb) { -++ fb_alloc_cmap(&cfb->fb.cmap, 0, 0); -++ kfree(cfb); -++ } -++} -++ -++static void jz4750fb_unmap_smem(struct lcd_cfb_info *cfb) -++{ -++ struct page * map = NULL; -++ unsigned char *tmp; -++ unsigned int page_shift, needroom, bpp, w, h; -++ -++ bpp = jz4750_lcd_info->osd.fg0.bpp; -++ if ( bpp == 18 || bpp == 24) -++ bpp = 32; -++ if ( bpp == 15 ) -++ bpp = 16; -++ w = jz4750_lcd_info->osd.fg0.w; -++ h = jz4750_lcd_info->osd.fg0.h; -++ needroom = ((w * bpp + 7) >> 3) * h; -++#if defined(CONFIG_FB_JZ4750_LCD_USE_2LAYER_FRAMEBUFFER) -++ bpp = jz4750_lcd_info->osd.fg1.bpp; -++ if ( bpp == 18 || bpp == 24) -++ bpp = 32; -++ if ( bpp == 15 ) -++ bpp = 16; -++ w = jz4750_lcd_info->osd.fg1.w; -++ h = jz4750_lcd_info->osd.fg1.h; -++ needroom += ((w * bpp + 7) >> 3) * h; -++#endif -++ -++ for (page_shift = 0; page_shift < 12; page_shift++) -++ if ((PAGE_SIZE << page_shift) >= needroom) -++ break; -++ -++ if (cfb && cfb->fb.screen_base) { -++ iounmap(cfb->fb.screen_base); -++ cfb->fb.screen_base = NULL; -++ release_mem_region(cfb->fb.fix.smem_start, -++ cfb->fb.fix.smem_len); -++ } -++ -++ if (lcd_palette) { -++ map = virt_to_page(lcd_palette); -++ clear_bit(PG_reserved, &map->flags); -++ free_pages((int)lcd_palette, 0); -++ } -++ -++ if (lcd_frame0) { -++ for (tmp=(unsigned char *)lcd_frame0; -++ tmp < lcd_frame0 + (PAGE_SIZE << page_shift); -++ tmp += PAGE_SIZE) { -++ map = virt_to_page(tmp); -++ clear_bit(PG_reserved, &map->flags); -++ } -++ free_pages((int)lcd_frame0, page_shift); -++ } -++} -++ -++/* initial dma descriptors */ -++static void jz4750fb_descriptor_init( struct jz4750lcd_info * lcd_info ) -++{ -++ unsigned int pal_size; -++ -++ switch ( lcd_info->osd.fg0.bpp ) { -++ case 1: -++ pal_size = 4; -++ break; -++ case 2: -++ pal_size = 8; -++ break; -++ case 4: -++ pal_size = 32; -++ break; -++ case 8: -++ default: -++ pal_size = 512; -++ } -++ -++ pal_size /= 4; -++ -++ dma0_desc_palette = dma_desc_base + 0; -++ dma0_desc0 = dma_desc_base + 1; -++ dma0_desc1 = dma_desc_base + 2; -++ dma0_desc_cmd0 = dma_desc_base + 3; /* use only once */ -++ dma0_desc_cmd = dma_desc_base + 4; -++ dma1_desc0 = dma_desc_base + 5; -++ dma1_desc1 = dma_desc_base + 6; -++ -++ /* -++ * Normal TFT panel's DMA Chan0: -++ * TO LCD Panel: -++ * no palette: dma0_desc0 <<==>> dma0_desc0 -++ * palette : dma0_desc_palette <<==>> dma0_desc0 -++ * TO TV Encoder: -++ * no palette: dma0_desc0 <<==>> dma0_desc1 -++ * palette: dma0_desc_palette --> dma0_desc0 -++ * --> dma0_desc1 --> dma0_desc_palette --> ... -++ * -++ * SMART LCD TFT panel(dma0_desc_cmd)'s DMA Chan0: -++ * TO LCD Panel: -++ * no palette: dma0_desc_cmd <<==>> dma0_desc0 -++ * palette : dma0_desc_palette --> dma0_desc_cmd -++ * --> dma0_desc0 --> dma0_desc_palette --> ... -++ * TO TV Encoder: -++ * no palette: dma0_desc_cmd --> dma0_desc0 -++ * --> dma0_desc1 --> dma0_desc_cmd --> ... -++ * palette: dma0_desc_palette --> dma0_desc_cmd -++ * --> dma0_desc0 --> dma0_desc1 -++ * --> dma0_desc_palette --> ... -++ * DMA Chan1: -++ * TO LCD Panel: -++ * dma1_desc0 <<==>> dma1_desc0 -++ * TO TV Encoder: -++ * dma1_desc0 <<==>> dma1_desc1 -++ */ -++ -++#if defined(CONFIG_FB_JZ4750_SLCD) -++ /* First CMD descriptors, use only once, cmd_num isn't 0 */ -++ dma0_desc_cmd0->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -++ dma0_desc_cmd0->databuf = (unsigned int)virt_to_phys((void *)lcd_cmdbuf); -++ dma0_desc_cmd0->frame_id = (unsigned int)0x0da0cad0; /* dma0's cmd0 */ -++ dma0_desc_cmd0->cmd = LCD_CMD_CMD | 3; /* command */ -++ dma0_desc_cmd0->offsize = 0; -++ dma0_desc_cmd0->page_width = 0; -++ dma0_desc_cmd0->cmd_num = 3; -++ -++ /* Dummy Command Descriptor, cmd_num is 0 */ -++ dma0_desc_cmd->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -++ dma0_desc_cmd->databuf = 0; -++ dma0_desc_cmd->frame_id = (unsigned int)0x0da000cd; /* dma0's cmd0 */ -++ dma0_desc_cmd->cmd = LCD_CMD_CMD | 0; /* dummy command */ -++ dma0_desc_cmd->cmd_num = 0; -++ dma0_desc_cmd->offsize = 0; -++ dma0_desc_cmd->page_width = 0; -++ -++ /* Palette Descriptor */ -++ dma0_desc_palette->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd0); -++#else -++ /* Palette Descriptor */ -++ dma0_desc_palette->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -++#endif -++ dma0_desc_palette->databuf = (unsigned int)virt_to_phys((void *)lcd_palette); -++ dma0_desc_palette->frame_id = (unsigned int)0xaaaaaaaa; -++ dma0_desc_palette->cmd = LCD_CMD_PAL | pal_size; /* Palette Descriptor */ -++ -++ /* DMA0 Descriptor0 */ -++ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) /* TVE mode */ -++ dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc1); -++ else{ /* Normal TFT LCD */ -++#if defined(CONFIG_FB_JZ4750_SLCD) -++ dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd); -++#else -++ dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -++#endif -++ } -++ -++ dma0_desc0->databuf = virt_to_phys((void *)lcd_frame0); -++ dma0_desc0->frame_id = (unsigned int)0x0000da00; /* DMA0'0 */ -++ -++ /* DMA0 Descriptor1 */ -++ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) { /* TVE mode */ -++ -++ -++ if (lcd_info->osd.fg0.bpp <= 8) /* load palette only once at setup */ -++ dma0_desc1->next_desc = (unsigned int)virt_to_phys(dma0_desc_palette); -++ else -++#if defined(CONFIG_FB_JZ4750_SLCD) /* for smatlcd */ -++ dma0_desc1->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd); -++#else -++ dma0_desc1->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -++#endif -++ dma0_desc1->frame_id = (unsigned int)0x0000da01; /* DMA0'1 */ -++ } -++ -++ if (lcd_info->osd.fg0.bpp <= 8) /* load palette only once at setup */ -++ REG_LCD_DA0 = virt_to_phys(dma0_desc_palette); -++ else { -++#if defined(CONFIG_FB_JZ4750_SLCD) /* for smartlcd */ -++ REG_LCD_DA0 = virt_to_phys(dma0_desc_cmd0); //smart lcd -++#else -++ REG_LCD_DA0 = virt_to_phys(dma0_desc0); //tft -++#endif -++ } -++ -++ /* DMA1 Descriptor0 */ -++ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) /* TVE mode */ -++ dma1_desc0->next_desc = (unsigned int)virt_to_phys(dma1_desc1); -++ else /* Normal TFT LCD */ -++ dma1_desc0->next_desc = (unsigned int)virt_to_phys(dma1_desc0); -++ -++ dma1_desc0->databuf = virt_to_phys((void *)lcd_frame1); -++ dma1_desc0->frame_id = (unsigned int)0x0000da10; /* DMA1'0 */ -++ -++ /* DMA1 Descriptor1 */ -++ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) { /* TVE mode */ -++ dma1_desc1->next_desc = (unsigned int)virt_to_phys(dma1_desc0); -++ dma1_desc1->frame_id = (unsigned int)0x0000da11; /* DMA1'1 */ -++ } -++ -++ REG_LCD_DA1 = virt_to_phys(dma1_desc0); /* set Dma-chan1's Descripter Addrress */ -++ dma_cache_wback_inv((unsigned int)(dma_desc_base), (DMA_DESC_NUM)*sizeof(struct jz4750_lcd_dma_desc)); -++ -++#if 0 -++ /* Palette Descriptor */ -++ if ( lcd_info->panel.cfg & LCD_CFG_LCDPIN_SLCD ) -++// dma0_desc_palette->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd); -++ dma0_desc_palette->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd1); -++ else -++ dma0_desc_palette->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -++ dma0_desc_palette->databuf = (unsigned int)virt_to_phys((void *)lcd_palette); -++ dma0_desc_palette->frame_id = (unsigned int)0xaaaaaaaa; -++ dma0_desc_palette->cmd = LCD_CMD_PAL | pal_size; /* Palette Descriptor */ -++ -++ /* Dummy Command Descriptor, cmd_num is 0 */ -++ dma0_desc_cmd->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -++ dma0_desc_cmd->databuf = (unsigned int)virt_to_phys((void *)lcd_cmdbuf); -++ dma0_desc_cmd->frame_id = (unsigned int)0x0da0cad0; /* dma0's cmd0 */ -++ dma0_desc_cmd->cmd = LCD_CMD_CMD | 3; /* dummy command */ -++ dma0_desc_cmd->offsize = 0; /* dummy command */ -++ dma0_desc_cmd->page_width = 0; /* dummy command */ -++ dma0_desc_cmd->cmd_num = 3; -++ -++//--------------------------------- -++ dma0_desc_cmd1->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -++ dma0_desc_cmd1->databuf = 0; -++ dma0_desc_cmd1->frame_id = (unsigned int)0x0da0cad1; /* dma0's cmd0 */ -++ dma0_desc_cmd1->cmd = LCD_CMD_CMD | 0; /* dummy command */ -++ dma0_desc_cmd1->cmd_num = 0; -++ dma0_desc_cmd1->offsize = 0; /* dummy command */ -++ dma0_desc_cmd1->page_width = 0; /* dummy command */ -++//----------------------------------- -++ /* DMA0 Descriptor0 */ -++ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) /* TVE mode */ -++ dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc1); -++ else{ /* Normal TFT LCD */ -++ if (lcd_info->osd.fg0.bpp <= 8) /* load palette only once at setup?? */ -++// dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc_palette); //tft -++ dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd); // smart lcd -++ else if ( lcd_info->panel.cfg & LCD_CFG_LCDPIN_SLCD ) -++ dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd1); -++// dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd); -++ else -++ dma0_desc0->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -++ } -++ -++ dma0_desc0->databuf = virt_to_phys((void *)lcd_frame0); -++ dma0_desc0->frame_id = (unsigned int)0x0000da00; /* DMA0'0 */ -++ -++ /* DMA0 Descriptor1 */ -++ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) { /* TVE mode */ -++ if (lcd_info->osd.fg0.bpp <= 8) /* load palette only once at setup?? */ -++ dma0_desc1->next_desc = (unsigned int)virt_to_phys(dma0_desc_palette); -++ -++ else if ( lcd_info->panel.cfg & LCD_CFG_LCDPIN_SLCD ) -++ dma0_desc1->next_desc = (unsigned int)virt_to_phys(dma0_desc_cmd); -++ else -++ dma0_desc1->next_desc = (unsigned int)virt_to_phys(dma0_desc0); -++ dma0_desc1->frame_id = (unsigned int)0x0000da01; /* DMA0'1 */ -++ } -++ -++ /* DMA1 Descriptor0 */ -++ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) /* TVE mode */ -++ dma1_desc0->next_desc = (unsigned int)virt_to_phys(dma1_desc1); -++ else /* Normal TFT LCD */ -++ dma1_desc0->next_desc = (unsigned int)virt_to_phys(dma1_desc0); -++ -++ dma1_desc0->databuf = virt_to_phys((void *)lcd_frame1); -++ dma1_desc0->frame_id = (unsigned int)0x0000da10; /* DMA1'0 */ -++ -++ /* DMA1 Descriptor1 */ -++ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) { /* TVE mode */ -++ dma1_desc1->next_desc = (unsigned int)virt_to_phys(dma1_desc0); -++ dma1_desc1->frame_id = (unsigned int)0x0000da11; /* DMA1'1 */ -++ } -++ -++ if (lcd_info->osd.fg0.bpp <= 8) /* load palette only once at setup?? */ -++ REG_LCD_DA0 = virt_to_phys(dma0_desc_palette); -++ else -++// REG_LCD_DA0 = virt_to_phys(dma0_desc_cmd); //smart lcd -++ REG_LCD_DA0 = virt_to_phys(dma0_desc0); //tft -++ REG_LCD_DA1 = virt_to_phys(dma1_desc0); /* set Dma-chan1's Descripter Addrress */ -++ dma_cache_wback_inv((unsigned int)(dma_desc_base), (DMA_DESC_NUM)*sizeof(struct jz4750_lcd_dma_desc)); -++#endif -++} -++ -++static void jz4750fb_set_panel_mode( struct jz4750lcd_info * lcd_info ) -++{ -++ struct jz4750lcd_panel_t *panel = &lcd_info->panel; -++ -++ /* set bpp */ -++ lcd_info->panel.ctrl &= ~LCD_CTRL_BPP_MASK; -++ if ( lcd_info->osd.fg0.bpp == 1 ) -++ lcd_info->panel.ctrl |= LCD_CTRL_BPP_1; -++ else if ( lcd_info->osd.fg0.bpp == 2 ) -++ lcd_info->panel.ctrl |= LCD_CTRL_BPP_2; -++ else if ( lcd_info->osd.fg0.bpp == 4 ) -++ lcd_info->panel.ctrl |= LCD_CTRL_BPP_4; -++ else if ( lcd_info->osd.fg0.bpp == 8 ) -++ lcd_info->panel.ctrl |= LCD_CTRL_BPP_8; -++ else if ( lcd_info->osd.fg0.bpp == 15 ) -++ lcd_info->panel.ctrl |= LCD_CTRL_BPP_16 | LCD_CTRL_RGB555; -++ else if ( lcd_info->osd.fg0.bpp == 16 ) -++ lcd_info->panel.ctrl |= LCD_CTRL_BPP_16 | LCD_CTRL_RGB565; -++ else if ( lcd_info->osd.fg0.bpp > 16 && lcd_info->osd.fg0.bpp < 32+1 ) { -++ lcd_info->osd.fg0.bpp = 32; -++ lcd_info->panel.ctrl |= LCD_CTRL_BPP_18_24; -++ } -++ else { -++ printk("The BPP %d is not supported\n", lcd_info->osd.fg0.bpp); -++ lcd_info->osd.fg0.bpp = 32; -++ lcd_info->panel.ctrl |= LCD_CTRL_BPP_18_24; -++ } -++ -++ lcd_info->panel.cfg |= LCD_CFG_NEWDES; /* use 8words descriptor always */ -++ -++ REG_LCD_CTRL = lcd_info->panel.ctrl; /* LCDC Controll Register */ -++ REG_LCD_CFG = lcd_info->panel.cfg; /* LCDC Configure Register */ -++ REG_SLCD_CFG = lcd_info->panel.slcd_cfg; /* Smart LCD Configure Register */ -++ -++ if ( lcd_info->panel.cfg & LCD_CFG_LCDPIN_SLCD ) /* enable Smart LCD DMA */ -++ REG_SLCD_CTRL = SLCD_CTRL_DMA_EN; -++ -++ switch ( lcd_info->panel.cfg & LCD_CFG_MODE_MASK ) { -++ case LCD_CFG_MODE_GENERIC_TFT: -++ case LCD_CFG_MODE_INTER_CCIR656: -++ case LCD_CFG_MODE_NONINTER_CCIR656: -++ case LCD_CFG_MODE_SLCD: -++ default: /* only support TFT16 TFT32, not support STN and Special TFT by now(10-06-2008)*/ -++ REG_LCD_VAT = (((panel->blw + panel->w + panel->elw + panel->hsw)) << 16) | (panel->vsw + panel->bfw + panel->h + panel->efw); -++ REG_LCD_DAH = ((panel->hsw + panel->blw) << 16) | (panel->hsw + panel->blw + panel->w); -++ REG_LCD_DAV = ((panel->vsw + panel->bfw) << 16) | (panel->vsw + panel->bfw + panel->h); -++ REG_LCD_HSYNC = (0 << 16) | panel->hsw; -++ REG_LCD_VSYNC = (0 << 16) | panel->vsw; -++ break; -++ } -++} -++ -++ -++static void jz4750fb_set_osd_mode( struct jz4750lcd_info * lcd_info ) -++{ -++ dprintk("%s, %d\n", __FILE__, __LINE__ ); -++ lcd_info->osd.osd_ctrl &= ~(LCD_OSDCTRL_OSDBPP_MASK); -++ if ( lcd_info->osd.fg1.bpp == 15 ) -++ lcd_info->osd.osd_ctrl |= LCD_OSDCTRL_OSDBPP_15_16|LCD_OSDCTRL_RGB555; -++ else if ( lcd_info->osd.fg1.bpp == 16 ) -++ lcd_info->osd.osd_ctrl |= LCD_OSDCTRL_OSDBPP_15_16|LCD_OSDCTRL_RGB565; -++ else { -++ lcd_info->osd.fg1.bpp = 32; -++ lcd_info->osd.osd_ctrl |= LCD_OSDCTRL_OSDBPP_18_24; -++ } -++ -++ REG_LCD_OSDC = lcd_info->osd.osd_cfg; /* F0, F1, alpha, */ -++ -++ REG_LCD_OSDCTRL = lcd_info->osd.osd_ctrl; /* IPUEN, bpp */ -++ REG_LCD_RGBC = lcd_info->osd.rgb_ctrl; -++ REG_LCD_BGC = lcd_info->osd.bgcolor; -++ REG_LCD_KEY0 = lcd_info->osd.colorkey0; -++ REG_LCD_KEY1 = lcd_info->osd.colorkey1; -++ REG_LCD_ALPHA = lcd_info->osd.alpha; -++ REG_LCD_IPUR = lcd_info->osd.ipu_restart; -++} -++ -++static void jz4750fb_foreground_resize( struct jz4750lcd_info * lcd_info ) -++{ -++ int fg0_line_size, fg0_frm_size, fg1_line_size, fg1_frm_size; -++ /* -++ * NOTE: -++ * Foreground change sequence: -++ * 1. Change Position Registers -> LCD_OSDCTL.Change; -++ * 2. LCD_OSDCTRL.Change -> descripter->Size -++ * Foreground, only one of the following can be change at one time: -++ * 1. F0 size; -++ * 2. F0 position -++ * 3. F1 size -++ * 4. F1 position -++ */ -++ -++ /* -++ * The rules of f0, f1's position: -++ * f0.x + f0.w <= panel.w; -++ * f0.y + f0.h <= panel.h; -++ * -++ * When output is LCD panel, fg.y and fg.h can be odd number or even number. -++ * When output is TVE, as the TVE has odd frame and even frame, -++ * to simplified operation, fg.y and fg.h should be even number always. -++ * -++ */ -++ -++ /* Foreground 0 */ -++ if ( lcd_info->osd.fg0.x >= lcd_info->panel.w ) -++ lcd_info->osd.fg0.x = lcd_info->panel.w - 1; -++ if ( lcd_info->osd.fg0.y >= lcd_info->panel.h ) -++ lcd_info->osd.fg0.y = lcd_info->panel.h - 1; -++ if ( lcd_info->osd.fg0.x + lcd_info->osd.fg0.w > lcd_info->panel.w ) -++ lcd_info->osd.fg0.w = lcd_info->panel.w - lcd_info->osd.fg0.x; -++ if ( lcd_info->osd.fg0.y + lcd_info->osd.fg0.h > lcd_info->panel.h ) -++ lcd_info->osd.fg0.h = lcd_info->panel.h - lcd_info->osd.fg0.y; -++ /* Foreground 1 */ -++ /* Case TVE ??? TVE 720x573 or 720x480*/ -++ if ( lcd_info->osd.fg1.x >= lcd_info->panel.w ) -++ lcd_info->osd.fg1.x = lcd_info->panel.w - 1; -++ if ( lcd_info->osd.fg1.y >= lcd_info->panel.h ) -++ lcd_info->osd.fg1.y = lcd_info->panel.h - 1; -++ if ( lcd_info->osd.fg1.x + lcd_info->osd.fg1.w > lcd_info->panel.w ) -++ lcd_info->osd.fg1.w = lcd_info->panel.w - lcd_info->osd.fg1.x; -++ if ( lcd_info->osd.fg1.y + lcd_info->osd.fg1.h > lcd_info->panel.h ) -++ lcd_info->osd.fg1.h = lcd_info->panel.h - lcd_info->osd.fg1.y; -++ -++// fg0_line_size = lcd_info->osd.fg0.w*((lcd_info->osd.fg0.bpp+7)/8); -++ fg0_line_size = (lcd_info->osd.fg0.w*(lcd_info->osd.fg0.bpp)/8); -++ fg0_line_size = ((fg0_line_size+3)>>2)<<2; /* word aligned */ -++ fg0_frm_size = fg0_line_size * lcd_info->osd.fg0.h; -++ -++ fg1_line_size = lcd_info->osd.fg1.w*((lcd_info->osd.fg1.bpp+7)/8); -++ fg1_line_size = ((fg1_line_size+3)>>2)<<2; /* word aligned */ -++ fg1_frm_size = fg1_line_size * lcd_info->osd.fg1.h; -++ -++ if ( lcd_info->osd.fg_change ) { -++ if ( lcd_info->osd.fg_change & FG0_CHANGE_POSITION ) { /* F1 change position */ -++ REG_LCD_XYP0 = lcd_info->osd.fg0.y << 16 | lcd_info->osd.fg0.x; -++ } -++ if ( lcd_info->osd.fg_change & FG1_CHANGE_POSITION ) { /* F1 change position */ -++ REG_LCD_XYP1 = lcd_info->osd.fg1.y << 16 | lcd_info->osd.fg1.x; -++ } -++ -++ /* set change */ -++ if ( !(lcd_info->osd.osd_ctrl & LCD_OSDCTRL_IPU) && -++ (lcd_info->osd.fg_change != FG_CHANGE_ALL) ) -++ REG_LCD_OSDCTRL |= LCD_OSDCTRL_CHANGES; -++ -++ /* wait change ready??? */ -++// while ( REG_LCD_OSDS & LCD_OSDS_READY ) /* fix in the future, Wolfgang, 06-20-2008 */ -++ print_dbg("wait LCD_OSDS_READY\n"); -++ -++ if ( lcd_info->osd.fg_change & FG0_CHANGE_SIZE ) { /* change FG0 size */ -++ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) { /* output to TV */ -++ dma0_desc0->cmd = dma0_desc1->cmd = (fg0_frm_size/4)/2; -++ dma0_desc0->offsize = dma0_desc1->offsize -++ = fg0_line_size/4; -++ dma0_desc0->page_width = dma0_desc1->page_width -++ = fg0_line_size/4; -++ dma0_desc1->databuf = virt_to_phys((void *)(lcd_frame0 + fg0_line_size)); -++ } -++ else { -++ dma0_desc0->cmd = dma0_desc1->cmd = fg0_frm_size/4; -++ dma0_desc0->offsize = dma0_desc1->offsize =0; -++ dma0_desc0->page_width = dma0_desc1->page_width = 0; -++ } -++ -++ dma0_desc0->desc_size = dma0_desc1->desc_size -++ = lcd_info->osd.fg0.h << 16 | lcd_info->osd.fg0.w; -++ REG_LCD_SIZE0 = (lcd_info->osd.fg0.h<<16)|lcd_info->osd.fg0.w; -++ -++ } -++ -++ if ( lcd_info->osd.fg_change & FG1_CHANGE_SIZE ) { /* change FG1 size*/ -++ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) { /* output to TV */ -++ dma1_desc0->cmd = dma1_desc1->cmd = (fg1_frm_size/4)/2; -++ dma1_desc0->offsize = dma1_desc1->offsize = fg1_line_size/4; -++ dma1_desc0->page_width = dma1_desc1->page_width = fg1_line_size/4; -++ dma1_desc1->databuf = virt_to_phys((void *)(lcd_frame1 + fg1_line_size)); -++ } -++ else { -++ dma1_desc0->cmd = dma1_desc1->cmd = fg1_frm_size/4; -++ dma1_desc0->offsize = dma1_desc1->offsize = 0; -++ dma1_desc0->page_width = dma1_desc1->page_width = 0; -++ } -++ -++ dma1_desc0->desc_size = dma1_desc1->desc_size -++ = lcd_info->osd.fg1.h << 16 | lcd_info->osd.fg1.w; -++ REG_LCD_SIZE1 = lcd_info->osd.fg1.h << 16|lcd_info->osd.fg1.w; -++ } -++ -++ dma_cache_wback((unsigned int)(dma_desc_base), (DMA_DESC_NUM)*sizeof(struct jz4750_lcd_dma_desc)); -++ lcd_info->osd.fg_change = FG_NOCHANGE; /* clear change flag */ -++ } -++} -++ -++static void jz4750fb_change_clock( struct jz4750lcd_info * lcd_info ) -++{ -++#if defined(CONFIG_JZ4750_FUWA) || defined(CONFIG_JZ4750_APUS) /* FPGA test, pixdiv */ -++#if 0 -++ REG_LCD_REV = 0x00000004; -++ printk("Fuwa test, pixclk divide REG_LCD_REV=0x%08x\n", REG_LCD_REV); -++ printk("Fuwa test, pixclk %d\n", JZ_EXTAL/(((REG_LCD_REV&0xFF)+1)*2)); -++#endif -++ unsigned int val = 0; -++ unsigned int pclk; -++ /* Timing setting */ -++ __cpm_stop_lcd(); -++ -++ val = lcd_info->panel.fclk; /* frame clk */ -++ -++ if ( (lcd_info->panel.cfg & LCD_CFG_MODE_MASK) != LCD_CFG_MODE_SERIAL_TFT) { -++ pclk = val * (lcd_info->panel.w + lcd_info->panel.hsw + lcd_info->panel.elw + lcd_info->panel.blw) * (lcd_info->panel.h + lcd_info->panel.vsw + lcd_info->panel.efw + lcd_info->panel.bfw); /* Pixclk */ -++ } -++ else { -++ /* serial mode: Hsync period = 3*Width_Pixel */ -++ pclk = val * (lcd_info->panel.w*3 + lcd_info->panel.hsw + lcd_info->panel.elw + lcd_info->panel.blw) * (lcd_info->panel.h + lcd_info->panel.vsw + lcd_info->panel.efw + lcd_info->panel.bfw); /* Pixclk */ -++ } -++ -++ /********* In TVE mode PCLK = 27MHz ***********/ -++ if ( lcd_info->panel.cfg & LCD_CFG_TVEN ) { /* LCDC output to TVE */ -++ REG_CPM_LPCDR |= CPM_LPCDR_LTCS; -++ val = 11; /* PLLCLK = 324 */ -++ __cpm_set_pixdiv(val); -++ -++ dprintk("REG_CPM_LPCDR = 0x%08x\n", REG_CPM_LPCDR); -++ -++ val = pclk * 3 ; /* LCDClock > 2.5*Pixclock */ -++ -++ val =(__cpm_get_pllout()) / val; -++ if ( val > 0x1f ) { -++ printk("lcd clock divide is too large, set it to 0x1f\n"); -++ val = 0x1f; -++ } -++ __cpm_set_ldiv( val ); -++ REG_CPM_LPCDR |= CPM_LPCDR_LTCS; -++ REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */ -++ -++ } -++ else { /* LCDC output to LCD panel */ -++// REG_CPM_LPCDR = 0; -++ val = __cpm_get_pllout2() / pclk; /* pclk */ -++ val--; -++ dprintk("ratio: val = %d\n", val); -++ if ( val > 0x7ff ) { -++ printk("pixel clock divid is too large, set it to 0x7ff\n"); -++ val = 0x7ff; -++ } -++ -++ __cpm_set_pixdiv(val); -++ -++ dprintk("REG_CPM_LPCDR = 0x%08x\n", REG_CPM_LPCDR); -++ val = pclk * 3 ; /* LCDClock > 2.5*Pixclock */ -++ val =__cpm_get_pllout2() / val; -++ if ( val > 0x1f ) { -++ printk("lcd clock divide is too large, set it to 0x1f\n"); -++ val = 0x1f; -++ } -++ __cpm_set_ldiv( val ); -++ REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */ -++ -++ } -++ -++ dprintk("REG_CPM_LPCDR=0x%08x\n", REG_CPM_LPCDR); -++ dprintk("REG_CPM_CPCCR=0x%08x\n", REG_CPM_CPCCR); -++ -++ jz_clocks.pixclk = __cpm_get_pixclk(); -++ jz_clocks.lcdclk = __cpm_get_lcdclk(); -++ printk("LCDC: PixClock:%d LcdClock:%d\n", -++ jz_clocks.pixclk, jz_clocks.lcdclk); -++ -++ __cpm_start_lcd(); -++ udelay(1000); -++#else -++ -++#error "Set lcd clock first, Not support your chipset now!!!" -++ /* -++ * set lcd device clock and lcd pixel clock. -++ * what about TVE mode??? -++ * -++ */ -++#endif -++ -++} -++ -++/* -++ * jz4750fb_set_mode(), set osd configure, resize foreground -++ * -++ */ -++static void jz4750fb_set_mode( struct jz4750lcd_info * lcd_info ) -++{ -++ struct lcd_cfb_info *cfb = jz4750fb_info; -++ -++ jz4750fb_set_osd_mode(lcd_info); -++ jz4750fb_foreground_resize(lcd_info); -++ jz4750fb_set_var(&cfb->fb.var, -1, &cfb->fb); -++} -++ -++/* -++ * jz4750fb_deep_set_mode, -++ * -++ */ -++static void jz4750fb_deep_set_mode( struct jz4750lcd_info * lcd_info ) -++{ -++ /* configurate sequence: -++ * 1. disable lcdc. -++ * 2. init frame descriptor. -++ * 3. set panel mode -++ * 4. set osd mode -++ * 5. start lcd clock in CPM -++ * 6. enable lcdc. -++ */ -++ -++ __lcd_clr_ena(); /* Quick Disable */ -++ lcd_info->osd.fg_change = FG_CHANGE_ALL; /* change FG0, FG1 size, postion??? */ -++ jz4750fb_descriptor_init(lcd_info); -++ jz4750fb_set_panel_mode(lcd_info); -++ jz4750fb_set_mode(lcd_info); -++ jz4750fb_change_clock(lcd_info); -++ __lcd_set_ena(); /* enable lcdc */ -++} -++ -++ -++static irqreturn_t jz4750fb_interrupt_handler(int irq, void *dev_id) -++{ -++ unsigned int state; -++ static int irqcnt=0; -++ -++ state = REG_LCD_STATE; -++ dprintk("In the lcd interrupt handler, state=0x%x\n", state); -++ -++ if (state & LCD_STATE_EOF) /* End of frame */ -++ REG_LCD_STATE = state & ~LCD_STATE_EOF; -++ -++ if (state & LCD_STATE_IFU0) { -++ printk("%s, InFiFo0 underrun\n", __FUNCTION__); -++ REG_LCD_STATE = state & ~LCD_STATE_IFU0; -++ } -++ -++ if (state & LCD_STATE_IFU1) { -++ printk("%s, InFiFo1 underrun\n", __FUNCTION__); -++ REG_LCD_STATE = state & ~LCD_STATE_IFU1; -++ } -++ -++ if (state & LCD_STATE_OFU) { /* Out fifo underrun */ -++ REG_LCD_STATE = state & ~LCD_STATE_OFU; -++ if ( irqcnt++ > 100 ) { -++ __lcd_disable_ofu_intr(); -++ printk("disable Out FiFo underrun irq.\n"); -++ } -++ printk("%s, Out FiFo underrun.\n", __FUNCTION__); -++ } -++ -++ return IRQ_HANDLED; -++} -++ -++#ifdef CONFIG_PM -++ -++/* -++ * Suspend the LCDC. -++ */ -++static int jzfb_suspend(void) -++{ -++ __lcd_clr_ena(); /* Quick Disable */ -++ __lcd_display_off(); -++ __cpm_stop_lcd(); -++ -++ return 0; -++} -++ -++/* -++ * Resume the LCDC. -++ */ -++static int jzfb_resume(void) -++{ -++ __cpm_start_lcd(); -++ __gpio_set_pin(GPIO_DISP_OFF_N); -++ __lcd_special_on(); -++ __lcd_set_ena(); -++ mdelay(200); -++ __lcd_set_backlight_level(80); -++ -++ return 0; -++} -++ -++/* -++ * Power management hook. Note that we won't be called from IRQ context, -++ * unlike the blank functions above, so we may sleep. -++ */ -++static int jzlcd_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -++{ -++ int ret; -++ struct lcd_cfb_info *cfb = pm_dev->data; -++ -++ if (!cfb) return -EINVAL; -++ -++ switch (req) { -++ case PM_SUSPEND: -++ ret = jzfb_suspend(); -++ break; -++ -++ case PM_RESUME: -++ ret = jzfb_resume(); -++ break; -++ -++ default: -++ ret = -EINVAL; -++ break; -++ } -++ return ret; -++} -++#else -++#define jzfb_suspend NULL -++#define jzfb_resume NULL -++#endif /* CONFIG_PM */ -++ -++/* The following routine is only for test */ -++ -++#ifdef DEBUG -++static void test_gpio(int gpio_num, int delay) { -++ __gpio_as_output(gpio_num); -++ while(1) { -++ __gpio_set_pin(gpio_num); -++ udelay(delay); -++ __gpio_clear_pin(gpio_num); -++ udelay(delay); -++ } -++} -++static void display_v_color_bar(int w, int h, int bpp) { -++ int i, j, wpl, data = 0; -++ int *ptr; -++ ptr = (int *)lcd_frame0; -++// ptr = (int *)lcd_frame1; -++ wpl = w*bpp/32; -++ if (!(bpp > 8)) -++ switch(bpp){ -++ case 1: -++ for (j = 0;j < h; j++) -++ for (i = 0;i < wpl; i++) { -++ *ptr++ = 0x00ff00ff; -++ } -++ break; -++ case 2: -++ for (j = 0;j < h; j++) -++ for (i = 0;i < wpl; i++) { -++ data = (i%4)*0x55555555; -++ *ptr++ = data; -++ } -++ break; -++ case 4: -++ for (j = 0;j < h; j++) -++ for (i = 0;i < wpl; i++) { -++ data = (i%16)*0x11111111; -++ *ptr++ = data; -++ } -++ break; -++ case 8: -++ for (j = 0;j < h; j++) -++ for (i = 0;i < wpl; i+=2) { -++ data = (i%(256))*0x01010101; -++ *ptr++ = data; -++ *ptr++ = data; -++ } -++ break; -++ } -++ else { -++ switch(bpp) { -++ case 16: -++ for (j = 0;j < h; j++) -++ for (i = 0;i < wpl; i++) { -++ if((i/4)%8==0) -++ *ptr++ = 0xffffffff; -++ else if ((i/4)%8==1) -++ *ptr++ = 0xf800f800; -++ else if ((i/4)%8==2) -++ *ptr++ = 0xffe0ffe0; -++ else if ((i/4)%8==3) -++ *ptr++ = 0x07e007e0; -++ else if ((i/4)%8==4) -++ *ptr++ = 0x07ff07ff; -++ else if ((i/4)%8==5) -++ *ptr++ = 0x001f001f; -++ else if ((i/4)%8==6) -++ *ptr++ = 0xf81ff81f; -++ else if ((i/4)%8==7) -++ *ptr++ = 0x00000000; -++ } -++ break; -++ case 18: -++ case 24: -++ case 32: -++ default: -++#if 1 -++ for (j = 0;j < h; j++) -++ for (i = 0;i < wpl; i++) { -++ if((i/8)%8==7) -++ *ptr++ = 0xffffff; -++ else if ((i/8)%8==1) -++ *ptr++ = 0xff0000; -++ else if ((i/8)%8==2) -++ *ptr++ = 0xffff00; -++ else if ((i/8)%8==3) -++ *ptr++ = 0x00ff00; -++ else if ((i/8)%8==4) -++ *ptr++ = 0x00ffff; -++ else if ((i/8)%8==5) -++ *ptr++ = 0x0000ff; -++ else if ((i/8)%8==6) -++ *ptr++ = 0xff00ff; -++ else if ((i/8)%8==0) -++ *ptr++ = 0x000000; -++ } -++#else -++ for (j = 0;j < h; j++) -++ for (i = 0;i < wpl; i++) { -++ if((i/8)%8==7) -++ *ptr++ = 0x00ff0000; -++ else if ((i/8)%8==1) -++ *ptr++ = 0xffff0000; -++ else if ((i/8)%8==2) -++ *ptr++ = 0x20ff0000; -++ else if ((i/8)%8==3) -++ *ptr++ = 0x40ff0000; -++ else if ((i/8)%8==4) -++ *ptr++ = 0x60ff0000; -++ else if ((i/8)%8==5) -++ *ptr++ = 0x80ff0000; -++ else if ((i/8)%8==6) -++ *ptr++ = 0xa0ff0000; -++ else if ((i/8)%8==0) -++ *ptr++ = 0xc0ff0000; -++ } -++#endif -++ break; -++ } -++ } -++} -++static void display_h_color_bar(int w, int h, int bpp) { -++ int i, data = 0; -++ int *ptr; -++ int wpl; //word_per_line -++ ptr = (int *)lcd_frame0; -++// ptr = (int *)lcd_frame1; -++ wpl = w*bpp/32; -++ if (!(bpp > 8)) -++ for (i = 0;i < wpl*h;i++) { -++ switch(bpp){ -++ case 1: -++ if(i%(wpl*8)==0) -++ data = ((i/(wpl*8))%2)*0xffffffff; -++ *ptr++ = data; -++ break; -++ case 2: -++ if(i%(wpl*8)==0) -++ data = ((i/(wpl*8))%4)*0x55555555; -++ *ptr++ = data; -++ break; -++ case 4: -++ if(i%(wpl*8)==0) -++ data = ((i/(wpl*8))%16)*0x11111111; -++ *ptr++ = data; -++ break; -++ case 8: -++ if(i%(wpl*8)==0) -++ data = ((i/(wpl*8))%256)*0x01010101; -++ *ptr++ = data; -++ break; -++ } -++ } -++ else { -++ -++ switch(bpp) { -++ case 15: -++ case 16: -++ for (i = 0;i < wpl*h;i++) { -++ if (((i/(wpl*8)) % 8) == 0) -++ *ptr++ = 0xffffffff; -++ else if (((i/(wpl*8)) % 8) == 1) -++ *ptr++ = 0xf800f800; -++ else if (((i/(wpl*8)) % 8) == 2) -++ *ptr++ = 0xffe0ffe0; -++ else if (((i/(wpl*8)) % 8) == 3) -++ *ptr++ = 0x07e007e0; -++ else if (((i/(wpl*8)) % 8) == 4) -++ *ptr++ = 0x07ff07ff; -++ else if (((i/(wpl*8)) % 8) == 5) -++ *ptr++ = 0x001f001f; -++ else if (((i/(wpl*8)) % 8) == 6) -++ *ptr++ = 0xf81ff81f; -++ else if (((i/(wpl*8)) % 8) == 7) -++ *ptr++ = 0x00000000; -++ } -++ break; -++ case 18: -++ case 24: -++ case 32: -++ default: -++ for (i = 0;i < wpl*h;i++) { -++ if (((i/(wpl*8)) % 8) == 7) -++ *ptr++ = 0xffffff; -++ else if (((i/(wpl*8)) % 8) == 2) -++ *ptr++ = 0xff0000; -++ else if (((i/(wpl*8)) % 8) == 4) -++ *ptr++ = 0xffff00; -++ else if (((i/(wpl*8)) % 8) == 6) -++ *ptr++ = 0x00ff00; -++ else if (((i/(wpl*8)) % 8) == 1) -++ *ptr++ = 0x00ffff; -++ else if (((i/(wpl*8)) % 8) == 3) -++ *ptr++ = 0x0000ff; -++ else if (((i/(wpl*8)) % 8) == 5) -++ *ptr++ = 0x000000; -++ else if (((i/(wpl*8)) % 8) == 0) -++ *ptr++ = 0xff00ff; -++ } -++ break; -++ } -++ -++ } -++ -++} -++#endif -++ -++static int __init jz4750fb_init(void) -++{ -++ struct lcd_cfb_info *cfb; -++ int err = 0; -++ -++ /* gpio init __gpio_as_lcd */ -++ if (jz4750_lcd_info->panel.cfg & LCD_CFG_MODE_TFT_16BIT) -++ __gpio_as_lcd_16bit(); -++ else if (jz4750_lcd_info->panel.cfg & LCD_CFG_MODE_TFT_24BIT) -++ __gpio_as_lcd_24bit(); -++ else -++ __gpio_as_lcd_18bit(); -++ /* In special mode, we only need init special pin, -++ * as general lcd pin has init in uboot */ -++#if defined(CONFIG_SOC_JZ4750) -++ switch (jz4750_lcd_info->panel.cfg & LCD_CFG_MODE_MASK) { -++ case LCD_CFG_MODE_SPECIAL_TFT_1: -++ case LCD_CFG_MODE_SPECIAL_TFT_2: -++ case LCD_CFG_MODE_SPECIAL_TFT_3: -++ __gpio_as_lcd_special(); -++ break; -++ default: -++ ; -++ } -++#endif -++ if ( jz4750_lcd_info->osd.fg0.bpp > 16 && -++ jz4750_lcd_info->osd.fg0.bpp < 32 ) { -++ jz4750_lcd_info->osd.fg0.bpp = 32; -++ } -++ -++ switch ( jz4750_lcd_info->osd.fg1.bpp ) { -++ case 15: -++ case 16: -++ break; -++ case 17 ... 32: -++ jz4750_lcd_info->osd.fg1.bpp = 32; -++ break; -++ default: -++ printk("jz4750fb fg1 not support bpp(%d), force to 32bpp\n", -++ jz4750_lcd_info->osd.fg1.bpp); -++ jz4750_lcd_info->osd.fg1.bpp = 32; -++ } -++ __lcd_clr_dis(); -++ __lcd_clr_ena(); -++ -++ /* Configure SLCD module for setting smart lcd control registers */ -++#if defined(CONFIG_FB_JZ4750_SLCD) -++ __lcd_as_smart_lcd(); -++ __slcd_disable_dma(); -++ __init_slcd_bus(); /* Note: modify this depend on you lcd */ -++ -++#endif -++ /* init clk */ -++ jz4750fb_change_clock(jz4750_lcd_info); -++ __lcd_display_pin_init(); -++ __lcd_slcd_special_on(); -++ -++ cfb = jz4750fb_alloc_fb_info(); -++ if (!cfb) -++ goto failed; -++ -++ err = jz4750fb_map_smem(cfb); -++ if (err) -++ goto failed; -++ -++ jz4750fb_deep_set_mode( jz4750_lcd_info ); -++ -++ err = register_framebuffer(&cfb->fb); -++ if (err < 0) { -++ dprintk("jzfb_init(): register framebuffer err.\n"); -++ goto failed; -++ } -++ printk("fb%d: %s frame buffer device, using %dK of video memory\n", -++ cfb->fb.node, cfb->fb.fix.id, cfb->fb.fix.smem_len>>10); -++ -++ if (request_irq(IRQ_LCD, jz4750fb_interrupt_handler, IRQF_DISABLED, -++ "lcd", 0)) { -++ err = -EBUSY; -++ goto failed; -++ } -++ -++#ifdef CONFIG_PM -++ /* -++ * Note that the console registers this as well, but we want to -++ * power down the display prior to sleeping. -++ */ -++ cfb->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, jzlcd_pm_callback); -++ if (cfb->pm) -++ cfb->pm->data = cfb; -++#endif -++ -++ __lcd_set_ena(); /* enalbe LCD Controller */ -++ __lcd_display_on(); -++ -++#ifdef DEBUG -++ display_h_color_bar(jz4750_lcd_info->osd.fg0.w, jz4750_lcd_info->osd.fg0.h, jz4750_lcd_info->osd.fg0.bpp); -++#endif -++ print_lcdc_registers(); -++ return 0; -++ -++failed: -++ print_dbg(); -++ jz4750fb_unmap_smem(cfb); -++ jz4750fb_free_fb_info(cfb); -++ -++ return err; -++} -++ -++#if 0 -++static int jzfb_remove(struct device *dev) -++{ -++ struct lcd_cfb_info *cfb = dev_get_drvdata(dev); -++ jzfb_unmap_smem(cfb); -++ jzfb_free_fb_info(cfb); -++ return 0; -++} -++#endif -++ -++#if 0 -++static struct device_driver jzfb_driver = { -++ .name = "jz-lcd", -++ .bus = &platform_bus_type, -++ .probe = jzfb_probe, -++ .remove = jzfb_remove, -++ .suspend = jzfb_suspend, -++ .resume = jzfb_resume, -++}; -++#endif -++ -++static void __exit jz4750fb_cleanup(void) -++{ -++ //driver_unregister(&jzfb_driver); -++ //jzfb_remove(); -++} -++ -++module_init(jz4750fb_init); -++module_exit(jz4750fb_cleanup); -+diff -urN linux-2.6.24.7.old/drivers/video/jz4750_lcd.h linux-2.6.24.7/drivers/video/jz4750_lcd.h -+--- linux-2.6.24.7.old/drivers/video/jz4750_lcd.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/video/jz4750_lcd.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,756 @@ -++/* -++ * linux/drivers/video/jz4750_lcd.h -- Ingenic Jz4750 On-Chip LCD frame buffer device -++ * -++ * Copyright (C) 2005-2008, Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ */ -++ -++#ifndef __JZ4750_LCD_H__ -++#define __JZ4750_LCD_H__ -++ -++//#include -++ -++ -++#define NR_PALETTE 256 -++#define PALETTE_SIZE (NR_PALETTE*2) -++ -++/* use new descriptor(8 words) */ -++struct jz4750_lcd_dma_desc { -++ unsigned int next_desc; /* LCDDAx */ -++ unsigned int databuf; /* LCDSAx */ -++ unsigned int frame_id; /* LCDFIDx */ -++ unsigned int cmd; /* LCDCMDx */ -++ unsigned int offsize; /* Stride Offsize(in word) */ -++ unsigned int page_width; /* Stride Pagewidth(in word) */ -++ unsigned int cmd_num; /* Command Number(for SLCD) */ -++ unsigned int desc_size; /* Foreground Size */ -++}; -++ -++struct jz4750lcd_panel_t { -++ unsigned int cfg; /* panel mode and pin usage etc. */ -++ unsigned int slcd_cfg; /* Smart lcd configurations */ -++ unsigned int ctrl; /* lcd controll register */ -++ unsigned int w; /* Panel Width(in pixel) */ -++ unsigned int h; /* Panel Height(in line) */ -++ unsigned int fclk; /* frame clk */ -++ unsigned int hsw; /* hsync width, in pclk */ -++ unsigned int vsw; /* vsync width, in line count */ -++ unsigned int elw; /* end of line, in pclk */ -++ unsigned int blw; /* begin of line, in pclk */ -++ unsigned int efw; /* end of frame, in line count */ -++ unsigned int bfw; /* begin of frame, in line count */ -++}; -++ -++ -++struct jz4750lcd_fg_t { -++ int bpp; /* foreground bpp */ -++ int x; /* foreground start position x */ -++ int y; /* foreground start position y */ -++ int w; /* foreground width */ -++ int h; /* foreground height */ -++}; -++ -++struct jz4750lcd_osd_t { -++ unsigned int osd_cfg; /* OSDEN, ALHPAEN, F0EN, F1EN, etc */ -++ unsigned int osd_ctrl; /* IPUEN, OSDBPP, etc */ -++ unsigned int rgb_ctrl; /* RGB Dummy, RGB sequence, RGB to YUV */ -++ unsigned int bgcolor; /* background color(RGB888) */ -++ unsigned int colorkey0; /* foreground0's Colorkey enable, Colorkey value */ -++ unsigned int colorkey1; /* foreground1's Colorkey enable, Colorkey value */ -++ unsigned int alpha; /* ALPHAEN, alpha value */ -++ unsigned int ipu_restart; /* IPU Restart enable, ipu restart interval time */ -++ -++#define FG_NOCHANGE 0x0000 -++#define FG0_CHANGE_SIZE 0x0001 -++#define FG0_CHANGE_POSITION 0x0002 -++#define FG1_CHANGE_SIZE 0x0010 -++#define FG1_CHANGE_POSITION 0x0020 -++#define FG_CHANGE_ALL ( FG0_CHANGE_SIZE | FG0_CHANGE_POSITION | \ -++ FG1_CHANGE_SIZE | FG1_CHANGE_POSITION ) -++ int fg_change; -++ struct jz4750lcd_fg_t fg0; /* foreground 0 */ -++ struct jz4750lcd_fg_t fg1; /* foreground 1 */ -++}; -++ -++struct jz4750lcd_info { -++ struct jz4750lcd_panel_t panel; -++ struct jz4750lcd_osd_t osd; -++}; -++ -++ -++/* Jz LCDFB supported I/O controls. */ -++#define FBIOSETBACKLIGHT 0x4688 /* set back light level */ -++#define FBIODISPON 0x4689 /* display on */ -++#define FBIODISPOFF 0x468a /* display off */ -++#define FBIORESET 0x468b /* lcd reset */ -++#define FBIOPRINT_REG 0x468c /* print lcd registers(debug) */ -++#define FBIOROTATE 0x46a0 /* rotated fb */ -++#define FBIOGETBUFADDRS 0x46a1 /* get buffers addresses */ -++#define FBIO_GET_MODE 0x46a2 /* get lcd info */ -++#define FBIO_SET_MODE 0x46a3 /* set osd mode */ -++#define FBIO_DEEP_SET_MODE 0x46a4 /* set panel and osd mode */ -++#define FBIO_MODE_SWITCH 0x46a5 /* switch mode between LCD and TVE */ -++#define FBIO_GET_TVE_MODE 0x46a6 /* get tve info */ -++#define FBIO_SET_TVE_MODE 0x46a7 /* set tve mode */ -++ -++/* -++ * LCD panel specific definition -++ */ -++/* AUO */ -++#if defined(CONFIG_JZ4750_LCD_AUO_A043FL01V2) -++#if defined(CONFIG_JZ4750_APUS) /* board pavo */ -++ #define SPEN (32*3+29) /*LCD_CS*/ -++ #define SPCK (32*3+26) /*LCD_SCL*/ -++ #define SPDA (32*3+27) /*LCD_SDA*/ -++ #define LCD_RET (32*4+25) /*LCD_DISP_N use for lcd reset*/ -++#elif defined(CONFIG_JZ4750_FUWA) /* board pavo */ -++ #define SPEN (32*3+29) /*LCD_CS*/ -++ #define SPCK (32*3+26) /*LCD_SCL*/ -++ #define SPDA (32*3+27) /*LCD_SDA*/ -++ #define LCD_RET (32*5+2) /*LCD_DISP_N use for lcd reset*/ -++#else -++#error "driver/video/Jzlcd.h, please define SPI pins on your board." -++#endif -++ -++#define __spi_write_reg(reg, val) \ -++ do { \ -++ unsigned char no; \ -++ unsigned short value; \ -++ unsigned char a=0; \ -++ unsigned char b=0; \ -++ __gpio_as_output(SPEN); /* use SPDA */ \ -++ __gpio_as_output(SPCK); /* use SPCK */ \ -++ __gpio_as_output(SPDA); /* use SPDA */ \ -++ a=reg; \ -++ b=val; \ -++ __gpio_set_pin(SPEN); \ -++ __gpio_clear_pin(SPCK); \ -++ udelay(50); \ -++ __gpio_clear_pin(SPDA); \ -++ __gpio_clear_pin(SPEN); \ -++ udelay(50); \ -++ value=((a<<8)|(b&0xFF)); \ -++ for(no=0;no<16;no++) \ -++ { \ -++ if((value&0x8000)==0x8000){ \ -++ __gpio_set_pin(SPDA);} \ -++ else{ \ -++ __gpio_clear_pin(SPDA); } \ -++ udelay(50); \ -++ __gpio_set_pin(SPCK); \ -++ value=(value<<1); \ -++ udelay(50); \ -++ __gpio_clear_pin(SPCK); \ -++ } \ -++ __gpio_set_pin(SPEN); \ -++ udelay(400); \ -++ } while (0) -++#define __spi_read_reg(reg,val) \ -++ do{ \ -++ unsigned char no; \ -++ unsigned short value; \ -++ __gpio_as_output(SPEN); /* use SPDA */ \ -++ __gpio_as_output(SPCK); /* use SPCK */ \ -++ __gpio_as_output(SPDA); /* use SPDA */ \ -++ value = ((reg << 0) | (1 << 7)); \ -++ val = 0; \ -++ __gpio_as_output(SPDA); \ -++ __gpio_set_pin(SPEN); \ -++ __gpio_clear_pin(SPCK); \ -++ udelay(50); \ -++ __gpio_clear_pin(SPDA); \ -++ __gpio_clear_pin(SPEN); \ -++ udelay(50); \ -++ for (no = 0; no < 16; no++ ) { \ -++ udelay(50); \ -++ if(no < 8) \ -++ { \ -++ if (value & 0x80) /* send data */ \ -++ __gpio_set_pin(SPDA); \ -++ else \ -++ __gpio_clear_pin(SPDA); \ -++ udelay(50); \ -++ __gpio_set_pin(SPCK); \ -++ value = (value << 1); \ -++ udelay(50); \ -++ __gpio_clear_pin(SPCK); \ -++ if(no == 7) \ -++ __gpio_as_input(SPDA); \ -++ } \ -++ else \ -++ { \ -++ udelay(100); \ -++ __gpio_set_pin(SPCK); \ -++ udelay(50); \ -++ val = (val << 1); \ -++ val |= __gpio_get_pin(SPDA); \ -++ __gpio_clear_pin(SPCK); \ -++ } \ -++ } \ -++ __gpio_as_output(SPDA); \ -++ __gpio_set_pin(SPEN); \ -++ udelay(400); \ -++ } while(0) -++ -++#define __lcd_special_pin_init() \ -++ do { \ -++ __gpio_as_output(SPEN); /* use SPDA */ \ -++ __gpio_as_output(SPCK); /* use SPCK */ \ -++ __gpio_as_output(SPDA); /* use SPDA */ \ -++ __gpio_as_output(LCD_RET); \ -++ udelay(50); \ -++ __gpio_clear_pin(LCD_RET); \ -++ udelay(100); \ -++ __gpio_set_pin(LCD_RET); \ -++ } while (0) -++#define __lcd_special_on() \ -++ do { \ -++ udelay(50); \ -++ __gpio_clear_pin(LCD_RET); \ -++ udelay(100); \ -++ __gpio_set_pin(LCD_RET); \ -++} while (0) -++ -++ #define __lcd_special_off() \ -++ do { \ -++ __gpio_clear_pin(LCD_RET); \ -++ } while (0) -++ -++#endif /* CONFIG_JZLCD_AUO_A030FL01_V1 */ -++ -++/* TRULY_TFTG320240DTSW */ -++#if defined(CONFIG_JZ4750_LCD_TRULY_TFTG320240DTSW_16BIT) || defined(CONFIG_JZ4750_LCD_TRULY_TFTG320240DTSW_18BIT) -++ -++#if defined(CONFIG_JZ4750_FUWA) -++#define LCD_RESET_PIN (32*3+25)// LCD_REV, GPD25 -++#else -++#error "Define LCD_RESET_PIN on your board" -++#endif -++ -++#define __lcd_special_on() \ -++do { \ -++ __gpio_as_output(32*3+30);\ -++ __gpio_clear_pin(32*3+30);\ -++ __gpio_as_output(LCD_RESET_PIN); \ -++ __gpio_set_pin(LCD_RESET_PIN); \ -++ udelay(100); \ -++ __gpio_clear_pin(LCD_RESET_PIN); \ -++ udelay(100); \ -++ __gpio_set_pin(LCD_RESET_PIN); \ -++} while (0) -++ -++#endif /* CONFIG_JZ4750_LCD_TRULY_TFTG320240DTSW */ -++ -++// Wolfgang 2008.02.23 -++#if defined(CONFIG_JZ4750_LCD_TOPPOLY_TD025THEA7_RGB_DELTA) || defined(CONFIG_JZ4750_LCD_TOPPOLY_TD025THEA7_RGB_DUMMY) -++ -++#if defined(CONFIG_JZ4750_LCD_TOPPOLY_TD025THEA7_RGB_DELTA) -++#define PANEL_MODE 0x02 /* RGB Delta */ -++#elif defined(CONFIG_JZ4750_LCD_TOPPOLY_TD025THEA7_RGB_DUMMY) -++#define PANEL_MODE 0x00 /* RGB Dummy */ -++#endif -++ -++#if defined(CONFIG_JZ4750_FUWA) /* board FuWa */ -++ #define SPEN (32*3+16) //LCD_D16 - GPD16 -++ #define SPCK (32*3+17) //LCD_D17 - GPD17 -++ #define SPDA (32*3+21) //LCD_DE - GPD21 -++ #define LCD_RET (32*3+25) //LCD_REV - GPD25 //use for lcd reset -++#else -++#error "please define SPI pins on your board." -++#endif -++ -++ #define __spi_write_reg1(reg, val) \ -++ do { \ -++ unsigned char no;\ -++ unsigned short value;\ -++ unsigned char a=0;\ -++ unsigned char b=0;\ -++ a=reg;\ -++ b=val;\ -++ __gpio_set_pin(SPEN);\ -++ udelay(100);\ -++ __gpio_clear_pin(SPCK);\ -++ __gpio_clear_pin(SPDA);\ -++ __gpio_clear_pin(SPEN);\ -++ udelay(25);\ -++ value=((a<<8)|(b&0xFF));\ -++ for(no=0;no<16;no++)\ -++ {\ -++ __gpio_clear_pin(SPCK);\ -++ if((value&0x8000)==0x8000)\ -++ __gpio_set_pin(SPDA);\ -++ else\ -++ __gpio_clear_pin(SPDA);\ -++ udelay(25);\ -++ __gpio_set_pin(SPCK);\ -++ value=(value<<1); \ -++ udelay(25);\ -++ }\ -++ __gpio_clear_pin(SPCK);\ -++ __gpio_set_pin(SPEN);\ -++ udelay(100);\ -++ } while (0) -++ -++ #define __spi_write_reg(reg, val) \ -++ do {\ -++ __spi_write_reg1((reg<<2), val); \ -++ udelay(100); \ -++ }while(0) -++ -++ #define __lcd_special_pin_init() \ -++ do { \ -++ __gpio_as_output(SPEN); /* use SPDA */\ -++ __gpio_as_output(SPCK); /* use SPCK */\ -++ __gpio_as_output(SPDA); /* use SPDA */\ -++ __gpio_as_output(SPDA); /* use reset */\ -++ __gpio_as_output(LCD_RET); /* use reset */\ -++ __gpio_set_pin(LCD_RET);\ -++ mdelay(15);\ -++ __gpio_clear_pin(LCD_RET);\ -++ mdelay(15);\ -++ __gpio_set_pin(LCD_RET);\ -++ } while (0) -++ -++ #define __lcd_special_on() \ -++ do { \ -++ mdelay(10); \ -++ __spi_write_reg(0x00, 0x10); \ -++ __spi_write_reg(0x01, 0xB1); \ -++ __spi_write_reg(0x00, 0x10); \ -++ __spi_write_reg(0x01, 0xB1); \ -++ __spi_write_reg(0x02, PANEL_MODE); /* RGBD MODE */ \ -++ __spi_write_reg(0x03, 0x01); /* Noninterlace*/ \ -++ mdelay(10); \ -++ } while (0) -++ -++ #define __lcd_special_off() \ -++ do { \ -++ } while (0) -++ -++#endif /* CONFIG_JZ4750_LCD_TOPPOLY_TD025THEA7_RGB_DELTA */ -++ -++ -++#if defined(CONFIG_JZ4750_LCD_FOXCONN_PT035TN01) || defined(CONFIG_JZ4750_LCD_INNOLUX_PT035TN01_SERIAL) -++ -++#if defined(CONFIG_JZ4750_LCD_FOXCONN_PT035TN01) /* board FUWA */ -++#define MODE 0xcd /* 24bit parellel RGB */ -++#endif -++#if defined(CONFIG_JZ4750_LCD_INNOLUX_PT035TN01_SERIAL) -++#define MODE 0xc9 /* 8bit serial RGB */ -++#endif -++ -++#if defined(CONFIG_JZ4750_FUWA) /* board FuWa */ -++#if 0 -++ #define SPEN (32*5+7) //LCD_SPL GPF7 -++ #define SPCK (32*5+6) //LCD_CLS GPF6 -++ #define SPDA (32*5+5) //LCD_PS GPF5 -++ #define LCD_RET (32*5+4) //LCD_REV GPF4 //use for lcd reset -++#endif -++ #define SPEN (32*3+29) /*LCD_CS*/ -++ #define SPCK (32*3+26) /*LCD_SCL*/ -++ #define SPDA (32*3+27) /*LCD_SDA*/ -++ #define LCD_RET (32*4+25) /*LCD_DISP_N use for lcd reset*/ -++#else -++#error "driver/video/Jzlcd.h, please define SPI pins on your board." -++#endif -++ -++ #define __spi_write_reg1(reg, val) \ -++ do { \ -++ unsigned char no;\ -++ unsigned short value;\ -++ unsigned char a=0;\ -++ unsigned char b=0;\ -++ a=reg;\ -++ b=val;\ -++ __gpio_set_pin(SPEN);\ -++ __gpio_set_pin(SPCK);\ -++ __gpio_clear_pin(SPDA);\ -++ __gpio_clear_pin(SPEN);\ -++ udelay(25);\ -++ value=((a<<8)|(b&0xFF));\ -++ for(no=0;no<16;no++)\ -++ {\ -++ __gpio_clear_pin(SPCK);\ -++ if((value&0x8000)==0x8000)\ -++ __gpio_set_pin(SPDA);\ -++ else\ -++ __gpio_clear_pin(SPDA);\ -++ udelay(25);\ -++ __gpio_set_pin(SPCK);\ -++ value=(value<<1); \ -++ udelay(25);\ -++ }\ -++ __gpio_set_pin(SPEN);\ -++ udelay(100);\ -++ } while (0) -++ -++ #define __spi_write_reg(reg, val) \ -++ do {\ -++ __spi_write_reg1((reg<<2|2), val); \ -++ udelay(100); \ -++ }while(0) -++ -++ #define __lcd_special_pin_init() \ -++ do { \ -++ __gpio_as_output(SPEN); /* use SPDA */\ -++ __gpio_as_output(SPCK); /* use SPCK */\ -++ __gpio_as_output(SPDA); /* use SPDA */\ -++ __gpio_as_output(LCD_RET);\ -++ udelay(50);\ -++ __gpio_clear_pin(LCD_RET);\ -++ mdelay(150);\ -++ __gpio_set_pin(LCD_RET);\ -++ } while (0) -++ -++ #define __lcd_special_on() \ -++ do { \ -++ udelay(50);\ -++ __gpio_clear_pin(LCD_RET);\ -++ mdelay(150);\ -++ __gpio_set_pin(LCD_RET);\ -++ mdelay(10);\ -++ __spi_write_reg(0x00, 0x03); \ -++ __spi_write_reg(0x01, 0x40); \ -++ __spi_write_reg(0x02, 0x11); \ -++ __spi_write_reg(0x03, MODE); /* mode */ \ -++ __spi_write_reg(0x04, 0x32); \ -++ __spi_write_reg(0x05, 0x0e); \ -++ __spi_write_reg(0x07, 0x03); \ -++ __spi_write_reg(0x08, 0x08); \ -++ __spi_write_reg(0x09, 0x32); \ -++ __spi_write_reg(0x0A, 0x88); \ -++ __spi_write_reg(0x0B, 0xc6); \ -++ __spi_write_reg(0x0C, 0x20); \ -++ __spi_write_reg(0x0D, 0x20); \ -++ } while (0) //reg 0x0a is control the display direction:DB0->horizontal level DB1->vertical level -++ -++/* __spi_write_reg(0x02, 0x03); \ -++ __spi_write_reg(0x06, 0x40); \ -++ __spi_write_reg(0x0a, 0x11); \ -++ __spi_write_reg(0x0e, 0xcd); \ -++ __spi_write_reg(0x12, 0x32); \ -++ __spi_write_reg(0x16, 0x0e); \ -++ __spi_write_reg(0x1e, 0x03); \ -++ __spi_write_reg(0x22, 0x08); \ -++ __spi_write_reg(0x26, 0x40); \ -++ __spi_write_reg(0x2a, 0x88); \ -++ __spi_write_reg(0x2e, 0x88); \ -++ __spi_write_reg(0x32, 0x20); \ -++ __spi_write_reg(0x36, 0x20); \ -++*/ -++// } while (0) //reg 0x0a is control the display direction:DB0->horizontal level DB1->vertical level -++ -++ #define __lcd_special_off() \ -++ do { \ -++ __spi_write_reg(0x00, 0x03); \ -++ } while (0) -++ -++#endif /* CONFIG_JZ4750_LCD_FOXCONN_PT035TN01 or CONFIG_JZ4750_LCD_INNOLUX_PT035TN01_SERIAL */ -++ -++#if defined(CONFIG_JZ4750_LCD_TRULY_TFT_GG1P0319LTSW_W) -++static inline void CmdWrite(unsigned int cmd) -++{ -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); /* wait slcd ready */ -++ udelay(30); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | cmd; -++} -++ -++static inline void DataWrite(unsigned int data) -++{ -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); /* wait slcd ready */ -++// udelay(30); -++ REG_SLCD_DATA = SLCD_DATA_RS_DATA | data; -++} -++ -++ -++static inline void delay(long delay_time) -++{ -++ long cnt; -++ -++// delay_time *= (384/8); -++ delay_time *= (43/8); -++ -++ for (cnt=0;cnt SETP 3 -++ CmdWrite(0x0000); -++ CmdWrite(0x01A0); -++ CmdWrite(0x3B01); -++ -++ CmdWrite(0x2809); -++ delay(1000); -++ CmdWrite(0x1900); -++ delay(1000); -++ CmdWrite(0x2110); -++ delay(1000); -++ CmdWrite(0x1805); -++ delay(1000); -++ CmdWrite(0x1E01); -++ delay(1000); -++ CmdWrite(0x1847); -++ delay(1000); -++ CmdWrite(0x1867); -++ delay(1000); -++ CmdWrite(0x18F7); -++ delay(1000); -++ CmdWrite(0x2100); -++ delay(1000); -++ CmdWrite(0x2809); -++ delay(1000); -++ CmdWrite(0x1A05); -++ delay(1000); -++ CmdWrite(0x19E8); -++ delay(1000); -++ CmdWrite(0x1F64); -++ delay(1000); -++ CmdWrite(0x2045); -++ delay(1000); -++ CmdWrite(0x1E81); -++ delay(1000); -++ CmdWrite(0x1B09); -++ delay(1000); -++ CmdWrite(0x0020); -++ delay(1000); -++ CmdWrite(0x0120); -++ delay(1000); -++ -++ CmdWrite(0x3B01); -++ delay(1000); -++ -++ /* Set Window(239,319), Set Cursor(239,319) */ -++ CmdWrite(0x0510); -++ CmdWrite(0x01C0); -++ CmdWrite(0x4500); -++ CmdWrite(0x46EF); -++ CmdWrite(0x4800); -++ CmdWrite(0x4700); -++ CmdWrite(0x4A3F); -++ CmdWrite(0x4901); -++ CmdWrite(0x42EF); -++ CmdWrite(0x443F); -++ CmdWrite(0x4301); -++ -++} -++ -++#if defined(CONFIG_JZ4750_FUWA) -++//#define PIN_CS_N (32*2+xx) /* a low voltage */ -++#define PIN_RD_N (32*3+21) /* LCD_DE: GP D21, a high voltage */ -++#define PIN_RESET_N (32*3+25) /* LCD_REV GP D25 */ -++#else -++#error "Define special lcd pins for your platform." -++#endif -++ -++#define __lcd_slcd_pin_init() \ -++ do { \ -++ __gpio_as_output(PIN_RD_N); /* RD#: LCD_REV */ \ -++ __gpio_as_output(PIN_RESET_N); /* RESET#: LCD_SPL */ \ -++ __gpio_set_pin(PIN_RD_N); /*set read signal high */ \ -++ __gpio_set_pin(PIN_RESET_N); \ -++ mdelay(100); \ -++ __gpio_clear_pin(PIN_RESET_N); \ -++ mdelay(100); \ -++ __gpio_set_pin(PIN_RESET_N); \ -++ /* Configure SLCD module */ \ -++ REG_LCD_CTRL &= ~(LCD_CTRL_ENA|LCD_CTRL_DIS); /* disable lcdc */ \ -++ REG_LCD_CFG = LCD_CFG_LCDPIN_SLCD | 0x0D; /* LCM */ \ -++ REG_SLCD_CTRL &= ~SLCD_CTRL_DMA_EN; /* disable slcd dma */ \ -++ REG_SLCD_CFG = SLCD_CFG_DWIDTH_16BIT | SLCD_CFG_CWIDTH_16BIT | SLCD_CFG_CS_ACTIVE_LOW | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING | SLCD_CFG_TYPE_PARALLEL; \ -++ REG_LCD_REV = 0x04; /* lcd clock??? */ \ -++ printk("Fuwa test, pixclk divide REG_LCD_REV=0x%08x\n", REG_LCD_REV); \ -++}while (0) -++ -++#define __lcd_slcd_special_on() \ -++ do { \ -++ __lcd_slcd_pin_init(); \ -++ SlcdInit(); \ -++ REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN; /* slcdc dma enable */ \ -++ } while (0) -++ -++#endif /* #if CONFIG_JZ4750_LCD_TRULY_TFT_GG1P0319LTSW_W */ -++ -++#ifndef __lcd_special_pin_init -++#define __lcd_special_pin_init() -++#endif -++#ifndef __lcd_special_on -++#define __lcd_special_on() -++#endif -++#ifndef __lcd_special_off -++#define __lcd_special_off() -++#endif -++ -++ -++/* -++ * Platform specific definition -++ */ -++#if defined(CONFIG_SOC_JZ4750) -++ -++#if defined(CONFIG_JZ4750_APUS) /* board apus */ -++#define __lcd_display_pin_init() \ -++do { \ -++ __gpio_as_output(GPIO_LCD_VCC_EN_N); \ -++ __lcd_special_pin_init(); \ -++} while (0) -++#define __lcd_display_on() \ -++do { \ -++ __gpio_clear_pin(GPIO_LCD_VCC_EN_N); \ -++ __lcd_special_on(); \ -++ __lcd_set_backlight_level(80); \ -++} while (0) -++ -++#define __lcd_display_off() \ -++do { \ -++ __lcd_close_backlight(); \ -++ __lcd_special_off(); \ -++} while (0) -++ -++#else /* other boards */ -++ -++#define __lcd_display_pin_init() \ -++do { \ -++ __lcd_special_pin_init(); \ -++} while (0) -++#define __lcd_display_on() \ -++do { \ -++ __lcd_special_on(); \ -++ __lcd_set_backlight_level(80); \ -++} while (0) -++ -++#define __lcd_display_off() \ -++do { \ -++ __lcd_close_backlight(); \ -++ __lcd_special_off(); \ -++} while (0) -++#endif /* APUS */ -++#endif /* CONFIG_SOC_JZ4750 */ -++ -++ -++/***************************************************************************** -++ * LCD display pin dummy macros -++ *****************************************************************************/ -++ -++#ifndef __lcd_display_pin_init -++#define __lcd_display_pin_init() -++#endif -++#ifndef __lcd_slcd_special_on -++#define __lcd_slcd_special_on() -++#endif -++#ifndef __lcd_display_on -++#define __lcd_display_on() -++#endif -++#ifndef __lcd_display_off -++#define __lcd_display_off() -++#endif -++#ifndef __lcd_set_backlight_level -++#define __lcd_set_backlight_level(n) -++#endif -++ -++#endif /* __JZ4750_LCD_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/video/jz4750_tve.c linux-2.6.24.7/drivers/video/jz4750_tve.c -+--- linux-2.6.24.7.old/drivers/video/jz4750_tve.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/video/jz4750_tve.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,104 @@ -++ -++/* -++ * linux/drivers/video/jz4750_tve.c -- Ingenic Jz4750 TVE Controller operation -++ * interface. -++ * Copyright (C) 2005-2008, Ingenic Semiconductor Inc. -++ * Author: Wolfgang Wang, -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ * You should have received a copy of the GNU General Public License along -++ * with this program; if not, write to the Free Software Foundation, Inc., -++ * 675 Mass Ave, Cambridge, MA 02139, USA. -++ */ -++ -++ -++#include -++#include "jz4750_tve.h" -++ -++struct jz4750tve_info jz4750_tve_info_PAL = { -++ .ctrl = (4 << TVE_CTRL_YCDLY_BIT) | TVE_CTRL_SYNCT | TVE_CTRL_PAL | TVE_CTRL_SWRST, /* PAL, SVIDEO */ -++ .frcfg = (23 << TVE_FRCFG_L1ST_BIT) | (625 << TVE_FRCFG_NLINE_BIT), -++ .slcfg1 = (800<ctrl = (jz4750_tve_info->ctrl | TVE_CTRL_DAPD) & ( ~( TVE_CTRL_DAPD1 | TVE_CTRL_DAPD2)); -++ jz4750_tve_info->ctrl &= ~TVE_CTRL_SWRST; -++ REG_TVE_CTRL = jz4750_tve_info->ctrl; -++} -++ -++/* turn off TVE, turn off DACn... */ -++void jz4750tve_disable_tve(void) -++{ -++ jz4750_tve_info->ctrl &= ~TVE_CTRL_DAPD;/* DACn disabled??? */ -++ jz4750_tve_info->ctrl |= TVE_CTRL_SWRST;/* DACn disabled??? */ -++ REG_TVE_CTRL = jz4750_tve_info->ctrl; -++} -++ -++void jz4750tve_set_tve_mode( struct jz4750tve_info *tve ) -++{ -++ REG_TVE_CTRL = tve->ctrl; -++ REG_TVE_FRCFG = tve->frcfg; -++ REG_TVE_SLCFG1 = tve->slcfg1; -++ REG_TVE_SLCFG2 = tve->slcfg2; -++ REG_TVE_SLCFG3 = tve->slcfg3; -++ REG_TVE_LTCFG1 = tve->ltcfg1; -++ REG_TVE_LTCFG2 = tve->ltcfg2; -++ REG_TVE_CFREQ = tve->cfreq; -++ REG_TVE_CPHASE = tve->cphase; -++ REG_TVE_CBCRCFG = tve->cbcrcfg; -++ REG_TVE_WSSCR = tve->wsscr; -++ REG_TVE_WSSCFG1 = tve->wsscfg1; -++ REG_TVE_WSSCFG2 = tve->wsscfg2; -++ REG_TVE_WSSCFG3 = tve->wsscfg3; -++} -++ -++void jz4750tve_init( int tve_mode ) -++{ -++ switch ( tve_mode ) { -++ case PANEL_MODE_TVE_PAL: -++ jz4750_tve_info = &jz4750_tve_info_PAL; -++ break; -++ case PANEL_MODE_TVE_NTSC: -++ jz4750_tve_info = &jz4750_tve_info_NTSC; -++ break; -++ } -++ -++ jz4750tve_set_tve_mode( jz4750_tve_info ); -++// jz4750tve_enable_tve(); -++} -+diff -urN linux-2.6.24.7.old/drivers/video/jz4750_tve.h linux-2.6.24.7/drivers/video/jz4750_tve.h -+--- linux-2.6.24.7.old/drivers/video/jz4750_tve.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/video/jz4750_tve.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,45 @@ -++#ifndef __JZ4750_TVE_H__ -++#define __JZ4750_TVE_H__ -++ -++ -++#define PANEL_MODE_LCD_PANEL 0 -++#define PANEL_MODE_TVE_PAL 1 -++#define PANEL_MODE_TVE_NTSC 2 -++ -++/* TV parameter */ -++#define TVE_WIDTH_PAL 720 -++#define TVE_HEIGHT_PAL 573 -++#define TVE_FREQ_PAL 50 -++#define TVE_WIDTH_NTSC 720 -++#define TVE_HEIGHT_NTSC 482 -++#define TVE_FREQ_NTSC 60 -++ -++ -++/* Structure for TVE */ -++struct jz4750tve_info { -++ unsigned int ctrl; -++ unsigned int frcfg; -++ unsigned int slcfg1; -++ unsigned int slcfg2; -++ unsigned int slcfg3; -++ unsigned int ltcfg1; -++ unsigned int ltcfg2; -++ unsigned int cfreq; -++ unsigned int cphase; -++ unsigned int cbcrcfg; -++ unsigned int wsscr; -++ unsigned int wsscfg1; -++ unsigned int wsscfg2; -++ unsigned int wsscfg3; -++}; -++ -++extern struct jz4750tve_info *jz4750_tve_info; -++ -++extern void jz4750tve_enable_tve(void); -++extern void jz4750tve_disable_tve(void); -++ -++extern void jz4750tve_set_tve_mode( struct jz4750tve_info *tve ); -++extern void jz4750tve_init( int tve_mode ); -++ -++ -++#endif /* __JZ4750_TVE_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/video/jz_kgm_spfd5420a.h linux-2.6.24.7/drivers/video/jz_kgm_spfd5420a.h -+--- linux-2.6.24.7.old/drivers/video/jz_kgm_spfd5420a.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/video/jz_kgm_spfd5420a.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,382 @@ -++/* Set registers of smart lcd acording to the following routines -++ * Note: BUS width and CMD width and register value width -++ * This example: BUS is 8, 9, 16 or 18-bit; CMD and DATA is 16-bit -++ * Configure SLCD module to initialize smart lcd registers -++ -++ switch (bus) { -++ case 8: -++ REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_8_x2 -++ | SLCD_CFG_CWIDTH_8BIT | SLCD_CFG_CS_ACTIVE_LOW -++ | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING -++ | SLCD_CFG_TYPE_PARALLEL; -++ __gpio_as_slcd_8bit(); -++ break; -++ case 9: -++ REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_8_x2 -++ | SLCD_CFG_CWIDTH_8BIT | SLCD_CFG_CS_ACTIVE_LOW -++ | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING -++ | SLCD_CFG_TYPE_PARALLEL; -++ __gpio_as_slcd_9bit(); -++ break; -++ case 16: -++ REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_16 -++ | SLCD_CFG_CWIDTH_16BIT | SLCD_CFG_CS_ACTIVE_LOW -++ | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING -++ | SLCD_CFG_TYPE_PARALLEL; -++ __gpio_as_slcd_16bit(); -++ break; -++ case 18: -++ REG_SLCD_CFG = SLCD_CFG_BURST_8_WORD | SLCD_CFG_DWIDTH_18 -++ | SLCD_CFG_CWIDTH_18BIT | SLCD_CFG_CS_ACTIVE_LOW -++ | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_CLK_ACTIVE_FALLING -++ | SLCD_CFG_TYPE_PARALLEL; -++ __gpio_as_slcd_18bit(); -++ break; -++ } -++ -++ static void Mcupanel_RegSet(unsigned int cmd, unsigned int data) -++ { -++ switch (bus) { -++ case 8: -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_DATA | (data&0xffff); -++ break; -++ case 9: -++ data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); -++ data = ((data << 6) & 0xfc0000) | ((data << 4) & 0xfc00) | ((data << 2) & 0xfc); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_DATA | data; -++ break; -++ case 16: -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | (cmd&0xffff); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_DATA | (data&0xffff); -++ break; -++ case 18: -++ cmd = ((cmd & 0xff) << 1) | ((cmd & 0xff00) << 2); -++ data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | cmd; -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_DATA | ((data<<6)&0xfc0000)|((data<<4)&0xfc00) | ((data<<2)&0xfc); -++ break; -++ default: -++ printk("Don't support %d bit Bus\n", jzfb.bus ); -++ break; -++ } -++ } -++ -++ static void Mcupanel_Command(unsigned int cmd) { -++ switch (bus) { -++ case 8: -++ case 9: -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0); -++ break; -++ case 16: -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | (cmd&0xffff); -++ break; -++ case 18: -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) << 2) | ((cmd&0xff) << 1); -++ break; -++ default: -++ printk("Don't support %d bit Bus\n", jzfb.bus ); -++ break; -++ } -++ } -++ -++ *Display---------------------------------------- -++ Note: BUS and BPP, send data to gram data register to display -++ BUS: 8, 9, 16 or 18-bit; BPP: 8, 16, 18-bit -++ switch (bus) { -++ case 8: -++ switch (bpp) { -++ case 8: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -++ break; -++ case 15: -++ case 16: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x2; -++ break; -++ case 17 ... 32: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x3; -++ break; -++ default: -++ printk("The BPP %d is not supported\n", jzfb.bpp); -++ break; -++ } -++ break; -++ case 9: -++ switch (bpp) { -++ case 8: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -++ break; -++ case 15 ... 16: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x2; -++ break; -++ case 17 ... 32: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_9_x2; -++ break; -++ default: -++ printk("The BPP %d is not supported\n", jzfb.bpp); -++ break; -++ } -++ break; -++ case 16: -++ switch (bpp) { -++ case 8: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -++ break; -++ case 15 ... 16: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_16; -++ break; -++ case 17 ... 32: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x3; -++ break; -++ default: -++ printk("The BPP %d is not supported\n", jzfb.bpp); -++ break; -++ } -++ break; -++ case 18: -++ switch (bpp) { -++ case 8: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_8_x1; -++ break; -++ case 15: -++ case 16: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_16; -++ break; -++ case 17 ... 32: -++ REG_SLCD_CFG &= ~SLCD_CFG_DWIDTH_MASK; -++ REG_SLCD_CFG |= SLCD_CFG_DWIDTH_18; -++ break; -++ default: -++ printk("The BPP %d is not supported\n", jzfb.bpp); -++ break; -++ } -++ break; -++ default: -++ printk("Error: The BUS %d is not supported\n", jzfb.bus); -++ break; -++ } -++ dprintk("SLCD_CFG=0x%x\n", REG_SLCD_CFG); -++} -++ ************************************************************************************************/ -++ -++#ifndef __JZ_KGM_SPF5420A_H__ -++#define __JZ_KGM_SPF5420A_H__ -++ -++#include -++ -++#if defined(CONFIG_JZ4750_SLCD_KGM701A3_TFT_SPFD5420A) -++#define WR_GRAM_CMD 0x0202 -++ -++#if defined(CONFIG_JZ4750_FUWA) -++#define PIN_CS_N (32*3+24) // Chip select //GPD24; -++#define PIN_RESET_N (32*5+6) /* LCD_REV GPF6 */ -++#else -++#error "Define special lcd pins for your platform." -++#endif -++ -++/* Sent a command with data (18-bit bus, 16-bit index, 16-bit register value) */ -++static void Mcupanel_RegSet(unsigned int cmd, unsigned int data) -++{ -++ cmd = ((cmd & 0xff) << 1) | ((cmd & 0xff00) << 2); -++ data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); -++ data = ((data<<6)&0xfc0000)|((data<<4)&0xfc00) | ((data<<2)&0xfc); -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | cmd; -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_DATA | data; -++} -++ -++/* Sent a command without data (18-bit bus, 16-bit index) */ -++static void Mcupanel_Command(unsigned int cmd) { -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); -++ REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) << 2) | ((cmd&0xff) << 1); -++} -++ -++/* Set the start address of screen, for example (0, 0) */ -++void Mcupanel_SetAddr(u32 x, u32 y) //u32 -++{ -++ Mcupanel_RegSet(0x200,x) ; -++ udelay(1); -++ Mcupanel_RegSet(0x201,y) ; -++ udelay(1); -++ Mcupanel_Command(0x202); -++ -++} -++ -++#undef __lcd_special_pin_init -++#define __lcd_special_pin_init() \ -++do { \ -++ __gpio_as_output(PIN_CS_N); \ -++ __gpio_as_output(PIN_RESET_N); \ -++ __gpio_clear_pin(PIN_CS_N); /* Clear CS */ \ -++ mdelay(100); \ -++ __gpio_set_pin(PIN_RESET_N); \ -++ mdelay(10); \ -++ __gpio_clear_pin(PIN_RESET_N); \ -++ mdelay(10); \ -++ __gpio_set_pin(PIN_RESET_N); \ -++ mdelay(100); \ -++} while(0) -++ -++ -++#define GAMMA() \ -++do { \ -++ Mcupanel_RegSet(0x0300,0x0101); \ -++ Mcupanel_RegSet(0x0301,0x0b27); \ -++ Mcupanel_RegSet(0x0302,0x132a); \ -++ Mcupanel_RegSet(0x0303,0x2a13); \ -++ Mcupanel_RegSet(0x0304,0x270b); \ -++ Mcupanel_RegSet(0x0305,0x0101); \ -++ Mcupanel_RegSet(0x0306,0x1205); \ -++ Mcupanel_RegSet(0x0307,0x0512); \ -++ Mcupanel_RegSet(0x0308,0x0005); \ -++ Mcupanel_RegSet(0x0309,0x0003); \ -++ Mcupanel_RegSet(0x030a,0x0f04); \ -++ Mcupanel_RegSet(0x030b,0x0f00); \ -++ Mcupanel_RegSet(0x030c,0x000f); \ -++ Mcupanel_RegSet(0x030d,0x040f); \ -++ Mcupanel_RegSet(0x030e,0x0300); \ -++ Mcupanel_RegSet(0x030f,0x0500); \ -++ /*** secorrect gamma2 ***/ \ -++ Mcupanel_RegSet(0x0400,0x3500); \ -++ Mcupanel_RegSet(0x0401,0x0001); \ -++ Mcupanel_RegSet(0x0404,0x0000); \ -++ Mcupanel_RegSet(0x0500,0x0000); \ -++ Mcupanel_RegSet(0x0501,0x0000); \ -++ Mcupanel_RegSet(0x0502,0x0000); \ -++ Mcupanel_RegSet(0x0503,0x0000); \ -++ Mcupanel_RegSet(0x0504,0x0000); \ -++ Mcupanel_RegSet(0x0505,0x0000); \ -++ Mcupanel_RegSet(0x0600,0x0000); \ -++ Mcupanel_RegSet(0x0606,0x0000); \ -++ Mcupanel_RegSet(0x06f0,0x0000); \ -++ Mcupanel_RegSet(0x07f0,0x5420); \ -++ Mcupanel_RegSet(0x07f3,0x288a); \ -++ Mcupanel_RegSet(0x07f4,0x0022); \ -++ Mcupanel_RegSet(0x07f5,0x0001); \ -++ Mcupanel_RegSet(0x07f0,0x0000); \ -++} while(0) -++ -++#define SlcdInit() \ -++do { \ -++ __gpio_set_pin(PIN_RESET_N); \ -++ mdelay(10); \ -++ __gpio_clear_pin(PIN_RESET_N); \ -++ mdelay(10); \ -++ __gpio_set_pin(PIN_RESET_N); \ -++ mdelay(100); \ -++ Mcupanel_RegSet(0x0600, 0x0001); /*soft reset*/ \ -++ mdelay(10); \ -++ Mcupanel_RegSet(0x0600, 0x0000); /*soft reset*/ \ -++ mdelay(10); \ -++ Mcupanel_RegSet(0x0606,0x0000); \ -++ udelay(10); \ -++ Mcupanel_RegSet(0x0007,0x0001); \ -++ udelay(10); \ -++ Mcupanel_RegSet(0x0110,0x0001); \ -++ udelay(10); \ -++ Mcupanel_RegSet(0x0100,0x17b0); \ -++ Mcupanel_RegSet(0x0101,0x0147); \ -++ Mcupanel_RegSet(0x0102,0x019d); \ -++ Mcupanel_RegSet(0x0103,0x8600); \ -++ Mcupanel_RegSet(0x0281,0x0010); \ -++ udelay(10); \ -++ Mcupanel_RegSet(0x0102,0x01bd); \ -++ udelay(10); \ -++ /************initial************/\ -++ Mcupanel_RegSet(0x0000,0x0000); \ -++ Mcupanel_RegSet(0x0001,0x0000); \ -++ Mcupanel_RegSet(0x0002,0x0400); \ -++ Mcupanel_RegSet(0x0003,0x12b8); /*up:0x1288 down:0x12B8 left:0x1290 right:0x12A0*/ \ -++ Mcupanel_RegSet(0x0006,0x0000); \ -++ Mcupanel_RegSet(0x0008,0x0503); \ -++ Mcupanel_RegSet(0x0009,0x0001); \ -++ Mcupanel_RegSet(0x000b,0x0010); \ -++ Mcupanel_RegSet(0x000c,0x0000); \ -++ Mcupanel_RegSet(0x000f,0x0000); \ -++ Mcupanel_RegSet(0x0007,0x0001); \ -++ Mcupanel_RegSet(0x0010,0x0010); \ -++ Mcupanel_RegSet(0x0011,0x0202); \ -++ Mcupanel_RegSet(0x0012,0x0300); \ -++ Mcupanel_RegSet(0x0020,0x021e); \ -++ Mcupanel_RegSet(0x0021,0x0202); \ -++ Mcupanel_RegSet(0x0022,0x0100); \ -++ Mcupanel_RegSet(0x0090,0x0000); \ -++ Mcupanel_RegSet(0x0092,0x0000); \ -++ Mcupanel_RegSet(0x0100,0x16b0); \ -++ Mcupanel_RegSet(0x0101,0x0147); \ -++ Mcupanel_RegSet(0x0102,0x01bd); \ -++ Mcupanel_RegSet(0x0103,0x2c00); \ -++ Mcupanel_RegSet(0x0107,0x0000); \ -++ Mcupanel_RegSet(0x0110,0x0001); \ -++ Mcupanel_RegSet(0x0210,0x0000); \ -++ Mcupanel_RegSet(0x0211,0x00ef); \ -++ Mcupanel_RegSet(0x0212,0x0000); \ -++ Mcupanel_RegSet(0x0213,0x018f); \ -++ Mcupanel_RegSet(0x0280,0x0000); \ -++ Mcupanel_RegSet(0x0281,0x0001); \ -++ Mcupanel_RegSet(0x0282,0x0000); \ -++ GAMMA(); \ -++ Mcupanel_RegSet(0x0007,0x0173); \ -++ Mcupanel_Command(0x0202); /*Write Data to GRAM */ \ -++ udelay(10);\ -++ Mcupanel_SetAddr(0,0);\ -++ udelay(100);\ -++} while(0) -++ -++/*---- LCD Initial ----*/ -++#undef __lcd_slcd_pin_init -++#define __lcd_slcd_pin_init() \ -++ do { \ -++ __lcd_special_pin_init(); \ -++}while (0) -++ -++#undef __lcd_slcd_special_on -++#define __lcd_slcd_special_on() \ -++ do { \ -++ __lcd_slcd_pin_init(); \ -++ SlcdInit(); \ -++ REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN; /* slcdc dma enable */ \ -++ } while (0) -++ -++#define __init_slcd_bus()\ -++do{\ -++ __slcd_set_data_18bit();\ -++ __slcd_set_cmd_18bit();\ -++ __slcd_set_cs_low();\ -++ __slcd_set_rs_low();\ -++ __slcd_set_clk_falling();\ -++ __slcd_set_parallel_type();\ -++}while(0) -++#endif /* #if CONFIG_JZ4750_SLCD_KGM701A3_TFT_SPFD5420A */ -++ -++#endif /* __JZ_KGM_SPF5420A_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/video/jz_toppoly_td043mgeb1.h linux-2.6.24.7/drivers/video/jz_toppoly_td043mgeb1.h -+--- linux-2.6.24.7.old/drivers/video/jz_toppoly_td043mgeb1.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/video/jz_toppoly_td043mgeb1.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,264 @@ -++ -++#ifndef __JZ_KGM_TOPPOLY_TD043MGEB1_H__ -++#define __JZ_KGM_TOPPOLY_TD043MGEB1_H__ -++ -++#include -++ -++#if defined(CONFIG_JZ4750_LCD_TOPPOLY_TD043MGEB1) -++#if defined(CONFIG_JZ4750_APUS) /* board FuWa */ -++ #define SPEN (32*3+29) /*LCD_CS*/ -++ #define SPCK (32*3+26) /*LCD_SCL*/ -++ #define SPDA (32*3+27) /*LCD_SDA*/ -++ #define LCD_RET (32*4+23) /*LCD_DISP_N use for lcd reset*/ -++ #define LCD_STBY (32*4+25) /*LCD_STBY, use for lcd standby*/ -++#else -++#error "driver/video/Jzlcd.h, please define SPI pins on your board." -++#endif -++ -++#define __spi_write_reg(reg, val) \ -++ do { \ -++ unsigned char no; \ -++ unsigned short value; \ -++ unsigned char a=0; \ -++ unsigned char b=0; \ -++ __gpio_as_output(SPEN); /* use SPDA */ \ -++ __gpio_as_output(SPCK); /* use SPCK */ \ -++ __gpio_as_output(SPDA); /* use SPDA */ \ -++ a=reg; \ -++ b=val; \ -++ __gpio_set_pin(SPEN); \ -++ __gpio_clear_pin(SPCK); \ -++ udelay(500); \ -++ __gpio_clear_pin(SPDA); \ -++ __gpio_clear_pin(SPEN); \ -++ udelay(500); \ -++ value=((a<<8)|(b&0xFF)); \ -++ for(no=0;no<16;no++) \ -++ { \ -++ if((value&0x8000)==0x8000){ \ -++ __gpio_set_pin(SPDA);} \ -++ else{ \ -++ __gpio_clear_pin(SPDA); } \ -++ udelay(500); \ -++ __gpio_set_pin(SPCK); \ -++ value=(value<<1); \ -++ udelay(500); \ -++ __gpio_clear_pin(SPCK); \ -++ } \ -++ __gpio_set_pin(SPEN); \ -++ udelay(4000); \ -++ } while (0) -++#define __spi_read_reg(reg,val) \ -++ do{ \ -++ unsigned char no; \ -++ unsigned short value; \ -++ __gpio_as_output(SPEN); /* use SPDA */ \ -++ __gpio_as_output(SPCK); /* use SPCK */ \ -++ __gpio_as_output(SPDA); /* use SPDA */ \ -++ value = ((reg << 0) | (1 << 7)); \ -++ val = 0; \ -++ __gpio_as_output(SPDA); \ -++ __gpio_set_pin(SPEN); \ -++ __gpio_clear_pin(SPCK); \ -++ udelay(50); \ -++ __gpio_clear_pin(SPDA); \ -++ __gpio_clear_pin(SPEN); \ -++ udelay(50); \ -++ for (no = 0; no < 16; no++ ) { \ -++ udelay(50); \ -++ if(no < 8) \ -++ { \ -++ if (value & 0x80) /* send data */ \ -++ __gpio_set_pin(SPDA); \ -++ else \ -++ __gpio_clear_pin(SPDA); \ -++ udelay(50); \ -++ __gpio_set_pin(SPCK); \ -++ value = (value << 1); \ -++ udelay(50); \ -++ __gpio_clear_pin(SPCK); \ -++ if(no == 7) \ -++ __gpio_as_input(SPDA); \ -++ } \ -++ else \ -++ { \ -++ udelay(100); \ -++ __gpio_set_pin(SPCK); \ -++ udelay(50); \ -++ val = (val << 1); \ -++ val |= __gpio_get_pin(SPDA); \ -++ __gpio_clear_pin(SPCK); \ -++ } \ -++ } \ -++ __gpio_as_output(SPDA); \ -++ __gpio_set_pin(SPEN); \ -++ udelay(400); \ -++ } while(0) -++ -++#define __lcd_special_pin_init() \ -++ do { \ -++ __gpio_as_output(SPEN); /* use SPDA */ \ -++ __gpio_as_output(SPCK); /* use SPCK */ \ -++ __gpio_as_output(SPDA); /* use SPDA */ \ -++ __gpio_as_output(LCD_STBY); \ -++ __gpio_as_output(LCD_RET); \ -++ udelay(500); \ -++ __gpio_clear_pin(LCD_RET); \ -++ udelay(1000); \ -++ __gpio_set_pin(LCD_RET); \ -++ udelay(1000); \ -++ __gpio_set_pin(LCD_STBY); \ -++ udelay(1000); \ -++ } while (0) -++#define __lcd_special_on() \ -++ do { \ -++} while (0) -++ -++ #define __lcd_special_off() \ -++ do { \ -++ __gpio_clear_pin(LCD_RET); \ -++ } while (0) -++ -++#endif /* CONFIG_JZLCD_AUO_A030FL01_V1 */ -++ -++#endif /* __JZ_KGM_TOPPOLY_TD043MGEB1_H__ */ -++/* 2.2 -++ __spi_write_reg(0x02, 0x07 ); \ -++ __spi_write_reg(0x03, 0x5f); \ -++ __spi_write_reg(0x04, 0x17); \ -++ __spi_write_reg(0x05, 0x20); \ -++ __spi_write_reg(0x06, 0x08); \ -++ __spi_write_reg(0x07, 0x26); \ -++ __spi_write_reg(0x08, 0x13); \ -++ __spi_write_reg(0x09, 0x33); \ -++ __spi_write_reg(0x0a, 0x20); \ -++ __spi_write_reg(0x0b, 0x20); \ -++ __spi_write_reg(0x0c, 0x20); \ -++ __spi_write_reg(0x0d, 0x20); \ -++ __spi_write_reg(0x0e, 0x10); \ -++ __spi_write_reg(0x0f, 0x10); \ -++ __spi_write_reg(0x10, 0x10); \ -++ __spi_write_reg(0x11, 0x15); \ -++ __spi_write_reg(0x12, 0xaa); \ -++ __spi_write_reg(0x13, 0xff); \ -++ __spi_write_reg(0x14, 0x86); \ -++ __spi_write_reg(0x15, 0x8e); \ -++ __spi_write_reg(0x16, 0xd6); \ -++ __spi_write_reg(0x17, 0xfe); \ -++ __spi_write_reg(0x18, 0x28); \ -++ __spi_write_reg(0x19, 0x52); \ -++ __spi_write_reg(0x1a, 0x7c); \ -++ __spi_write_reg(0x1b, 0xe9); \ -++ __spi_write_reg(0x1c, 0x42); \ -++ __spi_write_reg(0x1d, 0x88); \ -++ __spi_write_reg(0x1e, 0xb8); \ -++ __spi_write_reg(0x1f, 0xff); \ -++ __spi_write_reg(0x20, 0xf0); \ -++ __spi_write_reg(0x21, 0xf0); \ -++ __spi_write_reg(0x22, 0x07); \ -++*/ -++/* 3.1 -++ __spi_write_reg(0x02, 0x07); \ -++ __spi_write_reg(0x03, 0x5f); \ -++ __spi_write_reg(0x04, 0x17); \ -++ __spi_write_reg(0x05, 0x20); \ -++ __spi_write_reg(0x06, 0x08); \ -++ __spi_write_reg(0x07, 0x20); \ -++ __spi_write_reg(0x08, 0x20); \ -++ __spi_write_reg(0x09, 0x20); \ -++ __spi_write_reg(0x0a, 0x20); \ -++ __spi_write_reg(0x0b, 0x20); \ -++ __spi_write_reg(0x0c, 0x20); \ -++ __spi_write_reg(0x0d, 0x22); \ -++ __spi_write_reg(0x0e, 0x10); \ -++ __spi_write_reg(0x0f, 0x10); \ -++ __spi_write_reg(0x10, 0x10); \ -++ __spi_write_reg(0x11, 0x15); \ -++ __spi_write_reg(0x12, 0x6a); \ -++ __spi_write_reg(0x13, 0xff); \ -++ __spi_write_reg(0x14, 0x86); \ -++ __spi_write_reg(0x15, 0x7c); \ -++ __spi_write_reg(0x16, 0xc2); \ -++ __spi_write_reg(0x17, 0xd1); \ -++ __spi_write_reg(0x18, 0xf5); \ -++ __spi_write_reg(0x19, 0x25); \ -++ __spi_write_reg(0x1a, 0x4a); \ -++ __spi_write_reg(0x1b, 0xbf); \ -++ __spi_write_reg(0x1c, 0x15); \ -++ __spi_write_reg(0x1d, 0x6a); \ -++ __spi_write_reg(0x1e, 0xa4); \ -++ __spi_write_reg(0x1f, 0xff); \ -++ __spi_write_reg(0x20, 0xf0); \ -++ __spi_write_reg(0x21, 0xf0); \ -++ __spi_write_reg(0x22, 0x08); \ -++ */ -++ /* 2.5 -++ __spi_write_reg(0x02, 0x07); \ -++ __spi_write_reg(0x03, 0x5f); \ -++ __spi_write_reg(0x04, 0x17); \ -++ __spi_write_reg(0x05, 0x20); \ -++ __spi_write_reg(0x06, 0x08); \ -++ __spi_write_reg(0x07, 0x20); \ -++ __spi_write_reg(0x08, 0x20); \ -++ __spi_write_reg(0x09, 0x20); \ -++ __spi_write_reg(0x0a, 0x20); \ -++ __spi_write_reg(0x0b, 0x20); \ -++ __spi_write_reg(0x0c, 0x20); \ -++ __spi_write_reg(0x0d, 0x22); \ -++ __spi_write_reg(0x0e, 0x10); \ -++ __spi_write_reg(0x0f, 0x10); \ -++ __spi_write_reg(0x10, 0x10); \ -++ __spi_write_reg(0x11, 0x15); \ -++ __spi_write_reg(0x12, 0xaa); \ -++ __spi_write_reg(0x13, 0xff); \ -++ __spi_write_reg(0x14, 0x86); \ -++ __spi_write_reg(0x15, 0x89); \ -++ __spi_write_reg(0x16, 0xc6); \ -++ __spi_write_reg(0x17, 0xea); \ -++ __spi_write_reg(0x18, 0x0c); \ -++ __spi_write_reg(0x19, 0x33); \ -++ __spi_write_reg(0x1a, 0x5e); \ -++ __spi_write_reg(0x1b, 0xd0); \ -++ __spi_write_reg(0x1c, 0x33); \ -++ __spi_write_reg(0x1d, 0x7e); \ -++ __spi_write_reg(0x1e, 0xb3); \ -++ __spi_write_reg(0x1f, 0xff); \ -++ __spi_write_reg(0x20, 0xf0); \ -++ __spi_write_reg(0x21, 0xf0); \ -++ __spi_write_reg(0x22, 0x08); \ -++*/ -++/* -++ __spi_write_reg(0x02, 0x07); \ -++ __spi_write_reg(0x03, 0x5f); \ -++ __spi_write_reg(0x04, 0x17); \ -++ __spi_write_reg(0x05, 0x20); \ -++ __spi_write_reg(0x06, 0x08); \ -++ __spi_write_reg(0x07, 0x20); \ -++ __spi_write_reg(0x08, 0x20); \ -++ __spi_write_reg(0x09, 0x20); \ -++ __spi_write_reg(0x0a, 0x20); \ -++ __spi_write_reg(0x0b, 0x20); \ -++ __spi_write_reg(0x0c, 0x20); \ -++ __spi_write_reg(0x0d, 0x22); \ -++ __spi_write_reg(0x0e, 0x10); \ -++ __spi_write_reg(0x0f, 0x10); \ -++ __spi_write_reg(0x10, 0x10); \ -++ __spi_write_reg(0x11, 0x15); \ -++ __spi_write_reg(0x12, 0xaa); \ -++ __spi_write_reg(0x13, 0xff); \ -++ __spi_write_reg(0x14, 0x86); \ -++ __spi_write_reg(0x15, 0x84); \ -++ __spi_write_reg(0x16, 0xc3); \ -++ __spi_write_reg(0x17, 0xd8); \ -++ __spi_write_reg(0x18, 0x01); \ -++ __spi_write_reg(0x19, 0x28); \ -++ __spi_write_reg(0x1a, 0x53); \ -++ __spi_write_reg(0x1b, 0xc5); \ -++ __spi_write_reg(0x1c, 0x26); \ -++ __spi_write_reg(0x1d, 0x74); \ -++ __spi_write_reg(0x1e, 0xae); \ -++ __spi_write_reg(0x1f, 0xff); \ -++ __spi_write_reg(0x20, 0xf0); \ -++ __spi_write_reg(0x21, 0xf0); \ -++ __spi_write_reg(0x22, 0x08); \ -++ */ -+diff -urN linux-2.6.24.7.old/drivers/video/jzlcd.c linux-2.6.24.7/drivers/video/jzlcd.c -+--- linux-2.6.24.7.old/drivers/video/jzlcd.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/video/jzlcd.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1571 @@ -++/* -++ * linux/drivers/video/jzlcd.c -- Ingenic On-Chip LCD frame buffer device -++ * -++ * Copyright (C) 2005-2007, Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "console/fbcon.h" -++ -++#include "jzlcd.h" -++ -++#undef DEBUG -++//#define DEBUG -++#ifdef DEBUG -++#define dprintk(x...) printk(x) -++#else -++#define dprintk(x...) -++#endif -++ -++#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) -++#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) -++#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) -++#ifdef DEBUG -++#define print_dbg(f, arg...) printk("dbg::" __FILE__ ",LINE(%d): " f "\n", __LINE__, ## arg) -++#else -++#define print_dbg(f, arg...) do {} while (0) -++#endif -++ -++struct lcd_cfb_info { -++ struct fb_info fb; -++ struct display_switch *dispsw; -++ signed int currcon; -++ int func_use_count; -++ -++ struct { -++ u16 red, green, blue; -++ } palette[NR_PALETTE]; -++#ifdef CONFIG_PM -++ struct pm_dev *pm; -++#endif -++#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -++ struct task_struct *rotate_daemon_thread; -++#endif -++}; -++ -++static struct lcd_cfb_info *jzlcd_info; -++ -++struct jzfb_info { -++ unsigned int cfg; /* panel mode and pin usage etc. */ -++ unsigned int w; -++ unsigned int h; -++ unsigned int bpp; /* bit per pixel */ -++ unsigned int fclk; /* frame clk */ -++ unsigned int hsw; /* hsync width, in pclk */ -++ unsigned int vsw; /* vsync width, in line count */ -++ unsigned int elw; /* end of line, in pclk */ -++ unsigned int blw; /* begin of line, in pclk */ -++ unsigned int efw; /* end of frame, in line count */ -++ unsigned int bfw; /* begin of frame, in line count */ -++}; -++ -++static struct jzfb_info jzfb = { -++#if defined(CONFIG_JZLCD_SHARP_LQ035Q7) -++ MODE_TFT_SHARP | PCLK_N | VSYNC_N, -++ 240, 320, 16, 60, 1, 2, 1, 2, 0, 6 -++#endif -++#if defined(CONFIG_JZLCD_SAMSUNG_LTS350Q1) -++ MODE_TFT_SAMSUNG | PCLK_N, -++ 240, 320, 16, 60, 1, 2, (254-240), 0, 7, 0 -++#endif -++#if defined(CONFIG_JZLCD_SAMSUNG_LTV350QVF04) -++ MODE_TFT_GEN | HSYNC_N | VSYNC_N, -++ 320, 240, 16, 70, 19, 4, 20, 14, 18, 6 -++#endif -++#if defined(CONFIG_JZLCD_SAMSUNG_LTP400WQF01) -++ MODE_TFT_GEN | HSYNC_N | VSYNC_N, -++ 480, 272, 16, 60, 41, 10, 2, 2, 2, 2 -++#endif -++ -++#if defined(CONFIG_JZLCD_SAMSUNG_LTP400WQF02) -++ /* MODE_TFT_18BIT: JZ4740@ version */ -++ MODE_TFT_GEN | MODE_TFT_18BIT | HSYNC_N | VSYNC_N, -++ 480, 272, 32, 60, 41, 10, 2, 2, 2, 2 -++#endif -++#if defined(CONFIG_JZLCD_TRULY_TFTG320240DTSW) -++ MODE_TFT_GEN | HSYNC_N | VSYNC_N | PCLK_N, -++ 320, 240, 16, 85, 30, 3, 38, 20, 11, 8 -++#endif -++#if defined(CONFIG_JZLCD_TRULY_TFTG320240DTSW_SERIAL) -++ MODE_8BIT_SERIAL_TFT | HSYNC_N | VSYNC_N | PCLK_N, -++ /* serial mode 280 lines, parallel mode 240 lines */ -++ 320, 280, 32, 60, (30*3), 3, (20*3), (38*3), 46, 23 -++#endif -++#if defined(CONFIG_JZLCD_AUO_A030FL01_V1) -++ MODE_TFT_GEN | MODE_TFT_18BIT | HSYNC_N | VSYNC_N, -++ 480, 272, 32, 60, 39, 10, 8, 4, 4, 2 -++#endif -++#if defined(CONFIG_JZLCD_TRULY_TFTG240320UTSW_63W_E) -++ MODE_TFT_GEN | HSYNC_N | VSYNC_N | PCLK_N | DE_N, -++ 320, 240, 16, 60, 3, 3, 3, 3, 3, 85 /* 320x240 */ -++#endif -++#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) && defined(CONFIG_JZ4740_PAVO) -++ MODE_TFT_GEN | HSYNC_N | VSYNC_N | MODE_TFT_18BIT | PCLK_N, -++// 320, 240, 18, 110, 1, 1, 10, 50, 10, 13 -++ 320, 240, 18, 80, 1, 1, 10, 50, 10, 13 -++#endif -++#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) && !(defined(CONFIG_JZ4740_PAVO)) -++ MODE_TFT_GEN | HSYNC_N | VSYNC_N | PCLK_N, -++ 320, 240, 16, 110, 1, 1, 10, 50, 10, 13 -++#endif -++#if defined(CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL) -++ MODE_8BIT_SERIAL_TFT | PCLK_N | HSYNC_N | VSYNC_N, -++ 320, 240, 32, 60, 1, 1, 10, 50, 10, 13 -++#endif -++#if defined(CONFIG_JZLCD_HYNIX_HT10X21) -++ MODE_TFT_GEN | PCLK_N, -++ 1024, 768, 16, 45, 1, 1, 75, 0, 3, 0 -++#endif -++#if defined(CONFIG_JZLCD_TOSHIBA_LTM084P363) -++ MODE_TFT_GEN | PCLK_N, -++ 800, 600, 16, 50, 1, 2, 199, 0, 2, 0 -++#endif -++#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42) -++ MODE_TFT_SHARP | PCLK_N, -++ 800, 600, 16, 40, 1, 1, 255, 0, 34, 0 -++#endif -++#if defined(CONFIG_JZLCD_CSTN_800x600) -++ MODE_STN_COLOR_DUAL | STN_DAT_PIN8, -++ 800, 600, 16, 30, 8, 1, 0, 0, 0, 0 -++#endif -++#if defined(CONFIG_JZLCD_CSTN_320x240) -++ MODE_STN_COLOR_SINGLE | STN_DAT_PIN8, -++ 320, 240, 16, 120, 8, 1, 8, 0, 0, 0 -++#endif -++#if defined(CONFIG_JZLCD_MSTN_640x480) -++ MODE_STN_MONO_DUAL | STN_DAT_PIN4, -++ 640, 480, 8, 110, 4, 1, 4, 0, 0, 0 -++#endif -++#if defined(CONFIG_JZLCD_MSTN_320x240) -++ MODE_STN_MONO_SINGLE | STN_DAT_PIN4, -++ 320, 240, 8, 110, 4, 1, 4, 0, 0, 0 -++#endif -++#if defined(CONFIG_JZLCD_MSTN_480x320) -++ MODE_STN_MONO_SINGLE | STN_DAT_PIN8 -++#if defined(CONFIG_JZLCD_MSTN_INVERSE) -++ | DATA_INVERSE -++#endif -++ , 480, 320, 8, 65, 8, 1, 8, 0, 0, 0 -++#endif -++ -++#if defined(CONFIG_JZLCD_MSTN_240x128) -++ MODE_STN_MONO_SINGLE | STN_DAT_PIN1 -++#if defined(CONFIG_JZLCD_MSTN_INVERSE) -++ | DATA_INVERSE -++#endif -++ , 240, 128, 8, 100, 1, 1, 1, 0, 0, 0 -++#endif -++}; -++ -++static struct lcd_desc *lcd_desc_base; -++static struct lcd_desc *lcd_palette_desc; -++static struct lcd_desc *lcd_frame_desc0; -++static struct lcd_desc *lcd_frame_desc1; -++ -++static unsigned char *lcd_palette; -++static unsigned char *lcd_frame[CONFIG_JZLCD_FRAMEBUFFER_MAX]; -++struct jz_lcd_buffer_addrs_t jz_lcd_buffer_addrs; -++//extern struct display fb_display[MAX_NR_CONSOLES]; -++#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -++static unsigned char *lcd_frame_user_fb; -++/* default rotate angle */ -++static volatile int rotate_angle = CONFIG_JZLCD_FRAMEBUFFER_DEFAULT_ROTATE_ANGLE; -++#endif -++ -++#ifdef DEBUG -++static void print_regs(void) /* debug */ -++{ -++ printk("REG_LCD_CFG:\t0x%8.8x\n", REG_LCD_CFG); -++ printk("REG_LCD_VSYNC:\t0x%8.8x\n", REG_LCD_VSYNC); -++ printk("REG_LCD_HSYNC:\t0x%8.8x\n", REG_LCD_HSYNC); -++ printk("REG_LCD_VAT:\t0x%8.8x\n", REG_LCD_VAT); -++ printk("REG_LCD_DAH:\t0x%8.8x\n", REG_LCD_DAH); -++ printk("REG_LCD_DAV:\t0x%8.8x\n", REG_LCD_DAV); -++ printk("REG_LCD_PS:\t0x%8.8x\n", REG_LCD_PS); -++ printk("REG_LCD_CLS:\t0x%8.8x\n", REG_LCD_CLS); -++ printk("REG_LCD_SPL:\t0x%8.8x\n", REG_LCD_SPL); -++ printk("REG_LCD_REV:\t0x%8.8x\n", REG_LCD_REV); -++ printk("REG_LCD_CTRL:\t0x%8.8x\n", REG_LCD_CTRL); -++ printk("REG_LCD_STATE:\t0x%8.8x\n", REG_LCD_STATE); -++ printk("REG_LCD_IID:\t0x%8.8x\n", REG_LCD_IID); -++ printk("REG_LCD_DA0:\t0x%8.8x\n", REG_LCD_DA0); -++ printk("REG_LCD_SA0:\t0x%8.8x\n", REG_LCD_SA0); -++ printk("REG_LCD_FID0:\t0x%8.8x\n", REG_LCD_FID0); -++ printk("REG_LCD_CMD0:\t0x%8.8x\n", REG_LCD_CMD0); -++ -++ printk("==================================\n"); -++ printk("REG_LCD_VSYNC:\t%d:%d\n", REG_LCD_VSYNC>>16, REG_LCD_VSYNC&0xfff); -++ printk("REG_LCD_HSYNC:\t%d:%d\n", REG_LCD_HSYNC>>16, REG_LCD_HSYNC&0xfff); -++ printk("REG_LCD_VAT:\t%d:%d\n", REG_LCD_VAT>>16, REG_LCD_VAT&0xfff); -++ printk("REG_LCD_DAH:\t%d:%d\n", REG_LCD_DAH>>16, REG_LCD_DAH&0xfff); -++ printk("REG_LCD_DAV:\t%d:%d\n", REG_LCD_DAV>>16, REG_LCD_DAV&0xfff); -++ printk("==================================\n"); -++ -++} -++#else -++#define print_regs() -++#endif -++ -++#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -++static int jzfb_rotate_daemon_thread(void *info) -++{ -++ int i,j; -++ struct fb_info *fb = &jzlcd_info->fb; -++ -++ while (!kthread_should_stop()) { -++#if (CONFIG_JZLCD_FRAMEBUFFER_BPP == 8) -++ unsigned char *plcd_frame = (unsigned char *)lcd_frame[0]; -++ unsigned char *pfb = (unsigned char *) (fb->screen_base); -++#elif (CONFIG_JZLCD_FRAMEBUFFER_BPP == 16) -++ unsigned short *plcd_frame = (unsigned short *)lcd_frame[0]; -++ unsigned short *pfb = (unsigned short *) (fb->screen_base); -++#elif (CONFIG_JZLCD_FRAMEBUFFER_BPP == 32) -++ unsigned int *plcd_frame = (unsigned int *)lcd_frame[0]; -++ unsigned int *pfb = (unsigned int *) (fb->screen_base); -++#else -++#error "ERROR, rotate not support this bpp." -++#endif -++ switch ( rotate_angle ) { -++ case FB_ROTATE_UR: -++ printk("%s, Warning, this shouldn't reache\n", __FUNCTION__); -++ ssleep(1); -++ break; -++ case FB_ROTATE_UD: /* cost about 30ms, can be accelrated by dma in the future */ -++ plcd_frame += jzfb.w*jzfb.h -1; -++ for (i=0;ivar.height+1; i++) { -++ for (j=1; j < fb->var.width+1; j++) -++ plcd_frame[j*fb->var.height-i] = *pfb++; -++ } -++ msleep(100); /* sleep 100ms */ -++ break; -++ case FB_ROTATE_CCW: /* cost about 80ms */ -++ for (i=0;ivar.height;i++) { -++ for ( j=fb->var.width-1;j>=0;j--) -++ plcd_frame[j*fb->var.height+i] = *pfb++; -++ } -++ msleep(100); /* sleep 100ms */ -++ break; -++ default: /* FB_ROTATE_UR */ -++ dprintk("Unknown rotate(%d) type\n", rotate_angle); -++ ssleep(1); -++ } -++ -++ dma_cache_wback_inv((unsigned int)(lcd_frame_user_fb), fb->fix.smem_len); -++ } -++ return 0; -++} -++/* -++ * rotate param angle: -++ * 0: FB_ROTATE_UR, 0'C -++ * 1: FB_ROTATE_CW, 90'C -++ * 2: FB_ROTATE_UD, 180'C -++ * 3: FB_ROTATE_CCW, 270'C -++ */ -++static int jzfb_rotate_change( int angle ) -++{ -++ struct fb_info *fb = &jzlcd_info->fb; -++ -++ /* clear frame buffer */ -++ memset((void*)lcd_frame_user_fb, 0x00, fb->fix.smem_len); -++ switch ( angle ) { -++ case FB_ROTATE_UR: -++ fb->var.width = fb->var.xres = fb->var.xres_virtual = jzfb.w; -++ fb->var.height = fb->var.yres = fb->var.yres_virtual = jzfb.h; -++ /* change lcd controller's data buffer to lcd_frame_user_fb*/ -++ lcd_frame_desc0->databuf = virt_to_phys((void *)lcd_frame_user_fb); -++ if ( rotate_angle != FB_ROTATE_UR ) -++ kthread_stop(jzlcd_info->rotate_daemon_thread); -++ rotate_angle = angle; -++ break; -++ case FB_ROTATE_UD: -++ case FB_ROTATE_CW: -++ case FB_ROTATE_CCW: -++ if ( angle == FB_ROTATE_UD ) { -++ fb->var.width = fb->var.xres = fb->var.xres_virtual = jzfb.w; -++ fb->var.height = fb->var.yres = fb->var.yres_virtual = jzfb.h; -++ } -++ else { /* CW, CCW */ -++ fb->var.width = fb->var.xres = fb->var.xres_virtual = jzfb.h; -++ fb->var.height = fb->var.yres = fb->var.yres_virtual = jzfb.w; -++ } -++ /* change lcd controller's data buffer to lcd_frame[0]*/ -++ lcd_frame_desc0->databuf = virt_to_phys((void *)lcd_frame[0]); -++ if ( rotate_angle == FB_ROTATE_UR || \ -++ jzlcd_info->rotate_daemon_thread == NULL) -++ jzlcd_info->rotate_daemon_thread = kthread_run( jzfb_rotate_daemon_thread, jzlcd_info, "%s", "jzlcd-rotate-daemon"); /* start rotate daemon */ -++ rotate_angle = angle; -++ break; -++ default: -++ printk("Invalid angle(%d)\n", (unsigned int)angle); -++ } -++ fb->fix.line_length = fb->var.xres * CONFIG_JZLCD_FRAMEBUFFER_BPP/8; -++ dma_cache_wback_inv((unsigned int)(lcd_frame_desc0), sizeof(struct lcd_desc)); -++ return 0; -++} -++ -++void jzfb_fb_rotate(struct fb_info *fbi, int angle) -++{ -++ jzfb_rotate_change( angle/90 ); -++} -++#endif /* #if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) */ -++ -++static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) -++{ -++ chan &= 0xffff; -++ chan >>= 16 - bf->length; -++ return chan << bf->offset; -++} -++ -++static int jzfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, -++ u_int transp, struct fb_info *info) -++{ -++ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -++ unsigned short *ptr, ctmp; -++ -++// print_dbg("regno:%d,RGBt:(%d,%d,%d,%d)\t", regno, red, green, blue, transp); -++ if (regno >= NR_PALETTE) -++ return 1; -++ -++ cfb->palette[regno].red = red ; -++ cfb->palette[regno].green = green; -++ cfb->palette[regno].blue = blue; -++ if (cfb->fb.var.bits_per_pixel <= 16) { -++ red >>= 8; -++ green >>= 8; -++ blue >>= 8; -++ -++ red &= 0xff; -++ green &= 0xff; -++ blue &= 0xff; -++ } -++ switch (cfb->fb.var.bits_per_pixel) { -++ case 1: -++ case 2: -++ case 4: -++ case 8: -++ if (((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_SINGLE) || -++ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) { -++ ctmp = (77L * red + 150L * green + 29L * blue) >> 8; -++ ctmp = ((ctmp >> 3) << 11) | ((ctmp >> 2) << 5) | -++ (ctmp >> 3); -++ } else { -++ /* RGB 565 */ -++ if (((red >> 3) == 0) && ((red >> 2) != 0)) -++ red = 1 << 3; -++ if (((blue >> 3) == 0) && ((blue >> 2) != 0)) -++ blue = 1 << 3; -++ ctmp = ((red >> 3) << 11) -++ | ((green >> 2) << 5) | (blue >> 3); -++ } -++ -++ ptr = (unsigned short *)lcd_palette; -++ ptr = (unsigned short *)(((u32)ptr)|0xa0000000); -++ ptr[regno] = ctmp; -++ -++ break; -++ -++ case 15: -++ if (regno < 16) -++ ((u32 *)cfb->fb.pseudo_palette)[regno] = -++ ((red >> 3) << 10) | -++ ((green >> 3) << 5) | -++ (blue >> 3); -++ break; -++ case 16: -++ if (regno < 16) { -++ ((u32 *)cfb->fb.pseudo_palette)[regno] = -++ ((red >> 3) << 11) | -++ ((green >> 2) << 5) | -++ (blue >> 3); -++ } -++ break; -++ case 18: -++ case 24: -++ case 32: -++ if (regno < 16) -++ ((u32 *)cfb->fb.pseudo_palette)[regno] = -++ (red << 16) | -++ (green << 8) | -++ (blue << 0); -++ -++/* if (regno < 16) { -++ unsigned val; -++ val = chan_to_field(red, &cfb->fb.var.red); -++ val |= chan_to_field(green, &cfb->fb.var.green); -++ val |= chan_to_field(blue, &cfb->fb.var.blue); -++ ((u32 *)cfb->fb.pseudo_palette)[regno] = val; -++ } -++*/ -++ -++ break; -++ } -++ return 0; -++} -++ -++ -++static int jzfb_ioctl (struct fb_info *fb, unsigned int cmd, unsigned long arg ) -++{ -++ int ret = 0; -++ void __user *argp = (void __user *)arg; -++ -++ switch (cmd) { -++ case FBIOSETBACKLIGHT: -++ __lcd_set_backlight_level(arg); /* We support 8 levels here. */ -++ break; -++ case FBIODISPON: -++ __lcd_display_on(); -++ break; -++ case FBIODISPOFF: -++ __lcd_display_off(); -++ break; -++ case FBIOPRINT_REGS: -++ print_regs(); -++ break; -++ case FBIOGETBUFADDRS: -++ if ( copy_to_user(argp, &jz_lcd_buffer_addrs, -++ sizeof(struct jz_lcd_buffer_addrs_t)) ) -++ return -EFAULT; -++ break; -++#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -++ case FBIOROTATE: -++ ret = jzfb_rotate_change(arg); -++ break; -++#endif /* defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) */ -++ default: -++ printk("Warn: Command(%x) not support\n", cmd); -++ ret = -1; -++ break; -++ } -++ return ret; -++ -++} -++ -++/* Use mmap /dev/fb can only get a non-cacheable Virtual Address. */ -++static int jzfb_mmap(struct fb_info *info, struct vm_area_struct *vma) -++{ -++ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -++ unsigned long start; -++ unsigned long off; -++ u32 len; -++ -++ off = vma->vm_pgoff << PAGE_SHIFT; -++ //fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); -++ -++ /* frame buffer memory */ -++ start = cfb->fb.fix.smem_start; -++ len = PAGE_ALIGN((start & ~PAGE_MASK) + cfb->fb.fix.smem_len); -++ start &= PAGE_MASK; -++ -++ if ((vma->vm_end - vma->vm_start + off) > len) -++ return -EINVAL; -++ off += start; -++ -++ vma->vm_pgoff = off >> PAGE_SHIFT; -++ vma->vm_flags |= VM_IO; -++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* Uncacheable */ -++ -++#if 1 -++ pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; -++ pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; /* Uncacheable */ -++// pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; /* Write-Through */ -++#endif -++ -++ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, -++ vma->vm_end - vma->vm_start, -++ vma->vm_page_prot)) { -++ return -EAGAIN; -++ } -++ return 0; -++} -++ -++/* checks var and eventually tweaks it to something supported, -++ * DO NOT MODIFY PAR */ -++static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -++{ -++ print_dbg("jzfb_check_var"); -++ return 0; -++} -++ -++ -++/* -++ * set the video mode according to info->var -++ */ -++static int jzfb_set_par(struct fb_info *info) -++{ -++ print_dbg("jzfb_set_par"); -++ return 0; -++} -++ -++ -++/* -++ * (Un)Blank the display. -++ * Fix me: should we use VESA value? -++ */ -++static int jzfb_blank(int blank_mode, struct fb_info *info) -++{ -++ -++ dprintk("fb_blank %d %p", blank_mode, info); -++ -++ switch (blank_mode) { -++ -++ case FB_BLANK_UNBLANK: -++ //case FB_BLANK_NORMAL: -++ /* Turn on panel */ -++ __lcd_set_ena(); -++ __lcd_display_on(); -++ break; -++ -++ case FB_BLANK_NORMAL: -++ case FB_BLANK_VSYNC_SUSPEND: -++ case FB_BLANK_HSYNC_SUSPEND: -++ case FB_BLANK_POWERDOWN: -++#if 0 -++ /* Turn off panel */ -++ __lcd_set_dis(); -++ __lcd_display_off(); -++#endif -++ break; -++ default: -++ break; -++ -++ } -++ return 0; -++} -++ -++/* -++ * pan display -++ */ -++static int jzfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) -++{ -++ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -++ int dy; -++ -++ if (!var || !cfb) { -++ return -EINVAL; -++ } -++ -++ if (var->xoffset - cfb->fb.var.xoffset) { -++ /* No support for X panning for now! */ -++ return -EINVAL; -++ } -++ -++ dy = var->yoffset - cfb->fb.var.yoffset; -++ print_dbg("var.yoffset: %d", dy); -++ if (dy) { -++ -++ print_dbg("Panning screen of %d lines", dy); -++ -++ lcd_frame_desc0->databuf += (cfb->fb.fix.line_length * dy); -++ /* TODO: Wait for current frame to finished */ -++ } -++ -++ return 0; -++} -++ -++ -++/* use default function cfb_fillrect, cfb_copyarea, cfb_imageblit */ -++static struct fb_ops jzfb_ops = { -++ .owner = THIS_MODULE, -++ .fb_setcolreg = jzfb_setcolreg, -++ .fb_check_var = jzfb_check_var, -++ .fb_set_par = jzfb_set_par, -++ .fb_blank = jzfb_blank, -++ .fb_pan_display = jzfb_pan_display, -++ .fb_fillrect = cfb_fillrect, -++ .fb_copyarea = cfb_copyarea, -++ .fb_imageblit = cfb_imageblit, -++ .fb_mmap = jzfb_mmap, -++ .fb_ioctl = jzfb_ioctl, -++#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -++ .fb_rotate = jzfb_fb_rotate, -++#endif -++}; -++ -++static int jzfb_set_var(struct fb_var_screeninfo *var, int con, -++ struct fb_info *info) -++{ -++ struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info; -++ int chgvar = 0; -++ -++ var->height = jzfb.h ; -++ var->width = jzfb.w ; -++ var->bits_per_pixel = jzfb.bpp; -++ -++ var->vmode = FB_VMODE_NONINTERLACED; -++ var->activate = cfb->fb.var.activate; -++ var->xres = var->width; -++ var->yres = var->height; -++ var->xres_virtual = var->width; -++ var->yres_virtual = var->height; -++ var->xoffset = 0; -++ var->yoffset = 0; -++ var->pixclock = 0; -++ var->left_margin = 0; -++ var->right_margin = 0; -++ var->upper_margin = 0; -++ var->lower_margin = 0; -++ var->hsync_len = 0; -++ var->vsync_len = 0; -++ var->sync = 0; -++ var->activate &= ~FB_ACTIVATE_TEST; -++ -++ /* -++ * CONUPDATE and SMOOTH_XPAN are equal. However, -++ * SMOOTH_XPAN is only used internally by fbcon. -++ */ -++ if (var->vmode & FB_VMODE_CONUPDATE) { -++ var->vmode |= FB_VMODE_YWRAP; -++ var->xoffset = cfb->fb.var.xoffset; -++ var->yoffset = cfb->fb.var.yoffset; -++ } -++ -++ if (var->activate & FB_ACTIVATE_TEST) -++ return 0; -++ -++ if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) -++ return -EINVAL; -++ -++ if (cfb->fb.var.xres != var->xres) -++ chgvar = 1; -++ if (cfb->fb.var.yres != var->yres) -++ chgvar = 1; -++ if (cfb->fb.var.xres_virtual != var->xres_virtual) -++ chgvar = 1; -++ if (cfb->fb.var.yres_virtual != var->yres_virtual) -++ chgvar = 1; -++ if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel) -++ chgvar = 1; -++ -++ var->red.msb_right = 0; -++ var->green.msb_right = 0; -++ var->blue.msb_right = 0; -++ -++ switch(var->bits_per_pixel){ -++ case 1: /* Mono */ -++ cfb->fb.fix.visual = FB_VISUAL_MONO01; -++ cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) / 8; -++ break; -++ case 2: /* Mono */ -++ var->red.offset = 0; -++ var->red.length = 2; -++ var->green.offset = 0; -++ var->green.length = 2; -++ var->blue.offset = 0; -++ var->blue.length = 2; -++ -++ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -++ cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) / 8; -++ break; -++ case 4: /* PSEUDOCOLOUR*/ -++ var->red.offset = 0; -++ var->red.length = 4; -++ var->green.offset = 0; -++ var->green.length = 4; -++ var->blue.offset = 0; -++ var->blue.length = 4; -++ -++ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -++ cfb->fb.fix.line_length = var->xres / 2; -++ break; -++ case 8: /* PSEUDOCOLOUR, 256 */ -++ var->red.offset = 0; -++ var->red.length = 8; -++ var->green.offset = 0; -++ var->green.length = 8; -++ var->blue.offset = 0; -++ var->blue.length = 8; -++ -++ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -++ cfb->fb.fix.line_length = var->xres ; -++ break; -++ case 15: /* DIRECTCOLOUR, 32k */ -++ var->bits_per_pixel = 15; -++ var->red.offset = 10; -++ var->red.length = 5; -++ var->green.offset = 5; -++ var->green.length = 5; -++ var->blue.offset = 0; -++ var->blue.length = 5; -++ -++ cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR; -++ cfb->fb.fix.line_length = var->xres_virtual * 2; -++ break; -++ case 16: /* DIRECTCOLOUR, 64k */ -++ var->bits_per_pixel = 16; -++ var->red.offset = 11; -++ var->red.length = 5; -++ var->green.offset = 5; -++ var->green.length = 6; -++ var->blue.offset = 0; -++ var->blue.length = 5; -++ -++ cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; -++ cfb->fb.fix.line_length = var->xres_virtual * 2; -++ break; -++ case 18: -++ case 24: -++ case 32: -++ /* DIRECTCOLOUR, 16M */ -++ var->bits_per_pixel = 32; -++ -++ var->red.offset = 16; -++ var->red.length = 8; -++ var->green.offset = 8; -++ var->green.length = 8; -++ var->blue.offset = 0; -++ var->blue.length = 8; -++ var->transp.offset = 24; -++ var->transp.length = 8; -++ -++ cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; -++ cfb->fb.fix.line_length = var->xres_virtual * 4; -++ break; -++ -++ default: /* in theory this should never happen */ -++ printk(KERN_WARNING "%s: don't support for %dbpp\n", -++ cfb->fb.fix.id, var->bits_per_pixel); -++ break; -++ } -++ -++ cfb->fb.var = *var; -++ cfb->fb.var.activate &= ~FB_ACTIVATE_ALL; -++ -++ /* -++ * Update the old var. The fbcon drivers still use this. -++ * Once they are using cfb->fb.var, this can be dropped. -++ * --rmk -++ */ -++ //display->var = cfb->fb.var; -++ /* -++ * If we are setting all the virtual consoles, also set the -++ * defaults used to create new consoles. -++ */ -++ fb_set_cmap(&cfb->fb.cmap, &cfb->fb); -++ dprintk("jzfb_set_var: after fb_set_cmap...\n"); -++ -++ return 0; -++} -++ -++static struct lcd_cfb_info * jzfb_alloc_fb_info(void) -++{ -++ struct lcd_cfb_info *cfb; -++ -++ cfb = kmalloc(sizeof(struct lcd_cfb_info) + sizeof(u32) * 16, GFP_KERNEL); -++ -++ if (!cfb) -++ return NULL; -++ -++ jzlcd_info = cfb; -++ -++ memset(cfb, 0, sizeof(struct lcd_cfb_info) ); -++ -++ cfb->currcon = -1; -++ -++ -++ strcpy(cfb->fb.fix.id, "jz-lcd"); -++ cfb->fb.fix.type = FB_TYPE_PACKED_PIXELS; -++ cfb->fb.fix.type_aux = 0; -++ cfb->fb.fix.xpanstep = 1; -++ cfb->fb.fix.ypanstep = 1; -++ cfb->fb.fix.ywrapstep = 0; -++ cfb->fb.fix.accel = FB_ACCEL_NONE; -++ -++ cfb->fb.var.nonstd = 0; -++ cfb->fb.var.activate = FB_ACTIVATE_NOW; -++ cfb->fb.var.height = -1; -++ cfb->fb.var.width = -1; -++ cfb->fb.var.accel_flags = FB_ACCELF_TEXT; -++ -++ cfb->fb.fbops = &jzfb_ops; -++ cfb->fb.flags = FBINFO_FLAG_DEFAULT; -++ -++ cfb->fb.pseudo_palette = (void *)(cfb + 1); -++ -++ switch (jzfb.bpp) { -++ case 1: -++ fb_alloc_cmap(&cfb->fb.cmap, 4, 0); -++ break; -++ case 2: -++ fb_alloc_cmap(&cfb->fb.cmap, 8, 0); -++ break; -++ case 4: -++ fb_alloc_cmap(&cfb->fb.cmap, 32, 0); -++ break; -++ case 8: -++ -++ default: -++ fb_alloc_cmap(&cfb->fb.cmap, 256, 0); -++ break; -++ } -++ dprintk("fb_alloc_cmap,fb.cmap.len:%d....\n", cfb->fb.cmap.len); -++ -++ return cfb; -++} -++ -++/* -++ * Map screen memory -++ */ -++static int jzfb_map_smem(struct lcd_cfb_info *cfb) -++{ -++ struct page * map = NULL; -++ unsigned char *tmp; -++ unsigned int page_shift, needroom, t; -++#if defined(CONFIG_SOC_JZ4740) -++ if (jzfb.bpp == 18 || jzfb.bpp == 24) -++ t = 32; -++ else -++ t = jzfb.bpp; -++#else -++ if (jzfb.bpp == 15) -++ t = 16; -++ else -++ t = jzfb.bpp; -++#endif -++ -++ needroom = ((jzfb.w * t + 7) >> 3) * jzfb.h; -++ for (page_shift = 0; page_shift < 12; page_shift++) -++ if ((PAGE_SIZE << page_shift) >= needroom) -++ break; -++ -++ /* lcd_palette room total 4KB: -++ * 0 -- 512: lcd palette -++ * 1024 -- [1024+16*3]: lcd descripters -++ * [1024+16*3] -- 4096: reserved -++ */ -++ lcd_palette = (unsigned char *)__get_free_pages(GFP_KERNEL, 0); -++ if ((!lcd_palette)) -++ return -ENOMEM; -++ -++ memset((void *)lcd_palette, 0, PAGE_SIZE); -++ map = virt_to_page(lcd_palette); -++ set_bit(PG_reserved, &map->flags); -++ lcd_desc_base = (struct lcd_desc *)(lcd_palette + 1024); -++ -++ jz_lcd_buffer_addrs.fb_num = CONFIG_JZLCD_FRAMEBUFFER_MAX; -++ printk("jzlcd use %d framebuffer:\n", CONFIG_JZLCD_FRAMEBUFFER_MAX); -++ /* alloc frame buffer space */ -++ for ( t = 0; t < CONFIG_JZLCD_FRAMEBUFFER_MAX; t++ ) { -++ lcd_frame[t] = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); -++ if ((!lcd_frame[t])) { -++ printk("no mem for fb[%d]\n", t); -++ return -ENOMEM; -++ } -++// memset((void *)lcd_frame[t], 0, PAGE_SIZE << page_shift); -++ for (tmp=(unsigned char *)lcd_frame[t]; -++ tmp < lcd_frame[t] + (PAGE_SIZE << page_shift); -++ tmp += PAGE_SIZE) { -++ map = virt_to_page(tmp); -++ set_bit(PG_reserved, &map->flags); -++ } -++ jz_lcd_buffer_addrs.fb_phys_addr[t] = virt_to_phys((void *)lcd_frame[t]); -++ printk("jzlcd fb[%d] phys addr =0x%08x\n", -++ t, jz_lcd_buffer_addrs.fb_phys_addr[t]); -++ } -++#if !defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -++ cfb->fb.fix.smem_start = virt_to_phys((void *)lcd_frame[0]); -++ cfb->fb.fix.smem_len = (PAGE_SIZE << page_shift); -++ cfb->fb.screen_base = -++ (unsigned char *)(((unsigned int)lcd_frame[0] & 0x1fffffff) | 0xa0000000); -++#else /* Framebuffer rotate */ -++ lcd_frame_user_fb = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); -++ if ((!lcd_frame_user_fb)) { -++ printk("no mem for fb[%d]\n", t); -++ return -ENOMEM; -++ } -++ memset((void *)lcd_frame_user_fb, 0, PAGE_SIZE << page_shift); -++ for (tmp=(unsigned char *)lcd_frame_user_fb; -++ tmp < lcd_frame_user_fb + (PAGE_SIZE << page_shift); -++ tmp += PAGE_SIZE) { -++ map = virt_to_page(tmp); -++ set_bit(PG_reserved, &map->flags); -++ } -++ -++ printk("Rotate userfb phys addr =0x%08x\n", -++ (unsigned int)virt_to_phys((void *)lcd_frame_user_fb)); -++ cfb->fb.fix.smem_start = virt_to_phys((void *)lcd_frame_user_fb); -++ cfb->fb.fix.smem_len = (PAGE_SIZE << page_shift); -++ cfb->fb.screen_base = (unsigned char *)(((unsigned int)lcd_frame_user_fb & 0x1fffffff) | 0xa0000000); -++ -++#endif /* #if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) */ -++ if (!cfb->fb.screen_base) { -++ printk("%s: unable to map screen memory\n", cfb->fb.fix.id); -++ return -ENOMEM; -++ } -++ -++ return 0; -++} -++ -++static void jzfb_free_fb_info(struct lcd_cfb_info *cfb) -++{ -++ if (cfb) { -++ fb_alloc_cmap(&cfb->fb.cmap, 0, 0); -++ kfree(cfb); -++ } -++} -++ -++static void jzfb_unmap_smem(struct lcd_cfb_info *cfb) -++{ -++ struct page * map = NULL; -++ unsigned char *tmp; -++ unsigned int page_shift, needroom, t; -++#if defined(CONFIG_SOC_JZ4740) -++ if (jzfb.bpp == 18 || jzfb.bpp == 24) -++ t = 32; -++ else -++ t = jzfb.bpp; -++#else -++ if (jzfb.bpp == 15) -++ t = 16; -++ else -++ t = jzfb.bpp; -++#endif -++ needroom = ((jzfb.w * t + 7) >> 3) * jzfb.h; -++ for (page_shift = 0; page_shift < 12; page_shift++) -++ if ((PAGE_SIZE << page_shift) >= needroom) -++ break; -++ -++ if (cfb && cfb->fb.screen_base) { -++ iounmap(cfb->fb.screen_base); -++ cfb->fb.screen_base = NULL; -++ release_mem_region(cfb->fb.fix.smem_start, -++ cfb->fb.fix.smem_len); -++ } -++ -++ if (lcd_palette) { -++ map = virt_to_page(lcd_palette); -++ clear_bit(PG_reserved, &map->flags); -++ free_pages((int)lcd_palette, 0); -++ } -++ -++ for ( t=0; t < CONFIG_JZLCD_FRAMEBUFFER_MAX; t++ ) { -++ if (lcd_frame[t]) { -++ for (tmp=(unsigned char *)lcd_frame[t]; -++ tmp < lcd_frame[t] + (PAGE_SIZE << page_shift); -++ tmp += PAGE_SIZE) { -++ map = virt_to_page(tmp); -++ clear_bit(PG_reserved, &map->flags); -++ } -++ free_pages((int)lcd_frame[t], page_shift); -++ } -++ } -++#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -++ if (lcd_frame_user_fb) { -++ for (tmp=(unsigned char *)lcd_frame_user_fb; -++ tmp < lcd_frame_user_fb + (PAGE_SIZE << page_shift); -++ tmp += PAGE_SIZE) { -++ map = virt_to_page(tmp); -++ clear_bit(PG_reserved, &map->flags); -++ } -++ free_pages((int)lcd_frame_user_fb, page_shift); -++ } -++ -++#endif -++} -++ -++static void lcd_descriptor_init(void) -++{ -++ int i; -++ unsigned int pal_size; -++ unsigned int frm_size, ln_size; -++ unsigned char dual_panel = 0; -++ -++ i = jzfb.bpp; -++#if defined(CONFIG_SOC_JZ4740) -++ if (i == 18 || i == 24) -++ i = 32; -++#else -++ if (i == 15) -++ i = 16; -++#endif -++ frm_size = (jzfb.w*jzfb.h*i)>>3; -++ ln_size = (jzfb.w*i)>>3; -++ -++ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || -++ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) { -++ dual_panel = 1; -++ frm_size >>= 1; -++ } -++ -++ frm_size = frm_size / 4; -++ ln_size = ln_size / 4; -++ -++ switch (jzfb.bpp) { -++ case 1: -++ pal_size = 4; -++ break; -++ case 2: -++ pal_size = 8; -++ break; -++ case 4: -++ pal_size = 32; -++ break; -++ case 8: -++ default: -++ pal_size = 512; -++ } -++ -++ pal_size /= 4; -++ -++ lcd_frame_desc0 = lcd_desc_base + 0; -++ lcd_frame_desc1 = lcd_desc_base + 1; -++ lcd_palette_desc = lcd_desc_base + 2; -++ -++ jz_lcd_buffer_addrs.lcd_desc_phys_addr = (unsigned int)virt_to_phys(lcd_frame_desc0); -++ -++ /* Palette Descriptor */ -++ lcd_palette_desc->next_desc = (int)virt_to_phys(lcd_frame_desc0); -++ lcd_palette_desc->databuf = (int)virt_to_phys((void *)lcd_palette); -++ lcd_palette_desc->frame_id = (unsigned int)0xdeadbeaf; -++ lcd_palette_desc->cmd = pal_size|LCD_CMD_PAL; /* Palette Descriptor */ -++ -++ /* Frame Descriptor 0 */ -++ if (jzfb.bpp <= 8) -++ lcd_frame_desc0->next_desc = (int)virt_to_phys(lcd_palette_desc); -++ else -++ lcd_frame_desc0->next_desc = (int)virt_to_phys(lcd_frame_desc0); -++ lcd_frame_desc0->databuf = virt_to_phys((void *)lcd_frame[0]); -++ lcd_frame_desc0->frame_id = (unsigned int)0xbeafbeaf; -++ lcd_frame_desc0->cmd = LCD_CMD_SOFINT | LCD_CMD_EOFINT | frm_size; -++ dma_cache_wback_inv((unsigned int)(lcd_palette_desc),0x10); -++ dma_cache_wback_inv((unsigned int)(lcd_frame_desc0),0x10); -++ -++ if (!(dual_panel)) -++ return; -++ -++ /* Frame Descriptor 1 */ -++ lcd_frame_desc1->next_desc = (int)virt_to_phys(lcd_frame_desc1); -++ lcd_frame_desc1->databuf = virt_to_phys((void *)(lcd_frame[0] + frm_size * 4)); -++ lcd_frame_desc1->frame_id = (unsigned int)0xdeaddead; -++ lcd_frame_desc1->cmd = LCD_CMD_SOFINT | LCD_CMD_EOFINT | frm_size; -++ dma_cache_wback_inv((unsigned int)(lcd_frame_desc1),0x10); -++} -++ -++static int lcd_hw_init(void) -++{ -++ unsigned int val = 0; -++ unsigned int pclk; -++ unsigned int stnH; -++ int ret = 0; -++ -++ /* Setting Control register */ -++ switch (jzfb.bpp) { -++ case 1: -++ val |= LCD_CTRL_BPP_1; -++ break; -++ case 2: -++ val |= LCD_CTRL_BPP_2; -++ break; -++ case 4: -++ val |= LCD_CTRL_BPP_4; -++ break; -++ case 8: -++ val |= LCD_CTRL_BPP_8; -++ break; -++ case 15: -++ val |= LCD_CTRL_RGB555; -++ case 16: -++ val |= LCD_CTRL_BPP_16; -++ break; -++#if defined(CONFIG_SOC_JZ4740) -++ case 17 ... 32: -++ val |= LCD_CTRL_BPP_18_24; /* target is 4bytes/pixel */ -++ break; -++#endif -++ default: -++ printk("The BPP %d is not supported\n", jzfb.bpp); -++ val |= LCD_CTRL_BPP_16; -++ break; -++ } -++ -++ switch (jzfb.cfg & MODE_MASK) { -++ case MODE_STN_MONO_DUAL: -++ case MODE_STN_COLOR_DUAL: -++ case MODE_STN_MONO_SINGLE: -++ case MODE_STN_COLOR_SINGLE: -++ switch (jzfb.bpp) { -++ case 1: -++ case 2: -++ val |= LCD_CTRL_FRC_2; -++ break; -++ case 4: -++ val |= LCD_CTRL_FRC_4; -++ break; -++ case 8: -++ default: -++ val |= LCD_CTRL_FRC_16; -++ break; -++ } -++ break; -++ } -++ -++ val |= LCD_CTRL_BST_16; /* Burst Length is 16WORD=64Byte */ -++ -++ switch (jzfb.cfg & MODE_MASK) { -++ case MODE_STN_MONO_DUAL: -++ case MODE_STN_COLOR_DUAL: -++ case MODE_STN_MONO_SINGLE: -++ case MODE_STN_COLOR_SINGLE: -++ switch (jzfb.cfg & STN_DAT_PINMASK) { -++#define align2(n) (n)=((((n)+1)>>1)<<1) -++#define align4(n) (n)=((((n)+3)>>2)<<2) -++#define align8(n) (n)=((((n)+7)>>3)<<3) -++ case STN_DAT_PIN1: -++ /* Do not adjust the hori-param value. */ -++ break; -++ case STN_DAT_PIN2: -++ align2(jzfb.hsw); -++ align2(jzfb.elw); -++ align2(jzfb.blw); -++ break; -++ case STN_DAT_PIN4: -++ align4(jzfb.hsw); -++ align4(jzfb.elw); -++ align4(jzfb.blw); -++ break; -++ case STN_DAT_PIN8: -++ align8(jzfb.hsw); -++ align8(jzfb.elw); -++ align8(jzfb.blw); -++ break; -++ } -++ break; -++ } -++ -++ val |= 1 << 26; /* Output FIFO underrun protection */ -++ REG_LCD_CTRL = val; -++ -++ switch (jzfb.cfg & MODE_MASK) { -++ case MODE_STN_MONO_DUAL: -++ case MODE_STN_COLOR_DUAL: -++ case MODE_STN_MONO_SINGLE: -++ case MODE_STN_COLOR_SINGLE: -++ if (((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL) || -++ ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL)) -++ stnH = jzfb.h >> 1; -++ else -++ stnH = jzfb.h; -++ -++ REG_LCD_VSYNC = (0 << 16) | jzfb.vsw; -++ REG_LCD_HSYNC = ((jzfb.blw+jzfb.w) << 16) | (jzfb.blw+jzfb.w+jzfb.hsw); -++ -++ /* Screen setting */ -++ REG_LCD_VAT = ((jzfb.blw + jzfb.w + jzfb.hsw + jzfb.elw) << 16) | (stnH + jzfb.vsw + jzfb.bfw + jzfb.efw); -++ REG_LCD_DAH = (jzfb.blw << 16) | (jzfb.blw + jzfb.w); -++ REG_LCD_DAV = (0 << 16) | (stnH); -++ -++ /* AC BIAs signal */ -++ REG_LCD_PS = (0 << 16) | (stnH+jzfb.vsw+jzfb.efw+jzfb.bfw); -++ -++ break; -++ -++ case MODE_TFT_GEN: -++ case MODE_TFT_SHARP: -++ case MODE_TFT_CASIO: -++ case MODE_TFT_SAMSUNG: -++ case MODE_8BIT_SERIAL_TFT: -++ case MODE_TFT_18BIT: -++ REG_LCD_VSYNC = (0 << 16) | jzfb.vsw; -++#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42) -++ REG_LCD_DAV = (0 << 16) | ( jzfb.h ); -++#else -++ REG_LCD_DAV = ((jzfb.vsw + jzfb.bfw) << 16) | (jzfb.vsw + jzfb.bfw + jzfb.h); -++#endif /*#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42)*/ -++ REG_LCD_VAT = (((jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw)) << 16) | (jzfb.vsw + jzfb.bfw + jzfb.h + jzfb.efw); -++ REG_LCD_HSYNC = (0 << 16) | jzfb.hsw; -++ REG_LCD_DAH = ((jzfb.hsw + jzfb.blw) << 16) | (jzfb.hsw + jzfb.blw + jzfb.w); -++ break; -++ } -++ -++ switch (jzfb.cfg & MODE_MASK) { -++ case MODE_TFT_SAMSUNG: -++ { -++ unsigned int total, tp_s, tp_e, ckv_s, ckv_e; -++ unsigned int rev_s, rev_e, inv_s, inv_e; -++ total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw; -++ tp_s = jzfb.blw + jzfb.w + 1; -++ tp_e = tp_s + 1; -++ ckv_s = tp_s - jz_clocks.pixclk/(1000000000/4100); -++ ckv_e = tp_s + total; -++ rev_s = tp_s - 11; /* -11.5 clk */ -++ rev_e = rev_s + total; -++ inv_s = tp_s; -++ inv_e = inv_s + total; -++ REG_LCD_CLS = (tp_s << 16) | tp_e; -++ REG_LCD_PS = (ckv_s << 16) | ckv_e; -++ REG_LCD_SPL = (rev_s << 16) | rev_e; -++ REG_LCD_REV = (inv_s << 16) | inv_e; -++ jzfb.cfg |= STFT_REVHI | STFT_SPLHI; -++ break; -++ } -++ case MODE_TFT_SHARP: -++ { -++ unsigned int total, cls_s, cls_e, ps_s, ps_e; -++ unsigned int spl_s, spl_e, rev_s, rev_e; -++ total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw; -++#if !defined(CONFIG_JZLCD_INNOLUX_AT080TN42) -++ spl_s = 1; -++ spl_e = spl_s + 1; -++ cls_s = 0; -++ cls_e = total - 60; /* > 4us (pclk = 80ns) */ -++ ps_s = cls_s; -++ ps_e = cls_e; -++ rev_s = total - 40; /* > 3us (pclk = 80ns) */ -++ rev_e = rev_s + total; -++ jzfb.cfg |= STFT_PSHI; -++#else /*#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42)*/ -++ spl_s = total - 5; /* LD */ -++ spl_e = total - 3; -++ cls_s = 32; /* CKV */ -++ cls_e = 145; -++ ps_s = 0; /* OEV */ -++ ps_e = 45; -++ rev_s = 0; /* POL */ -++ rev_e = 0; -++#endif /*#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42)*/ -++ REG_LCD_SPL = (spl_s << 16) | spl_e; -++ REG_LCD_CLS = (cls_s << 16) | cls_e; -++ REG_LCD_PS = (ps_s << 16) | ps_e; -++ REG_LCD_REV = (rev_s << 16) | rev_e; -++ break; -++ } -++ case MODE_TFT_CASIO: -++ break; -++ } -++ -++ /* Configure the LCD panel */ -++ REG_LCD_CFG = jzfb.cfg; -++ -++ /* Timing setting */ -++ __cpm_stop_lcd(); -++ -++ val = jzfb.fclk; /* frame clk */ -++ -++ if ( (jzfb.cfg & MODE_MASK) != MODE_8BIT_SERIAL_TFT) { -++ pclk = val * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) * -++ (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */ -++ } -++ else { -++ /* serial mode: Hsync period = 3*Width_Pixel */ -++ pclk = val * (jzfb.w*3 + jzfb.hsw + jzfb.elw + jzfb.blw) * -++ (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */ -++ } -++ -++ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) || -++ ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL)) -++ pclk = (pclk * 3); -++ -++ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) || -++ ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || -++ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_SINGLE) || -++ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) -++ pclk = pclk >> ((jzfb.cfg & STN_DAT_PINMASK) >> 4); -++ -++ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || -++ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) -++ pclk >>= 1; -++#if defined(CONFIG_SOC_JZ4730) -++ val = __cpm_get_pllout() / pclk; -++ REG_CPM_CFCR2 = val - 1; -++ val = __cpm_get_pllout() / (pclk * 4); -++ val = __cpm_divisor_encode(val); -++ __cpm_set_lcdclk_div(val); -++ REG_CPM_CFCR |= CPM_CFCR_UPE; -++#elif defined(CONFIG_SOC_JZ4740) -++ val = ( __cpm_get_pllout2()) / pclk; -++ val--; -++ if ( val > 0x3ff ) { -++ printk("pixel clock divid is too large, set it to 0x3ff\n"); -++ val = 0x3ff; -++ } -++ __cpm_set_pixdiv(val); -++ -++ val = pclk * 3 ; /* LCDClock > 2.5*Pixclock */ -++ val =__cpm_get_pllout() / val; -++ if ( val > 0x1f ) { -++ printk("lcd clock divide is too large, set it to 0x1f\n"); -++ val = 0x1f; -++ } -++ __cpm_set_ldiv( val ); -++ REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */ -++ -++#else -++ printk("drivers/video/Jzlcd.c, CONFIG_MIPS, please set chip type.\n"); -++#endif /*#ifdef CONFIG_MIPS_JZ4730 */ -++ -++ jz_clocks.pixclk = __cpm_get_pixclk(); -++ jz_clocks.lcdclk = __cpm_get_lcdclk(); -++ printk("LCDC: PixClock:%d LcdClock:%d\n", -++ jz_clocks.pixclk, jz_clocks.lcdclk); -++ -++ __cpm_start_lcd(); -++ udelay(1000); -++ return ret; -++} -++ -++static irqreturn_t lcd_interrupt_handler(int irq, void *dev_id) -++{ -++ unsigned int state; -++ -++ state = REG_LCD_STATE; -++ -++ if (state & LCD_STATE_EOF) /* End of frame */ -++ REG_LCD_STATE = state & ~LCD_STATE_EOF; -++ -++ if (state & LCD_STATE_IFU0) { -++ dprintk("InFiFo0 underrun\n"); -++ REG_LCD_STATE = state & ~LCD_STATE_IFU0; -++ } -++ -++ if (state & LCD_STATE_OFU) { /* Out fifo underrun */ -++ REG_LCD_STATE = state & ~LCD_STATE_OFU; -++ dprintk("Out FiFo underrun.\n"); -++ } -++ return IRQ_HANDLED; -++} -++ -++#ifdef CONFIG_PM -++ -++/* -++ * Suspend the LCDC. -++ */ -++static int jzfb_suspend(void) -++{ -++ __lcd_clr_ena(); /* Quick Disable */ -++ __lcd_display_off(); -++ __cpm_stop_lcd(); -++ -++ return 0; -++} -++ -++/* -++ * Resume the LCDC. -++ */ -++#ifdef CONFIG_SOC_JZ4730 -++static int jzfb_resume(void) -++{ -++ __cpm_start_lcd(); -++ -++ __lcd_display_pin_init(); -++ -++ __lcd_display_on(); -++ -++ lcd_hw_init(); -++ -++ if (jzfb.bpp <= 8) -++ REG_LCD_DA0 = virt_to_phys(lcd_palette_desc); -++ else -++ REG_LCD_DA0 = virt_to_phys(lcd_frame_desc0); -++ -++ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || -++ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) -++ REG_LCD_DA1 = virt_to_phys(lcd_frame_desc1); -++ -++ __lcd_set_ena(); -++ return 0; -++} -++ -++#else -++/* -++ * Resume the LCDC. -++ */ -++static int jzfb_resume(void) -++{ -++ __cpm_start_lcd(); -++ __gpio_set_pin(GPIO_DISP_OFF_N); -++ __lcd_special_on(); -++ __lcd_set_ena(); -++ mdelay(200); -++ __lcd_set_backlight_level(80); -++ -++ return 0; -++} -++#endif /* CONFIG_MIPS_JZ4730 */ -++ -++/* -++ * Power management hook. Note that we won't be called from IRQ context, -++ * unlike the blank functions above, so we may sleep. -++ */ -++static int jzlcd_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -++{ -++ int ret; -++ struct lcd_cfb_info *cfb = pm_dev->data; -++ -++ if (!cfb) return -EINVAL; -++ -++ switch (req) { -++ case PM_SUSPEND: -++ ret = jzfb_suspend(); -++ break; -++ -++ case PM_RESUME: -++ ret = jzfb_resume(); -++ break; -++ -++ default: -++ ret = -EINVAL; -++ break; -++ } -++ return ret; -++} -++#else -++#define jzfb_suspend NULL -++#define jzfb_resume NULL -++#endif /* CONFIG_PM */ -++ -++static int __init jzfb_init(void) -++{ -++ struct lcd_cfb_info *cfb; -++ int err = 0; -++ -++ /* In special mode, we only need init special pin, -++ * as general lcd pin has init in uboot */ -++#if defined(CONFIG_SOC_JZ4740) || defined(CONFIG_SOC_JZ4750) -++ switch (jzfb.cfg & MODE_MASK) { -++ case LCD_CFG_MODE_SPECIAL_TFT_1: -++ case LCD_CFG_MODE_SPECIAL_TFT_2: -++ case LCD_CFG_MODE_SPECIAL_TFT_3: -++ __gpio_as_lcd_special(); -++ break; -++ default: -++ ; -++ } -++#endif -++ __lcd_display_pin_init(); -++ -++ cfb = jzfb_alloc_fb_info(); -++ if (!cfb) -++ goto failed; -++ -++ err = jzfb_map_smem(cfb); -++ if (err) -++ goto failed; -++ -++ jzfb_set_var(&cfb->fb.var, -1, &cfb->fb); -++ -++ lcd_descriptor_init(); -++ -++ err = lcd_hw_init(); -++ if (err) -++ goto failed; -++ -++ if (jzfb.bpp <= 8) -++ REG_LCD_DA0 = virt_to_phys(lcd_palette_desc); -++ else -++ REG_LCD_DA0 = virt_to_phys(lcd_frame_desc0); -++ -++ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || -++ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) -++ REG_LCD_DA1 = virt_to_phys(lcd_frame_desc1); -++ -++ __lcd_set_ena(); -++ -++ if (request_irq(IRQ_LCD, lcd_interrupt_handler, IRQF_DISABLED, -++ "lcd", 0)) { -++ err = -EBUSY; -++ goto failed; -++ } -++ -++ __lcd_enable_ofu_intr(); /* enable OutFifo underrun */ -++// __lcd_enable_ifu0_intr(); /* needn't enable InFifo underrun */ -++ -++#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -++ jzfb_rotate_change(rotate_angle); -++ /* sleep n??? */ -++#endif -++ err = register_framebuffer(&cfb->fb); -++ if (err < 0) { -++ dprintk("jzfb_init(): register framebuffer err.\n"); -++ goto failed; -++ } -++ -++ printk("fb%d: %s frame buffer device, using %dK of video memory\n", -++ cfb->fb.node, cfb->fb.fix.id, cfb->fb.fix.smem_len>>10); -++ -++#ifdef CONFIG_PM -++ /* -++ * Note that the console registers this as well, but we want to -++ * power down the display prior to sleeping. -++ */ -++ cfb->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, jzlcd_pm_callback); -++ if (cfb->pm) -++ cfb->pm->data = cfb; -++#endif -++ -++ __lcd_display_on(); -++ -++ return 0; -++ -++failed: -++ jzfb_unmap_smem(cfb); -++ jzfb_free_fb_info(cfb); -++ -++ return err; -++} -++ -++#if 0 -++static int jzfb_remove(struct device *dev) -++{ -++ struct lcd_cfb_info *cfb = dev_get_drvdata(dev); -++ jzfb_unmap_smem(cfb); -++ jzfb_free_fb_info(cfb); -++ return 0; -++} -++#endif -++ -++#if 0 -++static struct device_driver jzfb_driver = { -++ .name = "jz-lcd", -++ .bus = &platform_bus_type, -++ .probe = jzfb_probe, -++ .remove = jzfb_remove, -++ .suspend = jzfb_suspend, -++ .resume = jzfb_resume, -++}; -++#endif -++ -++static void __exit jzfb_cleanup(void) -++{ -++#if defined(CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT) -++ kthread_stop(jzlcd_info->rotate_daemon_thread); -++#endif -++// driver_unregister(&jzfb_driver); -++// jzfb_remove(); -++} -++ -++module_init(jzfb_init); -++module_exit(jzfb_cleanup); -++ -++MODULE_DESCRIPTION("JzSOC LCD Controller driver"); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/drivers/video/jzlcd.h linux-2.6.24.7/drivers/video/jzlcd.h -+--- linux-2.6.24.7.old/drivers/video/jzlcd.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/video/jzlcd.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,791 @@ -++/* -++ * linux/drivers/video/jzlcd.h -- Ingenic On-Chip LCD frame buffer device -++ * -++ * Copyright (C) 2005-2007, Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ */ -++#ifndef __JZLCD_H__ -++#define __JZLCD_H__ -++ -++#include -++ -++#define NR_PALETTE 256 -++ -++struct lcd_desc{ -++ unsigned int next_desc; /* LCDDAx */ -++ unsigned int databuf; /* LCDSAx */ -++ unsigned int frame_id; /* LCDFIDx */ -++ unsigned int cmd; /* LCDCMDx */ -++}; -++ -++#define MODE_MASK 0x0f -++#define MODE_TFT_GEN 0x00 -++#define MODE_TFT_SHARP 0x01 -++#define MODE_TFT_CASIO 0x02 -++#define MODE_TFT_SAMSUNG 0x03 -++#define MODE_CCIR656_NONINT 0x04 -++#define MODE_CCIR656_INT 0x05 -++#define MODE_STN_COLOR_SINGLE 0x08 -++#define MODE_STN_MONO_SINGLE 0x09 -++#define MODE_STN_COLOR_DUAL 0x0a -++#define MODE_STN_MONO_DUAL 0x0b -++#define MODE_8BIT_SERIAL_TFT 0x0c -++ -++#define MODE_TFT_18BIT (1<<7) -++ -++#define STN_DAT_PIN1 (0x00 << 4) -++#define STN_DAT_PIN2 (0x01 << 4) -++#define STN_DAT_PIN4 (0x02 << 4) -++#define STN_DAT_PIN8 (0x03 << 4) -++#define STN_DAT_PINMASK STN_DAT_PIN8 -++ -++#define STFT_PSHI (1 << 15) -++#define STFT_CLSHI (1 << 14) -++#define STFT_SPLHI (1 << 13) -++#define STFT_REVHI (1 << 12) -++ -++#define SYNC_MASTER (0 << 16) -++#define SYNC_SLAVE (1 << 16) -++ -++#define DE_P (0 << 9) -++#define DE_N (1 << 9) -++ -++#define PCLK_P (0 << 10) -++#define PCLK_N (1 << 10) -++ -++#define HSYNC_P (0 << 11) -++#define HSYNC_N (1 << 11) -++ -++#define VSYNC_P (0 << 8) -++#define VSYNC_N (1 << 8) -++ -++#define DATA_NORMAL (0 << 17) -++#define DATA_INVERSE (1 << 17) -++ -++ -++/* Jz LCDFB supported I/O controls. */ -++#define FBIOSETBACKLIGHT 0x4688 -++#define FBIODISPON 0x4689 -++#define FBIODISPOFF 0x468a -++#define FBIORESET 0x468b -++#define FBIOPRINT_REGS 0x468c -++#define FBIOGETBUFADDRS 0x468d -++#define FBIOROTATE 0x46a0 /* rotated fb */ -++ -++struct jz_lcd_buffer_addrs_t { -++ int fb_num; -++ unsigned int lcd_desc_phys_addr; -++ unsigned int fb_phys_addr[CONFIG_JZLCD_FRAMEBUFFER_MAX]; -++}; -++ -++ -++/* -++ * LCD panel specific definition -++ */ -++#if defined(CONFIG_JZLCD_TRULY_TFTG320240DTSW) -++ -++#if defined(CONFIG_JZ4730_PMP) -++#define LCD_RESET_PIN 63 -++#endif -++ -++#define __lcd_special_on() \ -++do { \ -++ __gpio_set_pin(LCD_RESET_PIN); \ -++ __gpio_as_output(LCD_RESET_PIN); \ -++ __gpio_clear_pin(LCD_RESET_PIN); \ -++ udelay(100); \ -++ __gpio_set_pin(LCD_RESET_PIN); \ -++} while (0) -++ -++#endif /* CONFIG_JZLCD_TRULY_TFTG320240DTSW */ -++ -++#if defined(CONFIG_JZLCD_SAMSUNG_LTV350QVF04) -++ -++#if defined(CONFIG_JZ4730_FPRINT) -++#define PortSDI 60 -++#define PortSCL 61 -++#define PortCS 62 -++#define PortRST 63 -++#define PortSht 64 -++#endif -++ -++#if defined(CONFIG_JZ4730_GPS) -++#define PortSDI 74 -++#define PortSCL 72 -++#define PortCS 73 -++#define PortRST 60 -++#define PortSht 59 -++#endif -++ -++#ifndef PortSDI -++#define PortSDI 0 -++#endif -++#ifndef PortSCL -++#define PortSCL 0 -++#endif -++#ifndef PortCS -++#define PortCS 0 -++#endif -++#ifndef PortRST -++#define PortRST 0 -++#endif -++#ifndef PortSht -++#define PortSht 0 -++#endif -++ -++#define __lcd_special_pin_init() \ -++do { \ -++ __gpio_as_output(PortSDI); /* SDI */\ -++ __gpio_as_output(PortSCL); /* SCL */ \ -++ __gpio_as_output(PortCS); /* CS */ \ -++ __gpio_as_output(PortRST); /* Reset */ \ -++ __gpio_as_output(PortSht); /* Shut Down # */ \ -++ __gpio_set_pin(PortCS); \ -++ __gpio_set_pin(PortSCL); \ -++ __gpio_set_pin(PortSDI); \ -++} while (0) -++ -++#define __spi_out(val) \ -++do { \ -++ int __i__; \ -++ unsigned int _t_ = (val); \ -++ __gpio_clear_pin(PortCS); \ -++ udelay(25); \ -++ for (__i__ = 0; __i__ < 24; __i__++ ) { \ -++ __gpio_clear_pin(PortSCL); \ -++ if (_t_ & 0x800000) \ -++ __gpio_set_pin(PortSDI); \ -++ else \ -++ __gpio_clear_pin(PortSDI); \ -++ _t_ <<= 1; \ -++ udelay(25); \ -++ __gpio_set_pin(PortSCL); \ -++ udelay(25); \ -++ } \ -++ __gpio_set_pin(PortCS); \ -++ udelay(25); \ -++ __gpio_set_pin(PortSDI); \ -++ udelay(25); \ -++ __gpio_set_pin(PortSCL); \ -++} while (0) -++ -++#define __spi_id_op_data(rs, rw, val) \ -++ __spi_out((0x1d<<18)|((rs)<<17)|((rw)<<16)|(val)) -++ -++#define __spi_write_reg(reg, val) \ -++do { \ -++ __spi_id_op_data(0, 0, (reg)); \ -++ __spi_id_op_data(1, 0, (val)); \ -++} while (0) -++ -++#define __lcd_special_on() \ -++do { \ -++ __gpio_set_pin(PortSht); \ -++ __gpio_clear_pin(PortRST); \ -++ mdelay(10); \ -++ __gpio_set_pin(PortRST); \ -++ mdelay(1); \ -++ __spi_write_reg(0x09, 0); \ -++ mdelay(10); \ -++ __spi_write_reg(0x09, 0x4000); \ -++ __spi_write_reg(0x0a, 0x2000); \ -++ mdelay(40); \ -++ __spi_write_reg(0x09, 0x4055); \ -++ mdelay(50); \ -++ __spi_write_reg(0x01, 0x409d); \ -++ __spi_write_reg(0x02, 0x0204); \ -++ __spi_write_reg(0x03, 0x0100); \ -++ __spi_write_reg(0x04, 0x3000); \ -++ __spi_write_reg(0x05, 0x4003); \ -++ __spi_write_reg(0x06, 0x000a); \ -++ __spi_write_reg(0x07, 0x0021); \ -++ __spi_write_reg(0x08, 0x0c00); \ -++ __spi_write_reg(0x10, 0x0103); \ -++ __spi_write_reg(0x11, 0x0301); \ -++ __spi_write_reg(0x12, 0x1f0f); \ -++ __spi_write_reg(0x13, 0x1f0f); \ -++ __spi_write_reg(0x14, 0x0707); \ -++ __spi_write_reg(0x15, 0x0307); \ -++ __spi_write_reg(0x16, 0x0707); \ -++ __spi_write_reg(0x17, 0x0000); \ -++ __spi_write_reg(0x18, 0x0004); \ -++ __spi_write_reg(0x19, 0x0000); \ -++ mdelay(60); \ -++ __spi_write_reg(0x09, 0x4a55); \ -++ __spi_write_reg(0x05, 0x5003); \ -++} while (0) -++ -++#define __lcd_special_off() \ -++do { \ -++ __spi_write_reg(0x09, 0x4055); \ -++ __spi_write_reg(0x05, 0x4003); \ -++ __spi_write_reg(0x0a, 0x0000); \ -++ mdelay(10); \ -++ __spi_write_reg(0x09, 0x4000); \ -++ __gpio_clear_pin(PortSht); \ -++} while (0) -++ -++#endif /* CONFIG_JZLCD_SAMSUNG_LTV350QVF04 */ -++ -++#if defined(CONFIG_JZLCD_AUO_A030FL01_V1) -++#if defined(CONFIG_JZ4740_PAVO) /* board pavo */ -++ #define SPEN (32*1+18) /*LCD_CS*/ -++ #define SPCK (32*1+17) /*LCD_SCL*/ -++ #define SPDA (32*2+12) /*LCD_SDA*/ -++ #define LCD_RET (32*2+23) /*use for lcd reset*/ -++#elif defined(CONFIG_JZ4740_LYRA) /* board lyra */ -++ #define SPEN (32*3+19) //LCD_CS -++ #define SPCK (32*3+18) //LCD_SCL -++ #define SPDA (32*3+20) //LCD_SDA -++ #define LCD_RET (32*3+31) //use for lcd reset -++#else -++#error "driver/video/Jzlcd.h, please define SPI pins on your board." -++#endif -++ -++#define __spi_write_reg(reg, val) \ -++ do { \ -++ unsigned char no; \ -++ unsigned short value; \ -++ unsigned char a=0; \ -++ unsigned char b=0; \ -++ __gpio_as_output(SPEN); /* use SPDA */ \ -++ __gpio_as_output(SPCK); /* use SPCK */ \ -++ __gpio_as_output(SPDA); /* use SPDA */ \ -++ a=reg; \ -++ b=val; \ -++ __gpio_set_pin(SPEN); \ -++ __gpio_clear_pin(SPCK); \ -++ udelay(50); \ -++ __gpio_clear_pin(SPDA); \ -++ __gpio_clear_pin(SPEN); \ -++ udelay(50); \ -++ value=((a<<8)|(b&0xFF)); \ -++ for(no=0;no<16;no++) \ -++ { \ -++ if((value&0x8000)==0x8000){ \ -++ __gpio_set_pin(SPDA);} \ -++ else{ \ -++ __gpio_clear_pin(SPDA); } \ -++ udelay(400); \ -++ __gpio_set_pin(SPCK); \ -++ value=(value<<1); \ -++ udelay(50); \ -++ __gpio_clear_pin(SPCK); \ -++ } \ -++ __gpio_set_pin(SPEN); \ -++ udelay(400); \ -++ } while (0) -++#define __spi_read_reg(reg,val) \ -++ do{ \ -++ unsigned char no; \ -++ unsigned short value; \ -++ __gpio_as_output(SPEN); /* use SPDA */ \ -++ __gpio_as_output(SPCK); /* use SPCK */ \ -++ __gpio_as_output(SPDA); /* use SPDA */ \ -++ value = ((reg << 0) | (1 << 7)); \ -++ val = 0; \ -++ __gpio_as_output(SPDA); \ -++ __gpio_set_pin(SPEN); \ -++ __gpio_set_pin(SPCK); \ -++ udelay(1); \ -++ __gpio_clear_pin(SPDA); \ -++ __gpio_clear_pin(SPEN); \ -++ udelay(1); \ -++ for (no = 0; no < 16; no++ ) { \ -++ __gpio_clear_pin(SPCK); \ -++ udelay(1); \ -++ if(no < 8) \ -++ { \ -++ if (value & 0x80) /* send data */ \ -++ __gpio_set_pin(SPDA); \ -++ else \ -++ __gpio_clear_pin(SPDA); \ -++ value = (value << 1); \ -++ udelay(1); \ -++ __gpio_set_pin(SPCK); \ -++ udelay(1); \ -++ } \ -++ else \ -++ { \ -++ __gpio_as_input(SPDA); \ -++ udelay(1); \ -++ __gpio_set_pin(SPCK); \ -++ udelay(1); \ -++ val = (val << 1); \ -++ val |= __gpio_get_pin(SPDA); \ -++ udelay(1); \ -++ } \ -++ udelay(400); \ -++ } \ -++ __gpio_as_output(SPDA); \ -++ __gpio_set_pin(SPEN); \ -++ udelay(400); \ -++ } while(0) -++ -++#define __lcd_special_pin_init() \ -++ do { \ -++ __gpio_as_output(SPEN); /* use SPDA */ \ -++ __gpio_as_output(SPCK); /* use SPCK */ \ -++ __gpio_as_output(SPDA); /* use SPDA */ \ -++ __gpio_as_output(LCD_RET); \ -++ udelay(50); \ -++ __gpio_clear_pin(LCD_RET); \ -++ udelay(100); \ -++ __gpio_set_pin(LCD_RET); \ -++ } while (0) -++#define __lcd_special_on() \ -++ do { \ -++ udelay(50); \ -++ __gpio_clear_pin(LCD_RET); \ -++ udelay(100); \ -++ __gpio_set_pin(LCD_RET); \ -++ __spi_write_reg(0x0D, 0x44); \ -++ __spi_write_reg(0x0D, 0x4D); \ -++ __spi_write_reg(0x0B, 0x06); \ -++ __spi_write_reg(0x40, 0xC0); \ -++ __spi_write_reg(0x42, 0x43); \ -++ __spi_write_reg(0x44, 0x28); \ -++ __spi_write_reg(0x0D, 0x4F); \ -++} while (0) -++ -++ #define __lcd_special_off() \ -++ do { \ -++ __spi_write_reg(0x04, 0x4C); \ -++ } while (0) -++ -++#endif /* CONFIG_JZLCD_AUO_A030FL01_V1 */ -++ -++//#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) -++#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) || defined(CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL) -++ -++#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) /* board pmp */ -++#define MODE 0xcd /* 24bit parellel RGB */ -++#endif -++#if defined(CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL) -++#define MODE 0xc9 /* 8bit serial RGB */ -++#endif -++ -++#if defined(CONFIG_JZ4730_PMP) -++ #define SPEN 60 //LCD_SPL -++ #define SPCK 61 //LCD_CLS -++ #define SPDA 62 //LCD_PS -++ #define LCD_RET 63 //LCD_REV //use for lcd reset -++#elif defined(CONFIG_JZ4740_LEO) /* board leo */ -++ #define SPEN (32*1+18) //LCD_SPL -++ #define SPCK (32*1+17) //LCD_CLS -++ #define SPDA (32*2+22) //LCD_PS -++ #define LCD_RET (32*2+23) //LCD_REV //use for lcd reset -++#elif defined(CONFIG_JZ4740_PAVO) /* board pavo */ -++ #define SPEN (32*1+18) //LCD_SPL -++ #define SPCK (32*1+17) //LCD_CLS -++ #define SPDA (32*2+12) //LCD_D12 -++ #define LCD_RET (32*2+23) //LCD_REV, GPC23 -++#if 0 /*old driver*/ -++ #define SPEN (32*1+18) //LCD_SPL -++ #define SPCK (32*1+17) //LCD_CLS -++ #define SPDA (32*2+12) //LCD_D12 -++ #define LCD_RET (32*3+27) //PWM4 //use for lcd reset -++#endif -++#else -++#error "driver/video/Jzlcd.h, please define SPI pins on your board." -++#endif -++ -++ #define __spi_write_reg1(reg, val) \ -++ do { \ -++ unsigned char no;\ -++ unsigned short value;\ -++ unsigned char a=0;\ -++ unsigned char b=0;\ -++ a=reg;\ -++ b=val;\ -++ __gpio_set_pin(SPEN);\ -++ __gpio_set_pin(SPCK);\ -++ __gpio_clear_pin(SPDA);\ -++ __gpio_clear_pin(SPEN);\ -++ udelay(25);\ -++ value=((a<<8)|(b&0xFF));\ -++ for(no=0;no<16;no++)\ -++ {\ -++ __gpio_clear_pin(SPCK);\ -++ if((value&0x8000)==0x8000)\ -++ __gpio_set_pin(SPDA);\ -++ else\ -++ __gpio_clear_pin(SPDA);\ -++ udelay(25);\ -++ __gpio_set_pin(SPCK);\ -++ value=(value<<1); \ -++ udelay(25);\ -++ }\ -++ __gpio_set_pin(SPEN);\ -++ udelay(100);\ -++ } while (0) -++ -++ #define __spi_write_reg(reg, val) \ -++ do {\ -++ __spi_write_reg1((reg<<2|2), val); \ -++ udelay(100); \ -++ }while(0) -++ -++ #define __lcd_special_pin_init() \ -++ do { \ -++ __gpio_as_output(SPEN); /* use SPDA */\ -++ __gpio_as_output(SPCK); /* use SPCK */\ -++ __gpio_as_output(SPDA); /* use SPDA */\ -++ __gpio_as_output(LCD_RET);\ -++ udelay(50);\ -++ __gpio_clear_pin(LCD_RET);\ -++ mdelay(150);\ -++ __gpio_set_pin(LCD_RET);\ -++ } while (0) -++ -++ #define __lcd_special_on() \ -++ do { \ -++ udelay(50);\ -++ __gpio_clear_pin(LCD_RET);\ -++ mdelay(150);\ -++ __gpio_set_pin(LCD_RET);\ -++ mdelay(10);\ -++ __spi_write_reg(0x00, 0x03); \ -++ __spi_write_reg(0x01, 0x40); \ -++ __spi_write_reg(0x02, 0x11); \ -++ __spi_write_reg(0x03, MODE); /* mode */ \ -++ __spi_write_reg(0x04, 0x32); \ -++ __spi_write_reg(0x05, 0x0e); \ -++ __spi_write_reg(0x07, 0x03); \ -++ __spi_write_reg(0x08, 0x08); \ -++ __spi_write_reg(0x09, 0x32); \ -++ __spi_write_reg(0x0A, 0x88); \ -++ __spi_write_reg(0x0B, 0xc6); \ -++ __spi_write_reg(0x0C, 0x20); \ -++ __spi_write_reg(0x0D, 0x20); \ -++ } while (0) //reg 0x0a is control the display direction:DB0->horizontal level DB1->vertical level -++ -++/* __spi_write_reg(0x02, 0x03); \ -++ __spi_write_reg(0x06, 0x40); \ -++ __spi_write_reg(0x0a, 0x11); \ -++ __spi_write_reg(0x0e, 0xcd); \ -++ __spi_write_reg(0x12, 0x32); \ -++ __spi_write_reg(0x16, 0x0e); \ -++ __spi_write_reg(0x1e, 0x03); \ -++ __spi_write_reg(0x22, 0x08); \ -++ __spi_write_reg(0x26, 0x40); \ -++ __spi_write_reg(0x2a, 0x88); \ -++ __spi_write_reg(0x2e, 0x88); \ -++ __spi_write_reg(0x32, 0x20); \ -++ __spi_write_reg(0x36, 0x20); \ -++*/ -++// } while (0) //reg 0x0a is control the display direction:DB0->horizontal level DB1->vertical level -++ -++ #define __lcd_special_off() \ -++ do { \ -++ __spi_write_reg(0x00, 0x03); \ -++ } while (0) -++ -++#endif /* CONFIG_JZLCD_FOXCONN_PT035TN01 or CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL */ -++ -++ -++#ifndef __lcd_special_pin_init -++#define __lcd_special_pin_init() -++#endif -++#ifndef __lcd_special_on -++#define __lcd_special_on() -++#endif -++#ifndef __lcd_special_off -++#define __lcd_special_off() -++#endif -++ -++ -++/* -++ * Platform specific definition -++ */ -++ -++#if defined(CONFIG_JZ4730_GPS) -++ -++#define __lcd_set_backlight_level(n) \ -++do { \ -++ ; \ -++} while (0) -++ -++#define __lcd_display_pin_init() \ -++do { \ -++ __lcd_special_pin_init(); \ -++ __gpio_as_output(94); /* PWM0 pin */ \ -++ __gpio_as_output(95); /* PWM1 pin */ \ -++} while (0) -++ -++#define __lcd_display_on() \ -++do { \ -++ __lcd_special_on(); \ -++ __gpio_set_pin(94); /* PWM0 pin */ \ -++ __gpio_set_pin(95); /* PWM1 pin */ \ -++ __lcd_set_backlight_level(8); \ -++} while (0) -++ -++#define __lcd_display_off() \ -++do { \ -++ __lcd_special_off(); \ -++} while (0) -++ -++#endif /* CONFIG_JZ4730_GPS */ -++ -++#if defined(CONFIG_JZ4730_FPRINT) -++ -++#define __lcd_set_backlight_level(n) \ -++do { \ -++ REG_PWM_DUT(0) = n; \ -++ REG_PWM_PER(0) = 7; \ -++ REG_PWM_CTR(0) = 0x81; \ -++} while (0) -++ -++#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) -++ -++#define __lcd_display_pin_init() \ -++do { \ -++ __lcd_special_pin_init();\ -++ __gpio_as_pwm();\ -++ __lcd_set_backlight_level(8);\ -++} while (0) -++ -++#define __lcd_display_on() \ -++do { \ -++ __lcd_set_backlight_level(8); \ -++ __lcd_special_on();\ -++} while (0) -++ -++#define __lcd_display_off() \ -++do { \ -++ __lcd_set_backlight_level(0); \ -++ __lcd_special_off();\ -++} while (0) -++ -++#else -++ -++#define __lcd_display_pin_init() \ -++do { \ -++ __gpio_as_output(GPIO_DISP_OFF_N); \ -++ __gpio_as_pwm(); \ -++ __lcd_set_backlight_level(8); \ -++} while (0) -++ -++#define __lcd_display_on() \ -++do { \ -++ __lcd_set_backlight_level(8); \ -++ __gpio_set_pin(GPIO_DISP_OFF_N); \ -++} while (0) -++ -++#define __lcd_display_off() \ -++do { \ -++ __lcd_set_backlight_level(0); \ -++ __gpio_clear_pin(GPIO_DISP_OFF_N); \ -++} while (0) -++#endif -++ -++#endif /* CONFIG_JZ4730_FPRINT */ -++ -++#if defined(CONFIG_JZ4730_LIBRA) -++ -++#define __lcd_set_backlight_level(n) \ -++do { \ -++} while (0) -++ -++#define __lcd_display_pin_init() \ -++do { \ -++ __lcd_special_pin_init(); \ -++ __gpio_clear_pin(100); \ -++ __gpio_as_output(100); \ -++ __gpio_as_output(94); \ -++ __gpio_as_output(95); \ -++ __lcd_set_backlight_level(8); \ -++} while (0) -++ -++#define __lcd_display_on() \ -++do { \ -++ __lcd_special_on(); \ -++ __gpio_set_pin(100); \ -++ __gpio_set_pin(94); \ -++ __gpio_set_pin(95); \ -++} while (0) -++ -++#define __lcd_display_off() \ -++do { \ -++ __lcd_special_off(); \ -++ __gpio_clear_pin(100); \ -++ __gpio_clear_pin(94); \ -++ __gpio_clear_pin(95); \ -++} while (0) -++ -++#endif /* CONFIG_JZ4730_LIBRA */ -++ -++#if defined(CONFIG_JZ4730_PMP) -++ -++#define __lcd_set_backlight_level(n) \ -++do { \ -++ REG_PWM_DUT(0) = n; \ -++ REG_PWM_PER(0) = 7; \ -++ REG_PWM_CTR(0) = 0x81; \ -++} while (0) -++ -++#define __lcd_display_pin_init() \ -++do { \ -++ __gpio_as_output(GPIO_DISP_OFF_N); \ -++ __gpio_as_pwm(); \ -++ __lcd_set_backlight_level(10); \ -++ __lcd_special_pin_init(); \ -++} while (0) -++ -++#define __lcd_display_on() \ -++do { \ -++ __lcd_special_on(); \ -++ __lcd_set_backlight_level(8); \ -++ __gpio_set_pin(GPIO_DISP_OFF_N); \ -++} while (0) -++ -++#define __lcd_display_off() \ -++do { \ -++ __lcd_special_off(); \ -++ __lcd_set_backlight_level(0); \ -++ __gpio_clear_pin(GPIO_DISP_OFF_N); \ -++} while (0) -++ -++#endif /* CONFIG_JZ4730_PMP */ -++ -++/*#if defined(CONFIG_JZ4740_LEO) || defined(CONFIG_JZ4740_PAVO)*/ -++#if defined(CONFIG_SOC_JZ4740) -++#if defined(CONFIG_JZ4740_PAVO) || defined(CONFIG_JZ4740_LYRA) -++#define GPIO_PWM 123 /* GP_D27 */ -++#define PWM_CHN 4 /* pwm channel */ -++#define PWM_FULL 101 -++/* 100 level: 0,1,...,100 */ -++#define __lcd_set_backlight_level(n)\ -++do { \ -++__gpio_as_output(32*3+27); \ -++__gpio_set_pin(32*3+27); \ -++} while (0) -++ -++#define __lcd_close_backlight() \ -++do { \ -++__gpio_as_output(GPIO_PWM); \ -++__gpio_clear_pin(GPIO_PWM); \ -++} while (0) -++ -++#elif defined(CONFIG_JZ4720_VIRGO) -++#define GPIO_PWM 119 /* GP_D23 */ -++#define PWM_CHN 0 /* pwm channel */ -++#define PWM_FULL 101 -++/* 100 level: 0,1,...,100 */ -++/*#define __lcd_set_backlight_level(n) \ -++do { \ -++ __gpio_as_pwm(0); \ -++ __tcu_disable_pwm_output(PWM_CHN); \ -++ __tcu_stop_counter(PWM_CHN); \ -++ __tcu_init_pwm_output_high(PWM_CHN); \ -++ __tcu_set_pwm_output_shutdown_abrupt(PWM_CHN); \ -++ __tcu_select_clk_div1(PWM_CHN); \ -++ __tcu_mask_full_match_irq(PWM_CHN); \ -++ __tcu_mask_half_match_irq(PWM_CHN); \ -++ __tcu_set_count(PWM_CHN,0); \ -++ __tcu_set_full_data(PWM_CHN,__cpm_get_extalclk()/1000); \ -++ __tcu_set_half_data(PWM_CHN,__cpm_get_extalclk()/1000*n/100); \ -++ __tcu_enable_pwm_output(PWM_CHN); \ -++ __tcu_select_extalclk(PWM_CHN); \ -++ __tcu_start_counter(PWM_CHN); \ -++} while (0) -++*/ -++ -++#define __lcd_set_backlight_level(n) \ -++do { \ -++ __gpio_as_output(GPIO_PWM); \ -++ __gpio_set_pin(GPIO_PWM); \ -++} while (0) -++ -++#define __lcd_close_backlight() \ -++do { \ -++__gpio_as_output(GPIO_PWM); \ -++__gpio_clear_pin(GPIO_PWM); \ -++} while (0) -++ -++#else -++#define __lcd_set_backlight_level(n) -++#define __lcd_close_backlight() -++ -++#endif /* #if defined(CONFIG_MIPS_JZ4740_PAVO) */ -++ -++#define __lcd_display_pin_init() \ -++do { \ -++ __gpio_as_output(GPIO_DISP_OFF_N); \ -++ __cpm_start_tcu(); \ -++ __lcd_special_pin_init(); \ -++} while (0) -++/* __lcd_set_backlight_level(100); \*/ -++#define __lcd_display_on() \ -++do { \ -++ __gpio_set_pin(GPIO_DISP_OFF_N); \ -++ __lcd_special_on(); \ -++ __lcd_set_backlight_level(80); \ -++} while (0) -++ -++#define __lcd_display_off() \ -++do { \ -++ __lcd_special_off(); \ -++ __lcd_close_backlight(); \ -++ __gpio_clear_pin(GPIO_DISP_OFF_N); \ -++} while (0) -++ -++#endif /* CONFIG_MIPS_JZ4740_LEO */ -++ -++#if defined(CONFIG_JZLCD_MSTN_240x128) -++ -++#if 0 /* The final version does not use software emulation of VCOM. */ -++ -++#define GPIO_VSYNC 59 -++#define GPIO_VCOM 90 -++ -++#define REG_VCOM REG_GPIO_GPDR((GPIO_VCOM>>5)) -++#define VCOM_BIT (1 << (GPIO_VCOM & 0x1f)) -++static unsigned int vcom_static; -++static void vsync_irq(int irq, void *dev_id, struct pt_regs *reg) -++{ -++ vcom_static = REG_VCOM; -++ vcom_static ^= VCOM_BIT; -++ REG_VCOM = vcom_static; -++} -++ -++#define __lcd_display_pin_init() \ -++ __gpio_as_irq_rise_edge(GPIO_VSYNC); \ -++ __gpio_as_output(GPIO_VCOM); \ -++ { \ -++ static int inited = 0; \ -++ if (!inited) { \ -++ inited = 1; \ -++ if (request_irq(IRQ_GPIO_0 + GPIO_VSYNC, vsync_irq, SA_INTERRUPT, \ -++ "vsync", 0)) { \ -++ err = -EBUSY; \ -++ goto failed; \ -++ }}} -++ -++#endif -++ -++/* We uses AC BIAs pin to generate VCOM signal, so above code should be removed. -++ */ -++#endif -++/***************************************************************************** -++ * LCD display pin dummy macros -++ *****************************************************************************/ -++#ifndef __lcd_display_pin_init -++#define __lcd_display_pin_init() -++#endif -++#ifndef __lcd_display_on -++#define __lcd_display_on() -++#endif -++#ifndef __lcd_display_off -++#define __lcd_display_off() -++#endif -++#ifndef __lcd_set_backlight_level -++#define __lcd_set_backlight_level(n) -++#endif -++ -++#endif /* __JZLCD_H__ */ -+diff -urN linux-2.6.24.7.old/drivers/watchdog/Kconfig linux-2.6.24.7/drivers/watchdog/Kconfig -+--- linux-2.6.24.7.old/drivers/watchdog/Kconfig 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/watchdog/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -45,6 +45,15 @@ -+ -+ # Architecture Independent -+ -++config JZ_WDT -++ bool 'JzSoC On-Chip watchdog' -++ help -++ Watchdog timer embedded into JZSOC chips. This will reboot your -++ system when the timeout is reached. -++ -++ To compile this driver as a module, choose M here: the -++ module will be called jz_wdt. -++ -+ config SOFT_WATCHDOG -+ tristate "Software watchdog" -+ help -+diff -urN linux-2.6.24.7.old/drivers/watchdog/Makefile linux-2.6.24.7/drivers/watchdog/Makefile -+--- linux-2.6.24.7.old/drivers/watchdog/Makefile 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/drivers/watchdog/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -10,6 +10,9 @@ -+ # that also fails then you can fall back to the software watchdog -+ # to give you some cover. -+ -++# JZ-watchdog timer -++obj-$(CONFIG_JZ_WDT) += jz_wdt.o -++ -+ # ISA-based Watchdog Cards -+ obj-$(CONFIG_PCWATCHDOG) += pcwd.o -+ obj-$(CONFIG_MIXCOMWD) += mixcomwd.o -+diff -urN linux-2.6.24.7.old/drivers/watchdog/jz_wdt.c linux-2.6.24.7/drivers/watchdog/jz_wdt.c -+--- linux-2.6.24.7.old/drivers/watchdog/jz_wdt.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/drivers/watchdog/jz_wdt.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,203 @@ -++/* -++ * linux/drivers/char/jz_wdt.c -++ * -++ * Watchdog driver for the Ingenic JzSOC -++ * -++ * Author: Wei Jianli -++ * -++ * 2005 (c) Ingenic Semiconductor. This file is licensed under the -++ * terms of the GNU General Public License version 2. This program is -++ * licensed "as is" without any warranty of any kind, whether express -++ * or implied. -++ */ -++ -++#include -++//#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#define TIMER_MARGIN 60 /* (secs) Default is 1 minute */ -++ -++static unsigned int timer_margin = TIMER_MARGIN; /* in seconds */ -++static unsigned int timer_rate; -++static unsigned int pre_margin; -++static unsigned long jz_wdt_users = 0; -++ -++#ifdef MODULE -++MODULE_PARM(timer_margin, "i"); -++#endif -++ -++static void -++jz_wdt_ping(void) -++{ -++ printk("jz_wdt_ping\n"); -++ /* reload counter with (new) margin */ -++#ifdef CONFIG_SOC_JZ4730 -++ pre_margin = 0xffffffff - timer_rate * timer_margin; -++ __wdt_set_count(pre_margin); -++#endif -++#ifdef CONFIG_SOC_JZ4740 -++ pre_margin = timer_rate * timer_margin; -++ __wdt_set_count(0); -++ __wdt_set_data(pre_margin); -++#endif -++} -++ -++/* -++ * Allow only one person to hold it open -++ */ -++ -++static int -++jz_wdt_open(struct inode *inode, struct file *file) -++{ -++ if (test_and_set_bit(1, &jz_wdt_users)) -++ return -EBUSY; -++ -++ printk("jz_wdt_open\n"); -++#ifdef CONFIG_SOC_JZ4730 -++ if (REG_CPM_OCR & CPM_OCR_EXT_RTC_CLK) -++ timer_rate = 32768; -++ else -++ timer_rate = JZ_EXTAL/128; -++#endif -++ -++#ifdef CONFIG_SOC_JZ4740 -++ /* Initialize the wdt clocks */ -++ __wdt_select_rtcclk(); -++ __wdt_select_clk_div1024(); -++ __tcu_start_wdt_clock(); -++ timer_rate = 32; /* 32768 / 1024 */ -++#endif -++ -++ jz_wdt_ping(); -++ __wdt_start(); -++ -++ return 0; -++} -++ -++static int -++jz_wdt_release(struct inode *inode, struct file *file) -++{ -++ /* -++ * Shut off the timer. -++ * Lock it in if it's a module and we defined ...NOWAYOUT -++ */ -++ jz_wdt_ping(); -++#ifndef CONFIG_WATCHDOG_NOWAYOUT -++ /* SW can't stop wdt once it was started */ -++#endif -++ jz_wdt_users = 0; -++ return 0; -++} -++ -++static ssize_t -++jz_wdt_write(struct file *file, const char *data, size_t len, loff_t * ppos) -++{ -++ /* Can't seek (pwrite) on this device */ -++ if (ppos != &file->f_pos) -++ return -ESPIPE; -++ -++ printk("jz_wdt_write\n"); -++ -++ /* Refresh counter */ -++ if (len) { -++ jz_wdt_ping(); -++ return 1; -++ } -++ return 0; -++} -++ -++static int -++jz_wdt_ioctl(struct inode *inode, struct file *file, -++ unsigned int cmd, unsigned long arg) -++{ -++ int new_margin; -++ static struct watchdog_info ident = { -++ .identity = "JzSOC Watchdog", -++ .options = WDIOF_SETTIMEOUT, -++ .firmware_version = 0, -++ }; -++ -++ switch (cmd) { -++ default: -++ return -ENOIOCTLCMD; -++ case WDIOC_GETSUPPORT: -++ return copy_to_user((struct watchdog_info *) arg, &ident, -++ sizeof (ident)); -++ case WDIOC_GETSTATUS: -++ return put_user(0, (int *) arg); -++ case WDIOC_GETBOOTSTATUS: -++#ifdef CONFIG_SOC_JZ4730 -++ return put_user(REG_CPM_RSTR, (int *) arg); -++#endif -++#ifdef CONFIG_SOC_JZ4740 -++ return put_user(REG_RTC_HWRSR, (int *) arg); -++#endif -++ case WDIOC_KEEPALIVE: -++ jz_wdt_ping(); -++ return 0; -++ case WDIOC_SETTIMEOUT: -++ if (get_user(new_margin, (int *) arg)) -++ return -EFAULT; -++ if (new_margin < 1) -++ return -EINVAL; -++ timer_margin = new_margin; -++ jz_wdt_ping(); -++ /* Fall */ -++ case WDIOC_GETTIMEOUT: -++ return put_user(timer_margin, (int *) arg); -++ } -++} -++ -++static struct file_operations jz_wdt_fops = { -++ .owner = THIS_MODULE, -++ .write = jz_wdt_write, -++ .ioctl = jz_wdt_ioctl, -++ .open = jz_wdt_open, -++ .release = jz_wdt_release, -++}; -++ -++static struct miscdevice jz_wdt_miscdev = { -++ .minor = WATCHDOG_MINOR, -++ .name = "jz_wdt", -++ .fops = &jz_wdt_fops -++}; -++ -++static int __init -++jz_wdt_init(void) -++{ -++ int ret; -++ -++ ret = misc_register(&jz_wdt_miscdev); -++ -++ if (ret) -++ return ret; -++ -++ printk("JzSOC Watchdog Timer: timer margin %d sec\n", timer_margin); -++ -++ return 0; -++} -++ -++static void __exit -++jz_wdt_exit(void) -++{ -++ misc_deregister(&jz_wdt_miscdev); -++} -++ -++module_init(jz_wdt_init); -++module_exit(jz_wdt_exit); -++ -++MODULE_AUTHOR("Wei Jianli"); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/fs/Kconfig linux-2.6.24.7/fs/Kconfig -+--- linux-2.6.24.7.old/fs/Kconfig 2009-04-12 18:05:07.000000000 +0200 -++++ linux-2.6.24.7/fs/Kconfig 2009-04-12 18:27:23.000000000 +0200 -+@@ -1389,6 +1389,9 @@ -+ -+ endchoice -+ -++# UBIFS File system configuration -++source "fs/ubifs/Kconfig" -++ -+ config CRAMFS -+ tristate "Compressed ROM file system support (cramfs)" -+ depends on BLOCK -+diff -urN linux-2.6.24.7.old/fs/Kconfig.orig linux-2.6.24.7/fs/Kconfig.orig -+--- linux-2.6.24.7.old/fs/Kconfig.orig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/Kconfig.orig 2009-04-12 18:01:55.000000000 +0200 -+@@ -0,0 +1,2202 @@ -++# -++# File system configuration -++# -++ -++menu "File systems" -++ -++if BLOCK -++ -++config EXT2_FS -++ tristate "Second extended fs support" -++ help -++ Ext2 is a standard Linux file system for hard disks. -++ -++ To compile this file system support as a module, choose M here: the -++ module will be called ext2. -++ -++ If unsure, say Y. -++ -++config EXT2_FS_XATTR -++ bool "Ext2 extended attributes" -++ depends on EXT2_FS -++ help -++ Extended attributes are name:value pairs associated with inodes by -++ the kernel or by users (see the attr(5) manual page, or visit -++ for details). -++ -++ If unsure, say N. -++ -++config EXT2_FS_POSIX_ACL -++ bool "Ext2 POSIX Access Control Lists" -++ depends on EXT2_FS_XATTR -++ select FS_POSIX_ACL -++ help -++ Posix Access Control Lists (ACLs) support permissions for users and -++ groups beyond the owner/group/world scheme. -++ -++ To learn more about Access Control Lists, visit the Posix ACLs for -++ Linux website . -++ -++ If you don't know what Access Control Lists are, say N -++ -++config EXT2_FS_SECURITY -++ bool "Ext2 Security Labels" -++ depends on EXT2_FS_XATTR -++ help -++ Security labels support alternative access control models -++ implemented by security modules like SELinux. This option -++ enables an extended attribute handler for file security -++ labels in the ext2 filesystem. -++ -++ If you are not using a security module that requires using -++ extended attributes for file security labels, say N. -++ -++config EXT2_FS_XIP -++ bool "Ext2 execute in place support" -++ depends on EXT2_FS && MMU -++ help -++ Execute in place can be used on memory-backed block devices. If you -++ enable this option, you can select to mount block devices which are -++ capable of this feature without using the page cache. -++ -++ If you do not use a block device that is capable of using this, -++ or if unsure, say N. -++ -++config FS_XIP -++# execute in place -++ bool -++ depends on EXT2_FS_XIP -++ default y -++ -++config EXT3_FS -++ tristate "Ext3 journalling file system support" -++ select JBD -++ help -++ This is the journalling version of the Second extended file system -++ (often called ext3), the de facto standard Linux file system -++ (method to organize files on a storage device) for hard disks. -++ -++ The journalling code included in this driver means you do not have -++ to run e2fsck (file system checker) on your file systems after a -++ crash. The journal keeps track of any changes that were being made -++ at the time the system crashed, and can ensure that your file system -++ is consistent without the need for a lengthy check. -++ -++ Other than adding the journal to the file system, the on-disk format -++ of ext3 is identical to ext2. It is possible to freely switch -++ between using the ext3 driver and the ext2 driver, as long as the -++ file system has been cleanly unmounted, or e2fsck is run on the file -++ system. -++ -++ To add a journal on an existing ext2 file system or change the -++ behavior of ext3 file systems, you can use the tune2fs utility ("man -++ tune2fs"). To modify attributes of files and directories on ext3 -++ file systems, use chattr ("man chattr"). You need to be using -++ e2fsprogs version 1.20 or later in order to create ext3 journals -++ (available at ). -++ -++ To compile this file system support as a module, choose M here: the -++ module will be called ext3. -++ -++config EXT3_FS_XATTR -++ bool "Ext3 extended attributes" -++ depends on EXT3_FS -++ default y -++ help -++ Extended attributes are name:value pairs associated with inodes by -++ the kernel or by users (see the attr(5) manual page, or visit -++ for details). -++ -++ If unsure, say N. -++ -++ You need this for POSIX ACL support on ext3. -++ -++config EXT3_FS_POSIX_ACL -++ bool "Ext3 POSIX Access Control Lists" -++ depends on EXT3_FS_XATTR -++ select FS_POSIX_ACL -++ help -++ Posix Access Control Lists (ACLs) support permissions for users and -++ groups beyond the owner/group/world scheme. -++ -++ To learn more about Access Control Lists, visit the Posix ACLs for -++ Linux website . -++ -++ If you don't know what Access Control Lists are, say N -++ -++config EXT3_FS_SECURITY -++ bool "Ext3 Security Labels" -++ depends on EXT3_FS_XATTR -++ help -++ Security labels support alternative access control models -++ implemented by security modules like SELinux. This option -++ enables an extended attribute handler for file security -++ labels in the ext3 filesystem. -++ -++ If you are not using a security module that requires using -++ extended attributes for file security labels, say N. -++ -++config EXT4DEV_FS -++ tristate "Ext4dev/ext4 extended fs support development (EXPERIMENTAL)" -++ depends on EXPERIMENTAL -++ select JBD2 -++ select CRC16 -++ help -++ Ext4dev is a predecessor filesystem of the next generation -++ extended fs ext4, based on ext3 filesystem code. It will be -++ renamed ext4 fs later, once ext4dev is mature and stabilized. -++ -++ Unlike the change from ext2 filesystem to ext3 filesystem, -++ the on-disk format of ext4dev is not the same as ext3 any more: -++ it is based on extent maps and it supports 48-bit physical block -++ numbers. These combined on-disk format changes will allow -++ ext4dev/ext4 to handle more than 16 TB filesystem volumes -- -++ a hard limit that ext3 cannot overcome without changing the -++ on-disk format. -++ -++ Other than extent maps and 48-bit block numbers, ext4dev also is -++ likely to have other new features such as persistent preallocation, -++ high resolution time stamps, and larger file support etc. These -++ features will be added to ext4dev gradually. -++ -++ To compile this file system support as a module, choose M here. The -++ module will be called ext4dev. -++ -++ If unsure, say N. -++ -++config EXT4DEV_FS_XATTR -++ bool "Ext4dev extended attributes" -++ depends on EXT4DEV_FS -++ default y -++ help -++ Extended attributes are name:value pairs associated with inodes by -++ the kernel or by users (see the attr(5) manual page, or visit -++ for details). -++ -++ If unsure, say N. -++ -++ You need this for POSIX ACL support on ext4dev/ext4. -++ -++config EXT4DEV_FS_POSIX_ACL -++ bool "Ext4dev POSIX Access Control Lists" -++ depends on EXT4DEV_FS_XATTR -++ select FS_POSIX_ACL -++ help -++ POSIX Access Control Lists (ACLs) support permissions for users and -++ groups beyond the owner/group/world scheme. -++ -++ To learn more about Access Control Lists, visit the POSIX ACLs for -++ Linux website . -++ -++ If you don't know what Access Control Lists are, say N -++ -++config EXT4DEV_FS_SECURITY -++ bool "Ext4dev Security Labels" -++ depends on EXT4DEV_FS_XATTR -++ help -++ Security labels support alternative access control models -++ implemented by security modules like SELinux. This option -++ enables an extended attribute handler for file security -++ labels in the ext4dev/ext4 filesystem. -++ -++ If you are not using a security module that requires using -++ extended attributes for file security labels, say N. -++ -++config JBD -++ tristate -++ help -++ This is a generic journalling layer for block devices. It is -++ currently used by the ext3 and OCFS2 file systems, but it could -++ also be used to add journal support to other file systems or block -++ devices such as RAID or LVM. -++ -++ If you are using the ext3 or OCFS2 file systems, you need to -++ say Y here. If you are not using ext3 OCFS2 then you will probably -++ want to say N. -++ -++ To compile this device as a module, choose M here: the module will be -++ called jbd. If you are compiling ext3 or OCFS2 into the kernel, -++ you cannot compile this code as a module. -++ -++config JBD_DEBUG -++ bool "JBD (ext3) debugging support" -++ depends on JBD && DEBUG_FS -++ help -++ If you are using the ext3 journaled file system (or potentially any -++ other file system/device using JBD), this option allows you to -++ enable debugging output while the system is running, in order to -++ help track down any problems you are having. By default the -++ debugging output will be turned off. -++ -++ If you select Y here, then you will be able to turn on debugging -++ with "echo N > /sys/kernel/debug/jbd/jbd-debug", where N is a -++ number between 1 and 5, the higher the number, the more debugging -++ output is generated. To turn debugging off again, do -++ "echo 0 > /sys/kernel/debug/jbd/jbd-debug". -++ -++config JBD2 -++ tristate -++ help -++ This is a generic journaling layer for block devices that support -++ both 32-bit and 64-bit block numbers. It is currently used by -++ the ext4dev/ext4 filesystem, but it could also be used to add -++ journal support to other file systems or block devices such -++ as RAID or LVM. -++ -++ If you are using ext4dev/ext4, you need to say Y here. If you are not -++ using ext4dev/ext4 then you will probably want to say N. -++ -++ To compile this device as a module, choose M here. The module will be -++ called jbd2. If you are compiling ext4dev/ext4 into the kernel, -++ you cannot compile this code as a module. -++ -++config JBD2_DEBUG -++ bool "JBD2 (ext4dev/ext4) debugging support" -++ depends on JBD2 && DEBUG_FS -++ help -++ If you are using the ext4dev/ext4 journaled file system (or -++ potentially any other filesystem/device using JBD2), this option -++ allows you to enable debugging output while the system is running, -++ in order to help track down any problems you are having. -++ By default, the debugging output will be turned off. -++ -++ If you select Y here, then you will be able to turn on debugging -++ with "echo N > /sys/kernel/debug/jbd2/jbd2-debug", where N is a -++ number between 1 and 5. The higher the number, the more debugging -++ output is generated. To turn debugging off again, do -++ "echo 0 > /sys/kernel/debug/jbd2/jbd2-debug". -++ -++config FS_MBCACHE -++# Meta block cache for Extended Attributes (ext2/ext3/ext4) -++ tristate -++ depends on EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4DEV_FS_XATTR -++ default y if EXT2_FS=y || EXT3_FS=y || EXT4DEV_FS=y -++ default m if EXT2_FS=m || EXT3_FS=m || EXT4DEV_FS=m -++ -++config REISERFS_FS -++ tristate "Reiserfs support" -++ help -++ Stores not just filenames but the files themselves in a balanced -++ tree. Uses journalling. -++ -++ Balanced trees are more efficient than traditional file system -++ architectural foundations. -++ -++ In general, ReiserFS is as fast as ext2, but is very efficient with -++ large directories and small files. Additional patches are needed -++ for NFS and quotas, please see for links. -++ -++ It is more easily extended to have features currently found in -++ database and keyword search systems than block allocation based file -++ systems are. The next version will be so extended, and will support -++ plugins consistent with our motto ``It takes more than a license to -++ make source code open.'' -++ -++ Read to learn more about reiserfs. -++ -++ Sponsored by Threshold Networks, Emusic.com, and Bigstorage.com. -++ -++ If you like it, you can pay us to add new features to it that you -++ need, buy a support contract, or pay us to port it to another OS. -++ -++config REISERFS_CHECK -++ bool "Enable reiserfs debug mode" -++ depends on REISERFS_FS -++ help -++ If you set this to Y, then ReiserFS will perform every check it can -++ possibly imagine of its internal consistency throughout its -++ operation. It will also go substantially slower. More than once we -++ have forgotten that this was on, and then gone despondent over the -++ latest benchmarks.:-) Use of this option allows our team to go all -++ out in checking for consistency when debugging without fear of its -++ effect on end users. If you are on the verge of sending in a bug -++ report, say Y and you might get a useful error message. Almost -++ everyone should say N. -++ -++config REISERFS_PROC_INFO -++ bool "Stats in /proc/fs/reiserfs" -++ depends on REISERFS_FS && PROC_FS -++ help -++ Create under /proc/fs/reiserfs a hierarchy of files, displaying -++ various ReiserFS statistics and internal data at the expense of -++ making your kernel or module slightly larger (+8 KB). This also -++ increases the amount of kernel memory required for each mount. -++ Almost everyone but ReiserFS developers and people fine-tuning -++ reiserfs or tracing problems should say N. -++ -++config REISERFS_FS_XATTR -++ bool "ReiserFS extended attributes" -++ depends on REISERFS_FS -++ help -++ Extended attributes are name:value pairs associated with inodes by -++ the kernel or by users (see the attr(5) manual page, or visit -++ for details). -++ -++ If unsure, say N. -++ -++config REISERFS_FS_POSIX_ACL -++ bool "ReiserFS POSIX Access Control Lists" -++ depends on REISERFS_FS_XATTR -++ select FS_POSIX_ACL -++ help -++ Posix Access Control Lists (ACLs) support permissions for users and -++ groups beyond the owner/group/world scheme. -++ -++ To learn more about Access Control Lists, visit the Posix ACLs for -++ Linux website . -++ -++ If you don't know what Access Control Lists are, say N -++ -++config REISERFS_FS_SECURITY -++ bool "ReiserFS Security Labels" -++ depends on REISERFS_FS_XATTR -++ help -++ Security labels support alternative access control models -++ implemented by security modules like SELinux. This option -++ enables an extended attribute handler for file security -++ labels in the ReiserFS filesystem. -++ -++ If you are not using a security module that requires using -++ extended attributes for file security labels, say N. -++ -++config JFS_FS -++ tristate "JFS filesystem support" -++ select NLS -++ help -++ This is a port of IBM's Journaled Filesystem . More information is -++ available in the file . -++ -++ If you do not intend to use the JFS filesystem, say N. -++ -++config JFS_POSIX_ACL -++ bool "JFS POSIX Access Control Lists" -++ depends on JFS_FS -++ select FS_POSIX_ACL -++ help -++ Posix Access Control Lists (ACLs) support permissions for users and -++ groups beyond the owner/group/world scheme. -++ -++ To learn more about Access Control Lists, visit the Posix ACLs for -++ Linux website . -++ -++ If you don't know what Access Control Lists are, say N -++ -++config JFS_SECURITY -++ bool "JFS Security Labels" -++ depends on JFS_FS -++ help -++ Security labels support alternative access control models -++ implemented by security modules like SELinux. This option -++ enables an extended attribute handler for file security -++ labels in the jfs filesystem. -++ -++ If you are not using a security module that requires using -++ extended attributes for file security labels, say N. -++ -++config JFS_DEBUG -++ bool "JFS debugging" -++ depends on JFS_FS -++ help -++ If you are experiencing any problems with the JFS filesystem, say -++ Y here. This will result in additional debugging messages to be -++ written to the system log. Under normal circumstances, this -++ results in very little overhead. -++ -++config JFS_STATISTICS -++ bool "JFS statistics" -++ depends on JFS_FS -++ help -++ Enabling this option will cause statistics from the JFS file system -++ to be made available to the user in the /proc/fs/jfs/ directory. -++ -++config FS_POSIX_ACL -++# Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs) -++# -++# NOTE: you can implement Posix ACLs without these helpers (XFS does). -++# Never use this symbol for ifdefs. -++# -++ bool -++ default n -++ -++source "fs/xfs/Kconfig" -++source "fs/gfs2/Kconfig" -++source "fs/yaffs2/Kconfig" -++ -++config OCFS2_FS -++ tristate "OCFS2 file system support" -++ depends on NET && SYSFS -++ select CONFIGFS_FS -++ select JBD -++ select CRC32 -++ help -++ OCFS2 is a general purpose extent based shared disk cluster file -++ system with many similarities to ext3. It supports 64 bit inode -++ numbers, and has automatically extending metadata groups which may -++ also make it attractive for non-clustered use. -++ -++ You'll want to install the ocfs2-tools package in order to at least -++ get "mount.ocfs2". -++ -++ Project web page: http://oss.oracle.com/projects/ocfs2 -++ Tools web page: http://oss.oracle.com/projects/ocfs2-tools -++ OCFS2 mailing lists: http://oss.oracle.com/projects/ocfs2/mailman/ -++ -++ Note: Features which OCFS2 does not support yet: -++ - extended attributes -++ - quotas -++ - cluster aware flock -++ - Directory change notification (F_NOTIFY) -++ - Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease) -++ - POSIX ACLs -++ - readpages / writepages (not user visible) -++ -++config OCFS2_DEBUG_MASKLOG -++ bool "OCFS2 logging support" -++ depends on OCFS2_FS -++ default y -++ help -++ The ocfs2 filesystem has an extensive logging system. The system -++ allows selection of events to log via files in /sys/o2cb/logmask/. -++ This option will enlarge your kernel, but it allows debugging of -++ ocfs2 filesystem issues. -++ -++config OCFS2_DEBUG_FS -++ bool "OCFS2 expensive checks" -++ depends on OCFS2_FS -++ default n -++ help -++ This option will enable expensive consistency checks. Enable -++ this option for debugging only as it is likely to decrease -++ performance of the filesystem. -++ -++config MINI_FO -++ tristate "Mini fanout overlay filesystem" -++ -++config MINIX_FS -++ tristate "Minix fs support" -++ help -++ Minix is a simple operating system used in many classes about OS's. -++ The minix file system (method to organize files on a hard disk -++ partition or a floppy disk) was the original file system for Linux, -++ but has been superseded by the second extended file system ext2fs. -++ You don't want to use the minix file system on your hard disk -++ because of certain built-in restrictions, but it is sometimes found -++ on older Linux floppy disks. This option will enlarge your kernel -++ by about 28 KB. If unsure, say N. -++ -++ To compile this file system support as a module, choose M here: the -++ module will be called minix. Note that the file system of your root -++ partition (the one containing the directory /) cannot be compiled as -++ a module. -++ -++config ROMFS_FS -++ tristate "ROM file system support" -++ ---help--- -++ This is a very small read-only file system mainly intended for -++ initial ram disks of installation disks, but it could be used for -++ other read-only media as well. Read -++ for details. -++ -++ To compile this file system support as a module, choose M here: the -++ module will be called romfs. Note that the file system of your -++ root partition (the one containing the directory /) cannot be a -++ module. -++ -++ If you don't know whether you need it, then you don't need it: -++ answer N. -++ -++endif -++ -++config INOTIFY -++ bool "Inotify file change notification support" -++ default y -++ ---help--- -++ Say Y here to enable inotify support. Inotify is a file change -++ notification system and a replacement for dnotify. Inotify fixes -++ numerous shortcomings in dnotify and introduces several new features -++ including multiple file events, one-shot support, and unmount -++ notification. -++ -++ For more information, see -++ -++ If unsure, say Y. -++ -++config INOTIFY_USER -++ bool "Inotify support for userspace" -++ depends on INOTIFY -++ default y -++ ---help--- -++ Say Y here to enable inotify support for userspace, including the -++ associated system calls. Inotify allows monitoring of both files and -++ directories via a single open fd. Events are read from the file -++ descriptor, which is also select()- and poll()-able. -++ -++ For more information, see -++ -++ If unsure, say Y. -++ -++config QUOTA -++ bool "Quota support" -++ help -++ If you say Y here, you will be able to set per user limits for disk -++ usage (also called disk quotas). Currently, it works for the -++ ext2, ext3, and reiserfs file system. ext3 also supports journalled -++ quotas for which you don't need to run quotacheck(8) after an unclean -++ shutdown. -++ For further details, read the Quota mini-HOWTO, available from -++ , or the documentation provided -++ with the quota tools. Probably the quota support is only useful for -++ multi user systems. If unsure, say N. -++ -++config QUOTA_NETLINK_INTERFACE -++ bool "Report quota messages through netlink interface" -++ depends on QUOTA && NET -++ help -++ If you say Y here, quota warnings (about exceeding softlimit, reaching -++ hardlimit, etc.) will be reported through netlink interface. If unsure, -++ say Y. -++ -++config PRINT_QUOTA_WARNING -++ bool "Print quota warnings to console (OBSOLETE)" -++ depends on QUOTA -++ default y -++ help -++ If you say Y here, quota warnings (about exceeding softlimit, reaching -++ hardlimit, etc.) will be printed to the process' controlling terminal. -++ Note that this behavior is currently deprecated and may go away in -++ future. Please use notification via netlink socket instead. -++ -++config QFMT_V1 -++ tristate "Old quota format support" -++ depends on QUOTA -++ help -++ This quota format was (is) used by kernels earlier than 2.4.22. If -++ you have quota working and you don't want to convert to new quota -++ format say Y here. -++ -++config QFMT_V2 -++ tristate "Quota format v2 support" -++ depends on QUOTA -++ help -++ This quota format allows using quotas with 32-bit UIDs/GIDs. If you -++ need this functionality say Y here. -++ -++config QUOTACTL -++ bool -++ depends on XFS_QUOTA || QUOTA -++ default y -++ -++config DNOTIFY -++ bool "Dnotify support" -++ default y -++ help -++ Dnotify is a directory-based per-fd file change notification system -++ that uses signals to communicate events to user-space. There exist -++ superior alternatives, but some applications may still rely on -++ dnotify. -++ -++ If unsure, say Y. -++ -++config AUTOFS_FS -++ tristate "Kernel automounter support" -++ help -++ The automounter is a tool to automatically mount remote file systems -++ on demand. This implementation is partially kernel-based to reduce -++ overhead in the already-mounted case; this is unlike the BSD -++ automounter (amd), which is a pure user space daemon. -++ -++ To use the automounter you need the user-space tools from the autofs -++ package; you can find the location in . -++ You also want to answer Y to "NFS file system support", below. -++ -++ If you want to use the newer version of the automounter with more -++ features, say N here and say Y to "Kernel automounter v4 support", -++ below. -++ -++ To compile this support as a module, choose M here: the module will be -++ called autofs. -++ -++ If you are not a part of a fairly large, distributed network, you -++ probably do not need an automounter, and can say N here. -++ -++config AUTOFS4_FS -++ tristate "Kernel automounter version 4 support (also supports v3)" -++ help -++ The automounter is a tool to automatically mount remote file systems -++ on demand. This implementation is partially kernel-based to reduce -++ overhead in the already-mounted case; this is unlike the BSD -++ automounter (amd), which is a pure user space daemon. -++ -++ To use the automounter you need the user-space tools from -++ ; you also -++ want to answer Y to "NFS file system support", below. -++ -++ To compile this support as a module, choose M here: the module will be -++ called autofs4. You will need to add "alias autofs autofs4" to your -++ modules configuration file. -++ -++ If you are not a part of a fairly large, distributed network or -++ don't have a laptop which needs to dynamically reconfigure to the -++ local network, you probably do not need an automounter, and can say -++ N here. -++ -++config FUSE_FS -++ tristate "Filesystem in Userspace support" -++ help -++ With FUSE it is possible to implement a fully functional filesystem -++ in a userspace program. -++ -++ There's also companion library: libfuse. This library along with -++ utilities is available from the FUSE homepage: -++ -++ -++ See for more information. -++ See for needed library/utility version. -++ -++ If you want to develop a userspace FS, or if you want to use -++ a filesystem based on FUSE, answer Y or M. -++ -++config GENERIC_ACL -++ bool -++ select FS_POSIX_ACL -++ -++if BLOCK -++menu "CD-ROM/DVD Filesystems" -++ -++config ISO9660_FS -++ tristate "ISO 9660 CDROM file system support" -++ help -++ This is the standard file system used on CD-ROMs. It was previously -++ known as "High Sierra File System" and is called "hsfs" on other -++ Unix systems. The so-called Rock-Ridge extensions which allow for -++ long Unix filenames and symbolic links are also supported by this -++ driver. If you have a CD-ROM drive and want to do more with it than -++ just listen to audio CDs and watch its LEDs, say Y (and read -++ and the CD-ROM-HOWTO, -++ available from ), thereby -++ enlarging your kernel by about 27 KB; otherwise say N. -++ -++ To compile this file system support as a module, choose M here: the -++ module will be called isofs. -++ -++config JOLIET -++ bool "Microsoft Joliet CDROM extensions" -++ depends on ISO9660_FS -++ select NLS -++ help -++ Joliet is a Microsoft extension for the ISO 9660 CD-ROM file system -++ which allows for long filenames in unicode format (unicode is the -++ new 16 bit character code, successor to ASCII, which encodes the -++ characters of almost all languages of the world; see -++ for more information). Say Y here if you -++ want to be able to read Joliet CD-ROMs under Linux. -++ -++config ZISOFS -++ bool "Transparent decompression extension" -++ depends on ISO9660_FS -++ select ZLIB_INFLATE -++ help -++ This is a Linux-specific extension to RockRidge which lets you store -++ data in compressed form on a CD-ROM and have it transparently -++ decompressed when the CD-ROM is accessed. See -++ for the tools -++ necessary to create such a filesystem. Say Y here if you want to be -++ able to read such compressed CD-ROMs. -++ -++config UDF_FS -++ tristate "UDF file system support" -++ help -++ This is the new file system used on some CD-ROMs and DVDs. Say Y if -++ you intend to mount DVD discs or CDRW's written in packet mode, or -++ if written to by other UDF utilities, such as DirectCD. -++ Please read . -++ -++ To compile this file system support as a module, choose M here: the -++ module will be called udf. -++ -++ If unsure, say N. -++ -++config UDF_NLS -++ bool -++ default y -++ depends on (UDF_FS=m && NLS) || (UDF_FS=y && NLS=y) -++ -++endmenu -++endif -++ -++if BLOCK -++menu "DOS/FAT/NT Filesystems" -++ -++config FAT_FS -++ tristate -++ select NLS -++ help -++ If you want to use one of the FAT-based file systems (the MS-DOS and -++ VFAT (Windows 95) file systems), then you must say Y or M here -++ to include FAT support. You will then be able to mount partitions or -++ diskettes with FAT-based file systems and transparently access the -++ files on them, i.e. MSDOS files will look and behave just like all -++ other Unix files. -++ -++ This FAT support is not a file system in itself, it only provides -++ the foundation for the other file systems. You will have to say Y or -++ M to at least one of "MSDOS fs support" or "VFAT fs support" in -++ order to make use of it. -++ -++ Another way to read and write MSDOS floppies and hard drive -++ partitions from within Linux (but not transparently) is with the -++ mtools ("man mtools") program suite. You don't need to say Y here in -++ order to do that. -++ -++ If you need to move large files on floppies between a DOS and a -++ Linux box, say Y here, mount the floppy under Linux with an MSDOS -++ file system and use GNU tar's M option. GNU tar is a program -++ available for Unix and DOS ("man tar" or "info tar"). -++ -++ The FAT support will enlarge your kernel by about 37 KB. If unsure, -++ say Y. -++ -++ To compile this as a module, choose M here: the module will be called -++ fat. Note that if you compile the FAT support as a module, you -++ cannot compile any of the FAT-based file systems into the kernel -++ -- they will have to be modules as well. -++ -++config MSDOS_FS -++ tristate "MSDOS fs support" -++ select FAT_FS -++ help -++ This allows you to mount MSDOS partitions of your hard drive (unless -++ they are compressed; to access compressed MSDOS partitions under -++ Linux, you can either use the DOS emulator DOSEMU, described in the -++ DOSEMU-HOWTO, available from -++ , or try dmsdosfs in -++ . If you -++ intend to use dosemu with a non-compressed MSDOS partition, say Y -++ here) and MSDOS floppies. This means that file access becomes -++ transparent, i.e. the MSDOS files look and behave just like all -++ other Unix files. -++ -++ If you have Windows 95 or Windows NT installed on your MSDOS -++ partitions, you should use the VFAT file system (say Y to "VFAT fs -++ support" below), or you will not be able to see the long filenames -++ generated by Windows 95 / Windows NT. -++ -++ This option will enlarge your kernel by about 7 KB. If unsure, -++ answer Y. This will only work if you said Y to "DOS FAT fs support" -++ as well. To compile this as a module, choose M here: the module will -++ be called msdos. -++ -++config VFAT_FS -++ tristate "VFAT (Windows-95) fs support" -++ select FAT_FS -++ help -++ This option provides support for normal Windows file systems with -++ long filenames. That includes non-compressed FAT-based file systems -++ used by Windows 95, Windows 98, Windows NT 4.0, and the Unix -++ programs from the mtools package. -++ -++ The VFAT support enlarges your kernel by about 10 KB and it only -++ works if you said Y to the "DOS FAT fs support" above. Please read -++ the file for details. If -++ unsure, say Y. -++ -++ To compile this as a module, choose M here: the module will be called -++ vfat. -++ -++config FAT_DEFAULT_CODEPAGE -++ int "Default codepage for FAT" -++ depends on MSDOS_FS || VFAT_FS -++ default 437 -++ help -++ This option should be set to the codepage of your FAT filesystems. -++ It can be overridden with the "codepage" mount option. -++ See for more information. -++ -++config FAT_DEFAULT_IOCHARSET -++ string "Default iocharset for FAT" -++ depends on VFAT_FS -++ default "iso8859-1" -++ help -++ Set this to the default input/output character set you'd -++ like FAT to use. It should probably match the character set -++ that most of your FAT filesystems use, and can be overridden -++ with the "iocharset" mount option for FAT filesystems. -++ Note that "utf8" is not recommended for FAT filesystems. -++ If unsure, you shouldn't set "utf8" here. -++ See for more information. -++ -++config NTFS_FS -++ tristate "NTFS file system support" -++ select NLS -++ help -++ NTFS is the file system of Microsoft Windows NT, 2000, XP and 2003. -++ -++ Saying Y or M here enables read support. There is partial, but -++ safe, write support available. For write support you must also -++ say Y to "NTFS write support" below. -++ -++ There are also a number of user-space tools available, called -++ ntfsprogs. These include ntfsundelete and ntfsresize, that work -++ without NTFS support enabled in the kernel. -++ -++ This is a rewrite from scratch of Linux NTFS support and replaced -++ the old NTFS code starting with Linux 2.5.11. A backport to -++ the Linux 2.4 kernel series is separately available as a patch -++ from the project web site. -++ -++ For more information see -++ and . -++ -++ To compile this file system support as a module, choose M here: the -++ module will be called ntfs. -++ -++ If you are not using Windows NT, 2000, XP or 2003 in addition to -++ Linux on your computer it is safe to say N. -++ -++config NTFS_DEBUG -++ bool "NTFS debugging support" -++ depends on NTFS_FS -++ help -++ If you are experiencing any problems with the NTFS file system, say -++ Y here. This will result in additional consistency checks to be -++ performed by the driver as well as additional debugging messages to -++ be written to the system log. Note that debugging messages are -++ disabled by default. To enable them, supply the option debug_msgs=1 -++ at the kernel command line when booting the kernel or as an option -++ to insmod when loading the ntfs module. Once the driver is active, -++ you can enable debugging messages by doing (as root): -++ echo 1 > /proc/sys/fs/ntfs-debug -++ Replacing the "1" with "0" would disable debug messages. -++ -++ If you leave debugging messages disabled, this results in little -++ overhead, but enabling debug messages results in very significant -++ slowdown of the system. -++ -++ When reporting bugs, please try to have available a full dump of -++ debugging messages while the misbehaviour was occurring. -++ -++config NTFS_RW -++ bool "NTFS write support" -++ depends on NTFS_FS -++ help -++ This enables the partial, but safe, write support in the NTFS driver. -++ -++ The only supported operation is overwriting existing files, without -++ changing the file length. No file or directory creation, deletion or -++ renaming is possible. Note only non-resident files can be written to -++ so you may find that some very small files (<500 bytes or so) cannot -++ be written to. -++ -++ While we cannot guarantee that it will not damage any data, we have -++ so far not received a single report where the driver would have -++ damaged someones data so we assume it is perfectly safe to use. -++ -++ Note: While write support is safe in this version (a rewrite from -++ scratch of the NTFS support), it should be noted that the old NTFS -++ write support, included in Linux 2.5.10 and before (since 1997), -++ is not safe. -++ -++ This is currently useful with TopologiLinux. TopologiLinux is run -++ on top of any DOS/Microsoft Windows system without partitioning your -++ hard disk. Unlike other Linux distributions TopologiLinux does not -++ need its own partition. For more information see -++ -++ -++ It is perfectly safe to say N here. -++ -++endmenu -++endif -++ -++menu "Pseudo filesystems" -++ -++config PROC_FS -++ bool "/proc file system support" if EMBEDDED -++ default y -++ help -++ This is a virtual file system providing information about the status -++ of the system. "Virtual" means that it doesn't take up any space on -++ your hard disk: the files are created on the fly by the kernel when -++ you try to access them. Also, you cannot read the files with older -++ version of the program less: you need to use more or cat. -++ -++ It's totally cool; for example, "cat /proc/interrupts" gives -++ information about what the different IRQs are used for at the moment -++ (there is a small number of Interrupt ReQuest lines in your computer -++ that are used by the attached devices to gain the CPU's attention -- -++ often a source of trouble if two devices are mistakenly configured -++ to use the same IRQ). The program procinfo to display some -++ information about your system gathered from the /proc file system. -++ -++ Before you can use the /proc file system, it has to be mounted, -++ meaning it has to be given a location in the directory hierarchy. -++ That location should be /proc. A command such as "mount -t proc proc -++ /proc" or the equivalent line in /etc/fstab does the job. -++ -++ The /proc file system is explained in the file -++ and on the proc(5) manpage -++ ("man 5 proc"). -++ -++ This option will enlarge your kernel by about 67 KB. Several -++ programs depend on this, so everyone should say Y here. -++ -++config PROC_KCORE -++ bool "/proc/kcore support" if !ARM -++ depends on PROC_FS && MMU -++ -++config PROC_VMCORE -++ bool "/proc/vmcore support (EXPERIMENTAL)" -++ depends on PROC_FS && EXPERIMENTAL && CRASH_DUMP -++ default y -++ help -++ Exports the dump image of crashed kernel in ELF format. -++ -++config PROC_SYSCTL -++ bool "Sysctl support (/proc/sys)" if EMBEDDED -++ depends on PROC_FS -++ select SYSCTL -++ default y -++ ---help--- -++ The sysctl interface provides a means of dynamically changing -++ certain kernel parameters and variables on the fly without requiring -++ a recompile of the kernel or reboot of the system. The primary -++ interface is through /proc/sys. If you say Y here a tree of -++ modifiable sysctl entries will be generated beneath the -++ /proc/sys directory. They are explained in the files -++ in . Note that enabling this -++ option will enlarge the kernel by at least 8 KB. -++ -++ As it is generally a good thing, you should say Y here unless -++ building a kernel for install/rescue disks or your system is very -++ limited in memory. -++ -++config SYSFS -++ bool "sysfs file system support" if EMBEDDED -++ default y -++ help -++ The sysfs filesystem is a virtual filesystem that the kernel uses to -++ export internal kernel objects, their attributes, and their -++ relationships to one another. -++ -++ Users can use sysfs to ascertain useful information about the running -++ kernel, such as the devices the kernel has discovered on each bus and -++ which driver each is bound to. sysfs can also be used to tune devices -++ and other kernel subsystems. -++ -++ Some system agents rely on the information in sysfs to operate. -++ /sbin/hotplug uses device and object attributes in sysfs to assist in -++ delegating policy decisions, like persistently naming devices. -++ -++ sysfs is currently used by the block subsystem to mount the root -++ partition. If sysfs is disabled you must specify the boot device on -++ the kernel boot command line via its major and minor numbers. For -++ example, "root=03:01" for /dev/hda1. -++ -++ Designers of embedded systems may wish to say N here to conserve space. -++ -++config TMPFS -++ bool "Virtual memory file system support (former shm fs)" -++ help -++ Tmpfs is a file system which keeps all files in virtual memory. -++ -++ Everything in tmpfs is temporary in the sense that no files will be -++ created on your hard drive. The files live in memory and swap -++ space. If you unmount a tmpfs instance, everything stored therein is -++ lost. -++ -++ See for details. -++ -++config TMPFS_POSIX_ACL -++ bool "Tmpfs POSIX Access Control Lists" -++ depends on TMPFS -++ select GENERIC_ACL -++ help -++ POSIX Access Control Lists (ACLs) support permissions for users and -++ groups beyond the owner/group/world scheme. -++ -++ To learn more about Access Control Lists, visit the POSIX ACLs for -++ Linux website . -++ -++ If you don't know what Access Control Lists are, say N. -++ -++config HUGETLBFS -++ bool "HugeTLB file system support" -++ depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || BROKEN -++ help -++ hugetlbfs is a filesystem backing for HugeTLB pages, based on -++ ramfs. For architectures that support it, say Y here and read -++ for details. -++ -++ If unsure, say N. -++ -++config HUGETLB_PAGE -++ def_bool HUGETLBFS -++ -++config CONFIGFS_FS -++ tristate "Userspace-driven configuration filesystem (EXPERIMENTAL)" -++ depends on SYSFS && EXPERIMENTAL -++ help -++ configfs is a ram-based filesystem that provides the converse -++ of sysfs's functionality. Where sysfs is a filesystem-based -++ view of kernel objects, configfs is a filesystem-based manager -++ of kernel objects, or config_items. -++ -++ Both sysfs and configfs can and should exist together on the -++ same system. One is not a replacement for the other. -++ -++endmenu -++ -++menu "Miscellaneous filesystems" -++ -++config ADFS_FS -++ tristate "ADFS file system support (EXPERIMENTAL)" -++ depends on BLOCK && EXPERIMENTAL -++ help -++ The Acorn Disc Filing System is the standard file system of the -++ RiscOS operating system which runs on Acorn's ARM-based Risc PC -++ systems and the Acorn Archimedes range of machines. If you say Y -++ here, Linux will be able to read from ADFS partitions on hard drives -++ and from ADFS-formatted floppy discs. If you also want to be able to -++ write to those devices, say Y to "ADFS write support" below. -++ -++ The ADFS partition should be the first partition (i.e., -++ /dev/[hs]d?1) on each of your drives. Please read the file -++ for further details. -++ -++ To compile this code as a module, choose M here: the module will be -++ called adfs. -++ -++ If unsure, say N. -++ -++config ADFS_FS_RW -++ bool "ADFS write support (DANGEROUS)" -++ depends on ADFS_FS -++ help -++ If you say Y here, you will be able to write to ADFS partitions on -++ hard drives and ADFS-formatted floppy disks. This is experimental -++ codes, so if you're unsure, say N. -++ -++config AFFS_FS -++ tristate "Amiga FFS file system support (EXPERIMENTAL)" -++ depends on BLOCK && EXPERIMENTAL -++ help -++ The Fast File System (FFS) is the common file system used on hard -++ disks by Amiga(tm) systems since AmigaOS Version 1.3 (34.20). Say Y -++ if you want to be able to read and write files from and to an Amiga -++ FFS partition on your hard drive. Amiga floppies however cannot be -++ read with this driver due to an incompatibility of the floppy -++ controller used in an Amiga and the standard floppy controller in -++ PCs and workstations. Read -++ and . -++ -++ With this driver you can also mount disk files used by Bernd -++ Schmidt's Un*X Amiga Emulator -++ (). -++ If you want to do this, you will also need to say Y or M to "Loop -++ device support", above. -++ -++ To compile this file system support as a module, choose M here: the -++ module will be called affs. If unsure, say N. -++ -++config ECRYPT_FS -++ tristate "eCrypt filesystem layer support (EXPERIMENTAL)" -++ depends on EXPERIMENTAL && KEYS && CRYPTO && NET -++ help -++ Encrypted filesystem that operates on the VFS layer. See -++ to learn more about -++ eCryptfs. Userspace components are required and can be -++ obtained from . -++ -++ To compile this file system support as a module, choose M here: the -++ module will be called ecryptfs. -++ -++config HFS_FS -++ tristate "Apple Macintosh file system support (EXPERIMENTAL)" -++ depends on BLOCK && EXPERIMENTAL -++ select NLS -++ help -++ If you say Y here, you will be able to mount Macintosh-formatted -++ floppy disks and hard drive partitions with full read-write access. -++ Please read to learn about -++ the available mount options. -++ -++ To compile this file system support as a module, choose M here: the -++ module will be called hfs. -++ -++config HFSPLUS_FS -++ tristate "Apple Extended HFS file system support" -++ depends on BLOCK -++ select NLS -++ select NLS_UTF8 -++ help -++ If you say Y here, you will be able to mount extended format -++ Macintosh-formatted hard drive partitions with full read-write access. -++ -++ This file system is often called HFS+ and was introduced with -++ MacOS 8. It includes all Mac specific filesystem data such as -++ data forks and creator codes, but it also has several UNIX -++ style features such as file ownership and permissions. -++ -++config BEFS_FS -++ tristate "BeOS file system (BeFS) support (read only) (EXPERIMENTAL)" -++ depends on BLOCK && EXPERIMENTAL -++ select NLS -++ help -++ The BeOS File System (BeFS) is the native file system of Be, Inc's -++ BeOS. Notable features include support for arbitrary attributes -++ on files and directories, and database-like indices on selected -++ attributes. (Also note that this driver doesn't make those features -++ available at this time). It is a 64 bit filesystem, so it supports -++ extremely large volumes and files. -++ -++ If you use this filesystem, you should also say Y to at least one -++ of the NLS (native language support) options below. -++ -++ If you don't know what this is about, say N. -++ -++ To compile this as a module, choose M here: the module will be -++ called befs. -++ -++config BEFS_DEBUG -++ bool "Debug BeFS" -++ depends on BEFS_FS -++ help -++ If you say Y here, you can use the 'debug' mount option to enable -++ debugging output from the driver. -++ -++config BFS_FS -++ tristate "BFS file system support (EXPERIMENTAL)" -++ depends on BLOCK && EXPERIMENTAL -++ help -++ Boot File System (BFS) is a file system used under SCO UnixWare to -++ allow the bootloader access to the kernel image and other important -++ files during the boot process. It is usually mounted under /stand -++ and corresponds to the slice marked as "STAND" in the UnixWare -++ partition. You should say Y if you want to read or write the files -++ on your /stand slice from within Linux. You then also need to say Y -++ to "UnixWare slices support", below. More information about the BFS -++ file system is contained in the file -++ . -++ -++ If you don't know what this is about, say N. -++ -++ To compile this as a module, choose M here: the module will be called -++ bfs. Note that the file system of your root partition (the one -++ containing the directory /) cannot be compiled as a module. -++ -++ -++ -++config EFS_FS -++ tristate "EFS file system support (read only) (EXPERIMENTAL)" -++ depends on BLOCK && EXPERIMENTAL -++ help -++ EFS is an older file system used for non-ISO9660 CD-ROMs and hard -++ disk partitions by SGI's IRIX operating system (IRIX 6.0 and newer -++ uses the XFS file system for hard disk partitions however). -++ -++ This implementation only offers read-only access. If you don't know -++ what all this is about, it's safe to say N. For more information -++ about EFS see its home page at . -++ -++ To compile the EFS file system support as a module, choose M here: the -++ module will be called efs. -++ -++config JFFS2_FS -++ tristate "Journalling Flash File System v2 (JFFS2) support" -++ select CRC32 -++ depends on MTD -++ help -++ JFFS2 is the second generation of the Journalling Flash File System -++ for use on diskless embedded devices. It provides improved wear -++ levelling, compression and support for hard links. You cannot use -++ this on normal block devices, only on 'MTD' devices. -++ -++ Further information on the design and implementation of JFFS2 is -++ available at . -++ -++config JFFS2_FS_DEBUG -++ int "JFFS2 debugging verbosity (0 = quiet, 2 = noisy)" -++ depends on JFFS2_FS -++ default "0" -++ help -++ This controls the amount of debugging messages produced by the JFFS2 -++ code. Set it to zero for use in production systems. For evaluation, -++ testing and debugging, it's advisable to set it to one. This will -++ enable a few assertions and will print debugging messages at the -++ KERN_DEBUG loglevel, where they won't normally be visible. Level 2 -++ is unlikely to be useful - it enables extra debugging in certain -++ areas which at one point needed debugging, but when the bugs were -++ located and fixed, the detailed messages were relegated to level 2. -++ -++ If reporting bugs, please try to have available a full dump of the -++ messages at debug level 1 while the misbehaviour was occurring. -++ -++config JFFS2_FS_WRITEBUFFER -++ bool "JFFS2 write-buffering support" -++ depends on JFFS2_FS -++ default y -++ help -++ This enables the write-buffering support in JFFS2. -++ -++ This functionality is required to support JFFS2 on the following -++ types of flash devices: -++ - NAND flash -++ - NOR flash with transparent ECC -++ - DataFlash -++ -++config JFFS2_FS_WBUF_VERIFY -++ bool "Verify JFFS2 write-buffer reads" -++ depends on JFFS2_FS_WRITEBUFFER -++ default n -++ help -++ This causes JFFS2 to read back every page written through the -++ write-buffer, and check for errors. -++ -++config JFFS2_SUMMARY -++ bool "JFFS2 summary support (EXPERIMENTAL)" -++ depends on JFFS2_FS && EXPERIMENTAL -++ default n -++ help -++ This feature makes it possible to use summary information -++ for faster filesystem mount. -++ -++ The summary information can be inserted into a filesystem image -++ by the utility 'sumtool'. -++ -++ If unsure, say 'N'. -++ -++config JFFS2_FS_XATTR -++ bool "JFFS2 XATTR support (EXPERIMENTAL)" -++ depends on JFFS2_FS && EXPERIMENTAL -++ default n -++ help -++ Extended attributes are name:value pairs associated with inodes by -++ the kernel or by users (see the attr(5) manual page, or visit -++ for details). -++ -++ If unsure, say N. -++ -++config JFFS2_FS_POSIX_ACL -++ bool "JFFS2 POSIX Access Control Lists" -++ depends on JFFS2_FS_XATTR -++ default y -++ select FS_POSIX_ACL -++ help -++ Posix Access Control Lists (ACLs) support permissions for users and -++ groups beyond the owner/group/world scheme. -++ -++ To learn more about Access Control Lists, visit the Posix ACLs for -++ Linux website . -++ -++ If you don't know what Access Control Lists are, say N -++ -++config JFFS2_FS_SECURITY -++ bool "JFFS2 Security Labels" -++ depends on JFFS2_FS_XATTR -++ default y -++ help -++ Security labels support alternative access control models -++ implemented by security modules like SELinux. This option -++ enables an extended attribute handler for file security -++ labels in the jffs2 filesystem. -++ -++ If you are not using a security module that requires using -++ extended attributes for file security labels, say N. -++ -++config JFFS2_COMPRESSION_OPTIONS -++ bool "Advanced compression options for JFFS2" -++ depends on JFFS2_FS -++ default n -++ help -++ Enabling this option allows you to explicitly choose which -++ compression modules, if any, are enabled in JFFS2. Removing -++ compressors can mean you cannot read existing file systems, -++ and enabling experimental compressors can mean that you -++ write a file system which cannot be read by a standard kernel. -++ -++ If unsure, you should _definitely_ say 'N'. -++ -++config JFFS2_ZLIB -++ bool "JFFS2 ZLIB compression support" if JFFS2_COMPRESSION_OPTIONS -++ select ZLIB_INFLATE -++ select ZLIB_DEFLATE -++ depends on JFFS2_FS -++ default y -++ help -++ Zlib is designed to be a free, general-purpose, legally unencumbered, -++ lossless data-compression library for use on virtually any computer -++ hardware and operating system. See for -++ further information. -++ -++ Say 'Y' if unsure. -++ -++config JFFS2_LZO -++ bool "JFFS2 LZO compression support" if JFFS2_COMPRESSION_OPTIONS -++ select LZO_COMPRESS -++ select LZO_DECOMPRESS -++ depends on JFFS2_FS -++ default n -++ help -++ minilzo-based compression. Generally works better than Zlib. -++ -++ This feature was added in July, 2007. Say 'N' if you need -++ compatibility with older bootloaders or kernels. -++ -++config JFFS2_RTIME -++ bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS -++ depends on JFFS2_FS -++ default y -++ help -++ Rtime does manage to recompress already-compressed data. Say 'Y' if unsure. -++ -++config JFFS2_RUBIN -++ bool "JFFS2 RUBIN compression support" if JFFS2_COMPRESSION_OPTIONS -++ depends on JFFS2_FS -++ default n -++ help -++ RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure. -++ -++choice -++ prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS -++ default JFFS2_CMODE_PRIORITY -++ depends on JFFS2_FS -++ help -++ You can set here the default compression mode of JFFS2 from -++ the available compression modes. Don't touch if unsure. -++ -++config JFFS2_CMODE_NONE -++ bool "no compression" -++ help -++ Uses no compression. -++ -++config JFFS2_CMODE_PRIORITY -++ bool "priority" -++ help -++ Tries the compressors in a predefined order and chooses the first -++ successful one. -++ -++config JFFS2_CMODE_SIZE -++ bool "size (EXPERIMENTAL)" -++ help -++ Tries all compressors and chooses the one which has the smallest -++ result. -++ -++config JFFS2_CMODE_FAVOURLZO -++ bool "Favour LZO" -++ help -++ Tries all compressors and chooses the one which has the smallest -++ result but gives some preference to LZO (which has faster -++ decompression) at the expense of size. -++ -++endchoice -++ -++config CRAMFS -++ tristate "Compressed ROM file system support (cramfs)" -++ depends on BLOCK -++ select ZLIB_INFLATE -++ help -++ Saying Y here includes support for CramFs (Compressed ROM File -++ System). CramFs is designed to be a simple, small, and compressed -++ file system for ROM based embedded systems. CramFs is read-only, -++ limited to 256MB file systems (with 16MB files), and doesn't support -++ 16/32 bits uid/gid, hard links and timestamps. -++ -++ See and -++ for further information. -++ -++ To compile this as a module, choose M here: the module will be called -++ cramfs. Note that the root file system (the one containing the -++ directory /) cannot be compiled as a module. -++ -++ If unsure, say N. -++ -++config SQUASHFS -++ tristate "SquashFS 3.0 - Squashed file system support" -++ select ZLIB_INFLATE -++ help -++ Saying Y here includes support for SquashFS 3.0 (a Compressed Read-Only File -++ System). Squashfs is a highly compressed read-only filesystem for Linux. -++ It uses zlib compression to compress both files, inodes and directories. -++ Inodes in the system are very small and all blocks are packed to minimise -++ data overhead. Block sizes greater than 4K are supported up to a maximum of 64K. -++ SquashFS 3.0 supports 64 bit filesystems and files (larger than 4GB), full -++ uid/gid information, hard links and timestamps. -++ -++ Squashfs is intended for general read-only filesystem use, for archival -++ use (i.e. in cases where a .tar.gz file may be used), and in embedded -++ systems where low overhead is needed. Further information and filesystem tools -++ are available from http://squashfs.sourceforge.net. -++ -++ If you want to compile this as a module ( = code which can be -++ inserted in and removed from the running kernel whenever you want), -++ say M here and read . The module -++ will be called squashfs. Note that the root file system (the one -++ containing the directory /) cannot be compiled as a module. -++ -++ If unsure, say N. -++ -++config SQUASHFS_EMBEDDED -++ -++ bool "Additional options for memory-constrained systems" -++ depends on SQUASHFS -++ default n -++ help -++ Saying Y here allows you to specify cache sizes and how Squashfs -++ allocates memory. This is only intended for memory constrained -++ systems. -++ -++ If unsure, say N. -++ -++config SQUASHFS_FRAGMENT_CACHE_SIZE -++ int "Number of fragments cached" if SQUASHFS_EMBEDDED -++ depends on SQUASHFS -++ default "3" -++ help -++ By default SquashFS caches the last 3 fragments read from -++ the filesystem. Increasing this amount may mean SquashFS -++ has to re-read fragments less often from disk, at the expense -++ of extra system memory. Decreasing this amount will mean -++ SquashFS uses less memory at the expense of extra reads from disk. -++ -++ Note there must be at least one cached fragment. Anything -++ much more than three will probably not make much difference. -++ -++config SQUASHFS_VMALLOC -++ bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED -++ depends on SQUASHFS -++ default n -++ help -++ By default SquashFS uses kmalloc to obtain fragment cache memory. -++ Kmalloc memory is the standard kernel allocator, but it can fail -++ on memory constrained systems. Because of the way Vmalloc works, -++ Vmalloc can succeed when kmalloc fails. Specifying this option -++ will make SquashFS always use Vmalloc to allocate the -++ fragment cache memory. -++ -++ If unsure, say N. -++ -++config VXFS_FS -++ tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" -++ depends on BLOCK -++ help -++ FreeVxFS is a file system driver that support the VERITAS VxFS(TM) -++ file system format. VERITAS VxFS(TM) is the standard file system -++ of SCO UnixWare (and possibly others) and optionally available -++ for Sunsoft Solaris, HP-UX and many other operating systems. -++ Currently only readonly access is supported. -++ -++ NOTE: the file system type as used by mount(1), mount(2) and -++ fstab(5) is 'vxfs' as it describes the file system format, not -++ the actual driver. -++ -++ To compile this as a module, choose M here: the module will be -++ called freevxfs. If unsure, say N. -++ -++ -++config HPFS_FS -++ tristate "OS/2 HPFS file system support" -++ depends on BLOCK -++ help -++ OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS -++ is the file system used for organizing files on OS/2 hard disk -++ partitions. Say Y if you want to be able to read files from and -++ write files to an OS/2 HPFS partition on your hard drive. OS/2 -++ floppies however are in regular MSDOS format, so you don't need this -++ option in order to be able to read them. Read -++ . -++ -++ To compile this file system support as a module, choose M here: the -++ module will be called hpfs. If unsure, say N. -++ -++ -++ -++config QNX4FS_FS -++ tristate "QNX4 file system support (read only)" -++ depends on BLOCK -++ help -++ This is the file system used by the real-time operating systems -++ QNX 4 and QNX 6 (the latter is also called QNX RTP). -++ Further information is available at . -++ Say Y if you intend to mount QNX hard disks or floppies. -++ Unless you say Y to "QNX4FS read-write support" below, you will -++ only be able to read these file systems. -++ -++ To compile this file system support as a module, choose M here: the -++ module will be called qnx4. -++ -++ If you don't know whether you need it, then you don't need it: -++ answer N. -++ -++config QNX4FS_RW -++ bool "QNX4FS write support (DANGEROUS)" -++ depends on QNX4FS_FS && EXPERIMENTAL && BROKEN -++ help -++ Say Y if you want to test write support for QNX4 file systems. -++ -++ It's currently broken, so for now: -++ answer N. -++ -++ -++ -++config SYSV_FS -++ tristate "System V/Xenix/V7/Coherent file system support" -++ depends on BLOCK -++ help -++ SCO, Xenix and Coherent are commercial Unix systems for Intel -++ machines, and Version 7 was used on the DEC PDP-11. Saying Y -++ here would allow you to read from their floppies and hard disk -++ partitions. -++ -++ If you have floppies or hard disk partitions like that, it is likely -++ that they contain binaries from those other Unix systems; in order -++ to run these binaries, you will want to install linux-abi which is -++ a set of kernel modules that lets you run SCO, Xenix, Wyse, -++ UnixWare, Dell Unix and System V programs under Linux. It is -++ available via FTP (user: ftp) from -++ ). -++ NOTE: that will work only for binaries from Intel-based systems; -++ PDP ones will have to wait until somebody ports Linux to -11 ;-) -++ -++ If you only intend to mount files from some other Unix over the -++ network using NFS, you don't need the System V file system support -++ (but you need NFS file system support obviously). -++ -++ Note that this option is generally not needed for floppies, since a -++ good portable way to transport files and directories between unixes -++ (and even other operating systems) is given by the tar program ("man -++ tar" or preferably "info tar"). Note also that this option has -++ nothing whatsoever to do with the option "System V IPC". Read about -++ the System V file system in -++ . -++ Saying Y here will enlarge your kernel by about 27 KB. -++ -++ To compile this as a module, choose M here: the module will be called -++ sysv. -++ -++ If you haven't heard about all of this before, it's safe to say N. -++ -++ -++ -++config UFS_FS -++ tristate "UFS file system support (read only)" -++ depends on BLOCK -++ help -++ BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD, -++ OpenBSD and NeXTstep) use a file system called UFS. Some System V -++ Unixes can create and mount hard disk partitions and diskettes using -++ this file system as well. Saying Y here will allow you to read from -++ these partitions; if you also want to write to them, say Y to the -++ experimental "UFS file system write support", below. Please read the -++ file for more information. -++ -++ The recently released UFS2 variant (used in FreeBSD 5.x) is -++ READ-ONLY supported. -++ -++ If you only intend to mount files from some other Unix over the -++ network using NFS, you don't need the UFS file system support (but -++ you need NFS file system support obviously). -++ -++ Note that this option is generally not needed for floppies, since a -++ good portable way to transport files and directories between unixes -++ (and even other operating systems) is given by the tar program ("man -++ tar" or preferably "info tar"). -++ -++ When accessing NeXTstep files, you may need to convert them from the -++ NeXT character set to the Latin1 character set; use the program -++ recode ("info recode") for this purpose. -++ -++ To compile the UFS file system support as a module, choose M here: the -++ module will be called ufs. -++ -++ If you haven't heard about all of this before, it's safe to say N. -++ -++config UFS_FS_WRITE -++ bool "UFS file system write support (DANGEROUS)" -++ depends on UFS_FS && EXPERIMENTAL -++ help -++ Say Y here if you want to try writing to UFS partitions. This is -++ experimental, so you should back up your UFS partitions beforehand. -++ -++config UFS_DEBUG -++ bool "UFS debugging" -++ depends on UFS_FS -++ help -++ If you are experiencing any problems with the UFS filesystem, say -++ Y here. This will result in _many_ additional debugging messages to be -++ written to the system log. -++ -++endmenu -++ -++menuconfig NETWORK_FILESYSTEMS -++ bool "Network File Systems" -++ default y -++ depends on NET -++ ---help--- -++ Say Y here to get to see options for network filesystems and -++ filesystem-related networking code, such as NFS daemon and -++ RPCSEC security modules. -++ This option alone does not add any kernel code. -++ -++ If you say N, all options in this submenu will be skipped and -++ disabled; if unsure, say Y here. -++ -++if NETWORK_FILESYSTEMS -++ -++config NFS_FS -++ tristate "NFS file system support" -++ depends on INET -++ select LOCKD -++ select SUNRPC -++ select NFS_ACL_SUPPORT if NFS_V3_ACL -++ help -++ If you are connected to some other (usually local) Unix computer -++ (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing -++ on that computer (the NFS server) using the Network File Sharing -++ protocol, say Y. "Mounting files" means that the client can access -++ the files with usual UNIX commands as if they were sitting on the -++ client's hard disk. For this to work, the server must run the -++ programs nfsd and mountd (but does not need to have NFS file system -++ support enabled in its kernel). NFS is explained in the Network -++ Administrator's Guide, available from -++ , on its man page: "man -++ nfs", and in the NFS-HOWTO. -++ -++ A superior but less widely used alternative to NFS is provided by -++ the Coda file system; see "Coda file system support" below. -++ -++ If you say Y here, you should have said Y to TCP/IP networking also. -++ This option would enlarge your kernel by about 27 KB. -++ -++ To compile this file system support as a module, choose M here: the -++ module will be called nfs. -++ -++ If you are configuring a diskless machine which will mount its root -++ file system over NFS at boot time, say Y here and to "Kernel -++ level IP autoconfiguration" above and to "Root file system on NFS" -++ below. You cannot compile this driver as a module in this case. -++ There are two packages designed for booting diskless machines over -++ the net: netboot, available from -++ , and Etherboot, -++ available from . -++ -++ If you don't know what all this is about, say N. -++ -++config NFS_V3 -++ bool "Provide NFSv3 client support" -++ depends on NFS_FS -++ help -++ Say Y here if you want your NFS client to be able to speak version -++ 3 of the NFS protocol. -++ -++ If unsure, say Y. -++ -++config NFS_V3_ACL -++ bool "Provide client support for the NFSv3 ACL protocol extension" -++ depends on NFS_V3 -++ help -++ Implement the NFSv3 ACL protocol extension for manipulating POSIX -++ Access Control Lists. The server should also be compiled with -++ the NFSv3 ACL protocol extension; see the CONFIG_NFSD_V3_ACL option. -++ -++ If unsure, say N. -++ -++config NFS_V4 -++ bool "Provide NFSv4 client support (EXPERIMENTAL)" -++ depends on NFS_FS && EXPERIMENTAL -++ select RPCSEC_GSS_KRB5 -++ help -++ Say Y here if you want your NFS client to be able to speak the newer -++ version 4 of the NFS protocol. -++ -++ Note: Requires auxiliary userspace daemons which may be found on -++ http://www.citi.umich.edu/projects/nfsv4/ -++ -++ If unsure, say N. -++ -++config NFS_DIRECTIO -++ bool "Allow direct I/O on NFS files" -++ depends on NFS_FS -++ help -++ This option enables applications to perform uncached I/O on files -++ in NFS file systems using the O_DIRECT open() flag. When O_DIRECT -++ is set for a file, its data is not cached in the system's page -++ cache. Data is moved to and from user-level application buffers -++ directly. Unlike local disk-based file systems, NFS O_DIRECT has -++ no alignment restrictions. -++ -++ Unless your program is designed to use O_DIRECT properly, you are -++ much better off allowing the NFS client to manage data caching for -++ you. Misusing O_DIRECT can cause poor server performance or network -++ storms. This kernel build option defaults OFF to avoid exposing -++ system administrators unwittingly to a potentially hazardous -++ feature. -++ -++ For more details on NFS O_DIRECT, see fs/nfs/direct.c. -++ -++ If unsure, say N. This reduces the size of the NFS client, and -++ causes open() to return EINVAL if a file residing in NFS is -++ opened with the O_DIRECT flag. -++ -++config NFSD -++ tristate "NFS server support" -++ depends on INET -++ select LOCKD -++ select SUNRPC -++ select EXPORTFS -++ select NFSD_V2_ACL if NFSD_V3_ACL -++ select NFS_ACL_SUPPORT if NFSD_V2_ACL -++ select NFSD_TCP if NFSD_V4 -++ select CRYPTO_MD5 if NFSD_V4 -++ select CRYPTO if NFSD_V4 -++ select FS_POSIX_ACL if NFSD_V4 -++ help -++ If you want your Linux box to act as an NFS *server*, so that other -++ computers on your local network which support NFS can access certain -++ directories on your box transparently, you have two options: you can -++ use the self-contained user space program nfsd, in which case you -++ should say N here, or you can say Y and use the kernel based NFS -++ server. The advantage of the kernel based solution is that it is -++ faster. -++ -++ In either case, you will need support software; the respective -++ locations are given in the file in the -++ NFS section. -++ -++ If you say Y here, you will get support for version 2 of the NFS -++ protocol (NFSv2). If you also want NFSv3, say Y to the next question -++ as well. -++ -++ Please read the NFS-HOWTO, available from -++ . -++ -++ To compile the NFS server support as a module, choose M here: the -++ module will be called nfsd. If unsure, say N. -++ -++config NFSD_V2_ACL -++ bool -++ depends on NFSD -++ -++config NFSD_V3 -++ bool "Provide NFSv3 server support" -++ depends on NFSD -++ help -++ If you would like to include the NFSv3 server as well as the NFSv2 -++ server, say Y here. If unsure, say Y. -++ -++config NFSD_V3_ACL -++ bool "Provide server support for the NFSv3 ACL protocol extension" -++ depends on NFSD_V3 -++ help -++ Implement the NFSv3 ACL protocol extension for manipulating POSIX -++ Access Control Lists on exported file systems. NFS clients should -++ be compiled with the NFSv3 ACL protocol extension; see the -++ CONFIG_NFS_V3_ACL option. If unsure, say N. -++ -++config NFSD_V4 -++ bool "Provide NFSv4 server support (EXPERIMENTAL)" -++ depends on NFSD && NFSD_V3 && EXPERIMENTAL -++ select RPCSEC_GSS_KRB5 -++ help -++ If you would like to include the NFSv4 server as well as the NFSv2 -++ and NFSv3 servers, say Y here. This feature is experimental, and -++ should only be used if you are interested in helping to test NFSv4. -++ If unsure, say N. -++ -++config NFSD_TCP -++ bool "Provide NFS server over TCP support" -++ depends on NFSD -++ default y -++ help -++ If you want your NFS server to support TCP connections, say Y here. -++ TCP connections usually perform better than the default UDP when -++ the network is lossy or congested. If unsure, say Y. -++ -++config ROOT_NFS -++ bool "Root file system on NFS" -++ depends on NFS_FS=y && IP_PNP -++ help -++ If you want your Linux box to mount its whole root file system (the -++ one containing the directory /) from some other computer over the -++ net via NFS (presumably because your box doesn't have a hard disk), -++ say Y. Read for details. It is -++ likely that in this case, you also want to say Y to "Kernel level IP -++ autoconfiguration" so that your box can discover its network address -++ at boot time. -++ -++ Most people say N here. -++ -++config LOCKD -++ tristate -++ -++config LOCKD_V4 -++ bool -++ depends on NFSD_V3 || NFS_V3 -++ default y -++ -++config EXPORTFS -++ tristate -++ -++config NFS_ACL_SUPPORT -++ tristate -++ select FS_POSIX_ACL -++ -++config NFS_COMMON -++ bool -++ depends on NFSD || NFS_FS -++ default y -++ -++config SUNRPC -++ tristate -++ -++config SUNRPC_GSS -++ tristate -++ -++config SUNRPC_XPRT_RDMA -++ tristate "RDMA transport for sunrpc (EXPERIMENTAL)" -++ depends on SUNRPC && INFINIBAND && EXPERIMENTAL -++ default m -++ help -++ Adds a client RPC transport for supporting kernel NFS over RDMA -++ mounts, including Infiniband and iWARP. Experimental. -++ -++config SUNRPC_BIND34 -++ bool "Support for rpcbind versions 3 & 4 (EXPERIMENTAL)" -++ depends on SUNRPC && EXPERIMENTAL -++ help -++ Provides kernel support for querying rpcbind servers via versions 3 -++ and 4 of the rpcbind protocol. The kernel automatically falls back -++ to version 2 if a remote rpcbind service does not support versions -++ 3 or 4. -++ -++ If unsure, say N to get traditional behavior (version 2 rpcbind -++ requests only). -++ -++config RPCSEC_GSS_KRB5 -++ tristate "Secure RPC: Kerberos V mechanism (EXPERIMENTAL)" -++ depends on SUNRPC && EXPERIMENTAL -++ select SUNRPC_GSS -++ select CRYPTO -++ select CRYPTO_MD5 -++ select CRYPTO_DES -++ select CRYPTO_CBC -++ help -++ Provides for secure RPC calls by means of a gss-api -++ mechanism based on Kerberos V5. This is required for -++ NFSv4. -++ -++ Note: Requires an auxiliary userspace daemon which may be found on -++ http://www.citi.umich.edu/projects/nfsv4/ -++ -++ If unsure, say N. -++ -++config RPCSEC_GSS_SPKM3 -++ tristate "Secure RPC: SPKM3 mechanism (EXPERIMENTAL)" -++ depends on SUNRPC && EXPERIMENTAL -++ select SUNRPC_GSS -++ select CRYPTO -++ select CRYPTO_MD5 -++ select CRYPTO_DES -++ select CRYPTO_CAST5 -++ select CRYPTO_CBC -++ help -++ Provides for secure RPC calls by means of a gss-api -++ mechanism based on the SPKM3 public-key mechanism. -++ -++ Note: Requires an auxiliary userspace daemon which may be found on -++ http://www.citi.umich.edu/projects/nfsv4/ -++ -++ If unsure, say N. -++ -++config SMB_FS -++ tristate "SMB file system support (to mount Windows shares etc.)" -++ depends on INET -++ select NLS -++ help -++ SMB (Server Message Block) is the protocol Windows for Workgroups -++ (WfW), Windows 95/98, Windows NT and OS/2 Lan Manager use to share -++ files and printers over local networks. Saying Y here allows you to -++ mount their file systems (often called "shares" in this context) and -++ access them just like any other Unix directory. Currently, this -++ works only if the Windows machines use TCP/IP as the underlying -++ transport protocol, and not NetBEUI. For details, read -++ and the SMB-HOWTO, -++ available from . -++ -++ Note: if you just want your box to act as an SMB *server* and make -++ files and printing services available to Windows clients (which need -++ to have a TCP/IP stack), you don't need to say Y here; you can use -++ the program SAMBA (available from ) -++ for that. -++ -++ General information about how to connect Linux, Windows machines and -++ Macs is on the WWW at . -++ -++ To compile the SMB support as a module, choose M here: the module will -++ be called smbfs. Most people say N, however. -++ -++config SMB_NLS_DEFAULT -++ bool "Use a default NLS" -++ depends on SMB_FS -++ help -++ Enabling this will make smbfs use nls translations by default. You -++ need to specify the local charset (CONFIG_NLS_DEFAULT) in the nls -++ settings and you need to give the default nls for the SMB server as -++ CONFIG_SMB_NLS_REMOTE. -++ -++ The nls settings can be changed at mount time, if your smbmount -++ supports that, using the codepage and iocharset parameters. -++ -++ smbmount from samba 2.2.0 or later supports this. -++ -++config SMB_NLS_REMOTE -++ string "Default Remote NLS Option" -++ depends on SMB_NLS_DEFAULT -++ default "cp437" -++ help -++ This setting allows you to specify a default value for which -++ codepage the server uses. If this field is left blank no -++ translations will be done by default. The local codepage/charset -++ default to CONFIG_NLS_DEFAULT. -++ -++ The nls settings can be changed at mount time, if your smbmount -++ supports that, using the codepage and iocharset parameters. -++ -++ smbmount from samba 2.2.0 or later supports this. -++ -++config CIFS -++ tristate "CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)" -++ depends on INET -++ select NLS -++ help -++ This is the client VFS module for the Common Internet File System -++ (CIFS) protocol which is the successor to the Server Message Block -++ (SMB) protocol, the native file sharing mechanism for most early -++ PC operating systems. The CIFS protocol is fully supported by -++ file servers such as Windows 2000 (including Windows 2003, NT 4 -++ and Windows XP) as well by Samba (which provides excellent CIFS -++ server support for Linux and many other operating systems). Limited -++ support for OS/2 and Windows ME and similar servers is provided as well. -++ -++ The intent of the cifs module is to provide an advanced -++ network file system client for mounting to CIFS compliant servers, -++ including support for dfs (hierarchical name space), secure per-user -++ session establishment, safe distributed caching (oplock), optional -++ packet signing, Unicode and other internationalization improvements. -++ If you need to mount to Samba or Windows from this machine, say Y. -++ -++config CIFS_STATS -++ bool "CIFS statistics" -++ depends on CIFS -++ help -++ Enabling this option will cause statistics for each server share -++ mounted by the cifs client to be displayed in /proc/fs/cifs/Stats -++ -++config CIFS_STATS2 -++ bool "Extended statistics" -++ depends on CIFS_STATS -++ help -++ Enabling this option will allow more detailed statistics on SMB -++ request timing to be displayed in /proc/fs/cifs/DebugData and also -++ allow optional logging of slow responses to dmesg (depending on the -++ value of /proc/fs/cifs/cifsFYI, see fs/cifs/README for more details). -++ These additional statistics may have a minor effect on performance -++ and memory utilization. -++ -++ Unless you are a developer or are doing network performance analysis -++ or tuning, say N. -++ -++config CIFS_WEAK_PW_HASH -++ bool "Support legacy servers which use weaker LANMAN security" -++ depends on CIFS -++ help -++ Modern CIFS servers including Samba and most Windows versions -++ (since 1997) support stronger NTLM (and even NTLMv2 and Kerberos) -++ security mechanisms. These hash the password more securely -++ than the mechanisms used in the older LANMAN version of the -++ SMB protocol needed to establish sessions with old SMB servers. -++ -++ Enabling this option allows the cifs module to mount to older -++ LANMAN based servers such as OS/2 and Windows 95, but such -++ mounts may be less secure than mounts using NTLM or more recent -++ security mechanisms if you are on a public network. Unless you -++ have a need to access old SMB servers (and are on a private -++ network) you probably want to say N. Even if this support -++ is enabled in the kernel build, they will not be used -++ automatically. At runtime LANMAN mounts are disabled but -++ can be set to required (or optional) either in -++ /proc/fs/cifs (see fs/cifs/README for more detail) or via an -++ option on the mount command. This support is disabled by -++ default in order to reduce the possibility of a downgrade -++ attack. -++ -++ If unsure, say N. -++ -++config CIFS_XATTR -++ bool "CIFS extended attributes" -++ depends on CIFS -++ help -++ Extended attributes are name:value pairs associated with inodes by -++ the kernel or by users (see the attr(5) manual page, or visit -++ for details). CIFS maps the name of -++ extended attributes beginning with the user namespace prefix -++ to SMB/CIFS EAs. EAs are stored on Windows servers without the -++ user namespace prefix, but their names are seen by Linux cifs clients -++ prefaced by the user namespace prefix. The system namespace -++ (used by some filesystems to store ACLs) is not supported at -++ this time. -++ -++ If unsure, say N. -++ -++config CIFS_POSIX -++ bool "CIFS POSIX Extensions" -++ depends on CIFS_XATTR -++ help -++ Enabling this option will cause the cifs client to attempt to -++ negotiate a newer dialect with servers, such as Samba 3.0.5 -++ or later, that optionally can handle more POSIX like (rather -++ than Windows like) file behavior. It also enables -++ support for POSIX ACLs (getfacl and setfacl) to servers -++ (such as Samba 3.10 and later) which can negotiate -++ CIFS POSIX ACL support. If unsure, say N. -++ -++config CIFS_DEBUG2 -++ bool "Enable additional CIFS debugging routines" -++ depends on CIFS -++ help -++ Enabling this option adds a few more debugging routines -++ to the cifs code which slightly increases the size of -++ the cifs module and can cause additional logging of debug -++ messages in some error paths, slowing performance. This -++ option can be turned off unless you are debugging -++ cifs problems. If unsure, say N. -++ -++config CIFS_EXPERIMENTAL -++ bool "CIFS Experimental Features (EXPERIMENTAL)" -++ depends on CIFS && EXPERIMENTAL -++ help -++ Enables cifs features under testing. These features are -++ experimental and currently include DFS support and directory -++ change notification ie fcntl(F_DNOTIFY), as well as the upcall -++ mechanism which will be used for Kerberos session negotiation -++ and uid remapping. Some of these features also may depend on -++ setting a value of 1 to the pseudo-file /proc/fs/cifs/Experimental -++ (which is disabled by default). See the file fs/cifs/README -++ for more details. If unsure, say N. -++ -++config CIFS_UPCALL -++ bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" -++ depends on CIFS_EXPERIMENTAL -++ depends on KEYS -++ help -++ Enables an upcall mechanism for CIFS which will be used to contact -++ userspace helper utilities to provide SPNEGO packaged Kerberos -++ tickets which are needed to mount to certain secure servers -++ (for which more secure Kerberos authentication is required). If -++ unsure, say N. -++ -++config NCP_FS -++ tristate "NCP file system support (to mount NetWare volumes)" -++ depends on IPX!=n || INET -++ help -++ NCP (NetWare Core Protocol) is a protocol that runs over IPX and is -++ used by Novell NetWare clients to talk to file servers. It is to -++ IPX what NFS is to TCP/IP, if that helps. Saying Y here allows you -++ to mount NetWare file server volumes and to access them just like -++ any other Unix directory. For details, please read the file -++ in the kernel source and -++ the IPX-HOWTO from . -++ -++ You do not have to say Y here if you want your Linux box to act as a -++ file *server* for Novell NetWare clients. -++ -++ General information about how to connect Linux, Windows machines and -++ Macs is on the WWW at . -++ -++ To compile this as a module, choose M here: the module will be called -++ ncpfs. Say N unless you are connected to a Novell network. -++ -++source "fs/ncpfs/Kconfig" -++ -++config CODA_FS -++ tristate "Coda file system support (advanced network fs)" -++ depends on INET -++ help -++ Coda is an advanced network file system, similar to NFS in that it -++ enables you to mount file systems of a remote server and access them -++ with regular Unix commands as if they were sitting on your hard -++ disk. Coda has several advantages over NFS: support for -++ disconnected operation (e.g. for laptops), read/write server -++ replication, security model for authentication and encryption, -++ persistent client caches and write back caching. -++ -++ If you say Y here, your Linux box will be able to act as a Coda -++ *client*. You will need user level code as well, both for the -++ client and server. Servers are currently user level, i.e. they need -++ no kernel support. Please read -++ and check out the Coda -++ home page . -++ -++ To compile the coda client support as a module, choose M here: the -++ module will be called coda. -++ -++config CODA_FS_OLD_API -++ bool "Use 96-bit Coda file identifiers" -++ depends on CODA_FS -++ help -++ A new kernel-userspace API had to be introduced for Coda v6.0 -++ to support larger 128-bit file identifiers as needed by the -++ new realms implementation. -++ -++ However this new API is not backward compatible with older -++ clients. If you really need to run the old Coda userspace -++ cache manager then say Y. -++ -++ For most cases you probably want to say N. -++ -++config AFS_FS -++ tristate "Andrew File System support (AFS) (EXPERIMENTAL)" -++ depends on INET && EXPERIMENTAL -++ select AF_RXRPC -++ help -++ If you say Y here, you will get an experimental Andrew File System -++ driver. It currently only supports unsecured read-only AFS access. -++ -++ See for more information. -++ -++ If unsure, say N. -++ -++config AFS_DEBUG -++ bool "AFS dynamic debugging" -++ depends on AFS_FS -++ help -++ Say Y here to make runtime controllable debugging messages appear. -++ -++ See for more information. -++ -++ If unsure, say N. -++ -++config 9P_FS -++ tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)" -++ depends on INET && NET_9P && EXPERIMENTAL -++ help -++ If you say Y here, you will get experimental support for -++ Plan 9 resource sharing via the 9P2000 protocol. -++ -++ See for more information. -++ -++ If unsure, say N. -++ -++endif # NETWORK_FILESYSTEMS -++ -++if BLOCK -++menu "Partition Types" -++ -++source "fs/partitions/Kconfig" -++ -++endmenu -++endif -++ -++source "fs/nls/Kconfig" -++source "fs/dlm/Kconfig" -++ -++endmenu -++ -+diff -urN linux-2.6.24.7.old/fs/fs-writeback.c linux-2.6.24.7/fs/fs-writeback.c -+--- linux-2.6.24.7.old/fs/fs-writeback.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/fs/fs-writeback.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -386,8 +386,6 @@ -+ * WB_SYNC_HOLD is a hack for sys_sync(): reattach the inode to sb->s_dirty so -+ * that it can be located for waiting on in __writeback_single_inode(). -+ * -+- * Called under inode_lock. -+- * -+ * If `bdi' is non-zero then we're being asked to writeback a specific queue. -+ * This function assumes that the blockdev superblock's inodes are backed by -+ * a variety of queues, so all inodes are searched. For other superblocks, -+@@ -403,11 +401,12 @@ -+ * on the writer throttling path, and we get decent balancing between many -+ * throttled threads: we don't want them all piling up on inode_sync_wait. -+ */ -+-static void -+-sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc) -++void generic_sync_sb_inodes(struct super_block *sb, -++ struct writeback_control *wbc) -+ { -+ const unsigned long start = jiffies; /* livelock avoidance */ -+ -++ spin_lock(&inode_lock); -+ if (!wbc->for_kupdate || list_empty(&sb->s_io)) -+ queue_io(sb, wbc->older_than_this); -+ -+@@ -482,8 +481,16 @@ -+ if (wbc->nr_to_write <= 0) -+ break; -+ } -++ spin_unlock(&inode_lock); -+ return; /* Leave any unwritten inodes on s_io */ -+ } -++EXPORT_SYMBOL_GPL(generic_sync_sb_inodes); -++ -++static void sync_sb_inodes(struct super_block *sb, -++ struct writeback_control *wbc) -++{ -++ generic_sync_sb_inodes(sb, wbc); -++} -+ -+ /* -+ * Start writeback of dirty pagecache data against all unlocked inodes. -+@@ -524,11 +531,8 @@ -+ * be unmounted by the time it is released. -+ */ -+ if (down_read_trylock(&sb->s_umount)) { -+- if (sb->s_root) { -+- spin_lock(&inode_lock); -++ if (sb->s_root) -+ sync_sb_inodes(sb, wbc); -+- spin_unlock(&inode_lock); -+- } -+ up_read(&sb->s_umount); -+ } -+ spin_lock(&sb_lock); -+@@ -566,9 +570,7 @@ -+ (inodes_stat.nr_inodes - inodes_stat.nr_unused) + -+ nr_dirty + nr_unstable; -+ wbc.nr_to_write += wbc.nr_to_write / 2; /* Bit more for luck */ -+- spin_lock(&inode_lock); -+ sync_sb_inodes(sb, &wbc); -+- spin_unlock(&inode_lock); -+ } -+ -+ /* -+diff -urN linux-2.6.24.7.old/fs/ubifs/Kconfig linux-2.6.24.7/fs/ubifs/Kconfig -+--- linux-2.6.24.7.old/fs/ubifs/Kconfig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,71 @@ -++config UBIFS_FS -++ tristate "UBIFS file system support" -++ select CRC16 -++ select CRC32 -++ depends on MTD_UBI -++ help -++ UBIFS is a file system for flash devices which works on top of UBI. -++ -++config UBIFS_FS_XATTR -++ bool "Extended attributes support" -++ depends on UBIFS_FS -++ help -++ This option enables support of extended attributes. -++ -++config UBIFS_FS_ADVANCED_COMPR -++ bool "Advanced compression options" -++ depends on UBIFS_FS -++ help -++ This option allows to explicitly choose which compressions, if any, -++ are enabled in UBIFS. Removing compressors means inbility to read -++ existing file systems. -++ -++ If unsure, say 'N'. -++ -++config UBIFS_FS_LZO -++ bool "LZO compression support" if UBIFS_FS_ADVANCED_COMPR -++ select CRYPTO -++ select CRYPTO_LZO -++ depends on UBIFS_FS -++ default y -++ help -++ LZO compressor is generally faster then zlib but compresses worse. -++ Say 'Y' if unsure. -++ -++config UBIFS_FS_ZLIB -++ bool "ZLIB compression support" if UBIFS_FS_ADVANCED_COMPR -++ select CRYPTO -++ select CRYPTO_DEFLATE -++ depends on UBIFS_FS -++ default y -++ help -++ Zlib copresses better then LZO but it is slower. Say 'Y' if unsure. -++ -++# Debugging-related stuff -++config UBIFS_FS_DEBUG -++ bool "Enable debugging" -++ depends on UBIFS_FS -++ select DEBUG_FS -++ select KALLSYMS_ALL -++ help -++ This option enables UBIFS debugging. -++ -++config UBIFS_FS_DEBUG_MSG_LVL -++ int "Default message level (0 = no extra messages, 3 = lots)" -++ depends on UBIFS_FS_DEBUG -++ default "0" -++ help -++ This controls the amount of debugging messages produced by UBIFS. -++ If reporting bugs, please try to have available a full dump of the -++ messages at level 1 while the misbehaviour was occurring. Level 2 -++ may become necessary if level 1 messages were not enough to find the -++ bug. Generally Level 3 should be avoided. -++ -++config UBIFS_FS_DEBUG_CHKS -++ bool "Enable extra checks" -++ depends on UBIFS_FS_DEBUG -++ help -++ If extra checks are enabled UBIFS will check the consistency of its -++ internal data structures during operation. However, UBIFS performance -++ is dramatically slower when this option is selected especially if the -++ file system is large. -+diff -urN linux-2.6.24.7.old/fs/ubifs/Kconfig.debug linux-2.6.24.7/fs/ubifs/Kconfig.debug -+--- linux-2.6.24.7.old/fs/ubifs/Kconfig.debug 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/Kconfig.debug 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,173 @@ -++# UBIFS debugging configuration options, part of fs/ubifs/Kconfig -++ -++config UBIFS_FS_DEBUG -++ bool "Enable debugging" -++ default n -++ depends on UBIFS_FS -++ select DEBUG_FS -++ select KALLSYMS_ALL -++ help -++ This option enables UBIFS debugging. -++ -++menu "Debugging messages" -++ depends on UBIFS_FS_DEBUG -++ -++config UBIFS_FS_DEBUG_MSG_GEN -++ bool "General messages" -++ default n -++ help -++ This option enables general debugging messages. -++ -++config UBIFS_FS_DEBUG_MSG_JRN -++ bool "Journal messages" -++ default n -++ help -++ This option enables detailed journal debugging messages. -++ -++config UBIFS_FS_DEBUG_MSG_CMT -++ bool "Commit messages" -++ default n -++ help -++ This option enables detailed journal commit debugging messages. -++ -++config UBIFS_FS_DEBUG_MSG_BUDG -++ bool "Budgeting messages" -++ default n -++ help -++ This option enables detailed budgeting debugging messages. -++ -++config UBIFS_FS_DEBUG_MSG_LOG -++ bool "Log messages" -++ default n -++ help -++ This option enables detailed journal log debugging messages. -++ -++config UBIFS_FS_DEBUG_MSG_TNC -++ bool "Tree Node Cache (TNC) messages" -++ default n -++ help -++ This option enables detailed TNC debugging messages. -++ -++config UBIFS_FS_DEBUG_MSG_LP -++ bool "LEB properties (lprops) messages" -++ default n -++ help -++ This option enables detailed lprops debugging messages. -++ -++config UBIFS_FS_DEBUG_MSG_FIND -++ bool "LEB search messages" -++ default n -++ help -++ This option enables detailed LEB search debugging messages. -++ -++config UBIFS_FS_DEBUG_MSG_MNT -++ bool "Mount messages" -++ default n -++ help -++ This option enables detailed mount debugging messages, including -++ recovery messages. -++ -++config UBIFS_FS_DEBUG_MSG_IO -++ bool "Input/output messages" -++ default n -++ help -++ This option enables detailed I/O debugging messages. -++ -++config UBIFS_FS_DEBUG_MSG_GC -++ bool "Garbage collection messages" -++ default n -++ help -++ This option enables detailed garbage collection debugging messages. -++ -++config UBIFS_FS_DEBUG_MSG_SCAN -++ bool "Scan messages" -++ default n -++ help -++ This option enables detailed scan debugging messages. -++ -++endmenu -++ -++menu "Extra self-checks" -++ depends on UBIFS_FS_DEBUG -++ -++config UBIFS_FS_DEBUG_CHK_MEMPRESS -++ bool "Create memory pressure" -++ default n -++ depends on UBIFS_FS_DEBUG -++ help -++ This option causes kernel memory pressure in order to make TNC shrinker -++ run. -++ -++config UBIFS_FS_DEBUG_CHK_LPROPS -++ bool "Check LEB properties (lprops)" -++ default n -++ depends on UBIFS_FS_DEBUG -++ help -++ This option enables a function which runs during journal commit and -++ checks that the dirty and free space is correct for every LEB. Note, -++ this option makes UBIFS scan whole media before each commit which is -++ very slow. -++ -++config UBIFS_FS_DEBUG_CHK_TNC -++ bool "Check Tree Node Cache (TNC)" -++ default n -++ depends on UBIFS_FS_DEBUG -++ help -++ This option enables a function which runs after every -++ TNC insert / delete and checks that the TNC nodes are correct. -++ -++config UBIFS_FS_DEBUG_CHK_ORPH -++ bool "Check orphan area" -++ default n -++ depends on UBIFS_FS_DEBUG -++ help -++ This option enables a function which runs during journal commit and -++ checks that the orphan area is correct. -++ -++config UBIFS_FS_DEBUG_CHK_IDX_SZ -++ bool "Check indexing tree size" -++ default n -++ depends on UBIFS_FS_DEBUG -++ help -++ This option enables checking of the znode size accounting variables. -++ -++config UBIFS_FS_DEBUG_CHK_OLD_IDX -++ bool "Check old indexing tree" -++ default n -++ depends on UBIFS_FS_DEBUG -++ help -++ This option enables checking of the old indexing tree which must be -++ intact to allow recovery in the event of an unclean unmount. -++ -++config UBIFS_FS_DEBUG_CHK_OTHER -++ bool "Other checks" -++ default n -++ depends on UBIFS_FS_DEBUG -++ help -++ This option enables different checks which are light-weight and do not -++ affect file-system performance too much. -++ -++endmenu -++ -++config UBIFS_FS_DEBUG_FORCE_IN_THE_GAPS -++ bool "Force in-the-gaps commit method" -++ default n -++ depends on UBIFS_FS_DEBUG -++ help -++ This option makes UBIFS use the in-the-gap commit method much more -++ often than it is normally used (normally it is used only as fall-back -++ method when there is no space to do the "normal" commit method). It -++ is useful to run tests with this option enabled from time to time -++ because it may reveal UBIFS bugs which would otherwise be really -++ difficult to hit. -++ -++config UBIFS_FS_DEBUG_TEST_RCVRY -++ bool "Simulate random device removal (recovery testing)" -++ default n -++ depends on UBIFS_FS_DEBUG -++ help -++ This option provides the ability to test recovery from unclean -++ unmounts. It causes UBIFS to simulate device removal. At a some -++ random point UBIFS will switch to "failure mode" after which all I/O -++ operations will fail. UBIFS can then be unmounted and mounted again -++ at which point "failure mode" is switched off and recovery ensues. -+diff -urN linux-2.6.24.7.old/fs/ubifs/Makefile linux-2.6.24.7/fs/ubifs/Makefile -+--- linux-2.6.24.7.old/fs/ubifs/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,9 @@ -++obj-$(CONFIG_UBIFS_FS) += ubifs.o -++ -++ubifs-y += shrinker.o journal.o file.o dir.o super.o sb.o io.o -++ubifs-y += tnc.o master.o scan.o replay.o log.o commit.o gc.o orphan.o -++ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o -++ubifs-y += recovery.o ioctl.o compat.o lpt_commit.o tnc_misc.o -++ -++ubifs-$(CONFIG_UBIFS_FS_DEBUG) += debug.o -++ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o -+diff -urN linux-2.6.24.7.old/fs/ubifs/budget.c linux-2.6.24.7/fs/ubifs/budget.c -+--- linux-2.6.24.7.old/fs/ubifs/budget.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/budget.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,871 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Adrian Hunter -++ * Artem Bityutskiy (Битюцкий Ðртём) -++ */ -++ -++/* -++ * This file implements the budgeting unit which is responsible for UBIFS space -++ * management. -++ * -++ * Factors such as compression, wasted space at the ends of LEBs, space in other -++ * journal heads, the effect of updates on the index, and so on, make it -++ * impossible to accurately predict the amount of space needed. Consequently -++ * approximations are used. -++ */ -++ -++#include "ubifs.h" -++#include -++#include -++ -++/* -++ * When pessimistic budget calculations say that there is no enough space, -++ * UBIFS starts writing back dirty inodes and pages, doing garbage collection, -++ * or committing. The below constants define maximum number of times UBIFS -++ * repeats the operations. -++ */ -++#define MAX_SHRINK_RETRIES 8 -++#define MAX_GC_RETRIES 4 -++#define MAX_CMT_RETRIES 2 -++#define MAX_NOSPC_RETRIES 1 -++ -++/* -++ * The below constant defines amount of dirty pages which should be written -++ * back at when trying to shrink the liability. -++ */ -++#define NR_TO_WRITE 16 -++ -++/** -++ * struct retries_info - information about re-tries while making free space. -++ * @prev_liability: previous liability -++ * @shrink_cnt: how many times the liability was shrinked -++ * @shrink_retries: count of liability shrink re-tries (increased when -++ * liability does not shrink) -++ * @try_gc: GC should be tried first -++ * @gc_retries: how many times GC was run -++ * @cmt_retries: how many times commit has been done -++ * @nospc_retries: how many times GC returned %-ENOSPC -++ * -++ * Since we consider budgeting to be the fast-path, and this structure has to -++ * be allocated on stack and zeroed out, we make it smaller using bit-fields. -++ */ -++struct retries_info { -++ long long prev_liability; -++ unsigned int shrink_cnt; -++ unsigned int shrink_retries:5; -++ unsigned int try_gc:1; -++ unsigned int gc_retries:4; -++ unsigned int cmt_retries:3; -++ unsigned int nospc_retries:1; -++}; -++ -++/* TODO: remove compatibility stuff as late as possible */ -++#ifndef UBIFS_COMPAT_USE_OLD_PREPARE_WRITE -++/** -++ * shrink_liability - write-back some dirty pages/inodes. -++ * @c: UBIFS file-system description object -++ * @nr_to_write: how many dirty pages to write-back -++ * -++ * This function shrinks UBIFS liability by means of writing back some amount -++ * of dirty inodes and their pages. Returns the amount of pages which were -++ * written back. The returned value does not include dirty inodes which were -++ * synchronized. -++ * -++ * Note, this function synchronizes even VFS inodes which are locked -++ * (@i_mutex) by the caller of the budgeting function, because write-back does -++ * not touch @i_mutex. -++ */ -++static int shrink_liability(struct ubifs_info *c, int nr_to_write) -++{ -++ struct writeback_control wbc = { -++ .sync_mode = WB_SYNC_NONE, -++ .range_end = LLONG_MAX, -++ .nr_to_write = nr_to_write, -++ }; -++ -++ generic_sync_sb_inodes(c->vfs_sb, &wbc); -++ dbg_budg("%ld pages were written back", nr_to_write - wbc.nr_to_write); -++ return nr_to_write - wbc.nr_to_write; -++} -++ -++ -++/** -++ * run_gc - run garbage collector. -++ * @c: UBIFS file-system description object -++ * -++ * This function runs garbage collector to make some more free space. Returns -++ * zero if a free LEB has been produced, %-EAGAIN if commit is required, and a -++ * negative error code in case of failure. -++ */ -++static int run_gc(struct ubifs_info *c) -++{ -++ int err, lnum; -++ -++ /* Make some free space by garbage-collecting dirty space */ -++ down_read(&c->commit_sem); -++ lnum = ubifs_garbage_collect(c, 1); -++ up_read(&c->commit_sem); -++ if (lnum < 0) -++ return lnum; -++ -++ /* GC freed one LEB, return it to lprops */ -++ dbg_budg("GC freed LEB %d", lnum); -++ err = ubifs_return_leb(c, lnum); -++ if (err) -++ return err; -++ -++ return 0; -++} -++ -++/** -++ * make_free_space - make more free space on the file-system. -++ * @c: UBIFS file-system description object -++ * @ri: information about previous invocations of this function -++ * -++ * This function is called when an operation cannot be budgeted because there -++ * is supposedly no free space. But in most cases there is some free space: -++ * o budgeting is pessimistic, so it always budgets more then it is actually -++ * needed, so shrinking the liability is one way to make free space - the -++ * cached data will take less space then it was budgeted for; -++ * o GC may turn some dark space into free space (budgeting treats dark space -++ * as not available); -++ * o commit may free some LEB, i.e., turn freeable LEBs into free LEBs. -++ * -++ * So this function tries to do the above. Returns %-EAGAIN if some free space -++ * was presumably made and the caller has to re-try budgeting the operation. -++ * Returns %-ENOSPC if it couldn't do more free space, and other negative error -++ * codes on failures. -++ */ -++static int make_free_space(struct ubifs_info *c, struct retries_info *ri) -++{ -++ int err; -++ -++ /* -++ * If we have some dirty pages and inodes (liability), try to write -++ * them back unless this was tried too many times without effect -++ * already. -++ */ -++ if (ri->shrink_retries < MAX_SHRINK_RETRIES && !ri->try_gc) { -++ long long liability; -++ -++ spin_lock(&c->space_lock); -++ liability = c->budg_idx_growth + c->budg_data_growth + -++ c->budg_dd_growth; -++ spin_unlock(&c->space_lock); -++ -++ if (ri->prev_liability >= liability) { -++ /* Liability does not shrink, next time try GC then */ -++ ri->shrink_retries += 1; -++ if (ri->gc_retries < MAX_GC_RETRIES) -++ ri->try_gc = 1; -++ dbg_budg("liability did not shrink: retries %d of %d", -++ ri->shrink_retries, MAX_SHRINK_RETRIES); -++ } -++ -++ dbg_budg("force write-back (count %d)", ri->shrink_cnt); -++ shrink_liability(c, NR_TO_WRITE + ri->shrink_cnt); -++ -++ ri->prev_liability = liability; -++ ri->shrink_cnt += 1; -++ return -EAGAIN; -++ } -++ -++ /* -++ * Try to run garbage collector unless it was already tried too many -++ * times. -++ */ -++ if (ri->gc_retries < MAX_GC_RETRIES) { -++ ri->gc_retries += 1; -++ dbg_budg("run GC, retries %d of %d", -++ ri->gc_retries, MAX_GC_RETRIES); -++ -++ ri->try_gc = 0; -++ err = run_gc(c); -++ if (!err) -++ return -EAGAIN; -++ -++ if (err == -EAGAIN) { -++ dbg_budg("GC asked to commit"); -++ err = ubifs_run_commit(c); -++ if (err) -++ return err; -++ return -EAGAIN; -++ } -++ -++ if (err != -ENOSPC) -++ return err; -++ -++ /* -++ * GC could not make any progress. If this is the first time, -++ * then it makes sense to try to commit, because it might make -++ * some dirty space. -++ */ -++ dbg_budg("GC returned -ENOSPC, retries %d", -++ ri->nospc_retries); -++ if (ri->nospc_retries >= MAX_NOSPC_RETRIES) -++ return err; -++ ri->nospc_retries += 1; -++ } -++ -++ /* Neither GC nor write-back helped, try to commit */ -++ if (ri->cmt_retries < MAX_CMT_RETRIES) { -++ ri->cmt_retries += 1; -++ dbg_budg("run commit, retries %d of %d", -++ ri->cmt_retries, MAX_CMT_RETRIES); -++ err = ubifs_run_commit(c); -++ if (err) -++ return err; -++ return -EAGAIN; -++ } -++ -++ return -ENOSPC; -++} -++#endif /* UBIFS_COMPAT_USE_OLD_PREPARE_WRITE */ -++ -++/** -++ * ubifs_calc_min_idx_lebs - calculate amount of eraseblocks for the index. -++ * @c: UBIFS file-system description object -++ * -++ * This function calculates and returns the number of eraseblocks which should -++ * be kept for index usage. -++ */ -++int ubifs_calc_min_idx_lebs(struct ubifs_info *c) -++{ -++ int ret; -++ uint64_t idx_size; -++ -++ idx_size = c->old_idx_sz + c->budg_idx_growth + c->budg_uncommitted_idx; -++ -++ /* And make sure we have twice the index size of space reserved */ -++ idx_size <<= 1; -++ -++ /* -++ * We do not maintain 'old_idx_size' as 'old_idx_lebs'/'old_idx_bytes' -++ * pair, nor similarly the two variables for the new index size, so we -++ * have to do this costly 64-bit division on fast-path. -++ */ -++ if (do_div(idx_size, c->leb_size - c->max_idx_node_sz)) -++ ret = idx_size + 1; -++ else -++ ret = idx_size; -++ /* -++ * The index head is not available for the in-the-gaps method, so add an -++ * extra LEB to compensate. -++ */ -++ ret += 1; -++ /* -++ * At present the index needs at least 2 LEBs: one for the index head -++ * and one for in-the-gaps method (which currently does not cater for -++ * the index head and so excludes it from consideration). -++ */ -++ if (ret < 2) -++ ret = 2; -++ return ret; -++} -++ -++/** -++ * ubifs_calc_available - calculate available FS space. -++ * @c: UBIFS file-system description object -++ * -++ * This function calculates and returns amount of FS space available for use. -++ */ -++long long ubifs_calc_available(const struct ubifs_info *c) -++{ -++ long long available, subtract_lebs; -++ -++ /* -++ * Force the amount available to the total size reported if the used -++ * space is zero. -++ */ -++ if (c->lst.total_used <= UBIFS_INO_NODE_SZ && -++ c->budg_data_growth + c->budg_dd_growth == 0) { -++ /* Do the same calculation as for c->block_cnt */ -++ available = c->main_lebs - 2; -++ available *= c->leb_size - c->dark_wm; -++ return available; -++ } -++ -++ available = c->main_bytes - c->lst.total_used; -++ -++ /* -++ * Now 'available' contains theoretically available flash space -++ * assuming there is no index, so we have to subtract the space which -++ * is reserved for the index. -++ */ -++ subtract_lebs = c->min_idx_lebs; -++ -++ /* Take into account that GC reserves one LEB for its own needs */ -++ subtract_lebs += 1; -++ -++ /* -++ * The GC journal head LEB is not really accessible. And since -++ * different write types go to different heads, we may count only on -++ * one head's space. -++ */ -++ subtract_lebs += c->jhead_cnt - 1; -++ -++ /* We also reserve one LEB for deletions, which bypass budgeting */ -++ subtract_lebs += 1; -++ -++ available -= subtract_lebs * c->leb_size; -++ -++ /* Subtract the dead space which is not available for use */ -++ available -= c->lst.total_dead; -++ -++ /* -++ * Subtract dark space, which might or might not be usable - it depends -++ * on the data which we have on the media and which will be written. If -++ * this is a lot of uncompressed or not-compressible data, the dark -++ * space cannot be used. -++ */ -++ available -= c->lst.total_dark; -++ -++ /* -++ * However, there is more dark space. The index may be bigger than -++ * min_idx_lebs. Those extra LEBs are assumed to be available, but -++ * their dark space is not included in total_dark, so it is subtracted -++ * here. -++ */ -++ if (c->lst.idx_lebs > c->min_idx_lebs) { -++ subtract_lebs = c->lst.idx_lebs - c->min_idx_lebs; -++ available -= subtract_lebs * c->dark_wm; -++ } -++ -++ return available; -++} -++ -++/** -++ * rp_can_write - check whether the user is allowed to write. -++ * @c: UBIFS file-system description object -++ * @avail: available space on FS -++ * -++ * UBIFS has so-called "reserved pool" which is flash space reserved -++ * for the superuser and for uses whose UID/GID is recorded in UBIFS superblock. -++ * This function checks whether current user is allowed to write -++ * to the file-system - it returns %1 if there is plenty of space or the user -++ * is eligible to use the reserved pool and %0 otherwise. -++ */ -++static int rp_can_write(struct ubifs_info *c, long long avail) -++{ -++ if (avail > c->rp_size || current->fsuid == c->rp_uid || -++ capable(CAP_SYS_RESOURCE) || -++ (c->rp_gid != 0 && in_group_p(c->rp_gid))) -++ return 1; -++ -++ return 0; -++} -++ -++/** -++ * do_budget_space - reserve flash space for index and data growth. -++ * @c: UBIFS file-system description object -++ * -++ * This function makes sure UBIFS has enough free eraseblocks for index growth -++ * and data. -++ * -++ * When budgeting index space, UBIFS reserves twice as more LEBs as the index -++ * would take if it was consolidated and written to the flash. This guarantees -++ * that the "in-the-gaps" commit method always succeeds and UBIFS will always -++ * be able to commit dirty index. So this function basically adds amount of -++ * budgeted index space to the size of the current index, multiplies this by 2, -++ * and makes sure this does not exceed the amount of free eraseblocks. -++ * -++ * Notes about @c->min_idx_lebs and @c->lst.idx_lebs variables: -++ * o @c->lst.idx_lebs is the number of LEBs the index currently uses. It might -++ * be large, because UBIFS does not do any index consolidation as long as -++ * there is free space. IOW, the index may take a lot of LEBs, but the LEBs -++ * will contain a lot of dirt. -++ * o @c->min_idx_lebs is the the index presumably takes. IOW, the index may be -++ * consolidated to take up to @c->min_idx_lebs LEBs. -++ * -++ * This function returns zero in case of success, and %-ENOSPC in case of -++ * failure. -++ */ -++static int do_budget_space(struct ubifs_info *c) -++{ -++ long long outstanding, available; -++ int lebs, rsvd_idx_lebs, min_idx_lebs; -++ -++ /* First budget index space */ -++ min_idx_lebs = ubifs_calc_min_idx_lebs(c); -++ -++ /* Now 'min_idx_lebs' contains number of LEBs to reserve */ -++ if (min_idx_lebs > c->lst.idx_lebs) -++ rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs; -++ else -++ rsvd_idx_lebs = 0; -++ -++ /* -++ * The number of LEBs that are available to be used by the index is: -++ * -++ * @c->lst.empty_lebs + @c->freeable_cnt + @c->idx_gc_cnt - -++ * @c->lst.taken_empty_lebs -++ * -++ * @empty_lebs are available because they are empty. @freeable_cnt are -++ * available because they contain only free and dirty space and the -++ * index allocation always occurs after wbufs are synch'ed. -++ * @idx_gc_cnt are available because they are index LEBs that have been -++ * garbage collected (including trivial GC) and are awaiting the commit -++ * before they can be unmapped - note that the in-the-gaps method will -++ * grab these if it needs them. @taken_empty_lebs are empty_lebs that -++ * have already been allocated for some purpose (also includes those -++ * LEBs on the @idx_gc list). -++ * -++ * Note, @taken_empty_lebs may temporarily be higher by one because of -++ * the way we serialize LEB allocations and budgeting. See a comment in -++ * 'ubifs_find_free_space()'. -++ */ -++ lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - -++ c->lst.taken_empty_lebs; -++ if (unlikely(rsvd_idx_lebs > lebs)) { -++ dbg_budg("out of indexing space: min_idx_lebs %d (old %d), " -++ "rsvd_idx_lebs %d", min_idx_lebs, c->min_idx_lebs, -++ rsvd_idx_lebs); -++ return -ENOSPC; -++ } -++ -++ available = ubifs_calc_available(c); -++ outstanding = c->budg_data_growth + c->budg_dd_growth; -++ -++ if (unlikely(available < outstanding)) { -++ dbg_budg("out of data space: available %lld, outstanding %lld", -++ available, outstanding); -++ return -ENOSPC; -++ } -++ -++ if (!rp_can_write(c, available - outstanding)) -++ return -ENOSPC; -++ -++ c->min_idx_lebs = min_idx_lebs; -++ return 0; -++} -++ -++/** -++ * calc_idx_growth - calculate approximate index growth from budgeting request. -++ * @c: UBIFS file-system description object -++ * @req: budgeting request -++ * -++ * For now we assume each new node adds one znode. But this is rather poor -++ * approximation, though. -++ */ -++static int calc_idx_growth(const struct ubifs_info *c, -++ const struct ubifs_budget_req *req) -++{ -++ int znodes; -++ -++ znodes = req->new_ino + (req->new_page << UBIFS_BLOCKS_PER_PAGE_SHIFT) + -++ req->new_dent; -++ return znodes * c->max_idx_node_sz; -++} -++ -++/** -++ * calc_data_growth - calculate approximate amount of new data from budgeting -++ * request. -++ * @c: UBIFS file-system description object -++ * @req: budgeting request -++ */ -++static int calc_data_growth(const struct ubifs_info *c, -++ const struct ubifs_budget_req *req) -++{ -++ int data_growth; -++ -++ data_growth = req->new_ino ? c->inode_budget : 0; -++ if (req->new_page) -++ data_growth += c->page_budget; -++ if (req->new_dent) -++ data_growth += c->dent_budget; -++ data_growth += req->new_ino_d; -++ -++ return data_growth; -++} -++ -++/** -++ * calc_dd_growth - calculate approximate amount of data which makes other data -++ * dirty from budgeting request. -++ * @c: UBIFS file-system description object -++ * @req: budgeting request -++ */ -++static int calc_dd_growth(const struct ubifs_info *c, -++ const struct ubifs_budget_req *req) -++{ -++ int dd_growth; -++ -++ dd_growth = req->dirtied_page ? c->page_budget : 0; -++ -++ if (req->dirtied_ino) -++ dd_growth += c->inode_budget << (req->dirtied_ino - 1); -++ if (req->mod_dent) -++ dd_growth += c->dent_budget; -++ dd_growth += req->dirtied_ino_d; -++ -++ return dd_growth; -++} -++ -++/** -++ * ubifs_budget_space - ensure there is enough space to complete an operation. -++ * @c: UBIFS file-system description object -++ * @req: budget request -++ * -++ * This function allocates budget for an operation. It uses pessimistic -++ * approximation of how much flash space the operation needs. The goal of this -++ * function is to make sure UBIFS always has flash space to flush all dirty -++ * pages, dirty inodes, and dirty znodes (liability). This function may force -++ * commit, garbage-collection or write-back. Returns zero in case of success, -++ * %-ENOSPC if there is no free space and other negative error codes in case of -++ * failures. -++ */ -++int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req) -++{ -++ int uninitialized_var(cmt_retries), uninitialized_var(wb_retries); -++ int err, idx_growth, data_growth, dd_growth; -++ struct retries_info ri; -++ -++ data_growth = calc_data_growth(c, req); -++ dd_growth = calc_dd_growth(c, req); -++ if (!data_growth && !dd_growth) -++ return 0; -++ idx_growth = calc_idx_growth(c, req); -++ memset(&ri, 0, sizeof(struct retries_info)); -++ -++again: -++ spin_lock(&c->space_lock); -++ ubifs_assert(c->budg_idx_growth >= 0); -++ ubifs_assert(c->budg_data_growth >= 0); -++ ubifs_assert(c->budg_dd_growth >= 0); -++ -++ c->budg_idx_growth += idx_growth; -++ c->budg_data_growth += data_growth; -++ c->budg_dd_growth += dd_growth; -++ -++ err = do_budget_space(c); -++ if (unlikely(err)) { -++ /* Restore the old values */ -++ c->budg_idx_growth -= idx_growth; -++ c->budg_data_growth -= data_growth; -++ c->budg_dd_growth -= dd_growth; -++ spin_unlock(&c->space_lock); -++ -++ goto make_space; -++ } -++ -++ req->idx_growth = idx_growth; -++ req->data_growth = data_growth; -++ req->dd_growth = dd_growth; -++ spin_unlock(&c->space_lock); -++ -++ return 0; -++ -++make_space: -++/* TODO: remove compatibility stuff as late as possible */ -++#ifdef UBIFS_COMPAT_USE_OLD_PREPARE_WRITE -++ err = ubifs_make_free_space(c, &ri, req->locked_pg); -++#else -++ err = make_free_space(c, &ri); -++#endif -++ -++ if (err == -EAGAIN) { -++ dbg_budg("try again"); -++ cond_resched(); -++ goto again; -++ } else if (err == -ENOSPC) -++ dbg_budg("FS is full, -ENOSPC"); -++ else -++ ubifs_err("cannot budget space, error %d", err); -++ -++ return err; -++} -++ -++/** -++ * ubifs_release_budget - release budgeted free space. -++ * @c: UBIFS file-system description object -++ * @req: budget request -++ * -++ * This function releases the space budgeted by 'ubifs_budget_space()'. Note, -++ * since the index changes (which were budgeted for in @req->idx_growth) will -++ * only be written to the media on commit, this function moves the index budget -++ * from @c->budg_idx_growth to @c->budg_uncommitted_idx. The latter will be -++ * zeroed by the commit operation. -++ */ -++void ubifs_release_budget(struct ubifs_info *c, struct ubifs_budget_req *req) -++{ -++ if (!req->data_growth && !req->dd_growth) -++ return; -++ -++ if (req->idx_growth == -1) -++ req->idx_growth = calc_idx_growth(c, req); -++ -++ spin_lock(&c->space_lock); -++ c->budg_idx_growth -= req->idx_growth; -++ c->budg_uncommitted_idx += req->idx_growth; -++ c->budg_data_growth -= req->data_growth; -++ c->budg_dd_growth -= req->dd_growth; -++ c->min_idx_lebs = ubifs_calc_min_idx_lebs(c); -++ -++ ubifs_assert(c->budg_idx_growth >= 0); -++ ubifs_assert(c->budg_data_growth >= 0); -++ ubifs_assert(c->min_idx_lebs < c->main_lebs); -++ spin_unlock(&c->space_lock); -++} -++ -++/** -++ * ubifs_convert_page_budget - convert budget of a new page. -++ * @c: UBIFS file-system description object -++ * -++ * This function converts budget which was allocated for a new page of data to -++ * the budget of changing an existing page of data. The latter is not larger -++ * then the former, so this function only does simple re-calculation and does -++ * not involve any write-back. -++ */ -++void ubifs_convert_page_budget(struct ubifs_info *c) -++{ -++ spin_lock(&c->space_lock); -++ /* Release the index growth reservation */ -++ c->budg_idx_growth -= c->max_idx_node_sz << UBIFS_BLOCKS_PER_PAGE_SHIFT; -++ /* Release the data growth reservation */ -++ c->budg_data_growth -= c->page_budget; -++ /* Increase the dirty data growth reservation instead */ -++ c->budg_dd_growth += c->page_budget; -++ /* And re-calculate the indexing space reservation */ -++ c->min_idx_lebs = ubifs_calc_min_idx_lebs(c); -++ spin_unlock(&c->space_lock); -++} -++ -++/** -++ * ubifs_budget_inode_op - budget an operation on inode. -++ * @c: UBIFS file-system description object -++ * @inode: VFS inode which will be made dirty by the operation -++ * @req: budget request of the operation -++ * -++ * This function is called to get budget for an operation which changes an -++ * inode. The inode may be in dirty or clean state. The former means there is -++ * no need to allocate the budget as it has already been allocated before. The -++ * latter means that the inode change budget has to be allocated. -++ * -++ * The caller has to pass the inode which is going to be changed. This function -++ * acquires budget the for as described in @req plus the budget for changing -++ * the inode dirty, if needed. Returns zero in case of success, %-ENOSPC if -++ * there is no more flash space, and other negative error codes in case of -++ * failure. -++ * -++ * Note, upon exit, this function leaves the inode locked, and the -++ * 'ubifs_release_ino_dirty()' or 'ubifs_release_ino_clean()' function has to -++ * be called to unlock it. -++ */ -++int ubifs_budget_inode_op(struct ubifs_info *c, struct inode *inode, -++ struct ubifs_budget_req *req) -++{ -++ struct ubifs_inode *ui = ubifs_inode(inode); -++ int err, old = req->dirtied_ino; -++ -++ ubifs_assert(req->dirtied_ino <= 3); -++ ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 3); -++ -++again: -++ /* -++ * If the inode is clean, it will be dirtied by this operation and we -++ * have to budget for this. -++ */ -++ req->dirtied_ino += !ui->dirty; -++ if (req->dirtied_ino > old) -++ req->dirtied_ino_d += ui->data_len; -++ -++ /* -++ * Note, if the budget request does not actually request anything -++ * (i.e., @req contains only zeroes), 'ubifs_budget_space()' will -++ * return almost straight away. -++ */ -++ err = ubifs_budget_space(c, req); -++ if (unlikely(err)) -++ return err; -++ -++ mutex_lock(&ui->budg_mutex); -++ -++ if (req->dirtied_ino != old + !ui->dirty) { -++ /* The inode has probably been written back meanwhile */ -++ ubifs_release_budget(c, req); -++ mutex_unlock(&ui->budg_mutex); -++ req->dirtied_ino = old; -++ req->dirtied_ino_d -= ui->data_len; -++ goto again; -++ } -++ -++ UBIFS_DBG(ui->budgeted = 1); -++ return 0; -++} -++ -++/** -++ * ubifs_release_ino_dirty - release budget of a "dirtying" operation. -++ * @c: UBIFS file-system description object -++ * @inode: VFS inode the operation worked on -++ * @req: budget to release -++ * -++ * This function has to be called at the end of VFS operations which acquired -++ * budget via 'ubifs_budget_inode_op()'. It assumes that the inode has been -++ * marked as dirty and will be synchronized later by write-back, so it does not -++ * release the budget of the inode. -++ * -++ * Note, this function also avoids releasing page budgets which are released -++ * separately. -++ */ -++void ubifs_release_ino_dirty(struct ubifs_info *c, struct inode *inode, -++ struct ubifs_budget_req *req) -++{ -++ ubifs_assert(req->dirtied_ino <= 4); -++ ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4); -++ ubifs_assert(req->idx_growth >= 0); -++ ubifs_assert(req->data_growth >= 0); -++ ubifs_assert(req->dd_growth >= 0); -++ -++ if (req->dirtied_ino) { -++ req->dd_growth -= c->inode_budget; -++ req->dd_growth -= req->dirtied_ino_d; -++ } -++ -++ if (req->dirtied_page) { -++ req->dd_growth -= c->page_budget; -++ ubifs_assert(req->new_page == 0); -++ } else if (req->new_page) { -++ req->idx_growth -= -++ c->max_idx_node_sz << UBIFS_BLOCKS_PER_PAGE_SHIFT; -++ req->data_growth -= c->page_budget; -++ ubifs_assert(req->dirtied_page == 0); -++ } -++ -++ ubifs_assert(req->dd_growth >= 0); -++ ubifs_release_budget(c, req); -++ mutex_unlock(&ubifs_inode(inode)->budg_mutex); -++} -++ -++/** -++ * ubifs_cancel_ino_op - cancel budget of an operation on inode. -++ * @c: UBIFS file-system description object -++ * @inode: VFS inode the operation worked on -++ * @req: budget to release -++ * -++ * This function has to be called if the operation failed and whole budget has -++ * to be released, including the budget for inode which would had been -++ * dirtied. It is important not to mark the inode dirty before calling this -++ * function. -++ */ -++void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode, -++ struct ubifs_budget_req *req) -++{ -++ ubifs_assert(req->dirtied_ino <= 4); -++ ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4); -++ ubifs_assert(req->idx_growth >= 0); -++ ubifs_assert(req->data_growth >= 0); -++ ubifs_assert(req->dd_growth >= 0); -++ -++ ubifs_release_budget(c, req); -++ mutex_unlock(&ubifs_inode(inode)->budg_mutex); -++} -++ -++/** -++ * ubifs_release_ino_clean - release budget of a "cleaning" operation. -++ * @c: UBIFS file-system description object -++ * @inode: VFS inode the operation worked on -++ * @req: budget to release -++ * -++ * This function has to be called at the end of VFS operations which acquired -++ * budget via 'ubifs_budget_inode_op()'. It assumed the operation synchronized -++ * the inode, so it marks the inode clean, unlocks it and releases whole budget. -++ * -++ * Note, this function also avoids releasing page budgets which are released -++ * separately. -++ */ -++void ubifs_release_ino_clean(struct ubifs_info *c, struct inode *inode, -++ struct ubifs_budget_req *req) -++{ -++ struct ubifs_inode *ui = ubifs_inode(inode); -++ -++ ubifs_assert(req->dirtied_ino <= 4); -++ ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4); -++ ubifs_assert(req->idx_growth >= 0); -++ ubifs_assert(req->data_growth >= 0); -++ ubifs_assert(req->dd_growth >= 0); -++ ubifs_assert(!req->dirtied_page); -++ ubifs_assert(!req->new_page); -++ UBIFS_DBG(ui->budgeted = 0); -++ -++ ubifs_release_budget(c, req); -++ if (ui->dirty) { -++ ui->dirty = 0; -++ /* -++ * Note, VFS still treats the inode as dirty and -++ * 'ubifs_write_inode()' will be called, but it'll do nothing -++ * because @ui->dirty is %0. -++ */ -++ atomic_long_dec(&c->dirty_ino_cnt); -++ } -++ mutex_unlock(&ubifs_inode(inode)->budg_mutex); -++} -++ -++/** -++ * ubifs_release_new_page_budget - release budget of a new page. -++ * @c: UBIFS file-system description object -++ * -++ * This is a helper function which releases budget corresponding to the budget -++ * of one new page of data. -++ */ -++void ubifs_release_new_page_budget(struct ubifs_info *c) -++{ -++ struct ubifs_budget_req req = { .new_page = 1, -++ .idx_growth = -1, -++ .data_growth = c->page_budget }; -++ -++ ubifs_release_budget(c, &req); -++} -++ -++/** -++ * ubifs_budg_get_free_space - return amount of free space. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns amount of free space on the file-system. -++ */ -++long long ubifs_budg_get_free_space(struct ubifs_info *c) -++{ -++ int min_idx_lebs, rsvd_idx_lebs; -++ long long available, outstanding, free; -++ -++ /* Do exactly the same calculations as in 'do_budget_space()' */ -++ spin_lock(&c->space_lock); -++ min_idx_lebs = ubifs_calc_min_idx_lebs(c); -++ -++ if (min_idx_lebs > c->lst.idx_lebs) -++ rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs; -++ else -++ rsvd_idx_lebs = 0; -++ -++ if (rsvd_idx_lebs > c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt -++ - c->lst.taken_empty_lebs) { -++ spin_unlock(&c->space_lock); -++ return 0; -++ } -++ -++ c->min_idx_lebs = min_idx_lebs; -++ available = ubifs_calc_available(c); -++ outstanding = c->budg_data_growth + c->budg_dd_growth; -++ spin_unlock(&c->space_lock); -++ -++ if (available > outstanding) -++ free = ubifs_reported_space(c, available - outstanding); -++ else -++ free = 0; -++ -++ return free; -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/build.c linux-2.6.24.7/fs/ubifs/build.c -+--- linux-2.6.24.7.old/fs/ubifs/build.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/build.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1423 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* -++ * This file implements UBIFS initialization, mount and un-mount. Some -++ * initialization stuff which is rather large and complex is placed at -++ * corresponding subsystems, but most of it is here. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "ubifs.h" -++ -++/* Slab cache for UBIFS inodes */ -++struct kmem_cache *ubifs_inode_slab; -++ -++/* TODO: remove compatibility stuff as late as possible */ -++#ifndef UBIFS_COMPAT_NO_SHRINKER -++/* UBIFS TNC shrinker description */ -++static struct shrinker ubifs_shrinker_info = { -++ .shrink = ubifs_shrinker, -++ .seeks = DEFAULT_SEEKS, -++}; -++#endif -++ -++/** -++ * init_constants_early - initialize UBIFS constants. -++ * @c: UBIFS file-system description object -++ * -++ * This function initialize UBIFS constants which do not need the superblock to -++ * be read. It also checks that the UBI volume satisfies basic UBIFS -++ * requirements. Returns zero in case of success and a negative error code in -++ * case of failure. -++ */ -++static int init_constants_early(struct ubifs_info *c) -++{ -++ if (c->vi.corrupted) { -++ ubifs_warn("UBI volume is corrupted - read-only mode"); -++ c->ro_media = 1; -++ } -++ -++ if (c->di.ro_mode) { -++ ubifs_msg("read-only UBI device"); -++ c->ro_media = 1; -++ } -++ -++ if (c->vi.vol_type == UBI_STATIC_VOLUME) { -++ ubifs_msg("static UBI volume - read-only mode"); -++ c->ro_media = 1; -++ } -++ -++ c->leb_cnt = c->vi.size; -++ c->leb_size = c->vi.usable_leb_size; -++ c->half_leb_size = c->leb_size / 2; -++ c->min_io_size = c->di.min_io_size; -++ c->min_io_shift = fls(c->min_io_size) - 1; -++ -++ if (c->leb_size < UBIFS_MIN_LEB_SZ) { -++ ubifs_err("too small LEBs (%d bytes), min. is %d bytes", -++ c->leb_size, UBIFS_MIN_LEB_SZ); -++ return -EINVAL; -++ } -++ -++ if (c->leb_cnt < UBIFS_MIN_LEB_CNT) { -++ ubifs_err("too few LEBs (%d), min. is %d", -++ c->leb_cnt, UBIFS_MIN_LEB_CNT); -++ return -EINVAL; -++ } -++ -++ if (!is_power_of_2(c->min_io_size)) { -++ ubifs_err("bad min. I/O size %d", c->min_io_size); -++ return -EINVAL; -++ } -++ -++ /* -++ * UBIFS aligns all node to 8-byte boundary, so to make function in -++ * io.c simpler, assume minimum I/O unit size to be 8 bytes if it is -++ * less than 8. -++ */ -++ if (c->min_io_size < 8) { -++ c->min_io_size = 8; -++ c->min_io_shift = 3; -++ } -++ -++ c->ref_node_alsz = ALIGN(UBIFS_REF_NODE_SZ, c->min_io_size); -++ c->mst_node_alsz = ALIGN(UBIFS_MST_NODE_SZ, c->min_io_size); -++ -++ /* -++ * Initialize node length ranges which are mostly needed for node -++ * length validation. -++ */ -++ c->ranges[UBIFS_PAD_NODE].len = UBIFS_PAD_NODE_SZ; -++ c->ranges[UBIFS_SB_NODE].len = UBIFS_SB_NODE_SZ; -++ c->ranges[UBIFS_MST_NODE].len = UBIFS_MST_NODE_SZ; -++ c->ranges[UBIFS_REF_NODE].len = UBIFS_REF_NODE_SZ; -++ c->ranges[UBIFS_TRUN_NODE].len = UBIFS_TRUN_NODE_SZ; -++ c->ranges[UBIFS_CS_NODE].len = UBIFS_CS_NODE_SZ; -++ -++ c->ranges[UBIFS_INO_NODE].min_len = UBIFS_INO_NODE_SZ; -++ c->ranges[UBIFS_INO_NODE].max_len = UBIFS_MAX_INO_NODE_SZ; -++ c->ranges[UBIFS_ORPH_NODE].min_len = -++ UBIFS_ORPH_NODE_SZ + sizeof(__le64); -++ c->ranges[UBIFS_ORPH_NODE].max_len = c->leb_size; -++ c->ranges[UBIFS_DENT_NODE].min_len = UBIFS_DENT_NODE_SZ; -++ c->ranges[UBIFS_DENT_NODE].max_len = UBIFS_MAX_DENT_NODE_SZ; -++ c->ranges[UBIFS_XENT_NODE].min_len = UBIFS_XENT_NODE_SZ; -++ c->ranges[UBIFS_XENT_NODE].max_len = UBIFS_MAX_XENT_NODE_SZ; -++ c->ranges[UBIFS_DATA_NODE].min_len = UBIFS_DATA_NODE_SZ; -++ c->ranges[UBIFS_DATA_NODE].max_len = UBIFS_MAX_DATA_NODE_SZ; -++ /* -++ * Minimum indexing node size is amended later when superblock is -++ * read and the key length is known. -++ */ -++ c->ranges[UBIFS_IDX_NODE].min_len = UBIFS_IDX_NODE_SZ + UBIFS_BRANCH_SZ; -++ /* -++ * Maximum indexing node size is amended later when superblock is -++ * read and the fanout is known. -++ */ -++ c->ranges[UBIFS_IDX_NODE].max_len = INT_MAX; -++ -++ /* -++ * Initialize dead and dark LEB space watermarks. -++ * -++ * Dead space is the space which cannot be used. Its watermark is -++ * equivalent to min. I/O unit or minimum node size if it is greater -++ * then min. I/O unit. -++ * -++ * Dark space is the space which might be used, or might not, depending -++ * on which node should be written to the LEB. Its watermark is -++ * equivalent to maximum UBIFS node size. -++ */ -++ c->dead_wm = ALIGN(MIN_WRITE_SZ, c->min_io_size); -++ c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size); -++ -++ return 0; -++} -++ -++/** -++ * bud_wbuf_callback - bud LEB write-buffer synchronization call-back. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB the write-buffer was synchronized to -++ * @free: how many free bytes left in this LEB -++ * @pad: how many bytes were padded -++ * -++ * This is a callback function which is called by the I/O unit when the -++ * write-buffer is synchronized. We need this to correctly maintain space -++ * accounting in bud logical eraseblocks. This function returns zero in case of -++ * success and a negative error code in case of failure. -++ * -++ * This function actually belongs to the journal, but we keep it here because -++ * we want to keep it static. -++ */ -++static int bud_wbuf_callback(struct ubifs_info *c, int lnum, int free, int pad) -++{ -++ return ubifs_update_one_lp(c, lnum, free, pad, 0, 0); -++} -++ -++/* -++ * init_constants_late - initialize UBIFS constants. -++ * @c: UBIFS file-system description object -++ * -++ * This is a helper function which initializes various UBIFS constants after -++ * the superblock has been read. It also checks various UBIFS parameters and -++ * makes sure they are all right. Returns zero in case of success and a -++ * negative error code in case of failure. -++ */ -++static int init_constants_late(struct ubifs_info *c) -++{ -++ int tmp, err; -++ uint64_t tmp64; -++ -++ c->main_bytes = c->main_lebs * c->leb_size; -++ -++ c->max_znode_sz = sizeof(struct ubifs_znode) + -++ c->fanout * sizeof(struct ubifs_zbranch); -++ -++ tmp = ubifs_idx_node_sz(c, 1); -++ c->ranges[UBIFS_IDX_NODE].min_len = tmp; -++ c->min_idx_node_sz = ALIGN(tmp, 8); -++ -++ tmp = ubifs_idx_node_sz(c, c->fanout); -++ c->ranges[UBIFS_IDX_NODE].max_len = tmp; -++ c->max_idx_node_sz = ALIGN(tmp, 8); -++ -++ /* Make sure LEB size is large enough to fit full commit */ -++ tmp = UBIFS_CS_NODE_SZ + UBIFS_REF_NODE_SZ * c->jhead_cnt; -++ tmp = ALIGN(tmp, c->min_io_size); -++ if (tmp > c->leb_size) { -++ dbg_err("too small LEB size %d, at least %d needed", -++ c->leb_size, tmp); -++ return -EINVAL; -++ } -++ -++ /* -++ * Make sure that the log is large enough to fit reference nodes for -++ * all buds plus one reserved LEB. -++ */ -++ tmp64 = c->max_bud_bytes; -++ tmp = do_div(tmp64, c->leb_size); -++ c->max_bud_cnt = tmp64 + !!tmp; -++ tmp = (c->ref_node_alsz * c->max_bud_cnt + c->leb_size - 1); -++ tmp /= c->leb_size; -++ tmp += 1; -++ if (c->log_lebs < tmp) { -++ dbg_err("too small log %d LEBs, required min. %d LEBs", -++ c->log_lebs, tmp); -++ return -EINVAL; -++ } -++ -++ /* -++ * When budgeting we assume worst-case scenarios when the pages are not -++ * be compressed and direntries are of the maximum size. -++ * -++ * Note, data, which may be stored in inodes is budgeted separately, so -++ * it is not included into 'c->inode_budget'. -++ * -++ * c->page_budget is PAGE_CACHE_SIZE + UBIFS_CH_SZ * blocks_per_page -++ */ -++ c->page_budget = PAGE_CACHE_SIZE + UBIFS_CH_SZ; -++ c->inode_budget = UBIFS_INO_NODE_SZ; -++ c->dent_budget = UBIFS_MAX_DENT_NODE_SZ; -++ -++ /* -++ * When the amount of flash space used by buds becomes -++ * 'c->max_bud_bytes', UBIFS just blocks all writers and starts commit. -++ * The writers are unblocked when the commit is finished. To avoid -++ * writers to be blocked UBIFS initiates background commit in advance, -++ * when number of bud bytes becomes above the limit defined below. -++ */ -++ c->bg_bud_bytes = (c->max_bud_bytes * 13) >> 4; -++ -++ /* -++ * Ensure minimum journal size. All the bytes in the journal heads are -++ * considered to be used, when calculating the current journal usage. -++ * Consequently, if the journal is too small, UBIFS will treat it as -++ * always full. -++ */ -++ tmp64 = (uint64_t)(c->jhead_cnt + 1) * c->leb_size + 1; -++ if (c->bg_bud_bytes < tmp64) -++ c->bg_bud_bytes = tmp64; -++ if (c->max_bud_bytes < tmp64 + c->leb_size) -++ c->max_bud_bytes = tmp64 + c->leb_size; -++ -++ err = ubifs_calc_lpt_geom(c); -++ if (err) -++ return err; -++ -++ c->min_idx_lebs = ubifs_calc_min_idx_lebs(c); -++ -++ /* -++ * Calculate total amount of FS blocks. This number is not used -++ * internally because it does not make much sense for UBIFS, but it is -++ * necessary to report something for the 'statfs()' call. -++ * -++ * Subtract the LEB reserved for GC and the LEB which is reserved for -++ * deletions. -++ * -++ * Review 'ubifs_calc_available()' if changing this calculation. -++ */ -++ tmp64 = c->main_lebs - 2; -++ tmp64 *= c->leb_size - c->dark_wm; -++ tmp64 = ubifs_reported_space(c, tmp64); -++ c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT; -++ -++ return 0; -++} -++ -++/** -++ * care_about_gc_lnum - take care about reserved GC LEB. -++ * @c: UBIFS file-system description object -++ * -++ * This function ensures that the LEB reserved for garbage collection is -++ * unmapped and is marked as "taken" in lprops. We also have to set free space -++ * to LEB size and dirty space to zero, because lprops may contain out-of-date -++ * information if the file-system was un-mounted before it has been committed. -++ * This function returns zero in case of success and a negative error code in -++ * case of failure. -++ */ -++static int care_about_gc_lnum(struct ubifs_info *c) -++{ -++ int err; -++ -++ if (c->gc_lnum == -1) { -++ ubifs_err("no LEB for GC"); -++ return -EINVAL; -++ } -++ -++ err = ubifs_leb_unmap(c, c->gc_lnum); -++ if (err) -++ return err; -++ -++ /* And we have to tell lprops that this LEB is taken */ -++ err = ubifs_change_one_lp(c, c->gc_lnum, c->leb_size, 0, -++ LPROPS_TAKEN, 0, 0); -++ return err; -++} -++ -++/** -++ * alloc_wbufs - allocate write-buffers. -++ * @c: UBIFS file-system description object -++ * -++ * This helper function allocates and initializes UBIFS write-buffers. Returns -++ * zero in case of success and %-ENOMEM in case of failure. -++ */ -++static int alloc_wbufs(struct ubifs_info *c) -++{ -++ int i, err; -++ -++ c->jheads = kzalloc(c->jhead_cnt * sizeof(struct ubifs_jhead), -++ GFP_KERNEL); -++ if (!c->jheads) -++ return -ENOMEM; -++ -++ /* Initialize journal heads */ -++ for (i = 0; i < c->jhead_cnt; i++) { -++ INIT_LIST_HEAD(&c->jheads[i].buds_list); -++ err = ubifs_wbuf_init(c, &c->jheads[i].wbuf); -++ if (err) -++ return err; -++ -++ c->jheads[i].wbuf.sync_callback = &bud_wbuf_callback; -++ c->jheads[i].wbuf.jhead = i; -++ } -++ -++ c->jheads[BASEHD].wbuf.dtype = UBI_SHORTTERM; -++ /* -++ * Garbage Collector head likely contains long-term data and -++ * does not need to be synchronized by timer. -++ */ -++ c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM; -++ c->jheads[GCHD].wbuf.timeout = 0; -++ -++ sprintf(c->bgt_name, "%s%d_%d", SYNCER_BG_NAME, -++ c->vi.ubi_num, c->vi.vol_id); -++ -++ return 0; -++} -++ -++/** -++ * free_wbufs - free write-buffers. -++ * @c: UBIFS file-system description object -++ */ -++static void free_wbufs(struct ubifs_info *c) -++{ -++ int i; -++ -++ if (c->jheads) { -++ for (i = 0; i < c->jhead_cnt; i++) { -++ kfree(c->jheads[i].wbuf.buf); -++ kfree(c->jheads[i].wbuf.inodes); -++ } -++ kfree(c->jheads); -++ c->jheads = NULL; -++ } -++} -++ -++/** -++ * free_orphans - free orphans. -++ * @c: UBIFS file-system description object -++ */ -++static void free_orphans(struct ubifs_info *c) -++{ -++ struct ubifs_orphan *orph; -++ -++ while (c->orph_dnext) { -++ orph = c->orph_dnext; -++ c->orph_dnext = orph->dnext; -++ list_del(&orph->list); -++ kfree(orph); -++ } -++ -++ while (!list_empty(&c->orph_list)) { -++ orph = list_entry(c->orph_list.next, struct ubifs_orphan, list); -++ list_del(&orph->list); -++ kfree(orph); -++ dbg_err("orphan list not empty at unmount"); -++ } -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(c->orph_buf); -++#else -++ vfree(c->orph_buf); -++#endif -++ c->orph_buf = NULL; -++} -++ -++/** -++ * free_buds - free per-bud objects. -++ * @c: UBIFS file-system description object -++ */ -++static void free_buds(struct ubifs_info *c) -++{ -++ struct rb_node *this = c->buds.rb_node; -++ struct ubifs_bud *bud; -++ -++ while (this) { -++ if (this->rb_left) -++ this = this->rb_left; -++ else if (this->rb_right) -++ this = this->rb_right; -++ else { -++ bud = rb_entry(this, struct ubifs_bud, rb); -++ this = rb_parent(this); -++ if (this) { -++ if (this->rb_left == &bud->rb) -++ this->rb_left = NULL; -++ else -++ this->rb_right = NULL; -++ } -++ kfree(bud); -++ } -++ } -++} -++ -++/** -++ * check_volume_empty - check if the UBI volume is empty. -++ * @c: UBIFS file-system description object -++ * -++ * This function checks if the UBIFS volume is empty by looking if its LEBs are -++ * mapped or not. The result of checking is stored in the @c->empty variable. -++ * Returns zero in case of success and a negative error code in case of -++ * failure. -++ */ -++static int check_volume_empty(struct ubifs_info *c) -++{ -++ int lnum, err; -++ -++ c->empty = 1; -++ for (lnum = 0; lnum < c->leb_cnt; lnum++) { -++ err = ubi_is_mapped(c->ubi, lnum); -++ if (unlikely(err < 0)) -++ return err; -++ if (err == 1) { -++ c->empty = 0; -++ break; -++ } -++ -++ cond_resched(); -++ } -++ -++ return 0; -++} -++ -++/** -++ * mount_ubifs - mount UBIFS file-system. -++ * @c: UBIFS file-system description object -++ * -++ * This function mounts UBIFS file system. Returns zero in case of success and -++ * a negative error code in case of failure. -++ * -++ * Note, the function does not de-allocate resources it it fails half way -++ * through, and the caller has to do this instead. -++ */ -++static int mount_ubifs(struct ubifs_info *c) -++{ -++ struct super_block *sb = c->vfs_sb; -++ int err, mounted_read_only = (sb->s_flags & MS_RDONLY); -++ unsigned long long x; -++ size_t sz; -++ -++ err = init_constants_early(c); -++ if (err) -++ return err; -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ c->dbg_buf = kmalloc(c->leb_size, GFP_KERNEL); -++#else -++ c->dbg_buf = vmalloc(c->leb_size); -++#endif -++ if (!c->dbg_buf) -++ return -ENOMEM; -++#endif -++ -++ err = check_volume_empty(c); -++ if (err) -++ return err; -++ -++ if (c->empty && (mounted_read_only || c->ro_media)) { -++ /* -++ * This UBI volume is empty, and read-only, or the file system -++ * is mounted read-only - we cannot format it. -++ */ -++ ubifs_err("can't format empty UBI volume: read-only %s", -++ c->ro_media ? "UBI volume" : "mount"); -++ return -EROFS; -++ } -++ -++ if (c->ro_media && !mounted_read_only) { -++ ubifs_err("cannot mount read-write - read-only media"); -++ return -EROFS; -++ } -++ -++ /* -++ * The requirement for the buffer is that it should fit indexing B-tree -++ * height amount of integers. We assume the height if the TNC tree will -++ * never exceed 64. -++ */ -++ c->bottom_up_buf = kmalloc(BOTTOM_UP_HEIGHT * sizeof(int), GFP_KERNEL); -++ if (!c->bottom_up_buf) -++ return -ENOMEM; -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ c->sbuf = kmalloc(c->leb_size, GFP_KERNEL); -++#else -++ c->sbuf = vmalloc(c->leb_size); -++#endif -++ if (!c->sbuf) -++ return -ENOMEM; -++ -++ if (!mounted_read_only) { -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ c->ileb_buf = kmalloc(c->leb_size, GFP_KERNEL); -++#else -++ c->ileb_buf = vmalloc(c->leb_size); -++#endif -++ if (!c->ileb_buf) -++ return -ENOMEM; -++ } -++ -++ err = ubifs_read_superblock(c); -++ if (err) -++ return err; -++ -++ /* -++ * Make sure the compressor which is set as the default on in the -++ * superblock was actually compiled in. -++ */ -++ if (!ubifs_compr_present(c->default_compr)) { -++ ubifs_warn("'%s' compressor is set by superblock, but not " -++ "compiled in", ubifs_compr_name(c->default_compr)); -++ c->default_compr = UBIFS_COMPR_NONE; -++ } -++ -++ dbg_failure_mode_registration(c); -++ -++ err = init_constants_late(c); -++ if (err) -++ return err; -++ -++ sz = ALIGN(c->max_idx_node_sz, c->min_io_size); -++ sz = ALIGN(sz + c->max_idx_node_sz, c->min_io_size); -++ c->cbuf = kmalloc(sz, GFP_NOFS); -++ if (!c->cbuf) -++ return -ENOMEM; -++ -++ if (!mounted_read_only) { -++ err = alloc_wbufs(c); -++ if (err) -++ return err; -++ -++ /* Create background thread */ -++ c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name); -++ if (!c->bgt) -++ c->bgt = ERR_PTR(-EINVAL); -++ if (IS_ERR(c->bgt)) { -++ err = PTR_ERR(c->bgt); -++ c->bgt = NULL; -++ ubifs_err("cannot spawn \"%s\", error %d", -++ c->bgt_name, err); -++ return err; -++ } -++ } -++ -++ err = ubifs_read_master(c); -++ if (err) -++ return err; -++ -++ if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) { -++ ubifs_msg("recovery needed"); -++ c->need_recovery = 1; -++ if (!mounted_read_only) { -++ err = ubifs_recover_inl_heads(c, c->sbuf); -++ if (err) -++ return err; -++ } -++ } else if (!mounted_read_only) { -++ /* -++ * Set the "dirty" flag so that if we reboot uncleanly we -++ * will notice this immediately on the next mount. -++ */ -++ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); -++ err = ubifs_write_master(c); -++ if (err) -++ return err; -++ } -++ -++ err = ubifs_lpt_init(c, 1, !mounted_read_only); -++ if (err) -++ return err; -++ -++ err = dbg_check_idx_size(c, c->old_idx_sz); -++ if (err) -++ return err; -++ -++ err = ubifs_replay_journal(c); -++ if (err) -++ return err; -++ -++ if (!mounted_read_only) { -++ int lnum; -++ -++ if (c->need_recovery) -++ err = ubifs_recover_gc_lnum(c); -++ else -++ err = care_about_gc_lnum(c); -++ if (err) -++ return err; -++ err = ubifs_mount_orphans(c, c->need_recovery); -++ if (err) -++ return err; -++ -++ /* Check for enough log space */ -++ lnum = c->lhead_lnum + 1; -++ if (lnum >= UBIFS_LOG_LNUM + c->log_lebs) -++ lnum = UBIFS_LOG_LNUM; -++ if (lnum == c->ltail_lnum) { -++ err = ubifs_consolidate_log(c); -++ if (err) -++ return err; -++ } -++ -++ /* Check for enough free space */ -++ if (ubifs_calc_available(c) <= 0) { -++ ubifs_err("insufficient available space"); -++ return -EINVAL; -++ } -++ -++ err = dbg_check_lprops(c); -++ if (err) -++ return err; -++ } -++ -++ if (c->need_recovery) { -++ err = ubifs_recover_size(c); -++ if (err) -++ return err; -++ } -++ -++ spin_lock(&ubifs_infos_lock); -++ list_add_tail(&c->infos_list, &ubifs_infos); -++ spin_unlock(&ubifs_infos_lock); -++ -++ if (c->need_recovery) { -++ if (mounted_read_only) -++ ubifs_msg("recovery deferred"); -++ else { -++ c->need_recovery = 0; -++ ubifs_msg("recovery completed"); -++ } -++ } -++ -++ ubifs_msg("mounted UBI device %d, volume %d", c->vi.ubi_num, -++ c->vi.vol_id); -++ if (mounted_read_only) -++ ubifs_msg("mounted read-only"); -++ ubifs_msg("minimal I/O unit size: %d bytes", c->min_io_size); -++ ubifs_msg("logical eraseblock size: %d bytes (%d KiB)", -++ c->leb_size, c->leb_size / 1024); -++ x = (unsigned long long)c->main_lebs * c->leb_size; -++ ubifs_msg("file system size: %lld bytes (%lld KiB, %lld MiB, " -++ "%d LEBs)", x, x >> 10, x >> 20, c->main_lebs); -++ x = (unsigned long long)c->log_lebs * c->leb_size + c->max_bud_bytes; -++ ubifs_msg("journal size: %lld bytes (%lld KiB, %lld MiB, " -++ "%d LEBs)", x, x >> 10, x >> 20, -++ c->log_lebs + c->max_bud_cnt); -++ ubifs_msg("data journal heads: %d", -++ c->jhead_cnt - NONDATA_JHEADS_CNT); -++ ubifs_msg("default compressor: %s", -++ ubifs_compr_name(c->default_compr)); -++ -++ dbg_msg("compiled on: " __DATE__ " at " __TIME__); -++ dbg_msg("fast unmount: %d", c->fast_unmount); -++ dbg_msg("big_lpt %d", c->big_lpt); -++ dbg_msg("log LEBs: %d (%d - %d)", -++ c->log_lebs, UBIFS_LOG_LNUM, c->log_last); -++ dbg_msg("LPT area LEBs: %d (%d - %d)", -++ c->lpt_lebs, c->lpt_first, c->lpt_last); -++ dbg_msg("orphan area LEBs: %d (%d - %d)", -++ c->orph_lebs, c->orph_first, c->orph_last); -++ dbg_msg("main area LEBs: %d (%d - %d)", -++ c->main_lebs, c->main_first, c->leb_cnt - 1); -++ dbg_msg("index LEBs: %d", c->lst.idx_lebs); -++ dbg_msg("total index bytes: %lld (%lld KiB, %lld MiB)", -++ c->old_idx_sz, c->old_idx_sz >> 10, c->old_idx_sz >> 20); -++ dbg_msg("key hash type: %d", c->key_hash_type); -++ dbg_msg("tree fanout: %d", c->fanout); -++ dbg_msg("reserved GC LEB: %d", c->gc_lnum); -++ dbg_msg("first main LEB: %d", c->main_first); -++ dbg_msg("dead watermark: %d", c->dead_wm); -++ dbg_msg("dark watermark: %d", c->dark_wm); -++ x = c->main_lebs * c->dark_wm; -++ dbg_msg("max. dark space: %lld (%lld KiB, %lld MiB)", -++ x, x >> 10, x >> 20); -++ dbg_msg("maximum bud bytes: %lld (%lld KiB, %lld MiB)", -++ c->max_bud_bytes, c->max_bud_bytes >> 10, -++ c->max_bud_bytes >> 20); -++ dbg_msg("BG commit bud bytes: %lld (%lld KiB, %lld MiB)", -++ c->bg_bud_bytes, c->bg_bud_bytes >> 10, -++ c->bg_bud_bytes >> 20); -++ dbg_msg("current bud bytes %lld (%lld KiB, %lld MiB)", -++ c->bud_bytes, c->bud_bytes >> 10, c->bud_bytes >> 20); -++ dbg_msg("max. seq. number: %llu", c->max_sqnum); -++ dbg_msg("commit number: %llu", c->cmt_no); -++ -++ return 0; -++} -++ -++/** -++ * ubifs_umount - un-mount UBIFS file-system. -++ * @c: UBIFS file-system description object -++ * -++ * Note, this function is called to free allocated resourced when un-mounting, -++ * as well as free resources when an error occurred while we were half way -++ * through mounting (error path cleanup function). So it has to make sure the -++ * resource was actually allocated before freeing it. -++ */ -++void ubifs_umount(struct ubifs_info *c) -++{ -++ dbg_gen("un-mounting UBI device %d, volume %d", c->vi.ubi_num, -++ c->vi.vol_id); -++ -++ ubifs_destroy_size_tree(c); -++ -++ if (c->bgt) -++ kthread_stop(c->bgt); -++ -++ free_buds(c); -++ ubifs_destroy_idx_gc(c); -++ ubifs_tnc_close(c); -++ -++ free_wbufs(c); -++ free_orphans(c); -++ ubifs_lpt_free(c, 0); -++ -++ while (!list_empty(&c->unclean_leb_list)) { -++ struct ubifs_unclean_leb *ucleb; -++ -++ ucleb = list_entry(c->unclean_leb_list.next, -++ struct ubifs_unclean_leb, list); -++ list_del(&ucleb->list); -++ kfree(ucleb); -++ } -++ -++ while (!list_empty(&c->old_buds)) { -++ struct ubifs_bud *bud; -++ -++ bud = list_entry(c->old_buds.next, struct ubifs_bud, list); -++ list_del(&bud->list); -++ kfree(bud); -++ } -++ -++ kfree(c->rcvrd_mst_node); -++ kfree(c->mst_node); -++ kfree(c->bottom_up_buf); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(c->sbuf); -++ UBIFS_DBG(kfree(c->dbg_buf)); -++ kfree(c->ileb_buf); -++#else -++ vfree(c->sbuf); -++ UBIFS_DBG(vfree(c->dbg_buf)); -++ vfree(c->ileb_buf); -++#endif -++ dbg_failure_mode_deregistration(c); -++} -++ -++/** -++ * ubifs_remount_rw - re-mount in read-write mode. -++ * @c: UBIFS file-system description object -++ * -++ * UBIFS avoids allocating many unnecessary resources when mounted in read-only -++ * mode. This function allocates the needed resources and re-mounts UBIFS in -++ * read-write mode. -++ */ -++int ubifs_remount_rw(struct ubifs_info *c) -++{ -++ int err, lnum; -++ -++ if (c->ro_media) -++ return -EINVAL; -++ -++ mutex_lock(&c->umount_mutex); -++ c->remounting_rw = 1; -++ -++ /* Check for enough free space */ -++ if (ubifs_calc_available(c) <= 0) { -++ ubifs_err("insufficient available space"); -++ err = -EINVAL; -++ goto out; -++ } -++ -++ if (c->old_leb_cnt != c->leb_cnt) { -++ struct ubifs_sb_node *sup; -++ -++ sup = ubifs_read_sb_node(c); -++ if (IS_ERR(sup)) { -++ err = PTR_ERR(sup); -++ goto out; -++ } -++ sup->leb_cnt = cpu_to_le32(c->leb_cnt); -++ err = ubifs_write_sb_node(c, sup); -++ if (err) -++ goto out; -++ } -++ -++ if (c->need_recovery) { -++ ubifs_msg("completing deferred recovery"); -++ err = ubifs_write_rcvrd_mst_node(c); -++ if (err) -++ goto out; -++ err = ubifs_recover_size(c); -++ if (err) -++ goto out; -++ err = ubifs_clean_lebs(c, c->sbuf); -++ if (err) -++ goto out; -++ err = ubifs_recover_inl_heads(c, c->sbuf); -++ if (err) -++ goto out; -++ } -++ -++ if (!(c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY))) { -++ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); -++ err = ubifs_write_master(c); -++ if (err) -++ goto out; -++ } -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ c->ileb_buf = kmalloc(c->leb_size, GFP_KERNEL); -++#else -++ c->ileb_buf = vmalloc(c->leb_size); -++#endif -++ if (!c->ileb_buf) { -++ err = -ENOMEM; -++ goto out; -++ } -++ -++ err = ubifs_lpt_init(c, 0, 1); -++ if (err) -++ goto out; -++ -++ err = alloc_wbufs(c); -++ if (err) -++ goto out; -++ -++ ubifs_create_buds_lists(c); -++ -++ /* Create background thread */ -++ c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name); -++ if (!c->bgt) -++ c->bgt = ERR_PTR(-EINVAL); -++ if (IS_ERR(c->bgt)) { -++ err = PTR_ERR(c->bgt); -++ c->bgt = NULL; -++ ubifs_err("cannot spawn \"%s\", error %d", -++ c->bgt_name, err); -++ return err; -++ } -++ -++ if (c->need_recovery) -++ err = ubifs_recover_gc_lnum(c); -++ else -++ err = care_about_gc_lnum(c); -++ if (err) -++ goto out; -++ -++ err = ubifs_mount_orphans(c, c->need_recovery); -++ if (err) -++ goto out; -++ /* Check for enough log space */ -++ lnum = c->lhead_lnum + 1; -++ if (lnum >= UBIFS_LOG_LNUM + c->log_lebs) -++ lnum = UBIFS_LOG_LNUM; -++ if (lnum == c->ltail_lnum) { -++ err = ubifs_consolidate_log(c); -++ if (err) -++ goto out; -++ } -++ -++ if (c->need_recovery) { -++ c->need_recovery = 0; -++ ubifs_msg("deferred recovery completed"); -++ } -++ -++ dbg_gen("re-mounted read-write"); -++ c->vfs_sb->s_flags &= ~MS_RDONLY; -++ c->remounting_rw = 0; -++ mutex_unlock(&c->umount_mutex); -++ return 0; -++ -++out: -++ free_orphans(c); -++ if (c->bgt) { -++ kthread_stop(c->bgt); -++ c->bgt = NULL; -++ } -++ free_wbufs(c); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(c->ileb_buf); -++#else -++ vfree(c->ileb_buf); -++#endif -++ c->ileb_buf = NULL; -++ ubifs_lpt_free(c, 1); -++ c->remounting_rw = 0; -++ mutex_unlock(&c->umount_mutex); -++ return err; -++} -++ -++/** -++ * commit_on_unmount - commit the journal when un-mounting. -++ * @c: UBIFS file-system description object -++ * -++ * This function is called during un-mounting and it commits the journal unless -++ * the "fast unmount" mode is enabled. It also avoids committing the journal if -++ * it contains too few data. -++ * -++ * Sometimes recovery requires the journal to be committed at least once, and -++ * this function takes care about this. -++ */ -++static void commit_on_unmount(struct ubifs_info *c) -++{ -++ if (!c->fast_unmount) { -++ long long bud_bytes; -++ -++ spin_lock(&c->buds_lock); -++ bud_bytes = c->bud_bytes; -++ spin_unlock(&c->buds_lock); -++ if (bud_bytes > c->leb_size) -++ ubifs_run_commit(c); -++ } -++ -++ if (c->recovery_needs_commit) -++ ubifs_recovery_commit(c); -++} -++ -++/** -++ * ubifs_remount_ro - re-mount in read-only mode. -++ * @c: UBIFS file-system description object -++ * -++ * We rely on VFS to have stopped writing. Possibly the background thread could -++ * be running a commit, however kthread_stop will wait in that case. -++ */ -++void ubifs_remount_ro(struct ubifs_info *c) -++{ -++ int i, err; -++ -++ ubifs_assert(!c->need_recovery); -++ -++ commit_on_unmount(c); -++ -++ mutex_lock(&c->umount_mutex); -++ if (c->bgt) { -++ kthread_stop(c->bgt); -++ c->bgt = NULL; -++ } -++ -++ for (i = 0; i < c->jhead_cnt; i++) { -++ ubifs_wbuf_sync(&c->jheads[i].wbuf); -++ del_timer_sync(&c->jheads[i].wbuf.timer); -++ } -++ -++ if (!c->ro_media) { -++ c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); -++ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); -++ c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum); -++ err = ubifs_write_master(c); -++ if (err) -++ ubifs_ro_mode(c, err); -++ } -++ -++ ubifs_destroy_idx_gc(c); -++ free_wbufs(c); -++ free_orphans(c); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(c->ileb_buf); -++#else -++ vfree(c->ileb_buf); -++#endif -++ c->ileb_buf = NULL; -++ ubifs_lpt_free(c, 1); -++ mutex_unlock(&c->umount_mutex); -++} -++ -++/** -++ * open_ubi - parse UBI device name string and open the UBI device. -++ * @c: UBIFS file-system description object -++ * @name: UBI volume name -++ * @mode: UBI volume open mode -++ * -++ * There are several ways to specify UBI volumes when mounting UBIFS: -++ * o ubiX_Y - UBI device number X, volume Y; -++ * o ubiY - UBI device number 0, volume Y; -++ * o ubiX:NAME - mount UBI device X, volume with name NAME; -++ * o ubi:NAME - mount UBI device 0, volume with name NAME. -++ * -++ * Alternative '!' separator may be used instead of ':' (because some shells -++ * like busybox may interpret ':' as an NFS host name separator). This function -++ * returns zero in case of success and a negative error code in case of -++ * failure. -++ */ -++static int open_ubi(struct ubifs_info *c, const char *name, int mode) -++{ -++ int dev, vol; -++ char *endptr; -++ -++ if (name[0] != 'u' || name[1] != 'b' || name[2] != 'i') -++ return -EINVAL; -++ -++ if ((name[3] == ':' || name[3] == '!') && name[4] != '\0') { -++ /* ubi:NAME method */ -++ c->ubi = ubi_open_volume_nm(0, name + 4, mode); -++ if (IS_ERR(c->ubi)) -++ return PTR_ERR(c->ubi); -++ } else if (isdigit(name[3])) { -++ dev = simple_strtoul(name + 3, &endptr, 0); -++ if (*endptr == '\0') { -++ /* ubiY method */ -++ c->ubi = ubi_open_volume(0, dev, mode); -++ if (IS_ERR(c->ubi)) -++ return PTR_ERR(c->ubi); -++ } else if (*endptr == '_' && isdigit(endptr[1])) { -++ /* ubiX_Y method */ -++ vol = simple_strtoul(endptr + 1, &endptr, 0); -++ if (*endptr != '\0') -++ return -EINVAL; -++ c->ubi = ubi_open_volume(dev, vol, mode); -++ if (IS_ERR(c->ubi)) -++ return PTR_ERR(c->ubi); -++ } else if ((*endptr == ':' || *endptr == '!') && -++ endptr[1] != '\0') { -++ /* ubiX:NAME method */ -++ c->ubi = ubi_open_volume_nm(dev, ++endptr, mode); -++ if (IS_ERR(c->ubi)) -++ return PTR_ERR(c->ubi); -++ } -++ } -++ -++ if (!c->ubi) -++ return -EINVAL; -++ -++ ubi_get_volume_info(c->ubi, &c->vi); -++ ubi_get_device_info(c->vi.ubi_num, &c->di); -++ return 0; -++} -++ -++static int sb_test(struct super_block *sb, void *data) -++{ -++ dev_t *dev = data; -++ -++ return sb->s_dev == *dev; -++} -++ -++static int sb_set(struct super_block *sb, void *data) -++{ -++ return 0; -++} -++ -++/* -++ * UBIFS mount options. -++ * -++ * Opt_fast_unmount: do not run a journal commit before un-mounting -++ * Opt_norm_unmount: run a journal commit before un-mounting -++ * Opt_err: just end of array marker -++ */ -++enum { -++ Opt_fast_unmount, -++ Opt_norm_unmount, -++ Opt_err, -++}; -++ -++static match_table_t tokens = { -++ {Opt_fast_unmount, "fast_unmount"}, -++ {Opt_norm_unmount, "norm_unmount"}, -++ {Opt_err, NULL}, -++}; -++ -++/** -++ * ubifs_parse_options - parse mount parameters. -++ * @c: UBIFS file-system description object -++ * @options: parameters to parse -++ * @is_remount: non-zero if this is FS re-mount -++ * -++ * This function parses UBIFS mount options and returns zero in case success -++ * and a negative error code in case of failure. -++ */ -++int ubifs_parse_options(struct ubifs_info *c, char *options, int is_remount) -++{ -++ char *p; -++ substring_t args[MAX_OPT_ARGS]; -++ -++ if (!options) -++ return 0; -++ -++ while ((p = strsep(&options, ",")) != NULL) { -++ int token; -++ -++ if (!*p) -++ continue; -++ -++ token = match_token(p, tokens, args); -++ switch (token) { -++ case Opt_fast_unmount: -++ c->mount_opts.unmount_mode = 2; -++ c->fast_unmount = 1; -++ break; -++ case Opt_norm_unmount: -++ c->mount_opts.unmount_mode = 1; -++ c->fast_unmount = 0; -++ break; -++ default: -++ ubifs_err("unrecognized mount option \"%s\" " -++ "or missing value", p); -++ return -EINVAL; -++ } -++ } -++ -++ return 0; -++} -++ -++static int ubifs_get_sb(struct file_system_type *fs_type, int flags, -++ const char *name, void *data, struct vfsmount *mnt) -++{ -++ int err; -++ struct super_block *sb; -++ struct ubifs_info *c; -++ struct inode *root; -++ -++ dbg_gen("name %s, flags %#x", name, flags); -++ -++ c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL); -++ if (!c) -++ return -ENOMEM; -++ -++ spin_lock_init(&c->cnt_lock); -++ spin_lock_init(&c->cs_lock); -++ spin_lock_init(&c->buds_lock); -++ spin_lock_init(&c->space_lock); -++ spin_lock_init(&c->orphan_lock); -++ init_rwsem(&c->commit_sem); -++ mutex_init(&c->lp_mutex); -++ mutex_init(&c->tnc_mutex); -++ mutex_init(&c->log_mutex); -++ mutex_init(&c->mst_mutex); -++ mutex_init(&c->umount_mutex); -++ init_waitqueue_head(&c->cmt_wq); -++ c->buds = RB_ROOT; -++ c->old_idx = RB_ROOT; -++ c->size_tree = RB_ROOT; -++ c->orph_tree = RB_ROOT; -++ INIT_LIST_HEAD(&c->infos_list); -++ INIT_LIST_HEAD(&c->idx_gc); -++ INIT_LIST_HEAD(&c->replay_list); -++ INIT_LIST_HEAD(&c->replay_buds); -++ INIT_LIST_HEAD(&c->uncat_list); -++ INIT_LIST_HEAD(&c->empty_list); -++ INIT_LIST_HEAD(&c->freeable_list); -++ INIT_LIST_HEAD(&c->frdi_idx_list); -++ INIT_LIST_HEAD(&c->unclean_leb_list); -++ INIT_LIST_HEAD(&c->old_buds); -++ INIT_LIST_HEAD(&c->orph_list); -++ INIT_LIST_HEAD(&c->orph_new); -++ -++ c->highest_inum = UBIFS_FIRST_INO; -++ get_random_bytes(&c->vfs_gen, sizeof(int)); -++ c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM; -++ -++ err = ubifs_parse_options(c, data, 0); -++ if (err) -++ goto out_free; -++ -++ /* -++ * Get UBI device number and volume ID. Mount it read-only so far -++ * because this might be a new mount point, and UBI allows only one -++ * read-write user at a time. -++ */ -++ err = open_ubi(c, name, UBI_READONLY); -++ if (err) { -++ ubifs_err("cannot open \"%s\", error %d", name, err); -++ goto out_free; -++ } -++ -++ dbg_gen("opened ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); -++ -++ sb = sget(fs_type, &sb_test, &sb_set, &c->vi.cdev); -++ if (IS_ERR(sb)) { -++ err = PTR_ERR(sb); -++ goto out_close; -++ } -++ -++ if (sb->s_root) { -++ /* A new mount point for already mounted UBIFS */ -++ dbg_gen("this ubi volume is already mounted"); -++ err = simple_set_mnt(mnt, sb); -++ goto out_close; -++ } -++ -++ /* Re-open the UBI device in read-write mode */ -++ ubi_close_volume(c->ubi); -++ c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READWRITE); -++ if (IS_ERR(c->ubi)) { -++ err = PTR_ERR(c->ubi); -++ goto out_free; -++ } -++ -++ c->vfs_sb = sb; -++ sb->s_fs_info = c; -++ sb->s_magic = UBIFS_SUPER_MAGIC; -++ sb->s_blocksize = UBIFS_BLOCK_SIZE; -++ sb->s_blocksize_bits = UBIFS_BLOCK_SHIFT; -++ sb->s_dev = c->vi.cdev; -++ sb->s_maxbytes = c->max_inode_sz = -++ min_t(uint64_t, MAX_LFS_FILESIZE, UBIFS_MAX_INODE_SZ); -++ sb->s_op = &ubifs_super_operations; -++ sb->s_flags = flags; -++ -++ mutex_lock(&c->umount_mutex); -++ err = mount_ubifs(c); -++ if (err) { -++ ubifs_assert(err < 0); -++ goto out_umount; -++ } -++ -++ /* Read the root inode */ -++ root = ubifs_iget(sb, UBIFS_ROOT_INO); -++ if (IS_ERR(root)) { -++ err = PTR_ERR(root); -++ goto out_umount; -++ } -++ -++ sb->s_root = d_alloc_root(root); -++ if (!sb->s_root) -++ goto out_iput; -++ -++ mutex_unlock(&c->umount_mutex); -++ -++ /* We do not support atime */ -++ sb->s_flags |= MS_ACTIVE | MS_NOATIME; -++ return simple_set_mnt(mnt, sb); -++ -++out_iput: -++ iput(root); -++out_umount: -++ spin_lock(&ubifs_infos_lock); -++ if (c->infos_list.next) -++ list_del(&c->infos_list); -++ spin_unlock(&ubifs_infos_lock); -++ ubifs_umount(c); -++ mutex_unlock(&c->umount_mutex); -++ up_write(&sb->s_umount); -++ sb->s_root = NULL; -++ deactivate_super(sb); -++out_close: -++ ubi_close_volume(c->ubi); -++out_free: -++ kfree(c); -++ return err; -++} -++ -++static void ubifs_kill_sb(struct super_block *sb) -++{ -++ struct ubifs_info *c = sb->s_fs_info; -++ -++ if (sb->s_root != NULL && !(sb->s_flags & MS_RDONLY)) -++ commit_on_unmount(c); -++ /* The un-mount routine is actually done in put_super() */ -++ generic_shutdown_super(sb); -++} -++ -++static struct file_system_type ubifs_fs_type = { -++ .name = "ubifs", -++ .owner = THIS_MODULE, -++ .get_sb = ubifs_get_sb, -++ .kill_sb = ubifs_kill_sb -++}; -++ -++/* -++ * Inode slab cache constructor. -++ * -++ * TODO: remove backward compatibility as late as possible -++ */ -++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) -++static void inode_slab_ctor(void *obj, struct kmem_cache *cachep, -++ unsigned long flags) -++#else -++static void inode_slab_ctor(struct kmem_cache *cachep, void *obj) -++#endif -++{ -++ struct ubifs_inode *inode = obj; -++ inode_init_once(&inode->vfs_inode); -++} -++ -++static int __init ubifs_init(void) -++{ -++ int err; -++ -++ BUILD_BUG_ON(sizeof(struct ubifs_ch) != 24); -++ -++ /* Make sure node sizes are 8-byte aligned */ -++ BUILD_BUG_ON(UBIFS_CH_SZ & 7); -++ BUILD_BUG_ON(UBIFS_INO_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_DENT_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_XENT_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_DATA_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_TRUN_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_SB_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_MST_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_REF_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_CS_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_ORPH_NODE_SZ & 7); -++ -++ BUILD_BUG_ON(UBIFS_MAX_DENT_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_MAX_XENT_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_MAX_DATA_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_MAX_INO_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_MAX_NODE_SZ & 7); -++ BUILD_BUG_ON(MIN_WRITE_SZ & 7); -++ -++ /* Check min. node size */ -++ BUILD_BUG_ON(UBIFS_INO_NODE_SZ < MIN_WRITE_SZ); -++ BUILD_BUG_ON(UBIFS_DENT_NODE_SZ < MIN_WRITE_SZ); -++ BUILD_BUG_ON(UBIFS_XENT_NODE_SZ < MIN_WRITE_SZ); -++ BUILD_BUG_ON(UBIFS_TRUN_NODE_SZ < MIN_WRITE_SZ); -++ -++ BUILD_BUG_ON(UBIFS_MAX_DENT_NODE_SZ > UBIFS_MAX_NODE_SZ); -++ BUILD_BUG_ON(UBIFS_MAX_XENT_NODE_SZ > UBIFS_MAX_NODE_SZ); -++ BUILD_BUG_ON(UBIFS_MAX_DATA_NODE_SZ > UBIFS_MAX_NODE_SZ); -++ BUILD_BUG_ON(UBIFS_MAX_INO_NODE_SZ > UBIFS_MAX_NODE_SZ); -++ -++ /* We do not support multiple pages per block ATM */ -++ BUILD_BUG_ON(UBIFS_BLOCK_SIZE != PAGE_CACHE_SIZE); -++ -++ /* Defined node sizes */ -++ BUILD_BUG_ON(UBIFS_SB_NODE_SZ != 4096); -++ BUILD_BUG_ON(UBIFS_MST_NODE_SZ != 512); -++ BUILD_BUG_ON(UBIFS_INO_NODE_SZ != 160); -++ BUILD_BUG_ON(UBIFS_REF_NODE_SZ != 64); -++ -++ err = bdi_init(&ubifs_backing_dev_info); -++ if (err) -++ return err; -++ -++ err = register_filesystem(&ubifs_fs_type); -++ if (err) { -++ ubifs_err("cannot register file system, error %d", err); -++ goto out; -++ } -++ -++ err = -ENOMEM; -++ ubifs_inode_slab = kmem_cache_create("ubifs_inode_slab", -++ sizeof(struct ubifs_inode), 0, -++ SLAB_MEM_SPREAD | SLAB_RECLAIM_ACCOUNT, -++ &inode_slab_ctor UBIFSCOMPATNULL); -++ if (!ubifs_inode_slab) -++ goto out_reg; -++ -++ register_shrinker(&ubifs_shrinker_info); -++ dbg_mempressure_init(); -++ -++ err = ubifs_compressors_init(); -++ if (err) -++ goto out_compr; -++ -++ return 0; -++ -++out_compr: -++ dbg_mempressure_exit(); -++ unregister_shrinker(&ubifs_shrinker_info); -++ kmem_cache_destroy(ubifs_inode_slab); -++out_reg: -++ unregister_filesystem(&ubifs_fs_type); -++out: -++ bdi_destroy(&ubifs_backing_dev_info); -++ return err; -++} -++/* late_initcall to let compressors initialize first */ -++late_initcall(ubifs_init); -++ -++static void __exit ubifs_exit(void) -++{ -++ ubifs_assert(list_empty(&ubifs_infos)); -++ ubifs_assert(atomic_long_read(&ubifs_clean_zn_cnt) == 0); -++ -++ ubifs_compressors_exit(); -++ dbg_mempressure_exit(); -++ unregister_shrinker(&ubifs_shrinker_info); -++ kmem_cache_destroy(ubifs_inode_slab); -++ unregister_filesystem(&ubifs_fs_type); -++ bdi_destroy(&ubifs_backing_dev_info); -++ dbg_leak_report(); -++} -++module_exit(ubifs_exit); -++ -++MODULE_LICENSE("GPL"); -++MODULE_VERSION(__stringify(UBIFS_VERSION)); -++MODULE_AUTHOR("Artem Bityutskiy, Adrian Hunter"); -++MODULE_DESCRIPTION("UBIFS - UBI File System"); -+diff -urN linux-2.6.24.7.old/fs/ubifs/commit.c linux-2.6.24.7/fs/ubifs/commit.c -+--- linux-2.6.24.7.old/fs/ubifs/commit.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/commit.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,718 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Adrian Hunter -++ * Artem Bityutskiy (Битюцкий Ðртём) -++ */ -++ -++/* -++ * This file implements functions that manage the running of the commit process. -++ * Each affected module has its own functions to accomplish their part in the -++ * commit and those functions are called here. -++ * -++ * The commit is the process whereby all updates to the index and LEB properties -++ * are written out together and the journal becomes empty. This keeps the -++ * file system consistent - at all times the state can be recreated by reading -++ * the index and LEB properties and then replaying the journal. -++ * -++ * The commit is split into two parts named "commit start" and "commit end". -++ * During commit start, the commit process has exclusive access to the journal -++ * by holding the commit semaphore down for writing. As few I/O operations as -++ * possible are performed during commit start, instead the nodes that are to be -++ * written are merely identified. During commit end, the commit semaphore is no -++ * longer held and the journal is again in operation, allowing users to continue -++ * to use the file system while the bulk of the commit I/O is performed. The -++ * purpose of this two-step approach is to prevent the commit from causing any -++ * latency blips. Note that in any case, the commit does not prevent lookups -++ * (as permitted by the TNC mutex), or access to VFS data structures e.g. page -++ * cache. -++ */ -++ -++#include -++#include -++#include "ubifs.h" -++ -++/** -++ * do_commit - commit the journal. -++ * @c: UBIFS file-system description object -++ * -++ * This function implements UBIFS commit. It has to be called with commit lock -++ * locked. Returns zero in case of success and a negative error code in case of -++ * failure. -++ */ -++static int do_commit(struct ubifs_info *c) -++{ -++ int err, new_ltail_lnum, old_ltail_lnum, i; -++ struct ubifs_zbranch zroot; -++ struct ubifs_lp_stats lst; -++ -++ dbg_cmt("start"); -++ if (c->ro_media) { -++ err = -EROFS; -++ goto out_up; -++ } -++ -++ c->recovery_needs_commit = 0; -++ -++ /* Sync all write buffers (necessary for recovery) */ -++ for (i = 0; i < c->jhead_cnt; i++) { -++ err = ubifs_wbuf_sync(&c->jheads[i].wbuf); -++ if (err) -++ goto out_up; -++ } -++ -++ err = ubifs_gc_start_commit(c); -++ if (err) -++ goto out_up; -++ err = dbg_check_lprops(c); -++ if (err) -++ goto out_up; -++ err = ubifs_log_start_commit(c, &new_ltail_lnum); -++ if (err) -++ goto out_up; -++ err = ubifs_tnc_start_commit(c, &zroot); -++ if (err) -++ goto out_up; -++ err = ubifs_lpt_start_commit(c); -++ if (err) -++ goto out_up; -++ err = ubifs_orphan_start_commit(c); -++ if (err) -++ goto out_up; -++ -++ ubifs_get_lp_stats(c, &lst); -++ -++ up_write(&c->commit_sem); -++ -++ err = ubifs_tnc_end_commit(c); -++ if (err) -++ goto out; -++ err = ubifs_lpt_end_commit(c); -++ if (err) -++ goto out; -++ err = ubifs_orphan_end_commit(c); -++ if (err) -++ goto out; -++ old_ltail_lnum = c->ltail_lnum; -++ err = ubifs_log_end_commit(c, new_ltail_lnum); -++ if (err) -++ goto out; -++ err = dbg_check_old_index(c, &zroot); -++ if (err) -++ goto out; -++ -++ mutex_lock(&c->mst_mutex); -++ c->mst_node->cmt_no = cpu_to_le64(++c->cmt_no); -++ c->mst_node->log_lnum = cpu_to_le32(new_ltail_lnum); -++ c->mst_node->root_lnum = cpu_to_le32(zroot.lnum); -++ c->mst_node->root_offs = cpu_to_le32(zroot.offs); -++ c->mst_node->root_len = cpu_to_le32(zroot.len); -++ c->mst_node->ihead_lnum = cpu_to_le32(c->ihead_lnum); -++ c->mst_node->ihead_offs = cpu_to_le32(c->ihead_offs); -++ c->mst_node->index_size = cpu_to_le64(c->old_idx_sz); -++ c->mst_node->lpt_lnum = cpu_to_le32(c->lpt_lnum); -++ c->mst_node->lpt_offs = cpu_to_le32(c->lpt_offs); -++ c->mst_node->nhead_lnum = cpu_to_le32(c->nhead_lnum); -++ c->mst_node->nhead_offs = cpu_to_le32(c->nhead_offs); -++ c->mst_node->ltab_lnum = cpu_to_le32(c->ltab_lnum); -++ c->mst_node->ltab_offs = cpu_to_le32(c->ltab_offs); -++ c->mst_node->lsave_lnum = cpu_to_le32(c->lsave_lnum); -++ c->mst_node->lsave_offs = cpu_to_le32(c->lsave_offs); -++ c->mst_node->lscan_lnum = cpu_to_le32(c->lscan_lnum); -++ c->mst_node->empty_lebs = cpu_to_le32(lst.empty_lebs); -++ c->mst_node->idx_lebs = cpu_to_le32(lst.idx_lebs); -++ c->mst_node->total_free = cpu_to_le64(lst.total_free); -++ c->mst_node->total_dirty = cpu_to_le64(lst.total_dirty); -++ c->mst_node->total_used = cpu_to_le64(lst.total_used); -++ c->mst_node->total_dead = cpu_to_le64(lst.total_dead); -++ c->mst_node->total_dark = cpu_to_le64(lst.total_dark); -++ if (c->no_orphs) -++ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); -++ else -++ c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_NO_ORPHS); -++ err = ubifs_write_master(c); -++ mutex_unlock(&c->mst_mutex); -++ if (err) -++ goto out; -++ -++ err = ubifs_log_post_commit(c, old_ltail_lnum); -++ if (err) -++ goto out; -++ err = ubifs_gc_end_commit(c); -++ if (err) -++ goto out; -++ err = ubifs_lpt_post_commit(c); -++ if (err) -++ goto out; -++ -++ spin_lock(&c->cs_lock); -++ c->cmt_state = COMMIT_RESTING; -++ wake_up(&c->cmt_wq); -++ dbg_cmt("commit end"); -++ spin_unlock(&c->cs_lock); -++ -++ return 0; -++ -++out_up: -++ up_write(&c->commit_sem); -++out: -++ ubifs_err("commit failed, error %d", err); -++ spin_lock(&c->cs_lock); -++ c->cmt_state = COMMIT_BROKEN; -++ wake_up(&c->cmt_wq); -++ spin_unlock(&c->cs_lock); -++ ubifs_ro_mode(c, err); -++ return err; -++} -++ -++/** -++ * run_bg_commit - run background commit if it is needed. -++ * @c: UBIFS file-system description object -++ * -++ * This function runs background commit if it is needed. Returns zero in case -++ * of success and a negative error code in case of failure. -++ */ -++static int run_bg_commit(struct ubifs_info *c) -++{ -++ spin_lock(&c->cs_lock); -++ /* -++ * Run background commit only if background commit was requested or if -++ * commit is required. -++ */ -++ if (c->cmt_state != COMMIT_BACKGROUND && -++ c->cmt_state != COMMIT_REQUIRED) -++ goto out; -++ spin_unlock(&c->cs_lock); -++ -++ down_write(&c->commit_sem); -++ spin_lock(&c->cs_lock); -++ if (c->cmt_state == COMMIT_REQUIRED) -++ c->cmt_state = COMMIT_RUNNING_REQUIRED; -++ else if (c->cmt_state == COMMIT_BACKGROUND) -++ c->cmt_state = COMMIT_RUNNING_BACKGROUND; -++ else -++ goto out_cmt_unlock; -++ spin_unlock(&c->cs_lock); -++ -++ return do_commit(c); -++ -++out_cmt_unlock: -++ up_write(&c->commit_sem); -++out: -++ spin_unlock(&c->cs_lock); -++ return 0; -++} -++ -++/** -++ * ubifs_bg_thread - UBIFS background thread function. -++ * @info: points to the file-system description object -++ * -++ * This function implements various file-system background activities: -++ * o when a write-buffer timer expires it synchronizes the appropriate -++ * write-buffer; -++ * o when the journal is about to be full, it starts in-advance commit. -++ * -++ * Note, other stuff like background garbage collection may be added here in -++ * future. -++ */ -++int ubifs_bg_thread(void *info) -++{ -++ int err; -++ struct ubifs_info *c = info; -++ -++ ubifs_msg("background thread \"%s\" started, PID %d", -++ c->bgt_name, current->pid); -++ set_freezable(); -++ -++ while (1) { -++ if (kthread_should_stop()) -++ break; -++ -++ if (try_to_freeze()) -++ continue; -++ -++ set_current_state(TASK_INTERRUPTIBLE); -++ /* Check if there is something to do */ -++ if (!c->need_bgt) { -++ /* -++ * Nothing prevents us from going sleep now and -++ * be never woken up and block the task which -++ * could wait in 'kthread_stop()' forever. -++ */ -++ if (kthread_should_stop()) -++ break; -++ schedule(); -++ continue; -++ } else -++ __set_current_state(TASK_RUNNING); -++ -++ c->need_bgt = 0; -++ err = ubifs_bg_wbufs_sync(c); -++ if (err) -++ ubifs_ro_mode(c, err); -++ -++ run_bg_commit(c); -++ cond_resched(); -++ } -++ -++ dbg_msg("background thread \"%s\" stops", c->bgt_name); -++ return 0; -++} -++ -++/** -++ * ubifs_commit_required - set commit state to "required". -++ * @c: UBIFS file-system description object -++ * -++ * This function is called if a commit is required but cannot be done from the -++ * calling function, so it is just flagged instead. -++ */ -++void ubifs_commit_required(struct ubifs_info *c) -++{ -++ spin_lock(&c->cs_lock); -++ switch (c->cmt_state) { -++ case COMMIT_RESTING: -++ case COMMIT_BACKGROUND: -++ dbg_cmt("old: %s, new: %s", dbg_cstate(c->cmt_state), -++ dbg_cstate(COMMIT_REQUIRED)); -++ c->cmt_state = COMMIT_REQUIRED; -++ break; -++ case COMMIT_RUNNING_BACKGROUND: -++ dbg_cmt("old: %s, new: %s", dbg_cstate(c->cmt_state), -++ dbg_cstate(COMMIT_RUNNING_REQUIRED)); -++ c->cmt_state = COMMIT_RUNNING_REQUIRED; -++ break; -++ case COMMIT_REQUIRED: -++ case COMMIT_RUNNING_REQUIRED: -++ case COMMIT_BROKEN: -++ break; -++ } -++ spin_unlock(&c->cs_lock); -++} -++ -++/** -++ * ubifs_request_bg_commit - notify the background thread to do a commit. -++ * @c: UBIFS file-system description object -++ * -++ * This function is called if the journal is full enough to make a commit -++ * worthwhile, so background thread is kicked to start it. -++ */ -++void ubifs_request_bg_commit(struct ubifs_info *c) -++{ -++ spin_lock(&c->cs_lock); -++ if (c->cmt_state == COMMIT_RESTING) { -++ dbg_cmt("old: %s, new: %s", dbg_cstate(c->cmt_state), -++ dbg_cstate(COMMIT_BACKGROUND)); -++ c->cmt_state = COMMIT_BACKGROUND; -++ spin_unlock(&c->cs_lock); -++ ubifs_wake_up_bgt(c); -++ } else -++ spin_unlock(&c->cs_lock); -++} -++ -++/** -++ * wait_for_commit - wait for commit. -++ * @c: UBIFS file-system description object -++ * -++ * This function sleeps until the commit operation is no longer running. -++ */ -++static int wait_for_commit(struct ubifs_info *c) -++{ -++ dbg_cmt("pid %d goes sleep", current->pid); -++ -++ /* -++ * The following sleeps if the condition is false, and will be woken -++ * when the commit ends. It is possible, although very unlikely, that we -++ * will wake up and see the subsequent commit running, rather than the -++ * one we were waiting for, and go back to sleep. However, we will be -++ * woken again, so there is no danger of sleeping forever. -++ */ -++ wait_event(c->cmt_wq, c->cmt_state != COMMIT_RUNNING_BACKGROUND && -++ c->cmt_state != COMMIT_RUNNING_REQUIRED); -++ dbg_cmt("commit finished, pid %d woke up", current->pid); -++ return 0; -++} -++ -++/** -++ * ubifs_run_commit - run or wait for commit. -++ * @c: UBIFS file-system description object -++ * -++ * This function runs commit and returns zero in case of success and a negative -++ * error code in case of failure. -++ */ -++int ubifs_run_commit(struct ubifs_info *c) -++{ -++ int err = 0; -++ -++ spin_lock(&c->cs_lock); -++ if (c->cmt_state == COMMIT_BROKEN) { -++ err = -EINVAL; -++ goto out; -++ } -++ -++ if (c->cmt_state == COMMIT_RUNNING_BACKGROUND) -++ /* -++ * We set the commit state to 'running required' to indicate -++ * that we want it to complete as quickly as possible. -++ */ -++ c->cmt_state = COMMIT_RUNNING_REQUIRED; -++ -++ if (c->cmt_state == COMMIT_RUNNING_REQUIRED) { -++ spin_unlock(&c->cs_lock); -++ return wait_for_commit(c); -++ } -++ spin_unlock(&c->cs_lock); -++ -++ /* Ok, the commit is indeed needed */ -++ -++ down_write(&c->commit_sem); -++ spin_lock(&c->cs_lock); -++ /* -++ * Since we unlocked 'c->cs_lock', the state may have changed, so -++ * re-check it. -++ */ -++ if (c->cmt_state == COMMIT_BROKEN) { -++ err = -EINVAL; -++ goto out_cmt_unlock; -++ } -++ -++ if (c->cmt_state == COMMIT_RUNNING_BACKGROUND) -++ c->cmt_state = COMMIT_RUNNING_REQUIRED; -++ -++ if (c->cmt_state == COMMIT_RUNNING_REQUIRED) { -++ up_write(&c->commit_sem); -++ spin_unlock(&c->cs_lock); -++ return wait_for_commit(c); -++ } -++ c->cmt_state = COMMIT_RUNNING_REQUIRED; -++ spin_unlock(&c->cs_lock); -++ -++ err = do_commit(c); -++ return err; -++ -++out_cmt_unlock: -++ up_write(&c->commit_sem); -++out: -++ spin_unlock(&c->cs_lock); -++ return err; -++} -++ -++/** -++ * ubifs_recovery_commit - if needed, ensure a commit has run since recovery. -++ * @c: UBIFS file-system description object -++ * -++ * This function ensures that a commit has been run since recovery and before -++ * unmounting cleanly. Errors are ignored because in that case a subsequent -++ * unmount will not be clean. -++ * -++ * The recovery needs a commit when it updates TNC directly without there being -++ * a corresponding record of the change in the journal. In that case, if UBIFS -++ * were to unmount cleanly without having run a commit, the TNC changes would -++ * be lost. -++ */ -++void ubifs_recovery_commit(struct ubifs_info *c) -++{ -++ spin_lock(&c->cs_lock); -++ if (!c->recovery_needs_commit || -++ c->cmt_state == COMMIT_BROKEN || -++ c->cmt_state == COMMIT_RUNNING_BACKGROUND || -++ c->cmt_state == COMMIT_RUNNING_REQUIRED) { -++ spin_unlock(&c->cs_lock); -++ return; -++ } -++ spin_unlock(&c->cs_lock); -++ down_write(&c->commit_sem); -++ spin_lock(&c->cs_lock); -++ if (!c->recovery_needs_commit || -++ c->cmt_state == COMMIT_BROKEN || -++ c->cmt_state == COMMIT_RUNNING_BACKGROUND || -++ c->cmt_state == COMMIT_RUNNING_REQUIRED) { -++ spin_unlock(&c->cs_lock); -++ up_write(&c->commit_sem); -++ return; -++ } -++ c->cmt_state = COMMIT_RUNNING_REQUIRED; -++ spin_unlock(&c->cs_lock); -++ do_commit(c); -++} -++ -++/** -++ * ubifs_gc_should_commit - determine if it is time for GC to run commit. -++ * @c: UBIFS file-system description object -++ * -++ * This function is called by garbage collection to determine if commit should -++ * be run. If commit state is @COMMIT_BACKGROUND, which means that the journal -++ * is full enough to start commit, this function returns true. It is not -++ * absolutely necessary to commit yet, but it feels like this should be better -++ * then to keep doing GC. This function returns %1 if GC has to initiate commit -++ * and %0 if not. -++ */ -++int ubifs_gc_should_commit(struct ubifs_info *c) -++{ -++ int ret = 0; -++ -++ spin_lock(&c->cs_lock); -++ if (c->cmt_state == COMMIT_BACKGROUND) { -++ dbg_cmt("commit required now"); -++ c->cmt_state = COMMIT_REQUIRED; -++ } else -++ dbg_cmt("commit not requested"); -++ if (c->cmt_state == COMMIT_REQUIRED) -++ ret = 1; -++ spin_unlock(&c->cs_lock); -++ return ret; -++} -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ -++/** -++ * struct idx_node - hold index nodes during index tree traversal. -++ * @list: list -++ * @iip: index in parent (slot number of this indexing node in the parent -++ * indexing node) -++ * @upper_key: all keys in this indexing node have to be less or equivalent to -++ * this key -++ * @idx: index node (8-byte aligned because all node structures must be 8-byte -++ * aligned) -++ */ -++struct idx_node { -++ struct list_head list; -++ int iip; -++ union ubifs_key upper_key; -++ struct ubifs_idx_node idx __attribute__((aligned(8))); -++}; -++ -++/** -++ * dbg_old_index_check_init - get information for the next old index check. -++ * @c: UBIFS file-system description object -++ * @zroot: root of the index -++ * -++ * This function records information about the index that will be needed for the -++ * next old index check i.e. 'dbg_check_old_index()'. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot) -++{ -++ struct ubifs_idx_node *idx; -++ int lnum, offs, len, err = 0; -++ -++ c->old_zroot = *zroot; -++ -++ lnum = c->old_zroot.lnum; -++ offs = c->old_zroot.offs; -++ len = c->old_zroot.len; -++ -++ idx = kmalloc(c->max_idx_node_sz, GFP_NOFS); -++ if (!idx) -++ return -ENOMEM; -++ -++ err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs); -++ if (err) -++ goto out; -++ -++ c->old_zroot_level = le16_to_cpu(idx->level); -++ c->old_zroot_sqnum = le64_to_cpu(idx->ch.sqnum); -++out: -++ kfree(idx); -++ return err; -++} -++ -++/** -++ * dbg_check_old_index - check the old copy of the index. -++ * @c: UBIFS file-system description object -++ * @zroot: root of the new index -++ * -++ * In order to be able to recover from an unclean unmount, a complete copy of -++ * the index must exist on flash. This is the "old" index. The commit process -++ * must write the "new" index to flash without overwriting or destroying any -++ * part of the old index. This function is run at commit end in order to check -++ * that the old index does indeed exist completely intact. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot) -++{ -++ int lnum, offs, len, err = 0, uninitialized_var(last_level), child_cnt; -++ int first = 1, iip; -++ union ubifs_key lower_key, upper_key, l_key, u_key; -++ unsigned long long uninitialized_var(last_sqnum); -++ struct ubifs_idx_node *idx; -++ struct list_head list; -++ struct idx_node *i; -++ size_t sz; -++ -++ if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX)) -++ goto out; -++ -++ INIT_LIST_HEAD(&list); -++ -++ sz = sizeof(struct idx_node) + ubifs_idx_node_sz(c, c->fanout) - -++ UBIFS_IDX_NODE_SZ; -++ -++ /* Start at the old zroot */ -++ lnum = c->old_zroot.lnum; -++ offs = c->old_zroot.offs; -++ len = c->old_zroot.len; -++ iip = 0; -++ -++ /* -++ * Traverse the index tree preorder depth-first i.e. do a node and then -++ * its subtrees from left to right. -++ */ -++ while (1) { -++ struct ubifs_branch *br; -++ -++ /* Get the next index node */ -++ i = kmalloc(sz, GFP_NOFS); -++ if (!i) { -++ err = -ENOMEM; -++ goto out_free; -++ } -++ i->iip = iip; -++ /* Keep the index nodes on our path in a linked list */ -++ list_add_tail(&i->list, &list); -++ /* Read the index node */ -++ idx = &i->idx; -++ err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs); -++ if (err) -++ goto out_free; -++ /* Validate index node */ -++ child_cnt = le16_to_cpu(idx->child_cnt); -++ if (child_cnt < 1 || child_cnt > c->fanout) { -++ err = 1; -++ goto out_dump; -++ } -++ if (first) { -++ first = 0; -++ /* Check root level and sqnum */ -++ if (le16_to_cpu(idx->level) != c->old_zroot_level) { -++ err = 2; -++ goto out_dump; -++ } -++ if (le64_to_cpu(idx->ch.sqnum) != c->old_zroot_sqnum) { -++ err = 3; -++ goto out_dump; -++ } -++ /* Set last values as though root had a parent */ -++ last_level = le16_to_cpu(idx->level) + 1; -++ last_sqnum = le64_to_cpu(idx->ch.sqnum) + 1; -++ key_read(c, ubifs_idx_key(c, idx), &lower_key); -++ highest_ino_key(c, &upper_key, INUM_WATERMARK); -++ } -++ key_copy(c, &upper_key, &i->upper_key); -++ if (le16_to_cpu(idx->level) != last_level - 1) { -++ err = 3; -++ goto out_dump; -++ } -++ /* -++ * The index is always written bottom up hence a child's sqnum -++ * is always less than the parents. -++ */ -++ if (le64_to_cpu(idx->ch.sqnum) >= last_sqnum) { -++ err = 4; -++ goto out_dump; -++ } -++ /* Check key range */ -++ key_read(c, ubifs_idx_key(c, idx), &l_key); -++ br = ubifs_idx_branch(c, idx, child_cnt - 1); -++ key_read(c, &br->key, &u_key); -++ if (keys_cmp(c, &lower_key, &l_key) > 0) { -++ err = 5; -++ goto out_dump; -++ } -++ if (keys_cmp(c, &upper_key, &u_key) < 0) { -++ err = 6; -++ goto out_dump; -++ } -++ if (keys_cmp(c, &upper_key, &u_key) == 0) -++ if (!is_hash_key(c, &u_key)) { -++ err = 7; -++ goto out_dump; -++ } -++ /* Go to next index node */ -++ if (le16_to_cpu(idx->level) == 0) { -++ /* At the bottom, so go up until can go right */ -++ while (1) { -++ /* Drop the bottom of the list */ -++ list_del(&i->list); -++ kfree(i); -++ /* No more list means we are done */ -++ if (list_empty(&list)) -++ goto out; -++ /* Look at the new bottom */ -++ i = list_entry(list.prev, struct idx_node, -++ list); -++ idx = &i->idx; -++ /* Can we go right */ -++ if (iip + 1 < le16_to_cpu(idx->child_cnt)) { -++ iip = iip + 1; -++ break; -++ } else -++ /* Nope, so go up again */ -++ iip = i->iip; -++ } -++ } else -++ /* Go down left */ -++ iip = 0; -++ /* -++ * We have the parent in 'idx' and now we set up for reading the -++ * child pointed to by slot 'iip'. -++ */ -++ last_level = le16_to_cpu(idx->level); -++ last_sqnum = le64_to_cpu(idx->ch.sqnum); -++ br = ubifs_idx_branch(c, idx, iip); -++ lnum = le32_to_cpu(br->lnum); -++ offs = le32_to_cpu(br->offs); -++ len = le32_to_cpu(br->len); -++ key_read(c, &br->key, &lower_key); -++ if (iip + 1 < le16_to_cpu(idx->child_cnt)) { -++ br = ubifs_idx_branch(c, idx, iip + 1); -++ key_read(c, &br->key, &upper_key); -++ } else -++ key_copy(c, &i->upper_key, &upper_key); -++ } -++out: -++ err = dbg_old_index_check_init(c, zroot); -++ if (err) -++ goto out_free; -++ -++ return 0; -++ -++out_dump: -++ dbg_err("dumping index node (iip=%d)", i->iip); -++ dbg_dump_node(c, idx); -++ list_del(&i->list); -++ kfree(i); -++ if (!list_empty(&list)) { -++ i = list_entry(list.prev, struct idx_node, list); -++ dbg_err("dumping parent index node"); -++ dbg_dump_node(c, &i->idx); -++ } -++out_free: -++ while (!list_empty(&list)) { -++ i = list_entry(list.next, struct idx_node, list); -++ list_del(&i->list); -++ kfree(i); -++ } -++ ubifs_err("failed, error %d", err); -++ if (err > 0) -++ err = -EINVAL; -++ return err; -++} -++ -++#endif /* CONFIG_UBIFS_FS_DEBUG */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/compat.c linux-2.6.24.7/fs/ubifs/compat.c -+--- linux-2.6.24.7.old/fs/ubifs/compat.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/compat.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,480 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy -++ * Adrian Hunter -++ */ -++ -++#include "ubifs.h" -++#include -++ -++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)) -++#define BYTES_PER_LINE 32 -++ -++/** -++ * ubifs_hexdump - dump a buffer. -++ * @ptr: the buffer to dump -++ * @size: buffer size which must be multiple of 4 bytes -++ */ -++void ubifs_hexdump(const void *ptr, int size) -++{ -++ int i, k = 0, rows, columns; -++ const uint8_t *p = ptr; -++ -++ rows = size / BYTES_PER_LINE + size % BYTES_PER_LINE; -++ for (i = 0; i < rows; i++) { -++ int j; -++ -++ cond_resched(); -++ columns = min(size - k, BYTES_PER_LINE) / 4; -++ if (columns == 0) -++ break; -++ printk(KERN_DEBUG "%5d: ", i * BYTES_PER_LINE); -++ for (j = 0; j < columns; j++) { -++ int n, N; -++ -++ N = size - k > 4 ? 4 : size - k; -++ for (n = 0; n < N; n++) -++ printk("%02x", p[k++]); -++ printk(" "); -++ } -++ printk("\n"); -++ } -++} -++#endif /* LINUX_VERSION_CODE < 2.6.23 */ -++ -++#ifdef UBIFS_COMPAT_USE_OLD_IGET -++struct inode *ubifs_iget(struct super_block *sb, unsigned long inum) -++{ -++ struct inode *inode; -++ -++ inode = iget(sb, inum); -++ if (!inode) { -++ make_bad_inode(inode); -++ return ERR_PTR(-EINVAL); -++ } -++ -++ return inode; -++} -++ -++int validate_inode(struct ubifs_info *c, const struct inode *inode); -++ -++void ubifs_read_inode(struct inode *inode) -++{ -++ int err; -++ union ubifs_key key; -++ struct ubifs_ino_node *ino; -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ struct ubifs_inode *ui = ubifs_inode(inode); -++ -++ dbg_gen("inode %lu", inode->i_ino); -++ ubifs_assert(inode->i_state & I_LOCK); -++ -++ ino = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS); -++ if (!ino) { -++ err = -ENOMEM; -++ goto out; -++ } -++ -++ ino_key_init(c, &key, inode->i_ino); -++ -++ err = ubifs_tnc_lookup(c, &key, ino); -++ if (err) -++ goto out_ino; -++ -++ inode->i_flags |= (S_NOCMTIME | S_NOATIME); -++ inode->i_nlink = le32_to_cpu(ino->nlink); -++ inode->i_uid = le32_to_cpu(ino->uid); -++ inode->i_gid = le32_to_cpu(ino->gid); -++ inode->i_atime.tv_sec = (int64_t)le64_to_cpu(ino->atime_sec); -++ inode->i_atime.tv_nsec = le32_to_cpu(ino->atime_nsec); -++ inode->i_mtime.tv_sec = (int64_t)le64_to_cpu(ino->mtime_sec); -++ inode->i_mtime.tv_nsec = le32_to_cpu(ino->mtime_nsec); -++ inode->i_ctime.tv_sec = (int64_t)le64_to_cpu(ino->ctime_sec); -++ inode->i_ctime.tv_nsec = le32_to_cpu(ino->ctime_nsec); -++ inode->i_mode = le32_to_cpu(ino->mode); -++ inode->i_size = le64_to_cpu(ino->size); -++ -++ ui->data_len = le32_to_cpu(ino->data_len); -++ ui->flags = le32_to_cpu(ino->flags); -++ ui->compr_type = le16_to_cpu(ino->compr_type); -++ ui->creat_sqnum = le64_to_cpu(ino->creat_sqnum); -++ ui->xattr_cnt = le32_to_cpu(ino->xattr_cnt); -++ ui->xattr_size = le64_to_cpu(ino->xattr_size); -++ ui->xattr_names = le32_to_cpu(ino->xattr_names); -++ -++ err = validate_inode(c, inode); -++ if (err) -++ goto out_invalid; -++ -++ switch (inode->i_mode & S_IFMT) { -++ case S_IFREG: -++ inode->i_mapping->a_ops = &ubifs_file_address_operations; -++ inode->i_op = &ubifs_file_inode_operations; -++ inode->i_fop = &ubifs_file_operations; -++ if (ui->data_len != 0) { -++ err = 10; -++ goto out_invalid; -++ } -++ break; -++ case S_IFDIR: -++ inode->i_op = &ubifs_dir_inode_operations; -++ inode->i_fop = &ubifs_dir_operations; -++ if (ui->data_len != 0) { -++ err = 11; -++ goto out_invalid; -++ } -++ break; -++ case S_IFLNK: -++ inode->i_op = &ubifs_symlink_inode_operations; -++ if (ui->data_len <= 0 || ui->data_len > UBIFS_MAX_INO_DATA) { -++ err = 12; -++ goto out_invalid; -++ } -++ ui->data = kmalloc(ui->data_len + 1, GFP_KERNEL); -++ if (!ui->data) { -++ err = -ENOMEM; -++ goto out_ino; -++ } -++ memcpy(ui->data, ino->data, ui->data_len); -++ ((char *)ui->data)[ui->data_len] = '\0'; -++ break; -++ case S_IFBLK: -++ case S_IFCHR: -++ { -++ dev_t rdev; -++ union ubifs_dev_desc *dev; -++ -++ ui->data = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS); -++ if (!ui->data) { -++ err = -ENOMEM; -++ goto out_ino; -++ } -++ -++ dev = (union ubifs_dev_desc *)ino->data; -++ if (ui->data_len == sizeof(dev->new)) { -++ rdev = new_decode_dev(__le32_to_cpu(dev->new)); -++ } else if (ui->data_len == sizeof(dev->huge)) { -++ rdev = huge_decode_dev(__le64_to_cpu(dev->huge)); -++ } else { -++ err = 13; -++ goto out_invalid; -++ } -++ inode->i_op = &ubifs_file_inode_operations; -++ init_special_inode(inode, inode->i_mode, rdev); -++ break; -++ } -++ case S_IFSOCK: -++ case S_IFIFO: -++ inode->i_op = &ubifs_file_inode_operations; -++ init_special_inode(inode, inode->i_mode, 0); -++ if (ui->data_len != 0) { -++ err = 14; -++ goto out_invalid; -++ } -++ break; -++ default: -++ err = 15; -++ goto out_invalid; -++ } -++ -++ ubifs_set_inode_flags(inode); -++ kfree(ino); -++ return; -++ -++out_invalid: -++ ubifs_err("inode %lu validation failed, error %d", inode->i_ino, err); -++ dbg_dump_inode(c, inode); -++ dbg_dump_node(c, ino); -++ err = -EINVAL; -++out_ino: -++ kfree(ino); -++out: -++ ubifs_err("failed to read inode %lu, error %d", inode->i_ino, err); -++ make_bad_inode(inode); -++ return; -++} -++#endif /* UBIFS_COMPAT_USE_OLD_IGET */ -++ -++#ifdef UBIFS_COMPAT_USE_OLD_PREPARE_WRITE -++int ubifs_prepare_write(struct file *file, struct page *page, unsigned from, -++ unsigned to) -++{ -++ struct inode *inode = page->mapping->host; -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; -++ struct ubifs_budget_req req; -++ int err; -++ -++ ubifs_assert(PageLocked(page)); -++ ubifs_assert(mutex_is_locked(&inode->i_mutex)); -++ ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY)); -++ -++ if (c->ro_media) -++ return -EINVAL; -++ -++ if (!PageUptodate(page)) { -++ /* -++ * The page is not loaded from the flash and has to be loaded -++ * unless we are writing all of it. -++ */ -++ if (from == 0 && to == PAGE_CACHE_SIZE) -++ /* -++ * Set the PG_checked flag to make the further code -++ * allocate full budget, because we do not know whether -++ * the page exists on the flash media or not. -++ */ -++ SetPageChecked(page); -++ else { -++ err = do_readpage(page); -++ if (err) -++ return err; -++ } -++ -++ SetPageUptodate(page); -++ ClearPageError(page); -++ } -++ -++ memset(&req, 0, sizeof(struct ubifs_budget_req)); -++ if (!PagePrivate(page)) { -++ /* -++ * If the PG_Checked flag is set, the page corresponds to a -++ * hole or to a place beyond the inode. In this case we have to -++ * budget for a new page, otherwise for a dirtied page. -++ */ -++ if (PageChecked(page)) -++ req.new_page = 1; -++ else -++ req.dirtied_page = 1; -++ } else -++ req.locked_pg = 1; -++ -++ if (pos > inode->i_size) -++ /* -++ * We are writing beyond the file which means we are going to -++ * change inode size and make the inode dirty. And in turn, -++ * this means we have to budget for making the inode dirty. -++ * -++ * Note, if the inode is already dirty, -++ * 'ubifs_budget_inode_op()' will not allocate any budget, -++ * but will just lock the @budg_mutex of the inode to prevent -++ * it from becoming clean before we have changed its size, -++ * which is going to happen in 'ubifs_write_end()'. -++ */ -++ err = ubifs_budget_inode_op(c, inode, &req); -++ else -++ /* -++ * The inode is not going to be marked as dirty by this write -++ * operation, do do not budget for this. -++ */ -++ err = ubifs_budget_space(c, &req); -++ -++ return err; -++} -++ -++int ubifs_commit_write(struct file *file, struct page *page, unsigned from, -++ unsigned to) -++{ -++ struct inode *inode = page->mapping->host; -++ struct ubifs_inode *ui = ubifs_inode(inode); -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; -++ -++ dbg_gen("ino %lu, pg %lu, offs %lld-%lld (in pg: %u-%u, %u bytes) " -++ "flags %#lx", inode->i_ino, page->index, pos - to + from, -++ pos, from, to, to - from, page->flags); -++ ubifs_assert(PageUptodate(page)); -++ ubifs_assert(mutex_is_locked(&inode->i_mutex)); -++ -++ if (!PagePrivate(page)) { -++ SetPagePrivate(page); -++ atomic_long_inc(&c->dirty_pg_cnt); -++ __set_page_dirty_nobuffers(page); -++ } -++ -++ if (pos > inode->i_size) { -++ i_size_write(inode, pos); -++ -++ /* -++ * Note, we do not set 'I_DIRTY_PAGES' (which means that the -++ * inode has dirty pages), this has been done in -++ * '__set_page_dirty_nobuffers()'. -++ */ -++ mark_inode_dirty_sync(inode); -++ -++ /* -++ * The inode has been marked dirty, unlock it. This is a bit -++ * hacky because normally we would have to call -++ * 'ubifs_release_ino_dirty()'. But we know there is nothing -++ * to release because page's budget will be released -++ * in 'ubifs_write_inode()', so just unlock the inode here for -++ * optimization. -++ */ -++ mutex_unlock(&ui->budg_mutex); -++ } -++ -++ return 0; -++} -++ -++#include -++ -++#define MAX_SHRINK_RETRIES 8 -++#define MAX_GC_RETRIES 4 -++#define MAX_CMT_RETRIES 2 -++#define MAX_NOSPC_RETRIES 1 -++#define NR_TO_WRITE 16 -++ -++struct retries_info { -++ long long prev_liability; -++ unsigned int shrink_cnt; -++ unsigned int shrink_retries:5; -++ unsigned int try_gc:1; -++ unsigned int gc_retries:4; -++ unsigned int cmt_retries:3; -++ unsigned int nospc_retries:1; -++}; -++ -++static int shrink_liability(struct ubifs_info *c, int nr_to_write, -++ int locked_pg) -++{ -++ struct writeback_control wbc = { -++ .sync_mode = WB_SYNC_NONE, -++ .range_end = LLONG_MAX, -++ .nr_to_write = nr_to_write, -++ .skip_locked_pages = locked_pg, -++ }; -++ -++ writeback_inodes_sb(c->vfs_sb, &wbc); -++ dbg_budg("%ld pages were written back", nr_to_write - wbc.nr_to_write); -++ return nr_to_write - wbc.nr_to_write; -++} -++ -++static int run_gc(struct ubifs_info *c) -++{ -++ int err, lnum; -++ -++ /* Make some free space by garbage-collecting dirty space */ -++ down_read(&c->commit_sem); -++ lnum = ubifs_garbage_collect(c, 1); -++ up_read(&c->commit_sem); -++ if (lnum < 0) -++ return lnum; -++ -++ /* GC freed one LEB, return it to lprops */ -++ dbg_budg("GC freed LEB %d", lnum); -++ err = ubifs_return_leb(c, lnum); -++ if (err) -++ return err; -++ -++ return 0; -++} -++ -++int ubifs_make_free_space(struct ubifs_info *c, struct retries_info *ri, -++ int locked_pg) -++{ -++ int err; -++ -++ /* -++ * If we have some dirty pages and inodes (liability), try to write -++ * them back unless this was tried too many times without effect -++ * already. -++ */ -++ if (ri->shrink_retries < MAX_SHRINK_RETRIES && !ri->try_gc) { -++ long long liability; -++ -++ spin_lock(&c->space_lock); -++ liability = c->budg_idx_growth + c->budg_data_growth + -++ c->budg_dd_growth; -++ spin_unlock(&c->space_lock); -++ -++ if (ri->prev_liability >= liability) { -++ /* Liability does not shrink, next time try GC then */ -++ ri->shrink_retries += 1; -++ if (ri->gc_retries < MAX_GC_RETRIES) -++ ri->try_gc = 1; -++ dbg_budg("liability did not shrink: retries %d of %d", -++ ri->shrink_retries, MAX_SHRINK_RETRIES); -++ } -++ -++ dbg_budg("force write-back (count %d)", ri->shrink_cnt); -++ shrink_liability(c, NR_TO_WRITE + ri->shrink_cnt, locked_pg); -++ -++ ri->prev_liability = liability; -++ ri->shrink_cnt += 1; -++ return -EAGAIN; -++ } -++ -++ /* -++ * Try to run garbage collector unless it was already tried too many -++ * times. -++ */ -++ if (ri->gc_retries < MAX_GC_RETRIES) { -++ ri->gc_retries += 1; -++ dbg_budg("run GC, retries %d of %d", -++ ri->gc_retries, MAX_GC_RETRIES); -++ -++ ri->try_gc = 0; -++ err = run_gc(c); -++ if (!err) -++ return -EAGAIN; -++ -++ if (err == -EAGAIN) { -++ dbg_budg("GC asked to commit"); -++ err = ubifs_run_commit(c); -++ if (err) -++ return err; -++ return -EAGAIN; -++ } -++ -++ if (err != -ENOSPC) -++ return err; -++ -++ /* -++ * GC could not make any progress. If this is the first time, -++ * then it makes sense to try to commit, because it might make -++ * some dirty space. -++ */ -++ dbg_budg("GC returned -ENOSPC, retries %d", -++ ri->nospc_retries); -++ if (ri->nospc_retries >= MAX_NOSPC_RETRIES) -++ return err; -++ ri->nospc_retries += 1; -++ } -++ -++ /* Neither GC nor write-back helped, try to commit */ -++ if (ri->cmt_retries < MAX_CMT_RETRIES) { -++ ri->cmt_retries += 1; -++ dbg_budg("run commit, retries %d of %d", -++ ri->cmt_retries, MAX_CMT_RETRIES); -++ err = ubifs_run_commit(c); -++ if (err) -++ return err; -++ return -EAGAIN; -++ } -++ -++ return -ENOSPC; -++} -++ -++#endif /* UBIFS_COMPAT_USE_OLD_PREPARE_WRITE */ -++ -++#ifdef UBIFS_COMPAT_NO_SHARED_MMAP -++int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma) -++{ -++ return generic_file_readonly_mmap(file, vma); -++} -++#endif /* UBIFS_COMPAT_NO_SHARED_MMAP */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/compat.h linux-2.6.24.7/fs/ubifs/compat.h -+--- linux-2.6.24.7.old/fs/ubifs/compat.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/compat.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,88 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Author: Artem Bityutskiy -++ * Adrian Hunter -++ */ -++ -++#ifndef __UBIFS_COMPAT_H__ -++#define __UBIFS_COMPAT_H__ -++ -++#include -++ -++struct inode; -++struct file; -++struct page; -++struct ubifs_info; -++struct retries_info; -++ -++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)) -++/* iget() does not exist since 2.6.25 */ -++#define UBIFS_COMPAT_USE_OLD_IGET -++void ubifs_read_inode(struct inode *inode); -++#endif -++ -++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) -++/* -++ * We have write_begin() write_end() instead of prepare_write(), commit_write() -++ * since 2.6.24. -++ */ -++#define UBIFS_COMPAT_USE_OLD_PREPARE_WRITE -++#define do_readpage(page) ubifs_do_readpage(page) -++int ubifs_do_readpage(struct page *page); -++int ubifs_prepare_write(struct file *file, struct page *page, unsigned from, -++ unsigned to); -++int ubifs_commit_write(struct file *file, struct page *page, unsigned from, -++ unsigned to); -++int ubifs_make_free_space(struct ubifs_info *c, struct retries_info *ri, -++ int locked_pg); -++#define bdi_init(x) 0 -++#define bdi_destroy(x) -++#endif -++ -++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)) -++#define UBIFS_COMPAT_NO_SHRINKER -++#define register_shrinker(x) -++#define unregister_shrinker(x) -++#define dbg_mempressure_init() -++#define dbg_mempressure_exit() -++#define set_freezable() -++#define is_owner_or_cap(inode) \ -++ ((current->fsuid == (inode)->i_uid) || capable(CAP_FOWNER)) -++/* This is to hide slab cache interface changes - destructor was dropped */ -++#define UBIFSCOMPATNULL ,NULL -++#else -++#define UBIFSCOMPATNULL -++#endif -++ -++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)) -++#define uninitialized_var(x) x = x -++/* print_hex_dump() did not exist in kernel prior to 2.6.22 */ -++#define print_hex_dump(a, b, c, f, e, buf, len, g) ubifs_hexdump(buf, len) -++void ubifs_hexdump(const void *ptr, int size); -++/* -++ * Older kernel have no '->page_mkwrite()' call-back in -++ * 'struct vm_operations_struct', so we just do not support writeble mmaps. The -++ * support can be added if someone needs it badly, though. -++ */ -++int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma); -++#define UBIFS_COMPAT_NO_SHARED_MMAP -++#endif -++ -++ -++#endif /* !__UBIFS_COMPAT_H__ */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/compress.c linux-2.6.24.7/fs/ubifs/compress.c -+--- linux-2.6.24.7.old/fs/ubifs/compress.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/compress.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,253 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * Copyright (C) 2006, 2007 University of Szeged, Hungary -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Adrian Hunter -++ * Artem Bityutskiy (Битюцкий Ðртём) -++ * Zoltan Sogor -++ */ -++ -++/* -++ * This file provides a single place to access to compression and -++ * decompression. -++ */ -++ -++#include -++#include "ubifs.h" -++ -++/* Fake description object for the "none" compressor */ -++static struct ubifs_compressor none_compr = { -++ .compr_type = UBIFS_COMPR_NONE, -++ .name = "no compression", -++ .capi_name = "", -++}; -++ -++#ifdef CONFIG_UBIFS_FS_LZO -++static DEFINE_MUTEX(lzo_mutex); -++ -++static struct ubifs_compressor lzo_compr = { -++ .compr_type = UBIFS_COMPR_LZO, -++ .comp_mutex = &lzo_mutex, -++ .name = "LZO", -++ .capi_name = "lzo", -++}; -++#else -++static struct ubifs_compressor lzo_compr = { -++ .compr_type = UBIFS_COMPR_LZO, -++ .name = "LZO", -++}; -++#endif -++ -++#ifdef CONFIG_UBIFS_FS_ZLIB -++static DEFINE_MUTEX(deflate_mutex); -++static DEFINE_MUTEX(inflate_mutex); -++ -++static struct ubifs_compressor zlib_compr = { -++ .compr_type = UBIFS_COMPR_ZLIB, -++ .comp_mutex = &deflate_mutex, -++ .decomp_mutex = &inflate_mutex, -++ .name = "zlib", -++ .capi_name = "deflate", -++}; -++#else -++static struct ubifs_compressor zlib_compr = { -++ .compr_type = UBIFS_COMPR_ZLIB, -++ .name = "zlib", -++}; -++#endif -++ -++/* All UBIFS compressors */ -++struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; -++ -++/** -++ * ubifs_compress - compress data. -++ * @in_buf: data to compress -++ * @in_len: length of the data to compress -++ * @out_buf: output buffer where compressed data should be stored -++ * @out_len: output buffer length is returned here -++ * @compr_type: type of compression to use on enter, actually used compression -++ * type on exit -++ * -++ * This function compresses input buffer @in_buf of length @in_len and stores -++ * the result in the output buffer @out_buf and the resulting length in -++ * @out_len. If the input buffer does not compress, it is just copied to the -++ * @out_buf. The same happens if @compr_type is %UBIFS_COMPR_NONE or if -++ * compression error occurred. -++ * -++ * Note, if the input buffer was not compressed, it is copied to the output -++ * buffer and %UBIFS_COMPR_NONE is returned in @compr_type. -++ * -++ * This functions returns %0 on success or a negative error code on failure. -++ */ -++void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len, -++ int *compr_type) -++{ -++ int err; -++ struct ubifs_compressor *compr = ubifs_compressors[*compr_type]; -++ -++ if (*compr_type == UBIFS_COMPR_NONE) -++ goto no_compr; -++ -++ /* If the input data is small, do not even try to compress it */ -++ if (in_len < UBIFS_MIN_COMPR_LEN) -++ goto no_compr; -++ -++ if (compr->comp_mutex) -++ mutex_lock(compr->comp_mutex); -++ err = crypto_comp_compress(compr->cc, in_buf, in_len, out_buf, -++ out_len); -++ if (compr->comp_mutex) -++ mutex_unlock(compr->comp_mutex); -++ if (unlikely(err)) { -++ ubifs_warn("cannot compress %d bytes, compressor %s, " -++ "error %d, leave data uncompressed", -++ in_len, compr->name, err); -++ goto no_compr; -++ } -++ -++ /* -++ * Presently, we just require that compression results in less data, -++ * rather than any defined minimum compression ratio or amount. -++ */ -++ if (ALIGN(*out_len, 8) >= ALIGN(in_len, 8)) -++ goto no_compr; -++ -++ return; -++ -++no_compr: -++ memcpy(out_buf, in_buf, in_len); -++ *out_len = in_len; -++ *compr_type = UBIFS_COMPR_NONE; -++} -++ -++/** -++ * ubifs_decompress - decompress data. -++ * @in_buf: data to decompress -++ * @in_len: length of the data to decompress -++ * @out_buf: output buffer where decompressed data should -++ * @out_len: output length is returned here -++ * @compr_type: type of compression -++ * -++ * This function decompresses data from buffer @in_buf into buffer @out_buf. -++ * The length of the uncompressed data is returned in @out_len. This functions -++ * returns %0 on success or a negative error code on failure. -++ */ -++int ubifs_decompress(const void *in_buf, int in_len, void *out_buf, -++ int *out_len, int compr_type) -++{ -++ int err; -++ struct ubifs_compressor *compr; -++ -++ if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) { -++ ubifs_err("invalid compression type %d", compr_type); -++ return -EINVAL; -++ } -++ -++ compr = ubifs_compressors[compr_type]; -++ -++ if (unlikely(!compr->capi_name)) { -++ ubifs_err("%s compression is not compiled in", compr->name); -++ return -EINVAL; -++ } -++ -++ if (compr_type == UBIFS_COMPR_NONE) { -++ memcpy(out_buf, in_buf, in_len); -++ *out_len = in_len; -++ return 0; -++ } -++ -++ if (compr->decomp_mutex) -++ mutex_lock(compr->decomp_mutex); -++ err = crypto_comp_decompress(compr->cc, in_buf, in_len, out_buf, -++ out_len); -++ if (compr->decomp_mutex) -++ mutex_unlock(compr->decomp_mutex); -++ if (err) -++ ubifs_err("cannot decompress %d bytes, compressor %s, " -++ "error %d", in_len, compr->name, err); -++ -++ return err; -++} -++ -++/** -++ * compr_init - initialize a compressor. -++ * @compr: compressor description object -++ * -++ * This function initializes the requested compressor and returns zero in case -++ * of success or a negative error code in case of failure. -++ */ -++static int __init compr_init(struct ubifs_compressor *compr) -++{ -++ if (compr->capi_name) { -++ compr->cc = crypto_alloc_comp(compr->capi_name, 0, 0); -++ if (IS_ERR(compr->cc)) { -++ ubifs_err("cannot initialize compressor %s, error %ld", -++ compr->name, PTR_ERR(compr->cc)); -++ return PTR_ERR(compr->cc); -++ } -++ } -++ -++ ubifs_compressors[compr->compr_type] = compr; -++ return 0; -++} -++ -++/** -++ * compr_exit - de-initialize a compressor. -++ * @compr: compressor description object -++ */ -++static void compr_exit(struct ubifs_compressor *compr) -++{ -++ if (compr->capi_name) -++ crypto_free_comp(compr->cc); -++ return; -++} -++ -++/** -++ * ubifs_compressors_init - initialize UBIFS compressors. -++ * -++ * This function initializes the compressor which were compiled in. Returns -++ * zero in case of success and a negative error code in case of failure. -++ */ -++int __init ubifs_compressors_init(void) -++{ -++ int err; -++ -++ err = compr_init(&lzo_compr); -++ if (err) -++ return err; -++ -++ err = compr_init(&zlib_compr); -++ if (err) -++ goto out_lzo; -++ -++ ubifs_compressors[UBIFS_COMPR_NONE] = &none_compr; -++ return 0; -++ -++out_lzo: -++ compr_exit(&lzo_compr); -++ return err; -++} -++ -++/** -++ * ubifs_compressors_exit - de-initialize UBIFS compressors. -++ */ -++void __exit ubifs_compressors_exit(void) -++{ -++ compr_exit(&lzo_compr); -++ compr_exit(&zlib_compr); -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/debug.c linux-2.6.24.7/fs/ubifs/debug.c -+--- linux-2.6.24.7.old/fs/ubifs/debug.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/debug.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1517 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* -++ * This file implements most of the debugging stuff which is compiled in only -++ * when it is enabled. But some debugging check functions are implemented in -++ * corresponding subsystem, just because they are closely related and utilize -++ * various local functions of those subsystems. -++ */ -++ -++#define UBIFS_DBG_PRESERVE_UBI -++ -++#include "ubifs.h" -++#include -++#include -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ -++DEFINE_SPINLOCK(dbg_lock); -++ -++static char dbg_key_buf0[128]; -++static char dbg_key_buf1[128]; -++ -++unsigned int ubifs_msg_flags = UBIFS_MSG_FLAGS_DEFAULT; -++unsigned int ubifs_chk_flags = UBIFS_CHK_FLAGS_DEFAULT; -++unsigned int ubifs_tst_flags; -++ -++module_param_named(debug_msgs, ubifs_msg_flags, uint, S_IRUGO | S_IWUSR); -++module_param_named(debug_chks, ubifs_chk_flags, uint, S_IRUGO | S_IWUSR); -++module_param_named(debug_tsts, ubifs_tst_flags, uint, S_IRUGO | S_IWUSR); -++ -++MODULE_PARM_DESC(debug_msgs, "Debug message type flags"); -++MODULE_PARM_DESC(debug_chks, "Debug check flags"); -++MODULE_PARM_DESC(debug_tsts, "Debug special test flags"); -++ -++static const char *get_key_fmt(int fmt) -++{ -++ switch (fmt) { -++ case UBIFS_SIMPLE_KEY_FMT: -++ return "simple"; -++ default: -++ return "unknown/invalid format"; -++ } -++} -++ -++static const char *get_key_hash(int hash) -++{ -++ switch (hash) { -++ case UBIFS_KEY_HASH_R5: -++ return "R5"; -++ case UBIFS_KEY_HASH_TEST: -++ return "test"; -++ default: -++ return "unknown/invalid name hash"; -++ } -++} -++ -++static const char *get_key_type(int type) -++{ -++ switch (type) { -++ case UBIFS_INO_KEY: -++ return "inode"; -++ case UBIFS_DENT_KEY: -++ return "direntry"; -++ case UBIFS_XENT_KEY: -++ return "xentry"; -++ case UBIFS_DATA_KEY: -++ return "data"; -++ case UBIFS_TRUN_KEY: -++ return "truncate"; -++ default: -++ return "unknown/invalid key"; -++ } -++} -++ -++static void sprintf_key(const struct ubifs_info *c, const union ubifs_key *key, -++ char *buffer) -++{ -++ char *p = buffer; -++ int type = key_type(c, key); -++ -++ if (c->key_fmt == UBIFS_SIMPLE_KEY_FMT) { -++ switch (type) { -++ case UBIFS_INO_KEY: -++ sprintf(p, "(%lu, %s)", key_ino(c, key), -++ get_key_type(type)); -++ break; -++ case UBIFS_DENT_KEY: -++ case UBIFS_XENT_KEY: -++ sprintf(p, "(%lu, %s, %#08x)", key_ino(c, key), -++ get_key_type(type), key_hash(c, key)); -++ break; -++ case UBIFS_DATA_KEY: -++ sprintf(p, "(%lu, %s, %u)", key_ino(c, key), -++ get_key_type(type), key_block(c, key)); -++ break; -++ case UBIFS_TRUN_KEY: -++ sprintf(p, "(%lu, %s)", -++ key_ino(c, key), get_key_type(type)); -++ break; -++ default: -++ sprintf(p, "(bad key type: %#08x, %#08x)", -++ key->u32[0], key->u32[1]); -++ } -++ } else -++ sprintf(p, "bad key format %d", c->key_fmt); -++} -++ -++const char *dbg_key_str0(const struct ubifs_info *c, const union ubifs_key *key) -++{ -++ /* dbg_lock must be held */ -++ sprintf_key(c, key, dbg_key_buf0); -++ return dbg_key_buf0; -++} -++ -++const char *dbg_key_str1(const struct ubifs_info *c, const union ubifs_key *key) -++{ -++ /* dbg_lock must be held */ -++ sprintf_key(c, key, dbg_key_buf1); -++ return dbg_key_buf1; -++} -++ -++const char *dbg_ntype(int type) -++{ -++ switch (type) { -++ case UBIFS_PAD_NODE: -++ return "padding node"; -++ case UBIFS_SB_NODE: -++ return "superblock node"; -++ case UBIFS_MST_NODE: -++ return "master node"; -++ case UBIFS_REF_NODE: -++ return "reference node"; -++ case UBIFS_INO_NODE: -++ return "inode node"; -++ case UBIFS_DENT_NODE: -++ return "direntry node"; -++ case UBIFS_XENT_NODE: -++ return "xentry node"; -++ case UBIFS_DATA_NODE: -++ return "data node"; -++ case UBIFS_TRUN_NODE: -++ return "truncate node"; -++ case UBIFS_IDX_NODE: -++ return "indexing node"; -++ case UBIFS_CS_NODE: -++ return "commit start node"; -++ case UBIFS_ORPH_NODE: -++ return "orphan node"; -++ default: -++ return "unknown node"; -++ } -++} -++ -++static const char *dbg_gtype(int type) -++{ -++ switch (type) { -++ case UBIFS_NO_NODE_GROUP: -++ return "no node group"; -++ case UBIFS_IN_NODE_GROUP: -++ return "in node group"; -++ case UBIFS_LAST_OF_NODE_GROUP: -++ return "last of node group"; -++ default: -++ return "unknown"; -++ } -++} -++ -++const char *dbg_cstate(int cmt_state) -++{ -++ switch (cmt_state) { -++ case COMMIT_RESTING: -++ return "commit resting"; -++ case COMMIT_BACKGROUND: -++ return "background commit requested"; -++ case COMMIT_REQUIRED: -++ return "commit required"; -++ case COMMIT_RUNNING_BACKGROUND: -++ return "BACKGROUND commit running"; -++ case COMMIT_RUNNING_REQUIRED: -++ return "commit running and required"; -++ case COMMIT_BROKEN: -++ return "broken commit"; -++ default: -++ return "unknown commit state"; -++ } -++} -++ -++static void dump_ch(const struct ubifs_ch *ch) -++{ -++ printk(KERN_DEBUG "\tmagic %#x\n", le32_to_cpu(ch->magic)); -++ printk(KERN_DEBUG "\tcrc %#x\n", le32_to_cpu(ch->crc)); -++ printk(KERN_DEBUG "\tnode_type %d (%s)\n", ch->node_type, -++ dbg_ntype(ch->node_type)); -++ printk(KERN_DEBUG "\tgroup_type %d (%s)\n", ch->group_type, -++ dbg_gtype(ch->group_type)); -++ printk(KERN_DEBUG "\tsqnum %llu\n", -++ (unsigned long long)le64_to_cpu(ch->sqnum)); -++ printk(KERN_DEBUG "\tlen %u\n", le32_to_cpu(ch->len)); -++} -++ -++void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode) -++{ -++ const struct ubifs_inode *ui = ubifs_inode(inode); -++ -++ printk(KERN_DEBUG "inode %lu\n", inode->i_ino); -++ printk(KERN_DEBUG "size %llu\n", -++ (unsigned long long)i_size_read(inode)); -++ printk(KERN_DEBUG "nlink %u\n", inode->i_nlink); -++ printk(KERN_DEBUG "uid %u\n", (unsigned int)inode->i_uid); -++ printk(KERN_DEBUG "gid %u\n", (unsigned int)inode->i_gid); -++ printk(KERN_DEBUG "atime %u.%u\n", -++ (unsigned int)inode->i_atime.tv_sec, -++ (unsigned int)inode->i_atime.tv_nsec); -++ printk(KERN_DEBUG "mtime %u.%u\n", -++ (unsigned int)inode->i_mtime.tv_sec, -++ (unsigned int)inode->i_mtime.tv_nsec); -++ printk(KERN_DEBUG "ctime %u.%u\n", -++ (unsigned int)inode->i_ctime.tv_sec, -++ (unsigned int)inode->i_ctime.tv_nsec); -++ printk(KERN_DEBUG "creat_sqnum %llu\n", ui->creat_sqnum); -++ printk(KERN_DEBUG "xattr_size %lld\n", ui->xattr_size); -++ printk(KERN_DEBUG "xattr_cnt %d\n", ui->xattr_cnt); -++ printk(KERN_DEBUG "xattr_names %d\n", ui->xattr_names); -++ printk(KERN_DEBUG "dirty %u\n", ui->dirty); -++ printk(KERN_DEBUG "xattr %u\n", ui->xattr); -++ printk(KERN_DEBUG "flags %d\n", ui->flags); -++ printk(KERN_DEBUG "compr_type %d\n", ui->compr_type); -++ printk(KERN_DEBUG "data_len %d\n", ui->data_len); -++} -++ -++void dbg_dump_node(const struct ubifs_info *c, const void *node) -++{ -++ int i, n; -++ union ubifs_key key; -++ const struct ubifs_ch *ch = node; -++ -++ if (dbg_failure_mode) -++ return; -++ -++ /* If the magic is incorrect, just hexdump the first bytes */ -++ if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC) { -++ printk(KERN_DEBUG "Not a node, first %zu bytes:", UBIFS_CH_SZ); -++ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, -++ (void *)node, UBIFS_CH_SZ, 1); -++ return; -++ } -++ -++ spin_lock(&dbg_lock); -++ dump_ch(node); -++ -++ switch (ch->node_type) { -++ case UBIFS_PAD_NODE: -++ { -++ const struct ubifs_pad_node *pad = node; -++ -++ printk(KERN_DEBUG "\tpad_len %u\n", -++ le32_to_cpu(pad->pad_len)); -++ break; -++ } -++ case UBIFS_SB_NODE: -++ { -++ const struct ubifs_sb_node *sup = node; -++ unsigned int sup_flags = le32_to_cpu(sup->flags); -++ -++ printk(KERN_DEBUG "\tkey_hash %d (%s)\n", -++ (int)sup->key_hash, get_key_hash(sup->key_hash)); -++ printk(KERN_DEBUG "\tkey_fmt %d (%s)\n", -++ (int)sup->key_fmt, get_key_fmt(sup->key_fmt)); -++ printk(KERN_DEBUG "\tflags %#x\n", sup_flags); -++ printk(KERN_DEBUG "\t big_lpt %u\n", -++ !!(sup_flags & UBIFS_FLG_BIGLPT)); -++ printk(KERN_DEBUG "\tmin_io_size %u\n", -++ le32_to_cpu(sup->min_io_size)); -++ printk(KERN_DEBUG "\tleb_size %u\n", -++ le32_to_cpu(sup->leb_size)); -++ printk(KERN_DEBUG "\tleb_cnt %u\n", -++ le32_to_cpu(sup->leb_cnt)); -++ printk(KERN_DEBUG "\tmax_leb_cnt %u\n", -++ le32_to_cpu(sup->max_leb_cnt)); -++ printk(KERN_DEBUG "\tmax_bud_bytes %llu\n", -++ (unsigned long long)le64_to_cpu(sup->max_bud_bytes)); -++ printk(KERN_DEBUG "\tlog_lebs %u\n", -++ le32_to_cpu(sup->log_lebs)); -++ printk(KERN_DEBUG "\tlpt_lebs %u\n", -++ le32_to_cpu(sup->lpt_lebs)); -++ printk(KERN_DEBUG "\torph_lebs %u\n", -++ le32_to_cpu(sup->orph_lebs)); -++ printk(KERN_DEBUG "\tjhead_cnt %u\n", -++ le32_to_cpu(sup->jhead_cnt)); -++ printk(KERN_DEBUG "\tfanout %u\n", -++ le32_to_cpu(sup->fanout)); -++ printk(KERN_DEBUG "\tlsave_cnt %u\n", -++ le32_to_cpu(sup->lsave_cnt)); -++ printk(KERN_DEBUG "\tdefault_compr %u\n", -++ (int)le16_to_cpu(sup->default_compr)); -++ printk(KERN_DEBUG "\trp_size %llu\n", -++ (unsigned long long)le64_to_cpu(sup->rp_size)); -++ printk(KERN_DEBUG "\trp_uid %u\n", -++ le32_to_cpu(sup->rp_uid)); -++ printk(KERN_DEBUG "\trp_gid %u\n", -++ le32_to_cpu(sup->rp_gid)); -++ printk(KERN_DEBUG "\tfmt_version %u\n", -++ le32_to_cpu(sup->fmt_version)); -++ printk(KERN_DEBUG "\ttime_gran %u\n", -++ le32_to_cpu(sup->time_gran)); -++ break; -++ } -++ case UBIFS_MST_NODE: -++ { -++ const struct ubifs_mst_node *mst = node; -++ -++ printk(KERN_DEBUG "\thighest_inum %llu\n", -++ (unsigned long long)le64_to_cpu(mst->highest_inum)); -++ printk(KERN_DEBUG "\tcommit number %llu\n", -++ (unsigned long long)le64_to_cpu(mst->cmt_no)); -++ printk(KERN_DEBUG "\tflags %#x\n", -++ le32_to_cpu(mst->flags)); -++ printk(KERN_DEBUG "\tlog_lnum %u\n", -++ le32_to_cpu(mst->log_lnum)); -++ printk(KERN_DEBUG "\troot_lnum %u\n", -++ le32_to_cpu(mst->root_lnum)); -++ printk(KERN_DEBUG "\troot_offs %u\n", -++ le32_to_cpu(mst->root_offs)); -++ printk(KERN_DEBUG "\troot_len %u\n", -++ le32_to_cpu(mst->root_len)); -++ printk(KERN_DEBUG "\tgc_lnum %u\n", -++ le32_to_cpu(mst->gc_lnum)); -++ printk(KERN_DEBUG "\tihead_lnum %u\n", -++ le32_to_cpu(mst->ihead_lnum)); -++ printk(KERN_DEBUG "\tihead_offs %u\n", -++ le32_to_cpu(mst->ihead_offs)); -++ printk(KERN_DEBUG "\tindex_size %u\n", -++ le32_to_cpu(mst->index_size)); -++ printk(KERN_DEBUG "\tlpt_lnum %u\n", -++ le32_to_cpu(mst->lpt_lnum)); -++ printk(KERN_DEBUG "\tlpt_offs %u\n", -++ le32_to_cpu(mst->lpt_offs)); -++ printk(KERN_DEBUG "\tnhead_lnum %u\n", -++ le32_to_cpu(mst->nhead_lnum)); -++ printk(KERN_DEBUG "\tnhead_offs %u\n", -++ le32_to_cpu(mst->nhead_offs)); -++ printk(KERN_DEBUG "\tltab_lnum %u\n", -++ le32_to_cpu(mst->ltab_lnum)); -++ printk(KERN_DEBUG "\tltab_offs %u\n", -++ le32_to_cpu(mst->ltab_offs)); -++ printk(KERN_DEBUG "\tlsave_lnum %u\n", -++ le32_to_cpu(mst->lsave_lnum)); -++ printk(KERN_DEBUG "\tlsave_offs %u\n", -++ le32_to_cpu(mst->lsave_offs)); -++ printk(KERN_DEBUG "\tlscan_lnum %u\n", -++ le32_to_cpu(mst->lscan_lnum)); -++ printk(KERN_DEBUG "\tleb_cnt %u\n", -++ le32_to_cpu(mst->leb_cnt)); -++ printk(KERN_DEBUG "\tempty_lebs %u\n", -++ le32_to_cpu(mst->empty_lebs)); -++ printk(KERN_DEBUG "\tidx_lebs %u\n", -++ le32_to_cpu(mst->idx_lebs)); -++ printk(KERN_DEBUG "\ttotal_free %llu\n", -++ (unsigned long long)le64_to_cpu(mst->total_free)); -++ printk(KERN_DEBUG "\ttotal_dirty %llu\n", -++ (unsigned long long)le64_to_cpu(mst->total_dirty)); -++ printk(KERN_DEBUG "\ttotal_used %llu\n", -++ (unsigned long long)le64_to_cpu(mst->total_used)); -++ printk(KERN_DEBUG "\ttotal_dead %llu\n", -++ (unsigned long long)le64_to_cpu(mst->total_dead)); -++ printk(KERN_DEBUG "\ttotal_dark %llu\n", -++ (unsigned long long)le64_to_cpu(mst->total_dark)); -++ break; -++ } -++ case UBIFS_REF_NODE: -++ { -++ const struct ubifs_ref_node *ref = node; -++ -++ printk(KERN_DEBUG "\tlnum %u\n", -++ le32_to_cpu(ref->lnum)); -++ printk(KERN_DEBUG "\toffs %u\n", -++ le32_to_cpu(ref->offs)); -++ printk(KERN_DEBUG "\tjhead %u\n", -++ le32_to_cpu(ref->jhead)); -++ break; -++ } -++ case UBIFS_INO_NODE: -++ { -++ const struct ubifs_ino_node *ino = node; -++ -++ key_read(c, &ino->key, &key); -++ printk(KERN_DEBUG "\tkey %s\n", DBGKEY(&key)); -++ printk(KERN_DEBUG "\tsize %llu\n", -++ (unsigned long long)le64_to_cpu(ino->size)); -++ printk(KERN_DEBUG "\tnlink %u\n", -++ le32_to_cpu(ino->nlink)); -++ printk(KERN_DEBUG "\tatime %lld.%u\n", -++ (long long)le64_to_cpu(ino->atime_sec), -++ le32_to_cpu(ino->atime_nsec)); -++ printk(KERN_DEBUG "\tmtime %lld.%u\n", -++ (long long)le64_to_cpu(ino->mtime_sec), -++ le32_to_cpu(ino->mtime_nsec)); -++ printk(KERN_DEBUG "\tctime %lld.%u\n", -++ (long long)le64_to_cpu(ino->ctime_sec), -++ le32_to_cpu(ino->ctime_nsec)); -++ printk(KERN_DEBUG "\tuid %u\n", -++ le32_to_cpu(ino->uid)); -++ printk(KERN_DEBUG "\tgid %u\n", -++ le32_to_cpu(ino->gid)); -++ printk(KERN_DEBUG "\tmode %u\n", -++ le32_to_cpu(ino->mode)); -++ printk(KERN_DEBUG "\tflags %#x\n", -++ le32_to_cpu(ino->flags)); -++ printk(KERN_DEBUG "\txattr_cnt %u\n", -++ le32_to_cpu(ino->xattr_cnt)); -++ printk(KERN_DEBUG "\txattr_size %llu\n", -++ (unsigned long long)le64_to_cpu(ino->xattr_size)); -++ printk(KERN_DEBUG "\txattr_names %u\n", -++ le32_to_cpu(ino->xattr_names)); -++ printk(KERN_DEBUG "\tcompr_type %#x\n", -++ (int)le16_to_cpu(ino->compr_type)); -++ printk(KERN_DEBUG "\tdata len %u\n", -++ le32_to_cpu(ino->data_len)); -++ break; -++ } -++ case UBIFS_DENT_NODE: -++ case UBIFS_XENT_NODE: -++ { -++ const struct ubifs_dent_node *dent = node; -++ int nlen = le16_to_cpu(dent->nlen); -++ -++ key_read(c, &dent->key, &key); -++ printk(KERN_DEBUG "\tkey %s\n", DBGKEY(&key)); -++ printk(KERN_DEBUG "\tinum %llu\n", -++ (unsigned long long)le64_to_cpu(dent->inum)); -++ printk(KERN_DEBUG "\ttype %d\n", (int)dent->type); -++ printk(KERN_DEBUG "\tnlen %d\n", nlen); -++ printk(KERN_DEBUG "\tname "); -++ -++ if (nlen > UBIFS_MAX_NLEN) { -++ nlen = UBIFS_MAX_NLEN; -++ printk(KERN_DEBUG "\tWarning! Node is corrupted\n"); -++ } -++ -++ for (i = 0; i < nlen && dent->name[i]; i++) -++ printk("%c", dent->name[i]); -++ printk("\n"); -++ -++ break; -++ } -++ case UBIFS_DATA_NODE: -++ { -++ const struct ubifs_data_node *dn = node; -++ int dlen = le32_to_cpu(ch->len) - UBIFS_DATA_NODE_SZ; -++ -++ key_read(c, &dn->key, &key); -++ printk(KERN_DEBUG "\tkey %s\n", DBGKEY(&key)); -++ printk(KERN_DEBUG "\tsize %u\n", -++ le32_to_cpu(dn->size)); -++ printk(KERN_DEBUG "\tcompr_typ %d\n", -++ (int)le16_to_cpu(dn->compr_type)); -++ printk(KERN_DEBUG "\tdata size %d\n", -++ dlen); -++ printk(KERN_DEBUG "\tdata:\n"); -++ print_hex_dump(KERN_DEBUG, "\t", DUMP_PREFIX_OFFSET, 32, 1, -++ (void *)&dn->data, dlen, 0); -++ break; -++ } -++ case UBIFS_TRUN_NODE: -++ { -++ const struct ubifs_trun_node *trun = node; -++ -++ key_read(c, &trun->key, &key); -++ printk(KERN_DEBUG "\tkey %s\n", DBGKEY(&key)); -++ printk(KERN_DEBUG "\told_size %llu\n", -++ (unsigned long long)le64_to_cpu(trun->old_size)); -++ printk(KERN_DEBUG "\tnew_size %llu\n", -++ (unsigned long long)le64_to_cpu(trun->new_size)); -++ break; -++ } -++ case UBIFS_IDX_NODE: -++ { -++ const struct ubifs_idx_node *idx = node; -++ -++ n = le16_to_cpu(idx->child_cnt); -++ printk(KERN_DEBUG "\tchild_cnt %d\n", n); -++ printk(KERN_DEBUG "\tlevel %d\n", -++ (int)le16_to_cpu(idx->level)); -++ printk(KERN_DEBUG "\tBranches:\n"); -++ -++ for (i = 0; i < n && i < c->fanout - 1; i++) { -++ const struct ubifs_branch *br; -++ -++ br = ubifs_idx_branch(c, idx, i); -++ key_read(c, &br->key, &key); -++ printk(KERN_DEBUG "\t%d: LEB %d:%d len %d key %s\n", -++ i, le32_to_cpu(br->lnum), le32_to_cpu(br->offs), -++ le32_to_cpu(br->len), DBGKEY(&key)); -++ } -++ break; -++ } -++ case UBIFS_CS_NODE: -++ break; -++ case UBIFS_ORPH_NODE: -++ { -++ const struct ubifs_orph_node *orph = node; -++ -++ printk(KERN_DEBUG "\tcommit number %llu\n", -++ (unsigned long long) -++ le64_to_cpu(orph->cmt_no) & LLONG_MAX); -++ printk(KERN_DEBUG "\tlast node flag %llu\n", -++ (unsigned long long)(le64_to_cpu(orph->cmt_no)) >> 63); -++ n = (le32_to_cpu(ch->len) - UBIFS_ORPH_NODE_SZ) >> 3; -++ printk(KERN_DEBUG "\t%d orphan inode numbers:\n", n); -++ for (i = 0; i < n; i++) -++ printk(KERN_DEBUG "\t ino %llu\n", -++ le64_to_cpu(orph->inos[i])); -++ break; -++ } -++ default: -++ printk(KERN_DEBUG "node type %d was not recognized\n", -++ (int)ch->node_type); -++ } -++ spin_unlock(&dbg_lock); -++} -++ -++void dbg_dump_budget_req(const struct ubifs_budget_req *req) -++{ -++ spin_lock(&dbg_lock); -++ printk(KERN_DEBUG "Budgeting request: new_ino %d, dirtied_ino %d\n", -++ req->new_ino, req->dirtied_ino); -++ printk(KERN_DEBUG "\tnew_ino_d %d, dirtied_ino_d %d\n", -++ req->new_ino_d, req->dirtied_ino_d); -++ printk(KERN_DEBUG "\tnew_page %d, dirtied_page %d\n", -++ req->new_page, req->dirtied_page); -++ printk(KERN_DEBUG "\tnew_dent %d, mod_dent %d\n", -++ req->new_dent, req->mod_dent); -++/* TODO: remove compatibility stuff as late as possible */ -++#ifdef UBIFS_COMPAT_USE_OLD_PREPARE_WRITE -++ printk(KERN_DEBUG "\tlocked_pg %d idx_growth %d\n", -++ req->locked_pg, req->idx_growth); -++#else -++ printk(KERN_DEBUG "\tidx_growth %d\n", req->idx_growth); -++#endif -++ printk(KERN_DEBUG "\tdata_growth %d dd_growth %d\n", -++ req->data_growth, req->dd_growth); -++ spin_unlock(&dbg_lock); -++} -++ -++void dbg_dump_lstats(const struct ubifs_lp_stats *lst) -++{ -++ spin_lock(&dbg_lock); -++ printk(KERN_DEBUG "Lprops statistics: empty_lebs %d, idx_lebs %d\n", -++ lst->empty_lebs, lst->idx_lebs); -++ printk(KERN_DEBUG "\ttaken_empty_lebs %d, total_free %lld, " -++ "total_dirty %lld\n", lst->taken_empty_lebs, lst->total_free, -++ lst->total_dirty); -++ printk(KERN_DEBUG "\ttotal_used %lld, total_dark %lld, " -++ "total_dead %lld\n", lst->total_used, lst->total_dark, -++ lst->total_dead); -++ spin_unlock(&dbg_lock); -++} -++ -++void dbg_dump_budg(struct ubifs_info *c) -++{ -++ int i; -++ struct rb_node *rb; -++ struct ubifs_bud *bud; -++ struct ubifs_gced_idx_leb *idx_gc; -++ -++ spin_lock(&dbg_lock); -++ printk(KERN_DEBUG "Budgeting info: budg_data_growth %lld, " -++ "budg_dd_growth %lld, budg_idx_growth %lld\n", -++ c->budg_data_growth, c->budg_dd_growth, c->budg_idx_growth); -++ printk(KERN_DEBUG "\tdata budget sum %lld, total budget sum %lld, " -++ "freeable_cnt %d\n", c->budg_data_growth + c->budg_dd_growth, -++ c->budg_data_growth + c->budg_dd_growth + c->budg_idx_growth, -++ c->freeable_cnt); -++ printk(KERN_DEBUG "\tmin_idx_lebs %d, old_idx_sz %lld, " -++ "calc_idx_sz %lld, idx_gc_cnt %d\n", c->min_idx_lebs, -++ c->old_idx_sz, c->calc_idx_sz, c->idx_gc_cnt); -++ printk(KERN_DEBUG "\tdirty_pg_cnt %ld, dirty_ino_cnt %ld, " -++ "dirty_zn_cnt %ld, clean_zn_cnt %ld\n", -++ atomic_long_read(&c->dirty_pg_cnt), -++ atomic_long_read(&c->dirty_ino_cnt), -++ atomic_long_read(&c->dirty_zn_cnt), -++ atomic_long_read(&c->clean_zn_cnt)); -++ printk(KERN_DEBUG "\tdark_wm %d, dead_wm %d, max_idx_node_sz %d\n", -++ c->dark_wm, c->dead_wm, c->max_idx_node_sz); -++ printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n", -++ c->gc_lnum, c->ihead_lnum); -++ for (i = 0; i < c->jhead_cnt; i++) -++ printk(KERN_DEBUG "\tjhead %d\t LEB %d\n", -++ c->jheads[i].wbuf.jhead, c->jheads[i].wbuf.lnum); -++ for (rb = rb_first(&c->buds); rb; rb = rb_next(rb)) { -++ bud = rb_entry(rb, struct ubifs_bud, rb); -++ printk(KERN_DEBUG "\tbud LEB %d\n", bud->lnum); -++ } -++ list_for_each_entry(bud, &c->old_buds, list) -++ printk(KERN_DEBUG "\told bud LEB %d\n", bud->lnum); -++ list_for_each_entry(idx_gc, &c->idx_gc, list) -++ printk(KERN_DEBUG "\tGC'ed idx LEB %d unmap %d\n", -++ idx_gc->lnum, idx_gc->unmap); -++ printk(KERN_DEBUG "\tcommit state %d\n", c->cmt_state); -++ spin_unlock(&dbg_lock); -++} -++ -++void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp) -++{ -++ printk(KERN_DEBUG "LEB %d lprops: free %d, dirty %d (used %d), " -++ "flags %#x\n", lp->lnum, lp->free, lp->dirty, -++ c->leb_size - lp->free - lp->dirty, lp->flags); -++} -++ -++void dbg_dump_lprops(struct ubifs_info *c) -++{ -++ int lnum, err; -++ struct ubifs_lprops lp; -++ struct ubifs_lp_stats lst; -++ -++ printk(KERN_DEBUG "Dumping LEB properties\n"); -++ ubifs_get_lp_stats(c, &lst); -++ dbg_dump_lstats(&lst); -++ -++ for (lnum = c->main_first; lnum < c->leb_cnt; lnum++) { -++ err = ubifs_read_one_lp(c, lnum, &lp); -++ if (err) -++ ubifs_err("cannot read lprops for LEB %d", lnum); -++ -++ dbg_dump_lprop(c, &lp); -++ } -++} -++ -++void dbg_dump_leb(const struct ubifs_info *c, int lnum) -++{ -++ struct ubifs_scan_leb *sleb; -++ struct ubifs_scan_node *snod; -++ -++ if (dbg_failure_mode) -++ return; -++ -++ printk(KERN_DEBUG "Dumping LEB %d\n", lnum); -++ -++ sleb = ubifs_scan(c, lnum, 0, c->dbg_buf); -++ if (IS_ERR(sleb)) { -++ ubifs_err("scan error %d", (int)PTR_ERR(sleb)); -++ return; -++ } -++ -++ printk(KERN_DEBUG "LEB %d has %d nodes ending at %d\n", lnum, -++ sleb->nodes_cnt, sleb->endpt); -++ -++ list_for_each_entry(snod, &sleb->nodes, list) { -++ cond_resched(); -++ printk(KERN_DEBUG "Dumping node at LEB %d:%d len %d\n", lnum, -++ snod->offs, snod->len); -++ dbg_dump_node(c, snod->node); -++ } -++ -++ ubifs_scan_destroy(sleb); -++ return; -++} -++ -++void dbg_dump_znode(const struct ubifs_info *c, -++ const struct ubifs_znode *znode) -++{ -++ int n; -++ const struct ubifs_zbranch *zbr; -++ -++ spin_lock(&dbg_lock); -++ if (znode->parent) -++ zbr = &znode->parent->zbranch[znode->iip]; -++ else -++ zbr = &c->zroot; -++ -++ printk(KERN_DEBUG "znode %p, LEB %d:%d len %d parent %p iip %d level %d" -++ " child_cnt %d flags %lx\n", znode, zbr->lnum, zbr->offs, -++ zbr->len, znode->parent, znode->iip, znode->level, -++ znode->child_cnt, znode->flags); -++ -++ if (znode->child_cnt <= 0 || znode->child_cnt > c->fanout) { -++ spin_unlock(&dbg_lock); -++ return; -++ } -++ -++ printk(KERN_DEBUG "zbranches:\n"); -++ for (n = 0; n < znode->child_cnt; n++) { -++ cond_resched(); -++ -++ zbr = &znode->zbranch[n]; -++ if (znode->level > 0) -++ printk(KERN_DEBUG "\t%d: znode %p LEB %d:%d len %d key " -++ "%s\n", n, zbr->znode, zbr->lnum, -++ zbr->offs, zbr->len, -++ DBGKEY(&zbr->key)); -++ else -++ printk(KERN_DEBUG "\t%d: LNC %p LEB %d:%d len %d key " -++ "%s\n", n, zbr->znode, zbr->lnum, -++ zbr->offs, zbr->len, -++ DBGKEY(&zbr->key)); -++ } -++ spin_unlock(&dbg_lock); -++} -++ -++void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat) -++{ -++ int i; -++ -++ printk(KERN_DEBUG "Dumping heap cat %d (%d elements)\n", -++ cat, heap->cnt); -++ for (i = 0; i < heap->cnt; i++) { -++ struct ubifs_lprops *lprops = heap->arr[i]; -++ -++ printk(KERN_DEBUG "\t%d. LEB %d hpos %d free %d dirty %d " -++ "flags %d\n", i, lprops->lnum, lprops->hpos, -++ lprops->free, lprops->dirty, lprops->flags); -++ } -++} -++ -++void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, -++ struct ubifs_nnode *parent, int iip) -++{ -++ int i; -++ -++ printk(KERN_DEBUG "Dumping pnode:\n"); -++ printk(KERN_DEBUG "\taddress %zx parent %zx cnext %zx\n", -++ (size_t)pnode, (size_t)parent, (size_t)pnode->cnext); -++ printk(KERN_DEBUG "\tflags %lu iip %d level %d num %d\n", -++ pnode->flags, iip, pnode->level, pnode->num); -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ struct ubifs_lprops *lp = &pnode->lprops[i]; -++ -++ printk(KERN_DEBUG "\t%d: free %d dirty %d flags %d lnum %d\n", -++ i, lp->free, lp->dirty, lp->flags, lp->lnum); -++ } -++} -++ -++void dbg_dump_tnc(struct ubifs_info *c) -++{ -++ struct ubifs_znode *znode; -++ int level; -++ -++ printk(KERN_DEBUG "\n"); -++ printk(KERN_DEBUG "Dumping the TNC tree\n"); -++ znode = ubifs_tnc_levelorder_next(c->zroot.znode, NULL); -++ level = znode->level; -++ printk(KERN_DEBUG "== Level %d ==\n", level); -++ while (znode) { -++ if (level != znode->level) { -++ level = znode->level; -++ printk(KERN_DEBUG "== Level %d ==\n", level); -++ } -++ dbg_dump_znode(c, znode); -++ znode = ubifs_tnc_levelorder_next(c->zroot.znode, znode); -++ } -++ -++ printk(KERN_DEBUG "\n"); -++} -++ -++/* -++ * dbg_check_dir - check directory inode size. -++ * @c: UBIFS file-system description object -++ * @dir: the directory to calculate size for -++ * @size: the result is returned here -++ * -++ * This function makes sure that directory size is correct. Returns zero -++ * in case of success and a negative error code in case of failure. -++ * -++ * Note, it is good idea to make sure the @dir->i_mutex is locked before -++ * calling this function. -++ */ -++int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir) -++{ -++ union ubifs_key key; -++ struct ubifs_dent_node *dent, *pdent = NULL; -++ struct qstr nm = { .name = NULL }; -++ loff_t size = UBIFS_INO_NODE_SZ; -++ -++ if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) -++ return 0; -++ -++ if (!S_ISDIR(dir->i_mode)) -++ return 0; -++ -++ lowest_dent_key(c, &key, dir->i_ino); -++ while (1) { -++ int err; -++ -++ dent = ubifs_tnc_next_ent(c, &key, &nm); -++ if (IS_ERR(dent)) { -++ err = PTR_ERR(dent); -++ if (err == -ENOENT) -++ break; -++ return err; -++ } -++ -++ nm.name = dent->name; -++ nm.len = le16_to_cpu(dent->nlen); -++ size += CALC_DENT_SIZE(nm.len); -++ kfree(pdent); -++ pdent = dent; -++ key_read(c, &dent->key, &key); -++ } -++ -++ kfree(pdent); -++ -++ if (i_size_read(dir) != size) { -++ ubifs_err("bad directory dir %lu size %llu, " -++ "calculated %llu", dir->i_ino, -++ (unsigned long long)i_size_read(dir), -++ (unsigned long long)size); -++ dump_stack(); -++ return -EINVAL; -++ } -++ -++ return 0; -++} -++ -++/** -++ * dbg_check_key_order - make sure that colliding keys are properly ordered. -++ * @c: UBIFS file-system description object -++ * @zbr1: first zbranch -++ * @zbr1: following zbranch -++ * -++ * In UBIFS indexing B-tree colliding keys has to be sorted in binary order of -++ * names of the direntries/xentries which are referred by the keys. This -++ * function reads direntries/xentries referred by @zbr1 and @zbr2 and makes -++ * sure the name of direntry/xentry referred by @zbr1 is less than -++ * direntry/xentry referred by @zbr2. Returns zero if this is true, %1 if not, -++ * and a negative error code in case of failure. -++ */ -++static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1, -++ struct ubifs_zbranch *zbr2) -++{ -++ int err, nlen1, nlen2, cmp; -++ struct ubifs_dent_node *dent1, *dent2; -++ union ubifs_key key; -++ -++ ubifs_assert(!keys_cmp(c, &zbr1->key, &zbr2->key)); -++ dent1 = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS); -++ if (!dent1) -++ return -ENOMEM; -++ dent2 = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS); -++ if (!dent2) { -++ err = -ENOMEM; -++ goto out_free; -++ } -++ -++ err = dbg_read_leaf_nolock(c, zbr1, dent1); -++ if (err) -++ goto out_free; -++ err = ubifs_validate_entry(c, dent1); -++ if (err) -++ goto out_free; -++ -++ err = dbg_read_leaf_nolock(c, zbr2, dent2); -++ if (err) -++ goto out_free; -++ err = ubifs_validate_entry(c, dent2); -++ if (err) -++ goto out_free; -++ -++ /* Make sure node keys are the same as in zbranch */ -++ err = 1; -++ key_read(c, &dent1->key, &key); -++ if (keys_cmp(c, &zbr1->key, &key)) { -++ dbg_err("1st entry at %d:%d has key %s", zbr1->lnum, -++ zbr1->offs, DBGKEY(&key)); -++ dbg_err("but it should have key %s according to tnc", -++ DBGKEY(&zbr1->key)); -++ dbg_dump_node(c, dent1); -++ goto out_free; -++ } -++ -++ key_read(c, &dent2->key, &key); -++ if (keys_cmp(c, &zbr2->key, &key)) { -++ dbg_err("2nd entry at %d:%d has key %s", zbr1->lnum, -++ zbr1->offs, DBGKEY(&key)); -++ dbg_err("but it should have key %s according to tnc", -++ DBGKEY(&zbr2->key)); -++ dbg_dump_node(c, dent2); -++ goto out_free; -++ } -++ -++ nlen1 = le16_to_cpu(dent1->nlen); -++ nlen2 = le16_to_cpu(dent2->nlen); -++ -++ cmp = memcmp(dent1->name, dent2->name, min_t(int, nlen1, nlen2)); -++ if (cmp < 0 || (cmp == 0 && nlen1 < nlen2)) { -++ err = 0; -++ goto out_free; -++ } -++ if (cmp == 0 && nlen1 == nlen2) -++ dbg_err("2 xent/dent nodes with the same name"); -++ else -++ dbg_err("bad order of colliding key %s", -++ DBGKEY(&key)); -++ -++ dbg_msg("first node at %d:%d\n", zbr1->lnum, zbr1->offs); -++ dbg_dump_node(c, dent1); -++ dbg_msg("second node at %d:%d\n", zbr2->lnum, zbr2->offs); -++ dbg_dump_node(c, dent2); -++ -++out_free: -++ kfree(dent2); -++ kfree(dent1); -++ return err; -++} -++ -++/** -++ * dbg_check_znode - check if znode is all right. -++ * @c: UBIFS file-system description object -++ * @zbr: zbranch which points to this znode -++ * -++ * This function makes sure that znode referred to by @zbr is all right. -++ * Returns zero if it is, and %-EINVAL if it is not. -++ */ -++static int dbg_check_znode(struct ubifs_info *c, struct ubifs_zbranch *zbr) -++{ -++ struct ubifs_znode *znode = zbr->znode; -++ struct ubifs_znode *zp = znode->parent; -++ int n, err, cmp; -++ -++ if (znode->child_cnt <= 0 || znode->child_cnt > c->fanout) { -++ err = 1; -++ goto out; -++ } -++ if (znode->level < 0) { -++ err = 2; -++ goto out; -++ } -++ if (znode->iip < 0 || znode->iip >= c->fanout) { -++ err = 3; -++ goto out; -++ } -++ -++ if (zbr->len == 0) -++ /* Only dirty zbranch may have no on-flash nodes */ -++ if (!ubifs_zn_dirty(znode)) { -++ err = 4; -++ goto out; -++ } -++ -++ if (ubifs_zn_dirty(znode)) { -++ /* -++ * If znode is dirty, its parent has to be dirty as well. The -++ * order of the operation is important, so we have to have -++ * memory barriers. -++ */ -++ smp_mb(); -++ if (zp && !ubifs_zn_dirty(zp)) { -++ /* -++ * The dirty flag is atomic and is cleared outside the -++ * TNC mutex, so znode's dirty flag may now have -++ * been cleared. The child is always cleared before the -++ * parent, so we just need to check again. -++ */ -++ smp_mb(); -++ if (ubifs_zn_dirty(znode)) { -++ err = 5; -++ goto out; -++ } -++ } -++ } -++ -++ if (zp) { -++ const union ubifs_key *min, *max; -++ -++ if (znode->level != zp->level - 1) { -++ err = 6; -++ goto out; -++ } -++ -++ /* Make sure the 'parent' pointer in our znode is correct */ -++ err = ubifs_search_zbranch(c, zp, &zbr->key, &n); -++ if (!err) { -++ /* This zbranch does not exist in the parent */ -++ err = 7; -++ goto out; -++ } -++ -++ if (znode->iip >= zp->child_cnt) { -++ err = 8; -++ goto out; -++ } -++ -++ if (znode->iip != n) { -++ /* This may happen only in case of collisions */ -++ if (keys_cmp(c, &zp->zbranch[n].key, -++ &zp->zbranch[znode->iip].key)) { -++ err = 9; -++ goto out; -++ } -++ n = znode->iip; -++ } -++ -++ /* -++ * Make sure that the first key in our znode is greater than or -++ * equal to the key in the pointing zbranch. -++ */ -++ min = &zbr->key; -++ cmp = keys_cmp(c, min, &znode->zbranch[0].key); -++ if (cmp == 1) { -++ err = 10; -++ goto out; -++ } -++ -++ if (n + 1 < zp->child_cnt) { -++ max = &zp->zbranch[n + 1].key; -++ -++ /* -++ * Make sure the last key in our znode is less or -++ * equivalent than the the key in zbranch which goes -++ * after our pointing zbranch. -++ */ -++ cmp = keys_cmp(c, max, -++ &znode->zbranch[znode->child_cnt - 1].key); -++ if (cmp == -1) { -++ err = 11; -++ goto out; -++ } -++ } -++ } else { -++ /* This may only be root znode */ -++ if (zbr != &c->zroot) { -++ err = 12; -++ goto out; -++ } -++ } -++ -++ /* -++ * Make sure that next key is greater or equivalent then the previous -++ * one. -++ */ -++ for (n = 1; n < znode->child_cnt; n++) { -++ cmp = keys_cmp(c, &znode->zbranch[n - 1].key, -++ &znode->zbranch[n].key); -++ if (cmp > 0) { -++ err = 13; -++ goto out; -++ } -++ if (cmp == 0) { -++ /* This can only be keys with colliding hash */ -++ if (!is_hash_key(c, &znode->zbranch[n].key)) { -++ err = 14; -++ goto out; -++ } -++ -++ if (znode->level != 0 || c->replaying) -++ continue; -++ -++ /* -++ * Colliding keys should follow binary order of -++ * corresponding xentry/dentry names. -++ */ -++ err = dbg_check_key_order(c, &znode->zbranch[n - 1], -++ &znode->zbranch[n]); -++ if (err < 0) -++ return err; -++ if (err) { -++ err = 15; -++ goto out; -++ } -++ } -++ } -++ -++ for (n = 0; n < znode->child_cnt; n++) { -++ if (!znode->zbranch[n].znode && -++ (znode->zbranch[n].lnum == 0 || -++ znode->zbranch[n].len == 0)) { -++ err = 16; -++ goto out; -++ } -++ -++ if (znode->zbranch[n].lnum != 0 && -++ znode->zbranch[n].len == 0) { -++ err = 17; -++ goto out; -++ } -++ -++ if (znode->zbranch[n].lnum == 0 && -++ znode->zbranch[n].len != 0) { -++ err = 18; -++ goto out; -++ } -++ -++ if (znode->zbranch[n].lnum == 0 && -++ znode->zbranch[n].offs != 0) { -++ err = 19; -++ goto out; -++ } -++ -++ if (znode->level != 0 && znode->zbranch[n].znode) -++ if (znode->zbranch[n].znode->parent != znode) { -++ err = 20; -++ goto out; -++ } -++ } -++ -++ return 0; -++ -++out: -++ ubifs_err("failed, error %d", err); -++ ubifs_msg("dump of the znode"); -++ dbg_dump_znode(c, znode); -++ if (zp) { -++ ubifs_msg("dump of the parent znode"); -++ dbg_dump_znode(c, zp); -++ } -++ dump_stack(); -++ return -EINVAL; -++} -++ -++/** -++ * dbg_check_tnc - check TNC tree. -++ * @c: UBIFS file-system description object -++ * @extra: do extra checks that are possible at start commit -++ * -++ * This function traverses whole TNC tree and checks every znode. Returns zero -++ * if everything is all right and %-EINVAL if something is wrong with TNC. -++ */ -++int dbg_check_tnc(struct ubifs_info *c, int extra) -++{ -++ struct ubifs_znode *znode; -++ long clean_cnt = 0, dirty_cnt = 0; -++ int err, last; -++ -++ if (!(ubifs_chk_flags & UBIFS_CHK_TNC)) -++ return 0; -++ -++ ubifs_assert(mutex_is_locked(&c->tnc_mutex)); -++ if (!c->zroot.znode) -++ return 0; -++ -++ znode = ubifs_tnc_postorder_first(c->zroot.znode); -++ while (1) { -++ struct ubifs_znode *prev; -++ struct ubifs_zbranch *zbr; -++ -++ if (!znode->parent) -++ zbr = &c->zroot; -++ else -++ zbr = &znode->parent->zbranch[znode->iip]; -++ -++ err = dbg_check_znode(c, zbr); -++ if (err) -++ return err; -++ -++ if (extra) { -++ if (ubifs_zn_dirty(znode)) -++ dirty_cnt += 1; -++ else -++ clean_cnt += 1; -++ } -++ -++ prev = znode; -++ znode = ubifs_tnc_postorder_next(znode); -++ if (!znode) -++ break; -++ -++ /* -++ * If the last key of this znode is equivalent to the first key -++ * of the next znode (collision), then check order of the keys. -++ */ -++ last = prev->child_cnt - 1; -++ if (prev->level == 0 && znode->level == 0 && !c->replaying && -++ !keys_cmp(c, &prev->zbranch[last].key, -++ &znode->zbranch[0].key)) { -++ err = dbg_check_key_order(c, &prev->zbranch[last], -++ &znode->zbranch[0]); -++ if (err < 0) -++ return err; -++ if (err) { -++ ubifs_msg("first znode"); -++ dbg_dump_znode(c, prev); -++ ubifs_msg("second znode"); -++ dbg_dump_znode(c, znode); -++ return -EINVAL; -++ } -++ } -++ } -++ -++ if (extra) { -++ if (clean_cnt != atomic_long_read(&c->clean_zn_cnt)) { -++ ubifs_err("incorrect clean_zn_cnt %ld, calculated %ld", -++ atomic_long_read(&c->clean_zn_cnt), -++ clean_cnt); -++ return -EINVAL; -++ } -++ if (dirty_cnt != atomic_long_read(&c->dirty_zn_cnt)) { -++ ubifs_err("incorrect dirty_zn_cnt %ld, calculated %ld", -++ atomic_long_read(&c->dirty_zn_cnt), -++ dirty_cnt); -++ return -EINVAL; -++ } -++ } -++ -++ return 0; -++} -++ -++static int dbg_add_size(struct ubifs_info *c, struct ubifs_znode *znode, -++ void *priv) -++{ -++ long long *idx_size = priv; -++ int add; -++ -++ add = ubifs_idx_node_sz(c, znode->child_cnt); -++ add = ALIGN(add, 8); -++ *idx_size += add; -++ return 0; -++} -++ -++int dbg_check_idx_size(struct ubifs_info *c, long long idx_size) -++{ -++ int err; -++ long long calc = 0; -++ -++ if (!(ubifs_chk_flags & UBIFS_CHK_IDX_SZ)) -++ return 0; -++ -++ err = dbg_walk_index(c, NULL, dbg_add_size, &calc); -++ if (err) { -++ ubifs_err("error %d while walking the index", err); -++ return err; -++ } -++ -++ if (calc != idx_size) { -++ ubifs_err("index size check failed"); -++ ubifs_err("calculated size is %lld, should be %lld", -++ calc, idx_size); -++ dump_stack(); -++ return -EINVAL; -++ } -++ -++ return 0; -++} -++ -++static int invocation_cnt; -++ -++int dbg_force_in_the_gaps(void) -++{ -++ if (!dbg_force_in_the_gaps_enabled) -++ return 0; -++ /* Force in-the-gaps every 8th commit */ -++ return !((invocation_cnt++) & 0x7); -++} -++ -++#endif /* CONFIG_UBIFS_FS_DEBUG */ -++ -++/* Failure mode for recovery testing */ -++ -++#define chance(n, d) (simple_rand() <= (n) * 32768LL / (d)) -++ -++struct failure_mode_info { -++ struct list_head list; -++ struct ubifs_info *c; -++}; -++ -++static LIST_HEAD(fmi_list); -++static DEFINE_SPINLOCK(fmi_lock); -++ -++static unsigned int next; -++ -++static int simple_rand(void) -++{ -++ if (next == 0) -++ next = current->pid; -++ next = next * 1103515245 + 12345; -++ return (next >> 16) & 32767; -++} -++ -++void dbg_failure_mode_registration(struct ubifs_info *c) -++{ -++ struct failure_mode_info *fmi; -++ -++ fmi = kmalloc(sizeof(struct failure_mode_info), GFP_NOFS); -++ if (!fmi) { -++ dbg_err("Failed to register failure mode - no memory"); -++ return; -++ } -++ fmi->c = c; -++ spin_lock(&fmi_lock); -++ list_add_tail(&fmi->list, &fmi_list); -++ spin_unlock(&fmi_lock); -++} -++ -++void dbg_failure_mode_deregistration(struct ubifs_info *c) -++{ -++ struct failure_mode_info *fmi, *tmp; -++ -++ spin_lock(&fmi_lock); -++ list_for_each_entry_safe(fmi, tmp, &fmi_list, list) -++ if (fmi->c == c) { -++ list_del(&fmi->list); -++ kfree(fmi); -++ } -++ spin_unlock(&fmi_lock); -++} -++ -++static struct ubifs_info *dbg_find_info(struct ubi_volume_desc *desc) -++{ -++ struct failure_mode_info *fmi; -++ -++ spin_lock(&fmi_lock); -++ list_for_each_entry(fmi, &fmi_list, list) -++ if (fmi->c->ubi == desc) { -++ struct ubifs_info *c = fmi->c; -++ -++ spin_unlock(&fmi_lock); -++ return c; -++ } -++ spin_unlock(&fmi_lock); -++ return NULL; -++} -++ -++static int in_failure_mode(struct ubi_volume_desc *desc) -++{ -++ struct ubifs_info *c = dbg_find_info(desc); -++ -++ if (c) -++ return c->failure_mode; -++ return 0; -++} -++ -++static int do_fail(struct ubi_volume_desc *desc, int lnum, int write) -++{ -++ struct ubifs_info *c = dbg_find_info(desc); -++ -++ if (!c || !dbg_failure_mode) -++ return 0; -++ if (c->failure_mode) -++ return 1; -++ if (!c->fail_cnt) { -++ /* First call - decide delay to failure */ -++ if (chance(1, 2)) { -++ unsigned int delay = 1 << (simple_rand() >> 11); -++ -++ if (chance(1, 2)) { -++ c->fail_delay = 1; -++ c->fail_timeout = jiffies + -++ msecs_to_jiffies(delay); -++ dbg_rcvry("failing after %ums", delay); -++ } else { -++ c->fail_delay = 2; -++ c->fail_cnt_max = delay; -++ dbg_rcvry("failing after %u calls", delay); -++ } -++ } -++ c->fail_cnt += 1; -++ } -++ /* Determine if failure delay has expired */ -++ if (c->fail_delay == 1) { -++ if (time_before(jiffies, c->fail_timeout)) -++ return 0; -++ } else if (c->fail_delay == 2) -++ if (c->fail_cnt++ < c->fail_cnt_max) -++ return 0; -++ if (lnum == UBIFS_SB_LNUM) { -++ if (write) { -++ if (chance(1, 2)) -++ return 0; -++ } else if (chance(19, 20)) -++ return 0; -++ dbg_rcvry("failing in super block LEB %d", lnum); -++ } else if (lnum == UBIFS_MST_LNUM || lnum == UBIFS_MST_LNUM + 1) { -++ if (chance(19, 20)) -++ return 0; -++ dbg_rcvry("failing in master LEB %d", lnum); -++ } else if (lnum >= UBIFS_LOG_LNUM && lnum <= c->log_last) { -++ if (write) { -++ if (chance(99, 100)) -++ return 0; -++ } else if (chance(399, 400)) -++ return 0; -++ dbg_rcvry("failing in log LEB %d", lnum); -++ } else if (lnum >= c->lpt_first && lnum <= c->lpt_last) { -++ if (write) { -++ if (chance(7, 8)) -++ return 0; -++ } else if (chance(19, 20)) -++ return 0; -++ dbg_rcvry("failing in LPT LEB %d", lnum); -++ } else if (lnum >= c->orph_first && lnum <= c->orph_last) { -++ if (write) { -++ if (chance(1, 2)) -++ return 0; -++ } else if (chance(9, 10)) -++ return 0; -++ dbg_rcvry("failing in orphan LEB %d", lnum); -++ } else if (lnum == c->ihead_lnum) { -++ if (chance(99, 100)) -++ return 0; -++ dbg_rcvry("failing in index head LEB %d", lnum); -++ } else if (c->jheads && lnum == c->jheads[GCHD].wbuf.lnum) { -++ if (chance(9, 10)) -++ return 0; -++ dbg_rcvry("failing in GC head LEB %d", lnum); -++ } else if (write && !RB_EMPTY_ROOT(&c->buds) && -++ !ubifs_search_bud(c, lnum)) { -++ if (chance(19, 20)) -++ return 0; -++ dbg_rcvry("failing in non-bud LEB %d", lnum); -++ } else if (c->cmt_state == COMMIT_RUNNING_BACKGROUND || -++ c->cmt_state == COMMIT_RUNNING_REQUIRED) { -++ if (chance(999, 1000)) -++ return 0; -++ dbg_rcvry("failing in bud LEB %d commit running", lnum); -++ } else { -++ if (chance(9999, 10000)) -++ return 0; -++ dbg_rcvry("failing in bud LEB %d commit not running", lnum); -++ } -++ ubifs_err("*** SETTING FAILURE MODE ON (LEB %d) ***", lnum); -++ c->failure_mode = 1; -++ dump_stack(); -++ return 1; -++} -++ -++static void cut_data(const void *buf, int len) -++{ -++ int flen, i; -++ unsigned char *p = (void *)buf; -++ -++ flen = (len * (long long)simple_rand()) >> 15; -++ for (i = flen; i < len; i++) -++ p[i] = 0xff; -++} -++ -++int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, -++ int len, int check) -++{ -++ if (in_failure_mode(desc)) -++ return -EIO; -++ return ubi_leb_read(desc, lnum, buf, offset, len, check); -++} -++ -++int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, -++ int offset, int len, int dtype) -++{ -++ int err; -++ -++ if (in_failure_mode(desc)) -++ return -EIO; -++ if (do_fail(desc, lnum, 1)) -++ cut_data(buf, len); -++ err = ubi_leb_write(desc, lnum, buf, offset, len, dtype); -++ if (err) -++ return err; -++ if (in_failure_mode(desc)) -++ return -EIO; -++ return 0; -++} -++ -++int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, -++ int len, int dtype) -++{ -++ int err; -++ -++ if (do_fail(desc, lnum, 1)) -++ return -EIO; -++ err = ubi_leb_change(desc, lnum, buf, len, dtype); -++ if (err) -++ return err; -++ if (do_fail(desc, lnum, 1)) -++ return -EIO; -++ return 0; -++} -++ -++int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum) -++{ -++ int err; -++ -++ if (do_fail(desc, lnum, 0)) -++ return -EIO; -++ err = ubi_leb_erase(desc, lnum); -++ if (err) -++ return err; -++ if (do_fail(desc, lnum, 0)) -++ return -EIO; -++ return 0; -++} -++ -++int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum) -++{ -++ int err; -++ -++ if (do_fail(desc, lnum, 0)) -++ return -EIO; -++ err = ubi_leb_unmap(desc, lnum); -++ if (err) -++ return err; -++ if (do_fail(desc, lnum, 0)) -++ return -EIO; -++ return 0; -++} -++ -++int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum) -++{ -++ if (in_failure_mode(desc)) -++ return -EIO; -++ return ubi_is_mapped(desc, lnum); -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/debug.h linux-2.6.24.7/fs/ubifs/debug.h -+--- linux-2.6.24.7.old/fs/ubifs/debug.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/debug.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,392 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++#ifndef __UBIFS_DEBUG_H__ -++#define __UBIFS_DEBUG_H__ -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ -++#define UBIFS_DBG(op) op -++ -++#define ubifs_assert(expr) do { \ -++ if (unlikely(!(expr))) { \ -++ printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \ -++ __func__, __LINE__, current->pid); \ -++ dbg_dump_stack(); \ -++ } \ -++} while (0) -++ -++#define ubifs_assert_cmt_locked(c) do { \ -++ if (unlikely(down_write_trylock(&(c)->commit_sem))) { \ -++ up_write(&(c)->commit_sem); \ -++ printk(KERN_CRIT "commit lock is not locked!\n"); \ -++ ubifs_assert(0); \ -++ } \ -++} while (0) -++ -++#define dbg_dump_stack() do { \ -++ if (!dbg_failure_mode) \ -++ dump_stack(); \ -++} while (0) -++ -++/* Generic debugging messages */ -++#define dbg_msg(fmt, ...) do { \ -++ spin_lock(&dbg_lock); \ -++ printk(KERN_DEBUG "UBIFS DBG (pid %d): %s: " fmt "\n", current->pid, \ -++ __func__, ##__VA_ARGS__); \ -++ spin_unlock(&dbg_lock); \ -++} while (0) -++ -++#define dbg_do_msg(typ, fmt, ...) do { \ -++ if (ubifs_msg_flags & typ) \ -++ dbg_msg(fmt, ##__VA_ARGS__); \ -++} while (0) -++ -++#define dbg_err(fmt, ...) do { \ -++ spin_lock(&dbg_lock); \ -++ ubifs_err(fmt, ##__VA_ARGS__); \ -++ spin_unlock(&dbg_lock); \ -++} while (0) -++ -++const char *dbg_key_str0(const struct ubifs_info *c, -++ const union ubifs_key *key); -++const char *dbg_key_str1(const struct ubifs_info *c, -++ const union ubifs_key *key); -++ -++/* -++ * DBGKEY macros require dbg_lock to be held, which it is in the dbg message -++ * macros. -++ */ -++#define DBGKEY(key) dbg_key_str0(c, (key)) -++#define DBGKEY1(key) dbg_key_str1(c, (key)) -++ -++/* General messages */ -++#define dbg_gen(fmt, ...) dbg_do_msg(UBIFS_MSG_GEN, fmt, ##__VA_ARGS__) -++ -++/* Additional journal messages */ -++#define dbg_jnl(fmt, ...) dbg_do_msg(UBIFS_MSG_JNL, fmt, ##__VA_ARGS__) -++ -++/* Additional TNC messages */ -++#define dbg_tnc(fmt, ...) dbg_do_msg(UBIFS_MSG_TNC, fmt, ##__VA_ARGS__) -++ -++/* Additional lprops messages */ -++#define dbg_lp(fmt, ...) dbg_do_msg(UBIFS_MSG_LP, fmt, ##__VA_ARGS__) -++ -++/* Additional LEB find messages */ -++#define dbg_find(fmt, ...) dbg_do_msg(UBIFS_MSG_FIND, fmt, ##__VA_ARGS__) -++ -++/* Additional mount messages */ -++#define dbg_mnt(fmt, ...) dbg_do_msg(UBIFS_MSG_MNT, fmt, ##__VA_ARGS__) -++ -++/* Additional I/O messages */ -++#define dbg_io(fmt, ...) dbg_do_msg(UBIFS_MSG_IO, fmt, ##__VA_ARGS__) -++ -++/* Additional commit messages */ -++#define dbg_cmt(fmt, ...) dbg_do_msg(UBIFS_MSG_CMT, fmt, ##__VA_ARGS__) -++ -++/* Additional budgeting messages */ -++#define dbg_budg(fmt, ...) dbg_do_msg(UBIFS_MSG_BUDG, fmt, ##__VA_ARGS__) -++ -++/* Additional log messages */ -++#define dbg_log(fmt, ...) dbg_do_msg(UBIFS_MSG_LOG, fmt, ##__VA_ARGS__) -++ -++/* Additional gc messages */ -++#define dbg_gc(fmt, ...) dbg_do_msg(UBIFS_MSG_GC, fmt, ##__VA_ARGS__) -++ -++/* Additional scan messages */ -++#define dbg_scan(fmt, ...) dbg_do_msg(UBIFS_MSG_SCAN, fmt, ##__VA_ARGS__) -++ -++/* Additional recovery messages */ -++#define dbg_rcvry(fmt, ...) dbg_do_msg(UBIFS_MSG_RCVRY, fmt, ##__VA_ARGS__) -++ -++/* -++ * Debugging message type flags (must match msg_type_names in debug.c). -++ * -++ * UBIFS_MSG_GEN: general messages -++ * UBIFS_MSG_JNL: journal messages -++ * UBIFS_MSG_MNT: mount messages -++ * UBIFS_MSG_CMT: commit messages -++ * UBIFS_MSG_FIND: LEB find messages -++ * UBIFS_MSG_BUDG: budgeting messages -++ * UBIFS_MSG_GC: garbage collection messages -++ * UBIFS_MSG_TNC: TNC messages -++ * UBIFS_MSG_LP: lprops messages -++ * UBIFS_MSG_IO: I/O messages -++ * UBIFS_MSG_LOG: log messages -++ * UBIFS_MSG_SCAN: scan messages -++ * UBIFS_MSG_RCVRY: recovery messages -++ */ -++enum { -++ UBIFS_MSG_GEN = 0x1, -++ UBIFS_MSG_JNL = 0x2, -++ UBIFS_MSG_MNT = 0x4, -++ UBIFS_MSG_CMT = 0x8, -++ UBIFS_MSG_FIND = 0x10, -++ UBIFS_MSG_BUDG = 0x20, -++ UBIFS_MSG_GC = 0x40, -++ UBIFS_MSG_TNC = 0x80, -++ UBIFS_MSG_LP = 0x100, -++ UBIFS_MSG_IO = 0x200, -++ UBIFS_MSG_LOG = 0x400, -++ UBIFS_MSG_SCAN = 0x800, -++ UBIFS_MSG_RCVRY = 0x1000, -++}; -++ -++/* Debugging message type flags for each default debug message level */ -++#define UBIFS_MSG_LVL_0 0 -++#define UBIFS_MSG_LVL_1 0x1 -++#define UBIFS_MSG_LVL_2 0x7f -++#define UBIFS_MSG_LVL_3 0xffff -++ -++/* -++ * Debugging check flags (must match chk_names in debug.c). -++ * -++ * UBIFS_CHK_GEN: general checks -++ * UBIFS_CHK_TNC: check TNC -++ * UBIFS_CHK_IDX_SZ: check index size -++ * UBIFS_CHK_ORPH: check orphans -++ * UBIFS_CHK_OLD_IDX: check the old index -++ * UBIFS_CHK_LPROPS: check lprops -++ */ -++enum { -++ UBIFS_CHK_GEN = 0x1, -++ UBIFS_CHK_TNC = 0x2, -++ UBIFS_CHK_IDX_SZ = 0x4, -++ UBIFS_CHK_ORPH = 0x8, -++ UBIFS_CHK_OLD_IDX = 0x10, -++ UBIFS_CHK_LPROPS = 0x20, -++}; -++ -++/* -++ * Special testing flags (must match tst_names in debug.c). -++ * -++ * UBIFS_TST_FORCE_IN_THE_GAPS: force the use of in-the-gaps method -++ * UBIFS_TST_RCVRY: failure mode for recovery testing -++ */ -++enum { -++ UBIFS_TST_FORCE_IN_THE_GAPS = 0x2, -++ UBIFS_TST_RCVRY = 0x4, -++}; -++ -++#if CONFIG_UBIFS_FS_DEBUG_MSG_LVL == 1 -++#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_1 -++#elif CONFIG_UBIFS_FS_DEBUG_MSG_LVL == 2 -++#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_2 -++#elif CONFIG_UBIFS_FS_DEBUG_MSG_LVL == 3 -++#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_3 -++#else -++#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_0 -++#endif -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG_CHKS -++#define UBIFS_CHK_FLAGS_DEFAULT 0xffffffff -++#else -++#define UBIFS_CHK_FLAGS_DEFAULT 0 -++#endif -++ -++extern spinlock_t dbg_lock; -++ -++extern unsigned int ubifs_msg_flags; -++extern unsigned int ubifs_chk_flags; -++extern unsigned int ubifs_tst_flags; -++ -++/* Dump functions */ -++ -++const char *dbg_ntype(int type); -++const char *dbg_cstate(int cmt_state); -++const char *dbg_get_key_dump(const struct ubifs_info *c, -++ const union ubifs_key *key); -++void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode); -++void dbg_dump_node(const struct ubifs_info *c, const void *node); -++void dbg_dump_budget_req(const struct ubifs_budget_req *req); -++void dbg_dump_lstats(const struct ubifs_lp_stats *lst); -++void dbg_dump_budg(struct ubifs_info *c); -++void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp); -++void dbg_dump_lprops(struct ubifs_info *c); -++void dbg_dump_leb(const struct ubifs_info *c, int lnum); -++void dbg_dump_znode(const struct ubifs_info *c, -++ const struct ubifs_znode *znode); -++void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat); -++void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, -++ struct ubifs_nnode *parent, int iip); -++void dbg_dump_tnc(struct ubifs_info *c); -++ -++/* Checking helper functions */ -++ -++typedef int (*dbg_leaf_callback)(struct ubifs_info *c, -++ struct ubifs_zbranch *zbr, void *priv); -++typedef int (*dbg_znode_callback)(struct ubifs_info *c, -++ struct ubifs_znode *znode, void *priv); -++ -++int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb, -++ dbg_znode_callback znode_cb, void *priv); -++int dbg_read_leaf_nolock(struct ubifs_info *c, struct ubifs_zbranch *zbr, -++ void *node); -++ -++/* Checking functions */ -++ -++int dbg_check_lprops(struct ubifs_info *c); -++ -++int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot); -++int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot); -++ -++int dbg_check_cats(struct ubifs_info *c); -++ -++int dbg_check_ltab(struct ubifs_info *c); -++ -++int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir); -++ -++int dbg_check_tnc(struct ubifs_info *c, int extra); -++ -++int dbg_check_idx_size(struct ubifs_info *c, long long idx_size); -++ -++void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat, -++ int add_pos); -++ -++int dbg_check_lprops(struct ubifs_info *c); -++int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode, -++ int row, int col); -++ -++/* Force the use of in-the-gaps method for testing */ -++ -++#define dbg_force_in_the_gaps_enabled \ -++ (ubifs_tst_flags & UBIFS_TST_FORCE_IN_THE_GAPS) -++ -++int dbg_force_in_the_gaps(void); -++ -++/* Failure mode for recovery testing */ -++ -++#define dbg_failure_mode (ubifs_tst_flags & UBIFS_TST_RCVRY) -++ -++void dbg_failure_mode_registration(struct ubifs_info *c); -++void dbg_failure_mode_deregistration(struct ubifs_info *c); -++ -++#ifndef UBIFS_DBG_PRESERVE_UBI -++ -++#define ubi_leb_read dbg_leb_read -++#define ubi_leb_write dbg_leb_write -++#define ubi_leb_change dbg_leb_change -++#define ubi_leb_erase dbg_leb_erase -++#define ubi_leb_unmap dbg_leb_unmap -++#define ubi_is_mapped dbg_is_mapped -++ -++#endif -++ -++int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, -++ int len, int check); -++int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, -++ int offset, int len, int dtype); -++int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, -++ int len, int dtype); -++int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum); -++int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum); -++int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum); -++ -++static inline int dbg_read(struct ubi_volume_desc *desc, int lnum, char *buf, -++ int offset, int len) -++{ -++ return dbg_leb_read(desc, lnum, buf, offset, len, 0); -++} -++ -++static inline int dbg_write(struct ubi_volume_desc *desc, int lnum, -++ const void *buf, int offset, int len) -++{ -++ return dbg_leb_write(desc, lnum, buf, offset, len, UBI_UNKNOWN); -++} -++ -++static inline int dbg_change(struct ubi_volume_desc *desc, int lnum, -++ const void *buf, int len) -++{ -++ return dbg_leb_change(desc, lnum, buf, len, UBI_UNKNOWN); -++} -++ -++#else /* !CONFIG_UBIFS_FS_DEBUG */ -++ -++#define UBIFS_DBG(op) -++#define ubifs_assert(expr) ({}) -++#define ubifs_assert_cmt_locked(c) -++#define dbg_dump_stack() -++#define dbg_err(fmt, ...) ({}) -++#define dbg_msg(fmt, ...) ({}) -++#define dbg_key(c, key, fmt, ...) ({}) -++ -++#define dbg_gen(fmt, ...) ({}) -++#define dbg_jnl(fmt, ...) ({}) -++#define dbg_tnc(fmt, ...) ({}) -++#define dbg_lp(fmt, ...) ({}) -++#define dbg_find(fmt, ...) ({}) -++#define dbg_mnt(fmt, ...) ({}) -++#define dbg_io(fmt, ...) ({}) -++#define dbg_cmt(fmt, ...) ({}) -++#define dbg_budg(fmt, ...) ({}) -++#define dbg_log(fmt, ...) ({}) -++#define dbg_gc(fmt, ...) ({}) -++#define dbg_scan(fmt, ...) ({}) -++#define dbg_rcvry(fmt, ...) ({}) -++ -++#define dbg_ntype(type) "" -++#define dbg_cstate(cmt_state) "" -++#define dbg_get_key_dump(c, key) ({}) -++#define dbg_dump_inode(c, inode) ({}) -++#define dbg_dump_node(c, node) ({}) -++#define dbg_dump_budget_req(req) ({}) -++#define dbg_dump_lstats(lst) ({}) -++#define dbg_dump_budg(c) ({}) -++#define dbg_dump_lprop(c, lp) ({}) -++#define dbg_dump_lprops(c) ({}) -++#define dbg_dump_leb(c, lnum) ({}) -++#define dbg_dump_znode(c, znode) ({}) -++#define dbg_dump_heap(c, heap, cat) ({}) -++#define dbg_dump_pnode(c, pnode, parent, iip) ({}) -++#define dbg_dump_tnc(c) ({}) -++ -++#define dbg_walk_index(c, leaf_cb, znode_cb, priv) 0 -++#define dbg_read_leaf_nolock(c, zbr, node) 0 -++ -++#define dbg_old_index_check_init(c, zroot) 0 -++#define dbg_check_old_index(c, zroot) 0 -++ -++#define dbg_check_cats(c) 0 -++ -++#define dbg_check_ltab(c) 0 -++ -++#define dbg_check_dir_size(c, dir) 0 -++ -++#define dbg_check_tnc(c, x) 0 -++ -++#define dbg_check_idx_size(c, idx_size) 0 -++ -++#define dbg_check_heap(c, heap, cat, add_pos) ({}) -++ -++#define dbg_check_lprops(c) 0 -++#define dbg_check_lpt_nodes(c, cnode, row, col) 0 -++ -++#define dbg_force_in_the_gaps_enabled 0 -++#define dbg_force_in_the_gaps() 0 -++ -++#define dbg_failure_mode 0 -++#define dbg_failure_mode_registration(c) ({}) -++#define dbg_failure_mode_deregistration(c) ({}) -++ -++#endif /* !CONFIG_UBIFS_FS_DEBUG */ -++ -++#endif /* !__UBIFS_DEBUG_H__ */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/dir.c linux-2.6.24.7/fs/ubifs/dir.c -+--- linux-2.6.24.7.old/fs/ubifs/dir.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/dir.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1017 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * Copyright (C) 2006, 2007 University of Szeged, Hungary -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ * Zoltan Sogor -++ */ -++ -++/* -++ * This file implements directory operations. -++ * -++ * All FS operations in this file allocate budget before writing anything to the -++ * media. If they fail to allocate it, the error is returned. The only -++ * exceptions are 'ubifs_unlink()' and 'ubifs_rmdir()' which keep working even -++ * if they unable to allocate the budget, because deletion %-ENOSPC failure is -++ * not what users are usually ready to get. UBIFS budgeting subsystem has some -++ * space reserved for these purposes. -++ * -++ * All operations in this file change the parent inode, e.g., 'ubifs_link()' -++ * changes ctime and nlink of the parent inode. The parent inode is written to -++ * the media straight away - it is not marked as dirty and there is no -++ * write-back for it. This was done to simplify file-system recovery which -++ * would otherwise be very difficult to do. So instead of marking the parent -++ * inode dirty, the operations mark it clean. -++ */ -++ -++#include "ubifs.h" -++ -++/* -++ * Provide backing_dev_info in order to disable readahead. For UBIFS, I/O is -++ * not deferred, it is done immediately in readpage, which means the user would -++ * have to wait not just for their own I/O but the readahead I/O as well i.e. -++ * completely pointless. -++ */ -++struct backing_dev_info ubifs_backing_dev_info = { -++ .ra_pages = 0, /* Set to zero to disable readahead */ -++ .state = 0, -++ .capabilities = BDI_CAP_MAP_COPY, -++ .unplug_io_fn = default_unplug_io_fn, -++}; -++ -++/** -++ * inherit_flags - inherit flags of the parent inode. -++ * @dir: parent inode -++ * @mode: new inode mode flags -++ * -++ * This is a helper function for 'ubifs_new_inode()' which inherits flag of the -++ * parent directory inode @dir. UBIFS inodes inherit the following flags: -++ * o %UBIFS_COMPR_FL, which is useful to switch compression on/of on -++ * sub-directory basis; -++ * o %UBIFS_SYNC_FL - useful for the same reasons; -++ * o %UBIFS_DIRSYNC_FL - similar, but relevant only to directories. -++ * -++ * This function returns the inherited flags. -++ */ -++static int inherit_flags(const struct inode *dir, int mode) -++{ -++ int flags; -++ const struct ubifs_inode *ui = ubifs_inode(dir); -++ -++ if (!S_ISDIR(dir->i_mode)) -++ /* -++ * The parent is not a directory, which means that an extended -++ * attribute inode is being created. No flags. -++ */ -++ return 0; -++ -++ flags = ui->flags & (UBIFS_COMPR_FL | UBIFS_SYNC_FL | UBIFS_DIRSYNC_FL); -++ if (!S_ISDIR(mode)) -++ /* The "DIRSYNC" flag only applies to directories */ -++ flags &= ~UBIFS_DIRSYNC_FL; -++ -++ return flags; -++} -++ -++/** -++ * ubifs_new_inode - allocate new UBIFS inode object. -++ * @c: UBIFS file-system description object -++ * @dir: parent directory inode -++ * @mode: inode mode flags -++ * -++ * This function finds an unused inode number, allocates new inode and -++ * initializes it. Returns new inode in case of success and an error code in -++ * case of failure. -++ */ -++struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir, -++ int mode) -++{ -++ struct inode *inode; -++ struct ubifs_inode *ui; -++ -++ inode = new_inode(c->vfs_sb); -++ if (!inode) -++ return ERR_PTR(-ENOMEM); -++ -++ /* -++ * Set 'S_NOCMTIME' to prevent VFS form updating [mc]time of inodes and -++ * marking them dirty in file write path (see 'file_update_time()'). -++ * UBIFS has to fully control "clean <-> dirty" transitions of inodes -++ * to make budgeting work. -++ */ -++ inode->i_flags |= (S_NOCMTIME); -++ -++ inode->i_uid = current->fsuid; -++ if (dir->i_mode & S_ISGID) { -++ inode->i_gid = dir->i_gid; -++ if (S_ISDIR(mode)) -++ mode |= S_ISGID; -++ } else -++ inode->i_gid = current->fsgid; -++ inode->i_mode = mode; -++ inode->i_mtime = inode->i_atime = inode->i_ctime = -++ ubifs_current_time(inode); -++ inode->i_mapping->nrpages = 0; -++ /* Disable readahead */ -++ inode->i_mapping->backing_dev_info = &ubifs_backing_dev_info; -++ -++ switch (mode & S_IFMT) { -++ case S_IFREG: -++ inode->i_mapping->a_ops = &ubifs_file_address_operations; -++ inode->i_op = &ubifs_file_inode_operations; -++ inode->i_fop = &ubifs_file_operations; -++ break; -++ case S_IFDIR: -++ inode->i_op = &ubifs_dir_inode_operations; -++ inode->i_fop = &ubifs_dir_operations; -++ inode->i_size = UBIFS_INO_NODE_SZ; -++ break; -++ case S_IFLNK: -++ inode->i_op = &ubifs_symlink_inode_operations; -++ break; -++ case S_IFSOCK: -++ case S_IFIFO: -++ case S_IFBLK: -++ case S_IFCHR: -++ inode->i_op = &ubifs_file_inode_operations; -++ break; -++ default: -++ BUG(); -++ } -++ -++ ui = ubifs_inode(inode); -++ ui->flags = inherit_flags(dir, mode); -++ ubifs_set_inode_flags(inode); -++ -++ if (S_ISREG(mode)) -++ ui->compr_type = c->default_compr; -++ else -++ ui->compr_type = UBIFS_COMPR_NONE; -++ -++ spin_lock(&c->cnt_lock); -++ /* Inode number overflow is currently not supported */ -++ if (c->highest_inum >= INUM_WARN_WATERMARK) { -++ if (c->highest_inum >= INUM_WATERMARK) { -++ spin_unlock(&c->cnt_lock); -++ ubifs_err("out of inode numbers"); -++ make_bad_inode(inode); -++ iput(inode); -++ return ERR_PTR(-EINVAL); -++ } -++ ubifs_warn("running out of inode numbers (current %lu, max %d)", -++ c->highest_inum, INUM_WATERMARK); -++ } -++ -++ inode->i_ino = ++c->highest_inum; -++ inode->i_generation = ++c->vfs_gen; -++ /* -++ * The creation sequence number remains with this inode for its -++ * lifetime. All nodes for this inode have a greater sequence number, -++ * and so it is possible to distinguish obsolete nodes belonging to a -++ * previous incarnation of the same inode number - for example, for the -++ * purpose of rebuilding the index. -++ */ -++ ui->creat_sqnum = ++c->max_sqnum; -++ spin_unlock(&c->cnt_lock); -++ -++ return inode; -++} -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ -++static int dbg_check_name(struct ubifs_dent_node *dent, struct qstr *nm) -++{ -++ if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) -++ return 0; -++ if (le16_to_cpu(dent->nlen) != nm->len) -++ return -EINVAL; -++ if (memcmp(dent->name, nm->name, nm->len)) -++ return -EINVAL; -++ return 0; -++} -++ -++#else -++ -++#define dbg_check_name(dent, nm) 0 -++ -++#endif -++ -++static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, -++ struct nameidata *nd) -++{ -++ int err; -++ union ubifs_key key; -++ struct inode *inode = NULL; -++ struct ubifs_dent_node *dent; -++ struct ubifs_info *c = dir->i_sb->s_fs_info; -++ -++ dbg_gen("'%.*s' in dir ino %lu", -++ dentry->d_name.len, dentry->d_name.name, dir->i_ino); -++ -++ if (dentry->d_name.len > UBIFS_MAX_NLEN) -++ return ERR_PTR(-ENAMETOOLONG); -++ -++ dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS); -++ if (!dent) -++ return ERR_PTR(-ENOMEM); -++ -++ dent_key_init(c, &key, dir->i_ino, &dentry->d_name); -++ -++ err = ubifs_tnc_lookup_nm(c, &key, dent, &dentry->d_name); -++ if (err) { -++ if (err == -ENOENT) { -++ dbg_gen("not found"); -++ goto done; -++ } -++ goto out; -++ } -++ -++ if (dbg_check_name(dent, &dentry->d_name)) { -++ err = -EINVAL; -++ goto out; -++ } -++ -++ inode = ubifs_iget(dir->i_sb, le64_to_cpu(dent->inum)); -++ if (IS_ERR(inode)) { -++ /* -++ * This should not happen. Probably the file-system needs -++ * checking. -++ */ -++ err = PTR_ERR(inode); -++ ubifs_err("dead directory entry '%.*s', error %d", -++ dentry->d_name.len, dentry->d_name.name, err); -++ ubifs_ro_mode(c, err); -++ goto out; -++ } -++ -++done: -++ kfree(dent); -++ /* -++ * Note, d_splice_alias() would be required instead if we supported -++ * NFS. -++ */ -++ d_add(dentry, inode); -++ return NULL; -++ -++out: -++ kfree(dent); -++ return ERR_PTR(err); -++} -++ -++static int ubifs_create(struct inode *dir, struct dentry *dentry, int mode, -++ struct nameidata *nd) -++{ -++ struct inode *inode; -++ struct ubifs_info *c = dir->i_sb->s_fs_info; -++ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 }; -++ int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len); -++ -++ dbg_gen("dent '%.*s', mode %#x in dir ino %lu", -++ dentry->d_name.len, dentry->d_name.name, mode, dir->i_ino); -++ -++ inode = ubifs_new_inode(c, dir, mode); -++ if (IS_ERR(inode)) -++ return PTR_ERR(inode); -++ -++ err = ubifs_budget_inode_op(c, dir, &req); -++ if (err) -++ goto out; -++ -++ dir->i_size += sz_change; -++ -++ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, -++ IS_DIRSYNC(dir), 0); -++ if (err) -++ goto out_budg; -++ -++ insert_inode_hash(inode); -++ d_instantiate(dentry, inode); -++ ubifs_release_ino_clean(c, dir, &req); -++ return 0; -++ -++out_budg: -++ dir->i_size -= sz_change; -++ ubifs_cancel_ino_op(c, dir, &req); -++ ubifs_err("cannot create regular file, error %d", err); -++out: -++ make_bad_inode(inode); -++ iput(inode); -++ return err; -++} -++ -++/** -++ * vfs_dent_type - get VFS directory entry type. -++ * @type: UBIFS directory entry type -++ * -++ * This function converts UBIFS directory entry type into VFS directory entry -++ * type. -++ */ -++static unsigned int vfs_dent_type(uint8_t type) -++{ -++ switch (type) { -++ case UBIFS_ITYPE_REG: -++ return DT_REG; -++ case UBIFS_ITYPE_DIR: -++ return DT_DIR; -++ case UBIFS_ITYPE_LNK: -++ return DT_LNK; -++ case UBIFS_ITYPE_BLK: -++ return DT_BLK; -++ case UBIFS_ITYPE_CHR: -++ return DT_CHR; -++ case UBIFS_ITYPE_FIFO: -++ return DT_FIFO; -++ case UBIFS_ITYPE_SOCK: -++ return DT_SOCK; -++ default: -++ BUG(); -++ } -++ return 0; -++} -++ -++/* -++ * The classical Unix view for directory is that it is a linear array of -++ * (name, inode number) entries. Linux/VFS assumes this model as well. -++ * Particularly, 'readdir()' call wants us to return a directory entry offset -++ * which later may be used to continue 'readdir()'ing the directory or to -++ * 'seek()' to that specific direntry. Obviously UBIFS does not really fit this -++ * model because directory entries are identified by keys, which may collide. -++ * -++ * UBIFS uses directory entry hash value for directory offsets, so -++ * 'seekdir()'/'telldir()' may not always work because of possible key -++ * collisions. But UBIFS guarantees that consecutive 'readdir()' calls work -++ * properly by means of saving full directory entry name in the private field -++ * of the file description object. -++ * -++ * This means that UBIFS cannot support NFS which requires full -++ * 'seekdir()'/'telldir()' support. -++ */ -++static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) -++{ -++ int err, over = 0; -++ struct qstr nm; -++ union ubifs_key key; -++ struct ubifs_dent_node *dent; -++ struct inode *dir = file->f_path.dentry->d_inode; -++ struct ubifs_info *c = dir->i_sb->s_fs_info; -++ -++ dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos); -++ -++ if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2) -++ /* -++ * The directory was seek'ed to a senseless position or there -++ * are no more entries. -++ */ -++ return 0; -++ -++ /* File positions 0 and 1 correspond to "." and ".." */ -++ if (file->f_pos == 0) { -++ ubifs_assert(!file->private_data); -++ over = filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR); -++ if (over) -++ return 0; -++ file->f_pos = 1; -++ } -++ -++ if (file->f_pos == 1) { -++ ubifs_assert(!file->private_data); -++ over = filldir(dirent, "..", 2, 1, -++ parent_ino(file->f_path.dentry), DT_DIR); -++ if (over) -++ return 0; -++ -++ /* Find the first entry in TNC and save it */ -++ lowest_dent_key(c, &key, dir->i_ino); -++ nm.name = NULL; -++ dent = ubifs_tnc_next_ent(c, &key, &nm); -++ if (IS_ERR(dent)) { -++ err = PTR_ERR(dent); -++ goto out; -++ } -++ -++ file->f_pos = key_hash_flash(c, &dent->key); -++ file->private_data = dent; -++ } -++ -++ dent = file->private_data; -++ if (!dent) { -++ /* -++ * The directory was seek'ed to and is now readdir'ed. -++ * Find the entry corresponding to @file->f_pos or the -++ * closest one. -++ */ -++ dent_key_init_hash(c, &key, dir->i_ino, file->f_pos); -++ nm.name = NULL; -++ dent = ubifs_tnc_next_ent(c, &key, &nm); -++ if (IS_ERR(dent)) { -++ err = PTR_ERR(dent); -++ goto out; -++ } -++ file->f_pos = key_hash_flash(c, &dent->key); -++ file->private_data = dent; -++ } -++ -++ while (1) { -++ dbg_gen("feed '%s', ino %llu, new f_pos %#x", -++ dent->name, le64_to_cpu(dent->inum), -++ key_hash_flash(c, &dent->key)); -++ ubifs_assert(dent->ch.sqnum > ubifs_inode(dir)->creat_sqnum); -++ -++ nm.len = le16_to_cpu(dent->nlen); -++ over = filldir(dirent, dent->name, nm.len, file->f_pos, -++ le64_to_cpu(dent->inum), -++ vfs_dent_type(dent->type)); -++ if (over) -++ return 0; -++ -++ /* Switch to the next entry */ -++ key_read(c, &dent->key, &key); -++ nm.name = dent->name; -++ dent = ubifs_tnc_next_ent(c, &key, &nm); -++ if (IS_ERR(dent)) { -++ err = PTR_ERR(dent); -++ goto out; -++ } -++ -++ kfree(file->private_data); -++ file->f_pos = key_hash_flash(c, &dent->key); -++ file->private_data = dent; -++ cond_resched(); -++ } -++ -++out: -++ if (err != -ENOENT) { -++ ubifs_err("cannot find next direntry, error %d", err); -++ return err; -++ } -++ -++ kfree(file->private_data); -++ file->private_data = NULL; -++ file->f_pos = 2; -++ return 0; -++} -++ -++/* If a directory is seeked, we have to free saved readdir() state */ -++loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int origin) -++{ -++ kfree(file->private_data); -++ file->private_data = NULL; -++ return generic_file_llseek(file, offset, origin); -++} -++ -++/* Free saved readdir() state when the directory is closed */ -++static int ubifs_dir_release(struct inode *dir, struct file *file) -++{ -++ kfree(file->private_data); -++ file->private_data = NULL; -++ return 0; -++} -++ -++static int ubifs_link(struct dentry *old_dentry, struct inode *dir, -++ struct dentry *dentry) -++{ -++ struct ubifs_info *c = dir->i_sb->s_fs_info; -++ struct inode *inode = old_dentry->d_inode; -++ struct ubifs_inode *ui = ubifs_inode(inode); -++ struct ubifs_budget_req req = { .new_dent = 1, .dirtied_ino = 1, -++ .dirtied_ino_d = ui->data_len }; -++ int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len); -++ -++ dbg_gen("dent '%.*s' to ino %lu (nlink %d) in dir ino %lu", -++ dentry->d_name.len, dentry->d_name.name, inode->i_ino, -++ inode->i_nlink, dir->i_ino); -++ -++ err = ubifs_budget_inode_op(c, dir, &req); -++ if (err) -++ return err; -++ -++ inc_nlink(inode); -++ dir->i_size += sz_change; -++ inode->i_ctime = dir->i_mtime = dir->i_ctime = -++ ubifs_current_time(inode); -++ -++ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, -++ IS_DIRSYNC(dir), 0); -++ if (err) -++ goto out_budg; -++ -++ atomic_inc(&inode->i_count); -++ d_instantiate(dentry, inode); -++ ubifs_release_ino_clean(c, dir, &req); -++ return 0; -++ -++out_budg: -++ dir->i_size -= sz_change; -++ ubifs_cancel_ino_op(c, dir, &req); -++ drop_nlink(inode); -++ iput(inode); -++ return err; -++} -++ -++static int ubifs_unlink(struct inode *dir, struct dentry *dentry) -++{ -++ struct ubifs_info *c = dir->i_sb->s_fs_info; -++ struct inode *inode = dentry->d_inode; -++ struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 1 }; -++ int sz_change = CALC_DENT_SIZE(dentry->d_name.len); -++ int err, budgeted = 1; -++ -++ dbg_gen("dent '%.*s' from ino %lu (nlink %d) in dir ino %lu", -++ dentry->d_name.len, dentry->d_name.name, inode->i_ino, -++ inode->i_nlink, dir->i_ino); -++ -++ err = ubifs_budget_inode_op(c, dir, &req); -++ if (err) { -++ if (err != -ENOSPC) -++ return err; -++ err = 0; -++ budgeted = 0; -++ } -++ -++ dir->i_size -= sz_change; -++ dir->i_mtime = dir->i_ctime = ubifs_current_time(dir); -++ -++ inode->i_ctime = dir->i_ctime; -++ drop_nlink(inode); -++ -++ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1, -++ IS_DIRSYNC(dir), 0); -++ if (err) -++ goto out_budg; -++ -++ if (budgeted) -++ ubifs_release_ino_clean(c, dir, &req); -++ -++ return 0; -++ -++out_budg: -++ dir->i_size += sz_change; -++ inc_nlink(inode); -++ if (budgeted) -++ ubifs_cancel_ino_op(c, dir, &req); -++ return err; -++} -++ -++/** -++ * check_dir_empty - check if a directory is empty or not. -++ * @c: UBIFS file-system description object -++ * @dir: VFS inode object of the directory to check -++ * -++ * This function checks if directory @dir is empty. Returns zero if the -++ * directory is empty, %-ENOTEMPTY if it is not, and other negative error codes -++ * in case of of errors. -++ */ -++static int check_dir_empty(struct ubifs_info *c, struct inode *dir) -++{ -++ struct qstr nm = { .name = NULL }; -++ struct ubifs_dent_node *dent; -++ union ubifs_key key; -++ int err; -++ -++ lowest_dent_key(c, &key, dir->i_ino); -++ dent = ubifs_tnc_next_ent(c, &key, &nm); -++ if (IS_ERR(dent)) { -++ err = PTR_ERR(dent); -++ if (err == -ENOENT) -++ err = 0; -++ } else { -++ kfree(dent); -++ err = -ENOTEMPTY; -++ } -++ -++ return err; -++} -++ -++static int ubifs_rmdir(struct inode *dir, struct dentry *dentry) -++{ -++ struct ubifs_info *c = dir->i_sb->s_fs_info; -++ struct inode *inode = dentry->d_inode; -++ struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 1 }; -++ int sz_change = CALC_DENT_SIZE(dentry->d_name.len); -++ int err, budgeted = 0; -++ -++ dbg_gen("directory '%.*s', ino %lu in dir ino %lu", dentry->d_name.len, -++ dentry->d_name.name, inode->i_ino, dir->i_ino); -++ -++ err = check_dir_empty(c, dentry->d_inode); -++ if (err) -++ return err; -++ -++ budgeted = 1; -++ err = ubifs_budget_inode_op(c, dir, &req); -++ if (err) { -++ if (err != -ENOSPC) -++ return err; -++ budgeted = 0; -++ } -++ -++ dir->i_size -= sz_change; -++ dir->i_mtime = dir->i_ctime = ubifs_current_time(dir); -++ drop_nlink(dir); -++ -++ inode->i_size = 0; -++ inode->i_ctime = dir->i_ctime; -++ clear_nlink(inode); -++ -++ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1, -++ IS_DIRSYNC(dir), 0); -++ if (err) -++ goto out_budg; -++ -++ if (budgeted) -++ ubifs_release_ino_clean(c, dir, &req); -++ -++ return 0; -++ -++out_budg: -++ dir->i_size += sz_change; -++ inc_nlink(dir); -++ inc_nlink(inode); -++ inc_nlink(inode); -++ if (budgeted) -++ ubifs_cancel_ino_op(c, dir, &req); -++ return err; -++} -++ -++static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, int mode) -++{ -++ struct inode *inode; -++ struct ubifs_info *c = dir->i_sb->s_fs_info; -++ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 }; -++ int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len); -++ -++ dbg_gen("dent '%.*s', mode %#x in dir ino %lu", -++ dentry->d_name.len, dentry->d_name.name, mode, dir->i_ino); -++ -++ err = ubifs_budget_inode_op(c, dir, &req); -++ if (err) -++ return err; -++ -++ inode = ubifs_new_inode(c, dir, S_IFDIR | mode); -++ if (IS_ERR(inode)) { -++ err = PTR_ERR(inode); -++ goto out_budg; -++ } -++ -++ insert_inode_hash(inode); -++ inc_nlink(inode); -++ -++ dir->i_mtime = dir->i_ctime = ubifs_current_time(dir); -++ dir->i_size += sz_change; -++ inc_nlink(dir); -++ -++ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, -++ IS_DIRSYNC(dir), 0); -++ if (err) { -++ ubifs_err("cannot create directory, error %d", err); -++ goto out_inode; -++ } -++ -++ d_instantiate(dentry, inode); -++ ubifs_release_ino_clean(c, dir, &req); -++ return 0; -++ -++out_inode: -++ dir->i_size -= sz_change; -++ drop_nlink(dir); -++ make_bad_inode(inode); -++ iput(inode); -++out_budg: -++ ubifs_cancel_ino_op(c, dir, &req); -++ return err; -++} -++ -++static int ubifs_mknod(struct inode *dir, struct dentry *dentry, -++ int mode, dev_t rdev) -++{ -++ struct inode *inode; -++ struct ubifs_info *c = dir->i_sb->s_fs_info; -++ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 }; -++ union ubifs_dev_desc *dev = NULL; -++ int sz_change = CALC_DENT_SIZE(dentry->d_name.len); -++ int err, devlen = 0; -++ -++ dbg_gen("dent '%.*s' in dir ino %lu", -++ dentry->d_name.len, dentry->d_name.name, dir->i_ino); -++ -++ if (!new_valid_dev(rdev)) -++ return -EINVAL; -++ -++ if (S_ISBLK(mode) || S_ISCHR(mode)) { -++ dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS); -++ if (!dev) -++ return -ENOMEM; -++ devlen = ubifs_encode_dev(dev, rdev); -++ } -++ -++ err = ubifs_budget_inode_op(c, dir, &req); -++ if (err) { -++ kfree(dev); -++ return err; -++ } -++ -++ inode = ubifs_new_inode(c, dir, mode); -++ if (IS_ERR(inode)) { -++ kfree(dev); -++ err = PTR_ERR(inode); -++ goto out_budg; -++ } -++ -++ init_special_inode(inode, inode->i_mode, rdev); -++ -++ inode->i_size = devlen; -++ ubifs_inode(inode)->data = dev; -++ ubifs_inode(inode)->data_len = devlen; -++ -++ dir->i_size += sz_change; -++ -++ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, -++ IS_DIRSYNC(dir), 0); -++ if (err) -++ goto out_inode; -++ -++ insert_inode_hash(inode); -++ d_instantiate(dentry, inode); -++ ubifs_release_ino_clean(c, dir, &req); -++ return 0; -++ -++out_inode: -++ dir->i_size -= sz_change; -++ make_bad_inode(inode); -++ iput(inode); -++out_budg: -++ ubifs_cancel_ino_op(c, dir, &req); -++ return err; -++} -++ -++static int ubifs_symlink(struct inode *dir, struct dentry *dentry, -++ const char *symname) -++{ -++ struct inode *inode; -++ struct ubifs_inode *ui; -++ struct ubifs_info *c = dir->i_sb->s_fs_info; -++ int err, len = strlen(symname); -++ int sz_change = CALC_DENT_SIZE(dentry->d_name.len); -++ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, -++ .new_ino_d = len }; -++ -++ dbg_gen("dent '%.*s', target '%s' in dir ino %lu", dentry->d_name.len, -++ dentry->d_name.name, symname, dir->i_ino); -++ -++ if (len > UBIFS_MAX_INO_DATA) -++ return -ENAMETOOLONG; -++ -++ err = ubifs_budget_inode_op(c, dir, &req); -++ if (err) -++ return err; -++ -++ inode = ubifs_new_inode(c, dir, S_IFLNK | S_IRWXUGO); -++ if (IS_ERR(inode)) { -++ err = PTR_ERR(inode); -++ goto out_budg; -++ } -++ -++ ui = ubifs_inode(inode); -++ ui->data = kmalloc(len + 1, GFP_NOFS); -++ if (!ui->data) { -++ err = -ENOMEM; -++ goto out_inode; -++ } -++ -++ memcpy(ui->data, symname, len); -++ ((char *)ui->data)[len] = '\0'; -++ /* -++ * The terminating zero byte is not written to the flash media and it -++ * is put just to make later in-memory string processing simpler. Thus, -++ * data length is @len, not @len + %1. -++ */ -++ ui->data_len = len; -++ inode->i_size = len; -++ -++ dir->i_size += sz_change; -++ -++ err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, -++ IS_DIRSYNC(dir), 0); -++ if (err) -++ goto out_dir; -++ -++ insert_inode_hash(inode); -++ d_instantiate(dentry, inode); -++ ubifs_release_ino_clean(c, dir, &req); -++ return 0; -++ -++out_dir: -++ dir->i_size -= sz_change; -++out_inode: -++ make_bad_inode(inode); -++ iput(inode); -++out_budg: -++ ubifs_cancel_ino_op(c, dir, &req); -++ return err; -++} -++ -++static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry, -++ struct inode *new_dir, struct dentry *new_dentry) -++{ -++ struct ubifs_info *c = old_dir->i_sb->s_fs_info; -++ struct inode *old_inode = old_dentry->d_inode; -++ struct inode *new_inode = new_dentry->d_inode; -++ int err, move = (new_dir != old_dir); -++ int is_dir = S_ISDIR(old_inode->i_mode); -++ int unlink = !!new_inode; -++ int dirsync = (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)); -++ int new_sz = CALC_DENT_SIZE(new_dentry->d_name.len); -++ int old_sz = CALC_DENT_SIZE(old_dentry->d_name.len); -++ struct ubifs_budget_req req = { .new_dent = 1, .mod_dent = 1 }; -++ struct timespec time = ubifs_current_time(old_dir); -++ -++ dbg_gen("dent '%.*s' ino %lu in dir ino %lu to dent '%.*s' in " -++ "dir ino %lu", old_dentry->d_name.len, old_dentry->d_name.name, -++ old_inode->i_ino, old_dir->i_ino, new_dentry->d_name.len, -++ new_dentry->d_name.name, new_dir->i_ino); -++ -++ if (unlink && is_dir) { -++ err = check_dir_empty(c, new_inode); -++ if (err) -++ return err; -++ } -++ -++ if (move) { -++ req.dirtied_ino = 1; -++ if (unlink) { -++ req.dirtied_ino += 2; -++ req.dirtied_ino_d = ubifs_inode(new_inode)->data_len; -++ } -++ } -++ -++ /* -++ * Note, rename may write @new_dir inode if the directory entry is -++ * moved there. And if the @new_dir is dirty, we do not bother to make -++ * it clean. It could be done, but requires extra coding which does not -++ * seem to be really worth it. -++ */ -++ err = ubifs_budget_inode_op(c, old_dir, &req); -++ if (err) -++ return err; -++ -++ /* -++ * Like most other Unix systems, set the ctime for inodes on a -++ * rename. -++ */ -++ old_inode->i_ctime = time; -++ -++ /* -++ * If we moved a directory to another parent directory, decrement -++ * 'i_nlink' of the old parent. Also, update 'i_size' of the old parent -++ * as well as its [mc]time. -++ */ -++ if (is_dir && move) -++ drop_nlink(old_dir); -++ old_dir->i_size -= old_sz; -++ old_dir->i_mtime = old_dir->i_ctime = time; -++ new_dir->i_mtime = new_dir->i_ctime = time; -++ -++ /* -++ * If we moved a directory object to new directory, parent's 'i_nlink' -++ * should be adjusted. -++ */ -++ if (move && is_dir) -++ inc_nlink(new_dir); -++ -++ /* -++ * And finally, if we unlinked a direntry which happened to have the -++ * same name as the moved direntry, we have to decrement 'i_nlink' of -++ * the unlinked inode and change its ctime. -++ */ -++ if (unlink) { -++ /* -++ * Directories cannot have hard-links, so if this is a -++ * directory, decrement its 'i_nlink' twice because an empty -++ * directory has 'i_nlink' 2. -++ */ -++ if (is_dir) -++ drop_nlink(new_inode); -++ new_inode->i_ctime = time; -++ drop_nlink(new_inode); -++ } else -++ new_dir->i_size += new_sz; -++ -++ err = ubifs_jnl_rename(c, old_dir, old_dentry, new_dir, new_dentry, -++ dirsync); -++ if (err) -++ goto out_inode; -++ -++ ubifs_release_ino_clean(c, old_dir, &req); -++ return 0; -++ -++out_inode: -++ if (unlink) { -++ if (is_dir) -++ inc_nlink(new_inode); -++ inc_nlink(new_inode); -++ } else -++ new_dir->i_size -= new_sz; -++ old_dir->i_size += old_sz; -++ if (is_dir && move) { -++ drop_nlink(new_dir); -++ inc_nlink(old_dir); -++ } -++ ubifs_cancel_ino_op(c, old_dir, &req); -++ return err; -++} -++ -++int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry, -++ struct kstat *stat) -++{ -++ struct inode *inode = dentry->d_inode; -++ loff_t size; -++ -++ stat->dev = inode->i_sb->s_dev; -++ stat->ino = inode->i_ino; -++ stat->mode = inode->i_mode; -++ stat->nlink = inode->i_nlink; -++ stat->uid = inode->i_uid; -++ stat->gid = inode->i_gid; -++ stat->rdev = inode->i_rdev; -++ stat->atime = inode->i_atime; -++ stat->mtime = inode->i_mtime; -++ stat->ctime = inode->i_ctime; -++ stat->blksize = UBIFS_BLOCK_SIZE; -++ stat->size = i_size_read(inode); -++ -++ spin_lock(&inode->i_lock); -++ size = ubifs_inode(inode)->xattr_size; -++ spin_unlock(&inode->i_lock); -++ -++ /* -++ * Unfortunately, the 'stat()' system call was designed for block -++ * device based file systems, and it is not appropriate for UBIFS, -++ * because UBIFS does not have notion of "block". For example, it is -++ * difficult to tell how many block a directory takes - it actually -++ * takes less than 300 bytes, but we have to round it to block size, -++ * which introduces large mistake. This makes utilities like 'du' to -++ * report completely senseless numbers. This is the reason why UBIFS -++ * goes the same way as JFFS2 - it reports zero blocks for everything -++ * but regular files, which makes more sense than reporting completely -++ * wrong sizes. -++ */ -++ if (S_ISREG(inode->i_mode)) -++ size += stat->size; -++ -++ size = ALIGN(size, UBIFS_BLOCK_SIZE); -++ /* -++ * Note, user-space expects 512-byte blocks count irrespectively of what -++ * was reported in @stat->size. -++ */ -++ stat->blocks = size >> 9; -++ -++ return 0; -++} -++ -++struct inode_operations ubifs_dir_inode_operations = { -++ .lookup = ubifs_lookup, -++ .create = ubifs_create, -++ .link = ubifs_link, -++ .symlink = ubifs_symlink, -++ .unlink = ubifs_unlink, -++ .mkdir = ubifs_mkdir, -++ .rmdir = ubifs_rmdir, -++ .mknod = ubifs_mknod, -++ .rename = ubifs_rename, -++ .setattr = ubifs_setattr, -++ .getattr = ubifs_getattr, -++#ifdef CONFIG_UBIFS_FS_XATTR -++ .setxattr = ubifs_setxattr, -++ .getxattr = ubifs_getxattr, -++ .listxattr = ubifs_listxattr, -++ .removexattr = ubifs_removexattr, -++#endif -++}; -++ -++struct file_operations ubifs_dir_operations = { -++ .llseek = ubifs_dir_llseek, -++ .release = ubifs_dir_release, -++ .read = generic_read_dir, -++ .readdir = ubifs_readdir, -++ .fsync = ubifs_fsync, -++ .unlocked_ioctl = ubifs_ioctl, -++#ifdef CONFIG_COMPAT -++ .compat_ioctl = ubifs_compat_ioctl, -++#endif -++}; -+diff -urN linux-2.6.24.7.old/fs/ubifs/file.c linux-2.6.24.7/fs/ubifs/file.c -+--- linux-2.6.24.7.old/fs/ubifs/file.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/file.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,983 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* -++ * This file implements VFS file and inode operations of regular files, device -++ * nodes and symlinks as well as address space operations. -++ * -++ * UBIFS uses 2 page flags: PG_private and PG_checked. PG_private is set if the -++ * page is dirty and is used for budgeting purposes - dirty pages should not be -++ * budgeted. The PG_checked flag is set if full budgeting is required for the -++ * page e.g., when it corresponds to a file hole or it is just beyond the file -++ * size. The budgeting is done in 'ubifs_write_begin()', because it is OK to -++ * fail in this function, and the budget is released in 'ubifs_write_end()'. So -++ * the PG_private and PG_checked flags carry the information about how the page -++ * was budgeted, to make it possible to release the budget properly. -++ * -++ * A thing to keep in mind: inode's 'i_mutex' is locked in most VFS operations -++ * we implement. However, this is not true for '->writepage()', which might be -++ * called with 'i_mutex' unlocked. For example, when pdflush is performing -++ * write-back, it calls 'writepage()' with unlocked 'i_mutex', although the -++ * inode has 'I_LOCK' flag in this case. At "normal" work-paths 'i_mutex' is -++ * locked in '->writepage', e.g. in "sys_write -> alloc_pages -> direct reclaim -++ * path'. So, in '->writepage()' we are only guaranteed that the page is -++ * locked. -++ * -++ * Similarly, 'i_mutex' does not have to be locked in readpage(), e.g., -++ * readahead path does not have it locked ("sys_read -> generic_file_aio_read -++ * -> ondemand_readahead -> readpage"). In case of readahead, 'I_LOCK' flag is -++ * not set as well. -++ * -++ * This, for example means that there might be 2 concurrent '->writepage()' -++ * calls for the same inode, but different inode dirty pages. -++ */ -++ -++#include "ubifs.h" -++#include -++ -++static int read_block(struct inode *inode, void *addr, unsigned int block, -++ struct ubifs_data_node *dn) -++{ -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ int err, len, out_len; -++ union ubifs_key key; -++ unsigned int dlen; -++ -++ data_key_init(c, &key, inode->i_ino, block); -++ err = ubifs_tnc_lookup(c, &key, dn); -++ if (err) { -++ if (err == -ENOENT) -++ /* Not found, so it must be a hole */ -++ memset(addr, 0, UBIFS_BLOCK_SIZE); -++ return err; -++ } -++ -++ ubifs_assert(dn->ch.sqnum > ubifs_inode(inode)->creat_sqnum); -++ -++ len = le32_to_cpu(dn->size); -++ if (len <= 0 || len > UBIFS_BLOCK_SIZE) -++ goto dump; -++ -++ dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ; -++ out_len = UBIFS_BLOCK_SIZE; -++ err = ubifs_decompress(&dn->data, dlen, addr, &out_len, -++ le16_to_cpu(dn->compr_type)); -++ if (err || len != out_len) -++ goto dump; -++ -++ /* -++ * Data length can be less than a full block, even for blocks that are -++ * not the last in the file (e.g., as a result of making a hole and -++ * appending data). Ensure that the remainder is zeroed out. -++ */ -++ if (len < UBIFS_BLOCK_SIZE) -++ memset(addr + len, 0, UBIFS_BLOCK_SIZE - len); -++ -++ return 0; -++ -++dump: -++ ubifs_err("bad data node (block %u, inode %lu)", -++ block, inode->i_ino); -++ dbg_dump_node(c, dn); -++ return -EINVAL; -++} -++ -++/* TODO: remove compatibility stuff as late as possible */ -++#ifdef UBIFS_COMPAT_USE_OLD_PREPARE_WRITE -++int ubifs_do_readpage(struct page *page) -++#else -++static int do_readpage(struct page *page) -++#endif -++{ -++ void *addr; -++ int err = 0, i; -++ unsigned int block, beyond; -++ struct ubifs_data_node *dn; -++ struct inode *inode = page->mapping->host; -++ loff_t i_size = i_size_read(inode); -++ -++ dbg_gen("ino %lu, pg %lu, i_size %lld, flags %#lx", -++ inode->i_ino, page->index, i_size, page->flags); -++ ubifs_assert(!PageChecked(page)); -++ ubifs_assert(!PagePrivate(page)); -++ -++ addr = kmap(page); -++ -++ block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT; -++ beyond = (i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; -++ if (block >= beyond) { -++ /* Reading beyond inode */ -++ SetPageChecked(page); -++ memset(addr, 0, PAGE_CACHE_SIZE); -++ goto out; -++ } -++ -++ dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS); -++ if (!dn) { -++ err = -ENOMEM; -++ goto error; -++ } -++ -++ i = 0; -++ while (1) { -++ int ret; -++ -++ if (block >= beyond) { -++ /* Reading beyond inode */ -++ err = -ENOENT; -++ memset(addr, 0, UBIFS_BLOCK_SIZE); -++ } else { -++ ret = read_block(inode, addr, block, dn); -++ if (ret) { -++ err = ret; -++ if (err != -ENOENT) -++ break; -++ } -++ } -++ if (++i >= UBIFS_BLOCKS_PER_PAGE) -++ break; -++ block += 1; -++ addr += UBIFS_BLOCK_SIZE; -++ } -++ if (err) { -++ if (err == -ENOENT) { -++ /* Not found, so it must be a hole */ -++ SetPageChecked(page); -++ dbg_gen("hole"); -++ goto out_free; -++ } -++ ubifs_err("cannot read page %lu of inode %lu, error %d", -++ page->index, inode->i_ino, err); -++ goto error; -++ } -++ -++out_free: -++ kfree(dn); -++out: -++ SetPageUptodate(page); -++ ClearPageError(page); -++ flush_dcache_page(page); -++ kunmap(page); -++ return 0; -++ -++error: -++ kfree(dn); -++ ClearPageUptodate(page); -++ SetPageError(page); -++ flush_dcache_page(page); -++ kunmap(page); -++ return err; -++} -++ -++/* TODO: remove compatibility stuff as late as possible */ -++#ifndef UBIFS_COMPAT_USE_OLD_PREPARE_WRITE -++ -++static int ubifs_write_begin(struct file *file, struct address_space *mapping, -++ loff_t pos, unsigned len, unsigned flags, -++ struct page **pagep, void **fsdata) -++{ -++ struct inode *inode = mapping->host; -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ pgoff_t index = pos >> PAGE_CACHE_SHIFT; -++ struct ubifs_budget_req req = { .new_page = 1 }; -++ loff_t i_size = i_size_read(inode); -++ int uninitialized_var(err); -++ struct page *page; -++ -++ ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY)); -++ -++ if (unlikely(c->ro_media)) -++ return -EROFS; -++ -++ /* -++ * We are about to have a page of data written and we have to budget for -++ * this. The very important point here is that we have to budget before -++ * locking the page, because budgeting may force write-back, which -++ * would wait on locked pages and deadlock if we had the page locked. -++ * -++ * At this point we do not know anything about the page of data we are -++ * going to change, so assume the biggest budget (i.e., assume that -++ * this is a new page of data and it does not override an older page of -++ * data in the inode). Later the budget will be amended if this is not -++ * true. -++ */ -++ if (pos + len > i_size) -++ /* -++ * We are writing beyond the file which means we are going to -++ * change inode size and make the inode dirty. And in turn, -++ * this means we have to budget for making the inode dirty. -++ * -++ * Note, if the inode is already dirty, -++ * 'ubifs_budget_inode_op()' will not allocate any budget, -++ * but will just lock the @budg_mutex of the inode to prevent -++ * it from becoming clean before we have changed its size, -++ * which is going to happen in 'ubifs_write_end()'. -++ */ -++ err = ubifs_budget_inode_op(c, inode, &req); -++ else -++ /* -++ * The inode is not going to be marked as dirty by this write -++ * operation, do not budget for this. -++ */ -++ err = ubifs_budget_space(c, &req); -++ if (unlikely(err)) -++ return err; -++ -++ page = __grab_cache_page(mapping, index); -++ if (unlikely(!page)) { -++ err = -ENOMEM; -++ goto out_release; -++ } -++ -++ if (!PageUptodate(page)) { -++ /* -++ * The page is not loaded from the flash and has to be loaded -++ * unless we are writing all of it. -++ */ -++ if (!(pos & PAGE_CACHE_MASK) && len == PAGE_CACHE_SIZE) -++ /* -++ * Set the PG_checked flag to make the further code -++ * assume the page is new. -++ */ -++ SetPageChecked(page); -++ else { -++ err = do_readpage(page); -++ if (err) -++ goto out_unlock; -++ } -++ -++ SetPageUptodate(page); -++ ClearPageError(page); -++ } -++ -++ if (PagePrivate(page)) -++ /* -++ * The page is dirty, which means it was budgeted twice: -++ * o first time the budget was allocated by the task which -++ * made the page dirty and set the PG_private flag; -++ * o and then we budgeted for it for the second time at the -++ * very beginning of this function. -++ * -++ * So what we have to do is to release the page budget we -++ * allocated. -++ * -++ * Note, the page write operation may change the inode length, -++ * which makes it dirty and means the budget should be -++ * allocated. This was done above in the "pos + len > i_size" -++ * case. If this was done, we do not free the the inode budget, -++ * because we cannot as we are really going to mark it dirty in -++ * the 'ubifs_write_end()' function. -++ */ -++ ubifs_release_new_page_budget(c); -++ else if (!PageChecked(page)) -++ /* -++ * The page is not new, which means we are changing the page -++ * which already exists on the media. This means that changing -++ * the page does not make the amount of indexing information -++ * larger, and this part of the budget which we have already -++ * acquired may be released. -++ */ -++ ubifs_convert_page_budget(c); -++ -++ *pagep = page; -++ return 0; -++ -++out_unlock: -++ unlock_page(page); -++ page_cache_release(page); -++out_release: -++ if (pos + len > i_size) -++ ubifs_cancel_ino_op(c, inode, &req); -++ else -++ ubifs_release_budget(c, &req); -++ return err; -++} -++ -++static int ubifs_write_end(struct file *file, struct address_space *mapping, -++ loff_t pos, unsigned len, unsigned copied, -++ struct page *page, void *fsdata) -++{ -++ struct inode *inode = mapping->host; -++ struct ubifs_inode *ui = ubifs_inode(inode); -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ loff_t i_size = i_size_read(inode); -++ -++ dbg_gen("ino %lu, pos %llu, pg %lu, len %u, copied %d, i_size %lld", -++ inode->i_ino, pos, page->index, len, copied, i_size); -++ -++ if (unlikely(copied < len && len == PAGE_CACHE_SIZE)) { -++ /* -++ * VFS copied less data to the page that it intended and -++ * declared in its '->write_begin()' call via the @len -++ * argument. If the page was not up-to-date, and @len was -++ * @PAGE_CACHE_SIZE, the 'ubifs_write_begin()' function did -++ * not load it from the media (for optimization reasons). This -++ * means that part of the page contains garbage. So read the -++ * page now. -++ */ -++ dbg_gen("copied %d instead of %d, read page and repeat", -++ copied, len); -++ -++ if (pos + len > i_size) -++ /* See a comment below about this hacky unlock */ -++ mutex_unlock(&ui->budg_mutex); -++ -++ copied = do_readpage(page); -++ -++ /* -++ * Return 0 to force VFS to repeat the whole operation, or the -++ * error code if 'do_readpage()' failed. -++ */ -++ goto out; -++ } -++ -++ if (!PagePrivate(page)) { -++ SetPagePrivate(page); -++ atomic_long_inc(&c->dirty_pg_cnt); -++ __set_page_dirty_nobuffers(page); -++ } -++ -++ if (pos + len > i_size) { -++ i_size_write(inode, pos + len); -++ -++ /* -++ * Note, we do not set @I_DIRTY_PAGES (which means that the -++ * inode has dirty pages), this has been done in -++ * '__set_page_dirty_nobuffers()'. -++ */ -++ mark_inode_dirty_sync(inode); -++ -++ /* -++ * The inode has been marked dirty, unlock it. This is a bit -++ * hacky because normally we would have to call -++ * 'ubifs_release_ino_dirty()'. But we know there is nothing -++ * to release because page's budget will be released in -++ * 'ubifs_write_page()' and inode's budget will be released in -++ * 'ubifs_write_inode()', so just unlock the inode here for -++ * optimization. -++ */ -++ mutex_unlock(&ui->budg_mutex); -++ } -++ -++out: -++ unlock_page(page); -++ page_cache_release(page); -++ return copied; -++} -++ -++#endif /* UBIFS_COMPAT_USE_OLD_PREPARE_WRITE */ -++ -++static int ubifs_readpage(struct file *file, struct page *page) -++{ -++ do_readpage(page); -++ unlock_page(page); -++ return 0; -++} -++ -++/** -++ * release_existing_page_budget - release budget of an existing page. -++ * @c: UBIFS file-system description object -++ * -++ * This is a helper function which releases budget corresponding to the budget -++ * of changing one one page of data which already exists on the flash media. -++ * -++ * This function was not moved to "budget.c" because there is only one user. -++ */ -++static void release_existing_page_budget(struct ubifs_info *c) -++{ -++ struct ubifs_budget_req req = { .dd_growth = c->page_budget}; -++ -++ ubifs_release_budget(c, &req); -++} -++ -++static int do_writepage(struct page *page, int len) -++{ -++ int err = 0, i, blen; -++ unsigned int block; -++ void *addr; -++ union ubifs_key key; -++ struct inode *inode = page->mapping->host; -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ -++ /* Update radix tree tags */ -++ set_page_writeback(page); -++ -++ addr = kmap(page); -++ -++ block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT; -++ i = 0; -++ while (len) { -++ blen = min_t(int, len, UBIFS_BLOCK_SIZE); -++ data_key_init(c, &key, inode->i_ino, block); -++ err = ubifs_jnl_write_data(c, inode, &key, addr, blen); -++ if (err) -++ break; -++ if (++i >= UBIFS_BLOCKS_PER_PAGE) -++ break; -++ block += 1; -++ addr += blen; -++ len -= blen; -++ } -++ if (err) { -++ SetPageError(page); -++ ubifs_err("cannot write page %lu of inode %lu, error %d", -++ page->index, inode->i_ino, err); -++ ubifs_ro_mode(c, err); -++ } -++ -++ ubifs_assert(PagePrivate(page)); -++ if (PageChecked(page)) -++ ubifs_release_new_page_budget(c); -++ else -++ release_existing_page_budget(c); -++ -++ atomic_long_dec(&c->dirty_pg_cnt); -++ ClearPagePrivate(page); -++ ClearPageChecked(page); -++ -++ kunmap(page); -++ unlock_page(page); -++ end_page_writeback(page); -++ -++ return err; -++} -++ -++static int ubifs_writepage(struct page *page, struct writeback_control *wbc) -++{ -++ struct inode *inode = page->mapping->host; -++ loff_t i_size = i_size_read(inode); -++ pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT; -++ int len; -++ void *kaddr; -++ -++ dbg_gen("ino %lu, pg %lu, pg flags %#lx", -++ inode->i_ino, page->index, page->flags); -++ ubifs_assert(PagePrivate(page)); -++ -++ /* Is the page fully inside i_size? */ -++ if (page->index < end_index) -++ return do_writepage(page, PAGE_CACHE_SIZE); -++ -++ /* Is the page fully outside i_size? (truncate in progress) */ -++ len = i_size & (PAGE_CACHE_SIZE - 1); -++ if (page->index >= end_index + 1 || !len) { -++ unlock_page(page); -++ return 0; -++ } -++ -++ /* -++ * The page straddles i_size. It must be zeroed out on each and every -++ * writepage invocation because it may be mmapped. "A file is mapped -++ * in multiples of the page size. For a file that is not a multiple of -++ * the page size, the remaining memory is zeroed when mapped, and -++ * writes to that region are not written out to the file." -++ */ -++ kaddr = kmap_atomic(page, KM_USER0); -++ memset(kaddr + len, 0, PAGE_CACHE_SIZE - len); -++ flush_dcache_page(page); -++ kunmap_atomic(kaddr, KM_USER0); -++ -++ return do_writepage(page, len); -++} -++ -++static int ubifs_trunc(struct inode *inode, loff_t new_size) -++{ -++ loff_t old_size; -++ int err; -++ -++ dbg_gen("ino %lu, size %lld -> %lld", -++ inode->i_ino, inode->i_size, new_size); -++ old_size = inode->i_size; -++ -++ err = vmtruncate(inode, new_size); -++ if (err) -++ return err; -++ -++ if (new_size < old_size) { -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ int offset = new_size & (UBIFS_BLOCK_SIZE - 1); -++ -++ if (offset) { -++ pgoff_t index = new_size >> PAGE_CACHE_SHIFT; -++ struct page *page; -++ -++ page = find_lock_page(inode->i_mapping, index); -++ if (page) { -++ if (PageDirty(page)) { -++ ubifs_assert(PagePrivate(page)); -++ -++ clear_page_dirty_for_io(page); -++ if (UBIFS_BLOCKS_PER_PAGE_SHIFT) -++ offset = new_size & -++ (PAGE_CACHE_SIZE - 1); -++ err = do_writepage(page, offset); -++ page_cache_release(page); -++ if (err) -++ return err; -++ /* -++ * We could now tell ubifs_jnl_truncate -++ * not to read the last block. -++ */ -++ } else { -++ /* -++ * We could 'kmap()' the page and -++ * pass the data to ubifs_jnl_truncate -++ * to save it from having to read it. -++ */ -++ unlock_page(page); -++ page_cache_release(page); -++ } -++ } -++ } -++ err = ubifs_jnl_truncate(c, inode->i_ino, old_size, new_size); -++ if (err) -++ return err; -++ } -++ -++ return 0; -++} -++ -++int ubifs_setattr(struct dentry *dentry, struct iattr *attr) -++{ -++ unsigned int ia_valid = attr->ia_valid; -++ struct inode *inode = dentry->d_inode; -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ struct ubifs_budget_req req; -++ int truncation, err = 0; -++ -++ dbg_gen("ino %lu, ia_valid %#x", inode->i_ino, ia_valid); -++ err = inode_change_ok(inode, attr); -++ if (err) -++ return err; -++ -++ memset(&req, 0, sizeof(struct ubifs_budget_req)); -++ -++ /* -++ * If this is truncation, and we do not truncate on a block boundary, -++ * budget for changing one data block, because the last block will be -++ * re-written. -++ */ -++ truncation = (ia_valid & ATTR_SIZE) && attr->ia_size != inode->i_size; -++ if (truncation && attr->ia_size < inode->i_size && -++ (attr->ia_size & (UBIFS_BLOCK_SIZE - 1))) -++ req.dirtied_page = 1; -++ -++ err = ubifs_budget_inode_op(c, inode, &req); -++ if (err) -++ return err; -++ -++ if (truncation) { -++ err = ubifs_trunc(inode, attr->ia_size); -++ if (err) { -++ ubifs_cancel_ino_op(c, inode, &req); -++ return err; -++ } -++ -++ inode->i_mtime = inode->i_ctime = ubifs_current_time(inode); -++ } -++ -++ if (ia_valid & ATTR_UID) -++ inode->i_uid = attr->ia_uid; -++ if (ia_valid & ATTR_GID) -++ inode->i_gid = attr->ia_gid; -++ if (ia_valid & ATTR_ATIME) -++ inode->i_atime = timespec_trunc(attr->ia_atime, -++ inode->i_sb->s_time_gran); -++ if (ia_valid & ATTR_MTIME) -++ inode->i_mtime = timespec_trunc(attr->ia_mtime, -++ inode->i_sb->s_time_gran); -++ if (ia_valid & ATTR_CTIME) -++ inode->i_ctime = timespec_trunc(attr->ia_ctime, -++ inode->i_sb->s_time_gran); -++ if (ia_valid & ATTR_MODE) { -++ umode_t mode = attr->ia_mode; -++ -++ if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) -++ mode &= ~S_ISGID; -++ inode->i_mode = mode; -++ } -++ -++ mark_inode_dirty_sync(inode); -++ ubifs_release_ino_dirty(c, inode, &req); -++ -++ if (req.dirtied_page) { -++ /* -++ * Truncation code does not make the reenacted page dirty, it -++ * just changes it on journal level, so we have to release page -++ * change budget. -++ */ -++ memset(&req, 0, sizeof(struct ubifs_budget_req)); -++ req.dd_growth = c->page_budget; -++ ubifs_release_budget(c, &req); -++ } -++ -++ if (IS_SYNC(inode)) -++ err = write_inode_now(inode, 1); -++ -++ return err; -++} -++ -++static void ubifs_invalidatepage(struct page *page, unsigned long offset) -++{ -++ struct inode *inode = page->mapping->host; -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ struct ubifs_budget_req req; -++ -++ ubifs_assert(PagePrivate(page)); -++ if (offset) -++ /* Partial page remains dirty */ -++ return; -++ -++ memset(&req, 0, sizeof(struct ubifs_budget_req)); -++ if (PageChecked(page)) { -++ req.new_page = 1; -++ req.idx_growth = -1; -++ req.data_growth = c->page_budget; -++ } else -++ req.dd_growth = c->page_budget; -++ ubifs_release_budget(c, &req); -++ -++ atomic_long_dec(&c->dirty_pg_cnt); -++ ClearPagePrivate(page); -++ ClearPageChecked(page); -++} -++ -++static void *ubifs_follow_link(struct dentry *dentry, struct nameidata *nd) -++{ -++ struct ubifs_inode *ui = ubifs_inode(dentry->d_inode); -++ -++ nd_set_link(nd, ui->data); -++ return NULL; -++} -++ -++int ubifs_fsync(struct file *file, struct dentry *dentry, int datasync) -++{ -++ struct inode *inode = dentry->d_inode; -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ int err; -++ -++ dbg_gen("syncing inode %lu", inode->i_ino); -++ -++ /* Synchronize the inode and dirty pages */ -++ err = write_inode_now(inode, 1); -++ if (err) -++ return err; -++ -++ /* -++ * Some data related to this inode may still sit in a write-buffer. -++ * Flush them. -++ */ -++ err = ubifs_sync_wbufs_by_inodes(c, &inode, 1); -++ if (err) -++ return err; -++ -++ return 0; -++} -++ -++/** -++ * mctime_update_needed - check if mtime or ctime update is needed. -++ * @inode: the inode to do the check for -++ * @now: current time -++ * -++ * This helper function checks if the inode mtime/ctime should be updated or -++ * not. If current values of the time-stamps are within the UBIFS inode time -++ * granularity, they are not updated. This is an optimization. -++ */ -++static inline int mctime_update_needed(struct inode *inode, -++ struct timespec *now) -++{ -++ if (!timespec_equal(&inode->i_mtime, now) || -++ !timespec_equal(&inode->i_ctime, now)) -++ return 1; -++ return 0; -++} -++ -++/** -++ * update_ctime - update mtime and ctime of an inode. -++ * @c: UBIFS file-system description object -++ * @inode: inode to update -++ * -++ * This function updates mtime and ctime of the inode if it is not equivalent to -++ * current time. Returns zero in case of success and a negative error code in -++ * case of failure. -++ */ -++static int update_mctime(struct ubifs_info *c, struct inode *inode) -++{ -++ struct timespec now = ubifs_current_time(inode); -++ -++ if (mctime_update_needed(inode, &now)) { -++ struct ubifs_budget_req req; -++ int err; -++ -++ memset(&req, 0, sizeof(struct ubifs_budget_req)); -++ err = ubifs_budget_inode_op(c, inode, &req); -++ if (err) -++ return err; -++ -++ inode->i_mtime = inode->i_ctime = now; -++ mark_inode_dirty_sync(inode); -++ mutex_unlock(&ubifs_inode(inode)->budg_mutex); -++ } -++ -++ return 0; -++} -++ -++static ssize_t ubifs_write(struct file *file, const char __user *buf, -++ size_t len, loff_t *ppos) -++{ -++ int err; -++ ssize_t ret; -++ struct inode *inode = file->f_mapping->host; -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ -++ err = update_mctime(c, inode); -++ if (err) -++ return err; -++ -++ ret = do_sync_write(file, buf, len, ppos); -++ if (ret < 0) -++ return ret; -++ -++ if (ret > 0 && IS_SYNC(inode)) { -++ err = ubifs_sync_wbufs_by_inodes(c, &inode, 1); -++ if (err) -++ return err; -++ } -++ -++ return ret; -++} -++ -++static ssize_t ubifs_aio_write(struct kiocb *iocb, const struct iovec *iov, -++ unsigned long nr_segs, loff_t pos) -++{ -++ int err; -++ ssize_t ret; -++ struct inode *inode = iocb->ki_filp->f_mapping->host; -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ -++ err = update_mctime(c, inode); -++ if (err) -++ return err; -++ -++ ret = generic_file_aio_write(iocb, iov, nr_segs, pos); -++ if (ret < 0) -++ return ret; -++ -++ if (ret > 0 && IS_SYNC(inode)) { -++ err = ubifs_sync_wbufs_by_inodes(c, &inode, 1); -++ if (err) -++ return err; -++ } -++ -++ return ret; -++} -++ -++static int ubifs_set_page_dirty(struct page *page) -++{ -++ int ret; -++ -++ ret = __set_page_dirty_nobuffers(page); -++ /* -++ * An attempt to dirty a page without budgeting for it - should not -++ * happen. -++ */ -++ ubifs_assert(ret == 0); -++ return ret; -++} -++ -++static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags) -++{ -++ /* -++ * An attempt to release a dirty page without budgeting for it - should -++ * not happen. -++ */ -++ if (PageWriteback(page)) -++ return 0; -++ ubifs_assert(PagePrivate(page)); -++ ubifs_assert(0); -++ ClearPagePrivate(page); -++ ClearPageChecked(page); -++ return 1; -++} -++ -++#ifndef UBIFS_COMPAT_NO_SHARED_MMAP -++ -++/* -++ * mmap()d file has taken write protection fault and is being made -++ * writable. UBIFS must ensure page is budgeted for. -++ */ -++static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page) -++{ -++ struct inode *inode = vma->vm_file->f_path.dentry->d_inode; -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ struct timespec now = ubifs_current_time(inode); -++ struct ubifs_budget_req req = { .new_page = 1 }; -++ int err, update_time; -++ -++ dbg_gen("ino %lu, pg %lu, i_size %lld", inode->i_ino, page->index, -++ i_size_read(inode)); -++ ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY)); -++ -++ if (unlikely(c->ro_media)) -++ return -EROFS; -++ -++ /* -++ * We have not locked @page so far so we may budget for changing the -++ * page. Note, we cannot do this after we locked the page, because -++ * budgeting may cause write-back which would cause deadlock. -++ * -++ * At the moment we do not know whether the page is dirty or not, so we -++ * assume that it is not and budget for a new page. We could look at -++ * the @PG_private flag and figure this out, but we may race with write -++ * back and the page state may change by the time we lock it, so this -++ * would need additional care. We do not bother with this at the -++ * moment, although it might be good idea to do. Instead, we allocate -++ * budget for a new page and amend it later on if the page was in fact -++ * dirty. -++ * -++ * The budgeting-related logic of this function is similar to what we -++ * do in 'ubifs_write_begin()' and 'ubifs_write_end()'. Glance there -++ * for more comments. -++ */ -++ if (mctime_update_needed(inode, &now)) { -++ /* -++ * We have to change inode time stamp which requires extra -++ * budgeting. -++ */ -++ update_time = 1; -++ err = ubifs_budget_inode_op(c, inode, &req); -++ } else { -++ update_time = 0; -++ err = ubifs_budget_space(c, &req); -++ } -++ if (unlikely(err)) { -++ if (err == -ENOSPC) -++ ubifs_warn("out of space for mmapped file " -++ "(inode number %lu)", inode->i_ino); -++ return err; -++ } -++ -++ lock_page(page); -++ if (unlikely(page->mapping != inode->i_mapping || -++ page_offset(page) > i_size_read(inode))) { -++ /* Page got truncated out from underneath us */ -++ err = -EINVAL; -++ goto out_unlock; -++ } -++ -++ if (PagePrivate(page)) -++ ubifs_release_new_page_budget(c); -++ else { -++ if (!PageChecked(page)) -++ ubifs_convert_page_budget(c); -++ SetPagePrivate(page); -++ atomic_long_inc(&c->dirty_pg_cnt); -++ __set_page_dirty_nobuffers(page); -++ } -++ -++ if (update_time) { -++ inode->i_mtime = inode->i_ctime = now; -++ mark_inode_dirty_sync(inode); -++ mutex_unlock(&ubifs_inode(inode)->budg_mutex); -++ } -++ -++ unlock_page(page); -++ return 0; -++ -++out_unlock: -++ unlock_page(page); -++ if (update_time) -++ ubifs_cancel_ino_op(c, inode, &req); -++ else -++ ubifs_release_budget(c, &req); -++ return err; -++} -++ -++struct vm_operations_struct ubifs_file_vm_ops = { -++#if (LINUX_VERSION_CODE == KERNEL_VERSION(2,6,22)) -++ .nopage = filemap_nopage, -++#else -++ .fault = filemap_fault, -++#endif -++ .page_mkwrite = ubifs_vm_page_mkwrite, -++}; -++ -++static int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma) -++{ -++ int err; -++ -++ /* 'generic_file_mmap()' takes care of NOMMU case */ -++ err = generic_file_mmap(file, vma); -++ if (err) -++ return err; -++ vma->vm_ops = &ubifs_file_vm_ops; -++ return 0; -++} -++#endif -++ -++struct address_space_operations ubifs_file_address_operations = { -++ .readpage = ubifs_readpage, -++ .writepage = ubifs_writepage, -++/* TODO: remove compatibility stuff as late as possible */ -++#ifdef UBIFS_COMPAT_USE_OLD_PREPARE_WRITE -++ .prepare_write = ubifs_prepare_write, -++ .commit_write = ubifs_commit_write, -++#else -++ .write_begin = ubifs_write_begin, -++ .write_end = ubifs_write_end, -++#endif -++ .invalidatepage = ubifs_invalidatepage, -++ .set_page_dirty = ubifs_set_page_dirty, -++ .releasepage = ubifs_releasepage, -++}; -++ -++struct inode_operations ubifs_file_inode_operations = { -++ .setattr = ubifs_setattr, -++ .getattr = ubifs_getattr, -++#ifdef CONFIG_UBIFS_FS_XATTR -++ .setxattr = ubifs_setxattr, -++ .getxattr = ubifs_getxattr, -++ .listxattr = ubifs_listxattr, -++ .removexattr = ubifs_removexattr, -++#endif -++}; -++ -++struct inode_operations ubifs_symlink_inode_operations = { -++ .readlink = generic_readlink, -++ .follow_link = ubifs_follow_link, -++ .setattr = ubifs_setattr, -++ .getattr = ubifs_getattr, -++}; -++ -++struct file_operations ubifs_file_operations = { -++ .llseek = generic_file_llseek, -++ .read = do_sync_read, -++ .write = ubifs_write, -++ .aio_read = generic_file_aio_read, -++ .aio_write = ubifs_aio_write, -++ .mmap = ubifs_file_mmap, -++ .fsync = ubifs_fsync, -++ .unlocked_ioctl = ubifs_ioctl, -++#ifdef CONFIG_COMPAT -++ .compat_ioctl = ubifs_compat_ioctl, -++#endif -++}; -+diff -urN linux-2.6.24.7.old/fs/ubifs/find.c linux-2.6.24.7/fs/ubifs/find.c -+--- linux-2.6.24.7.old/fs/ubifs/find.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/find.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,971 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* -++ * This file contains functions for finding LEBs for various purposes e.g. -++ * garbage collection. In general, lprops category heaps and lists are used -++ * for fast access, falling back on scanning the LPT as a last resort. -++ */ -++ -++#include -++#include "ubifs.h" -++ -++/** -++ * struct scan_data - data provided to scan callback functions -++ * @min_space: minimum number of bytes for which to scan -++ * @pick_free: whether it is OK to scan for empty LEBs -++ * @lnum: LEB number found is returned here -++ * @exclude_index: whether to exclude index LEBs -++ */ -++struct scan_data { -++ int min_space; -++ int pick_free; -++ int lnum; -++ int exclude_index; -++}; -++ -++/** -++ * valuable - determine whether LEB properties are valuable. -++ * @c: the UBIFS file-system description object -++ * @lprops: LEB properties -++ * -++ * This function return %1 if the LEB properties should be added to the LEB -++ * properties tree in memory. Otherwise %0 is returned. -++ */ -++static int valuable(struct ubifs_info *c, const struct ubifs_lprops *lprops) -++{ -++ int n, cat = lprops->flags & LPROPS_CAT_MASK; -++ struct ubifs_lpt_heap *heap; -++ -++ switch (cat) { -++ case LPROPS_DIRTY: -++ case LPROPS_DIRTY_IDX: -++ case LPROPS_FREE: -++ heap = &c->lpt_heap[cat - 1]; -++ if (heap->cnt < heap->max_cnt) -++ return 1; -++ if (lprops->free + lprops->dirty >= c->dark_wm) -++ return 1; -++ return 0; -++ case LPROPS_EMPTY: -++ n = c->lst.empty_lebs + c->freeable_cnt - -++ c->lst.taken_empty_lebs; -++ if (n < c->lsave_cnt) -++ return 1; -++ return 0; -++ case LPROPS_FREEABLE: -++ return 1; -++ case LPROPS_FRDI_IDX: -++ return 1; -++ } -++ return 0; -++} -++ -++/** -++ * scan_for_dirty_cb - dirty space scan callback. -++ * @c: the UBIFS file-system description object -++ * @lprops: LEB properties to scan -++ * @in_tree: whether the LEB properties are in main memory -++ * @data: information passed to and from the caller of the scan -++ * -++ * This function returns a code that indicates whether the scan should continue -++ * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree -++ * in main memory (%LPT_SCAN_ADD), or whether the scan should stop -++ * (%LPT_SCAN_STOP). -++ */ -++static int scan_for_dirty_cb(struct ubifs_info *c, -++ const struct ubifs_lprops *lprops, int in_tree, -++ struct scan_data *data) -++{ -++ int ret = LPT_SCAN_CONTINUE; -++ -++ /* Exclude LEBs that are currently in use */ -++ if (lprops->flags & LPROPS_TAKEN) -++ return LPT_SCAN_CONTINUE; -++ /* Determine whether to add these LEB properties to the tree */ -++ if (!in_tree && valuable(c, lprops)) -++ ret |= LPT_SCAN_ADD; -++ /* Exclude LEBs with too little space */ -++ if (lprops->free + lprops->dirty < data->min_space) -++ return ret; -++ /* If specified, exclude index LEBs */ -++ if (data->exclude_index && lprops->flags & LPROPS_INDEX) -++ return ret; -++ /* If specified, exclude empty or freeable LEBs */ -++ if (!data->pick_free && lprops->free + lprops->dirty == c->leb_size) -++ return ret; -++ /* Exclude LEBs with too little dirty space (unless it is empty) */ -++ if (lprops->dirty < c->dead_wm && lprops->free != c->leb_size) -++ return ret; -++ /* Finally we found space */ -++ data->lnum = lprops->lnum; -++ return LPT_SCAN_ADD | LPT_SCAN_STOP; -++} -++ -++/** -++ * scan_for_dirty - find a data LEB with free space. -++ * @c: the UBIFS file-system description object -++ * @min_space: minimum amount free plus dirty space the returned LEB has to -++ * have -++ * @pick_free: if it is OK to return a free or freeable LEB -++ * @exclude_index: whether to exclude index LEBs -++ * -++ * This function returns a pointer to the LEB properties found or a negative -++ * error code. -++ */ -++static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c, -++ int min_space, int pick_free, -++ int exclude_index) -++{ -++ const struct ubifs_lprops *lprops; -++ struct ubifs_lpt_heap *heap; -++ struct scan_data data; -++ int err, i; -++ -++ /* There may be an LEB with enough dirty space on the free heap */ -++ heap = &c->lpt_heap[LPROPS_FREE - 1]; -++ for (i = 0; i < heap->cnt; i++) { -++ lprops = heap->arr[i]; -++ if (lprops->free + lprops->dirty < min_space) -++ continue; -++ if (lprops->dirty < c->dead_wm) -++ continue; -++ return lprops; -++ } -++ /* -++ * A LEB may have fallen off of the bottom of the dirty heap, and ended -++ * up as uncategorized even though it has enough dirty space for us now, -++ * so check the uncategorized list. N.B. neither empty nor freeable LEBs -++ * can end up as uncategorized because they are kept on lists not -++ * finite-sized heaps. -++ */ -++ list_for_each_entry(lprops, &c->uncat_list, list) { -++ if (lprops->flags & LPROPS_TAKEN) -++ continue; -++ if (lprops->free + lprops->dirty < min_space) -++ continue; -++ if (exclude_index && (lprops->flags & LPROPS_INDEX)) -++ continue; -++ if (lprops->dirty < c->dead_wm) -++ continue; -++ return lprops; -++ } -++ /* We have looked everywhere in main memory, now scan the flash */ -++ if (c->pnodes_have >= c->pnode_cnt) -++ /* All pnodes are in memory, so skip scan */ -++ return ERR_PTR(-ENOSPC); -++ data.min_space = min_space; -++ data.pick_free = pick_free; -++ data.lnum = -1; -++ data.exclude_index = exclude_index; -++ err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum, -++ (ubifs_lpt_scan_callback)scan_for_dirty_cb, -++ &data); -++ if (err) -++ return ERR_PTR(err); -++ ubifs_assert(data.lnum >= c->main_first && data.lnum < c->leb_cnt); -++ c->lscan_lnum = data.lnum; -++ lprops = ubifs_lpt_lookup_dirty(c, data.lnum); -++ if (IS_ERR(lprops)) -++ return lprops; -++ ubifs_assert(lprops->lnum == data.lnum); -++ ubifs_assert(lprops->free + lprops->dirty >= min_space); -++ ubifs_assert(lprops->dirty >= c->dead_wm); -++ ubifs_assert(!(lprops->flags & LPROPS_TAKEN)); -++ ubifs_assert(!(lprops->flags & LPROPS_INDEX)); -++ return lprops; -++} -++ -++/** -++ * ubifs_find_dirty_leb - find a dirty LEB for the Garbage Collector. -++ * @c: the UBIFS file-system description object -++ * @ret_lp: LEB properties are returned here on exit -++ * @min_space: minimum amount free plus dirty space the returned LEB has to -++ * have -++ * @pick_free: controls whether it is OK to pick empty or index LEBs -++ * -++ * This function tries to find a dirty logical eraseblock which has at least -++ * @min_space free and dirty space. It prefers to take an LEB from the dirty or -++ * dirty index heap, and it falls-back to LPT scanning if the heaps are empty -++ * or do not have an LEB which satisfies the @min_space criteria. -++ * -++ * Note: -++ * o LEBs which have less than dead watermark of dirty space are never picked -++ * by this function; -++ * -++ * Returns zero and the LEB properties of -++ * found dirty LEB in case of success, %-ENOSPC if no dirty LEB was found and a -++ * negative error code in case of other failures. The returned LEB is marked as -++ * "taken". -++ * -++ * The additional @pick_free argument controls if this function has to return a -++ * free or freeable LEB if one is present. For example, GC must to set it to %1, -++ * when called from the journal space reservation function, because the -++ * appearance of free space may coincide with the loss of enough dirty space -++ * for GC to succeed anyway. -++ * -++ * In contrast, if the Garbage Collector is called from budgeting, it should -++ * just make free space, not return LEBs which are already free or freeable. -++ * -++ * In addition @pick_free is set to %2 by the recovery process in order to -++ * recover gc_lnum in which case an index LEB must not be returned. -++ */ -++int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp, -++ int min_space, int pick_free) -++{ -++ int err = 0, sum, exclude_index = pick_free == 2 ? 1 : 0; -++ const struct ubifs_lprops *lp = NULL, *idx_lp = NULL; -++ struct ubifs_lpt_heap *heap, *idx_heap; -++ -++ ubifs_get_lprops(c); -++ -++ if (pick_free) { -++ int lebs, rsvd_idx_lebs = 0; -++ -++ spin_lock(&c->space_lock); -++ lebs = c->lst.empty_lebs; -++ lebs += c->freeable_cnt - c->lst.taken_empty_lebs; -++ -++ /* -++ * Note, the index may consume more LEBs than have been reserved -++ * for it. It is OK because it might be consolidated by GC. -++ * But if the index takes fewer LEBs than it is reserved for it, -++ * this function must avoid picking those reserved LEBs. -++ */ -++ if (c->min_idx_lebs >= c->lst.idx_lebs) { -++ rsvd_idx_lebs = c->min_idx_lebs - c->lst.idx_lebs; -++ exclude_index = 1; -++ } -++ spin_unlock(&c->space_lock); -++ -++ /* Check if there are enough free LEBs for the index */ -++ if (rsvd_idx_lebs < lebs) { -++ /* OK, try to find an empty LEB */ -++ lp = ubifs_fast_find_empty(c); -++ if (lp) -++ goto found; -++ -++ /* Or a freeable LEB */ -++ lp = ubifs_fast_find_freeable(c); -++ if (lp) -++ goto found; -++ } else -++ /* -++ * We cannot pick free/freeable LEBs in the below code. -++ */ -++ pick_free = 0; -++ } else { -++ spin_lock(&c->space_lock); -++ exclude_index = (c->min_idx_lebs >= c->lst.idx_lebs); -++ spin_unlock(&c->space_lock); -++ } -++ -++ /* Look on the dirty and dirty index heaps */ -++ heap = &c->lpt_heap[LPROPS_DIRTY - 1]; -++ idx_heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1]; -++ -++ if (idx_heap->cnt && !exclude_index) { -++ idx_lp = idx_heap->arr[0]; -++ sum = idx_lp->free + idx_lp->dirty; -++ /* -++ * Since we reserve twice as more space for the index than it -++ * actually takes, it does not make sense to pick indexing LEBs -++ * with less than half LEB of dirty space. -++ */ -++ if (sum < min_space || sum < c->half_leb_size) -++ idx_lp = NULL; -++ } -++ -++ if (heap->cnt) { -++ lp = heap->arr[0]; -++ if (lp->dirty + lp->free < min_space) -++ lp = NULL; -++ } -++ -++ /* Pick the LEB with most space */ -++ if (idx_lp && lp) { -++ if (idx_lp->free + idx_lp->dirty >= lp->free + lp->dirty) -++ lp = idx_lp; -++ } else if (idx_lp && !lp) -++ lp = idx_lp; -++ -++ if (lp) { -++ ubifs_assert(lp->dirty >= c->dead_wm); -++ goto found; -++ } -++ -++ /* Did not find a dirty LEB on the dirty heaps, have to scan */ -++ dbg_find("scanning LPT for a dirty LEB"); -++ lp = scan_for_dirty(c, min_space, pick_free, exclude_index); -++ if (IS_ERR(lp)) { -++ err = PTR_ERR(lp); -++ goto out; -++ } -++ ubifs_assert(lp->dirty >= c->dead_wm); -++ -++found: -++ dbg_find("found LEB %d, free %d, dirty %d, flags %#x", -++ lp->lnum, lp->free, lp->dirty, lp->flags); -++ -++ lp = ubifs_change_lp(c, lp, -1, -1, lp->flags | LPROPS_TAKEN, 0); -++ if (IS_ERR(lp)) { -++ err = PTR_ERR(lp); -++ goto out; -++ } -++ -++ memcpy(ret_lp, lp, sizeof(struct ubifs_lprops)); -++ -++out: -++ ubifs_release_lprops(c); -++ return err; -++} -++ -++/** -++ * scan_for_free_cb - free space scan callback. -++ * @c: the UBIFS file-system description object -++ * @lprops: LEB properties to scan -++ * @in_tree: whether the LEB properties are in main memory -++ * @data: information passed to and from the caller of the scan -++ * -++ * This function returns a code that indicates whether the scan should continue -++ * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree -++ * in main memory (%LPT_SCAN_ADD), or whether the scan should stop -++ * (%LPT_SCAN_STOP). -++ */ -++static int scan_for_free_cb(struct ubifs_info *c, -++ const struct ubifs_lprops *lprops, int in_tree, -++ struct scan_data *data) -++{ -++ int ret = LPT_SCAN_CONTINUE; -++ -++ /* Exclude LEBs that are currently in use */ -++ if (lprops->flags & LPROPS_TAKEN) -++ return LPT_SCAN_CONTINUE; -++ /* Determine whether to add these LEB properties to the tree */ -++ if (!in_tree && valuable(c, lprops)) -++ ret |= LPT_SCAN_ADD; -++ /* Exclude index LEBs */ -++ if (lprops->flags & LPROPS_INDEX) -++ return ret; -++ /* Exclude LEBs with too little space */ -++ if (lprops->free < data->min_space) -++ return ret; -++ /* If specified, exclude empty LEBs */ -++ if (!data->pick_free && lprops->free == c->leb_size) -++ return ret; -++ /* -++ * LEBs that have only free and dirty space must not be allocated -++ * because they may have been unmapped already or they may have data -++ * that is obsolete only because of nodes that are still sitting in a -++ * wbuf. -++ */ -++ if (lprops->free + lprops->dirty == c->leb_size && lprops->dirty > 0) -++ return ret; -++ /* Finally we found space */ -++ data->lnum = lprops->lnum; -++ return LPT_SCAN_ADD | LPT_SCAN_STOP; -++} -++ -++/** -++ * do_find_free_space - find a data LEB with free space. -++ * @c: the UBIFS file-system description object -++ * @min_space: minimum amount of free space required -++ * @pick_free: whether it is OK to scan for empty LEBs -++ * @squeeze: whether to try to find space in a non-empty LEB first -++ * -++ * This function returns a pointer to the LEB properties found or a negative -++ * error code. -++ */ -++static -++const struct ubifs_lprops *do_find_free_space(struct ubifs_info *c, -++ int min_space, int pick_free, -++ int squeeze) -++{ -++ const struct ubifs_lprops *lprops; -++ struct ubifs_lpt_heap *heap; -++ struct scan_data data; -++ int err, i; -++ -++ if (squeeze) { -++ lprops = ubifs_fast_find_free(c); -++ if (lprops && lprops->free >= min_space) -++ return lprops; -++ } -++ if (pick_free) { -++ lprops = ubifs_fast_find_empty(c); -++ if (lprops) -++ return lprops; -++ } -++ if (!squeeze) { -++ lprops = ubifs_fast_find_free(c); -++ if (lprops && lprops->free >= min_space) -++ return lprops; -++ } -++ /* There may be an LEB with enough free space on the dirty heap */ -++ heap = &c->lpt_heap[LPROPS_DIRTY - 1]; -++ for (i = 0; i < heap->cnt; i++) { -++ lprops = heap->arr[i]; -++ if (lprops->free >= min_space) -++ return lprops; -++ } -++ /* -++ * A LEB may have fallen off of the bottom of the free heap, and ended -++ * up as uncategorized even though it has enough free space for us now, -++ * so check the uncategorized list. N.B. neither empty nor freeable LEBs -++ * can end up as uncategorized because they are kept on lists not -++ * finite-sized heaps. -++ */ -++ list_for_each_entry(lprops, &c->uncat_list, list) { -++ if (lprops->flags & LPROPS_TAKEN) -++ continue; -++ if (lprops->flags & LPROPS_INDEX) -++ continue; -++ if (lprops->free >= min_space) -++ return lprops; -++ } -++ /* We have looked everywhere in main memory, now scan the flash */ -++ if (c->pnodes_have >= c->pnode_cnt) -++ /* All pnodes are in memory, so skip scan */ -++ return ERR_PTR(-ENOSPC); -++ data.min_space = min_space; -++ data.pick_free = pick_free; -++ data.lnum = -1; -++ err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum, -++ (ubifs_lpt_scan_callback)scan_for_free_cb, -++ &data); -++ if (err) -++ return ERR_PTR(err); -++ ubifs_assert(data.lnum >= c->main_first && data.lnum < c->leb_cnt); -++ c->lscan_lnum = data.lnum; -++ lprops = ubifs_lpt_lookup_dirty(c, data.lnum); -++ if (IS_ERR(lprops)) -++ return lprops; -++ ubifs_assert(lprops->lnum == data.lnum); -++ ubifs_assert(lprops->free >= min_space); -++ ubifs_assert(!(lprops->flags & LPROPS_TAKEN)); -++ ubifs_assert(!(lprops->flags & LPROPS_INDEX)); -++ return lprops; -++} -++ -++/** -++ * ubifs_find_free_space - find a data LEB with free space. -++ * @c: the UBIFS file-system description object -++ * @min_space: minimum amount of required free space -++ * @free: contains amount of free space in the LEB on exit -++ * @squeeze: whether to try to find space in a non-empty LEB first -++ * -++ * This function looks for an LEB with at least @min_space bytes of free space. -++ * It tries to find an empty LEB if possible. If no empty LEBs are available, -++ * this function searches for a non-empty data LEB. The returned LEB is marked -++ * as "taken". -++ * -++ * This function returns found LEB number in case of success, %-ENOSPC if it -++ * failed to find a LEB with @min_space bytes of free space and other a negative -++ * error codes in case of failure. -++ */ -++int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *free, -++ int squeeze) -++{ -++ const struct ubifs_lprops *lprops; -++ int lebs, rsvd_idx_lebs, pick_free = 0, err, lnum, flags; -++ -++ dbg_find("min_space %d", min_space); -++ ubifs_assert(min_space > 0 && min_space <= c->dark_wm); -++ -++ ubifs_get_lprops(c); -++ -++ /* Check if there are enough empty LEBs for commit */ -++ spin_lock(&c->space_lock); -++ if (c->min_idx_lebs > c->lst.idx_lebs) -++ rsvd_idx_lebs = c->min_idx_lebs - c->lst.idx_lebs; -++ else -++ rsvd_idx_lebs = 0; -++ lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - -++ c->lst.taken_empty_lebs; -++ ubifs_assert(lebs + c->lst.idx_lebs >= c->min_idx_lebs); -++ if (rsvd_idx_lebs < lebs) -++ /* -++ * OK to allocate an empty LEB, but we still don't want to go -++ * looking for one if there aren't any. -++ */ -++ if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) { -++ pick_free = 1; -++ /* -++ * Because we release the space lock, we must account -++ * for this allocation here. After the LEB properties -++ * flags have been updated, we subtract one. Note, the -++ * result of this is that lprops also decreases -++ * @taken_empty_lebs in 'ubifs_change_lp()', so it is -++ * off by one for a short period of time which may -++ * introduce a small disturbance to budgeting -++ * calculations, but this is harmless because at the -++ * worst case this would make the budgeting subsystem -++ * be more pessimistic than needed. -++ * -++ * Fundamentally, this is about serialization of the -++ * budgeting and lprops subsystems. We could make the -++ * @space_lock a mutex and avoid dropping it before -++ * calling 'ubifs_change_lp()', but mutex is more -++ * heavy-weight, and we want budgeting to be as fast as -++ * possible. -++ */ -++ c->lst.taken_empty_lebs += 1; -++ } -++ spin_unlock(&c->space_lock); -++ -++ lprops = do_find_free_space(c, min_space, pick_free, squeeze); -++ if (IS_ERR(lprops)) { -++ err = PTR_ERR(lprops); -++ goto out; -++ } -++ -++ lnum = lprops->lnum; -++ flags = lprops->flags | LPROPS_TAKEN; -++ -++ lprops = ubifs_change_lp(c, lprops, -1, -1, flags, 0); -++ if (IS_ERR(lprops)) { -++ err = PTR_ERR(lprops); -++ goto out; -++ } -++ -++ if (pick_free) { -++ spin_lock(&c->space_lock); -++ c->lst.taken_empty_lebs -= 1; -++ spin_unlock(&c->space_lock); -++ } -++ -++ *free = lprops->free; -++ ubifs_release_lprops(c); -++ -++ if (*free == c->leb_size) { -++ /* -++ * Ensure that empty LEBs have been unmapped. They may not have -++ * been, for example, because of an unclean unmount. Also -++ * LEBs that were freeable LEBs (free + dirty == leb_size) will -++ * not have been unmapped. -++ */ -++ err = ubifs_leb_unmap(c, lnum); -++ if (err) -++ return err; -++ } -++ -++ dbg_find("found LEB %d, free %d", lnum, *free); -++ ubifs_assert(*free >= min_space); -++ return lnum; -++ -++out: -++ if (pick_free) { -++ spin_lock(&c->space_lock); -++ c->lst.taken_empty_lebs -= 1; -++ spin_unlock(&c->space_lock); -++ } -++ ubifs_release_lprops(c); -++ return err; -++} -++ -++/** -++ * scan_for_idx_cb - callback used by the scan for a free LEB for the index. -++ * @c: the UBIFS file-system description object -++ * @lprops: LEB properties to scan -++ * @in_tree: whether the LEB properties are in main memory -++ * @data: information passed to and from the caller of the scan -++ * -++ * This function returns a code that indicates whether the scan should continue -++ * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree -++ * in main memory (%LPT_SCAN_ADD), or whether the scan should stop -++ * (%LPT_SCAN_STOP). -++ */ -++static int scan_for_idx_cb(struct ubifs_info *c, -++ const struct ubifs_lprops *lprops, int in_tree, -++ struct scan_data *data) -++{ -++ int ret = LPT_SCAN_CONTINUE; -++ -++ /* Exclude LEBs that are currently in use */ -++ if (lprops->flags & LPROPS_TAKEN) -++ return LPT_SCAN_CONTINUE; -++ /* Determine whether to add these LEB properties to the tree */ -++ if (!in_tree && valuable(c, lprops)) -++ ret |= LPT_SCAN_ADD; -++ /* Exclude index LEBS */ -++ if (lprops->flags & LPROPS_INDEX) -++ return ret; -++ /* Exclude LEBs that cannot be made empty */ -++ if (lprops->free + lprops->dirty != c->leb_size) -++ return ret; -++ /* -++ * We are allocating for the index so it is safe to allocate LEBs with -++ * only free and dirty space, because write buffers are sync'd at commit -++ * start. -++ */ -++ data->lnum = lprops->lnum; -++ return LPT_SCAN_ADD | LPT_SCAN_STOP; -++} -++ -++/** -++ * scan_for_leb_for_idx - scan for a free LEB for the index. -++ * @c: the UBIFS file-system description object -++ */ -++static const struct ubifs_lprops *scan_for_leb_for_idx(struct ubifs_info *c) -++{ -++ struct ubifs_lprops *lprops; -++ struct scan_data data; -++ int err; -++ -++ data.lnum = -1; -++ err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum, -++ (ubifs_lpt_scan_callback)scan_for_idx_cb, -++ &data); -++ if (err) -++ return ERR_PTR(err); -++ ubifs_assert(data.lnum >= c->main_first && data.lnum < c->leb_cnt); -++ c->lscan_lnum = data.lnum; -++ lprops = ubifs_lpt_lookup_dirty(c, data.lnum); -++ if (IS_ERR(lprops)) -++ return lprops; -++ ubifs_assert(lprops->lnum == data.lnum); -++ ubifs_assert(lprops->free + lprops->dirty == c->leb_size); -++ ubifs_assert(!(lprops->flags & LPROPS_TAKEN)); -++ ubifs_assert(!(lprops->flags & LPROPS_INDEX)); -++ return lprops; -++} -++ -++/** -++ * ubifs_find_free_leb_for_idx - find a free LEB for the index. -++ * @c: the UBIFS file-system description object -++ * -++ * This function looks for a free LEB and returns that LEB number. The returned -++ * LEB is marked as "taken", "index". -++ * -++ * Only empty LEBs are allocated. This is for two reasons. First, the commit -++ * calculates the number of LEBs to allocate based on the assumption that they -++ * will be empty. Secondly, free space at the end of an index LEB is not -++ * guaranteed to be empty because it may have been used by the in-the-gaps -++ * method prior to an unclean unmount. -++ * -++ * If no LEB is found %-ENOSPC is returned. For other failures another negative -++ * error code is returned. -++ */ -++int ubifs_find_free_leb_for_idx(struct ubifs_info *c) -++{ -++ const struct ubifs_lprops *lprops; -++ int lnum = -1, err, flags; -++ -++ ubifs_get_lprops(c); -++ -++ lprops = ubifs_fast_find_empty(c); -++ if (!lprops) { -++ lprops = ubifs_fast_find_freeable(c); -++ if (!lprops) { -++ ubifs_assert(c->freeable_cnt == 0); -++ if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) { -++ lprops = scan_for_leb_for_idx(c); -++ if (IS_ERR(lprops)) { -++ err = PTR_ERR(lprops); -++ goto out; -++ } -++ } -++ } -++ } -++ -++ if (!lprops) { -++ err = -ENOSPC; -++ goto out; -++ } -++ -++ lnum = lprops->lnum; -++ -++ dbg_find("found LEB %d, free %d, dirty %d, flags %#x", -++ lnum, lprops->free, lprops->dirty, lprops->flags); -++ -++ flags = lprops->flags | LPROPS_TAKEN | LPROPS_INDEX; -++ lprops = ubifs_change_lp(c, lprops, c->leb_size, 0, flags, 0); -++ if (IS_ERR(lprops)) { -++ err = PTR_ERR(lprops); -++ goto out; -++ } -++ -++ ubifs_release_lprops(c); -++ -++ /* -++ * Ensure that empty LEBs have been unmapped. They may not have been, -++ * for example, because of an unclean unmount. Also LEBs that were -++ * freeable LEBs (free + dirty == leb_size) will not have been unmapped. -++ */ -++ err = ubifs_leb_unmap(c, lnum); -++ if (err) { -++ ubifs_change_one_lp(c, lnum, -1, -1, 0, -++ LPROPS_TAKEN | LPROPS_INDEX, 0); -++ return err; -++ } -++ -++ return lnum; -++ -++out: -++ ubifs_release_lprops(c); -++ return err; -++} -++ -++static int cmp_dirty_idx(const struct ubifs_lprops **a, -++ const struct ubifs_lprops **b) -++{ -++ const struct ubifs_lprops *lpa = *a; -++ const struct ubifs_lprops *lpb = *b; -++ -++ return lpa->dirty + lpa->free - lpb->dirty - lpb->free; -++} -++ -++static void swap_dirty_idx(struct ubifs_lprops **a, struct ubifs_lprops **b, -++ int size) -++{ -++ struct ubifs_lprops *t = *a; -++ -++ *a = *b; -++ *b = t; -++} -++ -++/** -++ * ubifs_save_dirty_idx_lnums - save an array of the most dirty index LEB nos. -++ * @c: the UBIFS file-system description object -++ * -++ * This function is called each commit to create an array of LEB numbers of -++ * dirty index LEBs sorted in order of dirty and free space. This is used by -++ * the in-the-gaps method of TNC commit. -++ */ -++int ubifs_save_dirty_idx_lnums(struct ubifs_info *c) -++{ -++ int i; -++ -++ ubifs_get_lprops(c); -++ /* Copy the LPROPS_DIRTY_IDX heap */ -++ c->dirty_idx.cnt = c->lpt_heap[LPROPS_DIRTY_IDX - 1].cnt; -++ memcpy(c->dirty_idx.arr, c->lpt_heap[LPROPS_DIRTY_IDX - 1].arr, -++ sizeof(void *) * c->dirty_idx.cnt); -++ /* Sort it so that the dirtiest is now at the end */ -++ sort(c->dirty_idx.arr, c->dirty_idx.cnt, sizeof(void *), -++ (int (*)(const void *, const void *))cmp_dirty_idx, -++ (void (*)(void *, void *, int))swap_dirty_idx); -++ dbg_find("found %d dirty index LEBs", c->dirty_idx.cnt); -++ if (c->dirty_idx.cnt) -++ dbg_find("dirtiest index LEB is %d with dirty %d and free %d", -++ c->dirty_idx.arr[c->dirty_idx.cnt - 1]->lnum, -++ c->dirty_idx.arr[c->dirty_idx.cnt - 1]->dirty, -++ c->dirty_idx.arr[c->dirty_idx.cnt - 1]->free); -++ /* Replace the lprops pointers with LEB numbers */ -++ for (i = 0; i < c->dirty_idx.cnt; i++) -++ c->dirty_idx.arr[i] = (void *)(size_t)c->dirty_idx.arr[i]->lnum; -++ ubifs_release_lprops(c); -++ return 0; -++} -++ -++/** -++ * scan_dirty_idx_cb - callback used by the scan for a dirty index LEB. -++ * @c: the UBIFS file-system description object -++ * @lprops: LEB properties to scan -++ * @in_tree: whether the LEB properties are in main memory -++ * @data: information passed to and from the caller of the scan -++ * -++ * This function returns a code that indicates whether the scan should continue -++ * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree -++ * in main memory (%LPT_SCAN_ADD), or whether the scan should stop -++ * (%LPT_SCAN_STOP). -++ */ -++static int scan_dirty_idx_cb(struct ubifs_info *c, -++ const struct ubifs_lprops *lprops, int in_tree, -++ struct scan_data *data) -++{ -++ int ret = LPT_SCAN_CONTINUE; -++ -++ /* Exclude LEBs that are currently in use */ -++ if (lprops->flags & LPROPS_TAKEN) -++ return LPT_SCAN_CONTINUE; -++ /* Determine whether to add these LEB properties to the tree */ -++ if (!in_tree && valuable(c, lprops)) -++ ret |= LPT_SCAN_ADD; -++ /* Exclude non-index LEBs */ -++ if (!(lprops->flags & LPROPS_INDEX)) -++ return ret; -++ /* Exclude LEBs with too little space */ -++ if (lprops->free + lprops->dirty < c->min_idx_node_sz) -++ return ret; -++ /* Finally we found space */ -++ data->lnum = lprops->lnum; -++ return LPT_SCAN_ADD | LPT_SCAN_STOP; -++} -++ -++/** -++ * find_dirty_idx_leb - find a dirty index LEB. -++ * @c: the UBIFS file-system description object -++ * -++ * This function returns LEB number upon success and a negative error code upon -++ * failure. In particular, -ENOSPC is returned if a dirty index LEB is not -++ * found. -++ * -++ * Note that this function scans the entire LPT but it is called very rarely. -++ */ -++static int find_dirty_idx_leb(struct ubifs_info *c) -++{ -++ const struct ubifs_lprops *lprops; -++ struct ubifs_lpt_heap *heap; -++ struct scan_data data; -++ int err, i, ret; -++ -++ /* Check all structures in memory first */ -++ data.lnum = -1; -++ heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1]; -++ for (i = 0; i < heap->cnt; i++) { -++ lprops = heap->arr[i]; -++ ret = scan_dirty_idx_cb(c, lprops, 1, &data); -++ if (ret & LPT_SCAN_STOP) -++ goto found; -++ } -++ list_for_each_entry(lprops, &c->frdi_idx_list, list) { -++ ret = scan_dirty_idx_cb(c, lprops, 1, &data); -++ if (ret & LPT_SCAN_STOP) -++ goto found; -++ } -++ list_for_each_entry(lprops, &c->uncat_list, list) { -++ ret = scan_dirty_idx_cb(c, lprops, 1, &data); -++ if (ret & LPT_SCAN_STOP) -++ goto found; -++ } -++ if (c->pnodes_have >= c->pnode_cnt) -++ /* All pnodes are in memory, so skip scan */ -++ return -ENOSPC; -++ err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum, -++ (ubifs_lpt_scan_callback)scan_dirty_idx_cb, -++ &data); -++ if (err) -++ return err; -++found: -++ ubifs_assert(data.lnum >= c->main_first && data.lnum < c->leb_cnt); -++ c->lscan_lnum = data.lnum; -++ lprops = ubifs_lpt_lookup_dirty(c, data.lnum); -++ if (IS_ERR(lprops)) -++ return PTR_ERR(lprops); -++ ubifs_assert(lprops->lnum == data.lnum); -++ ubifs_assert(lprops->free + lprops->dirty >= c->min_idx_node_sz); -++ ubifs_assert(!(lprops->flags & LPROPS_TAKEN)); -++ ubifs_assert((lprops->flags & LPROPS_INDEX)); -++ -++ dbg_find("found dirty LEB %d, free %d, dirty %d, flags %#x", -++ lprops->lnum, lprops->free, lprops->dirty, lprops->flags); -++ -++ lprops = ubifs_change_lp(c, lprops, -1, -1, -++ lprops->flags | LPROPS_TAKEN, 0); -++ if (IS_ERR(lprops)) -++ return PTR_ERR(lprops); -++ -++ return lprops->lnum; -++} -++ -++/** -++ * get_idx_gc_leb - try to get a LEB number from trivial GC. -++ * @c: the UBIFS file-system description object -++ */ -++static int get_idx_gc_leb(struct ubifs_info *c) -++{ -++ const struct ubifs_lprops *lp; -++ int err, lnum; -++ -++ err = ubifs_get_idx_gc_leb(c); -++ if (err < 0) -++ return err; -++ lnum = err; -++ /* -++ * The LEB was due to be unmapped after the commit but -++ * it is needed now for this commit. -++ */ -++ lp = ubifs_lpt_lookup_dirty(c, lnum); -++ if (unlikely(IS_ERR(lp))) -++ return PTR_ERR(lp); -++ lp = ubifs_change_lp(c, lp, -1, -1, lp->flags | LPROPS_INDEX, -1); -++ if (unlikely(IS_ERR(lp))) -++ return PTR_ERR(lp); -++ dbg_find("LEB %d, dirty %d and free %d flags %#x", -++ lp->lnum, lp->dirty, lp->free, lp->flags); -++ return lnum; -++} -++ -++/** -++ * find_dirtiest_idx_leb - find dirtiest index LEB from dirtiest array. -++ * @c: the UBIFS file-system description object -++ */ -++static int find_dirtiest_idx_leb(struct ubifs_info *c) -++{ -++ const struct ubifs_lprops *lp; -++ int lnum; -++ -++ while (1) { -++ if (!c->dirty_idx.cnt) -++ return -ENOSPC; -++ /* The lprops pointers were replaced by LEB numbers */ -++ lnum = (size_t)c->dirty_idx.arr[--c->dirty_idx.cnt]; -++ lp = ubifs_lpt_lookup(c, lnum); -++ if (IS_ERR(lp)) -++ return PTR_ERR(lp); -++ if ((lp->flags & LPROPS_TAKEN) || !(lp->flags & LPROPS_INDEX)) -++ continue; -++ lp = ubifs_change_lp(c, lp, -1, -1, -++ lp->flags | LPROPS_TAKEN, 0); -++ if (IS_ERR(lp)) -++ return PTR_ERR(lp); -++ break; -++ } -++ dbg_find("LEB %d, dirty %d and free %d flags %#x", lp->lnum, lp->dirty, -++ lp->free, lp->flags); -++ ubifs_assert(lp->flags | LPROPS_TAKEN); -++ ubifs_assert(lp->flags | LPROPS_INDEX); -++ return lnum; -++} -++ -++/** -++ * ubifs_find_dirty_idx_leb - try to find dirtiest index LEB as at last commit. -++ * @c: the UBIFS file-system description object -++ * -++ * This function attempts to find an untaken index LEB with the most free and -++ * dirty space that can be used without overwriting index nodes that were in the -++ * last index committed. -++ */ -++int ubifs_find_dirty_idx_leb(struct ubifs_info *c) -++{ -++ int err; -++ -++ ubifs_get_lprops(c); -++ -++ /* -++ * We made an array of the dirtiest index LEB numbers as at the start of -++ * last commit. Try that array first. -++ */ -++ err = find_dirtiest_idx_leb(c); -++ -++ /* Next try scanning the entire LPT */ -++ if (err == -ENOSPC) -++ err = find_dirty_idx_leb(c); -++ -++ /* Finally take any index LEBs awaiting trivial GC */ -++ if (err == -ENOSPC) -++ err = get_idx_gc_leb(c); -++ -++ ubifs_release_lprops(c); -++ return err; -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/gc.c linux-2.6.24.7/fs/ubifs/gc.c -+--- linux-2.6.24.7.old/fs/ubifs/gc.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/gc.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,762 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Adrian Hunter -++ * Artem Bityutskiy (Битюцкий Ðртём) -++ */ -++ -++/* -++ * This file implements garbage collection. The procedure for garbage collection -++ * is different depending on whether a LEB as an index LEB (contains index -++ * nodes) or not. For non-index LEBs, garbage collection finds a LEB which -++ * contains a lot of dirty space (obsolete nodes), and copies the non-obsolete -++ * nodes to the journal, at which point the garbage-collected LEB is free to be -++ * reused. For index LEBs, garbage collection marks the non-obsolete index nodes -++ * dirty in the TNC, and after the next commit, the garbage-collected LEB is -++ * to be reused. Garbage collection will cause the number of dirty index nodes -++ * to grow, however sufficient space is reserved for the index to ensure the -++ * commit will never run out of space. -++ */ -++ -++#include -++#include "ubifs.h" -++ -++/* -++ * GC tries to optimize the way it fit nodes to available space, and it sorts -++ * nodes a little. The below constants are watermarks which define "large", -++ * "medium", and "small" nodes. -++ */ -++#define MEDIUM_NODE_WM (UBIFS_BLOCK_SIZE / 4) -++#define SMALL_NODE_WM UBIFS_MAX_DENT_NODE_SZ -++ -++/* -++ * GC may need to move more then one LEB to make progress. The below constants -++ * define "soft" and "hard" limits on the number of LEBs the garbage collector -++ * may move. -++ */ -++#define SOFT_LEBS_LIMIT 4 -++#define HARD_LEBS_LIMIT 32 -++ -++/** -++ * switch_gc_head - switch the garbage collection journal head. -++ * @c: UBIFS file-system description object -++ * @buf: buffer to write -++ * @len: length of the buffer to write -++ * @lnum: LEB number written is returned here -++ * @offs: offset written is returned here -++ * -++ * This function switch the GC head to the next LEB which is reserved in -++ * @c->gc_lnum. Returns %0 in case of success, %-EAGAIN if commit is required, -++ * and other negative error code in case of failures. -++ */ -++static int switch_gc_head(struct ubifs_info *c) -++{ -++ int err, gc_lnum = c->gc_lnum; -++ struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf; -++ -++ ubifs_assert(gc_lnum != -1); -++ dbg_gc("switch GC head from LEB %d:%d to LEB %d (waste %d bytes)", -++ wbuf->lnum, wbuf->offs + wbuf->used, gc_lnum, -++ c->leb_size - wbuf->offs - wbuf->used); -++ -++ err = ubifs_wbuf_sync_nolock(wbuf); -++ if (err) -++ return err; -++ -++ /* -++ * The GC write-buffer was synchronized, we may safely unmap -++ * 'c->gc_lnum'. -++ */ -++ err = ubifs_leb_unmap(c, gc_lnum); -++ if (err) -++ return err; -++ -++ err = ubifs_add_bud_to_log(c, GCHD, gc_lnum, 0); -++ if (err) -++ return err; -++ -++ c->gc_lnum = -1; -++ err = ubifs_wbuf_seek_nolock(wbuf, gc_lnum, 0, UBI_LONGTERM); -++ return err; -++} -++ -++/** -++ * move_nodes - move nodes. -++ * @c: UBIFS file-system description object -++ * @sleb: describes nodes to move -++ * -++ * This function moves valid nodes from data LEB described by @sleb to the GC -++ * journal head. The obsolete nodes are dropped. -++ * -++ * When moving nodes we have to deal with classical bin-packing problem: the -++ * space in the current GC journal head LEB and in @c->gc_lnum are the "bins", -++ * where the nodes in the @sleb->nodes list are the elements which should be -++ * fit optimally to the bins. This function uses the "first fit decreasing" -++ * strategy, although it does not really sort the nodes but just split them on -++ * 3 classes - large, medium, and small, so they are roughly sorted. -++ * -++ * This function returns zero in case of success, %-EAGAIN if commit is -++ * required, and other negative error codes in case of other failures. -++ */ -++static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb) -++{ -++ struct ubifs_scan_node *snod, *tmp; -++ struct list_head large, medium, small; -++ struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf; -++ int avail, err, min = INT_MAX; -++ -++ INIT_LIST_HEAD(&large); -++ INIT_LIST_HEAD(&medium); -++ INIT_LIST_HEAD(&small); -++ -++ list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) { -++ struct list_head *lst; -++ -++ ubifs_assert(snod->type != UBIFS_IDX_NODE); -++ ubifs_assert(snod->type != UBIFS_REF_NODE); -++ ubifs_assert(snod->type != UBIFS_CS_NODE); -++ -++ err = ubifs_tnc_has_node(c, &snod->key, 0, sleb->lnum, -++ snod->offs, 0); -++ if (err < 0) -++ goto out; -++ -++ lst = &snod->list; -++ list_del(lst); -++ if (!err) { -++ /* The node is obsolete, remove it from the list */ -++ kfree(snod); -++ continue; -++ } -++ -++ /* -++ * Sort the list of nodes so that large nodes go first, and -++ * small nodes go last. -++ */ -++ if (snod->len > MEDIUM_NODE_WM) -++ list_add(lst, &large); -++ else if (snod->len > SMALL_NODE_WM) -++ list_add(lst, &medium); -++ else -++ list_add(lst, &small); -++ -++ /* And find the smallest node */ -++ if (snod->len < min) -++ min = snod->len; -++ } -++ -++ /* -++ * Join the tree lists so that we'd have one roughly sorted list -++ * ('large' will be the head of the joined list). -++ */ -++ list_splice(&medium, large.prev); -++ list_splice(&small, large.prev); -++ -++ if (wbuf->lnum == -1) { -++ /* -++ * The GC journal head is not set, because it is the first GC -++ * invocation since mount. -++ */ -++ err = switch_gc_head(c); -++ if (err) -++ goto out; -++ } -++ -++ /* Write nodes to their new location. Use the first-fit strategy */ -++ while (1) { -++ avail = c->leb_size - wbuf->offs - wbuf->used; -++ list_for_each_entry_safe(snod, tmp, &large, list) { -++ int new_lnum, new_offs; -++ -++ if (avail < min) -++ break; -++ -++ if (snod->len > avail) -++ /* This node does not fit */ -++ continue; -++ -++ cond_resched(); -++ -++ new_lnum = wbuf->lnum; -++ new_offs = wbuf->offs + wbuf->used; -++ err = ubifs_wbuf_write_nolock(wbuf, snod->node, -++ snod->len); -++ -++ err = ubifs_tnc_replace(c, &snod->key, sleb->lnum, -++ snod->offs, new_lnum, new_offs, -++ snod->len); -++ if (err) -++ goto out; -++ -++ avail = c->leb_size - wbuf->offs - wbuf->used; -++ list_del(&snod->list); -++ kfree(snod); -++ } -++ -++ if (list_empty(&large)) -++ break; -++ -++ /* -++ * Waste the rest of the space in the LEB and switch to the -++ * next LEB. -++ */ -++ err = switch_gc_head(c); -++ if (err) -++ goto out; -++ } -++ -++ return 0; -++ -++out: -++ list_for_each_entry_safe(snod, tmp, &large, list) { -++ list_del(&snod->list); -++ kfree(snod); -++ } -++ return err; -++} -++ -++/** -++ * gc_sync_wbufs - sync write-buffers for GC. -++ * @c: UBIFS file-system description object -++ * -++ * We must guarantee that obsoleting nodes are on flash. Unfortunately they may -++ * be in a write-buffer instead. That is, a node could be written to a -++ * write-buffer, obsoleting another node in a LEB that is GC'd. If that LEB is -++ * erased before the write-buffer is sync'd and then there is an unclean -++ * unmount, then an existing node is lost. To avoid this, we sync all -++ * write-buffers. -++ * -++ * This function returns %0 on success or a negative error code on failure. -++ */ -++static int gc_sync_wbufs(struct ubifs_info *c) -++{ -++ int err, i; -++ -++ for (i = 0; i < c->jhead_cnt; i++) { -++ if (i == GCHD) -++ continue; -++ err = ubifs_wbuf_sync(&c->jheads[i].wbuf); -++ if (err) -++ return err; -++ } -++ return 0; -++} -++ -++/** -++ * ubifs_garbage_collect_leb - garbage-collect a logical eraseblock. -++ * @c: UBIFS file-system description object -++ * @lp: describes the LEB to garbage collect -++ * -++ * This function garbage-collects an LEB and returns one of the @LEB_FREED, -++ * @LEB_RETAINED, etc positive codes in case of success, %-EAGAIN if commit is -++ * required, and other negative error codes in case of failures. -++ */ -++int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) -++{ -++ struct ubifs_scan_leb *sleb; -++ struct ubifs_scan_node *snod; -++ struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf; -++ int err = 0, lnum = lp->lnum; -++ -++ ubifs_assert(c->gc_lnum != -1 || wbuf->offs + wbuf->used == 0 || -++ c->need_recovery); -++ ubifs_assert(c->gc_lnum != lnum); -++ ubifs_assert(wbuf->lnum != lnum); -++ -++ /* -++ * We scan the entire LEB even though we only really need to scan up to -++ * (c->leb_size - lp->free). -++ */ -++ sleb = ubifs_scan(c, lnum, 0, c->sbuf); -++ if (IS_ERR(sleb)) -++ return PTR_ERR(sleb); -++ -++ ubifs_assert(!list_empty(&sleb->nodes)); -++ snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list); -++ -++ if (snod->type == UBIFS_IDX_NODE) { -++ struct ubifs_gced_idx_leb *idx_gc; -++ -++ dbg_gc("indexing LEB %d (free %d, dirty %d)", -++ lnum, lp->free, lp->dirty); -++ list_for_each_entry(snod, &sleb->nodes, list) { -++ struct ubifs_idx_node *idx = snod->node; -++ int level = le16_to_cpu(idx->level); -++ -++ ubifs_assert(snod->type == UBIFS_IDX_NODE); -++ key_read(c, ubifs_idx_key(c, idx), &snod->key); -++ err = ubifs_dirty_idx_node(c, &snod->key, level, lnum, -++ snod->offs); -++ if (err) -++ goto out; -++ } -++ -++ idx_gc = kmalloc(sizeof(struct ubifs_gced_idx_leb), GFP_NOFS); -++ if (!idx_gc) { -++ err = -ENOMEM; -++ goto out; -++ } -++ -++ idx_gc->lnum = lnum; -++ idx_gc->unmap = 0; -++ list_add(&idx_gc->list, &c->idx_gc); -++ -++ /* -++ * Don't release the LEB until after the next commit, because -++ * it may contain date which is needed for recovery. So -++ * although we freed this LEB, it will become usable only after -++ * the commit. -++ */ -++ err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0, -++ LPROPS_INDEX, 1); -++ if (err) -++ goto out; -++ err = LEB_FREED_IDX; -++ } else { -++ dbg_gc("data LEB %d (free %d, dirty %d)", -++ lnum, lp->free, lp->dirty); -++ -++ err = move_nodes(c, sleb); -++ if (err) -++ goto out; -++ -++ err = gc_sync_wbufs(c); -++ if (err) -++ goto out; -++ -++ err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0, 0, 0); -++ if (err) -++ goto out; -++ -++ if (c->gc_lnum == -1) { -++ c->gc_lnum = lnum; -++ err = LEB_RETAINED; -++ } else { -++ err = ubifs_wbuf_sync_nolock(wbuf); -++ if (err) -++ goto out; -++ -++ err = ubifs_leb_unmap(c, lnum); -++ if (err) -++ goto out; -++ -++ err = LEB_FREED; -++ } -++ } -++ -++out: -++ ubifs_scan_destroy(sleb); -++ return err; -++} -++ -++/** -++ * ubifs_garbage_collect - UBIFS garbage collector. -++ * @c: UBIFS file-system description object -++ * @anyway: do GC even if there are free LEBs -++ * -++ * This function does out-of-place garbage collection. The return codes are: -++ * o positive LEB number if the LEB has been freed and may be used; -++ * o %-EAGAIN if the caller has to run commit; -++ * o %-ENOSPC if GC failed to make any progress; -++ * o other negative error codes in case of other errors. -++ * -++ * Garbage collector writes data to the journal when GC'ing data LEBs, and just -++ * marking indexing nodes dirty when GC'ing indexing LEBs. Thus, at some point -++ * commit may be required. But commit cannot be run from inside GC, because the -++ * caller might be holding the commit lock, so %-EAGAIN is returned instead; -++ * And this error code means that the caller has to run commit, and re-run GC -++ * if there is still no free space. -++ * -++ * There are many reasons why this function may return %-EAGAIN: -++ * o the log is full and there is no space to write an LEB reference for -++ * @c->gc_lnum; -++ * o the journal is too large and exceeds size limitations; -++ * o GC moved indexing LEBs, but they can be used only after the commit; -++ * o the shrinker fails to find clean znodes to free and requests the commit; -++ * o etc. -++ * -++ * Note, if the file-system is close to be full, this function may return -++ * %-EAGAIN infinitely, so the caller has to limit amount of re-invocations of -++ * the function. E.g., this happens if the limits on the journal size are too -++ * tough and GC writes too much to the journal before an LEB is freed. This -++ * might also mean that the journal is too large, and the TNC becomes to big, -++ * so that the shrinker is constantly called, finds not clean znodes to free, -++ * and requests commit. Well, this may also happen if the journal is all right, -++ * but another kernel process consumes too much memory. Anyway, infinite -++ * %-EAGAIN may happen, but in some extreme/misconfiguration cases. -++ */ -++int ubifs_garbage_collect(struct ubifs_info *c, int anyway) -++{ -++ int i, err, ret, min_space = c->dead_wm; -++ struct ubifs_lprops lp; -++ struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf; -++ -++ ubifs_assert_cmt_locked(c); -++ -++ if (ubifs_gc_should_commit(c)) -++ return -EAGAIN; -++ -++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); -++ /* We expect the write-buffer to be empty on entry */ -++ ubifs_assert(!wbuf->used); -++ -++ for (i = 0; ; i++) { -++ int space_before = c->leb_size - wbuf->offs - wbuf->used; -++ int space_after; -++ -++ cond_resched(); -++ -++ /* Give the commit an opportunity to run */ -++ if (ubifs_gc_should_commit(c)) { -++ ret = -EAGAIN; -++ break; -++ } -++ -++ if (i > SOFT_LEBS_LIMIT && !list_empty(&c->idx_gc)) { -++ /* -++ * We've done enough iterations. Indexing LEBs were -++ * moved and will be available after the commit. -++ */ -++ dbg_gc("soft limit, some index LEBs GC'ed, -EAGAIN"); -++ ubifs_commit_required(c); -++ ret = -EAGAIN; -++ break; -++ } -++ -++ if (i > HARD_LEBS_LIMIT) { -++ /* -++ * We've moved too many LEBs and have not made -++ * progress, give up. -++ */ -++ dbg_gc("hard limit, -ENOSPC"); -++ ret = -ENOSPC; -++ break; -++ } -++ -++ /* -++ * Empty and freeable LEBs can turn up while we waited for -++ * the wbuf lock, or while we have been running GC. In that -++ * case, we should just return one of those instead of -++ * continuing to GC dirty LEBs. Hence we request -++ * 'ubifs_find_dirty_leb()' to return an empty LEB if it can. -++ */ -++ ret = ubifs_find_dirty_leb(c, &lp, min_space, anyway ? 0 : 1); -++ if (ret) { -++ if (ret == -ENOSPC) -++ dbg_gc("no more dirty LEBs"); -++ break; -++ } -++ -++ dbg_gc("found LEB %d: free %d, dirty %d, sum %d " -++ "(min. space %d)", lp.lnum, lp.free, lp.dirty, -++ lp.free + lp.dirty, min_space); -++ -++ if (lp.free + lp.dirty == c->leb_size) { -++ /* An empty LEB was returned */ -++ dbg_gc("LEB %d is free, return it", lp.lnum); -++ /* -++ * ubifs_find_dirty_leb() doesn't return freeable index -++ * LEBs. -++ */ -++ ubifs_assert(!(lp.flags & LPROPS_INDEX)); -++ if (lp.free != c->leb_size) { -++ /* -++ * Write buffers must be sync'd before -++ * unmapping freeable LEBs, because one of them -++ * may contain data which obsoletes something -++ * in 'lp.pnum'. -++ */ -++ ret = gc_sync_wbufs(c); -++ if (ret) -++ goto out; -++ ret = ubifs_change_one_lp(c, lp.lnum, -++ c->leb_size, 0, 0, 0, -++ 0); -++ if (ret) -++ goto out; -++ } -++ ret = ubifs_leb_unmap(c, lp.lnum); -++ if (ret) -++ goto out; -++ ret = lp.lnum; -++ break; -++ } -++ -++ space_before = c->leb_size - wbuf->offs - wbuf->used; -++ if (wbuf->lnum == -1) -++ space_before = 0; -++ -++ ret = ubifs_garbage_collect_leb(c, &lp); -++ if (ret < 0) { -++ if (ret == -EAGAIN || ret == -ENOSPC) { -++ /* -++ * These codes are not errors, so we have to -++ * return the LEB to lprops. But if the -++ * 'ubifs_return_leb()' function fails, its -++ * failure code is propagated to the caller -++ * instead of the original '-EAGAIN' or -++ * '-ENOSPC'. -++ */ -++ err = ubifs_return_leb(c, lp.lnum); -++ if (err) -++ ret = err; -++ break; -++ } -++ goto out; -++ } -++ -++ if (ret == LEB_FREED) { -++ /* An LEB has been freed and is ready for use */ -++ dbg_gc("LEB %d freed, return", lp.lnum); -++ ret = lp.lnum; -++ break; -++ } -++ -++ if (ret == LEB_FREED_IDX) { -++ /* -++ * This was an indexing LEB and it cannot be -++ * immediately used. And instead of requesting the -++ * commit straight away, we try to garbage collect some -++ * more. -++ */ -++ dbg_gc("indexing LEB %d freed, continue", lp.lnum); -++ continue; -++ } -++ -++ ubifs_assert(ret == LEB_RETAINED); -++ space_after = c->leb_size - wbuf->offs - wbuf->used; -++ dbg_gc("LEB %d retained, freed %d bytes", lp.lnum, -++ space_after - space_before); -++ -++ if (space_after > space_before) { -++ /* GC makes progress, keep working */ -++ min_space >>= 1; -++ if (min_space < c->dead_wm) -++ min_space = c->dead_wm; -++ continue; -++ } -++ -++ dbg_gc("did not make progress"); -++ -++ /* -++ * GC moved an LEB bud have not done any progress. This means -++ * that the previous GC head LEB contained too few free space -++ * and the LEB which was GC'ed contained only large nodes which -++ * did not fit that space. -++ * -++ * We can do 2 things: -++ * 1. pick another LEB in a hope it'll contain a small node -++ * which will fit the space we have at the end of current GC -++ * head LEB, but there is no guarantee, so we try this out -++ * unless we have already been working for too long; -++ * 2. request an LEB with more dirty space, which will force -++ * 'ubifs_find_dirty_leb()' to start scanning the lprops -++ * table, instead of just picking one from the heap -++ * (previously it already picked the dirtiest LEB). -++ */ -++ if (i < SOFT_LEBS_LIMIT) { -++ dbg_gc("try again"); -++ continue; -++ } -++ -++ min_space <<= 1; -++ if (min_space > c->dark_wm) -++ min_space = c->dark_wm; -++ dbg_gc("set min. space to %d", min_space); -++ } -++ -++ if (ret == -ENOSPC && !list_empty(&c->idx_gc)) { -++ dbg_gc("no space, some index LEBs GC'ed, -EAGAIN"); -++ ubifs_commit_required(c); -++ ret = -EAGAIN; -++ } -++ -++ err = ubifs_wbuf_sync_nolock(wbuf); -++ if (!err) -++ err = ubifs_leb_unmap(c, c->gc_lnum); -++ if (err) -++ ret = err; -++ mutex_unlock(&wbuf->io_mutex); -++ return ret; -++ -++out: -++ ubifs_assert(ret < 0); -++ ubifs_assert(ret != -ENOSPC && ret != -EAGAIN); -++ ubifs_wbuf_sync_nolock(wbuf); -++ mutex_unlock(&wbuf->io_mutex); -++ ubifs_return_leb(c, lp.lnum); -++ return ret; -++} -++ -++/** -++ * ubifs_gc_start_commit - garbage collection at start of commit. -++ * @c: UBIFS file-system description object -++ * -++ * If a LEB has only dirty and free space, then we may safely unmap it and make -++ * it free. Note, we cannot do this with indexing LEBs because dirty space may -++ * correspond index nodes that are required for recovery. In that case, the -++ * LEB cannot be unmapped until after the next commit. -++ * -++ * This function returns %0 upon success and a negative error code upon failure. -++ */ -++int ubifs_gc_start_commit(struct ubifs_info *c) -++{ -++ struct ubifs_gced_idx_leb *idx_gc; -++ const struct ubifs_lprops *lp; -++ int err = 0, flags; -++ -++ ubifs_get_lprops(c); -++ -++ /* -++ * Unmap (non-index) freeable LEBs. Note that recovery requires that all -++ * wbufs are sync'd before this, which is done in 'do_commit()'. -++ */ -++ while (1) { -++ lp = ubifs_fast_find_freeable(c); -++ if (unlikely(IS_ERR(lp))) { -++ err = PTR_ERR(lp); -++ goto out; -++ } -++ if (!lp) -++ break; -++ ubifs_assert(!(lp->flags & LPROPS_TAKEN)); -++ ubifs_assert(!(lp->flags & LPROPS_INDEX)); -++ err = ubifs_leb_unmap(c, lp->lnum); -++ if (err) -++ goto out; -++ lp = ubifs_change_lp(c, lp, c->leb_size, 0, lp->flags, 0); -++ if (unlikely(IS_ERR(lp))) { -++ err = PTR_ERR(lp); -++ goto out; -++ } -++ ubifs_assert(!(lp->flags & LPROPS_TAKEN)); -++ ubifs_assert(!(lp->flags & LPROPS_INDEX)); -++ } -++ -++ /* Mark GC'd index LEBs OK to unmap after this commit finishes */ -++ list_for_each_entry(idx_gc, &c->idx_gc, list) -++ idx_gc->unmap = 1; -++ -++ /* Record index freeable LEBs for unmapping after commit */ -++ while (1) { -++ lp = ubifs_fast_find_frdi_idx(c); -++ if (unlikely(IS_ERR(lp))) { -++ err = PTR_ERR(lp); -++ goto out; -++ } -++ if (!lp) -++ break; -++ idx_gc = kmalloc(sizeof(struct ubifs_gced_idx_leb), GFP_NOFS); -++ if (!idx_gc) { -++ err = -ENOMEM; -++ goto out; -++ } -++ ubifs_assert(!(lp->flags & LPROPS_TAKEN)); -++ ubifs_assert(lp->flags & LPROPS_INDEX); -++ /* Don't release the LEB until after the next commit */ -++ flags = (lp->flags | LPROPS_TAKEN) ^ LPROPS_INDEX; -++ lp = ubifs_change_lp(c, lp, c->leb_size, 0, flags, 1); -++ if (unlikely(IS_ERR(lp))) { -++ err = PTR_ERR(lp); -++ kfree(idx_gc); -++ goto out; -++ } -++ ubifs_assert(lp->flags & LPROPS_TAKEN); -++ ubifs_assert(!(lp->flags & LPROPS_INDEX)); -++ idx_gc->lnum = lp->lnum; -++ idx_gc->unmap = 1; -++ list_add(&idx_gc->list, &c->idx_gc); -++ } -++out: -++ ubifs_release_lprops(c); -++ return err; -++} -++ -++/** -++ * ubifs_gc_end_commit - garbage collection at end of commit. -++ * @c: UBIFS file-system description object -++ * -++ * This function completes out-of-place garbage collection of index LEBs. -++ */ -++int ubifs_gc_end_commit(struct ubifs_info *c) -++{ -++ struct ubifs_gced_idx_leb *idx_gc, *tmp; -++ struct ubifs_wbuf *wbuf; -++ int err = 0; -++ -++ wbuf = &c->jheads[GCHD].wbuf; -++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); -++ list_for_each_entry_safe(idx_gc, tmp, &c->idx_gc, list) -++ if (idx_gc->unmap) { -++ dbg_gc("LEB %d", idx_gc->lnum); -++ err = ubifs_leb_unmap(c, idx_gc->lnum); -++ if (err) -++ goto out; -++ err = ubifs_change_one_lp(c, idx_gc->lnum, -1, -1, 0, -++ LPROPS_TAKEN, -1); -++ if (err) -++ goto out; -++ list_del(&idx_gc->list); -++ kfree(idx_gc); -++ } -++out: -++ mutex_unlock(&wbuf->io_mutex); -++ return err; -++} -++ -++/** -++ * ubifs_destroy_idx_gc - destroy idx_gc list. -++ * @c: UBIFS file-system description object -++ * -++ * This function destroys the idx_gc list. It is called when unmounting or -++ * remounting read-only so locks are not needed. -++ */ -++void ubifs_destroy_idx_gc(struct ubifs_info *c) -++{ -++ while (!list_empty(&c->idx_gc)) { -++ struct ubifs_gced_idx_leb *idx_gc; -++ -++ idx_gc = list_entry(c->idx_gc.next, struct ubifs_gced_idx_leb, -++ list); -++ c->idx_gc_cnt -= 1; -++ list_del(&idx_gc->list); -++ kfree(idx_gc); -++ } -++ -++} -++ -++/** -++ * ubifs_get_idx_gc_leb - get a LEB from GC'd index LEB list. -++ * @c: UBIFS file-system description object -++ * -++ * Called during start commit so locks are not needed. -++ */ -++int ubifs_get_idx_gc_leb(struct ubifs_info *c) -++{ -++ struct ubifs_gced_idx_leb *idx_gc; -++ int lnum; -++ -++ if (list_empty(&c->idx_gc)) -++ return -ENOSPC; -++ idx_gc = list_entry(c->idx_gc.next, struct ubifs_gced_idx_leb, list); -++ lnum = idx_gc->lnum; -++ /* c->idx_gc_cnt is updated by the caller when lprops are updated */ -++ list_del(&idx_gc->list); -++ kfree(idx_gc); -++ return lnum; -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/io.c linux-2.6.24.7/fs/ubifs/io.c -+--- linux-2.6.24.7.old/fs/ubifs/io.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/io.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,921 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * Copyright (C) 2006, 2007 University of Szeged, Hungary -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ * Zoltan Sogor -++ */ -++ -++/* -++ * This file implements UBIFS I/O subsystem which provides various I/O-related -++ * helper functions (reading/writing/checking/validating nodes) and implements -++ * write-buffering support. Write buffers help to save space which otherwise -++ * would have been wasted for padding to the nearest minimal I/O unit boundary. -++ * Instead, data first goes to the write-buffer and is flushed when the -++ * buffer is full or when it is not used for some time (by timer). This is -++ * similarto the mechanism is used by JFFS2. -++ * -++ * Write-buffers are defined by 'struct ubifs_wbuf' objects and protected by -++ * mutexes defined inside these objects. Since sometimes upper-level code -++ * has to lock the write-buffer (e.g. journal space reservation code), many -++ * functions related to write-buffers have "nolock" suffix which means that the -++ * caller has to lock the write-buffer before calling this function. -++ * -++ * UBIFS stores nodes at 64 bit-aligned addresses. If the node length is not -++ * aligned, UBIFS starts the next node from the aligned address, and the padded -++ * bytes may contain any rubbish. In other words, UBIFS does not put padding -++ * bytes in those small gaps. Common headers of nodes store real node lengths, -++ * not aligned lengths. Indexing nodes also store real lengths in branches. -++ * -++ * UBIFS uses padding when it pads to the next min. I/O unit. In this case it -++ * uses padding nodes or padding bytes, if the padding node does not fit. -++ * -++ * All UBIFS nodes are protected by CRC checksums and UBIFS checks all nodes -++ * every time they are read from the flash media. -++ */ -++ -++#include -++#include "ubifs.h" -++ -++/** -++ * ubifs_check_node - check node. -++ * @c: UBIFS file-system description object -++ * @buf: node to check -++ * @lnum: logical eraseblock number -++ * @offs: offset within the logical eraseblock -++ * @quiet: print no messages -++ * -++ * This function checks node magic number and CRC checksum. This function also -++ * validates node length to prevent UBIFS from becoming crazy when an attacker -++ * feeds it a file-system image with incorrect nodes. For example, too large -++ * node length in the common header could cause UBIFS to read memory outside of -++ * allocated buffer when checking the CRC checksum. -++ * -++ * This function returns zero in case of success %-EUCLEAN in case of bad CRC -++ * or magic. -++ */ -++int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, -++ int offs, int quiet) -++{ -++ int err = -EINVAL, type, node_len; -++ uint32_t crc, node_crc, magic; -++ const struct ubifs_ch *ch = buf; -++ -++ ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0); -++ ubifs_assert(!(offs & 7) && offs < c->leb_size); -++ -++ magic = le32_to_cpu(ch->magic); -++ if (magic != UBIFS_NODE_MAGIC) { -++ if (!quiet) -++ ubifs_err("bad magic %#08x, expected %#08x", -++ magic, UBIFS_NODE_MAGIC); -++ err = -EUCLEAN; -++ goto out; -++ } -++ -++ type = ch->node_type; -++ if (type < 0 || type >= UBIFS_NODE_TYPES_CNT) { -++ if (!quiet) -++ ubifs_err("bad node type %d", type); -++ goto out; -++ } -++ -++ node_len = le32_to_cpu(ch->len); -++ if (node_len + offs > c->leb_size) -++ goto out_len; -++ -++ if (c->ranges[type].max_len == 0) { -++ if (node_len != c->ranges[type].len) -++ goto out_len; -++ } else if (node_len < c->ranges[type].min_len || -++ node_len > c->ranges[type].max_len) -++ goto out_len; -++ -++ crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); -++ node_crc = le32_to_cpu(ch->crc); -++ if (crc != node_crc) { -++ if (!quiet) -++ ubifs_err("bad CRC: calculated %#08x, read %#08x", -++ crc, node_crc); -++ err = -EUCLEAN; -++ goto out; -++ } -++ -++ return 0; -++ -++out_len: -++ if (!quiet) -++ ubifs_err("bad node length %d", node_len); -++out: -++ if (!quiet) { -++ ubifs_err("bad node at LEB %d:%d", lnum, offs); -++ dbg_dump_node(c, buf); -++ dbg_dump_stack(); -++ } -++ return err; -++} -++ -++/** -++ * ubifs_pad - pad flash space. -++ * @c: UBIFS file-system description object -++ * @buf: buffer to put padding to -++ * @pad: how many bytes to pad -++ * -++ * The flash media obliges us to write only in chunks of %c->min_io_size and -++ * when we have to write less data we add padding node to the write-buffer and -++ * pad it to the next minimal I/O unit's boundary. Padding nodes help when the -++ * media is being scanned. If the amount of wasted space is not enough to fit a -++ * padding node which takes %UBIFS_PAD_NODE_SZ bytes, we write padding bytes -++ * pattern (%UBIFS_PADDING_BYTE). -++ * -++ * Padding nodes are also used to fill gaps when the "commit-in-gaps" method is -++ * used. -++ */ -++void ubifs_pad(const struct ubifs_info *c, void *buf, int pad) -++{ -++ uint32_t crc; -++ -++ ubifs_assert(pad >= 0 && !(pad & 7)); -++ -++ if (pad >= UBIFS_PAD_NODE_SZ) { -++ struct ubifs_ch *ch = buf; -++ struct ubifs_pad_node *pad_node = buf; -++ -++ ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC); -++ ch->node_type = UBIFS_PAD_NODE; -++ ch->group_type = UBIFS_NO_NODE_GROUP; -++ ch->padding[0] = ch->padding[1] = 0; -++ ch->sqnum = 0; -++ ch->len = cpu_to_le32(UBIFS_PAD_NODE_SZ); -++ pad -= UBIFS_PAD_NODE_SZ; -++ pad_node->pad_len = cpu_to_le32(pad); -++ crc = crc32(UBIFS_CRC32_INIT, buf + 8, UBIFS_PAD_NODE_SZ - 8); -++ ch->crc = cpu_to_le32(crc); -++ memset(buf + UBIFS_PAD_NODE_SZ, 0, pad); -++ } else if (pad > 0) -++ /* Too little space, padding node won't fit */ -++ memset(buf, UBIFS_PADDING_BYTE, pad); -++} -++ -++/** -++ * next_sqnum - get next sequence number. -++ * @c: UBIFS file-system description object -++ */ -++static unsigned long long next_sqnum(struct ubifs_info *c) -++{ -++ unsigned long long sqnum; -++ -++ spin_lock(&c->cnt_lock); -++ sqnum = ++c->max_sqnum; -++ spin_unlock(&c->cnt_lock); -++ -++ if (unlikely(sqnum >= SQNUM_WARN_WATERMARK)) { -++ if (sqnum >= SQNUM_WATERMARK) { -++ ubifs_err("sequence number overflow %llu, end of life", -++ sqnum); -++ ubifs_ro_mode(c, -EINVAL); -++ } -++ ubifs_warn("running out of sequence numbers, end of life soon"); -++ } -++ -++ return sqnum; -++} -++ -++/** -++ * ubifs_prepare_node - prepare node to be written to flash. -++ * @c: UBIFS file-system description object -++ * @node: the node to pad -++ * @len: node length -++ * @pad: if the buffer has to be padded -++ * -++ * This function prepares node at @node to be written to the media - it -++ * calculates node CRC, fills the common header, and adds proper padding up to -++ * the next minimum I/O unit if @pad is not zero. -++ */ -++void ubifs_prepare_node(struct ubifs_info *c, void *node, int len, int pad) -++{ -++ uint32_t crc; -++ struct ubifs_ch *ch = node; -++ unsigned long long sqnum = next_sqnum(c); -++ -++ ubifs_assert(len >= UBIFS_CH_SZ); -++ -++ ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC); -++ ch->len = cpu_to_le32(len); -++ ch->group_type = UBIFS_NO_NODE_GROUP; -++ ch->sqnum = cpu_to_le64(sqnum); -++ ch->padding[0] = ch->padding[1] = 0; -++ crc = crc32(UBIFS_CRC32_INIT, node + 8, len - 8); -++ ch->crc = cpu_to_le32(crc); -++ -++ if (pad) { -++ len = ALIGN(len, 8); -++ pad = ALIGN(len, c->min_io_size) - len; -++ ubifs_pad(c, node + len, pad); -++ } -++} -++ -++/** -++ * ubifs_prep_grp_node - prepare node of a group to be written to flash. -++ * @c: UBIFS file-system description object -++ * @node: the node to pad -++ * @len: node length -++ * @last: indicates the last node of the group -++ * -++ * This function prepares node at @node to be written to the media - it -++ * calculates node CRC and fills the common header. -++ */ -++void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last) -++{ -++ uint32_t crc; -++ struct ubifs_ch *ch = node; -++ unsigned long long sqnum = next_sqnum(c); -++ -++ ubifs_assert(len >= UBIFS_CH_SZ); -++ -++ ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC); -++ ch->len = cpu_to_le32(len); -++ if (last) -++ ch->group_type = UBIFS_LAST_OF_NODE_GROUP; -++ else -++ ch->group_type = UBIFS_IN_NODE_GROUP; -++ ch->sqnum = cpu_to_le64(sqnum); -++ ch->padding[0] = ch->padding[1] = 0; -++ crc = crc32(UBIFS_CRC32_INIT, node + 8, len - 8); -++ ch->crc = cpu_to_le32(crc); -++} -++ -++/** -++ * wbuf_timer_callback - write-buffer timer callback function. -++ * @data: timer data (write-buffer descriptor) -++ * -++ * This function is called when the write-buffer timer expires. -++ */ -++static void wbuf_timer_callback_nolock(unsigned long data) -++{ -++ struct ubifs_wbuf *wbuf = (struct ubifs_wbuf *)data; -++ -++ wbuf->need_sync = 1; -++ wbuf->c->need_wbuf_sync = 1; -++ ubifs_wake_up_bgt(wbuf->c); -++} -++ -++/** -++ * new_wbuf_timer - start new write-buffer timer. -++ * @wbuf: write-buffer descriptor -++ */ -++static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf) -++{ -++ ubifs_assert(!timer_pending(&wbuf->timer)); -++ -++ if (!wbuf->timeout) -++ return; -++ -++ wbuf->timer.expires = jiffies + wbuf->timeout; -++ add_timer(&wbuf->timer); -++} -++ -++/** -++ * cancel_wbuf_timer - cancel write-buffer timer. -++ * @wbuf: write-buffer descriptor -++ */ -++static void cancel_wbuf_timer_nolock(struct ubifs_wbuf *wbuf) -++{ -++ /* -++ * If the syncer is waiting for the lock (from the background thread's -++ * context) and another task is changing write-buffer then the syncing -++ * should be canceled. -++ */ -++ wbuf->need_sync = 0; -++ del_timer(&wbuf->timer); -++} -++ -++/** -++ * ubifs_wbuf_sync_nolock - synchronize write-buffer. -++ * @wbuf: write-buffer to synchronize -++ * -++ * This function synchronizes write-buffer @buf and returns zero in case of -++ * success or a negative error code in case of failure. -++ */ -++int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf) -++{ -++ struct ubifs_info *c = wbuf->c; -++ int err, dirt; -++ -++ cancel_wbuf_timer_nolock(wbuf); -++ if (!wbuf->used || wbuf->lnum == -1) -++ /* Write-buffer is empty or not seeked */ -++ return 0; -++ -++ dbg_io("LEB %d:%d, %d bytes", -++ wbuf->lnum, wbuf->offs, wbuf->used); -++ ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY)); -++ ubifs_assert(!(wbuf->avail & 7)); -++ ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size); -++ -++ if (c->ro_media) -++ return -EROFS; -++ -++ ubifs_pad(c, wbuf->buf + wbuf->used, wbuf->avail); -++ err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs, -++ c->min_io_size, wbuf->dtype); -++ if (err) { -++ ubifs_err("cannot write %d bytes to LEB %d:%d", -++ c->min_io_size, wbuf->lnum, wbuf->offs); -++ dbg_dump_stack(); -++ return err; -++ } -++ -++ dirt = wbuf->avail; -++ -++ spin_lock(&wbuf->lock); -++ wbuf->offs += c->min_io_size; -++ wbuf->avail = c->min_io_size; -++ wbuf->used = 0; -++ wbuf->next_ino = 0; -++ spin_unlock(&wbuf->lock); -++ -++ if (wbuf->sync_callback) -++ err = wbuf->sync_callback(c, wbuf->lnum, -++ c->leb_size - wbuf->offs, dirt); -++ return err; -++} -++ -++/** -++ * ubifs_wbuf_seek_nolock - seek write-buffer. -++ * @wbuf: write-buffer -++ * @lnum: logical eraseblock number to seek to -++ * @offs: logical eraseblock offset to seek to -++ * @dtype: data type -++ * -++ * This function targets the write buffer to logical eraseblock @lnum:@offs. -++ * The write-buffer is synchronized if it is not empty. Returns zero in case of -++ * success and a negative error code in case of failure. -++ */ -++int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs, -++ int dtype) -++{ -++ const struct ubifs_info *c = wbuf->c; -++ -++ dbg_io("LEB %d:%d", lnum, offs); -++ ubifs_assert(lnum >= 0 && lnum < c->leb_cnt); -++ ubifs_assert(offs >= 0 && offs <= c->leb_size); -++ ubifs_assert(offs % c->min_io_size == 0 && !(offs & 7)); -++ ubifs_assert(lnum != wbuf->lnum); -++ -++ if (wbuf->used > 0) { -++ int err = ubifs_wbuf_sync_nolock(wbuf); -++ -++ if (err) -++ return err; -++ } -++ -++ spin_lock(&wbuf->lock); -++ wbuf->lnum = lnum; -++ wbuf->offs = offs; -++ wbuf->avail = c->min_io_size; -++ wbuf->used = 0; -++ spin_unlock(&wbuf->lock); -++ wbuf->dtype = dtype; -++ -++ return 0; -++} -++ -++/** -++ * ubifs_bg_wbufs_sync - synchronize write-buffers. -++ * @c: UBIFS file-system description object -++ * -++ * This function is called by background thread to synchronize write-buffers. -++ * Returns zero in case of success and a negative error code in case of -++ * failure. -++ */ -++int ubifs_bg_wbufs_sync(struct ubifs_info *c) -++{ -++ int err, i; -++ -++ if (!c->need_wbuf_sync) -++ return 0; -++ c->need_wbuf_sync = 0; -++ -++ if (c->ro_media) { -++ err = -EROFS; -++ goto out_timers; -++ } -++ -++ dbg_io("synchronize"); -++ for (i = 0; i < c->jhead_cnt; i++) { -++ struct ubifs_wbuf *wbuf = &c->jheads[i].wbuf; -++ -++ cond_resched(); -++ -++ /* -++ * If the mutex is locked then wbuf is being changed, so -++ * synchronization is not necessary. -++ */ -++ if (mutex_is_locked(&wbuf->io_mutex)) -++ continue; -++ -++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); -++ if (!wbuf->need_sync) { -++ mutex_unlock(&wbuf->io_mutex); -++ continue; -++ } -++ -++ err = ubifs_wbuf_sync_nolock(wbuf); -++ mutex_unlock(&wbuf->io_mutex); -++ if (err) { -++ ubifs_err("cannot sync write-buffer, error %d", err); -++ ubifs_ro_mode(c, err); -++ goto out_timers; -++ } -++ } -++ -++ return 0; -++ -++out_timers: -++ /* Cancel all timers to prevent repeated errors */ -++ for (i = 0; i < c->jhead_cnt; i++) { -++ struct ubifs_wbuf *wbuf = &c->jheads[i].wbuf; -++ -++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); -++ cancel_wbuf_timer_nolock(wbuf); -++ mutex_unlock(&wbuf->io_mutex); -++ } -++ return err; -++} -++ -++/** -++ * ubifs_wbuf_write_nolock - write data to flash via write-buffer. -++ * @wbuf: write-buffer -++ * @buf: node to write -++ * @len: node length -++ * -++ * This function writes data to flash via write-buffer @wbuf. This means that -++ * the last piece of the node won't reach the flash media immediately if it -++ * does not take whole minimal I/O unit. Instead, the node will sit in RAM -++ * until the write-buffer is synchronized (e.g., by timer). -++ * -++ * This function returns zero in case of success and a negative error code in -++ * case of failure. If the node cannot be written because there is no more -++ * space in this logical eraseblock, %-ENOSPC is returned. -++ */ -++int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) -++{ -++ struct ubifs_info *c = wbuf->c; -++ int err, written, n, aligned_len = ALIGN(len, 8), offs; -++ -++ dbg_io("%d bytes (%s) to wbuf at LEB %d:%d", len, -++ dbg_ntype(((struct ubifs_ch *)buf)->node_type), wbuf->lnum, -++ wbuf->offs + wbuf->used); -++ ubifs_assert(len > 0 && wbuf->lnum >= 0 && wbuf->lnum < c->leb_cnt); -++ ubifs_assert(wbuf->offs >= 0 && wbuf->offs % c->min_io_size == 0); -++ ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size); -++ ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size); -++ ubifs_assert(mutex_is_locked(&wbuf->io_mutex)); -++ -++ if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) { -++ err = -ENOSPC; -++ goto out; -++ } -++ -++ cancel_wbuf_timer_nolock(wbuf); -++ -++ if (c->ro_media) -++ return -EROFS; -++ -++ if (aligned_len <= wbuf->avail) { -++ /* -++ * The node is not very large and fits entirely within -++ * write-buffer. -++ */ -++ memcpy(wbuf->buf + wbuf->used, buf, len); -++ -++ if (aligned_len == wbuf->avail) { -++ dbg_io("flush wbuf to LEB %d:%d", wbuf->lnum, -++ wbuf->offs); -++ err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, -++ wbuf->offs, c->min_io_size, -++ wbuf->dtype); -++ if (err) -++ goto out; -++ -++ spin_lock(&wbuf->lock); -++ wbuf->offs += c->min_io_size; -++ wbuf->avail = c->min_io_size; -++ wbuf->used = 0; -++ wbuf->next_ino = 0; -++ spin_unlock(&wbuf->lock); -++ } else { -++ spin_lock(&wbuf->lock); -++ wbuf->avail -= aligned_len; -++ wbuf->used += aligned_len; -++ spin_unlock(&wbuf->lock); -++ } -++ -++ goto exit; -++ } -++ -++ /* -++ * The node is large enough and does not fit entirely within current -++ * minimal I/O unit. We have to fill and flush write-buffer and switch -++ * to the next min. I/O unit. -++ */ -++ dbg_io("flush wbuf to LEB %d:%d", wbuf->lnum, wbuf->offs); -++ memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail); -++ err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs, -++ c->min_io_size, wbuf->dtype); -++ if (err) -++ goto out; -++ -++ offs = wbuf->offs + c->min_io_size; -++ len -= wbuf->avail; -++ aligned_len -= wbuf->avail; -++ written = wbuf->avail; -++ -++ /* -++ * The remaining data may take more whole min. I/O units, so write the -++ * remains multiple to min. I/O unit size directly to the flash media. -++ * We align node length to 8-byte boundary because we anyway flash wbuf -++ * if the remaining space is less than 8 bytes. -++ */ -++ n = aligned_len >> c->min_io_shift; -++ if (n) { -++ n <<= c->min_io_shift; -++ dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum, offs); -++ err = ubi_leb_write(c->ubi, wbuf->lnum, buf + written, offs, n, -++ wbuf->dtype); -++ if (err) -++ goto out; -++ offs += n; -++ aligned_len -= n; -++ len -= n; -++ written += n; -++ } -++ -++ spin_lock(&wbuf->lock); -++ if (aligned_len) -++ /* -++ * And now we have what's left and what does not take whole -++ * min. I/O unit, so write it to the write-buffer and we are -++ * done. -++ */ -++ memcpy(wbuf->buf, buf + written, len); -++ -++ wbuf->offs = offs; -++ wbuf->used = aligned_len; -++ wbuf->avail = c->min_io_size - aligned_len; -++ wbuf->next_ino = 0; -++ spin_unlock(&wbuf->lock); -++ -++exit: -++ if (wbuf->sync_callback) { -++ int free = c->leb_size - wbuf->offs - wbuf->used; -++ -++ err = wbuf->sync_callback(c, wbuf->lnum, free, 0); -++ if (err) -++ goto out; -++ } -++ -++ if (wbuf->used) -++ new_wbuf_timer_nolock(wbuf); -++ -++ return 0; -++ -++out: -++ ubifs_err("cannot write %d bytes to LEB %d:%d, error %d", -++ len, wbuf->lnum, wbuf->offs, err); -++ dbg_dump_node(c, buf); -++ dbg_dump_stack(); -++ dbg_dump_leb(c, wbuf->lnum); -++ return err; -++} -++ -++/** -++ * ubifs_write_node - write node to the media. -++ * @c: UBIFS file-system description object -++ * @buf: the node to write -++ * @len: node length -++ * @lnum: logical eraseblock number -++ * @offs: offset within the logical eraseblock -++ * @dtype: node life-time hint (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN) -++ * -++ * This function automatically fills node magic number, assigns sequence -++ * number, and calculates node CRC checksum. The length of the @buf buffer has -++ * to be aligned to the minimal I/O unit size. This function automatically -++ * appends padding node and padding bytes if needed. Returns zero in case of -++ * success and a negative error code in case of failure. -++ */ -++int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum, -++ int offs, int dtype) -++{ -++ int err, buf_len = ALIGN(len, c->min_io_size); -++ -++ dbg_io("LEB %d:%d, %s, length %d (aligned %d)", -++ lnum, offs, dbg_ntype(((struct ubifs_ch *)buf)->node_type), len, -++ buf_len); -++ ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0); -++ ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size); -++ -++ if (c->ro_media) -++ return -EROFS; -++ -++ ubifs_prepare_node(c, buf, len, 1); -++ err = ubi_leb_write(c->ubi, lnum, buf, offs, buf_len, dtype); -++ if (err) { -++ ubifs_err("cannot write %d bytes to LEB %d:%d, error %d", -++ buf_len, lnum, offs, err); -++ dbg_dump_node(c, buf); -++ dbg_dump_stack(); -++ } -++ -++ return err; -++} -++ -++/** -++ * ubifs_read_node_wbuf - read node from the media or write-buffer. -++ * @wbuf: wbuf to check for un-written data -++ * @buf: buffer to read to -++ * @type: node type -++ * @len: node length -++ * @lnum: logical eraseblock number -++ * @offs: offset within the logical eraseblock -++ * -++ * This function reads a node of known type and length, checks it and stores -++ * in @buf. If the node partially or fully sits in the write-buffer, this -++ * function takes data from the buffer, otherwise it reads the flash media. -++ * Returns zero in case of success, %-EUCLEAN if CRC mismatched and a negative -++ * error code in case of failure. -++ */ -++int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len, -++ int lnum, int offs) -++{ -++ const struct ubifs_info *c = wbuf->c; -++ int err, rlen, overlap; -++ struct ubifs_ch *ch = buf; -++ -++ dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len); -++ ubifs_assert(wbuf && lnum >= 0 && lnum < c->leb_cnt && offs >= 0); -++ ubifs_assert(!(offs & 7) && offs < c->leb_size); -++ ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT); -++ -++ spin_lock(&wbuf->lock); -++ overlap = (lnum == wbuf->lnum && offs + len > wbuf->offs); -++ if (!overlap) { -++ /* We may safely unlock the write-buffer and read the data */ -++ spin_unlock(&wbuf->lock); -++ return ubifs_read_node(c, buf, type, len, lnum, offs); -++ } -++ -++ /* Don't read under wbuf */ -++ rlen = wbuf->offs - offs; -++ if (rlen < 0) -++ rlen = 0; -++ -++ /* Copy the rest from the write-buffer */ -++ memcpy(buf + rlen, wbuf->buf + offs + rlen - wbuf->offs, len - rlen); -++ spin_unlock(&wbuf->lock); -++ -++ if (rlen > 0) { -++ /* Read everything that goes before write-buffer */ -++ err = ubi_read(c->ubi, lnum, buf, offs, rlen); -++ if (err && err != -EBADMSG) { -++ ubifs_err("failed to read node %d from LEB %d:%d, " -++ "error %d", type, lnum, offs, err); -++ dbg_dump_stack(); -++ return err; -++ } -++ } -++ -++ err = ubifs_check_node(c, buf, lnum, offs, 0); -++ if (err) { -++ ubifs_err("expected node type %d", type); -++ return err; -++ } -++ -++ if (type != ch->node_type) { -++ ubifs_err("bad node type (%d but expected %d)", -++ ch->node_type, type); -++ goto out; -++ } -++ -++ rlen = le32_to_cpu(ch->len); -++ if (rlen != len) { -++ ubifs_err("bad node length %d, expected %d", rlen, len); -++ goto out; -++ } -++ -++ return 0; -++ -++out: -++ ubifs_err("bad node at LEB %d:%d", lnum, offs); -++ dbg_dump_node(c, buf); -++ dbg_dump_stack(); -++ return -EINVAL; -++} -++ -++/** -++ * ubifs_read_node - read node. -++ * @c: UBIFS file-system description object -++ * @buf: buffer to read to -++ * @type: node type -++ * @len: node length (not aligned) -++ * @lnum: logical eraseblock number -++ * @offs: offset within the logical eraseblock -++ * -++ * This function reads a node of known type and and length, checks it and -++ * stores in @buf. Returns zero in case of success, %-EUCLEAN if CRC mismatched -++ * and a negative error code in case of failure. -++ */ -++int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len, -++ int lnum, int offs) -++{ -++ int err, l; -++ struct ubifs_ch *ch = buf; -++ -++ dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len); -++ ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0); -++ ubifs_assert(len >= UBIFS_CH_SZ && offs + len <= c->leb_size); -++ ubifs_assert(!(offs & 7) && offs < c->leb_size); -++ ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT); -++ -++ err = ubi_read(c->ubi, lnum, buf, offs, len); -++ if (err && err != -EBADMSG) { -++ ubifs_err("cannot read node %d from LEB %d:%d, error %d", -++ type, lnum, offs, err); -++ return err; -++ } -++ -++ err = ubifs_check_node(c, buf, lnum, offs, 0); -++ if (err) { -++ ubifs_err("expected node type %d", type); -++ return err; -++ } -++ -++ if (type != ch->node_type) { -++ ubifs_err("bad node type (%d but expected %d)", -++ ch->node_type, type); -++ goto out; -++ } -++ -++ l = le32_to_cpu(ch->len); -++ if (l != len) { -++ ubifs_err("bad node length %d, expected %d", l, len); -++ goto out; -++ } -++ -++ return 0; -++ -++out: -++ ubifs_err("bad node at LEB %d:%d", lnum, offs); -++ dbg_dump_node(c, buf); -++ dbg_dump_stack(); -++ return -EINVAL; -++} -++ -++/** -++ * ubifs_wbuf_init - initialize write-buffer. -++ * @c: UBIFS file-system description object -++ * @wbuf: write-buffer to initialize -++ * -++ * This function initializes write buffer. Returns zero in case of success -++ * %-ENOMEM in case of failure. -++ */ -++int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf) -++{ -++ size_t size; -++ -++ wbuf->buf = kmalloc(c->min_io_size, GFP_KERNEL); -++ if (!wbuf->buf) -++ return -ENOMEM; -++ -++ size = (c->min_io_size / UBIFS_CH_SZ + 1) * sizeof(ino_t); -++ wbuf->inodes = kmalloc(size, GFP_KERNEL); -++ if (!wbuf->inodes) { -++ kfree(wbuf->buf); -++ wbuf->buf = NULL; -++ return -ENOMEM; -++ } -++ -++ wbuf->used = 0; -++ wbuf->lnum = wbuf->offs = -1; -++ wbuf->avail = c->min_io_size; -++ wbuf->dtype = UBI_UNKNOWN; -++ wbuf->sync_callback = NULL; -++ mutex_init(&wbuf->io_mutex); -++ spin_lock_init(&wbuf->lock); -++ -++ wbuf->c = c; -++ init_timer(&wbuf->timer); -++ wbuf->timer.function = wbuf_timer_callback_nolock; -++ wbuf->timer.data = (unsigned long)wbuf; -++ wbuf->timeout = DEFAULT_WBUF_TIMEOUT; -++ wbuf->next_ino = 0; -++ -++ return 0; -++} -++ -++/** -++ * ubifs_wbuf_add_ino_nolock - add an inode number into the wbuf inode array. -++ * @wbuf: the write-buffer whereto add -++ * @inum: the inode number -++ * -++ * This function adds an inode number to the inode array of the write-buffer. -++ */ -++void ubifs_wbuf_add_ino_nolock(struct ubifs_wbuf *wbuf, ino_t inum) -++{ -++ if (!wbuf->buf) -++ /* NOR flash or something similar */ -++ return; -++ -++ spin_lock(&wbuf->lock); -++ if (wbuf->used) -++ wbuf->inodes[wbuf->next_ino++] = inum; -++ spin_unlock(&wbuf->lock); -++} -++ -++/** -++ * wbuf_has_ino - returns if the wbuf contains data from the inode. -++ * @wbuf: the write-buffer -++ * @inum: the inode number -++ * -++ * This function returns with %1 if the write-buffer contains some data from the -++ * given inode otherwise it returns with %0. -++ */ -++static int wbuf_has_ino(struct ubifs_wbuf *wbuf, ino_t inum) -++{ -++ int i, ret = 0; -++ -++ spin_lock(&wbuf->lock); -++ for (i = 0; i < wbuf->next_ino; i++) -++ if (inum == wbuf->inodes[i]) { -++ ret = 1; -++ break; -++ } -++ spin_unlock(&wbuf->lock); -++ -++ return ret; -++} -++ -++/** -++ * ubifs_sync_wbufs_by_inodes - synchronize write-buffers which have data. -++ * belonging to specified inodes. -++ * @c: UBIFS file-system description object -++ * @inodes: array of inodes -++ * @count: number of elements in @inodes -++ * -++ * This function synchronizes write-buffers which contain nodes belonging to -++ * any inode specified in @inodes array. Returns zero in case of success and a -++ * negative error code in case of failure. -++ */ -++int ubifs_sync_wbufs_by_inodes(struct ubifs_info *c, -++ struct inode * const *inodes, int count) -++{ -++ int i, j, err = 0; -++ -++ ubifs_assert(count); -++ -++ for (i = 0; i < c->jhead_cnt; i++) { -++ struct ubifs_wbuf *wbuf = &c->jheads[i].wbuf; -++ -++ if (i == GCHD) -++ /* -++ * GC head is special, do not look at it. Even if the -++ * head contains something related to this inode, it is -++ * a _copy_ of corresponding on-flash node which sits -++ * somewhere else. -++ */ -++ continue; -++ -++ for (j = 0; j < count && !err; j++) -++ if (wbuf_has_ino(wbuf, inodes[j]->i_ino)) { -++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); -++ if (wbuf_has_ino(wbuf, inodes[j]->i_ino)) -++ err = ubifs_wbuf_sync_nolock(wbuf); -++ mutex_unlock(&wbuf->io_mutex); -++ break; -++ } -++ -++ if (err) { -++ ubifs_ro_mode(c, err); -++ break; -++ } -++ } -++ -++ return err; -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/ioctl.c linux-2.6.24.7/fs/ubifs/ioctl.c -+--- linux-2.6.24.7.old/fs/ubifs/ioctl.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/ioctl.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,204 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * Copyright (C) 2006, 2007 University of Szeged, Hungary -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Zoltan Sogor -++ * Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* This file implements EXT2-compatible extended attribute ioctl() calls */ -++ -++#include -++#include -++#include "ubifs.h" -++ -++/** -++ * ubifs_set_inode_flags - set VFS inode flags. -++ * @inode: VFS inode to set flags for -++ * -++ * This function propagates flags from UBIFS inode object to VFS inode object. -++ */ -++void ubifs_set_inode_flags(struct inode *inode) -++{ -++ unsigned int flags = ubifs_inode(inode)->flags; -++ -++ inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_DIRSYNC); -++ if (flags & UBIFS_SYNC_FL) -++ inode->i_flags |= S_SYNC; -++ if (flags & UBIFS_APPEND_FL) -++ inode->i_flags |= S_APPEND; -++ if (flags & UBIFS_IMMUTABLE_FL) -++ inode->i_flags |= S_IMMUTABLE; -++ if (flags & UBIFS_DIRSYNC_FL) -++ inode->i_flags |= S_DIRSYNC; -++} -++ -++/* -++ * ioctl2ubifs - convert ioctl inode flags to UBIFS inode flags. -++ * @ioctl_flags: flags to convert -++ * -++ * This function convert ioctl flags (@FS_COMPR_FL, etc) to UBIFS inode flags -++ * (@UBIFS_COMPR_FL, etc). -++ */ -++static int ioctl2ubifs(int ioctl_flags) -++{ -++ int ubifs_flags = 0; -++ -++ if (ioctl_flags & FS_COMPR_FL) -++ ubifs_flags |= UBIFS_COMPR_FL; -++ if (ioctl_flags & FS_SYNC_FL) -++ ubifs_flags |= UBIFS_SYNC_FL; -++ if (ioctl_flags & FS_APPEND_FL) -++ ubifs_flags |= UBIFS_APPEND_FL; -++ if (ioctl_flags & FS_IMMUTABLE_FL) -++ ubifs_flags |= UBIFS_IMMUTABLE_FL; -++ if (ioctl_flags & FS_DIRSYNC_FL) -++ ubifs_flags |= UBIFS_DIRSYNC_FL; -++ -++ return ubifs_flags; -++} -++ -++/* -++ * ubifs2ioctl - convert UBIFS inode flags to ioctl inode flags. -++ * @ubifs_flags: flags to convert -++ * -++ * This function convert UBIFS (@UBIFS_COMPR_FL, etc) to ioctl flags -++ * (@FS_COMPR_FL, etc). -++ */ -++static int ubifs2ioctl(int ubifs_flags) -++{ -++ int ioctl_flags = 0; -++ -++ if (ubifs_flags & UBIFS_COMPR_FL) -++ ioctl_flags |= FS_COMPR_FL; -++ if (ubifs_flags & UBIFS_SYNC_FL) -++ ioctl_flags |= FS_SYNC_FL; -++ if (ubifs_flags & UBIFS_APPEND_FL) -++ ioctl_flags |= FS_APPEND_FL; -++ if (ubifs_flags & UBIFS_IMMUTABLE_FL) -++ ioctl_flags |= FS_IMMUTABLE_FL; -++ if (ubifs_flags & UBIFS_DIRSYNC_FL) -++ ioctl_flags |= FS_DIRSYNC_FL; -++ -++ return ioctl_flags; -++} -++ -++static int setflags(struct inode *inode, int flags) -++{ -++ struct ubifs_inode *ui = ubifs_inode(inode); -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ struct ubifs_budget_req req; -++ int oldflags, err; -++ -++ mutex_lock(&inode->i_mutex); -++ -++ memset(&req, 0 , sizeof(struct ubifs_budget_req)); -++ err = ubifs_budget_inode_op(c, inode, &req); -++ if (err) -++ goto out; -++ -++ /* -++ * The IMMUTABLE and APPEND_ONLY flags can only be changed by -++ * the relevant capability. -++ */ -++ oldflags = ubifs2ioctl(ui->flags); -++ if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) { -++ if (!capable(CAP_LINUX_IMMUTABLE)) { -++ err = -EPERM; -++ goto out_budg; -++ } -++ } -++ -++ ui->flags = ioctl2ubifs(flags); -++ ubifs_set_inode_flags(inode); -++ -++ inode->i_ctime = ubifs_current_time(inode); -++ mark_inode_dirty_sync(inode); -++ -++ ubifs_release_ino_dirty(c, inode, &req); -++ -++ if (IS_SYNC(inode)) -++ err = write_inode_now(inode, 1); -++ -++ mutex_unlock(&inode->i_mutex); -++ return err; -++ -++out_budg: -++ ubifs_cancel_ino_op(c, inode, &req); -++out: -++ ubifs_err("can't modify inode %lu attributes", inode->i_ino); -++ mutex_unlock(&inode->i_mutex); -++ return err; -++} -++ -++long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -++{ -++ int flags; -++ struct inode *inode = file->f_path.dentry->d_inode; -++ -++ switch (cmd) { -++ case FS_IOC_GETFLAGS: -++ flags = ubifs2ioctl(ubifs_inode(inode)->flags); -++ -++ return put_user(flags, (int __user *) arg); -++ -++ case FS_IOC_SETFLAGS: { -++ if (IS_RDONLY(inode)) -++ return -EROFS; -++ -++ if (!is_owner_or_cap(inode)) -++ return -EACCES; -++ -++ if (get_user(flags, (int __user *) arg)) -++ return -EFAULT; -++ -++ if (!S_ISDIR(inode->i_mode)) -++ flags &= ~FS_DIRSYNC_FL; -++ -++ return setflags(inode, flags); -++ } -++ -++ default: -++ return -ENOTTY; -++ } -++} -++ -++#ifdef CONFIG_COMPAT -++long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -++{ -++ int err; -++ -++ switch (cmd) { -++ case FS_IOC32_GETFLAGS: -++ cmd = FS_IOC_GETFLAGS; -++ break; -++ case FS_IOC32_SETFLAGS: -++ cmd = FS_IOC_SETFLAGS; -++ break; -++ default: -++ return -ENOIOCTLCMD; -++ } -++ -++ lock_kernel(); -++ err = ubifs_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); -++ unlock_kernel(); -++ -++ return err; -++} -++#endif -+diff -urN linux-2.6.24.7.old/fs/ubifs/journal.c linux-2.6.24.7/fs/ubifs/journal.c -+--- linux-2.6.24.7.old/fs/ubifs/journal.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/journal.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1275 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* -++ * This file implements UBIFS journal. -++ * -++ * The journal consists of 2 parts - the log and bud LEBs. The log has fixed -++ * length and position, while a bud logical eraseblock is any LEB in the main -++ * area. Buds contain file system data - data nodes, inode nodes, etc. The log -++ * contains only references to buds and some other stuff like commit -++ * start node. The idea is that when we commit the journal, we do -++ * not copy the data, the buds just become indexed. Since after the commit the -++ * nodes in bud eraseblocks become leaf nodes of the file system index tree, we -++ * use term "bud". Analogy is obvious, bud eraseblocks contain nodes which will -++ * become leafs in the future. -++ * -++ * The journal is multi-headed because we want to write data to the journal as -++ * optimally as possible. It is nice to have nodes belonging to the same inode -++ * in one LEB, so we may write data owned by different inodes to different -++ * journal heads, although at present only one data head is used. -++ * -++ * For recovery reasons, the base head contains all inode nodes, all directory -++ * entry nodes and all truncate nodes. This means that the other heads contain -++ * only data nodes. -++ * -++ * Bud LEBs may be half-indexed. For example, if the bud was not full at the -++ * time of commit, the bud is retained to continue to be used in the journal, -++ * even though the "front" of the LEB is now indexed. In that case, the log -++ * reference contains the offset where the bud starts for the purposes of the -++ * journal. -++ * -++ * The journal size has to be limited, because the larger is the journal, the -++ * longer it takes to mount UBIFS (scanning the journal) and the more memory it -++ * takes (indexing in the TNC). -++ * -++ * Note, all the journal write operations like 'ubifs_jnl_update()' here, which -++ * write multiple UBIFS nodes to the journal at one go, are atomic with respect -++ * to unclean reboots. Should the unclean reboot happen, the recovery code drops -++ * all the nodes. -++ */ -++ -++#include "ubifs.h" -++ -++/** -++ * zero_ino_node_unused - zero out unused fields of an on-flash inode node. -++ * @ino: the inode to zero out -++ */ -++static inline void zero_ino_node_unused(struct ubifs_ino_node *ino) -++{ -++ memset(ino->padding, 0, 26); -++} -++ -++/** -++ * zero_dent_node_unused - zero out unused fields of an on-flash directory -++ * entry node. -++ * @ino: the directory entry to zero out -++ */ -++static inline void zero_dent_node_unused(struct ubifs_dent_node *dent) -++{ -++ dent->padding1 = 0; -++ memset(dent->padding2, 0, 4); -++} -++ -++/** -++ * zero_data_node_unused - zero out unused fields of an on-flash data node. -++ * @ino: the data node to zero out -++ */ -++static inline void zero_data_node_unused(struct ubifs_data_node *data) -++{ -++ memset(data->padding, 0, 2); -++} -++ -++/** -++ * reserve_space - reserve space in the journal. -++ * @c: UBIFS file-system description object -++ * @jhead: journal head number -++ * @len: node length -++ * -++ * This function reserves space in journal head @head. If the reservation -++ * succeeded, the journal head stays locked and later has to be unlocked using -++ * 'release_head()'. 'write_node()' and 'write_head()' functions also unlock -++ * it. Returns zero in case of success, %-EAGAIN if commit has to be done, and -++ * other negative error codes in case of other failures. -++ */ -++static int reserve_space(struct ubifs_info *c, int jhead, int len) -++{ -++ int err = 0, err1, retries = 0, avail, lnum, offs, free, squeeze; -++ struct ubifs_wbuf *wbuf = &c->jheads[jhead].wbuf; -++ -++ /* -++ * Typically, the base head has smaller nodes written to it, so it is -++ * better to try to allocate space at the ends of eraseblocks. This is -++ * what the squeeze parameter does. -++ */ -++ squeeze = (jhead == BASEHD); -++again: -++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); -++ avail = c->leb_size - wbuf->offs - wbuf->used; -++ -++ if (wbuf->lnum != -1 && avail >= len) -++ return 0; -++ -++ /* -++ * Write buffer wasn't seek'ed or there is no enough space - look for an -++ * LEB with some empty space. -++ */ -++ lnum = ubifs_find_free_space(c, len, &free, squeeze); -++ if (lnum >= 0) { -++ /* Found an LEB, add it to the journal head */ -++ offs = c->leb_size - free; -++ err = ubifs_add_bud_to_log(c, jhead, lnum, offs); -++ if (err) -++ goto out_return; -++ /* A new bud was successfully allocated and added to the log */ -++ goto out; -++ } -++ -++ err = lnum; -++ if (err != -ENOSPC) -++ goto out_unlock; -++ -++ /* -++ * No free space, we have to run garbage collector to make -++ * some. But the write-buffer mutex has to be unlocked because -++ * GC have to sync write buffers, which may lead a deadlock. -++ */ -++ dbg_jnl("no free space jhead %d, run GC", jhead); -++ mutex_unlock(&wbuf->io_mutex); -++ -++ lnum = ubifs_garbage_collect(c, 0); -++ if (lnum < 0) { -++ err = lnum; -++ if (err != -ENOSPC) -++ return err; -++ -++ /* -++ * GC could not make a free LEB. But someone else may -++ * have allocated new bud for this journal head, -++ * because we dropped the 'io_mutex', so try once -++ * again. -++ */ -++ dbg_jnl("GC couldn't make a free LEB for jhead %d", jhead); -++ if (retries++ < 2) { -++ dbg_jnl("retry (%d)", retries); -++ goto again; -++ } -++ -++ dbg_jnl("return -ENOSPC"); -++ return err; -++ } -++ -++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); -++ dbg_jnl("got LEB %d for jhead %d", lnum, jhead); -++ avail = c->leb_size - wbuf->offs - wbuf->used; -++ -++ if (wbuf->lnum != -1 && avail >= len) { -++ /* -++ * Someone else has switched the journal head and we have -++ * enough space now. This happens when more then one process is -++ * trying to write to the same journal head at the same time. -++ */ -++ dbg_jnl("return LEB %d back, already have LEB %d:%d", -++ lnum, wbuf->lnum, wbuf->offs + wbuf->used); -++ err = ubifs_return_leb(c, lnum); -++ if (err) -++ goto out_unlock; -++ return 0; -++ } -++ -++ err = ubifs_add_bud_to_log(c, jhead, lnum, 0); -++ if (err) -++ goto out_return; -++ offs = 0; -++ -++out: -++ err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs, UBI_SHORTTERM); -++ if (err) -++ goto out_unlock; -++ -++ return 0; -++ -++out_unlock: -++ mutex_unlock(&wbuf->io_mutex); -++ return err; -++ -++out_return: -++ /* An error occurred and the LEB has to be returned to lprops */ -++ ubifs_assert(err < 0); -++ err1 = ubifs_return_leb(c, lnum); -++ if (err1 && err == -EAGAIN) -++ /* -++ * Return original error code 'err' only if it is not -++ * '-EAGAIN', which is not really an error. Otherwise, return -++ * the error code of 'ubifs_return_leb()'. -++ */ -++ err = err1; -++ mutex_unlock(&wbuf->io_mutex); -++ return err; -++} -++ -++/** -++ * write_node - write node to a journal head. -++ * @c: UBIFS file-system description object -++ * @jhead: journal head -++ * @node: node to write -++ * @len: node length -++ * @lnum: LEB number written is returned here -++ * @offs: offset written is returned here -++ * -++ * This function writes a node to reserved space of journal head @jhead. -++ * Returns zero in case of success and a negative error code in case of -++ * failure. -++ */ -++static int write_node(struct ubifs_info *c, int jhead, void *node, int len, -++ int *lnum, int *offs) -++{ -++ struct ubifs_wbuf *wbuf = &c->jheads[jhead].wbuf; -++ -++ ubifs_assert(jhead != GCHD); -++ -++ *lnum = c->jheads[jhead].wbuf.lnum; -++ *offs = c->jheads[jhead].wbuf.offs + c->jheads[jhead].wbuf.used; -++ -++ dbg_jnl("jhead %d, LEB %d:%d, len %d", jhead, *lnum, *offs, len); -++ ubifs_prepare_node(c, node, len, 0); -++ -++ return ubifs_wbuf_write_nolock(wbuf, node, len); -++} -++ -++/** -++ * write_head - write data to a journal head. -++ * @c: UBIFS file-system description object -++ * @jhead: journal head -++ * @buf: buffer to write -++ * @len: length to write -++ * @lnum: LEB number written is returned here -++ * @offs: offset written is returned here -++ * @sync: non-zero if the write-buffer has to by synchronized -++ * -++ * This function is the same as 'write_node()' but it does not assume the -++ * buffer it is writing is a node, so it does not prepare it (which means -++ * initializing common header and calculating CRC). -++ */ -++static int write_head(struct ubifs_info *c, int jhead, void *buf, int len, -++ int *lnum, int *offs, int sync) -++{ -++ int err; -++ struct ubifs_wbuf *wbuf = &c->jheads[jhead].wbuf; -++ -++ ubifs_assert(jhead != GCHD); -++ -++ *lnum = c->jheads[jhead].wbuf.lnum; -++ *offs = c->jheads[jhead].wbuf.offs + c->jheads[jhead].wbuf.used; -++ dbg_jnl("jhead %d, LEB %d:%d, len %d", jhead, *lnum, *offs, len); -++ -++ err = ubifs_wbuf_write_nolock(wbuf, buf, len); -++ if (err) -++ return err; -++ if (sync) -++ err = ubifs_wbuf_sync_nolock(wbuf); -++ return err; -++} -++ -++/** -++ * make_reservation - reserve journal space. -++ * @c: UBIFS file-system description object -++ * @jhead: journal head -++ * @len: how many bytes to reserve -++ * -++ * This function makes space reservation in journal head @jhead. The function -++ * takes the commit lock and locks the journal head, and the caller has to -++ * unlock the head and finish the reservation with 'finish_reservation()'. -++ * Returns zero in case of success and a negative error code in case of -++ * failure. -++ * -++ * Note, the journal head may be unlocked as soon as the data is written, while -++ * the commit lock has to be released after the data has been added to the -++ * TNC. -++ */ -++static int make_reservation(struct ubifs_info *c, int jhead, int len) -++{ -++ int err, cmt_retries = 0, nospc_retries = 0; -++ -++ ubifs_assert(len <= c->dark_wm); -++ -++again: -++ down_read(&c->commit_sem); -++ err = reserve_space(c, jhead, len); -++ if (!err) -++ return 0; -++ up_read(&c->commit_sem); -++ -++ if (err == -ENOSPC) { -++ /* -++ * GC could not make any progress. We should try to commit -++ * once because it could make some dirty space and GC would -++ * make progress, so make the error -EAGAIN so that the below -++ * will commit and re-try. -++ */ -++ if (nospc_retries++ < 2) { -++ dbg_jnl("no space, retry"); -++ err = -EAGAIN; -++ } -++ -++ /* -++ * This means that the budgeting is incorrect. We always have -++ * to be able to write to the media, because all operations are -++ * budgeted. Deletions are not budgeted, though, but we reserve -++ * an extra LEB for them. -++ */ -++ } -++ -++ if (err != -EAGAIN) -++ goto out; -++ -++ /* -++ * -EAGAIN means that the journal is full or too large, or the above -++ * code wants to do one commit. Do this and re-try. -++ */ -++ if (cmt_retries > 128) { -++ /* -++ * This should not happen unless the journal size limitations -++ * are too tough. -++ */ -++ ubifs_err("stuck in space allocation"); -++ err = -ENOSPC; -++ goto out; -++ } else if (cmt_retries > 32) -++ ubifs_warn("too many space allocation re-tries (%d)", -++ cmt_retries); -++ -++ dbg_jnl("-EAGAIN, commit and retry (retried %d times)", -++ cmt_retries); -++ cmt_retries += 1; -++ -++ err = ubifs_run_commit(c); -++ if (err) -++ return err; -++ goto again; -++ -++out: -++ ubifs_err("cannot reserve %d bytes in jhead %d, error %d", -++ len, jhead, err); -++ if (err == -ENOSPC) { -++ /* This are some budgeting problems, print useful information */ -++ down_write(&c->commit_sem); -++ spin_lock(&c->space_lock); -++ dbg_dump_stack(); -++ dbg_dump_budg(c); -++ spin_unlock(&c->space_lock); -++ dbg_dump_lprops(c); -++ cmt_retries = dbg_check_lprops(c); -++ up_write(&c->commit_sem); -++ } -++ -++ return err; -++} -++ -++/** -++ * release_head - release a journal head. -++ * @c: UBIFS file-system description object -++ * @jhead: journal head -++ * -++ * This function releases journal head @jhead which was locked by -++ * the 'make_reservation()' function. It has to be called after each successful -++ * 'make_reservation()' invocation. -++ */ -++static inline void release_head(struct ubifs_info *c, int jhead) -++{ -++ mutex_unlock(&c->jheads[jhead].wbuf.io_mutex); -++} -++ -++/** -++ * finish_reservation - finish a reservation. -++ * @c: UBIFS file-system description object -++ * -++ * This function finishes journal space reservation. It must be called after -++ * 'make_reservation()'. -++ */ -++static void finish_reservation(struct ubifs_info *c) -++{ -++ up_read(&c->commit_sem); -++} -++ -++/** -++ * get_dent_type - translate VFS inode mode to UBIFS directory entry type. -++ * @mode: inode mode -++ */ -++static int get_dent_type(int mode) -++{ -++ switch (mode & S_IFMT) { -++ case S_IFREG: -++ return UBIFS_ITYPE_REG; -++ case S_IFDIR: -++ return UBIFS_ITYPE_DIR; -++ case S_IFLNK: -++ return UBIFS_ITYPE_LNK; -++ case S_IFBLK: -++ return UBIFS_ITYPE_BLK; -++ case S_IFCHR: -++ return UBIFS_ITYPE_CHR; -++ case S_IFIFO: -++ return UBIFS_ITYPE_FIFO; -++ case S_IFSOCK: -++ return UBIFS_ITYPE_SOCK; -++ default: -++ BUG(); -++ } -++ return 0; -++} -++ -++/** -++ * pack_inode - pack an inode node. -++ * @c: UBIFS file-system description object -++ * @ino: buffer in which to pack inode node -++ * @inode: inode to pack -++ * @last: indicates the last node of the group -++ * @last_reference: non-zero if this is a deletion inode -++ */ -++static void pack_inode(struct ubifs_info *c, struct ubifs_ino_node *ino, -++ const struct inode *inode, int last, int last_reference) -++{ -++ int data_len = 0; -++ struct ubifs_inode *ui = ubifs_inode(inode); -++ -++ ino->ch.node_type = UBIFS_INO_NODE; -++ ino_key_init_flash(c, &ino->key, inode->i_ino); -++ ino->creat_sqnum = cpu_to_le64(ui->creat_sqnum); -++ ino->size = cpu_to_le64(i_size_read(inode)); -++ ino->nlink = cpu_to_le32(inode->i_nlink); -++ ino->atime_sec = cpu_to_le64(inode->i_atime.tv_sec); -++ ino->atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec); -++ ino->ctime_sec = cpu_to_le64(inode->i_ctime.tv_sec); -++ ino->ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); -++ ino->mtime_sec = cpu_to_le64(inode->i_mtime.tv_sec); -++ ino->mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); -++ ino->uid = cpu_to_le32(inode->i_uid); -++ ino->gid = cpu_to_le32(inode->i_gid); -++ ino->mode = cpu_to_le32(inode->i_mode); -++ ino->flags = cpu_to_le32(ui->flags); -++ ino->compr_type = cpu_to_le16(ui->compr_type); -++ ino->xattr_cnt = cpu_to_le32(ui->xattr_cnt); -++ ino->xattr_size = cpu_to_le64(ui->xattr_size); -++ ino->xattr_names = cpu_to_le32(ui->xattr_names); -++ ino->data_len = cpu_to_le32(ui->data_len); -++ zero_ino_node_unused(ino); -++ -++ /* -++ * Drop the attached data if this is a deletion inode, the data is not -++ * needed anymore. -++ */ -++ if (!last_reference) { -++ memcpy(ino->data, ui->data, ui->data_len); -++ data_len = ui->data_len; -++ } -++ -++ ubifs_prep_grp_node(c, ino, UBIFS_INO_NODE_SZ + data_len, last); -++} -++ -++/** -++ * ubifs_jnl_update - update inode. -++ * @c: UBIFS file-system description object -++ * @dir: parent inode or host inode in case of extended attributes -++ * @nm: directory entry name -++ * @inode: inode -++ * @deletion: indicates a directory entry deletion i.e unlink or rmdir -++ * @sync: non-zero if the write-buffer has to be synchronized -++ * @xent: non-zero if the directory entry is an extended attribute entry -++ * -++ * This function updates an inode by writing a directory entry (or extended -++ * attribute entry), the inode itself, and the parent directory inode (or the -++ * host inode) to the journal. -++ * -++ * The function writes the host inode @dir last, which is important in case of -++ * extended attributes. Indeed, then we guarantee that if the host inode gets -++ * synchronized, and the write-buffer it sits in gets flushed, the extended -++ * attribute inode gets flushed too. And this is exactly what the user expects - -++ * synchronizing the host inode synchronizes its extended attributes. -++ * Similarly, this guarantees that if @dir is synchronized, its directory entry -++ * corresponding to @nm gets synchronized too. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, -++ const struct qstr *nm, const struct inode *inode, -++ int deletion, int sync, int xent) -++{ -++ int err, dlen, ilen, len, lnum, ino_offs, dent_offs; -++ int aligned_dlen, aligned_ilen; -++ int last_reference = !!(deletion && inode->i_nlink == 0); -++ struct ubifs_dent_node *dent; -++ struct ubifs_ino_node *ino; -++ union ubifs_key dent_key, ino_key; -++ -++ dbg_jnl("ino %lu, dent '%.*s', data len %d in dir ino %lu", -++ inode->i_ino, nm->len, nm->name, ubifs_inode(inode)->data_len, -++ dir->i_ino); -++ ubifs_assert(ubifs_inode(dir)->data_len == 0); -++ -++ dlen = UBIFS_DENT_NODE_SZ + nm->len + 1; -++ ilen = UBIFS_INO_NODE_SZ; -++ -++ /* -++ * If the last reference to the inode is being deleted, then there is no -++ * need to attach and write inode data, it is being deleted anyway. -++ */ -++ if (!last_reference) -++ ilen += ubifs_inode(inode)->data_len; -++ -++ aligned_dlen = ALIGN(dlen, 8); -++ aligned_ilen = ALIGN(ilen, 8); -++ -++ len = aligned_dlen + aligned_ilen + UBIFS_INO_NODE_SZ; -++ -++ dent = kmalloc(len, GFP_NOFS); -++ if (!dent) -++ return -ENOMEM; -++ -++ /* Make reservation before allocating sequence numbers */ -++ err = make_reservation(c, BASEHD, len); -++ if (err) -++ goto out_free; -++ -++ if (!xent) { -++ dent->ch.node_type = UBIFS_DENT_NODE; -++ dent_key_init(c, &dent_key, dir->i_ino, nm); -++ } else { -++ dent->ch.node_type = UBIFS_XENT_NODE; -++ xent_key_init(c, &dent_key, dir->i_ino, nm); -++ } -++ -++ key_write(c, &dent_key, dent->key); -++ dent->inum = deletion ? 0 : cpu_to_le64(inode->i_ino); -++ dent->type = get_dent_type(inode->i_mode); -++ dent->nlen = cpu_to_le16(nm->len); -++ memcpy(dent->name, nm->name, nm->len); -++ dent->name[nm->len] = '\0'; -++ zero_dent_node_unused(dent); -++ ubifs_prep_grp_node(c, dent, dlen, 0); -++ -++ ino = (void *)dent + aligned_dlen; -++ pack_inode(c, ino, inode, 0, last_reference); -++ -++ ino = (void *)ino + aligned_ilen; -++ pack_inode(c, ino, dir, 1, 0); -++ -++ if (last_reference) { -++ err = ubifs_add_orphan(c, inode->i_ino); -++ if (err) { -++ release_head(c, BASEHD); -++ goto out_finish; -++ } -++ } -++ -++ err = write_head(c, BASEHD, dent, len, &lnum, &dent_offs, sync); -++ if (!sync && !err) { -++ struct ubifs_wbuf *wbuf = &c->jheads[BASEHD].wbuf; -++ -++ ubifs_wbuf_add_ino_nolock(wbuf, inode->i_ino); -++ ubifs_wbuf_add_ino_nolock(wbuf, dir->i_ino); -++ } -++ release_head(c, BASEHD); -++ kfree(dent); -++ if (err) -++ goto out_ro; -++ -++ if (deletion) { -++ err = ubifs_tnc_remove_nm(c, &dent_key, nm); -++ if (err) -++ goto out_ro; -++ err = ubifs_add_dirt(c, lnum, dlen); -++ } else -++ err = ubifs_tnc_add_nm(c, &dent_key, lnum, dent_offs, dlen, nm); -++ if (err) -++ goto out_ro; -++ -++ /* -++ * Note, we do not remove the inode from TNC even if the last reference -++ * to it has just been deleted, because the inode may still be opened. -++ * Instead, the inode has been added to orphan lists and the orphan -++ * subsystem will take further care about it. -++ */ -++ ino_key_init(c, &ino_key, inode->i_ino); -++ ino_offs = dent_offs + aligned_dlen; -++ err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, ilen); -++ if (err) -++ goto out_ro; -++ -++ ino_key_init(c, &ino_key, dir->i_ino); -++ ino_offs += aligned_ilen; -++ err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, UBIFS_INO_NODE_SZ); -++ if (err) -++ goto out_ro; -++ -++ finish_reservation(c); -++ return 0; -++ -++out_finish: -++ finish_reservation(c); -++out_free: -++ kfree(dent); -++ return err; -++ -++out_ro: -++ ubifs_ro_mode(c, err); -++ if (last_reference) -++ ubifs_delete_orphan(c, inode->i_ino); -++ finish_reservation(c); -++ return err; -++} -++ -++/** -++ * ubifs_jnl_write_data - write a data node to the journal. -++ * @c: UBIFS file-system description object -++ * @inode: inode the data node belongs to -++ * @key: node key -++ * @buf: buffer to write -++ * @len: data length (must not exceed %UBIFS_BLOCK_SIZE) -++ * -++ * This function writes a data node to the journal. Returns %0 if the data node -++ * was successfully written, and a negative error code in case of failure. -++ */ -++int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode, -++ const union ubifs_key *key, const void *buf, int len) -++{ -++ int err, lnum, offs, compr_type, out_len; -++ int dlen = UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR; -++ const struct ubifs_inode *ui = ubifs_inode(inode); -++ struct ubifs_data_node *data; -++ -++ dbg_jnl("ino %lu, blk %u, len %d, key %s", key_ino(c, key), -++ key_block(c, key), len, DBGKEY(key)); -++ ubifs_assert(len <= UBIFS_BLOCK_SIZE); -++ -++ data = kmalloc(dlen, GFP_NOFS); -++ if (!data) -++ return -ENOMEM; -++ -++ data->ch.node_type = UBIFS_DATA_NODE; -++ key_write(c, key, &data->key); -++ data->size = cpu_to_le32(len); -++ zero_data_node_unused(data); -++ -++ if (!(ui->flags && UBIFS_COMPR_FL)) -++ /* Compression is disabled for this inode */ -++ compr_type = UBIFS_COMPR_NONE; -++ else -++ compr_type = ui->compr_type; -++ -++ out_len = dlen - UBIFS_DATA_NODE_SZ; -++ ubifs_compress(buf, len, &data->data, &out_len, &compr_type); -++ ubifs_assert(out_len <= UBIFS_BLOCK_SIZE); -++ -++ dlen = UBIFS_DATA_NODE_SZ + out_len; -++ data->compr_type = cpu_to_le16(compr_type); -++ -++ /* Make reservation before allocating sequence numbers */ -++ err = make_reservation(c, DATAHD, dlen); -++ if (err) -++ goto out_free; -++ -++ err = write_node(c, DATAHD, data, dlen, &lnum, &offs); -++ if (!err) -++ ubifs_wbuf_add_ino_nolock(&c->jheads[DATAHD].wbuf, -++ key_ino(c, key)); -++ release_head(c, DATAHD); -++ if (err) -++ goto out_ro; -++ -++ err = ubifs_tnc_add(c, key, lnum, offs, dlen); -++ if (err) -++ goto out_ro; -++ -++ finish_reservation(c); -++ kfree(data); -++ return 0; -++ -++out_ro: -++ ubifs_ro_mode(c, err); -++ finish_reservation(c); -++out_free: -++ kfree(data); -++ return err; -++} -++ -++/** -++ * ubifs_jnl_write_inode - flush inode to the journal. -++ * @c: UBIFS file-system description object -++ * @inode: inode to flush -++ * @last_reference: inode has been deleted -++ * @sync: non-zero if the write-buffer has to be synchronized -++ * -++ * This function writes inode @inode to the journal (to the base head). Returns -++ * zero in case of success and a negative error code in case of failure. -++ */ -++int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode, -++ int last_reference, int sync) -++{ -++ int err, len, lnum, offs; -++ struct ubifs_ino_node *ino; -++ struct ubifs_inode *ui = ubifs_inode(inode); -++ -++ dbg_jnl("ino %lu%s", inode->i_ino, -++ last_reference ? " (last reference)" : ""); -++ if (last_reference) -++ ubifs_assert(inode->i_nlink == 0); -++ -++ /* If the inode is deleted, do not write the attached data */ -++ len = UBIFS_INO_NODE_SZ; -++ if (!last_reference) -++ len += ui->data_len; -++ ino = kmalloc(len, GFP_NOFS); -++ if (!ino) -++ return -ENOMEM; -++ -++ /* Make reservation before allocating sequence numbers */ -++ err = make_reservation(c, BASEHD, len); -++ if (err) -++ goto out_free; -++ -++ pack_inode(c, ino, inode, 1, last_reference); -++ -++ err = write_head(c, BASEHD, ino, len, &lnum, &offs, sync); -++ if (!sync && !err) -++ ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, -++ inode->i_ino); -++ release_head(c, BASEHD); -++ if (err) -++ goto out_ro; -++ -++ if (last_reference) { -++ err = ubifs_tnc_remove_ino(c, inode->i_ino); -++ if (err) -++ goto out_ro; -++ ubifs_delete_orphan(c, inode->i_ino); -++ err = ubifs_add_dirt(c, lnum, len); -++ } else { -++ union ubifs_key key; -++ -++ ino_key_init(c, &key, inode->i_ino); -++ err = ubifs_tnc_add(c, &key, lnum, offs, len); -++ } -++ if (err) -++ goto out_ro; -++ -++ finish_reservation(c); -++ kfree(ino); -++ return 0; -++ -++out_ro: -++ ubifs_ro_mode(c, err); -++ finish_reservation(c); -++out_free: -++ kfree(ino); -++ return err; -++} -++ -++/** -++ * ubifs_jnl_rename - rename a directory entry. -++ * @c: UBIFS file-system description object -++ * @old_dir: parent inode of directory entry to rename -++ * @old_dentry: directory entry to rename -++ * @new_dir: parent inode of directory entry to rename -++ * @new_dentry: new directory entry (or directory entry to replace) -++ * @sync: non-zero if the write-buffer has to be synchronized -++ * -++ * Returns zero in case of success and a negative error code in case of failure. -++ */ -++int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, -++ const struct dentry *old_dentry, -++ const struct inode *new_dir, -++ const struct dentry *new_dentry, int sync) -++{ -++ const struct inode *old_inode = old_dentry->d_inode; -++ const struct inode *new_inode = new_dentry->d_inode; -++ int err, dlen1, dlen2, ilen, lnum, offs, len; -++ int aligned_dlen1, aligned_dlen2, plen = UBIFS_INO_NODE_SZ; -++ int last_reference = !!(new_inode && new_inode->i_nlink == 0); -++ struct ubifs_dent_node *dent, *dent2; -++ void *p; -++ union ubifs_key key; -++ -++ dbg_jnl("dent '%.*s' in dir ino %lu to dent '%.*s' in dir ino %lu", -++ old_dentry->d_name.len, old_dentry->d_name.name, -++ old_dir->i_ino, new_dentry->d_name.len, -++ new_dentry->d_name.name, new_dir->i_ino); -++ -++ ubifs_assert(ubifs_inode(old_dir)->data_len == 0); -++ ubifs_assert(ubifs_inode(new_dir)->data_len == 0); -++ -++ dlen1 = UBIFS_DENT_NODE_SZ + new_dentry->d_name.len + 1; -++ dlen2 = UBIFS_DENT_NODE_SZ + old_dentry->d_name.len + 1; -++ if (new_inode) { -++ ilen = UBIFS_INO_NODE_SZ; -++ if (!last_reference) -++ ilen += ubifs_inode(new_inode)->data_len; -++ } else -++ ilen = 0; -++ -++ aligned_dlen1 = ALIGN(dlen1, 8); -++ aligned_dlen2 = ALIGN(dlen2, 8); -++ -++ len = aligned_dlen1 + aligned_dlen2 + ALIGN(ilen, 8) + ALIGN(plen, 8); -++ if (old_dir != new_dir) -++ len += plen; -++ -++ dent = kmalloc(len, GFP_NOFS); -++ if (!dent) -++ return -ENOMEM; -++ -++ /* Make reservation before allocating sequence numbers */ -++ err = make_reservation(c, BASEHD, len); -++ if (err) -++ goto out_free; -++ -++ /* Make new dent */ -++ dent->ch.node_type = UBIFS_DENT_NODE; -++ dent_key_init_flash(c, &dent->key, new_dir->i_ino, &new_dentry->d_name); -++ dent->inum = cpu_to_le64(old_inode->i_ino); -++ dent->type = get_dent_type(old_inode->i_mode); -++ dent->nlen = cpu_to_le16(new_dentry->d_name.len); -++ memcpy(dent->name, new_dentry->d_name.name, new_dentry->d_name.len); -++ dent->name[new_dentry->d_name.len] = '\0'; -++ zero_dent_node_unused(dent); -++ ubifs_prep_grp_node(c, dent, dlen1, 0); -++ -++ dent2 = (void *)dent + aligned_dlen1; -++ -++ /* Make deletion dent */ -++ dent2->ch.node_type = UBIFS_DENT_NODE; -++ dent_key_init_flash(c, &dent2->key, old_dir->i_ino, -++ &old_dentry->d_name); -++ dent2->inum = 0; -++ dent2->type = DT_UNKNOWN; -++ dent2->nlen = cpu_to_le16(old_dentry->d_name.len); -++ memcpy(dent2->name, old_dentry->d_name.name, old_dentry->d_name.len); -++ dent2->name[old_dentry->d_name.len] = '\0'; -++ zero_dent_node_unused(dent2); -++ ubifs_prep_grp_node(c, dent2, dlen2, 0); -++ -++ p = (void *)dent2 + aligned_dlen2; -++ if (new_inode) { -++ pack_inode(c, p, new_inode, 0, last_reference); -++ p += ALIGN(ilen, 8); -++ } -++ -++ if (old_dir == new_dir) -++ pack_inode(c, p, old_dir, 1, 0); -++ else { -++ pack_inode(c, p, old_dir, 0, 0); -++ p += ALIGN(plen, 8); -++ pack_inode(c, p, new_dir, 1, 0); -++ } -++ -++ if (last_reference) { -++ err = ubifs_add_orphan(c, new_inode->i_ino); -++ if (err) { -++ release_head(c, BASEHD); -++ goto out_finish; -++ } -++ } -++ -++ err = write_head(c, BASEHD, dent, len, &lnum, &offs, sync); -++ if (!sync && !err) { -++ struct ubifs_wbuf *wbuf = &c->jheads[BASEHD].wbuf; -++ -++ ubifs_wbuf_add_ino_nolock(wbuf, new_dir->i_ino); -++ ubifs_wbuf_add_ino_nolock(wbuf, old_dir->i_ino); -++ if (new_inode) -++ ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, -++ new_inode->i_ino); -++ } -++ release_head(c, BASEHD); -++ if (err) -++ goto out_ro; -++ -++ dent_key_init(c, &key, new_dir->i_ino, &new_dentry->d_name); -++ err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen1, &new_dentry->d_name); -++ if (err) -++ goto out_ro; -++ -++ err = ubifs_add_dirt(c, lnum, dlen2); -++ if (err) -++ goto out_ro; -++ -++ dent_key_init(c, &key, old_dir->i_ino, &old_dentry->d_name); -++ err = ubifs_tnc_remove_nm(c, &key, &old_dentry->d_name); -++ if (err) -++ goto out_ro; -++ -++ offs += aligned_dlen1 + aligned_dlen2; -++ if (new_inode) { -++ ino_key_init(c, &key, new_inode->i_ino); -++ err = ubifs_tnc_add(c, &key, lnum, offs, ilen); -++ if (err) -++ goto out_ro; -++ offs += ALIGN(ilen, 8); -++ } -++ -++ ino_key_init(c, &key, old_dir->i_ino); -++ err = ubifs_tnc_add(c, &key, lnum, offs, plen); -++ if (err) -++ goto out_ro; -++ -++ if (old_dir != new_dir) { -++ offs += ALIGN(plen, 8); -++ ino_key_init(c, &key, new_dir->i_ino); -++ err = ubifs_tnc_add(c, &key, lnum, offs, plen); -++ if (err) -++ goto out_ro; -++ } -++ -++ finish_reservation(c); -++ kfree(dent); -++ return 0; -++ -++out_ro: -++ ubifs_ro_mode(c, err); -++ if (last_reference) -++ ubifs_delete_orphan(c, new_inode->i_ino); -++out_finish: -++ finish_reservation(c); -++out_free: -++ kfree(dent); -++ return err; -++} -++ -++/** -++ * recomp_data_node - re-compress a truncated data node. -++ * @dn: data node to re-compress -++ * @new_len: new length -++ * -++ * This function is used when an inode is truncated and the last data node of -++ * the inode has to be re-compressed and re-written. -++ */ -++static int recomp_data_node(struct ubifs_data_node *dn, int *new_len) -++{ -++ void *buf; -++ int err, len, compr_type, out_len; -++ -++ out_len = le32_to_cpu(dn->size); -++ buf = kmalloc(out_len * WORST_COMPR_FACTOR, GFP_NOFS); -++ if (!buf) -++ return -ENOMEM; -++ -++ len = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ; -++ compr_type = le16_to_cpu(dn->compr_type); -++ err = ubifs_decompress(&dn->data, len, buf, &out_len, compr_type); -++ if (err) -++ goto out; -++ -++ ubifs_compress(buf, *new_len, &dn->data, &out_len, &compr_type); -++ ubifs_assert(out_len <= UBIFS_BLOCK_SIZE); -++ dn->compr_type = cpu_to_le16(compr_type); -++ dn->size = cpu_to_le32(*new_len); -++ *new_len = UBIFS_DATA_NODE_SZ + out_len; -++out: -++ kfree(buf); -++ return err; -++} -++ -++/** -++ * ubifs_jnl_truncate - update the journal for a truncation. -++ * @c: UBIFS file-system description object -++ * @inum: inode number of inode being truncated -++ * @old_size: old size -++ * @new_size: new size -++ * -++ * When the size of a file decreases due to truncation, a truncation node is -++ * written, the journal tree is updated, and the last data block is re-written -++ * if it has been affected. -++ * -++ * This function returns %0 in the case of success, and a negative error code in -++ * case of failure. -++ */ -++int ubifs_jnl_truncate(struct ubifs_info *c, ino_t inum, -++ loff_t old_size, loff_t new_size) -++{ -++ union ubifs_key key, to_key; -++ struct ubifs_trun_node *trun; -++ struct ubifs_data_node *uninitialized_var(dn); -++ int err, dlen, len, lnum, offs, bit, sz; -++ unsigned int blk; -++ -++ dbg_jnl("ino %lu, size %lld -> %lld", inum, old_size, new_size); -++ -++ sz = UBIFS_TRUN_NODE_SZ + UBIFS_MAX_DATA_NODE_SZ * WORST_COMPR_FACTOR; -++ trun = kmalloc(sz, GFP_NOFS); -++ if (!trun) -++ return -ENOMEM; -++ -++ trun->ch.node_type = UBIFS_TRUN_NODE; -++ trun_key_init_flash(c, &trun->key, inum); -++ trun->old_size = cpu_to_le64(old_size); -++ trun->new_size = cpu_to_le64(new_size); -++ -++ dlen = new_size & (UBIFS_BLOCK_SIZE - 1); -++ -++ if (dlen) { -++ /* Get last data block so it can be truncated */ -++ dn = (void *)trun + ALIGN(UBIFS_TRUN_NODE_SZ, 8); -++ blk = new_size / UBIFS_BLOCK_SIZE; -++ data_key_init(c, &key, inum, blk); -++ dbg_jnl("last block key %s", DBGKEY(&key)); -++ err = ubifs_tnc_lookup(c, &key, dn); -++ if (err == -ENOENT) -++ dlen = 0; /* Not found (so it is a hole) */ -++ else if (err) -++ goto out_free; -++ else { -++ if (le32_to_cpu(dn->size) <= dlen) -++ dlen = 0; /* Nothing to do */ -++ else { -++ int compr_type = le16_to_cpu(dn->compr_type); -++ -++ if (compr_type != UBIFS_COMPR_NONE) { -++ err = recomp_data_node(dn, &dlen); -++ if (err) -++ goto out_free; -++ } else { -++ dn->size = cpu_to_le32(dlen); -++ dlen += UBIFS_DATA_NODE_SZ; -++ } -++ zero_data_node_unused(dn); -++ } -++ } -++ } -++ -++ if (dlen) -++ len = ALIGN(UBIFS_TRUN_NODE_SZ, 8) + dlen; -++ else -++ len = UBIFS_TRUN_NODE_SZ; -++ -++ /* Must make reservation before allocating sequence numbers */ -++ err = make_reservation(c, BASEHD, len); -++ if (err) -++ goto out_free; -++ -++ ubifs_prepare_node(c, trun, UBIFS_TRUN_NODE_SZ, 0); -++ if (dlen) -++ ubifs_prepare_node(c, dn, dlen, 0); -++ -++ err = write_head(c, BASEHD, trun, len, &lnum, &offs, 0); -++ if (!err) -++ ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, inum); -++ release_head(c, BASEHD); -++ if (err) -++ goto out_ro; -++ -++ if (dlen) { -++ offs += ALIGN(UBIFS_TRUN_NODE_SZ, 8); -++ err = ubifs_tnc_add(c, &key, lnum, offs, dlen); -++ if (err) -++ goto out_ro; -++ } -++ -++ err = ubifs_add_dirt(c, lnum, UBIFS_TRUN_NODE_SZ); -++ if (err) -++ goto out_ro; -++ -++ bit = new_size & (UBIFS_BLOCK_SIZE - 1); -++ -++ blk = new_size / UBIFS_BLOCK_SIZE + (bit ? 1 : 0); -++ data_key_init(c, &key, inum, blk); -++ -++ bit = old_size & (UBIFS_BLOCK_SIZE - 1); -++ -++ blk = old_size / UBIFS_BLOCK_SIZE - (bit ? 0: 1); -++ data_key_init(c, &to_key, inum, blk); -++ -++ err = ubifs_tnc_remove_range(c, &key, &to_key); -++ if (err) -++ goto out_ro; -++ -++ finish_reservation(c); -++ kfree(trun); -++ return 0; -++ -++out_ro: -++ ubifs_ro_mode(c, err); -++ finish_reservation(c); -++out_free: -++ kfree(trun); -++ return err; -++} -++ -++#ifdef CONFIG_UBIFS_FS_XATTR -++ -++int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host, -++ const struct inode *inode, const struct qstr *nm, -++ int sync) -++{ -++ int err, xlen, hlen, len, lnum, xent_offs, aligned_xlen; -++ struct ubifs_dent_node *xent; -++ struct ubifs_ino_node *ino; -++ union ubifs_key xent_key, key1, key2; -++ -++ dbg_jnl("host %lu, xattr ino %lu, name '%s', data len %d", -++ host->i_ino, inode->i_ino, nm->name, -++ ubifs_inode(inode)->data_len); -++ ubifs_assert(inode->i_nlink == 0); -++ -++ /* -++ * Since we are deleting the inode, we do not bother to attach any data -++ * to it and assume its length is %UBIFS_INO_NODE_SZ. -++ */ -++ xlen = UBIFS_DENT_NODE_SZ + nm->len + 1; -++ aligned_xlen = ALIGN(xlen, 8); -++ hlen = ubifs_inode(host)->data_len + UBIFS_INO_NODE_SZ; -++ len = aligned_xlen + UBIFS_INO_NODE_SZ + ALIGN(hlen, 8); -++ -++ xent = kmalloc(len, GFP_NOFS); -++ if (!xent) -++ return -ENOMEM; -++ -++ /* Make reservation before allocating sequence numbers */ -++ err = make_reservation(c, BASEHD, len); -++ if (err) { -++ kfree(xent); -++ return err; -++ } -++ -++ xent->ch.node_type = UBIFS_XENT_NODE; -++ xent_key_init(c, &xent_key, host->i_ino, nm); -++ key_write(c, &xent_key, xent->key); -++ xent->inum = 0; -++ xent->type = get_dent_type(inode->i_mode); -++ xent->nlen = cpu_to_le16(nm->len); -++ memcpy(xent->name, nm->name, nm->len); -++ xent->name[nm->len] = '\0'; -++ zero_dent_node_unused(xent); -++ ubifs_prep_grp_node(c, xent, xlen, 0); -++ -++ ino = (void *)xent + aligned_xlen; -++ pack_inode(c, ino, inode, 0, 1); -++ -++ ino = (void *)ino + UBIFS_INO_NODE_SZ; -++ pack_inode(c, ino, host, 1, 0); -++ -++ err = write_head(c, BASEHD, xent, len, &lnum, &xent_offs, sync); -++ if (!sync && !err) -++ ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, host->i_ino); -++ release_head(c, BASEHD); -++ kfree(xent); -++ if (err) -++ goto out_ro; -++ -++ /* Remove the extended attribute entry from TNC */ -++ err = ubifs_tnc_remove_nm(c, &xent_key, nm); -++ if (err) -++ goto out_ro; -++ err = ubifs_add_dirt(c, lnum, xlen); -++ if (err) -++ goto out_ro; -++ -++ /* -++ * Remove all nodes belonging to the extended attribute inode from TNC. -++ * Well, there actually must be only one node - the inode itself. -++ */ -++ lowest_ino_key(c, &key1, inode->i_ino); -++ highest_ino_key(c, &key2, inode->i_ino); -++ err = ubifs_tnc_remove_range(c, &key1, &key2); -++ if (err) -++ goto out_ro; -++ err = ubifs_add_dirt(c, lnum, UBIFS_INO_NODE_SZ); -++ if (err) -++ goto out_ro; -++ -++ /* And update TNC with the new host inode position */ -++ ino_key_init(c, &key1, host->i_ino); -++ err = ubifs_tnc_add(c, &key1, lnum, xent_offs + len - hlen, hlen); -++ if (err) -++ goto out_ro; -++ -++ finish_reservation(c); -++ return 0; -++ -++out_ro: -++ ubifs_ro_mode(c, err); -++ finish_reservation(c); -++ return err; -++} -++ -++/** -++ * ubifs_jnl_write_2_inodes - write 2 inodes to the journal. -++ * @c: UBIFS file-system description object -++ * @inode1: first inode to write -++ * @inode2: second inode to write -++ * @sync: non-zero if the write-buffer has to be synchronized -++ * -++ * This function writes 2 inodes @inode1 and @inode2 to the journal (to the -++ * base head - first @inode1, then @inode2). Returns zero in case of success -++ * and a negative error code in case of failure. -++ */ -++int ubifs_jnl_write_2_inodes(struct ubifs_info *c, const struct inode *inode1, -++ const struct inode *inode2, int sync) -++{ -++ int err, len1, len2, aligned_len, aligned_len1, lnum, offs; -++ struct ubifs_ino_node *ino; -++ union ubifs_key key; -++ -++ dbg_jnl("ino %lu, ino %lu", inode1->i_ino, inode2->i_ino); -++ ubifs_assert(inode1->i_nlink > 0); -++ ubifs_assert(inode2->i_nlink > 0); -++ -++ len1 = UBIFS_INO_NODE_SZ + ubifs_inode(inode1)->data_len; -++ len2 = UBIFS_INO_NODE_SZ + ubifs_inode(inode2)->data_len; -++ aligned_len1 = ALIGN(len1, 8); -++ aligned_len = aligned_len1 + ALIGN(len2, 8); -++ -++ ino = kmalloc(aligned_len, GFP_NOFS); -++ if (!ino) -++ return -ENOMEM; -++ -++ /* Make reservation before allocating sequence numbers */ -++ err = make_reservation(c, BASEHD, aligned_len); -++ if (err) -++ goto out_free; -++ -++ pack_inode(c, ino, inode1, 0, 0); -++ pack_inode(c, (void *)ino + aligned_len1, inode2, 1, 0); -++ -++ err = write_head(c, BASEHD, ino, aligned_len, &lnum, &offs, 0); -++ if (!sync && !err) { -++ struct ubifs_wbuf *wbuf = &c->jheads[BASEHD].wbuf; -++ -++ ubifs_wbuf_add_ino_nolock(wbuf, inode1->i_ino); -++ ubifs_wbuf_add_ino_nolock(wbuf, inode2->i_ino); -++ } -++ release_head(c, BASEHD); -++ if (err) -++ goto out_ro; -++ -++ ino_key_init(c, &key, inode1->i_ino); -++ err = ubifs_tnc_add(c, &key, lnum, offs, len1); -++ if (err) -++ goto out_ro; -++ -++ ino_key_init(c, &key, inode2->i_ino); -++ err = ubifs_tnc_add(c, &key, lnum, offs + aligned_len1, len2); -++ if (err) -++ goto out_ro; -++ -++ finish_reservation(c); -++ kfree(ino); -++ return 0; -++ -++out_ro: -++ ubifs_ro_mode(c, err); -++ finish_reservation(c); -++out_free: -++ kfree(ino); -++ return err; -++} -++ -++#endif /* CONFIG_UBIFS_FS_XATTR */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/key.h linux-2.6.24.7/fs/ubifs/key.h -+--- linux-2.6.24.7.old/fs/ubifs/key.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/key.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,566 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* -++ * This header contains various key-related definitions and helper function. -++ * UBIFS allows several key schemes, so we access key fields only via these -++ * helpers. At the moment only one key scheme is supported. -++ * -++ * Simple key scheme -++ * ~~~~~~~~~~~~~~~~~ -++ * -++ * Keys are 64-bits long. First 32-bits are inode number (parent inode number -++ * in case of direntry key). Next 3 bits are node type. The last 29 bits are -++ * 4KiB offset in case of inode node, and direntry hash in case of a direntry -++ * node. We use "r5" hash borrowed from reiserfs. -++ */ -++ -++#ifndef __UBIFS_KEY_H__ -++#define __UBIFS_KEY_H__ -++ -++/** -++ * key_r5_hash - R5 hash function (borrowed from reiserfs). -++ * @s: direntry name -++ * @len: name length -++ */ -++static inline uint32_t key_r5_hash(const char *s, int len) -++{ -++ uint32_t a = 0; -++ const signed char *str = (const signed char *)s; -++ -++ while (*str) { -++ a += *str << 4; -++ a += *str >> 4; -++ a *= 11; -++ str++; -++ } -++ -++ /* TODO: change this to -++ * a &= UBIFS_S_KEY_HASH_MASK; */ -++ a &= 0x1FFFFFFF; -++ -++ /* -++ * We use hash values as offset in directories, so values %0 and %1 are -++ * reserved for "." and "..". %2 is reserved for "end of readdir" -++ * marker. -++ */ -++ if (unlikely(a >= 0 && a <= 2)) -++ a += 3; -++ return a; -++} -++ -++/** -++ * tmp_key_r5_hash - R5 hash function (borrowed from reiserfs). -++ * @s: direntry name -++ * @len: name length -++ * TODO: this should die soon -++ */ -++static inline uint32_t tmp_key_r5_hash(const char *s, int len) -++{ -++ uint32_t a = 0; -++ const signed char *str = (const signed char *)s; -++ -++ while (*str) { -++ a += *str << 4; -++ a += *str >> 4; -++ a *= 11; -++ str++; -++ } -++ -++ a &= 0x01FFFFFF; -++ -++ /* -++ * We use hash values as offset in directories, so values %0 and %1 are -++ * reserved for "." and "..". %2 is reserved for possible future use. -++ */ -++ if (unlikely(a >= 0 && a <= 2)) -++ a += 3; -++ return a; -++} -++ -++/** -++ * key_test_hash - testing hash function. -++ * @str: direntry name -++ * @len: name length -++ */ -++static inline uint32_t key_test_hash(const char *str, int len) -++{ -++ uint32_t a = 0; -++ -++ len = min_t(uint32_t, len, 4); -++ memcpy(&a, str, len); -++ /* TODO: change this to -++ * a &= UBIFS_S_KEY_HASH_MASK; */ -++ a &= 0x1FFFFFFF; -++ if (unlikely(a >= 0 && a <= 2)) -++ a += 3; -++ return a; -++} -++ -++/** -++ * ino_key_init - initialize inode key. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: inode number -++ */ -++static inline void ino_key_init(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum) -++{ -++ key->u32[0] = inum; -++ key->u32[1] = UBIFS_INO_KEY << UBIFS_S_KEY_BLOCK_BITS; -++} -++ -++/** -++ * ino_key_init_flash - initialize on-flash inode key. -++ * @c: UBIFS file-system description object -++ * @k: key to initialize -++ * @inum: inode number -++ */ -++static inline void ino_key_init_flash(const struct ubifs_info *c, void *k, -++ ino_t inum) -++{ -++ union ubifs_key *key = k; -++ -++ key->j32[0] = cpu_to_le32(inum); -++ key->j32[1] = cpu_to_le32(UBIFS_INO_KEY << UBIFS_S_KEY_BLOCK_BITS); -++ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8); -++} -++ -++/** -++ * lowest_ino_key - get the lowest possible inode key. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: inode number -++ */ -++static inline void lowest_ino_key(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum) -++{ -++ key->u32[0] = inum; -++ key->u32[1] = 0; -++} -++ -++/** -++ * highest_ino_key - get the highest possible inode key. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: inode number -++ */ -++static inline void highest_ino_key(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum) -++{ -++ key->u32[0] = inum; -++ key->u32[1] = 0xffffffff; -++} -++ -++/** -++ * dent_key_init - initialize directory entry key. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: parent inode number -++ * @nm: direntry name and length -++ */ -++static inline void dent_key_init(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum, -++ const struct qstr *nm) -++{ -++ uint32_t hash = c->key_hash(nm->name, nm->len); -++ -++ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK)); -++ key->u32[0] = inum; -++ key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS); -++} -++ -++/** -++ * dent_key_init_hash - initialize directory entry key without re-calculating -++ * hash function. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: parent inode number -++ * @hash: direntry name hash -++ */ -++static inline void dent_key_init_hash(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum, -++ uint32_t hash) -++{ -++ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK)); -++ key->u32[0] = inum; -++ key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS); -++} -++ -++/** -++ * dent_key_init_flash - initialize on-flash directory entry key. -++ * @c: UBIFS file-system description object -++ * @k: key to initialize -++ * @inum: parent inode number -++ * @nm: direntry name and length -++ */ -++static inline void dent_key_init_flash(const struct ubifs_info *c, void *k, -++ ino_t inum, const struct qstr *nm) -++{ -++ union ubifs_key *key = k; -++ uint32_t hash = c->key_hash(nm->name, nm->len); -++ -++ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK)); -++ key->j32[0] = cpu_to_le32(inum); -++ key->j32[1] = cpu_to_le32(hash | -++ (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS)); -++ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8); -++} -++ -++/** -++ * lowest_dent_key - get the lowest possible directory entry key. -++ * @c: UBIFS file-system description object -++ * @key: where to store the lowest key -++ * @inum: parent inode number -++ */ -++static inline void lowest_dent_key(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum) -++{ -++ key->u32[0] = inum; -++ key->u32[1] = UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS; -++} -++ -++/** -++ * xent_key_init - initialize extended attribute entry key. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: host inode number -++ * @nm: extended attribute entry name and length -++ */ -++static inline void xent_key_init(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum, -++ const struct qstr *nm) -++{ -++ uint32_t hash = c->key_hash(nm->name, nm->len); -++ -++ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK)); -++ key->u32[0] = inum; -++ key->u32[1] = hash | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS); -++} -++ -++/** -++ * xent_key_init_hash - initialize extended attribute entry key without -++ * re-calculating hash function. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: host inode number -++ * @hash: extended attribute entry name hash -++ */ -++static inline void xent_key_init_hash(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum, -++ uint32_t hash) -++{ -++ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK)); -++ key->u32[0] = inum; -++ key->u32[1] = hash | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS); -++} -++ -++/** -++ * xent_key_init_flash - initialize on-flash extended attribute entry key. -++ * @c: UBIFS file-system description object -++ * @k: key to initialize -++ * @inum: host inode number -++ * @nm: extended attribute entry name and length -++ */ -++static inline void xent_key_init_flash(const struct ubifs_info *c, void *k, -++ ino_t inum, const struct qstr *nm) -++{ -++ union ubifs_key *key = k; -++ uint32_t hash = c->key_hash(nm->name, nm->len); -++ -++ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK)); -++ key->j32[0] = cpu_to_le32(inum); -++ key->j32[1] = cpu_to_le32(hash | -++ (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS)); -++ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8); -++} -++ -++/** -++ * lowest_xent_key - get the lowest possible extended attribute entry key. -++ * @c: UBIFS file-system description object -++ * @key: where to store the lowest key -++ * @inum: host inode number -++ */ -++static inline void lowest_xent_key(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum) -++{ -++ key->u32[0] = inum; -++ key->u32[1] = UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS; -++} -++ -++/** -++ * data_key_init - initialize data key. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: inode number -++ * @block: block number -++ */ -++static inline void data_key_init(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum, -++ unsigned int block) -++{ -++ ubifs_assert(!(block & ~UBIFS_S_KEY_BLOCK_MASK)); -++ key->u32[0] = inum; -++ key->u32[1] = block | (UBIFS_DATA_KEY << UBIFS_S_KEY_BLOCK_BITS); -++} -++ -++/** -++ * data_key_init_flash - initialize on-flash data key. -++ * @c: UBIFS file-system description object -++ * @k: key to initialize -++ * @inum: inode number -++ * @block: block number -++ */ -++static inline void data_key_init_flash(const struct ubifs_info *c, void *k, -++ ino_t inum, unsigned int block) -++{ -++ union ubifs_key *key = k; -++ -++ ubifs_assert(!(block & ~UBIFS_S_KEY_BLOCK_MASK)); -++ key->j32[0] = cpu_to_le32(inum); -++ key->j32[1] = cpu_to_le32(block | -++ (UBIFS_DATA_KEY << UBIFS_S_KEY_BLOCK_BITS)); -++ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8); -++} -++ -++/** -++ * trun_key_init - initialize truncation node key. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: inode number -++ */ -++static inline void trun_key_init(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum) -++{ -++ key->u32[0] = inum; -++ key->u32[1] = UBIFS_TRUN_KEY << UBIFS_S_KEY_BLOCK_BITS; -++} -++ -++/** -++ * trun_key_init_flash - initialize on-flash truncation node key. -++ * @c: UBIFS file-system description object -++ * @k: key to initialize -++ * @inum: inode number -++ */ -++static inline void trun_key_init_flash(const struct ubifs_info *c, void *k, -++ ino_t inum) -++{ -++ union ubifs_key *key = k; -++ -++ key->j32[0] = cpu_to_le32(inum); -++ key->j32[1] = cpu_to_le32(UBIFS_TRUN_KEY << UBIFS_S_KEY_BLOCK_BITS); -++ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8); -++} -++ -++/** -++ * key_type - get key type. -++ * @c: UBIFS file-system description object -++ * @key: key to get type of -++ */ -++static inline int key_type(const struct ubifs_info *c, -++ const union ubifs_key *key) -++{ -++ return key->u32[1] >> UBIFS_S_KEY_BLOCK_BITS; -++} -++ -++/** -++ * key_type_flash - get type of a on-flash formatted key. -++ * @c: UBIFS file-system description object -++ * @k: key to get type of -++ */ -++static inline int key_type_flash(const struct ubifs_info *c, const void *k) -++{ -++ const union ubifs_key *key = k; -++ -++ return le32_to_cpu(key->u32[1]) >> UBIFS_S_KEY_BLOCK_BITS; -++} -++ -++/** -++ * key_ino - fetch inode number from key. -++ * @c: UBIFS file-system description object -++ * @k: key to fetch inode number from -++ */ -++static inline ino_t key_ino(const struct ubifs_info *c, const void *k) -++{ -++ const union ubifs_key *key = k; -++ -++ return key->u32[0]; -++} -++ -++/** -++ * key_ino_flash - fetch inode number from an on-flash formatted key. -++ * @c: UBIFS file-system description object -++ * @k: key to fetch inode number from -++ */ -++static inline ino_t key_ino_flash(const struct ubifs_info *c, const void *k) -++{ -++ const union ubifs_key *key = k; -++ -++ return le32_to_cpu(key->j32[0]); -++} -++ -++/** -++ * key_hash - get directory entry hash. -++ * @c: UBIFS file-system description object -++ * @key: the key to get hash from -++ */ -++static inline int key_hash(const struct ubifs_info *c, -++ const union ubifs_key *key) -++{ -++ return key->u32[1] & UBIFS_S_KEY_HASH_MASK; -++} -++ -++/** -++ * key_hash_flash - get directory entry hash from an on-flash formatted key. -++ * @c: UBIFS file-system description object -++ * @k: the key to get hash from -++ */ -++static inline int key_hash_flash(const struct ubifs_info *c, const void *k) -++{ -++ const union ubifs_key *key = k; -++ -++ return le32_to_cpu(key->j32[1]) & UBIFS_S_KEY_HASH_MASK; -++} -++ -++/** -++ * key_block - get data block number. -++ * @c: UBIFS file-system description object -++ * @key: the key to get the block number from -++ */ -++static inline unsigned int key_block(const struct ubifs_info *c, -++ const union ubifs_key *key) -++{ -++ return key->u32[1] & UBIFS_S_KEY_BLOCK_MASK; -++} -++ -++/** -++ * key_read - transform a key to in-memory format. -++ * @c: UBIFS file-system description object -++ * @from: the key to transform -++ * @to: the key to store the result -++ */ -++static inline void key_read(const struct ubifs_info *c, const void *from, -++ union ubifs_key *to) -++{ -++ const union ubifs_key *f = from; -++ -++ to->u32[0] = le32_to_cpu(f->j32[0]); -++ to->u32[1] = le32_to_cpu(f->j32[1]); -++} -++ -++/** -++ * key_write - transform a key from in-memory format. -++ * @c: UBIFS file-system description object -++ * @from: the key to transform -++ * @to: the key to store the result -++ */ -++static inline void key_write(const struct ubifs_info *c, -++ const union ubifs_key *from, void *to) -++{ -++ union ubifs_key *t = to; -++ -++ t->j32[0] = cpu_to_le32(from->u32[0]); -++ t->j32[1] = cpu_to_le32(from->u32[1]); -++ memset(to + 8, 0, UBIFS_MAX_KEY_LEN - 8); -++} -++ -++/** -++ * key_write_idx - transform a key from in-memory format for the index. -++ * @c: UBIFS file-system description object -++ * @from: the key to transform -++ * @to: the key to store the result -++ */ -++static inline void key_write_idx(const struct ubifs_info *c, -++ const union ubifs_key *from, void *to) -++{ -++ union ubifs_key *t = to; -++ -++ t->j32[0] = cpu_to_le32(from->u32[0]); -++ t->j32[1] = cpu_to_le32(from->u32[1]); -++} -++ -++/** -++ * key_copy - copy a key. -++ * @c: UBIFS file-system description object -++ * @from: the key to copy from -++ * @to: the key to copy to -++ */ -++static inline void key_copy(const struct ubifs_info *c, -++ const union ubifs_key *from, union ubifs_key *to) -++{ -++ to->u64[0] = from->u64[0]; -++} -++ -++/** -++ * keys_cmp - compare keys. -++ * @c: UBIFS file-system description object -++ * @key1: the first key to compare -++ * @key2: the second key to compare -++ * -++ * This function compares 2 keys and returns %-1 if @key1 is less than -++ * @key2, 0 if the keys are equivalent and %1 if @key1 is greater than @key2. -++ */ -++static inline int keys_cmp(const struct ubifs_info *c, -++ const union ubifs_key *key1, -++ const union ubifs_key *key2) -++{ -++ if (key1->u32[0] < key2->u32[0]) -++ return -1; -++ if (key1->u32[0] > key2->u32[0]) -++ return 1; -++ if (key1->u32[1] < key2->u32[1]) -++ return -1; -++ if (key1->u32[1] > key2->u32[1]) -++ return 1; -++ -++ return 0; -++} -++ -++/** -++ * is_hash_key - is a key vulnerable to hash collisions. -++ * @c: UBIFS file-system description object -++ * @key: key -++ * -++ * This function returns %1 if @key is a hashed key or %0 otherwise. -++ */ -++static inline int is_hash_key(const struct ubifs_info *c, -++ const union ubifs_key *key) -++{ -++ int type = key_type(c, key); -++ -++ return type == UBIFS_DENT_KEY || type == UBIFS_XENT_KEY; -++} -++ -++/** -++ * key_max_inode_size - get maximum file size allowed by current key format. -++ * @c: UBIFS file-system description object -++ */ -++static inline unsigned long long key_max_inode_size(const struct ubifs_info *c) -++{ -++ switch (c->key_fmt) { -++ case UBIFS_SIMPLE_KEY_FMT: -++ return (1ULL << UBIFS_S_KEY_BLOCK_BITS) * UBIFS_BLOCK_SIZE; -++ default: -++ return 0; -++ } -++} -++#endif /* !__UBIFS_KEY_H__ */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/log.c linux-2.6.24.7/fs/ubifs/log.c -+--- linux-2.6.24.7.old/fs/ubifs/log.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/log.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,803 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* -++ * This file is a part of UBIFS journal implementation and contains various -++ * functions which manipulate the log. The log is a fixed area on the flash -++ * which does not contain any data but refers to buds. The log is a part of the -++ * journal. -++ */ -++ -++#include "ubifs.h" -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++static int dbg_check_bud_bytes(struct ubifs_info *c); -++#else -++#define dbg_check_bud_bytes(c) 0 -++#endif -++ -++/** -++ * ubifs_search_bud - search bud LEB. -++ * @c: UBIFS file-system description object -++ * @lnum: logical eraseblock number to search -++ * -++ * This function searches bud LEB @lnum. Returns bud description object in case -++ * of success and %NULL if there is no bud with this LEB number. -++ */ -++struct ubifs_bud *ubifs_search_bud(struct ubifs_info *c, int lnum) -++{ -++ struct rb_node *p; -++ struct ubifs_bud *bud; -++ -++ spin_lock(&c->buds_lock); -++ p = c->buds.rb_node; -++ while (p) { -++ bud = rb_entry(p, struct ubifs_bud, rb); -++ if (lnum < bud->lnum) -++ p = p->rb_left; -++ else if (lnum > bud->lnum) -++ p = p->rb_right; -++ else { -++ spin_unlock(&c->buds_lock); -++ return bud; -++ } -++ } -++ spin_unlock(&c->buds_lock); -++ return NULL; -++} -++ -++/** -++ * ubifs_get_wbuf - get the wbuf associated with a LEB, if there is one. -++ * @c: UBIFS file-system description object -++ * @lnum: logical eraseblock number to search -++ * -++ * This functions returns the wbuf for @lnum or %NULL if there is not one. -++ */ -++struct ubifs_wbuf *ubifs_get_wbuf(struct ubifs_info *c, int lnum) -++{ -++ struct rb_node *p; -++ struct ubifs_bud *bud; -++ int jhead; -++ -++ if (!c->jheads) -++ return NULL; -++ -++ spin_lock(&c->buds_lock); -++ p = c->buds.rb_node; -++ while (p) { -++ bud = rb_entry(p, struct ubifs_bud, rb); -++ if (lnum < bud->lnum) -++ p = p->rb_left; -++ else if (lnum > bud->lnum) -++ p = p->rb_right; -++ else { -++ jhead = bud->jhead; -++ spin_unlock(&c->buds_lock); -++ return &c->jheads[jhead].wbuf; -++ } -++ } -++ spin_unlock(&c->buds_lock); -++ return NULL; -++} -++ -++/** -++ * next_log_lnum - switch to the next log LEB. -++ * @c: UBIFS file-system description object -++ * @lnum: current log LEB -++ */ -++static inline int next_log_lnum(const struct ubifs_info *c, int lnum) -++{ -++ lnum += 1; -++ if (lnum > c->log_last) -++ lnum = UBIFS_LOG_LNUM; -++ -++ return lnum; -++} -++ -++/** -++ * empty_log_bytes - calculate amount of empty space in the log. -++ * @c: UBIFS file-system description object -++ */ -++static inline long long empty_log_bytes(const struct ubifs_info *c) -++{ -++ long long h, t; -++ -++ h = c->lhead_lnum * c->leb_size + c->lhead_offs; -++ t = c->ltail_lnum * c->leb_size; -++ -++ if (h >= t) -++ return c->log_bytes - h + t; -++ else -++ return t - h; -++} -++ -++/** -++ * ubifs_add_bud - add bud LEB to the tree of buds and its journal head list. -++ * @c: UBIFS file-system description object -++ * @bud: the bud to add -++ */ -++void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud) -++{ -++ struct rb_node **p, *parent = NULL; -++ struct ubifs_bud *b; -++ struct ubifs_jhead *jhead; -++ -++ spin_lock(&c->buds_lock); -++ p = &c->buds.rb_node; -++ while (*p) { -++ parent = *p; -++ b = rb_entry(parent, struct ubifs_bud, rb); -++ ubifs_assert(bud->lnum != b->lnum); -++ if (bud->lnum < b->lnum) -++ p = &(*p)->rb_left; -++ else -++ p = &(*p)->rb_right; -++ } -++ -++ rb_link_node(&bud->rb, parent, p); -++ rb_insert_color(&bud->rb, &c->buds); -++ if (c->jheads) { -++ jhead = &c->jheads[bud->jhead]; -++ list_add_tail(&bud->list, &jhead->buds_list); -++ } else -++ ubifs_assert(c->replaying && (c->vfs_sb->s_flags & MS_RDONLY)); -++ -++ /* -++ * Note, although this is a new bud, we anyway account this space now, -++ * before any data has been written to it, because this is about to -++ * guarantee fixed mount time, and this bud will anyway be read and -++ * scanned. -++ */ -++ c->bud_bytes += c->leb_size - bud->start; -++ -++ dbg_log("LEB %d:%d, jhead %d, bud_bytes %lld", bud->lnum, -++ bud->start, bud->jhead, c->bud_bytes); -++ spin_unlock(&c->buds_lock); -++} -++ -++/** -++ * ubifs_create_buds_lists - create journal head buds lists for remount rw. -++ * @c: UBIFS file-system description object -++ */ -++void ubifs_create_buds_lists(struct ubifs_info *c) -++{ -++ struct rb_node *p; -++ -++ spin_lock(&c->buds_lock); -++ p = rb_first(&c->buds); -++ while (p) { -++ struct ubifs_bud *bud = rb_entry(p, struct ubifs_bud, rb); -++ struct ubifs_jhead *jhead = &c->jheads[bud->jhead]; -++ -++ list_add_tail(&bud->list, &jhead->buds_list); -++ p = rb_next(p); -++ } -++ spin_unlock(&c->buds_lock); -++} -++ -++/** -++ * ubifs_add_bud_to_log - add a new bud to the log. -++ * @c: UBIFS file-system description object -++ * @jhead: journal head the bud belongs to -++ * @lnum: LEB number of the bud -++ * @offs: starting offset of the bud -++ * -++ * This function writes reference node for the new bud LEB @lnum it to the log, -++ * and adds it to the buds tress. It also makes sure that log size does not -++ * exceed the 'c->max_bud_bytes' limit. Returns zero in case of success, -++ * %-EAGAIN if commit is required, and a negative error codes in case of -++ * failure. -++ */ -++int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs) -++{ -++ int err; -++ struct ubifs_bud *bud; -++ struct ubifs_ref_node *ref; -++ -++ bud = kmalloc(sizeof(struct ubifs_bud), GFP_NOFS); -++ if (!bud) -++ return -ENOMEM; -++ ref = kzalloc(c->ref_node_alsz, GFP_NOFS); -++ if (!ref) { -++ kfree(bud); -++ return -ENOMEM; -++ } -++ -++ mutex_lock(&c->log_mutex); -++ /* Make sure we have enough space in the log */ -++ if (empty_log_bytes(c) - c->ref_node_alsz < c->min_log_bytes) { -++ dbg_log("not enough log space - %lld, required %d", -++ empty_log_bytes(c), c->min_log_bytes); -++ ubifs_commit_required(c); -++ err = -EAGAIN; -++ goto out_unlock; -++ } -++ -++ /* -++ * Make sure the the amount of space in buds will not exceed -++ * 'c->max_bud_bytes' limit, because we want to guarantee mount time -++ * limits. -++ * -++ * It is not necessary to hold @c->buds_lock when reading @c->bud_bytes -++ * because we are holding @c->log_mutex. All @c->bud_bytes take place -++ * when both @c->log_mutex and @c->bud_bytes are locked. -++ */ -++ if (c->bud_bytes + c->leb_size - offs > c->max_bud_bytes) { -++ dbg_log("bud bytes %lld (%lld max), require commit", -++ c->bud_bytes, c->max_bud_bytes); -++ ubifs_commit_required(c); -++ err = -EAGAIN; -++ goto out_unlock; -++ } -++ -++ /* -++ * If the journal is full enough - start background commit. Note, it is -++ * OK to read 'c->cmt_state' without spinlock because integer reads -++ * are atomic in the kernel. -++ */ -++ if (c->bud_bytes >= c->bg_bud_bytes && -++ c->cmt_state == COMMIT_RESTING) { -++ dbg_log("bud bytes %lld (%lld max), initiate BG commit", -++ c->bud_bytes, c->max_bud_bytes); -++ ubifs_request_bg_commit(c); -++ } -++ -++ bud->lnum = lnum; -++ bud->start = offs; -++ bud->jhead = jhead; -++ -++ ref->ch.node_type = UBIFS_REF_NODE; -++ ref->lnum = cpu_to_le32(bud->lnum); -++ ref->offs = cpu_to_le32(bud->start); -++ ref->jhead = cpu_to_le32(jhead); -++ -++ if (c->lhead_offs > c->leb_size - c->ref_node_alsz) { -++ c->lhead_lnum = next_log_lnum(c, c->lhead_lnum); -++ c->lhead_offs = 0; -++ } -++ -++ if (c->lhead_offs == 0) { -++ /* Must ensure next log LEB has been unmapped */ -++ err = ubifs_leb_unmap(c, c->lhead_lnum); -++ if (err) -++ goto out_unlock; -++ } -++ -++ if (bud->start == 0) { -++ /* -++ * Before writing the LEB reference which refers an empty LEB -++ * to the log, we have to make sure it is mapped, because -++ * otherwise we'd risk to refer an LEB with garbage in case of -++ * an unclean reboot, because the target LEB might have been -++ * unmapped, but not yet physically erased. -++ */ -++ err = ubi_leb_map(c->ubi, bud->lnum, UBI_SHORTTERM); -++ if (err) -++ goto out_unlock; -++ } -++ -++ dbg_log("write ref LEB %d:%d", -++ c->lhead_lnum, c->lhead_offs); -++ err = ubifs_write_node(c, ref, UBIFS_REF_NODE_SZ, c->lhead_lnum, -++ c->lhead_offs, UBI_SHORTTERM); -++ c->lhead_offs += c->ref_node_alsz; -++ if (err) -++ goto out_unlock; -++ -++ ubifs_add_bud(c, bud); -++ -++ mutex_unlock(&c->log_mutex); -++ kfree(ref); -++ return 0; -++ -++out_unlock: -++ mutex_unlock(&c->log_mutex); -++ kfree(ref); -++ kfree(bud); -++ return err; -++} -++ -++/** -++ * remove_buds - remove used buds. -++ * @c: UBIFS file-system description object -++ * -++ * This function removes use buds from the buds tree. It does not remove the -++ * buds which are pointed to by journal heads. -++ */ -++static void remove_buds(struct ubifs_info *c) -++{ -++ struct rb_node *p; -++ -++ ubifs_assert(list_empty(&c->old_buds)); -++ c->cmt_bud_bytes = 0; -++ spin_lock(&c->buds_lock); -++ p = rb_first(&c->buds); -++ while (p) { -++ struct rb_node *p1 = p; -++ struct ubifs_bud *bud; -++ struct ubifs_wbuf *wbuf; -++ -++ p = rb_next(p); -++ bud = rb_entry(p1, struct ubifs_bud, rb); -++ wbuf = &c->jheads[bud->jhead].wbuf; -++ -++ if (wbuf->lnum == bud->lnum) { -++ /* -++ * Do not remove buds which are pointed to by journal -++ * heads (non-closed buds). -++ */ -++ c->cmt_bud_bytes += wbuf->offs - bud->start; -++ dbg_log("preserve %d:%d, jhead %d, bud bytes %d, " -++ "cmt_bud_bytes %lld", bud->lnum, bud->start, -++ bud->jhead, wbuf->offs - bud->start, -++ c->cmt_bud_bytes); -++ bud->start = wbuf->offs; -++ } else { -++ c->cmt_bud_bytes += c->leb_size - bud->start; -++ dbg_log("remove %d:%d, jhead %d, bud bytes %d, " -++ "cmt_bud_bytes %lld", bud->lnum, bud->start, -++ bud->jhead, c->leb_size - bud->start, -++ c->cmt_bud_bytes); -++ rb_erase(p1, &c->buds); -++ list_del(&bud->list); -++ /* -++ * If the commit does not finish, the recovery will need -++ * to replay the journal, in which case the old buds -++ * must be unchanged. Do not release them until post -++ * commit i.e. do not allow them to be garbage -++ * collected. -++ */ -++ list_add(&bud->list, &c->old_buds); -++ } -++ } -++ spin_unlock(&c->buds_lock); -++} -++ -++/** -++ * ubifs_log_start_commit - start commit. -++ * @c: UBIFS file-system description object -++ * @ltail_lnum: return new log tail LEB number -++ * -++ * The commit operation starts with writing "commit start" node to the log and -++ * reference nodes for all journal heads which will define new journal after -++ * the commit has been finished. The commit start and reference nodes are -++ * written in one go to the nearest empty log LEB (hence, when commit is -++ * finished UBIFS may safely unmap all the previous log LEBs). This function -++ * returns zero in case of success and a negative error code in case of -++ * failure. -++ */ -++int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum) -++{ -++ void *buf; -++ struct ubifs_cs_node *cs; -++ struct ubifs_ref_node *ref; -++ int err, i, max_len, len; -++ -++ err = dbg_check_bud_bytes(c); -++ if (err) -++ return err; -++ -++ max_len = UBIFS_CS_NODE_SZ + c->jhead_cnt * UBIFS_REF_NODE_SZ; -++ max_len = ALIGN(max_len, c->min_io_size); -++ buf = cs = kmalloc(max_len, GFP_NOFS); -++ if (!buf) -++ return -ENOMEM; -++ -++ cs->ch.node_type = UBIFS_CS_NODE; -++ cs->cmt_no = cpu_to_le64(c->cmt_no + 1); -++ ubifs_prepare_node(c, cs, UBIFS_CS_NODE_SZ, 0); -++ -++ /* -++ * Note, we do not lock 'c->log_mutex' because this is the commit start -++ * phase and we are exclusively using the log. And we do not lock -++ * write-buffer because nobody can write to the file-system at this -++ * phase. -++ */ -++ -++ len = UBIFS_CS_NODE_SZ; -++ for (i = 0; i < c->jhead_cnt; i++) { -++ int lnum = c->jheads[i].wbuf.lnum; -++ int offs = c->jheads[i].wbuf.offs; -++ -++ if (lnum == -1 || offs == c->leb_size) -++ continue; -++ -++ dbg_log("add ref to LEB %d:%d for jhead %d", lnum, offs, i); -++ ref = buf + len; -++ ref->ch.node_type = UBIFS_REF_NODE; -++ ref->lnum = cpu_to_le32(lnum); -++ ref->offs = cpu_to_le32(offs); -++ ref->jhead = cpu_to_le32(i); -++ -++ ubifs_prepare_node(c, ref, UBIFS_REF_NODE_SZ, 0); -++ len += UBIFS_REF_NODE_SZ; -++ } -++ -++ ubifs_pad(c, buf + len, ALIGN(len, c->min_io_size) - len); -++ -++ /* Switch to the next log LEB */ -++ if (c->lhead_offs) { -++ c->lhead_lnum = next_log_lnum(c, c->lhead_lnum); -++ c->lhead_offs = 0; -++ } -++ -++ if (c->lhead_offs == 0) { -++ /* Must ensure next LEB has been unmapped */ -++ err = ubifs_leb_unmap(c, c->lhead_lnum); -++ if (err) -++ goto out; -++ } -++ -++ len = ALIGN(len, c->min_io_size); -++ dbg_log("writing commit start at LEB %d:0, len %d", c->lhead_lnum, len); -++ err = ubifs_leb_write(c, c->lhead_lnum, cs, 0, len, UBI_SHORTTERM); -++ if (err) -++ goto out; -++ -++ *ltail_lnum = c->lhead_lnum; -++ -++ c->lhead_offs += len; -++ if (c->lhead_offs == c->leb_size) { -++ c->lhead_lnum = next_log_lnum(c, c->lhead_lnum); -++ c->lhead_offs = 0; -++ } -++ -++ remove_buds(c); -++ -++ /* -++ * We have started the commit and now users may use the rest of the log -++ * for new writes. -++ */ -++ c->min_log_bytes = 0; -++ -++out: -++ kfree(buf); -++ return err; -++} -++ -++/** -++ * ubifs_log_end_commit - end commit. -++ * @c: UBIFS file-system description object -++ * @ltail_lnum: new log tail LEB number -++ * -++ * This function is called on when the commit operation was finished. It -++ * moves log tail to new position and unmaps LEBs which contain obsolete data. -++ * Returns zero in case of success and a negative error code in case of -++ * failure. -++ */ -++int ubifs_log_end_commit(struct ubifs_info *c, int ltail_lnum) -++{ -++ int err; -++ -++ /* -++ * At this phase we have to lock 'c->log_mutex' because UBIFS allows FS -++ * writes during commit. Its only short "commit" start phase when -++ * writers are blocked. -++ */ -++ mutex_lock(&c->log_mutex); -++ -++ dbg_log("old tail was LEB %d:0, new tail is LEB %d:0", -++ c->ltail_lnum, ltail_lnum); -++ -++ c->ltail_lnum = ltail_lnum; -++ /* -++ * The commit is finished and from now on it must be guaranteed that -++ * there is always enough space for the next commit. -++ */ -++ c->min_log_bytes = c->leb_size; -++ -++ spin_lock(&c->buds_lock); -++ c->bud_bytes -= c->cmt_bud_bytes; -++ spin_unlock(&c->buds_lock); -++ -++ err = dbg_check_bud_bytes(c); -++ -++ mutex_unlock(&c->log_mutex); -++ return err; -++} -++ -++/** -++ * ubifs_log_post_commit - things to do after commit is completed. -++ * @c: UBIFS file-system description object -++ * @old_ltail_lnum: old log tail LEB number -++ * -++ * Release buds only after commit is completed, because they must be unchanged -++ * if recovery is needed. -++ * -++ * Unmap log LEBs only after commit is completed, because they may be needed for -++ * recovery. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_log_post_commit(struct ubifs_info *c, int old_ltail_lnum) -++{ -++ int lnum, err = 0; -++ -++ while (!list_empty(&c->old_buds)) { -++ struct ubifs_bud *bud; -++ -++ bud = list_entry(c->old_buds.next, struct ubifs_bud, list); -++ err = ubifs_return_leb(c, bud->lnum); -++ if (err) -++ return err; -++ list_del(&bud->list); -++ kfree(bud); -++ } -++ mutex_lock(&c->log_mutex); -++ for (lnum = old_ltail_lnum; lnum != c->ltail_lnum; -++ lnum = next_log_lnum(c, lnum)) { -++ dbg_log("unmap log LEB %d", lnum); -++ err = ubifs_leb_unmap(c, lnum); -++ if (err) -++ goto out; -++ } -++out: -++ mutex_unlock(&c->log_mutex); -++ return err; -++} -++ -++/** -++ * struct done_ref - references that have been done. -++ * @rb: rb-tree node -++ * @lnum: LEB number -++ */ -++struct done_ref { -++ struct rb_node rb; -++ int lnum; -++}; -++ -++/** -++ * done_already - determine if a reference has been done already. -++ * @done_tree: rb-tree to store references that have been done -++ * @lnum: LEB number of reference -++ * -++ * This function returns %1 if the reference has been done, %0 if not, otherwise -++ * a negative error code is returned. -++ */ -++static int done_already(struct rb_root *done_tree, int lnum) -++{ -++ struct rb_node **p = &done_tree->rb_node, *parent = NULL; -++ struct done_ref *dr; -++ -++ while (*p) { -++ parent = *p; -++ dr = rb_entry(parent, struct done_ref, rb); -++ if (lnum < dr->lnum) -++ p = &(*p)->rb_left; -++ else if (lnum > dr->lnum) -++ p = &(*p)->rb_right; -++ else -++ return 1; -++ } -++ -++ dr = kzalloc(sizeof(struct done_ref), GFP_NOFS); -++ if (!dr) -++ return -ENOMEM; -++ -++ dr->lnum = lnum; -++ -++ rb_link_node(&dr->rb, parent, p); -++ rb_insert_color(&dr->rb, done_tree); -++ -++ return 0; -++} -++ -++/** -++ * destroy_done_tree - destroy the done tree. -++ * @done_tree: done tree to destroy -++ */ -++static void destroy_done_tree(struct rb_root *done_tree) -++{ -++ struct rb_node *this = done_tree->rb_node; -++ struct done_ref *dr; -++ -++ while (this) { -++ if (this->rb_left) { -++ this = this->rb_left; -++ continue; -++ } else if (this->rb_right) { -++ this = this->rb_right; -++ continue; -++ } -++ dr = rb_entry(this, struct done_ref, rb); -++ this = rb_parent(this); -++ if (this) { -++ if (this->rb_left == &dr->rb) -++ this->rb_left = NULL; -++ else -++ this->rb_right = NULL; -++ } -++ kfree(dr); -++ } -++} -++ -++/** -++ * add_node - add a node to the consolidated log. -++ * @c: UBIFS file-system description object -++ * @buf: buffer to which to add -++ * @lnum: LEB number to which to write is passed and returned here -++ * @offs: offset to where to write is passed and returned here -++ * @node: node to add -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int add_node(struct ubifs_info *c, void *buf, int *lnum, int *offs, -++ void *node) -++{ -++ struct ubifs_ch *ch = node; -++ int len = le32_to_cpu(ch->len), remains = c->leb_size - *offs; -++ -++ if (len > remains) { -++ int sz = ALIGN(*offs, c->min_io_size), err; -++ -++ ubifs_pad(c, buf + *offs, sz - *offs); -++ err = ubi_leb_change(c->ubi, *lnum, buf, sz, UBI_SHORTTERM); -++ if (err) -++ return err; -++ *lnum = next_log_lnum(c, *lnum); -++ *offs = 0; -++ } -++ memcpy(buf + *offs, node, len); -++ *offs += ALIGN(len, 8); -++ return 0; -++} -++ -++/** -++ * ubifs_consolidate_log - consolidate the log. -++ * @c: UBIFS file-system description object -++ * -++ * Repeated failed commits could cause the log to be full, but at least 1 LEB is -++ * needed for commit. This function rewrites the reference nodes in the log -++ * omitting duplicates, and failed CS nodes, and leaving no gaps. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_consolidate_log(struct ubifs_info *c) -++{ -++ struct ubifs_scan_leb *sleb; -++ struct ubifs_scan_node *snod; -++ struct rb_root done_tree = RB_ROOT; -++ int lnum, err, first = 1, write_lnum, offs = 0; -++ void *buf; -++ -++ dbg_rcvry("log tail LEB %d, log head LEB %d", c->ltail_lnum, -++ c->lhead_lnum); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ buf = kmalloc(c->leb_size, GFP_KERNEL); -++#else -++ buf = vmalloc(c->leb_size); -++#endif -++ if (!buf) -++ return -ENOMEM; -++ lnum = c->ltail_lnum; -++ write_lnum = lnum; -++ while (1) { -++ sleb = ubifs_scan(c, lnum, 0, c->sbuf); -++ if (IS_ERR(sleb)) { -++ err = PTR_ERR(sleb); -++ goto out_free; -++ } -++ list_for_each_entry(snod, &sleb->nodes, list) { -++ switch (snod->type) { -++ case UBIFS_REF_NODE: { -++ struct ubifs_ref_node *ref = snod->node; -++ int ref_lnum = le32_to_cpu(ref->lnum); -++ -++ err = done_already(&done_tree, ref_lnum); -++ if (err < 0) -++ goto out_scan; -++ if (err != 1) { -++ err = add_node(c, buf, &write_lnum, -++ &offs, snod->node); -++ if (err) -++ goto out_scan; -++ } -++ break; -++ } -++ case UBIFS_CS_NODE: -++ if (!first) -++ break; -++ err = add_node(c, buf, &write_lnum, &offs, -++ snod->node); -++ if (err) -++ goto out_scan; -++ first = 0; -++ break; -++ } -++ } -++ ubifs_scan_destroy(sleb); -++ if (lnum == c->lhead_lnum) -++ break; -++ lnum = next_log_lnum(c, lnum); -++ } -++ if (offs) { -++ int sz = ALIGN(offs, c->min_io_size); -++ -++ ubifs_pad(c, buf + offs, sz - offs); -++ err = ubi_leb_change(c->ubi, write_lnum, buf, sz, -++ UBI_SHORTTERM); -++ if (err) -++ goto out_free; -++ offs = ALIGN(offs, c->min_io_size); -++ } -++ destroy_done_tree(&done_tree); -++ vfree(buf); -++ if (write_lnum == c->lhead_lnum) { -++ ubifs_err("log is too full"); -++ return -EINVAL; -++ } -++ /* Unmap remaining LEBs */ -++ lnum = write_lnum; -++ do { -++ lnum = next_log_lnum(c, lnum); -++ err = ubifs_leb_unmap(c, lnum); -++ if (err) -++ return err; -++ } while (lnum != c->lhead_lnum); -++ c->lhead_lnum = write_lnum; -++ c->lhead_offs = offs; -++ dbg_rcvry("new log head at %d:%d", c->lhead_lnum, c->lhead_offs); -++ return 0; -++ -++out_scan: -++ ubifs_scan_destroy(sleb); -++out_free: -++ destroy_done_tree(&done_tree); -++ vfree(buf); -++ return err; -++} -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ -++/** -++ * dbg_check_bud_bytes - make sure bud bytes calculation are all right. -++ * @c: UBIFS file-system description object -++ * -++ * This function makes sure the amount of flash space used by closed buds -++ * ('c->bud_bytes' is correct). Returns zero in case of success and %-EINVAL in -++ * case of failure. -++ */ -++static int dbg_check_bud_bytes(struct ubifs_info *c) -++{ -++ int i, err = 0; -++ struct ubifs_bud *bud; -++ long long bud_bytes = 0; -++ -++ if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) -++ return 0; -++ -++ spin_lock(&c->buds_lock); -++ for (i = 0; i < c->jhead_cnt; i++) -++ list_for_each_entry(bud, &c->jheads[i].buds_list, list) -++ bud_bytes += c->leb_size - bud->start; -++ -++ if (c->bud_bytes != bud_bytes) { -++ ubifs_err("bad bud_bytes %lld, calculated %lld", -++ c->bud_bytes, bud_bytes); -++ err = -EINVAL; -++ } -++ spin_unlock(&c->buds_lock); -++ -++ return err; -++} -++ -++#endif /* CONFIG_UBIFS_FS_DEBUG */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/lprops.c linux-2.6.24.7/fs/ubifs/lprops.c -+--- linux-2.6.24.7.old/fs/ubifs/lprops.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/lprops.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1353 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Adrian Hunter -++ * Artem Bityutskiy (Битюцкий Ðртём) -++ */ -++ -++/* -++ * This file implements the functions that access LEB properties and their -++ * categories. LEBs are categorized based on the needs of UBIFS, and the -++ * categories are stored as either heaps or lists to provide a fast way of -++ * finding a LEB in a particular category. For example, UBIFS may need to find -++ * an empty LEB for the journal, or a very dirty LEB for garbage collection. -++ */ -++ -++#include "ubifs.h" -++ -++/** -++ * get_heap_comp_val - get the LEB properties value for heap comparisons. -++ * @lprops: LEB properties -++ * @cat: LEB category -++ */ -++static int get_heap_comp_val(struct ubifs_lprops *lprops, int cat) -++{ -++ switch (cat) { -++ case LPROPS_FREE: -++ return lprops->free; -++ case LPROPS_DIRTY_IDX: -++ return lprops->free + lprops->dirty; -++ default: -++ return lprops->dirty; -++ } -++} -++ -++/** -++ * move_up_lpt_heap - move a new heap entry up as far as possible. -++ * @c: UBIFS file-system description object -++ * @heap: LEB category heap -++ * @lprops: LEB properties to move -++ * @cat: LEB category -++ * -++ * New entries to a heap are added at the bottom and then moved up until the -++ * parent's value is greater. In the case of LPT's category heaps, the value -++ * is either the amount of free space or the amount of dirty space, depending -++ * on the category. -++ */ -++static void move_up_lpt_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, -++ struct ubifs_lprops *lprops, int cat) -++{ -++ int val1, val2, hpos; -++ -++ hpos = lprops->hpos; -++ if (!hpos) -++ return; /* Already top of the heap */ -++ val1 = get_heap_comp_val(lprops, cat); -++ /* Compare to parent and, if greater, move up the heap */ -++ do { -++ int ppos = (hpos - 1) / 2; -++ -++ val2 = get_heap_comp_val(heap->arr[ppos], cat); -++ if (val2 >= val1) -++ return; -++ /* Greater than parent so move up */ -++ heap->arr[ppos]->hpos = hpos; -++ heap->arr[hpos] = heap->arr[ppos]; -++ heap->arr[ppos] = lprops; -++ lprops->hpos = ppos; -++ hpos = ppos; -++ } while (hpos); -++} -++ -++/** -++ * adjust_lpt_heap - move a changed heap entry up or down the heap. -++ * @c: UBIFS file-system description object -++ * @heap: LEB category heap -++ * @lprops: LEB properties to move -++ * @hpos: heap position of @lprops -++ * @cat: LEB category -++ * -++ * Changed entries in a heap are moved up or down until the parent's value is -++ * greater. In the case of LPT's category heaps, the value is either the amount -++ * of free space or the amount of dirty space, depending on the category. -++ */ -++static void adjust_lpt_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, -++ struct ubifs_lprops *lprops, int hpos, int cat) -++{ -++ int val1, val2, val3, cpos; -++ -++ val1 = get_heap_comp_val(lprops, cat); -++ /* Compare to parent and, if greater than parent, move up the heap */ -++ if (hpos) { -++ int ppos = (hpos - 1) / 2; -++ -++ val2 = get_heap_comp_val(heap->arr[ppos], cat); -++ if (val1 > val2) { -++ /* Greater than parent so move up */ -++ while (1) { -++ heap->arr[ppos]->hpos = hpos; -++ heap->arr[hpos] = heap->arr[ppos]; -++ heap->arr[ppos] = lprops; -++ lprops->hpos = ppos; -++ hpos = ppos; -++ if (!hpos) -++ return; -++ ppos = (hpos - 1) / 2; -++ val2 = get_heap_comp_val(heap->arr[ppos], cat); -++ if (val1 <= val2) -++ return; -++ /* Still greater than parent so keep going */ -++ } -++ } -++ } -++ /* Not greater than parent, so compare to children */ -++ while (1) { -++ /* Compare to left child */ -++ cpos = hpos * 2 + 1; -++ if (cpos >= heap->cnt) -++ return; -++ val2 = get_heap_comp_val(heap->arr[cpos], cat); -++ if (val1 < val2) { -++ /* Less than left child, so promote biggest child */ -++ if (cpos + 1 < heap->cnt) { -++ val3 = get_heap_comp_val(heap->arr[cpos + 1], -++ cat); -++ if (val3 > val2) -++ cpos += 1; /* Right child is bigger */ -++ } -++ heap->arr[cpos]->hpos = hpos; -++ heap->arr[hpos] = heap->arr[cpos]; -++ heap->arr[cpos] = lprops; -++ lprops->hpos = cpos; -++ hpos = cpos; -++ continue; -++ } -++ /* Compare to right child */ -++ cpos += 1; -++ if (cpos >= heap->cnt) -++ return; -++ val3 = get_heap_comp_val(heap->arr[cpos], cat); -++ if (val1 < val3) { -++ /* Less than right child, so promote right child */ -++ heap->arr[cpos]->hpos = hpos; -++ heap->arr[hpos] = heap->arr[cpos]; -++ heap->arr[cpos] = lprops; -++ lprops->hpos = cpos; -++ hpos = cpos; -++ continue; -++ } -++ return; -++ } -++} -++ -++/** -++ * add_to_lpt_heap - add LEB properties to a LEB category heap. -++ * @c: UBIFS file-system description object -++ * @lprops: LEB properties to add -++ * @cat: LEB category -++ * -++ * This function returns %1 if @lprops is added to the heap for LEB category -++ * @cat, otherwise %0 is returned because the heap is full. -++ */ -++static int add_to_lpt_heap(struct ubifs_info *c, struct ubifs_lprops *lprops, -++ int cat) -++{ -++ struct ubifs_lpt_heap *heap = &c->lpt_heap[cat - 1]; -++ -++ if (heap->cnt >= heap->max_cnt) { -++ const int b = LPT_HEAP_SZ / 2 - 1; -++ int cpos, val1, val2; -++ -++ /* Compare to some other LEB on the bottom of heap */ -++ /* Pick a position kind of randomly */ -++ cpos = (((size_t)lprops >> 4) & b) + b; -++ ubifs_assert(cpos >= b); -++ ubifs_assert(cpos < LPT_HEAP_SZ); -++ ubifs_assert(cpos < heap->cnt); -++ -++ val1 = get_heap_comp_val(lprops, cat); -++ val2 = get_heap_comp_val(heap->arr[cpos], cat); -++ if (val1 > val2) { -++ struct ubifs_lprops *lp; -++ -++ lp = heap->arr[cpos]; -++ lp->flags &= ~LPROPS_CAT_MASK; -++ lp->flags |= LPROPS_UNCAT; -++ list_add(&lp->list, &c->uncat_list); -++ lprops->hpos = cpos; -++ heap->arr[cpos] = lprops; -++ move_up_lpt_heap(c, heap, lprops, cat); -++ dbg_check_heap(c, heap, cat, lprops->hpos); -++ return 1; /* Added to heap */ -++ } -++ dbg_check_heap(c, heap, cat, -1); -++ return 0; /* Not added to heap */ -++ } else { -++ lprops->hpos = heap->cnt++; -++ heap->arr[lprops->hpos] = lprops; -++ move_up_lpt_heap(c, heap, lprops, cat); -++ dbg_check_heap(c, heap, cat, lprops->hpos); -++ return 1; /* Added to heap */ -++ } -++} -++ -++/** -++ * remove_from_lpt_heap - remove LEB properties from a LEB category heap. -++ * @c: UBIFS file-system description object -++ * @lprops: LEB properties to remove -++ * @cat: LEB category -++ */ -++static void remove_from_lpt_heap(struct ubifs_info *c, -++ struct ubifs_lprops *lprops, int cat) -++{ -++ struct ubifs_lpt_heap *heap; -++ int hpos = lprops->hpos; -++ -++ heap = &c->lpt_heap[cat - 1]; -++ ubifs_assert(hpos >= 0 && hpos < heap->cnt); -++ ubifs_assert(heap->arr[hpos] == lprops); -++ heap->cnt -= 1; -++ if (hpos < heap->cnt) { -++ heap->arr[hpos] = heap->arr[heap->cnt]; -++ heap->arr[hpos]->hpos = hpos; -++ adjust_lpt_heap(c, heap, heap->arr[hpos], hpos, cat); -++ } -++ dbg_check_heap(c, heap, cat, -1); -++} -++ -++/** -++ * lpt_heap_replace - replace lprops in a category heap. -++ * @c: UBIFS file-system description object -++ * @old_lprops: LEB properties to replace -++ * @new_lprops: LEB properties with which to replace -++ * @cat: LEB category -++ * -++ * During commit it is sometimes necessary to copy a pnode (see dirty_cow_pnode) -++ * and the lprops that the pnode contains. When that happens, references in -++ * the category heaps to those lprops must be updated to point to the new -++ * lprops. This function does that. -++ */ -++static void lpt_heap_replace(struct ubifs_info *c, -++ struct ubifs_lprops *old_lprops, -++ struct ubifs_lprops *new_lprops, int cat) -++{ -++ struct ubifs_lpt_heap *heap; -++ int hpos = new_lprops->hpos; -++ -++ heap = &c->lpt_heap[cat - 1]; -++ heap->arr[hpos] = new_lprops; -++} -++ -++/** -++ * ubifs_add_to_cat - add LEB properties to a category list or heap. -++ * @c: UBIFS file-system description object -++ * @lprops: LEB properties to add -++ * @cat: LEB category to which to add -++ * -++ * LEB properties are categorized to enable fast find operations. -++ */ -++void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops, -++ int cat) -++{ -++ switch (cat) { -++ case LPROPS_DIRTY: -++ case LPROPS_DIRTY_IDX: -++ case LPROPS_FREE: -++ if (add_to_lpt_heap(c, lprops, cat)) -++ break; -++ /* No more room on heap so make it uncategorized */ -++ cat = LPROPS_UNCAT; -++ /* Fall through */ -++ case LPROPS_UNCAT: -++ list_add(&lprops->list, &c->uncat_list); -++ break; -++ case LPROPS_EMPTY: -++ list_add(&lprops->list, &c->empty_list); -++ break; -++ case LPROPS_FREEABLE: -++ list_add(&lprops->list, &c->freeable_list); -++ c->freeable_cnt += 1; -++ break; -++ case LPROPS_FRDI_IDX: -++ list_add(&lprops->list, &c->frdi_idx_list); -++ break; -++ default: -++ ubifs_assert(0); -++ } -++ lprops->flags &= ~LPROPS_CAT_MASK; -++ lprops->flags |= cat; -++} -++ -++/** -++ * ubifs_remove_from_cat - remove LEB properties from a category list or heap. -++ * @c: UBIFS file-system description object -++ * @lprops: LEB properties to remove -++ * @cat: LEB category from which to remove -++ * -++ * LEB properties are categorized to enable fast find operations. -++ */ -++static void ubifs_remove_from_cat(struct ubifs_info *c, -++ struct ubifs_lprops *lprops, int cat) -++{ -++ switch (cat) { -++ case LPROPS_DIRTY: -++ case LPROPS_DIRTY_IDX: -++ case LPROPS_FREE: -++ remove_from_lpt_heap(c, lprops, cat); -++ break; -++ case LPROPS_FREEABLE: -++ c->freeable_cnt -= 1; -++ ubifs_assert(c->freeable_cnt >= 0); -++ /* Fall through */ -++ case LPROPS_UNCAT: -++ case LPROPS_EMPTY: -++ case LPROPS_FRDI_IDX: -++ ubifs_assert(!list_empty(&lprops->list)); -++ list_del(&lprops->list); -++ break; -++ default: -++ ubifs_assert(0); -++ } -++} -++ -++/** -++ * ubifs_replace_cat - replace lprops in a category list or heap. -++ * @c: UBIFS file-system description object -++ * @old_lprops: LEB properties to replace -++ * @new_lprops: LEB properties with which to replace -++ * -++ * During commit it is sometimes necessary to copy a pnode (see dirty_cow_pnode) -++ * and the lprops that the pnode contains. When that happens, references in -++ * category lists and heaps must be replaced. This function does that. -++ */ -++void ubifs_replace_cat(struct ubifs_info *c, struct ubifs_lprops *old_lprops, -++ struct ubifs_lprops *new_lprops) -++{ -++ int cat; -++ -++ cat = new_lprops->flags & LPROPS_CAT_MASK; -++ switch (cat) { -++ case LPROPS_DIRTY: -++ case LPROPS_DIRTY_IDX: -++ case LPROPS_FREE: -++ lpt_heap_replace(c, old_lprops, new_lprops, cat); -++ break; -++ case LPROPS_UNCAT: -++ case LPROPS_EMPTY: -++ case LPROPS_FREEABLE: -++ case LPROPS_FRDI_IDX: -++ list_replace(&old_lprops->list, &new_lprops->list); -++ break; -++ default: -++ ubifs_assert(0); -++ } -++} -++ -++/** -++ * ubifs_ensure_cat - ensure LEB properties are categorized. -++ * @c: UBIFS file-system description object -++ * @lprops: LEB properties -++ * -++ * A LEB may have fallen off of the bottom of a heap, and ended up as -++ * uncategorized even though it has enough space for us now. If that is the case -++ * this function will put the LEB back onto a heap. -++ */ -++void ubifs_ensure_cat(struct ubifs_info *c, struct ubifs_lprops *lprops) -++{ -++ int cat = lprops->flags & LPROPS_CAT_MASK; -++ -++ if (cat != LPROPS_UNCAT) -++ return; -++ cat = ubifs_categorize_lprops(c, lprops); -++ if (cat == LPROPS_UNCAT) -++ return; -++ ubifs_remove_from_cat(c, lprops, LPROPS_UNCAT); -++ ubifs_add_to_cat(c, lprops, cat); -++} -++ -++/** -++ * ubifs_categorize_lprops - categorize LEB properties. -++ * @c: UBIFS file-system description object -++ * @lprops: LEB properties to categorize -++ * -++ * LEB properties are categorized to enable fast find operations. This function -++ * returns the LEB category to which the LEB properties belong. Note however -++ * that if the LEB category is stored as a heap and the heap is full, the -++ * LEB properties may have their category changed to %LPROPS_UNCAT. -++ */ -++int ubifs_categorize_lprops(const struct ubifs_info *c, -++ const struct ubifs_lprops *lprops) -++{ -++ if (lprops->flags & LPROPS_TAKEN) -++ return LPROPS_UNCAT; -++ -++ if (lprops->free == c->leb_size) { -++ ubifs_assert(!(lprops->flags & LPROPS_INDEX)); -++ return LPROPS_EMPTY; -++ } -++ -++ if (lprops->free + lprops->dirty == c->leb_size) { -++ if (lprops->flags & LPROPS_INDEX) -++ return LPROPS_FRDI_IDX; -++ else -++ return LPROPS_FREEABLE; -++ } -++ -++ if (lprops->flags & LPROPS_INDEX) { -++ if (lprops->dirty + lprops->free >= c->min_idx_node_sz) -++ return LPROPS_DIRTY_IDX; -++ } else { -++ if (lprops->dirty >= c->dead_wm && -++ lprops->dirty > lprops->free) -++ return LPROPS_DIRTY; -++ if (lprops->free > 0) -++ return LPROPS_FREE; -++ } -++ -++ return LPROPS_UNCAT; -++} -++ -++/** -++ * change_category - change LEB properties category. -++ * @c: UBIFS file-system description object -++ * @lprops: LEB properties to recategorize -++ * -++ * LEB properties are categorized to enable fast find operations. When the LEB -++ * properties change they must be recategorized. -++ */ -++static void change_category(struct ubifs_info *c, struct ubifs_lprops *lprops) -++{ -++ int old_cat = lprops->flags & LPROPS_CAT_MASK; -++ int new_cat = ubifs_categorize_lprops(c, lprops); -++ -++ if (old_cat == new_cat) { -++ struct ubifs_lpt_heap *heap = &c->lpt_heap[new_cat - 1]; -++ -++ /* lprops on a heap now must be moved up or down */ -++ if (new_cat < 1 || new_cat > LPROPS_HEAP_CNT) -++ return; /* Not on a heap */ -++ heap = &c->lpt_heap[new_cat - 1]; -++ adjust_lpt_heap(c, heap, lprops, lprops->hpos, new_cat); -++ } else { -++ ubifs_remove_from_cat(c, lprops, old_cat); -++ ubifs_add_to_cat(c, lprops, new_cat); -++ } -++} -++ -++/** -++ * ubifs_get_lprops - get reference to LEB properties. -++ * @c: the UBIFS file-system description object -++ * -++ * This function locks lprops. Lprops have to be unlocked by -++ * 'ubifs_release_lprops()'. -++ */ -++void ubifs_get_lprops(struct ubifs_info *c) -++{ -++ mutex_lock(&c->lp_mutex); -++} -++ -++/** -++ * calc_dark - calculate LEB dark space size. -++ * @c: the UBIFS file-system description object -++ * @spc: amount of free and dirty space in the LEB -++ * -++ * This function calculates amount of dark space in an LEB which has @spc bytes -++ * of free and dirty space. Returns the calculations result. -++ * -++ * Dark space is the space which is not always usable - it depends on which -++ * nodes are written in which order. E.g., if an LEB has only 512 free bytes, -++ * it is dark space, because it cannot fit a large data node. So UBIFS cannot -++ * count on this LEB and treat these 512 bytes as usable because it is not true -++ * if, for example, only big chunks of uncompressible data will be written to -++ * the FS. -++ */ -++static int calc_dark(struct ubifs_info *c, int spc) -++{ -++ ubifs_assert(!(spc & 7)); -++ -++ if (spc < c->dark_wm) -++ return spc; -++ -++ /* -++ * If we have slightly more space then the dark space watermark, we can -++ * anyway safely assume it we'll be able to write a node of the -++ * smallest size there. -++ */ -++ if (spc - c->dark_wm < MIN_WRITE_SZ) -++ return spc - MIN_WRITE_SZ; -++ -++ return c->dark_wm; -++} -++ -++/** -++ * is_lprops_dirty - determine if LEB properties are dirty. -++ * @c: the UBIFS file-system description object -++ * @lprops: LEB properties to test -++ */ -++static int is_lprops_dirty(struct ubifs_info *c, struct ubifs_lprops *lprops) -++{ -++ struct ubifs_pnode *pnode; -++ int pos; -++ -++ pos = (lprops->lnum - c->main_first) & (UBIFS_LPT_FANOUT - 1); -++ pnode = (struct ubifs_pnode *)container_of(lprops - pos, -++ struct ubifs_pnode, -++ lprops[0]); -++ return !test_bit(COW_ZNODE, &pnode->flags) && -++ test_bit(DIRTY_CNODE, &pnode->flags); -++} -++ -++/** -++ * ubifs_change_lp - change LEB properties. -++ * @c: the UBIFS file-system description object -++ * @lp: LEB properties to change -++ * @free: new free space amount -++ * @dirty: new dirty space amount -++ * @flags: new flags -++ * @idx_gc_cnt: change to the count of idx_gc list -++ * -++ * This function changes LEB properties. This function does not change a LEB -++ * property (@free, @dirty or @flag) if the value passed is %-1. -++ * -++ * This function returns a pointer to the updated LEB properties on success -++ * and a negative error code on failure. N.B. the LEB properties may have had to -++ * be copied (due to COW) and consequently the pointer returned may not be the -++ * same as the pointer passed. -++ */ -++const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c, -++ const struct ubifs_lprops *lp, -++ int free, int dirty, int flags, -++ int idx_gc_cnt) -++{ -++ /* -++ * This is the only function that is allowed to change lprops, so we -++ * discard the const qualifier. -++ */ -++ struct ubifs_lprops *lprops = (struct ubifs_lprops *)lp; -++ -++ dbg_lp("LEB %d, free %d, dirty %d, flags %d", -++ lprops->lnum, free, dirty, flags); -++ -++ ubifs_assert(mutex_is_locked(&c->lp_mutex)); -++ ubifs_assert(c->lst.empty_lebs >= 0 && -++ c->lst.empty_lebs <= c->main_lebs); -++ ubifs_assert(c->freeable_cnt >= 0); -++ ubifs_assert(c->freeable_cnt <= c->main_lebs); -++ ubifs_assert(c->lst.taken_empty_lebs >= 0); -++ ubifs_assert(c->lst.taken_empty_lebs <= c->lst.empty_lebs); -++ ubifs_assert(!(c->lst.total_free & 7) && !(c->lst.total_dirty & 7)); -++ ubifs_assert(!(c->lst.total_dead & 7) && !(c->lst.total_dark & 7)); -++ ubifs_assert(!(c->lst.total_used & 7)); -++ -++ if (!is_lprops_dirty(c, lprops)) { -++ lprops = ubifs_lpt_lookup_dirty(c, lprops->lnum); -++ if (IS_ERR(lprops)) -++ return lprops; -++ } else -++ ubifs_assert(lprops == ubifs_lpt_lookup_dirty(c, lprops->lnum)); -++ -++ ubifs_assert(!(lprops->free & 7) && !(lprops->dirty & 7)); -++ -++ spin_lock(&c->space_lock); -++ -++ if ((lprops->flags & LPROPS_TAKEN) && lprops->free == c->leb_size) -++ c->lst.taken_empty_lebs -= 1; -++ -++ if (!(lprops->flags & LPROPS_INDEX)) { -++ int old_spc; -++ -++ old_spc = lprops->free + lprops->dirty; -++ if (old_spc < c->dead_wm) -++ c->lst.total_dead -= old_spc; -++ else -++ c->lst.total_dark -= calc_dark(c, old_spc); -++ -++ c->lst.total_used -= c->leb_size - old_spc; -++ } -++ -++ if (free != -1) { -++ free = ALIGN(free, 8); -++ c->lst.total_free += free - lprops->free; -++ -++ /* Increase or decrease empty LEBs counter if needed */ -++ if (free == c->leb_size) { -++ if (lprops->free != c->leb_size) -++ c->lst.empty_lebs += 1; -++ } else if (lprops->free == c->leb_size) -++ c->lst.empty_lebs -= 1; -++ lprops->free = free; -++ } -++ -++ if (dirty != -1) { -++ dirty = ALIGN(dirty, 8); -++ c->lst.total_dirty += dirty - lprops->dirty; -++ lprops->dirty = dirty; -++ } -++ -++ if (flags != -1) { -++ /* Take care about indexing LEBs counter if needed */ -++ if ((lprops->flags & LPROPS_INDEX)) { -++ if (!(flags & LPROPS_INDEX)) -++ c->lst.idx_lebs -= 1; -++ } else if (flags & LPROPS_INDEX) -++ c->lst.idx_lebs += 1; -++ lprops->flags = flags; -++ } -++ -++ if (!(lprops->flags & LPROPS_INDEX)) { -++ int new_spc; -++ -++ new_spc = lprops->free + lprops->dirty; -++ if (new_spc < c->dead_wm) -++ c->lst.total_dead += new_spc; -++ else -++ c->lst.total_dark += calc_dark(c, new_spc); -++ -++ c->lst.total_used += c->leb_size - new_spc; -++ } -++ -++ if ((lprops->flags & LPROPS_TAKEN) && lprops->free == c->leb_size) -++ c->lst.taken_empty_lebs += 1; -++ -++ change_category(c, lprops); -++ -++ c->idx_gc_cnt += idx_gc_cnt; -++ -++ spin_unlock(&c->space_lock); -++ -++ return lprops; -++} -++ -++/** -++ * ubifs_release_lprops - release lprops lock. -++ * @c: the UBIFS file-system description object -++ * -++ * This function has to be called after each 'ubifs_get_lprops()' call to -++ * unlock lprops. -++ */ -++void ubifs_release_lprops(struct ubifs_info *c) -++{ -++ ubifs_assert(mutex_is_locked(&c->lp_mutex)); -++ ubifs_assert(c->lst.empty_lebs >= 0 && -++ c->lst.empty_lebs <= c->main_lebs); -++ -++ mutex_unlock(&c->lp_mutex); -++} -++ -++/** -++ * ubifs_get_lp_stats - get lprops statistics. -++ * @c: UBIFS file-system description object -++ * @st: return statistics -++ */ -++void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *st) -++{ -++ spin_lock(&c->space_lock); -++ memcpy(st, &c->lst, sizeof(struct ubifs_lp_stats)); -++ spin_unlock(&c->space_lock); -++} -++ -++/** -++ * ubifs_change_one_lp - change LEB properties. -++ * @c: the UBIFS file-system description object -++ * @lnum: LEB to change properties for -++ * @free: amount of free space -++ * @dirty: amount of dirty space -++ * @flags_set: flags to set -++ * @flags_clean: flags to clean -++ * @idx_gc_cnt: change to the count of idx_gc list -++ * -++ * This function changes properties of LEB @lnum. It is a helper wrapper over -++ * 'ubifs_change_lp()' which hides lprops get/release. The arguments are the -++ * same as in case of 'ubifs_change_lp()'. Returns zero in case of success and -++ * a negative error code in case of failure. -++ */ -++int ubifs_change_one_lp(struct ubifs_info *c, int lnum, int free, int dirty, -++ int flags_set, int flags_clean, int idx_gc_cnt) -++{ -++ int err = 0, flags; -++ const struct ubifs_lprops *lp; -++ -++ ubifs_get_lprops(c); -++ -++ lp = ubifs_lpt_lookup_dirty(c, lnum); -++ if (IS_ERR(lp)) { -++ err = PTR_ERR(lp); -++ goto out; -++ } -++ -++ flags = (lp->flags | flags_set) & ~flags_clean; -++ lp = ubifs_change_lp(c, lp, free, dirty, flags, idx_gc_cnt); -++ if (IS_ERR(lp)) -++ err = PTR_ERR(lp); -++ -++out: -++ ubifs_release_lprops(c); -++ return err; -++} -++ -++/** -++ * ubifs_update_one_lp - update LEB properties. -++ * @c: the UBIFS file-system description object -++ * @lnum: LEB to change properties for -++ * @free: amount of free space -++ * @dirty: amount of dirty space to add -++ * @flags_set: flags to set -++ * @flags_clean: flags to clean -++ * -++ * This function is the same as 'ubifs_change_one_lp()' but @dirty is added to -++ * current dirty space, not substitutes it. -++ */ -++int ubifs_update_one_lp(struct ubifs_info *c, int lnum, int free, int dirty, -++ int flags_set, int flags_clean) -++{ -++ int err = 0, flags; -++ const struct ubifs_lprops *lp; -++ -++ ubifs_get_lprops(c); -++ -++ lp = ubifs_lpt_lookup_dirty(c, lnum); -++ if (IS_ERR(lp)) { -++ err = PTR_ERR(lp); -++ goto out; -++ } -++ -++ flags = (lp->flags | flags_set) & ~flags_clean; -++ lp = ubifs_change_lp(c, lp, free, lp->dirty + dirty, flags, 0); -++ if (IS_ERR(lp)) -++ err = PTR_ERR(lp); -++ -++out: -++ ubifs_release_lprops(c); -++ return err; -++} -++ -++/** -++ * ubifs_read_one_lp - read LEB properties. -++ * @c: the UBIFS file-system description object -++ * @lnum: LEB to read properties for -++ * @lp: where to store read properties -++ * -++ * This helper function reads properties of a LEB @lnum and stores them in @lp. -++ * Returns zero in case of success and a negative error code in case of -++ * failure. -++ */ -++int ubifs_read_one_lp(struct ubifs_info *c, int lnum, struct ubifs_lprops *lp) -++{ -++ int err = 0; -++ const struct ubifs_lprops *lpp; -++ -++ ubifs_get_lprops(c); -++ -++ lpp = ubifs_lpt_lookup(c, lnum); -++ if (IS_ERR(lpp)) { -++ err = PTR_ERR(lpp); -++ goto out; -++ } -++ -++ memcpy(lp, lpp, sizeof(struct ubifs_lprops)); -++ -++out: -++ ubifs_release_lprops(c); -++ return err; -++} -++ -++/** -++ * ubifs_fast_find_free - try to find a LEB with free space quickly. -++ * @c: the UBIFS file-system description object -++ * -++ * This function returns LEB properties for a LEB with free space or %NULL if -++ * the function is unable to find a LEB quickly. -++ */ -++const struct ubifs_lprops *ubifs_fast_find_free(struct ubifs_info *c) -++{ -++ struct ubifs_lprops *lprops; -++ struct ubifs_lpt_heap *heap; -++ -++ ubifs_assert(mutex_is_locked(&c->lp_mutex)); -++ -++ heap = &c->lpt_heap[LPROPS_FREE - 1]; -++ if (heap->cnt == 0) -++ return NULL; -++ -++ lprops = heap->arr[0]; -++ ubifs_assert(!(lprops->flags & LPROPS_TAKEN)); -++ ubifs_assert(!(lprops->flags & LPROPS_INDEX)); -++ return lprops; -++} -++ -++/** -++ * ubifs_fast_find_empty - try to find an empty LEB quickly. -++ * @c: the UBIFS file-system description object -++ * -++ * This function returns LEB properties for an empty LEB or %NULL if the -++ * function is unable to find an empty LEB quickly. -++ */ -++const struct ubifs_lprops *ubifs_fast_find_empty(struct ubifs_info *c) -++{ -++ struct ubifs_lprops *lprops; -++ -++ ubifs_assert(mutex_is_locked(&c->lp_mutex)); -++ -++ if (list_empty(&c->empty_list)) -++ return NULL; -++ -++ lprops = list_entry(c->empty_list.next, struct ubifs_lprops, list); -++ ubifs_assert(!(lprops->flags & LPROPS_TAKEN)); -++ ubifs_assert(!(lprops->flags & LPROPS_INDEX)); -++ ubifs_assert(lprops->free == c->leb_size); -++ return lprops; -++} -++ -++/** -++ * ubifs_fast_find_freeable - try to find a freeable LEB quickly. -++ * @c: the UBIFS file-system description object -++ * -++ * This function returns LEB properties for a freeable LEB or %NULL if the -++ * function is unable to find a freeable LEB quickly. -++ */ -++const struct ubifs_lprops *ubifs_fast_find_freeable(struct ubifs_info *c) -++{ -++ struct ubifs_lprops *lprops; -++ -++ ubifs_assert(mutex_is_locked(&c->lp_mutex)); -++ -++ if (list_empty(&c->freeable_list)) -++ return NULL; -++ -++ lprops = list_entry(c->freeable_list.next, struct ubifs_lprops, list); -++ ubifs_assert(!(lprops->flags & LPROPS_TAKEN)); -++ ubifs_assert(!(lprops->flags & LPROPS_INDEX)); -++ ubifs_assert(lprops->free + lprops->dirty == c->leb_size); -++ ubifs_assert(c->freeable_cnt > 0); -++ return lprops; -++} -++ -++/** -++ * ubifs_fast_find_frdi_idx - try to find a freeable index LEB quickly. -++ * @c: the UBIFS file-system description object -++ * -++ * This function returns LEB properties for a freeable index LEB or %NULL if the -++ * function is unable to find a freeable index LEB quickly. -++ */ -++const struct ubifs_lprops *ubifs_fast_find_frdi_idx(struct ubifs_info *c) -++{ -++ struct ubifs_lprops *lprops; -++ -++ ubifs_assert(mutex_is_locked(&c->lp_mutex)); -++ -++ if (list_empty(&c->frdi_idx_list)) -++ return NULL; -++ -++ lprops = list_entry(c->frdi_idx_list.next, struct ubifs_lprops, list); -++ ubifs_assert(!(lprops->flags & LPROPS_TAKEN)); -++ ubifs_assert((lprops->flags & LPROPS_INDEX)); -++ ubifs_assert(lprops->free + lprops->dirty == c->leb_size); -++ return lprops; -++} -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ -++/** -++ * dbg_check_cats - check category heaps and lists. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int dbg_check_cats(struct ubifs_info *c) -++{ -++ struct ubifs_lprops *lprops; -++ struct list_head *pos; -++ int i, cat; -++ -++ if (!(ubifs_chk_flags & (UBIFS_CHK_GEN | UBIFS_CHK_LPROPS))) -++ return 0; -++ -++ list_for_each_entry(lprops, &c->empty_list, list) { -++ if (lprops->free != c->leb_size) { -++ ubifs_err("non-empty LEB %d on empty list " -++ "(free %d dirty %d flags %d)", lprops->lnum, -++ lprops->free, lprops->dirty, lprops->flags); -++ return -EINVAL; -++ } -++ if (lprops->flags & LPROPS_TAKEN) { -++ ubifs_err("taken LEB %d on empty list " -++ "(free %d dirty %d flags %d)", lprops->lnum, -++ lprops->free, lprops->dirty, lprops->flags); -++ return -EINVAL; -++ } -++ } -++ -++ i = 0; -++ list_for_each_entry(lprops, &c->freeable_list, list) { -++ if (lprops->free + lprops->dirty != c->leb_size) { -++ ubifs_err("non-freeable LEB %d on freeable list " -++ "(free %d dirty %d flags %d)", lprops->lnum, -++ lprops->free, lprops->dirty, lprops->flags); -++ return -EINVAL; -++ } -++ if (lprops->flags & LPROPS_TAKEN) { -++ ubifs_err("taken LEB %d on freeable list " -++ "(free %d dirty %d flags %d)", lprops->lnum, -++ lprops->free, lprops->dirty, lprops->flags); -++ return -EINVAL; -++ } -++ i += 1; -++ } -++ if (i != c->freeable_cnt) { -++ ubifs_err("freeable list count %d expected %d", i, -++ c->freeable_cnt); -++ return -EINVAL; -++ } -++ -++ i = 0; -++ list_for_each(pos, &c->idx_gc) -++ i += 1; -++ if (i != c->idx_gc_cnt) { -++ ubifs_err("idx_gc list count %d expected %d", i, -++ c->idx_gc_cnt); -++ return -EINVAL; -++ } -++ -++ list_for_each_entry(lprops, &c->frdi_idx_list, list) { -++ if (lprops->free + lprops->dirty != c->leb_size) { -++ ubifs_err("non-freeable LEB %d on frdi_idx list " -++ "(free %d dirty %d flags %d)", lprops->lnum, -++ lprops->free, lprops->dirty, lprops->flags); -++ return -EINVAL; -++ } -++ if (lprops->flags & LPROPS_TAKEN) { -++ ubifs_err("taken LEB %d on frdi_idx list " -++ "(free %d dirty %d flags %d)", lprops->lnum, -++ lprops->free, lprops->dirty, lprops->flags); -++ return -EINVAL; -++ } -++ if (!(lprops->flags & LPROPS_INDEX)) { -++ ubifs_err("non-index LEB %d on frdi_idx list " -++ "(free %d dirty %d flags %d)", lprops->lnum, -++ lprops->free, lprops->dirty, lprops->flags); -++ return -EINVAL; -++ } -++ } -++ -++ for (cat = 1; cat <= LPROPS_HEAP_CNT; cat++) { -++ struct ubifs_lpt_heap *heap = &c->lpt_heap[cat - 1]; -++ -++ for (i = 0; i < heap->cnt; i++) { -++ lprops = heap->arr[i]; -++ if (!lprops) { -++ ubifs_err("null ptr in LPT heap cat %d", cat); -++ return -EINVAL; -++ } -++ if (lprops->hpos != i) { -++ ubifs_err("bad ptr in LPT heap cat %d", cat); -++ return -EINVAL; -++ } -++ if (lprops->flags & LPROPS_TAKEN) { -++ ubifs_err("taken LEB in LPT heap cat %d", cat); -++ return -EINVAL; -++ } -++ } -++ } -++ -++ return 0; -++} -++ -++void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat, -++ int add_pos) -++{ -++ int i = 0, j, err = 0; -++ -++ if (!(ubifs_chk_flags & (UBIFS_CHK_GEN | UBIFS_CHK_LPROPS))) -++ return; -++ -++ for (i = 0; i < heap->cnt; i++) { -++ struct ubifs_lprops *lprops = heap->arr[i]; -++ struct ubifs_lprops *lp; -++ -++ if (i != add_pos) -++ if ((lprops->flags & LPROPS_CAT_MASK) != cat) { -++ err = 1; -++ goto out; -++ } -++ if (lprops->hpos != i) { -++ err = 2; -++ goto out; -++ } -++ lp = ubifs_lpt_lookup(c, lprops->lnum); -++ if (IS_ERR(lp)) { -++ err = 3; -++ goto out; -++ } -++ if (lprops != lp) { -++ dbg_msg("lprops %zx lp %zx lprops->lnum %d lp->lnum %d", -++ (size_t)lprops, (size_t)lp, lprops->lnum, -++ lp->lnum); -++ err = 4; -++ goto out; -++ } -++ for (j = 0; j < i; j++) { -++ lp = heap->arr[j]; -++ if (lp == lprops) { -++ err = 5; -++ goto out; -++ } -++ if (lp->lnum == lprops->lnum) { -++ err = 6; -++ goto out; -++ } -++ } -++ } -++out: -++ if (err) { -++ dbg_msg("failed cat %d hpos %d err %d", cat, i, err); -++ dbg_dump_stack(); -++ dbg_dump_heap(c, heap, cat); -++ } -++} -++ -++/** -++ * struct scan_check_data - data provided to scan callback function. -++ * @lst: LEB properties statistics -++ * @err: error code -++ */ -++struct scan_check_data { -++ struct ubifs_lp_stats lst; -++ int err; -++}; -++ -++/** -++ * scan_check_cb - scan callback. -++ * @c: the UBIFS file-system description object -++ * @lp: LEB properties to scan -++ * @in_tree: whether the LEB properties are in main memory -++ * @data: information passed to and from the caller of the scan -++ * -++ * This function returns a code that indicates whether the scan should continue -++ * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree -++ * in main memory (%LPT_SCAN_ADD), or whether the scan should stop -++ * (%LPT_SCAN_STOP). -++ */ -++static int scan_check_cb(struct ubifs_info *c, -++ const struct ubifs_lprops *lp, int in_tree, -++ struct scan_check_data *data) -++{ -++ struct ubifs_scan_leb *sleb; -++ struct ubifs_scan_node *snod; -++ struct ubifs_lp_stats *lst = &data->lst; -++ int cat, lnum = lp->lnum, is_idx = 0, used = 0, free, dirty; -++ -++ cat = lp->flags & LPROPS_CAT_MASK; -++ if (cat != LPROPS_UNCAT) { -++ cat = ubifs_categorize_lprops(c, lp); -++ if (cat != (lp->flags & LPROPS_CAT_MASK)) { -++ ubifs_err("bad LEB category %d expected %d", -++ (lp->flags & LPROPS_CAT_MASK), cat); -++ goto out; -++ } -++ } -++ -++ /* Check lp is on its category list (if it has one) */ -++ if (in_tree) { -++ struct list_head *list = NULL; -++ -++ switch (cat) { -++ case LPROPS_EMPTY: -++ list = &c->empty_list; -++ break; -++ case LPROPS_FREEABLE: -++ list = &c->freeable_list; -++ break; -++ case LPROPS_FRDI_IDX: -++ list = &c->frdi_idx_list; -++ break; -++ case LPROPS_UNCAT: -++ list = &c->uncat_list; -++ break; -++ } -++ if (list) { -++ struct ubifs_lprops *lprops; -++ int found = 0; -++ -++ list_for_each_entry(lprops, list, list) { -++ if (lprops == lp) { -++ found = 1; -++ break; -++ } -++ } -++ if (!found) { -++ ubifs_err("bad LPT list (category %d)", cat); -++ goto out; -++ } -++ } -++ } -++ -++ /* Check lp is on its category heap (if it has one) */ -++ if (in_tree && cat > 0 && cat <= LPROPS_HEAP_CNT) { -++ struct ubifs_lpt_heap *heap = &c->lpt_heap[cat - 1]; -++ -++ if ((lp->hpos != -1 && heap->arr[lp->hpos]->lnum != lnum) || -++ lp != heap->arr[lp->hpos]) { -++ ubifs_err("bad LPT heap (category %d)", cat); -++ goto out; -++ } -++ } -++ -++ sleb = ubifs_scan(c, lnum, 0, c->dbg_buf); -++ if (IS_ERR(sleb)) { -++ /* -++ * After an unclean unmount, empty and freeable LEBs -++ * may contain garbage. -++ */ -++ if (lp->free == c->leb_size) { -++ ubifs_err("scan errors were in empty LEB " -++ "- continuing checking"); -++ lst->empty_lebs += 1; -++ lst->total_free += c->leb_size; -++ lst->total_dark += calc_dark(c, c->leb_size); -++ return LPT_SCAN_CONTINUE; -++ } -++ -++ if (lp->free + lp->dirty == c->leb_size && -++ !(lp->flags & LPROPS_INDEX)) { -++ ubifs_err("scan errors were in freeable LEB " -++ "- continuing checking"); -++ lst->total_free += lp->free; -++ lst->total_dirty += lp->dirty; -++ lst->total_dark += calc_dark(c, c->leb_size); -++ return LPT_SCAN_CONTINUE; -++ } -++ data->err = PTR_ERR(sleb); -++ return LPT_SCAN_STOP; -++ } -++ -++ is_idx = -1; -++ list_for_each_entry(snod, &sleb->nodes, list) { -++ int found, level = 0; -++ -++ cond_resched(); -++ -++ if (is_idx == -1) -++ is_idx = (snod->type == UBIFS_IDX_NODE) ? 1 : 0; -++ -++ if (is_idx && snod->type != UBIFS_IDX_NODE) { -++ ubifs_err("indexing node in data LEB %d:%d", -++ lnum, snod->offs); -++ goto out_destroy; -++ } -++ -++ if (snod->type == UBIFS_IDX_NODE) { -++ struct ubifs_idx_node *idx = snod->node; -++ -++ key_read(c, ubifs_idx_key(c, idx), &snod->key); -++ level = le16_to_cpu(idx->level); -++ } -++ -++ found = ubifs_tnc_has_node(c, &snod->key, level, lnum, -++ snod->offs, is_idx); -++ if (found) { -++ if (found < 0) -++ goto out_destroy; -++ used += ALIGN(snod->len, 8); -++ } -++ } -++ -++ free = c->leb_size - sleb->endpt; -++ dirty = sleb->endpt - used; -++ -++ if (free > c->leb_size || free < 0 || dirty > c->leb_size || -++ dirty < 0) { -++ ubifs_err("bad calculated accounting for LEB %d: " -++ "free %d, dirty %d", lnum, free, dirty); -++ goto out_destroy; -++ } -++ -++ if (lp->free + lp->dirty == c->leb_size && -++ free + dirty == c->leb_size) -++ if ((is_idx && !(lp->flags & LPROPS_INDEX)) || -++ (!is_idx && free == c->leb_size)) { -++ /* -++ * Empty or freeable LEBs could contain index -++ * nodes from an uncompleted commit due to an -++ * unclean unmount. Or they could be empty for -++ * the same reason. -++ */ -++ free = lp->free; -++ dirty = lp->dirty; -++ is_idx = 0; -++ } -++ -++ if (is_idx && lp->free + lp->dirty == free + dirty && -++ lnum != c->ihead_lnum) { -++ /* -++ * After an unclean unmount, an index LEB could have a different -++ * amount of free space than the value recorded by lprops. That -++ * is because the in-the-gaps method may use free space or -++ * create free space (as a side-effect of using ubi_leb_change -++ * and not writing the whole LEB). The incorrect free space -++ * value is not a problem because the index is only ever -++ * allocated empty LEBs, so there will never be an attempt to -++ * write to the free space at the end of an index LEB - except -++ * by the in-the-gaps method for which it is not a problem. -++ */ -++ free = lp->free; -++ dirty = lp->dirty; -++ } -++ -++ if (lp->free != free || lp->dirty != dirty) -++ goto out_print; -++ -++ if (is_idx && !(lp->flags & LPROPS_INDEX)) { -++ if (free == c->leb_size) -++ /* Free but not unmapped LEB, it's fine */ -++ is_idx = 0; -++ else { -++ ubifs_err("indexing node without indexing " -++ "flag"); -++ goto out_print; -++ } -++ } -++ -++ if (!is_idx && (lp->flags & LPROPS_INDEX)) { -++ ubifs_err("data node with indexing flag"); -++ goto out_print; -++ } -++ -++ if (free == c->leb_size) -++ lst->empty_lebs += 1; -++ -++ if (is_idx) -++ lst->idx_lebs += 1; -++ -++ if (!(lp->flags & LPROPS_INDEX)) -++ lst->total_used += c->leb_size - free - dirty; -++ lst->total_free += free; -++ lst->total_dirty += dirty; -++ -++ if (!(lp->flags & LPROPS_INDEX)) { -++ int spc = free + dirty; -++ -++ if (spc < c->dead_wm) -++ lst->total_dead += spc; -++ else -++ lst->total_dark += calc_dark(c, spc); -++ } -++ -++ ubifs_scan_destroy(sleb); -++ -++ return LPT_SCAN_CONTINUE; -++ -++out_print: -++ ubifs_err("bad accounting of LEB %d: free %d, dirty %d flags %#x, " -++ "should be free %d, dirty %d", -++ lnum, lp->free, lp->dirty, lp->flags, free, dirty); -++ dbg_dump_leb(c, lnum); -++out_destroy: -++ ubifs_scan_destroy(sleb); -++out: -++ data->err = -EINVAL; -++ return LPT_SCAN_STOP; -++} -++ -++/** -++ * dbg_check_lprops - check all LEB properties. -++ * @c: UBIFS file-system description object -++ * -++ * This function checks all LEB properties and makes sure they are all correct. -++ * It returns zero if everything is fine, %-EINVAL if there is an inconsistency -++ * and other negative error codes in case of other errors. This function is -++ * called while the file system is locked (because of commit start), so no -++ * additional locking is required. Note that locking the LPT mutex would cause -++ * a circular lock dependency with the TNC mutex. -++ */ -++int dbg_check_lprops(struct ubifs_info *c) -++{ -++ int i, err; -++ struct scan_check_data data; -++ struct ubifs_lp_stats *lst = &data.lst; -++ -++ if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS)) -++ return 0; -++ -++ /* -++ * As we are going to scan the media, the write buffers have to be -++ * synchronized. -++ */ -++ for (i = 0; i < c->jhead_cnt; i++) { -++ err = ubifs_wbuf_sync(&c->jheads[i].wbuf); -++ if (err) -++ return err; -++ } -++ -++ memset(lst, 0, sizeof(struct ubifs_lp_stats)); -++ -++ data.err = 0; -++ err = ubifs_lpt_scan_nolock(c, c->main_first, c->leb_cnt - 1, -++ (ubifs_lpt_scan_callback)scan_check_cb, -++ &data); -++ if (err && err != -ENOSPC) -++ goto out; -++ if (data.err) { -++ err = data.err; -++ goto out; -++ } -++ -++ if (lst->empty_lebs != c->lst.empty_lebs || -++ lst->idx_lebs != c->lst.idx_lebs || -++ lst->total_free != c->lst.total_free || -++ lst->total_dirty != c->lst.total_dirty || -++ lst->total_used != c->lst.total_used) { -++ ubifs_err("bad overall accounting"); -++ ubifs_err("calculated: empty_lebs %d, idx_lebs %d, " -++ "total_free %lld, total_dirty %lld, total_used %lld", -++ lst->empty_lebs, lst->idx_lebs, lst->total_free, -++ lst->total_dirty, lst->total_used); -++ ubifs_err("read from lprops: empty_lebs %d, idx_lebs %d, " -++ "total_free %lld, total_dirty %lld, total_used %lld", -++ c->lst.empty_lebs, c->lst.idx_lebs, c->lst.total_free, -++ c->lst.total_dirty, c->lst.total_used); -++ err = -EINVAL; -++ goto out; -++ } -++ -++ if (lst->total_dead != c->lst.total_dead || -++ lst->total_dark != c->lst.total_dark) { -++ ubifs_err("bad dead/dark space accounting"); -++ ubifs_err("calculated: total_dead %lld, total_dark %lld", -++ lst->total_dead, lst->total_dark); -++ ubifs_err("read from lprops: total_dead %lld, total_dark %lld", -++ c->lst.total_dead, c->lst.total_dark); -++ err = -EINVAL; -++ goto out; -++ } -++ -++ err = dbg_check_cats(c); -++out: -++ return err; -++} -++ -++#endif /* CONFIG_UBIFS_FS_DEBUG */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/lpt.c linux-2.6.24.7/fs/ubifs/lpt.c -+--- linux-2.6.24.7.old/fs/ubifs/lpt.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/lpt.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,2279 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Adrian Hunter -++ * Artem Bityutskiy (Битюцкий Ðртём) -++ */ -++ -++/* -++ * This file implements the LEB properties tree (LPT) area. The LPT area -++ * contains the LEB properties tree, a table of LPT area eraseblocks (ltab), and -++ * (for the "big" model) a table of saved LEB numbers (lsave). The LPT area sits -++ * between the log and the orphan area. -++ * -++ * The LPT area is like a miniature self-contained file system. It is required -++ * that it never runs out of space, is fast to access and update, and scales -++ * logarithmically. The LEB properties tree is implemented as a wandering tree -++ * much like the TNC, and the LPT area has its own garbage collection. -++ * -++ * The LPT has two slightly different forms called the "small model" and the -++ * "big model". The small model is used when the entire LEB properties table -++ * can be written into a single eraseblock. In that case, garbage collection -++ * consists of just writing the whole table, which therefore makes all other -++ * eraseblocks reusable. In the case of the big model, dirty eraseblocks are -++ * selected for garbage collection, which consists are marking the nodes in -++ * that LEB as dirty, and then only the dirty nodes are written out. Also, in -++ * the case of the big model, a table of LEB numbers is saved so that the entire -++ * LPT does not to be scanned looking for empty eraseblocks when UBIFS is first -++ * mounted. -++ */ -++ -++#include -++#include "ubifs.h" -++ -++/** -++ * do_calc_lpt_geom - calculate sizes for the LPT area. -++ * @c: the UBIFS file-system description object -++ * -++ * Calculate the sizes of LPT bit fields, nodes, and tree, based on the -++ * properties of the flash and whether LPT is "big" (c->big_lpt). -++ */ -++static void do_calc_lpt_geom(struct ubifs_info *c) -++{ -++ int i, n, bits, per_leb_wastage, max_pnode_cnt; -++ long long sz, tot_wastage; -++ -++ n = c->main_lebs + c->max_leb_cnt - c->leb_cnt; -++ max_pnode_cnt = DIV_ROUND_UP(n, UBIFS_LPT_FANOUT); -++ -++ c->lpt_hght = 1; -++ n = UBIFS_LPT_FANOUT; -++ while (n < max_pnode_cnt) { -++ c->lpt_hght += 1; -++ n <<= UBIFS_LPT_FANOUT_SHIFT; -++ } -++ -++ c->pnode_cnt = DIV_ROUND_UP(c->main_lebs, UBIFS_LPT_FANOUT); -++ -++ n = DIV_ROUND_UP(c->pnode_cnt, UBIFS_LPT_FANOUT); -++ c->nnode_cnt = n; -++ for (i = 1; i < c->lpt_hght; i++) { -++ n = DIV_ROUND_UP(n, UBIFS_LPT_FANOUT); -++ c->nnode_cnt += n; -++ } -++ -++ c->space_bits = fls(c->leb_size) - 3; -++ c->lpt_lnum_bits = fls(c->lpt_lebs); -++ c->lpt_offs_bits = fls(c->leb_size - 1); -++ c->lpt_spc_bits = fls(c->leb_size); -++ -++ n = DIV_ROUND_UP(c->max_leb_cnt, UBIFS_LPT_FANOUT); -++ c->pcnt_bits = fls(n - 1); -++ -++ c->lnum_bits = fls(c->max_leb_cnt - 1); -++ -++ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS + -++ (c->big_lpt ? c->pcnt_bits : 0) + -++ (c->space_bits * 2 + 1) * UBIFS_LPT_FANOUT; -++ c->pnode_sz = (bits + 7) / 8; -++ -++ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS + -++ (c->big_lpt ? c->pcnt_bits : 0) + -++ (c->lpt_lnum_bits + c->lpt_offs_bits) * UBIFS_LPT_FANOUT; -++ c->nnode_sz = (bits + 7) / 8; -++ -++ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS + -++ c->lpt_lebs * c->lpt_spc_bits * 2; -++ c->ltab_sz = (bits + 7) / 8; -++ -++ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS + -++ c->lnum_bits * c->lsave_cnt; -++ c->lsave_sz = (bits + 7) / 8; -++ -++ /* Calculate the minimum LPT size */ -++ c->lpt_sz = (long long)c->pnode_cnt * c->pnode_sz; -++ c->lpt_sz += (long long)c->nnode_cnt * c->nnode_sz; -++ c->lpt_sz += c->ltab_sz; -++ c->lpt_sz += c->lsave_sz; -++ -++ /* Add wastage */ -++ sz = c->lpt_sz; -++ per_leb_wastage = max_t(int, c->pnode_sz, c->nnode_sz); -++ sz += per_leb_wastage; -++ tot_wastage = per_leb_wastage; -++ while (sz > c->leb_size) { -++ sz += per_leb_wastage; -++ sz -= c->leb_size; -++ tot_wastage += per_leb_wastage; -++ } -++ tot_wastage += ALIGN(sz, c->min_io_size) - sz; -++ c->lpt_sz += tot_wastage; -++} -++ -++/** -++ * ubifs_calc_lpt_geom - calculate and check sizes for the LPT area. -++ * @c: the UBIFS file-system description object -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_calc_lpt_geom(struct ubifs_info *c) -++{ -++ int lebs_needed; -++ uint64_t sz; -++ -++ do_calc_lpt_geom(c); -++ -++ /* Verify that lpt_lebs is big enough */ -++ sz = c->lpt_sz * 2; /* Must have at least 2 times the size */ -++ sz += c->leb_size - 1; -++ do_div(sz, c->leb_size); -++ lebs_needed = sz; -++ if (lebs_needed > c->lpt_lebs) { -++ ubifs_err("too few LPT LEBs"); -++ return -EINVAL; -++ } -++ -++ /* Verify that ltab fits in a single LEB (since ltab is a single node */ -++ if (c->ltab_sz > c->leb_size) { -++ ubifs_err("LPT ltab too big"); -++ return -EINVAL; -++ } -++ -++ return 0; -++} -++ -++/** -++ * calc_dflt_lpt_geom - calculate default LPT geometry. -++ * @c: the UBIFS file-system description object -++ * @main_lebs: number of main area LEBs is passed and returned here -++ * @big_lpt: whether the LPT area is "big" is returned here -++ * -++ * The size of the LPT area depends on parameters that themselves are dependent -++ * on the size of the LPT area. This function, successively recalculates the LPT -++ * area geometry until the parameters and resultant geometry are consistent. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs, -++ int *big_lpt) -++{ -++ int i, lebs_needed; -++ uint64_t sz; -++ -++ /* Start by assuming the minimum number of LPT LEBs */ -++ c->lpt_lebs = UBIFS_MIN_LPT_LEBS; -++ c->main_lebs = *main_lebs - c->lpt_lebs; -++ if (c->main_lebs <= 0) -++ return -EINVAL; -++ -++ /* And assume we will use the small LPT model */ -++ c->big_lpt = 0; -++ -++ /* -++ * Calculate the geometry based on assumptions above and then see if it -++ * makes sense -++ */ -++ do_calc_lpt_geom(c); -++ -++ /* Small LPT model must have lpt_sz < leb_size */ -++ if (c->lpt_sz > c->leb_size) { -++ /* Nope, so try again using big LPT model */ -++ c->big_lpt = 1; -++ do_calc_lpt_geom(c); -++ } -++ -++ /* Now check there are enough LPT LEBs */ -++ for (i = 0; i < 64 ; i++) { -++ sz = c->lpt_sz * 4; /* Allow 4 times the size */ -++ sz += c->leb_size - 1; -++ do_div(sz, c->leb_size); -++ lebs_needed = sz; -++ if (lebs_needed > c->lpt_lebs) { -++ /* Not enough LPT LEBs so try again with more */ -++ c->lpt_lebs = lebs_needed; -++ c->main_lebs = *main_lebs - c->lpt_lebs; -++ if (c->main_lebs <= 0) -++ return -EINVAL; -++ do_calc_lpt_geom(c); -++ continue; -++ } -++ if (c->ltab_sz > c->leb_size) { -++ ubifs_err("LPT ltab too big"); -++ return -EINVAL; -++ } -++ *main_lebs = c->main_lebs; -++ *big_lpt = c->big_lpt; -++ return 0; -++ } -++ return -EINVAL; -++} -++ -++/** -++ * pack_bits - pack bit fields end-to-end. -++ * @addr: address at which to pack (passed and next address returned) -++ * @pos: bit position at which to pack (passed and next position returned) -++ * @val: value to pack -++ * @nrbits: number of bits of value to pack (1-32) -++ */ -++static void pack_bits(uint8_t **addr, int *pos, uint32_t val, int nrbits) -++{ -++ uint8_t *p = *addr; -++ int b = *pos; -++ -++ ubifs_assert(nrbits > 0); -++ ubifs_assert(nrbits <= 32); -++ ubifs_assert(*pos >= 0); -++ ubifs_assert(*pos < 8); -++ ubifs_assert((val >> nrbits) == 0 || nrbits == 32); -++ if (b) { -++ *p |= ((uint8_t)val) << b; -++ nrbits += b; -++ if (nrbits > 8) { -++ *++p = (uint8_t)(val >>= (8 - b)); -++ if (nrbits > 16) { -++ *++p = (uint8_t)(val >>= 8); -++ if (nrbits > 24) { -++ *++p = (uint8_t)(val >>= 8); -++ if (nrbits > 32) -++ *++p = (uint8_t)(val >>= 8); -++ } -++ } -++ } -++ } else { -++ *p = (uint8_t)val; -++ if (nrbits > 8) { -++ *++p = (uint8_t)(val >>= 8); -++ if (nrbits > 16) { -++ *++p = (uint8_t)(val >>= 8); -++ if (nrbits > 24) -++ *++p = (uint8_t)(val >>= 8); -++ } -++ } -++ } -++ b = nrbits & 7; -++ if (b == 0) -++ p++; -++ *addr = p; -++ *pos = b; -++} -++ -++/** -++ * ubifs_unpack_bits - unpack bit fields. -++ * @addr: address at which to unpack (passed and next address returned) -++ * @pos: bit position at which to unpack (passed and next position returned) -++ * @nrbits: number of bits of value to unpack (1-32) -++ * -++ * This functions returns the value unpacked. -++ */ -++uint32_t ubifs_unpack_bits(uint8_t **addr, int *pos, int nrbits) -++{ -++ const int k = 32 - nrbits; -++ uint8_t *p = *addr; -++ int b = *pos; -++ uint32_t val; -++ -++ ubifs_assert(nrbits > 0); -++ ubifs_assert(nrbits <= 32); -++ ubifs_assert(*pos >= 0); -++ ubifs_assert(*pos < 8); -++ if (b) { -++ val = p[1] | ((uint32_t)p[2] << 8) | ((uint32_t)p[3] << 16) | -++ ((uint32_t)p[4] << 24); -++ val <<= (8 - b); -++ val |= *p >> b; -++ nrbits += b; -++ } else -++ val = p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) | -++ ((uint32_t)p[3] << 24); -++ val <<= k; -++ val >>= k; -++ b = nrbits & 7; -++ p += nrbits / 8; -++ *addr = p; -++ *pos = b; -++ ubifs_assert((val >> nrbits) == 0 || nrbits - b == 32); -++ return val; -++} -++ -++/** -++ * ubifs_pack_pnode - pack all the bit fields of a pnode. -++ * @c: UBIFS file-system description object -++ * @buf: buffer into which to pack -++ * @pnode: pnode to pack -++ */ -++void ubifs_pack_pnode(struct ubifs_info *c, void *buf, -++ struct ubifs_pnode *pnode) -++{ -++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; -++ int i, pos = 0; -++ uint16_t crc; -++ -++ pack_bits(&addr, &pos, UBIFS_LPT_PNODE, UBIFS_LPT_TYPE_BITS); -++ if (c->big_lpt) -++ pack_bits(&addr, &pos, pnode->num, c->pcnt_bits); -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ pack_bits(&addr, &pos, pnode->lprops[i].free >> 3, -++ c->space_bits); -++ pack_bits(&addr, &pos, pnode->lprops[i].dirty >> 3, -++ c->space_bits); -++ if (pnode->lprops[i].flags & LPROPS_INDEX) -++ pack_bits(&addr, &pos, 1, 1); -++ else -++ pack_bits(&addr, &pos, 0, 1); -++ } -++ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES, -++ c->pnode_sz - UBIFS_LPT_CRC_BYTES); -++ addr = buf; -++ pos = 0; -++ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS); -++} -++ -++/** -++ * ubifs_pack_nnode - pack all the bit fields of a nnode. -++ * @c: UBIFS file-system description object -++ * @buf: buffer into which to pack -++ * @nnode: nnode to pack -++ */ -++void ubifs_pack_nnode(struct ubifs_info *c, void *buf, -++ struct ubifs_nnode *nnode) -++{ -++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; -++ int i, pos = 0; -++ uint16_t crc; -++ -++ pack_bits(&addr, &pos, UBIFS_LPT_NNODE, UBIFS_LPT_TYPE_BITS); -++ if (c->big_lpt) -++ pack_bits(&addr, &pos, nnode->num, c->pcnt_bits); -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ int lnum = nnode->nbranch[i].lnum; -++ -++ if (lnum == 0) -++ lnum = c->lpt_last + 1; -++ pack_bits(&addr, &pos, lnum - c->lpt_first, c->lpt_lnum_bits); -++ pack_bits(&addr, &pos, nnode->nbranch[i].offs, -++ c->lpt_offs_bits); -++ } -++ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES, -++ c->nnode_sz - UBIFS_LPT_CRC_BYTES); -++ addr = buf; -++ pos = 0; -++ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS); -++} -++ -++/** -++ * ubifs_pack_ltab - pack the LPT's own lprops table. -++ * @c: UBIFS file-system description object -++ * @buf: buffer into which to pack -++ * @ltab: LPT's own lprops table to pack -++ */ -++void ubifs_pack_ltab(struct ubifs_info *c, void *buf, -++ struct ubifs_lpt_lprops *ltab) -++{ -++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; -++ int i, pos = 0; -++ uint16_t crc; -++ -++ pack_bits(&addr, &pos, UBIFS_LPT_LTAB, UBIFS_LPT_TYPE_BITS); -++ for (i = 0; i < c->lpt_lebs; i++) { -++ pack_bits(&addr, &pos, ltab[i].free, c->lpt_spc_bits); -++ pack_bits(&addr, &pos, ltab[i].dirty, c->lpt_spc_bits); -++ } -++ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES, -++ c->ltab_sz - UBIFS_LPT_CRC_BYTES); -++ addr = buf; -++ pos = 0; -++ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS); -++} -++ -++/** -++ * ubifs_pack_lsave - pack the LPT's save table. -++ * @c: UBIFS file-system description object -++ * @buf: buffer into which to pack -++ * @lsave: LPT's save table to pack -++ */ -++void ubifs_pack_lsave(struct ubifs_info *c, void *buf, int *lsave) -++{ -++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; -++ int i, pos = 0; -++ uint16_t crc; -++ -++ pack_bits(&addr, &pos, UBIFS_LPT_LSAVE, UBIFS_LPT_TYPE_BITS); -++ for (i = 0; i < c->lsave_cnt; i++) -++ pack_bits(&addr, &pos, lsave[i], c->lnum_bits); -++ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES, -++ c->lsave_sz - UBIFS_LPT_CRC_BYTES); -++ addr = buf; -++ pos = 0; -++ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS); -++} -++ -++/** -++ * ubifs_add_lpt_dirt - add dirty space to LPT LEB properties. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number to which to add dirty space -++ * @dirty: amount of dirty space to add -++ */ -++void ubifs_add_lpt_dirt(struct ubifs_info *c, int lnum, int dirty) -++{ -++ if (!dirty || !lnum) -++ return; -++ dbg_lp("LEB %d add %d to %d", -++ lnum, dirty, c->ltab[lnum - c->lpt_first].dirty); -++ ubifs_assert(lnum >= c->lpt_first && lnum <= c->lpt_last); -++ c->ltab[lnum - c->lpt_first].dirty += dirty; -++} -++ -++/** -++ * set_ltab - set LPT LEB properties. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number -++ * @free: amount of free space -++ * @dirty: amount of dirty space -++ */ -++static void set_ltab(struct ubifs_info *c, int lnum, int free, int dirty) -++{ -++ dbg_lp("LEB %d free %d dirty %d to %d %d", -++ lnum, c->ltab[lnum - c->lpt_first].free, -++ c->ltab[lnum - c->lpt_first].dirty, free, dirty); -++ ubifs_assert(lnum >= c->lpt_first && lnum <= c->lpt_last); -++ c->ltab[lnum - c->lpt_first].free = free; -++ c->ltab[lnum - c->lpt_first].dirty = dirty; -++} -++ -++/** -++ * ubifs_add_nnode_dirt - add dirty space to LPT LEB properties. -++ * @c: UBIFS file-system description object -++ * @nnode: nnode for which to add dirt -++ */ -++void ubifs_add_nnode_dirt(struct ubifs_info *c, struct ubifs_nnode *nnode) -++{ -++ struct ubifs_nnode *np = nnode->parent; -++ -++ if (np) -++ ubifs_add_lpt_dirt(c, np->nbranch[nnode->iip].lnum, -++ c->nnode_sz); -++ else { -++ ubifs_add_lpt_dirt(c, c->lpt_lnum, c->nnode_sz); -++ if (!(c->lpt_drty_flgs & LTAB_DIRTY)) { -++ c->lpt_drty_flgs |= LTAB_DIRTY; -++ ubifs_add_lpt_dirt(c, c->ltab_lnum, c->ltab_sz); -++ } -++ } -++} -++ -++/** -++ * add_pnode_dirt - add dirty space to LPT LEB properties. -++ * @c: UBIFS file-system description object -++ * @pnode: pnode for which to add dirt -++ */ -++static void add_pnode_dirt(struct ubifs_info *c, struct ubifs_pnode *pnode) -++{ -++ ubifs_add_lpt_dirt(c, pnode->parent->nbranch[pnode->iip].lnum, -++ c->pnode_sz); -++} -++ -++/** -++ * calc_nnode_num - calculate nnode number. -++ * @row: the row in the tree (root is zero) -++ * @col: the column in the row (leftmost is zero) -++ * -++ * The nnode number is a number that uniquely identifies a nnode and can be used -++ * easily to traverse the tree from the root to that nnode. -++ * -++ * This function calculates and returns the nnode number for the nnode at @row -++ * and @col. -++ */ -++static int calc_nnode_num(int row, int col) -++{ -++ int num, bits; -++ -++ num = 1; -++ while (row--) { -++ bits = (col & (UBIFS_LPT_FANOUT - 1)); -++ col >>= UBIFS_LPT_FANOUT_SHIFT; -++ num <<= UBIFS_LPT_FANOUT_SHIFT; -++ num |= bits; -++ } -++ return num; -++} -++ -++/** -++ * calc_nnode_num_from_parent - calculate nnode number. -++ * @c: UBIFS file-system description object -++ * @parent: parent nnode -++ * @iip: index in parent -++ * -++ * The nnode number is a number that uniquely identifies a nnode and can be used -++ * easily to traverse the tree from the root to that nnode. -++ * -++ * This function calculates and returns the nnode number based on the parent's -++ * nnode number and the index in parent. -++ */ -++static int calc_nnode_num_from_parent(struct ubifs_info *c, -++ struct ubifs_nnode *parent, int iip) -++{ -++ int num, shft; -++ -++ if (!parent) -++ return 1; -++ shft = (c->lpt_hght - parent->level) * UBIFS_LPT_FANOUT_SHIFT; -++ num = parent->num ^ (1 << shft); -++ num |= (UBIFS_LPT_FANOUT + iip) << shft; -++ return num; -++} -++ -++/** -++ * calc_pnode_num_from_parent - calculate pnode number. -++ * @c: UBIFS file-system description object -++ * @parent: parent nnode -++ * @iip: index in parent -++ * -++ * The pnode number is a number that uniquely identifies a pnode and can be used -++ * easily to traverse the tree from the root to that pnode. -++ * -++ * This function calculates and returns the pnode number based on the parent's -++ * nnode number and the index in parent. -++ */ -++static int calc_pnode_num_from_parent(struct ubifs_info *c, -++ struct ubifs_nnode *parent, int iip) -++{ -++ int i, n = c->lpt_hght - 1, pnum = parent->num, num = 0; -++ -++ for (i = 0; i < n; i++) { -++ num <<= UBIFS_LPT_FANOUT_SHIFT; -++ num |= pnum & (UBIFS_LPT_FANOUT - 1); -++ pnum >>= UBIFS_LPT_FANOUT_SHIFT; -++ } -++ num <<= UBIFS_LPT_FANOUT_SHIFT; -++ num |= iip; -++ return num; -++} -++ -++/** -++ * ubifs_create_dflt_lpt - create default LPT. -++ * @c: UBIFS file-system description object -++ * @main_lebs: number of main area LEBs is passed and returned here -++ * @lpt_first: LEB number of first LPT LEB -++ * @lpt_lebs: number of LEBs for LPT is passed and returned here -++ * @big_lpt: use big LPT model is passed and returned here -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, -++ int *lpt_lebs, int *big_lpt) -++{ -++ int lnum, err = 0, node_sz, iopos, i, j, cnt, len, alen, row; -++ int blnum, boffs, bsz, bcnt; -++ struct ubifs_pnode *pnode = NULL; -++ struct ubifs_nnode *nnode = NULL; -++ void *buf = NULL, *p; -++ struct ubifs_lpt_lprops *ltab = NULL; -++ int *lsave = NULL; -++ -++ err = calc_dflt_lpt_geom(c, main_lebs, big_lpt); -++ if (err) -++ return err; -++ *lpt_lebs = c->lpt_lebs; -++ -++ /* Needed by 'ubifs_pack_nnode()' and 'set_ltab()' */ -++ c->lpt_first = lpt_first; -++ /* Needed by 'set_ltab()' */ -++ c->lpt_last = lpt_first + c->lpt_lebs - 1; -++ /* Needed by 'ubifs_pack_lsave()' */ -++ c->main_first = c->leb_cnt - *main_lebs; -++ -++ lsave = kmalloc(sizeof(int) * c->lsave_cnt, GFP_KERNEL); -++ pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_KERNEL); -++ nnode = kzalloc(sizeof(struct ubifs_nnode), GFP_KERNEL); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ buf = kmalloc(c->leb_size, GFP_KERNEL); -++ ltab = kmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs, GFP_KERNEL); -++#else -++ buf = vmalloc(c->leb_size); -++ ltab = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs); -++#endif -++ if (!pnode || !nnode || !buf || !ltab || !lsave) { -++ err = -ENOMEM; -++ goto out; -++ } -++ -++ ubifs_assert(!c->ltab); -++ c->ltab = ltab; /* Needed by set_ltab */ -++ -++ /* Initialize LPT's own lprops */ -++ for (i = 0; i < c->lpt_lebs; i++) { -++ ltab[i].free = c->leb_size; -++ ltab[i].dirty = 0; -++ ltab[i].tgc = 0; -++ ltab[i].cmt = 0; -++ } -++ -++ lnum = lpt_first; -++ p = buf; -++ /* Number of leaf nodes (pnodes) */ -++ cnt = c->pnode_cnt; -++ -++ /* -++ * The first pnode contains the LEB properties for the LEBs that contain -++ * the root inode node and the root index node of the index tree. -++ */ -++ node_sz = ALIGN(ubifs_idx_node_sz(c, 1), 8); -++ iopos = ALIGN(node_sz, c->min_io_size); -++ pnode->lprops[0].free = c->leb_size - iopos; -++ pnode->lprops[0].dirty = iopos - node_sz; -++ pnode->lprops[0].flags = LPROPS_INDEX; -++ -++ node_sz = UBIFS_INO_NODE_SZ; -++ iopos = ALIGN(node_sz, c->min_io_size); -++ pnode->lprops[1].free = c->leb_size - iopos; -++ pnode->lprops[1].dirty = iopos - node_sz; -++ -++ for (i = 2; i < UBIFS_LPT_FANOUT; i++) -++ pnode->lprops[i].free = c->leb_size; -++ -++ /* Add first pnode */ -++ ubifs_pack_pnode(c, p, pnode); -++ p += c->pnode_sz; -++ len = c->pnode_sz; -++ pnode->num += 1; -++ -++ /* Reset pnode values for remaining pnodes */ -++ pnode->lprops[0].free = c->leb_size; -++ pnode->lprops[0].dirty = 0; -++ pnode->lprops[0].flags = 0; -++ -++ pnode->lprops[1].free = c->leb_size; -++ pnode->lprops[1].dirty = 0; -++ -++ /* -++ * To calculate the internal node branches, we keep information about -++ * the level below. -++ */ -++ blnum = lnum; /* LEB number of level below */ -++ boffs = 0; /* Offset of level below */ -++ bcnt = cnt; /* Number of nodes in level below */ -++ bsz = c->pnode_sz; /* Size of nodes in level below */ -++ -++ /* Add all remaining pnodes */ -++ for (i = 1; i < cnt; i++) { -++ if (len + c->pnode_sz > c->leb_size) { -++ alen = ALIGN(len, c->min_io_size); -++ set_ltab(c, lnum, c->leb_size - alen, alen - len); -++ memset(p, 0xff, alen - len); -++ err = ubi_leb_change(c->ubi, lnum++, buf, alen, -++ UBI_SHORTTERM); -++ if (err) -++ goto out; -++ p = buf; -++ len = 0; -++ } -++ ubifs_pack_pnode(c, p, pnode); -++ p += c->pnode_sz; -++ len += c->pnode_sz; -++ /* -++ * pnodes are simply numbered left to right starting at zero, -++ * which means the pnode number can be used easily to traverse -++ * down the tree to the corresponding pnode. -++ */ -++ pnode->num += 1; -++ } -++ -++ row = 0; -++ for (i = UBIFS_LPT_FANOUT; cnt > i; i <<= UBIFS_LPT_FANOUT_SHIFT) -++ row += 1; -++ /* Add all nnodes, one level at a time */ -++ while (1) { -++ /* Number of internal nodes (nnodes) at next level */ -++ cnt = DIV_ROUND_UP(cnt, UBIFS_LPT_FANOUT); -++ for (i = 0; i < cnt; i++) { -++ if (len + c->nnode_sz > c->leb_size) { -++ alen = ALIGN(len, c->min_io_size); -++ set_ltab(c, lnum, c->leb_size - alen, -++ alen - len); -++ memset(p, 0xff, alen - len); -++ err = ubi_leb_change(c->ubi, lnum++, buf, alen, -++ UBI_SHORTTERM); -++ if (err) -++ goto out; -++ p = buf; -++ len = 0; -++ } -++ /* Only 1 nnode at this level, so it is the root */ -++ if (cnt == 1) { -++ c->lpt_lnum = lnum; -++ c->lpt_offs = len; -++ } -++ /* Set branches to the level below */ -++ for (j = 0; j < UBIFS_LPT_FANOUT; j++) { -++ if (bcnt) { -++ if (boffs + bsz > c->leb_size) { -++ blnum += 1; -++ boffs = 0; -++ } -++ nnode->nbranch[j].lnum = blnum; -++ nnode->nbranch[j].offs = boffs; -++ boffs += bsz; -++ bcnt--; -++ } else { -++ nnode->nbranch[j].lnum = 0; -++ nnode->nbranch[j].offs = 0; -++ } -++ } -++ nnode->num = calc_nnode_num(row, i); -++ ubifs_pack_nnode(c, p, nnode); -++ p += c->nnode_sz; -++ len += c->nnode_sz; -++ } -++ /* Only 1 nnode at this level, so it is the root */ -++ if (cnt == 1) -++ break; -++ /* Update the information about the level below */ -++ bcnt = cnt; -++ bsz = c->nnode_sz; -++ row -= 1; -++ } -++ -++ if (*big_lpt) { -++ /* Need to add LPT's save table */ -++ if (len + c->lsave_sz > c->leb_size) { -++ alen = ALIGN(len, c->min_io_size); -++ set_ltab(c, lnum, c->leb_size - alen, alen - len); -++ memset(p, 0xff, alen - len); -++ err = ubi_leb_change(c->ubi, lnum++, buf, alen, -++ UBI_SHORTTERM); -++ if (err) -++ goto out; -++ p = buf; -++ len = 0; -++ } -++ -++ c->lsave_lnum = lnum; -++ c->lsave_offs = len; -++ -++ for (i = 0; i < c->lsave_cnt && i < *main_lebs; i++) -++ lsave[i] = c->main_first + i; -++ for (; i < c->lsave_cnt; i++) -++ lsave[i] = c->main_first; -++ -++ ubifs_pack_lsave(c, p, lsave); -++ p += c->lsave_sz; -++ len += c->lsave_sz; -++ } -++ -++ /* Need to add LPT's own LEB properties table */ -++ if (len + c->ltab_sz > c->leb_size) { -++ alen = ALIGN(len, c->min_io_size); -++ set_ltab(c, lnum, c->leb_size - alen, alen - len); -++ memset(p, 0xff, alen - len); -++ err = ubi_leb_change(c->ubi, lnum++, buf, alen, UBI_SHORTTERM); -++ if (err) -++ goto out; -++ p = buf; -++ len = 0; -++ } -++ -++ c->ltab_lnum = lnum; -++ c->ltab_offs = len; -++ -++ /* Update ltab before packing it */ -++ len += c->ltab_sz; -++ alen = ALIGN(len, c->min_io_size); -++ set_ltab(c, lnum, c->leb_size - alen, alen - len); -++ -++ ubifs_pack_ltab(c, p, ltab); -++ p += c->ltab_sz; -++ -++ /* Write remaining buffer */ -++ memset(p, 0xff, alen - len); -++ err = ubi_leb_change(c->ubi, lnum, buf, alen, UBI_SHORTTERM); -++ if (err) -++ goto out; -++ -++ c->nhead_lnum = lnum; -++ c->nhead_offs = ALIGN(len, c->min_io_size); -++ -++ dbg_lp("space_bits %d", c->space_bits); -++ dbg_lp("lpt_lnum_bits %d", c->lpt_lnum_bits); -++ dbg_lp("lpt_offs_bits %d", c->lpt_offs_bits); -++ dbg_lp("lpt_spc_bits %d", c->lpt_spc_bits); -++ dbg_lp("pcnt_bits %d", c->pcnt_bits); -++ dbg_lp("lnum_bits %d", c->lnum_bits); -++ dbg_lp("pnode_sz %d", c->pnode_sz); -++ dbg_lp("nnode_sz %d", c->nnode_sz); -++ dbg_lp("ltab_sz %d", c->ltab_sz); -++ dbg_lp("lsave_sz %d", c->lsave_sz); -++ dbg_lp("lsave_cnt %d", c->lsave_cnt); -++ dbg_lp("lpt_hght %d", c->lpt_hght); -++ dbg_lp("big_lpt %d", c->big_lpt); -++ dbg_lp("LPT root is at %d:%d", c->lpt_lnum, c->lpt_offs); -++ dbg_lp("LPT head is at %d:%d", c->nhead_lnum, c->nhead_offs); -++ dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs); -++ if (c->big_lpt) -++ dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs); -++out: -++ c->ltab = NULL; -++ kfree(lsave); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(ltab); -++ kfree(buf); -++#else -++ vfree(ltab); -++ vfree(buf); -++#endif -++ kfree(nnode); -++ kfree(pnode); -++ return err; -++} -++ -++/** -++ * update_cats - add LEB properties of a pnode to LEB category lists and heaps. -++ * @c: UBIFS file-system description object -++ * @pnode: pnode -++ * -++ * When a pnode is loaded into memory, the LEB properties it contains are added, -++ * by this function, to the LEB category lists and heaps. -++ */ -++static void update_cats(struct ubifs_info *c, struct ubifs_pnode *pnode) -++{ -++ int i; -++ -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ int cat = pnode->lprops[i].flags & LPROPS_CAT_MASK; -++ int lnum = pnode->lprops[i].lnum; -++ -++ if (!lnum) -++ return; -++ ubifs_add_to_cat(c, &pnode->lprops[i], cat); -++ } -++} -++ -++/** -++ * replace_cats - add LEB properties of a pnode to LEB category lists and heaps. -++ * @c: UBIFS file-system description object -++ * @old_pnode: pnode copied -++ * @new_pnode: pnode copy -++ * -++ * During commit it is sometimes necessary to copy a pnode -++ * (see dirty_cow_pnode). When that happens, references in -++ * category lists and heaps must be replaced. This function does that. -++ */ -++static void replace_cats(struct ubifs_info *c, struct ubifs_pnode *old_pnode, -++ struct ubifs_pnode *new_pnode) -++{ -++ int i; -++ -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ if (!new_pnode->lprops[i].lnum) -++ return; -++ ubifs_replace_cat(c, &old_pnode->lprops[i], -++ &new_pnode->lprops[i]); -++ } -++} -++ -++/** -++ * check_lpt_crc - check LPT node crc is correct. -++ * @c: UBIFS file-system description object -++ * @buf: buffer containing node -++ * @len: length of node -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int check_lpt_crc(void *buf, int len) -++{ -++ int pos = 0; -++ uint8_t *addr = buf; -++ uint16_t crc, calc_crc; -++ -++ crc = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_CRC_BITS); -++ calc_crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES, -++ len - UBIFS_LPT_CRC_BYTES); -++ if (crc != calc_crc) { -++ ubifs_err("invalid crc in LPT node: crc %hx calc %hx", crc, -++ calc_crc); -++ dbg_dump_stack(); -++ return -EINVAL; -++ } -++ return 0; -++} -++ -++/** -++ * check_lpt_type - check LPT node type is correct. -++ * @c: UBIFS file-system description object -++ * @addr: address of type bit field is passed and returned updated here -++ * @pos: position of type bit field is passed and returned updated here -++ * @type: expected type -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int check_lpt_type(uint8_t **addr, int *pos, int type) -++{ -++ int node_type; -++ -++ node_type = ubifs_unpack_bits(addr, pos, UBIFS_LPT_TYPE_BITS); -++ if (node_type != type) { -++ ubifs_err("invalid type (%d) in LPT node type %d", node_type, -++ type); -++ dbg_dump_stack(); -++ return -EINVAL; -++ } -++ return 0; -++} -++ -++/** -++ * unpack_pnode - unpack a pnode. -++ * @c: UBIFS file-system description object -++ * @buf: buffer containing packed pnode to unpack -++ * @pnode: pnode structure to fill -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int unpack_pnode(struct ubifs_info *c, void *buf, -++ struct ubifs_pnode *pnode) -++{ -++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; -++ int i, pos = 0, err; -++ -++ err = check_lpt_type(&addr, &pos, UBIFS_LPT_PNODE); -++ if (err) -++ return err; -++ if (c->big_lpt) -++ pnode->num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits); -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ struct ubifs_lprops * const lprops = &pnode->lprops[i]; -++ -++ lprops->free = ubifs_unpack_bits(&addr, &pos, c->space_bits); -++ lprops->free <<= 3; -++ lprops->dirty = ubifs_unpack_bits(&addr, &pos, c->space_bits); -++ lprops->dirty <<= 3; -++ -++ if (ubifs_unpack_bits(&addr, &pos, 1)) -++ lprops->flags = LPROPS_INDEX; -++ else -++ lprops->flags = 0; -++ lprops->flags |= ubifs_categorize_lprops(c, lprops); -++ } -++ err = check_lpt_crc(buf, c->pnode_sz); -++ return err; -++} -++ -++/** -++ * unpack_nnode - unpack a nnode. -++ * @c: UBIFS file-system description object -++ * @buf: buffer containing packed nnode to unpack -++ * @nnode: nnode structure to fill -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int unpack_nnode(struct ubifs_info *c, void *buf, -++ struct ubifs_nnode *nnode) -++{ -++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; -++ int i, pos = 0, err; -++ -++ err = check_lpt_type(&addr, &pos, UBIFS_LPT_NNODE); -++ if (err) -++ return err; -++ if (c->big_lpt) -++ nnode->num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits); -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ int lnum; -++ -++ lnum = ubifs_unpack_bits(&addr, &pos, c->lpt_lnum_bits) + -++ c->lpt_first; -++ if (lnum == c->lpt_last + 1) -++ lnum = 0; -++ nnode->nbranch[i].lnum = lnum; -++ nnode->nbranch[i].offs = ubifs_unpack_bits(&addr, &pos, -++ c->lpt_offs_bits); -++ } -++ err = check_lpt_crc(buf, c->nnode_sz); -++ return err; -++} -++ -++/** -++ * unpack_ltab - unpack the LPT's own lprops table. -++ * @c: UBIFS file-system description object -++ * @buf: buffer from which to unpack -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int unpack_ltab(struct ubifs_info *c, void *buf) -++{ -++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; -++ int i, pos = 0, err; -++ -++ err = check_lpt_type(&addr, &pos, UBIFS_LPT_LTAB); -++ if (err) -++ return err; -++ for (i = 0; i < c->lpt_lebs; i++) { -++ int free = ubifs_unpack_bits(&addr, &pos, c->lpt_spc_bits); -++ int dirty = ubifs_unpack_bits(&addr, &pos, c->lpt_spc_bits); -++ -++ if (free < 0 || free > c->leb_size || dirty < 0 || -++ dirty > c->leb_size || free + dirty > c->leb_size) -++ return -EINVAL; -++ -++ c->ltab[i].free = free; -++ c->ltab[i].dirty = dirty; -++ c->ltab[i].tgc = 0; -++ c->ltab[i].cmt = 0; -++ } -++ err = check_lpt_crc(buf, c->ltab_sz); -++ return err; -++} -++ -++/** -++ * unpack_lsave - unpack the LPT's save table. -++ * @c: UBIFS file-system description object -++ * @buf: buffer from which to unpack -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int unpack_lsave(struct ubifs_info *c, void *buf) -++{ -++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; -++ int i, pos = 0, err; -++ -++ err = check_lpt_type(&addr, &pos, UBIFS_LPT_LSAVE); -++ if (err) -++ return err; -++ for (i = 0; i < c->lsave_cnt; i++) { -++ int lnum = ubifs_unpack_bits(&addr, &pos, c->lnum_bits); -++ -++ if (lnum < c->main_first || lnum >= c->leb_cnt) -++ return -EINVAL; -++ c->lsave[i] = lnum; -++ } -++ err = check_lpt_crc(buf, c->lsave_sz); -++ return err; -++} -++ -++/** -++ * validate_nnode - validate a nnode. -++ * @c: UBIFS file-system description object -++ * @nnode: nnode to validate -++ * @parent: parent nnode (or NULL for the root nnode) -++ * @iip: index in parent -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int validate_nnode(struct ubifs_info *c, struct ubifs_nnode *nnode, -++ struct ubifs_nnode *parent, int iip) -++{ -++ int i, lvl, max_offs; -++ -++ if (c->big_lpt) { -++ int num = calc_nnode_num_from_parent(c, parent, iip); -++ -++ if (nnode->num != num) -++ return -EINVAL; -++ } -++ lvl = parent ? parent->level - 1 : c->lpt_hght; -++ if (lvl < 1) -++ return -EINVAL; -++ if (lvl == 1) -++ max_offs = c->leb_size - c->pnode_sz; -++ else -++ max_offs = c->leb_size - c->nnode_sz; -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ int lnum = nnode->nbranch[i].lnum; -++ int offs = nnode->nbranch[i].offs; -++ -++ if (lnum == 0) { -++ if (offs != 0) -++ return -EINVAL; -++ continue; -++ } -++ if (lnum < c->lpt_first || lnum > c->lpt_last) -++ return -EINVAL; -++ if (offs < 0 || offs > max_offs) -++ return -EINVAL; -++ } -++ return 0; -++} -++ -++/** -++ * validate_pnode - validate a pnode. -++ * @c: UBIFS file-system description object -++ * @pnode: pnode to validate -++ * @parent: parent nnode -++ * @iip: index in parent -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int validate_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, -++ struct ubifs_nnode *parent, int iip) -++{ -++ int i; -++ -++ if (c->big_lpt) { -++ int num = calc_pnode_num_from_parent(c, parent, iip); -++ -++ if (pnode->num != num) -++ return -EINVAL; -++ } -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ int free = pnode->lprops[i].free; -++ int dirty = pnode->lprops[i].dirty; -++ -++ if (free < 0 || free > c->leb_size || free % c->min_io_size || -++ (free & 7)) -++ return -EINVAL; -++ if (dirty < 0 || dirty > c->leb_size || (dirty & 7)) -++ return -EINVAL; -++ if (dirty + free > c->leb_size) -++ return -EINVAL; -++ } -++ return 0; -++} -++ -++/** -++ * set_pnode_lnum - set LEB numbers on a pnode. -++ * @c: UBIFS file-system description object -++ * @pnode: pnode to update -++ * -++ * This function calculates the LEB numbers for the LEB properties it contains -++ * based on the pnode number. -++ */ -++static void set_pnode_lnum(struct ubifs_info *c, struct ubifs_pnode *pnode) -++{ -++ int i, lnum; -++ -++ lnum = (pnode->num << UBIFS_LPT_FANOUT_SHIFT) + c->main_first; -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ if (lnum >= c->leb_cnt) -++ return; -++ pnode->lprops[i].lnum = lnum++; -++ } -++} -++ -++/** -++ * ubifs_read_nnode - read a nnode from flash and link it to the tree in memory. -++ * @c: UBIFS file-system description object -++ * @parent: parent nnode (or NULL for the root) -++ * @iip: index in parent -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip) -++{ -++ struct ubifs_nbranch *branch = NULL; -++ struct ubifs_nnode *nnode = NULL; -++ void *buf = c->lpt_nod_buf; -++ int err, lnum, offs; -++ -++ if (parent) { -++ branch = &parent->nbranch[iip]; -++ lnum = branch->lnum; -++ offs = branch->offs; -++ } else { -++ lnum = c->lpt_lnum; -++ offs = c->lpt_offs; -++ } -++ nnode = kzalloc(sizeof(struct ubifs_nnode), GFP_NOFS); -++ if (!nnode) { -++ err = -ENOMEM; -++ goto out; -++ } -++ if (lnum == 0) { -++ /* -++ * This nnode was not written which just means that the LEB -++ * properties in the subtree below it describe empty LEBs. We -++ * make the nnode as though we had read it, which in fact means -++ * doing almost nothing. -++ */ -++ if (c->big_lpt) -++ nnode->num = calc_nnode_num_from_parent(c, parent, iip); -++ } else { -++ err = ubi_read(c->ubi, lnum, buf, offs, c->nnode_sz); -++ if (err) -++ goto out; -++ err = unpack_nnode(c, buf, nnode); -++ if (err) -++ goto out; -++ } -++ err = validate_nnode(c, nnode, parent, iip); -++ if (err) -++ goto out; -++ if (!c->big_lpt) -++ nnode->num = calc_nnode_num_from_parent(c, parent, iip); -++ if (parent) { -++ branch->nnode = nnode; -++ nnode->level = parent->level - 1; -++ } else { -++ c->nroot = nnode; -++ nnode->level = c->lpt_hght; -++ } -++ nnode->parent = parent; -++ nnode->iip = iip; -++ return 0; -++ -++out: -++ ubifs_err("error %d reading nnode at %d:%d", err, lnum, offs); -++ kfree(nnode); -++ return err; -++} -++ -++/** -++ * read_pnode - read a pnode from flash and link it to the tree in memory. -++ * @c: UBIFS file-system description object -++ * @parent: parent nnode -++ * @iip: index in parent -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip) -++{ -++ struct ubifs_nbranch *branch; -++ struct ubifs_pnode *pnode = NULL; -++ void *buf = c->lpt_nod_buf; -++ int err, lnum, offs; -++ -++ branch = &parent->nbranch[iip]; -++ lnum = branch->lnum; -++ offs = branch->offs; -++ pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_NOFS); -++ if (!pnode) { -++ err = -ENOMEM; -++ goto out; -++ } -++ if (lnum == 0) { -++ /* -++ * This pnode was not written which just means that the LEB -++ * properties in it describe empty LEBs. We make the pnode as -++ * though we had read it. -++ */ -++ int i; -++ -++ if (c->big_lpt) -++ pnode->num = calc_pnode_num_from_parent(c, parent, iip); -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ struct ubifs_lprops * const lprops = &pnode->lprops[i]; -++ -++ lprops->free = c->leb_size; -++ lprops->flags = ubifs_categorize_lprops(c, lprops); -++ } -++ } else { -++ err = ubi_read(c->ubi, lnum, buf, offs, c->pnode_sz); -++ if (err) -++ goto out; -++ err = unpack_pnode(c, buf, pnode); -++ if (err) -++ goto out; -++ } -++ err = validate_pnode(c, pnode, parent, iip); -++ if (err) -++ goto out; -++ if (!c->big_lpt) -++ pnode->num = calc_pnode_num_from_parent(c, parent, iip); -++ branch->pnode = pnode; -++ pnode->parent = parent; -++ pnode->iip = iip; -++ set_pnode_lnum(c, pnode); -++ c->pnodes_have += 1; -++ return 0; -++ -++out: -++ ubifs_err("error %d reading pnode at %d:%d", err, lnum, offs); -++ dbg_dump_pnode(c, pnode, parent, iip); -++ dbg_msg("calc num: %d", calc_pnode_num_from_parent(c, parent, iip)); -++ kfree(pnode); -++ return err; -++} -++ -++/** -++ * read_ltab - read LPT's own lprops table. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int read_ltab(struct ubifs_info *c) -++{ -++ int err; -++ void *buf; -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ buf = kmalloc(c->ltab_sz, GFP_KERNEL); -++#else -++ buf = vmalloc(c->ltab_sz); -++#endif -++ if (!buf) -++ return -ENOMEM; -++ err = ubi_read(c->ubi, c->ltab_lnum, buf, c->ltab_offs, c->ltab_sz); -++ if (err) -++ goto out; -++ err = unpack_ltab(c, buf); -++out: -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(buf); -++#else -++ vfree(buf); -++#endif -++ return err; -++} -++ -++/** -++ * read_lsave - read LPT's save table. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int read_lsave(struct ubifs_info *c) -++{ -++ int err, i; -++ void *buf; -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ buf = kmalloc(c->lsave_sz, GFP_KERNEL); -++#else -++ buf = vmalloc(c->lsave_sz); -++#endif -++ if (!buf) -++ return -ENOMEM; -++ err = ubi_read(c->ubi, c->lsave_lnum, buf, c->lsave_offs, c->lsave_sz); -++ if (err) -++ goto out; -++ err = unpack_lsave(c, buf); -++ if (err) -++ goto out; -++ for (i = 0; i < c->lsave_cnt; i++) { -++ int lnum = c->lsave[i]; -++ -++ /* -++ * Due to automatic resizing, the values in the lsave table -++ * could be beyond the volume size - just ignore them. -++ */ -++ if (lnum >= c->leb_cnt) -++ continue; -++ ubifs_lpt_lookup(c, lnum); -++ } -++out: -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(buf); -++#else -++ vfree(buf); -++#endif -++ return err; -++} -++ -++/** -++ * ubifs_get_nnode - get a nnode. -++ * @c: UBIFS file-system description object -++ * @parent: parent nnode (or NULL for the root) -++ * @iip: index in parent -++ * -++ * This function returns a pointer to the nnode on success or a negative error -++ * code on failure. -++ */ -++struct ubifs_nnode *ubifs_get_nnode(struct ubifs_info *c, -++ struct ubifs_nnode *parent, int iip) -++{ -++ struct ubifs_nbranch *branch; -++ struct ubifs_nnode *nnode; -++ int err; -++ -++ branch = &parent->nbranch[iip]; -++ nnode = branch->nnode; -++ if (nnode) -++ return nnode; -++ err = ubifs_read_nnode(c, parent, iip); -++ if (err) -++ return ERR_PTR(err); -++ return branch->nnode; -++} -++ -++/** -++ * ubifs_get_pnode - get a pnode. -++ * @c: UBIFS file-system description object -++ * @parent: parent nnode -++ * @iip: index in parent -++ * -++ * This function returns a pointer to the pnode on success or a negative error -++ * code on failure. -++ */ -++struct ubifs_pnode *ubifs_get_pnode(struct ubifs_info *c, -++ struct ubifs_nnode *parent, int iip) -++{ -++ struct ubifs_nbranch *branch; -++ struct ubifs_pnode *pnode; -++ int err; -++ -++ branch = &parent->nbranch[iip]; -++ pnode = branch->pnode; -++ if (pnode) -++ return pnode; -++ err = read_pnode(c, parent, iip); -++ if (err) -++ return ERR_PTR(err); -++ update_cats(c, branch->pnode); -++ return branch->pnode; -++} -++ -++/** -++ * ubifs_lpt_lookup - lookup LEB properties in the LPT. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number to lookup -++ * -++ * This function returns a pointer to the LEB properties on success or a -++ * negative error code on failure. -++ */ -++struct ubifs_lprops *ubifs_lpt_lookup(struct ubifs_info *c, int lnum) -++{ -++ int err, i, h, iip, shft; -++ struct ubifs_nnode *nnode; -++ struct ubifs_pnode *pnode; -++ -++ if (!c->nroot) { -++ err = ubifs_read_nnode(c, NULL, 0); -++ if (err) -++ return ERR_PTR(err); -++ } -++ nnode = c->nroot; -++ i = lnum - c->main_first; -++ shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT; -++ for (h = 1; h < c->lpt_hght; h++) { -++ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); -++ shft -= UBIFS_LPT_FANOUT_SHIFT; -++ nnode = ubifs_get_nnode(c, nnode, iip); -++ if (IS_ERR(nnode)) -++ return ERR_PTR(PTR_ERR(nnode)); -++ } -++ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); -++ shft -= UBIFS_LPT_FANOUT_SHIFT; -++ pnode = ubifs_get_pnode(c, nnode, iip); -++ if (IS_ERR(pnode)) -++ return ERR_PTR(PTR_ERR(pnode)); -++ iip = (i & (UBIFS_LPT_FANOUT - 1)); -++ dbg_lp("LEB %d, free %d, dirty %d, flags %d", lnum, -++ pnode->lprops[iip].free, pnode->lprops[iip].dirty, -++ pnode->lprops[iip].flags); -++ return &pnode->lprops[iip]; -++} -++ -++/** -++ * dirty_cow_nnode - ensure a nnode is not being committed. -++ * @c: UBIFS file-system description object -++ * @nnode: nnode to check -++ * -++ * Returns dirtied nnode on success or negative error code on failure. -++ */ -++static struct ubifs_nnode *dirty_cow_nnode(struct ubifs_info *c, -++ struct ubifs_nnode *nnode) -++{ -++ struct ubifs_nnode *n; -++ int i; -++ -++ if (!test_bit(COW_CNODE, &nnode->flags)) { -++ /* nnode is not being committed */ -++ if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) { -++ c->dirty_nn_cnt += 1; -++ ubifs_add_nnode_dirt(c, nnode); -++ } -++ return nnode; -++ } -++ -++ /* nnode is being committed, so copy it */ -++ n = kmalloc(sizeof(struct ubifs_nnode), GFP_NOFS); -++ if (unlikely(!n)) -++ return ERR_PTR(-ENOMEM); -++ -++ memcpy(n, nnode, sizeof(struct ubifs_nnode)); -++ n->cnext = NULL; -++ __set_bit(DIRTY_CNODE, &n->flags); -++ __clear_bit(COW_CNODE, &n->flags); -++ -++ /* The children now have new parent */ -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ struct ubifs_nbranch *branch = &n->nbranch[i]; -++ -++ if (branch->cnode) -++ branch->cnode->parent = n; -++ } -++ -++ ubifs_assert(!test_bit(OBSOLETE_CNODE, &nnode->flags)); -++ __set_bit(OBSOLETE_CNODE, &nnode->flags); -++ -++ c->dirty_nn_cnt += 1; -++ ubifs_add_nnode_dirt(c, nnode); -++ if (nnode->parent) -++ nnode->parent->nbranch[n->iip].nnode = n; -++ else -++ c->nroot = n; -++ return n; -++} -++ -++/** -++ * dirty_cow_pnode - ensure a pnode is not being committed. -++ * @c: UBIFS file-system description object -++ * @pnode: pnode to check -++ * -++ * Returns dirtied pnode on success or negative error code on failure. -++ */ -++static struct ubifs_pnode *dirty_cow_pnode(struct ubifs_info *c, -++ struct ubifs_pnode *pnode) -++{ -++ struct ubifs_pnode *p; -++ -++ if (!test_bit(COW_CNODE, &pnode->flags)) { -++ /* pnode is not being committed */ -++ if (!test_and_set_bit(DIRTY_CNODE, &pnode->flags)) { -++ c->dirty_pn_cnt += 1; -++ add_pnode_dirt(c, pnode); -++ } -++ return pnode; -++ } -++ -++ /* pnode is being committed, so copy it */ -++ p = kmalloc(sizeof(struct ubifs_pnode), GFP_NOFS); -++ if (unlikely(!p)) -++ return ERR_PTR(-ENOMEM); -++ -++ memcpy(p, pnode, sizeof(struct ubifs_pnode)); -++ p->cnext = NULL; -++ __set_bit(DIRTY_CNODE, &p->flags); -++ __clear_bit(COW_CNODE, &p->flags); -++ replace_cats(c, pnode, p); -++ -++ ubifs_assert(!test_bit(OBSOLETE_CNODE, &pnode->flags)); -++ __set_bit(OBSOLETE_CNODE, &pnode->flags); -++ -++ c->dirty_pn_cnt += 1; -++ add_pnode_dirt(c, pnode); -++ pnode->parent->nbranch[p->iip].pnode = p; -++ return p; -++} -++ -++/** -++ * ubifs_lpt_lookup_dirty - lookup LEB properties in the LPT. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number to lookup -++ * -++ * This function returns a pointer to the LEB properties on success or a -++ * negative error code on failure. -++ */ -++struct ubifs_lprops *ubifs_lpt_lookup_dirty(struct ubifs_info *c, int lnum) -++{ -++ int err, i, h, iip, shft; -++ struct ubifs_nnode *nnode; -++ struct ubifs_pnode *pnode; -++ -++ if (!c->nroot) { -++ err = ubifs_read_nnode(c, NULL, 0); -++ if (err) -++ return ERR_PTR(err); -++ } -++ nnode = c->nroot; -++ nnode = dirty_cow_nnode(c, nnode); -++ if (IS_ERR(nnode)) -++ return ERR_PTR(PTR_ERR(nnode)); -++ i = lnum - c->main_first; -++ shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT; -++ for (h = 1; h < c->lpt_hght; h++) { -++ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); -++ shft -= UBIFS_LPT_FANOUT_SHIFT; -++ nnode = ubifs_get_nnode(c, nnode, iip); -++ if (IS_ERR(nnode)) -++ return ERR_PTR(PTR_ERR(nnode)); -++ nnode = dirty_cow_nnode(c, nnode); -++ if (IS_ERR(nnode)) -++ return ERR_PTR(PTR_ERR(nnode)); -++ } -++ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); -++ shft -= UBIFS_LPT_FANOUT_SHIFT; -++ pnode = ubifs_get_pnode(c, nnode, iip); -++ if (IS_ERR(pnode)) -++ return ERR_PTR(PTR_ERR(pnode)); -++ pnode = dirty_cow_pnode(c, pnode); -++ if (IS_ERR(pnode)) -++ return ERR_PTR(PTR_ERR(pnode)); -++ iip = (i & (UBIFS_LPT_FANOUT - 1)); -++ dbg_lp("LEB %d, free %d, dirty %d, flags %d", lnum, -++ pnode->lprops[iip].free, pnode->lprops[iip].dirty, -++ pnode->lprops[iip].flags); -++ ubifs_assert(test_bit(DIRTY_CNODE, &pnode->flags)); -++ return &pnode->lprops[iip]; -++} -++ -++/** -++ * lpt_init_rd - initialize the LPT for reading. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int lpt_init_rd(struct ubifs_info *c) -++{ -++ int err, i; -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ c->ltab = kmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs, GFP_KERNEL); -++#else -++ c->ltab = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs); -++#endif -++ if (!c->ltab) -++ return -ENOMEM; -++ -++ i = max_t(int, c->nnode_sz, c->pnode_sz); -++ c->lpt_nod_buf = kmalloc(i, GFP_KERNEL); -++ if (!c->lpt_nod_buf) -++ return -ENOMEM; -++ -++ for (i = 0; i < LPROPS_HEAP_CNT; i++) { -++ c->lpt_heap[i].arr = kmalloc(sizeof(void *) * LPT_HEAP_SZ, -++ GFP_KERNEL); -++ if (!c->lpt_heap[i].arr) -++ return -ENOMEM; -++ c->lpt_heap[i].cnt = 0; -++ c->lpt_heap[i].max_cnt = LPT_HEAP_SZ; -++ } -++ -++ c->dirty_idx.arr = kmalloc(sizeof(void *) * LPT_HEAP_SZ, GFP_KERNEL); -++ if (!c->dirty_idx.arr) -++ return -ENOMEM; -++ c->dirty_idx.cnt = 0; -++ c->dirty_idx.max_cnt = LPT_HEAP_SZ; -++ -++ err = read_ltab(c); -++ if (err) -++ return err; -++ -++ dbg_lp("space_bits %d", c->space_bits); -++ dbg_lp("lpt_lnum_bits %d", c->lpt_lnum_bits); -++ dbg_lp("lpt_offs_bits %d", c->lpt_offs_bits); -++ dbg_lp("lpt_spc_bits %d", c->lpt_spc_bits); -++ dbg_lp("pcnt_bits %d", c->pcnt_bits); -++ dbg_lp("lnum_bits %d", c->lnum_bits); -++ dbg_lp("pnode_sz %d", c->pnode_sz); -++ dbg_lp("nnode_sz %d", c->nnode_sz); -++ dbg_lp("ltab_sz %d", c->ltab_sz); -++ dbg_lp("lsave_sz %d", c->lsave_sz); -++ dbg_lp("lsave_cnt %d", c->lsave_cnt); -++ dbg_lp("lpt_hght %d", c->lpt_hght); -++ dbg_lp("big_lpt %d", c->big_lpt); -++ dbg_lp("LPT root is at %d:%d", c->lpt_lnum, c->lpt_offs); -++ dbg_lp("LPT head is at %d:%d", c->nhead_lnum, c->nhead_offs); -++ dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs); -++ if (c->big_lpt) -++ dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs); -++ -++ return 0; -++} -++ -++/** -++ * lpt_init_wr - initialize the LPT for writing. -++ * @c: UBIFS file-system description object -++ * -++ * 'lpt_init_rd()' must have been called already. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int lpt_init_wr(struct ubifs_info *c) -++{ -++ int err, i; -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ c->ltab_cmt = kmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs, GFP_KERNEL); -++ if (!c->ltab_cmt) -++ return -ENOMEM; -++ c->lpt_buf = kmalloc(c->leb_size, GFP_KERNEL); -++ if (!c->lpt_buf) -++ return -ENOMEM; -++#else -++ c->ltab_cmt = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs); -++ if (!c->ltab_cmt) -++ return -ENOMEM; -++ c->lpt_buf = vmalloc(c->leb_size); -++ if (!c->lpt_buf) -++ return -ENOMEM; -++#endif -++ -++ if (c->big_lpt) { -++ c->lsave = kmalloc(sizeof(int) * c->lsave_cnt, GFP_NOFS); -++ if (!c->lsave) -++ return -ENOMEM; -++ err = read_lsave(c); -++ if (err) -++ return err; -++ } -++ -++ for (i = 0; i < c->lpt_lebs; i++) -++ if (c->ltab[i].free == c->leb_size) { -++ err = ubifs_leb_unmap(c, i + c->lpt_first); -++ if (err) -++ return err; -++ } -++ -++ return 0; -++} -++ -++/** -++ * ubifs_lpt_init - initialize the LPT. -++ * @c: UBIFS file-system description object -++ * @rd: whether to initialize lpt for reading -++ * @wr: whether to initialize lpt for writing -++ * -++ * For mounting 'rw', @rd and @wr are both true. For mounting 'ro', @rd is true -++ * and @wr is false. For mounting from 'ro' to 'rw', @rd is false and @wr is -++ * true. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr) -++{ -++ int err; -++ -++ if (rd) { -++ err = lpt_init_rd(c); -++ if (err) -++ return err; -++ } -++ -++ if (wr) { -++ err = lpt_init_wr(c); -++ if (err) -++ return err; -++ } -++ -++ return 0; -++} -++ -++/** -++ * struct lpt_scan_node - somewhere to put nodes while we scan LPT. -++ * @nnode: where to keep a nnode -++ * @pnode: where to keep a pnode -++ * @cnode: where to keep a cnode -++ * @in_tree: is the node in the tree in memory -++ * @ptr.nnode: pointer to the nnode (if it is an nnode) which may be here or in -++ * the tree -++ * @ptr.pnode: ditto for pnode -++ * @ptr.cnode: ditto for cnode -++ */ -++struct lpt_scan_node { -++ union { -++ struct ubifs_nnode nnode; -++ struct ubifs_pnode pnode; -++ struct ubifs_cnode cnode; -++ }; -++ int in_tree; -++ union { -++ struct ubifs_nnode *nnode; -++ struct ubifs_pnode *pnode; -++ struct ubifs_cnode *cnode; -++ } ptr; -++}; -++ -++/** -++ * scan_get_nnode - for the scan, get a nnode from either the tree or flash. -++ * @c: the UBIFS file-system description object -++ * @path: where to put the nnode -++ * @parent: parent of the nnode -++ * @iip: index in parent of the nnode -++ * -++ * This function returns a pointer to the nnode on success or a negative error -++ * code on failure. -++ */ -++static struct ubifs_nnode *scan_get_nnode(struct ubifs_info *c, -++ struct lpt_scan_node *path, -++ struct ubifs_nnode *parent, int iip) -++{ -++ struct ubifs_nbranch *branch; -++ struct ubifs_nnode *nnode; -++ void *buf = c->lpt_nod_buf; -++ int err; -++ -++ branch = &parent->nbranch[iip]; -++ nnode = branch->nnode; -++ if (nnode) { -++ path->in_tree = 1; -++ path->ptr.nnode = nnode; -++ return nnode; -++ } -++ nnode = &path->nnode; -++ path->in_tree = 0; -++ path->ptr.nnode = nnode; -++ memset(nnode, 0, sizeof(struct ubifs_nnode)); -++ if (branch->lnum == 0) { -++ /* -++ * This nnode was not written which just means that the LEB -++ * properties in the subtree below it describe empty LEBs. We -++ * make the nnode as though we had read it, which in fact means -++ * doing almost nothing. -++ */ -++ if (c->big_lpt) -++ nnode->num = calc_nnode_num_from_parent(c, parent, iip); -++ } else { -++ err = ubi_read(c->ubi, branch->lnum, buf, branch->offs, -++ c->nnode_sz); -++ if (err) -++ return ERR_PTR(err); -++ err = unpack_nnode(c, buf, nnode); -++ if (err) -++ return ERR_PTR(err); -++ } -++ err = validate_nnode(c, nnode, parent, iip); -++ if (err) -++ return ERR_PTR(err); -++ if (!c->big_lpt) -++ nnode->num = calc_nnode_num_from_parent(c, parent, iip); -++ nnode->level = parent->level - 1; -++ nnode->parent = parent; -++ nnode->iip = iip; -++ return nnode; -++} -++ -++/** -++ * scan_get_pnode - for the scan, get a pnode from either the tree or flash. -++ * @c: the UBIFS file-system description object -++ * @path: where to put the pnode -++ * @parent: parent of the pnode -++ * @iip: index in parent of the pnode -++ * -++ * This function returns a pointer to the pnode on success or a negative error -++ * code on failure. -++ */ -++static struct ubifs_pnode *scan_get_pnode(struct ubifs_info *c, -++ struct lpt_scan_node *path, -++ struct ubifs_nnode *parent, int iip) -++{ -++ struct ubifs_nbranch *branch; -++ struct ubifs_pnode *pnode; -++ void *buf = c->lpt_nod_buf; -++ int err; -++ -++ branch = &parent->nbranch[iip]; -++ pnode = branch->pnode; -++ if (pnode) { -++ path->in_tree = 1; -++ path->ptr.pnode = pnode; -++ return pnode; -++ } -++ pnode = &path->pnode; -++ path->in_tree = 0; -++ path->ptr.pnode = pnode; -++ memset(pnode, 0, sizeof(struct ubifs_pnode)); -++ if (branch->lnum == 0) { -++ /* -++ * This pnode was not written which just means that the LEB -++ * properties in it describe empty LEBs. We make the pnode as -++ * though we had read it. -++ */ -++ int i; -++ -++ if (c->big_lpt) -++ pnode->num = calc_pnode_num_from_parent(c, parent, iip); -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ struct ubifs_lprops * const lprops = &pnode->lprops[i]; -++ -++ lprops->free = c->leb_size; -++ lprops->flags = ubifs_categorize_lprops(c, lprops); -++ } -++ } else { -++ ubifs_assert(branch->lnum >= c->lpt_first && -++ branch->lnum <= c->lpt_last); -++ ubifs_assert(branch->offs >= 0 && branch->offs < c->leb_size); -++ err = ubi_read(c->ubi, branch->lnum, buf, branch->offs, -++ c->pnode_sz); -++ if (err) -++ return ERR_PTR(err); -++ err = unpack_pnode(c, buf, pnode); -++ if (err) -++ return ERR_PTR(err); -++ } -++ err = validate_pnode(c, pnode, parent, iip); -++ if (err) -++ return ERR_PTR(err); -++ if (!c->big_lpt) -++ pnode->num = calc_pnode_num_from_parent(c, parent, iip); -++ pnode->parent = parent; -++ pnode->iip = iip; -++ set_pnode_lnum(c, pnode); -++ return pnode; -++} -++ -++/** -++ * ubifs_lpt_scan_nolock - scan the LPT. -++ * @c: the UBIFS file-system description object -++ * @start_lnum: LEB number from which to start scanning -++ * @end_lnum: LEB number at which to stop scanning -++ * @scan_cb: callback function called for each lprops -++ * @data: data to be passed to the callback function -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_lpt_scan_nolock(struct ubifs_info *c, int start_lnum, int end_lnum, -++ ubifs_lpt_scan_callback scan_cb, void *data) -++{ -++ int err = 0, i, h, iip, shft; -++ struct ubifs_nnode *nnode; -++ struct ubifs_pnode *pnode; -++ struct lpt_scan_node *path; -++ -++ if (start_lnum == -1) { -++ start_lnum = end_lnum + 1; -++ if (start_lnum >= c->leb_cnt) -++ start_lnum = c->main_first; -++ } -++ -++ ubifs_assert(start_lnum >= c->main_first && start_lnum < c->leb_cnt); -++ ubifs_assert(end_lnum >= c->main_first && end_lnum < c->leb_cnt); -++ -++ if (!c->nroot) { -++ err = ubifs_read_nnode(c, NULL, 0); -++ if (err) -++ return err; -++ } -++ -++ path = kmalloc(sizeof(struct lpt_scan_node) * (c->lpt_hght + 1), -++ GFP_NOFS); -++ if (!path) -++ return -ENOMEM; -++ -++ path[0].ptr.nnode = c->nroot; -++ path[0].in_tree = 1; -++again: -++ /* Descend to the pnode containing start_lnum */ -++ nnode = c->nroot; -++ i = start_lnum - c->main_first; -++ shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT; -++ for (h = 1; h < c->lpt_hght; h++) { -++ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); -++ shft -= UBIFS_LPT_FANOUT_SHIFT; -++ nnode = scan_get_nnode(c, path + h, nnode, iip); -++ if (IS_ERR(nnode)) { -++ err = PTR_ERR(nnode); -++ goto out; -++ } -++ } -++ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); -++ shft -= UBIFS_LPT_FANOUT_SHIFT; -++ pnode = scan_get_pnode(c, path + h, nnode, iip); -++ if (IS_ERR(pnode)) { -++ err = PTR_ERR(pnode); -++ goto out; -++ } -++ iip = (i & (UBIFS_LPT_FANOUT - 1)); -++ -++ /* Loop for each lprops */ -++ while (1) { -++ struct ubifs_lprops *lprops = &pnode->lprops[iip]; -++ int ret, lnum = lprops->lnum; -++ -++ ret = scan_cb(c, lprops, path[h].in_tree, data); -++ if (ret < 0) { -++ err = ret; -++ goto out; -++ } -++ if (ret & LPT_SCAN_ADD) { -++ /* Add all the nodes in path to the tree in memory */ -++ for (h = 1; h < c->lpt_hght; h++) { -++ const size_t sz = sizeof(struct ubifs_nnode); -++ struct ubifs_nnode *parent; -++ -++ if (path[h].in_tree) -++ continue; -++ nnode = kmalloc(sz, GFP_NOFS); -++ if (!nnode) { -++ err = -ENOMEM; -++ goto out; -++ } -++ memcpy(nnode, &path[h].nnode, sz); -++ parent = nnode->parent; -++ parent->nbranch[nnode->iip].nnode = nnode; -++ path[h].ptr.nnode = nnode; -++ path[h].in_tree = 1; -++ path[h + 1].cnode.parent = nnode; -++ } -++ if (path[h].in_tree) -++ ubifs_ensure_cat(c, lprops); -++ else { -++ const size_t sz = sizeof(struct ubifs_pnode); -++ struct ubifs_nnode *parent; -++ -++ pnode = kmalloc(sz, GFP_NOFS); -++ if (!pnode) { -++ err = -ENOMEM; -++ goto out; -++ } -++ memcpy(pnode, &path[h].pnode, sz); -++ parent = pnode->parent; -++ parent->nbranch[pnode->iip].pnode = pnode; -++ path[h].ptr.pnode = pnode; -++ path[h].in_tree = 1; -++ update_cats(c, pnode); -++ c->pnodes_have += 1; -++ } -++ err = dbg_check_lpt_nodes(c, (struct ubifs_cnode *) -++ c->nroot, 0, 0); -++ if (err) -++ goto out; -++ err = dbg_check_cats(c); -++ if (err) -++ goto out; -++ } -++ if (ret & LPT_SCAN_STOP) { -++ err = 0; -++ break; -++ } -++ /* Get the next lprops */ -++ if (lnum == end_lnum) { -++ /* -++ * We got to the end without finding what we were -++ * looking for -++ */ -++ err = -ENOSPC; -++ goto out; -++ } -++ if (lnum + 1 >= c->leb_cnt) { -++ /* Wrap-around to the beginning */ -++ start_lnum = c->main_first; -++ goto again; -++ } -++ if (iip + 1 < UBIFS_LPT_FANOUT) { -++ /* Next lprops is in the same pnode */ -++ iip += 1; -++ continue; -++ } -++ /* We need to get the next pnode. Go up until we can go right */ -++ iip = pnode->iip; -++ while (1) { -++ h -= 1; -++ ubifs_assert(h >= 0); -++ nnode = path[h].ptr.nnode; -++ if (iip + 1 < UBIFS_LPT_FANOUT) -++ break; -++ iip = nnode->iip; -++ } -++ /* Go right */ -++ iip += 1; -++ /* Descend to the pnode */ -++ h += 1; -++ for (; h < c->lpt_hght; h++) { -++ nnode = scan_get_nnode(c, path + h, nnode, iip); -++ if (IS_ERR(nnode)) { -++ err = PTR_ERR(nnode); -++ goto out; -++ } -++ iip = 0; -++ } -++ pnode = scan_get_pnode(c, path + h, nnode, iip); -++ if (IS_ERR(pnode)) { -++ err = PTR_ERR(pnode); -++ goto out; -++ } -++ iip = 0; -++ } -++out: -++ kfree(path); -++ return err; -++} -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ -++/** -++ * dbg_chk_pnode - check a pnode. -++ * @c: the UBIFS file-system description object -++ * @pnode: pnode to check -++ * @col: pnode column -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, -++ int col) -++{ -++ int i; -++ -++ if (pnode->num != col) { -++ dbg_err("pnode num %d expected %d parent num %d iip %d", -++ pnode->num, col, pnode->parent->num, pnode->iip); -++ return -EINVAL; -++ } -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ struct ubifs_lprops *lp, *lprops = &pnode->lprops[i]; -++ int lnum = (pnode->num << UBIFS_LPT_FANOUT_SHIFT) + i + -++ c->main_first; -++ int found, cat = lprops->flags & LPROPS_CAT_MASK; -++ struct ubifs_lpt_heap *heap; -++ struct list_head *list = NULL; -++ -++ if (lnum >= c->leb_cnt) -++ continue; -++ if (lprops->lnum != lnum) { -++ dbg_err("bad LEB number %d expected %d", -++ lprops->lnum, lnum); -++ return -EINVAL; -++ } -++ if (lprops->flags & LPROPS_TAKEN) { -++ if (cat != LPROPS_UNCAT) { -++ dbg_err("LEB %d taken but not uncat %d", -++ lprops->lnum, cat); -++ return -EINVAL; -++ } -++ continue; -++ } -++ if (lprops->flags & LPROPS_INDEX) { -++ switch (cat) { -++ case LPROPS_UNCAT: -++ case LPROPS_DIRTY_IDX: -++ case LPROPS_FRDI_IDX: -++ break; -++ default: -++ dbg_err("LEB %d index but cat %d", -++ lprops->lnum, cat); -++ return -EINVAL; -++ } -++ } else { -++ switch (cat) { -++ case LPROPS_UNCAT: -++ case LPROPS_DIRTY: -++ case LPROPS_FREE: -++ case LPROPS_EMPTY: -++ case LPROPS_FREEABLE: -++ break; -++ default: -++ dbg_err("LEB %d not index but cat %d", -++ lprops->lnum, cat); -++ return -EINVAL; -++ } -++ } -++ switch (cat) { -++ case LPROPS_UNCAT: -++ list = &c->uncat_list; -++ break; -++ case LPROPS_EMPTY: -++ list = &c->empty_list; -++ break; -++ case LPROPS_FREEABLE: -++ list = &c->freeable_list; -++ break; -++ case LPROPS_FRDI_IDX: -++ list = &c->frdi_idx_list; -++ break; -++ } -++ found = 0; -++ switch (cat) { -++ case LPROPS_DIRTY: -++ case LPROPS_DIRTY_IDX: -++ case LPROPS_FREE: -++ heap = &c->lpt_heap[cat - 1]; -++ if (lprops->hpos < heap->cnt && -++ heap->arr[lprops->hpos] == lprops) -++ found = 1; -++ break; -++ case LPROPS_UNCAT: -++ case LPROPS_EMPTY: -++ case LPROPS_FREEABLE: -++ case LPROPS_FRDI_IDX: -++ list_for_each_entry(lp, list, list) -++ if (lprops == lp) { -++ found = 1; -++ break; -++ } -++ break; -++ } -++ if (!found) { -++ dbg_err("LEB %d cat %d not found in cat heap/list", -++ lprops->lnum, cat); -++ return -EINVAL; -++ } -++ switch (cat) { -++ case LPROPS_EMPTY: -++ if (lprops->free != c->leb_size) { -++ dbg_err("LEB %d cat %d free %d dirty %d", -++ lprops->lnum, cat, lprops->free, -++ lprops->dirty); -++ return -EINVAL; -++ } -++ case LPROPS_FREEABLE: -++ case LPROPS_FRDI_IDX: -++ if (lprops->free + lprops->dirty != c->leb_size) { -++ dbg_err("LEB %d cat %d free %d dirty %d", -++ lprops->lnum, cat, lprops->free, -++ lprops->dirty); -++ return -EINVAL; -++ } -++ } -++ } -++ return 0; -++} -++ -++/** -++ * dbg_check_lpt_nodes - check nnodes and pnodes. -++ * @c: the UBIFS file-system description object -++ * @cnode: next cnode (nnode or pnode) to check -++ * @row: row of cnode (root is zero) -++ * @col: column of cnode (leftmost is zero) -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode, -++ int row, int col) -++{ -++ struct ubifs_nnode *nnode, *nn; -++ struct ubifs_cnode *cn; -++ int num, iip = 0, err; -++ -++ if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS)) -++ return 0; -++ -++ while (cnode) { -++ ubifs_assert(row >= 0); -++ nnode = cnode->parent; -++ if (cnode->level) { -++ /* cnode is a nnode */ -++ num = calc_nnode_num(row, col); -++ if (cnode->num != num) { -++ dbg_err("nnode num %d expected %d " -++ "parent num %d iip %d", cnode->num, num, -++ (nnode ? nnode->num : 0), cnode->iip); -++ return -EINVAL; -++ } -++ nn = (struct ubifs_nnode *)cnode; -++ while (iip < UBIFS_LPT_FANOUT) { -++ cn = nn->nbranch[iip].cnode; -++ if (cn) { -++ /* Go down */ -++ row += 1; -++ col <<= UBIFS_LPT_FANOUT_SHIFT; -++ col += iip; -++ iip = 0; -++ cnode = cn; -++ break; -++ } -++ /* Go right */ -++ iip += 1; -++ } -++ if (iip < UBIFS_LPT_FANOUT) -++ continue; -++ } else { -++ struct ubifs_pnode *pnode; -++ -++ /* cnode is a pnode */ -++ pnode = (struct ubifs_pnode *)cnode; -++ err = dbg_chk_pnode(c, pnode, col); -++ if (err) -++ return err; -++ } -++ /* Go up and to the right */ -++ row -= 1; -++ col >>= UBIFS_LPT_FANOUT_SHIFT; -++ iip = cnode->iip + 1; -++ cnode = (struct ubifs_cnode *)nnode; -++ } -++ return 0; -++} -++ -++#endif /* CONFIG_UBIFS_FS_DEBUG */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/lpt_commit.c linux-2.6.24.7/fs/ubifs/lpt_commit.c -+--- linux-2.6.24.7.old/fs/ubifs/lpt_commit.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/lpt_commit.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1639 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Adrian Hunter -++ * Artem Bityutskiy (Битюцкий Ðртём) -++ */ -++ -++/* -++ * This file implements commit-related functionality of the LEB properties -++ * subsystem. -++ */ -++ -++#include -++#include "ubifs.h" -++ -++/** -++ * first_dirty_cnode - find first dirty cnode. -++ * @c: UBIFS file-system description object -++ * @nnode: nnode at which to start -++ * -++ * This function returns the first dirty cnode or %NULL if there is not one. -++ */ -++static struct ubifs_cnode *first_dirty_cnode(struct ubifs_nnode *nnode) -++{ -++ ubifs_assert(nnode); -++ while (1) { -++ int i, cont = 0; -++ -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ struct ubifs_cnode *cnode; -++ -++ cnode = nnode->nbranch[i].cnode; -++ if (cnode && -++ test_bit(DIRTY_CNODE, &cnode->flags)) { -++ if (cnode->level == 0) -++ return cnode; -++ nnode = (struct ubifs_nnode *)cnode; -++ cont = 1; -++ break; -++ } -++ } -++ if (!cont) -++ return (struct ubifs_cnode *)nnode; -++ } -++} -++ -++/** -++ * next_dirty_cnode - find next dirty cnode. -++ * @cnode: cnode from which to begin searching -++ * -++ * This function returns the next dirty cnode or %NULL if there is not one. -++ */ -++static struct ubifs_cnode *next_dirty_cnode(struct ubifs_cnode *cnode) -++{ -++ struct ubifs_nnode *nnode; -++ int i; -++ -++ ubifs_assert(cnode); -++ nnode = cnode->parent; -++ if (!nnode) -++ return NULL; -++ for (i = cnode->iip + 1; i < UBIFS_LPT_FANOUT; i++) { -++ cnode = nnode->nbranch[i].cnode; -++ if (cnode && test_bit(DIRTY_CNODE, &cnode->flags)) { -++ if (cnode->level == 0) -++ return cnode; /* cnode is a pnode */ -++ /* cnode is a nnode */ -++ return first_dirty_cnode((struct ubifs_nnode *)cnode); -++ } -++ } -++ return (struct ubifs_cnode *)nnode; -++} -++ -++/** -++ * get_cnodes_to_commit - create list of dirty cnodes to commit. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns the number of cnodes to commit. -++ */ -++static int get_cnodes_to_commit(struct ubifs_info *c) -++{ -++ struct ubifs_cnode *cnode, *cnext; -++ int cnt = 0; -++ -++ if (!c->nroot) -++ return 0; -++ -++ if (!test_bit(DIRTY_CNODE, &c->nroot->flags)) -++ return 0; -++ -++ c->lpt_cnext = first_dirty_cnode(c->nroot); -++ cnode = c->lpt_cnext; -++ if (!cnode) -++ return 0; -++ cnt += 1; -++ while (1) { -++ ubifs_assert(!test_bit(COW_ZNODE, &cnode->flags)); -++ __set_bit(COW_ZNODE, &cnode->flags); -++ cnext = next_dirty_cnode(cnode); -++ if (!cnext) { -++ cnode->cnext = c->lpt_cnext; -++ break; -++ } -++ cnode->cnext = cnext; -++ cnode = cnext; -++ cnt += 1; -++ } -++ dbg_cmt("committing %d cnodes", cnt); -++ dbg_lp("committing %d cnodes", cnt); -++ ubifs_assert(cnt == c->dirty_nn_cnt + c->dirty_pn_cnt); -++ return cnt; -++} -++ -++/** -++ * upd_ltab - update LPT LEB properties. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number -++ * @free: amount of free space -++ * @dirty: amount of dirty space to add -++ */ -++static void upd_ltab(struct ubifs_info *c, int lnum, int free, int dirty) -++{ -++ dbg_lp("LEB %d free %d dirty %d to %d +%d", -++ lnum, c->ltab[lnum - c->lpt_first].free, -++ c->ltab[lnum - c->lpt_first].dirty, free, dirty); -++ ubifs_assert(lnum >= c->lpt_first && lnum <= c->lpt_last); -++ c->ltab[lnum - c->lpt_first].free = free; -++ c->ltab[lnum - c->lpt_first].dirty += dirty; -++} -++ -++/** -++ * alloc_lpt_leb - allocate an LPT LEB that is empty. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number is passed and returned here -++ * -++ * This function finds the next empty LEB in the ltab starting from @lnum. If a -++ * an empty LEB is found it is returned in @lnum and the function returns %0. -++ * Otherwise the function returns -ENOSPC. Note however, that LPT is designed -++ * never to run out of space. -++ */ -++static int alloc_lpt_leb(struct ubifs_info *c, int *lnum) -++{ -++ int i, n; -++ -++ n = *lnum - c->lpt_first + 1; -++ for (i = n; i < c->lpt_lebs; i++) { -++ if (c->ltab[i].tgc || c->ltab[i].cmt) -++ continue; -++ if (c->ltab[i].free == c->leb_size) { -++ c->ltab[i].cmt = 1; -++ *lnum = i + c->lpt_first; -++ return 0; -++ } -++ } -++ -++ for (i = 0; i < n; i++) { -++ if (c->ltab[i].tgc || c->ltab[i].cmt) -++ continue; -++ if (c->ltab[i].free == c->leb_size) { -++ c->ltab[i].cmt = 1; -++ *lnum = i + c->lpt_first; -++ return 0; -++ } -++ } -++ dbg_err("last LEB %d", *lnum); -++ dump_stack(); -++ return -ENOSPC; -++} -++ -++/** -++ * layout_cnodes - layout cnodes for commit. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int layout_cnodes(struct ubifs_info *c) -++{ -++ int lnum, offs, len, alen, done_lsave, done_ltab, err; -++ struct ubifs_cnode *cnode; -++ -++ cnode = c->lpt_cnext; -++ if (!cnode) -++ return 0; -++ lnum = c->nhead_lnum; -++ offs = c->nhead_offs; -++ /* Try to place lsave and ltab nicely */ -++ done_lsave = !c->big_lpt; -++ done_ltab = 0; -++ if (!done_lsave && offs + c->lsave_sz <= c->leb_size) { -++ done_lsave = 1; -++ c->lsave_lnum = lnum; -++ c->lsave_offs = offs; -++ offs += c->lsave_sz; -++ } -++ -++ if (offs + c->ltab_sz <= c->leb_size) { -++ done_ltab = 1; -++ c->ltab_lnum = lnum; -++ c->ltab_offs = offs; -++ offs += c->ltab_sz; -++ } -++ -++ do { -++ if (cnode->level) { -++ len = c->nnode_sz; -++ c->dirty_nn_cnt -= 1; -++ } else { -++ len = c->pnode_sz; -++ c->dirty_pn_cnt -= 1; -++ } -++ while (offs + len > c->leb_size) { -++ alen = ALIGN(offs, c->min_io_size); -++ upd_ltab(c, lnum, c->leb_size - alen, alen - offs); -++ err = alloc_lpt_leb(c, &lnum); -++ if (err) -++ return err; -++ offs = 0; -++ ubifs_assert(lnum >= c->lpt_first && -++ lnum <= c->lpt_last); -++ /* Try to place lsave and ltab nicely */ -++ if (!done_lsave) { -++ done_lsave = 1; -++ c->lsave_lnum = lnum; -++ c->lsave_offs = offs; -++ offs += c->lsave_sz; -++ continue; -++ } -++ if (!done_ltab) { -++ done_ltab = 1; -++ c->ltab_lnum = lnum; -++ c->ltab_offs = offs; -++ offs += c->ltab_sz; -++ continue; -++ } -++ break; -++ } -++ if (cnode->parent) { -++ cnode->parent->nbranch[cnode->iip].lnum = lnum; -++ cnode->parent->nbranch[cnode->iip].offs = offs; -++ } else { -++ c->lpt_lnum = lnum; -++ c->lpt_offs = offs; -++ } -++ offs += len; -++ cnode = cnode->cnext; -++ } while (cnode && cnode != c->lpt_cnext); -++ -++ /* Make sure to place LPT's save table */ -++ if (!done_lsave) { -++ if (offs + c->lsave_sz > c->leb_size) { -++ alen = ALIGN(offs, c->min_io_size); -++ upd_ltab(c, lnum, c->leb_size - alen, alen - offs); -++ err = alloc_lpt_leb(c, &lnum); -++ if (err) -++ return err; -++ offs = 0; -++ ubifs_assert(lnum >= c->lpt_first && -++ lnum <= c->lpt_last); -++ } -++ done_lsave = 1; -++ c->lsave_lnum = lnum; -++ c->lsave_offs = offs; -++ offs += c->lsave_sz; -++ } -++ -++ /* Make sure to place LPT's own lprops table */ -++ if (!done_ltab) { -++ if (offs + c->ltab_sz > c->leb_size) { -++ alen = ALIGN(offs, c->min_io_size); -++ upd_ltab(c, lnum, c->leb_size - alen, alen - offs); -++ err = alloc_lpt_leb(c, &lnum); -++ if (err) -++ return err; -++ offs = 0; -++ ubifs_assert(lnum >= c->lpt_first && -++ lnum <= c->lpt_last); -++ } -++ done_ltab = 1; -++ c->ltab_lnum = lnum; -++ c->ltab_offs = offs; -++ offs += c->ltab_sz; -++ } -++ -++ alen = ALIGN(offs, c->min_io_size); -++ upd_ltab(c, lnum, c->leb_size - alen, alen - offs); -++ return 0; -++} -++ -++/** -++ * realloc_lpt_leb - allocate an LPT LEB that is empty. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number is passed and returned here -++ * -++ * This function duplicates exactly the results of the function alloc_lpt_leb. -++ * It is used during end commit to reallocate the same LEB numbers that were -++ * allocated by alloc_lpt_leb during start commit. -++ * -++ * This function finds the next LEB that was allocated by the alloc_lpt_leb -++ * function starting from @lnum. If a LEB is found it is returned in @lnum and -++ * the function returns %0. Otherwise the function returns -ENOSPC. -++ * Note however, that LPT is designed never to run out of space. -++ */ -++static int realloc_lpt_leb(struct ubifs_info *c, int *lnum) -++{ -++ int i, n; -++ -++ n = *lnum - c->lpt_first + 1; -++ for (i = n; i < c->lpt_lebs; i++) -++ if (c->ltab[i].cmt) { -++ c->ltab[i].cmt = 0; -++ *lnum = i + c->lpt_first; -++ return 0; -++ } -++ -++ for (i = 0; i < n; i++) -++ if (c->ltab[i].cmt) { -++ c->ltab[i].cmt = 0; -++ *lnum = i + c->lpt_first; -++ return 0; -++ } -++ dbg_err("last LEB %d", *lnum); -++ dump_stack(); -++ return -ENOSPC; -++} -++ -++/** -++ * write_cnodes - write cnodes for commit. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int write_cnodes(struct ubifs_info *c) -++{ -++ int lnum, offs, len, from, err, wlen, alen, done_ltab, done_lsave; -++ struct ubifs_cnode *cnode; -++ void *buf = c->lpt_buf; -++ -++ cnode = c->lpt_cnext; -++ if (!cnode) -++ return 0; -++ lnum = c->nhead_lnum; -++ offs = c->nhead_offs; -++ from = offs; -++ /* Ensure empty LEB is unmapped */ -++ if (offs == 0) { -++ err = ubifs_leb_unmap(c, lnum); -++ if (err) -++ return err; -++ } -++ /* Try to place lsave and ltab nicely */ -++ done_lsave = !c->big_lpt; -++ done_ltab = 0; -++ if (!done_lsave && offs + c->lsave_sz <= c->leb_size) { -++ done_lsave = 1; -++ ubifs_pack_lsave(c, buf + offs, c->lsave); -++ offs += c->lsave_sz; -++ } -++ -++ if (offs + c->ltab_sz <= c->leb_size) { -++ done_ltab = 1; -++ ubifs_pack_ltab(c, buf + offs, c->ltab_cmt); -++ offs += c->ltab_sz; -++ } -++ -++ /* Loop for each cnode */ -++ do { -++ if (cnode->level) -++ len = c->nnode_sz; -++ else -++ len = c->pnode_sz; -++ while (offs + len > c->leb_size) { -++ wlen = offs - from; -++ if (wlen) { -++ alen = ALIGN(wlen, c->min_io_size); -++ memset(buf + offs, 0xff, alen - wlen); -++ err = ubifs_leb_write(c, lnum, buf + from, from, -++ alen, UBI_SHORTTERM); -++ if (err) -++ return err; -++ } -++ err = realloc_lpt_leb(c, &lnum); -++ if (err) -++ return err; -++ offs = 0; -++ from = 0; -++ ubifs_assert(lnum >= c->lpt_first && -++ lnum <= c->lpt_last); -++ err = ubifs_leb_unmap(c, lnum); -++ if (err) -++ return err; -++ /* Try to place lsave and ltab nicely */ -++ if (!done_lsave) { -++ done_lsave = 1; -++ ubifs_pack_lsave(c, buf + offs, c->lsave); -++ offs += c->lsave_sz; -++ continue; -++ } -++ if (!done_ltab) { -++ done_ltab = 1; -++ ubifs_pack_ltab(c, buf + offs, c->ltab_cmt); -++ offs += c->ltab_sz; -++ continue; -++ } -++ break; -++ } -++ if (cnode->level) -++ ubifs_pack_nnode(c, buf + offs, -++ (struct ubifs_nnode *)cnode); -++ else -++ ubifs_pack_pnode(c, buf + offs, -++ (struct ubifs_pnode *)cnode); -++ /* -++ * The reason for the barriers is the same as in case of TNC. -++ * See comment in 'write_index()'. 'dirty_cow_nnode()' and -++ * 'dirty_cow_pnode()' are the functions for which this is -++ * important. -++ */ -++ clear_bit(DIRTY_CNODE, &cnode->flags); -++ smp_mb__before_clear_bit(); -++ clear_bit(COW_ZNODE, &cnode->flags); -++ smp_mb__after_clear_bit(); -++ offs += len; -++ cnode = cnode->cnext; -++ } while (cnode && cnode != c->lpt_cnext); -++ -++ /* Make sure to place LPT's save table */ -++ if (!done_lsave) { -++ if (offs + c->lsave_sz > c->leb_size) { -++ wlen = offs - from; -++ alen = ALIGN(wlen, c->min_io_size); -++ memset(buf + offs, 0xff, alen - wlen); -++ err = ubifs_leb_write(c, lnum, buf + from, from, alen, -++ UBI_SHORTTERM); -++ if (err) -++ return err; -++ err = realloc_lpt_leb(c, &lnum); -++ if (err) -++ return err; -++ offs = 0; -++ ubifs_assert(lnum >= c->lpt_first && -++ lnum <= c->lpt_last); -++ err = ubifs_leb_unmap(c, lnum); -++ if (err) -++ return err; -++ } -++ done_lsave = 1; -++ ubifs_pack_lsave(c, buf + offs, c->lsave); -++ offs += c->lsave_sz; -++ } -++ -++ /* Make sure to place LPT's own lprops table */ -++ if (!done_ltab) { -++ if (offs + c->ltab_sz > c->leb_size) { -++ wlen = offs - from; -++ alen = ALIGN(wlen, c->min_io_size); -++ memset(buf + offs, 0xff, alen - wlen); -++ err = ubifs_leb_write(c, lnum, buf + from, from, alen, -++ UBI_SHORTTERM); -++ if (err) -++ return err; -++ err = realloc_lpt_leb(c, &lnum); -++ if (err) -++ return err; -++ offs = 0; -++ ubifs_assert(lnum >= c->lpt_first && -++ lnum <= c->lpt_last); -++ err = ubifs_leb_unmap(c, lnum); -++ if (err) -++ return err; -++ } -++ done_ltab = 1; -++ ubifs_pack_ltab(c, buf + offs, c->ltab_cmt); -++ offs += c->ltab_sz; -++ } -++ -++ /* Write remaining data in buffer */ -++ wlen = offs - from; -++ alen = ALIGN(wlen, c->min_io_size); -++ memset(buf + offs, 0xff, alen - wlen); -++ err = ubifs_leb_write(c, lnum, buf + from, from, alen, UBI_SHORTTERM); -++ if (err) -++ return err; -++ c->nhead_lnum = lnum; -++ c->nhead_offs = ALIGN(offs, c->min_io_size); -++ -++ dbg_lp("LPT root is at %d:%d", c->lpt_lnum, c->lpt_offs); -++ dbg_lp("LPT head is at %d:%d", c->nhead_lnum, c->nhead_offs); -++ dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs); -++ if (c->big_lpt) -++ dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs); -++ return 0; -++} -++ -++/** -++ * next_pnode - find next pnode. -++ * @c: UBIFS file-system description object -++ * @pnode: pnode -++ * -++ * This function returns the next pnode or %NULL if there are no more pnodes. -++ */ -++static struct ubifs_pnode *next_pnode(struct ubifs_info *c, -++ struct ubifs_pnode *pnode) -++{ -++ struct ubifs_nnode *nnode; -++ int iip; -++ -++ /* Try to go right */ -++ nnode = pnode->parent; -++ iip = pnode->iip + 1; -++ if (iip < UBIFS_LPT_FANOUT) { -++ /* We assume here that LEB zero is never an LPT LEB */ -++ if (nnode->nbranch[iip].lnum) -++ return ubifs_get_pnode(c, nnode, iip); -++ else -++ return NULL; -++ } -++ -++ /* Go up while can't go right */ -++ do { -++ iip = nnode->iip + 1; -++ nnode = nnode->parent; -++ if (!nnode) -++ return NULL; -++ /* We assume here that LEB zero is never an LPT LEB */ -++ } while (iip >= UBIFS_LPT_FANOUT || !nnode->nbranch[iip].lnum); -++ -++ /* Go right */ -++ nnode = ubifs_get_nnode(c, nnode, iip); -++ if (IS_ERR(nnode)) -++ return (void *)nnode; -++ -++ /* Go down to level 1 */ -++ while (nnode->level > 1) { -++ nnode = ubifs_get_nnode(c, nnode, 0); -++ if (IS_ERR(nnode)) -++ return (void *)nnode; -++ } -++ -++ return ubifs_get_pnode(c, nnode, 0); -++} -++ -++/** -++ * pnode_lookup - lookup a pnode in the LPT. -++ * @c: UBIFS file-system description object -++ * @i: pnode number (0 to main_lebs - 1) -++ * -++ * This function returns a pointer to the pnode on success or a negative -++ * error code on failure. -++ */ -++static struct ubifs_pnode *pnode_lookup(struct ubifs_info *c, int i) -++{ -++ int err, h, iip, shft; -++ struct ubifs_nnode *nnode; -++ -++ if (!c->nroot) { -++ err = ubifs_read_nnode(c, NULL, 0); -++ if (err) -++ return ERR_PTR(err); -++ } -++ i <<= UBIFS_LPT_FANOUT_SHIFT; -++ nnode = c->nroot; -++ shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT; -++ for (h = 1; h < c->lpt_hght; h++) { -++ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); -++ shft -= UBIFS_LPT_FANOUT_SHIFT; -++ nnode = ubifs_get_nnode(c, nnode, iip); -++ if (IS_ERR(nnode)) -++ return ERR_PTR(PTR_ERR(nnode)); -++ } -++ iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); -++ return ubifs_get_pnode(c, nnode, iip); -++} -++ -++/** -++ * add_pnode_dirt - add dirty space to LPT LEB properties. -++ * @c: UBIFS file-system description object -++ * @pnode: pnode for which to add dirt -++ */ -++static void add_pnode_dirt(struct ubifs_info *c, struct ubifs_pnode *pnode) -++{ -++ ubifs_add_lpt_dirt(c, pnode->parent->nbranch[pnode->iip].lnum, -++ c->pnode_sz); -++} -++ -++/** -++ * do_make_pnode_dirty - mark a pnode dirty. -++ * @c: UBIFS file-system description object -++ * @pnode: pnode to mark dirty -++ */ -++static void do_make_pnode_dirty(struct ubifs_info *c, struct ubifs_pnode *pnode) -++{ -++ /* Assumes cnext list is empty i.e. not called during commit */ -++ if (!test_and_set_bit(DIRTY_CNODE, &pnode->flags)) { -++ struct ubifs_nnode *nnode; -++ -++ c->dirty_pn_cnt += 1; -++ add_pnode_dirt(c, pnode); -++ /* Mark parent and ancestors dirty too */ -++ nnode = pnode->parent; -++ while (nnode) { -++ if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) { -++ c->dirty_nn_cnt += 1; -++ ubifs_add_nnode_dirt(c, nnode); -++ nnode = nnode->parent; -++ } else -++ break; -++ } -++ } -++} -++ -++/** -++ * make_tree_dirty - mark the entire LEB properties tree dirty. -++ * @c: UBIFS file-system description object -++ * -++ * This function is used by the "small" LPT model to cause the entire LEB -++ * properties tree to be written. The "small" LPT model does not use LPT -++ * garbage collection because it is more efficient to write the entire tree -++ * (because it is small). -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int make_tree_dirty(struct ubifs_info *c) -++{ -++ struct ubifs_pnode *pnode; -++ -++ pnode = pnode_lookup(c, 0); -++ while (pnode) { -++ do_make_pnode_dirty(c, pnode); -++ pnode = next_pnode(c, pnode); -++ if (IS_ERR(pnode)) -++ return PTR_ERR(pnode); -++ } -++ return 0; -++} -++ -++/** -++ * need_write_all - determine if the LPT area is running out of free space. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns %1 if the LPT area is running out of free space and %0 -++ * if it is not. -++ */ -++static int need_write_all(struct ubifs_info *c) -++{ -++ long long free = 0; -++ int i; -++ -++ for (i = 0; i < c->lpt_lebs; i++) { -++ if (i + c->lpt_first == c->nhead_lnum) -++ free += c->leb_size - c->nhead_offs; -++ else if (c->ltab[i].free == c->leb_size) -++ free += c->leb_size; -++ else if (c->ltab[i].free + c->ltab[i].dirty == c->leb_size) -++ free += c->leb_size; -++ } -++ /* Less than twice the size left */ -++ if (free <= c->lpt_sz * 2) -++ return 1; -++ return 0; -++} -++ -++/** -++ * lpt_tgc_start - start trivial garbage collection of LPT LEBs. -++ * @c: UBIFS file-system description object -++ * -++ * LPT trivial garbage collection is where a LPT LEB contains only dirty and -++ * free space and so may be reused as soon as the next commit is completed. -++ * This function is called during start commit to mark LPT LEBs for trivial GC. -++ */ -++static void lpt_tgc_start(struct ubifs_info *c) -++{ -++ int i; -++ -++ for (i = 0; i < c->lpt_lebs; i++) { -++ if (i + c->lpt_first == c->nhead_lnum) -++ continue; -++ if (c->ltab[i].dirty > 0 && -++ c->ltab[i].free + c->ltab[i].dirty == c->leb_size) { -++ c->ltab[i].tgc = 1; -++ c->ltab[i].free = c->leb_size; -++ c->ltab[i].dirty = 0; -++ dbg_lp("LEB %d", i + c->lpt_first); -++ } -++ } -++} -++ -++/** -++ * lpt_tgc_end - end trivial garbage collection of LPT LEBs. -++ * @c: UBIFS file-system description object -++ * -++ * LPT trivial garbage collection is where a LPT LEB contains only dirty and -++ * free space and so may be reused as soon as the next commit is completed. -++ * This function is called after the commit is completed (master node has been -++ * written) and unmaps LPT LEBs that were marked for trivial GC. -++ */ -++static int lpt_tgc_end(struct ubifs_info *c) -++{ -++ int i, err; -++ -++ for (i = 0; i < c->lpt_lebs; i++) -++ if (c->ltab[i].tgc) { -++ err = ubifs_leb_unmap(c, i + c->lpt_first); -++ if (err) -++ return err; -++ c->ltab[i].tgc = 0; -++ dbg_lp("LEB %d", i + c->lpt_first); -++ } -++ return 0; -++} -++ -++/** -++ * populate_lsave - fill the lsave array with important LEB numbers. -++ * @c: the UBIFS file-system description object -++ * -++ * This function is only called for the "big" model. It records a small number -++ * of LEB numbers of important LEBs. Important LEBs are ones that are (from -++ * most important to least important): empty, freeable, freeable index, dirty -++ * index, dirty or free. Upon mount, we read this list of LEB numbers and bring -++ * their pnodes into memory. That will stop us from having to scan the LPT -++ * straight away. For the "small" model we assume that scanning the LPT is no -++ * big deal. -++ */ -++static void populate_lsave(struct ubifs_info *c) -++{ -++ struct ubifs_lprops *lprops; -++ struct ubifs_lpt_heap *heap; -++ int i, cnt = 0; -++ -++ ubifs_assert(c->big_lpt); -++ if (!(c->lpt_drty_flgs & LSAVE_DIRTY)) { -++ c->lpt_drty_flgs |= LSAVE_DIRTY; -++ ubifs_add_lpt_dirt(c, c->lsave_lnum, c->lsave_sz); -++ } -++ list_for_each_entry(lprops, &c->empty_list, list) { -++ c->lsave[cnt++] = lprops->lnum; -++ if (cnt >= c->lsave_cnt) -++ return; -++ } -++ list_for_each_entry(lprops, &c->freeable_list, list) { -++ c->lsave[cnt++] = lprops->lnum; -++ if (cnt >= c->lsave_cnt) -++ return; -++ } -++ list_for_each_entry(lprops, &c->frdi_idx_list, list) { -++ c->lsave[cnt++] = lprops->lnum; -++ if (cnt >= c->lsave_cnt) -++ return; -++ } -++ heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1]; -++ for (i = 0; i < heap->cnt; i++) { -++ c->lsave[cnt++] = heap->arr[i]->lnum; -++ if (cnt >= c->lsave_cnt) -++ return; -++ } -++ heap = &c->lpt_heap[LPROPS_DIRTY - 1]; -++ for (i = 0; i < heap->cnt; i++) { -++ c->lsave[cnt++] = heap->arr[i]->lnum; -++ if (cnt >= c->lsave_cnt) -++ return; -++ } -++ heap = &c->lpt_heap[LPROPS_FREE - 1]; -++ for (i = 0; i < heap->cnt; i++) { -++ c->lsave[cnt++] = heap->arr[i]->lnum; -++ if (cnt >= c->lsave_cnt) -++ return; -++ } -++ /* Fill it up completely */ -++ while (cnt < c->lsave_cnt) -++ c->lsave[cnt++] = c->main_first; -++} -++ -++/** -++ * ubifs_lpt_start_commit - UBIFS commit starts. -++ * @c: the UBIFS file-system description object -++ * -++ * This function has to be called when UBIFS starts the commit operation. -++ * This function "freezes" all currently dirty LEB properties and does not -++ * change them anymore. Further changes are saved and tracked separately -++ * because they are not part of this commit. This function returns zero in case -++ * of success and a negative error code in case of failure. -++ */ -++int ubifs_lpt_start_commit(struct ubifs_info *c) -++{ -++ int err, cnt; -++ -++ dbg_lp(""); -++ -++ mutex_lock(&c->lp_mutex); -++ err = dbg_check_ltab(c); -++ if (err) -++ goto out; -++ -++ lpt_tgc_start(c); -++ -++ if (!c->dirty_pn_cnt) { -++ dbg_cmt("no cnodes to commit"); -++ err = 0; -++ goto out; -++ } -++ -++ if (!c->big_lpt && need_write_all(c)) { -++ /* If needed, write everything */ -++ err = make_tree_dirty(c); -++ if (err) -++ goto out; -++ lpt_tgc_start(c); -++ } -++ -++ if (c->big_lpt) -++ populate_lsave(c); -++ -++ cnt = get_cnodes_to_commit(c); -++ ubifs_assert(cnt != 0); -++ -++ err = layout_cnodes(c); -++ if (err) -++ goto out; -++ -++ /* Copy the LPT's own lprops for end commit to write */ -++ memcpy(c->ltab_cmt, c->ltab, -++ sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs); -++ c->lpt_drty_flgs &= ~(LTAB_DIRTY | LSAVE_DIRTY); -++ -++out: -++ mutex_unlock(&c->lp_mutex); -++ return err; -++} -++ -++/** -++ * free_obsolete_cnodes - free obsolete cnodes for commit end. -++ * @c: UBIFS file-system description object -++ */ -++static void free_obsolete_cnodes(struct ubifs_info *c) -++{ -++ struct ubifs_cnode *cnode, *cnext; -++ -++ cnext = c->lpt_cnext; -++ if (!cnext) -++ return; -++ do { -++ cnode = cnext; -++ cnext = cnode->cnext; -++ if (test_bit(OBSOLETE_CNODE, &cnode->flags)) -++ kfree(cnode); -++ else -++ cnode->cnext = NULL; -++ } while (cnext != c->lpt_cnext); -++ c->lpt_cnext = NULL; -++} -++ -++/** -++ * ubifs_lpt_end_commit - finish the commit operation. -++ * @c: the UBIFS file-system description object -++ * -++ * This function has to be called when the commit operation finishes. It -++ * flushes the changes which were "frozen" by 'ubifs_lprops_start_commit()' to -++ * the media. Returns zero in case of success and a negative error code in case -++ * of failure. -++ */ -++int ubifs_lpt_end_commit(struct ubifs_info *c) -++{ -++ int err; -++ -++ dbg_lp(""); -++ -++ if (!c->lpt_cnext) -++ return 0; -++ -++ err = write_cnodes(c); -++ if (err) -++ return err; -++ -++ mutex_lock(&c->lp_mutex); -++ free_obsolete_cnodes(c); -++ mutex_unlock(&c->lp_mutex); -++ -++ return 0; -++} -++ -++/** -++ * nnode_lookup - lookup a nnode in the LPT. -++ * @c: UBIFS file-system description object -++ * @i: nnode number -++ * -++ * This function returns a pointer to the nnode on success or a negative -++ * error code on failure. -++ */ -++static struct ubifs_nnode *nnode_lookup(struct ubifs_info *c, int i) -++{ -++ int err, iip; -++ struct ubifs_nnode *nnode; -++ -++ if (!c->nroot) { -++ err = ubifs_read_nnode(c, NULL, 0); -++ if (err) -++ return ERR_PTR(err); -++ } -++ nnode = c->nroot; -++ while (1) { -++ iip = i & (UBIFS_LPT_FANOUT - 1); -++ i >>= UBIFS_LPT_FANOUT_SHIFT; -++ if (!i) -++ break; -++ nnode = ubifs_get_nnode(c, nnode, iip); -++ if (IS_ERR(nnode)) -++ return nnode; -++ } -++ return nnode; -++} -++ -++/** -++ * make_nnode_dirty - find a nnode and, if found, make it dirty. -++ * @c: UBIFS file-system description object -++ * @node_num: nnode number of nnode to make dirty -++ * @lnum: LEB number where nnode was written -++ * @offs: offset where nnode was written -++ * -++ * This function is used by LPT garbage collection. LPT garbage collection is -++ * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection -++ * simply involves marking all the nodes in the LEB being garbage-collected as -++ * dirty. The dirty nodes are written next commit, after which the LEB is free -++ * to be reused. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int make_nnode_dirty(struct ubifs_info *c, int node_num, int lnum, -++ int offs) -++{ -++ struct ubifs_nnode *nnode; -++ -++ nnode = nnode_lookup(c, node_num); -++ if (IS_ERR(nnode)) -++ return PTR_ERR(nnode); -++ if (nnode->parent) { -++ struct ubifs_nbranch *branch; -++ -++ branch = &nnode->parent->nbranch[nnode->iip]; -++ if (branch->lnum != lnum || branch->offs != offs) -++ return 0; /* nnode is obsolete */ -++ } else if (c->lpt_lnum != lnum || c->lpt_offs != offs) -++ return 0; /* nnode is obsolete */ -++ /* Assumes cnext list is empty i.e. not called during commit */ -++ if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) { -++ c->dirty_nn_cnt += 1; -++ ubifs_add_nnode_dirt(c, nnode); -++ /* Mark parent and ancestors dirty too */ -++ nnode = nnode->parent; -++ while (nnode) { -++ if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) { -++ c->dirty_nn_cnt += 1; -++ ubifs_add_nnode_dirt(c, nnode); -++ nnode = nnode->parent; -++ } else -++ break; -++ } -++ } -++ return 0; -++} -++ -++/** -++ * make_pnode_dirty - find a pnode and, if found, make it dirty. -++ * @c: UBIFS file-system description object -++ * @node_num: pnode number of pnode to make dirty -++ * @lnum: LEB number where pnode was written -++ * @offs: offset where pnode was written -++ * -++ * This function is used by LPT garbage collection. LPT garbage collection is -++ * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection -++ * simply involves marking all the nodes in the LEB being garbage-collected as -++ * dirty. The dirty nodes are written next commit, after which the LEB is free -++ * to be reused. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int make_pnode_dirty(struct ubifs_info *c, int node_num, int lnum, -++ int offs) -++{ -++ struct ubifs_pnode *pnode; -++ struct ubifs_nbranch *branch; -++ -++ pnode = pnode_lookup(c, node_num); -++ if (IS_ERR(pnode)) -++ return PTR_ERR(pnode); -++ branch = &pnode->parent->nbranch[pnode->iip]; -++ if (branch->lnum != lnum || branch->offs != offs) -++ return 0; -++ do_make_pnode_dirty(c, pnode); -++ return 0; -++} -++ -++/** -++ * make_ltab_dirty - make ltab node dirty. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number where ltab was written -++ * @offs: offset where ltab was written -++ * -++ * This function is used by LPT garbage collection. LPT garbage collection is -++ * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection -++ * simply involves marking all the nodes in the LEB being garbage-collected as -++ * dirty. The dirty nodes are written next commit, after which the LEB is free -++ * to be reused. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int make_ltab_dirty(struct ubifs_info *c, int lnum, int offs) -++{ -++ if (lnum != c->ltab_lnum || offs != c->ltab_offs) -++ return 0; /* This ltab node is obsolete */ -++ if (!(c->lpt_drty_flgs & LTAB_DIRTY)) { -++ c->lpt_drty_flgs |= LTAB_DIRTY; -++ ubifs_add_lpt_dirt(c, c->ltab_lnum, c->ltab_sz); -++ } -++ return 0; -++} -++ -++/** -++ * make_lsave_dirty - make lsave node dirty. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number where lsave was written -++ * @offs: offset where lsave was written -++ * -++ * This function is used by LPT garbage collection. LPT garbage collection is -++ * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection -++ * simply involves marking all the nodes in the LEB being garbage-collected as -++ * dirty. The dirty nodes are written next commit, after which the LEB is free -++ * to be reused. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int make_lsave_dirty(struct ubifs_info *c, int lnum, int offs) -++{ -++ if (lnum != c->lsave_lnum || offs != c->lsave_offs) -++ return 0; /* This lsave node is obsolete */ -++ if (!(c->lpt_drty_flgs & LSAVE_DIRTY)) { -++ c->lpt_drty_flgs |= LSAVE_DIRTY; -++ ubifs_add_lpt_dirt(c, c->lsave_lnum, c->lsave_sz); -++ } -++ return 0; -++} -++ -++/** -++ * make_node_dirty - make node dirty. -++ * @c: UBIFS file-system description object -++ * @node_type: LPT node type -++ * @node_num: node number -++ * @lnum: LEB number where node was written -++ * @offs: offset where node was written -++ * -++ * This function is used by LPT garbage collection. LPT garbage collection is -++ * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection -++ * simply involves marking all the nodes in the LEB being garbage-collected as -++ * dirty. The dirty nodes are written next commit, after which the LEB is free -++ * to be reused. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int make_node_dirty(struct ubifs_info *c, int node_type, int node_num, -++ int lnum, int offs) -++{ -++ switch (node_type) { -++ case UBIFS_LPT_NNODE: -++ return make_nnode_dirty(c, node_num, lnum, offs); -++ case UBIFS_LPT_PNODE: -++ return make_pnode_dirty(c, node_num, lnum, offs); -++ case UBIFS_LPT_LTAB: -++ return make_ltab_dirty(c, lnum, offs); -++ case UBIFS_LPT_LSAVE: -++ return make_lsave_dirty(c, lnum, offs); -++ } -++ return -EINVAL; -++} -++ -++/** -++ * get_lpt_node_len - return the length of a node based on its type. -++ * @c: UBIFS file-system description object -++ * @node_type: LPT node type -++ */ -++static int get_lpt_node_len(struct ubifs_info *c, int node_type) -++{ -++ switch (node_type) { -++ case UBIFS_LPT_NNODE: -++ return c->nnode_sz; -++ case UBIFS_LPT_PNODE: -++ return c->pnode_sz; -++ case UBIFS_LPT_LTAB: -++ return c->ltab_sz; -++ case UBIFS_LPT_LSAVE: -++ return c->lsave_sz; -++ } -++ return 0; -++} -++ -++/** -++ * get_pad_len - return the length of padding in a buffer. -++ * @c: UBIFS file-system description object -++ * @buf: buffer -++ * @len: length of buffer -++ */ -++static int get_pad_len(struct ubifs_info *c, uint8_t *buf, int len) -++{ -++ int offs, pad_len; -++ -++ if (c->min_io_size == 1) -++ return 0; -++ offs = c->leb_size - len; -++ pad_len = ALIGN(offs, c->min_io_size) - offs; -++ return pad_len; -++} -++ -++/** -++ * get_lpt_node_type - return type (and node number) of a node in a buffer. -++ * @c: UBIFS file-system description object -++ * @buf: buffer -++ * @node_num: node number is returned here -++ */ -++static int get_lpt_node_type(struct ubifs_info *c, uint8_t *buf, int *node_num) -++{ -++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; -++ int pos = 0, node_type; -++ -++ node_type = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_TYPE_BITS); -++ *node_num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits); -++ return node_type; -++} -++ -++/** -++ * is_a_node - determine if a buffer contains a node. -++ * @c: UBIFS file-system description object -++ * @buf: buffer -++ * @len: length of buffer -++ * -++ * This function returns %1 if the buffer contains a node or %0 if it does not. -++ */ -++static int is_a_node(struct ubifs_info *c, uint8_t *buf, int len) -++{ -++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; -++ int pos = 0, node_type, node_len; -++ uint16_t crc, calc_crc; -++ -++ node_type = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_TYPE_BITS); -++ if (node_type == UBIFS_LPT_NOT_A_NODE) -++ return 0; -++ node_len = get_lpt_node_len(c, node_type); -++ if (!node_len || node_len > len) -++ return 0; -++ pos = 0; -++ addr = buf; -++ crc = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_CRC_BITS); -++ calc_crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES, -++ node_len - UBIFS_LPT_CRC_BYTES); -++ if (crc != calc_crc) -++ return 0; -++ return 1; -++} -++ -++ -++/** -++ * lpt_gc_lnum - garbage collect a LPT LEB. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number to garbage collect -++ * -++ * LPT garbage collection is used only for the "big" LPT model -++ * (c->big_lpt == 1). Garbage collection simply involves marking all the nodes -++ * in the LEB being garbage-collected as dirty. The dirty nodes are written -++ * next commit, after which the LEB is free to be reused. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int lpt_gc_lnum(struct ubifs_info *c, int lnum) -++{ -++ int err, len = c->leb_size, node_type, node_num, node_len, offs; -++ void *buf = c->lpt_buf; -++ -++ dbg_lp("LEB %d", lnum); -++ err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size); -++ if (err) { -++ ubifs_err("cannot read LEB %d, error %d", lnum, err); -++ return err; -++ } -++ while (1) { -++ if (!is_a_node(c, buf, len)) { -++ int pad_len; -++ -++ pad_len = get_pad_len(c, buf, len); -++ if (pad_len) { -++ buf += pad_len; -++ len -= pad_len; -++ continue; -++ } -++ return 0; -++ } -++ node_type = get_lpt_node_type(c, buf, &node_num); -++ node_len = get_lpt_node_len(c, node_type); -++ offs = c->leb_size - len; -++ ubifs_assert(node_len != 0); -++ mutex_lock(&c->lp_mutex); -++ err = make_node_dirty(c, node_type, node_num, lnum, offs); -++ mutex_unlock(&c->lp_mutex); -++ if (err) -++ return err; -++ buf += node_len; -++ len -= node_len; -++ } -++ return 0; -++} -++ -++/** -++ * lpt_gc - LPT garbage collection. -++ * @c: UBIFS file-system description object -++ * -++ * Select a LPT LEB for LPT garbage collection and call 'lpt_gc_lnum()'. -++ * Returns %0 on success and a negative error code on failure. -++ */ -++static int lpt_gc(struct ubifs_info *c) -++{ -++ int i, lnum = -1, dirty = 0; -++ -++ mutex_lock(&c->lp_mutex); -++ for (i = 0; i < c->lpt_lebs; i++) { -++ ubifs_assert(!c->ltab[i].tgc); -++ if (i + c->lpt_first == c->nhead_lnum || -++ c->ltab[i].free + c->ltab[i].dirty == c->leb_size) -++ continue; -++ if (c->ltab[i].dirty > dirty) { -++ dirty = c->ltab[i].dirty; -++ lnum = i + c->lpt_first; -++ } -++ } -++ mutex_unlock(&c->lp_mutex); -++ if (lnum == -1) -++ return -ENOSPC; -++ return lpt_gc_lnum(c, lnum); -++} -++ -++/** -++ * ubifs_lpt_post_commit - post commit LPT trivial GC and LPT GC. -++ * @c: UBIFS file-system description object -++ * -++ * LPT trivial GC is completed after a commit. Also LPT GC is done after a -++ * commit for the "big" LPT model. -++ */ -++int ubifs_lpt_post_commit(struct ubifs_info *c) -++{ -++ int err; -++ -++ mutex_lock(&c->lp_mutex); -++ err = lpt_tgc_end(c); -++ if (err) -++ goto out; -++ if (c->big_lpt) -++ while (need_write_all(c)) { -++ mutex_unlock(&c->lp_mutex); -++ err = lpt_gc(c); -++ if (err) -++ return err; -++ mutex_lock(&c->lp_mutex); -++ } -++out: -++ mutex_unlock(&c->lp_mutex); -++ return err; -++} -++ -++/** -++ * first_nnode - find the first nnode in memory. -++ * @c: UBIFS file-system description object -++ * @hght: height of tree where nnode found is returned here -++ * -++ * This function returns a pointer to the nnode found or %NULL if no nnode is -++ * found. This function is a helper to 'ubifs_lpt_free()'. -++ */ -++static struct ubifs_nnode *first_nnode(struct ubifs_info *c, int *hght) -++{ -++ struct ubifs_nnode *nnode; -++ int h, i, found; -++ -++ nnode = c->nroot; -++ *hght = 0; -++ if (!nnode) -++ return NULL; -++ for (h = 1; h < c->lpt_hght; h++) { -++ found = 0; -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ if (nnode->nbranch[i].nnode) { -++ found = 1; -++ nnode = nnode->nbranch[i].nnode; -++ *hght = h; -++ break; -++ } -++ } -++ if (!found) -++ break; -++ } -++ return nnode; -++} -++ -++/** -++ * next_nnode - find the next nnode in memory. -++ * @c: UBIFS file-system description object -++ * @nnode: nnode from which to start. -++ * @hght: height of tree where nnode is, is passed and returned here -++ * -++ * This function returns a pointer to the nnode found or %NULL if no nnode is -++ * found. This function is a helper to 'ubifs_lpt_free()'. -++ */ -++static struct ubifs_nnode *next_nnode(struct ubifs_info *c, -++ struct ubifs_nnode *nnode, int *hght) -++{ -++ struct ubifs_nnode *parent; -++ int iip, h, i, found; -++ -++ parent = nnode->parent; -++ if (!parent) -++ return NULL; -++ if (nnode->iip == UBIFS_LPT_FANOUT - 1) { -++ *hght -= 1; -++ return parent; -++ } -++ for (iip = nnode->iip + 1; iip < UBIFS_LPT_FANOUT; iip++) { -++ nnode = parent->nbranch[iip].nnode; -++ if (nnode) -++ break; -++ } -++ if (!nnode) { -++ *hght -= 1; -++ return parent; -++ } -++ for (h = *hght + 1; h < c->lpt_hght; h++) { -++ found = 0; -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ if (nnode->nbranch[i].nnode) { -++ found = 1; -++ nnode = nnode->nbranch[i].nnode; -++ *hght = h; -++ break; -++ } -++ } -++ if (!found) -++ break; -++ } -++ return nnode; -++} -++ -++/** -++ * ubifs_lpt_free - free resources owned by the LPT. -++ * @c: UBIFS file-system description object -++ * @wr_only: free only resources used for writing -++ */ -++void ubifs_lpt_free(struct ubifs_info *c, int wr_only) -++{ -++ struct ubifs_nnode *nnode; -++ int i, hght; -++ -++ /* Free write-only things first */ -++ -++ free_obsolete_cnodes(c); /* Leftover from a failed commit */ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(c->ltab_cmt); -++ kfree(c->lpt_buf); -++#else -++ vfree(c->ltab_cmt); -++ vfree(c->lpt_buf); -++#endif -++ c->ltab_cmt = NULL; -++ c->lpt_buf = NULL; -++ kfree(c->lsave); -++ c->lsave = NULL; -++ -++ if (wr_only) -++ return; -++ -++ /* Now free the rest */ -++ -++ nnode = first_nnode(c, &hght); -++ while (nnode) { -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) -++ kfree(nnode->nbranch[i].nnode); -++ nnode = next_nnode(c, nnode, &hght); -++ } -++ for (i = 0; i < LPROPS_HEAP_CNT; i++) -++ kfree(c->lpt_heap[i].arr); -++ kfree(c->dirty_idx.arr); -++ kfree(c->nroot); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(c->ltab); -++#else -++ vfree(c->ltab); -++#endif -++ kfree(c->lpt_nod_buf); -++} -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ -++/** -++ * dbg_is_all_ff - determine if a buffer contains only 0xff bytes. -++ * @buf: buffer -++ * @len: buffer length -++ */ -++static int dbg_is_all_ff(uint8_t *buf, int len) -++{ -++ int i; -++ -++ for (i = 0; i < len; i++) -++ if (buf[i] != 0xff) -++ return 0; -++ return 1; -++} -++ -++/** -++ * dbg_is_nnode_dirty - determine if a nnode is dirty. -++ * @c: the UBIFS file-system description object -++ * @lnum: LEB number where nnode was written -++ * @offs: offset where nnode was written -++ */ -++static int dbg_is_nnode_dirty(struct ubifs_info *c, int lnum, int offs) -++{ -++ struct ubifs_nnode *nnode; -++ int hght; -++ -++ /* Entire tree is in memory so first_nnode / next_nnode are ok */ -++ nnode = first_nnode(c, &hght); -++ for (; nnode; nnode = next_nnode(c, nnode, &hght)) { -++ struct ubifs_nbranch *branch; -++ -++ cond_resched(); -++ if (nnode->parent) { -++ branch = &nnode->parent->nbranch[nnode->iip]; -++ if (branch->lnum != lnum || branch->offs != offs) -++ continue; -++ if (test_bit(DIRTY_CNODE, &nnode->flags)) -++ return 1; -++ return 0; -++ } else { -++ if (c->lpt_lnum != lnum || c->lpt_offs != offs) -++ continue; -++ if (test_bit(DIRTY_CNODE, &nnode->flags)) -++ return 1; -++ return 0; -++ } -++ } -++ return 1; -++} -++ -++/** -++ * dbg_is_pnode_dirty - determine if a pnode is dirty. -++ * @c: the UBIFS file-system description object -++ * @lnum: LEB number where pnode was written -++ * @offs: offset where pnode was written -++ */ -++static int dbg_is_pnode_dirty(struct ubifs_info *c, int lnum, int offs) -++{ -++ int i, cnt; -++ -++ cnt = DIV_ROUND_UP(c->main_lebs, UBIFS_LPT_FANOUT); -++ for (i = 0; i < cnt; i++) { -++ struct ubifs_pnode *pnode; -++ struct ubifs_nbranch *branch; -++ -++ cond_resched(); -++ pnode = pnode_lookup(c, i); -++ if (IS_ERR(pnode)) -++ return PTR_ERR(pnode); -++ branch = &pnode->parent->nbranch[pnode->iip]; -++ if (branch->lnum != lnum || branch->offs != offs) -++ continue; -++ if (test_bit(DIRTY_CNODE, &pnode->flags)) -++ return 1; -++ return 0; -++ } -++ return 1; -++} -++ -++/** -++ * dbg_is_ltab_dirty - determine if a ltab node is dirty. -++ * @c: the UBIFS file-system description object -++ * @lnum: LEB number where ltab node was written -++ * @offs: offset where ltab node was written -++ */ -++static int dbg_is_ltab_dirty(struct ubifs_info *c, int lnum, int offs) -++{ -++ if (lnum != c->ltab_lnum || offs != c->ltab_offs) -++ return 1; -++ return (c->lpt_drty_flgs & LTAB_DIRTY) != 0; -++} -++ -++/** -++ * dbg_is_lsave_dirty - determine if a lsave node is dirty. -++ * @c: the UBIFS file-system description object -++ * @lnum: LEB number where lsave node was written -++ * @offs: offset where lsave node was written -++ */ -++static int dbg_is_lsave_dirty(struct ubifs_info *c, int lnum, int offs) -++{ -++ if (lnum != c->lsave_lnum || offs != c->lsave_offs) -++ return 1; -++ return (c->lpt_drty_flgs & LSAVE_DIRTY) != 0; -++} -++ -++/** -++ * dbg_is_node_dirty - determine if a node is dirty. -++ * @c: the UBIFS file-system description object -++ * @node_type: node type -++ * @lnum: LEB number where node was written -++ * @offs: offset where node was written -++ */ -++static int dbg_is_node_dirty(struct ubifs_info *c, int node_type, int lnum, -++ int offs) -++{ -++ switch (node_type) { -++ case UBIFS_LPT_NNODE: -++ return dbg_is_nnode_dirty(c, lnum, offs); -++ case UBIFS_LPT_PNODE: -++ return dbg_is_pnode_dirty(c, lnum, offs); -++ case UBIFS_LPT_LTAB: -++ return dbg_is_ltab_dirty(c, lnum, offs); -++ case UBIFS_LPT_LSAVE: -++ return dbg_is_lsave_dirty(c, lnum, offs); -++ } -++ return 1; -++} -++ -++/** -++ * dbg_check_ltab_lnum - check the ltab for a LPT LEB number. -++ * @c: the UBIFS file-system description object -++ * @lnum: LEB number where node was written -++ * @offs: offset where node was written -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum) -++{ -++ int err, len = c->leb_size, dirty = 0, node_type, node_num, node_len; -++ int ret; -++ void *buf = c->dbg_buf; -++ -++ dbg_lp("LEB %d", lnum); -++ err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size); -++ if (err) { -++ dbg_msg("ubi_read failed, LEB %d, error %d", lnum, err); -++ return err; -++ } -++ while (1) { -++ if (!is_a_node(c, buf, len)) { -++ int i, pad_len; -++ -++ pad_len = get_pad_len(c, buf, len); -++ if (pad_len) { -++ buf += pad_len; -++ len -= pad_len; -++ dirty += pad_len; -++ continue; -++ } -++ if (!dbg_is_all_ff(buf, len)) { -++ dbg_msg("invalid empty space in LEB %d at %d", -++ lnum, c->leb_size - len); -++ err = -EINVAL; -++ } -++ i = lnum - c->lpt_first; -++ if (len != c->ltab[i].free) { -++ dbg_msg("invalid free space in LEB %d " -++ "(free %d, expected %d)", -++ lnum, len, c->ltab[i].free); -++ err = -EINVAL; -++ } -++ if (dirty != c->ltab[i].dirty) { -++ dbg_msg("invalid dirty space in LEB %d " -++ "(dirty %d, expected %d)", -++ lnum, dirty, c->ltab[i].dirty); -++ err = -EINVAL; -++ } -++ return err; -++ } -++ node_type = get_lpt_node_type(c, buf, &node_num); -++ node_len = get_lpt_node_len(c, node_type); -++ ret = dbg_is_node_dirty(c, node_type, lnum, c->leb_size - len); -++ if (ret == 1) -++ dirty += node_len; -++ buf += node_len; -++ len -= node_len; -++ } -++} -++ -++/** -++ * dbg_check_ltab - check the free and dirty space in the ltab. -++ * @c: the UBIFS file-system description object -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int dbg_check_ltab(struct ubifs_info *c) -++{ -++ int lnum, err, i, cnt; -++ -++ if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS)) -++ return 0; -++ -++ /* Bring the entire tree into memory */ -++ cnt = DIV_ROUND_UP(c->main_lebs, UBIFS_LPT_FANOUT); -++ for (i = 0; i < cnt; i++) { -++ struct ubifs_pnode *pnode; -++ -++ pnode = pnode_lookup(c, i); -++ if (IS_ERR(pnode)) -++ return PTR_ERR(pnode); -++ cond_resched(); -++ } -++ -++ /* Check nodes */ -++ err = dbg_check_lpt_nodes(c, (struct ubifs_cnode *)c->nroot, 0, 0); -++ if (err) -++ return err; -++ -++ /* Check each LEB */ -++ for (lnum = c->lpt_first; lnum <= c->lpt_last; lnum++) { -++ err = dbg_check_ltab_lnum(c, lnum); -++ if (err) { -++ dbg_err("failed at LEB %d", lnum); -++ return err; -++ } -++ } -++ -++ dbg_lp("succeeded"); -++ return 0; -++} -++ -++#endif /* CONFIG_UBIFS_FS_DEBUG */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/master.c linux-2.6.24.7/fs/ubifs/master.c -+--- linux-2.6.24.7.old/fs/ubifs/master.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/master.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,387 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* This file implements reading and writing the master node */ -++ -++#include "ubifs.h" -++ -++/** -++ * scan_for_master - search the valid master node. -++ * @c: UBIFS file-system description object -++ * -++ * This function scans the master node LEBs and search for the latest master -++ * node. Returns zero in case of success and a negative error code in case of -++ * failure. -++ */ -++static int scan_for_master(struct ubifs_info *c) -++{ -++ struct ubifs_scan_leb *sleb; -++ struct ubifs_scan_node *snod; -++ int lnum, offs = 0, nodes_cnt; -++ -++ lnum = UBIFS_MST_LNUM; -++ -++ sleb = ubifs_scan(c, lnum, 0, c->sbuf); -++ if (IS_ERR(sleb)) -++ return PTR_ERR(sleb); -++ nodes_cnt = sleb->nodes_cnt; -++ if (nodes_cnt > 0) { -++ snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, -++ list); -++ if (snod->type != UBIFS_MST_NODE) -++ goto out; -++ memcpy(c->mst_node, snod->node, snod->len); -++ offs = snod->offs; -++ } -++ ubifs_scan_destroy(sleb); -++ -++ lnum += 1; -++ -++ sleb = ubifs_scan(c, lnum, 0, c->sbuf); -++ if (IS_ERR(sleb)) -++ return PTR_ERR(sleb); -++ if (sleb->nodes_cnt != nodes_cnt) -++ goto out; -++ if (!sleb->nodes_cnt) -++ goto out; -++ snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, list); -++ if (snod->type != UBIFS_MST_NODE) -++ goto out; -++ if (snod->offs != offs) -++ goto out; -++ if (memcmp((void *)c->mst_node + UBIFS_CH_SZ, -++ (void *)snod->node + UBIFS_CH_SZ, -++ UBIFS_MST_NODE_SZ - UBIFS_CH_SZ)) -++ goto out; -++ c->mst_offs = offs; -++ ubifs_scan_destroy(sleb); -++ return 0; -++ -++out: -++ ubifs_scan_destroy(sleb); -++ return -EINVAL; -++} -++ -++/** -++ * validate_master - validate master node. -++ * @c: UBIFS file-system description object -++ * -++ * This function validates data which was read from master node. Returns zero -++ * if the data is all right and %-EINVAL if not. -++ */ -++static int validate_master(const struct ubifs_info *c) -++{ -++ unsigned long long main_sz; -++ int err; -++ -++ if (c->max_sqnum >= SQNUM_WATERMARK) { -++ err = 1; -++ goto out; -++ } -++ -++ if (c->cmt_no >= c->max_sqnum) { -++ err = 2; -++ goto out; -++ } -++ -++ if (c->highest_inum >= INUM_WATERMARK) { -++ err = 3; -++ goto out; -++ } -++ -++ if (c->lhead_lnum < UBIFS_LOG_LNUM || -++ c->lhead_lnum >= UBIFS_LOG_LNUM + c->log_lebs || -++ c->lhead_offs < 0 || c->lhead_offs >= c->leb_size || -++ c->lhead_offs & (c->min_io_size - 1)) { -++ err = 4; -++ goto out; -++ } -++ -++ if (c->zroot.lnum >= c->leb_cnt || c->zroot.lnum < c->main_first || -++ c->zroot.offs >= c->leb_size || c->zroot.offs & 7) { -++ err = 5; -++ goto out; -++ } -++ -++ if (c->zroot.len < c->ranges[UBIFS_IDX_NODE].min_len || -++ c->zroot.len > c->ranges[UBIFS_IDX_NODE].max_len) { -++ err = 6; -++ goto out; -++ } -++ -++ if (c->gc_lnum >= c->leb_cnt || c->gc_lnum < c->main_first) { -++ err = 7; -++ goto out; -++ } -++ -++ if (c->ihead_lnum >= c->leb_cnt || c->ihead_lnum < c->main_first || -++ c->ihead_offs % c->min_io_size || c->ihead_offs < 0 || -++ c->ihead_offs > c->leb_size || c->ihead_offs & 7) { -++ err = 8; -++ goto out; -++ } -++ -++ main_sz = c->main_lebs * (unsigned long long)c->leb_size; -++ if (c->old_idx_sz & 7 || c->old_idx_sz >= main_sz) { -++ err = 9; -++ goto out; -++ } -++ -++ if (c->lpt_lnum < c->lpt_first || c->lpt_lnum > c->lpt_last || -++ c->lpt_offs < 0 || c->lpt_offs + c->nnode_sz > c->leb_size) { -++ err = 10; -++ goto out; -++ } -++ -++ if (c->nhead_lnum < c->lpt_first || c->nhead_lnum > c->lpt_last || -++ c->nhead_offs < 0 || c->nhead_offs % c->min_io_size || -++ c->nhead_offs > c->leb_size) { -++ err = 11; -++ goto out; -++ } -++ -++ if (c->ltab_lnum < c->lpt_first || c->ltab_lnum > c->lpt_last || -++ c->ltab_offs < 0 || -++ c->ltab_offs + c->ltab_sz > c->leb_size) { -++ err = 12; -++ goto out; -++ } -++ -++ if (c->big_lpt && (c->lsave_lnum < c->lpt_first || -++ c->lsave_lnum > c->lpt_last || c->lsave_offs < 0 || -++ c->lsave_offs + c->lsave_sz > c->leb_size)) { -++ err = 13; -++ goto out; -++ } -++ -++ if (c->lscan_lnum < c->main_first || c->lscan_lnum >= c->leb_cnt) { -++ err = 14; -++ goto out; -++ } -++ -++ if (c->lst.empty_lebs < 0 || c->lst.empty_lebs > c->main_lebs - 2) { -++ err = 15; -++ goto out; -++ } -++ -++ if (c->lst.idx_lebs < 0 || c->lst.idx_lebs > c->main_lebs - 1) { -++ err = 16; -++ goto out; -++ } -++ -++ if (c->lst.total_free < 0 || c->lst.total_free > main_sz || -++ c->lst.total_free & 7) { -++ err = 17; -++ goto out; -++ } -++ -++ if (c->lst.total_dirty < 0 || (c->lst.total_dirty & 7)) { -++ err = 18; -++ goto out; -++ } -++ -++ if (c->lst.total_used < 0 || (c->lst.total_used & 7)) { -++ err = 19; -++ goto out; -++ } -++ -++ if (c->lst.total_free + c->lst.total_dirty + -++ c->lst.total_used > main_sz) { -++ err = 20; -++ goto out; -++ } -++ -++ if (c->lst.total_dead + c->lst.total_dark + -++ c->lst.total_used + c->old_idx_sz > main_sz) { -++ err = 21; -++ goto out; -++ } -++ -++ if (c->lst.total_dead < 0 || -++ c->lst.total_dead > c->lst.total_free + c->lst.total_dirty || -++ c->lst.total_dead & 7) { -++ err = 22; -++ goto out; -++ } -++ -++ if (c->lst.total_dark < 0 || -++ c->lst.total_dark > c->lst.total_free + c->lst.total_dirty || -++ c->lst.total_dark & 7) { -++ err = 23; -++ goto out; -++ } -++ -++ return 0; -++ -++out: -++ ubifs_err("bad master node at offset %d error %d", c->mst_offs, err); -++ dbg_dump_node(c, c->mst_node); -++ return -EINVAL; -++} -++ -++/** -++ * ubifs_read_master - read master node. -++ * @c: UBIFS file-system description object -++ * -++ * This function finds and reads the master node during file-system mount. If -++ * the flash is empty, it creates default master node as well. Returns zero in -++ * case of success and a negative error code in case of failure. -++ */ -++int ubifs_read_master(struct ubifs_info *c) -++{ -++ int err, old_leb_cnt; -++ -++ c->mst_node = kzalloc(c->mst_node_alsz, GFP_KERNEL); -++ if (!c->mst_node) -++ return -ENOMEM; -++ -++ err = scan_for_master(c); -++ if (err) { -++ err = ubifs_recover_master_node(c); -++ if (err) -++ /* -++ * Note, we do not free 'c->mst_node' here because the -++ * unmount routine will take care of this. -++ */ -++ return err; -++ } -++ -++ /* Make sure that the recovery flag is clear */ -++ c->mst_node->flags &= cpu_to_le32(~UBIFS_MST_RCVRY); -++ -++ c->max_sqnum = le64_to_cpu(c->mst_node->ch.sqnum); -++ c->highest_inum = le64_to_cpu(c->mst_node->highest_inum); -++ c->cmt_no = le64_to_cpu(c->mst_node->cmt_no); -++ c->zroot.lnum = le32_to_cpu(c->mst_node->root_lnum); -++ c->zroot.offs = le32_to_cpu(c->mst_node->root_offs); -++ c->zroot.len = le32_to_cpu(c->mst_node->root_len); -++ c->lhead_lnum = le32_to_cpu(c->mst_node->log_lnum); -++ c->gc_lnum = le32_to_cpu(c->mst_node->gc_lnum); -++ c->ihead_lnum = le32_to_cpu(c->mst_node->ihead_lnum); -++ c->ihead_offs = le32_to_cpu(c->mst_node->ihead_offs); -++ c->old_idx_sz = le64_to_cpu(c->mst_node->index_size); -++ c->lpt_lnum = le32_to_cpu(c->mst_node->lpt_lnum); -++ c->lpt_offs = le32_to_cpu(c->mst_node->lpt_offs); -++ c->nhead_lnum = le32_to_cpu(c->mst_node->nhead_lnum); -++ c->nhead_offs = le32_to_cpu(c->mst_node->nhead_offs); -++ c->ltab_lnum = le32_to_cpu(c->mst_node->ltab_lnum); -++ c->ltab_offs = le32_to_cpu(c->mst_node->ltab_offs); -++ c->lsave_lnum = le32_to_cpu(c->mst_node->lsave_lnum); -++ c->lsave_offs = le32_to_cpu(c->mst_node->lsave_offs); -++ c->lscan_lnum = le32_to_cpu(c->mst_node->lscan_lnum); -++ c->lst.empty_lebs = le32_to_cpu(c->mst_node->empty_lebs); -++ c->lst.idx_lebs = le32_to_cpu(c->mst_node->idx_lebs); -++ old_leb_cnt = le32_to_cpu(c->mst_node->leb_cnt); -++ c->lst.total_free = le64_to_cpu(c->mst_node->total_free); -++ c->lst.total_dirty = le64_to_cpu(c->mst_node->total_dirty); -++ c->lst.total_used = le64_to_cpu(c->mst_node->total_used); -++ c->lst.total_dead = le64_to_cpu(c->mst_node->total_dead); -++ c->lst.total_dark = le64_to_cpu(c->mst_node->total_dark); -++ -++ c->calc_idx_sz = c->old_idx_sz; -++ -++ if (c->mst_node->flags & cpu_to_le32(UBIFS_MST_NO_ORPHS)) -++ c->no_orphs = 1; -++ -++ if (old_leb_cnt != c->leb_cnt) { -++ /* The file system has been resized */ -++ int growth = c->leb_cnt - old_leb_cnt; -++ -++ if (c->leb_cnt < old_leb_cnt || -++ c->leb_cnt < UBIFS_MIN_LEB_CNT) { -++ ubifs_err("bad leb_cnt on master node"); -++ dbg_dump_node(c, c->mst_node); -++ return -EINVAL; -++ } -++ -++ dbg_mnt("Auto resizing (master) from %d LEBs to %d LEBs", -++ old_leb_cnt, c->leb_cnt); -++ c->lst.empty_lebs += growth; -++ c->lst.total_free += growth * (long long)c->leb_size; -++ c->lst.total_dark += growth * (long long)c->dark_wm; -++ -++ /* -++ * Reflect changes back onto the master node. N.B. the master -++ * node gets written immediately whenever mounting (or -++ * remounting) in read-write mode, so we do not need to write it -++ * here. -++ */ -++ c->mst_node->leb_cnt = cpu_to_le32(c->leb_cnt); -++ c->mst_node->empty_lebs = cpu_to_le32(c->lst.empty_lebs); -++ c->mst_node->total_free = cpu_to_le64(c->lst.total_free); -++ c->mst_node->total_dark = cpu_to_le64(c->lst.total_dark); -++ } -++ -++ err = validate_master(c); -++ if (err) -++ return err; -++ -++ err = dbg_old_index_check_init(c, &c->zroot); -++ -++ return err; -++} -++ -++/** -++ * ubifs_write_master - write master node. -++ * @c: UBIFS file-system description object -++ * -++ * This function writes the master node. The caller has to take the -++ * @c->mst_mutex lock before calling this function. Returns zero in case of -++ * success and a negative error code in case of failure. The master node is -++ * written twice to enable recovery. -++ */ -++int ubifs_write_master(struct ubifs_info *c) -++{ -++ int err, lnum, offs, len; -++ -++ if (c->ro_media) -++ return -EINVAL; -++ -++ lnum = UBIFS_MST_LNUM; -++ offs = c->mst_offs + c->mst_node_alsz; -++ len = UBIFS_MST_NODE_SZ; -++ -++ if (offs + UBIFS_MST_NODE_SZ > c->leb_size) { -++ err = ubifs_leb_unmap(c, lnum); -++ if (err) -++ return err; -++ offs = 0; -++ } -++ -++ c->mst_offs = offs; -++ c->mst_node->highest_inum = cpu_to_le64(c->highest_inum); -++ -++ err = ubifs_write_node(c, c->mst_node, len, lnum, offs, UBI_SHORTTERM); -++ if (err) -++ return err; -++ -++ lnum += 1; -++ -++ if (offs == 0) { -++ err = ubifs_leb_unmap(c, lnum); -++ if (err) -++ return err; -++ } -++ err = ubifs_write_node(c, c->mst_node, len, lnum, offs, UBI_SHORTTERM); -++ -++ return err; -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/misc.h linux-2.6.24.7/fs/ubifs/misc.h -+--- linux-2.6.24.7.old/fs/ubifs/misc.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/misc.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,310 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* -++ * This file contains miscellaneous helper functions. -++ */ -++ -++#ifndef __UBIFS_MISC_H__ -++#define __UBIFS_MISC_H__ -++ -++/** -++ * ubifs_zn_dirty - check if znode is dirty. -++ * @znode: znode to check -++ * -++ * This helper function returns %1 if @znode is dirty and %0 otherwise. -++ */ -++static inline int ubifs_zn_dirty(const struct ubifs_znode *znode) -++{ -++ return !!test_bit(DIRTY_ZNODE, &znode->flags); -++} -++ -++/** -++ * ubifs_wake_up_bgt - wake up background thread. -++ * @c: UBIFS file-system description object -++ */ -++static inline void ubifs_wake_up_bgt(struct ubifs_info *c) -++{ -++ if (c->bgt && !c->need_bgt) { -++ c->need_bgt = 1; -++ wake_up_process(c->bgt); -++ } -++} -++ -++/** -++ * ubifs_tnc_find_child - find next child in znode. -++ * @znode: znode to search at -++ * @start: the zbranch index to start at -++ * -++ * This helper function looks for znode child starting at index @start. Returns -++ * the child or %NULL if no children were found. -++ */ -++static inline struct ubifs_znode * -++ubifs_tnc_find_child(struct ubifs_znode *znode, int start) -++{ -++ while (start < znode->child_cnt) { -++ if (znode->zbranch[start].znode) -++ return znode->zbranch[start].znode; -++ start += 1; -++ } -++ -++ return NULL; -++} -++ -++/** -++ * ubifs_inode - get UBIFS inode information by VFS 'struct inode' object. -++ * @inode: the VFS 'struct inode' pointer -++ */ -++static inline struct ubifs_inode *ubifs_inode(const struct inode *inode) -++{ -++ return container_of(inode, struct ubifs_inode, vfs_inode); -++} -++ -++/** -++ * ubifs_ro_mode - switch UBIFS to read read-only mode. -++ * @c: UBIFS file-system description object -++ * @err: error code which is the reason of switching to R/O mode -++ */ -++static inline void ubifs_ro_mode(struct ubifs_info *c, int err) -++{ -++ if (!c->ro_media) { -++ c->ro_media = 1; -++ ubifs_warn("switched to read-only mode, error %d", err); -++ dbg_dump_stack(); -++ } -++} -++ -++/** -++ * ubifs_compr_present - check if compressor was compiled in. -++ * @compr_type: compressor type to check -++ * -++ * This function returns %1 of compressor of type @compr_type is present, and -++ * %0 if not. -++ */ -++static inline int ubifs_compr_present(int compr_type) -++{ -++ ubifs_assert(compr_type >= 0 && compr_type < UBIFS_COMPR_TYPES_CNT); -++ return !!ubifs_compressors[compr_type]->capi_name; -++} -++ -++/** -++ * ubifs_compr_name - get compressor name string by its type. -++ * @compr_type: compressor type -++ * -++ * This function returns compressor type string. -++ */ -++static inline const char *ubifs_compr_name(int compr_type) -++{ -++ ubifs_assert(compr_type >= 0 && compr_type < UBIFS_COMPR_TYPES_CNT); -++ return ubifs_compressors[compr_type]->name; -++} -++ -++/** -++ * ubifs_wbuf_sync - synchronize write-buffer. -++ * @wbuf: write-buffer to synchronize -++ * -++ * This is the same as as 'ubifs_wbuf_sync_nolock()' but it does not assume -++ * that the write-buffer is already locked. -++ */ -++static inline int ubifs_wbuf_sync(struct ubifs_wbuf *wbuf) -++{ -++ int err; -++ -++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); -++ err = ubifs_wbuf_sync_nolock(wbuf); -++ mutex_unlock(&wbuf->io_mutex); -++ return err; -++} -++ -++/** -++ * ubifs_leb_unmap - unmap an LEB. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number to unmap -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static inline int ubifs_leb_unmap(const struct ubifs_info *c, int lnum) -++{ -++ int err; -++ -++ err = ubi_leb_unmap(c->ubi, lnum); -++ if (err) { -++ ubifs_err("unmap LEB %d failed, error %d", lnum, err); -++ return err; -++ } -++ -++ return 0; -++} -++ -++/** -++ * ubifs_leb_write - write to a LEB. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number to write -++ * @buf: buffer to write from -++ * @offs: offset within LEB to write to -++ * @len: length to write -++ * @dtype: data type -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static inline int ubifs_leb_write(const struct ubifs_info *c, int lnum, -++ const void *buf, int offs, int len, int dtype) -++{ -++ int err; -++ -++ err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype); -++ if (err) { -++ ubifs_err("writing %d bytes at %d:%d, error %d", -++ len, lnum, offs, err); -++ return err; -++ } -++ -++ return 0; -++} -++ -++/** -++ * ubifs_encode_dev - encode device node IDs. -++ * @dev: UBIFS device node information -++ * @rdev: device IDs to encode -++ * -++ * This is a helper function which encodes major/minor numbers of a device node -++ * into UBIFS device node description. We use standard Linux "new" and "huge" -++ * encodings. -++ */ -++static inline int ubifs_encode_dev(union ubifs_dev_desc *dev, dev_t rdev) -++{ -++ if (new_valid_dev(rdev)) { -++ dev->new = cpu_to_le32(new_encode_dev(rdev)); -++ return sizeof(dev->new); -++ } else { -++ dev->huge = cpu_to_le64(huge_encode_dev(rdev)); -++ return sizeof(dev->huge); -++ } -++} -++ -++/** -++ * ubifs_add_dirt - add dirty space to LEB properties. -++ * @c: the UBIFS file-system description object -++ * @lnum: LEB to add dirty space for -++ * @dirty: dirty space to add -++ * -++ * This is a helper function which increased amount of dirty LEB space. Returns -++ * zero in case of success and a negative error code in case of failure. -++ */ -++static inline int ubifs_add_dirt(struct ubifs_info *c, int lnum, int dirty) -++{ -++ return ubifs_update_one_lp(c, lnum, -1, dirty, 0, 0); -++} -++ -++/** -++ * ubifs_return_leb - return LEB to lprops. -++ * @c: the UBIFS file-system description object -++ * @lnum: LEB to return -++ * -++ * This helper function cleans the "taken" flag of a logical eraseblock in the -++ * lprops. Returns zero in case of success and a negative error code in case of -++ * failure. -++ */ -++static inline int ubifs_return_leb(struct ubifs_info *c, int lnum) -++{ -++ return ubifs_change_one_lp(c, lnum, -1, -1, 0, LPROPS_TAKEN, 0); -++} -++ -++/** -++ * ubifs_idx_node_sz - return index node size. -++ * @c: the UBIFS file-system description object -++ * @child_cnt: number of children of this index node -++ */ -++static inline int ubifs_idx_node_sz(const struct ubifs_info *c, int child_cnt) -++{ -++ return UBIFS_IDX_NODE_SZ + (UBIFS_BRANCH_SZ + c->key_len) * child_cnt; -++} -++ -++/** -++ * ubifs_idx_branch - return pointer to an index branch. -++ * @c: the UBIFS file-system description object -++ * @idx: index node -++ * @bnum: branch number -++ */ -++static inline -++struct ubifs_branch *ubifs_idx_branch(const struct ubifs_info *c, -++ const struct ubifs_idx_node *idx, -++ int bnum) -++{ -++ return (struct ubifs_branch *)((void *)idx->branches + -++ (UBIFS_BRANCH_SZ + c->key_len) * bnum); -++} -++ -++/** -++ * ubifs_idx_key - return pointer to an index key. -++ * @c: the UBIFS file-system description object -++ * @idx: index node -++ */ -++static inline void *ubifs_idx_key(const struct ubifs_info *c, -++ const struct ubifs_idx_node *idx) -++{ -++ return (void *)((struct ubifs_branch *)idx->branches)->key; -++} -++ -++/** -++ * ubifs_reported_space - calculate reported free space. -++ * @c: the UBIFS file-system description object -++ * @free: amount of free space -++ * -++ * This function calculates amount of free space which will be reported to -++ * user-space. User-space application tend to expect that if the file-system -++ * (e.g., via the 'statfs()' call) reports that it has N bytes available, they -++ * are able to write a file of size N. UBIFS attaches node headers to each data -++ * node and it has to write indexind nodes as well. This introduces additional -++ * overhead, and UBIFS it has to report sligtly less free space to meet the -++ * above expectetion. -++ * -++ * This function assumes free space is made up of uncompressed data nodes and -++ * full index nodes (one per data node, doubled because we always allow enough -++ * space to write the index twice). -++ * -++ * Note, the calculation is pessimistic, which means that most of the time -++ * UBIFS reports less space than it actually has. -++ */ -++static inline long long ubifs_reported_space(const struct ubifs_info *c, -++ uint64_t free) -++{ -++ int divisor, factor; -++ -++ divisor = UBIFS_MAX_DATA_NODE_SZ + (c->max_idx_node_sz << 1); -++ factor = UBIFS_MAX_DATA_NODE_SZ - UBIFS_DATA_NODE_SZ; -++ do_div(free, divisor); -++ -++ return free * factor; -++} -++ -++/** -++ * ubifs_current_time - round current time to time granularity. -++ * @inode: inode -++ */ -++static inline struct timespec ubifs_current_time(struct inode *inode) -++{ -++ return (inode->i_sb->s_time_gran < NSEC_PER_SEC) ? -++ current_fs_time(inode->i_sb) : CURRENT_TIME_SEC; -++} -++ -++#endif /* __UBIFS_MISC_H__ */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/config linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/config -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/config 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/config 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,11 @@ -++[core] -++ repositoryformatversion = 0 -++ filemode = true -++ bare = false -++ logallrefupdates = true -++[remote "origin"] -++ url = git://git.infradead.org/~dedekind/mkfs.ubifs.git -++ fetch = +refs/heads/*:refs/remotes/origin/* -++[branch "master"] -++ remote = origin -++ merge = refs/heads/master -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/description linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/description -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/description 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/description 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++Unnamed repository; edit this file to name it for gitweb. -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/head linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/head -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/head 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/head 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++ref: refs/heads/master -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/applypatch-msg linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/applypatch-msg -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/applypatch-msg 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/applypatch-msg 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,15 @@ -++#!/bin/sh -++# -++# An example hook script to check the commit log message taken by -++# applypatch from an e-mail message. -++# -++# The hook should exit with non-zero status after issuing an -++# appropriate message if it wants to stop the commit. The hook is -++# allowed to edit the commit message file. -++# -++# To enable this hook, make this file executable. -++ -++. git-sh-setup -++test -x "$GIT_DIR/hooks/commit-msg" && -++ exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"} -++: -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/commit-msg linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/commit-msg -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/commit-msg 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/commit-msg 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,24 @@ -++#!/bin/sh -++# -++# An example hook script to check the commit log message. -++# Called by git-commit with one argument, the name of the file -++# that has the commit message. The hook should exit with non-zero -++# status after issuing an appropriate message if it wants to stop the -++# commit. The hook is allowed to edit the commit message file. -++# -++# To enable this hook, make this file executable. -++ -++# Uncomment the below to add a Signed-off-by line to the message. -++# Doing this in a hook is a bad idea in general, but the prepare-commit-msg -++# hook is more suited to it. -++# -++# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -++# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" -++ -++# This example catches duplicate Signed-off-by lines. -++ -++test "" = "$(grep '^Signed-off-by: ' "$1" | -++ sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { -++ echo >&2 Duplicate Signed-off-by lines. -++ exit 1 -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/post-commit linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/post-commit -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/post-commit 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/post-commit 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,8 @@ -++#!/bin/sh -++# -++# An example hook script that is called after a successful -++# commit is made. -++# -++# To enable this hook, make this file executable. -++ -++: Nothing -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/post-receive linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/post-receive -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/post-receive 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/post-receive 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,16 @@ -++#!/bin/sh -++# -++# An example hook script for the post-receive event -++# -++# This script is run after receive-pack has accepted a pack and the -++# repository has been updated. It is passed arguments in through stdin -++# in the form -++# -++# For example: -++# aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master -++# -++# see contrib/hooks/ for an sample, or uncomment the next line (on debian) -++# -++ -++ -++#. /usr/share/doc/git-core/contrib/hooks/post-receive-email -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/post-update linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/post-update -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/post-update 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/post-update 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,8 @@ -++#!/bin/sh -++# -++# An example hook script to prepare a packed repository for use over -++# dumb transports. -++# -++# To enable this hook, make this file executable by "chmod +x post-update". -++ -++exec git-update-server-info -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/pre-applypatch linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/pre-applypatch -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/pre-applypatch 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/pre-applypatch 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,14 @@ -++#!/bin/sh -++# -++# An example hook script to verify what is about to be committed -++# by applypatch from an e-mail message. -++# -++# The hook should exit with non-zero status after issuing an -++# appropriate message if it wants to stop the commit. -++# -++# To enable this hook, make this file executable. -++ -++. git-sh-setup -++test -x "$GIT_DIR/hooks/pre-commit" && -++ exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"} -++: -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/pre-commit linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/pre-commit -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/pre-commit 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/pre-commit 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,70 @@ -++#!/bin/sh -++# -++# An example hook script to verify what is about to be committed. -++# Called by git-commit with no arguments. The hook should -++# exit with non-zero status after issuing an appropriate message if -++# it wants to stop the commit. -++# -++# To enable this hook, make this file executable. -++ -++# This is slightly modified from Andrew Morton's Perfect Patch. -++# Lines you introduce should not have trailing whitespace. -++# Also check for an indentation that has SP before a TAB. -++ -++if git-rev-parse --verify HEAD 2>/dev/null -++then -++ git-diff-index -p -M --cached HEAD -- -++else -++ # NEEDSWORK: we should produce a diff with an empty tree here -++ # if we want to do the same verification for the initial import. -++ : -++fi | -++perl -e ' -++ my $found_bad = 0; -++ my $filename; -++ my $reported_filename = ""; -++ my $lineno; -++ sub bad_line { -++ my ($why, $line) = @_; -++ if (!$found_bad) { -++ print STDERR "*\n"; -++ print STDERR "* You have some suspicious patch lines:\n"; -++ print STDERR "*\n"; -++ $found_bad = 1; -++ } -++ if ($reported_filename ne $filename) { -++ print STDERR "* In $filename\n"; -++ $reported_filename = $filename; -++ } -++ print STDERR "* $why (line $lineno)\n"; -++ print STDERR "$filename:$lineno:$line\n"; -++ } -++ while (<>) { -++ if (m|^diff --git a/(.*) b/\1$|) { -++ $filename = $1; -++ next; -++ } -++ if (/^@@ -\S+ \+(\d+)/) { -++ $lineno = $1 - 1; -++ next; -++ } -++ if (/^ /) { -++ $lineno++; -++ next; -++ } -++ if (s/^\+//) { -++ $lineno++; -++ chomp; -++ if (/\s$/) { -++ bad_line("trailing whitespace", $_); -++ } -++ if (/^\s* \t/) { -++ bad_line("indent SP followed by a TAB", $_); -++ } -++ if (/^([<>])\1{6} |^={7}$/) { -++ bad_line("unresolved merge conflict", $_); -++ } -++ } -++ } -++ exit($found_bad); -++' -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/pre-rebase linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/pre-rebase -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/pre-rebase 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/pre-rebase 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,150 @@ -++#!/bin/sh -++# -++# Copyright (c) 2006 Junio C Hamano -++# -++ -++publish=next -++basebranch="$1" -++if test "$#" = 2 -++then -++ topic="refs/heads/$2" -++else -++ topic=`git symbolic-ref HEAD` -++fi -++ -++case "$basebranch,$topic" in -++master,refs/heads/??/*) -++ ;; -++*) -++ exit 0 ;# we do not interrupt others. -++ ;; -++esac -++ -++# Now we are dealing with a topic branch being rebased -++# on top of master. Is it OK to rebase it? -++ -++# Is topic fully merged to master? -++not_in_master=`git-rev-list --pretty=oneline ^master "$topic"` -++if test -z "$not_in_master" -++then -++ echo >&2 "$topic is fully merged to master; better remove it." -++ exit 1 ;# we could allow it, but there is no point. -++fi -++ -++# Is topic ever merged to next? If so you should not be rebasing it. -++only_next_1=`git-rev-list ^master "^$topic" ${publish} | sort` -++only_next_2=`git-rev-list ^master ${publish} | sort` -++if test "$only_next_1" = "$only_next_2" -++then -++ not_in_topic=`git-rev-list "^$topic" master` -++ if test -z "$not_in_topic" -++ then -++ echo >&2 "$topic is already up-to-date with master" -++ exit 1 ;# we could allow it, but there is no point. -++ else -++ exit 0 -++ fi -++else -++ not_in_next=`git-rev-list --pretty=oneline ^${publish} "$topic"` -++ perl -e ' -++ my $topic = $ARGV[0]; -++ my $msg = "* $topic has commits already merged to public branch:\n"; -++ my (%not_in_next) = map { -++ /^([0-9a-f]+) /; -++ ($1 => 1); -++ } split(/\n/, $ARGV[1]); -++ for my $elem (map { -++ /^([0-9a-f]+) (.*)$/; -++ [$1 => $2]; -++ } split(/\n/, $ARGV[2])) { -++ if (!exists $not_in_next{$elem->[0]}) { -++ if ($msg) { -++ print STDERR $msg; -++ undef $msg; -++ } -++ print STDERR " $elem->[1]\n"; -++ } -++ } -++ ' "$topic" "$not_in_next" "$not_in_master" -++ exit 1 -++fi -++ -++exit 0 -++ -++################################################################ -++ -++This sample hook safeguards topic branches that have been -++published from being rewound. -++ -++The workflow assumed here is: -++ -++ * Once a topic branch forks from "master", "master" is never -++ merged into it again (either directly or indirectly). -++ -++ * Once a topic branch is fully cooked and merged into "master", -++ it is deleted. If you need to build on top of it to correct -++ earlier mistakes, a new topic branch is created by forking at -++ the tip of the "master". This is not strictly necessary, but -++ it makes it easier to keep your history simple. -++ -++ * Whenever you need to test or publish your changes to topic -++ branches, merge them into "next" branch. -++ -++The script, being an example, hardcodes the publish branch name -++to be "next", but it is trivial to make it configurable via -++$GIT_DIR/config mechanism. -++ -++With this workflow, you would want to know: -++ -++(1) ... if a topic branch has ever been merged to "next". Young -++ topic branches can have stupid mistakes you would rather -++ clean up before publishing, and things that have not been -++ merged into other branches can be easily rebased without -++ affecting other people. But once it is published, you would -++ not want to rewind it. -++ -++(2) ... if a topic branch has been fully merged to "master". -++ Then you can delete it. More importantly, you should not -++ build on top of it -- other people may already want to -++ change things related to the topic as patches against your -++ "master", so if you need further changes, it is better to -++ fork the topic (perhaps with the same name) afresh from the -++ tip of "master". -++ -++Let's look at this example: -++ -++ o---o---o---o---o---o---o---o---o---o "next" -++ / / / / -++ / a---a---b A / / -++ / / / / -++ / / c---c---c---c B / -++ / / / \ / -++ / / / b---b C \ / -++ / / / / \ / -++ ---o---o---o---o---o---o---o---o---o---o---o "master" -++ -++ -++A, B and C are topic branches. -++ -++ * A has one fix since it was merged up to "next". -++ -++ * B has finished. It has been fully merged up to "master" and "next", -++ and is ready to be deleted. -++ -++ * C has not merged to "next" at all. -++ -++We would want to allow C to be rebased, refuse A, and encourage -++B to be deleted. -++ -++To compute (1): -++ -++ git-rev-list ^master ^topic next -++ git-rev-list ^master next -++ -++ if these match, topic has not merged in next at all. -++ -++To compute (2): -++ -++ git-rev-list master..topic -++ -++ if this is empty, it is fully merged to "master". -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/prepare-commit-msg linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/prepare-commit-msg -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/prepare-commit-msg 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/prepare-commit-msg 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,36 @@ -++#!/bin/sh -++# -++# An example hook script to prepare the commit log message. -++# Called by git-commit with the name of the file that has the -++# commit message, followed by the description of the commit -++# message's source. The hook's purpose is to edit the commit -++# message file. If the hook fails with a non-zero status, -++# the commit is aborted. -++# -++# To enable this hook, make this file executable. -++ -++# This hook includes three examples. The first comments out the -++# "Conflicts:" part of a merge commit. -++# -++# The second includes the output of "git diff --name-status -r" -++# into the message, just before the "git status" output. It is -++# commented because it doesn't cope with --amend or with squashed -++# commits. -++# -++# The third example adds a Signed-off-by line to the message, that can -++# still be edited. This is rarely a good idea. -++ -++case "$2 $3" in -++ merge) -++ sed -i '/^Conflicts:/,/#/!b;s/^/# &/;s/^# #/#/' "$1" ;; -++ -++# ""|template) -++# perl -i -pe ' -++# print "\n" . `git diff --cached --name-status -r` -++# if /^#/ && $first++ == 0' "$1" ;; -++ -++ *) ;; -++esac -++ -++# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -++# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/update linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/update -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/hooks/update 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/hooks/update 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,107 @@ -++#!/bin/sh -++# -++# An example hook script to blocks unannotated tags from entering. -++# Called by git-receive-pack with arguments: refname sha1-old sha1-new -++# -++# To enable this hook, make this file executable by "chmod +x update". -++# -++# Config -++# ------ -++# hooks.allowunannotated -++# This boolean sets whether unannotated tags will be allowed into the -++# repository. By default they won't be. -++# hooks.allowdeletetag -++# This boolean sets whether deleting tags will be allowed in the -++# repository. By default they won't be. -++# hooks.allowdeletebranch -++# This boolean sets whether deleting branches will be allowed in the -++# repository. By default they won't be. -++# -++ -++# --- Command line -++refname="$1" -++oldrev="$2" -++newrev="$3" -++ -++# --- Safety check -++if [ -z "$GIT_DIR" ]; then -++ echo "Don't run this script from the command line." >&2 -++ echo " (if you want, you could supply GIT_DIR then run" >&2 -++ echo " $0 )" >&2 -++ exit 1 -++fi -++ -++if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then -++ echo "Usage: $0 " >&2 -++ exit 1 -++fi -++ -++# --- Config -++allowunannotated=$(git config --bool hooks.allowunannotated) -++allowdeletebranch=$(git config --bool hooks.allowdeletebranch) -++allowdeletetag=$(git config --bool hooks.allowdeletetag) -++ -++# check for no description -++projectdesc=$(sed -e '1q' "$GIT_DIR/description") -++if [ -z "$projectdesc" -o "$projectdesc" = "Unnamed repository; edit this file to name it for gitweb." ]; then -++ echo "*** Project description file hasn't been set" >&2 -++ exit 1 -++fi -++ -++# --- Check types -++# if $newrev is 0000...0000, it's a commit to delete a ref. -++if [ "$newrev" = "0000000000000000000000000000000000000000" ]; then -++ newrev_type=delete -++else -++ newrev_type=$(git-cat-file -t $newrev) -++fi -++ -++case "$refname","$newrev_type" in -++ refs/tags/*,commit) -++ # un-annotated tag -++ short_refname=${refname##refs/tags/} -++ if [ "$allowunannotated" != "true" ]; then -++ echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 -++ echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 -++ exit 1 -++ fi -++ ;; -++ refs/tags/*,delete) -++ # delete tag -++ if [ "$allowdeletetag" != "true" ]; then -++ echo "*** Deleting a tag is not allowed in this repository" >&2 -++ exit 1 -++ fi -++ ;; -++ refs/tags/*,tag) -++ # annotated tag -++ ;; -++ refs/heads/*,commit) -++ # branch -++ ;; -++ refs/heads/*,delete) -++ # delete branch -++ if [ "$allowdeletebranch" != "true" ]; then -++ echo "*** Deleting a branch is not allowed in this repository" >&2 -++ exit 1 -++ fi -++ ;; -++ refs/remotes/*,commit) -++ # tracking branch -++ ;; -++ refs/remotes/*,delete) -++ # delete tracking branch -++ if [ "$allowdeletebranch" != "true" ]; then -++ echo "*** Deleting a tracking branch is not allowed in this repository" >&2 -++ exit 1 -++ fi -++ ;; -++ *) -++ # Anything else (is there anything else?) -++ echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 -++ exit 1 -++ ;; -++esac -++ -++# --- Finished -++exit 0 -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/info/exclude linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/info/exclude -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/info/exclude 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/info/exclude 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,6 @@ -++# git-ls-files --others --exclude-from=.git/info/exclude -++# Lines that start with '#' are comments. -++# For a project mostly in C, the following would be a good set of -++# exclude patterns (uncomment them if you want to use them): -++# *.[oa] -++# *~ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/logs/head linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/logs/head -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/logs/head 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/logs/head 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++0000000000000000000000000000000000000000 549a9c94e7919c86fc260dd534fd908343348228 root 1208919344 -0400 -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/logs/refs/heads/master linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/logs/refs/heads/master -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/logs/refs/heads/master 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/logs/refs/heads/master 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++0000000000000000000000000000000000000000 549a9c94e7919c86fc260dd534fd908343348228 root 1208919344 -0400 -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/logs/refs/remotes/origin/master linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/logs/refs/remotes/origin/master -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/logs/refs/remotes/origin/master 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/logs/refs/remotes/origin/master 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++0000000000000000000000000000000000000000 549a9c94e7919c86fc260dd534fd908343348228 root 1208919344 -0400 clone: from git://git.infradead.org/~dedekind/mkfs.ubifs.git -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/objects/pack/pack-b57e0a817d6303b8f24187e61200a9f06e6974ce.keep linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/objects/pack/pack-b57e0a817d6303b8f24187e61200a9f06e6974ce.keep -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/objects/pack/pack-b57e0a817d6303b8f24187e61200a9f06e6974ce.keep 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/objects/pack/pack-b57e0a817d6303b8f24187e61200a9f06e6974ce.keep 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++fetch-pack 29608 on localhost.localdomain -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/refs/heads/master linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/refs/heads/master -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/refs/heads/master 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/refs/heads/master 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++549a9c94e7919c86fc260dd534fd908343348228 -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/refs/remotes/origin/head linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/refs/remotes/origin/head -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/refs/remotes/origin/head 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/refs/remotes/origin/head 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++ref: refs/remotes/origin/master -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/refs/remotes/origin/master linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/refs/remotes/origin/master -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.git/refs/remotes/origin/master 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.git/refs/remotes/origin/master 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1 @@ -++549a9c94e7919c86fc260dd534fd908343348228 -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.gitignore linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.gitignore -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/.gitignore 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/.gitignore 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,5 @@ -++*.o -++mkfs.ubifs -++patches -++cscope.out -++.pc -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/Makefile linux-2.6.24.7/fs/ubifs/mkfs.ubifs/Makefile -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,24 @@ -++ifeq ($(origin CC),default) -++CC = gcc -++endif -++ -++ALL_SOURCES=*.[ch] hashtable/*.[ch] -++ -++CFLAGS := $(CFLAGS) -Wall -O2 -I./lzo/include -I../../../include -++ -++LDFLAGS := $(LDFLAGS) -lz -llzo2 -lm -L./lzo/lib -++ -++TARGETS = mkfs.ubifs -++ -++all: $(TARGETS) -++ -++mkfs.ubifs: crc16.o crc32.o lpt.o compr.o hashtable/hashtable.o \ -++ hashtable/hashtable_itr.o devtable.o -++ -++clean: -++ rm -f *.o $(TARGETS) cscope.* -++ -++cscope: -++ @echo $(ALL_SOURCES) > cscope.files -++ @cscope -bR -++ @rm cscope.files -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/compr.c linux-2.6.24.7/fs/ubifs/mkfs.ubifs/compr.c -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/compr.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/compr.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,154 @@ -++/* -++ * Copyright (C) 2008 Nokia Corporation. -++ * Copyright (C) 2008 University of Szeged, Hungary -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy -++ * Adrian Hunter -++ * Zoltan Sogor -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "compr.h" -++#include "ubifs-media.h" -++ -++static void *lzo_mem; -++static unsigned long long errcnt = 0; -++ -++#define DEFLATE_DEF_LEVEL Z_DEFAULT_COMPRESSION -++#define DEFLATE_DEF_WINBITS 11 -++#define DEFLATE_DEF_MEMLEVEL 8 -++ -++static int zlib_deflate(void *in_buf, size_t in_len, void *out_buf, -++ size_t *out_len) -++{ -++ z_stream strm; -++ -++ strm.zalloc = NULL; -++ strm.zfree = NULL; -++ -++ /* -++ * Match exactly the zlib parameters used by the linux kernel crypto -++ * API. -++ */ -++ if (deflateInit2(&strm, DEFLATE_DEF_LEVEL, Z_DEFLATED, -++ -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL, -++ Z_DEFAULT_STRATEGY)) { -++ errcnt += 1; -++ return -1; -++ } -++ -++ strm.next_in = in_buf; -++ strm.avail_in = in_len; -++ strm.total_in = 0; -++ -++ strm.next_out = out_buf; -++ strm.avail_out = *out_len; -++ strm.total_out = 0; -++ -++ if (deflate(&strm, Z_FINISH) != Z_STREAM_END) { -++ deflateEnd(&strm); -++ errcnt += 1; -++ return -1; -++ } -++ -++ if (deflateEnd(&strm) != Z_OK) { -++ errcnt += 1; -++ return -1; -++ } -++ -++ *out_len = strm.total_out; -++ -++ return 0; -++} -++ -++static int lzo_compress(void *in_buf, size_t in_len, void *out_buf, -++ size_t *out_len) -++{ -++ lzo_uint len; -++ int ret; -++ -++ len = *out_len; -++ ret = lzo1x_999_compress(in_buf, in_len, out_buf, &len, lzo_mem); -++ *out_len = len; -++ -++ if (ret != LZO_E_OK) { -++ errcnt += 1; -++ return -1; -++ } -++ -++ return 0; -++} -++ -++static int no_compress(void *in_buf, size_t in_len, void *out_buf, -++ size_t *out_len) -++{ -++ memcpy(out_buf, in_buf, in_len); -++ *out_len = in_len; -++ return 0; -++} -++ -++int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len, -++ int type) -++{ -++ int ret = 1; -++ -++ if (in_len < UBIFS_MIN_COMPR_LEN) { -++ no_compress(in_buf, in_len, out_buf, out_len); -++ return MKFS_UBIFS_COMPR_NONE; -++ } -++ -++ switch (type) { -++ case MKFS_UBIFS_COMPR_LZO: -++ ret = lzo_compress(in_buf, in_len, out_buf, out_len); -++ break; -++ case MKFS_UBIFS_COMPR_ZLIB: -++ ret = zlib_deflate(in_buf, in_len, out_buf, out_len); -++ break; -++ case MKFS_UBIFS_COMPR_NONE: -++ ret = 1; -++ break; -++ default: -++ errcnt += 1; -++ break; -++ } -++ if (ret || *out_len >= in_len) { -++ no_compress(in_buf, in_len, out_buf, out_len); -++ return MKFS_UBIFS_COMPR_NONE; -++ } -++ return type; -++} -++ -++int init_compression(void) -++{ -++ lzo_mem = malloc(LZO1X_999_MEM_COMPRESS); -++ if (!lzo_mem) -++ return -1; -++ return 0; -++} -++ -++void destroy_compression(void) -++{ -++ free(lzo_mem); -++ if (errcnt) -++ fprintf(stderr, "%llu compression errors occurred\n", errcnt); -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/compr.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/compr.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/compr.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/compr.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,38 @@ -++/* -++ * Copyright (C) 2008 Nokia Corporation. -++ * Copyright (C) 2008 University of Szeged, Hungary -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy -++ * Adrian Hunter -++ * Zoltan Sogor -++ */ -++ -++#ifndef __UBIFS_COMPRESS_H__ -++#define __UBIFS_COMPRESS_H__ -++ -++enum compression_type -++{ -++ MKFS_UBIFS_COMPR_NONE, -++ MKFS_UBIFS_COMPR_LZO, -++ MKFS_UBIFS_COMPR_ZLIB, -++}; -++ -++int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len, -++ int type); -++int init_compression(void); -++void destroy_compression(void); -++ -++#endif -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/copying linux-2.6.24.7/fs/ubifs/mkfs.ubifs/copying -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/copying 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/copying 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,340 @@ -++ GNU GENERAL PUBLIC LICENSE -++ Version 2, June 1991 -++ -++ Copyright (C) 1989, 1991 Free Software Foundation, Inc. -++ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ Everyone is permitted to copy and distribute verbatim copies -++ of this license document, but changing it is not allowed. -++ -++ Preamble -++ -++ The licenses for most software are designed to take away your -++freedom to share and change it. By contrast, the GNU General Public -++License is intended to guarantee your freedom to share and change free -++software--to make sure the software is free for all its users. This -++General Public License applies to most of the Free Software -++Foundation's software and to any other program whose authors commit to -++using it. (Some other Free Software Foundation software is covered by -++the GNU Library General Public License instead.) You can apply it to -++your programs, too. -++ -++ When we speak of free software, we are referring to freedom, not -++price. Our General Public Licenses are designed to make sure that you -++have the freedom to distribute copies of free software (and charge for -++this service if you wish), that you receive source code or can get it -++if you want it, that you can change the software or use pieces of it -++in new free programs; and that you know you can do these things. -++ -++ To protect your rights, we need to make restrictions that forbid -++anyone to deny you these rights or to ask you to surrender the rights. -++These restrictions translate to certain responsibilities for you if you -++distribute copies of the software, or if you modify it. -++ -++ For example, if you distribute copies of such a program, whether -++gratis or for a fee, you must give the recipients all the rights that -++you have. You must make sure that they, too, receive or can get the -++source code. And you must show them these terms so they know their -++rights. -++ -++ We protect your rights with two steps: (1) copyright the software, and -++(2) offer you this license which gives you legal permission to copy, -++distribute and/or modify the software. -++ -++ Also, for each author's protection and ours, we want to make certain -++that everyone understands that there is no warranty for this free -++software. If the software is modified by someone else and passed on, we -++want its recipients to know that what they have is not the original, so -++that any problems introduced by others will not reflect on the original -++authors' reputations. -++ -++ Finally, any free program is threatened constantly by software -++patents. We wish to avoid the danger that redistributors of a free -++program will individually obtain patent licenses, in effect making the -++program proprietary. To prevent this, we have made it clear that any -++patent must be licensed for everyone's free use or not licensed at all. -++ -++ The precise terms and conditions for copying, distribution and -++modification follow. -++ -++ GNU GENERAL PUBLIC LICENSE -++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION -++ -++ 0. This License applies to any program or other work which contains -++a notice placed by the copyright holder saying it may be distributed -++under the terms of this General Public License. The "Program", below, -++refers to any such program or work, and a "work based on the Program" -++means either the Program or any derivative work under copyright law: -++that is to say, a work containing the Program or a portion of it, -++either verbatim or with modifications and/or translated into another -++language. (Hereinafter, translation is included without limitation in -++the term "modification".) Each licensee is addressed as "you". -++ -++Activities other than copying, distribution and modification are not -++covered by this License; they are outside its scope. The act of -++running the Program is not restricted, and the output from the Program -++is covered only if its contents constitute a work based on the -++Program (independent of having been made by running the Program). -++Whether that is true depends on what the Program does. -++ -++ 1. You may copy and distribute verbatim copies of the Program's -++source code as you receive it, in any medium, provided that you -++conspicuously and appropriately publish on each copy an appropriate -++copyright notice and disclaimer of warranty; keep intact all the -++notices that refer to this License and to the absence of any warranty; -++and give any other recipients of the Program a copy of this License -++along with the Program. -++ -++You may charge a fee for the physical act of transferring a copy, and -++you may at your option offer warranty protection in exchange for a fee. -++ -++ 2. You may modify your copy or copies of the Program or any portion -++of it, thus forming a work based on the Program, and copy and -++distribute such modifications or work under the terms of Section 1 -++above, provided that you also meet all of these conditions: -++ -++ a) You must cause the modified files to carry prominent notices -++ stating that you changed the files and the date of any change. -++ -++ b) You must cause any work that you distribute or publish, that in -++ whole or in part contains or is derived from the Program or any -++ part thereof, to be licensed as a whole at no charge to all third -++ parties under the terms of this License. -++ -++ c) If the modified program normally reads commands interactively -++ when run, you must cause it, when started running for such -++ interactive use in the most ordinary way, to print or display an -++ announcement including an appropriate copyright notice and a -++ notice that there is no warranty (or else, saying that you provide -++ a warranty) and that users may redistribute the program under -++ these conditions, and telling the user how to view a copy of this -++ License. (Exception: if the Program itself is interactive but -++ does not normally print such an announcement, your work based on -++ the Program is not required to print an announcement.) -++ -++These requirements apply to the modified work as a whole. If -++identifiable sections of that work are not derived from the Program, -++and can be reasonably considered independent and separate works in -++themselves, then this License, and its terms, do not apply to those -++sections when you distribute them as separate works. But when you -++distribute the same sections as part of a whole which is a work based -++on the Program, the distribution of the whole must be on the terms of -++this License, whose permissions for other licensees extend to the -++entire whole, and thus to each and every part regardless of who wrote it. -++ -++Thus, it is not the intent of this section to claim rights or contest -++your rights to work written entirely by you; rather, the intent is to -++exercise the right to control the distribution of derivative or -++collective works based on the Program. -++ -++In addition, mere aggregation of another work not based on the Program -++with the Program (or with a work based on the Program) on a volume of -++a storage or distribution medium does not bring the other work under -++the scope of this License. -++ -++ 3. You may copy and distribute the Program (or a work based on it, -++under Section 2) in object code or executable form under the terms of -++Sections 1 and 2 above provided that you also do one of the following: -++ -++ a) Accompany it with the complete corresponding machine-readable -++ source code, which must be distributed under the terms of Sections -++ 1 and 2 above on a medium customarily used for software interchange; or, -++ -++ b) Accompany it with a written offer, valid for at least three -++ years, to give any third party, for a charge no more than your -++ cost of physically performing source distribution, a complete -++ machine-readable copy of the corresponding source code, to be -++ distributed under the terms of Sections 1 and 2 above on a medium -++ customarily used for software interchange; or, -++ -++ c) Accompany it with the information you received as to the offer -++ to distribute corresponding source code. (This alternative is -++ allowed only for noncommercial distribution and only if you -++ received the program in object code or executable form with such -++ an offer, in accord with Subsection b above.) -++ -++The source code for a work means the preferred form of the work for -++making modifications to it. For an executable work, complete source -++code means all the source code for all modules it contains, plus any -++associated interface definition files, plus the scripts used to -++control compilation and installation of the executable. However, as a -++special exception, the source code distributed need not include -++anything that is normally distributed (in either source or binary -++form) with the major components (compiler, kernel, and so on) of the -++operating system on which the executable runs, unless that component -++itself accompanies the executable. -++ -++If distribution of executable or object code is made by offering -++access to copy from a designated place, then offering equivalent -++access to copy the source code from the same place counts as -++distribution of the source code, even though third parties are not -++compelled to copy the source along with the object code. -++ -++ 4. You may not copy, modify, sublicense, or distribute the Program -++except as expressly provided under this License. Any attempt -++otherwise to copy, modify, sublicense or distribute the Program is -++void, and will automatically terminate your rights under this License. -++However, parties who have received copies, or rights, from you under -++this License will not have their licenses terminated so long as such -++parties remain in full compliance. -++ -++ 5. You are not required to accept this License, since you have not -++signed it. However, nothing else grants you permission to modify or -++distribute the Program or its derivative works. These actions are -++prohibited by law if you do not accept this License. Therefore, by -++modifying or distributing the Program (or any work based on the -++Program), you indicate your acceptance of this License to do so, and -++all its terms and conditions for copying, distributing or modifying -++the Program or works based on it. -++ -++ 6. Each time you redistribute the Program (or any work based on the -++Program), the recipient automatically receives a license from the -++original licensor to copy, distribute or modify the Program subject to -++these terms and conditions. You may not impose any further -++restrictions on the recipients' exercise of the rights granted herein. -++You are not responsible for enforcing compliance by third parties to -++this License. -++ -++ 7. If, as a consequence of a court judgment or allegation of patent -++infringement or for any other reason (not limited to patent issues), -++conditions are imposed on you (whether by court order, agreement or -++otherwise) that contradict the conditions of this License, they do not -++excuse you from the conditions of this License. If you cannot -++distribute so as to satisfy simultaneously your obligations under this -++License and any other pertinent obligations, then as a consequence you -++may not distribute the Program at all. For example, if a patent -++license would not permit royalty-free redistribution of the Program by -++all those who receive copies directly or indirectly through you, then -++the only way you could satisfy both it and this License would be to -++refrain entirely from distribution of the Program. -++ -++If any portion of this section is held invalid or unenforceable under -++any particular circumstance, the balance of the section is intended to -++apply and the section as a whole is intended to apply in other -++circumstances. -++ -++It is not the purpose of this section to induce you to infringe any -++patents or other property right claims or to contest validity of any -++such claims; this section has the sole purpose of protecting the -++integrity of the free software distribution system, which is -++implemented by public license practices. Many people have made -++generous contributions to the wide range of software distributed -++through that system in reliance on consistent application of that -++system; it is up to the author/donor to decide if he or she is willing -++to distribute software through any other system and a licensee cannot -++impose that choice. -++ -++This section is intended to make thoroughly clear what is believed to -++be a consequence of the rest of this License. -++ -++ 8. If the distribution and/or use of the Program is restricted in -++certain countries either by patents or by copyrighted interfaces, the -++original copyright holder who places the Program under this License -++may add an explicit geographical distribution limitation excluding -++those countries, so that distribution is permitted only in or among -++countries not thus excluded. In such case, this License incorporates -++the limitation as if written in the body of this License. -++ -++ 9. The Free Software Foundation may publish revised and/or new versions -++of the General Public License from time to time. Such new versions will -++be similar in spirit to the present version, but may differ in detail to -++address new problems or concerns. -++ -++Each version is given a distinguishing version number. If the Program -++specifies a version number of this License which applies to it and "any -++later version", you have the option of following the terms and conditions -++either of that version or of any later version published by the Free -++Software Foundation. If the Program does not specify a version number of -++this License, you may choose any version ever published by the Free Software -++Foundation. -++ -++ 10. If you wish to incorporate parts of the Program into other free -++programs whose distribution conditions are different, write to the author -++to ask for permission. For software which is copyrighted by the Free -++Software Foundation, write to the Free Software Foundation; we sometimes -++make exceptions for this. Our decision will be guided by the two goals -++of preserving the free status of all derivatives of our free software and -++of promoting the sharing and reuse of software generally. -++ -++ NO WARRANTY -++ -++ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -++FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -++OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -++PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -++OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -++MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -++TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -++PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -++REPAIR OR CORRECTION. -++ -++ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -++WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -++REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -++INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -++OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -++TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -++YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -++PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -++POSSIBILITY OF SUCH DAMAGES. -++ -++ END OF TERMS AND CONDITIONS -++ -++ How to Apply These Terms to Your New Programs -++ -++ If you develop a new program, and you want it to be of the greatest -++possible use to the public, the best way to achieve this is to make it -++free software which everyone can redistribute and change under these terms. -++ -++ To do so, attach the following notices to the program. It is safest -++to attach them to the start of each source file to most effectively -++convey the exclusion of warranty; and each file should have at least -++the "copyright" line and a pointer to where the full notice is found. -++ -++ -++ Copyright (C) 19yy -++ -++ This program is free software; you can redistribute it and/or modify -++ it under the terms of the GNU General Public License as published by -++ the Free Software Foundation; either version 2 of the License, or -++ (at your option) any later version. -++ -++ This program is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with this program; if not, write to the Free Software -++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ -++ -++Also add information on how to contact you by electronic and paper mail. -++ -++If the program is interactive, make it output a short notice like this -++when it starts in an interactive mode: -++ -++ Gnomovision version 69, Copyright (C) 19yy name of author -++ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. -++ This is free software, and you are welcome to redistribute it -++ under certain conditions; type `show c' for details. -++ -++The hypothetical commands `show w' and `show c' should show the appropriate -++parts of the General Public License. Of course, the commands you use may -++be called something other than `show w' and `show c'; they could even be -++mouse-clicks or menu items--whatever suits your program. -++ -++You should also get your employer (if you work as a programmer) or your -++school, if any, to sign a "copyright disclaimer" for the program, if -++necessary. Here is a sample; alter the names: -++ -++ Yoyodyne, Inc., hereby disclaims all copyright interest in the program -++ `Gnomovision' (which makes passes at compilers) written by James Hacker. -++ -++ , 1 April 1989 -++ Ty Coon, President of Vice -++ -++This General Public License does not permit incorporating your program into -++proprietary programs. If your program is a subroutine library, you may -++consider it more useful to permit linking proprietary applications with the -++library. If this is what you want to do, use the GNU Library General -++Public License instead of this License. -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/crc16.c linux-2.6.24.7/fs/ubifs/mkfs.ubifs/crc16.c -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/crc16.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/crc16.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,56 @@ -++/* -++ * This code was taken from the linux kernel. The license is GPL Version 2. -++ */ -++ -++#include "crc16.h" -++ -++/** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */ -++uint16_t const crc16_table[256] = { -++ 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, -++ 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, -++ 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, -++ 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, -++ 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, -++ 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, -++ 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, -++ 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, -++ 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, -++ 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, -++ 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, -++ 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, -++ 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, -++ 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, -++ 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, -++ 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, -++ 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, -++ 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, -++ 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, -++ 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, -++ 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, -++ 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, -++ 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, -++ 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, -++ 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, -++ 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, -++ 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, -++ 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, -++ 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, -++ 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, -++ 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, -++ 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 -++}; -++ -++/** -++ * crc16 - compute the CRC-16 for the data buffer -++ * @crc: previous CRC value -++ * @buffer: data pointer -++ * @len: number of bytes in the buffer -++ * -++ * Returns the updated CRC value. -++ */ -++uint16_t crc16(uint16_t crc, uint8_t const *buffer, size_t len) -++{ -++ while (len--) -++ crc = crc16_byte(crc, *buffer++); -++ return crc; -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/crc16.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/crc16.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/crc16.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/crc16.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,27 @@ -++/* -++ * Implements the standard CRC-16: -++ * Width 16 -++ * Poly 0x8005 (x^16 + x^15 + x^2 + 1) -++ * Init 0 -++ * -++ * Copyright (c) 2005 Ben Gardner -++ * -++ * This code was taken from the linux kernel. The license is GPL Version 2. -++ */ -++ -++#ifndef __CRC16_H__ -++#define __CRC16_H__ -++ -++#include -++#include -++ -++extern uint16_t const crc16_table[256]; -++ -++extern uint16_t crc16(uint16_t crc, const uint8_t *buffer, size_t len); -++ -++static inline uint16_t crc16_byte(uint16_t crc, const uint8_t data) -++{ -++ return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff]; -++} -++ -++#endif /* __CRC16_H__ */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/crc32.c linux-2.6.24.7/fs/ubifs/mkfs.ubifs/crc32.c -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/crc32.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/crc32.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,95 @@ -++/* -++ * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or -++ * code or tables extracted from it, as desired without restriction. -++ * -++ * First, the polynomial itself and its table of feedback terms. The -++ * polynomial is -++ * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 -++ * -++ * Note that we take it "backwards" and put the highest-order term in -++ * the lowest-order bit. The X^32 term is "implied"; the LSB is the -++ * X^31 term, etc. The X^0 term (usually shown as "+1") results in -++ * the MSB being 1 -++ * -++ * Note that the usual hardware shift register implementation, which -++ * is what we're using (we're merely optimizing it by doing eight-bit -++ * chunks at a time) shifts bits into the lowest-order term. In our -++ * implementation, that means shifting towards the right. Why do we -++ * do it this way? Because the calculated CRC must be transmitted in -++ * order from highest-order term to lowest-order term. UARTs transmit -++ * characters in order from LSB to MSB. By storing the CRC this way -++ * we hand it to the UART in the order low-byte to high-byte; the UART -++ * sends each low-bit to hight-bit; and the result is transmission bit -++ * by bit from highest- to lowest-order term without requiring any bit -++ * shuffling on our part. Reception works similarly -++ * -++ * The feedback terms table consists of 256, 32-bit entries. Notes -++ * -++ * The table can be generated at runtime if desired; code to do so -++ * is shown later. It might not be obvious, but the feedback -++ * terms simply represent the results of eight shift/xor opera -++ * tions for all combinations of data and CRC register values -++ * -++ * The values must be right-shifted by eight bits by the "updcrc -++ * logic; the shift must be unsigned (bring in zeroes). On some -++ * hardware you could probably optimize the shift in assembler by -++ * using byte-swap instructions -++ * polynomial $edb88320 -++ */ -++ -++#include -++ -++const uint32_t crc32_table[256] = { -++ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, -++ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, -++ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, -++ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, -++ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, -++ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, -++ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, -++ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, -++ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, -++ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, -++ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, -++ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, -++ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, -++ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, -++ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, -++ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, -++ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, -++ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, -++ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, -++ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, -++ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, -++ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, -++ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, -++ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, -++ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, -++ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, -++ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, -++ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, -++ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, -++ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, -++ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, -++ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, -++ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, -++ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, -++ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, -++ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, -++ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, -++ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, -++ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, -++ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, -++ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, -++ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, -++ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, -++ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, -++ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, -++ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, -++ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, -++ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, -++ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, -++ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, -++ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, -++ 0x2d02ef8dL -++}; -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/crc32.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/crc32.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/crc32.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/crc32.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,22 @@ -++/* -++ * This code was taken from the linux kernel. The license is GPL Version 2. -++ */ -++ -++#ifndef __CRC32_H__ -++#define __CRC32_H__ -++ -++#include -++ -++extern const uint32_t crc32_table[256]; -++ -++/* Return a 32-bit CRC of the contents of the buffer. */ -++static inline uint32_t crc32(uint32_t val, const void *ss, int len) -++{ -++ const unsigned char *s = ss; -++ -++ while (--len >= 0) -++ val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8); -++ return val; -++} -++ -++#endif /* __CRC32_H__ */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/defs.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/defs.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/defs.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/defs.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,105 @@ -++/* -++ * Greate deal of the code was taken from the kernel UBIFS implementation, and -++ * this file contains some "glue" definitions. -++ */ -++ -++#ifndef __UBIFS_DEFS_H__ -++#define __UBIFS_DEFS_H__ -++ -++#define t16(x) ({ \ -++ uint16_t __b = (x); \ -++ (__LITTLE_ENDIAN==__BYTE_ORDER) ? __b : bswap_16(__b); \ -++}) -++ -++#define t32(x) ({ \ -++ uint32_t __b = (x); \ -++ (__LITTLE_ENDIAN==__BYTE_ORDER) ? __b : bswap_32(__b); \ -++}) -++ -++#define t64(x) ({ \ -++ uint64_t __b = (x); \ -++ (__LITTLE_ENDIAN==__BYTE_ORDER) ? __b : bswap_64(__b); \ -++}) -++ -++#define cpu_to_le16(x) ((__le16){t16(x)}) -++#define cpu_to_le32(x) ((__le32){t32(x)}) -++#define cpu_to_le64(x) ((__le64){t64(x)}) -++ -++#define le16_to_cpu(x) (t16((x))) -++#define le32_to_cpu(x) (t32((x))) -++#define le64_to_cpu(x) (t64((x))) -++ -++#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) -++#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) -++ -++#define min_t(t,x,y) ({ \ -++ typeof((x)) _x = (x); \ -++ typeof((y)) _y = (y); \ -++ (_x < _y) ? _x : _y; \ -++}) -++ -++#define max_t(t,x,y) ({ \ -++ typeof((x)) _x = (x); \ -++ typeof((y)) _y = (y); \ -++ (_x > _y) ? _x : _y; \ -++}) -++ -++#define unlikely(x) (x) -++ -++struct qstr -++{ -++ char *name; -++ size_t len; -++}; -++ -++/** -++ * fls - find last (most-significant) bit set -++ * @x: the word to search -++ * -++ * This is defined the same way as ffs. -++ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. -++ */ -++static inline int fls(int x) -++{ -++ int r = 32; -++ -++ if (!x) -++ return 0; -++ if (!(x & 0xffff0000u)) { -++ x <<= 16; -++ r -= 16; -++ } -++ if (!(x & 0xff000000u)) { -++ x <<= 8; -++ r -= 8; -++ } -++ if (!(x & 0xf0000000u)) { -++ x <<= 4; -++ r -= 4; -++ } -++ if (!(x & 0xc0000000u)) { -++ x <<= 2; -++ r -= 2; -++ } -++ if (!(x & 0x80000000u)) { -++ x <<= 1; -++ r -= 1; -++ } -++ return r; -++} -++ -++#define do_div(n,base) ({ \ -++int __res; \ -++__res = ((unsigned long) n) % (unsigned) base; \ -++n = ((unsigned long) n) / (unsigned) base; \ -++__res; }) -++ -++#if INT_MAX != 0x7fffffff -++#error : sizeof(int) must be 4 for this program -++#endif -++ -++#if (~0ULL) != 0xffffffffffffffffULL -++#error : sizeof(long long) must be 8 for this program -++#endif -++ -++#endif -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/devtable.c linux-2.6.24.7/fs/ubifs/mkfs.ubifs/devtable.c -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/devtable.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/devtable.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,524 @@ -++/* -++ * Copyright (C) 2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Author: Artem Bityutskiy -++ * -++ * Part of the device table parsing code was taken from the mkfs.jffs2 utility. -++ * The original author of that code is Erik Andersen, hence: -++ * Copyright (C) 2001, 2002 Erik Andersen -++ */ -++ -++/* -++ * This file implemented device table support. Device table entries take the -++ * form of: -++ * -++ * /dev/mem c 640 0 0 1 1 0 0 - -++ * -++ * Type can be one of: -++ * f A regular file -++ * d Directory -++ * c Character special device file -++ * b Block special device file -++ * p Fifo (named pipe) -++ * -++ * Don't bother with symlinks (permissions are irrelevant), hard links (special -++ * cases of regular files), or sockets (why bother). -++ * -++ * Regular files must exist in the target root directory. If a char, block, -++ * fifo, or directory does not exist, it will be created. -++ * -++ * Please, refer the device_table.txt file which can be found at MTD utilities -++ * for more information about what the device table is. -++ */ -++ -++#include "mkfs.ubifs.h" -++#include "hashtable/hashtable.h" -++#include "hashtable/hashtable_itr.h" -++ -++/* -++ * The hash table which contains paths to files/directories/device nodes -++ * referred to in the device table. For example, if the device table refers -++ * "/dev/loop0", the @path_htbl will contain "/dev" element. -++ */ -++static struct hashtable *path_htbl; -++ -++/* Hash function used for hash tables */ -++static unsigned int r5_hash(void *s) -++{ -++ unsigned int a = 0; -++ const signed char *str = s; -++ -++ while (*str) { -++ a += *str << 4; -++ a += *str >> 4; -++ a *= 11; -++ str++; -++ } -++ -++ return a; -++} -++ -++/* -++ * Check whether 2 keys of a hash table are equivalent. The keys are path/file -++ * names, so we simply use 'strcmp()'. -++ */ -++static int is_equivalent(void *k1, void *k2) -++{ -++ return !strcmp(k1, k2); -++} -++ -++/** -++ * separate_last - separate out the last path component -++ * @buf: the path to split -++ * @len: length of the @buf string -++ * @path: the beginning of path is returned here -++ * @name: the last path component is returned here -++ * -++ * This helper function separates out the the last component of the full path -++ * string. For example, "/dev/loop" would be split on "/dev" and "loop". This -++ * function allocates memory for @path and @name and return the result there. -++ * Returns zero in case of success and a negative error code in case of -++ * failure. -++ */ -++static int separate_last(const char *buf, int len, char **path, char **name) -++{ -++ int path_len = len, name_len; -++ const char *p = buf + len, *n; -++ -++ while (*--p != '/') -++ path_len -= 1; -++ -++ /* Drop the final '/' unless this is the root directory */ -++ name_len = len - path_len; -++ n = buf + path_len; -++ if (path_len > 1) -++ path_len -= 1; -++ -++ *path = malloc(path_len + 1); -++ if (!*path) -++ return err_msg("cannot allocate %d bytes of memory", -++ path_len + 1); -++ memcpy(*path, buf, path_len); -++ (*path)[path_len] = '\0'; -++ -++ *name = malloc(name_len + 1); -++ if (!*name) { -++ free(*path); -++ return err_msg("cannot allocate %d bytes of memory", -++ name_len + 1); -++ } -++ memcpy(*name, n, name_len + 1); -++ -++ return 0; -++} -++ -++static int interpret_table_entry(const char *root, const char *line) -++{ -++ char buf[1024], type, *path = NULL, *name = NULL; -++ int len; -++ struct path_htbl_element *ph_elt = NULL; -++ struct name_htbl_element *nh_elt = NULL; -++ unsigned int mode = 0755, uid = 0, gid = 0, major = 0, minor = 0; -++ unsigned int start = 0, increment = 0, count = 0; -++ -++ if (sscanf(line, "%1023s %c %o %u %u %u %u %u %u %u", -++ buf, &type, &mode, &uid, &gid, &major, &minor, -++ &start, &increment, &count) < 0) -++ return sys_err_msg("sscanf failed"); -++ -++ dbg_msg(3, "name %s, type %c, mode %o, uid %u, gid %u, major %u, " -++ "minor %u, start %u, inc %u, cnt %u", -++ buf, type, mode, uid, gid, major, minor, start, -++ increment, count); -++ -++ len = strnlen(buf, 1024); -++ if (len == 1024) -++ return err_msg("too long path"); -++ -++ if (!strcmp(buf, "/")) -++ return err_msg("device table entries require absolute paths"); -++ if (buf[1] == '\0') -++ return err_msg("root directory cannot be created"); -++ if (strstr(buf, "//")) -++ return err_msg("'//' cannot be used in the path"); -++ if (buf[len - 1] == '/') -++ return err_msg("do not put '/' at the end"); -++ -++ if (strstr(buf, "/./") || strstr(buf, "/../") || -++ !strcmp(buf + len - 2, "/.") || !strcmp(buf + len - 3, "/..")) -++ return err_msg("'.' and '..' cannot be used in the path"); -++ -++ switch (type) { -++ case 'd': -++ mode |= S_IFDIR; -++ break; -++ case 'f': -++ mode |= S_IFREG; -++ break; -++ case 'p': -++ mode |= S_IFIFO; -++ break; -++ case 'c': -++ mode |= S_IFCHR; -++ break; -++ case 'b': -++ mode |= S_IFBLK; -++ break; -++ default: -++ return err_msg("unsupported file type '%c'", type); -++ } -++ -++ if (separate_last(buf, len, &path, &name)) -++ return -1; -++ -++ /* -++ * Check if this path already exist in the path hash table and add it -++ * if it is not. -++ */ -++ ph_elt = hashtable_search(path_htbl, path); -++ if (!ph_elt) { -++ dbg_msg(3, "inserting '%s' into path hash table", path); -++ ph_elt = malloc(sizeof(struct path_htbl_element)); -++ if (!ph_elt) { -++ err_msg("cannot allocate %d bytes of memory", -++ sizeof(struct path_htbl_element)); -++ goto out_free; -++ } -++ -++ if (!hashtable_insert(path_htbl, path, ph_elt)) { -++ err_msg("cannot insert into path hash table"); -++ goto out_free; -++ } -++ -++ ph_elt->path = path; -++ path = NULL; -++ ph_elt->name_htbl = create_hashtable(128, &r5_hash, -++ &is_equivalent); -++ if (!ph_elt->name_htbl) { -++ err_msg("cannot create name hash table"); -++ goto out_free; -++ } -++ } -++ -++ if (increment != 0 && count == 0) -++ return err_msg("count cannot be zero if increment is non-zero"); -++ -++ /* -++ * Add the file/directory/device node (last component of the path) to -++ * the name hashtable. The name hashtable resides in the corresponding -++ * path hashtable element. -++ */ -++ -++ if (count == 0) { -++ /* This entry does not require any iterating */ -++ nh_elt = malloc(sizeof(struct name_htbl_element)); -++ if (!nh_elt) { -++ err_msg("cannot allocate %d bytes of memory", -++ sizeof(struct name_htbl_element)); -++ goto out_free; -++ } -++ -++ nh_elt->mode = mode; -++ nh_elt->uid = uid; -++ nh_elt->gid = gid; -++ nh_elt->dev = makedev(major, minor); -++ -++ dbg_msg(3, "inserting '%s' into name hash table (major %d, minor %d)", -++ name, major(nh_elt->dev), minor(nh_elt->dev)); -++ -++ if (hashtable_search(ph_elt->name_htbl, name)) -++ return err_msg("'%s' is referred twice", buf); -++ -++ nh_elt->name = name; -++ if (!hashtable_insert(ph_elt->name_htbl, name, nh_elt)) { -++ err_msg("cannot insert into name hash table"); -++ goto out_free; -++ } -++ } else { -++ int i, num = start + increment * count, len = strlen(name) + 20; -++ char *nm; -++ -++ for (i = start; i < num; i++) { -++ nh_elt = malloc(sizeof(struct name_htbl_element)); -++ if (!nh_elt) { -++ err_msg("cannot allocate %d bytes of memory", -++ sizeof(struct name_htbl_element)); -++ goto out_free; -++ } -++ -++ nh_elt->mode = mode; -++ nh_elt->uid = uid; -++ nh_elt->gid = gid; -++ nh_elt->dev = makedev(major, minor + i - start); -++ -++ nm = malloc(len); -++ if (!nm) { -++ err_msg("cannot allocate %d bytes of memory", len); -++ goto out_free; -++ } -++ -++ sprintf(nm, "%s%d", name, i); -++ nh_elt->name = nm; -++ -++ dbg_msg(3, "inserting '%s' into name hash table (major %d, minor %d)", -++ nm, major(nh_elt->dev), minor(nh_elt->dev)); -++ -++ if (hashtable_search(ph_elt->name_htbl, nm)) { -++ err_msg("'%s' is referred twice", buf); -++ free (nm); -++ goto out_free; -++ } -++ -++ if (!hashtable_insert(ph_elt->name_htbl, nm, nh_elt)) { -++ err_msg("cannot insert into name hash table"); -++ free (nm); -++ goto out_free; -++ } -++ } -++ free(name); -++ name = NULL; -++ } -++ -++ return 0; -++ -++out_free: -++ free(ph_elt); -++ free(nh_elt); -++ free(path); -++ free(name); -++ return -1; -++} -++ -++/** -++ * parse_devtable - parse the device table. -++ * @tbl_file: device table file name -++ * -++ * This function parses the device table and prepare the hash table which will -++ * later be used by mkfs.ubifs to create the specified files/device nodes. -++ * Returns zero in case of success and a negative error code in case of -++ * failure. -++ */ -++int parse_devtable(const char *root, const char *tbl_file) -++{ -++ FILE *f; -++ char *line = NULL; -++ struct stat st; -++ size_t len; -++ -++ dbg_msg(1, "parsing device table file '%s'", tbl_file); -++ -++ path_htbl = create_hashtable(128, &r5_hash, &is_equivalent); -++ if (!path_htbl) -++ return err_msg("cannot create path hash table"); -++ -++ f = fopen(tbl_file, "r"); -++ if (!f) -++ return sys_err_msg("cannot open '%s'", tbl_file); -++ -++ if (fstat(fileno(f), &st) < 0) { -++ sys_err_msg("cannot stat '%s'", tbl_file); -++ goto out_close; -++ } -++ -++ if (st.st_size < 10) { -++ sys_err_msg("'%s' is too short", tbl_file); -++ goto out_close; -++ } -++ -++ /* -++ * The general plan now is to read in one line at a time, check for -++ * leading comment delimiters ('#'), then try and parse the line as a -++ * device table -++ */ -++ while (getline(&line, &len, f) != -1) { -++ /* First trim off any white-space */ -++ len = strlen(line); -++ -++ /* Trim trailing white-space */ -++ while (len > 0 && isspace(line[len - 1])) -++ line[--len] = '\0'; -++ /* Trim leading white-space */ -++ memmove(line, &line[strspn(line, " \n\r\t\v")], len); -++ -++ /* How long are we after trimming? */ -++ len = strlen(line); -++ -++ /* If this is not a comment line, try to interpret it */ -++ if (len && *line != '#') { -++ if (interpret_table_entry(root, line)) { -++ err_msg("cannot parse '%s'", line); -++ goto out_close; -++ } -++ } -++ -++ free(line); -++ line = NULL; -++ } -++ -++ dbg_msg(1, "finished parsing"); -++ fclose(f); -++ return 0; -++ -++out_close: -++ fclose(f); -++ free_devtable_info(); -++ return -1; -++} -++ -++/** -++ * devtbl_find_path - find a path in the path hash table. -++ * @path: UBIFS path to find. -++ * -++ * This looks up the path hash table. Returns the path hash table element -++ * reference if @path was found and %NULL if not. -++ */ -++struct path_htbl_element *devtbl_find_path(const char *path) -++{ -++ if (!path_htbl) -++ return NULL; -++ -++ return hashtable_search(path_htbl, (void *)path); -++} -++ -++/** -++ * devtbl_find_name - find a name in the name hash table. -++ * @ph_etl: path hash table element to find at -++ * @name: name to find -++ * -++ * This looks up the name hash table. Returns the name hash table element -++ * reference if @name found and %NULL if not. -++ */ -++struct name_htbl_element *devtbl_find_name(struct path_htbl_element *ph_elt, -++ const char *name) -++{ -++ if (!path_htbl) -++ return NULL; -++ -++ return hashtable_search(ph_elt->name_htbl, (void *)name); -++} -++ -++/** -++ * override_attributes - override inode attributes. -++ * @st: struct stat object to containing the attributes to override -++ * @ph_elt: path hash table element object -++ * @nh_elt: name hash table element object containing the new values -++ * -++ * The device table file may override attributes like UID of files. For -++ * example, the device table may contain a "/dev" entry, and the UBIFS FS on -++ * the host may contain "/dev" directory. In this case the attributes of the -++ * "/dev" directory inode has to be as the device table specifies. -++ * -++ * Note, the hash element is removed by this function as well. -++ */ -++int override_attributes(struct stat *st, struct path_htbl_element *ph_elt, -++ struct name_htbl_element *nh_elt) -++{ -++ if (!path_htbl) -++ return 0; -++ -++ if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode) || -++ S_ISFIFO(st->st_mode)) -++ return err_msg("%s/%s both exists at UBIFS root at host, " -++ "and is referred from the device table", -++ strcmp(ph_elt->path, "/") ? ph_elt->path : "", -++ nh_elt->name); -++ -++ if ((st->st_mode & S_IFMT) != (nh_elt->mode & S_IFMT)) -++ return err_msg("%s/%s is referred from the device table also exists in " -++ "the UBIFS root directory at host, but the file type is " -++ "different", strcmp(ph_elt->path, "/") ? ph_elt->path : "", -++ nh_elt->name); -++ -++ dbg_msg(3, "set UID %d, GID %d, mode %o for %s/%s as device table says", -++ nh_elt->uid, nh_elt->gid, nh_elt->mode, ph_elt->path, nh_elt->name); -++ -++ st->st_uid = nh_elt->uid; -++ st->st_gid = nh_elt->gid; -++ st->st_mode = nh_elt->mode; -++ -++ hashtable_remove(ph_elt->name_htbl, (void *)nh_elt->name); -++ return 0; -++} -++ -++/** -++ * first_name_htbl_element - return first element of the name hash table. -++ * @ph_elt: the path hash table the name hash table belongs to -++ * @itr: double pointer to a 'struct hashtable_itr' object where the -++ * information about further iterations is stored -++ * -++ * This function implements name hash table iteration together with -++ * 'next_name_htbl_element()'. Returns the first name hash table element or -++ * %NULL if the hash table is empty. -++ */ -++struct name_htbl_element * -++first_name_htbl_element(struct path_htbl_element *ph_elt, -++ struct hashtable_itr **itr) -++{ -++ if (!path_htbl || !ph_elt || hashtable_count(ph_elt->name_htbl) == 0) -++ return NULL; -++ -++ *itr = hashtable_iterator(ph_elt->name_htbl); -++ return hashtable_iterator_value(*itr); -++} -++ -++/** -++ * first_name_htbl_element - return next element of the name hash table. -++ * @ph_elt: the path hash table the name hash table belongs to -++ * @itr: double pointer to a 'struct hashtable_itr' object where the -++ * information about further iterations is stored -++ * -++ * This function implements name hash table iteration together with -++ * 'first_name_htbl_element()'. Returns the next name hash table element or -++ * %NULL if there are no more elements. -++ */ -++struct name_htbl_element * -++next_name_htbl_element(struct path_htbl_element *ph_elt, -++ struct hashtable_itr **itr) -++{ -++ if (!path_htbl || !ph_elt || !hashtable_iterator_advance(*itr)) -++ return NULL; -++ -++ return hashtable_iterator_value(*itr); -++} -++ -++/** -++ * free_devtable_info - free device table information. -++ * -++ * This function frees the path hash table and the name hash tables. -++ */ -++void free_devtable_info(void) -++{ -++ struct hashtable_itr *ph_itr; -++ struct path_htbl_element *ph_elt; -++ -++ if (!path_htbl) -++ return; -++ -++ if (hashtable_count(path_htbl) > 0) { -++ ph_itr = hashtable_iterator(path_htbl); -++ do { -++ ph_elt = hashtable_iterator_value(ph_itr); -++ /* -++ * Note, since we use the same string for the key and -++ * @name in the name hash table elements, we do not -++ * have to iterate name hash table because @name memory -++ * will be freed when freeing the key. -++ */ -++ hashtable_destroy(ph_elt->name_htbl, 1); -++ } while (hashtable_iterator_advance(ph_itr)); -++ } -++ hashtable_destroy(path_htbl, 1); -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/hashtable/hashtable.c linux-2.6.24.7/fs/ubifs/mkfs.ubifs/hashtable/hashtable.c -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/hashtable/hashtable.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/hashtable/hashtable.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,274 @@ -++/* Copyright (C) 2004 Christopher Clark */ -++ -++#include "hashtable.h" -++#include "hashtable_private.h" -++#include -++#include -++#include -++#include -++ -++/* -++Credit for primes table: Aaron Krowne -++ http://br.endernet.org/~akrowne/ -++ http://planetmath.org/encyclopedia/GoodHashTablePrimes.html -++*/ -++static const unsigned int primes[] = { -++53, 97, 193, 389, -++769, 1543, 3079, 6151, -++12289, 24593, 49157, 98317, -++196613, 393241, 786433, 1572869, -++3145739, 6291469, 12582917, 25165843, -++50331653, 100663319, 201326611, 402653189, -++805306457, 1610612741 -++}; -++const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]); -++const float max_load_factor = 0.65; -++ -++/*****************************************************************************/ -++struct hashtable * -++create_hashtable(unsigned int minsize, -++ unsigned int (*hashf) (void*), -++ int (*eqf) (void*,void*)) -++{ -++ struct hashtable *h; -++ unsigned int pindex, size = primes[0]; -++ /* Check requested hashtable isn't too large */ -++ if (minsize > (1u << 30)) return NULL; -++ /* Enforce size as prime */ -++ for (pindex=0; pindex < prime_table_length; pindex++) { -++ if (primes[pindex] > minsize) { size = primes[pindex]; break; } -++ } -++ h = (struct hashtable *)malloc(sizeof(struct hashtable)); -++ if (NULL == h) return NULL; /*oom*/ -++ h->table = (struct entry **)malloc(sizeof(struct entry*) * size); -++ if (NULL == h->table) { free(h); return NULL; } /*oom*/ -++ memset(h->table, 0, size * sizeof(struct entry *)); -++ h->tablelength = size; -++ h->primeindex = pindex; -++ h->entrycount = 0; -++ h->hashfn = hashf; -++ h->eqfn = eqf; -++ h->loadlimit = (unsigned int) ceil(size * max_load_factor); -++ return h; -++} -++ -++/*****************************************************************************/ -++unsigned int -++hash(struct hashtable *h, void *k) -++{ -++ /* Aim to protect against poor hash functions by adding logic here -++ * - logic taken from java 1.4 hashtable source */ -++ unsigned int i = h->hashfn(k); -++ i += ~(i << 9); -++ i ^= ((i >> 14) | (i << 18)); /* >>> */ -++ i += (i << 4); -++ i ^= ((i >> 10) | (i << 22)); /* >>> */ -++ return i; -++} -++ -++/*****************************************************************************/ -++static int -++hashtable_expand(struct hashtable *h) -++{ -++ /* Double the size of the table to accomodate more entries */ -++ struct entry **newtable; -++ struct entry *e; -++ struct entry **pE; -++ unsigned int newsize, i, index; -++ /* Check we're not hitting max capacity */ -++ if (h->primeindex == (prime_table_length - 1)) return 0; -++ newsize = primes[++(h->primeindex)]; -++ -++ newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize); -++ if (NULL != newtable) -++ { -++ memset(newtable, 0, newsize * sizeof(struct entry *)); -++ /* This algorithm is not 'stable'. ie. it reverses the list -++ * when it transfers entries between the tables */ -++ for (i = 0; i < h->tablelength; i++) { -++ while (NULL != (e = h->table[i])) { -++ h->table[i] = e->next; -++ index = indexFor(newsize,e->h); -++ e->next = newtable[index]; -++ newtable[index] = e; -++ } -++ } -++ free(h->table); -++ h->table = newtable; -++ } -++ /* Plan B: realloc instead */ -++ else -++ { -++ newtable = (struct entry **) -++ realloc(h->table, newsize * sizeof(struct entry *)); -++ if (NULL == newtable) { (h->primeindex)--; return 0; } -++ h->table = newtable; -++ memset(newtable[h->tablelength], 0, newsize - h->tablelength); -++ for (i = 0; i < h->tablelength; i++) { -++ for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) { -++ index = indexFor(newsize,e->h); -++ if (index == i) -++ { -++ pE = &(e->next); -++ } -++ else -++ { -++ *pE = e->next; -++ e->next = newtable[index]; -++ newtable[index] = e; -++ } -++ } -++ } -++ } -++ h->tablelength = newsize; -++ h->loadlimit = (unsigned int) ceil(newsize * max_load_factor); -++ return -1; -++} -++ -++/*****************************************************************************/ -++unsigned int -++hashtable_count(struct hashtable *h) -++{ -++ return h->entrycount; -++} -++ -++/*****************************************************************************/ -++int -++hashtable_insert(struct hashtable *h, void *k, void *v) -++{ -++ /* This method allows duplicate keys - but they shouldn't be used */ -++ unsigned int index; -++ struct entry *e; -++ if (++(h->entrycount) > h->loadlimit) -++ { -++ /* Ignore the return value. If expand fails, we should -++ * still try cramming just this value into the existing table -++ * -- we may not have memory for a larger table, but one more -++ * element may be ok. Next time we insert, we'll try expanding again.*/ -++ hashtable_expand(h); -++ } -++ e = (struct entry *)malloc(sizeof(struct entry)); -++ if (NULL == e) { --(h->entrycount); return 0; } /*oom*/ -++ e->h = hash(h,k); -++ index = indexFor(h->tablelength,e->h); -++ e->k = k; -++ e->v = v; -++ e->next = h->table[index]; -++ h->table[index] = e; -++ return -1; -++} -++ -++/*****************************************************************************/ -++void * /* returns value associated with key */ -++hashtable_search(struct hashtable *h, void *k) -++{ -++ struct entry *e; -++ unsigned int hashvalue, index; -++ hashvalue = hash(h,k); -++ index = indexFor(h->tablelength,hashvalue); -++ e = h->table[index]; -++ while (NULL != e) -++ { -++ /* Check hash value to short circuit heavier comparison */ -++ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v; -++ e = e->next; -++ } -++ return NULL; -++} -++ -++/*****************************************************************************/ -++void * /* returns value associated with key */ -++hashtable_remove(struct hashtable *h, void *k) -++{ -++ /* TODO: consider compacting the table when the load factor drops enough, -++ * or provide a 'compact' method. */ -++ -++ struct entry *e; -++ struct entry **pE; -++ void *v; -++ unsigned int hashvalue, index; -++ -++ hashvalue = hash(h,k); -++ index = indexFor(h->tablelength,hash(h,k)); -++ pE = &(h->table[index]); -++ e = *pE; -++ while (NULL != e) -++ { -++ /* Check hash value to short circuit heavier comparison */ -++ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) -++ { -++ *pE = e->next; -++ h->entrycount--; -++ v = e->v; -++ freekey(e->k); -++ free(e); -++ return v; -++ } -++ pE = &(e->next); -++ e = e->next; -++ } -++ return NULL; -++} -++ -++/*****************************************************************************/ -++/* destroy */ -++void -++hashtable_destroy(struct hashtable *h, int free_values) -++{ -++ unsigned int i; -++ struct entry *e, *f; -++ struct entry **table = h->table; -++ if (free_values) -++ { -++ for (i = 0; i < h->tablelength; i++) -++ { -++ e = table[i]; -++ while (NULL != e) -++ { f = e; e = e->next; freekey(f->k); free(f->v); free(f); } -++ } -++ } -++ else -++ { -++ for (i = 0; i < h->tablelength; i++) -++ { -++ e = table[i]; -++ while (NULL != e) -++ { f = e; e = e->next; freekey(f->k); free(f); } -++ } -++ } -++ free(h->table); -++ free(h); -++} -++ -++/* -++ * Copyright (c) 2002, Christopher Clark -++ * All rights reserved. -++ * -++ * Redistribution and use in source and binary forms, with or without -++ * modification, are permitted provided that the following conditions -++ * are met: -++ * -++ * * Redistributions of source code must retain the above copyright -++ * notice, this list of conditions and the following disclaimer. -++ * -++ * * Redistributions in binary form must reproduce the above copyright -++ * notice, this list of conditions and the following disclaimer in the -++ * documentation and/or other materials provided with the distribution. -++ * -++ * * Neither the name of the original author; nor the names of any contributors -++ * may be used to endorse or promote products derived from this software -++ * without specific prior written permission. -++ * -++ * -++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -++ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -++*/ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/hashtable/hashtable.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/hashtable/hashtable.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/hashtable/hashtable.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/hashtable/hashtable.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,199 @@ -++/* Copyright (C) 2002 Christopher Clark */ -++ -++#ifndef __HASHTABLE_CWC22_H__ -++#define __HASHTABLE_CWC22_H__ -++ -++struct hashtable; -++ -++/* Example of use: -++ * -++ * struct hashtable *h; -++ * struct some_key *k; -++ * struct some_value *v; -++ * -++ * static unsigned int hash_from_key_fn( void *k ); -++ * static int keys_equal_fn ( void *key1, void *key2 ); -++ * -++ * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn); -++ * k = (struct some_key *) malloc(sizeof(struct some_key)); -++ * v = (struct some_value *) malloc(sizeof(struct some_value)); -++ * -++ * (initialise k and v to suitable values) -++ * -++ * if (! hashtable_insert(h,k,v) ) -++ * { exit(-1); } -++ * -++ * if (NULL == (found = hashtable_search(h,k) )) -++ * { printf("not found!"); } -++ * -++ * if (NULL == (found = hashtable_remove(h,k) )) -++ * { printf("Not found\n"); } -++ * -++ */ -++ -++/* Macros may be used to define type-safe(r) hashtable access functions, with -++ * methods specialized to take known key and value types as parameters. -++ * -++ * Example: -++ * -++ * Insert this at the start of your file: -++ * -++ * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value); -++ * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value); -++ * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value); -++ * -++ * This defines the functions 'insert_some', 'search_some' and 'remove_some'. -++ * These operate just like hashtable_insert etc., with the same parameters, -++ * but their function signatures have 'struct some_key *' rather than -++ * 'void *', and hence can generate compile time errors if your program is -++ * supplying incorrect data as a key (and similarly for value). -++ * -++ * Note that the hash and key equality functions passed to create_hashtable -++ * still take 'void *' parameters instead of 'some key *'. This shouldn't be -++ * a difficult issue as they're only defined and passed once, and the other -++ * functions will ensure that only valid keys are supplied to them. -++ * -++ * The cost for this checking is increased code size and runtime overhead -++ * - if performance is important, it may be worth switching back to the -++ * unsafe methods once your program has been debugged with the safe methods. -++ * This just requires switching to some simple alternative defines - eg: -++ * #define insert_some hashtable_insert -++ * -++ */ -++ -++/***************************************************************************** -++ * create_hashtable -++ -++ * @name create_hashtable -++ * @param minsize minimum initial size of hashtable -++ * @param hashfunction function for hashing keys -++ * @param key_eq_fn function for determining key equality -++ * @return newly created hashtable or NULL on failure -++ */ -++ -++struct hashtable * -++create_hashtable(unsigned int minsize, -++ unsigned int (*hashfunction) (void*), -++ int (*key_eq_fn) (void*,void*)); -++ -++/***************************************************************************** -++ * hashtable_insert -++ -++ * @name hashtable_insert -++ * @param h the hashtable to insert into -++ * @param k the key - hashtable claims ownership and will free on removal -++ * @param v the value - does not claim ownership -++ * @return non-zero for successful insertion -++ * -++ * This function will cause the table to expand if the insertion would take -++ * the ratio of entries to table size over the maximum load factor. -++ * -++ * This function does not check for repeated insertions with a duplicate key. -++ * The value returned when using a duplicate key is undefined -- when -++ * the hashtable changes size, the order of retrieval of duplicate key -++ * entries is reversed. -++ * If in doubt, remove before insert. -++ */ -++ -++int -++hashtable_insert(struct hashtable *h, void *k, void *v); -++ -++#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \ -++int fnname (struct hashtable *h, keytype *k, valuetype *v) \ -++{ \ -++ return hashtable_insert(h,k,v); \ -++} -++ -++/***************************************************************************** -++ * hashtable_search -++ -++ * @name hashtable_search -++ * @param h the hashtable to search -++ * @param k the key to search for - does not claim ownership -++ * @return the value associated with the key, or NULL if none found -++ */ -++ -++void * -++hashtable_search(struct hashtable *h, void *k); -++ -++#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \ -++valuetype * fnname (struct hashtable *h, keytype *k) \ -++{ \ -++ return (valuetype *) (hashtable_search(h,k)); \ -++} -++ -++/***************************************************************************** -++ * hashtable_remove -++ -++ * @name hashtable_remove -++ * @param h the hashtable to remove the item from -++ * @param k the key to search for - does not claim ownership -++ * @return the value associated with the key, or NULL if none found -++ */ -++ -++void * /* returns value */ -++hashtable_remove(struct hashtable *h, void *k); -++ -++#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \ -++valuetype * fnname (struct hashtable *h, keytype *k) \ -++{ \ -++ return (valuetype *) (hashtable_remove(h,k)); \ -++} -++ -++ -++/***************************************************************************** -++ * hashtable_count -++ -++ * @name hashtable_count -++ * @param h the hashtable -++ * @return the number of items stored in the hashtable -++ */ -++unsigned int -++hashtable_count(struct hashtable *h); -++ -++ -++/***************************************************************************** -++ * hashtable_destroy -++ -++ * @name hashtable_destroy -++ * @param h the hashtable -++ * @param free_values whether to call 'free' on the remaining values -++ */ -++ -++void -++hashtable_destroy(struct hashtable *h, int free_values); -++ -++#endif /* __HASHTABLE_CWC22_H__ */ -++ -++/* -++ * Copyright (c) 2002, Christopher Clark -++ * All rights reserved. -++ * -++ * Redistribution and use in source and binary forms, with or without -++ * modification, are permitted provided that the following conditions -++ * are met: -++ * -++ * * Redistributions of source code must retain the above copyright -++ * notice, this list of conditions and the following disclaimer. -++ * -++ * * Redistributions in binary form must reproduce the above copyright -++ * notice, this list of conditions and the following disclaimer in the -++ * documentation and/or other materials provided with the distribution. -++ * -++ * * Neither the name of the original author; nor the names of any contributors -++ * may be used to endorse or promote products derived from this software -++ * without specific prior written permission. -++ * -++ * -++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -++ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -++*/ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/hashtable/hashtable_itr.c linux-2.6.24.7/fs/ubifs/mkfs.ubifs/hashtable/hashtable_itr.c -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/hashtable/hashtable_itr.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/hashtable/hashtable_itr.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,188 @@ -++/* Copyright (C) 2002, 2004 Christopher Clark */ -++ -++#include "hashtable.h" -++#include "hashtable_private.h" -++#include "hashtable_itr.h" -++#include /* defines NULL */ -++ -++/*****************************************************************************/ -++/* hashtable_iterator - iterator constructor */ -++ -++struct hashtable_itr * -++hashtable_iterator(struct hashtable *h) -++{ -++ unsigned int i, tablelength; -++ struct hashtable_itr *itr = (struct hashtable_itr *) -++ malloc(sizeof(struct hashtable_itr)); -++ if (NULL == itr) return NULL; -++ itr->h = h; -++ itr->e = NULL; -++ itr->parent = NULL; -++ tablelength = h->tablelength; -++ itr->index = tablelength; -++ if (0 == h->entrycount) return itr; -++ -++ for (i = 0; i < tablelength; i++) -++ { -++ if (NULL != h->table[i]) -++ { -++ itr->e = h->table[i]; -++ itr->index = i; -++ break; -++ } -++ } -++ return itr; -++} -++ -++/*****************************************************************************/ -++/* key - return the key of the (key,value) pair at the current position */ -++/* value - return the value of the (key,value) pair at the current position */ -++ -++void * -++hashtable_iterator_key(struct hashtable_itr *i) -++{ return i->e->k; } -++ -++void * -++hashtable_iterator_value(struct hashtable_itr *i) -++{ return i->e->v; } -++ -++/*****************************************************************************/ -++/* advance - advance the iterator to the next element -++ * returns zero if advanced to end of table */ -++ -++int -++hashtable_iterator_advance(struct hashtable_itr *itr) -++{ -++ unsigned int j,tablelength; -++ struct entry **table; -++ struct entry *next; -++ if (NULL == itr->e) return 0; /* stupidity check */ -++ -++ next = itr->e->next; -++ if (NULL != next) -++ { -++ itr->parent = itr->e; -++ itr->e = next; -++ return -1; -++ } -++ tablelength = itr->h->tablelength; -++ itr->parent = NULL; -++ if (tablelength <= (j = ++(itr->index))) -++ { -++ itr->e = NULL; -++ return 0; -++ } -++ table = itr->h->table; -++ while (NULL == (next = table[j])) -++ { -++ if (++j >= tablelength) -++ { -++ itr->index = tablelength; -++ itr->e = NULL; -++ return 0; -++ } -++ } -++ itr->index = j; -++ itr->e = next; -++ return -1; -++} -++ -++/*****************************************************************************/ -++/* remove - remove the entry at the current iterator position -++ * and advance the iterator, if there is a successive -++ * element. -++ * If you want the value, read it before you remove: -++ * beware memory leaks if you don't. -++ * Returns zero if end of iteration. */ -++ -++int -++hashtable_iterator_remove(struct hashtable_itr *itr) -++{ -++ struct entry *remember_e, *remember_parent; -++ int ret; -++ -++ /* Do the removal */ -++ if (NULL == (itr->parent)) -++ { -++ /* element is head of a chain */ -++ itr->h->table[itr->index] = itr->e->next; -++ } else { -++ /* element is mid-chain */ -++ itr->parent->next = itr->e->next; -++ } -++ /* itr->e is now outside the hashtable */ -++ remember_e = itr->e; -++ itr->h->entrycount--; -++ freekey(remember_e->k); -++ -++ /* Advance the iterator, correcting the parent */ -++ remember_parent = itr->parent; -++ ret = hashtable_iterator_advance(itr); -++ if (itr->parent == remember_e) { itr->parent = remember_parent; } -++ free(remember_e); -++ return ret; -++} -++ -++/*****************************************************************************/ -++int /* returns zero if not found */ -++hashtable_iterator_search(struct hashtable_itr *itr, -++ struct hashtable *h, void *k) -++{ -++ struct entry *e, *parent; -++ unsigned int hashvalue, index; -++ -++ hashvalue = hash(h,k); -++ index = indexFor(h->tablelength,hashvalue); -++ -++ e = h->table[index]; -++ parent = NULL; -++ while (NULL != e) -++ { -++ /* Check hash value to short circuit heavier comparison */ -++ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) -++ { -++ itr->index = index; -++ itr->e = e; -++ itr->parent = parent; -++ itr->h = h; -++ return -1; -++ } -++ parent = e; -++ e = e->next; -++ } -++ return 0; -++} -++ -++ -++/* -++ * Copyright (c) 2002, 2004, Christopher Clark -++ * All rights reserved. -++ * -++ * Redistribution and use in source and binary forms, with or without -++ * modification, are permitted provided that the following conditions -++ * are met: -++ * -++ * * Redistributions of source code must retain the above copyright -++ * notice, this list of conditions and the following disclaimer. -++ * -++ * * Redistributions in binary form must reproduce the above copyright -++ * notice, this list of conditions and the following disclaimer in the -++ * documentation and/or other materials provided with the distribution. -++ * -++ * * Neither the name of the original author; nor the names of any contributors -++ * may be used to endorse or promote products derived from this software -++ * without specific prior written permission. -++ * -++ * -++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -++ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -++*/ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/hashtable/hashtable_itr.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/hashtable/hashtable_itr.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/hashtable/hashtable_itr.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/hashtable/hashtable_itr.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,112 @@ -++/* Copyright (C) 2002, 2004 Christopher Clark */ -++ -++#ifndef __HASHTABLE_ITR_CWC22__ -++#define __HASHTABLE_ITR_CWC22__ -++#include "hashtable.h" -++#include "hashtable_private.h" /* needed to enable inlining */ -++ -++/*****************************************************************************/ -++/* This struct is only concrete here to allow the inlining of two of the -++ * accessor functions. */ -++struct hashtable_itr -++{ -++ struct hashtable *h; -++ struct entry *e; -++ struct entry *parent; -++ unsigned int index; -++}; -++ -++ -++/*****************************************************************************/ -++/* hashtable_iterator -++ */ -++ -++struct hashtable_itr * -++hashtable_iterator(struct hashtable *h); -++ -++/*****************************************************************************/ -++/* hashtable_iterator_key -++ * - return the value of the (key,value) pair at the current position */ -++ -++extern inline void * -++hashtable_iterator_key(struct hashtable_itr *i) -++{ -++ return i->e->k; -++} -++ -++/*****************************************************************************/ -++/* value - return the value of the (key,value) pair at the current position */ -++ -++extern inline void * -++hashtable_iterator_value(struct hashtable_itr *i) -++{ -++ return i->e->v; -++} -++ -++/*****************************************************************************/ -++/* advance - advance the iterator to the next element -++ * returns zero if advanced to end of table */ -++ -++int -++hashtable_iterator_advance(struct hashtable_itr *itr); -++ -++/*****************************************************************************/ -++/* remove - remove current element and advance the iterator to the next element -++ * NB: if you need the value to free it, read it before -++ * removing. ie: beware memory leaks! -++ * returns zero if advanced to end of table */ -++ -++int -++hashtable_iterator_remove(struct hashtable_itr *itr); -++ -++/*****************************************************************************/ -++/* search - overwrite the supplied iterator, to point to the entry -++ * matching the supplied key. -++ h points to the hashtable to be searched. -++ * returns zero if not found. */ -++int -++hashtable_iterator_search(struct hashtable_itr *itr, -++ struct hashtable *h, void *k); -++ -++#define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \ -++int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \ -++{ \ -++ return (hashtable_iterator_search(i,h,k)); \ -++} -++ -++ -++ -++#endif /* __HASHTABLE_ITR_CWC22__*/ -++ -++/* -++ * Copyright (c) 2002, 2004, Christopher Clark -++ * All rights reserved. -++ * -++ * Redistribution and use in source and binary forms, with or without -++ * modification, are permitted provided that the following conditions -++ * are met: -++ * -++ * * Redistributions of source code must retain the above copyright -++ * notice, this list of conditions and the following disclaimer. -++ * -++ * * Redistributions in binary form must reproduce the above copyright -++ * notice, this list of conditions and the following disclaimer in the -++ * documentation and/or other materials provided with the distribution. -++ * -++ * * Neither the name of the original author; nor the names of any contributors -++ * may be used to endorse or promote products derived from this software -++ * without specific prior written permission. -++ * -++ * -++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -++ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -++*/ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/hashtable/hashtable_private.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/hashtable/hashtable_private.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/hashtable/hashtable_private.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/hashtable/hashtable_private.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,85 @@ -++/* Copyright (C) 2002, 2004 Christopher Clark */ -++ -++#ifndef __HASHTABLE_PRIVATE_CWC22_H__ -++#define __HASHTABLE_PRIVATE_CWC22_H__ -++ -++#include "hashtable.h" -++ -++/*****************************************************************************/ -++struct entry -++{ -++ void *k, *v; -++ unsigned int h; -++ struct entry *next; -++}; -++ -++struct hashtable { -++ unsigned int tablelength; -++ struct entry **table; -++ unsigned int entrycount; -++ unsigned int loadlimit; -++ unsigned int primeindex; -++ unsigned int (*hashfn) (void *k); -++ int (*eqfn) (void *k1, void *k2); -++}; -++ -++/*****************************************************************************/ -++unsigned int -++hash(struct hashtable *h, void *k); -++ -++/*****************************************************************************/ -++/* indexFor */ -++static inline unsigned int -++indexFor(unsigned int tablelength, unsigned int hashvalue) { -++ return (hashvalue % tablelength); -++}; -++ -++/* Only works if tablelength == 2^N */ -++/*static inline unsigned int -++indexFor(unsigned int tablelength, unsigned int hashvalue) -++{ -++ return (hashvalue & (tablelength - 1u)); -++} -++*/ -++ -++/*****************************************************************************/ -++#define freekey(X) free(X) -++/*define freekey(X) ; */ -++ -++ -++/*****************************************************************************/ -++ -++#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/ -++ -++/* -++ * Copyright (c) 2002, Christopher Clark -++ * All rights reserved. -++ * -++ * Redistribution and use in source and binary forms, with or without -++ * modification, are permitted provided that the following conditions -++ * are met: -++ * -++ * * Redistributions of source code must retain the above copyright -++ * notice, this list of conditions and the following disclaimer. -++ * -++ * * Redistributions in binary form must reproduce the above copyright -++ * notice, this list of conditions and the following disclaimer in the -++ * documentation and/or other materials provided with the distribution. -++ * -++ * * Neither the name of the original author; nor the names of any contributors -++ * may be used to endorse or promote products derived from this software -++ * without specific prior written permission. -++ * -++ * -++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -++ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -++*/ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/key.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/key.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/key.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/key.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,511 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* -++ * This header contains various key-related definitions and helper function. -++ * UBIFS allows several key schemes, so we access key fields only via these -++ * helpers. At the moment only one key scheme is supported. -++ * -++ * Simple key scheme -++ * ~~~~~~~~~~~~~~~~~ -++ * -++ * Keys are 64-bits long. First 32-bits are inode number (parent inode number -++ * in case of direntry key). Next 3 bits are node type. The last 29 bits are -++ * 4KiB offset in case of inode node, and direntry hash in case of a direntry -++ * node. We use "r5" hash borrowed from reiserfs. -++ */ -++ -++#ifndef __UBIFS_KEY_H__ -++#define __UBIFS_KEY_H__ -++ -++/** -++ * key_r5_hash - R5 hash function (borrowed from reiserfs). -++ * @s: direntry name -++ * @len: name length -++ */ -++static inline uint32_t key_r5_hash(const char *s, int len) -++{ -++ uint32_t a = 0; -++ const signed char *str = (const signed char *)s; -++ -++ while (*str) { -++ a += *str << 4; -++ a += *str >> 4; -++ a *= 11; -++ str++; -++ } -++ -++ a &= UBIFS_S_KEY_HASH_MASK; -++ -++ /* -++ * We use hash values as offset in directories, so values %0 and %1 are -++ * reserved for "." and "..". %2 is reserved for possible future use. -++ */ -++ if (unlikely(a >= 0 && a <= 2)) -++ a += 3; -++ return a; -++} -++ -++/** -++ * key_test_hash - testing hash function. -++ * @str: direntry name -++ * @len: name length -++ */ -++static inline uint32_t key_test_hash(const char *str, int len) -++{ -++ uint32_t a = 0; -++ -++ len = min_t(uint32_t, len, 4); -++ memcpy(&a, str, len); -++ a &= UBIFS_S_KEY_HASH_MASK; -++ if (unlikely(a >= 0 && a <= 2)) -++ a += 3; -++ return a; -++} -++ -++/** -++ * ino_key_init - initialize inode key. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: inode number -++ */ -++static inline void ino_key_init(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum) -++{ -++ key->u32[0] = inum; -++ key->u32[1] = UBIFS_INO_KEY << UBIFS_S_KEY_BLOCK_BITS; -++} -++ -++/** -++ * ino_key_init_flash - initialize on-flash inode key. -++ * @c: UBIFS file-system description object -++ * @k: key to initialize -++ * @inum: inode number -++ */ -++static inline void ino_key_init_flash(const struct ubifs_info *c, void *k, -++ ino_t inum) -++{ -++ union ubifs_key *key = k; -++ -++ key->j32[0] = cpu_to_le32(inum); -++ key->j32[1] = cpu_to_le32(UBIFS_INO_KEY << UBIFS_S_KEY_BLOCK_BITS); -++ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8); -++} -++ -++/** -++ * lowest_ino_key - get the lowest possible inode key. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: inode number -++ */ -++static inline void lowest_ino_key(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum) -++{ -++ key->u32[0] = inum; -++ key->u32[1] = 0; -++} -++ -++/** -++ * highest_ino_key - get the highest possible inode key. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: inode number -++ */ -++static inline void highest_ino_key(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum) -++{ -++ key->u32[0] = inum; -++ key->u32[1] = 0xffffffff; -++} -++ -++/** -++ * dent_key_init - initialize directory entry key. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: parent inode number -++ * @nm: direntry name and length -++ */ -++static inline void dent_key_init(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum, -++ const struct qstr *nm) -++{ -++ uint32_t hash = c->key_hash(nm->name, nm->len); -++ -++ key->u32[0] = inum; -++ key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS); -++} -++ -++/** -++ * dent_key_init_hash - initialize directory entry key without re-calculating -++ * hash function. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: parent inode number -++ * @hash: direntry name hash -++ */ -++static inline void dent_key_init_hash(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum, -++ uint32_t hash) -++{ -++ key->u32[0] = inum; -++ key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS); -++} -++ -++/** -++ * dent_key_init_flash - initialize on-flash directory entry key. -++ * @c: UBIFS file-system description object -++ * @k: key to initialize -++ * @inum: parent inode number -++ * @nm: direntry name and length -++ */ -++static inline void dent_key_init_flash(const struct ubifs_info *c, void *k, -++ ino_t inum, const struct qstr *nm) -++{ -++ union ubifs_key *key = k; -++ uint32_t hash = c->key_hash(nm->name, nm->len); -++ -++ key->j32[0] = cpu_to_le32(inum); -++ key->j32[1] = cpu_to_le32(hash | -++ (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS)); -++ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8); -++} -++ -++/** -++ * lowest_dent_key - get the lowest possible directory entry key. -++ * @c: UBIFS file-system description object -++ * @key: where to store the lowest key -++ * @inum: parent inode number -++ */ -++static inline void lowest_dent_key(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum) -++{ -++ key->u32[0] = inum; -++ key->u32[1] = UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS; -++} -++ -++/** -++ * xent_key_init - initialize extended attribute entry key. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: host inode number -++ * @nm: extended attribute entry name and length -++ */ -++static inline void xent_key_init(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum, -++ const struct qstr *nm) -++{ -++ uint32_t hash = c->key_hash(nm->name, nm->len); -++ -++ key->u32[0] = inum; -++ key->u32[1] = hash | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS); -++} -++ -++/** -++ * xent_key_init_hash - initialize extended attribute entry key without -++ * re-calculating hash function. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: host inode number -++ * @hash: extended attribute entry name hash -++ */ -++static inline void xent_key_init_hash(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum, -++ uint32_t hash) -++{ -++ key->u32[0] = inum; -++ key->u32[1] = hash | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS); -++} -++ -++/** -++ * xent_key_init_flash - initialize on-flash extended attribute entry key. -++ * @c: UBIFS file-system description object -++ * @k: key to initialize -++ * @inum: host inode number -++ * @nm: extended attribute entry name and length -++ */ -++static inline void xent_key_init_flash(const struct ubifs_info *c, void *k, -++ ino_t inum, const struct qstr *nm) -++{ -++ union ubifs_key *key = k; -++ uint32_t hash = c->key_hash(nm->name, nm->len); -++ -++ key->j32[0] = cpu_to_le32(inum); -++ key->j32[1] = cpu_to_le32(hash | -++ (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS)); -++ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8); -++} -++ -++/** -++ * lowest_xent_key - get the lowest possible extended attribute entry key. -++ * @c: UBIFS file-system description object -++ * @key: where to store the lowest key -++ * @inum: host inode number -++ */ -++static inline void lowest_xent_key(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum) -++{ -++ key->u32[0] = inum; -++ key->u32[1] = UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS; -++} -++ -++/** -++ * data_key_init - initialize data key. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: inode number -++ * @block: block number -++ */ -++static inline void data_key_init(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum, -++ unsigned int block) -++{ -++ key->u32[0] = inum; -++ key->u32[1] = block | (UBIFS_DATA_KEY << UBIFS_S_KEY_BLOCK_BITS); -++} -++ -++/** -++ * data_key_init_flash - initialize on-flash data key. -++ * @c: UBIFS file-system description object -++ * @k: key to initialize -++ * @inum: inode number -++ * @block: block number -++ */ -++static inline void data_key_init_flash(const struct ubifs_info *c, void *k, -++ ino_t inum, unsigned int block) -++{ -++ union ubifs_key *key = k; -++ -++ key->j32[0] = cpu_to_le32(inum); -++ key->j32[1] = cpu_to_le32(block | -++ (UBIFS_DATA_KEY << UBIFS_S_KEY_BLOCK_BITS)); -++ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8); -++} -++ -++/** -++ * trun_key_init - initialize truncation node key. -++ * @c: UBIFS file-system description object -++ * @key: key to initialize -++ * @inum: inode number -++ */ -++static inline void trun_key_init(const struct ubifs_info *c, -++ union ubifs_key *key, ino_t inum) -++{ -++ key->u32[0] = inum; -++ key->u32[1] = UBIFS_TRUN_KEY << UBIFS_S_KEY_BLOCK_BITS; -++} -++ -++/** -++ * trun_key_init_flash - initialize on-flash truncation node key. -++ * @c: UBIFS file-system description object -++ * @k: key to initialize -++ * @inum: inode number -++ */ -++static inline void trun_key_init_flash(const struct ubifs_info *c, void *k, -++ ino_t inum) -++{ -++ union ubifs_key *key = k; -++ -++ key->j32[0] = cpu_to_le32(inum); -++ key->j32[1] = cpu_to_le32(UBIFS_TRUN_KEY << UBIFS_S_KEY_BLOCK_BITS); -++ memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8); -++} -++ -++/** -++ * key_type - get key type. -++ * @c: UBIFS file-system description object -++ * @key: key to get type of -++ */ -++static inline int key_type(const struct ubifs_info *c, -++ const union ubifs_key *key) -++{ -++ return key->u32[1] >> UBIFS_S_KEY_BLOCK_BITS; -++} -++ -++/** -++ * key_type_flash - get type of a on-flash formatted key. -++ * @c: UBIFS file-system description object -++ * @k: key to get type of -++ */ -++static inline int key_type_flash(const struct ubifs_info *c, const void *k) -++{ -++ const union ubifs_key *key = k; -++ -++ return le32_to_cpu(key->u32[1]) >> UBIFS_S_KEY_BLOCK_BITS; -++} -++ -++/** -++ * key_ino - fetch inode number from key. -++ * @c: UBIFS file-system description object -++ * @k: key to fetch inode number from -++ */ -++static inline ino_t key_ino(const struct ubifs_info *c, const void *k) -++{ -++ const union ubifs_key *key = k; -++ -++ return key->u32[0]; -++} -++ -++/** -++ * key_ino_flash - fetch inode number from an on-flash formatted key. -++ * @c: UBIFS file-system description object -++ * @k: key to fetch inode number from -++ */ -++static inline ino_t key_ino_flash(const struct ubifs_info *c, const void *k) -++{ -++ const union ubifs_key *key = k; -++ -++ return le32_to_cpu(key->j32[0]); -++} -++ -++/** -++ * key_hash - get directory entry hash. -++ * @c: UBIFS file-system description object -++ * @key: the key to get hash from -++ */ -++static inline int key_hash(const struct ubifs_info *c, -++ const union ubifs_key *key) -++{ -++ return key->u32[1] & UBIFS_S_KEY_HASH_MASK; -++} -++ -++/** -++ * key_hash_flash - get directory entry hash from an on-flash formatted key. -++ * @c: UBIFS file-system description object -++ * @k: the key to get hash from -++ */ -++static inline int key_hash_flash(const struct ubifs_info *c, const void *k) -++{ -++ const union ubifs_key *key = k; -++ -++ return le32_to_cpu(key->j32[1]) & UBIFS_S_KEY_HASH_MASK; -++} -++ -++/** -++ * key_block - get data block number. -++ * @c: UBIFS file-system description object -++ * @key: the key to get the block number from -++ */ -++static inline unsigned int key_block(const struct ubifs_info *c, -++ const union ubifs_key *key) -++{ -++ return key->u32[1] & UBIFS_S_KEY_BLOCK_MASK; -++} -++ -++/** -++ * key_read - transform a key to in-memory format. -++ * @c: UBIFS file-system description object -++ * @from: the key to transform -++ * @to: the key to store the result -++ */ -++static inline void key_read(const struct ubifs_info *c, const void *from, -++ union ubifs_key *to) -++{ -++ const union ubifs_key *f = from; -++ -++ to->u32[0] = le32_to_cpu(f->j32[0]); -++ to->u32[1] = le32_to_cpu(f->j32[1]); -++} -++ -++/** -++ * key_write - transform a key from in-memory format. -++ * @c: UBIFS file-system description object -++ * @from: the key to transform -++ * @to: the key to store the result -++ */ -++static inline void key_write(const struct ubifs_info *c, -++ const union ubifs_key *from, void *to) -++{ -++ union ubifs_key *t = to; -++ -++ t->j32[0] = cpu_to_le32(from->u32[0]); -++ t->j32[1] = cpu_to_le32(from->u32[1]); -++ memset(to + 8, 0, UBIFS_MAX_KEY_LEN - 8); -++} -++ -++/** -++ * key_write_idx - transform a key from in-memory format for the index. -++ * @c: UBIFS file-system description object -++ * @from: the key to transform -++ * @to: the key to store the result -++ */ -++static inline void key_write_idx(const struct ubifs_info *c, -++ const union ubifs_key *from, void *to) -++{ -++ union ubifs_key *t = to; -++ -++ t->j32[0] = cpu_to_le32(from->u32[0]); -++ t->j32[1] = cpu_to_le32(from->u32[1]); -++} -++ -++/** -++ * key_copy - copy a key. -++ * @c: UBIFS file-system description object -++ * @from: the key to copy from -++ * @to: the key to copy to -++ */ -++static inline void key_copy(const struct ubifs_info *c, -++ const union ubifs_key *from, union ubifs_key *to) -++{ -++ to->u64[0] = from->u64[0]; -++} -++ -++/** -++ * keys_cmp - compare keys. -++ * @c: UBIFS file-system description object -++ * @key1: the first key to compare -++ * @key2: the second key to compare -++ * -++ * This function compares 2 keys and returns %-1 if @key1 is less than -++ * @key2, 0 if the keys are equivalent and %1 if @key1 is greater than @key2. -++ */ -++static inline int keys_cmp(const struct ubifs_info *c, -++ const union ubifs_key *key1, -++ const union ubifs_key *key2) -++{ -++ if (key1->u32[0] < key2->u32[0]) -++ return -1; -++ if (key1->u32[0] > key2->u32[0]) -++ return 1; -++ if (key1->u32[1] < key2->u32[1]) -++ return -1; -++ if (key1->u32[1] > key2->u32[1]) -++ return 1; -++ -++ return 0; -++} -++ -++/** -++ * is_hash_key - is a key vulnerable to hash collisions. -++ * @c: UBIFS file-system description object -++ * @key: key -++ * -++ * This function returns %1 if @key is a hashed key or %0 otherwise. -++ */ -++static inline int is_hash_key(const struct ubifs_info *c, -++ const union ubifs_key *key) -++{ -++ int type = key_type(c, key); -++ -++ return type == UBIFS_DENT_KEY || type == UBIFS_XENT_KEY; -++} -++ -++#endif /* !__UBIFS_KEY_H__ */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lpt.c linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lpt.c -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lpt.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lpt.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,577 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006, 2007 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Adrian Hunter -++ * Artem Bityutskiy -++ */ -++ -++#include "mkfs.ubifs.h" -++ -++/** -++ * do_calc_lpt_geom - calculate sizes for the LPT area. -++ * @c: the UBIFS file-system description object -++ * -++ * Calculate the sizes of LPT bit fields, nodes, and tree, based on the -++ * properties of the flash and whether LPT is "big" (c->big_lpt). -++ */ -++static void do_calc_lpt_geom(struct ubifs_info *c) -++{ -++ int n, bits, per_leb_wastage; -++ long long sz, tot_wastage; -++ -++ c->pnode_cnt = (c->main_lebs + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT; -++ -++ n = (c->pnode_cnt + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT; -++ c->nnode_cnt = n; -++ while (n > 1) { -++ n = (n + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT; -++ c->nnode_cnt += n; -++ } -++ -++ c->lpt_hght = 1; -++ n = UBIFS_LPT_FANOUT; -++ while (n < c->pnode_cnt) { -++ c->lpt_hght += 1; -++ n <<= UBIFS_LPT_FANOUT_SHIFT; -++ } -++ -++ c->space_bits = fls(c->leb_size) - 3; -++ c->lpt_lnum_bits = fls(c->lpt_lebs); -++ c->lpt_offs_bits = fls(c->leb_size - 1); -++ c->lpt_spc_bits = fls(c->leb_size); -++ -++ n = (c->max_leb_cnt + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT; -++ c->pcnt_bits = fls(n - 1); -++ -++ c->lnum_bits = fls(c->max_leb_cnt - 1); -++ -++ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS + -++ (c->big_lpt ? c->pcnt_bits : 0) + -++ (c->space_bits * 2 + 1) * UBIFS_LPT_FANOUT; -++ c->pnode_sz = (bits + 7) / 8; -++ -++ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS + -++ (c->big_lpt ? c->pcnt_bits : 0) + -++ (c->lpt_lnum_bits + c->lpt_offs_bits) * UBIFS_LPT_FANOUT; -++ c->nnode_sz = (bits + 7) / 8; -++ -++ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS + -++ c->lpt_lebs * c->lpt_spc_bits * 2; -++ c->ltab_sz = (bits + 7) / 8; -++ -++ bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS + -++ c->lnum_bits * c->lsave_cnt; -++ c->lsave_sz = (bits + 7) / 8; -++ -++ /* Calculate the minimum LPT size */ -++ c->lpt_sz = (long long)c->pnode_cnt * c->pnode_sz; -++ c->lpt_sz += (long long)c->nnode_cnt * c->nnode_sz; -++ c->lpt_sz += c->ltab_sz; -++ c->lpt_sz += c->lsave_sz; -++ -++ /* Add wastage */ -++ sz = c->lpt_sz; -++ per_leb_wastage = max_t(int, c->pnode_sz, c->nnode_sz); -++ sz += per_leb_wastage; -++ tot_wastage = per_leb_wastage; -++ while (sz > c->leb_size) { -++ sz += per_leb_wastage; -++ sz -= c->leb_size; -++ tot_wastage += per_leb_wastage; -++ } -++ tot_wastage += ALIGN(sz, c->min_io_size) - sz; -++ c->lpt_sz += tot_wastage; -++} -++ -++/** -++ * calc_dflt_lpt_geom - calculate default LPT geometry. -++ * @c: the UBIFS file-system description object -++ * @main_lebs: number of main area LEBs is passed and returned here -++ * @big_lpt: whether the LPT area is "big" is returned here -++ * -++ * The size of the LPT area depends on parameters that themselves are dependent -++ * on the size of the LPT area. This function, successively recalculates the LPT -++ * area geometry until the parameters and resultant geometry are consistent. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs, int *big_lpt) -++{ -++ int i, lebs_needed; -++ long long sz; -++ -++ /* Start by assuming the minimum number of LPT LEBs */ -++ c->lpt_lebs = UBIFS_MIN_LPT_LEBS; -++ c->main_lebs = *main_lebs - c->lpt_lebs; -++ if (c->main_lebs <= 0) -++ return -EINVAL; -++ -++ /* And assume we will use the small LPT model */ -++ c->big_lpt = 0; -++ -++ /* -++ * Calculate the geometry based on assumptions above and then see if it -++ * makes sense -++ */ -++ do_calc_lpt_geom(c); -++ -++ /* Small LPT model must have lpt_sz < leb_size */ -++ if (c->lpt_sz > c->leb_size) { -++ /* Nope, so try again using big LPT model */ -++ c->big_lpt = 1; -++ do_calc_lpt_geom(c); -++ } -++ -++ /* Now check there are enough LPT LEBs */ -++ for (i = 0; i < 64 ; i++) { -++ sz = c->lpt_sz * 4; /* Allow 4 times the size */ -++ sz += c->leb_size - 1; -++ do_div(sz, c->leb_size); -++ lebs_needed = sz; -++ if (lebs_needed > c->lpt_lebs) { -++ /* Not enough LPT LEBs so try again with more */ -++ c->lpt_lebs = lebs_needed; -++ c->main_lebs = *main_lebs - c->lpt_lebs; -++ if (c->main_lebs <= 0) -++ return -EINVAL; -++ do_calc_lpt_geom(c); -++ continue; -++ } -++ if (c->ltab_sz > c->leb_size) { -++ err_msg("LPT ltab too big"); -++ return -EINVAL; -++ } -++ *main_lebs = c->main_lebs; -++ *big_lpt = c->big_lpt; -++ return 0; -++ } -++ return -EINVAL; -++} -++ -++/** -++ * pack_bits - pack bit fields end-to-end. -++ * @addr: address at which to pack (passed and next address returned) -++ * @pos: bit position at which to pack (passed and next position returned) -++ * @val: value to pack -++ * @nrbits: number of bits of value to pack (1-32) -++ */ -++static void pack_bits(uint8_t **addr, int *pos, uint32_t val, int nrbits) -++{ -++ uint8_t *p = *addr; -++ int b = *pos; -++ -++ if (b) { -++ *p |= ((uint8_t)val) << b; -++ nrbits += b; -++ if (nrbits > 8) { -++ *++p = (uint8_t)(val >>= (8 - b)); -++ if (nrbits > 16) { -++ *++p = (uint8_t)(val >>= 8); -++ if (nrbits > 24) { -++ *++p = (uint8_t)(val >>= 8); -++ if (nrbits > 32) -++ *++p = (uint8_t)(val >>= 8); -++ } -++ } -++ } -++ } else { -++ *p = (uint8_t)val; -++ if (nrbits > 8) { -++ *++p = (uint8_t)(val >>= 8); -++ if (nrbits > 16) { -++ *++p = (uint8_t)(val >>= 8); -++ if (nrbits > 24) -++ *++p = (uint8_t)(val >>= 8); -++ } -++ } -++ } -++ b = nrbits & 7; -++ if (b == 0) -++ p++; -++ *addr = p; -++ *pos = b; -++} -++ -++/** -++ * pack_pnode - pack all the bit fields of a pnode. -++ * @c: UBIFS file-system description object -++ * @buf: buffer into which to pack -++ * @pnode: pnode to pack -++ */ -++static void pack_pnode(struct ubifs_info *c, void *buf, -++ struct ubifs_pnode *pnode) -++{ -++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; -++ int i, pos = 0; -++ uint16_t crc; -++ -++ pack_bits(&addr, &pos, UBIFS_LPT_PNODE, UBIFS_LPT_TYPE_BITS); -++ if (c->big_lpt) -++ pack_bits(&addr, &pos, pnode->num, c->pcnt_bits); -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ pack_bits(&addr, &pos, pnode->lprops[i].free >> 3, -++ c->space_bits); -++ pack_bits(&addr, &pos, pnode->lprops[i].dirty >> 3, -++ c->space_bits); -++ if (pnode->lprops[i].flags & LPROPS_INDEX) -++ pack_bits(&addr, &pos, 1, 1); -++ else -++ pack_bits(&addr, &pos, 0, 1); -++ } -++ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES, -++ c->pnode_sz - UBIFS_LPT_CRC_BYTES); -++ addr = buf; -++ pos = 0; -++ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS); -++} -++ -++/** -++ * pack_nnode - pack all the bit fields of a nnode. -++ * @c: UBIFS file-system description object -++ * @buf: buffer into which to pack -++ * @nnode: nnode to pack -++ */ -++static void pack_nnode(struct ubifs_info *c, void *buf, -++ struct ubifs_nnode *nnode) -++{ -++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; -++ int i, pos = 0; -++ uint16_t crc; -++ -++ pack_bits(&addr, &pos, UBIFS_LPT_NNODE, UBIFS_LPT_TYPE_BITS); -++ if (c->big_lpt) -++ pack_bits(&addr, &pos, nnode->num, c->pcnt_bits); -++ for (i = 0; i < UBIFS_LPT_FANOUT; i++) { -++ int lnum = nnode->nbranch[i].lnum; -++ -++ if (lnum == 0) -++ lnum = c->lpt_last + 1; -++ pack_bits(&addr, &pos, lnum - c->lpt_first, c->lpt_lnum_bits); -++ pack_bits(&addr, &pos, nnode->nbranch[i].offs, -++ c->lpt_offs_bits); -++ } -++ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES, -++ c->nnode_sz - UBIFS_LPT_CRC_BYTES); -++ addr = buf; -++ pos = 0; -++ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS); -++} -++ -++/** -++ * pack_ltab - pack the LPT's own lprops table. -++ * @c: UBIFS file-system description object -++ * @buf: buffer into which to pack -++ * @ltab: LPT's own lprops table to pack -++ */ -++static void pack_ltab(struct ubifs_info *c, void *buf, -++ struct ubifs_lpt_lprops *ltab) -++{ -++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; -++ int i, pos = 0; -++ uint16_t crc; -++ -++ pack_bits(&addr, &pos, UBIFS_LPT_LTAB, UBIFS_LPT_TYPE_BITS); -++ for (i = 0; i < c->lpt_lebs; i++) { -++ pack_bits(&addr, &pos, ltab[i].free, c->lpt_spc_bits); -++ pack_bits(&addr, &pos, ltab[i].dirty, c->lpt_spc_bits); -++ } -++ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES, -++ c->ltab_sz - UBIFS_LPT_CRC_BYTES); -++ addr = buf; -++ pos = 0; -++ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS); -++} -++ -++/** -++ * pack_lsave - pack the LPT's save table. -++ * @c: UBIFS file-system description object -++ * @buf: buffer into which to pack -++ * @lsave: LPT's save table to pack -++ */ -++static void pack_lsave(struct ubifs_info *c, void *buf, int *lsave) -++{ -++ uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; -++ int i, pos = 0; -++ uint16_t crc; -++ -++ pack_bits(&addr, &pos, UBIFS_LPT_LSAVE, UBIFS_LPT_TYPE_BITS); -++ for (i = 0; i < c->lsave_cnt; i++) -++ pack_bits(&addr, &pos, lsave[i], c->lnum_bits); -++ crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES, -++ c->lsave_sz - UBIFS_LPT_CRC_BYTES); -++ addr = buf; -++ pos = 0; -++ pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS); -++} -++ -++/** -++ * set_ltab - set LPT LEB properties. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number -++ * @free: amount of free space -++ * @dirty: amount of dirty space -++ */ -++static void set_ltab(struct ubifs_info *c, int lnum, int free, int dirty) -++{ -++ dbg_msg(3, "LEB %d free %d dirty %d to %d %d", -++ lnum, c->ltab[lnum - c->lpt_first].free, -++ c->ltab[lnum - c->lpt_first].dirty, free, dirty); -++ c->ltab[lnum - c->lpt_first].free = free; -++ c->ltab[lnum - c->lpt_first].dirty = dirty; -++} -++ -++/** -++ * calc_nnode_num - calculate nnode number. -++ * @row: the row in the tree (root is zero) -++ * @col: the column in the row (leftmost is zero) -++ * -++ * The nnode number is a number that uniquely identifies a nnode and can be used -++ * easily to traverse the tree from the root to that nnode. -++ * -++ * This function calculates and returns the nnode number for the nnode at @row -++ * and @col. -++ */ -++static int calc_nnode_num(int row, int col) -++{ -++ int num, bits; -++ -++ num = 1; -++ while (row--) { -++ bits = (col & (UBIFS_LPT_FANOUT - 1)); -++ col >>= UBIFS_LPT_FANOUT_SHIFT; -++ num <<= UBIFS_LPT_FANOUT_SHIFT; -++ num |= bits; -++ } -++ return num; -++} -++ -++/** -++ * create_lpt - create LPT. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int create_lpt(struct ubifs_info *c) -++{ -++ int lnum, err = 0, i, j, cnt, len, alen, row; -++ int blnum, boffs, bsz, bcnt; -++ struct ubifs_pnode *pnode = NULL; -++ struct ubifs_nnode *nnode = NULL; -++ void *buf = NULL, *p; -++ int *lsave = NULL; -++ -++ pnode = malloc(sizeof(struct ubifs_pnode)); -++ nnode = malloc(sizeof(struct ubifs_nnode)); -++ buf = malloc(c->leb_size); -++ lsave = malloc(sizeof(int) * c->lsave_cnt); -++ if (!pnode || !nnode || !buf || !lsave) { -++ err = -ENOMEM; -++ goto out; -++ } -++ memset(pnode, 0 , sizeof(struct ubifs_pnode)); -++ memset(nnode, 0 , sizeof(struct ubifs_pnode)); -++ -++ c->lscan_lnum = c->main_first; -++ -++ lnum = c->lpt_first; -++ p = buf; -++ len = 0; -++ /* Number of leaf nodes (pnodes) */ -++ cnt = (c->main_lebs + UBIFS_LPT_FANOUT - 1) >> UBIFS_LPT_FANOUT_SHIFT; -++ //printf("pnode_cnt=%d\n",cnt); -++ -++ /* -++ * To calculate the internal node branches, we keep information about -++ * the level below. -++ */ -++ blnum = lnum; /* LEB number of level below */ -++ boffs = 0; /* Offset of level below */ -++ bcnt = cnt; /* Number of nodes in level below */ -++ bsz = c->pnode_sz; /* Size of nodes in level below */ -++ -++ /* Add pnodes */ -++ for (i = 0; i < cnt; i++) { -++ if (len + c->pnode_sz > c->leb_size) { -++ alen = ALIGN(len, c->min_io_size); -++ set_ltab(c, lnum, c->leb_size - alen, alen - len); -++ memset(p, 0xff, alen - len); -++ err = write_leb(lnum++, alen, buf); -++ if (err) -++ goto out; -++ p = buf; -++ len = 0; -++ } -++ /* Fill in the pnode */ -++ for (j = 0; j < UBIFS_LPT_FANOUT; j++) { -++ int k = (i << UBIFS_LPT_FANOUT_SHIFT) + j; -++ -++ if (k < c->main_lebs) -++ pnode->lprops[j] = c->lpt[k]; -++ else { -++ pnode->lprops[j].free = c->leb_size; -++ pnode->lprops[j].dirty = 0; -++ pnode->lprops[j].flags = 0; -++ } -++ } -++ pack_pnode(c, p, pnode); -++ p += c->pnode_sz; -++ len += c->pnode_sz; -++ /* -++ * pnodes are simply numbered left to right starting at zero, -++ * which means the pnode number can be used easily to traverse -++ * down the tree to the corresponding pnode. -++ */ -++ pnode->num += 1; -++ } -++ -++ row = c->lpt_hght - 1; -++ /* Add all nnodes, one level at a time */ -++ while (1) { -++ /* Number of internal nodes (nnodes) at next level */ -++ cnt = (cnt + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT; -++ if (cnt == 0) -++ cnt = 1; -++ for (i = 0; i < cnt; i++) { -++ if (len + c->nnode_sz > c->leb_size) { -++ alen = ALIGN(len, c->min_io_size); -++ set_ltab(c, lnum, c->leb_size - alen, -++ alen - len); -++ memset(p, 0xff, alen - len); -++ err = write_leb(lnum++, alen, buf); -++ if (err) -++ goto out; -++ p = buf; -++ len = 0; -++ } -++ /* The root is on row zero */ -++ if (row == 0) { -++ c->lpt_lnum = lnum; -++ c->lpt_offs = len; -++ } -++ /* Set branches to the level below */ -++ for (j = 0; j < UBIFS_LPT_FANOUT; j++) { -++ if (bcnt) { -++ if (boffs + bsz > c->leb_size) { -++ blnum += 1; -++ boffs = 0; -++ } -++ nnode->nbranch[j].lnum = blnum; -++ nnode->nbranch[j].offs = boffs; -++ boffs += bsz; -++ bcnt--; -++ } else { -++ nnode->nbranch[j].lnum = 0; -++ nnode->nbranch[j].offs = 0; -++ } -++ } -++ nnode->num = calc_nnode_num(row, i); -++ pack_nnode(c, p, nnode); -++ p += c->nnode_sz; -++ len += c->nnode_sz; -++ } -++ /* Row zero is the top row */ -++ if (row == 0) -++ break; -++ /* Update the information about the level below */ -++ bcnt = cnt; -++ bsz = c->nnode_sz; -++ row -= 1; -++ } -++ -++ if (c->big_lpt) { -++ /* Need to add LPT's save table */ -++ if (len + c->lsave_sz > c->leb_size) { -++ alen = ALIGN(len, c->min_io_size); -++ set_ltab(c, lnum, c->leb_size - alen, alen - len); -++ memset(p, 0xff, alen - len); -++ err = write_leb(lnum++, alen, buf); -++ if (err) -++ goto out; -++ p = buf; -++ len = 0; -++ } -++ -++ c->lsave_lnum = lnum; -++ c->lsave_offs = len; -++ -++ for (i = 0; i < c->lsave_cnt; i++) -++ lsave[i] = c->main_first + i; -++ -++ pack_lsave(c, p, lsave); -++ p += c->lsave_sz; -++ len += c->lsave_sz; -++ } -++ -++ /* Need to add LPT's own LEB properties table */ -++ if (len + c->ltab_sz > c->leb_size) { -++ alen = ALIGN(len, c->min_io_size); -++ set_ltab(c, lnum, c->leb_size - alen, alen - len); -++ memset(p, 0xff, alen - len); -++ err = write_leb(lnum++, alen, buf); -++ if (err) -++ goto out; -++ p = buf; -++ len = 0; -++ } -++ -++ c->ltab_lnum = lnum; -++ c->ltab_offs = len; -++ -++ /* Update ltab before packing it */ -++ len += c->ltab_sz; -++ alen = ALIGN(len, c->min_io_size); -++ set_ltab(c, lnum, c->leb_size - alen, alen - len); -++ -++ pack_ltab(c, p, c->ltab); -++ p += c->ltab_sz; -++ -++ /* Write remaining buffer */ -++ memset(p, 0xff, alen - len); -++ err = write_leb(lnum, alen, buf); -++ if (err) -++ goto out; -++ -++ c->nhead_lnum = lnum; -++ c->nhead_offs = ALIGN(len, c->min_io_size); -++ -++ dbg_msg(1, "space_bits: %d", c->space_bits); -++ dbg_msg(1, "lpt_lnum_bits: %d", c->lpt_lnum_bits); -++ dbg_msg(1, "lpt_offs_bits: %d", c->lpt_offs_bits); -++ dbg_msg(1, "lpt_spc_bits: %d", c->lpt_spc_bits); -++ dbg_msg(1, "pcnt_bits: %d", c->pcnt_bits); -++ dbg_msg(1, "lnum_bits: %d", c->lnum_bits); -++ dbg_msg(1, "pnode_sz: %d", c->pnode_sz); -++ dbg_msg(1, "nnode_sz: %d", c->nnode_sz); -++ dbg_msg(1, "ltab_sz: %d", c->ltab_sz); -++ dbg_msg(1, "lsave_sz: %d", c->lsave_sz); -++ dbg_msg(1, "lsave_cnt: %d", c->lsave_cnt); -++ dbg_msg(1, "lpt_hght: %d", c->lpt_hght); -++ dbg_msg(1, "big_lpt: %d", c->big_lpt); -++ dbg_msg(1, "LPT root is at %d:%d", c->lpt_lnum, c->lpt_offs); -++ dbg_msg(1, "LPT head is at %d:%d", c->nhead_lnum, c->nhead_offs); -++ dbg_msg(1, "LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs); -++ if (c->big_lpt) -++ dbg_msg(1, "LPT lsave is at %d:%d", -++ c->lsave_lnum, c->lsave_offs); -++out: -++ free(lsave); -++ free(buf); -++ free(nnode); -++ free(pnode); -++ return err; -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lpt.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lpt.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lpt.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lpt.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,28 @@ -++/* -++ * Copyright (C) 2008 Nokia Corporation. -++ * Copyright (C) 2008 University of Szeged, Hungary -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy -++ * Adrian Hunter -++ */ -++ -++#ifndef __UBIFS_LPT_H__ -++#define __UBIFS_LPT_H__ -++ -++int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs, int *big_lpt); -++int create_lpt(struct ubifs_info *c); -++ -++#endif -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,92 @@ -++/* lzo1.h -- public interface of the LZO1 compression algorithm -++ -++ This file is part of the LZO real-time data compression library. -++ -++ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer -++ All Rights Reserved. -++ -++ The LZO library is free software; you can redistribute it and/or -++ modify it under the terms of the GNU General Public License, -++ version 2, as published by the Free Software Foundation. -++ -++ The LZO library is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with the LZO library; see the file COPYING. -++ If not, write to the Free Software Foundation, Inc., -++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -++ -++ Markus F.X.J. Oberhumer -++ -++ http://www.oberhumer.com/opensource/lzo/ -++ */ -++ -++ -++#ifndef __LZO1_H_INCLUDED -++#define __LZO1_H_INCLUDED -++ -++#ifndef __LZOCONF_H_INCLUDED -++#include "lzoconf.h" -++#endif -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++/* Memory required for the wrkmem parameter. -++ * When the required size is 0, you can also pass a NULL pointer. -++ */ -++ -++#define LZO1_MEM_COMPRESS ((lzo_uint32) (8192L * lzo_sizeof_dict_t)) -++#define LZO1_MEM_DECOMPRESS (0) -++ -++ -++LZO_EXTERN(int) -++lzo1_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++LZO_EXTERN(int) -++lzo1_decompress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++ -++/*********************************************************************** -++// better compression ratio at the cost of more memory and time -++************************************************************************/ -++ -++#define LZO1_99_MEM_COMPRESS ((lzo_uint32) (65536L * lzo_sizeof_dict_t)) -++ -++LZO_EXTERN(int) -++lzo1_99_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++ -++#ifdef __cplusplus -++} /* extern "C" */ -++#endif -++ -++#endif /* already included */ -++ -++ -++/* vim:set ts=4 et: */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1a.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1a.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1a.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1a.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,92 @@ -++/* lzo1a.h -- public interface of the LZO1A compression algorithm -++ -++ This file is part of the LZO real-time data compression library. -++ -++ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer -++ All Rights Reserved. -++ -++ The LZO library is free software; you can redistribute it and/or -++ modify it under the terms of the GNU General Public License, -++ version 2, as published by the Free Software Foundation. -++ -++ The LZO library is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with the LZO library; see the file COPYING. -++ If not, write to the Free Software Foundation, Inc., -++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -++ -++ Markus F.X.J. Oberhumer -++ -++ http://www.oberhumer.com/opensource/lzo/ -++ */ -++ -++ -++#ifndef __LZO1A_H_INCLUDED -++#define __LZO1A_H_INCLUDED -++ -++#ifndef __LZOCONF_H_INCLUDED -++#include "lzoconf.h" -++#endif -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++/* Memory required for the wrkmem parameter. -++ * When the required size is 0, you can also pass a NULL pointer. -++ */ -++ -++#define LZO1A_MEM_COMPRESS ((lzo_uint32) (8192L * lzo_sizeof_dict_t)) -++#define LZO1A_MEM_DECOMPRESS (0) -++ -++ -++LZO_EXTERN(int) -++lzo1a_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++LZO_EXTERN(int) -++lzo1a_decompress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++ -++/*********************************************************************** -++// better compression ratio at the cost of more memory and time -++************************************************************************/ -++ -++#define LZO1A_99_MEM_COMPRESS ((lzo_uint32) (65536L * lzo_sizeof_dict_t)) -++ -++LZO_EXTERN(int) -++lzo1a_99_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++ -++#ifdef __cplusplus -++} /* extern "C" */ -++#endif -++ -++#endif /* already included */ -++ -++ -++/* vim:set ts=4 et: */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1b.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1b.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1b.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1b.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,156 @@ -++/* lzo1b.h -- public interface of the LZO1B compression algorithm -++ -++ This file is part of the LZO real-time data compression library. -++ -++ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer -++ All Rights Reserved. -++ -++ The LZO library is free software; you can redistribute it and/or -++ modify it under the terms of the GNU General Public License, -++ version 2, as published by the Free Software Foundation. -++ -++ The LZO library is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with the LZO library; see the file COPYING. -++ If not, write to the Free Software Foundation, Inc., -++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -++ -++ Markus F.X.J. Oberhumer -++ -++ http://www.oberhumer.com/opensource/lzo/ -++ */ -++ -++ -++#ifndef __LZO1B_H_INCLUDED -++#define __LZO1B_H_INCLUDED -++ -++#ifndef __LZOCONF_H_INCLUDED -++#include "lzoconf.h" -++#endif -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++/* Memory required for the wrkmem parameter. -++ * When the required size is 0, you can also pass a NULL pointer. -++ */ -++ -++#define LZO1B_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) -++#define LZO1B_MEM_DECOMPRESS (0) -++ -++ -++/* compression levels */ -++#define LZO1B_BEST_SPEED 1 -++#define LZO1B_BEST_COMPRESSION 9 -++#define LZO1B_DEFAULT_COMPRESSION (-1) /* fastest by default */ -++ -++ -++LZO_EXTERN(int) -++lzo1b_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem, -++ int compression_level ); -++ -++/* decompression */ -++LZO_EXTERN(int) -++lzo1b_decompress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++/* safe decompression with overrun testing */ -++LZO_EXTERN(int) -++lzo1b_decompress_safe ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++LZO_EXTERN(int) -++lzo1b_1_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++LZO_EXTERN(int) -++lzo1b_2_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++LZO_EXTERN(int) -++lzo1b_3_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++LZO_EXTERN(int) -++lzo1b_4_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++LZO_EXTERN(int) -++lzo1b_5_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++LZO_EXTERN(int) -++lzo1b_6_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++LZO_EXTERN(int) -++lzo1b_7_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++LZO_EXTERN(int) -++lzo1b_8_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++LZO_EXTERN(int) -++lzo1b_9_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++/*********************************************************************** -++// better compression ratio at the cost of more memory and time -++************************************************************************/ -++ -++#define LZO1B_99_MEM_COMPRESS ((lzo_uint32) (65536L * lzo_sizeof_dict_t)) -++ -++LZO_EXTERN(int) -++lzo1b_99_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++#define LZO1B_999_MEM_COMPRESS ((lzo_uint32) (3 * 65536L * sizeof(lzo_xint))) -++ -++LZO_EXTERN(int) -++lzo1b_999_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++ -++#ifdef __cplusplus -++} /* extern "C" */ -++#endif -++ -++#endif /* already included */ -++ -++ -++/* vim:set ts=4 et: */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1c.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1c.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1c.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1c.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,156 @@ -++/* lzo1c.h -- public interface of the LZO1C compression algorithm -++ -++ This file is part of the LZO real-time data compression library. -++ -++ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer -++ All Rights Reserved. -++ -++ The LZO library is free software; you can redistribute it and/or -++ modify it under the terms of the GNU General Public License, -++ version 2, as published by the Free Software Foundation. -++ -++ The LZO library is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with the LZO library; see the file COPYING. -++ If not, write to the Free Software Foundation, Inc., -++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -++ -++ Markus F.X.J. Oberhumer -++ -++ http://www.oberhumer.com/opensource/lzo/ -++ */ -++ -++ -++#ifndef __LZO1C_H_INCLUDED -++#define __LZO1C_H_INCLUDED -++ -++#ifndef __LZOCONF_H_INCLUDED -++#include "lzoconf.h" -++#endif -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++/* Memory required for the wrkmem parameter. -++ * When the required size is 0, you can also pass a NULL pointer. -++ */ -++ -++#define LZO1C_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) -++#define LZO1C_MEM_DECOMPRESS (0) -++ -++ -++/* compression levels */ -++#define LZO1C_BEST_SPEED 1 -++#define LZO1C_BEST_COMPRESSION 9 -++#define LZO1C_DEFAULT_COMPRESSION (-1) /* fastest by default */ -++ -++ -++LZO_EXTERN(int) -++lzo1c_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem, -++ int compression_level ); -++ -++/* decompression */ -++LZO_EXTERN(int) -++lzo1c_decompress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++/* safe decompression with overrun testing */ -++LZO_EXTERN(int) -++lzo1c_decompress_safe ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++LZO_EXTERN(int) -++lzo1c_1_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++LZO_EXTERN(int) -++lzo1c_2_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++LZO_EXTERN(int) -++lzo1c_3_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++LZO_EXTERN(int) -++lzo1c_4_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++LZO_EXTERN(int) -++lzo1c_5_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++LZO_EXTERN(int) -++lzo1c_6_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++LZO_EXTERN(int) -++lzo1c_7_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++LZO_EXTERN(int) -++lzo1c_8_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++LZO_EXTERN(int) -++lzo1c_9_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++/*********************************************************************** -++// better compression ratio at the cost of more memory and time -++************************************************************************/ -++ -++#define LZO1C_99_MEM_COMPRESS ((lzo_uint32) (65536L * lzo_sizeof_dict_t)) -++ -++LZO_EXTERN(int) -++lzo1c_99_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++#define LZO1C_999_MEM_COMPRESS ((lzo_uint32) (5 * 16384L * sizeof(short))) -++ -++LZO_EXTERN(int) -++lzo1c_999_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++ -++#ifdef __cplusplus -++} /* extern "C" */ -++#endif -++ -++#endif /* already included */ -++ -++ -++/* vim:set ts=4 et: */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1f.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1f.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1f.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1f.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,104 @@ -++/* lzo1f.h -- public interface of the LZO1F compression algorithm -++ -++ This file is part of the LZO real-time data compression library. -++ -++ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer -++ All Rights Reserved. -++ -++ The LZO library is free software; you can redistribute it and/or -++ modify it under the terms of the GNU General Public License, -++ version 2, as published by the Free Software Foundation. -++ -++ The LZO library is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with the LZO library; see the file COPYING. -++ If not, write to the Free Software Foundation, Inc., -++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -++ -++ Markus F.X.J. Oberhumer -++ -++ http://www.oberhumer.com/opensource/lzo/ -++ */ -++ -++ -++#ifndef __LZO1F_H_INCLUDED -++#define __LZO1F_H_INCLUDED -++ -++#ifndef __LZOCONF_H_INCLUDED -++#include "lzoconf.h" -++#endif -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++/* Memory required for the wrkmem parameter. -++ * When the required size is 0, you can also pass a NULL pointer. -++ */ -++ -++#define LZO1F_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) -++#define LZO1F_MEM_DECOMPRESS (0) -++ -++ -++/* decompression */ -++LZO_EXTERN(int) -++lzo1f_decompress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++/* safe decompression with overrun testing */ -++LZO_EXTERN(int) -++lzo1f_decompress_safe ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++LZO_EXTERN(int) -++lzo1f_1_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++/*********************************************************************** -++// better compression ratio at the cost of more memory and time -++************************************************************************/ -++ -++#define LZO1F_999_MEM_COMPRESS ((lzo_uint32) (5 * 16384L * sizeof(short))) -++ -++LZO_EXTERN(int) -++lzo1f_999_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++ -++#ifdef __cplusplus -++} /* extern "C" */ -++#endif -++ -++#endif /* already included */ -++ -++ -++/* vim:set ts=4 et: */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1x.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1x.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1x.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1x.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,173 @@ -++/* lzo1x.h -- public interface of the LZO1X compression algorithm -++ -++ This file is part of the LZO real-time data compression library. -++ -++ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer -++ All Rights Reserved. -++ -++ The LZO library is free software; you can redistribute it and/or -++ modify it under the terms of the GNU General Public License, -++ version 2, as published by the Free Software Foundation. -++ -++ The LZO library is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with the LZO library; see the file COPYING. -++ If not, write to the Free Software Foundation, Inc., -++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -++ -++ Markus F.X.J. Oberhumer -++ -++ http://www.oberhumer.com/opensource/lzo/ -++ */ -++ -++ -++#ifndef __LZO1X_H_INCLUDED -++#define __LZO1X_H_INCLUDED -++ -++#ifndef __LZOCONF_H_INCLUDED -++#include "lzoconf.h" -++#endif -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++/* Memory required for the wrkmem parameter. -++ * When the required size is 0, you can also pass a NULL pointer. -++ */ -++ -++#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS -++#define LZO1X_MEM_DECOMPRESS (0) -++#define LZO1X_MEM_OPTIMIZE (0) -++ -++ -++/* decompression */ -++LZO_EXTERN(int) -++lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++/* safe decompression with overrun testing */ -++LZO_EXTERN(int) -++lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) -++ -++LZO_EXTERN(int) -++lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++/*********************************************************************** -++// special compressor versions -++************************************************************************/ -++ -++/* this version needs only 8 kB work memory */ -++#define LZO1X_1_11_MEM_COMPRESS ((lzo_uint32) (2048L * lzo_sizeof_dict_t)) -++ -++LZO_EXTERN(int) -++lzo1x_1_11_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++/* this version needs 16 kB work memory */ -++#define LZO1X_1_12_MEM_COMPRESS ((lzo_uint32) (4096L * lzo_sizeof_dict_t)) -++ -++LZO_EXTERN(int) -++lzo1x_1_12_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++/* use this version if you need a little more compression speed */ -++#define LZO1X_1_15_MEM_COMPRESS ((lzo_uint32) (32768L * lzo_sizeof_dict_t)) -++ -++LZO_EXTERN(int) -++lzo1x_1_15_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++/*********************************************************************** -++// better compression ratio at the cost of more memory and time -++************************************************************************/ -++ -++#define LZO1X_999_MEM_COMPRESS ((lzo_uint32) (14 * 16384L * sizeof(short))) -++ -++LZO_EXTERN(int) -++lzo1x_999_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++LZO_EXTERN(int) -++lzo1x_999_compress_dict ( const lzo_bytep in , lzo_uint in_len, -++ lzo_bytep out, lzo_uintp out_len, -++ lzo_voidp wrkmem, -++ const lzo_bytep dict, lzo_uint dict_len ); -++ -++LZO_EXTERN(int) -++lzo1x_999_compress_level ( const lzo_bytep in , lzo_uint in_len, -++ lzo_bytep out, lzo_uintp out_len, -++ lzo_voidp wrkmem, -++ const lzo_bytep dict, lzo_uint dict_len, -++ lzo_callback_p cb, -++ int compression_level ); -++ -++LZO_EXTERN(int) -++lzo1x_decompress_dict_safe ( const lzo_bytep in, lzo_uint in_len, -++ lzo_bytep out, lzo_uintp out_len, -++ lzo_voidp wrkmem /* NOT USED */, -++ const lzo_bytep dict, lzo_uint dict_len ); -++ -++ -++/*********************************************************************** -++// optimize a compressed data block -++************************************************************************/ -++ -++LZO_EXTERN(int) -++lzo1x_optimize ( lzo_bytep in , lzo_uint in_len, -++ lzo_bytep out, lzo_uintp out_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++ -++ -++#ifdef __cplusplus -++} /* extern "C" */ -++#endif -++ -++#endif /* already included */ -++ -++ -++/* vim:set ts=4 et: */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1y.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1y.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1y.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1y.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,141 @@ -++/* lzo1y.h -- public interface of the LZO1Y compression algorithm -++ -++ This file is part of the LZO real-time data compression library. -++ -++ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer -++ All Rights Reserved. -++ -++ The LZO library is free software; you can redistribute it and/or -++ modify it under the terms of the GNU General Public License, -++ version 2, as published by the Free Software Foundation. -++ -++ The LZO library is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with the LZO library; see the file COPYING. -++ If not, write to the Free Software Foundation, Inc., -++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -++ -++ Markus F.X.J. Oberhumer -++ -++ http://www.oberhumer.com/opensource/lzo/ -++ */ -++ -++ -++#ifndef __LZO1Y_H_INCLUDED -++#define __LZO1Y_H_INCLUDED -++ -++#ifndef __LZOCONF_H_INCLUDED -++#include "lzoconf.h" -++#endif -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++/* Memory required for the wrkmem parameter. -++ * When the required size is 0, you can also pass a NULL pointer. -++ */ -++ -++#define LZO1Y_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) -++#define LZO1Y_MEM_DECOMPRESS (0) -++#define LZO1Y_MEM_OPTIMIZE (0) -++ -++ -++/* decompression */ -++LZO_EXTERN(int) -++lzo1y_decompress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++/* safe decompression with overrun testing */ -++LZO_EXTERN(int) -++lzo1y_decompress_safe ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++LZO_EXTERN(int) -++lzo1y_1_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++/*********************************************************************** -++// better compression ratio at the cost of more memory and time -++************************************************************************/ -++ -++#define LZO1Y_999_MEM_COMPRESS ((lzo_uint32) (14 * 16384L * sizeof(short))) -++ -++LZO_EXTERN(int) -++lzo1y_999_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++LZO_EXTERN(int) -++lzo1y_999_compress_dict ( const lzo_bytep in , lzo_uint in_len, -++ lzo_bytep out, lzo_uintp out_len, -++ lzo_voidp wrkmem, -++ const lzo_bytep dict, lzo_uint dict_len ); -++ -++LZO_EXTERN(int) -++lzo1y_999_compress_level ( const lzo_bytep in , lzo_uint in_len, -++ lzo_bytep out, lzo_uintp out_len, -++ lzo_voidp wrkmem, -++ const lzo_bytep dict, lzo_uint dict_len, -++ lzo_callback_p cb, -++ int compression_level ); -++ -++LZO_EXTERN(int) -++lzo1y_decompress_dict_safe ( const lzo_bytep in, lzo_uint in_len, -++ lzo_bytep out, lzo_uintp out_len, -++ lzo_voidp wrkmem /* NOT USED */, -++ const lzo_bytep dict, lzo_uint dict_len ); -++ -++ -++/*********************************************************************** -++// optimize a compressed data block -++************************************************************************/ -++ -++LZO_EXTERN(int) -++lzo1y_optimize ( lzo_bytep in , lzo_uint in_len, -++ lzo_bytep out, lzo_uintp out_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++ -++ -++#ifdef __cplusplus -++} /* extern "C" */ -++#endif -++ -++#endif /* already included */ -++ -++ -++/* vim:set ts=4 et: */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1z.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1z.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1z.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo1z.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,146 @@ -++/* lzo1z.h -- public interface of the LZO1Z compression algorithm -++ -++ This file is part of the LZO real-time data compression library. -++ -++ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer -++ All Rights Reserved. -++ -++ The LZO library is free software; you can redistribute it and/or -++ modify it under the terms of the GNU General Public License, -++ version 2, as published by the Free Software Foundation. -++ -++ The LZO library is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with the LZO library; see the file COPYING. -++ If not, write to the Free Software Foundation, Inc., -++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -++ -++ Markus F.X.J. Oberhumer -++ -++ http://www.oberhumer.com/opensource/lzo/ -++ */ -++ -++ -++#ifndef __LZO1Z_H_INCLUDED -++#define __LZO1Z_H_INCLUDED -++ -++#ifndef __LZOCONF_H_INCLUDED -++#include "lzoconf.h" -++#endif -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++/* Memory required for the wrkmem parameter. -++ * When the required size is 0, you can also pass a NULL pointer. -++ */ -++ -++#define LZO1Z_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) -++#define LZO1Z_MEM_DECOMPRESS (0) -++#define LZO1Z_MEM_OPTIMIZE (0) -++ -++ -++/* decompression */ -++LZO_EXTERN(int) -++lzo1z_decompress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++/* safe decompression with overrun testing */ -++LZO_EXTERN(int) -++lzo1z_decompress_safe ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++#if 0 -++/* not yet implemented */ -++LZO_EXTERN(int) -++lzo1z_1_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++#endif -++ -++ -++/*********************************************************************** -++// better compression ratio at the cost of more memory and time -++************************************************************************/ -++ -++#define LZO1Z_999_MEM_COMPRESS ((lzo_uint32) (14 * 16384L * sizeof(short))) -++ -++LZO_EXTERN(int) -++lzo1z_999_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++LZO_EXTERN(int) -++lzo1z_999_compress_dict ( const lzo_bytep in , lzo_uint in_len, -++ lzo_bytep out, lzo_uintp out_len, -++ lzo_voidp wrkmem, -++ const lzo_bytep dict, lzo_uint dict_len ); -++ -++LZO_EXTERN(int) -++lzo1z_999_compress_level ( const lzo_bytep in , lzo_uint in_len, -++ lzo_bytep out, lzo_uintp out_len, -++ lzo_voidp wrkmem, -++ const lzo_bytep dict, lzo_uint dict_len, -++ lzo_callback_p cb, -++ int compression_level ); -++ -++LZO_EXTERN(int) -++lzo1z_decompress_dict_safe ( const lzo_bytep in, lzo_uint in_len, -++ lzo_bytep out, lzo_uintp out_len, -++ lzo_voidp wrkmem /* NOT USED */, -++ const lzo_bytep dict, lzo_uint dict_len ); -++ -++ -++/*********************************************************************** -++// optimize a compressed data block -++************************************************************************/ -++ -++#if 0 -++/* not yet implemented */ -++LZO_EXTERN(int) -++lzo1z_optimize ( lzo_bytep in , lzo_uint in_len, -++ lzo_bytep out, lzo_uintp out_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++#endif -++ -++ -++ -++#ifdef __cplusplus -++} /* extern "C" */ -++#endif -++ -++#endif /* already included */ -++ -++ -++/* vim:set ts=4 et: */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo2a.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo2a.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo2a.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo2a.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,88 @@ -++/* lzo2a.h -- public interface of the LZO2A compression algorithm -++ -++ This file is part of the LZO real-time data compression library. -++ -++ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer -++ All Rights Reserved. -++ -++ The LZO library is free software; you can redistribute it and/or -++ modify it under the terms of the GNU General Public License, -++ version 2, as published by the Free Software Foundation. -++ -++ The LZO library is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with the LZO library; see the file COPYING. -++ If not, write to the Free Software Foundation, Inc., -++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -++ -++ Markus F.X.J. Oberhumer -++ -++ http://www.oberhumer.com/opensource/lzo/ -++ */ -++ -++ -++#ifndef __LZO2A_H_INCLUDED -++#define __LZO2A_H_INCLUDED -++ -++#ifndef __LZOCONF_H_INCLUDED -++#include "lzoconf.h" -++#endif -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++ -++/*********************************************************************** -++// -++************************************************************************/ -++ -++#define LZO2A_MEM_DECOMPRESS (0) -++ -++/* decompression */ -++LZO_EXTERN(int) -++lzo2a_decompress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++/* safe decompression with overrun testing */ -++LZO_EXTERN(int) -++lzo2a_decompress_safe ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem /* NOT USED */ ); -++ -++ -++/*********************************************************************** -++// better compression ratio at the cost of more memory and time -++************************************************************************/ -++ -++#define LZO2A_999_MEM_COMPRESS ((lzo_uint32) (8 * 16384L * sizeof(short))) -++ -++LZO_EXTERN(int) -++lzo2a_999_compress ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++ -++ -++#ifdef __cplusplus -++} /* extern "C" */ -++#endif -++ -++#endif /* already included */ -++ -++ -++/* vim:set ts=4 et: */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo_asm.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo_asm.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo_asm.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzo_asm.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,135 @@ -++/* lzo_asm.h -- assembler prototypes for the LZO data compression library -++ -++ This file is part of the LZO real-time data compression library. -++ -++ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer -++ All Rights Reserved. -++ -++ The LZO library is free software; you can redistribute it and/or -++ modify it under the terms of the GNU General Public License, -++ version 2, as published by the Free Software Foundation. -++ -++ The LZO library is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with the LZO library; see the file COPYING. -++ If not, write to the Free Software Foundation, Inc., -++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -++ -++ Markus F.X.J. Oberhumer -++ -++ http://www.oberhumer.com/opensource/lzo/ -++ */ -++ -++ -++#ifndef __LZO_ASM_H_INCLUDED -++#define __LZO_ASM_H_INCLUDED -++ -++#ifndef __LZOCONF_H_INCLUDED -++#include "lzoconf.h" -++#endif -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++ -++/*********************************************************************** -++// assembly decompressors -++************************************************************************/ -++ -++LZO_EXTERN(int) lzo1c_decompress_asm -++ (const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem); -++LZO_EXTERN(int) lzo1c_decompress_asm_safe -++ (const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem); -++ -++LZO_EXTERN(int) lzo1f_decompress_asm_fast -++ (const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem); -++LZO_EXTERN(int) lzo1f_decompress_asm_fast_safe -++ (const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem); -++ -++LZO_EXTERN(int) lzo1x_decompress_asm -++ (const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem); -++LZO_EXTERN(int) lzo1x_decompress_asm_safe -++ (const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem); -++LZO_EXTERN(int) lzo1x_decompress_asm_fast -++ (const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem); -++LZO_EXTERN(int) lzo1x_decompress_asm_fast_safe -++ (const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem); -++ -++LZO_EXTERN(int) lzo1y_decompress_asm -++ (const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem); -++LZO_EXTERN(int) lzo1y_decompress_asm_safe -++ (const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem); -++LZO_EXTERN(int) lzo1y_decompress_asm_fast -++ (const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem); -++LZO_EXTERN(int) lzo1y_decompress_asm_fast_safe -++ (const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem); -++ -++ -++/*********************************************************************** -++// checksum and misc functions -++************************************************************************/ -++ -++#if 0 -++ -++LZO_EXTERN(lzo_uint32) -++lzo_crc32_asm(lzo_uint32 _c, const lzo_bytep _buf, lzo_uint _len, -++ const lzo_uint32p _crc_table); -++ -++LZO_EXTERN(lzo_uint32) -++lzo_crc32_asm_small(lzo_uint32 _c, const lzo_bytep _buf, lzo_uint _len); -++ -++LZO_EXTERN(int) -++lzo_cpuid_asm(lzo_uint32p /* lzo_uint32 info[16] */ ); -++ -++LZO_EXTERN(lzo_uint32) -++lzo_rdtsc_asm(lzo_uint32p /* lzo_uint32 ticks[2] */ ); -++ -++#endif -++ -++ -++#ifdef __cplusplus -++} /* extern "C" */ -++#endif -++ -++#endif /* already included */ -++ -++ -++/* vim:set ts=4 et: */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzoconf.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzoconf.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzoconf.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzoconf.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,413 @@ -++/* lzoconf.h -- configuration for the LZO real-time data compression library -++ -++ This file is part of the LZO real-time data compression library. -++ -++ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer -++ All Rights Reserved. -++ -++ The LZO library is free software; you can redistribute it and/or -++ modify it under the terms of the GNU General Public License, -++ version 2, as published by the Free Software Foundation. -++ -++ The LZO library is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with the LZO library; see the file COPYING. -++ If not, write to the Free Software Foundation, Inc., -++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -++ -++ Markus F.X.J. Oberhumer -++ -++ http://www.oberhumer.com/opensource/lzo/ -++ */ -++ -++ -++#ifndef __LZOCONF_H_INCLUDED -++#define __LZOCONF_H_INCLUDED -++ -++#define LZO_VERSION 0x2020 -++#define LZO_VERSION_STRING "2.02" -++#define LZO_VERSION_DATE "Oct 17 2005" -++ -++/* internal Autoconf configuration file - only used when building LZO */ -++#if defined(LZO_HAVE_CONFIG_H) -++# include -++#endif -++#include -++#include -++ -++ -++/*********************************************************************** -++// LZO requires a conforming -++************************************************************************/ -++ -++#if !defined(CHAR_BIT) || (CHAR_BIT != 8) -++# error "invalid CHAR_BIT" -++#endif -++#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) -++# error "check your compiler installation" -++#endif -++#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) -++# error "your limits.h macros are broken" -++#endif -++ -++/* get OS and architecture defines */ -++#ifndef __LZODEFS_H_INCLUDED -++#include "lzodefs.h" -++#endif -++ -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++ -++/*********************************************************************** -++// some core defines -++************************************************************************/ -++ -++#if !defined(LZO_UINT32_C) -++# if (UINT_MAX < LZO_0xffffffffL) -++# define LZO_UINT32_C(c) c ## UL -++# else -++# define LZO_UINT32_C(c) ((c) + 0U) -++# endif -++#endif -++ -++/* memory checkers */ -++#if !defined(__LZO_CHECKER) -++# if defined(__BOUNDS_CHECKING_ON) -++# define __LZO_CHECKER 1 -++# elif defined(__CHECKER__) -++# define __LZO_CHECKER 1 -++# elif defined(__INSURE__) -++# define __LZO_CHECKER 1 -++# elif defined(__PURIFY__) -++# define __LZO_CHECKER 1 -++# endif -++#endif -++ -++ -++/*********************************************************************** -++// integral and pointer types -++************************************************************************/ -++ -++/* lzo_uint should match size_t */ -++#if !defined(LZO_UINT_MAX) -++# if defined(LZO_ABI_LLP64) /* WIN64 */ -++# if defined(LZO_OS_WIN64) -++ typedef unsigned __int64 lzo_uint; -++ typedef __int64 lzo_int; -++# else -++ typedef unsigned long long lzo_uint; -++ typedef long long lzo_int; -++# endif -++# define LZO_UINT_MAX 0xffffffffffffffffull -++# define LZO_INT_MAX 9223372036854775807LL -++# define LZO_INT_MIN (-1LL - LZO_INT_MAX) -++# elif defined(LZO_ABI_IP32L64) /* MIPS R5900 */ -++ typedef unsigned int lzo_uint; -++ typedef int lzo_int; -++# define LZO_UINT_MAX UINT_MAX -++# define LZO_INT_MAX INT_MAX -++# define LZO_INT_MIN INT_MIN -++# elif (ULONG_MAX >= LZO_0xffffffffL) -++ typedef unsigned long lzo_uint; -++ typedef long lzo_int; -++# define LZO_UINT_MAX ULONG_MAX -++# define LZO_INT_MAX LONG_MAX -++# define LZO_INT_MIN LONG_MIN -++# else -++# error "lzo_uint" -++# endif -++#endif -++ -++/* Integral types with 32 bits or more. */ -++#if !defined(LZO_UINT32_MAX) -++# if (UINT_MAX >= LZO_0xffffffffL) -++ typedef unsigned int lzo_uint32; -++ typedef int lzo_int32; -++# define LZO_UINT32_MAX UINT_MAX -++# define LZO_INT32_MAX INT_MAX -++# define LZO_INT32_MIN INT_MIN -++# elif (ULONG_MAX >= LZO_0xffffffffL) -++ typedef unsigned long lzo_uint32; -++ typedef long lzo_int32; -++# define LZO_UINT32_MAX ULONG_MAX -++# define LZO_INT32_MAX LONG_MAX -++# define LZO_INT32_MIN LONG_MIN -++# else -++# error "lzo_uint32" -++# endif -++#endif -++ -++/* The larger type of lzo_uint and lzo_uint32. */ -++#if (LZO_UINT_MAX >= LZO_UINT32_MAX) -++# define lzo_xint lzo_uint -++#else -++# define lzo_xint lzo_uint32 -++#endif -++ -++/* Memory model that allows to access memory at offsets of lzo_uint. */ -++#if !defined(__LZO_MMODEL) -++# if (LZO_UINT_MAX <= UINT_MAX) -++# define __LZO_MMODEL -++# elif defined(LZO_HAVE_MM_HUGE_PTR) -++# define __LZO_MMODEL_HUGE 1 -++# define __LZO_MMODEL __huge -++# else -++# define __LZO_MMODEL -++# endif -++#endif -++ -++/* no typedef here because of const-pointer issues */ -++#define lzo_bytep unsigned char __LZO_MMODEL * -++#define lzo_charp char __LZO_MMODEL * -++#define lzo_voidp void __LZO_MMODEL * -++#define lzo_shortp short __LZO_MMODEL * -++#define lzo_ushortp unsigned short __LZO_MMODEL * -++#define lzo_uint32p lzo_uint32 __LZO_MMODEL * -++#define lzo_int32p lzo_int32 __LZO_MMODEL * -++#define lzo_uintp lzo_uint __LZO_MMODEL * -++#define lzo_intp lzo_int __LZO_MMODEL * -++#define lzo_xintp lzo_xint __LZO_MMODEL * -++#define lzo_voidpp lzo_voidp __LZO_MMODEL * -++#define lzo_bytepp lzo_bytep __LZO_MMODEL * -++/* deprecated - use `lzo_bytep' instead of `lzo_byte *' */ -++#define lzo_byte unsigned char __LZO_MMODEL -++ -++typedef int lzo_bool; -++ -++ -++/*********************************************************************** -++// function types -++************************************************************************/ -++ -++/* name mangling */ -++#if !defined(__LZO_EXTERN_C) -++# ifdef __cplusplus -++# define __LZO_EXTERN_C extern "C" -++# else -++# define __LZO_EXTERN_C extern -++# endif -++#endif -++ -++/* calling convention */ -++#if !defined(__LZO_CDECL) -++# define __LZO_CDECL __lzo_cdecl -++#endif -++ -++/* DLL export information */ -++#if !defined(__LZO_EXPORT1) -++# define __LZO_EXPORT1 -++#endif -++#if !defined(__LZO_EXPORT2) -++# define __LZO_EXPORT2 -++#endif -++ -++/* __cdecl calling convention for public C and assembly functions */ -++#if !defined(LZO_PUBLIC) -++# define LZO_PUBLIC(_rettype) __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL -++#endif -++#if !defined(LZO_EXTERN) -++# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype) -++#endif -++#if !defined(LZO_PRIVATE) -++# define LZO_PRIVATE(_rettype) static _rettype __LZO_CDECL -++#endif -++ -++/* function types */ -++typedef int -++(__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++typedef int -++(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++typedef int -++(__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem ); -++ -++typedef int -++(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem, -++ const lzo_bytep dict, lzo_uint dict_len ); -++ -++typedef int -++(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len, -++ lzo_bytep dst, lzo_uintp dst_len, -++ lzo_voidp wrkmem, -++ const lzo_bytep dict, lzo_uint dict_len ); -++ -++ -++/* Callback interface. Currently only the progress indicator ("nprogress") -++ * is used, but this may change in a future release. */ -++ -++struct lzo_callback_t; -++typedef struct lzo_callback_t lzo_callback_t; -++#define lzo_callback_p lzo_callback_t __LZO_MMODEL * -++ -++/* malloc & free function types */ -++typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t) -++ (lzo_callback_p self, lzo_uint items, lzo_uint size); -++typedef void (__LZO_CDECL *lzo_free_func_t) -++ (lzo_callback_p self, lzo_voidp ptr); -++ -++/* a progress indicator callback function */ -++typedef void (__LZO_CDECL *lzo_progress_func_t) -++ (lzo_callback_p, lzo_uint, lzo_uint, int); -++ -++struct lzo_callback_t -++{ -++ /* custom allocators (set to 0 to disable) */ -++ lzo_alloc_func_t nalloc; /* [not used right now] */ -++ lzo_free_func_t nfree; /* [not used right now] */ -++ -++ /* a progress indicator callback function (set to 0 to disable) */ -++ lzo_progress_func_t nprogress; -++ -++ /* NOTE: the first parameter "self" of the nalloc/nfree/nprogress -++ * callbacks points back to this struct, so you are free to store -++ * some extra info in the following variables. */ -++ lzo_voidp user1; -++ lzo_xint user2; -++ lzo_xint user3; -++}; -++ -++ -++/*********************************************************************** -++// error codes and prototypes -++************************************************************************/ -++ -++/* Error codes for the compression/decompression functions. Negative -++ * values are errors, positive values will be used for special but -++ * normal events. -++ */ -++#define LZO_E_OK 0 -++#define LZO_E_ERROR (-1) -++#define LZO_E_OUT_OF_MEMORY (-2) /* [not used right now] */ -++#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */ -++#define LZO_E_INPUT_OVERRUN (-4) -++#define LZO_E_OUTPUT_OVERRUN (-5) -++#define LZO_E_LOOKBEHIND_OVERRUN (-6) -++#define LZO_E_EOF_NOT_FOUND (-7) -++#define LZO_E_INPUT_NOT_CONSUMED (-8) -++#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */ -++ -++ -++#ifndef lzo_sizeof_dict_t -++# define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep)) -++#endif -++ -++/* lzo_init() should be the first function you call. -++ * Check the return code ! -++ * -++ * lzo_init() is a macro to allow checking that the library and the -++ * compiler's view of various types are consistent. -++ */ -++#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ -++ (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\ -++ (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ -++ (int)sizeof(lzo_callback_t)) -++LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int); -++ -++/* version functions (useful for shared libraries) */ -++LZO_EXTERN(unsigned) lzo_version(void); -++LZO_EXTERN(const char *) lzo_version_string(void); -++LZO_EXTERN(const char *) lzo_version_date(void); -++LZO_EXTERN(const lzo_charp) _lzo_version_string(void); -++LZO_EXTERN(const lzo_charp) _lzo_version_date(void); -++ -++/* string functions */ -++LZO_EXTERN(int) -++lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len); -++LZO_EXTERN(lzo_voidp) -++lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); -++LZO_EXTERN(lzo_voidp) -++lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); -++LZO_EXTERN(lzo_voidp) -++lzo_memset(lzo_voidp _s, int _c, lzo_uint _len); -++ -++/* checksum functions */ -++LZO_EXTERN(lzo_uint32) -++lzo_adler32(lzo_uint32 _adler, const lzo_bytep _buf, lzo_uint _len); -++LZO_EXTERN(lzo_uint32) -++lzo_crc32(lzo_uint32 _c, const lzo_bytep _buf, lzo_uint _len); -++LZO_EXTERN(const lzo_uint32p) -++lzo_get_crc32_table(void); -++ -++/* misc. */ -++LZO_EXTERN(int) _lzo_config_check(void); -++typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u; -++typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u; -++typedef union { void *vp; lzo_bytep bp; lzo_uint32 u32; long l; } lzo_align_t; -++ -++/* align a char pointer on a boundary that is a multiple of `size' */ -++LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size); -++#define LZO_PTR_ALIGN_UP(_ptr,_size) \ -++ ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size))) -++ -++ -++/*********************************************************************** -++// deprecated macros - only for backward compatibility with LZO v1.xx -++************************************************************************/ -++ -++#if defined(LZO_CFG_COMPAT) -++ -++#define __LZOCONF_H 1 -++ -++#if defined(LZO_ARCH_I086) -++# define __LZO_i386 1 -++#elif defined(LZO_ARCH_I386) -++# define __LZO_i386 1 -++#endif -++ -++#if defined(LZO_OS_DOS16) -++# define __LZO_DOS 1 -++# define __LZO_DOS16 1 -++#elif defined(LZO_OS_DOS32) -++# define __LZO_DOS 1 -++#elif defined(LZO_OS_WIN16) -++# define __LZO_WIN 1 -++# define __LZO_WIN16 1 -++#elif defined(LZO_OS_WIN32) -++# define __LZO_WIN 1 -++#endif -++ -++#define __LZO_CMODEL -++#define __LZO_DMODEL -++#define __LZO_ENTRY __LZO_CDECL -++#define LZO_EXTERN_CDECL LZO_EXTERN -++#define LZO_ALIGN LZO_PTR_ALIGN_UP -++ -++#define lzo_compress_asm_t lzo_compress_t -++#define lzo_decompress_asm_t lzo_decompress_t -++ -++#endif /* LZO_CFG_COMPAT */ -++ -++ -++#ifdef __cplusplus -++} /* extern "C" */ -++#endif -++ -++#endif /* already included */ -++ -++ -++/* vim:set ts=4 et: */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzodefs.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzodefs.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzodefs.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzodefs.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1545 @@ -++/* lzodefs.h -- architecture, OS and compiler specific defines -++ -++ This file is part of the LZO real-time data compression library. -++ -++ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer -++ All Rights Reserved. -++ -++ The LZO library is free software; you can redistribute it and/or -++ modify it under the terms of the GNU General Public License, -++ version 2, as published by the Free Software Foundation. -++ -++ The LZO library is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with the LZO library; see the file COPYING. -++ If not, write to the Free Software Foundation, Inc., -++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -++ -++ Markus F.X.J. Oberhumer -++ -++ http://www.oberhumer.com/opensource/lzo/ -++ */ -++ -++ -++#ifndef __LZODEFS_H_INCLUDED -++#define __LZODEFS_H_INCLUDED 1 -++ -++#if defined(__CYGWIN32__) && !defined(__CYGWIN__) -++# define __CYGWIN__ __CYGWIN32__ -++#endif -++#if defined(__IBMCPP__) && !defined(__IBMC__) -++# define __IBMC__ __IBMCPP__ -++#endif -++#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER) -++# define __INTEL_COMPILER __ICL -++#endif -++#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) -++# define _ALL_SOURCE 1 -++#endif -++#if defined(__mips__) && defined(__R5900__) -++# if !defined(__LONG_MAX__) -++# define __LONG_MAX__ 9223372036854775807L -++# endif -++#endif -++#if defined(__INTEL_COMPILER) && defined(__linux__) -++# pragma warning(disable: 193) -++#endif -++#if defined(__KEIL__) && defined(__C166__) -++# pragma warning disable = 322 -++#elif 0 && defined(__C251__) -++# pragma warning disable = 322 -++#endif -++#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) -++# if (_MSC_VER >= 1300) -++# pragma warning(disable: 4668) -++# endif -++#endif -++#if 0 && defined(__WATCOMC__) -++# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) -++# pragma warning 203 9 -++# endif -++#endif -++#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) -++# pragma option -h -++#endif -++#if 0 -++#define LZO_0xffffL 0xfffful -++#define LZO_0xffffffffL 0xfffffffful -++#else -++#define LZO_0xffffL 65535ul -++#define LZO_0xffffffffL 4294967295ul -++#endif -++#if (LZO_0xffffL == LZO_0xffffffffL) -++# error "your preprocessor is broken 1" -++#endif -++#if (16ul * 16384ul != 262144ul) -++# error "your preprocessor is broken 2" -++#endif -++#if 0 -++#if (32767 >= 4294967295ul) -++# error "your preprocessor is broken 3" -++#endif -++#if (65535u >= 4294967295ul) -++# error "your preprocessor is broken 4" -++#endif -++#endif -++#if (UINT_MAX == LZO_0xffffL) -++#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) -++# if !defined(MSDOS) -++# define MSDOS 1 -++# endif -++# if !defined(_MSDOS) -++# define _MSDOS 1 -++# endif -++#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) -++# if (__VERSION == 520) && (MB_LEN_MAX == 1) -++# if !defined(__AZTEC_C__) -++# define __AZTEC_C__ __VERSION -++# endif -++# if !defined(__DOS__) -++# define __DOS__ 1 -++# endif -++# endif -++#endif -++#endif -++#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL) -++# define ptrdiff_t long -++# define _PTRDIFF_T_DEFINED -++#endif -++#if (UINT_MAX == LZO_0xffffL) -++# undef __LZO_RENAME_A -++# undef __LZO_RENAME_B -++# if defined(__AZTEC_C__) && defined(__DOS__) -++# define __LZO_RENAME_A 1 -++# elif defined(_MSC_VER) && defined(MSDOS) -++# if (_MSC_VER < 600) -++# define __LZO_RENAME_A 1 -++# elif (_MSC_VER < 700) -++# define __LZO_RENAME_B 1 -++# endif -++# elif defined(__TSC__) && defined(__OS2__) -++# define __LZO_RENAME_A 1 -++# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) -++# define __LZO_RENAME_A 1 -++# elif defined(__PACIFIC__) && defined(DOS) -++# if !defined(__far) -++# define __far far -++# endif -++# if !defined(__near) -++# define __near near -++# endif -++# endif -++# if defined(__LZO_RENAME_A) -++# if !defined(__cdecl) -++# define __cdecl cdecl -++# endif -++# if !defined(__far) -++# define __far far -++# endif -++# if !defined(__huge) -++# define __huge huge -++# endif -++# if !defined(__near) -++# define __near near -++# endif -++# if !defined(__pascal) -++# define __pascal pascal -++# endif -++# if !defined(__huge) -++# define __huge huge -++# endif -++# elif defined(__LZO_RENAME_B) -++# if !defined(__cdecl) -++# define __cdecl _cdecl -++# endif -++# if !defined(__far) -++# define __far _far -++# endif -++# if !defined(__huge) -++# define __huge _huge -++# endif -++# if !defined(__near) -++# define __near _near -++# endif -++# if !defined(__pascal) -++# define __pascal _pascal -++# endif -++# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) -++# if !defined(__cdecl) -++# define __cdecl cdecl -++# endif -++# if !defined(__pascal) -++# define __pascal pascal -++# endif -++# endif -++# undef __LZO_RENAME_A -++# undef __LZO_RENAME_B -++#endif -++#if (UINT_MAX == LZO_0xffffL) -++#if defined(__AZTEC_C__) && defined(__DOS__) -++# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 -++#elif defined(_MSC_VER) && defined(MSDOS) -++# if (_MSC_VER < 600) -++# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 -++# endif -++# if (_MSC_VER < 700) -++# define LZO_BROKEN_INTEGRAL_PROMOTION 1 -++# define LZO_BROKEN_SIZEOF 1 -++# endif -++#elif defined(__PACIFIC__) && defined(DOS) -++# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 -++#elif defined(__TURBOC__) && defined(__MSDOS__) -++# if (__TURBOC__ < 0x0150) -++# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 -++# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 -++# define LZO_BROKEN_INTEGRAL_PROMOTION 1 -++# endif -++# if (__TURBOC__ < 0x0200) -++# define LZO_BROKEN_SIZEOF 1 -++# endif -++# if (__TURBOC__ < 0x0400) && defined(__cplusplus) -++# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 -++# endif -++#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) -++# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 -++# define LZO_BROKEN_SIZEOF 1 -++#endif -++#endif -++#if defined(__WATCOMC__) && (__WATCOMC__ < 900) -++# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 -++#endif -++#define LZO_CPP_STRINGIZE(x) #x -++#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) -++#define LZO_CPP_CONCAT2(a,b) a ## b -++#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c -++#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d -++#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e -++#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) -++#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) -++#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) -++#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) -++#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o)) -++#if 1 && defined(__cplusplus) -++# if !defined(__STDC_CONSTANT_MACROS) -++# define __STDC_CONSTANT_MACROS 1 -++# endif -++# if !defined(__STDC_LIMIT_MACROS) -++# define __STDC_LIMIT_MACROS 1 -++# endif -++#endif -++#if defined(__cplusplus) -++# define LZO_EXTERN_C extern "C" -++#else -++# define LZO_EXTERN_C extern -++#endif -++#if !defined(__LZO_OS_OVERRIDE) -++#if defined(LZO_OS_FREESTANDING) -++# define LZO_INFO_OS "freestanding" -++#elif defined(LZO_OS_EMBEDDED) -++# define LZO_INFO_OS "embedded" -++#elif defined(__CYGWIN__) && defined(__GNUC__) -++# define LZO_OS_CYGWIN 1 -++# define LZO_INFO_OS "cygwin" -++#elif defined(__EMX__) && defined(__GNUC__) -++# define LZO_OS_EMX 1 -++# define LZO_INFO_OS "emx" -++#elif defined(__BEOS__) -++# define LZO_OS_BEOS 1 -++# define LZO_INFO_OS "beos" -++#elif defined(__Lynx__) -++# define LZO_OS_LYNXOS 1 -++# define LZO_INFO_OS "lynxos" -++#elif defined(__OS400__) -++# define LZO_OS_OS400 1 -++# define LZO_INFO_OS "os400" -++#elif defined(__QNX__) -++# define LZO_OS_QNX 1 -++# define LZO_INFO_OS "qnx" -++#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) -++# define LZO_OS_DOS32 1 -++# define LZO_INFO_OS "dos32" -++#elif defined(__BORLANDC__) && defined(__DPMI16__) -++# define LZO_OS_DOS16 1 -++# define LZO_INFO_OS "dos16" -++#elif defined(__ZTC__) && defined(DOS386) -++# define LZO_OS_DOS32 1 -++# define LZO_INFO_OS "dos32" -++#elif defined(__OS2__) || defined(__OS2V2__) -++# if (UINT_MAX == LZO_0xffffL) -++# define LZO_OS_OS216 1 -++# define LZO_INFO_OS "os216" -++# elif (UINT_MAX == LZO_0xffffffffL) -++# define LZO_OS_OS2 1 -++# define LZO_INFO_OS "os2" -++# else -++# error "check your limits.h header" -++# endif -++#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) -++# define LZO_OS_WIN64 1 -++# define LZO_INFO_OS "win64" -++#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) -++# define LZO_OS_WIN32 1 -++# define LZO_INFO_OS "win32" -++#elif defined(__MWERKS__) && defined(__INTEL__) -++# define LZO_OS_WIN32 1 -++# define LZO_INFO_OS "win32" -++#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) -++# if (UINT_MAX == LZO_0xffffL) -++# define LZO_OS_WIN16 1 -++# define LZO_INFO_OS "win16" -++# elif (UINT_MAX == LZO_0xffffffffL) -++# define LZO_OS_WIN32 1 -++# define LZO_INFO_OS "win32" -++# else -++# error "check your limits.h header" -++# endif -++#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) -++# if (UINT_MAX == LZO_0xffffL) -++# define LZO_OS_DOS16 1 -++# define LZO_INFO_OS "dos16" -++# elif (UINT_MAX == LZO_0xffffffffL) -++# define LZO_OS_DOS32 1 -++# define LZO_INFO_OS "dos32" -++# else -++# error "check your limits.h header" -++# endif -++#elif defined(__WATCOMC__) -++# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) -++# define LZO_OS_DOS16 1 -++# define LZO_INFO_OS "dos16" -++# elif defined(__NT__) && (__WATCOMC__ < 1100) -++# define LZO_OS_WIN32 1 -++# define LZO_INFO_OS "win32" -++# else -++# error "please specify a target using the -bt compiler option" -++# endif -++#elif defined(__palmos__) -++# define LZO_OS_PALMOS 1 -++# define LZO_INFO_OS "palmos" -++#elif defined(__TOS__) || defined(__atarist__) -++# define LZO_OS_TOS 1 -++# define LZO_INFO_OS "tos" -++#elif defined(macintosh) && !defined(__ppc__) -++# define LZO_OS_MACCLASSIC 1 -++# define LZO_INFO_OS "macclassic" -++#elif defined(__VMS) -++# define LZO_OS_VMS 1 -++# define LZO_INFO_OS "vms" -++#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) -++# define LZO_OS_CONSOLE 1 -++# define LZO_OS_CONSOLE_PS2 1 -++# define LZO_INFO_OS "console" -++# define LZO_INFO_OS_CONSOLE "ps2" -++#elif (defined(__mips__) && defined(__psp__)) -++# define LZO_OS_CONSOLE 1 -++# define LZO_OS_CONSOLE_PSP 1 -++# define LZO_INFO_OS "console" -++# define LZO_INFO_OS_CONSOLE "psp" -++#else -++# define LZO_OS_POSIX 1 -++# define LZO_INFO_OS "posix" -++#endif -++#if (LZO_OS_POSIX) -++# if defined(_AIX) || defined(__AIX__) || defined(__aix__) -++# define LZO_OS_POSIX_AIX 1 -++# define LZO_INFO_OS_POSIX "aix" -++# elif defined(__FreeBSD__) -++# define LZO_OS_POSIX_FREEBSD 1 -++# define LZO_INFO_OS_POSIX "freebsd" -++# elif defined(__hpux__) || defined(__hpux) -++# define LZO_OS_POSIX_HPUX 1 -++# define LZO_INFO_OS_POSIX "hpux" -++# elif defined(__INTERIX) -++# define LZO_OS_POSIX_INTERIX 1 -++# define LZO_INFO_OS_POSIX "interix" -++# elif defined(__IRIX__) || defined(__irix__) -++# define LZO_OS_POSIX_IRIX 1 -++# define LZO_INFO_OS_POSIX "irix" -++# elif defined(__linux__) || defined(__linux) -++# define LZO_OS_POSIX_LINUX 1 -++# define LZO_INFO_OS_POSIX "linux" -++# elif defined(__APPLE__) || defined(__MACOS__) -++# define LZO_OS_POSIX_MACOSX 1 -++# define LZO_INFO_OS_POSIX "macosx" -++# elif defined(__NetBSD__) -++# define LZO_OS_POSIX_NETBSD 1 -++# define LZO_INFO_OS_POSIX "netbsd" -++# elif defined(__OpenBSD__) -++# define LZO_OS_POSIX_OPENBSD 1 -++# define LZO_INFO_OS_POSIX "openbsd" -++# elif defined(__osf__) -++# define LZO_OS_POSIX_OSF 1 -++# define LZO_INFO_OS_POSIX "osf" -++# elif defined(__solaris__) || defined(__sun) -++# if defined(__SVR4) || defined(__svr4__) -++# define LZO_OS_POSIX_SOLARIS 1 -++# define LZO_INFO_OS_POSIX "solaris" -++# else -++# define LZO_OS_POSIX_SUNOS 1 -++# define LZO_INFO_OS_POSIX "sunos" -++# endif -++# elif defined(__ultrix__) || defined(__ultrix) -++# define LZO_OS_POSIX_ULTRIX 1 -++# define LZO_INFO_OS_POSIX "ultrix" -++# else -++# define LZO_OS_POSIX_UNKNOWN 1 -++# define LZO_INFO_OS_POSIX "unknown" -++# endif -++#endif -++#endif -++#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) -++# if (UINT_MAX != LZO_0xffffL) -++# error "this should not happen" -++# endif -++# if (ULONG_MAX != LZO_0xffffffffL) -++# error "this should not happen" -++# endif -++#endif -++#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) -++# if (UINT_MAX != LZO_0xffffffffL) -++# error "this should not happen" -++# endif -++# if (ULONG_MAX != LZO_0xffffffffL) -++# error "this should not happen" -++# endif -++#endif -++#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) -++# define LZO_CC_CILLY 1 -++# define LZO_INFO_CC "Cilly" -++# if defined(__CILLY__) -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__CILLY__) -++# else -++# define LZO_INFO_CCVER "unknown" -++# endif -++#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) -++# define LZO_CC_SDCC 1 -++# define LZO_INFO_CC "sdcc" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(SDCC) -++#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) -++# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__) -++# define LZO_INFO_CC "Pathscale C" -++# define LZO_INFO_CCVER __PATHSCALE__ -++#elif defined(__INTEL_COMPILER) -++# define LZO_CC_INTELC 1 -++# define LZO_INFO_CC "Intel C" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__INTEL_COMPILER) -++#elif defined(__POCC__) && defined(_WIN32) -++# define LZO_CC_PELLESC 1 -++# define LZO_INFO_CC "Pelles C" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__POCC__) -++#elif defined(__llvm__) && defined(__GNUC__) && defined(__VERSION__) -++# define LZO_CC_LLVM 1 -++# define LZO_INFO_CC "llvm-gcc" -++# define LZO_INFO_CCVER __VERSION__ -++#elif defined(__GNUC__) && defined(__VERSION__) -++# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) -++# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) -++# elif defined(__GNUC_MINOR__) -++# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) -++# else -++# define LZO_CC_GNUC (__GNUC__ * 0x10000L) -++# endif -++# define LZO_INFO_CC "gcc" -++# define LZO_INFO_CCVER __VERSION__ -++#elif defined(__AZTEC_C__) -++# define LZO_CC_AZTECC 1 -++# define LZO_INFO_CC "Aztec C" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__AZTEC_C__) -++#elif defined(__BORLANDC__) -++# define LZO_CC_BORLANDC 1 -++# define LZO_INFO_CC "Borland C" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__BORLANDC__) -++#elif defined(__DMC__) && defined(__SC__) -++# define LZO_CC_DMC 1 -++# define LZO_INFO_CC "Digital Mars C" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__DMC__) -++#elif defined(__DECC) -++# define LZO_CC_DECC 1 -++# define LZO_INFO_CC "DEC C" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__DECC) -++#elif defined(__HIGHC__) -++# define LZO_CC_HIGHC 1 -++# define LZO_INFO_CC "MetaWare High C" -++# define LZO_INFO_CCVER "unknown" -++#elif defined(__IBMC__) -++# define LZO_CC_IBMC 1 -++# define LZO_INFO_CC "IBM C" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__IBMC__) -++#elif defined(__KEIL__) && defined(__C166__) -++# define LZO_CC_KEILC 1 -++# define LZO_INFO_CC "Keil C" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__C166__) -++#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) -++# define LZO_CC_LCCWIN32 1 -++# define LZO_INFO_CC "lcc-win32" -++# define LZO_INFO_CCVER "unknown" -++#elif defined(__LCC__) -++# define LZO_CC_LCC 1 -++# define LZO_INFO_CC "lcc" -++# if defined(__LCC_VERSION__) -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__LCC_VERSION__) -++# else -++# define LZO_INFO_CCVER "unknown" -++# endif -++#elif defined(_MSC_VER) -++# define LZO_CC_MSC 1 -++# define LZO_INFO_CC "Microsoft C" -++# if defined(_MSC_FULL_VER) -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(_MSC_VER) "." LZO_CPP_MACRO_EXPAND(_MSC_FULL_VER) -++# else -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(_MSC_VER) -++# endif -++#elif defined(__MWERKS__) -++# define LZO_CC_MWERKS 1 -++# define LZO_INFO_CC "Metrowerks C" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__MWERKS__) -++#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) -++# define LZO_CC_NDPC 1 -++# define LZO_INFO_CC "Microway NDP C" -++# define LZO_INFO_CCVER "unknown" -++#elif defined(__PACIFIC__) -++# define LZO_CC_PACIFICC 1 -++# define LZO_INFO_CC "Pacific C" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__PACIFIC__) -++#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) -++# define LZO_CC_PGI 1 -++# define LZO_INFO_CC "Portland Group PGI C" -++# define LZO_INFO_CCVER "unknown" -++#elif defined(__PUREC__) && defined(__TOS__) -++# define LZO_CC_PUREC 1 -++# define LZO_INFO_CC "Pure C" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__PUREC__) -++#elif defined(__SC__) && defined(__ZTC__) -++# define LZO_CC_SYMANTECC 1 -++# define LZO_INFO_CC "Symantec C" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__SC__) -++#elif defined(__SUNPRO_C) -++# define LZO_CC_SUNPROC 1 -++# define LZO_INFO_CC "Sun C" -++# define LZO_INFO_CCVER "unknown" -++#elif defined(__TINYC__) -++# define LZO_CC_TINYC 1 -++# define LZO_INFO_CC "Tiny C" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__TINYC__) -++#elif defined(__TSC__) -++# define LZO_CC_TOPSPEEDC 1 -++# define LZO_INFO_CC "TopSpeed C" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__TSC__) -++#elif defined(__WATCOMC__) -++# define LZO_CC_WATCOMC 1 -++# define LZO_INFO_CC "Watcom C" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__WATCOMC__) -++#elif defined(__TURBOC__) -++# define LZO_CC_TURBOC 1 -++# define LZO_INFO_CC "Turbo C" -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__TURBOC__) -++#elif defined(__ZTC__) -++# define LZO_CC_ZORTECHC 1 -++# define LZO_INFO_CC "Zortech C" -++# if (__ZTC__ == 0x310) -++# define LZO_INFO_CCVER "0x310" -++# else -++# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__ZTC__) -++# endif -++#else -++# define LZO_CC_UNKNOWN 1 -++# define LZO_INFO_CC "unknown" -++# define LZO_INFO_CCVER "unknown" -++#endif -++#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) -++# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" -++#endif -++#if !defined(__LZO_ARCH_OVERRIDE) -++#if defined(LZO_ARCH_GENERIC) -++# define LZO_INFO_ARCH "generic" -++#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) -++# define LZO_ARCH_I086 1 -++# define LZO_ARCH_IA16 1 -++# define LZO_INFO_ARCH "i086" -++#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) -++# define LZO_ARCH_ALPHA 1 -++# define LZO_INFO_ARCH "alpha" -++#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) -++# define LZO_ARCH_AMD64 1 -++# define LZO_INFO_ARCH "amd64" -++#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB)) -++# define LZO_ARCH_ARM 1 -++# define LZO_ARCH_ARM_THUMB 1 -++# define LZO_INFO_ARCH "arm_thumb" -++#elif defined(__arm__) || defined(_M_ARM) -++# define LZO_ARCH_ARM 1 -++# define LZO_INFO_ARCH "arm" -++#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) -++# define LZO_ARCH_AVR 1 -++# define LZO_INFO_ARCH "avr" -++#elif defined(__bfin__) -++# define LZO_ARCH_BLACKFIN 1 -++# define LZO_INFO_ARCH "blackfin" -++#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) -++# define LZO_ARCH_C166 1 -++# define LZO_INFO_ARCH "c166" -++#elif defined(__cris__) -++# define LZO_ARCH_CRIS 1 -++# define LZO_INFO_ARCH "cris" -++#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) -++# define LZO_ARCH_H8300 1 -++# define LZO_INFO_ARCH "h8300" -++#elif defined(__hppa__) || defined(__hppa) -++# define LZO_ARCH_HPPA 1 -++# define LZO_INFO_ARCH "hppa" -++#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) -++# define LZO_ARCH_I386 1 -++# define LZO_ARCH_IA32 1 -++# define LZO_INFO_ARCH "i386" -++#elif (LZO_CC_ZORTECHC && defined(__I86__)) -++# define LZO_ARCH_I386 1 -++# define LZO_ARCH_IA32 1 -++# define LZO_INFO_ARCH "i386" -++#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) -++# define LZO_ARCH_I386 1 -++# define LZO_ARCH_IA32 1 -++# define LZO_INFO_ARCH "i386" -++#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) -++# define LZO_ARCH_IA64 1 -++# define LZO_INFO_ARCH "ia64" -++#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) -++# define LZO_ARCH_M16C 1 -++# define LZO_INFO_ARCH "m16c" -++#elif defined(__m32r__) -++# define LZO_ARCH_M32R 1 -++# define LZO_INFO_ARCH "m32r" -++#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(_M_M68K) -++# define LZO_ARCH_M68K 1 -++# define LZO_INFO_ARCH "m68k" -++#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) -++# define LZO_ARCH_MCS251 1 -++# define LZO_INFO_ARCH "mcs251" -++#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) -++# define LZO_ARCH_MCS51 1 -++# define LZO_INFO_ARCH "mcs51" -++#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) -++# define LZO_ARCH_MIPS 1 -++# define LZO_INFO_ARCH "mips" -++#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) -++# define LZO_ARCH_MSP430 1 -++# define LZO_INFO_ARCH "msp430" -++#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) -++# define LZO_ARCH_POWERPC 1 -++# define LZO_INFO_ARCH "powerpc" -++#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) -++# define LZO_ARCH_S390 1 -++# define LZO_INFO_ARCH "s390" -++#elif defined(__sh__) || defined(_M_SH) -++# define LZO_ARCH_SH 1 -++# define LZO_INFO_ARCH "sh" -++#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) -++# define LZO_ARCH_SPARC 1 -++# define LZO_INFO_ARCH "sparc" -++#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) -++# define LZO_ARCH_Z80 1 -++# define LZO_INFO_ARCH "z80" -++#else -++# define LZO_ARCH_UNKNOWN 1 -++# define LZO_INFO_ARCH "unknown" -++#endif -++#endif -++#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) -++# error "FIXME - missing define for CPU architecture" -++#endif -++#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) -++# error "FIXME - missing WIN32 define for CPU architecture" -++#endif -++#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) -++# error "FIXME - missing WIN64 define for CPU architecture" -++#endif -++#if (LZO_OS_OS216 || LZO_OS_WIN16) -++# define LZO_ARCH_I086PM 1 -++# define LZO_ARCH_IA16PM 1 -++#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) -++# define LZO_ARCH_I086PM 1 -++# define LZO_ARCH_IA16PM 1 -++#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) -++# define LZO_ARCH_I086PM 1 -++# define LZO_ARCH_IA16PM 1 -++#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) -++# define LZO_ARCH_I086PM 1 -++# define LZO_ARCH_IA16PM 1 -++#endif -++#if defined(LZO_ARCH_ARM_THUMB) && !defined(LZO_ARCH_ARM) -++# error "this should not happen" -++#endif -++#if defined(LZO_ARCH_I086PM) && !defined(LZO_ARCH_I086) -++# error "this should not happen" -++#endif -++#if (LZO_ARCH_I086) -++# if (UINT_MAX != LZO_0xffffL) -++# error "this should not happen" -++# endif -++# if (ULONG_MAX != LZO_0xffffffffL) -++# error "this should not happen" -++# endif -++#endif -++#if (LZO_ARCH_I386) -++# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) -++# error "this should not happen" -++# endif -++# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) -++# error "this should not happen" -++# endif -++# if (ULONG_MAX != LZO_0xffffffffL) -++# error "this should not happen" -++# endif -++#endif -++#if !defined(__LZO_MM_OVERRIDE) -++#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) -++#if (UINT_MAX != LZO_0xffffL) -++# error "this should not happen" -++#endif -++#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) -++# define LZO_MM_TINY 1 -++#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) -++# define LZO_MM_HUGE 1 -++#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) -++# define LZO_MM_SMALL 1 -++#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) -++# define LZO_MM_MEDIUM 1 -++#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) -++# define LZO_MM_COMPACT 1 -++#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) -++# define LZO_MM_LARGE 1 -++#elif (LZO_CC_AZTECC) -++# if defined(_LARGE_CODE) && defined(_LARGE_DATA) -++# define LZO_MM_LARGE 1 -++# elif defined(_LARGE_CODE) -++# define LZO_MM_MEDIUM 1 -++# elif defined(_LARGE_DATA) -++# define LZO_MM_COMPACT 1 -++# else -++# define LZO_MM_SMALL 1 -++# endif -++#elif (LZO_CC_ZORTECHC && defined(__VCM__)) -++# define LZO_MM_LARGE 1 -++#else -++# error "unknown memory model" -++#endif -++#define LZO_HAVE_MM_HUGE_PTR 1 -++#define LZO_HAVE_MM_HUGE_ARRAY 1 -++#if (LZO_MM_TINY) -++# undef LZO_HAVE_MM_HUGE_ARRAY -++#endif -++#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) -++# undef LZO_HAVE_MM_HUGE_PTR -++# undef LZO_HAVE_MM_HUGE_ARRAY -++#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) -++# undef LZO_HAVE_MM_HUGE_ARRAY -++#elif (LZO_CC_MSC && defined(_QC)) -++# undef LZO_HAVE_MM_HUGE_ARRAY -++# if (_MSC_VER < 600) -++# undef LZO_HAVE_MM_HUGE_PTR -++# endif -++#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) -++# undef LZO_HAVE_MM_HUGE_ARRAY -++#endif -++#if (LZO_ARCH_I086PM) && !defined(LZO_HAVE_MM_HUGE_PTR) -++# if (LZO_OS_DOS16) -++# error "this should not happen" -++# elif (LZO_CC_ZORTECHC) -++# else -++# error "this should not happen" -++# endif -++#endif -++#ifdef __cplusplus -++extern "C" { -++#endif -++#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) -++ extern void __near __cdecl _AHSHIFT(void); -++# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) -++#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) -++ extern void __near __cdecl _AHSHIFT(void); -++# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) -++#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) -++ extern void __near __cdecl _AHSHIFT(void); -++# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) -++#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) -++ extern void __near __cdecl _AHSHIFT(void); -++# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) -++#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) -++# define LZO_MM_AHSHIFT 12 -++#elif (LZO_CC_WATCOMC) -++ extern unsigned char _HShift; -++# define LZO_MM_AHSHIFT ((unsigned) _HShift) -++#else -++# error "FIXME - implement LZO_MM_AHSHIFT" -++#endif -++#ifdef __cplusplus -++} -++#endif -++#elif (LZO_ARCH_C166) -++#if !defined(__MODEL__) -++# error "FIXME - C166 __MODEL__" -++#elif ((__MODEL__) == 0) -++# define LZO_MM_SMALL 1 -++#elif ((__MODEL__) == 1) -++# define LZO_MM_SMALL 1 -++#elif ((__MODEL__) == 2) -++# define LZO_MM_LARGE 1 -++#elif ((__MODEL__) == 3) -++# define LZO_MM_TINY 1 -++#elif ((__MODEL__) == 4) -++# define LZO_MM_XTINY 1 -++#elif ((__MODEL__) == 5) -++# define LZO_MM_XSMALL 1 -++#else -++# error "FIXME - C166 __MODEL__" -++#endif -++#elif (LZO_ARCH_MCS251) -++#if !defined(__MODEL__) -++# error "FIXME - MCS251 __MODEL__" -++#elif ((__MODEL__) == 0) -++# define LZO_MM_SMALL 1 -++#elif ((__MODEL__) == 2) -++# define LZO_MM_LARGE 1 -++#elif ((__MODEL__) == 3) -++# define LZO_MM_TINY 1 -++#elif ((__MODEL__) == 4) -++# define LZO_MM_XTINY 1 -++#elif ((__MODEL__) == 5) -++# define LZO_MM_XSMALL 1 -++#else -++# error "FIXME - MCS251 __MODEL__" -++#endif -++#elif (LZO_ARCH_MCS51) -++#if !defined(__MODEL__) -++# error "FIXME - MCS51 __MODEL__" -++#elif ((__MODEL__) == 1) -++# define LZO_MM_SMALL 1 -++#elif ((__MODEL__) == 2) -++# define LZO_MM_LARGE 1 -++#elif ((__MODEL__) == 3) -++# define LZO_MM_TINY 1 -++#elif ((__MODEL__) == 4) -++# define LZO_MM_XTINY 1 -++#elif ((__MODEL__) == 5) -++# define LZO_MM_XSMALL 1 -++#else -++# error "FIXME - MCS51 __MODEL__" -++#endif -++#else -++# define LZO_MM_FLAT 1 -++#endif -++#if (LZO_MM_FLAT) -++# define LZO_INFO_MM "flat" -++#elif (LZO_MM_TINY) -++# define LZO_INFO_MM "tiny" -++#elif (LZO_MM_SMALL) -++# define LZO_INFO_MM "small" -++#elif (LZO_MM_MEDIUM) -++# define LZO_INFO_MM "medium" -++#elif (LZO_MM_COMPACT) -++# define LZO_INFO_MM "compact" -++#elif (LZO_MM_LARGE) -++# define LZO_INFO_MM "large" -++#elif (LZO_MM_HUGE) -++# define LZO_INFO_MM "huge" -++#else -++# error "unknown memory model" -++#endif -++#endif -++#if defined(SIZEOF_SHORT) -++# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) -++#endif -++#if defined(SIZEOF_INT) -++# define LZO_SIZEOF_INT (SIZEOF_INT) -++#endif -++#if defined(SIZEOF_LONG) -++# define LZO_SIZEOF_LONG (SIZEOF_LONG) -++#endif -++#if defined(SIZEOF_LONG_LONG) -++# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) -++#endif -++#if defined(SIZEOF___INT16) -++# define LZO_SIZEOF___INT16 (SIZEOF___INT16) -++#endif -++#if defined(SIZEOF___INT32) -++# define LZO_SIZEOF___INT32 (SIZEOF___INT32) -++#endif -++#if defined(SIZEOF___INT64) -++# define LZO_SIZEOF___INT64 (SIZEOF___INT64) -++#endif -++#if defined(SIZEOF_VOID_P) -++# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) -++#endif -++#if defined(SIZEOF_SIZE_T) -++# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) -++#endif -++#if defined(SIZEOF_PTRDIFF_T) -++# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) -++#endif -++#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) -++#if !defined(LZO_SIZEOF_SHORT) -++# if (USHRT_MAX == LZO_0xffffL) -++# define LZO_SIZEOF_SHORT 2 -++# elif (__LZO_LSR(USHRT_MAX,7) == 1) -++# define LZO_SIZEOF_SHORT 1 -++# elif (__LZO_LSR(USHRT_MAX,15) == 1) -++# define LZO_SIZEOF_SHORT 2 -++# elif (__LZO_LSR(USHRT_MAX,31) == 1) -++# define LZO_SIZEOF_SHORT 4 -++# elif (__LZO_LSR(USHRT_MAX,63) == 1) -++# define LZO_SIZEOF_SHORT 8 -++# elif (__LZO_LSR(USHRT_MAX,127) == 1) -++# define LZO_SIZEOF_SHORT 16 -++# else -++# error "LZO_SIZEOF_SHORT" -++# endif -++#endif -++#if !defined(LZO_SIZEOF_INT) -++# if (UINT_MAX == LZO_0xffffL) -++# define LZO_SIZEOF_INT 2 -++# elif (UINT_MAX == LZO_0xffffffffL) -++# define LZO_SIZEOF_INT 4 -++# elif (__LZO_LSR(UINT_MAX,7) == 1) -++# define LZO_SIZEOF_INT 1 -++# elif (__LZO_LSR(UINT_MAX,15) == 1) -++# define LZO_SIZEOF_INT 2 -++# elif (__LZO_LSR(UINT_MAX,31) == 1) -++# define LZO_SIZEOF_INT 4 -++# elif (__LZO_LSR(UINT_MAX,63) == 1) -++# define LZO_SIZEOF_INT 8 -++# elif (__LZO_LSR(UINT_MAX,127) == 1) -++# define LZO_SIZEOF_INT 16 -++# else -++# error "LZO_SIZEOF_INT" -++# endif -++#endif -++#if !defined(LZO_SIZEOF_LONG) -++# if (ULONG_MAX == LZO_0xffffffffL) -++# define LZO_SIZEOF_LONG 4 -++# elif (__LZO_LSR(ULONG_MAX,7) == 1) -++# define LZO_SIZEOF_LONG 1 -++# elif (__LZO_LSR(ULONG_MAX,15) == 1) -++# define LZO_SIZEOF_LONG 2 -++# elif (__LZO_LSR(ULONG_MAX,31) == 1) -++# define LZO_SIZEOF_LONG 4 -++# elif (__LZO_LSR(ULONG_MAX,63) == 1) -++# define LZO_SIZEOF_LONG 8 -++# elif (__LZO_LSR(ULONG_MAX,127) == 1) -++# define LZO_SIZEOF_LONG 16 -++# else -++# error "LZO_SIZEOF_LONG" -++# endif -++#endif -++#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) -++#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) -++# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) -++# if (LZO_CC_GNUC >= 0x030300ul) -++# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0) -++# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG -++# endif -++# endif -++# endif -++#endif -++#endif -++#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) -++#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) -++#if (LZO_ARCH_I086 && LZO_CC_DMC) -++#elif (LZO_CC_CILLY) && defined(__GNUC__) -++# define LZO_SIZEOF_LONG_LONG 8 -++#elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) -++# define LZO_SIZEOF_LONG_LONG 8 -++#elif ((LZO_OS_WIN32 || LZO_OS_WIN64) && LZO_CC_MSC && (_MSC_VER >= 1400)) -++# define LZO_SIZEOF_LONG_LONG 8 -++#elif (LZO_OS_WIN64) -++# define LZO_SIZEOF___INT64 8 -++#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) -++# define LZO_SIZEOF_LONG_LONG 8 -++#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) -++# define LZO_SIZEOF_LONG_LONG 8 -++#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) -++# define LZO_SIZEOF_LONG_LONG 8 -++#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI)) -++# define LZO_SIZEOF_LONG_LONG 8 -++#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) -++# define LZO_SIZEOF___INT64 8 -++#elif (LZO_OS_WIN32 && (LZO_CC_MSC)) -++# define LZO_SIZEOF___INT64 8 -++#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) -++# define LZO_SIZEOF___INT64 8 -++#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) -++# define LZO_SIZEOF___INT64 8 -++#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64)) -++# define LZO_SIZEOF___INT64 8 -++#elif (LZO_OS_OS400) && defined(__LLP64_IFC__) -++# define LZO_SIZEOF_LONG_LONG 8 -++#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) -++# define LZO_SIZEOF_LONG_LONG 8 -++#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) -++#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -++# define LZO_SIZEOF_LONG_LONG 8 -++#endif -++#endif -++#endif -++#if defined(__cplusplus) && defined(LZO_CC_GNUC) -++# if (LZO_CC_GNUC < 0x020800ul) -++# undef LZO_SIZEOF_LONG_LONG -++# endif -++#endif -++#if defined(LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG) -++# undef LZO_SIZEOF_LONG_LONG -++#endif -++#if !defined(LZO_SIZEOF_VOID_P) -++#if (LZO_ARCH_I086) -++# define __LZO_WORDSIZE 2 -++# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) -++# define LZO_SIZEOF_VOID_P 2 -++# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) -++# define LZO_SIZEOF_VOID_P 4 -++# else -++# error "LZO_MM" -++# endif -++#elif (LZO_ARCH_AVR || LZO_ARCH_Z80) -++# define __LZO_WORDSIZE 1 -++# define LZO_SIZEOF_VOID_P 2 -++#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) -++# define LZO_SIZEOF_VOID_P 2 -++#elif (LZO_ARCH_H8300) -++# if defined(__NORMAL_MODE__) -++# define __LZO_WORDSIZE 4 -++# define LZO_SIZEOF_VOID_P 2 -++# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) -++# define __LZO_WORDSIZE 4 -++# define LZO_SIZEOF_VOID_P 4 -++# else -++# define __LZO_WORDSIZE 2 -++# define LZO_SIZEOF_VOID_P 2 -++# endif -++# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) -++# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT -++# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT -++# endif -++#elif (LZO_ARCH_M16C) -++# define __LZO_WORDSIZE 2 -++# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) -++# define LZO_SIZEOF_VOID_P 4 -++# else -++# define LZO_SIZEOF_VOID_P 2 -++# endif -++#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) -++# define __LZO_WORDSIZE 8 -++# define LZO_SIZEOF_VOID_P 4 -++#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) -++# define __LZO_WORDSIZE 8 -++# define LZO_SIZEOF_VOID_P 8 -++#elif (LZO_OS_OS400) && defined(__LLP64_IFC__) -++# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG -++# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG -++# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG -++#elif (LZO_OS_OS400) -++# define __LZO_WORDSIZE LZO_SIZEOF_LONG -++# define LZO_SIZEOF_VOID_P 16 -++# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG -++# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG -++#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) -++# define LZO_SIZEOF_VOID_P 8 -++# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG -++# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG -++#else -++# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG -++#endif -++#endif -++#if !defined(LZO_WORDSIZE) -++# if defined(__LZO_WORDSIZE) -++# define LZO_WORDSIZE __LZO_WORDSIZE -++# else -++# define LZO_WORDSIZE LZO_SIZEOF_VOID_P -++# endif -++#endif -++#if !defined(LZO_SIZEOF_SIZE_T) -++#if (LZO_ARCH_I086 || LZO_ARCH_M16C) -++# define LZO_SIZEOF_SIZE_T 2 -++#else -++# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P -++#endif -++#endif -++#if !defined(LZO_SIZEOF_PTRDIFF_T) -++#if (LZO_ARCH_I086) -++# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) -++# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P -++# elif (LZO_MM_COMPACT || LZO_MM_LARGE) -++# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) -++# define LZO_SIZEOF_PTRDIFF_T 4 -++# else -++# define LZO_SIZEOF_PTRDIFF_T 2 -++# endif -++# else -++# error "LZO_MM" -++# endif -++#else -++# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T -++#endif -++#endif -++#if !defined(LZO_ABI_BIG_ENDIAN) && !defined(LZO_ABI_LITTLE_ENDIAN) && !defined(LZO_ABI_NEUTRAL_ENDIAN) -++#if (LZO_ARCH_AMD64 || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) -++# define LZO_ABI_LITTLE_ENDIAN 1 -++#elif (LZO_ARCH_M68K || LZO_ARCH_S390) -++# define LZO_ABI_BIG_ENDIAN 1 -++#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) -++# define LZO_ABI_BIG_ENDIAN 1 -++#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) -++# define LZO_ABI_LITTLE_ENDIAN 1 -++#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) -++# define LZO_ABI_BIG_ENDIAN 1 -++#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) -++# define LZO_ABI_LITTLE_ENDIAN 1 -++#endif -++#endif -++#if defined(LZO_ABI_BIG_ENDIAN) && defined(LZO_ABI_LITTLE_ENDIAN) -++# error "this should not happen" -++#endif -++#if defined(LZO_ABI_BIG_ENDIAN) -++# define LZO_INFO_ABI_ENDIAN "be" -++#elif defined(LZO_ABI_LITTLE_ENDIAN) -++# define LZO_INFO_ABI_ENDIAN "le" -++#elif defined(LZO_ABI_NEUTRAL_ENDIAN) -++# define LZO_INFO_ABI_ENDIAN "neutral" -++#endif -++#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) -++# define LZO_ABI_I8LP16 1 -++# define LZO_INFO_ABI_PM "i8lp16" -++#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) -++# define LZO_ABI_ILP16 1 -++# define LZO_INFO_ABI_PM "ilp16" -++#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) -++# define LZO_ABI_ILP32 1 -++# define LZO_INFO_ABI_PM "ilp32" -++#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) -++# define LZO_ABI_LLP64 1 -++# define LZO_INFO_ABI_PM "llp64" -++#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) -++# define LZO_ABI_LP64 1 -++# define LZO_INFO_ABI_PM "lp64" -++#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) -++# define LZO_ABI_ILP64 1 -++# define LZO_INFO_ABI_PM "ilp64" -++#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) -++# define LZO_ABI_IP32L64 1 -++# define LZO_INFO_ABI_PM "ip32l64" -++#endif -++#if !defined(__LZO_LIBC_OVERRIDE) -++#if defined(LZO_LIBC_NAKED) -++# define LZO_INFO_LIBC "naked" -++#elif defined(LZO_LIBC_FREESTANDING) -++# define LZO_INFO_LIBC "freestanding" -++#elif defined(LZO_LIBC_MOSTLY_FREESTANDING) -++# define LZO_INFO_LIBC "mfreestanding" -++#elif defined(LZO_LIBC_ISOC90) -++# define LZO_INFO_LIBC "isoc90" -++#elif defined(LZO_LIBC_ISOC99) -++# define LZO_INFO_LIBC "isoc99" -++#elif defined(__dietlibc__) -++# define LZO_LIBC_DIETLIBC 1 -++# define LZO_INFO_LIBC "dietlibc" -++#elif defined(_NEWLIB_VERSION) -++# define LZO_LIBC_NEWLIB 1 -++# define LZO_INFO_LIBC "newlib" -++#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) -++# if defined(__UCLIBC_SUBLEVEL__) -++# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__) -++# else -++# define LZO_LIBC_UCLIBC 0x00090bL -++# endif -++# define LZO_INFO_LIBC "uclibc" -++#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) -++# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100) -++# define LZO_INFO_LIBC "glibc" -++#elif (LZO_CC_MWERKS) && defined(__MSL__) -++# define LZO_LIBC_MSL __MSL__ -++# define LZO_INFO_LIBC "msl" -++#else -++# define LZO_LIBC_DEFAULT 1 -++# define LZO_INFO_LIBC "default" -++#endif -++#endif -++#if (LZO_CC_GNUC >= 0x020800ul) -++# define __lzo_gnuc_extension__ __extension__ -++#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -++# define __lzo_gnuc_extension__ __extension__ -++#else -++# define __lzo_gnuc_extension__ -++#endif -++#if (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) -++# define lzo_alignof(e) __alignof__(e) -++#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) -++# define lzo_alignof(e) __alignof__(e) -++#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) -++# define lzo_alignof(e) __alignof(e) -++#endif -++#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) -++#elif defined(__cplusplus) -++# define __lzo_inline inline -++#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) -++# define __lzo_inline __inline -++#elif (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) -++# define __lzo_inline __inline__ -++#elif (LZO_CC_DMC) -++# define __lzo_inline __inline -++#elif (LZO_CC_INTELC) -++# define __lzo_inline __inline -++#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) -++# define __lzo_inline __inline -++#elif (LZO_CC_MSC && (_MSC_VER >= 900)) -++# define __lzo_inline __inline -++#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -++# define __lzo_inline inline -++#endif -++#if (LZO_CC_GNUC >= 0x030200ul) -++# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) -++#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && (LZO_OS_WIN32 || LZO_OS_WIN64)) -++# define __lzo_forceinline __forceinline -++#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) -++# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) -++#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -++# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) -++#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) -++# define __lzo_forceinline __forceinline -++#endif -++#if (LZO_CC_GNUC >= 0x030200ul) -++# define __lzo_noinline __attribute__((__noinline__)) -++#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && (LZO_OS_WIN32 || LZO_OS_WIN64)) -++# define __lzo_noinline __declspec(noinline) -++#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) -++# define __lzo_noinline __attribute__((__noinline__)) -++#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -++# define __lzo_noinline __attribute__((__noinline__)) -++#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) -++# define __lzo_noinline __declspec(noinline) -++#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) -++# if defined(__cplusplus) -++# else -++# define __lzo_noinline __declspec(noinline) -++# endif -++#endif -++#if (defined(__lzo_forceinline) || defined(__lzo_noinline)) && !defined(__lzo_inline) -++# error "this should not happen" -++#endif -++#if (LZO_CC_GNUC >= 0x020700ul) -++# define __lzo_noreturn __attribute__((__noreturn__)) -++#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && (LZO_OS_WIN32 || LZO_OS_WIN64)) -++# define __lzo_noreturn __declspec(noreturn) -++#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && (LZO_OS_POSIX)) -++# define __lzo_noreturn __attribute__((__noreturn__)) -++#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -++# define __lzo_noreturn __attribute__((__noreturn__)) -++#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) -++# define __lzo_noreturn __declspec(noreturn) -++#endif -++#if (LZO_CC_GNUC >= 0x030400ul) -++# define __lzo_constructor __attribute__((__constructor__,__used__)) -++#elif (LZO_CC_GNUC >= 0x020700ul) -++# define __lzo_constructor __attribute__((__constructor__)) -++#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -++# define __lzo_constructor __attribute__((__constructor__)) -++#endif -++#if (LZO_CC_GNUC >= 0x030400ul) -++# define __lzo_destructor __attribute__((__destructor__,__used__)) -++#elif (LZO_CC_GNUC >= 0x020700ul) -++# define __lzo_destructor __attribute__((__destructor__)) -++#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -++# define __lzo_destructor __attribute__((__destructor__)) -++#endif -++#if defined(__lzo_destructor) && !defined(__lzo_constructor) -++# error "this should not happen" -++#endif -++#if (LZO_CC_GNUC >= 0x030200ul) -++# define __lzo_likely(e) (__builtin_expect(!!(e),1)) -++# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) -++#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) -++# define __lzo_likely(e) (__builtin_expect(!!(e),1)) -++# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) -++#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) -++# define __lzo_likely(e) (__builtin_expect(!!(e),1)) -++# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) -++#else -++# define __lzo_likely(e) (e) -++# define __lzo_unlikely(e) (e) -++#endif -++#if !defined(LZO_UNUSED) -++# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) -++# define LZO_UNUSED(var) ((void) &var) -++# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) -++# define LZO_UNUSED(var) if (&var) ; else -++# elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) -++# define LZO_UNUSED(var) ((void) var) -++# elif (LZO_CC_MSC && (_MSC_VER < 900)) -++# define LZO_UNUSED(var) if (&var) ; else -++# elif (LZO_CC_KEILC) -++# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];} -++# elif (LZO_CC_PACIFICC) -++# define LZO_UNUSED(var) ((void) sizeof(var)) -++# elif (LZO_CC_WATCOMC) && defined(__cplusplus) -++# define LZO_UNUSED(var) ((void) var) -++# else -++# define LZO_UNUSED(var) ((void) &var) -++# endif -++#endif -++#if !defined(LZO_UNUSED_FUNC) -++# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) -++# define LZO_UNUSED_FUNC(func) ((void) func) -++# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) -++# define LZO_UNUSED_FUNC(func) if (func) ; else -++# elif (LZO_CC_LLVM) -++# define LZO_UNUSED_FUNC(func) ((void) &func) -++# elif (LZO_CC_MSC && (_MSC_VER < 900)) -++# define LZO_UNUSED_FUNC(func) if (func) ; else -++# elif (LZO_CC_MSC) -++# define LZO_UNUSED_FUNC(func) ((void) &func) -++# elif (LZO_CC_KEILC || LZO_CC_PELLESC) -++# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];} -++# else -++# define LZO_UNUSED_FUNC(func) ((void) func) -++# endif -++#endif -++#if !defined(LZO_UNUSED_LABEL) -++# if (LZO_CC_WATCOMC) && defined(__cplusplus) -++# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l -++# elif (LZO_CC_INTELC || LZO_CC_WATCOMC) -++# define LZO_UNUSED_LABEL(l) if (0) goto l -++# else -++# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l -++# endif -++#endif -++#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) -++# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) -++# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; -++# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) -++# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)]; -++# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) -++# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; -++# else -++# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)]; -++# endif -++#endif -++#if !defined(LZO_COMPILE_TIME_ASSERT) -++# if (LZO_CC_AZTECC) -++# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];} -++# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) -++# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; -++# elif (LZO_CC_MSC && (_MSC_VER < 900)) -++# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; -++# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) -++# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; -++# else -++# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];} -++# endif -++#endif -++#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) -++# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) -++# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) -++# define __lzo_cdecl __cdecl -++# define __lzo_cdecl_atexit -++# define __lzo_cdecl_main __cdecl -++# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) -++# define __lzo_cdecl_qsort __pascal -++# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) -++# define __lzo_cdecl_qsort _stdcall -++# else -++# define __lzo_cdecl_qsort __cdecl -++# endif -++# elif (LZO_CC_WATCOMC) -++# define __lzo_cdecl __cdecl -++# else -++# define __lzo_cdecl __cdecl -++# define __lzo_cdecl_atexit __cdecl -++# define __lzo_cdecl_main __cdecl -++# define __lzo_cdecl_qsort __cdecl -++# endif -++# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) -++# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) -++# define __lzo_cdecl_sighandler __pascal -++# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) -++# define __lzo_cdecl_sighandler _stdcall -++# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) -++# define __lzo_cdecl_sighandler __clrcall -++# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) -++# if defined(_DLL) -++# define __lzo_cdecl_sighandler _far _cdecl _loadds -++# elif defined(_MT) -++# define __lzo_cdecl_sighandler _far _cdecl -++# else -++# define __lzo_cdecl_sighandler _cdecl -++# endif -++# else -++# define __lzo_cdecl_sighandler __cdecl -++# endif -++#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) -++# define __lzo_cdecl cdecl -++#endif -++#if !defined(__lzo_cdecl) -++# define __lzo_cdecl -++#endif -++#if !defined(__lzo_cdecl_atexit) -++# define __lzo_cdecl_atexit -++#endif -++#if !defined(__lzo_cdecl_main) -++# define __lzo_cdecl_main -++#endif -++#if !defined(__lzo_cdecl_qsort) -++# define __lzo_cdecl_qsort -++#endif -++#if !defined(__lzo_cdecl_sighandler) -++# define __lzo_cdecl_sighandler -++#endif -++#if !defined(__lzo_cdecl_va) -++# define __lzo_cdecl_va __lzo_cdecl -++#endif -++#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) -++# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) -++# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) -++# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) -++# else -++# define LZO_HAVE_WINDOWS_H 1 -++# endif -++#endif -++#if (LZO_ARCH_ALPHA) -++# define LZO_OPT_AVOID_UINT_INDEX 1 -++# define LZO_OPT_AVOID_SHORT 1 -++# define LZO_OPT_AVOID_USHORT 1 -++#elif (LZO_ARCH_AMD64) -++# define LZO_OPT_AVOID_INT_INDEX 1 -++# define LZO_OPT_AVOID_UINT_INDEX 1 -++# define LZO_OPT_UNALIGNED16 1 -++# define LZO_OPT_UNALIGNED32 1 -++# define LZO_OPT_UNALIGNED64 1 -++#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB) -++#elif (LZO_ARCH_ARM) -++# define LZO_OPT_AVOID_SHORT 1 -++# define LZO_OPT_AVOID_USHORT 1 -++#elif (LZO_ARCH_CRIS) -++# define LZO_OPT_UNALIGNED16 1 -++# define LZO_OPT_UNALIGNED32 1 -++#elif (LZO_ARCH_I386) -++# define LZO_OPT_UNALIGNED16 1 -++# define LZO_OPT_UNALIGNED32 1 -++#elif (LZO_ARCH_IA64) -++# define LZO_OPT_AVOID_INT_INDEX 1 -++# define LZO_OPT_AVOID_UINT_INDEX 1 -++# define LZO_OPT_PREFER_POSTINC 1 -++#elif (LZO_ARCH_M68K) -++# define LZO_OPT_PREFER_POSTINC 1 -++# define LZO_OPT_PREFER_PREDEC 1 -++# if defined(__mc68020__) && !defined(__mcoldfire__) -++# define LZO_OPT_UNALIGNED16 1 -++# define LZO_OPT_UNALIGNED32 1 -++# endif -++#elif (LZO_ARCH_MIPS) -++# define LZO_OPT_AVOID_UINT_INDEX 1 -++#elif (LZO_ARCH_POWERPC) -++# define LZO_OPT_PREFER_PREINC 1 -++# define LZO_OPT_PREFER_PREDEC 1 -++# if defined(LZO_ABI_BIG_ENDIAN) -++# define LZO_OPT_UNALIGNED16 1 -++# define LZO_OPT_UNALIGNED32 1 -++# endif -++#elif (LZO_ARCH_S390) -++# define LZO_OPT_UNALIGNED16 1 -++# define LZO_OPT_UNALIGNED32 1 -++# if (LZO_SIZEOF_SIZE_T == 8) -++# define LZO_OPT_UNALIGNED64 1 -++# endif -++#elif (LZO_ARCH_SH) -++# define LZO_OPT_PREFER_POSTINC 1 -++# define LZO_OPT_PREFER_PREDEC 1 -++#endif -++#if !defined(LZO_CFG_NO_INLINE_ASM) -++#if defined(LZO_CC_LLVM) -++# define LZO_CFG_NO_INLINE_ASM 1 -++#endif -++#endif -++#if !defined(LZO_CFG_NO_UNALIGNED) -++#if defined(LZO_ABI_NEUTRAL_ENDIAN) || defined(LZO_ARCH_GENERIC) -++# define LZO_CFG_NO_UNALIGNED 1 -++#endif -++#endif -++#if defined(LZO_CFG_NO_UNALIGNED) -++# undef LZO_OPT_UNALIGNED16 -++# undef LZO_OPT_UNALIGNED32 -++# undef LZO_OPT_UNALIGNED64 -++#endif -++#if defined(LZO_CFG_NO_INLINE_ASM) -++#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) -++# define LZO_ASM_SYNTAX_MSC 1 -++#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) -++#elif (LZO_ARCH_I386 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) -++# define LZO_ASM_SYNTAX_GNUC 1 -++#elif (LZO_ARCH_AMD64 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) -++# define LZO_ASM_SYNTAX_GNUC 1 -++#endif -++#if (LZO_ASM_SYNTAX_GNUC) -++#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) -++# define __LZO_ASM_CLOBBER "ax" -++#elif (LZO_CC_INTELC) -++# define __LZO_ASM_CLOBBER "memory" -++#else -++# define __LZO_ASM_CLOBBER "cc", "memory" -++#endif -++#endif -++#if defined(__LZO_INFOSTR_MM) -++#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) -++# define __LZO_INFOSTR_MM "" -++#elif defined(LZO_INFO_MM) -++# define __LZO_INFOSTR_MM "." LZO_INFO_MM -++#else -++# define __LZO_INFOSTR_MM "" -++#endif -++#if defined(__LZO_INFOSTR_PM) -++#elif defined(LZO_INFO_ABI_PM) -++# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM -++#else -++# define __LZO_INFOSTR_PM "" -++#endif -++#if defined(__LZO_INFOSTR_ENDIAN) -++#elif defined(LZO_INFO_ABI_ENDIAN) -++# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN -++#else -++# define __LZO_INFOSTR_ENDIAN "" -++#endif -++#if defined(__LZO_INFOSTR_OSNAME) -++#elif defined(LZO_INFO_OS_CONSOLE) -++# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE -++#elif defined(LZO_INFO_OS_POSIX) -++# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX -++#else -++# define __LZO_INFOSTR_OSNAME LZO_INFO_OS -++#endif -++#if defined(__LZO_INFOSTR_LIBC) -++#elif defined(LZO_INFO_LIBC) -++# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC -++#else -++# define __LZO_INFOSTR_LIBC "" -++#endif -++#if defined(__LZO_INFOSTR_CCVER) -++#elif defined(LZO_INFO_CCVER) -++# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER -++#else -++# define __LZO_INFOSTR_CCVER "" -++#endif -++#define LZO_INFO_STRING \ -++ LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ -++ " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER -++ -++#endif /* already included */ -++ -++/* vim:set ts=4 et: */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzoutil.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzoutil.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzoutil.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/include/lzo/lzoutil.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,69 @@ -++/* lzoutil.h -- utilitiy functions for use by applications [DEPRECATED] -++ -++ This file is part of the LZO real-time data compression library. -++ -++ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer -++ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer -++ All Rights Reserved. -++ -++ The LZO library is free software; you can redistribute it and/or -++ modify it under the terms of the GNU General Public License, -++ version 2, as published by the Free Software Foundation. -++ -++ The LZO library is distributed in the hope that it will be useful, -++ but WITHOUT ANY WARRANTY; without even the implied warranty of -++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ GNU General Public License for more details. -++ -++ You should have received a copy of the GNU General Public License -++ along with the LZO library; see the file COPYING. -++ If not, write to the Free Software Foundation, Inc., -++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -++ -++ Markus F.X.J. Oberhumer -++ -++ http://www.oberhumer.com/opensource/lzo/ -++ */ -++ -++ -++#ifndef __LZOUTIL_H_INCLUDED -++#define __LZOUTIL_H_INCLUDED -++ -++#ifndef __LZOCONF_H_INCLUDED -++#include "lzoconf.h" -++#endif -++ -++#ifdef __cplusplus -++extern "C" { -++#endif -++ -++ -++/*********************************************************************** -++// LZO-v1 deprecated macros (which were used in the old example programs) -++// DO NOT USE -++************************************************************************/ -++ -++#define lzo_alloc(a,b) (malloc((a)*(b))) -++#define lzo_malloc(a) (malloc(a)) -++#define lzo_free(a) (free(a)) -++ -++#define lzo_fread(f,b,s) (fread(b,1,s,f)) -++#define lzo_fwrite(f,b,s) (fwrite(b,1,s,f)) -++ -++ -++#ifdef __cplusplus -++} /* extern "C" */ -++#endif -++ -++#endif /* already included */ -++ -++ -++/* vim:set ts=4 et: */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/lib/liblzo2.la linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/lib/liblzo2.la -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/lzo/lib/liblzo2.la 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/lzo/lib/liblzo2.la 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,35 @@ -++# liblzo2.la - a libtool library file -++# Generated by ltmain.sh - GNU libtool 1.5.6 (1.1220.2.95 2004/04/11 05:50:42) Debian: 220 $ -++# -++# Please DO NOT delete this file! -++# It is necessary for linking the library. -++ -++# The name that we can dlopen(3). -++dlname='liblzo2.so.2' -++ -++# Names of this library. -++library_names='liblzo2.so.2.0.0 liblzo2.so.2 liblzo2.so' -++ -++# The name of the static archive. -++old_library='liblzo2.a' -++ -++# Libraries that this one depends upon. -++dependency_libs='' -++ -++# Version information for liblzo2. -++current=2 -++age=0 -++revision=0 -++ -++# Is this an already installed library? -++installed=yes -++ -++# Should we warn about portability when linking against -modules? -++shouldnotlink=no -++ -++# Files to dlopen/dlpreopen -++dlopen='' -++dlpreopen='' -++ -++# Directory that this library needs to be installed in: -++libdir='/home/yrtan/lzo/lib' -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/mkfs.ubifs.c linux-2.6.24.7/fs/ubifs/mkfs.ubifs/mkfs.ubifs.c -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/mkfs.ubifs.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/mkfs.ubifs.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,2163 @@ -++/* -++ * Copyright (C) 2008 Nokia Corporation. -++ * Copyright (C) 2008 University of Szeged, Hungary -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Adrian Hunter -++ * Artem Bityutskiy -++ * Zoltan Sogor -++ */ -++ -++#include "mkfs.ubifs.h" -++ -++#define PROGRAM_VERSION "0.6" -++ -++/* Size (prime number) of hash table for link counting */ -++#define HASH_TABLE_SIZE 10099 -++ -++/* The node buffer must allow for worst case compression */ -++#define NODE_BUFFER_SIZE (UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE * 4) -++ -++/* Default time granularity in nanoseconds */ -++#define DEFAULT_TIME_GRAN 1000000000 -++ -++/* UBI EC and VID header sizes - used when calculating LEB size from PRB size */ -++#define UBI_EC_HDR_SIZE 64 -++#define UBI_VID_HDR_SIZE 64 -++ -++/** -++ * struct idx_entry - index entry. -++ * @next: next index entry (NULL at end of list) -++ * @prev: previous index entry (NULL at beginning of list) -++ * @key: key -++ * @name: directory entry name used for sorting colliding keys by name -++ * @lnum: LEB number -++ * @offs: offset -++ * @len: length -++ * -++ * The index is recorded as a linked list which is sorted and used to create -++ * the bottom level of the on-flash index tree. The remaining levels of the -++ * index tree are each built from the level below. -++ */ -++struct idx_entry { -++ struct idx_entry *next; -++ struct idx_entry *prev; -++ union ubifs_key key; -++ char *name; -++ int lnum; -++ int offs; -++ int len; -++}; -++ -++/** -++ * struct inum_mapping - inode number mapping for link counting. -++ * @next: next inum_mapping (NULL at end of list) -++ * @prev: previous inum_mapping (NULL at beginning of list) -++ * @dev: source device on which the source inode number resides -++ * @inum: source inode number of the file -++ * @use_inum: target inode number of the file -++ * @use_nlink: number of links -++ * @path_name: a path name of the file -++ * @st: struct stat object containing inode attributes which have to be used -++ * when the inode is being created (actually only UID, GID, access -++ * mode, major and minor device numbers) -++ * -++ * If a file has more than one hard link, then the number of hard links that -++ * exist in the source directory hierarchy must be counted to exclude the -++ * possibility that the file is linked from outside the source directory -++ * hierarchy. -++ * -++ * The inum_mappings are stored in a hash_table of linked lists. -++ */ -++struct inum_mapping { -++ struct inum_mapping *next; -++ struct inum_mapping *prev; -++ dev_t dev; -++ ino_t inum; -++ ino_t use_inum; -++ unsigned int use_nlink; -++ char *path_name; -++ struct stat st; -++}; -++ -++/* -++ * Because we copy functions from the kernel, we use a subset of the UBIFS -++ * file-system description object struct ubifs_info. -++ */ -++static struct ubifs_info info_, *c = &info_; -++ -++/* Debug levels are: 0 (none), 1 (statistics), 2 (files) ,3 (more details) */ -++int debug_level; -++int verbose; -++ -++static char *root; -++static int root_len; -++static struct stat root_st; -++static char *output; -++static int out_fd; -++static int squash_owner; -++ -++/* The 'head' (position) which nodes are written */ -++static int head_lnum; -++static int head_offs; -++static int head_flags; -++ -++/* The index list */ -++static struct idx_entry *idx_list_first; -++static struct idx_entry *idx_list_last; -++static size_t idx_cnt; -++ -++/* Global buffers */ -++static void *leb_buf; -++static void *node_buf; -++static void *block_buf; -++ -++/* Hash table for inode link counting */ -++static struct inum_mapping **hash_table; -++ -++/* Inode creation sequence number */ -++static unsigned long long creat_sqnum; -++ -++static const char *optstring = "d:r:m:o:D:h?vVe:c:g:f:P:k:x:j:l:j:U"; -++ -++static const struct option longopts[] = { -++ {"root", 1, NULL, 'r'}, -++ {"min-io-size", 1, NULL, 'm'}, -++ {"leb-size", 1, NULL, 'e'}, -++ {"max-leb-cnt", 1, NULL, 'c'}, -++ {"output", 1, NULL, 'o'}, -++ {"devtable", 1, NULL, 'D'}, -++ {"help", 0, NULL, 'h'}, -++ {"verbose", 0, NULL, 'v'}, -++ {"version", 0, NULL, 'V'}, -++ {"debug-level", 1, NULL, 'g'}, -++ {"jrn-size", 1, NULL, 'j'}, -++ {"compr", 1, NULL, 'x'}, -++ {"fanout", 1, NULL, 'f'}, -++ {"keyhash", 1, NULL, 'k'}, -++ {"log-lebs", 1, NULL, 'l'}, -++ {"orph-lebs", 1, NULL, 'p'}, -++ {"squash-uids" , 0, NULL, 'U'}, -++ {NULL, 0, NULL, 0} -++}; -++ -++static const char *helptext = -++"Usage: mkfs.ubifs [OPTIONS]\n" -++"Make a UBIFS file system image from an existing directory tree\n\n" -++"Options:\n" -++"-r, -d, --root=DIR build file system from directory DIR\n" -++"-m, --min-io-size=SIZE minimum I/O unit size\n" -++"-e, --leb-size=SIZE logical erase block size\n" -++"-c, --max-leb-cnt=COUNT maximum logical erase block count\n" -++"-o, --output=FILE output to FILE\n" -++"-j, --jrn-size=SIZE journal size\n" -++"-x, --compr=TYPE compression type - \"lzo\", \"zlib\" or \"none\"\n" -++" (default: \"lzo\")\n" -++"-f, --fanout=NUM fanout NUM (default: 8)\n" -++"-k, --keyhash=TYPE key hash type - \"r5\" or \"test\" (default: \"r5\")\n" -++"-l, --log-lebs=COUNT count of erase blocks for the log\n" -++"-p, --orph-lebs=COUNT count of erase blocks for orphans (default: 1)\n" -++"-D, --devtable=FILE use device table FILE\n" -++"-U, --squash-uids squash owners making all files owned by root\n" -++"-v, --verbose verbose operation\n" -++"-V, --version display version information\n" -++"-g, --debug=LEVEL display debug information (0 - none, 1 - statistics,\n" -++" 2 - files, 3 - more details)\n" -++"-h, --help display this help text\n\n" -++"Note, SIZE is specified in bytes, but it may also be specified in Kilobytes,\n" -++"Megabytes, and Gigabytes if a KiB, MiB, or GiB suffix is used.\n"; -++ -++/** -++ * make_path - make a path name from a directory and a name. -++ * @dir: directory path name -++ * @name: name -++ */ -++static char *make_path(const char *dir, const char *name) -++{ -++ char *s; -++ -++ s = malloc(strlen(dir) + strlen(name) + 2); -++ if (!s) -++ return NULL; -++ strcpy(s, dir); -++ if (dir[strlen(dir) - 1] != '/') -++ strcat(s, "/"); -++ strcat(s, name); -++ return s; -++} -++ -++/** -++ * same_dir - determine if two file descriptors refer to the same directory. -++ * @fd1: file descriptor 1 -++ * @fd2: file descriptor 2 -++ */ -++static int same_dir(int fd1, int fd2) -++{ -++ struct stat stat1, stat2; -++ -++ if (fstat(fd1, &stat1) == -1) -++ return -1; -++ if (fstat(fd2, &stat2) == -1) -++ return -1; -++ return stat1.st_dev == stat2.st_dev && stat1.st_ino == stat2.st_ino; -++} -++ -++/** -++ * do_openat - open a file in a directory. -++ * @fd: file descriptor of open directory -++ * @path: path relative to directory -++ * @flags: open flags -++ * -++ * This function is provided because the library function openat is sometimes -++ * not available. -++ */ -++static int do_openat(int fd, const char *path, int flags) -++{ -++ int ret; -++ char *cwd; -++ -++ cwd = getcwd(NULL, 0); -++ if (!cwd) -++ return -1; -++ ret = fchdir(fd); -++ if (ret != -1) -++ ret = open(path, flags); -++ chdir(cwd); -++ free(cwd); -++ return ret; -++} -++ -++/** -++ * in_path - determine if a file is beneath a directory. -++ * @dir_name: directory path name -++ * @file_name: file path name -++ */ -++static int in_path(const char *dir_name, const char *file_name) -++{ -++ char *fn = strdup(file_name); -++ char *dn; -++ int fd1, fd2, fd3, ret = -1, top_fd; -++ -++ if (!fn) -++ return -1; -++ top_fd = open("/", O_RDONLY); -++ if (top_fd != -1) { -++ dn = dirname(fn); -++ fd1 = open(dir_name, O_RDONLY); -++ if (fd1 != -1) { -++ fd2 = open(dn, O_RDONLY); -++ if (fd2 != -1) { -++ while (1) { -++ int same; -++ -++ same = same_dir(fd1, fd2); -++ if (same) { -++ ret = same; -++ break; -++ } -++ if (same_dir(fd2, top_fd)) { -++ ret = 0; -++ break; -++ } -++ fd3 = do_openat(fd2, "..", O_RDONLY); -++ if (fd3 == -1) -++ break; -++ close(fd2); -++ fd2 = fd3; -++ } -++ close(fd2); -++ } -++ close(fd1); -++ } -++ close(top_fd); -++ } -++ free(fn); -++ return ret; -++} -++ -++/** -++ * calc_min_log_lebs - calculate the minimum number of log LEBs needed. -++ * @max_bud_bytes: journal size (buds only) -++ */ -++static int calc_min_log_lebs(unsigned long long max_bud_bytes) -++{ -++ int buds, log_lebs; -++ unsigned long long log_size; -++ -++ buds = (max_bud_bytes + c->leb_size - 1) / c->leb_size; -++ log_size = ALIGN(UBIFS_REF_NODE_SZ, c->min_io_size); -++ log_size *= buds; -++ log_size += ALIGN(UBIFS_CS_NODE_SZ + -++ UBIFS_REF_NODE_SZ * (c->jhead_cnt + 2), -++ c->min_io_size); -++ log_lebs = (log_size + c->leb_size - 1) / c->leb_size; -++ log_lebs += 1; -++ return log_lebs; -++} -++ -++static inline int is_power_of_2(unsigned long long n) -++{ -++ return (n != 0 && ((n & (n - 1)) == 0)); -++} -++ -++static int validate_options(void) -++{ -++ int tmp; -++ -++ if (!root) -++ return err_msg("root directory was not specified"); -++ if (!output) -++ return err_msg("no output file specified"); -++ if (in_path(root, output)) -++ return err_msg("output file cannot be in the UBIFS root " -++ "directory"); -++ if (!is_power_of_2(c->min_io_size)) -++ return err_msg("min. I/O unit size should be power of 2"); -++ if (c->leb_size < c->min_io_size) -++ return err_msg("min. I/O unit cannot be larger than LEB size"); -++ if (c->leb_size < UBIFS_MIN_LEB_SZ) -++ return err_msg("too smal LEB size %d, minimum is %d", -++ c->min_io_size, UBIFS_MIN_LEB_SZ); -++ if (c->leb_size % c->min_io_size) -++ return err_msg("LEB should be multiple of min. I/O units"); -++ if (c->leb_size % 8) -++ return err_msg("LEB size has to be multiple of 8"); -++ if (c->leb_size > 1024*1024) -++ return err_msg("too large LEB size %d", c->leb_size); -++ if (c->max_leb_cnt < UBIFS_MIN_LEB_CNT) -++ return err_msg("too low max. count of LEBs, minimum is %d", -++ UBIFS_MIN_LEB_CNT); -++ if (c->fanout < UBIFS_MIN_FANOUT) -++ return err_msg("too low fanout, minimum is %d", -++ UBIFS_MIN_FANOUT); -++ tmp = c->leb_size - UBIFS_IDX_NODE_SZ; -++ tmp /= UBIFS_BRANCH_SZ + UBIFS_MAX_KEY_LEN; -++ if (c->fanout > tmp) -++ return err_msg("too high fanout, maximum is %d", tmp); -++ if (c->log_lebs < UBIFS_MIN_LOG_LEBS) -++ return err_msg("too few log LEBs, minimum is %d", -++ UBIFS_MIN_LOG_LEBS); -++ if (c->log_lebs >= c->max_leb_cnt - UBIFS_MIN_LEB_CNT) -++ return err_msg("too many log LEBs, maximum is %d", -++ c->max_leb_cnt - UBIFS_MIN_LEB_CNT); -++ if (c->orph_lebs < UBIFS_MIN_ORPH_LEBS) -++ return err_msg("too few orphan LEBs, minimum is %d", -++ UBIFS_MIN_ORPH_LEBS); -++ if (c->orph_lebs >= c->max_leb_cnt - UBIFS_MIN_LEB_CNT) -++ return err_msg("too many orphan LEBs, maximum is %d", -++ c->max_leb_cnt - UBIFS_MIN_LEB_CNT); -++ tmp = UBIFS_SB_LEBS + UBIFS_MST_LEBS + c->log_lebs + c->lpt_lebs; -++ tmp += c->orph_lebs + 4; -++ if (tmp > c->max_leb_cnt) -++ return err_msg("too low max. count of LEBs, expected at " -++ "least %d", tmp); -++ tmp = calc_min_log_lebs(c->max_bud_bytes); -++ if (c->log_lebs < calc_min_log_lebs(c->max_bud_bytes)) -++ return err_msg("too few log LEBs, expected at least %d", -++ tmp); -++ return 0; -++} -++ -++/** -++ * get_multiplier - convert size specifier to an integer multiplier. -++ * @str: the size specifier string -++ * -++ * This function parses the @str size specifier, which may be one of -++ * 'KiB', 'MiB', or 'GiB' into an integer multiplier. Returns positive -++ * size multiplier in case of success and %-1 in case of failure. -++ */ -++static int get_multiplier(const char *str) -++{ -++ if (!str) -++ return 1; -++ -++ /* Remove spaces before the specifier */ -++ while (*str == ' ' || *str == '\t') -++ str += 1; -++ -++ if (!strcmp(str, "KiB")) -++ return 1024; -++ if (!strcmp(str, "MiB")) -++ return 1024 * 1024; -++ if (!strcmp(str, "GiB")) -++ return 1024 * 1024 * 1024; -++ -++ return -1; -++} -++ -++/** -++ * get_bytes - convert a string containing amount of bytes into an -++ * integer. -++ * @str: string to convert -++ * -++ * This function parses @str which may have one of 'KiB', 'MiB', or 'GiB' size -++ * specifiers. Returns positive amount of bytes in case of success and %-1 in -++ * case of failure. -++ */ -++static long long get_bytes(const char *str) -++{ -++ char *endp; -++ long long bytes = strtoull(str, &endp, 0); -++ -++ if (endp == str || bytes < 0) -++ return err_msg("incorrect amount of bytes: \"%s\"", str); -++ -++ if (*endp != '\0') { -++ int mult = get_multiplier(endp); -++ -++ if (mult == -1) -++ return err_msg("bad size specifier: \"%s\" - " -++ "should be 'KiB', 'MiB' or 'GiB'", endp); -++ bytes *= mult; -++ } -++ -++ return bytes; -++} -++ -++static int get_options(int argc, char**argv) -++{ -++ int opt, i; -++ const char *tbl_file = NULL; -++ struct stat st; -++ char *endp; -++ -++ c->fanout = 8; -++ c->orph_lebs = 1; -++ c->key_hash = key_r5_hash; -++ c->key_len = UBIFS_SK_LEN; -++ c->default_compr = UBIFS_COMPR_LZO; -++ c->lsave_cnt = 256; -++ c->leb_size = -1; -++ c->min_io_size = -1; -++ c->max_bud_bytes = -1; -++ c->log_lebs = -1; -++ -++ while (1) { -++ opt = getopt_long(argc, argv, optstring, longopts, &i); -++ if (opt == -1) -++ break; -++ switch (opt) { -++ case 'r': -++ case 'd': -++ root_len = strlen(optarg); -++ root = malloc(root_len + 2); -++ if (!root) -++ return err_msg("cannot allocate memory"); -++ -++ /* -++ * The further code expects '/' at the end of the root -++ * UBIFS directory on the host. -++ */ -++ memcpy(root, optarg, root_len); -++ if (root[root_len - 1] != '/') -++ root[root_len++] = '/'; -++ root[root_len] = 0; -++ -++ /* Make sure the root directory exists */ -++ if (stat(root, &st)) -++ return sys_err_msg("bad root directory '%s'", -++ root); -++ break; -++ case 'm': -++ c->min_io_size = get_bytes(optarg); -++ if (c->min_io_size <= 0) -++ return err_msg("bad min. I/O size"); -++ break; -++ case 'e': -++ c->leb_size = get_bytes(optarg); -++ if (c->leb_size <= 0) -++ return err_msg("bad LEB size"); -++ break; -++ case 'c': -++ c->max_leb_cnt = get_bytes(optarg); -++ if (c->max_leb_cnt <= 0) -++ return err_msg("bad maximum LEB count"); -++ break; -++ case 'o': -++ output = strdup(optarg); -++ break; -++ case 'D': -++ tbl_file = optarg; -++ if (stat(tbl_file, &st) < 0) -++ return sys_err_msg("bad device table file '%s'", -++ tbl_file); -++ break; -++ case 'h': -++ case '?': -++ printf(helptext); -++ exit(0); -++ case 'v': -++ verbose = 1; -++ break; -++ case 'V': -++ printf("Version " PROGRAM_VERSION "\n"); -++ exit(0); -++ case 'g': -++ debug_level = strtol(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || -++ debug_level < 0 || debug_level > 3) -++ return err_msg("bad debugging level '%s'", -++ optarg); -++ break; -++ case 'f': -++ c->fanout = strtol(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || c->fanout <= 0) -++ return err_msg("bad fanout %s", optarg); -++ break; -++ case 'l': -++ c->log_lebs = strtol(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || c->log_lebs <= 0) -++ return err_msg("bad count of log LEBs '%s'", -++ optarg); -++ break; -++ case 'p': -++ c->orph_lebs = strtol(optarg, &endp, 0); -++ if (*endp != '\0' || endp == optarg || -++ c->orph_lebs <= 0) -++ return err_msg("bad orphan LEB count '%s'", -++ optarg); -++ break; -++ case 'k': -++ if (strcmp(optarg, "r5") == 0) { -++ c->key_hash = key_r5_hash; -++ c->key_hash_type = UBIFS_KEY_HASH_R5; -++ } else if (strcmp(optarg, "test") == 0) { -++ c->key_hash = key_test_hash; -++ c->key_hash_type = UBIFS_KEY_HASH_TEST; -++ } else -++ return err_msg("bad key hash"); -++ break; -++ case 'x': -++ if (strcmp(optarg, "lzo") == 0) -++ c->default_compr = UBIFS_COMPR_LZO; -++ else if (strcmp(optarg, "zlib") == 0) -++ c->default_compr = UBIFS_COMPR_ZLIB; -++ else if (strcmp(optarg, "none") == 0) -++ c->default_compr = UBIFS_COMPR_NONE; -++ else -++ return err_msg("bad compressor name"); -++ break; -++ case 'j': -++ c->max_bud_bytes = get_bytes(optarg); -++ if (c->max_bud_bytes <= 0) -++ return err_msg("bad maximum amount of buds"); -++ break; -++ case 'U': -++ squash_owner = 1; -++ break; -++ } -++ } -++ -++ if (c->min_io_size == -1) -++ return err_msg("min. I/O unit was not specified " -++ "(use -h for help)"); -++ -++ if (c->leb_size == -1) -++ return err_msg("LEB size was not specified (use -h for help)"); -++ -++ if (c->max_bud_bytes == -1) { -++ int lebs; -++ -++ lebs = c->max_leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS; -++ lebs -= c->orph_lebs; -++ if (c->log_lebs) -++ lebs -= c->log_lebs; -++ else -++ lebs -= UBIFS_MIN_LOG_LEBS; -++ if (c->lpt_lebs) -++ lebs -= c->lpt_lebs; -++ else -++ lebs -= UBIFS_MIN_LPT_LEBS; -++ /* Make the journal about 12.5% of main area lebs */ -++ c->max_bud_bytes = (lebs / 8) * (long long)c->leb_size; -++ /* Make the max journal size 8MiB */ -++ if (c->max_bud_bytes > 8 * 1024 * 1024) -++ c->max_bud_bytes = 8 * 1024 * 1024; -++ if (c->max_bud_bytes < 4 * c->leb_size) -++ c->max_bud_bytes = 4 * c->leb_size; -++ } -++ -++ if (c->log_lebs == -1) { -++ c->log_lebs = calc_min_log_lebs(c->max_bud_bytes); -++ c->log_lebs += 2; -++ } -++ -++ if (verbose) { -++ printf("mkfs.ubifs\n"); -++ printf("\troot: %s\n", root); -++ printf("\tmin_io_size: %d\n", c->min_io_size); -++ printf("\tleb_size: %d\n", c->leb_size); -++ printf("\tmax_leb_cnt: %d\n", c->max_leb_cnt); -++ printf("\toutput: %s\n", output); -++ printf("\tjrn_size: %llu\n", c->max_bud_bytes); -++ switch (c->default_compr) { -++ case UBIFS_COMPR_LZO: -++ printf("\tcompr: lzo\n"); -++ break; -++ case UBIFS_COMPR_ZLIB: -++ printf("\tcompr: zlib\n"); -++ break; -++ case UBIFS_COMPR_NONE: -++ printf("\tcompr: none\n"); -++ break; -++ } -++ printf("\tkeyhash: %s\n", (c->key_hash == key_r5_hash) ? -++ "r5" : "test"); -++ printf("\tfanout: %d\n", c->fanout); -++ printf("\torph_lebs: %d\n", c->orph_lebs); -++ } -++ -++ if (c->min_io_size < 8) -++ c->min_io_size = 8; -++ -++ if (validate_options()) -++ return -1; -++ -++ if (tbl_file && parse_devtable(root, tbl_file)) -++ return err_msg("cannot parse device table file '%s'", tbl_file); -++ -++ return 0; -++} -++ -++/** -++ * prepare_node - fill in the common header. -++ * @node: node -++ * @len: node length -++ */ -++static void prepare_node(void *node, int len) -++{ -++ uint32_t crc; -++ struct ubifs_ch *ch = node; -++ -++ ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC); -++ ch->len = cpu_to_le32(len); -++ ch->group_type = UBIFS_NO_NODE_GROUP; -++ ch->sqnum = cpu_to_le64(++c->max_sqnum); -++ ch->padding[0] = ch->padding[1] = 0; -++ crc = crc32(UBIFS_CRC32_INIT, node + 8, len - 8); -++ ch->crc = cpu_to_le32(crc); -++} -++ -++/** -++ * write_leb - copy the image of a LEB to the output file. -++ * @lnum: LEB number -++ * @len: length of data in the buffer -++ * @buf: buffer (must be at least c->leb_size bytes) -++ */ -++int write_leb(int lnum, int len, void *buf) -++{ -++ off64_t pos = (off64_t)lnum * c->leb_size; -++ -++ dbg_msg(3, "LEB %d len %d", lnum, len); -++ if (lseek64(out_fd, pos, SEEK_SET) != pos) -++ return sys_err_msg("lseek64 failed seeking %lld", pos); -++ -++ memset(buf + len, 0xff, c->leb_size - len); -++ -++ if (write(out_fd, buf, c->leb_size) != c->leb_size) -++ return sys_err_msg("write failed writing %d bytes at pos %lld", -++ c->leb_size, pos); -++ -++ return 0; -++} -++ -++/** -++ * write_empty_leb - copy the image of an empty LEB to the output file. -++ * @lnum: LEB number -++ */ -++static int write_empty_leb(int lnum) -++{ -++ return write_leb(lnum, 0, leb_buf); -++} -++ -++/** -++ * do_pad - pad a buffer to the minimum I/O size. -++ * @buf: buffer -++ * @len: buffer length -++ */ -++static int do_pad(void *buf, int len) -++{ -++ int pad_len, alen = ALIGN(len, 8), wlen = ALIGN(alen, c->min_io_size); -++ uint32_t crc; -++ -++ memset(buf + len, 0xff, alen - len); -++ pad_len = wlen - alen; -++ dbg_msg(3, "len %d pad_len %d", len, pad_len); -++ buf += alen; -++ if (pad_len >= UBIFS_PAD_NODE_SZ) { -++ struct ubifs_ch *ch = buf; -++ struct ubifs_pad_node *pad_node = buf; -++ -++ ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC); -++ ch->node_type = UBIFS_PAD_NODE; -++ ch->group_type = UBIFS_NO_NODE_GROUP; -++ ch->padding[0] = ch->padding[1] = 0; -++ ch->sqnum = cpu_to_le64(0); -++ ch->len = cpu_to_le32(UBIFS_PAD_NODE_SZ); -++ -++ pad_len -= UBIFS_PAD_NODE_SZ; -++ pad_node->pad_len = cpu_to_le32(pad_len); -++ -++ crc = crc32(UBIFS_CRC32_INIT, buf + 8, UBIFS_PAD_NODE_SZ - 8); -++ ch->crc = cpu_to_le32(crc); -++ -++ memset(buf + UBIFS_PAD_NODE_SZ, 0, pad_len); -++ } else if (pad_len > 0) -++ memset(buf, UBIFS_PADDING_BYTE, pad_len); -++ -++ return wlen; -++} -++ -++/** -++ * write_node - write a node to a LEB. -++ * @node: node -++ * @len: node length -++ * @lnum: LEB number -++ */ -++static int write_node(void *node, int len, int lnum) -++{ -++ prepare_node(node, len); -++ -++ memcpy(leb_buf, node, len); -++ -++ len = do_pad(leb_buf, len); -++ -++ return write_leb(lnum, len, leb_buf); -++} -++ -++/** -++ * calc_dark - calculate LEB dark space size. -++ * @c: the UBIFS file-system description object -++ * @spc: amount of free and dirty space in the LEB -++ * -++ * This function calculates amount of dark space in an LEB which has @spc bytes -++ * of free and dirty space. Returns the calculations result. -++ * -++ * Dark space is the space which is not always usable - it depends on which -++ * nodes are written in which order. E.g., if an LEB has only 512 free bytes, -++ * it is dark space, because it cannot fit a large data node. So UBIFS cannot -++ * count on this LEB and treat these 512 bytes as usable because it is not true -++ * if, for example, only big chunks of uncompressible data will be written to -++ * the FS. -++ */ -++static int calc_dark(struct ubifs_info *c, int spc) -++{ -++ if (spc < c->dark_wm) -++ return spc; -++ -++ /* -++ * If we have slightly more space then the dark space watermark, we can -++ * anyway safely assume it we'll be able to write a node of the -++ * smallest size there. -++ */ -++ if (spc - c->dark_wm < MIN_WRITE_SZ) -++ return spc - MIN_WRITE_SZ; -++ -++ return c->dark_wm; -++} -++ -++/** -++ * set_lprops - set the LEB property values for a LEB. -++ * @lnum: LEB number -++ * @offs: end offset of data in the LEB -++ * @flags: LEB property flags -++ */ -++static void set_lprops(int lnum, int offs, int flags) -++{ -++ int i = lnum - c->main_first, free, dirty; -++ int a = max_t(int, c->min_io_size, 8); -++ -++ free = c->leb_size - ALIGN(offs, a); -++ dirty = c->leb_size - free - ALIGN(offs, 8); -++ dbg_msg(3, "LEB %d free %d dirty %d flags %d", lnum, free, dirty, -++ flags); -++ c->lpt[i].free = free; -++ c->lpt[i].dirty = dirty; -++ c->lpt[i].flags = flags; -++ c->lst.total_free += free; -++ c->lst.total_dirty += dirty; -++ if (flags & LPROPS_INDEX) -++ c->lst.idx_lebs += 1; -++ else { -++ int spc; -++ -++ spc = free + dirty; -++ if (spc < c->dead_wm) -++ c->lst.total_dead += spc; -++ else -++ c->lst.total_dark += calc_dark(c, spc); -++ c->lst.total_used += c->leb_size - spc; -++ } -++} -++ -++/** -++ * add_to_index - add a node key and position to the index. -++ * @key: node key -++ * @lnum: node LEB number -++ * @offs: node offset -++ * @len: node length -++ */ -++static int add_to_index(union ubifs_key *key, char *name, int lnum, int offs, -++ int len) -++{ -++ struct idx_entry *e; -++ -++ dbg_msg(3, "LEB %d offs %d len %d", lnum, offs, len); -++ e = malloc(sizeof(struct idx_entry)); -++ if (!e) -++ return err_msg("out of memory"); -++ e->next = NULL; -++ e->prev = idx_list_last; -++ e->key = *key; -++ e->name = name; -++ e->lnum = lnum; -++ e->offs = offs; -++ e->len = len; -++ if (!idx_list_first) -++ idx_list_first = e; -++ if (idx_list_last) -++ idx_list_last->next = e; -++ idx_list_last = e; -++ idx_cnt += 1; -++ return 0; -++} -++ -++/** -++ * flush_nodes - write the current head and move the head to the next LEB. -++ */ -++static int flush_nodes(void) -++{ -++ int len, err; -++ -++ if (!head_offs) -++ return 0; -++ len = do_pad(leb_buf, head_offs); -++ err = write_leb(head_lnum, len, leb_buf); -++ if (err) -++ return err; -++ set_lprops(head_lnum, head_offs, head_flags); -++ head_lnum += 1; -++ head_offs = 0; -++ return 0; -++} -++ -++/** -++ * reserve_space - reserve space for a node on the head. -++ * @len: node length -++ * @lnum: LEB number is returned here -++ * @offs: offset is returned here -++ */ -++static int reserve_space(int len, int *lnum, int *offs) -++{ -++ int err; -++ -++ if (len > c->leb_size - head_offs) { -++ err = flush_nodes(); -++ if (err) -++ return err; -++ } -++ *lnum = head_lnum; -++ *offs = head_offs; -++ head_offs += ALIGN(len, 8); -++ return 0; -++} -++ -++/** -++ * add_node - write a node to the head. -++ * @key: node key -++ * @node: node -++ * @len: node length -++ */ -++static int add_node(union ubifs_key *key, char *name, void *node, int len) -++{ -++ int err, lnum, offs; -++ -++ prepare_node(node, len); -++ -++ err = reserve_space(len, &lnum, &offs); -++ if (err) -++ return err; -++ -++ memcpy(leb_buf + offs, node, len); -++ memset(leb_buf + offs + len, 0xff, ALIGN(len, 8) - len); -++ -++ add_to_index(key, name, lnum, offs, len); -++ -++ return 0; -++} -++ -++/** -++ * add_inode_with_data - write an inode. -++ * @st: stat information of source inode -++ * @inum: target inode number -++ * @data: inode data (for special inodes e.g. symlink path etc) -++ * @data_len: inode data length -++ * @flags: source inode flags -++ */ -++static int add_inode_with_data(struct stat *st, ino_t inum, void *data, -++ unsigned int data_len, int flags) -++{ -++ struct ubifs_ino_node *ino = node_buf; -++ union ubifs_key key; -++ int len, use_flags = 0; -++ -++ if (c->default_compr != UBIFS_COMPR_NONE) -++ use_flags |= UBIFS_COMPR_FL; -++ if (flags & FS_COMPR_FL) -++ use_flags |= UBIFS_COMPR_FL; -++ if (flags & FS_SYNC_FL) -++ use_flags |= UBIFS_SYNC_FL; -++ if (flags & FS_IMMUTABLE_FL) -++ use_flags |= UBIFS_IMMUTABLE_FL; -++ if (flags & FS_APPEND_FL) -++ use_flags |= UBIFS_APPEND_FL; -++ if (flags & FS_DIRSYNC_FL && S_ISDIR(st->st_mode)) -++ use_flags |= UBIFS_DIRSYNC_FL; -++ -++ memset(ino, 0, UBIFS_INO_NODE_SZ); -++ -++ ino_key_init(c, &key, inum); -++ ino->ch.node_type = UBIFS_INO_NODE; -++ key_write(c, &key, &ino->key); -++ ino->creat_sqnum = cpu_to_le64(creat_sqnum); -++ ino->size = cpu_to_le64(st->st_size); -++ ino->nlink = cpu_to_le32(st->st_nlink); -++ /* -++ * The time fields are updated assuming the default time granularity -++ * of 1 second. To support finer granularities, utime() would be needed. -++ */ -++ ino->atime_sec = cpu_to_le64(st->st_atime); -++ ino->ctime_sec = cpu_to_le64(st->st_ctime); -++ ino->mtime_sec = cpu_to_le64(st->st_mtime); -++ ino->atime_nsec = 0; -++ ino->ctime_nsec = 0; -++ ino->mtime_nsec = 0; -++ ino->uid = cpu_to_le32(st->st_uid); -++ ino->gid = cpu_to_le32(st->st_gid); -++ ino->uid = cpu_to_le32(st->st_uid); -++ ino->gid = cpu_to_le32(st->st_gid); -++ ino->mode = cpu_to_le32(st->st_mode); -++ ino->flags = cpu_to_le32(use_flags); -++ ino->data_len = cpu_to_le32(data_len); -++ ino->compr_type = cpu_to_le16(c->default_compr); -++ if (data_len) -++ memcpy(&ino->data, data, data_len); -++ -++ len = UBIFS_INO_NODE_SZ + data_len; -++ -++ return add_node(&key, NULL, ino, len); -++} -++ -++/** -++ * add_inode - write an inode. -++ * @st: stat information of source inode -++ * @inum: target inode number -++ * @flags: source inode flags -++ */ -++static int add_inode(struct stat *st, ino_t inum, int flags) -++{ -++ return add_inode_with_data(st, inum, NULL, 0, flags); -++} -++ -++/** -++ * add_dir_inode - write an inode for a directory. -++ * @dir: source directory -++ * @inum: target inode number -++ * @size: target directory size -++ * @nlink: target directory link count -++ * @st: struct stat object describing attributes (except size and nlink) of the -++ * target inode to create -++ * -++ * Note, this function may be called with %NULL @dir, when the directory which -++ * is being created does not exist at the host file system, but is defined by -++ * the device table. -++ */ -++static int add_dir_inode(DIR *dir, ino_t inum, loff_t size, unsigned int nlink, -++ struct stat *st) -++{ -++ int fd, flags = 0; -++ -++ st->st_size = size; -++ st->st_nlink = nlink; -++ -++ if (dir) { -++ fd = dirfd(dir); -++ if (fd == -1) -++ return sys_err_msg("dirfd failed"); -++ if (ioctl(fd, FS_IOC_GETFLAGS, &flags) == -1) -++ flags = 0; -++ } -++ -++ return add_inode(st, inum, flags); -++} -++ -++/** -++ * add_dev_inode - write an inode for a character or block device. -++ * @st: stat information of source inode -++ * @inum: target inode number -++ * @flags: source inode flags -++ */ -++static int add_dev_inode(struct stat *st, ino_t inum, int flags) -++{ -++ union ubifs_dev_desc dev; -++ -++ dev.huge = cpu_to_le64(makedev(major(st->st_rdev), minor(st->st_rdev))); -++ return add_inode_with_data(st, inum, &dev, 8, flags); -++} -++ -++/** -++ * add_symlink_inode - write an inode for a symbolic link. -++ * @path_name: path name of symbolic link inode itself (not the link target) -++ * @st: stat information of source inode -++ * @inum: target inode number -++ * @flags: source inode flags -++ */ -++static int add_symlink_inode(const char *path_name, struct stat *st, ino_t inum, -++ int flags) -++{ -++ char buf[UBIFS_MAX_INO_DATA + 2]; -++ ssize_t len; -++ -++ /* Take the symlink as is */ -++ len = readlink(path_name, buf, UBIFS_MAX_INO_DATA + 1); -++ if (len <= 0) -++ return sys_err_msg("readlink failed for %s", path_name); -++ if (len > UBIFS_MAX_INO_DATA) -++ return err_msg("symlink too long for %s", path_name); -++ -++ return add_inode_with_data(st, inum, buf, len, flags); -++} -++ -++/** -++ * add_dent_node - write a directory entry node. -++ * @dir_inum: target inode number of directory -++ * @name: directory entry name -++ * @inum: target inode number of the directory entry -++ * @type: type of the target inode -++ */ -++static int add_dent_node(ino_t dir_inum, const char *name, ino_t inum, -++ unsigned char type) -++{ -++ struct ubifs_dent_node *dent = node_buf; -++ union ubifs_key key; -++ struct qstr dname; -++ char *kname; -++ int len; -++ -++ dbg_msg(3, "%s ino %lu type %u dir ino %lu", name, inum, -++ (unsigned)type, dir_inum); -++ memset(dent, 0, UBIFS_DENT_NODE_SZ); -++ -++ dname.name = (void *)name; -++ dname.len = strlen(name); -++ -++ dent->ch.node_type = UBIFS_DENT_NODE; -++ -++ dent_key_init(c, &key, dir_inum, &dname); -++ key_write(c, &key, dent->key); -++ dent->inum = cpu_to_le64(inum); -++ dent->padding1 = 0; -++ dent->type = type; -++ dent->nlen = cpu_to_le16(dname.len); -++ memcpy(dent->name, dname.name, dname.len); -++ dent->name[dname.len] = '\0'; -++ -++ len = UBIFS_DENT_NODE_SZ + dname.len + 1; -++ -++ kname = strdup(name); -++ if (!kname) -++ return err_msg("cannot allocate memory"); -++ -++ return add_node(&key, kname, dent, len); -++} -++ -++/** -++ * lookup_inum_mapping - add an inode mapping for link counting. -++ * @dev: source device on which source inode number resides -++ * @inum: source inode number -++ */ -++static struct inum_mapping *lookup_inum_mapping(dev_t dev, ino_t inum) -++{ -++ struct inum_mapping *im; -++ unsigned int k; -++ -++ k = inum % HASH_TABLE_SIZE; -++ im = hash_table[k]; -++ while (im) { -++ if (im->dev == dev && im->inum == inum) -++ return im; -++ im = im->next; -++ } -++ im = malloc(sizeof(struct inum_mapping)); -++ if (!im) -++ return NULL; -++ im->next = hash_table[k]; -++ im->prev = NULL; -++ im->dev = dev; -++ im->inum = inum; -++ im->use_inum = 0; -++ im->use_nlink = 0; -++ if (hash_table[k]) -++ hash_table[k]->prev = im; -++ hash_table[k] = im; -++ return im; -++} -++ -++/** -++ * all_zero - does a buffer contain only zero bytes. -++ * @buf: buffer -++ * @len: buffer length -++ */ -++static int all_zero(void *buf, int len) -++{ -++ unsigned char *p = buf; -++ -++ while (len--) -++ if (*p++ != 0) -++ return 0; -++ return 1; -++} -++ -++/** -++ * add_file - write the data of a file and its inode to the output file. -++ * @path_name: source path name -++ * @st: source inode stat information -++ * @inum: target inode number -++ * @flags: source inode flags -++ */ -++static int add_file(const char *path_name, struct stat *st, ino_t inum, -++ int flags) -++{ -++ struct ubifs_data_node *dn = node_buf; -++ void *buf = block_buf; -++ loff_t file_size = 0; -++ ssize_t ret, bytes_read; -++ union ubifs_key key; -++ int fd, dn_len, err, compr_type, use_compr; -++ unsigned int block_no = 0; -++ size_t out_len; -++ -++ fd = open(path_name, O_RDONLY | O_LARGEFILE); -++ if (fd == -1) -++ return sys_err_msg("failed to open file '%s'", path_name); -++ do { -++ /* Read next block */ -++ bytes_read = 0; -++ do { -++ ret = read(fd, buf + bytes_read, -++ UBIFS_BLOCK_SIZE - bytes_read); -++ if (ret == -1) { -++ sys_err_msg("failed to read file '%s'", -++ path_name); -++ close(fd); -++ return 1; -++ } -++ bytes_read += ret; -++ } while (ret != 0 && bytes_read != UBIFS_BLOCK_SIZE); -++ if (bytes_read == 0) -++ break; -++ file_size += bytes_read; -++ /* Skip holes */ -++ if (all_zero(buf, bytes_read)) { -++ block_no += 1; -++ continue; -++ } -++ /* Make data node */ -++ memset(dn, 0, UBIFS_DATA_NODE_SZ); -++ data_key_init(c, &key, inum, block_no++); -++ dn->ch.node_type = UBIFS_DATA_NODE; -++ key_write(c, &key, &dn->key); -++ dn->size = cpu_to_le32(bytes_read); -++ out_len = NODE_BUFFER_SIZE - UBIFS_DATA_NODE_SZ; -++ if (c->default_compr == UBIFS_COMPR_NONE && -++ (flags & FS_COMPR_FL)) -++ use_compr = UBIFS_COMPR_LZO; -++ else -++ use_compr = c->default_compr; -++ compr_type = compress_data(buf, bytes_read, &dn->data, -++ &out_len, use_compr); -++ dn->compr_type = cpu_to_le16(compr_type); -++ dn_len = UBIFS_DATA_NODE_SZ + out_len; -++ /* Add data node to file system */ -++ err = add_node(&key, NULL, dn, dn_len); -++ if (err) { -++ close(fd); -++ return err; -++ } -++ } while (ret != 0); -++ if (close(fd) == -1) -++ return sys_err_msg("failed to close file '%s'", path_name); -++ if (file_size != st->st_size) -++ return err_msg("file size changed during writing file '%s'", -++ path_name); -++ return add_inode(st, inum, flags); -++} -++ -++/** -++ * add_non_dir - write a non-directory to the output file. -++ * @path_name: source path name -++ * @inum: target inode number is passed and returned here (due to link counting) -++ * @nlink: number of links if known otherwise zero -++ * @type: UBIFS inode type is returned here -++ * @st: struct stat object containing inode attributes which should be use when -++ * creating the UBIFS inode -++ */ -++static int add_non_dir(const char *path_name, ino_t *inum, unsigned int nlink, -++ unsigned char *type, struct stat *st) -++{ -++ int fd, flags = 0; -++ -++ dbg_msg(2, "%s", path_name); -++ -++ if (S_ISREG(st->st_mode)) { -++ fd = open(path_name, O_RDONLY); -++ if (fd == -1) -++ return sys_err_msg("failed to open file '%s'", -++ path_name); -++ if (ioctl(fd, FS_IOC_GETFLAGS, &flags) == -1) -++ flags = 0; -++ if (close(fd) == -1) -++ return sys_err_msg("failed to close file '%s'", -++ path_name); -++ *type = UBIFS_ITYPE_REG; -++ } else if (S_ISCHR(st->st_mode)) -++ *type = UBIFS_ITYPE_CHR; -++ else if (S_ISBLK(st->st_mode)) -++ *type = UBIFS_ITYPE_BLK; -++ else if (S_ISLNK(st->st_mode)) -++ *type = UBIFS_ITYPE_LNK; -++ else if (S_ISSOCK(st->st_mode)) -++ *type = UBIFS_ITYPE_SOCK; -++ else if (S_ISFIFO(st->st_mode)) -++ *type = UBIFS_ITYPE_FIFO; -++ else -++ return err_msg("file '%s' has unknown inode type", path_name); -++ -++ if (nlink) -++ st->st_nlink = nlink; -++ else if (st->st_nlink > 1) { -++ /* -++ * If the number of links is greater than 1, then add this file -++ * later when we know the number of links that we actually have. -++ * For now, we just put the inode mapping in the hash table. -++ */ -++ struct inum_mapping *im; -++ -++ im = lookup_inum_mapping(st->st_dev, st->st_ino); -++ if (!im) -++ return err_msg("out of memory"); -++ if (im->use_nlink == 0) { -++ /* New entry */ -++ im->use_inum = *inum; -++ im->use_nlink = 1; -++ im->path_name = malloc(strlen(path_name) + 1); -++ if (!im->path_name) -++ return err_msg("out of memory"); -++ strcpy(im->path_name, path_name); -++ } else { -++ /* Existing entry */ -++ *inum = im->use_inum; -++ im->use_nlink += 1; -++ /* Return unused inode number */ -++ c->highest_inum -= 1; -++ } -++ -++ memcpy(&im->st, st, sizeof(struct stat)); -++ return 0; -++ } else -++ st->st_nlink = 1; -++ -++ creat_sqnum = ++c->max_sqnum; -++ -++ if (S_ISREG(st->st_mode)) -++ return add_file(path_name, st, *inum, flags); -++ if (S_ISCHR(st->st_mode)) -++ return add_dev_inode(st, *inum, flags); -++ if (S_ISBLK(st->st_mode)) -++ return add_dev_inode(st, *inum, flags); -++ if (S_ISLNK(st->st_mode)) -++ return add_symlink_inode(path_name, st, *inum, flags); -++ if (S_ISSOCK(st->st_mode)) -++ return add_inode(st, *inum, flags); -++ if (S_ISFIFO(st->st_mode)) -++ return add_inode(st, *inum, flags); -++ -++ return err_msg("file '%s' has unknown inode type", path_name); -++} -++ -++/** -++ * add_directory - write a directory tree to the output file. -++ * @dir_name: directory path name -++ * @dir_inum: UBIFS inode number of directory -++ * @st: directory inode statistics -++ * @non_existing: non-zero if this function is called for a directory which -++ * does not exist on the host file-system and it is being -++ * created because it is defined in the device table file. -++ */ -++static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st, -++ int non_existing) -++{ -++ struct dirent *entry; -++ DIR *dir = NULL; -++ int err = 0; -++ loff_t size = UBIFS_INO_NODE_SZ; -++ char *name = NULL; -++ unsigned int nlink = 2; -++ struct path_htbl_element *ph_elt; -++ struct name_htbl_element *nh_elt = NULL; -++ struct hashtable_itr *itr; -++ ino_t inum; -++ unsigned char type; -++ unsigned long long dir_creat_sqnum = ++c->max_sqnum; -++ -++ dbg_msg(2, "%s", dir_name); -++ if (!non_existing) { -++ dir = opendir(dir_name); -++ if (dir == NULL) -++ return sys_err_msg("cannot open directory '%s'", -++ dir_name); -++ } -++ -++ /* -++ * Check whether this directory contains files which should be -++ * added/changed because they were specified in the device table. -++ * @ph_elt will be non-zero if yes. -++ */ -++ ph_elt = devtbl_find_path(dir_name + root_len - 1); -++ -++ /* -++ * Before adding the directory itself, we have to iterate over all the -++ * entries the device table adds to this directory and create them. -++ */ -++ for (; !non_existing;) { -++ struct stat dent_st; -++ -++ errno = 0; -++ entry = readdir(dir); -++ if (!entry) { -++ if (errno == 0) -++ break; -++ sys_err_msg("error reading directory '%s'", dir_name); -++ err = -1; -++ break; -++ } -++ -++ if (strcmp(".", entry->d_name) == 0) -++ continue; -++ if (strcmp("..", entry->d_name) == 0) -++ continue; -++ -++ if (ph_elt) -++ /* -++ * This directory was referred to at the device table -++ * file. Check if this directory entry is referred at -++ * too. -++ */ -++ nh_elt = devtbl_find_name(ph_elt, entry->d_name); -++ -++ /* -++ * We are going to create the file corresponding to this -++ * directory entry (@entry->d_name). We use 'struct stat' -++ * object to pass information about file attributes (actually -++ * only about UID, GID, mode, major, and minor). Get attributes -++ * for this file from the UBIFS rootfs on the host. -++ */ -++ free(name); -++ name = make_path(dir_name, entry->d_name); -++ if (lstat(name, &dent_st) == -1) { -++ sys_err_msg("lstat failed for file '%s'", name); -++ goto out_free; -++ } -++ -++ if (squash_owner) -++ /* -++ * Squash UID/GID. But the device table may override -++ * this. -++ */ -++ dent_st.st_uid = dent_st.st_gid = 0; -++ -++ /* -++ * And if the device table describes the same file, override -++ * the attributes. However, this is not allowed for device node -++ * files. -++ */ -++ if (nh_elt && override_attributes(&dent_st, ph_elt, nh_elt)) -++ goto out_free; -++ -++ inum = ++c->highest_inum; -++ -++ if (S_ISDIR(dent_st.st_mode)) { -++ err = add_directory(name, inum, &dent_st, 0); -++ if (err) -++ goto out_free; -++ nlink += 1; -++ type = UBIFS_ITYPE_DIR; -++ } else { -++ err = add_non_dir(name, &inum, 0, &type, &dent_st); -++ if (err) -++ goto out_free; -++ } -++ -++ err = add_dent_node(dir_inum, entry->d_name, inum, type); -++ if (err) -++ goto out_free; -++ size += ALIGN(UBIFS_DENT_NODE_SZ + strlen(entry->d_name) + 1, -++ 8); -++ } -++ -++ /* -++ * OK, we have created all files in this directory (recursively), let's -++ * also create all files described in the device table. All t -++ */ -++ nh_elt = first_name_htbl_element(ph_elt, &itr); -++ while (nh_elt) { -++ struct stat fake_st; -++ -++ /* -++ * We prohibit creating regular files using the device table, -++ * the device table may only re-define attributes of regular -++ * files. -++ */ -++ if (S_ISREG(nh_elt->mode)) { -++ err_msg("Bad device table entry %s/%s - it is " -++ "prohibited to create regular files " -++ "via device table", -++ strcmp(ph_elt->path, "/") ? ph_elt->path : "", -++ nh_elt->name); -++ goto out_free; -++ } -++ -++ memcpy(&fake_st, &root_st, sizeof(struct stat)); -++ fake_st.st_uid = nh_elt->uid; -++ fake_st.st_uid = nh_elt->uid; -++ fake_st.st_mode = nh_elt->mode; -++ fake_st.st_rdev = nh_elt->dev; -++ fake_st.st_nlink = 1; -++ -++ free(name); -++ name = make_path(dir_name, nh_elt->name); -++ inum = ++c->highest_inum; -++ -++ if (S_ISDIR(nh_elt->mode)) { -++ err = add_directory(name, inum, &fake_st, 1); -++ if (err) -++ goto out_free; -++ nlink += 1; -++ type = UBIFS_ITYPE_DIR; -++ } else { -++ err = add_non_dir(name, &inum, 0, &type, &fake_st); -++ if (err) -++ goto out_free; -++ } -++ -++ err = add_dent_node(dir_inum, nh_elt->name, inum, type); -++ if (err) -++ goto out_free; -++ size += ALIGN(UBIFS_DENT_NODE_SZ + strlen(nh_elt->name) + 1, 8); -++ -++ nh_elt = next_name_htbl_element(ph_elt, &itr); -++ } -++ -++ creat_sqnum = dir_creat_sqnum; -++ -++ err = add_dir_inode(dir, dir_inum, size, nlink, st); -++ if (err) -++ goto out_free; -++ -++ free(name); -++ if (!non_existing && closedir(dir) == -1) -++ return sys_err_msg("error closing directory '%s'", dir_name); -++ -++ return 0; -++ -++out_free: -++ free(name); -++ if (!non_existing) -++ closedir(dir); -++ return -1; -++} -++ -++/** -++ * add_multi_linked_files - write all the files for which we counted links. -++ */ -++static int add_multi_linked_files(void) -++{ -++ int i, err; -++ -++ for (i = 0; i < HASH_TABLE_SIZE; i++) { -++ struct inum_mapping *im; -++ unsigned char type = 0; -++ -++ for (im = hash_table[i]; im; im = im->next) { -++ dbg_msg(2, "%s", im->path_name); -++ err = add_non_dir(im->path_name, &im->use_inum, -++ im->use_nlink, &type, &im->st); -++ if (err) -++ return err; -++ } -++ } -++ return 0; -++} -++ -++/** -++ * write_data - write the files and directories. -++ */ -++static int write_data(void) -++{ -++ int err; -++ -++ err = stat(root, &root_st); -++ if (err) -++ return sys_err_msg("bad root file-system directory '%s'", root); -++ root_st.st_uid = root_st.st_gid = 0; -++ root_st.st_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO; -++ -++ head_flags = 0; -++ err = add_directory(root, UBIFS_ROOT_INO, &root_st, 0); -++ if (err) -++ return err; -++ err = add_multi_linked_files(); -++ if (err) -++ return err; -++ return flush_nodes(); -++} -++ -++static int namecmp(const char *name1, const char *name2) -++{ -++ size_t len1 = strlen(name1), len2 = strlen(name2); -++ size_t clen = (len1 < len2) ? len1 : len2; -++ int cmp; -++ -++ cmp = memcmp(name1, name2, clen); -++ if (cmp) -++ return cmp; -++ return (len1 < len2) ? -1 : 1; -++} -++ -++static int cmp_idx(const void *a, const void *b) -++{ -++ const struct idx_entry *e1 = *(const struct idx_entry **)a; -++ const struct idx_entry *e2 = *(const struct idx_entry **)b; -++ int cmp; -++ -++ cmp = keys_cmp(c, &e1->key, &e2->key); -++ if (cmp) -++ return cmp; -++ return namecmp(e1->name, e2->name); -++} -++ -++/** -++ * add_idx_node - write an index node to the head. -++ * @node: index node -++ * @child_cnt: number of children of this index node -++ */ -++static int add_idx_node(void *node, int child_cnt) -++{ -++ int err, lnum, offs, len; -++ -++ len = ubifs_idx_node_sz(c, child_cnt); -++ -++ prepare_node(node, len); -++ -++ err = reserve_space(len, &lnum, &offs); -++ if (err) -++ return err; -++ -++ memcpy(leb_buf + offs, node, len); -++ memset(leb_buf + offs + len, 0xff, ALIGN(len, 8) - len); -++ -++ c->old_idx_sz += ALIGN(len, 8); -++ -++ dbg_msg(3, "at %d:%d len %d index size %llu", lnum, offs, len, -++ c->old_idx_sz); -++ -++ /* The last index node written will be the root */ -++ c->zroot.lnum = lnum; -++ c->zroot.offs = offs; -++ c->zroot.len = len; -++ -++ return 0; -++} -++ -++/** -++ * write_index - write out the index. -++ */ -++static int write_index(void) -++{ -++ size_t sz, i, cnt, idx_sz, pstep, bcnt; -++ struct idx_entry **idx_ptr, **p; -++ struct ubifs_idx_node *idx; -++ struct ubifs_branch *br; -++ int child_cnt, j, level, blnum, boffs, blen, blast_len, err; -++ -++ dbg_msg(1, "leaf node count: %d", idx_cnt); -++ -++ /* Reset the head for the index */ -++ head_flags = LPROPS_INDEX; -++ /* Allocate index node */ -++ idx_sz = ubifs_idx_node_sz(c, c->fanout); -++ idx = malloc(idx_sz); -++ if (!idx) -++ return err_msg("out of memory"); -++ /* Make an array of pointers to sort the index list */ -++ sz = idx_cnt * sizeof(struct idx_entry *); -++ if (sz / sizeof(struct idx_entry *) != idx_cnt) { -++ free(idx); -++ return err_msg("index is too big (%zu entries)", idx_cnt); -++ } -++ idx_ptr = malloc(sz); -++ if (!idx_ptr) { -++ free(idx); -++ return err_msg("out of memory - needed %zu bytes for index", -++ sz); -++ } -++ idx_ptr[0] = idx_list_first; -++ for (i = 1; i < idx_cnt; i++) -++ idx_ptr[i] = idx_ptr[i - 1]->next; -++ qsort(idx_ptr, idx_cnt, sizeof(struct idx_entry *), cmp_idx); -++ /* Write level 0 index nodes */ -++ cnt = idx_cnt / c->fanout; -++ if (idx_cnt % c->fanout) -++ cnt += 1; -++ p = idx_ptr; -++ blnum = head_lnum; -++ boffs = head_offs; -++ for (i = 0; i < cnt; i++) { -++ /* -++ * Calculate the child count. All index nodes are created full -++ * except for the last index node on each row. -++ */ -++ if (i == cnt - 1) { -++ child_cnt = idx_cnt % c->fanout; -++ if (child_cnt == 0) -++ child_cnt = c->fanout; -++ } else -++ child_cnt = c->fanout; -++ memset(idx, 0, idx_sz); -++ idx->ch.node_type = UBIFS_IDX_NODE; -++ idx->child_cnt = cpu_to_le16(child_cnt); -++ idx->level = cpu_to_le16(0); -++ for (j = 0; j < child_cnt; j++, p++) { -++ br = ubifs_idx_branch(c, idx, j); -++ key_write_idx(c, &(*p)->key, &br->key); -++ br->lnum = cpu_to_le32((*p)->lnum); -++ br->offs = cpu_to_le32((*p)->offs); -++ br->len = cpu_to_le32((*p)->len); -++ } -++ add_idx_node(idx, child_cnt); -++ } -++ /* Write level 1 index nodes and above */ -++ level = 0; -++ pstep = 1; -++ while (cnt > 1) { -++ /* -++ * 'blast_len' is the length of the last index node in the level -++ * below. -++ */ -++ blast_len = ubifs_idx_node_sz(c, child_cnt); -++ /* 'bcnt' is the number of index nodes in the level below */ -++ bcnt = cnt; -++ /* 'cnt' is the number of index nodes in this level */ -++ cnt = (cnt + c->fanout - 1) / c->fanout; -++ if (cnt == 0) -++ cnt = 1; -++ level += 1; -++ /* -++ * The key of an index node is the same as the key of its first -++ * child. Thus we can get the key by stepping along the bottom -++ * level 'p' with an increasing large step 'pstep'. -++ */ -++ p = idx_ptr; -++ pstep *= c->fanout; -++ for (i = 0; i < cnt; i++) { -++ /* -++ * Calculate the child count. All index nodes are -++ * created full except for the last index node on each -++ * row. -++ */ -++ if (i == cnt - 1) { -++ child_cnt = bcnt % c->fanout; -++ if (child_cnt == 0) -++ child_cnt = c->fanout; -++ } else -++ child_cnt = c->fanout; -++ memset(idx, 0, idx_sz); -++ idx->ch.node_type = UBIFS_IDX_NODE; -++ idx->child_cnt = cpu_to_le16(child_cnt); -++ idx->level = cpu_to_le16(level); -++ for (j = 0; j < child_cnt; j++) { -++ size_t bn = i * c->fanout + j; -++ -++ /* -++ * The length of the index node in the level -++ * below is 'idx_sz' except when it is the last -++ * node on the row. i.e. all the others on the -++ * row are full. -++ */ -++ if (bn == bcnt - 1) -++ blen = blast_len; -++ else -++ blen = idx_sz; -++ /* -++ * 'blnum' and 'boffs' hold the position of the -++ * index node on the level below. -++ */ -++ if (boffs + blen > c->leb_size) { -++ blnum += 1; -++ boffs = 0; -++ } -++ /* -++ * Fill in the branch with the key and position -++ * of the index node from the level below. -++ */ -++ br = ubifs_idx_branch(c, idx, j); -++ key_write_idx(c, &(*p)->key, &br->key); -++ br->lnum = cpu_to_le32(blnum); -++ br->offs = cpu_to_le32(boffs); -++ br->len = cpu_to_le32(blen); -++ /* -++ * Step to the next index node on the level -++ * below. -++ */ -++ boffs += ALIGN(blen, 8); -++ p += pstep; -++ } -++ add_idx_node(idx, child_cnt); -++ } -++ } -++ -++ /* Free stuff */ -++ for (i = 0; i < idx_cnt; i++) -++ free(idx_ptr[i]); -++ free(idx_ptr); -++ free(idx); -++ -++ dbg_msg(1, "zroot is at %d:%d len %d", c->zroot.lnum, c->zroot.offs, -++ c->zroot.len); -++ -++ /* Set the index head */ -++ c->ihead_lnum = head_lnum; -++ c->ihead_offs = ALIGN(head_offs, c->min_io_size); -++ dbg_msg(1, "ihead is at %d:%d", c->ihead_lnum, c->ihead_offs); -++ -++ /* Flush the last index LEB */ -++ err = flush_nodes(); -++ if (err) -++ return err; -++ -++ return 0; -++} -++ -++/** -++ * set_gc_lnum - set the LEB number reserved for the garbage collector. -++ */ -++static int set_gc_lnum(void) -++{ -++ int err; -++ -++ c->gc_lnum = head_lnum++; -++ err = write_empty_leb(c->gc_lnum); -++ if (err) -++ return err; -++ set_lprops(c->gc_lnum, 0, 0); -++ c->lst.empty_lebs += 1; -++ return 0; -++} -++ -++/** -++ * finalize_leb_cnt - now that we know how many LEBs we used. -++ */ -++static int finalize_leb_cnt(void) -++{ -++ c->leb_cnt = head_lnum; -++ if (c->leb_cnt > c->max_leb_cnt) -++ /* TODO: in this case it segfaults because buffer overruns - we -++ * somewhere allocate smaller buffers - fix */ -++ return err_msg("max_leb_cnt too low (%d needed)", c->leb_cnt); -++ c->main_lebs = c->leb_cnt - c->main_first; -++ if (verbose) { -++ printf("\tsuper lebs: %d\n", UBIFS_SB_LEBS); -++ printf("\tmaster lebs: %d\n", UBIFS_MST_LEBS); -++ printf("\tlog_lebs: %d\n", c->log_lebs); -++ printf("\tlpt_lebs: %d\n", c->lpt_lebs); -++ printf("\torph_lebs: %d\n", c->orph_lebs); -++ printf("\tmain_lebs: %d\n", c->main_lebs); -++ printf("\tgc lebs: %d\n", 1); -++ printf("\tindex lebs: %d\n", c->lst.idx_lebs); -++ printf("\tleb_cnt: %d\n", c->leb_cnt); -++ } -++ dbg_msg(1, "total_free: %llu", c->lst.total_free); -++ dbg_msg(1, "total_dirty: %llu", c->lst.total_dirty); -++ dbg_msg(1, "total_used: %llu", c->lst.total_used); -++ dbg_msg(1, "total_dead: %llu", c->lst.total_dead); -++ dbg_msg(1, "total_dark: %llu", c->lst.total_dark); -++ dbg_msg(1, "index size: %llu", c->old_idx_sz); -++ dbg_msg(1, "empty_lebs: %d", c->lst.empty_lebs); -++ return 0; -++} -++ -++/** -++ * write_super - write the super block. -++ */ -++static int write_super(void) -++{ -++ struct ubifs_sb_node sup; -++ -++ memset(&sup, 0, UBIFS_SB_NODE_SZ); -++ -++ sup.ch.node_type = UBIFS_SB_NODE; -++ sup.key_hash = c->key_hash_type; -++ sup.min_io_size = cpu_to_le32(c->min_io_size); -++ sup.leb_size = cpu_to_le32(c->leb_size); -++ sup.leb_cnt = cpu_to_le32(c->leb_cnt); -++ sup.max_leb_cnt = cpu_to_le32(c->max_leb_cnt); -++ sup.max_bud_bytes = cpu_to_le64(c->max_bud_bytes); -++ sup.log_lebs = cpu_to_le32(c->log_lebs); -++ sup.lpt_lebs = cpu_to_le32(c->lpt_lebs); -++ sup.orph_lebs = cpu_to_le32(c->orph_lebs); -++ sup.jhead_cnt = cpu_to_le32(c->jhead_cnt); -++ sup.fanout = cpu_to_le32(c->fanout); -++ sup.lsave_cnt = cpu_to_le32(c->lsave_cnt); -++ sup.fmt_version = cpu_to_le32(UBIFS_FORMAT_VERSION); -++ sup.default_compr = cpu_to_le16(c->default_compr); -++ sup.time_gran = cpu_to_le32(DEFAULT_TIME_GRAN); -++ if (c->big_lpt) -++ sup.flags |= UBIFS_FLG_BIGLPT; -++ -++ return write_node(&sup, UBIFS_SB_NODE_SZ, UBIFS_SB_LNUM); -++} -++ -++/** -++ * write_master - write the master node. -++ */ -++static int write_master(void) -++{ -++ struct ubifs_mst_node mst; -++ int err; -++ -++ memset(&mst, 0, UBIFS_MST_NODE_SZ); -++ -++ mst.ch.node_type = UBIFS_MST_NODE; -++ mst.log_lnum = cpu_to_le32(UBIFS_LOG_LNUM); -++ mst.highest_inum = cpu_to_le64(c->highest_inum); -++ mst.cmt_no = cpu_to_le64(0); -++ mst.flags = cpu_to_le32(UBIFS_MST_NO_ORPHS); -++ mst.root_lnum = cpu_to_le32(c->zroot.lnum); -++ mst.root_offs = cpu_to_le32(c->zroot.offs); -++ mst.root_len = cpu_to_le32(c->zroot.len); -++ mst.gc_lnum = cpu_to_le32(c->gc_lnum); -++ mst.ihead_lnum = cpu_to_le32(c->ihead_lnum); -++ mst.ihead_offs = cpu_to_le32(c->ihead_offs); -++ mst.index_size = cpu_to_le64(c->old_idx_sz); -++ mst.lpt_lnum = cpu_to_le32(c->lpt_lnum); -++ mst.lpt_offs = cpu_to_le32(c->lpt_offs); -++ mst.nhead_lnum = cpu_to_le32(c->nhead_lnum); -++ mst.nhead_offs = cpu_to_le32(c->nhead_offs); -++ mst.ltab_lnum = cpu_to_le32(c->ltab_lnum); -++ mst.ltab_offs = cpu_to_le32(c->ltab_offs); -++ mst.lsave_lnum = cpu_to_le32(c->lsave_lnum); -++ mst.lsave_offs = cpu_to_le32(c->lsave_offs); -++ mst.lscan_lnum = cpu_to_le32(c->lscan_lnum); -++ mst.empty_lebs = cpu_to_le32(c->lst.empty_lebs); -++ mst.idx_lebs = cpu_to_le32(c->lst.idx_lebs); -++ mst.total_free = cpu_to_le64(c->lst.total_free); -++ mst.total_dirty = cpu_to_le64(c->lst.total_dirty); -++ mst.total_used = cpu_to_le64(c->lst.total_used); -++ mst.total_dead = cpu_to_le64(c->lst.total_dead); -++ mst.total_dark = cpu_to_le64(c->lst.total_dark); -++ mst.leb_cnt = cpu_to_le32(c->leb_cnt); -++ -++ err = write_node(&mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM); -++ if (err) -++ return err; -++ -++ err = write_node(&mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM + 1); -++ if (err) -++ return err; -++ -++ return 0; -++} -++ -++/** -++ * write_log - write an empty log. -++ */ -++static int write_log(void) -++{ -++ struct ubifs_cs_node cs; -++ int err, i, lnum; -++ -++ lnum = UBIFS_LOG_LNUM; -++ -++ cs.ch.node_type = UBIFS_CS_NODE; -++ cs.cmt_no = cpu_to_le64(0); -++ -++ err = write_node(&cs, UBIFS_CS_NODE_SZ, lnum); -++ if (err) -++ return err; -++ -++ lnum += 1; -++ -++ for (i = 1; i < c->log_lebs; i++, lnum++) { -++ err = write_empty_leb(lnum); -++ if (err) -++ return err; -++ } -++ -++ return 0; -++} -++ -++/** -++ * write_lpt - write the LEB properties tree. -++ */ -++static int write_lpt(void) -++{ -++ int err, lnum; -++ -++ err = create_lpt(c); -++ if (err) -++ return err; -++ -++ lnum = c->nhead_lnum + 1; -++ while (lnum <= c->lpt_last) { -++ err = write_empty_leb(lnum++); -++ if (err) -++ return err; -++ } -++ -++ return 0; -++} -++ -++/** -++ * write_orphan_area - write an empty orphan area. -++ */ -++static int write_orphan_area(void) -++{ -++ int err, i, lnum; -++ -++ lnum = UBIFS_LOG_LNUM + c->log_lebs + c->lpt_lebs; -++ for (i = 0; i < c->orph_lebs; i++, lnum++) { -++ err = write_empty_leb(lnum); -++ if (err) -++ return err; -++ } -++ return 0; -++} -++ -++/** -++ * open_target - open the output file. -++ */ -++static int open_target(void) -++{ -++ out_fd = open(output, O_CREAT | O_RDWR | O_TRUNC, -++ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); -++ if (out_fd == -1) -++ return sys_err_msg("cannot create output file '%s'", output); -++ return 0; -++} -++ -++/** -++ * close_target - close the output file. -++ */ -++static int close_target(void) -++{ -++ if (close(out_fd) == -1) -++ return sys_err_msg("cannot close output file '%s'", output); -++ return 0; -++} -++ -++/** -++ * init - initialize things. -++ */ -++static int init(void) -++{ -++ int err, i, main_lebs, big_lpt = 0, sz; -++ -++ c->highest_inum = UBIFS_FIRST_INO; -++ -++ c->jhead_cnt = 1; -++ -++ main_lebs = c->max_leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS; -++ main_lebs -= c->log_lebs + c->orph_lebs; -++ -++ err = calc_dflt_lpt_geom(c, &main_lebs, &big_lpt); -++ if (err) -++ return err; -++ -++ c->main_first = UBIFS_LOG_LNUM + c->log_lebs + c->lpt_lebs + -++ c->orph_lebs; -++ head_lnum = c->main_first; -++ head_offs = 0; -++ -++ c->lpt_first = UBIFS_LOG_LNUM + c->log_lebs; -++ c->lpt_last = c->lpt_first + c->lpt_lebs - 1; -++ -++ c->lpt = malloc(c->main_lebs * sizeof(struct ubifs_lprops)); -++ if (!c->lpt) -++ return err_msg("unable to allocate LPT"); -++ -++ c->ltab = malloc(c->lpt_lebs * sizeof(struct ubifs_lprops)); -++ if (!c->ltab) -++ return err_msg("unable to allocate LPT ltab"); -++ -++ /* Initialize LPT's own lprops */ -++ for (i = 0; i < c->lpt_lebs; i++) { -++ c->ltab[i].free = c->leb_size; -++ c->ltab[i].dirty = 0; -++ } -++ -++ c->dead_wm = ALIGN(MIN_WRITE_SZ, c->min_io_size); -++ c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size); -++ dbg_msg(1, "dead_wm %d dark_wm %d", c->dead_wm, c->dark_wm); -++ -++ leb_buf = malloc(c->leb_size); -++ if (!leb_buf) -++ return err_msg("out of memory"); -++ -++ node_buf = malloc(NODE_BUFFER_SIZE); -++ if (!node_buf) -++ return err_msg("out of memory"); -++ -++ block_buf = malloc(UBIFS_BLOCK_SIZE); -++ if (!block_buf) -++ return err_msg("out of memory"); -++ -++ sz = sizeof(struct inum_mapping *) * HASH_TABLE_SIZE; -++ hash_table = malloc(sz); -++ if (!hash_table) -++ return err_msg("out of memory"); -++ memset(hash_table, 0, sz); -++ -++ err = init_compression(); -++ if (err) -++ return err; -++ -++ return 0; -++} -++ -++static void destroy_hash_table(void) -++{ -++ int i; -++ -++ for (i = 0; i < HASH_TABLE_SIZE; i++) { -++ struct inum_mapping *im, *q; -++ -++ for (im = hash_table[i]; im; ) { -++ q = im; -++ im = im->next; -++ free(q->path_name); -++ free(q); -++ } -++ } -++} -++ -++/** -++ * deinit - deinitialize things. -++ */ -++static void deinit(void) -++{ -++ free(c->lpt); -++ free(c->ltab); -++ free(leb_buf); -++ free(node_buf); -++ free(block_buf); -++ destroy_hash_table(); -++ free(hash_table); -++ destroy_compression(); -++ free_devtable_info(); -++} -++ -++/** -++ * mkfs - make the file system. -++ * -++ * Each on-flash area has a corresponding function to create it. The order of -++ * the functions reflects what information must be known to complete each stage. -++ * As a consequence the output file is not written sequentially. No effort has -++ * been made to make efficient use of memory or to allow for the possibility of -++ * incremental updates to the output file. -++ */ -++static int mkfs(void) -++{ -++ int err = 0; -++ -++ err = init(); -++ if (err) -++ goto out; -++ -++ err = write_data(); -++ if (err) -++ goto out; -++ -++ err = set_gc_lnum(); -++ if (err) -++ goto out; -++ -++ err = write_index(); -++ if (err) -++ goto out; -++ -++ err = finalize_leb_cnt(); -++ if (err) -++ goto out; -++ -++ err = write_lpt(); -++ if (err) -++ goto out; -++ -++ err = write_super(); -++ if (err) -++ goto out; -++ -++ err = write_master(); -++ if (err) -++ goto out; -++ -++ err = write_log(); -++ if (err) -++ goto out; -++ -++ err = write_orphan_area(); -++ -++out: -++ deinit(); -++ return err; -++} -++ -++int main(int argc, char *argv[]) -++{ -++ int err; -++ -++ err = get_options(argc, argv); -++ if (err) -++ return err; -++ -++ err = open_target(); -++ if (err) -++ return err; -++ -++ err = mkfs(); -++ if (err) { -++ close_target(); -++ return err; -++ } -++ -++ err = close_target(); -++ if (err) -++ return err; -++ -++ if (verbose) -++ printf("Success!\n"); -++ -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/mkfs.ubifs.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/mkfs.ubifs.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/mkfs.ubifs.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/mkfs.ubifs.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,143 @@ -++/* -++ * Copyright (C) 2008 Nokia Corporation. -++ * Copyright (C) 2008 University of Szeged, Hungary -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy -++ * Adrian Hunter -++ * Zoltan Sogor -++ */ -++ -++#ifndef __MKFS_UBIFS_H__ -++#define __MKFS_UBIFS_H__ -++ -++#define _GNU_SOURCE -++#define _LARGEFILE64_SOURCE -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "crc32.h" -++#include "defs.h" -++#include "crc16.h" -++#include "ubifs-media.h" -++#include "ubifs.h" -++#include "key.h" -++#include "lpt.h" -++#include "compr.h" -++ -++/* -++ * Compression flags are duplicated so that compr.c can compile without ubifs.h. -++ * Here we make sure they are the same. -++ */ -++#if MKFS_UBIFS_COMPR_NONE != UBIFS_COMPR_NONE -++#error MKFS_UBIFS_COMPR_NONE != UBIFS_COMPR_NONE -++#endif -++#if MKFS_UBIFS_COMPR_LZO != UBIFS_COMPR_LZO -++#error MKFS_UBIFS_COMPR_LZO != UBIFS_COMPR_LZO -++#endif -++#if MKFS_UBIFS_COMPR_ZLIB != UBIFS_COMPR_ZLIB -++#error MKFS_UBIFS_COMPR_ZLIB != UBIFS_COMPR_ZLIB -++#endif -++ -++extern int verbose; -++extern int debug_level; -++ -++#define dbg_msg(lvl, fmt, ...) do {if (debug_level >= lvl) \ -++ printf("mkfs.ubifs: %s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \ -++} while(0) -++ -++#define err_msg(fmt, ...) ({ \ -++ fprintf(stderr, "Error: " fmt "\n", ##__VA_ARGS__); \ -++ -1; \ -++}) -++ -++#define sys_err_msg(fmt, ...) ({ \ -++ int err_ = errno; \ -++ fprintf(stderr, "Error: " fmt "\n", ##__VA_ARGS__); \ -++ fprintf(stderr, " %s (error %d)\n", strerror(err_), err_); \ -++ -1; \ -++}) -++ -++/** -++ * struct path_htbl_element - an element of the path hash table. -++ * @path: the UBIFS path the element describes (the key of the element) -++ * @name_htbl: one more (nested) hash table containing names of all -++ * files/directories/device nodes which should be created at this -++ * path -++ * -++ * See device table handling for more information. -++ */ -++struct path_htbl_element { -++ const char *path; -++ struct hashtable *name_htbl; -++}; -++ -++/** -++ * struct name_htbl_element - an element in the name hash table -++ * @name: name of the file/directory/device node (the key of the element) -++ * @mode: accsess rights and file type -++ * @uid: user ID -++ * @gid: group ID -++ * @major: device node major number -++ * @minor: device node minor number -++ * -++ * This is an element of the name hash table. Name hash table sits in the path -++ * hash table elements and describes file names which should be created/changed -++ * at this path. -++ */ -++struct name_htbl_element { -++ const char *name; -++ unsigned int mode; -++ unsigned int uid; -++ unsigned int gid; -++ dev_t dev; -++}; -++ -++struct hashtable_itr; -++ -++int write_leb(int lnum, int len, void *buf); -++int parse_devtable(const char *root, const char *tbl_file); -++struct path_htbl_element *devtbl_find_path(const char *path); -++struct name_htbl_element *devtbl_find_name(struct path_htbl_element *ph_elt, -++ const char *name); -++int override_attributes(struct stat *st, struct path_htbl_element *ph_elt, -++ struct name_htbl_element *nh_elt); -++struct name_htbl_element * -++first_name_htbl_element(struct path_htbl_element *ph_elt, -++ struct hashtable_itr **itr); -++struct name_htbl_element * -++next_name_htbl_element(struct path_htbl_element *ph_elt, -++ struct hashtable_itr **itr); -++void free_devtable_info(void); -++ -++#endif -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/readme linux-2.6.24.7/fs/ubifs/mkfs.ubifs/readme -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/readme 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/readme 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,28 @@ -++UBIFS File System - Make File System program -++ -++* crc16.h and crc16.c were copied from the linux kernel. -++* crc32.h and crc32.c were copied from mtd-utils and amended. -++* ubifs-media.h is fs/ubifs/ubifs-media.h from the linux kernel -++* ubifs.h is a selection of definitions from fs/ubifs/ubifs.h from the linux kernel. -++* key.h is copied from fs/ubifs/key.h from the linux kernel. -++* defs.h is a bunch of definitions to smooth things over. -++* lpt.c is a selection of functions copied from fs/ubifs/lpt.c from the linux kernel, and amended. -++* hashtable/* was downloaded from http://www.cl.cam.ac.uk/~cwc22/hashtable/ -++ -++*************************************************************************** -++ -++To build the mkfs.ubifs: -++ -++$ cd fs/ubifs/mkfs.ubifs -++$ make -++ -++To run mkfs.ubifs: -++ -++$ export LD_LIBRARY_PATH=`pwd`/lzo/lib:$LD_LIBRARY_PATH -++$ ./mkfs.ubifs -h -++ -++To build an ubifs image: -++ -++$ ./mkfs.ubifs -r /nfsroot/root26 -m 2048 -e 258048 -c 813 -o ubifs.img -++ -++*************************************************************************** -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/ubifs-media.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/ubifs-media.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/ubifs-media.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/ubifs-media.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,725 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* -++ * This file describes UBIFS on-flash format and contains definitions of all the -++ * relevant data structures and constants. -++ * -++ * All UBIFS on-flash objects are stored in the form of nodes. All nodes start -++ * with the UBIFS node magic number and have the same common header. Nodes -++ * always sit at 8-byte aligned positions on the media and node header sizes are -++ * also 8-byte aligned (except for the indexing node and the padding node). -++ */ -++ -++#ifndef __UBIFS_MEDIA_H__ -++#define __UBIFS_MEDIA_H__ -++ -++/* UBIFS node magic number (must not have the padding byte first or last) */ -++#define UBIFS_NODE_MAGIC 0x06101831 -++ -++/* UBIFS on-flash format version */ -++#define UBIFS_FORMAT_VERSION 3 -++ -++/* Minimum logical eraseblock size in bytes */ -++#define UBIFS_MIN_LEB_SZ (15*1024) -++ -++/* Initial CRC32 value used when calculating CRC checksums */ -++#define UBIFS_CRC32_INIT 0xFFFFFFFFU -++ -++/* -++ * UBIFS does not try to compress data if its length is less than the below -++ * constant. -++ */ -++#define UBIFS_MIN_COMPR_LEN 128 -++ -++/* Root inode number */ -++#define UBIFS_ROOT_INO 1 -++ -++/* Lowest inode number used for regular inodes (not UBIFS-only internal ones) */ -++#define UBIFS_FIRST_INO 64 -++ -++/* -++ * Maximum file name and extended attribute length (must be a multiple of 8, -++ * minus 1). -++ */ -++#define UBIFS_MAX_NLEN 255 -++ -++/* Maximum number of data journal heads */ -++#define UBIFS_MAX_JHEADS 1 -++ -++/* -++ * Size of UBIFS data block. Note, UBIFS is not a block oriented file-system, -++ * which means that it does not treat the underlying media as consisting of -++ * blocks like in case of hard drives. Do not be confused. UBIFS block is just -++ * the maximum amount of data which one data node can have or which can be -++ * attached to an inode node. -++ */ -++#define UBIFS_BLOCK_SIZE 4096 -++#define UBIFS_BLOCK_SHIFT 12 -++#define UBIFS_BLOCK_MASK 0x00000FFF -++ -++/* UBIFS padding byte pattern (must not be first or last byte of node magic) */ -++#define UBIFS_PADDING_BYTE 0xCE -++ -++/* Maximum possible key length */ -++#define UBIFS_MAX_KEY_LEN 16 -++ -++/* Key length ("simple" format) */ -++#define UBIFS_SK_LEN 8 -++ -++/* Minimum index tree fanout */ -++#define UBIFS_MIN_FANOUT 2 -++ -++/* Maximum number of levels in UBIFS indexing B-tree */ -++#define UBIFS_MAX_LEVELS 512 -++ -++/* Maximum amount of data attached to an inode in bytes */ -++#define UBIFS_MAX_INO_DATA UBIFS_BLOCK_SIZE -++ -++/* LEB Properties Tree fanout (must be power of 2) and fanout shift */ -++#define UBIFS_LPT_FANOUT 4 -++#define UBIFS_LPT_FANOUT_SHIFT 2 -++ -++/* LEB Properties Tree bit field sizes */ -++#define UBIFS_LPT_CRC_BITS 16 -++#define UBIFS_LPT_CRC_BYTES 2 -++#define UBIFS_LPT_TYPE_BITS 4 -++ -++/* The key is always at the same position in all keyed nodes */ -++#define UBIFS_KEY_OFFSET offsetof(struct ubifs_ino_node, key) -++ -++/* -++ * LEB Properties Tree node types. -++ * -++ * UBIFS_LPT_PNODE: LPT leaf node (contains LEB properties) -++ * UBIFS_LPT_NNODE: LPT internal node -++ * UBIFS_LPT_LTAB: LPT's own lprops table -++ * UBIFS_LPT_LSAVE: LPT's save table (big model only) -++ * UBIFS_LPT_NODE_CNT: count of LPT node types -++ * UBIFS_LPT_NOT_A_NODE: all ones (15 for 4 bits) is never a valid node type -++ */ -++enum { -++ UBIFS_LPT_PNODE, -++ UBIFS_LPT_NNODE, -++ UBIFS_LPT_LTAB, -++ UBIFS_LPT_LSAVE, -++ UBIFS_LPT_NODE_CNT, -++ UBIFS_LPT_NOT_A_NODE = (1 << UBIFS_LPT_TYPE_BITS) - 1, -++}; -++ -++/* -++ * UBIFS inode types. -++ * -++ * UBIFS_ITYPE_REG: regular file -++ * UBIFS_ITYPE_DIR: directory -++ * UBIFS_ITYPE_LNK: soft link -++ * UBIFS_ITYPE_BLK: block device node -++ * UBIFS_ITYPE_CHR: character device node -++ * UBIFS_ITYPE_FIFO: fifo -++ * UBIFS_ITYPE_SOCK: socket -++ * UBIFS_ITYPES_CNT: count of supported file types -++ */ -++enum { -++ UBIFS_ITYPE_REG, -++ UBIFS_ITYPE_DIR, -++ UBIFS_ITYPE_LNK, -++ UBIFS_ITYPE_BLK, -++ UBIFS_ITYPE_CHR, -++ UBIFS_ITYPE_FIFO, -++ UBIFS_ITYPE_SOCK, -++ UBIFS_ITYPES_CNT, -++}; -++ -++/* -++ * Supported key hash functions. -++ * -++ * UBIFS_KEY_HASH_R5: R5 hash -++ * UBIFS_KEY_HASH_TEST: test hash which just returns first 4 bytes of the name -++ */ -++enum { -++ UBIFS_KEY_HASH_R5, -++ UBIFS_KEY_HASH_TEST, -++}; -++ -++/* -++ * Supported key formats. -++ * -++ * UBIFS_SIMPLE_KEY_FMT: simple key format -++ */ -++enum { -++ UBIFS_SIMPLE_KEY_FMT, -++}; -++ -++/* -++ * The simple key format uses 29 bits for storing UBIFS block number and hash -++ * value. -++ */ -++#define UBIFS_S_KEY_BLOCK_BITS 29 -++#define UBIFS_S_KEY_BLOCK_MASK 0x1FFFFFFF -++#define UBIFS_S_KEY_HASH_BITS UBIFS_S_KEY_BLOCK_BITS -++#define UBIFS_S_KEY_HASH_MASK UBIFS_S_KEY_BLOCK_MASK -++ -++/* -++ * Key types. -++ * -++ * UBIFS_INO_KEY: inode node key -++ * UBIFS_DATA_KEY: data node key -++ * UBIFS_DENT_KEY: directory entry node key -++ * UBIFS_XENT_KEY: extended attribute entry key -++ * UBIFS_TRUN_KEY: truncation node key -++ * UBIFS_KEY_TYPES_CNT: number of supported key types -++ */ -++enum { -++ UBIFS_INO_KEY, -++ UBIFS_DATA_KEY, -++ UBIFS_DENT_KEY, -++ UBIFS_XENT_KEY, -++ UBIFS_TRUN_KEY, -++ UBIFS_KEY_TYPES_CNT, -++}; -++ -++/* Count of LEBs reserved for the superblock area */ -++#define UBIFS_SB_LEBS 1 -++/* Count of LEBs reserved for the master area */ -++#define UBIFS_MST_LEBS 2 -++ -++/* First LEB of the superblock area */ -++#define UBIFS_SB_LNUM 0 -++/* First LEB of the master area */ -++#define UBIFS_MST_LNUM (UBIFS_SB_LNUM + UBIFS_SB_LEBS) -++/* First LEB of the log area */ -++#define UBIFS_LOG_LNUM (UBIFS_MST_LNUM + UBIFS_MST_LEBS) -++ -++/* Minimum number of logical eraseblocks in the log */ -++#define UBIFS_MIN_LOG_LEBS 2 -++/* Minimum number of bud logical eraseblocks */ -++#define UBIFS_MIN_BUD_LEBS 2 -++/* Minimum number of journal logical eraseblocks */ -++#define UBIFS_MIN_JNL_LEBS (UBIFS_MIN_LOG_LEBS + UBIFS_MIN_BUD_LEBS) -++/* Minimum number of LPT area logical eraseblocks */ -++#define UBIFS_MIN_LPT_LEBS 2 -++/* Minimum number of orphan area logical eraseblocks */ -++#define UBIFS_MIN_ORPH_LEBS 1 -++/* Minimum number of main area logical eraseblocks */ -++#define UBIFS_MIN_MAIN_LEBS 8 -++ -++/* Minimum number of logical eraseblocks */ -++#define UBIFS_MIN_LEB_CNT (UBIFS_SB_LEBS + UBIFS_MST_LEBS + \ -++ UBIFS_MIN_LOG_LEBS + UBIFS_MIN_BUD_LEBS + \ -++ UBIFS_MIN_LPT_LEBS + UBIFS_MIN_ORPH_LEBS + \ -++ UBIFS_MIN_MAIN_LEBS) -++ -++/* Node sizes (N.B. these are guaranteed to be multiples of 8) */ -++#define UBIFS_CH_SZ sizeof(struct ubifs_ch) -++#define UBIFS_INO_NODE_SZ sizeof(struct ubifs_ino_node) -++#define UBIFS_DATA_NODE_SZ sizeof(struct ubifs_data_node) -++#define UBIFS_DENT_NODE_SZ sizeof(struct ubifs_dent_node) -++#define UBIFS_TRUN_NODE_SZ sizeof(struct ubifs_trun_node) -++#define UBIFS_PAD_NODE_SZ sizeof(struct ubifs_pad_node) -++#define UBIFS_SB_NODE_SZ sizeof(struct ubifs_sb_node) -++#define UBIFS_MST_NODE_SZ sizeof(struct ubifs_mst_node) -++#define UBIFS_REF_NODE_SZ sizeof(struct ubifs_ref_node) -++#define UBIFS_IDX_NODE_SZ sizeof(struct ubifs_idx_node) -++#define UBIFS_CS_NODE_SZ sizeof(struct ubifs_cs_node) -++#define UBIFS_ORPH_NODE_SZ sizeof(struct ubifs_orph_node) -++/* Extended attribute entry nodes are identical to directory entry nodes */ -++#define UBIFS_XENT_NODE_SZ UBIFS_DENT_NODE_SZ -++/* Only this does not have to be multiple of 8 bytes */ -++#define UBIFS_BRANCH_SZ sizeof(struct ubifs_branch) -++ -++/* Maximum node sizes (N.B. these are guaranteed to be multiples of 8) */ -++#define UBIFS_MAX_DATA_NODE_SZ (UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE) -++#define UBIFS_MAX_INO_NODE_SZ (UBIFS_INO_NODE_SZ + UBIFS_MAX_INO_DATA) -++#define UBIFS_MAX_DENT_NODE_SZ (UBIFS_DENT_NODE_SZ + UBIFS_MAX_NLEN + 1) -++#define UBIFS_MAX_XENT_NODE_SZ UBIFS_MAX_DENT_NODE_SZ -++ -++/* The largest UBIFS node */ -++#define UBIFS_MAX_NODE_SZ UBIFS_MAX_INO_NODE_SZ -++ -++/* -++ * On-flash inode flags. -++ * -++ * UBIFS_COMPR_FL: use compression for this inode -++ * UBIFS_SYNC_FL: I/O on this inode has to be synchronous -++ * UBIFS_IMMUTABLE_FL: inode is immutable -++ * UBIFS_APPEND_FL: writes to the inode may only append data -++ * UBIFS_DIRSYNC_FL: I/O on this directory inode has to be synchronous -++ * -++ * Note, these are on-flash flags which correspond to ioctl flags -++ * (@FS_COMPR_FL, etc). They have the same values now, but generally, do not -++ * have to be the same. -++ */ -++enum { -++ UBIFS_COMPR_FL = 0x01, -++ UBIFS_SYNC_FL = 0x02, -++ UBIFS_IMMUTABLE_FL = 0x04, -++ UBIFS_APPEND_FL = 0x08, -++ UBIFS_DIRSYNC_FL = 0x10, -++}; -++ -++/* Inode flag bits used by UBIFS */ -++#define UBIFS_FL_MASK 0x0000001F -++ -++/* -++ * UBIFS compression algorithms. -++ * -++ * UBIFS_COMPR_NONE: no compression -++ * UBIFS_COMPR_LZO: LZO compression -++ * UBIFS_COMPR_ZLIB: ZLIB compression -++ * UBIFS_COMPR_TYPES_CNT: count of supported compression types -++ */ -++enum { -++ UBIFS_COMPR_NONE, -++ UBIFS_COMPR_LZO, -++ UBIFS_COMPR_ZLIB, -++ UBIFS_COMPR_TYPES_CNT, -++}; -++ -++/* -++ * UBIFS node types. -++ * -++ * UBIFS_INO_NODE: inode node -++ * UBIFS_DATA_NODE: data node -++ * UBIFS_DENT_NODE: directory entry node -++ * UBIFS_XENT_NODE: extended attribute node -++ * UBIFS_TRUN_NODE: truncation node -++ * UBIFS_PAD_NODE: padding node -++ * UBIFS_SB_NODE: superblock node -++ * UBIFS_MST_NODE: master node -++ * UBIFS_REF_NODE: LEB reference node -++ * UBIFS_IDX_NODE: index node -++ * UBIFS_CS_NODE: commit start node -++ * UBIFS_ORPH_NODE: orphan node -++ * UBIFS_NODE_TYPES_CNT: count of supported node types -++ * -++ * Note, we index arrays by these numbers, so keep them low and contiguous. -++ * Node type constants for inodes, direntries and so on have to be the same as -++ * corresponding key type constants. -++ */ -++enum { -++ UBIFS_INO_NODE, -++ UBIFS_DATA_NODE, -++ UBIFS_DENT_NODE, -++ UBIFS_XENT_NODE, -++ UBIFS_TRUN_NODE, -++ UBIFS_PAD_NODE, -++ UBIFS_SB_NODE, -++ UBIFS_MST_NODE, -++ UBIFS_REF_NODE, -++ UBIFS_IDX_NODE, -++ UBIFS_CS_NODE, -++ UBIFS_ORPH_NODE, -++ UBIFS_NODE_TYPES_CNT, -++}; -++ -++/* -++ * Master node flags. -++ * -++ * UBIFS_MST_DIRTY: rebooted uncleanly - master node is dirty -++ * UBIFS_MST_NO_ORPHS: no orphan inodes present -++ * UBIFS_MST_RCVRY: written by recovery -++ */ -++enum { -++ UBIFS_MST_DIRTY = 1, -++ UBIFS_MST_NO_ORPHS = 2, -++ UBIFS_MST_RCVRY = 4, -++}; -++ -++/* -++ * Node group type (used by recovery to recover whole group or none). -++ * -++ * UBIFS_NO_NODE_GROUP: this node is not part of a group -++ * UBIFS_IN_NODE_GROUP: this node is a part of a group -++ * UBIFS_LAST_OF_NODE_GROUP: this node is the last in a group -++ */ -++enum { -++ UBIFS_NO_NODE_GROUP = 0, -++ UBIFS_IN_NODE_GROUP, -++ UBIFS_LAST_OF_NODE_GROUP, -++}; -++ -++/* -++ * Superblock flags. -++ * -++ * UBIFS_FLG_BIGLPT: if "big" LPT model is used if set -++ */ -++enum { -++ UBIFS_FLG_BIGLPT = 0x02, -++}; -++ -++/** -++ * struct ubifs_ch - common header node. -++ * @magic: UBIFS node magic number (%UBIFS_NODE_MAGIC) -++ * @crc: CRC-32 checksum of the node header -++ * @sqnum: sequence number -++ * @len: full node length -++ * @node_type: node type -++ * @group_type: node group type -++ * @padding: reserved for future, zeroes -++ * -++ * Every UBIFS node starts with this common part. If the node has a key, the -++ * key always goes next. -++ */ -++struct ubifs_ch { -++ __le32 magic; -++ __le32 crc; -++ __le64 sqnum; -++ __le32 len; -++ __u8 node_type; -++ __u8 group_type; -++ __u8 padding[2]; -++} __attribute__ ((packed)); -++ -++/** -++ * union ubifs_dev_desc - device node descriptor. -++ * @new: new type device descriptor -++ * @huge: huge type device descriptor -++ * -++ * This data structure describes major/minor numbers of a device node. In an -++ * inode is a device node then its data contains an object of this type. UBIFS -++ * uses standard Linux "new" and "huge" device node encodings. -++ */ -++union ubifs_dev_desc { -++ __le32 new; -++ __le64 huge; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_ino_node - inode node. -++ * @ch: common header -++ * @key: node key -++ * @creat_sqnum: sequence number at time of creation -++ * @size: inode size in bytes (amount of uncompressed data) -++ * @atime_sec: access time seconds -++ * @ctime_sec: creation time seconds -++ * @mtime_sec: modification time seconds -++ * @atime_nsec: access time nanoseconds -++ * @ctime_nsec: creation time nanoseconds -++ * @mtime_nsec: modification time nanoseconds -++ * @nlink: number of hard links -++ * @uid: owner ID -++ * @gid: group ID -++ * @mode: access flags -++ * @flags: per-inode flags (%UBIFS_COMPR_FL, %UBIFS_SYNC_FL, etc) -++ * @data_len: inode data length -++ * @xattr_cnt: count of extended attributes this inode has -++ * @xattr_size: summarized size of all extended attributes in bytes -++ * @xattr_names: sum of lengths of all extended attribute names belonging to -++ * this inode -++ * @compr_type: compression type used for this inode -++ * @padding: reserved for future, zeroes -++ * @data: data attached to the inode -++ * -++ * Note, even though inode compression type is defined by @compr_type, some -++ * nodes of this inode may be compressed with different compressor - this -++ * happens if compression type is changed while the inode already has data -++ * nodes. But @compr_type will be use for further writes to the inode. -++ * -++ * Note, do not forget to amend 'zero_ino_node_unused()' function when changing -++ * the padding fields. -++ */ -++struct ubifs_ino_node { -++ struct ubifs_ch ch; -++ __u8 key[UBIFS_MAX_KEY_LEN]; -++ __le64 creat_sqnum; -++ __le64 size; -++ __le64 atime_sec; -++ __le64 ctime_sec; -++ __le64 mtime_sec; -++ __le32 atime_nsec; -++ __le32 ctime_nsec; -++ __le32 mtime_nsec; -++ __le32 nlink; -++ __le32 uid; -++ __le32 gid; -++ __le32 mode; -++ __le32 flags; -++ __le32 data_len; -++ __le32 xattr_cnt; -++ __le64 xattr_size; -++ __le32 xattr_names; -++ __le16 compr_type; -++ __u8 padding[26]; /* Watch 'zero_ino_node_unused()' if changing! */ -++ __u8 data[]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_dent_node - directory entry node. -++ * @ch: common header -++ * @key: node key -++ * @inum: target inode number -++ * @padding1: reserved for future, zeroes -++ * @type: type of the target inode (%UBIFS_ITYPE_REG, %UBIFS_ITYPE_DIR, etc) -++ * @nlen: name length -++ * @padding2: reserved for future, zeroes -++ * @name: zero-terminated name -++ * -++ * Note, do not forget to amend 'zero_dent_node_unused()' function when -++ * changing the padding fields. -++ */ -++struct ubifs_dent_node { -++ struct ubifs_ch ch; -++ __u8 key[UBIFS_MAX_KEY_LEN]; -++ __le64 inum; -++ __u8 padding1; -++ __u8 type; -++ __le16 nlen; -++ __u8 padding2[4]; /* Watch 'zero_dent_node_unused()' if changing! */ -++ __u8 name[]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_data_node - data node. -++ * @ch: common header -++ * @key: node key -++ * @size: uncompressed data size in bytes -++ * @compr_type: compression type (%UBIFS_COMPR_NONE, %UBIFS_COMPR_LZO, etc) -++ * @padding: reserved for future, zeroes -++ * @data: data -++ * -++ * Note, do not forget to amend 'zero_data_node_unused()' function when -++ * changing the padding fields. -++ */ -++struct ubifs_data_node { -++ struct ubifs_ch ch; -++ __u8 key[UBIFS_MAX_KEY_LEN]; -++ __le32 size; -++ __le16 compr_type; -++ __u8 padding[2]; /* Watch 'zero_data_node_unused()' if changing! */ -++ __u8 data[]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_trun_node - truncation node. -++ * @ch: common header -++ * @key: truncation node key -++ * @old_size: size before truncation -++ * @new_size: size after truncation -++ * -++ * This node exists only in the journal and never goes to the main area. -++ */ -++struct ubifs_trun_node { -++ struct ubifs_ch ch; -++ __u8 key[UBIFS_MAX_KEY_LEN]; -++ __le64 old_size; -++ __le64 new_size; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_pad_node - padding node. -++ * @ch: common header -++ * @pad_len: how many bytes after this node are unused (because padded) -++ * @padding: reserved for future, zeroes -++ */ -++struct ubifs_pad_node { -++ struct ubifs_ch ch; -++ __le32 pad_len; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_sb_node - superblock node. -++ * @ch: common header -++ * @padding: reserved for future, zeroes -++ * @key_hash: type of hash function used in keys -++ * @key_fmt: format of the key -++ * @flags: file-system flags (%UBIFS_FLG_BIGLPT, etc) -++ * @min_io_size: minimal input/output unit size -++ * @leb_size: logical eraseblock size in bytes -++ * @leb_cnt: count of LEBs used by filesystem -++ * @max_leb_cnt: maximum count of LEBs used by filesystem -++ * @max_bud_bytes: maximum amount of data stored in buds -++ * @log_lebs: log size in logical eraseblocks -++ * @lpt_lebs: number of LEBs used for lprops table -++ * @orph_lebs: number of LEBs used for recording orphans -++ * @jhead_cnt: count of journal heads -++ * @fanout: tree fanout (max. number of links per indexing node) -++ * @lsave_cnt: number of LEB numbers in LPT's save table -++ * @fmt_version: UBIFS on-flash format version -++ * @default_compr: default compression algorithm (%UBIFS_COMPR_LZO, etc) -++ * @padding1: reserved for future, zeroes -++ * @rp_uid: reserve pool UID -++ * @rp_gid: reserve pool GID -++ * @rp_size: size of the reserved pool in bytes -++ * @padding2: reserved for future, zeroes -++ * @time_gran: time granularity in nanoseconds -++ */ -++struct ubifs_sb_node { -++ struct ubifs_ch ch; -++ __u8 padding[2]; -++ __u8 key_hash; -++ __u8 key_fmt; -++ __le32 flags; -++ __le32 min_io_size; -++ __le32 leb_size; -++ __le32 leb_cnt; -++ __le32 max_leb_cnt; -++ __le64 max_bud_bytes; -++ __le32 log_lebs; -++ __le32 lpt_lebs; -++ __le32 orph_lebs; -++ __le32 jhead_cnt; -++ __le32 fanout; -++ __le32 lsave_cnt; -++ __le32 fmt_version; -++ __le16 default_compr; -++ __u8 padding1[2]; -++ __le32 rp_uid; -++ __le32 rp_gid; -++ __le64 rp_size; -++ __le32 time_gran; -++ __u8 padding2[3988]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_mst_node - master node. -++ * @ch: common header -++ * @highest_inum: highest inode number in the committed index -++ * @cmt_no: commit number -++ * @flags: various flags (%UBIFS_MST_DIRTY, etc) -++ * @log_lnum: start of the log -++ * @root_lnum: LEB number of the root indexing node -++ * @root_offs: offset within @root_lnum -++ * @root_len: root indexing node length -++ * @gc_lnum: LEB reserved for garbage collection (%-1 value means the LEB was -++ * not reserved and should be reserved on mount) -++ * @ihead_lnum: LEB number of index head -++ * @ihead_offs: offset of index head -++ * @index_size: size of index on flash -++ * @total_free: total free space in bytes -++ * @total_dirty: total dirty space in bytes -++ * @total_used: total used space in bytes (includes only data LEBs) -++ * @total_dead: total dead space in bytes (includes only data LEBs) -++ * @total_dark: total dark space in bytes (includes only data LEBs) -++ * @lpt_lnum: LEB number of LPT root nnode -++ * @lpt_offs: offset of LPT root nnode -++ * @nhead_lnum: LEB number of LPT head -++ * @nhead_offs: offset of LPT head -++ * @ltab_lnum: LEB number of LPT's own lprops table -++ * @ltab_offs: offset of LPT's own lprops table -++ * @lsave_lnum: LEB number of LPT's save table (big model only) -++ * @lsave_offs: offset of LPT's save table (big model only) -++ * @lscan_lnum: LEB number of last LPT scan -++ * @empty_lebs: number of empty logical eraseblocks -++ * @idx_lebs: number of indexing logical eraseblocks -++ * @leb_cnt: count of LEBs used by filesystem -++ * @padding: reserved for future, zeroes -++ */ -++struct ubifs_mst_node { -++ struct ubifs_ch ch; -++ __le64 highest_inum; -++ __le64 cmt_no; -++ __le32 flags; -++ __le32 log_lnum; -++ __le32 root_lnum; -++ __le32 root_offs; -++ __le32 root_len; -++ __le32 gc_lnum; -++ __le32 ihead_lnum; -++ __le32 ihead_offs; -++ __le64 index_size; -++ __le64 total_free; -++ __le64 total_dirty; -++ __le64 total_used; -++ __le64 total_dead; -++ __le64 total_dark; -++ __le32 lpt_lnum; -++ __le32 lpt_offs; -++ __le32 nhead_lnum; -++ __le32 nhead_offs; -++ __le32 ltab_lnum; -++ __le32 ltab_offs; -++ __le32 lsave_lnum; -++ __le32 lsave_offs; -++ __le32 lscan_lnum; -++ __le32 empty_lebs; -++ __le32 idx_lebs; -++ __le32 leb_cnt; -++ __u8 padding[344]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_ref_node - logical eraseblock reference node. -++ * @ch: common header -++ * @lnum: the referred logical eraseblock number -++ * @offs: start offset in the referred LEB -++ * @jhead: journal head number -++ * @padding: reserved for future, zeroes -++ */ -++struct ubifs_ref_node { -++ struct ubifs_ch ch; -++ __le32 lnum; -++ __le32 offs; -++ __le32 jhead; -++ __u8 padding[28]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_branch - key/reference/length branch -++ * @lnum: LEB number of the target node -++ * @offs: offset within @lnum -++ * @len: target node length -++ * @key: key -++ */ -++struct ubifs_branch { -++ __le32 lnum; -++ __le32 offs; -++ __le32 len; -++ __u8 key[]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_idx_node - indexing node. -++ * @ch: common header -++ * @child_cnt: number of child index nodes -++ * @level: tree level -++ * @branches: LEB number / offset / length / key branches -++ */ -++struct ubifs_idx_node { -++ struct ubifs_ch ch; -++ __le16 child_cnt; -++ __le16 level; -++ __u8 branches[]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_cs_node - commit start node. -++ * @ch: common header -++ * @cmt_no: commit number -++ */ -++struct ubifs_cs_node { -++ struct ubifs_ch ch; -++ __le64 cmt_no; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_orph_node - orphan node. -++ * @ch: common header -++ * @cmt_no: commit number (also top bit is set on the last node of the commit) -++ * @inos: inode numbers of orphans -++ */ -++struct ubifs_orph_node { -++ struct ubifs_ch ch; -++ __le64 cmt_no; -++ __le64 inos[]; -++} __attribute__ ((packed)); -++ -++#endif /* __UBIFS_MEDIA_H__ */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/ubifs.h linux-2.6.24.7/fs/ubifs/mkfs.ubifs/ubifs.h -+--- linux-2.6.24.7.old/fs/ubifs/mkfs.ubifs/ubifs.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/mkfs.ubifs/ubifs.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,424 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2008 Nokia Corporation. -++ * Copyright (C) 2008 University of Szeged, Hungary -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy -++ * Adrian Hunter -++ * Zoltan Sogor -++ */ -++ -++#ifndef __UBIFS_H__ -++#define __UBIFS_H__ -++ -++/* Minimum amount of data UBIFS writes to the flash */ -++#define MIN_WRITE_SZ (UBIFS_DATA_NODE_SZ + 8) -++ -++/* Largest key size supported in this implementation */ -++#define CUR_MAX_KEY_LEN UBIFS_SK_LEN -++ -++/* The below union makes it easier to deal with keys */ -++union ubifs_key -++{ -++ uint8_t u8[CUR_MAX_KEY_LEN]; -++ uint32_t u32[CUR_MAX_KEY_LEN/4]; -++ uint64_t u64[CUR_MAX_KEY_LEN/8]; -++ __le32 j32[CUR_MAX_KEY_LEN/4]; -++}; -++ -++/* -++ * LEB properties flags. -++ * -++ * LPROPS_UNCAT: not categorized -++ * LPROPS_DIRTY: dirty > 0, not index -++ * LPROPS_DIRTY_IDX: dirty + free > UBIFS_CH_SZ and index -++ * LPROPS_FREE: free > 0, not empty, not index -++ * LPROPS_HEAP_CNT: number of heaps used for storing categorized LEBs -++ * LPROPS_EMPTY: LEB is empty, not taken -++ * LPROPS_FREEABLE: free + dirty == leb_size, not index, not taken -++ * LPROPS_FRDI_IDX: free + dirty == leb_size and index, may be taken -++ * LPROPS_CAT_MASK: mask for the LEB categories above -++ * LPROPS_TAKEN: LEB was taken (this flag is not saved on the media) -++ * LPROPS_INDEX: LEB contains indexing nodes (this flag also exists on flash) -++ */ -++enum { -++ LPROPS_UNCAT = 0, -++ LPROPS_DIRTY = 1, -++ LPROPS_DIRTY_IDX = 2, -++ LPROPS_FREE = 3, -++ LPROPS_HEAP_CNT = 3, -++ LPROPS_EMPTY = 4, -++ LPROPS_FREEABLE = 5, -++ LPROPS_FRDI_IDX = 6, -++ LPROPS_CAT_MASK = 15, -++ LPROPS_TAKEN = 16, -++ LPROPS_INDEX = 32, -++}; -++ -++/** -++ * struct ubifs_lprops - logical eraseblock properties. -++ * @free: amount of free space in bytes -++ * @dirty: amount of dirty space in bytes -++ * @flags: LEB properties flags (see above) -++ */ -++struct ubifs_lprops -++{ -++ int free; -++ int dirty; -++ int flags; -++}; -++ -++/** -++ * struct ubifs_lpt_lprops - LPT logical eraseblock properties. -++ * @free: amount of free space in bytes -++ * @dirty: amount of dirty space in bytes -++ */ -++struct ubifs_lpt_lprops -++{ -++ int free; -++ int dirty; -++}; -++ -++struct ubifs_nnode; -++ -++/** -++ * struct ubifs_cnode - LEB Properties Tree common node. -++ * @parent: parent nnode -++ * @cnext: next cnode to commit -++ * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE) -++ * @iip: index in parent -++ * @level: level in the tree (zero for pnodes, greater than zero for nnodes) -++ * @num: node number -++ */ -++struct ubifs_cnode -++{ -++ struct ubifs_nnode *parent; -++ struct ubifs_cnode *cnext; -++ unsigned long flags; -++ int iip; -++ int level; -++ int num; -++}; -++ -++/** -++ * struct ubifs_pnode - LEB Properties Tree leaf node. -++ * @parent: parent nnode -++ * @cnext: next cnode to commit -++ * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE) -++ * @iip: index in parent -++ * @level: level in the tree (always zero for pnodes) -++ * @num: node number -++ * @lprops: LEB properties array -++ */ -++struct ubifs_pnode -++{ -++ struct ubifs_nnode *parent; -++ struct ubifs_cnode *cnext; -++ unsigned long flags; -++ int iip; -++ int level; -++ int num; -++ struct ubifs_lprops lprops[UBIFS_LPT_FANOUT]; -++}; -++ -++/** -++ * struct ubifs_nbranch - LEB Properties Tree internal node branch. -++ * @lnum: LEB number of child -++ * @offs: offset of child -++ * @nnode: nnode child -++ * @pnode: pnode child -++ * @cnode: cnode child -++ */ -++struct ubifs_nbranch -++{ -++ int lnum; -++ int offs; -++ union -++ { -++ struct ubifs_nnode *nnode; -++ struct ubifs_pnode *pnode; -++ struct ubifs_cnode *cnode; -++ }; -++}; -++ -++/** -++ * struct ubifs_nnode - LEB Properties Tree internal node. -++ * @parent: parent nnode -++ * @cnext: next cnode to commit -++ * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE) -++ * @iip: index in parent -++ * @level: level in the tree (always greater than zero for nnodes) -++ * @num: node number -++ * @nbranch: branches to child nodes -++ */ -++struct ubifs_nnode -++{ -++ struct ubifs_nnode *parent; -++ struct ubifs_cnode *cnext; -++ unsigned long flags; -++ int iip; -++ int level; -++ int num; -++ struct ubifs_nbranch nbranch[UBIFS_LPT_FANOUT]; -++}; -++ -++/** -++ * struct ubifs_lp_stats - statistics of eraseblocks in the main area. -++ * @empty_lebs: number of empty LEBs -++ * @taken_empty_lebs: number of taken LEBs -++ * @idx_lebs: number of indexing LEBs -++ * @total_free: total free space in bytes -++ * @total_dirty: total dirty space in bytes -++ * @total_used: total used space in bytes (includes only data LEBs) -++ * @total_dead: total dead space in bytes (includes only data LEBs) -++ * @total_dark: total dark space in bytes (includes only data LEBs) -++ */ -++struct ubifs_lp_stats { -++ int empty_lebs; -++ int taken_empty_lebs; -++ int idx_lebs; -++ long long total_free; -++ long long total_dirty; -++ long long total_used; -++ long long total_dead; -++ long long total_dark; -++}; -++ -++/** -++ * struct ubifs_zbranch - key/coordinate/length branch stored in znodes. -++ * @key: key -++ * @znode: znode address in memory -++ * @lnum: LEB number of the indexing node -++ * @offs: offset of the indexing node within @lnum -++ * @len: target node length -++ */ -++struct ubifs_zbranch -++{ -++ union ubifs_key key; -++ struct ubifs_znode *znode; -++ int lnum; -++ int offs; -++ int len; -++}; -++ -++/** -++ * struct ubifs_znode - in-memory representation of an indexing node. -++ * @parent: parent znode or NULL if it is the root -++ * @cnext: next znode to commit -++ * @flags: flags -++ * @time: last access time (seconds) -++ * @level: level of the entry in the TNC tree -++ * @child_cnt: count of child znodes -++ * @iip: index in parent's zbranch array -++ * @alt: lower bound of key range has altered i.e. child inserted at slot 0 -++ * @zbranch: array of znode branches (@c->fanout elements) -++ */ -++struct ubifs_znode -++{ -++ struct ubifs_znode *parent; -++ struct ubifs_znode *cnext; -++ unsigned long flags; -++ unsigned long time; -++ int level; -++ int child_cnt; -++ int iip; -++ int alt; -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ int lnum, offs, len; -++#endif -++ struct ubifs_zbranch zbranch[]; -++}; -++ -++/** -++ * struct ubifs_info - UBIFS file-system description data structure -++ * (per-superblock). -++ * -++ * @highest_inum: highest used inode number -++ * @max_sqnum: current global sequence number -++ * -++ * @jhead_cnt: count of journal heads -++ * @max_bud_bytes: maximum number of bytes allowed in buds -++ * -++ * @zroot: zbranch which points to the root index node and znode -++ * @ihead_lnum: LEB number of index head -++ * @ihead_offs: offset of index head -++ * -++ * @log_lebs: number of logical eraseblocks in the log -++ * @lpt_lebs: number of LEBs used for lprops table -++ * @lpt_first: first LEB of the lprops table area -++ * @lpt_last: last LEB of the lprops table area -++ * @main_lebs: count of LEBs in the main area -++ * @main_first: first LEB of the main area -++ * @default_compr: default compression type -++ * -++ * @key_hash_type: type of the key hash -++ * @key_hash: direntry key hash function -++ * @key_len: key length -++ * @fanout: fanout of the index tree (number of links per indexing node) -++ * -++ * @min_io_size: minimal input/output unit size -++ * @leb_size: logical eraseblock size in bytes -++ * @leb_cnt: count of logical eraseblocks -++ * @max_leb_cnt: maximum count of logical eraseblocks -++ * -++ * @old_idx_sz: size of index on flash -++ * @lst: lprops statistics -++ * -++ * @dead_wm: LEB dead space watermark -++ * @dark_wm: LEB dark space watermark -++ * -++ * @gc_lnum: LEB number used for garbage collection -++ * @space_bits: number of bits needed to record free or dirty space -++ * @lpt_lnum_bits: number of bits needed to record a LEB number in the LPT -++ * @lpt_offs_bits: number of bits needed to record an offset in the LPT -++ * @lpt_spc_bits: number of bits needed to space in the LPT -++ * @pcnt_bits: number of bits needed to record pnode or nnode number -++ * @lnum_bits: number of bits needed to record LEB number -++ * @nnode_sz: size of on-flash nnode -++ * @pnode_sz: size of on-flash pnode -++ * @ltab_sz: size of on-flash LPT lprops table -++ * @lsave_sz: size of on-flash LPT save table -++ * @pnode_cnt: number of pnodes -++ * @nnode_cnt: number of nnodes -++ * @lpt_hght: height of the LPT -++ * -++ * @lpt_lnum: LEB number of the root nnode of the LPT -++ * @lpt_offs: offset of the root nnode of the LPT -++ * @nhead_lnum: LEB number of LPT head -++ * @nhead_offs: offset of LPT head -++ * @big_lpt: flag that LPT is too big to write whole during commit -++ * @lpt_sz: LPT size -++ * -++ * @ltab_lnum: LEB number of LPT's own lprops table -++ * @ltab_offs: offset of LPT's own lprops table -++ * @lpt: lprops table -++ * @ltab: LPT's own lprops table -++ * @lsave_cnt: number of LEB numbers in LPT's save table -++ * @lsave_lnum: LEB number of LPT's save table -++ * @lsave_offs: offset of LPT's save table -++ * @lsave: LPT's save table -++ * @lscan_lnum: LEB number of last LPT scan -++ */ -++struct ubifs_info -++{ -++ ino_t highest_inum; -++ unsigned long long max_sqnum; -++ -++ int jhead_cnt; -++ long long max_bud_bytes; -++ -++ struct ubifs_zbranch zroot; -++ int ihead_lnum; -++ int ihead_offs; -++ -++ int log_lebs; -++ int lpt_lebs; -++ int lpt_first; -++ int lpt_last; -++ int orph_lebs; -++ int main_lebs; -++ int main_first; -++ int default_compr; -++ -++ uint8_t key_hash_type; -++ uint32_t (*key_hash)(const char *str, int len); -++ int key_len; -++ int fanout; -++ -++ int min_io_size; -++ int leb_size; -++ int leb_cnt; -++ int max_leb_cnt; -++ -++ unsigned long long old_idx_sz; -++ struct ubifs_lp_stats lst; -++ -++ int dead_wm; -++ int dark_wm; -++ -++ int gc_lnum; -++ -++ int space_bits; -++ int lpt_lnum_bits; -++ int lpt_offs_bits; -++ int lpt_spc_bits; -++ int pcnt_bits; -++ int lnum_bits; -++ int nnode_sz; -++ int pnode_sz; -++ int ltab_sz; -++ int lsave_sz; -++ int pnode_cnt; -++ int nnode_cnt; -++ int lpt_hght; -++ -++ int lpt_lnum; -++ int lpt_offs; -++ int nhead_lnum; -++ int nhead_offs; -++ int big_lpt; -++ long long lpt_sz; -++ -++ int ltab_lnum; -++ int ltab_offs; -++ struct ubifs_lprops *lpt; -++ struct ubifs_lpt_lprops *ltab; -++ int lsave_cnt; -++ int lsave_lnum; -++ int lsave_offs; -++ int *lsave; -++ int lscan_lnum; -++ -++}; -++ -++/** -++ * ubifs_idx_node_sz - return index node size. -++ * @c: the UBIFS file-system description object -++ * @child_cnt: number of children of this index node -++ */ -++static inline int ubifs_idx_node_sz(const struct ubifs_info *c, int child_cnt) -++{ -++ return UBIFS_IDX_NODE_SZ + (UBIFS_BRANCH_SZ + c->key_len) * child_cnt; -++} -++ -++/** -++ * ubifs_idx_branch - return pointer to an index branch. -++ * @c: the UBIFS file-system description object -++ * @idx: index node -++ * @bnum: branch number -++ */ -++static inline -++struct ubifs_branch *ubifs_idx_branch(const struct ubifs_info *c, -++ const struct ubifs_idx_node *idx, -++ int bnum) -++{ -++ return (struct ubifs_branch *)((void *)idx->branches + -++ (UBIFS_BRANCH_SZ + c->key_len) * bnum); -++} -++ -++/** -++ * ubifs_idx_key - return pointer to an index key. -++ * @c: the UBIFS file-system description object -++ * @idx: index node -++ */ -++static inline void *ubifs_idx_key(const struct ubifs_info *c, -++ const struct ubifs_idx_node *idx) -++{ -++ return (void *)((struct ubifs_branch *)idx->branches)->key; -++} -++ -++#endif /* __UBIFS_H__ */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/orphan.c linux-2.6.24.7/fs/ubifs/orphan.c -+--- linux-2.6.24.7.old/fs/ubifs/orphan.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/orphan.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,959 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Author: Adrian Hunter -++ */ -++ -++#include "ubifs.h" -++ -++/* -++ * An orphan is an inode number whose inode node has been committed to the index -++ * with a link count of zero. That happens when an open file is deleted -++ * (unlinked) and then a commit is run. In the normal course of events the inode -++ * would be deleted when the file is closed. However in the case of an unclean -++ * unmount, orphans need to be accounted for. After an unclean unmount, the -++ * orphans' inodes must be deleted which means either scanning the entire index -++ * looking for them, or keeping a list on flash somewhere. This unit implements -++ * the latter approach. -++ * -++ * The orphan area is a fixed number of LEBs situated between the LPT area and -++ * the main area. The number of orphan area LEBs is specified when the file -++ * system is created. The minimum number is 1. The size of the orphan area -++ * should be so that it can hold the maximum number of orphans that are expected -++ * to ever exist at one time. -++ * -++ * The number of orphans that can fit in a LEB is: -++ * -++ * (c->leb_size - UBIFS_ORPH_NODE_SZ) / sizeof(__le64) -++ * -++ * For example: a 15872 byte LEB can fit 1980 orphans so 1 LEB may be enough. -++ * -++ * Orphans are accumulated in a rb-tree. When an inode's link count drops to -++ * zero, the inode number is added to the rb-tree. It is removed from the tree -++ * when the inode is deleted. Any new orphans that are in the orphan tree when -++ * the commit is run, are written to the orphan area in 1 or more orph nodes. -++ * If the orphan area is full, it is consolidated to make space. There is -++ * always enough space because validation prevents the user from creating more -++ * than the maximum number of orphans allowed. -++ */ -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++static int dbg_check_orphans(struct ubifs_info *c); -++#else -++#define dbg_check_orphans(c) 0 -++#endif -++ -++/** -++ * ubifs_add_orphan - add an orphan. -++ * @c: UBIFS file-system description object -++ * @inum: orphan inode number -++ * -++ * Add an orphan. This function is called when an inodes link count drops to -++ * zero. -++ */ -++int ubifs_add_orphan(struct ubifs_info *c, ino_t inum) -++{ -++ struct ubifs_orphan *orphan, *o; -++ struct rb_node **p, *parent = NULL; -++ -++ orphan = kzalloc(sizeof(struct ubifs_orphan), GFP_NOFS); -++ if (!orphan) -++ return -ENOMEM; -++ orphan->inum = inum; -++ orphan->new = 1; -++ -++ spin_lock(&c->orphan_lock); -++ if (c->tot_orphans >= c->max_orphans) { -++ spin_unlock(&c->orphan_lock); -++ kfree(orphan); -++ return -ENFILE; -++ } -++ p = &c->orph_tree.rb_node; -++ while (*p) { -++ parent = *p; -++ o = rb_entry(parent, struct ubifs_orphan, rb); -++ if (inum < o->inum) -++ p = &(*p)->rb_left; -++ else if (inum > o->inum) -++ p = &(*p)->rb_right; -++ else { -++ dbg_err("orphaned twice"); -++ spin_unlock(&c->orphan_lock); -++ kfree(orphan); -++ return 0; -++ } -++ } -++ c->tot_orphans += 1; -++ c->new_orphans += 1; -++ rb_link_node(&orphan->rb, parent, p); -++ rb_insert_color(&orphan->rb, &c->orph_tree); -++ list_add_tail(&orphan->list, &c->orph_list); -++ list_add_tail(&orphan->new_list, &c->orph_new); -++ spin_unlock(&c->orphan_lock); -++ dbg_gen("ino %lu", inum); -++ return 0; -++} -++ -++/** -++ * ubifs_delete_orphan - delete an orphan. -++ * @c: UBIFS file-system description object -++ * @inum: orphan inode number -++ * -++ * Delete an orphan. This function is called when an inode is deleted. -++ */ -++void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum) -++{ -++ struct ubifs_orphan *o; -++ struct rb_node *p; -++ -++ spin_lock(&c->orphan_lock); -++ p = c->orph_tree.rb_node; -++ while (p) { -++ o = rb_entry(p, struct ubifs_orphan, rb); -++ if (inum < o->inum) -++ p = p->rb_left; -++ else if (inum > o->inum) -++ p = p->rb_right; -++ else { -++ if (o->dnext) { -++ spin_unlock(&c->orphan_lock); -++ dbg_gen("deleted twice ino %lu", inum); -++ return; -++ } -++ if (o->cnext) { -++ o->dnext = c->orph_dnext; -++ c->orph_dnext = o; -++ spin_unlock(&c->orphan_lock); -++ dbg_gen("delete later ino %lu", inum); -++ return; -++ } -++ rb_erase(p, &c->orph_tree); -++ list_del(&o->list); -++ c->tot_orphans -= 1; -++ if (o->new) { -++ list_del(&o->new_list); -++ c->new_orphans -= 1; -++ } -++ spin_unlock(&c->orphan_lock); -++ kfree(o); -++ dbg_gen("inum %lu", inum); -++ return; -++ } -++ } -++ spin_unlock(&c->orphan_lock); -++ dbg_err("missing orphan ino %lu", inum); -++ dbg_dump_stack(); -++} -++ -++/** -++ * ubifs_orphan_start_commit - start commit of orphans. -++ * @c: UBIFS file-system description object -++ * -++ * Start commit of orphans. -++ */ -++int ubifs_orphan_start_commit(struct ubifs_info *c) -++{ -++ struct ubifs_orphan *orphan, **last; -++ -++ spin_lock(&c->orphan_lock); -++ last = &c->orph_cnext; -++ list_for_each_entry(orphan, &c->orph_new, new_list) { -++ ubifs_assert(orphan->new); -++ orphan->new = 0; -++ *last = orphan; -++ last = &orphan->cnext; -++ } -++ *last = orphan->cnext; -++ c->cmt_orphans = c->new_orphans; -++ c->new_orphans = 0; -++ dbg_cmt("%d orphans to commit", c->cmt_orphans); -++ INIT_LIST_HEAD(&c->orph_new); -++ if (c->tot_orphans == 0) -++ c->no_orphs = 1; -++ else -++ c->no_orphs = 0; -++ spin_unlock(&c->orphan_lock); -++ return 0; -++} -++ -++/** -++ * avail_orphs - calculate available space. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns the number of orphans that can be written in the -++ * available space. -++ */ -++static int avail_orphs(struct ubifs_info *c) -++{ -++ int avail_lebs, avail, gap; -++ -++ avail_lebs = c->orph_lebs - (c->ohead_lnum - c->orph_first) - 1; -++ avail = avail_lebs * -++ ((c->leb_size - UBIFS_ORPH_NODE_SZ) / sizeof(__le64)); -++ gap = c->leb_size - c->ohead_offs; -++ if (gap >= UBIFS_ORPH_NODE_SZ + sizeof(__le64)) -++ avail += (gap - UBIFS_ORPH_NODE_SZ) / sizeof(__le64); -++ return avail; -++} -++ -++/** -++ * tot_avail_orphs - calculate total space. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns the number of orphans that can be written in half -++ * the total space. That leaves half the space for adding new orphans. -++ */ -++static int tot_avail_orphs(struct ubifs_info *c) -++{ -++ int avail_lebs, avail; -++ -++ avail_lebs = c->orph_lebs; -++ avail = avail_lebs * -++ ((c->leb_size - UBIFS_ORPH_NODE_SZ) / sizeof(__le64)); -++ return avail / 2; -++} -++ -++/** -++ * do_write_orph_node - write a node -++ * @c: UBIFS file-system description object -++ * @len: length of node -++ * @atomic: write atomically -++ * -++ * This function writes a node to the orphan head from the orphan buffer. If -++ * %atomic is not zero, then the write is done atomically. On success, %0 is -++ * returned, otherwise a negative error code is returned. -++ */ -++static int do_write_orph_node(struct ubifs_info *c, int len, int atomic) -++{ -++ int err = 0; -++ -++ if (atomic) { -++ ubifs_assert(c->ohead_offs == 0); -++ ubifs_prepare_node(c, c->orph_buf, len, 1); -++ len = ALIGN(len, c->min_io_size); -++ err = ubi_leb_change(c->ubi, c->ohead_lnum, c->orph_buf, len, -++ UBI_SHORTTERM); -++ } else { -++ if (c->ohead_offs == 0) { -++ /* Ensure LEB has been unmapped */ -++ err = ubifs_leb_unmap(c, c->ohead_lnum); -++ if (err) -++ return err; -++ } -++ err = ubifs_write_node(c, c->orph_buf, len, c->ohead_lnum, -++ c->ohead_offs, UBI_SHORTTERM); -++ } -++ return err; -++} -++ -++/** -++ * write_orph_node - write an orph node -++ * @c: UBIFS file-system description object -++ * @atomic: write atomically -++ * -++ * This function builds an orph node from the cnext list and writes it to the -++ * orphan head. On success, %0 is returned, otherwise a negative error code -++ * is returned. -++ */ -++static int write_orph_node(struct ubifs_info *c, int atomic) -++{ -++ struct ubifs_orphan *orphan, *cnext; -++ struct ubifs_orph_node *orph; -++ int gap, err, len, cnt, i; -++ -++ ubifs_assert(c->cmt_orphans > 0); -++ gap = c->leb_size - c->ohead_offs; -++ if (gap < UBIFS_ORPH_NODE_SZ + sizeof(__le64)) { -++ c->ohead_lnum += 1; -++ c->ohead_offs = 0; -++ gap = c->leb_size; -++ if (c->ohead_lnum > c->orph_last) { -++ /* -++ * We limit the number of orphans so that this should -++ * never happen. -++ */ -++ ubifs_err("out of space in orphan area"); -++ return -EINVAL; -++ } -++ } -++ cnt = (gap - UBIFS_ORPH_NODE_SZ) / sizeof(__le64); -++ if (cnt > c->cmt_orphans) -++ cnt = c->cmt_orphans; -++ len = UBIFS_ORPH_NODE_SZ + cnt * sizeof(__le64); -++ ubifs_assert(c->orph_buf); -++ orph = c->orph_buf; -++ orph->ch.node_type = UBIFS_ORPH_NODE; -++ spin_lock(&c->orphan_lock); -++ cnext = c->orph_cnext; -++ for (i = 0; i < cnt; i++) { -++ orphan = cnext; -++ orph->inos[i] = cpu_to_le64(orphan->inum); -++ cnext = orphan->cnext; -++ orphan->cnext = NULL; -++ } -++ c->orph_cnext = cnext; -++ c->cmt_orphans -= cnt; -++ spin_unlock(&c->orphan_lock); -++ if (c->cmt_orphans) -++ orph->cmt_no = cpu_to_le64(c->cmt_no + 1); -++ else -++ /* Mark the last node of the commit */ -++ orph->cmt_no = cpu_to_le64((c->cmt_no + 1) | (1ULL << 63)); -++ ubifs_assert(c->ohead_offs + len <= c->leb_size); -++ ubifs_assert(c->ohead_lnum >= c->orph_first); -++ ubifs_assert(c->ohead_lnum <= c->orph_last); -++ err = do_write_orph_node(c, len, atomic); -++ c->ohead_offs += ALIGN(len, c->min_io_size); -++ c->ohead_offs = ALIGN(c->ohead_offs, 8); -++ return err; -++} -++ -++/** -++ * write_orph_nodes - write orph nodes until there are no more to commit -++ * @c: UBIFS file-system description object -++ * @atomic: write atomically -++ * -++ * This function writes orph nodes for all the orphans to commit. On success, -++ * %0 is returned, otherwise a negative error code is returned. -++ */ -++static int write_orph_nodes(struct ubifs_info *c, int atomic) -++{ -++ int err; -++ -++ while (c->cmt_orphans > 0) { -++ err = write_orph_node(c, atomic); -++ if (err) -++ return err; -++ } -++ if (atomic) { -++ int lnum; -++ -++ /* Unmap any unused LEBs after consolidation */ -++ lnum = c->ohead_lnum + 1; -++ for (lnum = c->ohead_lnum + 1; lnum <= c->orph_last; lnum++) { -++ err = ubifs_leb_unmap(c, lnum); -++ if (err) -++ return err; -++ } -++ } -++ return 0; -++} -++ -++/** -++ * consolidate - consolidate the orphan area. -++ * @c: UBIFS file-system description object -++ * -++ * This function enables consolidation by putting all the orphans into the list -++ * to commit. The list is in the order that the orphans were added, and the -++ * LEBs are written atomically in order, so at no time can orphans be lost by -++ * an unclean unmount. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int consolidate(struct ubifs_info *c) -++{ -++ int tot_avail = tot_avail_orphs(c), err = 0; -++ -++ spin_lock(&c->orphan_lock); -++ dbg_cmt("there is space for %d orphans and there are %d", -++ tot_avail, c->tot_orphans); -++ if (c->tot_orphans - c->new_orphans <= tot_avail) { -++ struct ubifs_orphan *orphan, **last; -++ int cnt = 0; -++ -++ /* Change the cnext list to include all non-new orphans */ -++ last = &c->orph_cnext; -++ list_for_each_entry(orphan, &c->orph_list, list) { -++ if (orphan->new) -++ continue; -++ *last = orphan; -++ last = &orphan->cnext; -++ cnt += 1; -++ } -++ *last = orphan->cnext; -++ ubifs_assert(cnt == c->tot_orphans - c->new_orphans); -++ c->cmt_orphans = cnt; -++ c->ohead_lnum = c->orph_first; -++ c->ohead_offs = 0; -++ } else { -++ /* -++ * We limit the number of orphans so that this should -++ * never happen. -++ */ -++ ubifs_err("out of space in orphan area"); -++ err = -EINVAL; -++ } -++ spin_unlock(&c->orphan_lock); -++ return err; -++} -++ -++/** -++ * commit_orphans - commit orphans. -++ * @c: UBIFS file-system description object -++ * -++ * This function commits orphans to flash. On success, %0 is returned, -++ * otherwise a negative error code is returned. -++ */ -++static int commit_orphans(struct ubifs_info *c) -++{ -++ int avail, atomic = 0, err; -++ -++ ubifs_assert(c->cmt_orphans > 0); -++ avail = avail_orphs(c); -++ if (avail < c->cmt_orphans) { -++ /* Not enough space to write new orphans, so consolidate */ -++ err = consolidate(c); -++ if (err) -++ return err; -++ atomic = 1; -++ } -++ err = write_orph_nodes(c, atomic); -++ return err; -++} -++ -++/** -++ * erase_deleted - erase the orphans marked for deletion. -++ * @c: UBIFS file-system description object -++ * -++ * During commit, the orphans being committed cannot be deleted, so they are -++ * marked for deletion and deleted by this function. Also, the recovery -++ * adds killed orphans to the deletion list, and therefore they are deleted -++ * here too. -++ */ -++static void erase_deleted(struct ubifs_info *c) -++{ -++ struct ubifs_orphan *orphan, *dnext; -++ -++ spin_lock(&c->orphan_lock); -++ dnext = c->orph_dnext; -++ while (dnext) { -++ orphan = dnext; -++ dnext = orphan->dnext; -++ ubifs_assert(!orphan->new); -++ rb_erase(&orphan->rb, &c->orph_tree); -++ list_del(&orphan->list); -++ c->tot_orphans -= 1; -++ dbg_gen("deleting orphan ino %lu", orphan->inum); -++ kfree(orphan); -++ } -++ c->orph_dnext = NULL; -++ spin_unlock(&c->orphan_lock); -++} -++ -++/** -++ * ubifs_orphan_end_commit - end commit of orphans. -++ * @c: UBIFS file-system description object -++ * -++ * End commit of orphans. -++ */ -++int ubifs_orphan_end_commit(struct ubifs_info *c) -++{ -++ int err; -++ -++ if (c->cmt_orphans != 0) { -++ err = commit_orphans(c); -++ if (err) -++ return err; -++ } -++ erase_deleted(c); -++ err = dbg_check_orphans(c); -++ return err; -++} -++ -++/** -++ * clear_orphans - erase all LEBs used for orphans. -++ * @c: UBIFS file-system description object -++ * -++ * If recovery is not required, then the orphans from the previous session -++ * are not needed. This function locates the LEBs used to record -++ * orphans, and un-maps them. -++ */ -++static int clear_orphans(struct ubifs_info *c) -++{ -++ int lnum, err; -++ -++ for (lnum = c->orph_first; lnum <= c->orph_last; lnum++) { -++ err = ubifs_leb_unmap(c, lnum); -++ if (err) -++ return err; -++ } -++ c->ohead_lnum = c->orph_first; -++ c->ohead_offs = 0; -++ return 0; -++} -++ -++/** -++ * insert_dead_orphan - insert an orphan. -++ * @c: UBIFS file-system description object -++ * @inum: orphan inode number -++ * -++ * This function is a helper to the 'do_kill_orphans()' function. The orphan -++ * must be kept until the next commit, so it is added to the rb-tree and the -++ * deletion list. -++ */ -++static int insert_dead_orphan(struct ubifs_info *c, ino_t inum) -++{ -++ struct ubifs_orphan *orphan, *o; -++ struct rb_node **p, *parent = NULL; -++ -++ orphan = kzalloc(sizeof(struct ubifs_orphan), GFP_KERNEL); -++ if (!orphan) -++ return -ENOMEM; -++ orphan->inum = inum; -++ -++ p = &c->orph_tree.rb_node; -++ while (*p) { -++ parent = *p; -++ o = rb_entry(parent, struct ubifs_orphan, rb); -++ if (inum < o->inum) -++ p = &(*p)->rb_left; -++ else if (inum > o->inum) -++ p = &(*p)->rb_right; -++ else { -++ /* Already added - no problem */ -++ kfree(orphan); -++ return 0; -++ } -++ } -++ c->tot_orphans += 1; -++ rb_link_node(&orphan->rb, parent, p); -++ rb_insert_color(&orphan->rb, &c->orph_tree); -++ list_add_tail(&orphan->list, &c->orph_list); -++ orphan->dnext = c->orph_dnext; -++ c->orph_dnext = orphan; -++ dbg_mnt("ino %lu, new %d, tot %d", -++ inum, c->new_orphans, c->tot_orphans); -++ return 0; -++} -++ -++/** -++ * do_kill_orphans - remove orphan inodes from the index. -++ * @c: UBIFS file-system description object -++ * @sleb: scanned LEB -++ * @last_cmt_no: cmt_no of last orph node read is passed and returned here -++ * @outofdate: whether the LEB is out of date is returned here -++ * @last_flagged: whether the end orph node is encountered -++ * -++ * This function is a helper to the 'kill_orphans()' function. It goes through -++ * every orphan node in a LEB and for every inode number recorded, removes -++ * all keys for that inode from the TNC. -++ */ -++static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb, -++ unsigned long long *last_cmt_no, int *outofdate, -++ int *last_flagged) -++{ -++ struct ubifs_scan_node *snod; -++ struct ubifs_orph_node *orph; -++ unsigned long long cmt_no; -++ ino_t inum; -++ int i, n, err, first = 1; -++ -++ list_for_each_entry(snod, &sleb->nodes, list) { -++ if (snod->type != UBIFS_ORPH_NODE) { -++ ubifs_err("invalid node type %d in orphan area at " -++ "%d:%d", snod->type, sleb->lnum, snod->offs); -++ dbg_dump_node(c, snod->node); -++ return -EINVAL; -++ } -++ -++ orph = snod->node; -++ -++ /* Check commit number */ -++ cmt_no = le64_to_cpu(orph->cmt_no) & LLONG_MAX; -++ /* -++ * The commit number on the master node may be less, because -++ * of a failed commit. If there are several failed commits in a -++ * row, the commit number written on orph nodes will continue to -++ * increase (because the commit number is adjusted here) even -++ * though the commit number on the master node stays the same -++ * because the master node has not been re-written. -++ */ -++ if (cmt_no > c->cmt_no) -++ c->cmt_no = cmt_no; -++ if (cmt_no < *last_cmt_no && *last_flagged) { -++ /* -++ * The last orph node had a higher commit number and was -++ * flagged as the last written for that commit number. -++ * That makes this orph node, out of date. -++ */ -++ if (!first) { -++ ubifs_err("out of order commit number %llu in " -++ "orphan node at %d:%d", -++ cmt_no, sleb->lnum, snod->offs); -++ dbg_dump_node(c, snod->node); -++ return -EINVAL; -++ } -++ dbg_rcvry("out of date LEB %d", sleb->lnum); -++ *outofdate = 1; -++ return 0; -++ } -++ -++ if (first) -++ first = 0; -++ -++ n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3; -++ for (i = 0; i < n; i++) { -++ inum = le64_to_cpu(orph->inos[i]); -++ dbg_rcvry("deleting orphaned inode %lu", inum); -++ err = ubifs_tnc_remove_ino(c, inum); -++ if (err) -++ return err; -++ err = insert_dead_orphan(c, inum); -++ if (err) -++ return err; -++ } -++ -++ *last_cmt_no = cmt_no; -++ if (le64_to_cpu(orph->cmt_no) & (1ULL << 63)) { -++ dbg_rcvry("last orph node for commit %llu at %d:%d", -++ cmt_no, sleb->lnum, snod->offs); -++ *last_flagged = 1; -++ } else -++ *last_flagged = 0; -++ } -++ -++ return 0; -++} -++ -++/** -++ * kill_orphans - remove all orphan inodes from the index. -++ * @c: UBIFS file-system description object -++ * -++ * If recovery is required, then orphan inodes recorded during the previous -++ * session (which ended with an unclean unmount) must be deleted from the index. -++ * This is done by updating the TNC, but since the index is not updated until -++ * the next commit, the LEBs where the orphan information is recorded are not -++ * erased until the next commit. -++ */ -++static int kill_orphans(struct ubifs_info *c) -++{ -++ unsigned long long last_cmt_no = 0; -++ int lnum, err = 0, outofdate = 0, last_flagged = 0; -++ -++ c->ohead_lnum = c->orph_first; -++ c->ohead_offs = 0; -++ /* Check no-orphans flag and skip this if no orphans */ -++ if (c->no_orphs) { -++ dbg_rcvry("no orphans"); -++ return 0; -++ } -++ /* -++ * Orph nodes always start at c->orph_first and are written to each -++ * successive LEB in turn. Generally unused LEBs will have been unmapped -++ * but may contain out of date orph nodes if the unmap didn't go -++ * through. In addition, the last orph node written for each commit is -++ * marked (top bit of orph->cmt_no is set to 1). It is possible that -++ * there are orph nodes from the next commit (i.e. the commit did not -++ * complete successfully). In that case, no orphans will have been lost -++ * due to the way that orphans are written, and any orphans added will -++ * be valid orphans anyway and so can be deleted. -++ */ -++ for (lnum = c->orph_first; lnum <= c->orph_last; lnum++) { -++ struct ubifs_scan_leb *sleb; -++ -++ dbg_rcvry("LEB %d", lnum); -++ sleb = ubifs_scan(c, lnum, 0, c->sbuf); -++ if (IS_ERR(sleb)) { -++ sleb = ubifs_recover_leb(c, lnum, 0, c->sbuf, 0); -++ if (IS_ERR(sleb)) { -++ err = PTR_ERR(sleb); -++ break; -++ } -++ } -++ err = do_kill_orphans(c, sleb, &last_cmt_no, &outofdate, -++ &last_flagged); -++ if (err || outofdate) { -++ ubifs_scan_destroy(sleb); -++ break; -++ } -++ if (sleb->endpt) { -++ c->ohead_lnum = lnum; -++ c->ohead_offs = sleb->endpt; -++ } -++ ubifs_scan_destroy(sleb); -++ } -++ return err; -++} -++ -++/** -++ * ubifs_mount_orphans - delete orphan inodes and erase LEBs that recorded them. -++ * @c: UBIFS file-system description object -++ * @unclean: %1 => recover from unclean unmount -++ * -++ * This function is called when mounting to erase orphans from the previous -++ * session. If UBIFS was not unmounted cleanly, then the inodes recorded as -++ * orphans are deleted. -++ */ -++int ubifs_mount_orphans(struct ubifs_info *c, int unclean) -++{ -++ int err = 0; -++ -++ c->max_orphans = tot_avail_orphs(c); -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ c->orph_buf = kmalloc(c->leb_size, GFP_KERNEL); -++#else -++ c->orph_buf = vmalloc(c->leb_size); -++#endif -++ if (!c->orph_buf) -++ return -ENOMEM; -++ -++ if (unclean) -++ err = kill_orphans(c); -++ else -++ err = clear_orphans(c); -++ -++ return err; -++} -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ -++struct check_orphan { -++ struct rb_node rb; -++ ino_t inum; -++}; -++ -++struct check_info { -++ unsigned long last_ino; -++ unsigned long tot_inos; -++ unsigned long missing; -++ unsigned long long leaf_cnt; -++ struct ubifs_ino_node *node; -++ struct rb_root root; -++}; -++ -++static int dbg_find_orphan(struct ubifs_info *c, ino_t inum) -++{ -++ struct ubifs_orphan *o; -++ struct rb_node *p; -++ -++ spin_lock(&c->orphan_lock); -++ p = c->orph_tree.rb_node; -++ while (p) { -++ o = rb_entry(p, struct ubifs_orphan, rb); -++ if (inum < o->inum) -++ p = p->rb_left; -++ else if (inum > o->inum) -++ p = p->rb_right; -++ else { -++ spin_unlock(&c->orphan_lock); -++ return 1; -++ } -++ } -++ spin_unlock(&c->orphan_lock); -++ return 0; -++} -++ -++static int dbg_ins_check_orphan(struct rb_root *root, ino_t inum) -++{ -++ struct check_orphan *orphan, *o; -++ struct rb_node **p, *parent = NULL; -++ -++ orphan = kzalloc(sizeof(struct check_orphan), GFP_NOFS); -++ if (!orphan) -++ return -ENOMEM; -++ orphan->inum = inum; -++ -++ p = &root->rb_node; -++ while (*p) { -++ parent = *p; -++ o = rb_entry(parent, struct check_orphan, rb); -++ if (inum < o->inum) -++ p = &(*p)->rb_left; -++ else if (inum > o->inum) -++ p = &(*p)->rb_right; -++ else { -++ kfree(orphan); -++ return 0; -++ } -++ } -++ rb_link_node(&orphan->rb, parent, p); -++ rb_insert_color(&orphan->rb, root); -++ return 0; -++} -++ -++static int dbg_find_check_orphan(struct rb_root *root, ino_t inum) -++{ -++ struct check_orphan *o; -++ struct rb_node *p; -++ -++ p = root->rb_node; -++ while (p) { -++ o = rb_entry(p, struct check_orphan, rb); -++ if (inum < o->inum) -++ p = p->rb_left; -++ else if (inum > o->inum) -++ p = p->rb_right; -++ else -++ return 1; -++ } -++ return 0; -++} -++ -++static void dbg_free_check_tree(struct rb_root *root) -++{ -++ struct rb_node *this = root->rb_node; -++ struct check_orphan *o; -++ -++ while (this) { -++ if (this->rb_left) { -++ this = this->rb_left; -++ continue; -++ } else if (this->rb_right) { -++ this = this->rb_right; -++ continue; -++ } -++ o = rb_entry(this, struct check_orphan, rb); -++ this = rb_parent(this); -++ if (this) { -++ if (this->rb_left == &o->rb) -++ this->rb_left = NULL; -++ else -++ this->rb_right = NULL; -++ } -++ kfree(o); -++ } -++} -++ -++static int dbg_orphan_check(struct ubifs_info *c, struct ubifs_zbranch *zbr, -++ void *priv) -++{ -++ struct check_info *ci = priv; -++ ino_t inum; -++ int err; -++ -++ inum = key_ino(c, &zbr->key); -++ if (inum != ci->last_ino) { -++ /* Lowest node type is the inode node, so it comes first */ -++ if (key_type(c, &zbr->key) != UBIFS_INO_KEY) -++ ubifs_err("found orphan node ino %lu, type %d", inum, -++ key_type(c, &zbr->key)); -++ ci->last_ino = inum; -++ ci->tot_inos += 1; -++ err = dbg_read_leaf_nolock(c, zbr, ci->node); -++ if (err) { -++ ubifs_err("node read failed, error %d", err); -++ return err; -++ } -++ if (ci->node->nlink == 0) -++ /* Must be recorded as an orphan */ -++ if (!dbg_find_check_orphan(&ci->root, inum) && -++ !dbg_find_orphan(c, inum)) { -++ ubifs_err("missing orphan, ino %lu", inum); -++ ci->missing += 1; -++ } -++ } -++ ci->leaf_cnt += 1; -++ return 0; -++} -++ -++static int dbg_read_orphans(struct check_info *ci, struct ubifs_scan_leb *sleb) -++{ -++ struct ubifs_scan_node *snod; -++ struct ubifs_orph_node *orph; -++ ino_t inum; -++ int i, n, err; -++ -++ list_for_each_entry(snod, &sleb->nodes, list) { -++ cond_resched(); -++ if (snod->type != UBIFS_ORPH_NODE) -++ continue; -++ orph = snod->node; -++ n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3; -++ for (i = 0; i < n; i++) { -++ inum = le64_to_cpu(orph->inos[i]); -++ err = dbg_ins_check_orphan(&ci->root, inum); -++ if (err) -++ return err; -++ } -++ } -++ return 0; -++} -++ -++static int dbg_scan_orphans(struct ubifs_info *c, struct check_info *ci) -++{ -++ int lnum, err = 0; -++ -++ /* Check no-orphans flag and skip this if no orphans */ -++ if (c->no_orphs) -++ return 0; -++ -++ for (lnum = c->orph_first; lnum <= c->orph_last; lnum++) { -++ struct ubifs_scan_leb *sleb; -++ -++ sleb = ubifs_scan(c, lnum, 0, c->dbg_buf); -++ if (IS_ERR(sleb)) { -++ err = PTR_ERR(sleb); -++ break; -++ } -++ -++ err = dbg_read_orphans(ci, sleb); -++ ubifs_scan_destroy(sleb); -++ if (err) -++ break; -++ } -++ -++ return err; -++} -++ -++static int dbg_check_orphans(struct ubifs_info *c) -++{ -++ struct check_info ci; -++ int err; -++ -++ if (!(ubifs_chk_flags & UBIFS_CHK_ORPH)) -++ return 0; -++ -++ ci.last_ino = 0; -++ ci.tot_inos = 0; -++ ci.missing = 0; -++ ci.leaf_cnt = 0; -++ ci.root = RB_ROOT; -++ ci.node = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS); -++ if (!ci.node) { -++ ubifs_err("out of memory"); -++ return -ENOMEM; -++ } -++ -++ err = dbg_scan_orphans(c, &ci); -++ if (err) -++ goto out; -++ -++ err = dbg_walk_index(c, &dbg_orphan_check, NULL, &ci); -++ if (err) { -++ ubifs_err("cannot scan TNC, error %d", err); -++ goto out; -++ } -++ -++ if (ci.missing) { -++ ubifs_err("%lu missing orphan(s)", ci.missing); -++ err = -EINVAL; -++ goto out; -++ } -++ -++ dbg_cmt("last inode number is %lu", ci.last_ino); -++ dbg_cmt("total number of inodes is %lu", ci.tot_inos); -++ dbg_cmt("total number of leaf nodes is %llu", ci.leaf_cnt); -++ -++out: -++ dbg_free_check_tree(&ci.root); -++ kfree(ci.node); -++ return err; -++} -++ -++#endif /* CONFIG_UBIFS_FS_DEBUG */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/recovery.c linux-2.6.24.7/fs/ubifs/recovery.c -+--- linux-2.6.24.7.old/fs/ubifs/recovery.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/recovery.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1524 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Adrian Hunter -++ * Artem Bityutskiy (Битюцкий Ðртём) -++ */ -++ -++/* -++ * This file implements functions needed to recover from unclean un-mounts. -++ * When UBIFS is mounted, it checks a flag on the master node to determine if -++ * an un-mount was completed sucessfully. If not, the process of mounting -++ * incorparates additional checking and fixing of on-flash data structures. -++ * UBIFS always cleans away all remnants of an unclean un-mount, so that -++ * errors do not accumulate. However UBIFS defers recovery if it is mounted -++ * read-only, and the flash is not modified in that case. -++ */ -++ -++#include -++#include "ubifs.h" -++ -++/** -++ * is_empty - determine whether a buffer is empty (contains all 0xff). -++ * @buf: buffer to clean -++ * @len: length of buffer -++ * -++ * This function returns %1 if the buffer is empty (contains all 0xff) otherwise -++ * %0 is returned. -++ */ -++static int is_empty(void *buf, int len) -++{ -++ uint8_t *p = buf; -++ int i; -++ -++ for (i = 0; i < len; i++) -++ if (*p++ != 0xff) -++ return 0; -++ return 1; -++} -++ -++/** -++ * get_master_node - get the last valid master node allowing for corruption. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number -++ * @pbuf: buffer containing the LEB read, is returned here -++ * @mst: master node, if found, is returned here -++ * @cor: corruption, if found, is returned here -++ * -++ * This function allocates a buffer, reads the LEB into it, and finds and -++ * returns the last valid master node allowing for one area of corruption. -++ * The corrupt area, if there is one, must be consistent with the assumption -++ * that it is the result of an unclean unmount while the master node was being -++ * written. Under those circumstances, it is valid to use the previously written -++ * master node. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int get_master_node(const struct ubifs_info *c, int lnum, void **pbuf, -++ struct ubifs_mst_node **mst, void **cor) -++{ -++ const int sz = c->mst_node_alsz; -++ int err, offs, len; -++ void *sbuf, *buf; -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ sbuf = kmalloc(c->leb_size, GFP_KERNEL); -++#else -++ sbuf = vmalloc(c->leb_size); -++#endif -++ if (!sbuf) -++ return -ENOMEM; -++ -++ err = ubi_read(c->ubi, lnum, sbuf, 0, c->leb_size); -++ if (err && err != -EBADMSG) -++ goto out_free; -++ -++ /* Find the first position that is definitely not a node */ -++ offs = 0; -++ buf = sbuf; -++ len = c->leb_size; -++ while (offs + UBIFS_MST_NODE_SZ <= c->leb_size) { -++ struct ubifs_ch *ch = buf; -++ -++ if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC) -++ break; -++ offs += sz; -++ buf += sz; -++ len -= sz; -++ } -++ /* See if there was a valid master node before that */ -++ if (offs) { -++ int ret; -++ -++ offs -= sz; -++ buf -= sz; -++ len += sz; -++ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1); -++ if (ret != SCANNED_A_NODE && offs) { -++ /* Could have been corruption so check one place back */ -++ offs -= sz; -++ buf -= sz; -++ len += sz; -++ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1); -++ if (ret != SCANNED_A_NODE) -++ /* -++ * We accept only one area of corruption because -++ * we are assuming that it was caused while -++ * trying to write a master node. -++ */ -++ goto out_err; -++ } -++ if (ret == SCANNED_A_NODE) { -++ struct ubifs_ch *ch = buf; -++ -++ if (ch->node_type != UBIFS_MST_NODE) -++ goto out_err; -++ dbg_rcvry("found a master node at %d:%d", lnum, offs); -++ *mst = buf; -++ offs += sz; -++ buf += sz; -++ len -= sz; -++ } -++ } -++ /* Check for corruption */ -++ if (offs < c->leb_size) { -++ if (!is_empty(buf, min_t(int, len, sz))) { -++ *cor = buf; -++ dbg_rcvry("found corruption at %d:%d", lnum, offs); -++ } -++ offs += sz; -++ buf += sz; -++ len -= sz; -++ } -++ /* Check remaining empty space */ -++ if (offs < c->leb_size) -++ if (!is_empty(buf, len)) -++ goto out_err; -++ *pbuf = sbuf; -++ return 0; -++ -++out_err: -++ err = -EINVAL; -++out_free: -++ vfree(sbuf); -++ *mst = NULL; -++ *cor = NULL; -++ return err; -++} -++ -++/** -++ * write_rcvrd_mst_node - write recovered master node. -++ * @c: UBIFS file-system description object -++ * @mst: master node -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int write_rcvrd_mst_node(struct ubifs_info *c, -++ struct ubifs_mst_node *mst) -++{ -++ int err = 0, lnum = UBIFS_MST_LNUM, sz = c->mst_node_alsz; -++ uint32_t save_flags; -++ -++ dbg_rcvry("recovery"); -++ -++ save_flags = mst->flags; -++ mst->flags = cpu_to_le32(le32_to_cpu(mst->flags) | UBIFS_MST_RCVRY); -++ -++ ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1); -++ err = ubi_leb_change(c->ubi, lnum, mst, sz, UBI_SHORTTERM); -++ if (err) -++ goto out; -++ err = ubi_leb_change(c->ubi, lnum + 1, mst, sz, UBI_SHORTTERM); -++ if (err) -++ goto out; -++out: -++ mst->flags = save_flags; -++ return err; -++} -++ -++/** -++ * ubifs_recover_master_node - recover the master node. -++ * @c: UBIFS file-system description object -++ * -++ * This function recovers the master node from corruption that may occur due to -++ * an unclean unmount. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_recover_master_node(struct ubifs_info *c) -++{ -++ void *buf1 = NULL, *buf2 = NULL, *cor1 = NULL, *cor2 = NULL; -++ struct ubifs_mst_node *mst1 = NULL, *mst2 = NULL, *mst; -++ const int sz = c->mst_node_alsz; -++ int err, offs1, offs2; -++ -++ dbg_rcvry("recovery"); -++ -++ err = get_master_node(c, UBIFS_MST_LNUM, &buf1, &mst1, &cor1); -++ if (err) -++ goto out_free; -++ -++ err = get_master_node(c, UBIFS_MST_LNUM + 1, &buf2, &mst2, &cor2); -++ if (err) -++ goto out_free; -++ -++ if (mst1) { -++ offs1 = (void *)mst1 - buf1; -++ if ((le32_to_cpu(mst1->flags) & UBIFS_MST_RCVRY) && -++ (offs1 == 0 && !cor1)) { -++ /* -++ * mst1 was written by recovery at offset 0 with no -++ * corruption. -++ */ -++ dbg_rcvry("recovery recovery"); -++ mst = mst1; -++ } else if (mst2) { -++ offs2 = (void *)mst2 - buf2; -++ if (offs1 == offs2) { -++ /* Same offset, so must be the same */ -++ if (memcmp((void *)mst1 + UBIFS_CH_SZ, -++ (void *)mst2 + UBIFS_CH_SZ, -++ UBIFS_MST_NODE_SZ - UBIFS_CH_SZ)) -++ goto out_err; -++ mst = mst1; -++ } else if (offs2 + sz == offs1) { -++ /* 1st LEB was written, 2nd was not */ -++ if (cor1) -++ goto out_err; -++ mst = mst1; -++ } else if (offs1 == 0 && offs2 + sz >= c->leb_size) { -++ /* 1st LEB was unmapped and written, 2nd not */ -++ if (cor1) -++ goto out_err; -++ mst = mst1; -++ } else -++ goto out_err; -++ } else { -++ /* -++ * 2nd LEB was unmapped and about to be written, so -++ * there must be only one master node in the first LEB -++ * and no corruption. -++ */ -++ if (offs1 != 0 || cor1) -++ goto out_err; -++ mst = mst1; -++ } -++ } else { -++ if (!mst2) -++ goto out_err; -++ /* -++ * 1st LEB was unmapped and about to be written, so there must -++ * be no room left in 2nd LEB. -++ */ -++ offs2 = (void *)mst2 - buf2; -++ if (offs2 + sz + sz <= c->leb_size) -++ goto out_err; -++ mst = mst2; -++ } -++ -++ dbg_rcvry("recovered master node from LEB %d", -++ (mst == mst1 ? UBIFS_MST_LNUM : UBIFS_MST_LNUM + 1)); -++ -++ memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ); -++ -++ if ((c->vfs_sb->s_flags & MS_RDONLY)) { -++ /* Read-only mode. Keep a copy for switching to rw mode */ -++ c->rcvrd_mst_node = kmalloc(sz, GFP_KERNEL); -++ if (!c->rcvrd_mst_node) { -++ err = -ENOMEM; -++ goto out_free; -++ } -++ memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ); -++ } else { -++ /* Write the recovered master node */ -++ c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1; -++ err = write_rcvrd_mst_node(c, c->mst_node); -++ if (err) -++ goto out_free; -++ } -++ -++ vfree(buf2); -++ vfree(buf1); -++ -++ return 0; -++ -++out_err: -++ err = -EINVAL; -++out_free: -++ ubifs_err("failed to recover master node"); -++ if (mst1) { -++ dbg_err("dumping first master node"); -++ dbg_dump_node(c, mst1); -++ } -++ if (mst2) { -++ dbg_err("dumping second master node"); -++ dbg_dump_node(c, mst2); -++ } -++ vfree(buf2); -++ vfree(buf1); -++ return err; -++} -++ -++/** -++ * ubifs_write_rcvrd_mst_node - write the recovered master node. -++ * @c: UBIFS file-system description object -++ * -++ * This function writes the master node that was recovered during mounting in -++ * read-only mode and must now be written because we are remounting rw. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_write_rcvrd_mst_node(struct ubifs_info *c) -++{ -++ int err; -++ -++ if (!c->rcvrd_mst_node) -++ return 0; -++ c->rcvrd_mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); -++ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); -++ err = write_rcvrd_mst_node(c, c->rcvrd_mst_node); -++ if (err) -++ return err; -++ kfree(c->rcvrd_mst_node); -++ c->rcvrd_mst_node = NULL; -++ return 0; -++} -++ -++/** -++ * is_last_write - determine if an offset was in the last write to a LEB. -++ * @c: UBIFS file-system description object -++ * @buf: buffer to check -++ * @offs: offset to check -++ * -++ * This function returns %1 if @offs was in the last write to the LEB whose data -++ * is in @buf, otherwise %0 is returned. The determination is made by checking -++ * for subsequent empty space starting from the next min_io_size boundary (or a -++ * bit less than the common header size if min_io_size is one). -++ */ -++static int is_last_write(const struct ubifs_info *c, void *buf, int offs) -++{ -++ int empty_offs; -++ int check_len; -++ uint8_t *p; -++ -++ if (c->min_io_size == 1) { -++ check_len = c->leb_size - offs; -++ p = buf + check_len; -++ for (; check_len > 0; check_len--) -++ if (*--p != 0xff) -++ break; -++ /* -++ * 'check_len' is the size of the corruption which cannot be -++ * more than the size of 1 node if it was caused by an unclean -++ * unmount. -++ */ -++ if (check_len > UBIFS_MAX_NODE_SZ) -++ return 0; -++ return 1; -++ } -++ -++ /* -++ * Round up to the next c->min_io_size boundary i.e. 'offs' is in the -++ * last wbuf written. After that should be empty space. -++ */ -++ empty_offs = ALIGN(offs + 1, c->min_io_size); -++ check_len = c->leb_size - empty_offs; -++ p = buf + empty_offs - offs; -++ -++ for (; check_len > 0; check_len--) -++ if (*p++ != 0xff) -++ return 0; -++ return 1; -++} -++ -++/** -++ * clean_buf - clean the data from an LEB sitting in a buffer. -++ * @c: UBIFS file-system description object -++ * @buf: buffer to clean -++ * @lnum: LEB number to clean -++ * @offs: offset from which to clean -++ * @len: length of buffer -++ * -++ * This function pads up to the next min_io_size boundary (if there is one) and -++ * sets empty space to all 0xff. @buf, @offs and @len are updated to the next -++ * min_io_size boundary (if there is one). -++ */ -++static void clean_buf(const struct ubifs_info *c, void **buf, int lnum, -++ int *offs, int *len) -++{ -++ int empty_offs, pad_len; -++ -++ lnum = lnum; -++ dbg_rcvry("cleaning corruption at %d:%d", lnum, *offs); -++ -++ if (c->min_io_size == 1) { -++ memset(*buf, 0xff, c->leb_size - *offs); -++ return; -++ } -++ -++ ubifs_assert(!(*offs & 7)); -++ empty_offs = ALIGN(*offs, c->min_io_size); -++ pad_len = empty_offs - *offs; -++ ubifs_pad(c, *buf, pad_len); -++ *offs += pad_len; -++ *buf += pad_len; -++ *len -= pad_len; -++ memset(*buf, 0xff, c->leb_size - empty_offs); -++} -++ -++/** -++ * no_more_nodes - determine if there are no more nodes in a buffer. -++ * @c: UBIFS file-system description object -++ * @buf: buffer to check -++ * @len: length of buffer -++ * @lnum: LEB number of the LEB from which @buf was read -++ * @offs: offset from which @buf was read -++ * -++ * This function scans @buf for more nodes and returns %0 is a node is found and -++ * %1 if no more nodes are found. -++ */ -++static int no_more_nodes(const struct ubifs_info *c, void *buf, int len, -++ int lnum, int offs) -++{ -++ int skip, next_offs = 0; -++ -++ if (len > UBIFS_DATA_NODE_SZ) { -++ struct ubifs_ch *ch = buf; -++ int dlen = le32_to_cpu(ch->len); -++ -++ if (ch->node_type == UBIFS_DATA_NODE && dlen >= UBIFS_CH_SZ && -++ dlen <= UBIFS_MAX_DATA_NODE_SZ) -++ /* The corrupt node looks like a data node */ -++ next_offs = ALIGN(offs + dlen, 8); -++ } -++ -++ if (c->min_io_size == 1) -++ skip = 8; -++ else -++ skip = ALIGN(offs + 1, c->min_io_size) - offs; -++ -++ offs += skip; -++ buf += skip; -++ len -= skip; -++ while (len > 8) { -++ struct ubifs_ch *ch = buf; -++ uint32_t magic = le32_to_cpu(ch->magic); -++ int ret; -++ -++ if (magic == UBIFS_NODE_MAGIC) { -++ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1); -++ if (ret == SCANNED_A_NODE || ret > 0) { -++ /* -++ * There is a small chance this is just data in -++ * a data node, so check that possibility. e.g. -++ * this is part of a file that itself contains -++ * a UBIFS image. -++ */ -++ if (next_offs && offs + le32_to_cpu(ch->len) <= -++ next_offs) -++ continue; -++ dbg_rcvry("unexpected node at %d:%d", lnum, -++ offs); -++ return 0; -++ } -++ } -++ offs += 8; -++ buf += 8; -++ len -= 8; -++ } -++ return 1; -++} -++ -++/** -++ * fix_unclean_leb - fix an unclean LEB. -++ * @c: UBIFS file-system description object -++ * @sleb: scanned LEB information -++ * @start: offset where scan started -++ */ -++static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb, -++ int start) -++{ -++ int lnum = sleb->lnum, endpt = start; -++ -++ /* Get the end offset of the last node we are keeping */ -++ if (!list_empty(&sleb->nodes)) { -++ struct ubifs_scan_node *snod; -++ -++ snod = list_entry(sleb->nodes.prev, -++ struct ubifs_scan_node, list); -++ endpt = snod->offs + snod->len; -++ } -++ -++ if ((c->vfs_sb->s_flags & MS_RDONLY) && !c->remounting_rw) { -++ /* Add to recovery list */ -++ struct ubifs_unclean_leb *ucleb; -++ -++ dbg_rcvry("need to fix LEB %d start %d endpt %d", -++ lnum, start, sleb->endpt); -++ ucleb = kzalloc(sizeof(struct ubifs_unclean_leb), GFP_NOFS); -++ if (!ucleb) -++ return -ENOMEM; -++ ucleb->lnum = lnum; -++ ucleb->endpt = endpt; -++ list_add_tail(&ucleb->list, &c->unclean_leb_list); -++ } else { -++ /* Write the fixed LEB back to flash */ -++ int err; -++ -++ dbg_rcvry("fixing LEB %d start %d endpt %d", -++ lnum, start, sleb->endpt); -++ if (endpt == 0) { -++ err = ubifs_leb_unmap(c, lnum); -++ if (err) -++ return err; -++ } else { -++ int len = ALIGN(endpt, c->min_io_size); -++ -++ if (start) { -++ err = ubi_read(c->ubi, lnum, sleb->buf, 0, -++ start); -++ if (err) -++ return err; -++ } -++ /* Pad to min_io_size */ -++ if (len > endpt) { -++ int pad_len = len - ALIGN(endpt, 8); -++ -++ if (pad_len > 0) { -++ void *buf = sleb->buf + len - pad_len; -++ -++ ubifs_pad(c, buf, pad_len); -++ } -++ } -++ err = ubi_leb_change(c->ubi, lnum, sleb->buf, len, -++ UBI_UNKNOWN); -++ if (err) -++ return err; -++ } -++ } -++ return 0; -++} -++ -++/** -++ * drop_incomplete_group - drop nodes from an incomplete group. -++ * @sleb: scanned LEB information -++ * @offs: offset of dropped nodes is returned here -++ * -++ * This function returns %1 if nodes are dropped and %0 otherwise. -++ */ -++static int drop_incomplete_group(struct ubifs_scan_leb *sleb, int *offs) -++{ -++ int dropped = 0; -++ -++ while (!list_empty(&sleb->nodes)) { -++ struct ubifs_scan_node *snod; -++ struct ubifs_ch *ch; -++ -++ snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, -++ list); -++ ch = snod->node; -++ if (ch->group_type != UBIFS_IN_NODE_GROUP) -++ return dropped; -++ dbg_rcvry("dropping node at %d:%d", sleb->lnum, snod->offs); -++ *offs = snod->offs; -++ list_del(&snod->list); -++ kfree(snod); -++ sleb->nodes_cnt -= 1; -++ dropped = 1; -++ } -++ return dropped; -++} -++ -++/** -++ * ubifs_recover_leb - scan and recover a LEB. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number -++ * @offs: offset -++ * @sbuf: LEB-sized buffer to use -++ * @grouped: nodes may be grouped for recovery -++ * -++ * This function does a scan of a LEB, but caters for errors that might have -++ * been caused by the unclean unmount from which we are attempting to recover. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, -++ int offs, void *sbuf, int grouped) -++{ -++ int err, len = c->leb_size - offs, need_clean = 0, quiet = 1; -++ int empty_chkd = 0, start = offs; -++ struct ubifs_scan_leb *sleb; -++ void *buf = sbuf + offs; -++ -++ dbg_rcvry("%d:%d", lnum, offs); -++ -++ sleb = ubifs_start_scan(c, lnum, offs, sbuf); -++ if (IS_ERR(sleb)) -++ return sleb; -++ -++ if (sleb->ecc) -++ need_clean = 1; -++ -++ while (len >= 8) { -++ int ret; -++ -++ dbg_scan("look at LEB %d:%d (%d bytes left)", -++ lnum, offs, len); -++ -++ cond_resched(); -++ -++ /* -++ * Scan quietly until there is an error from which we cannot -++ * recover -++ */ -++ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, quiet); -++ -++ if (ret == SCANNED_A_NODE) { -++ /* A valid node, and not a padding node */ -++ struct ubifs_ch *ch = buf; -++ int node_len; -++ -++ err = ubifs_add_snod(c, sleb, buf, offs); -++ if (err) -++ goto error; -++ node_len = ALIGN(le32_to_cpu(ch->len), 8); -++ offs += node_len; -++ buf += node_len; -++ len -= node_len; -++ continue; -++ } -++ -++ if (ret > 0) { -++ /* Padding bytes or a valid padding node */ -++ offs += ret; -++ buf += ret; -++ len -= ret; -++ continue; -++ } -++ -++ if (ret == SCANNED_EMPTY_SPACE) { -++ if (!is_empty(buf, len)) { -++ if (!is_last_write(c, buf, offs)) -++ break; -++ clean_buf(c, &buf, lnum, &offs, &len); -++ need_clean = 1; -++ } -++ empty_chkd = 1; -++ break; -++ } -++ -++ if (ret == SCANNED_GARBAGE || ret == SCANNED_A_BAD_PAD_NODE) -++ if (is_last_write(c, buf, offs)) { -++ clean_buf(c, &buf, lnum, &offs, &len); -++ need_clean = 1; -++ empty_chkd = 1; -++ break; -++ } -++ -++ if (ret == SCANNED_A_CORRUPT_NODE) -++ if (no_more_nodes(c, buf, len, lnum, offs)) { -++ clean_buf(c, &buf, lnum, &offs, &len); -++ need_clean = 1; -++ empty_chkd = 1; -++ break; -++ } -++ -++ if (quiet) { -++ /* Redo the last scan but noisily */ -++ quiet = 0; -++ continue; -++ } -++ -++ switch (ret) { -++ case SCANNED_GARBAGE: -++ dbg_err("garbage"); -++ goto corrupted; -++ case SCANNED_A_CORRUPT_NODE: -++ case SCANNED_A_BAD_PAD_NODE: -++ dbg_err("bad node"); -++ goto corrupted; -++ default: -++ dbg_err("unknown"); -++ goto corrupted; -++ } -++ } -++ -++ if (!empty_chkd && !is_empty(buf, len)) { -++ if (is_last_write(c, buf, offs)) { -++ clean_buf(c, &buf, lnum, &offs, &len); -++ need_clean = 1; -++ } else { -++ ubifs_err("corrupt empty space at LEB %d:%d", -++ lnum, offs); -++ goto corrupted; -++ } -++ } -++ -++ /* Drop nodes from incomplete group */ -++ if (grouped && drop_incomplete_group(sleb, &offs)) { -++ buf = sbuf + offs; -++ len = c->leb_size - offs; -++ clean_buf(c, &buf, lnum, &offs, &len); -++ need_clean = 1; -++ } -++ -++ if (offs % c->min_io_size) { -++ clean_buf(c, &buf, lnum, &offs, &len); -++ need_clean = 1; -++ } -++ -++ ubifs_end_scan(c, sleb, lnum, offs); -++ -++ if (need_clean) { -++ err = fix_unclean_leb(c, sleb, start); -++ if (err) -++ goto error; -++ } -++ -++ return sleb; -++ -++corrupted: -++ ubifs_scanned_corruption(c, lnum, offs, buf); -++ err = -EUCLEAN; -++error: -++ ubifs_err("LEB %d scanning failed", lnum); -++ ubifs_scan_destroy(sleb); -++ return ERR_PTR(err); -++} -++ -++/** -++ * get_cs_sqnum - get commit start sequence number. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number of commit start node -++ * @offs: offset of commit start node -++ * @cs_sqnum: commit start sequence number is returned here -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int get_cs_sqnum(struct ubifs_info *c, int lnum, int offs, -++ unsigned long long *cs_sqnum) -++{ -++ struct ubifs_cs_node *cs_node = NULL; -++ int err, ret; -++ -++ dbg_rcvry("at %d:%d", lnum, offs); -++ cs_node = kmalloc(UBIFS_CS_NODE_SZ, GFP_KERNEL); -++ if (!cs_node) -++ return -ENOMEM; -++ if (c->leb_size - offs < UBIFS_CS_NODE_SZ) -++ goto out_err; -++ err = ubi_read(c->ubi, lnum, (void *)cs_node, offs, UBIFS_CS_NODE_SZ); -++ if (err && err != -EBADMSG) -++ goto out_free; -++ ret = ubifs_scan_a_node(c, cs_node, UBIFS_CS_NODE_SZ, lnum, offs, 0); -++ if (ret != SCANNED_A_NODE) { -++ dbg_err("Not a valid node"); -++ goto out_err; -++ } -++ if (cs_node->ch.node_type != UBIFS_CS_NODE) { -++ dbg_err("Node a CS node, type is %d", cs_node->ch.node_type); -++ goto out_err; -++ } -++ if (le64_to_cpu(cs_node->cmt_no) != c->cmt_no) { -++ dbg_err("CS node cmt_no %llu != current cmt_no %llu", -++ (unsigned long long)le64_to_cpu(cs_node->cmt_no), -++ c->cmt_no); -++ goto out_err; -++ } -++ *cs_sqnum = le64_to_cpu(cs_node->ch.sqnum); -++ dbg_rcvry("commit start sqnum %llu", *cs_sqnum); -++ kfree(cs_node); -++ return 0; -++ -++out_err: -++ err = -EINVAL; -++out_free: -++ ubifs_err("failed to get CS sqnum"); -++ kfree(cs_node); -++ return err; -++} -++ -++/** -++ * ubifs_recover_log_leb - scan and recover a log LEB. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number -++ * @offs: offset -++ * @sbuf: LEB-sized buffer to use -++ * -++ * This function does a scan of a LEB, but caters for errors that might have -++ * been caused by the unclean unmount from which we are attempting to recover. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum, -++ int offs, void *sbuf) -++{ -++ struct ubifs_scan_leb *sleb; -++ int next_lnum; -++ -++ dbg_rcvry("LEB %d", lnum); -++ next_lnum = lnum + 1; -++ if (next_lnum >= UBIFS_LOG_LNUM + c->log_lebs) -++ next_lnum = UBIFS_LOG_LNUM; -++ if (next_lnum != c->ltail_lnum) { -++ /* -++ * We can only recover at the end of the log, so check that the -++ * next log LEB is empty or out of date. -++ */ -++ sleb = ubifs_scan(c, next_lnum, 0, sbuf); -++ if (IS_ERR(sleb)) -++ return sleb; -++ if (sleb->nodes_cnt) { -++ struct ubifs_scan_node *snod; -++ unsigned long long cs_sqnum = c->cs_sqnum; -++ -++ snod = list_entry(sleb->nodes.next, -++ struct ubifs_scan_node, list); -++ if (cs_sqnum == 0) { -++ int err; -++ -++ err = get_cs_sqnum(c, lnum, offs, &cs_sqnum); -++ if (err) { -++ ubifs_scan_destroy(sleb); -++ return ERR_PTR(err); -++ } -++ } -++ if (snod->sqnum > cs_sqnum) { -++ ubifs_err("unrecoverable log corruption " -++ "in LEB %d", lnum); -++ ubifs_scan_destroy(sleb); -++ return ERR_PTR(-EUCLEAN); -++ } -++ } -++ ubifs_scan_destroy(sleb); -++ } -++ return ubifs_recover_leb(c, lnum, offs, sbuf, 0); -++} -++ -++/** -++ * recover_head - recover a head. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number of head to recover -++ * @offs: offset of head to recover -++ * @sbuf: LEB-sized buffer to use -++ * -++ * This function ensures that there is no data on the flash at a head location. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int recover_head(const struct ubifs_info *c, int lnum, int offs, -++ void *sbuf) -++{ -++ int len, err, need_clean = 0; -++ -++ if (c->min_io_size > 1) -++ len = c->min_io_size; -++ else -++ len = 512; -++ if (offs + len > c->leb_size) -++ len = c->leb_size - offs; -++ -++ if (!len) -++ return 0; -++ -++ /* Read at the head location and check it is empty flash */ -++ err = ubi_read(c->ubi, lnum, sbuf, offs, len); -++ if (err) -++ need_clean = 1; -++ else { -++ uint8_t *p = sbuf; -++ -++ while (len--) -++ if (*p++ != 0xff) { -++ need_clean = 1; -++ break; -++ } -++ } -++ -++ if (need_clean) { -++ dbg_rcvry("cleaning head at %d:%d", lnum, offs); -++ if (offs == 0) -++ return ubifs_leb_unmap(c, lnum); -++ err = ubi_read(c->ubi, lnum, sbuf, 0, offs); -++ if (err) -++ return err; -++ return ubi_leb_change(c->ubi, lnum, sbuf, offs, UBI_UNKNOWN); -++ } -++ -++ return 0; -++} -++ -++/** -++ * ubifs_recover_inl_heads - recover index and LPT heads. -++ * @c: UBIFS file-system description object -++ * @sbuf: LEB-sized buffer to use -++ * -++ * This function ensures that there is no data on the flash at the index and -++ * LPT head locations. -++ * -++ * This deals with the recovery of a half-completed journal commit. UBIFS is -++ * careful never to overwrite the last version of the index or the LPT. Because -++ * the index and LPT are wandering trees, data from a half-completed commit will -++ * not be referenced anywhere in UBIFS. The data will be either in LEBs that are -++ * assumed to be empty and will be unmapped anyway before use, or in the index -++ * and LPT heads. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf) -++{ -++ int err; -++ -++ ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY) || c->remounting_rw); -++ -++ dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs); -++ err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf); -++ if (err) -++ return err; -++ -++ dbg_rcvry("checking LPT head at %d:%d", c->nhead_lnum, c->nhead_offs); -++ err = recover_head(c, c->nhead_lnum, c->nhead_offs, sbuf); -++ if (err) -++ return err; -++ -++ return 0; -++} -++ -++/** -++ * clean_an_unclean_leb - read and write a LEB to remove corruption. -++ * @c: UBIFS file-system description object -++ * @ucleb: unclean LEB information -++ * @sbuf: LEB-sized buffer to use -++ * -++ * This function reads a LEB up to a point pre-determined by the mount recovery, -++ * checks the nodes, and writes the result back to the flash, thereby cleaning -++ * off any following corruption, or non-fatal ECC errors. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int clean_an_unclean_leb(const struct ubifs_info *c, -++ struct ubifs_unclean_leb *ucleb, void *sbuf) -++{ -++ int err, lnum = ucleb->lnum, offs = 0, len = ucleb->endpt, quiet = 1; -++ void *buf = sbuf; -++ -++ dbg_rcvry("LEB %d len %d", lnum, len); -++ -++ if (len == 0) { -++ /* Nothing to read, just unmap it */ -++ err = ubifs_leb_unmap(c, lnum); -++ if (err) -++ return err; -++ return 0; -++ } -++ -++ err = ubi_read(c->ubi, lnum, buf, offs, len); -++ if (err && err != -EBADMSG) -++ return err; -++ -++ while (len >= 8) { -++ int ret; -++ -++ cond_resched(); -++ -++ /* Scan quietly until there is an error */ -++ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, quiet); -++ -++ if (ret == SCANNED_A_NODE) { -++ /* A valid node, and not a padding node */ -++ struct ubifs_ch *ch = buf; -++ int node_len; -++ -++ node_len = ALIGN(le32_to_cpu(ch->len), 8); -++ offs += node_len; -++ buf += node_len; -++ len -= node_len; -++ continue; -++ } -++ -++ if (ret > 0) { -++ /* Padding bytes or a valid padding node */ -++ offs += ret; -++ buf += ret; -++ len -= ret; -++ continue; -++ } -++ -++ if (ret == SCANNED_EMPTY_SPACE) { -++ ubifs_err("unexpected empty space at %d:%d", -++ lnum, offs); -++ return -EUCLEAN; -++ } -++ -++ if (quiet) { -++ /* Redo the last scan but noisily */ -++ quiet = 0; -++ continue; -++ } -++ -++ ubifs_scanned_corruption(c, lnum, offs, buf); -++ return -EUCLEAN; -++ } -++ -++ /* Pad to min_io_size */ -++ len = ALIGN(ucleb->endpt, c->min_io_size); -++ if (len > ucleb->endpt) { -++ int pad_len = len - ALIGN(ucleb->endpt, 8); -++ -++ if (pad_len > 0) { -++ buf = c->sbuf + len - pad_len; -++ ubifs_pad(c, buf, pad_len); -++ } -++ } -++ -++ /* Write back the LEB atomically */ -++ err = ubi_leb_change(c->ubi, lnum, sbuf, len, UBI_UNKNOWN); -++ if (err) -++ return err; -++ -++ dbg_rcvry("cleaned LEB %d", lnum); -++ -++ return 0; -++} -++ -++/** -++ * ubifs_clean_lebs - clean LEBs recovered during read-only mount. -++ * @c: UBIFS file-system description object -++ * @sbuf: LEB-sized buffer to use -++ * -++ * This function cleans a LEB identified during recovery that needs to be -++ * written but was not because UBIFS was mounted read-only. This happens when -++ * remounting to read-write mode. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_clean_lebs(const struct ubifs_info *c, void *sbuf) -++{ -++ dbg_rcvry("recovery"); -++ while (!list_empty(&c->unclean_leb_list)) { -++ struct ubifs_unclean_leb *ucleb; -++ int err; -++ -++ ucleb = list_entry(c->unclean_leb_list.next, -++ struct ubifs_unclean_leb, list); -++ err = clean_an_unclean_leb(c, ucleb, sbuf); -++ if (err) -++ return err; -++ list_del(&ucleb->list); -++ kfree(ucleb); -++ } -++ return 0; -++} -++ -++/** -++ * ubifs_recover_gc_lnum - recover the GC LEB number. -++ * @c: UBIFS file-system description object -++ * -++ * Out-of-place garbage collection requires always one empty LEB with which to -++ * start garbage collection. The LEB number is recorded in c->gc_lnum and is -++ * written to the master node on unmounting. In the case of an unclean unmount -++ * the value of gc_lnum recorded in the master node is out of date and cannot -++ * be used. Instead, recovery must allocate an empty LEB for this purpose. -++ * However, there may not be enough empty space, in which case it must be -++ * possible to GC the dirtiest LEB into the GC head LEB. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_recover_gc_lnum(struct ubifs_info *c) -++{ -++ struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf; -++ struct ubifs_lprops lp; -++ int lnum, err; -++ -++ c->gc_lnum = -1; -++ if (wbuf->lnum == -1) { -++ dbg_rcvry("no GC head LEB"); -++ goto find_free; -++ } -++ /* -++ * See whether the used space in the dirtiest LEB fits in the GC head -++ * LEB. -++ */ -++ err = ubifs_find_dirty_leb(c, &lp, c->dead_wm, 2); -++ if (err) { -++ if (err == -ENOSPC) -++ dbg_err("could not find a dirty LEB"); -++ return err; -++ } -++ ubifs_assert(!(lp.flags & LPROPS_INDEX)); -++ lnum = lp.lnum; -++ if (lp.free + lp.dirty == c->leb_size) { -++ /* An empty LEB was returned */ -++ if (lp.free != c->leb_size) { -++ err = ubifs_change_one_lp(c, lnum, c->leb_size, -++ 0, 0, 0, 0); -++ if (err) -++ return err; -++ } -++ err = ubifs_leb_unmap(c, lnum); -++ if (err) -++ return err; -++ c->gc_lnum = lnum; -++ dbg_rcvry("allocated LEB %d for GC", lnum); -++ return 0; -++ } -++ /* -++ * There was no empty LEB so the used space in the dirtiest LEB must fit -++ * in the GC head LEB. -++ */ -++ if (lp.free + lp.dirty < wbuf->offs) { -++ dbg_rcvry("LEB %d doesn't fit in GC head LEB %d:%d", -++ lnum, wbuf->lnum, wbuf->offs); -++ err = ubifs_return_leb(c, lnum); -++ if (err) -++ return err; -++ goto find_free; -++ } -++ /* It fits, so GC it - use locking to keep 'ubifs_assert()' happy */ -++ dbg_rcvry("GC'ing LEB %d", lnum); -++ mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); -++ err = ubifs_garbage_collect_leb(c, &lp); -++ if (err >= 0) { -++ int err2 = ubifs_wbuf_sync_nolock(wbuf); -++ -++ if (err2) -++ err = err2; -++ } -++ mutex_unlock(&wbuf->io_mutex); -++ if (err < 0) { -++ dbg_err("GC failed, error %d", err); -++ if (err == -EAGAIN) -++ err = -EINVAL; -++ return err; -++ } -++ if (err != LEB_RETAINED) { -++ dbg_err("GC returned %d", err); -++ return -EINVAL; -++ } -++ err = ubifs_leb_unmap(c, c->gc_lnum); -++ if (err) -++ return err; -++ dbg_rcvry("allocated LEB %d for GC", lnum); -++ return 0; -++ -++find_free: -++ /* -++ * There is no GC head LEB or the free space in the GC head LEB is too -++ * small. Allocate gc_lnum by calling 'ubifs_find_free_leb_for_idx()' so -++ * GC is not run. -++ */ -++ lnum = ubifs_find_free_leb_for_idx(c); -++ if (lnum < 0) { -++ dbg_err("could not find an empty LEB"); -++ return lnum; -++ } -++ /* And reset the index flag */ -++ err = ubifs_change_one_lp(c, lnum, -1, -1, 0, LPROPS_INDEX, 0); -++ if (err) -++ return err; -++ c->gc_lnum = lnum; -++ dbg_rcvry("allocated LEB %d for GC", lnum); -++ return 0; -++} -++ -++/** -++ * struct size_entry - inode size information for recovery. -++ * @rb: link in the RB-tree of sizes -++ * @inum: inode number -++ * @i_size: size on inode -++ * @d_size: maximum size based on data nodes -++ * @exists: indicates whether the inode exists -++ * @inode: inode if pinned in memory awaiting rw mode to fix it -++ */ -++struct size_entry { -++ struct rb_node rb; -++ ino_t inum; -++ loff_t i_size; -++ loff_t d_size; -++ int exists; -++ struct inode *inode; -++}; -++ -++/** -++ * add_ino - add an entry to the size tree. -++ * @c: UBIFS file-system description object -++ * @inum: inode number -++ * @i_size: size on inode -++ * @d_size: maximum size based on data nodes -++ * @exists: indicates whether the inode exists -++ */ -++static int add_ino(struct ubifs_info *c, ino_t inum, loff_t i_size, -++ loff_t d_size, int exists) -++{ -++ struct rb_node **p = &c->size_tree.rb_node, *parent = NULL; -++ struct size_entry *e; -++ -++ while (*p) { -++ parent = *p; -++ e = rb_entry(parent, struct size_entry, rb); -++ if (inum < e->inum) -++ p = &(*p)->rb_left; -++ else -++ p = &(*p)->rb_right; -++ } -++ -++ e = kzalloc(sizeof(struct size_entry), GFP_KERNEL); -++ if (!e) -++ return -ENOMEM; -++ -++ e->inum = inum; -++ e->i_size = i_size; -++ e->d_size = d_size; -++ e->exists = exists; -++ -++ rb_link_node(&e->rb, parent, p); -++ rb_insert_color(&e->rb, &c->size_tree); -++ -++ return 0; -++} -++ -++/** -++ * find_ino - find an entry on the size tree. -++ * @c: UBIFS file-system description object -++ * @inum: inode number -++ */ -++static struct size_entry *find_ino(struct ubifs_info *c, ino_t inum) -++{ -++ struct rb_node *p = c->size_tree.rb_node; -++ struct size_entry *e; -++ -++ while (p) { -++ e = rb_entry(p, struct size_entry, rb); -++ if (inum < e->inum) -++ p = p->rb_left; -++ else if (inum > e->inum) -++ p = p->rb_right; -++ else -++ return e; -++ } -++ return NULL; -++} -++ -++/** -++ * remove_ino - remove an entry from the size tree. -++ * @c: UBIFS file-system description object -++ * @inum: inode number -++ */ -++static void remove_ino(struct ubifs_info *c, ino_t inum) -++{ -++ struct size_entry *e = find_ino(c, inum); -++ -++ if (!e) -++ return; -++ rb_erase(&e->rb, &c->size_tree); -++ kfree(e); -++} -++ -++/** -++ * ubifs_destroy_size_tree - free resources related to the size tree. -++ * @c: UBIFS file-system description object -++ */ -++void ubifs_destroy_size_tree(struct ubifs_info *c) -++{ -++ struct rb_node *this = c->size_tree.rb_node; -++ struct size_entry *e; -++ -++ while (this) { -++ if (this->rb_left) { -++ this = this->rb_left; -++ continue; -++ } else if (this->rb_right) { -++ this = this->rb_right; -++ continue; -++ } -++ e = rb_entry(this, struct size_entry, rb); -++ if (e->inode) -++ iput(e->inode); -++ this = rb_parent(this); -++ if (this) { -++ if (this->rb_left == &e->rb) -++ this->rb_left = NULL; -++ else -++ this->rb_right = NULL; -++ } -++ kfree(e); -++ } -++ c->size_tree = RB_ROOT; -++} -++ -++/** -++ * ubifs_recover_size_accum - accumulate inode sizes for recovery. -++ * @c: UBIFS file-system description object -++ * @key: node key -++ * @deletion: node is for a deletion -++ * @new_size: inode size -++ * -++ * This function has two purposes: -++ * 1) to ensure there are no data nodes that fall outside the inode size -++ * 2) to ensure there are no data nodes for inodes that do not exist -++ * To accomplish those purposes, a rb-tree is constructed containing an entry -++ * for each inode number in the journal that has not been deleted, and recording -++ * the size from the inode node, the maximum size of any data node (also altered -++ * by truncations) and a flag indicating a inode number for which no inode node -++ * was present in the journal. -++ * -++ * Note that there is still the possibility that there are data nodes that have -++ * been committed that are beyond the inode size, however the only way to find -++ * them would be to scan the entire index. Alternatively, some provision could -++ * be made to record the size of inodes at the start of commit, which would seem -++ * very cumbersome for a scenario that is quite unlikely and the only negative -++ * consequence of which is wasted space. -++ * -++ * This functions returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key, -++ int deletion, loff_t new_size) -++{ -++ ino_t inum = key_ino(c, key); -++ struct size_entry *e; -++ int err; -++ -++ switch (key_type(c, key)) { -++ case UBIFS_INO_KEY: -++ if (deletion) -++ remove_ino(c, inum); -++ else { -++ e = find_ino(c, inum); -++ if (e) { -++ e->i_size = new_size; -++ e->exists = 1; -++ } else { -++ err = add_ino(c, inum, new_size, 0, 1); -++ if (err) -++ return err; -++ } -++ } -++ break; -++ case UBIFS_DATA_KEY: -++ e = find_ino(c, inum); -++ if (e) { -++ if (new_size > e->d_size) -++ e->d_size = new_size; -++ } else { -++ err = add_ino(c, inum, 0, new_size, 0); -++ if (err) -++ return err; -++ } -++ break; -++ case UBIFS_TRUN_KEY: -++ e = find_ino(c, inum); -++ if (e) -++ e->d_size = new_size; -++ break; -++ } -++ return 0; -++} -++ -++/** -++ * fix_size_in_place - fix inode size in place on flash. -++ * @c: UBIFS file-system description object -++ * @e: inode size information for recovery -++ */ -++static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e) -++{ -++ struct ubifs_ino_node *ino = c->sbuf; -++ unsigned char *p; -++ union ubifs_key key; -++ int err, lnum, offs, len; -++ loff_t i_size; -++ uint32_t crc; -++ -++ /* Locate the inode node LEB number and offset */ -++ ino_key_init(c, &key, e->inum); -++ err = ubifs_tnc_locate(c, &key, ino, &lnum, &offs); -++ if (err) -++ goto out; -++ /* -++ * If the size recorded on the inode node is greater than the size that -++ * was calculated from nodes in the journal then don't change the inode. -++ */ -++ i_size = le64_to_cpu(ino->size); -++ if (i_size >= e->d_size) -++ return 0; -++ /* Read the LEB */ -++ err = ubi_read(c->ubi, lnum, c->sbuf, 0, c->leb_size); -++ if (err) -++ goto out; -++ /* Change the size field and recalculate the CRC */ -++ ino = c->sbuf + offs; -++ ino->size = cpu_to_le64(e->d_size); -++ len = le32_to_cpu(ino->ch.len); -++ crc = crc32(UBIFS_CRC32_INIT, (void *)ino + 8, len - 8); -++ ino->ch.crc = cpu_to_le32(crc); -++ /* Work out where data in the LEB ends and free space begins */ -++ p = c->sbuf; -++ len = c->leb_size - 1; -++ while (p[len] == 0xff) -++ len -= 1; -++ len = ALIGN(len + 1, c->min_io_size); -++ /* Atomically write the fixed LEB back again */ -++ err = ubi_leb_change(c->ubi, lnum, c->sbuf, len, UBI_UNKNOWN); -++ if (err) -++ goto out; -++ dbg_rcvry("inode %lu at %d:%d size %lld -> %lld ", e->inum, lnum, offs, -++ i_size, e->d_size); -++ return 0; -++ -++out: -++ ubifs_warn("inode %lu failed to fix size %lld -> %lld error %d", -++ e->inum, e->i_size, e->d_size, err); -++ return err; -++} -++ -++/** -++ * ubifs_recover_size - recover inode size. -++ * @c: UBIFS file-system description object -++ * -++ * This function attempts to fix inode size discrepancies identified by the -++ * 'ubifs_recover_size_accum()' function. -++ * -++ * This functions returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_recover_size(struct ubifs_info *c) -++{ -++ struct rb_node *this = rb_first(&c->size_tree); -++ -++ while (this) { -++ struct size_entry *e; -++ int err; -++ -++ e = rb_entry(this, struct size_entry, rb); -++ if (!e->exists) { -++ union ubifs_key key; -++ -++ ino_key_init(c, &key, e->inum); -++ err = ubifs_tnc_lookup(c, &key, c->sbuf); -++ if (err && err != -ENOENT) -++ return err; -++ if (err == -ENOENT) { -++ /* Remove data nodes that have no inode */ -++ dbg_rcvry("removing ino %lu", e->inum); -++ err = ubifs_tnc_remove_ino(c, e->inum); -++ if (err) -++ return err; -++ /* -++ * If we later unmount cleanly without -++ * committing, the TNC changes will be lost, -++ * hence we set a flag to ensure a commit is -++ * done. -++ */ -++ c->recovery_needs_commit = 1; -++ } else { -++ struct ubifs_ino_node *ino = c->sbuf; -++ -++ e->exists = 1; -++ e->i_size = le64_to_cpu(ino->size); -++ } -++ } -++ if (e->exists && e->i_size < e->d_size) { -++ if (!e->inode && (c->vfs_sb->s_flags & MS_RDONLY)) { -++ /* Fix the inode size and pin it in memory */ -++ struct inode *inode; -++ -++ inode = ubifs_iget(c->vfs_sb, e->inum); -++ if (IS_ERR(inode)) -++ return PTR_ERR(inode); -++ if (inode->i_size < e->d_size) { -++ dbg_rcvry("ino %lu size %lld -> %lld", -++ e->inum, e->d_size, -++ inode->i_size); -++ inode->i_size = e->d_size; -++ e->inode = inode; -++ this = rb_next(this); -++ continue; -++ } -++ iput(inode); -++ } else { -++ /* Fix the size in place */ -++ err = fix_size_in_place(c, e); -++ if (err) { -++ if (e->inode) -++ /* -++ * We have changed the inode -++ * size in memory but failed to -++ * fix it on flash. Mark it -++ * dirty without budgeting, and -++ * hope we don't run out of -++ * space. -++ */ -++ mark_inode_dirty_sync(e->inode); -++ /* -++ * We consider that failing to recover -++ * the size is not fatal, because it -++ * only affects files that were being -++ * written without synchronization and -++ * the only down side is that some space -++ * may be wasted. -++ */ -++ err = 0; -++ } -++ if (e->inode) -++ iput(e->inode); -++ } -++ } -++ this = rb_next(this); -++ rb_erase(&e->rb, &c->size_tree); -++ kfree(e); -++ } -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/replay.c linux-2.6.24.7/fs/ubifs/replay.c -+--- linux-2.6.24.7.old/fs/ubifs/replay.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/replay.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1049 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Adrian Hunter -++ * Artem Bityutskiy (Битюцкий Ðртём) -++ */ -++ -++/* -++ * This file contains journal replay code. It runs when the file-system is being -++ * mounted and requires no locking. -++ * -++ * The larger is the journal, the longer it takes to scan it, so the longer it -++ * takes to mount UBIFS. This is why the journal has limited size which may be -++ * changed depending on the system requirements. But a larger journal gives -++ * faster I/O speed because it writes the index less frequently. So this is a -++ * trade-off. Also, the journal is indexed by the in-memory index (TNC), so the -++ * larger is the journal, the more memory its index may consume. -++ */ -++ -++#include "ubifs.h" -++ -++/* -++ * Replay flags. -++ * -++ * REPLAY_DELETION: node was deleted -++ * REPLAY_REF: node is a reference node -++ */ -++enum { -++ REPLAY_DELETION = 1, -++ REPLAY_REF = 2, -++}; -++ -++/** -++ * struct replay_entry - replay tree entry. -++ * @lnum: logical eraseblock number of the node -++ * @offs: node offset -++ * @len: node length -++ * @sqnum: node sequence number -++ * @flags: replay flags -++ * @rb: links the replay tree -++ * @key: node key -++ * @nm: directory entry name -++ * @old_size: truncation old size -++ * @new_size: truncation new size -++ * @free: amount of free space in a bud -++ * @dirty: amount of dirty space in a bud from padding and deletion nodes -++ * -++ * UBIFS journal replay must compare node sequence numbers, which means it must -++ * build a tree of node information to insert into the TNC. -++ */ -++struct replay_entry { -++ int lnum; -++ int offs; -++ int len; -++ unsigned long long sqnum; -++ int flags; -++ struct rb_node rb; -++ union ubifs_key key; -++ union { -++ struct qstr nm; -++ struct { -++ loff_t old_size; -++ loff_t new_size; -++ }; -++ struct { -++ int free; -++ int dirty; -++ }; -++ }; -++}; -++ -++/** -++ * struct bud_entry - entry in the list of buds to replay. -++ * @list: next bud in the list -++ * @bud: bud description object -++ * @free: free bytes in the bud -++ * @sqnum: reference node sequence number -++ */ -++struct bud_entry { -++ struct list_head list; -++ struct ubifs_bud *bud; -++ int free; -++ unsigned long long sqnum; -++}; -++ -++/** -++ * set_bud_lprops - set free and dirty space used by a bud. -++ * @c: UBIFS file-system description object -++ * @r: replay entry of bud -++ */ -++static int set_bud_lprops(struct ubifs_info *c, struct replay_entry *r) -++{ -++ const struct ubifs_lprops *lp; -++ int err = 0, dirty; -++ -++ ubifs_get_lprops(c); -++ -++ lp = ubifs_lpt_lookup_dirty(c, r->lnum); -++ if (IS_ERR(lp)) { -++ err = PTR_ERR(lp); -++ goto out; -++ } -++ -++ dirty = lp->dirty; -++ if (r->offs == 0 && (lp->free != c->leb_size || lp->dirty != 0)) { -++ dbg_mnt("bud LEB %d was GC'd (%d free, %d dirty)", r->lnum, -++ lp->free, lp->dirty); -++ dbg_gc("bud LEB %d was GC'd (%d free, %d dirty)", r->lnum, -++ lp->free, lp->dirty); -++ dirty -= c->leb_size - lp->free; -++ if (dirty != 0) -++ dbg_msg("LEB %d lp: %d free %d dirty " -++ "replay: %d free %d dirty", r->lnum, lp->free, -++ lp->dirty, r->free, r->dirty); -++ } -++ lp = ubifs_change_lp(c, lp, r->free, dirty + r->dirty, -++ lp->flags | LPROPS_TAKEN, 0); -++ if (IS_ERR(lp)) { -++ err = PTR_ERR(lp); -++ goto out; -++ } -++out: -++ ubifs_release_lprops(c); -++ return err; -++} -++ -++/** -++ * trun_remove_range - apply a replay entry for a truncation to the TNC. -++ * @c: UBIFS file-system description object -++ * @r: replay entry of truncation -++ */ -++static int trun_remove_range(struct ubifs_info *c, struct replay_entry *r) -++{ -++ unsigned min_blk, max_blk; -++ union ubifs_key min_key, max_key; -++ ino_t ino; -++ -++ min_blk = r->new_size / UBIFS_BLOCK_SIZE; -++ if (r->new_size & (UBIFS_BLOCK_SIZE - 1)) -++ min_blk += 1; -++ -++ max_blk = r->old_size / UBIFS_BLOCK_SIZE; -++ if ((r->old_size & (UBIFS_BLOCK_SIZE - 1)) == 0) -++ max_blk -= 1; -++ -++ ino = key_ino(c, &r->key); -++ -++ data_key_init(c, &min_key, ino, min_blk); -++ data_key_init(c, &max_key, ino, max_blk); -++ -++ return ubifs_tnc_remove_range(c, &min_key, &max_key); -++} -++ -++/** -++ * apply_replay_entry - apply a replay entry to the TNC. -++ * @c: UBIFS file-system description object -++ * @r: replay entry to apply -++ * -++ * Apply a replay entry to the TNC. -++ */ -++static int apply_replay_entry(struct ubifs_info *c, struct replay_entry *r) -++{ -++ int err, deletion = ((r->flags & REPLAY_DELETION) != 0); -++ -++ dbg_mnt("LEB %d:%d len %d flgs %d sqnum %llu %s", r->lnum, -++ r->offs, r->len, r->flags, r->sqnum, DBGKEY(&r->key)); -++ -++ /* Set c->replay_sqnum to help deal with dangling branches. */ -++ c->replay_sqnum = r->sqnum; -++ -++ if (r->flags & REPLAY_REF) -++ err = set_bud_lprops(c, r); -++ else if (is_hash_key(c, &r->key)) { -++ if (deletion) -++ err = ubifs_tnc_remove_nm(c, &r->key, &r->nm); -++ else -++ err = ubifs_tnc_add_nm(c, &r->key, r->lnum, r->offs, -++ r->len, &r->nm); -++ } else { -++ if (deletion) -++ switch (key_type(c, &r->key)) { -++ case UBIFS_INO_KEY: -++ { -++ ino_t inum = key_ino(c, &r->key); -++ -++ err = ubifs_tnc_remove_ino(c, inum); -++ break; -++ } -++ case UBIFS_TRUN_KEY: -++ err = trun_remove_range(c, r); -++ break; -++ default: -++ err = ubifs_tnc_remove(c, &r->key); -++ break; -++ } -++ else -++ err = ubifs_tnc_add(c, &r->key, r->lnum, r->offs, -++ r->len); -++ if (err) -++ return err; -++ -++ if (c->need_recovery) -++ err = ubifs_recover_size_accum(c, &r->key, deletion, -++ r->new_size); -++ } -++ -++ return err; -++} -++ -++/** -++ * destroy_replay_tree - destroy the replay. -++ * @c: UBIFS file-system description object -++ * -++ * Destroy the replay tree. -++ */ -++static void destroy_replay_tree(struct ubifs_info *c) -++{ -++ struct rb_node *this = c->replay_tree.rb_node; -++ struct replay_entry *r; -++ -++ while (this) { -++ if (this->rb_left) { -++ this = this->rb_left; -++ continue; -++ } else if (this->rb_right) { -++ this = this->rb_right; -++ continue; -++ } -++ r = rb_entry(this, struct replay_entry, rb); -++ this = rb_parent(this); -++ if (this) { -++ if (this->rb_left == &r->rb) -++ this->rb_left = NULL; -++ else -++ this->rb_right = NULL; -++ } -++ if (is_hash_key(c, &r->key)) -++ kfree(r->nm.name); -++ kfree(r); -++ } -++ c->replay_tree = RB_ROOT; -++} -++ -++/** -++ * apply_replay_tree - apply the replay tree to the TNC. -++ * @c: UBIFS file-system description object -++ * -++ * Apply the replay tree. -++ * Returns zero in case of success and a negative error code in case of -++ * failure. -++ */ -++static int apply_replay_tree(struct ubifs_info *c) -++{ -++ struct rb_node *this = rb_first(&c->replay_tree); -++ -++ while (this) { -++ struct replay_entry *r; -++ int err; -++ -++ cond_resched(); -++ -++ r = rb_entry(this, struct replay_entry, rb); -++ err = apply_replay_entry(c, r); -++ if (err) -++ return err; -++ this = rb_next(this); -++ } -++ return 0; -++} -++ -++/** -++ * insert_node - insert a node to the replay tree. -++ * @c: UBIFS file-system description object -++ * @lnum: node logical eraseblock number -++ * @offs: node offset -++ * @len: node length -++ * @key: node key -++ * @sqnum: sequence number -++ * @deletion: non-zero if this is a deletion -++ * @used: number of bytes in use in a LEB -++ * @old_size: truncation old size -++ * @new_size: truncation new size -++ * -++ * This function inserts a scanned non-direntry node to the replay tree. The -++ * replay tree is an RB-tree containing @struct replay_entry elements which are -++ * indexed by the sequence number. The replay tree is applied at the very end -++ * of the replay process. Since the tree is sorted in sequence number order, -++ * the older modifications are applied first. This function returns zero in -++ * case of success and a negative error code in case of failure. -++ */ -++static int insert_node(struct ubifs_info *c, int lnum, int offs, int len, -++ union ubifs_key *key, unsigned long long sqnum, -++ int deletion, int *used, loff_t old_size, -++ loff_t new_size) -++{ -++ struct rb_node **p = &c->replay_tree.rb_node, *parent = NULL; -++ struct replay_entry *r; -++ -++ if (key_ino(c, key) >= c->highest_inum) -++ c->highest_inum = key_ino(c, key); -++ -++ dbg_mnt("add LEB %d:%d, key %s", lnum, offs, DBGKEY(key)); -++ while (*p) { -++ parent = *p; -++ r = rb_entry(parent, struct replay_entry, rb); -++ if (sqnum < r->sqnum) { -++ p = &(*p)->rb_left; -++ continue; -++ } else if (sqnum > r->sqnum) { -++ p = &(*p)->rb_right; -++ continue; -++ } -++ ubifs_err("duplicate sqnum in replay"); -++ return -EINVAL; -++ } -++ -++ r = kzalloc(sizeof(struct replay_entry), GFP_KERNEL); -++ if (!r) -++ return -ENOMEM; -++ -++ if (!deletion) -++ *used += ALIGN(len, 8); -++ r->lnum = lnum; -++ r->offs = offs; -++ r->len = len; -++ r->sqnum = sqnum; -++ r->flags = (deletion ? REPLAY_DELETION : 0); -++ r->old_size = old_size; -++ r->new_size = new_size; -++ key_copy(c, key, &r->key); -++ -++ rb_link_node(&r->rb, parent, p); -++ rb_insert_color(&r->rb, &c->replay_tree); -++ return 0; -++} -++ -++/** -++ * insert_dent - insert a directory entry node into the replay tree. -++ * @c: UBIFS file-system description object -++ * @lnum: node logical eraseblock number -++ * @offs: node offset -++ * @len: node length -++ * @key: node key -++ * @name: directory entry name -++ * @nlen: directory entry name length -++ * @sqnum: sequence number -++ * @deletion: non-zero if this is a deletion -++ * @used: number of bytes in use in a LEB -++ * -++ * This function inserts a scanned directory entry node to the replay tree. -++ * Returns zero in case of success and a negative error code in case of -++ * failure. -++ * -++ * This function is also used for extended attribute entries because they are -++ * implemented as directory entry nodes. -++ */ -++static int insert_dent(struct ubifs_info *c, int lnum, int offs, int len, -++ union ubifs_key *key, const char *name, int nlen, -++ unsigned long long sqnum, int deletion, int *used) -++{ -++ struct rb_node **p = &c->replay_tree.rb_node, *parent = NULL; -++ struct replay_entry *r; -++ char *nbuf; -++ -++ if (key_ino(c, key) >= c->highest_inum) -++ c->highest_inum = key_ino(c, key); -++ -++ dbg_mnt("add LEB %d:%d, key %s", lnum, offs, DBGKEY(key)); -++ while (*p) { -++ parent = *p; -++ r = rb_entry(parent, struct replay_entry, rb); -++ if (sqnum < r->sqnum) { -++ p = &(*p)->rb_left; -++ continue; -++ } -++ if (sqnum > r->sqnum) { -++ p = &(*p)->rb_right; -++ continue; -++ } -++ ubifs_err("duplicate sqnum in replay"); -++ return -EINVAL; -++ } -++ -++ r = kzalloc(sizeof(struct replay_entry), GFP_KERNEL); -++ if (!r) -++ return -ENOMEM; -++ nbuf = kmalloc(nlen + 1, GFP_KERNEL); -++ if (!nbuf) { -++ kfree(r); -++ return -ENOMEM; -++ } -++ -++ if (!deletion) -++ *used += ALIGN(len, 8); -++ r->lnum = lnum; -++ r->offs = offs; -++ r->len = len; -++ r->sqnum = sqnum; -++ r->nm.len = nlen; -++ memcpy(nbuf, name, nlen); -++ nbuf[nlen] = '\0'; -++ r->nm.name = nbuf; -++ r->flags = (deletion ? REPLAY_DELETION : 0); -++ key_copy(c, key, &r->key); -++ -++ ubifs_assert(!*p); -++ rb_link_node(&r->rb, parent, p); -++ rb_insert_color(&r->rb, &c->replay_tree); -++ return 0; -++} -++ -++/** -++ * ubifs_validate_entry - validate directory or extended attribute entry node. -++ * @c: UBIFS file-system description object -++ * @dent: the node to validate -++ * -++ * This function validates directory or extended attribute entry node @dent. -++ * Returns zero if the node is all right and a %-EINVAL if not. -++ */ -++int ubifs_validate_entry(struct ubifs_info *c, -++ const struct ubifs_dent_node *dent) -++{ -++ int key_type = key_type_flash(c, dent->key); -++ int nlen = le16_to_cpu(dent->nlen); -++ -++ if (le32_to_cpu(dent->ch.len) != nlen + UBIFS_DENT_NODE_SZ + 1 || -++ dent->type >= UBIFS_ITYPES_CNT || -++ nlen > UBIFS_MAX_NLEN || dent->name[nlen] != 0 || -++ strnlen(dent->name, nlen) != nlen || -++ le64_to_cpu(dent->inum) > MAX_INUM) { -++ ubifs_err("bad %s node", key_type == UBIFS_DENT_KEY ? -++ "directory entry" : "extended attribute entry"); -++ return -EINVAL; -++ } -++ -++ if (key_type != UBIFS_DENT_KEY && key_type != UBIFS_XENT_KEY) { -++ ubifs_err("bad key type %d", key_type); -++ return -EINVAL; -++ } -++ -++ return 0; -++} -++ -++/** -++ * replay_bud - replay a bud logical eraseblock. -++ * @c: UBIFS file-system description object -++ * @lnum: bud logical eraseblock number to replay -++ * @offs: bud start offset -++ * @jhead: journal head to which this bud belongs -++ * @free: amount of free space in the bud is returned here -++ * @dirty: amount of dirty space from padding and deletion nodes is returned -++ * here -++ * -++ * This function returns zero in case of success and a negative error code in -++ * case of failure. -++ */ -++static int replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead, -++ int *free, int *dirty) -++{ -++ int err = 0, used = 0; -++ struct ubifs_scan_leb *sleb; -++ struct ubifs_scan_node *snod; -++ struct ubifs_bud *bud; -++ -++ dbg_mnt("replay bud LEB %d, head %d", lnum, jhead); -++ if (c->need_recovery) -++ sleb = ubifs_recover_leb(c, lnum, offs, c->sbuf, jhead != GCHD); -++ else -++ sleb = ubifs_scan(c, lnum, offs, c->sbuf); -++ if (IS_ERR(sleb)) -++ return PTR_ERR(sleb); -++ -++ /* -++ * The bud does not have to start from offset zero - the beginning of -++ * the 'lnum' LEB may contain previously committed data. One of the -++ * things we have to do in replay is to correctly update lprops with -++ * newer information about this LEB. -++ * -++ * At this point lprops thinks that this LEB has 'c->leb_size - offs' -++ * bytes of free space because it only contain information about -++ * committed data. -++ * -++ * But we know that real amount of free space is 'c->leb_size - -++ * sleb->endpt', and the space in the 'lnum' LEB between 'offs' and -++ * 'sleb->endpt' is used by bud data. We have to correctly calculate -++ * how much of these data are dirty and update lprops with this -++ * information. -++ * -++ * The dirt in that LEB region is comprised of padding nodes, deletion -++ * nodes, truncation nodes and nodes which are obsoleted by subsequent -++ * nodes in this LEB. So instead of calculating clean space, we -++ * calculate used space ('used' variable). -++ */ -++ -++ list_for_each_entry(snod, &sleb->nodes, list) { -++ int deletion = 0; -++ -++ cond_resched(); -++ -++ if (snod->sqnum >= SQNUM_WATERMARK) { -++ ubifs_err("file system's life ended"); -++ goto out_dump; -++ } -++ -++ if (snod->sqnum > c->max_sqnum) -++ c->max_sqnum = snod->sqnum; -++ -++ switch (snod->type) { -++ case UBIFS_INO_NODE: -++ { -++ struct ubifs_ino_node *ino = snod->node; -++ loff_t new_size = le64_to_cpu(ino->size); -++ -++ if (le32_to_cpu(ino->nlink) == 0) -++ deletion = 1; -++ err = insert_node(c, lnum, snod->offs, snod->len, -++ &snod->key, snod->sqnum, deletion, -++ &used, 0, new_size); -++ break; -++ } -++ case UBIFS_DATA_NODE: -++ { -++ struct ubifs_data_node *dn = snod->node; -++ loff_t new_size = le32_to_cpu(dn->size) + -++ key_block(c, &snod->key) * -++ UBIFS_BLOCK_SIZE; -++ -++ err = insert_node(c, lnum, snod->offs, snod->len, -++ &snod->key, snod->sqnum, deletion, -++ &used, 0, new_size); -++ break; -++ } -++ case UBIFS_DENT_NODE: -++ case UBIFS_XENT_NODE: -++ { -++ struct ubifs_dent_node *dent = snod->node; -++ -++ err = ubifs_validate_entry(c, dent); -++ if (err) -++ goto out_dump; -++ -++ err = insert_dent(c, lnum, snod->offs, snod->len, -++ &snod->key, dent->name, -++ le16_to_cpu(dent->nlen), snod->sqnum, -++ !le64_to_cpu(dent->inum), &used); -++ break; -++ } -++ case UBIFS_TRUN_NODE: -++ { -++ struct ubifs_trun_node *trun = snod->node; -++ loff_t old_size = le64_to_cpu(trun->old_size); -++ loff_t new_size = le64_to_cpu(trun->new_size); -++ -++ /* Validate truncation node */ -++ if (old_size < 0 || old_size > c->max_inode_sz || -++ new_size < 0 || new_size > c->max_inode_sz || -++ old_size <= new_size) { -++ ubifs_err("bad truncation node"); -++ goto out_dump; -++ } -++ -++ err = insert_node(c, lnum, snod->offs, snod->len, -++ &snod->key, snod->sqnum, 1, &used, -++ old_size, new_size); -++ break; -++ } -++ default: -++ ubifs_err("unexpected node type %d in bud LEB %d:%d", -++ snod->type, lnum, snod->offs); -++ err = -EINVAL; -++ goto out_dump; -++ } -++ if (err) -++ goto out; -++ } -++ -++ bud = ubifs_search_bud(c, lnum); -++ if (!bud) -++ BUG(); -++ -++ ubifs_assert(sleb->endpt - offs >= used); -++ ubifs_assert(sleb->endpt % c->min_io_size == 0); -++ -++ if (sleb->endpt + c->min_io_size <= c->leb_size && -++ !(c->vfs_sb->s_flags & MS_RDONLY)) -++ err = ubifs_wbuf_seek_nolock(&c->jheads[jhead].wbuf, lnum, -++ sleb->endpt, UBI_SHORTTERM); -++ -++ *dirty = sleb->endpt - offs - used; -++ *free = c->leb_size - sleb->endpt; -++ -++out: -++ ubifs_scan_destroy(sleb); -++ return err; -++ -++out_dump: -++ ubifs_err("bad node is at LEB %d:%d", lnum, snod->offs); -++ dbg_dump_node(c, snod->node); -++ ubifs_scan_destroy(sleb); -++ return -EINVAL; -++} -++ -++/** -++ * insert_ref_node - insert a reference node to the replay tree. -++ * @c: UBIFS file-system description object -++ * @lnum: node logical eraseblock number -++ * @offs: node offset -++ * @sqnum: sequence number -++ * @free: amount of free space in bud -++ * @dirty: amount of dirty space from padding and deletion nodes -++ * -++ * This function inserts a reference node to the replay tree and returns zero -++ * in case of success ort a negative error code in case of failure. -++ */ -++static int insert_ref_node(struct ubifs_info *c, int lnum, int offs, -++ unsigned long long sqnum, int free, int dirty) -++{ -++ struct rb_node **p = &c->replay_tree.rb_node, *parent = NULL; -++ struct replay_entry *r; -++ -++ dbg_mnt("add ref LEB %d:%d", lnum, offs); -++ while (*p) { -++ parent = *p; -++ r = rb_entry(parent, struct replay_entry, rb); -++ if (sqnum < r->sqnum) { -++ p = &(*p)->rb_left; -++ continue; -++ } else if (sqnum > r->sqnum) { -++ p = &(*p)->rb_right; -++ continue; -++ } -++ ubifs_err("duplicate sqnum in replay tree"); -++ return -EINVAL; -++ } -++ -++ r = kzalloc(sizeof(struct replay_entry), GFP_KERNEL); -++ if (!r) -++ return -ENOMEM; -++ -++ r->lnum = lnum; -++ r->offs = offs; -++ r->sqnum = sqnum; -++ r->flags = REPLAY_REF; -++ r->free = free; -++ r->dirty = dirty; -++ -++ rb_link_node(&r->rb, parent, p); -++ rb_insert_color(&r->rb, &c->replay_tree); -++ return 0; -++} -++ -++/** -++ * replay_buds - replay all buds. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns zero in case of success and a negative error code in -++ * case of failure. -++ */ -++static int replay_buds(struct ubifs_info *c) -++{ -++ struct bud_entry *b; -++ int err, uninitialized_var(free), uninitialized_var(dirty); -++ -++ list_for_each_entry(b, &c->replay_buds, list) { -++ err = replay_bud(c, b->bud->lnum, b->bud->start, b->bud->jhead, -++ &free, &dirty); -++ if (err) -++ return err; -++ err = insert_ref_node(c, b->bud->lnum, b->bud->start, b->sqnum, -++ free, dirty); -++ if (err) -++ return err; -++ } -++ -++ return 0; -++} -++ -++/** -++ * destroy_bud_list - destroy the list of buds to replay. -++ * @c: UBIFS file-system description object -++ */ -++static void destroy_bud_list(struct ubifs_info *c) -++{ -++ struct bud_entry *b; -++ -++ while (!list_empty(&c->replay_buds)) { -++ b = list_entry(c->replay_buds.next, struct bud_entry, list); -++ list_del(&b->list); -++ kfree(b); -++ } -++} -++ -++/** -++ * add_replay_bud - add a bud to the list of buds to replay. -++ * @c: UBIFS file-system description object -++ * @lnum: bud logical eraseblock number to replay -++ * @offs: bud start offset -++ * @jhead: journal head to which this bud belongs -++ * @sqnum: reference node sequence number -++ * -++ * This function returns zero in case of success and a negative error code in -++ * case of failure. -++ */ -++static int add_replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead, -++ unsigned long long sqnum) -++{ -++ struct ubifs_bud *bud; -++ struct bud_entry *b; -++ -++ dbg_mnt("add replay bud LEB %d:%d, head %d", lnum, offs, jhead); -++ -++ bud = kmalloc(sizeof(struct ubifs_bud), GFP_KERNEL); -++ if (!bud) -++ return -ENOMEM; -++ -++ b = kmalloc(sizeof(struct bud_entry), GFP_KERNEL); -++ if (!b) { -++ kfree(bud); -++ return -ENOMEM; -++ } -++ -++ bud->lnum = lnum; -++ bud->start = offs; -++ bud->jhead = jhead; -++ ubifs_add_bud(c, bud); -++ -++ b->bud = bud; -++ b->sqnum = sqnum; -++ list_add_tail(&b->list, &c->replay_buds); -++ -++ return 0; -++} -++ -++/** -++ * validate_ref - validate a reference node. -++ * @c: UBIFS file-system description object -++ * @ref: the reference node to validate -++ * @ref_lnum: LEB number of the reference node -++ * @ref_offs: reference node offset -++ * -++ * This function returns %1 if a bud reference already exists for the LEB. %0 is -++ * returned if the reference node is new, otherwise %-EINVAL is returned if -++ * validation failed. -++ */ -++static int validate_ref(struct ubifs_info *c, const struct ubifs_ref_node *ref) -++{ -++ struct ubifs_bud *bud; -++ int lnum = le32_to_cpu(ref->lnum); -++ unsigned int offs = le32_to_cpu(ref->offs); -++ unsigned int jhead = le32_to_cpu(ref->jhead); -++ -++ /* -++ * ref->offs may point to the end of LEB when the journal head points -++ * to the end of LEB and we write reference node for it during commit. -++ * So this is why we require 'offs > c->leb_size'. -++ */ -++ if (jhead >= c->jhead_cnt || lnum >= c->leb_cnt || -++ lnum < c->main_first || offs > c->leb_size || -++ offs & (c->min_io_size - 1)) -++ return -EINVAL; -++ -++ /* Make sure we have not already looked at this bud */ -++ bud = ubifs_search_bud(c, lnum); -++ if (bud) { -++ if (bud->jhead == jhead && bud->start <= offs) -++ return 1; -++ ubifs_err("bud at LEB %d:%d was already referred", lnum, offs); -++ return -EINVAL; -++ } -++ -++ return 0; -++} -++ -++/** -++ * replay_log_leb - replay a log logical eraseblock. -++ * @c: UBIFS file-system description object -++ * @lnum: log logical eraseblock to replay -++ * @offs: offset to start replaying from -++ * @sbuf: scan buffer -++ * -++ * This function replays a log LEB and returns zero in case of success, %1 if -++ * this is the last LEB in the log, and a negative error code in case of -++ * failure. -++ */ -++static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf) -++{ -++ int err; -++ struct ubifs_scan_leb *sleb; -++ struct ubifs_scan_node *snod; -++ const struct ubifs_cs_node *node; -++ -++ dbg_mnt("replay log LEB %d:%d", lnum, offs); -++ sleb = ubifs_scan(c, lnum, offs, sbuf); -++ if (IS_ERR(sleb)) { -++ if (c->need_recovery) -++ sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf); -++ if (IS_ERR(sleb)) -++ return PTR_ERR(sleb); -++ } -++ -++ if (sleb->nodes_cnt == 0) { -++ err = 1; -++ goto out; -++ } -++ -++ node = sleb->buf; -++ -++ snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list); -++ if (c->cs_sqnum == 0) { -++ /* -++ * This is the first log LEB we are looking at, make sure that -++ * the first node is a commit start node. Also record its -++ * sequence number so that UBIFS can determine where the log -++ * ends, because all nodes which were have higher sequence -++ * numbers. -++ */ -++ if (snod->type != UBIFS_CS_NODE) { -++ dbg_err("first log node at LEB %d:%d is not CS node", -++ lnum, offs); -++ goto out_dump; -++ } -++ if (le64_to_cpu(node->cmt_no) != c->cmt_no) { -++ dbg_err("first CS node at LEB %d:%d has wrong " -++ "commit number %llu expected %llu", -++ lnum, offs, -++ (unsigned long long)le64_to_cpu(node->cmt_no), -++ c->cmt_no); -++ goto out_dump; -++ } -++ -++ c->cs_sqnum = le64_to_cpu(node->ch.sqnum); -++ dbg_mnt("commit start sqnum %llu", c->cs_sqnum); -++ } -++ -++ if (snod->sqnum < c->cs_sqnum) { -++ /* -++ * This means that we reached end of log and now -++ * look to the older log data, which was already -++ * committed but the eraseblock was not erased (UBIFS -++ * only unmaps it). So this basically means we have to -++ * exit with "end of log" code. -++ */ -++ err = 1; -++ goto out; -++ } -++ -++ /* Make sure the first node sits at offset zero of the LEB */ -++ if (snod->offs != 0) { -++ dbg_err("first node is not at zero offset"); -++ goto out_dump; -++ } -++ -++ list_for_each_entry(snod, &sleb->nodes, list) { -++ -++ cond_resched(); -++ -++ if (snod->sqnum >= SQNUM_WATERMARK) { -++ ubifs_err("file system's life ended"); -++ goto out_dump; -++ } -++ -++ if (snod->sqnum < c->cs_sqnum) { -++ dbg_err("bad sqnum %llu, commit sqnum %llu", -++ snod->sqnum, c->cs_sqnum); -++ goto out_dump; -++ } -++ -++ if (snod->sqnum > c->max_sqnum) -++ c->max_sqnum = snod->sqnum; -++ -++ switch (snod->type) { -++ case UBIFS_REF_NODE: { -++ const struct ubifs_ref_node *ref = snod->node; -++ -++ err = validate_ref(c, ref); -++ if (err == 1) -++ break; /* Already have this bud */ -++ if (err) -++ goto out_dump; -++ -++ err = add_replay_bud(c, le32_to_cpu(ref->lnum), -++ le32_to_cpu(ref->offs), -++ le32_to_cpu(ref->jhead), -++ snod->sqnum); -++ if (err) -++ goto out; -++ -++ break; -++ } -++ case UBIFS_CS_NODE: -++ /* Make sure it sits at the beginning of LEB */ -++ if (snod->offs != 0) { -++ ubifs_err("unexpected node in log"); -++ goto out_dump; -++ } -++ break; -++ default: -++ ubifs_err("unexpected node in log"); -++ goto out_dump; -++ } -++ } -++ -++ if (sleb->endpt || c->lhead_offs >= c->leb_size) { -++ c->lhead_lnum = lnum; -++ c->lhead_offs = sleb->endpt; -++ } -++ -++ err = !sleb->endpt; -++out: -++ ubifs_scan_destroy(sleb); -++ return err; -++ -++out_dump: -++ ubifs_err("log error detected while replying the log at LEB %d:%d", -++ lnum, offs + snod->offs); -++ dbg_dump_node(c, snod->node); -++ ubifs_scan_destroy(sleb); -++ return -EINVAL; -++} -++ -++/** -++ * take_ihead - update the status of the index head in lprops to 'taken'. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns the amount of free space in the index head LEB or a -++ * negative error code. -++ */ -++static int take_ihead(struct ubifs_info *c) -++{ -++ const struct ubifs_lprops *lp; -++ int err, free; -++ -++ ubifs_get_lprops(c); -++ -++ lp = ubifs_lpt_lookup_dirty(c, c->ihead_lnum); -++ if (IS_ERR(lp)) { -++ err = PTR_ERR(lp); -++ goto out; -++ } -++ -++ free = lp->free; -++ -++ lp = ubifs_change_lp(c, lp, -1, -1, lp->flags | LPROPS_TAKEN, 0); -++ if (IS_ERR(lp)) { -++ err = PTR_ERR(lp); -++ goto out; -++ } -++ -++ err = free; -++out: -++ ubifs_release_lprops(c); -++ return err; -++} -++ -++/** -++ * ubifs_replay_journal - replay journal. -++ * @c: UBIFS file-system description object -++ * -++ * This function scans the journal, replays and cleans it up. It makes sure all -++ * memory data structures related to uncommitted journal are built (dirty TNC -++ * tree, tree of buds, modified lprops, etc). -++ */ -++int ubifs_replay_journal(struct ubifs_info *c) -++{ -++ int err, i, lnum, offs, free; -++ void *sbuf = NULL; -++ -++ /* Update the status of the index head in lprops to 'taken' */ -++ free = take_ihead(c); -++ if (free < 0) -++ return free; /* Error code */ -++ -++ if (c->ihead_offs != c->leb_size - free) { -++ ubifs_err("bad index head LEB %d:%d", c->ihead_lnum, -++ c->ihead_offs); -++ return -EINVAL; -++ } -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ sbuf = kmalloc(c->leb_size, GFP_KERNEL); -++#else -++ sbuf = vmalloc(c->leb_size); -++#endif -++ if (!sbuf) -++ return -ENOMEM; -++ -++ dbg_mnt("start replaying the journal"); -++ -++ c->replaying = 1; -++ -++ lnum = c->ltail_lnum = c->lhead_lnum; -++ offs = c->lhead_offs; -++ -++ for (i = 0; i < c->log_lebs; i++, lnum++) { -++ if (lnum >= UBIFS_LOG_LNUM + c->log_lebs) { -++ /* -++ * The log is logically circular, we reached the last -++ * LEB, switch to the first one. -++ */ -++ lnum = UBIFS_LOG_LNUM; -++ offs = 0; -++ } -++ err = replay_log_leb(c, lnum, offs, sbuf); -++ if (err == 1) -++ /* We hit the end of the log */ -++ break; -++ if (err) -++ goto out; -++ offs = 0; -++ } -++ -++ err = replay_buds(c); -++ if (err) -++ goto out; -++ -++ err = apply_replay_tree(c); -++ if (err) -++ goto out; -++ -++ ubifs_assert(c->bud_bytes <= c->max_bud_bytes || c->need_recovery); -++ dbg_mnt("finished, log head LEB %d:%d, max_sqnum %llu, " -++ "highest_inum %lu", c->lhead_lnum, c->lhead_offs, c->max_sqnum, -++ c->highest_inum); -++out: -++ destroy_replay_tree(c); -++ destroy_bud_list(c); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(sbuf); -++#else -++ vfree(sbuf); -++#endif -++ c->replaying = 0; -++ return err; -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/sb.c linux-2.6.24.7/fs/ubifs/sb.c -+--- linux-2.6.24.7.old/fs/ubifs/sb.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/sb.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,617 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* -++ * This file implements UBIFS superblock. The superblock is stored at the first -++ * LEB of the volume and is never changed by UBIFS. Only user-space tools may -++ * change it. The superblock node mostly contains geometry information. -++ */ -++ -++#include "ubifs.h" -++ -++/* -++ * Default journal size in logical eraseblocks as a percent of total -++ * flash size. -++ */ -++#define DEFAULT_JNL_PERCENT 5 -++ -++/* Default maximum journal size in bytes */ -++#define DEFAULT_MAX_JNL (32*1024*1024) -++ -++/* Default indexing tree fanout */ -++#define DEFAULT_FANOUT 8 -++ -++/* Default number of LEBs for orphan information */ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++#define DEFAULT_ORPHAN_LEBS 2 /* 2 is better for testing */ -++#else -++#define DEFAULT_ORPHAN_LEBS 1 -++#endif -++ -++/* Default number of journal heads */ -++#define DEFAULT_JHEADS_CNT 1 -++ -++/* Default positions of different LEBs in the main area */ -++#define DEFAULT_IDX_LEB 0 -++#define DEFAULT_DATA_LEB 1 -++#define DEFAULT_GC_LEB 2 -++ -++/* Default number of LEB numbers in LPT's save table */ -++#define DEFAULT_LSAVE_CNT 256 -++ -++/* Default reserved pool size as a percent of maximum free space */ -++#define DEFAULT_RP_PERCENT 5 -++ -++/* The default maximum size of reserved pool in bytes */ -++#define DEFAULT_MAX_RP_SIZE (5*1024*1024) -++ -++/* Default UBIFS compressor */ -++#define DEFAULT_COMPRESSOR UBIFS_COMPR_LZO -++ -++/* Default time granularity in nanoseconds */ -++#define DEFAULT_TIME_GRAN 1000000000 -++ -++/** -++ * create_default_filesystem - format empty UBI volume. -++ * @c: UBIFS file-system description object -++ * -++ * This function creates default empty file-system. Returns zero in case of -++ * success and a negative error code in case of failure. -++ */ -++static int create_default_filesystem(struct ubifs_info *c) -++{ -++ struct ubifs_sb_node *sup; -++ struct ubifs_mst_node *mst; -++ struct ubifs_idx_node *idx; -++ struct ubifs_branch *br; -++ struct ubifs_ino_node *ino; -++ struct ubifs_cs_node *cs; -++ union ubifs_key key; -++ int err, tmp, jnl_lebs, log_lebs, max_buds, main_lebs, main_first; -++ int lpt_lebs, lpt_first, orph_lebs, big_lpt, ino_waste, sup_flags = 0; -++ uint64_t tmp64, main_bytes; -++ -++ /* Some functions called from here depend on the @c->key_len filed */ -++ c->key_len = UBIFS_SK_LEN; -++ -++ /* -++ * First of all, we have to calculate default file-system geometry - -++ * log size, journal size, etc. -++ */ -++ c->max_leb_cnt = c->leb_cnt; -++ if (c->leb_cnt < 0x7FFFFFFF / DEFAULT_JNL_PERCENT) -++ /* We can first multiply then divide and have no overflow */ -++ jnl_lebs = c->leb_cnt * DEFAULT_JNL_PERCENT / 100; -++ else -++ jnl_lebs = (c->leb_cnt / 100) * DEFAULT_JNL_PERCENT; -++ -++ if (jnl_lebs < UBIFS_MIN_JNL_LEBS) -++ jnl_lebs = UBIFS_MIN_JNL_LEBS; -++ if (jnl_lebs * c->leb_size > DEFAULT_MAX_JNL) -++ jnl_lebs = DEFAULT_MAX_JNL / c->leb_size; -++ -++ /* -++ * The log should be large enough to fit reference nodes for all bud -++ * LEBs. Because buds do not have to start from the beginning of LEBs -++ * (half of the LEB may contain committed data), the log should -++ * generally be larger, make it twice as large. -++ */ -++ tmp = 2 * (c->ref_node_alsz * jnl_lebs) + c->leb_size - 1; -++ log_lebs = tmp / c->leb_size; -++ /* Plus one LEB reserved for commit */ -++ log_lebs += 1; -++ /* And some extra space to allow writes while committing */ -++ log_lebs += 1; -++ -++ max_buds = jnl_lebs - log_lebs; -++ if (max_buds < UBIFS_MIN_BUD_LEBS) -++ max_buds = UBIFS_MIN_BUD_LEBS; -++ -++ /* -++ * Orphan nodes are stored in a separate area. One node can store a lot -++ * of orphan inode numbers, but when new orphan comes we just add a new -++ * orphan node. At some point the nodes are consolidated into one -++ * orphan node. -++ */ -++ orph_lebs = DEFAULT_ORPHAN_LEBS; -++ -++ main_lebs = c->leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS - log_lebs; -++ main_lebs -= orph_lebs; -++ -++ lpt_first = UBIFS_LOG_LNUM + log_lebs; -++ c->lsave_cnt = DEFAULT_LSAVE_CNT; -++ err = ubifs_create_dflt_lpt(c, &main_lebs, lpt_first, &lpt_lebs, -++ &big_lpt); -++ if (err) -++ return err; -++ -++ dbg_gen("LEB Properties Tree created (LEBs %d-%d)", lpt_first, -++ lpt_first + lpt_lebs - 1); -++ -++ main_first = c->leb_cnt - main_lebs; -++ -++ /* Create default superblock */ -++ tmp = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size); -++ sup = kzalloc(tmp, GFP_KERNEL); -++ if (!sup) -++ return -ENOMEM; -++ -++ tmp64 = (uint64_t)max_buds * c->leb_size; -++ if (big_lpt) -++ sup_flags |= UBIFS_FLG_BIGLPT; -++ -++ sup->ch.node_type = UBIFS_SB_NODE; -++ sup->key_hash = UBIFS_KEY_HASH_R5; -++ sup->flags = cpu_to_le32(sup_flags); -++ sup->min_io_size = cpu_to_le32(c->min_io_size); -++ sup->leb_size = cpu_to_le32(c->leb_size); -++ sup->leb_cnt = cpu_to_le32(c->leb_cnt); -++ sup->max_leb_cnt = cpu_to_le32(c->max_leb_cnt); -++ sup->max_bud_bytes = cpu_to_le64(tmp64); -++ sup->log_lebs = cpu_to_le32(log_lebs); -++ sup->lpt_lebs = cpu_to_le32(lpt_lebs); -++ sup->orph_lebs = cpu_to_le32(orph_lebs); -++ sup->jhead_cnt = cpu_to_le32(DEFAULT_JHEADS_CNT); -++ sup->fanout = cpu_to_le32(DEFAULT_FANOUT); -++ sup->lsave_cnt = cpu_to_le32(c->lsave_cnt); -++ sup->fmt_version = cpu_to_le32(UBIFS_FORMAT_VERSION); -++ sup->default_compr = cpu_to_le16(DEFAULT_COMPRESSOR); -++ sup->time_gran = cpu_to_le32(DEFAULT_TIME_GRAN); -++ -++ main_bytes = (uint64_t)main_lebs * c->leb_size; -++ tmp64 = main_bytes * DEFAULT_RP_PERCENT; -++ do_div(tmp64, 100); -++ if (tmp64 > DEFAULT_MAX_RP_SIZE) -++ tmp64 = DEFAULT_MAX_RP_SIZE; -++ sup->rp_size = cpu_to_le64(tmp64); -++ -++ err = ubifs_write_node(c, sup, UBIFS_SB_NODE_SZ, 0, 0, UBI_LONGTERM); -++ kfree(sup); -++ if (err) -++ return err; -++ -++ dbg_gen("default superblock created at LEB 0:0"); -++ -++ /* Create default master node */ -++ mst = kzalloc(c->mst_node_alsz, GFP_KERNEL); -++ if (!mst) -++ return -ENOMEM; -++ -++ mst->ch.node_type = UBIFS_MST_NODE; -++ mst->log_lnum = cpu_to_le32(UBIFS_LOG_LNUM); -++ mst->highest_inum = cpu_to_le64(UBIFS_FIRST_INO); -++ mst->cmt_no = 0; -++ mst->root_lnum = cpu_to_le32(main_first + DEFAULT_IDX_LEB); -++ mst->root_offs = 0; -++ tmp = ubifs_idx_node_sz(c, 1); -++ mst->root_len = cpu_to_le32(tmp); -++ mst->gc_lnum = cpu_to_le32(main_first + DEFAULT_GC_LEB); -++ mst->ihead_lnum = cpu_to_le32(main_first + DEFAULT_IDX_LEB); -++ mst->ihead_offs = cpu_to_le32(ALIGN(tmp, c->min_io_size)); -++ mst->index_size = cpu_to_le64(ALIGN(tmp, 8)); -++ mst->lpt_lnum = cpu_to_le32(c->lpt_lnum); -++ mst->lpt_offs = cpu_to_le32(c->lpt_offs); -++ mst->nhead_lnum = cpu_to_le32(c->nhead_lnum); -++ mst->nhead_offs = cpu_to_le32(c->nhead_offs); -++ mst->ltab_lnum = cpu_to_le32(c->ltab_lnum); -++ mst->ltab_offs = cpu_to_le32(c->ltab_offs); -++ mst->lsave_lnum = cpu_to_le32(c->lsave_lnum); -++ mst->lsave_offs = cpu_to_le32(c->lsave_offs); -++ mst->lscan_lnum = cpu_to_le32(main_first); -++ mst->empty_lebs = cpu_to_le32(main_lebs - 2); -++ mst->idx_lebs = cpu_to_le32(1); -++ mst->leb_cnt = cpu_to_le32(c->leb_cnt); -++ -++ /* Calculate lprops statistics */ -++ tmp64 = main_bytes; -++ tmp64 -= ALIGN(ubifs_idx_node_sz(c, 1), c->min_io_size); -++ tmp64 -= ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size); -++ mst->total_free = cpu_to_le64(tmp64); -++ -++ tmp64 = ALIGN(ubifs_idx_node_sz(c, 1), c->min_io_size); -++ ino_waste = ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size) - -++ UBIFS_INO_NODE_SZ; -++ tmp64 += ino_waste; -++ tmp64 -= ALIGN(ubifs_idx_node_sz(c, 1), 8); -++ mst->total_dirty = cpu_to_le64(tmp64); -++ -++ /* The indexing LEB does not contribute to dark space */ -++ tmp64 = (c->main_lebs - 1) * c->dark_wm; -++ mst->total_dark = cpu_to_le64(tmp64); -++ -++ mst->total_used = cpu_to_le64(UBIFS_INO_NODE_SZ); -++ -++ err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM, 0, -++ UBI_UNKNOWN); -++ if (err) { -++ kfree(mst); -++ return err; -++ } -++ err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM + 1, 0, -++ UBI_UNKNOWN); -++ kfree(mst); -++ if (err) -++ return err; -++ -++ dbg_gen("default master node created at LEB %d:0", UBIFS_MST_LNUM); -++ -++ /* Create the root indexing node */ -++ tmp = ubifs_idx_node_sz(c, 1); -++ idx = kzalloc(ALIGN(tmp, c->min_io_size), GFP_KERNEL); -++ if (!idx) -++ return -ENOMEM; -++ -++ c->key_fmt = UBIFS_SIMPLE_KEY_FMT; -++ c->key_hash = key_r5_hash; -++ -++ idx->ch.node_type = UBIFS_IDX_NODE; -++ idx->child_cnt = cpu_to_le16(1); -++ ino_key_init(c, &key, UBIFS_ROOT_INO); -++ br = ubifs_idx_branch(c, idx, 0); -++ key_write_idx(c, &key, &br->key); -++ br->lnum = cpu_to_le32(main_first + DEFAULT_DATA_LEB); -++ br->len = cpu_to_le32(UBIFS_INO_NODE_SZ); -++ err = ubifs_write_node(c, idx, tmp, main_first + DEFAULT_IDX_LEB, 0, -++ UBI_UNKNOWN); -++ kfree(idx); -++ if (err) -++ return err; -++ -++ dbg_gen("default root indexing node created LEB %d:0", -++ main_first + DEFAULT_IDX_LEB); -++ -++ /* Create default root inode */ -++ tmp = ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size); -++ ino = kzalloc(tmp, GFP_KERNEL); -++ if (!ino) -++ return -ENOMEM; -++ -++ ino_key_init_flash(c, &ino->key, UBIFS_ROOT_INO); -++ ino->ch.node_type = UBIFS_INO_NODE; -++ ino->creat_sqnum = cpu_to_le64(++c->max_sqnum); -++ ino->nlink = cpu_to_le32(2); -++ tmp = cpu_to_le64(CURRENT_TIME_SEC.tv_sec); -++ ino->atime_sec = tmp; -++ ino->ctime_sec = tmp; -++ ino->mtime_sec = tmp; -++ ino->atime_nsec = 0; -++ ino->ctime_nsec = 0; -++ ino->mtime_nsec = 0; -++ ino->mode = cpu_to_le32(S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO); -++ ino->size = cpu_to_le64(UBIFS_INO_NODE_SZ); -++ -++ /* Set compression enabled by default */ -++ ino->flags = cpu_to_le32(UBIFS_COMPR_FL); -++ -++ err = ubifs_write_node(c, ino, UBIFS_INO_NODE_SZ, -++ main_first + DEFAULT_DATA_LEB, 0, -++ UBI_UNKNOWN); -++ kfree(ino); -++ if (err) -++ return err; -++ -++ dbg_gen("root inode created at LEB %d:0", -++ main_first + DEFAULT_DATA_LEB); -++ -++ /* -++ * The first node in the log has to be the commit start node. This is -++ * always the case during normal file-system operation. Write a fake -++ * commit start node to the log. -++ */ -++ tmp = ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size); -++ cs = kzalloc(tmp, GFP_KERNEL); -++ if (!cs) -++ return -ENOMEM; -++ -++ cs->ch.node_type = UBIFS_CS_NODE; -++ err = ubifs_write_node(c, cs, UBIFS_CS_NODE_SZ, UBIFS_LOG_LNUM, -++ 0, UBI_UNKNOWN); -++ kfree(cs); -++ -++ ubifs_msg("default file-system created"); -++ return 0; -++} -++ -++/** -++ * validate_sb - validate superblock node. -++ * @c: UBIFS file-system description object -++ * @sup: superblock node -++ * -++ * This function validates superblock node @sup. Since most of data was read -++ * from the superblock and stored in @c, the function validates fields in @c -++ * instead. Returns zero in case of success and %-EINVAL in case of validation -++ * failure. -++ */ -++static int validate_sb(struct ubifs_info *c, struct ubifs_sb_node *sup) -++{ -++ long long max_bytes; -++ int err = 1; -++ -++ if (!c->key_hash) { -++ err = 2; -++ goto failed; -++ } -++ -++ if (sup->key_fmt != UBIFS_SIMPLE_KEY_FMT) { -++ err = 3; -++ goto failed; -++ } -++ -++ if (le32_to_cpu(sup->min_io_size) != c->min_io_size) { -++ ubifs_err("min. I/O unit mismatch: %d in superblock, %d real", -++ le32_to_cpu(sup->min_io_size), c->min_io_size); -++ goto failed; -++ } -++ -++ if (le32_to_cpu(sup->leb_size) != c->leb_size) { -++ ubifs_err("LEB size mismatch: %d in superblock, %d real", -++ le32_to_cpu(sup->leb_size), c->leb_size); -++ goto failed; -++ } -++ -++ if (c->leb_cnt < UBIFS_MIN_LEB_CNT || c->leb_cnt > c->vi.size) { -++ ubifs_err("bad LEB count: %d in superblock, %d on UBI volume, " -++ "%d minimum required", c->leb_cnt, c->vi.size, -++ UBIFS_MIN_LEB_CNT); -++ goto failed; -++ } -++ -++ if (c->max_leb_cnt < c->leb_cnt) { -++ ubifs_err("max. LEB count %d less than LEB count %d", -++ c->max_leb_cnt, c->leb_cnt); -++ goto failed; -++ } -++ -++ if (c->log_lebs < UBIFS_MIN_LOG_LEBS || -++ c->lpt_lebs < UBIFS_MIN_LPT_LEBS || -++ c->orph_lebs < UBIFS_MIN_ORPH_LEBS || -++ c->main_lebs < UBIFS_MIN_MAIN_LEBS) { -++ err = 6; -++ goto failed; -++ } -++ -++ if (c->main_lebs < UBIFS_MIN_MAIN_LEBS) { -++ err = 7; -++ goto failed; -++ } -++ -++ if (c->max_bud_bytes < (long long)c->leb_size * UBIFS_MIN_BUD_LEBS || -++ c->max_bud_bytes > (long long)c->leb_size * c->main_lebs) { -++ err = 8; -++ goto failed; -++ } -++ -++ if (c->jhead_cnt < NONDATA_JHEADS_CNT + 1 || -++ c->jhead_cnt > NONDATA_JHEADS_CNT + UBIFS_MAX_JHEADS) { -++ err = 9; -++ goto failed; -++ } -++ -++ if (c->fanout < UBIFS_MIN_FANOUT || -++ ubifs_idx_node_sz(c, c->fanout) > c->leb_size) { -++ err = 10; -++ goto failed; -++ } -++ -++ if (c->lsave_cnt < 0 || (c->lsave_cnt > DEFAULT_LSAVE_CNT && -++ c->lsave_cnt > c->max_leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS - -++ c->log_lebs - c->lpt_lebs - c->orph_lebs)) { -++ err = 11; -++ goto failed; -++ } -++ -++ if (UBIFS_SB_LEBS + UBIFS_MST_LEBS + c->log_lebs + c->lpt_lebs + -++ c->orph_lebs + c->main_lebs != c->leb_cnt) { -++ err = 12; -++ goto failed; -++ } -++ -++ if (c->default_compr < 0 || c->default_compr >= UBIFS_COMPR_TYPES_CNT) { -++ err = 13; -++ goto failed; -++ } -++ -++ max_bytes = c->main_lebs * (long long)c->leb_size; -++ if (c->rp_size < 0 || max_bytes < c->rp_size) { -++ err = 14; -++ goto failed; -++ } -++ -++ if (le32_to_cpu(sup->time_gran) > 1000000000 || -++ le32_to_cpu(sup->time_gran) < 1) { -++ err = 15; -++ goto failed; -++ } -++ -++ return 0; -++ -++failed: -++ ubifs_err("bad superblock, error %d", err); -++ dbg_dump_node(c, sup); -++ return -EINVAL; -++} -++ -++/** -++ * ubifs_read_sb_node - read superblock node. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns a pointer to the superblock node or a negative error -++ * code. -++ */ -++struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c) -++{ -++ struct ubifs_sb_node *sup; -++ int err; -++ -++ sup = kmalloc(ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size), GFP_NOFS); -++ if (!sup) -++ return ERR_PTR(-ENOMEM); -++ -++ err = ubifs_read_node(c, sup, UBIFS_SB_NODE, UBIFS_SB_NODE_SZ, -++ UBIFS_SB_LNUM, 0); -++ if (err) { -++ kfree(sup); -++ return ERR_PTR(err); -++ } -++ -++ return sup; -++} -++ -++/** -++ * ubifs_write_sb_node - write superblock node. -++ * @c: UBIFS file-system description object -++ * @sup: superblock node read with 'ubifs_read_sb_node()' -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup) -++{ -++ int len = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size); -++ -++ ubifs_prepare_node(c, sup, UBIFS_SB_NODE_SZ, 1); -++ return ubi_leb_change(c->ubi, UBIFS_SB_LNUM, sup, len, UBI_LONGTERM); -++} -++ -++/** -++ * ubifs_read_superblock - read superblock. -++ * @c: UBIFS file-system description object -++ * -++ * This function finds, reads and checks the superblock. If an empty UBI volume -++ * is being mounted, this function creates default superblock. Returns zero in -++ * case of success, and a negative error code in case of failure. -++ */ -++int ubifs_read_superblock(struct ubifs_info *c) -++{ -++ int err, sup_flags; -++ struct ubifs_sb_node *sup; -++ -++ if (c->empty) { -++ err = create_default_filesystem(c); -++ if (err) -++ return err; -++ } -++ -++ sup = ubifs_read_sb_node(c); -++ if (IS_ERR(sup)) -++ return PTR_ERR(sup); -++ -++ /* -++ * The software supports all previous versions but not future versions, -++ * due to the unavailability of time-travelling equipment. -++ */ -++ c->fmt_version = le32_to_cpu(sup->fmt_version); -++ if (c->fmt_version > UBIFS_FORMAT_VERSION) { -++ ubifs_err("on-flash format version is %d, but software only " -++ "supports up to version %d", c->fmt_version, -++ UBIFS_FORMAT_VERSION); -++ err = -EINVAL; -++ goto out; -++ } -++ -++ if (c->fmt_version == 1) { -++ ubifs_err("on-flash format version %d is not supported", -++ c->fmt_version); -++ err = -EINVAL; -++ goto out; -++ } -++ -++ switch (sup->key_hash) { -++ case UBIFS_KEY_HASH_R5: -++ /* TODO: this should die soon */ -++ if (c->fmt_version == 2) -++ c->key_hash = tmp_key_r5_hash; -++ else -++ c->key_hash = key_r5_hash; -++ c->key_hash_type = UBIFS_KEY_HASH_R5; -++ break; -++ -++ case UBIFS_KEY_HASH_TEST: -++ c->key_hash = key_test_hash; -++ c->key_hash_type = UBIFS_KEY_HASH_TEST; -++ break; -++ }; -++ -++ c->key_fmt = sup->key_fmt; -++ -++ switch (c->key_fmt) { -++ case UBIFS_SIMPLE_KEY_FMT: -++ c->key_len = UBIFS_SK_LEN; -++ break; -++ default: -++ ubifs_err("unsupported key format"); -++ err = -EINVAL; -++ goto out; -++ } -++ -++ c->leb_cnt = le32_to_cpu(sup->leb_cnt); -++ c->max_leb_cnt = le32_to_cpu(sup->max_leb_cnt); -++ c->max_bud_bytes = le64_to_cpu(sup->max_bud_bytes); -++ c->log_lebs = le32_to_cpu(sup->log_lebs); -++ c->lpt_lebs = le32_to_cpu(sup->lpt_lebs); -++ c->orph_lebs = le32_to_cpu(sup->orph_lebs); -++ c->jhead_cnt = le32_to_cpu(sup->jhead_cnt) + NONDATA_JHEADS_CNT; -++ c->fanout = le32_to_cpu(sup->fanout); -++ c->lsave_cnt = le32_to_cpu(sup->lsave_cnt); -++ c->default_compr = le16_to_cpu(sup->default_compr); -++ c->rp_size = le64_to_cpu(sup->rp_size); -++ c->rp_uid = le32_to_cpu(sup->rp_uid); -++ c->rp_gid = le32_to_cpu(sup->rp_gid); -++ sup_flags = le32_to_cpu(sup->flags); -++ -++ c->vfs_sb->s_time_gran = le32_to_cpu(sup->time_gran); -++ -++ c->big_lpt = !!(sup_flags & UBIFS_FLG_BIGLPT); -++ -++ /* Automatically increase file system size to the maximum size */ -++ c->old_leb_cnt = c->leb_cnt; -++ if (c->leb_cnt < c->vi.size && c->leb_cnt < c->max_leb_cnt) { -++ c->leb_cnt = min_t(int, c->max_leb_cnt, c->vi.size); -++ if (c->vfs_sb->s_flags & MS_RDONLY) -++ dbg_mnt("Auto resizing (ro) from %d LEBs to %d LEBs", -++ c->old_leb_cnt, c->leb_cnt); -++ else { -++ dbg_mnt("Auto resizing (sb) from %d LEBs to %d LEBs", -++ c->old_leb_cnt, c->leb_cnt); -++ sup->leb_cnt = cpu_to_le32(c->leb_cnt); -++ err = ubifs_write_sb_node(c, sup); -++ if (err) -++ goto out; -++ c->old_leb_cnt = c->leb_cnt; -++ } -++ } -++ -++ c->log_bytes = (long long)c->log_lebs * c->leb_size; -++ c->log_last = UBIFS_LOG_LNUM + c->log_lebs - 1; -++ c->lpt_first = UBIFS_LOG_LNUM + c->log_lebs; -++ c->lpt_last = c->lpt_first + c->lpt_lebs - 1; -++ c->orph_first = c->lpt_last + 1; -++ c->orph_last = c->orph_first + c->orph_lebs - 1; -++ c->main_lebs = c->leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS; -++ c->main_lebs -= c->log_lebs + c->lpt_lebs + c->orph_lebs; -++ c->main_first = c->leb_cnt - c->main_lebs; -++ c->report_rp_size = ubifs_reported_space(c, c->rp_size); -++ -++ err = validate_sb(c, sup); -++out: -++ kfree(sup); -++ return err; -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/scan.c linux-2.6.24.7/fs/ubifs/scan.c -+--- linux-2.6.24.7.old/fs/ubifs/scan.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/scan.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,362 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Adrian Hunter -++ * Artem Bityutskiy (Битюцкий Ðртём) -++ */ -++ -++/* -++ * This file implements the scan which is a general-purpose function for -++ * determining what nodes are in an eraseblock. The scan is used to replay the -++ * journal, to do garbage collection. for the TNC in-the-gaps method, and by -++ * debugging functions. -++ */ -++ -++#include "ubifs.h" -++ -++/** -++ * scan_padding_bytes - scan for padding bytes. -++ * @buf: buffer to scan -++ * @len: length of buffer -++ * -++ * This function returns the number of padding bytes on success and -++ * %SCANNED_GARBAGE on failure. -++ */ -++static int scan_padding_bytes(void *buf, int len) -++{ -++ int pad_len = 0, max_pad_len = min_t(int, UBIFS_PAD_NODE_SZ, len); -++ uint8_t *p = buf; -++ -++ dbg_scan("not a node"); -++ -++ while (pad_len < max_pad_len && *p++ == UBIFS_PADDING_BYTE) -++ pad_len += 1; -++ -++ if (!pad_len || (pad_len & 7)) -++ return SCANNED_GARBAGE; -++ -++ dbg_scan("%d padding bytes", pad_len); -++ -++ return pad_len; -++} -++ -++/** -++ * ubifs_scan_a_node - scan for a node or padding. -++ * @c: UBIFS file-system description object -++ * @buf: buffer to scan -++ * @len: length of buffer -++ * @lnum: logical eraseblock number -++ * @offs: offset within the logical eraseblock -++ * @quiet: print no messages -++ * -++ * This function returns a scanning code to indicate what was scanned. -++ */ -++int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum, -++ int offs, int quiet) -++{ -++ struct ubifs_ch *ch = buf; -++ uint32_t magic; -++ -++ magic = le32_to_cpu(ch->magic); -++ -++ if (magic == 0xFFFFFFFF) { -++ dbg_scan("hit empty space"); -++ return SCANNED_EMPTY_SPACE; -++ } -++ -++ if (magic != UBIFS_NODE_MAGIC) -++ return scan_padding_bytes(buf, len); -++ -++ if (len < UBIFS_CH_SZ) -++ return SCANNED_GARBAGE; -++ -++ dbg_scan("scanning %s", dbg_ntype(ch->node_type)); -++ -++ if (ubifs_check_node(c, buf, lnum, offs, quiet)) -++ return SCANNED_A_CORRUPT_NODE; -++ -++ if (ch->node_type == UBIFS_PAD_NODE) { -++ struct ubifs_pad_node *pad = buf; -++ int pad_len = le32_to_cpu(pad->pad_len); -++ int node_len = le32_to_cpu(ch->len); -++ -++ /* Validate the padding node */ -++ if (pad_len < 0 || -++ offs + node_len + pad_len > c->leb_size) { -++ if (!quiet) { -++ ubifs_err("bad pad node at LEB %d:%d", -++ lnum, offs); -++ dbg_dump_node(c, pad); -++ } -++ return SCANNED_A_BAD_PAD_NODE; -++ } -++ -++ /* Make the node pads to 8-byte boundary */ -++ if ((node_len + pad_len) & 7) { -++ if (!quiet) { -++ dbg_err("bad padding length %d - %d", -++ offs, offs + node_len + pad_len); -++ } -++ return SCANNED_A_BAD_PAD_NODE; -++ } -++ -++ dbg_scan("%d bytes padded, offset now %d", -++ pad_len, ALIGN(offs + node_len + pad_len, 8)); -++ -++ return node_len + pad_len; -++ } -++ -++ return SCANNED_A_NODE; -++} -++ -++/** -++ * ubifs_start_scan - create LEB scanning information at start of scan. -++ * @c: UBIFS file-system description object -++ * @lnum: logical eraseblock number -++ * @offs: offset to start at (usually zero) -++ * @sbuf: scan buffer (must be c->leb_size) -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++struct ubifs_scan_leb *ubifs_start_scan(const struct ubifs_info *c, int lnum, -++ int offs, void *sbuf) -++{ -++ struct ubifs_scan_leb *sleb; -++ int err; -++ -++ dbg_scan("scan LEB %d:%d", lnum, offs); -++ -++ sleb = kzalloc(sizeof(struct ubifs_scan_leb), GFP_NOFS); -++ if (!sleb) -++ return ERR_PTR(-ENOMEM); -++ -++ sleb->lnum = lnum; -++ INIT_LIST_HEAD(&sleb->nodes); -++ sleb->buf = sbuf; -++ -++ err = ubi_read(c->ubi, lnum, sbuf + offs, offs, c->leb_size - offs); -++ if (err && err != -EBADMSG) { -++ ubifs_err("cannot read %d bytes from LEB %d:%d," -++ " error %d", c->leb_size - offs, lnum, offs, err); -++ kfree(sleb); -++ return ERR_PTR(err); -++ } -++ -++ if (err == -EBADMSG) -++ sleb->ecc = 1; -++ -++ return sleb; -++} -++ -++/** -++ * ubifs_end_scan - update LEB scanning information at end of scan. -++ * @c: UBIFS file-system description object -++ * @sleb: scanning information -++ * @lnum: logical eraseblock number -++ * @offs: offset to start at (usually zero) -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++void ubifs_end_scan(const struct ubifs_info *c, struct ubifs_scan_leb *sleb, -++ int lnum, int offs) -++{ -++ lnum = lnum; -++ dbg_scan("stop scanning LEB %d at offset %d", lnum, offs); -++ ubifs_assert(offs % c->min_io_size == 0); -++ -++ sleb->endpt = ALIGN(offs, c->min_io_size); -++} -++ -++/** -++ * ubifs_add_snod - add a scanned node to LEB scanning information. -++ * @c: UBIFS file-system description object -++ * @sleb: scanning information -++ * @buf: buffer containing node -++ * @offs: offset of node on flash -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb, -++ void *buf, int offs) -++{ -++ struct ubifs_ch *ch = buf; -++ struct ubifs_ino_node *ino = buf; -++ struct ubifs_scan_node *snod; -++ -++ snod = kzalloc(sizeof(struct ubifs_scan_node), GFP_NOFS); -++ if (!snod) -++ return -ENOMEM; -++ -++ snod->sqnum = le64_to_cpu(ch->sqnum); -++ snod->type = ch->node_type; -++ snod->offs = offs; -++ snod->len = le32_to_cpu(ch->len); -++ snod->node = buf; -++ -++ switch (ch->node_type) { -++ case UBIFS_INO_NODE: -++ case UBIFS_DENT_NODE: -++ case UBIFS_XENT_NODE: -++ case UBIFS_DATA_NODE: -++ case UBIFS_TRUN_NODE: -++ /* -++ * The key is in the same place in all keyed -++ * nodes. -++ */ -++ key_read(c, &ino->key, &snod->key); -++ break; -++ } -++ list_add_tail(&snod->list, &sleb->nodes); -++ sleb->nodes_cnt += 1; -++ return 0; -++} -++ -++/** -++ * ubifs_scanned_corruption - print information after UBIFS scanned corruption. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number of corruption -++ * @offs: offset of corruption -++ * @buf: buffer containing corruption -++ */ -++void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs, -++ void *buf) -++{ -++ int len; -++ -++ ubifs_err("corrupted data at LEB %d:%d", lnum, offs); -++ if (dbg_failure_mode) -++ return; -++ len = c->leb_size - offs; -++ if (len > 4096) -++ len = 4096; -++ dbg_err("first %d bytes from LEB %d:%d", len, lnum, offs); -++ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1); -++} -++ -++/** -++ * ubifs_scan - scan a logical eraseblock. -++ * @c: UBIFS file-system description object -++ * @lnum: logical eraseblock number -++ * @offs: offset to start at (usually zero) -++ * @sbuf: scan buffer (must be c->leb_size) -++ * -++ * This function scans LEB number @lnum and returns complete information about -++ * its contents. Returns an error code in case of failure. -++ */ -++struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum, -++ int offs, void *sbuf) -++{ -++ void *buf = sbuf + offs; -++ int err, len = c->leb_size - offs; -++ struct ubifs_scan_leb *sleb; -++ -++ sleb = ubifs_start_scan(c, lnum, offs, sbuf); -++ if (IS_ERR(sleb)) -++ return sleb; -++ -++ while (len >= 8) { -++ struct ubifs_ch *ch = buf; -++ int node_len, ret; -++ -++ dbg_scan("look at LEB %d:%d (%d bytes left)", -++ lnum, offs, len); -++ -++ cond_resched(); -++ -++ ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 0); -++ -++ if (ret > 0) { -++ /* Padding bytes or a valid padding node */ -++ offs += ret; -++ buf += ret; -++ len -= ret; -++ continue; -++ } -++ -++ if (ret == SCANNED_EMPTY_SPACE) -++ /* Empty space is checked later */ -++ break; -++ -++ switch (ret) { -++ case SCANNED_GARBAGE: -++ dbg_err("garbage"); -++ goto corrupted; -++ case SCANNED_A_NODE: -++ break; -++ case SCANNED_A_CORRUPT_NODE: -++ case SCANNED_A_BAD_PAD_NODE: -++ dbg_err("bad node"); -++ goto corrupted; -++ default: -++ dbg_err("unknown"); -++ goto corrupted; -++ } -++ -++ err = ubifs_add_snod(c, sleb, buf, offs); -++ if (err) -++ goto error; -++ -++ node_len = ALIGN(le32_to_cpu(ch->len), 8); -++ offs += node_len; -++ buf += node_len; -++ len -= node_len; -++ } -++ -++ if (offs % c->min_io_size) -++ goto corrupted; -++ -++ ubifs_end_scan(c, sleb, lnum, offs); -++ -++ for (; len > 4; offs += 4, buf = buf + 4, len -= 4) -++ if (*(uint32_t *)buf != 0xffffffff) -++ break; -++ for (; len; offs++, buf++, len--) -++ if (*(uint8_t *)buf != 0xff) { -++ ubifs_err("corrupt empty space at LEB %d:%d", -++ lnum, offs); -++ goto corrupted; -++ } -++ -++ return sleb; -++ -++corrupted: -++ ubifs_scanned_corruption(c, lnum, offs, buf); -++ err = -EUCLEAN; -++error: -++ ubifs_err("LEB %d scanning failed", lnum); -++ ubifs_scan_destroy(sleb); -++ return ERR_PTR(err); -++} -++ -++/** -++ * ubifs_scan_destroy - destroy LEB scanning information. -++ * @sleb: scanning information to free -++ */ -++void ubifs_scan_destroy(struct ubifs_scan_leb *sleb) -++{ -++ struct ubifs_scan_node *node; -++ struct list_head *head; -++ -++ head = &sleb->nodes; -++ while (!list_empty(head)) { -++ node = list_entry(head->next, struct ubifs_scan_node, list); -++ list_del(&node->list); -++ kfree(node); -++ } -++ kfree(sleb); -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/shrinker.c linux-2.6.24.7/fs/ubifs/shrinker.c -+--- linux-2.6.24.7.old/fs/ubifs/shrinker.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/shrinker.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,322 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* -++ * This file implements UBIFS shrinker which evicts clean znodes from the TNC -++ * tree when Linux VM needs more RAM. -++ * -++ * We do not implement any LRU lists to find oldest znodes to free because it -++ * would add additional overhead to the file system fast paths. So the shrinker -++ * just walks the TNC tree when searching for znodes to free. -++ * -++ * If the root of a TNC sub-tree is clean and old enough, then the children are -++ * also clean and old enough. So the shrinker walks the TNC in level order and -++ * dumps entire sub-trees. -++ * -++ * The age of znodes is just the time-stamp when they were last looked at. -++ * The current shrinker first tries to evict old znodes, then young ones. -++ * -++ * Since the shrinker is global, it has to protect against races with FS -++ * un-mounts, which is done by the 'ubifs_infos_lock' and 'c->umount_mutex'. -++ */ -++ -++#include "ubifs.h" -++ -++/* List of all UBIFS file-system instances */ -++LIST_HEAD(ubifs_infos); -++ -++/* -++ * We number each shrinker run and record the number on the ubifs_info structure -++ * so that we can easily work out which ubifs_info structures have already been -++ * done by the current run. -++ */ -++static unsigned int shrinker_run_no; -++ -++/* Protects 'ubifs_infos' list */ -++DEFINE_SPINLOCK(ubifs_infos_lock); -++ -++/* Global clean znode counter (for all mounted UBIFS instances) */ -++atomic_long_t ubifs_clean_zn_cnt; -++ -++/** -++ * shrink_tnc - shrink TNC tree. -++ * @c: UBIFS file-system description object -++ * @nr: number of znodes to free -++ * @age: the age of znodes to free -++ * @contention: if any contention, this is set to %1 -++ * -++ * This function traverses TNC tree and frees clean znodes. It does not free -++ * clean znodes which younger then @age. Returns number of freed znodes. -++ */ -++static int shrink_tnc(struct ubifs_info *c, int nr, int age, int *contention) -++{ -++ int total_freed = 0; -++ struct ubifs_znode *znode, *zprev; -++ int time = get_seconds(); -++ -++ ubifs_assert(mutex_is_locked(&c->umount_mutex)); -++ ubifs_assert(mutex_is_locked(&c->tnc_mutex)); -++ -++ if (!c->zroot.znode || atomic_long_read(&c->clean_zn_cnt) == 0) -++ return 0; -++ -++ /* -++ * Traverse the TNC tree in levelorder manner, so that it is possible -++ * to destroy large sub-trees. Indeed, if a znode is old, then all its -++ * children are older or of the same age. -++ * -++ * Note, we are holding 'c->tnc_mutex', so we do not have to lock the -++ * 'c->space_lock' when _reading_ 'c->clean_zn_cnt', because it is -++ * changed only when the 'c->tnc_mutex' is held. -++ */ -++ zprev = NULL; -++ znode = ubifs_tnc_levelorder_next(c->zroot.znode, NULL); -++ while (znode && total_freed < nr && -++ atomic_long_read(&c->clean_zn_cnt) > 0) { -++ int freed; -++ -++ /* -++ * If the znode is clean, but it is in the 'c->cnext' list, this -++ * means that this znode has just been written to flash as a -++ * part of commit and was marked clean. They will be removed -++ * from the list at end commit. We cannot change the list, -++ * because it is not protected by any mutex (design decision to -++ * make commit really independent and parallel to main I/O). So -++ * we just skip these znodes. -++ * -++ * Note, the 'clean_zn_cnt' counters are not updated until -++ * after the commit, so the UBIFS shrinker does not report -++ * the znodes which are in the 'c->cnext' list as freeable. -++ * -++ * Also note, if the root of a sub-tree is not in 'c->cnext', -++ * then the whole sub-tree is not in 'c->cnext' as well, so it -++ * is safe to dump whole sub-tree. -++ */ -++ -++ if (znode->cnext) { -++ /* -++ * Very soon these znodes will be removed from the list -++ * and become freeable. -++ */ -++ *contention = 1; -++ } else if (!ubifs_zn_dirty(znode) && -++ abs(time - znode->time) >= age) { -++ if (znode->parent) -++ znode->parent->zbranch[znode->iip].znode = NULL; -++ else -++ c->zroot.znode = NULL; -++ -++ freed = ubifs_destroy_tnc_subtree(znode); -++ atomic_long_sub(freed, &ubifs_clean_zn_cnt); -++ atomic_long_sub(freed, &c->clean_zn_cnt); -++ ubifs_assert(atomic_long_read(&c->clean_zn_cnt) >= 0); -++ total_freed += freed; -++ znode = zprev; -++ } -++ -++ if (unlikely(!c->zroot.znode)) -++ break; -++ -++ zprev = znode; -++ znode = ubifs_tnc_levelorder_next(c->zroot.znode, znode); -++ cond_resched(); -++ } -++ -++ return total_freed; -++} -++ -++/** -++ * shrink_tnc_trees - shrink UBIFS TNC trees. -++ * @nr: number of znodes to free -++ * @age: the age of znodes to free -++ * @contention: if any contention, this is set to %1 -++ * -++ * This function walks the list of mounted UBIFS file-systems and frees clean -++ * znodes which are older then @age, until at least @nr znodes are freed. -++ * Returns the number of freed znodes. -++ */ -++static int shrink_tnc_trees(int nr, int age, int *contention) -++{ -++ struct ubifs_info *c; -++ struct list_head *p; -++ unsigned int run_no; -++ int freed = 0; -++ -++ spin_lock(&ubifs_infos_lock); -++ do -++ run_no = ++shrinker_run_no; -++ while (run_no == 0); -++ /* Iterate over all mounted UBIFS file-systems and try to shrink them */ -++ p = ubifs_infos.next; -++ while (p != &ubifs_infos) { -++ c = list_entry(p, struct ubifs_info, infos_list); -++ /* -++ * We move the ones we do to the end of the list, so we stop -++ * when we see one we have already done. -++ */ -++ if (c->shrinker_run_no == run_no) -++ break; -++ if (!mutex_trylock(&c->umount_mutex)) { -++ /* Some un-mount is in progress, try next FS */ -++ *contention = 1; -++ p = p->next; -++ continue; -++ } -++ /* -++ * We're holding 'c->umount_mutex', so the file-system won't go -++ * away. -++ */ -++ if (!mutex_trylock(&c->tnc_mutex)) { -++ mutex_unlock(&c->umount_mutex); -++ *contention = 1; -++ p = p->next; -++ continue; -++ } -++ spin_unlock(&ubifs_infos_lock); -++ /* -++ * OK, now we have TNC locked, the file-system cannot go away - -++ * it is safe to reap the cache. -++ */ -++ c->shrinker_run_no = run_no; -++ freed += shrink_tnc(c, nr, age, contention); -++ mutex_unlock(&c->tnc_mutex); -++ spin_lock(&ubifs_infos_lock); -++ /* Get the next list element before we move this one */ -++ p = p->next; -++ /* -++ * Move this one to the end of the list to provide some -++ * fairness. -++ */ -++ list_del(&c->infos_list); -++ list_add_tail(&c->infos_list, &ubifs_infos); -++ mutex_unlock(&c->umount_mutex); -++ if (freed >= nr) -++ break; -++ } -++ spin_unlock(&ubifs_infos_lock); -++ return freed; -++} -++ -++/** -++ * kick_a_thread - kick a background thread to start commit. -++ * -++ * This function kicks a background thread to start background commit. Returns -++ * %-1 if a thread was kicked or there is another reason to assume the memory -++ * will soon be freed or become freeable. If there are no dirty znodes, returns -++ * %0. -++ */ -++static int kick_a_thread(void) -++{ -++ int i; -++ struct ubifs_info *c; -++ -++ /* -++ * Iterate over all mounted UBIFS file-systems and find out if there is -++ * already an ongoing commit operation there. If no, then iterate for -++ * the second time and initiate background commit. -++ */ -++ spin_lock(&ubifs_infos_lock); -++ for (i = 0; i < 2; i++) { -++ list_for_each_entry(c, &ubifs_infos, infos_list) { -++ long dirty_zn_cnt; -++ -++ if (!mutex_trylock(&c->umount_mutex)) { -++ /* -++ * Some un-mount is in progress, it will -++ * certainly free memory, so just return. -++ */ -++ spin_unlock(&ubifs_infos_lock); -++ return -1; -++ } -++ -++ dirty_zn_cnt = atomic_long_read(&c->dirty_zn_cnt); -++ -++ if (!dirty_zn_cnt || c->cmt_state == COMMIT_BROKEN || -++ c->ro_media) { -++ mutex_unlock(&c->umount_mutex); -++ continue; -++ } -++ -++ if (c->cmt_state != COMMIT_RESTING) { -++ spin_unlock(&ubifs_infos_lock); -++ mutex_unlock(&c->umount_mutex); -++ return -1; -++ } -++ -++ if (i == 1) { -++ list_del(&c->infos_list); -++ list_add_tail(&c->infos_list, &ubifs_infos); -++ spin_unlock(&ubifs_infos_lock); -++ -++ ubifs_request_bg_commit(c); -++ mutex_unlock(&c->umount_mutex); -++ return -1; -++ } -++ mutex_unlock(&c->umount_mutex); -++ } -++ } -++ spin_unlock(&ubifs_infos_lock); -++ -++ return 0; -++} -++ -++int ubifs_shrinker(int nr, gfp_t gfp_mask) -++{ -++ int freed, contention = 0; -++ long clean_zn_cnt = atomic_long_read(&ubifs_clean_zn_cnt); -++ -++ if (nr == 0) -++ return clean_zn_cnt; -++ -++ if (!clean_zn_cnt) { -++ /* -++ * No clean znodes, nothing to reap. All we can do in this case -++ * is to kick background threads to start commit, which will -++ * probably make clean znodes which, in turn, will be freeable. -++ * And we return -1 which means will make VM call us again -++ * later. -++ */ -++ dbg_tnc("no clean znodes, kick a thread"); -++ return kick_a_thread(); -++ } -++ -++ freed = shrink_tnc_trees(nr, OLD_ZNODE_AGE, &contention); -++ if (freed >= nr) -++ goto out; -++ -++ dbg_tnc("not enough old znodes, try to free young ones"); -++ freed += shrink_tnc_trees(nr - freed, YOUNG_ZNODE_AGE, &contention); -++ if (freed >= nr) -++ goto out; -++ -++ dbg_tnc("not enough young znodes, free all"); -++ freed += shrink_tnc_trees(nr - freed, 0, &contention); -++ -++ if (!freed && contention) { -++ dbg_tnc("freed nothing, but contention"); -++ return -1; -++ } -++ -++out: -++ dbg_tnc("%d znodes were freed, requested %d", freed, nr); -++ return freed; -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/super.c linux-2.6.24.7/fs/ubifs/super.c -+--- linux-2.6.24.7.old/fs/ubifs/super.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/super.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,2016 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* -++ * This file implements UBIFS initialization and VFS superblock operations. Some -++ * initialization stuff which is rather large and complex is placed at -++ * corresponding subsystems, but most of it is here. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "ubifs.h" -++ -++/* Slab cache for UBIFS inodes */ -++struct kmem_cache *ubifs_inode_slab; -++ -++#ifndef UBIFS_COMPAT_NO_SHRINKER -++/* UBIFS TNC shrinker description */ -++static struct shrinker ubifs_shrinker_info = { -++ .shrink = ubifs_shrinker, -++ .seeks = DEFAULT_SEEKS, -++}; -++#endif -++ -++/** -++ * validate_inode - validate inode. -++ * @c: UBIFS file-system description object -++ * @inode: the inode to validate -++ * -++ * This is a helper function for 'ubifs_iget()' which validates various fields -++ * of a newly built inode to make sure they contain sane values and prevent -++ * possible vulnerabilities. Returns zero if the inode is all right and -++ * a non-zero error code if not. -++ */ -++#ifndef UBIFS_COMPAT_USE_OLD_IGET -++static int validate_inode(struct ubifs_info *c, const struct inode *inode) -++#else -++int validate_inode(struct ubifs_info *c, const struct inode *inode) -++#endif -++{ -++ int err; -++ const struct ubifs_inode *ui = ubifs_inode(inode); -++ -++ if (inode->i_size > c->max_inode_sz) { -++ ubifs_err("inode is too large (%lld)", -++ (long long)inode->i_size); -++ return 1; -++ } -++ -++ if (ui->compr_type < 0 || ui->compr_type >= UBIFS_COMPR_TYPES_CNT) { -++ ubifs_err("unknown compression type %d", ui->compr_type); -++ return 2; -++ } -++ -++ if (ui->xattr_cnt < 0) -++ return 3; -++ -++ if (ui->xattr_size < 0) -++ return 4; -++ -++ if (ui->xattr_names < 0 || -++ ui->xattr_names + ui->xattr_cnt > XATTR_LIST_MAX) -++ return 5; -++ -++ if (ui->data_len < 0 || ui->data_len > UBIFS_MAX_INO_DATA) -++ return 6; -++ -++ if (!ubifs_compr_present(ui->compr_type)) { -++ ubifs_warn("inode %lu uses '%s' compression, but it was not " -++ "compiled in", inode->i_ino, -++ ubifs_compr_name(ui->compr_type)); -++ } -++ -++ err = dbg_check_dir_size(c, inode); -++ return err; -++} -++ -++#ifndef UBIFS_COMPAT_USE_OLD_IGET -++struct inode *ubifs_iget(struct super_block *sb, unsigned long inum) -++{ -++ int err; -++ union ubifs_key key; -++ struct ubifs_ino_node *ino; -++ struct ubifs_info *c = sb->s_fs_info; -++ struct inode *inode; -++ struct ubifs_inode *ui; -++ -++ dbg_gen("inode %lu", inum); -++ -++ inode = iget_locked(sb, inum); -++ if (!inode) -++ return ERR_PTR(-ENOMEM); -++ if (!(inode->i_state & I_NEW)) -++ return inode; -++ ui = ubifs_inode(inode); -++ -++ ino = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS); -++ if (!ino) { -++ err = -ENOMEM; -++ goto out; -++ } -++ -++ ino_key_init(c, &key, inode->i_ino); -++ -++ err = ubifs_tnc_lookup(c, &key, ino); -++ if (err) -++ goto out_ino; -++ -++ inode->i_flags |= (S_NOCMTIME | S_NOATIME); -++ inode->i_nlink = le32_to_cpu(ino->nlink); -++ inode->i_uid = le32_to_cpu(ino->uid); -++ inode->i_gid = le32_to_cpu(ino->gid); -++ inode->i_atime.tv_sec = (int64_t)le64_to_cpu(ino->atime_sec); -++ inode->i_atime.tv_nsec = le32_to_cpu(ino->atime_nsec); -++ inode->i_mtime.tv_sec = (int64_t)le64_to_cpu(ino->mtime_sec); -++ inode->i_mtime.tv_nsec = le32_to_cpu(ino->mtime_nsec); -++ inode->i_ctime.tv_sec = (int64_t)le64_to_cpu(ino->ctime_sec); -++ inode->i_ctime.tv_nsec = le32_to_cpu(ino->ctime_nsec); -++ inode->i_mode = le32_to_cpu(ino->mode); -++ inode->i_size = le64_to_cpu(ino->size); -++ -++ ui->data_len = le32_to_cpu(ino->data_len); -++ ui->flags = le32_to_cpu(ino->flags); -++ ui->compr_type = le16_to_cpu(ino->compr_type); -++ ui->creat_sqnum = le64_to_cpu(ino->creat_sqnum); -++ ui->xattr_cnt = le32_to_cpu(ino->xattr_cnt); -++ ui->xattr_size = le64_to_cpu(ino->xattr_size); -++ ui->xattr_names = le32_to_cpu(ino->xattr_names); -++ -++ err = validate_inode(c, inode); -++ if (err) -++ goto out_invalid; -++ -++ /* Disable readahead */ -++ inode->i_mapping->backing_dev_info = &ubifs_backing_dev_info; -++ -++ switch (inode->i_mode & S_IFMT) { -++ case S_IFREG: -++ inode->i_mapping->a_ops = &ubifs_file_address_operations; -++ inode->i_op = &ubifs_file_inode_operations; -++ inode->i_fop = &ubifs_file_operations; -++ if (ui->data_len != 0) { -++ err = 10; -++ goto out_invalid; -++ } -++ break; -++ case S_IFDIR: -++ inode->i_op = &ubifs_dir_inode_operations; -++ inode->i_fop = &ubifs_dir_operations; -++ if (ui->data_len != 0) { -++ err = 11; -++ goto out_invalid; -++ } -++ break; -++ case S_IFLNK: -++ inode->i_op = &ubifs_symlink_inode_operations; -++ if (ui->data_len <= 0 || ui->data_len > UBIFS_MAX_INO_DATA) { -++ err = 12; -++ goto out_invalid; -++ } -++ ui->data = kmalloc(ui->data_len + 1, GFP_NOFS); -++ if (!ui->data) { -++ err = -ENOMEM; -++ goto out_ino; -++ } -++ memcpy(ui->data, ino->data, ui->data_len); -++ ((char *)ui->data)[ui->data_len] = '\0'; -++ break; -++ case S_IFBLK: -++ case S_IFCHR: -++ { -++ dev_t rdev; -++ union ubifs_dev_desc *dev; -++ -++ ui->data = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS); -++ if (!ui->data) { -++ err = -ENOMEM; -++ goto out_ino; -++ } -++ -++ dev = (union ubifs_dev_desc *)ino->data; -++ if (ui->data_len == sizeof(dev->new)) -++ rdev = new_decode_dev(le32_to_cpu(dev->new)); -++ else if (ui->data_len == sizeof(dev->huge)) -++ rdev = huge_decode_dev(le64_to_cpu(dev->huge)); -++ else { -++ err = 13; -++ goto out_invalid; -++ } -++ memcpy(ui->data, ino->data, ui->data_len); -++ inode->i_op = &ubifs_file_inode_operations; -++ init_special_inode(inode, inode->i_mode, rdev); -++ break; -++ } -++ case S_IFSOCK: -++ case S_IFIFO: -++ inode->i_op = &ubifs_file_inode_operations; -++ init_special_inode(inode, inode->i_mode, 0); -++ if (ui->data_len != 0) { -++ err = 14; -++ goto out_invalid; -++ } -++ break; -++ default: -++ err = 15; -++ goto out_invalid; -++ } -++ -++ kfree(ino); -++ ubifs_set_inode_flags(inode); -++ unlock_new_inode(inode); -++ return inode; -++ -++out_invalid: -++ ubifs_err("inode %lu validation failed, error %d", inode->i_ino, err); -++ dbg_dump_node(c, ino); -++ dbg_dump_inode(c, inode); -++ err = -EINVAL; -++out_ino: -++ kfree(ino); -++out: -++ ubifs_err("failed to read inode %lu, error %d", inode->i_ino, err); -++ iget_failed(inode); -++ return ERR_PTR(err); -++} -++ -++#endif /* UBIFS_COMPAT_USE_OLD_IGET */ -++ -++static struct inode *ubifs_alloc_inode(struct super_block *sb) -++{ -++ struct ubifs_inode *ui; -++ -++ ui = kmem_cache_alloc(ubifs_inode_slab, GFP_NOFS); -++ if (!ui) -++ return NULL; -++ -++ memset((void *)ui + sizeof(struct inode), 0, -++ sizeof(struct ubifs_inode) - sizeof(struct inode)); -++ mutex_init(&ui->budg_mutex); -++ return &ui->vfs_inode; -++}; -++ -++static void ubifs_destroy_inode(struct inode *inode) -++{ -++ struct ubifs_inode *ui = ubifs_inode(inode); -++ -++ kfree(ui->data); -++ kmem_cache_free(ubifs_inode_slab, inode); -++} -++ -++/* -++ * Note, Linux write-back code calls this without 'i_mutex'. -++ */ -++static int ubifs_write_inode(struct inode *inode, int wait) -++{ -++ int err; -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ struct ubifs_inode *ui = ubifs_inode(inode); -++ struct ubifs_budget_req req = {.dd_growth = c->inode_budget, -++ .dirtied_ino_d = ui->data_len}; -++ -++ ubifs_assert(!ui->xattr); -++ if (is_bad_inode(inode)) -++ return 0; -++ -++ mutex_lock(&ui->budg_mutex); -++ -++ /* -++ * Due to races between write-back forced by budgeting -++ * (see 'sync_some_inodes()') and pdflush write-back, the inode may -++ * have already been synchronized, do not do this again. -++ * -++ * This might also happen if it was synchronized in e.g. ubifs_link()', -++ * etc. -++ */ -++ if (!ui->dirty) { -++ mutex_unlock(&ui->budg_mutex); -++ return 0; -++ } -++ -++ ubifs_assert(ui->budgeted); -++ dbg_gen("inode %lu", inode->i_ino); -++ -++ err = ubifs_jnl_write_inode(c, inode, 0, IS_SYNC(inode)); -++ if (err) -++ ubifs_err("can't write inode %lu, error %d", inode->i_ino, err); -++ -++ ui->dirty = 0; -++ UBIFS_DBG(ui->budgeted = 0); -++ atomic_long_dec(&c->dirty_ino_cnt); -++ -++ ubifs_release_budget(c, &req); -++ mutex_unlock(&ui->budg_mutex); -++ -++ return err; -++} -++ -++static void ubifs_delete_inode(struct inode *inode) -++{ -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ struct ubifs_inode *ui = ubifs_inode(inode); -++ struct ubifs_budget_req req = {.dd_growth = c->inode_budget, -++ .dirtied_ino_d = ui->data_len}; -++ int err; -++ -++ if (ui->xattr) { -++ /* -++ * Extended attribute inode deletions are fully handled in -++ * 'ubifs_removexattr()'. These inodes are special and have -++ * limited usage, so there is nothing to do here. -++ */ -++ ubifs_assert(!ui->dirty); -++ goto out; -++ } -++ -++ dbg_gen("inode %lu", inode->i_ino); -++ ubifs_assert(!atomic_read(&inode->i_count)); -++ ubifs_assert(inode->i_nlink == 0); -++ -++ truncate_inode_pages(&inode->i_data, 0); -++ if (is_bad_inode(inode)) -++ goto out; -++ -++ mutex_lock(&ui->budg_mutex); -++ -++ inode->i_size = 0; -++ -++ err = ubifs_jnl_write_inode(c, inode, 1, IS_SYNC(inode)); -++ if (err) -++ /* -++ * Worst case we have a lost orphan inode wasting space, so a -++ * simple error message is ok here. -++ */ -++ ubifs_err("can't write inode %lu, error %d", inode->i_ino, err); -++ -++ if (ui->dirty) { -++ ubifs_assert(ui->budgeted); -++ atomic_long_dec(&c->dirty_ino_cnt); -++ ui->dirty = 0; -++ UBIFS_DBG(ui->budgeted = 0); -++ ubifs_release_budget(c, &req); -++ } -++ -++ mutex_unlock(&ui->budg_mutex); -++out: -++ clear_inode(inode); -++} -++ -++static void ubifs_dirty_inode(struct inode *inode) -++{ -++ struct ubifs_inode *ui = ubifs_inode(inode); -++ -++ ubifs_assert(mutex_is_locked(&ui->budg_mutex)); -++ if (!ui->dirty) { -++ struct ubifs_info *c = inode->i_sb->s_fs_info; -++ -++ ui->dirty = 1; -++ atomic_long_inc(&c->dirty_ino_cnt); -++ dbg_gen("inode %lu", inode->i_ino); -++ } -++} -++ -++static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf) -++{ -++ struct ubifs_info *c = dentry->d_sb->s_fs_info; -++ unsigned long long free; -++ -++ free = ubifs_budg_get_free_space(c); -++ dbg_gen("free space %lld bytes (%lld blocks)", -++ free, free >> UBIFS_BLOCK_SHIFT); -++ -++ buf->f_type = UBIFS_SUPER_MAGIC; -++ buf->f_bsize = UBIFS_BLOCK_SIZE; -++ buf->f_blocks = c->block_cnt; -++ buf->f_bfree = free >> UBIFS_BLOCK_SHIFT; -++ if (free > c->report_rp_size) -++ buf->f_bavail = (free - c->report_rp_size) >> UBIFS_BLOCK_SHIFT; -++ else -++ buf->f_bavail = 0; -++ buf->f_files = 0; -++ buf->f_ffree = 0; -++ buf->f_namelen = UBIFS_MAX_NLEN; -++ -++ return 0; -++} -++ -++static int ubifs_show_options(struct seq_file *s, struct vfsmount *mnt) -++{ -++ struct ubifs_info *c = mnt->mnt_sb->s_fs_info; -++ -++ if (c->mount_opts.unmount_mode == 2) -++ seq_printf(s, ",fast_unmount"); -++ else if (c->mount_opts.unmount_mode == 1) -++ seq_printf(s, ",norm_unmount"); -++ -++ return 0; -++} -++ -++static int ubifs_sync_fs(struct super_block *sb, int wait) -++{ -++ struct ubifs_info *c = sb->s_fs_info; -++ int i, ret = 0, err; -++ -++ if (c->jheads) -++ for (i = 0; i < c->jhead_cnt; i++) { -++ err = ubifs_wbuf_sync(&c->jheads[i].wbuf); -++ if (err && !ret) -++ ret = err; -++ } -++ /* -++ * We ought to call sync for c->ubi but it does not have one. If it had -++ * it would in turn call mtd->sync, however mtd operations are -++ * synchronous anyway, so we don't lose any sleep here. -++ */ -++ return ret; -++} -++ -++/** -++ * init_constants_early - initialize UBIFS constants. -++ * @c: UBIFS file-system description object -++ * -++ * This function initialize UBIFS constants which do not need the superblock to -++ * be read. It also checks that the UBI volume satisfies basic UBIFS -++ * requirements. Returns zero in case of success and a negative error code in -++ * case of failure. -++ */ -++static int init_constants_early(struct ubifs_info *c) -++{ -++ if (c->vi.corrupted) { -++ ubifs_warn("UBI volume is corrupted - read-only mode"); -++ c->ro_media = 1; -++ } -++ -++ if (c->di.ro_mode) { -++ ubifs_msg("read-only UBI device"); -++ c->ro_media = 1; -++ } -++ -++ if (c->vi.vol_type == UBI_STATIC_VOLUME) { -++ ubifs_msg("static UBI volume - read-only mode"); -++ c->ro_media = 1; -++ } -++ -++ c->leb_cnt = c->vi.size; -++ c->leb_size = c->vi.usable_leb_size; -++ c->half_leb_size = c->leb_size / 2; -++ c->min_io_size = c->di.min_io_size; -++ c->min_io_shift = fls(c->min_io_size) - 1; -++ -++ if (c->leb_size < UBIFS_MIN_LEB_SZ) { -++ ubifs_err("too small LEBs (%d bytes), min. is %d bytes", -++ c->leb_size, UBIFS_MIN_LEB_SZ); -++ return -EINVAL; -++ } -++ -++ if (c->leb_cnt < UBIFS_MIN_LEB_CNT) { -++ ubifs_err("too few LEBs (%d), min. is %d", -++ c->leb_cnt, UBIFS_MIN_LEB_CNT); -++ return -EINVAL; -++ } -++ -++ if (!is_power_of_2(c->min_io_size)) { -++ ubifs_err("bad min. I/O size %d", c->min_io_size); -++ return -EINVAL; -++ } -++ -++ /* -++ * UBIFS aligns all node to 8-byte boundary, so to make function in -++ * io.c simpler, assume minimum I/O unit size to be 8 bytes if it is -++ * less than 8. -++ */ -++ if (c->min_io_size < 8) { -++ c->min_io_size = 8; -++ c->min_io_shift = 3; -++ } -++ -++ c->ref_node_alsz = ALIGN(UBIFS_REF_NODE_SZ, c->min_io_size); -++ c->mst_node_alsz = ALIGN(UBIFS_MST_NODE_SZ, c->min_io_size); -++ -++ /* -++ * Initialize node length ranges which are mostly needed for node -++ * length validation. -++ */ -++ c->ranges[UBIFS_PAD_NODE].len = UBIFS_PAD_NODE_SZ; -++ c->ranges[UBIFS_SB_NODE].len = UBIFS_SB_NODE_SZ; -++ c->ranges[UBIFS_MST_NODE].len = UBIFS_MST_NODE_SZ; -++ c->ranges[UBIFS_REF_NODE].len = UBIFS_REF_NODE_SZ; -++ c->ranges[UBIFS_TRUN_NODE].len = UBIFS_TRUN_NODE_SZ; -++ c->ranges[UBIFS_CS_NODE].len = UBIFS_CS_NODE_SZ; -++ -++ c->ranges[UBIFS_INO_NODE].min_len = UBIFS_INO_NODE_SZ; -++ c->ranges[UBIFS_INO_NODE].max_len = UBIFS_MAX_INO_NODE_SZ; -++ c->ranges[UBIFS_ORPH_NODE].min_len = -++ UBIFS_ORPH_NODE_SZ + sizeof(__le64); -++ c->ranges[UBIFS_ORPH_NODE].max_len = c->leb_size; -++ c->ranges[UBIFS_DENT_NODE].min_len = UBIFS_DENT_NODE_SZ; -++ c->ranges[UBIFS_DENT_NODE].max_len = UBIFS_MAX_DENT_NODE_SZ; -++ c->ranges[UBIFS_XENT_NODE].min_len = UBIFS_XENT_NODE_SZ; -++ c->ranges[UBIFS_XENT_NODE].max_len = UBIFS_MAX_XENT_NODE_SZ; -++ c->ranges[UBIFS_DATA_NODE].min_len = UBIFS_DATA_NODE_SZ; -++ c->ranges[UBIFS_DATA_NODE].max_len = UBIFS_MAX_DATA_NODE_SZ; -++ /* -++ * Minimum indexing node size is amended later when superblock is -++ * read and the key length is known. -++ */ -++ c->ranges[UBIFS_IDX_NODE].min_len = UBIFS_IDX_NODE_SZ + UBIFS_BRANCH_SZ; -++ /* -++ * Maximum indexing node size is amended later when superblock is -++ * read and the fanout is known. -++ */ -++ c->ranges[UBIFS_IDX_NODE].max_len = INT_MAX; -++ -++ /* -++ * Initialize dead and dark LEB space watermarks. -++ * -++ * Dead space is the space which cannot be used. Its watermark is -++ * equivalent to min. I/O unit or minimum node size if it is greater -++ * then min. I/O unit. -++ * -++ * Dark space is the space which might be used, or might not, depending -++ * on which node should be written to the LEB. Its watermark is -++ * equivalent to maximum UBIFS node size. -++ */ -++ c->dead_wm = ALIGN(MIN_WRITE_SZ, c->min_io_size); -++ c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size); -++ -++ return 0; -++} -++ -++/** -++ * bud_wbuf_callback - bud LEB write-buffer synchronization call-back. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB the write-buffer was synchronized to -++ * @free: how many free bytes left in this LEB -++ * @pad: how many bytes were padded -++ * -++ * This is a callback function which is called by the I/O unit when the -++ * write-buffer is synchronized. We need this to correctly maintain space -++ * accounting in bud logical eraseblocks. This function returns zero in case of -++ * success and a negative error code in case of failure. -++ * -++ * This function actually belongs to the journal, but we keep it here because -++ * we want to keep it static. -++ */ -++static int bud_wbuf_callback(struct ubifs_info *c, int lnum, int free, int pad) -++{ -++ return ubifs_update_one_lp(c, lnum, free, pad, 0, 0); -++} -++ -++/* -++ * init_constants_late - initialize UBIFS constants. -++ * @c: UBIFS file-system description object -++ * -++ * This is a helper function which initializes various UBIFS constants after -++ * the superblock has been read. It also checks various UBIFS parameters and -++ * makes sure they are all right. Returns zero in case of success and a -++ * negative error code in case of failure. -++ */ -++static int init_constants_late(struct ubifs_info *c) -++{ -++ int tmp, err; -++ uint64_t tmp64; -++ -++ c->main_bytes = c->main_lebs * c->leb_size; -++ -++ c->max_znode_sz = sizeof(struct ubifs_znode) + -++ c->fanout * sizeof(struct ubifs_zbranch); -++ -++ tmp = ubifs_idx_node_sz(c, 1); -++ c->ranges[UBIFS_IDX_NODE].min_len = tmp; -++ c->min_idx_node_sz = ALIGN(tmp, 8); -++ -++ tmp = ubifs_idx_node_sz(c, c->fanout); -++ c->ranges[UBIFS_IDX_NODE].max_len = tmp; -++ c->max_idx_node_sz = ALIGN(tmp, 8); -++ -++ /* Make sure LEB size is large enough to fit full commit */ -++ tmp = UBIFS_CS_NODE_SZ + UBIFS_REF_NODE_SZ * c->jhead_cnt; -++ tmp = ALIGN(tmp, c->min_io_size); -++ if (tmp > c->leb_size) { -++ dbg_err("too small LEB size %d, at least %d needed", -++ c->leb_size, tmp); -++ return -EINVAL; -++ } -++ -++ /* -++ * Make sure that the log is large enough to fit reference nodes for -++ * all buds plus one reserved LEB. -++ */ -++ tmp64 = c->max_bud_bytes; -++ tmp = do_div(tmp64, c->leb_size); -++ c->max_bud_cnt = tmp64 + !!tmp; -++ tmp = (c->ref_node_alsz * c->max_bud_cnt + c->leb_size - 1); -++ tmp /= c->leb_size; -++ tmp += 1; -++ if (c->log_lebs < tmp) { -++ dbg_err("too small log %d LEBs, required min. %d LEBs", -++ c->log_lebs, tmp); -++ return -EINVAL; -++ } -++ -++ /* -++ * When budgeting we assume worst-case scenarios when the pages are not -++ * be compressed and direntries are of the maximum size. -++ * -++ * Note, data, which may be stored in inodes is budgeted separately, so -++ * it is not included into 'c->inode_budget'. -++ */ -++ c->page_budget = UBIFS_MAX_DATA_NODE_SZ * UBIFS_BLOCKS_PER_PAGE; -++ c->inode_budget = UBIFS_INO_NODE_SZ; -++ c->dent_budget = UBIFS_MAX_DENT_NODE_SZ; -++ -++ /* -++ * When the amount of flash space used by buds becomes -++ * 'c->max_bud_bytes', UBIFS just blocks all writers and starts commit. -++ * The writers are unblocked when the commit is finished. To avoid -++ * writers to be blocked UBIFS initiates background commit in advance, -++ * when number of bud bytes becomes above the limit defined below. -++ */ -++ c->bg_bud_bytes = (c->max_bud_bytes * 13) >> 4; -++ -++ /* -++ * Ensure minimum journal size. All the bytes in the journal heads are -++ * considered to be used, when calculating the current journal usage. -++ * Consequently, if the journal is too small, UBIFS will treat it as -++ * always full. -++ */ -++ tmp64 = (uint64_t)(c->jhead_cnt + 1) * c->leb_size + 1; -++ if (c->bg_bud_bytes < tmp64) -++ c->bg_bud_bytes = tmp64; -++ if (c->max_bud_bytes < tmp64 + c->leb_size) -++ c->max_bud_bytes = tmp64 + c->leb_size; -++ -++ err = ubifs_calc_lpt_geom(c); -++ if (err) -++ return err; -++ -++ c->min_idx_lebs = ubifs_calc_min_idx_lebs(c); -++ -++ /* -++ * Calculate total amount of FS blocks. This number is not used -++ * internally because it does not make much sense for UBIFS, but it is -++ * necessary to report something for the 'statfs()' call. -++ * -++ * Subtract the LEB reserved for GC and the LEB which is reserved for -++ * deletions. -++ * -++ * Review 'ubifs_calc_available()' if changing this calculation. -++ */ -++ tmp64 = c->main_lebs - 2; -++ tmp64 *= c->leb_size - c->dark_wm; -++ tmp64 = ubifs_reported_space(c, tmp64); -++ c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT; -++ -++ return 0; -++} -++ -++/** -++ * care_about_gc_lnum - take care about reserved GC LEB. -++ * @c: UBIFS file-system description object -++ * -++ * This function ensures that the LEB reserved for garbage collection is -++ * unmapped and is marked as "taken" in lprops. We also have to set free space -++ * to LEB size and dirty space to zero, because lprops may contain out-of-date -++ * information if the file-system was un-mounted before it has been committed. -++ * This function returns zero in case of success and a negative error code in -++ * case of failure. -++ */ -++static int care_about_gc_lnum(struct ubifs_info *c) -++{ -++ int err; -++ -++ if (c->gc_lnum == -1) { -++ ubifs_err("no LEB for GC"); -++ return -EINVAL; -++ } -++ -++ err = ubifs_leb_unmap(c, c->gc_lnum); -++ if (err) -++ return err; -++ -++ /* And we have to tell lprops that this LEB is taken */ -++ err = ubifs_change_one_lp(c, c->gc_lnum, c->leb_size, 0, -++ LPROPS_TAKEN, 0, 0); -++ return err; -++} -++ -++/** -++ * alloc_wbufs - allocate write-buffers. -++ * @c: UBIFS file-system description object -++ * -++ * This helper function allocates and initializes UBIFS write-buffers. Returns -++ * zero in case of success and %-ENOMEM in case of failure. -++ */ -++static int alloc_wbufs(struct ubifs_info *c) -++{ -++ int i, err; -++ -++ c->jheads = kzalloc(c->jhead_cnt * sizeof(struct ubifs_jhead), -++ GFP_KERNEL); -++ if (!c->jheads) -++ return -ENOMEM; -++ -++ /* Initialize journal heads */ -++ for (i = 0; i < c->jhead_cnt; i++) { -++ INIT_LIST_HEAD(&c->jheads[i].buds_list); -++ err = ubifs_wbuf_init(c, &c->jheads[i].wbuf); -++ if (err) -++ return err; -++ -++ c->jheads[i].wbuf.sync_callback = &bud_wbuf_callback; -++ c->jheads[i].wbuf.jhead = i; -++ } -++ -++ c->jheads[BASEHD].wbuf.dtype = UBI_SHORTTERM; -++ /* -++ * Garbage Collector head likely contains long-term data and -++ * does not need to be synchronized by timer. -++ */ -++ c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM; -++ c->jheads[GCHD].wbuf.timeout = 0; -++ -++ return 0; -++} -++ -++/** -++ * free_wbufs - free write-buffers. -++ * @c: UBIFS file-system description object -++ */ -++static void free_wbufs(struct ubifs_info *c) -++{ -++ int i; -++ -++ if (c->jheads) { -++ for (i = 0; i < c->jhead_cnt; i++) { -++ kfree(c->jheads[i].wbuf.buf); -++ kfree(c->jheads[i].wbuf.inodes); -++ } -++ kfree(c->jheads); -++ c->jheads = NULL; -++ } -++} -++ -++/** -++ * free_orphans - free orphans. -++ * @c: UBIFS file-system description object -++ */ -++static void free_orphans(struct ubifs_info *c) -++{ -++ struct ubifs_orphan *orph; -++ -++ while (c->orph_dnext) { -++ orph = c->orph_dnext; -++ c->orph_dnext = orph->dnext; -++ list_del(&orph->list); -++ kfree(orph); -++ } -++ -++ while (!list_empty(&c->orph_list)) { -++ orph = list_entry(c->orph_list.next, struct ubifs_orphan, list); -++ list_del(&orph->list); -++ kfree(orph); -++ dbg_err("orphan list not empty at unmount"); -++ } -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(c->orph_buf); -++#else -++ vfree(c->orph_buf); -++#endif -++ c->orph_buf = NULL; -++} -++ -++/** -++ * free_buds - free per-bud objects. -++ * @c: UBIFS file-system description object -++ */ -++static void free_buds(struct ubifs_info *c) -++{ -++ struct rb_node *this = c->buds.rb_node; -++ struct ubifs_bud *bud; -++ -++ while (this) { -++ if (this->rb_left) -++ this = this->rb_left; -++ else if (this->rb_right) -++ this = this->rb_right; -++ else { -++ bud = rb_entry(this, struct ubifs_bud, rb); -++ this = rb_parent(this); -++ if (this) { -++ if (this->rb_left == &bud->rb) -++ this->rb_left = NULL; -++ else -++ this->rb_right = NULL; -++ } -++ kfree(bud); -++ } -++ } -++} -++ -++/** -++ * check_volume_empty - check if the UBI volume is empty. -++ * @c: UBIFS file-system description object -++ * -++ * This function checks if the UBIFS volume is empty by looking if its LEBs are -++ * mapped or not. The result of checking is stored in the @c->empty variable. -++ * Returns zero in case of success and a negative error code in case of -++ * failure. -++ */ -++static int check_volume_empty(struct ubifs_info *c) -++{ -++ int lnum, err; -++ -++ c->empty = 1; -++ for (lnum = 0; lnum < c->leb_cnt; lnum++) { -++ err = ubi_is_mapped(c->ubi, lnum); -++ if (unlikely(err < 0)) -++ return err; -++ if (err == 1) { -++ c->empty = 0; -++ break; -++ } -++ -++ cond_resched(); -++ } -++ -++ return 0; -++} -++ -++/* -++ * UBIFS mount options. -++ * -++ * Opt_fast_unmount: do not run a journal commit before un-mounting -++ * Opt_norm_unmount: run a journal commit before un-mounting -++ * Opt_err: just end of array marker -++ */ -++enum { -++ Opt_fast_unmount, -++ Opt_norm_unmount, -++ Opt_err, -++}; -++ -++static match_table_t tokens = { -++ {Opt_fast_unmount, "fast_unmount"}, -++ {Opt_norm_unmount, "norm_unmount"}, -++ {Opt_err, NULL}, -++}; -++ -++/** -++ * ubifs_parse_options - parse mount parameters. -++ * @c: UBIFS file-system description object -++ * @options: parameters to parse -++ * @is_remount: non-zero if this is FS re-mount -++ * -++ * This function parses UBIFS mount options and returns zero in case success -++ * and a negative error code in case of failure. -++ */ -++static int ubifs_parse_options(struct ubifs_info *c, char *options, -++ int is_remount) -++{ -++ char *p; -++ substring_t args[MAX_OPT_ARGS]; -++ -++ if (!options) -++ return 0; -++ -++ while ((p = strsep(&options, ","))) { -++ int token; -++ -++ if (!*p) -++ continue; -++ -++ token = match_token(p, tokens, args); -++ switch (token) { -++ case Opt_fast_unmount: -++ c->mount_opts.unmount_mode = 2; -++ c->fast_unmount = 1; -++ break; -++ case Opt_norm_unmount: -++ c->mount_opts.unmount_mode = 1; -++ c->fast_unmount = 0; -++ break; -++ default: -++ ubifs_err("unrecognized mount option \"%s\" " -++ "or missing value", p); -++ return -EINVAL; -++ } -++ } -++ -++ return 0; -++} -++ -++/** -++ * destroy_journal - destroy journal data structures. -++ * @c: UBIFS file-system description object -++ * -++ * This function destroys journal data structures including those that may have -++ * been created by recovery functions. -++ */ -++static void destroy_journal(struct ubifs_info *c) -++{ -++ while (!list_empty(&c->unclean_leb_list)) { -++ struct ubifs_unclean_leb *ucleb; -++ -++ ucleb = list_entry(c->unclean_leb_list.next, -++ struct ubifs_unclean_leb, list); -++ list_del(&ucleb->list); -++ kfree(ucleb); -++ } -++ while (!list_empty(&c->old_buds)) { -++ struct ubifs_bud *bud; -++ -++ bud = list_entry(c->old_buds.next, struct ubifs_bud, list); -++ list_del(&bud->list); -++ kfree(bud); -++ } -++ ubifs_destroy_idx_gc(c); -++ ubifs_destroy_size_tree(c); -++ ubifs_tnc_close(c); -++ free_buds(c); -++} -++ -++/** -++ * mount_ubifs - mount UBIFS file-system. -++ * @c: UBIFS file-system description object -++ * -++ * This function mounts UBIFS file system. Returns zero in case of success and -++ * a negative error code in case of failure. -++ * -++ * Note, the function does not de-allocate resources it it fails half way -++ * through, and the caller has to do this instead. -++ */ -++static int mount_ubifs(struct ubifs_info *c) -++{ -++ struct super_block *sb = c->vfs_sb; -++ int err, mounted_read_only = (sb->s_flags & MS_RDONLY); -++ unsigned long long x; -++ size_t sz; -++ -++ err = init_constants_early(c); -++ if (err) -++ return err; -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ c->dbg_buf = kmalloc(c->leb_size, GFP_KERNEL); -++#else -++ c->dbg_buf = vmalloc(c->leb_size); -++#endif -++ if (!c->dbg_buf) -++ return -ENOMEM; -++#endif -++ -++ err = check_volume_empty(c); -++ if (err) -++ goto out_free; -++ -++ if (c->empty && (mounted_read_only || c->ro_media)) { -++ /* -++ * This UBI volume is empty, and read-only, or the file system -++ * is mounted read-only - we cannot format it. -++ */ -++ ubifs_err("can't format empty UBI volume: read-only %s", -++ c->ro_media ? "UBI volume" : "mount"); -++ err = -EROFS; -++ goto out_free; -++ } -++ -++ if (c->ro_media && !mounted_read_only) { -++ ubifs_err("cannot mount read-write - read-only media"); -++ err = -EROFS; -++ goto out_free; -++ } -++ -++ /* -++ * The requirement for the buffer is that it should fit indexing B-tree -++ * height amount of integers. We assume the height if the TNC tree will -++ * never exceed 64. -++ */ -++ err = -ENOMEM; -++ c->bottom_up_buf = kmalloc(BOTTOM_UP_HEIGHT * sizeof(int), GFP_KERNEL); -++ if (!c->bottom_up_buf) -++ goto out_free; -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ c->sbuf = kmalloc(c->leb_size, GFP_KERNEL); -++#else -++ c->sbuf = vmalloc(c->leb_size); -++#endif -++ if (!c->sbuf) -++ goto out_free; -++ -++ if (!mounted_read_only) { -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ c->ileb_buf = kmalloc(c->leb_size, GFP_KERNEL); -++#else -++ c->ileb_buf = vmalloc(c->leb_size); -++#endif -++ if (!c->ileb_buf) -++ goto out_free; -++ } -++ -++ err = ubifs_read_superblock(c); -++ if (err) -++ goto out_free; -++ -++ /* -++ * Make sure the compressor which is set as the default on in the -++ * superblock was actually compiled in. -++ */ -++ if (!ubifs_compr_present(c->default_compr)) { -++ ubifs_warn("'%s' compressor is set by superblock, but not " -++ "compiled in", ubifs_compr_name(c->default_compr)); -++ c->default_compr = UBIFS_COMPR_NONE; -++ } -++ -++ dbg_failure_mode_registration(c); -++ -++ err = init_constants_late(c); -++ if (err) -++ goto out_dereg; -++ -++ sz = ALIGN(c->max_idx_node_sz, c->min_io_size); -++ sz = ALIGN(sz + c->max_idx_node_sz, c->min_io_size); -++ c->cbuf = kmalloc(sz, GFP_NOFS); -++ if (!c->cbuf) { -++ err = -ENOMEM; -++ goto out_dereg; -++ } -++ -++ if (!mounted_read_only) { -++ err = alloc_wbufs(c); -++ if (err) -++ goto out_cbuf; -++ -++ /* Create background thread */ -++ sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, -++ c->vi.vol_id); -++ c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name); -++ if (!c->bgt) -++ c->bgt = ERR_PTR(-EINVAL); -++ if (IS_ERR(c->bgt)) { -++ err = PTR_ERR(c->bgt); -++ c->bgt = NULL; -++ ubifs_err("cannot spawn \"%s\", error %d", -++ c->bgt_name, err); -++ goto out_wbufs; -++ } -++ wake_up_process(c->bgt); -++ } -++ -++ err = ubifs_read_master(c); -++ if (err) -++ goto out_stop; -++ -++ if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) { -++ ubifs_msg("recovery needed"); -++ c->need_recovery = 1; -++ if (!mounted_read_only) { -++ err = ubifs_recover_inl_heads(c, c->sbuf); -++ if (err) -++ goto out_master; -++ } -++ } else if (!mounted_read_only) { -++ /* -++ * Set the "dirty" flag so that if we reboot uncleanly we -++ * will notice this immediately on the next mount. -++ */ -++ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); -++ err = ubifs_write_master(c); -++ if (err) -++ goto out_master; -++ } -++ -++ err = ubifs_lpt_init(c, 1, !mounted_read_only); -++ if (err) -++ goto out_master; -++ -++ err = dbg_check_idx_size(c, c->old_idx_sz); -++ if (err) -++ goto out_lpt; -++ -++ err = ubifs_replay_journal(c); -++ if (err) -++ goto out_journal; -++ -++ if (!mounted_read_only) { -++ int lnum; -++ -++ err = ubifs_mount_orphans(c, c->need_recovery); -++ if (err) -++ goto out_journal; -++ -++ if (c->need_recovery) -++ err = ubifs_recover_gc_lnum(c); -++ else -++ err = care_about_gc_lnum(c); -++ if (err) -++ goto out_orphans; -++ -++ /* Check for enough log space */ -++ lnum = c->lhead_lnum + 1; -++ if (lnum >= UBIFS_LOG_LNUM + c->log_lebs) -++ lnum = UBIFS_LOG_LNUM; -++ if (lnum == c->ltail_lnum) { -++ err = ubifs_consolidate_log(c); -++ if (err) -++ goto out_orphans; -++ } -++ -++ /* Check for enough free space */ -++ if (ubifs_calc_available(c) <= 0) { -++ ubifs_err("insufficient available space"); -++ err = -EINVAL; -++ goto out_orphans; -++ } -++ -++ err = dbg_check_lprops(c); -++ if (err) -++ goto out_orphans; -++ } -++ -++ if (c->need_recovery) { -++ err = ubifs_recover_size(c); -++ if (err) -++ goto out_orphans; -++ } -++ -++ spin_lock(&ubifs_infos_lock); -++ list_add_tail(&c->infos_list, &ubifs_infos); -++ spin_unlock(&ubifs_infos_lock); -++ -++ if (c->need_recovery) { -++ if (mounted_read_only) -++ ubifs_msg("recovery deferred"); -++ else { -++ c->need_recovery = 0; -++ ubifs_msg("recovery completed"); -++ } -++ } -++ -++ ubifs_msg("mounted UBI device %d, volume %d", c->vi.ubi_num, -++ c->vi.vol_id); -++ if (mounted_read_only) -++ ubifs_msg("mounted read-only"); -++ ubifs_msg("minimal I/O unit size: %d bytes", c->min_io_size); -++ ubifs_msg("logical eraseblock size: %d bytes (%d KiB)", -++ c->leb_size, c->leb_size / 1024); -++ x = (unsigned long long)c->main_lebs * c->leb_size; -++ ubifs_msg("file system size: %lld bytes (%lld KiB, %lld MiB, " -++ "%d LEBs)", x, x >> 10, x >> 20, c->main_lebs); -++ x = (unsigned long long)c->log_lebs * c->leb_size + c->max_bud_bytes; -++ ubifs_msg("journal size: %lld bytes (%lld KiB, %lld MiB, " -++ "%d LEBs)", x, x >> 10, x >> 20, -++ c->log_lebs + c->max_bud_cnt); -++ ubifs_msg("data journal heads: %d", -++ c->jhead_cnt - NONDATA_JHEADS_CNT); -++ ubifs_msg("default compressor: %s", -++ ubifs_compr_name(c->default_compr)); -++ ubifs_msg("media format %d, latest format %d", -++ c->fmt_version, UBIFS_FORMAT_VERSION); -++ -++ dbg_msg("compiled on: " __DATE__ " at " __TIME__); -++ dbg_msg("fast unmount: %d", c->fast_unmount); -++ dbg_msg("big_lpt %d", c->big_lpt); -++ dbg_msg("log LEBs: %d (%d - %d)", -++ c->log_lebs, UBIFS_LOG_LNUM, c->log_last); -++ dbg_msg("LPT area LEBs: %d (%d - %d)", -++ c->lpt_lebs, c->lpt_first, c->lpt_last); -++ dbg_msg("orphan area LEBs: %d (%d - %d)", -++ c->orph_lebs, c->orph_first, c->orph_last); -++ dbg_msg("main area LEBs: %d (%d - %d)", -++ c->main_lebs, c->main_first, c->leb_cnt - 1); -++ dbg_msg("index LEBs: %d", c->lst.idx_lebs); -++ dbg_msg("total index bytes: %lld (%lld KiB, %lld MiB)", -++ c->old_idx_sz, c->old_idx_sz >> 10, c->old_idx_sz >> 20); -++ dbg_msg("key hash type: %d", c->key_hash_type); -++ dbg_msg("tree fanout: %d", c->fanout); -++ dbg_msg("reserved GC LEB: %d", c->gc_lnum); -++ dbg_msg("first main LEB: %d", c->main_first); -++ dbg_msg("dead watermark: %d", c->dead_wm); -++ dbg_msg("dark watermark: %d", c->dark_wm); -++ x = c->main_lebs * c->dark_wm; -++ dbg_msg("max. dark space: %lld (%lld KiB, %lld MiB)", -++ x, x >> 10, x >> 20); -++ dbg_msg("maximum bud bytes: %lld (%lld KiB, %lld MiB)", -++ c->max_bud_bytes, c->max_bud_bytes >> 10, -++ c->max_bud_bytes >> 20); -++ dbg_msg("BG commit bud bytes: %lld (%lld KiB, %lld MiB)", -++ c->bg_bud_bytes, c->bg_bud_bytes >> 10, -++ c->bg_bud_bytes >> 20); -++ dbg_msg("current bud bytes %lld (%lld KiB, %lld MiB)", -++ c->bud_bytes, c->bud_bytes >> 10, c->bud_bytes >> 20); -++ dbg_msg("max. seq. number: %llu", c->max_sqnum); -++ dbg_msg("commit number: %llu", c->cmt_no); -++ -++ return 0; -++ -++out_orphans: -++ free_orphans(c); -++out_journal: -++ destroy_journal(c); -++out_lpt: -++ ubifs_lpt_free(c, 0); -++out_master: -++ kfree(c->mst_node); -++ kfree(c->rcvrd_mst_node); -++out_stop: -++ if (c->bgt) -++ kthread_stop(c->bgt); -++out_wbufs: -++ free_wbufs(c); -++out_cbuf: -++ kfree(c->cbuf); -++out_dereg: -++ dbg_failure_mode_deregistration(c); -++out_free: -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(c->ileb_buf); -++ kfree(c->sbuf); -++ UBIFS_DBG(kfree(c->dbg_buf)); -++#else -++ vfree(c->ileb_buf); -++ vfree(c->sbuf); -++ UBIFS_DBG(vfree(c->dbg_buf)); -++#endif -++ kfree(c->bottom_up_buf); -++ return err; -++} -++ -++/** -++ * ubifs_umount - un-mount UBIFS file-system. -++ * @c: UBIFS file-system description object -++ * -++ * Note, this function is called to free allocated resourced when un-mounting, -++ * as well as free resources when an error occurred while we were half way -++ * through mounting (error path cleanup function). So it has to make sure the -++ * resource was actually allocated before freeing it. -++ */ -++static void ubifs_umount(struct ubifs_info *c) -++{ -++ dbg_gen("un-mounting UBI device %d, volume %d", c->vi.ubi_num, -++ c->vi.vol_id); -++ -++ if (c->bgt) -++ kthread_stop(c->bgt); -++ -++ destroy_journal(c); -++ free_wbufs(c); -++ free_orphans(c); -++ ubifs_lpt_free(c, 0); -++ -++ kfree(c->cbuf); -++ kfree(c->rcvrd_mst_node); -++ kfree(c->mst_node); -++ kfree(c->bottom_up_buf); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(c->sbuf); -++ UBIFS_DBG(kfree(c->dbg_buf)); -++ kfree(c->ileb_buf); -++#else -++ vfree(c->sbuf); -++ UBIFS_DBG(vfree(c->dbg_buf)); -++ vfree(c->ileb_buf); -++#endif -++ dbg_failure_mode_deregistration(c); -++} -++ -++/** -++ * ubifs_remount_rw - re-mount in read-write mode. -++ * @c: UBIFS file-system description object -++ * -++ * UBIFS avoids allocating many unnecessary resources when mounted in read-only -++ * mode. This function allocates the needed resources and re-mounts UBIFS in -++ * read-write mode. -++ */ -++static int ubifs_remount_rw(struct ubifs_info *c) -++{ -++ int err, lnum; -++ -++ if (c->ro_media) -++ return -EINVAL; -++ -++ mutex_lock(&c->umount_mutex); -++ c->remounting_rw = 1; -++ -++ /* Check for enough free space */ -++ if (ubifs_calc_available(c) <= 0) { -++ ubifs_err("insufficient available space"); -++ err = -EINVAL; -++ goto out; -++ } -++ -++ if (c->old_leb_cnt != c->leb_cnt) { -++ struct ubifs_sb_node *sup; -++ -++ sup = ubifs_read_sb_node(c); -++ if (IS_ERR(sup)) { -++ err = PTR_ERR(sup); -++ goto out; -++ } -++ sup->leb_cnt = cpu_to_le32(c->leb_cnt); -++ err = ubifs_write_sb_node(c, sup); -++ if (err) -++ goto out; -++ } -++ -++ if (c->need_recovery) { -++ ubifs_msg("completing deferred recovery"); -++ err = ubifs_write_rcvrd_mst_node(c); -++ if (err) -++ goto out; -++ err = ubifs_recover_size(c); -++ if (err) -++ goto out; -++ err = ubifs_clean_lebs(c, c->sbuf); -++ if (err) -++ goto out; -++ err = ubifs_recover_inl_heads(c, c->sbuf); -++ if (err) -++ goto out; -++ } -++ -++ if (!(c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY))) { -++ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); -++ err = ubifs_write_master(c); -++ if (err) -++ goto out; -++ } -++ -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ c->ileb_buf = kmalloc(c->leb_size, GFP_KERNEL); -++#else -++ c->ileb_buf = vmalloc(c->leb_size); -++#endif -++ if (!c->ileb_buf) { -++ err = -ENOMEM; -++ goto out; -++ } -++ -++ err = ubifs_lpt_init(c, 0, 1); -++ if (err) -++ goto out; -++ -++ err = alloc_wbufs(c); -++ if (err) -++ goto out; -++ -++ ubifs_create_buds_lists(c); -++ -++ /* Create background thread */ -++ c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name); -++ if (!c->bgt) -++ c->bgt = ERR_PTR(-EINVAL); -++ if (IS_ERR(c->bgt)) { -++ err = PTR_ERR(c->bgt); -++ c->bgt = NULL; -++ ubifs_err("cannot spawn \"%s\", error %d", -++ c->bgt_name, err); -++ return err; -++ } -++ wake_up_process(c->bgt); -++ -++ err = ubifs_mount_orphans(c, c->need_recovery); -++ if (err) -++ goto out; -++ -++ if (c->need_recovery) -++ err = ubifs_recover_gc_lnum(c); -++ else -++ err = care_about_gc_lnum(c); -++ if (err) -++ goto out; -++ -++ /* Check for enough log space */ -++ lnum = c->lhead_lnum + 1; -++ if (lnum >= UBIFS_LOG_LNUM + c->log_lebs) -++ lnum = UBIFS_LOG_LNUM; -++ if (lnum == c->ltail_lnum) { -++ err = ubifs_consolidate_log(c); -++ if (err) -++ goto out; -++ } -++ -++ if (c->need_recovery) { -++ c->need_recovery = 0; -++ ubifs_msg("deferred recovery completed"); -++ } -++ -++ dbg_gen("re-mounted read-write"); -++ c->vfs_sb->s_flags &= ~MS_RDONLY; -++ c->remounting_rw = 0; -++ mutex_unlock(&c->umount_mutex); -++ return 0; -++ -++out: -++ free_orphans(c); -++ if (c->bgt) { -++ kthread_stop(c->bgt); -++ c->bgt = NULL; -++ } -++ free_wbufs(c); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(c->ileb_buf); -++#else -++ vfree(c->ileb_buf); -++#endif -++ c->ileb_buf = NULL; -++ ubifs_lpt_free(c, 1); -++ c->remounting_rw = 0; -++ mutex_unlock(&c->umount_mutex); -++ return err; -++} -++ -++/** -++ * commit_on_unmount - commit the journal when un-mounting. -++ * @c: UBIFS file-system description object -++ * -++ * This function is called during un-mounting and it commits the journal unless -++ * the "fast unmount" mode is enabled. It also avoids committing the journal if -++ * it contains too few data. -++ * -++ * Sometimes recovery requires the journal to be committed at least once, and -++ * this function takes care about this. -++ */ -++static void commit_on_unmount(struct ubifs_info *c) -++{ -++ if (!c->fast_unmount) { -++ long long bud_bytes; -++ -++ spin_lock(&c->buds_lock); -++ bud_bytes = c->bud_bytes; -++ spin_unlock(&c->buds_lock); -++ if (bud_bytes > c->leb_size) -++ ubifs_run_commit(c); -++ } -++ -++ if (c->recovery_needs_commit) -++ ubifs_recovery_commit(c); -++} -++ -++/** -++ * ubifs_remount_ro - re-mount in read-only mode. -++ * @c: UBIFS file-system description object -++ * -++ * We rely on VFS to have stopped writing. Possibly the background thread could -++ * be running a commit, however kthread_stop will wait in that case. -++ */ -++static void ubifs_remount_ro(struct ubifs_info *c) -++{ -++ int i, err; -++ -++ ubifs_assert(!c->need_recovery); -++ commit_on_unmount(c); -++ -++ mutex_lock(&c->umount_mutex); -++ if (c->bgt) { -++ kthread_stop(c->bgt); -++ c->bgt = NULL; -++ } -++ -++ for (i = 0; i < c->jhead_cnt; i++) { -++ ubifs_wbuf_sync(&c->jheads[i].wbuf); -++ del_timer_sync(&c->jheads[i].wbuf.timer); -++ } -++ -++ if (!c->ro_media) { -++ c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); -++ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); -++ c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum); -++ err = ubifs_write_master(c); -++ if (err) -++ ubifs_ro_mode(c, err); -++ } -++ -++ ubifs_destroy_idx_gc(c); -++ free_wbufs(c); -++ free_orphans(c); -++#if defined(CONFIG_MTD_NAND_DMA) && !defined(CONFIG_MTD_NAND_DMABUF) -++ kfree(c->ileb_buf); -++#else -++ vfree(c->ileb_buf); -++#endif -++ c->ileb_buf = NULL; -++ ubifs_lpt_free(c, 1); -++ mutex_unlock(&c->umount_mutex); -++} -++ -++static void ubifs_put_super(struct super_block *sb) -++{ -++ int i; -++ struct ubifs_info *c = sb->s_fs_info; -++ -++ ubifs_msg("un-mount UBI device %d, volume %d", c->vi.ubi_num, -++ c->vi.vol_id); -++ /* -++ * The following asserts are only valid if there has not been a failure -++ * of the media. For example, there will be dirty inodes if we failed -++ * to write them back because of I/O errors. -++ */ -++ ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0); -++ ubifs_assert(atomic_long_read(&c->dirty_ino_cnt) == 0); -++ ubifs_assert(c->budg_idx_growth == 0); -++ ubifs_assert(c->budg_data_growth == 0); -++ -++ /* -++ * The 'c->umount_lock' prevents races between UBIFS memory shrinker -++ * and file system un-mount. Namely, it prevents the shrinker from -++ * picking this superblock for shrinking - it will be just skipped if -++ * the mutex is locked. -++ */ -++ mutex_lock(&c->umount_mutex); -++ -++ spin_lock(&ubifs_infos_lock); -++ list_del(&c->infos_list); -++ spin_unlock(&ubifs_infos_lock); -++ -++ if (!(c->vfs_sb->s_flags & MS_RDONLY)) { -++ /* -++ * First of all kill the background thread to make sure it does -++ * not interfere with un-mounting and freeing resources. -++ */ -++ if (c->bgt) { -++ kthread_stop(c->bgt); -++ c->bgt = NULL; -++ } -++ -++ /* Synchronize write-buffers */ -++ if (c->jheads) -++ for (i = 0; i < c->jhead_cnt; i++) { -++ ubifs_wbuf_sync(&c->jheads[i].wbuf); -++ del_timer_sync(&c->jheads[i].wbuf.timer); -++ } -++ -++ /* -++ * On fatal errors c->ro_media is set to 1, in which case we do -++ * not write the master node. -++ */ -++ if (!c->ro_media) { -++ /* -++ * We are being cleanly unmounted which means the -++ * orphans were killed - indicate this in the master -++ * node. Also save the reserved GC LEB number. -++ */ -++ int err; -++ -++ c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); -++ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); -++ c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum); -++ err = ubifs_write_master(c); -++ if (err) -++ /* -++ * Recovery will attempt to fix the master area -++ * next mount, so we just print a message and -++ * continue to unmount normally. -++ */ -++ ubifs_err("failed to write master node, " -++ "error %d", err); -++ } -++ } -++ -++ ubifs_umount(c); -++ ubi_close_volume(c->ubi); -++ mutex_unlock(&c->umount_mutex); -++ kfree(c); -++} -++ -++static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) -++{ -++ int err; -++ struct ubifs_info *c = sb->s_fs_info; -++ -++ dbg_gen("old flags %#lx, new flags %#x", sb->s_flags, *flags); -++ -++ err = ubifs_parse_options(c, data, 1); -++ if (err) { -++ ubifs_err("invalid or unknown remount parameter"); -++ return err; -++ } -++ if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { -++ err = ubifs_remount_rw(c); -++ if (err) -++ return err; -++ } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) -++ ubifs_remount_ro(c); -++ -++ return 0; -++} -++ -++struct super_operations ubifs_super_operations = { -++#ifdef UBIFS_COMPAT_USE_OLD_IGET -++ .read_inode = ubifs_read_inode, -++#endif -++ .alloc_inode = ubifs_alloc_inode, -++ .destroy_inode = ubifs_destroy_inode, -++ .put_super = ubifs_put_super, -++ .write_inode = ubifs_write_inode, -++ .delete_inode = ubifs_delete_inode, -++ .statfs = ubifs_statfs, -++ .dirty_inode = ubifs_dirty_inode, -++ .remount_fs = ubifs_remount_fs, -++ .show_options = ubifs_show_options, -++ .sync_fs = ubifs_sync_fs, -++}; -++ -++/** -++ * open_ubi - parse UBI device name string and open the UBI device. -++ * @name: UBI volume name -++ * @mode: UBI volume open mode -++ * -++ * There are several ways to specify UBI volumes when mounting UBIFS: -++ * o ubiX_Y - UBI device number X, volume Y; -++ * o ubiY - UBI device number 0, volume Y; -++ * o ubiX:NAME - mount UBI device X, volume with name NAME; -++ * o ubi:NAME - mount UBI device 0, volume with name NAME. -++ * -++ * Alternative '!' separator may be used instead of ':' (because some shells -++ * like busybox may interpret ':' as an NFS host name separator). This function -++ * returns ubi volume object in case of success and a negative error code in -++ * case of failure. -++ */ -++static struct ubi_volume_desc *open_ubi(const char *name, int mode) -++{ -++ int dev, vol; -++ char *endptr; -++ -++ if (name[0] != 'u' || name[1] != 'b' || name[2] != 'i') -++ return ERR_PTR(-EINVAL); -++ -++ /* ubi:NAME method */ -++ if ((name[3] == ':' || name[3] == '!') && name[4] != '\0') -++ return ubi_open_volume_nm(0, name + 4, mode); -++ -++ if (!isdigit(name[3])) -++ return ERR_PTR(-EINVAL); -++ -++ dev = simple_strtoul(name + 3, &endptr, 0); -++ -++ /* ubiY method */ -++ if (*endptr == '\0') -++ return ubi_open_volume(0, dev, mode); -++ -++ /* ubiX_Y method */ -++ if (*endptr == '_' && isdigit(endptr[1])) { -++ vol = simple_strtoul(endptr + 1, &endptr, 0); -++ if (*endptr != '\0') -++ return ERR_PTR(-EINVAL); -++ return ubi_open_volume(dev, vol, mode); -++ } -++ -++ /* ubiX:NAME method */ -++ if ((*endptr == ':' || *endptr == '!') && endptr[1] != '\0') -++ return ubi_open_volume_nm(dev, ++endptr, mode); -++ -++ return ERR_PTR(-EINVAL); -++} -++ -++static int ubifs_fill_super(struct super_block *sb, void *data, int silent) -++{ -++ struct ubi_volume_desc *ubi = sb->s_fs_info; -++ struct ubifs_info *c; -++ struct inode *root; -++ int err; -++ -++ c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL); -++ if (!c) -++ return -ENOMEM; -++ -++ spin_lock_init(&c->cnt_lock); -++ spin_lock_init(&c->cs_lock); -++ spin_lock_init(&c->buds_lock); -++ spin_lock_init(&c->space_lock); -++ spin_lock_init(&c->orphan_lock); -++ init_rwsem(&c->commit_sem); -++ mutex_init(&c->lp_mutex); -++ mutex_init(&c->tnc_mutex); -++ mutex_init(&c->log_mutex); -++ mutex_init(&c->mst_mutex); -++ mutex_init(&c->umount_mutex); -++ init_waitqueue_head(&c->cmt_wq); -++ c->buds = RB_ROOT; -++ c->old_idx = RB_ROOT; -++ c->size_tree = RB_ROOT; -++ c->orph_tree = RB_ROOT; -++ INIT_LIST_HEAD(&c->infos_list); -++ INIT_LIST_HEAD(&c->idx_gc); -++ INIT_LIST_HEAD(&c->replay_list); -++ INIT_LIST_HEAD(&c->replay_buds); -++ INIT_LIST_HEAD(&c->uncat_list); -++ INIT_LIST_HEAD(&c->empty_list); -++ INIT_LIST_HEAD(&c->freeable_list); -++ INIT_LIST_HEAD(&c->frdi_idx_list); -++ INIT_LIST_HEAD(&c->unclean_leb_list); -++ INIT_LIST_HEAD(&c->old_buds); -++ INIT_LIST_HEAD(&c->orph_list); -++ INIT_LIST_HEAD(&c->orph_new); -++ -++ c->highest_inum = UBIFS_FIRST_INO; -++ get_random_bytes(&c->vfs_gen, sizeof(int)); -++ c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM; -++ -++ ubi_get_volume_info(ubi, &c->vi); -++ ubi_get_device_info(c->vi.ubi_num, &c->di); -++ -++ /* Re-open the UBI device in read-write mode */ -++ c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READWRITE); -++ if (IS_ERR(c->ubi)) { -++ err = PTR_ERR(c->ubi); -++ goto out_free; -++ } -++ -++ err = ubifs_parse_options(c, data, 0); -++ if (err) -++ goto out_close; -++ -++ c->vfs_sb = sb; -++ -++ sb->s_fs_info = c; -++ sb->s_magic = UBIFS_SUPER_MAGIC; -++ sb->s_blocksize = UBIFS_BLOCK_SIZE; -++ sb->s_blocksize_bits = UBIFS_BLOCK_SHIFT; -++ sb->s_dev = c->vi.cdev; -++ sb->s_maxbytes = c->max_inode_sz = key_max_inode_size(c); -++ if (c->max_inode_sz > MAX_LFS_FILESIZE) -++ sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE; -++ sb->s_op = &ubifs_super_operations; -++ -++ mutex_lock(&c->umount_mutex); -++ err = mount_ubifs(c); -++ if (err) { -++ ubifs_assert(err < 0); -++ goto out_unlock; -++ } -++ -++ /* Read the root inode */ -++ root = ubifs_iget(sb, UBIFS_ROOT_INO); -++ if (IS_ERR(root)) { -++ err = PTR_ERR(root); -++ goto out_umount; -++ } -++ -++ sb->s_root = d_alloc_root(root); -++ if (!sb->s_root) -++ goto out_iput; -++ -++ mutex_unlock(&c->umount_mutex); -++ -++ return 0; -++ -++out_iput: -++ iput(root); -++out_umount: -++ spin_lock(&ubifs_infos_lock); -++ list_del(&c->infos_list); -++ spin_unlock(&ubifs_infos_lock); -++ ubifs_umount(c); -++out_unlock: -++ mutex_unlock(&c->umount_mutex); -++out_close: -++ ubi_close_volume(c->ubi); -++out_free: -++ kfree(c); -++ return err; -++} -++ -++static int sb_test(struct super_block *sb, void *data) -++{ -++ dev_t *dev = data; -++ -++ return sb->s_dev == *dev; -++} -++ -++static int sb_set(struct super_block *sb, void *data) -++{ -++ dev_t *dev = data; -++ -++ sb->s_dev = *dev; -++ return 0; -++} -++ -++static int ubifs_get_sb(struct file_system_type *fs_type, int flags, -++ const char *name, void *data, struct vfsmount *mnt) -++{ -++ struct ubi_volume_desc *ubi; -++ struct ubi_volume_info vi; -++ struct super_block *sb; -++ int err; -++ -++ dbg_gen("name %s, flags %#x", name, flags); -++ -++ /* -++ * Get UBI device number and volume ID. Mount it read-only so far -++ * because this might be a new mount point, and UBI allows only one -++ * read-write user at a time. -++ */ -++ ubi = open_ubi(name, UBI_READONLY); -++ if (IS_ERR(ubi)) { -++ ubifs_err("cannot open \"%s\", error %d", -++ name, (int)PTR_ERR(ubi)); -++ return PTR_ERR(ubi); -++ } -++ ubi_get_volume_info(ubi, &vi); -++ -++ dbg_gen("opened ubi%d_%d", vi.ubi_num, vi.vol_id); -++ -++ sb = sget(fs_type, &sb_test, &sb_set, &vi.cdev); -++ if (IS_ERR(sb)) { -++ err = PTR_ERR(sb); -++ goto out_close; -++ } -++ -++ if (sb->s_root) { -++ /* A new mount point for already mounted UBIFS */ -++ dbg_gen("this ubi volume is already mounted"); -++ if ((flags ^ sb->s_flags) & MS_RDONLY) { -++ err = -EBUSY; -++ goto out_deact; -++ } -++ } else { -++ sb->s_flags = flags; -++ /* -++ * Pass 'ubi' to 'fill_super()' in sb->s_fs_info where it is -++ * replaced by 'c'. -++ */ -++ sb->s_fs_info = ubi; -++ err = ubifs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); -++ if (err) -++ goto out_deact; -++ /* We do not support atime */ -++ sb->s_flags |= MS_ACTIVE | MS_NOATIME; -++ } -++ -++ /* 'fill_super()' opens ubi again so we must close it here */ -++ ubi_close_volume(ubi); -++ -++ return simple_set_mnt(mnt, sb); -++ -++out_deact: -++ up_write(&sb->s_umount); -++ deactivate_super(sb); -++out_close: -++ ubi_close_volume(ubi); -++ return err; -++} -++ -++static void ubifs_kill_sb(struct super_block *sb) -++{ -++ struct ubifs_info *c = sb->s_fs_info; -++ -++ /* -++ * We do 'commit_on_unmount()' here instead of 'ubifs_put_super()' -++ * in order to be outside BKL. -++ */ -++ if (sb->s_root && !(sb->s_flags & MS_RDONLY)) -++ commit_on_unmount(c); -++ /* The un-mount routine is actually done in put_super() */ -++ generic_shutdown_super(sb); -++} -++ -++static struct file_system_type ubifs_fs_type = { -++ .name = "ubifs", -++ .owner = THIS_MODULE, -++ .get_sb = ubifs_get_sb, -++ .kill_sb = ubifs_kill_sb -++}; -++ -++/* -++ * Inode slab cache constructor. -++ */ -++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) -++static void inode_slab_ctor(void *obj, struct kmem_cache *cachep, -++ unsigned long flags) -++#else -++static void inode_slab_ctor(struct kmem_cache *cachep, void *obj) -++#endif -++{ -++ struct ubifs_inode *inode = obj; -++ inode_init_once(&inode->vfs_inode); -++} -++ -++static int __init ubifs_init(void) -++{ -++ int err; -++ -++ BUILD_BUG_ON(sizeof(struct ubifs_ch) != 24); -++ -++ /* Make sure node sizes are 8-byte aligned */ -++ BUILD_BUG_ON(UBIFS_CH_SZ & 7); -++ BUILD_BUG_ON(UBIFS_INO_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_DENT_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_XENT_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_DATA_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_TRUN_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_SB_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_MST_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_REF_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_CS_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_ORPH_NODE_SZ & 7); -++ -++ BUILD_BUG_ON(UBIFS_MAX_DENT_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_MAX_XENT_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_MAX_DATA_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_MAX_INO_NODE_SZ & 7); -++ BUILD_BUG_ON(UBIFS_MAX_NODE_SZ & 7); -++ BUILD_BUG_ON(MIN_WRITE_SZ & 7); -++ -++ /* Check min. node size */ -++ BUILD_BUG_ON(UBIFS_INO_NODE_SZ < MIN_WRITE_SZ); -++ BUILD_BUG_ON(UBIFS_DENT_NODE_SZ < MIN_WRITE_SZ); -++ BUILD_BUG_ON(UBIFS_XENT_NODE_SZ < MIN_WRITE_SZ); -++ BUILD_BUG_ON(UBIFS_TRUN_NODE_SZ < MIN_WRITE_SZ); -++ -++ BUILD_BUG_ON(UBIFS_MAX_DENT_NODE_SZ > UBIFS_MAX_NODE_SZ); -++ BUILD_BUG_ON(UBIFS_MAX_XENT_NODE_SZ > UBIFS_MAX_NODE_SZ); -++ BUILD_BUG_ON(UBIFS_MAX_DATA_NODE_SZ > UBIFS_MAX_NODE_SZ); -++ BUILD_BUG_ON(UBIFS_MAX_INO_NODE_SZ > UBIFS_MAX_NODE_SZ); -++ -++ /* Defined node sizes */ -++ BUILD_BUG_ON(UBIFS_SB_NODE_SZ != 4096); -++ BUILD_BUG_ON(UBIFS_MST_NODE_SZ != 512); -++ BUILD_BUG_ON(UBIFS_INO_NODE_SZ != 160); -++ BUILD_BUG_ON(UBIFS_REF_NODE_SZ != 64); -++ -++ /* -++ * We require that PAGE_CACHE_SIZE is greater-than-or-equal-to -++ * UBIFS_BLOCK_SIZE. It is assumed that both are powers of 2. -++ */ -++ if (PAGE_CACHE_SIZE < UBIFS_BLOCK_SIZE) { -++ ubifs_err("VFS page cache size is %u bytes, but UBIFS requires" -++ " at least 4096 bytes", -++ (unsigned int)PAGE_CACHE_SIZE); -++ return -EINVAL; -++ } -++ -++ err = bdi_init(&ubifs_backing_dev_info); -++ if (err) -++ return err; -++ -++ err = register_filesystem(&ubifs_fs_type); -++ if (err) { -++ ubifs_err("cannot register file system, error %d", err); -++ goto out; -++ } -++ -++ err = -ENOMEM; -++ ubifs_inode_slab = kmem_cache_create("ubifs_inode_slab", -++ sizeof(struct ubifs_inode), 0, -++ SLAB_MEM_SPREAD | SLAB_RECLAIM_ACCOUNT, -++ &inode_slab_ctor UBIFSCOMPATNULL); -++ if (!ubifs_inode_slab) -++ goto out_reg; -++ -++ register_shrinker(&ubifs_shrinker_info); -++ -++ err = ubifs_compressors_init(); -++ if (err) -++ goto out_compr; -++ -++ return 0; -++ -++out_compr: -++ unregister_shrinker(&ubifs_shrinker_info); -++ kmem_cache_destroy(ubifs_inode_slab); -++out_reg: -++ unregister_filesystem(&ubifs_fs_type); -++out: -++ bdi_destroy(&ubifs_backing_dev_info); -++ return err; -++} -++/* late_initcall to let compressors initialize first */ -++late_initcall(ubifs_init); -++ -++static void __exit ubifs_exit(void) -++{ -++ ubifs_assert(list_empty(&ubifs_infos)); -++ ubifs_assert(atomic_long_read(&ubifs_clean_zn_cnt) == 0); -++ -++ ubifs_compressors_exit(); -++ unregister_shrinker(&ubifs_shrinker_info); -++ kmem_cache_destroy(ubifs_inode_slab); -++ unregister_filesystem(&ubifs_fs_type); -++ bdi_destroy(&ubifs_backing_dev_info); -++} -++module_exit(ubifs_exit); -++ -++MODULE_LICENSE("GPL"); -++MODULE_VERSION(__stringify(UBIFS_VERSION)); -++MODULE_AUTHOR("Artem Bityutskiy, Adrian Hunter"); -++MODULE_DESCRIPTION("UBIFS - UBI File System"); -+diff -urN linux-2.6.24.7.old/fs/ubifs/tnc.c linux-2.6.24.7/fs/ubifs/tnc.c -+--- linux-2.6.24.7.old/fs/ubifs/tnc.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/tnc.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,3300 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Adrian Hunter -++ * Artem Bityutskiy (Битюцкий Ðртём) -++ */ -++ -++/* -++ * This file implements TNC (Tree Node Cache) which caches indexing nodes of -++ * the UBIFS B-tree. -++ * -++ * At the moment the locking rules of the TNC tree are quite simple and -++ * straightforward. We just have a mutex and lock it when we traverse the -++ * tree. If a znode is not in memory, we read it from flash while still having -++ * the mutex locked. -++ */ -++ -++#include -++#include "ubifs.h" -++ -++/* -++ * Returned codes of 'matches_name()' and 'fallible_matches_name()' functions. -++ * @NAME_LESS: name corresponding to the first argument is less than second -++ * @NAME_MATCHES: names match -++ * @NAME_GREATER: name corresponding to the second argument is greater than -++ * first -++ * @NOT_ON_MEDIA: node referred by zbranch does not exist on the media -++ * -++ * These constants were introduce to improve readability. -++ */ -++enum { -++ NAME_LESS = 0, -++ NAME_MATCHES = 1, -++ NAME_GREATER = 2, -++ NOT_ON_MEDIA = 3, -++}; -++ -++/** -++ * insert_old_idx - record an index node obsoleted since the last commit start. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number of obsoleted index node -++ * @offs: offset of obsoleted index node -++ * -++ * Returns %0 on success, and a negative error code on failure. -++ * -++ * For recovery, there must always be a complete intact version of the index on -++ * flash at all times. That is called the "old index". It is the index as at the -++ * time of the last successful commit. Many of the index nodes in the old index -++ * may be dirty, but they must not be erased until the next successful commit -++ * (at which point that index becomes the old index). -++ * -++ * That means that the garbage collection and the in-the-gaps method of -++ * committing must be able to determine if an index node is in the old index. -++ * Most of the old index nodes can be found by looking up the TNC using the -++ * 'lookup_znode()' function. However, some of the old index nodes may have -++ * been deleted from the current index or may have been changed so much that -++ * they cannot be easily found. In those cases, an entry is added to an RB-tree. -++ * That is what this function does. The RB-tree is ordered by LEB number and -++ * offset because they uniquely identify the old index node. -++ */ -++static int insert_old_idx(struct ubifs_info *c, int lnum, int offs) -++{ -++ struct ubifs_old_idx *old_idx, *o; -++ struct rb_node **p, *parent = NULL; -++ -++ old_idx = kmalloc(sizeof(struct ubifs_old_idx), GFP_NOFS); -++ if (unlikely(!old_idx)) -++ return -ENOMEM; -++ old_idx->lnum = lnum; -++ old_idx->offs = offs; -++ -++ p = &c->old_idx.rb_node; -++ while (*p) { -++ parent = *p; -++ o = rb_entry(parent, struct ubifs_old_idx, rb); -++ if (lnum < o->lnum) -++ p = &(*p)->rb_left; -++ else if (lnum > o->lnum) -++ p = &(*p)->rb_right; -++ else if (offs < o->offs) -++ p = &(*p)->rb_left; -++ else if (offs > o->offs) -++ p = &(*p)->rb_right; -++ else { -++ ubifs_err("old idx added twice!"); -++ kfree(old_idx); -++ return 0; -++ } -++ } -++ rb_link_node(&old_idx->rb, parent, p); -++ rb_insert_color(&old_idx->rb, &c->old_idx); -++ return 0; -++} -++ -++/** -++ * insert_old_idx_znode - record a znode obsoleted since last commit start. -++ * @c: UBIFS file-system description object -++ * @znode: znode of obsoleted index node -++ * -++ * Returns %0 on success, and a negative error code on failure. -++ */ -++int insert_old_idx_znode(struct ubifs_info *c, struct ubifs_znode *znode) -++{ -++ if (znode->parent) { -++ struct ubifs_zbranch *zbr; -++ -++ zbr = &znode->parent->zbranch[znode->iip]; -++ if (zbr->len) -++ return insert_old_idx(c, zbr->lnum, zbr->offs); -++ } else -++ if (c->zroot.len) -++ return insert_old_idx(c, c->zroot.lnum, -++ c->zroot.offs); -++ return 0; -++} -++ -++/** -++ * ins_clr_old_idx_znode - record a znode obsoleted since last commit start. -++ * @c: UBIFS file-system description object -++ * @znode: znode of obsoleted index node -++ * -++ * Returns %0 on success, and a negative error code on failure. -++ */ -++static int ins_clr_old_idx_znode(struct ubifs_info *c, -++ struct ubifs_znode *znode) -++{ -++ int err; -++ -++ if (znode->parent) { -++ struct ubifs_zbranch *zbr; -++ -++ zbr = &znode->parent->zbranch[znode->iip]; -++ if (zbr->len) { -++ err = insert_old_idx(c, zbr->lnum, zbr->offs); -++ if (err) -++ return err; -++ zbr->lnum = 0; -++ zbr->offs = 0; -++ zbr->len = 0; -++ } -++ } else -++ if (c->zroot.len) { -++ err = insert_old_idx(c, c->zroot.lnum, c->zroot.offs); -++ if (err) -++ return err; -++ c->zroot.lnum = 0; -++ c->zroot.offs = 0; -++ c->zroot.len = 0; -++ } -++ return 0; -++} -++ -++/** -++ * destroy_old_idx - destroy the old_idx RB-tree. -++ * @c: UBIFS file-system description object -++ * -++ * During start commit, the old_idx RB-tree is used to avoid overwriting index -++ * nodes that were in the index last commit but have since been deleted. This -++ * is necessary for recovery i.e. the old index must be kept intact until the -++ * new index is successfully written. The old-idx RB-tree is used for the -++ * in-the-gaps method of writing index nodes and is destroyed every commit. -++ */ -++void destroy_old_idx(struct ubifs_info *c) -++{ -++ struct rb_node *this = c->old_idx.rb_node; -++ struct ubifs_old_idx *old_idx; -++ -++ while (this) { -++ if (this->rb_left) { -++ this = this->rb_left; -++ continue; -++ } else if (this->rb_right) { -++ this = this->rb_right; -++ continue; -++ } -++ old_idx = rb_entry(this, struct ubifs_old_idx, rb); -++ this = rb_parent(this); -++ if (this) { -++ if (this->rb_left == &old_idx->rb) -++ this->rb_left = NULL; -++ else -++ this->rb_right = NULL; -++ } -++ kfree(old_idx); -++ } -++ c->old_idx = RB_ROOT; -++} -++ -++/** -++ * read_znode - read an indexing node from flash and fill znode. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB of the indexing node to read -++ * @offs: node offset -++ * @len: node length -++ * @znode: znode to read to -++ * -++ * This function reads an indexing node from the flash media and fills znode -++ * with the read data. Returns zero in case of success and a negative error -++ * code in case of failure. The read indexing node is validated and if anything -++ * is wrong with it, this function prints complaint messages and returns -++ * %-EINVAL. -++ */ -++static int read_znode(struct ubifs_info *c, int lnum, int offs, int len, -++ struct ubifs_znode *znode) -++{ -++ int i, err, type, cmp; -++ struct ubifs_idx_node *idx; -++ -++ idx = kmalloc(c->max_idx_node_sz, GFP_NOFS); -++ if (!idx) -++ return -ENOMEM; -++ -++ err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs); -++ if (err < 0) -++ goto out; -++ -++ znode->child_cnt = le16_to_cpu(idx->child_cnt); -++ znode->level = le16_to_cpu(idx->level); -++ -++ dbg_tnc("LEB %d:%d, level %d, %d branch", -++ lnum, offs, znode->level, znode->child_cnt); -++ -++ if (znode->child_cnt > c->fanout || znode->level > UBIFS_MAX_LEVELS) { -++ dbg_err("current fanout %d, branch count %d", -++ c->fanout, znode->child_cnt); -++ dbg_err("max levels %d, znode level %d", -++ UBIFS_MAX_LEVELS, znode->level); -++ goto out_dump; -++ } -++ -++ for (i = 0; i < znode->child_cnt; i++) { -++ const struct ubifs_branch *br = ubifs_idx_branch(c, idx, i); -++ struct ubifs_zbranch *zbr = &znode->zbranch[i]; -++ -++ key_read(c, &br->key, &zbr->key); -++ zbr->lnum = le32_to_cpu(br->lnum); -++ zbr->offs = le32_to_cpu(br->offs); -++ zbr->len = le32_to_cpu(br->len); -++ zbr->znode = NULL; -++ -++ /* Validate branch */ -++ -++ if (zbr->lnum < c->main_first || -++ zbr->lnum >= c->leb_cnt || zbr->offs < 0 || -++ zbr->offs + zbr->len > c->leb_size || zbr->offs & 7) { -++ dbg_err("bad branch %d", i); -++ goto out_dump; -++ } -++ -++ switch (key_type(c, &zbr->key)) { -++ case UBIFS_INO_KEY: -++ case UBIFS_DATA_KEY: -++ case UBIFS_DENT_KEY: -++ case UBIFS_XENT_KEY: -++ break; -++ default: -++ dbg_msg("bad key type at slot %d: %s", i, -++ DBGKEY(&zbr->key)); -++ goto out_dump; -++ } -++ -++ if (znode->level) -++ continue; -++ -++ type = key_type(c, &zbr->key); -++ if (c->ranges[type].max_len == 0) { -++ if (zbr->len != c->ranges[type].len) { -++ dbg_err("bad target node (type %d) length (%d)", -++ type, zbr->len); -++ dbg_err("have to be %d", c->ranges[type].len); -++ goto out_dump; -++ } -++ } else if (zbr->len < c->ranges[type].min_len || -++ zbr->len > c->ranges[type].max_len) { -++ dbg_err("bad target node (type %d) length (%d)", -++ type, zbr->len); -++ dbg_err("have to be in range of %d-%d", -++ c->ranges[type].min_len, -++ c->ranges[type].max_len); -++ goto out_dump; -++ } -++ } -++ -++ /* -++ * Ensure that the next key is greater or equivalent to the -++ * previous one. -++ */ -++ for (i = 0; i < znode->child_cnt - 1; i++) { -++ const union ubifs_key *key1, *key2; -++ -++ key1 = &znode->zbranch[i].key; -++ key2 = &znode->zbranch[i + 1].key; -++ -++ cmp = keys_cmp(c, key1, key2); -++ if (cmp > 0) { -++ dbg_err("bad key order (keys %d and %d)", i, i + 1); -++ goto out_dump; -++ } else if (cmp == 0 && !is_hash_key(c, key1)) { -++ /* These can only be keys with colliding hash */ -++ dbg_err("keys %d and %d are not hashed but equivalent", -++ i, i + 1); -++ goto out_dump; -++ } -++ } -++ -++ kfree(idx); -++ return 0; -++ -++out: -++ kfree(idx); -++ return err; -++ -++out_dump: -++ ubifs_err("bad indexing node at LEB %d:%d", lnum, offs); -++ dbg_dump_node(c, idx); -++ kfree(idx); -++ return -EINVAL; -++} -++ -++/** -++ * load_znode - load znode to TNC cache. -++ * @c: UBIFS file-system description object -++ * @zbr: znode branch -++ * @parent: znode's parent -++ * @iip: index in parent -++ * -++ * This function loads znode pointed to by @zbr into the TNC cache and -++ * returns pointer to it in case of success and a negative error code in case -++ * of failure. -++ */ -++static struct ubifs_znode *load_znode(struct ubifs_info *c, -++ struct ubifs_zbranch *zbr, -++ struct ubifs_znode *parent, int iip) -++{ -++ int err; -++ struct ubifs_znode *znode; -++ -++ ubifs_assert(!zbr->znode); -++ /* -++ * A slab cache is not presently used for znodes because the znode size -++ * depends on the fanout which is stored in the superblock. -++ */ -++ znode = kzalloc(c->max_znode_sz, GFP_NOFS); -++ if (!znode) -++ return ERR_PTR(-ENOMEM); -++ -++ err = read_znode(c, zbr->lnum, zbr->offs, zbr->len, znode); -++ if (err) -++ goto out; -++ -++ atomic_long_inc(&c->clean_zn_cnt); -++ -++ /* -++ * Increment the global clean znode counter as well. It is OK that -++ * global and per-FS clean znode counters may be inconsistent for some -++ * short time (because we might be preempted at this point), the global -++ * one is only used in shrinker. -++ */ -++ atomic_long_inc(&ubifs_clean_zn_cnt); -++ -++ zbr->znode = znode; -++ znode->parent = parent; -++ znode->time = get_seconds(); -++ znode->iip = iip; -++ -++ return znode; -++ -++out: -++ kfree(znode); -++ return ERR_PTR(err); -++} -++ -++/** -++ * copy_znode - copy a dirty znode. -++ * @c: UBIFS file-system description object -++ * @znode: znode to copy -++ * -++ * A dirty znode being committed may not be changed, so it is copied. -++ */ -++static struct ubifs_znode *copy_znode(struct ubifs_info *c, -++ struct ubifs_znode *znode) -++{ -++ struct ubifs_znode *zn; -++ -++ zn = kmalloc(c->max_znode_sz, GFP_NOFS); -++ if (unlikely(!zn)) -++ return ERR_PTR(-ENOMEM); -++ -++ memcpy(zn, znode, c->max_znode_sz); -++ zn->cnext = NULL; -++ __set_bit(DIRTY_ZNODE, &zn->flags); -++ __clear_bit(COW_ZNODE, &zn->flags); -++ -++ ubifs_assert(!test_bit(OBSOLETE_ZNODE, &znode->flags)); -++ __set_bit(OBSOLETE_ZNODE, &znode->flags); -++ -++ if (znode->level != 0) { -++ int i; -++ const int n = zn->child_cnt; -++ -++ /* The children now have new parent */ -++ for (i = 0; i < n; i++) { -++ struct ubifs_zbranch *zbr = &zn->zbranch[i]; -++ -++ if (zbr->znode) -++ zbr->znode->parent = zn; -++ } -++ } -++ -++ atomic_long_inc(&c->dirty_zn_cnt); -++ return zn; -++} -++ -++/** -++ * add_idx_dirt - add dirt due to a dirty znode. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number of index node -++ * @dirt: size of index node -++ * -++ * This function updates lprops dirty space and the new size of the index. -++ */ -++static int add_idx_dirt(struct ubifs_info *c, int lnum, int dirt) -++{ -++ c->calc_idx_sz -= ALIGN(dirt, 8); -++ return ubifs_add_dirt(c, lnum, dirt); -++} -++ -++/** -++ * dirty_cow_znode - ensure a znode is not being committed. -++ * @c: UBIFS file-system description object -++ * @zbr: branch of znode to check -++ * -++ * Returns dirtied znode on success or negative error code on failure. -++ */ -++static struct ubifs_znode *dirty_cow_znode(struct ubifs_info *c, -++ struct ubifs_zbranch *zbr) -++{ -++ struct ubifs_znode *znode = zbr->znode; -++ struct ubifs_znode *zn; -++ int err; -++ -++ if (!test_bit(COW_ZNODE, &znode->flags)) { -++ /* znode is not being committed */ -++ if (!test_and_set_bit(DIRTY_ZNODE, &znode->flags)) { -++ atomic_long_inc(&c->dirty_zn_cnt); -++ atomic_long_dec(&c->clean_zn_cnt); -++ atomic_long_dec(&ubifs_clean_zn_cnt); -++ err = add_idx_dirt(c, zbr->lnum, zbr->len); -++ if (unlikely(err)) -++ return ERR_PTR(err); -++ } -++ return znode; -++ } -++ -++ zn = copy_znode(c, znode); -++ if (unlikely(IS_ERR(zn))) -++ return zn; -++ -++ if (zbr->len) { -++ err = insert_old_idx(c, zbr->lnum, zbr->offs); -++ if (unlikely(err)) -++ return ERR_PTR(err); -++ err = add_idx_dirt(c, zbr->lnum, zbr->len); -++ } else -++ err = 0; -++ -++ zbr->znode = zn; -++ zbr->lnum = 0; -++ zbr->offs = 0; -++ zbr->len = 0; -++ -++ if (unlikely(err)) -++ return ERR_PTR(err); -++ return zn; -++} -++ -++/** -++ * lnc_add - add a leaf node to the leaf node cache. -++ * @c: UBIFS file-system description object -++ * @zbr: zbranch of leaf node -++ * @node: leaf node -++ * -++ * Leaf nodes are non-index nodes directory entry nodes or data nodes. The -++ * purpose of the leaf node cache is to save re-reading the same leaf node over -++ * and over again. Most things are cached by VFS, however the file system must -++ * cache directory entries for readdir and for resolving hash collisions. The -++ * present implementation of the leaf node cache is extremely simple, and -++ * allows for error returns that are not used but that may be needed if a more -++ * complex implementation is created. -++ * -++ * Note, this function does not add the @node object to LNC directly, but -++ * allocates a copy of the object and adds the copy to LNC. The reason for this -++ * is that @node has been allocated outside of the TNC subsystem and will be -++ * used with @c->tnc_mutex unlock upon return from the TNC subsystem. But LNC -++ * may be changed at any time, e.g. freed by the shrinker. -++ */ -++static int lnc_add(struct ubifs_info *c, struct ubifs_zbranch *zbr, -++ const void *node) -++{ -++ int err; -++ void *lnc_node; -++ const struct ubifs_dent_node *dent = node; -++ -++ ubifs_assert(!zbr->leaf); -++ ubifs_assert(zbr->len != 0); -++ ubifs_assert(is_hash_key(c, &zbr->key)); -++ -++ err = ubifs_validate_entry(c, dent); -++ if (err) { -++ dbg_dump_stack(); -++ dbg_dump_node(c, dent); -++ return err; -++ } -++ -++ lnc_node = kmalloc(zbr->len, GFP_NOFS); -++ if (!lnc_node) -++ /* We don't have to have the cache, so no error */ -++ return 0; -++ -++ memcpy(lnc_node, node, zbr->len); -++ zbr->leaf = lnc_node; -++ return 0; -++} -++ -++ /** -++ * lnc_add_directly - add a leaf node to the leaf-node-cache. -++ * @c: UBIFS file-system description object -++ * @zbr: zbranch of leaf node -++ * @node: leaf node -++ * -++ * This function is similar to 'lnc_add()', but it does not create a copy of -++ * @node but inserts @node to TNC directly. -++ */ -++static int lnc_add_directly(struct ubifs_info *c, struct ubifs_zbranch *zbr, -++ void *node) -++{ -++ int err; -++ -++ ubifs_assert(!zbr->leaf); -++ ubifs_assert(zbr->len != 0); -++ -++ err = ubifs_validate_entry(c, node); -++ if (err) { -++ dbg_dump_stack(); -++ dbg_dump_node(c, node); -++ return err; -++ } -++ -++ zbr->leaf = node; -++ return 0; -++} -++ -++/** -++ * lnc_free - remove a leaf node from the leaf node cache. -++ * @zbr: zbranch of leaf node -++ * @node: leaf node -++ */ -++static void lnc_free(struct ubifs_zbranch *zbr) -++{ -++ if (!zbr->leaf) -++ return; -++ kfree(zbr->leaf); -++ zbr->leaf = NULL; -++} -++ -++/** -++ * tnc_read_node - read a leaf node from the flash media. -++ * @c: UBIFS file-system description object -++ * @zbr: key and position of the node -++ * @node: node is returned here -++ * -++ * This function reads a node defined by @zbr from the flash media. Returns -++ * zero in case of success or a negative negative error code in case of -++ * failure. -++ */ -++static int tnc_read_node(struct ubifs_info *c, struct ubifs_zbranch *zbr, -++ void *node) -++{ -++ union ubifs_key key1, *key = &zbr->key; -++ int err, type = key_type(c, key); -++ struct ubifs_wbuf *wbuf; -++ -++ ubifs_assert(!zbr->leaf); -++ -++ /* -++ * 'zbr' has to point to on-flash node. The node may sit in a bud and -++ * may even be in a write buffer, so we have to take care about this. -++ */ -++ wbuf = ubifs_get_wbuf(c, zbr->lnum); -++ if (wbuf) -++ err = ubifs_read_node_wbuf(wbuf, node, type, zbr->len, -++ zbr->lnum, zbr->offs); -++ else -++ err = ubifs_read_node(c, node, type, zbr->len, zbr->lnum, -++ zbr->offs); -++ -++ if (err) { -++ dbg_tnc("key %s", DBGKEY(key)); -++ return err; -++ } -++ -++ /* Make sure the key of the read node is correct */ -++ key_read(c, key, &key1); -++ if (memcmp(node + UBIFS_KEY_OFFSET, &key1, c->key_len)) { -++ ubifs_err("bad key in node at LEB %d:%d", -++ zbr->lnum, zbr->offs); -++ dbg_tnc("looked for key %s found node's key %s", -++ DBGKEY(key), DBGKEY1(&key1)); -++ dbg_dump_node(c, node); -++ return -EINVAL; -++ } -++ -++ return 0; -++} -++ -++/** -++ * tnc_read_node_nm - read a "hashed" leaf node. -++ * @c: UBIFS file-system description object -++ * @zbr: key and position of the node -++ * @node: node is returned here -++ * -++ * This function reads a "hashed" node defined by @zbr from the leaf node cache -++ * (in it is there) or from the hash media, in which case the node is also -++ * added to LNC. Returns zero in case of success or a negative negative error -++ * code in case of failure. -++ */ -++static int tnc_read_node_nm(struct ubifs_info *c, struct ubifs_zbranch *zbr, -++ void *node) -++{ -++ int err; -++ -++ ubifs_assert(is_hash_key(c, &zbr->key)); -++ -++ if (zbr->leaf) { -++ /* Read from the leaf node cache */ -++ ubifs_assert(zbr->len != 0); -++ memcpy(node, zbr->leaf, zbr->len); -++ return 0; -++ } -++ -++ err = tnc_read_node(c, zbr, node); -++ if (err) -++ return err; -++ -++ /* Add the node to the leaf node cache */ -++ err = lnc_add(c, zbr, node); -++ return err; -++} -++ -++/** -++ * try_read_node - read a node if it is a node. -++ * @c: UBIFS file-system description object -++ * @buf: buffer to read to -++ * @type: node type -++ * @len: node length (not aligned) -++ * @lnum: LEB number of node to read -++ * @offs: offset of node to read -++ * -++ * This function tries to read a node of known type and length, checks it and -++ * stores it in @buf. This function returns %1 if a node is present and %0 if -++ * a node is not present. A negative error code is returned for I/O errors. -++ * This function performs that same function as ubifs_read_node except that -++ * it does not require that there is actually a node present and instead -++ * the return code indicates if a node was read. -++ */ -++static int try_read_node(const struct ubifs_info *c, void *buf, int type, -++ int len, int lnum, int offs) -++{ -++ int err, node_len; -++ struct ubifs_ch *ch = buf; -++ uint32_t crc, node_crc; -++ -++ dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len); -++ -++ err = ubi_read(c->ubi, lnum, buf, offs, len); -++ if (err) { -++ ubifs_err("cannot read node type %d from LEB %d:%d, error %d", -++ type, lnum, offs, err); -++ return err; -++ } -++ -++ if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC) -++ return 0; -++ -++ if (ch->node_type != type) -++ return 0; -++ -++ node_len = le32_to_cpu(ch->len); -++ if (node_len != len) -++ return 0; -++ -++ crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); -++ node_crc = le32_to_cpu(ch->crc); -++ if (crc != node_crc) -++ return 0; -++ -++ return 1; -++} -++ -++/** -++ * fallible_read_node - try to read a leaf node. -++ * @c: UBIFS file-system description object -++ * @key: key of node to read -++ * @zbr: position of node -++ * @node: node returned -++ * -++ * This function tries to read a node and returns %1 if the node is read, %0 -++ * if the node is not present, and a negative error code in the case of error. -++ */ -++static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key, -++ struct ubifs_zbranch *zbr, void *node) -++{ -++ int ret; -++ -++ dbg_tnc("LEB %d:%d, key %s", zbr->lnum, zbr->offs, DBGKEY(key)); -++ -++ ret = try_read_node(c, node, key_type(c, key), zbr->len, zbr->lnum, -++ zbr->offs); -++ if (ret == 1) { -++ union ubifs_key node_key; -++ struct ubifs_dent_node *dent = node; -++ -++ /* All nodes have key in the same place */ -++ key_read(c, &dent->key, &node_key); -++ if (keys_cmp(c, key, &node_key) != 0) -++ ret = 0; -++ } -++ if (ret == 0) -++ dbg_mnt("dangling branch LEB %d:%d len %d, key %s", -++ zbr->lnum, zbr->offs, zbr->len, DBGKEY(key)); -++ return ret; -++} -++ -++/** -++ * matches_name - determine if a directory or extended attribute entry matches -++ * a given name. -++ * @c: UBIFS file-system description object -++ * @zbr: zbranch of dent -++ * @nm: name to match -++ * -++ * This function checks if xentry/direntry referred by zbranch @zbr matches name -++ * @nm. Returns %NAME_MATCHES if it does, %NAME_LESS if the name referred by -++ * @zbr is less than @nm, and %NAME_GREATER if it is greater than @nm. In case -++ * of failure, a negative error code is returned. -++ */ -++static int matches_name(struct ubifs_info *c, struct ubifs_zbranch *zbr, -++ const struct qstr *nm) -++{ -++ struct ubifs_dent_node *dent; -++ int nlen, err; -++ -++ /* If possible, match against the dent in the leaf node cache */ -++ if (!zbr->leaf) { -++ dent = kmalloc(zbr->len, GFP_NOFS); -++ if (!dent) -++ return -ENOMEM; -++ -++ err = tnc_read_node(c, zbr, dent); -++ if (err) -++ goto out_free; -++ -++ /* Add the node to the leaf node cache */ -++ err = lnc_add_directly(c, zbr, dent); -++ if (err) -++ goto out_free; -++ } else -++ dent = zbr->leaf; -++ -++ nlen = le16_to_cpu(dent->nlen); -++ err = memcmp(dent->name, nm->name, min_t(int, nlen, nm->len)); -++ if (err == 0) { -++ if (nlen == nm->len) -++ return NAME_MATCHES; -++ else if (nlen < nm->len) -++ return NAME_LESS; -++ else -++ return NAME_GREATER; -++ } else if (err < 0) -++ return NAME_LESS; -++ else -++ return NAME_GREATER; -++ -++out_free: -++ kfree(dent); -++ return err; -++} -++ -++/** -++ * get_znode - get a TNC znode that may not be loaded yet. -++ * @c: UBIFS file-system description object -++ * @znode: parent znode -++ * @n: znode branch slot number -++ * -++ * This function returns the znode or a negative error code. -++ */ -++static struct ubifs_znode *get_znode(struct ubifs_info *c, -++ struct ubifs_znode *znode, int n) -++{ -++ struct ubifs_zbranch *zbr; -++ -++ zbr = &znode->zbranch[n]; -++ if (zbr->znode) -++ znode = zbr->znode; -++ else -++ znode = load_znode(c, zbr, znode, n); -++ return znode; -++} -++ -++/** -++ * tnc_next - find next TNC entry. -++ * @c: UBIFS file-system description object -++ * @zn: znode is passed and returned here -++ * @n: znode branch slot number is passed and returned here -++ * -++ * This function returns %0 if the next TNC entry is found, %-ENOENT if there is -++ * no next entry, or a negative error code otherwise. -++ */ -++static int tnc_next(struct ubifs_info *c, struct ubifs_znode **zn, int *n) -++{ -++ struct ubifs_znode *znode = *zn; -++ int nn = *n; -++ -++ nn += 1; -++ if (nn < znode->child_cnt) { -++ *n = nn; -++ return 0; -++ } -++ while (1) { -++ struct ubifs_znode *zp; -++ -++ zp = znode->parent; -++ if (!zp) -++ return -ENOENT; -++ nn = znode->iip + 1; -++ znode = zp; -++ if (nn < znode->child_cnt) { -++ znode = get_znode(c, znode, nn); -++ if (IS_ERR(znode)) -++ return PTR_ERR(znode); -++ while (znode->level != 0) { -++ znode = get_znode(c, znode, 0); -++ if (IS_ERR(znode)) -++ return PTR_ERR(znode); -++ } -++ nn = 0; -++ break; -++ } -++ } -++ *zn = znode; -++ *n = nn; -++ return 0; -++} -++ -++/** -++ * tnc_prev - find previous TNC entry. -++ * @c: UBIFS file-system description object -++ * @zn: znode is returned here -++ * @n: znode branch slot number is passed and returned here -++ * -++ * This function returns %0 if the previous TNC entry is found, %-ENOENT if -++ * there is no next entry, or a negative error code otherwise. -++ */ -++static int tnc_prev(struct ubifs_info *c, struct ubifs_znode **zn, int *n) -++{ -++ struct ubifs_znode *znode = *zn; -++ int nn = *n; -++ -++ if (nn > 0) { -++ *n = nn - 1; -++ return 0; -++ } -++ while (1) { -++ struct ubifs_znode *zp; -++ -++ zp = znode->parent; -++ if (!zp) -++ return -ENOENT; -++ nn = znode->iip - 1; -++ znode = zp; -++ if (nn >= 0) { -++ znode = get_znode(c, znode, nn); -++ if (IS_ERR(znode)) -++ return PTR_ERR(znode); -++ while (znode->level != 0) { -++ nn = znode->child_cnt - 1; -++ znode = get_znode(c, znode, nn); -++ if (IS_ERR(znode)) -++ return PTR_ERR(znode); -++ } -++ nn = znode->child_cnt - 1; -++ break; -++ } -++ } -++ *zn = znode; -++ *n = nn; -++ return 0; -++} -++ -++/** -++ * resolve_collision - resolve a collision. -++ * @c: UBIFS file-system description object -++ * @key: key of a directory or extended attribute entry -++ * @zn: znode is returned here -++ * @n: zbranch number is passed and returned here -++ * @nm: name of the entry -++ * -++ * This function is called for "hashed" keys to make sure that the found key -++ * really corresponds to the looked up node (directory or extended attribute -++ * entry). It returns %1 and sets @zn and @n if the collision is resolved. -++ * %0 is returned if @nm is not found and @zn and @n are set to the previous -++ * entry, i.e. to the entry after which @nm could follow if it were in TNC. -++ * This means that @n may be set to %-1 if the leftmost key in @zn is the -++ * previous one. A negative error code is returned on failures. -++ */ -++static int resolve_collision(struct ubifs_info *c, const union ubifs_key *key, -++ struct ubifs_znode **zn, int *n, -++ const struct qstr *nm) -++{ -++ int err; -++ -++ err = matches_name(c, &(*zn)->zbranch[*n], nm); -++ if (unlikely(err < 0)) -++ return err; -++ if (err == NAME_MATCHES) -++ return 1; -++ -++ if (err == NAME_GREATER) { -++ /* Look left */ -++ while (1) { -++ err = tnc_prev(c, zn, n); -++ if (err == -ENOENT) { -++ ubifs_assert(*n == 0); -++ *n = -1; -++ return 0; -++ } -++ if (err < 0) -++ return err; -++ if (keys_cmp(c, &(*zn)->zbranch[*n].key, key)) { -++ /* -++ * We have found the branch after which we would -++ * like to insert, but inserting in this znode -++ * may still be wrong. Consider the following 3 -++ * znodes, in the case where we are resolving a -++ * collision with Key2. -++ * -++ * znode zp -++ * ---------------------- -++ * level 1 | Key0 | Key1 | -++ * ----------------------- -++ * | | -++ * znode za | | znode zb -++ * ------------ ------------ -++ * level 0 | Key0 | | Key2 | -++ * ------------ ------------ -++ * -++ * The lookup finds Key2 in znode zb. Lets say -++ * there is no match and the name is greater so -++ * we look left. When we find Key0, we end up -++ * here. If we return now, we will insert into -++ * znode za at slot n = 1. But that is invalid -++ * according to the parent's keys. Key2 must -++ * be inserted into znode zb. -++ * -++ * Note, this problem is not relevant for the -++ * case when we go right, because -++ * 'tnc_insert()' would correct the parent key. -++ */ -++ if (*n == (*zn)->child_cnt - 1) { -++ err = tnc_next(c, zn, n); -++ if (err) { -++ /* Should be impossible */ -++ ubifs_assert(0); -++ if (err == -ENOENT) -++ err = -EINVAL; -++ return err; -++ } -++ ubifs_assert(*n == 0); -++ *n = -1; -++ } -++ return 0; -++ } -++ err = matches_name(c, &(*zn)->zbranch[*n], nm); -++ if (err < 0) -++ return err; -++ if (err == NAME_LESS) -++ return 0; -++ if (err == NAME_MATCHES) -++ return 1; -++ ubifs_assert(err == NAME_GREATER); -++ } -++ } else { -++ int nn = *n; -++ struct ubifs_znode *znode = *zn; -++ -++ /* Look right */ -++ while (1) { -++ err = tnc_next(c, &znode, &nn); -++ if (err == -ENOENT) -++ return 0; -++ if (err < 0) -++ return err; -++ if (keys_cmp(c, &znode->zbranch[nn].key, key)) -++ return 0; -++ err = matches_name(c, &znode->zbranch[nn], nm); -++ if (err < 0) -++ return err; -++ if (err == NAME_GREATER) -++ return 0; -++ *zn = znode; -++ *n = nn; -++ if (err == NAME_MATCHES) -++ return 1; -++ ubifs_assert(err == NAME_LESS); -++ } -++ } -++} -++ -++/** -++ * fallible_matches_name - determine if a dent matches a given name. -++ * @c: UBIFS file-system description object -++ * @zbr: zbranch of dent -++ * @nm: name to match -++ * -++ * This is a "fallible" version of 'matches_name()' function which does not -++ * panic if the direntry/xentry referred by @zbr does not exist on the media. -++ * -++ * This function checks if xentry/direntry referred by zbranch @zbr matches name -++ * @nm. Returns %NAME_MATCHES it does, %NAME_LESS if the name referred by @zbr -++ * is less than @nm, %NAME_GREATER if it is greater than @nm, and @NOT_ON_MEDIA -++ * if xentry/direntry referred by @zbr does not exist on the media. A negative -++ * error code is returned in case of failure. -++ */ -++static int fallible_matches_name(struct ubifs_info *c, -++ struct ubifs_zbranch *zbr, -++ const struct qstr *nm) -++{ -++ struct ubifs_dent_node *dent; -++ int nlen, err; -++ -++ /* If possible, match against the dent in the leaf node cache */ -++ if (!zbr->leaf) { -++ dent = kmalloc(zbr->len, GFP_NOFS); -++ if (!dent) -++ return -ENOMEM; -++ -++ err = fallible_read_node(c, &zbr->key, zbr, dent); -++ if (err < 0) -++ goto out_free; -++ if (err == 0) { -++ /* The node was not present */ -++ err = NOT_ON_MEDIA; -++ goto out_free; -++ } -++ ubifs_assert(err == 1); -++ -++ err = lnc_add_directly(c, zbr, dent); -++ if (err) -++ goto out_free; -++ } else -++ dent = zbr->leaf; -++ -++ nlen = le16_to_cpu(dent->nlen); -++ err = memcmp(dent->name, nm->name, min_t(int, nlen, nm->len)); -++ if (err == 0) { -++ if (nlen == nm->len) -++ return NAME_MATCHES; -++ else if (nlen < nm->len) -++ return NAME_LESS; -++ else -++ return NAME_GREATER; -++ } else if (err < 0) -++ return NAME_LESS; -++ else -++ return NAME_GREATER; -++ -++out_free: -++ kfree(dent); -++ return err; -++} -++ -++/** -++ * fallible_resolve_collision - resolve a collision even if nodes are missing. -++ * @c: UBIFS file-system description object -++ * @key: key -++ * @zn: znode is returned here -++ * @n: branch number is passed and returned here -++ * @nm: name of directory entry -++ * @adding: indicates caller is adding a key to the TNC -++ * -++ * This is a "fallible" version of the 'resolve_collision()' function which -++ * does not panic if one of the nodes referred to by TNC does not exist on the -++ * media. This may happen when replaying the journal if a deleted node was -++ * Garbage-collected and the commit was not done. A branch that refers to a node -++ * that is not present is called a dangling branch. The following are the return -++ * codes for this function: -++ * o if @nm was found, %1 is returned and @zn and @n are set to the found -++ * branch; -++ * o if we are @adding and @nm was not found, %0 is returned; -++ * o if we are not @adding and @nm was not found, but a dangling branch was -++ * found, then %1 is returned and @zn and @n are set to the dangling branch; -++ * o a negative error code is returned in case of failure. -++ */ -++static int fallible_resolve_collision(struct ubifs_info *c, -++ const union ubifs_key *key, -++ struct ubifs_znode **zn, int *n, -++ const struct qstr *nm, int adding) -++{ -++ struct ubifs_znode *o_znode = NULL, *znode = *zn; -++ int uninitialized_var(o_n), err, cmp, unsure = 0, nn = *n; -++ -++ cmp = fallible_matches_name(c, &znode->zbranch[nn], nm); -++ if (unlikely(cmp < 0)) -++ return cmp; -++ if (cmp == NAME_MATCHES) -++ return 1; -++ if (cmp == NOT_ON_MEDIA) { -++ o_znode = znode; -++ o_n = nn; -++ /* -++ * We are unlucky and hit a dangling branch straight away. -++ * Now we do not really know where to go to find the needed -++ * branch - to the left or to the right. Well, let's try left. -++ */ -++ unsure = 1; -++ } else if (!adding) -++ unsure = 1; /* Remove a dangling branch wherever it is */ -++ -++ if (cmp == NAME_GREATER || unsure) { -++ /* Look left */ -++ while (1) { -++ err = tnc_prev(c, zn, n); -++ if (err == -ENOENT) { -++ ubifs_assert(*n == 0); -++ *n = -1; -++ break; -++ } -++ if (err < 0) -++ return err; -++ if (keys_cmp(c, &(*zn)->zbranch[*n].key, key)) { -++ /* See comments in 'resolve_collision()' */ -++ if (*n == (*zn)->child_cnt - 1) { -++ err = tnc_next(c, zn, n); -++ if (err) { -++ /* Should be impossible */ -++ ubifs_assert(0); -++ if (err == -ENOENT) -++ err = -EINVAL; -++ return err; -++ } -++ ubifs_assert(*n == 0); -++ *n = -1; -++ } -++ break; -++ } -++ err = fallible_matches_name(c, &(*zn)->zbranch[*n], nm); -++ if (err < 0) -++ return err; -++ if (err == NAME_MATCHES) -++ return 1; -++ if (err == NOT_ON_MEDIA) { -++ o_znode = *zn; -++ o_n = *n; -++ continue; -++ } -++ if (!adding) -++ continue; -++ if (err == NAME_LESS) -++ break; -++ else -++ unsure = 0; -++ } -++ } -++ -++ if (cmp == NAME_LESS || unsure) { -++ /* Look right */ -++ *zn = znode; -++ *n = nn; -++ while (1) { -++ err = tnc_next(c, &znode, &nn); -++ if (err == -ENOENT) -++ break; -++ if (err < 0) -++ return err; -++ if (keys_cmp(c, &znode->zbranch[nn].key, key)) -++ break; -++ err = fallible_matches_name(c, &znode->zbranch[nn], nm); -++ if (err < 0) -++ return err; -++ if (err == NAME_GREATER) -++ break; -++ *zn = znode; -++ *n = nn; -++ if (err == NAME_MATCHES) -++ return 1; -++ if (err == NOT_ON_MEDIA) { -++ o_znode = znode; -++ o_n = nn; -++ } -++ } -++ } -++ -++ /* Never match a dangling branch when adding */ -++ if (adding || !o_znode) -++ return 0; -++ -++ dbg_mnt("dangling match LEB %d:%d len %d %s", -++ o_znode->zbranch[o_n].lnum, o_znode->zbranch[o_n].offs, -++ o_znode->zbranch[o_n].len, DBGKEY(key)); -++ *zn = o_znode; -++ *n = o_n; -++ return 1; -++} -++ -++/** -++ * matches_position - determine if a zbranch matches a given position. -++ * @zbr: zbranch of dent -++ * @lnum: LEB number of dent to match -++ * @offs: offset of dent to match -++ * -++ * This function returns %1 if @lnum:@offs matches, and %0 otherwise. -++ */ -++static int matches_position(struct ubifs_zbranch *zbr, int lnum, int offs) -++{ -++ if (zbr->lnum == lnum && zbr->offs == offs) -++ return 1; -++ else -++ return 0; -++} -++ -++/** -++ * resolve_collision_directly - resolve a collision directly. -++ * @c: UBIFS file-system description object -++ * @key: key of directory entry -++ * @zn: znode is passed and returned here -++ * @n: zbranch number is passed and returned here -++ * @lnum: LEB number of dent node to match -++ * @offs: offset of dent node to match -++ * -++ * This function is used for "hashed" keys to make sure the found directory or -++ * extended attribute entry node is what was looked for. It is used when the -++ * flash address of the right node is known (@lnum:@offs) which makes it much -++ * easier to resolve collisions (no need to read entries and match full -++ * names). This function returns %1 and sets @zn and @n if the collision is -++ * resolved, %0 if @lnum:@offs is not found and @zn and @n are set to the -++ * previous directory entry. Otherwise a negative error code is returned. -++ */ -++static int resolve_collision_directly(struct ubifs_info *c, -++ const union ubifs_key *key, -++ struct ubifs_znode **zn, int *n, -++ int lnum, int offs) -++{ -++ struct ubifs_znode *znode; -++ int nn, err; -++ -++ znode = *zn; -++ nn = *n; -++ if (matches_position(&znode->zbranch[nn], lnum, offs)) -++ return 1; -++ -++ /* Look left */ -++ while (1) { -++ err = tnc_prev(c, &znode, &nn); -++ if (err == -ENOENT) -++ break; -++ if (err < 0) -++ return err; -++ if (keys_cmp(c, &znode->zbranch[nn].key, key)) -++ break; -++ if (matches_position(&znode->zbranch[nn], lnum, offs)) { -++ *zn = znode; -++ *n = nn; -++ return 1; -++ } -++ } -++ -++ /* Look right */ -++ znode = *zn; -++ nn = *n; -++ while (1) { -++ err = tnc_next(c, &znode, &nn); -++ if (err == -ENOENT) -++ return 0; -++ if (err < 0) -++ return err; -++ if (keys_cmp(c, &znode->zbranch[nn].key, key)) -++ return 0; -++ *zn = znode; -++ *n = nn; -++ if (matches_position(&znode->zbranch[nn], lnum, offs)) -++ return 1; -++ } -++} -++ -++/** -++ * dirty_cow_bottom_up - dirty a znode and its ancestors. -++ * @c: UBIFS file-system description object -++ * @znode: znode to dirty -++ * -++ * If we do not have a unique key that resides in a znode, then we cannot -++ * dirty that znode from the top down (i.e. by using lookup_level0_dirty) -++ * This function records the path back to the last dirty ancestor, and then -++ * dirties the znodes on that path. -++ */ -++static struct ubifs_znode *dirty_cow_bottom_up(struct ubifs_info *c, -++ struct ubifs_znode *znode) -++{ -++ struct ubifs_znode *zp; -++ int *path = c->bottom_up_buf, p = 0; -++ -++ ubifs_assert(c->zroot.znode); -++ ubifs_assert(znode); -++ if (c->zroot.znode->level > BOTTOM_UP_HEIGHT) { -++ kfree(c->bottom_up_buf); -++ c->bottom_up_buf = kmalloc(c->zroot.znode->level * sizeof(int), -++ GFP_NOFS); -++ if (!c->bottom_up_buf) -++ return ERR_PTR(-ENOMEM); -++ path = c->bottom_up_buf; -++ } -++ if (c->zroot.znode->level) { -++ /* Go up until parent is dirty */ -++ while (1) { -++ int n; -++ -++ zp = znode->parent; -++ if (!zp) -++ break; -++ n = znode->iip; -++ ubifs_assert(p < c->zroot.znode->level); -++ path[p++] = n; -++ if (!zp->cnext && ubifs_zn_dirty(znode)) -++ break; -++ znode = zp; -++ } -++ } -++ -++ /* Come back down, dirtying as we go */ -++ while (1) { -++ struct ubifs_zbranch *zbr; -++ -++ zp = znode->parent; -++ if (zp) { -++ ubifs_assert(path[p - 1] >= 0); -++ ubifs_assert(path[p - 1] < zp->child_cnt); -++ zbr = &zp->zbranch[path[--p]]; -++ znode = dirty_cow_znode(c, zbr); -++ } else { -++ ubifs_assert(znode == c->zroot.znode); -++ znode = dirty_cow_znode(c, &c->zroot); -++ } -++ if (unlikely(IS_ERR(znode)) || !p) -++ break; -++ ubifs_assert(path[p - 1] >= 0); -++ ubifs_assert(path[p - 1] < znode->child_cnt); -++ znode = znode->zbranch[path[p - 1]].znode; -++ } -++ -++ return znode; -++} -++ -++/** -++ * lookup_level0 - search for zero-level znode. -++ * @c: UBIFS file-system description object -++ * @key: key to lookup -++ * @zn: znode is returned here -++ * @n: znode branch slot number is returned here -++ * -++ * This function looks up the TNC tree and search for zero-level znode which -++ * refers key @key. The found zero-level znode is returned in @zn. There are 3 -++ * cases: -++ * o exact match, i.e. the found zero-level znode contains key @key, then %1 -++ * is returned and slot number of the matched branch is stored in @n; -++ * o not exact match, which means that zero-level znode does not contain -++ * @key, then %0 is returned and slot number of the closed branch is stored -++ * in @n; -++ * o @key is so small that it is even less than the lowest key of the -++ * leftmost zero-level node, then %0 is returned and %0 is stored in @n. -++ * -++ * Note, when the TNC tree is traversed, some znodes may be absent, then this -++ * function reads corresponding indexing nodes and inserts them to TNC. In -++ * case of failure, a negative error code is returned. -++ */ -++static int lookup_level0(struct ubifs_info *c, const union ubifs_key *key, -++ struct ubifs_znode **zn, int *n) -++{ -++ int err, exact; -++ struct ubifs_znode *znode; -++ unsigned long time = get_seconds(); -++ -++ dbg_tnc("search key %s", DBGKEY(key)); -++ -++ znode = c->zroot.znode; -++ if (unlikely(!znode)) { -++ znode = load_znode(c, &c->zroot, NULL, 0); -++ if (IS_ERR(znode)) -++ return PTR_ERR(znode); -++ } -++ -++ znode->time = time; -++ -++ while (1) { -++ struct ubifs_zbranch *zbr; -++ -++ exact = ubifs_search_zbranch(c, znode, key, n); -++ -++ if (znode->level == 0) -++ break; -++ -++ if (*n < 0) -++ *n = 0; -++ zbr = &znode->zbranch[*n]; -++ -++ if (zbr->znode) { -++ znode->time = time; -++ znode = zbr->znode; -++ continue; -++ } -++ -++ /* znode is not in TNC cache, load it from the media */ -++ znode = load_znode(c, zbr, znode, *n); -++ if (IS_ERR(znode)) -++ return PTR_ERR(znode); -++ } -++ -++ *zn = znode; -++ if (exact || !is_hash_key(c, key) || *n != -1) { -++ dbg_tnc("found %d, lvl %d, n %d", exact, znode->level, *n); -++ return exact; -++ } -++ -++ /* -++ * Here is a tricky place. We have not found the key and this is a -++ * "hashed" key, which may collide. The rest of the code deals with -++ * situations like this: -++ * -++ * | 3 | 5 | -++ * / \ -++ * | 3 | 5 | | 6 | 7 | (x) -++ * -++ * Or more a complex example: -++ * -++ * | 1 | 5 | -++ * / \ -++ * | 1 | 3 | | 5 | 8 | -++ * \ / -++ * | 5 | 5 | | 6 | 7 | (x) -++ * -++ * In the examples, if we are looking for key "5", we may reach nodes -++ * marked with "(x)". In this case what we have do is to look at the -++ * left and see if there is "5" key there. If there is, we have to -++ * return it. -++ * -++ * Note, this whole situation is possible because we allow to have -++ * elements which are equivalent to the next key in the parent in the -++ * children of current znode. For example, this happens if we split a -++ * znode like this: | 3 | 5 | 5 | 6 | 7 |, which results in something -++ * like this: -++ * | 3 | 5 | -++ * / \ -++ * | 3 | 5 | | 5 | 6 | 7 | -++ * ^ -++ * And this becomes what is at the first "picture" after key "5" marked -++ * with "^" is removed. What could be done is we could prohibit -++ * splitting in the middle of the colliding sequence. Also, when -++ * removing the leftmost key, we would have to correct the key of the -++ * parent node, which would introduce additional complications. Namely, -++ * if we changed the the leftmost key of the parent znode, the garbage -++ * collector would be unable to find it (GC is doing this when GC'ing -++ * indexing LEBs). Although we already have an additional RB-tree where -++ * we save such changed znodes (see 'ins_clr_old_idx_znode()') until -++ * after the commit. But anyway, this does not look easy to implement -++ * so we did not try this. -++ */ -++ err = tnc_prev(c, &znode, n); -++ if (err == -ENOENT) { -++ dbg_tnc("found 0, lvl %d, n -1", znode->level); -++ *n = -1; -++ return 0; -++ } -++ if (unlikely(err < 0)) -++ return err; -++ if (keys_cmp(c, key, &znode->zbranch[*n].key)) { -++ dbg_tnc("found 0, lvl %d, n -1", znode->level); -++ *n = -1; -++ return 0; -++ } -++ -++ dbg_tnc("found 1, lvl %d, n %d", znode->level, *n); -++ *zn = znode; -++ return 1; -++} -++ -++/** -++ * lookup_level0_dirty - search for zero-level znode dirtying. -++ * @c: UBIFS file-system description object -++ * @key: key to lookup -++ * @zn: znode is returned here -++ * @n: znode branch slot number is returned here -++ * -++ * This function looks up the TNC tree and search for zero-level znode which -++ * refers key @key. The found zero-level znode is returned in @zn. There are 3 -++ * cases: -++ * o exact match, i.e. the found zero-level znode contains key @key, then %1 -++ * is returned and slot number of the matched branch is stored in @n; -++ * o not exact match, which means that zero-level znode does not contain @key -++ * then %0 is returned and slot number of the closed branch is stored in -++ * @n; -++ * o @key is so small that it is even less than the lowest key of the -++ * leftmost zero-level node, then %0 is returned and %-1 is stored in @n. -++ * -++ * Additionally all znodes in the path from the root to the located zero-level -++ * znode are marked as dirty. -++ * -++ * Note, when the TNC tree is traversed, some znodes may be absent, then this -++ * function reads corresponding indexing nodes and inserts them to TNC. In -++ * case of failure, a negative error code is returned. -++ */ -++static int lookup_level0_dirty(struct ubifs_info *c, const union ubifs_key *key, -++ struct ubifs_znode **zn, int *n) -++{ -++ int err, exact; -++ struct ubifs_znode *znode; -++ unsigned long time = get_seconds(); -++ -++ dbg_tnc("search and dirty key %s", DBGKEY(key)); -++ -++ znode = c->zroot.znode; -++ if (unlikely(!znode)) { -++ znode = load_znode(c, &c->zroot, NULL, 0); -++ if (IS_ERR(znode)) -++ return PTR_ERR(znode); -++ } -++ -++ znode = dirty_cow_znode(c, &c->zroot); -++ if (IS_ERR(znode)) -++ return PTR_ERR(znode); -++ -++ znode->time = time; -++ -++ while (1) { -++ struct ubifs_zbranch *zbr; -++ -++ exact = ubifs_search_zbranch(c, znode, key, n); -++ -++ if (znode->level == 0) -++ break; -++ -++ if (*n < 0) -++ *n = 0; -++ zbr = &znode->zbranch[*n]; -++ -++ if (zbr->znode) { -++ znode->time = time; -++ znode = dirty_cow_znode(c, zbr); -++ if (IS_ERR(znode)) -++ return PTR_ERR(znode); -++ continue; -++ } -++ -++ /* znode is not in TNC cache, load it from the media */ -++ znode = load_znode(c, zbr, znode, *n); -++ if (IS_ERR(znode)) -++ return PTR_ERR(znode); -++ znode = dirty_cow_znode(c, zbr); -++ if (IS_ERR(znode)) -++ return PTR_ERR(znode); -++ } -++ -++ *zn = znode; -++ if (exact || !is_hash_key(c, key) || *n != -1) { -++ dbg_tnc("found %d, lvl %d, n %d", exact, znode->level, *n); -++ return exact; -++ } -++ -++ /* -++ * See huge comment at 'lookup_level0_dirty()' what is the rest of the -++ * code. -++ */ -++ err = tnc_prev(c, &znode, n); -++ if (err == -ENOENT) { -++ *n = -1; -++ dbg_tnc("found 0, lvl %d, n -1", znode->level); -++ return 0; -++ } -++ if (unlikely(err < 0)) -++ return err; -++ if (keys_cmp(c, key, &znode->zbranch[*n].key)) { -++ *n = -1; -++ dbg_tnc("found 0, lvl %d, n -1", znode->level); -++ return 0; -++ } -++ -++ if (znode->cnext || !ubifs_zn_dirty(znode)) { -++ znode = dirty_cow_bottom_up(c, znode); -++ if (IS_ERR(znode)) -++ return PTR_ERR(znode); -++ } -++ -++ dbg_tnc("found 1, lvl %d, n %d", znode->level, *n); -++ *zn = znode; -++ return 1; -++} -++ -++/** -++ * ubifs_tnc_lookup - look up a file-system node. -++ * @c: UBIFS file-system description object -++ * @key: node key to lookup -++ * @node: the node is returned here -++ * -++ * This function look up and reads node with key @key. The caller has to make -++ * sure the @node buffer is large enough to fit the node. Returns zero in case -++ * of success, %-ENOENT if the node was not found, and a negative error code in -++ * case of failure. -++ */ -++int ubifs_tnc_lookup(struct ubifs_info *c, const union ubifs_key *key, -++ void *node) -++{ -++ int found, n, err; -++ struct ubifs_znode *znode; -++ struct ubifs_zbranch zbr, *zt; -++ -++ mutex_lock(&c->tnc_mutex); -++ found = lookup_level0(c, key, &znode, &n); -++ if (!found) { -++ err = -ENOENT; -++ goto out; -++ } else if (found < 0) { -++ err = found; -++ goto out; -++ } -++ zt = &znode->zbranch[n]; -++ if (is_hash_key(c, key)) { -++ /* -++ * In this case the leaf node cache gets used, so we pass the -++ * address of the zbranch and keep the mutex locked -++ */ -++ err = tnc_read_node_nm(c, zt, node); -++ goto out; -++ } -++ zbr = znode->zbranch[n]; -++ mutex_unlock(&c->tnc_mutex); -++ -++ err = tnc_read_node(c, &zbr, node); -++ return err; -++ -++out: -++ mutex_unlock(&c->tnc_mutex); -++ return err; -++} -++ -++/** -++ * ubifs_tnc_locate - look up a file-system node and return it and its location. -++ * @c: UBIFS file-system description object -++ * @key: node key to lookup -++ * @node: the node is returned here -++ * @lnum: LEB number is returned here -++ * @offs: offset is returned here -++ * -++ * This function is the same as 'ubifs_tnc_lookup()' but it returns the node -++ * location also. See 'ubifs_tnc_lookup()'. -++ */ -++int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key, -++ void *node, int *lnum, int *offs) -++{ -++ int found, n, err; -++ struct ubifs_znode *znode; -++ struct ubifs_zbranch zbr, *zt; -++ -++ mutex_lock(&c->tnc_mutex); -++ found = lookup_level0(c, key, &znode, &n); -++ if (!found) { -++ err = -ENOENT; -++ goto out; -++ } else if (found < 0) { -++ err = found; -++ goto out; -++ } -++ zt = &znode->zbranch[n]; -++ if (is_hash_key(c, key)) { -++ /* -++ * In this case the leaf node cache gets used, so we pass the -++ * address of the zbranch and keep the mutex locked -++ */ -++ *lnum = zt->lnum; -++ *offs = zt->offs; -++ err = tnc_read_node_nm(c, zt, node); -++ goto out; -++ } -++ zbr = znode->zbranch[n]; -++ mutex_unlock(&c->tnc_mutex); -++ -++ *lnum = zbr.lnum; -++ *offs = zbr.offs; -++ -++ err = tnc_read_node(c, &zbr, node); -++ return err; -++ -++out: -++ mutex_unlock(&c->tnc_mutex); -++ return err; -++} -++ -++/** -++ * do_lookup_nm- look up a "hashed" node. -++ * directory entry file-system node. -++ * @c: UBIFS file-system description object -++ * @key: node key to lookup -++ * @node: the node is returned here -++ * @nm: node name -++ * -++ * This function look up and reads a node which contains name hash in the key. -++ * Since the hash may have collisions, there may be many nodes with the same -++ * key, so we have to sequentially look to all of them until the needed one is -++ * found. This function returns zero in case of success, %-ENOENT if the node -++ * was not found, and a negative error code in case of failure. -++ */ -++static int do_lookup_nm(struct ubifs_info *c, const union ubifs_key *key, -++ void *node, const struct qstr *nm) -++{ -++ int found, n, err; -++ struct ubifs_znode *znode; -++ struct ubifs_zbranch zbr; -++ -++ dbg_tnc("name '%.*s' key %s", nm->len, nm->name, DBGKEY(key)); -++ mutex_lock(&c->tnc_mutex); -++ found = lookup_level0(c, key, &znode, &n); -++ if (!found) { -++ err = -ENOENT; -++ goto out_unlock; -++ } else if (found < 0) { -++ err = found; -++ goto out_unlock; -++ } -++ -++ ubifs_assert(n >= 0); -++ -++ err = resolve_collision(c, key, &znode, &n, nm); -++ dbg_tnc("rc returned %d, znode %p, n %d", err, znode, n); -++ if (unlikely(err < 0)) -++ goto out_unlock; -++ if (err == 0) { -++ err = -ENOENT; -++ goto out_unlock; -++ } -++ -++ zbr = znode->zbranch[n]; -++ mutex_unlock(&c->tnc_mutex); -++ -++ err = tnc_read_node_nm(c, &zbr, node); -++ return err; -++ -++out_unlock: -++ mutex_unlock(&c->tnc_mutex); -++ return err; -++} -++ -++/** -++ * ubifs_tnc_lookup_nm- look up a "hashed" node. -++ * directory entry file-system node. -++ * @c: UBIFS file-system description object -++ * @key: node key to lookup -++ * @node: the node is returned here -++ * @nm: node name -++ * -++ * This function look up and reads a node which contains name hash in the key. -++ * Since the hash may have collisions, there may be many nodes with the same -++ * key, so we have to sequentially look to all of them until the needed one is -++ * found. This function returns zero in case of success, %-ENOENT if the node -++ * was not found, and a negative error code in case of failure. -++ */ -++int ubifs_tnc_lookup_nm(struct ubifs_info *c, const union ubifs_key *key, -++ void *node, const struct qstr *nm) -++{ -++ int err, len; -++ const struct ubifs_dent_node *dent = node; -++ -++ /* -++ * We assume that in most of the cases there are no name collisions and -++ * 'ubifs_tnc_lookup()' returns us the right direntry. -++ */ -++ err = ubifs_tnc_lookup(c, key, node); -++ if (err) -++ return err; -++ -++ len = le16_to_cpu(dent->nlen); -++ if (nm->len == len && !memcmp(dent->name, nm->name, len)) -++ return 0; -++ -++ /* -++ * Unluckily, there are hash collisions and we have to iterate over -++ * them look at each direntry with colliding name hash sequentially. -++ */ -++ return do_lookup_nm(c, key, node, nm); -++} -++ -++/** -++ * correct_parent_keys - correct parent znodes' keys. -++ * @c: UBIFS file-system description object -++ * @znode: znode to correct parent znodes for -++ * -++ * This is a helper function for 'tnc_insert()'. When the key of the leftmost -++ * zbranch changes, keys of parent znodes have to be corrected. This helper -++ * function is called in such situations and corrects the keys if needed. -++ */ -++static void correct_parent_keys(const struct ubifs_info *c, -++ struct ubifs_znode *znode) -++{ -++ union ubifs_key *key, *key1; -++ -++ ubifs_assert(znode->parent); -++ ubifs_assert(znode->iip == 0); -++ -++ key = &znode->zbranch[0].key; -++ key1 = &znode->parent->zbranch[0].key; -++ -++ while (keys_cmp(c, key, key1) < 0) { -++ key_copy(c, key, key1); -++ znode = znode->parent; -++ if (!znode->parent || znode->iip) -++ break; -++ key1 = &znode->parent->zbranch[0].key; -++ } -++} -++ -++/** -++ * insert_zbranch - insert a zbranch into a znode. -++ * @znode: znode into which to insert -++ * @zbr: zbranch to insert -++ * @n: slot number to insert to -++ * -++ * This is a helper function for 'tnc_insert()'. UBIFS does not allow "gaps" in -++ * znode's array of zbranches and keeps zbranches consolidated, so when a new -++ * zbranch has to be inserted to the @znode->zbranches[]' array at the @n-th -++ * slot, zbranches starting from @n have to be moved right. -++ */ -++static void insert_zbranch(struct ubifs_znode *znode, -++ const struct ubifs_zbranch *zbr, int n) -++{ -++ int i; -++ -++ ubifs_assert(ubifs_zn_dirty(znode)); -++ -++ if (znode->level) { -++ for (i = znode->child_cnt; i > n; i--) { -++ znode->zbranch[i] = znode->zbranch[i - 1]; -++ if (znode->zbranch[i].znode) -++ znode->zbranch[i].znode->iip = i; -++ } -++ if (zbr->znode) -++ zbr->znode->iip = n; -++ } else -++ for (i = znode->child_cnt; i > n; i--) -++ znode->zbranch[i] = znode->zbranch[i - 1]; -++ -++ znode->zbranch[n] = *zbr; -++ znode->child_cnt += 1; -++ -++ /* -++ * After inserting at slot zero, the lower bound of the key range of -++ * this znode may have changed. If this znode is subsequently split -++ * then the upper bound of the key range may change, and furthermore -++ * it could change to be lower than the original lower bound. If that -++ * happens, then it will no longer be possible to find this znode in the -++ * TNC using the key from the index node on flash. That is bad because -++ * if it is not found, we will assume it is obsolete and may overwrite -++ * it. Then if there is an unclean unmount, we will start using the -++ * old index which will be broken. -++ * -++ * So we first mark znodes that have insertions at slot zero, and then -++ * if they are split we add their lnum/offs to the old_idx tree. -++ */ -++ if (n == 0) -++ znode->alt = 1; -++} -++ -++/** -++ * tnc_insert - insert a node into TNC. -++ * @c: UBIFS file-system description object -++ * @znode: znode to insert into -++ * @zbr: branch to insert -++ * @n: slot number to insert new zbranch to -++ * -++ * This function inserts a new node described by @zbr into znode @znode. If -++ * znode does not have a free slot for new zbranch, it is split. Parent znodes -++ * are splat as well if needed. Returns zero in case of success or a negative -++ * error code in case of failure. -++ */ -++static int tnc_insert(struct ubifs_info *c, struct ubifs_znode *znode, -++ struct ubifs_zbranch *zbr, int n) -++{ -++ struct ubifs_znode *zn, *zi, *zp; -++ int i, keep, move, appending = 0; -++ union ubifs_key *key = &zbr->key; -++ -++ ubifs_assert(n >= 0 && n <= c->fanout); -++ -++ /* Implement naive insert for now */ -++again: -++ zp = znode->parent; -++ if (znode->child_cnt < c->fanout) { -++ ubifs_assert(n != c->fanout); -++ dbg_tnc("inserted at %d level %d, key %s", n, znode->level, -++ DBGKEY(key)); -++ -++ insert_zbranch(znode, zbr, n); -++ -++ /* Ensure parent's key is correct */ -++ if (n == 0 && zp && znode->iip == 0) -++ correct_parent_keys(c, znode); -++ -++ return 0; -++ } -++ -++ /* -++ * Unfortunately, @znode does not have more empty slots and we have to -++ * split it. -++ */ -++ dbg_tnc("splitting level %d, key %s", znode->level, DBGKEY(key)); -++ -++ if (znode->alt) -++ /* -++ * We can no longer be sure of finding this znode by key, so we -++ * record it in the old_idx tree. -++ */ -++ ins_clr_old_idx_znode(c, znode); -++ -++ zn = kzalloc(c->max_znode_sz, GFP_NOFS); -++ if (!zn) -++ return -ENOMEM; -++ zn->parent = zp; -++ zn->level = znode->level; -++ -++ /* Decide where to split */ -++ if (znode->level == 0 && n == c->fanout && -++ key_type(c, key) == UBIFS_DATA_KEY) { -++ union ubifs_key *key1; -++ -++ /* -++ * If this is an inode which is being appended - do not split -++ * it because no other zbranches can be inserted between -++ * zbranches of consecutive data nodes anyway. -++ */ -++ key1 = &znode->zbranch[n - 1].key; -++ if (key_ino(c, key1) == key_ino(c, key) && -++ key_type(c, key1) == UBIFS_DATA_KEY && -++ key_block(c, key1) == key_block(c, key) - 1) -++ appending = 1; -++ } -++ -++ if (appending) { -++ keep = c->fanout; -++ move = 0; -++ } else { -++ keep = (c->fanout + 1) / 2; -++ move = c->fanout - keep; -++ } -++ -++ /* -++ * Although we don't at present, we could look at the neighbors and see -++ * if we can move some zbranches there. -++ */ -++ -++ if (n < keep) { -++ /* Insert into existing znode */ -++ zi = znode; -++ move += 1; -++ keep -= 1; -++ } else { -++ /* Insert into new znode */ -++ zi = zn; -++ n -= keep; -++ /* Re-parent */ -++ if (zn->level != 0) -++ zbr->znode->parent = zn; -++ } -++ -++ __set_bit(DIRTY_ZNODE, &zn->flags); -++ atomic_long_inc(&c->dirty_zn_cnt); -++ -++ zn->child_cnt = move; -++ znode->child_cnt = keep; -++ -++ dbg_tnc("moving %d, keeping %d", move, keep); -++ -++ /* Move zbranch */ -++ for (i = 0; i < move; i++) { -++ zn->zbranch[i] = znode->zbranch[keep + i]; -++ /* Re-parent */ -++ if (zn->level != 0) -++ if (zn->zbranch[i].znode) { -++ zn->zbranch[i].znode->parent = zn; -++ zn->zbranch[i].znode->iip = i; -++ } -++ } -++ -++ /* Insert new key and branch */ -++ dbg_tnc("inserting at %d level %d, key %s", n, zn->level, DBGKEY(key)); -++ -++ insert_zbranch(zi, zbr, n); -++ -++ /* Insert new znode (produced by spitting) into the parent */ -++ if (zp) { -++ i = n; -++ /* Locate insertion point */ -++ n = znode->iip + 1; -++ if (appending && n != c->fanout) -++ appending = 0; -++ -++ if (i == 0 && zi == znode && znode->iip == 0) -++ correct_parent_keys(c, znode); -++ -++ /* Tail recursion */ -++ zbr->key = zn->zbranch[0].key; -++ zbr->znode = zn; -++ zbr->lnum = 0; -++ zbr->offs = 0; -++ zbr->len = 0; -++ znode = zp; -++ -++ goto again; -++ } -++ -++ /* We have to split root znode */ -++ dbg_tnc("creating new zroot at level %d", znode->level + 1); -++ -++ zi = kzalloc(c->max_znode_sz, GFP_NOFS); -++ if (!zi) -++ return -ENOMEM; -++ -++ zi->child_cnt = 2; -++ zi->level = znode->level + 1; -++ -++ __set_bit(DIRTY_ZNODE, &zi->flags); -++ atomic_long_inc(&c->dirty_zn_cnt); -++ -++ zi->zbranch[0].key = znode->zbranch[0].key; -++ zi->zbranch[0].znode = znode; -++ zi->zbranch[0].lnum = c->zroot.lnum; -++ zi->zbranch[0].offs = c->zroot.offs; -++ zi->zbranch[0].len = c->zroot.len; -++ zi->zbranch[1].key = zn->zbranch[0].key; -++ zi->zbranch[1].znode = zn; -++ -++ c->zroot.lnum = 0; -++ c->zroot.offs = 0; -++ c->zroot.len = 0; -++ c->zroot.znode = zi; -++ -++ zn->parent = zi; -++ zn->iip = 1; -++ znode->parent = zi; -++ znode->iip = 0; -++ -++ return 0; -++} -++ -++/** -++ * ubifs_tnc_add - add a node to TNC. -++ * @c: UBIFS file-system description object -++ * @key: key to add -++ * @lnum: LEB number of node -++ * @offs: node offset -++ * @len: node length -++ * -++ * This function adds a node with key @key to TNC. The node may be new or it may -++ * obsolete some existing one. Returns %0 on success or negative error code on -++ * failure. -++ */ -++int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum, -++ int offs, int len) -++{ -++ int found, n, err = 0; -++ struct ubifs_znode *znode; -++ -++ mutex_lock(&c->tnc_mutex); -++ dbg_tnc("%d:%d, len %d, key %s", lnum, offs, len, DBGKEY(key)); -++ found = lookup_level0_dirty(c, key, &znode, &n); -++ if (!found) { -++ struct ubifs_zbranch zbr; -++ -++ zbr.znode = NULL; -++ zbr.lnum = lnum; -++ zbr.offs = offs; -++ zbr.len = len; -++ key_copy(c, key, &zbr.key); -++ err = tnc_insert(c, znode, &zbr, n + 1); -++ } else if (found == 1) { -++ struct ubifs_zbranch *zbr = &znode->zbranch[n]; -++ -++ lnc_free(zbr); -++ err = ubifs_add_dirt(c, zbr->lnum, zbr->len); -++ zbr->lnum = lnum; -++ zbr->offs = offs; -++ zbr->len = len; -++ } else -++ err = found; -++ if (!err) -++ err = dbg_check_tnc(c, 0); -++ mutex_unlock(&c->tnc_mutex); -++ -++ return err; -++} -++ -++/** -++ * ubifs_tnc_replace - replace a node in the TNC only if the old node is found. -++ * @c: UBIFS file-system description object -++ * @key: key to add -++ * @old_lnum: LEB number of old node -++ * @old_offs: old node offset -++ * @lnum: LEB number of node -++ * @offs: node offset -++ * @len: node length -++ * -++ * This function replaces a node with key @key in the TNC only if the old node -++ * is found. This function is called by garbage collection when node are moved. -++ * Returns %0 on success or negative error code on failure. -++ */ -++int ubifs_tnc_replace(struct ubifs_info *c, const union ubifs_key *key, -++ int old_lnum, int old_offs, int lnum, int offs, int len) -++{ -++ int found, n, err = 0; -++ struct ubifs_znode *znode; -++ -++ mutex_lock(&c->tnc_mutex); -++ dbg_tnc("old LEB %d:%d, new LEB %d:%d, len %d, key %s", old_lnum, -++ old_offs, lnum, offs, len, DBGKEY(key)); -++ found = lookup_level0_dirty(c, key, &znode, &n); -++ if (found < 0) { -++ err = found; -++ goto out_unlock; -++ } -++ -++ if (found == 1) { -++ struct ubifs_zbranch *zbr = &znode->zbranch[n]; -++ -++ found = 0; -++ if (zbr->lnum == old_lnum && zbr->offs == old_offs) { -++ lnc_free(zbr); -++ err = ubifs_add_dirt(c, zbr->lnum, zbr->len); -++ if (err) -++ goto out_unlock; -++ zbr->lnum = lnum; -++ zbr->offs = offs; -++ zbr->len = len; -++ found = 1; -++ } else if (is_hash_key(c, key)) { -++ found = resolve_collision_directly(c, key, &znode, &n, -++ old_lnum, old_offs); -++ dbg_tnc("rc returned %d, znode %p, n %d, LEB %d:%d", -++ found, znode, n, old_lnum, old_offs); -++ if (found < 0) { -++ err = found; -++ goto out_unlock; -++ } -++ -++ if (found) { -++ /* Ensure the znode is dirtied */ -++ if (znode->cnext || !ubifs_zn_dirty(znode)) { -++ znode = dirty_cow_bottom_up(c, -++ znode); -++ if (IS_ERR(znode)) { -++ err = PTR_ERR(znode); -++ goto out_unlock; -++ } -++ } -++ zbr = &znode->zbranch[n]; -++ lnc_free(zbr); -++ err = ubifs_add_dirt(c, zbr->lnum, -++ zbr->len); -++ if (err) -++ goto out_unlock; -++ zbr->lnum = lnum; -++ zbr->offs = offs; -++ zbr->len = len; -++ } -++ } -++ } -++ -++ if (!found) -++ err = ubifs_add_dirt(c, lnum, len); -++ -++ if (!err) -++ err = dbg_check_tnc(c, 0); -++ -++out_unlock: -++ mutex_unlock(&c->tnc_mutex); -++ return err; -++} -++ -++/** -++ * ubifs_tnc_add_nm - add a "hashed" node to TNC. -++ * @c: UBIFS file-system description object -++ * @key: key to add -++ * @lnum: LEB number of node -++ * @offs: node offset -++ * @len: node length -++ * @nm: node name -++ * -++ * This is the same as 'ubifs_tnc_add()' but it should be used with keys which -++ * may have collisions, like directory entry keys. -++ */ -++int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key, -++ int lnum, int offs, int len, const struct qstr *nm) -++{ -++ int found, n, err = 0; -++ struct ubifs_znode *znode; -++ -++ mutex_lock(&c->tnc_mutex); -++ dbg_tnc("LEB %d:%d, name '%.*s', key %s", lnum, offs, nm->len, nm->name, -++ DBGKEY(key)); -++ found = lookup_level0_dirty(c, key, &znode, &n); -++ if (found < 0) { -++ err = found; -++ goto out_unlock; -++ } -++ -++ if (found == 1) { -++ if (c->replaying) -++ found = fallible_resolve_collision(c, key, &znode, &n, -++ nm, 1); -++ else -++ found = resolve_collision(c, key, &znode, &n, nm); -++ dbg_tnc("rc returned %d, znode %p, n %d", found, znode, n); -++ if (found < 0) { -++ err = found; -++ goto out_unlock; -++ } -++ -++ /* Ensure the znode is dirtied */ -++ if (znode->cnext || !ubifs_zn_dirty(znode)) { -++ znode = dirty_cow_bottom_up(c, znode); -++ if (IS_ERR(znode)) { -++ err = PTR_ERR(znode); -++ goto out_unlock; -++ } -++ } -++ -++ if (found == 1) { -++ struct ubifs_zbranch *zbr = &znode->zbranch[n]; -++ -++ lnc_free(zbr); -++ err = ubifs_add_dirt(c, zbr->lnum, zbr->len); -++ zbr->lnum = lnum; -++ zbr->offs = offs; -++ zbr->len = len; -++ goto out_unlock; -++ } -++ } -++ -++ if (!found) { -++ struct ubifs_zbranch zbr; -++ -++ zbr.znode = NULL; -++ zbr.lnum = lnum; -++ zbr.offs = offs; -++ zbr.len = len; -++ key_copy(c, key, &zbr.key); -++ err = tnc_insert(c, znode, &zbr, n + 1); -++ if (err) -++ goto out_unlock; -++ if (c->replaying && c->replay_sqnum < c->cs_sqnum) { -++ /* -++ * This node was moved by garbage collection. We can -++ * tell because it is in the journal but it has a -++ * sequence number earlier than the last commit-start. -++ * We did not find it in the index so there may be a -++ * dangling branch still in the index. So we remove it -++ * by passing 'ubifs_tnc_remove_nm()' the same key but -++ * an unmatchable name. -++ */ -++ struct qstr noname = { .len = 0, .name = "" }; -++ -++ err = dbg_check_tnc(c, 0); -++ mutex_unlock(&c->tnc_mutex); -++ if (err) -++ return err; -++ return ubifs_tnc_remove_nm(c, key, &noname); -++ } -++ } -++ -++out_unlock: -++ if (!err) -++ err = dbg_check_tnc(c, 0); -++ mutex_unlock(&c->tnc_mutex); -++ return err; -++} -++ -++/** -++ * tnc_delete - delete a znode form TNC. -++ * @c: UBIFS file-system description object -++ * @znode: znode to delete from -++ * @n: zbranch slot number to delete -++ * -++ * This function deletes a leaf node from @n-th slot of @znode. Returns zero in -++ * case of success and a negative error code in case of failure. -++ */ -++static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n) -++{ -++ struct ubifs_zbranch *zbr; -++ struct ubifs_znode *zp; -++ int i, err; -++ -++ /* Delete without merge for now */ -++ ubifs_assert(znode->level == 0); -++ ubifs_assert(n >= 0 && n < c->fanout); -++ dbg_tnc("deleting %s", DBGKEY(&znode->zbranch[n].key)); -++ -++ zbr = &znode->zbranch[n]; -++ lnc_free(zbr); -++ -++ err = ubifs_add_dirt(c, zbr->lnum, zbr->len); -++ if (err) { -++ dbg_dump_znode(c, znode); -++ return err; -++ } -++ -++ /* We do not "gap" zbranch slots */ -++ for (i = n; i < znode->child_cnt - 1; i++) -++ znode->zbranch[i] = znode->zbranch[i + 1]; -++ znode->child_cnt -= 1; -++ -++ if (znode->child_cnt > 0) -++ return 0; -++ -++ /* -++ * This was the last zbranch, we have to delete this znode from the -++ * parent. -++ */ -++ -++ do { -++ ubifs_assert(!test_bit(OBSOLETE_ZNODE, &znode->flags)); -++ ubifs_assert(ubifs_zn_dirty(znode)); -++ -++ zp = znode->parent; -++ n = znode->iip; -++ -++ atomic_long_dec(&c->dirty_zn_cnt); -++ -++ err = insert_old_idx_znode(c, znode); -++ if (err) -++ return err; -++ -++ if (znode->cnext) { -++ __set_bit(OBSOLETE_ZNODE, &znode->flags); -++ atomic_long_inc(&c->clean_zn_cnt); -++ atomic_long_inc(&ubifs_clean_zn_cnt); -++ } else -++ kfree(znode); -++ znode = zp; -++ } while (znode->child_cnt == 1); /* while removing last child */ -++ -++ /* Remove from znode, entry n - 1 */ -++ znode->child_cnt -= 1; -++ ubifs_assert(znode->level != 0); -++ for (i = n; i < znode->child_cnt; i++) { -++ znode->zbranch[i] = znode->zbranch[i + 1]; -++ if (znode->zbranch[i].znode) -++ znode->zbranch[i].znode->iip = i; -++ } -++ -++ /* -++ * If this is the root and it has only 1 child then -++ * collapse the tree. -++ */ -++ if (!znode->parent) { -++ while (znode->child_cnt == 1 && znode->level != 0) { -++ zp = znode; -++ zbr = &znode->zbranch[0]; -++ znode = get_znode(c, znode, 0); -++ if (IS_ERR(znode)) -++ return PTR_ERR(znode); -++ znode = dirty_cow_znode(c, zbr); -++ if (IS_ERR(znode)) -++ return PTR_ERR(znode); -++ znode->parent = NULL; -++ znode->iip = 0; -++ if (c->zroot.len) { -++ err = insert_old_idx(c, c->zroot.lnum, -++ c->zroot.offs); -++ if (err) -++ return err; -++ } -++ c->zroot.lnum = zbr->lnum; -++ c->zroot.offs = zbr->offs; -++ c->zroot.len = zbr->len; -++ c->zroot.znode = znode; -++ ubifs_assert(!test_bit(OBSOLETE_ZNODE, -++ &zp->flags)); -++ ubifs_assert(test_bit(DIRTY_ZNODE, &zp->flags)); -++ atomic_long_dec(&c->dirty_zn_cnt); -++ -++ if (zp->cnext) { -++ __set_bit(OBSOLETE_ZNODE, &zp->flags); -++ atomic_long_inc(&c->clean_zn_cnt); -++ atomic_long_inc(&ubifs_clean_zn_cnt); -++ } else -++ kfree(zp); -++ } -++ } -++ -++ return 0; -++} -++ -++/** -++ * ubifs_tnc_remove - remove an index entry of a node. -++ * @c: UBIFS file-system description object -++ * @key: key of node -++ * -++ * Returns %0 on success or negative error code on failure. -++ */ -++int ubifs_tnc_remove(struct ubifs_info *c, const union ubifs_key *key) -++{ -++ int found, n, err = 0; -++ struct ubifs_znode *znode; -++ -++ mutex_lock(&c->tnc_mutex); -++ dbg_tnc("key %s", DBGKEY(key)); -++ found = lookup_level0_dirty(c, key, &znode, &n); -++ if (found < 0) { -++ err = found; -++ goto out_unlock; -++ } -++ if (found == 1) -++ err = tnc_delete(c, znode, n); -++ if (!err) -++ err = dbg_check_tnc(c, 0); -++ -++out_unlock: -++ mutex_unlock(&c->tnc_mutex); -++ return err; -++} -++ -++/** -++ * ubifs_tnc_remove_nm - remove an index entry for a "hashed" node. -++ * @c: UBIFS file-system description object -++ * @key: key of node -++ * @nm: directory entry name -++ * -++ * Returns %0 on success or negative error code on failure. -++ */ -++int ubifs_tnc_remove_nm(struct ubifs_info *c, const union ubifs_key *key, -++ const struct qstr *nm) -++{ -++ int n, err; -++ struct ubifs_znode *znode; -++ -++ mutex_lock(&c->tnc_mutex); -++ dbg_tnc("%.*s, key %s", nm->len, nm->name, DBGKEY(key)); -++ err = lookup_level0_dirty(c, key, &znode, &n); -++ if (err < 0) -++ goto out_unlock; -++ -++ if (err) { -++ if (c->replaying) -++ err = fallible_resolve_collision(c, key, &znode, &n, -++ nm, 0); -++ else -++ err = resolve_collision(c, key, &znode, &n, nm); -++ dbg_tnc("rc returned %d, znode %p, n %d", err, znode, n); -++ if (err < 0) -++ goto out_unlock; -++ if (err) { -++ /* Ensure the znode is dirtied */ -++ if (znode->cnext || !ubifs_zn_dirty(znode)) { -++ znode = dirty_cow_bottom_up(c, znode); -++ if (IS_ERR(znode)) { -++ err = PTR_ERR(znode); -++ goto out_unlock; -++ } -++ } -++ err = tnc_delete(c, znode, n); -++ } -++ } -++ -++out_unlock: -++ if (!err) -++ err = dbg_check_tnc(c, 0); -++ mutex_unlock(&c->tnc_mutex); -++ return err; -++} -++ -++/** -++ * key_in_range - determine if a key falls within a range of keys. -++ * @c: UBIFS file-system description object -++ * @key: key to check -++ * @from_key: lowest key in range -++ * @to_key: highest key in range -++ * -++ * This function returns %1 if the key is in range and %0 otherwise. -++ */ -++static int key_in_range(struct ubifs_info *c, union ubifs_key *key, -++ union ubifs_key *from_key, union ubifs_key *to_key) -++{ -++ if (keys_cmp(c, key, from_key) < 0) -++ return 0; -++ if (keys_cmp(c, key, to_key) > 0) -++ return 0; -++ return 1; -++} -++ -++/** -++ * ubifs_tnc_remove_range - remove index entries in range. -++ * @c: UBIFS file-system description object -++ * @from_key: lowest key to remove -++ * @to_key: highest key to remove -++ * -++ * This function removes index entries starting at @from_key and ending at -++ * @to_key. This function returns zero in case of success and a negative error -++ * code in case of failure. -++ */ -++int ubifs_tnc_remove_range(struct ubifs_info *c, union ubifs_key *from_key, -++ union ubifs_key *to_key) -++{ -++ int i, n, k, err = 0; -++ struct ubifs_znode *znode; -++ union ubifs_key *key; -++ -++ mutex_lock(&c->tnc_mutex); -++ while (1) { -++ /* Find first level 0 znode that contains keys to remove */ -++ err = lookup_level0(c, from_key, &znode, &n); -++ if (err < 0) -++ goto out_unlock; -++ -++ if (err) -++ key = from_key; -++ else { -++ err = tnc_next(c, &znode, &n); -++ if (err == -ENOENT) { -++ err = 0; -++ goto out_unlock; -++ } -++ if (err < 0) -++ goto out_unlock; -++ key = &znode->zbranch[n].key; -++ if (!key_in_range(c, key, from_key, to_key)) { -++ err = 0; -++ goto out_unlock; -++ } -++ } -++ -++ /* Ensure the znode is dirtied */ -++ if (znode->cnext || !ubifs_zn_dirty(znode)) { -++ znode = dirty_cow_bottom_up(c, znode); -++ if (IS_ERR(znode)) { -++ err = PTR_ERR(znode); -++ goto out_unlock; -++ } -++ } -++ -++ /* Remove all keys in range except the first */ -++ for (i = n + 1, k = 0; i < znode->child_cnt; i++, k++) { -++ key = &znode->zbranch[i].key; -++ if (!key_in_range(c, key, from_key, to_key)) -++ break; -++ lnc_free(&znode->zbranch[i]); -++ err = ubifs_add_dirt(c, znode->zbranch[i].lnum, -++ znode->zbranch[i].len); -++ if (err) { -++ dbg_dump_znode(c, znode); -++ goto out_unlock; -++ } -++ dbg_tnc("removing %s", DBGKEY(key)); -++ } -++ if (k) { -++ for (i = n + 1 + k; i < znode->child_cnt; i++) -++ znode->zbranch[i - k] = znode->zbranch[i]; -++ znode->child_cnt -= k; -++ } -++ -++ /* Now delete the first */ -++ err = tnc_delete(c, znode, n); -++ if (err) -++ goto out_unlock; -++ } -++ -++out_unlock: -++ if (!err) -++ err = dbg_check_tnc(c, 0); -++ mutex_unlock(&c->tnc_mutex); -++ return err; -++} -++ -++/** -++ * ubifs_tnc_remove_ino - remove an inode from TNC. -++ * @c: UBIFS file-system description object -++ * @inum: inode number to remove -++ * -++ * This function remove inode @inum and all the extended attributes associated -++ * with the anode from TNC and returns zero in case of success or a negative -++ * error code in case of failure. -++ */ -++int ubifs_tnc_remove_ino(struct ubifs_info *c, ino_t inum) -++{ -++ union ubifs_key key1, key2; -++ struct ubifs_dent_node *xent, *pxent = NULL; -++ struct qstr nm = { .name = NULL }; -++ -++ dbg_tnc("ino %lu", inum); -++ -++ /* -++ * Walk all extended attribute entries and remove them together with -++ * corresponding extended attribute inodes. -++ */ -++ lowest_xent_key(c, &key1, inum); -++ while (1) { -++ ino_t xattr_inum; -++ int err; -++ -++ xent = ubifs_tnc_next_ent(c, &key1, &nm); -++ if (IS_ERR(xent)) { -++ err = PTR_ERR(xent); -++ if (err == -ENOENT) -++ break; -++ return err; -++ } -++ -++ xattr_inum = le64_to_cpu(xent->inum); -++ dbg_tnc("xent '%s', ino %lu", xent->name, xattr_inum); -++ -++ nm.name = xent->name; -++ nm.len = le16_to_cpu(xent->nlen); -++ err = ubifs_tnc_remove_nm(c, &key1, &nm); -++ if (err) { -++ kfree(xent); -++ return err; -++ } -++ -++ lowest_ino_key(c, &key1, xattr_inum); -++ highest_ino_key(c, &key2, xattr_inum); -++ err = ubifs_tnc_remove_range(c, &key1, &key2); -++ if (err) { -++ kfree(xent); -++ return err; -++ } -++ -++ kfree(pxent); -++ pxent = xent; -++ key_read(c, &xent->key, &key1); -++ } -++ -++ kfree(pxent); -++ lowest_ino_key(c, &key1, inum); -++ highest_ino_key(c, &key2, inum); -++ -++ return ubifs_tnc_remove_range(c, &key1, &key2); -++} -++ -++/** -++ * ubifs_tnc_next_ent - walk directory or extended attribute entries. -++ * @c: UBIFS file-system description object -++ * @key: key of last entry -++ * @nm: name of last entry found or %NULL -++ * -++ * This function finds and reads the next directory or extended attribute entry -++ * after the given key (@key) if there is one. @nm is used to resolve -++ * collisions. -++ * -++ * If the name of the current entry is not known and only the key is known, -++ * @nm->name has to be %NULL. In this case the semantics of this function is a -++ * little bit different and it returns the entry corresponding to this key, not -++ * the next one. If the key was not found, the closest "right" entry is -++ * returned. -++ * -++ * If the fist entry has to be found, @key has to contain the lowest possible -++ * key value for this inode and @name has to be %NULL. -++ * -++ * This function returns the found directory or extended attribute entry node -++ * in case of success, %-ENOENT is returned if no entry was found, and a -++ * negative error code is returned in case of failure. -++ */ -++struct ubifs_dent_node *ubifs_tnc_next_ent(struct ubifs_info *c, -++ union ubifs_key *key, -++ const struct qstr *nm) -++{ -++ int n, err, type = key_type(c, key); -++ struct ubifs_znode *znode; -++ struct ubifs_dent_node *dent; -++ struct ubifs_zbranch *zbr; -++ union ubifs_key *dkey; -++ -++ dbg_tnc("%s %s", nm->name ? (char *)nm->name : "(lowest)", DBGKEY(key)); -++ ubifs_assert(is_hash_key(c, key)); -++ -++ mutex_lock(&c->tnc_mutex); -++ err = lookup_level0(c, key, &znode, &n); -++ if (unlikely(err < 0)) -++ goto out_unlock; -++ -++ if (nm->name) { -++ if (err) { -++ /* Handle collisions */ -++ err = resolve_collision(c, key, &znode, &n, nm); -++ dbg_tnc("rc returned %d, znode %p, n %d", -++ err, znode, n); -++ if (unlikely(err < 0)) -++ goto out_unlock; -++ } -++ -++ /* Now find next entry */ -++ err = tnc_next(c, &znode, &n); -++ if (unlikely(err)) -++ goto out_unlock; -++ } else { -++ /* -++ * The full name of the entry was not given, in which case the -++ * behavior of this function is a little different and it -++ * returns current entry, not the next one. -++ */ -++ if (!err) { -++ /* -++ * However, the given key does not exist in the TNC -++ * tree and @znode/@n variables contain the closest -++ * "preceding" element. Switch to the next one. -++ */ -++ err = tnc_next(c, &znode, &n); -++ if (err) -++ goto out_unlock; -++ } -++ } -++ -++ zbr = &znode->zbranch[n]; -++ dent = kmalloc(zbr->len, GFP_NOFS); -++ if (unlikely(!dent)) { -++ err = -ENOMEM; -++ goto out_unlock; -++ } -++ -++ /* -++ * The above 'tnc_next()' call could lead us to the next inode, check -++ * this. -++ */ -++ dkey = &zbr->key; -++ if (key_ino(c, dkey) != key_ino(c, key) || -++ key_type(c, dkey) != type) { -++ err = -ENOENT; -++ goto out_free; -++ } -++ -++ err = tnc_read_node_nm(c, zbr, dent); -++ if (unlikely(err)) -++ goto out_free; -++ -++ mutex_unlock(&c->tnc_mutex); -++ return dent; -++ -++out_free: -++ kfree(dent); -++out_unlock: -++ mutex_unlock(&c->tnc_mutex); -++ return ERR_PTR(err); -++} -++ -++/** -++ * tnc_destroy_cnext - destroy left-over obsolete znodes from a failed commit. -++ * @c: UBIFS file-system description object -++ * -++ * Destroy left-over obsolete znodes from a failed commit. -++ */ -++static void tnc_destroy_cnext(struct ubifs_info *c) -++{ -++ struct ubifs_znode *cnext; -++ -++ if (!c->cnext) -++ return; -++ ubifs_assert(c->cmt_state == COMMIT_BROKEN); -++ cnext = c->cnext; -++ do { -++ struct ubifs_znode *znode = cnext; -++ -++ cnext = cnext->cnext; -++ if (test_bit(OBSOLETE_ZNODE, &znode->flags)) -++ kfree(znode); -++ } while (cnext && cnext != c->cnext); -++} -++ -++/** -++ * ubifs_tnc_close - close TNC subsystem and free all related resources. -++ * @c: UBIFS file-system description object -++ */ -++void ubifs_tnc_close(struct ubifs_info *c) -++{ -++ long clean_freed; -++ -++ tnc_destroy_cnext(c); -++ if (c->zroot.znode) { -++ clean_freed = ubifs_destroy_tnc_subtree(c->zroot.znode); -++ atomic_long_sub(clean_freed, &ubifs_clean_zn_cnt); -++ } -++ kfree(c->gap_lebs); -++ kfree(c->ilebs); -++ destroy_old_idx(c); -++} -++ -++/** -++ * left_znode - get the znode to the left. -++ * @c: UBIFS file-system description object -++ * @znode: znode -++ * -++ * This function returns a pointer to the znode to the left of @znode or NULL if -++ * there is not one. A negative error code is returned on failure. -++ */ -++static struct ubifs_znode *left_znode(struct ubifs_info *c, -++ struct ubifs_znode *znode) -++{ -++ int level = znode->level; -++ -++ while (1) { -++ int n = znode->iip - 1; -++ -++ /* Go up until we can go left */ -++ znode = znode->parent; -++ if (!znode) -++ return NULL; -++ if (n >= 0) { -++ /* Now go down the rightmost branch to 'level' */ -++ znode = get_znode(c, znode, n); -++ if (IS_ERR(znode)) -++ return znode; -++ while (znode->level != level) { -++ n = znode->child_cnt - 1; -++ znode = get_znode(c, znode, n); -++ if (IS_ERR(znode)) -++ return znode; -++ } -++ break; -++ } -++ } -++ return znode; -++} -++ -++/** -++ * right_znode - get the znode to the right. -++ * @c: UBIFS file-system description object -++ * @znode: znode -++ * -++ * This function returns a pointer to the znode to the right of @znode or NULL -++ * if there is not one. A negative error code is returned on failure. -++ */ -++static struct ubifs_znode *right_znode(struct ubifs_info *c, -++ struct ubifs_znode *znode) -++{ -++ int level = znode->level; -++ -++ while (1) { -++ int n = znode->iip + 1; -++ -++ /* Go up until we can go right */ -++ znode = znode->parent; -++ if (!znode) -++ return NULL; -++ if (n < znode->child_cnt) { -++ /* Now go down the leftmost branch to 'level' */ -++ znode = get_znode(c, znode, n); -++ if (IS_ERR(znode)) -++ return znode; -++ while (znode->level != level) { -++ znode = get_znode(c, znode, 0); -++ if (IS_ERR(znode)) -++ return znode; -++ } -++ break; -++ } -++ } -++ return znode; -++} -++ -++/** -++ * lookup_znode - find a particular indexing node from TNC. -++ * @c: UBIFS file-system description object -++ * @key: index node key to lookup -++ * @level: index node level -++ * @lnum: index node LEB number -++ * @offs: index node offset -++ * -++ * This function searches an indexing node by its first key @key and its -++ * address @lnum:@offs. It looks up the indexing tree by pulling all indexing -++ * nodes it traverses to TNC. This function is called fro indexing nodes which -++ * were found on the media by scanning, for example when garbage-collecting or -++ * when doing in-the-gaps commit. This means that the indexing node which is -++ * looked for does not have to have exactly the same leftmost key @key, because -++ * the leftmost key may have been changed, in which case TNC will contain a -++ * dirty znode which still refers the same @lnum:@offs. This function is clever -++ * enough to recognize such indexing nodes. -++ * -++ * Note, if a znode was deleted or changed too much, then this function will -++ * not find it. For situations like this UBIFS has the old index RB-tree -++ * (indexed by @lnum:@offs). -++ * -++ * This function returns a pointer to the znode found or %NULL if it is not -++ * found. A negative error code is returned on failure. -++ */ -++static struct ubifs_znode *lookup_znode(struct ubifs_info *c, -++ union ubifs_key *key, int level, -++ int lnum, int offs) -++{ -++ struct ubifs_znode *znode, *zn; -++ int n, nn; -++ -++ /* -++ * The arguments have probably been read off flash, so don't assume -++ * they are valid. -++ */ -++ if (level < 0) -++ return ERR_PTR(-EINVAL); -++ -++ /* Get the root znode */ -++ znode = c->zroot.znode; -++ if (!znode) { -++ znode = load_znode(c, &c->zroot, NULL, 0); -++ if (IS_ERR(znode)) -++ return znode; -++ } -++ /* Check if it is the one we are looking for */ -++ if (c->zroot.lnum == lnum && c->zroot.offs == offs) -++ return znode; -++ /* Descend to the parent level i.e. (level + 1) */ -++ if (level >= znode->level) -++ return NULL; -++ while (1) { -++ ubifs_search_zbranch(c, znode, key, &n); -++ if (n < 0) { -++ /* -++ * We reached a znode where the leftmost key is greater -++ * than the key we are searching for. This is the same -++ * situation as the one described in a huge comment at -++ * the end of the 'lookup_level0()' function. And for -++ * exactly the same reasons we have to try to look left -++ * before giving up. -++ */ -++ znode = left_znode(c, znode); -++ if (!znode) -++ return NULL; -++ if (IS_ERR(znode)) -++ return znode; -++ ubifs_search_zbranch(c, znode, key, &n); -++ ubifs_assert(n >= 0); -++ } -++ if (znode->level == level + 1) -++ break; -++ znode = get_znode(c, znode, n); -++ if (IS_ERR(znode)) -++ return znode; -++ } -++ /* Check if the child is the one we are looking for */ -++ if (znode->zbranch[n].lnum == lnum && znode->zbranch[n].offs == offs) -++ return get_znode(c, znode, n); -++ /* If the key is unique, there is nowhere else to look */ -++ if (!is_hash_key(c, key)) -++ return NULL; -++ /* -++ * The key is not unique and so may be also in the znodes to either -++ * side. -++ */ -++ zn = znode; -++ nn = n; -++ /* Look left */ -++ while (1) { -++ /* Move one branch to the left */ -++ if (n) -++ n -= 1; -++ else { -++ znode = left_znode(c, znode); -++ if (!znode) -++ break; -++ if (IS_ERR(znode)) -++ return znode; -++ n = znode->child_cnt - 1; -++ } -++ /* Check it */ -++ if (znode->zbranch[n].lnum == lnum && -++ znode->zbranch[n].offs == offs) -++ return get_znode(c, znode, n); -++ /* Stop if the key is less than the one we are looking for */ -++ if (keys_cmp(c, &znode->zbranch[n].key, key) < 0) -++ break; -++ } -++ /* Back to the middle */ -++ znode = zn; -++ n = nn; -++ /* Look right */ -++ while (1) { -++ /* Move one branch to the right */ -++ if (++n >= znode->child_cnt) { -++ znode = right_znode(c, znode); -++ if (!znode) -++ break; -++ if (IS_ERR(znode)) -++ return znode; -++ n = 0; -++ } -++ /* Check it */ -++ if (znode->zbranch[n].lnum == lnum && -++ znode->zbranch[n].offs == offs) -++ return get_znode(c, znode, n); -++ /* Stop if the key is greater than the one we are looking for */ -++ if (keys_cmp(c, &znode->zbranch[n].key, key) > 0) -++ break; -++ } -++ return NULL; -++} -++ -++/** -++ * is_idx_node_in_tnc - determine if an index node is in the TNC. -++ * @c: UBIFS file-system description object -++ * @key: key of index node -++ * @level: index node level -++ * @lnum: LEB number of index node -++ * @offs: offset of index node -++ * -++ * This function returns %0 if the index node is not referred to in the TNC, %1 -++ * if the index node is referred to in the TNC and the corresponding znode is -++ * dirty, %2 if an index node is referred to in the TNC and the corresponding -++ * znode is clean, and a negative error code in case of failure. -++ * -++ * Note, the @key argument has to be the key of the first child. Also note, -++ * this function relies on the fact that 0:0 is never a valid LEB number and -++ * offset for a main-area node. -++ */ -++int is_idx_node_in_tnc(struct ubifs_info *c, union ubifs_key *key, int level, -++ int lnum, int offs) -++{ -++ struct ubifs_znode *znode; -++ -++ znode = lookup_znode(c, key, level, lnum, offs); -++ if (!znode) -++ return 0; -++ if (IS_ERR(znode)) -++ return PTR_ERR(znode); -++ -++ return ubifs_zn_dirty(znode) ? 1 : 2; -++} -++ -++/** -++ * is_leaf_node_in_tnc - determine if a non-indexing not is in the TNC. -++ * @c: UBIFS file-system description object -++ * @key: node key -++ * @lnum: node LEB number -++ * @offs: node offset -++ * -++ * This function returns %1 if the node is referred to in the TNC, %0 if it is -++ * not, and a negative error code in case of failure. -++ * -++ * Note, this function relies on the fact that 0:0 is never a valid LEB number -++ * and offset for a main-area node. -++ */ -++static int is_leaf_node_in_tnc(struct ubifs_info *c, union ubifs_key *key, -++ int lnum, int offs) -++{ -++ struct ubifs_zbranch *zbr; -++ struct ubifs_znode *znode, *zn; -++ int n, found, err, nn; -++ const int unique = !is_hash_key(c, key); -++ -++ found = lookup_level0(c, key, &znode, &n); -++ if (found < 0) -++ return found; /* Error code */ -++ if (!found) -++ return 0; -++ zbr = &znode->zbranch[n]; -++ if (lnum == zbr->lnum && offs == zbr->offs) -++ return 1; /* Found it */ -++ if (unique) -++ return 0; -++ /* -++ * Because the key is not unique, we have to look left -++ * and right as well -++ */ -++ zn = znode; -++ nn = n; -++ /* Look left */ -++ while (1) { -++ err = tnc_prev(c, &znode, &n); -++ if (err == -ENOENT) -++ break; -++ if (err) -++ return err; -++ if (keys_cmp(c, key, &znode->zbranch[n].key)) -++ break; -++ zbr = &znode->zbranch[n]; -++ if (lnum == zbr->lnum && offs == zbr->offs) -++ return 1; /* Found it */ -++ } -++ /* Look right */ -++ znode = zn; -++ n = nn; -++ while (1) { -++ err = tnc_next(c, &znode, &n); -++ if (err) { -++ if (err == -ENOENT) -++ return 0; -++ return err; -++ } -++ if (keys_cmp(c, key, &znode->zbranch[n].key)) -++ break; -++ zbr = &znode->zbranch[n]; -++ if (lnum == zbr->lnum && offs == zbr->offs) -++ return 1; /* Found it */ -++ } -++ return 0; -++} -++ -++/** -++ * ubifs_tnc_has_node - determine whether a node is in the TNC. -++ * @c: UBIFS file-system description object -++ * @key: node key -++ * @level: index node level (if it is an index node) -++ * @lnum: node LEB number -++ * @offs: node offset -++ * @is_idx: non-zero if the node is an index node -++ * -++ * This function returns %1 if the node is in the TNC, %0 if it is not, and a -++ * negative error code in case of failure. For index nodes, @key has to be the -++ * key of the first child. An index node is considered to be in the TNC only if -++ * the corresponding znode is clean or has not been loaded. -++ */ -++int ubifs_tnc_has_node(struct ubifs_info *c, union ubifs_key *key, int level, -++ int lnum, int offs, int is_idx) -++{ -++ int err; -++ -++ mutex_lock(&c->tnc_mutex); -++ if (is_idx) { -++ err = is_idx_node_in_tnc(c, key, level, lnum, offs); -++ if (err < 0) -++ goto out_unlock; -++ if (err == 1) -++ /* The index node was found but it was dirty */ -++ err = 0; -++ else if (err == 2) -++ /* The index node was found and it was clean */ -++ err = 1; -++ else -++ BUG_ON(err != 0); -++ } else -++ err = is_leaf_node_in_tnc(c, key, lnum, offs); -++ -++out_unlock: -++ mutex_unlock(&c->tnc_mutex); -++ return err; -++} -++ -++/** -++ * ubifs_dirty_idx_node - dirty an index node. -++ * @c: UBIFS file-system description object -++ * @key: index node key -++ * @level: index node level -++ * @lnum: index node LEB number -++ * @offs: index node offset -++ * -++ * This function loads and dirties an index node so that it can be garbage -++ * collected. The @key argument has to be the key of the first child. This -++ * function relies on the fact that 0:0 is never a valid LEB number and offset -++ * for a main-area node. Returns %0 on success and a negative error code on -++ * failure. -++ */ -++int ubifs_dirty_idx_node(struct ubifs_info *c, union ubifs_key *key, int level, -++ int lnum, int offs) -++{ -++ struct ubifs_znode *znode; -++ int err = 0; -++ -++ mutex_lock(&c->tnc_mutex); -++ znode = lookup_znode(c, key, level, lnum, offs); -++ if (!znode) -++ goto out_unlock; -++ if (IS_ERR(znode)) { -++ err = PTR_ERR(znode); -++ goto out_unlock; -++ } -++ znode = dirty_cow_bottom_up(c, znode); -++ if (IS_ERR(znode)) { -++ err = PTR_ERR(znode); -++ goto out_unlock; -++ } -++ -++out_unlock: -++ mutex_unlock(&c->tnc_mutex); -++ return err; -++} -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ -++/** -++ * dbg_walk_sub_tree - walk index subtree. -++ * @c: UBIFS file-system description object -++ * @znode: root znode of the subtree to walk -++ * @leaf_cb: called for each leaf node -++ * @znode_cb: called for each indexing node -++ * @priv: private date which is passed to callbacks -++ * -++ * This is a helper function which recursively walks the UBIFS index, reading -++ * each indexing node from the media if needed. Returns zero in case of success -++ * and a negative error code in case of failure. -++ */ -++static int dbg_walk_sub_tree(struct ubifs_info *c, struct ubifs_znode *znode, -++ dbg_leaf_callback leaf_cb, -++ dbg_znode_callback znode_cb, void *priv) -++{ -++ int n, err; -++ -++ cond_resched(); -++ -++ if (znode_cb) { -++ err = znode_cb(c, znode, priv); -++ if (err) -++ return err; -++ } -++ -++ if (znode->level == 0) { -++ if (!leaf_cb) -++ return 0; -++ -++ for (n = 0; n < znode->child_cnt; n++) { -++ struct ubifs_zbranch *zbr = &znode->zbranch[n]; -++ -++ err = leaf_cb(c, zbr, priv); -++ if (err) -++ return err; -++ } -++ } else -++ for (n = 0; n < znode->child_cnt; n++) { -++ struct ubifs_znode *zn; -++ -++ zn = get_znode(c, znode, n); -++ if (IS_ERR(zn)) -++ return PTR_ERR(zn); -++ err = dbg_walk_sub_tree(c, zn, leaf_cb, znode_cb, priv); -++ if (err) -++ return err; -++ } -++ -++ return 0; -++} -++ -++/** -++ * dbg_walk_index - walk the on-flash index. -++ * @c: UBIFS file-system description object -++ * @leaf_cb: called for each leaf node -++ * @znode_cb: called for each indexing node -++ * @priv: private date which is passed to callbacks -++ * -++ * This function walks the UBIFS index and calls the @leaf_cb for each leaf -++ * node and @znode_cb for each indexing node. Returns zero in case of success -++ * and a negative error code in case of failure. -++ * -++ * Because 'dbg_walk_sub_tree()' is recursive, it runs the risk of exceeding the -++ * stack space. -++ * -++ * It would be better if this function removed every znode it pulled to into -++ * the TNC, so that the behavior more closely matched the non-debugging -++ * behavior. -++ */ -++int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb, -++ dbg_znode_callback znode_cb, void *priv) -++{ -++ int err = 0; -++ -++ mutex_lock(&c->tnc_mutex); -++ if (!c->zroot.znode) { -++ c->zroot.znode = load_znode(c, &c->zroot, NULL, 0); -++ if (IS_ERR(c->zroot.znode)) { -++ err = PTR_ERR(c->zroot.znode); -++ c->zroot.znode = NULL; -++ goto out_unlock; -++ } -++ } -++ -++ err = dbg_walk_sub_tree(c, c->zroot.znode, leaf_cb, znode_cb, priv); -++ -++out_unlock: -++ mutex_unlock(&c->tnc_mutex); -++ return err; -++} -++ -++int dbg_read_leaf_nolock(struct ubifs_info *c, struct ubifs_zbranch *zbr, -++ void *node) -++{ -++ ubifs_assert(mutex_is_locked(&c->tnc_mutex)); -++ if (is_hash_key(c, &zbr->key)) -++ return tnc_read_node_nm(c, zbr, node); -++ return tnc_read_node(c, zbr, node); -++} -++ -++#endif /* CONFIG_UBIFS_FS_DEBUG */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/tnc_commit.c linux-2.6.24.7/fs/ubifs/tnc_commit.c -+--- linux-2.6.24.7.old/fs/ubifs/tnc_commit.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/tnc_commit.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1105 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Adrian Hunter -++ * Artem Bityutskiy (Битюцкий Ðртём) -++ */ -++ -++/* This file implements TNC functions for committing */ -++ -++#include "ubifs.h" -++ -++/** -++ * make_idx_node - make an index node for fill-the-gaps method of TNC commit. -++ * @c: UBIFS file-system description object -++ * @idx: buffer in which to place new index node -++ * @znode: znode from which to make new index node -++ * @lnum: LEB number where new index node will be written -++ * @offs: offset where new index node will be written -++ * @len: length of new index node -++ */ -++static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx, -++ struct ubifs_znode *znode, int lnum, int offs, int len) -++{ -++ struct ubifs_znode *zp; -++ int i, err; -++ -++ /* Make index node */ -++ idx->ch.node_type = UBIFS_IDX_NODE; -++ idx->child_cnt = cpu_to_le16(znode->child_cnt); -++ idx->level = cpu_to_le16(znode->level); -++ for (i = 0; i < znode->child_cnt; i++) { -++ struct ubifs_branch *br = ubifs_idx_branch(c, idx, i); -++ struct ubifs_zbranch *zbr = &znode->zbranch[i]; -++ -++ key_write_idx(c, &zbr->key, &br->key); -++ br->lnum = cpu_to_le32(zbr->lnum); -++ br->offs = cpu_to_le32(zbr->offs); -++ br->len = cpu_to_le32(zbr->len); -++ if (!zbr->lnum || !zbr->len) { -++ ubifs_err("bad ref in znode"); -++ dbg_dump_znode(c, znode); -++ if (zbr->znode) -++ dbg_dump_znode(c, zbr->znode); -++ } -++ } -++ ubifs_prepare_node(c, idx, len, 0); -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ znode->lnum = lnum; -++ znode->offs = offs; -++ znode->len = len; -++#endif -++ -++ err = insert_old_idx_znode(c, znode); -++ -++ /* Update the parent */ -++ zp = znode->parent; -++ if (zp) { -++ struct ubifs_zbranch *zbr; -++ -++ zbr = &zp->zbranch[znode->iip]; -++ zbr->lnum = lnum; -++ zbr->offs = offs; -++ zbr->len = len; -++ } else { -++ c->zroot.lnum = lnum; -++ c->zroot.offs = offs; -++ c->zroot.len = len; -++ } -++ c->calc_idx_sz += ALIGN(len, 8); -++ -++ atomic_long_dec(&c->dirty_zn_cnt); -++ -++ ubifs_assert(ubifs_zn_dirty(znode)); -++ ubifs_assert(test_bit(COW_ZNODE, &znode->flags)); -++ -++ __clear_bit(DIRTY_ZNODE, &znode->flags); -++ __clear_bit(COW_ZNODE, &znode->flags); -++ -++ return err; -++} -++ -++/** -++ * fill_gap - make index nodes in gaps in dirty index LEBs. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number that gap appears in -++ * @gap_start: offset of start of gap -++ * @gap_end: offset of end of gap -++ * @dirt: adds dirty space to this -++ * -++ * This function returns the number of index nodes written into the gap. -++ */ -++static int fill_gap(struct ubifs_info *c, int lnum, int gap_start, int gap_end, -++ int *dirt) -++{ -++ int len, gap_remains, gap_pos, written, pad_len; -++ -++ ubifs_assert((gap_start & 7) == 0); -++ ubifs_assert((gap_end & 7) == 0); -++ ubifs_assert(gap_end >= gap_start); -++ -++ gap_remains = gap_end - gap_start; -++ if (!gap_remains) -++ return 0; -++ gap_pos = gap_start; -++ written = 0; -++ while (c->enext) { -++ len = ubifs_idx_node_sz(c, c->enext->child_cnt); -++ if (len < gap_remains) { -++ struct ubifs_znode *znode = c->enext; -++ const int alen = ALIGN(len, 8); -++ int err; -++ -++ ubifs_assert(alen <= gap_remains); -++ err = make_idx_node(c, c->ileb_buf + gap_pos, znode, -++ lnum, gap_pos, len); -++ if (err) -++ return err; -++ gap_remains -= alen; -++ gap_pos += alen; -++ c->enext = znode->cnext; -++ if (c->enext == c->cnext) -++ c->enext = NULL; -++ written += 1; -++ } else -++ break; -++ } -++ if (gap_end == c->leb_size) { -++ c->ileb_len = ALIGN(gap_pos, c->min_io_size); -++ /* Pad to end of min_io_size */ -++ pad_len = c->ileb_len - gap_pos; -++ } else -++ /* Pad to end of gap */ -++ pad_len = gap_remains; -++ dbg_gc("LEB %d:%d to %d len %d nodes written %d wasted bytes %d", -++ lnum, gap_start, gap_end, gap_end - gap_start, written, pad_len); -++ ubifs_pad(c, c->ileb_buf + gap_pos, pad_len); -++ *dirt += pad_len; -++ return written; -++} -++ -++/** -++ * find_old_idx - find an index node obsoleted since the last commit start. -++ * @c: UBIFS file-system description object -++ * @lnum: LEB number of obsoleted index node -++ * @offs: offset of obsoleted index node -++ * -++ * Returns %1 if found and %0 otherwise. -++ */ -++static int find_old_idx(struct ubifs_info *c, int lnum, int offs) -++{ -++ struct ubifs_old_idx *o; -++ struct rb_node *p; -++ -++ p = c->old_idx.rb_node; -++ while (p) { -++ o = rb_entry(p, struct ubifs_old_idx, rb); -++ if (lnum < o->lnum) -++ p = p->rb_left; -++ else if (lnum > o->lnum) -++ p = p->rb_right; -++ else if (offs < o->offs) -++ p = p->rb_left; -++ else if (offs > o->offs) -++ p = p->rb_right; -++ else -++ return 1; -++ } -++ return 0; -++} -++ -++/** -++ * is_idx_node_in_use - determine if an index node can be overwritten. -++ * @c: UBIFS file-system description object -++ * @key: key of index node -++ * @level: index node level -++ * @lnum: LEB number of index node -++ * @offs: offset of index node -++ * -++ * If @key / @lnum / @offs identify an index node that was not part of the old -++ * index, then this function returns %0 (obsolete). Else if the index node was -++ * part of the old index but is now dirty %1 is returned, else if it is clean %2 -++ * is returned. A negative error code is returned on failure. -++ */ -++static int is_idx_node_in_use(struct ubifs_info *c, union ubifs_key *key, -++ int level, int lnum, int offs) -++{ -++ int ret; -++ -++ ret = is_idx_node_in_tnc(c, key, level, lnum, offs); -++ if (ret < 0) -++ return ret; /* Error code */ -++ if (ret == 0) -++ if (find_old_idx(c, lnum, offs)) -++ return 1; -++ return ret; -++} -++ -++/** -++ * layout_leb_in_gaps - layout index nodes using in-the-gaps method. -++ * @c: UBIFS file-system description object -++ * @p: return LEB number here -++ * -++ * This function lays out new index nodes for dirty znodes using in-the-gaps -++ * method of TNC commit. -++ * This function merely puts the next znode into the next gap, making no attempt -++ * to try to maximise the number of znodes that fit. -++ * This function returns the number of index nodes written into the gaps, or a -++ * negative error code on failure. -++ */ -++static int layout_leb_in_gaps(struct ubifs_info *c, int *p) -++{ -++ struct ubifs_scan_leb *sleb; -++ struct ubifs_scan_node *snod; -++ int lnum, dirt = 0, gap_start, gap_end, err, written, tot_written; -++ -++ tot_written = 0; -++ /* Get an index LEB with lots of obsolete index nodes */ -++ lnum = ubifs_find_dirty_idx_leb(c); -++ if (lnum < 0) -++ /* -++ * There also may be dirt in the index head that could be -++ * filled, however we do not check there at present. -++ */ -++ return lnum; /* Error code */ -++ *p = lnum; -++ dbg_gc("LEB %d", lnum); -++ /* -++ * Scan the index LEB. We use the generic scan for this even though -++ * it is more comprehensive and less efficient than is needed for this -++ * purpose. -++ */ -++ sleb = ubifs_scan(c, lnum, 0, c->ileb_buf); -++ c->ileb_len = 0; -++ if (IS_ERR(sleb)) -++ return PTR_ERR(sleb); -++ gap_start = 0; -++ list_for_each_entry(snod, &sleb->nodes, list) { -++ struct ubifs_idx_node *idx; -++ int in_use, level; -++ -++ ubifs_assert(snod->type == UBIFS_IDX_NODE); -++ idx = snod->node; -++ key_read(c, ubifs_idx_key(c, idx), &snod->key); -++ level = le16_to_cpu(idx->level); -++ /* Determine if the index node is in use (not obsolete) */ -++ in_use = is_idx_node_in_use(c, &snod->key, level, lnum, -++ snod->offs); -++ if (in_use < 0) { -++ ubifs_scan_destroy(sleb); -++ return in_use; /* Error code */ -++ } -++ if (in_use) { -++ if (in_use == 1) -++ dirt += ALIGN(snod->len, 8); -++ /* -++ * The obsolete index nodes form gaps that can be -++ * overwritten. This gap has ended because we have -++ * found an index node that is still in use -++ * i.e. not obsolete -++ */ -++ gap_end = snod->offs; -++ /* Try to fill gap */ -++ written = fill_gap(c, lnum, gap_start, gap_end, &dirt); -++ if (written < 0) { -++ ubifs_scan_destroy(sleb); -++ return written; /* Error code */ -++ } -++ tot_written += written; -++ gap_start = ALIGN(snod->offs + snod->len, 8); -++ } -++ } -++ ubifs_scan_destroy(sleb); -++ c->ileb_len = c->leb_size; -++ gap_end = c->leb_size; -++ /* Try to fill gap */ -++ written = fill_gap(c, lnum, gap_start, gap_end, &dirt); -++ if (written < 0) -++ return written; /* Error code */ -++ tot_written += written; -++ if (tot_written == 0) { -++ struct ubifs_lprops lp; -++ -++ dbg_gc("LEB %d wrote %d index nodes", lnum, tot_written); -++ err = ubifs_read_one_lp(c, lnum, &lp); -++ if (err) -++ return err; -++ if (lp.free == c->leb_size) { -++ /* -++ * We must have snatched this LEB from the idx_gc list -++ * so we need to correct the free and dirty space. -++ */ -++ err = ubifs_change_one_lp(c, lnum, -++ c->leb_size - c->ileb_len, -++ dirt, 0, 0, 0); -++ if (err) -++ return err; -++ } -++ return 0; -++ } -++ err = ubifs_change_one_lp(c, lnum, c->leb_size - c->ileb_len, dirt, -++ 0, 0, 0); -++ if (err) -++ return err; -++ err = ubi_leb_change(c->ubi, lnum, c->ileb_buf, c->ileb_len, -++ UBI_SHORTTERM); -++ if (err) { -++ ubifs_err("ubi_leb_change failed, error %d", err); -++ return err; -++ } -++ dbg_gc("LEB %d wrote %d index nodes", lnum, tot_written); -++ return tot_written; -++} -++ -++/** -++ * get_leb_cnt - calculate the number of empty LEBs needed to commit. -++ * @c: UBIFS file-system description object -++ * @cnt: number of znodes to commit -++ * -++ * This function returns the number of empty LEBs needed to commit @cnt znodes -++ * to the current index head. The number is not exact and may be more than -++ * needed. -++ */ -++static int get_leb_cnt(struct ubifs_info *c, int cnt) -++{ -++ int d; -++ -++ /* Assume maximum index node size (i.e. overestimate space needed) */ -++ cnt -= (c->leb_size - c->ihead_offs) / c->max_idx_node_sz; -++ if (cnt < 0) -++ cnt = 0; -++ d = c->leb_size / c->max_idx_node_sz; -++ return DIV_ROUND_UP(cnt, d); -++} -++ -++/** -++ * layout_in_gaps - in-the-gaps method of committing TNC. -++ * @c: UBIFS file-system description object -++ * @cnt: number of dirty znodes to commit. -++ * -++ * This function lays out new index nodes for dirty znodes using in-the-gaps -++ * method of TNC commit. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int layout_in_gaps(struct ubifs_info *c, int cnt) -++{ -++ int err, leb_needed_cnt, written, *p; -++ -++ dbg_gc("%d znodes to write", cnt); -++ -++ c->gap_lebs = kmalloc(sizeof(int) * (c->lst.idx_lebs + 1), GFP_NOFS); -++ if (!c->gap_lebs) -++ return -ENOMEM; -++ -++ p = c->gap_lebs; -++ do { -++ ubifs_assert(p < c->gap_lebs + sizeof(int) * c->lst.idx_lebs); -++ written = layout_leb_in_gaps(c, p); -++ if (written < 0) { -++ err = written; -++ if (err == -ENOSPC) { -++ if (!dbg_force_in_the_gaps_enabled) { -++ /* -++ * Do not print scary warnings if the -++ * debugging option which forces -++ * in-the-gaps is enabled. -++ */ -++ ubifs_err("out of space"); -++ spin_lock(&c->space_lock); -++ dbg_dump_budg(c); -++ spin_unlock(&c->space_lock); -++ dbg_dump_lprops(c); -++ } -++ /* Try to commit anyway */ -++ err = 0; -++ break; -++ } -++ kfree(c->gap_lebs); -++ c->gap_lebs = NULL; -++ return err; -++ } -++ p++; -++ cnt -= written; -++ leb_needed_cnt = get_leb_cnt(c, cnt); -++ dbg_gc("%d znodes remaining, need %d LEBs, have %d", cnt, -++ leb_needed_cnt, c->ileb_cnt); -++ } while (leb_needed_cnt > c->ileb_cnt); -++ -++ *p = -1; -++ return 0; -++} -++ -++/** -++ * layout_in_empty_space - layout index nodes in empty space. -++ * @c: UBIFS file-system description object -++ * -++ * This function lays out new index nodes for dirty znodes using empty LEBs. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int layout_in_empty_space(struct ubifs_info *c) -++{ -++ struct ubifs_znode *znode, *cnext, *zp; -++ int lnum, offs, len, next_len, buf_len, buf_offs, used, avail; -++ int wlen, blen, err; -++ -++ cnext = c->enext; -++ if (!cnext) -++ return 0; -++ -++ lnum = c->ihead_lnum; -++ buf_offs = c->ihead_offs; -++ -++ buf_len = ubifs_idx_node_sz(c, c->fanout); -++ buf_len = ALIGN(buf_len, c->min_io_size); -++ used = 0; -++ avail = buf_len; -++ -++ /* Ensure there is enough room for first write */ -++ next_len = ubifs_idx_node_sz(c, cnext->child_cnt); -++ if (buf_offs + next_len > c->leb_size) -++ lnum = -1; -++ -++ while (1) { -++ znode = cnext; -++ -++ len = ubifs_idx_node_sz(c, znode->child_cnt); -++ -++ /* Determine the index node position */ -++ if (lnum == -1) { -++ if (c->ileb_nxt >= c->ileb_cnt) { -++ ubifs_err("out of space"); -++ return -ENOSPC; -++ } -++ lnum = c->ilebs[c->ileb_nxt++]; -++ buf_offs = 0; -++ used = 0; -++ avail = buf_len; -++ } -++ -++ offs = buf_offs + used; -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ znode->lnum = lnum; -++ znode->offs = offs; -++ znode->len = len; -++#endif -++ -++ /* Update the parent */ -++ zp = znode->parent; -++ if (zp) { -++ struct ubifs_zbranch *zbr; -++ int i; -++ -++ i = znode->iip; -++ zbr = &zp->zbranch[i]; -++ zbr->lnum = lnum; -++ zbr->offs = offs; -++ zbr->len = len; -++ } else { -++ c->zroot.lnum = lnum; -++ c->zroot.offs = offs; -++ c->zroot.len = len; -++ } -++ c->calc_idx_sz += ALIGN(len, 8); -++ -++ /* -++ * Once lprops is updated, we can decrease the dirty znode count -++ * but it is easier to just do it here. -++ */ -++ atomic_long_dec(&c->dirty_zn_cnt); -++ -++ /* -++ * Calculate the next index node length to see if there is -++ * enough room for it -++ */ -++ cnext = znode->cnext; -++ if (cnext == c->cnext) -++ next_len = 0; -++ else -++ next_len = ubifs_idx_node_sz(c, cnext->child_cnt); -++ -++ if (c->min_io_size == 1) { -++ buf_offs += ALIGN(len, 8); -++ if (next_len) { -++ if (buf_offs + next_len <= c->leb_size) -++ continue; -++ err = ubifs_update_one_lp(c, lnum, 0, -++ c->leb_size - buf_offs, 0, 0); -++ if (err) -++ return err; -++ lnum = -1; -++ continue; -++ } -++ err = ubifs_update_one_lp(c, lnum, -++ c->leb_size - buf_offs, 0, 0, 0); -++ if (err) -++ return err; -++ break; -++ } -++ -++ /* Update buffer positions */ -++ wlen = used + len; -++ used += ALIGN(len, 8); -++ avail -= ALIGN(len, 8); -++ -++ if (next_len != 0 && -++ buf_offs + used + next_len <= c->leb_size && -++ avail > 0) -++ continue; -++ -++ if (avail <= 0 && next_len && -++ buf_offs + used + next_len <= c->leb_size) -++ blen = buf_len; -++ else -++ blen = ALIGN(wlen, c->min_io_size); -++ -++ /* The buffer is full or there are no more znodes to do */ -++ buf_offs += blen; -++ if (next_len) { -++ if (buf_offs + next_len > c->leb_size) { -++ err = ubifs_update_one_lp(c, lnum, -++ c->leb_size - buf_offs, blen - used, -++ 0, 0); -++ if (err) -++ return err; -++ lnum = -1; -++ } -++ used -= blen; -++ if (used < 0) -++ used = 0; -++ avail = buf_len - used; -++ continue; -++ } -++ err = ubifs_update_one_lp(c, lnum, c->leb_size - buf_offs, -++ blen - used, 0, 0); -++ if (err) -++ return err; -++ break; -++ } -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ c->new_ihead_lnum = lnum; -++ c->new_ihead_offs = buf_offs; -++#endif -++ -++ return 0; -++} -++ -++/** -++ * layout_commit - determine positions of index nodes to commit. -++ * @c: UBIFS file-system description object -++ * @no_space: indicates that insufficient empty LEBs were allocated -++ * @cnt: number of znodes to commit -++ * -++ * Calculate and update the positions of index nodes to commit. If there were -++ * an insufficient number of empty LEBs allocated, then index nodes are placed -++ * into the gaps created by obsolete index nodes in non-empty index LEBs. For -++ * this purpose, an obsolete index node is one that was not in the index as at -++ * the end of the last commit. To write "in-the-gaps" requires that those index -++ * LEBs are updated atomically in-place. -++ */ -++static int layout_commit(struct ubifs_info *c, int no_space, int cnt) -++{ -++ int err; -++ -++ if (no_space) { -++ err = layout_in_gaps(c, cnt); -++ if (err) -++ return err; -++ } -++ err = layout_in_empty_space(c); -++ return err; -++} -++ -++/** -++ * find_first_dirty - find first dirty znode. -++ * @znode: znode to begin searching from -++ */ -++static struct ubifs_znode *find_first_dirty(struct ubifs_znode *znode) -++{ -++ int i, cont; -++ -++ if (!znode) -++ return NULL; -++ -++ while (1) { -++ if (znode->level == 0) { -++ if (ubifs_zn_dirty(znode)) -++ return znode; -++ return NULL; -++ } -++ cont = 0; -++ for (i = 0; i < znode->child_cnt; i++) { -++ struct ubifs_zbranch *zbr = &znode->zbranch[i]; -++ -++ if (zbr->znode && ubifs_zn_dirty(zbr->znode)) { -++ znode = zbr->znode; -++ cont = 1; -++ break; -++ } -++ } -++ if (!cont) { -++ if (ubifs_zn_dirty(znode)) -++ return znode; -++ return NULL; -++ } -++ } -++} -++ -++/** -++ * find_next_dirty - find next dirty znode. -++ * @znode: znode to begin searching from -++ */ -++static struct ubifs_znode *find_next_dirty(struct ubifs_znode *znode) -++{ -++ int n = znode->iip + 1; -++ -++ znode = znode->parent; -++ if (!znode) -++ return NULL; -++ for (; n < znode->child_cnt; n++) { -++ struct ubifs_zbranch *zbr = &znode->zbranch[n]; -++ -++ if (zbr->znode && ubifs_zn_dirty(zbr->znode)) -++ return find_first_dirty(zbr->znode); -++ } -++ return znode; -++} -++ -++/** -++ * get_znodes_to_commit - create list of dirty znodes to commit. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns the number of znodes to commit. -++ */ -++static int get_znodes_to_commit(struct ubifs_info *c) -++{ -++ struct ubifs_znode *znode, *cnext; -++ int cnt = 0; -++ -++ c->cnext = find_first_dirty(c->zroot.znode); -++ znode = c->enext = c->cnext; -++ if (!znode) { -++ dbg_cmt("no znodes to commit"); -++ return 0; -++ } -++ cnt += 1; -++ while (1) { -++ ubifs_assert(!test_bit(COW_ZNODE, &znode->flags)); -++ __set_bit(COW_ZNODE, &znode->flags); -++ znode->alt = 0; -++ cnext = find_next_dirty(znode); -++ if (!cnext) { -++ znode->cnext = c->cnext; -++ break; -++ } -++ znode->cnext = cnext; -++ znode = cnext; -++ cnt += 1; -++ } -++ dbg_cmt("committing %d znodes", cnt); -++ ubifs_assert(cnt == atomic_long_read(&c->dirty_zn_cnt)); -++ return cnt; -++} -++ -++/** -++ * alloc_idx_lebs - allocate empty LEBs to be used to commit. -++ * @c: UBIFS file-system description object -++ * @cnt: number of znodes to commit -++ * -++ * This function returns %-ENOSPC if it cannot allocate a sufficient number of -++ * empty LEBs. %0 is returned on success, otherwise a negative error code -++ * is returned. -++ */ -++static int alloc_idx_lebs(struct ubifs_info *c, int cnt) -++{ -++ int i, leb_cnt, lnum; -++ -++ c->ileb_cnt = 0; -++ c->ileb_nxt = 0; -++ leb_cnt = get_leb_cnt(c, cnt); -++ dbg_cmt("need about %d empty LEBS for TNC commit", leb_cnt); -++ if (!leb_cnt) -++ return 0; -++ c->ilebs = kmalloc(leb_cnt * sizeof(int), GFP_NOFS); -++ if (!c->ilebs) -++ return -ENOMEM; -++ for (i = 0; i < leb_cnt; i++) { -++ lnum = ubifs_find_free_leb_for_idx(c); -++ if (lnum < 0) -++ return lnum; -++ c->ilebs[c->ileb_cnt++] = lnum; -++ dbg_cmt("LEB %d", lnum); -++ } -++ if (dbg_force_in_the_gaps()) -++ return -ENOSPC; -++ return 0; -++} -++ -++/** -++ * free_unused_idx_lebs - free unused LEBs that were allocated for the commit. -++ * @c: UBIFS file-system description object -++ * -++ * It is possible that we allocate more empty LEBs for the commit than we need. -++ * This functions frees the surplus. -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int free_unused_idx_lebs(struct ubifs_info *c) -++{ -++ int i, err = 0, lnum, er; -++ -++ for (i = c->ileb_nxt; i < c->ileb_cnt; i++) { -++ lnum = c->ilebs[i]; -++ dbg_cmt("LEB %d", lnum); -++ er = ubifs_change_one_lp(c, lnum, -1, -1, 0, -++ LPROPS_INDEX | LPROPS_TAKEN, 0); -++ if (!err) -++ err = er; -++ } -++ return err; -++} -++ -++/** -++ * free_idx_lebs - free unused LEBs after commit end. -++ * @c: UBIFS file-system description object -++ * -++ * This function returns %0 on success and a negative error code on failure. -++ */ -++static int free_idx_lebs(struct ubifs_info *c) -++{ -++ int err; -++ -++ err = free_unused_idx_lebs(c); -++ kfree(c->ilebs); -++ c->ilebs = NULL; -++ return err; -++} -++ -++/** -++ * ubifs_tnc_start_commit - start TNC commit. -++ * @c: UBIFS file-system description object -++ * @zroot: new index root position is returned here -++ * -++ * This function prepares the list of indexing nodes to commit and lays out -++ * their positions on flash. If there is not enough free space it uses the -++ * in-gap commit method. Returns zero in case of success and a negative error -++ * code in case of failure. -++ */ -++int ubifs_tnc_start_commit(struct ubifs_info *c, struct ubifs_zbranch *zroot) -++{ -++ int err = 0, cnt; -++ -++ mutex_lock(&c->tnc_mutex); -++ err = dbg_check_tnc(c, 1); -++ if (err) -++ goto out; -++ cnt = get_znodes_to_commit(c); -++ if (cnt != 0) { -++ int no_space = 0; -++ -++ err = alloc_idx_lebs(c, cnt); -++ if (err == -ENOSPC) -++ no_space = 1; -++ else if (err) -++ goto out_free; -++ err = layout_commit(c, no_space, cnt); -++ if (err) -++ goto out_free; -++ ubifs_assert(atomic_long_read(&c->dirty_zn_cnt) == 0); -++ err = free_unused_idx_lebs(c); -++ if (err) -++ goto out; -++ } -++ destroy_old_idx(c); -++ memcpy(zroot, &c->zroot, sizeof(struct ubifs_zbranch)); -++ -++ err = ubifs_save_dirty_idx_lnums(c); -++ if (err) -++ goto out; -++ -++ spin_lock(&c->space_lock); -++ /* -++ * Although we have not finished committing yet, update size of the -++ * committed index ('c->old_idx_sz') and zero out the index growth -++ * budget. It is OK to do this now, because we've reserved all the -++ * space which is needed to commit the index, and it is save for the -++ * budgeting subsystem to assume the index is already committed, -++ * even though it is not. -++ */ -++ c->old_idx_sz = c->calc_idx_sz; -++ c->budg_uncommitted_idx = 0; -++ spin_unlock(&c->space_lock); -++ mutex_unlock(&c->tnc_mutex); -++ -++ dbg_cmt("number of index LEBs %d", c->lst.idx_lebs); -++ dbg_cmt("size of index %llu", c->calc_idx_sz); -++ return err; -++ -++out_free: -++ free_idx_lebs(c); -++out: -++ mutex_unlock(&c->tnc_mutex); -++ return err; -++} -++ -++/** -++ * write_index - write index nodes. -++ * @c: UBIFS file-system description object -++ * -++ * This function writes the index nodes whose positions were laid out in the -++ * layout_in_empty_space function. -++ */ -++static int write_index(struct ubifs_info *c) -++{ -++ struct ubifs_idx_node *idx; -++ struct ubifs_znode *znode, *cnext; -++ int i, lnum, offs, len, next_len, buf_len, buf_offs, used; -++ int avail, wlen, err, lnum_pos = 0; -++ -++ cnext = c->enext; -++ if (!cnext) -++ return 0; -++ -++ /* -++ * Always write index nodes to the index head so that index nodes and -++ * other types of nodes are never mixed in the same erase block. -++ */ -++ lnum = c->ihead_lnum; -++ buf_offs = c->ihead_offs; -++ -++ /* Allocate commit buffer */ -++ buf_len = ALIGN(c->max_idx_node_sz, c->min_io_size); -++ used = 0; -++ avail = buf_len; -++ -++ /* Ensure there is enough room for first write */ -++ next_len = ubifs_idx_node_sz(c, cnext->child_cnt); -++ if (buf_offs + next_len > c->leb_size) { -++ err = ubifs_update_one_lp(c, lnum, -1, -1, 0, LPROPS_TAKEN); -++ if (err) -++ return err; -++ lnum = -1; -++ } -++ -++ while (1) { -++ cond_resched(); -++ -++ znode = cnext; -++ idx = c->cbuf + used; -++ -++ /* Make index node */ -++ idx->ch.node_type = UBIFS_IDX_NODE; -++ idx->child_cnt = cpu_to_le16(znode->child_cnt); -++ idx->level = cpu_to_le16(znode->level); -++ for (i = 0; i < znode->child_cnt; i++) { -++ struct ubifs_branch *br = ubifs_idx_branch(c, idx, i); -++ struct ubifs_zbranch *zbr = &znode->zbranch[i]; -++ -++ key_write_idx(c, &zbr->key, &br->key); -++ br->lnum = cpu_to_le32(zbr->lnum); -++ br->offs = cpu_to_le32(zbr->offs); -++ br->len = cpu_to_le32(zbr->len); -++ if (!zbr->lnum || !zbr->len) { -++ ubifs_err("bad ref in znode"); -++ dbg_dump_znode(c, znode); -++ if (zbr->znode) -++ dbg_dump_znode(c, zbr->znode); -++ } -++ } -++ len = ubifs_idx_node_sz(c, znode->child_cnt); -++ ubifs_prepare_node(c, idx, len, 0); -++ -++ /* Determine the index node position */ -++ if (lnum == -1) { -++ lnum = c->ilebs[lnum_pos++]; -++ buf_offs = 0; -++ used = 0; -++ avail = buf_len; -++ } -++ offs = buf_offs + used; -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ if (lnum != znode->lnum || offs != znode->offs || -++ len != znode->len) { -++ ubifs_err("inconsistent znode posn"); -++ return -EINVAL; -++ } -++#endif -++ -++ /* Grab some stuff from znode while we still can */ -++ cnext = znode->cnext; -++ -++ ubifs_assert(ubifs_zn_dirty(znode)); -++ ubifs_assert(test_bit(COW_ZNODE, &znode->flags)); -++ -++ /* -++ * It is important that other threads should see %DIRTY_ZNODE -++ * flag cleared before %COW_ZNODE. Specifically, it matters in -++ * the 'dirty_cow_znode()' function. This is the reason for the -++ * first barrier. Also, we want the bit changes to be seen to -++ * other threads ASAP, to avoid unnecesarry copying, which is -++ * the reason for the second barrier. -++ */ -++ clear_bit(DIRTY_ZNODE, &znode->flags); -++ smp_mb__before_clear_bit(); -++ clear_bit(COW_ZNODE, &znode->flags); -++ smp_mb__after_clear_bit(); -++ -++ /* Do not access znode from this point on */ -++ -++ /* Update buffer positions */ -++ wlen = used + len; -++ used += ALIGN(len, 8); -++ avail -= ALIGN(len, 8); -++ -++ /* -++ * Calculate the next index node length to see if there is -++ * enough room for it -++ */ -++ if (cnext == c->cnext) -++ next_len = 0; -++ else -++ next_len = ubifs_idx_node_sz(c, cnext->child_cnt); -++ -++ if (c->min_io_size == 1) { -++ /* -++ * Write the prepared index node immediately if there is -++ * no minimum IO size -++ */ -++ err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs, -++ wlen, UBI_SHORTTERM); -++ if (err) -++ return err; -++ buf_offs += ALIGN(wlen, 8); -++ if (next_len) { -++ used = 0; -++ avail = buf_len; -++ if (buf_offs + next_len > c->leb_size) { -++ err = ubifs_update_one_lp(c, lnum, -1, -++ -1, 0, -++ LPROPS_TAKEN); -++ if (err) -++ return err; -++ lnum = -1; -++ } -++ continue; -++ } -++ } else { -++ int blen, nxt_offs = buf_offs + used + next_len; -++ -++ if (next_len && nxt_offs <= c->leb_size) { -++ if (avail > 0) -++ continue; -++ else -++ blen = buf_len; -++ } else { -++ wlen = ALIGN(wlen, 8); -++ blen = ALIGN(wlen, c->min_io_size); -++ ubifs_pad(c, c->cbuf + wlen, blen - wlen); -++ } -++ /* -++ * The buffer is full or there are no more znodes -++ * to do -++ */ -++ err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs, -++ blen, UBI_SHORTTERM); -++ if (err) -++ return err; -++ buf_offs += blen; -++ if (next_len) { -++ if (nxt_offs > c->leb_size) { -++ err = ubifs_update_one_lp(c, lnum, -1, -++ -1, 0, -++ LPROPS_TAKEN); -++ if (err) -++ return err; -++ lnum = -1; -++ } -++ used -= blen; -++ if (used < 0) -++ used = 0; -++ avail = buf_len - used; -++ memmove(c->cbuf, c->cbuf + blen, used); -++ continue; -++ } -++ } -++ break; -++ } -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ if (lnum != c->new_ihead_lnum || buf_offs != c->new_ihead_offs) { -++ ubifs_err("inconsistent ihead"); -++ return -EINVAL; -++ } -++#endif -++ -++ c->ihead_lnum = lnum; -++ c->ihead_offs = buf_offs; -++ -++ return 0; -++} -++ -++/** -++ * free_obsolete_znodes - free obsolete znodes. -++ * @c: UBIFS file-system description object -++ * -++ * At the end of commit end, obsolete znodes are freed. -++ */ -++static void free_obsolete_znodes(struct ubifs_info *c) -++{ -++ struct ubifs_znode *znode, *cnext; -++ -++ cnext = c->cnext; -++ do { -++ znode = cnext; -++ cnext = znode->cnext; -++ if (test_bit(OBSOLETE_ZNODE, &znode->flags)) -++ kfree(znode); -++ else { -++ znode->cnext = NULL; -++ atomic_long_inc(&c->clean_zn_cnt); -++ atomic_long_inc(&ubifs_clean_zn_cnt); -++ } -++ } while (cnext != c->cnext); -++} -++ -++/** -++ * return_gap_lebs - return LEBs used by the in-gap commit method. -++ * @c: UBIFS file-system description object -++ * -++ * This function clears the "taken" flag for the LEBs which were used by the -++ * "commit in-the-gaps" method. -++ */ -++static int return_gap_lebs(struct ubifs_info *c) -++{ -++ int *p, err; -++ -++ if (!c->gap_lebs) -++ return 0; -++ -++ dbg_cmt(""); -++ for (p = c->gap_lebs; *p != -1; p++) { -++ err = ubifs_change_one_lp(c, *p, -1, -1, 0, LPROPS_TAKEN, 0); -++ if (err) -++ return err; -++ } -++ -++ kfree(c->gap_lebs); -++ c->gap_lebs = NULL; -++ return 0; -++} -++ -++/** -++ * ubifs_tnc_end_commit - update the TNC for commit end. -++ * @c: UBIFS file-system description object -++ * -++ * Write the dirty znodes. -++ */ -++int ubifs_tnc_end_commit(struct ubifs_info *c) -++{ -++ int err; -++ -++ if (!c->cnext) -++ return 0; -++ -++ err = return_gap_lebs(c); -++ if (err) -++ return err; -++ -++ err = write_index(c); -++ if (err) -++ return err; -++ -++ mutex_lock(&c->tnc_mutex); -++ -++ dbg_cmt("TNC height is %d", c->zroot.znode->level + 1); -++ -++ free_obsolete_znodes(c); -++ -++ c->cnext = NULL; -++ kfree(c->ilebs); -++ c->ilebs = NULL; -++ -++ mutex_unlock(&c->tnc_mutex); -++ -++ return 0; -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/tnc_misc.c linux-2.6.24.7/fs/ubifs/tnc_misc.c -+--- linux-2.6.24.7.old/fs/ubifs/tnc_misc.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/tnc_misc.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,259 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Adrian Hunter -++ * Artem Bityutskiy (Битюцкий Ðртём) -++ */ -++ -++/* -++ * This file contains miscelanious TNC-related functions shared betweend -++ * different files. This file does not form any logically separate TNC -++ * sub-system. The file was created because there is a lot of TNC code and -++ * putting it all in one file would make that file too big and unreadable. -++ * Nonetheless, this contains more or less "generic" code which may be used for -++ * more then one specific task. -++ */ -++ -++#include "ubifs.h" -++ -++/** -++ * ubifs_tnc_levelorder_next - next TNC tree element in levelorder traversal. -++ * @zr: root of the subtree to traverse -++ * @znode: previous znode -++ * -++ * This function implements levelorder TNC traversal. The LNC is ignored. -++ * Returns the next element or %NULL if @znode is already the last one. -++ */ -++struct ubifs_znode *ubifs_tnc_levelorder_next(struct ubifs_znode *zr, -++ struct ubifs_znode *znode) -++{ -++ int level, iip, level_search = 0; -++ struct ubifs_znode *zn; -++ -++ ubifs_assert(zr); -++ -++ if (unlikely(!znode)) -++ return zr; -++ -++ if (unlikely(znode == zr)) { -++ if (znode->level == 0) -++ return NULL; -++ return ubifs_tnc_find_child(zr, 0); -++ } -++ -++ level = znode->level; -++ -++ iip = znode->iip; -++ while (1) { -++ ubifs_assert(znode->level <= zr->level); -++ -++ /* -++ * First walk up until there is a znode with next branch to -++ * look at. -++ */ -++ while (znode->parent != zr && iip >= znode->parent->child_cnt) { -++ znode = znode->parent; -++ iip = znode->iip; -++ } -++ -++ if (unlikely(znode->parent == zr && -++ iip >= znode->parent->child_cnt)) { -++ /* This level is done, switch to the lower one */ -++ level -= 1; -++ if (level_search || level < 0) -++ /* -++ * We were already looking for znode at lower -++ * level ('level_search'). As we are here -++ * again, it just does not exist. Or all levels -++ * were finished ('level < 0'). -++ */ -++ return NULL; -++ -++ level_search = 1; -++ iip = -1; -++ znode = ubifs_tnc_find_child(zr, 0); -++ ubifs_assert(znode); -++ } -++ -++ /* Switch to the next index */ -++ zn = ubifs_tnc_find_child(znode->parent, iip + 1); -++ if (!zn) { -++ /* No more children to look at, we have walk up */ -++ iip = znode->parent->child_cnt; -++ continue; -++ } -++ -++ /* Walk back down to the level we came from ('level') */ -++ while (zn->level != level) { -++ znode = zn; -++ zn = ubifs_tnc_find_child(zn, 0); -++ if (!zn) { -++ /* -++ * This path is not too deep so it does not -++ * reach 'level'. Try next path. -++ */ -++ iip = znode->iip; -++ break; -++ } -++ } -++ -++ if (zn) { -++ ubifs_assert(zn->level >= 0); -++ return zn; -++ } -++ } -++} -++ -++/** -++ * ubifs_search_zbranch - search znode branch. -++ * @c: UBIFS file-system description object -++ * @znode: znode to search in -++ * @key: key to search for -++ * @n: znode branch slot number is returned here -++ * -++ * This is a helper function which search branch with key @key in @znode using -++ * binary search. The result of the search may be: -++ * o exact match, then %1 is returned, and the slot number of the branch is -++ * stored in @n; -++ * o no exact match, then %0 is returned and the slot number of the left -++ * closest branch is returned in @n; the slot if all keys in this znode are -++ * greater than @key, then %-1 is returned in @n. -++ */ -++int ubifs_search_zbranch(const struct ubifs_info *c, -++ const struct ubifs_znode *znode, -++ const union ubifs_key *key, int *n) -++{ -++ int beg = 0, end = znode->child_cnt, uninitialized_var(mid); -++ int uninitialized_var(cmp); -++ const struct ubifs_zbranch *zbr = &znode->zbranch[0]; -++ -++ ubifs_assert(end > beg); -++ -++ while (end > beg) { -++ mid = (beg + end) >> 1; -++ cmp = keys_cmp(c, key, &zbr[mid].key); -++ if (cmp > 0) -++ beg = mid + 1; -++ else if (cmp < 0) -++ end = mid; -++ else { -++ *n = mid; -++ return 1; -++ } -++ } -++ -++ *n = end - 1; -++ -++ /* The insert point is after *n */ -++ ubifs_assert(*n >= -1 && *n < znode->child_cnt); -++ if (*n == -1) -++ ubifs_assert(keys_cmp(c, key, &zbr[0].key) < 0); -++ else -++ ubifs_assert(keys_cmp(c, key, &zbr[*n].key) > 0); -++ if (*n + 1 < znode->child_cnt) -++ ubifs_assert(keys_cmp(c, key, &zbr[*n + 1].key) < 0); -++ -++ return 0; -++} -++ -++/** -++ * ubifs_tnc_postorder_first - find first znode to do postorder tree traversal. -++ * @znode: znode to start at (root of the sub-tree to traverse) -++ * -++ * Find the lowest leftmost znode in a subtree of the TNC tree. The LNC is -++ * ignored. -++ */ -++struct ubifs_znode *ubifs_tnc_postorder_first(struct ubifs_znode *znode) -++{ -++ if (unlikely(!znode)) -++ return NULL; -++ -++ while (znode->level > 0) { -++ struct ubifs_znode *child; -++ -++ child = ubifs_tnc_find_child(znode, 0); -++ if (!child) -++ return znode; -++ znode = child; -++ } -++ -++ return znode; -++} -++ -++/** -++ * ubifs_tnc_postorder_next - next TNC tree element in postorder traversal. -++ * @znode: previous znode -++ * -++ * This function implements postorder TNC traversal. The LNC is ignored. -++ * Returns the next element or %NULL if @znode is already the last one. -++ */ -++struct ubifs_znode *ubifs_tnc_postorder_next(struct ubifs_znode *znode) -++{ -++ struct ubifs_znode *zn; -++ -++ ubifs_assert(znode); -++ if (unlikely(!znode->parent)) -++ return NULL; -++ -++ /* Switch to the next index in the parent */ -++ zn = ubifs_tnc_find_child(znode->parent, znode->iip + 1); -++ if (!zn) -++ /* This is in fact the last child, return parent */ -++ return znode->parent; -++ -++ /* Go to the first znode in this new subtree */ -++ return ubifs_tnc_postorder_first(zn); -++} -++ -++/** -++ * ubifs_destroy_tnc_subtree - destroy all znodes connected to a subtree. -++ * @znode: znode defining subtree to destroy -++ * -++ * This function destroys subtree of the TNC tree. Returns number of clean -++ * znodes in the subtree. -++ */ -++long ubifs_destroy_tnc_subtree(struct ubifs_znode *znode) -++{ -++ struct ubifs_znode *zn = ubifs_tnc_postorder_first(znode); -++ long clean_freed = 0; -++ int n; -++ -++ ubifs_assert(zn); -++ while (1) { -++ for (n = 0; n < zn->child_cnt; n++) { -++ if (!zn->zbranch[n].znode) -++ continue; -++ -++ if (zn->level > 0 && -++ !ubifs_zn_dirty(zn->zbranch[n].znode)) -++ clean_freed += 1; -++ -++ cond_resched(); -++ kfree(zn->zbranch[n].znode); -++ } -++ -++ if (zn == znode) { -++ if (!ubifs_zn_dirty(zn)) -++ clean_freed += 1; -++ kfree(zn); -++ return clean_freed; -++ } -++ -++ zn = ubifs_tnc_postorder_next(zn); -++ } -++} -+diff -urN linux-2.6.24.7.old/fs/ubifs/ubifs-media.h linux-2.6.24.7/fs/ubifs/ubifs-media.h -+--- linux-2.6.24.7.old/fs/ubifs/ubifs-media.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/ubifs-media.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,731 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* -++ * This file describes UBIFS on-flash format and contains definitions of all the -++ * relevant data structures and constants. -++ * -++ * All UBIFS on-flash objects are stored in the form of nodes. All nodes start -++ * with the UBIFS node magic number and have the same common header. Nodes -++ * always sit at 8-byte aligned positions on the media and node header sizes are -++ * also 8-byte aligned (except for the indexing node and the padding node). -++ */ -++ -++#ifndef __UBIFS_MEDIA_H__ -++#define __UBIFS_MEDIA_H__ -++ -++/* UBIFS node magic number (must not have the padding byte first or last) */ -++#define UBIFS_NODE_MAGIC 0x06101831 -++ -++/* UBIFS on-flash format version */ -++#define UBIFS_FORMAT_VERSION 3 -++ -++/* Minimum logical eraseblock size in bytes */ -++#define UBIFS_MIN_LEB_SZ (15*1024) -++ -++/* Initial CRC32 value used when calculating CRC checksums */ -++#define UBIFS_CRC32_INIT 0xFFFFFFFFU -++ -++/* -++ * UBIFS does not try to compress data if its length is less than the below -++ * constant. -++ */ -++#define UBIFS_MIN_COMPR_LEN 128 -++ -++/* Root inode number */ -++#define UBIFS_ROOT_INO 1 -++ -++/* Lowest inode number used for regular inodes (not UBIFS-only internal ones) */ -++#define UBIFS_FIRST_INO 64 -++ -++/* -++ * Maximum file name and extended attribute length (must be a multiple of 8, -++ * minus 1). -++ */ -++#define UBIFS_MAX_NLEN 255 -++ -++/* Maximum number of data journal heads */ -++#define UBIFS_MAX_JHEADS 1 -++ -++/* -++ * Size of UBIFS data block. Note, UBIFS is not a block oriented file-system, -++ * which means that it does not treat the underlying media as consisting of -++ * blocks like in case of hard drives. Do not be confused. UBIFS block is just -++ * the maximum amount of data which one data node can have or which can be -++ * attached to an inode node. -++ */ -++#define UBIFS_BLOCK_SIZE 4096 -++#define UBIFS_BLOCK_SHIFT 12 -++#define UBIFS_BLOCK_MASK 0x00000FFF -++ -++/* UBIFS padding byte pattern (must not be first or last byte of node magic) */ -++#define UBIFS_PADDING_BYTE 0xCE -++ -++/* Maximum possible key length */ -++#define UBIFS_MAX_KEY_LEN 16 -++ -++/* Key length ("simple" format) */ -++#define UBIFS_SK_LEN 8 -++ -++/* Minimum index tree fanout */ -++#define UBIFS_MIN_FANOUT 2 -++ -++/* Maximum number of levels in UBIFS indexing B-tree */ -++#define UBIFS_MAX_LEVELS 512 -++ -++/* Maximum amount of data attached to an inode in bytes */ -++#define UBIFS_MAX_INO_DATA UBIFS_BLOCK_SIZE -++ -++/* LEB Properties Tree fanout (must be power of 2) and fanout shift */ -++#define UBIFS_LPT_FANOUT 4 -++#define UBIFS_LPT_FANOUT_SHIFT 2 -++ -++/* LEB Properties Tree bit field sizes */ -++#define UBIFS_LPT_CRC_BITS 16 -++#define UBIFS_LPT_CRC_BYTES 2 -++#define UBIFS_LPT_TYPE_BITS 4 -++ -++/* The key is always at the same position in all keyed nodes */ -++#define UBIFS_KEY_OFFSET offsetof(struct ubifs_ino_node, key) -++ -++/* -++ * LEB Properties Tree node types. -++ * -++ * UBIFS_LPT_PNODE: LPT leaf node (contains LEB properties) -++ * UBIFS_LPT_NNODE: LPT internal node -++ * UBIFS_LPT_LTAB: LPT's own lprops table -++ * UBIFS_LPT_LSAVE: LPT's save table (big model only) -++ * UBIFS_LPT_NODE_CNT: count of LPT node types -++ * UBIFS_LPT_NOT_A_NODE: all ones (15 for 4 bits) is never a valid node type -++ */ -++enum { -++ UBIFS_LPT_PNODE, -++ UBIFS_LPT_NNODE, -++ UBIFS_LPT_LTAB, -++ UBIFS_LPT_LSAVE, -++ UBIFS_LPT_NODE_CNT, -++ UBIFS_LPT_NOT_A_NODE = (1 << UBIFS_LPT_TYPE_BITS) - 1, -++}; -++ -++/* -++ * UBIFS inode types. -++ * -++ * UBIFS_ITYPE_REG: regular file -++ * UBIFS_ITYPE_DIR: directory -++ * UBIFS_ITYPE_LNK: soft link -++ * UBIFS_ITYPE_BLK: block device node -++ * UBIFS_ITYPE_CHR: character device node -++ * UBIFS_ITYPE_FIFO: fifo -++ * UBIFS_ITYPE_SOCK: socket -++ * UBIFS_ITYPES_CNT: count of supported file types -++ */ -++enum { -++ UBIFS_ITYPE_REG, -++ UBIFS_ITYPE_DIR, -++ UBIFS_ITYPE_LNK, -++ UBIFS_ITYPE_BLK, -++ UBIFS_ITYPE_CHR, -++ UBIFS_ITYPE_FIFO, -++ UBIFS_ITYPE_SOCK, -++ UBIFS_ITYPES_CNT, -++}; -++ -++/* -++ * Supported key hash functions. -++ * -++ * UBIFS_KEY_HASH_R5: R5 hash -++ * UBIFS_KEY_HASH_TEST: test hash which just returns first 4 bytes of the name -++ */ -++enum { -++ UBIFS_KEY_HASH_R5, -++ UBIFS_KEY_HASH_TEST, -++}; -++ -++/* -++ * Supported key formats. -++ * -++ * UBIFS_SIMPLE_KEY_FMT: simple key format -++ */ -++enum { -++ UBIFS_SIMPLE_KEY_FMT, -++}; -++ -++/* -++ * The simple key format uses 29 bits for storing UBIFS block number and hash -++ * value. -++ */ -++#define UBIFS_S_KEY_BLOCK_BITS 29 -++/* -++ * TODO: this is a temporary hach which was added to support old format and to -++ * avoid breaking binary compatibility. It is temporaty and should go. The -++ * define should be -++ * #define UBIFS_S_KEY_BLOCK_MASK 0x1FFFFFFF -++ */ -++#define UBIFS_S_KEY_BLOCK_MASK (c->fmt_version == 2 ? 0x01FFFFFF : 0x1FFFFFFF) -++#define UBIFS_S_KEY_HASH_BITS UBIFS_S_KEY_BLOCK_BITS -++#define UBIFS_S_KEY_HASH_MASK UBIFS_S_KEY_BLOCK_MASK -++ -++/* -++ * Key types. -++ * -++ * UBIFS_INO_KEY: inode node key -++ * UBIFS_DATA_KEY: data node key -++ * UBIFS_DENT_KEY: directory entry node key -++ * UBIFS_XENT_KEY: extended attribute entry key -++ * UBIFS_TRUN_KEY: truncation node key -++ * UBIFS_KEY_TYPES_CNT: number of supported key types -++ */ -++enum { -++ UBIFS_INO_KEY, -++ UBIFS_DATA_KEY, -++ UBIFS_DENT_KEY, -++ UBIFS_XENT_KEY, -++ UBIFS_TRUN_KEY, -++ UBIFS_KEY_TYPES_CNT, -++}; -++ -++/* Count of LEBs reserved for the superblock area */ -++#define UBIFS_SB_LEBS 1 -++/* Count of LEBs reserved for the master area */ -++#define UBIFS_MST_LEBS 2 -++ -++/* First LEB of the superblock area */ -++#define UBIFS_SB_LNUM 0 -++/* First LEB of the master area */ -++#define UBIFS_MST_LNUM (UBIFS_SB_LNUM + UBIFS_SB_LEBS) -++/* First LEB of the log area */ -++#define UBIFS_LOG_LNUM (UBIFS_MST_LNUM + UBIFS_MST_LEBS) -++ -++/* Minimum number of logical eraseblocks in the log */ -++#define UBIFS_MIN_LOG_LEBS 2 -++/* Minimum number of bud logical eraseblocks */ -++#define UBIFS_MIN_BUD_LEBS 2 -++/* Minimum number of journal logical eraseblocks */ -++#define UBIFS_MIN_JNL_LEBS (UBIFS_MIN_LOG_LEBS + UBIFS_MIN_BUD_LEBS) -++/* Minimum number of LPT area logical eraseblocks */ -++#define UBIFS_MIN_LPT_LEBS 2 -++/* Minimum number of orphan area logical eraseblocks */ -++#define UBIFS_MIN_ORPH_LEBS 1 -++/* Minimum number of main area logical eraseblocks */ -++#define UBIFS_MIN_MAIN_LEBS 8 -++ -++/* Minimum number of logical eraseblocks */ -++#define UBIFS_MIN_LEB_CNT (UBIFS_SB_LEBS + UBIFS_MST_LEBS + \ -++ UBIFS_MIN_LOG_LEBS + UBIFS_MIN_BUD_LEBS + \ -++ UBIFS_MIN_LPT_LEBS + UBIFS_MIN_ORPH_LEBS + \ -++ UBIFS_MIN_MAIN_LEBS) -++ -++/* Node sizes (N.B. these are guaranteed to be multiples of 8) */ -++#define UBIFS_CH_SZ sizeof(struct ubifs_ch) -++#define UBIFS_INO_NODE_SZ sizeof(struct ubifs_ino_node) -++#define UBIFS_DATA_NODE_SZ sizeof(struct ubifs_data_node) -++#define UBIFS_DENT_NODE_SZ sizeof(struct ubifs_dent_node) -++#define UBIFS_TRUN_NODE_SZ sizeof(struct ubifs_trun_node) -++#define UBIFS_PAD_NODE_SZ sizeof(struct ubifs_pad_node) -++#define UBIFS_SB_NODE_SZ sizeof(struct ubifs_sb_node) -++#define UBIFS_MST_NODE_SZ sizeof(struct ubifs_mst_node) -++#define UBIFS_REF_NODE_SZ sizeof(struct ubifs_ref_node) -++#define UBIFS_IDX_NODE_SZ sizeof(struct ubifs_idx_node) -++#define UBIFS_CS_NODE_SZ sizeof(struct ubifs_cs_node) -++#define UBIFS_ORPH_NODE_SZ sizeof(struct ubifs_orph_node) -++/* Extended attribute entry nodes are identical to directory entry nodes */ -++#define UBIFS_XENT_NODE_SZ UBIFS_DENT_NODE_SZ -++/* Only this does not have to be multiple of 8 bytes */ -++#define UBIFS_BRANCH_SZ sizeof(struct ubifs_branch) -++ -++/* Maximum node sizes (N.B. these are guaranteed to be multiples of 8) */ -++#define UBIFS_MAX_DATA_NODE_SZ (UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE) -++#define UBIFS_MAX_INO_NODE_SZ (UBIFS_INO_NODE_SZ + UBIFS_MAX_INO_DATA) -++#define UBIFS_MAX_DENT_NODE_SZ (UBIFS_DENT_NODE_SZ + UBIFS_MAX_NLEN + 1) -++#define UBIFS_MAX_XENT_NODE_SZ UBIFS_MAX_DENT_NODE_SZ -++ -++/* The largest UBIFS node */ -++#define UBIFS_MAX_NODE_SZ UBIFS_MAX_INO_NODE_SZ -++ -++/* -++ * On-flash inode flags. -++ * -++ * UBIFS_COMPR_FL: use compression for this inode -++ * UBIFS_SYNC_FL: I/O on this inode has to be synchronous -++ * UBIFS_IMMUTABLE_FL: inode is immutable -++ * UBIFS_APPEND_FL: writes to the inode may only append data -++ * UBIFS_DIRSYNC_FL: I/O on this directory inode has to be synchronous -++ * -++ * Note, these are on-flash flags which correspond to ioctl flags -++ * (@FS_COMPR_FL, etc). They have the same values now, but generally, do not -++ * have to be the same. -++ */ -++enum { -++ UBIFS_COMPR_FL = 0x01, -++ UBIFS_SYNC_FL = 0x02, -++ UBIFS_IMMUTABLE_FL = 0x04, -++ UBIFS_APPEND_FL = 0x08, -++ UBIFS_DIRSYNC_FL = 0x10, -++}; -++ -++/* Inode flag bits used by UBIFS */ -++#define UBIFS_FL_MASK 0x0000001F -++ -++/* -++ * UBIFS compression types. -++ * -++ * UBIFS_COMPR_NONE: no compression -++ * UBIFS_COMPR_LZO: LZO compression -++ * UBIFS_COMPR_ZLIB: ZLIB compression -++ * UBIFS_COMPR_TYPES_CNT: count of supported compression types -++ */ -++enum { -++ UBIFS_COMPR_NONE, -++ UBIFS_COMPR_LZO, -++ UBIFS_COMPR_ZLIB, -++ UBIFS_COMPR_TYPES_CNT, -++}; -++ -++/* -++ * UBIFS node types. -++ * -++ * UBIFS_INO_NODE: inode node -++ * UBIFS_DATA_NODE: data node -++ * UBIFS_DENT_NODE: directory entry node -++ * UBIFS_XENT_NODE: extended attribute node -++ * UBIFS_TRUN_NODE: truncation node -++ * UBIFS_PAD_NODE: padding node -++ * UBIFS_SB_NODE: superblock node -++ * UBIFS_MST_NODE: master node -++ * UBIFS_REF_NODE: LEB reference node -++ * UBIFS_IDX_NODE: index node -++ * UBIFS_CS_NODE: commit start node -++ * UBIFS_ORPH_NODE: orphan node -++ * UBIFS_NODE_TYPES_CNT: count of supported node types -++ * -++ * Note, we index arrays by these numbers, so keep them low and contiguous. -++ * Node type constants for inodes, direntries and so on have to be the same as -++ * corresponding key type constants. -++ */ -++enum { -++ UBIFS_INO_NODE, -++ UBIFS_DATA_NODE, -++ UBIFS_DENT_NODE, -++ UBIFS_XENT_NODE, -++ UBIFS_TRUN_NODE, -++ UBIFS_PAD_NODE, -++ UBIFS_SB_NODE, -++ UBIFS_MST_NODE, -++ UBIFS_REF_NODE, -++ UBIFS_IDX_NODE, -++ UBIFS_CS_NODE, -++ UBIFS_ORPH_NODE, -++ UBIFS_NODE_TYPES_CNT, -++}; -++ -++/* -++ * Master node flags. -++ * -++ * UBIFS_MST_DIRTY: rebooted uncleanly - master node is dirty -++ * UBIFS_MST_NO_ORPHS: no orphan inodes present -++ * UBIFS_MST_RCVRY: written by recovery -++ */ -++enum { -++ UBIFS_MST_DIRTY = 1, -++ UBIFS_MST_NO_ORPHS = 2, -++ UBIFS_MST_RCVRY = 4, -++}; -++ -++/* -++ * Node group type (used by recovery to recover whole group or none). -++ * -++ * UBIFS_NO_NODE_GROUP: this node is not part of a group -++ * UBIFS_IN_NODE_GROUP: this node is a part of a group -++ * UBIFS_LAST_OF_NODE_GROUP: this node is the last in a group -++ */ -++enum { -++ UBIFS_NO_NODE_GROUP = 0, -++ UBIFS_IN_NODE_GROUP, -++ UBIFS_LAST_OF_NODE_GROUP, -++}; -++ -++/* -++ * Superblock flags. -++ * -++ * UBIFS_FLG_BIGLPT: if "big" LPT model is used if set -++ */ -++enum { -++ UBIFS_FLG_BIGLPT = 0x02, -++}; -++ -++/** -++ * struct ubifs_ch - common header node. -++ * @magic: UBIFS node magic number (%UBIFS_NODE_MAGIC) -++ * @crc: CRC-32 checksum of the node header -++ * @sqnum: sequence number -++ * @len: full node length -++ * @node_type: node type -++ * @group_type: node group type -++ * @padding: reserved for future, zeroes -++ * -++ * Every UBIFS node starts with this common part. If the node has a key, the -++ * key always goes next. -++ */ -++struct ubifs_ch { -++ __le32 magic; -++ __le32 crc; -++ __le64 sqnum; -++ __le32 len; -++ __u8 node_type; -++ __u8 group_type; -++ __u8 padding[2]; -++} __attribute__ ((packed)); -++ -++/** -++ * union ubifs_dev_desc - device node descriptor. -++ * @new: new type device descriptor -++ * @huge: huge type device descriptor -++ * -++ * This data structure describes major/minor numbers of a device node. In an -++ * inode is a device node then its data contains an object of this type. UBIFS -++ * uses standard Linux "new" and "huge" device node encodings. -++ */ -++union ubifs_dev_desc { -++ __le32 new; -++ __le64 huge; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_ino_node - inode node. -++ * @ch: common header -++ * @key: node key -++ * @creat_sqnum: sequence number at time of creation -++ * @size: inode size in bytes (amount of uncompressed data) -++ * @atime_sec: access time seconds -++ * @ctime_sec: creation time seconds -++ * @mtime_sec: modification time seconds -++ * @atime_nsec: access time nanoseconds -++ * @ctime_nsec: creation time nanoseconds -++ * @mtime_nsec: modification time nanoseconds -++ * @nlink: number of hard links -++ * @uid: owner ID -++ * @gid: group ID -++ * @mode: access flags -++ * @flags: per-inode flags (%UBIFS_COMPR_FL, %UBIFS_SYNC_FL, etc) -++ * @data_len: inode data length -++ * @xattr_cnt: count of extended attributes this inode has -++ * @xattr_size: summarized size of all extended attributes in bytes -++ * @xattr_names: sum of lengths of all extended attribute names belonging to -++ * this inode -++ * @compr_type: compression type used for this inode -++ * @padding: reserved for future, zeroes -++ * @data: data attached to the inode -++ * -++ * Note, even though inode compression type is defined by @compr_type, some -++ * nodes of this inode may be compressed with different compressor - this -++ * happens if compression type is changed while the inode already has data -++ * nodes. But @compr_type will be use for further writes to the inode. -++ * -++ * Note, do not forget to amend 'zero_ino_node_unused()' function when changing -++ * the padding fields. -++ */ -++struct ubifs_ino_node { -++ struct ubifs_ch ch; -++ __u8 key[UBIFS_MAX_KEY_LEN]; -++ __le64 creat_sqnum; -++ __le64 size; -++ __le64 atime_sec; -++ __le64 ctime_sec; -++ __le64 mtime_sec; -++ __le32 atime_nsec; -++ __le32 ctime_nsec; -++ __le32 mtime_nsec; -++ __le32 nlink; -++ __le32 uid; -++ __le32 gid; -++ __le32 mode; -++ __le32 flags; -++ __le32 data_len; -++ __le32 xattr_cnt; -++ __le64 xattr_size; -++ __le32 xattr_names; -++ __le16 compr_type; -++ __u8 padding[26]; /* Watch 'zero_ino_node_unused()' if changing! */ -++ __u8 data[]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_dent_node - directory entry node. -++ * @ch: common header -++ * @key: node key -++ * @inum: target inode number -++ * @padding1: reserved for future, zeroes -++ * @type: type of the target inode (%UBIFS_ITYPE_REG, %UBIFS_ITYPE_DIR, etc) -++ * @nlen: name length -++ * @padding2: reserved for future, zeroes -++ * @name: zero-terminated name -++ * -++ * Note, do not forget to amend 'zero_dent_node_unused()' function when -++ * changing the padding fields. -++ */ -++struct ubifs_dent_node { -++ struct ubifs_ch ch; -++ __u8 key[UBIFS_MAX_KEY_LEN]; -++ __le64 inum; -++ __u8 padding1; -++ __u8 type; -++ __le16 nlen; -++ __u8 padding2[4]; /* Watch 'zero_dent_node_unused()' if changing! */ -++ __u8 name[]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_data_node - data node. -++ * @ch: common header -++ * @key: node key -++ * @size: uncompressed data size in bytes -++ * @compr_type: compression type (%UBIFS_COMPR_NONE, %UBIFS_COMPR_LZO, etc) -++ * @padding: reserved for future, zeroes -++ * @data: data -++ * -++ * Note, do not forget to amend 'zero_data_node_unused()' function when -++ * changing the padding fields. -++ */ -++struct ubifs_data_node { -++ struct ubifs_ch ch; -++ __u8 key[UBIFS_MAX_KEY_LEN]; -++ __le32 size; -++ __le16 compr_type; -++ __u8 padding[2]; /* Watch 'zero_data_node_unused()' if changing! */ -++ __u8 data[]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_trun_node - truncation node. -++ * @ch: common header -++ * @key: truncation node key -++ * @old_size: size before truncation -++ * @new_size: size after truncation -++ * -++ * This node exists only in the journal and never goes to the main area. -++ */ -++struct ubifs_trun_node { -++ struct ubifs_ch ch; -++ __u8 key[UBIFS_MAX_KEY_LEN]; -++ __le64 old_size; -++ __le64 new_size; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_pad_node - padding node. -++ * @ch: common header -++ * @pad_len: how many bytes after this node are unused (because padded) -++ * @padding: reserved for future, zeroes -++ */ -++struct ubifs_pad_node { -++ struct ubifs_ch ch; -++ __le32 pad_len; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_sb_node - superblock node. -++ * @ch: common header -++ * @padding: reserved for future, zeroes -++ * @key_hash: type of hash function used in keys -++ * @key_fmt: format of the key -++ * @flags: file-system flags (%UBIFS_FLG_BIGLPT, etc) -++ * @min_io_size: minimal input/output unit size -++ * @leb_size: logical eraseblock size in bytes -++ * @leb_cnt: count of LEBs used by filesystem -++ * @max_leb_cnt: maximum count of LEBs used by filesystem -++ * @max_bud_bytes: maximum amount of data stored in buds -++ * @log_lebs: log size in logical eraseblocks -++ * @lpt_lebs: number of LEBs used for lprops table -++ * @orph_lebs: number of LEBs used for recording orphans -++ * @jhead_cnt: count of journal heads -++ * @fanout: tree fanout (max. number of links per indexing node) -++ * @lsave_cnt: number of LEB numbers in LPT's save table -++ * @fmt_version: UBIFS on-flash format version -++ * @default_compr: default compression -++ * @padding1: reserved for future, zeroes -++ * @rp_uid: reserve pool UID -++ * @rp_gid: reserve pool GID -++ * @rp_size: size of the reserved pool in bytes -++ * @padding2: reserved for future, zeroes -++ * @time_gran: time granularity in nanoseconds -++ */ -++struct ubifs_sb_node { -++ struct ubifs_ch ch; -++ __u8 padding[2]; -++ __u8 key_hash; -++ __u8 key_fmt; -++ __le32 flags; -++ __le32 min_io_size; -++ __le32 leb_size; -++ __le32 leb_cnt; -++ __le32 max_leb_cnt; -++ __le64 max_bud_bytes; -++ __le32 log_lebs; -++ __le32 lpt_lebs; -++ __le32 orph_lebs; -++ __le32 jhead_cnt; -++ __le32 fanout; -++ __le32 lsave_cnt; -++ __le32 fmt_version; -++ __le16 default_compr; -++ __u8 padding1[2]; -++ __le32 rp_uid; -++ __le32 rp_gid; -++ __le64 rp_size; -++ __le32 time_gran; -++ __u8 padding2[3988]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_mst_node - master node. -++ * @ch: common header -++ * @highest_inum: highest inode number in the committed index -++ * @cmt_no: commit number -++ * @flags: various flags (%UBIFS_MST_DIRTY, etc) -++ * @log_lnum: start of the log -++ * @root_lnum: LEB number of the root indexing node -++ * @root_offs: offset within @root_lnum -++ * @root_len: root indexing node length -++ * @gc_lnum: LEB reserved for garbage collection (%-1 value means the LEB was -++ * not reserved and should be reserved on mount) -++ * @ihead_lnum: LEB number of index head -++ * @ihead_offs: offset of index head -++ * @index_size: size of index on flash -++ * @total_free: total free space in bytes -++ * @total_dirty: total dirty space in bytes -++ * @total_used: total used space in bytes (includes only data LEBs) -++ * @total_dead: total dead space in bytes (includes only data LEBs) -++ * @total_dark: total dark space in bytes (includes only data LEBs) -++ * @lpt_lnum: LEB number of LPT root nnode -++ * @lpt_offs: offset of LPT root nnode -++ * @nhead_lnum: LEB number of LPT head -++ * @nhead_offs: offset of LPT head -++ * @ltab_lnum: LEB number of LPT's own lprops table -++ * @ltab_offs: offset of LPT's own lprops table -++ * @lsave_lnum: LEB number of LPT's save table (big model only) -++ * @lsave_offs: offset of LPT's save table (big model only) -++ * @lscan_lnum: LEB number of last LPT scan -++ * @empty_lebs: number of empty logical eraseblocks -++ * @idx_lebs: number of indexing logical eraseblocks -++ * @leb_cnt: count of LEBs used by filesystem -++ * @padding: reserved for future, zeroes -++ */ -++struct ubifs_mst_node { -++ struct ubifs_ch ch; -++ __le64 highest_inum; -++ __le64 cmt_no; -++ __le32 flags; -++ __le32 log_lnum; -++ __le32 root_lnum; -++ __le32 root_offs; -++ __le32 root_len; -++ __le32 gc_lnum; -++ __le32 ihead_lnum; -++ __le32 ihead_offs; -++ __le64 index_size; -++ __le64 total_free; -++ __le64 total_dirty; -++ __le64 total_used; -++ __le64 total_dead; -++ __le64 total_dark; -++ __le32 lpt_lnum; -++ __le32 lpt_offs; -++ __le32 nhead_lnum; -++ __le32 nhead_offs; -++ __le32 ltab_lnum; -++ __le32 ltab_offs; -++ __le32 lsave_lnum; -++ __le32 lsave_offs; -++ __le32 lscan_lnum; -++ __le32 empty_lebs; -++ __le32 idx_lebs; -++ __le32 leb_cnt; -++ __u8 padding[344]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_ref_node - logical eraseblock reference node. -++ * @ch: common header -++ * @lnum: the referred logical eraseblock number -++ * @offs: start offset in the referred LEB -++ * @jhead: journal head number -++ * @padding: reserved for future, zeroes -++ */ -++struct ubifs_ref_node { -++ struct ubifs_ch ch; -++ __le32 lnum; -++ __le32 offs; -++ __le32 jhead; -++ __u8 padding[28]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_branch - key/reference/length branch -++ * @lnum: LEB number of the target node -++ * @offs: offset within @lnum -++ * @len: target node length -++ * @key: key -++ */ -++struct ubifs_branch { -++ __le32 lnum; -++ __le32 offs; -++ __le32 len; -++ __u8 key[]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_idx_node - indexing node. -++ * @ch: common header -++ * @child_cnt: number of child index nodes -++ * @level: tree level -++ * @branches: LEB number / offset / length / key branches -++ */ -++struct ubifs_idx_node { -++ struct ubifs_ch ch; -++ __le16 child_cnt; -++ __le16 level; -++ __u8 branches[]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_cs_node - commit start node. -++ * @ch: common header -++ * @cmt_no: commit number -++ */ -++struct ubifs_cs_node { -++ struct ubifs_ch ch; -++ __le64 cmt_no; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubifs_orph_node - orphan node. -++ * @ch: common header -++ * @cmt_no: commit number (also top bit is set on the last node of the commit) -++ * @inos: inode numbers of orphans -++ */ -++struct ubifs_orph_node { -++ struct ubifs_ch ch; -++ __le64 cmt_no; -++ __le64 inos[]; -++} __attribute__ ((packed)); -++ -++#endif /* __UBIFS_MEDIA_H__ */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/ubifs.h linux-2.6.24.7/fs/ubifs/ubifs.h -+--- linux-2.6.24.7.old/fs/ubifs/ubifs.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/ubifs.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1589 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* Implementation version 0.6 */ -++ -++#ifndef __UBIFS_H__ -++#define __UBIFS_H__ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "ubifs-media.h" -++#include "compat.h" -++ -++/* Version of this UBIFS implementation */ -++#define UBIFS_VERSION 1 -++ -++/* Normal UBIFS messages */ -++#define ubifs_msg(fmt, ...) \ -++ printk(KERN_NOTICE "UBIFS: " fmt "\n", ##__VA_ARGS__) -++/* UBIFS error messages */ -++#define ubifs_err(fmt, ...) \ -++ printk(KERN_ERR "UBIFS error (pid %d): %s: " fmt "\n", current->pid, \ -++ __func__, ##__VA_ARGS__) -++/* UBIFS warning messages */ -++#define ubifs_warn(fmt, ...) \ -++ printk(KERN_WARNING "UBIFS warning (pid %d): %s: " fmt "\n", \ -++ current->pid, __func__, ##__VA_ARGS__) -++ -++/* UBIFS file system VFS magic number */ -++#define UBIFS_SUPER_MAGIC 0x24051905 -++ -++/* Number of UBIFS blocks per VFS page */ -++#define UBIFS_BLOCKS_PER_PAGE (PAGE_CACHE_SIZE / UBIFS_BLOCK_SIZE) -++#define UBIFS_BLOCKS_PER_PAGE_SHIFT (PAGE_CACHE_SHIFT - UBIFS_BLOCK_SHIFT) -++ -++/* "File system end of life" sequence number watermark */ -++#define SQNUM_WARN_WATERMARK 0xFFFFFFFF00000000ULL -++#define SQNUM_WATERMARK 0xFFFFFFFFFF000000ULL -++ -++/* Minimum amount of data UBIFS writes to the flash */ -++#define MIN_WRITE_SZ (UBIFS_DATA_NODE_SZ + 8) -++ -++/* -++ * Currently we do not support inode number overlapping and re-using, so this -++ * watermark defines dangerous inode number level. This should be fixed later, -++ * although it is difficult to exceed current limit. Another option is to use -++ * 64-bit inode numbers, but this means more overhead. -++ */ -++#define INUM_WARN_WATERMARK 0xFFF00000 -++#define INUM_WATERMARK 0xFFFFFF00 -++ -++/* Largest key size supported in this implementation */ -++#define CUR_MAX_KEY_LEN UBIFS_SK_LEN -++ -++/* Maximum number of entries in each LPT (LEB category) heap */ -++#define LPT_HEAP_SZ 256 -++ -++/* -++ * Background thread name pattern. The numbers are UBI device and volume -++ * numbers. -++ */ -++#define BGT_NAME_PATTERN "ubifs_bgt%d_%d" -++ -++/* Default write-buffer synchronization timeout (5 secs) */ -++#define DEFAULT_WBUF_TIMEOUT (5 * HZ) -++ -++/* Maximum possible inode number (only 32-bit inodes are supported now) */ -++#define MAX_INUM 0xFFFFFFFF -++ -++/* Number of non-data journal heads */ -++#define NONDATA_JHEADS_CNT 2 -++ -++/* Garbage collector head */ -++#define GCHD 0 -++/* Base journal head number */ -++#define BASEHD 1 -++/* First "general purpose" journal head */ -++#define DATAHD 2 -++ -++/* -++ * How much a directory entry/extended attribute entry adds to the parent/host -++ * inode. -++ */ -++#define CALC_DENT_SIZE(name_len) ALIGN(UBIFS_DENT_NODE_SZ + (name_len) + 1, 8) -++ -++/* -++ * Znodes which were not touched for 'OLD_ZNODE_AGE' seconds are considered -++ * "old", and znode which were touched last 'YOUNG_ZNODE_AGE' seconds ago are -++ * considered "young". This is used by shrinker when selecting znode to trim -++ * off. -++ */ -++#define OLD_ZNODE_AGE 20 -++#define YOUNG_ZNODE_AGE 5 -++ -++/* -++ * Some compressors, like LZO, may end up with more data then the input buffer. -++ * So UBIFS always allocates larger output buffer, to be sure the compressor -++ * will not corrupt memory in case of worst case compression. -++ */ -++#define WORST_COMPR_FACTOR 2 -++ -++/* Maximum expected tree height for use by bottom_up_buf */ -++#define BOTTOM_UP_HEIGHT 64 -++ -++/* -++ * Znode flags (actually, bit numbers which store the flags). -++ * -++ * DIRTY_ZNODE: znode is dirty -++ * COW_ZNODE: znode is being committed and a new instance of this znode has to -++ * be created before changing this znode -++ * OBSOLETE_ZNODE: znode is obsolete, which means it was deleted, but it is -++ * still in the commit list and the ongoing commit operation -++ * will commit it, and delete this znode after it is done -++ */ -++enum { -++ DIRTY_ZNODE = 0, -++ COW_ZNODE = 1, -++ OBSOLETE_ZNODE = 2 -++}; -++ -++/* -++ * Commit states. -++ * -++ * COMMIT_RESTING: commit is not wanted -++ * COMMIT_BACKGROUND: background commit has been requested -++ * COMMIT_REQUIRED: commit is required -++ * COMMIT_RUNNING_BACKGROUND: background commit is running -++ * COMMIT_RUNNING_REQUIRED: commit is running and it is required -++ * COMMIT_BROKEN: commit failed -++ */ -++enum { -++ COMMIT_RESTING = 0, -++ COMMIT_BACKGROUND, -++ COMMIT_REQUIRED, -++ COMMIT_RUNNING_BACKGROUND, -++ COMMIT_RUNNING_REQUIRED, -++ COMMIT_BROKEN, -++}; -++ -++/* -++ * 'ubifs_scan_a_node()' return values. -++ * -++ * SCANNED_GARBAGE: scanned garbage -++ * SCANNED_EMPTY_SPACE: scanned empty space -++ * SCANNED_A_NODE: scanned a valid node -++ * SCANNED_A_CORRUPT_NODE: scanned a corrupted node -++ * SCANNED_A_BAD_PAD_NODE: scanned a padding node with invalid pad length -++ * -++ * Greater than zero means: 'scanned that number of padding bytes' -++ */ -++enum { -++ SCANNED_GARBAGE = 0, -++ SCANNED_EMPTY_SPACE = -1, -++ SCANNED_A_NODE = -2, -++ SCANNED_A_CORRUPT_NODE = -3, -++ SCANNED_A_BAD_PAD_NODE = -4, -++}; -++ -++/* -++ * LPT cnode flag bits. -++ * -++ * DIRTY_CNODE: cnode is dirty -++ * COW_CNODE: cnode is being committed and must be copied before writing -++ * OBSOLETE_CNODE: cnode is being committed and has been copied (or deleted), -++ * so it can (and must) be freed when the commit is finished -++ */ -++enum { -++ DIRTY_CNODE = 0, -++ COW_CNODE = 1, -++ OBSOLETE_CNODE = 2, -++}; -++ -++/* -++ * Dirty flag bits (lpt_drty_flgs) for LPT special nodes. -++ * -++ * LTAB_DIRTY: ltab node is dirty -++ * LSAVE_DIRTY: lsave node is dirty -++ */ -++enum { -++ LTAB_DIRTY = 1, -++ LSAVE_DIRTY = 2, -++}; -++ -++/* -++ * Return codes used by the garbage collector. -++ * @LEB_FREED: the logical eraseblock was freed and is ready to use -++ * @LEB_FREED_IDX: indexing LEB was freed and can be used only after the commit -++ * @LEB_RETAINED: the logical eraseblock was freed and retained for GC purposes -++ */ -++enum { -++ LEB_FREED, -++ LEB_FREED_IDX, -++ LEB_RETAINED, -++}; -++ -++/** -++ * struct ubifs_old_idx - index node obsoleted since last commit start. -++ * @rb: rb-tree node -++ * @lnum: LEB number of obsoleted index node -++ * @offs: offset of obsoleted index node -++ */ -++struct ubifs_old_idx { -++ struct rb_node rb; -++ int lnum; -++ int offs; -++}; -++ -++/* The below union makes it easier to deal with keys */ -++union ubifs_key { -++ uint8_t u8[CUR_MAX_KEY_LEN]; -++ uint32_t u32[CUR_MAX_KEY_LEN/4]; -++ uint64_t u64[CUR_MAX_KEY_LEN/8]; -++ __le32 j32[CUR_MAX_KEY_LEN/4]; -++}; -++ -++/** -++ * struct ubifs_scan_node - UBIFS scanned node information. -++ * @list: list of scanned nodes -++ * @key: key of node scanned (if it has one) -++ * @sqnum: sequence number -++ * @type: type of node scanned -++ * @offs: offset with LEB of node scanned -++ * @len: length of node scanned -++ * @node: raw node -++ */ -++struct ubifs_scan_node { -++ struct list_head list; -++ union ubifs_key key; -++ unsigned long long sqnum; -++ int type; -++ int offs; -++ int len; -++ void *node; -++}; -++ -++/** -++ * struct ubifs_scan_leb - UBIFS scanned LEB information. -++ * @lnum: logical eraseblock number -++ * @nodes_cnt: number of nodes scanned -++ * @nodes: list of struct ubifs_scan_node -++ * @endpt: end point (and therefore the start of empty space) -++ * @ecc: read returned -EBADMSG -++ * @buf: buffer containing entire LEB scanned -++ */ -++struct ubifs_scan_leb { -++ int lnum; -++ int nodes_cnt; -++ struct list_head nodes; -++ int endpt; -++ int ecc; -++ void *buf; -++}; -++ -++/** -++ * struct ubifs_gced_idx_leb - garbage-collected indexing LEB. -++ * @list: list -++ * @lnum: LEB number -++ * @unmap: OK to unmap this LEB -++ * -++ * This data structure is used to temporary store garbage-collected indexing -++ * LEBs - they are not released immediately, but only after the next commit. -++ * This is needed to guarantee recoverability. -++ */ -++struct ubifs_gced_idx_leb { -++ struct list_head list; -++ int lnum; -++ int unmap; -++}; -++ -++/** -++ * struct ubifs_inode - UBIFS in-memory inode description. -++ * @vfs_inode: VFS inode description object -++ * @creat_sqnum: sequence number at time of creation -++ * @xattr_size: summarized size of all extended attributes in bytes, protected -++ * by @inode->i_lock -++ * @xattr_cnt: count of extended attributes this inode has -++ * @xattr_names: sum of lengths of all extended attribute names belonging to -++ * this inode -++ * @dirty: non-zero if the inode is dirty -++ * @xattr: non-zero if this is an extended attribute inode -++ * @budgeted: non-zero if the inode has been budgeted (used for debugging) -++ * @budg_mutex: serializes inode budgeting and write-back -++ * @flags: inode flags (@UBIFS_COMPR_FL, etc) -++ * @compr_type: default compression type used for this inode -++ * @data_len: length of the data attached to the inode -++ * @data: inode's data -++ * -++ * UBIFS has its own inode mutex, besides the VFS 'i_mutex'. The reason for -++ * this is budgeting - UBIFS has to budget each operation. So, if an operation -++ * is going to mark an inode dirty, it has to allocate budget for this. It -++ * cannot just mark it dirty because there is no guarantee there will be enough -++ * flash space when it is time to write the inode back. This means that UBIFS -++ * has to have full control over "clean <-> dirty" transitions of inodes (and -++ * pages actually, but it is easy for pages, because we have -++ * 'ubifs_prepare_write()' which is called _before_ every page change). But -++ * unfortunately, VFS marks inodes dirty in many places, and it does not ask -++ * the file-system if it is allowed to do so (there is a notifier, but it is -++ * not enough), i.e., there is no mechanism to synchronize with this. So we -++ * introduce our own dirty flag to UBIFS inodes and our own inode mutex to -++ * serialize "clean <-> dirty" transitions. -++ */ -++struct ubifs_inode { -++ struct inode vfs_inode; -++ unsigned long long creat_sqnum; -++ long long xattr_size; -++ int xattr_cnt; -++ int xattr_names; -++ unsigned int dirty:1; -++ unsigned int xattr:1; -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ unsigned int budgeted:1; -++#endif -++ struct mutex budg_mutex; -++ int flags; -++ int compr_type; -++ int data_len; -++ void *data; -++}; -++ -++/** -++ * struct ubifs_unclean_leb - records a LEB recovered under read-only mode. -++ * @list: list -++ * @lnum: LEB number of recovered LEB -++ * @endpt: offset where recovery ended -++ * -++ * This structure records a LEB identified during recovery that needs to be -++ * cleaned but was not because UBIFS was mounted read-only. The information -++ * is used to clean the LEB when remounting to read-write mode. -++ */ -++struct ubifs_unclean_leb { -++ struct list_head list; -++ int lnum; -++ int endpt; -++}; -++ -++/* -++ * LEB properties flags. -++ * -++ * LPROPS_UNCAT: not categorized -++ * LPROPS_DIRTY: dirty > 0, not index -++ * LPROPS_DIRTY_IDX: dirty + free > UBIFS_CH_SZ and index -++ * LPROPS_FREE: free > 0, not empty, not index -++ * LPROPS_HEAP_CNT: number of heaps used for storing categorized LEBs -++ * LPROPS_EMPTY: LEB is empty, not taken -++ * LPROPS_FREEABLE: free + dirty == leb_size, not index, not taken -++ * LPROPS_FRDI_IDX: free + dirty == leb_size and index, may be taken -++ * LPROPS_CAT_MASK: mask for the LEB categories above -++ * LPROPS_TAKEN: LEB was taken (this flag is not saved on the media) -++ * LPROPS_INDEX: LEB contains indexing nodes (this flag also exists on flash) -++ */ -++enum { -++ LPROPS_UNCAT = 0, -++ LPROPS_DIRTY = 1, -++ LPROPS_DIRTY_IDX = 2, -++ LPROPS_FREE = 3, -++ LPROPS_HEAP_CNT = 3, -++ LPROPS_EMPTY = 4, -++ LPROPS_FREEABLE = 5, -++ LPROPS_FRDI_IDX = 6, -++ LPROPS_CAT_MASK = 15, -++ LPROPS_TAKEN = 16, -++ LPROPS_INDEX = 32, -++}; -++ -++/** -++ * struct ubifs_lprops - logical eraseblock properties. -++ * @free: amount of free space in bytes -++ * @dirty: amount of dirty space in bytes -++ * @flags: LEB properties flags (see above) -++ * @lnum: LEB number -++ * @list: list of same-category lprops (for LPROPS_EMPTY and LPROPS_FREEABLE) -++ * @hpos: heap position in heap of same-category lprops (other categories) -++ */ -++struct ubifs_lprops { -++ int free; -++ int dirty; -++ int flags; -++ int lnum; -++ union { -++ struct list_head list; -++ int hpos; -++ }; -++}; -++ -++/** -++ * struct ubifs_lpt_lprops - LPT logical eraseblock properties. -++ * @free: amount of free space in bytes -++ * @dirty: amount of dirty space in bytes -++ * @tgc: trivial GC flag (1 => unmap after commit end) -++ * @cmt: commit flag (1 => reserved for commit) -++ */ -++struct ubifs_lpt_lprops { -++ int free; -++ int dirty; -++ unsigned tgc : 1; -++ unsigned cmt : 1; -++}; -++ -++/** -++ * struct ubifs_lp_stats - statistics of eraseblocks in the main area. -++ * @empty_lebs: number of empty LEBs -++ * @taken_empty_lebs: number of taken LEBs -++ * @idx_lebs: number of indexing LEBs -++ * @total_free: total free space in bytes -++ * @total_dirty: total dirty space in bytes -++ * @total_used: total used space in bytes (includes only data LEBs) -++ * @total_dead: total dead space in bytes (includes only data LEBs) -++ * @total_dark: total dark space in bytes (includes only data LEBs) -++ * -++ * N.B. total_dirty and total_used are different to other total_* fields, -++ * because they account _all_ LEBs, not just data LEBs. -++ * -++ * 'taken_empty_lebs' counts the LEBs that are in the transient state of having -++ * been 'taken' for use but not yet written to. 'taken_empty_lebs' is needed -++ * to account correctly for gc_lnum, otherwise 'empty_lebs' could be used -++ * by itself (in which case 'unused_lebs' would be a better name). In the case -++ * of gc_lnum, it is 'taken' at mount time or whenever a LEB is retained by GC, -++ * but unlike other empty LEBs that are 'taken', it may not be written straight -++ * away (i.e. before the next commit start or unmount), so either gc_lnum must -++ * be specially accounted for, or the current approach followed i.e. count it -++ * under 'taken_empty_lebs'. -++ */ -++struct ubifs_lp_stats { -++ int empty_lebs; -++ int taken_empty_lebs; -++ int idx_lebs; -++ long long total_free; -++ long long total_dirty; -++ long long total_used; -++ long long total_dead; -++ long long total_dark; -++}; -++ -++struct ubifs_nnode; -++ -++/** -++ * struct ubifs_cnode - LEB Properties Tree common node. -++ * @parent: parent nnode -++ * @cnext: next cnode to commit -++ * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE) -++ * @iip: index in parent -++ * @level: level in the tree (zero for pnodes, greater than zero for nnodes) -++ * @num: node number -++ */ -++struct ubifs_cnode { -++ struct ubifs_nnode *parent; -++ struct ubifs_cnode *cnext; -++ unsigned long flags; -++ int iip; -++ int level; -++ int num; -++}; -++ -++/** -++ * struct ubifs_pnode - LEB Properties Tree leaf node. -++ * @parent: parent nnode -++ * @cnext: next cnode to commit -++ * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE) -++ * @iip: index in parent -++ * @level: level in the tree (always zero for pnodes) -++ * @num: node number -++ * @lprops: LEB properties array -++ */ -++struct ubifs_pnode { -++ struct ubifs_nnode *parent; -++ struct ubifs_cnode *cnext; -++ unsigned long flags; -++ int iip; -++ int level; -++ int num; -++ struct ubifs_lprops lprops[UBIFS_LPT_FANOUT]; -++}; -++ -++/** -++ * struct ubifs_nbranch - LEB Properties Tree internal node branch. -++ * @lnum: LEB number of child -++ * @offs: offset of child -++ * @nnode: nnode child -++ * @pnode: pnode child -++ * @cnode: cnode child -++ */ -++struct ubifs_nbranch { -++ int lnum; -++ int offs; -++ union { -++ struct ubifs_nnode *nnode; -++ struct ubifs_pnode *pnode; -++ struct ubifs_cnode *cnode; -++ }; -++}; -++ -++/** -++ * struct ubifs_nnode - LEB Properties Tree internal node. -++ * @parent: parent nnode -++ * @cnext: next cnode to commit -++ * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE) -++ * @iip: index in parent -++ * @level: level in the tree (always greater than zero for nnodes) -++ * @num: node number -++ * @nbranch: branches to child nodes -++ */ -++struct ubifs_nnode { -++ struct ubifs_nnode *parent; -++ struct ubifs_cnode *cnext; -++ unsigned long flags; -++ int iip; -++ int level; -++ int num; -++ struct ubifs_nbranch nbranch[UBIFS_LPT_FANOUT]; -++}; -++ -++/** -++ * struct ubifs_lpt_heap - heap of categorized lprops. -++ * @arr: heap array -++ * @cnt: number in heap -++ * @max_cnt: maximum number allowed in heap -++ * -++ * There are %LPROPS_HEAP_CNT heaps. -++ */ -++struct ubifs_lpt_heap { -++ struct ubifs_lprops **arr; -++ int cnt; -++ int max_cnt; -++}; -++ -++/* -++ * Return codes for LPT scan callback function. -++ * -++ * LPT_SCAN_CONTINUE: continue scanning -++ * LPT_SCAN_ADD: add the LEB properties scanned to the tree in memory -++ * LPT_SCAN_STOP: stop scanning -++ */ -++enum { -++ LPT_SCAN_CONTINUE = 0, -++ LPT_SCAN_ADD = 1, -++ LPT_SCAN_STOP = 2, -++}; -++ -++struct ubifs_info; -++ -++/* Callback used by the 'ubifs_lpt_scan_nolock()' function */ -++typedef int (*ubifs_lpt_scan_callback)(struct ubifs_info *c, -++ const struct ubifs_lprops *lprops, -++ int in_tree, void *data); -++ -++/** -++ * struct ubifs_wbuf - UBIFS write-buffer. -++ * @c: UBIFS file-system description object -++ * @buf: write-buffer (of min. flash I/O unit size) -++ * @lnum: logical eraseblock number the write-buffer points to -++ * @offs: write-buffer offset in this logical eraseblock -++ * @avail: number of bytes available in the write-buffer -++ * @used: number of used bytes in the write-buffer -++ * @dtype: type of data stored in this LEB (%UBI_LONGTERM, %UBI_SHORTTERM, -++ * %UBI_UNKNOWN) -++ * @jhead: journal head the mutex belongs to (note, needed only to shut lockdep -++ * up by 'mutex_lock_nested()). -++ * @sync_callback: write-buffer synchronization callback -++ * @io_mutex: serializes write-buffer I/O -++ * @lock: serializes @buf, @lnum, @offs, @avail, @used, @next_ino and @inodes -++ * fields -++ * @timer: write-buffer timer -++ * @timeout: timer expire interval in jiffies -++ * @need_sync: it is set if its timer expired and needs sync -++ * @next_ino: points to the next position of the following inode number -++ * @inodes: stores the inode numbers of the nodes which are in wbuf -++ * -++ * The write-buffer synchronization callback is called when the write-buffer is -++ * synchronized in order to notify how much space was wasted due to -++ * write-buffer padding and how much free space is left in the LEB. -++ * -++ * Note: the fields @buf, @lnum, @offs, @avail and @used can be read under -++ * spin-lock or mutex because they are written under both mutex and spin-lock. -++ * @buf is appended to under mutex but overwritten under both mutex and -++ * spin-lock. Thus the data between @buf and @buf + @used can be read under -++ * spinlock. -++ */ -++struct ubifs_wbuf { -++ struct ubifs_info *c; -++ void *buf; -++ int lnum; -++ int offs; -++ int avail; -++ int used; -++ int dtype; -++ int jhead; -++ int (*sync_callback)(struct ubifs_info *c, int lnum, int free, int pad); -++ struct mutex io_mutex; -++ spinlock_t lock; -++ struct timer_list timer; -++ int timeout; -++ int need_sync; -++ int next_ino; -++ ino_t *inodes; -++}; -++ -++/** -++ * struct ubifs_bud - bud logical eraseblock. -++ * @lnum: logical eraseblock number -++ * @start: where the (uncommitted) bud data starts -++ * @jhead: journal head number this bud belongs to -++ * @list: link in the list buds belonging to the same journal head -++ * @rb: link in the tree of all buds -++ */ -++struct ubifs_bud { -++ int lnum; -++ int start; -++ int jhead; -++ struct list_head list; -++ struct rb_node rb; -++}; -++ -++/** -++ * struct ubifs_jhead - journal head. -++ * @wbuf: head's write-buffer -++ * @buds_list: list of bud LEBs belonging to this journal head -++ * -++ * Note, the @buds list is protected by the @c->buds_lock. -++ */ -++struct ubifs_jhead { -++ struct ubifs_wbuf wbuf; -++ struct list_head buds_list; -++}; -++ -++/** -++ * struct ubifs_zbranch - key/coordinate/length branch stored in znodes. -++ * @key: key -++ * @znode: znode address in memory -++ * @lnum: LEB number of the indexing node -++ * @offs: offset of the indexing node within @lnum -++ * @len: target node length -++ */ -++struct ubifs_zbranch { -++ union ubifs_key key; -++ union { -++ struct ubifs_znode *znode; -++ void *leaf; -++ }; -++ int lnum; -++ int offs; -++ int len; -++}; -++ -++/** -++ * struct ubifs_znode - in-memory representation of an indexing node. -++ * @parent: parent znode or NULL if it is the root -++ * @cnext: next znode to commit -++ * @flags: znode flags (%DIRTY_ZNODE, %COW_ZNODE or %OBSOLETE_ZNODE) -++ * @time: last access time (seconds) -++ * @level: level of the entry in the TNC tree -++ * @child_cnt: count of child znodes -++ * @iip: index in parent's zbranch array -++ * @alt: lower bound of key range has altered i.e. child inserted at slot 0 -++ * @lnum: LEB number of the corresponding indexing node -++ * @offs: offset of the corresponding indexing node -++ * @len: length of the corresponding indexing node -++ * @zbranch: array of znode branches (@c->fanout elements) -++ */ -++struct ubifs_znode { -++ struct ubifs_znode *parent; -++ struct ubifs_znode *cnext; -++ unsigned long flags; -++ unsigned long time; -++ int level; -++ int child_cnt; -++ int iip; -++ int alt; -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ int lnum, offs, len; -++#endif -++ struct ubifs_zbranch zbranch[]; -++}; -++ -++/** -++ * struct ubifs_node_range - node length range description data structure. -++ * @len: fixed node length -++ * @min_len: minimum possible node length -++ * @max_len: maximum possible node length -++ * -++ * If @max_len is %0, the node has fixed length @len. -++ */ -++struct ubifs_node_range { -++ union { -++ int len; -++ int min_len; -++ }; -++ int max_len; -++}; -++ -++/** -++ * struct ubifs_compressor - UBIFS compressor description structure. -++ * @compr_type: compressor type (%UBIFS_COMPR_LZO, etc) -++ * @cc: cryptoapi compressor handle -++ * @comp_mutex: mutex used during compression -++ * @decomp_mutex: mutex used during decompression -++ * @name: compressor name -++ * @capi_name: cryptoapi compressor name -++ */ -++struct ubifs_compressor { -++ int compr_type; -++ struct crypto_comp *cc; -++ struct mutex *comp_mutex; -++ struct mutex *decomp_mutex; -++ const char *name; -++ const char *capi_name; -++}; -++ -++/** -++ * struct ubifs_budget_req - budget requirements of an operation. -++ * -++ * @new_ino: non-zero if the operation adds a new inode -++ * @dirtied_ino: how many inodes the operation makes dirty -++ * @new_page: non-zero if the operation adds a new page -++ * @dirtied_page: non-zero if the operation makes a page dirty -++ * @new_dent: non-zero if the operation adds a new directory entry -++ * @mod_dent: non-zero if the operation removes or modifies an existing -++ * directory entry -++ * @new_ino_d: now much data newly created inode contains -++ * @dirtied_ino_d: now much data dirtied inode contains -++ * @idx_growth: how much the index will supposedly grow -++ * @data_growth: how much new data the operation will supposedly add -++ * @dd_growth: how much data that makes other data dirty the operation will -++ * supposedly add -++ * -++ * @idx_growth, @data_growth and @dd_growth are not used in budget request. The -++ * budgeting subsystem caches index and data growth values there to avoid -++ * re-calculating them when the budget is released. However, if @idx_growth is -++ * %-1, it is calculated by the release function using other fields. -++ * -++ * An inode may contain 4KiB of data at max., thus the widths of @new_ino_d -++ * is 13 bits, and @dirtied_ino_d - 15, because up to 4 inodes may be made -++ * dirty by the re-name operation. -++ */ -++struct ubifs_budget_req { -++ unsigned int new_ino:1; -++ unsigned int dirtied_ino:4; -++ unsigned int new_page:1; -++ unsigned int dirtied_page:1; -++ unsigned int new_dent:1; -++ unsigned int mod_dent:1; -++/* TODO: remove compatibility stuff as late as possible */ -++#ifdef UBIFS_COMPAT_USE_OLD_PREPARE_WRITE -++ unsigned int locked_pg:1; -++#endif -++ unsigned int new_ino_d:13; -++ unsigned int dirtied_ino_d:15; -++ int idx_growth; -++ int data_growth; -++ int dd_growth; -++}; -++ -++/** -++ * struct ubifs_orphan - stores the inode number of an orphan. -++ * @rb: rb-tree node of rb-tree of orphans sorted by inode number -++ * @list: list head of list of orphans in order added -++ * @new_list: list head of list of orphans added since the last commit -++ * @cnext: next orphan to commit -++ * @dnext: next orphan to delete -++ * @inum: inode number -++ * @new: %1 => added since the last commit, otherwise %0 -++ */ -++struct ubifs_orphan { -++ struct rb_node rb; -++ struct list_head list; -++ struct list_head new_list; -++ struct ubifs_orphan *cnext; -++ struct ubifs_orphan *dnext; -++ ino_t inum; -++ int new; -++}; -++ -++/** -++ * struct ubifs_mount_opts - UBIFS-specific mount options information. -++ * @unmount_mode: selected unmount mode (%0 default, %1 normal, %2 fast) -++ */ -++struct ubifs_mount_opts { -++ unsigned int unmount_mode:2; -++}; -++ -++/** -++ * struct ubifs_info - UBIFS file-system description data structure -++ * (per-superblock). -++ * @vfs_sb: VFS @struct super_block object -++ * -++ * @highest_inum: highest used inode number -++ * @vfs_gen: VFS inode generation counter -++ * @max_sqnum: current global sequence number -++ * @cmt_no: commit number (last successfully completed commit) -++ * @cnt_lock: protects @highest_inum, @vfs_gen, and @max_sqnum counters -++ * @fmt_version: UBIFS on-flash format version -++ * -++ * @lhead_lnum: log head logical eraseblock number -++ * @lhead_offs: log head offset -++ * @ltail_lnum: log tail logical eraseblock number (offset is always 0) -++ * @log_mutex: protects the log, @lhead_lnum, @lhead_offs, @ltail_lnum, and -++ * @bud_bytes -++ * @min_log_bytes: minimum required number of bytes in the log -++ * @cmt_bud_bytes: used during commit to temporarily amount of bytes in -++ * committed buds -++ * -++ * @buds: tree of all buds indexed by bud LEB number -++ * @bud_bytes: how many bytes of flash is used by buds -++ * @buds_lock: protects the @buds tree, @bud_bytes, and per-journal head bud -++ * lists -++ * @jhead_cnt: count of journal heads -++ * @jheads: journal heads (head zero is base head) -++ * @max_bud_bytes: maximum number of bytes allowed in buds -++ * @bg_bud_bytes: number of bud bytes when background commit is initiated -++ * @old_buds: buds to be released after commit ends -++ * @max_bud_cnt: maximum number of buds -++ * -++ * @commit_sem: synchronizes committer with other processes -++ * @cmt_state: commit state -++ * @cs_lock: commit state lock -++ * @cmt_wq: wait queue to sleep on if the log is full and a commit is running -++ * @fast_unmount: do not run journal commit before unmounting -++ * @big_lpt: flag that LPT is too big to write whole during commit -++ * -++ * @tnc_mutex: protects the Tree Node Cache (TNC), @zroot, @cnext, @enext, and -++ * @calc_idx_sz -++ * @zroot: zbranch which points to the root index node and znode -++ * @cnext: next znode to commit -++ * @enext: next znode to commit to empty space -++ * @gap_lebs: array of LEBs used by the in-gaps commit method -++ * @cbuf: commit buffer -++ * @ileb_buf: buffer for commit in-the-gaps method -++ * @ileb_len: length of data in ileb_buf -++ * @ihead_lnum: LEB number of index head -++ * @ihead_offs: offset of index head -++ * @ilebs: pre-allocated index LEBs -++ * @ileb_cnt: number of pre-allocated index LEBs -++ * @ileb_nxt: next pre-allocated index LEBs -++ * @old_idx: tree of index nodes obsoleted since the last commit start -++ * @bottom_up_buf: a buffer which is used by 'dirty_cow_bottom_up()' in tnc.c -++ * @new_ihead_lnum: used by debugging to check ihead_lnum -++ * @new_ihead_offs: used by debugging to check ihead_offs -++ * -++ * @mst_node: master node -++ * @mst_offs: offset of valid master node -++ * @mst_mutex: protects the master node area, @mst_node, and @mst_offs -++ * -++ * @log_lebs: number of logical eraseblocks in the log -++ * @log_bytes: log size in bytes -++ * @log_last: last LEB of the log -++ * @lpt_lebs: number of LEBs used for lprops table -++ * @lpt_first: first LEB of the lprops table area -++ * @lpt_last: last LEB of the lprops table area -++ * @orph_lebs: number of LEBs used for the orphan area -++ * @orph_first: first LEB of the orphan area -++ * @orph_last: last LEB of the orphan area -++ * @main_lebs: count of LEBs in the main area -++ * @main_first: first LEB of the main area -++ * @main_bytes: main area size in bytes -++ * @default_compr: default compression type -++ * -++ * @key_hash_type: type of the key hash -++ * @key_hash: direntry key hash function -++ * @key_fmt: key format -++ * @key_len: key length -++ * @fanout: fanout of the index tree (number of links per indexing node) -++ * -++ * @min_io_size: minimal input/output unit size -++ * @min_io_shift: number of bits in @min_io_size minus one -++ * @leb_size: logical eraseblock size in bytes -++ * @half_leb_size: half LEB size -++ * @leb_cnt: count of logical eraseblocks -++ * @max_leb_cnt: maximum count of logical eraseblocks -++ * @old_leb_cnt: count of logical eraseblocks before resize -++ * @ro_media: the underlying UBI volume is read-only -++ * -++ * @dirty_pg_cnt: number of dirty pages (not used) -++ * @dirty_ino_cnt: number of dirty inodes (not used) -++ * @dirty_zn_cnt: number of dirty znodes -++ * @clean_zn_cnt: number of clean znodes -++ * -++ * @budg_idx_growth: amount of bytes budgeted for index growth -++ * @budg_data_growth: amount of bytes budgeted for cached data -++ * @budg_dd_growth: amount of bytes budgeted for cached data that will make -++ * other data dirty -++ * @budg_uncommitted_idx: amount of bytes were budgeted for growth of the index, -++ * but which still have to be taken into account because -++ * the index has not been committed so far -++ * @space_lock: protects @budg_idx_growth, @budg_data_growth, @budg_dd_growth, -++ * @budg_uncommited_idx, @min_idx_lebs, @old_idx_sz, and @lst; -++ * @min_idx_lebs: minimum number of LEBs required for the index -++ * @old_idx_sz: size of index on flash -++ * @calc_idx_sz: temporary variable which is used to calculate new index size -++ * (contains accurate new index size at end of TNC commit start) -++ * @lst: lprops statistics -++ * -++ * @page_budget: budget for a page -++ * @inode_budget: budget for an inode -++ * @dent_budget: budget for a directory entry -++ * -++ * @ref_node_alsz: size of the LEB reference node aligned to the min. flash -++ * I/O unit -++ * @mst_node_alsz: master node aligned size -++ * @min_idx_node_sz: minimum indexing node aligned on 8-bytes boundary -++ * @max_idx_node_sz: maximum indexing node aligned on 8-bytes boundary -++ * @max_inode_sz: maximum possible inode size in bytes -++ * @max_znode_sz: size of znode in bytes -++ * @dead_wm: LEB dead space watermark -++ * @dark_wm: LEB dark space watermark -++ * @block_cnt: count of 4KiB blocks on the FS -++ * -++ * @ranges: UBIFS node length ranges -++ * @ubi: UBI volume descriptor -++ * @di: UBI device information -++ * @vi: UBI volume information -++ * -++ * @orph_tree: rb-tree of orphan inode numbers -++ * @orph_list: list of orphan inode numbers in order added -++ * @orph_new: list of orphan inode numbers added since last commit -++ * @orph_cnext: next orphan to commit -++ * @orph_dnext: next orphan to delete -++ * @orphan_lock: lock for orph_tree and orph_new -++ * @orph_buf: buffer for orphan nodes -++ * @new_orphans: number of orphans since last commit -++ * @cmt_orphans: number of orphans being committed -++ * @tot_orphans: number of orphans in the rb_tree -++ * @max_orphans: maximum number of orphans allowed -++ * @ohead_lnum: orphan head LEB number -++ * @ohead_offs: orphan head offset -++ * @no_orphs: non-zero if there are no orphans -++ * -++ * @bgt: UBIFS background thread -++ * @bgt_name: background thread name -++ * @need_bgt: if background thread should run -++ * @need_wbuf_sync: if write-buffers have to be synchronized -++ * -++ * @gc_lnum: LEB number used for garbage collection -++ * @sbuf: a buffer of LEB size used by GC and replay for scanning -++ * @idx_gc: list of index LEBs that have been garbage collected -++ * @idx_gc_cnt: number of elements on the idx_gc list -++ * -++ * @infos_list: links all 'ubifs_info' objects -++ * @umount_mutex: serializes shrinker and un-mount -++ * @shrinker_run_no: shrinker run number -++ * -++ * @space_bits: number of bits needed to record free or dirty space -++ * @lpt_lnum_bits: number of bits needed to record a LEB number in the LPT -++ * @lpt_offs_bits: number of bits needed to record an offset in the LPT -++ * @lpt_spc_bits: number of bits needed to space in the LPT -++ * @pcnt_bits: number of bits needed to record pnode or nnode number -++ * @lnum_bits: number of bits needed to record LEB number -++ * @nnode_sz: size of on-flash nnode -++ * @pnode_sz: size of on-flash pnode -++ * @ltab_sz: size of on-flash LPT lprops table -++ * @lsave_sz: size of on-flash LPT save table -++ * @pnode_cnt: number of pnodes -++ * @nnode_cnt: number of nnodes -++ * @lpt_hght: height of the LPT -++ * @pnodes_have: number of pnodes in memory -++ * -++ * @lp_mutex: protects lprops table and all the other lprops-related fields -++ * @lpt_lnum: LEB number of the root nnode of the LPT -++ * @lpt_offs: offset of the root nnode of the LPT -++ * @nhead_lnum: LEB number of LPT head -++ * @nhead_offs: offset of LPT head -++ * @lpt_drty_flgs: dirty flags for LPT special nodes e.g. ltab -++ * @dirty_nn_cnt: number of dirty nnodes -++ * @dirty_pn_cnt: number of dirty pnodes -++ * @lpt_sz: LPT size -++ * @lpt_nod_buf: buffer for an on-flash nnode or pnode -++ * @lpt_buf: buffer of LEB size used by LPT -++ * @nroot: address in memory of the root nnode of the LPT -++ * @lpt_cnext: next LPT node to commit -++ * @lpt_heap: array of heaps of categorized lprops -++ * @dirty_idx: a (reverse sorted) copy of the LPROPS_DIRTY_IDX heap as at -++ * previous commit start -++ * @uncat_list: list of un-categorized LEBs -++ * @empty_list: list of empty LEBs -++ * @freeable_list: list of freeable non-index LEBs (free + dirty == leb_size) -++ * @frdi_idx_list: list of freeable index LEBs (free + dirty == leb_size) -++ * @freeable_cnt: number of freeable LEBs in @freeable_list -++ * -++ * @ltab_lnum: LEB number of LPT's own lprops table -++ * @ltab_offs: offset of LPT's own lprops table -++ * @ltab: LPT's own lprops table -++ * @ltab_cmt: LPT's own lprops table (commit copy) -++ * @lsave_cnt: number of LEB numbers in LPT's save table -++ * @lsave_lnum: LEB number of LPT's save table -++ * @lsave_offs: offset of LPT's save table -++ * @lsave: LPT's save table -++ * @lscan_lnum: LEB number of last LPT scan -++ * -++ * @rp_size: size of the reserved pool in bytes -++ * @report_rp_size: size of the reserved pool reported to userspace -++ * @rp_uid: reserved pool user ID -++ * @rp_gid: reserved pool group ID -++ * -++ * @empty: if the UBI device is empty -++ * @replay_tree: temporary tree used during journal replay -++ * @replay_list: temporary list used during journal replay -++ * @replay_buds: list of buds to replay -++ * @cs_sqnum: sequence number of first node in the log (commit start node) -++ * @replay_sqnum: sequence number of node currently being replayed -++ * @need_recovery: file-system needs recovery -++ * @replaying: set to %1 during journal replay -++ * @unclean_leb_list: LEBs to recover when mounting ro to rw -++ * @rcvrd_mst_node: recovered master node to write when mounting ro to rw -++ * @size_tree: inode size information for recovery -++ * @recovery_needs_commit: a commit must be done before unmounting -++ * @remounting_rw: set while remounting from ro to rw (sb flags have MS_RDONLY) -++ * @mount_opts: UBIFS-specific mount options -++ * -++ * @dbg_buf: a buffer of LEB size used for debugging purposes -++ * @old_zroot: old index root - used by 'dbg_check_old_index()' -++ * @old_zroot_level: old index root level - used by 'dbg_check_old_index()' -++ * @old_zroot_sqnum: old index root sqnum - used by 'dbg_check_old_index()' -++ * @failure_mode: failure mode for recovery testing -++ * @fail_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls -++ * @fail_timeout: time in jiffies when delay of failure mode expires -++ * @fail_cnt: current number of calls to failure mode I/O functions -++ * @fail_cnt_max: number of calls by which to delay failure mode -++ */ -++struct ubifs_info { -++ struct super_block *vfs_sb; -++ -++ ino_t highest_inum; -++ unsigned int vfs_gen; -++ unsigned long long max_sqnum; -++ unsigned long long cmt_no; -++ spinlock_t cnt_lock; -++ int fmt_version; -++ -++ int lhead_lnum; -++ int lhead_offs; -++ int ltail_lnum; -++ struct mutex log_mutex; -++ int min_log_bytes; -++ long long cmt_bud_bytes; -++ -++ struct rb_root buds; -++ long long bud_bytes; -++ spinlock_t buds_lock; -++ int jhead_cnt; -++ struct ubifs_jhead *jheads; -++ long long max_bud_bytes; -++ long long bg_bud_bytes; -++ struct list_head old_buds; -++ int max_bud_cnt; -++ -++ struct rw_semaphore commit_sem; -++ int cmt_state; -++ spinlock_t cs_lock; -++ wait_queue_head_t cmt_wq; -++ unsigned int fast_unmount:1; -++ unsigned int big_lpt:1; -++ -++ struct mutex tnc_mutex; -++ struct ubifs_zbranch zroot; -++ struct ubifs_znode *cnext; -++ struct ubifs_znode *enext; -++ int *gap_lebs; -++ void *cbuf; -++ void *ileb_buf; -++ int ileb_len; -++ int ihead_lnum; -++ int ihead_offs; -++ int *ilebs; -++ int ileb_cnt; -++ int ileb_nxt; -++ struct rb_root old_idx; -++ int *bottom_up_buf; -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ int new_ihead_lnum; -++ int new_ihead_offs; -++#endif -++ -++ struct ubifs_mst_node *mst_node; -++ int mst_offs; -++ struct mutex mst_mutex; -++ -++ int log_lebs; -++ long long log_bytes; -++ int log_last; -++ int lpt_lebs; -++ int lpt_first; -++ int lpt_last; -++ int orph_lebs; -++ int orph_first; -++ int orph_last; -++ int main_lebs; -++ int main_first; -++ long long main_bytes; -++ int default_compr; -++ -++ uint8_t key_hash_type; -++ uint32_t (*key_hash)(const char *str, int len); -++ int key_fmt; -++ int key_len; -++ int fanout; -++ -++ int min_io_size; -++ int min_io_shift; -++ int leb_size; -++ int half_leb_size; -++ int leb_cnt; -++ int max_leb_cnt; -++ int old_leb_cnt; -++ int ro_media; -++ -++ atomic_long_t dirty_pg_cnt; -++ atomic_long_t dirty_ino_cnt; -++ atomic_long_t dirty_zn_cnt; -++ atomic_long_t clean_zn_cnt; -++ -++ long long budg_idx_growth; -++ long long budg_data_growth; -++ long long budg_dd_growth; -++ long long budg_uncommitted_idx; -++ spinlock_t space_lock; -++ int min_idx_lebs; -++ unsigned long long old_idx_sz; -++ unsigned long long calc_idx_sz; -++ struct ubifs_lp_stats lst; -++ -++ int page_budget; -++ int inode_budget; -++ int dent_budget; -++ -++ int ref_node_alsz; -++ int mst_node_alsz; -++ int min_idx_node_sz; -++ int max_idx_node_sz; -++ long long max_inode_sz; -++ int max_znode_sz; -++ int dead_wm; -++ int dark_wm; -++ int block_cnt; -++ -++ struct ubifs_node_range ranges[UBIFS_NODE_TYPES_CNT]; -++ struct ubi_volume_desc *ubi; -++ struct ubi_device_info di; -++ struct ubi_volume_info vi; -++ -++ struct rb_root orph_tree; -++ struct list_head orph_list; -++ struct list_head orph_new; -++ struct ubifs_orphan *orph_cnext; -++ struct ubifs_orphan *orph_dnext; -++ spinlock_t orphan_lock; -++ void *orph_buf; -++ int new_orphans; -++ int cmt_orphans; -++ int tot_orphans; -++ int max_orphans; -++ int ohead_lnum; -++ int ohead_offs; -++ int no_orphs; -++ -++ struct task_struct *bgt; -++ char bgt_name[sizeof(BGT_NAME_PATTERN) + 9]; -++ int need_bgt; -++ int need_wbuf_sync; -++ -++ int gc_lnum; -++ void *sbuf; -++ struct list_head idx_gc; -++ int idx_gc_cnt; -++ -++ struct list_head infos_list; -++ struct mutex umount_mutex; -++ unsigned int shrinker_run_no; -++ -++ int space_bits; -++ int lpt_lnum_bits; -++ int lpt_offs_bits; -++ int lpt_spc_bits; -++ int pcnt_bits; -++ int lnum_bits; -++ int nnode_sz; -++ int pnode_sz; -++ int ltab_sz; -++ int lsave_sz; -++ int pnode_cnt; -++ int nnode_cnt; -++ int lpt_hght; -++ int pnodes_have; -++ -++ struct mutex lp_mutex; -++ int lpt_lnum; -++ int lpt_offs; -++ int nhead_lnum; -++ int nhead_offs; -++ int lpt_drty_flgs; -++ int dirty_nn_cnt; -++ int dirty_pn_cnt; -++ long long lpt_sz; -++ void *lpt_nod_buf; -++ void *lpt_buf; -++ struct ubifs_nnode *nroot; -++ struct ubifs_cnode *lpt_cnext; -++ struct ubifs_lpt_heap lpt_heap[LPROPS_HEAP_CNT]; -++ struct ubifs_lpt_heap dirty_idx; -++ struct list_head uncat_list; -++ struct list_head empty_list; -++ struct list_head freeable_list; -++ struct list_head frdi_idx_list; -++ int freeable_cnt; -++ -++ int ltab_lnum; -++ int ltab_offs; -++ struct ubifs_lpt_lprops *ltab; -++ struct ubifs_lpt_lprops *ltab_cmt; -++ int lsave_cnt; -++ int lsave_lnum; -++ int lsave_offs; -++ int *lsave; -++ int lscan_lnum; -++ -++ long long rp_size; -++ long long report_rp_size; -++ uid_t rp_uid; -++ gid_t rp_gid; -++ -++ /* The below fields are used only during mounting and re-mounting */ -++ int empty; -++ struct rb_root replay_tree; -++ struct list_head replay_list; -++ struct list_head replay_buds; -++ unsigned long long cs_sqnum; -++ unsigned long long replay_sqnum; -++ int need_recovery; -++ int replaying; -++ struct list_head unclean_leb_list; -++ struct ubifs_mst_node *rcvrd_mst_node; -++ struct rb_root size_tree; -++ int recovery_needs_commit; -++ int remounting_rw; -++ struct ubifs_mount_opts mount_opts; -++ -++#ifdef CONFIG_UBIFS_FS_DEBUG -++ void *dbg_buf; -++ struct ubifs_zbranch old_zroot; -++ int old_zroot_level; -++ unsigned long long old_zroot_sqnum; -++ int failure_mode; -++ int fail_delay; -++ unsigned long fail_timeout; -++ unsigned int fail_cnt; -++ unsigned int fail_cnt_max; -++#endif -++}; -++ -++extern struct list_head ubifs_infos; -++extern spinlock_t ubifs_infos_lock; -++extern atomic_long_t ubifs_clean_zn_cnt; -++extern struct kmem_cache *ubifs_inode_slab; -++extern struct super_operations ubifs_super_operations; -++extern struct address_space_operations ubifs_file_address_operations; -++extern struct file_operations ubifs_file_operations; -++extern struct inode_operations ubifs_file_inode_operations; -++extern struct file_operations ubifs_dir_operations; -++extern struct inode_operations ubifs_dir_inode_operations; -++extern struct inode_operations ubifs_symlink_inode_operations; -++extern struct backing_dev_info ubifs_backing_dev_info; -++extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; -++ -++/* io.c */ -++int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len); -++int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs, -++ int dtype); -++int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf); -++int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len, -++ int lnum, int offs); -++int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len, -++ int lnum, int offs); -++int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum, -++ int offs, int dtype); -++int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, -++ int offs, int quiet); -++void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad); -++void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last); -++int ubifs_io_init(struct ubifs_info *c); -++void ubifs_pad(const struct ubifs_info *c, void *buf, int pad); -++int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf); -++int ubifs_bg_wbufs_sync(struct ubifs_info *c); -++void ubifs_wbuf_add_ino_nolock(struct ubifs_wbuf *wbuf, ino_t inum); -++int ubifs_sync_wbufs_by_inodes(struct ubifs_info *c, -++ struct inode * const *inodes, int count); -++ -++/* scan.c */ -++struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum, -++ int offs, void *sbuf); -++void ubifs_scan_destroy(struct ubifs_scan_leb *sleb); -++int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum, -++ int offs, int quiet); -++struct ubifs_scan_leb *ubifs_start_scan(const struct ubifs_info *c, int lnum, -++ int offs, void *sbuf); -++void ubifs_end_scan(const struct ubifs_info *c, struct ubifs_scan_leb *sleb, -++ int lnum, int offs); -++int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb, -++ void *buf, int offs); -++void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs, -++ void *buf); -++ -++/* log.c */ -++void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud); -++void ubifs_create_buds_lists(struct ubifs_info *c); -++int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs); -++struct ubifs_bud *ubifs_search_bud(struct ubifs_info *c, int lnum); -++struct ubifs_wbuf *ubifs_get_wbuf(struct ubifs_info *c, int lnum); -++int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum); -++int ubifs_log_end_commit(struct ubifs_info *c, int new_ltail_lnum); -++int ubifs_log_post_commit(struct ubifs_info *c, int old_ltail_lnum); -++int ubifs_consolidate_log(struct ubifs_info *c); -++ -++/* journal.c */ -++int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, -++ const struct qstr *nm, const struct inode *inode, -++ int deletion, int sync, int xent); -++int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode, -++ const union ubifs_key *key, const void *buf, int len); -++int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode, -++ int last_reference, int sync); -++int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, -++ const struct dentry *old_dentry, -++ const struct inode *new_dir, -++ const struct dentry *new_dentry, int sync); -++int ubifs_jnl_truncate(struct ubifs_info *c, ino_t inum, -++ loff_t old_size, loff_t new_size); -++int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host, -++ const struct inode *inode, const struct qstr *nm, -++ int sync); -++int ubifs_jnl_write_2_inodes(struct ubifs_info *c, const struct inode *inode1, -++ const struct inode *inode2, int sync); -++ -++/* budget.c */ -++int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req); -++void ubifs_release_budget(struct ubifs_info *c, struct ubifs_budget_req *req); -++int ubifs_budget_inode_op(struct ubifs_info *c, struct inode *inode, -++ struct ubifs_budget_req *req); -++void ubifs_release_ino_dirty(struct ubifs_info *c, struct inode *inode, -++ struct ubifs_budget_req *req); -++void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode, -++ struct ubifs_budget_req *req); -++int ubifs_budget_ino_cleaning(struct ubifs_info *c, struct inode *inode, -++ struct ubifs_budget_req *req); -++void ubifs_release_ino_clean(struct ubifs_info *c, struct inode *inode, -++ struct ubifs_budget_req *req); -++long long ubifs_budg_get_free_space(struct ubifs_info *c); -++int ubifs_calc_min_idx_lebs(struct ubifs_info *c); -++void ubifs_convert_page_budget(struct ubifs_info *c); -++void ubifs_release_new_page_budget(struct ubifs_info *c); -++long long ubifs_calc_available(const struct ubifs_info *c); -++ -++/* find.c */ -++int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *free, -++ int squeeze); -++int ubifs_find_free_leb_for_idx(struct ubifs_info *c); -++int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp, -++ int min_space, int pick_free); -++int ubifs_find_dirty_idx_leb(struct ubifs_info *c); -++int ubifs_save_dirty_idx_lnums(struct ubifs_info *c); -++ -++/* tnc.c */ -++int ubifs_tnc_lookup(struct ubifs_info *c, const union ubifs_key *key, -++ void *node); -++int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key, -++ void *node, int *lnum, int *offs); -++int ubifs_tnc_lookup_nm(struct ubifs_info *c, const union ubifs_key *key, -++ void *node, const struct qstr *nm); -++int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum, -++ int offs, int len); -++int ubifs_tnc_replace(struct ubifs_info *c, const union ubifs_key *key, -++ int old_lnum, int old_offs, int lnum, int offs, int len); -++int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key, -++ int lnum, int offs, int len, const struct qstr *nm); -++int ubifs_tnc_remove(struct ubifs_info *c, const union ubifs_key *key); -++int ubifs_tnc_remove_nm(struct ubifs_info *c, const union ubifs_key *key, -++ const struct qstr *nm); -++int ubifs_tnc_remove_range(struct ubifs_info *c, union ubifs_key *from_key, -++ union ubifs_key *to_key); -++int ubifs_tnc_remove_ino(struct ubifs_info *c, ino_t inum); -++struct ubifs_dent_node *ubifs_tnc_next_ent(struct ubifs_info *c, -++ union ubifs_key *key, -++ const struct qstr *nm); -++void ubifs_tnc_close(struct ubifs_info *c); -++int ubifs_tnc_has_node(struct ubifs_info *c, union ubifs_key *key, int level, -++ int lnum, int offs, int is_idx); -++int ubifs_dirty_idx_node(struct ubifs_info *c, union ubifs_key *key, int level, -++ int lnum, int offs); -++/* Shared by tnc.c for tnc_commit.c */ -++void destroy_old_idx(struct ubifs_info *c); -++int is_idx_node_in_tnc(struct ubifs_info *c, union ubifs_key *key, int level, -++ int lnum, int offs); -++int insert_old_idx_znode(struct ubifs_info *c, struct ubifs_znode *znode); -++ -++/* tnc_misc.c */ -++struct ubifs_znode *ubifs_tnc_levelorder_next(struct ubifs_znode *zr, -++ struct ubifs_znode *znode); -++int ubifs_search_zbranch(const struct ubifs_info *c, -++ const struct ubifs_znode *znode, -++ const union ubifs_key *key, int *n); -++struct ubifs_znode *ubifs_tnc_postorder_first(struct ubifs_znode *znode); -++struct ubifs_znode *ubifs_tnc_postorder_next(struct ubifs_znode *znode); -++long ubifs_destroy_tnc_subtree(struct ubifs_znode *zr); -++ -++/* tnc_commit.c */ -++int ubifs_tnc_start_commit(struct ubifs_info *c, struct ubifs_zbranch *zroot); -++int ubifs_tnc_end_commit(struct ubifs_info *c); -++ -++/* shrinker.c */ -++int ubifs_shrinker(int nr_to_scan, gfp_t gfp_mask); -++ -++/* commit.c */ -++int ubifs_bg_thread(void *info); -++void ubifs_commit_required(struct ubifs_info *c); -++void ubifs_request_bg_commit(struct ubifs_info *c); -++int ubifs_run_commit(struct ubifs_info *c); -++void ubifs_recovery_commit(struct ubifs_info *c); -++int ubifs_gc_should_commit(struct ubifs_info *c); -++void ubifs_wait_for_commit(struct ubifs_info *c); -++ -++/* master.c */ -++int ubifs_read_master(struct ubifs_info *c); -++int ubifs_write_master(struct ubifs_info *c); -++ -++/* sb.c */ -++int ubifs_read_superblock(struct ubifs_info *c); -++struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c); -++int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup); -++ -++/* replay.c */ -++int ubifs_validate_entry(struct ubifs_info *c, -++ const struct ubifs_dent_node *dent); -++int ubifs_replay_journal(struct ubifs_info *c); -++ -++/* gc.c */ -++int ubifs_garbage_collect(struct ubifs_info *c, int anyway); -++int ubifs_gc_start_commit(struct ubifs_info *c); -++int ubifs_gc_end_commit(struct ubifs_info *c); -++void ubifs_destroy_idx_gc(struct ubifs_info *c); -++int ubifs_get_idx_gc_leb(struct ubifs_info *c); -++int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp); -++ -++/* orphan.c */ -++int ubifs_add_orphan(struct ubifs_info *c, ino_t inum); -++void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum); -++int ubifs_orphan_start_commit(struct ubifs_info *c); -++int ubifs_orphan_end_commit(struct ubifs_info *c); -++int ubifs_mount_orphans(struct ubifs_info *c, int unclean); -++ -++/* lpt.c */ -++int ubifs_calc_lpt_geom(struct ubifs_info *c); -++int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, -++ int *lpt_lebs, int *big_lpt); -++int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr); -++struct ubifs_lprops *ubifs_lpt_lookup(struct ubifs_info *c, int lnum); -++struct ubifs_lprops *ubifs_lpt_lookup_dirty(struct ubifs_info *c, int lnum); -++int ubifs_lpt_scan_nolock(struct ubifs_info *c, int start_lnum, int end_lnum, -++ ubifs_lpt_scan_callback scan_cb, void *data); -++ -++/* Shared by lpt.c for lpt_commit.c */ -++void ubifs_pack_lsave(struct ubifs_info *c, void *buf, int *lsave); -++void ubifs_pack_ltab(struct ubifs_info *c, void *buf, -++ struct ubifs_lpt_lprops *ltab); -++void ubifs_pack_pnode(struct ubifs_info *c, void *buf, -++ struct ubifs_pnode *pnode); -++void ubifs_pack_nnode(struct ubifs_info *c, void *buf, -++ struct ubifs_nnode *nnode); -++struct ubifs_pnode *ubifs_get_pnode(struct ubifs_info *c, -++ struct ubifs_nnode *parent, int iip); -++struct ubifs_nnode *ubifs_get_nnode(struct ubifs_info *c, -++ struct ubifs_nnode *parent, int iip); -++int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip); -++void ubifs_add_lpt_dirt(struct ubifs_info *c, int lnum, int dirty); -++void ubifs_add_nnode_dirt(struct ubifs_info *c, struct ubifs_nnode *nnode); -++uint32_t ubifs_unpack_bits(uint8_t **addr, int *pos, int nrbits); -++struct ubifs_nnode *ubifs_first_nnode(struct ubifs_info *c, int *hght); -++ -++/* lpt_commit.c */ -++int ubifs_lpt_start_commit(struct ubifs_info *c); -++int ubifs_lpt_end_commit(struct ubifs_info *c); -++int ubifs_lpt_post_commit(struct ubifs_info *c); -++void ubifs_lpt_free(struct ubifs_info *c, int wr_only); -++ -++/* lprops.c */ -++void ubifs_get_lprops(struct ubifs_info *c); -++const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c, -++ const struct ubifs_lprops *lp, -++ int free, int dirty, int flags, -++ int idx_gc_cnt); -++void ubifs_release_lprops(struct ubifs_info *c); -++void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *stats); -++void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops, -++ int cat); -++void ubifs_replace_cat(struct ubifs_info *c, struct ubifs_lprops *old_lprops, -++ struct ubifs_lprops *new_lprops); -++void ubifs_ensure_cat(struct ubifs_info *c, struct ubifs_lprops *lprops); -++int ubifs_categorize_lprops(const struct ubifs_info *c, -++ const struct ubifs_lprops *lprops); -++int ubifs_change_one_lp(struct ubifs_info *c, int lnum, int free, int dirty, -++ int flags_set, int flags_clean, int idx_gc_cnt); -++int ubifs_update_one_lp(struct ubifs_info *c, int lnum, int free, int dirty, -++ int flags_set, int flags_clean); -++int ubifs_read_one_lp(struct ubifs_info *c, int lnum, struct ubifs_lprops *lp); -++const struct ubifs_lprops *ubifs_fast_find_free(struct ubifs_info *c); -++const struct ubifs_lprops *ubifs_fast_find_empty(struct ubifs_info *c); -++const struct ubifs_lprops *ubifs_fast_find_freeable(struct ubifs_info *c); -++const struct ubifs_lprops *ubifs_fast_find_frdi_idx(struct ubifs_info *c); -++ -++/* file.c */ -++int ubifs_fsync(struct file *file, struct dentry *dentry, int datasync); -++int ubifs_setattr(struct dentry *dentry, struct iattr *attr); -++ -++/* dir.c */ -++struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir, -++ int mode); -++int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry, -++ struct kstat *stat); -++ -++/* xattr.c */ -++int ubifs_setxattr(struct dentry *dentry, const char *name, -++ const void *value, size_t size, int flags); -++ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf, -++ size_t size); -++ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size); -++int ubifs_removexattr(struct dentry *dentry, const char *name); -++ -++/* super.c */ -++struct inode *ubifs_iget(struct super_block *sb, unsigned long inum); -++ -++/* recovery.c */ -++int ubifs_recover_master_node(struct ubifs_info *c); -++int ubifs_write_rcvrd_mst_node(struct ubifs_info *c); -++struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, -++ int offs, void *sbuf, int grouped); -++struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum, -++ int offs, void *sbuf); -++int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf); -++int ubifs_clean_lebs(const struct ubifs_info *c, void *sbuf); -++int ubifs_recover_gc_lnum(struct ubifs_info *c); -++int ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key, -++ int deletion, loff_t new_size); -++int ubifs_recover_size(struct ubifs_info *c); -++void ubifs_destroy_size_tree(struct ubifs_info *c); -++ -++/* ioctl.c */ -++long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -++void ubifs_set_inode_flags(struct inode *inode); -++#ifdef CONFIG_COMPAT -++long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -++#endif -++ -++/* compressor.c */ -++int __init ubifs_compressors_init(void); -++void __exit ubifs_compressors_exit(void); -++void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len, -++ int *compr_type); -++int ubifs_decompress(const void *buf, int len, void *out, int *out_len, -++ int compr_type); -++ -++#include "debug.h" -++#include "misc.h" -++#include "key.h" -++ -++#endif /* !__UBIFS_H__ */ -+diff -urN linux-2.6.24.7.old/fs/ubifs/xattr.c linux-2.6.24.7/fs/ubifs/xattr.c -+--- linux-2.6.24.7.old/fs/ubifs/xattr.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/fs/ubifs/xattr.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,582 @@ -++/* -++ * This file is part of UBIFS. -++ * -++ * Copyright (C) 2006-2008 Nokia Corporation. -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License version 2 as published by -++ * the Free Software Foundation. -++ * -++ * This program is distributed in the hope that it will be useful, but WITHOUT -++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -++ * more details. -++ * -++ * You should have received a copy of the GNU General Public License along with -++ * this program; if not, write to the Free Software Foundation, Inc., 51 -++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -++ * -++ * Authors: Artem Bityutskiy (Битюцкий Ðртём) -++ * Adrian Hunter -++ */ -++ -++/* -++ * This file implements UBIFS extended attributes support. -++ * -++ * Extended attributes are implemented as regular inodes with attached data, -++ * which limits extended attribute size to UBIFS block size (4KiB). Names of -++ * extended attributes are described by extended attribute entries (xentries), -++ * which are almost identical to directory entries, but have different key type. -++ * -++ * In other words, the situation with extended attributes is very similar to -++ * directories. Indeed, any inode (but of course not xattr inodes) may have a -++ * number of associated xentries, just like directory inodes have associated -++ * directory entries. Extended attribute entries store the name of the extended -++ * attribute, the host inode number, and the extended attribute inode number. -++ * Similarly, direntries store the name, the parent and the target inode -++ * numbers. Thus, most of the common UBIFS mechanisms may be re-used for -++ * extended attributes. -++ * -++ * The number of extended attributes is not limited, but there is Linux -++ * limitation on the maximum possible size of the list of all extended -++ * attributes associated with an inode (%XATTR_LIST_MAX), so UBIFS makes sure -++ * the sum of all extended attribute names of the inode does not exceed that -++ * limit. -++ * -++ * Extended attributes are synchronous, which means they are written to the -++ * flash media synchronously and there is no write-back for extended attribute -++ * inodes. The extended attribute values are not stored in compressed form on -++ * the media. -++ * -++ * Since extended attributes are represented by regular inodes, they are cached -++ * in the VFS inode cache. The xentries are cached in the LNC cache (see -++ * tnc.c). -++ * -++ * ACL support is not implemented. -++ */ -++ -++#include -++#include -++#include "ubifs.h" -++ -++/* How many bytes an extended attribute adds to the host inode */ -++#define CALC_XATTR_BYTES(data_len) ALIGN(UBIFS_INO_NODE_SZ + (data_len) + 1, 8) -++ -++/* -++ * Extended attribute type constants. -++ * -++ * USER_XATTR: user extended attribute ("user.*") -++ * TRUSTED_XATTR: trusted extended attribute ("trusted.*) -++ * SECURITY_XATTR: security extended attribute ("security.*") -++ */ -++enum { -++ USER_XATTR, -++ TRUSTED_XATTR, -++ SECURITY_XATTR, -++}; -++ -++static struct inode_operations none_inode_operations; -++static struct address_space_operations none_address_operations; -++static struct file_operations none_file_operations; -++ -++/** -++ * create_xattr - create an extended attribute. -++ * @c: UBIFS file-system description object -++ * @host: host inode -++ * @nm: extended attribute name -++ * @value: extended attribute value -++ * @size: size of extended attribute value -++ * -++ * This is a helper function which creates an extended attribute of name @nm -++ * and value @value for inode @host. The host inode is also updated on flash -++ * because the ctime and extended attribute accounting data changes. This -++ * function returns zero in case of success and a negative error code in case -++ * of failure. -++ */ -++static int create_xattr(struct ubifs_info *c, struct inode *host, -++ const struct qstr *nm, const void *value, int size) -++{ -++ struct ubifs_inode *ui, *host_ui = ubifs_inode(host); -++ struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, -++ .new_ino_d = size }; -++ struct inode *inode; -++ int err; -++ -++ /* -++ * Linux limits the maximum size of the extended attribute names list -++ * to %XATTR_LIST_MAX. This means we should not allow creating more* -++ * extended attributes if the name list becomes larger. This limitation -++ * is artificial for UBIFS, though. -++ */ -++ if (host_ui->xattr_names + host_ui->xattr_cnt + -++ nm->len + 1 > XATTR_LIST_MAX) -++ return -ENOSPC; -++ -++ err = ubifs_budget_inode_op(c, host, &req); -++ if (err) -++ return err; -++ -++ inode = ubifs_new_inode(c, host, S_IFREG | S_IRWXUGO); -++ if (IS_ERR(inode)) { -++ err = PTR_ERR(inode); -++ goto out_budg; -++ } -++ -++ /* Re-define all operations to be "nothing" */ -++ inode->i_mapping->a_ops = &none_address_operations; -++ inode->i_op = &none_inode_operations; -++ inode->i_fop = &none_file_operations; -++ -++ inode->i_flags |= S_SYNC | S_NOATIME | S_NOCMTIME | S_NOQUOTA; -++ ui = ubifs_inode(inode); -++ ui->xattr = 1; -++ ui->data = kmalloc(size, GFP_NOFS); -++ if (!ui->data) { -++ err = -ENOMEM; -++ goto out_inode; -++ } -++ -++ memcpy(ui->data, value, size); -++ host->i_ctime = ubifs_current_time(host); -++ host_ui->xattr_cnt += 1; -++ spin_lock(&host->i_lock); -++ host_ui->xattr_size += CALC_DENT_SIZE(nm->len); -++ host_ui->xattr_size += CALC_XATTR_BYTES(size); -++ spin_unlock(&host->i_lock); -++ host_ui->xattr_names += nm->len; -++ -++ /* -++ * We do not use i_size_write() because nobody can race with us as we -++ * are holding host @host->i_mutex - every xattr operation for this -++ * inode is serialized by it. -++ */ -++ inode->i_size = size; -++ ui->data_len = size; -++ -++ /* -++ * Note, it is important that 'ubifs_jnl_update()' writes the @host -++ * inode last, so when it gets synchronized and the write-buffer is -++ * flushed, the extended attribute is flushed as well. -++ */ -++ err = ubifs_jnl_update(c, host, nm, inode, 0, IS_DIRSYNC(host), 1); -++ if (err) -++ goto out_cancel; -++ -++ ubifs_release_ino_clean(c, host, &req); -++ insert_inode_hash(inode); -++ iput(inode); -++ return 0; -++ -++out_cancel: -++ host_ui->xattr_cnt -= 1; -++ spin_lock(&host->i_lock); -++ host_ui->xattr_size -= CALC_DENT_SIZE(nm->len); -++ host_ui->xattr_size -= CALC_XATTR_BYTES(size); -++ spin_unlock(&host->i_lock); -++out_inode: -++ make_bad_inode(inode); -++ iput(inode); -++out_budg: -++ ubifs_cancel_ino_op(c, host, &req); -++ return err; -++} -++ -++/** -++ * change_xattr - change an extended attribute. -++ * @c: UBIFS file-system description object -++ * @host: host inode -++ * @inode: extended attribute inode -++ * @value: extended attribute value -++ * @size: size of extended attribute value -++ * -++ * This helper function changes the value of extended attribute @inode with new -++ * data from @value. Returns zero in case of success and a negative error code -++ * in case of failure. -++ */ -++static int change_xattr(struct ubifs_info *c, struct inode *host, -++ struct inode *inode, const void *value, int size) -++{ -++ struct ubifs_inode *host_ui = ubifs_inode(host); -++ struct ubifs_inode *ui = ubifs_inode(inode); -++ struct ubifs_budget_req req = { .dirtied_ino = 1, -++ .dirtied_ino_d = ui->data_len }; -++ int err; -++ -++ ubifs_assert(ui->data_len == inode->i_size); -++ -++ err = ubifs_budget_inode_op(c, host, &req); -++ if (err) -++ return err; -++ -++ host->i_ctime = ubifs_current_time(host); -++ spin_lock(&host->i_lock); -++ host_ui->xattr_size -= CALC_XATTR_BYTES(ui->data_len); -++ host_ui->xattr_size += CALC_XATTR_BYTES(size); -++ spin_unlock(&host->i_lock); -++ -++ kfree(ui->data); -++ ui->data = kmalloc(size, GFP_NOFS); -++ if (!ui->data) { -++ err = -ENOMEM; -++ goto out_budg; -++ } -++ -++ memcpy(ui->data, value, size); -++ inode->i_size = size; -++ ui->data_len = size; -++ -++ /* -++ * It is important to write the host inode after the xattr inode -++ * because if the host inode gets synchronized, then the extended -++ * attribute inode gets synchronized, because it goes before the host -++ * inode in the write-buffer. -++ */ -++ err = ubifs_jnl_write_2_inodes(c, inode, host, IS_DIRSYNC(host)); -++ if (err) -++ goto out_cancel; -++ -++ ubifs_release_ino_clean(c, host, &req); -++ return 0; -++ -++out_cancel: -++ spin_lock(&host->i_lock); -++ host_ui->xattr_size -= CALC_XATTR_BYTES(size); -++ host_ui->xattr_size += CALC_XATTR_BYTES(ui->data_len); -++ spin_unlock(&host->i_lock); -++ make_bad_inode(inode); -++out_budg: -++ ubifs_cancel_ino_op(c, host, &req); -++ return err; -++} -++ -++/** -++ * check_namespace - check extended attribute name-space. -++ * @nm: extended attribute name -++ * -++ * This function makes sure the extended attribute name belongs to one of the -++ * supported extended attribute name-spaces. Returns name-space index in case -++ * of success and a negative error code in case of failure. -++ */ -++static int check_namespace(const struct qstr *nm) -++{ -++ int type; -++ -++ if (nm->len > UBIFS_MAX_NLEN) -++ return -ENAMETOOLONG; -++ -++ if (!strncmp(nm->name, XATTR_TRUSTED_PREFIX, -++ XATTR_TRUSTED_PREFIX_LEN)) { -++ if (nm->name[sizeof(XATTR_TRUSTED_PREFIX) - 1] == '\0') -++ return -EINVAL; -++ type = TRUSTED_XATTR; -++ } else if (!strncmp(nm->name, XATTR_USER_PREFIX, -++ XATTR_USER_PREFIX_LEN)) { -++ if (nm->name[XATTR_USER_PREFIX_LEN] == '\0') -++ return -EINVAL; -++ type = USER_XATTR; -++ } else if (!strncmp(nm->name, XATTR_SECURITY_PREFIX, -++ XATTR_SECURITY_PREFIX_LEN)) { -++ if (nm->name[sizeof(XATTR_SECURITY_PREFIX) - 1] == '\0') -++ return -EINVAL; -++ type = SECURITY_XATTR; -++ } else -++ return -EOPNOTSUPP; -++ -++ return type; -++} -++ -++int ubifs_setxattr(struct dentry *dentry, const char *name, -++ const void *value, size_t size, int flags) -++{ -++ struct inode *inode, *host = dentry->d_inode; -++ struct ubifs_info *c = host->i_sb->s_fs_info; -++ struct qstr nm = { .name = name, .len = strlen(name) }; -++ struct ubifs_dent_node *xent; -++ union ubifs_key key; -++ int err, type; -++ -++ dbg_gen("xattr '%s', host ino %lu ('%.*s'), size %zd", name, -++ host->i_ino, dentry->d_name.len, dentry->d_name.name, size); -++ ubifs_assert(ubifs_inode(host)->xattr_cnt >= 0); -++ ubifs_assert(ubifs_inode(host)->xattr_size >= 0); -++ ubifs_assert(ubifs_inode(host)->xattr_names >= 0); -++ -++ if (size > UBIFS_MAX_INO_DATA) -++ return -ERANGE; -++ -++ type = check_namespace(&nm); -++ if (type < 0) -++ return type; -++ -++ xent = kmalloc(UBIFS_MAX_XENT_NODE_SZ, GFP_NOFS); -++ if (!xent) -++ return -ENOMEM; -++ -++ /* -++ * The extended attribute entries are stored in LNC, so multiple -++ * look-ups do not involve reading the flash. -++ */ -++ xent_key_init(c, &key, host->i_ino, &nm); -++ err = ubifs_tnc_lookup_nm(c, &key, xent, &nm); -++ if (err) { -++ if (err != -ENOENT) -++ goto out_free; -++ -++ if (flags & XATTR_REPLACE) -++ /* We are asked not to create the xattr */ -++ err = -ENODATA; -++ else -++ err = create_xattr(c, host, &nm, value, size); -++ goto out_free; -++ } -++ -++ if (flags & XATTR_CREATE) { -++ /* We are asked not to replace the xattr */ -++ err = -EEXIST; -++ goto out_free; -++ } -++ -++ inode = ubifs_iget(c->vfs_sb, le64_to_cpu(xent->inum)); -++ if (IS_ERR(inode)) { -++ ubifs_err("dead extended attribute entry, error %d", err); -++ ubifs_ro_mode(c, err); -++ err = PTR_ERR(inode); -++ goto out_free; -++ } -++ -++ err = change_xattr(c, host, inode, value, size); -++ iput(inode); -++ -++out_free: -++ kfree(xent); -++ return err; -++} -++ -++ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf, -++ size_t size) -++{ -++ struct inode *inode, *host = dentry->d_inode; -++ struct ubifs_info *c = host->i_sb->s_fs_info; -++ struct qstr nm = { .name = name, .len = strlen(name) }; -++ struct ubifs_inode *ui; -++ struct ubifs_dent_node *xent; -++ union ubifs_key key; -++ int err; -++ -++ dbg_gen("xattr '%s', ino %lu ('%.*s'), buf size %zd", name, -++ host->i_ino, dentry->d_name.len, dentry->d_name.name, size); -++ ubifs_assert(ubifs_inode(host)->xattr_cnt >= 0); -++ ubifs_assert(ubifs_inode(host)->xattr_size >= 0); -++ ubifs_assert(ubifs_inode(host)->xattr_names >= 0); -++ -++ err = check_namespace(&nm); -++ if (err < 0) -++ return err; -++ -++ xent = kmalloc(UBIFS_MAX_XENT_NODE_SZ, GFP_NOFS); -++ if (!xent) -++ return -ENOMEM; -++ -++ mutex_lock(&host->i_mutex); -++ xent_key_init(c, &key, host->i_ino, &nm); -++ err = ubifs_tnc_lookup_nm(c, &key, xent, &nm); -++ if (err) { -++ if (err == -ENOENT) -++ err = -ENODATA; -++ goto out_unlock; -++ } -++ -++ inode = ubifs_iget(c->vfs_sb, le64_to_cpu(xent->inum)); -++ if (IS_ERR(inode)) { -++ ubifs_err("dead extended attribute entry, error %d", err); -++ ubifs_ro_mode(c, err); -++ err = PTR_ERR(inode); -++ goto out_unlock; -++ } -++ -++ ui = ubifs_inode(inode); -++ ubifs_assert(inode->i_size == ui->data_len); -++ ubifs_assert(ubifs_inode(host)->xattr_size > ui->data_len); -++ -++ if (buf) { -++ /* If @buf is %NULL we are supposed to return the length */ -++ if (ui->data_len > size) { -++ dbg_err("buffer size %zd, xattr len %d", -++ size, ui->data_len); -++ err = -ERANGE; -++ goto out_iput; -++ } -++ -++ memcpy(buf, ui->data, ui->data_len); -++ } -++ err = ui->data_len; -++ -++out_iput: -++ iput(inode); -++out_unlock: -++ mutex_unlock(&host->i_mutex); -++ kfree(xent); -++ return err; -++} -++ -++ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size) -++{ -++ struct inode *host = dentry->d_inode; -++ struct ubifs_info *c = host->i_sb->s_fs_info; -++ struct ubifs_inode *host_ui = ubifs_inode(host); -++ union ubifs_key key; -++ struct ubifs_dent_node *xent, *pxent = NULL; -++ int err, len, written = 0; -++ struct qstr nm = { .name = NULL }; -++ -++ dbg_gen("ino %lu ('%.*s'), buffer size %zd", host->i_ino, -++ dentry->d_name.len, dentry->d_name.name, size); -++ ubifs_assert(host_ui->xattr_cnt >= 0); -++ ubifs_assert(host_ui->xattr_size >= 0); -++ ubifs_assert(host_ui->xattr_names >= 0); -++ -++ len = host_ui->xattr_names + host_ui->xattr_cnt; -++ if (!buffer) -++ /* -++ * We should return the minimum buffer size which will fit a -++ * null-terminated list of all the extended attribute names. -++ */ -++ return len; -++ -++ if (len > size) -++ return -ERANGE; -++ -++ lowest_xent_key(c, &key, host->i_ino); -++ -++ mutex_lock(&host->i_mutex); -++ while (1) { -++ int type; -++ -++ xent = ubifs_tnc_next_ent(c, &key, &nm); -++ if (unlikely(IS_ERR(xent))) { -++ err = PTR_ERR(xent); -++ break; -++ } -++ -++ nm.name = xent->name; -++ nm.len = le16_to_cpu(xent->nlen); -++ -++ type = check_namespace(&nm); -++ if (unlikely(type < 0)) { -++ err = type; -++ break; -++ } -++ -++ /* Show trusted namespace only for "power" users */ -++ if (type != TRUSTED_XATTR || capable(CAP_SYS_ADMIN)) { -++ memcpy(buffer + written, nm.name, nm.len + 1); -++ written += nm.len + 1; -++ } -++ -++ kfree(pxent); -++ pxent = xent; -++ key_read(c, &xent->key, &key); -++ } -++ mutex_unlock(&host->i_mutex); -++ -++ kfree(pxent); -++ if (err != -ENOENT) { -++ ubifs_err("cannot find next direntry, error %d", err); -++ return err; -++ } -++ -++ ubifs_assert(written <= size); -++ return written; -++} -++ -++static int remove_xattr(struct ubifs_info *c, struct inode *host, -++ struct inode *inode, const struct qstr *nm) -++{ -++ struct ubifs_inode *host_ui = ubifs_inode(host); -++ struct ubifs_inode *ui = ubifs_inode(inode); -++ struct ubifs_budget_req req = { .dirtied_ino = 1, .mod_dent = 1 }; -++ int err; -++ -++ ubifs_assert(ui->data_len == inode->i_size); -++ -++ err = ubifs_budget_inode_op(c, host, &req); -++ if (err) -++ return err; -++ -++ host->i_ctime = ubifs_current_time(host); -++ host_ui->xattr_cnt -= 1; -++ spin_lock(&host->i_lock); -++ host_ui->xattr_size -= CALC_XATTR_BYTES(ui->data_len); -++ spin_unlock(&host->i_lock); -++ host_ui->xattr_names -= nm->len; -++ -++ err = ubifs_jnl_delete_xattr(c, host, inode, nm, IS_DIRSYNC(host)); -++ if (err) -++ goto out_cancel; -++ -++ ubifs_release_ino_clean(c, host, &req); -++ return 0; -++ -++out_cancel: -++ ubifs_cancel_ino_op(c, host, &req); -++ host_ui->xattr_cnt += 1; -++ spin_lock(&host->i_lock); -++ host_ui->xattr_size += CALC_XATTR_BYTES(ui->data_len); -++ spin_unlock(&host->i_lock); -++ make_bad_inode(inode); -++ return err; -++} -++ -++int ubifs_removexattr(struct dentry *dentry, const char *name) -++{ -++ struct inode *inode, *host = dentry->d_inode; -++ struct ubifs_info *c = host->i_sb->s_fs_info; -++ struct qstr nm = { .name = name, .len = strlen(name) }; -++ struct ubifs_dent_node *xent; -++ union ubifs_key key; -++ int err; -++ -++ dbg_gen("xattr '%s', ino %lu ('%.*s')", name, -++ host->i_ino, dentry->d_name.len, dentry->d_name.name); -++ ubifs_assert(mutex_is_locked(&host->i_mutex)); -++ ubifs_assert(ubifs_inode(host)->xattr_cnt >= 0); -++ ubifs_assert(ubifs_inode(host)->xattr_size >= 0); -++ ubifs_assert(ubifs_inode(host)->xattr_names >= 0); -++ -++ err = check_namespace(&nm); -++ if (err < 0) -++ return err; -++ -++ xent = kmalloc(UBIFS_MAX_XENT_NODE_SZ, GFP_NOFS); -++ if (!xent) -++ return -ENOMEM; -++ -++ xent_key_init(c, &key, host->i_ino, &nm); -++ err = ubifs_tnc_lookup_nm(c, &key, xent, &nm); -++ if (err) { -++ if (err == -ENOENT) -++ err = -ENODATA; -++ goto out_free; -++ } -++ -++ inode = ubifs_iget(c->vfs_sb, le64_to_cpu(xent->inum)); -++ if (IS_ERR(inode)) { -++ ubifs_err("dead extended attribute node entry"); -++ ubifs_ro_mode(c, err); -++ err = PTR_ERR(inode); -++ goto out_free; -++ } -++ -++ ubifs_assert(inode->i_nlink == 1); -++ inode->i_nlink = 0; -++ err = remove_xattr(c, host, inode, &nm); -++ if (err) -++ inode->i_nlink = 1; -++ -++ /* If @i_nlink is 0, 'iput()' will delete the inode */ -++ iput(inode); -++ -++out_free: -++ kfree(xent); -++ return err; -++} -+diff -urN linux-2.6.24.7.old/include/asm-mips/bootinfo.h linux-2.6.24.7/include/asm-mips/bootinfo.h -+--- linux-2.6.24.7.old/include/asm-mips/bootinfo.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/include/asm-mips/bootinfo.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -198,6 +198,14 @@ -+ #define MACH_GROUP_BRCM 23 /* Broadcom */ -+ #define MACH_BCM47XX 1 /* Broadcom BCM47XX */ -+ -++/* -++ * Valid machtype for group INGENIC -++ */ -++#define MACH_INGENIC_JZ4730 0 /* JZ4730 SOC */ -++#define MACH_INGENIC_JZ4740 1 /* JZ4740 SOC */ -++#define MACH_INGENIC_JZ4750 2 /* JZ4750 SOC */ -++#define MACH_INGENIC_JZ4750D 3 /* JZ4750D SOC */ -++ -+ #define CL_SIZE COMMAND_LINE_SIZE -+ -+ const char *get_system_type(void); -+diff -urN linux-2.6.24.7.old/include/asm-mips/cpu.h linux-2.6.24.7/include/asm-mips/cpu.h -+--- linux-2.6.24.7.old/include/asm-mips/cpu.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/include/asm-mips/cpu.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -33,6 +33,7 @@ -+ #define PRID_COMP_TOSHIBA 0x070000 -+ #define PRID_COMP_LSI 0x080000 -+ #define PRID_COMP_LEXRA 0x0b0000 -++#define PRID_COMP_INGENIC 0xd00000 -+ -+ -+ /* -+@@ -113,6 +114,12 @@ -+ #define PRID_IMP_BCM3302 0x9000 -+ -+ /* -++ * These are the PRID's for when 23:16 == PRID_COMP_INGENIC -++ */ -++ -++#define PRID_IMP_JZRISC 0x0200 -++ -++/* -+ * Definitions for 7:0 on legacy processors -+ */ -+ -+@@ -203,6 +210,11 @@ -+ */ -+ CPU_5KC, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2, -+ -++ /* -++ * Ingenic class processors -++ */ -++ CPU_JZRISC, CPU_XBURST, -++ -+ CPU_LAST -+ }; -+ -+diff -urN linux-2.6.24.7.old/include/asm-mips/jzsoc.h linux-2.6.24.7/include/asm-mips/jzsoc.h -+--- linux-2.6.24.7.old/include/asm-mips/jzsoc.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/jzsoc.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,49 @@ -++/* -++ * linux/include/asm-mips/jzsoc.h -++ * -++ * Ingenic's JZXXXX SoC common include. -++ * -++ * Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZSOC_H__ -++#define __ASM_JZSOC_H__ -++ -++/* -++ * SoC include -++ */ -++ -++#ifdef CONFIG_SOC_JZ4730 -++#include -++#endif -++ -++#ifdef CONFIG_SOC_JZ4740 -++#include -++#endif -++ -++#ifdef CONFIG_SOC_JZ4750 -++#include -++#endif -++ -++#ifdef CONFIG_SOC_JZ4750D -++#include -++#endif -++ -++/* -++ * Generic I/O routines -++ */ -++#define readb(addr) (*(volatile unsigned char *)(addr)) -++#define readw(addr) (*(volatile unsigned short *)(addr)) -++#define readl(addr) (*(volatile unsigned int *)(addr)) -++ -++#define writeb(b,addr) ((*(volatile unsigned char *)(addr)) = (b)) -++#define writew(b,addr) ((*(volatile unsigned short *)(addr)) = (b)) -++#define writel(b,addr) ((*(volatile unsigned int *)(addr)) = (b)) -++ -++#endif /* __ASM_JZSOC_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-generic/irq.h linux-2.6.24.7/include/asm-mips/mach-generic/irq.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-generic/irq.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/include/asm-mips/mach-generic/irq.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -9,7 +9,7 @@ -+ #define __ASM_MACH_GENERIC_IRQ_H -+ -+ #ifndef NR_IRQS -+-#define NR_IRQS 128 -++#define NR_IRQS 256 -+ #endif -+ -+ #ifdef CONFIG_I8259 -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4730/board-pmp.h linux-2.6.24.7/include/asm-mips/mach-jz4730/board-pmp.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4730/board-pmp.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4730/board-pmp.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,83 @@ -++/* -++ * linux/include/asm-mips/mach-jz4730/board-pmp.h -++ * -++ * JZ4730-based PMP board ver 2.x definition. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4730_PMP_H__ -++#define __ASM_JZ4730_PMP_H__ -++ -++/*====================================================================== -++ * EXTAL frequency -++ */ -++#define JZ_EXTAL 12000000 /* EXTAL: 12 MHz */ -++#define JZ_EXTAL2 32768 /* EXTAL2: 32.768 KHz */ -++ -++ -++/*====================================================================== -++ * GPIO -++ */ -++#define GPIO_PW_I 97 -++#define GPIO_PW_O 66 -++#define GPIO_LED_EN 92 -++#define GPIO_DISP_OFF_N 93 -++#define GPIO_PWM0 94 -++#define GPIO_RTC_IRQ 96 -++#define GPIO_USB_CLK_EN 29 -++#define GPIO_CHARG_STAT 125 -++#define GPIO_TS_PENIRQ 98 -++#define GPIO_UDC_HOTPLUG 86 -++ -++/*====================================================================== -++ * MMC/SD -++ */ -++#define MSC_WP_PIN 82 -++#define MSC_POWEREN_PIN 91 -++#define MSC_HOTPLUG_PIN 90 -++#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + MSC_HOTPLUG_PIN) -++ -++/* enable slot power */ -++#define __msc_init_io() \ -++do { \ -++ __gpio_as_input(MSC_WP_PIN); \ -++ __gpio_as_output(MSC_POWEREN_PIN); \ -++} while (0) -++ -++/* enable slot power */ -++#define __msc_enable_power() \ -++do { \ -++ __gpio_clear_pin(MSC_POWEREN_PIN); \ -++} while (0) -++ -++/* disable slot power */ -++#define __msc_disable_power() \ -++do { \ -++ __gpio_set_pin(MSC_POWEREN_PIN); \ -++} while (0) -++ -++/* detect card insertion or not */ -++#define __msc_card_detected(slot) \ -++({ \ -++ int ret; \ -++ if (slot == 0) { \ -++ __gpio_mask_irq(MSC_HOTPLUG_IRQ); \ -++ __gpio_as_input(MSC_HOTPLUG_PIN); \ -++ ret = __gpio_get_pin(MSC_HOTPLUG_PIN); \ -++ __gpio_unmask_irq(MSC_HOTPLUG_IRQ); \ -++ } \ -++ else { \ -++ ret = 1; \ -++ } \ -++ ret = !ret; \ -++ ret; \ -++}) -++ -++#endif /* __ASM_JZ4730_PMP_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4730/clock.h linux-2.6.24.7/include/asm-mips/mach-jz4730/clock.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4730/clock.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4730/clock.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,184 @@ -++/* -++ * linux/include/asm-mips/mach-jz4730/clock.h -++ * -++ * JZ4730 clocks definition. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4730_CLOCK_H__ -++#define __ASM_JZ4730_CLOCK_H__ -++ -++#ifndef JZ_EXTAL -++#define JZ_EXTAL 3686400 -++#endif -++ -++#ifndef JZ_EXTAL2 -++#define JZ_EXTAL2 32768 -++#endif -++ -++/* -++ * JZ4730 clocks structure -++ */ -++typedef struct { -++ unsigned int iclk; /* CPU core clock */ -++ unsigned int sclk; /* AHB bus clock */ -++ unsigned int mclk; /* Memory bus clock */ -++ unsigned int pclk; /* APB bus clock */ -++ unsigned int devclk; /* Devcie clock to specific modules */ -++ unsigned int rtcclk; /* RTC module clock */ -++ unsigned int uartclk; /* UART module clock */ -++ unsigned int lcdclk; /* LCD module clock */ -++ unsigned int pixclk; /* LCD pixel clock */ -++ unsigned int usbclk; /* USB module clock */ -++ unsigned int i2sclk; /* I2S module clock */ -++ unsigned int mscclk; /* MMC/SD module clock */ -++} jz_clocks_t; -++ -++extern jz_clocks_t jz_clocks; -++ -++ -++static __inline__ unsigned int __cpm_get_pllout(void) -++{ -++ unsigned int nf, nr, no, pllout; -++ unsigned long plcr = REG_CPM_PLCR1; -++ unsigned long od[4] = {1, 2, 2, 4}; -++ if (plcr & CPM_PLCR1_PLL1EN) { -++ nf = (plcr & CPM_PLCR1_PLL1FD_MASK) >> CPM_PLCR1_PLL1FD_BIT; -++ nr = (plcr & CPM_PLCR1_PLL1RD_MASK) >> CPM_PLCR1_PLL1RD_BIT; -++ no = od[((plcr & CPM_PLCR1_PLL1OD_MASK) >> CPM_PLCR1_PLL1OD_BIT)]; -++ pllout = (JZ_EXTAL) / ((nr+2) * no) * (nf+2); -++ } else -++ pllout = JZ_EXTAL; -++ return pllout; -++} -++ -++static __inline__ unsigned int __cpm_get_iclk(void) -++{ -++ unsigned int iclk; -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ unsigned long cfcr = REG_CPM_CFCR; -++ unsigned long plcr = REG_CPM_PLCR1; -++ if (plcr & CPM_PLCR1_PLL1EN) -++ iclk = __cpm_get_pllout() / -++ div[(cfcr & CPM_CFCR_IFR_MASK) >> CPM_CFCR_IFR_BIT]; -++ else -++ iclk = JZ_EXTAL; -++ return iclk; -++} -++ -++static __inline__ unsigned int __cpm_get_sclk(void) -++{ -++ unsigned int sclk; -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ unsigned long cfcr = REG_CPM_CFCR; -++ unsigned long plcr = REG_CPM_PLCR1; -++ if (plcr & CPM_PLCR1_PLL1EN) -++ sclk = __cpm_get_pllout() / -++ div[(cfcr & CPM_CFCR_SFR_MASK) >> CPM_CFCR_SFR_BIT]; -++ else -++ sclk = JZ_EXTAL; -++ return sclk; -++} -++ -++static __inline__ unsigned int __cpm_get_mclk(void) -++{ -++ unsigned int mclk; -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ unsigned long cfcr = REG_CPM_CFCR; -++ unsigned long plcr = REG_CPM_PLCR1; -++ if (plcr & CPM_PLCR1_PLL1EN) -++ mclk = __cpm_get_pllout() / -++ div[(cfcr & CPM_CFCR_MFR_MASK) >> CPM_CFCR_MFR_BIT]; -++ else -++ mclk = JZ_EXTAL; -++ return mclk; -++} -++ -++static __inline__ unsigned int __cpm_get_pclk(void) -++{ -++ unsigned int devclk; -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ unsigned long cfcr = REG_CPM_CFCR; -++ unsigned long plcr = REG_CPM_PLCR1; -++ if (plcr & CPM_PLCR1_PLL1EN) -++ devclk = __cpm_get_pllout() / -++ div[(cfcr & CPM_CFCR_PFR_MASK) >> CPM_CFCR_PFR_BIT]; -++ else -++ devclk = JZ_EXTAL; -++ return devclk; -++} -++ -++static __inline__ unsigned int __cpm_get_lcdclk(void) -++{ -++ unsigned int lcdclk; -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ unsigned long cfcr = REG_CPM_CFCR; -++ unsigned long plcr = REG_CPM_PLCR1; -++ if (plcr & CPM_PLCR1_PLL1EN) -++ lcdclk = __cpm_get_pllout() / -++ div[(cfcr & CPM_CFCR_LFR_MASK) >> CPM_CFCR_LFR_BIT]; -++ else -++ lcdclk = JZ_EXTAL; -++ return lcdclk; -++} -++ -++static __inline__ unsigned int __cpm_get_pixclk(void) -++{ -++ unsigned int pixclk; -++ unsigned long cfcr2 = REG_CPM_CFCR2; -++ pixclk = __cpm_get_pllout() / (cfcr2 + 1); -++ return pixclk; -++} -++ -++static __inline__ unsigned int __cpm_get_devclk(void) -++{ -++ return JZ_EXTAL; -++} -++ -++static __inline__ unsigned int __cpm_get_rtcclk(void) -++{ -++ return JZ_EXTAL2; -++} -++ -++static __inline__ unsigned int __cpm_get_uartclk(void) -++{ -++ return JZ_EXTAL; -++} -++ -++static __inline__ unsigned int __cpm_get_usbclk(void) -++{ -++ unsigned int usbclk; -++ unsigned long cfcr = REG_CPM_CFCR; -++ if (cfcr & CPM_CFCR_UCS) -++ usbclk = 48000000; -++ else -++ usbclk = __cpm_get_pllout() / -++ (((cfcr &CPM_CFCR_UFR_MASK) >> CPM_CFCR_UFR_BIT) + 1); -++ return usbclk; -++} -++ -++static __inline__ unsigned int __cpm_get_i2sclk(void) -++{ -++ unsigned int i2sclk; -++ unsigned long cfcr = REG_CPM_CFCR; -++ i2sclk = __cpm_get_pllout() / -++ ((cfcr & CPM_CFCR_I2S) ? 2: 1); -++ return i2sclk; -++} -++ -++static __inline__ unsigned int __cpm_get_mscclk(void) -++{ -++ if (REG_CPM_CFCR & CPM_CFCR_MSC) -++ return 24000000; -++ else -++ return 16000000; -++} -++ -++#endif /* __ASM_JZ4730_CLOCK_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4730/dma.h linux-2.6.24.7/include/asm-mips/mach-jz4730/dma.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4730/dma.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4730/dma.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,272 @@ -++/* -++ * linux/include/asm-mips/mach-jz4730/dma.h -++ * -++ * JZ4730 DMA definition. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4730_DMA_H__ -++#define __ASM_JZ4730_DMA_H__ -++ -++#include -++#include /* need byte IO */ -++#include /* And spinlocks */ -++#include -++#include -++ -++#define DMA_UNIT_32 32 -++#define DMA_UNIT_16 16 -++ -++ -++/* block-mode EOP: high DREQ: high DACK: low*/ -++#define DMA_BLOCK_CONF \ -++ DMAC_DCCSR_TM | \ -++ DMAC_DCCSR_DS_8b | DMAC_DCCSR_RDIL_IGN | \ -++ DMAC_DCCSR_ERDM_HLEVEL | DMAC_DCCSR_EACKS -++ -++/* single-mode EOP: high DREQ: high DACK: low */ -++#define DMA_SINGLE_CONF \ -++ DMAC_DCCSR_DS_8b | DMAC_DCCSR_RDIL_IGN | \ -++ DMAC_DCCSR_ERDM_HLEVEL | DMAC_DCCSR_EACKS -++ -++#define DMA_8bit_RX_CONF \ -++ DMAC_DCCSR_DAM | \ -++ DMAC_DCCSR_SWDH_8 | DMAC_DCCSR_DWDH_32 | \ -++ DMAC_DCCSR_DS_8b | DMAC_DCCSR_RDIL_IGN -++ -++#define DMA_8bit_TX_CONF \ -++ DMAC_DCCSR_SAM | \ -++ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_8 | \ -++ DMAC_DCCSR_DS_8b | DMAC_DCCSR_RDIL_IGN -++ -++#define DMA_16bit_RX_CONF \ -++ DMAC_DCCSR_DAM | \ -++ DMAC_DCCSR_SWDH_16 | DMAC_DCCSR_DWDH_32 | \ -++ DMAC_DCCSR_DS_16b | DMAC_DCCSR_RDIL_IGN -++ -++#define DMA_16bit_TX_CONF \ -++ DMAC_DCCSR_SAM | \ -++ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_16 | \ -++ DMAC_DCCSR_DS_16b | DMAC_DCCSR_RDIL_IGN -++ -++#define DMA_32bit_RX_CONF \ -++ DMAC_DCCSR_DAM | \ -++ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_32 | \ -++ DMAC_DCCSR_DS_32b | DMAC_DCCSR_RDIL_IGN -++ -++#define DMA_32bit_TX_CONF \ -++ DMAC_DCCSR_SAM | \ -++ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_32 | \ -++ DMAC_DCCSR_DS_32b | DMAC_DCCSR_RDIL_IGN -++ -++#define DMA_16BYTE_RX_CONF \ -++ DMAC_DCCSR_DAM | \ -++ DMAC_DCCSR_SWDH_8 | DMAC_DCCSR_DWDH_32 | \ -++ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN -++ -++#define DMA_16BYTE_TX_CONF \ -++ DMAC_DCCSR_SAM | \ -++ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_8 | \ -++ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN -++ -++#define DMA_AIC_32_16BYTE_TX_CMD \ -++ DMAC_DCCSR_SAM | \ -++ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_32 | \ -++ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN -++ -++#define DMA_AIC_32_16BYTE_RX_CMD \ -++ DMAC_DCCSR_DAM | \ -++ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_32 | \ -++ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN -++ -++#define DMA_AIC_16BIT_TX_CMD \ -++ DMAC_DCCSR_SAM | \ -++ DMAC_DCCSR_SWDH_16 | DMAC_DCCSR_DWDH_16 | \ -++ DMAC_DCCSR_DS_16b | DMAC_DCCSR_RDIL_IGN -++ -++#define DMA_AIC_16BIT_RX_CMD \ -++ DMAC_DCCSR_DAM | \ -++ DMAC_DCCSR_SWDH_16 | DMAC_DCCSR_DWDH_16 | \ -++ DMAC_DCCSR_DS_16b | DMAC_DCCSR_RDIL_IGN -++ -++#define DMA_AIC_16BYTE_RX_CMD \ -++ DMAC_DCCSR_DAM | \ -++ DMAC_DCCSR_SWDH_16 | DMAC_DCCSR_DWDH_16 | \ -++ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN -++ -++#define DMA_AIC_16BYTE_TX_CMD \ -++ DMAC_DCCSR_SAM | \ -++ DMAC_DCCSR_SWDH_16 | DMAC_DCCSR_DWDH_16 | \ -++ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN -++ -++/* DMA Device ID's follow */ -++enum { -++ DMA_ID_UART0_TX = 0, -++ DMA_ID_UART0_RX, -++ DMA_ID_UART1_TX, -++ DMA_ID_UART1_RX, -++ DMA_ID_UART2_TX, -++ DMA_ID_UART2_RX, -++ DMA_ID_UART3_TX, -++ DMA_ID_UART3_RX, -++ DMA_ID_SSI_TX, -++ DMA_ID_SSI_RX, -++ DMA_ID_MSC_TX, -++ DMA_ID_MSC_RX, -++ DMA_ID_AIC_TX, -++ DMA_ID_AIC_RX, -++ DMA_ID_BLOCK, /* DREQ */ -++ DMA_ID_SINGLE, /* DREQ */ -++ DMA_ID_PCMCIA0_TX, -++ DMA_ID_PCMCIA0_RX, -++ DMA_ID_PCMCIA1_TX, -++ DMA_ID_PCMCIA2_RX, -++ DMA_ID_AUTO, -++ DMA_ID_RAW_SET, -++ NUM_DMA_DEV -++}; -++ -++/* dummy DCCSR bit, i386 style DMA macros compitable */ -++#define DMA_MODE_READ 0 /* I/O to memory, no autoinit, -++ * increment, single mode */ -++#define DMA_MODE_WRITE 1 /* memory to I/O, no autoinit, -++ * increment, single mode */ -++#define DMA_MODE_CASCADE 2 /* pass thru DREQ->HRQ, -++ * DACK<-HLDA only */ -++#define DMA_AUTOINIT 3 -++#define DMA_MODE_MASK 3 -++ -++struct jz_dma_chan { -++ int dev_id; /* this channel is allocated if >=0, -++ * free otherwise */ -++ unsigned int io; -++ const char *dev_str; -++ int irq; -++ void *irq_dev; -++ unsigned int fifo_addr; -++ unsigned int mode; -++ unsigned int source; -++}; -++ -++extern struct jz_dma_chan jz_dma_table[]; -++ -++extern int jz_request_dma(int dev_id, -++ const char *dev_str, -++ irqreturn_t (*irqhandler)(int, void *), -++ unsigned long irqflags, -++ void *irq_dev_id); -++extern void jz_free_dma(unsigned int dmanr); -++ -++extern int jz_dma_read_proc(char *buf, char **start, off_t fpos, -++ int length, int *eof, void *data); -++extern void dump_jz_dma_channel(unsigned int dmanr); -++ -++extern void enable_dma(unsigned int dmanr); -++extern void disable_dma(unsigned int dmanr); -++extern void set_dma_addr(unsigned int dmanr, unsigned int a); -++extern void set_dma_count(unsigned int dmanr, unsigned int count); -++extern void set_dma_mode(unsigned int dmanr, unsigned int mode); -++extern void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); -++extern void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); -++extern int get_dma_residue(unsigned int dmanr); -++ -++extern spinlock_t dma_spin_lock; -++ -++static __inline__ unsigned long claim_dma_lock(void) -++{ -++ unsigned long flags; -++ spin_lock_irqsave(&dma_spin_lock, flags); -++ return flags; -++} -++ -++static __inline__ void release_dma_lock(unsigned long flags) -++{ -++ spin_unlock_irqrestore(&dma_spin_lock, flags); -++} -++ -++/* Clear the 'DMA Pointer Flip Flop'. -++ * Write 0 for LSB/MSB, 1 for MSB/LSB access. -++ */ -++#define clear_dma_ff(channel) -++ -++static __inline__ struct jz_dma_chan *get_dma_chan(unsigned int dmanr) -++{ -++ if (dmanr > NUM_DMA -++ || jz_dma_table[dmanr].dev_id < 0) -++ return NULL; -++ return &jz_dma_table[dmanr]; -++} -++ -++static __inline__ int dma_halted(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return 1; -++ return __dmac_channel_transmit_halt_detected(dmanr) ? 1 : 0; -++} -++ -++static __inline__ unsigned int get_dma_mode(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return 0; -++ return chan->mode; -++} -++ -++static __inline__ void clear_dma_done(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TC | DMAC_DCCSR_AR); -++} -++ -++static __inline__ void clear_dma_halt(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT); -++ REG_DMAC_DMACR &= ~(DMAC_DMACR_HTR); -++} -++static __inline__ void clear_dma_flag(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TC | DMAC_DCCSR_AR); -++ REG_DMAC_DMACR &= ~(DMAC_DMACR_HTR | DMAC_DMACR_AER); -++} -++ -++static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) -++{ -++} -++ -++static __inline__ unsigned int get_dma_done_status(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ unsigned long dccsr; -++ if (!chan) -++ return 0; -++ -++ dccsr = REG_DMAC_DCCSR(chan->io); -++ return dccsr & (DMAC_DCCSR_HLT | DMAC_DCCSR_TC | DMAC_DCCSR_AR); -++} -++ -++static __inline__ int get_dma_done_irq(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return -1; -++ -++ return chan->irq; -++} -++ -++#endif /* __ASM_JZ4730_DMA_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4730/jz4730.h linux-2.6.24.7/include/asm-mips/mach-jz4730/jz4730.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4730/jz4730.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4730/jz4730.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,40 @@ -++/* -++ * linux/include/asm-mips/mach-jz4730/jz4730.h -++ * -++ * JZ4730 common definition. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4730_H__ -++#define __ASM_JZ4730_H__ -++ -++#include -++#include -++#include -++#include -++ -++/*------------------------------------------------------------------ -++ * Platform definitions -++ */ -++#ifdef CONFIG_JZ4730_PMP -++#include -++#endif -++ -++/* Add other platform definition here ... */ -++ -++ -++/*------------------------------------------------------------------ -++ * Follows are related to platform definitions -++ */ -++ -++#include -++#include -++ -++#endif /* __ASM_JZ4730_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4730/misc.h linux-2.6.24.7/include/asm-mips/mach-jz4730/misc.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4730/misc.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4730/misc.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,28 @@ -++/* -++ * linux/include/asm-mips/mach-jz4730/misc.h -++ * -++ * JZ4730 miscillaneous definitions. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4730_MISC_H__ -++#define __ASM_JZ4730_MISC_H__ -++ -++/* -++ * I2C routines -++ */ -++ -++extern void i2c_open(void); -++extern void i2c_close(void); -++extern void i2c_setclk(unsigned int i2cclk); -++extern int i2c_read(unsigned char, unsigned char *, unsigned char, int); -++extern int i2c_write(unsigned char, unsigned char *, unsigned char, int); -++ -++#endif /* __ASM_JZ4730_MISC_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4730/ops.h linux-2.6.24.7/include/asm-mips/mach-jz4730/ops.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4730/ops.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4730/ops.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,2541 @@ -++/* -++ * linux/include/asm-mips/mach-jz4730/ops.h -++ * -++ * JZ4730 module operations definition. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4730_OPS_H__ -++#define __ASM_JZ4730_OPS_H__ -++ -++/*************************************************************************** -++ * MSC -++ ***************************************************************************/ -++ -++#define __msc_start_op() \ -++ ( REG_MSC_STRPCL = MSC_STRPCL_START_OP | MSC_STRPCL_CLOCK_CONTROL_START ) -++ -++#define __msc_set_resto(to) ( REG_MSC_RESTO = to ) -++#define __msc_set_rdto(to) ( REG_MSC_RDTO = to ) -++#define __msc_set_cmd(cmd) ( REG_MSC_CMD = cmd ) -++#define __msc_set_arg(arg) ( REG_MSC_ARG = arg ) -++#define __msc_set_nob(nob) ( REG_MSC_NOB = nob ) -++#define __msc_get_nob() ( REG_MSC_NOB ) -++#define __msc_set_blklen(len) ( REG_MSC_BLKLEN = len ) -++#define __msc_set_cmdat(cmdat) ( REG_MSC_CMDAT = cmdat ) -++#define __msc_set_cmdat_ioabort() ( REG_MSC_CMDAT |= MSC_CMDAT_IO_ABORT ) -++#define __msc_clear_cmdat_ioabort() ( REG_MSC_CMDAT &= ~MSC_CMDAT_IO_ABORT ) -++ -++#define __msc_set_cmdat_bus_width1() \ -++do { \ -++ REG_MSC_CMDAT &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ -++ REG_MSC_CMDAT |= MSC_CMDAT_BUS_WIDTH_1BIT; \ -++} while(0) -++ -++#define __msc_set_cmdat_bus_width4() \ -++do { \ -++ REG_MSC_CMDAT &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ -++ REG_MSC_CMDAT |= MSC_CMDAT_BUS_WIDTH_4BIT; \ -++} while(0) -++ -++#define __msc_set_cmdat_dma_en() ( REG_MSC_CMDAT |= MSC_CMDAT_DMA_EN ) -++#define __msc_set_cmdat_init() ( REG_MSC_CMDAT |= MSC_CMDAT_INIT ) -++#define __msc_set_cmdat_busy() ( REG_MSC_CMDAT |= MSC_CMDAT_BUSY ) -++#define __msc_set_cmdat_stream() ( REG_MSC_CMDAT |= MSC_CMDAT_STREAM_BLOCK ) -++#define __msc_set_cmdat_block() ( REG_MSC_CMDAT &= ~MSC_CMDAT_STREAM_BLOCK ) -++#define __msc_set_cmdat_read() ( REG_MSC_CMDAT &= ~MSC_CMDAT_WRITE_READ ) -++#define __msc_set_cmdat_write() ( REG_MSC_CMDAT |= MSC_CMDAT_WRITE_READ ) -++#define __msc_set_cmdat_data_en() ( REG_MSC_CMDAT |= MSC_CMDAT_DATA_EN ) -++ -++/* r is MSC_CMDAT_RESPONSE_FORMAT_Rx or MSC_CMDAT_RESPONSE_FORMAT_NONE */ -++#define __msc_set_cmdat_res_format(r) \ -++do { \ -++ REG_MSC_CMDAT &= ~MSC_CMDAT_RESPONSE_FORMAT_MASK; \ -++ REG_MSC_CMDAT |= (r); \ -++} while(0) -++ -++#define __msc_clear_cmdat() \ -++ REG_MSC_CMDAT &= ~( MSC_CMDAT_IO_ABORT | MSC_CMDAT_DMA_EN | MSC_CMDAT_INIT| \ -++ MSC_CMDAT_BUSY | MSC_CMDAT_STREAM_BLOCK | MSC_CMDAT_WRITE_READ | \ -++ MSC_CMDAT_DATA_EN | MSC_CMDAT_RESPONSE_FORMAT_MASK ) -++ -++#define __msc_get_imask() ( REG_MSC_IMASK ) -++#define __msc_mask_all_intrs() ( REG_MSC_IMASK = 0xff ) -++#define __msc_unmask_all_intrs() ( REG_MSC_IMASK = 0x00 ) -++#define __msc_mask_rd() ( REG_MSC_IMASK |= MSC_IMASK_RXFIFO_RD_REQ ) -++#define __msc_unmask_rd() ( REG_MSC_IMASK &= ~MSC_IMASK_RXFIFO_RD_REQ ) -++#define __msc_mask_wr() ( REG_MSC_IMASK |= MSC_IMASK_TXFIFO_WR_REQ ) -++#define __msc_unmask_wr() ( REG_MSC_IMASK &= ~MSC_IMASK_TXFIFO_WR_REQ ) -++#define __msc_mask_endcmdres() ( REG_MSC_IMASK |= MSC_IMASK_END_CMD_RES ) -++#define __msc_unmask_endcmdres() ( REG_MSC_IMASK &= ~MSC_IMASK_END_CMD_RES ) -++#define __msc_mask_datatrandone() ( REG_MSC_IMASK |= MSC_IMASK_DATA_TRAN_DONE ) -++#define __msc_unmask_datatrandone() ( REG_MSC_IMASK &= ~MSC_IMASK_DATA_TRAN_DONE ) -++#define __msc_mask_prgdone() ( REG_MSC_IMASK |= MSC_IMASK_PRG_DONE ) -++#define __msc_unmask_prgdone() ( REG_MSC_IMASK &= ~MSC_IMASK_PRG_DONE ) -++ -++/* n=0,1,2,3,4,5,6,7 */ -++#define __msc_set_clkrt(n) \ -++do { \ -++ REG_MSC_CLKRT = n; \ -++} while(0) -++ -++#define __msc_get_ireg() ( REG_MSC_IREG ) -++#define __msc_ireg_rd() ( REG_MSC_IREG & MSC_IREG_RXFIFO_RD_REQ ) -++#define __msc_ireg_wr() ( REG_MSC_IREG & MSC_IREG_TXFIFO_WR_REQ ) -++#define __msc_ireg_end_cmd_res() ( REG_MSC_IREG & MSC_IREG_END_CMD_RES ) -++#define __msc_ireg_data_tran_done() ( REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE ) -++#define __msc_ireg_prg_done() ( REG_MSC_IREG & MSC_IREG_PRG_DONE ) -++#define __msc_ireg_clear_end_cmd_res() ( REG_MSC_IREG = MSC_IREG_END_CMD_RES ) -++#define __msc_ireg_clear_data_tran_done() ( REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE ) -++#define __msc_ireg_clear_prg_done() ( REG_MSC_IREG = MSC_IREG_PRG_DONE ) -++ -++#define __msc_get_stat() ( REG_MSC_STAT ) -++#define __msc_stat_not_end_cmd_res() ( (REG_MSC_STAT & MSC_STAT_END_CMD_RES) == 0) -++#define __msc_stat_crc_err() \ -++ ( REG_MSC_STAT & (MSC_STAT_CRC_RES_ERR | MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR_YES) ) -++#define __msc_stat_res_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_RES_ERR ) -++#define __msc_stat_rd_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_READ_ERROR ) -++#define __msc_stat_wr_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_WRITE_ERROR_YES ) -++#define __msc_stat_resto_err() ( REG_MSC_STAT & MSC_STAT_TIME_OUT_RES ) -++#define __msc_stat_rdto_err() ( REG_MSC_STAT & MSC_STAT_TIME_OUT_READ ) -++ -++#define __msc_rd_resfifo() ( REG_MSC_RES ) -++#define __msc_rd_rxfifo() ( REG_MSC_RXFIFO ) -++#define __msc_wr_txfifo(v) ( REG_MSC_TXFIFO = v ) -++ -++#define __msc_reset() \ -++do { \ -++ REG_MSC_STRPCL = MSC_STRPCL_RESET; \ -++ while (REG_MSC_STAT & MSC_STAT_IS_RESETTING); \ -++} while (0) -++ -++#define __msc_start_clk() \ -++do { \ -++ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_START; \ -++} while (0) -++ -++#define __msc_stop_clk() \ -++do { \ -++ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP; \ -++} while (0) -++ -++#define MMC_CLK 19169200 -++#define SD_CLK 24576000 -++ -++/* msc_clk should little than pclk and little than clk retrieve from card */ -++#define __msc_calc_clk_divisor(type,dev_clk,msc_clk,lv) \ -++do { \ -++ unsigned int rate, pclk, i; \ -++ pclk = dev_clk; \ -++ rate = type?SD_CLK:MMC_CLK; \ -++ if (msc_clk && msc_clk < pclk) \ -++ pclk = msc_clk; \ -++ i = 0; \ -++ while (pclk < rate) \ -++ { \ -++ i ++; \ -++ rate >>= 1; \ -++ } \ -++ lv = i; \ -++} while(0) -++ -++/* divide rate to little than or equal to 400kHz */ -++#define __msc_calc_slow_clk_divisor(type, lv) \ -++do { \ -++ unsigned int rate, i; \ -++ rate = (type?SD_CLK:MMC_CLK)/1000/400; \ -++ i = 0; \ -++ while (rate > 0) \ -++ { \ -++ rate >>= 1; \ -++ i ++; \ -++ } \ -++ lv = i; \ -++} while(0) -++ -++/*************************************************************************** -++ * RTC -++ ***************************************************************************/ -++ -++#define __rtc_start() ( REG_RTC_RCR |= RTC_RCR_START ) -++#define __rtc_stop() ( REG_RTC_RCR &= ~RTC_RCR_START ) -++ -++#define __rtc_enable_alarm() ( REG_RTC_RCR |= RTC_RCR_AE ) -++#define __rtc_disable_alarm() ( REG_RTC_RCR &= ~RTC_RCR_AE ) -++#define __rtc_enable_alarm_irq() ( REG_RTC_RCR |= RTC_RCR_AIE ) -++#define __rtc_disable_alarm_irq() ( REG_RTC_RCR &= ~RTC_RCR_AIE ) -++ -++#define __rtc_enable_1hz_irq() ( REG_RTC_RCR |= RTC_RCR_HZIE ) -++#define __rtc_disable_1hz_irq() ( REG_RTC_RCR &= ~RTC_RCR_HZIE ) -++ -++#define __rtc_is_alarm_flag() ( REG_RTC_RCR & RTC_RCR_AF ) -++#define __rtc_is_1hz_flag() ( REG_RTC_RCR & RTC_RCR_HZ ) -++#define __rtc_clear_alarm_flag() ( REG_RTC_RCR &= ~RTC_RCR_AF ) -++#define __rtc_clear_1hz_flag() ( REG_RTC_RCR &= ~RTC_RCR_HZ ) -++ -++#define __rtc_set_second(s) ( REG_RTC_RSR = (s) ) -++#define __rtc_get_second() REG_RTC_RSR -++#define __rtc_set_alarm(s) ( REG_RTC_RSAR = (s) ) -++#define __rtc_get_alarm() REG_RTC_RSAR -++ -++#define __rtc_adjust_1hz(f32k) \ -++ ( REG_RTC_RGR = (REG_RTC_RGR & ~(RTC_REG_DIV_MASK | RTC_RGR_ADJ_MASK)) | f32k | 0 ) -++#define __rtc_lock_1hz() ( REG_RTC_RGR |= RTC_RGR_LOCK ) -++ -++ -++/*************************************************************************** -++ * FIR -++ ***************************************************************************/ -++ -++/* enable/disable fir unit */ -++#define __fir_enable() ( REG_FIR_CR1 |= FIR_CR1_FIRUE ) -++#define __fir_disable() ( REG_FIR_CR1 &= ~FIR_CR1_FIRUE ) -++ -++/* enable/disable address comparison */ -++#define __fir_enable_ac() ( REG_FIR_CR1 |= FIR_CR1_ACE ) -++#define __fir_disable_ac() ( REG_FIR_CR1 &= ~FIR_CR1_ACE ) -++ -++/* select frame end mode as underrun or normal */ -++#define __fir_set_eous() ( REG_FIR_CR1 |= FIR_CR1_EOUS ) -++#define __fir_clear_eous() ( REG_FIR_CR1 &= ~FIR_CR1_EOUS ) -++ -++/* enable/disable transmitter idle interrupt */ -++#define __fir_enable_tii() ( REG_FIR_CR1 |= FIR_CR1_TIIE ) -++#define __fir_disable_tii() ( REG_FIR_CR1 &= ~FIR_CR1_TIIE ) -++ -++/* enable/disable transmit FIFO service request interrupt */ -++#define __fir_enable_tfi() ( REG_FIR_CR1 |= FIR_CR1_TFIE ) -++#define __fir_disable_tfi() ( REG_FIR_CR1 &= ~FIR_CR1_TFIE ) -++ -++/* enable/disable receive FIFO service request interrupt */ -++#define __fir_enable_rfi() ( REG_FIR_CR1 |= FIR_CR1_RFIE ) -++#define __fir_disable_rfi() ( REG_FIR_CR1 &= ~FIR_CR1_RFIE ) -++ -++/* enable/disable tx function */ -++#define __fir_tx_enable() ( REG_FIR_CR1 |= FIR_CR1_TXE ) -++#define __fir_tx_disable() ( REG_FIR_CR1 &= ~FIR_CR1_TXE ) -++ -++/* enable/disable rx function */ -++#define __fir_rx_enable() ( REG_FIR_CR1 |= FIR_CR1_RXE ) -++#define __fir_rx_disable() ( REG_FIR_CR1 &= ~FIR_CR1_RXE ) -++ -++ -++/* enable/disable serial infrared interaction pulse (SIP) */ -++#define __fir_enable_sip() ( REG_FIR_CR2 |= FIR_CR2_SIPE ) -++#define __fir_disable_sip() ( REG_FIR_CR2 &= ~FIR_CR2_SIPE ) -++ -++/* un-inverted CRC value is sent out */ -++#define __fir_enable_bcrc() ( REG_FIR_CR2 |= FIR_CR2_BCRC ) -++ -++/* inverted CRC value is sent out */ -++#define __fir_disable_bcrc() ( REG_FIR_CR2 &= ~FIR_CR2_BCRC ) -++ -++/* enable/disable Transmit Frame Length Register */ -++#define __fir_enable_tflr() ( REG_FIR_CR2 |= FIR_CR2_TFLRS ) -++#define __fir_disable_tflr() ( REG_FIR_CR2 &= ~FIR_CR2_TFLRS ) -++ -++/* Preamble is transmitted in idle state */ -++#define __fir_set_iss() ( REG_FIR_CR2 |= FIR_CR2_ISS ) -++ -++/* Abort symbol is transmitted in idle state */ -++#define __fir_clear_iss() ( REG_FIR_CR2 &= ~FIR_CR2_ISS ) -++ -++/* enable/disable loopback mode */ -++#define __fir_enable_loopback() ( REG_FIR_CR2 |= FIR_CR2_LMS ) -++#define __fir_disable_loopback() ( REG_FIR_CR2 &= ~FIR_CR2_LMS ) -++ -++/* select transmit pin polarity */ -++#define __fir_tpp_negative() ( REG_FIR_CR2 |= FIR_CR2_TPPS ) -++#define __fir_tpp_positive() ( REG_FIR_CR2 &= ~FIR_CR2_TPPS ) -++ -++/* select receive pin polarity */ -++#define __fir_rpp_negative() ( REG_FIR_CR2 |= FIR_CR2_RPPS ) -++#define __fir_rpp_positive() ( REG_FIR_CR2 &= ~FIR_CR2_RPPS ) -++ -++/* n=16,32,64,128 */ -++#define __fir_set_txfifo_trigger(n) \ -++do { \ -++ REG_FIR_CR2 &= ~FIR_CR2_TTRG_MASK; \ -++ REG_FIR_CR2 |= FIR_CR2_TTRG_##n; \ -++} while (0) -++ -++/* n=16,32,64,128 */ -++#define __fir_set_rxfifo_trigger(n) \ -++do { \ -++ REG_FIR_CR2 &= ~FIR_CR2_RTRG_MASK; \ -++ REG_FIR_CR2 |= FIR_CR2_RTRG_##n; \ -++} while (0) -++ -++ -++/* FIR status checking */ -++ -++#define __fir_test_rfw() ( REG_FIR_SR & FIR_SR_RFW ) -++#define __fir_test_rfa() ( REG_FIR_SR & FIR_SR_RFA ) -++#define __fir_test_tfrtl() ( REG_FIR_SR & FIR_SR_TFRTL ) -++#define __fir_test_rfrtl() ( REG_FIR_SR & FIR_SR_RFRTL ) -++#define __fir_test_urun() ( REG_FIR_SR & FIR_SR_URUN ) -++#define __fir_test_rfte() ( REG_FIR_SR & FIR_SR_RFTE ) -++#define __fir_test_orun() ( REG_FIR_SR & FIR_SR_ORUN ) -++#define __fir_test_crce() ( REG_FIR_SR & FIR_SR_CRCE ) -++#define __fir_test_fend() ( REG_FIR_SR & FIR_SR_FEND ) -++#define __fir_test_tff() ( REG_FIR_SR & FIR_SR_TFF ) -++#define __fir_test_rfe() ( REG_FIR_SR & FIR_SR_RFE ) -++#define __fir_test_tidle() ( REG_FIR_SR & FIR_SR_TIDLE ) -++#define __fir_test_rb() ( REG_FIR_SR & FIR_SR_RB ) -++ -++#define __fir_clear_status() \ -++do { \ -++ REG_FIR_SR |= FIR_SR_RFW | FIR_SR_RFA | FIR_SR_URUN; \ -++} while (0) -++ -++#define __fir_clear_rfw() ( REG_FIR_SR |= FIR_SR_RFW ) -++#define __fir_clear_rfa() ( REG_FIR_SR |= FIR_SR_RFA ) -++#define __fir_clear_urun() ( REG_FIR_SR |= FIR_SR_URUN ) -++ -++#define __fir_set_tflr(len) \ -++do { \ -++ REG_FIR_TFLR = len; \ -++} while (0) -++ -++#define __fir_set_addr(a) ( REG_FIR_AR = (a) ) -++ -++#define __fir_write_data(data) ( REG_FIR_TDR = data ) -++#define __fir_read_data(data) ( data = REG_FIR_RDR ) -++ -++/*************************************************************************** -++ * SCC -++ ***************************************************************************/ -++ -++#define __scc_enable(base) ( REG_SCC_CR(base) |= SCC_CR_SCCE ) -++#define __scc_disable(base) ( REG_SCC_CR(base) &= ~SCC_CR_SCCE ) -++ -++#define __scc_set_tx_mode(base) ( REG_SCC_CR(base) |= SCC_CR_TRS ) -++#define __scc_set_rx_mode(base) ( REG_SCC_CR(base) &= ~SCC_CR_TRS ) -++ -++#define __scc_enable_t2r(base) ( REG_SCC_CR(base) |= SCC_CR_T2R ) -++#define __scc_disable_t2r(base) ( REG_SCC_CR(base) &= ~SCC_CR_T2R ) -++ -++#define __scc_clk_as_devclk(base) \ -++do { \ -++ REG_SCC_CR(base) &= ~SCC_CR_FDIV_MASK; \ -++ REG_SCC_CR(base) |= SCC_CR_FDIV_1; \ -++} while (0) -++ -++#define __scc_clk_as_half_devclk(base) \ -++do { \ -++ REG_SCC_CR(base) &= ~SCC_CR_FDIV_MASK; \ -++ REG_SCC_CR(base) |= SCC_CR_FDIV_2; \ -++} while (0) -++ -++/* n=1,4,8,14 */ -++#define __scc_set_fifo_trigger(base, n) \ -++do { \ -++ REG_SCC_CR(base) &= ~SCC_CR_TRIG_MASK; \ -++ REG_SCC_CR(base) |= SCC_CR_TRIG_##n; \ -++} while (0) -++ -++#define __scc_set_protocol(base, p) \ -++do { \ -++ if (p) \ -++ REG_SCC_CR(base) |= SCC_CR_TP; \ -++ else \ -++ REG_SCC_CR(base) &= ~SCC_CR_TP; \ -++} while (0) -++ -++#define __scc_flush_fifo(base) ( REG_SCC_CR(base) |= SCC_CR_FLUSH ) -++ -++#define __scc_set_invert_mode(base) ( REG_SCC_CR(base) |= SCC_CR_CONV ) -++#define __scc_set_direct_mode(base) ( REG_SCC_CR(base) &= ~SCC_CR_CONV ) -++ -++#define SCC_ERR_INTRS \ -++ ( SCC_CR_ECIE | SCC_CR_EPIE | SCC_CR_RETIE | SCC_CR_EOIE ) -++#define SCC_ALL_INTRS \ -++ ( SCC_CR_TXIE | SCC_CR_RXIE | SCC_CR_TENDIE | SCC_CR_RTOIE | \ -++ SCC_CR_ECIE | SCC_CR_EPIE | SCC_CR_RETIE | SCC_CR_EOIE ) -++ -++#define __scc_enable_err_intrs(base) ( REG_SCC_CR(base) |= SCC_ERR_INTRS ) -++#define __scc_disable_err_intrs(base) ( REG_SCC_CR(base) &= ~SCC_ERR_INTRS ) -++ -++#define SCC_ALL_ERRORS \ -++ ( SCC_SR_ORER | SCC_SR_RTO | SCC_SR_PER | SCC_SR_RETR_3 | SCC_SR_ECNTO) -++ -++#define __scc_clear_errors(base) ( REG_SCC_SR(base) &= ~SCC_ALL_ERRORS ) -++ -++#define __scc_enable_all_intrs(base) ( REG_SCC_CR(base) |= SCC_ALL_INTRS ) -++#define __scc_disable_all_intrs(base) ( REG_SCC_CR(base) &= ~SCC_ALL_INTRS ) -++ -++#define __scc_enable_tx_intr(base) ( REG_SCC_CR(base) |= SCC_CR_TXIE | SCC_CR_TENDIE ) -++#define __scc_disable_tx_intr(base) ( REG_SCC_CR(base) &= ~(SCC_CR_TXIE | SCC_CR_TENDIE) ) -++ -++#define __scc_enable_rx_intr(base) ( REG_SCC_CR(base) |= SCC_CR_RXIE) -++#define __scc_disable_rx_intr(base) ( REG_SCC_CR(base) &= ~SCC_CR_RXIE) -++ -++#define __scc_set_tsend(base) ( REG_SCC_CR(base) |= SCC_CR_TSEND ) -++#define __scc_clear_tsend(base) ( REG_SCC_CR(base) &= ~SCC_CR_TSEND ) -++ -++#define __scc_set_clockstop(base) ( REG_SCC_CR(base) |= SCC_CR_CLKSTP ) -++#define __scc_clear_clockstop(base) ( REG_SCC_CR(base) &= ~SCC_CR_CLKSTP ) -++ -++#define __scc_clockstop_low(base) \ -++do { \ -++ REG_SCC_CR(base) &= ~SCC_CR_PX_MASK; \ -++ REG_SCC_CR(base) |= SCC_CR_PX_STOP_LOW; \ -++} while (0) -++ -++#define __scc_clockstop_high(base) \ -++do { \ -++ REG_SCC_CR(base) &= ~SCC_CR_PX_MASK; \ -++ REG_SCC_CR(base) |= SCC_CR_PX_STOP_HIGH; \ -++} while (0) -++ -++ -++/* SCC status checking */ -++#define __scc_check_transfer_status(base) ( REG_SCC_SR(base) & SCC_SR_TRANS ) -++#define __scc_check_rx_overrun_error(base) ( REG_SCC_SR(base) & SCC_SR_ORER ) -++#define __scc_check_rx_timeout(base) ( REG_SCC_SR(base) & SCC_SR_RTO ) -++#define __scc_check_parity_error(base) ( REG_SCC_SR(base) & SCC_SR_PER ) -++#define __scc_check_txfifo_trigger(base) ( REG_SCC_SR(base) & SCC_SR_TFTG ) -++#define __scc_check_rxfifo_trigger(base) ( REG_SCC_SR(base) & SCC_SR_RFTG ) -++#define __scc_check_tx_end(base) ( REG_SCC_SR(base) & SCC_SR_TEND ) -++#define __scc_check_retx_3(base) ( REG_SCC_SR(base) & SCC_SR_RETR_3 ) -++#define __scc_check_ecnt_overflow(base) ( REG_SCC_SR(base) & SCC_SR_ECNTO ) -++ -++ -++/*************************************************************************** -++ * WDT -++ ***************************************************************************/ -++ -++#define __wdt_set_count(count) ( REG_WDT_WTCNT = (count) ) -++#define __wdt_start() ( REG_WDT_WTCSR |= WDT_WTCSR_START ) -++#define __wdt_stop() ( REG_WDT_WTCSR &= ~WDT_WTCSR_START ) -++ -++ -++/*************************************************************************** -++ * OST -++ ***************************************************************************/ -++ -++#define __ost_enable_all() ( REG_OST_TER |= 0x07 ) -++#define __ost_disable_all() ( REG_OST_TER &= ~0x07 ) -++#define __ost_enable_channel(n) ( REG_OST_TER |= (1 << (n)) ) -++#define __ost_disable_channel(n) ( REG_OST_TER &= ~(1 << (n)) ) -++#define __ost_set_reload(n, val) ( REG_OST_TRDR(n) = (val) ) -++#define __ost_set_count(n, val) ( REG_OST_TCNT(n) = (val) ) -++#define __ost_get_count(n) ( REG_OST_TCNT(n) ) -++#define __ost_set_clock(n, cs) \ -++do { \ -++ REG_OST_TCSR(n) &= ~OST_TCSR_CKS_MASK; \ -++ REG_OST_TCSR(n) |= cs; \ -++} while (0) -++#define __ost_set_mode(n, val) ( REG_OST_TCSR(n) = (val) ) -++#define __ost_enable_interrupt(n) ( REG_OST_TCSR(n) |= OST_TCSR_UIE ) -++#define __ost_disable_interrupt(n) ( REG_OST_TCSR(n) &= ~OST_TCSR_UIE ) -++#define __ost_uf_detected(n) ( REG_OST_TCSR(n) & OST_TCSR_UF ) -++#define __ost_clear_uf(n) ( REG_OST_TCSR(n) &= ~OST_TCSR_UF ) -++#define __ost_is_busy(n) ( REG_OST_TCSR(n) & OST_TCSR_BUSY ) -++#define __ost_clear_busy(n) ( REG_OST_TCSR(n) &= ~OST_TCSR_BUSY ) -++ -++ -++/*************************************************************************** -++ * UART -++ ***************************************************************************/ -++ -++#define __uart_enable(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) |= UARTFCR_UUE | UARTFCR_FE ) -++#define __uart_disable(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) = ~UARTFCR_UUE ) -++ -++#define __uart_enable_transmit_irq(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_TIE ) -++#define __uart_disable_transmit_irq(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~UARTIER_TIE ) -++ -++#define __uart_enable_receive_irq(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE ) -++#define __uart_disable_receive_irq(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~(UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE) ) -++ -++#define __uart_enable_loopback(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) |= UARTMCR_LOOP ) -++#define __uart_disable_loopback(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) &= ~UARTMCR_LOOP ) -++ -++#define __uart_set_8n1(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) = UARTLCR_WLEN_8 ) -++ -++#define __uart_set_baud(n, devclk, baud) \ -++ do { \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) |= UARTLCR_DLAB; \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_DLLR) = (devclk / 16 / baud) & 0xff; \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_DLHR) = ((devclk / 16 / baud) >> 8) & 0xff; \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) &= ~UARTLCR_DLAB; \ -++ } while (0) -++ -++#define __uart_parity_error(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_PER) != 0 ) -++ -++#define __uart_clear_errors(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) &= ~(UARTLSR_ORER | UARTLSR_BRK | UARTLSR_FER | UARTLSR_PER | UARTLSR_RFER) ) -++ -++#define __uart_transmit_fifo_empty(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TDRQ) != 0 ) -++ -++#define __uart_transmit_end(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TEMT) != 0 ) -++ -++#define __uart_transmit_char(n, ch) \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_TDR) = (ch) -++ -++#define __uart_receive_fifo_full(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) -++ -++#define __uart_receive_ready(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) -++ -++#define __uart_receive_char(n) \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_RDR) -++ -++#define __uart_disable_irda() \ -++ ( REG8(IRDA_BASE + OFF_SIRCR) &= ~(SIRCR_TSIRE | SIRCR_RSIRE) ) -++#define __uart_enable_irda() \ -++ /* Tx high pulse as 0, Rx low pulse as 0 */ \ -++ ( REG8(IRDA_BASE + OFF_SIRCR) = SIRCR_TSIRE | SIRCR_RSIRE | SIRCR_RXPL | SIRCR_TPWS ) -++ -++ -++/*************************************************************************** -++ * INTC -++ ***************************************************************************/ -++#define __intc_unmask_irq(n) ( REG_INTC_IMCR = (1 << (n)) ) -++#define __intc_mask_irq(n) ( REG_INTC_IMSR = (1 << (n)) ) -++#define __intc_ack_irq(n) ( REG_INTC_IPR = (1 << (n)) ) -++ -++/*************************************************************************** -++ * CIM -++ ***************************************************************************/ -++ -++#define __cim_enable() ( REG_CIM_CTRL |= CIM_CTRL_ENA ) -++#define __cim_disable() ( REG_CIM_CTRL &= ~CIM_CTRL_ENA ) -++ -++#define __cim_input_data_inverse() ( REG_CIM_CFG |= CIM_CFG_INV_DAT ) -++#define __cim_input_data_normal() ( REG_CIM_CFG &= ~CIM_CFG_INV_DAT ) -++ -++#define __cim_vsync_active_low() ( REG_CIM_CFG |= CIM_CFG_VSP ) -++#define __cim_vsync_active_high() ( REG_CIM_CFG &= ~CIM_CFG_VSP ) -++ -++#define __cim_hsync_active_low() ( REG_CIM_CFG |= CIM_CFG_HSP ) -++#define __cim_hsync_active_high() ( REG_CIM_CFG &= ~CIM_CFG_HSP ) -++ -++#define __cim_sample_data_at_pclk_falling_edge() \ -++ ( REG_CIM_CFG |= CIM_CFG_PCP ) -++#define __cim_sample_data_at_pclk_rising_edge() \ -++ ( REG_CIM_CFG &= ~CIM_CFG_PCP ) -++ -++#define __cim_enable_dummy_zero() ( REG_CIM_CFG |= CIM_CFG_DUMMY_ZERO ) -++#define __cim_disable_dummy_zero() ( REG_CIM_CFG &= ~CIM_CFG_DUMMY_ZERO ) -++ -++#define __cim_select_external_vsync() ( REG_CIM_CFG |= CIM_CFG_EXT_VSYNC ) -++#define __cim_select_internal_vsync() ( REG_CIM_CFG &= ~CIM_CFG_EXT_VSYNC ) -++ -++/* n=0-7 */ -++#define __cim_set_data_packing_mode(n) \ -++do { \ -++ REG_CIM_CFG &= ~CIM_CFG_PACK_MASK; \ -++ REG_CIM_CFG |= (CIM_CFG_PACK_##n); \ -++} while (0) -++ -++#define __cim_enable_ccir656_progressive_mode() \ -++do { \ -++ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ -++ REG_CIM_CFG |= CIM_CFG_DSM_CPM; \ -++} while (0) -++ -++#define __cim_enable_ccir656_interlace_mode() \ -++do { \ -++ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ -++ REG_CIM_CFG |= CIM_CFG_DSM_CIM; \ -++} while (0) -++ -++#define __cim_enable_gated_clock_mode() \ -++do { \ -++ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ -++ REG_CIM_CFG |= CIM_CFG_DSM_GCM; \ -++} while (0) -++ -++#define __cim_enable_nongated_clock_mode() \ -++do { \ -++ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ -++ REG_CIM_CFG |= CIM_CFG_DSM_NGCM; \ -++} while (0) -++ -++/* sclk:system bus clock -++ * mclk: CIM master clock -++ */ -++#define __cim_set_master_clk(sclk, mclk) \ -++do { \ -++ REG_CIM_CTRL &= ~CIM_CTRL_MCLKDIV_MASK; \ -++ REG_CIM_CTRL |= (((sclk)/(mclk) - 1) << CIM_CTRL_MCLKDIV_BIT); \ -++} while (0) -++ -++#define __cim_enable_sof_intr() \ -++ ( REG_CIM_CTRL |= CIM_CTRL_DMA_SOFM ) -++#define __cim_disable_sof_intr() \ -++ ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_SOFM ) -++ -++#define __cim_enable_eof_intr() \ -++ ( REG_CIM_CTRL |= CIM_CTRL_DMA_EOFM ) -++#define __cim_disable_eof_intr() \ -++ ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_EOFM ) -++ -++#define __cim_enable_stop_intr() \ -++ ( REG_CIM_CTRL |= CIM_CTRL_DMA_STOPM ) -++#define __cim_disable_stop_intr() \ -++ ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_STOPM ) -++ -++#define __cim_enable_trig_intr() \ -++ ( REG_CIM_CTRL |= CIM_CTRL_RXF_TRIGM ) -++#define __cim_disable_trig_intr() \ -++ ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_TRIGM ) -++ -++#define __cim_enable_rxfifo_overflow_intr() \ -++ ( REG_CIM_CTRL |= CIM_CTRL_RXF_OFM ) -++#define __cim_disable_rxfifo_overflow_intr() \ -++ ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_OFM ) -++ -++/* n=1-16 */ -++#define __cim_set_frame_rate(n) \ -++do { \ -++ REG_CIM_CTRL &= ~CIM_CTRL_FRC_MASK; \ -++ REG_CIM_CTRL |= CIM_CTRL_FRC_##n; \ -++} while (0) -++ -++#define __cim_enable_dma() ( REG_CIM_CTRL |= CIM_CTRL_DMA_EN ) -++#define __cim_disable_dma() ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_EN ) -++ -++#define __cim_reset_rxfifo() ( REG_CIM_CTRL |= CIM_CTRL_RXF_RST ) -++#define __cim_unreset_rxfifo() ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_RST ) -++ -++/* n=4,8,12,16,20,24,28,32 */ -++#define __cim_set_rxfifo_trigger(n) \ -++do { \ -++ REG_CIM_CTRL &= ~CIM_CTRL_RXF_TRIG_MASK; \ -++ REG_CIM_CTRL |= CIM_CTRL_RXF_TRIG_##n; \ -++} while (0) -++ -++#define __cim_clear_state() ( REG_CIM_STATE = 0 ) -++ -++#define __cim_disable_done() ( REG_CIM_STATE & CIM_STATE_VDD ) -++#define __cim_rxfifo_empty() ( REG_CIM_STATE & CIM_STATE_RXF_EMPTY ) -++#define __cim_rxfifo_reach_trigger() ( REG_CIM_STATE & CIM_STATE_RXF_TRIG ) -++#define __cim_rxfifo_overflow() ( REG_CIM_STATE & CIM_STATE_RXF_OF ) -++#define __cim_clear_rxfifo_overflow() ( REG_CIM_STATE &= ~CIM_STATE_RXF_OF ) -++#define __cim_dma_stop() ( REG_CIM_STATE & CIM_STATE_DMA_STOP ) -++#define __cim_dma_eof() ( REG_CIM_STATE & CIM_STATE_DMA_EOF ) -++#define __cim_dma_sof() ( REG_CIM_STATE & CIM_STATE_DMA_SOF ) -++ -++#define __cim_get_iid() ( REG_CIM_IID ) -++#define __cim_get_image_data() ( REG_CIM_RXFIFO ) -++#define __cim_get_dam_cmd() ( REG_CIM_CMD ) -++ -++#define __cim_set_da(a) ( REG_CIM_DA = (a) ) -++ -++/*************************************************************************** -++ * PWM -++ ***************************************************************************/ -++ -++/* n is the pwm channel (0,1,..) */ -++#define __pwm_enable_module(n) ( REG_PWM_CTR(n) |= PWM_CTR_EN ) -++#define __pwm_disable_module(n) ( REG_PWM_CTR(n) &= ~PWM_CTR_EN ) -++#define __pwm_graceful_shutdown_mode(n) ( REG_PWM_CTR(n) &= ~PWM_CTR_SD ) -++#define __pwm_abrupt_shutdown_mode(n) ( REG_PWM_CTR(n) |= PWM_CTR_SD ) -++#define __pwm_set_full_duty(n) ( REG_PWM_DUT(n) |= PWM_DUT_FDUTY ) -++ -++#define __pwm_set_prescale(n, p) \ -++ ( REG_PWM_CTR(n) = ((REG_PWM_CTR(n) & ~PWM_CTR_PRESCALE_MASK) | (p) ) ) -++#define __pwm_set_period(n, p) \ -++ ( REG_PWM_PER(n) = ( (REG_PWM_PER(n) & ~PWM_PER_PERIOD_MASK) | (p) ) ) -++#define __pwm_set_duty(n, d) \ -++ ( REG_PWM_DUT(n) = ( (REG_PWM_DUT(n) & ~(PWM_DUT_FDUTY | PWM_DUT_DUTY_MASK)) | (d) ) ) -++ -++/*************************************************************************** -++ * EMC -++ ***************************************************************************/ -++ -++#define __emc_enable_split() ( REG_EMC_BCR = EMC_BCR_BRE ) -++#define __emc_disable_split() ( REG_EMC_BCR = 0 ) -++ -++#define __emc_smem_bus_width(n) /* 8, 16 or 32*/ \ -++ ( REG_EMC_SMCR = (REG_EMC_SMCR & EMC_SMCR_BW_MASK) | \ -++ EMC_SMCR_BW_##n##BIT ) -++#define __emc_smem_byte_control() \ -++ ( REG_EMC_SMCR = (REG_EMC_SMCR | EMC_SMCR_BCM ) -++#define __emc_normal_smem() \ -++ ( REG_EMC_SMCR = (REG_EMC_SMCR & ~EMC_SMCR_SMT ) -++#define __emc_burst_smem() \ -++ ( REG_EMC_SMCR = (REG_EMC_SMCR | EMC_SMCR_SMT ) -++#define __emc_smem_burstlen(n) /* 4, 8, 16 or 32 */ \ -++ ( REG_EMC_SMCR = (REG_EMC_SMCR & EMC_SMCR_BL_MASK) | (EMC_SMCR_BL_##n ) -++ -++/*************************************************************************** -++ * GPIO -++ ***************************************************************************/ -++ -++/* p is the port number (0,1,2,3) -++ * o is the pin offset (0-31) inside the port -++ * n is the absolute number of a pin (0-124), regardless of the port -++ * m is the interrupt manner (low/high/falling/rising) -++ */ -++ -++#define __gpio_port_data(p) ( REG_GPIO_GPDR(p) ) -++ -++#define __gpio_port_as_output(p, o) \ -++do { \ -++ unsigned int tmp; \ -++ REG_GPIO_GPIER(p) &= ~(1 << (o)); \ -++ REG_GPIO_GPDIR(p) |= (1 << (o)); \ -++ if (o < 16) { \ -++ tmp = REG_GPIO_GPALR(p); \ -++ tmp &= ~(3 << ((o) << 1)); \ -++ REG_GPIO_GPALR(p) = tmp; \ -++ } else { \ -++ tmp = REG_GPIO_GPAUR(p); \ -++ tmp &= ~(3 << (((o) - 16)<< 1)); \ -++ REG_GPIO_GPAUR(p) = tmp; \ -++ } \ -++} while (0) -++ -++#define __gpio_port_as_input(p, o) \ -++do { \ -++ unsigned int tmp; \ -++ REG_GPIO_GPIER(p) &= ~(1 << (o)); \ -++ REG_GPIO_GPDIR(p) &= ~(1 << (o)); \ -++ if (o < 16) { \ -++ tmp = REG_GPIO_GPALR(p); \ -++ tmp &= ~(3 << ((o) << 1)); \ -++ REG_GPIO_GPALR(p) = tmp; \ -++ } else { \ -++ tmp = REG_GPIO_GPAUR(p); \ -++ tmp &= ~(3 << (((o) - 16)<< 1)); \ -++ REG_GPIO_GPAUR(p) = tmp; \ -++ } \ -++} while (0) -++ -++#define __gpio_as_output(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ __gpio_port_as_output(p, o); \ -++} while (0) -++ -++#define __gpio_as_input(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ __gpio_port_as_input(p, o); \ -++} while (0) -++ -++#define __gpio_set_pin(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ __gpio_port_data(p) |= (1 << o); \ -++} while (0) -++ -++#define __gpio_clear_pin(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ __gpio_port_data(p) &= ~(1 << o); \ -++} while (0) -++ -++static __inline__ unsigned int __gpio_get_pin(unsigned int n) -++{ -++ unsigned int p, o; -++ p = (n) / 32; -++ o = (n) % 32; -++ if (__gpio_port_data(p) & (1 << o)) -++ return 1; -++ else -++ return 0; -++} -++ -++#define __gpio_set_irq_detect_manner(p, o, m) \ -++do { \ -++ unsigned int tmp; \ -++ if (o < 16) { \ -++ tmp = REG_GPIO_GPIDLR(p); \ -++ tmp &= ~(3 << ((o) << 1)); \ -++ tmp |= ((m) << ((o) << 1)); \ -++ REG_GPIO_GPIDLR(p) = tmp; \ -++ } else { \ -++ tmp = REG_GPIO_GPIDUR(p); \ -++ tmp &= ~(3 << (((o)-16) << 1)); \ -++ tmp |= ((m) << (((o)-16) << 1)); \ -++ REG_GPIO_GPIDUR(p) = tmp; \ -++ } \ -++} while (0) -++ -++#define __gpio_port_as_irq(p, o, m) \ -++do { \ -++ __gpio_port_as_input(p, o); \ -++ __gpio_set_irq_detect_manner(p, o, m); \ -++} while (0) -++ -++#define __gpio_as_irq(n, m) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ __gpio_port_as_irq(p, o, m); \ -++} while (0) -++ -++ -++#define __gpio_as_irq_high_level(n) __gpio_as_irq(n, GPIO_IRQ_HILEVEL) -++#define __gpio_as_irq_low_level(n) __gpio_as_irq(n, GPIO_IRQ_LOLEVEL) -++#define __gpio_as_irq_fall_edge(n) __gpio_as_irq(n, GPIO_IRQ_FALLEDG) -++#define __gpio_as_irq_rise_edge(n) __gpio_as_irq(n, GPIO_IRQ_RAISEDG) -++ -++ -++#define __gpio_mask_irq(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_GPIER(p) &= ~(1 << o); \ -++} while (0) -++ -++#define __gpio_unmask_irq(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_GPIER(p) |= (1 << o); \ -++} while (0) -++ -++#define __gpio_ack_irq(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_GPFR(p) |= (1 << o); \ -++} while (0) -++ -++ -++static __inline__ unsigned int __gpio_get_irq(void) -++{ -++ unsigned int tmp, i; -++ -++ tmp = REG_GPIO_GPFR(3); -++ for (i=0; i<32; i++) -++ if (tmp & (1 << i)) -++ return 0x60 + i; -++ tmp = REG_GPIO_GPFR(2); -++ for (i=0; i<32; i++) -++ if (tmp & (1 << i)) -++ return 0x40 + i; -++ tmp = REG_GPIO_GPFR(1); -++ for (i=0; i<32; i++) -++ if (tmp & (1 << i)) -++ return 0x20 + i; -++ tmp = REG_GPIO_GPFR(0); -++ for (i=0; i<32; i++) -++ if (tmp & (1 << i)) -++ return i; -++ return 0; -++} -++ -++#define __gpio_group_irq(n) \ -++({ \ -++ register int tmp, i; \ -++ tmp = REG_GPIO_GPFR((n)); \ -++ for (i=31;i>=0;i--) \ -++ if (tmp & (1 << i)) \ -++ break; \ -++ i; \ -++}) -++ -++#define __gpio_enable_pull(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_GPPUR(p) |= (1 << o); \ -++} while (0) -++ -++#define __gpio_disable_pull(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_GPPUR(p) &= ~(1 << o); \ -++} while (0) -++ -++ -++/* Init the alternate function pins */ -++ -++ -++#define __gpio_as_ssi() \ -++do { \ -++ REG_GPIO_GPALR(2) &= 0xFC00FFFF; \ -++ REG_GPIO_GPALR(2) |= 0x01550000; \ -++} while (0) -++ -++#define __gpio_as_uart3() \ -++do { \ -++ REG_GPIO_GPAUR(0) &= 0xFFFF0000; \ -++ REG_GPIO_GPAUR(0) |= 0x00005555; \ -++} while (0) -++ -++#define __gpio_as_uart2() \ -++do { \ -++ REG_GPIO_GPALR(3) &= 0x3FFFFFFF; \ -++ REG_GPIO_GPALR(3) |= 0x40000000; \ -++ REG_GPIO_GPAUR(3) &= 0xF3FFFFFF; \ -++ REG_GPIO_GPAUR(3) |= 0x04000000; \ -++} while (0) -++ -++#define __gpio_as_uart1() \ -++do { \ -++ REG_GPIO_GPAUR(0) &= 0xFFF0FFFF; \ -++ REG_GPIO_GPAUR(0) |= 0x00050000; \ -++} while (0) -++ -++#define __gpio_as_uart0() \ -++do { \ -++ REG_GPIO_GPAUR(3) &= 0x0FFFFFFF; \ -++ REG_GPIO_GPAUR(3) |= 0x50000000; \ -++} while (0) -++ -++ -++#define __gpio_as_scc0() \ -++do { \ -++ REG_GPIO_GPALR(2) &= 0xFFFFFFCC; \ -++ REG_GPIO_GPALR(2) |= 0x00000011; \ -++} while (0) -++ -++#define __gpio_as_scc1() \ -++do { \ -++ REG_GPIO_GPALR(2) &= 0xFFFFFF33; \ -++ REG_GPIO_GPALR(2) |= 0x00000044; \ -++} while (0) -++ -++#define __gpio_as_scc() \ -++do { \ -++ __gpio_as_scc0(); \ -++ __gpio_as_scc1(); \ -++} while (0) -++ -++#define __gpio_as_dma() \ -++do { \ -++ REG_GPIO_GPALR(0) &= 0x00FFFFFF; \ -++ REG_GPIO_GPALR(0) |= 0x55000000; \ -++ REG_GPIO_GPAUR(0) &= 0xFF0FFFFF; \ -++ REG_GPIO_GPAUR(0) |= 0x00500000; \ -++} while (0) -++ -++#define __gpio_as_msc() \ -++do { \ -++ REG_GPIO_GPALR(1) &= 0xFFFF000F; \ -++ REG_GPIO_GPALR(1) |= 0x00005550; \ -++} while (0) -++ -++#define __gpio_as_pcmcia() \ -++do { \ -++ REG_GPIO_GPAUR(2) &= 0xF000FFFF; \ -++ REG_GPIO_GPAUR(2) |= 0x05550000; \ -++} while (0) -++ -++#define __gpio_as_emc(csmask) \ -++do { \ -++ REG_GPIO_GPALR(2) &= 0x3FFFFFFF; \ -++ REG_GPIO_GPALR(2) |= 0x40000000; \ -++ REG_GPIO_GPAUR(2) &= 0xFFFF0000; \ -++ REG_GPIO_GPAUR(2) |= 0x00005555; \ -++} while (0) -++ -++#define __gpio_as_lcd_slave() \ -++do { \ -++ REG_GPIO_GPALR(1) &= 0x0000FFFF; \ -++ REG_GPIO_GPALR(1) |= 0x55550000; \ -++ REG_GPIO_GPAUR(1) &= 0x00000000; \ -++ REG_GPIO_GPAUR(1) |= 0x55555555; \ -++} while (0) -++ -++#define __gpio_as_lcd_master() \ -++do { \ -++ REG_GPIO_GPALR(1) &= 0x0000FFFF; \ -++ REG_GPIO_GPALR(1) |= 0x55550000; \ -++ REG_GPIO_GPAUR(1) &= 0x00000000; \ -++ REG_GPIO_GPAUR(1) |= 0x556A5555; \ -++} while (0) -++ -++#define __gpio_as_usb() \ -++do { \ -++ REG_GPIO_GPAUR(0) &= 0x00FFFFFF; \ -++ REG_GPIO_GPAUR(0) |= 0x55000000; \ -++} while (0) -++ -++#define __gpio_as_ac97() \ -++do { \ -++ REG_GPIO_GPALR(2) &= 0xC3FF03FF; \ -++ REG_GPIO_GPALR(2) |= 0x24005400; \ -++} while (0) -++ -++#define __gpio_as_i2s_slave() \ -++do { \ -++ REG_GPIO_GPALR(2) &= 0xC3FF0CFF; \ -++ REG_GPIO_GPALR(2) |= 0x14005100; \ -++} while (0) -++ -++#define __gpio_as_i2s_master() \ -++do { \ -++ REG_GPIO_GPALR(2) &= 0xC3FF0CFF; \ -++ REG_GPIO_GPALR(2) |= 0x28005100; \ -++} while (0) -++ -++#define __gpio_as_eth() \ -++do { \ -++ REG_GPIO_GPAUR(3) &= 0xFC000000; \ -++ REG_GPIO_GPAUR(3) |= 0x01555555; \ -++} while (0) -++ -++#define __gpio_as_pwm() \ -++do { \ -++ REG_GPIO_GPAUR(2) &= 0x0FFFFFFF; \ -++ REG_GPIO_GPAUR(2) |= 0x50000000; \ -++} while (0) -++ -++#define __gpio_as_ps2() \ -++do { \ -++ REG_GPIO_GPALR(1) &= 0xFFFFFFF0; \ -++ REG_GPIO_GPALR(1) |= 0x00000005; \ -++} while (0) -++ -++#define __gpio_as_uprt() \ -++do { \ -++ REG_GPIO_GPALR(1) &= 0x0000000F; \ -++ REG_GPIO_GPALR(1) |= 0x55555550; \ -++ REG_GPIO_GPALR(3) &= 0xC0000000; \ -++ REG_GPIO_GPALR(3) |= 0x15555555; \ -++} while (0) -++ -++#define __gpio_as_cim() \ -++do { \ -++ REG_GPIO_GPALR(0) &= 0xFF000000; \ -++ REG_GPIO_GPALR(0) |= 0x00555555; \ -++} while (0) -++ -++/*************************************************************************** -++ * HARB -++ ***************************************************************************/ -++ -++#define __harb_usb0_udc() \ -++do { \ -++ REG_HARB_HAPOR &= ~HARB_HAPOR_UCHSEL; \ -++} while (0) -++ -++#define __harb_usb0_uhc() \ -++do { \ -++ REG_HARB_HAPOR |= HARB_HAPOR_UCHSEL; \ -++} while (0) -++ -++#define __harb_set_priority(n) \ -++do { \ -++ REG_HARB_HAPOR = ((REG_HARB_HAPOR & ~HARB_HAPOR_PRIO_MASK) | n); \ -++} while (0) -++ -++/*************************************************************************** -++ * I2C -++ ***************************************************************************/ -++ -++#define __i2c_enable() ( REG_I2C_CR |= I2C_CR_I2CE ) -++#define __i2c_disable() ( REG_I2C_CR &= ~I2C_CR_I2CE ) -++ -++#define __i2c_send_start() ( REG_I2C_CR |= I2C_CR_STA ) -++#define __i2c_send_stop() ( REG_I2C_CR |= I2C_CR_STO ) -++#define __i2c_send_ack() ( REG_I2C_CR &= ~I2C_CR_AC ) -++#define __i2c_send_nack() ( REG_I2C_CR |= I2C_CR_AC ) -++ -++#define __i2c_set_drf() ( REG_I2C_SR |= I2C_SR_DRF ) -++#define __i2c_clear_drf() ( REG_I2C_SR &= ~I2C_SR_DRF ) -++#define __i2c_check_drf() ( REG_I2C_SR & I2C_SR_DRF ) -++ -++#define __i2c_received_ack() ( !(REG_I2C_SR & I2C_SR_ACKF) ) -++#define __i2c_is_busy() ( REG_I2C_SR & I2C_SR_BUSY ) -++#define __i2c_transmit_ended() ( REG_I2C_SR & I2C_SR_TEND ) -++ -++#define __i2c_set_clk(dev_clk, i2c_clk) \ -++ ( REG_I2C_GR = (dev_clk) / (16*(i2c_clk)) - 1 ) -++ -++#define __i2c_read() ( REG_I2C_DR ) -++#define __i2c_write(val) ( REG_I2C_DR = (val) ) -++ -++/*************************************************************************** -++ * UDC -++ ***************************************************************************/ -++ -++#define __udc_set_16bit_phy() ( REG_UDC_DevCFGR |= UDC_DevCFGR_PI ) -++#define __udc_set_8bit_phy() ( REG_UDC_DevCFGR &= ~UDC_DevCFGR_PI ) -++ -++#define __udc_enable_sync_frame() ( REG_UDC_DevCFGR |= UDC_DevCFGR_SS ) -++#define __udc_disable_sync_frame() ( REG_UDC_DevCFGR &= ~UDC_DevCFGR_SS ) -++ -++#define __udc_self_powered() ( REG_UDC_DevCFGR |= UDC_DevCFGR_SP ) -++#define __udc_bus_powered() ( REG_UDC_DevCFGR &= ~UDC_DevCFGR_SP ) -++ -++#define __udc_enable_remote_wakeup() ( REG_UDC_DevCFGR |= UDC_DevCFGR_RW ) -++#define __udc_disable_remote_wakeup() ( REG_UDC_DevCFGR &= ~UDC_DevCFGR_RW ) -++ -++#define __udc_set_speed_high() \ -++do { \ -++ REG_UDC_DevCFGR &= ~UDC_DevCFGR_SPD_MASK; \ -++ REG_UDC_DevCFGR |= UDC_DevCFGR_SPD_HS; \ -++} while (0) -++ -++#define __udc_set_speed_full() \ -++do { \ -++ REG_UDC_DevCFGR &= ~UDC_DevCFGR_SPD_MASK; \ -++ REG_UDC_DevCFGR |= UDC_DevCFGR_SPD_FS; \ -++} while (0) -++ -++#define __udc_set_speed_low() \ -++do { \ -++ REG_UDC_DevCFGR &= ~UDC_DevCFGR_SPD_MASK; \ -++ REG_UDC_DevCFGR |= UDC_DevCFGR_SPD_LS; \ -++} while (0) -++ -++ -++#define __udc_set_dma_mode() ( REG_UDC_DevCR |= UDC_DevCR_DM ) -++#define __udc_set_slave_mode() ( REG_UDC_DevCR &= ~UDC_DevCR_DM ) -++#define __udc_set_big_endian() ( REG_UDC_DevCR |= UDC_DevCR_BE ) -++#define __udc_set_little_endian() ( REG_UDC_DevCR &= ~UDC_DevCR_BE ) -++#define __udc_generate_resume() ( REG_UDC_DevCR |= UDC_DevCR_RES ) -++#define __udc_clear_resume() ( REG_UDC_DevCR &= ~UDC_DevCR_RES ) -++ -++ -++#define __udc_get_enumarated_speed() ( REG_UDC_DevSR & UDC_DevSR_ENUMSPD_MASK ) -++#define __udc_suspend_detected() ( REG_UDC_DevSR & UDC_DevSR_SUSP ) -++#define __udc_get_alternate_setting() ( (REG_UDC_DevSR & UDC_DevSR_ALT_MASK) >> UDC_DevSR_ALT_BIT ) -++#define __udc_get_interface_number() ( (REG_UDC_DevSR & UDC_DevSR_INTF_MASK) >> UDC_DevSR_INTF_BIT ) -++#define __udc_get_config_number() ( (REG_UDC_DevSR & UDC_DevSR_CFG_MASK) >> UDC_DevSR_CFG_BIT ) -++ -++ -++#define __udc_sof_detected(r) ( (r) & UDC_DevIntR_SOF ) -++#define __udc_usb_suspend_detected(r) ( (r) & UDC_DevIntR_US ) -++#define __udc_usb_reset_detected(r) ( (r) & UDC_DevIntR_UR ) -++#define __udc_set_interface_detected(r) ( (r) & UDC_DevIntR_SI ) -++#define __udc_set_config_detected(r) ( (r) & UDC_DevIntR_SC ) -++ -++#define __udc_clear_sof() ( REG_UDC_DevIntR |= UDC_DevIntR_SOF ) -++#define __udc_clear_usb_suspend() ( REG_UDC_DevIntR |= UDC_DevIntR_US ) -++#define __udc_clear_usb_reset() ( REG_UDC_DevIntR |= UDC_DevIntR_UR ) -++#define __udc_clear_set_interface() ( REG_UDC_DevIntR |= UDC_DevIntR_SI ) -++#define __udc_clear_set_config() ( REG_UDC_DevIntR |= UDC_DevIntR_SC ) -++ -++#define __udc_mask_sof() ( REG_UDC_DevIntMR |= UDC_DevIntR_SOF ) -++#define __udc_mask_usb_suspend() ( REG_UDC_DevIntMR |= UDC_DevIntR_US ) -++#define __udc_mask_usb_reset() ( REG_UDC_DevIntMR |= UDC_DevIntR_UR ) -++#define __udc_mask_set_interface() ( REG_UDC_DevIntMR |= UDC_DevIntR_SI ) -++#define __udc_mask_set_config() ( REG_UDC_DevIntMR |= UDC_DevIntR_SC ) -++#define __udc_mask_all_dev_intrs() \ -++ ( REG_UDC_DevIntMR = UDC_DevIntR_SOF | UDC_DevIntR_US | \ -++ UDC_DevIntR_UR | UDC_DevIntR_SI | UDC_DevIntR_SC ) -++ -++#define __udc_unmask_sof() ( REG_UDC_DevIntMR &= ~UDC_DevIntR_SOF ) -++#define __udc_unmask_usb_suspend() ( REG_UDC_DevIntMR &= ~UDC_DevIntR_US ) -++#define __udc_unmask_usb_reset() ( REG_UDC_DevIntMR &= ~UDC_DevIntR_UR ) -++#define __udc_unmask_set_interface() ( REG_UDC_DevIntMR &= ~UDC_DevIntR_SI ) -++#define __udc_unmask_set_config() ( REG_UDC_DevIntMR &= ~UDC_DevIntR_SC ) -++#if 0 -++#define __udc_unmask_all_dev_intrs() \ -++ ( REG_UDC_DevIntMR = ~(UDC_DevIntR_SOF | UDC_DevIntR_US | \ -++ UDC_DevIntR_UR | UDC_DevIntR_SI | UDC_DevIntR_SC) ) -++#else -++#define __udc_unmask_all_dev_intrs() \ -++ ( REG_UDC_DevIntMR = 0x00000000 ) -++#endif -++ -++ -++#define __udc_ep0out_irq_detected(epintr) \ -++ ( (((epintr) & UDC_EPIntR_OUTEP_MASK) >> (UDC_EPIntR_OUTEP_BIT + 0)) & 0x1 ) -++#define __udc_ep5out_irq_detected(epintr) \ -++ ( (((epintr) & UDC_EPIntR_OUTEP_MASK) >> (UDC_EPIntR_OUTEP_BIT + 5)) & 0x1 ) -++#define __udc_ep6out_irq_detected(epintr) \ -++ ( (((epintr) & UDC_EPIntR_OUTEP_MASK) >> (UDC_EPIntR_OUTEP_BIT + 6)) & 0x1 ) -++#define __udc_ep7out_irq_detected(epintr) \ -++ ( (((epintr) & UDC_EPIntR_OUTEP_MASK) >> (UDC_EPIntR_OUTEP_BIT + 7)) & 0x1 ) -++ -++#define __udc_ep0in_irq_detected(epintr) \ -++ ( (((epintr) & UDC_EPIntR_INEP_MASK) >> (UDC_EPIntR_INEP_BIT + 0)) & 0x1 ) -++#define __udc_ep1in_irq_detected(epintr) \ -++ ( (((epintr) & UDC_EPIntR_INEP_MASK) >> (UDC_EPIntR_INEP_BIT + 1)) & 0x1 ) -++#define __udc_ep2in_irq_detected(epintr) \ -++ ( (((epintr) & UDC_EPIntR_INEP_MASK) >> (UDC_EPIntR_INEP_BIT + 2)) & 0x1 ) -++#define __udc_ep3in_irq_detected(epintr) \ -++ ( (((epintr) & UDC_EPIntR_INEP_MASK) >> (UDC_EPIntR_INEP_BIT + 3)) & 0x1 ) -++#define __udc_ep4in_irq_detected(epintr) \ -++ ( (((epintr) & UDC_EPIntR_INEP_MASK) >> (UDC_EPIntR_INEP_BIT + 4)) & 0x1 ) -++ -++ -++#define __udc_mask_ep0out_irq() \ -++ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_OUTEP_BIT + 0)) ) -++#define __udc_mask_ep5out_irq() \ -++ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_OUTEP_BIT + 5)) ) -++#define __udc_mask_ep6out_irq() \ -++ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_OUTEP_BIT + 6)) ) -++#define __udc_mask_ep7out_irq() \ -++ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_OUTEP_BIT + 7)) ) -++ -++#define __udc_unmask_ep0out_irq() \ -++ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_OUTEP_BIT + 0)) ) -++#define __udc_unmask_ep5out_irq() \ -++ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_OUTEP_BIT + 5)) ) -++#define __udc_unmask_ep6out_irq() \ -++ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_OUTEP_BIT + 6)) ) -++#define __udc_unmask_ep7out_irq() \ -++ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_OUTEP_BIT + 7)) ) -++ -++#define __udc_mask_ep0in_irq() \ -++ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_INEP_BIT + 0)) ) -++#define __udc_mask_ep1in_irq() \ -++ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_INEP_BIT + 1)) ) -++#define __udc_mask_ep2in_irq() \ -++ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_INEP_BIT + 2)) ) -++#define __udc_mask_ep3in_irq() \ -++ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_INEP_BIT + 3)) ) -++#define __udc_mask_ep4in_irq() \ -++ ( REG_UDC_EPIntMR |= (1 << (UDC_EPIntMR_INEP_BIT + 4)) ) -++ -++#define __udc_unmask_ep0in_irq() \ -++ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_INEP_BIT + 0)) ) -++#define __udc_unmask_ep1in_irq() \ -++ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_INEP_BIT + 1)) ) -++#define __udc_unmask_ep2in_irq() \ -++ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_INEP_BIT + 2)) ) -++#define __udc_unmask_ep3in_irq() \ -++ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_INEP_BIT + 3)) ) -++#define __udc_unmask_ep4in_irq() \ -++ ( REG_UDC_EPIntMR &= ~(1 << (UDC_EPIntMR_INEP_BIT + 4)) ) -++ -++#define __udc_mask_all_ep_intrs() \ -++ ( REG_UDC_EPIntMR = 0xffffffff ) -++#define __udc_unmask_all_ep_intrs() \ -++ ( REG_UDC_EPIntMR = 0x00000000 ) -++ -++ -++/* ep0 only CTRL, ep1 only INTR, ep2/3/5/6 only BULK, ep4/7 only ISO */ -++#define __udc_config_endpoint_type() \ -++do { \ -++ REG_UDC_EP0InCR = (REG_UDC_EP0InCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_CTRL; \ -++ REG_UDC_EP0OutCR = (REG_UDC_EP0OutCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_CTRL; \ -++ REG_UDC_EP1InCR = (REG_UDC_EP1InCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_INTR; \ -++ REG_UDC_EP2InCR = (REG_UDC_EP2InCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_BULK; \ -++ REG_UDC_EP3InCR = (REG_UDC_EP3InCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_BULK; \ -++ REG_UDC_EP4InCR = (REG_UDC_EP4InCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_ISO; \ -++ REG_UDC_EP5OutCR = (REG_UDC_EP5OutCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_BULK; \ -++ REG_UDC_EP6OutCR = (REG_UDC_EP6OutCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_BULK; \ -++ REG_UDC_EP7OutCR = (REG_UDC_EP7OutCR & ~UDC_EPCR_ET_MASK) | UDC_EPCR_ET_ISO; \ -++} while (0) -++ -++#define __udc_enable_ep0out_snoop_mode() ( REG_UDC_EP0OutCR |= UDC_EPCR_SN ) -++#define __udc_enable_ep5out_snoop_mode() ( REG_UDC_EP5OutCR |= UDC_EPCR_SN ) -++#define __udc_enable_ep6out_snoop_mode() ( REG_UDC_EP6OutCR |= UDC_EPCR_SN ) -++#define __udc_enable_ep7out_snoop_mode() ( REG_UDC_EP7OutCR |= UDC_EPCR_SN ) -++ -++#define __udc_disable_ep0out_snoop_mode() ( REG_UDC_EP0OutCR &= ~UDC_EPCR_SN ) -++#define __udc_disable_ep5out_snoop_mode() ( REG_UDC_EP5OutCR &= ~UDC_EPCR_SN ) -++#define __udc_disable_ep6out_snoop_mode() ( REG_UDC_EP6OutCR &= ~UDC_EPCR_SN ) -++#define __udc_disable_ep7out_snoop_mode() ( REG_UDC_EP7OutCR &= ~UDC_EPCR_SN ) -++ -++#define __udc_flush_ep0in_fifo() ( REG_UDC_EP0InCR |= UDC_EPCR_F ) -++#define __udc_flush_ep1in_fifo() ( REG_UDC_EP1InCR |= UDC_EPCR_F ) -++#define __udc_flush_ep2in_fifo() ( REG_UDC_EP2InCR |= UDC_EPCR_F ) -++#define __udc_flush_ep3in_fifo() ( REG_UDC_EP3InCR |= UDC_EPCR_F ) -++#define __udc_flush_ep4in_fifo() ( REG_UDC_EP4InCR |= UDC_EPCR_F ) -++ -++#define __udc_unflush_ep0in_fifo() ( REG_UDC_EP0InCR &= ~UDC_EPCR_F ) -++#define __udc_unflush_ep1in_fifo() ( REG_UDC_EP1InCR &= ~UDC_EPCR_F ) -++#define __udc_unflush_ep2in_fifo() ( REG_UDC_EP2InCR &= ~UDC_EPCR_F ) -++#define __udc_unflush_ep3in_fifo() ( REG_UDC_EP3InCR &= ~UDC_EPCR_F ) -++#define __udc_unflush_ep4in_fifo() ( REG_UDC_EP4InCR &= ~UDC_EPCR_F ) -++ -++#define __udc_enable_ep0in_stall() ( REG_UDC_EP0InCR |= UDC_EPCR_S ) -++#define __udc_enable_ep0out_stall() ( REG_UDC_EP0OutCR |= UDC_EPCR_S ) -++#define __udc_enable_ep1in_stall() ( REG_UDC_EP1InCR |= UDC_EPCR_S ) -++#define __udc_enable_ep2in_stall() ( REG_UDC_EP2InCR |= UDC_EPCR_S ) -++#define __udc_enable_ep3in_stall() ( REG_UDC_EP3InCR |= UDC_EPCR_S ) -++#define __udc_enable_ep4in_stall() ( REG_UDC_EP4InCR |= UDC_EPCR_S ) -++#define __udc_enable_ep5out_stall() ( REG_UDC_EP5OutCR |= UDC_EPCR_S ) -++#define __udc_enable_ep6out_stall() ( REG_UDC_EP6OutCR |= UDC_EPCR_S ) -++#define __udc_enable_ep7out_stall() ( REG_UDC_EP7OutCR |= UDC_EPCR_S ) -++ -++#define __udc_disable_ep0in_stall() ( REG_UDC_EP0InCR &= ~UDC_EPCR_S ) -++#define __udc_disable_ep0out_stall() ( REG_UDC_EP0OutCR &= ~UDC_EPCR_S ) -++#define __udc_disable_ep1in_stall() ( REG_UDC_EP1InCR &= ~UDC_EPCR_S ) -++#define __udc_disable_ep2in_stall() ( REG_UDC_EP2InCR &= ~UDC_EPCR_S ) -++#define __udc_disable_ep3in_stall() ( REG_UDC_EP3InCR &= ~UDC_EPCR_S ) -++#define __udc_disable_ep4in_stall() ( REG_UDC_EP4InCR &= ~UDC_EPCR_S ) -++#define __udc_disable_ep5out_stall() ( REG_UDC_EP5OutCR &= ~UDC_EPCR_S ) -++#define __udc_disable_ep6out_stall() ( REG_UDC_EP6OutCR &= ~UDC_EPCR_S ) -++#define __udc_disable_ep7out_stall() ( REG_UDC_EP7OutCR &= ~UDC_EPCR_S ) -++ -++ -++#define __udc_ep0out_packet_size() \ -++ ( (REG_UDC_EP0OutSR & UDC_EPSR_RXPKTSIZE_MASK) >> UDC_EPSR_RXPKTSIZE_BIT ) -++#define __udc_ep5out_packet_size() \ -++ ( (REG_UDC_EP5OutSR & UDC_EPSR_RXPKTSIZE_MASK) >> UDC_EPSR_RXPKTSIZE_BIT ) -++#define __udc_ep6out_packet_size() \ -++ ( (REG_UDC_EP6OutSR & UDC_EPSR_RXPKTSIZE_MASK) >> UDC_EPSR_RXPKTSIZE_BIT ) -++#define __udc_ep7out_packet_size() \ -++ ( (REG_UDC_EP7OutSR & UDC_EPSR_RXPKTSIZE_MASK) >> UDC_EPSR_RXPKTSIZE_BIT ) -++ -++#define __udc_ep0in_received_intoken() ( (REG_UDC_EP0InSR & UDC_EPSR_IN) ) -++#define __udc_ep1in_received_intoken() ( (REG_UDC_EP1InSR & UDC_EPSR_IN) ) -++#define __udc_ep2in_received_intoken() ( (REG_UDC_EP2InSR & UDC_EPSR_IN) ) -++#define __udc_ep3in_received_intoken() ( (REG_UDC_EP3InSR & UDC_EPSR_IN) ) -++#define __udc_ep4in_received_intoken() ( (REG_UDC_EP4InSR & UDC_EPSR_IN) ) -++ -++#define __udc_ep0out_received_none() \ -++ ( (REG_UDC_EP0OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_NONE ) -++#define __udc_ep0out_received_data() \ -++ ( (REG_UDC_EP0OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_RCVDATA ) -++#define __udc_ep0out_received_setup() \ -++ ( (REG_UDC_EP0OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_RCVSETUP ) -++ -++#define __udc_ep5out_received_none() \ -++ ( (REG_UDC_EP5OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_NONE ) -++#define __udc_ep5out_received_data() \ -++ ( (REG_UDC_EP5OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_RCVDATA ) -++#define __udc_ep5out_received_setup() \ -++ ( (REG_UDC_EP5OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_RCVSETUP ) -++ -++#define __udc_ep6out_received_none() \ -++ ( (REG_UDC_EP6OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_NONE ) -++#define __udc_ep6out_received_data() \ -++ ( (REG_UDC_EP6OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_RCVDATA ) -++#define __udc_ep6out_received_setup() \ -++ ( (REG_UDC_EP6OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_RCVSETUP ) -++ -++#define __udc_ep7out_received_none() \ -++ ( (REG_UDC_EP7OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_NONE ) -++#define __udc_ep7out_received_data() \ -++ ( (REG_UDC_EP7OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_RCVDATA ) -++#define __udc_ep7out_received_setup() \ -++ ( (REG_UDC_EP7OutSR & UDC_EPSR_OUT_MASK) == UDC_EPSR_OUT_RCVSETUP ) -++ -++/* ep7out ISO only */ -++#define __udc_ep7out_get_pid() \ -++ ( (REG_UDC_EP7OutSR & UDC_EPSR_PID_MASK) >> UDC_EPSR_PID_BIT ) -++ -++ -++#define __udc_ep0in_set_buffer_size(n) ( REG_UDC_EP0InBSR = (n) ) -++#define __udc_ep1in_set_buffer_size(n) ( REG_UDC_EP1InBSR = (n) ) -++#define __udc_ep2in_set_buffer_size(n) ( REG_UDC_EP2InBSR = (n) ) -++#define __udc_ep3in_set_buffer_size(n) ( REG_UDC_EP3InBSR = (n) ) -++#define __udc_ep4in_set_buffer_size(n) ( REG_UDC_EP4InBSR = (n) ) -++ -++#define __udc_ep0out_get_frame_number(n) ( UDC_EP0OutPFNR ) -++#define __udc_ep5out_get_frame_number(n) ( UDC_EP5OutPFNR ) -++#define __udc_ep6out_get_frame_number(n) ( UDC_EP6OutPFNR ) -++#define __udc_ep7out_get_frame_number(n) ( UDC_EP7OutPFNR ) -++ -++ -++#define __udc_ep0in_set_max_packet_size(n) ( REG_UDC_EP0InMPSR = (n) ) -++#define __udc_ep0out_set_max_packet_size(n) ( REG_UDC_EP0OutMPSR = (n) ) -++#define __udc_ep1in_set_max_packet_size(n) ( REG_UDC_EP1InMPSR = (n) ) -++#define __udc_ep2in_set_max_packet_size(n) ( REG_UDC_EP2InMPSR = (n) ) -++#define __udc_ep3in_set_max_packet_size(n) ( REG_UDC_EP3InMPSR = (n) ) -++#define __udc_ep4in_set_max_packet_size(n) ( REG_UDC_EP4InMPSR = (n) ) -++#define __udc_ep5out_set_max_packet_size(n) ( REG_UDC_EP5OutMPSR = (n) ) -++#define __udc_ep6out_set_max_packet_size(n) ( REG_UDC_EP6OutMPSR = (n) ) -++#define __udc_ep7out_set_max_packet_size(n) ( REG_UDC_EP7OutMPSR = (n) ) -++ -++/* set to 0xFFFF for UDC */ -++#define __udc_set_setup_command_address(n) ( REG_UDC_STCMAR = (n) ) -++ -++/* Init and configure EPxInfR(x=0,1,2,3,4,5,6,7) -++ * c: Configuration number to which this endpoint belongs -++ * i: Interface number to which this endpoint belongs -++ * a: Alternate setting to which this endpoint belongs -++ * p: max Packet size of this endpoint -++ */ -++ -++#define __udc_ep0info_init(c,i,a,p) \ -++do { \ -++ REG_UDC_EP0InfR &= ~UDC_EPInfR_MPS_MASK; \ -++ REG_UDC_EP0InfR |= ((p) << UDC_EPInfR_MPS_BIT); \ -++ REG_UDC_EP0InfR &= ~UDC_EPInfR_ALTS_MASK; \ -++ REG_UDC_EP0InfR |= ((a) << UDC_EPInfR_ALTS_BIT); \ -++ REG_UDC_EP0InfR &= ~UDC_EPInfR_IFN_MASK; \ -++ REG_UDC_EP0InfR |= ((i) << UDC_EPInfR_IFN_BIT); \ -++ REG_UDC_EP0InfR &= ~UDC_EPInfR_CGN_MASK; \ -++ REG_UDC_EP0InfR |= ((c) << UDC_EPInfR_CGN_BIT); \ -++ REG_UDC_EP0InfR &= ~UDC_EPInfR_EPT_MASK; \ -++ REG_UDC_EP0InfR |= UDC_EPInfR_EPT_CTRL; \ -++ REG_UDC_EP0InfR &= ~UDC_EPInfR_EPD; \ -++ REG_UDC_EP0InfR |= UDC_EPInfR_EPD_OUT; \ -++ REG_UDC_EP0InfR &= ~UDC_EPInfR_EPN_MASK; \ -++ REG_UDC_EP0InfR |= (0 << UDC_EPInfR_EPN_BIT); \ -++} while (0) -++ -++#define __udc_ep1info_init(c,i,a,p) \ -++do { \ -++ REG_UDC_EP1InfR &= ~UDC_EPInfR_MPS_MASK; \ -++ REG_UDC_EP1InfR |= ((p) << UDC_EPInfR_MPS_BIT); \ -++ REG_UDC_EP1InfR &= ~UDC_EPInfR_ALTS_MASK; \ -++ REG_UDC_EP1InfR |= ((a) << UDC_EPInfR_ALTS_BIT); \ -++ REG_UDC_EP1InfR &= ~UDC_EPInfR_IFN_MASK; \ -++ REG_UDC_EP1InfR |= ((i) << UDC_EPInfR_IFN_BIT); \ -++ REG_UDC_EP1InfR &= ~UDC_EPInfR_CGN_MASK; \ -++ REG_UDC_EP1InfR |= ((c) << UDC_EPInfR_CGN_BIT); \ -++ REG_UDC_EP1InfR &= ~UDC_EPInfR_EPT_MASK; \ -++ REG_UDC_EP1InfR |= UDC_EPInfR_EPT_INTR; \ -++ REG_UDC_EP1InfR &= ~UDC_EPInfR_EPD; \ -++ REG_UDC_EP1InfR |= UDC_EPInfR_EPD_IN; \ -++ REG_UDC_EP1InfR &= ~UDC_EPInfR_EPN_MASK; \ -++ REG_UDC_EP1InfR |= (1 << UDC_EPInfR_EPN_BIT); \ -++} while (0) -++ -++#define __udc_ep2info_init(c,i,a,p) \ -++do { \ -++ REG_UDC_EP2InfR &= ~UDC_EPInfR_MPS_MASK; \ -++ REG_UDC_EP2InfR |= ((p) << UDC_EPInfR_MPS_BIT); \ -++ REG_UDC_EP2InfR &= ~UDC_EPInfR_ALTS_MASK; \ -++ REG_UDC_EP2InfR |= ((a) << UDC_EPInfR_ALTS_BIT); \ -++ REG_UDC_EP2InfR &= ~UDC_EPInfR_IFN_MASK; \ -++ REG_UDC_EP2InfR |= ((i) << UDC_EPInfR_IFN_BIT); \ -++ REG_UDC_EP2InfR &= ~UDC_EPInfR_CGN_MASK; \ -++ REG_UDC_EP2InfR |= ((c) << UDC_EPInfR_CGN_BIT); \ -++ REG_UDC_EP2InfR &= ~UDC_EPInfR_EPT_MASK; \ -++ REG_UDC_EP2InfR |= UDC_EPInfR_EPT_BULK; \ -++ REG_UDC_EP2InfR &= ~UDC_EPInfR_EPD; \ -++ REG_UDC_EP2InfR |= UDC_EPInfR_EPD_IN; \ -++ REG_UDC_EP2InfR &= ~UDC_EPInfR_EPN_MASK; \ -++ REG_UDC_EP2InfR |= (2 << UDC_EPInfR_EPN_BIT); \ -++} while (0) -++ -++#define __udc_ep3info_init(c,i,a,p) \ -++do { \ -++ REG_UDC_EP3InfR &= ~UDC_EPInfR_MPS_MASK; \ -++ REG_UDC_EP3InfR |= ((p) << UDC_EPInfR_MPS_BIT); \ -++ REG_UDC_EP3InfR &= ~UDC_EPInfR_ALTS_MASK; \ -++ REG_UDC_EP3InfR |= ((a) << UDC_EPInfR_ALTS_BIT); \ -++ REG_UDC_EP3InfR &= ~UDC_EPInfR_IFN_MASK; \ -++ REG_UDC_EP3InfR |= ((i) << UDC_EPInfR_IFN_BIT); \ -++ REG_UDC_EP3InfR &= ~UDC_EPInfR_CGN_MASK; \ -++ REG_UDC_EP3InfR |= ((c) << UDC_EPInfR_CGN_BIT); \ -++ REG_UDC_EP3InfR &= ~UDC_EPInfR_EPT_MASK; \ -++ REG_UDC_EP3InfR |= UDC_EPInfR_EPT_BULK; \ -++ REG_UDC_EP3InfR &= ~UDC_EPInfR_EPD; \ -++ REG_UDC_EP3InfR |= UDC_EPInfR_EPD_IN; \ -++ REG_UDC_EP3InfR &= ~UDC_EPInfR_EPN_MASK; \ -++ REG_UDC_EP3InfR |= (3 << UDC_EPInfR_EPN_BIT); \ -++} while (0) -++ -++#define __udc_ep4info_init(c,i,a,p) \ -++do { \ -++ REG_UDC_EP4InfR &= ~UDC_EPInfR_MPS_MASK; \ -++ REG_UDC_EP4InfR |= ((p) << UDC_EPInfR_MPS_BIT); \ -++ REG_UDC_EP4InfR &= ~UDC_EPInfR_ALTS_MASK; \ -++ REG_UDC_EP4InfR |= ((a) << UDC_EPInfR_ALTS_BIT); \ -++ REG_UDC_EP4InfR &= ~UDC_EPInfR_IFN_MASK; \ -++ REG_UDC_EP4InfR |= ((i) << UDC_EPInfR_IFN_BIT); \ -++ REG_UDC_EP4InfR &= ~UDC_EPInfR_CGN_MASK; \ -++ REG_UDC_EP4InfR |= ((c) << UDC_EPInfR_CGN_BIT); \ -++ REG_UDC_EP4InfR &= ~UDC_EPInfR_EPT_MASK; \ -++ REG_UDC_EP4InfR |= UDC_EPInfR_EPT_ISO; \ -++ REG_UDC_EP4InfR &= ~UDC_EPInfR_EPD; \ -++ REG_UDC_EP4InfR |= UDC_EPInfR_EPD_IN; \ -++ REG_UDC_EP4InfR &= ~UDC_EPInfR_EPN_MASK; \ -++ REG_UDC_EP4InfR |= (4 << UDC_EPInfR_EPN_BIT); \ -++} while (0) -++ -++#define __udc_ep5info_init(c,i,a,p) \ -++do { \ -++ REG_UDC_EP5InfR &= ~UDC_EPInfR_MPS_MASK; \ -++ REG_UDC_EP5InfR |= ((p) << UDC_EPInfR_MPS_BIT); \ -++ REG_UDC_EP5InfR &= ~UDC_EPInfR_ALTS_MASK; \ -++ REG_UDC_EP5InfR |= ((a) << UDC_EPInfR_ALTS_BIT); \ -++ REG_UDC_EP5InfR &= ~UDC_EPInfR_IFN_MASK; \ -++ REG_UDC_EP5InfR |= ((i) << UDC_EPInfR_IFN_BIT); \ -++ REG_UDC_EP5InfR &= ~UDC_EPInfR_CGN_MASK; \ -++ REG_UDC_EP5InfR |= ((c) << UDC_EPInfR_CGN_BIT); \ -++ REG_UDC_EP5InfR &= ~UDC_EPInfR_EPT_MASK; \ -++ REG_UDC_EP5InfR |= UDC_EPInfR_EPT_BULK; \ -++ REG_UDC_EP5InfR &= ~UDC_EPInfR_EPD; \ -++ REG_UDC_EP5InfR |= UDC_EPInfR_EPD_OUT; \ -++ REG_UDC_EP5InfR &= ~UDC_EPInfR_EPN_MASK; \ -++ REG_UDC_EP5InfR |= (5 << UDC_EPInfR_EPN_BIT); \ -++} while (0) -++ -++#define __udc_ep6info_init(c,i,a,p) \ -++do { \ -++ REG_UDC_EP6InfR &= ~UDC_EPInfR_MPS_MASK; \ -++ REG_UDC_EP6InfR |= ((p) << UDC_EPInfR_MPS_BIT); \ -++ REG_UDC_EP6InfR &= ~UDC_EPInfR_ALTS_MASK; \ -++ REG_UDC_EP6InfR |= ((a) << UDC_EPInfR_ALTS_BIT); \ -++ REG_UDC_EP6InfR &= ~UDC_EPInfR_IFN_MASK; \ -++ REG_UDC_EP6InfR |= ((i) << UDC_EPInfR_IFN_BIT); \ -++ REG_UDC_EP6InfR &= ~UDC_EPInfR_CGN_MASK; \ -++ REG_UDC_EP6InfR |= ((c) << UDC_EPInfR_CGN_BIT); \ -++ REG_UDC_EP6InfR &= ~UDC_EPInfR_EPT_MASK; \ -++ REG_UDC_EP6InfR |= UDC_EPInfR_EPT_BULK; \ -++ REG_UDC_EP6InfR &= ~UDC_EPInfR_EPD; \ -++ REG_UDC_EP6InfR |= UDC_EPInfR_EPD_OUT; \ -++ REG_UDC_EP6InfR &= ~UDC_EPInfR_EPN_MASK; \ -++ REG_UDC_EP6InfR |= (6 << UDC_EPInfR_EPN_BIT); \ -++} while (0) -++ -++#define __udc_ep7info_init(c,i,a,p) \ -++do { \ -++ REG_UDC_EP7InfR &= ~UDC_EPInfR_MPS_MASK; \ -++ REG_UDC_EP7InfR |= ((p) << UDC_EPInfR_MPS_BIT); \ -++ REG_UDC_EP7InfR &= ~UDC_EPInfR_ALTS_MASK; \ -++ REG_UDC_EP7InfR |= ((a) << UDC_EPInfR_ALTS_BIT); \ -++ REG_UDC_EP7InfR &= ~UDC_EPInfR_IFN_MASK; \ -++ REG_UDC_EP7InfR |= ((i) << UDC_EPInfR_IFN_BIT); \ -++ REG_UDC_EP7InfR &= ~UDC_EPInfR_CGN_MASK; \ -++ REG_UDC_EP7InfR |= ((c) << UDC_EPInfR_CGN_BIT); \ -++ REG_UDC_EP7InfR &= ~UDC_EPInfR_EPT_MASK; \ -++ REG_UDC_EP7InfR |= UDC_EPInfR_EPT_ISO; \ -++ REG_UDC_EP7InfR &= ~UDC_EPInfR_EPD; \ -++ REG_UDC_EP7InfR |= UDC_EPInfR_EPD_OUT; \ -++ REG_UDC_EP7InfR &= ~UDC_EPInfR_EPN_MASK; \ -++ REG_UDC_EP7InfR |= (7 << UDC_EPInfR_EPN_BIT); \ -++} while (0) -++ -++ -++/*************************************************************************** -++ * DMAC -++ ***************************************************************************/ -++ -++/* n is the DMA channel (0 - 7) */ -++ -++#define __dmac_enable_all_channels() \ -++ ( REG_DMAC_DMACR |= DMAC_DMACR_DME | DMAC_DMACR_PR_ROUNDROBIN ) -++#define __dmac_disable_all_channels() \ -++ ( REG_DMAC_DMACR &= ~DMAC_DMACR_DME ) -++ -++/* p=0,1,2,3 */ -++#define __dmac_set_priority(p) \ -++do { \ -++ REG_DMAC_DMACR &= ~DMAC_DMACR_PR_MASK; \ -++ REG_DMAC_DMACR |= ((p) << DMAC_DMACR_PR_BIT); \ -++} while (0) -++ -++#define __dmac_test_halt_error() ( REG_DMAC_DMACR & DMAC_DMACR_HTR ) -++#define __dmac_test_addr_error() ( REG_DMAC_DMACR & DMAC_DMACR_AER ) -++ -++#define __dmac_enable_channel(n) \ -++ ( REG_DMAC_DCCSR(n) |= DMAC_DCCSR_CHDE ) -++#define __dmac_disable_channel(n) \ -++ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_CHDE ) -++#define __dmac_channel_enabled(n) \ -++ ( REG_DMAC_DCCSR(n) & DMAC_DCCSR_CHDE ) -++ -++#define __dmac_channel_enable_irq(n) \ -++ ( REG_DMAC_DCCSR(n) |= DMAC_DCCSR_TCIE ) -++#define __dmac_channel_disable_irq(n) \ -++ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_TCIE ) -++ -++#define __dmac_channel_transmit_halt_detected(n) \ -++ ( REG_DMAC_DCCSR(n) & DMAC_DCCSR_HLT ) -++#define __dmac_channel_transmit_end_detected(n) \ -++ ( REG_DMAC_DCCSR(n) & DMAC_DCCSR_TC ) -++#define __dmac_channel_address_error_detected(n) \ -++ ( REG_DMAC_DCCSR(n) & DMAC_DCCSR_AR ) -++ -++#define __dmac_channel_clear_transmit_halt(n) \ -++ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_HLT ) -++#define __dmac_channel_clear_transmit_end(n) \ -++ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_TC ) -++#define __dmac_channel_clear_address_error(n) \ -++ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_AR ) -++ -++#define __dmac_channel_set_single_mode(n) \ -++ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_TM ) -++#define __dmac_channel_set_block_mode(n) \ -++ ( REG_DMAC_DCCSR(n) |= DMAC_DCCSR_TM ) -++ -++#define __dmac_channel_set_transfer_unit_32bit(n) \ -++do { \ -++ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_DS_MASK; \ -++ REG_DMAC_DCCSR(n) |= DMAC_DCCSR_DS_32b; \ -++} while (0) -++ -++#define __dmac_channel_set_transfer_unit_16bit(n) \ -++do { \ -++ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_DS_MASK; \ -++ REG_DMAC_DCCSR(n) |= DMAC_DCCSR_DS_16b; \ -++} while (0) -++ -++#define __dmac_channel_set_transfer_unit_8bit(n) \ -++do { \ -++ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_DS_MASK; \ -++ REG_DMAC_DCCSR(n) |= DMAC_DCCSR_DS_8b; \ -++} while (0) -++ -++#define __dmac_channel_set_transfer_unit_16byte(n) \ -++do { \ -++ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_DS_MASK; \ -++ REG_DMAC_DCCSR(n) |= DMAC_DCCSR_DS_16B; \ -++} while (0) -++ -++#define __dmac_channel_set_transfer_unit_32byte(n) \ -++do { \ -++ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_DS_MASK; \ -++ REG_DMAC_DCCSR(n) |= DMAC_DCCSR_DS_32B; \ -++} while (0) -++ -++/* w=8,16,32 */ -++#define __dmac_channel_set_dest_port_width(n,w) \ -++do { \ -++ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_DWDH_MASK; \ -++ REG_DMAC_DCCSR(n) |= DMAC_DCCSR_DWDH_##w; \ -++} while (0) -++ -++/* w=8,16,32 */ -++#define __dmac_channel_set_src_port_width(n,w) \ -++do { \ -++ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_SWDH_MASK; \ -++ REG_DMAC_DCCSR(n) |= DMAC_DCCSR_SWDH_##w; \ -++} while (0) -++ -++/* v=0-15 */ -++#define __dmac_channel_set_rdil(n,v) \ -++do { \ -++ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_RDIL_MASK; \ -++ REG_DMAC_DCCSR(n) |= ((v) << DMAC_DCCSR_RDIL_BIT); \ -++} while (0) -++ -++#define __dmac_channel_dest_addr_fixed(n) \ -++ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_DAM ) -++#define __dmac_channel_dest_addr_increment(n) \ -++ ( REG_DMAC_DCCSR(n) |= DMAC_DCCSR_DAM ) -++ -++#define __dmac_channel_src_addr_fixed(n) \ -++ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_SAM ) -++#define __dmac_channel_src_addr_increment(n) \ -++ ( REG_DMAC_DCCSR(n) |= DMAC_DCCSR_SAM ) -++ -++#define __dmac_channel_set_eop_high(n) \ -++ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_EOPM ) -++#define __dmac_channel_set_eop_low(n) \ -++ ( REG_DMAC_DCCSR(n) |= DMAC_DCCSR_EOPM ) -++ -++#define __dmac_channel_set_erdm(n,m) \ -++do { \ -++ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_SWDH_MASK; \ -++ REG_DMAC_DCCSR(n) |= ((m) << DMAC_DCCSR_ERDM_BIT); \ -++} while (0) -++ -++#define __dmac_channel_set_eackm(n) \ -++ ( REG_DMAC_DCCSR(n) |= DMAC_DCCSR_EACKM ) -++#define __dmac_channel_clear_eackm(n) \ -++ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_EACKM ) -++ -++#define __dmac_channel_set_eacks(n) \ -++ ( REG_DMAC_DCCSR(n) |= DMAC_DCCSR_EACKS ) -++#define __dmac_channel_clear_eacks(n) \ -++ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_EACKS ) -++ -++ -++#define __dmac_channel_irq_detected(n) \ -++ ( REG_DMAC_DCCSR(n) & (DMAC_DCCSR_TC | DMAC_DCCSR_AR) ) -++ -++static __inline__ int __dmac_get_irq(void) -++{ -++ int i; -++ for (i=0;i> AIC_SR_TFL_BIT ) -++#define __aic_get_receive_count() \ -++ ( (REG_AIC_SR & AIC_SR_RFL_MASK) >> AIC_SR_RFL_BIT ) -++ -++#define __ac97_command_transmitted() ( REG_AIC_ACSR & AIC_ACSR_CADT ) -++#define __ac97_status_received() ( REG_AIC_ACSR & AIC_ACSR_SADR ) -++#define __ac97_status_receive_timeout() ( REG_AIC_ACSR & AIC_ACSR_RSTO ) -++#define __ac97_codec_is_low_power_mode() ( REG_AIC_ACSR & AIC_ACSR_CLPM ) -++#define __ac97_codec_is_ready() ( REG_AIC_ACSR & AIC_ACSR_CRDY ) -++ -++#define __i2s_is_busy() ( REG_AIC_I2SSR & AIC_I2SSR_BSY ) -++ -++#define CODEC_READ_CMD (1 << 19) -++#define CODEC_WRITE_CMD (0 << 19) -++#define CODEC_REG_INDEX_BIT 12 -++#define CODEC_REG_INDEX_MASK (0x7f << CODEC_REG_INDEX_BIT) /* 18:12 */ -++#define CODEC_REG_DATA_BIT 4 -++#define CODEC_REG_DATA_MASK (0x0ffff << 4) /* 19:4 */ -++ -++#define __ac97_out_rcmd_addr(reg) \ -++do { \ -++ REG_AIC_ACCAR = CODEC_READ_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ -++} while (0) -++ -++#define __ac97_out_wcmd_addr(reg) \ -++do { \ -++ REG_AIC_ACCAR = CODEC_WRITE_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ -++} while (0) -++ -++#define __ac97_out_data(value) \ -++do { \ -++ REG_AIC_ACCDR = ((value) << CODEC_REG_DATA_BIT); \ -++} while (0) -++ -++#define __ac97_in_data() \ -++ ( (REG_AIC_ACSDR & CODEC_REG_DATA_MASK) >> CODEC_REG_DATA_BIT ) -++ -++#define __ac97_in_status_addr() \ -++ ( (REG_AIC_ACSAR & CODEC_REG_INDEX_MASK) >> CODEC_REG_INDEX_BIT ) -++ -++#define __i2s_set_sample_rate(i2sclk, sync) \ -++ ( REG_AIC_I2SDIV = ((i2sclk) / (4*64)) / (sync) ) -++ -++#define __aic_write_tfifo(v) ( REG_AIC_DR = (v) ) -++#define __aic_read_rfifo() ( REG_AIC_DR ) -++ -++// -++// Define next ops for AC97 compatible -++// -++ -++#define AC97_ACSR AIC_ACSR -++ -++#define __ac97_enable() __aic_enable(); __aic_select_ac97() -++#define __ac97_disable() __aic_disable() -++#define __ac97_reset() __aic_reset() -++ -++#define __ac97_set_transmit_trigger(n) __aic_set_transmit_trigger(n) -++#define __ac97_set_receive_trigger(n) __aic_set_receive_trigger(n) -++ -++#define __ac97_enable_record() __aic_enable_record() -++#define __ac97_disable_record() __aic_disable_record() -++#define __ac97_enable_replay() __aic_enable_replay() -++#define __ac97_disable_replay() __aic_disable_replay() -++#define __ac97_enable_loopback() __aic_enable_loopback() -++#define __ac97_disable_loopback() __aic_disable_loopback() -++ -++#define __ac97_enable_transmit_dma() __aic_enable_transmit_dma() -++#define __ac97_disable_transmit_dma() __aic_disable_transmit_dma() -++#define __ac97_enable_receive_dma() __aic_enable_receive_dma() -++#define __ac97_disable_receive_dma() __aic_disable_receive_dma() -++ -++#define __ac97_transmit_request() __aic_transmit_request() -++#define __ac97_receive_request() __aic_receive_request() -++#define __ac97_transmit_underrun() __aic_transmit_underrun() -++#define __ac97_receive_overrun() __aic_receive_overrun() -++ -++#define __ac97_clear_errors() __aic_clear_errors() -++ -++#define __ac97_get_transmit_resident() __aic_get_transmit_resident() -++#define __ac97_get_receive_count() __aic_get_receive_count() -++ -++#define __ac97_enable_transmit_intr() __aic_enable_transmit_intr() -++#define __ac97_disable_transmit_intr() __aic_disable_transmit_intr() -++#define __ac97_enable_receive_intr() __aic_enable_receive_intr() -++#define __ac97_disable_receive_intr() __aic_disable_receive_intr() -++ -++#define __ac97_write_tfifo(v) __aic_write_tfifo(v) -++#define __ac97_read_rfifo() __aic_read_rfifo() -++ -++// -++// Define next ops for I2S compatible -++// -++ -++#define I2S_ACSR AIC_I2SSR -++ -++#define __i2s_enable() __aic_enable(); __aic_select_i2s() -++#define __i2s_disable() __aic_disable() -++#define __i2s_reset() __aic_reset() -++ -++#define __i2s_set_transmit_trigger(n) __aic_set_transmit_trigger(n) -++#define __i2s_set_receive_trigger(n) __aic_set_receive_trigger(n) -++ -++#define __i2s_enable_record() __aic_enable_record() -++#define __i2s_disable_record() __aic_disable_record() -++#define __i2s_enable_replay() __aic_enable_replay() -++#define __i2s_disable_replay() __aic_disable_replay() -++#define __i2s_enable_loopback() __aic_enable_loopback() -++#define __i2s_disable_loopback() __aic_disable_loopback() -++ -++#define __i2s_enable_transmit_dma() __aic_enable_transmit_dma() -++#define __i2s_disable_transmit_dma() __aic_disable_transmit_dma() -++#define __i2s_enable_receive_dma() __aic_enable_receive_dma() -++#define __i2s_disable_receive_dma() __aic_disable_receive_dma() -++ -++#define __i2s_transmit_request() __aic_transmit_request() -++#define __i2s_receive_request() __aic_receive_request() -++#define __i2s_transmit_underrun() __aic_transmit_underrun() -++#define __i2s_receive_overrun() __aic_receive_overrun() -++ -++#define __i2s_clear_errors() __aic_clear_errors() -++ -++#define __i2s_get_transmit_resident() __aic_get_transmit_resident() -++#define __i2s_get_receive_count() __aic_get_receive_count() -++ -++#define __i2s_enable_transmit_intr() __aic_enable_transmit_intr() -++#define __i2s_disable_transmit_intr() __aic_disable_transmit_intr() -++#define __i2s_enable_receive_intr() __aic_enable_receive_intr() -++#define __i2s_disable_receive_intr() __aic_disable_receive_intr() -++ -++#define __i2s_write_tfifo(v) __aic_write_tfifo(v) -++#define __i2s_read_rfifo() __aic_read_rfifo() -++ -++#define __i2s_reset_codec() \ -++ do { \ -++ __gpio_as_output(70); /* SDATA_OUT */ \ -++ __gpio_as_input(71); /* SDATA_IN */ \ -++ __gpio_as_output(78); /* SYNC */ \ -++ __gpio_as_output(69); /* RESET# */ \ -++ __gpio_clear_pin(70); \ -++ __gpio_clear_pin(71); \ -++ __gpio_clear_pin(78); \ -++ __gpio_clear_pin(69); \ -++ __gpio_as_i2s_master(); \ -++ } while (0) -++ -++ -++/*************************************************************************** -++ * LCD -++ ***************************************************************************/ -++ -++#define __lcd_set_dis() ( REG_LCD_CTRL |= LCD_CTRL_DIS ) -++#define __lcd_clr_dis() ( REG_LCD_CTRL &= ~LCD_CTRL_DIS ) -++ -++#define __lcd_set_ena() ( REG_LCD_CTRL |= LCD_CTRL_ENA ) -++#define __lcd_clr_ena() ( REG_LCD_CTRL &= ~LCD_CTRL_ENA ) -++ -++/* n=1,2,4,8,16 */ -++#define __lcd_set_bpp(n) \ -++ ( REG_LCD_CTRL = (REG_LCD_CTRL & ~LCD_CTRL_BPP_MASK) | LCD_CTRL_BPP_##n ) -++ -++/* n=4,8,16 */ -++#define __lcd_set_burst_length(n) \ -++do { \ -++ REG_LCD_CTRL &= ~LCD_CTRL_BST_MASK; \ -++ REG_LCD_CTRL |= LCD_CTRL_BST_n##; \ -++} while (0) -++ -++#define __lcd_select_rgb565() ( REG_LCD_CTRL &= ~LCD_CTRL_RGB555 ) -++#define __lcd_select_rgb555() ( REG_LCD_CTRL |= LCD_CTRL_RGB555 ) -++ -++#define __lcd_set_ofup() ( REG_LCD_CTRL |= LCD_CTRL_OFUP ) -++#define __lcd_clr_ofup() ( REG_LCD_CTRL &= ~LCD_CTRL_OFUP ) -++ -++/* n=2,4,16 */ -++#define __lcd_set_stn_frc(n) \ -++do { \ -++ REG_LCD_CTRL &= ~LCD_CTRL_FRC_MASK; \ -++ REG_LCD_CTRL |= LCD_CTRL_FRC_n##; \ -++} while (0) -++ -++ -++#define __lcd_pixel_endian_little() ( REG_LCD_CTRL |= LCD_CTRL_PEDN ) -++#define __lcd_pixel_endian_big() ( REG_LCD_CTRL &= ~LCD_CTRL_PEDN ) -++ -++#define __lcd_reverse_byte_endian() ( REG_LCD_CTRL |= LCD_CTRL_BEDN ) -++#define __lcd_normal_byte_endian() ( REG_LCD_CTRL &= ~LCD_CTRL_BEDN ) -++ -++#define __lcd_enable_eof_intr() ( REG_LCD_CTRL |= LCD_CTRL_EOFM ) -++#define __lcd_disable_eof_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_EOFM ) -++ -++#define __lcd_enable_sof_intr() ( REG_LCD_CTRL |= LCD_CTRL_SOFM ) -++#define __lcd_disable_sof_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_SOFM ) -++ -++#define __lcd_enable_ofu_intr() ( REG_LCD_CTRL |= LCD_CTRL_OFUM ) -++#define __lcd_disable_ofu_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_OFUM ) -++ -++#define __lcd_enable_ifu0_intr() ( REG_LCD_CTRL |= LCD_CTRL_IFUM0 ) -++#define __lcd_disable_ifu0_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_IFUM0 ) -++ -++#define __lcd_enable_ifu1_intr() ( REG_LCD_CTRL |= LCD_CTRL_IFUM1 ) -++#define __lcd_disable_ifu1_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_IFUM1 ) -++ -++#define __lcd_enable_ldd_intr() ( REG_LCD_CTRL |= LCD_CTRL_LDDM ) -++#define __lcd_disable_ldd_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_LDDM ) -++ -++#define __lcd_enable_qd_intr() ( REG_LCD_CTRL |= LCD_CTRL_QDM ) -++#define __lcd_disable_qd_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_QDM ) -++ -++ -++/* LCD status register indication */ -++ -++#define __lcd_quick_disable_done() ( REG_LCD_STATE & LCD_STATE_QD ) -++#define __lcd_disable_done() ( REG_LCD_STATE & LCD_STATE_LDD ) -++#define __lcd_infifo0_underrun() ( REG_LCD_STATE & LCD_STATE_IFU0 ) -++#define __lcd_infifo1_underrun() ( REG_LCD_STATE & LCD_STATE_IFU1 ) -++#define __lcd_outfifo_underrun() ( REG_LCD_STATE & LCD_STATE_OFU ) -++#define __lcd_start_of_frame() ( REG_LCD_STATE & LCD_STATE_SOF ) -++#define __lcd_end_of_frame() ( REG_LCD_STATE & LCD_STATE_EOF ) -++ -++#define __lcd_clr_outfifounderrun() ( REG_LCD_STATE &= ~LCD_STATE_OFU ) -++#define __lcd_clr_sof() ( REG_LCD_STATE &= ~LCD_STATE_SOF ) -++#define __lcd_clr_eof() ( REG_LCD_STATE &= ~LCD_STATE_EOF ) -++ -++#define __lcd_panel_white() ( REG_LCD_DEV |= LCD_DEV_WHITE ) -++#define __lcd_panel_black() ( REG_LCD_DEV &= ~LCD_DEV_WHITE ) -++ -++/* n=1,2,4,8 for single mono-STN -++ * n=4,8 for dual mono-STN -++ */ -++#define __lcd_set_panel_datawidth(n) \ -++do { \ -++ REG_LCD_DEV &= ~LCD_DEV_PDW_MASK; \ -++ REG_LCD_DEV |= LCD_DEV_PDW_n##; \ -++} while (0) -++ -++/* m=LCD_DEV_MODE_GENERUIC_TFT_xxx */ -++#define __lcd_set_panel_mode(m) \ -++do { \ -++ REG_LCD_DEV &= ~LCD_DEV_MODE_MASK; \ -++ REG_LCD_DEV |= (m); \ -++} while(0) -++ -++/* n = 0-255 */ -++#define __lcd_disable_ac_bias() ( REG_LCD_IO = 0xff ) -++#define __lcd_set_ac_bias(n) \ -++do { \ -++ REG_LCD_IO &= ~LCD_IO_ACB_MASK; \ -++ REG_LCD_IO |= ((n) << LCD_IO_ACB_BIT); \ -++} while(0) -++ -++#define __lcd_io_set_dir() ( REG_LCD_IO |= LCD_IO_DIR ) -++#define __lcd_io_clr_dir() ( REG_LCD_IO &= ~LCD_IO_DIR ) -++ -++#define __lcd_io_set_dep() ( REG_LCD_IO |= LCD_IO_DEP ) -++#define __lcd_io_clr_dep() ( REG_LCD_IO &= ~LCD_IO_DEP ) -++ -++#define __lcd_io_set_vsp() ( REG_LCD_IO |= LCD_IO_VSP ) -++#define __lcd_io_clr_vsp() ( REG_LCD_IO &= ~LCD_IO_VSP ) -++ -++#define __lcd_io_set_hsp() ( REG_LCD_IO |= LCD_IO_HSP ) -++#define __lcd_io_clr_hsp() ( REG_LCD_IO &= ~LCD_IO_HSP ) -++ -++#define __lcd_io_set_pcp() ( REG_LCD_IO |= LCD_IO_PCP ) -++#define __lcd_io_clr_pcp() ( REG_LCD_IO &= ~LCD_IO_PCP ) -++ -++#define __lcd_vsync_get_vps() \ -++ ( (REG_LCD_VSYNC & LCD_VSYNC_VPS_MASK) >> LCD_VSYNC_VPS_BIT ) -++ -++#define __lcd_vsync_get_vpe() \ -++ ( (REG_LCD_VSYNC & LCD_VSYNC_VPE_MASK) >> LCD_VSYNC_VPE_BIT ) -++#define __lcd_vsync_set_vpe(n) \ -++do { \ -++ REG_LCD_VSYNC &= ~LCD_VSYNC_VPE_MASK; \ -++ REG_LCD_VSYNC |= (n) << LCD_VSYNC_VPE_BIT; \ -++} while (0) -++ -++#define __lcd_hsync_get_hps() \ -++ ( (REG_LCD_HSYNC & LCD_HSYNC_HPS_MASK) >> LCD_HSYNC_HPS_BIT ) -++#define __lcd_hsync_set_hps(n) \ -++do { \ -++ REG_LCD_HSYNC &= ~LCD_HSYNC_HPS_MASK; \ -++ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPS_BIT; \ -++} while (0) -++ -++#define __lcd_hsync_get_hpe() \ -++ ( (REG_LCD_HSYNC & LCD_HSYNC_HPE_MASK) >> LCD_VSYNC_HPE_BIT ) -++#define __lcd_hsync_set_hpe(n) \ -++do { \ -++ REG_LCD_HSYNC &= ~LCD_HSYNC_HPE_MASK; \ -++ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPE_BIT; \ -++} while (0) -++ -++#define __lcd_vat_get_ht() \ -++ ( (REG_LCD_VAT & LCD_VAT_HT_MASK) >> LCD_VAT_HT_BIT ) -++#define __lcd_vat_set_ht(n) \ -++do { \ -++ REG_LCD_VAT &= ~LCD_VAT_HT_MASK; \ -++ REG_LCD_VAT |= (n) << LCD_VAT_HT_BIT; \ -++} while (0) -++ -++#define __lcd_vat_get_vt() \ -++ ( (REG_LCD_VAT & LCD_VAT_VT_MASK) >> LCD_VAT_VT_BIT ) -++#define __lcd_vat_set_vt(n) \ -++do { \ -++ REG_LCD_VAT &= ~LCD_VAT_VT_MASK; \ -++ REG_LCD_VAT |= (n) << LCD_VAT_VT_BIT; \ -++} while (0) -++ -++#define __lcd_dah_get_hds() \ -++ ( (REG_LCD_DAH & LCD_DAH_HDS_MASK) >> LCD_DAH_HDS_BIT ) -++#define __lcd_dah_set_hds(n) \ -++do { \ -++ REG_LCD_DAH &= ~LCD_DAH_HDS_MASK; \ -++ REG_LCD_DAH |= (n) << LCD_DAH_HDS_BIT; \ -++} while (0) -++ -++#define __lcd_dah_get_hde() \ -++ ( (REG_LCD_DAH & LCD_DAH_HDE_MASK) >> LCD_DAH_HDE_BIT ) -++#define __lcd_dah_set_hde(n) \ -++do { \ -++ REG_LCD_DAH &= ~LCD_DAH_HDE_MASK; \ -++ REG_LCD_DAH |= (n) << LCD_DAH_HDE_BIT; \ -++} while (0) -++ -++#define __lcd_dav_get_vds() \ -++ ( (REG_LCD_DAV & LCD_DAV_VDS_MASK) >> LCD_DAV_VDS_BIT ) -++#define __lcd_dav_set_vds(n) \ -++do { \ -++ REG_LCD_DAV &= ~LCD_DAV_VDS_MASK; \ -++ REG_LCD_DAV |= (n) << LCD_DAV_VDS_BIT; \ -++} while (0) -++ -++#define __lcd_dav_get_vde() \ -++ ( (REG_LCD_DAV & LCD_DAV_VDE_MASK) >> LCD_DAV_VDE_BIT ) -++#define __lcd_dav_set_vde(n) \ -++do { \ -++ REG_LCD_DAV &= ~LCD_DAV_VDE_MASK; \ -++ REG_LCD_DAV |= (n) << LCD_DAV_VDE_BIT; \ -++} while (0) -++ -++#define __lcd_cmd0_set_sofint() ( REG_LCD_CMD0 |= LCD_CMD_SOFINT ) -++#define __lcd_cmd0_clr_sofint() ( REG_LCD_CMD0 &= ~LCD_CMD_SOFINT ) -++#define __lcd_cmd1_set_sofint() ( REG_LCD_CMD1 |= LCD_CMD_SOFINT ) -++#define __lcd_cmd1_clr_sofint() ( REG_LCD_CMD1 &= ~LCD_CMD_SOFINT ) -++ -++#define __lcd_cmd0_set_eofint() ( REG_LCD_CMD0 |= LCD_CMD_EOFINT ) -++#define __lcd_cmd0_clr_eofint() ( REG_LCD_CMD0 &= ~LCD_CMD_EOFINT ) -++#define __lcd_cmd1_set_eofint() ( REG_LCD_CMD1 |= LCD_CMD_EOFINT ) -++#define __lcd_cmd1_clr_eofint() ( REG_LCD_CMD1 &= ~LCD_CMD_EOFINT ) -++ -++#define __lcd_cmd0_set_pal() ( REG_LCD_CMD0 |= LCD_CMD_PAL ) -++#define __lcd_cmd0_clr_pal() ( REG_LCD_CMD0 &= ~LCD_CMD_PAL ) -++ -++#define __lcd_cmd0_get_len() \ -++ ( (REG_LCD_CMD0 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) -++#define __lcd_cmd1_get_len() \ -++ ( (REG_LCD_CMD1 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) -++ -++ -++ -++/*************************************************************************** -++ * DES -++ ***************************************************************************/ -++ -++ -++/*************************************************************************** -++ * CPM -++ ***************************************************************************/ -++#define __cpm_plcr1_fd() \ -++ ((REG_CPM_PLCR1 & CPM_PLCR1_PLL1FD_MASK) >> CPM_PLCR1_PLL1FD_BIT) -++#define __cpm_plcr1_rd() \ -++ ((REG_CPM_PLCR1 & CPM_PLCR1_PLL1RD_MASK) >> CPM_PLCR1_PLL1RD_BIT) -++#define __cpm_plcr1_od() \ -++ ((REG_CPM_PLCR1 & CPM_PLCR1_PLL1OD_MASK) >> CPM_PLCR1_PLL1OD_BIT) -++#define __cpm_cfcr_mfr() \ -++ ((REG_CPM_CFCR & CPM_CFCR_MFR_MASK) >> CPM_CFCR_MFR_BIT) -++#define __cpm_cfcr_pfr() \ -++ ((REG_CPM_CFCR & CPM_CFCR_PFR_MASK) >> CPM_CFCR_PFR_BIT) -++#define __cpm_cfcr_sfr() \ -++ ((REG_CPM_CFCR & CPM_CFCR_SFR_MASK) >> CPM_CFCR_SFR_BIT) -++#define __cpm_cfcr_ifr() \ -++ ((REG_CPM_CFCR & CPM_CFCR_IFR_MASK) >> CPM_CFCR_IFR_BIT) -++ -++static __inline__ unsigned int __cpm_divisor_encode(unsigned int n) -++{ -++ unsigned int encode[10] = {1,2,3,4,6,8,12,16,24,32}; -++ int i; -++ for (i=0;i<10;i++) -++ if (n < encode[i]) -++ break; -++ return i; -++} -++ -++#define __cpm_set_mclk_div(n) \ -++do { \ -++ REG_CPM_CFCR = (REG_CPM_CFCR & ~CPM_CFCR_MFR_MASK) | \ -++ ((n) << (CPM_CFCR_MFR_BIT)); \ -++} while (0) -++ -++#define __cpm_set_pclk_div(n) \ -++do { \ -++ REG_CPM_CFCR = (REG_CPM_CFCR & ~CPM_CFCR_PFR_MASK) | \ -++ ((n) << (CPM_CFCR_PFR_BIT)); \ -++} while (0) -++ -++#define __cpm_set_sclk_div(n) \ -++do { \ -++ REG_CPM_CFCR = (REG_CPM_CFCR & ~CPM_CFCR_SFR_MASK) | \ -++ ((n) << (CPM_CFCR_SFR_BIT)); \ -++} while (0) -++ -++#define __cpm_set_iclk_div(n) \ -++do { \ -++ REG_CPM_CFCR = (REG_CPM_CFCR & ~CPM_CFCR_IFR_MASK) | \ -++ ((n) << (CPM_CFCR_IFR_BIT)); \ -++} while (0) -++ -++#define __cpm_set_lcdclk_div(n) \ -++do { \ -++ REG_CPM_CFCR = (REG_CPM_CFCR & ~CPM_CFCR_LFR_MASK) | \ -++ ((n) << (CPM_CFCR_LFR_BIT)); \ -++} while (0) -++ -++#define __cpm_enable_cko1() (REG_CPM_CFCR |= CPM_CFCR_CKOEN1) -++#define __cpm_enable_cko2() (REG_CPM_CFCR |= CPM_CFCR_CKOEN2) -++#define __cpm_disable_cko1() (REG_CPM_CFCR &= ~CPM_CFCR_CKOEN1) -++#define __cpm_disable_cko2() (REG_CPM_CFCR &= ~CPM_CFCR_CKOEN2) -++ -++#define __cpm_select_msc_clk(type) \ -++do { \ -++ if (type == 0) \ -++ REG_CPM_CFCR &= ~CPM_CFCR_MSC; \ -++ else \ -++ REG_CPM_CFCR |= CPM_CFCR_MSC; \ -++ REG_CPM_CFCR |= CPM_CFCR_UPE; \ -++} while(0) -++ -++#define __cpm_idle_mode() \ -++ (REG_CPM_LPCR = (REG_CPM_LPCR & ~CPM_LPCR_LPM_MASK) | \ -++ CPM_LPCR_LPM_IDLE) -++#define __cpm_sleep_mode() \ -++ (REG_CPM_LPCR = (REG_CPM_LPCR & ~CPM_LPCR_LPM_MASK) | \ -++ CPM_LPCR_LPM_SLEEP) -++#define __cpm_hibernate_mode() \ -++ (REG_CPM_LPCR = (REG_CPM_LPCR & ~CPM_LPCR_LPM_MASK) | \ -++ CPM_LPCR_LPM_HIBERNATE) -++ -++#define __cpm_start_uart0() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_UART0)) -++#define __cpm_start_uart1() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_UART1)) -++#define __cpm_start_uart2() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_UART2)) -++#define __cpm_start_uart3() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_UART3)) -++#define __cpm_start_ost() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_OST)) -++#define __cpm_start_dmac() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_DMAC)) -++#define __cpm_start_uhc() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_UHC)) -++#define __cpm_start_lcd() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_LCD)) -++#define __cpm_start_i2c() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_I2C)) -++#define __cpm_start_aic_pclk() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_AICPCLK)) -++#define __cpm_start_aic_bitclk() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_AICBCLK)) -++#define __cpm_start_pwm0() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_PWM0)) -++#define __cpm_start_pwm1() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_PWM1)) -++#define __cpm_start_ssi() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_SSI)) -++#define __cpm_start_msc() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_MSC)) -++#define __cpm_start_scc() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_SCC)) -++#define __cpm_start_eth() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_ETH)) -++#define __cpm_start_kbc() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_KBC)) -++#define __cpm_start_cim() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_CIM)) -++#define __cpm_start_udc() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_UDC)) -++#define __cpm_start_uprt() \ -++ (REG_CPM_MSCR &= ~(1 << CPM_MSCR_MSTP_UPRT)) -++#define __cpm_start_all() (REG_CPM_MSCR = 0) -++ -++#define __cpm_stop_uart0() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_UART0)) -++#define __cpm_stop_uart1() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_UART1)) -++#define __cpm_stop_uart2() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_UART2)) -++#define __cpm_stop_uart3() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_UART3)) -++#define __cpm_stop_ost() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_OST)) -++#define __cpm_stop_dmac() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_DMAC)) -++#define __cpm_stop_uhc() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_UHC)) -++#define __cpm_stop_lcd() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_LCD)) -++#define __cpm_stop_i2c() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_I2C)) -++#define __cpm_stop_aic_pclk() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_AICPCLK)) -++#define __cpm_stop_aic_bitclk() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_AICBCLK)) -++#define __cpm_stop_pwm0() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_PWM0)) -++#define __cpm_stop_pwm1() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_PWM1)) -++#define __cpm_stop_ssi() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_SSI)) -++#define __cpm_stop_msc() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_MSC)) -++#define __cpm_stop_scc() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_SCC)) -++#define __cpm_stop_eth() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_ETH)) -++#define __cpm_stop_kbc() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_KBC)) -++#define __cpm_stop_cim() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_CIM)) -++#define __cpm_stop_udc() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_UDC)) -++#define __cpm_stop_uprt() \ -++ (REG_CPM_MSCR |= (1 << CPM_MSCR_MSTP_UPRT)) -++#define __cpm_stop_all() (REG_CPM_MSCR = 0xffffffff) -++ -++#define __cpm_set_pin(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ if (p == 0) \ -++ REG_CPM_GSR0 |= (1 << o); \ -++ else if (p == 1) \ -++ REG_CPM_GSR1 |= (1 << o); \ -++ else if (p == 2) \ -++ REG_CPM_GSR2 |= (1 << o); \ -++ else if (p == 3) \ -++ REG_CPM_GSR3 |= (1 << o); \ -++} while (0) -++ -++#define __cpm_clear_pin(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ if (p == 0) \ -++ REG_CPM_GSR0 &= ~(1 << o); \ -++ else if (p == 1) \ -++ REG_CPM_GSR1 &= ~(1 << o); \ -++ else if (p == 2) \ -++ REG_CPM_GSR2 &= ~(1 << o); \ -++ else if (p == 3) \ -++ REG_CPM_GSR3 &= ~(1 << o); \ -++} while (0) -++ -++ -++/*************************************************************************** -++ * SSI -++ ***************************************************************************/ -++ -++#define __ssi_enable() ( REG_SSI_CR0 |= SSI_CR0_SSIE ) -++#define __ssi_disable() ( REG_SSI_CR0 &= ~SSI_CR0_SSIE ) -++#define __ssi_select_ce() ( REG_SSI_CR0 &= ~SSI_CR0_FSEL ) -++ -++#define __ssi_normal_mode() ( REG_SSI_ITR &= ~SSI_ITR_IVLTM_MASK ) -++ -++#define __ssi_select_ce2() \ -++do { \ -++ REG_SSI_CR0 |= SSI_CR0_FSEL; \ -++ REG_SSI_CR1 &= ~SSI_CR1_MULTS; \ -++} while (0) -++ -++#define __ssi_select_gpc() \ -++do { \ -++ REG_SSI_CR0 &= ~SSI_CR0_FSEL; \ -++ REG_SSI_CR1 |= SSI_CR1_MULTS; \ -++} while (0) -++ -++#define __ssi_enable_tx_intr() \ -++ ( REG_SSI_CR0 |= SSI_CR0_TIE | SSI_CR0_TEIE ) -++ -++#define __ssi_disable_tx_intr() \ -++ ( REG_SSI_CR0 &= ~(SSI_CR0_TIE | SSI_CR0_TEIE) ) -++ -++#define __ssi_enable_rx_intr() \ -++ ( REG_SSI_CR0 |= SSI_CR0_RIE | SSI_CR0_REIE ) -++ -++#define __ssi_disable_rx_intr() \ -++ ( REG_SSI_CR0 &= ~(SSI_CR0_RIE | SSI_CR0_REIE) ) -++ -++#define __ssi_enable_loopback() ( REG_SSI_CR0 |= SSI_CR0_LOOP ) -++#define __ssi_disable_loopback() ( REG_SSI_CR0 &= ~SSI_CR0_LOOP ) -++ -++#define __ssi_enable_receive() ( REG_SSI_CR0 &= ~SSI_CR0_DISREV ) -++#define __ssi_disable_receive() ( REG_SSI_CR0 |= SSI_CR0_DISREV ) -++ -++#define __ssi_finish_receive() \ -++ ( REG_SSI_CR0 |= (SSI_CR0_RFINE | SSI_CR0_RFINC) ) -++ -++#define __ssi_disable_recvfinish() \ -++ ( REG_SSI_CR0 &= ~(SSI_CR0_RFINE | SSI_CR0_RFINC) ) -++ -++#define __ssi_flush_txfifo() ( REG_SSI_CR0 |= SSI_CR0_TFLUSH ) -++#define __ssi_flush_rxfifo() ( REG_SSI_CR0 |= SSI_CR0_RFLUSH ) -++ -++#define __ssi_flush_fifo() \ -++ ( REG_SSI_CR0 |= SSI_CR0_TFLUSH | SSI_CR0_RFLUSH ) -++ -++#define __ssi_finish_transmit() ( REG_SSI_CR1 &= ~SSI_CR1_UNFIN ) -++ -++#define __ssi_spi_format() \ -++do { \ -++ REG_SSI_CR1 &= ~SSI_CR1_FMAT_MASK; \ -++ REG_SSI_CR1 |= SSI_CR1_FMAT_SPI; \ -++ REG_SSI_CR1 &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK);\ -++ REG_SSI_CR1 |= (SSI_CR1_TFVCK_1 | SSI_CR1_TCKFI_1); \ -++} while (0) -++ -++/* TI's SSP format, must clear SSI_CR1.UNFIN */ -++#define __ssi_ssp_format() \ -++do { \ -++ REG_SSI_CR1 &= ~(SSI_CR1_FMAT_MASK | SSI_CR1_UNFIN); \ -++ REG_SSI_CR1 |= SSI_CR1_FMAT_SSP; \ -++} while (0) -++ -++/* National's Microwire format, must clear SSI_CR0.RFINE, and set max delay */ -++#define __ssi_microwire_format() \ -++do { \ -++ REG_SSI_CR1 &= ~SSI_CR1_FMAT_MASK; \ -++ REG_SSI_CR1 |= SSI_CR1_FMAT_MW1; \ -++ REG_SSI_CR1 &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK);\ -++ REG_SSI_CR1 |= (SSI_CR1_TFVCK_3 | SSI_CR1_TCKFI_3); \ -++ REG_SSI_CR0 &= ~SSI_CR0_RFINE; \ -++} while (0) -++ -++/* CE# level (FRMHL), CE# in interval time (ITFRM), -++ clock phase and polarity (PHA POL), -++ interval time (SSIITR), interval characters/frame (SSIICR) */ -++ -++ /* frmhl,endian,mcom,flen,pha,pol MASK */ -++#define SSICR1_MISC_MASK \ -++ ( SSI_CR1_FRMHL_MASK | SSI_CR1_LFST | SSI_CR1_MCOM_MASK \ -++ | SSI_CR1_FLEN_MASK | SSI_CR1_PHA | SSI_CR1_POL ) \ -++ -++#define __ssi_spi_set_misc(frmhl,endian,flen,mcom,pha,pol) \ -++do { \ -++ REG_SSI_CR1 &= ~SSICR1_MISC_MASK; \ -++ REG_SSI_CR1 |= ((frmhl) << 30) | ((endian) << 25) | \ -++ (((mcom) - 1) << 12) | (((flen) - 2) << 4) | \ -++ ((pha) << 1) | (pol); \ -++} while(0) -++ -++/* Transfer with MSB or LSB first */ -++#define __ssi_set_msb() ( REG_SSI_CR1 &= ~SSI_CR1_LFST ) -++#define __ssi_set_lsb() ( REG_SSI_CR1 |= SSI_CR1_LFST ) -++ -++#define __ssi_set_frame_length(n) \ -++ REG_SSI_CR1 = (REG_SSI_CR1 & ~SSI_CR1_FLEN_MASK) | (((n) - 2) << 4) -++ -++/* n = 1 - 16 */ -++#define __ssi_set_microwire_command_length(n) \ -++ ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_MCOM_MASK) | SSI_CR1_MCOM_##n##BIT) ) -++ -++/* Set the clock phase for SPI */ -++#define __ssi_set_spi_clock_phase(n) \ -++ ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_PHA) | ((n&0x1) << 1 ))) -++ -++/* Set the clock polarity for SPI */ -++#define __ssi_set_spi_clock_polarity(n) \ -++ ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_POL) | ((n&0x1) << 0 ))) -++ -++/* n = 1,4,8,14 */ -++#define __ssi_set_tx_trigger(n) \ -++do { \ -++ REG_SSI_CR1 &= ~SSI_CR1_TTRG_MASK; \ -++ REG_SSI_CR1 |= SSI_CR1_TTRG_##n; \ -++} while (0) -++ -++/* n = 1,4,8,14 */ -++#define __ssi_set_rx_trigger(n) \ -++do { \ -++ REG_SSI_CR1 &= ~SSI_CR1_RTRG_MASK; \ -++ REG_SSI_CR1 |= SSI_CR1_RTRG_##n; \ -++} while (0) -++ -++#define __ssi_get_txfifo_count() \ -++ ( (REG_SSI_SR & SSI_SR_TFIFONUM_MASK) >> SSI_SR_TFIFONUM_BIT ) -++ -++#define __ssi_get_rxfifo_count() \ -++ ( (REG_SSI_SR & SSI_SR_RFIFONUM_MASK) >> SSI_SR_RFIFONUM_BIT ) -++ -++#define __ssi_clear_errors() \ -++ ( REG_SSI_SR &= ~(SSI_SR_UNDR | SSI_SR_OVER) ) -++ -++#define __ssi_transfer_end() ( REG_SSI_SR & SSI_SR_END ) -++#define __ssi_is_busy() ( REG_SSI_SR & SSI_SR_BUSY ) -++ -++#define __ssi_txfifo_full() ( REG_SSI_SR & SSI_SR_TFF ) -++#define __ssi_rxfifo_empty() ( REG_SSI_SR & SSI_SR_RFE ) -++#define __ssi_rxfifo_noempty() ( REG_SSI_SR & SSI_SR_RFHF ) -++#define __ssi_rxfifo_half_full() ( REG_SSI_SR & SSI_SR_RFHF ) -++#define __ssi_txfifo_half_empty() ( REG_SSI_SR & SSI_SR_TFHE ) -++#define __ssi_underrun() ( REG_SSI_SR & SSI_SR_UNDR ) -++#define __ssi_overrun() ( REG_SSI_SR & SSI_SR_OVER ) -++ -++#define __ssi_set_clk(dev_clk, ssi_clk) \ -++ ( REG_SSI_GR = (dev_clk) / (2*(ssi_clk)) - 1 ) -++ -++#define __ssi_receive_data() REG_SSI_DR -++#define __ssi_transmit_data(v) ( REG_SSI_DR = (v) ) -++ -++#endif /* __ASM_JZ4730_OPS_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4730/regs.h linux-2.6.24.7/include/asm-mips/mach-jz4730/regs.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4730/regs.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4730/regs.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,2550 @@ -++/* -++ * linux/include/asm-mips/mach-jz4730/regs.h -++ * -++ * JZ4730 registers definition. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4730_REGS_H__ -++#define __ASM_JZ4730_REGS_H__ -++ -++#if defined(__ASSEMBLY__) || defined(__LANGUAGE_ASSEMBLY) -++#define REG8(addr) (addr) -++#define REG16(addr) (addr) -++#define REG32(addr) (addr) -++#else -++#define REG8(addr) *((volatile unsigned char *)(addr)) -++#define REG16(addr) *((volatile unsigned short *)(addr)) -++#define REG32(addr) *((volatile unsigned int *)(addr)) -++#endif -++ -++#define HARB_BASE 0xB3000000 -++#define EMC_BASE 0xB3010000 -++#define DMAC_BASE 0xB3020000 -++#define UHC_BASE 0xB3030000 -++#define UDC_BASE 0xB3040000 -++#define LCD_BASE 0xB3050000 -++#define CIM_BASE 0xB3060000 -++#define ETH_BASE 0xB3100000 -++#define NBM_BASE 0xB3F00000 -++ -++#define CPM_BASE 0xB0000000 -++#define INTC_BASE 0xB0001000 -++#define OST_BASE 0xB0002000 -++#define RTC_BASE 0xB0003000 -++#define WDT_BASE 0xB0004000 -++#define GPIO_BASE 0xB0010000 -++#define AIC_BASE 0xB0020000 -++#define MSC_BASE 0xB0021000 -++#define UART0_BASE 0xB0030000 -++#define UART1_BASE 0xB0031000 -++#define UART2_BASE 0xB0032000 -++#define UART3_BASE 0xB0033000 -++#define FIR_BASE 0xB0040000 -++#define SCC_BASE 0xB0041000 -++#define SCC0_BASE 0xB0041000 -++#define I2C_BASE 0xB0042000 -++#define SSI_BASE 0xB0043000 -++#define SCC1_BASE 0xB0044000 -++#define PWM0_BASE 0xB0050000 -++#define PWM1_BASE 0xB0051000 -++#define DES_BASE 0xB0060000 -++#define UPRT_BASE 0xB0061000 -++#define KBC_BASE 0xB0062000 -++ -++ -++ -++ -++/************************************************************************* -++ * MSC -++ *************************************************************************/ -++#define MSC_STRPCL (MSC_BASE + 0x000) -++#define MSC_STAT (MSC_BASE + 0x004) -++#define MSC_CLKRT (MSC_BASE + 0x008) -++#define MSC_CMDAT (MSC_BASE + 0x00C) -++#define MSC_RESTO (MSC_BASE + 0x010) -++#define MSC_RDTO (MSC_BASE + 0x014) -++#define MSC_BLKLEN (MSC_BASE + 0x018) -++#define MSC_NOB (MSC_BASE + 0x01C) -++#define MSC_SNOB (MSC_BASE + 0x020) -++#define MSC_IMASK (MSC_BASE + 0x024) -++#define MSC_IREG (MSC_BASE + 0x028) -++#define MSC_CMD (MSC_BASE + 0x02C) -++#define MSC_ARG (MSC_BASE + 0x030) -++#define MSC_RES (MSC_BASE + 0x034) -++#define MSC_RXFIFO (MSC_BASE + 0x038) -++#define MSC_TXFIFO (MSC_BASE + 0x03C) -++ -++#define REG_MSC_STRPCL REG16(MSC_STRPCL) -++#define REG_MSC_STAT REG32(MSC_STAT) -++#define REG_MSC_CLKRT REG16(MSC_CLKRT) -++#define REG_MSC_CMDAT REG32(MSC_CMDAT) -++#define REG_MSC_RESTO REG16(MSC_RESTO) -++#define REG_MSC_RDTO REG16(MSC_RDTO) -++#define REG_MSC_BLKLEN REG16(MSC_BLKLEN) -++#define REG_MSC_NOB REG16(MSC_NOB) -++#define REG_MSC_SNOB REG16(MSC_SNOB) -++#define REG_MSC_IMASK REG16(MSC_IMASK) -++#define REG_MSC_IREG REG16(MSC_IREG) -++#define REG_MSC_CMD REG8(MSC_CMD) -++#define REG_MSC_ARG REG32(MSC_ARG) -++#define REG_MSC_RES REG16(MSC_RES) -++#define REG_MSC_RXFIFO REG32(MSC_RXFIFO) -++#define REG_MSC_TXFIFO REG32(MSC_TXFIFO) -++ -++/* MSC Clock and Control Register (MSC_STRPCL) */ -++ -++#define MSC_STRPCL_EXIT_MULTIPLE (1 << 7) -++#define MSC_STRPCL_EXIT_TRANSFER (1 << 6) -++#define MSC_STRPCL_START_READWAIT (1 << 5) -++#define MSC_STRPCL_STOP_READWAIT (1 << 4) -++#define MSC_STRPCL_RESET (1 << 3) -++#define MSC_STRPCL_START_OP (1 << 2) -++#define MSC_STRPCL_CLOCK_CONTROL_BIT 0 -++#define MSC_STRPCL_CLOCK_CONTROL_MASK (0x3 << MSC_STRPCL_CLOCK_CONTROL_BIT) -++ #define MSC_STRPCL_CLOCK_CONTROL_STOP (0x1 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Stop MMC/SD clock */ -++ #define MSC_STRPCL_CLOCK_CONTROL_START (0x2 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Start MMC/SD clock */ -++ -++/* MSC Status Register (MSC_STAT) */ -++ -++#define MSC_STAT_IS_RESETTING (1 << 15) -++#define MSC_STAT_SDIO_INT_ACTIVE (1 << 14) -++#define MSC_STAT_PRG_DONE (1 << 13) -++#define MSC_STAT_DATA_TRAN_DONE (1 << 12) -++#define MSC_STAT_END_CMD_RES (1 << 11) -++#define MSC_STAT_DATA_FIFO_AFULL (1 << 10) -++#define MSC_STAT_IS_READWAIT (1 << 9) -++#define MSC_STAT_CLK_EN (1 << 8) -++#define MSC_STAT_DATA_FIFO_FULL (1 << 7) -++#define MSC_STAT_DATA_FIFO_EMPTY (1 << 6) -++#define MSC_STAT_CRC_RES_ERR (1 << 5) -++#define MSC_STAT_CRC_READ_ERROR (1 << 4) -++#define MSC_STAT_CRC_WRITE_ERROR_BIT 2 -++#define MSC_STAT_CRC_WRITE_ERROR_MASK (0x3 << MSC_STAT_CRC_WRITE_ERROR_BIT) -++ #define MSC_STAT_CRC_WRITE_ERROR_NO (0 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No error on transmission of data */ -++ #define MSC_STAT_CRC_WRITE_ERROR (1 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* Card observed erroneous transmission of data */ -++ #define MSC_STAT_CRC_WRITE_ERROR_NOSTS (2 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No CRC status is sent back */ -++#define MSC_STAT_TIME_OUT_RES (1 << 1) -++#define MSC_STAT_TIME_OUT_READ (1 << 0) -++ -++/* MSC Bus Clock Control Register (MSC_CLKRT) */ -++ -++#define MSC_CLKRT_CLK_RATE_BIT 0 -++#define MSC_CLKRT_CLK_RATE_MASK (0x7 << MSC_CLKRT_CLK_RATE_BIT) -++ #define MSC_CLKRT_CLK_RATE_DIV_1 (0x0 << MSC_CLKRT_CLK_RATE_BIT) /* CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_2 (0x1 << MSC_CLKRT_CLK_RATE_BIT) /* 1/2 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_4 (0x2 << MSC_CLKRT_CLK_RATE_BIT) /* 1/4 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_8 (0x3 << MSC_CLKRT_CLK_RATE_BIT) /* 1/8 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_16 (0x4 << MSC_CLKRT_CLK_RATE_BIT) /* 1/16 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_32 (0x5 << MSC_CLKRT_CLK_RATE_BIT) /* 1/32 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_64 (0x6 << MSC_CLKRT_CLK_RATE_BIT) /* 1/64 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_128 (0x7 << MSC_CLKRT_CLK_RATE_BIT) /* 1/128 of CLK_SRC */ -++ -++/* MSC Command Sequence Control Register (MSC_CMDAT) */ -++ -++#define MSC_CMDAT_IO_ABORT (1 << 11) -++#define MSC_CMDAT_BUS_WIDTH_BIT 9 -++#define MSC_CMDAT_BUS_WIDTH_MASK (0x3 << MSC_CMDAT_BUS_WIDTH_BIT) -++ #define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) /* 1-bit data bus */ -++ #define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) /* 4-bit data bus */ -++ #define CMDAT_BUS_WIDTH1 (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) -++ #define CMDAT_BUS_WIDTH4 (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) -++#define MSC_CMDAT_DMA_EN (1 << 8) -++#define MSC_CMDAT_INIT (1 << 7) -++#define MSC_CMDAT_BUSY (1 << 6) -++#define MSC_CMDAT_STREAM_BLOCK (1 << 5) -++#define MSC_CMDAT_WRITE (1 << 4) -++#define MSC_CMDAT_READ (0 << 4) -++#define MSC_CMDAT_DATA_EN (1 << 3) -++#define MSC_CMDAT_RESPONSE_BIT 0 -++#define MSC_CMDAT_RESPONSE_MASK (0x7 << MSC_CMDAT_RESPONSE_BIT) -++ #define MSC_CMDAT_RESPONSE_NONE (0x0 << MSC_CMDAT_RESPONSE_BIT) /* No response */ -++ #define MSC_CMDAT_RESPONSE_R1 (0x1 << MSC_CMDAT_RESPONSE_BIT) /* Format R1 and R1b */ -++ #define MSC_CMDAT_RESPONSE_R2 (0x2 << MSC_CMDAT_RESPONSE_BIT) /* Format R2 */ -++ #define MSC_CMDAT_RESPONSE_R3 (0x3 << MSC_CMDAT_RESPONSE_BIT) /* Format R3 */ -++ #define MSC_CMDAT_RESPONSE_R4 (0x4 << MSC_CMDAT_RESPONSE_BIT) /* Format R4 */ -++ #define MSC_CMDAT_RESPONSE_R5 (0x5 << MSC_CMDAT_RESPONSE_BIT) /* Format R5 */ -++ #define MSC_CMDAT_RESPONSE_R6 (0x6 << MSC_CMDAT_RESPONSE_BIT) /* Format R6 */ -++ -++#define CMDAT_DMA_EN (1 << 8) -++#define CMDAT_INIT (1 << 7) -++#define CMDAT_BUSY (1 << 6) -++#define CMDAT_STREAM (1 << 5) -++#define CMDAT_WRITE (1 << 4) -++#define CMDAT_DATA_EN (1 << 3) -++ -++/* MSC Interrupts Mask Register (MSC_IMASK) */ -++ -++#define MSC_IMASK_SDIO (1 << 7) -++#define MSC_IMASK_TXFIFO_WR_REQ (1 << 6) -++#define MSC_IMASK_RXFIFO_RD_REQ (1 << 5) -++#define MSC_IMASK_END_CMD_RES (1 << 2) -++#define MSC_IMASK_PRG_DONE (1 << 1) -++#define MSC_IMASK_DATA_TRAN_DONE (1 << 0) -++ -++ -++/* MSC Interrupts Status Register (MSC_IREG) */ -++ -++#define MSC_IREG_SDIO (1 << 7) -++#define MSC_IREG_TXFIFO_WR_REQ (1 << 6) -++#define MSC_IREG_RXFIFO_RD_REQ (1 << 5) -++#define MSC_IREG_END_CMD_RES (1 << 2) -++#define MSC_IREG_PRG_DONE (1 << 1) -++#define MSC_IREG_DATA_TRAN_DONE (1 << 0) -++ -++ -++ -++ -++/************************************************************************* -++ * RTC -++ *************************************************************************/ -++#define RTC_RCR (RTC_BASE + 0x00) -++#define RTC_RSR (RTC_BASE + 0x04) -++#define RTC_RSAR (RTC_BASE + 0x08) -++#define RTC_RGR (RTC_BASE + 0x0c) -++ -++#define REG_RTC_RCR REG32(RTC_RCR) -++#define REG_RTC_RSR REG32(RTC_RSR) -++#define REG_RTC_RSAR REG32(RTC_RSAR) -++#define REG_RTC_RGR REG32(RTC_RGR) -++ -++#define RTC_RCR_HZ (1 << 6) -++#define RTC_RCR_HZIE (1 << 5) -++#define RTC_RCR_AF (1 << 4) -++#define RTC_RCR_AIE (1 << 3) -++#define RTC_RCR_AE (1 << 2) -++#define RTC_RCR_START (1 << 0) -++ -++#define RTC_RGR_LOCK (1 << 31) -++#define RTC_RGR_ADJ_BIT 16 -++#define RTC_RGR_ADJ_MASK (0x3ff << RTC_RGR_ADJ_BIT) -++#define RTC_RGR_DIV_BIT 0 -++#define RTC_REG_DIV_MASK (0xff << RTC_RGR_DIV_BIT) -++ -++ -++ -++ -++/************************************************************************* -++ * FIR -++ *************************************************************************/ -++#define FIR_TDR (FIR_BASE + 0x000) -++#define FIR_RDR (FIR_BASE + 0x004) -++#define FIR_TFLR (FIR_BASE + 0x008) -++#define FIR_AR (FIR_BASE + 0x00C) -++#define FIR_CR1 (FIR_BASE + 0x010) -++#define FIR_CR2 (FIR_BASE + 0x014) -++#define FIR_SR (FIR_BASE + 0x018) -++ -++#define REG_FIR_TDR REG8(FIR_TDR) -++#define REG_FIR_RDR REG8(FIR_RDR) -++#define REG_FIR_TFLR REG16(FIR_TFLR) -++#define REG_FIR_AR REG8(FIR_AR) -++#define REG_FIR_CR1 REG8(FIR_CR1) -++#define REG_FIR_CR2 REG16(FIR_CR2) -++#define REG_FIR_SR REG16(FIR_SR) -++ -++/* FIR Control Register 1 (FIR_CR1) */ -++ -++#define FIR_CR1_FIRUE (1 << 7) -++#define FIR_CR1_ACE (1 << 6) -++#define FIR_CR1_EOUS (1 << 5) -++#define FIR_CR1_TIIE (1 << 4) -++#define FIR_CR1_TFIE (1 << 3) -++#define FIR_CR1_RFIE (1 << 2) -++#define FIR_CR1_TXE (1 << 1) -++#define FIR_CR1_RXE (1 << 0) -++ -++/* FIR Control Register 2 (FIR_CR2) */ -++ -++#define FIR_CR2_SIPE (1 << 10) -++#define FIR_CR2_BCRC (1 << 9) -++#define FIR_CR2_TFLRS (1 << 8) -++#define FIR_CR2_ISS (1 << 7) -++#define FIR_CR2_LMS (1 << 6) -++#define FIR_CR2_TPPS (1 << 5) -++#define FIR_CR2_RPPS (1 << 4) -++#define FIR_CR2_TTRG_BIT 2 -++#define FIR_CR2_TTRG_MASK (0x3 << FIR_CR2_TTRG_BIT) -++ #define FIR_CR2_TTRG_16 (0 << FIR_CR2_TTRG_BIT) /* Transmit Trigger Level is 16 */ -++ #define FIR_CR2_TTRG_32 (1 << FIR_CR2_TTRG_BIT) /* Transmit Trigger Level is 32 */ -++ #define FIR_CR2_TTRG_64 (2 << FIR_CR2_TTRG_BIT) /* Transmit Trigger Level is 64 */ -++ #define FIR_CR2_TTRG_128 (3 << FIR_CR2_TTRG_BIT) /* Transmit Trigger Level is 128 */ -++#define FIR_CR2_RTRG_BIT 0 -++#define FIR_CR2_RTRG_MASK (0x3 << FIR_CR2_RTRG_BIT) -++ #define FIR_CR2_RTRG_16 (0 << FIR_CR2_RTRG_BIT) /* Receive Trigger Level is 16 */ -++ #define FIR_CR2_RTRG_32 (1 << FIR_CR2_RTRG_BIT) /* Receive Trigger Level is 32 */ -++ #define FIR_CR2_RTRG_64 (2 << FIR_CR2_RTRG_BIT) /* Receive Trigger Level is 64 */ -++ #define FIR_CR2_RTRG_128 (3 << FIR_CR2_RTRG_BIT) /* Receive Trigger Level is 128 */ -++ -++/* FIR Status Register (FIR_SR) */ -++ -++#define FIR_SR_RFW (1 << 12) -++#define FIR_SR_RFA (1 << 11) -++#define FIR_SR_TFRTL (1 << 10) -++#define FIR_SR_RFRTL (1 << 9) -++#define FIR_SR_URUN (1 << 8) -++#define FIR_SR_RFTE (1 << 7) -++#define FIR_SR_ORUN (1 << 6) -++#define FIR_SR_CRCE (1 << 5) -++#define FIR_SR_FEND (1 << 4) -++#define FIR_SR_TFF (1 << 3) -++#define FIR_SR_RFE (1 << 2) -++#define FIR_SR_TIDLE (1 << 1) -++#define FIR_SR_RB (1 << 0) -++ -++ -++ -++ -++/************************************************************************* -++ * SCC -++ *************************************************************************/ -++#define SCC_DR(base) ((base) + 0x000) -++#define SCC_FDR(base) ((base) + 0x004) -++#define SCC_CR(base) ((base) + 0x008) -++#define SCC1_CR(base) ((base) + 0x008) -++#define SCC_SR(base) ((base) + 0x00C) -++#define SCC_TFR(base) ((base) + 0x010) -++#define SCC_EGTR(base) ((base) + 0x014) -++#define SCC_ECR(base) ((base) + 0x018) -++#define SCC_RTOR(base) ((base) + 0x01C) -++ -++#define REG_SCC_DR(base) REG8(SCC_DR(base)) -++#define REG_SCC_FDR(base) REG8(SCC_FDR(base)) -++#define REG_SCC_CR(base) REG32(SCC_CR(base)) -++#define REG_SCC1_CR(base) REG32(SCC1_CR(base)) -++#define REG_SCC_SR(base) REG16(SCC_SR(base)) -++#define REG_SCC_TFR(base) REG16(SCC_TFR(base)) -++#define REG_SCC_EGTR(base) REG8(SCC_EGTR(base)) -++#define REG_SCC_ECR(base) REG32(SCC_ECR(base)) -++#define REG_SCC_RTOR(base) REG8(SCC_RTOR(base)) -++ -++/* SCC FIFO Data Count Register (SCC_FDR) */ -++ -++#define SCC_FDR_EMPTY 0x00 -++#define SCC_FDR_FULL 0x10 -++ -++/* SCC Control Register (SCC_CR) */ -++ -++#define SCC_CR_SCCE (1 << 31) -++#define SCC_CR_TRS (1 << 30) -++#define SCC_CR_T2R (1 << 29) -++#define SCC_CR_FDIV_BIT 24 -++#define SCC_CR_FDIV_MASK (0x3 << SCC_CR_FDIV_BIT) -++ #define SCC_CR_FDIV_1 (0 << SCC_CR_FDIV_BIT) /* SCC_CLK frequency is the same as device clock */ -++ #define SCC_CR_FDIV_2 (1 << SCC_CR_FDIV_BIT) /* SCC_CLK frequency is half of device clock */ -++#define SCC_CR_FLUSH (1 << 23) -++#define SCC_CR_TRIG_BIT 16 -++#define SCC_CR_TRIG_MASK (0x3 << SCC_CR_TRIG_BIT) -++ #define SCC_CR_TRIG_1 (0 << SCC_CR_TRIG_BIT) /* Receive/Transmit-FIFO Trigger is 1 */ -++ #define SCC_CR_TRIG_4 (1 << SCC_CR_TRIG_BIT) /* Receive/Transmit-FIFO Trigger is 4 */ -++ #define SCC_CR_TRIG_8 (2 << SCC_CR_TRIG_BIT) /* Receive/Transmit-FIFO Trigger is 8 */ -++ #define SCC_CR_TRIG_14 (3 << SCC_CR_TRIG_BIT) /* Receive/Transmit-FIFO Trigger is 14 */ -++#define SCC_CR_TP (1 << 15) -++#define SCC_CR_CONV (1 << 14) -++#define SCC_CR_TXIE (1 << 13) -++#define SCC_CR_RXIE (1 << 12) -++#define SCC_CR_TENDIE (1 << 11) -++#define SCC_CR_RTOIE (1 << 10) -++#define SCC_CR_ECIE (1 << 9) -++#define SCC_CR_EPIE (1 << 8) -++#define SCC_CR_RETIE (1 << 7) -++#define SCC_CR_EOIE (1 << 6) -++#define SCC_CR_TSEND (1 << 3) -++#define SCC_CR_PX_BIT 1 -++#define SCC_CR_PX_MASK (0x3 << SCC_CR_PX_BIT) -++ #define SCC_CR_PX_NOT_SUPPORT (0 << SCC_CR_PX_BIT) /* SCC does not support clock stop */ -++ #define SCC_CR_PX_STOP_LOW (1 << SCC_CR_PX_BIT) /* SCC_CLK stops at state low */ -++ #define SCC_CR_PX_STOP_HIGH (2 << SCC_CR_PX_BIT) /* SCC_CLK stops at state high */ -++#define SCC_CR_CLKSTP (1 << 0) -++ -++/* SCC Status Register (SCC_SR) */ -++ -++#define SCC_SR_TRANS (1 << 15) -++#define SCC_SR_ORER (1 << 12) -++#define SCC_SR_RTO (1 << 11) -++#define SCC_SR_PER (1 << 10) -++#define SCC_SR_TFTG (1 << 9) -++#define SCC_SR_RFTG (1 << 8) -++#define SCC_SR_TEND (1 << 7) -++#define SCC_SR_RETR_3 (1 << 4) -++#define SCC_SR_ECNTO (1 << 0) -++ -++ -++ -++ -++/************************************************************************* -++ * ETH -++ *************************************************************************/ -++#define ETH_BMR (ETH_BASE + 0x1000) -++#define ETH_TPDR (ETH_BASE + 0x1004) -++#define ETH_RPDR (ETH_BASE + 0x1008) -++#define ETH_RAR (ETH_BASE + 0x100C) -++#define ETH_TAR (ETH_BASE + 0x1010) -++#define ETH_SR (ETH_BASE + 0x1014) -++#define ETH_CR (ETH_BASE + 0x1018) -++#define ETH_IER (ETH_BASE + 0x101C) -++#define ETH_MFCR (ETH_BASE + 0x1020) -++#define ETH_CTAR (ETH_BASE + 0x1050) -++#define ETH_CRAR (ETH_BASE + 0x1054) -++#define ETH_MCR (ETH_BASE + 0x0000) -++#define ETH_MAHR (ETH_BASE + 0x0004) -++#define ETH_MALR (ETH_BASE + 0x0008) -++#define ETH_HTHR (ETH_BASE + 0x000C) -++#define ETH_HTLR (ETH_BASE + 0x0010) -++#define ETH_MIAR (ETH_BASE + 0x0014) -++#define ETH_MIDR (ETH_BASE + 0x0018) -++#define ETH_FCR (ETH_BASE + 0x001C) -++#define ETH_VTR1 (ETH_BASE + 0x0020) -++#define ETH_VTR2 (ETH_BASE + 0x0024) -++#define ETH_WKFR (ETH_BASE + 0x0028) -++#define ETH_PMTR (ETH_BASE + 0x002C) -++ -++#define REG_ETH_BMR REG32(ETH_BMR) -++#define REG_ETH_TPDR REG32(ETH_TPDR) -++#define REG_ETH_RPDR REG32(ETH_RPDR) -++#define REG_ETH_RAR REG32(ETH_RAR) -++#define REG_ETH_TAR REG32(ETH_TAR) -++#define REG_ETH_SR REG32(ETH_SR) -++#define REG_ETH_CR REG32(ETH_CR) -++#define REG_ETH_IER REG32(ETH_IER) -++#define REG_ETH_MFCR REG32(ETH_MFCR) -++#define REG_ETH_CTAR REG32(ETH_CTAR) -++#define REG_ETH_CRAR REG32(ETH_CRAR) -++#define REG_ETH_MCR REG32(ETH_MCR) -++#define REG_ETH_MAHR REG32(ETH_MAHR) -++#define REG_ETH_MALR REG32(ETH_MALR) -++#define REG_ETH_HTHR REG32(ETH_HTHR) -++#define REG_ETH_HTLR REG32(ETH_HTLR) -++#define REG_ETH_MIAR REG32(ETH_MIAR) -++#define REG_ETH_MIDR REG32(ETH_MIDR) -++#define REG_ETH_FCR REG32(ETH_FCR) -++#define REG_ETH_VTR1 REG32(ETH_VTR1) -++#define REG_ETH_VTR2 REG32(ETH_VTR2) -++#define REG_ETH_WKFR REG32(ETH_WKFR) -++#define REG_ETH_PMTR REG32(ETH_PMTR) -++ -++/* Bus Mode Register (ETH_BMR) */ -++ -++#define ETH_BMR_DBO (1 << 20) -++#define ETH_BMR_PBL_BIT 8 -++#define ETH_BMR_PBL_MASK (0x3f << ETH_BMR_PBL_BIT) -++ #define ETH_BMR_PBL_1 (0x1 << ETH_BMR_PBL_BIT) -++ #define ETH_BMR_PBL_4 (0x4 << ETH_BMR_PBL_BIT) -++#define ETH_BMR_BLE (1 << 7) -++#define ETH_BMR_DSL_BIT 2 -++#define ETH_BMR_DSL_MASK (0x1f << ETH_BMR_DSL_BIT) -++ #define ETH_BMR_DSL_0 (0x0 << ETH_BMR_DSL_BIT) -++ #define ETH_BMR_DSL_1 (0x1 << ETH_BMR_DSL_BIT) -++ #define ETH_BMR_DSL_2 (0x2 << ETH_BMR_DSL_BIT) -++ #define ETH_BMR_DSL_4 (0x4 << ETH_BMR_DSL_BIT) -++ #define ETH_BMR_DSL_8 (0x8 << ETH_BMR_DSL_BIT) -++#define ETH_BMR_SWR (1 << 0) -++ -++/* DMA Status Register (ETH_SR) */ -++ -++#define ETH_SR_EB_BIT 23 -++#define ETH_SR_EB_MASK (0x7 << ETH_SR_EB_BIT) -++ #define ETH_SR_EB_TX_ABORT (0x1 << ETH_SR_EB_BIT) -++ #define ETH_SR_EB_RX_ABORT (0x2 << ETH_SR_EB_BIT) -++#define ETH_SR_TS_BIT 20 -++#define ETH_SR_TS_MASK (0x7 << ETH_SR_TS_BIT) -++ #define ETH_SR_TS_STOP (0x0 << ETH_SR_TS_BIT) -++ #define ETH_SR_TS_FTD (0x1 << ETH_SR_TS_BIT) -++ #define ETH_SR_TS_WEOT (0x2 << ETH_SR_TS_BIT) -++ #define ETH_SR_TS_QDAT (0x3 << ETH_SR_TS_BIT) -++ #define ETH_SR_TS_SUSPEND (0x6 << ETH_SR_TS_BIT) -++ #define ETH_SR_TS_CTD (0x7 << ETH_SR_TS_BIT) -++#define ETH_SR_RS_BIT 17 -++#define ETH_SR_RS_MASK (0x7 << ETH_SR_RS_BIT) -++ #define ETH_SR_RS_STOP (0x0 << ETH_SR_RS_BIT) -++ #define ETH_SR_RS_FRD (0x1 << ETH_SR_RS_BIT) -++ #define ETH_SR_RS_CEOR (0x2 << ETH_SR_RS_BIT) -++ #define ETH_SR_RS_WRP (0x3 << ETH_SR_RS_BIT) -++ #define ETH_SR_RS_SUSPEND (0x4 << ETH_SR_RS_BIT) -++ #define ETH_SR_RS_CRD (0x5 << ETH_SR_RS_BIT) -++ #define ETH_SR_RS_FCF (0x6 << ETH_SR_RS_BIT) -++ #define ETH_SR_RS_QRF (0x7 << ETH_SR_RS_BIT) -++#define ETH_SR_NIS (1 << 16) -++#define ETH_SR_AIS (1 << 15) -++#define ETH_SR_ERI (1 << 14) -++#define ETH_SR_FBE (1 << 13) -++#define ETH_SR_ETI (1 << 10) -++#define ETH_SR_RWT (1 << 9) -++#define ETH_SR_RPS (1 << 8) -++#define ETH_SR_RU (1 << 7) -++#define ETH_SR_RI (1 << 6) -++#define ETH_SR_UNF (1 << 5) -++#define ETH_SR_TJT (1 << 3) -++#define ETH_SR_TU (1 << 2) -++#define ETH_SR_TPS (1 << 1) -++#define ETH_SR_TI (1 << 0) -++ -++/* Control (Operation Mode) Register (ETH_CR) */ -++ -++#define ETH_CR_TTM (1 << 22) -++#define ETH_CR_SF (1 << 21) -++#define ETH_CR_TR_BIT 14 -++#define ETH_CR_TR_MASK (0x3 << ETH_CR_TR_BIT) -++#define ETH_CR_ST (1 << 13) -++#define ETH_CR_OSF (1 << 2) -++#define ETH_CR_SR (1 << 1) -++ -++/* Interrupt Enable Register (ETH_IER) */ -++ -++#define ETH_IER_NI (1 << 16) -++#define ETH_IER_AI (1 << 15) -++#define ETH_IER_ERE (1 << 14) -++#define ETH_IER_FBE (1 << 13) -++#define ETH_IER_ET (1 << 10) -++#define ETH_IER_RWE (1 << 9) -++#define ETH_IER_RS (1 << 8) -++#define ETH_IER_RU (1 << 7) -++#define ETH_IER_RI (1 << 6) -++#define ETH_IER_UN (1 << 5) -++#define ETH_IER_TJ (1 << 3) -++#define ETH_IER_TU (1 << 2) -++#define ETH_IER_TS (1 << 1) -++#define ETH_IER_TI (1 << 0) -++ -++/* Missed Frame and Buffer Overflow Counter Register (ETH_MFCR) */ -++ -++#define ETH_MFCR_OVERFLOW_BIT 17 -++#define ETH_MFCR_OVERFLOW_MASK (0x7ff << ETH_MFCR_OVERFLOW_BIT) -++#define ETH_MFCR_MFC_BIT 0 -++#define ETH_MFCR_MFC_MASK (0xffff << ETH_MFCR_MFC_BIT) -++ -++/* MAC Control Register (ETH_MCR) */ -++ -++#define ETH_MCR_RA (1 << 31) -++#define ETH_MCR_HBD (1 << 28) -++#define ETH_MCR_PS (1 << 27) -++#define ETH_MCR_DRO (1 << 23) -++#define ETH_MCR_OM_BIT 21 -++#define ETH_MCR_OM_MASK (0x3 << ETH_MCR_OM_BIT) -++ #define ETH_MCR_OM_NORMAL (0x0 << ETH_MCR_OM_BIT) -++ #define ETH_MCR_OM_INTERNAL (0x1 << ETH_MCR_OM_BIT) -++ #define ETH_MCR_OM_EXTERNAL (0x2 << ETH_MCR_OM_BIT) -++#define ETH_MCR_F (1 << 20) -++#define ETH_MCR_PM (1 << 19) -++#define ETH_MCR_PR (1 << 18) -++#define ETH_MCR_IF (1 << 17) -++#define ETH_MCR_PB (1 << 16) -++#define ETH_MCR_HO (1 << 15) -++#define ETH_MCR_HP (1 << 13) -++#define ETH_MCR_LCC (1 << 12) -++#define ETH_MCR_DBF (1 << 11) -++#define ETH_MCR_DTRY (1 << 10) -++#define ETH_MCR_ASTP (1 << 8) -++#define ETH_MCR_BOLMT_BIT 6 -++#define ETH_MCR_BOLMT_MASK (0x3 << ETH_MCR_BOLMT_BIT) -++ #define ETH_MCR_BOLMT_10 (0 << ETH_MCR_BOLMT_BIT) -++ #define ETH_MCR_BOLMT_8 (1 << ETH_MCR_BOLMT_BIT) -++ #define ETH_MCR_BOLMT_4 (2 << ETH_MCR_BOLMT_BIT) -++ #define ETH_MCR_BOLMT_1 (3 << ETH_MCR_BOLMT_BIT) -++#define ETH_MCR_DC (1 << 5) -++#define ETH_MCR_TE (1 << 3) -++#define ETH_MCR_RE (1 << 2) -++ -++/* MII Address Register (ETH_MIAR) */ -++ -++#define ETH_MIAR_PHY_ADDR_BIT 11 -++#define ETH_MIAR_PHY_ADDR_MASK (0x1f << ETH_MIAR_PHY_ADDR_BIT) -++#define ETH_MIAR_MII_REG_BIT 6 -++#define ETH_MIAR_MII_REG_MASK (0x1f << ETH_MIAR_MII_REG_BIT) -++#define ETH_MIAR_MII_WRITE (1 << 1) -++#define ETH_MIAR_MII_BUSY (1 << 0) -++ -++/* Flow Control Register (ETH_FCR) */ -++ -++#define ETH_FCR_PAUSE_TIME_BIT 16 -++#define ETH_FCR_PAUSE_TIME_MASK (0xffff << ETH_FCR_PAUSE_TIME_BIT) -++#define ETH_FCR_PCF (1 << 2) -++#define ETH_FCR_FCE (1 << 1) -++#define ETH_FCR_BUSY (1 << 0) -++ -++/* PMT Control and Status Register (ETH_PMTR) */ -++ -++#define ETH_PMTR_GU (1 << 9) -++#define ETH_PMTR_RF (1 << 6) -++#define ETH_PMTR_MF (1 << 5) -++#define ETH_PMTR_RWK (1 << 2) -++#define ETH_PMTR_MPK (1 << 1) -++ -++/* Receive Descriptor 0 (ETH_RD0) Bits */ -++ -++#define ETH_RD0_OWN (1 << 31) -++#define ETH_RD0_FF (1 << 30) -++#define ETH_RD0_FL_BIT 16 -++#define ETH_RD0_FL_MASK (0x3fff << ETH_RD0_FL_BIT) -++#define ETH_RD0_ES (1 << 15) -++#define ETH_RD0_DE (1 << 14) -++#define ETH_RD0_LE (1 << 12) -++#define ETH_RD0_RF (1 << 11) -++#define ETH_RD0_MF (1 << 10) -++#define ETH_RD0_FD (1 << 9) -++#define ETH_RD0_LD (1 << 8) -++#define ETH_RD0_TL (1 << 7) -++#define ETH_RD0_CS (1 << 6) -++#define ETH_RD0_FT (1 << 5) -++#define ETH_RD0_WT (1 << 4) -++#define ETH_RD0_ME (1 << 3) -++#define ETH_RD0_DB (1 << 2) -++#define ETH_RD0_CE (1 << 1) -++ -++/* Receive Descriptor 1 (ETH_RD1) Bits */ -++ -++#define ETH_RD1_RER (1 << 25) -++#define ETH_RD1_RCH (1 << 24) -++#define ETH_RD1_RBS2_BIT 11 -++#define ETH_RD1_RBS2_MASK (0x7ff << ETH_RD1_RBS2_BIT) -++#define ETH_RD1_RBS1_BIT 0 -++#define ETH_RD1_RBS1_MASK (0x7ff << ETH_RD1_RBS1_BIT) -++ -++/* Transmit Descriptor 0 (ETH_TD0) Bits */ -++ -++#define ETH_TD0_OWN (1 << 31) -++#define ETH_TD0_FA (1 << 15) -++#define ETH_TD0_LOC (1 << 11) -++#define ETH_TD0_NC (1 << 10) -++#define ETH_TD0_LC (1 << 9) -++#define ETH_TD0_EC (1 << 8) -++#define ETH_TD0_HBF (1 << 7) -++#define ETH_TD0_CC_BIT 3 -++#define ETH_TD0_CC_MASK (0xf << ETH_TD0_CC_BIT) -++#define ETH_TD0_ED (1 << 2) -++#define ETH_TD0_UF (1 << 1) -++#define ETH_TD0_DF (1 << 0) -++ -++/* Transmit Descriptor 1 (ETH_TD1) Bits */ -++ -++#define ETH_TD1_IC (1 << 31) -++#define ETH_TD1_LS (1 << 30) -++#define ETH_TD1_FS (1 << 29) -++#define ETH_TD1_AC (1 << 26) -++#define ETH_TD1_TER (1 << 25) -++#define ETH_TD1_TCH (1 << 24) -++#define ETH_TD1_DPD (1 << 23) -++#define ETH_TD1_TBS2_BIT 11 -++#define ETH_TD1_TBS2_MASK (0x7ff << ETH_TD1_TBS2_BIT) -++#define ETH_TD1_TBS1_BIT 0 -++#define ETH_TD1_TBS1_MASK (0x7ff << ETH_TD1_TBS1_BIT) -++ -++ -++ -++ -++/************************************************************************* -++ * WDT -++ *************************************************************************/ -++#define WDT_WTCSR (WDT_BASE + 0x00) -++#define WDT_WTCNT (WDT_BASE + 0x04) -++ -++#define REG_WDT_WTCSR REG8(WDT_WTCSR) -++#define REG_WDT_WTCNT REG32(WDT_WTCNT) -++ -++#define WDT_WTCSR_START (1 << 4) -++ -++ -++ -++ -++/************************************************************************* -++ * OST -++ *************************************************************************/ -++#define OST_TER (OST_BASE + 0x00) -++#define OST_TRDR(n) (OST_BASE + 0x10 + ((n) * 0x20)) -++#define OST_TCNT(n) (OST_BASE + 0x14 + ((n) * 0x20)) -++#define OST_TCSR(n) (OST_BASE + 0x18 + ((n) * 0x20)) -++#define OST_TCRB(n) (OST_BASE + 0x1c + ((n) * 0x20)) -++ -++#define REG_OST_TER REG8(OST_TER) -++#define REG_OST_TRDR(n) REG32(OST_TRDR((n))) -++#define REG_OST_TCNT(n) REG32(OST_TCNT((n))) -++#define REG_OST_TCSR(n) REG16(OST_TCSR((n))) -++#define REG_OST_TCRB(n) REG32(OST_TCRB((n))) -++ -++#define OST_TCSR_BUSY (1 << 7) -++#define OST_TCSR_UF (1 << 6) -++#define OST_TCSR_UIE (1 << 5) -++#define OST_TCSR_CKS_BIT 0 -++#define OST_TCSR_CKS_MASK (0x07 << OST_TCSR_CKS_BIT) -++ #define OST_TCSR_CKS_PCLK_4 (0 << OST_TCSR_CKS_BIT) -++ #define OST_TCSR_CKS_PCLK_16 (1 << OST_TCSR_CKS_BIT) -++ #define OST_TCSR_CKS_PCLK_64 (2 << OST_TCSR_CKS_BIT) -++ #define OST_TCSR_CKS_PCLK_256 (3 << OST_TCSR_CKS_BIT) -++ #define OST_TCSR_CKS_RTCCLK (4 << OST_TCSR_CKS_BIT) -++ #define OST_TCSR_CKS_EXTAL (5 << OST_TCSR_CKS_BIT) -++ -++#define OST_TCSR0 OST_TCSR(0) -++#define OST_TCSR1 OST_TCSR(1) -++#define OST_TCSR2 OST_TCSR(2) -++#define OST_TRDR0 OST_TRDR(0) -++#define OST_TRDR1 OST_TRDR(1) -++#define OST_TRDR2 OST_TRDR(2) -++#define OST_TCNT0 OST_TCNT(0) -++#define OST_TCNT1 OST_TCNT(1) -++#define OST_TCNT2 OST_TCNT(2) -++#define OST_TCRB0 OST_TCRB(0) -++#define OST_TCRB1 OST_TCRB(1) -++#define OST_TCRB2 OST_TCRB(2) -++ -++/************************************************************************* -++ * UART -++ *************************************************************************/ -++ -++#define IRDA_BASE UART0_BASE -++#define UART_BASE UART0_BASE -++#define UART_OFF 0x1000 -++ -++/* register offset */ -++#define OFF_RDR (0x00) /* R 8b H'xx */ -++#define OFF_TDR (0x00) /* W 8b H'xx */ -++#define OFF_DLLR (0x00) /* RW 8b H'00 */ -++#define OFF_DLHR (0x04) /* RW 8b H'00 */ -++#define OFF_IER (0x04) /* RW 8b H'00 */ -++#define OFF_ISR (0x08) /* R 8b H'01 */ -++#define OFF_FCR (0x08) /* W 8b H'00 */ -++#define OFF_LCR (0x0C) /* RW 8b H'00 */ -++#define OFF_MCR (0x10) /* RW 8b H'00 */ -++#define OFF_LSR (0x14) /* R 8b H'00 */ -++#define OFF_MSR (0x18) /* R 8b H'00 */ -++#define OFF_SPR (0x1C) /* RW 8b H'00 */ -++#define OFF_MCR (0x10) /* RW 8b H'00 */ -++#define OFF_SIRCR (0x20) /* RW 8b H'00, UART0 */ -++ -++/* register address */ -++#define UART0_RDR (UART0_BASE + OFF_RDR) -++#define UART0_TDR (UART0_BASE + OFF_TDR) -++#define UART0_DLLR (UART0_BASE + OFF_DLLR) -++#define UART0_DLHR (UART0_BASE + OFF_DLHR) -++#define UART0_IER (UART0_BASE + OFF_IER) -++#define UART0_ISR (UART0_BASE + OFF_ISR) -++#define UART0_FCR (UART0_BASE + OFF_FCR) -++#define UART0_LCR (UART0_BASE + OFF_LCR) -++#define UART0_MCR (UART0_BASE + OFF_MCR) -++#define UART0_LSR (UART0_BASE + OFF_LSR) -++#define UART0_MSR (UART0_BASE + OFF_MSR) -++#define UART0_SPR (UART0_BASE + OFF_SPR) -++#define UART0_SIRCR (UART0_BASE + OFF_SIRCR) -++ -++#define UART1_RDR (UART1_BASE + OFF_RDR) -++#define UART1_TDR (UART1_BASE + OFF_TDR) -++#define UART1_DLLR (UART1_BASE + OFF_DLLR) -++#define UART1_DLHR (UART1_BASE + OFF_DLHR) -++#define UART1_IER (UART1_BASE + OFF_IER) -++#define UART1_ISR (UART1_BASE + OFF_ISR) -++#define UART1_FCR (UART1_BASE + OFF_FCR) -++#define UART1_LCR (UART1_BASE + OFF_LCR) -++#define UART1_MCR (UART1_BASE + OFF_MCR) -++#define UART1_LSR (UART1_BASE + OFF_LSR) -++#define UART1_MSR (UART1_BASE + OFF_MSR) -++#define UART1_SPR (UART1_BASE + OFF_SPR) -++#define UART1_SIRCR (UART1_BASE + OFF_SIRCR) -++ -++#define UART2_RDR (UART2_BASE + OFF_RDR) -++#define UART2_TDR (UART2_BASE + OFF_TDR) -++#define UART2_DLLR (UART2_BASE + OFF_DLLR) -++#define UART2_DLHR (UART2_BASE + OFF_DLHR) -++#define UART2_IER (UART2_BASE + OFF_IER) -++#define UART2_ISR (UART2_BASE + OFF_ISR) -++#define UART2_FCR (UART2_BASE + OFF_FCR) -++#define UART2_LCR (UART2_BASE + OFF_LCR) -++#define UART2_MCR (UART2_BASE + OFF_MCR) -++#define UART2_LSR (UART2_BASE + OFF_LSR) -++#define UART2_MSR (UART2_BASE + OFF_MSR) -++#define UART2_SPR (UART2_BASE + OFF_SPR) -++#define UART2_SIRCR (UART2_BASE + OFF_SIRCR) -++ -++#define UART3_RDR (UART3_BASE + OFF_RDR) -++#define UART3_TDR (UART3_BASE + OFF_TDR) -++#define UART3_DLLR (UART3_BASE + OFF_DLLR) -++#define UART3_DLHR (UART3_BASE + OFF_DLHR) -++#define UART3_IER (UART3_BASE + OFF_IER) -++#define UART3_ISR (UART3_BASE + OFF_ISR) -++#define UART3_FCR (UART3_BASE + OFF_FCR) -++#define UART3_LCR (UART3_BASE + OFF_LCR) -++#define UART3_MCR (UART3_BASE + OFF_MCR) -++#define UART3_LSR (UART3_BASE + OFF_LSR) -++#define UART3_MSR (UART3_BASE + OFF_MSR) -++#define UART3_SPR (UART3_BASE + OFF_SPR) -++#define UART3_SIRCR (UART3_BASE + OFF_SIRCR) -++ -++/* -++ * Define macros for UARTIER -++ * UART Interrupt Enable Register -++ */ -++#define UARTIER_RIE (1 << 0) /* 0: receive fifo "full" interrupt disable */ -++#define UARTIER_TIE (1 << 1) /* 0: transmit fifo "empty" interrupt disable */ -++#define UARTIER_RLIE (1 << 2) /* 0: receive line status interrupt disable */ -++#define UARTIER_MIE (1 << 3) /* 0: modem status interrupt disable */ -++#define UARTIER_RTIE (1 << 4) /* 0: receive timeout interrupt disable */ -++ -++/* -++ * Define macros for UARTISR -++ * UART Interrupt Status Register -++ */ -++#define UARTISR_IP (1 << 0) /* 0: interrupt is pending 1: no interrupt */ -++#define UARTISR_IID (7 << 1) /* Source of Interrupt */ -++#define UARTISR_IID_MSI (0 << 1) /* Modem status interrupt */ -++#define UARTISR_IID_THRI (1 << 1) /* Transmitter holding register empty */ -++#define UARTISR_IID_RDI (2 << 1) /* Receiver data interrupt */ -++#define UARTISR_IID_RLSI (3 << 1) /* Receiver line status interrupt */ -++#define UARTISR_FFMS (3 << 6) /* FIFO mode select, set when UARTFCR.FE is set to 1 */ -++#define UARTISR_FFMS_NO_FIFO (0 << 6) -++#define UARTISR_FFMS_FIFO_MODE (3 << 6) -++ -++/* -++ * Define macros for UARTFCR -++ * UART FIFO Control Register -++ */ -++#define UARTFCR_FE (1 << 0) /* 0: non-FIFO mode 1: FIFO mode */ -++#define UARTFCR_RFLS (1 << 1) /* write 1 to flush receive FIFO */ -++#define UARTFCR_TFLS (1 << 2) /* write 1 to flush transmit FIFO */ -++#define UARTFCR_DMS (1 << 3) /* 0: disable DMA mode */ -++#define UARTFCR_UUE (1 << 4) /* 0: disable UART */ -++#define UARTFCR_RTRG (3 << 6) /* Receive FIFO Data Trigger */ -++#define UARTFCR_RTRG_1 (0 << 6) -++#define UARTFCR_RTRG_4 (1 << 6) -++#define UARTFCR_RTRG_8 (2 << 6) -++#define UARTFCR_RTRG_15 (3 << 6) -++ -++/* -++ * Define macros for UARTLCR -++ * UART Line Control Register -++ */ -++#define UARTLCR_WLEN (3 << 0) /* word length */ -++#define UARTLCR_WLEN_5 (0 << 0) -++#define UARTLCR_WLEN_6 (1 << 0) -++#define UARTLCR_WLEN_7 (2 << 0) -++#define UARTLCR_WLEN_8 (3 << 0) -++#define UARTLCR_STOP (1 << 2) /* 0: 1 stop bit when word length is 5,6,7,8 -++ 1: 1.5 stop bits when 5; 2 stop bits when 6,7,8 */ -++#define UARTLCR_PE (1 << 3) /* 0: parity disable */ -++#define UARTLCR_PROE (1 << 4) /* 0: even parity 1: odd parity */ -++#define UARTLCR_SPAR (1 << 5) /* 0: sticky parity disable */ -++#define UARTLCR_SBRK (1 << 6) /* write 0 normal, write 1 send break */ -++#define UARTLCR_DLAB (1 << 7) /* 0: access UARTRDR/TDR/IER 1: access UARTDLLR/DLHR */ -++ -++/* -++ * Define macros for UARTLSR -++ * UART Line Status Register -++ */ -++#define UARTLSR_DR (1 << 0) /* 0: receive FIFO is empty 1: receive data is ready */ -++#define UARTLSR_ORER (1 << 1) /* 0: no overrun error */ -++#define UARTLSR_PER (1 << 2) /* 0: no parity error */ -++#define UARTLSR_FER (1 << 3) /* 0; no framing error */ -++#define UARTLSR_BRK (1 << 4) /* 0: no break detected 1: receive a break signal */ -++#define UARTLSR_TDRQ (1 << 5) /* 1: transmit FIFO half "empty" */ -++#define UARTLSR_TEMT (1 << 6) /* 1: transmit FIFO and shift registers empty */ -++#define UARTLSR_RFER (1 << 7) /* 0: no receive error 1: receive error in FIFO mode */ -++ -++/* -++ * Define macros for UARTMCR -++ * UART Modem Control Register -++ */ -++#define UARTMCR_DTR (1 << 0) /* 0: DTR_ ouput high */ -++#define UARTMCR_RTS (1 << 1) /* 0: RTS_ output high */ -++#define UARTMCR_OUT1 (1 << 2) /* 0: UARTMSR.RI is set to 0 and RI_ input high */ -++#define UARTMCR_OUT2 (1 << 3) /* 0: UARTMSR.DCD is set to 0 and DCD_ input high */ -++#define UARTMCR_LOOP (1 << 4) /* 0: normal 1: loopback mode */ -++#define UARTMCR_MCE (1 << 7) /* 0: modem function is disable */ -++ -++/* -++ * Define macros for UARTMSR -++ * UART Modem Status Register -++ */ -++#define UARTMSR_DCTS (1 << 0) /* 0: no change on CTS_ pin since last read of UARTMSR */ -++#define UARTMSR_DDSR (1 << 1) /* 0: no change on DSR_ pin since last read of UARTMSR */ -++#define UARTMSR_DRI (1 << 2) /* 0: no change on RI_ pin since last read of UARTMSR */ -++#define UARTMSR_DDCD (1 << 3) /* 0: no change on DCD_ pin since last read of UARTMSR */ -++#define UARTMSR_CTS (1 << 4) /* 0: CTS_ pin is high */ -++#define UARTMSR_DSR (1 << 5) /* 0: DSR_ pin is high */ -++#define UARTMSR_RI (1 << 6) /* 0: RI_ pin is high */ -++#define UARTMSR_DCD (1 << 7) /* 0: DCD_ pin is high */ -++ -++/* -++ * Define macros for SIRCR -++ * Slow IrDA Control Register -++ */ -++#define SIRCR_TSIRE (1 << 0) /* 0: transmitter is in UART mode 1: IrDA mode */ -++#define SIRCR_RSIRE (1 << 1) /* 0: receiver is in UART mode 1: IrDA mode */ -++#define SIRCR_TPWS (1 << 2) /* 0: transmit 0 pulse width is 3/16 of bit length -++ 1: 0 pulse width is 1.6us for 115.2Kbps */ -++#define SIRCR_TXPL (1 << 3) /* 0: encoder generates a positive pulse for 0 */ -++#define SIRCR_RXPL (1 << 4) /* 0: decoder interprets positive pulse as 0 */ -++ -++ -++ -++/************************************************************************* -++ * INTC -++ *************************************************************************/ -++#define INTC_ISR (INTC_BASE + 0x00) -++#define INTC_IMR (INTC_BASE + 0x04) -++#define INTC_IMSR (INTC_BASE + 0x08) -++#define INTC_IMCR (INTC_BASE + 0x0c) -++#define INTC_IPR (INTC_BASE + 0x10) -++ -++#define REG_INTC_ISR REG32(INTC_ISR) -++#define REG_INTC_IMR REG32(INTC_IMR) -++#define REG_INTC_IMSR REG32(INTC_IMSR) -++#define REG_INTC_IMCR REG32(INTC_IMCR) -++#define REG_INTC_IPR REG32(INTC_IPR) -++ -++#define IRQ_I2C 1 -++#define IRQ_PS2 2 -++#define IRQ_UPRT 3 -++#define IRQ_CORE 4 -++#define IRQ_UART3 6 -++#define IRQ_UART2 7 -++#define IRQ_UART1 8 -++#define IRQ_UART0 9 -++#define IRQ_SCC1 10 -++#define IRQ_SCC0 11 -++#define IRQ_UDC 12 -++#define IRQ_UHC 13 -++#define IRQ_MSC 14 -++#define IRQ_RTC 15 -++#define IRQ_FIR 16 -++#define IRQ_SSI 17 -++#define IRQ_CIM 18 -++#define IRQ_ETH 19 -++#define IRQ_AIC 20 -++#define IRQ_DMAC 21 -++#define IRQ_OST2 22 -++#define IRQ_OST1 23 -++#define IRQ_OST0 24 -++#define IRQ_GPIO3 25 -++#define IRQ_GPIO2 26 -++#define IRQ_GPIO1 27 -++#define IRQ_GPIO0 28 -++#define IRQ_LCD 30 -++ -++ -++ -++ -++/************************************************************************* -++ * CIM -++ *************************************************************************/ -++#define CIM_CFG (CIM_BASE + 0x0000) -++#define CIM_CTRL (CIM_BASE + 0x0004) -++#define CIM_STATE (CIM_BASE + 0x0008) -++#define CIM_IID (CIM_BASE + 0x000C) -++#define CIM_RXFIFO (CIM_BASE + 0x0010) -++#define CIM_DA (CIM_BASE + 0x0020) -++#define CIM_FA (CIM_BASE + 0x0024) -++#define CIM_FID (CIM_BASE + 0x0028) -++#define CIM_CMD (CIM_BASE + 0x002C) -++ -++#define REG_CIM_CFG REG32(CIM_CFG) -++#define REG_CIM_CTRL REG32(CIM_CTRL) -++#define REG_CIM_STATE REG32(CIM_STATE) -++#define REG_CIM_IID REG32(CIM_IID) -++#define REG_CIM_RXFIFO REG32(CIM_RXFIFO) -++#define REG_CIM_DA REG32(CIM_DA) -++#define REG_CIM_FA REG32(CIM_FA) -++#define REG_CIM_FID REG32(CIM_FID) -++#define REG_CIM_CMD REG32(CIM_CMD) -++ -++/* CIM Configuration Register (CIM_CFG) */ -++ -++#define CIM_CFG_INV_DAT (1 << 15) -++#define CIM_CFG_VSP (1 << 14) -++#define CIM_CFG_HSP (1 << 13) -++#define CIM_CFG_PCP (1 << 12) -++#define CIM_CFG_DUMMY_ZERO (1 << 9) -++#define CIM_CFG_EXT_VSYNC (1 << 8) -++#define CIM_CFG_PACK_BIT 4 -++#define CIM_CFG_PACK_MASK (0x7 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_0 (0 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_1 (1 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_2 (2 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_3 (3 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_4 (4 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_5 (5 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_6 (6 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_7 (7 << CIM_CFG_PACK_BIT) -++#define CIM_CFG_DSM_BIT 0 -++#define CIM_CFG_DSM_MASK (0x3 << CIM_CFG_DSM_BIT) -++ #define CIM_CFG_DSM_CPM (0 << CIM_CFG_DSM_BIT) /* CCIR656 Progressive Mode */ -++ #define CIM_CFG_DSM_CIM (1 << CIM_CFG_DSM_BIT) /* CCIR656 Interlace Mode */ -++ #define CIM_CFG_DSM_GCM (2 << CIM_CFG_DSM_BIT) /* Gated Clock Mode */ -++ #define CIM_CFG_DSM_NGCM (3 << CIM_CFG_DSM_BIT) /* Non-Gated Clock Mode */ -++ -++/* CIM Control Register (CIM_CTRL) */ -++ -++#define CIM_CTRL_MCLKDIV_BIT 24 -++#define CIM_CTRL_MCLKDIV_MASK (0xff << CIM_CTRL_MCLKDIV_BIT) -++#define CIM_CTRL_FRC_BIT 16 -++#define CIM_CTRL_FRC_MASK (0xf << CIM_CTRL_FRC_BIT) -++ #define CIM_CTRL_FRC_1 (0x0 << CIM_CTRL_FRC_BIT) /* Sample every frame */ -++ #define CIM_CTRL_FRC_2 (0x1 << CIM_CTRL_FRC_BIT) /* Sample 1/2 frame */ -++ #define CIM_CTRL_FRC_3 (0x2 << CIM_CTRL_FRC_BIT) /* Sample 1/3 frame */ -++ #define CIM_CTRL_FRC_4 (0x3 << CIM_CTRL_FRC_BIT) /* Sample 1/4 frame */ -++ #define CIM_CTRL_FRC_5 (0x4 << CIM_CTRL_FRC_BIT) /* Sample 1/5 frame */ -++ #define CIM_CTRL_FRC_6 (0x5 << CIM_CTRL_FRC_BIT) /* Sample 1/6 frame */ -++ #define CIM_CTRL_FRC_7 (0x6 << CIM_CTRL_FRC_BIT) /* Sample 1/7 frame */ -++ #define CIM_CTRL_FRC_8 (0x7 << CIM_CTRL_FRC_BIT) /* Sample 1/8 frame */ -++ #define CIM_CTRL_FRC_9 (0x8 << CIM_CTRL_FRC_BIT) /* Sample 1/9 frame */ -++ #define CIM_CTRL_FRC_10 (0x9 << CIM_CTRL_FRC_BIT) /* Sample 1/10 frame */ -++ #define CIM_CTRL_FRC_11 (0xA << CIM_CTRL_FRC_BIT) /* Sample 1/11 frame */ -++ #define CIM_CTRL_FRC_12 (0xB << CIM_CTRL_FRC_BIT) /* Sample 1/12 frame */ -++ #define CIM_CTRL_FRC_13 (0xC << CIM_CTRL_FRC_BIT) /* Sample 1/13 frame */ -++ #define CIM_CTRL_FRC_14 (0xD << CIM_CTRL_FRC_BIT) /* Sample 1/14 frame */ -++ #define CIM_CTRL_FRC_15 (0xE << CIM_CTRL_FRC_BIT) /* Sample 1/15 frame */ -++ #define CIM_CTRL_FRC_16 (0xF << CIM_CTRL_FRC_BIT) /* Sample 1/16 frame */ -++#define CIM_CTRL_VDDM (1 << 13) -++#define CIM_CTRL_DMA_SOFM (1 << 12) -++#define CIM_CTRL_DMA_EOFM (1 << 11) -++#define CIM_CTRL_DMA_STOPM (1 << 10) -++#define CIM_CTRL_RXF_TRIGM (1 << 9) -++#define CIM_CTRL_RXF_OFM (1 << 8) -++#define CIM_CTRL_RXF_TRIG_BIT 4 -++#define CIM_CTRL_RXF_TRIG_MASK (0x7 << CIM_CTRL_RXF_TRIG_BIT) -++ #define CIM_CTRL_RXF_TRIG_4 (0 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 4 */ -++ #define CIM_CTRL_RXF_TRIG_8 (1 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 8 */ -++ #define CIM_CTRL_RXF_TRIG_12 (2 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 12 */ -++ #define CIM_CTRL_RXF_TRIG_16 (3 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 16 */ -++ #define CIM_CTRL_RXF_TRIG_20 (4 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 20 */ -++ #define CIM_CTRL_RXF_TRIG_24 (5 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 24 */ -++ #define CIM_CTRL_RXF_TRIG_28 (6 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 28 */ -++ #define CIM_CTRL_RXF_TRIG_32 (7 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 32 */ -++#define CIM_CTRL_DMA_EN (1 << 2) -++#define CIM_CTRL_RXF_RST (1 << 1) -++#define CIM_CTRL_ENA (1 << 0) -++ -++/* CIM State Register (CIM_STATE) */ -++ -++#define CIM_STATE_DMA_SOF (1 << 6) -++#define CIM_STATE_DMA_EOF (1 << 5) -++#define CIM_STATE_DMA_STOP (1 << 4) -++#define CIM_STATE_RXF_OF (1 << 3) -++#define CIM_STATE_RXF_TRIG (1 << 2) -++#define CIM_STATE_RXF_EMPTY (1 << 1) -++#define CIM_STATE_VDD (1 << 0) -++ -++/* CIM DMA Command Register (CIM_CMD) */ -++ -++#define CIM_CMD_SOFINT (1 << 31) -++#define CIM_CMD_EOFINT (1 << 30) -++#define CIM_CMD_STOP (1 << 28) -++#define CIM_CMD_LEN_BIT 0 -++#define CIM_CMD_LEN_MASK (0xffffff << CIM_CMD_LEN_BIT) -++ -++ -++ -++ -++/************************************************************************* -++ * PWM -++ *************************************************************************/ -++#define PWM_CTR(n) (PWM##n##_BASE + 0x000) -++#define PWM_PER(n) (PWM##n##_BASE + 0x004) -++#define PWM_DUT(n) (PWM##n##_BASE + 0x008) -++ -++#define REG_PWM_CTR(n) REG8(PWM_CTR(n)) -++#define REG_PWM_PER(n) REG16(PWM_PER(n)) -++#define REG_PWM_DUT(n) REG16(PWM_DUT(n)) -++ -++/* PWM Control Register (PWM_CTR) */ -++ -++#define PWM_CTR_EN (1 << 7) -++#define PWM_CTR_SD (1 << 6) -++#define PWM_CTR_PRESCALE_BIT 0 -++#define PWM_CTR_PRESCALE_MASK (0x3f << PWM_CTR_PRESCALE_BIT) -++ -++/* PWM Period Register (PWM_PER) */ -++ -++#define PWM_PER_PERIOD_BIT 0 -++#define PWM_PER_PERIOD_MASK (0x3ff << PWM_PER_PERIOD_BIT) -++ -++/* PWM Duty Register (PWM_DUT) */ -++ -++#define PWM_DUT_FDUTY (1 << 10) -++#define PWM_DUT_DUTY_BIT 0 -++#define PWM_DUT_DUTY_MASK (0x3ff << PWM_DUT_DUTY_BIT) -++ -++ -++ -++ -++/************************************************************************* -++ * EMC -++ *************************************************************************/ -++#define EMC_BCR (EMC_BASE + 0x00) -++#define EMC_SMCR0 (EMC_BASE + 0x10) -++#define EMC_SMCR1 (EMC_BASE + 0x14) -++#define EMC_SMCR2 (EMC_BASE + 0x18) -++#define EMC_SMCR3 (EMC_BASE + 0x1c) -++#define EMC_SMCR4 (EMC_BASE + 0x20) -++#define EMC_SMCR5 (EMC_BASE + 0x24) -++#define EMC_SMCR6 (EMC_BASE + 0x28) -++#define EMC_SMCR7 (EMC_BASE + 0x2c) -++#define EMC_SACR0 (EMC_BASE + 0x30) -++#define EMC_SACR1 (EMC_BASE + 0x34) -++#define EMC_SACR2 (EMC_BASE + 0x38) -++#define EMC_SACR3 (EMC_BASE + 0x3c) -++#define EMC_SACR4 (EMC_BASE + 0x40) -++#define EMC_SACR5 (EMC_BASE + 0x44) -++#define EMC_SACR6 (EMC_BASE + 0x48) -++#define EMC_SACR7 (EMC_BASE + 0x4c) -++#define EMC_NFCSR (EMC_BASE + 0x50) -++#define EMC_NFECC (EMC_BASE + 0x54) -++#define EMC_PCCR1 (EMC_BASE + 0x60) -++#define EMC_PCCR2 (EMC_BASE + 0x64) -++#define EMC_PCCR3 (EMC_BASE + 0x68) -++#define EMC_PCCR4 (EMC_BASE + 0x6c) -++#define EMC_DMCR (EMC_BASE + 0x80) -++#define EMC_RTCSR (EMC_BASE + 0x84) -++#define EMC_RTCNT (EMC_BASE + 0x88) -++#define EMC_RTCOR (EMC_BASE + 0x8c) -++#define EMC_DMAR1 (EMC_BASE + 0x90) -++#define EMC_DMAR2 (EMC_BASE + 0x94) -++#define EMC_DMAR3 (EMC_BASE + 0x98) -++#define EMC_DMAR4 (EMC_BASE + 0x9c) -++ -++#define EMC_SDMR0 (EMC_BASE + 0xa000) -++#define EMC_SDMR1 (EMC_BASE + 0xb000) -++#define EMC_SDMR2 (EMC_BASE + 0xc000) -++#define EMC_SDMR3 (EMC_BASE + 0xd000) -++ -++#define REG_EMC_BCR REG32(EMC_BCR) -++#define REG_EMC_SMCR0 REG32(EMC_SMCR0) -++#define REG_EMC_SMCR1 REG32(EMC_SMCR1) -++#define REG_EMC_SMCR2 REG32(EMC_SMCR2) -++#define REG_EMC_SMCR3 REG32(EMC_SMCR3) -++#define REG_EMC_SMCR4 REG32(EMC_SMCR4) -++#define REG_EMC_SMCR5 REG32(EMC_SMCR5) -++#define REG_EMC_SMCR6 REG32(EMC_SMCR6) -++#define REG_EMC_SMCR7 REG32(EMC_SMCR7) -++#define REG_EMC_SACR0 REG32(EMC_SACR0) -++#define REG_EMC_SACR1 REG32(EMC_SACR1) -++#define REG_EMC_SACR2 REG32(EMC_SACR2) -++#define REG_EMC_SACR3 REG32(EMC_SACR3) -++#define REG_EMC_SACR4 REG32(EMC_SACR4) -++#define REG_EMC_SACR5 REG32(EMC_SACR5) -++#define REG_EMC_SACR6 REG32(EMC_SACR6) -++#define REG_EMC_SACR7 REG32(EMC_SACR7) -++#define REG_EMC_NFCSR REG32(EMC_NFCSR) -++#define REG_EMC_NFECC REG32(EMC_NFECC) -++#define REG_EMC_DMCR REG32(EMC_DMCR) -++#define REG_EMC_RTCSR REG16(EMC_RTCSR) -++#define REG_EMC_RTCNT REG16(EMC_RTCNT) -++#define REG_EMC_RTCOR REG16(EMC_RTCOR) -++#define REG_EMC_DMAR1 REG32(EMC_DMAR1) -++#define REG_EMC_DMAR2 REG32(EMC_DMAR2) -++#define REG_EMC_DMAR3 REG32(EMC_DMAR3) -++#define REG_EMC_DMAR4 REG32(EMC_DMAR4) -++#define REG_EMC_PCCR1 REG32(EMC_PCCR1) -++#define REG_EMC_PCCR2 REG32(EMC_PCCR2) -++#define REG_EMC_PCCR3 REG32(EMC_PCCR3) -++#define REG_EMC_PCCR4 REG32(EMC_PCCR4) -++ -++ -++#define EMC_BCR_BRE (1 << 1) -++ -++#define EMC_SMCR_STRV_BIT 24 -++#define EMC_SMCR_STRV_MASK (0x0f << EMC_SMCR_STRV_BIT) -++#define EMC_SMCR_TAW_BIT 20 -++#define EMC_SMCR_TAW_MASK (0x0f << EMC_SMCR_TAW_BIT) -++#define EMC_SMCR_TBP_BIT 16 -++#define EMC_SMCR_TBP_MASK (0x0f << EMC_SMCR_TBP_BIT) -++#define EMC_SMCR_TAH_BIT 12 -++#define EMC_SMCR_TAH_MASK (0x07 << EMC_SMCR_TAH_BIT) -++#define EMC_SMCR_TAS_BIT 8 -++#define EMC_SMCR_TAS_MASK (0x07 << EMC_SMCR_TAS_BIT) -++#define EMC_SMCR_BW_BIT 6 -++#define EMC_SMCR_BW_MASK (0x03 << EMC_SMCR_BW_BIT) -++ #define EMC_SMCR_BW_8BIT (0 << EMC_SMCR_BW_BIT) -++ #define EMC_SMCR_BW_16BIT (1 << EMC_SMCR_BW_BIT) -++ #define EMC_SMCR_BW_32BIT (2 << EMC_SMCR_BW_BIT) -++#define EMC_SMCR_BCM (1 << 3) -++#define EMC_SMCR_BL_BIT 1 -++#define EMC_SMCR_BL_MASK (0x03 << EMC_SMCR_BL_BIT) -++ #define EMC_SMCR_BL_4 (0 << EMC_SMCR_BL_BIT) -++ #define EMC_SMCR_BL_8 (1 << EMC_SMCR_BL_BIT) -++ #define EMC_SMCR_BL_16 (2 << EMC_SMCR_BL_BIT) -++ #define EMC_SMCR_BL_32 (3 << EMC_SMCR_BL_BIT) -++#define EMC_SMCR_SMT (1 << 0) -++ -++#define EMC_SACR_BASE_BIT 8 -++#define EMC_SACR_BASE_MASK (0xff << EMC_SACR_BASE_BIT) -++#define EMC_SACR_MASK_BIT 0 -++#define EMC_SACR_MASK_MASK (0xff << EMC_SACR_MASK_BIT) -++ -++#define EMC_NFCSR_RB (1 << 7) -++#define EMC_NFCSR_BOOT_SEL_BIT 4 -++#define EMC_NFCSR_BOOT_SEL_MASK (0x07 << EMC_NFCSR_BOOT_SEL_BIT) -++#define EMC_NFCSR_ERST (1 << 3) -++#define EMC_NFCSR_ECCE (1 << 2) -++#define EMC_NFCSR_FCE (1 << 1) -++#define EMC_NFCSR_NFE (1 << 0) -++ -++#define EMC_NFECC_ECC2_BIT 16 -++#define EMC_NFECC_ECC2_MASK (0xff << EMC_NFECC_ECC2_BIT) -++#define EMC_NFECC_ECC1_BIT 8 -++#define EMC_NFECC_ECC1_MASK (0xff << EMC_NFECC_ECC1_BIT) -++#define EMC_NFECC_ECC0_BIT 0 -++#define EMC_NFECC_ECC0_MASK (0xff << EMC_NFECC_ECC0_BIT) -++ -++#define EMC_DMCR_BW_BIT 31 -++#define EMC_DMCR_BW (1 << EMC_DMCR_BW_BIT) -++#define EMC_DMCR_CA_BIT 26 -++#define EMC_DMCR_CA_MASK (0x07 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_8 (0 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_9 (1 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_10 (2 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_11 (3 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_12 (4 << EMC_DMCR_CA_BIT) -++#define EMC_DMCR_RMODE (1 << 25) -++#define EMC_DMCR_RFSH (1 << 24) -++#define EMC_DMCR_MRSET (1 << 23) -++#define EMC_DMCR_RA_BIT 20 -++#define EMC_DMCR_RA_MASK (0x03 << EMC_DMCR_RA_BIT) -++ #define EMC_DMCR_RA_11 (0 << EMC_DMCR_RA_BIT) -++ #define EMC_DMCR_RA_12 (1 << EMC_DMCR_RA_BIT) -++ #define EMC_DMCR_RA_13 (2 << EMC_DMCR_RA_BIT) -++#define EMC_DMCR_BA_BIT 19 -++#define EMC_DMCR_BA (1 << EMC_DMCR_BA_BIT) -++#define EMC_DMCR_PDM (1 << 18) -++#define EMC_DMCR_EPIN (1 << 17) -++#define EMC_DMCR_TRAS_BIT 13 -++#define EMC_DMCR_TRAS_MASK (0x07 << EMC_DMCR_TRAS_BIT) -++#define EMC_DMCR_RCD_BIT 11 -++#define EMC_DMCR_RCD_MASK (0x03 << EMC_DMCR_RCD_BIT) -++#define EMC_DMCR_TPC_BIT 8 -++#define EMC_DMCR_TPC_MASK (0x07 << EMC_DMCR_TPC_BIT) -++#define EMC_DMCR_TRWL_BIT 5 -++#define EMC_DMCR_TRWL_MASK (0x03 << EMC_DMCR_TRWL_BIT) -++#define EMC_DMCR_TRC_BIT 2 -++#define EMC_DMCR_TRC_MASK (0x07 << EMC_DMCR_TRC_BIT) -++#define EMC_DMCR_TCL_BIT 0 -++#define EMC_DMCR_TCL_MASK (0x03 << EMC_DMCR_TCL_BIT) -++ -++#define EMC_RTCSR_CMF (1 << 7) -++#define EMC_RTCSR_CKS_BIT 0 -++#define EMC_RTCSR_CKS_MASK (0x07 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_DISABLE (0 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_4 (1 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_16 (2 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_64 (3 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_256 (4 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_1024 (5 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_2048 (6 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_4096 (7 << EMC_RTCSR_CKS_BIT) -++ -++#define EMC_DMAR_BASE_BIT 8 -++#define EMC_DMAR_BASE_MASK (0xff << EMC_DMAR_BASE_BIT) -++#define EMC_DMAR_MASK_BIT 0 -++#define EMC_DMAR_MASK_MASK (0xff << EMC_DMAR_MASK_BIT) -++ -++#define EMC_SDMR_BM (1 << 9) -++#define EMC_SDMR_OM_BIT 7 -++#define EMC_SDMR_OM_MASK (3 << EMC_SDMR_OM_BIT) -++ #define EMC_SDMR_OM_NORMAL (0 << EMC_SDMR_OM_BIT) -++#define EMC_SDMR_CAS_BIT 4 -++#define EMC_SDMR_CAS_MASK (7 << EMC_SDMR_CAS_BIT) -++ #define EMC_SDMR_CAS_1 (1 << EMC_SDMR_CAS_BIT) -++ #define EMC_SDMR_CAS_2 (2 << EMC_SDMR_CAS_BIT) -++ #define EMC_SDMR_CAS_3 (3 << EMC_SDMR_CAS_BIT) -++#define EMC_SDMR_BT_BIT 3 -++#define EMC_SDMR_BT_MASK (1 << EMC_SDMR_BT_BIT) -++ #define EMC_SDMR_BT_SEQ (0 << EMC_SDMR_BT_BIT) -++ #define EMC_SDMR_BT_INTR (1 << EMC_SDMR_BT_BIT) -++#define EMC_SDMR_BL_BIT 0 -++#define EMC_SDMR_BL_MASK (7 << EMC_SDMR_BL_BIT) -++ #define EMC_SDMR_BL_1 (0 << EMC_SDMR_BL_BIT) -++ #define EMC_SDMR_BL_2 (1 << EMC_SDMR_BL_BIT) -++ #define EMC_SDMR_BL_4 (2 << EMC_SDMR_BL_BIT) -++ #define EMC_SDMR_BL_8 (3 << EMC_SDMR_BL_BIT) -++ -++#define EMC_SDMR_CAS2_16BIT \ -++ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) -++#define EMC_SDMR_CAS2_32BIT \ -++ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) -++#define EMC_SDMR_CAS3_16BIT \ -++ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) -++#define EMC_SDMR_CAS3_32BIT \ -++ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) -++ -++#define EMC_PCCR12_AMW (1 << 31) -++#define EMC_PCCR12_AMAS_BIT 28 -++#define EMC_PCCR12_AMAS_MASK (0x07 << EMC_PCCR12_AMAS_BIT) -++#define EMC_PCCR12_AMAH_BIT 24 -++#define EMC_PCCR12_AMAH_MASK (0x07 << EMC_PCCR12_AMAH_BIT) -++#define EMC_PCCR12_AMPW_BIT 20 -++#define EMC_PCCR12_AMPW_MASK (0x0f << EMC_PCCR12_AMPW_BIT) -++#define EMC_PCCR12_AMRT_BIT 16 -++#define EMC_PCCR12_AMRT_MASK (0x0f << EMC_PCCR12_AMRT_BIT) -++#define EMC_PCCR12_CMW (1 << 15) -++#define EMC_PCCR12_CMAS_BIT 12 -++#define EMC_PCCR12_CMAS_MASK (0x07 << EMC_PCCR12_CMAS_BIT) -++#define EMC_PCCR12_CMAH_BIT 8 -++#define EMC_PCCR12_CMAH_MASK (0x07 << EMC_PCCR12_CMAH_BIT) -++#define EMC_PCCR12_CMPW_BIT 4 -++#define EMC_PCCR12_CMPW_MASK (0x0f << EMC_PCCR12_CMPW_BIT) -++#define EMC_PCCR12_CMRT_BIT 0 -++#define EMC_PCCR12_CMRT_MASK (0x07 << EMC_PCCR12_CMRT_BIT) -++ -++#define EMC_PCCR34_DRS_BIT 16 -++#define EMC_PCCR34_DRS_MASK (0x03 << EMC_PCCR34_DRS_BIT) -++ #define EMC_PCCR34_DRS_SPKR (1 << EMC_PCCR34_DRS_BIT) -++ #define EMC_PCCR34_DRS_IOIS16 (2 << EMC_PCCR34_DRS_BIT) -++ #define EMC_PCCR34_DRS_INPACK (3 << EMC_PCCR34_DRS_BIT) -++#define EMC_PCCR34_IOIS16 (1 << 15) -++#define EMC_PCCR34_IOW (1 << 14) -++#define EMC_PCCR34_TCB_BIT 12 -++#define EMC_PCCR34_TCB_MASK (0x03 << EMC_PCCR34_TCB_BIT) -++#define EMC_PCCR34_IORT_BIT 8 -++#define EMC_PCCR34_IORT_MASK (0x07 << EMC_PCCR34_IORT_BIT) -++#define EMC_PCCR34_IOAE_BIT 6 -++#define EMC_PCCR34_IOAE_MASK (0x03 << EMC_PCCR34_IOAE_BIT) -++ #define EMC_PCCR34_IOAE_NONE (0 << EMC_PCCR34_IOAE_BIT) -++ #define EMC_PCCR34_IOAE_1 (1 << EMC_PCCR34_IOAE_BIT) -++ #define EMC_PCCR34_IOAE_2 (2 << EMC_PCCR34_IOAE_BIT) -++ #define EMC_PCCR34_IOAE_5 (3 << EMC_PCCR34_IOAE_BIT) -++#define EMC_PCCR34_IOAH_BIT 4 -++#define EMC_PCCR34_IOAH_MASK (0x03 << EMC_PCCR34_IOAH_BIT) -++ #define EMC_PCCR34_IOAH_NONE (0 << EMC_PCCR34_IOAH_BIT) -++ #define EMC_PCCR34_IOAH_1 (1 << EMC_PCCR34_IOAH_BIT) -++ #define EMC_PCCR34_IOAH_2 (2 << EMC_PCCR34_IOAH_BIT) -++ #define EMC_PCCR34_IOAH_5 (3 << EMC_PCCR34_IOAH_BIT) -++#define EMC_PCCR34_IOPW_BIT 0 -++#define EMC_PCCR34_IOPW_MASK (0x0f << EMC_PCCR34_IOPW_BIT) -++ -++ -++ -++ -++/************************************************************************* -++ * GPIO -++ *************************************************************************/ -++#define GPIO_GPDR(n) (GPIO_BASE + (0x00 + (n)*0x30)) -++#define GPIO_GPDIR(n) (GPIO_BASE + (0x04 + (n)*0x30)) -++#define GPIO_GPODR(n) (GPIO_BASE + (0x08 + (n)*0x30)) -++#define GPIO_GPPUR(n) (GPIO_BASE + (0x0c + (n)*0x30)) -++#define GPIO_GPALR(n) (GPIO_BASE + (0x10 + (n)*0x30)) -++#define GPIO_GPAUR(n) (GPIO_BASE + (0x14 + (n)*0x30)) -++#define GPIO_GPIDLR(n) (GPIO_BASE + (0x18 + (n)*0x30)) -++#define GPIO_GPIDUR(n) (GPIO_BASE + (0x1c + (n)*0x30)) -++#define GPIO_GPIER(n) (GPIO_BASE + (0x20 + (n)*0x30)) -++#define GPIO_GPIMR(n) (GPIO_BASE + (0x24 + (n)*0x30)) -++#define GPIO_GPFR(n) (GPIO_BASE + (0x28 + (n)*0x30)) -++ -++#define REG_GPIO_GPDR(n) REG32(GPIO_GPDR((n))) -++#define REG_GPIO_GPDIR(n) REG32(GPIO_GPDIR((n))) -++#define REG_GPIO_GPODR(n) REG32(GPIO_GPODR((n))) -++#define REG_GPIO_GPPUR(n) REG32(GPIO_GPPUR((n))) -++#define REG_GPIO_GPALR(n) REG32(GPIO_GPALR((n))) -++#define REG_GPIO_GPAUR(n) REG32(GPIO_GPAUR((n))) -++#define REG_GPIO_GPIDLR(n) REG32(GPIO_GPIDLR((n))) -++#define REG_GPIO_GPIDUR(n) REG32(GPIO_GPIDUR((n))) -++#define REG_GPIO_GPIER(n) REG32(GPIO_GPIER((n))) -++#define REG_GPIO_GPIMR(n) REG32(GPIO_GPIMR((n))) -++#define REG_GPIO_GPFR(n) REG32(GPIO_GPFR((n))) -++ -++#define GPIO_IRQ_LOLEVEL 0 -++#define GPIO_IRQ_HILEVEL 1 -++#define GPIO_IRQ_FALLEDG 2 -++#define GPIO_IRQ_RAISEDG 3 -++ -++#define IRQ_GPIO_0 48 -++#define NUM_GPIO 128 -++ -++#define GPIO_GPDR0 GPIO_GPDR(0) -++#define GPIO_GPDR1 GPIO_GPDR(1) -++#define GPIO_GPDR2 GPIO_GPDR(2) -++#define GPIO_GPDR3 GPIO_GPDR(3) -++#define GPIO_GPDIR0 GPIO_GPDIR(0) -++#define GPIO_GPDIR1 GPIO_GPDIR(1) -++#define GPIO_GPDIR2 GPIO_GPDIR(2) -++#define GPIO_GPDIR3 GPIO_GPDIR(3) -++#define GPIO_GPODR0 GPIO_GPODR(0) -++#define GPIO_GPODR1 GPIO_GPODR(1) -++#define GPIO_GPODR2 GPIO_GPODR(2) -++#define GPIO_GPODR3 GPIO_GPODR(3) -++#define GPIO_GPPUR0 GPIO_GPPUR(0) -++#define GPIO_GPPUR1 GPIO_GPPUR(1) -++#define GPIO_GPPUR2 GPIO_GPPUR(2) -++#define GPIO_GPPUR3 GPIO_GPPUR(3) -++#define GPIO_GPALR0 GPIO_GPALR(0) -++#define GPIO_GPALR1 GPIO_GPALR(1) -++#define GPIO_GPALR2 GPIO_GPALR(2) -++#define GPIO_GPALR3 GPIO_GPALR(3) -++#define GPIO_GPAUR0 GPIO_GPAUR(0) -++#define GPIO_GPAUR1 GPIO_GPAUR(1) -++#define GPIO_GPAUR2 GPIO_GPAUR(2) -++#define GPIO_GPAUR3 GPIO_GPAUR(3) -++#define GPIO_GPIDLR0 GPIO_GPIDLR(0) -++#define GPIO_GPIDLR1 GPIO_GPIDLR(1) -++#define GPIO_GPIDLR2 GPIO_GPIDLR(2) -++#define GPIO_GPIDLR3 GPIO_GPIDLR(3) -++#define GPIO_GPIDUR0 GPIO_GPIDUR(0) -++#define GPIO_GPIDUR1 GPIO_GPIDUR(1) -++#define GPIO_GPIDUR2 GPIO_GPIDUR(2) -++#define GPIO_GPIDUR3 GPIO_GPIDUR(3) -++#define GPIO_GPIER0 GPIO_GPIER(0) -++#define GPIO_GPIER1 GPIO_GPIER(1) -++#define GPIO_GPIER2 GPIO_GPIER(2) -++#define GPIO_GPIER3 GPIO_GPIER(3) -++#define GPIO_GPIMR0 GPIO_GPIMR(0) -++#define GPIO_GPIMR1 GPIO_GPIMR(1) -++#define GPIO_GPIMR2 GPIO_GPIMR(2) -++#define GPIO_GPIMR3 GPIO_GPIMR(3) -++#define GPIO_GPFR0 GPIO_GPFR(0) -++#define GPIO_GPFR1 GPIO_GPFR(1) -++#define GPIO_GPFR2 GPIO_GPFR(2) -++#define GPIO_GPFR3 GPIO_GPFR(3) -++ -++ -++/************************************************************************* -++ * HARB -++ *************************************************************************/ -++#define HARB_HAPOR (HARB_BASE + 0x000) -++#define HARB_HMCTR (HARB_BASE + 0x010) -++#define HARB_HME8H (HARB_BASE + 0x014) -++#define HARB_HMCR1 (HARB_BASE + 0x018) -++#define HARB_HMER2 (HARB_BASE + 0x01C) -++#define HARB_HMER3 (HARB_BASE + 0x020) -++#define HARB_HMLTR (HARB_BASE + 0x024) -++ -++#define REG_HARB_HAPOR REG32(HARB_HAPOR) -++#define REG_HARB_HMCTR REG32(HARB_HMCTR) -++#define REG_HARB_HME8H REG32(HARB_HME8H) -++#define REG_HARB_HMCR1 REG32(HARB_HMCR1) -++#define REG_HARB_HMER2 REG32(HARB_HMER2) -++#define REG_HARB_HMER3 REG32(HARB_HMER3) -++#define REG_HARB_HMLTR REG32(HARB_HMLTR) -++ -++/* HARB Priority Order Register (HARB_HAPOR) */ -++ -++#define HARB_HAPOR_UCHSEL (1 << 7) -++#define HARB_HAPOR_PRIO_BIT 0 -++#define HARB_HAPOR_PRIO_MASK (0xf << HARB_HAPOR_PRIO_BIT) -++ -++/* AHB Monitor Control Register (HARB_HMCTR) */ -++ -++#define HARB_HMCTR_HET3_BIT 20 -++#define HARB_HMCTR_HET3_MASK (0xf << HARB_HMCTR_HET3_BIT) -++#define HARB_HMCTR_HMS3_BIT 16 -++#define HARB_HMCTR_HMS3_MASK (0xf << HARB_HMCTR_HMS3_BIT) -++#define HARB_HMCTR_HET2_BIT 12 -++#define HARB_HMCTR_HET2_MASK (0xf << HARB_HMCTR_HET2_BIT) -++#define HARB_HMCTR_HMS2_BIT 8 -++#define HARB_HMCTR_HMS2_MASK (0xf << HARB_HMCTR_HMS2_BIT) -++#define HARB_HMCTR_HOVF3 (1 << 7) -++#define HARB_HMCTR_HOVF2 (1 << 6) -++#define HARB_HMCTR_HOVF1 (1 << 5) -++#define HARB_HMCTR_HRST (1 << 4) -++#define HARB_HMCTR_HEE3 (1 << 2) -++#define HARB_HMCTR_HEE2 (1 << 1) -++#define HARB_HMCTR_HEE1 (1 << 0) -++ -++/* AHB Monitor Event 8bits High Register (HARB_HME8H) */ -++ -++#define HARB_HME8H_HC8H1_BIT 16 -++#define HARB_HME8H_HC8H1_MASK (0xff << HARB_HME8H_HC8H1_BIT) -++#define HARB_HME8H_HC8H2_BIT 8 -++#define HARB_HME8H_HC8H2_MASK (0xff << HARB_HME8H_HC8H2_BIT) -++#define HARB_HME8H_HC8H3_BIT 0 -++#define HARB_HME8H_HC8H3_MASK (0xff << HARB_HME8H_HC8H3_BIT) -++ -++/* AHB Monitor Latency Register (HARB_HMLTR) */ -++ -++#define HARB_HMLTR_HLT2_BIT 16 -++#define HARB_HMLTR_HLT2_MASK (0xffff << HARB_HMLTR_HLT2_BIT) -++#define HARB_HMLTR_HLT3_BIT 0 -++#define HARB_HMLTR_HLT3_MASK (0xffff << HARB_HMLTR_HLT3_BIT) -++ -++ -++ -++ -++/************************************************************************* -++ * I2C -++ *************************************************************************/ -++#define I2C_DR (I2C_BASE + 0x000) -++#define I2C_CR (I2C_BASE + 0x004) -++#define I2C_SR (I2C_BASE + 0x008) -++#define I2C_GR (I2C_BASE + 0x00C) -++ -++#define REG_I2C_DR REG8(I2C_DR) -++#define REG_I2C_CR REG8(I2C_CR) -++#define REG_I2C_SR REG8(I2C_SR) -++#define REG_I2C_GR REG16(I2C_GR) -++ -++/* I2C Control Register (I2C_CR) */ -++ -++#define I2C_CR_IEN (1 << 4) -++#define I2C_CR_STA (1 << 3) -++#define I2C_CR_STO (1 << 2) -++#define I2C_CR_AC (1 << 1) -++#define I2C_CR_I2CE (1 << 0) -++ -++/* I2C Status Register (I2C_SR) */ -++ -++#define I2C_SR_STX (1 << 4) -++#define I2C_SR_BUSY (1 << 3) -++#define I2C_SR_TEND (1 << 2) -++#define I2C_SR_DRF (1 << 1) -++#define I2C_SR_ACKF (1 << 0) -++ -++ -++ -++ -++/************************************************************************* -++ * UDC -++ *************************************************************************/ -++#define UDC_EP0InCR (UDC_BASE + 0x00) -++#define UDC_EP0InSR (UDC_BASE + 0x04) -++#define UDC_EP0InBSR (UDC_BASE + 0x08) -++#define UDC_EP0InMPSR (UDC_BASE + 0x0c) -++#define UDC_EP0InDesR (UDC_BASE + 0x14) -++#define UDC_EP1InCR (UDC_BASE + 0x20) -++#define UDC_EP1InSR (UDC_BASE + 0x24) -++#define UDC_EP1InBSR (UDC_BASE + 0x28) -++#define UDC_EP1InMPSR (UDC_BASE + 0x2c) -++#define UDC_EP1InDesR (UDC_BASE + 0x34) -++#define UDC_EP2InCR (UDC_BASE + 0x40) -++#define UDC_EP2InSR (UDC_BASE + 0x44) -++#define UDC_EP2InBSR (UDC_BASE + 0x48) -++#define UDC_EP2InMPSR (UDC_BASE + 0x4c) -++#define UDC_EP2InDesR (UDC_BASE + 0x54) -++#define UDC_EP3InCR (UDC_BASE + 0x60) -++#define UDC_EP3InSR (UDC_BASE + 0x64) -++#define UDC_EP3InBSR (UDC_BASE + 0x68) -++#define UDC_EP3InMPSR (UDC_BASE + 0x6c) -++#define UDC_EP3InDesR (UDC_BASE + 0x74) -++#define UDC_EP4InCR (UDC_BASE + 0x80) -++#define UDC_EP4InSR (UDC_BASE + 0x84) -++#define UDC_EP4InBSR (UDC_BASE + 0x88) -++#define UDC_EP4InMPSR (UDC_BASE + 0x8c) -++#define UDC_EP4InDesR (UDC_BASE + 0x94) -++ -++#define UDC_EP0OutCR (UDC_BASE + 0x200) -++#define UDC_EP0OutSR (UDC_BASE + 0x204) -++#define UDC_EP0OutPFNR (UDC_BASE + 0x208) -++#define UDC_EP0OutMPSR (UDC_BASE + 0x20c) -++#define UDC_EP0OutSBPR (UDC_BASE + 0x210) -++#define UDC_EP0OutDesR (UDC_BASE + 0x214) -++#define UDC_EP5OutCR (UDC_BASE + 0x2a0) -++#define UDC_EP5OutSR (UDC_BASE + 0x2a4) -++#define UDC_EP5OutPFNR (UDC_BASE + 0x2a8) -++#define UDC_EP5OutMPSR (UDC_BASE + 0x2ac) -++#define UDC_EP5OutDesR (UDC_BASE + 0x2b4) -++#define UDC_EP6OutCR (UDC_BASE + 0x2c0) -++#define UDC_EP6OutSR (UDC_BASE + 0x2c4) -++#define UDC_EP6OutPFNR (UDC_BASE + 0x2c8) -++#define UDC_EP6OutMPSR (UDC_BASE + 0x2cc) -++#define UDC_EP6OutDesR (UDC_BASE + 0x2d4) -++#define UDC_EP7OutCR (UDC_BASE + 0x2e0) -++#define UDC_EP7OutSR (UDC_BASE + 0x2e4) -++#define UDC_EP7OutPFNR (UDC_BASE + 0x2e8) -++#define UDC_EP7OutMPSR (UDC_BASE + 0x2ec) -++#define UDC_EP7OutDesR (UDC_BASE + 0x2f4) -++ -++#define UDC_DevCFGR (UDC_BASE + 0x400) -++#define UDC_DevCR (UDC_BASE + 0x404) -++#define UDC_DevSR (UDC_BASE + 0x408) -++#define UDC_DevIntR (UDC_BASE + 0x40c) -++#define UDC_DevIntMR (UDC_BASE + 0x410) -++#define UDC_EPIntR (UDC_BASE + 0x414) -++#define UDC_EPIntMR (UDC_BASE + 0x418) -++ -++#define UDC_STCMAR (UDC_BASE + 0x500) -++#define UDC_EP0InfR (UDC_BASE + 0x504) -++#define UDC_EP1InfR (UDC_BASE + 0x508) -++#define UDC_EP2InfR (UDC_BASE + 0x50c) -++#define UDC_EP3InfR (UDC_BASE + 0x510) -++#define UDC_EP4InfR (UDC_BASE + 0x514) -++#define UDC_EP5InfR (UDC_BASE + 0x518) -++#define UDC_EP6InfR (UDC_BASE + 0x51c) -++#define UDC_EP7InfR (UDC_BASE + 0x520) -++ -++#define UDC_TXCONFIRM (UDC_BASE + 0x41C) -++#define UDC_TXZLP (UDC_BASE + 0x420) -++#define UDC_RXCONFIRM (UDC_BASE + 0x41C) -++ -++#define UDC_RXFIFO (UDC_BASE + 0x800) -++#define UDC_TXFIFOEP0 (UDC_BASE + 0x840) -++ -++#define REG_UDC_EP0InCR REG32(UDC_EP0InCR) -++#define REG_UDC_EP0InSR REG32(UDC_EP0InSR) -++#define REG_UDC_EP0InBSR REG32(UDC_EP0InBSR) -++#define REG_UDC_EP0InMPSR REG32(UDC_EP0InMPSR) -++#define REG_UDC_EP0InDesR REG32(UDC_EP0InDesR) -++#define REG_UDC_EP1InCR REG32(UDC_EP1InCR) -++#define REG_UDC_EP1InSR REG32(UDC_EP1InSR) -++#define REG_UDC_EP1InBSR REG32(UDC_EP1InBSR) -++#define REG_UDC_EP1InMPSR REG32(UDC_EP1InMPSR) -++#define REG_UDC_EP1InDesR REG32(UDC_EP1InDesR) -++#define REG_UDC_EP2InCR REG32(UDC_EP2InCR) -++#define REG_UDC_EP2InSR REG32(UDC_EP2InSR) -++#define REG_UDC_EP2InBSR REG32(UDC_EP2InBSR) -++#define REG_UDC_EP2InMPSR REG32(UDC_EP2InMPSR) -++#define REG_UDC_EP2InDesR REG32(UDC_EP2InDesR) -++#define REG_UDC_EP3InCR REG32(UDC_EP3InCR) -++#define REG_UDC_EP3InSR REG32(UDC_EP3InSR) -++#define REG_UDC_EP3InBSR REG32(UDC_EP3InBSR) -++#define REG_UDC_EP3InMPSR REG32(UDC_EP3InMPSR) -++#define REG_UDC_EP3InDesR REG32(UDC_EP3InDesR) -++#define REG_UDC_EP4InCR REG32(UDC_EP4InCR) -++#define REG_UDC_EP4InSR REG32(UDC_EP4InSR) -++#define REG_UDC_EP4InBSR REG32(UDC_EP4InBSR) -++#define REG_UDC_EP4InMPSR REG32(UDC_EP4InMPSR) -++#define REG_UDC_EP4InDesR REG32(UDC_EP4InDesR) -++ -++#define REG_UDC_EP0OutCR REG32(UDC_EP0OutCR) -++#define REG_UDC_EP0OutSR REG32(UDC_EP0OutSR) -++#define REG_UDC_EP0OutPFNR REG32(UDC_EP0OutPFNR) -++#define REG_UDC_EP0OutMPSR REG32(UDC_EP0OutMPSR) -++#define REG_UDC_EP0OutSBPR REG32(UDC_EP0OutSBPR) -++#define REG_UDC_EP0OutDesR REG32(UDC_EP0OutDesR) -++#define REG_UDC_EP5OutCR REG32(UDC_EP5OutCR) -++#define REG_UDC_EP5OutSR REG32(UDC_EP5OutSR) -++#define REG_UDC_EP5OutPFNR REG32(UDC_EP5OutPFNR) -++#define REG_UDC_EP5OutMPSR REG32(UDC_EP5OutMPSR) -++#define REG_UDC_EP5OutDesR REG32(UDC_EP5OutDesR) -++#define REG_UDC_EP6OutCR REG32(UDC_EP6OutCR) -++#define REG_UDC_EP6OutSR REG32(UDC_EP6OutSR) -++#define REG_UDC_EP6OutPFNR REG32(UDC_EP6OutPFNR) -++#define REG_UDC_EP6OutMPSR REG32(UDC_EP6OutMPSR) -++#define REG_UDC_EP6OutDesR REG32(UDC_EP6OutDesR) -++#define REG_UDC_EP7OutCR REG32(UDC_EP7OutCR) -++#define REG_UDC_EP7OutSR REG32(UDC_EP7OutSR) -++#define REG_UDC_EP7OutPFNR REG32(UDC_EP7OutPFNR) -++#define REG_UDC_EP7OutMPSR REG32(UDC_EP7OutMPSR) -++#define REG_UDC_EP7OutDesR REG32(UDC_EP7OutDesR) -++ -++#define REG_UDC_DevCFGR REG32(UDC_DevCFGR) -++#define REG_UDC_DevCR REG32(UDC_DevCR) -++#define REG_UDC_DevSR REG32(UDC_DevSR) -++#define REG_UDC_DevIntR REG32(UDC_DevIntR) -++#define REG_UDC_DevIntMR REG32(UDC_DevIntMR) -++#define REG_UDC_EPIntR REG32(UDC_EPIntR) -++#define REG_UDC_EPIntMR REG32(UDC_EPIntMR) -++ -++#define REG_UDC_STCMAR REG32(UDC_STCMAR) -++#define REG_UDC_EP0InfR REG32(UDC_EP0InfR) -++#define REG_UDC_EP1InfR REG32(UDC_EP1InfR) -++#define REG_UDC_EP2InfR REG32(UDC_EP2InfR) -++#define REG_UDC_EP3InfR REG32(UDC_EP3InfR) -++#define REG_UDC_EP4InfR REG32(UDC_EP4InfR) -++#define REG_UDC_EP5InfR REG32(UDC_EP5InfR) -++#define REG_UDC_EP6InfR REG32(UDC_EP6InfR) -++#define REG_UDC_EP7InfR REG32(UDC_EP7InfR) -++ -++#define UDC_DevCFGR_PI (1 << 5) -++#define UDC_DevCFGR_SS (1 << 4) -++#define UDC_DevCFGR_SP (1 << 3) -++#define UDC_DevCFGR_RW (1 << 2) -++#define UDC_DevCFGR_SPD_BIT 0 -++#define UDC_DevCFGR_SPD_MASK (0x03 << UDC_DevCFGR_SPD_BIT) -++ #define UDC_DevCFGR_SPD_HS (0 << UDC_DevCFGR_SPD_BIT) -++ #define UDC_DevCFGR_SPD_LS (2 << UDC_DevCFGR_SPD_BIT) -++ #define UDC_DevCFGR_SPD_FS (3 << UDC_DevCFGR_SPD_BIT) -++ -++#define UDC_DevCR_DM (1 << 9) -++#define UDC_DevCR_BE (1 << 5) -++#define UDC_DevCR_RES (1 << 0) -++ -++#define UDC_DevSR_ENUMSPD_BIT 13 -++#define UDC_DevSR_ENUMSPD_MASK (0x03 << UDC_DevSR_ENUMSPD_BIT) -++ #define UDC_DevSR_ENUMSPD_HS (0 << UDC_DevSR_ENUMSPD_BIT) -++ #define UDC_DevSR_ENUMSPD_LS (2 << UDC_DevSR_ENUMSPD_BIT) -++ #define UDC_DevSR_ENUMSPD_FS (3 << UDC_DevSR_ENUMSPD_BIT) -++#define UDC_DevSR_SUSP (1 << 12) -++#define UDC_DevSR_ALT_BIT 8 -++#define UDC_DevSR_ALT_MASK (0x0f << UDC_DevSR_ALT_BIT) -++#define UDC_DevSR_INTF_BIT 4 -++#define UDC_DevSR_INTF_MASK (0x0f << UDC_DevSR_INTF_BIT) -++#define UDC_DevSR_CFG_BIT 0 -++#define UDC_DevSR_CFG_MASK (0x0f << UDC_DevSR_CFG_BIT) -++ -++#define UDC_DevIntR_ENUM (1 << 6) -++#define UDC_DevIntR_SOF (1 << 5) -++#define UDC_DevIntR_US (1 << 4) -++#define UDC_DevIntR_UR (1 << 3) -++#define UDC_DevIntR_SI (1 << 1) -++#define UDC_DevIntR_SC (1 << 0) -++ -++#define UDC_EPIntR_OUTEP_BIT 16 -++#define UDC_EPIntR_OUTEP_MASK (0xffff << UDC_EPIntR_OUTEP_BIT) -++#define UDC_EPIntR_OUTEP0 0x00010000 -++#define UDC_EPIntR_OUTEP5 0x00200000 -++#define UDC_EPIntR_OUTEP6 0x00400000 -++#define UDC_EPIntR_OUTEP7 0x00800000 -++#define UDC_EPIntR_INEP_BIT 0 -++#define UDC_EPIntR_INEP_MASK (0xffff << UDC_EPIntR_INEP_BIT) -++#define UDC_EPIntR_INEP0 0x00000001 -++#define UDC_EPIntR_INEP1 0x00000002 -++#define UDC_EPIntR_INEP2 0x00000004 -++#define UDC_EPIntR_INEP3 0x00000008 -++#define UDC_EPIntR_INEP4 0x00000010 -++ -++ -++#define UDC_EPIntMR_OUTEP_BIT 16 -++#define UDC_EPIntMR_OUTEP_MASK (0xffff << UDC_EPIntMR_OUTEP_BIT) -++#define UDC_EPIntMR_INEP_BIT 0 -++#define UDC_EPIntMR_INEP_MASK (0xffff << UDC_EPIntMR_INEP_BIT) -++ -++#define UDC_EPCR_ET_BIT 4 -++#define UDC_EPCR_ET_MASK (0x03 << UDC_EPCR_ET_BIT) -++ #define UDC_EPCR_ET_CTRL (0 << UDC_EPCR_ET_BIT) -++ #define UDC_EPCR_ET_ISO (1 << UDC_EPCR_ET_BIT) -++ #define UDC_EPCR_ET_BULK (2 << UDC_EPCR_ET_BIT) -++ #define UDC_EPCR_ET_INTR (3 << UDC_EPCR_ET_BIT) -++#define UDC_EPCR_SN (1 << 2) -++#define UDC_EPCR_F (1 << 1) -++#define UDC_EPCR_S (1 << 0) -++ -++#define UDC_EPSR_RXPKTSIZE_BIT 11 -++#define UDC_EPSR_RXPKTSIZE_MASK (0x7ff << UDC_EPSR_RXPKTSIZE_BIT) -++#define UDC_EPSR_IN (1 << 6) -++#define UDC_EPSR_OUT_BIT 4 -++#define UDC_EPSR_OUT_MASK (0x03 << UDC_EPSR_OUT_BIT) -++ #define UDC_EPSR_OUT_NONE (0 << UDC_EPSR_OUT_BIT) -++ #define UDC_EPSR_OUT_RCVDATA (1 << UDC_EPSR_OUT_BIT) -++ #define UDC_EPSR_OUT_RCVSETUP (2 << UDC_EPSR_OUT_BIT) -++#define UDC_EPSR_PID_BIT 0 -++#define UDC_EPSR_PID_MASK (0x0f << UDC_EPSR_PID_BIT) -++ -++#define UDC_EPInfR_MPS_BIT 19 -++#define UDC_EPInfR_MPS_MASK (0x3ff << UDC_EPInfR_MPS_BIT) -++#define UDC_EPInfR_ALTS_BIT 15 -++#define UDC_EPInfR_ALTS_MASK (0x0f << UDC_EPInfR_ALTS_BIT) -++#define UDC_EPInfR_IFN_BIT 11 -++#define UDC_EPInfR_IFN_MASK (0x0f << UDC_EPInfR_IFN_BIT) -++#define UDC_EPInfR_CGN_BIT 7 -++#define UDC_EPInfR_CGN_MASK (0x0f << UDC_EPInfR_CGN_BIT) -++#define UDC_EPInfR_EPT_BIT 5 -++#define UDC_EPInfR_EPT_MASK (0x03 << UDC_EPInfR_EPT_BIT) -++ #define UDC_EPInfR_EPT_CTRL (0 << UDC_EPInfR_EPT_BIT) -++ #define UDC_EPInfR_EPT_ISO (1 << UDC_EPInfR_EPT_BIT) -++ #define UDC_EPInfR_EPT_BULK (2 << UDC_EPInfR_EPT_BIT) -++ #define UDC_EPInfR_EPT_INTR (3 << UDC_EPInfR_EPT_BIT) -++#define UDC_EPInfR_EPD (1 << 4) -++ #define UDC_EPInfR_EPD_OUT (0 << 4) -++ #define UDC_EPInfR_EPD_IN (1 << 4) -++ -++#define UDC_EPInfR_EPN_BIT 0 -++#define UDC_EPInfR_EPN_MASK (0xf << UDC_EPInfR_EPN_BIT) -++ -++ -++ -++ -++/************************************************************************* -++ * DMAC -++ *************************************************************************/ -++#define DMAC_DSAR(n) (DMAC_BASE + (0x00 + (n) * 0x20)) -++#define DMAC_DDAR(n) (DMAC_BASE + (0x04 + (n) * 0x20)) -++#define DMAC_DTCR(n) (DMAC_BASE + (0x08 + (n) * 0x20)) -++#define DMAC_DRSR(n) (DMAC_BASE + (0x0c + (n) * 0x20)) -++#define DMAC_DCCSR(n) (DMAC_BASE + (0x10 + (n) * 0x20)) -++#define DMAC_DMAIPR (DMAC_BASE + 0xf8) -++#define DMAC_DMACR (DMAC_BASE + 0xfc) -++ -++#define REG_DMAC_DSAR(n) REG32(DMAC_DSAR((n))) -++#define REG_DMAC_DDAR(n) REG32(DMAC_DDAR((n))) -++#define REG_DMAC_DTCR(n) REG32(DMAC_DTCR((n))) -++#define REG_DMAC_DRSR(n) REG32(DMAC_DRSR((n))) -++#define REG_DMAC_DCCSR(n) REG32(DMAC_DCCSR((n))) -++#define REG_DMAC_DMAIPR REG32(DMAC_DMAIPR) -++#define REG_DMAC_DMACR REG32(DMAC_DMACR) -++ -++#define DMAC_DRSR_RS_BIT 0 -++#define DMAC_DRSR_RS_MASK (0x1f << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_EXTREXTR (0 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_PCMCIAOUT (4 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_PCMCIAIN (5 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_AUTO (8 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_DESOUT (10 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_DESIN (11 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_UART3OUT (14 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_UART3IN (15 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_UART2OUT (16 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_UART2IN (17 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_UART1OUT (18 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_UART1IN (19 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_UART0OUT (20 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_UART0IN (21 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_SSIOUT (22 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_SSIIN (23 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_AICOUT (24 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_AICIN (25 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_MSCOUT (26 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_MSCIN (27 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_OST2 (28 << DMAC_DRSR_RS_BIT) -++ -++#define DMAC_DCCSR_EACKS (1 << 31) -++#define DMAC_DCCSR_EACKM (1 << 30) -++#define DMAC_DCCSR_ERDM_BIT 28 -++#define DMAC_DCCSR_ERDM_MASK (0x03 << DMAC_DCCSR_ERDM_BIT) -++ #define DMAC_DCCSR_ERDM_LLEVEL (0 << DMAC_DCCSR_ERDM_BIT) -++ #define DMAC_DCCSR_ERDM_FEDGE (1 << DMAC_DCCSR_ERDM_BIT) -++ #define DMAC_DCCSR_ERDM_HLEVEL (2 << DMAC_DCCSR_ERDM_BIT) -++ #define DMAC_DCCSR_ERDM_REDGE (3 << DMAC_DCCSR_ERDM_BIT) -++#define DMAC_DCCSR_EOPM (1 << 27) -++#define DMAC_DCCSR_SAM (1 << 23) -++#define DMAC_DCCSR_DAM (1 << 22) -++#define DMAC_DCCSR_RDIL_BIT 16 -++#define DMAC_DCCSR_RDIL_MASK (0x0f << DMAC_DCCSR_RDIL_BIT) -++ #define DMAC_DCCSR_RDIL_IGN (0 << DMAC_DCCSR_RDIL_BIT) -++ #define DMAC_DCCSR_RDIL_2 (1 << DMAC_DCCSR_RDIL_BIT) -++ #define DMAC_DCCSR_RDIL_4 (2 << DMAC_DCCSR_RDIL_BIT) -++ #define DMAC_DCCSR_RDIL_8 (3 << DMAC_DCCSR_RDIL_BIT) -++ #define DMAC_DCCSR_RDIL_12 (4 << DMAC_DCCSR_RDIL_BIT) -++ #define DMAC_DCCSR_RDIL_16 (5 << DMAC_DCCSR_RDIL_BIT) -++ #define DMAC_DCCSR_RDIL_20 (6 << DMAC_DCCSR_RDIL_BIT) -++ #define DMAC_DCCSR_RDIL_24 (7 << DMAC_DCCSR_RDIL_BIT) -++ #define DMAC_DCCSR_RDIL_28 (8 << DMAC_DCCSR_RDIL_BIT) -++ #define DMAC_DCCSR_RDIL_32 (9 << DMAC_DCCSR_RDIL_BIT) -++ #define DMAC_DCCSR_RDIL_48 (10 << DMAC_DCCSR_RDIL_BIT) -++ #define DMAC_DCCSR_RDIL_60 (11 << DMAC_DCCSR_RDIL_BIT) -++ #define DMAC_DCCSR_RDIL_64 (12 << DMAC_DCCSR_RDIL_BIT) -++ #define DMAC_DCCSR_RDIL_124 (13 << DMAC_DCCSR_RDIL_BIT) -++ #define DMAC_DCCSR_RDIL_128 (14 << DMAC_DCCSR_RDIL_BIT) -++ #define DMAC_DCCSR_RDIL_200 (15 << DMAC_DCCSR_RDIL_BIT) -++#define DMAC_DCCSR_SWDH_BIT 14 -++#define DMAC_DCCSR_SWDH_MASK (0x03 << DMAC_DCCSR_SWDH_BIT) -++ #define DMAC_DCCSR_SWDH_32 (0 << DMAC_DCCSR_SWDH_BIT) -++ #define DMAC_DCCSR_SWDH_8 (1 << DMAC_DCCSR_SWDH_BIT) -++ #define DMAC_DCCSR_SWDH_16 (2 << DMAC_DCCSR_SWDH_BIT) -++#define DMAC_DCCSR_DWDH_BIT 12 -++#define DMAC_DCCSR_DWDH_MASK (0x03 << DMAC_DCCSR_DWDH_BIT) -++ #define DMAC_DCCSR_DWDH_32 (0 << DMAC_DCCSR_DWDH_BIT) -++ #define DMAC_DCCSR_DWDH_8 (1 << DMAC_DCCSR_DWDH_BIT) -++ #define DMAC_DCCSR_DWDH_16 (2 << DMAC_DCCSR_DWDH_BIT) -++#define DMAC_DCCSR_DS_BIT 8 -++#define DMAC_DCCSR_DS_MASK (0x07 << DMAC_DCCSR_DS_BIT) -++ #define DMAC_DCCSR_DS_32b (0 << DMAC_DCCSR_DS_BIT) -++ #define DMAC_DCCSR_DS_8b (1 << DMAC_DCCSR_DS_BIT) -++ #define DMAC_DCCSR_DS_16b (2 << DMAC_DCCSR_DS_BIT) -++ #define DMAC_DCCSR_DS_16B (3 << DMAC_DCCSR_DS_BIT) -++ #define DMAC_DCCSR_DS_32B (4 << DMAC_DCCSR_DS_BIT) -++#define DMAC_DCCSR_TM (1 << 7) -++#define DMAC_DCCSR_AR (1 << 4) -++#define DMAC_DCCSR_TC (1 << 3) -++#define DMAC_DCCSR_HLT (1 << 2) -++#define DMAC_DCCSR_TCIE (1 << 1) -++#define DMAC_DCCSR_CHDE (1 << 0) -++ -++#define DMAC_DMAIPR_CINT_BIT 8 -++#define DMAC_DMAIPR_CINT_MASK (0xff << DMAC_DMAIPR_CINT_BIT) -++ -++#define DMAC_DMACR_PR_BIT 8 -++#define DMAC_DMACR_PR_MASK (0x03 << DMAC_DMACR_PR_BIT) -++ #define DMAC_DMACR_PR_01234567 (0 << DMAC_DMACR_PR_BIT) -++ #define DMAC_DMACR_PR_02314675 (1 << DMAC_DMACR_PR_BIT) -++ #define DMAC_DMACR_PR_20136457 (2 << DMAC_DMACR_PR_BIT) -++ #define DMAC_DMACR_PR_ROUNDROBIN (3 << DMAC_DMACR_PR_BIT) -++#define DMAC_DMACR_HTR (1 << 3) -++#define DMAC_DMACR_AER (1 << 2) -++#define DMAC_DMACR_DME (1 << 0) -++ -++#define IRQ_DMA_0 32 -++#define NUM_DMA 6 -++ -++#define DMAC_DSAR0 DMAC_DSAR(0) -++#define DMAC_DDAR0 DMAC_DDAR(0) -++#define DMAC_DTCR0 DMAC_DTCR(0) -++#define DMAC_DRSR0 DMAC_DRSR(0) -++#define DMAC_DCCSR0 DMAC_DCCSR(0) -++ -++#define DMAC_DSAR1 DMAC_DSAR(1) -++#define DMAC_DDAR1 DMAC_DDAR(1) -++#define DMAC_DTCR1 DMAC_DTCR(1) -++#define DMAC_DRSR1 DMAC_DRSR(1) -++#define DMAC_DCCSR1 DMAC_DCCSR(1) -++ -++#define DMAC_DSAR2 DMAC_DSAR(2) -++#define DMAC_DDAR2 DMAC_DDAR(2) -++#define DMAC_DTCR2 DMAC_DTCR(2) -++#define DMAC_DRSR2 DMAC_DRSR(2) -++#define DMAC_DCCSR2 DMAC_DCCSR(2) -++ -++#define DMAC_DSAR3 DMAC_DSAR(3) -++#define DMAC_DDAR3 DMAC_DDAR(3) -++#define DMAC_DTCR3 DMAC_DTCR(3) -++#define DMAC_DRSR3 DMAC_DRSR(3) -++#define DMAC_DCCSR3 DMAC_DCCSR(3) -++ -++#define DMAC_DSAR4 DMAC_DSAR(4) -++#define DMAC_DDAR4 DMAC_DDAR(4) -++#define DMAC_DTCR4 DMAC_DTCR(4) -++#define DMAC_DRSR4 DMAC_DRSR(4) -++#define DMAC_DCCSR4 DMAC_DCCSR(4) -++ -++#define DMAC_DSAR5 DMAC_DSAR(5) -++#define DMAC_DDAR5 DMAC_DDAR(5) -++#define DMAC_DTCR5 DMAC_DTCR(5) -++#define DMAC_DRSR5 DMAC_DRSR(5) -++#define DMAC_DCCSR5 DMAC_DCCSR(5) -++ -++#define DMAC_DSAR6 DMAC_DSAR(6) -++#define DMAC_DDAR6 DMAC_DDAR(6) -++#define DMAC_DTCR6 DMAC_DTCR(6) -++#define DMAC_DRSR6 DMAC_DRSR(6) -++#define DMAC_DCCSR6 DMAC_DCCSR(6) -++ -++#define DMAC_DSAR7 DMAC_DSAR(7) -++#define DMAC_DDAR7 DMAC_DDAR(7) -++#define DMAC_DTCR7 DMAC_DTCR(7) -++#define DMAC_DRSR7 DMAC_DRSR(7) -++#define DMAC_DCCSR7 DMAC_DCCSR(7) -++ -++ -++ -++/************************************************************************* -++ * AIC -++ *************************************************************************/ -++#define AIC_FR (AIC_BASE + 0x000) -++#define AIC_CR (AIC_BASE + 0x004) -++#define AIC_ACCR1 (AIC_BASE + 0x008) -++#define AIC_ACCR2 (AIC_BASE + 0x00C) -++#define AIC_I2SCR (AIC_BASE + 0x010) -++#define AIC_SR (AIC_BASE + 0x014) -++#define AIC_ACSR (AIC_BASE + 0x018) -++#define AIC_I2SSR (AIC_BASE + 0x01C) -++#define AIC_ACCAR (AIC_BASE + 0x020) -++#define AIC_ACCDR (AIC_BASE + 0x024) -++#define AIC_ACSAR (AIC_BASE + 0x028) -++#define AIC_ACSDR (AIC_BASE + 0x02C) -++#define AIC_I2SDIV (AIC_BASE + 0x030) -++#define AIC_DR (AIC_BASE + 0x034) -++ -++#define REG_AIC_FR REG32(AIC_FR) -++#define REG_AIC_CR REG32(AIC_CR) -++#define REG_AIC_ACCR1 REG32(AIC_ACCR1) -++#define REG_AIC_ACCR2 REG32(AIC_ACCR2) -++#define REG_AIC_I2SCR REG32(AIC_I2SCR) -++#define REG_AIC_SR REG32(AIC_SR) -++#define REG_AIC_ACSR REG32(AIC_ACSR) -++#define REG_AIC_I2SSR REG32(AIC_I2SSR) -++#define REG_AIC_ACCAR REG32(AIC_ACCAR) -++#define REG_AIC_ACCDR REG32(AIC_ACCDR) -++#define REG_AIC_ACSAR REG32(AIC_ACSAR) -++#define REG_AIC_ACSDR REG32(AIC_ACSDR) -++#define REG_AIC_I2SDIV REG32(AIC_I2SDIV) -++#define REG_AIC_DR REG32(AIC_DR) -++ -++/* AIC Controller Configuration Register (AIC_FR) */ -++ -++#define AIC_FR_RFTH_BIT 12 -++#define AIC_FR_RFTH_MASK (0xf << AIC_FR_RFTH_BIT) -++#define AIC_FR_TFTH_BIT 8 -++#define AIC_FR_TFTH_MASK (0xf << AIC_FR_TFTH_BIT) -++#define AIC_FR_AUSEL (1 << 4) -++#define AIC_FR_RST (1 << 3) -++#define AIC_FR_BCKD (1 << 2) -++#define AIC_FR_SYNCD (1 << 1) -++#define AIC_FR_ENB (1 << 0) -++ -++/* AIC Controller Common Control Register (AIC_CR) */ -++ -++#define AIC_CR_RDMS (1 << 15) -++#define AIC_CR_TDMS (1 << 14) -++#define AIC_CR_FLUSH (1 << 8) -++#define AIC_CR_EROR (1 << 6) -++#define AIC_CR_ETUR (1 << 5) -++#define AIC_CR_ERFS (1 << 4) -++#define AIC_CR_ETFS (1 << 3) -++#define AIC_CR_ENLBF (1 << 2) -++#define AIC_CR_ERPL (1 << 1) -++#define AIC_CR_EREC (1 << 0) -++ -++/* AIC Controller AC-link Control Register 1 (AIC_ACCR1) */ -++ -++#define AIC_ACCR1_RS_BIT 16 -++#define AIC_ACCR1_RS_MASK (0x3ff << AIC_ACCR1_RS_BIT) -++ #define AIC_ACCR1_RS_SLOT12 (1 << 25) /* Slot 12 valid bit */ -++ #define AIC_ACCR1_RS_SLOT11 (1 << 24) /* Slot 11 valid bit */ -++ #define AIC_ACCR1_RS_SLOT10 (1 << 23) /* Slot 10 valid bit */ -++ #define AIC_ACCR1_RS_SLOT9 (1 << 22) /* Slot 9 valid bit */ -++ #define AIC_ACCR1_RS_SLOT8 (1 << 21) /* Slot 8 valid bit */ -++ #define AIC_ACCR1_RS_SLOT7 (1 << 20) /* Slot 7 valid bit */ -++ #define AIC_ACCR1_RS_SLOT6 (1 << 19) /* Slot 6 valid bit */ -++ #define AIC_ACCR1_RS_SLOT5 (1 << 18) /* Slot 5 valid bit */ -++ #define AIC_ACCR1_RS_SLOT4 (1 << 17) /* Slot 4 valid bit */ -++ #define AIC_ACCR1_RS_SLOT3 (1 << 16) /* Slot 3 valid bit */ -++#define AIC_ACCR1_XS_BIT 0 -++#define AIC_ACCR1_XS_MASK (0x3ff << AIC_ACCR1_XS_BIT) -++ #define AIC_ACCR1_XS_SLOT12 (1 << 9) /* Slot 12 valid bit */ -++ #define AIC_ACCR1_XS_SLOT11 (1 << 8) /* Slot 11 valid bit */ -++ #define AIC_ACCR1_XS_SLOT10 (1 << 7) /* Slot 10 valid bit */ -++ #define AIC_ACCR1_XS_SLOT9 (1 << 6) /* Slot 9 valid bit */ -++ #define AIC_ACCR1_XS_SLOT8 (1 << 5) /* Slot 8 valid bit */ -++ #define AIC_ACCR1_XS_SLOT7 (1 << 4) /* Slot 7 valid bit */ -++ #define AIC_ACCR1_XS_SLOT6 (1 << 3) /* Slot 6 valid bit */ -++ #define AIC_ACCR1_XS_SLOT5 (1 << 2) /* Slot 5 valid bit */ -++ #define AIC_ACCR1_XS_SLOT4 (1 << 1) /* Slot 4 valid bit */ -++ #define AIC_ACCR1_XS_SLOT3 (1 << 0) /* Slot 3 valid bit */ -++ -++/* AIC Controller AC-link Control Register 2 (AIC_ACCR2) */ -++ -++#define AIC_ACCR2_ERSTO (1 << 18) -++#define AIC_ACCR2_ESADR (1 << 17) -++#define AIC_ACCR2_ECADT (1 << 16) -++#define AIC_ACCR2_OASS_BIT 8 -++#define AIC_ACCR2_OASS_MASK (0x3 << AIC_ACCR2_OASS_BIT) -++ #define AIC_ACCR2_OASS_20BIT (0 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 20-bit */ -++ #define AIC_ACCR2_OASS_18BIT (1 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 18-bit */ -++ #define AIC_ACCR2_OASS_16BIT (2 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 16-bit */ -++ #define AIC_ACCR2_OASS_8BIT (3 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 8-bit */ -++#define AIC_ACCR2_IASS_BIT 6 -++#define AIC_ACCR2_IASS_MASK (0x3 << AIC_ACCR2_IASS_BIT) -++ #define AIC_ACCR2_IASS_20BIT (0 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 20-bit */ -++ #define AIC_ACCR2_IASS_18BIT (1 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 18-bit */ -++ #define AIC_ACCR2_IASS_16BIT (2 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 16-bit */ -++ #define AIC_ACCR2_IASS_8BIT (3 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 8-bit */ -++#define AIC_ACCR2_SO (1 << 3) -++#define AIC_ACCR2_SR (1 << 2) -++#define AIC_ACCR2_SS (1 << 1) -++#define AIC_ACCR2_SA (1 << 0) -++ -++/* AIC Controller I2S/MSB-justified Control Register (AIC_I2SCR) */ -++ -++#define AIC_I2SCR_STPBK (1 << 12) -++#define AIC_I2SCR_WL_BIT 1 -++#define AIC_I2SCR_WL_MASK (0x7 << AIC_I2SCR_WL_BIT) -++ #define AIC_I2SCR_WL_24BIT (0 << AIC_I2SCR_WL_BIT) /* Word Length is 24 bit */ -++ #define AIC_I2SCR_WL_20BIT (1 << AIC_I2SCR_WL_BIT) /* Word Length is 20 bit */ -++ #define AIC_I2SCR_WL_18BIT (2 << AIC_I2SCR_WL_BIT) /* Word Length is 18 bit */ -++ #define AIC_I2SCR_WL_16BIT (3 << AIC_I2SCR_WL_BIT) /* Word Length is 16 bit */ -++ #define AIC_I2SCR_WL_8BIT (4 << AIC_I2SCR_WL_BIT) /* Word Length is 8 bit */ -++#define AIC_I2SCR_AMSL (1 << 0) -++ -++/* AIC Controller FIFO Status Register (AIC_SR) */ -++ -++#define AIC_SR_RFL_BIT 24 -++#define AIC_SR_RFL_MASK (0x1f << AIC_SR_RFL_BIT) -++#define AIC_SR_TFL_BIT 8 -++#define AIC_SR_TFL_MASK (0x1f << AIC_SR_TFL_BIT) -++#define AIC_SR_ROR (1 << 6) -++#define AIC_SR_TUR (1 << 5) -++#define AIC_SR_RFS (1 << 4) -++#define AIC_SR_TFS (1 << 3) -++ -++/* AIC Controller AC-link Status Register (AIC_ACSR) */ -++ -++#define AIC_ACSR_CRDY (1 << 20) -++#define AIC_ACSR_CLPM (1 << 19) -++#define AIC_ACSR_RSTO (1 << 18) -++#define AIC_ACSR_SADR (1 << 17) -++#define AIC_ACSR_CADT (1 << 16) -++ -++/* AIC Controller I2S/MSB-justified Status Register (AIC_I2SSR) */ -++ -++#define AIC_I2SSR_BSY (1 << 2) -++ -++/* AIC Controller AC97 codec Command Address Register (AIC_ACCAR) */ -++ -++#define AIC_ACCAR_CAR_BIT 0 -++#define AIC_ACCAR_CAR_MASK (0xfffff << AIC_ACCAR_CAR_BIT) -++ -++/* AIC Controller AC97 codec Command Data Register (AIC_ACCDR) */ -++ -++#define AIC_ACCDR_CDR_BIT 0 -++#define AIC_ACCDR_CDR_MASK (0xfffff << AIC_ACCDR_CDR_BIT) -++ -++/* AIC Controller AC97 codec Status Address Register (AIC_ACSAR) */ -++ -++#define AIC_ACSAR_SAR_BIT 0 -++#define AIC_ACSAR_SAR_MASK (0xfffff << AIC_ACSAR_SAR_BIT) -++ -++/* AIC Controller AC97 codec Status Data Register (AIC_ACSDR) */ -++ -++#define AIC_ACSDR_SDR_BIT 0 -++#define AIC_ACSDR_SDR_MASK (0xfffff << AIC_ACSDR_SDR_BIT) -++ -++/* AIC Controller I2S/MSB-justified Clock Divider Register (AIC_I2SDIV) */ -++ -++#define AIC_I2SDIV_DIV_BIT 0 -++#define AIC_I2SDIV_DIV_MASK (0x7f << AIC_I2SDIV_DIV_BIT) -++ #define AIC_I2SDIV_BITCLK_3072KHZ (0x0C << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 3.072MHz */ -++ #define AIC_I2SDIV_BITCLK_2836KHZ (0x0D << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 2.836MHz */ -++ #define AIC_I2SDIV_BITCLK_1418KHZ (0x1A << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.418MHz */ -++ #define AIC_I2SDIV_BITCLK_1024KHZ (0x24 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.024MHz */ -++ #define AIC_I2SDIV_BITCLK_7089KHZ (0x34 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 708.92KHz */ -++ #define AIC_I2SDIV_BITCLK_512KHZ (0x48 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 512.00KHz */ -++ -++ -++ -++ -++/************************************************************************* -++ * LCD -++ *************************************************************************/ -++#define LCD_CFG (LCD_BASE + 0x00) -++#define LCD_VSYNC (LCD_BASE + 0x04) -++#define LCD_HSYNC (LCD_BASE + 0x08) -++#define LCD_VAT (LCD_BASE + 0x0c) -++#define LCD_DAH (LCD_BASE + 0x10) -++#define LCD_DAV (LCD_BASE + 0x14) -++#define LCD_PS (LCD_BASE + 0x18) -++#define LCD_CLS (LCD_BASE + 0x1c) -++#define LCD_SPL (LCD_BASE + 0x20) -++#define LCD_REV (LCD_BASE + 0x24) -++#define LCD_CTRL (LCD_BASE + 0x30) -++#define LCD_STATE (LCD_BASE + 0x34) -++#define LCD_IID (LCD_BASE + 0x38) -++#define LCD_DA0 (LCD_BASE + 0x40) -++#define LCD_SA0 (LCD_BASE + 0x44) -++#define LCD_FID0 (LCD_BASE + 0x48) -++#define LCD_CMD0 (LCD_BASE + 0x4c) -++#define LCD_DA1 (LCD_BASE + 0x50) -++#define LCD_SA1 (LCD_BASE + 0x54) -++#define LCD_FID1 (LCD_BASE + 0x58) -++#define LCD_CMD1 (LCD_BASE + 0x5c) -++ -++#define REG_LCD_CFG REG32(LCD_CFG) -++#define REG_LCD_VSYNC REG32(LCD_VSYNC) -++#define REG_LCD_HSYNC REG32(LCD_HSYNC) -++#define REG_LCD_VAT REG32(LCD_VAT) -++#define REG_LCD_DAH REG32(LCD_DAH) -++#define REG_LCD_DAV REG32(LCD_DAV) -++#define REG_LCD_PS REG32(LCD_PS) -++#define REG_LCD_CLS REG32(LCD_CLS) -++#define REG_LCD_SPL REG32(LCD_SPL) -++#define REG_LCD_REV REG32(LCD_REV) -++#define REG_LCD_CTRL REG32(LCD_CTRL) -++#define REG_LCD_STATE REG32(LCD_STATE) -++#define REG_LCD_IID REG32(LCD_IID) -++#define REG_LCD_DA0 REG32(LCD_DA0) -++#define REG_LCD_SA0 REG32(LCD_SA0) -++#define REG_LCD_FID0 REG32(LCD_FID0) -++#define REG_LCD_CMD0 REG32(LCD_CMD0) -++#define REG_LCD_DA1 REG32(LCD_DA1) -++#define REG_LCD_SA1 REG32(LCD_SA1) -++#define REG_LCD_FID1 REG32(LCD_FID1) -++#define REG_LCD_CMD1 REG32(LCD_CMD1) -++ -++#define LCD_CFG_PDW_BIT 4 -++#define LCD_CFG_PDW_MASK (0x03 << LCD_DEV_PDW_BIT) -++ #define LCD_CFG_PDW_1 (0 << LCD_DEV_PDW_BIT) -++ #define LCD_CFG_PDW_2 (1 << LCD_DEV_PDW_BIT) -++ #define LCD_CFG_PDW_4 (2 << LCD_DEV_PDW_BIT) -++ #define LCD_CFG_PDW_8 (3 << LCD_DEV_PDW_BIT) -++#define LCD_CFG_MODE_BIT 0 -++#define LCD_CFG_MODE_MASK (0x0f << LCD_DEV_MODE_BIT) -++ #define LCD_CFG_MODE_GENERIC_TFT (0 << LCD_DEV_MODE_BIT) -++ #define LCD_CFG_MODE_SHARP_HR (1 << LCD_DEV_MODE_BIT) -++ #define LCD_CFG_MODE_CASIO_TFT (2 << LCD_DEV_MODE_BIT) -++ #define LCD_CFG_MODE_SAMSUNG_ALPHA (3 << LCD_DEV_MODE_BIT) -++ #define LCD_CFG_MODE_NONINTER_CCIR656 (4 << LCD_DEV_MODE_BIT) -++ #define LCD_CFG_MODE_INTER_CCIR656 (6 << LCD_DEV_MODE_BIT) -++ #define LCD_CFG_MODE_SINGLE_CSTN (8 << LCD_DEV_MODE_BIT) -++ #define LCD_CFG_MODE_SINGLE_MSTN (9 << LCD_DEV_MODE_BIT) -++ #define LCD_CFG_MODE_DUAL_CSTN (10 << LCD_DEV_MODE_BIT) -++ #define LCD_CFG_MODE_DUAL_MSTN (11 << LCD_DEV_MODE_BIT) -++ -++#define LCD_VSYNC_VPS_BIT 16 -++#define LCD_VSYNC_VPS_MASK (0xffff << LCD_VSYNC_VPS_BIT) -++#define LCD_VSYNC_VPE_BIT 0 -++#define LCD_VSYNC_VPE_MASK (0xffff << LCD_VSYNC_VPS_BIT) -++ -++#define LCD_HSYNC_HPS_BIT 16 -++#define LCD_HSYNC_HPS_MASK (0xffff << LCD_HSYNC_HPS_BIT) -++#define LCD_HSYNC_HPE_BIT 0 -++#define LCD_HSYNC_HPE_MASK (0xffff << LCD_HSYNC_HPE_BIT) -++ -++#define LCD_VAT_HT_BIT 16 -++#define LCD_VAT_HT_MASK (0xffff << LCD_VAT_HT_BIT) -++#define LCD_VAT_VT_BIT 0 -++#define LCD_VAT_VT_MASK (0xffff << LCD_VAT_VT_BIT) -++ -++#define LCD_DAH_HDS_BIT 16 -++#define LCD_DAH_HDS_MASK (0xffff << LCD_DAH_HDS_BIT) -++#define LCD_DAH_HDE_BIT 0 -++#define LCD_DAH_HDE_MASK (0xffff << LCD_DAH_HDE_BIT) -++ -++#define LCD_DAV_VDS_BIT 16 -++#define LCD_DAV_VDS_MASK (0xffff << LCD_DAV_VDS_BIT) -++#define LCD_DAV_VDE_BIT 0 -++#define LCD_DAV_VDE_MASK (0xffff << LCD_DAV_VDE_BIT) -++ -++#define LCD_CTRL_BST_BIT 28 -++#define LCD_CTRL_BST_MASK (0x03 << LCD_CTRL_BST_BIT) -++ #define LCD_CTRL_BST_4 (0 << LCD_CTRL_BST_BIT) -++ #define LCD_CTRL_BST_8 (1 << LCD_CTRL_BST_BIT) -++ #define LCD_CTRL_BST_16 (2 << LCD_CTRL_BST_BIT) -++#define LCD_CTRL_RGB555 (1 << 27) -++#define LCD_CTRL_OFUP (1 << 26) -++#define LCD_CTRL_FRC_BIT 24 -++#define LCD_CTRL_FRC_MASK (0x03 << LCD_CTRL_FRC_BIT) -++ #define LCD_CTRL_FRC_16 (0 << LCD_CTRL_FRC_BIT) -++ #define LCD_CTRL_FRC_4 (1 << LCD_CTRL_FRC_BIT) -++ #define LCD_CTRL_FRC_2 (2 << LCD_CTRL_FRC_BIT) -++#define LCD_CTRL_PDD_BIT 16 -++#define LCD_CTRL_PDD_MASK (0xff << LCD_CTRL_PDD_BIT) -++#define LCD_CTRL_EOFM (1 << 13) -++#define LCD_CTRL_SOFM (1 << 12) -++#define LCD_CTRL_OFUM (1 << 11) -++#define LCD_CTRL_IFUM0 (1 << 10) -++#define LCD_CTRL_IFUM1 (1 << 9) -++#define LCD_CTRL_LDDM (1 << 8) -++#define LCD_CTRL_QDM (1 << 7) -++#define LCD_CTRL_BEDN (1 << 6) -++#define LCD_CTRL_PEDN (1 << 5) -++#define LCD_CTRL_DIS (1 << 4) -++#define LCD_CTRL_ENA (1 << 3) -++#define LCD_CTRL_BPP_BIT 0 -++#define LCD_CTRL_BPP_MASK (0x07 << LCD_CTRL_BPP_BIT) -++ #define LCD_CTRL_BPP_1 (0 << LCD_CTRL_BPP_BIT) -++ #define LCD_CTRL_BPP_2 (1 << LCD_CTRL_BPP_BIT) -++ #define LCD_CTRL_BPP_4 (2 << LCD_CTRL_BPP_BIT) -++ #define LCD_CTRL_BPP_8 (3 << LCD_CTRL_BPP_BIT) -++ #define LCD_CTRL_BPP_16 (4 << LCD_CTRL_BPP_BIT) -++ -++#define LCD_STATE_QD (1 << 7) -++#define LCD_STATE_EOF (1 << 5) -++#define LCD_STATE_SOF (1 << 4) -++#define LCD_STATE_OFU (1 << 3) -++#define LCD_STATE_IFU0 (1 << 2) -++#define LCD_STATE_IFU1 (1 << 1) -++#define LCD_STATE_LDD (1 << 0) -++ -++#define LCD_CMD_SOFINT (1 << 31) -++#define LCD_CMD_EOFINT (1 << 30) -++#define LCD_CMD_PAL (1 << 28) -++#define LCD_CMD_LEN_BIT 0 -++#define LCD_CMD_LEN_MASK (0xffffff << LCD_CMD_LEN_BIT) -++ -++ -++ -++ -++/************************************************************************* -++ * DES -++ *************************************************************************/ -++#define DES_CR1 (DES_BASE + 0x000) -++#define DES_CR2 (DES_BASE + 0x004) -++#define DES_SR (DES_BASE + 0x008) -++#define DES_K1L (DES_BASE + 0x010) -++#define DES_K1R (DES_BASE + 0x014) -++#define DES_K2L (DES_BASE + 0x018) -++#define DES_K2R (DES_BASE + 0x01C) -++#define DES_K3L (DES_BASE + 0x020) -++#define DES_K3R (DES_BASE + 0x024) -++#define DES_IVL (DES_BASE + 0x028) -++#define DES_IVR (DES_BASE + 0x02C) -++#define DES_DIN (DES_BASE + 0x030) -++#define DES_DOUT (DES_BASE + 0x034) -++ -++#define REG_DES_CR1 REG32(DES_CR1) -++#define REG_DES_CR2 REG32(DES_CR2) -++#define REG_DES_SR REG32(DES_SR) -++#define REG_DES_K1L REG32(DES_K1L) -++#define REG_DES_K1R REG32(DES_K1R) -++#define REG_DES_K2L REG32(DES_K2L) -++#define REG_DES_K2R REG32(DES_K2R) -++#define REG_DES_K3L REG32(DES_K3L) -++#define REG_DES_K3R REG32(DES_K3R) -++#define REG_DES_IVL REG32(DES_IVL) -++#define REG_DES_IVR REG32(DES_IVR) -++#define REG_DES_DIN REG32(DES_DIN) -++#define REG_DES_DOUT REG32(DES_DOUT) -++ -++/* DES Control Register 1 (DES_CR1) */ -++ -++#define DES_CR1_EN (1 << 0) -++ -++/* DES Control Register 2 (DES_CR2) */ -++ -++#define DES_CR2_ENDEC (1 << 3) -++#define DES_CR2_MODE (1 << 2) -++#define DES_CR2_ALG (1 << 1) -++#define DES_CR2_DMAE (1 << 0) -++ -++/* DES State Register (DES_SR) */ -++ -++#define DES_SR_IN_FULL (1 << 5) -++#define DES_SR_IN_LHF (1 << 4) -++#define DES_SR_IN_EMPTY (1 << 3) -++#define DES_SR_OUT_FULL (1 << 2) -++#define DES_SR_OUT_GHF (1 << 1) -++#define DES_SR_OUT_EMPTY (1 << 0) -++ -++ -++ -++ -++/************************************************************************* -++ * CPM -++ *************************************************************************/ -++#define CPM_CFCR (CPM_BASE+0x00) -++#define CPM_PLCR1 (CPM_BASE+0x10) -++#define CPM_OCR (CPM_BASE+0x1c) -++#define CPM_CFCR2 (CPM_BASE+0x60) -++#define CPM_LPCR (CPM_BASE+0x04) -++#define CPM_RSTR (CPM_BASE+0x08) -++#define CPM_MSCR (CPM_BASE+0x20) -++#define CPM_SCR (CPM_BASE+0x24) -++#define CPM_WRER (CPM_BASE+0x28) -++#define CPM_WFER (CPM_BASE+0x2c) -++#define CPM_WER (CPM_BASE+0x30) -++#define CPM_WSR (CPM_BASE+0x34) -++#define CPM_GSR0 (CPM_BASE+0x38) -++#define CPM_GSR1 (CPM_BASE+0x3c) -++#define CPM_GSR2 (CPM_BASE+0x40) -++#define CPM_SPR (CPM_BASE+0x44) -++#define CPM_GSR3 (CPM_BASE+0x48) -++ -++#define REG_CPM_CFCR REG32(CPM_CFCR) -++#define REG_CPM_PLCR1 REG32(CPM_PLCR1) -++#define REG_CPM_OCR REG32(CPM_OCR) -++#define REG_CPM_CFCR2 REG32(CPM_CFCR2) -++#define REG_CPM_LPCR REG32(CPM_LPCR) -++#define REG_CPM_RSTR REG32(CPM_RSTR) -++#define REG_CPM_MSCR REG32(CPM_MSCR) -++#define REG_CPM_SCR REG32(CPM_SCR) -++#define REG_CPM_WRER REG32(CPM_WRER) -++#define REG_CPM_WFER REG32(CPM_WFER) -++#define REG_CPM_WER REG32(CPM_WER) -++#define REG_CPM_WSR REG32(CPM_WSR) -++#define REG_CPM_GSR0 REG32(CPM_GSR0) -++#define REG_CPM_GSR1 REG32(CPM_GSR1) -++#define REG_CPM_GSR2 REG32(CPM_GSR2) -++#define REG_CPM_SPR REG32(CPM_SPR) -++#define REG_CPM_GSR3 REG32(CPM_GSR3) -++ -++#define CPM_CFCR_SSI (1 << 31) -++#define CPM_CFCR_LCD (1 << 30) -++#define CPM_CFCR_I2S (1 << 29) -++#define CPM_CFCR_UCS (1 << 28) -++#define CPM_CFCR_UFR_BIT 25 -++#define CPM_CFCR_UFR_MASK (0x07 << CPM_CFCR_UFR_BIT) -++#define CPM_CFCR_MSC (1 << 24) -++#define CPM_CFCR_CKOEN2 (1 << 23) -++#define CPM_CFCR_CKOEN1 (1 << 22) -++#define CPM_CFCR_UPE (1 << 20) -++#define CPM_CFCR_MFR_BIT 16 -++#define CPM_CFCR_MFR_MASK (0x0f << CPM_CFCR_MFR_BIT) -++#define CPM_CFCR_LFR_BIT 12 -++#define CPM_CFCR_LFR_MASK (0x0f << CPM_CFCR_LFR_BIT) -++#define CPM_CFCR_PFR_BIT 8 -++#define CPM_CFCR_PFR_MASK (0x0f << CPM_CFCR_PFR_BIT) -++#define CPM_CFCR_SFR_BIT 4 -++#define CPM_CFCR_SFR_MASK (0x0f << CPM_CFCR_SFR_BIT) -++#define CPM_CFCR_IFR_BIT 0 -++#define CPM_CFCR_IFR_MASK (0x0f << CPM_CFCR_IFR_BIT) -++ -++#define CPM_PLCR1_PLL1FD_BIT 23 -++#define CPM_PLCR1_PLL1FD_MASK (0x1ff << CPM_PLCR1_PLL1FD_BIT) -++#define CPM_PLCR1_PLL1RD_BIT 18 -++#define CPM_PLCR1_PLL1RD_MASK (0x1f << CPM_PLCR1_PLL1RD_BIT) -++#define CPM_PLCR1_PLL1OD_BIT 16 -++#define CPM_PLCR1_PLL1OD_MASK (0x03 << CPM_PLCR1_PLL1OD_BIT) -++#define CPM_PLCR1_PLL1S (1 << 10) -++#define CPM_PLCR1_PLL1BP (1 << 9) -++#define CPM_PLCR1_PLL1EN (1 << 8) -++#define CPM_PLCR1_PLL1ST_BIT 0 -++#define CPM_PLCR1_PLL1ST_MASK (0xff << CPM_PLCR1_PLL1ST_BIT) -++ -++#define CPM_OCR_O1ST_BIT 16 -++#define CPM_OCR_O1ST_MASK (0xff << CPM_OCR_O1ST_BIT) -++#define CPM_OCR_EXT_RTC_CLK (1<<8) -++#define CPM_OCR_SUSPEND_PHY1 (1<<7) -++#define CPM_OCR_SUSPEND_PHY0 (1<<6) -++ -++#define CPM_CFCR2_PXFR_BIT 0 -++#define CPM_CFCR2_PXFR_MASK (0x1ff << CPM_CFCR2_PXFR_BIT) -++ -++#define CPM_LPCR_DUTY_BIT 3 -++#define CPM_LPCR_DUTY_MASK (0x1f << CPM_LPCR_DUTY_BIT) -++#define CPM_LPCR_DOZE (1 << 2) -++#define CPM_LPCR_LPM_BIT 0 -++#define CPM_LPCR_LPM_MASK (0x03 << CPM_LPCR_LPM_BIT) -++ #define CPM_LPCR_LPM_IDLE (0 << CPM_LPCR_LPM_BIT) -++ #define CPM_LPCR_LPM_SLEEP (1 << CPM_LPCR_LPM_BIT) -++ #define CPM_LPCR_LPM_HIBERNATE (2 << CPM_LPCR_LPM_BIT) -++ -++#define CPM_RSTR_SR (1 << 2) -++#define CPM_RSTR_WR (1 << 1) -++#define CPM_RSTR_HR (1 << 0) -++ -++#define CPM_MSCR_MSTP_BIT 0 -++#define CPM_MSCR_MSTP_MASK (0x1ffffff << CPM_MSCR_MSTP_BIT) -++ #define CPM_MSCR_MSTP_UART0 0 -++ #define CPM_MSCR_MSTP_UART1 1 -++ #define CPM_MSCR_MSTP_UART2 2 -++ #define CPM_MSCR_MSTP_OST 3 -++ #define CPM_MSCR_MSTP_DMAC 5 -++ #define CPM_MSCR_MSTP_UHC 6 -++ #define CPM_MSCR_MSTP_LCD 7 -++ #define CPM_MSCR_MSTP_I2C 8 -++ #define CPM_MSCR_MSTP_AICPCLK 9 -++ #define CPM_MSCR_MSTP_PWM0 10 -++ #define CPM_MSCR_MSTP_PWM1 11 -++ #define CPM_MSCR_MSTP_SSI 12 -++ #define CPM_MSCR_MSTP_MSC 13 -++ #define CPM_MSCR_MSTP_SCC 14 -++ #define CPM_MSCR_MSTP_AICBCLK 18 -++ #define CPM_MSCR_MSTP_UART3 20 -++ #define CPM_MSCR_MSTP_ETH 21 -++ #define CPM_MSCR_MSTP_KBC 22 -++ #define CPM_MSCR_MSTP_CIM 23 -++ #define CPM_MSCR_MSTP_UDC 24 -++ #define CPM_MSCR_MSTP_UPRT 25 -++ -++#define CPM_SCR_O1SE (1 << 4) -++#define CPM_SCR_HGP (1 << 3) -++#define CPM_SCR_HZP (1 << 2) -++#define CPM_SCR_HZM (1 << 1) -++ -++#define CPM_WRER_RE_BIT 0 -++#define CPM_WRER_RE_MASK (0xffff << CPM_WRER_RE_BIT) -++ -++#define CPM_WFER_FE_BIT 0 -++#define CPM_WFER_FE_MASK (0xffff << CPM_WFER_FE_BIT) -++ -++#define CPM_WER_WERTC (1 << 31) -++#define CPM_WER_WEETH (1 << 30) -++#define CPM_WER_WE_BIT 0 -++#define CPM_WER_WE_MASK (0xffff << CPM_WER_WE_BIT) -++ -++#define CPM_WSR_WSRTC (1 << 31) -++#define CPM_WSR_WSETH (1 << 30) -++#define CPM_WSR_WS_BIT 0 -++#define CPM_WSR_WS_MASK (0xffff << CPM_WSR_WS_BIT) -++ -++ -++ -++ -++/************************************************************************* -++ * SSI -++ *************************************************************************/ -++#define SSI_DR (SSI_BASE + 0x000) -++#define SSI_CR0 (SSI_BASE + 0x004) -++#define SSI_CR1 (SSI_BASE + 0x008) -++#define SSI_SR (SSI_BASE + 0x00C) -++#define SSI_ITR (SSI_BASE + 0x010) -++#define SSI_ICR (SSI_BASE + 0x014) -++#define SSI_GR (SSI_BASE + 0x018) -++ -++#define REG_SSI_DR REG32(SSI_DR) -++#define REG_SSI_CR0 REG16(SSI_CR0) -++#define REG_SSI_CR1 REG32(SSI_CR1) -++#define REG_SSI_SR REG32(SSI_SR) -++#define REG_SSI_ITR REG16(SSI_ITR) -++#define REG_SSI_ICR REG8(SSI_ICR) -++#define REG_SSI_GR REG16(SSI_GR) -++ -++/* SSI Data Register (SSI_DR) */ -++ -++#define SSI_DR_GPC_BIT 0 -++#define SSI_DR_GPC_MASK (0x1ff << SSI_DR_GPC_BIT) -++ -++/* SSI Control Register 0 (SSI_CR0) */ -++ -++#define SSI_CR0_SSIE (1 << 15) -++#define SSI_CR0_TIE (1 << 14) -++#define SSI_CR0_RIE (1 << 13) -++#define SSI_CR0_TEIE (1 << 12) -++#define SSI_CR0_REIE (1 << 11) -++#define SSI_CR0_LOOP (1 << 10) -++#define SSI_CR0_RFINE (1 << 9) -++#define SSI_CR0_RFINC (1 << 8) -++#define SSI_CR0_FSEL (1 << 6) -++#define SSI_CR0_TFLUSH (1 << 2) -++#define SSI_CR0_RFLUSH (1 << 1) -++#define SSI_CR0_DISREV (1 << 0) -++ -++/* SSI Control Register 1 (SSI_CR1) */ -++ -++#define SSI_CR1_FRMHL_BIT 30 -++#define SSI_CR1_FRMHL_MASK (0x3 << SSI_CR1_FRMHL_BIT) -++ #define SSI_CR1_FRMHL_CELOW_CE2LOW (0 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is low valid */ -++ #define SSI_CR1_FRMHL_CEHIGH_CE2LOW (1 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is low valid */ -++ #define SSI_CR1_FRMHL_CELOW_CE2HIGH (2 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is high valid */ -++ #define SSI_CR1_FRMHL_CEHIGH_CE2HIGH (3 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is high valid */ -++#define SSI_CR1_TFVCK_BIT 28 -++#define SSI_CR1_TFVCK_MASK (0x3 << SSI_CR1_TFVCK_BIT) -++ #define SSI_CR1_TFVCK_0 (0 << SSI_CR1_TFVCK_BIT) -++ #define SSI_CR1_TFVCK_1 (1 << SSI_CR1_TFVCK_BIT) -++ #define SSI_CR1_TFVCK_2 (2 << SSI_CR1_TFVCK_BIT) -++ #define SSI_CR1_TFVCK_3 (3 << SSI_CR1_TFVCK_BIT) -++#define SSI_CR1_TCKFI_BIT 26 -++#define SSI_CR1_TCKFI_MASK (0x3 << SSI_CR1_TCKFI_BIT) -++ #define SSI_CR1_TCKFI_0 (0 << SSI_CR1_TCKFI_BIT) -++ #define SSI_CR1_TCKFI_1 (1 << SSI_CR1_TCKFI_BIT) -++ #define SSI_CR1_TCKFI_2 (2 << SSI_CR1_TCKFI_BIT) -++ #define SSI_CR1_TCKFI_3 (3 << SSI_CR1_TCKFI_BIT) -++#define SSI_CR1_LFST (1 << 25) -++#define SSI_CR1_ITFRM (1 << 24) -++#define SSI_CR1_UNFIN (1 << 23) -++#define SSI_CR1_MULTS (1 << 22) -++#define SSI_CR1_FMAT_BIT 20 -++#define SSI_CR1_FMAT_MASK (0x3 << SSI_CR1_FMAT_BIT) -++ #define SSI_CR1_FMAT_SPI (0 << SSI_CR1_FMAT_BIT) /* Motorola¡¯s SPI format */ -++ #define SSI_CR1_FMAT_SSP (1 << SSI_CR1_FMAT_BIT) /* TI's SSP format */ -++ #define SSI_CR1_FMAT_MW1 (2 << SSI_CR1_FMAT_BIT) /* National Microwire 1 format */ -++ #define SSI_CR1_FMAT_MW2 (3 << SSI_CR1_FMAT_BIT) /* National Microwire 2 format */ -++#define SSI_CR1_MCOM_BIT 12 -++#define SSI_CR1_MCOM_MASK (0xf << SSI_CR1_MCOM_BIT) -++ #define SSI_CR1_MCOM_1BIT (0x0 << SSI_CR1_MCOM_BIT) /* 1-bit command selected */ -++ #define SSI_CR1_MCOM_2BIT (0x1 << SSI_CR1_MCOM_BIT) /* 2-bit command selected */ -++ #define SSI_CR1_MCOM_3BIT (0x2 << SSI_CR1_MCOM_BIT) /* 3-bit command selected */ -++ #define SSI_CR1_MCOM_4BIT (0x3 << SSI_CR1_MCOM_BIT) /* 4-bit command selected */ -++ #define SSI_CR1_MCOM_5BIT (0x4 << SSI_CR1_MCOM_BIT) /* 5-bit command selected */ -++ #define SSI_CR1_MCOM_6BIT (0x5 << SSI_CR1_MCOM_BIT) /* 6-bit command selected */ -++ #define SSI_CR1_MCOM_7BIT (0x6 << SSI_CR1_MCOM_BIT) /* 7-bit command selected */ -++ #define SSI_CR1_MCOM_8BIT (0x7 << SSI_CR1_MCOM_BIT) /* 8-bit command selected */ -++ #define SSI_CR1_MCOM_9BIT (0x8 << SSI_CR1_MCOM_BIT) /* 9-bit command selected */ -++ #define SSI_CR1_MCOM_10BIT (0x9 << SSI_CR1_MCOM_BIT) /* 10-bit command selected */ -++ #define SSI_CR1_MCOM_11BIT (0xA << SSI_CR1_MCOM_BIT) /* 11-bit command selected */ -++ #define SSI_CR1_MCOM_12BIT (0xB << SSI_CR1_MCOM_BIT) /* 12-bit command selected */ -++ #define SSI_CR1_MCOM_13BIT (0xC << SSI_CR1_MCOM_BIT) /* 13-bit command selected */ -++ #define SSI_CR1_MCOM_14BIT (0xD << SSI_CR1_MCOM_BIT) /* 14-bit command selected */ -++ #define SSI_CR1_MCOM_15BIT (0xE << SSI_CR1_MCOM_BIT) /* 15-bit command selected */ -++ #define SSI_CR1_MCOM_16BIT (0xF << SSI_CR1_MCOM_BIT) /* 16-bit command selected */ -++#define SSI_CR1_TTRG_BIT 10 -++#define SSI_CR1_TTRG_MASK (0x3 << SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_1 (0 << SSI_CR1_TTRG_BIT)/* Less than or equal to 1 */ -++ #define SSI_CR1_TTRG_4 (1 << SSI_CR1_TTRG_BIT) /* Less than or equal to 4 */ -++ #define SSI_CR1_TTRG_8 (2 << SSI_CR1_TTRG_BIT) /* Less than or equal to 8 */ -++ #define SSI_CR1_TTRG_14 (3 << SSI_CR1_TTRG_BIT) /* Less than or equal to 14 */ -++#define SSI_CR1_RTRG_BIT 8 -++#define SSI_CR1_RTRG_MASK (0x3 << SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_1 (0 << SSI_CR1_RTRG_BIT) /* More than or equal to 1 */ -++ #define SSI_CR1_RTRG_4 (1 << SSI_CR1_RTRG_BIT) /* More than or equal to 4 */ -++ #define SSI_CR1_RTRG_8 (2 << SSI_CR1_RTRG_BIT) /* More than or equal to 8 */ -++ #define SSI_CR1_RTRG_14 (3 << SSI_CR1_RTRG_BIT) /* More than or equal to 14 */ -++#define SSI_CR1_FLEN_BIT 4 -++#define SSI_CR1_FLEN_MASK (0xf << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_2BIT (0x0 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_3BIT (0x1 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_4BIT (0x2 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_5BIT (0x3 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_6BIT (0x4 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_7BIT (0x5 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_8BIT (0x6 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_9BIT (0x7 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_10BIT (0x8 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_11BIT (0x9 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_12BIT (0xA << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_13BIT (0xB << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_14BIT (0xC << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_15BIT (0xD << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_16BIT (0xE << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_17BIT (0xF << SSI_CR1_FLEN_BIT) -++#define SSI_CR1_PHA (1 << 1) -++#define SSI_CR1_POL (1 << 0) -++ -++/* SSI Status Register (SSI_SR) */ -++ -++#define SSI_SR_TFIFONUM_BIT 13 -++#define SSI_SR_TFIFONUM_MASK (0x1f << SSI_SR_TFIFONUM_BIT) -++#define SSI_SR_RFIFONUM_BIT 8 -++#define SSI_SR_RFIFONUM_MASK (0x1f << SSI_SR_RFIFONUM_BIT) -++#define SSI_SR_END (1 << 7) -++#define SSI_SR_BUSY (1 << 6) -++#define SSI_SR_TFF (1 << 5) -++#define SSI_SR_RFE (1 << 4) -++#define SSI_SR_TFHE (1 << 3) -++#define SSI_SR_RFHF (1 << 2) -++#define SSI_SR_UNDR (1 << 1) -++#define SSI_SR_OVER (1 << 0) -++ -++/* SSI Interval Time Control Register (SSI_ITR) */ -++ -++#define SSI_ITR_CNTCLK (1 << 15) -++#define SSI_ITR_IVLTM_BIT 0 -++#define SSI_ITR_IVLTM_MASK (0x7fff << SSI_ITR_IVLTM_BIT) -++ -++#endif /* __ASM_JZ4730_REGS_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4730/serial.h linux-2.6.24.7/include/asm-mips/mach-jz4730/serial.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4730/serial.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4730/serial.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,33 @@ -++/* -++ * linux/include/asm-mips/mach-jz4730/serial.h -++ * -++ * JZ4730 serial port definition. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4730_SERIAL_H__ -++#define __ASM_JZ4730_SERIAL_H__ -++ -++#define JZ_BASE_BAUD (JZ_EXTAL/16) -++#define JZ_SERIAL_PORT_DEFNS \ -++ { .baud_base = JZ_BASE_BAUD, .irq = IRQ_UART0, \ -++ .flags = STD_COM_FLAGS, .iomem_base = (u8 *)UART0_BASE, \ -++ .iomem_reg_shift = 2, .io_type = SERIAL_IO_MEM }, \ -++ { .baud_base = JZ_BASE_BAUD, .irq = IRQ_UART1, \ -++ .flags = STD_COM_FLAGS, .iomem_base = (u8 *)UART1_BASE, \ -++ .iomem_reg_shift = 2, .io_type = SERIAL_IO_MEM }, \ -++ { .baud_base = JZ_BASE_BAUD, .irq = IRQ_UART2, \ -++ .flags = STD_COM_FLAGS, .iomem_base = (u8 *)UART2_BASE, \ -++ .iomem_reg_shift = 2, .io_type = SERIAL_IO_MEM }, \ -++ { .baud_base = JZ_BASE_BAUD, .irq = IRQ_UART3, \ -++ .flags = STD_COM_FLAGS, .iomem_base = (u8 *)UART3_BASE, \ -++ .iomem_reg_shift = 2, .io_type = SERIAL_IO_MEM }, -++ -++#endif /* __ASM_JZ4730_SERIAL_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4730/war.h linux-2.6.24.7/include/asm-mips/mach-jz4730/war.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4730/war.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4730/war.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,25 @@ -++/* -++ * This file is subject to the terms and conditions of the GNU General Public -++ * License. See the file "COPYING" in the main directory of this archive -++ * for more details. -++ * -++ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle -++ */ -++#ifndef __ASM_MIPS_MACH_JZ4740_WAR_H -++#define __ASM_MIPS_MACH_JZ4740_WAR_H -++ -++#define R4600_V1_INDEX_ICACHEOP_WAR 0 -++#define R4600_V1_HIT_CACHEOP_WAR 0 -++#define R4600_V2_HIT_CACHEOP_WAR 0 -++#define R5432_CP0_INTERRUPT_WAR 0 -++#define BCM1250_M3_WAR 0 -++#define SIBYTE_1956_WAR 0 -++#define MIPS4K_ICACHE_REFILL_WAR 0 -++#define MIPS_CACHE_SYNC_WAR 0 -++#define TX49XX_ICACHE_INDEX_INV_WAR 0 -++#define RM9000_CDEX_SMP_WAR 0 -++#define ICACHE_REFILLS_WORKAROUND_WAR 0 -++#define R10000_LLSC_WAR 0 -++#define MIPS34K_MISSED_ITLB_WAR 0 -++ -++#endif /* __ASM_MIPS_MACH_JZ4740_WAR_H */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4740/board-dipper.h linux-2.6.24.7/include/asm-mips/mach-jz4740/board-dipper.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4740/board-dipper.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4740/board-dipper.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,69 @@ -++/* -++ * linux/include/asm-mips/mach-jz4740/board-dipper.h -++ * -++ * JZ4725-based (16bit) Dipper board ver 1.x definition. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4725_DIPPER_H__ -++#define __ASM_JZ4725_DIPPER_H__ -++ -++/*====================================================================== -++ * Frequencies of on-board oscillators -++ */ -++#define JZ_EXTAL 12000000 /* Main extal freq: 12 MHz */ -++#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -++ -++/*====================================================================== -++ * GPIO JZ4725 -++ */ -++#define GPIO_SD_VCC_EN_N 85 /* GPC21 */ -++#define GPIO_SD_CD_N 91 /* GPC27 */ -++#define GPIO_SD_WP 112 /* GPD16 */ -++#define GPIO_USB_DETE 124 /* GPD28 */ -++#define GPIO_DC_DETE_N 103 /* GPD7 */ -++#define GPIO_CHARG_STAT_N 86 /* GPC22 */ -++#define GPIO_DISP_OFF_N 118 /* GPD22 */ -++ -++#define GPIO_UDC_HOTPLUG GPIO_USB_DETE -++ -++/*====================================================================== -++ * MMC/SD -++ */ -++ -++#define MSC_WP_PIN GPIO_SD_WP -++#define MSC_HOTPLUG_PIN GPIO_SD_CD_N -++#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) -++ -++#define __msc_init_io() \ -++do { \ -++ __gpio_as_output(GPIO_SD_VCC_EN_N); \ -++ __gpio_as_input(GPIO_SD_CD_N); \ -++} while (0) -++ -++#define __msc_enable_power() \ -++do { \ -++ __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ -++} while (0) -++ -++#define __msc_disable_power() \ -++do { \ -++ __gpio_set_pin(GPIO_SD_VCC_EN_N); \ -++} while (0) -++ -++#define __msc_card_detected(s) \ -++({ \ -++ int detected = 1; \ -++ if (__gpio_get_pin(GPIO_SD_CD_N)) \ -++ detected = 0; \ -++ detected; \ -++}) -++ -++#endif /* __ASM_JZ4740_DIPPER_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4740/board-leo.h linux-2.6.24.7/include/asm-mips/mach-jz4740/board-leo.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4740/board-leo.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4740/board-leo.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,56 @@ -++#ifndef __ASM_JZ4740_LEO_H__ -++#define __ASM_JZ4740_LEO_H__ -++ -++/* -++ * Define your board specific codes here !!! -++ */ -++ -++/*====================================================================== -++ * Frequencies of on-board oscillators -++ */ -++#define JZ_EXTAL 12000000 /* Main extal freq: 12 MHz */ -++#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -++ -++ -++/*====================================================================== -++ * GPIO -++ */ -++#define GPIO_DISP_OFF_N 100 -++#define GPIO_SD_VCC_EN_N 119 -++#define GPIO_SD_CD_N 120 -++#define GPIO_SD_WP 111 -++ -++/*====================================================================== -++ * MMC/SD -++ */ -++ -++#define MSC_WP_PIN GPIO_SD_WP -++#define MSC_HOTPLUG_PIN GPIO_SD_CD_N -++#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) -++ -++#define __msc_init_io() \ -++do { \ -++ __gpio_as_output(GPIO_SD_VCC_EN_N); \ -++ __gpio_as_input(GPIO_SD_CD_N); \ -++} while (0) -++ -++#define __msc_enable_power() \ -++do { \ -++ __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ -++} while (0) -++ -++#define __msc_disable_power() \ -++do { \ -++ __gpio_set_pin(GPIO_SD_VCC_EN_N); \ -++} while (0) -++ -++#define __msc_card_detected(s) \ -++({ \ -++ int detected = 1; \ -++ __gpio_as_input(GPIO_SD_CD_N); \ -++ if (__gpio_get_pin(GPIO_SD_CD_N)) \ -++ detected = 0; \ -++ detected; \ -++}) -++ -++#endif /* __ASM_JZ4740_BOARD_LEO_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4740/board-lyra.h linux-2.6.24.7/include/asm-mips/mach-jz4740/board-lyra.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4740/board-lyra.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4740/board-lyra.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,70 @@ -++/* -++ * linux/include/asm-mips/mach-jz4740/board-lyra.h -++ * -++ * JZ4740-based LYRA board ver 2.x definition. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4740_LYRA_H__ -++#define __ASM_JZ4740_LYRA_H__ -++ -++/*====================================================================== -++ * Frequencies of on-board oscillators -++ */ -++#define JZ_EXTAL 12000000 /* Main extal freq: 12 MHz */ -++#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -++ -++ -++/*====================================================================== -++ * GPIO -++ */ -++#define GPIO_SD_VCC_EN_N 113 /* GPD17 */ -++#define GPIO_SD_CD_N 110 /* GPD14 */ -++#define GPIO_SD_WP 112 /* GPD16 */ -++#define GPIO_USB_DETE 102 /* GPD6 */ -++#define GPIO_DC_DETE_N 103 /* GPD7 */ -++#define GPIO_CHARG_STAT_N 111 /* GPD15 */ -++#define GPIO_DISP_OFF_N 118 /* GPD22 */ -++#define GPIO_LED_EN 124 /* GPD28 */ -++ -++#define GPIO_UDC_HOTPLUG GPIO_USB_DETE -++/*====================================================================== -++ * MMC/SD -++ */ -++ -++#define MSC_WP_PIN GPIO_SD_WP -++#define MSC_HOTPLUG_PIN GPIO_SD_CD_N -++#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) -++ -++#define __msc_init_io() \ -++do { \ -++ __gpio_as_output(GPIO_SD_VCC_EN_N); \ -++ __gpio_as_input(GPIO_SD_CD_N); \ -++} while (0) -++ -++#define __msc_enable_power() \ -++do { \ -++ __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ -++} while (0) -++ -++#define __msc_disable_power() \ -++do { \ -++ __gpio_set_pin(GPIO_SD_VCC_EN_N); \ -++} while (0) -++ -++#define __msc_card_detected(s) \ -++({ \ -++ int detected = 1; \ -++ if (!(__gpio_get_pin(GPIO_SD_CD_N))) \ -++ detected = 0; \ -++ detected; \ -++}) -++ -++#endif /* __ASM_JZ4740_LYRA_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4740/board-pavo.h linux-2.6.24.7/include/asm-mips/mach-jz4740/board-pavo.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4740/board-pavo.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4740/board-pavo.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,70 @@ -++/* -++ * linux/include/asm-mips/mach-jz4740/board-pavo.h -++ * -++ * JZ4730-based PAVO board ver 2.x definition. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4740_PAVO_H__ -++#define __ASM_JZ4740_PAVO_H__ -++ -++/*====================================================================== -++ * Frequencies of on-board oscillators -++ */ -++#define JZ_EXTAL 12000000 /* Main extal freq: 12 MHz */ -++#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -++ -++ -++/*====================================================================== -++ * GPIO -++ */ -++#define GPIO_SD_VCC_EN_N 113 /* GPD17 */ -++#define GPIO_SD_CD_N 110 /* GPD14 */ -++#define GPIO_SD_WP 112 /* GPD16 */ -++#define GPIO_USB_DETE 102 /* GPD6 */ -++#define GPIO_DC_DETE_N 103 /* GPD7 */ -++#define GPIO_CHARG_STAT_N 111 /* GPD15 */ -++#define GPIO_DISP_OFF_N 118 /* GPD22 */ -++#define GPIO_LED_EN 124 /* GPD28 */ -++ -++#define GPIO_UDC_HOTPLUG GPIO_USB_DETE -++/*====================================================================== -++ * MMC/SD -++ */ -++ -++#define MSC_WP_PIN GPIO_SD_WP -++#define MSC_HOTPLUG_PIN GPIO_SD_CD_N -++#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) -++ -++#define __msc_init_io() \ -++do { \ -++ __gpio_as_output(GPIO_SD_VCC_EN_N); \ -++ __gpio_as_input(GPIO_SD_CD_N); \ -++} while (0) -++ -++#define __msc_enable_power() \ -++do { \ -++ __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ -++} while (0) -++ -++#define __msc_disable_power() \ -++do { \ -++ __gpio_set_pin(GPIO_SD_VCC_EN_N); \ -++} while (0) -++ -++#define __msc_card_detected(s) \ -++({ \ -++ int detected = 1; \ -++ if (__gpio_get_pin(GPIO_SD_CD_N)) \ -++ detected = 0; \ -++ detected; \ -++}) -++ -++#endif /* __ASM_JZ4740_PAVO_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4740/board-virgo.h linux-2.6.24.7/include/asm-mips/mach-jz4740/board-virgo.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4740/board-virgo.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4740/board-virgo.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,67 @@ -++/* -++ * linux/include/asm-mips/mach-jz4740/board-virgo.h -++ * -++ * JZ4720-based VIRGO board ver 1.x definition. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4720_VIRGO_H__ -++#define __ASM_JZ4720_VIRGO_H__ -++ -++/*====================================================================== -++ * Frequencies of on-board oscillators -++ */ -++#define JZ_EXTAL 12000000 /* Main extal freq: 12 MHz */ -++#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -++ -++/*====================================================================== -++ * GPIO VIRGO(JZ4720) -++ */ -++#define GPIO_SD_VCC_EN_N 115 /* GPD19 */ -++#define GPIO_SD_CD_N 116 /* GPD20 */ -++#define GPIO_USB_DETE 114 /* GPD18 */ -++#define GPIO_DC_DETE_N 120 /* GPD24 */ -++#define GPIO_DISP_OFF_N 118 /* GPD22 */ -++#define GPIO_LED_EN 117 /* GPD21 */ -++ -++#define GPIO_UDC_HOTPLUG GPIO_USB_DETE -++ -++/*====================================================================== -++ * MMC/SD -++ */ -++ -++#define MSC_HOTPLUG_PIN GPIO_SD_CD_N -++#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) -++ -++#define __msc_init_io() \ -++do { \ -++ __gpio_as_output(GPIO_SD_VCC_EN_N); \ -++ __gpio_as_input(GPIO_SD_CD_N); \ -++} while (0) -++ -++#define __msc_enable_power() \ -++do { \ -++ __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ -++} while (0) -++ -++#define __msc_disable_power() \ -++do { \ -++ __gpio_set_pin(GPIO_SD_VCC_EN_N); \ -++} while (0) -++ -++#define __msc_card_detected(s) \ -++({ \ -++ int detected = 1; \ -++ if (__gpio_get_pin(GPIO_SD_CD_N)) \ -++ detected = 0; \ -++ detected; \ -++}) -++ -++#endif /* __ASM_JZ4720_VIRGO_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4740/clock.h linux-2.6.24.7/include/asm-mips/mach-jz4740/clock.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4740/clock.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4740/clock.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,173 @@ -++/* -++ * linux/include/asm-mips/mach-jz4740/clock.h -++ * -++ * JZ4740 clocks definition. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4740_CLOCK_H__ -++#define __ASM_JZ4740_CLOCK_H__ -++ -++#ifndef JZ_EXTAL -++//#define JZ_EXTAL 3686400 /* 3.6864 MHz */ -++#define JZ_EXTAL 12000000 /* 3.6864 MHz */ -++#endif -++#ifndef JZ_EXTAL2 -++#define JZ_EXTAL2 32768 /* 32.768 KHz */ -++#endif -++ -++/* -++ * JZ4740 clocks structure -++ */ -++typedef struct { -++ unsigned int cclk; /* CPU clock */ -++ unsigned int hclk; /* System bus clock */ -++ unsigned int pclk; /* Peripheral bus clock */ -++ unsigned int mclk; /* Flash/SRAM/SDRAM clock */ -++ unsigned int lcdclk; /* LCDC module clock */ -++ unsigned int pixclk; /* LCD pixel clock */ -++ unsigned int i2sclk; /* AIC module clock */ -++ unsigned int usbclk; /* USB module clock */ -++ unsigned int mscclk; /* MSC module clock */ -++ unsigned int extalclk; /* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */ -++ unsigned int rtcclk; /* RTC clock for CPM,INTC,RTC,TCU,WDT */ -++} jz_clocks_t; -++ -++extern jz_clocks_t jz_clocks; -++ -++ -++/* PLL output frequency */ -++static __inline__ unsigned int __cpm_get_pllout(void) -++{ -++ unsigned long m, n, no, pllout; -++ unsigned long cppcr = REG_CPM_CPPCR; -++ unsigned long od[4] = {1, 2, 2, 4}; -++ if ((cppcr & CPM_CPPCR_PLLEN) && !(cppcr & CPM_CPPCR_PLLBP)) { -++ m = __cpm_get_pllm() + 2; -++ n = __cpm_get_plln() + 2; -++ no = od[__cpm_get_pllod()]; -++ pllout = ((JZ_EXTAL) / (n * no)) * m; -++ } else -++ pllout = JZ_EXTAL; -++ return pllout; -++} -++ -++/* PLL output frequency for MSC/I2S/LCD/USB */ -++static __inline__ unsigned int __cpm_get_pllout2(void) -++{ -++ if (REG_CPM_CPCCR & CPM_CPCCR_PCS) -++ return __cpm_get_pllout(); -++ else -++ return __cpm_get_pllout()/2; -++} -++ -++/* CPU core clock */ -++static __inline__ unsigned int __cpm_get_cclk(void) -++{ -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ -++ return __cpm_get_pllout() / div[__cpm_get_cdiv()]; -++} -++ -++/* AHB system bus clock */ -++static __inline__ unsigned int __cpm_get_hclk(void) -++{ -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ -++ return __cpm_get_pllout() / div[__cpm_get_hdiv()]; -++} -++ -++/* Memory bus clock */ -++static __inline__ unsigned int __cpm_get_mclk(void) -++{ -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ -++ return __cpm_get_pllout() / div[__cpm_get_mdiv()]; -++} -++ -++/* APB peripheral bus clock */ -++static __inline__ unsigned int __cpm_get_pclk(void) -++{ -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ -++ return __cpm_get_pllout() / div[__cpm_get_pdiv()]; -++} -++ -++/* LCDC module clock */ -++static __inline__ unsigned int __cpm_get_lcdclk(void) -++{ -++ return __cpm_get_pllout2() / (__cpm_get_ldiv() + 1); -++} -++ -++/* LCD pixel clock */ -++static __inline__ unsigned int __cpm_get_pixclk(void) -++{ -++ return __cpm_get_pllout2() / (__cpm_get_pixdiv() + 1); -++} -++ -++/* I2S clock */ -++static __inline__ unsigned int __cpm_get_i2sclk(void) -++{ -++ if (REG_CPM_CPCCR & CPM_CPCCR_I2CS) { -++ return __cpm_get_pllout2() / (__cpm_get_i2sdiv() + 1); -++ } -++ else { -++ return JZ_EXTAL; -++ } -++} -++ -++/* USB clock */ -++static __inline__ unsigned int __cpm_get_usbclk(void) -++{ -++ if (REG_CPM_CPCCR & CPM_CPCCR_UCS) { -++ return __cpm_get_pllout2() / (__cpm_get_udiv() + 1); -++ } -++ else { -++ return JZ_EXTAL; -++ } -++} -++ -++/* MSC clock */ -++static __inline__ unsigned int __cpm_get_mscclk(void) -++{ -++ return __cpm_get_pllout2() / (__cpm_get_mscdiv() + 1); -++} -++ -++/* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */ -++static __inline__ unsigned int __cpm_get_extalclk(void) -++{ -++ return JZ_EXTAL; -++} -++ -++/* RTC clock for CPM,INTC,RTC,TCU,WDT */ -++static __inline__ unsigned int __cpm_get_rtcclk(void) -++{ -++ return JZ_EXTAL2; -++} -++ -++/* -++ * Output 24MHz for SD and 16MHz for MMC. -++ */ -++static inline void __cpm_select_msc_clk(int sd) -++{ -++ unsigned int pllout2 = __cpm_get_pllout2(); -++ unsigned int div = 0; -++ -++ if (sd) { -++ div = pllout2 / 24000000; -++ } -++ else { -++ div = pllout2 / 16000000; -++ } -++ -++ REG_CPM_MSCCDR = div - 1; -++} -++ -++#endif /* __ASM_JZ4740_CLOCK_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4740/dma.h linux-2.6.24.7/include/asm-mips/mach-jz4740/dma.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4740/dma.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4740/dma.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,265 @@ -++/* -++ * linux/include/asm-mips/mach-jz4740/dma.h -++ * -++ * JZ4740 DMA definition. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4740_DMA_H__ -++#define __ASM_JZ4740_DMA_H__ -++ -++#include -++#include /* need byte IO */ -++#include /* And spinlocks */ -++#include -++#include -++ -++/* -++ * Descriptor structure for JZ4740 DMA engine -++ * Note: this structure must always be aligned to a 16-bytes boundary. -++ */ -++ -++typedef struct { -++ volatile u32 dcmd; /* DCMD value for the current transfer */ -++ volatile u32 dsadr; /* DSAR value for the current transfer */ -++ volatile u32 dtadr; /* DTAR value for the current transfer */ -++ volatile u32 ddadr; /* Points to the next descriptor + transfer count */ -++} jz_dma_desc; -++ -++ -++/* DMA Device ID's follow */ -++enum { -++ DMA_ID_UART0_TX = 0, -++ DMA_ID_UART0_RX, -++ DMA_ID_SSI_TX, -++ DMA_ID_SSI_RX, -++ DMA_ID_AIC_TX, -++ DMA_ID_AIC_RX, -++ DMA_ID_MSC_TX, -++ DMA_ID_MSC_RX, -++ DMA_ID_TCU_OVERFLOW, -++ DMA_ID_AUTO, -++ DMA_ID_RAW_SET, -++ DMA_ID_MAX -++}; -++ -++/* DMA modes, simulated by sw */ -++#define DMA_MODE_READ 0x0 /* I/O to memory, no autoinit, increment, single mode */ -++#define DMA_MODE_WRITE 0x1 /* memory to I/O, no autoinit, increment, single mode */ -++#define DMA_AUTOINIT 0x2 -++#define DMA_MODE_MASK 0x3 -++ -++struct jz_dma_chan { -++ int dev_id; /* DMA ID: this channel is allocated if >=0, free otherwise */ -++ unsigned int io; /* DMA channel number */ -++ const char *dev_str; /* string describes the DMA channel */ -++ int irq; /* DMA irq number */ -++ void *irq_dev; /* DMA private device structure */ -++ unsigned int fifo_addr; /* physical fifo address of the requested device */ -++ unsigned int cntl; /* DMA controll */ -++ unsigned int mode; /* DMA configuration */ -++ unsigned int source; /* DMA request source */ -++}; -++ -++extern struct jz_dma_chan jz_dma_table[]; -++ -++ -++#define DMA_8BIT_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_8BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_8BIT_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -++ DMAC_DCMD_DS_8BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_16BIT_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_16BIT_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_32BIT_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_32BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_32BIT_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_32BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_16BYTE_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_16BYTE_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_32BYTE_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_32BYTE_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -++ DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_32_16BYTE_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_32_16BYTE_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_16BIT_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_16BIT_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_16BYTE_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_16BYTE_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++extern int jz_request_dma(int dev_id, -++ const char *dev_str, -++ irqreturn_t (*irqhandler)(int, void *), -++ unsigned long irqflags, -++ void *irq_dev_id); -++extern void jz_free_dma(unsigned int dmanr); -++ -++extern int jz_dma_read_proc(char *buf, char **start, off_t fpos, -++ int length, int *eof, void *data); -++extern void dump_jz_dma_channel(unsigned int dmanr); -++ -++extern void enable_dma(unsigned int dmanr); -++extern void disable_dma(unsigned int dmanr); -++extern void set_dma_addr(unsigned int dmanr, unsigned int phyaddr); -++extern void set_dma_count(unsigned int dmanr, unsigned int bytecnt); -++extern void set_dma_mode(unsigned int dmanr, unsigned int mode); -++extern void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); -++extern void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); -++extern unsigned int get_dma_residue(unsigned int dmanr); -++ -++extern spinlock_t dma_spin_lock; -++ -++static __inline__ unsigned long claim_dma_lock(void) -++{ -++ unsigned long flags; -++ spin_lock_irqsave(&dma_spin_lock, flags); -++ return flags; -++} -++ -++static __inline__ void release_dma_lock(unsigned long flags) -++{ -++ spin_unlock_irqrestore(&dma_spin_lock, flags); -++} -++ -++/* Clear the 'DMA Pointer Flip Flop'. -++ * Write 0 for LSB/MSB, 1 for MSB/LSB access. -++ */ -++#define clear_dma_ff(channel) -++ -++static __inline__ struct jz_dma_chan *get_dma_chan(unsigned int dmanr) -++{ -++ if (dmanr > MAX_DMA_NUM -++ || jz_dma_table[dmanr].dev_id < 0) -++ return NULL; -++ return &jz_dma_table[dmanr]; -++} -++ -++static __inline__ int dma_halted(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return 1; -++ return __dmac_channel_transmit_halt_detected(dmanr) ? 1 : 0; -++} -++ -++static __inline__ unsigned int get_dma_mode(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return 0; -++ return chan->mode; -++} -++ -++static __inline__ void clear_dma_done(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -++} -++ -++static __inline__ void clear_dma_halt(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT); -++ REG_DMAC_DMACR &= ~(DMAC_DMACR_HLT); -++} -++ -++static __inline__ void clear_dma_flag(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -++ REG_DMAC_DMACR &= ~(DMAC_DMACR_HLT | DMAC_DMACR_AR); -++} -++ -++static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) -++{ -++} -++ -++static __inline__ unsigned int get_dma_done_status(unsigned int dmanr) -++{ -++ unsigned long dccsr; -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return 0; -++ dccsr = REG_DMAC_DCCSR(chan->io); -++ return dccsr & (DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -++} -++ -++static __inline__ int get_dma_done_irq(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return -1; -++ return chan->irq; -++} -++ -++#endif /* __ASM_JZ4740_DMA_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4740/jz4740.h linux-2.6.24.7/include/asm-mips/mach-jz4740/jz4740.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4740/jz4740.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4740/jz4740.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,56 @@ -++/* -++ * linux/include/asm-mips/mach-jz4740/jz4740.h -++ * -++ * JZ4740 common definition. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4740_H__ -++#define __ASM_JZ4740_H__ -++ -++#include -++#include -++#include -++#include -++ -++/*------------------------------------------------------------------ -++ * Platform definitions -++ */ -++#ifdef CONFIG_JZ4740_PAVO -++#include -++#endif -++ -++#ifdef CONFIG_JZ4740_LEO -++#include -++#endif -++ -++#ifdef CONFIG_JZ4740_LYRA -++#include -++#endif -++ -++#ifdef CONFIG_JZ4725_DIPPER -++#include -++#endif -++ -++#ifdef CONFIG_JZ4720_VIRGO -++#include -++#endif -++ -++/* Add other platform definition here ... */ -++ -++ -++/*------------------------------------------------------------------ -++ * Follows are related to platform definitions -++ */ -++ -++#include -++#include -++ -++#endif /* __ASM_JZ4740_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4740/misc.h linux-2.6.24.7/include/asm-mips/mach-jz4740/misc.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4740/misc.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4740/misc.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,43 @@ -++/* -++ * linux/include/asm-mips/mach-jz4740/misc.h -++ * -++ * Ingenic's JZ4740 common include. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4740_MISC_H__ -++#define __ASM_JZ4740_MISC_H__ -++ -++/*========================================================== -++ * I2C -++ *===========================================================*/ -++ -++#define I2C_EEPROM_DEV 0xA /* b'1010 */ -++#define I2C_RTC_DEV 0xD /* b'1101 */ -++#define DIMM0_SPD_ADDR 0 -++#define DIMM1_SPD_ADDR 1 -++#define DIMM2_SPD_ADDR 2 -++#define DIMM3_SPD_ADDR 3 -++#define JZ_HCI_ADDR 7 -++ -++#define DIMM_SPD_LEN 128 -++#define JZ_HCI_LEN 512 /* 4K bits E2PROM */ -++#define I2C_RTC_LEN 16 -++#define HCI_MAC_OFFSET 64 -++ -++extern void i2c_open(void); -++extern void i2c_close(void); -++extern void i2c_setclk(unsigned int i2cclk); -++extern int i2c_read(unsigned char device, unsigned char *buf, -++ unsigned char address, int count); -++extern int i2c_write(unsigned char device, unsigned char *buf, -++ unsigned char address, int count); -++ -++#endif /* __ASM_JZ4740_MISC_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4740/ops.h linux-2.6.24.7/include/asm-mips/mach-jz4740/ops.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4740/ops.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4740/ops.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,2224 @@ -++/* -++ * linux/include/asm-mips/mach-jz4740/ops.h -++ * -++ * Ingenic's JZ4740 common include. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++ -++#ifndef __JZ4740_OPS_H__ -++#define __JZ4740_OPS_H__ -++ -++/* -++ * Definition of Module Operations -++ */ -++ -++/*************************************************************************** -++ * GPIO -++ ***************************************************************************/ -++ -++//------------------------------------------------------ -++// GPIO Pins Description -++// -++// PORT 0: -++// -++// PIN/BIT N FUNC0 FUNC1 -++// 0 D0 - -++// 1 D1 - -++// 2 D2 - -++// 3 D3 - -++// 4 D4 - -++// 5 D5 - -++// 6 D6 - -++// 7 D7 - -++// 8 D8 - -++// 9 D9 - -++// 10 D10 - -++// 11 D11 - -++// 12 D12 - -++// 13 D13 - -++// 14 D14 - -++// 15 D15 - -++// 16 D16 - -++// 17 D17 - -++// 18 D18 - -++// 19 D19 - -++// 20 D20 - -++// 21 D21 - -++// 22 D22 - -++// 23 D23 - -++// 24 D24 - -++// 25 D25 - -++// 26 D26 - -++// 27 D27 - -++// 28 D28 - -++// 29 D29 - -++// 30 D30 - -++// 31 D31 - -++// -++//------------------------------------------------------ -++// PORT 1: -++// -++// PIN/BIT N FUNC0 FUNC1 -++// 0 A0 - -++// 1 A1 - -++// 2 A2 - -++// 3 A3 - -++// 4 A4 - -++// 5 A5 - -++// 6 A6 - -++// 7 A7 - -++// 8 A8 - -++// 9 A9 - -++// 10 A10 - -++// 11 A11 - -++// 12 A12 - -++// 13 A13 - -++// 14 A14 - -++// 15 A15/CL - -++// 16 A16/AL - -++// 17 LCD_CLS A21 -++// 18 LCD_SPL A22 -++// 19 DCS# - -++// 20 RAS# - -++// 21 CAS# - -++// 22 RDWE#/BUFD# - -++// 23 CKE - -++// 24 CKO - -++// 25 CS1# - -++// 26 CS2# - -++// 27 CS3# - -++// 28 CS4# - -++// 29 RD# - -++// 30 WR# - -++// 31 WE0# - -++// -++// Note: PIN15&16 are CL&AL when connecting to NAND flash. -++//------------------------------------------------------ -++// PORT 2: -++// -++// PIN/BIT N FUNC0 FUNC1 -++// 0 LCD_D0 - -++// 1 LCD_D1 - -++// 2 LCD_D2 - -++// 3 LCD_D3 - -++// 4 LCD_D4 - -++// 5 LCD_D5 - -++// 6 LCD_D6 - -++// 7 LCD_D7 - -++// 8 LCD_D8 - -++// 9 LCD_D9 - -++// 10 LCD_D10 - -++// 11 LCD_D11 - -++// 12 LCD_D12 - -++// 13 LCD_D13 - -++// 14 LCD_D14 - -++// 15 LCD_D15 - -++// 16 LCD_D16 - -++// 17 LCD_D17 - -++// 18 LCD_PCLK - -++// 19 LCD_HSYNC - -++// 20 LCD_VSYNC - -++// 21 LCD_DE - -++// 22 LCD_PS A19 -++// 23 LCD_REV A20 -++// 24 WE1# - -++// 25 WE2# - -++// 26 WE3# - -++// 27 WAIT# - -++// 28 FRE# - -++// 29 FWE# - -++// 30(NOTE:FRB#) - - -++// 31 - - -++// -++// NOTE(1): PIN30 is used for FRB# when connecting to NAND flash. -++//------------------------------------------------------ -++// PORT 3: -++// -++// PIN/BIT N FUNC0 FUNC1 -++// 0 CIM_D0 - -++// 1 CIM_D1 - -++// 2 CIM_D2 - -++// 3 CIM_D3 - -++// 4 CIM_D4 - -++// 5 CIM_D5 - -++// 6 CIM_D6 - -++// 7 CIM_D7 - -++// 8 MSC_CMD - -++// 9 MSC_CLK - -++// 10 MSC_D0 - -++// 11 MSC_D1 - -++// 12 MSC_D2 - -++// 13 MSC_D3 - -++// 14 CIM_MCLK - -++// 15 CIM_PCLK - -++// 16 CIM_VSYNC - -++// 17 CIM_HSYNC - -++// 18 SSI_CLK SCLK_RSTN -++// 19 SSI_CE0# BIT_CLK(AIC) -++// 20 SSI_DT SDATA_OUT(AIC) -++// 21 SSI_DR SDATA_IN(AIC) -++// 22 SSI_CE1#&GPC SYNC(AIC) -++// 23 PWM0 I2C_SDA -++// 24 PWM1 I2C_SCK -++// 25 PWM2 UART0_TxD -++// 26 PWM3 UART0_RxD -++// 27 PWM4 A17 -++// 28 PWM5 A18 -++// 29 - - -++// 30 PWM6 UART0_CTS/UART1_RxD -++// 31 PWM7 UART0_RTS/UART1_TxD -++// -++////////////////////////////////////////////////////////// -++ -++/* -++ * p is the port number (0,1,2,3) -++ * o is the pin offset (0-31) inside the port -++ * n is the absolute number of a pin (0-127), regardless of the port -++ */ -++ -++//------------------------------------------- -++// Function Pins Mode -++ -++#define __gpio_as_func0(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXFUNS(p) = (1 << o); \ -++ REG_GPIO_PXSELC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_as_func1(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXFUNS(p) = (1 << o); \ -++ REG_GPIO_PXSELS(p) = (1 << o); \ -++} while (0) -++ -++/* -++ * D0 ~ D31, A0 ~ A16, DCS#, RAS#, CAS#, CKE#, -++ * RDWE#, CKO#, WE0#, WE1#, WE2#, WE3# -++ */ -++#define __gpio_as_sdram_32bit() \ -++do { \ -++ REG_GPIO_PXFUNS(0) = 0xffffffff; \ -++ REG_GPIO_PXSELC(0) = 0xffffffff; \ -++ REG_GPIO_PXPES(0) = 0xffffffff; \ -++ REG_GPIO_PXFUNS(1) = 0x81f9ffff; \ -++ REG_GPIO_PXSELC(1) = 0x81f9ffff; \ -++ REG_GPIO_PXPES(1) = 0x81f9ffff; \ -++ REG_GPIO_PXFUNS(2) = 0x07000000; \ -++ REG_GPIO_PXSELC(2) = 0x07000000; \ -++ REG_GPIO_PXPES(2) = 0x07000000; \ -++} while (0) -++ -++/* -++ * D0 ~ D15, A0 ~ A16, DCS#, RAS#, CAS#, CKE#, -++ * RDWE#, CKO#, WE0#, WE1# -++ */ -++#define __gpio_as_sdram_16bit() \ -++do { \ -++ REG_GPIO_PXFUNS(0) = 0x5442bfaa; \ -++ REG_GPIO_PXSELC(0) = 0x5442bfaa; \ -++ REG_GPIO_PXPES(0) = 0x5442bfaa; \ -++ REG_GPIO_PXFUNS(1) = 0x81f9ffff; \ -++ REG_GPIO_PXSELC(1) = 0x81f9ffff; \ -++ REG_GPIO_PXPES(1) = 0x81f9ffff; \ -++ REG_GPIO_PXFUNS(2) = 0x01000000; \ -++ REG_GPIO_PXSELC(2) = 0x01000000; \ -++ REG_GPIO_PXPES(2) = 0x01000000; \ -++} while (0) -++ -++/* -++ * CS1#, CLE, ALE, FRE#, FWE#, FRB#, RDWE#/BUFD# -++ */ -++#define __gpio_as_nand() \ -++do { \ -++ REG_GPIO_PXFUNS(1) = 0x02018000; \ -++ REG_GPIO_PXSELC(1) = 0x02018000; \ -++ REG_GPIO_PXPES(1) = 0x02018000; \ -++ REG_GPIO_PXFUNS(2) = 0x30000000; \ -++ REG_GPIO_PXSELC(2) = 0x30000000; \ -++ REG_GPIO_PXPES(2) = 0x30000000; \ -++ REG_GPIO_PXFUNC(2) = 0x40000000; \ -++ REG_GPIO_PXSELC(2) = 0x40000000; \ -++ REG_GPIO_PXDIRC(2) = 0x40000000; \ -++ REG_GPIO_PXPES(2) = 0x40000000; \ -++ REG_GPIO_PXFUNS(1) = 0x00400000; \ -++ REG_GPIO_PXSELC(1) = 0x00400000; \ -++} while (0) -++ -++/* -++ * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D7 -++ */ -++#define __gpio_as_nor_8bit() \ -++do { \ -++ REG_GPIO_PXFUNS(0) = 0x000000ff; \ -++ REG_GPIO_PXSELC(0) = 0x000000ff; \ -++ REG_GPIO_PXPES(0) = 0x000000ff; \ -++ REG_GPIO_PXFUNS(1) = 0x7041ffff; \ -++ REG_GPIO_PXSELC(1) = 0x7041ffff; \ -++ REG_GPIO_PXPES(1) = 0x7041ffff; \ -++ REG_GPIO_PXFUNS(1) = 0x00060000; \ -++ REG_GPIO_PXSELS(1) = 0x00060000; \ -++ REG_GPIO_PXPES(1) = 0x00060000; \ -++ REG_GPIO_PXFUNS(2) = 0x08000000; \ -++ REG_GPIO_PXSELC(2) = 0x08000000; \ -++ REG_GPIO_PXPES(2) = 0x08000000; \ -++ REG_GPIO_PXFUNS(2) = 0x00c00000; \ -++ REG_GPIO_PXSELS(2) = 0x00c00000; \ -++ REG_GPIO_PXPES(2) = 0x00c00000; \ -++ REG_GPIO_PXFUNS(3) = 0x18000000; \ -++ REG_GPIO_PXSELS(3) = 0x18000000; \ -++ REG_GPIO_PXPES(3) = 0x18000000; \ -++} while (0) -++ -++/* -++ * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D15 -++ */ -++#define __gpio_as_nor_16bit() \ -++do { \ -++ REG_GPIO_PXFUNS(0) = 0x0000ffff; \ -++ REG_GPIO_PXSELC(0) = 0x0000ffff; \ -++ REG_GPIO_PXPES(0) = 0x0000ffff; \ -++ REG_GPIO_PXFUNS(1) = 0x7041ffff; \ -++ REG_GPIO_PXSELC(1) = 0x7041ffff; \ -++ REG_GPIO_PXPES(1) = 0x7041ffff; \ -++ REG_GPIO_PXFUNS(1) = 0x00060000; \ -++ REG_GPIO_PXSELS(1) = 0x00060000; \ -++ REG_GPIO_PXPES(1) = 0x00060000; \ -++ REG_GPIO_PXFUNS(2) = 0x08000000; \ -++ REG_GPIO_PXSELC(2) = 0x08000000; \ -++ REG_GPIO_PXPES(2) = 0x08000000; \ -++ REG_GPIO_PXFUNS(2) = 0x00c00000; \ -++ REG_GPIO_PXSELS(2) = 0x00c00000; \ -++ REG_GPIO_PXPES(2) = 0x00c00000; \ -++ REG_GPIO_PXFUNS(3) = 0x18000000; \ -++ REG_GPIO_PXSELS(3) = 0x18000000; \ -++ REG_GPIO_PXPES(3) = 0x18000000; \ -++} while (0) -++ -++/* -++ * UART0_TxD, UART_RxD0 -++ */ -++#define __gpio_as_uart0() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x06000000; \ -++ REG_GPIO_PXSELS(3) = 0x06000000; \ -++ REG_GPIO_PXPES(3) = 0x06000000; \ -++} while (0) -++ -++/* -++ * UART0_CTS, UART0_RTS -++ */ -++#define __gpio_as_ctsrts() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0xc0000000; \ -++ REG_GPIO_PXSELS(3) = 0xc0000000; \ -++ REG_GPIO_PXTRGC(3) = 0xc0000000; \ -++ REG_GPIO_PXPES(3) = 0xc0000000; \ -++} while (0) -++ -++/* -++ * UART1_TxD, UART1_RxD1 -++ */ -++#define __gpio_as_uart1() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0xc0000000; \ -++ REG_GPIO_PXSELC(3) = 0xc0000000; \ -++ REG_GPIO_PXTRGS(3) = 0xc0000000; \ -++ REG_GPIO_PXPES(3) = 0xc0000000; \ -++} while (0) -++ -++/* -++ * LCD_D0~LCD_D15, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -++ */ -++#define __gpio_as_lcd_16bit() \ -++do { \ -++ REG_GPIO_PXFUNS(2) = 0x003cffff; \ -++ REG_GPIO_PXSELC(2) = 0x003cffff; \ -++ REG_GPIO_PXPES(2) = 0x003cffff; \ -++} while (0) -++ -++/* -++ * LCD_D0~LCD_D17, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -++ */ -++#define __gpio_as_lcd_18bit() \ -++do { \ -++ REG_GPIO_PXFUNS(2) = 0x003fffff; \ -++ REG_GPIO_PXSELC(2) = 0x003fffff; \ -++ REG_GPIO_PXPES(2) = 0x003fffff; \ -++} while (0) -++ -++/* -++ * LCD_PS, LCD_REV, LCD_CLS, LCD_SPL -++ */ -++#define __gpio_as_lcd_special() \ -++do { \ -++ REG_GPIO_PXFUNS(1) = 0x00060000; \ -++ REG_GPIO_PXSELC(1) = 0x00060000; \ -++ REG_GPIO_PXPES(1) = 0x00060000; \ -++ REG_GPIO_PXFUNS(2) = 0x00c00000; \ -++ REG_GPIO_PXSELC(2) = 0x00c00000; \ -++ REG_GPIO_PXPES(2) = 0x00c00000; \ -++} while (0) -++ -++/* LCD_D0~LCD_D7, SLCD_RS, SLCD_CS */ -++#define __gpio_as_slcd_8bit() \ -++do { \ -++ REG_GPIO_PXFUNS(2) = 0x001800ff; \ -++ REG_GPIO_PXSELC(2) = 0x001800ff; \ -++} while (0) -++ -++/* LCD_D0~LCD_D7, SLCD_RS, SLCD_CS */ -++#define __gpio_as_slcd_9bit() \ -++do { \ -++ REG_GPIO_PXFUNS(2) = 0x001801ff; \ -++ REG_GPIO_PXSELC(2) = 0x001801ff; \ -++} while (0) -++ -++/* LCD_D0~LCD_D15, SLCD_RS, SLCD_CS */ -++#define __gpio_as_slcd_16bit() \ -++do { \ -++ REG_GPIO_PXFUNS(2) = 0x0018ffff; \ -++ REG_GPIO_PXSELC(2) = 0x0018ffff; \ -++} while (0) -++ -++/* LCD_D0~LCD_D17, SLCD_RS, SLCD_CS */ -++#define __gpio_as_slcd_18bit() \ -++do { \ -++ REG_GPIO_PXFUNS(2) = 0x001bffff; \ -++ REG_GPIO_PXSELC(2) = 0x001bffff; \ -++} while (0) -++ -++/* -++ * CIM_D0~CIM_D7, CIM_MCLK, CIM_PCLK, CIM_VSYNC, CIM_HSYNC -++ */ -++#define __gpio_as_cim() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x0003c0ff; \ -++ REG_GPIO_PXSELC(3) = 0x0003c0ff; \ -++ REG_GPIO_PXPES(3) = 0x0003c0ff; \ -++} while (0) -++ -++/* -++ * SDATA_OUT, SDATA_IN, BIT_CLK, SYNC, SCLK_RESET -++ */ -++#define __gpio_as_aic() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x007c0000; \ -++ REG_GPIO_PXSELS(3) = 0x007c0000; \ -++ REG_GPIO_PXPES(3) = 0x007c0000; \ -++} while (0) -++ -++/* -++ * MSC_CMD, MSC_CLK, MSC_D0 ~ MSC_D3 -++ */ -++#define __gpio_as_msc() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x00003f00; \ -++ REG_GPIO_PXSELC(3) = 0x00003f00; \ -++ REG_GPIO_PXPES(3) = 0x00003f00; \ -++} while (0) -++ -++/* -++ * SSI_CS0, SSI_CLK, SSI_DT, SSI_DR -++ */ -++#define __gpio_as_ssi() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x003c0000; \ -++ REG_GPIO_PXSELC(3) = 0x003c0000; \ -++ REG_GPIO_PXPES(3) = 0x003c0000; \ -++} while (0) -++ -++/* -++ * I2C_SCK, I2C_SDA -++ */ -++#define __gpio_as_i2c() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x01800000; \ -++ REG_GPIO_PXSELS(3) = 0x01800000; \ -++ REG_GPIO_PXPES(3) = 0x01800000; \ -++} while (0) -++ -++/* -++ * PWM0 -++ */ -++#define __gpio_as_pwm0() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x00800000; \ -++ REG_GPIO_PXSELC(3) = 0x00800000; \ -++ REG_GPIO_PXPES(3) = 0x00800000; \ -++} while (0) -++ -++/* -++ * PWM1 -++ */ -++#define __gpio_as_pwm1() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x01000000; \ -++ REG_GPIO_PXSELC(3) = 0x01000000; \ -++ REG_GPIO_PXPES(3) = 0x01000000; \ -++} while (0) -++ -++/* -++ * PWM2 -++ */ -++#define __gpio_as_pwm2() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x02000000; \ -++ REG_GPIO_PXSELC(3) = 0x02000000; \ -++ REG_GPIO_PXPES(3) = 0x02000000; \ -++} while (0) -++ -++/* -++ * PWM3 -++ */ -++#define __gpio_as_pwm3() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x04000000; \ -++ REG_GPIO_PXSELC(3) = 0x04000000; \ -++ REG_GPIO_PXPES(3) = 0x04000000; \ -++} while (0) -++ -++/* -++ * PWM4 -++ */ -++#define __gpio_as_pwm4() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x08000000; \ -++ REG_GPIO_PXSELC(3) = 0x08000000; \ -++ REG_GPIO_PXPES(3) = 0x08000000; \ -++} while (0) -++ -++/* -++ * PWM5 -++ */ -++#define __gpio_as_pwm5() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x10000000; \ -++ REG_GPIO_PXSELC(3) = 0x10000000; \ -++ REG_GPIO_PXPES(3) = 0x10000000; \ -++} while (0) -++ -++/* -++ * PWM6 -++ */ -++#define __gpio_as_pwm6() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x40000000; \ -++ REG_GPIO_PXSELC(3) = 0x40000000; \ -++ REG_GPIO_PXPES(3) = 0x40000000; \ -++} while (0) -++ -++/* -++ * PWM7 -++ */ -++#define __gpio_as_pwm7() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x80000000; \ -++ REG_GPIO_PXSELC(3) = 0x80000000; \ -++ REG_GPIO_PXPES(3) = 0x80000000; \ -++} while (0) -++ -++/* -++ * n = 0 ~ 7 -++ */ -++#define __gpio_as_pwm(n) __gpio_as_pwm##n() -++ -++//------------------------------------------- -++// GPIO or Interrupt Mode -++ -++#define __gpio_get_port(p) (REG_GPIO_PXPIN(p)) -++ -++#define __gpio_port_as_output(p, o) \ -++do { \ -++ REG_GPIO_PXFUNC(p) = (1 << (o)); \ -++ REG_GPIO_PXSELC(p) = (1 << (o)); \ -++ REG_GPIO_PXDIRS(p) = (1 << (o)); \ -++} while (0) -++ -++#define __gpio_port_as_input(p, o) \ -++do { \ -++ REG_GPIO_PXFUNC(p) = (1 << (o)); \ -++ REG_GPIO_PXSELC(p) = (1 << (o)); \ -++ REG_GPIO_PXDIRC(p) = (1 << (o)); \ -++} while (0) -++ -++#define __gpio_as_output(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ __gpio_port_as_output(p, o); \ -++} while (0) -++ -++#define __gpio_as_input(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ __gpio_port_as_input(p, o); \ -++} while (0) -++ -++#define __gpio_set_pin(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXDATS(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_clear_pin(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXDATC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_get_pin(n) \ -++({ \ -++ unsigned int p, o, v; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ if (__gpio_get_port(p) & (1 << o)) \ -++ v = 1; \ -++ else \ -++ v = 0; \ -++ v; \ -++}) -++ -++#define __gpio_as_irq_high_level(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMS(p) = (1 << o); \ -++ REG_GPIO_PXTRGC(p) = (1 << o); \ -++ REG_GPIO_PXFUNC(p) = (1 << o); \ -++ REG_GPIO_PXSELS(p) = (1 << o); \ -++ REG_GPIO_PXDIRS(p) = (1 << o); \ -++ REG_GPIO_PXFLGC(p) = (1 << o); \ -++ REG_GPIO_PXIMC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_as_irq_low_level(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMS(p) = (1 << o); \ -++ REG_GPIO_PXTRGC(p) = (1 << o); \ -++ REG_GPIO_PXFUNC(p) = (1 << o); \ -++ REG_GPIO_PXSELS(p) = (1 << o); \ -++ REG_GPIO_PXDIRC(p) = (1 << o); \ -++ REG_GPIO_PXFLGC(p) = (1 << o); \ -++ REG_GPIO_PXIMC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_as_irq_rise_edge(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMS(p) = (1 << o); \ -++ REG_GPIO_PXTRGS(p) = (1 << o); \ -++ REG_GPIO_PXFUNC(p) = (1 << o); \ -++ REG_GPIO_PXSELS(p) = (1 << o); \ -++ REG_GPIO_PXDIRS(p) = (1 << o); \ -++ REG_GPIO_PXFLGC(p) = (1 << o); \ -++ REG_GPIO_PXIMC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_as_irq_fall_edge(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMS(p) = (1 << o); \ -++ REG_GPIO_PXTRGS(p) = (1 << o); \ -++ REG_GPIO_PXFUNC(p) = (1 << o); \ -++ REG_GPIO_PXSELS(p) = (1 << o); \ -++ REG_GPIO_PXDIRC(p) = (1 << o); \ -++ REG_GPIO_PXFLGC(p) = (1 << o); \ -++ REG_GPIO_PXIMC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_mask_irq(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMS(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_unmask_irq(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_ack_irq(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXFLGC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_get_irq() \ -++({ \ -++ unsigned int p, i, tmp, v = 0; \ -++ for (p = 3; p >= 0; p--) { \ -++ tmp = REG_GPIO_PXFLG(p); \ -++ for (i = 0; i < 32; i++) \ -++ if (tmp & (1 << i)) \ -++ v = (32*p + i); \ -++ } \ -++ v; \ -++}) -++ -++#define __gpio_group_irq(n) \ -++({ \ -++ register int tmp, i; \ -++ tmp = REG_GPIO_PXFLG((n)); \ -++ for (i=31;i>=0;i--) \ -++ if (tmp & (1 << i)) \ -++ break; \ -++ i; \ -++}) -++ -++#define __gpio_enable_pull(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXPEC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_disable_pull(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXPES(p) = (1 << o); \ -++} while (0) -++ -++ -++/*************************************************************************** -++ * CPM -++ ***************************************************************************/ -++#define __cpm_get_pllm() \ -++ ((REG_CPM_CPPCR & CPM_CPPCR_PLLM_MASK) >> CPM_CPPCR_PLLM_BIT) -++#define __cpm_get_plln() \ -++ ((REG_CPM_CPPCR & CPM_CPPCR_PLLN_MASK) >> CPM_CPPCR_PLLN_BIT) -++#define __cpm_get_pllod() \ -++ ((REG_CPM_CPPCR & CPM_CPPCR_PLLOD_MASK) >> CPM_CPPCR_PLLOD_BIT) -++ -++#define __cpm_get_cdiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_CDIV_MASK) >> CPM_CPCCR_CDIV_BIT) -++#define __cpm_get_hdiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_HDIV_MASK) >> CPM_CPCCR_HDIV_BIT) -++#define __cpm_get_pdiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_PDIV_MASK) >> CPM_CPCCR_PDIV_BIT) -++#define __cpm_get_mdiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT) -++#define __cpm_get_ldiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_LDIV_MASK) >> CPM_CPCCR_LDIV_BIT) -++#define __cpm_get_udiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_UDIV_MASK) >> CPM_CPCCR_UDIV_BIT) -++#define __cpm_get_i2sdiv() \ -++ ((REG_CPM_I2SCDR & CPM_I2SCDR_I2SDIV_MASK) >> CPM_I2SCDR_I2SDIV_BIT) -++#define __cpm_get_pixdiv() \ -++ ((REG_CPM_LPCDR & CPM_LPCDR_PIXDIV_MASK) >> CPM_LPCDR_PIXDIV_BIT) -++#define __cpm_get_mscdiv() \ -++ ((REG_CPM_MSCCDR & CPM_MSCCDR_MSCDIV_MASK) >> CPM_MSCCDR_MSCDIV_BIT) -++#define __cpm_get_uhcdiv() \ -++ ((REG_CPM_UHCCDR & CPM_UHCCDR_UHCDIV_MASK) >> CPM_UHCCDR_UHCDIV_BIT) -++#define __cpm_get_ssidiv() \ -++ ((REG_CPM_SSICCDR & CPM_SSICDR_SSICDIV_MASK) >> CPM_SSICDR_SSIDIV_BIT) -++ -++#define __cpm_set_cdiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_CDIV_MASK) | ((v) << (CPM_CPCCR_CDIV_BIT))) -++#define __cpm_set_hdiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_HDIV_MASK) | ((v) << (CPM_CPCCR_HDIV_BIT))) -++#define __cpm_set_pdiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_PDIV_MASK) | ((v) << (CPM_CPCCR_PDIV_BIT))) -++#define __cpm_set_mdiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_MDIV_MASK) | ((v) << (CPM_CPCCR_MDIV_BIT))) -++#define __cpm_set_ldiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_LDIV_MASK) | ((v) << (CPM_CPCCR_LDIV_BIT))) -++#define __cpm_set_udiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | ((v) << (CPM_CPCCR_UDIV_BIT))) -++#define __cpm_set_i2sdiv(v) \ -++ (REG_CPM_I2SCDR = (REG_CPM_I2SCDR & ~CPM_I2SCDR_I2SDIV_MASK) | ((v) << (CPM_I2SCDR_I2SDIV_BIT))) -++#define __cpm_set_pixdiv(v) \ -++ (REG_CPM_LPCDR = (REG_CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | ((v) << (CPM_LPCDR_PIXDIV_BIT))) -++#define __cpm_set_mscdiv(v) \ -++ (REG_CPM_MSCCDR = (REG_CPM_MSCCDR & ~CPM_MSCCDR_MSCDIV_MASK) | ((v) << (CPM_MSCCDR_MSCDIV_BIT))) -++#define __cpm_set_uhcdiv(v) \ -++ (REG_CPM_UHCCDR = (REG_CPM_UHCCDR & ~CPM_UHCCDR_UHCDIV_MASK) | ((v) << (CPM_UHCCDR_UHCDIV_BIT))) -++#define __cpm_ssiclk_select_exclk() \ -++ (REG_CPM_SSICDR &= ~CPM_SSICDR_SCS) -++#define __cpm_ssiclk_select_pllout() \ -++ (REG_CPM_SSICDR |= CPM_SSICDR_SCS) -++#define __cpm_set_ssidiv(v) \ -++ (REG_CPM_SSICDR = (REG_CPM_SSICDR & ~CPM_SSICDR_SSIDIV_MASK) | ((v) << (CPM_SSICDR_SSIDIV_BIT))) -++ -++#define __cpm_select_i2sclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_I2CS) -++#define __cpm_select_i2sclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_I2CS) -++#define __cpm_enable_cko() (REG_CPM_CPCCR |= CPM_CPCCR_CLKOEN) -++#define __cpm_select_usbclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_UCS) -++#define __cpm_select_usbclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_UCS) -++#define __cpm_enable_pll_change() (REG_CPM_CPCCR |= CPM_CPCCR_CE) -++#define __cpm_pllout_direct() (REG_CPM_CPCCR |= CPM_CPCCR_PCS) -++#define __cpm_pllout_div2() (REG_CPM_CPCCR &= ~CPM_CPCCR_PCS) -++ -++#define __cpm_pll_is_on() (REG_CPM_CPPCR & CPM_CPPCR_PLLS) -++#define __cpm_pll_bypass() (REG_CPM_CPPCR |= CPM_CPPCR_PLLBP) -++#define __cpm_pll_enable() (REG_CPM_CPPCR |= CPM_CPPCR_PLLEN) -++ -++#define __cpm_get_cclk_doze_duty() \ -++ ((REG_CPM_LCR & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT) -++#define __cpm_set_cclk_doze_duty(v) \ -++ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_DOZE_DUTY_MASK) | ((v) << (CPM_LCR_DOZE_DUTY_BIT))) -++ -++#define __cpm_doze_mode() (REG_CPM_LCR |= CPM_LCR_DOZE_ON) -++#define __cpm_idle_mode() \ -++ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_IDLE) -++#define __cpm_sleep_mode() \ -++ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_SLEEP) -++ -++#define __cpm_stop_all() (REG_CPM_CLKGR = 0x7fff) -++#define __cpm_stop_uart1() (REG_CPM_CLKGR |= CPM_CLKGR_UART1) -++#define __cpm_stop_uhc() (REG_CPM_CLKGR |= CPM_CLKGR_UHC) -++#define __cpm_stop_ipu() (REG_CPM_CLKGR |= CPM_CLKGR_IPU) -++#define __cpm_stop_dmac() (REG_CPM_CLKGR |= CPM_CLKGR_DMAC) -++#define __cpm_stop_udc() (REG_CPM_CLKGR |= CPM_CLKGR_UDC) -++#define __cpm_stop_lcd() (REG_CPM_CLKGR |= CPM_CLKGR_LCD) -++#define __cpm_stop_cim() (REG_CPM_CLKGR |= CPM_CLKGR_CIM) -++#define __cpm_stop_sadc() (REG_CPM_CLKGR |= CPM_CLKGR_SADC) -++#define __cpm_stop_msc() (REG_CPM_CLKGR |= CPM_CLKGR_MSC) -++#define __cpm_stop_aic1() (REG_CPM_CLKGR |= CPM_CLKGR_AIC1) -++#define __cpm_stop_aic2() (REG_CPM_CLKGR |= CPM_CLKGR_AIC2) -++#define __cpm_stop_ssi() (REG_CPM_CLKGR |= CPM_CLKGR_SSI) -++#define __cpm_stop_i2c() (REG_CPM_CLKGR |= CPM_CLKGR_I2C) -++#define __cpm_stop_rtc() (REG_CPM_CLKGR |= CPM_CLKGR_RTC) -++#define __cpm_stop_tcu() (REG_CPM_CLKGR |= CPM_CLKGR_TCU) -++#define __cpm_stop_uart0() (REG_CPM_CLKGR |= CPM_CLKGR_UART0) -++ -++#define __cpm_start_all() (REG_CPM_CLKGR = 0x0) -++#define __cpm_start_uart1() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART1) -++#define __cpm_start_uhc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UHC) -++#define __cpm_start_ipu() (REG_CPM_CLKGR &= ~CPM_CLKGR_IPU) -++#define __cpm_start_dmac() (REG_CPM_CLKGR &= ~CPM_CLKGR_DMAC) -++#define __cpm_start_udc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UDC) -++#define __cpm_start_lcd() (REG_CPM_CLKGR &= ~CPM_CLKGR_LCD) -++#define __cpm_start_cim() (REG_CPM_CLKGR &= ~CPM_CLKGR_CIM) -++#define __cpm_start_sadc() (REG_CPM_CLKGR &= ~CPM_CLKGR_SADC) -++#define __cpm_start_msc() (REG_CPM_CLKGR &= ~CPM_CLKGR_MSC) -++#define __cpm_start_aic1() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC1) -++#define __cpm_start_aic2() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC2) -++#define __cpm_start_ssi() (REG_CPM_CLKGR &= ~CPM_CLKGR_SSI) -++#define __cpm_start_i2c() (REG_CPM_CLKGR &= ~CPM_CLKGR_I2C) -++#define __cpm_start_rtc() (REG_CPM_CLKGR &= ~CPM_CLKGR_RTC) -++#define __cpm_start_tcu() (REG_CPM_CLKGR &= ~CPM_CLKGR_TCU) -++#define __cpm_start_uart0() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART0) -++ -++#define __cpm_get_o1st() \ -++ ((REG_CPM_SCR & CPM_SCR_O1ST_MASK) >> CPM_SCR_O1ST_BIT) -++#define __cpm_set_o1st(v) \ -++ (REG_CPM_SCR = (REG_CPM_SCR & ~CPM_SCR_O1ST_MASK) | ((v) << (CPM_SCR_O1ST_BIT))) -++#define __cpm_suspend_usbphy() (REG_CPM_SCR |= CPM_SCR_USBPHY_SUSPEND) -++#define __cpm_enable_osc_in_sleep() (REG_CPM_SCR |= CPM_SCR_OSC_ENABLE) -++ -++ -++/*************************************************************************** -++ * TCU -++ ***************************************************************************/ -++// where 'n' is the TCU channel -++#define __tcu_select_extalclk(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_EXT_EN) -++#define __tcu_select_rtcclk(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_RTC_EN) -++#define __tcu_select_pclk(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_PCK_EN) -++ -++#define __tcu_select_clk_div1(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1) -++#define __tcu_select_clk_div4(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE4) -++#define __tcu_select_clk_div16(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE16) -++#define __tcu_select_clk_div64(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE64) -++#define __tcu_select_clk_div256(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE256) -++#define __tcu_select_clk_div1024(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1024) -++ -++#define __tcu_enable_pwm_output(n) ( REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_EN ) -++#define __tcu_disable_pwm_output(n) ( REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_EN ) -++ -++#define __tcu_init_pwm_output_high(n) ( REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_INITL_HIGH ) -++#define __tcu_init_pwm_output_low(n) ( REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_INITL_HIGH ) -++ -++#define __tcu_set_pwm_output_shutdown_graceful(n) ( REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_SD ) -++#define __tcu_set_pwm_output_shutdown_abrupt(n) ( REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_SD ) -++ -++#define __tcu_start_counter(n) ( REG_TCU_TESR |= (1 << (n)) ) -++#define __tcu_stop_counter(n) ( REG_TCU_TECR |= (1 << (n)) ) -++ -++#define __tcu_half_match_flag(n) ( REG_TCU_TFR & (1 << ((n) + 16)) ) -++#define __tcu_full_match_flag(n) ( REG_TCU_TFR & (1 << (n)) ) -++#define __tcu_set_half_match_flag(n) ( REG_TCU_TFSR = (1 << ((n) + 16)) ) -++#define __tcu_set_full_match_flag(n) ( REG_TCU_TFSR = (1 << (n)) ) -++#define __tcu_clear_half_match_flag(n) ( REG_TCU_TFCR = (1 << ((n) + 16)) ) -++#define __tcu_clear_full_match_flag(n) ( REG_TCU_TFCR = (1 << (n)) ) -++#define __tcu_mask_half_match_irq(n) ( REG_TCU_TMSR = (1 << ((n) + 16)) ) -++#define __tcu_mask_full_match_irq(n) ( REG_TCU_TMSR = (1 << (n)) ) -++#define __tcu_unmask_half_match_irq(n) ( REG_TCU_TMCR = (1 << ((n) + 16)) ) -++#define __tcu_unmask_full_match_irq(n) ( REG_TCU_TMCR = (1 << (n)) ) -++ -++#define __tcu_wdt_clock_stopped() ( REG_TCU_TSR & TCU_TSSR_WDTSC ) -++#define __tcu_timer_clock_stopped(n) ( REG_TCU_TSR & (1 << (n)) ) -++ -++#define __tcu_start_wdt_clock() ( REG_TCU_TSCR = TCU_TSSR_WDTSC ) -++#define __tcu_start_timer_clock(n) ( REG_TCU_TSCR = (1 << (n)) ) -++ -++#define __tcu_stop_wdt_clock() ( REG_TCU_TSSR = TCU_TSSR_WDTSC ) -++#define __tcu_stop_timer_clock(n) ( REG_TCU_TSSR = (1 << (n)) ) -++ -++#define __tcu_get_count(n) ( REG_TCU_TCNT((n)) ) -++#define __tcu_set_count(n,v) ( REG_TCU_TCNT((n)) = (v) ) -++#define __tcu_set_full_data(n,v) ( REG_TCU_TDFR((n)) = (v) ) -++#define __tcu_set_half_data(n,v) ( REG_TCU_TDHR((n)) = (v) ) -++ -++ -++/*************************************************************************** -++ * WDT -++ ***************************************************************************/ -++#define __wdt_start() ( REG_WDT_TCER |= WDT_TCER_TCEN ) -++#define __wdt_stop() ( REG_WDT_TCER &= ~WDT_TCER_TCEN ) -++#define __wdt_set_count(v) ( REG_WDT_TCNT = (v) ) -++#define __wdt_set_data(v) ( REG_WDT_TDR = (v) ) -++ -++#define __wdt_select_extalclk() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_EXT_EN) -++#define __wdt_select_rtcclk() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_RTC_EN) -++#define __wdt_select_pclk() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_PCK_EN) -++ -++#define __wdt_select_clk_div1() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1) -++#define __wdt_select_clk_div4() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE4) -++#define __wdt_select_clk_div16() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE16) -++#define __wdt_select_clk_div64() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE64) -++#define __wdt_select_clk_div256() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE256) -++#define __wdt_select_clk_div1024() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1024) -++ -++ -++/*************************************************************************** -++ * UART -++ ***************************************************************************/ -++ -++#define __uart_enable(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) |= UARTFCR_UUE | UARTFCR_FE ) -++#define __uart_disable(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) = ~UARTFCR_UUE ) -++ -++#define __uart_enable_transmit_irq(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_TIE ) -++#define __uart_disable_transmit_irq(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~UARTIER_TIE ) -++ -++#define __uart_enable_receive_irq(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE ) -++#define __uart_disable_receive_irq(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~(UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE) ) -++ -++#define __uart_enable_loopback(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) |= UARTMCR_LOOP ) -++#define __uart_disable_loopback(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) &= ~UARTMCR_LOOP ) -++ -++#define __uart_set_8n1(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) = UARTLCR_WLEN_8 ) -++ -++#define __uart_set_baud(n, devclk, baud) \ -++ do { \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) |= UARTLCR_DLAB; \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_DLLR) = (devclk / 16 / baud) & 0xff; \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_DLHR) = ((devclk / 16 / baud) >> 8) & 0xff; \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) &= ~UARTLCR_DLAB; \ -++ } while (0) -++ -++#define __uart_parity_error(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_PER) != 0 ) -++ -++#define __uart_clear_errors(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) &= ~(UARTLSR_ORER | UARTLSR_BRK | UARTLSR_FER | UARTLSR_PER | UARTLSR_RFER) ) -++ -++#define __uart_transmit_fifo_empty(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TDRQ) != 0 ) -++ -++#define __uart_transmit_end(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TEMT) != 0 ) -++ -++#define __uart_transmit_char(n, ch) \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_TDR) = (ch) -++ -++#define __uart_receive_fifo_full(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) -++ -++#define __uart_receive_ready(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) -++ -++#define __uart_receive_char(n) \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_RDR) -++ -++#define __uart_disable_irda() \ -++ ( REG8(IRDA_BASE + OFF_SIRCR) &= ~(SIRCR_TSIRE | SIRCR_RSIRE) ) -++#define __uart_enable_irda() \ -++ /* Tx high pulse as 0, Rx low pulse as 0 */ \ -++ ( REG8(IRDA_BASE + OFF_SIRCR) = SIRCR_TSIRE | SIRCR_RSIRE | SIRCR_RXPL | SIRCR_TPWS ) -++ -++ -++/*************************************************************************** -++ * DMAC -++ ***************************************************************************/ -++ -++/* n is the DMA channel (0 - 5) */ -++ -++#define __dmac_enable_module() \ -++ ( REG_DMAC_DMACR |= DMAC_DMACR_DMAE | DMAC_DMACR_PR_RR ) -++#define __dmac_disable_module() \ -++ ( REG_DMAC_DMACR &= ~DMAC_DMACR_DMAE ) -++ -++/* p=0,1,2,3 */ -++#define __dmac_set_priority(p) \ -++do { \ -++ REG_DMAC_DMACR &= ~DMAC_DMACR_PR_MASK; \ -++ REG_DMAC_DMACR |= ((p) << DMAC_DMACR_PR_BIT); \ -++} while (0) -++ -++#define __dmac_test_halt_error() ( REG_DMAC_DMACR & DMAC_DMACR_HLT ) -++#define __dmac_test_addr_error() ( REG_DMAC_DMACR & DMAC_DMACR_AR ) -++ -++#define __dmac_enable_descriptor(n) \ -++ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_NDES ) -++#define __dmac_disable_descriptor(n) \ -++ ( REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_NDES ) -++ -++#define __dmac_enable_channel(n) \ -++ ( REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_EN ) -++#define __dmac_disable_channel(n) \ -++ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_EN ) -++#define __dmac_channel_enabled(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_EN ) -++ -++#define __dmac_channel_enable_irq(n) \ -++ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_TIE ) -++#define __dmac_channel_disable_irq(n) \ -++ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_TIE ) -++ -++#define __dmac_channel_transmit_halt_detected(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_HLT ) -++#define __dmac_channel_transmit_end_detected(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_TT ) -++#define __dmac_channel_address_error_detected(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_AR ) -++#define __dmac_channel_count_terminated_detected(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_CT ) -++#define __dmac_channel_descriptor_invalid_detected(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_INV ) -++ -++#define __dmac_channel_clear_transmit_halt(n) \ -++ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_HLT ) -++#define __dmac_channel_clear_transmit_end(n) \ -++ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_TT ) -++#define __dmac_channel_clear_address_error(n) \ -++ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_AR ) -++#define __dmac_channel_clear_count_terminated(n) \ -++ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_CT ) -++#define __dmac_channel_clear_descriptor_invalid(n) \ -++ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_INV ) -++ -++#define __dmac_channel_set_single_mode(n) \ -++ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_TM ) -++#define __dmac_channel_set_block_mode(n) \ -++ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_TM ) -++ -++#define __dmac_channel_set_transfer_unit_32bit(n) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BIT; \ -++} while (0) -++ -++#define __dmac_channel_set_transfer_unit_16bit(n) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BIT; \ -++} while (0) -++ -++#define __dmac_channel_set_transfer_unit_8bit(n) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_8BIT; \ -++} while (0) -++ -++#define __dmac_channel_set_transfer_unit_16byte(n) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BYTE; \ -++} while (0) -++ -++#define __dmac_channel_set_transfer_unit_32byte(n) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BYTE; \ -++} while (0) -++ -++/* w=8,16,32 */ -++#define __dmac_channel_set_dest_port_width(n,w) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DWDH_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DWDH_##w; \ -++} while (0) -++ -++/* w=8,16,32 */ -++#define __dmac_channel_set_src_port_width(n,w) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SWDH_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_SWDH_##w; \ -++} while (0) -++ -++/* v=0-15 */ -++#define __dmac_channel_set_rdil(n,v) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_RDIL_MASK; \ -++ REG_DMAC_DCMD((n) |= ((v) << DMAC_DCMD_RDIL_BIT); \ -++} while (0) -++ -++#define __dmac_channel_dest_addr_fixed(n) \ -++ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DAI ) -++#define __dmac_channel_dest_addr_increment(n) \ -++ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_DAI ) -++ -++#define __dmac_channel_src_addr_fixed(n) \ -++ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SAI ) -++#define __dmac_channel_src_addr_increment(n) \ -++ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_SAI ) -++ -++#define __dmac_channel_set_doorbell(n) \ -++ ( REG_DMAC_DMADBSR = (1 << (n)) ) -++ -++#define __dmac_channel_irq_detected(n) ( REG_DMAC_DMAIPR & (1 << (n)) ) -++#define __dmac_channel_ack_irq(n) ( REG_DMAC_DMAIPR &= ~(1 << (n)) ) -++ -++static __inline__ int __dmac_get_irq(void) -++{ -++ int i; -++ for (i = 0; i < MAX_DMA_NUM; i++) -++ if (__dmac_channel_irq_detected(i)) -++ return i; -++ return -1; -++} -++ -++ -++/*************************************************************************** -++ * AIC (AC'97 & I2S Controller) -++ ***************************************************************************/ -++ -++#define __aic_enable() ( REG_AIC_FR |= AIC_FR_ENB ) -++#define __aic_disable() ( REG_AIC_FR &= ~AIC_FR_ENB ) -++ -++#define __aic_select_ac97() ( REG_AIC_FR &= ~AIC_FR_AUSEL ) -++#define __aic_select_i2s() ( REG_AIC_FR |= AIC_FR_AUSEL ) -++ -++#define __aic_play_zero() ( REG_AIC_FR &= ~AIC_FR_LSMP ) -++#define __aic_play_lastsample() ( REG_AIC_FR |= AIC_FR_LSMP ) -++ -++#define __i2s_as_master() ( REG_AIC_FR |= AIC_FR_BCKD | AIC_FR_SYNCD ) -++#define __i2s_as_slave() ( REG_AIC_FR &= ~(AIC_FR_BCKD | AIC_FR_SYNCD) ) -++#define __aic_reset_status() ( REG_AIC_FR & AIC_FR_RST ) -++ -++#define __aic_reset() \ -++do { \ -++ REG_AIC_FR |= AIC_FR_RST; \ -++} while(0) -++ -++ -++#define __aic_set_transmit_trigger(n) \ -++do { \ -++ REG_AIC_FR &= ~AIC_FR_TFTH_MASK; \ -++ REG_AIC_FR |= ((n) << AIC_FR_TFTH_BIT); \ -++} while(0) -++ -++#define __aic_set_receive_trigger(n) \ -++do { \ -++ REG_AIC_FR &= ~AIC_FR_RFTH_MASK; \ -++ REG_AIC_FR |= ((n) << AIC_FR_RFTH_BIT); \ -++} while(0) -++ -++#define __aic_enable_record() ( REG_AIC_CR |= AIC_CR_EREC ) -++#define __aic_disable_record() ( REG_AIC_CR &= ~AIC_CR_EREC ) -++#define __aic_enable_replay() ( REG_AIC_CR |= AIC_CR_ERPL ) -++#define __aic_disable_replay() ( REG_AIC_CR &= ~AIC_CR_ERPL ) -++#define __aic_enable_loopback() ( REG_AIC_CR |= AIC_CR_ENLBF ) -++#define __aic_disable_loopback() ( REG_AIC_CR &= ~AIC_CR_ENLBF ) -++ -++#define __aic_flush_fifo() ( REG_AIC_CR |= AIC_CR_FLUSH ) -++#define __aic_unflush_fifo() ( REG_AIC_CR &= ~AIC_CR_FLUSH ) -++ -++#define __aic_enable_transmit_intr() \ -++ ( REG_AIC_CR |= (AIC_CR_ETFS | AIC_CR_ETUR) ) -++#define __aic_disable_transmit_intr() \ -++ ( REG_AIC_CR &= ~(AIC_CR_ETFS | AIC_CR_ETUR) ) -++#define __aic_enable_receive_intr() \ -++ ( REG_AIC_CR |= (AIC_CR_ERFS | AIC_CR_EROR) ) -++#define __aic_disable_receive_intr() \ -++ ( REG_AIC_CR &= ~(AIC_CR_ERFS | AIC_CR_EROR) ) -++ -++#define __aic_enable_transmit_dma() ( REG_AIC_CR |= AIC_CR_TDMS ) -++#define __aic_disable_transmit_dma() ( REG_AIC_CR &= ~AIC_CR_TDMS ) -++#define __aic_enable_receive_dma() ( REG_AIC_CR |= AIC_CR_RDMS ) -++#define __aic_disable_receive_dma() ( REG_AIC_CR &= ~AIC_CR_RDMS ) -++ -++#define __aic_enable_mono2stereo() ( REG_AIC_CR |= AIC_CR_M2S ) -++#define __aic_disable_mono2stereo() ( REG_AIC_CR &= ~AIC_CR_M2S ) -++#define __aic_enable_byteswap() ( REG_AIC_CR |= AIC_CR_ENDSW ) -++#define __aic_disable_byteswap() ( REG_AIC_CR &= ~AIC_CR_ENDSW ) -++#define __aic_enable_unsignadj() ( REG_AIC_CR |= AIC_CR_AVSTSU ) -++#define __aic_disable_unsignadj() ( REG_AIC_CR &= ~AIC_CR_AVSTSU ) -++ -++#define AC97_PCM_XS_L_FRONT AIC_ACCR1_XS_SLOT3 -++#define AC97_PCM_XS_R_FRONT AIC_ACCR1_XS_SLOT4 -++#define AC97_PCM_XS_CENTER AIC_ACCR1_XS_SLOT6 -++#define AC97_PCM_XS_L_SURR AIC_ACCR1_XS_SLOT7 -++#define AC97_PCM_XS_R_SURR AIC_ACCR1_XS_SLOT8 -++#define AC97_PCM_XS_LFE AIC_ACCR1_XS_SLOT9 -++ -++#define AC97_PCM_RS_L_FRONT AIC_ACCR1_RS_SLOT3 -++#define AC97_PCM_RS_R_FRONT AIC_ACCR1_RS_SLOT4 -++#define AC97_PCM_RS_CENTER AIC_ACCR1_RS_SLOT6 -++#define AC97_PCM_RS_L_SURR AIC_ACCR1_RS_SLOT7 -++#define AC97_PCM_RS_R_SURR AIC_ACCR1_RS_SLOT8 -++#define AC97_PCM_RS_LFE AIC_ACCR1_RS_SLOT9 -++ -++#define __ac97_set_xs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK ) -++#define __ac97_set_xs_mono() \ -++do { \ -++ REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \ -++ REG_AIC_ACCR1 |= AC97_PCM_XS_R_FRONT; \ -++} while(0) -++#define __ac97_set_xs_stereo() \ -++do { \ -++ REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \ -++ REG_AIC_ACCR1 |= AC97_PCM_XS_L_FRONT | AC97_PCM_XS_R_FRONT; \ -++} while(0) -++ -++/* In fact, only stereo is support now. */ -++#define __ac97_set_rs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK ) -++#define __ac97_set_rs_mono() \ -++do { \ -++ REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \ -++ REG_AIC_ACCR1 |= AC97_PCM_RS_R_FRONT; \ -++} while(0) -++#define __ac97_set_rs_stereo() \ -++do { \ -++ REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \ -++ REG_AIC_ACCR1 |= AC97_PCM_RS_L_FRONT | AC97_PCM_RS_R_FRONT; \ -++} while(0) -++ -++#define __ac97_warm_reset_codec() \ -++ do { \ -++ REG_AIC_ACCR2 |= AIC_ACCR2_SA; \ -++ REG_AIC_ACCR2 |= AIC_ACCR2_SS; \ -++ udelay(2); \ -++ REG_AIC_ACCR2 &= ~AIC_ACCR2_SS; \ -++ REG_AIC_ACCR2 &= ~AIC_ACCR2_SA; \ -++ } while (0) -++ -++#define __ac97_cold_reset_codec() \ -++ do { \ -++ REG_AIC_ACCR2 |= AIC_ACCR2_SR; \ -++ udelay(2); \ -++ REG_AIC_ACCR2 &= ~AIC_ACCR2_SR; \ -++ } while (0) -++ -++/* n=8,16,18,20 */ -++#define __ac97_set_iass(n) \ -++ ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_IASS_MASK) | AIC_ACCR2_IASS_##n##BIT ) -++#define __ac97_set_oass(n) \ -++ ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_OASS_MASK) | AIC_ACCR2_OASS_##n##BIT ) -++ -++#define __i2s_select_i2s() ( REG_AIC_I2SCR &= ~AIC_I2SCR_AMSL ) -++#define __i2s_select_msbjustified() ( REG_AIC_I2SCR |= AIC_I2SCR_AMSL ) -++ -++/* n=8,16,18,20,24 */ -++/*#define __i2s_set_sample_size(n) \ -++ ( REG_AIC_I2SCR |= (REG_AIC_I2SCR & ~AIC_I2SCR_WL_MASK) | AIC_I2SCR_WL_##n##BIT )*/ -++ -++#define __i2s_set_oss_sample_size(n) \ -++ ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_OSS_MASK) | AIC_CR_OSS_##n##BIT ) -++#define __i2s_set_iss_sample_size(n) \ -++ ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_ISS_MASK) | AIC_CR_ISS_##n##BIT ) -++ -++#define __i2s_stop_bitclk() ( REG_AIC_I2SCR |= AIC_I2SCR_STPBK ) -++#define __i2s_start_bitclk() ( REG_AIC_I2SCR &= ~AIC_I2SCR_STPBK ) -++ -++#define __aic_transmit_request() ( REG_AIC_SR & AIC_SR_TFS ) -++#define __aic_receive_request() ( REG_AIC_SR & AIC_SR_RFS ) -++#define __aic_transmit_underrun() ( REG_AIC_SR & AIC_SR_TUR ) -++#define __aic_receive_overrun() ( REG_AIC_SR & AIC_SR_ROR ) -++ -++#define __aic_clear_errors() ( REG_AIC_SR &= ~(AIC_SR_TUR | AIC_SR_ROR) ) -++ -++#define __aic_get_transmit_resident() \ -++ ( (REG_AIC_SR & AIC_SR_TFL_MASK) >> AIC_SR_TFL_BIT ) -++#define __aic_get_receive_count() \ -++ ( (REG_AIC_SR & AIC_SR_RFL_MASK) >> AIC_SR_RFL_BIT ) -++ -++#define __ac97_command_transmitted() ( REG_AIC_ACSR & AIC_ACSR_CADT ) -++#define __ac97_status_received() ( REG_AIC_ACSR & AIC_ACSR_SADR ) -++#define __ac97_status_receive_timeout() ( REG_AIC_ACSR & AIC_ACSR_RSTO ) -++#define __ac97_codec_is_low_power_mode() ( REG_AIC_ACSR & AIC_ACSR_CLPM ) -++#define __ac97_codec_is_ready() ( REG_AIC_ACSR & AIC_ACSR_CRDY ) -++#define __ac97_slot_error_detected() ( REG_AIC_ACSR & AIC_ACSR_SLTERR ) -++#define __ac97_clear_slot_error() ( REG_AIC_ACSR &= ~AIC_ACSR_SLTERR ) -++ -++#define __i2s_is_busy() ( REG_AIC_I2SSR & AIC_I2SSR_BSY ) -++ -++#define CODEC_READ_CMD (1 << 19) -++#define CODEC_WRITE_CMD (0 << 19) -++#define CODEC_REG_INDEX_BIT 12 -++#define CODEC_REG_INDEX_MASK (0x7f << CODEC_REG_INDEX_BIT) /* 18:12 */ -++#define CODEC_REG_DATA_BIT 4 -++#define CODEC_REG_DATA_MASK (0x0ffff << 4) /* 19:4 */ -++ -++#define __ac97_out_rcmd_addr(reg) \ -++do { \ -++ REG_AIC_ACCAR = CODEC_READ_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ -++} while (0) -++ -++#define __ac97_out_wcmd_addr(reg) \ -++do { \ -++ REG_AIC_ACCAR = CODEC_WRITE_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ -++} while (0) -++ -++#define __ac97_out_data(value) \ -++do { \ -++ REG_AIC_ACCDR = ((value) << CODEC_REG_DATA_BIT); \ -++} while (0) -++ -++#define __ac97_in_data() \ -++ ( (REG_AIC_ACSDR & CODEC_REG_DATA_MASK) >> CODEC_REG_DATA_BIT ) -++ -++#define __ac97_in_status_addr() \ -++ ( (REG_AIC_ACSAR & CODEC_REG_INDEX_MASK) >> CODEC_REG_INDEX_BIT ) -++ -++#define __i2s_set_sample_rate(i2sclk, sync) \ -++ ( REG_AIC_I2SDIV = ((i2sclk) / (4*64)) / (sync) ) -++ -++#define __aic_write_tfifo(v) ( REG_AIC_DR = (v) ) -++#define __aic_read_rfifo() ( REG_AIC_DR ) -++ -++#define __aic_internal_codec() ( REG_AIC_FR |= AIC_FR_ICDC ) -++#define __aic_external_codec() ( REG_AIC_FR &= ~AIC_FR_ICDC ) -++ -++// -++// Define next ops for AC97 compatible -++// -++ -++#define AC97_ACSR AIC_ACSR -++ -++#define __ac97_enable() __aic_enable(); __aic_select_ac97() -++#define __ac97_disable() __aic_disable() -++#define __ac97_reset() __aic_reset() -++ -++#define __ac97_set_transmit_trigger(n) __aic_set_transmit_trigger(n) -++#define __ac97_set_receive_trigger(n) __aic_set_receive_trigger(n) -++ -++#define __ac97_enable_record() __aic_enable_record() -++#define __ac97_disable_record() __aic_disable_record() -++#define __ac97_enable_replay() __aic_enable_replay() -++#define __ac97_disable_replay() __aic_disable_replay() -++#define __ac97_enable_loopback() __aic_enable_loopback() -++#define __ac97_disable_loopback() __aic_disable_loopback() -++ -++#define __ac97_enable_transmit_dma() __aic_enable_transmit_dma() -++#define __ac97_disable_transmit_dma() __aic_disable_transmit_dma() -++#define __ac97_enable_receive_dma() __aic_enable_receive_dma() -++#define __ac97_disable_receive_dma() __aic_disable_receive_dma() -++ -++#define __ac97_transmit_request() __aic_transmit_request() -++#define __ac97_receive_request() __aic_receive_request() -++#define __ac97_transmit_underrun() __aic_transmit_underrun() -++#define __ac97_receive_overrun() __aic_receive_overrun() -++ -++#define __ac97_clear_errors() __aic_clear_errors() -++ -++#define __ac97_get_transmit_resident() __aic_get_transmit_resident() -++#define __ac97_get_receive_count() __aic_get_receive_count() -++ -++#define __ac97_enable_transmit_intr() __aic_enable_transmit_intr() -++#define __ac97_disable_transmit_intr() __aic_disable_transmit_intr() -++#define __ac97_enable_receive_intr() __aic_enable_receive_intr() -++#define __ac97_disable_receive_intr() __aic_disable_receive_intr() -++ -++#define __ac97_write_tfifo(v) __aic_write_tfifo(v) -++#define __ac97_read_rfifo() __aic_read_rfifo() -++ -++// -++// Define next ops for I2S compatible -++// -++ -++#define I2S_ACSR AIC_I2SSR -++ -++#define __i2s_enable() __aic_enable(); __aic_select_i2s() -++#define __i2s_disable() __aic_disable() -++#define __i2s_reset() __aic_reset() -++ -++#define __i2s_set_transmit_trigger(n) __aic_set_transmit_trigger(n) -++#define __i2s_set_receive_trigger(n) __aic_set_receive_trigger(n) -++ -++#define __i2s_enable_record() __aic_enable_record() -++#define __i2s_disable_record() __aic_disable_record() -++#define __i2s_enable_replay() __aic_enable_replay() -++#define __i2s_disable_replay() __aic_disable_replay() -++#define __i2s_enable_loopback() __aic_enable_loopback() -++#define __i2s_disable_loopback() __aic_disable_loopback() -++ -++#define __i2s_enable_transmit_dma() __aic_enable_transmit_dma() -++#define __i2s_disable_transmit_dma() __aic_disable_transmit_dma() -++#define __i2s_enable_receive_dma() __aic_enable_receive_dma() -++#define __i2s_disable_receive_dma() __aic_disable_receive_dma() -++ -++#define __i2s_transmit_request() __aic_transmit_request() -++#define __i2s_receive_request() __aic_receive_request() -++#define __i2s_transmit_underrun() __aic_transmit_underrun() -++#define __i2s_receive_overrun() __aic_receive_overrun() -++ -++#define __i2s_clear_errors() __aic_clear_errors() -++ -++#define __i2s_get_transmit_resident() __aic_get_transmit_resident() -++#define __i2s_get_receive_count() __aic_get_receive_count() -++ -++#define __i2s_enable_transmit_intr() __aic_enable_transmit_intr() -++#define __i2s_disable_transmit_intr() __aic_disable_transmit_intr() -++#define __i2s_enable_receive_intr() __aic_enable_receive_intr() -++#define __i2s_disable_receive_intr() __aic_disable_receive_intr() -++ -++#define __i2s_write_tfifo(v) __aic_write_tfifo(v) -++#define __i2s_read_rfifo() __aic_read_rfifo() -++ -++#define __i2s_reset_codec() \ -++ do { \ -++ } while (0) -++ -++ -++/*************************************************************************** -++ * ICDC -++ ***************************************************************************/ -++#define __i2s_internal_codec() __aic_internal_codec() -++#define __i2s_external_codec() __aic_external_codec() -++ -++/*************************************************************************** -++ * INTC -++ ***************************************************************************/ -++#define __intc_unmask_irq(n) ( REG_INTC_IMCR = (1 << (n)) ) -++#define __intc_mask_irq(n) ( REG_INTC_IMSR = (1 << (n)) ) -++#define __intc_ack_irq(n) ( REG_INTC_IPR = (1 << (n)) ) -++ -++ -++/*************************************************************************** -++ * I2C -++ ***************************************************************************/ -++ -++#define __i2c_enable() ( REG_I2C_CR |= I2C_CR_I2CE ) -++#define __i2c_disable() ( REG_I2C_CR &= ~I2C_CR_I2CE ) -++ -++#define __i2c_send_start() ( REG_I2C_CR |= I2C_CR_STA ) -++#define __i2c_send_stop() ( REG_I2C_CR |= I2C_CR_STO ) -++#define __i2c_send_ack() ( REG_I2C_CR &= ~I2C_CR_AC ) -++#define __i2c_send_nack() ( REG_I2C_CR |= I2C_CR_AC ) -++ -++#define __i2c_set_drf() ( REG_I2C_SR |= I2C_SR_DRF ) -++#define __i2c_clear_drf() ( REG_I2C_SR &= ~I2C_SR_DRF ) -++#define __i2c_check_drf() ( REG_I2C_SR & I2C_SR_DRF ) -++ -++#define __i2c_received_ack() ( !(REG_I2C_SR & I2C_SR_ACKF) ) -++#define __i2c_is_busy() ( REG_I2C_SR & I2C_SR_BUSY ) -++#define __i2c_transmit_ended() ( REG_I2C_SR & I2C_SR_TEND ) -++ -++#define __i2c_set_clk(dev_clk, i2c_clk) \ -++ ( REG_I2C_GR = (dev_clk) / (16*(i2c_clk)) - 1 ) -++ -++#define __i2c_read() ( REG_I2C_DR ) -++#define __i2c_write(val) ( REG_I2C_DR = (val) ) -++ -++ -++/*************************************************************************** -++ * MSC -++ ***************************************************************************/ -++ -++#define __msc_start_op() \ -++ ( REG_MSC_STRPCL = MSC_STRPCL_START_OP | MSC_STRPCL_CLOCK_CONTROL_START ) -++ -++#define __msc_set_resto(to) ( REG_MSC_RESTO = to ) -++#define __msc_set_rdto(to) ( REG_MSC_RDTO = to ) -++#define __msc_set_cmd(cmd) ( REG_MSC_CMD = cmd ) -++#define __msc_set_arg(arg) ( REG_MSC_ARG = arg ) -++#define __msc_set_nob(nob) ( REG_MSC_NOB = nob ) -++#define __msc_get_nob() ( REG_MSC_NOB ) -++#define __msc_set_blklen(len) ( REG_MSC_BLKLEN = len ) -++#define __msc_set_cmdat(cmdat) ( REG_MSC_CMDAT = cmdat ) -++#define __msc_set_cmdat_ioabort() ( REG_MSC_CMDAT |= MSC_CMDAT_IO_ABORT ) -++#define __msc_clear_cmdat_ioabort() ( REG_MSC_CMDAT &= ~MSC_CMDAT_IO_ABORT ) -++ -++#define __msc_set_cmdat_bus_width1() \ -++do { \ -++ REG_MSC_CMDAT &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ -++ REG_MSC_CMDAT |= MSC_CMDAT_BUS_WIDTH_1BIT; \ -++} while(0) -++ -++#define __msc_set_cmdat_bus_width4() \ -++do { \ -++ REG_MSC_CMDAT &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ -++ REG_MSC_CMDAT |= MSC_CMDAT_BUS_WIDTH_4BIT; \ -++} while(0) -++ -++#define __msc_set_cmdat_dma_en() ( REG_MSC_CMDAT |= MSC_CMDAT_DMA_EN ) -++#define __msc_set_cmdat_init() ( REG_MSC_CMDAT |= MSC_CMDAT_INIT ) -++#define __msc_set_cmdat_busy() ( REG_MSC_CMDAT |= MSC_CMDAT_BUSY ) -++#define __msc_set_cmdat_stream() ( REG_MSC_CMDAT |= MSC_CMDAT_STREAM_BLOCK ) -++#define __msc_set_cmdat_block() ( REG_MSC_CMDAT &= ~MSC_CMDAT_STREAM_BLOCK ) -++#define __msc_set_cmdat_read() ( REG_MSC_CMDAT &= ~MSC_CMDAT_WRITE_READ ) -++#define __msc_set_cmdat_write() ( REG_MSC_CMDAT |= MSC_CMDAT_WRITE_READ ) -++#define __msc_set_cmdat_data_en() ( REG_MSC_CMDAT |= MSC_CMDAT_DATA_EN ) -++ -++/* r is MSC_CMDAT_RESPONSE_FORMAT_Rx or MSC_CMDAT_RESPONSE_FORMAT_NONE */ -++#define __msc_set_cmdat_res_format(r) \ -++do { \ -++ REG_MSC_CMDAT &= ~MSC_CMDAT_RESPONSE_FORMAT_MASK; \ -++ REG_MSC_CMDAT |= (r); \ -++} while(0) -++ -++#define __msc_clear_cmdat() \ -++ REG_MSC_CMDAT &= ~( MSC_CMDAT_IO_ABORT | MSC_CMDAT_DMA_EN | MSC_CMDAT_INIT| \ -++ MSC_CMDAT_BUSY | MSC_CMDAT_STREAM_BLOCK | MSC_CMDAT_WRITE_READ | \ -++ MSC_CMDAT_DATA_EN | MSC_CMDAT_RESPONSE_FORMAT_MASK ) -++ -++#define __msc_get_imask() ( REG_MSC_IMASK ) -++#define __msc_mask_all_intrs() ( REG_MSC_IMASK = 0xff ) -++#define __msc_unmask_all_intrs() ( REG_MSC_IMASK = 0x00 ) -++#define __msc_mask_rd() ( REG_MSC_IMASK |= MSC_IMASK_RXFIFO_RD_REQ ) -++#define __msc_unmask_rd() ( REG_MSC_IMASK &= ~MSC_IMASK_RXFIFO_RD_REQ ) -++#define __msc_mask_wr() ( REG_MSC_IMASK |= MSC_IMASK_TXFIFO_WR_REQ ) -++#define __msc_unmask_wr() ( REG_MSC_IMASK &= ~MSC_IMASK_TXFIFO_WR_REQ ) -++#define __msc_mask_endcmdres() ( REG_MSC_IMASK |= MSC_IMASK_END_CMD_RES ) -++#define __msc_unmask_endcmdres() ( REG_MSC_IMASK &= ~MSC_IMASK_END_CMD_RES ) -++#define __msc_mask_datatrandone() ( REG_MSC_IMASK |= MSC_IMASK_DATA_TRAN_DONE ) -++#define __msc_unmask_datatrandone() ( REG_MSC_IMASK &= ~MSC_IMASK_DATA_TRAN_DONE ) -++#define __msc_mask_prgdone() ( REG_MSC_IMASK |= MSC_IMASK_PRG_DONE ) -++#define __msc_unmask_prgdone() ( REG_MSC_IMASK &= ~MSC_IMASK_PRG_DONE ) -++ -++/* n=0,1,2,3,4,5,6,7 */ -++#define __msc_set_clkrt(n) \ -++do { \ -++ REG_MSC_CLKRT = n; \ -++} while(0) -++ -++#define __msc_get_ireg() ( REG_MSC_IREG ) -++#define __msc_ireg_rd() ( REG_MSC_IREG & MSC_IREG_RXFIFO_RD_REQ ) -++#define __msc_ireg_wr() ( REG_MSC_IREG & MSC_IREG_TXFIFO_WR_REQ ) -++#define __msc_ireg_end_cmd_res() ( REG_MSC_IREG & MSC_IREG_END_CMD_RES ) -++#define __msc_ireg_data_tran_done() ( REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE ) -++#define __msc_ireg_prg_done() ( REG_MSC_IREG & MSC_IREG_PRG_DONE ) -++#define __msc_ireg_clear_end_cmd_res() ( REG_MSC_IREG = MSC_IREG_END_CMD_RES ) -++#define __msc_ireg_clear_data_tran_done() ( REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE ) -++#define __msc_ireg_clear_prg_done() ( REG_MSC_IREG = MSC_IREG_PRG_DONE ) -++ -++#define __msc_get_stat() ( REG_MSC_STAT ) -++#define __msc_stat_not_end_cmd_res() ( (REG_MSC_STAT & MSC_STAT_END_CMD_RES) == 0) -++#define __msc_stat_crc_err() \ -++ ( REG_MSC_STAT & (MSC_STAT_CRC_RES_ERR | MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR_YES) ) -++#define __msc_stat_res_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_RES_ERR ) -++#define __msc_stat_rd_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_READ_ERROR ) -++#define __msc_stat_wr_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_WRITE_ERROR_YES ) -++#define __msc_stat_resto_err() ( REG_MSC_STAT & MSC_STAT_TIME_OUT_RES ) -++#define __msc_stat_rdto_err() ( REG_MSC_STAT & MSC_STAT_TIME_OUT_READ ) -++ -++#define __msc_rd_resfifo() ( REG_MSC_RES ) -++#define __msc_rd_rxfifo() ( REG_MSC_RXFIFO ) -++#define __msc_wr_txfifo(v) ( REG_MSC_TXFIFO = v ) -++ -++#define __msc_reset() \ -++do { \ -++ REG_MSC_STRPCL = MSC_STRPCL_RESET; \ -++ while (REG_MSC_STAT & MSC_STAT_IS_RESETTING); \ -++} while (0) -++ -++#define __msc_start_clk() \ -++do { \ -++ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_START; \ -++} while (0) -++ -++#define __msc_stop_clk() \ -++do { \ -++ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP; \ -++} while (0) -++ -++#define MMC_CLK 19169200 -++#define SD_CLK 24576000 -++ -++/* msc_clk should little than pclk and little than clk retrieve from card */ -++#define __msc_calc_clk_divisor(type,dev_clk,msc_clk,lv) \ -++do { \ -++ unsigned int rate, pclk, i; \ -++ pclk = dev_clk; \ -++ rate = type?SD_CLK:MMC_CLK; \ -++ if (msc_clk && msc_clk < pclk) \ -++ pclk = msc_clk; \ -++ i = 0; \ -++ while (pclk < rate) \ -++ { \ -++ i ++; \ -++ rate >>= 1; \ -++ } \ -++ lv = i; \ -++} while(0) -++ -++/* divide rate to little than or equal to 400kHz */ -++#define __msc_calc_slow_clk_divisor(type, lv) \ -++do { \ -++ unsigned int rate, i; \ -++ rate = (type?SD_CLK:MMC_CLK)/1000/400; \ -++ i = 0; \ -++ while (rate > 0) \ -++ { \ -++ rate >>= 1; \ -++ i ++; \ -++ } \ -++ lv = i; \ -++} while(0) -++ -++ -++/*************************************************************************** -++ * SSI -++ ***************************************************************************/ -++ -++#define __ssi_enable() ( REG_SSI_CR0 |= SSI_CR0_SSIE ) -++#define __ssi_disable() ( REG_SSI_CR0 &= ~SSI_CR0_SSIE ) -++#define __ssi_select_ce() ( REG_SSI_CR0 &= ~SSI_CR0_FSEL ) -++ -++#define __ssi_normal_mode() ( REG_SSI_ITR &= ~SSI_ITR_IVLTM_MASK ) -++ -++#define __ssi_select_ce2() \ -++do { \ -++ REG_SSI_CR0 |= SSI_CR0_FSEL; \ -++ REG_SSI_CR1 &= ~SSI_CR1_MULTS; \ -++} while (0) -++ -++#define __ssi_select_gpc() \ -++do { \ -++ REG_SSI_CR0 &= ~SSI_CR0_FSEL; \ -++ REG_SSI_CR1 |= SSI_CR1_MULTS; \ -++} while (0) -++ -++#define __ssi_enable_tx_intr() \ -++ ( REG_SSI_CR0 |= SSI_CR0_TIE | SSI_CR0_TEIE ) -++ -++#define __ssi_disable_tx_intr() \ -++ ( REG_SSI_CR0 &= ~(SSI_CR0_TIE | SSI_CR0_TEIE) ) -++ -++#define __ssi_enable_rx_intr() \ -++ ( REG_SSI_CR0 |= SSI_CR0_RIE | SSI_CR0_REIE ) -++ -++#define __ssi_disable_rx_intr() \ -++ ( REG_SSI_CR0 &= ~(SSI_CR0_RIE | SSI_CR0_REIE) ) -++ -++#define __ssi_enable_txfifo_half_empty_intr() \ -++ ( REG_SSI_CR0 |= SSI_CR0_TIE ) -++#define __ssi_disable_txfifo_half_empty_intr() \ -++ ( REG_SSI_CR0 &= ~SSI_CR0_TIE ) -++#define __ssi_enable_tx_error_intr() \ -++ ( REG_SSI_CR0 |= SSI_CR0_TEIE ) -++#define __ssi_disable_tx_error_intr() \ -++ ( REG_SSI_CR0 &= ~SSI_CR0_TEIE ) -++ -++#define __ssi_enable_rxfifo_half_full_intr() \ -++ ( REG_SSI_CR0 |= SSI_CR0_RIE ) -++#define __ssi_disable_rxfifo_half_full_intr() \ -++ ( REG_SSI_CR0 &= ~SSI_CR0_RIE ) -++#define __ssi_enable_rx_error_intr() \ -++ ( REG_SSI_CR0 |= SSI_CR0_REIE ) -++#define __ssi_disable_rx_error_intr() \ -++ ( REG_SSI_CR0 &= ~SSI_CR0_REIE ) -++ -++#define __ssi_enable_loopback() ( REG_SSI_CR0 |= SSI_CR0_LOOP ) -++#define __ssi_disable_loopback() ( REG_SSI_CR0 &= ~SSI_CR0_LOOP ) -++ -++#define __ssi_enable_receive() ( REG_SSI_CR0 &= ~SSI_CR0_DISREV ) -++#define __ssi_disable_receive() ( REG_SSI_CR0 |= SSI_CR0_DISREV ) -++ -++#define __ssi_finish_receive() \ -++ ( REG_SSI_CR0 |= (SSI_CR0_RFINE | SSI_CR0_RFINC) ) -++ -++#define __ssi_disable_recvfinish() \ -++ ( REG_SSI_CR0 &= ~(SSI_CR0_RFINE | SSI_CR0_RFINC) ) -++ -++#define __ssi_flush_txfifo() ( REG_SSI_CR0 |= SSI_CR0_TFLUSH ) -++#define __ssi_flush_rxfifo() ( REG_SSI_CR0 |= SSI_CR0_RFLUSH ) -++ -++#define __ssi_flush_fifo() \ -++ ( REG_SSI_CR0 |= SSI_CR0_TFLUSH | SSI_CR0_RFLUSH ) -++ -++#define __ssi_finish_transmit() ( REG_SSI_CR1 &= ~SSI_CR1_UNFIN ) -++#define __ssi_wait_transmit() ( REG_SSI_CR1 |= SSI_CR1_UNFIN ) -++ -++#define __ssi_spi_format() \ -++do { \ -++ REG_SSI_CR1 &= ~SSI_CR1_FMAT_MASK; \ -++ REG_SSI_CR1 |= SSI_CR1_FMAT_SPI; \ -++ REG_SSI_CR1 &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK);\ -++ REG_SSI_CR1 |= (SSI_CR1_TFVCK_1 | SSI_CR1_TCKFI_1); \ -++} while (0) -++ -++/* TI's SSP format, must clear SSI_CR1.UNFIN */ -++#define __ssi_ssp_format() \ -++do { \ -++ REG_SSI_CR1 &= ~(SSI_CR1_FMAT_MASK | SSI_CR1_UNFIN); \ -++ REG_SSI_CR1 |= SSI_CR1_FMAT_SSP; \ -++} while (0) -++ -++/* National's Microwire format, must clear SSI_CR0.RFINE, and set max delay */ -++#define __ssi_microwire_format() \ -++do { \ -++ REG_SSI_CR1 &= ~SSI_CR1_FMAT_MASK; \ -++ REG_SSI_CR1 |= SSI_CR1_FMAT_MW1; \ -++ REG_SSI_CR1 &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK);\ -++ REG_SSI_CR1 |= (SSI_CR1_TFVCK_3 | SSI_CR1_TCKFI_3); \ -++ REG_SSI_CR0 &= ~SSI_CR0_RFINE; \ -++} while (0) -++ -++/* CE# level (FRMHL), CE# in interval time (ITFRM), -++ clock phase and polarity (PHA POL), -++ interval time (SSIITR), interval characters/frame (SSIICR) */ -++ -++ /* frmhl,endian,mcom,flen,pha,pol MASK */ -++#define SSICR1_MISC_MASK \ -++ ( SSI_CR1_FRMHL_MASK | SSI_CR1_LFST | SSI_CR1_MCOM_MASK \ -++ | SSI_CR1_FLEN_MASK | SSI_CR1_PHA | SSI_CR1_POL ) \ -++ -++#define __ssi_spi_set_misc(frmhl,endian,flen,mcom,pha,pol) \ -++do { \ -++ REG_SSI_CR1 &= ~SSICR1_MISC_MASK; \ -++ REG_SSI_CR1 |= ((frmhl) << 30) | ((endian) << 25) | \ -++ (((mcom) - 1) << 12) | (((flen) - 2) << 4) | \ -++ ((pha) << 1) | (pol); \ -++} while(0) -++ -++/* Transfer with MSB or LSB first */ -++#define __ssi_set_msb() ( REG_SSI_CR1 &= ~SSI_CR1_LFST ) -++#define __ssi_set_lsb() ( REG_SSI_CR1 |= SSI_CR1_LFST ) -++ -++#define __ssi_set_frame_length(n) \ -++ REG_SSI_CR1 = (REG_SSI_CR1 & ~SSI_CR1_FLEN_MASK) | (((n) - 2) << 4) -++ -++/* n = 1 - 16 */ -++#define __ssi_set_microwire_command_length(n) \ -++ ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_MCOM_MASK) | SSI_CR1_MCOM_##n##BIT) ) -++ -++/* Set the clock phase for SPI */ -++#define __ssi_set_spi_clock_phase(n) \ -++ ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_PHA) | ((n&0x1)<< 1))) -++ -++/* Set the clock polarity for SPI */ -++#define __ssi_set_spi_clock_polarity(n) \ -++ ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_POL) | (n&0x1)) ) -++ -++/* n = ix8 */ -++#define __ssi_set_tx_trigger(n) \ -++do { \ -++ REG_SSI_CR1 &= ~SSI_CR1_TTRG_MASK; \ -++ REG_SSI_CR1 |= (n/8)<> SSI_SR_TFIFONUM_BIT ) -++ -++#define __ssi_get_rxfifo_count() \ -++ ( (REG_SSI_SR & SSI_SR_RFIFONUM_MASK) >> SSI_SR_RFIFONUM_BIT ) -++ -++#define __ssi_transfer_end() ( REG_SSI_SR & SSI_SR_END ) -++#define __ssi_is_busy() ( REG_SSI_SR & SSI_SR_BUSY ) -++ -++#define __ssi_txfifo_full() ( REG_SSI_SR & SSI_SR_TFF ) -++#define __ssi_rxfifo_empty() ( REG_SSI_SR & SSI_SR_RFE ) -++#define __ssi_rxfifo_half_full() ( REG_SSI_SR & SSI_SR_RFHF ) -++#define __ssi_txfifo_half_empty() ( REG_SSI_SR & SSI_SR_TFHE ) -++#define __ssi_underrun() ( REG_SSI_SR & SSI_SR_UNDR ) -++#define __ssi_overrun() ( REG_SSI_SR & SSI_SR_OVER ) -++#define __ssi_clear_underrun() ( REG_SSI_SR = ~SSI_SR_UNDR ) -++#define __ssi_clear_overrun() ( REG_SSI_SR = ~SSI_SR_OVER ) -++#define __ssi_clear_errors() \ -++ ( REG_SSI_SR &= ~(SSI_SR_UNDR | SSI_SR_OVER) ) -++ -++ -++#define __ssi_set_clk(dev_clk, ssi_clk) \ -++ ( REG_SSI_GR = (dev_clk) / (2*(ssi_clk)) - 1 ) -++ -++#define __ssi_receive_data() REG_SSI_DR -++#define __ssi_transmit_data(v) ( REG_SSI_DR = (v) ) -++ -++ -++/*************************************************************************** -++ * CIM -++ ***************************************************************************/ -++ -++#define __cim_enable() ( REG_CIM_CTRL |= CIM_CTRL_ENA ) -++#define __cim_disable() ( REG_CIM_CTRL &= ~CIM_CTRL_ENA ) -++ -++#define __cim_input_data_inverse() ( REG_CIM_CFG |= CIM_CFG_INV_DAT ) -++#define __cim_input_data_normal() ( REG_CIM_CFG &= ~CIM_CFG_INV_DAT ) -++ -++#define __cim_vsync_active_low() ( REG_CIM_CFG |= CIM_CFG_VSP ) -++#define __cim_vsync_active_high() ( REG_CIM_CFG &= ~CIM_CFG_VSP ) -++ -++#define __cim_hsync_active_low() ( REG_CIM_CFG |= CIM_CFG_HSP ) -++#define __cim_hsync_active_high() ( REG_CIM_CFG &= ~CIM_CFG_HSP ) -++ -++#define __cim_sample_data_at_pclk_falling_edge() \ -++ ( REG_CIM_CFG |= CIM_CFG_PCP ) -++#define __cim_sample_data_at_pclk_rising_edge() \ -++ ( REG_CIM_CFG &= ~CIM_CFG_PCP ) -++ -++#define __cim_enable_dummy_zero() ( REG_CIM_CFG |= CIM_CFG_DUMMY_ZERO ) -++#define __cim_disable_dummy_zero() ( REG_CIM_CFG &= ~CIM_CFG_DUMMY_ZERO ) -++ -++#define __cim_select_external_vsync() ( REG_CIM_CFG |= CIM_CFG_EXT_VSYNC ) -++#define __cim_select_internal_vsync() ( REG_CIM_CFG &= ~CIM_CFG_EXT_VSYNC ) -++ -++/* n=0-7 */ -++#define __cim_set_data_packing_mode(n) \ -++do { \ -++ REG_CIM_CFG &= ~CIM_CFG_PACK_MASK; \ -++ REG_CIM_CFG |= (CIM_CFG_PACK_##n); \ -++} while (0) -++ -++#define __cim_enable_ccir656_progressive_mode() \ -++do { \ -++ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ -++ REG_CIM_CFG |= CIM_CFG_DSM_CPM; \ -++} while (0) -++ -++#define __cim_enable_ccir656_interlace_mode() \ -++do { \ -++ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ -++ REG_CIM_CFG |= CIM_CFG_DSM_CIM; \ -++} while (0) -++ -++#define __cim_enable_gated_clock_mode() \ -++do { \ -++ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ -++ REG_CIM_CFG |= CIM_CFG_DSM_GCM; \ -++} while (0) -++ -++#define __cim_enable_nongated_clock_mode() \ -++do { \ -++ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \ -++ REG_CIM_CFG |= CIM_CFG_DSM_NGCM; \ -++} while (0) -++ -++/* sclk:system bus clock -++ * mclk: CIM master clock -++ */ -++#define __cim_set_master_clk(sclk, mclk) \ -++do { \ -++ REG_CIM_CTRL &= ~CIM_CTRL_MCLKDIV_MASK; \ -++ REG_CIM_CTRL |= (((sclk)/(mclk) - 1) << CIM_CTRL_MCLKDIV_BIT); \ -++} while (0) -++ -++#define __cim_enable_sof_intr() \ -++ ( REG_CIM_CTRL |= CIM_CTRL_DMA_SOFM ) -++#define __cim_disable_sof_intr() \ -++ ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_SOFM ) -++ -++#define __cim_enable_eof_intr() \ -++ ( REG_CIM_CTRL |= CIM_CTRL_DMA_EOFM ) -++#define __cim_disable_eof_intr() \ -++ ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_EOFM ) -++ -++#define __cim_enable_stop_intr() \ -++ ( REG_CIM_CTRL |= CIM_CTRL_DMA_STOPM ) -++#define __cim_disable_stop_intr() \ -++ ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_STOPM ) -++ -++#define __cim_enable_trig_intr() \ -++ ( REG_CIM_CTRL |= CIM_CTRL_RXF_TRIGM ) -++#define __cim_disable_trig_intr() \ -++ ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_TRIGM ) -++ -++#define __cim_enable_rxfifo_overflow_intr() \ -++ ( REG_CIM_CTRL |= CIM_CTRL_RXF_OFM ) -++#define __cim_disable_rxfifo_overflow_intr() \ -++ ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_OFM ) -++ -++/* n=1-16 */ -++#define __cim_set_frame_rate(n) \ -++do { \ -++ REG_CIM_CTRL &= ~CIM_CTRL_FRC_MASK; \ -++ REG_CIM_CTRL |= CIM_CTRL_FRC_##n; \ -++} while (0) -++ -++#define __cim_enable_dma() ( REG_CIM_CTRL |= CIM_CTRL_DMA_EN ) -++#define __cim_disable_dma() ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_EN ) -++ -++#define __cim_reset_rxfifo() ( REG_CIM_CTRL |= CIM_CTRL_RXF_RST ) -++#define __cim_unreset_rxfifo() ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_RST ) -++ -++/* n=4,8,12,16,20,24,28,32 */ -++#define __cim_set_rxfifo_trigger(n) \ -++do { \ -++ REG_CIM_CTRL &= ~CIM_CTRL_RXF_TRIG_MASK; \ -++ REG_CIM_CTRL |= CIM_CTRL_RXF_TRIG_##n; \ -++} while (0) -++ -++#define __cim_clear_state() ( REG_CIM_STATE = 0 ) -++ -++#define __cim_disable_done() ( REG_CIM_STATE & CIM_STATE_VDD ) -++#define __cim_rxfifo_empty() ( REG_CIM_STATE & CIM_STATE_RXF_EMPTY ) -++#define __cim_rxfifo_reach_trigger() ( REG_CIM_STATE & CIM_STATE_RXF_TRIG ) -++#define __cim_rxfifo_overflow() ( REG_CIM_STATE & CIM_STATE_RXF_OF ) -++#define __cim_clear_rxfifo_overflow() ( REG_CIM_STATE &= ~CIM_STATE_RXF_OF ) -++#define __cim_dma_stop() ( REG_CIM_STATE & CIM_STATE_DMA_STOP ) -++#define __cim_dma_eof() ( REG_CIM_STATE & CIM_STATE_DMA_EOF ) -++#define __cim_dma_sof() ( REG_CIM_STATE & CIM_STATE_DMA_SOF ) -++ -++#define __cim_get_iid() ( REG_CIM_IID ) -++#define __cim_get_image_data() ( REG_CIM_RXFIFO ) -++#define __cim_get_dam_cmd() ( REG_CIM_CMD ) -++ -++#define __cim_set_da(a) ( REG_CIM_DA = (a) ) -++ -++/*************************************************************************** -++ * LCD -++ ***************************************************************************/ -++#define __lcd_as_smart_lcd() ( REG_LCD_CFG |= (1<> LCD_VSYNC_VPS_BIT ) -++ -++#define __lcd_vsync_get_vpe() \ -++ ( (REG_LCD_VSYNC & LCD_VSYNC_VPE_MASK) >> LCD_VSYNC_VPE_BIT ) -++#define __lcd_vsync_set_vpe(n) \ -++do { \ -++ REG_LCD_VSYNC &= ~LCD_VSYNC_VPE_MASK; \ -++ REG_LCD_VSYNC |= (n) << LCD_VSYNC_VPE_BIT; \ -++} while (0) -++ -++#define __lcd_hsync_get_hps() \ -++ ( (REG_LCD_HSYNC & LCD_HSYNC_HPS_MASK) >> LCD_HSYNC_HPS_BIT ) -++#define __lcd_hsync_set_hps(n) \ -++do { \ -++ REG_LCD_HSYNC &= ~LCD_HSYNC_HPS_MASK; \ -++ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPS_BIT; \ -++} while (0) -++ -++#define __lcd_hsync_get_hpe() \ -++ ( (REG_LCD_HSYNC & LCD_HSYNC_HPE_MASK) >> LCD_VSYNC_HPE_BIT ) -++#define __lcd_hsync_set_hpe(n) \ -++do { \ -++ REG_LCD_HSYNC &= ~LCD_HSYNC_HPE_MASK; \ -++ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPE_BIT; \ -++} while (0) -++ -++#define __lcd_vat_get_ht() \ -++ ( (REG_LCD_VAT & LCD_VAT_HT_MASK) >> LCD_VAT_HT_BIT ) -++#define __lcd_vat_set_ht(n) \ -++do { \ -++ REG_LCD_VAT &= ~LCD_VAT_HT_MASK; \ -++ REG_LCD_VAT |= (n) << LCD_VAT_HT_BIT; \ -++} while (0) -++ -++#define __lcd_vat_get_vt() \ -++ ( (REG_LCD_VAT & LCD_VAT_VT_MASK) >> LCD_VAT_VT_BIT ) -++#define __lcd_vat_set_vt(n) \ -++do { \ -++ REG_LCD_VAT &= ~LCD_VAT_VT_MASK; \ -++ REG_LCD_VAT |= (n) << LCD_VAT_VT_BIT; \ -++} while (0) -++ -++#define __lcd_dah_get_hds() \ -++ ( (REG_LCD_DAH & LCD_DAH_HDS_MASK) >> LCD_DAH_HDS_BIT ) -++#define __lcd_dah_set_hds(n) \ -++do { \ -++ REG_LCD_DAH &= ~LCD_DAH_HDS_MASK; \ -++ REG_LCD_DAH |= (n) << LCD_DAH_HDS_BIT; \ -++} while (0) -++ -++#define __lcd_dah_get_hde() \ -++ ( (REG_LCD_DAH & LCD_DAH_HDE_MASK) >> LCD_DAH_HDE_BIT ) -++#define __lcd_dah_set_hde(n) \ -++do { \ -++ REG_LCD_DAH &= ~LCD_DAH_HDE_MASK; \ -++ REG_LCD_DAH |= (n) << LCD_DAH_HDE_BIT; \ -++} while (0) -++ -++#define __lcd_dav_get_vds() \ -++ ( (REG_LCD_DAV & LCD_DAV_VDS_MASK) >> LCD_DAV_VDS_BIT ) -++#define __lcd_dav_set_vds(n) \ -++do { \ -++ REG_LCD_DAV &= ~LCD_DAV_VDS_MASK; \ -++ REG_LCD_DAV |= (n) << LCD_DAV_VDS_BIT; \ -++} while (0) -++ -++#define __lcd_dav_get_vde() \ -++ ( (REG_LCD_DAV & LCD_DAV_VDE_MASK) >> LCD_DAV_VDE_BIT ) -++#define __lcd_dav_set_vde(n) \ -++do { \ -++ REG_LCD_DAV &= ~LCD_DAV_VDE_MASK; \ -++ REG_LCD_DAV |= (n) << LCD_DAV_VDE_BIT; \ -++} while (0) -++ -++#define __lcd_cmd0_set_sofint() ( REG_LCD_CMD0 |= LCD_CMD_SOFINT ) -++#define __lcd_cmd0_clr_sofint() ( REG_LCD_CMD0 &= ~LCD_CMD_SOFINT ) -++#define __lcd_cmd1_set_sofint() ( REG_LCD_CMD1 |= LCD_CMD_SOFINT ) -++#define __lcd_cmd1_clr_sofint() ( REG_LCD_CMD1 &= ~LCD_CMD_SOFINT ) -++ -++#define __lcd_cmd0_set_eofint() ( REG_LCD_CMD0 |= LCD_CMD_EOFINT ) -++#define __lcd_cmd0_clr_eofint() ( REG_LCD_CMD0 &= ~LCD_CMD_EOFINT ) -++#define __lcd_cmd1_set_eofint() ( REG_LCD_CMD1 |= LCD_CMD_EOFINT ) -++#define __lcd_cmd1_clr_eofint() ( REG_LCD_CMD1 &= ~LCD_CMD_EOFINT ) -++ -++#define __lcd_cmd0_set_pal() ( REG_LCD_CMD0 |= LCD_CMD_PAL ) -++#define __lcd_cmd0_clr_pal() ( REG_LCD_CMD0 &= ~LCD_CMD_PAL ) -++ -++#define __lcd_cmd0_get_len() \ -++ ( (REG_LCD_CMD0 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) -++#define __lcd_cmd1_get_len() \ -++ ( (REG_LCD_CMD1 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) -++ -++/******************************************************* -++ * SMART LCD -++ *******************************************************/ -++ -++#define __slcd_dma_enable() (REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN) -++#define __slcd_dma_disable() \ -++do {\ -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); \ -++ REG_SLCD_CTRL &= ~SLCD_CTRL_DMA_EN; \ -++} while(0) -++ -++/******************************************************* -++ * SMART LCD -++ *******************************************************/ -++ -++#define __slcd_dma_enable() (REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN) -++#define __slcd_dma_disable() \ -++do {\ -++ while (REG_SLCD_STATE & SLCD_STATE_BUSY); \ -++ REG_SLCD_CTRL &= ~SLCD_CTRL_DMA_EN; \ -++} while(0) -++ -++/*************************************************************************** -++ * RTC ops -++ ***************************************************************************/ -++ -++#define __rtc_write_ready() ( (REG_RTC_RCR & RTC_RCR_WRDY) >> RTC_RCR_WRDY_BIT ) -++#define __rtc_enabled() ( REG_RTC_RCR |= RTC_RCR_RTCE ) -++#define __rtc_disabled() ( REG_RTC_RCR &= ~RTC_RCR_RTCE ) -++#define __rtc_enable_alarm() ( REG_RTC_RCR |= RTC_RCR_AE ) -++#define __rtc_disable_alarm() ( REG_RTC_RCR &= ~RTC_RCR_AE ) -++#define __rtc_enable_alarm_irq() ( REG_RTC_RCR |= RTC_RCR_AIE ) -++#define __rtc_disable_alarm_irq() ( REG_RTC_RCR &= ~RTC_RCR_AIE ) -++#define __rtc_enable_1Hz_irq() ( REG_RTC_RCR |= RTC_RCR_1HZIE ) -++#define __rtc_disable_1Hz_irq() ( REG_RTC_RCR &= ~RTC_RCR_1HZIE ) -++ -++#define __rtc_get_1Hz_flag() ( (REG_RTC_RCR >> RTC_RCR_1HZ_BIT) & 0x1 ) -++#define __rtc_clear_1Hz_flag() ( REG_RTC_RCR &= ~RTC_RCR_1HZ ) -++#define __rtc_get_alarm_flag() ( (REG_RTC_RCR >> RTC_RCR_AF_BIT) & 0x1 ) -++#define __rtc_clear_alarm_flag() ( REG_RTC_RCR &= ~RTC_RCR_AF ) -++ -++#define __rtc_get_second() ( REG_RTC_RSR ) -++#define __rtc_set_second(v) ( REG_RTC_RSR = v ) -++ -++#define __rtc_get_alarm_second() ( REG_RTC_RSAR ) -++#define __rtc_set_alarm_second(v) ( REG_RTC_RSAR = v ) -++ -++#define __rtc_RGR_is_locked() ( (REG_RTC_RGR >> RTC_RGR_LOCK) ) -++#define __rtc_lock_RGR() ( REG_RTC_RGR |= RTC_RGR_LOCK ) -++#define __rtc_unlock_RGR() ( REG_RTC_RGR &= ~RTC_RGR_LOCK ) -++#define __rtc_get_adjc_val() ( (REG_RTC_RGR & RTC_RGR_ADJC_MASK) >> RTC_RGR_ADJC_BIT ) -++#define __rtc_set_adjc_val(v) \ -++ ( REG_RTC_RGR = ( (REG_RTC_RGR & ~RTC_RGR_ADJC_MASK) | (v << RTC_RGR_ADJC_BIT) )) -++#define __rtc_get_nc1Hz_val() ( (REG_RTC_RGR & RTC_RGR_NC1HZ_MASK) >> RTC_RGR_NC1HZ_BIT ) -++#define __rtc_set_nc1Hz_val(v) \ -++ ( REG_RTC_RGR = ( (REG_RTC_RGR & ~RTC_RGR_NC1HZ_MASK) | (v << RTC_RGR_NC1HZ_BIT) )) -++ -++#define __rtc_power_down() ( REG_RTC_HCR |= RTC_HCR_PD ) -++ -++#define __rtc_get_hwfcr_val() ( REG_RTC_HWFCR & RTC_HWFCR_MASK ) -++#define __rtc_set_hwfcr_val(v) ( REG_RTC_HWFCR = (v) & RTC_HWFCR_MASK ) -++#define __rtc_get_hrcr_val() ( REG_RTC_HRCR & RTC_HRCR_MASK ) -++#define __rtc_set_hrcr_val(v) ( REG_RTC_HRCR = (v) & RTC_HRCR_MASK ) -++ -++#define __rtc_enable_alarm_wakeup() ( REG_RTC_HWCR |= RTC_HWCR_EALM ) -++#define __rtc_disable_alarm_wakeup() ( REG_RTC_HWCR &= ~RTC_HWCR_EALM ) -++ -++#define __rtc_status_hib_reset_occur() ( (REG_RTC_HWRSR >> RTC_HWRSR_HR) & 0x1 ) -++#define __rtc_status_ppr_reset_occur() ( (REG_RTC_HWRSR >> RTC_HWRSR_PPR) & 0x1 ) -++#define __rtc_status_wakeup_pin_waken_up() ( (REG_RTC_HWRSR >> RTC_HWRSR_PIN) & 0x1 ) -++#define __rtc_status_alarm_waken_up() ( (REG_RTC_HWRSR >> RTC_HWRSR_ALM) & 0x1 ) -++#define __rtc_clear_hib_stat_all() ( REG_RTC_HWRSR = 0 ) -++ -++#define __rtc_get_scratch_pattern() (REG_RTC_HSPR) -++#define __rtc_set_scratch_pattern(n) (REG_RTC_HSPR = n ) -++ -++ -++ -++#endif /* __JZ4740_OPS_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4740/regs.h linux-2.6.24.7/include/asm-mips/mach-jz4740/regs.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4740/regs.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4740/regs.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,2392 @@ -++/* -++ * linux/include/asm-mips/mach-jz4740/regs.h -++ * -++ * Ingenic's JZ4740 common include. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __JZ4740_REGS_H__ -++#define __JZ4740_REGS_H__ -++ -++#if defined(__ASSEMBLY__) || defined(__LANGUAGE_ASSEMBLY) -++#define REG8(addr) (addr) -++#define REG16(addr) (addr) -++#define REG32(addr) (addr) -++#else -++#define REG8(addr) *((volatile unsigned char *)(addr)) -++#define REG16(addr) *((volatile unsigned short *)(addr)) -++#define REG32(addr) *((volatile unsigned int *)(addr)) -++#endif -++ -++/* -++ * Define the module base addresses -++ */ -++#define CPM_BASE 0xB0000000 -++#define INTC_BASE 0xB0001000 -++#define TCU_BASE 0xB0002000 -++#define WDT_BASE 0xB0002000 -++#define RTC_BASE 0xB0003000 -++#define GPIO_BASE 0xB0010000 -++#define AIC_BASE 0xB0020000 -++#define ICDC_BASE 0xB0020000 -++#define MSC_BASE 0xB0021000 -++#define UART0_BASE 0xB0030000 -++#define UART1_BASE 0xB0031000 -++#define I2C_BASE 0xB0042000 -++#define SSI_BASE 0xB0043000 -++#define SADC_BASE 0xB0070000 -++#define EMC_BASE 0xB3010000 -++#define DMAC_BASE 0xB3020000 -++#define UHC_BASE 0xB3030000 -++#define UDC_BASE 0xB3040000 -++#define LCD_BASE 0xB3050000 -++#define SLCD_BASE 0xB3050000 -++#define CIM_BASE 0xB3060000 -++#define IPU_BASE 0xB3080000 -++#define ETH_BASE 0xB3100000 -++ -++ -++/************************************************************************* -++ * INTC (Interrupt Controller) -++ *************************************************************************/ -++#define INTC_ISR (INTC_BASE + 0x00) -++#define INTC_IMR (INTC_BASE + 0x04) -++#define INTC_IMSR (INTC_BASE + 0x08) -++#define INTC_IMCR (INTC_BASE + 0x0c) -++#define INTC_IPR (INTC_BASE + 0x10) -++ -++#define REG_INTC_ISR REG32(INTC_ISR) -++#define REG_INTC_IMR REG32(INTC_IMR) -++#define REG_INTC_IMSR REG32(INTC_IMSR) -++#define REG_INTC_IMCR REG32(INTC_IMCR) -++#define REG_INTC_IPR REG32(INTC_IPR) -++ -++// 1st-level interrupts -++#define IRQ_I2C 1 -++#define IRQ_UHC 3 -++#define IRQ_UART1 8 -++#define IRQ_UART0 9 -++#define IRQ_SADC 12 -++#define IRQ_MSC 14 -++#define IRQ_RTC 15 -++#define IRQ_SSI 16 -++#define IRQ_CIM 17 -++#define IRQ_AIC 18 -++#define IRQ_ETH 19 -++#define IRQ_DMAC 20 -++#define IRQ_TCU2 21 -++#define IRQ_TCU1 22 -++#define IRQ_TCU0 23 -++#define IRQ_UDC 24 -++#define IRQ_GPIO3 25 -++#define IRQ_GPIO2 26 -++#define IRQ_GPIO1 27 -++#define IRQ_GPIO0 28 -++#define IRQ_IPU 29 -++#define IRQ_LCD 30 -++ -++// 2nd-level interrupts -++#define IRQ_DMA_0 32 /* 32 to 37 for DMAC channel 0 to 5 */ -++#define IRQ_GPIO_0 48 /* 48 to 175 for GPIO pin 0 to 127 */ -++ -++#define NUM_DMA 6 -++#define NUM_GPIO 128 -++/************************************************************************* -++ * RTC -++ *************************************************************************/ -++#define RTC_RCR (RTC_BASE + 0x00) /* RTC Control Register */ -++#define RTC_RSR (RTC_BASE + 0x04) /* RTC Second Register */ -++#define RTC_RSAR (RTC_BASE + 0x08) /* RTC Second Alarm Register */ -++#define RTC_RGR (RTC_BASE + 0x0c) /* RTC Regulator Register */ -++ -++#define RTC_HCR (RTC_BASE + 0x20) /* Hibernate Control Register */ -++#define RTC_HWFCR (RTC_BASE + 0x24) /* Hibernate Wakeup Filter Counter Reg */ -++#define RTC_HRCR (RTC_BASE + 0x28) /* Hibernate Reset Counter Register */ -++#define RTC_HWCR (RTC_BASE + 0x2c) /* Hibernate Wakeup Control Register */ -++#define RTC_HWRSR (RTC_BASE + 0x30) /* Hibernate Wakeup Status Register */ -++#define RTC_HSPR (RTC_BASE + 0x34) /* Hibernate Scratch Pattern Register */ -++ -++#define REG_RTC_RCR REG32(RTC_RCR) -++#define REG_RTC_RSR REG32(RTC_RSR) -++#define REG_RTC_RSAR REG32(RTC_RSAR) -++#define REG_RTC_RGR REG32(RTC_RGR) -++#define REG_RTC_HCR REG32(RTC_HCR) -++#define REG_RTC_HWFCR REG32(RTC_HWFCR) -++#define REG_RTC_HRCR REG32(RTC_HRCR) -++#define REG_RTC_HWCR REG32(RTC_HWCR) -++#define REG_RTC_HWRSR REG32(RTC_HWRSR) -++#define REG_RTC_HSPR REG32(RTC_HSPR) -++ -++/* RTC Control Register */ -++#define RTC_RCR_WRDY_BIT 7 -++#define RTC_RCR_WRDY (1 << 7) /* Write Ready Flag */ -++#define RTC_RCR_1HZ_BIT 6 -++#define RTC_RCR_1HZ (1 << RTC_RCR_1HZ_BIT) /* 1Hz Flag */ -++#define RTC_RCR_1HZIE (1 << 5) /* 1Hz Interrupt Enable */ -++#define RTC_RCR_AF_BIT 4 -++#define RTC_RCR_AF (1 << RTC_RCR_AF_BIT) /* Alarm Flag */ -++#define RTC_RCR_AIE (1 << 3) /* Alarm Interrupt Enable */ -++#define RTC_RCR_AE (1 << 2) /* Alarm Enable */ -++#define RTC_RCR_RTCE (1 << 0) /* RTC Enable */ -++ -++/* RTC Regulator Register */ -++#define RTC_RGR_LOCK (1 << 31) /* Lock Bit */ -++#define RTC_RGR_ADJC_BIT 16 -++#define RTC_RGR_ADJC_MASK (0x3ff << RTC_RGR_ADJC_BIT) -++#define RTC_RGR_NC1HZ_BIT 0 -++#define RTC_RGR_NC1HZ_MASK (0xffff << RTC_RGR_NC1HZ_BIT) -++ -++/* Hibernate Control Register */ -++#define RTC_HCR_PD (1 << 0) /* Power Down */ -++ -++/* Hibernate Wakeup Filter Counter Register */ -++#define RTC_HWFCR_BIT 5 -++#define RTC_HWFCR_MASK (0x7ff << RTC_HWFCR_BIT) -++ -++/* Hibernate Reset Counter Register */ -++#define RTC_HRCR_BIT 5 -++#define RTC_HRCR_MASK (0x7f << RTC_HRCR_BIT) -++ -++/* Hibernate Wakeup Control Register */ -++#define RTC_HWCR_EALM (1 << 0) /* RTC alarm wakeup enable */ -++ -++/* Hibernate Wakeup Status Register */ -++#define RTC_HWRSR_HR (1 << 5) /* Hibernate reset */ -++#define RTC_HWRSR_PPR (1 << 4) /* PPR reset */ -++#define RTC_HWRSR_PIN (1 << 1) /* Wakeup pin status bit */ -++#define RTC_HWRSR_ALM (1 << 0) /* RTC alarm status bit */ -++ -++ -++/************************************************************************* -++ * CPM (Clock reset and Power control Management) -++ *************************************************************************/ -++#define CPM_CPCCR (CPM_BASE+0x00) -++#define CPM_CPPCR (CPM_BASE+0x10) -++#define CPM_I2SCDR (CPM_BASE+0x60) -++#define CPM_LPCDR (CPM_BASE+0x64) -++#define CPM_MSCCDR (CPM_BASE+0x68) -++#define CPM_UHCCDR (CPM_BASE+0x6C) -++#define CPM_SSICDR (CPM_BASE+0x74) -++ -++#define CPM_LCR (CPM_BASE+0x04) -++#define CPM_CLKGR (CPM_BASE+0x20) -++#define CPM_SCR (CPM_BASE+0x24) -++ -++#define CPM_HCR (CPM_BASE+0x30) -++#define CPM_HWFCR (CPM_BASE+0x34) -++#define CPM_HRCR (CPM_BASE+0x38) -++#define CPM_HWCR (CPM_BASE+0x3c) -++#define CPM_HWSR (CPM_BASE+0x40) -++#define CPM_HSPR (CPM_BASE+0x44) -++ -++#define CPM_RSR (CPM_BASE+0x08) -++ -++ -++#define REG_CPM_CPCCR REG32(CPM_CPCCR) -++#define REG_CPM_CPPCR REG32(CPM_CPPCR) -++#define REG_CPM_I2SCDR REG32(CPM_I2SCDR) -++#define REG_CPM_LPCDR REG32(CPM_LPCDR) -++#define REG_CPM_MSCCDR REG32(CPM_MSCCDR) -++#define REG_CPM_UHCCDR REG32(CPM_UHCCDR) -++#define REG_CPM_SSICDR REG32(CPM_SSICDR) -++ -++#define REG_CPM_LCR REG32(CPM_LCR) -++#define REG_CPM_CLKGR REG32(CPM_CLKGR) -++#define REG_CPM_SCR REG32(CPM_SCR) -++#define REG_CPM_HCR REG32(CPM_HCR) -++#define REG_CPM_HWFCR REG32(CPM_HWFCR) -++#define REG_CPM_HRCR REG32(CPM_HRCR) -++#define REG_CPM_HWCR REG32(CPM_HWCR) -++#define REG_CPM_HWSR REG32(CPM_HWSR) -++#define REG_CPM_HSPR REG32(CPM_HSPR) -++ -++#define REG_CPM_RSR REG32(CPM_RSR) -++ -++ -++/* Clock Control Register */ -++#define CPM_CPCCR_I2CS (1 << 31) -++#define CPM_CPCCR_CLKOEN (1 << 30) -++#define CPM_CPCCR_UCS (1 << 29) -++#define CPM_CPCCR_UDIV_BIT 23 -++#define CPM_CPCCR_UDIV_MASK (0x3f << CPM_CPCCR_UDIV_BIT) -++#define CPM_CPCCR_CE (1 << 22) -++#define CPM_CPCCR_PCS (1 << 21) -++#define CPM_CPCCR_LDIV_BIT 16 -++#define CPM_CPCCR_LDIV_MASK (0x1f << CPM_CPCCR_LDIV_BIT) -++#define CPM_CPCCR_MDIV_BIT 12 -++#define CPM_CPCCR_MDIV_MASK (0x0f << CPM_CPCCR_MDIV_BIT) -++#define CPM_CPCCR_PDIV_BIT 8 -++#define CPM_CPCCR_PDIV_MASK (0x0f << CPM_CPCCR_PDIV_BIT) -++#define CPM_CPCCR_HDIV_BIT 4 -++#define CPM_CPCCR_HDIV_MASK (0x0f << CPM_CPCCR_HDIV_BIT) -++#define CPM_CPCCR_CDIV_BIT 0 -++#define CPM_CPCCR_CDIV_MASK (0x0f << CPM_CPCCR_CDIV_BIT) -++ -++/* I2S Clock Divider Register */ -++#define CPM_I2SCDR_I2SDIV_BIT 0 -++#define CPM_I2SCDR_I2SDIV_MASK (0x1ff << CPM_I2SCDR_I2SDIV_BIT) -++ -++/* LCD Pixel Clock Divider Register */ -++#define CPM_LPCDR_PIXDIV_BIT 0 -++#define CPM_LPCDR_PIXDIV_MASK (0x7ff << CPM_LPCDR_PIXDIV_BIT) -++ -++/* MSC Clock Divider Register */ -++#define CPM_MSCCDR_MSCDIV_BIT 0 -++#define CPM_MSCCDR_MSCDIV_MASK (0x1f << CPM_MSCCDR_MSCDIV_BIT) -++ -++/* UHC Clock Divider Register */ -++#define CPM_UHCCDR_UHCDIV_BIT 0 -++#define CPM_UHCCDR_UHCDIV_MASK (0xf << CPM_UHCCDR_UHCDIV_BIT) -++ -++/* SSI Clock Divider Register */ -++#define CPM_SSICDR_SCS (1<<31) /* SSI clock source selection, 0:EXCLK, 1: PLL */ -++#define CPM_SSICDR_SSIDIV_BIT 0 -++#define CPM_SSICDR_SSIDIV_MASK (0xf << CPM_SSICDR_SSIDIV_BIT) -++ -++/* PLL Control Register */ -++#define CPM_CPPCR_PLLM_BIT 23 -++#define CPM_CPPCR_PLLM_MASK (0x1ff << CPM_CPPCR_PLLM_BIT) -++#define CPM_CPPCR_PLLN_BIT 18 -++#define CPM_CPPCR_PLLN_MASK (0x1f << CPM_CPPCR_PLLN_BIT) -++#define CPM_CPPCR_PLLOD_BIT 16 -++#define CPM_CPPCR_PLLOD_MASK (0x03 << CPM_CPPCR_PLLOD_BIT) -++#define CPM_CPPCR_PLLS (1 << 10) -++#define CPM_CPPCR_PLLBP (1 << 9) -++#define CPM_CPPCR_PLLEN (1 << 8) -++#define CPM_CPPCR_PLLST_BIT 0 -++#define CPM_CPPCR_PLLST_MASK (0xff << CPM_CPPCR_PLLST_BIT) -++ -++/* Low Power Control Register */ -++#define CPM_LCR_DOZE_DUTY_BIT 3 -++#define CPM_LCR_DOZE_DUTY_MASK (0x1f << CPM_LCR_DOZE_DUTY_BIT) -++#define CPM_LCR_DOZE_ON (1 << 2) -++#define CPM_LCR_LPM_BIT 0 -++#define CPM_LCR_LPM_MASK (0x3 << CPM_LCR_LPM_BIT) -++ #define CPM_LCR_LPM_IDLE (0x0 << CPM_LCR_LPM_BIT) -++ #define CPM_LCR_LPM_SLEEP (0x1 << CPM_LCR_LPM_BIT) -++ -++/* Clock Gate Register */ -++#define CPM_CLKGR_UART1 (1 << 15) -++#define CPM_CLKGR_UHC (1 << 14) -++#define CPM_CLKGR_IPU (1 << 13) -++#define CPM_CLKGR_DMAC (1 << 12) -++#define CPM_CLKGR_UDC (1 << 11) -++#define CPM_CLKGR_LCD (1 << 10) -++#define CPM_CLKGR_CIM (1 << 9) -++#define CPM_CLKGR_SADC (1 << 8) -++#define CPM_CLKGR_MSC (1 << 7) -++#define CPM_CLKGR_AIC1 (1 << 6) -++#define CPM_CLKGR_AIC2 (1 << 5) -++#define CPM_CLKGR_SSI (1 << 4) -++#define CPM_CLKGR_I2C (1 << 3) -++#define CPM_CLKGR_RTC (1 << 2) -++#define CPM_CLKGR_TCU (1 << 1) -++#define CPM_CLKGR_UART0 (1 << 0) -++ -++/* Sleep Control Register */ -++#define CPM_SCR_O1ST_BIT 8 -++#define CPM_SCR_O1ST_MASK (0xff << CPM_SCR_O1ST_BIT) -++#define CPM_SCR_USBPHY_ENABLE (1 << 6) -++#define CPM_SCR_OSC_ENABLE (1 << 4) -++ -++/* Hibernate Control Register */ -++#define CPM_HCR_PD (1 << 0) -++ -++/* Wakeup Filter Counter Register in Hibernate Mode */ -++#define CPM_HWFCR_TIME_BIT 0 -++#define CPM_HWFCR_TIME_MASK (0x3ff << CPM_HWFCR_TIME_BIT) -++ -++/* Reset Counter Register in Hibernate Mode */ -++#define CPM_HRCR_TIME_BIT 0 -++#define CPM_HRCR_TIME_MASK (0x7f << CPM_HRCR_TIME_BIT) -++ -++/* Wakeup Control Register in Hibernate Mode */ -++#define CPM_HWCR_WLE_LOW (0 << 2) -++#define CPM_HWCR_WLE_HIGH (1 << 2) -++#define CPM_HWCR_PIN_WAKEUP (1 << 1) -++#define CPM_HWCR_RTC_WAKEUP (1 << 0) -++ -++/* Wakeup Status Register in Hibernate Mode */ -++#define CPM_HWSR_WSR_PIN (1 << 1) -++#define CPM_HWSR_WSR_RTC (1 << 0) -++ -++/* Reset Status Register */ -++#define CPM_RSR_HR (1 << 2) -++#define CPM_RSR_WR (1 << 1) -++#define CPM_RSR_PR (1 << 0) -++ -++ -++/************************************************************************* -++ * TCU (Timer Counter Unit) -++ *************************************************************************/ -++#define TCU_TSR (TCU_BASE + 0x1C) /* Timer Stop Register */ -++#define TCU_TSSR (TCU_BASE + 0x2C) /* Timer Stop Set Register */ -++#define TCU_TSCR (TCU_BASE + 0x3C) /* Timer Stop Clear Register */ -++#define TCU_TER (TCU_BASE + 0x10) /* Timer Counter Enable Register */ -++#define TCU_TESR (TCU_BASE + 0x14) /* Timer Counter Enable Set Register */ -++#define TCU_TECR (TCU_BASE + 0x18) /* Timer Counter Enable Clear Register */ -++#define TCU_TFR (TCU_BASE + 0x20) /* Timer Flag Register */ -++#define TCU_TFSR (TCU_BASE + 0x24) /* Timer Flag Set Register */ -++#define TCU_TFCR (TCU_BASE + 0x28) /* Timer Flag Clear Register */ -++#define TCU_TMR (TCU_BASE + 0x30) /* Timer Mask Register */ -++#define TCU_TMSR (TCU_BASE + 0x34) /* Timer Mask Set Register */ -++#define TCU_TMCR (TCU_BASE + 0x38) /* Timer Mask Clear Register */ -++#define TCU_TDFR0 (TCU_BASE + 0x40) /* Timer Data Full Register */ -++#define TCU_TDHR0 (TCU_BASE + 0x44) /* Timer Data Half Register */ -++#define TCU_TCNT0 (TCU_BASE + 0x48) /* Timer Counter Register */ -++#define TCU_TCSR0 (TCU_BASE + 0x4C) /* Timer Control Register */ -++#define TCU_TDFR1 (TCU_BASE + 0x50) -++#define TCU_TDHR1 (TCU_BASE + 0x54) -++#define TCU_TCNT1 (TCU_BASE + 0x58) -++#define TCU_TCSR1 (TCU_BASE + 0x5C) -++#define TCU_TDFR2 (TCU_BASE + 0x60) -++#define TCU_TDHR2 (TCU_BASE + 0x64) -++#define TCU_TCNT2 (TCU_BASE + 0x68) -++#define TCU_TCSR2 (TCU_BASE + 0x6C) -++#define TCU_TDFR3 (TCU_BASE + 0x70) -++#define TCU_TDHR3 (TCU_BASE + 0x74) -++#define TCU_TCNT3 (TCU_BASE + 0x78) -++#define TCU_TCSR3 (TCU_BASE + 0x7C) -++#define TCU_TDFR4 (TCU_BASE + 0x80) -++#define TCU_TDHR4 (TCU_BASE + 0x84) -++#define TCU_TCNT4 (TCU_BASE + 0x88) -++#define TCU_TCSR4 (TCU_BASE + 0x8C) -++#define TCU_TDFR5 (TCU_BASE + 0x90) -++#define TCU_TDHR5 (TCU_BASE + 0x94) -++#define TCU_TCNT5 (TCU_BASE + 0x98) -++#define TCU_TCSR5 (TCU_BASE + 0x9C) -++ -++#define REG_TCU_TSR REG32(TCU_TSR) -++#define REG_TCU_TSSR REG32(TCU_TSSR) -++#define REG_TCU_TSCR REG32(TCU_TSCR) -++#define REG_TCU_TER REG8(TCU_TER) -++#define REG_TCU_TESR REG8(TCU_TESR) -++#define REG_TCU_TECR REG8(TCU_TECR) -++#define REG_TCU_TFR REG32(TCU_TFR) -++#define REG_TCU_TFSR REG32(TCU_TFSR) -++#define REG_TCU_TFCR REG32(TCU_TFCR) -++#define REG_TCU_TMR REG32(TCU_TMR) -++#define REG_TCU_TMSR REG32(TCU_TMSR) -++#define REG_TCU_TMCR REG32(TCU_TMCR) -++#define REG_TCU_TDFR0 REG16(TCU_TDFR0) -++#define REG_TCU_TDHR0 REG16(TCU_TDHR0) -++#define REG_TCU_TCNT0 REG16(TCU_TCNT0) -++#define REG_TCU_TCSR0 REG16(TCU_TCSR0) -++#define REG_TCU_TDFR1 REG16(TCU_TDFR1) -++#define REG_TCU_TDHR1 REG16(TCU_TDHR1) -++#define REG_TCU_TCNT1 REG16(TCU_TCNT1) -++#define REG_TCU_TCSR1 REG16(TCU_TCSR1) -++#define REG_TCU_TDFR2 REG16(TCU_TDFR2) -++#define REG_TCU_TDHR2 REG16(TCU_TDHR2) -++#define REG_TCU_TCNT2 REG16(TCU_TCNT2) -++#define REG_TCU_TCSR2 REG16(TCU_TCSR2) -++#define REG_TCU_TDFR3 REG16(TCU_TDFR3) -++#define REG_TCU_TDHR3 REG16(TCU_TDHR3) -++#define REG_TCU_TCNT3 REG16(TCU_TCNT3) -++#define REG_TCU_TCSR3 REG16(TCU_TCSR3) -++#define REG_TCU_TDFR4 REG16(TCU_TDFR4) -++#define REG_TCU_TDHR4 REG16(TCU_TDHR4) -++#define REG_TCU_TCNT4 REG16(TCU_TCNT4) -++#define REG_TCU_TCSR4 REG16(TCU_TCSR4) -++ -++// n = 0,1,2,3,4,5 -++#define TCU_TDFR(n) (TCU_BASE + (0x40 + (n)*0x10)) /* Timer Data Full Reg */ -++#define TCU_TDHR(n) (TCU_BASE + (0x44 + (n)*0x10)) /* Timer Data Half Reg */ -++#define TCU_TCNT(n) (TCU_BASE + (0x48 + (n)*0x10)) /* Timer Counter Reg */ -++#define TCU_TCSR(n) (TCU_BASE + (0x4C + (n)*0x10)) /* Timer Control Reg */ -++ -++#define REG_TCU_TDFR(n) REG16(TCU_TDFR((n))) -++#define REG_TCU_TDHR(n) REG16(TCU_TDHR((n))) -++#define REG_TCU_TCNT(n) REG16(TCU_TCNT((n))) -++#define REG_TCU_TCSR(n) REG16(TCU_TCSR((n))) -++ -++// Register definitions -++#define TCU_TCSR_PWM_SD (1 << 9) -++#define TCU_TCSR_PWM_INITL_HIGH (1 << 8) -++#define TCU_TCSR_PWM_EN (1 << 7) -++#define TCU_TCSR_PRESCALE_BIT 3 -++#define TCU_TCSR_PRESCALE_MASK (0x7 << TCU_TCSR_PRESCALE_BIT) -++ #define TCU_TCSR_PRESCALE1 (0x0 << TCU_TCSR_PRESCALE_BIT) -++ #define TCU_TCSR_PRESCALE4 (0x1 << TCU_TCSR_PRESCALE_BIT) -++ #define TCU_TCSR_PRESCALE16 (0x2 << TCU_TCSR_PRESCALE_BIT) -++ #define TCU_TCSR_PRESCALE64 (0x3 << TCU_TCSR_PRESCALE_BIT) -++ #define TCU_TCSR_PRESCALE256 (0x4 << TCU_TCSR_PRESCALE_BIT) -++ #define TCU_TCSR_PRESCALE1024 (0x5 << TCU_TCSR_PRESCALE_BIT) -++#define TCU_TCSR_EXT_EN (1 << 2) -++#define TCU_TCSR_RTC_EN (1 << 1) -++#define TCU_TCSR_PCK_EN (1 << 0) -++ -++#define TCU_TER_TCEN5 (1 << 5) -++#define TCU_TER_TCEN4 (1 << 4) -++#define TCU_TER_TCEN3 (1 << 3) -++#define TCU_TER_TCEN2 (1 << 2) -++#define TCU_TER_TCEN1 (1 << 1) -++#define TCU_TER_TCEN0 (1 << 0) -++ -++#define TCU_TESR_TCST5 (1 << 5) -++#define TCU_TESR_TCST4 (1 << 4) -++#define TCU_TESR_TCST3 (1 << 3) -++#define TCU_TESR_TCST2 (1 << 2) -++#define TCU_TESR_TCST1 (1 << 1) -++#define TCU_TESR_TCST0 (1 << 0) -++ -++#define TCU_TECR_TCCL5 (1 << 5) -++#define TCU_TECR_TCCL4 (1 << 4) -++#define TCU_TECR_TCCL3 (1 << 3) -++#define TCU_TECR_TCCL2 (1 << 2) -++#define TCU_TECR_TCCL1 (1 << 1) -++#define TCU_TECR_TCCL0 (1 << 0) -++ -++#define TCU_TFR_HFLAG5 (1 << 21) -++#define TCU_TFR_HFLAG4 (1 << 20) -++#define TCU_TFR_HFLAG3 (1 << 19) -++#define TCU_TFR_HFLAG2 (1 << 18) -++#define TCU_TFR_HFLAG1 (1 << 17) -++#define TCU_TFR_HFLAG0 (1 << 16) -++#define TCU_TFR_FFLAG5 (1 << 5) -++#define TCU_TFR_FFLAG4 (1 << 4) -++#define TCU_TFR_FFLAG3 (1 << 3) -++#define TCU_TFR_FFLAG2 (1 << 2) -++#define TCU_TFR_FFLAG1 (1 << 1) -++#define TCU_TFR_FFLAG0 (1 << 0) -++ -++#define TCU_TFSR_HFLAG5 (1 << 21) -++#define TCU_TFSR_HFLAG4 (1 << 20) -++#define TCU_TFSR_HFLAG3 (1 << 19) -++#define TCU_TFSR_HFLAG2 (1 << 18) -++#define TCU_TFSR_HFLAG1 (1 << 17) -++#define TCU_TFSR_HFLAG0 (1 << 16) -++#define TCU_TFSR_FFLAG5 (1 << 5) -++#define TCU_TFSR_FFLAG4 (1 << 4) -++#define TCU_TFSR_FFLAG3 (1 << 3) -++#define TCU_TFSR_FFLAG2 (1 << 2) -++#define TCU_TFSR_FFLAG1 (1 << 1) -++#define TCU_TFSR_FFLAG0 (1 << 0) -++ -++#define TCU_TFCR_HFLAG5 (1 << 21) -++#define TCU_TFCR_HFLAG4 (1 << 20) -++#define TCU_TFCR_HFLAG3 (1 << 19) -++#define TCU_TFCR_HFLAG2 (1 << 18) -++#define TCU_TFCR_HFLAG1 (1 << 17) -++#define TCU_TFCR_HFLAG0 (1 << 16) -++#define TCU_TFCR_FFLAG5 (1 << 5) -++#define TCU_TFCR_FFLAG4 (1 << 4) -++#define TCU_TFCR_FFLAG3 (1 << 3) -++#define TCU_TFCR_FFLAG2 (1 << 2) -++#define TCU_TFCR_FFLAG1 (1 << 1) -++#define TCU_TFCR_FFLAG0 (1 << 0) -++ -++#define TCU_TMR_HMASK5 (1 << 21) -++#define TCU_TMR_HMASK4 (1 << 20) -++#define TCU_TMR_HMASK3 (1 << 19) -++#define TCU_TMR_HMASK2 (1 << 18) -++#define TCU_TMR_HMASK1 (1 << 17) -++#define TCU_TMR_HMASK0 (1 << 16) -++#define TCU_TMR_FMASK5 (1 << 5) -++#define TCU_TMR_FMASK4 (1 << 4) -++#define TCU_TMR_FMASK3 (1 << 3) -++#define TCU_TMR_FMASK2 (1 << 2) -++#define TCU_TMR_FMASK1 (1 << 1) -++#define TCU_TMR_FMASK0 (1 << 0) -++ -++#define TCU_TMSR_HMST5 (1 << 21) -++#define TCU_TMSR_HMST4 (1 << 20) -++#define TCU_TMSR_HMST3 (1 << 19) -++#define TCU_TMSR_HMST2 (1 << 18) -++#define TCU_TMSR_HMST1 (1 << 17) -++#define TCU_TMSR_HMST0 (1 << 16) -++#define TCU_TMSR_FMST5 (1 << 5) -++#define TCU_TMSR_FMST4 (1 << 4) -++#define TCU_TMSR_FMST3 (1 << 3) -++#define TCU_TMSR_FMST2 (1 << 2) -++#define TCU_TMSR_FMST1 (1 << 1) -++#define TCU_TMSR_FMST0 (1 << 0) -++ -++#define TCU_TMCR_HMCL5 (1 << 21) -++#define TCU_TMCR_HMCL4 (1 << 20) -++#define TCU_TMCR_HMCL3 (1 << 19) -++#define TCU_TMCR_HMCL2 (1 << 18) -++#define TCU_TMCR_HMCL1 (1 << 17) -++#define TCU_TMCR_HMCL0 (1 << 16) -++#define TCU_TMCR_FMCL5 (1 << 5) -++#define TCU_TMCR_FMCL4 (1 << 4) -++#define TCU_TMCR_FMCL3 (1 << 3) -++#define TCU_TMCR_FMCL2 (1 << 2) -++#define TCU_TMCR_FMCL1 (1 << 1) -++#define TCU_TMCR_FMCL0 (1 << 0) -++ -++#define TCU_TSR_WDTS (1 << 16) -++#define TCU_TSR_STOP5 (1 << 5) -++#define TCU_TSR_STOP4 (1 << 4) -++#define TCU_TSR_STOP3 (1 << 3) -++#define TCU_TSR_STOP2 (1 << 2) -++#define TCU_TSR_STOP1 (1 << 1) -++#define TCU_TSR_STOP0 (1 << 0) -++ -++#define TCU_TSSR_WDTSS (1 << 16) -++#define TCU_TSSR_STPS5 (1 << 5) -++#define TCU_TSSR_STPS4 (1 << 4) -++#define TCU_TSSR_STPS3 (1 << 3) -++#define TCU_TSSR_STPS2 (1 << 2) -++#define TCU_TSSR_STPS1 (1 << 1) -++#define TCU_TSSR_STPS0 (1 << 0) -++ -++#define TCU_TSSR_WDTSC (1 << 16) -++#define TCU_TSSR_STPC5 (1 << 5) -++#define TCU_TSSR_STPC4 (1 << 4) -++#define TCU_TSSR_STPC3 (1 << 3) -++#define TCU_TSSR_STPC2 (1 << 2) -++#define TCU_TSSR_STPC1 (1 << 1) -++#define TCU_TSSR_STPC0 (1 << 0) -++ -++ -++/************************************************************************* -++ * WDT (WatchDog Timer) -++ *************************************************************************/ -++#define WDT_TDR (WDT_BASE + 0x00) -++#define WDT_TCER (WDT_BASE + 0x04) -++#define WDT_TCNT (WDT_BASE + 0x08) -++#define WDT_TCSR (WDT_BASE + 0x0C) -++ -++#define REG_WDT_TDR REG16(WDT_TDR) -++#define REG_WDT_TCER REG8(WDT_TCER) -++#define REG_WDT_TCNT REG16(WDT_TCNT) -++#define REG_WDT_TCSR REG16(WDT_TCSR) -++ -++// Register definition -++#define WDT_TCSR_PRESCALE_BIT 3 -++#define WDT_TCSR_PRESCALE_MASK (0x7 << WDT_TCSR_PRESCALE_BIT) -++ #define WDT_TCSR_PRESCALE1 (0x0 << WDT_TCSR_PRESCALE_BIT) -++ #define WDT_TCSR_PRESCALE4 (0x1 << WDT_TCSR_PRESCALE_BIT) -++ #define WDT_TCSR_PRESCALE16 (0x2 << WDT_TCSR_PRESCALE_BIT) -++ #define WDT_TCSR_PRESCALE64 (0x3 << WDT_TCSR_PRESCALE_BIT) -++ #define WDT_TCSR_PRESCALE256 (0x4 << WDT_TCSR_PRESCALE_BIT) -++ #define WDT_TCSR_PRESCALE1024 (0x5 << WDT_TCSR_PRESCALE_BIT) -++#define WDT_TCSR_EXT_EN (1 << 2) -++#define WDT_TCSR_RTC_EN (1 << 1) -++#define WDT_TCSR_PCK_EN (1 << 0) -++ -++#define WDT_TCER_TCEN (1 << 0) -++ -++ -++/************************************************************************* -++ * DMAC (DMA Controller) -++ *************************************************************************/ -++ -++#define MAX_DMA_NUM 6 /* max 6 channels */ -++ -++#define DMAC_DSAR(n) (DMAC_BASE + (0x00 + (n) * 0x20)) /* DMA source address */ -++#define DMAC_DTAR(n) (DMAC_BASE + (0x04 + (n) * 0x20)) /* DMA target address */ -++#define DMAC_DTCR(n) (DMAC_BASE + (0x08 + (n) * 0x20)) /* DMA transfer count */ -++#define DMAC_DRSR(n) (DMAC_BASE + (0x0c + (n) * 0x20)) /* DMA request source */ -++#define DMAC_DCCSR(n) (DMAC_BASE + (0x10 + (n) * 0x20)) /* DMA control/status */ -++#define DMAC_DCMD(n) (DMAC_BASE + (0x14 + (n) * 0x20)) /* DMA command */ -++#define DMAC_DDA(n) (DMAC_BASE + (0x18 + (n) * 0x20)) /* DMA descriptor address */ -++#define DMAC_DMACR (DMAC_BASE + 0x0300) /* DMA control register */ -++#define DMAC_DMAIPR (DMAC_BASE + 0x0304) /* DMA interrupt pending */ -++#define DMAC_DMADBR (DMAC_BASE + 0x0308) /* DMA doorbell */ -++#define DMAC_DMADBSR (DMAC_BASE + 0x030C) /* DMA doorbell set */ -++ -++// channel 0 -++#define DMAC_DSAR0 DMAC_DSAR(0) -++#define DMAC_DTAR0 DMAC_DTAR(0) -++#define DMAC_DTCR0 DMAC_DTCR(0) -++#define DMAC_DRSR0 DMAC_DRSR(0) -++#define DMAC_DCCSR0 DMAC_DCCSR(0) -++#define DMAC_DCMD0 DMAC_DCMD(0) -++#define DMAC_DDA0 DMAC_DDA(0) -++ -++// channel 1 -++#define DMAC_DSAR1 DMAC_DSAR(1) -++#define DMAC_DTAR1 DMAC_DTAR(1) -++#define DMAC_DTCR1 DMAC_DTCR(1) -++#define DMAC_DRSR1 DMAC_DRSR(1) -++#define DMAC_DCCSR1 DMAC_DCCSR(1) -++#define DMAC_DCMD1 DMAC_DCMD(1) -++#define DMAC_DDA1 DMAC_DDA(1) -++ -++// channel 2 -++#define DMAC_DSAR2 DMAC_DSAR(2) -++#define DMAC_DTAR2 DMAC_DTAR(2) -++#define DMAC_DTCR2 DMAC_DTCR(2) -++#define DMAC_DRSR2 DMAC_DRSR(2) -++#define DMAC_DCCSR2 DMAC_DCCSR(2) -++#define DMAC_DCMD2 DMAC_DCMD(2) -++#define DMAC_DDA2 DMAC_DDA(2) -++ -++// channel 3 -++#define DMAC_DSAR3 DMAC_DSAR(3) -++#define DMAC_DTAR3 DMAC_DTAR(3) -++#define DMAC_DTCR3 DMAC_DTCR(3) -++#define DMAC_DRSR3 DMAC_DRSR(3) -++#define DMAC_DCCSR3 DMAC_DCCSR(3) -++#define DMAC_DCMD3 DMAC_DCMD(3) -++#define DMAC_DDA3 DMAC_DDA(3) -++ -++// channel 4 -++#define DMAC_DSAR4 DMAC_DSAR(4) -++#define DMAC_DTAR4 DMAC_DTAR(4) -++#define DMAC_DTCR4 DMAC_DTCR(4) -++#define DMAC_DRSR4 DMAC_DRSR(4) -++#define DMAC_DCCSR4 DMAC_DCCSR(4) -++#define DMAC_DCMD4 DMAC_DCMD(4) -++#define DMAC_DDA4 DMAC_DDA(4) -++ -++// channel 5 -++#define DMAC_DSAR5 DMAC_DSAR(5) -++#define DMAC_DTAR5 DMAC_DTAR(5) -++#define DMAC_DTCR5 DMAC_DTCR(5) -++#define DMAC_DRSR5 DMAC_DRSR(5) -++#define DMAC_DCCSR5 DMAC_DCCSR(5) -++#define DMAC_DCMD5 DMAC_DCMD(5) -++#define DMAC_DDA5 DMAC_DDA(5) -++ -++#define REG_DMAC_DSAR(n) REG32(DMAC_DSAR((n))) -++#define REG_DMAC_DTAR(n) REG32(DMAC_DTAR((n))) -++#define REG_DMAC_DTCR(n) REG32(DMAC_DTCR((n))) -++#define REG_DMAC_DRSR(n) REG32(DMAC_DRSR((n))) -++#define REG_DMAC_DCCSR(n) REG32(DMAC_DCCSR((n))) -++#define REG_DMAC_DCMD(n) REG32(DMAC_DCMD((n))) -++#define REG_DMAC_DDA(n) REG32(DMAC_DDA((n))) -++#define REG_DMAC_DMACR REG32(DMAC_DMACR) -++#define REG_DMAC_DMAIPR REG32(DMAC_DMAIPR) -++#define REG_DMAC_DMADBR REG32(DMAC_DMADBR) -++#define REG_DMAC_DMADBSR REG32(DMAC_DMADBSR) -++ -++// DMA request source register -++#define DMAC_DRSR_RS_BIT 0 -++#define DMAC_DRSR_RS_MASK (0x1f << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_AUTO (8 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_UART0OUT (20 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_UART0IN (21 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_SSIOUT (22 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_SSIIN (23 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_AICOUT (24 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_AICIN (25 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_MSCOUT (26 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_MSCIN (27 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_TCU (28 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_SADC (29 << DMAC_DRSR_RS_BIT) -++ #define DMAC_DRSR_RS_SLCD (30 << DMAC_DRSR_RS_BIT) -++ -++// DMA channel control/status register -++#define DMAC_DCCSR_NDES (1 << 31) /* descriptor (0) or not (1) ? */ -++#define DMAC_DCCSR_CDOA_BIT 16 /* copy of DMA offset address */ -++#define DMAC_DCCSR_CDOA_MASK (0xff << DMAC_DCCSR_CDOA_BIT) -++#define DMAC_DCCSR_INV (1 << 6) /* descriptor invalid */ -++#define DMAC_DCCSR_AR (1 << 4) /* address error */ -++#define DMAC_DCCSR_TT (1 << 3) /* transfer terminated */ -++#define DMAC_DCCSR_HLT (1 << 2) /* DMA halted */ -++#define DMAC_DCCSR_CT (1 << 1) /* count terminated */ -++#define DMAC_DCCSR_EN (1 << 0) /* channel enable bit */ -++ -++// DMA channel command register -++#define DMAC_DCMD_SAI (1 << 23) /* source address increment */ -++#define DMAC_DCMD_DAI (1 << 22) /* dest address increment */ -++#define DMAC_DCMD_RDIL_BIT 16 /* request detection interval length */ -++#define DMAC_DCMD_RDIL_MASK (0x0f << DMAC_DCMD_RDIL_BIT) -++ #define DMAC_DCMD_RDIL_IGN (0 << DMAC_DCMD_RDIL_BIT) -++ #define DMAC_DCMD_RDIL_2 (1 << DMAC_DCMD_RDIL_BIT) -++ #define DMAC_DCMD_RDIL_4 (2 << DMAC_DCMD_RDIL_BIT) -++ #define DMAC_DCMD_RDIL_8 (3 << DMAC_DCMD_RDIL_BIT) -++ #define DMAC_DCMD_RDIL_12 (4 << DMAC_DCMD_RDIL_BIT) -++ #define DMAC_DCMD_RDIL_16 (5 << DMAC_DCMD_RDIL_BIT) -++ #define DMAC_DCMD_RDIL_20 (6 << DMAC_DCMD_RDIL_BIT) -++ #define DMAC_DCMD_RDIL_24 (7 << DMAC_DCMD_RDIL_BIT) -++ #define DMAC_DCMD_RDIL_28 (8 << DMAC_DCMD_RDIL_BIT) -++ #define DMAC_DCMD_RDIL_32 (9 << DMAC_DCMD_RDIL_BIT) -++ #define DMAC_DCMD_RDIL_48 (10 << DMAC_DCMD_RDIL_BIT) -++ #define DMAC_DCMD_RDIL_60 (11 << DMAC_DCMD_RDIL_BIT) -++ #define DMAC_DCMD_RDIL_64 (12 << DMAC_DCMD_RDIL_BIT) -++ #define DMAC_DCMD_RDIL_124 (13 << DMAC_DCMD_RDIL_BIT) -++ #define DMAC_DCMD_RDIL_128 (14 << DMAC_DCMD_RDIL_BIT) -++ #define DMAC_DCMD_RDIL_200 (15 << DMAC_DCMD_RDIL_BIT) -++#define DMAC_DCMD_SWDH_BIT 14 /* source port width */ -++#define DMAC_DCMD_SWDH_MASK (0x03 << DMAC_DCMD_SWDH_BIT) -++ #define DMAC_DCMD_SWDH_32 (0 << DMAC_DCMD_SWDH_BIT) -++ #define DMAC_DCMD_SWDH_8 (1 << DMAC_DCMD_SWDH_BIT) -++ #define DMAC_DCMD_SWDH_16 (2 << DMAC_DCMD_SWDH_BIT) -++#define DMAC_DCMD_DWDH_BIT 12 /* dest port width */ -++#define DMAC_DCMD_DWDH_MASK (0x03 << DMAC_DCMD_DWDH_BIT) -++ #define DMAC_DCMD_DWDH_32 (0 << DMAC_DCMD_DWDH_BIT) -++ #define DMAC_DCMD_DWDH_8 (1 << DMAC_DCMD_DWDH_BIT) -++ #define DMAC_DCMD_DWDH_16 (2 << DMAC_DCMD_DWDH_BIT) -++#define DMAC_DCMD_DS_BIT 8 /* transfer data size of a data unit */ -++#define DMAC_DCMD_DS_MASK (0x07 << DMAC_DCMD_DS_BIT) -++ #define DMAC_DCMD_DS_32BIT (0 << DMAC_DCMD_DS_BIT) -++ #define DMAC_DCMD_DS_8BIT (1 << DMAC_DCMD_DS_BIT) -++ #define DMAC_DCMD_DS_16BIT (2 << DMAC_DCMD_DS_BIT) -++ #define DMAC_DCMD_DS_16BYTE (3 << DMAC_DCMD_DS_BIT) -++ #define DMAC_DCMD_DS_32BYTE (4 << DMAC_DCMD_DS_BIT) -++#define DMAC_DCMD_TM (1 << 7) /* transfer mode: 0-single 1-block */ -++#define DMAC_DCMD_DES_V (1 << 4) /* descriptor valid flag */ -++#define DMAC_DCMD_DES_VM (1 << 3) /* descriptor valid mask: 1:support V-bit */ -++#define DMAC_DCMD_DES_VIE (1 << 2) /* DMA valid error interrupt enable */ -++#define DMAC_DCMD_TIE (1 << 1) /* DMA transfer interrupt enable */ -++#define DMAC_DCMD_LINK (1 << 0) /* descriptor link enable */ -++ -++// DMA descriptor address register -++#define DMAC_DDA_BASE_BIT 12 /* descriptor base address */ -++#define DMAC_DDA_BASE_MASK (0x0fffff << DMAC_DDA_BASE_BIT) -++#define DMAC_DDA_OFFSET_BIT 4 /* descriptor offset address */ -++#define DMAC_DDA_OFFSET_MASK (0x0ff << DMAC_DDA_OFFSET_BIT) -++ -++// DMA control register -++#define DMAC_DMACR_PR_BIT 8 /* channel priority mode */ -++#define DMAC_DMACR_PR_MASK (0x03 << DMAC_DMACR_PR_BIT) -++ #define DMAC_DMACR_PR_012345 (0 << DMAC_DMACR_PR_BIT) -++ #define DMAC_DMACR_PR_023145 (1 << DMAC_DMACR_PR_BIT) -++ #define DMAC_DMACR_PR_201345 (2 << DMAC_DMACR_PR_BIT) -++ #define DMAC_DMACR_PR_RR (3 << DMAC_DMACR_PR_BIT) /* round robin */ -++#define DMAC_DMACR_HLT (1 << 3) /* DMA halt flag */ -++#define DMAC_DMACR_AR (1 << 2) /* address error flag */ -++#define DMAC_DMACR_DMAE (1 << 0) /* DMA enable bit */ -++ -++// DMA doorbell register -++#define DMAC_DMADBR_DB5 (1 << 5) /* doorbell for channel 5 */ -++#define DMAC_DMADBR_DB4 (1 << 5) /* doorbell for channel 4 */ -++#define DMAC_DMADBR_DB3 (1 << 5) /* doorbell for channel 3 */ -++#define DMAC_DMADBR_DB2 (1 << 5) /* doorbell for channel 2 */ -++#define DMAC_DMADBR_DB1 (1 << 5) /* doorbell for channel 1 */ -++#define DMAC_DMADBR_DB0 (1 << 5) /* doorbell for channel 0 */ -++ -++// DMA doorbell set register -++#define DMAC_DMADBSR_DBS5 (1 << 5) /* enable doorbell for channel 5 */ -++#define DMAC_DMADBSR_DBS4 (1 << 5) /* enable doorbell for channel 4 */ -++#define DMAC_DMADBSR_DBS3 (1 << 5) /* enable doorbell for channel 3 */ -++#define DMAC_DMADBSR_DBS2 (1 << 5) /* enable doorbell for channel 2 */ -++#define DMAC_DMADBSR_DBS1 (1 << 5) /* enable doorbell for channel 1 */ -++#define DMAC_DMADBSR_DBS0 (1 << 5) /* enable doorbell for channel 0 */ -++ -++// DMA interrupt pending register -++#define DMAC_DMAIPR_CIRQ5 (1 << 5) /* irq pending status for channel 5 */ -++#define DMAC_DMAIPR_CIRQ4 (1 << 4) /* irq pending status for channel 4 */ -++#define DMAC_DMAIPR_CIRQ3 (1 << 3) /* irq pending status for channel 3 */ -++#define DMAC_DMAIPR_CIRQ2 (1 << 2) /* irq pending status for channel 2 */ -++#define DMAC_DMAIPR_CIRQ1 (1 << 1) /* irq pending status for channel 1 */ -++#define DMAC_DMAIPR_CIRQ0 (1 << 0) /* irq pending status for channel 0 */ -++ -++ -++/************************************************************************* -++ * GPIO (General-Purpose I/O Ports) -++ *************************************************************************/ -++#define MAX_GPIO_NUM 128 -++ -++//n = 0,1,2,3 -++#define GPIO_PXPIN(n) (GPIO_BASE + (0x00 + (n)*0x100)) /* PIN Level Register */ -++#define GPIO_PXDAT(n) (GPIO_BASE + (0x10 + (n)*0x100)) /* Port Data Register */ -++#define GPIO_PXDATS(n) (GPIO_BASE + (0x14 + (n)*0x100)) /* Port Data Set Register */ -++#define GPIO_PXDATC(n) (GPIO_BASE + (0x18 + (n)*0x100)) /* Port Data Clear Register */ -++#define GPIO_PXIM(n) (GPIO_BASE + (0x20 + (n)*0x100)) /* Interrupt Mask Register */ -++#define GPIO_PXIMS(n) (GPIO_BASE + (0x24 + (n)*0x100)) /* Interrupt Mask Set Reg */ -++#define GPIO_PXIMC(n) (GPIO_BASE + (0x28 + (n)*0x100)) /* Interrupt Mask Clear Reg */ -++#define GPIO_PXPE(n) (GPIO_BASE + (0x30 + (n)*0x100)) /* Pull Enable Register */ -++#define GPIO_PXPES(n) (GPIO_BASE + (0x34 + (n)*0x100)) /* Pull Enable Set Reg. */ -++#define GPIO_PXPEC(n) (GPIO_BASE + (0x38 + (n)*0x100)) /* Pull Enable Clear Reg. */ -++#define GPIO_PXFUN(n) (GPIO_BASE + (0x40 + (n)*0x100)) /* Function Register */ -++#define GPIO_PXFUNS(n) (GPIO_BASE + (0x44 + (n)*0x100)) /* Function Set Register */ -++#define GPIO_PXFUNC(n) (GPIO_BASE + (0x48 + (n)*0x100)) /* Function Clear Register */ -++#define GPIO_PXSEL(n) (GPIO_BASE + (0x50 + (n)*0x100)) /* Select Register */ -++#define GPIO_PXSELS(n) (GPIO_BASE + (0x54 + (n)*0x100)) /* Select Set Register */ -++#define GPIO_PXSELC(n) (GPIO_BASE + (0x58 + (n)*0x100)) /* Select Clear Register */ -++#define GPIO_PXDIR(n) (GPIO_BASE + (0x60 + (n)*0x100)) /* Direction Register */ -++#define GPIO_PXDIRS(n) (GPIO_BASE + (0x64 + (n)*0x100)) /* Direction Set Register */ -++#define GPIO_PXDIRC(n) (GPIO_BASE + (0x68 + (n)*0x100)) /* Direction Clear Register */ -++#define GPIO_PXTRG(n) (GPIO_BASE + (0x70 + (n)*0x100)) /* Trigger Register */ -++#define GPIO_PXTRGS(n) (GPIO_BASE + (0x74 + (n)*0x100)) /* Trigger Set Register */ -++#define GPIO_PXTRGC(n) (GPIO_BASE + (0x78 + (n)*0x100)) /* Trigger Set Register */ -++#define GPIO_PXFLG(n) (GPIO_BASE + (0x80 + (n)*0x100)) /* Port Flag Register */ -++#define GPIO_PXFLGC(n) (GPIO_BASE + (0x14 + (n)*0x100)) /* Port Flag Clear Register */ -++ -++#define REG_GPIO_PXPIN(n) REG32(GPIO_PXPIN((n))) /* PIN level */ -++#define REG_GPIO_PXDAT(n) REG32(GPIO_PXDAT((n))) /* 1: interrupt pending */ -++#define REG_GPIO_PXDATS(n) REG32(GPIO_PXDATS((n))) -++#define REG_GPIO_PXDATC(n) REG32(GPIO_PXDATC((n))) -++#define REG_GPIO_PXIM(n) REG32(GPIO_PXIM((n))) /* 1: mask pin interrupt */ -++#define REG_GPIO_PXIMS(n) REG32(GPIO_PXIMS((n))) -++#define REG_GPIO_PXIMC(n) REG32(GPIO_PXIMC((n))) -++#define REG_GPIO_PXPE(n) REG32(GPIO_PXPE((n))) /* 1: disable pull up/down */ -++#define REG_GPIO_PXPES(n) REG32(GPIO_PXPES((n))) -++#define REG_GPIO_PXPEC(n) REG32(GPIO_PXPEC((n))) -++#define REG_GPIO_PXFUN(n) REG32(GPIO_PXFUN((n))) /* 0:GPIO or intr, 1:FUNC */ -++#define REG_GPIO_PXFUNS(n) REG32(GPIO_PXFUNS((n))) -++#define REG_GPIO_PXFUNC(n) REG32(GPIO_PXFUNC((n))) -++#define REG_GPIO_PXSEL(n) REG32(GPIO_PXSEL((n))) /* 0:GPIO/Fun0,1:intr/fun1*/ -++#define REG_GPIO_PXSELS(n) REG32(GPIO_PXSELS((n))) -++#define REG_GPIO_PXSELC(n) REG32(GPIO_PXSELC((n))) -++#define REG_GPIO_PXDIR(n) REG32(GPIO_PXDIR((n))) /* 0:input/low-level-trig/falling-edge-trig, 1:output/high-level-trig/rising-edge-trig */ -++#define REG_GPIO_PXDIRS(n) REG32(GPIO_PXDIRS((n))) -++#define REG_GPIO_PXDIRC(n) REG32(GPIO_PXDIRC((n))) -++#define REG_GPIO_PXTRG(n) REG32(GPIO_PXTRG((n))) /* 0:level-trigger, 1:edge-trigger */ -++#define REG_GPIO_PXTRGS(n) REG32(GPIO_PXTRGS((n))) -++#define REG_GPIO_PXTRGC(n) REG32(GPIO_PXTRGC((n))) -++#define REG_GPIO_PXFLG(n) REG32(GPIO_PXFLG((n))) /* interrupt flag */ -++#define REG_GPIO_PXFLGC(n) REG32(GPIO_PXFLGC((n))) /* interrupt flag */ -++ -++ -++/************************************************************************* -++ * UART -++ *************************************************************************/ -++ -++#define IRDA_BASE UART0_BASE -++#define UART_BASE UART0_BASE -++#define UART_OFF 0x1000 -++ -++/* Register Offset */ -++#define OFF_RDR (0x00) /* R 8b H'xx */ -++#define OFF_TDR (0x00) /* W 8b H'xx */ -++#define OFF_DLLR (0x00) /* RW 8b H'00 */ -++#define OFF_DLHR (0x04) /* RW 8b H'00 */ -++#define OFF_IER (0x04) /* RW 8b H'00 */ -++#define OFF_ISR (0x08) /* R 8b H'01 */ -++#define OFF_FCR (0x08) /* W 8b H'00 */ -++#define OFF_LCR (0x0C) /* RW 8b H'00 */ -++#define OFF_MCR (0x10) /* RW 8b H'00 */ -++#define OFF_LSR (0x14) /* R 8b H'00 */ -++#define OFF_MSR (0x18) /* R 8b H'00 */ -++#define OFF_SPR (0x1C) /* RW 8b H'00 */ -++#define OFF_SIRCR (0x20) /* RW 8b H'00, UART0 */ -++#define OFF_UMR (0x24) /* RW 8b H'00, UART M Register */ -++#define OFF_UACR (0x28) /* RW 8b H'00, UART Add Cycle Register */ -++ -++/* Register Address */ -++#define UART0_RDR (UART0_BASE + OFF_RDR) -++#define UART0_TDR (UART0_BASE + OFF_TDR) -++#define UART0_DLLR (UART0_BASE + OFF_DLLR) -++#define UART0_DLHR (UART0_BASE + OFF_DLHR) -++#define UART0_IER (UART0_BASE + OFF_IER) -++#define UART0_ISR (UART0_BASE + OFF_ISR) -++#define UART0_FCR (UART0_BASE + OFF_FCR) -++#define UART0_LCR (UART0_BASE + OFF_LCR) -++#define UART0_MCR (UART0_BASE + OFF_MCR) -++#define UART0_LSR (UART0_BASE + OFF_LSR) -++#define UART0_MSR (UART0_BASE + OFF_MSR) -++#define UART0_SPR (UART0_BASE + OFF_SPR) -++#define UART0_SIRCR (UART0_BASE + OFF_SIRCR) -++#define UART0_UMR (UART0_BASE + OFF_UMR) -++#define UART0_UACR (UART0_BASE + OFF_UACR) -++ -++/* -++ * Define macros for UARTIER -++ * UART Interrupt Enable Register -++ */ -++#define UARTIER_RIE (1 << 0) /* 0: receive fifo full interrupt disable */ -++#define UARTIER_TIE (1 << 1) /* 0: transmit fifo empty interrupt disable */ -++#define UARTIER_RLIE (1 << 2) /* 0: receive line status interrupt disable */ -++#define UARTIER_MIE (1 << 3) /* 0: modem status interrupt disable */ -++#define UARTIER_RTIE (1 << 4) /* 0: receive timeout interrupt disable */ -++ -++/* -++ * Define macros for UARTISR -++ * UART Interrupt Status Register -++ */ -++#define UARTISR_IP (1 << 0) /* 0: interrupt is pending 1: no interrupt */ -++#define UARTISR_IID (7 << 1) /* Source of Interrupt */ -++#define UARTISR_IID_MSI (0 << 1) /* Modem status interrupt */ -++#define UARTISR_IID_THRI (1 << 1) /* Transmitter holding register empty */ -++#define UARTISR_IID_RDI (2 << 1) /* Receiver data interrupt */ -++#define UARTISR_IID_RLSI (3 << 1) /* Receiver line status interrupt */ -++#define UARTISR_IID_RTO (6 << 1) /* Receive timeout */ -++#define UARTISR_FFMS (3 << 6) /* FIFO mode select, set when UARTFCR.FE is set to 1 */ -++#define UARTISR_FFMS_NO_FIFO (0 << 6) -++#define UARTISR_FFMS_FIFO_MODE (3 << 6) -++ -++/* -++ * Define macros for UARTFCR -++ * UART FIFO Control Register -++ */ -++#define UARTFCR_FE (1 << 0) /* 0: non-FIFO mode 1: FIFO mode */ -++#define UARTFCR_RFLS (1 << 1) /* write 1 to flush receive FIFO */ -++#define UARTFCR_TFLS (1 << 2) /* write 1 to flush transmit FIFO */ -++#define UARTFCR_DMS (1 << 3) /* 0: disable DMA mode */ -++#define UARTFCR_UUE (1 << 4) /* 0: disable UART */ -++#define UARTFCR_RTRG (3 << 6) /* Receive FIFO Data Trigger */ -++#define UARTFCR_RTRG_1 (0 << 6) -++#define UARTFCR_RTRG_4 (1 << 6) -++#define UARTFCR_RTRG_8 (2 << 6) -++#define UARTFCR_RTRG_15 (3 << 6) -++ -++/* -++ * Define macros for UARTLCR -++ * UART Line Control Register -++ */ -++#define UARTLCR_WLEN (3 << 0) /* word length */ -++#define UARTLCR_WLEN_5 (0 << 0) -++#define UARTLCR_WLEN_6 (1 << 0) -++#define UARTLCR_WLEN_7 (2 << 0) -++#define UARTLCR_WLEN_8 (3 << 0) -++#define UARTLCR_STOP (1 << 2) /* 0: 1 stop bit when word length is 5,6,7,8 -++ 1: 1.5 stop bits when 5; 2 stop bits when 6,7,8 */ -++#define UARTLCR_STOP1 (0 << 2) -++#define UARTLCR_STOP2 (1 << 2) -++#define UARTLCR_PE (1 << 3) /* 0: parity disable */ -++#define UARTLCR_PROE (1 << 4) /* 0: even parity 1: odd parity */ -++#define UARTLCR_SPAR (1 << 5) /* 0: sticky parity disable */ -++#define UARTLCR_SBRK (1 << 6) /* write 0 normal, write 1 send break */ -++#define UARTLCR_DLAB (1 << 7) /* 0: access UARTRDR/TDR/IER 1: access UARTDLLR/DLHR */ -++ -++/* -++ * Define macros for UARTLSR -++ * UART Line Status Register -++ */ -++#define UARTLSR_DR (1 << 0) /* 0: receive FIFO is empty 1: receive data is ready */ -++#define UARTLSR_ORER (1 << 1) /* 0: no overrun error */ -++#define UARTLSR_PER (1 << 2) /* 0: no parity error */ -++#define UARTLSR_FER (1 << 3) /* 0; no framing error */ -++#define UARTLSR_BRK (1 << 4) /* 0: no break detected 1: receive a break signal */ -++#define UARTLSR_TDRQ (1 << 5) /* 1: transmit FIFO half "empty" */ -++#define UARTLSR_TEMT (1 << 6) /* 1: transmit FIFO and shift registers empty */ -++#define UARTLSR_RFER (1 << 7) /* 0: no receive error 1: receive error in FIFO mode */ -++ -++/* -++ * Define macros for UARTMCR -++ * UART Modem Control Register -++ */ -++#define UARTMCR_RTS (1 << 1) /* 0: RTS_ output high, 1: RTS_ output low */ -++#define UARTMCR_LOOP (1 << 4) /* 0: normal 1: loopback mode */ -++#define UARTMCR_MCE (1 << 7) /* 0: modem function is disable */ -++ -++/* -++ * Define macros for UARTMSR -++ * UART Modem Status Register -++ */ -++#define UARTMSR_CCTS (1 << 0) /* 1: a change on CTS_ pin */ -++#define UARTMSR_CTS (1 << 4) /* 0: CTS_ pin is high */ -++ -++/* -++ * Define macros for SIRCR -++ * Slow IrDA Control Register -++ */ -++#define SIRCR_TSIRE (1 << 0) /* 0: transmitter is in UART mode 1: SIR mode */ -++#define SIRCR_RSIRE (1 << 1) /* 0: receiver is in UART mode 1: SIR mode */ -++#define SIRCR_TPWS (1 << 2) /* 0: transmit 0 pulse width is 3/16 of bit length -++ 1: 0 pulse width is 1.6us for 115.2Kbps */ -++#define SIRCR_TDPL (1 << 3) /* 0: encoder generates a positive pulse for 0 */ -++#define SIRCR_RDPL (1 << 4) /* 0: decoder interprets positive pulse as 0 */ -++ -++ -++/************************************************************************* -++ * AIC (AC97/I2S Controller) -++ *************************************************************************/ -++#define AIC_FR (AIC_BASE + 0x000) -++#define AIC_CR (AIC_BASE + 0x004) -++#define AIC_ACCR1 (AIC_BASE + 0x008) -++#define AIC_ACCR2 (AIC_BASE + 0x00C) -++#define AIC_I2SCR (AIC_BASE + 0x010) -++#define AIC_SR (AIC_BASE + 0x014) -++#define AIC_ACSR (AIC_BASE + 0x018) -++#define AIC_I2SSR (AIC_BASE + 0x01C) -++#define AIC_ACCAR (AIC_BASE + 0x020) -++#define AIC_ACCDR (AIC_BASE + 0x024) -++#define AIC_ACSAR (AIC_BASE + 0x028) -++#define AIC_ACSDR (AIC_BASE + 0x02C) -++#define AIC_I2SDIV (AIC_BASE + 0x030) -++#define AIC_DR (AIC_BASE + 0x034) -++ -++#define REG_AIC_FR REG32(AIC_FR) -++#define REG_AIC_CR REG32(AIC_CR) -++#define REG_AIC_ACCR1 REG32(AIC_ACCR1) -++#define REG_AIC_ACCR2 REG32(AIC_ACCR2) -++#define REG_AIC_I2SCR REG32(AIC_I2SCR) -++#define REG_AIC_SR REG32(AIC_SR) -++#define REG_AIC_ACSR REG32(AIC_ACSR) -++#define REG_AIC_I2SSR REG32(AIC_I2SSR) -++#define REG_AIC_ACCAR REG32(AIC_ACCAR) -++#define REG_AIC_ACCDR REG32(AIC_ACCDR) -++#define REG_AIC_ACSAR REG32(AIC_ACSAR) -++#define REG_AIC_ACSDR REG32(AIC_ACSDR) -++#define REG_AIC_I2SDIV REG32(AIC_I2SDIV) -++#define REG_AIC_DR REG32(AIC_DR) -++ -++/* AIC Controller Configuration Register (AIC_FR) */ -++ -++#define AIC_FR_RFTH_BIT 12 /* Receive FIFO Threshold */ -++#define AIC_FR_RFTH_MASK (0xf << AIC_FR_RFTH_BIT) -++#define AIC_FR_TFTH_BIT 8 /* Transmit FIFO Threshold */ -++#define AIC_FR_TFTH_MASK (0xf << AIC_FR_TFTH_BIT) -++#define AIC_FR_LSMP (1 << 6) /* Play Zero sample or last sample */ -++#define AIC_FR_ICDC (1 << 5) /* External(0) or Internal CODEC(1) */ -++#define AIC_FR_AUSEL (1 << 4) /* AC97(0) or I2S/MSB-justified(1) */ -++#define AIC_FR_RST (1 << 3) /* AIC registers reset */ -++#define AIC_FR_BCKD (1 << 2) /* I2S BIT_CLK direction, 0:input,1:output */ -++#define AIC_FR_SYNCD (1 << 1) /* I2S SYNC direction, 0:input,1:output */ -++#define AIC_FR_ENB (1 << 0) /* AIC enable bit */ -++ -++/* AIC Controller Common Control Register (AIC_CR) */ -++ -++#define AIC_CR_OSS_BIT 19 /* Output Sample Size from memory (AIC V2 only) */ -++#define AIC_CR_OSS_MASK (0x7 << AIC_CR_OSS_BIT) -++ #define AIC_CR_OSS_8BIT (0x0 << AIC_CR_OSS_BIT) -++ #define AIC_CR_OSS_16BIT (0x1 << AIC_CR_OSS_BIT) -++ #define AIC_CR_OSS_18BIT (0x2 << AIC_CR_OSS_BIT) -++ #define AIC_CR_OSS_20BIT (0x3 << AIC_CR_OSS_BIT) -++ #define AIC_CR_OSS_24BIT (0x4 << AIC_CR_OSS_BIT) -++#define AIC_CR_ISS_BIT 16 /* Input Sample Size from memory (AIC V2 only) */ -++#define AIC_CR_ISS_MASK (0x7 << AIC_CR_ISS_BIT) -++ #define AIC_CR_ISS_8BIT (0x0 << AIC_CR_ISS_BIT) -++ #define AIC_CR_ISS_16BIT (0x1 << AIC_CR_ISS_BIT) -++ #define AIC_CR_ISS_18BIT (0x2 << AIC_CR_ISS_BIT) -++ #define AIC_CR_ISS_20BIT (0x3 << AIC_CR_ISS_BIT) -++ #define AIC_CR_ISS_24BIT (0x4 << AIC_CR_ISS_BIT) -++#define AIC_CR_RDMS (1 << 15) /* Receive DMA enable */ -++#define AIC_CR_TDMS (1 << 14) /* Transmit DMA enable */ -++#define AIC_CR_M2S (1 << 11) /* Mono to Stereo enable */ -++#define AIC_CR_ENDSW (1 << 10) /* Endian switch enable */ -++#define AIC_CR_AVSTSU (1 << 9) /* Signed <-> Unsigned toggle enable */ -++#define AIC_CR_FLUSH (1 << 8) /* Flush FIFO */ -++#define AIC_CR_EROR (1 << 6) /* Enable ROR interrupt */ -++#define AIC_CR_ETUR (1 << 5) /* Enable TUR interrupt */ -++#define AIC_CR_ERFS (1 << 4) /* Enable RFS interrupt */ -++#define AIC_CR_ETFS (1 << 3) /* Enable TFS interrupt */ -++#define AIC_CR_ENLBF (1 << 2) /* Enable Loopback Function */ -++#define AIC_CR_ERPL (1 << 1) /* Enable Playback Function */ -++#define AIC_CR_EREC (1 << 0) /* Enable Record Function */ -++ -++/* AIC Controller AC-link Control Register 1 (AIC_ACCR1) */ -++ -++#define AIC_ACCR1_RS_BIT 16 /* Receive Valid Slots */ -++#define AIC_ACCR1_RS_MASK (0x3ff << AIC_ACCR1_RS_BIT) -++ #define AIC_ACCR1_RS_SLOT12 (1 << 25) /* Slot 12 valid bit */ -++ #define AIC_ACCR1_RS_SLOT11 (1 << 24) /* Slot 11 valid bit */ -++ #define AIC_ACCR1_RS_SLOT10 (1 << 23) /* Slot 10 valid bit */ -++ #define AIC_ACCR1_RS_SLOT9 (1 << 22) /* Slot 9 valid bit, LFE */ -++ #define AIC_ACCR1_RS_SLOT8 (1 << 21) /* Slot 8 valid bit, Surround Right */ -++ #define AIC_ACCR1_RS_SLOT7 (1 << 20) /* Slot 7 valid bit, Surround Left */ -++ #define AIC_ACCR1_RS_SLOT6 (1 << 19) /* Slot 6 valid bit, PCM Center */ -++ #define AIC_ACCR1_RS_SLOT5 (1 << 18) /* Slot 5 valid bit */ -++ #define AIC_ACCR1_RS_SLOT4 (1 << 17) /* Slot 4 valid bit, PCM Right */ -++ #define AIC_ACCR1_RS_SLOT3 (1 << 16) /* Slot 3 valid bit, PCM Left */ -++#define AIC_ACCR1_XS_BIT 0 /* Transmit Valid Slots */ -++#define AIC_ACCR1_XS_MASK (0x3ff << AIC_ACCR1_XS_BIT) -++ #define AIC_ACCR1_XS_SLOT12 (1 << 9) /* Slot 12 valid bit */ -++ #define AIC_ACCR1_XS_SLOT11 (1 << 8) /* Slot 11 valid bit */ -++ #define AIC_ACCR1_XS_SLOT10 (1 << 7) /* Slot 10 valid bit */ -++ #define AIC_ACCR1_XS_SLOT9 (1 << 6) /* Slot 9 valid bit, LFE */ -++ #define AIC_ACCR1_XS_SLOT8 (1 << 5) /* Slot 8 valid bit, Surround Right */ -++ #define AIC_ACCR1_XS_SLOT7 (1 << 4) /* Slot 7 valid bit, Surround Left */ -++ #define AIC_ACCR1_XS_SLOT6 (1 << 3) /* Slot 6 valid bit, PCM Center */ -++ #define AIC_ACCR1_XS_SLOT5 (1 << 2) /* Slot 5 valid bit */ -++ #define AIC_ACCR1_XS_SLOT4 (1 << 1) /* Slot 4 valid bit, PCM Right */ -++ #define AIC_ACCR1_XS_SLOT3 (1 << 0) /* Slot 3 valid bit, PCM Left */ -++ -++/* AIC Controller AC-link Control Register 2 (AIC_ACCR2) */ -++ -++#define AIC_ACCR2_ERSTO (1 << 18) /* Enable RSTO interrupt */ -++#define AIC_ACCR2_ESADR (1 << 17) /* Enable SADR interrupt */ -++#define AIC_ACCR2_ECADT (1 << 16) /* Enable CADT interrupt */ -++#define AIC_ACCR2_OASS_BIT 8 /* Output Sample Size for AC-link */ -++#define AIC_ACCR2_OASS_MASK (0x3 << AIC_ACCR2_OASS_BIT) -++ #define AIC_ACCR2_OASS_20BIT (0 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 20-bit */ -++ #define AIC_ACCR2_OASS_18BIT (1 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 18-bit */ -++ #define AIC_ACCR2_OASS_16BIT (2 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 16-bit */ -++ #define AIC_ACCR2_OASS_8BIT (3 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 8-bit */ -++#define AIC_ACCR2_IASS_BIT 6 /* Output Sample Size for AC-link */ -++#define AIC_ACCR2_IASS_MASK (0x3 << AIC_ACCR2_IASS_BIT) -++ #define AIC_ACCR2_IASS_20BIT (0 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 20-bit */ -++ #define AIC_ACCR2_IASS_18BIT (1 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 18-bit */ -++ #define AIC_ACCR2_IASS_16BIT (2 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 16-bit */ -++ #define AIC_ACCR2_IASS_8BIT (3 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 8-bit */ -++#define AIC_ACCR2_SO (1 << 3) /* SDATA_OUT output value */ -++#define AIC_ACCR2_SR (1 << 2) /* RESET# pin level */ -++#define AIC_ACCR2_SS (1 << 1) /* SYNC pin level */ -++#define AIC_ACCR2_SA (1 << 0) /* SYNC and SDATA_OUT alternation */ -++ -++/* AIC Controller I2S/MSB-justified Control Register (AIC_I2SCR) */ -++ -++#define AIC_I2SCR_STPBK (1 << 12) /* Stop BIT_CLK for I2S/MSB-justified */ -++#define AIC_I2SCR_WL_BIT 1 /* Input/Output Sample Size for I2S/MSB-justified */ -++#define AIC_I2SCR_WL_MASK (0x7 << AIC_I2SCR_WL_BIT) -++ #define AIC_I2SCR_WL_24BIT (0 << AIC_I2SCR_WL_BIT) /* Word Length is 24 bit */ -++ #define AIC_I2SCR_WL_20BIT (1 << AIC_I2SCR_WL_BIT) /* Word Length is 20 bit */ -++ #define AIC_I2SCR_WL_18BIT (2 << AIC_I2SCR_WL_BIT) /* Word Length is 18 bit */ -++ #define AIC_I2SCR_WL_16BIT (3 << AIC_I2SCR_WL_BIT) /* Word Length is 16 bit */ -++ #define AIC_I2SCR_WL_8BIT (4 << AIC_I2SCR_WL_BIT) /* Word Length is 8 bit */ -++#define AIC_I2SCR_AMSL (1 << 0) /* 0:I2S, 1:MSB-justified */ -++ -++/* AIC Controller FIFO Status Register (AIC_SR) */ -++ -++#define AIC_SR_RFL_BIT 24 /* Receive FIFO Level */ -++#define AIC_SR_RFL_MASK (0x3f << AIC_SR_RFL_BIT) -++#define AIC_SR_TFL_BIT 8 /* Transmit FIFO level */ -++#define AIC_SR_TFL_MASK (0x3f << AIC_SR_TFL_BIT) -++#define AIC_SR_ROR (1 << 6) /* Receive FIFO Overrun */ -++#define AIC_SR_TUR (1 << 5) /* Transmit FIFO Underrun */ -++#define AIC_SR_RFS (1 << 4) /* Receive FIFO Service Request */ -++#define AIC_SR_TFS (1 << 3) /* Transmit FIFO Service Request */ -++ -++/* AIC Controller AC-link Status Register (AIC_ACSR) */ -++ -++#define AIC_ACSR_SLTERR (1 << 21) /* Slot Error Flag */ -++#define AIC_ACSR_CRDY (1 << 20) /* External CODEC Ready Flag */ -++#define AIC_ACSR_CLPM (1 << 19) /* External CODEC low power mode flag */ -++#define AIC_ACSR_RSTO (1 << 18) /* External CODEC regs read status timeout */ -++#define AIC_ACSR_SADR (1 << 17) /* External CODEC regs status addr and data received */ -++#define AIC_ACSR_CADT (1 << 16) /* Command Address and Data Transmitted */ -++ -++/* AIC Controller I2S/MSB-justified Status Register (AIC_I2SSR) */ -++ -++#define AIC_I2SSR_BSY (1 << 2) /* AIC Busy in I2S/MSB-justified format */ -++ -++/* AIC Controller AC97 codec Command Address Register (AIC_ACCAR) */ -++ -++#define AIC_ACCAR_CAR_BIT 0 -++#define AIC_ACCAR_CAR_MASK (0xfffff << AIC_ACCAR_CAR_BIT) -++ -++/* AIC Controller AC97 codec Command Data Register (AIC_ACCDR) */ -++ -++#define AIC_ACCDR_CDR_BIT 0 -++#define AIC_ACCDR_CDR_MASK (0xfffff << AIC_ACCDR_CDR_BIT) -++ -++/* AIC Controller AC97 codec Status Address Register (AIC_ACSAR) */ -++ -++#define AIC_ACSAR_SAR_BIT 0 -++#define AIC_ACSAR_SAR_MASK (0xfffff << AIC_ACSAR_SAR_BIT) -++ -++/* AIC Controller AC97 codec Status Data Register (AIC_ACSDR) */ -++ -++#define AIC_ACSDR_SDR_BIT 0 -++#define AIC_ACSDR_SDR_MASK (0xfffff << AIC_ACSDR_SDR_BIT) -++ -++/* AIC Controller I2S/MSB-justified Clock Divider Register (AIC_I2SDIV) */ -++ -++#define AIC_I2SDIV_DIV_BIT 0 -++#define AIC_I2SDIV_DIV_MASK (0x7f << AIC_I2SDIV_DIV_BIT) -++ #define AIC_I2SDIV_BITCLK_3072KHZ (0x0C << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 3.072MHz */ -++ #define AIC_I2SDIV_BITCLK_2836KHZ (0x0D << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 2.836MHz */ -++ #define AIC_I2SDIV_BITCLK_1418KHZ (0x1A << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.418MHz */ -++ #define AIC_I2SDIV_BITCLK_1024KHZ (0x24 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.024MHz */ -++ #define AIC_I2SDIV_BITCLK_7089KHZ (0x34 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 708.92KHz */ -++ #define AIC_I2SDIV_BITCLK_512KHZ (0x48 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 512.00KHz */ -++ -++ -++/************************************************************************* -++ * ICDC (Internal CODEC) -++ *************************************************************************/ -++#define ICDC_CR (ICDC_BASE + 0x0400) /* ICDC Control Register */ -++#define ICDC_APWAIT (ICDC_BASE + 0x0404) /* Anti-Pop WAIT Stage Timing Control Register */ -++#define ICDC_APPRE (ICDC_BASE + 0x0408) /* Anti-Pop HPEN-PRE Stage Timing Control Register */ -++#define ICDC_APHPEN (ICDC_BASE + 0x040C) /* Anti-Pop HPEN Stage Timing Control Register */ -++#define ICDC_APSR (ICDC_BASE + 0x0410) /* Anti-Pop Status Register */ -++#define ICDC_CDCCR1 (ICDC_BASE + 0x0080) -++#define ICDC_CDCCR2 (ICDC_BASE + 0x0084) -++ -++#define REG_ICDC_CR REG32(ICDC_CR) -++#define REG_ICDC_APWAIT REG32(ICDC_APWAIT) -++#define REG_ICDC_APPRE REG32(ICDC_APPRE) -++#define REG_ICDC_APHPEN REG32(ICDC_APHPEN) -++#define REG_ICDC_APSR REG32(ICDC_APSR) -++#define REG_ICDC_CDCCR1 REG32(ICDC_CDCCR1) -++#define REG_ICDC_CDCCR2 REG32(ICDC_CDCCR2) -++ -++/* ICDC Control Register */ -++#define ICDC_CR_LINVOL_BIT 24 /* LINE Input Volume Gain: GAIN=LINVOL*1.5-34.5 */ -++#define ICDC_CR_LINVOL_MASK (0x1f << ICDC_CR_LINVOL_BIT) -++#define ICDC_CR_ASRATE_BIT 20 /* Audio Sample Rate */ -++#define ICDC_CR_ASRATE_MASK (0x0f << ICDC_CR_ASRATE_BIT) -++ #define ICDC_CR_ASRATE_8000 (0x0 << ICDC_CR_ASRATE_BIT) -++ #define ICDC_CR_ASRATE_11025 (0x1 << ICDC_CR_ASRATE_BIT) -++ #define ICDC_CR_ASRATE_12000 (0x2 << ICDC_CR_ASRATE_BIT) -++ #define ICDC_CR_ASRATE_16000 (0x3 << ICDC_CR_ASRATE_BIT) -++ #define ICDC_CR_ASRATE_22050 (0x4 << ICDC_CR_ASRATE_BIT) -++ #define ICDC_CR_ASRATE_24000 (0x5 << ICDC_CR_ASRATE_BIT) -++ #define ICDC_CR_ASRATE_32000 (0x6 << ICDC_CR_ASRATE_BIT) -++ #define ICDC_CR_ASRATE_44100 (0x7 << ICDC_CR_ASRATE_BIT) -++ #define ICDC_CR_ASRATE_48000 (0x8 << ICDC_CR_ASRATE_BIT) -++#define ICDC_CR_MICBG_BIT 18 /* MIC Boost Gain */ -++#define ICDC_CR_MICBG_MASK (0x3 << ICDC_CR_MICBG_BIT) -++ #define ICDC_CR_MICBG_0DB (0x0 << ICDC_CR_MICBG_BIT) -++ #define ICDC_CR_MICBG_6DB (0x1 << ICDC_CR_MICBG_BIT) -++ #define ICDC_CR_MICBG_12DB (0x2 << ICDC_CR_MICBG_BIT) -++ #define ICDC_CR_MICBG_20DB (0x3 << ICDC_CR_MICBG_BIT) -++#define ICDC_CR_HPVOL_BIT 16 /* Headphone Volume Gain */ -++#define ICDC_CR_HPVOL_MASK (0x3 << ICDC_CR_HPVOL_BIT) -++ #define ICDC_CR_HPVOL_0DB (0x0 << ICDC_CR_HPVOL_BIT) -++ #define ICDC_CR_HPVOL_2DB (0x1 << ICDC_CR_HPVOL_BIT) -++ #define ICDC_CR_HPVOL_4DB (0x2 << ICDC_CR_HPVOL_BIT) -++ #define ICDC_CR_HPVOL_6DB (0x3 << ICDC_CR_HPVOL_BIT) -++#define ICDC_CR_ELINEIN (1 << 13) /* Enable LINE Input */ -++#define ICDC_CR_EMIC (1 << 12) /* Enable MIC Input */ -++#define ICDC_CR_SW1ON (1 << 11) /* Switch 1 in CODEC is on */ -++#define ICDC_CR_EADC (1 << 10) /* Enable ADC */ -++#define ICDC_CR_SW2ON (1 << 9) /* Switch 2 in CODEC is on */ -++#define ICDC_CR_EDAC (1 << 8) /* Enable DAC */ -++#define ICDC_CR_HPMUTE (1 << 5) /* Headphone Mute */ -++#define ICDC_CR_HPTON (1 << 4) /* Headphone Amplifier Trun On */ -++#define ICDC_CR_HPTOFF (1 << 3) /* Headphone Amplifier Trun Off */ -++#define ICDC_CR_TAAP (1 << 2) /* Turn Around of the Anti-Pop Procedure */ -++#define ICDC_CR_EAP (1 << 1) /* Enable Anti-Pop Procedure */ -++#define ICDC_CR_SUSPD (1 << 0) /* CODEC Suspend */ -++ -++/* Anti-Pop WAIT Stage Timing Control Register */ -++#define ICDC_APWAIT_WAITSN_BIT 0 -++#define ICDC_APWAIT_WAITSN_MASK (0x7ff << ICDC_APWAIT_WAITSN_BIT) -++ -++/* Anti-Pop HPEN-PRE Stage Timing Control Register */ -++#define ICDC_APPRE_PRESN_BIT 0 -++#define ICDC_APPRE_PRESN_MASK (0x1ff << ICDC_APPRE_PRESN_BIT) -++ -++/* Anti-Pop HPEN Stage Timing Control Register */ -++#define ICDC_APHPEN_HPENSN_BIT 0 -++#define ICDC_APHPEN_HPENSN_MASK (0x3fff << ICDC_APHPEN_HPENSN_BIT) -++ -++/* Anti-Pop Status Register */ -++#define ICDC_SR_HPST_BIT 14 /* Headphone Amplifier State */ -++#define ICDC_SR_HPST_MASK (0x7 << ICDC_SR_HPST_BIT) -++#define ICDC_SR_HPST_HP_OFF (0x0 << ICDC_SR_HPST_BIT) /* HP amplifier is off */ -++#define ICDC_SR_HPST_TON_WAIT (0x1 << ICDC_SR_HPST_BIT) /* wait state in turn-on */ -++ #define ICDC_SR_HPST_TON_PRE (0x2 << ICDC_SR_HPST_BIT) /* pre-enable state in turn-on */ -++#define ICDC_SR_HPST_TON_HPEN (0x3 << ICDC_SR_HPST_BIT) /* HP enable state in turn-on */ -++ #define ICDC_SR_HPST_TOFF_HPEN (0x4 << ICDC_SR_HPST_BIT) /* HP enable state in turn-off */ -++ #define ICDC_SR_HPST_TOFF_PRE (0x5 << ICDC_SR_HPST_BIT) /* pre-enable state in turn-off */ -++ #define ICDC_SR_HPST_TOFF_WAIT (0x6 << ICDC_SR_HPST_BIT) /* wait state in turn-off */ -++ #define ICDC_SR_HPST_HP_ON (0x7 << ICDC_SR_HPST_BIT) /* HP amplifier is on */ -++#define ICDC_SR_SNCNT_BIT 0 /* Sample Number Counter */ -++#define ICDC_SR_SNCNT_MASK (0x3fff << ICDC_SR_SNCNT_BIT) -++ -++ -++/************************************************************************* -++ * I2C -++ *************************************************************************/ -++#define I2C_DR (I2C_BASE + 0x000) -++#define I2C_CR (I2C_BASE + 0x004) -++#define I2C_SR (I2C_BASE + 0x008) -++#define I2C_GR (I2C_BASE + 0x00C) -++ -++#define REG_I2C_DR REG8(I2C_DR) -++#define REG_I2C_CR REG8(I2C_CR) -++#define REG_I2C_SR REG8(I2C_SR) -++#define REG_I2C_GR REG16(I2C_GR) -++ -++/* I2C Control Register (I2C_CR) */ -++ -++#define I2C_CR_IEN (1 << 4) -++#define I2C_CR_STA (1 << 3) -++#define I2C_CR_STO (1 << 2) -++#define I2C_CR_AC (1 << 1) -++#define I2C_CR_I2CE (1 << 0) -++ -++/* I2C Status Register (I2C_SR) */ -++ -++#define I2C_SR_STX (1 << 4) -++#define I2C_SR_BUSY (1 << 3) -++#define I2C_SR_TEND (1 << 2) -++#define I2C_SR_DRF (1 << 1) -++#define I2C_SR_ACKF (1 << 0) -++ -++ -++/************************************************************************* -++ * SSI -++ *************************************************************************/ -++#define SSI_DR (SSI_BASE + 0x000) -++#define SSI_CR0 (SSI_BASE + 0x004) -++#define SSI_CR1 (SSI_BASE + 0x008) -++#define SSI_SR (SSI_BASE + 0x00C) -++#define SSI_ITR (SSI_BASE + 0x010) -++#define SSI_ICR (SSI_BASE + 0x014) -++#define SSI_GR (SSI_BASE + 0x018) -++ -++#define REG_SSI_DR REG32(SSI_DR) -++#define REG_SSI_CR0 REG16(SSI_CR0) -++#define REG_SSI_CR1 REG32(SSI_CR1) -++#define REG_SSI_SR REG32(SSI_SR) -++#define REG_SSI_ITR REG16(SSI_ITR) -++#define REG_SSI_ICR REG8(SSI_ICR) -++#define REG_SSI_GR REG16(SSI_GR) -++ -++/* SSI Data Register (SSI_DR) */ -++ -++#define SSI_DR_GPC_BIT 0 -++#define SSI_DR_GPC_MASK (0x1ff << SSI_DR_GPC_BIT) -++ -++/* SSI Control Register 0 (SSI_CR0) */ -++ -++#define SSI_CR0_SSIE (1 << 15) -++#define SSI_CR0_TIE (1 << 14) -++#define SSI_CR0_RIE (1 << 13) -++#define SSI_CR0_TEIE (1 << 12) -++#define SSI_CR0_REIE (1 << 11) -++#define SSI_CR0_LOOP (1 << 10) -++#define SSI_CR0_RFINE (1 << 9) -++#define SSI_CR0_RFINC (1 << 8) -++#define SSI_CR0_FSEL (1 << 6) -++#define SSI_CR0_TFLUSH (1 << 2) -++#define SSI_CR0_RFLUSH (1 << 1) -++#define SSI_CR0_DISREV (1 << 0) -++ -++/* SSI Control Register 1 (SSI_CR1) */ -++ -++#define SSI_CR1_FRMHL_BIT 30 -++#define SSI_CR1_FRMHL_MASK (0x3 << SSI_CR1_FRMHL_BIT) -++ #define SSI_CR1_FRMHL_CELOW_CE2LOW (0 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is low valid */ -++ #define SSI_CR1_FRMHL_CEHIGH_CE2LOW (1 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is low valid */ -++ #define SSI_CR1_FRMHL_CELOW_CE2HIGH (2 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is high valid */ -++ #define SSI_CR1_FRMHL_CEHIGH_CE2HIGH (3 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is high valid */ -++#define SSI_CR1_TFVCK_BIT 28 -++#define SSI_CR1_TFVCK_MASK (0x3 << SSI_CR1_TFVCK_BIT) -++ #define SSI_CR1_TFVCK_0 (0 << SSI_CR1_TFVCK_BIT) -++ #define SSI_CR1_TFVCK_1 (1 << SSI_CR1_TFVCK_BIT) -++ #define SSI_CR1_TFVCK_2 (2 << SSI_CR1_TFVCK_BIT) -++ #define SSI_CR1_TFVCK_3 (3 << SSI_CR1_TFVCK_BIT) -++#define SSI_CR1_TCKFI_BIT 26 -++#define SSI_CR1_TCKFI_MASK (0x3 << SSI_CR1_TCKFI_BIT) -++ #define SSI_CR1_TCKFI_0 (0 << SSI_CR1_TCKFI_BIT) -++ #define SSI_CR1_TCKFI_1 (1 << SSI_CR1_TCKFI_BIT) -++ #define SSI_CR1_TCKFI_2 (2 << SSI_CR1_TCKFI_BIT) -++ #define SSI_CR1_TCKFI_3 (3 << SSI_CR1_TCKFI_BIT) -++#define SSI_CR1_LFST (1 << 25) -++#define SSI_CR1_ITFRM (1 << 24) -++#define SSI_CR1_UNFIN (1 << 23) -++#define SSI_CR1_MULTS (1 << 22) -++#define SSI_CR1_FMAT_BIT 20 -++#define SSI_CR1_FMAT_MASK (0x3 << SSI_CR1_FMAT_BIT) -++ #define SSI_CR1_FMAT_SPI (0 << SSI_CR1_FMAT_BIT) /* Motorola¡¯s SPI format */ -++ #define SSI_CR1_FMAT_SSP (1 << SSI_CR1_FMAT_BIT) /* TI's SSP format */ -++ #define SSI_CR1_FMAT_MW1 (2 << SSI_CR1_FMAT_BIT) /* National Microwire 1 format */ -++ #define SSI_CR1_FMAT_MW2 (3 << SSI_CR1_FMAT_BIT) /* National Microwire 2 format */ -++#define SSI_CR1_TTRG_BIT 16 -++#define SSI_CR1_TTRG_MASK (0xf << SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_1 (0 << SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_8 (1 << SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_16 (2 << SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_24 (3 << SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_32 (4 << SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_40 (5 << SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_48 (6 << SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_56 (7 << SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_64 (8 << SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_72 (9 << SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_80 (10<< SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_88 (11<< SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_96 (12<< SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_104 (13<< SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_112 (14<< SSI_CR1_TTRG_BIT) -++ #define SSI_CR1_TTRG_120 (15<< SSI_CR1_TTRG_BIT) -++#define SSI_CR1_MCOM_BIT 12 -++#define SSI_CR1_MCOM_MASK (0xf << SSI_CR1_MCOM_BIT) -++ #define SSI_CR1_MCOM_1BIT (0x0 << SSI_CR1_MCOM_BIT) /* 1-bit command selected */ -++ #define SSI_CR1_MCOM_2BIT (0x1 << SSI_CR1_MCOM_BIT) /* 2-bit command selected */ -++ #define SSI_CR1_MCOM_3BIT (0x2 << SSI_CR1_MCOM_BIT) /* 3-bit command selected */ -++ #define SSI_CR1_MCOM_4BIT (0x3 << SSI_CR1_MCOM_BIT) /* 4-bit command selected */ -++ #define SSI_CR1_MCOM_5BIT (0x4 << SSI_CR1_MCOM_BIT) /* 5-bit command selected */ -++ #define SSI_CR1_MCOM_6BIT (0x5 << SSI_CR1_MCOM_BIT) /* 6-bit command selected */ -++ #define SSI_CR1_MCOM_7BIT (0x6 << SSI_CR1_MCOM_BIT) /* 7-bit command selected */ -++ #define SSI_CR1_MCOM_8BIT (0x7 << SSI_CR1_MCOM_BIT) /* 8-bit command selected */ -++ #define SSI_CR1_MCOM_9BIT (0x8 << SSI_CR1_MCOM_BIT) /* 9-bit command selected */ -++ #define SSI_CR1_MCOM_10BIT (0x9 << SSI_CR1_MCOM_BIT) /* 10-bit command selected */ -++ #define SSI_CR1_MCOM_11BIT (0xA << SSI_CR1_MCOM_BIT) /* 11-bit command selected */ -++ #define SSI_CR1_MCOM_12BIT (0xB << SSI_CR1_MCOM_BIT) /* 12-bit command selected */ -++ #define SSI_CR1_MCOM_13BIT (0xC << SSI_CR1_MCOM_BIT) /* 13-bit command selected */ -++ #define SSI_CR1_MCOM_14BIT (0xD << SSI_CR1_MCOM_BIT) /* 14-bit command selected */ -++ #define SSI_CR1_MCOM_15BIT (0xE << SSI_CR1_MCOM_BIT) /* 15-bit command selected */ -++ #define SSI_CR1_MCOM_16BIT (0xF << SSI_CR1_MCOM_BIT) /* 16-bit command selected */ -++#define SSI_CR1_RTRG_BIT 8 -++#define SSI_CR1_RTRG_MASK (0xf << SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_1 (0 << SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_8 (1 << SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_16 (2 << SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_24 (3 << SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_32 (4 << SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_40 (5 << SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_48 (6 << SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_56 (7 << SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_64 (8 << SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_72 (9 << SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_80 (10<< SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_88 (11<< SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_96 (12<< SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_104 (13<< SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_112 (14<< SSI_CR1_RTRG_BIT) -++ #define SSI_CR1_RTRG_120 (15<< SSI_CR1_RTRG_BIT) -++#define SSI_CR1_FLEN_BIT 4 -++#define SSI_CR1_FLEN_MASK (0xf << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_2BIT (0x0 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_3BIT (0x1 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_4BIT (0x2 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_5BIT (0x3 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_6BIT (0x4 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_7BIT (0x5 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_8BIT (0x6 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_9BIT (0x7 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_10BIT (0x8 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_11BIT (0x9 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_12BIT (0xA << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_13BIT (0xB << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_14BIT (0xC << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_15BIT (0xD << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_16BIT (0xE << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_17BIT (0xF << SSI_CR1_FLEN_BIT) -++#define SSI_CR1_PHA (1 << 1) -++#define SSI_CR1_POL (1 << 0) -++ -++/* SSI Status Register (SSI_SR) */ -++ -++#define SSI_SR_TFIFONUM_BIT 16 -++#define SSI_SR_TFIFONUM_MASK (0xff << SSI_SR_TFIFONUM_BIT) -++#define SSI_SR_RFIFONUM_BIT 8 -++#define SSI_SR_RFIFONUM_MASK (0xff << SSI_SR_RFIFONUM_BIT) -++#define SSI_SR_END (1 << 7) -++#define SSI_SR_BUSY (1 << 6) -++#define SSI_SR_TFF (1 << 5) -++#define SSI_SR_RFE (1 << 4) -++#define SSI_SR_TFHE (1 << 3) -++#define SSI_SR_RFHF (1 << 2) -++#define SSI_SR_UNDR (1 << 1) -++#define SSI_SR_OVER (1 << 0) -++ -++/* SSI Interval Time Control Register (SSI_ITR) */ -++ -++#define SSI_ITR_CNTCLK (1 << 15) -++#define SSI_ITR_IVLTM_BIT 0 -++#define SSI_ITR_IVLTM_MASK (0x7fff << SSI_ITR_IVLTM_BIT) -++ -++ -++/************************************************************************* -++ * MSC -++ *************************************************************************/ -++#define MSC_STRPCL (MSC_BASE + 0x000) -++#define MSC_STAT (MSC_BASE + 0x004) -++#define MSC_CLKRT (MSC_BASE + 0x008) -++#define MSC_CMDAT (MSC_BASE + 0x00C) -++#define MSC_RESTO (MSC_BASE + 0x010) -++#define MSC_RDTO (MSC_BASE + 0x014) -++#define MSC_BLKLEN (MSC_BASE + 0x018) -++#define MSC_NOB (MSC_BASE + 0x01C) -++#define MSC_SNOB (MSC_BASE + 0x020) -++#define MSC_IMASK (MSC_BASE + 0x024) -++#define MSC_IREG (MSC_BASE + 0x028) -++#define MSC_CMD (MSC_BASE + 0x02C) -++#define MSC_ARG (MSC_BASE + 0x030) -++#define MSC_RES (MSC_BASE + 0x034) -++#define MSC_RXFIFO (MSC_BASE + 0x038) -++#define MSC_TXFIFO (MSC_BASE + 0x03C) -++ -++#define REG_MSC_STRPCL REG16(MSC_STRPCL) -++#define REG_MSC_STAT REG32(MSC_STAT) -++#define REG_MSC_CLKRT REG16(MSC_CLKRT) -++#define REG_MSC_CMDAT REG32(MSC_CMDAT) -++#define REG_MSC_RESTO REG16(MSC_RESTO) -++#define REG_MSC_RDTO REG16(MSC_RDTO) -++#define REG_MSC_BLKLEN REG16(MSC_BLKLEN) -++#define REG_MSC_NOB REG16(MSC_NOB) -++#define REG_MSC_SNOB REG16(MSC_SNOB) -++#define REG_MSC_IMASK REG16(MSC_IMASK) -++#define REG_MSC_IREG REG16(MSC_IREG) -++#define REG_MSC_CMD REG8(MSC_CMD) -++#define REG_MSC_ARG REG32(MSC_ARG) -++#define REG_MSC_RES REG16(MSC_RES) -++#define REG_MSC_RXFIFO REG32(MSC_RXFIFO) -++#define REG_MSC_TXFIFO REG32(MSC_TXFIFO) -++ -++/* MSC Clock and Control Register (MSC_STRPCL) */ -++ -++#define MSC_STRPCL_EXIT_MULTIPLE (1 << 7) -++#define MSC_STRPCL_EXIT_TRANSFER (1 << 6) -++#define MSC_STRPCL_START_READWAIT (1 << 5) -++#define MSC_STRPCL_STOP_READWAIT (1 << 4) -++#define MSC_STRPCL_RESET (1 << 3) -++#define MSC_STRPCL_START_OP (1 << 2) -++#define MSC_STRPCL_CLOCK_CONTROL_BIT 0 -++#define MSC_STRPCL_CLOCK_CONTROL_MASK (0x3 << MSC_STRPCL_CLOCK_CONTROL_BIT) -++ #define MSC_STRPCL_CLOCK_CONTROL_STOP (0x1 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Stop MMC/SD clock */ -++ #define MSC_STRPCL_CLOCK_CONTROL_START (0x2 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Start MMC/SD clock */ -++ -++/* MSC Status Register (MSC_STAT) */ -++ -++#define MSC_STAT_IS_RESETTING (1 << 15) -++#define MSC_STAT_SDIO_INT_ACTIVE (1 << 14) -++#define MSC_STAT_PRG_DONE (1 << 13) -++#define MSC_STAT_DATA_TRAN_DONE (1 << 12) -++#define MSC_STAT_END_CMD_RES (1 << 11) -++#define MSC_STAT_DATA_FIFO_AFULL (1 << 10) -++#define MSC_STAT_IS_READWAIT (1 << 9) -++#define MSC_STAT_CLK_EN (1 << 8) -++#define MSC_STAT_DATA_FIFO_FULL (1 << 7) -++#define MSC_STAT_DATA_FIFO_EMPTY (1 << 6) -++#define MSC_STAT_CRC_RES_ERR (1 << 5) -++#define MSC_STAT_CRC_READ_ERROR (1 << 4) -++#define MSC_STAT_CRC_WRITE_ERROR_BIT 2 -++#define MSC_STAT_CRC_WRITE_ERROR_MASK (0x3 << MSC_STAT_CRC_WRITE_ERROR_BIT) -++ #define MSC_STAT_CRC_WRITE_ERROR_NO (0 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No error on transmission of data */ -++ #define MSC_STAT_CRC_WRITE_ERROR (1 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* Card observed erroneous transmission of data */ -++ #define MSC_STAT_CRC_WRITE_ERROR_NOSTS (2 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No CRC status is sent back */ -++#define MSC_STAT_TIME_OUT_RES (1 << 1) -++#define MSC_STAT_TIME_OUT_READ (1 << 0) -++ -++/* MSC Bus Clock Control Register (MSC_CLKRT) */ -++ -++#define MSC_CLKRT_CLK_RATE_BIT 0 -++#define MSC_CLKRT_CLK_RATE_MASK (0x7 << MSC_CLKRT_CLK_RATE_BIT) -++ #define MSC_CLKRT_CLK_RATE_DIV_1 (0x0 << MSC_CLKRT_CLK_RATE_BIT) /* CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_2 (0x1 << MSC_CLKRT_CLK_RATE_BIT) /* 1/2 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_4 (0x2 << MSC_CLKRT_CLK_RATE_BIT) /* 1/4 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_8 (0x3 << MSC_CLKRT_CLK_RATE_BIT) /* 1/8 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_16 (0x4 << MSC_CLKRT_CLK_RATE_BIT) /* 1/16 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_32 (0x5 << MSC_CLKRT_CLK_RATE_BIT) /* 1/32 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_64 (0x6 << MSC_CLKRT_CLK_RATE_BIT) /* 1/64 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_128 (0x7 << MSC_CLKRT_CLK_RATE_BIT) /* 1/128 of CLK_SRC */ -++ -++/* MSC Command Sequence Control Register (MSC_CMDAT) */ -++ -++#define MSC_CMDAT_IO_ABORT (1 << 11) -++#define MSC_CMDAT_BUS_WIDTH_BIT 9 -++#define MSC_CMDAT_BUS_WIDTH_MASK (0x3 << MSC_CMDAT_BUS_WIDTH_BIT) -++ #define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) /* 1-bit data bus */ -++ #define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) /* 4-bit data bus */ -++ #define CMDAT_BUS_WIDTH1 (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) -++ #define CMDAT_BUS_WIDTH4 (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) -++#define MSC_CMDAT_DMA_EN (1 << 8) -++#define MSC_CMDAT_INIT (1 << 7) -++#define MSC_CMDAT_BUSY (1 << 6) -++#define MSC_CMDAT_STREAM_BLOCK (1 << 5) -++#define MSC_CMDAT_WRITE (1 << 4) -++#define MSC_CMDAT_READ (0 << 4) -++#define MSC_CMDAT_DATA_EN (1 << 3) -++#define MSC_CMDAT_RESPONSE_BIT 0 -++#define MSC_CMDAT_RESPONSE_MASK (0x7 << MSC_CMDAT_RESPONSE_BIT) -++ #define MSC_CMDAT_RESPONSE_NONE (0x0 << MSC_CMDAT_RESPONSE_BIT) /* No response */ -++ #define MSC_CMDAT_RESPONSE_R1 (0x1 << MSC_CMDAT_RESPONSE_BIT) /* Format R1 and R1b */ -++ #define MSC_CMDAT_RESPONSE_R2 (0x2 << MSC_CMDAT_RESPONSE_BIT) /* Format R2 */ -++ #define MSC_CMDAT_RESPONSE_R3 (0x3 << MSC_CMDAT_RESPONSE_BIT) /* Format R3 */ -++ #define MSC_CMDAT_RESPONSE_R4 (0x4 << MSC_CMDAT_RESPONSE_BIT) /* Format R4 */ -++ #define MSC_CMDAT_RESPONSE_R5 (0x5 << MSC_CMDAT_RESPONSE_BIT) /* Format R5 */ -++ #define MSC_CMDAT_RESPONSE_R6 (0x6 << MSC_CMDAT_RESPONSE_BIT) /* Format R6 */ -++ -++#define CMDAT_DMA_EN (1 << 8) -++#define CMDAT_INIT (1 << 7) -++#define CMDAT_BUSY (1 << 6) -++#define CMDAT_STREAM (1 << 5) -++#define CMDAT_WRITE (1 << 4) -++#define CMDAT_DATA_EN (1 << 3) -++ -++/* MSC Interrupts Mask Register (MSC_IMASK) */ -++ -++#define MSC_IMASK_SDIO (1 << 7) -++#define MSC_IMASK_TXFIFO_WR_REQ (1 << 6) -++#define MSC_IMASK_RXFIFO_RD_REQ (1 << 5) -++#define MSC_IMASK_END_CMD_RES (1 << 2) -++#define MSC_IMASK_PRG_DONE (1 << 1) -++#define MSC_IMASK_DATA_TRAN_DONE (1 << 0) -++ -++ -++/* MSC Interrupts Status Register (MSC_IREG) */ -++ -++#define MSC_IREG_SDIO (1 << 7) -++#define MSC_IREG_TXFIFO_WR_REQ (1 << 6) -++#define MSC_IREG_RXFIFO_RD_REQ (1 << 5) -++#define MSC_IREG_END_CMD_RES (1 << 2) -++#define MSC_IREG_PRG_DONE (1 << 1) -++#define MSC_IREG_DATA_TRAN_DONE (1 << 0) -++ -++ -++/************************************************************************* -++ * EMC (External Memory Controller) -++ *************************************************************************/ -++#define EMC_SMCR0 (EMC_BASE + 0x10) /* Static Memory Control Register 0 */ -++#define EMC_SMCR1 (EMC_BASE + 0x14) /* Static Memory Control Register 1 */ -++#define EMC_SMCR2 (EMC_BASE + 0x18) /* Static Memory Control Register 2 */ -++#define EMC_SMCR3 (EMC_BASE + 0x1c) /* Static Memory Control Register 3 */ -++#define EMC_SMCR4 (EMC_BASE + 0x20) /* Static Memory Control Register 4 */ -++#define EMC_SACR0 (EMC_BASE + 0x30) /* Static Memory Bank 0 Addr Config Reg */ -++#define EMC_SACR1 (EMC_BASE + 0x34) /* Static Memory Bank 1 Addr Config Reg */ -++#define EMC_SACR2 (EMC_BASE + 0x38) /* Static Memory Bank 2 Addr Config Reg */ -++#define EMC_SACR3 (EMC_BASE + 0x3c) /* Static Memory Bank 3 Addr Config Reg */ -++#define EMC_SACR4 (EMC_BASE + 0x40) /* Static Memory Bank 4 Addr Config Reg */ -++ -++#define EMC_NFCSR (EMC_BASE + 0x050) /* NAND Flash Control/Status Register */ -++#define EMC_NFECR (EMC_BASE + 0x100) /* NAND Flash ECC Control Register */ -++#define EMC_NFECC (EMC_BASE + 0x104) /* NAND Flash ECC Data Register */ -++#define EMC_NFPAR0 (EMC_BASE + 0x108) /* NAND Flash RS Parity 0 Register */ -++#define EMC_NFPAR1 (EMC_BASE + 0x10c) /* NAND Flash RS Parity 1 Register */ -++#define EMC_NFPAR2 (EMC_BASE + 0x110) /* NAND Flash RS Parity 2 Register */ -++#define EMC_NFINTS (EMC_BASE + 0x114) /* NAND Flash Interrupt Status Register */ -++#define EMC_NFINTE (EMC_BASE + 0x118) /* NAND Flash Interrupt Enable Register */ -++#define EMC_NFERR0 (EMC_BASE + 0x11c) /* NAND Flash RS Error Report 0 Register */ -++#define EMC_NFERR1 (EMC_BASE + 0x120) /* NAND Flash RS Error Report 1 Register */ -++#define EMC_NFERR2 (EMC_BASE + 0x124) /* NAND Flash RS Error Report 2 Register */ -++#define EMC_NFERR3 (EMC_BASE + 0x128) /* NAND Flash RS Error Report 3 Register */ -++ -++#define EMC_DMCR (EMC_BASE + 0x80) /* DRAM Control Register */ -++#define EMC_RTCSR (EMC_BASE + 0x84) /* Refresh Time Control/Status Register */ -++#define EMC_RTCNT (EMC_BASE + 0x88) /* Refresh Timer Counter */ -++#define EMC_RTCOR (EMC_BASE + 0x8c) /* Refresh Time Constant Register */ -++#define EMC_DMAR0 (EMC_BASE + 0x90) /* SDRAM Bank 0 Addr Config Register */ -++#define EMC_SDMR0 (EMC_BASE + 0xa000) /* Mode Register of SDRAM bank 0 */ -++ -++ -++#define REG_EMC_SMCR0 REG32(EMC_SMCR0) -++#define REG_EMC_SMCR1 REG32(EMC_SMCR1) -++#define REG_EMC_SMCR2 REG32(EMC_SMCR2) -++#define REG_EMC_SMCR3 REG32(EMC_SMCR3) -++#define REG_EMC_SMCR4 REG32(EMC_SMCR4) -++#define REG_EMC_SACR0 REG32(EMC_SACR0) -++#define REG_EMC_SACR1 REG32(EMC_SACR1) -++#define REG_EMC_SACR2 REG32(EMC_SACR2) -++#define REG_EMC_SACR3 REG32(EMC_SACR3) -++#define REG_EMC_SACR4 REG32(EMC_SACR4) -++ -++#define REG_EMC_NFCSR REG32(EMC_NFCSR) -++#define REG_EMC_NFECR REG32(EMC_NFECR) -++#define REG_EMC_NFECC REG32(EMC_NFECC) -++#define REG_EMC_NFPAR0 REG32(EMC_NFPAR0) -++#define REG_EMC_NFPAR1 REG32(EMC_NFPAR1) -++#define REG_EMC_NFPAR2 REG32(EMC_NFPAR2) -++#define REG_EMC_NFINTS REG32(EMC_NFINTS) -++#define REG_EMC_NFINTE REG32(EMC_NFINTE) -++#define REG_EMC_NFERR0 REG32(EMC_NFERR0) -++#define REG_EMC_NFERR1 REG32(EMC_NFERR1) -++#define REG_EMC_NFERR2 REG32(EMC_NFERR2) -++#define REG_EMC_NFERR3 REG32(EMC_NFERR3) -++ -++#define REG_EMC_DMCR REG32(EMC_DMCR) -++#define REG_EMC_RTCSR REG16(EMC_RTCSR) -++#define REG_EMC_RTCNT REG16(EMC_RTCNT) -++#define REG_EMC_RTCOR REG16(EMC_RTCOR) -++#define REG_EMC_DMAR0 REG32(EMC_DMAR0) -++ -++/* Static Memory Control Register */ -++#define EMC_SMCR_STRV_BIT 24 -++#define EMC_SMCR_STRV_MASK (0x0f << EMC_SMCR_STRV_BIT) -++#define EMC_SMCR_TAW_BIT 20 -++#define EMC_SMCR_TAW_MASK (0x0f << EMC_SMCR_TAW_BIT) -++#define EMC_SMCR_TBP_BIT 16 -++#define EMC_SMCR_TBP_MASK (0x0f << EMC_SMCR_TBP_BIT) -++#define EMC_SMCR_TAH_BIT 12 -++#define EMC_SMCR_TAH_MASK (0x07 << EMC_SMCR_TAH_BIT) -++#define EMC_SMCR_TAS_BIT 8 -++#define EMC_SMCR_TAS_MASK (0x07 << EMC_SMCR_TAS_BIT) -++#define EMC_SMCR_BW_BIT 6 -++#define EMC_SMCR_BW_MASK (0x03 << EMC_SMCR_BW_BIT) -++ #define EMC_SMCR_BW_8BIT (0 << EMC_SMCR_BW_BIT) -++ #define EMC_SMCR_BW_16BIT (1 << EMC_SMCR_BW_BIT) -++ #define EMC_SMCR_BW_32BIT (2 << EMC_SMCR_BW_BIT) -++#define EMC_SMCR_BCM (1 << 3) -++#define EMC_SMCR_BL_BIT 1 -++#define EMC_SMCR_BL_MASK (0x03 << EMC_SMCR_BL_BIT) -++ #define EMC_SMCR_BL_4 (0 << EMC_SMCR_BL_BIT) -++ #define EMC_SMCR_BL_8 (1 << EMC_SMCR_BL_BIT) -++ #define EMC_SMCR_BL_16 (2 << EMC_SMCR_BL_BIT) -++ #define EMC_SMCR_BL_32 (3 << EMC_SMCR_BL_BIT) -++#define EMC_SMCR_SMT (1 << 0) -++ -++/* Static Memory Bank Addr Config Reg */ -++#define EMC_SACR_BASE_BIT 8 -++#define EMC_SACR_BASE_MASK (0xff << EMC_SACR_BASE_BIT) -++#define EMC_SACR_MASK_BIT 0 -++#define EMC_SACR_MASK_MASK (0xff << EMC_SACR_MASK_BIT) -++ -++/* NAND Flash Control/Status Register */ -++#define EMC_NFCSR_NFCE4 (1 << 7) /* NAND Flash Enable */ -++#define EMC_NFCSR_NFE4 (1 << 6) /* NAND Flash FCE# Assertion Enable */ -++#define EMC_NFCSR_NFCE3 (1 << 5) -++#define EMC_NFCSR_NFE3 (1 << 4) -++#define EMC_NFCSR_NFCE2 (1 << 3) -++#define EMC_NFCSR_NFE2 (1 << 2) -++#define EMC_NFCSR_NFCE1 (1 << 1) -++#define EMC_NFCSR_NFE1 (1 << 0) -++ -++/* NAND Flash ECC Control Register */ -++#define EMC_NFECR_PRDY (1 << 4) /* Parity Ready */ -++#define EMC_NFECR_RS_DECODING (0 << 3) /* RS is in decoding phase */ -++#define EMC_NFECR_RS_ENCODING (1 << 3) /* RS is in encoding phase */ -++#define EMC_NFECR_HAMMING (0 << 2) /* Select HAMMING Correction Algorithm */ -++#define EMC_NFECR_RS (1 << 2) /* Select RS Correction Algorithm */ -++#define EMC_NFECR_ERST (1 << 1) /* ECC Reset */ -++#define EMC_NFECR_ECCE (1 << 0) /* ECC Enable */ -++ -++/* NAND Flash ECC Data Register */ -++#define EMC_NFECC_ECC2_BIT 16 -++#define EMC_NFECC_ECC2_MASK (0xff << EMC_NFECC_ECC2_BIT) -++#define EMC_NFECC_ECC1_BIT 8 -++#define EMC_NFECC_ECC1_MASK (0xff << EMC_NFECC_ECC1_BIT) -++#define EMC_NFECC_ECC0_BIT 0 -++#define EMC_NFECC_ECC0_MASK (0xff << EMC_NFECC_ECC0_BIT) -++ -++/* NAND Flash Interrupt Status Register */ -++#define EMC_NFINTS_ERRCNT_BIT 29 /* Error Count */ -++#define EMC_NFINTS_ERRCNT_MASK (0x7 << EMC_NFINTS_ERRCNT_BIT) -++#define EMC_NFINTS_PADF (1 << 4) /* Padding Finished */ -++#define EMC_NFINTS_DECF (1 << 3) /* Decoding Finished */ -++#define EMC_NFINTS_ENCF (1 << 2) /* Encoding Finished */ -++#define EMC_NFINTS_UNCOR (1 << 1) /* Uncorrectable Error Occurred */ -++#define EMC_NFINTS_ERR (1 << 0) /* Error Occurred */ -++ -++/* NAND Flash Interrupt Enable Register */ -++#define EMC_NFINTE_PADFE (1 << 4) /* Padding Finished Interrupt Enable */ -++#define EMC_NFINTE_DECFE (1 << 3) /* Decoding Finished Interrupt Enable */ -++#define EMC_NFINTE_ENCFE (1 << 2) /* Encoding Finished Interrupt Enable */ -++#define EMC_NFINTE_UNCORE (1 << 1) /* Uncorrectable Error Occurred Intr Enable */ -++#define EMC_NFINTE_ERRE (1 << 0) /* Error Occurred Interrupt */ -++ -++/* NAND Flash RS Error Report Register */ -++#define EMC_NFERR_INDEX_BIT 16 /* Error Symbol Index */ -++#define EMC_NFERR_INDEX_MASK (0x1ff << EMC_NFERR_INDEX_BIT) -++#define EMC_NFERR_MASK_BIT 0 /* Error Symbol Value */ -++#define EMC_NFERR_MASK_MASK (0x1ff << EMC_NFERR_MASK_BIT) -++ -++ -++/* DRAM Control Register */ -++#define EMC_DMCR_BW_BIT 31 -++#define EMC_DMCR_BW (1 << EMC_DMCR_BW_BIT) -++#define EMC_DMCR_CA_BIT 26 -++#define EMC_DMCR_CA_MASK (0x07 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_8 (0 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_9 (1 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_10 (2 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_11 (3 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_12 (4 << EMC_DMCR_CA_BIT) -++#define EMC_DMCR_RMODE (1 << 25) -++#define EMC_DMCR_RFSH (1 << 24) -++#define EMC_DMCR_MRSET (1 << 23) -++#define EMC_DMCR_RA_BIT 20 -++#define EMC_DMCR_RA_MASK (0x03 << EMC_DMCR_RA_BIT) -++ #define EMC_DMCR_RA_11 (0 << EMC_DMCR_RA_BIT) -++ #define EMC_DMCR_RA_12 (1 << EMC_DMCR_RA_BIT) -++ #define EMC_DMCR_RA_13 (2 << EMC_DMCR_RA_BIT) -++#define EMC_DMCR_BA_BIT 19 -++#define EMC_DMCR_BA (1 << EMC_DMCR_BA_BIT) -++#define EMC_DMCR_PDM (1 << 18) -++#define EMC_DMCR_EPIN (1 << 17) -++#define EMC_DMCR_TRAS_BIT 13 -++#define EMC_DMCR_TRAS_MASK (0x07 << EMC_DMCR_TRAS_BIT) -++#define EMC_DMCR_RCD_BIT 11 -++#define EMC_DMCR_RCD_MASK (0x03 << EMC_DMCR_RCD_BIT) -++#define EMC_DMCR_TPC_BIT 8 -++#define EMC_DMCR_TPC_MASK (0x07 << EMC_DMCR_TPC_BIT) -++#define EMC_DMCR_TRWL_BIT 5 -++#define EMC_DMCR_TRWL_MASK (0x03 << EMC_DMCR_TRWL_BIT) -++#define EMC_DMCR_TRC_BIT 2 -++#define EMC_DMCR_TRC_MASK (0x07 << EMC_DMCR_TRC_BIT) -++#define EMC_DMCR_TCL_BIT 0 -++#define EMC_DMCR_TCL_MASK (0x03 << EMC_DMCR_TCL_BIT) -++ -++/* Refresh Time Control/Status Register */ -++#define EMC_RTCSR_CMF (1 << 7) -++#define EMC_RTCSR_CKS_BIT 0 -++#define EMC_RTCSR_CKS_MASK (0x07 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_DISABLE (0 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_4 (1 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_16 (2 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_64 (3 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_256 (4 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_1024 (5 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_2048 (6 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_4096 (7 << EMC_RTCSR_CKS_BIT) -++ -++/* SDRAM Bank Address Configuration Register */ -++#define EMC_DMAR_BASE_BIT 8 -++#define EMC_DMAR_BASE_MASK (0xff << EMC_DMAR_BASE_BIT) -++#define EMC_DMAR_MASK_BIT 0 -++#define EMC_DMAR_MASK_MASK (0xff << EMC_DMAR_MASK_BIT) -++ -++/* Mode Register of SDRAM bank 0 */ -++#define EMC_SDMR_BM (1 << 9) /* Write Burst Mode */ -++#define EMC_SDMR_OM_BIT 7 /* Operating Mode */ -++#define EMC_SDMR_OM_MASK (3 << EMC_SDMR_OM_BIT) -++ #define EMC_SDMR_OM_NORMAL (0 << EMC_SDMR_OM_BIT) -++#define EMC_SDMR_CAS_BIT 4 /* CAS Latency */ -++#define EMC_SDMR_CAS_MASK (7 << EMC_SDMR_CAS_BIT) -++ #define EMC_SDMR_CAS_1 (1 << EMC_SDMR_CAS_BIT) -++ #define EMC_SDMR_CAS_2 (2 << EMC_SDMR_CAS_BIT) -++ #define EMC_SDMR_CAS_3 (3 << EMC_SDMR_CAS_BIT) -++#define EMC_SDMR_BT_BIT 3 /* Burst Type */ -++#define EMC_SDMR_BT_MASK (1 << EMC_SDMR_BT_BIT) -++ #define EMC_SDMR_BT_SEQ (0 << EMC_SDMR_BT_BIT) /* Sequential */ -++ #define EMC_SDMR_BT_INT (1 << EMC_SDMR_BT_BIT) /* Interleave */ -++#define EMC_SDMR_BL_BIT 0 /* Burst Length */ -++#define EMC_SDMR_BL_MASK (7 << EMC_SDMR_BL_BIT) -++ #define EMC_SDMR_BL_1 (0 << EMC_SDMR_BL_BIT) -++ #define EMC_SDMR_BL_2 (1 << EMC_SDMR_BL_BIT) -++ #define EMC_SDMR_BL_4 (2 << EMC_SDMR_BL_BIT) -++ #define EMC_SDMR_BL_8 (3 << EMC_SDMR_BL_BIT) -++ -++#define EMC_SDMR_CAS2_16BIT \ -++ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) -++#define EMC_SDMR_CAS2_32BIT \ -++ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) -++#define EMC_SDMR_CAS3_16BIT \ -++ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) -++#define EMC_SDMR_CAS3_32BIT \ -++ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) -++ -++ -++/************************************************************************* -++ * CIM -++ *************************************************************************/ -++#define CIM_CFG (CIM_BASE + 0x0000) -++#define CIM_CTRL (CIM_BASE + 0x0004) -++#define CIM_STATE (CIM_BASE + 0x0008) -++#define CIM_IID (CIM_BASE + 0x000C) -++#define CIM_RXFIFO (CIM_BASE + 0x0010) -++#define CIM_DA (CIM_BASE + 0x0020) -++#define CIM_FA (CIM_BASE + 0x0024) -++#define CIM_FID (CIM_BASE + 0x0028) -++#define CIM_CMD (CIM_BASE + 0x002C) -++ -++#define REG_CIM_CFG REG32(CIM_CFG) -++#define REG_CIM_CTRL REG32(CIM_CTRL) -++#define REG_CIM_STATE REG32(CIM_STATE) -++#define REG_CIM_IID REG32(CIM_IID) -++#define REG_CIM_RXFIFO REG32(CIM_RXFIFO) -++#define REG_CIM_DA REG32(CIM_DA) -++#define REG_CIM_FA REG32(CIM_FA) -++#define REG_CIM_FID REG32(CIM_FID) -++#define REG_CIM_CMD REG32(CIM_CMD) -++ -++/* CIM Configuration Register (CIM_CFG) */ -++ -++#define CIM_CFG_INV_DAT (1 << 15) -++#define CIM_CFG_VSP (1 << 14) -++#define CIM_CFG_HSP (1 << 13) -++#define CIM_CFG_PCP (1 << 12) -++#define CIM_CFG_DUMMY_ZERO (1 << 9) -++#define CIM_CFG_EXT_VSYNC (1 << 8) -++#define CIM_CFG_PACK_BIT 4 -++#define CIM_CFG_PACK_MASK (0x7 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_0 (0 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_1 (1 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_2 (2 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_3 (3 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_4 (4 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_5 (5 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_6 (6 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_7 (7 << CIM_CFG_PACK_BIT) -++#define CIM_CFG_DSM_BIT 0 -++#define CIM_CFG_DSM_MASK (0x3 << CIM_CFG_DSM_BIT) -++ #define CIM_CFG_DSM_CPM (0 << CIM_CFG_DSM_BIT) /* CCIR656 Progressive Mode */ -++ #define CIM_CFG_DSM_CIM (1 << CIM_CFG_DSM_BIT) /* CCIR656 Interlace Mode */ -++ #define CIM_CFG_DSM_GCM (2 << CIM_CFG_DSM_BIT) /* Gated Clock Mode */ -++ #define CIM_CFG_DSM_NGCM (3 << CIM_CFG_DSM_BIT) /* Non-Gated Clock Mode */ -++ -++/* CIM Control Register (CIM_CTRL) */ -++ -++#define CIM_CTRL_MCLKDIV_BIT 24 -++#define CIM_CTRL_MCLKDIV_MASK (0xff << CIM_CTRL_MCLKDIV_BIT) -++#define CIM_CTRL_FRC_BIT 16 -++#define CIM_CTRL_FRC_MASK (0xf << CIM_CTRL_FRC_BIT) -++ #define CIM_CTRL_FRC_1 (0x0 << CIM_CTRL_FRC_BIT) /* Sample every frame */ -++ #define CIM_CTRL_FRC_2 (0x1 << CIM_CTRL_FRC_BIT) /* Sample 1/2 frame */ -++ #define CIM_CTRL_FRC_3 (0x2 << CIM_CTRL_FRC_BIT) /* Sample 1/3 frame */ -++ #define CIM_CTRL_FRC_4 (0x3 << CIM_CTRL_FRC_BIT) /* Sample 1/4 frame */ -++ #define CIM_CTRL_FRC_5 (0x4 << CIM_CTRL_FRC_BIT) /* Sample 1/5 frame */ -++ #define CIM_CTRL_FRC_6 (0x5 << CIM_CTRL_FRC_BIT) /* Sample 1/6 frame */ -++ #define CIM_CTRL_FRC_7 (0x6 << CIM_CTRL_FRC_BIT) /* Sample 1/7 frame */ -++ #define CIM_CTRL_FRC_8 (0x7 << CIM_CTRL_FRC_BIT) /* Sample 1/8 frame */ -++ #define CIM_CTRL_FRC_9 (0x8 << CIM_CTRL_FRC_BIT) /* Sample 1/9 frame */ -++ #define CIM_CTRL_FRC_10 (0x9 << CIM_CTRL_FRC_BIT) /* Sample 1/10 frame */ -++ #define CIM_CTRL_FRC_11 (0xA << CIM_CTRL_FRC_BIT) /* Sample 1/11 frame */ -++ #define CIM_CTRL_FRC_12 (0xB << CIM_CTRL_FRC_BIT) /* Sample 1/12 frame */ -++ #define CIM_CTRL_FRC_13 (0xC << CIM_CTRL_FRC_BIT) /* Sample 1/13 frame */ -++ #define CIM_CTRL_FRC_14 (0xD << CIM_CTRL_FRC_BIT) /* Sample 1/14 frame */ -++ #define CIM_CTRL_FRC_15 (0xE << CIM_CTRL_FRC_BIT) /* Sample 1/15 frame */ -++ #define CIM_CTRL_FRC_16 (0xF << CIM_CTRL_FRC_BIT) /* Sample 1/16 frame */ -++#define CIM_CTRL_VDDM (1 << 13) -++#define CIM_CTRL_DMA_SOFM (1 << 12) -++#define CIM_CTRL_DMA_EOFM (1 << 11) -++#define CIM_CTRL_DMA_STOPM (1 << 10) -++#define CIM_CTRL_RXF_TRIGM (1 << 9) -++#define CIM_CTRL_RXF_OFM (1 << 8) -++#define CIM_CTRL_RXF_TRIG_BIT 4 -++#define CIM_CTRL_RXF_TRIG_MASK (0x7 << CIM_CTRL_RXF_TRIG_BIT) -++ #define CIM_CTRL_RXF_TRIG_4 (0 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 4 */ -++ #define CIM_CTRL_RXF_TRIG_8 (1 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 8 */ -++ #define CIM_CTRL_RXF_TRIG_12 (2 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 12 */ -++ #define CIM_CTRL_RXF_TRIG_16 (3 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 16 */ -++ #define CIM_CTRL_RXF_TRIG_20 (4 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 20 */ -++ #define CIM_CTRL_RXF_TRIG_24 (5 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 24 */ -++ #define CIM_CTRL_RXF_TRIG_28 (6 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 28 */ -++ #define CIM_CTRL_RXF_TRIG_32 (7 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 32 */ -++#define CIM_CTRL_DMA_EN (1 << 2) -++#define CIM_CTRL_RXF_RST (1 << 1) -++#define CIM_CTRL_ENA (1 << 0) -++ -++/* CIM State Register (CIM_STATE) */ -++ -++#define CIM_STATE_DMA_SOF (1 << 6) -++#define CIM_STATE_DMA_EOF (1 << 5) -++#define CIM_STATE_DMA_STOP (1 << 4) -++#define CIM_STATE_RXF_OF (1 << 3) -++#define CIM_STATE_RXF_TRIG (1 << 2) -++#define CIM_STATE_RXF_EMPTY (1 << 1) -++#define CIM_STATE_VDD (1 << 0) -++ -++/* CIM DMA Command Register (CIM_CMD) */ -++ -++#define CIM_CMD_SOFINT (1 << 31) -++#define CIM_CMD_EOFINT (1 << 30) -++#define CIM_CMD_STOP (1 << 28) -++#define CIM_CMD_LEN_BIT 0 -++#define CIM_CMD_LEN_MASK (0xffffff << CIM_CMD_LEN_BIT) -++ -++ -++/************************************************************************* -++ * SADC (Smart A/D Controller) -++ *************************************************************************/ -++ -++#define SADC_ENA (SADC_BASE + 0x00) /* ADC Enable Register */ -++#define SADC_CFG (SADC_BASE + 0x04) /* ADC Configure Register */ -++#define SADC_CTRL (SADC_BASE + 0x08) /* ADC Control Register */ -++#define SADC_STATE (SADC_BASE + 0x0C) /* ADC Status Register*/ -++#define SADC_SAMETIME (SADC_BASE + 0x10) /* ADC Same Point Time Register */ -++#define SADC_WAITTIME (SADC_BASE + 0x14) /* ADC Wait Time Register */ -++#define SADC_TSDAT (SADC_BASE + 0x18) /* ADC Touch Screen Data Register */ -++#define SADC_BATDAT (SADC_BASE + 0x1C) /* ADC PBAT Data Register */ -++#define SADC_SADDAT (SADC_BASE + 0x20) /* ADC SADCIN Data Register */ -++ -++#define REG_SADC_ENA REG8(SADC_ENA) -++#define REG_SADC_CFG REG32(SADC_CFG) -++#define REG_SADC_CTRL REG8(SADC_CTRL) -++#define REG_SADC_STATE REG8(SADC_STATE) -++#define REG_SADC_SAMETIME REG16(SADC_SAMETIME) -++#define REG_SADC_WAITTIME REG16(SADC_WAITTIME) -++#define REG_SADC_TSDAT REG32(SADC_TSDAT) -++#define REG_SADC_BATDAT REG16(SADC_BATDAT) -++#define REG_SADC_SADDAT REG16(SADC_SADDAT) -++ -++/* ADC Enable Register */ -++#define SADC_ENA_ADEN (1 << 7) /* Touch Screen Enable */ -++#define SADC_ENA_TSEN (1 << 2) /* Touch Screen Enable */ -++#define SADC_ENA_PBATEN (1 << 1) /* PBAT Enable */ -++#define SADC_ENA_SADCINEN (1 << 0) /* SADCIN Enable */ -++ -++/* ADC Configure Register */ -++#define SADC_CFG_EXIN (1 << 30) -++#define SADC_CFG_CLKOUT_NUM_BIT 16 -++#define SADC_CFG_CLKOUT_NUM_MASK (0x7 << SADC_CFG_CLKOUT_NUM_BIT) -++#define SADC_CFG_TS_DMA (1 << 15) /* Touch Screen DMA Enable */ -++#define SADC_CFG_XYZ_BIT 13 /* XYZ selection */ -++#define SADC_CFG_XYZ_MASK (0x3 << SADC_CFG_XYZ_BIT) -++ #define SADC_CFG_XY (0 << SADC_CFG_XYZ_BIT) -++ #define SADC_CFG_XYZ (1 << SADC_CFG_XYZ_BIT) -++ #define SADC_CFG_XYZ1Z2 (2 << SADC_CFG_XYZ_BIT) -++#define SADC_CFG_SNUM_BIT 10 /* Sample Number */ -++#define SADC_CFG_SNUM_MASK (0x7 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_1 (0x0 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_2 (0x1 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_3 (0x2 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_4 (0x3 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_5 (0x4 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_6 (0x5 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_8 (0x6 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_9 (0x7 << SADC_CFG_SNUM_BIT) -++#define SADC_CFG_CLKDIV_BIT 5 /* AD Converter frequency clock divider */ -++#define SADC_CFG_CLKDIV_MASK (0x1f << SADC_CFG_CLKDIV_BIT) -++#define SADC_CFG_PBAT_HIGH (0 << 4) /* PBAT >= 2.5V */ -++#define SADC_CFG_PBAT_LOW (1 << 4) /* PBAT < 2.5V */ -++#define SADC_CFG_CMD_BIT 0 /* ADC Command */ -++#define SADC_CFG_CMD_MASK (0xf << SADC_CFG_CMD_BIT) -++ #define SADC_CFG_CMD_X_SE (0x0 << SADC_CFG_CMD_BIT) /* X Single-End */ -++ #define SADC_CFG_CMD_Y_SE (0x1 << SADC_CFG_CMD_BIT) /* Y Single-End */ -++ #define SADC_CFG_CMD_X_DIFF (0x2 << SADC_CFG_CMD_BIT) /* X Differential */ -++ #define SADC_CFG_CMD_Y_DIFF (0x3 << SADC_CFG_CMD_BIT) /* Y Differential */ -++ #define SADC_CFG_CMD_Z1_DIFF (0x4 << SADC_CFG_CMD_BIT) /* Z1 Differential */ -++ #define SADC_CFG_CMD_Z2_DIFF (0x5 << SADC_CFG_CMD_BIT) /* Z2 Differential */ -++ #define SADC_CFG_CMD_Z3_DIFF (0x6 << SADC_CFG_CMD_BIT) /* Z3 Differential */ -++ #define SADC_CFG_CMD_Z4_DIFF (0x7 << SADC_CFG_CMD_BIT) /* Z4 Differential */ -++ #define SADC_CFG_CMD_TP_SE (0x8 << SADC_CFG_CMD_BIT) /* Touch Pressure */ -++ #define SADC_CFG_CMD_PBATH_SE (0x9 << SADC_CFG_CMD_BIT) /* PBAT >= 2.5V */ -++ #define SADC_CFG_CMD_PBATL_SE (0xa << SADC_CFG_CMD_BIT) /* PBAT < 2.5V */ -++ #define SADC_CFG_CMD_SADCIN_SE (0xb << SADC_CFG_CMD_BIT) /* Measure SADCIN */ -++ #define SADC_CFG_CMD_INT_PEN (0xc << SADC_CFG_CMD_BIT) /* INT_PEN Enable */ -++ -++/* ADC Control Register */ -++#define SADC_CTRL_PENDM (1 << 4) /* Pen Down Interrupt Mask */ -++#define SADC_CTRL_PENUM (1 << 3) /* Pen Up Interrupt Mask */ -++#define SADC_CTRL_TSRDYM (1 << 2) /* Touch Screen Data Ready Interrupt Mask */ -++#define SADC_CTRL_PBATRDYM (1 << 1) /* PBAT Data Ready Interrupt Mask */ -++#define SADC_CTRL_SRDYM (1 << 0) /* SADCIN Data Ready Interrupt Mask */ -++ -++/* ADC Status Register */ -++#define SADC_STATE_TSBUSY (1 << 7) /* TS A/D is working */ -++#define SADC_STATE_PBATBUSY (1 << 6) /* PBAT A/D is working */ -++#define SADC_STATE_SBUSY (1 << 5) /* SADCIN A/D is working */ -++#define SADC_STATE_PEND (1 << 4) /* Pen Down Interrupt Flag */ -++#define SADC_STATE_PENU (1 << 3) /* Pen Up Interrupt Flag */ -++#define SADC_STATE_TSRDY (1 << 2) /* Touch Screen Data Ready Interrupt Flag */ -++#define SADC_STATE_PBATRDY (1 << 1) /* PBAT Data Ready Interrupt Flag */ -++#define SADC_STATE_SRDY (1 << 0) /* SADCIN Data Ready Interrupt Flag */ -++ -++/* ADC Touch Screen Data Register */ -++#define SADC_TSDAT_DATA0_BIT 0 -++#define SADC_TSDAT_DATA0_MASK (0xfff << SADC_TSDAT_DATA0_BIT) -++#define SADC_TSDAT_TYPE0 (1 << 15) -++#define SADC_TSDAT_DATA1_BIT 16 -++#define SADC_TSDAT_DATA1_MASK (0xfff << SADC_TSDAT_DATA1_BIT) -++#define SADC_TSDAT_TYPE1 (1 << 31) -++ -++ -++/************************************************************************* -++ * SLCD (Smart LCD Controller) -++ *************************************************************************/ -++ -++#define SLCD_CFG (SLCD_BASE + 0xA0) /* SLCD Configure Register */ -++#define SLCD_CTRL (SLCD_BASE + 0xA4) /* SLCD Control Register */ -++#define SLCD_STATE (SLCD_BASE + 0xA8) /* SLCD Status Register */ -++#define SLCD_DATA (SLCD_BASE + 0xAC) /* SLCD Data Register */ -++#define SLCD_FIFO (SLCD_BASE + 0xB0) /* SLCD FIFO Register */ -++ -++#define REG_SLCD_CFG REG32(SLCD_CFG) -++#define REG_SLCD_CTRL REG8(SLCD_CTRL) -++#define REG_SLCD_STATE REG8(SLCD_STATE) -++#define REG_SLCD_DATA REG32(SLCD_DATA) -++#define REG_SLCD_FIFO REG32(SLCD_FIFO) -++ -++/* SLCD Configure Register */ -++#define SLCD_CFG_BURST_BIT 14 -++#define SLCD_CFG_BURST_MASK (0x3 << SLCD_CFG_BURST_BIT) -++ #define SLCD_CFG_BURST_4_WORD (0 << SLCD_CFG_BURST_BIT) -++ #define SLCD_CFG_BURST_8_WORD (1 << SLCD_CFG_BURST_BIT) -++#define SLCD_CFG_DWIDTH_BIT 10 -++#define SLCD_CFG_DWIDTH_MASK (0x7 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_18 (0 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_16 (1 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_8_x3 (2 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_8_x2 (3 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_8_x1 (4 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_9_x2 (7 << SLCD_CFG_DWIDTH_BIT) -++#define SLCD_CFG_CWIDTH_16BIT (0 << 8) -++#define SLCD_CFG_CWIDTH_8BIT (1 << 8) -++#define SLCD_CFG_CWIDTH_18BIT (2 << 8) -++#define SLCD_CFG_CS_ACTIVE_LOW (0 << 4) -++#define SLCD_CFG_CS_ACTIVE_HIGH (1 << 4) -++#define SLCD_CFG_RS_CMD_LOW (0 << 3) -++#define SLCD_CFG_RS_CMD_HIGH (1 << 3) -++#define SLCD_CFG_CLK_ACTIVE_FALLING (0 << 1) -++#define SLCD_CFG_CLK_ACTIVE_RISING (1 << 1) -++#define SLCD_CFG_TYPE_PARALLEL (0 << 0) -++#define SLCD_CFG_TYPE_SERIAL (1 << 0) -++ -++/* SLCD Control Register */ -++#define SLCD_CTRL_DMA_EN (1 << 0) -++ -++/* SLCD Status Register */ -++#define SLCD_STATE_BUSY (1 << 0) -++ -++/* SLCD Data Register */ -++#define SLCD_DATA_RS_DATA (0 << 31) -++#define SLCD_DATA_RS_COMMAND (1 << 31) -++ -++/* SLCD FIFO Register */ -++#define SLCD_FIFO_RS_DATA (0 << 31) -++#define SLCD_FIFO_RS_COMMAND (1 << 31) -++ -++ -++/************************************************************************* -++ * LCD (LCD Controller) -++ *************************************************************************/ -++#define LCD_CFG (LCD_BASE + 0x00) /* LCD Configure Register */ -++#define LCD_VSYNC (LCD_BASE + 0x04) /* Vertical Synchronize Register */ -++#define LCD_HSYNC (LCD_BASE + 0x08) /* Horizontal Synchronize Register */ -++#define LCD_VAT (LCD_BASE + 0x0c) /* Virtual Area Setting Register */ -++#define LCD_DAH (LCD_BASE + 0x10) /* Display Area Horizontal Start/End Point */ -++#define LCD_DAV (LCD_BASE + 0x14) /* Display Area Vertical Start/End Point */ -++#define LCD_PS (LCD_BASE + 0x18) /* PS Signal Setting */ -++#define LCD_CLS (LCD_BASE + 0x1c) /* CLS Signal Setting */ -++#define LCD_SPL (LCD_BASE + 0x20) /* SPL Signal Setting */ -++#define LCD_REV (LCD_BASE + 0x24) /* REV Signal Setting */ -++#define LCD_CTRL (LCD_BASE + 0x30) /* LCD Control Register */ -++#define LCD_STATE (LCD_BASE + 0x34) /* LCD Status Register */ -++#define LCD_IID (LCD_BASE + 0x38) /* Interrupt ID Register */ -++#define LCD_DA0 (LCD_BASE + 0x40) /* Descriptor Address Register 0 */ -++#define LCD_SA0 (LCD_BASE + 0x44) /* Source Address Register 0 */ -++#define LCD_FID0 (LCD_BASE + 0x48) /* Frame ID Register 0 */ -++#define LCD_CMD0 (LCD_BASE + 0x4c) /* DMA Command Register 0 */ -++#define LCD_DA1 (LCD_BASE + 0x50) /* Descriptor Address Register 1 */ -++#define LCD_SA1 (LCD_BASE + 0x54) /* Source Address Register 1 */ -++#define LCD_FID1 (LCD_BASE + 0x58) /* Frame ID Register 1 */ -++#define LCD_CMD1 (LCD_BASE + 0x5c) /* DMA Command Register 1 */ -++ -++#define REG_LCD_CFG REG32(LCD_CFG) -++#define REG_LCD_VSYNC REG32(LCD_VSYNC) -++#define REG_LCD_HSYNC REG32(LCD_HSYNC) -++#define REG_LCD_VAT REG32(LCD_VAT) -++#define REG_LCD_DAH REG32(LCD_DAH) -++#define REG_LCD_DAV REG32(LCD_DAV) -++#define REG_LCD_PS REG32(LCD_PS) -++#define REG_LCD_CLS REG32(LCD_CLS) -++#define REG_LCD_SPL REG32(LCD_SPL) -++#define REG_LCD_REV REG32(LCD_REV) -++#define REG_LCD_CTRL REG32(LCD_CTRL) -++#define REG_LCD_STATE REG32(LCD_STATE) -++#define REG_LCD_IID REG32(LCD_IID) -++#define REG_LCD_DA0 REG32(LCD_DA0) -++#define REG_LCD_SA0 REG32(LCD_SA0) -++#define REG_LCD_FID0 REG32(LCD_FID0) -++#define REG_LCD_CMD0 REG32(LCD_CMD0) -++#define REG_LCD_DA1 REG32(LCD_DA1) -++#define REG_LCD_SA1 REG32(LCD_SA1) -++#define REG_LCD_FID1 REG32(LCD_FID1) -++#define REG_LCD_CMD1 REG32(LCD_CMD1) -++ -++/* LCD Configure Register */ -++#define LCD_CFG_LCDPIN_BIT 31 /* LCD pins selection */ -++#define LCD_CFG_LCDPIN_MASK (0x1 << LCD_CFG_LCDPIN_BIT) -++ #define LCD_CFG_LCDPIN_LCD (0x0 << LCD_CFG_LCDPIN_BIT) -++ #define LCD_CFG_LCDPIN_SLCD (0x1 << LCD_CFG_LCDPIN_BIT) -++#define LCD_CFG_PSM (1 << 23) /* PS signal mode */ -++#define LCD_CFG_CLSM (1 << 22) /* CLS signal mode */ -++#define LCD_CFG_SPLM (1 << 21) /* SPL signal mode */ -++#define LCD_CFG_REVM (1 << 20) /* REV signal mode */ -++#define LCD_CFG_HSYNM (1 << 19) /* HSYNC signal mode */ -++#define LCD_CFG_PCLKM (1 << 18) /* PCLK signal mode */ -++#define LCD_CFG_INVDAT (1 << 17) /* Inverse output data */ -++#define LCD_CFG_SYNDIR_IN (1 << 16) /* VSYNC&HSYNC direction */ -++#define LCD_CFG_PSP (1 << 15) /* PS pin reset state */ -++#define LCD_CFG_CLSP (1 << 14) /* CLS pin reset state */ -++#define LCD_CFG_SPLP (1 << 13) /* SPL pin reset state */ -++#define LCD_CFG_REVP (1 << 12) /* REV pin reset state */ -++#define LCD_CFG_HSP (1 << 11) /* HSYNC pority:0-active high,1-active low */ -++#define LCD_CFG_PCP (1 << 10) /* PCLK pority:0-rising,1-falling */ -++#define LCD_CFG_DEP (1 << 9) /* DE pority:0-active high,1-active low */ -++#define LCD_CFG_VSP (1 << 8) /* VSYNC pority:0-rising,1-falling */ -++#define LCD_CFG_PDW_BIT 4 /* STN pins utilization */ -++#define LCD_CFG_PDW_MASK (0x3 << LCD_DEV_PDW_BIT) -++#define LCD_CFG_PDW_1 (0 << LCD_CFG_PDW_BIT) /* LCD_D[0] */ -++ #define LCD_CFG_PDW_2 (1 << LCD_CFG_PDW_BIT) /* LCD_D[0:1] */ -++ #define LCD_CFG_PDW_4 (2 << LCD_CFG_PDW_BIT) /* LCD_D[0:3]/LCD_D[8:11] */ -++ #define LCD_CFG_PDW_8 (3 << LCD_CFG_PDW_BIT) /* LCD_D[0:7]/LCD_D[8:15] */ -++#define LCD_CFG_MODE_BIT 0 /* Display Device Mode Select */ -++#define LCD_CFG_MODE_MASK (0x0f << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_GENERIC_TFT (0 << LCD_CFG_MODE_BIT) /* 16,18 bit TFT */ -++ #define LCD_CFG_MODE_SPECIAL_TFT_1 (1 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SPECIAL_TFT_2 (2 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SPECIAL_TFT_3 (3 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_NONINTER_CCIR656 (4 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_INTER_CCIR656 (6 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SINGLE_CSTN (8 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SINGLE_MSTN (9 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_DUAL_CSTN (10 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_DUAL_MSTN (11 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SERIAL_TFT (12 << LCD_CFG_MODE_BIT) -++ /* JZ47XX defines */ -++ #define LCD_CFG_MODE_SHARP_HR (1 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_CASIO_TFT (2 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SAMSUNG_ALPHA (3 << LCD_CFG_MODE_BIT) -++ -++ -++ -++/* Vertical Synchronize Register */ -++#define LCD_VSYNC_VPS_BIT 16 /* VSYNC pulse start in line clock, fixed to 0 */ -++#define LCD_VSYNC_VPS_MASK (0xffff << LCD_VSYNC_VPS_BIT) -++#define LCD_VSYNC_VPE_BIT 0 /* VSYNC pulse end in line clock */ -++#define LCD_VSYNC_VPE_MASK (0xffff << LCD_VSYNC_VPS_BIT) -++ -++/* Horizontal Synchronize Register */ -++#define LCD_HSYNC_HPS_BIT 16 /* HSYNC pulse start position in dot clock */ -++#define LCD_HSYNC_HPS_MASK (0xffff << LCD_HSYNC_HPS_BIT) -++#define LCD_HSYNC_HPE_BIT 0 /* HSYNC pulse end position in dot clock */ -++#define LCD_HSYNC_HPE_MASK (0xffff << LCD_HSYNC_HPE_BIT) -++ -++/* Virtual Area Setting Register */ -++#define LCD_VAT_HT_BIT 16 /* Horizontal Total size in dot clock */ -++#define LCD_VAT_HT_MASK (0xffff << LCD_VAT_HT_BIT) -++#define LCD_VAT_VT_BIT 0 /* Vertical Total size in dot clock */ -++#define LCD_VAT_VT_MASK (0xffff << LCD_VAT_VT_BIT) -++ -++/* Display Area Horizontal Start/End Point Register */ -++#define LCD_DAH_HDS_BIT 16 /* Horizontal display area start in dot clock */ -++#define LCD_DAH_HDS_MASK (0xffff << LCD_DAH_HDS_BIT) -++#define LCD_DAH_HDE_BIT 0 /* Horizontal display area end in dot clock */ -++#define LCD_DAH_HDE_MASK (0xffff << LCD_DAH_HDE_BIT) -++ -++/* Display Area Vertical Start/End Point Register */ -++#define LCD_DAV_VDS_BIT 16 /* Vertical display area start in line clock */ -++#define LCD_DAV_VDS_MASK (0xffff << LCD_DAV_VDS_BIT) -++#define LCD_DAV_VDE_BIT 0 /* Vertical display area end in line clock */ -++#define LCD_DAV_VDE_MASK (0xffff << LCD_DAV_VDE_BIT) -++ -++/* PS Signal Setting */ -++#define LCD_PS_PSS_BIT 16 /* PS signal start position in dot clock */ -++#define LCD_PS_PSS_MASK (0xffff << LCD_PS_PSS_BIT) -++#define LCD_PS_PSE_BIT 0 /* PS signal end position in dot clock */ -++#define LCD_PS_PSE_MASK (0xffff << LCD_PS_PSE_BIT) -++ -++/* CLS Signal Setting */ -++#define LCD_CLS_CLSS_BIT 16 /* CLS signal start position in dot clock */ -++#define LCD_CLS_CLSS_MASK (0xffff << LCD_CLS_CLSS_BIT) -++#define LCD_CLS_CLSE_BIT 0 /* CLS signal end position in dot clock */ -++#define LCD_CLS_CLSE_MASK (0xffff << LCD_CLS_CLSE_BIT) -++ -++/* SPL Signal Setting */ -++#define LCD_SPL_SPLS_BIT 16 /* SPL signal start position in dot clock */ -++#define LCD_SPL_SPLS_MASK (0xffff << LCD_SPL_SPLS_BIT) -++#define LCD_SPL_SPLE_BIT 0 /* SPL signal end position in dot clock */ -++#define LCD_SPL_SPLE_MASK (0xffff << LCD_SPL_SPLE_BIT) -++ -++/* REV Signal Setting */ -++#define LCD_REV_REVS_BIT 16 /* REV signal start position in dot clock */ -++#define LCD_REV_REVS_MASK (0xffff << LCD_REV_REVS_BIT) -++ -++/* LCD Control Register */ -++#define LCD_CTRL_BST_BIT 28 /* Burst Length Selection */ -++#define LCD_CTRL_BST_MASK (0x03 << LCD_CTRL_BST_BIT) -++ #define LCD_CTRL_BST_4 (0 << LCD_CTRL_BST_BIT) /* 4-word */ -++ #define LCD_CTRL_BST_8 (1 << LCD_CTRL_BST_BIT) /* 8-word */ -++ #define LCD_CTRL_BST_16 (2 << LCD_CTRL_BST_BIT) /* 16-word */ -++#define LCD_CTRL_RGB565 (0 << 27) /* RGB565 mode */ -++#define LCD_CTRL_RGB555 (1 << 27) /* RGB555 mode */ -++#define LCD_CTRL_OFUP (1 << 26) /* Output FIFO underrun protection enable */ -++#define LCD_CTRL_FRC_BIT 24 /* STN FRC Algorithm Selection */ -++#define LCD_CTRL_FRC_MASK (0x03 << LCD_CTRL_FRC_BIT) -++ #define LCD_CTRL_FRC_16 (0 << LCD_CTRL_FRC_BIT) /* 16 grayscale */ -++ #define LCD_CTRL_FRC_4 (1 << LCD_CTRL_FRC_BIT) /* 4 grayscale */ -++ #define LCD_CTRL_FRC_2 (2 << LCD_CTRL_FRC_BIT) /* 2 grayscale */ -++#define LCD_CTRL_PDD_BIT 16 /* Load Palette Delay Counter */ -++#define LCD_CTRL_PDD_MASK (0xff << LCD_CTRL_PDD_BIT) -++#define LCD_CTRL_EOFM (1 << 13) /* EOF interrupt mask */ -++#define LCD_CTRL_SOFM (1 << 12) /* SOF interrupt mask */ -++#define LCD_CTRL_OFUM (1 << 11) /* Output FIFO underrun interrupt mask */ -++#define LCD_CTRL_IFUM0 (1 << 10) /* Input FIFO 0 underrun interrupt mask */ -++#define LCD_CTRL_IFUM1 (1 << 9) /* Input FIFO 1 underrun interrupt mask */ -++#define LCD_CTRL_LDDM (1 << 8) /* LCD disable done interrupt mask */ -++#define LCD_CTRL_QDM (1 << 7) /* LCD quick disable done interrupt mask */ -++#define LCD_CTRL_BEDN (1 << 6) /* Endian selection */ -++#define LCD_CTRL_PEDN (1 << 5) /* Endian in byte:0-msb first, 1-lsb first */ -++#define LCD_CTRL_DIS (1 << 4) /* Disable indicate bit */ -++#define LCD_CTRL_ENA (1 << 3) /* LCD enable bit */ -++#define LCD_CTRL_BPP_BIT 0 /* Bits Per Pixel */ -++#define LCD_CTRL_BPP_MASK (0x07 << LCD_CTRL_BPP_BIT) -++ #define LCD_CTRL_BPP_1 (0 << LCD_CTRL_BPP_BIT) /* 1 bpp */ -++ #define LCD_CTRL_BPP_2 (1 << LCD_CTRL_BPP_BIT) /* 2 bpp */ -++ #define LCD_CTRL_BPP_4 (2 << LCD_CTRL_BPP_BIT) /* 4 bpp */ -++ #define LCD_CTRL_BPP_8 (3 << LCD_CTRL_BPP_BIT) /* 8 bpp */ -++ #define LCD_CTRL_BPP_16 (4 << LCD_CTRL_BPP_BIT) /* 15/16 bpp */ -++ #define LCD_CTRL_BPP_18_24 (5 << LCD_CTRL_BPP_BIT) /* 18/24/32 bpp */ -++ -++/* LCD Status Register */ -++#define LCD_STATE_QD (1 << 7) /* Quick Disable Done */ -++#define LCD_STATE_EOF (1 << 5) /* EOF Flag */ -++#define LCD_STATE_SOF (1 << 4) /* SOF Flag */ -++#define LCD_STATE_OFU (1 << 3) /* Output FIFO Underrun */ -++#define LCD_STATE_IFU0 (1 << 2) /* Input FIFO 0 Underrun */ -++#define LCD_STATE_IFU1 (1 << 1) /* Input FIFO 1 Underrun */ -++#define LCD_STATE_LDD (1 << 0) /* LCD Disabled */ -++ -++/* DMA Command Register */ -++#define LCD_CMD_SOFINT (1 << 31) -++#define LCD_CMD_EOFINT (1 << 30) -++#define LCD_CMD_PAL (1 << 28) -++#define LCD_CMD_LEN_BIT 0 -++#define LCD_CMD_LEN_MASK (0xffffff << LCD_CMD_LEN_BIT) -++ -++ -++/************************************************************************* -++ * USB Device -++ *************************************************************************/ -++#define USB_BASE UDC_BASE -++ -++#define USB_REG_FADDR (USB_BASE + 0x00) /* Function Address 8-bit */ -++#define USB_REG_POWER (USB_BASE + 0x01) /* Power Managemetn 8-bit */ -++#define USB_REG_INTRIN (USB_BASE + 0x02) /* Interrupt IN 16-bit */ -++#define USB_REG_INTROUT (USB_BASE + 0x04) /* Interrupt OUT 16-bit */ -++#define USB_REG_INTRINE (USB_BASE + 0x06) /* Intr IN enable 16-bit */ -++#define USB_REG_INTROUTE (USB_BASE + 0x08) /* Intr OUT enable 16-bit */ -++#define USB_REG_INTRUSB (USB_BASE + 0x0a) /* Interrupt USB 8-bit */ -++#define USB_REG_INTRUSBE (USB_BASE + 0x0b) /* Interrupt USB Enable 8-bit */ -++#define USB_REG_FRAME (USB_BASE + 0x0c) /* Frame number 16-bit */ -++#define USB_REG_INDEX (USB_BASE + 0x0e) /* Index register 8-bit */ -++#define USB_REG_TESTMODE (USB_BASE + 0x0f) /* USB test mode 8-bit */ -++ -++#define USB_REG_CSR0 (USB_BASE + 0x12) /* EP0 CSR 8-bit */ -++#define USB_REG_INMAXP (USB_BASE + 0x10) /* EP1-2 IN Max Pkt Size 16-bit */ -++#define USB_REG_INCSR (USB_BASE + 0x12) /* EP1-2 IN CSR LSB 8/16bit */ -++#define USB_REG_INCSRH (USB_BASE + 0x13) /* EP1-2 IN CSR MSB 8-bit */ -++#define USB_REG_OUTMAXP (USB_BASE + 0x14) /* EP1 OUT Max Pkt Size 16-bit */ -++#define USB_REG_OUTCSR (USB_BASE + 0x16) /* EP1 OUT CSR LSB 8/16bit */ -++#define USB_REG_OUTCSRH (USB_BASE + 0x17) /* EP1 OUT CSR MSB 8-bit */ -++#define USB_REG_OUTCOUNT (USB_BASE + 0x18) /* bytes in EP0/1 OUT FIFO 16-bit */ -++ -++#define USB_FIFO_EP0 (USB_BASE + 0x20) -++#define USB_FIFO_EP1 (USB_BASE + 0x24) -++#define USB_FIFO_EP2 (USB_BASE + 0x28) -++ -++#define USB_REG_EPINFO (USB_BASE + 0x78) /* Endpoint information */ -++#define USB_REG_RAMINFO (USB_BASE + 0x79) /* RAM information */ -++ -++#define USB_REG_INTR (USB_BASE + 0x200) /* DMA pending interrupts */ -++#define USB_REG_CNTL1 (USB_BASE + 0x204) /* DMA channel 1 control */ -++#define USB_REG_ADDR1 (USB_BASE + 0x208) /* DMA channel 1 AHB memory addr */ -++#define USB_REG_COUNT1 (USB_BASE + 0x20c) /* DMA channel 1 byte count */ -++#define USB_REG_CNTL2 (USB_BASE + 0x214) /* DMA channel 2 control */ -++#define USB_REG_ADDR2 (USB_BASE + 0x218) /* DMA channel 2 AHB memory addr */ -++#define USB_REG_COUNT2 (USB_BASE + 0x21c) /* DMA channel 2 byte count */ -++ -++ -++/* Power register bit masks */ -++#define USB_POWER_SUSPENDM 0x01 -++#define USB_POWER_RESUME 0x04 -++#define USB_POWER_HSMODE 0x10 -++#define USB_POWER_HSENAB 0x20 -++#define USB_POWER_SOFTCONN 0x40 -++ -++/* Interrupt register bit masks */ -++#define USB_INTR_SUSPEND 0x01 -++#define USB_INTR_RESUME 0x02 -++#define USB_INTR_RESET 0x04 -++ -++#define USB_INTR_EP0 0x0001 -++#define USB_INTR_INEP1 0x0002 -++#define USB_INTR_INEP2 0x0004 -++#define USB_INTR_OUTEP1 0x0002 -++ -++/* CSR0 bit masks */ -++#define USB_CSR0_OUTPKTRDY 0x01 -++#define USB_CSR0_INPKTRDY 0x02 -++#define USB_CSR0_SENTSTALL 0x04 -++#define USB_CSR0_DATAEND 0x08 -++#define USB_CSR0_SETUPEND 0x10 -++#define USB_CSR0_SENDSTALL 0x20 -++#define USB_CSR0_SVDOUTPKTRDY 0x40 -++#define USB_CSR0_SVDSETUPEND 0x80 -++ -++/* Endpoint CSR register bits */ -++#define USB_INCSRH_AUTOSET 0x80 -++#define USB_INCSRH_ISO 0x40 -++#define USB_INCSRH_MODE 0x20 -++#define USB_INCSRH_DMAREQENAB 0x10 -++#define USB_INCSRH_DMAREQMODE 0x04 -++#define USB_INCSR_CDT 0x40 -++#define USB_INCSR_SENTSTALL 0x20 -++#define USB_INCSR_SENDSTALL 0x10 -++#define USB_INCSR_FF 0x08 -++#define USB_INCSR_UNDERRUN 0x04 -++#define USB_INCSR_FFNOTEMPT 0x02 -++#define USB_INCSR_INPKTRDY 0x01 -++#define USB_OUTCSRH_AUTOCLR 0x80 -++#define USB_OUTCSRH_ISO 0x40 -++#define USB_OUTCSRH_DMAREQENAB 0x20 -++#define USB_OUTCSRH_DNYT 0x10 -++#define USB_OUTCSRH_DMAREQMODE 0x08 -++#define USB_OUTCSR_CDT 0x80 -++#define USB_OUTCSR_SENTSTALL 0x40 -++#define USB_OUTCSR_SENDSTALL 0x20 -++#define USB_OUTCSR_FF 0x10 -++#define USB_OUTCSR_DATAERR 0x08 -++#define USB_OUTCSR_OVERRUN 0x04 -++#define USB_OUTCSR_FFFULL 0x02 -++#define USB_OUTCSR_OUTPKTRDY 0x01 -++ -++/* Testmode register bits */ -++#define USB_TEST_SE0NAK 0x01 -++#define USB_TEST_J 0x02 -++#define USB_TEST_K 0x04 -++#define USB_TEST_PACKET 0x08 -++ -++/* DMA control bits */ -++#define USB_CNTL_ENA 0x01 -++#define USB_CNTL_DIR_IN 0x02 -++#define USB_CNTL_MODE_1 0x04 -++#define USB_CNTL_INTR_EN 0x08 -++#define USB_CNTL_EP(n) ((n) << 4) -++#define USB_CNTL_BURST_0 (0 << 9) -++#define USB_CNTL_BURST_4 (1 << 9) -++#define USB_CNTL_BURST_8 (2 << 9) -++#define USB_CNTL_BURST_16 (3 << 9) -++ -++#endif /* __JZ4740_REGS_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4740/serial.h linux-2.6.24.7/include/asm-mips/mach-jz4740/serial.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4740/serial.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4740/serial.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,30 @@ -++/* -++ * linux/include/asm-mips/mach-jz4740/serial.h -++ * -++ * Ingenic's JZ4740 common include. -++ * -++ * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_BOARD_SERIAL_H__ -++#define __ASM_BOARD_SERIAL_H__ -++ -++#ifndef CONFIG_SERIAL_MANY_PORTS -++#undef RS_TABLE_SIZE -++#define RS_TABLE_SIZE 1 -++#endif -++ -++#define JZ_BASE_BAUD (12000000/16) -++ -++#define JZ_SERIAL_PORT_DEFNS \ -++ { .baud_base = JZ_BASE_BAUD, .irq = IRQ_UART0, \ -++ .flags = STD_COM_FLAGS, .iomem_base = (u8 *)UART0_BASE, \ -++ .iomem_reg_shift = 2, .io_type = SERIAL_IO_MEM }, -++ -++#endif /* __ASM_BORAD_SERIAL_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4740/war.h linux-2.6.24.7/include/asm-mips/mach-jz4740/war.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4740/war.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4740/war.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,25 @@ -++/* -++ * This file is subject to the terms and conditions of the GNU General Public -++ * License. See the file "COPYING" in the main directory of this archive -++ * for more details. -++ * -++ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle -++ */ -++#ifndef __ASM_MIPS_MACH_JZ4740_WAR_H -++#define __ASM_MIPS_MACH_JZ4740_WAR_H -++ -++#define R4600_V1_INDEX_ICACHEOP_WAR 0 -++#define R4600_V1_HIT_CACHEOP_WAR 0 -++#define R4600_V2_HIT_CACHEOP_WAR 0 -++#define R5432_CP0_INTERRUPT_WAR 0 -++#define BCM1250_M3_WAR 0 -++#define SIBYTE_1956_WAR 0 -++#define MIPS4K_ICACHE_REFILL_WAR 0 -++#define MIPS_CACHE_SYNC_WAR 0 -++#define TX49XX_ICACHE_INDEX_INV_WAR 0 -++#define RM9000_CDEX_SMP_WAR 0 -++#define ICACHE_REFILLS_WORKAROUND_WAR 0 -++#define R10000_LLSC_WAR 0 -++#define MIPS34K_MISSED_ITLB_WAR 0 -++ -++#endif /* __ASM_MIPS_MACH_JZ4740_WAR_H */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4750/board-apus.h linux-2.6.24.7/include/asm-mips/mach-jz4750/board-apus.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4750/board-apus.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4750/board-apus.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,119 @@ -++/* -++ * linux/include/asm-mips/mach-jz4750/board-apus.h -++ * -++ * JZ4750-based APUS board ver 1.x definition. -++ * -++ * Copyright (C) 2008 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4750_APUS_H__ -++#define __ASM_JZ4750_APUS_H__ -++ -++/*====================================================================== -++ * Frequencies of on-board oscillators -++ */ -++#define JZ_EXTAL 24000000 /* Main extal freq: 24 MHz */ -++#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -++ -++/*====================================================================== -++ * GPIO -++ */ -++#define GPIO_DISP_OFF_N (32*4+25) /* GPE25 */ -++#define GPIO_SD0_VCC_EN_N (32*2+10) /* GPC10 */ -++#define GPIO_SD0_CD_N (32*2+11) /* GPC11 */ -++#define GPIO_SD0_WP (32*2+12) /* GPC12 */ -++#define GPIO_SD1_VCC_EN_N (32*2+13) /* GPC13 */ -++#define GPIO_SD1_CD_N (32*2+14) /* GPC14 */ -++#define GPIO_USB_DETE (32*2+11) /* GPC15 */ -++#define GPIO_DC_DETE_N (32*2+8) /* GPC8 */ -++#define GPIO_CHARG_STAT_N (32*2+9) /* GPC9 */ -++#define GPIO_LCD_VCC_EN_N (32*3+30) /* GPC10 */ -++#define GPIO_LCD_PWM (32*4+24) /* GPE24 */ -++#define GPIO_UDC_HOTPLUG GPIO_USB_DETE -++ -++ -++/*====================================================================== -++ * LCD backlight -++ */ -++#define LCD_PWM_CHN 4 /* pwm channel */ -++#define LCD_PWM_FULL 101 -++/* 100 level: 0,1,...,100 */ -++#define __lcd_set_backlight_level(n) \ -++do { \ -++ __gpio_as_output(GPIO_LCD_PWM); \ -++ __gpio_set_pin(GPIO_LCD_PWM); \ -++} while (0) -++ -++#define __lcd_close_backlight() \ -++do { \ -++ __gpio_as_output(GPIO_LCD_PWM); \ -++ __gpio_clear_pin(GPIO_LCD_PWM); \ -++} while (0) -++ -++/*====================================================================== -++ * MMC/SD -++ */ -++ -++#define MSC0_WP_PIN GPIO_SD0_WP -++#define MSC0_HOTPLUG_PIN GPIO_SD0_CD_N -++#define MSC0_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD0_CD_N) -++ -++#define MSC1_WP_PIN GPIO_SD1_WP -++#define MSC1_HOTPLUG_PIN GPIO_SD1_CD_N -++#define MSC1_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD1_CD_N) -++ -++#define __msc0_init_io() \ -++do { \ -++ __gpio_as_output(GPIO_SD0_VCC_EN_N); \ -++ __gpio_as_input(GPIO_SD0_CD_N); \ -++} while (0) -++ -++#define __msc0_enable_power() \ -++do { \ -++ __gpio_clear_pin(GPIO_SD0_VCC_EN_N); \ -++} while (0) -++ -++#define __msc0_disable_power() \ -++do { \ -++ __gpio_set_pin(GPIO_SD0_VCC_EN_N); \ -++} while (0) -++ -++#define __msc0_card_detected(s) \ -++({ \ -++ int detected = 1; \ -++ if (__gpio_get_pin(GPIO_SD0_CD_N)) \ -++ detected = 0; \ -++ detected; \ -++}) -++ -++#define __msc1_init_io() \ -++do { \ -++ __gpio_as_output(GPIO_SD1_VCC_EN_N); \ -++ __gpio_as_input(GPIO_SD1_CD_N); \ -++} while (0) -++ -++#define __msc1_enable_power() \ -++do { \ -++ __gpio_clear_pin(GPIO_SD1_VCC_EN_N); \ -++} while (0) -++ -++#define __msc1_disable_power() \ -++do { \ -++ __gpio_set_pin(GPIO_SD1_VCC_EN_N); \ -++} while (0) -++ -++#define __msc1_card_detected(s) \ -++({ \ -++ int detected = 0; \ -++ if (__gpio_get_pin(GPIO_SD1_CD_N)) \ -++ detected = 1; \ -++ detected; \ -++}) -++ -++#endif /* __ASM_JZ4750_APUS_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4750/board-fuwa.h linux-2.6.24.7/include/asm-mips/mach-jz4750/board-fuwa.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4750/board-fuwa.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4750/board-fuwa.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,93 @@ -++/* -++ * linux/include/asm-mips/mach-jz4750/board-fuwa.h -++ * -++ * JZ4750-based FUWA board ver 1.x definition. -++ * -++ * Copyright (C) 2008 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4750_FUWA_H__ -++#define __ASM_JZ4750_FUWA_H__ -++ -++#define CONFIG_FPGA /* fuwa is an FPGA board */ -++ -++/*====================================================================== -++ * Frequencies of on-board oscillators -++ */ -++#define JZ_EXTAL 48000000 /* Main extal freq: 12 MHz */ -++#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -++ -++ -++/*====================================================================== -++ * GPIO -++ */ -++#define GPIO_SD_VCC_EN_N 113 /* GPD17 */ -++#define GPIO_SD_CD_N 110 /* GPD14 */ -++#define GPIO_SD_WP 112 /* GPD16 */ -++#define GPIO_USB_DETE 102 /* GPD6 */ -++#define GPIO_DC_DETE_N 103 /* GPD7 */ -++#define GPIO_CHARG_STAT_N 111 /* GPD15 */ -++#define GPIO_DISP_OFF_N 121 /* GPD25, LCD_REV */ -++#define GPIO_LED_EN 124 /* GPD28 */ -++ -++#define GPIO_UDC_HOTPLUG GPIO_USB_DETE -++ -++/*====================================================================== -++ * LCD backlight -++ */ -++#define GPIO_LCD_PWM (32*4+20) /* GPE20 */ -++ -++#define LCD_PWM_CHN 0 /* pwm channel */ -++#define LCD_PWM_FULL 101 -++/* 100 level: 0,1,...,100 */ -++#define __lcd_set_backlight_level(n) \ -++do { \ -++ __gpio_as_output(GPIO_LCD_PWM); \ -++ __gpio_set_pin(GPIO_LCD_PWM); \ -++} while (0) -++ -++#define __lcd_close_backlight() \ -++do { \ -++ __gpio_as_output(GPIO_LCD_PWM); \ -++ __gpio_clear_pin(GPIO_LCD_PWM); \ -++} while (0) -++ -++/*====================================================================== -++ * MMC/SD -++ */ -++ -++#define MSC_WP_PIN GPIO_SD_WP -++#define MSC_HOTPLUG_PIN GPIO_SD_CD_N -++#define MSC_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD_CD_N) -++ -++#define __msc_init_io() \ -++do { \ -++ __gpio_as_output(GPIO_SD_VCC_EN_N); \ -++ __gpio_as_input(GPIO_SD_CD_N); \ -++} while (0) -++ -++#define __msc_enable_power() \ -++do { \ -++ __gpio_clear_pin(GPIO_SD_VCC_EN_N); \ -++} while (0) -++ -++#define __msc_disable_power() \ -++do { \ -++ __gpio_set_pin(GPIO_SD_VCC_EN_N); \ -++} while (0) -++ -++#define __msc_card_detected(s) \ -++({ \ -++ int detected = 1; \ -++ if (__gpio_get_pin(GPIO_SD_CD_N)) \ -++ detected = 0; \ -++ detected; \ -++}) -++ -++#endif /* __ASM_JZ4750_FUWA_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4750/clock.h linux-2.6.24.7/include/asm-mips/mach-jz4750/clock.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4750/clock.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4750/clock.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,204 @@ -++/* -++ * linux/include/asm-mips/mach-jz4750/clock.h -++ * -++ * JZ4750 clocks definition. -++ * -++ * Copyright (C) 2008 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4750_CLOCK_H__ -++#define __ASM_JZ4750_CLOCK_H__ -++ -++#ifndef JZ_EXTAL -++#define JZ_EXTAL 12000000 /* 3.6864 MHz */ -++#endif -++#ifndef JZ_EXTAL2 -++#define JZ_EXTAL2 32768 /* 32.768 KHz */ -++#endif -++ -++/* -++ * JZ4750 clocks structure -++ */ -++typedef struct { -++ unsigned int cclk; /* CPU clock */ -++ unsigned int hclk; /* System bus clock */ -++ unsigned int pclk; /* Peripheral bus clock */ -++ unsigned int mclk; /* Flash/SRAM/SDRAM clock */ -++ unsigned int lcdclk; /* LCDC module clock */ -++ unsigned int pixclk; /* LCD pixel clock */ -++ unsigned int i2sclk; /* AIC module clock */ -++ unsigned int usbclk; /* USB module clock */ -++ unsigned int mscclk; /* MSC module clock */ -++ unsigned int extalclk; /* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */ -++ unsigned int rtcclk; /* RTC clock for CPM,INTC,RTC,TCU,WDT */ -++} jz_clocks_t; -++ -++extern jz_clocks_t jz_clocks; -++ -++ -++/* PLL output frequency */ -++static __inline__ unsigned int __cpm_get_pllout(void) -++{ -++ unsigned long m, n, no, pllout; -++ unsigned long cppcr = REG_CPM_CPPCR; -++ unsigned long od[4] = {1, 2, 2, 4}; -++ if ((cppcr & CPM_CPPCR_PLLEN) && !(cppcr & CPM_CPPCR_PLLBP)) { -++ m = __cpm_get_pllm() + 2; -++ n = __cpm_get_plln() + 2; -++ no = od[__cpm_get_pllod()]; -++ pllout = ((JZ_EXTAL) / (n * no)) * m; -++ } else -++ pllout = JZ_EXTAL; -++ return pllout; -++} -++ -++/* PLL output frequency for MSC/I2S/LCD/USB */ -++static __inline__ unsigned int __cpm_get_pllout2(void) -++{ -++ if (REG_CPM_CPCCR & CPM_CPCCR_PCS) -++ return __cpm_get_pllout(); -++ else -++ return __cpm_get_pllout()/2; -++} -++ -++/* CPU core clock */ -++static __inline__ unsigned int __cpm_get_cclk(void) -++{ -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ -++ return __cpm_get_pllout() / div[__cpm_get_cdiv()]; -++} -++ -++/* AHB system bus clock */ -++static __inline__ unsigned int __cpm_get_hclk(void) -++{ -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ -++ return __cpm_get_pllout() / div[__cpm_get_hdiv()]; -++} -++ -++/* Memory bus clock */ -++static __inline__ unsigned int __cpm_get_mclk(void) -++{ -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ -++ return __cpm_get_pllout() / div[__cpm_get_mdiv()]; -++} -++ -++/* APB peripheral bus clock */ -++static __inline__ unsigned int __cpm_get_pclk(void) -++{ -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ -++ return __cpm_get_pllout() / div[__cpm_get_pdiv()]; -++} -++ -++/* LCDC module clock */ -++static __inline__ unsigned int __cpm_get_lcdclk(void) -++{ -++ return __cpm_get_pllout2() / (__cpm_get_ldiv() + 1); -++} -++ -++/* LCD pixel clock */ -++static __inline__ unsigned int __cpm_get_pixclk(void) -++{ -++ return __cpm_get_pllout2() / (__cpm_get_pixdiv() + 1); -++} -++ -++/* I2S clock */ -++static __inline__ unsigned int __cpm_get_i2sclk(void) -++{ -++ if (REG_CPM_CPCCR & CPM_CPCCR_I2CS) { -++ return __cpm_get_pllout2() / (__cpm_get_i2sdiv() + 1); -++ } -++ else { -++ return JZ_EXTAL; -++ } -++} -++ -++/* USB clock */ -++static __inline__ unsigned int __cpm_get_usbclk(void) -++{ -++ if (REG_CPM_CPCCR & CPM_CPCCR_UCS) { -++ return __cpm_get_pllout2() / (__cpm_get_udiv() + 1); -++ } -++ else { -++ return JZ_EXTAL; -++ } -++} -++ -++/* -++ * MSC clock -++ * @n: the index of MMC/SD controller -++ */ -++static __inline__ unsigned int __cpm_get_mscclk(int n) -++{ -++ return __cpm_get_pllout2() / (__cpm_get_mscdiv(n) + 1); -++} -++ -++/* EXTAL clock */ -++static __inline__ unsigned int __cpm_get_extalclk0(void) -++{ -++ return JZ_EXTAL; -++} -++ -++/* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */ -++static __inline__ unsigned int __cpm_get_extalclk(void) -++{ -++#if defined(CONFIG_FPGA) -++ return JZ_EXTAL; -++#else -++ if (REG_CPM_CPCCR & CPM_CPCCR_ECS) -++ return __cpm_get_extalclk0()/2; -++ else -++ return __cpm_get_extalclk0(); -++#endif -++} -++ -++/* RTC clock for CPM,INTC,RTC,TCU,WDT */ -++static __inline__ unsigned int __cpm_get_rtcclk(void) -++{ -++ return JZ_EXTAL2; -++} -++ -++/* -++ * Output 24MHz for SD and 16MHz for MMC. -++ * @n: the index of MMC/SD controller -++ */ -++static inline void __cpm_select_msc_clk(int n, int sd) -++{ -++ unsigned int pllout2 = __cpm_get_pllout2(); -++ unsigned int div = 0; -++ -++ if (sd) { -++ div = pllout2 / 24000000; -++ } -++ else { -++ div = pllout2 / 16000000; -++ } -++ -++ REG_CPM_MSCCDR(n) = div - 1; -++ REG_CPM_CPCCR |= CPM_CPCCR_CE; -++} -++ -++/* -++ * Output 48MHz for high speed card. -++ */ -++static inline void __cpm_select_msc_clk_high(int n, int sd) -++{ -++ unsigned int pllout2 = __cpm_get_pllout2(); -++ unsigned int div = 0; -++ -++ div = pllout2 / 48000000; -++ -++ REG_CPM_MSCCDR(n) = div - 1; -++ REG_CPM_CPCCR |= CPM_CPCCR_CE; -++} -++ -++#endif /* __ASM_JZ4750_CLOCK_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4750/dma.h linux-2.6.24.7/include/asm-mips/mach-jz4750/dma.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4750/dma.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4750/dma.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,307 @@ -++/* -++ * linux/include/asm-mips/mach-jz4750/dma.h -++ * -++ * JZ4750 DMA definition. -++ * -++ * Copyright (C) 2008 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4750_DMA_H__ -++#define __ASM_JZ4750_DMA_H__ -++ -++#include -++#include /* need byte IO */ -++#include /* And spinlocks */ -++#include -++#include -++ -++/* -++ * Descriptor structure for JZ4750 DMA engine -++ * Note: this structure must always be aligned to a 16-bytes boundary. -++ */ -++ -++/* old descriptor 4-word */ -++typedef struct { -++ volatile u32 dcmd; /* DCMD value for the current transfer */ -++ volatile u32 dsadr; /* DSAR value for the current transfer */ -++ volatile u32 dtadr; /* DTAR value for the current transfer */ -++ volatile u32 ddadr; /* Points to the next descriptor + transfer count */ -++} jz_dma_desc; -++ -++/* new descriptor 8-word */ -++typedef struct { -++ volatile u32 dcmd; /* DCMD value for the current transfer */ -++ volatile u32 dsadr; /* DSAR value for the current transfer */ -++ volatile u32 dtadr; /* DTAR value for the current transfer */ -++ volatile u32 ddadr; /* Points to the next descriptor + transfer count */ -++ volatile u32 dstrd; /* DMA source and target stride address */ -++ volatile u32 dreqt; /* DMA request type for current transfer */ -++ volatile u32 reserved0; /* Reserved */ -++ volatile u32 reserved1; /* Reserved */ -++} jz_dma_desc_8word; -++ -++/* DMA Device ID's follow */ -++enum { -++ DMA_ID_EXT = 0, /* External request with DREQn */ -++ DMA_ID_NAND, /* NAND DMA request */ -++ DMA_ID_BCH_ENC, /* BCH Encoding DMA request */ -++ DMA_ID_BCH_DEC, /* BCH Decoding DMA request */ -++ DMA_ID_AUTO, /* Auto-request */ -++// DMA_ID_TSSI_RX, /* TSSI receive fifo full request */ -++ DMA_ID_UART3_TX, /* UART3 transmit-fifo-empty request */ -++ DMA_ID_UART3_RX, /* UART3 receve-fifo-full request */ -++ DMA_ID_UART2_TX, /* UART2 transmit-fifo-empty request */ -++ DMA_ID_UART2_RX, /* UART2 receve-fifo-full request */ -++ DMA_ID_UART1_TX, /* UART1 transmit-fifo-empty request */ -++ DMA_ID_UART1_RX, /* UART1 receve-fifo-full request */ -++ DMA_ID_UART0_TX, /* UART0 transmit-fifo-empty request */ -++ DMA_ID_UART0_RX, /* UART0 receve-fifo-full request */ -++ DMA_ID_SSI0_TX, /* SSI0 transmit-fifo-full request */ -++ DMA_ID_SSI0_RX, /* SSI0 receive-fifo-empty request */ -++ DMA_ID_AIC_TX, /* AIC transmit-fifo-full request */ -++ DMA_ID_AIC_RX, /* AIC receive-fifo-empty request */ -++ DMA_ID_MSC0_TX, /* MSC0 transmit-fifo-full request */ -++ DMA_ID_MSC0_RX, /* MSC0 receive-fifo-empty request */ -++ DMA_ID_TCU_OVERFLOW, /* TCU channel n overflow interrupt */ -++ DMA_ID_SADC, /* SADC transfer request */ -++ DMA_ID_MSC1_TX, /* MSC1 transmit-fifo-full request */ -++ DMA_ID_MSC1_RX, /* MSC1 receive-fifo-empty request */ -++ DMA_ID_SSI1_TX, /* SSI1 transmit-fifo-full request */ -++ DMA_ID_SSI1_RX, /* SSI1 receive-fifo-empty request */ -++ DMA_ID_PCM_TX, /* PM transmit-fifo-full request */ -++ DMA_ID_PCM_RX, /* PM receive-fifo-empty request */ -++ DMA_ID_RAW_SET, -++ DMA_ID_MAX -++}; -++ -++/* DMA modes, simulated by sw */ -++#define DMA_MODE_READ 0x0 /* I/O to memory, no autoinit, increment, single mode */ -++#define DMA_MODE_WRITE 0x1 /* memory to I/O, no autoinit, increment, single mode */ -++#define DMA_AUTOINIT 0x2 -++#define DMA_MODE_MASK 0x3 -++ -++struct jz_dma_chan { -++ int dev_id; /* DMA ID: this channel is allocated if >=0, free otherwise */ -++ unsigned int io; /* DMA channel number */ -++ const char *dev_str; /* string describes the DMA channel */ -++ int irq; /* DMA irq number */ -++ void *irq_dev; /* DMA private device structure */ -++ unsigned int fifo_addr; /* physical fifo address of the requested device */ -++ unsigned int cntl; /* DMA controll */ -++ unsigned int mode; /* DMA configuration */ -++ unsigned int source; /* DMA request source */ -++}; -++ -++extern struct jz_dma_chan jz_dma_table[]; -++ -++ -++#define DMA_8BIT_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_8BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_8BIT_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -++ DMAC_DCMD_DS_8BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_16BIT_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_16BIT_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_32BIT_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_32BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_32BIT_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_32BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_16BYTE_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_16BYTE_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_32BYTE_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_32BYTE_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -++ DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_32_32BYTE_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN -++#define DMA_AIC_32_16BYTE_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_32_16BYTE_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_16BIT_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_16BIT_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_16BYTE_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_16BYTE_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_16BYTE_TX_CMD_UC \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++extern int jz_request_dma(int dev_id, -++ const char *dev_str, -++ irqreturn_t (*irqhandler)(int, void *), -++ unsigned long irqflags, -++ void *irq_dev_id); -++extern void jz_free_dma(unsigned int dmanr); -++ -++extern int jz_dma_read_proc(char *buf, char **start, off_t fpos, -++ int length, int *eof, void *data); -++extern void dump_jz_dma_channel(unsigned int dmanr); -++ -++extern void enable_dma(unsigned int dmanr); -++extern void disable_dma(unsigned int dmanr); -++extern void set_dma_addr(unsigned int dmanr, unsigned int phyaddr); -++extern void set_dma_count(unsigned int dmanr, unsigned int bytecnt); -++extern void set_dma_mode(unsigned int dmanr, unsigned int mode); -++extern void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); -++extern void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); -++extern void jz_set_dma_src_width(int dmanr, int nbit); -++extern void jz_set_dma_dest_width(int dmanr, int nbit); -++extern void jz_set_dma_block_size(int dmanr, int nbyte); -++extern unsigned int get_dma_residue(unsigned int dmanr); -++ -++extern spinlock_t dma_spin_lock; -++ -++static __inline__ unsigned long claim_dma_lock(void) -++{ -++ unsigned long flags; -++ spin_lock_irqsave(&dma_spin_lock, flags); -++ return flags; -++} -++ -++static __inline__ void release_dma_lock(unsigned long flags) -++{ -++ spin_unlock_irqrestore(&dma_spin_lock, flags); -++} -++ -++/* Clear the 'DMA Pointer Flip Flop'. -++ * Write 0 for LSB/MSB, 1 for MSB/LSB access. -++ */ -++#define clear_dma_ff(channel) -++ -++static __inline__ struct jz_dma_chan *get_dma_chan(unsigned int dmanr) -++{ -++ if (dmanr > MAX_DMA_NUM -++ || jz_dma_table[dmanr].dev_id < 0) -++ return NULL; -++ return &jz_dma_table[dmanr]; -++} -++ -++static __inline__ int dma_halted(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return 1; -++ return __dmac_channel_transmit_halt_detected(dmanr) ? 1 : 0; -++} -++ -++static __inline__ unsigned int get_dma_mode(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return 0; -++ return chan->mode; -++} -++ -++static __inline__ void clear_dma_done(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -++} -++ -++static __inline__ void clear_dma_halt(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT); -++ REG_DMAC_DMACR((chan->io)/HALF_DMA_NUM) &= ~(DMAC_DMACR_HLT); -++} -++ -++static __inline__ void clear_dma_flag(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -++ REG_DMAC_DMACR((chan->io)/HALF_DMA_NUM) &= ~(DMAC_DMACR_HLT | DMAC_DMACR_AR); -++} -++ -++static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) -++{ -++} -++ -++static __inline__ unsigned int get_dma_done_status(unsigned int dmanr) -++{ -++ unsigned long dccsr; -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return 0; -++ dccsr = REG_DMAC_DCCSR(chan->io); -++ return dccsr & (DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -++} -++ -++static __inline__ int get_dma_done_irq(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return -1; -++ return chan->irq; -++} -++ -++#endif /* __ASM_JZ4750_DMA_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4750/jz4750.h linux-2.6.24.7/include/asm-mips/mach-jz4750/jz4750.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4750/jz4750.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4750/jz4750.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,44 @@ -++/* -++ * linux/include/asm-mips/mach-jz4750/jz4750.h -++ * -++ * JZ4750 common definition. -++ * -++ * Copyright (C) 2008 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4750_H__ -++#define __ASM_JZ4750_H__ -++ -++#include -++#include -++#include -++#include -++ -++/*------------------------------------------------------------------ -++ * Platform definitions -++ */ -++#ifdef CONFIG_JZ4750_FUWA -++#include -++#endif -++ -++#ifdef CONFIG_JZ4750_APUS -++#include -++#endif -++ -++/* Add other platform definition here ... */ -++ -++ -++/*------------------------------------------------------------------ -++ * Follows are related to platform definitions -++ */ -++ -++#include -++#include -++ -++#endif /* __ASM_JZ4750_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4750/misc.h linux-2.6.24.7/include/asm-mips/mach-jz4750/misc.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4750/misc.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4750/misc.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,44 @@ -++/* -++ * linux/include/asm-mips/mach-jz4750/misc.h -++ * -++ * Ingenic's JZ4750 common include. -++ * -++ * Copyright (C) 2008 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4750_MISC_H__ -++#define __ASM_JZ4750_MISC_H__ -++ -++/*========================================================== -++ * I2C -++ *===========================================================*/ -++ -++#define I2C_EEPROM_DEV 0xA /* b'1010 */ -++#define I2C_RTC_DEV 0xD /* b'1101 */ -++#define DIMM0_SPD_ADDR 0 -++#define DIMM1_SPD_ADDR 1 -++#define DIMM2_SPD_ADDR 2 -++#define DIMM3_SPD_ADDR 3 -++#define JZ_HCI_ADDR 7 -++ -++#define DIMM_SPD_LEN 128 -++#define JZ_HCI_LEN 512 /* 4K bits E2PROM */ -++#define I2C_RTC_LEN 16 -++#define HCI_MAC_OFFSET 64 -++ -++extern void i2c_open(void); -++extern void i2c_close(void); -++extern void i2c_setclk(unsigned int i2cclk); -++ -++extern int i2c_read(unsigned char device, unsigned char *buf, -++ unsigned char address, int count); -++extern int i2c_write(unsigned char device, unsigned char *buf, -++ unsigned char address, int count); -++ -++#endif /* __ASM_JZ4750_MISC_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4750/ops.h linux-2.6.24.7/include/asm-mips/mach-jz4750/ops.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4750/ops.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4750/ops.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,3569 @@ -++/* -++ * linux/include/asm-mips/mach-jz4750/ops.h -++ * -++ * JZ4750 register definition. -++ * -++ * Copyright (C) 2008 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++ -++#ifndef __JZ4750_OPS_H__ -++#define __JZ4750_OPS_H__ -++ -++/* -++ * Definition of Module Operations -++ */ -++ -++/*************************************************************************** -++ * EMC -++ ***************************************************************************/ -++#define is_share_mode() ((REG_EMC_BCR & EMC_BCR_BSR_MASK) == EMC_BCR_BSR_SHARE) -++#define is_normal_order() (!(REG_EMC_BCR & EMC_BCR_PK_SEL)) -++ -++/*************************************************************************** -++ * GPIO -++ ***************************************************************************/ -++ -++//------------------------------------------------------ -++// GPIO Pins Description -++// -++// PORT 0: -++// -++// PIN/BIT N FUNC0 FUNC1 NOTE -++// 0 D0 - -++// 1 D1 - -++// 2 D2 - -++// 3 D3 - -++// 4 D4 - -++// 5 D5 - -++// 6 D6 - -++// 7 D7 - -++// 8 D8 - -++// 9 D9 - -++// 10 D10 - -++// 11 D11 - -++// 12 D12 - -++// 13 D13 - -++// 14 D14 - -++// 15 D15 - -++// 16 D16 - -++// 17 D17 - -++// 18 D18 - -++// 19 D19 - -++// 20 D20 - -++// 21 D21 - -++// 22 D22 - -++// 23 D23 - -++// 24 D24 - -++// 25 D25 - -++// 26 D26 - -++// 27 D27 - -++// 28 D28 - -++// 29 D29 - -++// 30 D30 - -++// 31 D31 - -++// -++//------------------------------------------------------ -++// PORT 1: -++// -++// PIN/BIT N FUNC0 FUNC1 NOTE -++// 0 A0 - -++// 1 A1 - -++// 2 A2 - -++// 3 A3 - -++// 4 A4 - -++// 5 A5 - -++// 6 A6 - -++// 7 A7 - -++// 8 A8 - -++// 9 A9 - -++// 10 A10 - -++// 11 A11 - -++// 12 A12 - -++// 13 A13 - -++// 14 A14 - -++// 15 A15/CLE SA3 -++// 16 DCS0# - -++// 17 RAS# - -++// 18 CAS# - -++// 19 RDWE#/BUFD# - -++// 20 WE0# - -++// 21 WE1# - -++// 22 WE2# - -++// 23 WE3# - -++// 24 CKO - Note1 -++// 25 CKE - -++// 26 SSI0_CLK - -++// 27 SSI0_DT - -++// 28 SSI0_DR - -++// 29 SSI0_CE0# - -++// 30 SSI0_CE1#_GPC - -++// 31 SSI0_CE2# - -++// -++// Note1: BIT24: it is CKO when chip is reset -++// -++//------------------------------------------------------ -++// PORT 2: -++// -++// PIN/BIT N FUNC0 FUNC1 NOTE -++// 0 SD0 A20 -++// 1 SD1 A21 -++// 2 SD2 A22 -++// 3 SD3 A23 -++// 4 SD4 A24 -++// 5 SD5 A25 -++// 6 SD6 - -++// 7 SD7 - -++// 8 SD8 TSDI0 -++// 9 SD9 TSDI1 -++// 10 SD10 TSDI2 -++// 11 SD11 TSDI3 -++// 12 SD12 TSDI4 -++// 13 SD13 TSDI5 -++// 14 SD14 TSDI6 -++// 15 SD15 TSDI7 -++// 16 A16/ALE SA4 -++// 17 SA0 A17 -++// 18 SA1 A18 -++// 19 SA2 A19 -++// 20 WAIT# - Note2 -++// 21 CS1# - -++// 22 CS2# - -++// 23 CS3# - -++// 24 CS4# - -++// 25 RD# - -++// 26 WR# - -++// 27 FRB# - Note3 -++// 28 FRE# - -++// 29 FWE# - -++// 30 BOOT_SEL0 - Note4 -++// 31 BOOT_SEL1 - Note5 -++// -++// Note2: BIT20: it is WAIT# pin when chip is reset -++// -++// Note3: BIT27: when NAND is used, it should connect to NANF FRB#. -++// -++// Note4: BIT30: it is BOOT_SEL0 when chip is reset, it can used as output GPIO. -++// -++// Note5: BIT31: it is BOOT_SEL1 when chip is reset, it can used as general GPIO. -++// -++//------------------------------------------------------ -++// PORT 3: -++// -++// PIN/BIT N FUNC0 FUNC1 NOTE -++// 0 LCD_D0 - -++// 1 LCD_D1 - -++// 2 LCD_D2 - -++// 3 LCD_D3 - -++// 4 LCD_D4 - -++// 5 LCD_D5 - -++// 6 LCD_D6 - -++// 7 LCD_D7 - -++// 8 LCD_D8 - -++// 9 LCD_D9 - -++// 10 LCD_D10 - -++// 11 LCD_D11 - -++// 12 LCD_D12 - -++// 13 LCD_D13 - -++// 14 LCD_D14 - -++// 15 LCD_D15 - -++// 16 LCD_D16 - -++// 17 LCD_D17 - -++// 18 LCD_PCLK - -++// 19 LCD_HSYNC - -++// 20 LCD_VSYNC - -++// 21 LCD_DE - -++// 22 LCD_CLS - -++// 23 LCD_SPL - -++// 24 LCD_PS - -++// 25 LCD_REV - -++// 26 SSI1_CLK - -++// 27 SSI1_DT - -++// 28 SSI1_DR - -++// 29 SSI1_CE0# - -++// 30 SSI1_CE1# - -++// 31 - - -++// -++//------------------------------------------------------ -++// PORT 4: -++// -++// PIN/BIT N FUNC0 FUNC1 NOTE -++// 0 CIM_D0 - -++// 1 CIM_D1 - -++// 2 CIM_D2 - -++// 3 CIM_D3 - -++// 4 CIM_D4 - -++// 5 CIM_D5 - -++// 6 CIM_D6 - -++// 7 CIM_D7 - -++// 8 CIM_MCLK - -++// 9 CIM_PCLK - -++// 10 CIM_VSYNC - -++// 11 CIM_HSYNC - -++// 12 I2C_SDA - -++// 13 I2C_SCK - -++// 14 - - -++// 15 - - -++// 16 UART1_RxD - -++// 17 UART1_TxD - -++// 18 UART1_CTS PCM_DIN -++// 19 UART1_RTS PCM_DOUT -++// 20 PWM0 PCM_CLK -++// 21 PWM1 PCM_SYN -++// 22 PWM2 SCLK_RSTN -++// 23 PWM3 BCLK -++// 24 PWM4 SYNC -++// 25 PWM5 OWI -++// 26 SDATO UART2_TxD -++// 27 SDATI UART2_RxD -++// 28 DCS1# - -++// 29 - - -++// 30 WKUP - Note6 -++// 31 - - Note7 -++// -++// Note6: BIT30: it is only used as input and interrupt, and with no pull-up and pull-down -++// -++// Note7: BIT31: it is used to select the function of UART or JTAG set by PESEL[31] -++// PESEL[31] = 0, select JTAG function -++// PESEL[31] = 1, select UART function -++// -++//------------------------------------------------------ -++// PORT 5: -++// -++// PIN/BIT N FUNC0 FUNC1 NOTE -++// 0 MSC0_D0 - -++// 1 MSC0_D1 - -++// 2 MSC0_D2 DREQ -++// 3 MSC0_D3 DACK -++// 4 MSC0_D4 UART0_RxD -++// 5 MSC0_D5 UART0_TxD -++// 6 MSC0_D6 UART0_CTS -++// 7 MSC0_D7 UART0_RTS -++// 8 MSC0_CLK - -++// 9 MSC0_CMD - -++// 10 MSC1_D0 - -++// 11 MSC1_D1 - -++// 12 MSC1_D2 - -++// 13 MSC1_D3 - -++// 14 MSC1_CLK - -++// 15 MSC1_CMD - -++// 16 UART3_RxD - -++// 17 UART3_TxD - -++// 18 UART3_CTS - -++// 19 UART3_RTS - -++// 20 TSCLK - -++// 21 TSSTR - -++// 22 TSFRM - -++// 23 TSFAIL - -++// 24 - - -++// 25 - - -++// 26 - - -++// 27 - - -++// 28 - - -++// 29 - - -++// 30 - - -++// 31 - - -++// -++////////////////////////////////////////////////////////// -++ -++/* -++ * p is the port number (0,1,2,3,4,5) -++ * o is the pin offset (0-31) inside the port -++ * n is the absolute number of a pin (0-191), regardless of the port -++ */ -++ -++//------------------------------------------- -++// Function Pins Mode -++ -++#define __gpio_as_func0(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXFUNS(p) = (1 << o); \ -++ REG_GPIO_PXSELC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_as_func1(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXFUNS(p) = (1 << o); \ -++ REG_GPIO_PXSELS(p) = (1 << o); \ -++} while (0) -++ -++/* -++ * D0 ~ D31, A0 ~ A14, DCS0#, RAS#, CAS#, -++ * RDWE#, WE0#, WE1#, WE2#, WE3#, CKO#, CKE# -++ */ -++#define __gpio_as_sdram_32bit() \ -++do { \ -++ REG_GPIO_PXFUNS(0) = 0xffffffff; \ -++ REG_GPIO_PXSELC(0) = 0xffffffff; \ -++ REG_GPIO_PXPES(0) = 0xffffffff; \ -++ REG_GPIO_PXFUNS(1) = 0x03ff7fff; \ -++ REG_GPIO_PXSELC(1) = 0x03ff7fff; \ -++ REG_GPIO_PXPES(1) = 0x03ff7fff; \ -++} while (0) -++ -++/* -++ * D0 ~ D15, A0 ~ A14, DCS0#, RAS#, CAS#, -++ * RDWE#, WE0#, WE1#, WE2#, WE3#, CKO#, CKE# -++ */ -++#define __gpio_as_sdram_16bit() \ -++do { \ -++ if (is_normal_order()) { \ -++ /* 32/16-bit data normal order */ \ -++ REG_GPIO_PXFUNS(0) = 0x0000ffff; \ -++ REG_GPIO_PXSELC(0) = 0x0000ffff; \ -++ REG_GPIO_PXPES(0) = 0x0000ffff; \ -++ } else { \ -++ /* 16-bit data special order */ \ -++ REG_GPIO_PXFUNS(0) = 0x00ffff00; \ -++ REG_GPIO_PXSELC(0) = 0x00ffff00; \ -++ REG_GPIO_PXPES(0) = 0x00ffff00; \ -++ } \ -++ REG_GPIO_PXFUNS(1) = 0x03ff7fff; \ -++ REG_GPIO_PXSELC(1) = 0x03ff7fff; \ -++ REG_GPIO_PXPES(1) = 0x03ff7fff; \ -++} while (0) -++ -++/* -++ * D0 ~ D7, CS1#, CLE, ALE, FRE#, FWE#, FRB#, RDWE#/BUFD# -++ * @n: chip select number(1 ~ 4) -++ */ -++#define __gpio_as_nand_8bit(n) \ -++do { \ -++ if (!is_share_mode()) { \ -++ /* unshare mode */ \ -++ REG_GPIO_PXFUNS(2) = 0x000000ff; /* SD0~SD7 */ \ -++ REG_GPIO_PXSELS(2) = 0x000000ff; \ -++ REG_GPIO_PXPES(2) = 0x000000ff; \ -++ REG_GPIO_PXFUNS(1) = 0x00008000; /* CLE(SA3) */ \ -++ REG_GPIO_PXSELS(1) = 0x00008000; \ -++ REG_GPIO_PXPES(1) = 0x00008000; \ -++ REG_GPIO_PXFUNS(2) = 0x00010000; /* ALE(SA4) */ \ -++ REG_GPIO_PXSELS(2) = 0x00010000; \ -++ REG_GPIO_PXPES(2) = 0x00010000; \ -++ } else { \ -++ /* share mode */ \ -++ if (is_normal_order()) { \ -++ /* 32/16-bit data normal order */ \ -++ REG_GPIO_PXFUNS(0) = 0x000000ff; /* D0~D7 */ \ -++ REG_GPIO_PXSELC(0) = 0x000000ff; \ -++ REG_GPIO_PXPES(0) = 0x000000ff; \ -++ } else { \ -++ /* 16-bit data special order */ \ -++ REG_GPIO_PXFUNS(0) = 0x0000ff00; /* D0~D7 */ \ -++ REG_GPIO_PXSELC(0) = 0x0000ff00; \ -++ REG_GPIO_PXPES(0) = 0x0000ff00; \ -++ } \ -++ REG_GPIO_PXFUNS(1) = 0x00008000; /* CLE(A15) */ \ -++ REG_GPIO_PXSELC(1) = 0x00008000; \ -++ REG_GPIO_PXPES(1) = 0x00008000; \ -++ REG_GPIO_PXFUNS(2) = 0x00010000; /* ALE(A16) */ \ -++ REG_GPIO_PXSELC(2) = 0x00010000; \ -++ REG_GPIO_PXPES(2) = 0x00010000; \ -++ } \ -++ REG_GPIO_PXFUNS(2) = 0x00200000 << ((n)-1); /* CSn */ \ -++ REG_GPIO_PXSELC(2) = 0x00200000 << ((n)-1); \ -++ REG_GPIO_PXPES(2) = 0x00200000 << ((n)-1); \ -++ \ -++ REG_GPIO_PXFUNS(1) = 0x00080000; /* RDWE#/BUFD# */ \ -++ REG_GPIO_PXSELC(1) = 0x00080000; \ -++ REG_GPIO_PXPES(1) = 0x00080000; \ -++ REG_GPIO_PXFUNS(2) = 0x30000000; /* FRE#, FWE# */ \ -++ REG_GPIO_PXSELC(2) = 0x30000000; \ -++ REG_GPIO_PXPES(2) = 0x30000000; \ -++ REG_GPIO_PXFUNC(2) = 0x08000000; /* FRB#(input) */ \ -++ REG_GPIO_PXSELC(2) = 0x08000000; \ -++ REG_GPIO_PXDIRC(2) = 0x08000000; \ -++ REG_GPIO_PXPES(2) = 0x08000000; \ -++} while (0) -++ -++ -++/* -++ * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D7 -++ * @n: chip select number(1 ~ 4) -++ */ -++#define __gpio_as_nor_8bit(n) \ -++do { \ -++ if (is_normal_order()) { \ -++ /* 32/16-bit data normal order */ \ -++ REG_GPIO_PXFUNS(0) = 0x000000ff; \ -++ REG_GPIO_PXSELC(0) = 0x000000ff; \ -++ REG_GPIO_PXPES(0) = 0x000000ff; \ -++ } else { \ -++ /* 16-bit data special order */ \ -++ REG_GPIO_PXFUNS(0) = 0x0000ff00; \ -++ REG_GPIO_PXSELC(0) = 0x0000ff00; \ -++ REG_GPIO_PXPES(0) = 0x0000ff00; \ -++ } \ -++ REG_GPIO_PXFUNS(2) = 0x00200000 << ((n)-1); /* CSn */ \ -++ REG_GPIO_PXSELC(2) = 0x00200000 << ((n)-1); \ -++ REG_GPIO_PXPES(2) = 0x00200000 << ((n)-1); \ -++ \ -++ REG_GPIO_PXFUNS(1) = 0x0000ffff; /* A0~A15 */ \ -++ REG_GPIO_PXSELC(1) = 0x0000ffff; \ -++ REG_GPIO_PXPES(1) = 0x0000ffff; \ -++ REG_GPIO_PXFUNS(2) = 0x06110007; /* RD#, WR#, WAIT#, A20~A22 */ \ -++ REG_GPIO_PXSELC(2) = 0x06110007; \ -++ REG_GPIO_PXPES(2) = 0x06110007; \ -++ REG_GPIO_PXFUNS(2) = 0x000e0000; /* A17~A19 */ \ -++ REG_GPIO_PXSELS(2) = 0x000e0000; \ -++ REG_GPIO_PXPES(2) = 0x000e0000; \ -++} while (0) -++ -++/* -++ * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D15 -++ * @n: chip select number(1 ~ 4) -++ */ -++#define __gpio_as_nor_16bit(n) \ -++do { \ -++ if (is_normal_order()) { \ -++ /* 32/16-bit data normal order */ \ -++ REG_GPIO_PXFUNS(0) = 0x0000ffff; \ -++ REG_GPIO_PXSELC(0) = 0x0000ffff; \ -++ REG_GPIO_PXPES(0) = 0x0000ffff; \ -++ } else { \ -++ /* 16-bit data special order */ \ -++ REG_GPIO_PXFUNS(0) = 0x00ffff00; \ -++ REG_GPIO_PXSELC(0) = 0x00ffff00; \ -++ REG_GPIO_PXPES(0) = 0x00ffff00; \ -++ } \ -++ REG_GPIO_PXFUNS(2) = 0x00200000 << ((n)-1); /* CSn */ \ -++ REG_GPIO_PXSELC(2) = 0x00200000 << ((n)-1); \ -++ REG_GPIO_PXPES(2) = 0x00200000 << ((n)-1); \ -++ \ -++ REG_GPIO_PXFUNS(1) = 0x0000ffff; /* A0~A15 */ \ -++ REG_GPIO_PXSELC(1) = 0x0000ffff; \ -++ REG_GPIO_PXPES(1) = 0x0000ffff; \ -++ REG_GPIO_PXFUNS(2) = 0x06110007; /* RD#, WR#, WAIT#, A20~A22 */ \ -++ REG_GPIO_PXSELC(2) = 0x06110007; \ -++ REG_GPIO_PXPES(2) = 0x06110007; \ -++ REG_GPIO_PXFUNS(2) = 0x000e0000; /* A17~A19 */ \ -++ REG_GPIO_PXSELS(2) = 0x000e0000; \ -++ REG_GPIO_PXPES(2) = 0x000e0000; \ -++} while (0) -++ -++/* -++ * UART0_TxD, UART0_RxD -++ */ -++#define __gpio_as_uart0() \ -++do { \ -++ REG_GPIO_PXFUNS(5) = 0x00000030; \ -++ REG_GPIO_PXSELS(5) = 0x00000030; \ -++ REG_GPIO_PXPES(5) = 0x00000030; \ -++} while (0) -++ -++/* -++ * UART0_TxD, UART0_RxD, UART0_CTS, UART0_RTS -++ */ -++#define __gpio_as_uart0_ctsrts() \ -++do { \ -++ REG_GPIO_PXFUNS(5) = 0x000000f0; \ -++ REG_GPIO_PXSELS(5) = 0x000000f0; \ -++ REG_GPIO_PXPES(5) = 0x000000f0; \ -++} while (0) -++ -++/* -++ * UART1_TxD, UART1_RxD -++ */ -++#define __gpio_as_uart1() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x00030000; \ -++ REG_GPIO_PXSELC(4) = 0x00030000; \ -++ REG_GPIO_PXPES(4) = 0x00030000; \ -++} while (0) -++ -++/* -++ * UART1_TxD, UART1_RxD, UART1_CTS, UART1_RTS -++ */ -++#define __gpio_as_uart1_ctsrts() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x000f0000; \ -++ REG_GPIO_PXSELC(4) = 0x000f0000; \ -++ REG_GPIO_PXPES(4) = 0x000f0000; \ -++} while (0) -++ -++/* -++ * UART2_TxD, UART2_RxD -++ */ -++#define __gpio_as_uart2() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x0c000000; \ -++ REG_GPIO_PXSELS(4) = 0x0c000000; \ -++ REG_GPIO_PXPES(4) = 0x0c000000; \ -++} while (0) -++ -++/* -++ * UART3_TxD, UART3_RxD -++ */ -++#define __gpio_as_uart3() \ -++do { \ -++ REG_GPIO_PXFUNS(5) = 0x00030000; \ -++ REG_GPIO_PXSELC(5) = 0x00030000; \ -++ REG_GPIO_PXPES(5) = 0x00030000; \ -++} while (0) -++ -++/* -++ * UART3_TxD, UART3_RxD, UART3_CTS, UART3_RTS -++ */ -++#define __gpio_as_uart3_ctsrts() \ -++do { \ -++ REG_GPIO_PXFUNS(5) = 0x000f0000; \ -++ REG_GPIO_PXSELC(5) = 0x000f0000; \ -++ REG_GPIO_PXPES(5) = 0x000f0000; \ -++} while (0) -++ -++/* -++ * TSCLK, TSSTR, TSFRM, TSFAIL, TSDI0~7 -++ */ -++#define __gpio_as_tssi() \ -++do { \ -++ REG_GPIO_PXFUNS(2) = 0x0000ff00; \ -++ REG_GPIO_PXSELS(2) = 0x0000ff00; \ -++ REG_GPIO_PXPES(2) = 0x0000ff00; \ -++ REG_GPIO_PXFUNS(5) = 0x00f00000; \ -++ REG_GPIO_PXSELC(5) = 0x00f00000; \ -++ REG_GPIO_PXPES(5) = 0x00f00000; \ -++} while (0) -++ -++/* -++ * LCD_D0~LCD_D7, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -++ */ -++#define __gpio_as_lcd_8bit() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x003c00ff; \ -++ REG_GPIO_PXSELC(3) = 0x003c00ff; \ -++ REG_GPIO_PXPES(3) = 0x003c00ff; \ -++} while (0) -++ -++/* -++ * LCD_D0~LCD_D15, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -++ */ -++#define __gpio_as_lcd_16bit() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x003cffff; \ -++ REG_GPIO_PXSELC(3) = 0x003cffff; \ -++ REG_GPIO_PXPES(3) = 0x003cffff; \ -++} while (0) -++ -++/* -++ * LCD_D0~LCD_D17, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -++ */ -++#define __gpio_as_lcd_18bit() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x003fffff; \ -++ REG_GPIO_PXSELC(3) = 0x003fffff; \ -++ REG_GPIO_PXPES(3) = 0x003fffff; \ -++} while (0) -++ -++/* -++ * LCD_D0~LCD_D17, LCD_D_R1, LCD_D_G0, LCD_D_G1, LCD_D_B1, -++ * LCD_D_R0, LCD_D_B0, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -++ */ -++#define __gpio_as_lcd_24bit() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x003fffff; \ -++ REG_GPIO_PXSELC(3) = 0x003fffff; \ -++ REG_GPIO_PXPES(3) = 0x003fffff; \ -++ REG_GPIO_PXFUNS(3) = 0x03c00000; \ -++ REG_GPIO_PXSELS(3) = 0x03c00000; \ -++ REG_GPIO_PXPES(3) = 0x03c00000; \ -++ REG_GPIO_PXFUNS(5) = 0x000c0000; \ -++ REG_GPIO_PXSELS(5) = 0x000c0000; \ -++ REG_GPIO_PXPES(5) = 0x000c0000; \ -++} while (0) -++ -++/* -++ * SLCD_DAT0~7, SLCD_CLK, SLCD_RS, SLCD_CS -++ */ -++#define __gpio_as_lcd_smart_pal_8bit() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x001c00ff; \ -++ REG_GPIO_PXSELC(3) = 0x001c00ff; \ -++ REG_GPIO_PXPES(3) = 0x001c00ff; \ -++} while (0) -++ -++/* -++ * SLCD_DAT0~15, SLCD_CLK, SLCD_RS, SLCD_CS -++ */ -++#define __gpio_as_lcd_smart_pal_15bit() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x001cffff; \ -++ REG_GPIO_PXSELC(3) = 0x001cffff; \ -++ REG_GPIO_PXPES(3) = 0x001cffff; \ -++} while (0) -++ -++/* -++ * SLCD_DAT0~17, SLCD_CLK, SLCD_RS, SLCD_CS -++ */ -++#define __gpio_as_lcd_smart_pal_17bit() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x001fffff; \ -++ REG_GPIO_PXSELC(3) = 0x001fffff; \ -++ REG_GPIO_PXPES(3) = 0x001fffff; \ -++} while (0) -++ -++/* -++ * SLCD_DAT15, SLCD_CLK, SLCD_RS, SLCD_CS -++ */ -++#define __gpio_as_lcd_smart_serial() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x001c8000; \ -++ REG_GPIO_PXSELC(3) = 0x001c8000; \ -++ REG_GPIO_PXPES(3) = 0x001c8000; \ -++} while (0) -++ -++/* -++ * LCD_CLS, LCD_SPL, LCD_PS, LCD_REV -++ */ -++#define __gpio_as_lcd_special() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x03C00000; \ -++ REG_GPIO_PXSELC(3) = 0x03C00000; \ -++ REG_GPIO_PXPES(3) = 0x03C00000; \ -++} while (0) -++ -++/* -++ * CIM_D0~CIM_D7, CIM_MCLK, CIM_PCLK, CIM_VSYNC, CIM_HSYNC -++ */ -++#define __gpio_as_cim() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x00000fff; \ -++ REG_GPIO_PXSELC(4) = 0x00000fff; \ -++ REG_GPIO_PXPES(4) = 0x00000fff; \ -++} while (0) -++ -++/* -++ * SDATO, SDATI, BCLK, SYNC, SCLK_RSTN(gpio sepc) or -++ * SDATA_OUT, SDATA_IN, BIT_CLK, SYNC, SCLK_RESET(aic spec) -++ */ -++#define __gpio_as_aic() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x0c000000; \ -++ REG_GPIO_PXSELS(4) = 0x0c000000; \ -++ REG_GPIO_PXPES(4) = 0x0c000000; \ -++ REG_GPIO_PXFUNS(4) = 0x00e00000; \ -++ REG_GPIO_PXSELC(4) = 0x00e00000; \ -++ REG_GPIO_PXPES(4) = 0x00e00000; \ -++} while (0) -++ -++/* -++ * PCM_DIN, PCM_DOUT, PCM_CLK, PCM_SYN -++*/ -++#define __gpio_as_pcm() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x003c0000; \ -++ REG_GPIO_PXSELS(4) = 0x003c0000; \ -++ REG_GPIO_PXPES(4) = 0x003c0000; \ -++} while (0) -++ -++/* -++ * OWI -++*/ -++#define __gpio_as_owi() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x02000000; \ -++ REG_GPIO_PXSELS(4) = 0x02000000; \ -++ REG_GPIO_PXPES(4) = 0x02000000; \ -++} while (0) -++ -++/* -++ * MSC0_CMD, MSC0_CLK, MSC0_D0 ~ MSC0_D3 -++ */ -++#define __gpio_as_msc0_4bit() \ -++do { \ -++ REG_GPIO_PXFUNS(5) = 0x0000030f; \ -++ REG_GPIO_PXSELC(5) = 0x0000030f; \ -++ REG_GPIO_PXPES(5) = 0x0000030f; \ -++} while (0) -++ -++/* -++ * MSC0_CMD, MSC0_CLK, MSC0_D0 ~ MSC0_D7 -++ */ -++#define __gpio_as_msc0_8bit() \ -++do { \ -++ REG_GPIO_PXFUNS(5) = 0x000003ff; \ -++ REG_GPIO_PXSELC(5) = 0x000003ff; \ -++ REG_GPIO_PXPES(5) = 0x000003ff; \ -++} while (0) -++ -++/* -++ * MSC1_CMD, MSC1_CLK, MSC1_D0 ~ MSC1_D3 -++ */ -++#define __gpio_as_msc1_4bit() \ -++do { \ -++ REG_GPIO_PXFUNS(5) = 0x0000fc00; \ -++ REG_GPIO_PXSELC(5) = 0x0000fc00; \ -++ REG_GPIO_PXPES(5) = 0x0000fc00; \ -++} while (0) -++ -++#define __gpio_as_msc __gpio_as_msc0_8bit /* default as msc0 8bit */ -++#define __gpio_as_msc0 __gpio_as_msc0_8bit /* msc0 default as 8bit */ -++#define __gpio_as_msc1 __gpio_as_msc1_4bit /* msc1 only support 4bit */ -++ -++/* -++ * SSI0_CE0, SSI0_CE1#_GPC, SSI0_CE2, SSI0_CLK, SSI0_DT, SSI0_DR -++ */ -++#define __gpio_as_ssi0() \ -++do { \ -++ REG_GPIO_PXFUNS(1) = 0xfc000000; \ -++ REG_GPIO_PXSELC(1) = 0xfc000000; \ -++ REG_GPIO_PXPES(1) = 0xfc000000; \ -++} while (0) -++ -++/* -++ * SSI1_CE0, SSI1_CE1, SSI1_CLK, SSI1_DT, SSI1_DR -++ */ -++#define __gpio_as_ssi1() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x7c000000; \ -++ REG_GPIO_PXSELC(3) = 0x7c000000; \ -++ REG_GPIO_PXPES(3) = 0x7c000000; \ -++} while (0) -++ -++/* n = 0(SSI0), 1(SSI1) */ -++#define __gpio_as_ssi(n) __gpio_as_ssi##n() -++ -++/* -++ * I2C_SCK, I2C_SDA -++ */ -++#define __gpio_as_i2c() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x00003000; \ -++ REG_GPIO_PXSELC(4) = 0x00003000; \ -++ REG_GPIO_PXPES(4) = 0x00003000; \ -++} while (0) -++ -++/* -++ * PWM0 -++ */ -++#define __gpio_as_pwm0() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x00100000; \ -++ REG_GPIO_PXSELC(4) = 0x00100000; \ -++ REG_GPIO_PXPES(4) = 0x00100000; \ -++} while (0) -++ -++/* -++ * PWM1 -++ */ -++#define __gpio_as_pwm1() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x00200000; \ -++ REG_GPIO_PXSELC(4) = 0x00200000; \ -++ REG_GPIO_PXPES(4) = 0x00200000; \ -++} while (0) -++ -++/* -++ * PWM2 -++ */ -++#define __gpio_as_pwm2() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x00400000; \ -++ REG_GPIO_PXSELC(4) = 0x00400000; \ -++ REG_GPIO_PXPES(4) = 0x00400000; \ -++} while (0) -++ -++/* -++ * PWM3 -++ */ -++#define __gpio_as_pwm3() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x00800000; \ -++ REG_GPIO_PXSELC(4) = 0x00800000; \ -++ REG_GPIO_PXPES(4) = 0x00800000; \ -++} while (0) -++ -++/* -++ * PWM4 -++ */ -++#define __gpio_as_pwm4() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x01000000; \ -++ REG_GPIO_PXSELC(4) = 0x01000000; \ -++ REG_GPIO_PXPES(4) = 0x01000000; \ -++} while (0) -++ -++/* -++ * PWM5 -++ */ -++#define __gpio_as_pwm5() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x02000000; \ -++ REG_GPIO_PXSELC(4) = 0x02000000; \ -++ REG_GPIO_PXPES(4) = 0x02000000; \ -++} while (0) -++ -++/* -++ * n = 0 ~ 5 -++ */ -++#define __gpio_as_pwm(n) __gpio_as_pwm##n() -++ -++/* -++ * DREQ -++ */ -++#define __gpio_as_dreq() \ -++do { \ -++ REG_GPIO_PXFUNS(5) = 0x00000004; \ -++ REG_GPIO_PXSELS(5) = 0x00000004; \ -++ REG_GPIO_PXPES(5) = 0x00000004; \ -++} while (0) -++ -++/* -++ * DACK -++ */ -++#define __gpio_as_dack() \ -++do { \ -++ REG_GPIO_PXFUNS(5) = 0x00000008; \ -++ REG_GPIO_PXSELS(5) = 0x00000008; \ -++ REG_GPIO_PXPES(5) = 0x00000008; \ -++} while (0) -++ -++/* -++ * GPIO or Interrupt Mode -++ */ -++#define __gpio_get_port(p) (REG_GPIO_PXPIN(p)) -++ -++#define __gpio_port_as_output(p, o) \ -++do { \ -++ REG_GPIO_PXFUNC(p) = (1 << (o)); \ -++ REG_GPIO_PXSELC(p) = (1 << (o)); \ -++ REG_GPIO_PXDIRS(p) = (1 << (o)); \ -++} while (0) -++ -++#define __gpio_port_as_input(p, o) \ -++do { \ -++ REG_GPIO_PXFUNC(p) = (1 << (o)); \ -++ REG_GPIO_PXSELC(p) = (1 << (o)); \ -++ REG_GPIO_PXDIRC(p) = (1 << (o)); \ -++} while (0) -++ -++#define __gpio_as_output(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ __gpio_port_as_output(p, o); \ -++} while (0) -++ -++#define __gpio_as_input(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ __gpio_port_as_input(p, o); \ -++} while (0) -++ -++#define __gpio_set_pin(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXDATS(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_clear_pin(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXDATC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_get_pin(n) \ -++({ \ -++ unsigned int p, o, v; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ if (__gpio_get_port(p) & (1 << o)) \ -++ v = 1; \ -++ else \ -++ v = 0; \ -++ v; \ -++}) -++ -++#define __gpio_as_irq_high_level(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMS(p) = (1 << o); \ -++ REG_GPIO_PXTRGC(p) = (1 << o); \ -++ REG_GPIO_PXFUNC(p) = (1 << o); \ -++ REG_GPIO_PXSELS(p) = (1 << o); \ -++ REG_GPIO_PXDIRS(p) = (1 << o); \ -++ REG_GPIO_PXFLGC(p) = (1 << o); \ -++ REG_GPIO_PXIMC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_as_irq_low_level(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMS(p) = (1 << o); \ -++ REG_GPIO_PXTRGC(p) = (1 << o); \ -++ REG_GPIO_PXFUNC(p) = (1 << o); \ -++ REG_GPIO_PXSELS(p) = (1 << o); \ -++ REG_GPIO_PXDIRC(p) = (1 << o); \ -++ REG_GPIO_PXFLGC(p) = (1 << o); \ -++ REG_GPIO_PXIMC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_as_irq_rise_edge(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMS(p) = (1 << o); \ -++ REG_GPIO_PXTRGS(p) = (1 << o); \ -++ REG_GPIO_PXFUNC(p) = (1 << o); \ -++ REG_GPIO_PXSELS(p) = (1 << o); \ -++ REG_GPIO_PXDIRS(p) = (1 << o); \ -++ REG_GPIO_PXFLGC(p) = (1 << o); \ -++ REG_GPIO_PXIMC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_as_irq_fall_edge(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMS(p) = (1 << o); \ -++ REG_GPIO_PXTRGS(p) = (1 << o); \ -++ REG_GPIO_PXFUNC(p) = (1 << o); \ -++ REG_GPIO_PXSELS(p) = (1 << o); \ -++ REG_GPIO_PXDIRC(p) = (1 << o); \ -++ REG_GPIO_PXFLGC(p) = (1 << o); \ -++ REG_GPIO_PXIMC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_mask_irq(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMS(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_unmask_irq(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_ack_irq(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXFLGC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_get_irq() \ -++({ \ -++ unsigned int p, i, tmp, v = 0; \ -++ for (p = 3; p >= 0; p--) { \ -++ tmp = REG_GPIO_PXFLG(p); \ -++ for (i = 0; i < 32; i++) \ -++ if (tmp & (1 << i)) \ -++ v = (32*p + i); \ -++ } \ -++ v; \ -++}) -++ -++#define __gpio_group_irq(n) \ -++({ \ -++ register int tmp, i; \ -++ tmp = REG_GPIO_PXFLG((n)); \ -++ for (i=31;i>=0;i--) \ -++ if (tmp & (1 << i)) \ -++ break; \ -++ i; \ -++}) -++ -++#define __gpio_enable_pull(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXPEC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_disable_pull(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXPES(p) = (1 << o); \ -++} while (0) -++ -++ -++/*************************************************************************** -++ * CPM -++ ***************************************************************************/ -++#define __cpm_get_pllm() \ -++ ((REG_CPM_CPPCR & CPM_CPPCR_PLLM_MASK) >> CPM_CPPCR_PLLM_BIT) -++#define __cpm_get_plln() \ -++ ((REG_CPM_CPPCR & CPM_CPPCR_PLLN_MASK) >> CPM_CPPCR_PLLN_BIT) -++#define __cpm_get_pllod() \ -++ ((REG_CPM_CPPCR & CPM_CPPCR_PLLOD_MASK) >> CPM_CPPCR_PLLOD_BIT) -++ -++#define __cpm_get_cdiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_CDIV_MASK) >> CPM_CPCCR_CDIV_BIT) -++#define __cpm_get_hdiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_HDIV_MASK) >> CPM_CPCCR_HDIV_BIT) -++#define __cpm_get_pdiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_PDIV_MASK) >> CPM_CPCCR_PDIV_BIT) -++#define __cpm_get_mdiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT) -++#define __cpm_get_ldiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_LDIV_MASK) >> CPM_CPCCR_LDIV_BIT) -++#define __cpm_get_udiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_UDIV_MASK) >> CPM_CPCCR_UDIV_BIT) -++#define __cpm_get_i2sdiv() \ -++ ((REG_CPM_I2SCDR & CPM_I2SCDR_I2SDIV_MASK) >> CPM_I2SCDR_I2SDIV_BIT) -++#define __cpm_get_pixdiv() \ -++ ((REG_CPM_LPCDR & CPM_LPCDR_PIXDIV_MASK) >> CPM_LPCDR_PIXDIV_BIT) -++#define __cpm_get_mscdiv(n) \ -++ ((REG_CPM_MSCCDR(n) & CPM_MSCCDR_MSCDIV_MASK) >> CPM_MSCCDR_MSCDIV_BIT) -++#define __cpm_get_uhcdiv() \ -++ ((REG_CPM_UHCCDR & CPM_UHCCDR_UHCDIV_MASK) >> CPM_UHCCDR_UHCDIV_BIT) -++#define __cpm_get_ssidiv() \ -++ ((REG_CPM_SSICCDR & CPM_SSICDR_SSICDIV_MASK) >> CPM_SSICDR_SSIDIV_BIT) -++#define __cpm_get_pcmdiv(v) \ -++ ((REG_CPM_PCMCDR & CPM_PCMCDR_PCMCD_MASK) >> CPM_PCMCDR_PCMCD_BIT) -++ -++#define __cpm_set_cdiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_CDIV_MASK) | ((v) << (CPM_CPCCR_CDIV_BIT))) -++#define __cpm_set_hdiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_HDIV_MASK) | ((v) << (CPM_CPCCR_HDIV_BIT))) -++#define __cpm_set_pdiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_PDIV_MASK) | ((v) << (CPM_CPCCR_PDIV_BIT))) -++#define __cpm_set_mdiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_MDIV_MASK) | ((v) << (CPM_CPCCR_MDIV_BIT))) -++#define __cpm_set_ldiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_LDIV_MASK) | ((v) << (CPM_CPCCR_LDIV_BIT))) -++#define __cpm_set_udiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | ((v) << (CPM_CPCCR_UDIV_BIT))) -++#define __cpm_set_i2sdiv(v) \ -++ (REG_CPM_I2SCDR = (REG_CPM_I2SCDR & ~CPM_I2SCDR_I2SDIV_MASK) | ((v) << (CPM_I2SCDR_I2SDIV_BIT))) -++#define __cpm_set_pixdiv(v) \ -++ (REG_CPM_LPCDR = (REG_CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | ((v) << (CPM_LPCDR_PIXDIV_BIT))) -++#define __cpm_set_mscdiv(n, v) \ -++ (REG_CPM_MSCCDR(n) = (REG_CPM_MSCCDR(n) & ~CPM_MSCCDR_MSCDIV_MASK) | ((v) << (CPM_MSCCDR_MSCDIV_BIT))) -++#define __cpm_set_uhcdiv(v) \ -++ (REG_CPM_UHCCDR = (REG_CPM_UHCCDR & ~CPM_UHCCDR_UHCDIV_MASK) | ((v) << (CPM_UHCCDR_UHCDIV_BIT))) -++#define __cpm_set_ssidiv(v) \ -++ (REG_CPM_SSICDR = (REG_CPM_SSICDR & ~CPM_SSICDR_SSIDIV_MASK) | ((v) << (CPM_SSICDR_SSIDIV_BIT))) -++#define __cpm_set_pcmdiv(v) \ -++ (REG_CPM_PCMCDR = (REG_CPM_PCMCDR & ~CPM_PCMCDR_PCMCD_MASK) | ((v) << (CPM_PCMCDR_PCMCD_BIT))) -++ -++#define __cpm_select_pcmclk_pll() (REG_CPM_PCMCDR |= CPM_PCMCDR_PCMS) -++#define __cpm_select_pcmclk_exclk() (REG_CPM_PCMCDR &= ~CPM_PCMCDR_PCMS) -++#define __cpm_select_pixclk_ext() (REG_CPM_LPCDR |= CPM_LPCDR_LPCS) -++#define __cpm_select_pixclk_pll() (REG_CPM_LPCDR &= ~CPM_LPCDR_LPCS) -++#define __cpm_select_tveclk_exclk() (REG_CPM_LPCDR |= CPM_CPCCR_LSCS) -++#define __cpm_select_tveclk_pll() (REG_CPM_LPCDR &= ~CPM_LPCDR_LSCS) -++#define __cpm_select_pixclk_lcd() (REG_CPM_LPCDR &= ~CPM_LPCDR_LTCS) -++#define __cpm_select_pixclk_tve() (REG_CPM_LPCDR |= CPM_LPCDR_LTCS) -++#define __cpm_select_i2sclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_I2CS) -++#define __cpm_select_i2sclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_I2CS) -++#define __cpm_select_usbclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_UCS) -++#define __cpm_select_usbclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_UCS) -++ -++#define __cpm_enable_cko() -++#define __cpm_exclk_direct() (REG_CPM_CPCCR &= ~CPM_CPCCR_ECS) -++#define __cpm_exclk_div2() (REG_CPM_CPCCR |= CPM_CPCCR_ECS) -++#define __cpm_enable_pll_change() (REG_CPM_CPCCR |= CPM_CPCCR_CE) -++#define __cpm_pllout_direct() (REG_CPM_CPCCR |= CPM_CPCCR_PCS) -++#define __cpm_pllout_div2() (REG_CPM_CPCCR &= ~CPM_CPCCR_PCS) -++#define __cpm_pll_enable() (REG_CPM_CPPCR |= CPM_CPPCR_PLLEN) -++ -++#define __cpm_pll_is_off() (REG_CPM_CPPSR & CPM_CPPSR_PLLOFF) -++#define __cpm_pll_is_on() (REG_CPM_CPPSR & CPM_CPPSR_PLLON) -++#define __cpm_pll_bypass() (REG_CPM_CPPSR |= CPM_CPPSR_PLLBP) -++ -++#define __cpm_get_cclk_doze_duty() \ -++ ((REG_CPM_LCR & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT) -++#define __cpm_set_cclk_doze_duty(v) \ -++ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_DOZE_DUTY_MASK) | ((v) << (CPM_LCR_DOZE_DUTY_BIT))) -++ -++#define __cpm_doze_mode() (REG_CPM_LCR |= CPM_LCR_DOZE_ON) -++#define __cpm_idle_mode() \ -++ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_IDLE) -++#define __cpm_sleep_mode() \ -++ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_SLEEP) -++ -++#define __cpm_stop_all() (REG_CPM_CLKGR = 0x1fffffff) -++#define __cpm_stop_cimram() (REG_CPM_CLKGR |= CPM_CLKGR_CIMRAM) -++#define __cpm_stop_idct() (REG_CPM_CLKGR |= CPM_CLKGR_IDCT) -++#define __cpm_stop_db() (REG_CPM_CLKGR |= CPM_CLKGR_DB) -++#define __cpm_stop_me() (REG_CPM_CLKGR |= CPM_CLKGR_ME) -++#define __cpm_stop_mc() (REG_CPM_CLKGR |= CPM_CLKGR_MC) -++#define __cpm_stop_tve() (REG_CPM_CLKGR |= CPM_CLKGR_TVE) -++#define __cpm_stop_tssi() (REG_CPM_CLKGR |= CPM_CLKGR_TSSI) -++#define __cpm_stop_owi() (REG_CPM_CLKGR |= CPM_CLKGR_OWI) -++#define __cpm_stop_pcm() (REG_CPM_CLKGR |= CPM_CLKGR_PCM) -++#define __cpm_stop_uart3() (REG_CPM_CLKGR |= CPM_CLKGR_UART3) -++#define __cpm_stop_uart2() (REG_CPM_CLKGR |= CPM_CLKGR_UART2) -++#define __cpm_stop_uart1() (REG_CPM_CLKGR |= CPM_CLKGR_UART1) -++#define __cpm_stop_uhc() (REG_CPM_CLKGR |= CPM_CLKGR_UHC) -++#define __cpm_stop_ipu() (REG_CPM_CLKGR |= CPM_CLKGR_IPU) -++#define __cpm_stop_dmac() (REG_CPM_CLKGR |= CPM_CLKGR_DMAC) -++#define __cpm_stop_udc() (REG_CPM_CLKGR |= CPM_CLKGR_UDC) -++#define __cpm_stop_lcd() (REG_CPM_CLKGR |= CPM_CLKGR_LCD) -++#define __cpm_stop_cim() (REG_CPM_CLKGR |= CPM_CLKGR_CIM) -++#define __cpm_stop_sadc() (REG_CPM_CLKGR |= CPM_CLKGR_SADC) -++#define __cpm_stop_msc(n) (REG_CPM_CLKGR |= CPM_CLKGR_MSC##n) -++#define __cpm_stop_aic1() (REG_CPM_CLKGR |= CPM_CLKGR_AIC1) -++#define __cpm_stop_aic2() (REG_CPM_CLKGR |= CPM_CLKGR_AIC2) -++#define __cpm_stop_ssi(n) (REG_CPM_CLKGR |= CPM_CLKGR_SSI##n) -++#define __cpm_stop_i2c() (REG_CPM_CLKGR |= CPM_CLKGR_I2C) -++#define __cpm_stop_rtc() (REG_CPM_CLKGR |= CPM_CLKGR_RTC) -++#define __cpm_stop_tcu() (REG_CPM_CLKGR |= CPM_CLKGR_TCU) -++#define __cpm_stop_uart0() (REG_CPM_CLKGR |= CPM_CLKGR_UART0) -++ -++#define __cpm_start_all() (REG_CPM_CLKGR = 0x0) -++#define __cpm_start_cimram() (REG_CPM_CLKGR &= ~CPM_CLKGR_CIMRAM) -++#define __cpm_start_idct() (REG_CPM_CLKGR &= ~CPM_CLKGR_IDCT) -++#define __cpm_start_db() (REG_CPM_CLKGR &= ~CPM_CLKGR_DB) -++#define __cpm_start_me() (REG_CPM_CLKGR &= ~CPM_CLKGR_ME) -++#define __cpm_start_mc() (REG_CPM_CLKGR &= ~CPM_CLKGR_MC) -++#define __cpm_start_tve() (REG_CPM_CLKGR &= ~CPM_CLKGR_TVE) -++#define __cpm_start_tssi() (REG_CPM_CLKGR &= ~CPM_CLKGR_TSSI) -++#define __cpm_start_owi() (REG_CPM_CLKGR &= ~CPM_CLKGR_OWI) -++#define __cpm_start_pcm() (REG_CPM_CLKGR &= ~CPM_CLKGR_PCM) -++#define __cpm_start_uart3() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART3) -++#define __cpm_start_uart2() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART2) -++#define __cpm_start_uart1() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART1) -++#define __cpm_start_uhc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UHC) -++#define __cpm_start_ipu() (REG_CPM_CLKGR &= ~CPM_CLKGR_IPU) -++#define __cpm_start_dmac() (REG_CPM_CLKGR &= ~CPM_CLKGR_DMAC) -++#define __cpm_start_udc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UDC) -++#define __cpm_start_lcd() (REG_CPM_CLKGR &= ~CPM_CLKGR_LCD) -++#define __cpm_start_cim() (REG_CPM_CLKGR &= ~CPM_CLKGR_CIM) -++#define __cpm_start_sadc() (REG_CPM_CLKGR &= ~CPM_CLKGR_SADC) -++#define __cpm_start_msc(n) (REG_CPM_CLKGR &= ~CPM_CLKGR_MSC##n) -++#define __cpm_start_aic1() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC1) -++#define __cpm_start_aic2() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC2) -++#define __cpm_start_ssi(n) (REG_CPM_CLKGR &= ~CPM_CLKGR_SSI##n) -++#define __cpm_start_i2c() (REG_CPM_CLKGR &= ~CPM_CLKGR_I2C) -++#define __cpm_start_rtc() (REG_CPM_CLKGR &= ~CPM_CLKGR_RTC) -++#define __cpm_start_tcu() (REG_CPM_CLKGR &= ~CPM_CLKGR_TCU) -++#define __cpm_start_uart0() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART0) -++ -++#define __cpm_get_o1st() \ -++ ((REG_CPM_OPCR & CPM_OPCR_O1ST_MASK) >> CPM_OPCR_O1ST_BIT) -++#define __cpm_set_o1st(v) \ -++ (REG_CPM_OPCR = (REG_CPM_OPCR & ~CPM_OPCR_O1ST_MASK) | ((v) << (CPM_OPCR_O1ST_BIT))) -++#define __cpm_enable_uhcphy() (REG_CPM_OPCR &= ~CPM_OPCR_UHCPHY_DISABLE) -++#define __cpm_suspend_uhcphy() (REG_CPM_OPCR |= CPM_OPCR_UHCPHY_DISABLE) -++#define __cpm_enable_udcphy() (REG_CPM_OPCR |= CPM_OPCR_UDCPHY_ENABLE) -++#define __cpm_suspend_udcphy() (REG_CPM_OPCR &= ~CPM_OPCR_UDCPHY_ENABLE) -++#define __cpm_enable_osc_in_sleep() (REG_CPM_OPCR |= CPM_OPCR_OSC_ENABLE) -++#define __cpm_disable_osc_in_sleep() (REG_CPM_OPCR &= ~CPM_OPCR_OSC_ENABLE) -++#define __cpm_select_rtcclk_rtc() (REG_CPM_OPCR |= CPM_OPCR_ERCS) -++#define __cpm_select_rtcclk_exclk() (REG_CPM_OPCR &= ~CPM_OPCR_ERCS) -++ -++ -++/*************************************************************************** -++ * TCU -++ ***************************************************************************/ -++// where 'n' is the TCU channel -++#define __tcu_select_extalclk(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_EXT_EN) -++#define __tcu_select_rtcclk(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_RTC_EN) -++#define __tcu_select_pclk(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_PCK_EN) -++#define __tcu_disable_pclk(n) \ -++ REG_TCU_TCSR(n) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PCK_EN); -++#define __tcu_select_clk_div1(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1) -++#define __tcu_select_clk_div4(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE4) -++#define __tcu_select_clk_div16(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE16) -++#define __tcu_select_clk_div64(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE64) -++#define __tcu_select_clk_div256(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE256) -++#define __tcu_select_clk_div1024(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1024) -++ -++#define __tcu_enable_pwm_output(n) (REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_EN) -++#define __tcu_disable_pwm_output(n) (REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_EN) -++ -++#define __tcu_init_pwm_output_high(n) (REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_INITL_HIGH) -++#define __tcu_init_pwm_output_low(n) (REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_INITL_HIGH) -++ -++#define __tcu_set_pwm_output_shutdown_graceful(n) (REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_SD) -++#define __tcu_set_pwm_output_shutdown_abrupt(n) (REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_SD) -++ -++#define __tcu_clear_counter_to_zero(n) (REG_TCU_TCSR((n)) |= TCU_TCSR_CNT_CLRZ) -++ -++#define __tcu_ost_enabled() (REG_TCU_TER & TCU_TER_OSTEN) -++#define __tcu_enable_ost() (REG_TCU_TESR = TCU_TESR_OSTST) -++#define __tcu_disable_ost() (REG_TCU_TECR = TCU_TECR_OSTCL) -++ -++#define __tcu_counter_enabled(n) (REG_TCU_TER & (1 << (n))) -++#define __tcu_start_counter(n) (REG_TCU_TESR |= (1 << (n))) -++#define __tcu_stop_counter(n) (REG_TCU_TECR |= (1 << (n))) -++ -++#define __tcu_half_match_flag(n) (REG_TCU_TFR & (1 << ((n) + 16))) -++#define __tcu_full_match_flag(n) (REG_TCU_TFR & (1 << (n))) -++#define __tcu_set_half_match_flag(n) (REG_TCU_TFSR = (1 << ((n) + 16))) -++#define __tcu_set_full_match_flag(n) (REG_TCU_TFSR = (1 << (n))) -++#define __tcu_clear_half_match_flag(n) (REG_TCU_TFCR = (1 << ((n) + 16))) -++#define __tcu_clear_full_match_flag(n) (REG_TCU_TFCR = (1 << (n))) -++#define __tcu_mask_half_match_irq(n) (REG_TCU_TMSR = (1 << ((n) + 16))) -++#define __tcu_mask_full_match_irq(n) (REG_TCU_TMSR = (1 << (n))) -++#define __tcu_unmask_half_match_irq(n) (REG_TCU_TMCR = (1 << ((n) + 16))) -++#define __tcu_unmask_full_match_irq(n) (REG_TCU_TMCR = (1 << (n))) -++ -++#define __tcu_ost_match_flag() (REG_TCU_TFR & TCU_TFR_OSTFLAG) -++#define __tcu_set_ost_match_flag() (REG_TCU_TFSR = TCU_TFSR_OSTFST) -++#define __tcu_clear_ost_match_flag() (REG_TCU_TFCR = TCU_TFCR_OSTFCL) -++#define __tcu_ost_match_irq_masked() (REG_TCU_TMR & TCU_TMR_OSTMASK) -++#define __tcu_mask_ost_match_irq() (REG_TCU_TMSR = TCU_TMSR_OSTMST) -++#define __tcu_unmask_ost_match_irq() (REG_TCU_TMCR = TCU_TMCR_OSTMCL) -++ -++#define __tcu_wdt_clock_stopped() (REG_TCU_TSR & TCU_TSSR_WDTSC) -++#define __tcu_ost_clock_stopped() (REG_TCU_TSR & TCU_TSR_OST) -++#define __tcu_timer_clock_stopped(n) (REG_TCU_TSR & (1 << (n))) -++ -++#define __tcu_start_wdt_clock() (REG_TCU_TSCR = TCU_TSSR_WDTSC) -++#define __tcu_start_ost_clock() (REG_TCU_TSCR = TCU_TSCR_OSTSC) -++#define __tcu_start_timer_clock(n) (REG_TCU_TSCR = (1 << (n))) -++ -++#define __tcu_stop_wdt_clock() (REG_TCU_TSSR = TCU_TSSR_WDTSC) -++#define __tcu_stop_ost_clock() (REG_TCU_TSSR = TCU_TSSR_OSTSS) -++#define __tcu_stop_timer_clock(n) (REG_TCU_TSSR = (1 << (n))) -++ -++#define __tcu_get_count(n) (REG_TCU_TCNT((n))) -++#define __tcu_set_count(n,v) (REG_TCU_TCNT((n)) = (v)) -++#define __tcu_set_full_data(n,v) (REG_TCU_TDFR((n)) = (v)) -++#define __tcu_set_half_data(n,v) (REG_TCU_TDHR((n)) = (v)) -++ -++/* TCU2, counter 1, 2*/ -++#define __tcu_read_real_value(n) (REG_TCU_TSTR & (1 << ((n) + 16))) -++#define __tcu_read_false_value(n) (REG_TCU_TSTR & (1 << ((n) + 16))) -++#define __tcu_counter_busy(n) (REG_TCU_TSTR & (1 << (n))) -++#define __tcu_counter_ready(n) (REG_TCU_TSTR & (1 << (n))) -++ -++#define __tcu_set_read_real_value(n) (REG_TCU_TSTSR = (1 << ((n) + 16))) -++#define __tcu_set_read_false_value(n) (REG_TCU_TSTCR = (1 << ((n) + 16))) -++#define __tcu_set_counter_busy(n) (REG_TCU_TSTSR = (1 << (n))) -++#define __tcu_set_counter_ready(n) (REG_TCU_TSTCR = (1 << (n))) -++ -++/* ost counter */ -++#define __ostcu_set_pwm_output_shutdown_graceful() (REG_TCU_OSTCSR &= ~TCU_TCSR_PWM_SD) -++#define __ostcu_set_ost_output_shutdown_abrupt() (REG_TCU_OSTCSR |= TCU_TCSR_PWM_SD) -++#define __ostcu_select_clk_div1() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE1) -++#define __ostcu_select_clk_div4() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE4) -++#define __ostcu_select_clk_div16() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE16) -++#define __ostcu_select_clk_div64() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE64) -++#define __ostcu_select_clk_div256() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE256) -++#define __ostcu_select_clk_div1024() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE1024) -++#define __ostcu_select_rtcclk() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~(TCU_OSTCSR_EXT_EN | TCU_OSTCSR_RTC_EN | TCU_OSTCSR_PCK_EN)) | TCU_OSTCSR_RTC_EN) -++#define __ostcu_select_extalclk() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~(TCU_OSTCSR_EXT_EN | TCU_OSTCSR_RTC_EN | TCU_OSTCSR_PCK_EN)) | TCU_OSTCSR_EXT_EN) -++#define __ostcu_select_pclk() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~(TCU_OSTCSR_EXT_EN | TCU_OSTCSR_RTC_EN | TCU_OSTCSR_PCK_EN)) | TCU_OSTCSR_PCK_EN) -++ -++ -++/*************************************************************************** -++ * WDT -++ ***************************************************************************/ -++#define __wdt_start() ( REG_WDT_TCER |= WDT_TCER_TCEN ) -++#define __wdt_stop() ( REG_WDT_TCER &= ~WDT_TCER_TCEN ) -++#define __wdt_set_count(v) ( REG_WDT_TCNT = (v) ) -++#define __wdt_set_data(v) ( REG_WDT_TDR = (v) ) -++ -++#define __wdt_select_extalclk() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_EXT_EN) -++#define __wdt_select_rtcclk() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_RTC_EN) -++#define __wdt_select_pclk() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_PCK_EN) -++ -++#define __wdt_select_clk_div1() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1) -++#define __wdt_select_clk_div4() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE4) -++#define __wdt_select_clk_div16() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE16) -++#define __wdt_select_clk_div64() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE64) -++#define __wdt_select_clk_div256() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE256) -++#define __wdt_select_clk_div1024() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1024) -++ -++ -++/*************************************************************************** -++ * UART -++ ***************************************************************************/ -++ -++#define __uart_enable(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) |= UARTFCR_UUE | UARTFCR_FE ) -++#define __uart_disable(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) = ~UARTFCR_UUE ) -++ -++#define __uart_enable_transmit_irq(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_TIE ) -++#define __uart_disable_transmit_irq(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~UARTIER_TIE ) -++ -++#define __uart_enable_receive_irq(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE ) -++#define __uart_disable_receive_irq(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~(UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE) ) -++ -++#define __uart_enable_loopback(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) |= UARTMCR_LOOP ) -++#define __uart_disable_loopback(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) &= ~UARTMCR_LOOP ) -++ -++#define __uart_set_8n1(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) = UARTLCR_WLEN_8 ) -++ -++#define __uart_set_baud(n, devclk, baud) \ -++ do { \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) |= UARTLCR_DLAB; \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_DLLR) = (devclk / 16 / baud) & 0xff; \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_DLHR) = ((devclk / 16 / baud) >> 8) & 0xff; \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) &= ~UARTLCR_DLAB; \ -++ } while (0) -++ -++#define __uart_parity_error(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_PER) != 0 ) -++ -++#define __uart_clear_errors(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) &= ~(UARTLSR_ORER | UARTLSR_BRK | UARTLSR_FER | UARTLSR_PER | UARTLSR_RFER) ) -++ -++#define __uart_transmit_fifo_empty(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TDRQ) != 0 ) -++ -++#define __uart_transmit_end(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TEMT) != 0 ) -++ -++#define __uart_transmit_char(n, ch) \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_TDR) = (ch) -++ -++#define __uart_receive_fifo_full(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) -++ -++#define __uart_receive_ready(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) -++ -++#define __uart_receive_char(n) \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_RDR) -++ -++#define __uart_disable_irda() \ -++ ( REG8(IRDA_BASE + OFF_SIRCR) &= ~(SIRCR_TSIRE | SIRCR_RSIRE) ) -++#define __uart_enable_irda() \ -++ /* Tx high pulse as 0, Rx low pulse as 0 */ \ -++ ( REG8(IRDA_BASE + OFF_SIRCR) = SIRCR_TSIRE | SIRCR_RSIRE | SIRCR_RXPL | SIRCR_TPWS ) -++ -++ -++/*************************************************************************** -++ * DMAC -++ ***************************************************************************/ -++ -++/* m is the DMA controller index (0, 1), n is the DMA channel index (0 - 11) */ -++ -++#define __dmac_enable_module(m) \ -++ ( REG_DMAC_DMACR(m) |= DMAC_DMACR_DMAE | DMAC_DMACR_PR_012345 ) -++#define __dmac_disable_module(m) \ -++ ( REG_DMAC_DMACR(m) &= ~DMAC_DMACR_DMAE ) -++ -++/* p=0,1,2,3 */ -++#define __dmac_set_priority(m,p) \ -++do { \ -++ REG_DMAC_DMACR(m) &= ~DMAC_DMACR_PR_MASK; \ -++ REG_DMAC_DMACR(m) |= ((p) << DMAC_DMACR_PR_BIT); \ -++} while (0) -++ -++#define __dmac_test_halt_error(m) ( REG_DMAC_DMACR(m) & DMAC_DMACR_HLT ) -++#define __dmac_test_addr_error(m) ( REG_DMAC_DMACR(m) & DMAC_DMACR_AR ) -++ -++#define __dmac_channel_enable_clk(n) \ -++ REG_DMAC_DMACKE((n)/HALF_DMA_NUM) |= 1 << ((n)-(n)/HALF_DMA_NUM*HALF_DMA_NUM); -++ -++#define __dmac_enable_descriptor(n) \ -++ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_NDES ) -++#define __dmac_disable_descriptor(n) \ -++ ( REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_NDES ) -++ -++#define __dmac_enable_channel(n) \ -++do { \ -++ REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_EN; \ -++} while (0) -++#define __dmac_disable_channel(n) \ -++do { \ -++ REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_EN; \ -++} while (0) -++#define __dmac_channel_enabled(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_EN ) -++ -++#define __dmac_channel_enable_irq(n) \ -++ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_TIE ) -++#define __dmac_channel_disable_irq(n) \ -++ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_TIE ) -++ -++#define __dmac_channel_transmit_halt_detected(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_HLT ) -++#define __dmac_channel_transmit_end_detected(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_TT ) -++#define __dmac_channel_address_error_detected(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_AR ) -++#define __dmac_channel_count_terminated_detected(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_CT ) -++#define __dmac_channel_descriptor_invalid_detected(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_INV ) -++ -++#define __dmac_channel_clear_transmit_halt(n) \ -++ do { \ -++ /* clear both channel halt error and globle halt error */ \ -++ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_HLT; \ -++ REG_DMAC_DMACR(n/HALF_DMA_NUM) &= ~DMAC_DMACR_HLT; \ -++ } while (0) -++#define __dmac_channel_clear_transmit_end(n) \ -++ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_TT ) -++#define __dmac_channel_clear_address_error(n) \ -++ do { \ -++ REG_DMAC_DDA(n) = 0; /* clear descriptor address register */ \ -++ REG_DMAC_DSAR(n) = 0; /* clear source address register */ \ -++ REG_DMAC_DTAR(n) = 0; /* clear target address register */ \ -++ /* clear both channel addr error and globle address error */ \ -++ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_AR; \ -++ REG_DMAC_DMACR(n/HALF_DMA_NUM) &= ~DMAC_DMACR_AR; \ -++ } while (0) -++#define __dmac_channel_clear_count_terminated(n) \ -++ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_CT ) -++#define __dmac_channel_clear_descriptor_invalid(n) \ -++ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_INV ) -++ -++#define __dmac_channel_set_transfer_unit_32bit(n) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BIT; \ -++} while (0) -++ -++#define __dmac_channel_set_transfer_unit_16bit(n) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BIT; \ -++} while (0) -++ -++#define __dmac_channel_set_transfer_unit_8bit(n) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_8BIT; \ -++} while (0) -++ -++#define __dmac_channel_set_transfer_unit_16byte(n) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BYTE; \ -++} while (0) -++ -++#define __dmac_channel_set_transfer_unit_32byte(n) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BYTE; \ -++} while (0) -++ -++/* w=8,16,32 */ -++#define __dmac_channel_set_dest_port_width(n,w) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DWDH_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DWDH_##w; \ -++} while (0) -++ -++/* w=8,16,32 */ -++#define __dmac_channel_set_src_port_width(n,w) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SWDH_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_SWDH_##w; \ -++} while (0) -++ -++/* v=0-15 */ -++#define __dmac_channel_set_rdil(n,v) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_RDIL_MASK; \ -++ REG_DMAC_DCMD((n) |= ((v) << DMAC_DCMD_RDIL_BIT); \ -++} while (0) -++ -++#define __dmac_channel_dest_addr_fixed(n) \ -++ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DAI ) -++#define __dmac_channel_dest_addr_increment(n) \ -++ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_DAI ) -++ -++#define __dmac_channel_src_addr_fixed(n) \ -++ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SAI ) -++#define __dmac_channel_src_addr_increment(n) \ -++ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_SAI ) -++ -++#define __dmac_channel_set_doorbell(n) \ -++ ( REG_DMAC_DMADBSR((n)/HALF_DMA_NUM) = (1 << ((n)-(n)/HALF_DMA_NUM*HALF_DMA_NUM)) ) -++ -++#define __dmac_channel_irq_detected(n) ( REG_DMAC_DMAIPR((n)/HALF_DMA_NUM) & (1 << ((n)-(n)/HALF_DMA_NUM*HALF_DMA_NUM)) ) -++#define __dmac_channel_ack_irq(n) ( REG_DMAC_DMAIPR((n)/HALF_DMA_NUM) &= ~(1 <<((n)-(n)/HALF_DMA_NUM*HALF_DMA_NUM)) ) -++ -++static __inline__ int __dmac_get_irq(void) -++{ -++ int i; -++ for (i = 0; i < MAX_DMA_NUM; i++) -++ if (__dmac_channel_irq_detected(i)) -++ return i; -++ return -1; -++} -++ -++ -++/*************************************************************************** -++ * AIC (AC'97 & I2S Controller) -++ ***************************************************************************/ -++ -++#define __aic_enable() ( REG_AIC_FR |= AIC_FR_ENB ) -++#define __aic_disable() ( REG_AIC_FR &= ~AIC_FR_ENB ) -++ -++#define __aic_select_ac97() ( REG_AIC_FR &= ~AIC_FR_AUSEL ) -++#define __aic_select_i2s() ( REG_AIC_FR |= AIC_FR_AUSEL ) -++ -++#define __aic_play_zero() ( REG_AIC_FR &= ~AIC_FR_LSMP ) -++#define __aic_play_lastsample() ( REG_AIC_FR |= AIC_FR_LSMP ) -++ -++#define __i2s_as_master() ( REG_AIC_FR |= AIC_FR_BCKD | AIC_FR_SYNCD ) -++#define __i2s_as_slave() ( REG_AIC_FR &= ~(AIC_FR_BCKD | AIC_FR_SYNCD) ) -++#define __aic_reset_status() ( REG_AIC_FR & AIC_FR_RST ) -++ -++#define __aic_reset() \ -++do { \ -++ REG_AIC_FR |= AIC_FR_RST; \ -++} while(0) -++ -++ -++#define __aic_set_transmit_trigger(n) \ -++do { \ -++ REG_AIC_FR &= ~AIC_FR_TFTH_MASK; \ -++ REG_AIC_FR |= ((n) << AIC_FR_TFTH_BIT); \ -++} while(0) -++ -++#define __aic_set_receive_trigger(n) \ -++do { \ -++ REG_AIC_FR &= ~AIC_FR_RFTH_MASK; \ -++ REG_AIC_FR |= ((n) << AIC_FR_RFTH_BIT); \ -++} while(0) -++ -++#define __aic_enable_record() ( REG_AIC_CR |= AIC_CR_EREC ) -++#define __aic_disable_record() ( REG_AIC_CR &= ~AIC_CR_EREC ) -++#define __aic_enable_replay() ( REG_AIC_CR |= AIC_CR_ERPL ) -++#define __aic_disable_replay() ( REG_AIC_CR &= ~AIC_CR_ERPL ) -++#define __aic_enable_loopback() ( REG_AIC_CR |= AIC_CR_ENLBF ) -++#define __aic_disable_loopback() ( REG_AIC_CR &= ~AIC_CR_ENLBF ) -++ -++#define __aic_flush_fifo() ( REG_AIC_CR |= AIC_CR_FLUSH ) -++#define __aic_unflush_fifo() ( REG_AIC_CR &= ~AIC_CR_FLUSH ) -++ -++#define __aic_enable_transmit_intr() \ -++ ( REG_AIC_CR |= (AIC_CR_ETFS | AIC_CR_ETUR) ) -++#define __aic_disable_transmit_intr() \ -++ ( REG_AIC_CR &= ~(AIC_CR_ETFS | AIC_CR_ETUR) ) -++#define __aic_enable_receive_intr() \ -++ ( REG_AIC_CR |= (AIC_CR_ERFS | AIC_CR_EROR) ) -++#define __aic_disable_receive_intr() \ -++ ( REG_AIC_CR &= ~(AIC_CR_ERFS | AIC_CR_EROR) ) -++ -++#define __aic_enable_transmit_dma() ( REG_AIC_CR |= AIC_CR_TDMS ) -++#define __aic_disable_transmit_dma() ( REG_AIC_CR &= ~AIC_CR_TDMS ) -++#define __aic_enable_receive_dma() ( REG_AIC_CR |= AIC_CR_RDMS ) -++#define __aic_disable_receive_dma() ( REG_AIC_CR &= ~AIC_CR_RDMS ) -++ -++#define __aic_enable_mono2stereo() ( REG_AIC_CR |= AIC_CR_M2S ) -++#define __aic_disable_mono2stereo() ( REG_AIC_CR &= ~AIC_CR_M2S ) -++#define __aic_enable_byteswap() ( REG_AIC_CR |= AIC_CR_ENDSW ) -++#define __aic_disable_byteswap() ( REG_AIC_CR &= ~AIC_CR_ENDSW ) -++#define __aic_enable_unsignadj() ( REG_AIC_CR |= AIC_CR_AVSTSU ) -++#define __aic_disable_unsignadj() ( REG_AIC_CR &= ~AIC_CR_AVSTSU ) -++ -++#define AC97_PCM_XS_L_FRONT AIC_ACCR1_XS_SLOT3 -++#define AC97_PCM_XS_R_FRONT AIC_ACCR1_XS_SLOT4 -++#define AC97_PCM_XS_CENTER AIC_ACCR1_XS_SLOT6 -++#define AC97_PCM_XS_L_SURR AIC_ACCR1_XS_SLOT7 -++#define AC97_PCM_XS_R_SURR AIC_ACCR1_XS_SLOT8 -++#define AC97_PCM_XS_LFE AIC_ACCR1_XS_SLOT9 -++ -++#define AC97_PCM_RS_L_FRONT AIC_ACCR1_RS_SLOT3 -++#define AC97_PCM_RS_R_FRONT AIC_ACCR1_RS_SLOT4 -++#define AC97_PCM_RS_CENTER AIC_ACCR1_RS_SLOT6 -++#define AC97_PCM_RS_L_SURR AIC_ACCR1_RS_SLOT7 -++#define AC97_PCM_RS_R_SURR AIC_ACCR1_RS_SLOT8 -++#define AC97_PCM_RS_LFE AIC_ACCR1_RS_SLOT9 -++ -++#define __ac97_set_xs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK ) -++#define __ac97_set_xs_mono() \ -++do { \ -++ REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \ -++ REG_AIC_ACCR1 |= AC97_PCM_XS_R_FRONT; \ -++} while(0) -++#define __ac97_set_xs_stereo() \ -++do { \ -++ REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \ -++ REG_AIC_ACCR1 |= AC97_PCM_XS_L_FRONT | AC97_PCM_XS_R_FRONT; \ -++} while(0) -++ -++/* In fact, only stereo is support now. */ -++#define __ac97_set_rs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK ) -++#define __ac97_set_rs_mono() \ -++do { \ -++ REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \ -++ REG_AIC_ACCR1 |= AC97_PCM_RS_R_FRONT; \ -++} while(0) -++#define __ac97_set_rs_stereo() \ -++do { \ -++ REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \ -++ REG_AIC_ACCR1 |= AC97_PCM_RS_L_FRONT | AC97_PCM_RS_R_FRONT; \ -++} while(0) -++ -++#define __ac97_warm_reset_codec() \ -++ do { \ -++ REG_AIC_ACCR2 |= AIC_ACCR2_SA; \ -++ REG_AIC_ACCR2 |= AIC_ACCR2_SS; \ -++ udelay(2); \ -++ REG_AIC_ACCR2 &= ~AIC_ACCR2_SS; \ -++ REG_AIC_ACCR2 &= ~AIC_ACCR2_SA; \ -++ } while (0) -++ -++#define __ac97_cold_reset_codec() \ -++ do { \ -++ REG_AIC_ACCR2 |= AIC_ACCR2_SR; \ -++ udelay(2); \ -++ REG_AIC_ACCR2 &= ~AIC_ACCR2_SR; \ -++ } while (0) -++ -++/* n=8,16,18,20 */ -++#define __ac97_set_iass(n) \ -++ ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_IASS_MASK) | AIC_ACCR2_IASS_##n##BIT ) -++#define __ac97_set_oass(n) \ -++ ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_OASS_MASK) | AIC_ACCR2_OASS_##n##BIT ) -++ -++#define __i2s_select_i2s() ( REG_AIC_I2SCR &= ~AIC_I2SCR_AMSL ) -++#define __i2s_select_msbjustified() ( REG_AIC_I2SCR |= AIC_I2SCR_AMSL ) -++ -++/* n=8,16,18,20,24 */ -++/*#define __i2s_set_sample_size(n) \ -++ ( REG_AIC_I2SCR |= (REG_AIC_I2SCR & ~AIC_I2SCR_WL_MASK) | AIC_I2SCR_WL_##n##BIT )*/ -++ -++#define __i2s_set_oss_sample_size(n) \ -++ ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_OSS_MASK) | AIC_CR_OSS_##n##BIT ) -++#define __i2s_set_iss_sample_size(n) \ -++ ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_ISS_MASK) | AIC_CR_ISS_##n##BIT ) -++ -++#define __i2s_stop_bitclk() ( REG_AIC_I2SCR |= AIC_I2SCR_STPBK ) -++#define __i2s_start_bitclk() ( REG_AIC_I2SCR &= ~AIC_I2SCR_STPBK ) -++ -++#define __aic_transmit_request() ( REG_AIC_SR & AIC_SR_TFS ) -++#define __aic_receive_request() ( REG_AIC_SR & AIC_SR_RFS ) -++#define __aic_transmit_underrun() ( REG_AIC_SR & AIC_SR_TUR ) -++#define __aic_receive_overrun() ( REG_AIC_SR & AIC_SR_ROR ) -++ -++#define __aic_clear_errors() ( REG_AIC_SR &= ~(AIC_SR_TUR | AIC_SR_ROR) ) -++ -++#define __aic_get_transmit_resident() \ -++ ( (REG_AIC_SR & AIC_SR_TFL_MASK) >> AIC_SR_TFL_BIT ) -++#define __aic_get_receive_count() \ -++ ( (REG_AIC_SR & AIC_SR_RFL_MASK) >> AIC_SR_RFL_BIT ) -++ -++#define __ac97_command_transmitted() ( REG_AIC_ACSR & AIC_ACSR_CADT ) -++#define __ac97_status_received() ( REG_AIC_ACSR & AIC_ACSR_SADR ) -++#define __ac97_status_receive_timeout() ( REG_AIC_ACSR & AIC_ACSR_RSTO ) -++#define __ac97_codec_is_low_power_mode() ( REG_AIC_ACSR & AIC_ACSR_CLPM ) -++#define __ac97_codec_is_ready() ( REG_AIC_ACSR & AIC_ACSR_CRDY ) -++#define __ac97_slot_error_detected() ( REG_AIC_ACSR & AIC_ACSR_SLTERR ) -++#define __ac97_clear_slot_error() ( REG_AIC_ACSR &= ~AIC_ACSR_SLTERR ) -++ -++#define __i2s_is_busy() ( REG_AIC_I2SSR & AIC_I2SSR_BSY ) -++ -++#define CODEC_READ_CMD (1 << 19) -++#define CODEC_WRITE_CMD (0 << 19) -++#define CODEC_REG_INDEX_BIT 12 -++#define CODEC_REG_INDEX_MASK (0x7f << CODEC_REG_INDEX_BIT) /* 18:12 */ -++#define CODEC_REG_DATA_BIT 4 -++#define CODEC_REG_DATA_MASK (0x0ffff << 4) /* 19:4 */ -++ -++#define __ac97_out_rcmd_addr(reg) \ -++do { \ -++ REG_AIC_ACCAR = CODEC_READ_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ -++} while (0) -++ -++#define __ac97_out_wcmd_addr(reg) \ -++do { \ -++ REG_AIC_ACCAR = CODEC_WRITE_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ -++} while (0) -++ -++#define __ac97_out_data(value) \ -++do { \ -++ REG_AIC_ACCDR = ((value) << CODEC_REG_DATA_BIT); \ -++} while (0) -++ -++#define __ac97_in_data() \ -++ ( (REG_AIC_ACSDR & CODEC_REG_DATA_MASK) >> CODEC_REG_DATA_BIT ) -++ -++#define __ac97_in_status_addr() \ -++ ( (REG_AIC_ACSAR & CODEC_REG_INDEX_MASK) >> CODEC_REG_INDEX_BIT ) -++ -++#define __i2s_set_sample_rate(i2sclk, sync) \ -++ ( REG_AIC_I2SDIV = ((i2sclk) / (4*64)) / (sync) ) -++ -++#define __aic_write_tfifo(v) ( REG_AIC_DR = (v) ) -++#define __aic_read_rfifo() ( REG_AIC_DR ) -++ -++#define __aic_internal_codec() ( REG_AIC_FR |= AIC_FR_ICDC ) -++#define __aic_external_codec() ( REG_AIC_FR &= ~AIC_FR_ICDC ) -++ -++// -++// Define next ops for AC97 compatible -++// -++ -++#define AC97_ACSR AIC_ACSR -++ -++#define __ac97_enable() __aic_enable(); __aic_select_ac97() -++#define __ac97_disable() __aic_disable() -++#define __ac97_reset() __aic_reset() -++ -++#define __ac97_set_transmit_trigger(n) __aic_set_transmit_trigger(n) -++#define __ac97_set_receive_trigger(n) __aic_set_receive_trigger(n) -++ -++#define __ac97_enable_record() __aic_enable_record() -++#define __ac97_disable_record() __aic_disable_record() -++#define __ac97_enable_replay() __aic_enable_replay() -++#define __ac97_disable_replay() __aic_disable_replay() -++#define __ac97_enable_loopback() __aic_enable_loopback() -++#define __ac97_disable_loopback() __aic_disable_loopback() -++ -++#define __ac97_enable_transmit_dma() __aic_enable_transmit_dma() -++#define __ac97_disable_transmit_dma() __aic_disable_transmit_dma() -++#define __ac97_enable_receive_dma() __aic_enable_receive_dma() -++#define __ac97_disable_receive_dma() __aic_disable_receive_dma() -++ -++#define __ac97_transmit_request() __aic_transmit_request() -++#define __ac97_receive_request() __aic_receive_request() -++#define __ac97_transmit_underrun() __aic_transmit_underrun() -++#define __ac97_receive_overrun() __aic_receive_overrun() -++ -++#define __ac97_clear_errors() __aic_clear_errors() -++ -++#define __ac97_get_transmit_resident() __aic_get_transmit_resident() -++#define __ac97_get_receive_count() __aic_get_receive_count() -++ -++#define __ac97_enable_transmit_intr() __aic_enable_transmit_intr() -++#define __ac97_disable_transmit_intr() __aic_disable_transmit_intr() -++#define __ac97_enable_receive_intr() __aic_enable_receive_intr() -++#define __ac97_disable_receive_intr() __aic_disable_receive_intr() -++ -++#define __ac97_write_tfifo(v) __aic_write_tfifo(v) -++#define __ac97_read_rfifo() __aic_read_rfifo() -++ -++// -++// Define next ops for I2S compatible -++// -++ -++#define I2S_ACSR AIC_I2SSR -++ -++#define __i2s_enable() __aic_enable(); __aic_select_i2s() -++#define __i2s_disable() __aic_disable() -++#define __i2s_reset() __aic_reset() -++ -++#define __i2s_set_transmit_trigger(n) __aic_set_transmit_trigger(n) -++#define __i2s_set_receive_trigger(n) __aic_set_receive_trigger(n) -++ -++#define __i2s_enable_record() __aic_enable_record() -++#define __i2s_disable_record() __aic_disable_record() -++#define __i2s_enable_replay() __aic_enable_replay() -++#define __i2s_disable_replay() __aic_disable_replay() -++#define __i2s_enable_loopback() __aic_enable_loopback() -++#define __i2s_disable_loopback() __aic_disable_loopback() -++ -++#define __i2s_enable_transmit_dma() __aic_enable_transmit_dma() -++#define __i2s_disable_transmit_dma() __aic_disable_transmit_dma() -++#define __i2s_enable_receive_dma() __aic_enable_receive_dma() -++#define __i2s_disable_receive_dma() __aic_disable_receive_dma() -++ -++#define __i2s_transmit_request() __aic_transmit_request() -++#define __i2s_receive_request() __aic_receive_request() -++#define __i2s_transmit_underrun() __aic_transmit_underrun() -++#define __i2s_receive_overrun() __aic_receive_overrun() -++ -++#define __i2s_clear_errors() __aic_clear_errors() -++ -++#define __i2s_get_transmit_resident() __aic_get_transmit_resident() -++#define __i2s_get_receive_count() __aic_get_receive_count() -++ -++#define __i2s_enable_transmit_intr() __aic_enable_transmit_intr() -++#define __i2s_disable_transmit_intr() __aic_disable_transmit_intr() -++#define __i2s_enable_receive_intr() __aic_enable_receive_intr() -++#define __i2s_disable_receive_intr() __aic_disable_receive_intr() -++ -++#define __i2s_write_tfifo(v) __aic_write_tfifo(v) -++#define __i2s_read_rfifo() __aic_read_rfifo() -++ -++#define __i2s_reset_codec() \ -++ do { \ -++ } while (0) -++ -++/************************************************************************* -++ * PCM Controller operation -++ *************************************************************************/ -++ -++#define __pcm_enable() ( REG_PCM_CTL |= PCM_CTL_PCMEN ) -++#define __pcm_disable() ( REG_PCM_CTL &= ~PCM_CTL_PCMEN ) -++ -++#define __pcm_clk_enable() ( REG_PCM_CTL |= PCM_CTL_CLKEN ) -++#define __pcm_clk_disable() ( REG_PCM_CTL &= ~PCM_CTL_CLKEN ) -++ -++#define __pcm_reset() ( REG_PCM_CTL |= PCM_CTL_RST ) -++#define __pcm_flush_fifo() ( REG_PCM_CTL |= PCM_CTL_FLUSH ) -++ -++#define __pcm_enable_record() ( REG_PCM_CTL |= PCM_CTL_EREC ) -++#define __pcm_disable_record() ( REG_PCM_CTL &= ~PCM_CTL_EREC ) -++#define __pcm_enable_playback() ( REG_PCM_CTL |= PCM_CTL_ERPL ) -++#define __pcm_disable_playback() ( REG_PCM_CTL &= ~PCM_CTL_ERPL ) -++ -++#define __pcm_enable_rxfifo() __pcm_enable_record() -++#define __pcm_disable_rxfifo() __pcm_disable_record() -++#define __pcm_enable_txfifo() __pcm_enable_playback() -++#define __pcm_disable_txfifo() __pcm_disable_playback() -++ -++#define __pcm_last_sample() ( REG_PCM_CTL |= PCM_CTL_LSMP ) -++#define __pcm_zero_sample() ( REG_PCM_CTL &= ~PCM_CTL_LSMP ) -++ -++#define __pcm_enable_transmit_dma() ( REG_PCM_CTL |= PCM_CTL_ETDMA ) -++#define __pcm_disable_transmit_dma() ( REG_PCM_CTL &= ~PCM_CTL_ETDMA ) -++#define __pcm_enable_receive_dma() ( REG_PCM_CTL |= PCM_CTL_ERDMA ) -++#define __pcm_disable_receive_dma() ( REG_PCM_CTL &= ~PCM_CTL_ERDMA ) -++ -++#define __pcm_as_master() ( REG_PCM_CFG &= PCM_CFG_MODE ) -++#define __pcm_as_slave() ( REG_PCM_CFG |= ~PCM_CFG_MODE ) -++ -++#define __pcm_set_transmit_trigger(n) \ -++do { \ -++ REG_PCM_CFG &= ~PCM_CFG_TFTH_MASK; \ -++ REG_PCM_CFG |= ((n) << PCM_CFG_TFTH_BIT); \ -++} while(0) -++ -++#define __pcm_set_receive_trigger(n) \ -++do { \ -++ REG_PCM_CFG &= ~PCM_CFG_RFTH_MASK; \ -++ REG_PCM_CFG |= ((n) << PCM_CFG_RFTH_BIT); \ -++} while(0) -++ -++#define __pcm_omsb_same_sync() ( REG_PCM_CFG &= ~PCM_CFG_OMSBPOS ) -++#define __pcm_omsb_next_sync() ( REG_PCM_CFG |= PCM_CFG_OMSBPOS ) -++ -++#define __pcm_imsb_same_sync() ( REG_PCM_CFG &= ~PCM_CFG_IMSBPOS ) -++#define __pcm_imsb_next_sync() ( REG_PCM_CFG |= PCM_CFG_IMSBPOS ) -++ -++/* set input sample size 8 or 16*/ -++#define __pcm_set_iss(n) \ -++( REG_PCM_CFG = (REG_PCM_CFG & ~PCM_CFG_ISS_MASK) | PCM_CFG_ISS_##n ) -++/* set output sample size 8 or 16*/ -++#define __pcm_set_oss(n) \ -++( REG_PCM_CFG = (REG_PCM_CFG & ~PCM_CFG_OSS_MASK) | PCM_CFG_OSS_##n ) -++ -++#define __pcm_set_valid_slot(n) \ -++( REG_PCM_CFG = (REG_PCM_CFG & ~PCM_CFG_SLOT_MASK) | PCM_CFG_SLOT_##n ) -++ -++#define __pcm_write_data(v) ( REG_PCM_DP = (v) ) -++#define __pcm_read_data() ( REG_PCM_DP ) -++ -++#define __pcm_enable_tfs_intr() ( REG_PCM_INTC |= PCM_INTC_ETFS ) -++#define __pcm_disable_tfs_intr() ( REG_PCM_INTC &= ~PCM_INTC_ETFS ) -++ -++#define __pcm_enable_tur_intr() ( REG_PCM_INTC |= PCM_INTC_ETUR ) -++#define __pcm_disable_tur_intr() ( REG_PCM_INTC &= ~PCM_INTC_ETUR ) -++ -++#define __pcm_enable_rfs_intr() ( REG_PCM_INTC |= PCM_INTC_ERFS ) -++#define __pcm_disable_rfs_intr() ( REG_PCM_INTC &= ~PCM_INTC_ERFS ) -++ -++#define __pcm_enable_ror_intr() ( REG_PCM_INTC |= PCM_INTC_EROR ) -++#define __pcm_disable_ror_intr() ( REG_PCM_INTC &= ~PCM_INTC_EROR ) -++ -++#define __pcm_ints_valid_tx() \ -++( ((REG_PCM_INTS & PCM_INTS_TFL_MASK) >> PCM_INTS_TFL_BIT) ) -++#define __pcm_ints_valid_rx() \ -++( ((REG_PCM_INTS & PCM_INTS_RFL_MASK) >> PCM_INTS_RFL_BIT) ) -++ -++#define __pcm_set_clk_div(n) \ -++( REG_PCM_DIV = (REG_PCM_DIV & ~PCM_DIV_CLKDIV_MASK) | ((n) << PCM_DIV_CLKDIV_BIT) ) -++ -++/* sysclk(cpm_pcm_sysclk) Hz is created by cpm logic, and pcmclk Hz is the pcm in/out clock wanted */ -++#define __pcm_set_clk_rate(sysclk, pcmclk) \ -++__pcm_set_clk_div(((sysclk) / (pcmclk) - 1)) -++ -++#define __pcm_set_sync_div(n) \ -++( REG_PCM_DIV = (REG_PCM_DIV & ~PCM_DIV_SYNDIV_MASK) | ((n) << PCM_DIV_SYNDIV_BIT) ) -++ -++/* pcmclk is source clock Hz, and sync is the frame sync clock Hz wanted */ -++#define __pcm_set_sync_rate(pcmclk, sync) \ -++__pcm_set_sync_div(((pcmclk) / (8 * (sync)) - 1)) -++ -++ /* set sync length in pcmclk n = 0 ... 63 */ -++#define __pcm_set_sync_len(n) \ -++( REG_PCM_DIV = (REG_PCM_DIV & ~PCM_DIV_SYNL_MASK) | (n << PCM_DIV_SYNL_BIT) ) -++ -++ -++/*************************************************************************** -++ * ICDC -++ ***************************************************************************/ -++#define __i2s_internal_codec() __aic_internal_codec() -++#define __i2s_external_codec() __aic_external_codec() -++ -++#define __icdc_clk_ready() ( REG_ICDC_CKCFG & ICDC_CKCFG_CKRDY ) -++#define __icdc_sel_adc() ( REG_ICDC_CKCFG |= ICDC_CKCFG_SELAD ) -++#define __icdc_sel_dac() ( REG_ICDC_CKCFG &= ~ICDC_CKCFG_SELAD ) -++ -++#define __icdc_set_rgwr() ( REG_ICDC_RGADW |= ICDC_RGADW_RGWR ) -++#define __icdc_clear_rgwr() ( REG_ICDC_RGADW &= ~ICDC_RGADW_RGWR ) -++#define __icdc_rgwr_ready() ( REG_ICDC_RGADW & ICDC_RGADW_RGWR ) -++ -++#define __icdc_set_addr(n) \ -++do { \ -++ REG_ICDC_RGADW &= ~ICDC_RGADW_RGADDR_MASK; \ -++ REG_ICDC_RGADW |= (n) << ICDC_RGADW_RGADDR_BIT; \ -++} while(0) -++ -++#define __icdc_set_cmd(n) \ -++do { \ -++ REG_ICDC_RGADW &= ~ICDC_RGADW_RGDIN_MASK; \ -++ REG_ICDC_RGADW |= (n) << ICDC_RGADW_RGDIN_BIT; \ -++} while(0) -++ -++#define __icdc_irq_pending() ( REG_ICDC_RGDATA & ICDC_RGDATA_IRQ ) -++#define __icdc_get_value() ( REG_ICDC_RGDATA & ICDC_RGDATA_RGDOUT_MASK ) -++ -++/*************************************************************************** -++ * INTC -++ ***************************************************************************/ -++#define __intc_unmask_irq(n) ( REG_INTC_IMCR = (1 << (n)) ) -++#define __intc_mask_irq(n) ( REG_INTC_IMSR = (1 << (n)) ) -++#define __intc_ack_irq(n) ( REG_INTC_IPR = (1 << (n)) ) /* A dummy ack, as the Pending Register is Read Only. Should we remove __intc_ack_irq() */ -++ -++ -++/*************************************************************************** -++ * I2C -++ ***************************************************************************/ -++ -++#define __i2c_enable() ( REG_I2C_CR |= I2C_CR_I2CE ) -++#define __i2c_disable() ( REG_I2C_CR &= ~I2C_CR_I2CE ) -++ -++#define __i2c_send_start() ( REG_I2C_CR |= I2C_CR_STA ) -++#define __i2c_send_stop() ( REG_I2C_CR |= I2C_CR_STO ) -++#define __i2c_send_ack() ( REG_I2C_CR &= ~I2C_CR_AC ) -++#define __i2c_send_nack() ( REG_I2C_CR |= I2C_CR_AC ) -++ -++#define __i2c_set_drf() ( REG_I2C_SR |= I2C_SR_DRF ) -++#define __i2c_clear_drf() ( REG_I2C_SR &= ~I2C_SR_DRF ) -++#define __i2c_check_drf() ( REG_I2C_SR & I2C_SR_DRF ) -++ -++#define __i2c_received_ack() ( !(REG_I2C_SR & I2C_SR_ACKF) ) -++#define __i2c_is_busy() ( REG_I2C_SR & I2C_SR_BUSY ) -++#define __i2c_transmit_ended() ( REG_I2C_SR & I2C_SR_TEND ) -++ -++#define __i2c_set_clk(dev_clk, i2c_clk) \ -++ ( REG_I2C_GR = (dev_clk) / (16*(i2c_clk)) - 1 ) -++ -++#define __i2c_read() ( REG_I2C_DR ) -++#define __i2c_write(val) ( REG_I2C_DR = (val) ) -++ -++ -++/*************************************************************************** -++ * MSC -++ ***************************************************************************/ -++/* n = 0, 1 (MSC0, MSC1) */ -++ -++#define __msc_start_op(n) \ -++ ( REG_MSC_STRPCL(n) = MSC_STRPCL_START_OP | MSC_STRPCL_CLOCK_CONTROL_START ) -++ -++#define __msc_set_resto(n, to) ( REG_MSC_RESTO(n) = to ) -++#define __msc_set_rdto(n, to) ( REG_MSC_RDTO(n) = to ) -++#define __msc_set_cmd(n, cmd) ( REG_MSC_CMD(n) = cmd ) -++#define __msc_set_arg(n, arg) ( REG_MSC_ARG(n) = arg ) -++#define __msc_set_nob(n, nob) ( REG_MSC_NOB(n) = nob ) -++#define __msc_get_nob(n) ( REG_MSC_NOB(n) ) -++#define __msc_set_blklen(n, len) ( REG_MSC_BLKLEN(n) = len ) -++#define __msc_set_cmdat(n, cmdat) ( REG_MSC_CMDAT(n) = cmdat ) -++#define __msc_set_cmdat_ioabort(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_IO_ABORT ) -++#define __msc_clear_cmdat_ioabort(n) ( REG_MSC_CMDAT(n) &= ~MSC_CMDAT_IO_ABORT ) -++ -++#define __msc_set_cmdat_bus_width1(n) \ -++do { \ -++ REG_MSC_CMDAT(n) &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ -++ REG_MSC_CMDAT(n) |= MSC_CMDAT_BUS_WIDTH_1BIT; \ -++} while(0) -++ -++#define __msc_set_cmdat_bus_width4(n) \ -++do { \ -++ REG_MSC_CMDAT(n) &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ -++ REG_MSC_CMDAT(n) |= MSC_CMDAT_BUS_WIDTH_4BIT; \ -++} while(0) -++ -++#define __msc_set_cmdat_dma_en(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_DMA_EN ) -++#define __msc_set_cmdat_init(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_INIT ) -++#define __msc_set_cmdat_busy(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_BUSY ) -++#define __msc_set_cmdat_stream(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_STREAM_BLOCK ) -++#define __msc_set_cmdat_block(n) ( REG_MSC_CMDAT(n) &= ~MSC_CMDAT_STREAM_BLOCK ) -++#define __msc_set_cmdat_read(n) ( REG_MSC_CMDAT(n) &= ~MSC_CMDAT_WRITE_READ ) -++#define __msc_set_cmdat_write(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_WRITE_READ ) -++#define __msc_set_cmdat_data_en(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_DATA_EN ) -++ -++/* r is MSC_CMDAT_RESPONSE_FORMAT_Rx or MSC_CMDAT_RESPONSE_FORMAT_NONE */ -++#define __msc_set_cmdat_res_format(n, r) \ -++do { \ -++ REG_MSC_CMDAT(n) &= ~MSC_CMDAT_RESPONSE_FORMAT_MASK; \ -++ REG_MSC_CMDAT(n) |= (r); \ -++} while(0) -++ -++#define __msc_clear_cmdat(n) \ -++ REG_MSC_CMDAT(n) &= ~( MSC_CMDAT_IO_ABORT | MSC_CMDAT_DMA_EN | MSC_CMDAT_INIT| \ -++ MSC_CMDAT_BUSY | MSC_CMDAT_STREAM_BLOCK | MSC_CMDAT_WRITE_READ | \ -++ MSC_CMDAT_DATA_EN | MSC_CMDAT_RESPONSE_FORMAT_MASK ) -++ -++#define __msc_get_imask(n) ( REG_MSC_IMASK(n) ) -++#define __msc_mask_all_intrs(n) ( REG_MSC_IMASK(n) = 0xff ) -++#define __msc_unmask_all_intrs(n) ( REG_MSC_IMASK(n) = 0x00 ) -++#define __msc_mask_rd(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_RXFIFO_RD_REQ ) -++#define __msc_unmask_rd(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_RXFIFO_RD_REQ ) -++#define __msc_mask_wr(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_TXFIFO_WR_REQ ) -++#define __msc_unmask_wr(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_TXFIFO_WR_REQ ) -++#define __msc_mask_endcmdres(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_END_CMD_RES ) -++#define __msc_unmask_endcmdres(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_END_CMD_RES ) -++#define __msc_mask_datatrandone(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_DATA_TRAN_DONE ) -++#define __msc_unmask_datatrandone(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_DATA_TRAN_DONE ) -++#define __msc_mask_prgdone(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_PRG_DONE ) -++#define __msc_unmask_prgdone(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_PRG_DONE ) -++ -++/* m=0,1,2,3,4,5,6,7 */ -++#define __msc_set_clkrt(n, m) \ -++do { \ -++ REG_MSC_CLKRT(n) = m; \ -++} while(0) -++ -++#define __msc_get_ireg(n) ( REG_MSC_IREG(n) ) -++#define __msc_ireg_rd(n) ( REG_MSC_IREG(n) & MSC_IREG_RXFIFO_RD_REQ ) -++#define __msc_ireg_wr(n) ( REG_MSC_IREG(n) & MSC_IREG_TXFIFO_WR_REQ ) -++#define __msc_ireg_end_cmd_res(n) ( REG_MSC_IREG(n) & MSC_IREG_END_CMD_RES ) -++#define __msc_ireg_data_tran_done(n) ( REG_MSC_IREG(n) & MSC_IREG_DATA_TRAN_DONE ) -++#define __msc_ireg_prg_done(n) ( REG_MSC_IREG(n) & MSC_IREG_PRG_DONE ) -++#define __msc_ireg_clear_end_cmd_res(n) ( REG_MSC_IREG(n) = MSC_IREG_END_CMD_RES ) -++#define __msc_ireg_clear_data_tran_done(n) ( REG_MSC_IREG(n) = MSC_IREG_DATA_TRAN_DONE ) -++#define __msc_ireg_clear_prg_done(n) ( REG_MSC_IREG(n) = MSC_IREG_PRG_DONE ) -++ -++#define __msc_get_stat(n) ( REG_MSC_STAT(n) ) -++#define __msc_stat_not_end_cmd_res(n) ( (REG_MSC_STAT(n) & MSC_STAT_END_CMD_RES) == 0) -++#define __msc_stat_crc_err(n) \ -++ ( REG_MSC_STAT(n) & (MSC_STAT_CRC_RES_ERR | MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR_YES) ) -++#define __msc_stat_res_crc_err(n) ( REG_MSC_STAT(n) & MSC_STAT_CRC_RES_ERR ) -++#define __msc_stat_rd_crc_err(n) ( REG_MSC_STAT(n) & MSC_STAT_CRC_READ_ERROR ) -++#define __msc_stat_wr_crc_err(n) ( REG_MSC_STAT(n) & MSC_STAT_CRC_WRITE_ERROR_YES ) -++#define __msc_stat_resto_err(n) ( REG_MSC_STAT(n) & MSC_STAT_TIME_OUT_RES ) -++#define __msc_stat_rdto_err(n) ( REG_MSC_STAT(n) & MSC_STAT_TIME_OUT_READ ) -++ -++#define __msc_rd_resfifo(n) ( REG_MSC_RES(n) ) -++#define __msc_rd_rxfifo(n) ( REG_MSC_RXFIFO(n) ) -++#define __msc_wr_txfifo(n, v) ( REG_MSC_TXFIFO(n) = v ) -++ -++#define __msc_reset(n) \ -++do { \ -++ REG_MSC_STRPCL(n) = MSC_STRPCL_RESET; \ -++ while (REG_MSC_STAT(n) & MSC_STAT_IS_RESETTING); \ -++} while (0) -++ -++#define __msc_start_clk(n) \ -++do { \ -++ REG_MSC_STRPCL(n) = MSC_STRPCL_CLOCK_CONTROL_START; \ -++} while (0) -++ -++#define __msc_stop_clk(n) \ -++do { \ -++ REG_MSC_STRPCL(n) = MSC_STRPCL_CLOCK_CONTROL_STOP; \ -++} while (0) -++ -++#define MMC_CLK 19169200 -++#define SD_CLK 24576000 -++ -++/* msc_clk should little than pclk and little than clk retrieve from card */ -++#define __msc_calc_clk_divisor(type,dev_clk,msc_clk,lv) \ -++do { \ -++ unsigned int rate, pclk, i; \ -++ pclk = dev_clk; \ -++ rate = type?SD_CLK:MMC_CLK; \ -++ if (msc_clk && msc_clk < pclk) \ -++ pclk = msc_clk; \ -++ i = 0; \ -++ while (pclk < rate) \ -++ { \ -++ i ++; \ -++ rate >>= 1; \ -++ } \ -++ lv = i; \ -++} while(0) -++ -++/* divide rate to little than or equal to 400kHz */ -++#define __msc_calc_slow_clk_divisor(type, lv) \ -++do { \ -++ unsigned int rate, i; \ -++ rate = (type?SD_CLK:MMC_CLK)/1000/400; \ -++ i = 0; \ -++ while (rate > 0) \ -++ { \ -++ rate >>= 1; \ -++ i ++; \ -++ } \ -++ lv = i; \ -++} while(0) -++ -++ -++/*************************************************************************** -++ * SSI (Synchronous Serial Interface) -++ ***************************************************************************/ -++/* n = 0, 1 (SSI0, SSI1) */ -++#define __ssi_enable(n) ( REG_SSI_CR0(n) |= SSI_CR0_SSIE ) -++#define __ssi_disable(n) ( REG_SSI_CR0(n) &= ~SSI_CR0_SSIE ) -++#define __ssi_select_ce(n) ( REG_SSI_CR0(n) &= ~SSI_CR0_FSEL ) -++ -++#define __ssi_normal_mode(n) ( REG_SSI_ITR(n) &= ~SSI_ITR_IVLTM_MASK ) -++ -++#define __ssi_select_ce2(n) \ -++do { \ -++ REG_SSI_CR0(n) |= SSI_CR0_FSEL; \ -++ REG_SSI_CR1(n) &= ~SSI_CR1_MULTS; \ -++} while (0) -++ -++#define __ssi_select_gpc(n) \ -++do { \ -++ REG_SSI_CR0(n) &= ~SSI_CR0_FSEL; \ -++ REG_SSI_CR1(n) |= SSI_CR1_MULTS; \ -++} while (0) -++ -++#define __ssi_underrun_auto_clear(n) \ -++do { \ -++ REG_SSI_CR0(n) |= SSI_CR0_EACLRUN; \ -++} while (0) -++ -++#define __ssi_underrun_clear_manually(n) \ -++do { \ -++ REG_SSI_CR0(n) &= ~SSI_CR0_EACLRUN; \ -++} while (0) -++ -++#define __ssi_enable_tx_intr(n) \ -++ ( REG_SSI_CR0(n) |= SSI_CR0_TIE | SSI_CR0_TEIE ) -++ -++#define __ssi_disable_tx_intr(n) \ -++ ( REG_SSI_CR0(n) &= ~(SSI_CR0_TIE | SSI_CR0_TEIE) ) -++ -++#define __ssi_enable_rx_intr(n) \ -++ ( REG_SSI_CR0(n) |= SSI_CR0_RIE | SSI_CR0_REIE ) -++ -++#define __ssi_disable_rx_intr(n) \ -++ ( REG_SSI_CR0(n) &= ~(SSI_CR0_RIE | SSI_CR0_REIE) ) -++ -++#define __ssi_enable_txfifo_half_empty_intr(n) \ -++ ( REG_SSI_CR0(n) |= SSI_CR0_TIE ) -++#define __ssi_disable_txfifo_half_empty_intr(n) \ -++ ( REG_SSI_CR0(n) &= ~SSI_CR0_TIE ) -++#define __ssi_enable_tx_error_intr(n) \ -++ ( REG_SSI_CR0(n) |= SSI_CR0_TEIE ) -++#define __ssi_disable_tx_error_intr(n) \ -++ ( REG_SSI_CR0(n) &= ~SSI_CR0_TEIE ) -++#define __ssi_enable_rxfifo_half_full_intr(n) \ -++ ( REG_SSI_CR0(n) |= SSI_CR0_RIE ) -++#define __ssi_disable_rxfifo_half_full_intr(n) \ -++ ( REG_SSI_CR0(n) &= ~SSI_CR0_RIE ) -++#define __ssi_enable_rx_error_intr(n) \ -++ ( REG_SSI_CR0(n) |= SSI_CR0_REIE ) -++#define __ssi_disable_rx_error_intr(n) \ -++ ( REG_SSI_CR0(n) &= ~SSI_CR0_REIE ) -++ -++#define __ssi_enable_loopback(n) ( REG_SSI_CR0(n) |= SSI_CR0_LOOP ) -++#define __ssi_disable_loopback(n) ( REG_SSI_CR0(n) &= ~SSI_CR0_LOOP ) -++ -++#define __ssi_enable_receive(n) ( REG_SSI_CR0(n) &= ~SSI_CR0_DISREV ) -++#define __ssi_disable_receive(n) ( REG_SSI_CR0(n) |= SSI_CR0_DISREV ) -++ -++#define __ssi_finish_receive(n) \ -++ ( REG_SSI_CR0(n) |= (SSI_CR0_RFINE | SSI_CR0_RFINC) ) -++ -++#define __ssi_disable_recvfinish(n) \ -++ ( REG_SSI_CR0(n) &= ~(SSI_CR0_RFINE | SSI_CR0_RFINC) ) -++ -++#define __ssi_flush_txfifo(n) ( REG_SSI_CR0(n) |= SSI_CR0_TFLUSH ) -++#define __ssi_flush_rxfifo(n) ( REG_SSI_CR0(n) |= SSI_CR0_RFLUSH ) -++ -++#define __ssi_flush_fifo(n) \ -++ ( REG_SSI_CR0(n) |= SSI_CR0_TFLUSH | SSI_CR0_RFLUSH ) -++ -++#define __ssi_finish_transmit(n) ( REG_SSI_CR1(n) &= ~SSI_CR1_UNFIN ) -++#define __ssi_wait_transmit(n) ( REG_SSI_CR1(n) |= SSI_CR1_UNFIN ) -++#define __ssi_use_busy_wait_mode(n) __ssi_wait_transmit(n) -++#define __ssi_unset_busy_wait_mode(n) __ssi_finish_transmit(n) -++ -++#define __ssi_spi_format(n) \ -++ do { \ -++ REG_SSI_CR1(n) &= ~SSI_CR1_FMAT_MASK; \ -++ REG_SSI_CR1(n) |= SSI_CR1_FMAT_SPI; \ -++ REG_SSI_CR1(n) &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK); \ -++ REG_SSI_CR1(n) |= (SSI_CR1_TFVCK_1 | SSI_CR1_TCKFI_1); \ -++ } while (0) -++ -++/* TI's SSP format, must clear SSI_CR1.UNFIN */ -++#define __ssi_ssp_format(n) \ -++ do { \ -++ REG_SSI_CR1(n) &= ~(SSI_CR1_FMAT_MASK | SSI_CR1_UNFIN); \ -++ REG_SSI_CR1(n) |= SSI_CR1_FMAT_SSP; \ -++ } while (0) -++ -++/* National's Microwire format, must clear SSI_CR0.RFINE, and set max delay */ -++#define __ssi_microwire_format(n) \ -++ do { \ -++ REG_SSI_CR1(n) &= ~SSI_CR1_FMAT_MASK; \ -++ REG_SSI_CR1(n) |= SSI_CR1_FMAT_MW1; \ -++ REG_SSI_CR1(n) &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK); \ -++ REG_SSI_CR1(n) |= (SSI_CR1_TFVCK_3 | SSI_CR1_TCKFI_3); \ -++ REG_SSI_CR0(n) &= ~SSI_CR0_RFINE; \ -++ } while (0) -++ -++/* CE# level (FRMHL), CE# in interval time (ITFRM), -++ clock phase and polarity (PHA POL), -++ interval time (SSIITR), interval characters/frame (SSIICR) */ -++ -++/* frmhl,endian,mcom,flen,pha,pol MASK */ -++#define SSICR1_MISC_MASK \ -++ ( SSI_CR1_FRMHL_MASK | SSI_CR1_LFST | SSI_CR1_MCOM_MASK \ -++ | SSI_CR1_FLEN_MASK | SSI_CR1_PHA | SSI_CR1_POL ) -++ -++#define __ssi_spi_set_misc(n,frmhl,endian,flen,mcom,pha,pol) \ -++ do { \ -++ REG_SSI_CR1(n) &= ~SSICR1_MISC_MASK; \ -++ REG_SSI_CR1(n) |= ((frmhl) << 30) | ((endian) << 25) | \ -++ (((mcom) - 1) << 12) | (((flen) - 2) << 4) | \ -++ ((pha) << 1) | (pol); \ -++ } while(0) -++ -++/* Transfer with MSB or LSB first */ -++#define __ssi_set_msb(n) ( REG_SSI_CR1(n) &= ~SSI_CR1_LFST ) -++#define __ssi_set_lsb(n) ( REG_SSI_CR1(n) |= SSI_CR1_LFST ) -++ -++#define __ssi_set_frame_length(n, m) \ -++ REG_SSI_CR1(n) = (REG_SSI_CR1(n) & ~SSI_CR1_FLEN_MASK) | (((m) - 2) << 4) -++ -++/* m = 1 - 16 */ -++#define __ssi_set_microwire_command_length(n,m) \ -++ ( REG_SSI_CR1(n) = ((REG_SSI_CR1(n) & ~SSI_CR1_MCOM_MASK) | SSI_CR1_MCOM_##m##BIT) ) -++ -++/* Set the clock phase for SPI */ -++#define __ssi_set_spi_clock_phase(n, m) \ -++ ( REG_SSI_CR1(n) = ((REG_SSI_CR1(n) & ~SSI_CR1_PHA) | (((m)&0x1)<< 1))) -++ -++/* Set the clock polarity for SPI */ -++#define __ssi_set_spi_clock_polarity(n, p) \ -++ ( REG_SSI_CR1(n) = ((REG_SSI_CR1(n) & ~SSI_CR1_POL) | ((p)&0x1)) ) -++ -++/* SSI tx trigger, m = i x 8 */ -++#define __ssi_set_tx_trigger(n, m) \ -++ do { \ -++ REG_SSI_CR1(n) &= ~SSI_CR1_TTRG_MASK; \ -++ REG_SSI_CR1(n) |= ((m)/8)<> SSI_SR_TFIFONUM_BIT ) -++ -++#define __ssi_get_rxfifo_count(n) \ -++ ( (REG_SSI_SR(n) & SSI_SR_RFIFONUM_MASK) >> SSI_SR_RFIFONUM_BIT ) -++ -++#define __ssi_transfer_end(n) ( REG_SSI_SR(n) & SSI_SR_END ) -++#define __ssi_is_busy(n) ( REG_SSI_SR(n) & SSI_SR_BUSY ) -++ -++#define __ssi_txfifo_full(n) ( REG_SSI_SR(n) & SSI_SR_TFF ) -++#define __ssi_rxfifo_empty(n) ( REG_SSI_SR(n) & SSI_SR_RFE ) -++#define __ssi_rxfifo_half_full(n) ( REG_SSI_SR(n) & SSI_SR_RFHF ) -++#define __ssi_txfifo_half_empty(n) ( REG_SSI_SR(n) & SSI_SR_TFHE ) -++#define __ssi_underrun(n) ( REG_SSI_SR(n) & SSI_SR_UNDR ) -++#define __ssi_overrun(n) ( REG_SSI_SR(n) & SSI_SR_OVER ) -++#define __ssi_clear_underrun(n) ( REG_SSI_SR(n) = ~SSI_SR_UNDR ) -++#define __ssi_clear_overrun(n) ( REG_SSI_SR(n) = ~SSI_SR_OVER ) -++#define __ssi_clear_errors(n) ( REG_SSI_SR(n) &= ~(SSI_SR_UNDR | SSI_SR_OVER) ) -++ -++#define __ssi_set_clk(n, dev_clk, ssi_clk) \ -++ ( REG_SSI_GR(n) = (dev_clk) / (2*(ssi_clk)) - 1 ) -++ -++#define __ssi_receive_data(n) REG_SSI_DR(n) -++#define __ssi_transmit_data(n, v) (REG_SSI_DR(n) = (v)) -++ -++ -++/*************************************************************************** -++ * CIM -++ ***************************************************************************/ -++ -++#define __cim_enable() ( REG_CIM_CTRL |= CIM_CTRL_ENA ) -++#define __cim_disable() ( REG_CIM_CTRL &= ~CIM_CTRL_ENA ) -++ -++/* n = 0, 1, 2, 3 */ -++#define __cim_set_input_data_stream_order(n) \ -++ do { \ -++ REG_CIM_CFG &= CIM_CFG_ORDER_MASK; \ -++ REG_CIM_CFG |= ((n)<>CIM_SIZE_LPF_BIT) -++#define __cim_get_pixel() ((REG_CIM_SIZE&CIM_SIZE_PPL_MASK)>>CIM_SIZE_PPL_BIT) -++ -++#define __cim_set_v_offset(a) ( REG_CIM_OFFSET = (REG_CIM_OFFSET&(~CIM_OFFSET_V_MASK)) | ((a)<>CIM_OFFSET_V_BIT) -++#define __cim_get_h_offset() ((REG_CIM_OFFSET&CIM_OFFSET_H_MASK)>>CIM_OFFSET_H_BIT) -++ -++/************************************************************************* -++ * SLCD (Smart LCD Controller) -++ *************************************************************************/ -++#define __slcd_set_data_18bit() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_18BIT ) -++#define __slcd_set_data_16bit() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_16BIT ) -++#define __slcd_set_data_8bit_x3() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_8BIT_x3 ) -++#define __slcd_set_data_8bit_x2() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_8BIT_x2 ) -++#define __slcd_set_data_8bit_x1() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_8BIT_x1 ) -++#define __slcd_set_data_24bit() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_24BIT ) -++#define __slcd_set_data_9bit_x2() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_9BIT_x2 ) -++ -++#define __slcd_set_cmd_16bit() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_CWIDTH_MASK) | SLCD_CFG_CWIDTH_16BIT ) -++#define __slcd_set_cmd_8bit() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_CWIDTH_MASK) | SLCD_CFG_CWIDTH_8BIT ) -++#define __slcd_set_cmd_18bit() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_CWIDTH_MASK) | SLCD_CFG_CWIDTH_18BIT ) -++#define __slcd_set_cmd_24bit() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_CWIDTH_MASK) | SLCD_CFG_CWIDTH_24BIT ) -++ -++#define __slcd_set_cs_high() ( REG_SLCD_CFG |= SLCD_CFG_CS_ACTIVE_HIGH ) -++#define __slcd_set_cs_low() ( REG_SLCD_CFG &= ~SLCD_CFG_CS_ACTIVE_HIGH ) -++ -++#define __slcd_set_rs_high() ( REG_SLCD_CFG |= SLCD_CFG_RS_CMD_HIGH ) -++#define __slcd_set_rs_low() ( REG_SLCD_CFG &= ~SLCD_CFG_RS_CMD_HIGH ) -++ -++#define __slcd_set_clk_falling() ( REG_SLCD_CFG &= ~SLCD_CFG_CLK_ACTIVE_RISING ) -++#define __slcd_set_clk_rising() ( REG_SLCD_CFG |= SLCD_CFG_CLK_ACTIVE_RISING ) -++ -++#define __slcd_set_parallel_type() ( REG_SLCD_CFG &= ~SLCD_CFG_TYPE_SERIAL ) -++#define __slcd_set_serial_type() ( REG_SLCD_CFG |= SLCD_CFG_TYPE_SERIAL ) -++ -++/* SLCD Control Register */ -++#define __slcd_enable_dma() ( REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN ) -++#define __slcd_disable_dma() ( REG_SLCD_CTRL &= ~SLCD_CTRL_DMA_EN ) -++ -++/* SLCD Status Register */ -++#define __slcd_is_busy() ( REG_SLCD_STATE & SLCD_STATE_BUSY ) -++ -++/* SLCD Data Register */ -++#define __slcd_set_cmd_rs() ( REG_SLCD_DATA |= SLCD_DATA_RS_COMMAND) -++#define __slcd_set_data_rs() ( REG_SLCD_DATA &= ~SLCD_DATA_RS_COMMAND) -++ -++ -++/*************************************************************************** -++ * LCD -++ ***************************************************************************/ -++ -++/*************************************************************************** -++ * LCD -++ ***************************************************************************/ -++#define __lcd_as_smart_lcd() ( REG_LCD_CFG |= ( LCD_CFG_LCDPIN_SLCD | LCD_CFG_MODE_SLCD)) -++#define __lcd_as_general_lcd() ( REG_LCD_CFG &= ~( LCD_CFG_LCDPIN_SLCD | LCD_CFG_MODE_SLCD)) -++ -++#define __lcd_enable_tvepeh() ( REG_LCD_CFG |= LCD_CFG_TVEPEH ) -++#define __lcd_disable_tvepeh() ( REG_LCD_CFG &= ~LCD_CFG_TVEPEH ) -++ -++#define __lcd_enable_fuhold() ( REG_LCD_CFG |= LCD_CFG_FUHOLD ) -++#define __lcd_disable_fuhold() ( REG_LCD_CFG &= ~LCD_CFG_FUHOLD ) -++ -++#define __lcd_des_8word() ( REG_LCD_CFG |= LCD_CFG_NEWDES ) -++#define __lcd_des_4word() ( REG_LCD_CFG &= ~LCD_CFG_NEWDES ) -++ -++#define __lcd_enable_bypass_pal() ( REG_LCD_CFG |= LCD_CFG_PALBP ) -++#define __lcd_disable_bypass_pal() ( REG_LCD_CFG &= ~LCD_CFG_PALBP ) -++ -++#define __lcd_set_lcdpnl_term() ( REG_LCD_CTRL |= LCD_CFG_TVEN ) -++#define __lcd_set_tv_term() ( REG_LCD_CTRL &= ~LCD_CFG_TVEN ) -++ -++#define __lcd_enable_auto_recover() ( REG_LCD_CFG |= LCD_CFG_RECOVER ) -++#define __lcd_disable_auto_recover() ( REG_LCD_CFG &= ~LCD_CFG_RECOVER ) -++ -++#define __lcd_enable_dither() ( REG_LCD_CFG |= LCD_CFG_DITHER ) -++#define __lcd_disable_dither() ( REG_LCD_CFG &= ~LCD_CFG_DITHER ) -++ -++#define __lcd_disable_ps_mode() ( REG_LCD_CFG |= LCD_CFG_PSM ) -++#define __lcd_enable_ps_mode() ( REG_LCD_CFG &= ~LCD_CFG_PSM ) -++ -++#define __lcd_disable_cls_mode() ( REG_LCD_CFG |= LCD_CFG_CLSM ) -++#define __lcd_enable_cls_mode() ( REG_LCD_CFG &= ~LCD_CFG_CLSM ) -++ -++#define __lcd_disable_spl_mode() ( REG_LCD_CFG |= LCD_CFG_SPLM ) -++#define __lcd_enable_spl_mode() ( REG_LCD_CFG &= ~LCD_CFG_SPLM ) -++ -++#define __lcd_disable_rev_mode() ( REG_LCD_CFG |= LCD_CFG_REVM ) -++#define __lcd_enable_rev_mode() ( REG_LCD_CFG &= ~LCD_CFG_REVM ) -++ -++#define __lcd_disable_hsync_mode() ( REG_LCD_CFG |= LCD_CFG_HSYNM ) -++#define __lcd_enable_hsync_mode() ( REG_LCD_CFG &= ~LCD_CFG_HSYNM ) -++ -++#define __lcd_disable_pclk_mode() ( REG_LCD_CFG |= LCD_CFG_PCLKM ) -++#define __lcd_enable_pclk_mode() ( REG_LCD_CFG &= ~LCD_CFG_PCLKM ) -++ -++#define __lcd_normal_outdata() ( REG_LCD_CFG &= ~LCD_CFG_INVDAT ) -++#define __lcd_inverse_outdata() ( REG_LCD_CFG |= LCD_CFG_INVDAT ) -++ -++#define __lcd_sync_input() ( REG_LCD_CFG |= LCD_CFG_SYNDIR_IN ) -++#define __lcd_sync_output() ( REG_LCD_CFG &= ~LCD_CFG_SYNDIR_IN ) -++ -++#define __lcd_hsync_active_high() ( REG_LCD_CFG &= ~LCD_CFG_HSP ) -++#define __lcd_hsync_active_low() ( REG_LCD_CFG |= LCD_CFG_HSP ) -++ -++#define __lcd_pclk_rising() ( REG_LCD_CFG &= ~LCD_CFG_PCP ) -++#define __lcd_pclk_falling() ( REG_LCD_CFG |= LCD_CFG_PCP ) -++ -++#define __lcd_de_active_high() ( REG_LCD_CFG &= ~LCD_CFG_DEP ) -++#define __lcd_de_active_low() ( REG_LCD_CFG |= LCD_CFG_DEP ) -++ -++#define __lcd_vsync_rising() ( REG_LCD_CFG &= ~LCD_CFG_VSP ) -++#define __lcd_vsync_falling() ( REG_LCD_CFG |= LCD_CFG_VSP ) -++ -++#define __lcd_set_16_tftpnl() \ -++ ( REG_LCD_CFG = (REG_LCD_CFG & ~LCD_CFG_MODE_TFT_MASK) | LCD_CFG_MODE_TFT_16BIT ) -++ -++#define __lcd_set_18_tftpnl() \ -++ ( REG_LCD_CFG = (REG_LCD_CFG & ~LCD_CFG_MODE_TFT_MASK) | LCD_CFG_MODE_TFT_18BIT ) -++ -++#define __lcd_set_24_tftpnl() ( REG_LCD_CFG |= LCD_CFG_MODE_TFT_24BIT ) -++ -++/* -++ * n=1,2,4,8 for single mono-STN -++ * n=4,8 for dual mono-STN -++ */ -++#define __lcd_set_panel_datawidth(n) \ -++do { \ -++ REG_LCD_CFG &= ~LCD_CFG_PDW_MASK; \ -++ REG_LCD_CFG |= LCD_CFG_PDW_n##; \ -++} while (0) -++ -++/* m = LCD_CFG_MODE_GENERUIC_TFT_xxx */ -++#define __lcd_set_panel_mode(m) \ -++do { \ -++ REG_LCD_CFG &= ~LCD_CFG_MODE_MASK; \ -++ REG_LCD_CFG |= (m); \ -++} while(0) -++ -++/* n=4,8,16 */ -++#define __lcd_set_burst_length(n) \ -++do { \ -++ REG_LCD_CTRL &= ~LCD_CTRL_BST_MASK; \ -++ REG_LCD_CTRL |= LCD_CTRL_BST_n##; \ -++} while (0) -++ -++#define __lcd_select_rgb565() ( REG_LCD_CTRL &= ~LCD_CTRL_RGB555 ) -++#define __lcd_select_rgb555() ( REG_LCD_CTRL |= LCD_CTRL_RGB555 ) -++ -++#define __lcd_set_ofup() ( REG_LCD_CTRL |= LCD_CTRL_OFUP ) -++#define __lcd_clr_ofup() ( REG_LCD_CTRL &= ~LCD_CTRL_OFUP ) -++ -++/* n=2,4,16 */ -++#define __lcd_set_stn_frc(n) \ -++do { \ -++ REG_LCD_CTRL &= ~LCD_CTRL_FRC_MASK; \ -++ REG_LCD_CTRL |= LCD_CTRL_FRC_n##; \ -++} while (0) -++ -++#define __lcd_enable_eof_intr() ( REG_LCD_CTRL |= LCD_CTRL_EOFM ) -++#define __lcd_disable_eof_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_EOFM ) -++ -++#define __lcd_enable_sof_intr() ( REG_LCD_CTRL |= LCD_CTRL_SOFM ) -++#define __lcd_disable_sof_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_SOFM ) -++ -++#define __lcd_enable_ofu_intr() ( REG_LCD_CTRL |= LCD_CTRL_OFUM ) -++#define __lcd_disable_ofu_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_OFUM ) -++ -++#define __lcd_enable_ifu0_intr() ( REG_LCD_CTRL |= LCD_CTRL_IFUM0 ) -++#define __lcd_disable_ifu0_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_IFUM0 ) -++ -++#define __lcd_enable_ifu1_intr() ( REG_LCD_CTRL |= LCD_CTRL_IFUM1 ) -++#define __lcd_disable_ifu1_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_IFUM1 ) -++ -++#define __lcd_enable_ldd_intr() ( REG_LCD_CTRL |= LCD_CTRL_LDDM ) -++#define __lcd_disable_ldd_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_LDDM ) -++ -++#define __lcd_enable_qd_intr() ( REG_LCD_CTRL |= LCD_CTRL_QDM ) -++#define __lcd_disable_qd_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_QDM ) -++ -++#define __lcd_reverse_byte_endian() ( REG_LCD_CTRL |= LCD_CTRL_BEDN ) -++#define __lcd_normal_byte_endian() ( REG_LCD_CTRL &= ~LCD_CTRL_BEDN ) -++ -++#define __lcd_pixel_endian_little() ( REG_LCD_CTRL |= LCD_CTRL_PEDN ) -++#define __lcd_pixel_endian_big() ( REG_LCD_CTRL &= ~LCD_CTRL_PEDN ) -++ -++#define __lcd_set_dis() ( REG_LCD_CTRL |= LCD_CTRL_DIS ) -++#define __lcd_clr_dis() ( REG_LCD_CTRL &= ~LCD_CTRL_DIS ) -++ -++#define __lcd_set_ena() ( REG_LCD_CTRL |= LCD_CTRL_ENA ) -++#define __lcd_clr_ena() ( REG_LCD_CTRL &= ~LCD_CTRL_ENA ) -++ -++/* n=1,2,4,8,16 */ -++#define __lcd_set_bpp(n) \ -++ ( REG_LCD_CTRL = (REG_LCD_CTRL & ~LCD_CTRL_BPP_MASK) | LCD_CTRL_BPP_##n ) -++ -++/* LCD status register indication */ -++ -++#define __lcd_quick_disable_done() ( REG_LCD_STATE & LCD_STATE_QD ) -++#define __lcd_disable_done() ( REG_LCD_STATE & LCD_STATE_LDD ) -++#define __lcd_infifo0_underrun() ( REG_LCD_STATE & LCD_STATE_IFU0 ) -++#define __lcd_infifo1_underrun() ( REG_LCD_STATE & LCD_STATE_IFU1 ) -++#define __lcd_outfifo_underrun() ( REG_LCD_STATE & LCD_STATE_OFU ) -++#define __lcd_start_of_frame() ( REG_LCD_STATE & LCD_STATE_SOF ) -++#define __lcd_end_of_frame() ( REG_LCD_STATE & LCD_STATE_EOF ) -++ -++#define __lcd_clr_outfifounderrun() ( REG_LCD_STATE &= ~LCD_STATE_OFU ) -++#define __lcd_clr_sof() ( REG_LCD_STATE &= ~LCD_STATE_SOF ) -++#define __lcd_clr_eof() ( REG_LCD_STATE &= ~LCD_STATE_EOF ) -++ -++/* OSD functions */ -++#define __lcd_enable_osd() (REG_LCD_OSDC |= LCD_OSDC_OSDEN) -++#define __lcd_enable_f0() (REG_LCD_OSDC |= LCD_OSDC_F0EN) -++#define __lcd_enable_f1() (REG_LCD_OSDC |= LCD_OSDC_F1EN) -++#define __lcd_enable_alpha() (REG_LCD_OSDC |= LCD_OSDC_ALPHAEN) -++#define __lcd_enable_alphamd() (REG_LCD_OSDC |= LCD_OSDC_ALPHAMD) -++ -++#define __lcd_disable_osd() (REG_LCD_OSDC &= ~LCD_OSDC_OSDEN) -++#define __lcd_disable_f0() (REG_LCD_OSDC &= ~LCD_OSDC_F0EN) -++#define __lcd_disable_f1() (REG_LCD_OSDC &= ~LCD_OSDC_F1EN) -++#define __lcd_disable_alpha() (REG_LCD_OSDC &= ~LCD_OSDC_ALPHAEN) -++#define __lcd_disable_alphamd() (REG_LCD_OSDC &= ~LCD_OSDC_ALPHAMD) -++ -++/* OSD Controll Register */ -++#define __lcd_fg1_use_ipu() (REG_LCD_OSDCTRL |= LCD_OSDCTRL_IPU) -++#define __lcd_fg1_use_dma_chan1() (REG_LCD_OSDCTRL &= ~LCD_OSDCTRL_IPU) -++#define __lcd_fg1_unuse_ipu() __lcd_fg1_use_dma_chan1() -++#define __lcd_osd_rgb555_mode() ( REG_LCD_OSDCTRL |= LCD_OSDCTRL_RGB555 ) -++#define __lcd_osd_rgb565_mode() ( REG_LCD_OSDCTRL &= ~LCD_OSDCTRL_RGB555 ) -++#define __lcd_osd_change_size() ( REG_LCD_OSDCTRL |= LCD_OSDCTRL_CHANGES ) -++#define __lcd_osd_bpp_15_16() \ -++ ( REG_LCD_OSDCTRL = (REG_LCD_OSDCTRL & ~LCD_OSDCTRL_OSDBPP_MASK) | LCD_OSDCTRL_OSDBPP_15_16 ) -++#define __lcd_osd_bpp_18_24() \ -++ ( REG_LCD_OSDCTRL = (REG_LCD_OSDCTRL & ~LCD_OSDCTRL_OSDBPP_MASK) | LCD_OSDCTRL_OSDBPP_18_24 ) -++ -++/* OSD State Register */ -++#define __lcd_start_of_fg1() ( REG_LCD_STATE & LCD_OSDS_SOF1 ) -++#define __lcd_end_of_fg1() ( REG_LCD_STATE & LCD_OSDS_EOF1 ) -++#define __lcd_start_of_fg0() ( REG_LCD_STATE & LCD_OSDS_SOF0 ) -++#define __lcd_end_of_fg0() ( REG_LCD_STATE & LCD_OSDS_EOF0 ) -++#define __lcd_change_is_rdy() ( REG_LCD_STATE & LCD_OSDS_READY ) -++ -++/* Foreground Color Key Register 0,1(foreground 0, foreground 1) */ -++#define __lcd_enable_colorkey0() (REG_LCD_KEY0 |= LCD_KEY_KEYEN) -++#define __lcd_enable_colorkey1() (REG_LCD_KEY1 |= LCD_KEY_KEYEN) -++#define __lcd_enable_colorkey0_md() (REG_LCD_KEY0 |= LCD_KEY_KEYMD) -++#define __lcd_enable_colorkey1_md() (REG_LCD_KEY1 |= LCD_KEY_KEYMD) -++#define __lcd_set_colorkey0(key) (REG_LCD_KEY0 = (REG_LCD_KEY0&~0xFFFFFF)|(key)) -++#define __lcd_set_colorkey1(key) (REG_LCD_KEY1 = (REG_LCD_KEY1&~0xFFFFFF)|(key)) -++ -++#define __lcd_disable_colorkey0() (REG_LCD_KEY0 &= ~LCD_KEY_KEYEN) -++#define __lcd_disable_colorkey1() (REG_LCD_KEY1 &= ~LCD_KEY_KEYEN) -++#define __lcd_disable_colorkey0_md() (REG_LCD_KEY0 &= ~LCD_KEY_KEYMD) -++#define __lcd_disable_colorkey1_md() (REG_LCD_KEY1 &= ~LCD_KEY_KEYMD) -++ -++/* IPU Restart Register */ -++#define __lcd_enable_ipu_restart() (REG_LCD_IPUR |= LCD_IPUR_IPUREN) -++#define __lcd_disable_ipu_restart() (REG_LCD_IPUR &= ~LCD_IPUR_IPUREN) -++#define __lcd_set_ipu_restart_triger(n) (REG_LCD_IPUR = (REG_LCD_IPUR&(~0xFFFFFF))|(n)) -++ -++/* RGB Control Register */ -++#define __lcd_enable_rgb_dummy() (REG_LCD_RGBC |= LCD_RGBC_RGBDM) -++#define __lcd_disable_rgb_dummy() (REG_LCD_RGBC &= ~LCD_RGBC_RGBDM) -++ -++#define __lcd_dummy_rgb() (REG_LCD_RGBC |= LCD_RGBC_DMM) -++#define __lcd_rgb_dummy() (REG_LCD_RGBC &= ~LCD_RGBC_DMM) -++ -++#define __lcd_rgb2ycc() (REG_LCD_RGBC |= LCD_RGBC_YCC) -++#define __lcd_notrgb2ycc() (REG_LCD_RGBC &= ~LCD_RGBC_YCC) -++ -++#define __lcd_odd_mode_rgb() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_RGB ) -++#define __lcd_odd_mode_rbg() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_RBG ) -++#define __lcd_odd_mode_grb() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_GRB) -++ -++#define __lcd_odd_mode_gbr() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_GBR) -++#define __lcd_odd_mode_brg() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_BRG) -++#define __lcd_odd_mode_bgr() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_BGR) -++ -++#define __lcd_even_mode_rgb() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_RGB ) -++#define __lcd_even_mode_rbg() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_RBG ) -++#define __lcd_even_mode_grb() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_GRB) -++ -++#define __lcd_even_mode_gbr() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_GBR) -++#define __lcd_even_mode_brg() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_BRG) -++#define __lcd_even_mode_bgr() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_BGR) -++ -++/* Vertical Synchronize Register */ -++#define __lcd_vsync_get_vps() \ -++ ( (REG_LCD_VSYNC & LCD_VSYNC_VPS_MASK) >> LCD_VSYNC_VPS_BIT ) -++ -++#define __lcd_vsync_get_vpe() \ -++ ( (REG_LCD_VSYNC & LCD_VSYNC_VPE_MASK) >> LCD_VSYNC_VPE_BIT ) -++#define __lcd_vsync_set_vpe(n) \ -++do { \ -++ REG_LCD_VSYNC &= ~LCD_VSYNC_VPE_MASK; \ -++ REG_LCD_VSYNC |= (n) << LCD_VSYNC_VPE_BIT; \ -++} while (0) -++ -++#define __lcd_hsync_get_hps() \ -++ ( (REG_LCD_HSYNC & LCD_HSYNC_HPS_MASK) >> LCD_HSYNC_HPS_BIT ) -++#define __lcd_hsync_set_hps(n) \ -++do { \ -++ REG_LCD_HSYNC &= ~LCD_HSYNC_HPS_MASK; \ -++ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPS_BIT; \ -++} while (0) -++ -++#define __lcd_hsync_get_hpe() \ -++ ( (REG_LCD_HSYNC & LCD_HSYNC_HPE_MASK) >> LCD_VSYNC_HPE_BIT ) -++#define __lcd_hsync_set_hpe(n) \ -++do { \ -++ REG_LCD_HSYNC &= ~LCD_HSYNC_HPE_MASK; \ -++ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPE_BIT; \ -++} while (0) -++ -++#define __lcd_vat_get_ht() \ -++ ( (REG_LCD_VAT & LCD_VAT_HT_MASK) >> LCD_VAT_HT_BIT ) -++#define __lcd_vat_set_ht(n) \ -++do { \ -++ REG_LCD_VAT &= ~LCD_VAT_HT_MASK; \ -++ REG_LCD_VAT |= (n) << LCD_VAT_HT_BIT; \ -++} while (0) -++ -++#define __lcd_vat_get_vt() \ -++ ( (REG_LCD_VAT & LCD_VAT_VT_MASK) >> LCD_VAT_VT_BIT ) -++#define __lcd_vat_set_vt(n) \ -++do { \ -++ REG_LCD_VAT &= ~LCD_VAT_VT_MASK; \ -++ REG_LCD_VAT |= (n) << LCD_VAT_VT_BIT; \ -++} while (0) -++ -++#define __lcd_dah_get_hds() \ -++ ( (REG_LCD_DAH & LCD_DAH_HDS_MASK) >> LCD_DAH_HDS_BIT ) -++#define __lcd_dah_set_hds(n) \ -++do { \ -++ REG_LCD_DAH &= ~LCD_DAH_HDS_MASK; \ -++ REG_LCD_DAH |= (n) << LCD_DAH_HDS_BIT; \ -++} while (0) -++ -++#define __lcd_dah_get_hde() \ -++ ( (REG_LCD_DAH & LCD_DAH_HDE_MASK) >> LCD_DAH_HDE_BIT ) -++#define __lcd_dah_set_hde(n) \ -++do { \ -++ REG_LCD_DAH &= ~LCD_DAH_HDE_MASK; \ -++ REG_LCD_DAH |= (n) << LCD_DAH_HDE_BIT; \ -++} while (0) -++ -++#define __lcd_dav_get_vds() \ -++ ( (REG_LCD_DAV & LCD_DAV_VDS_MASK) >> LCD_DAV_VDS_BIT ) -++#define __lcd_dav_set_vds(n) \ -++do { \ -++ REG_LCD_DAV &= ~LCD_DAV_VDS_MASK; \ -++ REG_LCD_DAV |= (n) << LCD_DAV_VDS_BIT; \ -++} while (0) -++ -++#define __lcd_dav_get_vde() \ -++ ( (REG_LCD_DAV & LCD_DAV_VDE_MASK) >> LCD_DAV_VDE_BIT ) -++#define __lcd_dav_set_vde(n) \ -++do { \ -++ REG_LCD_DAV &= ~LCD_DAV_VDE_MASK; \ -++ REG_LCD_DAV |= (n) << LCD_DAV_VDE_BIT; \ -++} while (0) -++ -++/* DMA Command Register */ -++#define __lcd_cmd0_set_sofint() ( REG_LCD_CMD0 |= LCD_CMD_SOFINT ) -++#define __lcd_cmd0_clr_sofint() ( REG_LCD_CMD0 &= ~LCD_CMD_SOFINT ) -++#define __lcd_cmd1_set_sofint() ( REG_LCD_CMD1 |= LCD_CMD_SOFINT ) -++#define __lcd_cmd1_clr_sofint() ( REG_LCD_CMD1 &= ~LCD_CMD_SOFINT ) -++ -++#define __lcd_cmd0_set_eofint() ( REG_LCD_CMD0 |= LCD_CMD_EOFINT ) -++#define __lcd_cmd0_clr_eofint() ( REG_LCD_CMD0 &= ~LCD_CMD_EOFINT ) -++#define __lcd_cmd1_set_eofint() ( REG_LCD_CMD1 |= LCD_CMD_EOFINT ) -++#define __lcd_cmd1_clr_eofint() ( REG_LCD_CMD1 &= ~LCD_CMD_EOFINT ) -++ -++#define __lcd_cmd0_set_pal() ( REG_LCD_CMD0 |= LCD_CMD_PAL ) -++#define __lcd_cmd0_clr_pal() ( REG_LCD_CMD0 &= ~LCD_CMD_PAL ) -++ -++#define __lcd_cmd0_get_len() \ -++ ( (REG_LCD_CMD0 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) -++#define __lcd_cmd1_get_len() \ -++ ( (REG_LCD_CMD1 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) -++ -++/************************************************************************* -++ * TVE (TV Encoder Controller) ops -++ *************************************************************************/ -++/* TV Encoder Control register ops */ -++#define __tve_soft_reset() (REG_TVE_CTRL |= TVE_CTRL_SWRST) -++ -++#define __tve_output_colorbar() (REG_TVE_CTRL |= TVE_CTRL_CLBAR) -++#define __tve_output_video() (REG_TVE_CTRL &= ~TVE_CTRL_CLBAR) -++ -++#define __tve_input_cr_first() (REG_TVE_CTRL |= TVE_CTRL_CR1ST) -++#define __tve_input_cb_first() (REG_TVE_CTRL &= ~TVE_CTRL_CR1ST) -++ -++#define __tve_set_0_as_black() (REG_TVE_CTRL |= TVE_CTRL_ZBLACK) -++#define __tve_set_16_as_black() (REG_TVE_CTRL &= ~TVE_CTRL_ZBLACK) -++ -++#define __tve_ena_invert_top_bottom() (REG_TVE_CTRL |= TVE_CTRL_FINV) -++#define __tve_dis_invert_top_bottom() (REG_TVE_CTRL &= ~TVE_CTRL_FINV) -++ -++#define __tve_set_pal_mode() (REG_TVE_CTRL |= TVE_CTRL_PAL) -++#define __tve_set_ntsc_mode() (REG_TVE_CTRL &= ~TVE_CTRL_PAL) -++ -++#define __tve_set_pal_dura() (REG_TVE_CTRL |= TVE_CTRL_SYNCT) -++#define __tve_set_ntsc_dura() (REG_TVE_CTRL &= ~TVE_CTRL_SYNCT) -++ -++/* n = 0 ~ 3 */ -++#define __tve_set_c_bandwidth(n) \ -++do {\ -++ REG_TVE_CTRL &= ~TVE_CTRL_CBW_MASK;\ -++ REG_TVE_CTRL |= (n) << TVE_CTRL_CBW_BIT; \ -++}while(0) -++ -++/* n = 0 ~ 3 */ -++#define __tve_set_c_gain(n) \ -++do {\ -++ REG_TVE_CTRL &= ~TVE_CTRL_CGAIN_MASK;\ -++ (REG_TVE_CTRL |= (n) << TVE_CTRL_CGAIN_BIT; \ -++}while(0) -++ -++/* n = 0 ~ 7 */ -++#define __tve_set_yc_delay(n) \ -++do { \ -++ REG_TVE_CTRL &= ~TVE_CTRL_YCDLY_MASK \ -++ REG_TVE_CTRL |= ((n) << TVE_CTRL_YCDLY_BIT); \ -++} while(0) -++ -++#define __tve_disable_all_dacs() (REG_TVE_CTRL |= TVE_CTRL_DAPD) -++#define __tve_disable_dac1() (REG_TVE_CTRL |= TVE_CTRL_DAPD1) -++#define __tve_enable_dac1() (REG_TVE_CTRL &= ~TVE_CTRL_DAPD1) -++#define __tve_disable_dac2() (REG_TVE_CTRL |= TVE_CTRL_DAPD2) -++#define __tve_enable_dac2() (REG_TVE_CTRL &= ~TVE_CTRL_DAPD2) -++#define __tve_disable_dac3() (REG_TVE_CTRL |= TVE_CTRL_DAPD3) -++#define __tve_enable_dac3() (REG_TVE_CTRL &= ~TVE_CTRL_DAPD3) -++ -++#define __tve_enable_svideo_fmt() (REG_TVE_CTRL |= TVE_CTRL_ECVBS) -++#define __tve_enable_cvbs_fmt() (REG_TVE_CTRL &= ~TVE_CTRL_ECVBS) -++ -++/* TV Encoder Frame Configure register ops */ -++/* n = 0 ~ 255 */ -++#define __tve_set_first_video_line(n) \ -++do {\ -++ REG_TVE_FRCFG &= ~TVE_FRCFG_L1ST_MASK;\ -++ REG_TVE_FRCFG |= (n) << TVE_FRCFG_L1ST_BIT;\ -++} while(0) -++/* n = 0 ~ 1023 */ -++#define __tve_set_line_num_per_frm(n) \ -++do {\ -++ REG_TVE_FRCFG &= ~TVE_FRCFG_NLINE_MASK;\ -++ REG_TVE_CFG |= (n) << TVE_FRCFG_NLINE_BIT;\ -++} while(0) -++#define __tve_get_video_line_num()\ -++ (((REG_TVE_FRCFG & TVE_FRCFG_NLINE_MASK) >> TVE_FRCFG_NLINE_BIT) - 1 - 2 * ((REG_TVE_FRCFG & TVE_FRCFG_L1ST_MASK) >> TVE_FRCFG_L1ST_BIT)) -++ -++/* TV Encoder Signal Level Configure register ops */ -++/* n = 0 ~ 1023 */ -++#define __tve_set_white_level(n) \ -++do {\ -++ REG_TVE_SLCFG1 &= ~TVE_SLCFG1_WHITEL_MASK;\ -++ REG_TVE_SLCFG1 |= (n) << TVE_SLCFG1_WHITEL_BIT;\ -++} while(0) -++/* n = 0 ~ 1023 */ -++#define __tve_set_black_level(n) \ -++do {\ -++ REG_TVE_SLCFG1 &= ~TVE_SLCFG1_BLACKL_MASK;\ -++ REG_TVE_SLCFG1 |= (n) << TVE_SLCFG1_BLACKL_BIT;\ -++} while(0) -++/* n = 0 ~ 1023 */ -++#define __tve_set_blank_level(n) \ -++do {\ -++ REG_TVE_SLCFG2 &= ~TVE_SLCFG2_BLANKL_MASK;\ -++ REG_TVE_SLCFG2 |= (n) << TVE_SLCFG2_BLANKL_BIT;\ -++} while(0) -++/* n = 0 ~ 1023 */ -++#define __tve_set_vbi_blank_level(n) \ -++do {\ -++ REG_TVE_SLCFG2 &= ~TVE_SLCFG2_VBLANKL_MASK;\ -++ REG_TVE_SLCFG2 |= (n) << TVE_SLCFG2_VBLANKL_BIT;\ -++} while(0) -++/* n = 0 ~ 1023 */ -++#define __tve_set_sync_level(n) \ -++do {\ -++ REG_TVE_SLCFG3 &= ~TVE_SLCFG3_SYNCL_MASK;\ -++ REG_TVE_SLCFG3 |= (n) << TVE_SLCFG3_SYNCL_BIT;\ -++} while(0) -++ -++/* TV Encoder Signal Level Configure register ops */ -++/* n = 0 ~ 31 */ -++#define __tve_set_front_porch(n) \ -++do {\ -++ REG_TVE_LTCFG1 &= ~TVE_LTCFG1_FRONTP_MASK;\ -++ REG_TVE_LTCFG1 |= (n) << TVE_LTCFG1_FRONTP_BIT; \ -++} while(0) -++/* n = 0 ~ 127 */ -++#define __tve_set_hsync_width(n) \ -++do {\ -++ REG_TVE_LTCFG1 &= ~TVE_LTCFG1_HSYNCW_MASK;\ -++ REG_TVE_LTCFG1 |= (n) << TVE_LTCFG1_HSYNCW_BIT; \ -++} while(0) -++/* n = 0 ~ 127 */ -++#define __tve_set_back_porch(n) \ -++do {\ -++ REG_TVE_LTCFG1 &= ~TVE_LTCFG1_BACKP_MASK;\ -++ REG_TVE_LTCFG1 |= (n) << TVE_LTCFG1_BACKP_BIT; \ -++} while(0) -++/* n = 0 ~ 2047 */ -++#define __tve_set_active_linec(n) \ -++do {\ -++ REG_TVE_LTCFG2 &= ~TVE_LTCFG2_ACTLIN_MASK;\ -++ REG_TVE_LTCFG2 |= (n) << TVE_LTCFG2_ACTLIN_BIT; \ -++} while(0) -++/* n = 0 ~ 31 */ -++#define __tve_set_breezy_way(n) \ -++do {\ -++ REG_TVE_LTCFG2 &= ~TVE_LTCFG2_PREBW_MASK;\ -++ REG_TVE_LTCFG2 |= (n) << TVE_LTCFG2_PREBW_BIT; \ -++} while(0) -++ -++/* n = 0 ~ 127 */ -++#define __tve_set_burst_width(n) \ -++do {\ -++ REG_TVE_LTCFG2 &= ~TVE_LTCFG2_BURSTW_MASK;\ -++ REG_TVE_LTCFG2 |= (n) << TVE_LTCFG2_BURSTW_BIT; \ -++} while(0) -++ -++/* TV Encoder Chrominance filter and Modulation register ops */ -++/* n = 0 ~ (2^32-1) */ -++#define __tve_set_c_sub_carrier_freq(n) REG_TVE_CFREQ = (n) -++/* n = 0 ~ 255 */ -++#define __tve_set_c_sub_carrier_init_phase(n) \ -++do { \ -++ REG_TVE_CPHASE &= ~TVE_CPHASE_INITPH_MASK; \ -++ REG_TVE_CPHASE |= (n) << TVE_CPHASE_INITPH_BIT; \ -++} while(0) -++/* n = 0 ~ 255 */ -++#define __tve_set_c_sub_carrier_act_phase(n) \ -++do { \ -++ REG_TVE_CPHASE &= ~TVE_CPHASE_ACTPH_MASK; \ -++ REG_TVE_CPHASE |= (n) << TVE_CPHASE_ACTPH_BIT; \ -++} while(0) -++/* n = 0 ~ 255 */ -++#define __tve_set_c_phase_rst_period(n) \ -++do { \ -++ REG_TVE_CPHASE &= ~TVE_CPHASE_CCRSTP_MASK; \ -++ REG_TVE_CPHASE |= (n) << TVE_CPHASE_CCRSTP_BIT; \ -++} while(0) -++/* n = 0 ~ 255 */ -++#define __tve_set_cb_burst_amp(n) \ -++do { \ -++ REG_TVE_CBCRCFG &= ~TVE_CBCRCFG_CBBA_MASK; \ -++ REG_TVE_CBCRCFG |= (n) << TVE_CBCRCFG_CBBA_BIT; \ -++} while(0) -++/* n = 0 ~ 255 */ -++#define __tve_set_cr_burst_amp(n) \ -++do { \ -++ REG_TVE_CBCRCFG &= ~TVE_CBCRCFG_CRBA_MASK; \ -++ REG_TVE_CBCRCFG |= (n) << TVE_CBCRCFG_CRBA_BIT; \ -++} while(0) -++/* n = 0 ~ 255 */ -++#define __tve_set_cb_gain_amp(n) \ -++do { \ -++ REG_TVE_CBCRCFG &= ~TVE_CBCRCFG_CBGAIN_MASK; \ -++ REG_TVE_CBCRCFG |= (n) << TVE_CBCRCFG_CBGAIN_BIT; \ -++} while(0) -++/* n = 0 ~ 255 */ -++#define __tve_set_cr_gain_amp(n) \ -++do { \ -++ REG_TVE_CBCRCFG &= ~TVE_CBCRCFG_CRGAIN_MASK; \ -++ REG_TVE_CBCRCFG |= (n) << TVE_CBCRCFG_CRGAIN_BIT; \ -++} while(0) -++ -++/* TV Encoder Wide Screen Signal Control register ops */ -++/* n = 0 ~ 7 */ -++#define __tve_set_notch_freq(n) \ -++do { \ -++ REG_TVE_WSSCR &= ~TVE_WSSCR_NCHFREQ_MASK; \ -++ REG_TVE_WSSCR |= (n) << TVE_WSSCR_NCHFREQ_BIT; \ -++} while(0) -++/* n = 0 ~ 7 */ -++#define __tve_set_notch_width() (REG_TVE_WSSCR |= TVE_WSSCR_NCHW_BIT) -++#define __tve_clear_notch_width() (REG_TVE_WSSCR &= ~TVE_WSSCR_NCHW_BIT) -++#define __tve_enable_notch() (REG_TVE_WSSCR |= TVE_WSSCR_ENCH_BIT) -++#define __tve_disable_notch() (REG_TVE_WSSCR &= ~TVE_WSSCR_ENCH_BIT) -++/* n = 0 ~ 7 */ -++#define __tve_set_wss_edge(n) \ -++do { \ -++ REG_TVE_WSSCR &= ~TVE_WSSCR_WSSEDGE_MASK; \ -++ REG_TVE_WSSCR |= (n) << TVE_WSSCR_WSSEDGE_BIT; \ -++} while(0) -++#define __tve_set_wss_clkbyp() (REG_TVE_WSSCR |= TVE_WSSCR_WSSCKBP_BIT) -++#define __tve_set_wss_type() (REG_TVE_WSSCR |= TVE_WSSCR_WSSTP_BIT) -++#define __tve_enable_wssf1() (REG_TVE_WSSCR |= TVE_WSSCR_EWSS1_BIT) -++#define __tve_enable_wssf0() (REG_TVE_WSSCR |= TVE_WSSCR_EWSS0_BIT) -++ -++/* TV Encoder Wide Screen Signal Configure register 1, 2 and 3 ops */ -++/* n = 0 ~ 1023 */ -++#define __tve_set_wss_level(n) \ -++do { \ -++ REG_TVE_WSSCFG1 &= ~TVE_WSSCFG1_WSSL_MASK; \ -++ REG_TVE_WSSCFG1 |= (n) << TVE_WSSCFG1_WSSL_BIT; \ -++} while(0) -++/* n = 0 ~ 4095 */ -++#define __tve_set_wss_freq(n) \ -++do { \ -++ REG_TVE_WSSCFG1 &= ~TVE_WSSCFG1_WSSFREQ_MASK; \ -++ REG_TVE_WSSCFG1 |= (n) << TVE_WSSCFG1_WSSFREQ_BIT; \ -++} while(0) -++/* n = 0, 1; l = 0 ~ 255 */ -++#define __tve_set_wss_line(n,v) \ -++do { \ -++ REG_TVE_WSSCFG##n &= ~TVE_WSSCFG_WSSLINE_MASK; \ -++ REG_TVE_WSSCFG##n |= (v) << TVE_WSSCFG_WSSLINE_BIT; \ -++} while(0) -++/* n = 0, 1; d = 0 ~ (2^20-1) */ -++#define __tve_set_wss_data(n, v) \ -++do { \ -++ REG_TVE_WSSCFG##n &= ~TVE_WSSCFG_WSSLINE_MASK; \ -++ REG_TVE_WSSCFG##n |= (v) << TVE_WSSCFG_WSSLINE_BIT; \ -++} while(0) -++ -++/*************************************************************************** -++ * RTC ops -++ ***************************************************************************/ -++ -++#define __rtc_write_ready() ( (REG_RTC_RCR & RTC_RCR_WRDY) >> RTC_RCR_WRDY_BIT ) -++#define __rtc_enabled() ( REG_RTC_RCR |= RTC_RCR_RTCE ) -++#define __rtc_disabled() ( REG_RTC_RCR &= ~RTC_RCR_RTCE ) -++#define __rtc_enable_alarm() ( REG_RTC_RCR |= RTC_RCR_AE ) -++#define __rtc_disable_alarm() ( REG_RTC_RCR &= ~RTC_RCR_AE ) -++#define __rtc_enable_alarm_irq() ( REG_RTC_RCR |= RTC_RCR_AIE ) -++#define __rtc_disable_alarm_irq() ( REG_RTC_RCR &= ~RTC_RCR_AIE ) -++#define __rtc_enable_1Hz_irq() ( REG_RTC_RCR |= RTC_RCR_1HZIE ) -++#define __rtc_disable_1Hz_irq() ( REG_RTC_RCR &= ~RTC_RCR_1HZIE ) -++ -++#define __rtc_get_1Hz_flag() ( (REG_RTC_RCR >> RTC_RCR_1HZ_BIT) & 0x1 ) -++#define __rtc_clear_1Hz_flag() ( REG_RTC_RCR &= ~RTC_RCR_1HZ ) -++#define __rtc_get_alarm_flag() ( (REG_RTC_RCR >> RTC_RCR_AF_BIT) & 0x1 ) -++#define __rtc_clear_alarm_flag() ( REG_RTC_RCR &= ~RTC_RCR_AF ) -++ -++#define __rtc_get_second() ( REG_RTC_RSR ) -++#define __rtc_set_second(v) ( REG_RTC_RSR = v ) -++ -++#define __rtc_get_alarm_second() ( REG_RTC_RSAR ) -++#define __rtc_set_alarm_second(v) ( REG_RTC_RSAR = v ) -++ -++#define __rtc_RGR_is_locked() ( (REG_RTC_RGR >> RTC_RGR_LOCK) ) -++#define __rtc_lock_RGR() ( REG_RTC_RGR |= RTC_RGR_LOCK ) -++#define __rtc_unlock_RGR() ( REG_RTC_RGR &= ~RTC_RGR_LOCK ) -++#define __rtc_get_adjc_val() ( (REG_RTC_RGR & RTC_RGR_ADJC_MASK) >> RTC_RGR_ADJC_BIT ) -++#define __rtc_set_adjc_val(v) \ -++ ( REG_RTC_RGR = ( (REG_RTC_RGR & ~RTC_RGR_ADJC_MASK) | (v << RTC_RGR_ADJC_BIT) )) -++#define __rtc_get_nc1Hz_val() ( (REG_RTC_RGR & RTC_RGR_NC1HZ_MASK) >> RTC_RGR_NC1HZ_BIT ) -++#define __rtc_set_nc1Hz_val(v) \ -++ ( REG_RTC_RGR = ( (REG_RTC_RGR & ~RTC_RGR_NC1HZ_MASK) | (v << RTC_RGR_NC1HZ_BIT) )) -++ -++#define __rtc_power_down() ( REG_RTC_HCR |= RTC_HCR_PD ) -++ -++#define __rtc_get_hwfcr_val() ( REG_RTC_HWFCR & RTC_HWFCR_MASK ) -++#define __rtc_set_hwfcr_val(v) ( REG_RTC_HWFCR = (v) & RTC_HWFCR_MASK ) -++#define __rtc_get_hrcr_val() ( REG_RTC_HRCR & RTC_HRCR_MASK ) -++#define __rtc_set_hrcr_val(v) ( REG_RTC_HRCR = (v) & RTC_HRCR_MASK ) -++ -++#define __rtc_enable_alarm_wakeup() ( REG_RTC_HWCR |= RTC_HWCR_EALM ) -++#define __rtc_disable_alarm_wakeup() ( REG_RTC_HWCR &= ~RTC_HWCR_EALM ) -++ -++#define __rtc_status_hib_reset_occur() ( (REG_RTC_HWRSR >> RTC_HWRSR_HR) & 0x1 ) -++#define __rtc_status_ppr_reset_occur() ( (REG_RTC_HWRSR >> RTC_HWRSR_PPR) & 0x1 ) -++#define __rtc_status_wakeup_pin_waken_up() ( (REG_RTC_HWRSR >> RTC_HWRSR_PIN) & 0x1 ) -++#define __rtc_status_alarm_waken_up() ( (REG_RTC_HWRSR >> RTC_HWRSR_ALM) & 0x1 ) -++#define __rtc_clear_hib_stat_all() ( REG_RTC_HWRSR = 0 ) -++ -++#define __rtc_get_scratch_pattern() (REG_RTC_HSPR) -++#define __rtc_set_scratch_pattern(n) (REG_RTC_HSPR = n ) -++ -++/************************************************************************* -++ * BCH -++ *************************************************************************/ -++#define __ecc_encoding_4bit() \ -++do { \ -++ REG_BCH_CRS = BCH_CR_ENCE | BCH_CR_BRST | BCH_CR_BCHE; \ -++ REG_BCH_CRC = BCH_CR_BSEL8; \ -++} while(0) -++#define __ecc_decoding_4bit() \ -++do { \ -++ REG_BCH_CRS = BCH_CR_BRST | BCH_CR_BCHE; \ -++ REG_BCH_CRC = BCH_CR_ENCE | BCH_CR_BSEL8; \ -++} while(0) -++#define __ecc_encoding_8bit() \ -++do { \ -++ REG_BCH_CRS = BCH_CR_ENCE | BCH_CR_BRST | BCH_CR_BSEL8 | BCH_CR_BCHE; \ -++} while(0) -++#define __ecc_decoding_8bit() \ -++do { \ -++ REG_BCH_CRS = BCH_CR_BRST | BCH_CR_BSEL8 | BCH_CR_BCHE; \ -++ REG_BCH_CRC = BCH_CR_ENCE; \ -++} while(0) -++#define __ecc_dma_enable() ( REG_BCH_CRS = BCH_CR_DMAE ) -++#define __ecc_disable() ( REG_BCH_CRC = BCH_CR_BCHE ) -++#define __ecc_encode_sync() while (!(REG_BCH_INTS & BCH_INTS_ENCF)) -++#define __ecc_decode_sync() while (!(REG_BCH_INTS & BCH_INTS_DECF)) -++#define __ecc_cnt_dec(n) \ -++do { \ -++ REG_BCH_CNT &= ~(BCH_CNT_DEC_MASK << BCH_CNT_DEC_BIT); \ -++ REG_BCH_CNT = (n) << BCH_CNT_DEC_BIT; \ -++} while(0) -++#define __ecc_cnt_enc(n) \ -++do { \ -++ REG_BCH_CNT &= ~(BCH_CNT_ENC_MASK << BCH_CNT_ENC_BIT); \ -++ REG_BCH_CNT = (n) << BCH_CNT_ENC_BIT; \ -++} while(0) -++ -++/*************************************************************************** -++ * OWI (one-wire bus) ops -++ ***************************************************************************/ -++ -++/* OW control register ops */ -++#define __owi_enable_all_interrupts() ( REG_OWI_CTL = (OWI_CTL_EBYTE | OWI_CTL_EBIT | OWI_CTL_ERST) ) -++#define __owi_disable_all_interrupts() ( REG_OWI_CTL = 0 ) -++ -++#define __owi_enable_byte_interrupt() ( REG_OWI_CTL |= OWI_CTL_EBYTE ) -++#define __owi_disable_byte_interrupt() ( REG_OWI_CTL &= ~OWI_CTL_EBYTE ) -++#define __owi_enable_bit_interrupt() ( REG_OWI_CTL |= OWI_CTL_EBIT ) -++#define __owi_disable_bit_interrupt() ( REG_OWI_CTL &= ~OWI_CTL_EBIT ) -++#define __owi_enable_rst_interrupt() ( REG_OWI_CTL |= OWI_CTL_ERST ) -++#define __owi_disable_rst_interrupt() ( REG_OWI_CTL &=~OWI_CTL_ERST ) -++ -++/* OW configure register ops */ -++#define __owi_select_regular_mode() ( REG_OWI_CFG &= ~OWI_CFG_MODE ) -++#define __owi_select_overdrive_mode() ( REG_OWI_CFG |= OWI_CFG_MODE ) -++ -++#define __owi_set_rddata() ( REG_OWI_CFG |= OWI_CFG_RDDATA ) -++#define __owi_clr_rddata() ( REG_OWI_CFG &= ~OWI_CFG_RDDATA ) -++#define __owi_get_rddata() ( REG_OWI_CFG & OWI_CFG_RDDATA ) -++ -++#define __owi_set_wrdata() ( REG_OWI_CFG |= OWI_CFG_WRDATA ) -++#define __owi_clr_wrdata() ( REG_OWI_CFG &= ~OWI_CFG_WRDATA ) -++#define __owi_get_wrdata() ( REG_OWI_CFG & OWI_CFG_WRDATA ) -++ -++#define __owi_get_rdst() ( REG_OWI_CFG & OWI_CFG_RDST ) -++ -++#define __owi_set_wr1rd() ( REG_OWI_CFG |= OWI_CFG_WR1RD ) -++#define __owi_clr_wr1rd() ( REG_OWI_CFG &= ~OWI_CFG_WR1RD ) -++#define __owi_get_wr1rd() ( REG_OWI_CFG & OWI_CFG_WR1RD ) -++ -++#define __owi_set_wr0() ( REG_OWI_CFG |= OWI_CFG_WR0 ) -++#define __owi_clr_wr0() ( REG_OWI_CFG &= ~OWI_CFG_WR0 ) -++#define __owi_get_wr0() ( REG_OWI_CFG & OWI_CFG_WR0 ) -++ -++#define __owi_set_rst() ( REG_OWI_CFG |= OWI_CFG_RST ) -++#define __owi_clr_rst() ( REG_OWI_CFG &= ~OWI_CFG_RST ) -++#define __owi_get_rst() ( REG_OWI_CFG & OWI_CFG_RST ) -++ -++#define __owi_enable_ow_ops() ( REG_OWI_CFG |= OWI_CFG_ENA ) -++#define __owi_disable_ow_ops() ( REG_OWI_CFG &= ~OWI_CFG_ENA ) -++#define __owi_get_enable() ( REG_OWI_CFG & OWI_CFG_ENA ) -++ -++#define __owi_wait_ops_rdy() \ -++ do { \ -++ while(__owi_get_enable()); \ -++ udelay(1); \ -++ } while(0); -++ -++/* OW status register ops */ -++#define __owi_clr_sts() ( REG_OWI_STS = 0 ) -++#define __owi_get_sts_pst() ( REG_OWI_STS & OWI_STS_PST ) -++#define __owi_get_sts_byte_rdy() ( REG_OWI_STS & OWI_STS_BYTE_RDY ) -++#define __owi_get_sts_bit_rdy() ( REG_OWI_STS & OWI_STS_BIT_RDY ) -++#define __owi_get_sts_pst_rdy() ( REG_OWI_STS & OWI_STS_PST_RDY ) -++ -++/************************************************************************* -++ * TSSI MPEG 2-TS slave interface operation -++ *************************************************************************/ -++#define __tssi_enable() ( REG_TSSI_ENA |= TSSI_ENA_ENA ) -++#define __tssi_disable() ( REG_TSSI_ENA &= ~TSSI_ENA_ENA ) -++#define __tssi_soft_reset() ( REG_TSSI_ENA |= TSSI_ENA_SFT_RST ) -++#define __tssi_dma_enable() ( REG_TSSI_ENA |= TSSI_ENA_DMA_EN ) -++#define __tssi_dma_disable() ( REG_TSSI_ENA &= ~TSSI_ENA_DMA_EN ) -++#define __tssi_filter_enable() ( REG_TSSI_ENA |= TSSI_ENA_PID_EN ) -++#define __tssi_filter_disable() ( REG_TSSI_ENA &= ~TSSI_ENA_PID_EN ) -++ -++/* n = 4, 8, 16 */ -++#define __tssi_set_tigger_num(n) \ -++ do { \ -++ REG_TSSI_CFG &= ~TSSI_CFG_TRIG_MASK; \ -++ REG_TSSI_CFG |= TSSI_CFG_TRIG_##n; \ -++ } while (0) -++ -++#define __tssi_set_wd_1() ( REG_TSSI_CFG |= TSSI_CFG_END_WD ) -++#define __tssi_set_wd_0() ( REG_TSSI_CFG &= ~TSSI_CFG_END_WD ) -++ -++#define __tssi_set_bt_1() ( REG_TSSI_CFG |= TSSI_CFG_END_BD ) -++#define __tssi_set_bt_0() ( REG_TSSI_CFG &= ~TSSI_CFG_END_BD ) -++ -++#define __tssi_set_data_pola_high() ( REG_TSSI_CFG |= TSSI_CFG_TSDI_H ) -++#define __tssi_set_data_pola_low() ( REG_TSSI_CFG &= ~TSSI_CFG_TSDI_H ) -++ -++#define __tssi_set_data_use_data0() ( REG_TSSI_CFG |= TSSI_CFG_USE_0 ) -++#define __tssi_set_data_use_data7() ( REG_TSSI_CFG &= ~TSSI_CFG_USE_0 ) -++ -++#define __tssi_select_clk_fast() ( REG_TSSI_CFG &= ~TSSI_CFG_TSCLK_CH ) -++#define __tssi_select_clk_slow() ( REG_TSSI_CFG |= TSSI_CFG_TSCLK_CH ) -++ -++#define __tssi_select_serail_mode() ( REG_TSSI_CFG &= ~TSSI_CFG_PARAL ) -++#define __tssi_select_paral_mode() ( REG_TSSI_CFG |= TSSI_CFG_PARAL ) -++ -++#define __tssi_select_clk_nega_edge() ( REG_TSSI_CFG &= ~TSSI_CFG_TSCLK_P ) -++#define __tssi_select_clk_posi_edge() ( REG_TSSI_CFG |= TSSI_CFG_TSCLK_P ) -++ -++#define __tssi_select_frm_act_high() ( REG_TSSI_CFG |= TSSI_CFG_TSFRM_H ) -++#define __tssi_select_frm_act_low() ( REG_TSSI_CFG &= ~TSSI_CFG_TSFRM_H ) -++ -++#define __tssi_select_str_act_high() ( REG_TSSI_CFG |= TSSI_CFG_TSSTR_H ) -++#define __tssi_select_str_act_low() ( REG_TSSI_CFG &= ~TSSI_CFG_TSSTR_H ) -++ -++#define __tssi_select_fail_act_high() ( REG_TSSI_CFG |= TSSI_CFG_TSFAIL_H ) -++#define __tssi_select_fail_act_low() ( REG_TSSI_CFG &= ~TSSI_CFG_TSFAIL_H ) -++ -++#define __tssi_enable_ovrn_irq() ( REG_TSSI_CTRL &= ~TSSI_CTRL_OVRNM ) -++#define __tssi_disable_ovrn_irq() ( REG_TSSI_CTRL |= TSSI_CTRL_OVRNM ) -++ -++#define __tssi_enable_trig_irq() ( REG_TSSI_CTRL &= ~TSSI_CTRL_TRIGM ) -++#define __tssi_disable_trig_irq() ( REG_TSSI_CTRL |= TSSI_CTRL_TRIGM ) -++ -++#define __tssi_state_is_overrun() ( REG_TSSI_STAT & TSSI_STAT_OVRN ) -++#define __tssi_state_trigger_meet() ( REG_TSSI_STAT & TSSI_STAT_TRIG ) -++#define __tssi_clear_state() ( REG_TSSI_STAT = 0 ) /* write 0??? */ -++#define __tssi_state_clear_overrun() ( REG_TSSI_STAT = TSSI_STAT_OVRN ) -++ -++#define __tssi_enable_filte_pid0() ( REG_TSSI_PEN |= TSSI_PEN_PID0 ) -++#define __tssi_disable_filte_pid0() ( REG_TSSI_PEN &= ~TSSI_PEN_PID0 ) -++ -++/* m = 0, ..., 15 */ -++#define __tssi_enable_pid_filter(m) \ -++ do { \ -++ int n = (m); \ -++ if ( n>=0 && n <(TSSI_PID_MAX*2) ) { \ -++ if ( n >= TSSI_PID_MAX ) n += 8; \ -++ REG_TSSI_PEN |= ( 1 << n ); \ -++ } \ -++ } while (0) -++ -++/* m = 0, ..., 15 */ -++#define __tssi_disable_pid_filter(m) \ -++ do { \ -++ int n = (m); \ -++ if ( n>=0 && n <(TSSI_PID_MAX*2) ) { \ -++ if ( n >= TSSI_PID_MAX ) n += 8; \ -++ REG_TSSI_PEN &= ~( 1 << n ); \ -++ } \ -++ } while (0) -++ -++/* n = 0, ..., 7 */ -++#define __tssi_set_pid0(n, pid0) \ -++ do { \ -++ REG_TSSI_PID(n) &= ~TSSI_PID_PID0_MASK; \ -++ REG_TSSI_PID(n) |= ((pid0)<=0 && n < TSSI_PID_MAX*2) { \ -++ if ( n < TSSI_PID_MAX ) \ -++ __tssi_set_pid0(n, pid); \ -++ else \ -++ __tssi_set_pid1(n-TSSI_PID_MAX, pid); \ -++ } \ -++ }while (0) -++ -++ -++#if 0 -++/************************************************************************* -++ * IPU (Image Processing Unit) -++ *************************************************************************/ -++#define u32 volatile unsigned long -++ -++#define write_reg(reg, val) \ -++do { \ -++ *(u32 *)(reg) = (val); \ -++} while(0) -++ -++#define read_reg(reg, off) (*(u32 *)((reg)+(off))) -++ -++ -++#define set_ipu_fmt(rgb_888_out_fmt, rgb_out_oft, out_fmt, yuv_pkg_out, in_oft, in_fmt ) \ -++({ write_reg( (IPU_V_BASE + REG_D_FMT), ((in_fmt) & IN_FMT_MSK)< Unsigned toggle enable */ -++#define AIC_CR_FLUSH (1 << 8) /* Flush FIFO */ -++#define AIC_CR_EROR (1 << 6) /* Enable ROR interrupt */ -++#define AIC_CR_ETUR (1 << 5) /* Enable TUR interrupt */ -++#define AIC_CR_ERFS (1 << 4) /* Enable RFS interrupt */ -++#define AIC_CR_ETFS (1 << 3) /* Enable TFS interrupt */ -++#define AIC_CR_ENLBF (1 << 2) /* Enable Loopback Function */ -++#define AIC_CR_ERPL (1 << 1) /* Enable Playback Function */ -++#define AIC_CR_EREC (1 << 0) /* Enable Record Function */ -++ -++/* AIC Controller AC-link Control Register 1 (AIC_ACCR1) */ -++ -++#define AIC_ACCR1_RS_BIT 16 /* Receive Valid Slots */ -++#define AIC_ACCR1_RS_MASK (0x3ff << AIC_ACCR1_RS_BIT) -++ #define AIC_ACCR1_RS_SLOT12 (1 << 25) /* Slot 12 valid bit */ -++ #define AIC_ACCR1_RS_SLOT11 (1 << 24) /* Slot 11 valid bit */ -++ #define AIC_ACCR1_RS_SLOT10 (1 << 23) /* Slot 10 valid bit */ -++ #define AIC_ACCR1_RS_SLOT9 (1 << 22) /* Slot 9 valid bit, LFE */ -++ #define AIC_ACCR1_RS_SLOT8 (1 << 21) /* Slot 8 valid bit, Surround Right */ -++ #define AIC_ACCR1_RS_SLOT7 (1 << 20) /* Slot 7 valid bit, Surround Left */ -++ #define AIC_ACCR1_RS_SLOT6 (1 << 19) /* Slot 6 valid bit, PCM Center */ -++ #define AIC_ACCR1_RS_SLOT5 (1 << 18) /* Slot 5 valid bit */ -++ #define AIC_ACCR1_RS_SLOT4 (1 << 17) /* Slot 4 valid bit, PCM Right */ -++ #define AIC_ACCR1_RS_SLOT3 (1 << 16) /* Slot 3 valid bit, PCM Left */ -++#define AIC_ACCR1_XS_BIT 0 /* Transmit Valid Slots */ -++#define AIC_ACCR1_XS_MASK (0x3ff << AIC_ACCR1_XS_BIT) -++ #define AIC_ACCR1_XS_SLOT12 (1 << 9) /* Slot 12 valid bit */ -++ #define AIC_ACCR1_XS_SLOT11 (1 << 8) /* Slot 11 valid bit */ -++ #define AIC_ACCR1_XS_SLOT10 (1 << 7) /* Slot 10 valid bit */ -++ #define AIC_ACCR1_XS_SLOT9 (1 << 6) /* Slot 9 valid bit, LFE */ -++ #define AIC_ACCR1_XS_SLOT8 (1 << 5) /* Slot 8 valid bit, Surround Right */ -++ #define AIC_ACCR1_XS_SLOT7 (1 << 4) /* Slot 7 valid bit, Surround Left */ -++ #define AIC_ACCR1_XS_SLOT6 (1 << 3) /* Slot 6 valid bit, PCM Center */ -++ #define AIC_ACCR1_XS_SLOT5 (1 << 2) /* Slot 5 valid bit */ -++ #define AIC_ACCR1_XS_SLOT4 (1 << 1) /* Slot 4 valid bit, PCM Right */ -++ #define AIC_ACCR1_XS_SLOT3 (1 << 0) /* Slot 3 valid bit, PCM Left */ -++ -++/* AIC Controller AC-link Control Register 2 (AIC_ACCR2) */ -++ -++#define AIC_ACCR2_ERSTO (1 << 18) /* Enable RSTO interrupt */ -++#define AIC_ACCR2_ESADR (1 << 17) /* Enable SADR interrupt */ -++#define AIC_ACCR2_ECADT (1 << 16) /* Enable CADT interrupt */ -++#define AIC_ACCR2_OASS_BIT 8 /* Output Sample Size for AC-link */ -++#define AIC_ACCR2_OASS_MASK (0x3 << AIC_ACCR2_OASS_BIT) -++ #define AIC_ACCR2_OASS_20BIT (0 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 20-bit */ -++ #define AIC_ACCR2_OASS_18BIT (1 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 18-bit */ -++ #define AIC_ACCR2_OASS_16BIT (2 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 16-bit */ -++ #define AIC_ACCR2_OASS_8BIT (3 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 8-bit */ -++#define AIC_ACCR2_IASS_BIT 6 /* Output Sample Size for AC-link */ -++#define AIC_ACCR2_IASS_MASK (0x3 << AIC_ACCR2_IASS_BIT) -++ #define AIC_ACCR2_IASS_20BIT (0 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 20-bit */ -++ #define AIC_ACCR2_IASS_18BIT (1 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 18-bit */ -++ #define AIC_ACCR2_IASS_16BIT (2 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 16-bit */ -++ #define AIC_ACCR2_IASS_8BIT (3 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 8-bit */ -++#define AIC_ACCR2_SO (1 << 3) /* SDATA_OUT output value */ -++#define AIC_ACCR2_SR (1 << 2) /* RESET# pin level */ -++#define AIC_ACCR2_SS (1 << 1) /* SYNC pin level */ -++#define AIC_ACCR2_SA (1 << 0) /* SYNC and SDATA_OUT alternation */ -++ -++/* AIC Controller I2S/MSB-justified Control Register (AIC_I2SCR) */ -++ -++#define AIC_I2SCR_STPBK (1 << 12) /* Stop BIT_CLK for I2S/MSB-justified */ -++#define AIC_I2SCR_WL_BIT 1 /* Input/Output Sample Size for I2S/MSB-justified */ -++#define AIC_I2SCR_WL_MASK (0x7 << AIC_I2SCR_WL_BIT) -++ #define AIC_I2SCR_WL_24BIT (0 << AIC_I2SCR_WL_BIT) /* Word Length is 24 bit */ -++ #define AIC_I2SCR_WL_20BIT (1 << AIC_I2SCR_WL_BIT) /* Word Length is 20 bit */ -++ #define AIC_I2SCR_WL_18BIT (2 << AIC_I2SCR_WL_BIT) /* Word Length is 18 bit */ -++ #define AIC_I2SCR_WL_16BIT (3 << AIC_I2SCR_WL_BIT) /* Word Length is 16 bit */ -++ #define AIC_I2SCR_WL_8BIT (4 << AIC_I2SCR_WL_BIT) /* Word Length is 8 bit */ -++#define AIC_I2SCR_AMSL (1 << 0) /* 0:I2S, 1:MSB-justified */ -++ -++/* AIC Controller FIFO Status Register (AIC_SR) */ -++ -++#define AIC_SR_RFL_BIT 24 /* Receive FIFO Level */ -++#define AIC_SR_RFL_MASK (0x3f << AIC_SR_RFL_BIT) -++#define AIC_SR_TFL_BIT 8 /* Transmit FIFO level */ -++#define AIC_SR_TFL_MASK (0x3f << AIC_SR_TFL_BIT) -++#define AIC_SR_ROR (1 << 6) /* Receive FIFO Overrun */ -++#define AIC_SR_TUR (1 << 5) /* Transmit FIFO Underrun */ -++#define AIC_SR_RFS (1 << 4) /* Receive FIFO Service Request */ -++#define AIC_SR_TFS (1 << 3) /* Transmit FIFO Service Request */ -++ -++/* AIC Controller AC-link Status Register (AIC_ACSR) */ -++ -++#define AIC_ACSR_SLTERR (1 << 21) /* Slot Error Flag */ -++#define AIC_ACSR_CRDY (1 << 20) /* External CODEC Ready Flag */ -++#define AIC_ACSR_CLPM (1 << 19) /* External CODEC low power mode flag */ -++#define AIC_ACSR_RSTO (1 << 18) /* External CODEC regs read status timeout */ -++#define AIC_ACSR_SADR (1 << 17) /* External CODEC regs status addr and data received */ -++#define AIC_ACSR_CADT (1 << 16) /* Command Address and Data Transmitted */ -++ -++/* AIC Controller I2S/MSB-justified Status Register (AIC_I2SSR) */ -++ -++#define AIC_I2SSR_BSY (1 << 2) /* AIC Busy in I2S/MSB-justified format */ -++ -++/* AIC Controller AC97 codec Command Address Register (AIC_ACCAR) */ -++ -++#define AIC_ACCAR_CAR_BIT 0 -++#define AIC_ACCAR_CAR_MASK (0xfffff << AIC_ACCAR_CAR_BIT) -++ -++/* AIC Controller AC97 codec Command Data Register (AIC_ACCDR) */ -++ -++#define AIC_ACCDR_CDR_BIT 0 -++#define AIC_ACCDR_CDR_MASK (0xfffff << AIC_ACCDR_CDR_BIT) -++ -++/* AIC Controller AC97 codec Status Address Register (AIC_ACSAR) */ -++ -++#define AIC_ACSAR_SAR_BIT 0 -++#define AIC_ACSAR_SAR_MASK (0xfffff << AIC_ACSAR_SAR_BIT) -++ -++/* AIC Controller AC97 codec Status Data Register (AIC_ACSDR) */ -++ -++#define AIC_ACSDR_SDR_BIT 0 -++#define AIC_ACSDR_SDR_MASK (0xfffff << AIC_ACSDR_SDR_BIT) -++ -++/* AIC Controller I2S/MSB-justified Clock Divider Register (AIC_I2SDIV) */ -++ -++#define AIC_I2SDIV_DIV_BIT 0 -++#define AIC_I2SDIV_DIV_MASK (0x7f << AIC_I2SDIV_DIV_BIT) -++ #define AIC_I2SDIV_BITCLK_3072KHZ (0x0C << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 3.072MHz */ -++ #define AIC_I2SDIV_BITCLK_2836KHZ (0x0D << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 2.836MHz */ -++ #define AIC_I2SDIV_BITCLK_1418KHZ (0x1A << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.418MHz */ -++ #define AIC_I2SDIV_BITCLK_1024KHZ (0x24 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.024MHz */ -++ #define AIC_I2SDIV_BITCLK_7089KHZ (0x34 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 708.92KHz */ -++ #define AIC_I2SDIV_BITCLK_512KHZ (0x48 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 512.00KHz */ -++ -++ -++/************************************************************************* -++ * ICDC (Internal CODEC) -++ *************************************************************************/ -++ -++#define ICDC_CKCFG (ICDC_BASE + 0x00a0) /* Clock Configure Register */ -++#define ICDC_RGADW (ICDC_BASE + 0x00a4) /* internal register access control */ -++#define ICDC_RGDATA (ICDC_BASE + 0x00a8) /* internal register data output */ -++ -++#define REG_ICDC_CKCFG REG32(ICDC_CKCFG) -++#define REG_ICDC_RGADW REG32(ICDC_RGADW) -++#define REG_ICDC_RGDATA REG32(ICDC_RGDATA) -++ -++/* ICDC Clock Configure Register */ -++#define ICDC_CKCFG_CKRDY (1 << 1) -++#define ICDC_CKCFG_SELAD (1 << 0) -++ -++/* ICDC internal register access control Register */ -++#define ICDC_RGADW_RGWR (1 << 16) -++#define ICDC_RGADW_RGADDR_BIT 8 -++#define ICDC_RGADW_RGADDR_MASK (0x7f << ICDC_RGADW_RGADDR_BIT) -++#define ICDC_RGADW_RGDIN_BIT 0 -++#define ICDC_RGADW_RGDIN_MASK (0xff << ICDC_RGADW_RGDIN_BIT) -++ -++/* ICDC internal register data output Register */ -++#define ICDC_RGDATA_IRQ (1 << 8) -++#define ICDC_RGDATA_RGDOUT_BIT 0 -++#define ICDC_RGDATA_RGDOUT_MASK (0xff << ICDC_RGDATA_RGDOUT_BIT) -++ -++/************************************************************************* -++ * PCM Controller -++ *************************************************************************/ -++ -++#define PCM_CTL (PCM_BASE + 0x000) -++#define PCM_CFG (PCM_BASE + 0x004) -++#define PCM_DP (PCM_BASE + 0x008) -++#define PCM_INTC (PCM_BASE + 0x00c) -++#define PCM_INTS (PCM_BASE + 0x010) -++#define PCM_DIV (PCM_BASE + 0x014) -++ -++#define REG_PCM_CTL REG32(PCM_CTL) -++#define REG_PCM_CFG REG32(PCM_CFG) -++#define REG_PCM_DP REG32(PCM_DP) -++#define REG_PCM_INTC REG32(PCM_INTC) -++#define REG_PCM_INTS REG32(PCM_INTS) -++#define REG_PCM_DIV REG32(PCM_DIV) -++ -++/* PCM Controller control Register (PCM_CTL) */ -++ -++#define PCM_CTL_ERDMA (1 << 9) /* Enable Receive DMA */ -++#define PCM_CTL_ETDMA (1 << 8) /* Enable Transmit DMA */ -++#define PCM_CTL_LSMP (1 << 7) /* Play Zero sample or last sample */ -++#define PCM_CTL_ERPL (1 << 6) /* Enable Playing Back Function */ -++#define PCM_CTL_EREC (1 << 5) /* Enable Recording Function */ -++#define PCM_CTL_FLUSH (1 << 4) /* FIFO flush */ -++#define PCM_CTL_RST (1 << 3) /* Reset PCM */ -++#define PCM_CTL_CLKEN (1 << 1) /* Enable the clock division logic */ -++#define PCM_CTL_PCMEN (1 << 0) /* Enable PCM module */ -++ -++/* PCM Controller configure Register (PCM_CFG) */ -++ -++#define PCM_CFG_SLOT_BIT 13 -++#define PCM_CFG_SLOT_MASK (0x3 << PCM_CFG_SLOT_BIT) -++ #define PCM_CFG_SLOT_0 (0 << PCM_CFG_SLOT_BIT) /* Slot is 0 */ -++ #define PCM_CFG_SLOT_1 (1 << PCM_CFG_SLOT_BIT) /* Slot is 1 */ -++ #define PCM_CFG_SLOT_2 (2 << PCM_CFG_SLOT_BIT) /* Slot is 2 */ -++ #define PCM_CFG_SLOT_3 (3 << PCM_CFG_SLOT_BIT) /* Slot is 3 */ -++#define PCM_CFG_ISS_BIT 12 -++#define PCM_CFG_ISS_MASK (0x1 << PCM_CFG_ISS_BIT) -++ #define PCM_CFG_ISS_8 (0 << PCM_CFG_ISS_BIT) -++ #define PCM_CFG_ISS_16 (1 << PCM_CFG_ISS_BIT) -++#define PCM_CFG_OSS_BIT 11 -++#define PCM_CFG_OSS_MASK (0x1 << PCM_CFG_OSS_BIT) -++ #define PCM_CFG_OSS_8 (0 << PCM_CFG_OSS_BIT) -++ #define PCM_CFG_OSS_16 (1 << PCM_CFG_OSS_BIT) -++#define PCM_CFG_IMSBPOS (1 << 10) -++#define PCM_CFG_OMSBPOS (1 << 9) -++#define PCM_CFG_RFTH_BIT 5 /* Receive FIFO Threshold */ -++#define PCM_CFG_RFTH_MASK (0xf << PCM_CFG_RFTH_BIT) -++#define PCM_CFG_TFTH_BIT 1 /* Transmit FIFO Threshold */ -++#define PCM_CFG_TFTH_MASK (0xf << PCM_CFG_TFTH_BIT) -++#define PCM_CFG_MODE (0x0 << 0) -++ -++/* PCM Controller interrupt control Register (PCM_INTC) */ -++ -++#define PCM_INTC_ETFS (1 << 3) -++#define PCM_INTC_ETUR (1 << 2) -++#define PCM_INTC_ERFS (1 << 1) -++#define PCM_INTC_EROR (1 << 0) -++ -++/* PCM Controller interrupt status Register (PCM_INTS) */ -++ -++#define PCM_INTS_RSTS (1 << 14) /* Reset or flush has not complete */ -++#define PCM_INTS_TFL_BIT 9 -++#define PCM_INTS_TFL_MASK (0x1f << PCM_INTS_TFL_BIT) -++#define PCM_INTS_TFS (1 << 8) /* Tranmit FIFO Service Request */ -++#define PCM_INTS_TUR (1 << 7) /* Transmit FIFO Under Run */ -++#define PCM_INTS_RFL_BIT 2 -++#define PCM_INTS_RFL_MASK (0x1f << PCM_INTS_RFL_BIT) -++#define PCM_INTS_RFS (1 << 1) /* Receive FIFO Service Request */ -++#define PCM_INTS_ROR (1 << 0) /* Receive FIFO Over Run */ -++ -++/* PCM Controller clock division Register (PCM_DIV) */ -++#define PCM_DIV_SYNL_BIT 11 -++#define PCM_DIV_SYNL_MASK (0x3f << PCM_DIV_SYNL_BIT) -++#define PCM_DIV_SYNDIV_BIT 6 -++#define PCM_DIV_SYNDIV_MASK (0x1f << PCM_DIV_SYNDIV_BIT) -++#define PCM_DIV_CLKDIV_BIT 0 -++#define PCM_DIV_CLKDIV_MASK (0x3f << PCM_DIV_CLKDIV_BIT) -++ -++ -++/************************************************************************* -++ * I2C -++ *************************************************************************/ -++#define I2C_DR (I2C_BASE + 0x000) -++#define I2C_CR (I2C_BASE + 0x004) -++#define I2C_SR (I2C_BASE + 0x008) -++#define I2C_GR (I2C_BASE + 0x00C) -++ -++#define REG_I2C_DR REG8(I2C_DR) -++#define REG_I2C_CR REG8(I2C_CR) -++#define REG_I2C_SR REG8(I2C_SR) -++#define REG_I2C_GR REG16(I2C_GR) -++ -++/* I2C Control Register (I2C_CR) */ -++ -++#define I2C_CR_IEN (1 << 4) -++#define I2C_CR_STA (1 << 3) -++#define I2C_CR_STO (1 << 2) -++#define I2C_CR_AC (1 << 1) -++#define I2C_CR_I2CE (1 << 0) -++ -++/* I2C Status Register (I2C_SR) */ -++ -++#define I2C_SR_STX (1 << 4) -++#define I2C_SR_BUSY (1 << 3) -++#define I2C_SR_TEND (1 << 2) -++#define I2C_SR_DRF (1 << 1) -++#define I2C_SR_ACKF (1 << 0) -++ -++ -++/************************************************************************* -++ * SSI (Synchronous Serial Interface) -++ *************************************************************************/ -++/* n = 0, 1 (SSI0, SSI1) */ -++#define SSI_DR(n) (SSI_BASE + 0x000 + (n)*0x2000) -++#define SSI_CR0(n) (SSI_BASE + 0x004 + (n)*0x2000) -++#define SSI_CR1(n) (SSI_BASE + 0x008 + (n)*0x2000) -++#define SSI_SR(n) (SSI_BASE + 0x00C + (n)*0x2000) -++#define SSI_ITR(n) (SSI_BASE + 0x010 + (n)*0x2000) -++#define SSI_ICR(n) (SSI_BASE + 0x014 + (n)*0x2000) -++#define SSI_GR(n) (SSI_BASE + 0x018 + (n)*0x2000) -++ -++#define REG_SSI_DR(n) REG32(SSI_DR(n)) -++#define REG_SSI_CR0(n) REG16(SSI_CR0(n)) -++#define REG_SSI_CR1(n) REG32(SSI_CR1(n)) -++#define REG_SSI_SR(n) REG32(SSI_SR(n)) -++#define REG_SSI_ITR(n) REG16(SSI_ITR(n)) -++#define REG_SSI_ICR(n) REG8(SSI_ICR(n)) -++#define REG_SSI_GR(n) REG16(SSI_GR(n)) -++ -++/* SSI Data Register (SSI_DR) */ -++ -++#define SSI_DR_GPC_BIT 0 -++#define SSI_DR_GPC_MASK (0x1ff << SSI_DR_GPC_BIT) -++ -++#define SSI_MAX_FIFO_ENTRIES 128 /* 128 txfifo and 128 rxfifo */ -++ -++/* SSI Control Register 0 (SSI_CR0) */ -++ -++#define SSI_CR0_SSIE (1 << 15) -++#define SSI_CR0_TIE (1 << 14) -++#define SSI_CR0_RIE (1 << 13) -++#define SSI_CR0_TEIE (1 << 12) -++#define SSI_CR0_REIE (1 << 11) -++#define SSI_CR0_LOOP (1 << 10) -++#define SSI_CR0_RFINE (1 << 9) -++#define SSI_CR0_RFINC (1 << 8) -++#define SSI_CR0_EACLRUN (1 << 7) /* hardware auto clear underrun when TxFifo no empty */ -++#define SSI_CR0_FSEL (1 << 6) -++#define SSI_CR0_TFLUSH (1 << 2) -++#define SSI_CR0_RFLUSH (1 << 1) -++#define SSI_CR0_DISREV (1 << 0) -++ -++/* SSI Control Register 1 (SSI_CR1) */ -++ -++#define SSI_CR1_FRMHL_BIT 30 -++#define SSI_CR1_FRMHL_MASK (0x3 << SSI_CR1_FRMHL_BIT) -++ #define SSI_CR1_FRMHL_CELOW_CE2LOW (0 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is low valid */ -++ #define SSI_CR1_FRMHL_CEHIGH_CE2LOW (1 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is low valid */ -++ #define SSI_CR1_FRMHL_CELOW_CE2HIGH (2 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is high valid */ -++ #define SSI_CR1_FRMHL_CEHIGH_CE2HIGH (3 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is high valid */ -++#define SSI_CR1_TFVCK_BIT 28 -++#define SSI_CR1_TFVCK_MASK (0x3 << SSI_CR1_TFVCK_BIT) -++ #define SSI_CR1_TFVCK_0 (0 << SSI_CR1_TFVCK_BIT) -++ #define SSI_CR1_TFVCK_1 (1 << SSI_CR1_TFVCK_BIT) -++ #define SSI_CR1_TFVCK_2 (2 << SSI_CR1_TFVCK_BIT) -++ #define SSI_CR1_TFVCK_3 (3 << SSI_CR1_TFVCK_BIT) -++#define SSI_CR1_TCKFI_BIT 26 -++#define SSI_CR1_TCKFI_MASK (0x3 << SSI_CR1_TCKFI_BIT) -++ #define SSI_CR1_TCKFI_0 (0 << SSI_CR1_TCKFI_BIT) -++ #define SSI_CR1_TCKFI_1 (1 << SSI_CR1_TCKFI_BIT) -++ #define SSI_CR1_TCKFI_2 (2 << SSI_CR1_TCKFI_BIT) -++ #define SSI_CR1_TCKFI_3 (3 << SSI_CR1_TCKFI_BIT) -++#define SSI_CR1_LFST (1 << 25) -++#define SSI_CR1_ITFRM (1 << 24) -++#define SSI_CR1_UNFIN (1 << 23) -++#define SSI_CR1_MULTS (1 << 22) -++#define SSI_CR1_FMAT_BIT 20 -++#define SSI_CR1_FMAT_MASK (0x3 << SSI_CR1_FMAT_BIT) -++ #define SSI_CR1_FMAT_SPI (0 << SSI_CR1_FMAT_BIT) /* Motorola¡¯s SPI format */ -++ #define SSI_CR1_FMAT_SSP (1 << SSI_CR1_FMAT_BIT) /* TI's SSP format */ -++ #define SSI_CR1_FMAT_MW1 (2 << SSI_CR1_FMAT_BIT) /* National Microwire 1 format */ -++ #define SSI_CR1_FMAT_MW2 (3 << SSI_CR1_FMAT_BIT) /* National Microwire 2 format */ -++#define SSI_CR1_TTRG_BIT 16 /* SSI1 TX trigger */ -++#define SSI_CR1_TTRG_MASK (0xf << SSI_CR1_TTRG_BIT) -++#define SSI_CR1_MCOM_BIT 12 -++#define SSI_CR1_MCOM_MASK (0xf << SSI_CR1_MCOM_BIT) -++ #define SSI_CR1_MCOM_1BIT (0x0 << SSI_CR1_MCOM_BIT) /* 1-bit command selected */ -++ #define SSI_CR1_MCOM_2BIT (0x1 << SSI_CR1_MCOM_BIT) /* 2-bit command selected */ -++ #define SSI_CR1_MCOM_3BIT (0x2 << SSI_CR1_MCOM_BIT) /* 3-bit command selected */ -++ #define SSI_CR1_MCOM_4BIT (0x3 << SSI_CR1_MCOM_BIT) /* 4-bit command selected */ -++ #define SSI_CR1_MCOM_5BIT (0x4 << SSI_CR1_MCOM_BIT) /* 5-bit command selected */ -++ #define SSI_CR1_MCOM_6BIT (0x5 << SSI_CR1_MCOM_BIT) /* 6-bit command selected */ -++ #define SSI_CR1_MCOM_7BIT (0x6 << SSI_CR1_MCOM_BIT) /* 7-bit command selected */ -++ #define SSI_CR1_MCOM_8BIT (0x7 << SSI_CR1_MCOM_BIT) /* 8-bit command selected */ -++ #define SSI_CR1_MCOM_9BIT (0x8 << SSI_CR1_MCOM_BIT) /* 9-bit command selected */ -++ #define SSI_CR1_MCOM_10BIT (0x9 << SSI_CR1_MCOM_BIT) /* 10-bit command selected */ -++ #define SSI_CR1_MCOM_11BIT (0xA << SSI_CR1_MCOM_BIT) /* 11-bit command selected */ -++ #define SSI_CR1_MCOM_12BIT (0xB << SSI_CR1_MCOM_BIT) /* 12-bit command selected */ -++ #define SSI_CR1_MCOM_13BIT (0xC << SSI_CR1_MCOM_BIT) /* 13-bit command selected */ -++ #define SSI_CR1_MCOM_14BIT (0xD << SSI_CR1_MCOM_BIT) /* 14-bit command selected */ -++ #define SSI_CR1_MCOM_15BIT (0xE << SSI_CR1_MCOM_BIT) /* 15-bit command selected */ -++ #define SSI_CR1_MCOM_16BIT (0xF << SSI_CR1_MCOM_BIT) /* 16-bit command selected */ -++#define SSI_CR1_RTRG_BIT 8 /* SSI RX trigger */ -++#define SSI_CR1_RTRG_MASK (0xf << SSI_CR1_RTRG_BIT) -++#define SSI_CR1_FLEN_BIT 4 -++#define SSI_CR1_FLEN_MASK (0xf << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_2BIT (0x0 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_3BIT (0x1 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_4BIT (0x2 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_5BIT (0x3 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_6BIT (0x4 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_7BIT (0x5 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_8BIT (0x6 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_9BIT (0x7 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_10BIT (0x8 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_11BIT (0x9 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_12BIT (0xA << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_13BIT (0xB << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_14BIT (0xC << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_15BIT (0xD << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_16BIT (0xE << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_17BIT (0xF << SSI_CR1_FLEN_BIT) -++#define SSI_CR1_PHA (1 << 1) -++#define SSI_CR1_POL (1 << 0) -++ -++/* SSI Status Register (SSI_SR) */ -++ -++#define SSI_SR_TFIFONUM_BIT 16 -++#define SSI_SR_TFIFONUM_MASK (0xff << SSI_SR_TFIFONUM_BIT) -++#define SSI_SR_RFIFONUM_BIT 8 -++#define SSI_SR_RFIFONUM_MASK (0xff << SSI_SR_RFIFONUM_BIT) -++#define SSI_SR_END (1 << 7) -++#define SSI_SR_BUSY (1 << 6) -++#define SSI_SR_TFF (1 << 5) -++#define SSI_SR_RFE (1 << 4) -++#define SSI_SR_TFHE (1 << 3) -++#define SSI_SR_RFHF (1 << 2) -++#define SSI_SR_UNDR (1 << 1) -++#define SSI_SR_OVER (1 << 0) -++ -++/* SSI Interval Time Control Register (SSI_ITR) */ -++ -++#define SSI_ITR_CNTCLK (1 << 15) -++#define SSI_ITR_IVLTM_BIT 0 -++#define SSI_ITR_IVLTM_MASK (0x7fff << SSI_ITR_IVLTM_BIT) -++ -++ -++/************************************************************************* -++ * MSC -++ ************************************************************************/ -++/* n = 0, 1 (MSC0, MSC1) */ -++#define MSC_STRPCL(n) (MSC_BASE + (n)*0x1000 + 0x000) -++#define MSC_STAT(n) (MSC_BASE + (n)*0x1000 + 0x004) -++#define MSC_CLKRT(n) (MSC_BASE + (n)*0x1000 + 0x008) -++#define MSC_CMDAT(n) (MSC_BASE + (n)*0x1000 + 0x00C) -++#define MSC_RESTO(n) (MSC_BASE + (n)*0x1000 + 0x010) -++#define MSC_RDTO(n) (MSC_BASE + (n)*0x1000 + 0x014) -++#define MSC_BLKLEN(n) (MSC_BASE + (n)*0x1000 + 0x018) -++#define MSC_NOB(n) (MSC_BASE + (n)*0x1000 + 0x01C) -++#define MSC_SNOB(n) (MSC_BASE + (n)*0x1000 + 0x020) -++#define MSC_IMASK(n) (MSC_BASE + (n)*0x1000 + 0x024) -++#define MSC_IREG(n) (MSC_BASE + (n)*0x1000 + 0x028) -++#define MSC_CMD(n) (MSC_BASE + (n)*0x1000 + 0x02C) -++#define MSC_ARG(n) (MSC_BASE + (n)*0x1000 + 0x030) -++#define MSC_RES(n) (MSC_BASE + (n)*0x1000 + 0x034) -++#define MSC_RXFIFO(n) (MSC_BASE + (n)*0x1000 + 0x038) -++#define MSC_TXFIFO(n) (MSC_BASE + (n)*0x1000 + 0x03C) -++#define MSC_LPM(n) (MSC_BASE + (n)*0x1000 + 0x040) -++ -++#define REG_MSC_STRPCL(n) REG16(MSC_STRPCL(n)) -++#define REG_MSC_STAT(n) REG32(MSC_STAT(n)) -++#define REG_MSC_CLKRT(n) REG16(MSC_CLKRT(n)) -++#define REG_MSC_CMDAT(n) REG32(MSC_CMDAT(n)) -++#define REG_MSC_RESTO(n) REG16(MSC_RESTO(n)) -++#define REG_MSC_RDTO(n) REG16(MSC_RDTO(n)) -++#define REG_MSC_BLKLEN(n) REG16(MSC_BLKLEN(n)) -++#define REG_MSC_NOB(n) REG16(MSC_NOB(n)) -++#define REG_MSC_SNOB(n) REG16(MSC_SNOB(n)) -++#define REG_MSC_IMASK(n) REG32(MSC_IMASK(n)) -++#define REG_MSC_IREG(n) REG16(MSC_IREG(n)) -++#define REG_MSC_CMD(n) REG8(MSC_CMD(n)) -++#define REG_MSC_ARG(n) REG32(MSC_ARG(n)) -++#define REG_MSC_RES(n) REG16(MSC_RES(n)) -++#define REG_MSC_RXFIFO(n) REG32(MSC_RXFIFO(n)) -++#define REG_MSC_TXFIFO(n) REG32(MSC_TXFIFO(n)) -++#define REG_MSC_LPM(n) REG32(MSC_LPM(n)) -++ -++/* MSC Clock and Control Register (MSC_STRPCL) */ -++#define MSC_STRPCL_SEND_CCSD (1 << 15) /*send command completion signal disable to ceata */ -++#define MSC_STRPCL_SEND_AS_CCSD (1 << 14) /*send internally generated stop after sending ccsd */ -++#define MSC_STRPCL_EXIT_MULTIPLE (1 << 7) -++#define MSC_STRPCL_EXIT_TRANSFER (1 << 6) -++#define MSC_STRPCL_START_READWAIT (1 << 5) -++#define MSC_STRPCL_STOP_READWAIT (1 << 4) -++#define MSC_STRPCL_RESET (1 << 3) -++#define MSC_STRPCL_START_OP (1 << 2) -++#define MSC_STRPCL_CLOCK_CONTROL_BIT 0 -++#define MSC_STRPCL_CLOCK_CONTROL_MASK (0x3 << MSC_STRPCL_CLOCK_CONTROL_BIT) -++ #define MSC_STRPCL_CLOCK_CONTROL_STOP (0x1 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Stop MMC/SD clock */ -++ #define MSC_STRPCL_CLOCK_CONTROL_START (0x2 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Start MMC/SD clock */ -++ -++/* MSC Status Register (MSC_STAT) */ -++#define MSC_STAT_AUTO_CMD_DONE (1 << 31) /*12 is internally generated by controller has finished */ -++#define MSC_STAT_IS_RESETTING (1 << 15) -++#define MSC_STAT_SDIO_INT_ACTIVE (1 << 14) -++#define MSC_STAT_PRG_DONE (1 << 13) -++#define MSC_STAT_DATA_TRAN_DONE (1 << 12) -++#define MSC_STAT_END_CMD_RES (1 << 11) -++#define MSC_STAT_DATA_FIFO_AFULL (1 << 10) -++#define MSC_STAT_IS_READWAIT (1 << 9) -++#define MSC_STAT_CLK_EN (1 << 8) -++#define MSC_STAT_DATA_FIFO_FULL (1 << 7) -++#define MSC_STAT_DATA_FIFO_EMPTY (1 << 6) -++#define MSC_STAT_CRC_RES_ERR (1 << 5) -++#define MSC_STAT_CRC_READ_ERROR (1 << 4) -++#define MSC_STAT_CRC_WRITE_ERROR_BIT 2 -++#define MSC_STAT_CRC_WRITE_ERROR_MASK (0x3 << MSC_STAT_CRC_WRITE_ERROR_BIT) -++ #define MSC_STAT_CRC_WRITE_ERROR_NO (0 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No error on transmission of data */ -++ #define MSC_STAT_CRC_WRITE_ERROR (1 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* Card observed erroneous transmission of data */ -++ #define MSC_STAT_CRC_WRITE_ERROR_NOSTS (2 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No CRC status is sent back */ -++#define MSC_STAT_TIME_OUT_RES (1 << 1) -++#define MSC_STAT_TIME_OUT_READ (1 << 0) -++ -++/* MSC Bus Clock Control Register (MSC_CLKRT) */ -++#define MSC_CLKRT_CLK_RATE_BIT 0 -++#define MSC_CLKRT_CLK_RATE_MASK (0x7 << MSC_CLKRT_CLK_RATE_BIT) -++ #define MSC_CLKRT_CLK_RATE_DIV_1 (0x0 << MSC_CLKRT_CLK_RATE_BIT) /* CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_2 (0x1 << MSC_CLKRT_CLK_RATE_BIT) /* 1/2 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_4 (0x2 << MSC_CLKRT_CLK_RATE_BIT) /* 1/4 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_8 (0x3 << MSC_CLKRT_CLK_RATE_BIT) /* 1/8 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_16 (0x4 << MSC_CLKRT_CLK_RATE_BIT) /* 1/16 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_32 (0x5 << MSC_CLKRT_CLK_RATE_BIT) /* 1/32 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_64 (0x6 << MSC_CLKRT_CLK_RATE_BIT) /* 1/64 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_128 (0x7 << MSC_CLKRT_CLK_RATE_BIT) /* 1/128 of CLK_SRC */ -++ -++/* MSC Command Sequence Control Register (MSC_CMDAT) */ -++#define MSC_CMDAT_CCS_EXPECTED (1 << 31) /* interrupts are enabled in ce-ata */ -++#define MSC_CMDAT_READ_CEATA (1 << 30) -++#define MSC_CMDAT_SDIO_PRDT (1 << 17) /* exact 2 cycle */ -++#define MSC_CMDAT_SEND_AS_STOP (1 << 16) -++#define MSC_CMDAT_RTRG_BIT 14 -++ #define MSC_CMDAT_RTRG_EQUALT_8 (0x0 << MSC_CMDAT_RTRG_BIT) -++ #define MSC_CMDAT_RTRG_EQUALT_16 (0x1 << MSC_CMDAT_RTRG_BIT) /* reset value */ -++ #define MSC_CMDAT_RTRG_EQUALT_24 (0x2 << MSC_CMDAT_RTRG_BIT) -++ -++#define MSC_CMDAT_TTRG_BIT 12 -++ #define MSC_CMDAT_TTRG_LESS_8 (0x0 << MSC_CMDAT_TTRG_BIT) -++ #define MSC_CMDAT_TTRG_LESS_16 (0x1 << MSC_CMDAT_TTRG_BIT) /*reset value */ -++ #define MSC_CMDAT_TTRG_LESS_24 (0x2 << MSC_CMDAT_TTRG_BIT) -++#define MSC_CMDAT_STOP_ABORT (1 << 11) -++#define MSC_CMDAT_BUS_WIDTH_BIT 9 -++#define MSC_CMDAT_BUS_WIDTH_MASK (0x3 << MSC_CMDAT_BUS_WIDTH_BIT) -++ #define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) /* 1-bit data bus */ -++ #define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) /* 4-bit data bus */ -++ #define MSC_CMDAT_BUS_WIDTH_8BIT (0x3 << MSC_CMDAT_BUS_WIDTH_BIT) /* 8-bit data bus */ -++#define MSC_CMDAT_DMA_EN (1 << 8) -++#define MSC_CMDAT_INIT (1 << 7) -++#define MSC_CMDAT_BUSY (1 << 6) -++#define MSC_CMDAT_STREAM_BLOCK (1 << 5) -++#define MSC_CMDAT_WRITE (1 << 4) -++#define MSC_CMDAT_READ (0 << 4) -++#define MSC_CMDAT_DATA_EN (1 << 3) -++#define MSC_CMDAT_RESPONSE_BIT 0 -++#define MSC_CMDAT_RESPONSE_MASK (0x7 << MSC_CMDAT_RESPONSE_BIT) -++ #define MSC_CMDAT_RESPONSE_NONE (0x0 << MSC_CMDAT_RESPONSE_BIT) /* No response */ -++ #define MSC_CMDAT_RESPONSE_R1 (0x1 << MSC_CMDAT_RESPONSE_BIT) /* Format R1 and R1b */ -++ #define MSC_CMDAT_RESPONSE_R2 (0x2 << MSC_CMDAT_RESPONSE_BIT) /* Format R2 */ -++ #define MSC_CMDAT_RESPONSE_R3 (0x3 << MSC_CMDAT_RESPONSE_BIT) /* Format R3 */ -++ #define MSC_CMDAT_RESPONSE_R4 (0x4 << MSC_CMDAT_RESPONSE_BIT) /* Format R4 */ -++ #define MSC_CMDAT_RESPONSE_R5 (0x5 << MSC_CMDAT_RESPONSE_BIT) /* Format R5 */ -++ #define MSC_CMDAT_RESPONSE_R6 (0x6 << MSC_CMDAT_RESPONSE_BIT) /* Format R6 */ -++ -++#define CMDAT_DMA_EN (1 << 8) -++#define CMDAT_INIT (1 << 7) -++#define CMDAT_BUSY (1 << 6) -++#define CMDAT_STREAM (1 << 5) -++#define CMDAT_WRITE (1 << 4) -++#define CMDAT_DATA_EN (1 << 3) -++ -++/* MSC Interrupts Mask Register (MSC_IMASK) */ -++#define MSC_IMASK_AUTO_CMD_DONE (1 << 8) -++#define MSC_IMASK_SDIO (1 << 7) -++#define MSC_IMASK_TXFIFO_WR_REQ (1 << 6) -++#define MSC_IMASK_RXFIFO_RD_REQ (1 << 5) -++#define MSC_IMASK_END_CMD_RES (1 << 2) -++#define MSC_IMASK_PRG_DONE (1 << 1) -++#define MSC_IMASK_DATA_TRAN_DONE (1 << 0) -++ -++/* MSC Interrupts Status Register (MSC_IREG) */ -++#define MSC_IREG_AUTO_CMD_DONE (1 << 8) -++#define MSC_IREG_SDIO (1 << 7) -++#define MSC_IREG_TXFIFO_WR_REQ (1 << 6) -++#define MSC_IREG_RXFIFO_RD_REQ (1 << 5) -++#define MSC_IREG_END_CMD_RES (1 << 2) -++#define MSC_IREG_PRG_DONE (1 << 1) -++#define MSC_IREG_DATA_TRAN_DONE (1 << 0) -++ -++/* MSC Low Power Mode Register (MSC_LPM) */ -++#define MSC_SET_LPM (1 << 0) -++ -++/************************************************************************* -++ * EMC (External Memory Controller) -++ *************************************************************************/ -++#define EMC_BCR (EMC_BASE + 0x00) /* Bus Control Register */ -++#define EMC_SMCR0 (EMC_BASE + 0x10) /* Static Memory Control Register 0 */ -++#define EMC_SMCR1 (EMC_BASE + 0x14) /* Static Memory Control Register 1 */ -++#define EMC_SMCR2 (EMC_BASE + 0x18) /* Static Memory Control Register 2 */ -++#define EMC_SMCR3 (EMC_BASE + 0x1c) /* Static Memory Control Register 3 */ -++#define EMC_SMCR4 (EMC_BASE + 0x20) /* Static Memory Control Register 4 */ -++#define EMC_SACR0 (EMC_BASE + 0x30) /* Static Memory Bank 0 Addr Config Reg */ -++#define EMC_SACR1 (EMC_BASE + 0x34) /* Static Memory Bank 1 Addr Config Reg */ -++#define EMC_SACR2 (EMC_BASE + 0x38) /* Static Memory Bank 2 Addr Config Reg */ -++#define EMC_SACR3 (EMC_BASE + 0x3c) /* Static Memory Bank 3 Addr Config Reg */ -++#define EMC_SACR4 (EMC_BASE + 0x40) /* Static Memory Bank 4 Addr Config Reg */ -++ -++#define EMC_NFCSR (EMC_BASE + 0x050) /* NAND Flash Control/Status Register */ -++ -++#define EMC_DMCR (EMC_BASE + 0x80) /* DRAM Control Register */ -++#define EMC_RTCSR (EMC_BASE + 0x84) /* Refresh Time Control/Status Register */ -++#define EMC_RTCNT (EMC_BASE + 0x88) /* Refresh Timer Counter */ -++#define EMC_RTCOR (EMC_BASE + 0x8c) /* Refresh Time Constant Register */ -++#define EMC_DMAR0 (EMC_BASE + 0x90) /* SDRAM Bank 0 Addr Config Register */ -++#define EMC_DMAR1 (EMC_BASE + 0x94) /* SDRAM Bank 1 Addr Config Register */ -++#define EMC_SDMR0 (EMC_BASE + 0xa000) /* Mode Register of SDRAM bank 0 */ -++ -++#define REG_EMC_BCR REG32(EMC_BCR) -++#define REG_EMC_SMCR0 REG32(EMC_SMCR0) -++#define REG_EMC_SMCR1 REG32(EMC_SMCR1) -++#define REG_EMC_SMCR2 REG32(EMC_SMCR2) -++#define REG_EMC_SMCR3 REG32(EMC_SMCR3) -++#define REG_EMC_SMCR4 REG32(EMC_SMCR4) -++#define REG_EMC_SACR0 REG32(EMC_SACR0) -++#define REG_EMC_SACR1 REG32(EMC_SACR1) -++#define REG_EMC_SACR2 REG32(EMC_SACR2) -++#define REG_EMC_SACR3 REG32(EMC_SACR3) -++#define REG_EMC_SACR4 REG32(EMC_SACR4) -++ -++#define REG_EMC_NFCSR REG32(EMC_NFCSR) -++ -++#define REG_EMC_DMCR REG32(EMC_DMCR) -++#define REG_EMC_RTCSR REG16(EMC_RTCSR) -++#define REG_EMC_RTCNT REG16(EMC_RTCNT) -++#define REG_EMC_RTCOR REG16(EMC_RTCOR) -++#define REG_EMC_DMAR0 REG32(EMC_DMAR0) -++#define REG_EMC_DMAR1 REG32(EMC_DMAR1) -++ -++/* Bus Control Register */ -++#define EMC_BCR_BT_SEL_BIT 30 -++#define EMC_BCR_BT_SEL_MASK (0x3 << EMC_BCR_BT_SEL_BIT) -++#define EMC_BCR_PK_SEL (1 << 24) -++#define EMC_BCR_BSR_MASK (1 << 2) /* Nand and SDRAM Bus Share Select: 0, share; 1, unshare */ -++ #define EMC_BCR_BSR_SHARE (0 << 2) -++ #define EMC_BCR_BSR_UNSHARE (1 << 2) -++#define EMC_BCR_BRE (1 << 1) -++#define EMC_BCR_ENDIAN (1 << 0) -++ -++/* Static Memory Control Register */ -++#define EMC_SMCR_STRV_BIT 24 -++#define EMC_SMCR_STRV_MASK (0x0f << EMC_SMCR_STRV_BIT) -++#define EMC_SMCR_TAW_BIT 20 -++#define EMC_SMCR_TAW_MASK (0x0f << EMC_SMCR_TAW_BIT) -++#define EMC_SMCR_TBP_BIT 16 -++#define EMC_SMCR_TBP_MASK (0x0f << EMC_SMCR_TBP_BIT) -++#define EMC_SMCR_TAH_BIT 12 -++#define EMC_SMCR_TAH_MASK (0x07 << EMC_SMCR_TAH_BIT) -++#define EMC_SMCR_TAS_BIT 8 -++#define EMC_SMCR_TAS_MASK (0x07 << EMC_SMCR_TAS_BIT) -++#define EMC_SMCR_BW_BIT 6 -++#define EMC_SMCR_BW_MASK (0x03 << EMC_SMCR_BW_BIT) -++ #define EMC_SMCR_BW_8BIT (0 << EMC_SMCR_BW_BIT) -++ #define EMC_SMCR_BW_16BIT (1 << EMC_SMCR_BW_BIT) -++ #define EMC_SMCR_BW_32BIT (2 << EMC_SMCR_BW_BIT) -++#define EMC_SMCR_BCM (1 << 3) -++#define EMC_SMCR_BL_BIT 1 -++#define EMC_SMCR_BL_MASK (0x03 << EMC_SMCR_BL_BIT) -++ #define EMC_SMCR_BL_4 (0 << EMC_SMCR_BL_BIT) -++ #define EMC_SMCR_BL_8 (1 << EMC_SMCR_BL_BIT) -++ #define EMC_SMCR_BL_16 (2 << EMC_SMCR_BL_BIT) -++ #define EMC_SMCR_BL_32 (3 << EMC_SMCR_BL_BIT) -++#define EMC_SMCR_SMT (1 << 0) -++ -++/* Static Memory Bank Addr Config Reg */ -++#define EMC_SACR_BASE_BIT 8 -++#define EMC_SACR_BASE_MASK (0xff << EMC_SACR_BASE_BIT) -++#define EMC_SACR_MASK_BIT 0 -++#define EMC_SACR_MASK_MASK (0xff << EMC_SACR_MASK_BIT) -++ -++/* NAND Flash Control/Status Register */ -++#define EMC_NFCSR_NFCE4 (1 << 7) /* NAND Flash Enable */ -++#define EMC_NFCSR_NFE4 (1 << 6) /* NAND Flash FCE# Assertion Enable */ -++#define EMC_NFCSR_NFCE3 (1 << 5) -++#define EMC_NFCSR_NFE3 (1 << 4) -++#define EMC_NFCSR_NFCE2 (1 << 3) -++#define EMC_NFCSR_NFE2 (1 << 2) -++#define EMC_NFCSR_NFCE1 (1 << 1) -++#define EMC_NFCSR_NFE1 (1 << 0) -++ -++/* DRAM Control Register */ -++#define EMC_DMCR_BW_BIT 31 -++#define EMC_DMCR_BW (1 << EMC_DMCR_BW_BIT) -++#define EMC_DMCR_CA_BIT 26 -++#define EMC_DMCR_CA_MASK (0x07 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_8 (0 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_9 (1 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_10 (2 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_11 (3 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_12 (4 << EMC_DMCR_CA_BIT) -++#define EMC_DMCR_RMODE (1 << 25) -++#define EMC_DMCR_RFSH (1 << 24) -++#define EMC_DMCR_MRSET (1 << 23) -++#define EMC_DMCR_RA_BIT 20 -++#define EMC_DMCR_RA_MASK (0x03 << EMC_DMCR_RA_BIT) -++ #define EMC_DMCR_RA_11 (0 << EMC_DMCR_RA_BIT) -++ #define EMC_DMCR_RA_12 (1 << EMC_DMCR_RA_BIT) -++ #define EMC_DMCR_RA_13 (2 << EMC_DMCR_RA_BIT) -++#define EMC_DMCR_BA_BIT 19 -++#define EMC_DMCR_BA (1 << EMC_DMCR_BA_BIT) -++#define EMC_DMCR_PDM (1 << 18) -++#define EMC_DMCR_EPIN (1 << 17) -++#define EMC_DMCR_MBSEL (1 << 16) -++#define EMC_DMCR_TRAS_BIT 13 -++#define EMC_DMCR_TRAS_MASK (0x07 << EMC_DMCR_TRAS_BIT) -++#define EMC_DMCR_RCD_BIT 11 -++#define EMC_DMCR_RCD_MASK (0x03 << EMC_DMCR_RCD_BIT) -++#define EMC_DMCR_TPC_BIT 8 -++#define EMC_DMCR_TPC_MASK (0x07 << EMC_DMCR_TPC_BIT) -++#define EMC_DMCR_TRWL_BIT 5 -++#define EMC_DMCR_TRWL_MASK (0x03 << EMC_DMCR_TRWL_BIT) -++#define EMC_DMCR_TRC_BIT 2 -++#define EMC_DMCR_TRC_MASK (0x07 << EMC_DMCR_TRC_BIT) -++#define EMC_DMCR_TCL_BIT 0 -++#define EMC_DMCR_TCL_MASK (0x03 << EMC_DMCR_TCL_BIT) -++ -++/* Refresh Time Control/Status Register */ -++#define EMC_RTCSR_SFR (1 << 8) /* self refresh flag */ -++#define EMC_RTCSR_CMF (1 << 7) -++#define EMC_RTCSR_CKS_BIT 0 -++#define EMC_RTCSR_CKS_MASK (0x07 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_DISABLE (0 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_4 (1 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_16 (2 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_64 (3 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_256 (4 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_1024 (5 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_2048 (6 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_4096 (7 << EMC_RTCSR_CKS_BIT) -++ -++/* SDRAM Bank Address Configuration Register */ -++#define EMC_DMAR_BASE_BIT 8 -++#define EMC_DMAR_BASE_MASK (0xff << EMC_DMAR_BASE_BIT) -++#define EMC_DMAR_MASK_BIT 0 -++#define EMC_DMAR_MASK_MASK (0xff << EMC_DMAR_MASK_BIT) -++ -++/* Mode Register of SDRAM bank 0 */ -++#define EMC_SDMR_BM (1 << 9) /* Write Burst Mode */ -++#define EMC_SDMR_OM_BIT 7 /* Operating Mode */ -++#define EMC_SDMR_OM_MASK (3 << EMC_SDMR_OM_BIT) -++ #define EMC_SDMR_OM_NORMAL (0 << EMC_SDMR_OM_BIT) -++#define EMC_SDMR_CAS_BIT 4 /* CAS Latency */ -++#define EMC_SDMR_CAS_MASK (7 << EMC_SDMR_CAS_BIT) -++ #define EMC_SDMR_CAS_1 (1 << EMC_SDMR_CAS_BIT) -++ #define EMC_SDMR_CAS_2 (2 << EMC_SDMR_CAS_BIT) -++ #define EMC_SDMR_CAS_3 (3 << EMC_SDMR_CAS_BIT) -++#define EMC_SDMR_BT_BIT 3 /* Burst Type */ -++#define EMC_SDMR_BT_MASK (1 << EMC_SDMR_BT_BIT) -++ #define EMC_SDMR_BT_SEQ (0 << EMC_SDMR_BT_BIT) /* Sequential */ -++ #define EMC_SDMR_BT_INT (1 << EMC_SDMR_BT_BIT) /* Interleave */ -++#define EMC_SDMR_BL_BIT 0 /* Burst Length */ -++#define EMC_SDMR_BL_MASK (7 << EMC_SDMR_BL_BIT) -++ #define EMC_SDMR_BL_1 (0 << EMC_SDMR_BL_BIT) -++ #define EMC_SDMR_BL_2 (1 << EMC_SDMR_BL_BIT) -++ #define EMC_SDMR_BL_4 (2 << EMC_SDMR_BL_BIT) -++ #define EMC_SDMR_BL_8 (3 << EMC_SDMR_BL_BIT) -++ -++#define EMC_SDMR_CAS2_16BIT \ -++ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) -++#define EMC_SDMR_CAS2_32BIT \ -++ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) -++#define EMC_SDMR_CAS3_16BIT \ -++ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) -++#define EMC_SDMR_CAS3_32BIT \ -++ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) -++ -++ -++/************************************************************************* -++ * CIM -++ *************************************************************************/ -++#define CIM_CFG (CIM_BASE + 0x0000) -++#define CIM_CTRL (CIM_BASE + 0x0004) -++#define CIM_STATE (CIM_BASE + 0x0008) -++#define CIM_IID (CIM_BASE + 0x000C) -++#define CIM_RXFIFO (CIM_BASE + 0x0010) -++#define CIM_DA (CIM_BASE + 0x0020) -++#define CIM_FA (CIM_BASE + 0x0024) -++#define CIM_FID (CIM_BASE + 0x0028) -++#define CIM_CMD (CIM_BASE + 0x002C) -++#define CIM_SIZE (CIM_BASE + 0x0030) -++#define CIM_OFFSET (CIM_BASE + 0x0034) -++#define CIM_RAM_ADDR (CIM_BASE + 0x1000) -++ -++#define REG_CIM_CFG REG32(CIM_CFG) -++#define REG_CIM_CTRL REG32(CIM_CTRL) -++#define REG_CIM_STATE REG32(CIM_STATE) -++#define REG_CIM_IID REG32(CIM_IID) -++#define REG_CIM_RXFIFO REG32(CIM_RXFIFO) -++#define REG_CIM_DA REG32(CIM_DA) -++#define REG_CIM_FA REG32(CIM_FA) -++#define REG_CIM_FID REG32(CIM_FID) -++#define REG_CIM_CMD REG32(CIM_CMD) -++#define REG_CIM_SIZE REG32(CIM_SIZE) -++#define REG_CIM_OFFSET REG32(CIM_OFFSET) -++ -++/* CIM Configuration Register (CIM_CFG) */ -++ -++#define CIM_CFG_ORDER_BIT 18 -++#define CIM_CFG_ORDER_MASK (0x3 << CIM_CFG_ORDER_BIT) -++ #define CIM_CFG_ORDER_0 (0x0 << CIM_CFG_ORDER_BIT) -++ #define CIM_CFG_ORDER_1 (0x1 << CIM_CFG_ORDER_BIT) -++ #define CIM_CFG_ORDER_2 (0x2 << CIM_CFG_ORDER_BIT) -++ #define CIM_CFG_ORDER_3 (0x3 << CIM_CFG_ORDER_BIT) -++#define CIM_CFG_DF_BIT 16 -++#define CIM_CFG_DF_MASK (0x3 << CIM_CFG_DF_BIT) -++ #define CIM_CFG_DF_RGB (0x0 << CIM_CFG_DF_BIT) -++ #define CIM_CFG_DF_RAWRGB CIM_CFG_DF_RGB -++ #define CIM_CFG_DF_BAYERRGB CIM_CFG_DF_RGB -++ #define CIM_CFG_DF_YUV444 (0x1 << CIM_CFG_DF_BIT) -++ #define CIM_CFG_DF_YUV422 (0x2 << CIM_CFG_DF_BIT) -++ #define CIM_CFG_DF_ITU656 (0x3 << CIM_CFG_DF_BIT) -++#define CIM_CFG_INV_DAT (1 << 15) -++#define CIM_CFG_VSP (1 << 14) -++#define CIM_CFG_HSP (1 << 13) -++#define CIM_CFG_PCP (1 << 12) /* PCLK working edge */ -++#define CIM_CFG_DMA_BUSRT_TYPE_BIT 10 -++#define CIM_CFG_DMA_BUSRT_TYPE_MASK (0x3 << CIM_CFG_DMA_BUSRT_TYPE_BIT) -++#define CIM_CFG_DMA_BUSRT_INCR (0 << CIM_CFG_DMA_BUSRT_TYPE_BIT) -++#define CIM_CFG_DMA_BUSRT_INCR4 (1 << CIM_CFG_DMA_BUSRT_TYPE_BIT) -++#define CIM_CFG_DMA_BUSRT_INCR8 (2 << CIM_CFG_DMA_BUSRT_TYPE_BIT) -++#define CIM_CFG_DUMMY_ZERO (1 << 9) -++#define CIM_CFG_EXT_VSYNC (1 << 8) -++#define CIM_CFG_PACK_BIT 4 -++#define CIM_CFG_PACK_MASK (0x7 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_0 (0 << CIM_CFG_PACK_BIT) /* 11 22 33 44 */ -++ #define CIM_CFG_PACK_1 (1 << CIM_CFG_PACK_BIT) /* 22 33 44 11 */ -++ #define CIM_CFG_PACK_2 (2 << CIM_CFG_PACK_BIT) /* 33 44 11 22 */ -++ #define CIM_CFG_PACK_3 (3 << CIM_CFG_PACK_BIT) /* 44 11 22 33 */ -++ #define CIM_CFG_PACK_4 (4 << CIM_CFG_PACK_BIT) /* 44 33 22 11 */ -++ #define CIM_CFG_PACK_5 (5 << CIM_CFG_PACK_BIT) /* 33 22 11 44 */ -++ #define CIM_CFG_PACK_6 (6 << CIM_CFG_PACK_BIT) /* 22 11 44 33 */ -++ #define CIM_CFG_PACK_7 (7 << CIM_CFG_PACK_BIT) /* 11 44 33 22 */ -++#define CIM_CFG_BYPASS_BIT 2 -++#define CIM_CFG_BYPASS_MASK (1 << CIM_CFG_BYPASS_BIT) -++ #define CIM_CFG_BYPASS (1 << CIM_CFG_BYPASS_BIT) -++#define CIM_CFG_DSM_BIT 0 -++#define CIM_CFG_DSM_MASK (0x3 << CIM_CFG_DSM_BIT) -++ #define CIM_CFG_DSM_CPM (0 << CIM_CFG_DSM_BIT) /* CCIR656 Progressive Mode */ -++ #define CIM_CFG_DSM_CIM (1 << CIM_CFG_DSM_BIT) /* CCIR656 Interlace Mode */ -++ #define CIM_CFG_DSM_GCM (2 << CIM_CFG_DSM_BIT) /* Gated Clock Mode */ -++ #define CIM_CFG_DSM_NGCM (3 << CIM_CFG_DSM_BIT) /* Non-Gated Clock Mode */ -++ -++/* CIM Control Register (CIM_CTRL) */ -++ -++#define CIM_CTRL_MCLKDIV_BIT 24 -++#define CIM_CTRL_MCLKDIV_MASK (0xff << CIM_CTRL_MCLKDIV_BIT) -++#define CIM_CTRL_FRC_BIT 16 -++#define CIM_CTRL_FRC_MASK (0xf << CIM_CTRL_FRC_BIT) -++ #define CIM_CTRL_FRC_1 (0x0 << CIM_CTRL_FRC_BIT) /* Sample every frame */ -++ #define CIM_CTRL_FRC_2 (0x1 << CIM_CTRL_FRC_BIT) /* Sample 1/2 frame */ -++ #define CIM_CTRL_FRC_3 (0x2 << CIM_CTRL_FRC_BIT) /* Sample 1/3 frame */ -++ #define CIM_CTRL_FRC_4 (0x3 << CIM_CTRL_FRC_BIT) /* Sample 1/4 frame */ -++ #define CIM_CTRL_FRC_5 (0x4 << CIM_CTRL_FRC_BIT) /* Sample 1/5 frame */ -++ #define CIM_CTRL_FRC_6 (0x5 << CIM_CTRL_FRC_BIT) /* Sample 1/6 frame */ -++ #define CIM_CTRL_FRC_7 (0x6 << CIM_CTRL_FRC_BIT) /* Sample 1/7 frame */ -++ #define CIM_CTRL_FRC_8 (0x7 << CIM_CTRL_FRC_BIT) /* Sample 1/8 frame */ -++ #define CIM_CTRL_FRC_9 (0x8 << CIM_CTRL_FRC_BIT) /* Sample 1/9 frame */ -++ #define CIM_CTRL_FRC_10 (0x9 << CIM_CTRL_FRC_BIT) /* Sample 1/10 frame */ -++ #define CIM_CTRL_FRC_11 (0xA << CIM_CTRL_FRC_BIT) /* Sample 1/11 frame */ -++ #define CIM_CTRL_FRC_12 (0xB << CIM_CTRL_FRC_BIT) /* Sample 1/12 frame */ -++ #define CIM_CTRL_FRC_13 (0xC << CIM_CTRL_FRC_BIT) /* Sample 1/13 frame */ -++ #define CIM_CTRL_FRC_14 (0xD << CIM_CTRL_FRC_BIT) /* Sample 1/14 frame */ -++ #define CIM_CTRL_FRC_15 (0xE << CIM_CTRL_FRC_BIT) /* Sample 1/15 frame */ -++ #define CIM_CTRL_FRC_16 (0xF << CIM_CTRL_FRC_BIT) /* Sample 1/16 frame */ -++#define CIM_CTRL_SIZEEN_BIT 14 -++#define CIM_CTRL_SIZEEN_MASK (0x1 << CIM_CTRL_SIZEEN_BIT) -++#define CIM_CTRL_SIZEEN (0x1 << CIM_CTRL_SIZEEN_BIT) -++#define CIM_CTRL_VDDM (1 << 13) /* VDD interrupt enable */ -++#define CIM_CTRL_DMA_SOFM (1 << 12) -++#define CIM_CTRL_DMA_EOFM (1 << 11) -++#define CIM_CTRL_DMA_STOPM (1 << 10) -++#define CIM_CTRL_RXF_TRIGM (1 << 9) -++#define CIM_CTRL_RXF_OFM (1 << 8) -++#define CIM_CTRL_RXF_TRIG_BIT 4 -++#define CIM_CTRL_RXF_TRIG_MASK (0x7 << CIM_CTRL_RXF_TRIG_BIT) -++ #define CIM_CTRL_RXF_TRIG_4 (0 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 4 */ -++ #define CIM_CTRL_RXF_TRIG_8 (1 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 8 */ -++ #define CIM_CTRL_RXF_TRIG_12 (2 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 12 */ -++ #define CIM_CTRL_RXF_TRIG_16 (3 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 16 */ -++ #define CIM_CTRL_RXF_TRIG_20 (4 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 20 */ -++ #define CIM_CTRL_RXF_TRIG_24 (5 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 24 */ -++ #define CIM_CTRL_RXF_TRIG_28 (6 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 28 */ -++ #define CIM_CTRL_RXF_TRIG_32 (7 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 32 */ -++#define CIM_CTRL_FAST_MODE_MASK (1 << 3) /* CIM fast mode mask */ -++#define CIM_CTRL_FAST_MODE (1 << 3) /* CIM works in fast mode */ -++#define CIM_CTRL_NORMAL_MODE (0 << 3) /* CIM works in normal mode */ -++#define CIM_CTRL_DMA_EN (1 << 2) /* Enable DMA */ -++#define CIM_CTRL_RXF_RST (1 << 1) /* RxFIFO reset */ -++#define CIM_CTRL_ENA (1 << 0) /* Enable CIM */ -++ -++/* CIM State Register (CIM_STATE) */ -++ -++#define CIM_STATE_DMA_SOF (1 << 6) /* DMA start irq */ -++#define CIM_STATE_DMA_EOF (1 << 5) /* DMA end irq */ -++#define CIM_STATE_DMA_STOP (1 << 4) /* DMA stop irq */ -++#define CIM_STATE_RXF_OF (1 << 3) /* RXFIFO over flow irq */ -++#define CIM_STATE_RXF_TRIG (1 << 2) /* RXFIFO triger meet irq */ -++#define CIM_STATE_RXF_EMPTY (1 << 1) /* RXFIFO empty irq */ -++#define CIM_STATE_VDD (1 << 0) /* CIM disabled irq */ -++ -++/* CIM DMA Command Register (CIM_CMD) */ -++ -++#define CIM_CMD_SOFINT (1 << 31) /* enable DMA start irq */ -++#define CIM_CMD_EOFINT (1 << 30) /* enable DMA end irq */ -++#define CIM_CMD_STOP (1 << 28) /* enable DMA stop irq */ -++#define CIM_CMD_LEN_BIT 0 -++#define CIM_CMD_LEN_MASK (0xffffff << CIM_CMD_LEN_BIT) -++ -++/* CIM Image Size Register (CIM_SIZE) */ -++#define CIM_SIZE_LPF_BIT 16 /* Lines per freame for csc output image */ -++#define CIM_SIZE_LPF_MASK (0x1fff << CIM_SIZE_LPF_BIT) -++#define CIM_SIZE_PPL_BIT 0 /* Pixels per line for csc output image, should be an even number */ -++#define CIM_SIZE_PPL_MASK (0x1fff << CIM_SIZE_PPL_BIT) -++ -++/* CIM Image Offset Register (CIM_OFFSET) */ -++#define CIM_OFFSET_V_BIT 16 /* Vertical offset */ -++#define CIM_OFFSET_V_MASK (0xfff << CIM_OFFSET_V_BIT) -++#define CIM_OFFSET_H_BIT 0 /* Horizontal offset, should be an enen number */ -++#define CIM_OFFSET_H_MASK (0xfff << CIM_OFFSET_H_BIT) /*OFFSET_H should be even number*/ -++ -++/************************************************************************* -++ * SADC (Smart A/D Controller) -++ *************************************************************************/ -++ -++#define SADC_ENA (SADC_BASE + 0x00) /* ADC Enable Register */ -++#define SADC_CFG (SADC_BASE + 0x04) /* ADC Configure Register */ -++#define SADC_CTRL (SADC_BASE + 0x08) /* ADC Control Register */ -++#define SADC_STATE (SADC_BASE + 0x0C) /* ADC Status Register*/ -++#define SADC_SAMETIME (SADC_BASE + 0x10) /* ADC Same Point Time Register */ -++#define SADC_WAITTIME (SADC_BASE + 0x14) /* ADC Wait Time Register */ -++#define SADC_TSDAT (SADC_BASE + 0x18) /* ADC Touch Screen Data Register */ -++#define SADC_BATDAT (SADC_BASE + 0x1C) /* ADC PBAT Data Register */ -++#define SADC_SADDAT (SADC_BASE + 0x20) /* ADC SADCIN Data Register */ -++#define SADC_ADCLK (SADC_BASE + 0x28) /* ADC Clock Divide Register */ -++ -++#define REG_SADC_ENA REG8(SADC_ENA) -++#define REG_SADC_CFG REG32(SADC_CFG) -++#define REG_SADC_CTRL REG8(SADC_CTRL) -++#define REG_SADC_STATE REG8(SADC_STATE) -++#define REG_SADC_SAMETIME REG16(SADC_SAMETIME) -++#define REG_SADC_WAITTIME REG16(SADC_WAITTIME) -++#define REG_SADC_TSDAT REG32(SADC_TSDAT) -++#define REG_SADC_BATDAT REG16(SADC_BATDAT) -++#define REG_SADC_SADDAT REG16(SADC_SADDAT) -++#define REG_SADC_ADCLK REG32(SADC_ADCLK) -++ -++/* ADC Enable Register */ -++#define SADC_ENA_ADEN (1 << 7) /* Touch Screen Enable */ -++#define SADC_ENA_ENTR_SLP (1 << 6) /* Touch Screen Enable */ -++#define SADC_ENA_EXIT_SLP (1 << 5) /* Touch Screen Enable */ -++#define SADC_ENA_TSEN (1 << 2) /* Touch Screen Enable */ -++#define SADC_ENA_PBATEN (1 << 1) /* PBAT Enable */ -++#define SADC_ENA_SADCINEN (1 << 0) /* SADCIN Enable */ -++ -++/* ADC Configure Register */ -++#define SADC_CFG_EXIN (1 << 30) -++#define SADC_CFG_CLKOUT_NUM_BIT 16 -++#define SADC_CFG_CLKOUT_NUM_MASK (0x7 << SADC_CFG_CLKOUT_NUM_BIT) -++#define SADC_CFG_TS_DMA (1 << 15) /* Touch Screen DMA Enable */ -++#define SADC_CFG_XYZ_BIT 13 /* XYZ selection */ -++#define SADC_CFG_XYZ_MASK (0x3 << SADC_CFG_XYZ_BIT) -++ #define SADC_CFG_XY (0 << SADC_CFG_XYZ_BIT) -++ #define SADC_CFG_XYZ (1 << SADC_CFG_XYZ_BIT) -++ #define SADC_CFG_XYZ1Z2 (2 << SADC_CFG_XYZ_BIT) -++#define SADC_CFG_SNUM_BIT 10 /* Sample Number */ -++#define SADC_CFG_SNUM_MASK (0x7 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_1 (0x0 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_2 (0x1 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_3 (0x2 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_4 (0x3 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_5 (0x4 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_6 (0x5 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_8 (0x6 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_9 (0x7 << SADC_CFG_SNUM_BIT) -++#define SADC_CFG_CLKDIV_BIT 5 /* AD Converter frequency clock divider */ -++#define SADC_CFG_CLKDIV_MASK (0x1f << SADC_CFG_CLKDIV_BIT) -++#define SADC_CFG_PBAT_HIGH (0 << 4) /* PBAT >= 2.5V */ -++#define SADC_CFG_PBAT_LOW (1 << 4) /* PBAT < 2.5V */ -++#define SADC_CFG_CMD_BIT 0 /* ADC Command */ -++#define SADC_CFG_CMD_MASK (0xf << SADC_CFG_CMD_BIT) -++ #define SADC_CFG_CMD_X_SE (0x0 << SADC_CFG_CMD_BIT) /* X Single-End */ -++ #define SADC_CFG_CMD_Y_SE (0x1 << SADC_CFG_CMD_BIT) /* Y Single-End */ -++ #define SADC_CFG_CMD_X_DIFF (0x2 << SADC_CFG_CMD_BIT) /* X Differential */ -++ #define SADC_CFG_CMD_Y_DIFF (0x3 << SADC_CFG_CMD_BIT) /* Y Differential */ -++ #define SADC_CFG_CMD_Z1_DIFF (0x4 << SADC_CFG_CMD_BIT) /* Z1 Differential */ -++ #define SADC_CFG_CMD_Z2_DIFF (0x5 << SADC_CFG_CMD_BIT) /* Z2 Differential */ -++ #define SADC_CFG_CMD_Z3_DIFF (0x6 << SADC_CFG_CMD_BIT) /* Z3 Differential */ -++ #define SADC_CFG_CMD_Z4_DIFF (0x7 << SADC_CFG_CMD_BIT) /* Z4 Differential */ -++ #define SADC_CFG_CMD_TP_SE (0x8 << SADC_CFG_CMD_BIT) /* Touch Pressure */ -++ #define SADC_CFG_CMD_PBATH_SE (0x9 << SADC_CFG_CMD_BIT) /* PBAT >= 2.5V */ -++ #define SADC_CFG_CMD_PBATL_SE (0xa << SADC_CFG_CMD_BIT) /* PBAT < 2.5V */ -++ #define SADC_CFG_CMD_SADCIN_SE (0xb << SADC_CFG_CMD_BIT) /* Measure SADCIN */ -++ #define SADC_CFG_CMD_INT_PEN (0xc << SADC_CFG_CMD_BIT) /* INT_PEN Enable */ -++ -++/* ADC Control Register */ -++#define SADC_CTRL_SLPENDM (1 << 5) /* sleep Interrupt Mask */ -++#define SADC_CTRL_PENDM (1 << 4) /* Pen Down Interrupt Mask */ -++#define SADC_CTRL_PENUM (1 << 3) /* Pen Up Interrupt Mask */ -++#define SADC_CTRL_TSRDYM (1 << 2) /* Touch Screen Data Ready Interrupt Mask */ -++#define SADC_CTRL_PBATRDYM (1 << 1) /* PBAT Data Ready Interrupt Mask */ -++#define SADC_CTRL_SRDYM (1 << 0) /* SADCIN Data Ready Interrupt Mask */ -++ -++/* ADC Status Register */ -++#define SADC_STATE_SLEEPND (1 << 5) /* Pen Down Interrupt Flag */ -++#define SADC_STATE_PEND (1 << 4) /* Pen Down Interrupt Flag */ -++#define SADC_STATE_PENU (1 << 3) /* Pen Up Interrupt Flag */ -++#define SADC_STATE_TSRDY (1 << 2) /* Touch Screen Data Ready Interrupt Flag */ -++#define SADC_STATE_PBATRDY (1 << 1) /* PBAT Data Ready Interrupt Flag */ -++#define SADC_STATE_SRDY (1 << 0) /* SADCIN Data Ready Interrupt Flag */ -++ -++/* ADC Touch Screen Data Register */ -++#define SADC_TSDAT_DATA0_BIT 0 -++#define SADC_TSDAT_DATA0_MASK (0xfff << SADC_TSDAT_DATA0_BIT) -++#define SADC_TSDAT_TYPE0 (1 << 15) -++#define SADC_TSDAT_DATA1_BIT 16 -++#define SADC_TSDAT_DATA1_MASK (0xfff << SADC_TSDAT_DATA1_BIT) -++#define SADC_TSDAT_TYPE1 (1 << 31) -++ -++/* ADC Clock Divide Register */ -++#define SADC_ADCLK_CLKDIV_10_BIT 16 -++#define SADC_ADCLK_CLKDIV_10_MASK (0x7f << SADC_ADCLK_CLKDIV_10_BIT) -++#define SADC_ADCLK_CLKDIV_BIT 0 -++#define SADC_ADCLK_CLKDIV_MASK (0x3f << SADC_ADCLK_CLKDIV_BIT) -++ -++/************************************************************************* -++ * SLCD (Smart LCD Controller) -++ *************************************************************************/ -++ -++#define SLCD_CFG (SLCD_BASE + 0xA0) /* SLCD Configure Register */ -++#define SLCD_CTRL (SLCD_BASE + 0xA4) /* SLCD Control Register */ -++#define SLCD_STATE (SLCD_BASE + 0xA8) /* SLCD Status Register */ -++#define SLCD_DATA (SLCD_BASE + 0xAC) /* SLCD Data Register */ -++ -++#define REG_SLCD_CFG REG32(SLCD_CFG) -++#define REG_SLCD_CTRL REG8(SLCD_CTRL) -++#define REG_SLCD_STATE REG8(SLCD_STATE) -++#define REG_SLCD_DATA REG32(SLCD_DATA) -++ -++/* SLCD Configure Register */ -++#define SLCD_CFG_DWIDTH_BIT 10 -++#define SLCD_CFG_DWIDTH_MASK (0x7 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_18BIT (0 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_16BIT (1 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_8BIT_x3 (2 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_8BIT_x2 (3 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_8BIT_x1 (4 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_24BIT (5 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_9BIT_x2 (7 << SLCD_CFG_DWIDTH_BIT) -++#define SLCD_CFG_CWIDTH_BIT (8) -++#define SLCD_CFG_CWIDTH_MASK (0x7 << SLCD_CFG_CWIDTH_BIT) -++#define SLCD_CFG_CWIDTH_16BIT (0 << SLCD_CFG_CWIDTH_BIT) -++#define SLCD_CFG_CWIDTH_8BIT (1 << SLCD_CFG_CWIDTH_BIT) -++#define SLCD_CFG_CWIDTH_18BIT (2 << SLCD_CFG_CWIDTH_BIT) -++#define SLCD_CFG_CWIDTH_24BIT (3 << SLCD_CFG_CWIDTH_BIT) -++#define SLCD_CFG_CS_ACTIVE_LOW (0 << 4) -++#define SLCD_CFG_CS_ACTIVE_HIGH (1 << 4) -++#define SLCD_CFG_RS_CMD_LOW (0 << 3) -++#define SLCD_CFG_RS_CMD_HIGH (1 << 3) -++#define SLCD_CFG_CLK_ACTIVE_FALLING (0 << 1) -++#define SLCD_CFG_CLK_ACTIVE_RISING (1 << 1) -++#define SLCD_CFG_TYPE_PARALLEL (0 << 0) -++#define SLCD_CFG_TYPE_SERIAL (1 << 0) -++ -++/* SLCD Control Register */ -++#define SLCD_CTRL_DMA_EN (1 << 0) -++ -++/* SLCD Status Register */ -++#define SLCD_STATE_BUSY (1 << 0) -++ -++/* SLCD Data Register */ -++#define SLCD_DATA_RS_DATA (0 << 31) -++#define SLCD_DATA_RS_COMMAND (1 << 31) -++ -++/************************************************************************* -++ * LCD (LCD Controller) -++ *************************************************************************/ -++#define LCD_CFG (LCD_BASE + 0x00) /* LCD Configure Register */ -++#define LCD_CTRL (LCD_BASE + 0x30) /* LCD Control Register */ -++#define LCD_STATE (LCD_BASE + 0x34) /* LCD Status Register */ -++ -++#define LCD_OSDC (LCD_BASE + 0x100) /* LCD OSD Configure Register */ -++#define LCD_OSDCTRL (LCD_BASE + 0x104) /* LCD OSD Control Register */ -++#define LCD_OSDS (LCD_BASE + 0x108) /* LCD OSD Status Register */ -++#define LCD_BGC (LCD_BASE + 0x10C) /* LCD Background Color Register */ -++#define LCD_KEY0 (LCD_BASE + 0x110) /* LCD Foreground Color Key Register 0 */ -++#define LCD_KEY1 (LCD_BASE + 0x114) /* LCD Foreground Color Key Register 1 */ -++#define LCD_ALPHA (LCD_BASE + 0x118) /* LCD ALPHA Register */ -++#define LCD_IPUR (LCD_BASE + 0x11C) /* LCD IPU Restart Register */ -++ -++#define LCD_VAT (LCD_BASE + 0x0c) /* Virtual Area Setting Register */ -++#define LCD_DAH (LCD_BASE + 0x10) /* Display Area Horizontal Start/End Point */ -++#define LCD_DAV (LCD_BASE + 0x14) /* Display Area Vertical Start/End Point */ -++ -++#define LCD_XYP0 (LCD_BASE + 0x120) /* Foreground 0 XY Position Register */ -++#define LCD_XYP1 (LCD_BASE + 0x124) /* Foreground 1 XY Position Register */ -++#define LCD_SIZE0 (LCD_BASE + 0x128) /* Foreground 0 Size Register */ -++#define LCD_SIZE1 (LCD_BASE + 0x12C) /* Foreground 1 Size Register */ -++#define LCD_RGBC (LCD_BASE + 0x90) /* RGB Controll Register */ -++ -++#define LCD_VSYNC (LCD_BASE + 0x04) /* Vertical Synchronize Register */ -++#define LCD_HSYNC (LCD_BASE + 0x08) /* Horizontal Synchronize Register */ -++#define LCD_PS (LCD_BASE + 0x18) /* PS Signal Setting */ -++#define LCD_CLS (LCD_BASE + 0x1c) /* CLS Signal Setting */ -++#define LCD_SPL (LCD_BASE + 0x20) /* SPL Signal Setting */ -++#define LCD_REV (LCD_BASE + 0x24) /* REV Signal Setting */ -++#define LCD_IID (LCD_BASE + 0x38) /* Interrupt ID Register */ -++#define LCD_DA0 (LCD_BASE + 0x40) /* Descriptor Address Register 0 */ -++#define LCD_SA0 (LCD_BASE + 0x44) /* Source Address Register 0 */ -++#define LCD_FID0 (LCD_BASE + 0x48) /* Frame ID Register 0 */ -++#define LCD_CMD0 (LCD_BASE + 0x4c) /* DMA Command Register 0 */ -++#define LCD_DA1 (LCD_BASE + 0x50) /* Descriptor Address Register 1 */ -++#define LCD_SA1 (LCD_BASE + 0x54) /* Source Address Register 1 */ -++#define LCD_FID1 (LCD_BASE + 0x58) /* Frame ID Register 1 */ -++#define LCD_CMD1 (LCD_BASE + 0x5c) /* DMA Command Register 1 */ -++ -++#define LCD_OFFS0 (LCD_BASE + 0x60) /* DMA Offsize Register 0 */ -++#define LCD_PW0 (LCD_BASE + 0x64) /* DMA Page Width Register 0 */ -++#define LCD_CNUM0 (LCD_BASE + 0x68) /* DMA Command Counter Register 0 */ -++#define LCD_DESSIZE0 (LCD_BASE + 0x6C) /* Foreground Size in Descriptor 0 Register*/ -++#define LCD_OFFS1 (LCD_BASE + 0x70) /* DMA Offsize Register 1 */ -++#define LCD_PW1 (LCD_BASE + 0x74) /* DMA Page Width Register 1 */ -++#define LCD_CNUM1 (LCD_BASE + 0x78) /* DMA Command Counter Register 1 */ -++#define LCD_DESSIZE1 (LCD_BASE + 0x7C) /* Foreground Size in Descriptor 1 Register*/ -++ -++#define REG_LCD_CFG REG32(LCD_CFG) -++#define REG_LCD_CTRL REG32(LCD_CTRL) -++#define REG_LCD_STATE REG32(LCD_STATE) -++ -++#define REG_LCD_OSDC REG16(LCD_OSDC) -++#define REG_LCD_OSDCTRL REG16(LCD_OSDCTRL) -++#define REG_LCD_OSDS REG16(LCD_OSDS) -++#define REG_LCD_BGC REG32(LCD_BGC) -++#define REG_LCD_KEY0 REG32(LCD_KEY0) -++#define REG_LCD_KEY1 REG32(LCD_KEY1) -++#define REG_LCD_ALPHA REG8(LCD_ALPHA) -++#define REG_LCD_IPUR REG32(LCD_IPUR) -++ -++#define REG_LCD_VAT REG32(LCD_VAT) -++#define REG_LCD_DAH REG32(LCD_DAH) -++#define REG_LCD_DAV REG32(LCD_DAV) -++ -++#define REG_LCD_XYP0 REG32(LCD_XYP0) -++#define REG_LCD_XYP1 REG32(LCD_XYP1) -++#define REG_LCD_SIZE0 REG32(LCD_SIZE0) -++#define REG_LCD_SIZE1 REG32(LCD_SIZE1) -++#define REG_LCD_RGBC REG16(LCD_RGBC) -++ -++#define REG_LCD_VSYNC REG32(LCD_VSYNC) -++#define REG_LCD_HSYNC REG32(LCD_HSYNC) -++#define REG_LCD_PS REG32(LCD_PS) -++#define REG_LCD_CLS REG32(LCD_CLS) -++#define REG_LCD_SPL REG32(LCD_SPL) -++#define REG_LCD_REV REG32(LCD_REV) -++#define REG_LCD_IID REG32(LCD_IID) -++#define REG_LCD_DA0 REG32(LCD_DA0) -++#define REG_LCD_SA0 REG32(LCD_SA0) -++#define REG_LCD_FID0 REG32(LCD_FID0) -++#define REG_LCD_CMD0 REG32(LCD_CMD0) -++#define REG_LCD_DA1 REG32(LCD_DA1) -++#define REG_LCD_SA1 REG32(LCD_SA1) -++#define REG_LCD_FID1 REG32(LCD_FID1) -++#define REG_LCD_CMD1 REG32(LCD_CMD1) -++ -++#define REG_LCD_OFFS0 REG32(LCD_OFFS0) -++#define REG_LCD_PW0 REG32(LCD_PW0) -++#define REG_LCD_CNUM0 REG32(LCD_CNUM0) -++#define REG_LCD_DESSIZE0 REG32(LCD_DESSIZE0) -++#define REG_LCD_OFFS1 REG32(LCD_OFFS1) -++#define REG_LCD_PW1 REG32(LCD_PW1) -++#define REG_LCD_CNUM1 REG32(LCD_CNUM1) -++#define REG_LCD_DESSIZE1 REG32(LCD_DESSIZE1) -++ -++/* LCD Configure Register */ -++#define LCD_CFG_LCDPIN_BIT 31 /* LCD pins selection */ -++#define LCD_CFG_LCDPIN_MASK (0x1 << LCD_CFG_LCDPIN_BIT) -++ #define LCD_CFG_LCDPIN_LCD (0x0 << LCD_CFG_LCDPIN_BIT) -++ #define LCD_CFG_LCDPIN_SLCD (0x1 << LCD_CFG_LCDPIN_BIT) -++#define LCD_CFG_TVEPEH (1 << 30) /* TVE PAL enable extra halfline signal */ -++#define LCD_CFG_FUHOLD (1 << 29) /* hold pixel clock when outFIFO underrun */ -++#define LCD_CFG_NEWDES (1 << 28) /* use new descripter. old: 4words, new:8words */ -++#define LCD_CFG_PALBP (1 << 27) /* bypass data format and alpha blending */ -++#define LCD_CFG_TVEN (1 << 26) /* indicate the terminal is lcd or tv */ -++#define LCD_CFG_RECOVER (1 << 25) /* Auto recover when output fifo underrun */ -++#define LCD_CFG_DITHER (1 << 24) /* Dither function */ -++#define LCD_CFG_PSM (1 << 23) /* PS signal mode */ -++#define LCD_CFG_CLSM (1 << 22) /* CLS signal mode */ -++#define LCD_CFG_SPLM (1 << 21) /* SPL signal mode */ -++#define LCD_CFG_REVM (1 << 20) /* REV signal mode */ -++#define LCD_CFG_HSYNM (1 << 19) /* HSYNC signal mode */ -++#define LCD_CFG_PCLKM (1 << 18) /* PCLK signal mode */ -++#define LCD_CFG_INVDAT (1 << 17) /* Inverse output data */ -++#define LCD_CFG_SYNDIR_IN (1 << 16) /* VSYNC&HSYNC direction */ -++#define LCD_CFG_PSP (1 << 15) /* PS pin reset state */ -++#define LCD_CFG_CLSP (1 << 14) /* CLS pin reset state */ -++#define LCD_CFG_SPLP (1 << 13) /* SPL pin reset state */ -++#define LCD_CFG_REVP (1 << 12) /* REV pin reset state */ -++#define LCD_CFG_HSP (1 << 11) /* HSYNC polarity:0-active high,1-active low */ -++#define LCD_CFG_PCP (1 << 10) /* PCLK polarity:0-rising,1-falling */ -++#define LCD_CFG_DEP (1 << 9) /* DE polarity:0-active high,1-active low */ -++#define LCD_CFG_VSP (1 << 8) /* VSYNC polarity:0-rising,1-falling */ -++#define LCD_CFG_MODE_TFT_18BIT (1 << 7) /* 18bit TFT */ -++#define LCD_CFG_MODE_TFT_16BIT (0 << 7) /* 16bit TFT */ -++#define LCD_CFG_MODE_TFT_24BIT (1 << 6) /* 24bit TFT */ -++#define LCD_CFG_PDW_BIT 4 /* STN pins utilization */ -++#define LCD_CFG_PDW_MASK (0x3 << LCD_DEV_PDW_BIT) -++#define LCD_CFG_PDW_1 (0 << LCD_CFG_PDW_BIT) /* LCD_D[0] */ -++ #define LCD_CFG_PDW_2 (1 << LCD_CFG_PDW_BIT) /* LCD_D[0:1] */ -++ #define LCD_CFG_PDW_4 (2 << LCD_CFG_PDW_BIT) /* LCD_D[0:3]/LCD_D[8:11] */ -++ #define LCD_CFG_PDW_8 (3 << LCD_CFG_PDW_BIT) /* LCD_D[0:7]/LCD_D[8:15] */ -++#define LCD_CFG_MODE_BIT 0 /* Display Device Mode Select */ -++#define LCD_CFG_MODE_MASK (0x0f << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_GENERIC_TFT (0 << LCD_CFG_MODE_BIT) /* 16,18 bit TFT */ -++ #define LCD_CFG_MODE_SPECIAL_TFT_1 (1 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SPECIAL_TFT_2 (2 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SPECIAL_TFT_3 (3 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_NONINTER_CCIR656 (4 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_INTER_CCIR656 (6 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SINGLE_CSTN (8 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SINGLE_MSTN (9 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_DUAL_CSTN (10 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_DUAL_MSTN (11 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SERIAL_TFT (12 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_LCM (13 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SLCD LCD_CFG_MODE_LCM -++ -++/* LCD Control Register */ -++#define LCD_CTRL_BST_BIT 28 /* Burst Length Selection */ -++#define LCD_CTRL_BST_MASK (0x03 << LCD_CTRL_BST_BIT) -++ #define LCD_CTRL_BST_4 (0 << LCD_CTRL_BST_BIT) /* 4-word */ -++ #define LCD_CTRL_BST_8 (1 << LCD_CTRL_BST_BIT) /* 8-word */ -++ #define LCD_CTRL_BST_16 (2 << LCD_CTRL_BST_BIT) /* 16-word */ -++ #define LCD_CTRL_BST_32 (3 << LCD_CTRL_BST_BIT) /* 32-word */ -++#define LCD_CTRL_RGB565 (0 << 27) /* RGB565 mode(foreground 0 in OSD mode) */ -++#define LCD_CTRL_RGB555 (1 << 27) /* RGB555 mode(foreground 0 in OSD mode) */ -++#define LCD_CTRL_OFUP (1 << 26) /* Output FIFO underrun protection enable */ -++#define LCD_CTRL_FRC_BIT 24 /* STN FRC Algorithm Selection */ -++#define LCD_CTRL_FRC_MASK (0x03 << LCD_CTRL_FRC_BIT) -++ #define LCD_CTRL_FRC_16 (0 << LCD_CTRL_FRC_BIT) /* 16 grayscale */ -++ #define LCD_CTRL_FRC_4 (1 << LCD_CTRL_FRC_BIT) /* 4 grayscale */ -++ #define LCD_CTRL_FRC_2 (2 << LCD_CTRL_FRC_BIT) /* 2 grayscale */ -++#define LCD_CTRL_PDD_BIT 16 /* Load Palette Delay Counter */ -++#define LCD_CTRL_PDD_MASK (0xff << LCD_CTRL_PDD_BIT) -++#define LCD_CTRL_EOFM (1 << 13) /* EOF interrupt mask */ -++#define LCD_CTRL_SOFM (1 << 12) /* SOF interrupt mask */ -++#define LCD_CTRL_OFUM (1 << 11) /* Output FIFO underrun interrupt mask */ -++#define LCD_CTRL_IFUM0 (1 << 10) /* Input FIFO 0 underrun interrupt mask */ -++#define LCD_CTRL_IFUM1 (1 << 9) /* Input FIFO 1 underrun interrupt mask */ -++#define LCD_CTRL_LDDM (1 << 8) /* LCD disable done interrupt mask */ -++#define LCD_CTRL_QDM (1 << 7) /* LCD quick disable done interrupt mask */ -++#define LCD_CTRL_BEDN (1 << 6) /* Endian selection */ -++#define LCD_CTRL_PEDN (1 << 5) /* Endian in byte:0-msb first, 1-lsb first */ -++#define LCD_CTRL_DIS (1 << 4) /* Disable indicate bit */ -++#define LCD_CTRL_ENA (1 << 3) /* LCD enable bit */ -++#define LCD_CTRL_BPP_BIT 0 /* Bits Per Pixel */ -++#define LCD_CTRL_BPP_MASK (0x07 << LCD_CTRL_BPP_BIT) -++ #define LCD_CTRL_BPP_1 (0 << LCD_CTRL_BPP_BIT) /* 1 bpp */ -++ #define LCD_CTRL_BPP_2 (1 << LCD_CTRL_BPP_BIT) /* 2 bpp */ -++ #define LCD_CTRL_BPP_4 (2 << LCD_CTRL_BPP_BIT) /* 4 bpp */ -++ #define LCD_CTRL_BPP_8 (3 << LCD_CTRL_BPP_BIT) /* 8 bpp */ -++ #define LCD_CTRL_BPP_16 (4 << LCD_CTRL_BPP_BIT) /* 15/16 bpp */ -++ #define LCD_CTRL_BPP_18_24 (5 << LCD_CTRL_BPP_BIT) /* 18/24/32 bpp */ -++ -++/* LCD Status Register */ -++#define LCD_STATE_QD (1 << 7) /* Quick Disable Done */ -++#define LCD_STATE_EOF (1 << 5) /* EOF Flag */ -++#define LCD_STATE_SOF (1 << 4) /* SOF Flag */ -++#define LCD_STATE_OFU (1 << 3) /* Output FIFO Underrun */ -++#define LCD_STATE_IFU0 (1 << 2) /* Input FIFO 0 Underrun */ -++#define LCD_STATE_IFU1 (1 << 1) /* Input FIFO 1 Underrun */ -++#define LCD_STATE_LDD (1 << 0) /* LCD Disabled */ -++ -++/* OSD Configure Register */ -++#define LCD_OSDC_SOFM1 (1 << 15) /* Start of frame interrupt mask for foreground 1 */ -++#define LCD_OSDC_EOFM1 (1 << 14) /* End of frame interrupt mask for foreground 1 */ -++#define LCD_OSDC_REM1 (1 << 13) /* Real end of frame mask for foreground 1 */ -++#define LCD_OSDC_SOFM0 (1 << 11) /* Start of frame interrupt mask for foreground 0 */ -++#define LCD_OSDC_EOFM0 (1 << 10) /* End of frame interrupt mask for foreground 0 */ -++#define LCD_OSDC_REM0 (1 << 9) /* Real end of frame mask for foreground 0 */ -++#define LCD_OSDC_REMB (1 << 7) /* Real end of frame mask for background */ -++#define LCD_OSDC_F1EN (1 << 4) /* enable foreground 1 */ -++#define LCD_OSDC_F0EN (1 << 3) /* enable foreground 0 */ -++#define LCD_OSDC_ALPHAEN (1 << 2) /* enable alpha blending */ -++#define LCD_OSDC_ALPHAMD (1 << 1) /* alpha blending mode */ -++#define LCD_OSDC_OSDEN (1 << 0) /* OSD mode enable */ -++ -++/* OSD Controll Register */ -++#define LCD_OSDCTRL_IPU (1 << 15) /* input data from IPU */ -++#define LCD_OSDCTRL_RGB565 (0 << 4) /* foreground 1, 16bpp, 0-RGB565, 1-RGB555 */ -++#define LCD_OSDCTRL_RGB555 (1 << 4) /* foreground 1, 16bpp, 0-RGB565, 1-RGB555 */ -++#define LCD_OSDCTRL_CHANGES (1 << 3) /* Change size flag */ -++#define LCD_OSDCTRL_OSDBPP_BIT 0 /* Bits Per Pixel of OSD Channel 1 */ -++#define LCD_OSDCTRL_OSDBPP_MASK (0x7< -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_BOARD_SERIAL_H__ -++#define __ASM_BOARD_SERIAL_H__ -++ -++#ifndef CONFIG_SERIAL_MANY_PORTS -++#undef RS_TABLE_SIZE -++#define RS_TABLE_SIZE 1 -++#endif -++ -++#define JZ_BASE_BAUD (12000000/16) -++ -++#define JZ_SERIAL_PORT_DEFNS \ -++ { .baud_base = JZ_BASE_BAUD, .irq = IRQ_UART0, \ -++ .flags = STD_COM_FLAGS, .iomem_base = (u8 *)UART0_BASE, \ -++ .iomem_reg_shift = 2, .io_type = SERIAL_IO_MEM }, -++ -++#endif /* __ASM_BORAD_SERIAL_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4750/war.h linux-2.6.24.7/include/asm-mips/mach-jz4750/war.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4750/war.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4750/war.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,25 @@ -++/* -++ * This file is subject to the terms and conditions of the GNU General Public -++ * License. See the file "COPYING" in the main directory of this archive -++ * for more details. -++ * -++ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle -++ */ -++#ifndef __ASM_MIPS_MACH_JZ4740_WAR_H -++#define __ASM_MIPS_MACH_JZ4740_WAR_H -++ -++#define R4600_V1_INDEX_ICACHEOP_WAR 0 -++#define R4600_V1_HIT_CACHEOP_WAR 0 -++#define R4600_V2_HIT_CACHEOP_WAR 0 -++#define R5432_CP0_INTERRUPT_WAR 0 -++#define BCM1250_M3_WAR 0 -++#define SIBYTE_1956_WAR 0 -++#define MIPS4K_ICACHE_REFILL_WAR 0 -++#define MIPS_CACHE_SYNC_WAR 0 -++#define TX49XX_ICACHE_INDEX_INV_WAR 0 -++#define RM9000_CDEX_SMP_WAR 0 -++#define ICACHE_REFILLS_WORKAROUND_WAR 0 -++#define R10000_LLSC_WAR 0 -++#define MIPS34K_MISSED_ITLB_WAR 0 -++ -++#endif /* __ASM_MIPS_MACH_JZ4740_WAR_H */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4750d/board-fuwa1.h linux-2.6.24.7/include/asm-mips/mach-jz4750d/board-fuwa1.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4750d/board-fuwa1.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4750d/board-fuwa1.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,124 @@ -++/* -++ * linux/include/asm-mips/mach-jz4750d/board-fuwa1.h -++ * -++ * JZ4750D-based FUWA1 board ver 1.x definition. -++ * -++ * Copyright (C) 2008 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4750D_FUWA1_H__ -++#define __ASM_JZ4750D_FUWA1_H__ -++ -++#define CONFIG_FPGA /* fuwa is an FPGA board */ -++ -++/*====================================================================== -++ * Frequencies of on-board oscillators -++ */ -++#define JZ_EXTAL 48000000 /* Main extal freq: 12 MHz */ -++#define JZ_EXTAL2 32768 /* RTC extal freq: 32.768 KHz */ -++#define CFG_DIV 1 /* hclk=pclk=mclk=CFG_EXTAL/CFG_DIV, just for FPGA board */ -++ -++ -++/*====================================================================== -++ * GPIO -++ */ -++#define GPIO_SD0_VCC_EN_N (32*2+10) /* GPC10 */ -++#define GPIO_SD0_CD_N (32*2+11) /* GPC11 */ -++#define GPIO_SD0_WP (32*2+12) /* GPC12 */ -++#define GPIO_SD1_VCC_EN_N (32*2+13) /* GPC13 */ -++#define GPIO_SD1_CD_N (32*2+14) /* GPC14 */ -++#define GPIO_USB_DETE 102 /* GPD6 */ -++#define GPIO_DC_DETE_N 103 /* GPD7 */ -++#define GPIO_CHARG_STAT_N 111 /* GPD15 */ -++#define GPIO_DISP_OFF_N 121 /* GPD25, LCD_REV */ -++//#define GPIO_LED_EN 124 /* GPD28 */ -++ -++#define GPIO_UDC_HOTPLUG GPIO_USB_DETE -++ -++/*====================================================================== -++ * LCD backlight -++ */ -++#define GPIO_LCD_PWM (32*4+20) /* GPE20 */ -++ -++#define LCD_PWM_CHN 0 /* pwm channel */ -++#define LCD_PWM_FULL 101 -++/* 100 level: 0,1,...,100 */ -++#define __lcd_set_backlight_level(n) \ -++do { \ -++ __gpio_as_output(GPIO_LCD_PWM); \ -++ __gpio_set_pin(GPIO_LCD_PWM); \ -++} while (0) -++ -++#define __lcd_close_backlight() \ -++do { \ -++ __gpio_as_output(GPIO_LCD_PWM); \ -++ __gpio_clear_pin(GPIO_LCD_PWM); \ -++} while (0) -++ -++/*====================================================================== -++ * MMC/SD -++ */ -++ -++#define MSC0_WP_PIN GPIO_SD0_WP -++#define MSC0_HOTPLUG_PIN GPIO_SD0_CD_N -++#define MSC0_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD0_CD_N) -++ -++#define MSC1_WP_PIN GPIO_SD1_WP -++#define MSC1_HOTPLUG_PIN GPIO_SD1_CD_N -++#define MSC1_HOTPLUG_IRQ (IRQ_GPIO_0 + GPIO_SD1_CD_N) -++ -++#define __msc0_init_io() \ -++do { \ -++ __gpio_as_output(GPIO_SD0_VCC_EN_N); \ -++ __gpio_as_input(GPIO_SD0_CD_N); \ -++} while (0) -++ -++#define __msc0_enable_power() \ -++do { \ -++ __gpio_clear_pin(GPIO_SD0_VCC_EN_N); \ -++} while (0) -++ -++#define __msc0_disable_power() \ -++do { \ -++ __gpio_set_pin(GPIO_SD0_VCC_EN_N); \ -++} while (0) -++ -++#define __msc0_card_detected(s) \ -++({ \ -++ int detected = 1; \ -++ if (__gpio_get_pin(GPIO_SD0_CD_N)) \ -++ detected = 0; \ -++ detected; \ -++}) -++ -++#define __msc1_init_io() \ -++do { \ -++ /* __gpio_as_output(GPIO_SD1_VCC_EN_N);*/ \ -++ /* __gpio_as_input(GPIO_SD1_CD_N);*/ \ -++} while (0) -++ -++#define __msc1_enable_power() \ -++do { \ -++ /* __gpio_clear_pin(GPIO_SD1_VCC_EN_N);*/ \ -++} while (0) -++ -++#define __msc1_disable_power() \ -++do { \ -++ /* __gpio_set_pin(GPIO_SD1_VCC_EN_N);*/ \ -++} while (0) -++ -++#define __msc1_card_detected(s) \ -++({ \ -++ int detected = 0; \ -++ if (__gpio_get_pin(GPIO_SD1_CD_N)) \ -++ detected = 1; \ -++ detected; \ -++}) -++ -++#endif /* __ASM_JZ4750d_FUWA1_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4750d/clock.h linux-2.6.24.7/include/asm-mips/mach-jz4750d/clock.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4750d/clock.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4750d/clock.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,230 @@ -++/* -++ * linux/include/asm-mips/mach-jz4750d/clock.h -++ * -++ * JZ4750D clocks definition. -++ * -++ * Copyright (C) 2008 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4750D_CLOCK_H__ -++#define __ASM_JZ4750D_CLOCK_H__ -++ -++#ifndef JZ_EXTAL -++#define JZ_EXTAL 12000000 /* 3.6864 MHz */ -++#endif -++#ifndef JZ_EXTAL2 -++#define JZ_EXTAL2 32768 /* 32.768 KHz */ -++#endif -++ -++/* -++ * JZ4750D clocks structure -++ */ -++typedef struct { -++ unsigned int cclk; /* CPU clock */ -++ unsigned int hclk; /* System bus clock */ -++ unsigned int pclk; /* Peripheral bus clock */ -++ unsigned int mclk; /* Flash/SRAM/SDRAM clock */ -++ unsigned int lcdclk; /* LCDC module clock */ -++ unsigned int pixclk; /* LCD pixel clock */ -++ unsigned int i2sclk; /* AIC module clock */ -++ unsigned int usbclk; /* USB module clock */ -++ unsigned int mscclk; /* MSC module clock */ -++ unsigned int extalclk; /* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */ -++ unsigned int rtcclk; /* RTC clock for CPM,INTC,RTC,TCU,WDT */ -++} jz_clocks_t; -++ -++extern jz_clocks_t jz_clocks; -++ -++ -++/* PLL output frequency */ -++static __inline__ unsigned int __cpm_get_pllout(void) -++{ -++#if defined(CONFIG_FPGA) -++ return JZ_EXTAL/CFG_DIV; -++#else -++ unsigned long m, n, no, pllout; -++ unsigned long cppcr = REG_CPM_CPPCR; -++ unsigned long od[4] = {1, 2, 2, 4}; -++ if ((cppcr & CPM_CPPCR_PLLEN) && !(cppcr & CPM_CPPCR_PLLBP)) { -++ m = __cpm_get_pllm() + 2; -++ n = __cpm_get_plln() + 2; -++ no = od[__cpm_get_pllod()]; -++ pllout = ((JZ_EXTAL) / (n * no)) * m; -++ } else -++ pllout = JZ_EXTAL; -++ return pllout; -++#endif -++} -++ -++/* PLL output frequency for MSC/I2S/LCD/USB */ -++static __inline__ unsigned int __cpm_get_pllout2(void) -++{ -++#if defined(CONFIG_FPGA) -++ return JZ_EXTAL/CFG_DIV; -++#else -++ if (REG_CPM_CPCCR & CPM_CPCCR_PCS) -++ return __cpm_get_pllout(); -++ else -++ return __cpm_get_pllout()/2; -++#endif -++} -++ -++/* CPU core clock */ -++static __inline__ unsigned int __cpm_get_cclk(void) -++{ -++ -++#if defined(CONFIG_FGPA) -++ return JZ_EXTAL; -++#else -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ return __cpm_get_pllout() / div[__cpm_get_cdiv()]; -++#endif -++} -++ -++/* AHB system bus clock */ -++static __inline__ unsigned int __cpm_get_hclk(void) -++{ -++#if defined(CONFIG_FPGA) -++ return JZ_EXTAL/CFG_DIV; -++#else -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ -++ return __cpm_get_pllout() / div[__cpm_get_hdiv()]; -++#endif -++ -++} -++ -++/* Memory bus clock */ -++static __inline__ unsigned int __cpm_get_mclk(void) -++{ -++#if defined(CONFIG_FPGA) -++ return JZ_EXTAL/CFG_DIV; -++#else -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ -++ return __cpm_get_pllout() / div[__cpm_get_mdiv()]; -++#endif -++} -++ -++/* APB peripheral bus clock */ -++static __inline__ unsigned int __cpm_get_pclk(void) -++{ -++#if defined(CONFIG_FPGA) -++ return JZ_EXTAL/CFG_DIV; -++#else -++ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; -++ -++ return __cpm_get_pllout() / div[__cpm_get_pdiv()]; -++#endif -++} -++ -++/* LCDC module clock */ -++static __inline__ unsigned int __cpm_get_lcdclk(void) -++{ -++ return __cpm_get_pllout2() / (__cpm_get_ldiv() + 1); -++} -++ -++/* LCD pixel clock */ -++static __inline__ unsigned int __cpm_get_pixclk(void) -++{ -++ return __cpm_get_pllout2() / (__cpm_get_pixdiv() + 1); -++} -++ -++/* I2S clock */ -++static __inline__ unsigned int __cpm_get_i2sclk(void) -++{ -++ if (REG_CPM_CPCCR & CPM_CPCCR_I2CS) { -++ return __cpm_get_pllout2() / (__cpm_get_i2sdiv() + 1); -++ } -++ else { -++ return JZ_EXTAL; -++ } -++} -++ -++/* USB clock */ -++static __inline__ unsigned int __cpm_get_usbclk(void) -++{ -++ if (REG_CPM_CPCCR & CPM_CPCCR_UCS) { -++ return __cpm_get_pllout2() / (__cpm_get_udiv() + 1); -++ } -++ else { -++ return JZ_EXTAL; -++ } -++} -++ -++/* -++ * MSC clock -++ * @n: the index of MMC/SD controller -++ */ -++static __inline__ unsigned int __cpm_get_mscclk(int n) -++{ -++ return __cpm_get_pllout2() / (__cpm_get_mscdiv(n) + 1); -++} -++ -++/* EXTAL clock */ -++static __inline__ unsigned int __cpm_get_extalclk0(void) -++{ -++ return JZ_EXTAL; -++} -++ -++/* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */ -++static __inline__ unsigned int __cpm_get_extalclk(void) -++{ -++#if defined(CONFIG_FPGA) -++ return __cpm_get_pllout(); -++#else -++ if (REG_CPM_CPCCR & CPM_CPCCR_ECS) -++ return __cpm_get_extalclk0()/2; -++ else -++ return __cpm_get_extalclk0(); -++#endif -++ -++} -++ -++/* RTC clock for CPM,INTC,RTC,TCU,WDT */ -++static __inline__ unsigned int __cpm_get_rtcclk(void) -++{ -++ return JZ_EXTAL2; -++} -++ -++/* -++ * Output 24MHz for SD and 16MHz for MMC. -++ * @n: the index of MMC/SD controller -++ */ -++static inline void __cpm_select_msc_clk(int n, int sd) -++{ -++ unsigned int pllout2 = __cpm_get_pllout2(); -++ unsigned int div = 0; -++ -++ if (sd) { -++ div = pllout2 / 24000000; -++ } -++ else { -++ div = pllout2 / 16000000; -++ } -++ -++ REG_CPM_MSCCDR(n) = div - 1; -++ REG_CPM_CPCCR |= CPM_CPCCR_CE; -++} -++ -++/* -++ * Output 48MHz for high speed card. -++ */ -++static inline void __cpm_select_msc_clk_high(int n, int sd) -++{ -++ unsigned int pllout2 = __cpm_get_pllout2(); -++ unsigned int div = 0; -++ -++ div = pllout2 / 48000000; -++ -++ REG_CPM_MSCCDR(n) = div - 1; -++ REG_CPM_CPCCR |= CPM_CPCCR_CE; -++} -++ -++#endif /* __ASM_JZ4750D_CLOCK_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4750d/dma.h linux-2.6.24.7/include/asm-mips/mach-jz4750d/dma.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4750d/dma.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4750d/dma.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,307 @@ -++/* -++ * linux/include/asm-mips/mach-jz4750d/dma.h -++ * -++ * JZ4750D DMA definition. -++ * -++ * Copyright (C) 2008 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4750D_DMA_H__ -++#define __ASM_JZ4750D_DMA_H__ -++ -++#include -++#include /* need byte IO */ -++#include /* And spinlocks */ -++#include -++#include -++ -++/* -++ * Descriptor structure for JZ4750D DMA engine -++ * Note: this structure must always be aligned to a 16-bytes boundary. -++ */ -++ -++/* old descriptor 4-word */ -++typedef struct { -++ volatile u32 dcmd; /* DCMD value for the current transfer */ -++ volatile u32 dsadr; /* DSAR value for the current transfer */ -++ volatile u32 dtadr; /* DTAR value for the current transfer */ -++ volatile u32 ddadr; /* Points to the next descriptor + transfer count */ -++} jz_dma_desc; -++ -++/* new descriptor 8-word */ -++typedef struct { -++ volatile u32 dcmd; /* DCMD value for the current transfer */ -++ volatile u32 dsadr; /* DSAR value for the current transfer */ -++ volatile u32 dtadr; /* DTAR value for the current transfer */ -++ volatile u32 ddadr; /* Points to the next descriptor + transfer count */ -++ volatile u32 dstrd; /* DMA source and target stride address */ -++ volatile u32 dreqt; /* DMA request type for current transfer */ -++ volatile u32 reserved0; /* Reserved */ -++ volatile u32 reserved1; /* Reserved */ -++} jz_dma_desc_8word; -++ -++/* DMA Device ID's follow */ -++enum { -++ DMA_ID_EXT = 0, /* External request with DREQn */ -++ DMA_ID_NAND, /* NAND DMA request */ -++ DMA_ID_BCH_ENC, /* BCH Encoding DMA request */ -++ DMA_ID_BCH_DEC, /* BCH Decoding DMA request */ -++ DMA_ID_AUTO, /* Auto-request */ -++// DMA_ID_TSSI_RX, /* TSSI receive fifo full request */ -++ DMA_ID_UART3_TX, /* UART3 transmit-fifo-empty request */ -++ DMA_ID_UART3_RX, /* UART3 receve-fifo-full request */ -++ DMA_ID_UART2_TX, /* UART2 transmit-fifo-empty request */ -++ DMA_ID_UART2_RX, /* UART2 receve-fifo-full request */ -++ DMA_ID_UART1_TX, /* UART1 transmit-fifo-empty request */ -++ DMA_ID_UART1_RX, /* UART1 receve-fifo-full request */ -++ DMA_ID_UART0_TX, /* UART0 transmit-fifo-empty request */ -++ DMA_ID_UART0_RX, /* UART0 receve-fifo-full request */ -++ DMA_ID_SSI0_TX, /* SSI0 transmit-fifo-full request */ -++ DMA_ID_SSI0_RX, /* SSI0 receive-fifo-empty request */ -++ DMA_ID_AIC_TX, /* AIC transmit-fifo-full request */ -++ DMA_ID_AIC_RX, /* AIC receive-fifo-empty request */ -++ DMA_ID_MSC0_TX, /* MSC0 transmit-fifo-full request */ -++ DMA_ID_MSC0_RX, /* MSC0 receive-fifo-empty request */ -++ DMA_ID_TCU_OVERFLOW, /* TCU channel n overflow interrupt */ -++ DMA_ID_SADC, /* SADC transfer request */ -++ DMA_ID_MSC1_TX, /* MSC1 transmit-fifo-full request */ -++ DMA_ID_MSC1_RX, /* MSC1 receive-fifo-empty request */ -++ DMA_ID_SSI1_TX, /* SSI1 transmit-fifo-full request */ -++ DMA_ID_SSI1_RX, /* SSI1 receive-fifo-empty request */ -++ DMA_ID_PCM_TX, /* PM transmit-fifo-full request */ -++ DMA_ID_PCM_RX, /* PM receive-fifo-empty request */ -++ DMA_ID_RAW_SET, -++ DMA_ID_MAX -++}; -++ -++/* DMA modes, simulated by sw */ -++#define DMA_MODE_READ 0x0 /* I/O to memory, no autoinit, increment, single mode */ -++#define DMA_MODE_WRITE 0x1 /* memory to I/O, no autoinit, increment, single mode */ -++#define DMA_AUTOINIT 0x2 -++#define DMA_MODE_MASK 0x3 -++ -++struct jz_dma_chan { -++ int dev_id; /* DMA ID: this channel is allocated if >=0, free otherwise */ -++ unsigned int io; /* DMA channel number */ -++ const char *dev_str; /* string describes the DMA channel */ -++ int irq; /* DMA irq number */ -++ void *irq_dev; /* DMA private device structure */ -++ unsigned int fifo_addr; /* physical fifo address of the requested device */ -++ unsigned int cntl; /* DMA controll */ -++ unsigned int mode; /* DMA configuration */ -++ unsigned int source; /* DMA request source */ -++}; -++ -++extern struct jz_dma_chan jz_dma_table[]; -++ -++ -++#define DMA_8BIT_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_8BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_8BIT_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -++ DMAC_DCMD_DS_8BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_16BIT_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_16BIT_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_32BIT_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_32BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_32BIT_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_32BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_16BYTE_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_16BYTE_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_32BYTE_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_32BYTE_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \ -++ DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_32_32BYTE_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN -++#define DMA_AIC_32_16BYTE_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_32_16BYTE_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_16BIT_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_16BIT_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_16BYTE_RX_CMD \ -++ DMAC_DCMD_DAI | \ -++ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_16BYTE_TX_CMD \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++#define DMA_AIC_16BYTE_TX_CMD_UC \ -++ DMAC_DCMD_SAI | \ -++ DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_16 | \ -++ DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN -++ -++extern int jz_request_dma(int dev_id, -++ const char *dev_str, -++ irqreturn_t (*irqhandler)(int, void *), -++ unsigned long irqflags, -++ void *irq_dev_id); -++extern void jz_free_dma(unsigned int dmanr); -++ -++extern int jz_dma_read_proc(char *buf, char **start, off_t fpos, -++ int length, int *eof, void *data); -++extern void dump_jz_dma_channel(unsigned int dmanr); -++ -++extern void enable_dma(unsigned int dmanr); -++extern void disable_dma(unsigned int dmanr); -++extern void set_dma_addr(unsigned int dmanr, unsigned int phyaddr); -++extern void set_dma_count(unsigned int dmanr, unsigned int bytecnt); -++extern void set_dma_mode(unsigned int dmanr, unsigned int mode); -++extern void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); -++extern void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); -++extern void jz_set_dma_src_width(int dmanr, int nbit); -++extern void jz_set_dma_dest_width(int dmanr, int nbit); -++extern void jz_set_dma_block_size(int dmanr, int nbyte); -++extern unsigned int get_dma_residue(unsigned int dmanr); -++ -++extern spinlock_t dma_spin_lock; -++ -++static __inline__ unsigned long claim_dma_lock(void) -++{ -++ unsigned long flags; -++ spin_lock_irqsave(&dma_spin_lock, flags); -++ return flags; -++} -++ -++static __inline__ void release_dma_lock(unsigned long flags) -++{ -++ spin_unlock_irqrestore(&dma_spin_lock, flags); -++} -++ -++/* Clear the 'DMA Pointer Flip Flop'. -++ * Write 0 for LSB/MSB, 1 for MSB/LSB access. -++ */ -++#define clear_dma_ff(channel) -++ -++static __inline__ struct jz_dma_chan *get_dma_chan(unsigned int dmanr) -++{ -++ if (dmanr > MAX_DMA_NUM -++ || jz_dma_table[dmanr].dev_id < 0) -++ return NULL; -++ return &jz_dma_table[dmanr]; -++} -++ -++static __inline__ int dma_halted(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return 1; -++ return __dmac_channel_transmit_halt_detected(dmanr) ? 1 : 0; -++} -++ -++static __inline__ unsigned int get_dma_mode(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return 0; -++ return chan->mode; -++} -++ -++static __inline__ void clear_dma_done(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -++} -++ -++static __inline__ void clear_dma_halt(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT); -++ REG_DMAC_DMACR((chan->io)/HALF_DMA_NUM) &= ~(DMAC_DMACR_HLT); -++} -++ -++static __inline__ void clear_dma_flag(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return; -++ REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -++ REG_DMAC_DMACR((chan->io)/HALF_DMA_NUM) &= ~(DMAC_DMACR_HLT | DMAC_DMACR_AR); -++} -++ -++static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) -++{ -++} -++ -++static __inline__ unsigned int get_dma_done_status(unsigned int dmanr) -++{ -++ unsigned long dccsr; -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return 0; -++ dccsr = REG_DMAC_DCCSR(chan->io); -++ return dccsr & (DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR); -++} -++ -++static __inline__ int get_dma_done_irq(unsigned int dmanr) -++{ -++ struct jz_dma_chan *chan = get_dma_chan(dmanr); -++ if (!chan) -++ return -1; -++ return chan->irq; -++} -++ -++#endif /* __ASM_JZ4750D_DMA_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4750d/jz4750d.h linux-2.6.24.7/include/asm-mips/mach-jz4750d/jz4750d.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4750d/jz4750d.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4750d/jz4750d.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,40 @@ -++/* -++ * linux/include/asm-mips/mach-jz4750d/jz4750d.h -++ * -++ * JZ4750 common definition. -++ * -++ * Copyright (C) 2008 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4750_H__ -++#define __ASM_JZ4750_H__ -++ -++#include -++#include -++#include -++#include -++ -++/*------------------------------------------------------------------ -++ * Platform definitions -++ */ -++#ifdef CONFIG_JZ4750D_FUWA1 -++#include -++#endif -++ -++/* Add other platform definition here ... */ -++ -++ -++/*------------------------------------------------------------------ -++ * Follows are related to platform definitions -++ */ -++ -++#include -++#include -++ -++#endif /* __ASM_JZ4750_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4750d/misc.h linux-2.6.24.7/include/asm-mips/mach-jz4750d/misc.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4750d/misc.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4750d/misc.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,44 @@ -++/* -++ * linux/include/asm-mips/mach-jz4750d/misc.h -++ * -++ * Ingenic's JZ4750D common include. -++ * -++ * Copyright (C) 2008 Ingenic Semiconductor Inc. -++ * -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_JZ4750D_MISC_H__ -++#define __ASM_JZ4750D_MISC_H__ -++ -++/*========================================================== -++ * I2C -++ *===========================================================*/ -++ -++#define I2C_EEPROM_DEV 0xA /* b'1010 */ -++#define I2C_RTC_DEV 0xD /* b'1101 */ -++#define DIMM0_SPD_ADDR 0 -++#define DIMM1_SPD_ADDR 1 -++#define DIMM2_SPD_ADDR 2 -++#define DIMM3_SPD_ADDR 3 -++#define JZ_HCI_ADDR 7 -++ -++#define DIMM_SPD_LEN 128 -++#define JZ_HCI_LEN 512 /* 4K bits E2PROM */ -++#define I2C_RTC_LEN 16 -++#define HCI_MAC_OFFSET 64 -++ -++extern void i2c_open(void); -++extern void i2c_close(void); -++extern void i2c_setclk(unsigned int i2cclk); -++ -++extern int i2c_read(unsigned char device, unsigned char *buf, -++ unsigned char address, int count); -++extern int i2c_write(unsigned char device, unsigned char *buf, -++ unsigned char address, int count); -++ -++#endif /* __ASM_JZ4750D_MISC_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4750d/ops.h linux-2.6.24.7/include/asm-mips/mach-jz4750d/ops.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4750d/ops.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4750d/ops.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,3450 @@ -++/* -++ * linux/include/asm-mips/mach-jz4750d/ops.h -++ * -++ * JZ4750D register definition. -++ * -++ * Copyright (C) 2008 Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++ -++#ifndef __JZ4750D_OPS_H__ -++#define __JZ4750D_OPS_H__ -++ -++/* -++ * Definition of Module Operations -++ */ -++ -++/*************************************************************************** -++ * EMC -++ ***************************************************************************/ -++#define is_share_mode() ((REG_EMC_BCR & EMC_BCR_BSR_MASK) == EMC_BCR_BSR_SHARE) -++ -++/*************************************************************************** -++ * GPIO -++ ***************************************************************************/ -++ -++//------------------------------------------------------ -++// GPIO Pins Description -++// -++// PORT 0: -++// -++// PIN/BIT N FUNC0 FUNC1 NOTE -++// 0 D0 - -++// 1 D1 - -++// 2 D2 - -++// 3 D3 - -++// 4 D4 - -++// 5 D5 - -++// 6 D6 - -++// 7 D7 - -++// 8 D8 - -++// 9 D9 - -++// 10 D10 - -++// 11 D11 - -++// 12 D12 - -++// 13 D13 - -++// 14 D14 - -++// 15 D15 - -++// 16 D16 - -++// 17 D17 - -++// 18 D18 - -++// 19 D19 - -++// 20 D20 - -++// 21 D21 - -++// 22 D22 - -++// 23 D23 - -++// 24 D24 - -++// 25 D25 - -++// 26 D26 - -++// 27 D27 - -++// 28 D28 - -++// 29 D29 - -++// 30 D30 - -++// 31 D31 - -++// -++//------------------------------------------------------ -++// PORT 1: -++// -++// PIN/BIT N FUNC0 FUNC1 FUNC2 NOTE -++// 0 A0 - - -++// 1 A1 - - -++// 2 A2 - - -++// 3 A3 - - -++// 4 A4 - - -++// 5 A5 - - -++// 6 A6 - - -++// 7 A7 - - -++// 8 A8 - - -++// 9 A9 - - -++// 10 A10 - - -++// 11 A11 - - -++// 12 A12 - - -++// 13 A13 - - -++// 14 A14 - - -++// 15 A15/CLE CL(unshare) MSC0_CLK -++// 16 DCS0# - - -++// 17 RAS# - - -++// 18 CAS# - - -++// 19 SDWE#/BUFD# - - -++// 20 WE0# - - -++// 21 WE1# - - -++// 22 WE2# - - -++// 23 WE3# - - -++// 24 CKO - - Note1 -++// 25 CKE - - -++// 26 SSI_CLK MSC1_CLK - -++// 27 SSI_DT MSC1_D1 - -++// 28 SSI_DR MSC1_D0 - -++// 29 SSI_CE0# MSC1_CMD - -++// 30 SSI_GPC MSC1_D2 - -++// 31 SSI_CE1# MSC1_D3 - -++// -++// Note1: BIT24: it is CKO when chip is reset -++// -++//------------------------------------------------------ -++// PORT 2: -++// -++// PIN/BIT N FUNC0 FUNC1 FUNC2 NOTE -++// 0 SD0 A20 - -++// 1 SD1 A21 - -++// 2 SD2 A22 - -++// 3 SD3 A23 - -++// 4 SD4 A24 - -++// 5 SD5 A25 - -++// 6 SD6 - - -++// 7 SD7 - - -++// 8 SD8 TSDI0 - -++// 9 SD9 TSDI1 - -++// 10 SD10 TSDI2 - -++// 11 SD11 TSDI3 - -++// 12 SD12 TSDI4 - -++// 13 SD13 TSDI5 - -++// 14 SD14 TSDI6 - -++// 15 SD15 TSDI7 - -++// 16 A16/ALE AL(unshare) MSC0_CMD -++// 17 A17 MSC0_D3 - -++// 18 A18 DREQ - -++// 19 A19 DACK - -++// 20 WAIT# - - Note2 -++// 21 CS1# - - -++// 22 CS2# - - -++// 23 CS3# - - -++// 24 CS4# - - -++// 25 RD# - - -++// 26 WR# - - -++// 27 FRB# - - Note3 -++// 28 FRE# MSC0_D0 - -++// 29 FWE# MSC0_D1 - -++// 30 - - - Note4 -++// 31 - - - Note5 -++// -++// Note2: BIT20: it is WIAT# pin when chip is reset -++// -++// Note3: BIT27: when NAND is used, it should connect to NANF FRB#. -++// -++// Note4: BIT30: it is BOOT_SEL0 which would be set as input without pulling when chip is reset. -++// -++// Note5: BIT31: it is BOOT_SEL1 which would be set as input without pulling when chip is reset. -++// -++//------------------------------------------------------ -++// PORT 3: -++// -++// PIN/BIT N FUNC0 FUNC1 NOTE -++// 0 LCD_B2 - -++// 1 LCD_B3 - -++// 2 LCD_B4 - -++// 3 LCD_B5 - -++// 4 LCD_B6 - -++// 5 LCD_B7 - -++// 6 LCD_G2 - -++// 7 LCD_G3 - -++// 8 LCD_G4 - -++// 9 LCD_G5 - -++// 10 LCD_G6 - -++// 11 LCD_G7 - -++// 12 LCD_R2 - -++// 13 LCD_R3 - -++// 14 LCD_R4 - -++// 15 LCD_R5 - -++// 16 LCD_R6 - -++// 17 LCD_R7 - -++// 18 LCD_PCLK - -++// 19 LCD_HSYNC - -++// 20 LCD_VSYNC - -++// 21 LCD_DE - -++// 22 LCD_CLS LCD_R1 -++// 23 LCD_SPL LCD_G0 -++// 24 LCD_PS LCD_G1 -++// 25 LCD_REV LCD_B1 -++// 26 LCD_B0 - -++// 27 LCD_R0 - -++// 28 UART0_RXD TSCLK -++// 29 UART0_TXD TSSTR -++// 30 UART0_CTS TSFRM -++// 31 UART0_RTS TSFAIL -++// -++//------------------------------------------------------ -++// PORT 4: -++// -++// PIN/BIT N FUNC0 FUNC1 FUNC2 NOTE -++// 0 CIM_D0 TSDI0 - -++// 1 CIM_D1 TSDI1 - -++// 2 CIM_D2 TSDI2 - -++// 3 CIM_D3 TSDI3 - -++// 4 CIM_D4 TSDI4 - -++// 5 CIM_D5 TSDI5 - -++// 6 CIM_D6 TSDI6 - -++// 7 CIM_D7 TSDI7 - -++// 8 CIM_MCLK TSFAIL - -++// 9 CIM_PCLK TSCLK - -++// 10 CIM_VSYNC TSSTR - -++// 11 CIM_HSYNC TSFRM - -++// 12 I2C_SDA - - -++// 13 I2C_SCK - - -++// 18 SDATO - - -++// 19 SDATI - - -++// 20 PWM0 - - -++// 22 PWM2 SYNC - -++// 23 PWM3 UART1_RxD BCLK -++// 24 PWM4 - - -++// 25 PWM5 UART1_TxD SCLK_RSTN -++// 28 DCS1# - - -++// 29 - - - Note6 -++// 30 WKUP - - Note7 -++// 31 - - - Note8 -++// -++// Note6: BIT29: it is BOOT_SEL2 which would be set as input without pulling when chip is reset. -++// Note7: BIT30: it is only used as input and interrupt, and with no pull-up and pull-down -++// Note8: BIT31: it is used to select the function of UART or JTAG set by PESEL[31] -++// PESEL[31] = 0, select JTAG function -++// PESEL[31] = 1, select UART function -++// -++//------------------------------------------------------ -++// PORT 5: -++// -++// PIN/BIT N FUNC0 FUNC1 NOTE -++// 10 SSI_CLK - -++// 11 SSI_DT PWM1 -++// 12 SSI_DR - -++// 13 SSI_CE0# - -++// 14 SSI_GPC - -++// 15 SSI_CE2# - -++// -++////////////////////////////////////////////////////////// -++ -++/*---------------------------------------------------------------- -++ * p is the port number (0,1,2,3,4,5) -++ * o is the pin offset (0-31) inside the port -++ * n is the absolute number of a pin (0-127), regardless of the port -++ */ -++ -++//------------------------------------------- -++// Function Pins Mode -++ -++#define __gpio_as_func0(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXFUNS(p) = (1 << o); \ -++ REG_GPIO_PXTRGC(p) = (1 << o); \ -++ REG_GPIO_PXSELC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_as_func1(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXFUNS(p) = (1 << o); \ -++ REG_GPIO_PXTRGC(p) = (1 << o); \ -++ REG_GPIO_PXSELS(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_as_func2(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXFUNS(p) = (1 << o); \ -++ REG_GPIO_PXTRGS(p) = (1 << o); \ -++ REG_GPIO_PXSELC(p) = (1 << o); \ -++} while (0) -++ -++/* -++ * D0 ~ D31, A0 ~ A14, DCS0#, RAS#, CAS#, -++ * RDWE#, WE0#, WE1#, WE2#, WE3#, CKO#, CKE# -++ */ -++#define __gpio_as_sdram_32bit() \ -++do { \ -++ REG_GPIO_PXFUNS(0) = 0xffffffff; \ -++ REG_GPIO_PXSELC(0) = 0xffffffff; \ -++ REG_GPIO_PXPES(0) = 0xffffffff; \ -++ REG_GPIO_PXFUNS(1) = 0x03ff7fff; \ -++ REG_GPIO_PXSELC(1) = 0x03ff7fff; \ -++ REG_GPIO_PXPES(1) = 0x03ff7fff; \ -++} while (0) -++ -++ -++/* -++ * D0 ~ D31, A0 ~ A14, DCS0#, RAS#, CAS#, -++ * RDWE#, WE0#, WE1#, WE2#, WE3#, CKO#, CKE# -++ * !!!!DCS1# -++ */ -++#define __gpio_as_sdram_x2_32bit() \ -++do { \ -++ REG_GPIO_PXFUNS(0) = 0xffffffff; \ -++ REG_GPIO_PXSELC(0) = 0xffffffff; \ -++ REG_GPIO_PXPES(0) = 0xffffffff; \ -++ REG_GPIO_PXFUNS(1) = 0x03ff7fff; \ -++ REG_GPIO_PXSELC(1) = 0x03ff7fff; \ -++ REG_GPIO_PXPES(1) = 0x03ff7fff; \ -++ REG_GPIO_PXFUNS(4) = 0x10000000; \ -++ REG_GPIO_PXSELC(4) = 0x10000000; \ -++ REG_GPIO_PXPES(4) = 0x10000000; \ -++} while (0) -++ -++/* -++ * D0 ~ D15, A0 ~ A14, DCS0#, RAS#, CAS#, -++ * RDWE#, WE0#, WE1#, WE2#, WE3#, CKO#, CKE# -++ */ -++#define __gpio_as_sdram_16bit() \ -++do { \ -++ /* 32/16-bit data normal order */ \ -++ REG_GPIO_PXFUNS(0) = 0x0000ffff; \ -++ REG_GPIO_PXSELC(0) = 0x0000ffff; \ -++ REG_GPIO_PXPES(0) = 0x0000ffff; \ -++ REG_GPIO_PXFUNS(1) = 0x03ff7fff; \ -++ REG_GPIO_PXSELC(1) = 0x03ff7fff; \ -++ REG_GPIO_PXPES(1) = 0x03ff7fff; \ -++} while (0) -++ -++/* -++ * D0 ~ D7, CS1#, CLE, ALE, FRE#, FWE#, FRB#, RDWE#/BUFD# -++ * @n: chip select number(1 ~ 4) -++ */ -++#define __gpio_as_nand_8bit(n) \ -++do { \ -++ if (!is_share_mode()) { \ -++ /* unshare mode */ \ -++ REG_GPIO_PXFUNS(2) = 0x000000ff; /* SD0~SD7 */ \ -++ REG_GPIO_PXSELS(2) = 0x000000ff; \ -++ REG_GPIO_PXPES(2) = 0x000000ff; \ -++ REG_GPIO_PXFUNS(1) = 0x00008000; /* CLE(SA3) */ \ -++ REG_GPIO_PXSELS(1) = 0x00008000; \ -++ REG_GPIO_PXPES(1) = 0x00008000; \ -++ REG_GPIO_PXFUNS(2) = 0x00010000; /* ALE(SA4) */ \ -++ REG_GPIO_PXSELS(2) = 0x00010000; \ -++ REG_GPIO_PXPES(2) = 0x00010000; \ -++ } else { \ -++ /* 32/16-bit data bus */ \ -++ REG_GPIO_PXFUNS(0) = 0x000000ff; /* D0~D7 */ \ -++ REG_GPIO_PXSELC(0) = 0x000000ff; \ -++ REG_GPIO_PXPES(0) = 0x000000ff; \ -++ REG_GPIO_PXFUNS(1) = 0x00008000; /* CLE(A15) */ \ -++ REG_GPIO_PXSELC(1) = 0x00008000; \ -++ REG_GPIO_PXPES(1) = 0x00008000; \ -++ REG_GPIO_PXFUNS(2) = 0x00010000; /* ALE(A16) */ \ -++ REG_GPIO_PXSELC(2) = 0x00010000; \ -++ REG_GPIO_PXPES(2) = 0x00010000; \ -++ } \ -++ REG_GPIO_PXFUNS(2) = 0x00200000 << ((n)-1); /* CSn */ \ -++ REG_GPIO_PXSELC(2) = 0x00200000 << ((n)-1); \ -++ REG_GPIO_PXPES(2) = 0x00200000 << ((n)-1); \ -++ \ -++ REG_GPIO_PXFUNS(1) = 0x00080000; /* RDWE#/BUFD# */ \ -++ REG_GPIO_PXSELC(1) = 0x00080000; \ -++ REG_GPIO_PXPES(1) = 0x00080000; \ -++ REG_GPIO_PXFUNS(2) = 0x30000000; /* FRE#, FWE# */ \ -++ REG_GPIO_PXSELC(2) = 0x30000000; \ -++ REG_GPIO_PXPES(2) = 0x30000000; \ -++ REG_GPIO_PXFUNC(2) = 0x08000000; /* FRB#(input) */ \ -++ REG_GPIO_PXSELC(2) = 0x08000000; \ -++ REG_GPIO_PXDIRC(2) = 0x08000000; \ -++ REG_GPIO_PXPES(2) = 0x08000000; \ -++} while (0) -++ -++ -++/* -++ * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D7 -++ * @n: chip select number(1 ~ 4) -++ */ -++#define __gpio_as_nor_8bit(n) \ -++do { \ -++ /* 32/16-bit data bus */ \ -++ REG_GPIO_PXFUNS(0) = 0x000000ff; \ -++ REG_GPIO_PXSELC(0) = 0x000000ff; \ -++ REG_GPIO_PXPES(0) = 0x000000ff; \ -++ \ -++ REG_GPIO_PXFUNS(2) = 0x00200000 << ((n)-1); /* CSn */ \ -++ REG_GPIO_PXSELC(2) = 0x00200000 << ((n)-1); \ -++ REG_GPIO_PXPES(2) = 0x00200000 << ((n)-1); \ -++ \ -++ REG_GPIO_PXFUNS(1) = 0x0000ffff; /* A0~A15 */ \ -++ REG_GPIO_PXSELC(1) = 0x0000ffff; \ -++ REG_GPIO_PXPES(1) = 0x0000ffff; \ -++ REG_GPIO_PXFUNS(2) = 0x06110007; /* RD#, WR#, WAIT#, A20~A22 */ \ -++ REG_GPIO_PXSELC(2) = 0x06110007; \ -++ REG_GPIO_PXPES(2) = 0x06110007; \ -++ REG_GPIO_PXFUNS(2) = 0x000e0000; /* A17~A19 */ \ -++ REG_GPIO_PXSELS(2) = 0x000e0000; \ -++ REG_GPIO_PXPES(2) = 0x000e0000; \ -++} while (0) -++ -++/* -++ * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D15 -++ * @n: chip select number(1 ~ 4) -++ */ -++#define __gpio_as_nor_16bit(n) \ -++do { \ -++ /* 32/16-bit data normal order */ \ -++ REG_GPIO_PXFUNS(0) = 0x0000ffff; \ -++ REG_GPIO_PXSELC(0) = 0x0000ffff; \ -++ REG_GPIO_PXPES(0) = 0x0000ffff; \ -++ \ -++ REG_GPIO_PXFUNS(2) = 0x00200000 << ((n)-1); /* CSn */ \ -++ REG_GPIO_PXSELC(2) = 0x00200000 << ((n)-1); \ -++ REG_GPIO_PXPES(2) = 0x00200000 << ((n)-1); \ -++ \ -++ REG_GPIO_PXFUNS(1) = 0x0000ffff; /* A0~A15 */ \ -++ REG_GPIO_PXSELC(1) = 0x0000ffff; \ -++ REG_GPIO_PXPES(1) = 0x0000ffff; \ -++ REG_GPIO_PXFUNS(2) = 0x06110007; /* RD#, WR#, WAIT#, A20~A22 */ \ -++ REG_GPIO_PXSELC(2) = 0x06110007; \ -++ REG_GPIO_PXPES(2) = 0x06110007; \ -++ REG_GPIO_PXFUNS(2) = 0x000e0000; /* A17~A19 */ \ -++ REG_GPIO_PXSELS(2) = 0x000e0000; \ -++ REG_GPIO_PXPES(2) = 0x000e0000; \ -++} while (0) -++ -++/* -++ * UART0_TxD, UART0_RxD -++ */ -++#define __gpio_as_uart0() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x30000000; \ -++ REG_GPIO_PXSELC(3) = 0x30000000; \ -++ REG_GPIO_PXPES(3) = 0x30000000; \ -++} while (0) -++ -++/* -++ * UART0_TxD, UART0_RxD, UART0_CTS, UART0_RTS -++ */ -++#define __gpio_as_uart0_ctsrts() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0xf0000000; \ -++ REG_GPIO_PXSELC(3) = 0xf0000000; \ -++ REG_GPIO_PXPES(3) = 0xf0000000; \ -++} while (0) -++ -++/* -++ * UART1_TxD, UART1_RxD -++ */ -++#define __gpio_as_uart1() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x02800000; \ -++ REG_GPIO_PXSELC(4) = 0x02800000; \ -++ REG_GPIO_PXPES(4) = 0x02800000; \ -++} while (0) -++ -++/* -++ * UART2_TxD, UART2_RxD, UART2_CTS, UART2_RTS using JTAG pins -++ */ -++#define __gpio_as_uart2() \ -++do { \ -++ REG_GPIO_PXSELS(4) = 0x80000000; \ -++} while (0) -++ -++/* -++ * TSCLK, TSSTR, TSFRM, TSFAIL, TSDI0~7 -++ */ -++#define __gpio_as_tssi() \ -++do { \ -++ REG_GPIO_PXFUNS(2) = 0x0000ff00; \ -++ REG_GPIO_PXSELS(2) = 0x0000ff00; \ -++ REG_GPIO_PXPES(2) = 0x0000ff00; \ -++ REG_GPIO_PXFUNS(5) = 0x00f00000; \ -++ REG_GPIO_PXSELC(5) = 0x00f00000; \ -++ REG_GPIO_PXPES(5) = 0x00f00000; \ -++} while (0) -++ -++/* -++ * LCD_D0~LCD_D7, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -++ */ -++#define __gpio_as_lcd_8bit() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x003c00ff; \ -++ REG_GPIO_PXTRGC(3) = 0x003c00ff; \ -++ REG_GPIO_PXSELC(3) = 0x003c00ff; \ -++ REG_GPIO_PXPES(3) = 0x003c00ff; \ -++} while (0) -++ -++/* -++ * LCD_D0~LCD_D15, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -++ */ -++#define __gpio_as_lcd_16bit() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x003cffff; \ -++ REG_GPIO_PXTRGC(3) = 0x003cffff; \ -++ REG_GPIO_PXSELC(3) = 0x003cffff; \ -++ REG_GPIO_PXPES(3) = 0x003cffff; \ -++} while (0) -++ -++/* -++ * LCD_R2~LCD_R7, LCD_G2~LCD_G7, LCD_B2~LCD_B7, -++ * LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -++ */ -++#define __gpio_as_lcd_18bit() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x003fffff; \ -++ REG_GPIO_PXTRGC(3) = 0x003fffff; \ -++ REG_GPIO_PXSELC(3) = 0x003fffff; \ -++ REG_GPIO_PXPES(3) = 0x003fffff; \ -++} while (0) -++ -++/* -++ * LCD_R0~LCD_R7, LCD_G0~LCD_G7, LCD_B0~LCD_B7, -++ * LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE -++ */ -++#define __gpio_as_lcd_24bit() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x0fffffff; \ -++ REG_GPIO_PXTRGC(3) = 0x0fffffff; \ -++ REG_GPIO_PXSELC(3) = 0x0c3fffff; \ -++ REG_GPIO_PXSELS(3) = 0x03c00000; \ -++ REG_GPIO_PXPES(3) = 0x0fffffff; \ -++} while (0) -++ -++/* -++ * LCD_CLS, LCD_SPL, LCD_PS, LCD_REV -++ */ -++#define __gpio_as_lcd_special() \ -++do { \ -++ REG_GPIO_PXFUNS(3) = 0x03C00000; \ -++ REG_GPIO_PXSELC(3) = 0x03C00000; \ -++ REG_GPIO_PXPES(3) = 0x03C00000; \ -++} while (0) -++ -++/* -++ * CIM_D0~CIM_D7, CIM_MCLK, CIM_PCLK, CIM_VSYNC, CIM_HSYNC -++ */ -++#define __gpio_as_cim() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x00000fff; \ -++ REG_GPIO_PXSELC(4) = 0x00000fff; \ -++ REG_GPIO_PXPES(4) = 0x00000fff; \ -++} while (0) -++ -++/* -++ * SDATO, SDATI, BCLK, SYNC, SCLK_RSTN(gpio sepc) or -++ * SDATA_OUT, SDATA_IN, BIT_CLK, SYNC, SCLK_RESET(aic spec) -++ */ -++#define __gpio_as_aic() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x16c00000; \ -++ REG_GPIO_PXTRGC(4) = 0x02c00000; \ -++ REG_GPIO_PXTRGS(4) = 0x14000000; \ -++ REG_GPIO_PXSELC(4) = 0x14c00000; \ -++ REG_GPIO_PXSELS(4) = 0x02000000; \ -++ REG_GPIO_PXPES(4) = 0x16c00000; \ -++} while (0) -++ -++/* -++ * MSC0_CMD, MSC0_CLK, MSC0_D0 ~ MSC0_D3 -++ */ -++#define __gpio_as_msc0_4bit() \ -++do { \ -++ REG_GPIO_PXFUNS(1) = 0x00008000; \ -++ REG_GPIO_PXTRGS(1) = 0x00008000; \ -++ REG_GPIO_PXSELC(1) = 0x00008000; \ -++ REG_GPIO_PXPES(1) = 0x00008000; \ -++ REG_GPIO_PXFUNS(2) = 0x38030000; \ -++ REG_GPIO_PXTRGS(2) = 0x00010000; \ -++ REG_GPIO_PXTRGC(2) = 0x38020000; \ -++ REG_GPIO_PXSELC(2) = 0x08010000; \ -++ REG_GPIO_PXSELS(2) = 0x30020000; \ -++ REG_GPIO_PXPES(2) = 0x38030000; \ -++} while (0) -++ -++ -++/* -++ * MSC1_CMD, MSC1_CLK, MSC1_D0 ~ MSC1_D3 -++ */ -++#define __gpio_as_msc1_4bit() \ -++do { \ -++ REG_GPIO_PXFUNS(1) = 0xfc000000; \ -++ REG_GPIO_PXTRGC(1) = 0xfc000000; \ -++ REG_GPIO_PXSELS(1) = 0xfc000000; \ -++ REG_GPIO_PXPES(1) = 0xfc000000; \ -++} while (0) -++ -++#define __gpio_as_msc __gpio_as_msc0_4bit /* default as msc0 4bit */ -++#define __gpio_as_msc0 __gpio_as_msc0_4bit /* msc0 default as 4bit */ -++#define __gpio_as_msc1 __gpio_as_msc1_4bit /* msc1 only support 4bit */ -++ -++/* -++ * SSI_CE0, SSI_CE1, SSI_GPC, SSI_CLK, SSI_DT, SSI_DR -++ */ -++#define __gpio_as_ssi() \ -++do { \ -++ REG_GPIO_PXFUNS(1) = 0xfc000000; \ -++ REG_GPIO_PXTRGC(1) = 0xfc000000; \ -++ REG_GPIO_PXSELC(1) = 0xfc000000; \ -++ REG_GPIO_PXPES(1) = 0xfc000000; \ -++} while (0) -++ -++/* -++ * SSI_CE0, SSI_CE2, SSI_GPC, SSI_CLK, SSI_DT, SSI1_DR -++ */ -++#define __gpio_as_ssi_1() \ -++do { \ -++ REG_GPIO_PXFUNS(5) = 0x0000fc00; \ -++ REG_GPIO_PXTRGC(5) = 0x0000fc00; \ -++ REG_GPIO_PXSELC(5) = 0x0000fc00; \ -++ REG_GPIO_PXPES(5) = 0x0000fc00; \ -++} while (0) -++ -++/* -++ * I2C_SCK, I2C_SDA -++ */ -++#define __gpio_as_i2c() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x00003000; \ -++ REG_GPIO_PXSELC(4) = 0x00003000; \ -++ REG_GPIO_PXPES(4) = 0x00003000; \ -++} while (0) -++ -++/* -++ * PWM0 -++ */ -++#define __gpio_as_pwm0() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x00100000; \ -++ REG_GPIO_PXSELC(4) = 0x00100000; \ -++ REG_GPIO_PXPES(4) = 0x00100000; \ -++} while (0) -++ -++/* -++ * PWM1 -++ */ -++#define __gpio_as_pwm1() \ -++do { \ -++ REG_GPIO_PXFUNS(5) = 0x00000800; \ -++ REG_GPIO_PXSELC(5) = 0x00000800; \ -++ REG_GPIO_PXPES(5) = 0x00000800; \ -++} while (0) -++ -++/* -++ * PWM2 -++ */ -++#define __gpio_as_pwm2() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x00400000; \ -++ REG_GPIO_PXSELC(4) = 0x00400000; \ -++ REG_GPIO_PXPES(4) = 0x00400000; \ -++} while (0) -++ -++/* -++ * PWM3 -++ */ -++#define __gpio_as_pwm3() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x00800000; \ -++ REG_GPIO_PXSELC(4) = 0x00800000; \ -++ REG_GPIO_PXPES(4) = 0x00800000; \ -++} while (0) -++ -++/* -++ * PWM4 -++ */ -++#define __gpio_as_pwm4() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x01000000; \ -++ REG_GPIO_PXSELC(4) = 0x01000000; \ -++ REG_GPIO_PXPES(4) = 0x01000000; \ -++} while (0) -++ -++/* -++ * PWM5 -++ */ -++#define __gpio_as_pwm5() \ -++do { \ -++ REG_GPIO_PXFUNS(4) = 0x02000000; \ -++ REG_GPIO_PXSELC(4) = 0x02000000; \ -++ REG_GPIO_PXPES(4) = 0x02000000; \ -++} while (0) -++ -++/* -++ * n = 0 ~ 5 -++ */ -++#define __gpio_as_pwm(n) __gpio_as_pwm##n() -++ -++/* -++ * DREQ -++ */ -++#define __gpio_as_dreq() \ -++do { \ -++ REG_GPIO_PXFUNS(5) = 0x00000004; \ -++ REG_GPIO_PXSELS(5) = 0x00000004; \ -++ REG_GPIO_PXPES(5) = 0x00000004; \ -++} while (0) -++ -++/* -++ * DACK -++ */ -++#define __gpio_as_dack() \ -++do { \ -++ REG_GPIO_PXFUNS(5) = 0x00000008; \ -++ REG_GPIO_PXSELS(5) = 0x00000008; \ -++ REG_GPIO_PXPES(5) = 0x00000008; \ -++} while (0) -++ -++/* -++ * GPIO or Interrupt Mode -++ */ -++#define __gpio_get_port(p) (REG_GPIO_PXPIN(p)) -++ -++#define __gpio_port_as_output(p, o) \ -++do { \ -++ REG_GPIO_PXFUNC(p) = (1 << (o)); \ -++ REG_GPIO_PXSELC(p) = (1 << (o)); \ -++ REG_GPIO_PXDIRS(p) = (1 << (o)); \ -++} while (0) -++ -++#define __gpio_port_as_input(p, o) \ -++do { \ -++ REG_GPIO_PXFUNC(p) = (1 << (o)); \ -++ REG_GPIO_PXSELC(p) = (1 << (o)); \ -++ REG_GPIO_PXDIRC(p) = (1 << (o)); \ -++} while (0) -++ -++#define __gpio_as_output(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ __gpio_port_as_output(p, o); \ -++} while (0) -++ -++#define __gpio_as_input(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ __gpio_port_as_input(p, o); \ -++} while (0) -++ -++#define __gpio_set_pin(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXDATS(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_clear_pin(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXDATC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_get_pin(n) \ -++({ \ -++ unsigned int p, o, v; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ if (__gpio_get_port(p) & (1 << o)) \ -++ v = 1; \ -++ else \ -++ v = 0; \ -++ v; \ -++}) -++ -++#define __gpio_as_irq_high_level(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMS(p) = (1 << o); \ -++ REG_GPIO_PXTRGC(p) = (1 << o); \ -++ REG_GPIO_PXFUNC(p) = (1 << o); \ -++ REG_GPIO_PXSELS(p) = (1 << o); \ -++ REG_GPIO_PXDIRS(p) = (1 << o); \ -++ REG_GPIO_PXFLGC(p) = (1 << o); \ -++ REG_GPIO_PXIMC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_as_irq_low_level(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMS(p) = (1 << o); \ -++ REG_GPIO_PXTRGC(p) = (1 << o); \ -++ REG_GPIO_PXFUNC(p) = (1 << o); \ -++ REG_GPIO_PXSELS(p) = (1 << o); \ -++ REG_GPIO_PXDIRC(p) = (1 << o); \ -++ REG_GPIO_PXFLGC(p) = (1 << o); \ -++ REG_GPIO_PXIMC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_as_irq_rise_edge(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMS(p) = (1 << o); \ -++ REG_GPIO_PXTRGS(p) = (1 << o); \ -++ REG_GPIO_PXFUNC(p) = (1 << o); \ -++ REG_GPIO_PXSELS(p) = (1 << o); \ -++ REG_GPIO_PXDIRS(p) = (1 << o); \ -++ REG_GPIO_PXFLGC(p) = (1 << o); \ -++ REG_GPIO_PXIMC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_as_irq_fall_edge(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMS(p) = (1 << o); \ -++ REG_GPIO_PXTRGS(p) = (1 << o); \ -++ REG_GPIO_PXFUNC(p) = (1 << o); \ -++ REG_GPIO_PXSELS(p) = (1 << o); \ -++ REG_GPIO_PXDIRC(p) = (1 << o); \ -++ REG_GPIO_PXFLGC(p) = (1 << o); \ -++ REG_GPIO_PXIMC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_mask_irq(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMS(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_unmask_irq(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXIMC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_ack_irq(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXFLGC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_get_irq() \ -++({ \ -++ unsigned int p, i, tmp, v = 0; \ -++ for (p = 3; p >= 0; p--) { \ -++ tmp = REG_GPIO_PXFLG(p); \ -++ for (i = 0; i < 32; i++) \ -++ if (tmp & (1 << i)) \ -++ v = (32*p + i); \ -++ } \ -++ v; \ -++}) -++ -++#define __gpio_group_irq(n) \ -++({ \ -++ register int tmp, i; \ -++ tmp = REG_GPIO_PXFLG((n)); \ -++ for (i=31;i>=0;i--) \ -++ if (tmp & (1 << i)) \ -++ break; \ -++ i; \ -++}) -++ -++#define __gpio_enable_pull(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXPEC(p) = (1 << o); \ -++} while (0) -++ -++#define __gpio_disable_pull(n) \ -++do { \ -++ unsigned int p, o; \ -++ p = (n) / 32; \ -++ o = (n) % 32; \ -++ REG_GPIO_PXPES(p) = (1 << o); \ -++} while (0) -++ -++ -++/*************************************************************************** -++ * CPM -++ ***************************************************************************/ -++#define __cpm_get_pllm() \ -++ ((REG_CPM_CPPCR & CPM_CPPCR_PLLM_MASK) >> CPM_CPPCR_PLLM_BIT) -++#define __cpm_get_plln() \ -++ ((REG_CPM_CPPCR & CPM_CPPCR_PLLN_MASK) >> CPM_CPPCR_PLLN_BIT) -++#define __cpm_get_pllod() \ -++ ((REG_CPM_CPPCR & CPM_CPPCR_PLLOD_MASK) >> CPM_CPPCR_PLLOD_BIT) -++ -++#define __cpm_get_cdiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_CDIV_MASK) >> CPM_CPCCR_CDIV_BIT) -++#define __cpm_get_hdiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_HDIV_MASK) >> CPM_CPCCR_HDIV_BIT) -++#define __cpm_get_pdiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_PDIV_MASK) >> CPM_CPCCR_PDIV_BIT) -++#define __cpm_get_mdiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT) -++#define __cpm_get_ldiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_LDIV_MASK) >> CPM_CPCCR_LDIV_BIT) -++#define __cpm_get_udiv() \ -++ ((REG_CPM_CPCCR & CPM_CPCCR_UDIV_MASK) >> CPM_CPCCR_UDIV_BIT) -++#define __cpm_get_i2sdiv() \ -++ ((REG_CPM_I2SCDR & CPM_I2SCDR_I2SDIV_MASK) >> CPM_I2SCDR_I2SDIV_BIT) -++#define __cpm_get_pixdiv() \ -++ ((REG_CPM_LPCDR & CPM_LPCDR_PIXDIV_MASK) >> CPM_LPCDR_PIXDIV_BIT) -++#define __cpm_get_mscdiv(n) \ -++ ((REG_CPM_MSCCDR(n) & CPM_MSCCDR_MSCDIV_MASK) >> CPM_MSCCDR_MSCDIV_BIT) -++#define __cpm_get_uhcdiv() \ -++ ((REG_CPM_UHCCDR & CPM_UHCCDR_UHCDIV_MASK) >> CPM_UHCCDR_UHCDIV_BIT) -++#define __cpm_get_ssidiv() \ -++ ((REG_CPM_SSICCDR & CPM_SSICDR_SSICDIV_MASK) >> CPM_SSICDR_SSIDIV_BIT) -++#define __cpm_get_pcmdiv(v) \ -++ ((REG_CPM_PCMCDR & CPM_PCMCDR_PCMCD_MASK) >> CPM_PCMCDR_PCMCD_BIT) -++ -++#define __cpm_set_cdiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_CDIV_MASK) | ((v) << (CPM_CPCCR_CDIV_BIT))) -++#define __cpm_set_hdiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_HDIV_MASK) | ((v) << (CPM_CPCCR_HDIV_BIT))) -++#define __cpm_set_pdiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_PDIV_MASK) | ((v) << (CPM_CPCCR_PDIV_BIT))) -++#define __cpm_set_mdiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_MDIV_MASK) | ((v) << (CPM_CPCCR_MDIV_BIT))) -++#define __cpm_set_ldiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_LDIV_MASK) | ((v) << (CPM_CPCCR_LDIV_BIT))) -++#define __cpm_set_udiv(v) \ -++ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | ((v) << (CPM_CPCCR_UDIV_BIT))) -++#define __cpm_set_i2sdiv(v) \ -++ (REG_CPM_I2SCDR = (REG_CPM_I2SCDR & ~CPM_I2SCDR_I2SDIV_MASK) | ((v) << (CPM_I2SCDR_I2SDIV_BIT))) -++#define __cpm_set_pixdiv(v) \ -++ (REG_CPM_LPCDR = (REG_CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | ((v) << (CPM_LPCDR_PIXDIV_BIT))) -++#define __cpm_set_mscdiv(n, v) \ -++ (REG_CPM_MSCCDR(n) = (REG_CPM_MSCCDR(n) & ~CPM_MSCCDR_MSCDIV_MASK) | ((v) << (CPM_MSCCDR_MSCDIV_BIT))) -++#define __cpm_set_uhcdiv(v) \ -++ (REG_CPM_UHCCDR = (REG_CPM_UHCCDR & ~CPM_UHCCDR_UHCDIV_MASK) | ((v) << (CPM_UHCCDR_UHCDIV_BIT))) -++#define __cpm_set_ssidiv(v) \ -++ (REG_CPM_SSICDR = (REG_CPM_SSICDR & ~CPM_SSICDR_SSIDIV_MASK) | ((v) << (CPM_SSICDR_SSIDIV_BIT))) -++#define __cpm_set_pcmdiv(v) \ -++ (REG_CPM_PCMCDR = (REG_CPM_PCMCDR & ~CPM_PCMCDR_PCMCD_MASK) | ((v) << (CPM_PCMCDR_PCMCD_BIT))) -++ -++#define __cpm_select_pcmclk_pll() (REG_CPM_PCMCDR |= CPM_PCMCDR_PCMS) -++#define __cpm_select_pcmclk_exclk() (REG_CPM_PCMCDR &= ~CPM_PCMCDR_PCMS) -++#define __cpm_select_pixclk_ext() (REG_CPM_LPCDR |= CPM_LPCDR_LPCS) -++#define __cpm_select_pixclk_pll() (REG_CPM_LPCDR &= ~CPM_LPCDR_LPCS) -++#define __cpm_select_tveclk_exclk() (REG_CPM_LPCDR |= CPM_CPCCR_LSCS) -++#define __cpm_select_tveclk_pll() (REG_CPM_LPCDR &= ~CPM_LPCDR_LSCS) -++#define __cpm_select_pixclk_lcd() (REG_CPM_LPCDR &= ~CPM_LPCDR_LTCS) -++#define __cpm_select_pixclk_tve() (REG_CPM_LPCDR |= CPM_LPCDR_LTCS) -++#define __cpm_select_i2sclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_I2CS) -++#define __cpm_select_i2sclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_I2CS) -++#define __cpm_select_usbclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_UCS) -++#define __cpm_select_usbclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_UCS) -++ -++#define __cpm_enable_cko() -++#define __cpm_exclk_direct() (REG_CPM_CPCCR &= ~CPM_CPCCR_ECS) -++#define __cpm_exclk_div2() (REG_CPM_CPCCR |= CPM_CPCCR_ECS) -++#define __cpm_enable_pll_change() (REG_CPM_CPCCR |= CPM_CPCCR_CE) -++#define __cpm_pllout_direct() (REG_CPM_CPCCR |= CPM_CPCCR_PCS) -++#define __cpm_pllout_div2() (REG_CPM_CPCCR &= ~CPM_CPCCR_PCS) -++#define __cpm_pll_enable() (REG_CPM_CPPCR |= CPM_CPPCR_PLLEN) -++ -++#define __cpm_pll_is_off() (REG_CPM_CPPSR & CPM_CPPSR_PLLOFF) -++#define __cpm_pll_is_on() (REG_CPM_CPPSR & CPM_CPPSR_PLLON) -++#define __cpm_pll_bypass() (REG_CPM_CPPSR |= CPM_CPPSR_PLLBP) -++ -++#define __cpm_get_cclk_doze_duty() \ -++ ((REG_CPM_LCR & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT) -++#define __cpm_set_cclk_doze_duty(v) \ -++ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_DOZE_DUTY_MASK) | ((v) << (CPM_LCR_DOZE_DUTY_BIT))) -++ -++#define __cpm_doze_mode() (REG_CPM_LCR |= CPM_LCR_DOZE_ON) -++#define __cpm_idle_mode() \ -++ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_IDLE) -++#define __cpm_sleep_mode() \ -++ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_SLEEP) -++ -++#define __cpm_stop_all() (REG_CPM_CLKGR = 0x1fffffff) -++#define __cpm_stop_cimram() (REG_CPM_CLKGR |= CPM_CLKGR_CIMRAM) -++#define __cpm_stop_idct() (REG_CPM_CLKGR |= CPM_CLKGR_IDCT) -++#define __cpm_stop_db() (REG_CPM_CLKGR |= CPM_CLKGR_DB) -++#define __cpm_stop_me() (REG_CPM_CLKGR |= CPM_CLKGR_ME) -++#define __cpm_stop_mc() (REG_CPM_CLKGR |= CPM_CLKGR_MC) -++#define __cpm_stop_tve() (REG_CPM_CLKGR |= CPM_CLKGR_TVE) -++#define __cpm_stop_tssi() (REG_CPM_CLKGR |= CPM_CLKGR_TSSI) -++#define __cpm_stop_owi() (REG_CPM_CLKGR |= CPM_CLKGR_OWI) -++#define __cpm_stop_pcm() (REG_CPM_CLKGR |= CPM_CLKGR_PCM) -++#define __cpm_stop_uart3() (REG_CPM_CLKGR |= CPM_CLKGR_UART3) -++#define __cpm_stop_uart2() (REG_CPM_CLKGR |= CPM_CLKGR_UART2) -++#define __cpm_stop_uart1() (REG_CPM_CLKGR |= CPM_CLKGR_UART1) -++#define __cpm_stop_uhc() (REG_CPM_CLKGR |= CPM_CLKGR_UHC) -++#define __cpm_stop_ipu() (REG_CPM_CLKGR |= CPM_CLKGR_IPU) -++#define __cpm_stop_dmac() (REG_CPM_CLKGR |= CPM_CLKGR_DMAC) -++#define __cpm_stop_udc() (REG_CPM_CLKGR |= CPM_CLKGR_UDC) -++#define __cpm_stop_lcd() (REG_CPM_CLKGR |= CPM_CLKGR_LCD) -++#define __cpm_stop_cim() (REG_CPM_CLKGR |= CPM_CLKGR_CIM) -++#define __cpm_stop_sadc() (REG_CPM_CLKGR |= CPM_CLKGR_SADC) -++#define __cpm_stop_msc(n) (REG_CPM_CLKGR |= CPM_CLKGR_MSC##n) -++#define __cpm_stop_aic1() (REG_CPM_CLKGR |= CPM_CLKGR_AIC1) -++#define __cpm_stop_aic2() (REG_CPM_CLKGR |= CPM_CLKGR_AIC2) -++#define __cpm_stop_ssi(n) (REG_CPM_CLKGR |= CPM_CLKGR_SSI##n) -++#define __cpm_stop_i2c() (REG_CPM_CLKGR |= CPM_CLKGR_I2C) -++#define __cpm_stop_rtc() (REG_CPM_CLKGR |= CPM_CLKGR_RTC) -++#define __cpm_stop_tcu() (REG_CPM_CLKGR |= CPM_CLKGR_TCU) -++#define __cpm_stop_uart0() (REG_CPM_CLKGR |= CPM_CLKGR_UART0) -++ -++#define __cpm_start_all() (REG_CPM_CLKGR = 0x0) -++#define __cpm_start_cimram() (REG_CPM_CLKGR &= ~CPM_CLKGR_CIMRAM) -++#define __cpm_start_idct() (REG_CPM_CLKGR &= ~CPM_CLKGR_IDCT) -++#define __cpm_start_db() (REG_CPM_CLKGR &= ~CPM_CLKGR_DB) -++#define __cpm_start_me() (REG_CPM_CLKGR &= ~CPM_CLKGR_ME) -++#define __cpm_start_mc() (REG_CPM_CLKGR &= ~CPM_CLKGR_MC) -++#define __cpm_start_tve() (REG_CPM_CLKGR &= ~CPM_CLKGR_TVE) -++#define __cpm_start_tssi() (REG_CPM_CLKGR &= ~CPM_CLKGR_TSSI) -++#define __cpm_start_owi() (REG_CPM_CLKGR &= ~CPM_CLKGR_OWI) -++#define __cpm_start_pcm() (REG_CPM_CLKGR &= ~CPM_CLKGR_PCM) -++#define __cpm_start_uart3() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART3) -++#define __cpm_start_uart2() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART2) -++#define __cpm_start_uart1() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART1) -++#define __cpm_start_uhc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UHC) -++#define __cpm_start_ipu() (REG_CPM_CLKGR &= ~CPM_CLKGR_IPU) -++#define __cpm_start_dmac() (REG_CPM_CLKGR &= ~CPM_CLKGR_DMAC) -++#define __cpm_start_udc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UDC) -++#define __cpm_start_lcd() (REG_CPM_CLKGR &= ~CPM_CLKGR_LCD) -++#define __cpm_start_cim() (REG_CPM_CLKGR &= ~CPM_CLKGR_CIM) -++#define __cpm_start_sadc() (REG_CPM_CLKGR &= ~CPM_CLKGR_SADC) -++#define __cpm_start_msc(n) (REG_CPM_CLKGR &= ~CPM_CLKGR_MSC##n) -++#define __cpm_start_aic1() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC1) -++#define __cpm_start_aic2() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC2) -++#define __cpm_start_ssi(n) (REG_CPM_CLKGR &= ~CPM_CLKGR_SSI##n) -++#define __cpm_start_i2c() (REG_CPM_CLKGR &= ~CPM_CLKGR_I2C) -++#define __cpm_start_rtc() (REG_CPM_CLKGR &= ~CPM_CLKGR_RTC) -++#define __cpm_start_tcu() (REG_CPM_CLKGR &= ~CPM_CLKGR_TCU) -++#define __cpm_start_uart0() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART0) -++ -++#define __cpm_get_o1st() \ -++ ((REG_CPM_OPCR & CPM_OPCR_O1ST_MASK) >> CPM_OPCR_O1ST_BIT) -++#define __cpm_set_o1st(v) \ -++ (REG_CPM_OPCR = (REG_CPM_OPCR & ~CPM_OPCR_O1ST_MASK) | ((v) << (CPM_OPCR_O1ST_BIT))) -++#define __cpm_enable_uhcphy() (REG_CPM_OPCR &= ~CPM_OPCR_UHCPHY_DISABLE) -++#define __cpm_suspend_uhcphy() (REG_CPM_OPCR |= CPM_OPCR_UHCPHY_DISABLE) -++#define __cpm_enable_udcphy() (REG_CPM_OPCR |= CPM_OPCR_UDCPHY_ENABLE) -++#define __cpm_suspend_udcphy() (REG_CPM_OPCR &= ~CPM_OPCR_UDCPHY_ENABLE) -++#define __cpm_enable_osc_in_sleep() (REG_CPM_OPCR |= CPM_OPCR_OSC_ENABLE) -++#define __cpm_disable_osc_in_sleep() (REG_CPM_OPCR &= ~CPM_OPCR_OSC_ENABLE) -++#define __cpm_select_rtcclk_rtc() (REG_CPM_OPCR |= CPM_OPCR_ERCS) -++#define __cpm_select_rtcclk_exclk() (REG_CPM_OPCR &= ~CPM_OPCR_ERCS) -++ -++ -++/*************************************************************************** -++ * TCU -++ ***************************************************************************/ -++// where 'n' is the TCU channel -++#define __tcu_select_extalclk(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_EXT_EN) -++#define __tcu_select_rtcclk(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_RTC_EN) -++#define __tcu_select_pclk(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_PCK_EN) -++#define __tcu_disable_pclk(n) \ -++ REG_TCU_TCSR(n) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PCK_EN); -++#define __tcu_select_clk_div1(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1) -++#define __tcu_select_clk_div4(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE4) -++#define __tcu_select_clk_div16(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE16) -++#define __tcu_select_clk_div64(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE64) -++#define __tcu_select_clk_div256(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE256) -++#define __tcu_select_clk_div1024(n) \ -++ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1024) -++ -++#define __tcu_enable_pwm_output(n) (REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_EN) -++#define __tcu_disable_pwm_output(n) (REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_EN) -++ -++#define __tcu_init_pwm_output_high(n) (REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_INITL_HIGH) -++#define __tcu_init_pwm_output_low(n) (REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_INITL_HIGH) -++ -++#define __tcu_set_pwm_output_shutdown_graceful(n) (REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_SD) -++#define __tcu_set_pwm_output_shutdown_abrupt(n) (REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_SD) -++ -++#define __tcu_clear_counter_to_zero(n) (REG_TCU_TCSR((n)) |= TCU_TCSR_CNT_CLRZ) -++ -++#define __tcu_ost_enabled() (REG_TCU_TER & TCU_TER_OSTEN) -++#define __tcu_enable_ost() (REG_TCU_TESR = TCU_TESR_OSTST) -++#define __tcu_disable_ost() (REG_TCU_TECR = TCU_TECR_OSTCL) -++ -++#define __tcu_counter_enabled(n) (REG_TCU_TER & (1 << (n))) -++#define __tcu_start_counter(n) (REG_TCU_TESR |= (1 << (n))) -++#define __tcu_stop_counter(n) (REG_TCU_TECR |= (1 << (n))) -++ -++#define __tcu_half_match_flag(n) (REG_TCU_TFR & (1 << ((n) + 16))) -++#define __tcu_full_match_flag(n) (REG_TCU_TFR & (1 << (n))) -++#define __tcu_set_half_match_flag(n) (REG_TCU_TFSR = (1 << ((n) + 16))) -++#define __tcu_set_full_match_flag(n) (REG_TCU_TFSR = (1 << (n))) -++#define __tcu_clear_half_match_flag(n) (REG_TCU_TFCR = (1 << ((n) + 16))) -++#define __tcu_clear_full_match_flag(n) (REG_TCU_TFCR = (1 << (n))) -++#define __tcu_mask_half_match_irq(n) (REG_TCU_TMSR = (1 << ((n) + 16))) -++#define __tcu_mask_full_match_irq(n) (REG_TCU_TMSR = (1 << (n))) -++#define __tcu_unmask_half_match_irq(n) (REG_TCU_TMCR = (1 << ((n) + 16))) -++#define __tcu_unmask_full_match_irq(n) (REG_TCU_TMCR = (1 << (n))) -++ -++#define __tcu_ost_match_flag() (REG_TCU_TFR & TCU_TFR_OSTFLAG) -++#define __tcu_set_ost_match_flag() (REG_TCU_TFSR = TCU_TFSR_OSTFST) -++#define __tcu_clear_ost_match_flag() (REG_TCU_TFCR = TCU_TFCR_OSTFCL) -++#define __tcu_ost_match_irq_masked() (REG_TCU_TMR & TCU_TMR_OSTMASK) -++#define __tcu_mask_ost_match_irq() (REG_TCU_TMSR = TCU_TMSR_OSTMST) -++#define __tcu_unmask_ost_match_irq() (REG_TCU_TMCR = TCU_TMCR_OSTMCL) -++ -++#define __tcu_wdt_clock_stopped() (REG_TCU_TSR & TCU_TSSR_WDTSC) -++#define __tcu_ost_clock_stopped() (REG_TCU_TSR & TCU_TSR_OST) -++#define __tcu_timer_clock_stopped(n) (REG_TCU_TSR & (1 << (n))) -++ -++#define __tcu_start_wdt_clock() (REG_TCU_TSCR = TCU_TSSR_WDTSC) -++#define __tcu_start_ost_clock() (REG_TCU_TSCR = TCU_TSCR_OSTSC) -++#define __tcu_start_timer_clock(n) (REG_TCU_TSCR = (1 << (n))) -++ -++#define __tcu_stop_wdt_clock() (REG_TCU_TSSR = TCU_TSSR_WDTSC) -++#define __tcu_stop_ost_clock() (REG_TCU_TSSR = TCU_TSSR_OSTSS) -++#define __tcu_stop_timer_clock(n) (REG_TCU_TSSR = (1 << (n))) -++ -++#define __tcu_get_count(n) (REG_TCU_TCNT((n))) -++#define __tcu_set_count(n,v) (REG_TCU_TCNT((n)) = (v)) -++#define __tcu_set_full_data(n,v) (REG_TCU_TDFR((n)) = (v)) -++#define __tcu_set_half_data(n,v) (REG_TCU_TDHR((n)) = (v)) -++ -++/* TCU2, counter 1, 2*/ -++#define __tcu_read_real_value(n) (REG_TCU_TSTR & (1 << ((n) + 16))) -++#define __tcu_read_false_value(n) (REG_TCU_TSTR & (1 << ((n) + 16))) -++#define __tcu_counter_busy(n) (REG_TCU_TSTR & (1 << (n))) -++#define __tcu_counter_ready(n) (REG_TCU_TSTR & (1 << (n))) -++ -++#define __tcu_set_read_real_value(n) (REG_TCU_TSTSR = (1 << ((n) + 16))) -++#define __tcu_set_read_false_value(n) (REG_TCU_TSTCR = (1 << ((n) + 16))) -++#define __tcu_set_counter_busy(n) (REG_TCU_TSTSR = (1 << (n))) -++#define __tcu_set_counter_ready(n) (REG_TCU_TSTCR = (1 << (n))) -++ -++/* ost counter */ -++#define __ostcu_set_pwm_output_shutdown_graceful() (REG_TCU_OSTCSR &= ~TCU_TCSR_PWM_SD) -++#define __ostcu_set_ost_output_shutdown_abrupt() (REG_TCU_OSTCSR |= TCU_TCSR_PWM_SD) -++#define __ostcu_select_clk_div1() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE1) -++#define __ostcu_select_clk_div4() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE4) -++#define __ostcu_select_clk_div16() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE16) -++#define __ostcu_select_clk_div64() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE64) -++#define __ostcu_select_clk_div256() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE256) -++#define __ostcu_select_clk_div1024() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~TCU_OSTCSR_PRESCALE_MASK) | TCU_OSTCSR_PRESCALE1024) -++#define __ostcu_select_rtcclk() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~(TCU_OSTCSR_EXT_EN | TCU_OSTCSR_RTC_EN | TCU_OSTCSR_PCK_EN)) | TCU_OSTCSR_RTC_EN) -++#define __ostcu_select_extalclk() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~(TCU_OSTCSR_EXT_EN | TCU_OSTCSR_RTC_EN | TCU_OSTCSR_PCK_EN)) | TCU_OSTCSR_EXT_EN) -++#define __ostcu_select_pclk() \ -++ (REG_TCU_OSTCSR = (REG_TCU_OSTCSR & ~(TCU_OSTCSR_EXT_EN | TCU_OSTCSR_RTC_EN | TCU_OSTCSR_PCK_EN)) | TCU_OSTCSR_PCK_EN) -++ -++ -++/*************************************************************************** -++ * WDT -++ ***************************************************************************/ -++#define __wdt_start() ( REG_WDT_TCER |= WDT_TCER_TCEN ) -++#define __wdt_stop() ( REG_WDT_TCER &= ~WDT_TCER_TCEN ) -++#define __wdt_set_count(v) ( REG_WDT_TCNT = (v) ) -++#define __wdt_set_data(v) ( REG_WDT_TDR = (v) ) -++ -++#define __wdt_select_extalclk() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_EXT_EN) -++#define __wdt_select_rtcclk() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_RTC_EN) -++#define __wdt_select_pclk() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_PCK_EN) -++ -++#define __wdt_select_clk_div1() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1) -++#define __wdt_select_clk_div4() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE4) -++#define __wdt_select_clk_div16() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE16) -++#define __wdt_select_clk_div64() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE64) -++#define __wdt_select_clk_div256() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE256) -++#define __wdt_select_clk_div1024() \ -++ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1024) -++ -++ -++/*************************************************************************** -++ * UART -++ ***************************************************************************/ -++ -++#define __uart_enable(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) |= UARTFCR_UUE | UARTFCR_FE ) -++#define __uart_disable(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_FCR) = ~UARTFCR_UUE ) -++ -++#define __uart_enable_transmit_irq(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_TIE ) -++#define __uart_disable_transmit_irq(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~UARTIER_TIE ) -++ -++#define __uart_enable_receive_irq(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) |= UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE ) -++#define __uart_disable_receive_irq(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_IER) &= ~(UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE) ) -++ -++#define __uart_enable_loopback(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) |= UARTMCR_LOOP ) -++#define __uart_disable_loopback(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_MCR) &= ~UARTMCR_LOOP ) -++ -++#define __uart_set_8n1(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) = UARTLCR_WLEN_8 ) -++ -++#define __uart_set_baud(n, devclk, baud) \ -++ do { \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) |= UARTLCR_DLAB; \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_DLLR) = (devclk / 16 / baud) & 0xff; \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_DLHR) = ((devclk / 16 / baud) >> 8) & 0xff; \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_LCR) &= ~UARTLCR_DLAB; \ -++ } while (0) -++ -++#define __uart_parity_error(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_PER) != 0 ) -++ -++#define __uart_clear_errors(n) \ -++ ( REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) &= ~(UARTLSR_ORER | UARTLSR_BRK | UARTLSR_FER | UARTLSR_PER | UARTLSR_RFER) ) -++ -++#define __uart_transmit_fifo_empty(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TDRQ) != 0 ) -++ -++#define __uart_transmit_end(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_TEMT) != 0 ) -++ -++#define __uart_transmit_char(n, ch) \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_TDR) = (ch) -++ -++#define __uart_receive_fifo_full(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) -++ -++#define __uart_receive_ready(n) \ -++ ( (REG8(UART_BASE + UART_OFF*(n) + OFF_LSR) & UARTLSR_DR) != 0 ) -++ -++#define __uart_receive_char(n) \ -++ REG8(UART_BASE + UART_OFF*(n) + OFF_RDR) -++ -++#define __uart_disable_irda() \ -++ ( REG8(IRDA_BASE + OFF_SIRCR) &= ~(SIRCR_TSIRE | SIRCR_RSIRE) ) -++#define __uart_enable_irda() \ -++ /* Tx high pulse as 0, Rx low pulse as 0 */ \ -++ ( REG8(IRDA_BASE + OFF_SIRCR) = SIRCR_TSIRE | SIRCR_RSIRE | SIRCR_RXPL | SIRCR_TPWS ) -++ -++ -++/*************************************************************************** -++ * DMAC -++ ***************************************************************************/ -++ -++/* m is the DMA controller index (0, 1), n is the DMA channel index (0 - 11) */ -++ -++#define __dmac_enable_module(m) \ -++ ( REG_DMAC_DMACR(m) |= DMAC_DMACR_DMAE | DMAC_DMACR_PR_012345 ) -++#define __dmac_disable_module(m) \ -++ ( REG_DMAC_DMACR(m) &= ~DMAC_DMACR_DMAE ) -++ -++/* p=0,1,2,3 */ -++#define __dmac_set_priority(m,p) \ -++do { \ -++ REG_DMAC_DMACR(m) &= ~DMAC_DMACR_PR_MASK; \ -++ REG_DMAC_DMACR(m) |= ((p) << DMAC_DMACR_PR_BIT); \ -++} while (0) -++ -++#define __dmac_test_halt_error(m) ( REG_DMAC_DMACR(m) & DMAC_DMACR_HLT ) -++#define __dmac_test_addr_error(m) ( REG_DMAC_DMACR(m) & DMAC_DMACR_AR ) -++ -++#define __dmac_channel_enable_clk(n) \ -++ REG_DMAC_DMACKE((n)/HALF_DMA_NUM) |= 1 << ((n)-(n)/HALF_DMA_NUM*HALF_DMA_NUM); -++ -++#define __dmac_enable_descriptor(n) \ -++ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_NDES ) -++#define __dmac_disable_descriptor(n) \ -++ ( REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_NDES ) -++ -++#define __dmac_enable_channel(n) \ -++do { \ -++ REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_EN; \ -++} while (0) -++#define __dmac_disable_channel(n) \ -++do { \ -++ REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_EN; \ -++} while (0) -++#define __dmac_channel_enabled(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_EN ) -++ -++#define __dmac_channel_enable_irq(n) \ -++ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_TIE ) -++#define __dmac_channel_disable_irq(n) \ -++ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_TIE ) -++ -++#define __dmac_channel_transmit_halt_detected(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_HLT ) -++#define __dmac_channel_transmit_end_detected(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_TT ) -++#define __dmac_channel_address_error_detected(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_AR ) -++#define __dmac_channel_count_terminated_detected(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_CT ) -++#define __dmac_channel_descriptor_invalid_detected(n) \ -++ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_INV ) -++ -++#define __dmac_channel_clear_transmit_halt(n) \ -++ do { \ -++ /* clear both channel halt error and globle halt error */ \ -++ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_HLT; \ -++ REG_DMAC_DMACR(n/HALF_DMA_NUM) &= ~DMAC_DMACR_HLT; \ -++ } while (0) -++#define __dmac_channel_clear_transmit_end(n) \ -++ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_TT ) -++#define __dmac_channel_clear_address_error(n) \ -++ do { \ -++ REG_DMAC_DDA(n) = 0; /* clear descriptor address register */ \ -++ REG_DMAC_DSAR(n) = 0; /* clear source address register */ \ -++ REG_DMAC_DTAR(n) = 0; /* clear target address register */ \ -++ /* clear both channel addr error and globle address error */ \ -++ REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_AR; \ -++ REG_DMAC_DMACR(n/HALF_DMA_NUM) &= ~DMAC_DMACR_AR; \ -++ } while (0) -++#define __dmac_channel_clear_count_terminated(n) \ -++ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_CT ) -++#define __dmac_channel_clear_descriptor_invalid(n) \ -++ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_INV ) -++ -++#define __dmac_channel_set_transfer_unit_32bit(n) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BIT; \ -++} while (0) -++ -++#define __dmac_channel_set_transfer_unit_16bit(n) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BIT; \ -++} while (0) -++ -++#define __dmac_channel_set_transfer_unit_8bit(n) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_8BIT; \ -++} while (0) -++ -++#define __dmac_channel_set_transfer_unit_16byte(n) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BYTE; \ -++} while (0) -++ -++#define __dmac_channel_set_transfer_unit_32byte(n) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BYTE; \ -++} while (0) -++ -++/* w=8,16,32 */ -++#define __dmac_channel_set_dest_port_width(n,w) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DWDH_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DWDH_##w; \ -++} while (0) -++ -++/* w=8,16,32 */ -++#define __dmac_channel_set_src_port_width(n,w) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SWDH_MASK; \ -++ REG_DMAC_DCMD((n)) |= DMAC_DCMD_SWDH_##w; \ -++} while (0) -++ -++/* v=0-15 */ -++#define __dmac_channel_set_rdil(n,v) \ -++do { \ -++ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_RDIL_MASK; \ -++ REG_DMAC_DCMD((n) |= ((v) << DMAC_DCMD_RDIL_BIT); \ -++} while (0) -++ -++#define __dmac_channel_dest_addr_fixed(n) \ -++ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DAI ) -++#define __dmac_channel_dest_addr_increment(n) \ -++ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_DAI ) -++ -++#define __dmac_channel_src_addr_fixed(n) \ -++ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SAI ) -++#define __dmac_channel_src_addr_increment(n) \ -++ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_SAI ) -++ -++#define __dmac_channel_set_doorbell(n) \ -++ ( REG_DMAC_DMADBSR((n)/HALF_DMA_NUM) = (1 << ((n)-(n)/HALF_DMA_NUM*HALF_DMA_NUM)) ) -++ -++#define __dmac_channel_irq_detected(n) ( REG_DMAC_DMAIPR((n)/HALF_DMA_NUM) & (1 << ((n)-(n)/HALF_DMA_NUM*HALF_DMA_NUM)) ) -++#define __dmac_channel_ack_irq(n) ( REG_DMAC_DMAIPR((n)/HALF_DMA_NUM) &= ~(1 <<((n)-(n)/HALF_DMA_NUM*HALF_DMA_NUM)) ) -++ -++static __inline__ int __dmac_get_irq(void) -++{ -++ int i; -++ for (i = 0; i < MAX_DMA_NUM; i++) -++ if (__dmac_channel_irq_detected(i)) -++ return i; -++ return -1; -++} -++ -++ -++/*************************************************************************** -++ * AIC (AC'97 & I2S Controller) -++ ***************************************************************************/ -++ -++#define __aic_enable() ( REG_AIC_FR |= AIC_FR_ENB ) -++#define __aic_disable() ( REG_AIC_FR &= ~AIC_FR_ENB ) -++ -++#define __aic_select_ac97() ( REG_AIC_FR &= ~AIC_FR_AUSEL ) -++#define __aic_select_i2s() ( REG_AIC_FR |= AIC_FR_AUSEL ) -++ -++#define __aic_play_zero() ( REG_AIC_FR &= ~AIC_FR_LSMP ) -++#define __aic_play_lastsample() ( REG_AIC_FR |= AIC_FR_LSMP ) -++ -++#define __i2s_as_master() ( REG_AIC_FR |= AIC_FR_BCKD | AIC_FR_SYNCD ) -++#define __i2s_as_slave() ( REG_AIC_FR &= ~(AIC_FR_BCKD | AIC_FR_SYNCD) ) -++#define __aic_reset_status() ( REG_AIC_FR & AIC_FR_RST ) -++ -++#define __aic_reset() \ -++do { \ -++ REG_AIC_FR |= AIC_FR_RST; \ -++} while(0) -++ -++ -++#define __aic_set_transmit_trigger(n) \ -++do { \ -++ REG_AIC_FR &= ~AIC_FR_TFTH_MASK; \ -++ REG_AIC_FR |= ((n) << AIC_FR_TFTH_BIT); \ -++} while(0) -++ -++#define __aic_set_receive_trigger(n) \ -++do { \ -++ REG_AIC_FR &= ~AIC_FR_RFTH_MASK; \ -++ REG_AIC_FR |= ((n) << AIC_FR_RFTH_BIT); \ -++} while(0) -++ -++#define __aic_enable_record() ( REG_AIC_CR |= AIC_CR_EREC ) -++#define __aic_disable_record() ( REG_AIC_CR &= ~AIC_CR_EREC ) -++#define __aic_enable_replay() ( REG_AIC_CR |= AIC_CR_ERPL ) -++#define __aic_disable_replay() ( REG_AIC_CR &= ~AIC_CR_ERPL ) -++#define __aic_enable_loopback() ( REG_AIC_CR |= AIC_CR_ENLBF ) -++#define __aic_disable_loopback() ( REG_AIC_CR &= ~AIC_CR_ENLBF ) -++ -++#define __aic_flush_fifo() ( REG_AIC_CR |= AIC_CR_FLUSH ) -++#define __aic_unflush_fifo() ( REG_AIC_CR &= ~AIC_CR_FLUSH ) -++ -++#define __aic_enable_transmit_intr() \ -++ ( REG_AIC_CR |= (AIC_CR_ETFS | AIC_CR_ETUR) ) -++#define __aic_disable_transmit_intr() \ -++ ( REG_AIC_CR &= ~(AIC_CR_ETFS | AIC_CR_ETUR) ) -++#define __aic_enable_receive_intr() \ -++ ( REG_AIC_CR |= (AIC_CR_ERFS | AIC_CR_EROR) ) -++#define __aic_disable_receive_intr() \ -++ ( REG_AIC_CR &= ~(AIC_CR_ERFS | AIC_CR_EROR) ) -++ -++#define __aic_enable_transmit_dma() ( REG_AIC_CR |= AIC_CR_TDMS ) -++#define __aic_disable_transmit_dma() ( REG_AIC_CR &= ~AIC_CR_TDMS ) -++#define __aic_enable_receive_dma() ( REG_AIC_CR |= AIC_CR_RDMS ) -++#define __aic_disable_receive_dma() ( REG_AIC_CR &= ~AIC_CR_RDMS ) -++ -++#define __aic_enable_mono2stereo() ( REG_AIC_CR |= AIC_CR_M2S ) -++#define __aic_disable_mono2stereo() ( REG_AIC_CR &= ~AIC_CR_M2S ) -++#define __aic_enable_byteswap() ( REG_AIC_CR |= AIC_CR_ENDSW ) -++#define __aic_disable_byteswap() ( REG_AIC_CR &= ~AIC_CR_ENDSW ) -++#define __aic_enable_unsignadj() ( REG_AIC_CR |= AIC_CR_AVSTSU ) -++#define __aic_disable_unsignadj() ( REG_AIC_CR &= ~AIC_CR_AVSTSU ) -++ -++#define AC97_PCM_XS_L_FRONT AIC_ACCR1_XS_SLOT3 -++#define AC97_PCM_XS_R_FRONT AIC_ACCR1_XS_SLOT4 -++#define AC97_PCM_XS_CENTER AIC_ACCR1_XS_SLOT6 -++#define AC97_PCM_XS_L_SURR AIC_ACCR1_XS_SLOT7 -++#define AC97_PCM_XS_R_SURR AIC_ACCR1_XS_SLOT8 -++#define AC97_PCM_XS_LFE AIC_ACCR1_XS_SLOT9 -++ -++#define AC97_PCM_RS_L_FRONT AIC_ACCR1_RS_SLOT3 -++#define AC97_PCM_RS_R_FRONT AIC_ACCR1_RS_SLOT4 -++#define AC97_PCM_RS_CENTER AIC_ACCR1_RS_SLOT6 -++#define AC97_PCM_RS_L_SURR AIC_ACCR1_RS_SLOT7 -++#define AC97_PCM_RS_R_SURR AIC_ACCR1_RS_SLOT8 -++#define AC97_PCM_RS_LFE AIC_ACCR1_RS_SLOT9 -++ -++#define __ac97_set_xs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK ) -++#define __ac97_set_xs_mono() \ -++do { \ -++ REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \ -++ REG_AIC_ACCR1 |= AC97_PCM_XS_R_FRONT; \ -++} while(0) -++#define __ac97_set_xs_stereo() \ -++do { \ -++ REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \ -++ REG_AIC_ACCR1 |= AC97_PCM_XS_L_FRONT | AC97_PCM_XS_R_FRONT; \ -++} while(0) -++ -++/* In fact, only stereo is support now. */ -++#define __ac97_set_rs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK ) -++#define __ac97_set_rs_mono() \ -++do { \ -++ REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \ -++ REG_AIC_ACCR1 |= AC97_PCM_RS_R_FRONT; \ -++} while(0) -++#define __ac97_set_rs_stereo() \ -++do { \ -++ REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \ -++ REG_AIC_ACCR1 |= AC97_PCM_RS_L_FRONT | AC97_PCM_RS_R_FRONT; \ -++} while(0) -++ -++#define __ac97_warm_reset_codec() \ -++ do { \ -++ REG_AIC_ACCR2 |= AIC_ACCR2_SA; \ -++ REG_AIC_ACCR2 |= AIC_ACCR2_SS; \ -++ udelay(2); \ -++ REG_AIC_ACCR2 &= ~AIC_ACCR2_SS; \ -++ REG_AIC_ACCR2 &= ~AIC_ACCR2_SA; \ -++ } while (0) -++ -++#define __ac97_cold_reset_codec() \ -++ do { \ -++ REG_AIC_ACCR2 |= AIC_ACCR2_SR; \ -++ udelay(2); \ -++ REG_AIC_ACCR2 &= ~AIC_ACCR2_SR; \ -++ } while (0) -++ -++/* n=8,16,18,20 */ -++#define __ac97_set_iass(n) \ -++ ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_IASS_MASK) | AIC_ACCR2_IASS_##n##BIT ) -++#define __ac97_set_oass(n) \ -++ ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_OASS_MASK) | AIC_ACCR2_OASS_##n##BIT ) -++ -++#define __i2s_select_i2s() ( REG_AIC_I2SCR &= ~AIC_I2SCR_AMSL ) -++#define __i2s_select_msbjustified() ( REG_AIC_I2SCR |= AIC_I2SCR_AMSL ) -++ -++/* n=8,16,18,20,24 */ -++/*#define __i2s_set_sample_size(n) \ -++ ( REG_AIC_I2SCR |= (REG_AIC_I2SCR & ~AIC_I2SCR_WL_MASK) | AIC_I2SCR_WL_##n##BIT )*/ -++ -++#define __i2s_set_oss_sample_size(n) \ -++ ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_OSS_MASK) | AIC_CR_OSS_##n##BIT ) -++#define __i2s_set_iss_sample_size(n) \ -++ ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_ISS_MASK) | AIC_CR_ISS_##n##BIT ) -++ -++#define __i2s_stop_bitclk() ( REG_AIC_I2SCR |= AIC_I2SCR_STPBK ) -++#define __i2s_start_bitclk() ( REG_AIC_I2SCR &= ~AIC_I2SCR_STPBK ) -++ -++#define __aic_transmit_request() ( REG_AIC_SR & AIC_SR_TFS ) -++#define __aic_receive_request() ( REG_AIC_SR & AIC_SR_RFS ) -++#define __aic_transmit_underrun() ( REG_AIC_SR & AIC_SR_TUR ) -++#define __aic_receive_overrun() ( REG_AIC_SR & AIC_SR_ROR ) -++ -++#define __aic_clear_errors() ( REG_AIC_SR &= ~(AIC_SR_TUR | AIC_SR_ROR) ) -++ -++#define __aic_get_transmit_resident() \ -++ ( (REG_AIC_SR & AIC_SR_TFL_MASK) >> AIC_SR_TFL_BIT ) -++#define __aic_get_receive_count() \ -++ ( (REG_AIC_SR & AIC_SR_RFL_MASK) >> AIC_SR_RFL_BIT ) -++ -++#define __ac97_command_transmitted() ( REG_AIC_ACSR & AIC_ACSR_CADT ) -++#define __ac97_status_received() ( REG_AIC_ACSR & AIC_ACSR_SADR ) -++#define __ac97_status_receive_timeout() ( REG_AIC_ACSR & AIC_ACSR_RSTO ) -++#define __ac97_codec_is_low_power_mode() ( REG_AIC_ACSR & AIC_ACSR_CLPM ) -++#define __ac97_codec_is_ready() ( REG_AIC_ACSR & AIC_ACSR_CRDY ) -++#define __ac97_slot_error_detected() ( REG_AIC_ACSR & AIC_ACSR_SLTERR ) -++#define __ac97_clear_slot_error() ( REG_AIC_ACSR &= ~AIC_ACSR_SLTERR ) -++ -++#define __i2s_is_busy() ( REG_AIC_I2SSR & AIC_I2SSR_BSY ) -++ -++#define CODEC_READ_CMD (1 << 19) -++#define CODEC_WRITE_CMD (0 << 19) -++#define CODEC_REG_INDEX_BIT 12 -++#define CODEC_REG_INDEX_MASK (0x7f << CODEC_REG_INDEX_BIT) /* 18:12 */ -++#define CODEC_REG_DATA_BIT 4 -++#define CODEC_REG_DATA_MASK (0x0ffff << 4) /* 19:4 */ -++ -++#define __ac97_out_rcmd_addr(reg) \ -++do { \ -++ REG_AIC_ACCAR = CODEC_READ_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ -++} while (0) -++ -++#define __ac97_out_wcmd_addr(reg) \ -++do { \ -++ REG_AIC_ACCAR = CODEC_WRITE_CMD | ((reg) << CODEC_REG_INDEX_BIT); \ -++} while (0) -++ -++#define __ac97_out_data(value) \ -++do { \ -++ REG_AIC_ACCDR = ((value) << CODEC_REG_DATA_BIT); \ -++} while (0) -++ -++#define __ac97_in_data() \ -++ ( (REG_AIC_ACSDR & CODEC_REG_DATA_MASK) >> CODEC_REG_DATA_BIT ) -++ -++#define __ac97_in_status_addr() \ -++ ( (REG_AIC_ACSAR & CODEC_REG_INDEX_MASK) >> CODEC_REG_INDEX_BIT ) -++ -++#define __i2s_set_sample_rate(i2sclk, sync) \ -++ ( REG_AIC_I2SDIV = ((i2sclk) / (4*64)) / (sync) ) -++ -++#define __aic_write_tfifo(v) ( REG_AIC_DR = (v) ) -++#define __aic_read_rfifo() ( REG_AIC_DR ) -++ -++#define __aic_internal_codec() ( REG_AIC_FR |= AIC_FR_ICDC ) -++#define __aic_external_codec() ( REG_AIC_FR &= ~AIC_FR_ICDC ) -++ -++// -++// Define next ops for AC97 compatible -++// -++ -++#define AC97_ACSR AIC_ACSR -++ -++#define __ac97_enable() __aic_enable(); __aic_select_ac97() -++#define __ac97_disable() __aic_disable() -++#define __ac97_reset() __aic_reset() -++ -++#define __ac97_set_transmit_trigger(n) __aic_set_transmit_trigger(n) -++#define __ac97_set_receive_trigger(n) __aic_set_receive_trigger(n) -++ -++#define __ac97_enable_record() __aic_enable_record() -++#define __ac97_disable_record() __aic_disable_record() -++#define __ac97_enable_replay() __aic_enable_replay() -++#define __ac97_disable_replay() __aic_disable_replay() -++#define __ac97_enable_loopback() __aic_enable_loopback() -++#define __ac97_disable_loopback() __aic_disable_loopback() -++ -++#define __ac97_enable_transmit_dma() __aic_enable_transmit_dma() -++#define __ac97_disable_transmit_dma() __aic_disable_transmit_dma() -++#define __ac97_enable_receive_dma() __aic_enable_receive_dma() -++#define __ac97_disable_receive_dma() __aic_disable_receive_dma() -++ -++#define __ac97_transmit_request() __aic_transmit_request() -++#define __ac97_receive_request() __aic_receive_request() -++#define __ac97_transmit_underrun() __aic_transmit_underrun() -++#define __ac97_receive_overrun() __aic_receive_overrun() -++ -++#define __ac97_clear_errors() __aic_clear_errors() -++ -++#define __ac97_get_transmit_resident() __aic_get_transmit_resident() -++#define __ac97_get_receive_count() __aic_get_receive_count() -++ -++#define __ac97_enable_transmit_intr() __aic_enable_transmit_intr() -++#define __ac97_disable_transmit_intr() __aic_disable_transmit_intr() -++#define __ac97_enable_receive_intr() __aic_enable_receive_intr() -++#define __ac97_disable_receive_intr() __aic_disable_receive_intr() -++ -++#define __ac97_write_tfifo(v) __aic_write_tfifo(v) -++#define __ac97_read_rfifo() __aic_read_rfifo() -++ -++// -++// Define next ops for I2S compatible -++// -++ -++#define I2S_ACSR AIC_I2SSR -++ -++#define __i2s_enable() __aic_enable(); __aic_select_i2s() -++#define __i2s_disable() __aic_disable() -++#define __i2s_reset() __aic_reset() -++ -++#define __i2s_set_transmit_trigger(n) __aic_set_transmit_trigger(n) -++#define __i2s_set_receive_trigger(n) __aic_set_receive_trigger(n) -++ -++#define __i2s_enable_record() __aic_enable_record() -++#define __i2s_disable_record() __aic_disable_record() -++#define __i2s_enable_replay() __aic_enable_replay() -++#define __i2s_disable_replay() __aic_disable_replay() -++#define __i2s_enable_loopback() __aic_enable_loopback() -++#define __i2s_disable_loopback() __aic_disable_loopback() -++ -++#define __i2s_enable_transmit_dma() __aic_enable_transmit_dma() -++#define __i2s_disable_transmit_dma() __aic_disable_transmit_dma() -++#define __i2s_enable_receive_dma() __aic_enable_receive_dma() -++#define __i2s_disable_receive_dma() __aic_disable_receive_dma() -++ -++#define __i2s_transmit_request() __aic_transmit_request() -++#define __i2s_receive_request() __aic_receive_request() -++#define __i2s_transmit_underrun() __aic_transmit_underrun() -++#define __i2s_receive_overrun() __aic_receive_overrun() -++ -++#define __i2s_clear_errors() __aic_clear_errors() -++ -++#define __i2s_get_transmit_resident() __aic_get_transmit_resident() -++#define __i2s_get_receive_count() __aic_get_receive_count() -++ -++#define __i2s_enable_transmit_intr() __aic_enable_transmit_intr() -++#define __i2s_disable_transmit_intr() __aic_disable_transmit_intr() -++#define __i2s_enable_receive_intr() __aic_enable_receive_intr() -++#define __i2s_disable_receive_intr() __aic_disable_receive_intr() -++ -++#define __i2s_write_tfifo(v) __aic_write_tfifo(v) -++#define __i2s_read_rfifo() __aic_read_rfifo() -++ -++#define __i2s_reset_codec() \ -++ do { \ -++ } while (0) -++ -++/************************************************************************* -++ * PCM Controller operation -++ *************************************************************************/ -++ -++#define __pcm_enable() ( REG_PCM_CTL |= PCM_CTL_PCMEN ) -++#define __pcm_disable() ( REG_PCM_CTL &= ~PCM_CTL_PCMEN ) -++ -++#define __pcm_clk_enable() ( REG_PCM_CTL |= PCM_CTL_CLKEN ) -++#define __pcm_clk_disable() ( REG_PCM_CTL &= ~PCM_CTL_CLKEN ) -++ -++#define __pcm_reset() ( REG_PCM_CTL |= PCM_CTL_RST ) -++#define __pcm_flush_fifo() ( REG_PCM_CTL |= PCM_CTL_FLUSH ) -++ -++#define __pcm_enable_record() ( REG_PCM_CTL |= PCM_CTL_EREC ) -++#define __pcm_disable_record() ( REG_PCM_CTL &= ~PCM_CTL_EREC ) -++#define __pcm_enable_playback() ( REG_PCM_CTL |= PCM_CTL_ERPL ) -++#define __pcm_disable_playback() ( REG_PCM_CTL &= ~PCM_CTL_ERPL ) -++ -++#define __pcm_enable_rxfifo() __pcm_enable_record() -++#define __pcm_disable_rxfifo() __pcm_disable_record() -++#define __pcm_enable_txfifo() __pcm_enable_playback() -++#define __pcm_disable_txfifo() __pcm_disable_playback() -++ -++#define __pcm_last_sample() ( REG_PCM_CTL |= PCM_CTL_LSMP ) -++#define __pcm_zero_sample() ( REG_PCM_CTL &= ~PCM_CTL_LSMP ) -++ -++#define __pcm_enable_transmit_dma() ( REG_PCM_CTL |= PCM_CTL_ETDMA ) -++#define __pcm_disable_transmit_dma() ( REG_PCM_CTL &= ~PCM_CTL_ETDMA ) -++#define __pcm_enable_receive_dma() ( REG_PCM_CTL |= PCM_CTL_ERDMA ) -++#define __pcm_disable_receive_dma() ( REG_PCM_CTL &= ~PCM_CTL_ERDMA ) -++ -++#define __pcm_as_master() ( REG_PCM_CFG &= PCM_CFG_MODE ) -++#define __pcm_as_slave() ( REG_PCM_CFG |= ~PCM_CFG_MODE ) -++ -++#define __pcm_set_transmit_trigger(n) \ -++do { \ -++ REG_PCM_CFG &= ~PCM_CFG_TFTH_MASK; \ -++ REG_PCM_CFG |= ((n) << PCM_CFG_TFTH_BIT); \ -++} while(0) -++ -++#define __pcm_set_receive_trigger(n) \ -++do { \ -++ REG_PCM_CFG &= ~PCM_CFG_RFTH_MASK; \ -++ REG_PCM_CFG |= ((n) << PCM_CFG_RFTH_BIT); \ -++} while(0) -++ -++#define __pcm_omsb_same_sync() ( REG_PCM_CFG &= ~PCM_CFG_OMSBPOS ) -++#define __pcm_omsb_next_sync() ( REG_PCM_CFG |= PCM_CFG_OMSBPOS ) -++ -++#define __pcm_imsb_same_sync() ( REG_PCM_CFG &= ~PCM_CFG_IMSBPOS ) -++#define __pcm_imsb_next_sync() ( REG_PCM_CFG |= PCM_CFG_IMSBPOS ) -++ -++/* set input sample size 8 or 16*/ -++#define __pcm_set_iss(n) \ -++( REG_PCM_CFG = (REG_PCM_CFG & ~PCM_CFG_ISS_MASK) | PCM_CFG_ISS_##n ) -++/* set output sample size 8 or 16*/ -++#define __pcm_set_oss(n) \ -++( REG_PCM_CFG = (REG_PCM_CFG & ~PCM_CFG_OSS_MASK) | PCM_CFG_OSS_##n ) -++ -++#define __pcm_set_valid_slot(n) \ -++( REG_PCM_CFG = (REG_PCM_CFG & ~PCM_CFG_SLOT_MASK) | PCM_CFG_SLOT_##n ) -++ -++#define __pcm_write_data(v) ( REG_PCM_DP = (v) ) -++#define __pcm_read_data() ( REG_PCM_DP ) -++ -++#define __pcm_enable_tfs_intr() ( REG_PCM_INTC |= PCM_INTC_ETFS ) -++#define __pcm_disable_tfs_intr() ( REG_PCM_INTC &= ~PCM_INTC_ETFS ) -++ -++#define __pcm_enable_tur_intr() ( REG_PCM_INTC |= PCM_INTC_ETUR ) -++#define __pcm_disable_tur_intr() ( REG_PCM_INTC &= ~PCM_INTC_ETUR ) -++ -++#define __pcm_enable_rfs_intr() ( REG_PCM_INTC |= PCM_INTC_ERFS ) -++#define __pcm_disable_rfs_intr() ( REG_PCM_INTC &= ~PCM_INTC_ERFS ) -++ -++#define __pcm_enable_ror_intr() ( REG_PCM_INTC |= PCM_INTC_EROR ) -++#define __pcm_disable_ror_intr() ( REG_PCM_INTC &= ~PCM_INTC_EROR ) -++ -++#define __pcm_ints_valid_tx() \ -++( ((REG_PCM_INTS & PCM_INTS_TFL_MASK) >> PCM_INTS_TFL_BIT) ) -++#define __pcm_ints_valid_rx() \ -++( ((REG_PCM_INTS & PCM_INTS_RFL_MASK) >> PCM_INTS_RFL_BIT) ) -++ -++#define __pcm_set_clk_div(n) \ -++( REG_PCM_DIV = (REG_PCM_DIV & ~PCM_DIV_CLKDIV_MASK) | ((n) << PCM_DIV_CLKDIV_BIT) ) -++ -++/* sysclk(cpm_pcm_sysclk) Hz is created by cpm logic, and pcmclk Hz is the pcm in/out clock wanted */ -++#define __pcm_set_clk_rate(sysclk, pcmclk) \ -++__pcm_set_clk_div(((sysclk) / (pcmclk) - 1)) -++ -++#define __pcm_set_sync_div(n) \ -++( REG_PCM_DIV = (REG_PCM_DIV & ~PCM_DIV_SYNDIV_MASK) | ((n) << PCM_DIV_SYNDIV_BIT) ) -++ -++/* pcmclk is source clock Hz, and sync is the frame sync clock Hz wanted */ -++#define __pcm_set_sync_rate(pcmclk, sync) \ -++__pcm_set_sync_div(((pcmclk) / (8 * (sync)) - 1)) -++ -++ /* set sync length in pcmclk n = 0 ... 63 */ -++#define __pcm_set_sync_len(n) \ -++( REG_PCM_DIV = (REG_PCM_DIV & ~PCM_DIV_SYNL_MASK) | (n << PCM_DIV_SYNL_BIT) ) -++ -++ -++/*************************************************************************** -++ * ICDC -++ ***************************************************************************/ -++#define __i2s_internal_codec() __aic_internal_codec() -++#define __i2s_external_codec() __aic_external_codec() -++ -++#define __icdc_clk_ready() ( REG_ICDC_CKCFG & ICDC_CKCFG_CKRDY ) -++#define __icdc_sel_adc() ( REG_ICDC_CKCFG |= ICDC_CKCFG_SELAD ) -++#define __icdc_sel_dac() ( REG_ICDC_CKCFG &= ~ICDC_CKCFG_SELAD ) -++ -++#define __icdc_set_rgwr() ( REG_ICDC_RGADW |= ICDC_RGADW_RGWR ) -++#define __icdc_clear_rgwr() ( REG_ICDC_RGADW &= ~ICDC_RGADW_RGWR ) -++#define __icdc_rgwr_ready() ( REG_ICDC_RGADW & ICDC_RGADW_RGWR ) -++ -++#define __icdc_set_addr(n) \ -++do { \ -++ REG_ICDC_RGADW &= ~ICDC_RGADW_RGADDR_MASK; \ -++ REG_ICDC_RGADW |= (n) << ICDC_RGADW_RGADDR_BIT; \ -++} while(0) -++ -++#define __icdc_set_cmd(n) \ -++do { \ -++ REG_ICDC_RGADW &= ~ICDC_RGADW_RGDIN_MASK; \ -++ REG_ICDC_RGADW |= (n) << ICDC_RGADW_RGDIN_BIT; \ -++} while(0) -++ -++#define __icdc_irq_pending() ( REG_ICDC_RGDATA & ICDC_RGDATA_IRQ ) -++#define __icdc_get_value() ( REG_ICDC_RGDATA & ICDC_RGDATA_RGDOUT_MASK ) -++ -++/*************************************************************************** -++ * INTC -++ ***************************************************************************/ -++#define __intc_unmask_irq(n) ( REG_INTC_IMCR = (1 << (n)) ) -++#define __intc_mask_irq(n) ( REG_INTC_IMSR = (1 << (n)) ) -++#define __intc_ack_irq(n) ( REG_INTC_IPR = (1 << (n)) ) /* A dummy ack, as the Pending Register is Read Only. Should we remove __intc_ack_irq() */ -++ -++ -++/*************************************************************************** -++ * I2C -++ ***************************************************************************/ -++ -++#define __i2c_enable() ( REG_I2C_CR |= I2C_CR_I2CE ) -++#define __i2c_disable() ( REG_I2C_CR &= ~I2C_CR_I2CE ) -++ -++#define __i2c_send_start() ( REG_I2C_CR |= I2C_CR_STA ) -++#define __i2c_send_stop() ( REG_I2C_CR |= I2C_CR_STO ) -++#define __i2c_send_ack() ( REG_I2C_CR &= ~I2C_CR_AC ) -++#define __i2c_send_nack() ( REG_I2C_CR |= I2C_CR_AC ) -++ -++#define __i2c_set_drf() ( REG_I2C_SR |= I2C_SR_DRF ) -++#define __i2c_clear_drf() ( REG_I2C_SR &= ~I2C_SR_DRF ) -++#define __i2c_check_drf() ( REG_I2C_SR & I2C_SR_DRF ) -++ -++#define __i2c_received_ack() ( !(REG_I2C_SR & I2C_SR_ACKF) ) -++#define __i2c_is_busy() ( REG_I2C_SR & I2C_SR_BUSY ) -++#define __i2c_transmit_ended() ( REG_I2C_SR & I2C_SR_TEND ) -++ -++#define __i2c_set_clk(dev_clk, i2c_clk) \ -++ ( REG_I2C_GR = (dev_clk) / (16*(i2c_clk)) - 1 ) -++ -++#define __i2c_read() ( REG_I2C_DR ) -++#define __i2c_write(val) ( REG_I2C_DR = (val) ) -++ -++ -++/*************************************************************************** -++ * MSC -++ ***************************************************************************/ -++/* n = 0, 1 (MSC0, MSC1) */ -++ -++#define __msc_start_op(n) \ -++ ( REG_MSC_STRPCL(n) = MSC_STRPCL_START_OP | MSC_STRPCL_CLOCK_CONTROL_START ) -++ -++#define __msc_set_resto(n, to) ( REG_MSC_RESTO(n) = to ) -++#define __msc_set_rdto(n, to) ( REG_MSC_RDTO(n) = to ) -++#define __msc_set_cmd(n, cmd) ( REG_MSC_CMD(n) = cmd ) -++#define __msc_set_arg(n, arg) ( REG_MSC_ARG(n) = arg ) -++#define __msc_set_nob(n, nob) ( REG_MSC_NOB(n) = nob ) -++#define __msc_get_nob(n) ( REG_MSC_NOB(n) ) -++#define __msc_set_blklen(n, len) ( REG_MSC_BLKLEN(n) = len ) -++#define __msc_set_cmdat(n, cmdat) ( REG_MSC_CMDAT(n) = cmdat ) -++#define __msc_set_cmdat_ioabort(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_IO_ABORT ) -++#define __msc_clear_cmdat_ioabort(n) ( REG_MSC_CMDAT(n) &= ~MSC_CMDAT_IO_ABORT ) -++ -++#define __msc_set_cmdat_bus_width1(n) \ -++do { \ -++ REG_MSC_CMDAT(n) &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ -++ REG_MSC_CMDAT(n) |= MSC_CMDAT_BUS_WIDTH_1BIT; \ -++} while(0) -++ -++#define __msc_set_cmdat_bus_width4(n) \ -++do { \ -++ REG_MSC_CMDAT(n) &= ~MSC_CMDAT_BUS_WIDTH_MASK; \ -++ REG_MSC_CMDAT(n) |= MSC_CMDAT_BUS_WIDTH_4BIT; \ -++} while(0) -++ -++#define __msc_set_cmdat_dma_en(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_DMA_EN ) -++#define __msc_set_cmdat_init(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_INIT ) -++#define __msc_set_cmdat_busy(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_BUSY ) -++#define __msc_set_cmdat_stream(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_STREAM_BLOCK ) -++#define __msc_set_cmdat_block(n) ( REG_MSC_CMDAT(n) &= ~MSC_CMDAT_STREAM_BLOCK ) -++#define __msc_set_cmdat_read(n) ( REG_MSC_CMDAT(n) &= ~MSC_CMDAT_WRITE_READ ) -++#define __msc_set_cmdat_write(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_WRITE_READ ) -++#define __msc_set_cmdat_data_en(n) ( REG_MSC_CMDAT(n) |= MSC_CMDAT_DATA_EN ) -++ -++/* r is MSC_CMDAT_RESPONSE_FORMAT_Rx or MSC_CMDAT_RESPONSE_FORMAT_NONE */ -++#define __msc_set_cmdat_res_format(n, r) \ -++do { \ -++ REG_MSC_CMDAT(n) &= ~MSC_CMDAT_RESPONSE_FORMAT_MASK; \ -++ REG_MSC_CMDAT(n) |= (r); \ -++} while(0) -++ -++#define __msc_clear_cmdat(n) \ -++ REG_MSC_CMDAT(n) &= ~( MSC_CMDAT_IO_ABORT | MSC_CMDAT_DMA_EN | MSC_CMDAT_INIT| \ -++ MSC_CMDAT_BUSY | MSC_CMDAT_STREAM_BLOCK | MSC_CMDAT_WRITE_READ | \ -++ MSC_CMDAT_DATA_EN | MSC_CMDAT_RESPONSE_FORMAT_MASK ) -++ -++#define __msc_get_imask(n) ( REG_MSC_IMASK(n) ) -++#define __msc_mask_all_intrs(n) ( REG_MSC_IMASK(n) = 0xff ) -++#define __msc_unmask_all_intrs(n) ( REG_MSC_IMASK(n) = 0x00 ) -++#define __msc_mask_rd(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_RXFIFO_RD_REQ ) -++#define __msc_unmask_rd(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_RXFIFO_RD_REQ ) -++#define __msc_mask_wr(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_TXFIFO_WR_REQ ) -++#define __msc_unmask_wr(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_TXFIFO_WR_REQ ) -++#define __msc_mask_endcmdres(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_END_CMD_RES ) -++#define __msc_unmask_endcmdres(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_END_CMD_RES ) -++#define __msc_mask_datatrandone(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_DATA_TRAN_DONE ) -++#define __msc_unmask_datatrandone(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_DATA_TRAN_DONE ) -++#define __msc_mask_prgdone(n) ( REG_MSC_IMASK(n) |= MSC_IMASK_PRG_DONE ) -++#define __msc_unmask_prgdone(n) ( REG_MSC_IMASK(n) &= ~MSC_IMASK_PRG_DONE ) -++ -++/* m=0,1,2,3,4,5,6,7 */ -++#define __msc_set_clkrt(n, m) \ -++do { \ -++ REG_MSC_CLKRT(n) = m; \ -++} while(0) -++ -++#define __msc_get_ireg(n) ( REG_MSC_IREG(n) ) -++#define __msc_ireg_rd(n) ( REG_MSC_IREG(n) & MSC_IREG_RXFIFO_RD_REQ ) -++#define __msc_ireg_wr(n) ( REG_MSC_IREG(n) & MSC_IREG_TXFIFO_WR_REQ ) -++#define __msc_ireg_end_cmd_res(n) ( REG_MSC_IREG(n) & MSC_IREG_END_CMD_RES ) -++#define __msc_ireg_data_tran_done(n) ( REG_MSC_IREG(n) & MSC_IREG_DATA_TRAN_DONE ) -++#define __msc_ireg_prg_done(n) ( REG_MSC_IREG(n) & MSC_IREG_PRG_DONE ) -++#define __msc_ireg_clear_end_cmd_res(n) ( REG_MSC_IREG(n) = MSC_IREG_END_CMD_RES ) -++#define __msc_ireg_clear_data_tran_done(n) ( REG_MSC_IREG(n) = MSC_IREG_DATA_TRAN_DONE ) -++#define __msc_ireg_clear_prg_done(n) ( REG_MSC_IREG(n) = MSC_IREG_PRG_DONE ) -++ -++#define __msc_get_stat(n) ( REG_MSC_STAT(n) ) -++#define __msc_stat_not_end_cmd_res(n) ( (REG_MSC_STAT(n) & MSC_STAT_END_CMD_RES) == 0) -++#define __msc_stat_crc_err(n) \ -++ ( REG_MSC_STAT(n) & (MSC_STAT_CRC_RES_ERR | MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR_YES) ) -++#define __msc_stat_res_crc_err(n) ( REG_MSC_STAT(n) & MSC_STAT_CRC_RES_ERR ) -++#define __msc_stat_rd_crc_err(n) ( REG_MSC_STAT(n) & MSC_STAT_CRC_READ_ERROR ) -++#define __msc_stat_wr_crc_err(n) ( REG_MSC_STAT(n) & MSC_STAT_CRC_WRITE_ERROR_YES ) -++#define __msc_stat_resto_err(n) ( REG_MSC_STAT(n) & MSC_STAT_TIME_OUT_RES ) -++#define __msc_stat_rdto_err(n) ( REG_MSC_STAT(n) & MSC_STAT_TIME_OUT_READ ) -++ -++#define __msc_rd_resfifo(n) ( REG_MSC_RES(n) ) -++#define __msc_rd_rxfifo(n) ( REG_MSC_RXFIFO(n) ) -++#define __msc_wr_txfifo(n, v) ( REG_MSC_TXFIFO(n) = v ) -++ -++#define __msc_reset(n) \ -++do { \ -++ REG_MSC_STRPCL(n) = MSC_STRPCL_RESET; \ -++ while (REG_MSC_STAT(n) & MSC_STAT_IS_RESETTING); \ -++} while (0) -++ -++#define __msc_start_clk(n) \ -++do { \ -++ REG_MSC_STRPCL(n) = MSC_STRPCL_CLOCK_CONTROL_START; \ -++} while (0) -++ -++#define __msc_stop_clk(n) \ -++do { \ -++ REG_MSC_STRPCL(n) = MSC_STRPCL_CLOCK_CONTROL_STOP; \ -++} while (0) -++ -++#define MMC_CLK 19169200 -++#define SD_CLK 24576000 -++ -++/* msc_clk should little than pclk and little than clk retrieve from card */ -++#define __msc_calc_clk_divisor(type,dev_clk,msc_clk,lv) \ -++do { \ -++ unsigned int rate, pclk, i; \ -++ pclk = dev_clk; \ -++ rate = type?SD_CLK:MMC_CLK; \ -++ if (msc_clk && msc_clk < pclk) \ -++ pclk = msc_clk; \ -++ i = 0; \ -++ while (pclk < rate) \ -++ { \ -++ i ++; \ -++ rate >>= 1; \ -++ } \ -++ lv = i; \ -++} while(0) -++ -++/* divide rate to little than or equal to 400kHz */ -++#define __msc_calc_slow_clk_divisor(type, lv) \ -++do { \ -++ unsigned int rate, i; \ -++ rate = (type?SD_CLK:MMC_CLK)/1000/400; \ -++ i = 0; \ -++ while (rate > 0) \ -++ { \ -++ rate >>= 1; \ -++ i ++; \ -++ } \ -++ lv = i; \ -++} while(0) -++ -++ -++/*************************************************************************** -++ * SSI (Synchronous Serial Interface) -++ ***************************************************************************/ -++/* n = 0, 1 (SSI0, SSI1) */ -++#define __ssi_enable(n) ( REG_SSI_CR0(n) |= SSI_CR0_SSIE ) -++#define __ssi_disable(n) ( REG_SSI_CR0(n) &= ~SSI_CR0_SSIE ) -++#define __ssi_select_ce(n) ( REG_SSI_CR0(n) &= ~SSI_CR0_FSEL ) -++ -++#define __ssi_normal_mode(n) ( REG_SSI_ITR(n) &= ~SSI_ITR_IVLTM_MASK ) -++ -++#define __ssi_select_ce2(n) \ -++do { \ -++ REG_SSI_CR0(n) |= SSI_CR0_FSEL; \ -++ REG_SSI_CR1(n) &= ~SSI_CR1_MULTS; \ -++} while (0) -++ -++#define __ssi_select_gpc(n) \ -++do { \ -++ REG_SSI_CR0(n) &= ~SSI_CR0_FSEL; \ -++ REG_SSI_CR1(n) |= SSI_CR1_MULTS; \ -++} while (0) -++ -++#define __ssi_underrun_auto_clear(n) \ -++do { \ -++ REG_SSI_CR0(n) |= SSI_CR0_EACLRUN; \ -++} while (0) -++ -++#define __ssi_underrun_clear_manually(n) \ -++do { \ -++ REG_SSI_CR0(n) &= ~SSI_CR0_EACLRUN; \ -++} while (0) -++ -++#define __ssi_enable_tx_intr(n) \ -++ ( REG_SSI_CR0(n) |= SSI_CR0_TIE | SSI_CR0_TEIE ) -++ -++#define __ssi_disable_tx_intr(n) \ -++ ( REG_SSI_CR0(n) &= ~(SSI_CR0_TIE | SSI_CR0_TEIE) ) -++ -++#define __ssi_enable_rx_intr(n) \ -++ ( REG_SSI_CR0(n) |= SSI_CR0_RIE | SSI_CR0_REIE ) -++ -++#define __ssi_disable_rx_intr(n) \ -++ ( REG_SSI_CR0(n) &= ~(SSI_CR0_RIE | SSI_CR0_REIE) ) -++ -++#define __ssi_enable_txfifo_half_empty_intr(n) \ -++ ( REG_SSI_CR0(n) |= SSI_CR0_TIE ) -++#define __ssi_disable_txfifo_half_empty_intr(n) \ -++ ( REG_SSI_CR0(n) &= ~SSI_CR0_TIE ) -++#define __ssi_enable_tx_error_intr(n) \ -++ ( REG_SSI_CR0(n) |= SSI_CR0_TEIE ) -++#define __ssi_disable_tx_error_intr(n) \ -++ ( REG_SSI_CR0(n) &= ~SSI_CR0_TEIE ) -++#define __ssi_enable_rxfifo_half_full_intr(n) \ -++ ( REG_SSI_CR0(n) |= SSI_CR0_RIE ) -++#define __ssi_disable_rxfifo_half_full_intr(n) \ -++ ( REG_SSI_CR0(n) &= ~SSI_CR0_RIE ) -++#define __ssi_enable_rx_error_intr(n) \ -++ ( REG_SSI_CR0(n) |= SSI_CR0_REIE ) -++#define __ssi_disable_rx_error_intr(n) \ -++ ( REG_SSI_CR0(n) &= ~SSI_CR0_REIE ) -++ -++#define __ssi_enable_loopback(n) ( REG_SSI_CR0(n) |= SSI_CR0_LOOP ) -++#define __ssi_disable_loopback(n) ( REG_SSI_CR0(n) &= ~SSI_CR0_LOOP ) -++ -++#define __ssi_enable_receive(n) ( REG_SSI_CR0(n) &= ~SSI_CR0_DISREV ) -++#define __ssi_disable_receive(n) ( REG_SSI_CR0(n) |= SSI_CR0_DISREV ) -++ -++#define __ssi_finish_receive(n) \ -++ ( REG_SSI_CR0(n) |= (SSI_CR0_RFINE | SSI_CR0_RFINC) ) -++ -++#define __ssi_disable_recvfinish(n) \ -++ ( REG_SSI_CR0(n) &= ~(SSI_CR0_RFINE | SSI_CR0_RFINC) ) -++ -++#define __ssi_flush_txfifo(n) ( REG_SSI_CR0(n) |= SSI_CR0_TFLUSH ) -++#define __ssi_flush_rxfifo(n) ( REG_SSI_CR0(n) |= SSI_CR0_RFLUSH ) -++ -++#define __ssi_flush_fifo(n) \ -++ ( REG_SSI_CR0(n) |= SSI_CR0_TFLUSH | SSI_CR0_RFLUSH ) -++ -++#define __ssi_finish_transmit(n) ( REG_SSI_CR1(n) &= ~SSI_CR1_UNFIN ) -++#define __ssi_wait_transmit(n) ( REG_SSI_CR1(n) |= SSI_CR1_UNFIN ) -++#define __ssi_use_busy_wait_mode(n) __ssi_wait_transmit(n) -++#define __ssi_unset_busy_wait_mode(n) __ssi_finish_transmit(n) -++ -++#define __ssi_spi_format(n) \ -++ do { \ -++ REG_SSI_CR1(n) &= ~SSI_CR1_FMAT_MASK; \ -++ REG_SSI_CR1(n) |= SSI_CR1_FMAT_SPI; \ -++ REG_SSI_CR1(n) &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK); \ -++ REG_SSI_CR1(n) |= (SSI_CR1_TFVCK_1 | SSI_CR1_TCKFI_1); \ -++ } while (0) -++ -++/* TI's SSP format, must clear SSI_CR1.UNFIN */ -++#define __ssi_ssp_format(n) \ -++ do { \ -++ REG_SSI_CR1(n) &= ~(SSI_CR1_FMAT_MASK | SSI_CR1_UNFIN); \ -++ REG_SSI_CR1(n) |= SSI_CR1_FMAT_SSP; \ -++ } while (0) -++ -++/* National's Microwire format, must clear SSI_CR0.RFINE, and set max delay */ -++#define __ssi_microwire_format(n) \ -++ do { \ -++ REG_SSI_CR1(n) &= ~SSI_CR1_FMAT_MASK; \ -++ REG_SSI_CR1(n) |= SSI_CR1_FMAT_MW1; \ -++ REG_SSI_CR1(n) &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK); \ -++ REG_SSI_CR1(n) |= (SSI_CR1_TFVCK_3 | SSI_CR1_TCKFI_3); \ -++ REG_SSI_CR0(n) &= ~SSI_CR0_RFINE; \ -++ } while (0) -++ -++/* CE# level (FRMHL), CE# in interval time (ITFRM), -++ clock phase and polarity (PHA POL), -++ interval time (SSIITR), interval characters/frame (SSIICR) */ -++ -++/* frmhl,endian,mcom,flen,pha,pol MASK */ -++#define SSICR1_MISC_MASK \ -++ ( SSI_CR1_FRMHL_MASK | SSI_CR1_LFST | SSI_CR1_MCOM_MASK \ -++ | SSI_CR1_FLEN_MASK | SSI_CR1_PHA | SSI_CR1_POL ) -++ -++#define __ssi_spi_set_misc(n,frmhl,endian,flen,mcom,pha,pol) \ -++ do { \ -++ REG_SSI_CR1(n) &= ~SSICR1_MISC_MASK; \ -++ REG_SSI_CR1(n) |= ((frmhl) << 30) | ((endian) << 25) | \ -++ (((mcom) - 1) << 12) | (((flen) - 2) << 4) | \ -++ ((pha) << 1) | (pol); \ -++ } while(0) -++ -++/* Transfer with MSB or LSB first */ -++#define __ssi_set_msb(n) ( REG_SSI_CR1(n) &= ~SSI_CR1_LFST ) -++#define __ssi_set_lsb(n) ( REG_SSI_CR1(n) |= SSI_CR1_LFST ) -++ -++#define __ssi_set_frame_length(n, m) \ -++ REG_SSI_CR1(n) = (REG_SSI_CR1(n) & ~SSI_CR1_FLEN_MASK) | (((m) - 2) << 4) -++ -++/* m = 1 - 16 */ -++#define __ssi_set_microwire_command_length(n,m) \ -++ ( REG_SSI_CR1(n) = ((REG_SSI_CR1(n) & ~SSI_CR1_MCOM_MASK) | SSI_CR1_MCOM_##m##BIT) ) -++ -++/* Set the clock phase for SPI */ -++#define __ssi_set_spi_clock_phase(n, m) \ -++ ( REG_SSI_CR1(n) = ((REG_SSI_CR1(n) & ~SSI_CR1_PHA) | (((m)&0x1)<< 1))) -++ -++/* Set the clock polarity for SPI */ -++#define __ssi_set_spi_clock_polarity(n, p) \ -++ ( REG_SSI_CR1(n) = ((REG_SSI_CR1(n) & ~SSI_CR1_POL) | ((p)&0x1)) ) -++ -++/* SSI tx trigger, m = i x 8 */ -++#define __ssi_set_tx_trigger(n, m) \ -++ do { \ -++ REG_SSI_CR1(n) &= ~SSI_CR1_TTRG_MASK; \ -++ REG_SSI_CR1(n) |= ((m)/8)<> SSI_SR_TFIFONUM_BIT ) -++ -++#define __ssi_get_rxfifo_count(n) \ -++ ( (REG_SSI_SR(n) & SSI_SR_RFIFONUM_MASK) >> SSI_SR_RFIFONUM_BIT ) -++ -++#define __ssi_transfer_end(n) ( REG_SSI_SR(n) & SSI_SR_END ) -++#define __ssi_is_busy(n) ( REG_SSI_SR(n) & SSI_SR_BUSY ) -++ -++#define __ssi_txfifo_full(n) ( REG_SSI_SR(n) & SSI_SR_TFF ) -++#define __ssi_rxfifo_empty(n) ( REG_SSI_SR(n) & SSI_SR_RFE ) -++#define __ssi_rxfifo_half_full(n) ( REG_SSI_SR(n) & SSI_SR_RFHF ) -++#define __ssi_txfifo_half_empty(n) ( REG_SSI_SR(n) & SSI_SR_TFHE ) -++#define __ssi_underrun(n) ( REG_SSI_SR(n) & SSI_SR_UNDR ) -++#define __ssi_overrun(n) ( REG_SSI_SR(n) & SSI_SR_OVER ) -++#define __ssi_clear_underrun(n) ( REG_SSI_SR(n) = ~SSI_SR_UNDR ) -++#define __ssi_clear_overrun(n) ( REG_SSI_SR(n) = ~SSI_SR_OVER ) -++#define __ssi_clear_errors(n) ( REG_SSI_SR(n) &= ~(SSI_SR_UNDR | SSI_SR_OVER) ) -++ -++#define __ssi_set_clk(n, dev_clk, ssi_clk) \ -++ ( REG_SSI_GR(n) = (dev_clk) / (2*(ssi_clk)) - 1 ) -++ -++#define __ssi_receive_data(n) REG_SSI_DR(n) -++#define __ssi_transmit_data(n, v) (REG_SSI_DR(n) = (v)) -++ -++ -++/*************************************************************************** -++ * CIM -++ ***************************************************************************/ -++ -++#define __cim_enable() ( REG_CIM_CTRL |= CIM_CTRL_ENA ) -++#define __cim_disable() ( REG_CIM_CTRL &= ~CIM_CTRL_ENA ) -++ -++/* n = 0, 1, 2, 3 */ -++#define __cim_set_input_data_stream_order(n) \ -++ do { \ -++ REG_CIM_CFG &= CIM_CFG_ORDER_MASK; \ -++ REG_CIM_CFG |= ((n)<>CIM_SIZE_LPF_BIT) -++#define __cim_get_pixel() ((REG_CIM_SIZE&CIM_SIZE_PPL_MASK)>>CIM_SIZE_PPL_BIT) -++ -++#define __cim_set_v_offset(a) ( REG_CIM_OFFSET = (REG_CIM_OFFSET&(~CIM_OFFSET_V_MASK)) | ((a)<>CIM_OFFSET_V_BIT) -++#define __cim_get_h_offset() ((REG_CIM_OFFSET&CIM_OFFSET_H_MASK)>>CIM_OFFSET_H_BIT) -++ -++/************************************************************************* -++ * SLCD (Smart LCD Controller) -++ *************************************************************************/ -++#define __slcd_set_data_18bit() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_18BIT ) -++#define __slcd_set_data_16bit() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_16BIT ) -++#define __slcd_set_data_8bit_x3() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_8BIT_x3 ) -++#define __slcd_set_data_8bit_x2() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_8BIT_x2 ) -++#define __slcd_set_data_8bit_x1() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_8BIT_x1 ) -++#define __slcd_set_data_24bit() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_24BIT ) -++#define __slcd_set_data_9bit_x2() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_DWIDTH_MASK) | SLCD_CFG_DWIDTH_9BIT_x2 ) -++ -++#define __slcd_set_cmd_16bit() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_CWIDTH_MASK) | SLCD_CFG_CWIDTH_16BIT ) -++#define __slcd_set_cmd_8bit() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_CWIDTH_MASK) | SLCD_CFG_CWIDTH_8BIT ) -++#define __slcd_set_cmd_18bit() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_CWIDTH_MASK) | SLCD_CFG_CWIDTH_18BIT ) -++#define __slcd_set_cmd_24bit() \ -++ ( REG_SLCD_CFG = (REG_SLCD_CFG & ~SLCD_CFG_CWIDTH_MASK) | SLCD_CFG_CWIDTH_24BIT ) -++ -++#define __slcd_set_cs_high() ( REG_SLCD_CFG |= SLCD_CFG_CS_ACTIVE_HIGH ) -++#define __slcd_set_cs_low() ( REG_SLCD_CFG &= ~SLCD_CFG_CS_ACTIVE_HIGH ) -++ -++#define __slcd_set_rs_high() ( REG_SLCD_CFG |= SLCD_CFG_RS_CMD_HIGH ) -++#define __slcd_set_rs_low() ( REG_SLCD_CFG &= ~SLCD_CFG_RS_CMD_HIGH ) -++ -++#define __slcd_set_clk_falling() ( REG_SLCD_CFG &= ~SLCD_CFG_CLK_ACTIVE_RISING ) -++#define __slcd_set_clk_rising() ( REG_SLCD_CFG |= SLCD_CFG_CLK_ACTIVE_RISING ) -++ -++#define __slcd_set_parallel_type() ( REG_SLCD_CFG &= ~SLCD_CFG_TYPE_SERIAL ) -++#define __slcd_set_serial_type() ( REG_SLCD_CFG |= SLCD_CFG_TYPE_SERIAL ) -++ -++/* SLCD Control Register */ -++#define __slcd_enable_dma() ( REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN ) -++#define __slcd_disable_dma() ( REG_SLCD_CTRL &= ~SLCD_CTRL_DMA_EN ) -++ -++/* SLCD Status Register */ -++#define __slcd_is_busy() ( REG_SLCD_STATE & SLCD_STATE_BUSY ) -++ -++/* SLCD Data Register */ -++#define __slcd_set_cmd_rs() ( REG_SLCD_DATA |= SLCD_DATA_RS_COMMAND) -++#define __slcd_set_data_rs() ( REG_SLCD_DATA &= ~SLCD_DATA_RS_COMMAND) -++ -++ -++/*************************************************************************** -++ * LCD -++ ***************************************************************************/ -++ -++/*************************************************************************** -++ * LCD -++ ***************************************************************************/ -++#define __lcd_as_smart_lcd() ( REG_LCD_CFG |= ( LCD_CFG_LCDPIN_SLCD | LCD_CFG_MODE_SLCD)) -++#define __lcd_as_general_lcd() ( REG_LCD_CFG &= ~( LCD_CFG_LCDPIN_SLCD | LCD_CFG_MODE_SLCD)) -++ -++#define __lcd_enable_tvepeh() ( REG_LCD_CFG |= LCD_CFG_TVEPEH ) -++#define __lcd_disable_tvepeh() ( REG_LCD_CFG &= ~LCD_CFG_TVEPEH ) -++ -++#define __lcd_enable_fuhold() ( REG_LCD_CFG |= LCD_CFG_FUHOLD ) -++#define __lcd_disable_fuhold() ( REG_LCD_CFG &= ~LCD_CFG_FUHOLD ) -++ -++#define __lcd_des_8word() ( REG_LCD_CFG |= LCD_CFG_NEWDES ) -++#define __lcd_des_4word() ( REG_LCD_CFG &= ~LCD_CFG_NEWDES ) -++ -++#define __lcd_enable_bypass_pal() ( REG_LCD_CFG |= LCD_CFG_PALBP ) -++#define __lcd_disable_bypass_pal() ( REG_LCD_CFG &= ~LCD_CFG_PALBP ) -++ -++#define __lcd_set_lcdpnl_term() ( REG_LCD_CTRL |= LCD_CFG_TVEN ) -++#define __lcd_set_tv_term() ( REG_LCD_CTRL &= ~LCD_CFG_TVEN ) -++ -++#define __lcd_enable_auto_recover() ( REG_LCD_CFG |= LCD_CFG_RECOVER ) -++#define __lcd_disable_auto_recover() ( REG_LCD_CFG &= ~LCD_CFG_RECOVER ) -++ -++#define __lcd_enable_dither() ( REG_LCD_CFG |= LCD_CFG_DITHER ) -++#define __lcd_disable_dither() ( REG_LCD_CFG &= ~LCD_CFG_DITHER ) -++ -++#define __lcd_disable_ps_mode() ( REG_LCD_CFG |= LCD_CFG_PSM ) -++#define __lcd_enable_ps_mode() ( REG_LCD_CFG &= ~LCD_CFG_PSM ) -++ -++#define __lcd_disable_cls_mode() ( REG_LCD_CFG |= LCD_CFG_CLSM ) -++#define __lcd_enable_cls_mode() ( REG_LCD_CFG &= ~LCD_CFG_CLSM ) -++ -++#define __lcd_disable_spl_mode() ( REG_LCD_CFG |= LCD_CFG_SPLM ) -++#define __lcd_enable_spl_mode() ( REG_LCD_CFG &= ~LCD_CFG_SPLM ) -++ -++#define __lcd_disable_rev_mode() ( REG_LCD_CFG |= LCD_CFG_REVM ) -++#define __lcd_enable_rev_mode() ( REG_LCD_CFG &= ~LCD_CFG_REVM ) -++ -++#define __lcd_disable_hsync_mode() ( REG_LCD_CFG |= LCD_CFG_HSYNM ) -++#define __lcd_enable_hsync_mode() ( REG_LCD_CFG &= ~LCD_CFG_HSYNM ) -++ -++#define __lcd_disable_pclk_mode() ( REG_LCD_CFG |= LCD_CFG_PCLKM ) -++#define __lcd_enable_pclk_mode() ( REG_LCD_CFG &= ~LCD_CFG_PCLKM ) -++ -++#define __lcd_normal_outdata() ( REG_LCD_CFG &= ~LCD_CFG_INVDAT ) -++#define __lcd_inverse_outdata() ( REG_LCD_CFG |= LCD_CFG_INVDAT ) -++ -++#define __lcd_sync_input() ( REG_LCD_CFG |= LCD_CFG_SYNDIR_IN ) -++#define __lcd_sync_output() ( REG_LCD_CFG &= ~LCD_CFG_SYNDIR_IN ) -++ -++#define __lcd_hsync_active_high() ( REG_LCD_CFG &= ~LCD_CFG_HSP ) -++#define __lcd_hsync_active_low() ( REG_LCD_CFG |= LCD_CFG_HSP ) -++ -++#define __lcd_pclk_rising() ( REG_LCD_CFG &= ~LCD_CFG_PCP ) -++#define __lcd_pclk_falling() ( REG_LCD_CFG |= LCD_CFG_PCP ) -++ -++#define __lcd_de_active_high() ( REG_LCD_CFG &= ~LCD_CFG_DEP ) -++#define __lcd_de_active_low() ( REG_LCD_CFG |= LCD_CFG_DEP ) -++ -++#define __lcd_vsync_rising() ( REG_LCD_CFG &= ~LCD_CFG_VSP ) -++#define __lcd_vsync_falling() ( REG_LCD_CFG |= LCD_CFG_VSP ) -++ -++#define __lcd_set_16_tftpnl() \ -++ ( REG_LCD_CFG = (REG_LCD_CFG & ~LCD_CFG_MODE_TFT_MASK) | LCD_CFG_MODE_TFT_16BIT ) -++ -++#define __lcd_set_18_tftpnl() \ -++ ( REG_LCD_CFG = (REG_LCD_CFG & ~LCD_CFG_MODE_TFT_MASK) | LCD_CFG_MODE_TFT_18BIT ) -++ -++#define __lcd_set_24_tftpnl() ( REG_LCD_CFG |= LCD_CFG_MODE_TFT_24BIT ) -++ -++/* -++ * n=1,2,4,8 for single mono-STN -++ * n=4,8 for dual mono-STN -++ */ -++#define __lcd_set_panel_datawidth(n) \ -++do { \ -++ REG_LCD_CFG &= ~LCD_CFG_PDW_MASK; \ -++ REG_LCD_CFG |= LCD_CFG_PDW_n##; \ -++} while (0) -++ -++/* m = LCD_CFG_MODE_GENERUIC_TFT_xxx */ -++#define __lcd_set_panel_mode(m) \ -++do { \ -++ REG_LCD_CFG &= ~LCD_CFG_MODE_MASK; \ -++ REG_LCD_CFG |= (m); \ -++} while(0) -++ -++/* n=4,8,16 */ -++#define __lcd_set_burst_length(n) \ -++do { \ -++ REG_LCD_CTRL &= ~LCD_CTRL_BST_MASK; \ -++ REG_LCD_CTRL |= LCD_CTRL_BST_n##; \ -++} while (0) -++ -++#define __lcd_select_rgb565() ( REG_LCD_CTRL &= ~LCD_CTRL_RGB555 ) -++#define __lcd_select_rgb555() ( REG_LCD_CTRL |= LCD_CTRL_RGB555 ) -++ -++#define __lcd_set_ofup() ( REG_LCD_CTRL |= LCD_CTRL_OFUP ) -++#define __lcd_clr_ofup() ( REG_LCD_CTRL &= ~LCD_CTRL_OFUP ) -++ -++/* n=2,4,16 */ -++#define __lcd_set_stn_frc(n) \ -++do { \ -++ REG_LCD_CTRL &= ~LCD_CTRL_FRC_MASK; \ -++ REG_LCD_CTRL |= LCD_CTRL_FRC_n##; \ -++} while (0) -++ -++#define __lcd_enable_eof_intr() ( REG_LCD_CTRL |= LCD_CTRL_EOFM ) -++#define __lcd_disable_eof_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_EOFM ) -++ -++#define __lcd_enable_sof_intr() ( REG_LCD_CTRL |= LCD_CTRL_SOFM ) -++#define __lcd_disable_sof_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_SOFM ) -++ -++#define __lcd_enable_ofu_intr() ( REG_LCD_CTRL |= LCD_CTRL_OFUM ) -++#define __lcd_disable_ofu_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_OFUM ) -++ -++#define __lcd_enable_ifu0_intr() ( REG_LCD_CTRL |= LCD_CTRL_IFUM0 ) -++#define __lcd_disable_ifu0_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_IFUM0 ) -++ -++#define __lcd_enable_ifu1_intr() ( REG_LCD_CTRL |= LCD_CTRL_IFUM1 ) -++#define __lcd_disable_ifu1_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_IFUM1 ) -++ -++#define __lcd_enable_ldd_intr() ( REG_LCD_CTRL |= LCD_CTRL_LDDM ) -++#define __lcd_disable_ldd_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_LDDM ) -++ -++#define __lcd_enable_qd_intr() ( REG_LCD_CTRL |= LCD_CTRL_QDM ) -++#define __lcd_disable_qd_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_QDM ) -++ -++#define __lcd_reverse_byte_endian() ( REG_LCD_CTRL |= LCD_CTRL_BEDN ) -++#define __lcd_normal_byte_endian() ( REG_LCD_CTRL &= ~LCD_CTRL_BEDN ) -++ -++#define __lcd_pixel_endian_little() ( REG_LCD_CTRL |= LCD_CTRL_PEDN ) -++#define __lcd_pixel_endian_big() ( REG_LCD_CTRL &= ~LCD_CTRL_PEDN ) -++ -++#define __lcd_set_dis() ( REG_LCD_CTRL |= LCD_CTRL_DIS ) -++#define __lcd_clr_dis() ( REG_LCD_CTRL &= ~LCD_CTRL_DIS ) -++ -++#define __lcd_set_ena() ( REG_LCD_CTRL |= LCD_CTRL_ENA ) -++#define __lcd_clr_ena() ( REG_LCD_CTRL &= ~LCD_CTRL_ENA ) -++ -++/* n=1,2,4,8,16 */ -++#define __lcd_set_bpp(n) \ -++ ( REG_LCD_CTRL = (REG_LCD_CTRL & ~LCD_CTRL_BPP_MASK) | LCD_CTRL_BPP_##n ) -++ -++/* LCD status register indication */ -++ -++#define __lcd_quick_disable_done() ( REG_LCD_STATE & LCD_STATE_QD ) -++#define __lcd_disable_done() ( REG_LCD_STATE & LCD_STATE_LDD ) -++#define __lcd_infifo0_underrun() ( REG_LCD_STATE & LCD_STATE_IFU0 ) -++#define __lcd_infifo1_underrun() ( REG_LCD_STATE & LCD_STATE_IFU1 ) -++#define __lcd_outfifo_underrun() ( REG_LCD_STATE & LCD_STATE_OFU ) -++#define __lcd_start_of_frame() ( REG_LCD_STATE & LCD_STATE_SOF ) -++#define __lcd_end_of_frame() ( REG_LCD_STATE & LCD_STATE_EOF ) -++ -++#define __lcd_clr_outfifounderrun() ( REG_LCD_STATE &= ~LCD_STATE_OFU ) -++#define __lcd_clr_sof() ( REG_LCD_STATE &= ~LCD_STATE_SOF ) -++#define __lcd_clr_eof() ( REG_LCD_STATE &= ~LCD_STATE_EOF ) -++ -++/* OSD functions */ -++#define __lcd_enable_osd() (REG_LCD_OSDC |= LCD_OSDC_OSDEN) -++#define __lcd_enable_f0() (REG_LCD_OSDC |= LCD_OSDC_F0EN) -++#define __lcd_enable_f1() (REG_LCD_OSDC |= LCD_OSDC_F1EN) -++#define __lcd_enable_alpha() (REG_LCD_OSDC |= LCD_OSDC_ALPHAEN) -++#define __lcd_enable_alphamd() (REG_LCD_OSDC |= LCD_OSDC_ALPHAMD) -++ -++#define __lcd_disable_osd() (REG_LCD_OSDC &= ~LCD_OSDC_OSDEN) -++#define __lcd_disable_f0() (REG_LCD_OSDC &= ~LCD_OSDC_F0EN) -++#define __lcd_disable_f1() (REG_LCD_OSDC &= ~LCD_OSDC_F1EN) -++#define __lcd_disable_alpha() (REG_LCD_OSDC &= ~LCD_OSDC_ALPHAEN) -++#define __lcd_disable_alphamd() (REG_LCD_OSDC &= ~LCD_OSDC_ALPHAMD) -++ -++/* OSD Controll Register */ -++#define __lcd_fg1_use_ipu() (REG_LCD_OSDCTRL |= LCD_OSDCTRL_IPU) -++#define __lcd_fg1_use_dma_chan1() (REG_LCD_OSDCTRL &= ~LCD_OSDCTRL_IPU) -++#define __lcd_fg1_unuse_ipu() __lcd_fg1_use_dma_chan1() -++#define __lcd_osd_rgb555_mode() ( REG_LCD_OSDCTRL |= LCD_OSDCTRL_RGB555 ) -++#define __lcd_osd_rgb565_mode() ( REG_LCD_OSDCTRL &= ~LCD_OSDCTRL_RGB555 ) -++#define __lcd_osd_change_size() ( REG_LCD_OSDCTRL |= LCD_OSDCTRL_CHANGES ) -++#define __lcd_osd_bpp_15_16() \ -++ ( REG_LCD_OSDCTRL = (REG_LCD_OSDCTRL & ~LCD_OSDCTRL_OSDBPP_MASK) | LCD_OSDCTRL_OSDBPP_15_16 ) -++#define __lcd_osd_bpp_18_24() \ -++ ( REG_LCD_OSDCTRL = (REG_LCD_OSDCTRL & ~LCD_OSDCTRL_OSDBPP_MASK) | LCD_OSDCTRL_OSDBPP_18_24 ) -++ -++/* OSD State Register */ -++#define __lcd_start_of_fg1() ( REG_LCD_STATE & LCD_OSDS_SOF1 ) -++#define __lcd_end_of_fg1() ( REG_LCD_STATE & LCD_OSDS_EOF1 ) -++#define __lcd_start_of_fg0() ( REG_LCD_STATE & LCD_OSDS_SOF0 ) -++#define __lcd_end_of_fg0() ( REG_LCD_STATE & LCD_OSDS_EOF0 ) -++#define __lcd_change_is_rdy() ( REG_LCD_STATE & LCD_OSDS_READY ) -++ -++/* Foreground Color Key Register 0,1(foreground 0, foreground 1) */ -++#define __lcd_enable_colorkey0() (REG_LCD_KEY0 |= LCD_KEY_KEYEN) -++#define __lcd_enable_colorkey1() (REG_LCD_KEY1 |= LCD_KEY_KEYEN) -++#define __lcd_enable_colorkey0_md() (REG_LCD_KEY0 |= LCD_KEY_KEYMD) -++#define __lcd_enable_colorkey1_md() (REG_LCD_KEY1 |= LCD_KEY_KEYMD) -++#define __lcd_set_colorkey0(key) (REG_LCD_KEY0 = (REG_LCD_KEY0&~0xFFFFFF)|(key)) -++#define __lcd_set_colorkey1(key) (REG_LCD_KEY1 = (REG_LCD_KEY1&~0xFFFFFF)|(key)) -++ -++#define __lcd_disable_colorkey0() (REG_LCD_KEY0 &= ~LCD_KEY_KEYEN) -++#define __lcd_disable_colorkey1() (REG_LCD_KEY1 &= ~LCD_KEY_KEYEN) -++#define __lcd_disable_colorkey0_md() (REG_LCD_KEY0 &= ~LCD_KEY_KEYMD) -++#define __lcd_disable_colorkey1_md() (REG_LCD_KEY1 &= ~LCD_KEY_KEYMD) -++ -++/* IPU Restart Register */ -++#define __lcd_enable_ipu_restart() (REG_LCD_IPUR |= LCD_IPUR_IPUREN) -++#define __lcd_disable_ipu_restart() (REG_LCD_IPUR &= ~LCD_IPUR_IPUREN) -++#define __lcd_set_ipu_restart_triger(n) (REG_LCD_IPUR = (REG_LCD_IPUR&(~0xFFFFFF))|(n)) -++ -++/* RGB Control Register */ -++#define __lcd_enable_rgb_dummy() (REG_LCD_RGBC |= LCD_RGBC_RGBDM) -++#define __lcd_disable_rgb_dummy() (REG_LCD_RGBC &= ~LCD_RGBC_RGBDM) -++ -++#define __lcd_dummy_rgb() (REG_LCD_RGBC |= LCD_RGBC_DMM) -++#define __lcd_rgb_dummy() (REG_LCD_RGBC &= ~LCD_RGBC_DMM) -++ -++#define __lcd_rgb2ycc() (REG_LCD_RGBC |= LCD_RGBC_YCC) -++#define __lcd_notrgb2ycc() (REG_LCD_RGBC &= ~LCD_RGBC_YCC) -++ -++#define __lcd_odd_mode_rgb() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_RGB ) -++#define __lcd_odd_mode_rbg() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_RBG ) -++#define __lcd_odd_mode_grb() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_GRB) -++ -++#define __lcd_odd_mode_gbr() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_GBR) -++#define __lcd_odd_mode_brg() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_BRG) -++#define __lcd_odd_mode_bgr() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_ODDRGB_MASK) | LCD_RGBC_ODD_BGR) -++ -++#define __lcd_even_mode_rgb() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_RGB ) -++#define __lcd_even_mode_rbg() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_RBG ) -++#define __lcd_even_mode_grb() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_GRB) -++ -++#define __lcd_even_mode_gbr() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_GBR) -++#define __lcd_even_mode_brg() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_BRG) -++#define __lcd_even_mode_bgr() \ -++ ( REG_LCD_RGBC = (REG_LCD_RGBC & ~LCD_RGBC_EVENRGB_MASK) | LCD_RGBC_EVEN_BGR) -++ -++/* Vertical Synchronize Register */ -++#define __lcd_vsync_get_vps() \ -++ ( (REG_LCD_VSYNC & LCD_VSYNC_VPS_MASK) >> LCD_VSYNC_VPS_BIT ) -++ -++#define __lcd_vsync_get_vpe() \ -++ ( (REG_LCD_VSYNC & LCD_VSYNC_VPE_MASK) >> LCD_VSYNC_VPE_BIT ) -++#define __lcd_vsync_set_vpe(n) \ -++do { \ -++ REG_LCD_VSYNC &= ~LCD_VSYNC_VPE_MASK; \ -++ REG_LCD_VSYNC |= (n) << LCD_VSYNC_VPE_BIT; \ -++} while (0) -++ -++#define __lcd_hsync_get_hps() \ -++ ( (REG_LCD_HSYNC & LCD_HSYNC_HPS_MASK) >> LCD_HSYNC_HPS_BIT ) -++#define __lcd_hsync_set_hps(n) \ -++do { \ -++ REG_LCD_HSYNC &= ~LCD_HSYNC_HPS_MASK; \ -++ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPS_BIT; \ -++} while (0) -++ -++#define __lcd_hsync_get_hpe() \ -++ ( (REG_LCD_HSYNC & LCD_HSYNC_HPE_MASK) >> LCD_VSYNC_HPE_BIT ) -++#define __lcd_hsync_set_hpe(n) \ -++do { \ -++ REG_LCD_HSYNC &= ~LCD_HSYNC_HPE_MASK; \ -++ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPE_BIT; \ -++} while (0) -++ -++#define __lcd_vat_get_ht() \ -++ ( (REG_LCD_VAT & LCD_VAT_HT_MASK) >> LCD_VAT_HT_BIT ) -++#define __lcd_vat_set_ht(n) \ -++do { \ -++ REG_LCD_VAT &= ~LCD_VAT_HT_MASK; \ -++ REG_LCD_VAT |= (n) << LCD_VAT_HT_BIT; \ -++} while (0) -++ -++#define __lcd_vat_get_vt() \ -++ ( (REG_LCD_VAT & LCD_VAT_VT_MASK) >> LCD_VAT_VT_BIT ) -++#define __lcd_vat_set_vt(n) \ -++do { \ -++ REG_LCD_VAT &= ~LCD_VAT_VT_MASK; \ -++ REG_LCD_VAT |= (n) << LCD_VAT_VT_BIT; \ -++} while (0) -++ -++#define __lcd_dah_get_hds() \ -++ ( (REG_LCD_DAH & LCD_DAH_HDS_MASK) >> LCD_DAH_HDS_BIT ) -++#define __lcd_dah_set_hds(n) \ -++do { \ -++ REG_LCD_DAH &= ~LCD_DAH_HDS_MASK; \ -++ REG_LCD_DAH |= (n) << LCD_DAH_HDS_BIT; \ -++} while (0) -++ -++#define __lcd_dah_get_hde() \ -++ ( (REG_LCD_DAH & LCD_DAH_HDE_MASK) >> LCD_DAH_HDE_BIT ) -++#define __lcd_dah_set_hde(n) \ -++do { \ -++ REG_LCD_DAH &= ~LCD_DAH_HDE_MASK; \ -++ REG_LCD_DAH |= (n) << LCD_DAH_HDE_BIT; \ -++} while (0) -++ -++#define __lcd_dav_get_vds() \ -++ ( (REG_LCD_DAV & LCD_DAV_VDS_MASK) >> LCD_DAV_VDS_BIT ) -++#define __lcd_dav_set_vds(n) \ -++do { \ -++ REG_LCD_DAV &= ~LCD_DAV_VDS_MASK; \ -++ REG_LCD_DAV |= (n) << LCD_DAV_VDS_BIT; \ -++} while (0) -++ -++#define __lcd_dav_get_vde() \ -++ ( (REG_LCD_DAV & LCD_DAV_VDE_MASK) >> LCD_DAV_VDE_BIT ) -++#define __lcd_dav_set_vde(n) \ -++do { \ -++ REG_LCD_DAV &= ~LCD_DAV_VDE_MASK; \ -++ REG_LCD_DAV |= (n) << LCD_DAV_VDE_BIT; \ -++} while (0) -++ -++/* DMA Command Register */ -++#define __lcd_cmd0_set_sofint() ( REG_LCD_CMD0 |= LCD_CMD_SOFINT ) -++#define __lcd_cmd0_clr_sofint() ( REG_LCD_CMD0 &= ~LCD_CMD_SOFINT ) -++#define __lcd_cmd1_set_sofint() ( REG_LCD_CMD1 |= LCD_CMD_SOFINT ) -++#define __lcd_cmd1_clr_sofint() ( REG_LCD_CMD1 &= ~LCD_CMD_SOFINT ) -++ -++#define __lcd_cmd0_set_eofint() ( REG_LCD_CMD0 |= LCD_CMD_EOFINT ) -++#define __lcd_cmd0_clr_eofint() ( REG_LCD_CMD0 &= ~LCD_CMD_EOFINT ) -++#define __lcd_cmd1_set_eofint() ( REG_LCD_CMD1 |= LCD_CMD_EOFINT ) -++#define __lcd_cmd1_clr_eofint() ( REG_LCD_CMD1 &= ~LCD_CMD_EOFINT ) -++ -++#define __lcd_cmd0_set_pal() ( REG_LCD_CMD0 |= LCD_CMD_PAL ) -++#define __lcd_cmd0_clr_pal() ( REG_LCD_CMD0 &= ~LCD_CMD_PAL ) -++ -++#define __lcd_cmd0_get_len() \ -++ ( (REG_LCD_CMD0 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) -++#define __lcd_cmd1_get_len() \ -++ ( (REG_LCD_CMD1 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT ) -++ -++/************************************************************************* -++ * TVE (TV Encoder Controller) ops -++ *************************************************************************/ -++/* TV Encoder Control register ops */ -++#define __tve_soft_reset() (REG_TVE_CTRL |= TVE_CTRL_SWRST) -++ -++#define __tve_output_colorbar() (REG_TVE_CTRL |= TVE_CTRL_CLBAR) -++#define __tve_output_video() (REG_TVE_CTRL &= ~TVE_CTRL_CLBAR) -++ -++#define __tve_input_cr_first() (REG_TVE_CTRL |= TVE_CTRL_CR1ST) -++#define __tve_input_cb_first() (REG_TVE_CTRL &= ~TVE_CTRL_CR1ST) -++ -++#define __tve_set_0_as_black() (REG_TVE_CTRL |= TVE_CTRL_ZBLACK) -++#define __tve_set_16_as_black() (REG_TVE_CTRL &= ~TVE_CTRL_ZBLACK) -++ -++#define __tve_ena_invert_top_bottom() (REG_TVE_CTRL |= TVE_CTRL_FINV) -++#define __tve_dis_invert_top_bottom() (REG_TVE_CTRL &= ~TVE_CTRL_FINV) -++ -++#define __tve_set_pal_mode() (REG_TVE_CTRL |= TVE_CTRL_PAL) -++#define __tve_set_ntsc_mode() (REG_TVE_CTRL &= ~TVE_CTRL_PAL) -++ -++#define __tve_set_pal_dura() (REG_TVE_CTRL |= TVE_CTRL_SYNCT) -++#define __tve_set_ntsc_dura() (REG_TVE_CTRL &= ~TVE_CTRL_SYNCT) -++ -++/* n = 0 ~ 3 */ -++#define __tve_set_c_bandwidth(n) \ -++do {\ -++ REG_TVE_CTRL &= ~TVE_CTRL_CBW_MASK;\ -++ REG_TVE_CTRL |= (n) << TVE_CTRL_CBW_BIT; \ -++}while(0) -++ -++/* n = 0 ~ 3 */ -++#define __tve_set_c_gain(n) \ -++do {\ -++ REG_TVE_CTRL &= ~TVE_CTRL_CGAIN_MASK;\ -++ (REG_TVE_CTRL |= (n) << TVE_CTRL_CGAIN_BIT; \ -++}while(0) -++ -++/* n = 0 ~ 7 */ -++#define __tve_set_yc_delay(n) \ -++do { \ -++ REG_TVE_CTRL &= ~TVE_CTRL_YCDLY_MASK \ -++ REG_TVE_CTRL |= ((n) << TVE_CTRL_YCDLY_BIT); \ -++} while(0) -++ -++#define __tve_disable_all_dacs() (REG_TVE_CTRL |= TVE_CTRL_DAPD) -++#define __tve_disable_dac1() (REG_TVE_CTRL |= TVE_CTRL_DAPD1) -++#define __tve_enable_dac1() (REG_TVE_CTRL &= ~TVE_CTRL_DAPD1) -++#define __tve_disable_dac2() (REG_TVE_CTRL |= TVE_CTRL_DAPD2) -++#define __tve_enable_dac2() (REG_TVE_CTRL &= ~TVE_CTRL_DAPD2) -++#define __tve_disable_dac3() (REG_TVE_CTRL |= TVE_CTRL_DAPD3) -++#define __tve_enable_dac3() (REG_TVE_CTRL &= ~TVE_CTRL_DAPD3) -++ -++#define __tve_enable_svideo_fmt() (REG_TVE_CTRL |= TVE_CTRL_ECVBS) -++#define __tve_enable_cvbs_fmt() (REG_TVE_CTRL &= ~TVE_CTRL_ECVBS) -++ -++/* TV Encoder Frame Configure register ops */ -++/* n = 0 ~ 255 */ -++#define __tve_set_first_video_line(n) \ -++do {\ -++ REG_TVE_FRCFG &= ~TVE_FRCFG_L1ST_MASK;\ -++ REG_TVE_FRCFG |= (n) << TVE_FRCFG_L1ST_BIT;\ -++} while(0) -++/* n = 0 ~ 1023 */ -++#define __tve_set_line_num_per_frm(n) \ -++do {\ -++ REG_TVE_FRCFG &= ~TVE_FRCFG_NLINE_MASK;\ -++ REG_TVE_CFG |= (n) << TVE_FRCFG_NLINE_BIT;\ -++} while(0) -++#define __tve_get_video_line_num()\ -++ (((REG_TVE_FRCFG & TVE_FRCFG_NLINE_MASK) >> TVE_FRCFG_NLINE_BIT) - 1 - 2 * ((REG_TVE_FRCFG & TVE_FRCFG_L1ST_MASK) >> TVE_FRCFG_L1ST_BIT)) -++ -++/* TV Encoder Signal Level Configure register ops */ -++/* n = 0 ~ 1023 */ -++#define __tve_set_white_level(n) \ -++do {\ -++ REG_TVE_SLCFG1 &= ~TVE_SLCFG1_WHITEL_MASK;\ -++ REG_TVE_SLCFG1 |= (n) << TVE_SLCFG1_WHITEL_BIT;\ -++} while(0) -++/* n = 0 ~ 1023 */ -++#define __tve_set_black_level(n) \ -++do {\ -++ REG_TVE_SLCFG1 &= ~TVE_SLCFG1_BLACKL_MASK;\ -++ REG_TVE_SLCFG1 |= (n) << TVE_SLCFG1_BLACKL_BIT;\ -++} while(0) -++/* n = 0 ~ 1023 */ -++#define __tve_set_blank_level(n) \ -++do {\ -++ REG_TVE_SLCFG2 &= ~TVE_SLCFG2_BLANKL_MASK;\ -++ REG_TVE_SLCFG2 |= (n) << TVE_SLCFG2_BLANKL_BIT;\ -++} while(0) -++/* n = 0 ~ 1023 */ -++#define __tve_set_vbi_blank_level(n) \ -++do {\ -++ REG_TVE_SLCFG2 &= ~TVE_SLCFG2_VBLANKL_MASK;\ -++ REG_TVE_SLCFG2 |= (n) << TVE_SLCFG2_VBLANKL_BIT;\ -++} while(0) -++/* n = 0 ~ 1023 */ -++#define __tve_set_sync_level(n) \ -++do {\ -++ REG_TVE_SLCFG3 &= ~TVE_SLCFG3_SYNCL_MASK;\ -++ REG_TVE_SLCFG3 |= (n) << TVE_SLCFG3_SYNCL_BIT;\ -++} while(0) -++ -++/* TV Encoder Signal Level Configure register ops */ -++/* n = 0 ~ 31 */ -++#define __tve_set_front_porch(n) \ -++do {\ -++ REG_TVE_LTCFG1 &= ~TVE_LTCFG1_FRONTP_MASK;\ -++ REG_TVE_LTCFG1 |= (n) << TVE_LTCFG1_FRONTP_BIT; \ -++} while(0) -++/* n = 0 ~ 127 */ -++#define __tve_set_hsync_width(n) \ -++do {\ -++ REG_TVE_LTCFG1 &= ~TVE_LTCFG1_HSYNCW_MASK;\ -++ REG_TVE_LTCFG1 |= (n) << TVE_LTCFG1_HSYNCW_BIT; \ -++} while(0) -++/* n = 0 ~ 127 */ -++#define __tve_set_back_porch(n) \ -++do {\ -++ REG_TVE_LTCFG1 &= ~TVE_LTCFG1_BACKP_MASK;\ -++ REG_TVE_LTCFG1 |= (n) << TVE_LTCFG1_BACKP_BIT; \ -++} while(0) -++/* n = 0 ~ 2047 */ -++#define __tve_set_active_linec(n) \ -++do {\ -++ REG_TVE_LTCFG2 &= ~TVE_LTCFG2_ACTLIN_MASK;\ -++ REG_TVE_LTCFG2 |= (n) << TVE_LTCFG2_ACTLIN_BIT; \ -++} while(0) -++/* n = 0 ~ 31 */ -++#define __tve_set_breezy_way(n) \ -++do {\ -++ REG_TVE_LTCFG2 &= ~TVE_LTCFG2_PREBW_MASK;\ -++ REG_TVE_LTCFG2 |= (n) << TVE_LTCFG2_PREBW_BIT; \ -++} while(0) -++ -++/* n = 0 ~ 127 */ -++#define __tve_set_burst_width(n) \ -++do {\ -++ REG_TVE_LTCFG2 &= ~TVE_LTCFG2_BURSTW_MASK;\ -++ REG_TVE_LTCFG2 |= (n) << TVE_LTCFG2_BURSTW_BIT; \ -++} while(0) -++ -++/* TV Encoder Chrominance filter and Modulation register ops */ -++/* n = 0 ~ (2^32-1) */ -++#define __tve_set_c_sub_carrier_freq(n) REG_TVE_CFREQ = (n) -++/* n = 0 ~ 255 */ -++#define __tve_set_c_sub_carrier_init_phase(n) \ -++do { \ -++ REG_TVE_CPHASE &= ~TVE_CPHASE_INITPH_MASK; \ -++ REG_TVE_CPHASE |= (n) << TVE_CPHASE_INITPH_BIT; \ -++} while(0) -++/* n = 0 ~ 255 */ -++#define __tve_set_c_sub_carrier_act_phase(n) \ -++do { \ -++ REG_TVE_CPHASE &= ~TVE_CPHASE_ACTPH_MASK; \ -++ REG_TVE_CPHASE |= (n) << TVE_CPHASE_ACTPH_BIT; \ -++} while(0) -++/* n = 0 ~ 255 */ -++#define __tve_set_c_phase_rst_period(n) \ -++do { \ -++ REG_TVE_CPHASE &= ~TVE_CPHASE_CCRSTP_MASK; \ -++ REG_TVE_CPHASE |= (n) << TVE_CPHASE_CCRSTP_BIT; \ -++} while(0) -++/* n = 0 ~ 255 */ -++#define __tve_set_cb_burst_amp(n) \ -++do { \ -++ REG_TVE_CBCRCFG &= ~TVE_CBCRCFG_CBBA_MASK; \ -++ REG_TVE_CBCRCFG |= (n) << TVE_CBCRCFG_CBBA_BIT; \ -++} while(0) -++/* n = 0 ~ 255 */ -++#define __tve_set_cr_burst_amp(n) \ -++do { \ -++ REG_TVE_CBCRCFG &= ~TVE_CBCRCFG_CRBA_MASK; \ -++ REG_TVE_CBCRCFG |= (n) << TVE_CBCRCFG_CRBA_BIT; \ -++} while(0) -++/* n = 0 ~ 255 */ -++#define __tve_set_cb_gain_amp(n) \ -++do { \ -++ REG_TVE_CBCRCFG &= ~TVE_CBCRCFG_CBGAIN_MASK; \ -++ REG_TVE_CBCRCFG |= (n) << TVE_CBCRCFG_CBGAIN_BIT; \ -++} while(0) -++/* n = 0 ~ 255 */ -++#define __tve_set_cr_gain_amp(n) \ -++do { \ -++ REG_TVE_CBCRCFG &= ~TVE_CBCRCFG_CRGAIN_MASK; \ -++ REG_TVE_CBCRCFG |= (n) << TVE_CBCRCFG_CRGAIN_BIT; \ -++} while(0) -++ -++/* TV Encoder Wide Screen Signal Control register ops */ -++/* n = 0 ~ 7 */ -++#define __tve_set_notch_freq(n) \ -++do { \ -++ REG_TVE_WSSCR &= ~TVE_WSSCR_NCHFREQ_MASK; \ -++ REG_TVE_WSSCR |= (n) << TVE_WSSCR_NCHFREQ_BIT; \ -++} while(0) -++/* n = 0 ~ 7 */ -++#define __tve_set_notch_width() (REG_TVE_WSSCR |= TVE_WSSCR_NCHW_BIT) -++#define __tve_clear_notch_width() (REG_TVE_WSSCR &= ~TVE_WSSCR_NCHW_BIT) -++#define __tve_enable_notch() (REG_TVE_WSSCR |= TVE_WSSCR_ENCH_BIT) -++#define __tve_disable_notch() (REG_TVE_WSSCR &= ~TVE_WSSCR_ENCH_BIT) -++/* n = 0 ~ 7 */ -++#define __tve_set_wss_edge(n) \ -++do { \ -++ REG_TVE_WSSCR &= ~TVE_WSSCR_WSSEDGE_MASK; \ -++ REG_TVE_WSSCR |= (n) << TVE_WSSCR_WSSEDGE_BIT; \ -++} while(0) -++#define __tve_set_wss_clkbyp() (REG_TVE_WSSCR |= TVE_WSSCR_WSSCKBP_BIT) -++#define __tve_set_wss_type() (REG_TVE_WSSCR |= TVE_WSSCR_WSSTP_BIT) -++#define __tve_enable_wssf1() (REG_TVE_WSSCR |= TVE_WSSCR_EWSS1_BIT) -++#define __tve_enable_wssf0() (REG_TVE_WSSCR |= TVE_WSSCR_EWSS0_BIT) -++ -++/* TV Encoder Wide Screen Signal Configure register 1, 2 and 3 ops */ -++/* n = 0 ~ 1023 */ -++#define __tve_set_wss_level(n) \ -++do { \ -++ REG_TVE_WSSCFG1 &= ~TVE_WSSCFG1_WSSL_MASK; \ -++ REG_TVE_WSSCFG1 |= (n) << TVE_WSSCFG1_WSSL_BIT; \ -++} while(0) -++/* n = 0 ~ 4095 */ -++#define __tve_set_wss_freq(n) \ -++do { \ -++ REG_TVE_WSSCFG1 &= ~TVE_WSSCFG1_WSSFREQ_MASK; \ -++ REG_TVE_WSSCFG1 |= (n) << TVE_WSSCFG1_WSSFREQ_BIT; \ -++} while(0) -++/* n = 0, 1; l = 0 ~ 255 */ -++#define __tve_set_wss_line(n,v) \ -++do { \ -++ REG_TVE_WSSCFG##n &= ~TVE_WSSCFG_WSSLINE_MASK; \ -++ REG_TVE_WSSCFG##n |= (v) << TVE_WSSCFG_WSSLINE_BIT; \ -++} while(0) -++/* n = 0, 1; d = 0 ~ (2^20-1) */ -++#define __tve_set_wss_data(n, v) \ -++do { \ -++ REG_TVE_WSSCFG##n &= ~TVE_WSSCFG_WSSLINE_MASK; \ -++ REG_TVE_WSSCFG##n |= (v) << TVE_WSSCFG_WSSLINE_BIT; \ -++} while(0) -++ -++/*************************************************************************** -++ * RTC ops -++ ***************************************************************************/ -++ -++#define __rtc_write_ready() ( (REG_RTC_RCR & RTC_RCR_WRDY) >> RTC_RCR_WRDY_BIT ) -++#define __rtc_enabled() ( REG_RTC_RCR |= RTC_RCR_RTCE ) -++#define __rtc_disabled() ( REG_RTC_RCR &= ~RTC_RCR_RTCE ) -++#define __rtc_enable_alarm() ( REG_RTC_RCR |= RTC_RCR_AE ) -++#define __rtc_disable_alarm() ( REG_RTC_RCR &= ~RTC_RCR_AE ) -++#define __rtc_enable_alarm_irq() ( REG_RTC_RCR |= RTC_RCR_AIE ) -++#define __rtc_disable_alarm_irq() ( REG_RTC_RCR &= ~RTC_RCR_AIE ) -++#define __rtc_enable_1Hz_irq() ( REG_RTC_RCR |= RTC_RCR_1HZIE ) -++#define __rtc_disable_1Hz_irq() ( REG_RTC_RCR &= ~RTC_RCR_1HZIE ) -++ -++#define __rtc_get_1Hz_flag() ( (REG_RTC_RCR >> RTC_RCR_1HZ_BIT) & 0x1 ) -++#define __rtc_clear_1Hz_flag() ( REG_RTC_RCR &= ~RTC_RCR_1HZ ) -++#define __rtc_get_alarm_flag() ( (REG_RTC_RCR >> RTC_RCR_AF_BIT) & 0x1 ) -++#define __rtc_clear_alarm_flag() ( REG_RTC_RCR &= ~RTC_RCR_AF ) -++ -++#define __rtc_get_second() ( REG_RTC_RSR ) -++#define __rtc_set_second(v) ( REG_RTC_RSR = v ) -++ -++#define __rtc_get_alarm_second() ( REG_RTC_RSAR ) -++#define __rtc_set_alarm_second(v) ( REG_RTC_RSAR = v ) -++ -++#define __rtc_RGR_is_locked() ( (REG_RTC_RGR >> RTC_RGR_LOCK) ) -++#define __rtc_lock_RGR() ( REG_RTC_RGR |= RTC_RGR_LOCK ) -++#define __rtc_unlock_RGR() ( REG_RTC_RGR &= ~RTC_RGR_LOCK ) -++#define __rtc_get_adjc_val() ( (REG_RTC_RGR & RTC_RGR_ADJC_MASK) >> RTC_RGR_ADJC_BIT ) -++#define __rtc_set_adjc_val(v) \ -++ ( REG_RTC_RGR = ( (REG_RTC_RGR & ~RTC_RGR_ADJC_MASK) | (v << RTC_RGR_ADJC_BIT) )) -++#define __rtc_get_nc1Hz_val() ( (REG_RTC_RGR & RTC_RGR_NC1HZ_MASK) >> RTC_RGR_NC1HZ_BIT ) -++#define __rtc_set_nc1Hz_val(v) \ -++ ( REG_RTC_RGR = ( (REG_RTC_RGR & ~RTC_RGR_NC1HZ_MASK) | (v << RTC_RGR_NC1HZ_BIT) )) -++ -++#define __rtc_power_down() ( REG_RTC_HCR |= RTC_HCR_PD ) -++ -++#define __rtc_get_hwfcr_val() ( REG_RTC_HWFCR & RTC_HWFCR_MASK ) -++#define __rtc_set_hwfcr_val(v) ( REG_RTC_HWFCR = (v) & RTC_HWFCR_MASK ) -++#define __rtc_get_hrcr_val() ( REG_RTC_HRCR & RTC_HRCR_MASK ) -++#define __rtc_set_hrcr_val(v) ( REG_RTC_HRCR = (v) & RTC_HRCR_MASK ) -++ -++#define __rtc_enable_alarm_wakeup() ( REG_RTC_HWCR |= RTC_HWCR_EALM ) -++#define __rtc_disable_alarm_wakeup() ( REG_RTC_HWCR &= ~RTC_HWCR_EALM ) -++ -++#define __rtc_status_hib_reset_occur() ( (REG_RTC_HWRSR >> RTC_HWRSR_HR) & 0x1 ) -++#define __rtc_status_ppr_reset_occur() ( (REG_RTC_HWRSR >> RTC_HWRSR_PPR) & 0x1 ) -++#define __rtc_status_wakeup_pin_waken_up() ( (REG_RTC_HWRSR >> RTC_HWRSR_PIN) & 0x1 ) -++#define __rtc_status_alarm_waken_up() ( (REG_RTC_HWRSR >> RTC_HWRSR_ALM) & 0x1 ) -++#define __rtc_clear_hib_stat_all() ( REG_RTC_HWRSR = 0 ) -++ -++#define __rtc_get_scratch_pattern() (REG_RTC_HSPR) -++#define __rtc_set_scratch_pattern(n) (REG_RTC_HSPR = n ) -++ -++/************************************************************************* -++ * BCH -++ *************************************************************************/ -++#define __ecc_encoding_4bit() \ -++do { \ -++ REG_BCH_CRS = BCH_CR_ENCE | BCH_CR_BRST | BCH_CR_BCHE; \ -++ REG_BCH_CRC = BCH_CR_BSEL8; \ -++} while(0) -++#define __ecc_decoding_4bit() \ -++do { \ -++ REG_BCH_CRS = BCH_CR_BRST | BCH_CR_BCHE; \ -++ REG_BCH_CRC = BCH_CR_ENCE | BCH_CR_BSEL8; \ -++} while(0) -++#define __ecc_encoding_8bit() \ -++do { \ -++ REG_BCH_CRS = BCH_CR_ENCE | BCH_CR_BRST | BCH_CR_BSEL8 | BCH_CR_BCHE; \ -++} while(0) -++#define __ecc_decoding_8bit() \ -++do { \ -++ REG_BCH_CRS = BCH_CR_BRST | BCH_CR_BSEL8 | BCH_CR_BCHE; \ -++ REG_BCH_CRC = BCH_CR_ENCE; \ -++} while(0) -++#define __ecc_dma_enable() ( REG_BCH_CRS = BCH_CR_DMAE ) -++#define __ecc_disable() ( REG_BCH_CRC = BCH_CR_BCHE ) -++#define __ecc_encode_sync() while (!(REG_BCH_INTS & BCH_INTS_ENCF)) -++#define __ecc_decode_sync() while (!(REG_BCH_INTS & BCH_INTS_DECF)) -++#define __ecc_cnt_dec(n) \ -++do { \ -++ REG_BCH_CNT &= ~(BCH_CNT_DEC_MASK << BCH_CNT_DEC_BIT); \ -++ REG_BCH_CNT = (n) << BCH_CNT_DEC_BIT; \ -++} while(0) -++#define __ecc_cnt_enc(n) \ -++do { \ -++ REG_BCH_CNT &= ~(BCH_CNT_ENC_MASK << BCH_CNT_ENC_BIT); \ -++ REG_BCH_CNT = (n) << BCH_CNT_ENC_BIT; \ -++} while(0) -++ -++/*************************************************************************** -++ * OWI (one-wire bus) ops -++ ***************************************************************************/ -++ -++/* OW control register ops */ -++#define __owi_enable_all_interrupts() ( REG_OWI_CTL = (OWI_CTL_EBYTE | OWI_CTL_EBIT | OWI_CTL_ERST) ) -++#define __owi_disable_all_interrupts() ( REG_OWI_CTL = 0 ) -++ -++#define __owi_enable_byte_interrupt() ( REG_OWI_CTL |= OWI_CTL_EBYTE ) -++#define __owi_disable_byte_interrupt() ( REG_OWI_CTL &= ~OWI_CTL_EBYTE ) -++#define __owi_enable_bit_interrupt() ( REG_OWI_CTL |= OWI_CTL_EBIT ) -++#define __owi_disable_bit_interrupt() ( REG_OWI_CTL &= ~OWI_CTL_EBIT ) -++#define __owi_enable_rst_interrupt() ( REG_OWI_CTL |= OWI_CTL_ERST ) -++#define __owi_disable_rst_interrupt() ( REG_OWI_CTL &=~OWI_CTL_ERST ) -++ -++/* OW configure register ops */ -++#define __owi_select_regular_mode() ( REG_OWI_CFG &= ~OWI_CFG_MODE ) -++#define __owi_select_overdrive_mode() ( REG_OWI_CFG |= OWI_CFG_MODE ) -++ -++#define __owi_set_rddata() ( REG_OWI_CFG |= OWI_CFG_RDDATA ) -++#define __owi_clr_rddata() ( REG_OWI_CFG &= ~OWI_CFG_RDDATA ) -++#define __owi_get_rddata() ( REG_OWI_CFG & OWI_CFG_RDDATA ) -++ -++#define __owi_set_wrdata() ( REG_OWI_CFG |= OWI_CFG_WRDATA ) -++#define __owi_clr_wrdata() ( REG_OWI_CFG &= ~OWI_CFG_WRDATA ) -++#define __owi_get_wrdata() ( REG_OWI_CFG & OWI_CFG_WRDATA ) -++ -++#define __owi_get_rdst() ( REG_OWI_CFG & OWI_CFG_RDST ) -++ -++#define __owi_set_wr1rd() ( REG_OWI_CFG |= OWI_CFG_WR1RD ) -++#define __owi_clr_wr1rd() ( REG_OWI_CFG &= ~OWI_CFG_WR1RD ) -++#define __owi_get_wr1rd() ( REG_OWI_CFG & OWI_CFG_WR1RD ) -++ -++#define __owi_set_wr0() ( REG_OWI_CFG |= OWI_CFG_WR0 ) -++#define __owi_clr_wr0() ( REG_OWI_CFG &= ~OWI_CFG_WR0 ) -++#define __owi_get_wr0() ( REG_OWI_CFG & OWI_CFG_WR0 ) -++ -++#define __owi_set_rst() ( REG_OWI_CFG |= OWI_CFG_RST ) -++#define __owi_clr_rst() ( REG_OWI_CFG &= ~OWI_CFG_RST ) -++#define __owi_get_rst() ( REG_OWI_CFG & OWI_CFG_RST ) -++ -++#define __owi_enable_ow_ops() ( REG_OWI_CFG |= OWI_CFG_ENA ) -++#define __owi_disable_ow_ops() ( REG_OWI_CFG &= ~OWI_CFG_ENA ) -++#define __owi_get_enable() ( REG_OWI_CFG & OWI_CFG_ENA ) -++ -++#define __owi_wait_ops_rdy() \ -++ do { \ -++ while(__owi_get_enable()); \ -++ udelay(1); \ -++ } while(0); -++ -++/* OW status register ops */ -++#define __owi_clr_sts() ( REG_OWI_STS = 0 ) -++#define __owi_get_sts_pst() ( REG_OWI_STS & OWI_STS_PST ) -++#define __owi_get_sts_byte_rdy() ( REG_OWI_STS & OWI_STS_BYTE_RDY ) -++#define __owi_get_sts_bit_rdy() ( REG_OWI_STS & OWI_STS_BIT_RDY ) -++#define __owi_get_sts_pst_rdy() ( REG_OWI_STS & OWI_STS_PST_RDY ) -++ -++/************************************************************************* -++ * TSSI MPEG 2-TS slave interface operation -++ *************************************************************************/ -++#define __tssi_enable() ( REG_TSSI_ENA |= TSSI_ENA_ENA ) -++#define __tssi_disable() ( REG_TSSI_ENA &= ~TSSI_ENA_ENA ) -++#define __tssi_soft_reset() ( REG_TSSI_ENA |= TSSI_ENA_SFT_RST ) -++#define __tssi_dma_enable() ( REG_TSSI_ENA |= TSSI_ENA_DMA_EN ) -++#define __tssi_dma_disable() ( REG_TSSI_ENA &= ~TSSI_ENA_DMA_EN ) -++#define __tssi_filter_enable() ( REG_TSSI_ENA |= TSSI_ENA_PID_EN ) -++#define __tssi_filter_disable() ( REG_TSSI_ENA &= ~TSSI_ENA_PID_EN ) -++ -++/* n = 4, 8, 16 */ -++#define __tssi_set_tigger_num(n) \ -++ do { \ -++ REG_TSSI_CFG &= ~TSSI_CFG_TRIG_MASK; \ -++ REG_TSSI_CFG |= TSSI_CFG_TRIG_##n; \ -++ } while (0) -++ -++#define __tssi_set_wd_1() ( REG_TSSI_CFG |= TSSI_CFG_END_WD ) -++#define __tssi_set_wd_0() ( REG_TSSI_CFG &= ~TSSI_CFG_END_WD ) -++ -++#define __tssi_set_bt_1() ( REG_TSSI_CFG |= TSSI_CFG_END_BD ) -++#define __tssi_set_bt_0() ( REG_TSSI_CFG &= ~TSSI_CFG_END_BD ) -++ -++#define __tssi_set_data_pola_high() ( REG_TSSI_CFG |= TSSI_CFG_TSDI_H ) -++#define __tssi_set_data_pola_low() ( REG_TSSI_CFG &= ~TSSI_CFG_TSDI_H ) -++ -++#define __tssi_set_data_use_data0() ( REG_TSSI_CFG |= TSSI_CFG_USE_0 ) -++#define __tssi_set_data_use_data7() ( REG_TSSI_CFG &= ~TSSI_CFG_USE_0 ) -++ -++#define __tssi_select_clk_fast() ( REG_TSSI_CFG &= ~TSSI_CFG_TSCLK_CH ) -++#define __tssi_select_clk_slow() ( REG_TSSI_CFG |= TSSI_CFG_TSCLK_CH ) -++ -++#define __tssi_select_serail_mode() ( REG_TSSI_CFG &= ~TSSI_CFG_PARAL ) -++#define __tssi_select_paral_mode() ( REG_TSSI_CFG |= TSSI_CFG_PARAL ) -++ -++#define __tssi_select_clk_nega_edge() ( REG_TSSI_CFG &= ~TSSI_CFG_TSCLK_P ) -++#define __tssi_select_clk_posi_edge() ( REG_TSSI_CFG |= TSSI_CFG_TSCLK_P ) -++ -++#define __tssi_select_frm_act_high() ( REG_TSSI_CFG |= TSSI_CFG_TSFRM_H ) -++#define __tssi_select_frm_act_low() ( REG_TSSI_CFG &= ~TSSI_CFG_TSFRM_H ) -++ -++#define __tssi_select_str_act_high() ( REG_TSSI_CFG |= TSSI_CFG_TSSTR_H ) -++#define __tssi_select_str_act_low() ( REG_TSSI_CFG &= ~TSSI_CFG_TSSTR_H ) -++ -++#define __tssi_select_fail_act_high() ( REG_TSSI_CFG |= TSSI_CFG_TSFAIL_H ) -++#define __tssi_select_fail_act_low() ( REG_TSSI_CFG &= ~TSSI_CFG_TSFAIL_H ) -++ -++#define __tssi_enable_ovrn_irq() ( REG_TSSI_CTRL &= ~TSSI_CTRL_OVRNM ) -++#define __tssi_disable_ovrn_irq() ( REG_TSSI_CTRL |= TSSI_CTRL_OVRNM ) -++ -++#define __tssi_enable_trig_irq() ( REG_TSSI_CTRL &= ~TSSI_CTRL_TRIGM ) -++#define __tssi_disable_trig_irq() ( REG_TSSI_CTRL |= TSSI_CTRL_TRIGM ) -++ -++#define __tssi_state_is_overrun() ( REG_TSSI_STAT & TSSI_STAT_OVRN ) -++#define __tssi_state_trigger_meet() ( REG_TSSI_STAT & TSSI_STAT_TRIG ) -++#define __tssi_clear_state() ( REG_TSSI_STAT = 0 ) /* write 0??? */ -++#define __tssi_state_clear_overrun() ( REG_TSSI_STAT = TSSI_STAT_OVRN ) -++ -++#define __tssi_enable_filte_pid0() ( REG_TSSI_PEN |= TSSI_PEN_PID0 ) -++#define __tssi_disable_filte_pid0() ( REG_TSSI_PEN &= ~TSSI_PEN_PID0 ) -++ -++/* m = 0, ..., 15 */ -++#define __tssi_enable_pid_filter(m) \ -++ do { \ -++ int n = (m); \ -++ if ( n>=0 && n <(TSSI_PID_MAX*2) ) { \ -++ if ( n >= TSSI_PID_MAX ) n += 8; \ -++ REG_TSSI_PEN |= ( 1 << n ); \ -++ } \ -++ } while (0) -++ -++/* m = 0, ..., 15 */ -++#define __tssi_disable_pid_filter(m) \ -++ do { \ -++ int n = (m); \ -++ if ( n>=0 && n <(TSSI_PID_MAX*2) ) { \ -++ if ( n >= TSSI_PID_MAX ) n += 8; \ -++ REG_TSSI_PEN &= ~( 1 << n ); \ -++ } \ -++ } while (0) -++ -++/* n = 0, ..., 7 */ -++#define __tssi_set_pid0(n, pid0) \ -++ do { \ -++ REG_TSSI_PID(n) &= ~TSSI_PID_PID0_MASK; \ -++ REG_TSSI_PID(n) |= ((pid0)<=0 && n < TSSI_PID_MAX*2) { \ -++ if ( n < TSSI_PID_MAX ) \ -++ __tssi_set_pid0(n, pid); \ -++ else \ -++ __tssi_set_pid1(n-TSSI_PID_MAX, pid); \ -++ } \ -++ }while (0) -++ -++ -++#if 0 -++/************************************************************************* -++ * IPU (Image Processing Unit) -++ *************************************************************************/ -++#define u32 volatile unsigned long -++ -++#define write_reg(reg, val) \ -++do { \ -++ *(u32 *)(reg) = (val); \ -++} while(0) -++ -++#define read_reg(reg, off) (*(u32 *)((reg)+(off))) -++ -++ -++#define set_ipu_fmt(rgb_888_out_fmt, rgb_out_oft, out_fmt, yuv_pkg_out, in_oft, in_fmt ) \ -++({ write_reg( (IPU_V_BASE + REG_D_FMT), ((in_fmt) & IN_FMT_MSK)< Unsigned toggle enable */ -++#define AIC_CR_FLUSH (1 << 8) /* Flush FIFO */ -++#define AIC_CR_EROR (1 << 6) /* Enable ROR interrupt */ -++#define AIC_CR_ETUR (1 << 5) /* Enable TUR interrupt */ -++#define AIC_CR_ERFS (1 << 4) /* Enable RFS interrupt */ -++#define AIC_CR_ETFS (1 << 3) /* Enable TFS interrupt */ -++#define AIC_CR_ENLBF (1 << 2) /* Enable Loopback Function */ -++#define AIC_CR_ERPL (1 << 1) /* Enable Playback Function */ -++#define AIC_CR_EREC (1 << 0) /* Enable Record Function */ -++ -++/* AIC Controller AC-link Control Register 1 (AIC_ACCR1) */ -++ -++#define AIC_ACCR1_RS_BIT 16 /* Receive Valid Slots */ -++#define AIC_ACCR1_RS_MASK (0x3ff << AIC_ACCR1_RS_BIT) -++ #define AIC_ACCR1_RS_SLOT12 (1 << 25) /* Slot 12 valid bit */ -++ #define AIC_ACCR1_RS_SLOT11 (1 << 24) /* Slot 11 valid bit */ -++ #define AIC_ACCR1_RS_SLOT10 (1 << 23) /* Slot 10 valid bit */ -++ #define AIC_ACCR1_RS_SLOT9 (1 << 22) /* Slot 9 valid bit, LFE */ -++ #define AIC_ACCR1_RS_SLOT8 (1 << 21) /* Slot 8 valid bit, Surround Right */ -++ #define AIC_ACCR1_RS_SLOT7 (1 << 20) /* Slot 7 valid bit, Surround Left */ -++ #define AIC_ACCR1_RS_SLOT6 (1 << 19) /* Slot 6 valid bit, PCM Center */ -++ #define AIC_ACCR1_RS_SLOT5 (1 << 18) /* Slot 5 valid bit */ -++ #define AIC_ACCR1_RS_SLOT4 (1 << 17) /* Slot 4 valid bit, PCM Right */ -++ #define AIC_ACCR1_RS_SLOT3 (1 << 16) /* Slot 3 valid bit, PCM Left */ -++#define AIC_ACCR1_XS_BIT 0 /* Transmit Valid Slots */ -++#define AIC_ACCR1_XS_MASK (0x3ff << AIC_ACCR1_XS_BIT) -++ #define AIC_ACCR1_XS_SLOT12 (1 << 9) /* Slot 12 valid bit */ -++ #define AIC_ACCR1_XS_SLOT11 (1 << 8) /* Slot 11 valid bit */ -++ #define AIC_ACCR1_XS_SLOT10 (1 << 7) /* Slot 10 valid bit */ -++ #define AIC_ACCR1_XS_SLOT9 (1 << 6) /* Slot 9 valid bit, LFE */ -++ #define AIC_ACCR1_XS_SLOT8 (1 << 5) /* Slot 8 valid bit, Surround Right */ -++ #define AIC_ACCR1_XS_SLOT7 (1 << 4) /* Slot 7 valid bit, Surround Left */ -++ #define AIC_ACCR1_XS_SLOT6 (1 << 3) /* Slot 6 valid bit, PCM Center */ -++ #define AIC_ACCR1_XS_SLOT5 (1 << 2) /* Slot 5 valid bit */ -++ #define AIC_ACCR1_XS_SLOT4 (1 << 1) /* Slot 4 valid bit, PCM Right */ -++ #define AIC_ACCR1_XS_SLOT3 (1 << 0) /* Slot 3 valid bit, PCM Left */ -++ -++/* AIC Controller AC-link Control Register 2 (AIC_ACCR2) */ -++ -++#define AIC_ACCR2_ERSTO (1 << 18) /* Enable RSTO interrupt */ -++#define AIC_ACCR2_ESADR (1 << 17) /* Enable SADR interrupt */ -++#define AIC_ACCR2_ECADT (1 << 16) /* Enable CADT interrupt */ -++#define AIC_ACCR2_OASS_BIT 8 /* Output Sample Size for AC-link */ -++#define AIC_ACCR2_OASS_MASK (0x3 << AIC_ACCR2_OASS_BIT) -++ #define AIC_ACCR2_OASS_20BIT (0 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 20-bit */ -++ #define AIC_ACCR2_OASS_18BIT (1 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 18-bit */ -++ #define AIC_ACCR2_OASS_16BIT (2 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 16-bit */ -++ #define AIC_ACCR2_OASS_8BIT (3 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 8-bit */ -++#define AIC_ACCR2_IASS_BIT 6 /* Output Sample Size for AC-link */ -++#define AIC_ACCR2_IASS_MASK (0x3 << AIC_ACCR2_IASS_BIT) -++ #define AIC_ACCR2_IASS_20BIT (0 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 20-bit */ -++ #define AIC_ACCR2_IASS_18BIT (1 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 18-bit */ -++ #define AIC_ACCR2_IASS_16BIT (2 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 16-bit */ -++ #define AIC_ACCR2_IASS_8BIT (3 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 8-bit */ -++#define AIC_ACCR2_SO (1 << 3) /* SDATA_OUT output value */ -++#define AIC_ACCR2_SR (1 << 2) /* RESET# pin level */ -++#define AIC_ACCR2_SS (1 << 1) /* SYNC pin level */ -++#define AIC_ACCR2_SA (1 << 0) /* SYNC and SDATA_OUT alternation */ -++ -++/* AIC Controller I2S/MSB-justified Control Register (AIC_I2SCR) */ -++ -++#define AIC_I2SCR_STPBK (1 << 12) /* Stop BIT_CLK for I2S/MSB-justified */ -++#define AIC_I2SCR_WL_BIT 1 /* Input/Output Sample Size for I2S/MSB-justified */ -++#define AIC_I2SCR_WL_MASK (0x7 << AIC_I2SCR_WL_BIT) -++ #define AIC_I2SCR_WL_24BIT (0 << AIC_I2SCR_WL_BIT) /* Word Length is 24 bit */ -++ #define AIC_I2SCR_WL_20BIT (1 << AIC_I2SCR_WL_BIT) /* Word Length is 20 bit */ -++ #define AIC_I2SCR_WL_18BIT (2 << AIC_I2SCR_WL_BIT) /* Word Length is 18 bit */ -++ #define AIC_I2SCR_WL_16BIT (3 << AIC_I2SCR_WL_BIT) /* Word Length is 16 bit */ -++ #define AIC_I2SCR_WL_8BIT (4 << AIC_I2SCR_WL_BIT) /* Word Length is 8 bit */ -++#define AIC_I2SCR_AMSL (1 << 0) /* 0:I2S, 1:MSB-justified */ -++ -++/* AIC Controller FIFO Status Register (AIC_SR) */ -++ -++#define AIC_SR_RFL_BIT 24 /* Receive FIFO Level */ -++#define AIC_SR_RFL_MASK (0x3f << AIC_SR_RFL_BIT) -++#define AIC_SR_TFL_BIT 8 /* Transmit FIFO level */ -++#define AIC_SR_TFL_MASK (0x3f << AIC_SR_TFL_BIT) -++#define AIC_SR_ROR (1 << 6) /* Receive FIFO Overrun */ -++#define AIC_SR_TUR (1 << 5) /* Transmit FIFO Underrun */ -++#define AIC_SR_RFS (1 << 4) /* Receive FIFO Service Request */ -++#define AIC_SR_TFS (1 << 3) /* Transmit FIFO Service Request */ -++ -++/* AIC Controller AC-link Status Register (AIC_ACSR) */ -++ -++#define AIC_ACSR_SLTERR (1 << 21) /* Slot Error Flag */ -++#define AIC_ACSR_CRDY (1 << 20) /* External CODEC Ready Flag */ -++#define AIC_ACSR_CLPM (1 << 19) /* External CODEC low power mode flag */ -++#define AIC_ACSR_RSTO (1 << 18) /* External CODEC regs read status timeout */ -++#define AIC_ACSR_SADR (1 << 17) /* External CODEC regs status addr and data received */ -++#define AIC_ACSR_CADT (1 << 16) /* Command Address and Data Transmitted */ -++ -++/* AIC Controller I2S/MSB-justified Status Register (AIC_I2SSR) */ -++ -++#define AIC_I2SSR_BSY (1 << 2) /* AIC Busy in I2S/MSB-justified format */ -++ -++/* AIC Controller AC97 codec Command Address Register (AIC_ACCAR) */ -++ -++#define AIC_ACCAR_CAR_BIT 0 -++#define AIC_ACCAR_CAR_MASK (0xfffff << AIC_ACCAR_CAR_BIT) -++ -++/* AIC Controller AC97 codec Command Data Register (AIC_ACCDR) */ -++ -++#define AIC_ACCDR_CDR_BIT 0 -++#define AIC_ACCDR_CDR_MASK (0xfffff << AIC_ACCDR_CDR_BIT) -++ -++/* AIC Controller AC97 codec Status Address Register (AIC_ACSAR) */ -++ -++#define AIC_ACSAR_SAR_BIT 0 -++#define AIC_ACSAR_SAR_MASK (0xfffff << AIC_ACSAR_SAR_BIT) -++ -++/* AIC Controller AC97 codec Status Data Register (AIC_ACSDR) */ -++ -++#define AIC_ACSDR_SDR_BIT 0 -++#define AIC_ACSDR_SDR_MASK (0xfffff << AIC_ACSDR_SDR_BIT) -++ -++/* AIC Controller I2S/MSB-justified Clock Divider Register (AIC_I2SDIV) */ -++ -++#define AIC_I2SDIV_DIV_BIT 0 -++#define AIC_I2SDIV_DIV_MASK (0x7f << AIC_I2SDIV_DIV_BIT) -++ #define AIC_I2SDIV_BITCLK_3072KHZ (0x0C << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 3.072MHz */ -++ #define AIC_I2SDIV_BITCLK_2836KHZ (0x0D << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 2.836MHz */ -++ #define AIC_I2SDIV_BITCLK_1418KHZ (0x1A << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.418MHz */ -++ #define AIC_I2SDIV_BITCLK_1024KHZ (0x24 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.024MHz */ -++ #define AIC_I2SDIV_BITCLK_7089KHZ (0x34 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 708.92KHz */ -++ #define AIC_I2SDIV_BITCLK_512KHZ (0x48 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 512.00KHz */ -++ -++ -++/************************************************************************* -++ * ICDC (Internal CODEC) -++ *************************************************************************/ -++ -++#define ICDC_CKCFG (ICDC_BASE + 0x00a0) /* Clock Configure Register */ -++#define ICDC_RGADW (ICDC_BASE + 0x00a4) /* internal register access control */ -++#define ICDC_RGDATA (ICDC_BASE + 0x00a8) /* internal register data output */ -++ -++#define REG_ICDC_CKCFG REG32(ICDC_CKCFG) -++#define REG_ICDC_RGADW REG32(ICDC_RGADW) -++#define REG_ICDC_RGDATA REG32(ICDC_RGDATA) -++ -++/* ICDC Clock Configure Register */ -++#define ICDC_CKCFG_CKRDY (1 << 1) -++#define ICDC_CKCFG_SELAD (1 << 0) -++ -++/* ICDC internal register access control Register */ -++#define ICDC_RGADW_RGWR (1 << 16) -++#define ICDC_RGADW_RGADDR_BIT 8 -++#define ICDC_RGADW_RGADDR_MASK (0x7f << ICDC_RGADW_RGADDR_BIT) -++#define ICDC_RGADW_RGDIN_BIT 0 -++#define ICDC_RGADW_RGDIN_MASK (0xff << ICDC_RGADW_RGDIN_BIT) -++ -++/* ICDC internal register data output Register */ -++#define ICDC_RGDATA_IRQ (1 << 8) -++#define ICDC_RGDATA_RGDOUT_BIT 0 -++#define ICDC_RGDATA_RGDOUT_MASK (0xff << ICDC_RGDATA_RGDOUT_BIT) -++ -++/************************************************************************* -++ * PCM Controller -++ *************************************************************************/ -++ -++#define PCM_CTL (PCM_BASE + 0x000) -++#define PCM_CFG (PCM_BASE + 0x004) -++#define PCM_DP (PCM_BASE + 0x008) -++#define PCM_INTC (PCM_BASE + 0x00c) -++#define PCM_INTS (PCM_BASE + 0x010) -++#define PCM_DIV (PCM_BASE + 0x014) -++ -++#define REG_PCM_CTL REG32(PCM_CTL) -++#define REG_PCM_CFG REG32(PCM_CFG) -++#define REG_PCM_DP REG32(PCM_DP) -++#define REG_PCM_INTC REG32(PCM_INTC) -++#define REG_PCM_INTS REG32(PCM_INTS) -++#define REG_PCM_DIV REG32(PCM_DIV) -++ -++/* PCM Controller control Register (PCM_CTL) */ -++ -++#define PCM_CTL_ERDMA (1 << 9) /* Enable Receive DMA */ -++#define PCM_CTL_ETDMA (1 << 8) /* Enable Transmit DMA */ -++#define PCM_CTL_LSMP (1 << 7) /* Play Zero sample or last sample */ -++#define PCM_CTL_ERPL (1 << 6) /* Enable Playing Back Function */ -++#define PCM_CTL_EREC (1 << 5) /* Enable Recording Function */ -++#define PCM_CTL_FLUSH (1 << 4) /* FIFO flush */ -++#define PCM_CTL_RST (1 << 3) /* Reset PCM */ -++#define PCM_CTL_CLKEN (1 << 1) /* Enable the clock division logic */ -++#define PCM_CTL_PCMEN (1 << 0) /* Enable PCM module */ -++ -++/* PCM Controller configure Register (PCM_CFG) */ -++ -++#define PCM_CFG_SLOT_BIT 13 -++#define PCM_CFG_SLOT_MASK (0x3 << PCM_CFG_SLOT_BIT) -++ #define PCM_CFG_SLOT_0 (0 << PCM_CFG_SLOT_BIT) /* Slot is 0 */ -++ #define PCM_CFG_SLOT_1 (1 << PCM_CFG_SLOT_BIT) /* Slot is 1 */ -++ #define PCM_CFG_SLOT_2 (2 << PCM_CFG_SLOT_BIT) /* Slot is 2 */ -++ #define PCM_CFG_SLOT_3 (3 << PCM_CFG_SLOT_BIT) /* Slot is 3 */ -++#define PCM_CFG_ISS_BIT 12 -++#define PCM_CFG_ISS_MASK (0x1 << PCM_CFG_ISS_BIT) -++ #define PCM_CFG_ISS_8 (0 << PCM_CFG_ISS_BIT) -++ #define PCM_CFG_ISS_16 (1 << PCM_CFG_ISS_BIT) -++#define PCM_CFG_OSS_BIT 11 -++#define PCM_CFG_OSS_MASK (0x1 << PCM_CFG_OSS_BIT) -++ #define PCM_CFG_OSS_8 (0 << PCM_CFG_OSS_BIT) -++ #define PCM_CFG_OSS_16 (1 << PCM_CFG_OSS_BIT) -++#define PCM_CFG_IMSBPOS (1 << 10) -++#define PCM_CFG_OMSBPOS (1 << 9) -++#define PCM_CFG_RFTH_BIT 5 /* Receive FIFO Threshold */ -++#define PCM_CFG_RFTH_MASK (0xf << PCM_CFG_RFTH_BIT) -++#define PCM_CFG_TFTH_BIT 1 /* Transmit FIFO Threshold */ -++#define PCM_CFG_TFTH_MASK (0xf << PCM_CFG_TFTH_BIT) -++#define PCM_CFG_MODE (0x0 << 0) -++ -++/* PCM Controller interrupt control Register (PCM_INTC) */ -++ -++#define PCM_INTC_ETFS (1 << 3) -++#define PCM_INTC_ETUR (1 << 2) -++#define PCM_INTC_ERFS (1 << 1) -++#define PCM_INTC_EROR (1 << 0) -++ -++/* PCM Controller interrupt status Register (PCM_INTS) */ -++ -++#define PCM_INTS_RSTS (1 << 14) /* Reset or flush has not complete */ -++#define PCM_INTS_TFL_BIT 9 -++#define PCM_INTS_TFL_MASK (0x1f << PCM_INTS_TFL_BIT) -++#define PCM_INTS_TFS (1 << 8) /* Tranmit FIFO Service Request */ -++#define PCM_INTS_TUR (1 << 7) /* Transmit FIFO Under Run */ -++#define PCM_INTS_RFL_BIT 2 -++#define PCM_INTS_RFL_MASK (0x1f << PCM_INTS_RFL_BIT) -++#define PCM_INTS_RFS (1 << 1) /* Receive FIFO Service Request */ -++#define PCM_INTS_ROR (1 << 0) /* Receive FIFO Over Run */ -++ -++/* PCM Controller clock division Register (PCM_DIV) */ -++#define PCM_DIV_SYNL_BIT 11 -++#define PCM_DIV_SYNL_MASK (0x3f << PCM_DIV_SYNL_BIT) -++#define PCM_DIV_SYNDIV_BIT 6 -++#define PCM_DIV_SYNDIV_MASK (0x1f << PCM_DIV_SYNDIV_BIT) -++#define PCM_DIV_CLKDIV_BIT 0 -++#define PCM_DIV_CLKDIV_MASK (0x3f << PCM_DIV_CLKDIV_BIT) -++ -++ -++/************************************************************************* -++ * I2C -++ *************************************************************************/ -++#define I2C_DR (I2C_BASE + 0x000) -++#define I2C_CR (I2C_BASE + 0x004) -++#define I2C_SR (I2C_BASE + 0x008) -++#define I2C_GR (I2C_BASE + 0x00C) -++ -++#define REG_I2C_DR REG8(I2C_DR) -++#define REG_I2C_CR REG8(I2C_CR) -++#define REG_I2C_SR REG8(I2C_SR) -++#define REG_I2C_GR REG16(I2C_GR) -++ -++/* I2C Control Register (I2C_CR) */ -++ -++#define I2C_CR_IEN (1 << 4) -++#define I2C_CR_STA (1 << 3) -++#define I2C_CR_STO (1 << 2) -++#define I2C_CR_AC (1 << 1) -++#define I2C_CR_I2CE (1 << 0) -++ -++/* I2C Status Register (I2C_SR) */ -++ -++#define I2C_SR_STX (1 << 4) -++#define I2C_SR_BUSY (1 << 3) -++#define I2C_SR_TEND (1 << 2) -++#define I2C_SR_DRF (1 << 1) -++#define I2C_SR_ACKF (1 << 0) -++ -++ -++/************************************************************************* -++ * SSI (Synchronous Serial Interface) -++ *************************************************************************/ -++/* n = 0, 1 (SSI0, SSI1) */ -++#define SSI_DR(n) (SSI_BASE + 0x000 + (n)*0x2000) -++#define SSI_CR0(n) (SSI_BASE + 0x004 + (n)*0x2000) -++#define SSI_CR1(n) (SSI_BASE + 0x008 + (n)*0x2000) -++#define SSI_SR(n) (SSI_BASE + 0x00C + (n)*0x2000) -++#define SSI_ITR(n) (SSI_BASE + 0x010 + (n)*0x2000) -++#define SSI_ICR(n) (SSI_BASE + 0x014 + (n)*0x2000) -++#define SSI_GR(n) (SSI_BASE + 0x018 + (n)*0x2000) -++ -++#define REG_SSI_DR(n) REG32(SSI_DR(n)) -++#define REG_SSI_CR0(n) REG16(SSI_CR0(n)) -++#define REG_SSI_CR1(n) REG32(SSI_CR1(n)) -++#define REG_SSI_SR(n) REG32(SSI_SR(n)) -++#define REG_SSI_ITR(n) REG16(SSI_ITR(n)) -++#define REG_SSI_ICR(n) REG8(SSI_ICR(n)) -++#define REG_SSI_GR(n) REG16(SSI_GR(n)) -++ -++/* SSI Data Register (SSI_DR) */ -++ -++#define SSI_DR_GPC_BIT 0 -++#define SSI_DR_GPC_MASK (0x1ff << SSI_DR_GPC_BIT) -++ -++#define SSI_MAX_FIFO_ENTRIES 128 /* 128 txfifo and 128 rxfifo */ -++ -++/* SSI Control Register 0 (SSI_CR0) */ -++ -++#define SSI_CR0_SSIE (1 << 15) -++#define SSI_CR0_TIE (1 << 14) -++#define SSI_CR0_RIE (1 << 13) -++#define SSI_CR0_TEIE (1 << 12) -++#define SSI_CR0_REIE (1 << 11) -++#define SSI_CR0_LOOP (1 << 10) -++#define SSI_CR0_RFINE (1 << 9) -++#define SSI_CR0_RFINC (1 << 8) -++#define SSI_CR0_EACLRUN (1 << 7) /* hardware auto clear underrun when TxFifo no empty */ -++#define SSI_CR0_FSEL (1 << 6) -++#define SSI_CR0_TFLUSH (1 << 2) -++#define SSI_CR0_RFLUSH (1 << 1) -++#define SSI_CR0_DISREV (1 << 0) -++ -++/* SSI Control Register 1 (SSI_CR1) */ -++ -++#define SSI_CR1_FRMHL_BIT 30 -++#define SSI_CR1_FRMHL_MASK (0x3 << SSI_CR1_FRMHL_BIT) -++ #define SSI_CR1_FRMHL_CELOW_CE2LOW (0 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is low valid */ -++ #define SSI_CR1_FRMHL_CEHIGH_CE2LOW (1 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is low valid */ -++ #define SSI_CR1_FRMHL_CELOW_CE2HIGH (2 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is high valid */ -++ #define SSI_CR1_FRMHL_CEHIGH_CE2HIGH (3 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is high valid */ -++#define SSI_CR1_TFVCK_BIT 28 -++#define SSI_CR1_TFVCK_MASK (0x3 << SSI_CR1_TFVCK_BIT) -++ #define SSI_CR1_TFVCK_0 (0 << SSI_CR1_TFVCK_BIT) -++ #define SSI_CR1_TFVCK_1 (1 << SSI_CR1_TFVCK_BIT) -++ #define SSI_CR1_TFVCK_2 (2 << SSI_CR1_TFVCK_BIT) -++ #define SSI_CR1_TFVCK_3 (3 << SSI_CR1_TFVCK_BIT) -++#define SSI_CR1_TCKFI_BIT 26 -++#define SSI_CR1_TCKFI_MASK (0x3 << SSI_CR1_TCKFI_BIT) -++ #define SSI_CR1_TCKFI_0 (0 << SSI_CR1_TCKFI_BIT) -++ #define SSI_CR1_TCKFI_1 (1 << SSI_CR1_TCKFI_BIT) -++ #define SSI_CR1_TCKFI_2 (2 << SSI_CR1_TCKFI_BIT) -++ #define SSI_CR1_TCKFI_3 (3 << SSI_CR1_TCKFI_BIT) -++#define SSI_CR1_LFST (1 << 25) -++#define SSI_CR1_ITFRM (1 << 24) -++#define SSI_CR1_UNFIN (1 << 23) -++#define SSI_CR1_MULTS (1 << 22) -++#define SSI_CR1_FMAT_BIT 20 -++#define SSI_CR1_FMAT_MASK (0x3 << SSI_CR1_FMAT_BIT) -++ #define SSI_CR1_FMAT_SPI (0 << SSI_CR1_FMAT_BIT) /* Motorola¡¯s SPI format */ -++ #define SSI_CR1_FMAT_SSP (1 << SSI_CR1_FMAT_BIT) /* TI's SSP format */ -++ #define SSI_CR1_FMAT_MW1 (2 << SSI_CR1_FMAT_BIT) /* National Microwire 1 format */ -++ #define SSI_CR1_FMAT_MW2 (3 << SSI_CR1_FMAT_BIT) /* National Microwire 2 format */ -++#define SSI_CR1_TTRG_BIT 16 /* SSI1 TX trigger */ -++#define SSI_CR1_TTRG_MASK (0xf << SSI_CR1_TTRG_BIT) -++#define SSI_CR1_MCOM_BIT 12 -++#define SSI_CR1_MCOM_MASK (0xf << SSI_CR1_MCOM_BIT) -++ #define SSI_CR1_MCOM_1BIT (0x0 << SSI_CR1_MCOM_BIT) /* 1-bit command selected */ -++ #define SSI_CR1_MCOM_2BIT (0x1 << SSI_CR1_MCOM_BIT) /* 2-bit command selected */ -++ #define SSI_CR1_MCOM_3BIT (0x2 << SSI_CR1_MCOM_BIT) /* 3-bit command selected */ -++ #define SSI_CR1_MCOM_4BIT (0x3 << SSI_CR1_MCOM_BIT) /* 4-bit command selected */ -++ #define SSI_CR1_MCOM_5BIT (0x4 << SSI_CR1_MCOM_BIT) /* 5-bit command selected */ -++ #define SSI_CR1_MCOM_6BIT (0x5 << SSI_CR1_MCOM_BIT) /* 6-bit command selected */ -++ #define SSI_CR1_MCOM_7BIT (0x6 << SSI_CR1_MCOM_BIT) /* 7-bit command selected */ -++ #define SSI_CR1_MCOM_8BIT (0x7 << SSI_CR1_MCOM_BIT) /* 8-bit command selected */ -++ #define SSI_CR1_MCOM_9BIT (0x8 << SSI_CR1_MCOM_BIT) /* 9-bit command selected */ -++ #define SSI_CR1_MCOM_10BIT (0x9 << SSI_CR1_MCOM_BIT) /* 10-bit command selected */ -++ #define SSI_CR1_MCOM_11BIT (0xA << SSI_CR1_MCOM_BIT) /* 11-bit command selected */ -++ #define SSI_CR1_MCOM_12BIT (0xB << SSI_CR1_MCOM_BIT) /* 12-bit command selected */ -++ #define SSI_CR1_MCOM_13BIT (0xC << SSI_CR1_MCOM_BIT) /* 13-bit command selected */ -++ #define SSI_CR1_MCOM_14BIT (0xD << SSI_CR1_MCOM_BIT) /* 14-bit command selected */ -++ #define SSI_CR1_MCOM_15BIT (0xE << SSI_CR1_MCOM_BIT) /* 15-bit command selected */ -++ #define SSI_CR1_MCOM_16BIT (0xF << SSI_CR1_MCOM_BIT) /* 16-bit command selected */ -++#define SSI_CR1_RTRG_BIT 8 /* SSI RX trigger */ -++#define SSI_CR1_RTRG_MASK (0xf << SSI_CR1_RTRG_BIT) -++#define SSI_CR1_FLEN_BIT 4 -++#define SSI_CR1_FLEN_MASK (0xf << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_2BIT (0x0 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_3BIT (0x1 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_4BIT (0x2 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_5BIT (0x3 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_6BIT (0x4 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_7BIT (0x5 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_8BIT (0x6 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_9BIT (0x7 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_10BIT (0x8 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_11BIT (0x9 << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_12BIT (0xA << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_13BIT (0xB << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_14BIT (0xC << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_15BIT (0xD << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_16BIT (0xE << SSI_CR1_FLEN_BIT) -++ #define SSI_CR1_FLEN_17BIT (0xF << SSI_CR1_FLEN_BIT) -++#define SSI_CR1_PHA (1 << 1) -++#define SSI_CR1_POL (1 << 0) -++ -++/* SSI Status Register (SSI_SR) */ -++ -++#define SSI_SR_TFIFONUM_BIT 16 -++#define SSI_SR_TFIFONUM_MASK (0xff << SSI_SR_TFIFONUM_BIT) -++#define SSI_SR_RFIFONUM_BIT 8 -++#define SSI_SR_RFIFONUM_MASK (0xff << SSI_SR_RFIFONUM_BIT) -++#define SSI_SR_END (1 << 7) -++#define SSI_SR_BUSY (1 << 6) -++#define SSI_SR_TFF (1 << 5) -++#define SSI_SR_RFE (1 << 4) -++#define SSI_SR_TFHE (1 << 3) -++#define SSI_SR_RFHF (1 << 2) -++#define SSI_SR_UNDR (1 << 1) -++#define SSI_SR_OVER (1 << 0) -++ -++/* SSI Interval Time Control Register (SSI_ITR) */ -++ -++#define SSI_ITR_CNTCLK (1 << 15) -++#define SSI_ITR_IVLTM_BIT 0 -++#define SSI_ITR_IVLTM_MASK (0x7fff << SSI_ITR_IVLTM_BIT) -++ -++ -++/************************************************************************* -++ * MSC -++ ************************************************************************/ -++/* n = 0, 1 (MSC0, MSC1) */ -++#define MSC_STRPCL(n) (MSC_BASE + (n)*0x1000 + 0x000) -++#define MSC_STAT(n) (MSC_BASE + (n)*0x1000 + 0x004) -++#define MSC_CLKRT(n) (MSC_BASE + (n)*0x1000 + 0x008) -++#define MSC_CMDAT(n) (MSC_BASE + (n)*0x1000 + 0x00C) -++#define MSC_RESTO(n) (MSC_BASE + (n)*0x1000 + 0x010) -++#define MSC_RDTO(n) (MSC_BASE + (n)*0x1000 + 0x014) -++#define MSC_BLKLEN(n) (MSC_BASE + (n)*0x1000 + 0x018) -++#define MSC_NOB(n) (MSC_BASE + (n)*0x1000 + 0x01C) -++#define MSC_SNOB(n) (MSC_BASE + (n)*0x1000 + 0x020) -++#define MSC_IMASK(n) (MSC_BASE + (n)*0x1000 + 0x024) -++#define MSC_IREG(n) (MSC_BASE + (n)*0x1000 + 0x028) -++#define MSC_CMD(n) (MSC_BASE + (n)*0x1000 + 0x02C) -++#define MSC_ARG(n) (MSC_BASE + (n)*0x1000 + 0x030) -++#define MSC_RES(n) (MSC_BASE + (n)*0x1000 + 0x034) -++#define MSC_RXFIFO(n) (MSC_BASE + (n)*0x1000 + 0x038) -++#define MSC_TXFIFO(n) (MSC_BASE + (n)*0x1000 + 0x03C) -++#define MSC_LPM(n) (MSC_BASE + (n)*0x1000 + 0x040) -++ -++#define REG_MSC_STRPCL(n) REG16(MSC_STRPCL(n)) -++#define REG_MSC_STAT(n) REG32(MSC_STAT(n)) -++#define REG_MSC_CLKRT(n) REG16(MSC_CLKRT(n)) -++#define REG_MSC_CMDAT(n) REG32(MSC_CMDAT(n)) -++#define REG_MSC_RESTO(n) REG16(MSC_RESTO(n)) -++#define REG_MSC_RDTO(n) REG16(MSC_RDTO(n)) -++#define REG_MSC_BLKLEN(n) REG16(MSC_BLKLEN(n)) -++#define REG_MSC_NOB(n) REG16(MSC_NOB(n)) -++#define REG_MSC_SNOB(n) REG16(MSC_SNOB(n)) -++#define REG_MSC_IMASK(n) REG32(MSC_IMASK(n)) -++#define REG_MSC_IREG(n) REG16(MSC_IREG(n)) -++#define REG_MSC_CMD(n) REG8(MSC_CMD(n)) -++#define REG_MSC_ARG(n) REG32(MSC_ARG(n)) -++#define REG_MSC_RES(n) REG16(MSC_RES(n)) -++#define REG_MSC_RXFIFO(n) REG32(MSC_RXFIFO(n)) -++#define REG_MSC_TXFIFO(n) REG32(MSC_TXFIFO(n)) -++#define REG_MSC_LPM(n) REG32(MSC_LPM(n)) -++ -++/* MSC Clock and Control Register (MSC_STRPCL) */ -++#define MSC_STRPCL_SEND_CCSD (1 << 15) /*send command completion signal disable to ceata */ -++#define MSC_STRPCL_SEND_AS_CCSD (1 << 14) /*send internally generated stop after sending ccsd */ -++#define MSC_STRPCL_EXIT_MULTIPLE (1 << 7) -++#define MSC_STRPCL_EXIT_TRANSFER (1 << 6) -++#define MSC_STRPCL_START_READWAIT (1 << 5) -++#define MSC_STRPCL_STOP_READWAIT (1 << 4) -++#define MSC_STRPCL_RESET (1 << 3) -++#define MSC_STRPCL_START_OP (1 << 2) -++#define MSC_STRPCL_CLOCK_CONTROL_BIT 0 -++#define MSC_STRPCL_CLOCK_CONTROL_MASK (0x3 << MSC_STRPCL_CLOCK_CONTROL_BIT) -++ #define MSC_STRPCL_CLOCK_CONTROL_STOP (0x1 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Stop MMC/SD clock */ -++ #define MSC_STRPCL_CLOCK_CONTROL_START (0x2 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Start MMC/SD clock */ -++ -++/* MSC Status Register (MSC_STAT) */ -++#define MSC_STAT_AUTO_CMD_DONE (1 << 31) /*12 is internally generated by controller has finished */ -++#define MSC_STAT_IS_RESETTING (1 << 15) -++#define MSC_STAT_SDIO_INT_ACTIVE (1 << 14) -++#define MSC_STAT_PRG_DONE (1 << 13) -++#define MSC_STAT_DATA_TRAN_DONE (1 << 12) -++#define MSC_STAT_END_CMD_RES (1 << 11) -++#define MSC_STAT_DATA_FIFO_AFULL (1 << 10) -++#define MSC_STAT_IS_READWAIT (1 << 9) -++#define MSC_STAT_CLK_EN (1 << 8) -++#define MSC_STAT_DATA_FIFO_FULL (1 << 7) -++#define MSC_STAT_DATA_FIFO_EMPTY (1 << 6) -++#define MSC_STAT_CRC_RES_ERR (1 << 5) -++#define MSC_STAT_CRC_READ_ERROR (1 << 4) -++#define MSC_STAT_CRC_WRITE_ERROR_BIT 2 -++#define MSC_STAT_CRC_WRITE_ERROR_MASK (0x3 << MSC_STAT_CRC_WRITE_ERROR_BIT) -++ #define MSC_STAT_CRC_WRITE_ERROR_NO (0 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No error on transmission of data */ -++ #define MSC_STAT_CRC_WRITE_ERROR (1 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* Card observed erroneous transmission of data */ -++ #define MSC_STAT_CRC_WRITE_ERROR_NOSTS (2 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No CRC status is sent back */ -++#define MSC_STAT_TIME_OUT_RES (1 << 1) -++#define MSC_STAT_TIME_OUT_READ (1 << 0) -++ -++/* MSC Bus Clock Control Register (MSC_CLKRT) */ -++#define MSC_CLKRT_CLK_RATE_BIT 0 -++#define MSC_CLKRT_CLK_RATE_MASK (0x7 << MSC_CLKRT_CLK_RATE_BIT) -++ #define MSC_CLKRT_CLK_RATE_DIV_1 (0x0 << MSC_CLKRT_CLK_RATE_BIT) /* CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_2 (0x1 << MSC_CLKRT_CLK_RATE_BIT) /* 1/2 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_4 (0x2 << MSC_CLKRT_CLK_RATE_BIT) /* 1/4 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_8 (0x3 << MSC_CLKRT_CLK_RATE_BIT) /* 1/8 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_16 (0x4 << MSC_CLKRT_CLK_RATE_BIT) /* 1/16 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_32 (0x5 << MSC_CLKRT_CLK_RATE_BIT) /* 1/32 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_64 (0x6 << MSC_CLKRT_CLK_RATE_BIT) /* 1/64 of CLK_SRC */ -++ #define MSC_CLKRT_CLK_RATE_DIV_128 (0x7 << MSC_CLKRT_CLK_RATE_BIT) /* 1/128 of CLK_SRC */ -++ -++/* MSC Command Sequence Control Register (MSC_CMDAT) */ -++#define MSC_CMDAT_CCS_EXPECTED (1 << 31) /* interrupts are enabled in ce-ata */ -++#define MSC_CMDAT_READ_CEATA (1 << 30) -++#define MSC_CMDAT_SDIO_PRDT (1 << 17) /* exact 2 cycle */ -++#define MSC_CMDAT_SEND_AS_STOP (1 << 16) -++#define MSC_CMDAT_RTRG_BIT 14 -++ #define MSC_CMDAT_RTRG_EQUALT_8 (0x0 << MSC_CMDAT_RTRG_BIT) -++ #define MSC_CMDAT_RTRG_EQUALT_16 (0x1 << MSC_CMDAT_RTRG_BIT) /* reset value */ -++ #define MSC_CMDAT_RTRG_EQUALT_24 (0x2 << MSC_CMDAT_RTRG_BIT) -++ -++#define MSC_CMDAT_TTRG_BIT 12 -++ #define MSC_CMDAT_TTRG_LESS_8 (0x0 << MSC_CMDAT_TTRG_BIT) -++ #define MSC_CMDAT_TTRG_LESS_16 (0x1 << MSC_CMDAT_TTRG_BIT) /*reset value */ -++ #define MSC_CMDAT_TTRG_LESS_24 (0x2 << MSC_CMDAT_TTRG_BIT) -++#define MSC_CMDAT_STOP_ABORT (1 << 11) -++#define MSC_CMDAT_BUS_WIDTH_BIT 9 -++#define MSC_CMDAT_BUS_WIDTH_MASK (0x3 << MSC_CMDAT_BUS_WIDTH_BIT) -++ #define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) /* 1-bit data bus */ -++ #define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) /* 4-bit data bus */ -++ #define MSC_CMDAT_BUS_WIDTH_8BIT (0x3 << MSC_CMDAT_BUS_WIDTH_BIT) /* 8-bit data bus */ -++#define MSC_CMDAT_DMA_EN (1 << 8) -++#define MSC_CMDAT_INIT (1 << 7) -++#define MSC_CMDAT_BUSY (1 << 6) -++#define MSC_CMDAT_STREAM_BLOCK (1 << 5) -++#define MSC_CMDAT_WRITE (1 << 4) -++#define MSC_CMDAT_READ (0 << 4) -++#define MSC_CMDAT_DATA_EN (1 << 3) -++#define MSC_CMDAT_RESPONSE_BIT 0 -++#define MSC_CMDAT_RESPONSE_MASK (0x7 << MSC_CMDAT_RESPONSE_BIT) -++ #define MSC_CMDAT_RESPONSE_NONE (0x0 << MSC_CMDAT_RESPONSE_BIT) /* No response */ -++ #define MSC_CMDAT_RESPONSE_R1 (0x1 << MSC_CMDAT_RESPONSE_BIT) /* Format R1 and R1b */ -++ #define MSC_CMDAT_RESPONSE_R2 (0x2 << MSC_CMDAT_RESPONSE_BIT) /* Format R2 */ -++ #define MSC_CMDAT_RESPONSE_R3 (0x3 << MSC_CMDAT_RESPONSE_BIT) /* Format R3 */ -++ #define MSC_CMDAT_RESPONSE_R4 (0x4 << MSC_CMDAT_RESPONSE_BIT) /* Format R4 */ -++ #define MSC_CMDAT_RESPONSE_R5 (0x5 << MSC_CMDAT_RESPONSE_BIT) /* Format R5 */ -++ #define MSC_CMDAT_RESPONSE_R6 (0x6 << MSC_CMDAT_RESPONSE_BIT) /* Format R6 */ -++ -++#define CMDAT_DMA_EN (1 << 8) -++#define CMDAT_INIT (1 << 7) -++#define CMDAT_BUSY (1 << 6) -++#define CMDAT_STREAM (1 << 5) -++#define CMDAT_WRITE (1 << 4) -++#define CMDAT_DATA_EN (1 << 3) -++ -++/* MSC Interrupts Mask Register (MSC_IMASK) */ -++#define MSC_IMASK_AUTO_CMD_DONE (1 << 8) -++#define MSC_IMASK_SDIO (1 << 7) -++#define MSC_IMASK_TXFIFO_WR_REQ (1 << 6) -++#define MSC_IMASK_RXFIFO_RD_REQ (1 << 5) -++#define MSC_IMASK_END_CMD_RES (1 << 2) -++#define MSC_IMASK_PRG_DONE (1 << 1) -++#define MSC_IMASK_DATA_TRAN_DONE (1 << 0) -++ -++/* MSC Interrupts Status Register (MSC_IREG) */ -++#define MSC_IREG_AUTO_CMD_DONE (1 << 8) -++#define MSC_IREG_SDIO (1 << 7) -++#define MSC_IREG_TXFIFO_WR_REQ (1 << 6) -++#define MSC_IREG_RXFIFO_RD_REQ (1 << 5) -++#define MSC_IREG_END_CMD_RES (1 << 2) -++#define MSC_IREG_PRG_DONE (1 << 1) -++#define MSC_IREG_DATA_TRAN_DONE (1 << 0) -++ -++/* MSC Low Power Mode Register (MSC_LPM) */ -++#define MSC_SET_LPM (1 << 0) -++ -++/************************************************************************* -++ * EMC (External Memory Controller) -++ *************************************************************************/ -++#define EMC_BCR (EMC_BASE + 0x00) /* Bus Control Register */ -++#define EMC_SMCR0 (EMC_BASE + 0x10) /* Static Memory Control Register 0 */ -++#define EMC_SMCR1 (EMC_BASE + 0x14) /* Static Memory Control Register 1 */ -++#define EMC_SMCR2 (EMC_BASE + 0x18) /* Static Memory Control Register 2 */ -++#define EMC_SMCR3 (EMC_BASE + 0x1c) /* Static Memory Control Register 3 */ -++#define EMC_SMCR4 (EMC_BASE + 0x20) /* Static Memory Control Register 4 */ -++#define EMC_SACR0 (EMC_BASE + 0x30) /* Static Memory Bank 0 Addr Config Reg */ -++#define EMC_SACR1 (EMC_BASE + 0x34) /* Static Memory Bank 1 Addr Config Reg */ -++#define EMC_SACR2 (EMC_BASE + 0x38) /* Static Memory Bank 2 Addr Config Reg */ -++#define EMC_SACR3 (EMC_BASE + 0x3c) /* Static Memory Bank 3 Addr Config Reg */ -++#define EMC_SACR4 (EMC_BASE + 0x40) /* Static Memory Bank 4 Addr Config Reg */ -++ -++#define EMC_NFCSR (EMC_BASE + 0x050) /* NAND Flash Control/Status Register */ -++ -++#define EMC_DMCR (EMC_BASE + 0x80) /* DRAM Control Register */ -++#define EMC_RTCSR (EMC_BASE + 0x84) /* Refresh Time Control/Status Register */ -++#define EMC_RTCNT (EMC_BASE + 0x88) /* Refresh Timer Counter */ -++#define EMC_RTCOR (EMC_BASE + 0x8c) /* Refresh Time Constant Register */ -++#define EMC_DMAR0 (EMC_BASE + 0x90) /* SDRAM Bank 0 Addr Config Register */ -++#define EMC_DMAR1 (EMC_BASE + 0x94) /* SDRAM Bank 1 Addr Config Register */ -++#define EMC_SDMR0 (EMC_BASE + 0xa000) /* Mode Register of SDRAM bank 0 */ -++ -++#define REG_EMC_BCR REG32(EMC_BCR) -++#define REG_EMC_SMCR0 REG32(EMC_SMCR0) -++#define REG_EMC_SMCR1 REG32(EMC_SMCR1) -++#define REG_EMC_SMCR2 REG32(EMC_SMCR2) -++#define REG_EMC_SMCR3 REG32(EMC_SMCR3) -++#define REG_EMC_SMCR4 REG32(EMC_SMCR4) -++#define REG_EMC_SACR0 REG32(EMC_SACR0) -++#define REG_EMC_SACR1 REG32(EMC_SACR1) -++#define REG_EMC_SACR2 REG32(EMC_SACR2) -++#define REG_EMC_SACR3 REG32(EMC_SACR3) -++#define REG_EMC_SACR4 REG32(EMC_SACR4) -++ -++#define REG_EMC_NFCSR REG32(EMC_NFCSR) -++ -++#define REG_EMC_DMCR REG32(EMC_DMCR) -++#define REG_EMC_RTCSR REG16(EMC_RTCSR) -++#define REG_EMC_RTCNT REG16(EMC_RTCNT) -++#define REG_EMC_RTCOR REG16(EMC_RTCOR) -++#define REG_EMC_DMAR0 REG32(EMC_DMAR0) -++#define REG_EMC_DMAR1 REG32(EMC_DMAR1) -++ -++/* Bus Control Register */ -++#define EMC_BCR_BT_SEL_BIT 30 -++#define EMC_BCR_BT_SEL_MASK (0x3 << EMC_BCR_BT_SEL_BIT) -++#define EMC_BCR_PK_SEL (1 << 24) -++#define EMC_BCR_BSR_MASK (1 << 2) /* Nand and SDRAM Bus Share Select: 0, share; 1, unshare */ -++ #define EMC_BCR_BSR_SHARE (0 << 2) -++ #define EMC_BCR_BSR_UNSHARE (1 << 2) -++#define EMC_BCR_BRE (1 << 1) -++#define EMC_BCR_ENDIAN (1 << 0) -++ -++/* Static Memory Control Register */ -++#define EMC_SMCR_STRV_BIT 24 -++#define EMC_SMCR_STRV_MASK (0x0f << EMC_SMCR_STRV_BIT) -++#define EMC_SMCR_TAW_BIT 20 -++#define EMC_SMCR_TAW_MASK (0x0f << EMC_SMCR_TAW_BIT) -++#define EMC_SMCR_TBP_BIT 16 -++#define EMC_SMCR_TBP_MASK (0x0f << EMC_SMCR_TBP_BIT) -++#define EMC_SMCR_TAH_BIT 12 -++#define EMC_SMCR_TAH_MASK (0x07 << EMC_SMCR_TAH_BIT) -++#define EMC_SMCR_TAS_BIT 8 -++#define EMC_SMCR_TAS_MASK (0x07 << EMC_SMCR_TAS_BIT) -++#define EMC_SMCR_BW_BIT 6 -++#define EMC_SMCR_BW_MASK (0x03 << EMC_SMCR_BW_BIT) -++ #define EMC_SMCR_BW_8BIT (0 << EMC_SMCR_BW_BIT) -++ #define EMC_SMCR_BW_16BIT (1 << EMC_SMCR_BW_BIT) -++ #define EMC_SMCR_BW_32BIT (2 << EMC_SMCR_BW_BIT) -++#define EMC_SMCR_BCM (1 << 3) -++#define EMC_SMCR_BL_BIT 1 -++#define EMC_SMCR_BL_MASK (0x03 << EMC_SMCR_BL_BIT) -++ #define EMC_SMCR_BL_4 (0 << EMC_SMCR_BL_BIT) -++ #define EMC_SMCR_BL_8 (1 << EMC_SMCR_BL_BIT) -++ #define EMC_SMCR_BL_16 (2 << EMC_SMCR_BL_BIT) -++ #define EMC_SMCR_BL_32 (3 << EMC_SMCR_BL_BIT) -++#define EMC_SMCR_SMT (1 << 0) -++ -++/* Static Memory Bank Addr Config Reg */ -++#define EMC_SACR_BASE_BIT 8 -++#define EMC_SACR_BASE_MASK (0xff << EMC_SACR_BASE_BIT) -++#define EMC_SACR_MASK_BIT 0 -++#define EMC_SACR_MASK_MASK (0xff << EMC_SACR_MASK_BIT) -++ -++/* NAND Flash Control/Status Register */ -++#define EMC_NFCSR_NFCE4 (1 << 7) /* NAND Flash Enable */ -++#define EMC_NFCSR_NFE4 (1 << 6) /* NAND Flash FCE# Assertion Enable */ -++#define EMC_NFCSR_NFCE3 (1 << 5) -++#define EMC_NFCSR_NFE3 (1 << 4) -++#define EMC_NFCSR_NFCE2 (1 << 3) -++#define EMC_NFCSR_NFE2 (1 << 2) -++#define EMC_NFCSR_NFCE1 (1 << 1) -++#define EMC_NFCSR_NFE1 (1 << 0) -++ -++/* DRAM Control Register */ -++#define EMC_DMCR_BW_BIT 31 -++#define EMC_DMCR_BW (1 << EMC_DMCR_BW_BIT) -++#define EMC_DMCR_CA_BIT 26 -++#define EMC_DMCR_CA_MASK (0x07 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_8 (0 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_9 (1 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_10 (2 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_11 (3 << EMC_DMCR_CA_BIT) -++ #define EMC_DMCR_CA_12 (4 << EMC_DMCR_CA_BIT) -++#define EMC_DMCR_RMODE (1 << 25) -++#define EMC_DMCR_RFSH (1 << 24) -++#define EMC_DMCR_MRSET (1 << 23) -++#define EMC_DMCR_RA_BIT 20 -++#define EMC_DMCR_RA_MASK (0x03 << EMC_DMCR_RA_BIT) -++ #define EMC_DMCR_RA_11 (0 << EMC_DMCR_RA_BIT) -++ #define EMC_DMCR_RA_12 (1 << EMC_DMCR_RA_BIT) -++ #define EMC_DMCR_RA_13 (2 << EMC_DMCR_RA_BIT) -++#define EMC_DMCR_BA_BIT 19 -++#define EMC_DMCR_BA (1 << EMC_DMCR_BA_BIT) -++#define EMC_DMCR_PDM (1 << 18) -++#define EMC_DMCR_EPIN (1 << 17) -++#define EMC_DMCR_MBSEL (1 << 16) -++#define EMC_DMCR_TRAS_BIT 13 -++#define EMC_DMCR_TRAS_MASK (0x07 << EMC_DMCR_TRAS_BIT) -++#define EMC_DMCR_RCD_BIT 11 -++#define EMC_DMCR_RCD_MASK (0x03 << EMC_DMCR_RCD_BIT) -++#define EMC_DMCR_TPC_BIT 8 -++#define EMC_DMCR_TPC_MASK (0x07 << EMC_DMCR_TPC_BIT) -++#define EMC_DMCR_TRWL_BIT 5 -++#define EMC_DMCR_TRWL_MASK (0x03 << EMC_DMCR_TRWL_BIT) -++#define EMC_DMCR_TRC_BIT 2 -++#define EMC_DMCR_TRC_MASK (0x07 << EMC_DMCR_TRC_BIT) -++#define EMC_DMCR_TCL_BIT 0 -++#define EMC_DMCR_TCL_MASK (0x03 << EMC_DMCR_TCL_BIT) -++ -++/* Refresh Time Control/Status Register */ -++#define EMC_RTCSR_SFR (1 << 8) /* self refresh flag */ -++#define EMC_RTCSR_CMF (1 << 7) -++#define EMC_RTCSR_CKS_BIT 0 -++#define EMC_RTCSR_CKS_MASK (0x07 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_DISABLE (0 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_4 (1 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_16 (2 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_64 (3 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_256 (4 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_1024 (5 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_2048 (6 << EMC_RTCSR_CKS_BIT) -++ #define EMC_RTCSR_CKS_4096 (7 << EMC_RTCSR_CKS_BIT) -++ -++/* SDRAM Bank Address Configuration Register */ -++#define EMC_DMAR_BASE_BIT 8 -++#define EMC_DMAR_BASE_MASK (0xff << EMC_DMAR_BASE_BIT) -++#define EMC_DMAR_MASK_BIT 0 -++#define EMC_DMAR_MASK_MASK (0xff << EMC_DMAR_MASK_BIT) -++ -++/* Mode Register of SDRAM bank 0 */ -++#define EMC_SDMR_BM (1 << 9) /* Write Burst Mode */ -++#define EMC_SDMR_OM_BIT 7 /* Operating Mode */ -++#define EMC_SDMR_OM_MASK (3 << EMC_SDMR_OM_BIT) -++ #define EMC_SDMR_OM_NORMAL (0 << EMC_SDMR_OM_BIT) -++#define EMC_SDMR_CAS_BIT 4 /* CAS Latency */ -++#define EMC_SDMR_CAS_MASK (7 << EMC_SDMR_CAS_BIT) -++ #define EMC_SDMR_CAS_1 (1 << EMC_SDMR_CAS_BIT) -++ #define EMC_SDMR_CAS_2 (2 << EMC_SDMR_CAS_BIT) -++ #define EMC_SDMR_CAS_3 (3 << EMC_SDMR_CAS_BIT) -++#define EMC_SDMR_BT_BIT 3 /* Burst Type */ -++#define EMC_SDMR_BT_MASK (1 << EMC_SDMR_BT_BIT) -++ #define EMC_SDMR_BT_SEQ (0 << EMC_SDMR_BT_BIT) /* Sequential */ -++ #define EMC_SDMR_BT_INT (1 << EMC_SDMR_BT_BIT) /* Interleave */ -++#define EMC_SDMR_BL_BIT 0 /* Burst Length */ -++#define EMC_SDMR_BL_MASK (7 << EMC_SDMR_BL_BIT) -++ #define EMC_SDMR_BL_1 (0 << EMC_SDMR_BL_BIT) -++ #define EMC_SDMR_BL_2 (1 << EMC_SDMR_BL_BIT) -++ #define EMC_SDMR_BL_4 (2 << EMC_SDMR_BL_BIT) -++ #define EMC_SDMR_BL_8 (3 << EMC_SDMR_BL_BIT) -++ -++#define EMC_SDMR_CAS2_16BIT \ -++ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) -++#define EMC_SDMR_CAS2_32BIT \ -++ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) -++#define EMC_SDMR_CAS3_16BIT \ -++ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2) -++#define EMC_SDMR_CAS3_32BIT \ -++ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4) -++ -++ -++/************************************************************************* -++ * CIM -++ *************************************************************************/ -++#define CIM_CFG (CIM_BASE + 0x0000) -++#define CIM_CTRL (CIM_BASE + 0x0004) -++#define CIM_STATE (CIM_BASE + 0x0008) -++#define CIM_IID (CIM_BASE + 0x000C) -++#define CIM_RXFIFO (CIM_BASE + 0x0010) -++#define CIM_DA (CIM_BASE + 0x0020) -++#define CIM_FA (CIM_BASE + 0x0024) -++#define CIM_FID (CIM_BASE + 0x0028) -++#define CIM_CMD (CIM_BASE + 0x002C) -++#define CIM_SIZE (CIM_BASE + 0x0030) -++#define CIM_OFFSET (CIM_BASE + 0x0034) -++#define CIM_RAM_ADDR (CIM_BASE + 0x1000) -++ -++#define REG_CIM_CFG REG32(CIM_CFG) -++#define REG_CIM_CTRL REG32(CIM_CTRL) -++#define REG_CIM_STATE REG32(CIM_STATE) -++#define REG_CIM_IID REG32(CIM_IID) -++#define REG_CIM_RXFIFO REG32(CIM_RXFIFO) -++#define REG_CIM_DA REG32(CIM_DA) -++#define REG_CIM_FA REG32(CIM_FA) -++#define REG_CIM_FID REG32(CIM_FID) -++#define REG_CIM_CMD REG32(CIM_CMD) -++#define REG_CIM_SIZE REG32(CIM_SIZE) -++#define REG_CIM_OFFSET REG32(CIM_OFFSET) -++ -++#define CIM_CFG_ORDER_BIT 18 -++#define CIM_CFG_ORDER_MASK (0x3 << CIM_CFG_ORDER_BIT) -++ #define CIM_CFG_ORDER_0 (0x0 << CIM_CFG_ORDER_BIT) /* Y0CbY1Cr; YCbCr */ -++ #define CIM_CFG_ORDER_1 (0x1 << CIM_CFG_ORDER_BIT) /* Y0CrY1Cb; YCrCb */ -++ #define CIM_CFG_ORDER_2 (0x2 << CIM_CFG_ORDER_BIT) /* CbY0CrY1; CbCrY */ -++ #define CIM_CFG_ORDER_3 (0x3 << CIM_CFG_ORDER_BIT) /* CrY0CbY1; CrCbY */ -++#define CIM_CFG_DF_BIT 16 -++#define CIM_CFG_DF_MASK (0x3 << CIM_CFG_DF_BIT) -++ #define CIM_CFG_DF_YUV444 (0x1 << CIM_CFG_DF_BIT) /* YCbCr444 */ -++ #define CIM_CFG_DF_YUV422 (0x2 << CIM_CFG_DF_BIT) /* YCbCr422 */ -++ #define CIM_CFG_DF_ITU656 (0x3 << CIM_CFG_DF_BIT) /* ITU656 YCbCr422 */ -++#define CIM_CFG_INV_DAT (1 << 15) -++#define CIM_CFG_VSP (1 << 14) /* VSYNC Polarity:0-rising edge active,1-falling edge active */ -++#define CIM_CFG_HSP (1 << 13) /* HSYNC Polarity:0-rising edge active,1-falling edge active */ -++#define CIM_CFG_PCP (1 << 12) /* PCLK working edge: 0-rising, 1-falling */ -++#define CIM_CFG_DMA_BURST_TYPE_BIT 10 -++#define CIM_CFG_DMA_BURST_TYPE_MASK (0x3 << CIM_CFG_DMA_BURST_TYPE_BIT) -++ #define CIM_CFG_DMA_BURST_INCR4 (0 << CIM_CFG_DMA_BURST_TYPE_BIT) -++ #define CIM_CFG_DMA_BURT_INCR8 (1 << CIM_CFG_DMA_BURST_TYPE_BIT) /* Suggested */ -++ #define CIM_CFG_DMA_BURT_INCR16 (2 << CIM_CFG_DMA_BURST_TYPE_BIT) /* Suggested High speed AHB*/ -++#define CIM_CFG_DUMMY_ZERO (1 << 9) -++#define CIM_CFG_EXT_VSYNC (1 << 8) /* Only for ITU656 Progressive mode */ -++#define CIM_CFG_PACK_BIT 4 -++#define CIM_CFG_PACK_MASK (0x7 << CIM_CFG_PACK_BIT) -++ #define CIM_CFG_PACK_0 (0 << CIM_CFG_PACK_BIT) /* 11 22 33 44 0xY0CbY1Cr */ -++ #define CIM_CFG_PACK_1 (1 << CIM_CFG_PACK_BIT) /* 22 33 44 11 0xCbY1CrY0 */ -++ #define CIM_CFG_PACK_2 (2 << CIM_CFG_PACK_BIT) /* 33 44 11 22 0xY1CrY0Cb */ -++ #define CIM_CFG_PACK_3 (3 << CIM_CFG_PACK_BIT) /* 44 11 22 33 0xCrY0CbY1 */ -++ #define CIM_CFG_PACK_4 (4 << CIM_CFG_PACK_BIT) /* 44 33 22 11 0xCrY1CbY0 */ -++ #define CIM_CFG_PACK_5 (5 << CIM_CFG_PACK_BIT) /* 33 22 11 44 0xY1CbY0Cr */ -++ #define CIM_CFG_PACK_6 (6 << CIM_CFG_PACK_BIT) /* 22 11 44 33 0xCbY0CrY1 */ -++ #define CIM_CFG_PACK_7 (7 << CIM_CFG_PACK_BIT) /* 11 44 33 22 0xY0CrY1Cb */ -++#define CIM_CFG_BYPASS_BIT 2 -++#define CIM_CFG_BYPASS_MASK (1 << CIM_CFG_BYPASS_BIT) -++ #define CIM_CFG_BYPASS (1 << CIM_CFG_BYPASS_BIT) -++#define CIM_CFG_DSM_BIT 0 -++#define CIM_CFG_DSM_MASK (0x3 << CIM_CFG_DSM_BIT) -++ #define CIM_CFG_DSM_CPM (0 << CIM_CFG_DSM_BIT) /* CCIR656 Progressive Mode */ -++ #define CIM_CFG_DSM_CIM (1 << CIM_CFG_DSM_BIT) /* CCIR656 Interlace Mode */ -++ #define CIM_CFG_DSM_GCM (2 << CIM_CFG_DSM_BIT) /* Gated Clock Mode */ -++ -++/* CIM Control Register (CIM_CTRL) */ -++#define CIM_CTRL_EEOF_LINE_BIT 20 -++#define CIM_CTRL_EEOF_LINE_MASK (0xfff << CIM_CTRL_MCLKDIV_BIT) -++#define CIM_CTRL_FRC_BIT 16 -++#define CIM_CTRL_FRC_MASK (0xf << CIM_CTRL_FRC_BIT) -++ #define CIM_CTRL_FRC_1 (0x0 << CIM_CTRL_FRC_BIT) /* Sample every frame */ -++ #define CIM_CTRL_FRC_2 (0x1 << CIM_CTRL_FRC_BIT) /* Sample 1/2 frame */ -++ #define CIM_CTRL_FRC_3 (0x2 << CIM_CTRL_FRC_BIT) /* Sample 1/3 frame */ -++ #define CIM_CTRL_FRC_4 (0x3 << CIM_CTRL_FRC_BIT) /* Sample 1/4 frame */ -++ #define CIM_CTRL_FRC_5 (0x4 << CIM_CTRL_FRC_BIT) /* Sample 1/5 frame */ -++ #define CIM_CTRL_FRC_6 (0x5 << CIM_CTRL_FRC_BIT) /* Sample 1/6 frame */ -++ #define CIM_CTRL_FRC_7 (0x6 << CIM_CTRL_FRC_BIT) /* Sample 1/7 frame */ -++ #define CIM_CTRL_FRC_8 (0x7 << CIM_CTRL_FRC_BIT) /* Sample 1/8 frame */ -++ #define CIM_CTRL_FRC_9 (0x8 << CIM_CTRL_FRC_BIT) /* Sample 1/9 frame */ -++ #define CIM_CTRL_FRC_10 (0x9 << CIM_CTRL_FRC_BIT) /* Sample 1/10 frame */ -++ #define CIM_CTRL_FRC_11 (0xA << CIM_CTRL_FRC_BIT) /* Sample 1/11 frame */ -++ #define CIM_CTRL_FRC_12 (0xB << CIM_CTRL_FRC_BIT) /* Sample 1/12 frame */ -++ #define CIM_CTRL_FRC_13 (0xC << CIM_CTRL_FRC_BIT) /* Sample 1/13 frame */ -++ #define CIM_CTRL_FRC_14 (0xD << CIM_CTRL_FRC_BIT) /* Sample 1/14 frame */ -++ #define CIM_CTRL_FRC_15 (0xE << CIM_CTRL_FRC_BIT) /* Sample 1/15 frame */ -++ #define CIM_CTRL_FRC_16 (0xF << CIM_CTRL_FRC_BIT) /* Sample 1/16 frame */ -++ -++#define CIM_CTRL_DMA_EEOFM (1 << 15) /* Enable EEOF interrupt */ -++#define CIM_CTRL_WIN_EN (1 << 14) -++#define CIM_CTRL_VDDM (1 << 13) /* VDD interrupt enable */ -++#define CIM_CTRL_DMA_SOFM (1 << 12) -++#define CIM_CTRL_DMA_EOFM (1 << 11) -++#define CIM_CTRL_DMA_STOPM (1 << 10) -++#define CIM_CTRL_RXF_TRIGM (1 << 9) -++#define CIM_CTRL_RXF_OFM (1 << 8) -++#define CIM_CTRL_DMA_SYNC (1 << 7) /*when change DA, do frame sync */ -++#define CIM_CTRL_RXF_TRIG_BIT 3 -++#define CIM_CTRL_RXF_TRIG_MASK (0xf << CIM_CTRL_RXF_TRIG_BIT) /* trigger value = (n+1)*burst_type */ -++#define CIM_CTRL_DMA_EN (1 << 2) /* Enable DMA */ -++#define CIM_CTRL_RXF_RST (1 << 1) /* RxFIFO reset */ -++#define CIM_CTRL_ENA (1 << 0) /* Enable CIM */ -++ -++/* CIM State Register (CIM_STATE) */ -++#define CIM_STATE_DMA_EEOF (1 << 7) /* DMA Line EEOf irq */ -++#define CIM_STATE_DMA_SOF (1 << 6) /* DMA start irq */ -++#define CIM_STATE_DMA_EOF (1 << 5) /* DMA end irq */ -++#define CIM_STATE_DMA_STOP (1 << 4) /* DMA stop irq */ -++#define CIM_STATE_RXF_OF (1 << 3) /* RXFIFO over flow irq */ -++#define CIM_STATE_RXF_TRIG (1 << 2) /* RXFIFO triger meet irq */ -++#define CIM_STATE_RXF_EMPTY (1 << 1) /* RXFIFO empty irq */ -++#define CIM_STATE_VDD (1 << 0) /* CIM disabled irq */ -++ -++/* CIM DMA Command Register (CIM_CMD) */ -++ -++#define CIM_CMD_SOFINT (1 << 31) /* enable DMA start irq */ -++#define CIM_CMD_EOFINT (1 << 30) /* enable DMA end irq */ -++#define CIM_CMD_EEOFINT (1 << 29) /* enable DMA EEOF irq */ -++#define CIM_CMD_STOP (1 << 28) /* enable DMA stop irq */ -++#define CIM_CMD_OFRCV (1 << 27) /* enable recovery when TXFiFo overflow */ -++#define CIM_CMD_LEN_BIT 0 -++#define CIM_CMD_LEN_MASK (0xffffff << CIM_CMD_LEN_BIT) -++ -++/* CIM Window-Image Size Register (CIM_SIZE) */ -++#define CIM_SIZE_LPF_BIT 16 /* Lines per freame for csc output image */ -++#define CIM_SIZE_LPF_MASK (0x1fff << CIM_SIZE_LPF_BIT) -++#define CIM_SIZE_PPL_BIT 0 /* Pixels per line for csc output image, should be an even number */ -++#define CIM_SIZE_PPL_MASK (0x1fff << CIM_SIZE_PPL_BIT) -++ -++/* CIM Image Offset Register (CIM_OFFSET) */ -++#define CIM_OFFSET_V_BIT 16 /* Vertical offset */ -++#define CIM_OFFSET_V_MASK (0xfff << CIM_OFFSET_V_BIT) -++#define CIM_OFFSET_H_BIT 0 /* Horizontal offset, should be an enen number */ -++#define CIM_OFFSET_H_MASK (0xfff << CIM_OFFSET_H_BIT) /*OFFSET_H should be even number*/ -++ -++/************************************************************************* -++ * SADC (Smart A/D Controller) -++ *************************************************************************/ -++ -++#define SADC_ENA (SADC_BASE + 0x00) /* ADC Enable Register */ -++#define SADC_CFG (SADC_BASE + 0x04) /* ADC Configure Register */ -++#define SADC_CTRL (SADC_BASE + 0x08) /* ADC Control Register */ -++#define SADC_STATE (SADC_BASE + 0x0C) /* ADC Status Register*/ -++#define SADC_SAMETIME (SADC_BASE + 0x10) /* ADC Same Point Time Register */ -++#define SADC_WAITTIME (SADC_BASE + 0x14) /* ADC Wait Time Register */ -++#define SADC_TSDAT (SADC_BASE + 0x18) /* ADC Touch Screen Data Register */ -++#define SADC_BATDAT (SADC_BASE + 0x1C) /* ADC PBAT Data Register */ -++#define SADC_SADDAT (SADC_BASE + 0x20) /* ADC SADCIN Data Register */ -++#define SADC_ADCLK (SADC_BASE + 0x28) /* ADC Clock Divide Register */ -++ -++#define REG_SADC_ENA REG8(SADC_ENA) -++#define REG_SADC_CFG REG32(SADC_CFG) -++#define REG_SADC_CTRL REG8(SADC_CTRL) -++#define REG_SADC_STATE REG8(SADC_STATE) -++#define REG_SADC_SAMETIME REG16(SADC_SAMETIME) -++#define REG_SADC_WAITTIME REG16(SADC_WAITTIME) -++#define REG_SADC_TSDAT REG32(SADC_TSDAT) -++#define REG_SADC_BATDAT REG16(SADC_BATDAT) -++#define REG_SADC_SADDAT REG16(SADC_SADDAT) -++#define REG_SADC_ADCLK REG32(SADC_ADCLK) -++ -++/* ADC Enable Register */ -++#define SADC_ENA_ADEN (1 << 7) /* Touch Screen Enable */ -++#define SADC_ENA_ENTR_SLP (1 << 6) /* Touch Screen Enable */ -++#define SADC_ENA_EXIT_SLP (1 << 5) /* Touch Screen Enable */ -++#define SADC_ENA_TSEN (1 << 2) /* Touch Screen Enable */ -++#define SADC_ENA_PBATEN (1 << 1) /* PBAT Enable */ -++#define SADC_ENA_SADCINEN (1 << 0) /* SADCIN Enable */ -++ -++/* ADC Configure Register */ -++#define SADC_CFG_EXIN (1 << 30) -++#define SADC_CFG_CLKOUT_NUM_BIT 16 -++#define SADC_CFG_CLKOUT_NUM_MASK (0x7 << SADC_CFG_CLKOUT_NUM_BIT) -++#define SADC_CFG_TS_DMA (1 << 15) /* Touch Screen DMA Enable */ -++#define SADC_CFG_XYZ_BIT 13 /* XYZ selection */ -++#define SADC_CFG_XYZ_MASK (0x3 << SADC_CFG_XYZ_BIT) -++ #define SADC_CFG_XY (0 << SADC_CFG_XYZ_BIT) -++ #define SADC_CFG_XYZ (1 << SADC_CFG_XYZ_BIT) -++ #define SADC_CFG_XYZ1Z2 (2 << SADC_CFG_XYZ_BIT) -++#define SADC_CFG_SNUM_BIT 10 /* Sample Number */ -++#define SADC_CFG_SNUM_MASK (0x7 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_1 (0x0 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_2 (0x1 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_3 (0x2 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_4 (0x3 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_5 (0x4 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_6 (0x5 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_8 (0x6 << SADC_CFG_SNUM_BIT) -++ #define SADC_CFG_SNUM_9 (0x7 << SADC_CFG_SNUM_BIT) -++#define SADC_CFG_CLKDIV_BIT 5 /* AD Converter frequency clock divider */ -++#define SADC_CFG_CLKDIV_MASK (0x1f << SADC_CFG_CLKDIV_BIT) -++#define SADC_CFG_PBAT_HIGH (0 << 4) /* PBAT >= 2.5V */ -++#define SADC_CFG_PBAT_LOW (1 << 4) /* PBAT < 2.5V */ -++#define SADC_CFG_CMD_BIT 0 /* ADC Command */ -++#define SADC_CFG_CMD_MASK (0xf << SADC_CFG_CMD_BIT) -++ #define SADC_CFG_CMD_X_SE (0x0 << SADC_CFG_CMD_BIT) /* X Single-End */ -++ #define SADC_CFG_CMD_Y_SE (0x1 << SADC_CFG_CMD_BIT) /* Y Single-End */ -++ #define SADC_CFG_CMD_X_DIFF (0x2 << SADC_CFG_CMD_BIT) /* X Differential */ -++ #define SADC_CFG_CMD_Y_DIFF (0x3 << SADC_CFG_CMD_BIT) /* Y Differential */ -++ #define SADC_CFG_CMD_Z1_DIFF (0x4 << SADC_CFG_CMD_BIT) /* Z1 Differential */ -++ #define SADC_CFG_CMD_Z2_DIFF (0x5 << SADC_CFG_CMD_BIT) /* Z2 Differential */ -++ #define SADC_CFG_CMD_Z3_DIFF (0x6 << SADC_CFG_CMD_BIT) /* Z3 Differential */ -++ #define SADC_CFG_CMD_Z4_DIFF (0x7 << SADC_CFG_CMD_BIT) /* Z4 Differential */ -++ #define SADC_CFG_CMD_TP_SE (0x8 << SADC_CFG_CMD_BIT) /* Touch Pressure */ -++ #define SADC_CFG_CMD_PBATH_SE (0x9 << SADC_CFG_CMD_BIT) /* PBAT >= 2.5V */ -++ #define SADC_CFG_CMD_PBATL_SE (0xa << SADC_CFG_CMD_BIT) /* PBAT < 2.5V */ -++ #define SADC_CFG_CMD_SADCIN_SE (0xb << SADC_CFG_CMD_BIT) /* Measure SADCIN */ -++ #define SADC_CFG_CMD_INT_PEN (0xc << SADC_CFG_CMD_BIT) /* INT_PEN Enable */ -++ -++/* ADC Control Register */ -++#define SADC_CTRL_SLPENDM (1 << 5) /* sleep Interrupt Mask */ -++#define SADC_CTRL_PENDM (1 << 4) /* Pen Down Interrupt Mask */ -++#define SADC_CTRL_PENUM (1 << 3) /* Pen Up Interrupt Mask */ -++#define SADC_CTRL_TSRDYM (1 << 2) /* Touch Screen Data Ready Interrupt Mask */ -++#define SADC_CTRL_PBATRDYM (1 << 1) /* PBAT Data Ready Interrupt Mask */ -++#define SADC_CTRL_SRDYM (1 << 0) /* SADCIN Data Ready Interrupt Mask */ -++ -++/* ADC Status Register */ -++#define SADC_STATE_SLEEPND (1 << 5) /* Pen Down Interrupt Flag */ -++#define SADC_STATE_PEND (1 << 4) /* Pen Down Interrupt Flag */ -++#define SADC_STATE_PENU (1 << 3) /* Pen Up Interrupt Flag */ -++#define SADC_STATE_TSRDY (1 << 2) /* Touch Screen Data Ready Interrupt Flag */ -++#define SADC_STATE_PBATRDY (1 << 1) /* PBAT Data Ready Interrupt Flag */ -++#define SADC_STATE_SRDY (1 << 0) /* SADCIN Data Ready Interrupt Flag */ -++ -++/* ADC Touch Screen Data Register */ -++#define SADC_TSDAT_DATA0_BIT 0 -++#define SADC_TSDAT_DATA0_MASK (0xfff << SADC_TSDAT_DATA0_BIT) -++#define SADC_TSDAT_TYPE0 (1 << 15) -++#define SADC_TSDAT_DATA1_BIT 16 -++#define SADC_TSDAT_DATA1_MASK (0xfff << SADC_TSDAT_DATA1_BIT) -++#define SADC_TSDAT_TYPE1 (1 << 31) -++ -++/* ADC Clock Divide Register */ -++#define SADC_ADCLK_CLKDIV_10_BIT 16 -++#define SADC_ADCLK_CLKDIV_10_MASK (0x7f << SADC_ADCLK_CLKDIV_10_BIT) -++#define SADC_ADCLK_CLKDIV_BIT 0 -++#define SADC_ADCLK_CLKDIV_MASK (0x3f << SADC_ADCLK_CLKDIV_BIT) -++ -++/************************************************************************* -++ * SLCD (Smart LCD Controller) -++ *************************************************************************/ -++ -++#define SLCD_CFG (SLCD_BASE + 0xA0) /* SLCD Configure Register */ -++#define SLCD_CTRL (SLCD_BASE + 0xA4) /* SLCD Control Register */ -++#define SLCD_STATE (SLCD_BASE + 0xA8) /* SLCD Status Register */ -++#define SLCD_DATA (SLCD_BASE + 0xAC) /* SLCD Data Register */ -++ -++#define REG_SLCD_CFG REG32(SLCD_CFG) -++#define REG_SLCD_CTRL REG8(SLCD_CTRL) -++#define REG_SLCD_STATE REG8(SLCD_STATE) -++#define REG_SLCD_DATA REG32(SLCD_DATA) -++ -++/* SLCD Configure Register */ -++#define SLCD_CFG_DWIDTH_BIT 10 -++#define SLCD_CFG_DWIDTH_MASK (0x7 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_18BIT (0 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_16BIT (1 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_8BIT_x3 (2 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_8BIT_x2 (3 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_8BIT_x1 (4 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_24BIT (5 << SLCD_CFG_DWIDTH_BIT) -++ #define SLCD_CFG_DWIDTH_9BIT_x2 (7 << SLCD_CFG_DWIDTH_BIT) -++#define SLCD_CFG_CWIDTH_BIT (8) -++#define SLCD_CFG_CWIDTH_MASK (0x7 << SLCD_CFG_CWIDTH_BIT) -++#define SLCD_CFG_CWIDTH_16BIT (0 << SLCD_CFG_CWIDTH_BIT) -++#define SLCD_CFG_CWIDTH_8BIT (1 << SLCD_CFG_CWIDTH_BIT) -++#define SLCD_CFG_CWIDTH_18BIT (2 << SLCD_CFG_CWIDTH_BIT) -++#define SLCD_CFG_CWIDTH_24BIT (3 << SLCD_CFG_CWIDTH_BIT) -++#define SLCD_CFG_CS_ACTIVE_LOW (0 << 4) -++#define SLCD_CFG_CS_ACTIVE_HIGH (1 << 4) -++#define SLCD_CFG_RS_CMD_LOW (0 << 3) -++#define SLCD_CFG_RS_CMD_HIGH (1 << 3) -++#define SLCD_CFG_CLK_ACTIVE_FALLING (0 << 1) -++#define SLCD_CFG_CLK_ACTIVE_RISING (1 << 1) -++#define SLCD_CFG_TYPE_PARALLEL (0 << 0) -++#define SLCD_CFG_TYPE_SERIAL (1 << 0) -++ -++/* SLCD Control Register */ -++#define SLCD_CTRL_DMA_EN (1 << 0) -++ -++/* SLCD Status Register */ -++#define SLCD_STATE_BUSY (1 << 0) -++ -++/* SLCD Data Register */ -++#define SLCD_DATA_RS_DATA (0 << 31) -++#define SLCD_DATA_RS_COMMAND (1 << 31) -++ -++/************************************************************************* -++ * LCD (LCD Controller) -++ *************************************************************************/ -++#define LCD_CFG (LCD_BASE + 0x00) /* LCD Configure Register */ -++#define LCD_CTRL (LCD_BASE + 0x30) /* LCD Control Register */ -++#define LCD_STATE (LCD_BASE + 0x34) /* LCD Status Register */ -++ -++#define LCD_OSDC (LCD_BASE + 0x100) /* LCD OSD Configure Register */ -++#define LCD_OSDCTRL (LCD_BASE + 0x104) /* LCD OSD Control Register */ -++#define LCD_OSDS (LCD_BASE + 0x108) /* LCD OSD Status Register */ -++#define LCD_BGC (LCD_BASE + 0x10C) /* LCD Background Color Register */ -++#define LCD_KEY0 (LCD_BASE + 0x110) /* LCD Foreground Color Key Register 0 */ -++#define LCD_KEY1 (LCD_BASE + 0x114) /* LCD Foreground Color Key Register 1 */ -++#define LCD_ALPHA (LCD_BASE + 0x118) /* LCD ALPHA Register */ -++#define LCD_IPUR (LCD_BASE + 0x11C) /* LCD IPU Restart Register */ -++ -++#define LCD_VAT (LCD_BASE + 0x0c) /* Virtual Area Setting Register */ -++#define LCD_DAH (LCD_BASE + 0x10) /* Display Area Horizontal Start/End Point */ -++#define LCD_DAV (LCD_BASE + 0x14) /* Display Area Vertical Start/End Point */ -++ -++#define LCD_XYP0 (LCD_BASE + 0x120) /* Foreground 0 XY Position Register */ -++#define LCD_XYP1 (LCD_BASE + 0x124) /* Foreground 1 XY Position Register */ -++#define LCD_SIZE0 (LCD_BASE + 0x128) /* Foreground 0 Size Register */ -++#define LCD_SIZE1 (LCD_BASE + 0x12C) /* Foreground 1 Size Register */ -++#define LCD_RGBC (LCD_BASE + 0x90) /* RGB Controll Register */ -++ -++#define LCD_VSYNC (LCD_BASE + 0x04) /* Vertical Synchronize Register */ -++#define LCD_HSYNC (LCD_BASE + 0x08) /* Horizontal Synchronize Register */ -++#define LCD_PS (LCD_BASE + 0x18) /* PS Signal Setting */ -++#define LCD_CLS (LCD_BASE + 0x1c) /* CLS Signal Setting */ -++#define LCD_SPL (LCD_BASE + 0x20) /* SPL Signal Setting */ -++#define LCD_REV (LCD_BASE + 0x24) /* REV Signal Setting */ -++#define LCD_IID (LCD_BASE + 0x38) /* Interrupt ID Register */ -++#define LCD_DA0 (LCD_BASE + 0x40) /* Descriptor Address Register 0 */ -++#define LCD_SA0 (LCD_BASE + 0x44) /* Source Address Register 0 */ -++#define LCD_FID0 (LCD_BASE + 0x48) /* Frame ID Register 0 */ -++#define LCD_CMD0 (LCD_BASE + 0x4c) /* DMA Command Register 0 */ -++#define LCD_DA1 (LCD_BASE + 0x50) /* Descriptor Address Register 1 */ -++#define LCD_SA1 (LCD_BASE + 0x54) /* Source Address Register 1 */ -++#define LCD_FID1 (LCD_BASE + 0x58) /* Frame ID Register 1 */ -++#define LCD_CMD1 (LCD_BASE + 0x5c) /* DMA Command Register 1 */ -++ -++#define LCD_OFFS0 (LCD_BASE + 0x60) /* DMA Offsize Register 0 */ -++#define LCD_PW0 (LCD_BASE + 0x64) /* DMA Page Width Register 0 */ -++#define LCD_CNUM0 (LCD_BASE + 0x68) /* DMA Command Counter Register 0 */ -++#define LCD_DESSIZE0 (LCD_BASE + 0x6C) /* Foreground Size in Descriptor 0 Register*/ -++#define LCD_OFFS1 (LCD_BASE + 0x70) /* DMA Offsize Register 1 */ -++#define LCD_PW1 (LCD_BASE + 0x74) /* DMA Page Width Register 1 */ -++#define LCD_CNUM1 (LCD_BASE + 0x78) /* DMA Command Counter Register 1 */ -++#define LCD_DESSIZE1 (LCD_BASE + 0x7C) /* Foreground Size in Descriptor 1 Register*/ -++ -++#define REG_LCD_CFG REG32(LCD_CFG) -++#define REG_LCD_CTRL REG32(LCD_CTRL) -++#define REG_LCD_STATE REG32(LCD_STATE) -++ -++#define REG_LCD_OSDC REG16(LCD_OSDC) -++#define REG_LCD_OSDCTRL REG16(LCD_OSDCTRL) -++#define REG_LCD_OSDS REG16(LCD_OSDS) -++#define REG_LCD_BGC REG32(LCD_BGC) -++#define REG_LCD_KEY0 REG32(LCD_KEY0) -++#define REG_LCD_KEY1 REG32(LCD_KEY1) -++#define REG_LCD_ALPHA REG8(LCD_ALPHA) -++#define REG_LCD_IPUR REG32(LCD_IPUR) -++ -++#define REG_LCD_VAT REG32(LCD_VAT) -++#define REG_LCD_DAH REG32(LCD_DAH) -++#define REG_LCD_DAV REG32(LCD_DAV) -++ -++#define REG_LCD_XYP0 REG32(LCD_XYP0) -++#define REG_LCD_XYP1 REG32(LCD_XYP1) -++#define REG_LCD_SIZE0 REG32(LCD_SIZE0) -++#define REG_LCD_SIZE1 REG32(LCD_SIZE1) -++#define REG_LCD_RGBC REG16(LCD_RGBC) -++ -++#define REG_LCD_VSYNC REG32(LCD_VSYNC) -++#define REG_LCD_HSYNC REG32(LCD_HSYNC) -++#define REG_LCD_PS REG32(LCD_PS) -++#define REG_LCD_CLS REG32(LCD_CLS) -++#define REG_LCD_SPL REG32(LCD_SPL) -++#define REG_LCD_REV REG32(LCD_REV) -++#define REG_LCD_IID REG32(LCD_IID) -++#define REG_LCD_DA0 REG32(LCD_DA0) -++#define REG_LCD_SA0 REG32(LCD_SA0) -++#define REG_LCD_FID0 REG32(LCD_FID0) -++#define REG_LCD_CMD0 REG32(LCD_CMD0) -++#define REG_LCD_DA1 REG32(LCD_DA1) -++#define REG_LCD_SA1 REG32(LCD_SA1) -++#define REG_LCD_FID1 REG32(LCD_FID1) -++#define REG_LCD_CMD1 REG32(LCD_CMD1) -++ -++#define REG_LCD_OFFS0 REG32(LCD_OFFS0) -++#define REG_LCD_PW0 REG32(LCD_PW0) -++#define REG_LCD_CNUM0 REG32(LCD_CNUM0) -++#define REG_LCD_DESSIZE0 REG32(LCD_DESSIZE0) -++#define REG_LCD_OFFS1 REG32(LCD_OFFS1) -++#define REG_LCD_PW1 REG32(LCD_PW1) -++#define REG_LCD_CNUM1 REG32(LCD_CNUM1) -++#define REG_LCD_DESSIZE1 REG32(LCD_DESSIZE1) -++ -++/* LCD Configure Register */ -++#define LCD_CFG_LCDPIN_BIT 31 /* LCD pins selection */ -++#define LCD_CFG_LCDPIN_MASK (0x1 << LCD_CFG_LCDPIN_BIT) -++ #define LCD_CFG_LCDPIN_LCD (0x0 << LCD_CFG_LCDPIN_BIT) -++ #define LCD_CFG_LCDPIN_SLCD (0x1 << LCD_CFG_LCDPIN_BIT) -++#define LCD_CFG_TVEPEH (1 << 30) /* TVE PAL enable extra halfline signal */ -++#define LCD_CFG_FUHOLD (1 << 29) /* hold pixel clock when outFIFO underrun */ -++#define LCD_CFG_NEWDES (1 << 28) /* use new descripter. old: 4words, new:8words */ -++#define LCD_CFG_PALBP (1 << 27) /* bypass data format and alpha blending */ -++#define LCD_CFG_TVEN (1 << 26) /* indicate the terminal is lcd or tv */ -++#define LCD_CFG_RECOVER (1 << 25) /* Auto recover when output fifo underrun */ -++#define LCD_CFG_DITHER (1 << 24) /* Dither function */ -++#define LCD_CFG_PSM (1 << 23) /* PS signal mode */ -++#define LCD_CFG_CLSM (1 << 22) /* CLS signal mode */ -++#define LCD_CFG_SPLM (1 << 21) /* SPL signal mode */ -++#define LCD_CFG_REVM (1 << 20) /* REV signal mode */ -++#define LCD_CFG_HSYNM (1 << 19) /* HSYNC signal mode */ -++#define LCD_CFG_PCLKM (1 << 18) /* PCLK signal mode */ -++#define LCD_CFG_INVDAT (1 << 17) /* Inverse output data */ -++#define LCD_CFG_SYNDIR_IN (1 << 16) /* VSYNC&HSYNC direction */ -++#define LCD_CFG_PSP (1 << 15) /* PS pin reset state */ -++#define LCD_CFG_CLSP (1 << 14) /* CLS pin reset state */ -++#define LCD_CFG_SPLP (1 << 13) /* SPL pin reset state */ -++#define LCD_CFG_REVP (1 << 12) /* REV pin reset state */ -++#define LCD_CFG_HSP (1 << 11) /* HSYNC polarity:0-active high,1-active low */ -++#define LCD_CFG_PCP (1 << 10) /* PCLK polarity:0-rising,1-falling */ -++#define LCD_CFG_DEP (1 << 9) /* DE polarity:0-active high,1-active low */ -++#define LCD_CFG_VSP (1 << 8) /* VSYNC polarity:0-rising,1-falling */ -++#define LCD_CFG_MODE_TFT_18BIT (1 << 7) /* 18bit TFT */ -++#define LCD_CFG_MODE_TFT_16BIT (0 << 7) /* 16bit TFT */ -++#define LCD_CFG_MODE_TFT_24BIT (1 << 6) /* 24bit TFT */ -++#define LCD_CFG_PDW_BIT 4 /* STN pins utilization */ -++#define LCD_CFG_PDW_MASK (0x3 << LCD_DEV_PDW_BIT) -++#define LCD_CFG_PDW_1 (0 << LCD_CFG_PDW_BIT) /* LCD_D[0] */ -++ #define LCD_CFG_PDW_2 (1 << LCD_CFG_PDW_BIT) /* LCD_D[0:1] */ -++ #define LCD_CFG_PDW_4 (2 << LCD_CFG_PDW_BIT) /* LCD_D[0:3]/LCD_D[8:11] */ -++ #define LCD_CFG_PDW_8 (3 << LCD_CFG_PDW_BIT) /* LCD_D[0:7]/LCD_D[8:15] */ -++#define LCD_CFG_MODE_BIT 0 /* Display Device Mode Select */ -++#define LCD_CFG_MODE_MASK (0x0f << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_GENERIC_TFT (0 << LCD_CFG_MODE_BIT) /* 16,18 bit TFT */ -++ #define LCD_CFG_MODE_SPECIAL_TFT_1 (1 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SPECIAL_TFT_2 (2 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SPECIAL_TFT_3 (3 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_NONINTER_CCIR656 (4 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_INTER_CCIR656 (6 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SINGLE_CSTN (8 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SINGLE_MSTN (9 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_DUAL_CSTN (10 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_DUAL_MSTN (11 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SERIAL_TFT (12 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_LCM (13 << LCD_CFG_MODE_BIT) -++ #define LCD_CFG_MODE_SLCD LCD_CFG_MODE_LCM -++ -++/* LCD Control Register */ -++#define LCD_CTRL_BST_BIT 28 /* Burst Length Selection */ -++#define LCD_CTRL_BST_MASK (0x03 << LCD_CTRL_BST_BIT) -++ #define LCD_CTRL_BST_4 (0 << LCD_CTRL_BST_BIT) /* 4-word */ -++ #define LCD_CTRL_BST_8 (1 << LCD_CTRL_BST_BIT) /* 8-word */ -++ #define LCD_CTRL_BST_16 (2 << LCD_CTRL_BST_BIT) /* 16-word */ -++ #define LCD_CTRL_BST_32 (3 << LCD_CTRL_BST_BIT) /* 32-word */ -++#define LCD_CTRL_RGB565 (0 << 27) /* RGB565 mode(foreground 0 in OSD mode) */ -++#define LCD_CTRL_RGB555 (1 << 27) /* RGB555 mode(foreground 0 in OSD mode) */ -++#define LCD_CTRL_OFUP (1 << 26) /* Output FIFO underrun protection enable */ -++#define LCD_CTRL_FRC_BIT 24 /* STN FRC Algorithm Selection */ -++#define LCD_CTRL_FRC_MASK (0x03 << LCD_CTRL_FRC_BIT) -++ #define LCD_CTRL_FRC_16 (0 << LCD_CTRL_FRC_BIT) /* 16 grayscale */ -++ #define LCD_CTRL_FRC_4 (1 << LCD_CTRL_FRC_BIT) /* 4 grayscale */ -++ #define LCD_CTRL_FRC_2 (2 << LCD_CTRL_FRC_BIT) /* 2 grayscale */ -++#define LCD_CTRL_PDD_BIT 16 /* Load Palette Delay Counter */ -++#define LCD_CTRL_PDD_MASK (0xff << LCD_CTRL_PDD_BIT) -++#define LCD_CTRL_EOFM (1 << 13) /* EOF interrupt mask */ -++#define LCD_CTRL_SOFM (1 << 12) /* SOF interrupt mask */ -++#define LCD_CTRL_OFUM (1 << 11) /* Output FIFO underrun interrupt mask */ -++#define LCD_CTRL_IFUM0 (1 << 10) /* Input FIFO 0 underrun interrupt mask */ -++#define LCD_CTRL_IFUM1 (1 << 9) /* Input FIFO 1 underrun interrupt mask */ -++#define LCD_CTRL_LDDM (1 << 8) /* LCD disable done interrupt mask */ -++#define LCD_CTRL_QDM (1 << 7) /* LCD quick disable done interrupt mask */ -++#define LCD_CTRL_BEDN (1 << 6) /* Endian selection */ -++#define LCD_CTRL_PEDN (1 << 5) /* Endian in byte:0-msb first, 1-lsb first */ -++#define LCD_CTRL_DIS (1 << 4) /* Disable indicate bit */ -++#define LCD_CTRL_ENA (1 << 3) /* LCD enable bit */ -++#define LCD_CTRL_BPP_BIT 0 /* Bits Per Pixel */ -++#define LCD_CTRL_BPP_MASK (0x07 << LCD_CTRL_BPP_BIT) -++ #define LCD_CTRL_BPP_1 (0 << LCD_CTRL_BPP_BIT) /* 1 bpp */ -++ #define LCD_CTRL_BPP_2 (1 << LCD_CTRL_BPP_BIT) /* 2 bpp */ -++ #define LCD_CTRL_BPP_4 (2 << LCD_CTRL_BPP_BIT) /* 4 bpp */ -++ #define LCD_CTRL_BPP_8 (3 << LCD_CTRL_BPP_BIT) /* 8 bpp */ -++ #define LCD_CTRL_BPP_16 (4 << LCD_CTRL_BPP_BIT) /* 15/16 bpp */ -++ #define LCD_CTRL_BPP_18_24 (5 << LCD_CTRL_BPP_BIT) /* 18/24/32 bpp */ -++ #define LCD_CTRL_BPP_CMPS_24 (6 << LCD_CTRL_BPP_BIT) /* 24 compress bpp */ -++ -++/* LCD Status Register */ -++#define LCD_STATE_QD (1 << 7) /* Quick Disable Done */ -++#define LCD_STATE_EOF (1 << 5) /* EOF Flag */ -++#define LCD_STATE_SOF (1 << 4) /* SOF Flag */ -++#define LCD_STATE_OFU (1 << 3) /* Output FIFO Underrun */ -++#define LCD_STATE_IFU0 (1 << 2) /* Input FIFO 0 Underrun */ -++#define LCD_STATE_IFU1 (1 << 1) /* Input FIFO 1 Underrun */ -++#define LCD_STATE_LDD (1 << 0) /* LCD Disabled */ -++ -++/* OSD Configure Register */ -++#define LCD_OSDC_SOFM1 (1 << 15) /* Start of frame interrupt mask for foreground 1 */ -++#define LCD_OSDC_EOFM1 (1 << 14) /* End of frame interrupt mask for foreground 1 */ -++#define LCD_OSDC_REM1 (1 << 13) /* Real end of frame mask for foreground 1 */ -++#define LCD_OSDC_SOFM0 (1 << 11) /* Start of frame interrupt mask for foreground 0 */ -++#define LCD_OSDC_EOFM0 (1 << 10) /* End of frame interrupt mask for foreground 0 */ -++#define LCD_OSDC_REM0 (1 << 9) /* Real end of frame mask for foreground 0 */ -++#define LCD_OSDC_REMB (1 << 7) /* Real end of frame mask for background */ -++#define LCD_OSDC_F1EN (1 << 4) /* enable foreground 1 */ -++#define LCD_OSDC_F0EN (1 << 3) /* enable foreground 0 */ -++#define LCD_OSDC_ALPHAEN (1 << 2) /* enable alpha blending */ -++#define LCD_OSDC_ALPHAMD (1 << 1) /* alpha blending mode */ -++#define LCD_OSDC_OSDEN (1 << 0) /* OSD mode enable */ -++ -++/* OSD Controll Register */ -++#define LCD_OSDCTRL_IPU (1 << 15) /* input data from IPU */ -++#define LCD_OSDCTRL_RGB565 (0 << 4) /* foreground 1, 16bpp, 0-RGB565, 1-RGB555 */ -++#define LCD_OSDCTRL_RGB555 (1 << 4) /* foreground 1, 16bpp, 0-RGB565, 1-RGB555 */ -++#define LCD_OSDCTRL_CHANGES (1 << 3) /* Change size flag */ -++#define LCD_OSDCTRL_OSDBPP_BIT 0 /* Bits Per Pixel of OSD Channel 1 */ -++#define LCD_OSDCTRL_OSDBPP_MASK (0x7< -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef __ASM_BOARD_SERIAL_H__ -++#define __ASM_BOARD_SERIAL_H__ -++ -++#ifndef CONFIG_SERIAL_MANY_PORTS -++#undef RS_TABLE_SIZE -++#define RS_TABLE_SIZE 1 -++#endif -++ -++#define JZ_BASE_BAUD (12000000/16) -++ -++#define JZ_SERIAL_PORT_DEFNS \ -++ { .baud_base = JZ_BASE_BAUD, .irq = IRQ_UART0, \ -++ .flags = STD_COM_FLAGS, .iomem_base = (u8 *)UART0_BASE, \ -++ .iomem_reg_shift = 2, .io_type = SERIAL_IO_MEM }, -++ -++#endif /* __ASM_BORAD_SERIAL_H__ */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/mach-jz4750d/war.h linux-2.6.24.7/include/asm-mips/mach-jz4750d/war.h -+--- linux-2.6.24.7.old/include/asm-mips/mach-jz4750d/war.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/mach-jz4750d/war.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,25 @@ -++/* -++ * This file is subject to the terms and conditions of the GNU General Public -++ * License. See the file "COPYING" in the main directory of this archive -++ * for more details. -++ * -++ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle -++ */ -++#ifndef __ASM_MIPS_MACH_JZ4740_WAR_H -++#define __ASM_MIPS_MACH_JZ4740_WAR_H -++ -++#define R4600_V1_INDEX_ICACHEOP_WAR 0 -++#define R4600_V1_HIT_CACHEOP_WAR 0 -++#define R4600_V2_HIT_CACHEOP_WAR 0 -++#define R5432_CP0_INTERRUPT_WAR 0 -++#define BCM1250_M3_WAR 0 -++#define SIBYTE_1956_WAR 0 -++#define MIPS4K_ICACHE_REFILL_WAR 0 -++#define MIPS_CACHE_SYNC_WAR 0 -++#define TX49XX_ICACHE_INDEX_INV_WAR 0 -++#define RM9000_CDEX_SMP_WAR 0 -++#define ICACHE_REFILLS_WORKAROUND_WAR 0 -++#define R10000_LLSC_WAR 0 -++#define MIPS34K_MISSED_ITLB_WAR 0 -++ -++#endif /* __ASM_MIPS_MACH_JZ4740_WAR_H */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/ptrace.h linux-2.6.24.7/include/asm-mips/ptrace.h -+--- linux-2.6.24.7.old/include/asm-mips/ptrace.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/include/asm-mips/ptrace.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -79,7 +79,7 @@ -+ /* -+ * Does the process account for user or for system time? -+ */ -+-#define user_mode(regs) (((regs)->cp0_status & KU_MASK) == KU_USER) -++#define user_mode(regs) ((((regs)->cp0_status & KU_MASK) == KU_USER) || (((regs)->cp0_status & 0x08000000) == 0x08000000)) -+ -+ #define instruction_pointer(regs) ((regs)->cp0_epc) -+ #define profile_pc(regs) instruction_pointer(regs) -+diff -urN linux-2.6.24.7.old/include/asm-mips/r4kcache.h linux-2.6.24.7/include/asm-mips/r4kcache.h -+--- linux-2.6.24.7.old/include/asm-mips/r4kcache.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/include/asm-mips/r4kcache.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -17,6 +17,58 @@ -+ #include -+ #include -+ -++#ifdef CONFIG_JZRISC -++ -++#define K0_TO_K1() \ -++do { \ -++ unsigned long __k0_addr; \ -++ \ -++ __asm__ __volatile__( \ -++ "la %0, 1f\n\t" \ -++ "or %0, %0, %1\n\t" \ -++ "jr %0\n\t" \ -++ "nop\n\t" \ -++ "1: nop\n" \ -++ : "=&r"(__k0_addr) \ -++ : "r" (0x20000000) ); \ -++} while(0) -++ -++#define K1_TO_K0() \ -++do { \ -++ unsigned long __k0_addr; \ -++ __asm__ __volatile__( \ -++ "nop;nop;nop;nop;nop;nop;nop\n\t" \ -++ "la %0, 1f\n\t" \ -++ "jr %0\n\t" \ -++ "nop\n\t" \ -++ "1: nop\n" \ -++ : "=&r" (__k0_addr)); \ -++} while (0) -++ -++#define INVALIDATE_BTB() \ -++do { \ -++ unsigned long tmp; \ -++ __asm__ __volatile__( \ -++ ".set mips32\n\t" \ -++ "mfc0 %0, $16, 7\n\t" \ -++ "nop\n\t" \ -++ "ori %0, 2\n\t" \ -++ "mtc0 %0, $16, 7\n\t" \ -++ "nop\n\t" \ -++ : "=&r" (tmp)); \ -++} while (0) -++ -++#define SYNC_WB() __asm__ __volatile__ ("sync") -++ -++#else /* CONFIG_JZRISC */ -++ -++#define K0_TO_K1() do { } while (0) -++#define K1_TO_K0() do { } while (0) -++#define INVALIDATE_BTB() do { } while (0) -++#define SYNC_WB() do { } while (0) -++ -++#endif /* CONFIG_JZRISC */ -++ -+ /* -+ * This macro return a properly sign-extended address suitable as base address -+ * for indexed cache operations. Two issues here: -+@@ -144,6 +196,7 @@ -+ { -+ __iflush_prologue -+ cache_op(Index_Invalidate_I, addr); -++ INVALIDATE_BTB(); -+ __iflush_epilogue -+ } -+ -+@@ -151,6 +204,7 @@ -+ { -+ __dflush_prologue -+ cache_op(Index_Writeback_Inv_D, addr); -++ SYNC_WB(); -+ __dflush_epilogue -+ } -+ -+@@ -163,6 +217,7 @@ -+ { -+ __iflush_prologue -+ cache_op(Hit_Invalidate_I, addr); -++ INVALIDATE_BTB(); -+ __iflush_epilogue -+ } -+ -+@@ -170,6 +225,7 @@ -+ { -+ __dflush_prologue -+ cache_op(Hit_Writeback_Inv_D, addr); -++ SYNC_WB(); -+ __dflush_epilogue -+ } -+ -+@@ -177,6 +233,7 @@ -+ { -+ __dflush_prologue -+ cache_op(Hit_Invalidate_D, addr); -++ SYNC_WB(); -+ __dflush_epilogue -+ } -+ -+@@ -209,6 +266,7 @@ -+ static inline void protected_flush_icache_line(unsigned long addr) -+ { -+ protected_cache_op(Hit_Invalidate_I, addr); -++ INVALIDATE_BTB(); -+ } -+ -+ /* -+@@ -220,6 +278,7 @@ -+ static inline void protected_writeback_dcache_line(unsigned long addr) -+ { -+ protected_cache_op(Hit_Writeback_Inv_D, addr); -++ SYNC_WB(); -+ } -+ -+ static inline void protected_writeback_scache_line(unsigned long addr) -+@@ -396,13 +455,123 @@ -+ __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16) -+ __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16) -+ __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16) -++#ifndef CONFIG_JZRISC -+ __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32) -+ __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32) -++#endif -+ __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32) -+ __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64) -+ __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64) -+ __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128) -+ -++#ifdef CONFIG_JZRISC -++ -++static inline void blast_dcache32(void) -++{ -++ unsigned long start = INDEX_BASE; -++ unsigned long end = start + current_cpu_data.dcache.waysize; -++ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit; -++ unsigned long ws_end = current_cpu_data.dcache.ways << -++ current_cpu_data.dcache.waybit; -++ unsigned long ws, addr; -++ -++ for (ws = 0; ws < ws_end; ws += ws_inc) -++ for (addr = start; addr < end; addr += 0x400) -++ cache32_unroll32(addr|ws,Index_Writeback_Inv_D); -++ -++ SYNC_WB(); -++} -++ -++static inline void blast_dcache32_page(unsigned long page) -++{ -++ unsigned long start = page; -++ unsigned long end = page + PAGE_SIZE; -++ -++ do { -++ cache32_unroll32(start,Hit_Writeback_Inv_D); -++ start += 0x400; -++ } while (start < end); -++ -++ SYNC_WB(); -++} -++ -++static inline void blast_dcache32_page_indexed(unsigned long page) -++{ -++ unsigned long indexmask = current_cpu_data.dcache.waysize - 1; -++ unsigned long start = INDEX_BASE + (page & indexmask); -++ unsigned long end = start + PAGE_SIZE; -++ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit; -++ unsigned long ws_end = current_cpu_data.dcache.ways << -++ current_cpu_data.dcache.waybit; -++ unsigned long ws, addr; -++ -++ for (ws = 0; ws < ws_end; ws += ws_inc) -++ for (addr = start; addr < end; addr += 0x400) -++ cache32_unroll32(addr|ws,Index_Writeback_Inv_D); -++ -++ SYNC_WB(); -++} -++ -++static inline void blast_icache32(void) -++{ -++ unsigned long start = INDEX_BASE; -++ unsigned long end = start + current_cpu_data.icache.waysize; -++ unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit; -++ unsigned long ws_end = current_cpu_data.icache.ways << -++ current_cpu_data.icache.waybit; -++ unsigned long ws, addr; -++ -++ K0_TO_K1(); -++ -++ for (ws = 0; ws < ws_end; ws += ws_inc) -++ for (addr = start; addr < end; addr += 0x400) -++ cache32_unroll32(addr|ws,Index_Invalidate_I); -++ -++ INVALIDATE_BTB(); -++ -++ K1_TO_K0(); -++} -++ -++static inline void blast_icache32_page(unsigned long page) -++{ -++ unsigned long start = page; -++ unsigned long end = page + PAGE_SIZE; -++ -++ K0_TO_K1(); -++ -++ do { -++ cache32_unroll32(start,Hit_Invalidate_I); -++ start += 0x400; -++ } while (start < end); -++ -++ INVALIDATE_BTB(); -++ -++ K1_TO_K0(); -++} -++ -++static inline void blast_icache32_page_indexed(unsigned long page) -++{ -++ unsigned long indexmask = current_cpu_data.icache.waysize - 1; -++ unsigned long start = INDEX_BASE + (page & indexmask); -++ unsigned long end = start + PAGE_SIZE; -++ unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit; -++ unsigned long ws_end = current_cpu_data.icache.ways << -++ current_cpu_data.icache.waybit; -++ unsigned long ws, addr; -++ -++ K0_TO_K1(); -++ -++ for (ws = 0; ws < ws_end; ws += ws_inc) -++ for (addr = start; addr < end; addr += 0x400) -++ cache32_unroll32(addr|ws,Index_Invalidate_I); -++ -++ INVALIDATE_BTB(); -++ -++ K1_TO_K0(); -++} -++ -++#endif /* CONFIG_JZRISC */ -++ -+ /* build blast_xxx_range, protected_blast_xxx_range */ -+ #define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \ -+ static inline void prot##blast_##pfx##cache##_range(unsigned long start, \ -+@@ -424,13 +593,73 @@ -+ __##pfx##flush_epilogue \ -+ } -+ -++#ifndef CONFIG_JZRISC -+ __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_) -++#endif -+ __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_) -++#ifndef CONFIG_JZRISC -+ __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_) -+ __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, ) -++#endif -+ __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, ) -+ /* blast_inv_dcache_range */ -+ __BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, ) -+ __BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, ) -+ -++#ifdef CONFIG_JZRISC -++ -++static inline void protected_blast_dcache_range(unsigned long start, -++ unsigned long end) -++{ -++ unsigned long lsize = cpu_dcache_line_size(); -++ unsigned long addr = start & ~(lsize - 1); -++ unsigned long aend = (end - 1) & ~(lsize - 1); -++ -++ while (1) { -++ protected_cache_op(Hit_Writeback_Inv_D, addr); -++ if (addr == aend) -++ break; -++ addr += lsize; -++ } -++ SYNC_WB(); -++} -++ -++static inline void protected_blast_icache_range(unsigned long start, -++ unsigned long end) -++{ -++ unsigned long lsize = cpu_icache_line_size(); -++ unsigned long addr = start & ~(lsize - 1); -++ unsigned long aend = (end - 1) & ~(lsize - 1); -++ -++ K0_TO_K1(); -++ -++ while (1) { -++ protected_cache_op(Hit_Invalidate_I, addr); -++ if (addr == aend) -++ break; -++ addr += lsize; -++ } -++ INVALIDATE_BTB(); -++ -++ K1_TO_K0(); -++} -++ -++static inline void blast_dcache_range(unsigned long start, -++ unsigned long end) -++{ -++ unsigned long lsize = cpu_dcache_line_size(); -++ unsigned long addr = start & ~(lsize - 1); -++ unsigned long aend = (end - 1) & ~(lsize - 1); -++ -++ while (1) { -++ cache_op(Hit_Writeback_Inv_D, addr); -++ if (addr == aend) -++ break; -++ addr += lsize; -++ } -++ SYNC_WB(); -++} -++ -++#endif /* CONFIG_JZRISC */ -++ -+ #endif /* _ASM_R4KCACHE_H */ -+diff -urN linux-2.6.24.7.old/include/asm-mips/sizes.h linux-2.6.24.7/include/asm-mips/sizes.h -+--- linux-2.6.24.7.old/include/asm-mips/sizes.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/asm-mips/sizes.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,56 @@ -++/* -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ * GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ */ -++/* DO NOT EDIT!! - this file automatically generated -++ * from .s file by awk -f s2h.awk -++ */ -++/* Size definitions -++ * Copyright (C) ARM Limited 1998. All rights reserved. -++ */ -++ -++#ifndef __sizes_h -++#define __sizes_h 1 -++ -++/* handy sizes */ -++#define SZ_16 0x00000010 -++#define SZ_256 0x00000100 -++#define SZ_512 0x00000200 -++ -++#define SZ_1K 0x00000400 -++#define SZ_4K 0x00001000 -++#define SZ_8K 0x00002000 -++#define SZ_16K 0x00004000 -++#define SZ_64K 0x00010000 -++#define SZ_128K 0x00020000 -++#define SZ_256K 0x00040000 -++#define SZ_512K 0x00080000 -++ -++#define SZ_1M 0x00100000 -++#define SZ_2M 0x00200000 -++#define SZ_4M 0x00400000 -++#define SZ_8M 0x00800000 -++#define SZ_16M 0x01000000 -++#define SZ_32M 0x02000000 -++#define SZ_64M 0x04000000 -++#define SZ_128M 0x08000000 -++#define SZ_256M 0x10000000 -++#define SZ_512M 0x20000000 -++ -++#define SZ_1G 0x40000000 -++#define SZ_2G 0x80000000 -++ -++#endif -++ -++/* END */ -+diff -urN linux-2.6.24.7.old/include/linux/fs.h linux-2.6.24.7/include/linux/fs.h -+--- linux-2.6.24.7.old/include/linux/fs.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/include/linux/fs.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -1670,6 +1670,8 @@ -+ extern int invalidate_inode_pages2(struct address_space *mapping); -+ extern int invalidate_inode_pages2_range(struct address_space *mapping, -+ pgoff_t start, pgoff_t end); -++extern void generic_sync_sb_inodes(struct super_block *sb, -++ struct writeback_control *wbc); -+ extern int write_inode_now(struct inode *, int); -+ extern int filemap_fdatawrite(struct address_space *); -+ extern int filemap_flush(struct address_space *); -+diff -urN linux-2.6.24.7.old/include/linux/i2c-dev.h linux-2.6.24.7/include/linux/i2c-dev.h -+--- linux-2.6.24.7.old/include/linux/i2c-dev.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/include/linux/i2c-dev.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -49,7 +49,8 @@ -+ -+ #define I2C_PEC 0x0708 /* != 0 to use PEC with SMBus */ -+ #define I2C_SMBUS 0x0720 /* SMBus transfer */ -+- -++#define I2C_SET_SUB_ADDRESS 0x0730 /* SMBus transfer */ -++#define I2C_SET_CLOCK 0x0731 /* SMBus transfer */ -+ -+ /* This is the structure as used in the I2C_SMBUS ioctl call */ -+ struct i2c_smbus_ioctl_data { -+@@ -71,4 +72,5 @@ -+ #define I2C_MAJOR 89 /* Device major number */ -+ #endif -+ -++extern void i2c_jz_setclk(unsigned int i2cclk); -+ #endif /* _LINUX_I2C_DEV_H */ -+diff -urN linux-2.6.24.7.old/include/linux/mmc/host.h linux-2.6.24.7/include/linux/mmc/host.h -+--- linux-2.6.24.7.old/include/linux/mmc/host.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/include/linux/mmc/host.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -41,6 +41,7 @@ -+ -+ #define MMC_BUS_WIDTH_1 0 -+ #define MMC_BUS_WIDTH_4 2 -++#define MMC_BUS_WIDTH_8 4 -+ -+ unsigned char timing; /* timing specification used */ -+ -+diff -urN linux-2.6.24.7.old/include/linux/mtd/mtd.h linux-2.6.24.7/include/linux/mtd/mtd.h -+--- linux-2.6.24.7.old/include/linux/mtd/mtd.h 2009-04-12 18:05:07.000000000 +0200 -++++ linux-2.6.24.7/include/linux/mtd/mtd.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -32,9 +32,9 @@ -+ specific to any particular block. */ -+ struct erase_info { -+ struct mtd_info *mtd; -+- u_int32_t addr; -+- u_int32_t len; -+- u_int32_t fail_addr; -++ u_int64_t addr; -++ u_int64_t len; -++ u_int64_t fail_addr; -+ u_long time; -+ u_long retries; -+ u_int dev; -+@@ -46,7 +46,7 @@ -+ }; -+ -+ struct mtd_erase_region_info { -+- u_int32_t offset; /* At which this region starts, from the beginning of the MTD */ -++ u_int64_t offset; /* At which this region starts, from the beginning of the MTD */ -+ u_int32_t erasesize; /* For this region */ -+ u_int32_t numblocks; /* Number of blocks of erasesize in this region */ -+ unsigned long *lockmap; /* If keeping bitmap of locks */ -+@@ -89,10 +89,10 @@ -+ */ -+ struct mtd_oob_ops { -+ mtd_oob_mode_t mode; -+- size_t len; -+- size_t retlen; -+- size_t ooblen; -+- size_t oobretlen; -++ size_mtd_t len; -++ size_mtd_t retlen; -++ size_mtd_t ooblen; -++ size_mtd_t oobretlen; -+ uint32_t ooboffs; -+ uint8_t *datbuf; -+ uint8_t *oobbuf; -+@@ -102,7 +102,7 @@ -+ struct mtd_info { -+ u_char type; -+ u_int32_t flags; -+- u_int32_t size; // Total size of the MTD -++ u_int64_t size; // Total size of the MTD -+ -+ /* "Major" erase size for the device. Naïve users may take this -+ * to be the only erase size available, or may use the more detailed -+@@ -144,18 +144,18 @@ -+ int (*erase) (struct mtd_info *mtd, struct erase_info *instr); -+ -+ /* This stuff for eXecute-In-Place */ -+- int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf); -++ int (*point) (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, size_mtd_t *retlen, u_char **mtdbuf); -+ -+ /* We probably shouldn't allow XIP if the unpoint isn't a NULL */ -+- void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len); -++ void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_mtd_t from, size_mtd_t len); -+ -+ -+- int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -+- int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); -++ int (*read) (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, size_mtd_t *retlen, u_char *buf); -++ int (*write) (struct mtd_info *mtd, loff_mtd_t to, size_mtd_t len, size_mtd_t *retlen, const u_char *buf); -+ -+- int (*read_oob) (struct mtd_info *mtd, loff_t from, -++ int (*read_oob) (struct mtd_info *mtd, loff_mtd_t from, -+ struct mtd_oob_ops *ops); -+- int (*write_oob) (struct mtd_info *mtd, loff_t to, -++ int (*write_oob) (struct mtd_info *mtd, loff_mtd_t to, -+ struct mtd_oob_ops *ops); -+ -+ /* -+@@ -163,33 +163,33 @@ -+ * flash devices. The user data is one time programmable but the -+ * factory data is read only. -+ */ -+- int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); -+- int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -+- int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); -+- int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -+- int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -+- int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len); -++ int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_mtd_t len); -++ int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, size_mtd_t *retlen, u_char *buf); -++ int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_mtd_t len); -++ int (*read_user_prot_reg) (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, size_mtd_t *retlen, u_char *buf); -++ int (*write_user_prot_reg) (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, size_mtd_t *retlen, u_char *buf); -++ int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len); -+ -+ /* kvec-based read/write methods. -+ NB: The 'count' parameter is the number of _vectors_, each of -+ which contains an (ofs, len) tuple. -+ */ -+- int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); -++ int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_mtd_t to, size_mtd_t *retlen); -+ -+ /* Sync */ -+ void (*sync) (struct mtd_info *mtd); -+ -+ /* Chip-supported device locking */ -+- int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len); -+- int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len); -++ int (*lock) (struct mtd_info *mtd, loff_mtd_t ofs, size_mtd_t len); -++ int (*unlock) (struct mtd_info *mtd, loff_mtd_t ofs, size_mtd_t len); -+ -+ /* Power Management functions */ -+ int (*suspend) (struct mtd_info *mtd); -+ void (*resume) (struct mtd_info *mtd); -+ -+ /* Bad block management functions */ -+- int (*block_isbad) (struct mtd_info *mtd, loff_t ofs); -+- int (*block_markbad) (struct mtd_info *mtd, loff_t ofs); -++ int (*block_isbad) (struct mtd_info *mtd, loff_mtd_t ofs); -++ int (*block_markbad) (struct mtd_info *mtd, loff_mtd_t ofs); -+ -+ struct notifier_block reboot_notifier; /* default mode before reboot */ -+ -+@@ -237,10 +237,10 @@ -+ extern int unregister_mtd_user (struct mtd_notifier *old); -+ -+ int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, -+- unsigned long count, loff_t to, size_t *retlen); -++ unsigned long count, loff_mtd_t to, size_mtd_t *retlen); -+ -+ int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs, -+- unsigned long count, loff_t from, size_t *retlen); -++ unsigned long count, loff_mtd_t from, size_mtd_t *retlen); -+ -+ #ifdef CONFIG_MTD_PARTITIONS -+ void mtd_erase_callback(struct erase_info *instr); -+diff -urN linux-2.6.24.7.old/include/linux/mtd/mtd.h.orig linux-2.6.24.7/include/linux/mtd/mtd.h.orig -+--- linux-2.6.24.7.old/include/linux/mtd/mtd.h.orig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/linux/mtd/mtd.h.orig 2009-04-12 18:01:55.000000000 +0200 -+@@ -0,0 +1,274 @@ -++/* -++ * $Id: mtd.h,v 1.61 2005/11/07 11:14:54 gleixner Exp $ -++ * -++ * Copyright (C) 1999-2003 David Woodhouse et al. -++ * -++ * Released under GPL -++ */ -++ -++#ifndef __MTD_MTD_H__ -++#define __MTD_MTD_H__ -++ -++#include -++#include -++#include -++#include -++ -++#include -++#include -++ -++#define MTD_CHAR_MAJOR 90 -++#define MTD_BLOCK_MAJOR 31 -++#define MAX_MTD_DEVICES 32 -++ -++#define MTD_ERASE_PENDING 0x01 -++#define MTD_ERASING 0x02 -++#define MTD_ERASE_SUSPEND 0x04 -++#define MTD_ERASE_DONE 0x08 -++#define MTD_ERASE_FAILED 0x10 -++ -++/* If the erase fails, fail_addr might indicate exactly which block failed. If -++ fail_addr = 0xffffffff, the failure was not at the device level or was not -++ specific to any particular block. */ -++struct erase_info { -++ struct mtd_info *mtd; -++ u_int32_t addr; -++ u_int32_t len; -++ u_int32_t fail_addr; -++ u_long time; -++ u_long retries; -++ u_int dev; -++ u_int cell; -++ void (*callback) (struct erase_info *self); -++ u_long priv; -++ u_char state; -++ struct erase_info *next; -++}; -++ -++struct mtd_erase_region_info { -++ u_int32_t offset; /* At which this region starts, from the beginning of the MTD */ -++ u_int32_t erasesize; /* For this region */ -++ u_int32_t numblocks; /* Number of blocks of erasesize in this region */ -++ unsigned long *lockmap; /* If keeping bitmap of locks */ -++}; -++ -++/* -++ * oob operation modes -++ * -++ * MTD_OOB_PLACE: oob data are placed at the given offset -++ * MTD_OOB_AUTO: oob data are automatically placed at the free areas -++ * which are defined by the ecclayout -++ * MTD_OOB_RAW: mode to read raw data+oob in one chunk. The oob data -++ * is inserted into the data. Thats a raw image of the -++ * flash contents. -++ */ -++typedef enum { -++ MTD_OOB_PLACE, -++ MTD_OOB_AUTO, -++ MTD_OOB_RAW, -++} mtd_oob_mode_t; -++ -++/** -++ * struct mtd_oob_ops - oob operation operands -++ * @mode: operation mode -++ * -++ * @len: number of data bytes to write/read -++ * -++ * @retlen: number of data bytes written/read -++ * -++ * @ooblen: number of oob bytes to write/read -++ * @oobretlen: number of oob bytes written/read -++ * @ooboffs: offset of oob data in the oob area (only relevant when -++ * mode = MTD_OOB_PLACE) -++ * @datbuf: data buffer - if NULL only oob data are read/written -++ * @oobbuf: oob data buffer -++ * -++ * Note, it is allowed to read more then one OOB area at one go, but not write. -++ * The interface assumes that the OOB write requests program only one page's -++ * OOB area. -++ */ -++struct mtd_oob_ops { -++ mtd_oob_mode_t mode; -++ size_t len; -++ size_t retlen; -++ size_t ooblen; -++ size_t oobretlen; -++ uint32_t ooboffs; -++ uint8_t *datbuf; -++ uint8_t *oobbuf; -++}; -++ -++struct mtd_info; -++struct mtd_info { -++ u_char type; -++ u_int32_t flags; -++ u_int32_t size; // Total size of the MTD -++ -++ /* "Major" erase size for the device. Naïve users may take this -++ * to be the only erase size available, or may use the more detailed -++ * information below if they desire -++ */ -++ u_int32_t erasesize; -++ /* Minimal writable flash unit size. In case of NOR flash it is 1 (even -++ * though individual bits can be cleared), in case of NAND flash it is -++ * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR -++ * it is of ECC block size, etc. It is illegal to have writesize = 0. -++ * Any driver registering a struct mtd_info must ensure a writesize of -++ * 1 or larger. -++ */ -++ u_int32_t writesize; -++ -++ u_int32_t oobsize; // Amount of OOB data per block (e.g. 16) -++ u_int32_t oobavail; // Available OOB bytes per block -++ -++ // Kernel-only stuff starts here. -++ char *name; -++ int index; -++ -++ /* ecc layout structure pointer - read only ! */ -++ struct nand_ecclayout *ecclayout; -++ -++ /* Data for variable erase regions. If numeraseregions is zero, -++ * it means that the whole device has erasesize as given above. -++ */ -++ int numeraseregions; -++ struct mtd_erase_region_info *eraseregions; -++ -++ /* -++ * Erase is an asynchronous operation. Device drivers are supposed -++ * to call instr->callback() whenever the operation completes, even -++ * if it completes with a failure. -++ * Callers are supposed to pass a callback function and wait for it -++ * to be called before writing to the block. -++ */ -++ int (*erase) (struct mtd_info *mtd, struct erase_info *instr); -++ -++ /* This stuff for eXecute-In-Place */ -++ int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf); -++ -++ /* We probably shouldn't allow XIP if the unpoint isn't a NULL */ -++ void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len); -++ -++ -++ int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -++ int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); -++ -++ int (*read_oob) (struct mtd_info *mtd, loff_t from, -++ struct mtd_oob_ops *ops); -++ int (*write_oob) (struct mtd_info *mtd, loff_t to, -++ struct mtd_oob_ops *ops); -++ -++ /* -++ * Methods to access the protection register area, present in some -++ * flash devices. The user data is one time programmable but the -++ * factory data is read only. -++ */ -++ int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); -++ int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -++ int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); -++ int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -++ int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -++ int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len); -++ -++ /* kvec-based read/write methods. -++ NB: The 'count' parameter is the number of _vectors_, each of -++ which contains an (ofs, len) tuple. -++ */ -++ int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); -++ -++ /* Sync */ -++ void (*sync) (struct mtd_info *mtd); -++ -++ /* Chip-supported device locking */ -++ int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len); -++ int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len); -++ -++ /* Power Management functions */ -++ int (*suspend) (struct mtd_info *mtd); -++ void (*resume) (struct mtd_info *mtd); -++ -++ /* Bad block management functions */ -++ int (*block_isbad) (struct mtd_info *mtd, loff_t ofs); -++ int (*block_markbad) (struct mtd_info *mtd, loff_t ofs); -++ -++ struct notifier_block reboot_notifier; /* default mode before reboot */ -++ -++ /* ECC status information */ -++ struct mtd_ecc_stats ecc_stats; -++ /* Subpage shift (NAND) */ -++ int subpage_sft; -++ -++ void *priv; -++ -++ struct module *owner; -++ int usecount; -++ -++ int (*refresh_device)(struct mtd_info *mtd); -++ struct mtd_info *split; -++ -++ /* If the driver is something smart, like UBI, it may need to maintain -++ * its own reference counting. The below functions are only for driver. -++ * The driver may register its callbacks. These callbacks are not -++ * supposed to be called by MTD users */ -++ int (*get_device) (struct mtd_info *mtd); -++ void (*put_device) (struct mtd_info *mtd); -++}; -++ -++ -++ /* Kernel-side ioctl definitions */ -++ -++extern int add_mtd_device(struct mtd_info *mtd); -++extern int del_mtd_device (struct mtd_info *mtd); -++ -++extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); -++extern struct mtd_info *get_mtd_device_nm(const char *name); -++ -++extern void put_mtd_device(struct mtd_info *mtd); -++ -++ -++struct mtd_notifier { -++ void (*add)(struct mtd_info *mtd); -++ void (*remove)(struct mtd_info *mtd); -++ struct list_head list; -++}; -++ -++ -++extern void register_mtd_user (struct mtd_notifier *new); -++extern int unregister_mtd_user (struct mtd_notifier *old); -++ -++int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, -++ unsigned long count, loff_t to, size_t *retlen); -++ -++int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs, -++ unsigned long count, loff_t from, size_t *retlen); -++ -++#ifdef CONFIG_MTD_PARTITIONS -++void mtd_erase_callback(struct erase_info *instr); -++#else -++static inline void mtd_erase_callback(struct erase_info *instr) -++{ -++ if (instr->callback) -++ instr->callback(instr); -++} -++#endif -++ -++/* -++ * Debugging macro and defines -++ */ -++#define MTD_DEBUG_LEVEL0 (0) /* Quiet */ -++#define MTD_DEBUG_LEVEL1 (1) /* Audible */ -++#define MTD_DEBUG_LEVEL2 (2) /* Loud */ -++#define MTD_DEBUG_LEVEL3 (3) /* Noisy */ -++ -++#ifdef CONFIG_MTD_DEBUG -++#define DEBUG(n, args...) \ -++ do { \ -++ if (n <= CONFIG_MTD_DEBUG_VERBOSE) \ -++ printk(KERN_INFO args); \ -++ } while(0) -++#else /* CONFIG_MTD_DEBUG */ -++#define DEBUG(n, args...) do { } while(0) -++ -++#endif /* CONFIG_MTD_DEBUG */ -++ -++#endif /* __MTD_MTD_H__ */ -+diff -urN linux-2.6.24.7.old/include/linux/mtd/nand.h linux-2.6.24.7/include/linux/mtd/nand.h -+--- linux-2.6.24.7.old/include/linux/mtd/nand.h 2009-04-12 18:05:07.000000000 +0200 -++++ linux-2.6.24.7/include/linux/mtd/nand.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -39,14 +39,14 @@ -+ extern void nand_wait_ready(struct mtd_info *mtd); -+ -+ /* The maximum number of NAND chips in an array */ -+-#define NAND_MAX_CHIPS 8 -++#define NAND_MAX_CHIPS 4 -+ -+ /* This constant declares the max. oobsize / page, which -+ * is supported now. If you add a chip with bigger oobsize/page -+ * adjust this accordingly. -+ */ -+-#define NAND_MAX_OOBSIZE 64 -+-#define NAND_MAX_PAGESIZE 2048 -++#define NAND_MAX_OOBSIZE 256 -++#define NAND_MAX_PAGESIZE 8192 -+ -+ /* -+ * Constants for hardware specific CLE/ALE/NCE function -+@@ -55,6 +55,10 @@ -+ * bits in one go. -+ */ -+ /* Select the chip by setting nCE to low */ -++#define NAND_NCE1 0x08 -++#define NAND_NCE2 0x10 -++#define NAND_NCE3 0x20 -++#define NAND_NCE4 0x40 -+ #define NAND_NCE 0x01 -+ /* Select the command latch by setting CLE to high */ -+ #define NAND_CLE 0x02 -+@@ -372,8 +376,8 @@ -+ void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len); -+ int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); -+ void (*select_chip)(struct mtd_info *mtd, int chip); -+- int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip); -+- int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); -++ int (*block_bad)(struct mtd_info *mtd, loff_mtd_t ofs, int getchip); -++ int (*block_markbad)(struct mtd_info *mtd, loff_mtd_t ofs); -+ void (*cmd_ctrl)(struct mtd_info *mtd, int dat, -+ unsigned int ctrl); -+ int (*dev_ready)(struct mtd_info *mtd); -+@@ -393,12 +397,14 @@ -+ int bbt_erase_shift; -+ int chip_shift; -+ int numchips; -+- unsigned long chipsize; -++ u64 chipsize; -+ int pagemask; -+ int pagebuf; -+ int subpagesize; -+ uint8_t cellinfo; -+ int badblockpos; -++ int realplanenum; /* number of planes the NAND has */ -++ int planenum; /* number of planes operating synchronously */ -+ -+ nand_state_t state; -+ -+@@ -450,7 +456,7 @@ -+ char *name; -+ int id; -+ unsigned long pagesize; -+- unsigned long chipsize; -++ u64 chipsize; -+ unsigned long erasesize; -+ unsigned long options; -+ }; -+@@ -538,13 +544,13 @@ -+ #define NAND_BBT_SCAN_MAXBLOCKS 4 -+ -+ extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd); -+-extern int nand_update_bbt(struct mtd_info *mtd, loff_t offs); -++extern int nand_update_bbt(struct mtd_info *mtd, loff_mtd_t offs); -+ extern int nand_default_bbt(struct mtd_info *mtd); -+-extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt); -++extern int nand_isbad_bbt(struct mtd_info *mtd, loff_mtd_t offs, int allowbbt); -+ extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, -+ int allowbbt); -+-extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, -+- size_t * retlen, uint8_t * buf); -++extern int nand_do_read(struct mtd_info *mtd, loff_mtd_t from, size_mtd_t len, -++ size_mtd_t * retlen, uint8_t * buf); -+ -+ /* -+ * Constants for oob configuration -+diff -urN linux-2.6.24.7.old/include/linux/mtd/partitions.h linux-2.6.24.7/include/linux/mtd/partitions.h -+--- linux-2.6.24.7.old/include/linux/mtd/partitions.h 2009-04-12 18:05:07.000000000 +0200 -++++ linux-2.6.24.7/include/linux/mtd/partitions.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -39,8 +39,9 @@ -+ struct mtd_partition; -+ struct mtd_partition { -+ char *name; /* identifier string */ -+- u_int32_t size; /* partition size */ -+- u_int32_t offset; /* offset within the master MTD space */ -++ u_int64_t size; /* partition size */ -++ u_int64_t offset; /* offset within the master MTD space */ -++ char use_planes; /* flag to specify whether multiple planes of NAND is used in the partition */ -+ u_int32_t mask_flags; /* master MTD flags to mask out for this partition */ -+ struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/ -+ struct mtd_info **mtdp; /* pointer to store the MTD object */ -+diff -urN linux-2.6.24.7.old/include/linux/mtd/partitions.h.orig linux-2.6.24.7/include/linux/mtd/partitions.h.orig -+--- linux-2.6.24.7.old/include/linux/mtd/partitions.h.orig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/linux/mtd/partitions.h.orig 2009-04-12 18:01:55.000000000 +0200 -+@@ -0,0 +1,78 @@ -++/* -++ * MTD partitioning layer definitions -++ * -++ * (C) 2000 Nicolas Pitre -++ * -++ * This code is GPL -++ * -++ * $Id: partitions.h,v 1.17 2005/11/07 11:14:55 gleixner Exp $ -++ */ -++ -++#ifndef MTD_PARTITIONS_H -++#define MTD_PARTITIONS_H -++ -++#include -++ -++ -++/* -++ * Partition definition structure: -++ * -++ * An array of struct partition is passed along with a MTD object to -++ * add_mtd_partitions() to create them. -++ * -++ * For each partition, these fields are available: -++ * name: string that will be used to label the partition's MTD device. -++ * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition -++ * will extend to the end of the master MTD device. -++ * offset: absolute starting position within the master MTD device; if -++ * defined as MTDPART_OFS_APPEND, the partition will start where the -++ * previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block. -++ * mask_flags: contains flags that have to be masked (removed) from the -++ * master MTD flag set for the corresponding MTD partition. -++ * For example, to force a read-only partition, simply adding -++ * MTD_WRITEABLE to the mask_flags will do the trick. -++ * -++ * Note: writeable partitions require their size and offset be -++ * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK). -++ */ -++ -++struct mtd_partition; -++struct mtd_partition { -++ char *name; /* identifier string */ -++ u_int32_t size; /* partition size */ -++ u_int32_t offset; /* offset within the master MTD space */ -++ u_int32_t mask_flags; /* master MTD flags to mask out for this partition */ -++ struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/ -++ struct mtd_info **mtdp; /* pointer to store the MTD object */ -++ int (*refresh_partition)(struct mtd_info *); -++}; -++ -++#define MTDPART_OFS_NXTBLK (-2) -++#define MTDPART_OFS_APPEND (-1) -++#define MTDPART_SIZ_FULL (0) -++ -++ -++int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int); -++int del_mtd_partitions(struct mtd_info *); -++int refresh_mtd_partitions(struct mtd_info *); -++ -++/* -++ * Functions dealing with the various ways of partitioning the space -++ */ -++ -++struct mtd_part_parser { -++ struct list_head list; -++ struct module *owner; -++ const char *name; -++ int (*parse_fn)(struct mtd_info *, struct mtd_partition **, unsigned long); -++}; -++ -++extern int register_mtd_parser(struct mtd_part_parser *parser); -++extern int deregister_mtd_parser(struct mtd_part_parser *parser); -++extern int parse_mtd_partitions(struct mtd_info *master, const char **types, -++ struct mtd_partition **pparts, unsigned long origin); -++ -++#define put_partition_parser(p) do { module_put((p)->owner); } while(0) -++ -++#endif -++ -+diff -urN linux-2.6.24.7.old/include/linux/mtd/ubi.h linux-2.6.24.7/include/linux/mtd/ubi.h -+--- linux-2.6.24.7.old/include/linux/mtd/ubi.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/include/linux/mtd/ubi.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -26,23 +26,6 @@ -+ #include -+ -+ /* -+- * UBI data type hint constants. -+- * -+- * UBI_LONGTERM: long-term data -+- * UBI_SHORTTERM: short-term data -+- * UBI_UNKNOWN: data persistence is unknown -+- * -+- * These constants are used when data is written to UBI volumes in order to -+- * help the UBI wear-leveling unit to find more appropriate physical -+- * eraseblocks. -+- */ -+-enum { -+- UBI_LONGTERM = 1, -+- UBI_SHORTTERM, -+- UBI_UNKNOWN -+-}; -+- -+-/* -+ * enum ubi_open_mode - UBI volume open mode constants. -+ * -+ * UBI_READONLY: read-only mode -+@@ -167,6 +150,7 @@ -+ int len, int dtype); -+ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum); -+ int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum); -++int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype); -+ int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum); -+ -+ /* -+diff -urN linux-2.6.24.7.old/include/linux/vt.h linux-2.6.24.7/include/linux/vt.h -+--- linux-2.6.24.7.old/include/linux/vt.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/include/linux/vt.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -18,10 +18,16 @@ -+ * resizing). -+ */ -+ #define MIN_NR_CONSOLES 1 /* must be at least 1 */ -+-#define MAX_NR_CONSOLES 63 /* serial lines start at 64 */ -+-#define MAX_NR_USER_CONSOLES 63 /* must be root to allocate above this */ -+- /* Note: the ioctl VT_GETSTATE does not work for -+- consoles 16 and higher (since it returns a short) */ -++ -++#if defined(CONFIG_JZSOC) -++#define MAX_NR_CONSOLES 2 -++#define MAX_NR_USER_CONSOLES 2 -++#else -++#define MAX_NR_CONSOLES 63 /* serial lines start at 64 */ -++#define MAX_NR_USER_CONSOLES 63 /* must be root to allocate above this */ -++ /* Note: the ioctl VT_GETSTATE does not work for -++ consoles 16 and higher (since it returns a short) */ -++#endif -+ -+ /* 0x56 is 'V', to avoid collision with termios and kd */ -+ -+diff -urN linux-2.6.24.7.old/include/linux/writeback.h linux-2.6.24.7/include/linux/writeback.h -+--- linux-2.6.24.7.old/include/linux/writeback.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/include/linux/writeback.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -70,6 +70,7 @@ -+ void writeback_inodes(struct writeback_control *wbc); -+ int inode_wait(void *); -+ void sync_inodes_sb(struct super_block *, int wait); -++void writeback_inodes_sb(struct super_block *sb, struct writeback_control *wbc); -+ void sync_inodes(int wait); -+ -+ /* writeback.h requires fs.h; it, too, is not included from here. */ -+diff -urN linux-2.6.24.7.old/include/mtd/mtd-abi.h linux-2.6.24.7/include/mtd/mtd-abi.h -+--- linux-2.6.24.7.old/include/mtd/mtd-abi.h 2009-04-12 18:05:07.000000000 +0200 -++++ linux-2.6.24.7/include/mtd/mtd-abi.h 2009-04-12 18:23:10.000000000 +0200 -+@@ -7,9 +7,18 @@ -+ #ifndef __MTD_ABI_H__ -+ #define __MTD_ABI_H__ -+ -++ -++#ifndef __KERNEL__ /* Urgh. The whole point of splitting this out into -++ separate files was to avoid #ifdef __KERNEL__ */ -++#define __user -++#endif -++ -++typedef unsigned long long size_mtd_t; -++typedef unsigned long long loff_mtd_t; -++ -+ struct erase_info_user { -+- uint32_t start; -+- uint32_t length; -++ uint64_t start; -++ uint64_t length; -+ }; -+ -+ struct mtd_oob_buf { -+@@ -18,6 +27,14 @@ -+ unsigned char __user *ptr; -+ }; -+ -++struct mtd_page_buf { -++ uint32_t start; //page start address -++ uint32_t ooblength; -++ uint32_t datlength; -++ unsigned char __user *oobptr; -++ unsigned char __user *datptr; -++}; -++ -+ #define MTD_ABSENT 0 -+ #define MTD_RAM 1 -+ #define MTD_ROM 2 -+@@ -52,7 +69,7 @@ -+ struct mtd_info_user { -+ uint8_t type; -+ uint32_t flags; -+- uint32_t size; // Total size of the MTD -++ uint64_t size; // Total size of the MTD -+ uint32_t erasesize; -+ uint32_t writesize; -+ uint32_t oobsize; // Amount of OOB data per block (e.g. 16) -+@@ -63,7 +80,7 @@ -+ }; -+ -+ struct region_info_user { -+- uint32_t offset; /* At which this region starts, -++ uint64_t offset; /* At which this region starts, -+ * from the beginning of the MTD */ -+ uint32_t erasesize; /* For this region */ -+ uint32_t numblocks; /* Number of blocks in this region */ -+@@ -86,8 +103,8 @@ -+ #define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user) -+ #define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo) -+ #define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo) -+-#define MEMGETBADBLOCK _IOW('M', 11, loff_t) -+-#define MEMSETBADBLOCK _IOW('M', 12, loff_t) -++#define MEMGETBADBLOCK _IOW('M', 11, loff_mtd_t) -++#define MEMSETBADBLOCK _IOW('M', 12, loff_mtd_t) -+ #define OTPSELECT _IOR('M', 13, int) -+ #define OTPGETREGIONCOUNT _IOW('M', 14, int) -+ #define OTPGETREGIONINFO _IOW('M', 15, struct otp_info) -+@@ -95,6 +112,7 @@ -+ #define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout) -+ #define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats) -+ #define MTDFILEMODE _IO('M', 19) -++#define MEMWRITEPAGE _IOWR('M', 20, struct mtd_page_buf) -+ #define MTDREFRESH _IO('M', 23) -+ -+ /* -+@@ -105,7 +123,7 @@ -+ uint32_t useecc; -+ uint32_t eccbytes; -+ uint32_t oobfree[8][2]; -+- uint32_t eccpos[32]; -++ uint32_t eccpos[104]; -+ }; -+ -+ struct nand_oobfree { -+@@ -120,7 +138,7 @@ -+ */ -+ struct nand_ecclayout { -+ uint32_t eccbytes; -+- uint32_t eccpos[64]; -++ uint32_t eccpos[128]; -+ uint32_t oobavail; -+ struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; -+ }; -+diff -urN linux-2.6.24.7.old/include/mtd/ubi-user.h linux-2.6.24.7/include/mtd/ubi-user.h -+--- linux-2.6.24.7.old/include/mtd/ubi-user.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/include/mtd/ubi-user.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -21,7 +21,26 @@ -+ #ifndef __UBI_USER_H__ -+ #define __UBI_USER_H__ -+ -++#ifndef __KERNEL__ /* Urgh. The whole point of splitting this out into -++ separate files was to avoid #ifdef __KERNEL__ */ -++#define __user -++#endif -+ /* -++ * UBI device creation (the same as MTD device attachment) -++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -++ * -++ * MTD devices may be attached using %UBI_IOCATT ioctl command of the UBI -++ * control device. The caller has to properly fill and pass -++ * &struct ubi_attach_req object - UBI will attach the MTD device specified in -++ * the request and return the newly created UBI device number as the ioctl -++ * return value. -++ * -++ * UBI device deletion (the same as MTD device detachment) -++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -++ * -++ * An UBI device maybe deleted with %UBI_IOCDET ioctl command of the UBI -++ * control device. -++ * -+ * UBI volume creation -+ * ~~~~~~~~~~~~~~~~~~~ -+ * -+@@ -48,7 +67,7 @@ -+ * -+ * Volume update should be done via the %UBI_IOCVOLUP IOCTL command of the -+ * corresponding UBI volume character device. A pointer to a 64-bit update -+- * size should be passed to the IOCTL. After then, UBI expects user to write -++ * size should be passed to the IOCTL. After this, UBI expects user to write -+ * this number of bytes to the volume character device. The update is finished -+ * when the claimed number of bytes is passed. So, the volume update sequence -+ * is something like: -+@@ -57,14 +76,24 @@ -+ * ioctl(fd, UBI_IOCVOLUP, &image_size); -+ * write(fd, buf, image_size); -+ * close(fd); -++ * -++ * Atomic eraseblock change -++ * ~~~~~~~~~~~~~~~~~~~~~~~~ -++ * -++ * Atomic eraseblock change operation is done via the %UBI_IOCEBCH IOCTL -++ * command of the corresponding UBI volume character device. A pointer to -++ * &struct ubi_leb_change_req has to be passed to the IOCTL. Then the user is -++ * expected to write the requested amount of bytes. This is similar to the -++ * "volume update" IOCTL. -+ */ -+ -+ /* -+- * When a new volume is created, users may either specify the volume number they -+- * want to create or to let UBI automatically assign a volume number using this -+- * constant. -++ * When a new UBI volume or UBI device is created, users may either specify the -++ * volume/device number they want to create or to let UBI automatically assign -++ * the number using these constants. -+ */ -+ #define UBI_VOL_NUM_AUTO (-1) -++#define UBI_DEV_NUM_AUTO (-1) -+ -+ /* Maximum volume name length */ -+ #define UBI_MAX_VOLUME_NAME 127 -+@@ -80,6 +109,15 @@ -+ /* Re-size an UBI volume */ -+ #define UBI_IOCRSVOL _IOW(UBI_IOC_MAGIC, 2, struct ubi_rsvol_req) -+ -++/* IOCTL commands of the UBI control character device */ -++ -++#define UBI_CTRL_IOC_MAGIC 'o' -++ -++/* Attach an MTD device */ -++#define UBI_IOCATT _IOW(UBI_CTRL_IOC_MAGIC, 64, struct ubi_attach_req) -++/* Detach an MTD device */ -++#define UBI_IOCDET _IOW(UBI_CTRL_IOC_MAGIC, 65, int32_t) -++ -+ /* IOCTL commands of UBI volume character devices */ -+ -+ #define UBI_VOL_IOC_MAGIC 'O' -+@@ -88,6 +126,30 @@ -+ #define UBI_IOCVOLUP _IOW(UBI_VOL_IOC_MAGIC, 0, int64_t) -+ /* An eraseblock erasure command, used for debugging, disabled by default */ -+ #define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 1, int32_t) -++/* An atomic eraseblock change command */ -++#define UBI_IOCEBCH _IOW(UBI_VOL_IOC_MAGIC, 2, int32_t) -++/* Start UBI leb read */ -++#define UBI_IOCLEBREAD _IOWR(UBI_VOL_IOC_MAGIC, 3, struct ubi_leb) -++ -++/* Maximum MTD device name length supported by UBI */ -++#define MAX_UBI_MTD_NAME_LEN 127 -++ -++/* -++ * UBI data type hint constants. -++ * -++ * UBI_LONGTERM: long-term data -++ * UBI_SHORTTERM: short-term data -++ * UBI_UNKNOWN: data persistence is unknown -++ * -++ * These constants are used when data is written to UBI volumes in order to -++ * help the UBI wear-leveling unit to find more appropriate physical -++ * eraseblocks. -++ */ -++enum { -++ UBI_LONGTERM = 1, -++ UBI_SHORTTERM = 2, -++ UBI_UNKNOWN = 3, -++}; -+ -+ /* -+ * UBI volume type constants. -+@@ -97,22 +159,58 @@ -+ */ -+ enum { -+ UBI_DYNAMIC_VOLUME = 3, -+- UBI_STATIC_VOLUME = 4 -++ UBI_STATIC_VOLUME = 4, -++}; -++ -++/** -++ * struct ubi_attach_req - attach MTD device request. -++ * @ubi_num: UBI device number to create -++ * @mtd_num: MTD device number to attach -++ * @vid_hdr_offset: VID header offset (use defaults if %0) -++ * @padding: reserved for future, not used, has to be zeroed -++ * -++ * This data structure is used to specify MTD device UBI has to attach and the -++ * parameters it has to use. The number which should be assigned to the new UBI -++ * device is passed in @ubi_num. UBI may automatically assign the number if -++ * @UBI_DEV_NUM_AUTO is passed. In this case, the device number is returned in -++ * @ubi_num. -++ * -++ * Most applications should pass %0 in @vid_hdr_offset to make UBI use default -++ * offset of the VID header within physical eraseblocks. The default offset is -++ * the next min. I/O unit after the EC header. For example, it will be offset -++ * 512 in case of a 512 bytes page NAND flash with no sub-page support. Or -++ * it will be 512 in case of a 2KiB page NAND flash with 4 512-byte sub-pages. -++ * -++ * But in rare cases, if this optimizes things, the VID header may be placed to -++ * a different offset. For example, the boot-loader might do things faster if the -++ * VID header sits at the end of the first 2KiB NAND page with 4 sub-pages. As -++ * the boot-loader would not normally need to read EC headers (unless it needs -++ * UBI in RW mode), it might be faster to calculate ECC. This is weird example, -++ * but it real-life example. So, in this example, @vid_hdr_offer would be -++ * 2KiB-64 bytes = 1984. Note, that this position is not even 512-bytes -++ * aligned, which is OK, as UBI is clever enough to realize this is 4th sub-page -++ * of the first page and add needed padding. -++ */ -++struct ubi_attach_req { -++ int32_t ubi_num; -++ int32_t mtd_num; -++ int32_t vid_hdr_offset; -++ uint8_t padding[12]; -+ }; -+ -+ /** -+ * struct ubi_mkvol_req - volume description data structure used in -+- * volume creation requests. -++ * volume creation requests. -+ * @vol_id: volume number -+ * @alignment: volume alignment -+ * @bytes: volume size in bytes -+ * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) -+- * @padding1: reserved for future, not used -++ * @padding1: reserved for future, not used, has to be zeroed -+ * @name_len: volume name length -+- * @padding2: reserved for future, not used -++ * @padding2: reserved for future, not used, has to be zeroed -+ * @name: volume name -+ * -+- * This structure is used by userspace programs when creating new volumes. The -++ * This structure is used by user-space programs when creating new volumes. The -+ * @used_bytes field is only necessary when creating static volumes. -+ * -+ * The @alignment field specifies the required alignment of the volume logical -+@@ -139,7 +237,7 @@ -+ int8_t padding1; -+ int16_t name_len; -+ int8_t padding2[4]; -+- char name[UBI_MAX_VOLUME_NAME+1]; -++ char name[UBI_MAX_VOLUME_NAME + 1]; -+ } __attribute__ ((packed)); -+ -+ /** -+@@ -158,4 +256,29 @@ -+ int32_t vol_id; -+ } __attribute__ ((packed)); -+ -++/** -++ * struct ubi_leb_change_req - a data structure used in atomic logical -++ * eraseblock change requests. -++ * @lnum: logical eraseblock number to change -++ * @bytes: how many bytes will be written to the logical eraseblock -++ * @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN) -++ * @padding: reserved for future, not used, has to be zeroed -++ */ -++struct ubi_leb_change_req { -++ int32_t lnum; -++ int32_t bytes; -++ uint8_t dtype; -++ uint8_t padding[7]; -++} __attribute__ ((packed)); -++ -++/** -++ * struct ubi_leb - a data structure describe LEB. -++ * @lnum: logical eraseblock number to dump -++ * @lebbuf: LEB data buffer -++ */ -++struct ubi_leb{ -++ unsigned int lnum; -++ char __user *buf; -++}; -++ -+ #endif /* __UBI_USER_H__ */ -+diff -urN linux-2.6.24.7.old/include/sound/pcm.h linux-2.6.24.7/include/sound/pcm.h -+--- linux-2.6.24.7.old/include/sound/pcm.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/include/sound/pcm.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -107,23 +107,23 @@ -+ #define SNDRV_PCM_RATE_5512 (1<<0) /* 5512Hz */ -+ #define SNDRV_PCM_RATE_8000 (1<<1) /* 8000Hz */ -+ #define SNDRV_PCM_RATE_11025 (1<<2) /* 11025Hz */ -+-#define SNDRV_PCM_RATE_16000 (1<<3) /* 16000Hz */ -+-#define SNDRV_PCM_RATE_22050 (1<<4) /* 22050Hz */ -+-#define SNDRV_PCM_RATE_32000 (1<<5) /* 32000Hz */ -+-#define SNDRV_PCM_RATE_44100 (1<<6) /* 44100Hz */ -+-#define SNDRV_PCM_RATE_48000 (1<<7) /* 48000Hz */ -+-#define SNDRV_PCM_RATE_64000 (1<<8) /* 64000Hz */ -+-#define SNDRV_PCM_RATE_88200 (1<<9) /* 88200Hz */ -+-#define SNDRV_PCM_RATE_96000 (1<<10) /* 96000Hz */ -+-#define SNDRV_PCM_RATE_176400 (1<<11) /* 176400Hz */ -+-#define SNDRV_PCM_RATE_192000 (1<<12) /* 192000Hz */ -++#define SNDRV_PCM_RATE_12000 (1<<3) /* 12000Hz */ -++#define SNDRV_PCM_RATE_16000 (1<<4) /* 16000Hz */ -++#define SNDRV_PCM_RATE_22050 (1<<5) /* 22050Hz */ -++#define SNDRV_PCM_RATE_24000 (1<<6) /* 24000Hz */ -++#define SNDRV_PCM_RATE_32000 (1<<7) /* 32000Hz */ -++#define SNDRV_PCM_RATE_44100 (1<<8) /* 44100Hz */ -++#define SNDRV_PCM_RATE_48000 (1<<9) /* 48000Hz */ -++#define SNDRV_PCM_RATE_64000 (1<<10) /* 64000Hz */ -++#define SNDRV_PCM_RATE_88200 (1<<11) /* 88200Hz */ -++#define SNDRV_PCM_RATE_96000 (1<<12) /* 96000Hz */ -++#define SNDRV_PCM_RATE_176400 (1<<13) /* 176400Hz */ -++#define SNDRV_PCM_RATE_192000 (1<<14) /* 192000Hz */ -+ -+ #define SNDRV_PCM_RATE_CONTINUOUS (1<<30) /* continuous range */ -+ #define SNDRV_PCM_RATE_KNOT (1<<31) /* supports more non-continuos rates */ -+ -+-#define SNDRV_PCM_RATE_8000_44100 (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_11025|\ -+- SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_22050|\ -+- SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100) -++#define SNDRV_PCM_RATE_8000_44100 (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_11025|SNDRV_PCM_RATE_12000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_22050|SNDRV_PCM_RATE_24000|SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100) -+ #define SNDRV_PCM_RATE_8000_48000 (SNDRV_PCM_RATE_8000_44100|SNDRV_PCM_RATE_48000) -+ #define SNDRV_PCM_RATE_8000_96000 (SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_64000|\ -+ SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000) -+diff -urN linux-2.6.24.7.old/include/sound/pcm.h.org linux-2.6.24.7/include/sound/pcm.h.org -+--- linux-2.6.24.7.old/include/sound/pcm.h.org 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/include/sound/pcm.h.org 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1011 @@ -++#ifndef __SOUND_PCM_H -++#define __SOUND_PCM_H -++ -++/* -++ * Digital Audio (PCM) abstract layer -++ * Copyright (c) by Jaroslav Kysela -++ * Abramo Bagnara -++ * -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ * GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++#define snd_pcm_substream_chip(substream) ((substream)->private_data) -++#define snd_pcm_chip(pcm) ((pcm)->private_data) -++ -++#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) -++#include "pcm_oss.h" -++#endif -++ -++/* -++ * Hardware (lowlevel) section -++ */ -++ -++struct snd_pcm_hardware { -++ unsigned int info; /* SNDRV_PCM_INFO_* */ -++ u64 formats; /* SNDRV_PCM_FMTBIT_* */ -++ unsigned int rates; /* SNDRV_PCM_RATE_* */ -++ unsigned int rate_min; /* min rate */ -++ unsigned int rate_max; /* max rate */ -++ unsigned int channels_min; /* min channels */ -++ unsigned int channels_max; /* max channels */ -++ size_t buffer_bytes_max; /* max buffer size */ -++ size_t period_bytes_min; /* min period size */ -++ size_t period_bytes_max; /* max period size */ -++ unsigned int periods_min; /* min # of periods */ -++ unsigned int periods_max; /* max # of periods */ -++ size_t fifo_size; /* fifo size in bytes */ -++}; -++ -++struct snd_pcm_substream; -++ -++struct snd_pcm_ops { -++ int (*open)(struct snd_pcm_substream *substream); -++ int (*close)(struct snd_pcm_substream *substream); -++ int (*ioctl)(struct snd_pcm_substream * substream, -++ unsigned int cmd, void *arg); -++ int (*hw_params)(struct snd_pcm_substream *substream, -++ struct snd_pcm_hw_params *params); -++ int (*hw_free)(struct snd_pcm_substream *substream); -++ int (*prepare)(struct snd_pcm_substream *substream); -++ int (*trigger)(struct snd_pcm_substream *substream, int cmd); -++ snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream); -++ int (*copy)(struct snd_pcm_substream *substream, int channel, -++ snd_pcm_uframes_t pos, -++ void __user *buf, snd_pcm_uframes_t count); -++ int (*silence)(struct snd_pcm_substream *substream, int channel, -++ snd_pcm_uframes_t pos, snd_pcm_uframes_t count); -++ struct page *(*page)(struct snd_pcm_substream *substream, -++ unsigned long offset); -++ int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct *vma); -++ int (*ack)(struct snd_pcm_substream *substream); -++}; -++ -++/* -++ * -++ */ -++ -++#define SNDRV_PCM_DEVICES 8 -++ -++#define SNDRV_PCM_IOCTL1_FALSE ((void *)0) -++#define SNDRV_PCM_IOCTL1_TRUE ((void *)1) -++ -++#define SNDRV_PCM_IOCTL1_RESET 0 -++#define SNDRV_PCM_IOCTL1_INFO 1 -++#define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2 -++#define SNDRV_PCM_IOCTL1_GSTATE 3 -++ -++#define SNDRV_PCM_TRIGGER_STOP 0 -++#define SNDRV_PCM_TRIGGER_START 1 -++#define SNDRV_PCM_TRIGGER_PAUSE_PUSH 3 -++#define SNDRV_PCM_TRIGGER_PAUSE_RELEASE 4 -++#define SNDRV_PCM_TRIGGER_SUSPEND 5 -++#define SNDRV_PCM_TRIGGER_RESUME 6 -++ -++#define SNDRV_PCM_POS_XRUN ((snd_pcm_uframes_t)-1) -++ -++/* If you change this don't forget to change rates[] table in pcm_native.c */ -++#define SNDRV_PCM_RATE_5512 (1<<0) /* 5512Hz */ -++#define SNDRV_PCM_RATE_8000 (1<<1) /* 8000Hz */ -++#define SNDRV_PCM_RATE_11025 (1<<2) /* 11025Hz */ -++#define SNDRV_PCM_RATE_16000 (1<<3) /* 16000Hz */ -++#define SNDRV_PCM_RATE_22050 (1<<4) /* 22050Hz */ -++#define SNDRV_PCM_RATE_32000 (1<<5) /* 32000Hz */ -++#define SNDRV_PCM_RATE_44100 (1<<6) /* 44100Hz */ -++#define SNDRV_PCM_RATE_48000 (1<<7) /* 48000Hz */ -++#define SNDRV_PCM_RATE_64000 (1<<8) /* 64000Hz */ -++#define SNDRV_PCM_RATE_88200 (1<<9) /* 88200Hz */ -++#define SNDRV_PCM_RATE_96000 (1<<10) /* 96000Hz */ -++#define SNDRV_PCM_RATE_176400 (1<<11) /* 176400Hz */ -++#define SNDRV_PCM_RATE_192000 (1<<12) /* 192000Hz */ -++ -++#define SNDRV_PCM_RATE_CONTINUOUS (1<<30) /* continuous range */ -++#define SNDRV_PCM_RATE_KNOT (1<<31) /* supports more non-continuos rates */ -++ -++#define SNDRV_PCM_RATE_8000_44100 (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_11025|\ -++ SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_22050|\ -++ SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100) -++#define SNDRV_PCM_RATE_8000_48000 (SNDRV_PCM_RATE_8000_44100|SNDRV_PCM_RATE_48000) -++#define SNDRV_PCM_RATE_8000_96000 (SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_64000|\ -++ SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000) -++#define SNDRV_PCM_RATE_8000_192000 (SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\ -++ SNDRV_PCM_RATE_192000) -++#define SNDRV_PCM_FMTBIT_S8 (1ULL << SNDRV_PCM_FORMAT_S8) -++#define SNDRV_PCM_FMTBIT_U8 (1ULL << SNDRV_PCM_FORMAT_U8) -++#define SNDRV_PCM_FMTBIT_S16_LE (1ULL << SNDRV_PCM_FORMAT_S16_LE) -++#define SNDRV_PCM_FMTBIT_S16_BE (1ULL << SNDRV_PCM_FORMAT_S16_BE) -++#define SNDRV_PCM_FMTBIT_U16_LE (1ULL << SNDRV_PCM_FORMAT_U16_LE) -++#define SNDRV_PCM_FMTBIT_U16_BE (1ULL << SNDRV_PCM_FORMAT_U16_BE) -++#define SNDRV_PCM_FMTBIT_S24_LE (1ULL << SNDRV_PCM_FORMAT_S24_LE) -++#define SNDRV_PCM_FMTBIT_S24_BE (1ULL << SNDRV_PCM_FORMAT_S24_BE) -++#define SNDRV_PCM_FMTBIT_U24_LE (1ULL << SNDRV_PCM_FORMAT_U24_LE) -++#define SNDRV_PCM_FMTBIT_U24_BE (1ULL << SNDRV_PCM_FORMAT_U24_BE) -++#define SNDRV_PCM_FMTBIT_S32_LE (1ULL << SNDRV_PCM_FORMAT_S32_LE) -++#define SNDRV_PCM_FMTBIT_S32_BE (1ULL << SNDRV_PCM_FORMAT_S32_BE) -++#define SNDRV_PCM_FMTBIT_U32_LE (1ULL << SNDRV_PCM_FORMAT_U32_LE) -++#define SNDRV_PCM_FMTBIT_U32_BE (1ULL << SNDRV_PCM_FORMAT_U32_BE) -++#define SNDRV_PCM_FMTBIT_FLOAT_LE (1ULL << SNDRV_PCM_FORMAT_FLOAT_LE) -++#define SNDRV_PCM_FMTBIT_FLOAT_BE (1ULL << SNDRV_PCM_FORMAT_FLOAT_BE) -++#define SNDRV_PCM_FMTBIT_FLOAT64_LE (1ULL << SNDRV_PCM_FORMAT_FLOAT64_LE) -++#define SNDRV_PCM_FMTBIT_FLOAT64_BE (1ULL << SNDRV_PCM_FORMAT_FLOAT64_BE) -++#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE) -++#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE) -++#define SNDRV_PCM_FMTBIT_MU_LAW (1ULL << SNDRV_PCM_FORMAT_MU_LAW) -++#define SNDRV_PCM_FMTBIT_A_LAW (1ULL << SNDRV_PCM_FORMAT_A_LAW) -++#define SNDRV_PCM_FMTBIT_IMA_ADPCM (1ULL << SNDRV_PCM_FORMAT_IMA_ADPCM) -++#define SNDRV_PCM_FMTBIT_MPEG (1ULL << SNDRV_PCM_FORMAT_MPEG) -++#define SNDRV_PCM_FMTBIT_GSM (1ULL << SNDRV_PCM_FORMAT_GSM) -++#define SNDRV_PCM_FMTBIT_SPECIAL (1ULL << SNDRV_PCM_FORMAT_SPECIAL) -++#define SNDRV_PCM_FMTBIT_S24_3LE (1ULL << SNDRV_PCM_FORMAT_S24_3LE) -++#define SNDRV_PCM_FMTBIT_U24_3LE (1ULL << SNDRV_PCM_FORMAT_U24_3LE) -++#define SNDRV_PCM_FMTBIT_S24_3BE (1ULL << SNDRV_PCM_FORMAT_S24_3BE) -++#define SNDRV_PCM_FMTBIT_U24_3BE (1ULL << SNDRV_PCM_FORMAT_U24_3BE) -++#define SNDRV_PCM_FMTBIT_S20_3LE (1ULL << SNDRV_PCM_FORMAT_S20_3LE) -++#define SNDRV_PCM_FMTBIT_U20_3LE (1ULL << SNDRV_PCM_FORMAT_U20_3LE) -++#define SNDRV_PCM_FMTBIT_S20_3BE (1ULL << SNDRV_PCM_FORMAT_S20_3BE) -++#define SNDRV_PCM_FMTBIT_U20_3BE (1ULL << SNDRV_PCM_FORMAT_U20_3BE) -++#define SNDRV_PCM_FMTBIT_S18_3LE (1ULL << SNDRV_PCM_FORMAT_S18_3LE) -++#define SNDRV_PCM_FMTBIT_U18_3LE (1ULL << SNDRV_PCM_FORMAT_U18_3LE) -++#define SNDRV_PCM_FMTBIT_S18_3BE (1ULL << SNDRV_PCM_FORMAT_S18_3BE) -++#define SNDRV_PCM_FMTBIT_U18_3BE (1ULL << SNDRV_PCM_FORMAT_U18_3BE) -++ -++#ifdef SNDRV_LITTLE_ENDIAN -++#define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE -++#define SNDRV_PCM_FMTBIT_U16 SNDRV_PCM_FMTBIT_U16_LE -++#define SNDRV_PCM_FMTBIT_S24 SNDRV_PCM_FMTBIT_S24_LE -++#define SNDRV_PCM_FMTBIT_U24 SNDRV_PCM_FMTBIT_U24_LE -++#define SNDRV_PCM_FMTBIT_S32 SNDRV_PCM_FMTBIT_S32_LE -++#define SNDRV_PCM_FMTBIT_U32 SNDRV_PCM_FMTBIT_U32_LE -++#define SNDRV_PCM_FMTBIT_FLOAT SNDRV_PCM_FMTBIT_FLOAT_LE -++#define SNDRV_PCM_FMTBIT_FLOAT64 SNDRV_PCM_FMTBIT_FLOAT64_LE -++#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE -++#endif -++#ifdef SNDRV_BIG_ENDIAN -++#define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_BE -++#define SNDRV_PCM_FMTBIT_U16 SNDRV_PCM_FMTBIT_U16_BE -++#define SNDRV_PCM_FMTBIT_S24 SNDRV_PCM_FMTBIT_S24_BE -++#define SNDRV_PCM_FMTBIT_U24 SNDRV_PCM_FMTBIT_U24_BE -++#define SNDRV_PCM_FMTBIT_S32 SNDRV_PCM_FMTBIT_S32_BE -++#define SNDRV_PCM_FMTBIT_U32 SNDRV_PCM_FMTBIT_U32_BE -++#define SNDRV_PCM_FMTBIT_FLOAT SNDRV_PCM_FMTBIT_FLOAT_BE -++#define SNDRV_PCM_FMTBIT_FLOAT64 SNDRV_PCM_FMTBIT_FLOAT64_BE -++#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE -++#endif -++ -++struct snd_pcm_file { -++ struct snd_pcm_substream *substream; -++ int no_compat_mmap; -++}; -++ -++struct snd_pcm_hw_rule; -++typedef int (*snd_pcm_hw_rule_func_t)(struct snd_pcm_hw_params *params, -++ struct snd_pcm_hw_rule *rule); -++ -++struct snd_pcm_hw_rule { -++ unsigned int cond; -++ snd_pcm_hw_rule_func_t func; -++ int var; -++ int deps[4]; -++ void *private; -++}; -++ -++struct snd_pcm_hw_constraints { -++ struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - -++ SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; -++ struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - -++ SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; -++ unsigned int rules_num; -++ unsigned int rules_all; -++ struct snd_pcm_hw_rule *rules; -++}; -++ -++static inline struct snd_mask *constrs_mask(struct snd_pcm_hw_constraints *constrs, -++ snd_pcm_hw_param_t var) -++{ -++ return &constrs->masks[var - SNDRV_PCM_HW_PARAM_FIRST_MASK]; -++} -++ -++static inline struct snd_interval *constrs_interval(struct snd_pcm_hw_constraints *constrs, -++ snd_pcm_hw_param_t var) -++{ -++ return &constrs->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]; -++} -++ -++struct snd_ratnum { -++ unsigned int num; -++ unsigned int den_min, den_max, den_step; -++}; -++ -++struct snd_ratden { -++ unsigned int num_min, num_max, num_step; -++ unsigned int den; -++}; -++ -++struct snd_pcm_hw_constraint_ratnums { -++ int nrats; -++ struct snd_ratnum *rats; -++}; -++ -++struct snd_pcm_hw_constraint_ratdens { -++ int nrats; -++ struct snd_ratden *rats; -++}; -++ -++struct snd_pcm_hw_constraint_list { -++ unsigned int count; -++ unsigned int *list; -++ unsigned int mask; -++}; -++ -++struct snd_pcm_runtime { -++ /* -- Status -- */ -++ struct snd_pcm_substream *trigger_master; -++ struct timespec trigger_tstamp; /* trigger timestamp */ -++ int overrange; -++ snd_pcm_uframes_t avail_max; -++ snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */ -++ snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time*/ -++ -++ /* -- HW params -- */ -++ snd_pcm_access_t access; /* access mode */ -++ snd_pcm_format_t format; /* SNDRV_PCM_FORMAT_* */ -++ snd_pcm_subformat_t subformat; /* subformat */ -++ unsigned int rate; /* rate in Hz */ -++ unsigned int channels; /* channels */ -++ snd_pcm_uframes_t period_size; /* period size */ -++ unsigned int periods; /* periods */ -++ snd_pcm_uframes_t buffer_size; /* buffer size */ -++ unsigned int tick_time; /* tick time */ -++ snd_pcm_uframes_t min_align; /* Min alignment for the format */ -++ size_t byte_align; -++ unsigned int frame_bits; -++ unsigned int sample_bits; -++ unsigned int info; -++ unsigned int rate_num; -++ unsigned int rate_den; -++ -++ /* -- SW params -- */ -++ int tstamp_mode; /* mmap timestamp is updated */ -++ unsigned int period_step; -++ unsigned int sleep_min; /* min ticks to sleep */ -++ snd_pcm_uframes_t xfer_align; /* xfer size need to be a multiple */ -++ snd_pcm_uframes_t start_threshold; -++ snd_pcm_uframes_t stop_threshold; -++ snd_pcm_uframes_t silence_threshold; /* Silence filling happens when -++ noise is nearest than this */ -++ snd_pcm_uframes_t silence_size; /* Silence filling size */ -++ snd_pcm_uframes_t boundary; /* pointers wrap point */ -++ -++ snd_pcm_uframes_t silence_start; /* starting pointer to silence area */ -++ snd_pcm_uframes_t silence_filled; /* size filled with silence */ -++ -++ union snd_pcm_sync_id sync; /* hardware synchronization ID */ -++ -++ /* -- mmap -- */ -++ struct snd_pcm_mmap_status *status; -++ struct snd_pcm_mmap_control *control; -++ -++ /* -- locking / scheduling -- */ -++ wait_queue_head_t sleep; -++ struct timer_list tick_timer; -++ struct fasync_struct *fasync; -++ -++ /* -- private section -- */ -++ void *private_data; -++ void (*private_free)(struct snd_pcm_runtime *runtime); -++ -++ /* -- hardware description -- */ -++ struct snd_pcm_hardware hw; -++ struct snd_pcm_hw_constraints hw_constraints; -++ -++ /* -- interrupt callbacks -- */ -++ void (*transfer_ack_begin)(struct snd_pcm_substream *substream); -++ void (*transfer_ack_end)(struct snd_pcm_substream *substream); -++ -++ /* -- timer -- */ -++ unsigned int timer_resolution; /* timer resolution */ -++ -++ /* -- DMA -- */ -++ unsigned char *dma_area; /* DMA area */ -++ dma_addr_t dma_addr; /* physical bus address (not accessible from main CPU) */ -++ size_t dma_bytes; /* size of DMA area */ -++ -++ struct snd_dma_buffer *dma_buffer_p; /* allocated buffer */ -++ -++#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) -++ /* -- OSS things -- */ -++ struct snd_pcm_oss_runtime oss; -++#endif -++}; -++ -++struct snd_pcm_group { /* keep linked substreams */ -++ spinlock_t lock; -++ struct list_head substreams; -++ int count; -++}; -++ -++struct snd_pcm_substream { -++ struct snd_pcm *pcm; -++ struct snd_pcm_str *pstr; -++ void *private_data; /* copied from pcm->private_data */ -++ int number; -++ char name[32]; /* substream name */ -++ int stream; /* stream (direction) */ -++ char latency_id[20]; /* latency identifier */ -++ size_t buffer_bytes_max; /* limit ring buffer size */ -++ struct snd_dma_buffer dma_buffer; -++ unsigned int dma_buf_id; -++ size_t dma_max; -++ /* -- hardware operations -- */ -++ struct snd_pcm_ops *ops; -++ /* -- runtime information -- */ -++ struct snd_pcm_runtime *runtime; -++ /* -- timer section -- */ -++ struct snd_timer *timer; /* timer */ -++ unsigned timer_running: 1; /* time is running */ -++ spinlock_t timer_lock; -++ /* -- next substream -- */ -++ struct snd_pcm_substream *next; -++ /* -- linked substreams -- */ -++ struct list_head link_list; /* linked list member */ -++ struct snd_pcm_group self_group; /* fake group for non linked substream (with substream lock inside) */ -++ struct snd_pcm_group *group; /* pointer to current group */ -++ /* -- assigned files -- */ -++ void *file; -++ int ref_count; -++ atomic_t mmap_count; -++ unsigned int f_flags; -++ void (*pcm_release)(struct snd_pcm_substream *); -++#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) -++ /* -- OSS things -- */ -++ struct snd_pcm_oss_substream oss; -++#endif -++#ifdef CONFIG_SND_VERBOSE_PROCFS -++ struct snd_info_entry *proc_root; -++ struct snd_info_entry *proc_info_entry; -++ struct snd_info_entry *proc_hw_params_entry; -++ struct snd_info_entry *proc_sw_params_entry; -++ struct snd_info_entry *proc_status_entry; -++ struct snd_info_entry *proc_prealloc_entry; -++ struct snd_info_entry *proc_prealloc_max_entry; -++#endif -++ /* misc flags */ -++ unsigned int hw_opened: 1; -++}; -++ -++#define SUBSTREAM_BUSY(substream) ((substream)->ref_count > 0) -++ -++ -++struct snd_pcm_str { -++ int stream; /* stream (direction) */ -++ struct snd_pcm *pcm; -++ /* -- substreams -- */ -++ unsigned int substream_count; -++ unsigned int substream_opened; -++ struct snd_pcm_substream *substream; -++#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) -++ /* -- OSS things -- */ -++ struct snd_pcm_oss_stream oss; -++#endif -++#ifdef CONFIG_SND_VERBOSE_PROCFS -++ struct snd_info_entry *proc_root; -++ struct snd_info_entry *proc_info_entry; -++#ifdef CONFIG_SND_PCM_XRUN_DEBUG -++ unsigned int xrun_debug; /* 0 = disabled, 1 = verbose, 2 = stacktrace */ -++ struct snd_info_entry *proc_xrun_debug_entry; -++#endif -++#endif -++}; -++ -++struct snd_pcm { -++ struct snd_card *card; -++ struct list_head list; -++ unsigned int device; /* device number */ -++ unsigned int info_flags; -++ unsigned short dev_class; -++ unsigned short dev_subclass; -++ char id[64]; -++ char name[80]; -++ struct snd_pcm_str streams[2]; -++ struct mutex open_mutex; -++ wait_queue_head_t open_wait; -++ void *private_data; -++ void (*private_free) (struct snd_pcm *pcm); -++ struct device *dev; /* actual hw device this belongs to */ -++#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) -++ struct snd_pcm_oss oss; -++#endif -++}; -++ -++struct snd_pcm_notify { -++ int (*n_register) (struct snd_pcm * pcm); -++ int (*n_disconnect) (struct snd_pcm * pcm); -++ int (*n_unregister) (struct snd_pcm * pcm); -++ struct list_head list; -++}; -++ -++/* -++ * Registering -++ */ -++ -++extern const struct file_operations snd_pcm_f_ops[2]; -++ -++int snd_pcm_new(struct snd_card *card, char *id, int device, -++ int playback_count, int capture_count, -++ struct snd_pcm **rpcm); -++int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count); -++ -++int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree); -++ -++/* -++ * Native I/O -++ */ -++ -++extern rwlock_t snd_pcm_link_rwlock; -++ -++int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info); -++int snd_pcm_info_user(struct snd_pcm_substream *substream, -++ struct snd_pcm_info __user *info); -++int snd_pcm_status(struct snd_pcm_substream *substream, -++ struct snd_pcm_status *status); -++int snd_pcm_start(struct snd_pcm_substream *substream); -++int snd_pcm_stop(struct snd_pcm_substream *substream, int status); -++int snd_pcm_drain_done(struct snd_pcm_substream *substream); -++#ifdef CONFIG_PM -++int snd_pcm_suspend(struct snd_pcm_substream *substream); -++int snd_pcm_suspend_all(struct snd_pcm *pcm); -++#endif -++int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg); -++int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct file *file, -++ struct snd_pcm_substream **rsubstream); -++void snd_pcm_release_substream(struct snd_pcm_substream *substream); -++int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, struct file *file, -++ struct snd_pcm_substream **rsubstream); -++void snd_pcm_detach_substream(struct snd_pcm_substream *substream); -++void snd_pcm_vma_notify_data(void *client, void *data); -++int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area); -++ -++#if BITS_PER_LONG >= 64 -++ -++static inline void div64_32(u_int64_t *n, u_int32_t div, u_int32_t *rem) -++{ -++ *rem = *n % div; -++ *n /= div; -++} -++ -++#elif defined(i386) -++ -++static inline void div64_32(u_int64_t *n, u_int32_t div, u_int32_t *rem) -++{ -++ u_int32_t low, high; -++ low = *n & 0xffffffff; -++ high = *n >> 32; -++ if (high) { -++ u_int32_t high1 = high % div; -++ high /= div; -++ asm("divl %2":"=a" (low), "=d" (*rem):"rm" (div), "a" (low), "d" (high1)); -++ *n = (u_int64_t)high << 32 | low; -++ } else { -++ *n = low / div; -++ *rem = low % div; -++ } -++} -++#else -++ -++static inline void divl(u_int32_t high, u_int32_t low, -++ u_int32_t div, -++ u_int32_t *q, u_int32_t *r) -++{ -++ u_int64_t n = (u_int64_t)high << 32 | low; -++ u_int64_t d = (u_int64_t)div << 31; -++ u_int32_t q1 = 0; -++ int c = 32; -++ while (n > 0xffffffffU) { -++ q1 <<= 1; -++ if (n >= d) { -++ n -= d; -++ q1 |= 1; -++ } -++ d >>= 1; -++ c--; -++ } -++ q1 <<= c; -++ if (n) { -++ low = n; -++ *q = q1 | (low / div); -++ *r = low % div; -++ } else { -++ *r = 0; -++ *q = q1; -++ } -++ return; -++} -++ -++static inline void div64_32(u_int64_t *n, u_int32_t div, u_int32_t *rem) -++{ -++ u_int32_t low, high; -++ low = *n & 0xffffffff; -++ high = *n >> 32; -++ if (high) { -++ u_int32_t high1 = high % div; -++ u_int32_t low1 = low; -++ high /= div; -++ divl(high1, low1, div, &low, rem); -++ *n = (u_int64_t)high << 32 | low; -++ } else { -++ *n = low / div; -++ *rem = low % div; -++ } -++} -++#endif -++ -++/* -++ * PCM library -++ */ -++ -++static inline int snd_pcm_stream_linked(struct snd_pcm_substream *substream) -++{ -++ return substream->group != &substream->self_group; -++} -++ -++static inline void snd_pcm_stream_lock(struct snd_pcm_substream *substream) -++{ -++ read_lock(&snd_pcm_link_rwlock); -++ spin_lock(&substream->self_group.lock); -++} -++ -++static inline void snd_pcm_stream_unlock(struct snd_pcm_substream *substream) -++{ -++ spin_unlock(&substream->self_group.lock); -++ read_unlock(&snd_pcm_link_rwlock); -++} -++ -++static inline void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream) -++{ -++ read_lock_irq(&snd_pcm_link_rwlock); -++ spin_lock(&substream->self_group.lock); -++} -++ -++static inline void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream) -++{ -++ spin_unlock(&substream->self_group.lock); -++ read_unlock_irq(&snd_pcm_link_rwlock); -++} -++ -++#define snd_pcm_stream_lock_irqsave(substream, flags) \ -++do { \ -++ read_lock_irqsave(&snd_pcm_link_rwlock, (flags)); \ -++ spin_lock(&substream->self_group.lock); \ -++} while (0) -++ -++#define snd_pcm_stream_unlock_irqrestore(substream, flags) \ -++do { \ -++ spin_unlock(&substream->self_group.lock); \ -++ read_unlock_irqrestore(&snd_pcm_link_rwlock, (flags)); \ -++} while (0) -++ -++#define snd_pcm_group_for_each_entry(s, substream) \ -++ list_for_each_entry(s, &substream->group->substreams, link_list) -++ -++static inline int snd_pcm_running(struct snd_pcm_substream *substream) -++{ -++ return (substream->runtime->status->state == SNDRV_PCM_STATE_RUNNING || -++ (substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING && -++ substream->stream == SNDRV_PCM_STREAM_PLAYBACK)); -++} -++ -++static inline ssize_t bytes_to_samples(struct snd_pcm_runtime *runtime, ssize_t size) -++{ -++ return size * 8 / runtime->sample_bits; -++} -++ -++static inline snd_pcm_sframes_t bytes_to_frames(struct snd_pcm_runtime *runtime, ssize_t size) -++{ -++ return size * 8 / runtime->frame_bits; -++} -++ -++static inline ssize_t samples_to_bytes(struct snd_pcm_runtime *runtime, ssize_t size) -++{ -++ return size * runtime->sample_bits / 8; -++} -++ -++static inline ssize_t frames_to_bytes(struct snd_pcm_runtime *runtime, snd_pcm_sframes_t size) -++{ -++ return size * runtime->frame_bits / 8; -++} -++ -++static inline int frame_aligned(struct snd_pcm_runtime *runtime, ssize_t bytes) -++{ -++ return bytes % runtime->byte_align == 0; -++} -++ -++static inline size_t snd_pcm_lib_buffer_bytes(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ return frames_to_bytes(runtime, runtime->buffer_size); -++} -++ -++static inline size_t snd_pcm_lib_period_bytes(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ return frames_to_bytes(runtime, runtime->period_size); -++} -++ -++/* -++ * result is: 0 ... (boundary - 1) -++ */ -++static inline snd_pcm_uframes_t snd_pcm_playback_avail(struct snd_pcm_runtime *runtime) -++{ -++ snd_pcm_sframes_t avail = runtime->status->hw_ptr + runtime->buffer_size - runtime->control->appl_ptr; -++ if (avail < 0) -++ avail += runtime->boundary; -++ else if ((snd_pcm_uframes_t) avail >= runtime->boundary) -++ avail -= runtime->boundary; -++ return avail; -++} -++ -++/* -++ * result is: 0 ... (boundary - 1) -++ */ -++static inline snd_pcm_uframes_t snd_pcm_capture_avail(struct snd_pcm_runtime *runtime) -++{ -++ snd_pcm_sframes_t avail = runtime->status->hw_ptr - runtime->control->appl_ptr; -++ if (avail < 0) -++ avail += runtime->boundary; -++ return avail; -++} -++ -++static inline snd_pcm_sframes_t snd_pcm_playback_hw_avail(struct snd_pcm_runtime *runtime) -++{ -++ return runtime->buffer_size - snd_pcm_playback_avail(runtime); -++} -++ -++static inline snd_pcm_sframes_t snd_pcm_capture_hw_avail(struct snd_pcm_runtime *runtime) -++{ -++ return runtime->buffer_size - snd_pcm_capture_avail(runtime); -++} -++ -++/** -++ * snd_pcm_playback_ready - check whether the playback buffer is available -++ * @substream: the pcm substream instance -++ * -++ * Checks whether enough free space is available on the playback buffer. -++ * -++ * Returns non-zero if available, or zero if not. -++ */ -++static inline int snd_pcm_playback_ready(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ return snd_pcm_playback_avail(runtime) >= runtime->control->avail_min; -++} -++ -++/** -++ * snd_pcm_capture_ready - check whether the capture buffer is available -++ * @substream: the pcm substream instance -++ * -++ * Checks whether enough capture data is available on the capture buffer. -++ * -++ * Returns non-zero if available, or zero if not. -++ */ -++static inline int snd_pcm_capture_ready(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ return snd_pcm_capture_avail(runtime) >= runtime->control->avail_min; -++} -++ -++/** -++ * snd_pcm_playback_data - check whether any data exists on the playback buffer -++ * @substream: the pcm substream instance -++ * -++ * Checks whether any data exists on the playback buffer. If stop_threshold -++ * is bigger or equal to boundary, then this function returns always non-zero. -++ * -++ * Returns non-zero if exists, or zero if not. -++ */ -++static inline int snd_pcm_playback_data(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ -++ if (runtime->stop_threshold >= runtime->boundary) -++ return 1; -++ return snd_pcm_playback_avail(runtime) < runtime->buffer_size; -++} -++ -++/** -++ * snd_pcm_playback_empty - check whether the playback buffer is empty -++ * @substream: the pcm substream instance -++ * -++ * Checks whether the playback buffer is empty. -++ * -++ * Returns non-zero if empty, or zero if not. -++ */ -++static inline int snd_pcm_playback_empty(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ return snd_pcm_playback_avail(runtime) >= runtime->buffer_size; -++} -++ -++/** -++ * snd_pcm_capture_empty - check whether the capture buffer is empty -++ * @substream: the pcm substream instance -++ * -++ * Checks whether the capture buffer is empty. -++ * -++ * Returns non-zero if empty, or zero if not. -++ */ -++static inline int snd_pcm_capture_empty(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ return snd_pcm_capture_avail(runtime) == 0; -++} -++ -++static inline void snd_pcm_trigger_done(struct snd_pcm_substream *substream, -++ struct snd_pcm_substream *master) -++{ -++ substream->runtime->trigger_master = master; -++} -++ -++static inline int hw_is_mask(int var) -++{ -++ return var >= SNDRV_PCM_HW_PARAM_FIRST_MASK && -++ var <= SNDRV_PCM_HW_PARAM_LAST_MASK; -++} -++ -++static inline int hw_is_interval(int var) -++{ -++ return var >= SNDRV_PCM_HW_PARAM_FIRST_INTERVAL && -++ var <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; -++} -++ -++static inline struct snd_mask *hw_param_mask(struct snd_pcm_hw_params *params, -++ snd_pcm_hw_param_t var) -++{ -++ return ¶ms->masks[var - SNDRV_PCM_HW_PARAM_FIRST_MASK]; -++} -++ -++static inline struct snd_interval *hw_param_interval(struct snd_pcm_hw_params *params, -++ snd_pcm_hw_param_t var) -++{ -++ return ¶ms->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]; -++} -++ -++static inline const struct snd_mask *hw_param_mask_c(const struct snd_pcm_hw_params *params, -++ snd_pcm_hw_param_t var) -++{ -++ return ¶ms->masks[var - SNDRV_PCM_HW_PARAM_FIRST_MASK]; -++} -++ -++static inline const struct snd_interval *hw_param_interval_c(const struct snd_pcm_hw_params *params, -++ snd_pcm_hw_param_t var) -++{ -++ return ¶ms->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]; -++} -++ -++#define params_access(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_ACCESS)) -++#define params_format(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_FORMAT)) -++#define params_subformat(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_SUBFORMAT)) -++#define params_channels(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_CHANNELS)->min -++#define params_rate(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_RATE)->min -++#define params_period_size(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_PERIOD_SIZE)->min -++#define params_period_bytes(p) ((params_period_size(p)*snd_pcm_format_physical_width(params_format(p))*params_channels(p))/8) -++#define params_periods(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_PERIODS)->min -++#define params_buffer_size(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_BUFFER_SIZE)->min -++#define params_buffer_bytes(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_BUFFER_BYTES)->min -++#define params_tick_time(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_TICK_TIME)->min -++ -++ -++int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v); -++void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c); -++void snd_interval_div(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c); -++void snd_interval_muldivk(const struct snd_interval *a, const struct snd_interval *b, -++ unsigned int k, struct snd_interval *c); -++void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k, -++ const struct snd_interval *b, struct snd_interval *c); -++int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask); -++int snd_interval_ratnum(struct snd_interval *i, -++ unsigned int rats_count, struct snd_ratnum *rats, -++ unsigned int *nump, unsigned int *denp); -++ -++void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params); -++void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var); -++int snd_pcm_hw_params_choose(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); -++ -++int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); -++ -++int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream); -++int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream); -++ -++int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, -++ u_int32_t mask); -++int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, -++ u_int64_t mask); -++int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, -++ unsigned int min, unsigned int max); -++int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var); -++int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime, -++ unsigned int cond, -++ snd_pcm_hw_param_t var, -++ struct snd_pcm_hw_constraint_list *l); -++int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime, -++ unsigned int cond, -++ snd_pcm_hw_param_t var, -++ struct snd_pcm_hw_constraint_ratnums *r); -++int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime, -++ unsigned int cond, -++ snd_pcm_hw_param_t var, -++ struct snd_pcm_hw_constraint_ratdens *r); -++int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime, -++ unsigned int cond, -++ unsigned int width, -++ unsigned int msbits); -++int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime, -++ unsigned int cond, -++ snd_pcm_hw_param_t var, -++ unsigned long step); -++int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime, -++ unsigned int cond, -++ snd_pcm_hw_param_t var); -++int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, -++ unsigned int cond, -++ int var, -++ snd_pcm_hw_rule_func_t func, void *private, -++ int dep, ...); -++ -++int snd_pcm_format_signed(snd_pcm_format_t format); -++int snd_pcm_format_unsigned(snd_pcm_format_t format); -++int snd_pcm_format_linear(snd_pcm_format_t format); -++int snd_pcm_format_little_endian(snd_pcm_format_t format); -++int snd_pcm_format_big_endian(snd_pcm_format_t format); -++#if 0 /* just for DocBook */ -++/** -++ * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian -++ * @format: the format to check -++ * -++ * Returns 1 if the given PCM format is CPU-endian, 0 if -++ * opposite, or a negative error code if endian not specified. -++ */ -++int snd_pcm_format_cpu_endian(snd_pcm_format_t format); -++#endif /* DocBook */ -++#ifdef SNDRV_LITTLE_ENDIAN -++#define snd_pcm_format_cpu_endian(format) snd_pcm_format_little_endian(format) -++#else -++#define snd_pcm_format_cpu_endian(format) snd_pcm_format_big_endian(format) -++#endif -++int snd_pcm_format_width(snd_pcm_format_t format); /* in bits */ -++int snd_pcm_format_physical_width(snd_pcm_format_t format); /* in bits */ -++ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples); -++const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format); -++int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames); -++snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian); -++ -++void snd_pcm_set_ops(struct snd_pcm * pcm, int direction, struct snd_pcm_ops *ops); -++void snd_pcm_set_sync(struct snd_pcm_substream *substream); -++int snd_pcm_lib_interleave_len(struct snd_pcm_substream *substream); -++int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, -++ unsigned int cmd, void *arg); -++int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream); -++int snd_pcm_playback_xrun_check(struct snd_pcm_substream *substream); -++int snd_pcm_capture_xrun_check(struct snd_pcm_substream *substream); -++int snd_pcm_playback_xrun_asap(struct snd_pcm_substream *substream); -++int snd_pcm_capture_xrun_asap(struct snd_pcm_substream *substream); -++void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_uframes_t new_hw_ptr); -++void snd_pcm_tick_prepare(struct snd_pcm_substream *substream); -++void snd_pcm_tick_set(struct snd_pcm_substream *substream, unsigned long ticks); -++void snd_pcm_tick_elapsed(struct snd_pcm_substream *substream); -++void snd_pcm_period_elapsed(struct snd_pcm_substream *substream); -++snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, -++ const void __user *buf, -++ snd_pcm_uframes_t frames); -++snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, -++ void __user *buf, snd_pcm_uframes_t frames); -++snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream, -++ void __user **bufs, snd_pcm_uframes_t frames); -++snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream, -++ void __user **bufs, snd_pcm_uframes_t frames); -++ -++extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates; -++ -++int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime); -++unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate); -++ -++static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substream, -++ struct snd_dma_buffer *bufp) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ if (bufp) { -++ runtime->dma_buffer_p = bufp; -++ runtime->dma_area = bufp->area; -++ runtime->dma_addr = bufp->addr; -++ runtime->dma_bytes = bufp->bytes; -++ } else { -++ runtime->dma_buffer_p = NULL; -++ runtime->dma_area = NULL; -++ runtime->dma_addr = 0; -++ runtime->dma_bytes = 0; -++ } -++} -++ -++/* -++ * Timer interface -++ */ -++ -++void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream); -++void snd_pcm_timer_init(struct snd_pcm_substream *substream); -++void snd_pcm_timer_done(struct snd_pcm_substream *substream); -++ -++/* -++ * Memory -++ */ -++ -++int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream); -++int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm); -++int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream, -++ int type, struct device *data, -++ size_t size, size_t max); -++int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm, -++ int type, void *data, -++ size_t size, size_t max); -++int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size); -++int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream); -++ -++#define snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_buffer_p->private_data) -++#define snd_pcm_sgbuf_pages(size) snd_sgbuf_aligned_pages(size) -++#define snd_pcm_sgbuf_get_addr(sgbuf,ofs) snd_sgbuf_get_addr(sgbuf,ofs) -++struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset); -++ -++/* handle mmap counter - PCM mmap callback should handle this counter properly */ -++static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) -++{ -++ struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; -++ atomic_inc(&substream->mmap_count); -++} -++ -++static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area) -++{ -++ struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; -++ atomic_dec(&substream->mmap_count); -++} -++ -++/* mmap for io-memory area */ -++#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA) -++#define SNDRV_PCM_INFO_MMAP_IOMEM SNDRV_PCM_INFO_MMAP -++int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, struct vm_area_struct *area); -++#else -++#define SNDRV_PCM_INFO_MMAP_IOMEM 0 -++#define snd_pcm_lib_mmap_iomem NULL -++#endif -++ -++static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max) -++{ -++ *max = dma < 4 ? 64 * 1024 : 128 * 1024; -++} -++ -++/* -++ * Misc -++ */ -++ -++#define SNDRV_PCM_DEFAULT_CON_SPDIF (IEC958_AES0_CON_EMPHASIS_NONE|\ -++ (IEC958_AES1_CON_ORIGINAL<<8)|\ -++ (IEC958_AES1_CON_PCM_CODER<<8)|\ -++ (IEC958_AES3_CON_FS_48000<<24)) -++ -++#endif /* __SOUND_PCM_H */ -+diff -urN linux-2.6.24.7.old/init/do_mounts.c linux-2.6.24.7/init/do_mounts.c -+--- linux-2.6.24.7.old/init/do_mounts.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/init/do_mounts.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -440,7 +440,9 @@ -+ -+ if (saved_root_name[0]) { -+ root_device_name = saved_root_name; -+- if (!strncmp(root_device_name, "mtd", 3)) { -++ if (!strncmp(root_device_name, "mtd", 3) || -++ !strncmp(root_device_name, "ubi", 3) || -++ !strncmp(root_device_name, "mmc", 3)) { -+ mount_block_root(root_device_name, root_mountflags); -+ goto out; -+ } -+diff -urN linux-2.6.24.7.old/sound/core/pcm_native.c linux-2.6.24.7/sound/core/pcm_native.c -+--- linux-2.6.24.7.old/sound/core/pcm_native.c 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/sound/core/pcm_native.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -1780,12 +1780,13 @@ -+ return snd_interval_refine(hw_param_interval(params, rule->var), &t); -+ } -+ -+-#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12 -++#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 14 -+ #error "Change this table" -+ #endif -+ -+-static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, -+- 48000, 64000, 88200, 96000, 176400, 192000 }; -++static unsigned int rates[] = { 5512, 8000, 11025, 12000, 16000, 22050, 24000, -++ 32000, 44100, 48000, 64000, 88200, 96000, -++ 176400, 192000 }; -+ -+ const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = { -+ .count = ARRAY_SIZE(rates), -+@@ -1796,9 +1797,17 @@ -+ struct snd_pcm_hw_rule *rule) -+ { -+ struct snd_pcm_hardware *hw = rule->private; -++#if 0 -+ return snd_interval_list(hw_param_interval(params, rule->var), -+ snd_pcm_known_rates.count, -+ snd_pcm_known_rates.list, hw->rates); -++#else -++ //printk("hw->rates=0x%08x\n",hw->rates);//0x3b6 -++ hw->rates = 0x3fe;//12KHz and 24KHz bits are all zero,you need set 1 -++ return snd_interval_list(hw_param_interval(params, rule->var), -++ snd_pcm_known_rates.count, -++ snd_pcm_known_rates.list, hw->rates); -++#endif -+ } -+ -+ static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params, -+diff -urN linux-2.6.24.7.old/sound/core/pcm_native.c.org linux-2.6.24.7/sound/core/pcm_native.c.org -+--- linux-2.6.24.7.old/sound/core/pcm_native.c.org 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/core/pcm_native.c.org 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,3451 @@ -++/* -++ * Digital Audio (PCM) abstract layer -++ * Copyright (c) by Jaroslav Kysela -++ * -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License as published by -++ * the Free Software Foundation; either version 2 of the License, or -++ * (at your option) any later version. -++ * -++ * This program is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -++ * GNU General Public License for more details. -++ * -++ * You should have received a copy of the GNU General Public License -++ * along with this program; if not, write to the Free Software -++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++/* -++ * Compatibility -++ */ -++ -++struct snd_pcm_hw_params_old { -++ unsigned int flags; -++ unsigned int masks[SNDRV_PCM_HW_PARAM_SUBFORMAT - -++ SNDRV_PCM_HW_PARAM_ACCESS + 1]; -++ struct snd_interval intervals[SNDRV_PCM_HW_PARAM_TICK_TIME - -++ SNDRV_PCM_HW_PARAM_SAMPLE_BITS + 1]; -++ unsigned int rmask; -++ unsigned int cmask; -++ unsigned int info; -++ unsigned int msbits; -++ unsigned int rate_num; -++ unsigned int rate_den; -++ snd_pcm_uframes_t fifo_size; -++ unsigned char reserved[64]; -++}; -++ -++#ifdef CONFIG_SND_SUPPORT_OLD_API -++#define SNDRV_PCM_IOCTL_HW_REFINE_OLD _IOWR('A', 0x10, struct snd_pcm_hw_params_old) -++#define SNDRV_PCM_IOCTL_HW_PARAMS_OLD _IOWR('A', 0x11, struct snd_pcm_hw_params_old) -++ -++static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream, -++ struct snd_pcm_hw_params_old __user * _oparams); -++static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream, -++ struct snd_pcm_hw_params_old __user * _oparams); -++#endif -++static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream); -++ -++/* -++ * -++ */ -++ -++DEFINE_RWLOCK(snd_pcm_link_rwlock); -++EXPORT_SYMBOL(snd_pcm_link_rwlock); -++ -++static DECLARE_RWSEM(snd_pcm_link_rwsem); -++ -++static inline mm_segment_t snd_enter_user(void) -++{ -++ mm_segment_t fs = get_fs(); -++ set_fs(get_ds()); -++ return fs; -++} -++ -++static inline void snd_leave_user(mm_segment_t fs) -++{ -++ set_fs(fs); -++} -++ -++ -++ -++int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info) -++{ -++ struct snd_pcm_runtime *runtime; -++ struct snd_pcm *pcm = substream->pcm; -++ struct snd_pcm_str *pstr = substream->pstr; -++ -++ snd_assert(substream != NULL, return -ENXIO); -++ memset(info, 0, sizeof(*info)); -++ info->card = pcm->card->number; -++ info->device = pcm->device; -++ info->stream = substream->stream; -++ info->subdevice = substream->number; -++ strlcpy(info->id, pcm->id, sizeof(info->id)); -++ strlcpy(info->name, pcm->name, sizeof(info->name)); -++ info->dev_class = pcm->dev_class; -++ info->dev_subclass = pcm->dev_subclass; -++ info->subdevices_count = pstr->substream_count; -++ info->subdevices_avail = pstr->substream_count - pstr->substream_opened; -++ strlcpy(info->subname, substream->name, sizeof(info->subname)); -++ runtime = substream->runtime; -++ /* AB: FIXME!!! This is definitely nonsense */ -++ if (runtime) { -++ info->sync = runtime->sync; -++ substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info); -++ } -++ return 0; -++} -++ -++int snd_pcm_info_user(struct snd_pcm_substream *substream, -++ struct snd_pcm_info __user * _info) -++{ -++ struct snd_pcm_info *info; -++ int err; -++ -++ info = kmalloc(sizeof(*info), GFP_KERNEL); -++ if (! info) -++ return -ENOMEM; -++ err = snd_pcm_info(substream, info); -++ if (err >= 0) { -++ if (copy_to_user(_info, info, sizeof(*info))) -++ err = -EFAULT; -++ } -++ kfree(info); -++ return err; -++} -++ -++#undef RULES_DEBUG -++ -++#ifdef RULES_DEBUG -++#define HW_PARAM(v) [SNDRV_PCM_HW_PARAM_##v] = #v -++char *snd_pcm_hw_param_names[] = { -++ HW_PARAM(ACCESS), -++ HW_PARAM(FORMAT), -++ HW_PARAM(SUBFORMAT), -++ HW_PARAM(SAMPLE_BITS), -++ HW_PARAM(FRAME_BITS), -++ HW_PARAM(CHANNELS), -++ HW_PARAM(RATE), -++ HW_PARAM(PERIOD_TIME), -++ HW_PARAM(PERIOD_SIZE), -++ HW_PARAM(PERIOD_BYTES), -++ HW_PARAM(PERIODS), -++ HW_PARAM(BUFFER_TIME), -++ HW_PARAM(BUFFER_SIZE), -++ HW_PARAM(BUFFER_BYTES), -++ HW_PARAM(TICK_TIME), -++}; -++#endif -++ -++int snd_pcm_hw_refine(struct snd_pcm_substream *substream, -++ struct snd_pcm_hw_params *params) -++{ -++ unsigned int k; -++ struct snd_pcm_hardware *hw; -++ struct snd_interval *i = NULL; -++ struct snd_mask *m = NULL; -++ struct snd_pcm_hw_constraints *constrs = &substream->runtime->hw_constraints; -++ unsigned int rstamps[constrs->rules_num]; -++ unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1]; -++ unsigned int stamp = 2; -++ int changed, again; -++ -++ params->info = 0; -++ params->fifo_size = 0; -++ if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS)) -++ params->msbits = 0; -++ if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) { -++ params->rate_num = 0; -++ params->rate_den = 0; -++ } -++ -++ for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) { -++ m = hw_param_mask(params, k); -++ if (snd_mask_empty(m)) -++ return -EINVAL; -++ if (!(params->rmask & (1 << k))) -++ continue; -++#ifdef RULES_DEBUG -++ printk("%s = ", snd_pcm_hw_param_names[k]); -++ printk("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); -++#endif -++ changed = snd_mask_refine(m, constrs_mask(constrs, k)); -++#ifdef RULES_DEBUG -++ printk("%04x%04x%04x%04x\n", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); -++#endif -++ if (changed) -++ params->cmask |= 1 << k; -++ if (changed < 0) -++ return changed; -++ } -++ -++ for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) { -++ i = hw_param_interval(params, k); -++ if (snd_interval_empty(i)) -++ return -EINVAL; -++ if (!(params->rmask & (1 << k))) -++ continue; -++#ifdef RULES_DEBUG -++ printk("%s = ", snd_pcm_hw_param_names[k]); -++ if (i->empty) -++ printk("empty"); -++ else -++ printk("%c%u %u%c", -++ i->openmin ? '(' : '[', i->min, -++ i->max, i->openmax ? ')' : ']'); -++ printk(" -> "); -++#endif -++ changed = snd_interval_refine(i, constrs_interval(constrs, k)); -++#ifdef RULES_DEBUG -++ if (i->empty) -++ printk("empty\n"); -++ else -++ printk("%c%u %u%c\n", -++ i->openmin ? '(' : '[', i->min, -++ i->max, i->openmax ? ')' : ']'); -++#endif -++ if (changed) -++ params->cmask |= 1 << k; -++ if (changed < 0) -++ return changed; -++ } -++ -++ for (k = 0; k < constrs->rules_num; k++) -++ rstamps[k] = 0; -++ for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) -++ vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0; -++ do { -++ again = 0; -++ for (k = 0; k < constrs->rules_num; k++) { -++ struct snd_pcm_hw_rule *r = &constrs->rules[k]; -++ unsigned int d; -++ int doit = 0; -++ if (r->cond && !(r->cond & params->flags)) -++ continue; -++ for (d = 0; r->deps[d] >= 0; d++) { -++ if (vstamps[r->deps[d]] > rstamps[k]) { -++ doit = 1; -++ break; -++ } -++ } -++ if (!doit) -++ continue; -++#ifdef RULES_DEBUG -++ printk("Rule %d [%p]: ", k, r->func); -++ if (r->var >= 0) { -++ printk("%s = ", snd_pcm_hw_param_names[r->var]); -++ if (hw_is_mask(r->var)) { -++ m = hw_param_mask(params, r->var); -++ printk("%x", *m->bits); -++ } else { -++ i = hw_param_interval(params, r->var); -++ if (i->empty) -++ printk("empty"); -++ else -++ printk("%c%u %u%c", -++ i->openmin ? '(' : '[', i->min, -++ i->max, i->openmax ? ')' : ']'); -++ } -++ } -++#endif -++ changed = r->func(params, r); -++#ifdef RULES_DEBUG -++ if (r->var >= 0) { -++ printk(" -> "); -++ if (hw_is_mask(r->var)) -++ printk("%x", *m->bits); -++ else { -++ if (i->empty) -++ printk("empty"); -++ else -++ printk("%c%u %u%c", -++ i->openmin ? '(' : '[', i->min, -++ i->max, i->openmax ? ')' : ']'); -++ } -++ } -++ printk("\n"); -++#endif -++ rstamps[k] = stamp; -++ if (changed && r->var >= 0) { -++ params->cmask |= (1 << r->var); -++ vstamps[r->var] = stamp; -++ again = 1; -++ } -++ if (changed < 0) -++ return changed; -++ stamp++; -++ } -++ } while (again); -++ if (!params->msbits) { -++ i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); -++ if (snd_interval_single(i)) -++ params->msbits = snd_interval_value(i); -++ } -++ -++ if (!params->rate_den) { -++ i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); -++ if (snd_interval_single(i)) { -++ params->rate_num = snd_interval_value(i); -++ params->rate_den = 1; -++ } -++ } -++ -++ hw = &substream->runtime->hw; -++ if (!params->info) -++ params->info = hw->info; -++ if (!params->fifo_size) -++ params->fifo_size = hw->fifo_size; -++ params->rmask = 0; -++ return 0; -++} -++ -++EXPORT_SYMBOL(snd_pcm_hw_refine); -++ -++static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream, -++ struct snd_pcm_hw_params __user * _params) -++{ -++ struct snd_pcm_hw_params *params; -++ int err; -++ -++ params = kmalloc(sizeof(*params), GFP_KERNEL); -++ if (!params) { -++ err = -ENOMEM; -++ goto out; -++ } -++ if (copy_from_user(params, _params, sizeof(*params))) { -++ err = -EFAULT; -++ goto out; -++ } -++ err = snd_pcm_hw_refine(substream, params); -++ if (copy_to_user(_params, params, sizeof(*params))) { -++ if (!err) -++ err = -EFAULT; -++ } -++out: -++ kfree(params); -++ return err; -++} -++ -++static int period_to_usecs(struct snd_pcm_runtime *runtime) -++{ -++ int usecs; -++ -++ if (! runtime->rate) -++ return -1; /* invalid */ -++ -++ /* take 75% of period time as the deadline */ -++ usecs = (750000 / runtime->rate) * runtime->period_size; -++ usecs += ((750000 % runtime->rate) * runtime->period_size) / -++ runtime->rate; -++ -++ return usecs; -++} -++ -++static int snd_pcm_hw_params(struct snd_pcm_substream *substream, -++ struct snd_pcm_hw_params *params) -++{ -++ struct snd_pcm_runtime *runtime; -++ int err, usecs; -++ unsigned int bits; -++ snd_pcm_uframes_t frames; -++ -++ snd_assert(substream != NULL, return -ENXIO); -++ runtime = substream->runtime; -++ snd_assert(runtime != NULL, return -ENXIO); -++ snd_pcm_stream_lock_irq(substream); -++ switch (runtime->status->state) { -++ case SNDRV_PCM_STATE_OPEN: -++ case SNDRV_PCM_STATE_SETUP: -++ case SNDRV_PCM_STATE_PREPARED: -++ break; -++ default: -++ snd_pcm_stream_unlock_irq(substream); -++ return -EBADFD; -++ } -++ snd_pcm_stream_unlock_irq(substream); -++#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) -++ if (!substream->oss.oss) -++#endif -++ if (atomic_read(&substream->mmap_count)) -++ return -EBADFD; -++ -++ params->rmask = ~0U; -++ err = snd_pcm_hw_refine(substream, params); -++ if (err < 0) -++ goto _error; -++ -++ err = snd_pcm_hw_params_choose(substream, params); -++ if (err < 0) -++ goto _error; -++ -++ if (substream->ops->hw_params != NULL) { -++ err = substream->ops->hw_params(substream, params); -++ if (err < 0) -++ goto _error; -++ } -++ -++ runtime->access = params_access(params); -++ runtime->format = params_format(params); -++ runtime->subformat = params_subformat(params); -++ runtime->channels = params_channels(params); -++ runtime->rate = params_rate(params); -++ runtime->period_size = params_period_size(params); -++ runtime->periods = params_periods(params); -++ runtime->buffer_size = params_buffer_size(params); -++ runtime->tick_time = params_tick_time(params); -++ runtime->info = params->info; -++ runtime->rate_num = params->rate_num; -++ runtime->rate_den = params->rate_den; -++ -++ bits = snd_pcm_format_physical_width(runtime->format); -++ runtime->sample_bits = bits; -++ bits *= runtime->channels; -++ runtime->frame_bits = bits; -++ frames = 1; -++ while (bits % 8 != 0) { -++ bits *= 2; -++ frames *= 2; -++ } -++ runtime->byte_align = bits / 8; -++ runtime->min_align = frames; -++ -++ /* Default sw params */ -++ runtime->tstamp_mode = SNDRV_PCM_TSTAMP_NONE; -++ runtime->period_step = 1; -++ runtime->sleep_min = 0; -++ runtime->control->avail_min = runtime->period_size; -++ runtime->xfer_align = runtime->period_size; -++ runtime->start_threshold = 1; -++ runtime->stop_threshold = runtime->buffer_size; -++ runtime->silence_threshold = 0; -++ runtime->silence_size = 0; -++ runtime->boundary = runtime->buffer_size; -++ while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size) -++ runtime->boundary *= 2; -++ -++ snd_pcm_timer_resolution_change(substream); -++ runtime->status->state = SNDRV_PCM_STATE_SETUP; -++ -++ remove_acceptable_latency(substream->latency_id); -++ if ((usecs = period_to_usecs(runtime)) >= 0) -++ set_acceptable_latency(substream->latency_id, usecs); -++ return 0; -++ _error: -++ /* hardware might be unuseable from this time, -++ so we force application to retry to set -++ the correct hardware parameter settings */ -++ runtime->status->state = SNDRV_PCM_STATE_OPEN; -++ if (substream->ops->hw_free != NULL) -++ substream->ops->hw_free(substream); -++ return err; -++} -++ -++static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream, -++ struct snd_pcm_hw_params __user * _params) -++{ -++ struct snd_pcm_hw_params *params; -++ int err; -++ -++ params = kmalloc(sizeof(*params), GFP_KERNEL); -++ if (!params) { -++ err = -ENOMEM; -++ goto out; -++ } -++ if (copy_from_user(params, _params, sizeof(*params))) { -++ err = -EFAULT; -++ goto out; -++ } -++ err = snd_pcm_hw_params(substream, params); -++ if (copy_to_user(_params, params, sizeof(*params))) { -++ if (!err) -++ err = -EFAULT; -++ } -++out: -++ kfree(params); -++ return err; -++} -++ -++static int snd_pcm_hw_free(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime; -++ int result = 0; -++ -++ snd_assert(substream != NULL, return -ENXIO); -++ runtime = substream->runtime; -++ snd_assert(runtime != NULL, return -ENXIO); -++ snd_pcm_stream_lock_irq(substream); -++ switch (runtime->status->state) { -++ case SNDRV_PCM_STATE_SETUP: -++ case SNDRV_PCM_STATE_PREPARED: -++ break; -++ default: -++ snd_pcm_stream_unlock_irq(substream); -++ return -EBADFD; -++ } -++ snd_pcm_stream_unlock_irq(substream); -++ if (atomic_read(&substream->mmap_count)) -++ return -EBADFD; -++ if (substream->ops->hw_free) -++ result = substream->ops->hw_free(substream); -++ runtime->status->state = SNDRV_PCM_STATE_OPEN; -++ remove_acceptable_latency(substream->latency_id); -++ return result; -++} -++ -++static int snd_pcm_sw_params(struct snd_pcm_substream *substream, -++ struct snd_pcm_sw_params *params) -++{ -++ struct snd_pcm_runtime *runtime; -++ -++ snd_assert(substream != NULL, return -ENXIO); -++ runtime = substream->runtime; -++ snd_assert(runtime != NULL, return -ENXIO); -++ snd_pcm_stream_lock_irq(substream); -++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { -++ snd_pcm_stream_unlock_irq(substream); -++ return -EBADFD; -++ } -++ snd_pcm_stream_unlock_irq(substream); -++ -++ if (params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST) -++ return -EINVAL; -++ if (params->avail_min == 0) -++ return -EINVAL; -++ if (params->xfer_align == 0 || -++ params->xfer_align % runtime->min_align != 0) -++ return -EINVAL; -++ if (params->silence_size >= runtime->boundary) { -++ if (params->silence_threshold != 0) -++ return -EINVAL; -++ } else { -++ if (params->silence_size > params->silence_threshold) -++ return -EINVAL; -++ if (params->silence_threshold > runtime->buffer_size) -++ return -EINVAL; -++ } -++ snd_pcm_stream_lock_irq(substream); -++ runtime->tstamp_mode = params->tstamp_mode; -++ runtime->sleep_min = params->sleep_min; -++ runtime->period_step = params->period_step; -++ runtime->control->avail_min = params->avail_min; -++ runtime->start_threshold = params->start_threshold; -++ runtime->stop_threshold = params->stop_threshold; -++ runtime->silence_threshold = params->silence_threshold; -++ runtime->silence_size = params->silence_size; -++ runtime->xfer_align = params->xfer_align; -++ params->boundary = runtime->boundary; -++ if (snd_pcm_running(substream)) { -++ if (runtime->sleep_min) -++ snd_pcm_tick_prepare(substream); -++ else -++ snd_pcm_tick_set(substream, 0); -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && -++ runtime->silence_size > 0) -++ snd_pcm_playback_silence(substream, ULONG_MAX); -++ wake_up(&runtime->sleep); -++ } -++ snd_pcm_stream_unlock_irq(substream); -++ return 0; -++} -++ -++static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream, -++ struct snd_pcm_sw_params __user * _params) -++{ -++ struct snd_pcm_sw_params params; -++ int err; -++ if (copy_from_user(¶ms, _params, sizeof(params))) -++ return -EFAULT; -++ err = snd_pcm_sw_params(substream, ¶ms); -++ if (copy_to_user(_params, ¶ms, sizeof(params))) -++ return -EFAULT; -++ return err; -++} -++ -++int snd_pcm_status(struct snd_pcm_substream *substream, -++ struct snd_pcm_status *status) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ -++ snd_pcm_stream_lock_irq(substream); -++ status->state = runtime->status->state; -++ status->suspended_state = runtime->status->suspended_state; -++ if (status->state == SNDRV_PCM_STATE_OPEN) -++ goto _end; -++ status->trigger_tstamp = runtime->trigger_tstamp; -++ if (snd_pcm_running(substream)) { -++ snd_pcm_update_hw_ptr(substream); -++ if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP) -++ status->tstamp = runtime->status->tstamp; -++ else -++ getnstimeofday(&status->tstamp); -++ } else -++ getnstimeofday(&status->tstamp); -++ status->appl_ptr = runtime->control->appl_ptr; -++ status->hw_ptr = runtime->status->hw_ptr; -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -++ status->avail = snd_pcm_playback_avail(runtime); -++ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING || -++ runtime->status->state == SNDRV_PCM_STATE_DRAINING) -++ status->delay = runtime->buffer_size - status->avail; -++ else -++ status->delay = 0; -++ } else { -++ status->avail = snd_pcm_capture_avail(runtime); -++ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) -++ status->delay = status->avail; -++ else -++ status->delay = 0; -++ } -++ status->avail_max = runtime->avail_max; -++ status->overrange = runtime->overrange; -++ runtime->avail_max = 0; -++ runtime->overrange = 0; -++ _end: -++ snd_pcm_stream_unlock_irq(substream); -++ return 0; -++} -++ -++static int snd_pcm_status_user(struct snd_pcm_substream *substream, -++ struct snd_pcm_status __user * _status) -++{ -++ struct snd_pcm_status status; -++ struct snd_pcm_runtime *runtime; -++ int res; -++ -++ snd_assert(substream != NULL, return -ENXIO); -++ runtime = substream->runtime; -++ memset(&status, 0, sizeof(status)); -++ res = snd_pcm_status(substream, &status); -++ if (res < 0) -++ return res; -++ if (copy_to_user(_status, &status, sizeof(status))) -++ return -EFAULT; -++ return 0; -++} -++ -++static int snd_pcm_channel_info(struct snd_pcm_substream *substream, -++ struct snd_pcm_channel_info * info) -++{ -++ struct snd_pcm_runtime *runtime; -++ unsigned int channel; -++ -++ snd_assert(substream != NULL, return -ENXIO); -++ channel = info->channel; -++ runtime = substream->runtime; -++ snd_pcm_stream_lock_irq(substream); -++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { -++ snd_pcm_stream_unlock_irq(substream); -++ return -EBADFD; -++ } -++ snd_pcm_stream_unlock_irq(substream); -++ if (channel >= runtime->channels) -++ return -EINVAL; -++ memset(info, 0, sizeof(*info)); -++ info->channel = channel; -++ return substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, info); -++} -++ -++static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream, -++ struct snd_pcm_channel_info __user * _info) -++{ -++ struct snd_pcm_channel_info info; -++ int res; -++ -++ if (copy_from_user(&info, _info, sizeof(info))) -++ return -EFAULT; -++ res = snd_pcm_channel_info(substream, &info); -++ if (res < 0) -++ return res; -++ if (copy_to_user(_info, &info, sizeof(info))) -++ return -EFAULT; -++ return 0; -++} -++ -++static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ if (runtime->trigger_master == NULL) -++ return; -++ if (runtime->trigger_master == substream) { -++ getnstimeofday(&runtime->trigger_tstamp); -++ } else { -++ snd_pcm_trigger_tstamp(runtime->trigger_master); -++ runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp; -++ } -++ runtime->trigger_master = NULL; -++} -++ -++struct action_ops { -++ int (*pre_action)(struct snd_pcm_substream *substream, int state); -++ int (*do_action)(struct snd_pcm_substream *substream, int state); -++ void (*undo_action)(struct snd_pcm_substream *substream, int state); -++ void (*post_action)(struct snd_pcm_substream *substream, int state); -++}; -++ -++/* -++ * this functions is core for handling of linked stream -++ * Note: the stream state might be changed also on failure -++ * Note2: call with calling stream lock + link lock -++ */ -++static int snd_pcm_action_group(struct action_ops *ops, -++ struct snd_pcm_substream *substream, -++ int state, int do_lock) -++{ -++ struct snd_pcm_substream *s = NULL; -++ struct snd_pcm_substream *s1; -++ int res = 0; -++ -++ snd_pcm_group_for_each_entry(s, substream) { -++ if (do_lock && s != substream) -++ spin_lock_nested(&s->self_group.lock, -++ SINGLE_DEPTH_NESTING); -++ res = ops->pre_action(s, state); -++ if (res < 0) -++ goto _unlock; -++ } -++ snd_pcm_group_for_each_entry(s, substream) { -++ res = ops->do_action(s, state); -++ if (res < 0) { -++ if (ops->undo_action) { -++ snd_pcm_group_for_each_entry(s1, substream) { -++ if (s1 == s) /* failed stream */ -++ break; -++ ops->undo_action(s1, state); -++ } -++ } -++ s = NULL; /* unlock all */ -++ goto _unlock; -++ } -++ } -++ snd_pcm_group_for_each_entry(s, substream) { -++ ops->post_action(s, state); -++ } -++ _unlock: -++ if (do_lock) { -++ /* unlock streams */ -++ snd_pcm_group_for_each_entry(s1, substream) { -++ if (s1 != substream) -++ spin_unlock(&s1->self_group.lock); -++ if (s1 == s) /* end */ -++ break; -++ } -++ } -++ return res; -++} -++ -++/* -++ * Note: call with stream lock -++ */ -++static int snd_pcm_action_single(struct action_ops *ops, -++ struct snd_pcm_substream *substream, -++ int state) -++{ -++ int res; -++ -++ res = ops->pre_action(substream, state); -++ if (res < 0) -++ return res; -++ res = ops->do_action(substream, state); -++ if (res == 0) -++ ops->post_action(substream, state); -++ else if (ops->undo_action) -++ ops->undo_action(substream, state); -++ return res; -++} -++ -++/* -++ * Note: call with stream lock -++ */ -++static int snd_pcm_action(struct action_ops *ops, -++ struct snd_pcm_substream *substream, -++ int state) -++{ -++ int res; -++ -++ if (snd_pcm_stream_linked(substream)) { -++ if (!spin_trylock(&substream->group->lock)) { -++ spin_unlock(&substream->self_group.lock); -++ spin_lock(&substream->group->lock); -++ spin_lock(&substream->self_group.lock); -++ } -++ res = snd_pcm_action_group(ops, substream, state, 1); -++ spin_unlock(&substream->group->lock); -++ } else { -++ res = snd_pcm_action_single(ops, substream, state); -++ } -++ return res; -++} -++ -++/* -++ * Note: don't use any locks before -++ */ -++static int snd_pcm_action_lock_irq(struct action_ops *ops, -++ struct snd_pcm_substream *substream, -++ int state) -++{ -++ int res; -++ -++ read_lock_irq(&snd_pcm_link_rwlock); -++ if (snd_pcm_stream_linked(substream)) { -++ spin_lock(&substream->group->lock); -++ spin_lock(&substream->self_group.lock); -++ res = snd_pcm_action_group(ops, substream, state, 1); -++ spin_unlock(&substream->self_group.lock); -++ spin_unlock(&substream->group->lock); -++ } else { -++ spin_lock(&substream->self_group.lock); -++ res = snd_pcm_action_single(ops, substream, state); -++ spin_unlock(&substream->self_group.lock); -++ } -++ read_unlock_irq(&snd_pcm_link_rwlock); -++ return res; -++} -++ -++/* -++ */ -++static int snd_pcm_action_nonatomic(struct action_ops *ops, -++ struct snd_pcm_substream *substream, -++ int state) -++{ -++ int res; -++ -++ down_read(&snd_pcm_link_rwsem); -++ if (snd_pcm_stream_linked(substream)) -++ res = snd_pcm_action_group(ops, substream, state, 0); -++ else -++ res = snd_pcm_action_single(ops, substream, state); -++ up_read(&snd_pcm_link_rwsem); -++ return res; -++} -++ -++/* -++ * start callbacks -++ */ -++static int snd_pcm_pre_start(struct snd_pcm_substream *substream, int state) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ if (runtime->status->state != SNDRV_PCM_STATE_PREPARED) -++ return -EBADFD; -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && -++ !snd_pcm_playback_data(substream)) -++ return -EPIPE; -++ runtime->trigger_master = substream; -++ return 0; -++} -++ -++static int snd_pcm_do_start(struct snd_pcm_substream *substream, int state) -++{ -++ if (substream->runtime->trigger_master != substream) -++ return 0; -++ return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START); -++} -++ -++static void snd_pcm_undo_start(struct snd_pcm_substream *substream, int state) -++{ -++ if (substream->runtime->trigger_master == substream) -++ substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP); -++} -++ -++static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ snd_pcm_trigger_tstamp(substream); -++ runtime->status->state = state; -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && -++ runtime->silence_size > 0) -++ snd_pcm_playback_silence(substream, ULONG_MAX); -++ if (runtime->sleep_min) -++ snd_pcm_tick_prepare(substream); -++ if (substream->timer) -++ snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTART, -++ &runtime->trigger_tstamp); -++} -++ -++static struct action_ops snd_pcm_action_start = { -++ .pre_action = snd_pcm_pre_start, -++ .do_action = snd_pcm_do_start, -++ .undo_action = snd_pcm_undo_start, -++ .post_action = snd_pcm_post_start -++}; -++ -++/** -++ * snd_pcm_start -++ * @substream: the PCM substream instance -++ * -++ * Start all linked streams. -++ */ -++int snd_pcm_start(struct snd_pcm_substream *substream) -++{ -++ return snd_pcm_action(&snd_pcm_action_start, substream, -++ SNDRV_PCM_STATE_RUNNING); -++} -++ -++/* -++ * stop callbacks -++ */ -++static int snd_pcm_pre_stop(struct snd_pcm_substream *substream, int state) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN) -++ return -EBADFD; -++ runtime->trigger_master = substream; -++ return 0; -++} -++ -++static int snd_pcm_do_stop(struct snd_pcm_substream *substream, int state) -++{ -++ if (substream->runtime->trigger_master == substream && -++ snd_pcm_running(substream)) -++ substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP); -++ return 0; /* unconditonally stop all substreams */ -++} -++ -++static void snd_pcm_post_stop(struct snd_pcm_substream *substream, int state) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ if (runtime->status->state != state) { -++ snd_pcm_trigger_tstamp(substream); -++ if (substream->timer) -++ snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTOP, -++ &runtime->trigger_tstamp); -++ runtime->status->state = state; -++ snd_pcm_tick_set(substream, 0); -++ } -++ wake_up(&runtime->sleep); -++} -++ -++static struct action_ops snd_pcm_action_stop = { -++ .pre_action = snd_pcm_pre_stop, -++ .do_action = snd_pcm_do_stop, -++ .post_action = snd_pcm_post_stop -++}; -++ -++/** -++ * snd_pcm_stop -++ * @substream: the PCM substream instance -++ * @state: PCM state after stopping the stream -++ * -++ * Try to stop all running streams in the substream group. -++ * The state of each stream is changed to the given value after that unconditionally. -++ */ -++int snd_pcm_stop(struct snd_pcm_substream *substream, int state) -++{ -++ return snd_pcm_action(&snd_pcm_action_stop, substream, state); -++} -++ -++EXPORT_SYMBOL(snd_pcm_stop); -++ -++/** -++ * snd_pcm_drain_done -++ * @substream: the PCM substream -++ * -++ * Stop the DMA only when the given stream is playback. -++ * The state is changed to SETUP. -++ * Unlike snd_pcm_stop(), this affects only the given stream. -++ */ -++int snd_pcm_drain_done(struct snd_pcm_substream *substream) -++{ -++ return snd_pcm_action_single(&snd_pcm_action_stop, substream, -++ SNDRV_PCM_STATE_SETUP); -++} -++ -++/* -++ * pause callbacks -++ */ -++static int snd_pcm_pre_pause(struct snd_pcm_substream *substream, int push) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ if (!(runtime->info & SNDRV_PCM_INFO_PAUSE)) -++ return -ENOSYS; -++ if (push) { -++ if (runtime->status->state != SNDRV_PCM_STATE_RUNNING) -++ return -EBADFD; -++ } else if (runtime->status->state != SNDRV_PCM_STATE_PAUSED) -++ return -EBADFD; -++ runtime->trigger_master = substream; -++ return 0; -++} -++ -++static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push) -++{ -++ if (substream->runtime->trigger_master != substream) -++ return 0; -++ return substream->ops->trigger(substream, -++ push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH : -++ SNDRV_PCM_TRIGGER_PAUSE_RELEASE); -++} -++ -++static void snd_pcm_undo_pause(struct snd_pcm_substream *substream, int push) -++{ -++ if (substream->runtime->trigger_master == substream) -++ substream->ops->trigger(substream, -++ push ? SNDRV_PCM_TRIGGER_PAUSE_RELEASE : -++ SNDRV_PCM_TRIGGER_PAUSE_PUSH); -++} -++ -++static void snd_pcm_post_pause(struct snd_pcm_substream *substream, int push) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ snd_pcm_trigger_tstamp(substream); -++ if (push) { -++ runtime->status->state = SNDRV_PCM_STATE_PAUSED; -++ if (substream->timer) -++ snd_timer_notify(substream->timer, -++ SNDRV_TIMER_EVENT_MPAUSE, -++ &runtime->trigger_tstamp); -++ snd_pcm_tick_set(substream, 0); -++ wake_up(&runtime->sleep); -++ } else { -++ runtime->status->state = SNDRV_PCM_STATE_RUNNING; -++ if (runtime->sleep_min) -++ snd_pcm_tick_prepare(substream); -++ if (substream->timer) -++ snd_timer_notify(substream->timer, -++ SNDRV_TIMER_EVENT_MCONTINUE, -++ &runtime->trigger_tstamp); -++ } -++} -++ -++static struct action_ops snd_pcm_action_pause = { -++ .pre_action = snd_pcm_pre_pause, -++ .do_action = snd_pcm_do_pause, -++ .undo_action = snd_pcm_undo_pause, -++ .post_action = snd_pcm_post_pause -++}; -++ -++/* -++ * Push/release the pause for all linked streams. -++ */ -++static int snd_pcm_pause(struct snd_pcm_substream *substream, int push) -++{ -++ return snd_pcm_action(&snd_pcm_action_pause, substream, push); -++} -++ -++#ifdef CONFIG_PM -++/* suspend */ -++ -++static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, int state) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) -++ return -EBUSY; -++ runtime->trigger_master = substream; -++ return 0; -++} -++ -++static int snd_pcm_do_suspend(struct snd_pcm_substream *substream, int state) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ if (runtime->trigger_master != substream) -++ return 0; -++ if (! snd_pcm_running(substream)) -++ return 0; -++ substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND); -++ return 0; /* suspend unconditionally */ -++} -++ -++static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, int state) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ snd_pcm_trigger_tstamp(substream); -++ if (substream->timer) -++ snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSUSPEND, -++ &runtime->trigger_tstamp); -++ runtime->status->suspended_state = runtime->status->state; -++ runtime->status->state = SNDRV_PCM_STATE_SUSPENDED; -++ snd_pcm_tick_set(substream, 0); -++ wake_up(&runtime->sleep); -++} -++ -++static struct action_ops snd_pcm_action_suspend = { -++ .pre_action = snd_pcm_pre_suspend, -++ .do_action = snd_pcm_do_suspend, -++ .post_action = snd_pcm_post_suspend -++}; -++ -++/** -++ * snd_pcm_suspend -++ * @substream: the PCM substream -++ * -++ * Trigger SUSPEND to all linked streams. -++ * After this call, all streams are changed to SUSPENDED state. -++ */ -++int snd_pcm_suspend(struct snd_pcm_substream *substream) -++{ -++ int err; -++ unsigned long flags; -++ -++ if (! substream) -++ return 0; -++ -++ snd_pcm_stream_lock_irqsave(substream, flags); -++ err = snd_pcm_action(&snd_pcm_action_suspend, substream, 0); -++ snd_pcm_stream_unlock_irqrestore(substream, flags); -++ return err; -++} -++ -++EXPORT_SYMBOL(snd_pcm_suspend); -++ -++/** -++ * snd_pcm_suspend_all -++ * @pcm: the PCM instance -++ * -++ * Trigger SUSPEND to all substreams in the given pcm. -++ * After this call, all streams are changed to SUSPENDED state. -++ */ -++int snd_pcm_suspend_all(struct snd_pcm *pcm) -++{ -++ struct snd_pcm_substream *substream; -++ int stream, err = 0; -++ -++ if (! pcm) -++ return 0; -++ -++ for (stream = 0; stream < 2; stream++) { -++ for (substream = pcm->streams[stream].substream; -++ substream; substream = substream->next) { -++ /* FIXME: the open/close code should lock this as well */ -++ if (substream->runtime == NULL) -++ continue; -++ err = snd_pcm_suspend(substream); -++ if (err < 0 && err != -EBUSY) -++ return err; -++ } -++ } -++ return 0; -++} -++ -++EXPORT_SYMBOL(snd_pcm_suspend_all); -++ -++/* resume */ -++ -++static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ if (!(runtime->info & SNDRV_PCM_INFO_RESUME)) -++ return -ENOSYS; -++ runtime->trigger_master = substream; -++ return 0; -++} -++ -++static int snd_pcm_do_resume(struct snd_pcm_substream *substream, int state) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ if (runtime->trigger_master != substream) -++ return 0; -++ /* DMA not running previously? */ -++ if (runtime->status->suspended_state != SNDRV_PCM_STATE_RUNNING && -++ (runtime->status->suspended_state != SNDRV_PCM_STATE_DRAINING || -++ substream->stream != SNDRV_PCM_STREAM_PLAYBACK)) -++ return 0; -++ return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_RESUME); -++} -++ -++static void snd_pcm_undo_resume(struct snd_pcm_substream *substream, int state) -++{ -++ if (substream->runtime->trigger_master == substream && -++ snd_pcm_running(substream)) -++ substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND); -++} -++ -++static void snd_pcm_post_resume(struct snd_pcm_substream *substream, int state) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ snd_pcm_trigger_tstamp(substream); -++ if (substream->timer) -++ snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MRESUME, -++ &runtime->trigger_tstamp); -++ runtime->status->state = runtime->status->suspended_state; -++ if (runtime->sleep_min) -++ snd_pcm_tick_prepare(substream); -++} -++ -++static struct action_ops snd_pcm_action_resume = { -++ .pre_action = snd_pcm_pre_resume, -++ .do_action = snd_pcm_do_resume, -++ .undo_action = snd_pcm_undo_resume, -++ .post_action = snd_pcm_post_resume -++}; -++ -++static int snd_pcm_resume(struct snd_pcm_substream *substream) -++{ -++ struct snd_card *card = substream->pcm->card; -++ int res; -++ -++ snd_power_lock(card); -++ if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) -++ res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0); -++ snd_power_unlock(card); -++ return res; -++} -++ -++#else -++ -++static int snd_pcm_resume(struct snd_pcm_substream *substream) -++{ -++ return -ENOSYS; -++} -++ -++#endif /* CONFIG_PM */ -++ -++/* -++ * xrun ioctl -++ * -++ * Change the RUNNING stream(s) to XRUN state. -++ */ -++static int snd_pcm_xrun(struct snd_pcm_substream *substream) -++{ -++ struct snd_card *card = substream->pcm->card; -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ int result; -++ -++ snd_power_lock(card); -++ if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { -++ result = snd_power_wait(card, SNDRV_CTL_POWER_D0); -++ if (result < 0) -++ goto _unlock; -++ } -++ -++ snd_pcm_stream_lock_irq(substream); -++ switch (runtime->status->state) { -++ case SNDRV_PCM_STATE_XRUN: -++ result = 0; /* already there */ -++ break; -++ case SNDRV_PCM_STATE_RUNNING: -++ result = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); -++ break; -++ default: -++ result = -EBADFD; -++ } -++ snd_pcm_stream_unlock_irq(substream); -++ _unlock: -++ snd_power_unlock(card); -++ return result; -++} -++ -++/* -++ * reset ioctl -++ */ -++static int snd_pcm_pre_reset(struct snd_pcm_substream *substream, int state) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ switch (runtime->status->state) { -++ case SNDRV_PCM_STATE_RUNNING: -++ case SNDRV_PCM_STATE_PREPARED: -++ case SNDRV_PCM_STATE_PAUSED: -++ case SNDRV_PCM_STATE_SUSPENDED: -++ return 0; -++ default: -++ return -EBADFD; -++ } -++} -++ -++static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ int err = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL); -++ if (err < 0) -++ return err; -++ // snd_assert(runtime->status->hw_ptr < runtime->buffer_size, ); -++ runtime->hw_ptr_base = 0; -++ runtime->hw_ptr_interrupt = runtime->status->hw_ptr - -++ runtime->status->hw_ptr % runtime->period_size; -++ runtime->silence_start = runtime->status->hw_ptr; -++ runtime->silence_filled = 0; -++ return 0; -++} -++ -++static void snd_pcm_post_reset(struct snd_pcm_substream *substream, int state) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ runtime->control->appl_ptr = runtime->status->hw_ptr; -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && -++ runtime->silence_size > 0) -++ snd_pcm_playback_silence(substream, ULONG_MAX); -++} -++ -++static struct action_ops snd_pcm_action_reset = { -++ .pre_action = snd_pcm_pre_reset, -++ .do_action = snd_pcm_do_reset, -++ .post_action = snd_pcm_post_reset -++}; -++ -++static int snd_pcm_reset(struct snd_pcm_substream *substream) -++{ -++ return snd_pcm_action_nonatomic(&snd_pcm_action_reset, substream, 0); -++} -++ -++/* -++ * prepare ioctl -++ */ -++/* we use the second argument for updating f_flags */ -++static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, -++ int f_flags) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN || -++ runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) -++ return -EBADFD; -++ if (snd_pcm_running(substream)) -++ return -EBUSY; -++ substream->f_flags = f_flags; -++ return 0; -++} -++ -++static int snd_pcm_do_prepare(struct snd_pcm_substream *substream, int state) -++{ -++ int err; -++ err = substream->ops->prepare(substream); -++ if (err < 0) -++ return err; -++ return snd_pcm_do_reset(substream, 0); -++} -++ -++static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ runtime->control->appl_ptr = runtime->status->hw_ptr; -++ runtime->status->state = SNDRV_PCM_STATE_PREPARED; -++} -++ -++static struct action_ops snd_pcm_action_prepare = { -++ .pre_action = snd_pcm_pre_prepare, -++ .do_action = snd_pcm_do_prepare, -++ .post_action = snd_pcm_post_prepare -++}; -++ -++/** -++ * snd_pcm_prepare -++ * @substream: the PCM substream instance -++ * @file: file to refer f_flags -++ * -++ * Prepare the PCM substream to be triggerable. -++ */ -++static int snd_pcm_prepare(struct snd_pcm_substream *substream, -++ struct file *file) -++{ -++ int res; -++ struct snd_card *card = substream->pcm->card; -++ int f_flags; -++ -++ if (file) -++ f_flags = file->f_flags; -++ else -++ f_flags = substream->f_flags; -++ -++ snd_power_lock(card); -++ if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) -++ res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, -++ substream, f_flags); -++ snd_power_unlock(card); -++ return res; -++} -++ -++/* -++ * drain ioctl -++ */ -++ -++static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state) -++{ -++ if (substream->f_flags & O_NONBLOCK) -++ return -EAGAIN; -++ substream->runtime->trigger_master = substream; -++ return 0; -++} -++ -++static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -++ switch (runtime->status->state) { -++ case SNDRV_PCM_STATE_PREPARED: -++ /* start playback stream if possible */ -++ if (! snd_pcm_playback_empty(substream)) { -++ snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING); -++ snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING); -++ } -++ break; -++ case SNDRV_PCM_STATE_RUNNING: -++ runtime->status->state = SNDRV_PCM_STATE_DRAINING; -++ break; -++ default: -++ break; -++ } -++ } else { -++ /* stop running stream */ -++ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) { -++ int state = snd_pcm_capture_avail(runtime) > 0 ? -++ SNDRV_PCM_STATE_DRAINING : SNDRV_PCM_STATE_SETUP; -++ snd_pcm_do_stop(substream, state); -++ snd_pcm_post_stop(substream, state); -++ } -++ } -++ return 0; -++} -++ -++static void snd_pcm_post_drain_init(struct snd_pcm_substream *substream, int state) -++{ -++} -++ -++static struct action_ops snd_pcm_action_drain_init = { -++ .pre_action = snd_pcm_pre_drain_init, -++ .do_action = snd_pcm_do_drain_init, -++ .post_action = snd_pcm_post_drain_init -++}; -++ -++struct drain_rec { -++ struct snd_pcm_substream *substream; -++ wait_queue_t wait; -++ snd_pcm_uframes_t stop_threshold; -++}; -++ -++static int snd_pcm_drop(struct snd_pcm_substream *substream); -++ -++/* -++ * Drain the stream(s). -++ * When the substream is linked, sync until the draining of all playback streams -++ * is finished. -++ * After this call, all streams are supposed to be either SETUP or DRAINING -++ * (capture only) state. -++ */ -++static int snd_pcm_drain(struct snd_pcm_substream *substream) -++{ -++ struct snd_card *card; -++ struct snd_pcm_runtime *runtime; -++ struct snd_pcm_substream *s; -++ int result = 0; -++ int i, num_drecs; -++ struct drain_rec *drec, drec_tmp, *d; -++ -++ snd_assert(substream != NULL, return -ENXIO); -++ card = substream->pcm->card; -++ runtime = substream->runtime; -++ -++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN) -++ return -EBADFD; -++ -++ snd_power_lock(card); -++ if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { -++ result = snd_power_wait(card, SNDRV_CTL_POWER_D0); -++ if (result < 0) { -++ snd_power_unlock(card); -++ return result; -++ } -++ } -++ -++ /* allocate temporary record for drain sync */ -++ down_read(&snd_pcm_link_rwsem); -++ if (snd_pcm_stream_linked(substream)) { -++ drec = kmalloc(substream->group->count * sizeof(*drec), GFP_KERNEL); -++ if (! drec) { -++ up_read(&snd_pcm_link_rwsem); -++ snd_power_unlock(card); -++ return -ENOMEM; -++ } -++ } else -++ drec = &drec_tmp; -++ -++ /* count only playback streams */ -++ num_drecs = 0; -++ snd_pcm_group_for_each_entry(s, substream) { -++ runtime = s->runtime; -++ if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { -++ d = &drec[num_drecs++]; -++ d->substream = s; -++ init_waitqueue_entry(&d->wait, current); -++ add_wait_queue(&runtime->sleep, &d->wait); -++ /* stop_threshold fixup to avoid endless loop when -++ * stop_threshold > buffer_size -++ */ -++ d->stop_threshold = runtime->stop_threshold; -++ if (runtime->stop_threshold > runtime->buffer_size) -++ runtime->stop_threshold = runtime->buffer_size; -++ } -++ } -++ up_read(&snd_pcm_link_rwsem); -++ -++ snd_pcm_stream_lock_irq(substream); -++ /* resume pause */ -++ if (substream->runtime->status->state == SNDRV_PCM_STATE_PAUSED) -++ snd_pcm_pause(substream, 0); -++ -++ /* pre-start/stop - all running streams are changed to DRAINING state */ -++ result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0); -++ if (result < 0) { -++ snd_pcm_stream_unlock_irq(substream); -++ goto _error; -++ } -++ -++ for (;;) { -++ long tout; -++ if (signal_pending(current)) { -++ result = -ERESTARTSYS; -++ break; -++ } -++ /* all finished? */ -++ for (i = 0; i < num_drecs; i++) { -++ runtime = drec[i].substream->runtime; -++ if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) -++ break; -++ } -++ if (i == num_drecs) -++ break; /* yes, all drained */ -++ -++ set_current_state(TASK_INTERRUPTIBLE); -++ snd_pcm_stream_unlock_irq(substream); -++ snd_power_unlock(card); -++ tout = schedule_timeout(10 * HZ); -++ snd_power_lock(card); -++ snd_pcm_stream_lock_irq(substream); -++ if (tout == 0) { -++ if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) -++ result = -ESTRPIPE; -++ else { -++ snd_printd("playback drain error (DMA or IRQ trouble?)\n"); -++ snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); -++ result = -EIO; -++ } -++ break; -++ } -++ } -++ -++ snd_pcm_stream_unlock_irq(substream); -++ -++ _error: -++ for (i = 0; i < num_drecs; i++) { -++ d = &drec[i]; -++ runtime = d->substream->runtime; -++ remove_wait_queue(&runtime->sleep, &d->wait); -++ runtime->stop_threshold = d->stop_threshold; -++ } -++ -++ if (drec != &drec_tmp) -++ kfree(drec); -++ snd_power_unlock(card); -++ -++ return result; -++} -++ -++/* -++ * drop ioctl -++ * -++ * Immediately put all linked substreams into SETUP state. -++ */ -++static int snd_pcm_drop(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime; -++ struct snd_card *card; -++ int result = 0; -++ -++ snd_assert(substream != NULL, return -ENXIO); -++ runtime = substream->runtime; -++ card = substream->pcm->card; -++ -++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN || -++ runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) -++ return -EBADFD; -++ -++ snd_power_lock(card); -++ if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { -++ result = snd_power_wait(card, SNDRV_CTL_POWER_D0); -++ if (result < 0) -++ goto _unlock; -++ } -++ -++ snd_pcm_stream_lock_irq(substream); -++ /* resume pause */ -++ if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) -++ snd_pcm_pause(substream, 0); -++ -++ snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); -++ /* runtime->control->appl_ptr = runtime->status->hw_ptr; */ -++ snd_pcm_stream_unlock_irq(substream); -++ _unlock: -++ snd_power_unlock(card); -++ return result; -++} -++ -++ -++/* WARNING: Don't forget to fput back the file */ -++static struct file *snd_pcm_file_fd(int fd) -++{ -++ struct file *file; -++ struct inode *inode; -++ unsigned int minor; -++ -++ file = fget(fd); -++ if (!file) -++ return NULL; -++ inode = file->f_path.dentry->d_inode; -++ if (!S_ISCHR(inode->i_mode) || -++ imajor(inode) != snd_major) { -++ fput(file); -++ return NULL; -++ } -++ minor = iminor(inode); -++ if (!snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK) && -++ !snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE)) { -++ fput(file); -++ return NULL; -++ } -++ return file; -++} -++ -++/* -++ * PCM link handling -++ */ -++static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) -++{ -++ int res = 0; -++ struct file *file; -++ struct snd_pcm_file *pcm_file; -++ struct snd_pcm_substream *substream1; -++ -++ file = snd_pcm_file_fd(fd); -++ if (!file) -++ return -EBADFD; -++ pcm_file = file->private_data; -++ substream1 = pcm_file->substream; -++ down_write(&snd_pcm_link_rwsem); -++ write_lock_irq(&snd_pcm_link_rwlock); -++ if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN || -++ substream->runtime->status->state != substream1->runtime->status->state) { -++ res = -EBADFD; -++ goto _end; -++ } -++ if (snd_pcm_stream_linked(substream1)) { -++ res = -EALREADY; -++ goto _end; -++ } -++ if (!snd_pcm_stream_linked(substream)) { -++ substream->group = kmalloc(sizeof(struct snd_pcm_group), GFP_ATOMIC); -++ if (substream->group == NULL) { -++ res = -ENOMEM; -++ goto _end; -++ } -++ spin_lock_init(&substream->group->lock); -++ INIT_LIST_HEAD(&substream->group->substreams); -++ list_add_tail(&substream->link_list, &substream->group->substreams); -++ substream->group->count = 1; -++ } -++ list_add_tail(&substream1->link_list, &substream->group->substreams); -++ substream->group->count++; -++ substream1->group = substream->group; -++ _end: -++ write_unlock_irq(&snd_pcm_link_rwlock); -++ up_write(&snd_pcm_link_rwsem); -++ fput(file); -++ return res; -++} -++ -++static void relink_to_local(struct snd_pcm_substream *substream) -++{ -++ substream->group = &substream->self_group; -++ INIT_LIST_HEAD(&substream->self_group.substreams); -++ list_add_tail(&substream->link_list, &substream->self_group.substreams); -++} -++ -++static int snd_pcm_unlink(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_substream *s; -++ int res = 0; -++ -++ down_write(&snd_pcm_link_rwsem); -++ write_lock_irq(&snd_pcm_link_rwlock); -++ if (!snd_pcm_stream_linked(substream)) { -++ res = -EALREADY; -++ goto _end; -++ } -++ list_del(&substream->link_list); -++ substream->group->count--; -++ if (substream->group->count == 1) { /* detach the last stream, too */ -++ snd_pcm_group_for_each_entry(s, substream) { -++ relink_to_local(s); -++ break; -++ } -++ kfree(substream->group); -++ } -++ relink_to_local(substream); -++ _end: -++ write_unlock_irq(&snd_pcm_link_rwlock); -++ up_write(&snd_pcm_link_rwsem); -++ return res; -++} -++ -++/* -++ * hw configurator -++ */ -++static int snd_pcm_hw_rule_mul(struct snd_pcm_hw_params *params, -++ struct snd_pcm_hw_rule *rule) -++{ -++ struct snd_interval t; -++ snd_interval_mul(hw_param_interval_c(params, rule->deps[0]), -++ hw_param_interval_c(params, rule->deps[1]), &t); -++ return snd_interval_refine(hw_param_interval(params, rule->var), &t); -++} -++ -++static int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params, -++ struct snd_pcm_hw_rule *rule) -++{ -++ struct snd_interval t; -++ snd_interval_div(hw_param_interval_c(params, rule->deps[0]), -++ hw_param_interval_c(params, rule->deps[1]), &t); -++ return snd_interval_refine(hw_param_interval(params, rule->var), &t); -++} -++ -++static int snd_pcm_hw_rule_muldivk(struct snd_pcm_hw_params *params, -++ struct snd_pcm_hw_rule *rule) -++{ -++ struct snd_interval t; -++ snd_interval_muldivk(hw_param_interval_c(params, rule->deps[0]), -++ hw_param_interval_c(params, rule->deps[1]), -++ (unsigned long) rule->private, &t); -++ return snd_interval_refine(hw_param_interval(params, rule->var), &t); -++} -++ -++static int snd_pcm_hw_rule_mulkdiv(struct snd_pcm_hw_params *params, -++ struct snd_pcm_hw_rule *rule) -++{ -++ struct snd_interval t; -++ snd_interval_mulkdiv(hw_param_interval_c(params, rule->deps[0]), -++ (unsigned long) rule->private, -++ hw_param_interval_c(params, rule->deps[1]), &t); -++ return snd_interval_refine(hw_param_interval(params, rule->var), &t); -++} -++ -++static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params, -++ struct snd_pcm_hw_rule *rule) -++{ -++ unsigned int k; -++ struct snd_interval *i = hw_param_interval(params, rule->deps[0]); -++ struct snd_mask m; -++ struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); -++ snd_mask_any(&m); -++ for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) { -++ int bits; -++ if (! snd_mask_test(mask, k)) -++ continue; -++ bits = snd_pcm_format_physical_width(k); -++ if (bits <= 0) -++ continue; /* ignore invalid formats */ -++ if ((unsigned)bits < i->min || (unsigned)bits > i->max) -++ snd_mask_reset(&m, k); -++ } -++ return snd_mask_refine(mask, &m); -++} -++ -++static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, -++ struct snd_pcm_hw_rule *rule) -++{ -++ struct snd_interval t; -++ unsigned int k; -++ t.min = UINT_MAX; -++ t.max = 0; -++ t.openmin = 0; -++ t.openmax = 0; -++ for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) { -++ int bits; -++ if (! snd_mask_test(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), k)) -++ continue; -++ bits = snd_pcm_format_physical_width(k); -++ if (bits <= 0) -++ continue; /* ignore invalid formats */ -++ if (t.min > (unsigned)bits) -++ t.min = bits; -++ if (t.max < (unsigned)bits) -++ t.max = bits; -++ } -++ t.integer = 1; -++ return snd_interval_refine(hw_param_interval(params, rule->var), &t); -++} -++ -++#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12 -++#error "Change this table" -++#endif -++ -++static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, -++ 48000, 64000, 88200, 96000, 176400, 192000 }; -++ -++const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = { -++ .count = ARRAY_SIZE(rates), -++ .list = rates, -++}; -++ -++static int snd_pcm_hw_rule_rate(struct snd_pcm_hw_params *params, -++ struct snd_pcm_hw_rule *rule) -++{ -++ struct snd_pcm_hardware *hw = rule->private; -++ return snd_interval_list(hw_param_interval(params, rule->var), -++ snd_pcm_known_rates.count, -++ snd_pcm_known_rates.list, hw->rates); -++} -++ -++static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params, -++ struct snd_pcm_hw_rule *rule) -++{ -++ struct snd_interval t; -++ struct snd_pcm_substream *substream = rule->private; -++ t.min = 0; -++ t.max = substream->buffer_bytes_max; -++ t.openmin = 0; -++ t.openmax = 0; -++ t.integer = 1; -++ return snd_interval_refine(hw_param_interval(params, rule->var), &t); -++} -++ -++int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints; -++ int k, err; -++ -++ for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) { -++ snd_mask_any(constrs_mask(constrs, k)); -++ } -++ -++ for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) { -++ snd_interval_any(constrs_interval(constrs, k)); -++ } -++ -++ snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_CHANNELS)); -++ snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_BUFFER_SIZE)); -++ snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_BUFFER_BYTES)); -++ snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)); -++ snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_FRAME_BITS)); -++ -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, -++ snd_pcm_hw_rule_format, NULL, -++ SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -++ snd_pcm_hw_rule_sample_bits, NULL, -++ SNDRV_PCM_HW_PARAM_FORMAT, -++ SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -++ snd_pcm_hw_rule_div, NULL, -++ SNDRV_PCM_HW_PARAM_FRAME_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS, -++ snd_pcm_hw_rule_mul, NULL, -++ SNDRV_PCM_HW_PARAM_SAMPLE_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS, -++ snd_pcm_hw_rule_mulkdiv, (void*) 8, -++ SNDRV_PCM_HW_PARAM_PERIOD_BYTES, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS, -++ snd_pcm_hw_rule_mulkdiv, (void*) 8, -++ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, -++ snd_pcm_hw_rule_div, NULL, -++ SNDRV_PCM_HW_PARAM_FRAME_BITS, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, -++ snd_pcm_hw_rule_mulkdiv, (void*) 1000000, -++ SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_PERIOD_TIME, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, -++ snd_pcm_hw_rule_mulkdiv, (void*) 1000000, -++ SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_BUFFER_TIME, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS, -++ snd_pcm_hw_rule_div, NULL, -++ SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -++ snd_pcm_hw_rule_div, NULL, -++ SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_PERIODS, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -++ snd_pcm_hw_rule_mulkdiv, (void*) 8, -++ SNDRV_PCM_HW_PARAM_PERIOD_BYTES, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -++ snd_pcm_hw_rule_muldivk, (void*) 1000000, -++ SNDRV_PCM_HW_PARAM_PERIOD_TIME, SNDRV_PCM_HW_PARAM_RATE, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -++ snd_pcm_hw_rule_mul, NULL, -++ SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_PERIODS, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -++ snd_pcm_hw_rule_mulkdiv, (void*) 8, -++ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -++ snd_pcm_hw_rule_muldivk, (void*) 1000000, -++ SNDRV_PCM_HW_PARAM_BUFFER_TIME, SNDRV_PCM_HW_PARAM_RATE, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, -++ snd_pcm_hw_rule_muldivk, (void*) 8, -++ SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -++ snd_pcm_hw_rule_muldivk, (void*) 8, -++ SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_TIME, -++ snd_pcm_hw_rule_mulkdiv, (void*) 1000000, -++ SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_RATE, -1); -++ if (err < 0) -++ return err; -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_TIME, -++ snd_pcm_hw_rule_mulkdiv, (void*) 1000000, -++ SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_RATE, -1); -++ if (err < 0) -++ return err; -++ return 0; -++} -++ -++int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ struct snd_pcm_hardware *hw = &runtime->hw; -++ int err; -++ unsigned int mask = 0; -++ -++ if (hw->info & SNDRV_PCM_INFO_INTERLEAVED) -++ mask |= 1 << SNDRV_PCM_ACCESS_RW_INTERLEAVED; -++ if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED) -++ mask |= 1 << SNDRV_PCM_ACCESS_RW_NONINTERLEAVED; -++ if (hw->info & SNDRV_PCM_INFO_MMAP) { -++ if (hw->info & SNDRV_PCM_INFO_INTERLEAVED) -++ mask |= 1 << SNDRV_PCM_ACCESS_MMAP_INTERLEAVED; -++ if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED) -++ mask |= 1 << SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED; -++ if (hw->info & SNDRV_PCM_INFO_COMPLEX) -++ mask |= 1 << SNDRV_PCM_ACCESS_MMAP_COMPLEX; -++ } -++ err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_ACCESS, mask); -++ snd_assert(err >= 0, return -EINVAL); -++ -++ err = snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats); -++ snd_assert(err >= 0, return -EINVAL); -++ -++ err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD); -++ snd_assert(err >= 0, return -EINVAL); -++ -++ err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, -++ hw->channels_min, hw->channels_max); -++ snd_assert(err >= 0, return -EINVAL); -++ -++ err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE, -++ hw->rate_min, hw->rate_max); -++ snd_assert(err >= 0, return -EINVAL); -++ -++ err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, -++ hw->period_bytes_min, hw->period_bytes_max); -++ snd_assert(err >= 0, return -EINVAL); -++ -++ err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS, -++ hw->periods_min, hw->periods_max); -++ snd_assert(err >= 0, return -EINVAL); -++ -++ err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -++ hw->period_bytes_min, hw->buffer_bytes_max); -++ snd_assert(err >= 0, return -EINVAL); -++ -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -++ snd_pcm_hw_rule_buffer_bytes_max, substream, -++ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -1); -++ if (err < 0) -++ return err; -++ -++ /* FIXME: remove */ -++ if (runtime->dma_bytes) { -++ err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0, runtime->dma_bytes); -++ snd_assert(err >= 0, return -EINVAL); -++ } -++ -++ if (!(hw->rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))) { -++ err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, -++ snd_pcm_hw_rule_rate, hw, -++ SNDRV_PCM_HW_PARAM_RATE, -1); -++ if (err < 0) -++ return err; -++ } -++ -++ /* FIXME: this belong to lowlevel */ -++ snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_TICK_TIME, -++ 1000000 / HZ, 1000000 / HZ); -++ snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); -++ -++ return 0; -++} -++ -++static void pcm_release_private(struct snd_pcm_substream *substream) -++{ -++ snd_pcm_unlink(substream); -++} -++ -++void snd_pcm_release_substream(struct snd_pcm_substream *substream) -++{ -++ substream->ref_count--; -++ if (substream->ref_count > 0) -++ return; -++ -++ snd_pcm_drop(substream); -++ if (substream->hw_opened) { -++ if (substream->ops->hw_free != NULL) -++ substream->ops->hw_free(substream); -++ substream->ops->close(substream); -++ substream->hw_opened = 0; -++ } -++ if (substream->pcm_release) { -++ substream->pcm_release(substream); -++ substream->pcm_release = NULL; -++ } -++ snd_pcm_detach_substream(substream); -++} -++ -++EXPORT_SYMBOL(snd_pcm_release_substream); -++ -++int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, -++ struct file *file, -++ struct snd_pcm_substream **rsubstream) -++{ -++ struct snd_pcm_substream *substream; -++ int err; -++ -++ err = snd_pcm_attach_substream(pcm, stream, file, &substream); -++ if (err < 0) -++ return err; -++ if (substream->ref_count > 1) { -++ *rsubstream = substream; -++ return 0; -++ } -++ -++ err = snd_pcm_hw_constraints_init(substream); -++ if (err < 0) { -++ snd_printd("snd_pcm_hw_constraints_init failed\n"); -++ goto error; -++ } -++ -++ if ((err = substream->ops->open(substream)) < 0) -++ goto error; -++ -++ substream->hw_opened = 1; -++ -++ err = snd_pcm_hw_constraints_complete(substream); -++ if (err < 0) { -++ snd_printd("snd_pcm_hw_constraints_complete failed\n"); -++ goto error; -++ } -++ -++ *rsubstream = substream; -++ return 0; -++ -++ error: -++ snd_pcm_release_substream(substream); -++ return err; -++} -++ -++EXPORT_SYMBOL(snd_pcm_open_substream); -++ -++static int snd_pcm_open_file(struct file *file, -++ struct snd_pcm *pcm, -++ int stream, -++ struct snd_pcm_file **rpcm_file) -++{ -++ struct snd_pcm_file *pcm_file; -++ struct snd_pcm_substream *substream; -++ struct snd_pcm_str *str; -++ int err; -++ -++ snd_assert(rpcm_file != NULL, return -EINVAL); -++ *rpcm_file = NULL; -++ -++ err = snd_pcm_open_substream(pcm, stream, file, &substream); -++ if (err < 0) -++ return err; -++ -++ pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL); -++ if (pcm_file == NULL) { -++ snd_pcm_release_substream(substream); -++ return -ENOMEM; -++ } -++ pcm_file->substream = substream; -++ if (substream->ref_count == 1) { -++ str = substream->pstr; -++ substream->file = pcm_file; -++ substream->pcm_release = pcm_release_private; -++ } -++ file->private_data = pcm_file; -++ *rpcm_file = pcm_file; -++ return 0; -++} -++ -++static int snd_pcm_playback_open(struct inode *inode, struct file *file) -++{ -++ struct snd_pcm *pcm; -++ -++ pcm = snd_lookup_minor_data(iminor(inode), -++ SNDRV_DEVICE_TYPE_PCM_PLAYBACK); -++ return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); -++} -++ -++static int snd_pcm_capture_open(struct inode *inode, struct file *file) -++{ -++ struct snd_pcm *pcm; -++ -++ pcm = snd_lookup_minor_data(iminor(inode), -++ SNDRV_DEVICE_TYPE_PCM_CAPTURE); -++ return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); -++} -++ -++static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) -++{ -++ int err; -++ struct snd_pcm_file *pcm_file; -++ wait_queue_t wait; -++ -++ if (pcm == NULL) { -++ err = -ENODEV; -++ goto __error1; -++ } -++ err = snd_card_file_add(pcm->card, file); -++ if (err < 0) -++ goto __error1; -++ if (!try_module_get(pcm->card->module)) { -++ err = -EFAULT; -++ goto __error2; -++ } -++ init_waitqueue_entry(&wait, current); -++ add_wait_queue(&pcm->open_wait, &wait); -++ mutex_lock(&pcm->open_mutex); -++ while (1) { -++ err = snd_pcm_open_file(file, pcm, stream, &pcm_file); -++ if (err >= 0) -++ break; -++ if (err == -EAGAIN) { -++ if (file->f_flags & O_NONBLOCK) { -++ err = -EBUSY; -++ break; -++ } -++ } else -++ break; -++ set_current_state(TASK_INTERRUPTIBLE); -++ mutex_unlock(&pcm->open_mutex); -++ schedule(); -++ mutex_lock(&pcm->open_mutex); -++ if (signal_pending(current)) { -++ err = -ERESTARTSYS; -++ break; -++ } -++ } -++ remove_wait_queue(&pcm->open_wait, &wait); -++ mutex_unlock(&pcm->open_mutex); -++ if (err < 0) -++ goto __error; -++ return err; -++ -++ __error: -++ module_put(pcm->card->module); -++ __error2: -++ snd_card_file_remove(pcm->card, file); -++ __error1: -++ return err; -++} -++ -++static int snd_pcm_release(struct inode *inode, struct file *file) -++{ -++ struct snd_pcm *pcm; -++ struct snd_pcm_substream *substream; -++ struct snd_pcm_file *pcm_file; -++ -++ pcm_file = file->private_data; -++ substream = pcm_file->substream; -++ snd_assert(substream != NULL, return -ENXIO); -++ pcm = substream->pcm; -++ fasync_helper(-1, file, 0, &substream->runtime->fasync); -++ mutex_lock(&pcm->open_mutex); -++ snd_pcm_release_substream(substream); -++ kfree(pcm_file); -++ mutex_unlock(&pcm->open_mutex); -++ wake_up(&pcm->open_wait); -++ module_put(pcm->card->module); -++ snd_card_file_remove(pcm->card, file); -++ return 0; -++} -++ -++static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream, -++ snd_pcm_uframes_t frames) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ snd_pcm_sframes_t appl_ptr; -++ snd_pcm_sframes_t ret; -++ snd_pcm_sframes_t hw_avail; -++ -++ if (frames == 0) -++ return 0; -++ -++ snd_pcm_stream_lock_irq(substream); -++ switch (runtime->status->state) { -++ case SNDRV_PCM_STATE_PREPARED: -++ break; -++ case SNDRV_PCM_STATE_DRAINING: -++ case SNDRV_PCM_STATE_RUNNING: -++ if (snd_pcm_update_hw_ptr(substream) >= 0) -++ break; -++ /* Fall through */ -++ case SNDRV_PCM_STATE_XRUN: -++ ret = -EPIPE; -++ goto __end; -++ default: -++ ret = -EBADFD; -++ goto __end; -++ } -++ -++ hw_avail = snd_pcm_playback_hw_avail(runtime); -++ if (hw_avail <= 0) { -++ ret = 0; -++ goto __end; -++ } -++ if (frames > (snd_pcm_uframes_t)hw_avail) -++ frames = hw_avail; -++ else -++ frames -= frames % runtime->xfer_align; -++ appl_ptr = runtime->control->appl_ptr - frames; -++ if (appl_ptr < 0) -++ appl_ptr += runtime->boundary; -++ runtime->control->appl_ptr = appl_ptr; -++ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING && -++ runtime->sleep_min) -++ snd_pcm_tick_prepare(substream); -++ ret = frames; -++ __end: -++ snd_pcm_stream_unlock_irq(substream); -++ return ret; -++} -++ -++static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substream, -++ snd_pcm_uframes_t frames) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ snd_pcm_sframes_t appl_ptr; -++ snd_pcm_sframes_t ret; -++ snd_pcm_sframes_t hw_avail; -++ -++ if (frames == 0) -++ return 0; -++ -++ snd_pcm_stream_lock_irq(substream); -++ switch (runtime->status->state) { -++ case SNDRV_PCM_STATE_PREPARED: -++ case SNDRV_PCM_STATE_DRAINING: -++ break; -++ case SNDRV_PCM_STATE_RUNNING: -++ if (snd_pcm_update_hw_ptr(substream) >= 0) -++ break; -++ /* Fall through */ -++ case SNDRV_PCM_STATE_XRUN: -++ ret = -EPIPE; -++ goto __end; -++ default: -++ ret = -EBADFD; -++ goto __end; -++ } -++ -++ hw_avail = snd_pcm_capture_hw_avail(runtime); -++ if (hw_avail <= 0) { -++ ret = 0; -++ goto __end; -++ } -++ if (frames > (snd_pcm_uframes_t)hw_avail) -++ frames = hw_avail; -++ else -++ frames -= frames % runtime->xfer_align; -++ appl_ptr = runtime->control->appl_ptr - frames; -++ if (appl_ptr < 0) -++ appl_ptr += runtime->boundary; -++ runtime->control->appl_ptr = appl_ptr; -++ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING && -++ runtime->sleep_min) -++ snd_pcm_tick_prepare(substream); -++ ret = frames; -++ __end: -++ snd_pcm_stream_unlock_irq(substream); -++ return ret; -++} -++ -++static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *substream, -++ snd_pcm_uframes_t frames) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ snd_pcm_sframes_t appl_ptr; -++ snd_pcm_sframes_t ret; -++ snd_pcm_sframes_t avail; -++ -++ if (frames == 0) -++ return 0; -++ -++ snd_pcm_stream_lock_irq(substream); -++ switch (runtime->status->state) { -++ case SNDRV_PCM_STATE_PREPARED: -++ case SNDRV_PCM_STATE_PAUSED: -++ break; -++ case SNDRV_PCM_STATE_DRAINING: -++ case SNDRV_PCM_STATE_RUNNING: -++ if (snd_pcm_update_hw_ptr(substream) >= 0) -++ break; -++ /* Fall through */ -++ case SNDRV_PCM_STATE_XRUN: -++ ret = -EPIPE; -++ goto __end; -++ default: -++ ret = -EBADFD; -++ goto __end; -++ } -++ -++ avail = snd_pcm_playback_avail(runtime); -++ if (avail <= 0) { -++ ret = 0; -++ goto __end; -++ } -++ if (frames > (snd_pcm_uframes_t)avail) -++ frames = avail; -++ else -++ frames -= frames % runtime->xfer_align; -++ appl_ptr = runtime->control->appl_ptr + frames; -++ if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary) -++ appl_ptr -= runtime->boundary; -++ runtime->control->appl_ptr = appl_ptr; -++ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING && -++ runtime->sleep_min) -++ snd_pcm_tick_prepare(substream); -++ ret = frames; -++ __end: -++ snd_pcm_stream_unlock_irq(substream); -++ return ret; -++} -++ -++static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *substream, -++ snd_pcm_uframes_t frames) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ snd_pcm_sframes_t appl_ptr; -++ snd_pcm_sframes_t ret; -++ snd_pcm_sframes_t avail; -++ -++ if (frames == 0) -++ return 0; -++ -++ snd_pcm_stream_lock_irq(substream); -++ switch (runtime->status->state) { -++ case SNDRV_PCM_STATE_PREPARED: -++ case SNDRV_PCM_STATE_DRAINING: -++ case SNDRV_PCM_STATE_PAUSED: -++ break; -++ case SNDRV_PCM_STATE_RUNNING: -++ if (snd_pcm_update_hw_ptr(substream) >= 0) -++ break; -++ /* Fall through */ -++ case SNDRV_PCM_STATE_XRUN: -++ ret = -EPIPE; -++ goto __end; -++ default: -++ ret = -EBADFD; -++ goto __end; -++ } -++ -++ avail = snd_pcm_capture_avail(runtime); -++ if (avail <= 0) { -++ ret = 0; -++ goto __end; -++ } -++ if (frames > (snd_pcm_uframes_t)avail) -++ frames = avail; -++ else -++ frames -= frames % runtime->xfer_align; -++ appl_ptr = runtime->control->appl_ptr + frames; -++ if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary) -++ appl_ptr -= runtime->boundary; -++ runtime->control->appl_ptr = appl_ptr; -++ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING && -++ runtime->sleep_min) -++ snd_pcm_tick_prepare(substream); -++ ret = frames; -++ __end: -++ snd_pcm_stream_unlock_irq(substream); -++ return ret; -++} -++ -++static int snd_pcm_hwsync(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ int err; -++ -++ snd_pcm_stream_lock_irq(substream); -++ switch (runtime->status->state) { -++ case SNDRV_PCM_STATE_DRAINING: -++ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -++ goto __badfd; -++ case SNDRV_PCM_STATE_RUNNING: -++ if ((err = snd_pcm_update_hw_ptr(substream)) < 0) -++ break; -++ /* Fall through */ -++ case SNDRV_PCM_STATE_PREPARED: -++ case SNDRV_PCM_STATE_SUSPENDED: -++ err = 0; -++ break; -++ case SNDRV_PCM_STATE_XRUN: -++ err = -EPIPE; -++ break; -++ default: -++ __badfd: -++ err = -EBADFD; -++ break; -++ } -++ snd_pcm_stream_unlock_irq(substream); -++ return err; -++} -++ -++static int snd_pcm_delay(struct snd_pcm_substream *substream, -++ snd_pcm_sframes_t __user *res) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ int err; -++ snd_pcm_sframes_t n = 0; -++ -++ snd_pcm_stream_lock_irq(substream); -++ switch (runtime->status->state) { -++ case SNDRV_PCM_STATE_DRAINING: -++ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -++ goto __badfd; -++ case SNDRV_PCM_STATE_RUNNING: -++ if ((err = snd_pcm_update_hw_ptr(substream)) < 0) -++ break; -++ /* Fall through */ -++ case SNDRV_PCM_STATE_PREPARED: -++ case SNDRV_PCM_STATE_SUSPENDED: -++ err = 0; -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -++ n = snd_pcm_playback_hw_avail(runtime); -++ else -++ n = snd_pcm_capture_avail(runtime); -++ break; -++ case SNDRV_PCM_STATE_XRUN: -++ err = -EPIPE; -++ break; -++ default: -++ __badfd: -++ err = -EBADFD; -++ break; -++ } -++ snd_pcm_stream_unlock_irq(substream); -++ if (!err) -++ if (put_user(n, res)) -++ err = -EFAULT; -++ return err; -++} -++ -++static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, -++ struct snd_pcm_sync_ptr __user *_sync_ptr) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ struct snd_pcm_sync_ptr sync_ptr; -++ volatile struct snd_pcm_mmap_status *status; -++ volatile struct snd_pcm_mmap_control *control; -++ int err; -++ -++ memset(&sync_ptr, 0, sizeof(sync_ptr)); -++ if (get_user(sync_ptr.flags, (unsigned __user *)&(_sync_ptr->flags))) -++ return -EFAULT; -++ if (copy_from_user(&sync_ptr.c.control, &(_sync_ptr->c.control), sizeof(struct snd_pcm_mmap_control))) -++ return -EFAULT; -++ status = runtime->status; -++ control = runtime->control; -++ if (sync_ptr.flags & SNDRV_PCM_SYNC_PTR_HWSYNC) { -++ err = snd_pcm_hwsync(substream); -++ if (err < 0) -++ return err; -++ } -++ snd_pcm_stream_lock_irq(substream); -++ if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) -++ control->appl_ptr = sync_ptr.c.control.appl_ptr; -++ else -++ sync_ptr.c.control.appl_ptr = control->appl_ptr; -++ if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) -++ control->avail_min = sync_ptr.c.control.avail_min; -++ else -++ sync_ptr.c.control.avail_min = control->avail_min; -++ sync_ptr.s.status.state = status->state; -++ sync_ptr.s.status.hw_ptr = status->hw_ptr; -++ sync_ptr.s.status.tstamp = status->tstamp; -++ sync_ptr.s.status.suspended_state = status->suspended_state; -++ snd_pcm_stream_unlock_irq(substream); -++ if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr))) -++ return -EFAULT; -++ return 0; -++} -++ -++static int snd_pcm_common_ioctl1(struct file *file, -++ struct snd_pcm_substream *substream, -++ unsigned int cmd, void __user *arg) -++{ -++ snd_assert(substream != NULL, return -ENXIO); -++ -++ switch (cmd) { -++ case SNDRV_PCM_IOCTL_PVERSION: -++ return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0; -++ case SNDRV_PCM_IOCTL_INFO: -++ return snd_pcm_info_user(substream, arg); -++ case SNDRV_PCM_IOCTL_TSTAMP: /* just for compatibility */ -++ return 0; -++ case SNDRV_PCM_IOCTL_HW_REFINE: -++ return snd_pcm_hw_refine_user(substream, arg); -++ case SNDRV_PCM_IOCTL_HW_PARAMS: -++ return snd_pcm_hw_params_user(substream, arg); -++ case SNDRV_PCM_IOCTL_HW_FREE: -++ return snd_pcm_hw_free(substream); -++ case SNDRV_PCM_IOCTL_SW_PARAMS: -++ return snd_pcm_sw_params_user(substream, arg); -++ case SNDRV_PCM_IOCTL_STATUS: -++ return snd_pcm_status_user(substream, arg); -++ case SNDRV_PCM_IOCTL_CHANNEL_INFO: -++ return snd_pcm_channel_info_user(substream, arg); -++ case SNDRV_PCM_IOCTL_PREPARE: -++ return snd_pcm_prepare(substream, file); -++ case SNDRV_PCM_IOCTL_RESET: -++ return snd_pcm_reset(substream); -++ case SNDRV_PCM_IOCTL_START: -++ return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING); -++ case SNDRV_PCM_IOCTL_LINK: -++ return snd_pcm_link(substream, (int)(unsigned long) arg); -++ case SNDRV_PCM_IOCTL_UNLINK: -++ return snd_pcm_unlink(substream); -++ case SNDRV_PCM_IOCTL_RESUME: -++ return snd_pcm_resume(substream); -++ case SNDRV_PCM_IOCTL_XRUN: -++ return snd_pcm_xrun(substream); -++ case SNDRV_PCM_IOCTL_HWSYNC: -++ return snd_pcm_hwsync(substream); -++ case SNDRV_PCM_IOCTL_DELAY: -++ return snd_pcm_delay(substream, arg); -++ case SNDRV_PCM_IOCTL_SYNC_PTR: -++ return snd_pcm_sync_ptr(substream, arg); -++#ifdef CONFIG_SND_SUPPORT_OLD_API -++ case SNDRV_PCM_IOCTL_HW_REFINE_OLD: -++ return snd_pcm_hw_refine_old_user(substream, arg); -++ case SNDRV_PCM_IOCTL_HW_PARAMS_OLD: -++ return snd_pcm_hw_params_old_user(substream, arg); -++#endif -++ case SNDRV_PCM_IOCTL_DRAIN: -++ return snd_pcm_drain(substream); -++ case SNDRV_PCM_IOCTL_DROP: -++ return snd_pcm_drop(substream); -++ case SNDRV_PCM_IOCTL_PAUSE: -++ { -++ int res; -++ snd_pcm_stream_lock_irq(substream); -++ res = snd_pcm_pause(substream, (int)(unsigned long)arg); -++ snd_pcm_stream_unlock_irq(substream); -++ return res; -++ } -++ } -++ snd_printd("unknown ioctl = 0x%x\n", cmd); -++ return -ENOTTY; -++} -++ -++static int snd_pcm_playback_ioctl1(struct file *file, -++ struct snd_pcm_substream *substream, -++ unsigned int cmd, void __user *arg) -++{ -++ snd_assert(substream != NULL, return -ENXIO); -++ snd_assert(substream->stream == SNDRV_PCM_STREAM_PLAYBACK, return -EINVAL); -++ switch (cmd) { -++ case SNDRV_PCM_IOCTL_WRITEI_FRAMES: -++ { -++ struct snd_xferi xferi; -++ struct snd_xferi __user *_xferi = arg; -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ snd_pcm_sframes_t result; -++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN) -++ return -EBADFD; -++ if (put_user(0, &_xferi->result)) -++ return -EFAULT; -++ if (copy_from_user(&xferi, _xferi, sizeof(xferi))) -++ return -EFAULT; -++ result = snd_pcm_lib_write(substream, xferi.buf, xferi.frames); -++ __put_user(result, &_xferi->result); -++ return result < 0 ? result : 0; -++ } -++ case SNDRV_PCM_IOCTL_WRITEN_FRAMES: -++ { -++ struct snd_xfern xfern; -++ struct snd_xfern __user *_xfern = arg; -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ void __user **bufs; -++ snd_pcm_sframes_t result; -++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN) -++ return -EBADFD; -++ if (runtime->channels > 128) -++ return -EINVAL; -++ if (put_user(0, &_xfern->result)) -++ return -EFAULT; -++ if (copy_from_user(&xfern, _xfern, sizeof(xfern))) -++ return -EFAULT; -++ bufs = kmalloc(sizeof(void *) * runtime->channels, GFP_KERNEL); -++ if (bufs == NULL) -++ return -ENOMEM; -++ if (copy_from_user(bufs, xfern.bufs, sizeof(void *) * runtime->channels)) { -++ kfree(bufs); -++ return -EFAULT; -++ } -++ result = snd_pcm_lib_writev(substream, bufs, xfern.frames); -++ kfree(bufs); -++ __put_user(result, &_xfern->result); -++ return result < 0 ? result : 0; -++ } -++ case SNDRV_PCM_IOCTL_REWIND: -++ { -++ snd_pcm_uframes_t frames; -++ snd_pcm_uframes_t __user *_frames = arg; -++ snd_pcm_sframes_t result; -++ if (get_user(frames, _frames)) -++ return -EFAULT; -++ if (put_user(0, _frames)) -++ return -EFAULT; -++ result = snd_pcm_playback_rewind(substream, frames); -++ __put_user(result, _frames); -++ return result < 0 ? result : 0; -++ } -++ case SNDRV_PCM_IOCTL_FORWARD: -++ { -++ snd_pcm_uframes_t frames; -++ snd_pcm_uframes_t __user *_frames = arg; -++ snd_pcm_sframes_t result; -++ if (get_user(frames, _frames)) -++ return -EFAULT; -++ if (put_user(0, _frames)) -++ return -EFAULT; -++ result = snd_pcm_playback_forward(substream, frames); -++ __put_user(result, _frames); -++ return result < 0 ? result : 0; -++ } -++ } -++ return snd_pcm_common_ioctl1(file, substream, cmd, arg); -++} -++ -++static int snd_pcm_capture_ioctl1(struct file *file, -++ struct snd_pcm_substream *substream, -++ unsigned int cmd, void __user *arg) -++{ -++ snd_assert(substream != NULL, return -ENXIO); -++ snd_assert(substream->stream == SNDRV_PCM_STREAM_CAPTURE, return -EINVAL); -++ switch (cmd) { -++ case SNDRV_PCM_IOCTL_READI_FRAMES: -++ { -++ struct snd_xferi xferi; -++ struct snd_xferi __user *_xferi = arg; -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ snd_pcm_sframes_t result; -++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN) -++ return -EBADFD; -++ if (put_user(0, &_xferi->result)) -++ return -EFAULT; -++ if (copy_from_user(&xferi, _xferi, sizeof(xferi))) -++ return -EFAULT; -++ result = snd_pcm_lib_read(substream, xferi.buf, xferi.frames); -++ __put_user(result, &_xferi->result); -++ return result < 0 ? result : 0; -++ } -++ case SNDRV_PCM_IOCTL_READN_FRAMES: -++ { -++ struct snd_xfern xfern; -++ struct snd_xfern __user *_xfern = arg; -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ void *bufs; -++ snd_pcm_sframes_t result; -++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN) -++ return -EBADFD; -++ if (runtime->channels > 128) -++ return -EINVAL; -++ if (put_user(0, &_xfern->result)) -++ return -EFAULT; -++ if (copy_from_user(&xfern, _xfern, sizeof(xfern))) -++ return -EFAULT; -++ bufs = kmalloc(sizeof(void *) * runtime->channels, GFP_KERNEL); -++ if (bufs == NULL) -++ return -ENOMEM; -++ if (copy_from_user(bufs, xfern.bufs, sizeof(void *) * runtime->channels)) { -++ kfree(bufs); -++ return -EFAULT; -++ } -++ result = snd_pcm_lib_readv(substream, bufs, xfern.frames); -++ kfree(bufs); -++ __put_user(result, &_xfern->result); -++ return result < 0 ? result : 0; -++ } -++ case SNDRV_PCM_IOCTL_REWIND: -++ { -++ snd_pcm_uframes_t frames; -++ snd_pcm_uframes_t __user *_frames = arg; -++ snd_pcm_sframes_t result; -++ if (get_user(frames, _frames)) -++ return -EFAULT; -++ if (put_user(0, _frames)) -++ return -EFAULT; -++ result = snd_pcm_capture_rewind(substream, frames); -++ __put_user(result, _frames); -++ return result < 0 ? result : 0; -++ } -++ case SNDRV_PCM_IOCTL_FORWARD: -++ { -++ snd_pcm_uframes_t frames; -++ snd_pcm_uframes_t __user *_frames = arg; -++ snd_pcm_sframes_t result; -++ if (get_user(frames, _frames)) -++ return -EFAULT; -++ if (put_user(0, _frames)) -++ return -EFAULT; -++ result = snd_pcm_capture_forward(substream, frames); -++ __put_user(result, _frames); -++ return result < 0 ? result : 0; -++ } -++ } -++ return snd_pcm_common_ioctl1(file, substream, cmd, arg); -++} -++ -++static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, -++ unsigned long arg) -++{ -++ struct snd_pcm_file *pcm_file; -++ -++ pcm_file = file->private_data; -++ -++ if (((cmd >> 8) & 0xff) != 'A') -++ return -ENOTTY; -++ -++ return snd_pcm_playback_ioctl1(file, pcm_file->substream, cmd, -++ (void __user *)arg); -++} -++ -++static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, -++ unsigned long arg) -++{ -++ struct snd_pcm_file *pcm_file; -++ -++ pcm_file = file->private_data; -++ -++ if (((cmd >> 8) & 0xff) != 'A') -++ return -ENOTTY; -++ -++ return snd_pcm_capture_ioctl1(file, pcm_file->substream, cmd, -++ (void __user *)arg); -++} -++ -++int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, -++ unsigned int cmd, void *arg) -++{ -++ mm_segment_t fs; -++ int result; -++ -++ fs = snd_enter_user(); -++ switch (substream->stream) { -++ case SNDRV_PCM_STREAM_PLAYBACK: -++ result = snd_pcm_playback_ioctl1(NULL, substream, cmd, -++ (void __user *)arg); -++ break; -++ case SNDRV_PCM_STREAM_CAPTURE: -++ result = snd_pcm_capture_ioctl1(NULL, substream, cmd, -++ (void __user *)arg); -++ break; -++ default: -++ result = -EINVAL; -++ break; -++ } -++ snd_leave_user(fs); -++ return result; -++} -++ -++EXPORT_SYMBOL(snd_pcm_kernel_ioctl); -++ -++static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, -++ loff_t * offset) -++{ -++ struct snd_pcm_file *pcm_file; -++ struct snd_pcm_substream *substream; -++ struct snd_pcm_runtime *runtime; -++ snd_pcm_sframes_t result; -++ -++ pcm_file = file->private_data; -++ substream = pcm_file->substream; -++ snd_assert(substream != NULL, return -ENXIO); -++ runtime = substream->runtime; -++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN) -++ return -EBADFD; -++ if (!frame_aligned(runtime, count)) -++ return -EINVAL; -++ count = bytes_to_frames(runtime, count); -++ result = snd_pcm_lib_read(substream, buf, count); -++ if (result > 0) -++ result = frames_to_bytes(runtime, result); -++ return result; -++} -++ -++static ssize_t snd_pcm_write(struct file *file, const char __user *buf, -++ size_t count, loff_t * offset) -++{ -++ struct snd_pcm_file *pcm_file; -++ struct snd_pcm_substream *substream; -++ struct snd_pcm_runtime *runtime; -++ snd_pcm_sframes_t result; -++ -++ pcm_file = file->private_data; -++ substream = pcm_file->substream; -++ snd_assert(substream != NULL, result = -ENXIO; goto end); -++ runtime = substream->runtime; -++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { -++ result = -EBADFD; -++ goto end; -++ } -++ if (!frame_aligned(runtime, count)) { -++ result = -EINVAL; -++ goto end; -++ } -++ count = bytes_to_frames(runtime, count); -++ result = snd_pcm_lib_write(substream, buf, count); -++ if (result > 0) -++ result = frames_to_bytes(runtime, result); -++ end: -++ return result; -++} -++ -++static ssize_t snd_pcm_aio_read(struct kiocb *iocb, const struct iovec *iov, -++ unsigned long nr_segs, loff_t pos) -++ -++{ -++ struct snd_pcm_file *pcm_file; -++ struct snd_pcm_substream *substream; -++ struct snd_pcm_runtime *runtime; -++ snd_pcm_sframes_t result; -++ unsigned long i; -++ void __user **bufs; -++ snd_pcm_uframes_t frames; -++ -++ pcm_file = iocb->ki_filp->private_data; -++ substream = pcm_file->substream; -++ snd_assert(substream != NULL, return -ENXIO); -++ runtime = substream->runtime; -++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN) -++ return -EBADFD; -++ if (nr_segs > 1024 || nr_segs != runtime->channels) -++ return -EINVAL; -++ if (!frame_aligned(runtime, iov->iov_len)) -++ return -EINVAL; -++ frames = bytes_to_samples(runtime, iov->iov_len); -++ bufs = kmalloc(sizeof(void *) * nr_segs, GFP_KERNEL); -++ if (bufs == NULL) -++ return -ENOMEM; -++ for (i = 0; i < nr_segs; ++i) -++ bufs[i] = iov[i].iov_base; -++ result = snd_pcm_lib_readv(substream, bufs, frames); -++ if (result > 0) -++ result = frames_to_bytes(runtime, result); -++ kfree(bufs); -++ return result; -++} -++ -++static ssize_t snd_pcm_aio_write(struct kiocb *iocb, const struct iovec *iov, -++ unsigned long nr_segs, loff_t pos) -++{ -++ struct snd_pcm_file *pcm_file; -++ struct snd_pcm_substream *substream; -++ struct snd_pcm_runtime *runtime; -++ snd_pcm_sframes_t result; -++ unsigned long i; -++ void __user **bufs; -++ snd_pcm_uframes_t frames; -++ -++ pcm_file = iocb->ki_filp->private_data; -++ substream = pcm_file->substream; -++ snd_assert(substream != NULL, result = -ENXIO; goto end); -++ runtime = substream->runtime; -++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { -++ result = -EBADFD; -++ goto end; -++ } -++ if (nr_segs > 128 || nr_segs != runtime->channels || -++ !frame_aligned(runtime, iov->iov_len)) { -++ result = -EINVAL; -++ goto end; -++ } -++ frames = bytes_to_samples(runtime, iov->iov_len); -++ bufs = kmalloc(sizeof(void *) * nr_segs, GFP_KERNEL); -++ if (bufs == NULL) -++ return -ENOMEM; -++ for (i = 0; i < nr_segs; ++i) -++ bufs[i] = iov[i].iov_base; -++ result = snd_pcm_lib_writev(substream, bufs, frames); -++ if (result > 0) -++ result = frames_to_bytes(runtime, result); -++ kfree(bufs); -++ end: -++ return result; -++} -++ -++static unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait) -++{ -++ struct snd_pcm_file *pcm_file; -++ struct snd_pcm_substream *substream; -++ struct snd_pcm_runtime *runtime; -++ unsigned int mask; -++ snd_pcm_uframes_t avail; -++ -++ pcm_file = file->private_data; -++ -++ substream = pcm_file->substream; -++ snd_assert(substream != NULL, return -ENXIO); -++ runtime = substream->runtime; -++ -++ poll_wait(file, &runtime->sleep, wait); -++ -++ snd_pcm_stream_lock_irq(substream); -++ avail = snd_pcm_playback_avail(runtime); -++ switch (runtime->status->state) { -++ case SNDRV_PCM_STATE_RUNNING: -++ case SNDRV_PCM_STATE_PREPARED: -++ case SNDRV_PCM_STATE_PAUSED: -++ if (avail >= runtime->control->avail_min) { -++ mask = POLLOUT | POLLWRNORM; -++ break; -++ } -++ /* Fall through */ -++ case SNDRV_PCM_STATE_DRAINING: -++ mask = 0; -++ break; -++ default: -++ mask = POLLOUT | POLLWRNORM | POLLERR; -++ break; -++ } -++ snd_pcm_stream_unlock_irq(substream); -++ return mask; -++} -++ -++static unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait) -++{ -++ struct snd_pcm_file *pcm_file; -++ struct snd_pcm_substream *substream; -++ struct snd_pcm_runtime *runtime; -++ unsigned int mask; -++ snd_pcm_uframes_t avail; -++ -++ pcm_file = file->private_data; -++ -++ substream = pcm_file->substream; -++ snd_assert(substream != NULL, return -ENXIO); -++ runtime = substream->runtime; -++ -++ poll_wait(file, &runtime->sleep, wait); -++ -++ snd_pcm_stream_lock_irq(substream); -++ avail = snd_pcm_capture_avail(runtime); -++ switch (runtime->status->state) { -++ case SNDRV_PCM_STATE_RUNNING: -++ case SNDRV_PCM_STATE_PREPARED: -++ case SNDRV_PCM_STATE_PAUSED: -++ if (avail >= runtime->control->avail_min) { -++ mask = POLLIN | POLLRDNORM; -++ break; -++ } -++ mask = 0; -++ break; -++ case SNDRV_PCM_STATE_DRAINING: -++ if (avail > 0) { -++ mask = POLLIN | POLLRDNORM; -++ break; -++ } -++ /* Fall through */ -++ default: -++ mask = POLLIN | POLLRDNORM | POLLERR; -++ break; -++ } -++ snd_pcm_stream_unlock_irq(substream); -++ return mask; -++} -++ -++/* -++ * mmap support -++ */ -++ -++/* -++ * Only on coherent architectures, we can mmap the status and the control records -++ * for effcient data transfer. On others, we have to use HWSYNC ioctl... -++ */ -++#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA) -++/* -++ * mmap status record -++ */ -++static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area, -++ unsigned long address, int *type) -++{ -++ struct snd_pcm_substream *substream = area->vm_private_data; -++ struct snd_pcm_runtime *runtime; -++ struct page * page; -++ -++ if (substream == NULL) -++ return NOPAGE_SIGBUS; -++ runtime = substream->runtime; -++ page = virt_to_page(runtime->status); -++ get_page(page); -++ if (type) -++ *type = VM_FAULT_MINOR; -++ return page; -++} -++ -++static struct vm_operations_struct snd_pcm_vm_ops_status = -++{ -++ .nopage = snd_pcm_mmap_status_nopage, -++}; -++ -++static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file, -++ struct vm_area_struct *area) -++{ -++ struct snd_pcm_runtime *runtime; -++ long size; -++ if (!(area->vm_flags & VM_READ)) -++ return -EINVAL; -++ runtime = substream->runtime; -++ snd_assert(runtime != NULL, return -EAGAIN); -++ size = area->vm_end - area->vm_start; -++ if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status))) -++ return -EINVAL; -++ area->vm_ops = &snd_pcm_vm_ops_status; -++ area->vm_private_data = substream; -++ area->vm_flags |= VM_RESERVED; -++ return 0; -++} -++ -++/* -++ * mmap control record -++ */ -++static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area, -++ unsigned long address, int *type) -++{ -++ struct snd_pcm_substream *substream = area->vm_private_data; -++ struct snd_pcm_runtime *runtime; -++ struct page * page; -++ -++ if (substream == NULL) -++ return NOPAGE_SIGBUS; -++ runtime = substream->runtime; -++ page = virt_to_page(runtime->control); -++ get_page(page); -++ if (type) -++ *type = VM_FAULT_MINOR; -++ return page; -++} -++ -++static struct vm_operations_struct snd_pcm_vm_ops_control = -++{ -++ .nopage = snd_pcm_mmap_control_nopage, -++}; -++ -++static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file, -++ struct vm_area_struct *area) -++{ -++ struct snd_pcm_runtime *runtime; -++ long size; -++ if (!(area->vm_flags & VM_READ)) -++ return -EINVAL; -++ runtime = substream->runtime; -++ snd_assert(runtime != NULL, return -EAGAIN); -++ size = area->vm_end - area->vm_start; -++ if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control))) -++ return -EINVAL; -++ area->vm_ops = &snd_pcm_vm_ops_control; -++ area->vm_private_data = substream; -++ area->vm_flags |= VM_RESERVED; -++ return 0; -++} -++#else /* ! coherent mmap */ -++/* -++ * don't support mmap for status and control records. -++ */ -++static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file, -++ struct vm_area_struct *area) -++{ -++ return -ENXIO; -++} -++static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file, -++ struct vm_area_struct *area) -++{ -++ return -ENXIO; -++} -++#endif /* coherent mmap */ -++ -++/* -++ * nopage callback for mmapping a RAM page -++ */ -++static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area, -++ unsigned long address, int *type) -++{ -++ struct snd_pcm_substream *substream = area->vm_private_data; -++ struct snd_pcm_runtime *runtime; -++ unsigned long offset; -++ struct page * page; -++ void *vaddr; -++ size_t dma_bytes; -++ -++ if (substream == NULL) -++ return NOPAGE_SIGBUS; -++ runtime = substream->runtime; -++ offset = area->vm_pgoff << PAGE_SHIFT; -++ offset += address - area->vm_start; -++ snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_SIGBUS); -++ dma_bytes = PAGE_ALIGN(runtime->dma_bytes); -++ if (offset > dma_bytes - PAGE_SIZE) -++ return NOPAGE_SIGBUS; -++ if (substream->ops->page) { -++ page = substream->ops->page(substream, offset); -++ if (! page) -++ return NOPAGE_OOM; /* XXX: is this really due to OOM? */ -++ } else { -++ vaddr = runtime->dma_area + offset; -++ page = virt_to_page(vaddr); -++ } -++ get_page(page); -++ if (type) -++ *type = VM_FAULT_MINOR; -++ return page; -++} -++ -++static struct vm_operations_struct snd_pcm_vm_ops_data = -++{ -++ .open = snd_pcm_mmap_data_open, -++ .close = snd_pcm_mmap_data_close, -++ .nopage = snd_pcm_mmap_data_nopage, -++}; -++ -++/* -++ * mmap the DMA buffer on RAM -++ */ -++static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, -++ struct vm_area_struct *area) -++{ -++ area->vm_ops = &snd_pcm_vm_ops_data; -++ area->vm_private_data = substream; -++ area->vm_flags |= VM_RESERVED; -++ atomic_inc(&substream->mmap_count); -++ return 0; -++} -++ -++/* -++ * mmap the DMA buffer on I/O memory area -++ */ -++#if SNDRV_PCM_INFO_MMAP_IOMEM -++static struct vm_operations_struct snd_pcm_vm_ops_data_mmio = -++{ -++ .open = snd_pcm_mmap_data_open, -++ .close = snd_pcm_mmap_data_close, -++}; -++ -++int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, -++ struct vm_area_struct *area) -++{ -++ long size; -++ unsigned long offset; -++ -++#ifdef pgprot_noncached -++ area->vm_page_prot = pgprot_noncached(area->vm_page_prot); -++#endif -++ area->vm_ops = &snd_pcm_vm_ops_data_mmio; -++ area->vm_private_data = substream; -++ area->vm_flags |= VM_IO; -++ size = area->vm_end - area->vm_start; -++ offset = area->vm_pgoff << PAGE_SHIFT; -++ if (io_remap_pfn_range(area, area->vm_start, -++ (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, -++ size, area->vm_page_prot)) -++ return -EAGAIN; -++ atomic_inc(&substream->mmap_count); -++ return 0; -++} -++ -++EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem); -++#endif /* SNDRV_PCM_INFO_MMAP */ -++ -++/* -++ * mmap DMA buffer -++ */ -++int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, -++ struct vm_area_struct *area) -++{ -++ struct snd_pcm_runtime *runtime; -++ long size; -++ unsigned long offset; -++ size_t dma_bytes; -++ -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -++ if (!(area->vm_flags & (VM_WRITE|VM_READ))) -++ return -EINVAL; -++ } else { -++ if (!(area->vm_flags & VM_READ)) -++ return -EINVAL; -++ } -++ runtime = substream->runtime; -++ snd_assert(runtime != NULL, return -EAGAIN); -++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN) -++ return -EBADFD; -++ if (!(runtime->info & SNDRV_PCM_INFO_MMAP)) -++ return -ENXIO; -++ if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || -++ runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) -++ return -EINVAL; -++ size = area->vm_end - area->vm_start; -++ offset = area->vm_pgoff << PAGE_SHIFT; -++ dma_bytes = PAGE_ALIGN(runtime->dma_bytes); -++ if ((size_t)size > dma_bytes) -++ return -EINVAL; -++ if (offset > dma_bytes - size) -++ return -EINVAL; -++ -++ if (substream->ops->mmap) -++ return substream->ops->mmap(substream, area); -++ else -++ return snd_pcm_default_mmap(substream, area); -++} -++ -++EXPORT_SYMBOL(snd_pcm_mmap_data); -++ -++static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) -++{ -++ struct snd_pcm_file * pcm_file; -++ struct snd_pcm_substream *substream; -++ unsigned long offset; -++ -++ pcm_file = file->private_data; -++ substream = pcm_file->substream; -++ snd_assert(substream != NULL, return -ENXIO); -++ -++ offset = area->vm_pgoff << PAGE_SHIFT; -++ switch (offset) { -++ case SNDRV_PCM_MMAP_OFFSET_STATUS: -++ if (pcm_file->no_compat_mmap) -++ return -ENXIO; -++ return snd_pcm_mmap_status(substream, file, area); -++ case SNDRV_PCM_MMAP_OFFSET_CONTROL: -++ if (pcm_file->no_compat_mmap) -++ return -ENXIO; -++ return snd_pcm_mmap_control(substream, file, area); -++ default: -++ return snd_pcm_mmap_data(substream, file, area); -++ } -++ return 0; -++} -++ -++static int snd_pcm_fasync(int fd, struct file * file, int on) -++{ -++ struct snd_pcm_file * pcm_file; -++ struct snd_pcm_substream *substream; -++ struct snd_pcm_runtime *runtime; -++ int err; -++ -++ pcm_file = file->private_data; -++ substream = pcm_file->substream; -++ snd_assert(substream != NULL, return -ENXIO); -++ runtime = substream->runtime; -++ -++ err = fasync_helper(fd, file, on, &runtime->fasync); -++ if (err < 0) -++ return err; -++ return 0; -++} -++ -++/* -++ * ioctl32 compat -++ */ -++#ifdef CONFIG_COMPAT -++#include "pcm_compat.c" -++#else -++#define snd_pcm_ioctl_compat NULL -++#endif -++ -++/* -++ * To be removed helpers to keep binary compatibility -++ */ -++ -++#ifdef CONFIG_SND_SUPPORT_OLD_API -++#define __OLD_TO_NEW_MASK(x) ((x&7)|((x&0x07fffff8)<<5)) -++#define __NEW_TO_OLD_MASK(x) ((x&7)|((x&0xffffff00)>>5)) -++ -++static void snd_pcm_hw_convert_from_old_params(struct snd_pcm_hw_params *params, -++ struct snd_pcm_hw_params_old *oparams) -++{ -++ unsigned int i; -++ -++ memset(params, 0, sizeof(*params)); -++ params->flags = oparams->flags; -++ for (i = 0; i < ARRAY_SIZE(oparams->masks); i++) -++ params->masks[i].bits[0] = oparams->masks[i]; -++ memcpy(params->intervals, oparams->intervals, sizeof(oparams->intervals)); -++ params->rmask = __OLD_TO_NEW_MASK(oparams->rmask); -++ params->cmask = __OLD_TO_NEW_MASK(oparams->cmask); -++ params->info = oparams->info; -++ params->msbits = oparams->msbits; -++ params->rate_num = oparams->rate_num; -++ params->rate_den = oparams->rate_den; -++ params->fifo_size = oparams->fifo_size; -++} -++ -++static void snd_pcm_hw_convert_to_old_params(struct snd_pcm_hw_params_old *oparams, -++ struct snd_pcm_hw_params *params) -++{ -++ unsigned int i; -++ -++ memset(oparams, 0, sizeof(*oparams)); -++ oparams->flags = params->flags; -++ for (i = 0; i < ARRAY_SIZE(oparams->masks); i++) -++ oparams->masks[i] = params->masks[i].bits[0]; -++ memcpy(oparams->intervals, params->intervals, sizeof(oparams->intervals)); -++ oparams->rmask = __NEW_TO_OLD_MASK(params->rmask); -++ oparams->cmask = __NEW_TO_OLD_MASK(params->cmask); -++ oparams->info = params->info; -++ oparams->msbits = params->msbits; -++ oparams->rate_num = params->rate_num; -++ oparams->rate_den = params->rate_den; -++ oparams->fifo_size = params->fifo_size; -++} -++ -++static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream, -++ struct snd_pcm_hw_params_old __user * _oparams) -++{ -++ struct snd_pcm_hw_params *params; -++ struct snd_pcm_hw_params_old *oparams = NULL; -++ int err; -++ -++ params = kmalloc(sizeof(*params), GFP_KERNEL); -++ if (!params) { -++ err = -ENOMEM; -++ goto out; -++ } -++ oparams = kmalloc(sizeof(*oparams), GFP_KERNEL); -++ if (!oparams) { -++ err = -ENOMEM; -++ goto out; -++ } -++ -++ if (copy_from_user(oparams, _oparams, sizeof(*oparams))) { -++ err = -EFAULT; -++ goto out; -++ } -++ snd_pcm_hw_convert_from_old_params(params, oparams); -++ err = snd_pcm_hw_refine(substream, params); -++ snd_pcm_hw_convert_to_old_params(oparams, params); -++ if (copy_to_user(_oparams, oparams, sizeof(*oparams))) { -++ if (!err) -++ err = -EFAULT; -++ } -++out: -++ kfree(params); -++ kfree(oparams); -++ return err; -++} -++ -++static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream, -++ struct snd_pcm_hw_params_old __user * _oparams) -++{ -++ struct snd_pcm_hw_params *params; -++ struct snd_pcm_hw_params_old *oparams = NULL; -++ int err; -++ -++ params = kmalloc(sizeof(*params), GFP_KERNEL); -++ if (!params) { -++ err = -ENOMEM; -++ goto out; -++ } -++ oparams = kmalloc(sizeof(*oparams), GFP_KERNEL); -++ if (!oparams) { -++ err = -ENOMEM; -++ goto out; -++ } -++ if (copy_from_user(oparams, _oparams, sizeof(*oparams))) { -++ err = -EFAULT; -++ goto out; -++ } -++ snd_pcm_hw_convert_from_old_params(params, oparams); -++ err = snd_pcm_hw_params(substream, params); -++ snd_pcm_hw_convert_to_old_params(oparams, params); -++ if (copy_to_user(_oparams, oparams, sizeof(*oparams))) { -++ if (!err) -++ err = -EFAULT; -++ } -++out: -++ kfree(params); -++ kfree(oparams); -++ return err; -++} -++#endif /* CONFIG_SND_SUPPORT_OLD_API */ -++ -++/* -++ * Register section -++ */ -++ -++const struct file_operations snd_pcm_f_ops[2] = { -++ { -++ .owner = THIS_MODULE, -++ .write = snd_pcm_write, -++ .aio_write = snd_pcm_aio_write, -++ .open = snd_pcm_playback_open, -++ .release = snd_pcm_release, -++ .poll = snd_pcm_playback_poll, -++ .unlocked_ioctl = snd_pcm_playback_ioctl, -++ .compat_ioctl = snd_pcm_ioctl_compat, -++ .mmap = snd_pcm_mmap, -++ .fasync = snd_pcm_fasync, -++ }, -++ { -++ .owner = THIS_MODULE, -++ .read = snd_pcm_read, -++ .aio_read = snd_pcm_aio_read, -++ .open = snd_pcm_capture_open, -++ .release = snd_pcm_release, -++ .poll = snd_pcm_capture_poll, -++ .unlocked_ioctl = snd_pcm_capture_ioctl, -++ .compat_ioctl = snd_pcm_ioctl_compat, -++ .mmap = snd_pcm_mmap, -++ .fasync = snd_pcm_fasync, -++ } -++}; -+diff -urN linux-2.6.24.7.old/sound/oss/Kconfig linux-2.6.24.7/sound/oss/Kconfig -+--- linux-2.6.24.7.old/sound/oss/Kconfig 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/sound/oss/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -5,6 +5,91 @@ -+ # -+ # Prompt user for primary drivers. -+ -++config OSS_OBSOLETE -++ bool "Obsolete OSS drivers" -++ depends on SOUND_PRIME -++ help -++ This option enables support for obsolete OSS drivers that -++ are scheduled for removal in the near future. -++ -++ Please contact Adrian Bunk if you had to -++ say Y here because your hardware is not properly supported -++ by ALSA. -++ -++ If unsure, say N. -++ -++config SOUND_JZ_AC97 -++ bool "Jz On-Chip AC97 driver" -++ depends on OSS_OBSOLETE -++ help -++ Say Y here if you have want to select the on-chip AC97 driver -++ on Jz4730/Jz4740/Jz5730. -++ -++config SOUND_JZ_I2S -++ bool "Jz On-Chip I2S driver" -++ depends on OSS_OBSOLETE -++ help -++ Say Y here if you have want to select the on-chip I2S driver -++ on Jz4730/Jz4740/Jz5730. -++ -++config SOUND_JZ_PCM -++ bool "Jz On-Chip PCM driver" -++ depends on SOC_JZ4750 -++ help -++ Say Y here if you have want to select the on-chip PCM driver -++ on Jz4750. -++ -++choice -++ prompt "I2S codec type" -++ depends on SOUND_JZ_I2S -++ -++config I2S_AK4642EN -++ bool "AK4642EN" -++ depends on SOC_JZ4730 -++ help -++ Answer Y if you have an external AK4642EN codec. -++ -++config I2S_ICODEC -++ bool "Internal On-Chip codec" -++ depends on SOC_JZ4740 -++ help -++ Answer Y if you have an internal I2S codec. -++ -++config I2S_DLV -++ bool "Internal On-Chip codec on Jz4750 or Jz4750d" -++ depends on SOC_JZ4750 || SOC_JZ4750D -++ help -++ Answer Y if you have an internal I2S codec on Jz4750 or Jz4750d. -++ -++endchoice -++ -++choice -++ prompt "PCM codec type" -++ depends on SOUND_JZ_PCM -++ -++config PCM_TLV320AIC1106 -++ bool "TLV320AIC1106" -++ help -++ Answer Y if you have an TI tlv320aic 1106 codec. -++ -++endchoice -++ -++config SOUND_BT878 -++ tristate "BT878 audio dma" -++ depends on SOUND_PRIME && PCI && OSS_OBSOLETE -++ ---help--- -++ Audio DMA support for bt878 based grabber boards. As you might have -++ already noticed, bt878 is listed with two functions in /proc/pci. -++ Function 0 does the video stuff (bt848 compatible), function 1 does -++ the same for audio data. This is a driver for the audio part of -++ the chip. If you say 'Y' here you get a oss-compatible dsp device -++ where you can record from. If you want just watch TV you probably -++ don't need this driver as most TV cards handle sound with a short -++ cable from the TV card to your sound card's line-in. -++ -++ To compile this driver as a module, choose M here: the module will -++ be called btaudio. -++ -+ config SOUND_BCM_CS4297A -+ tristate "Crystal Sound CS4297a (for Swarm)" -+ depends on SOUND_PRIME && SIBYTE_SWARM -+@@ -15,6 +100,13 @@ -+ note that CONFIG_KGDB should not be enabled at the same -+ time, since it also attempts to use this UART port. -+ -++config SOUND_ICH -++ tristate "Intel ICH (i8xx) audio support" -++ depends on SOUND_PRIME && PCI && OSS_OBSOLETE -++ help -++ Support for integral audio in Intel's I/O Controller Hub (ICH) -++ chipset, as used on the 810/820/840 motherboards. -++ -+ config SOUND_VWSND -+ tristate "SGI Visual Workstation Sound" -+ depends on SOUND_PRIME && X86_VISWS -+@@ -31,6 +123,14 @@ -+ Say Y or M if you have an SGI Indy or Indigo2 system and want to be able to -+ use its on-board A2 audio system. -+ -++config SOUND_VRC5477 -++ tristate "NEC Vrc5477 AC97 sound" -++ depends on SOUND_PRIME && DDB5477 -++ help -++ Say Y here to enable sound support for the NEC Vrc5477 chip, an -++ integrated, multi-function controller chip for MIPS CPUs. Works -++ with the AC97 codec. -++ -+ config SOUND_AU1550_AC97 -+ tristate "Au1550/Au1200 AC97 Sound" -+ select SND_AC97_CODEC -+@@ -75,7 +175,7 @@ -+ -+ -+ This driver differs slightly from OSS/Free, so PLEASE READ the -+- comments at the top of . -++ comments at the top of . -+ -+ config SOUND_MSNDCLAS -+ tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey" -+@@ -302,9 +402,29 @@ -+ and Pinnacle). Larger values reduce the chance of data overruns at -+ the expense of overall latency. If unsure, use the default. -+ -++config SOUND_VIA82CXXX -++ tristate "VIA 82C686 Audio Codec" -++ depends on SOUND_PRIME && PCI && OSS_OBSOLETE -++ help -++ Say Y here to include support for the audio codec found on VIA -++ 82Cxxx-based chips. Typically these are built into a motherboard. -++ -++ DO NOT select Sound Blaster or Adlib with this driver, unless -++ you have a Sound Blaster or Adlib card in addition to your VIA -++ audio chip. -++ -++config MIDI_VIA82CXXX -++ bool "VIA 82C686 MIDI" -++ depends on SOUND_VIA82CXXX && ISA_DMA_API -++ help -++ Answer Y to use the MIDI interface of the Via686. You may need to -++ enable this in the BIOS before it will work. This is for connection -++ to external MIDI hardware, and is not required for software playback -++ of MIDI files. -++ -+ config SOUND_OSS -+ tristate "OSS sound modules" -+- depends on SOUND_PRIME && ISA_DMA_API && VIRT_TO_BUS -++ depends on SOUND_PRIME && ISA_DMA_API -+ help -+ OSS is the Open Sound System suite of sound card drivers. They make -+ sound programming easier since they provide a common API. Say Y or -+@@ -336,10 +456,23 @@ -+ -+ Say Y unless you have 16MB or more RAM or a PCI sound card. -+ -++config SOUND_CS4232 -++ tristate "Crystal CS4232 based (PnP) cards" -++ depends on SOUND_OSS && OSS_OBSOLETE -++ help -++ Say Y here if you have a card based on the Crystal CS4232 chip set, -++ which uses its own Plug and Play protocol. -++ -++ If you compile the driver into the kernel, you have to add -++ "cs4232=,,,,," to the kernel -++ command line. -++ -++ See for more information on -++ configuring this card. -++ -+ config SOUND_SSCAPE -+ tristate "Ensoniq SoundScape support" -+ depends on SOUND_OSS -+- depends on VIRT_TO_BUS -+ help -+ Answer Y if you have a sound card based on the Ensoniq SoundScape -+ chipset. Such cards are being manufactured at least by Ensoniq, Spea -+@@ -564,7 +697,7 @@ -+ questions. -+ -+ Read the file and the head of -+- as well as -++ as well as -+ to get more information -+ about this driver and its configuration. -+ -+@@ -642,6 +775,13 @@ -+ Say Y here to include support for the Rockwell WaveArtist sound -+ system. This driver is mainly for the NetWinder. -+ -++config SOUND_TVMIXER -++ tristate "TV card (bt848) mixer support" -++ depends on SOUND_PRIME && I2C && VIDEO_V4L1 && OSS_OBSOLETE -++ help -++ Support for audio mixer facilities on the BT848 TV frame-grabber -++ card. -++ -+ config SOUND_KAHLUA -+ tristate "XpressAudio Sound Blaster emulation" -+ depends on SOUND_SB -+diff -urN linux-2.6.24.7.old/sound/oss/Makefile linux-2.6.24.7/sound/oss/Makefile -+--- linux-2.6.24.7.old/sound/oss/Makefile 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/sound/oss/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -10,6 +10,12 @@ -+ -+ # Please leave it as is, cause the link order is significant ! -+ -++obj-$(CONFIG_SOUND_JZ_AC97) += jz_ac97.o ac97_codec.o -++obj-$(CONFIG_I2S_AK4642EN) += ak4642en.o -++obj-$(CONFIG_I2S_ICODEC) += jzcodec.o jz_i2s.o -++obj-$(CONFIG_I2S_DLV) += jzdlv.o jz_i2s.o -++obj-$(CONFIG_SOUND_JZ_PCM) += jz_pcm_tlv320aic1106_dma.o -++ -+ obj-$(CONFIG_SOUND_SH_DAC_AUDIO) += sh_dac_audio.o -+ obj-$(CONFIG_SOUND_HAL2) += hal2.o -+ obj-$(CONFIG_SOUND_AEDSP16) += aedsp16.o -+diff -urN linux-2.6.24.7.old/sound/oss/ak4642en.c linux-2.6.24.7/sound/oss/ak4642en.c -+--- linux-2.6.24.7.old/sound/oss/ak4642en.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/oss/ak4642en.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,712 @@ -++/* -++ * linux/sound/oss/ak4642en.c -++ * -++ * AKM ak4642en codec chip driver to I2S interface -++ * -++ * Copyright (c) 2005-2007 Ingenic Semiconductor Inc. -++ * Author: -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ * Because the normal application of AUDIO devices are focused on Little_endian, -++ * then we only perform the little endian data format in driver. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "sound_config.h" -++ -++extern mixer_info info; -++extern _old_mixer_info old_info; -++extern int abnormal_data_count; -++ -++extern void (*clear_codec_mode)(void); -++extern void (*set_codec_gpio_pin)(void); -++extern void (*each_time_init_codec)(void); -++extern void (*set_codec_record)(void); -++extern void (*set_codec_replay)(void); -++extern void (*clear_codec_record)(void); -++extern void (*clear_codec_replay)(void); -++extern void (*set_codec_speed)(int range); -++extern void (*codec_mixer_old_info_id_name)(void); -++extern void (*codec_mixer_info_id_name)(void); -++extern void (*set_codec_volume)(int val); -++extern void (*set_codec_mic)(int val); -++extern void (*i2s_resume_codec)(void); -++extern void (*i2s_suspend_codec)(int wr,int rd); -++extern void (*set_replay_hp_or_speaker)(void); -++ -++#define I2S_PDN 68 -++#define JACK_PLUG_PIN 83 -++#define JACK_PLUG_IRQ (IRQ_GPIO_0 + JACK_PLUG_PIN) -++ -++static int jack_plug_level, old_level; -++static unsigned int i2c_addr = 0x26; //AK4642EN device address at I2C bus -++static unsigned int i2c_clk = 100000;//AK4642EN 400kHz max,but 100kHz here -++static unsigned int spk_hp = 0; -++static int codec_volume; -++ -++void set_ak4642en_gpio_pin(void); -++void each_time_init_ak4642en(void); -++void set_ak4642en_replay(void); -++void set_ak4642en_record(void); -++void turn_on_ak4642en(void); -++void turn_off_ak4642en(void); -++void set_ak4642en_speed(int rate); -++void reset_ak4642en(void); -++void ak4642en_mixer_old_info_id_name(void); -++void ak4642en_mixer_info_id_name(void); -++void set_ak4642en_bass(int val); -++void set_ak4642en_volume(int val); -++void set_ak4642en_mic(int val); -++void resume_ak4642en(void); -++void suspend_ak4642en(int wr,int rd); -++ -++static void write_reg(u8 reg, u8 val) -++{ -++ i2c_open(); -++ i2c_setclk(i2c_clk); -++ i2c_write((i2c_addr >> 1), &val, reg, 1); -++ i2c_close(); -++} -++ -++#if 0 -++static u8 read_reg(u8 reg) -++{ -++ u8 val; -++ i2c_open(); -++ i2c_setclk(i2c_clk); -++ i2c_read((i2c_addr >> 1), &val, reg, 1); -++ i2c_close(); -++ return val; -++} -++ -++static u16 i2s_codec_read(u8 reg) -++{ -++ u16 value; -++ value = read_reg(reg); -++ return value; -++} -++#endif -++ -++static void i2s_codec_write(u8 reg, u16 data) -++{ -++ u8 val = data & 0xff; -++ write_reg(reg, val); -++} -++ -++void set_ak4642en_gpio_pin(void) -++{ -++ //set AIC pin to I2S slave mode,only GPIO70,71,77,78 -++ __gpio_as_output(68); -++ __gpio_clear_pin(68); -++ __gpio_as_output(69); -++ __gpio_clear_pin(69); -++ __gpio_as_output(70); -++ __gpio_clear_pin(70); -++ __gpio_as_input(71); -++ __gpio_clear_pin(71); -++ __gpio_as_input(77); -++ __gpio_clear_pin(77); -++ __gpio_as_input(78); -++ __gpio_clear_pin(78); -++ REG_GPIO_GPALR(2) &= 0xC3FF0CFF; -++ REG_GPIO_GPALR(2) |= 0x14005000; -++ //set SCC clock initialization -++ REG_SCC1_CR(SCC1_BASE) = 0x00000000; -++ udelay(2); -++ REG_SCC1_CR(SCC1_BASE) |= 1 << 31; -++ udelay(2); -++ -++ __gpio_as_output(I2S_PDN); -++ __gpio_set_pin(I2S_PDN); -++ udelay(5); -++ __gpio_clear_pin(I2S_PDN); -++ ndelay(300);//>150ns -++ __gpio_set_pin(I2S_PDN); -++ mdelay(1); -++ //set PLL Master mode -++ i2s_codec_write(0x01, 0x0008);//master -++ i2s_codec_write(0x04, 0x006b);//ref:12MHz;BITCLK:64fs;I2S compli -++ i2s_codec_write(0x05, 0x000b);//sync:48KHz; -++ i2s_codec_write(0x00, 0x0040);//PMVCM -++ i2s_codec_write(0x01, 0x0009);//master,PLL enable -++ mdelay(40); -++ jack_plug_level = 10; -++ old_level = 100; -++ spk_hp = 0; -++ __gpio_disable_pull(JACK_PLUG_PIN); -++ udelay(10); -++ __gpio_as_input(JACK_PLUG_PIN); -++ jack_plug_level = __gpio_get_pin(JACK_PLUG_PIN); -++ //i suppose jack_plug_lvel is 1 indicate with HPO -++ if (jack_plug_level > 1 || jack_plug_level <0) -++ printk("Audio ak4642en codec Jack plug level is wrong!\n"); -++ if (jack_plug_level) -++ __gpio_as_irq_fall_edge(JACK_PLUG_PIN); -++ else -++ __gpio_as_irq_rise_edge(JACK_PLUG_PIN); -++} -++ -++void clear_ak4642en_mode(void) -++{ -++ spk_hp = 0; -++ i2s_codec_write(0x01, 0x0008);//master,PLL disable -++ //free_irq(JACK_PLUG_IRQ, i2s_controller); -++ __gpio_clear_pin(I2S_PDN); -++ udelay(2); -++ REG_SCC1_CR(SCC1_BASE) &= 0 << 31; -++ udelay(2); -++} -++ -++void set_ak4642en_replay(void) -++{ -++ //for poll -++ /*jack_plug_level is H for SPK,is L for HP*/ -++ jack_plug_level = __gpio_get_pin(JACK_PLUG_PIN); -++ if(old_level == jack_plug_level) -++ return; -++ old_level = jack_plug_level; -++ if(spk_hp == 1) -++ { -++ if(jack_plug_level == 1) -++ { -++ //now HeadPhone output,so clear SPK -++ i2s_codec_write(0x02, 0x0020); -++ i2s_codec_write(0x02, 0x0000); -++ i2s_codec_write(0x00, 0x0040); -++ } -++ else -++ { -++ //now Speaker output,so clear HP -++ i2s_codec_write(0x01, 0x0039); -++ i2s_codec_write(0x01, 0x0009); -++ i2s_codec_write(0x00, 0x0040); -++ i2s_codec_write(0x0e, 0x0000); -++ i2s_codec_write(0x0f, 0x0008); -++ } -++ } -++ spk_hp = 1; -++ if(jack_plug_level == 1) -++ { -++ //for HeadPhone output -++ i2s_codec_write(0x00, 0x0060); // -++ i2s_codec_write(0x0f, 0x0009); //5-10 -++ -++ i2s_codec_write(0x00, 0x0064); // -++ i2s_codec_write(0x09, 0x0091);// volume control 0dB -++ i2s_codec_write(0x0c, 0x0091);// 0dB(right) -++ //eq off -++ i2s_codec_write(0x11, 0x0000);//5-10 -++ i2s_codec_write(0x01, 0x0039); // -++ -++ i2s_codec_write(0x01, 0x0079); // -++ } -++ else -++ { -++ //for Speaker output -++ i2s_codec_write(0x00, 0x0040); -++ i2s_codec_write(0x02, 0x0020); -++ -++ i2s_codec_write(0x03, 0x0018);//5-10 -++ i2s_codec_write(0x06, 0x003c); -++ -++ i2s_codec_write(0x08, 0x00A1);//5-10 -++ -++ i2s_codec_write(0x0b, 0x0040); //5-10 -++ -++ i2s_codec_write(0x07, 0x002d); //5-10 -++ i2s_codec_write(0x09, 0x0091); -++ i2s_codec_write(0x0c, 0x0091); -++ //HP volume output value -++ -++ i2s_codec_write(0x0a, codec_volume);//5-10 -++ i2s_codec_write(0x0d, codec_volume);//5-10 -++ -++ i2s_codec_write(0x00, 0x0074); -++ i2s_codec_write(0x02, 0x00a0); -++ } -++} -++ -++void set_ak4642en_record(void) -++{ -++ abnormal_data_count = 0; -++ i2s_codec_write(0x02, 0x0004); -++ i2s_codec_write(0x03, 0x0038);// recording volume add -++ i2s_codec_write(0x06, 0x0000);//for ALC short waiting time -++ i2s_codec_write(0x08, 0x00e1); -++ i2s_codec_write(0x0b, 0x0000); -++ i2s_codec_write(0x07, 0x0021); // ALC on -++ -++ i2s_codec_write(0x10, 0x0000);//0x0001 -++ //i2s_codec_write(0x10, 0x0001);//0x0001 -++ i2s_codec_write(0x01, 0x0039); //for open pop noise -++ i2s_codec_write(0x01, 0x0079); -++ i2s_codec_write(0x00, 0x0065); -++ mdelay(300); -++} -++ -++void clear_ak4642en_replay(void) -++{ -++ //for poll -++ old_level = 100; -++ spk_hp = 0; -++ if(jack_plug_level == 1) -++ { -++ //for HeadPhone output -++ i2s_codec_write(0x01, 0x0039); // for close pop noise -++ mdelay(300); -++ i2s_codec_write(0x01, 0x0009); //PLL on I2S -++ i2s_codec_write(0x07, 0x0001); -++ i2s_codec_write(0x11, 0x0000); -++ i2s_codec_write(0x00, 0x0040); -++ i2s_codec_write(0x0f, 0x0008); // for open pop noise -++ } -++ else -++ { -++ //for Speaker output -++ i2s_codec_write(0x02, 0x0020); -++ i2s_codec_write(0x07, 0x0001); -++ i2s_codec_write(0x11, 0x0000); -++ i2s_codec_write(0x02, 0x0000); -++ i2s_codec_write(0x00, 0x0040); // for close pop noise -++ } -++} -++ -++void clear_ak4642en_record(void) -++{ -++ //for Mic input(Stereo) -++ i2s_codec_write(0x02, 0x0001); -++ i2s_codec_write(0x07, 0x0001); -++ i2s_codec_write(0x11, 0x0000); -++} -++ -++void each_time_init_ak4642en(void) -++{ -++ __i2s_disable(); -++ __i2s_as_slave(); -++ __i2s_set_sample_size(16); -++} -++ -++void set_ak4642en_speed(int rate) -++{ -++ //codec work at frequency -++ unsigned short speed = 0; -++ unsigned short val = 0; -++ switch (rate) -++ { -++ case 8000: -++ speed = 0x00; -++ if(jack_plug_level == 1) //speaker -++ { -++ i2s_codec_write(0x16, 0x0000); -++ i2s_codec_write(0x17, 0x0000); -++ i2s_codec_write(0x18, 0x0000); -++ i2s_codec_write(0x19, 0x0000); -++ i2s_codec_write(0x1A, 0x0000); -++ i2s_codec_write(0x1B, 0x0000); -++ i2s_codec_write(0x1C, 0x0027);//800hz -++ i2s_codec_write(0x1D, 0x0018); -++ i2s_codec_write(0x1E, 0x00b2); -++ i2s_codec_write(0x1F, 0x002f); -++ i2s_codec_write(0x11, 0x0010); //eq on -++ } -++ break; -++ case 12000: -++ speed = 0x01; -++ if(jack_plug_level == 1) -++ { -++ i2s_codec_write(0x16, 0x0000); -++ i2s_codec_write(0x17, 0x0000); -++ i2s_codec_write(0x18, 0x0000); -++ i2s_codec_write(0x19, 0x0000); -++ i2s_codec_write(0x1A, 0x0000); -++ i2s_codec_write(0x1B, 0x0000); -++ i2s_codec_write(0x1C, 0x0064); -++ i2s_codec_write(0x1D, 0x001a); -++ i2s_codec_write(0x1E, 0x0038); -++ i2s_codec_write(0x1F, 0x002b); -++ i2s_codec_write(0x11, 0x0010); //eq on -++ } -++ break; -++ case 16000: -++ speed = 0x02; -++ if(jack_plug_level == 1) -++ { -++ i2s_codec_write(0x16, 0x00af); -++ i2s_codec_write(0x17, 0x0020); -++ i2s_codec_write(0x18, 0x0043); -++ i2s_codec_write(0x19, 0x001a); -++ i2s_codec_write(0x1A, 0x00af); -++ i2s_codec_write(0x1B, 0x0020); -++ i2s_codec_write(0x1C, 0x00a0); -++ i2s_codec_write(0x1D, 0x001b); -++ i2s_codec_write(0x1E, 0x00c0); -++ i2s_codec_write(0x1F, 0x0028); -++ i2s_codec_write(0x11, 0x0018); //eq on -++ } -++ break; -++ case 24000: -++ speed = 0x03; -++ if(jack_plug_level == 1) -++ { -++ i2s_codec_write(0x16, 0x0086); -++ i2s_codec_write(0x17, 0x0015); -++ i2s_codec_write(0x18, 0x005d); -++ i2s_codec_write(0x19, 0x0006); -++ i2s_codec_write(0x1A, 0x0086); -++ i2s_codec_write(0x1B, 0x0015); -++ i2s_codec_write(0x1C, 0x00f5); -++ i2s_codec_write(0x1D, 0x001c); -++ i2s_codec_write(0x1E, 0x0016); -++ i2s_codec_write(0x1F, 0x0026); -++ i2s_codec_write(0x11, 0x0018); //eq on -++ } -++ break; -++ case 7350: -++ speed = 0x04; -++ if(jack_plug_level == 1) -++ { -++ i2s_codec_write(0x16, 0x0000); -++ i2s_codec_write(0x17, 0x0000); -++ i2s_codec_write(0x18, 0x0000); -++ i2s_codec_write(0x19, 0x0000); -++ i2s_codec_write(0x1A, 0x0000); -++ i2s_codec_write(0x1B, 0x0000); -++ i2s_codec_write(0x1C, 0x0027); -++ i2s_codec_write(0x1D, 0x0018); -++ i2s_codec_write(0x1E, 0x00b2); -++ i2s_codec_write(0x1F, 0x002f); -++ i2s_codec_write(0x11, 0x0010); //eq on -++ } -++ break; -++ case 11025: -++ speed = 0x05; -++ if(jack_plug_level == 1) -++ { -++ i2s_codec_write(0x16, 0x0059); -++ i2s_codec_write(0x17, 0x000d); -++ i2s_codec_write(0x18, 0x00cb); -++ i2s_codec_write(0x19, 0x0037); -++ i2s_codec_write(0x1A, 0x0059); -++ i2s_codec_write(0x1B, 0x000d); -++ i2s_codec_write(0x1C, 0x0046); -++ i2s_codec_write(0x1D, 0x001e); -++ i2s_codec_write(0x1E, 0x0074); -++ i2s_codec_write(0x1F, 0x0023); -++ i2s_codec_write(0x11, 0x0018); //eq on -++ } -++ break; -++ case 14700: -++ speed = 0x06; -++ if(jack_plug_level == 1) -++ { -++ i2s_codec_write(0x16, 0x0000); -++ i2s_codec_write(0x17, 0x0000); -++ i2s_codec_write(0x18, 0x0000); -++ i2s_codec_write(0x19, 0x0000); -++ i2s_codec_write(0x1A, 0x0000); -++ i2s_codec_write(0x1B, 0x0000); -++ i2s_codec_write(0x1C, 0x004a); -++ i2s_codec_write(0x1D, 0x001b); -++ i2s_codec_write(0x1E, 0x006c); -++ i2s_codec_write(0x1F, 0x0029); -++ i2s_codec_write(0x11, 0x0010); //eq on -++ } -++ break; -++ case 22050: -++ speed = 0x07; -++ if(jack_plug_level == 1) -++ { -++ i2s_codec_write(0x16, 0x002d); -++ i2s_codec_write(0x17, 0x0017); -++ i2s_codec_write(0x18, 0x0050); -++ i2s_codec_write(0x19, 0x0009); -++ i2s_codec_write(0x1A, 0x002d); -++ i2s_codec_write(0x1B, 0x0017); -++ i2s_codec_write(0x1C, 0x00d7); -++ i2s_codec_write(0x1D, 0x001c); -++ i2s_codec_write(0x1E, 0x0093); -++ i2s_codec_write(0x1F, 0x0026); -++ i2s_codec_write(0x11, 0x0018); //eq on -++ } -++ break; -++ case 32000: -++ speed = 0x0a; -++ if(jack_plug_level == 1) -++ { -++ i2s_codec_write(0x16, 0x0012); -++ i2s_codec_write(0x17, 0x0011); -++ i2s_codec_write(0x18, 0x006e); -++ i2s_codec_write(0x19, 0x003e); -++ i2s_codec_write(0x1A, 0x0012); -++ i2s_codec_write(0x1B, 0x0011); -++ i2s_codec_write(0x1C, 0x00aa); -++ i2s_codec_write(0x1D, 0x001d); -++ i2s_codec_write(0x1E, 0x00ab); -++ i2s_codec_write(0x1F, 0x0024); -++ i2s_codec_write(0x11, 0x0018); //eq on -++ } -++ break; -++ case 48000: -++ speed = 0x0b; -++ if(jack_plug_level == 1) -++ { -++ i2s_codec_write(0x16, 0x0082); -++ i2s_codec_write(0x17, 0x000c); -++ i2s_codec_write(0x18, 0x004b); -++ i2s_codec_write(0x19, 0x0036); -++ i2s_codec_write(0x1A, 0x0082); -++ i2s_codec_write(0x1B, 0x000c); -++ i2s_codec_write(0x1C, 0x0068); -++ i2s_codec_write(0x1D, 0x001e); -++ i2s_codec_write(0x1E, 0x0030); -++ i2s_codec_write(0x1F, 0x0023); -++ i2s_codec_write(0x11, 0x0018); //eq on -++ } -++ break; -++ case 29400: -++ speed = 0x0e; -++ if(jack_plug_level == 1) -++ { -++ i2s_codec_write(0x16, 0x003d); -++ i2s_codec_write(0x17, 0x0012); -++ i2s_codec_write(0x18, 0x0083); -++ i2s_codec_write(0x19, 0x0000); -++ i2s_codec_write(0x1A, 0x003d); -++ i2s_codec_write(0x1B, 0x0012); -++ i2s_codec_write(0x1C, 0x0079); -++ i2s_codec_write(0x1D, 0x001d); -++ i2s_codec_write(0x1E, 0x000d); -++ i2s_codec_write(0x1F, 0x0025); -++ i2s_codec_write(0x11, 0x0018); //eq on -++ } -++ break; -++ case 44100: -++ speed = 0x0f; -++ if(jack_plug_level == 1) -++ { -++ i2s_codec_write(0x16, 0x0059); -++ i2s_codec_write(0x17, 0x000d); -++ i2s_codec_write(0x18, 0x00cb); -++ i2s_codec_write(0x19, 0x0037); -++ i2s_codec_write(0x1A, 0x0059); -++ i2s_codec_write(0x1B, 0x000d); -++ i2s_codec_write(0x1C, 0x0046); -++ i2s_codec_write(0x1D, 0x001e); -++ i2s_codec_write(0x1E, 0x0074); -++ i2s_codec_write(0x1F, 0x0023); -++ i2s_codec_write(0x11, 0x0018); //eq on -++ } -++ break; -++ default: -++ break; -++ } -++ val = speed & 0x08; -++ val = val << 2; -++ speed = speed & 0x07; -++ val = val | speed; -++ i2s_codec_write(0x05, val); -++} -++ -++void ak4642en_mixer_old_info_id_name(void) -++{ -++ strncpy(info.id, "AK4642EN", sizeof(info.id)); -++ strncpy(info.name,"AKM AK4642en codec", sizeof(info.name)); -++} -++ -++void ak4642en_mixer_info_id_name(void) -++{ -++ strncpy(old_info.id, "AK4642EN", sizeof(old_info.id)); -++ strncpy(old_info.name,"AKM AK4642en codec", sizeof(old_info.name)); -++} -++ -++void set_ak4642en_volume(int val) -++{ -++ if ( val == 0 ) -++ codec_volume = 255; -++ else if ( val > 1 && val <= 10) -++ codec_volume = 92; -++ else if ( val > 10 && val <= 20 ) -++ codec_volume = 67; -++ else if ( val > 20 && val <= 30 ) -++ codec_volume = 50; -++ else if ( val > 30 && val <= 40 ) -++ codec_volume = 40; -++ else if ( val > 40 && val <= 50 ) -++ codec_volume = 30; -++ else if ( val > 50 && val <= 60 ) -++ codec_volume = 22; -++ else if ( val > 60&& val <= 70 ) -++ codec_volume = 15; -++ else if ( val > 70 && val <= 80 ) -++ codec_volume = 8; -++ else if ( val > 80 && val <= 90 ) -++ codec_volume = 4; -++ else if ( val > 90 && val <= 100 ) -++ codec_volume = 2; -++ -++ i2s_codec_write(0x0a, codec_volume); -++ i2s_codec_write(0x0d, codec_volume); -++} -++ -++void set_ak4642en_mic(int val) -++{ -++ int mic_gain; -++ mic_gain = 241 * val /100; -++ i2s_codec_write(0x09, mic_gain); -++ i2s_codec_write(0x0c, mic_gain); -++} -++ -++void resume_ak4642en(void) -++{ -++ __gpio_as_output(17); -++ __gpio_set_pin(17); //enable ak4642 -++ __gpio_as_output(68); -++ __gpio_clear_pin(68); -++ __gpio_as_output(69); -++ __gpio_clear_pin(69); -++ __gpio_as_output(70); -++ __gpio_clear_pin(70); -++ __gpio_as_input(71); -++ __gpio_clear_pin(71); -++ __gpio_as_input(77); -++ __gpio_clear_pin(77); -++ __gpio_as_input(78); -++ __gpio_clear_pin(78); -++ REG_GPIO_GPALR(2) &= 0xC3FF0CFF; -++ REG_GPIO_GPALR(2) |= 0x14005000; -++ //set SCC clock initialization -++ REG_SCC1_CR(SCC1_BASE) = 0x00000000; -++ udelay(2); -++ REG_SCC1_CR(SCC1_BASE) |= 1 << 31; -++ udelay(2); -++ __gpio_as_output(I2S_PDN); -++ __gpio_set_pin(I2S_PDN); -++ udelay(5); -++ __gpio_clear_pin(I2S_PDN); -++ ndelay(300);//>150ns -++ __gpio_set_pin(I2S_PDN); -++ mdelay(1); -++ //set PLL Master mode -++ i2s_codec_write(0x01, 0x0008);//master -++ i2s_codec_write(0x04, 0x006b);//ref:12MHz;BITCLK:64fs;I2S compli -++ i2s_codec_write(0x05, 0x000b);//sync:48KHz; -++ i2s_codec_write(0x00, 0x0040);//PMVCM -++ i2s_codec_write(0x01, 0x0009);//master,PLL enable -++ jack_plug_level = 10; -++ old_level = 100; -++ spk_hp = 0; -++ __gpio_as_input(JACK_PLUG_PIN); -++ jack_plug_level = __gpio_get_pin(JACK_PLUG_PIN); -++ //i suppose jack_plug_lvel is 1 indicate with HPO -++ if(jack_plug_level > 1 || jack_plug_level <0) -++ printk("Audio ak4642en codec Jack plug level is wrong!\n"); -++ if(jack_plug_level) -++ __gpio_as_irq_fall_edge(JACK_PLUG_PIN); -++ else -++ __gpio_as_irq_rise_edge(JACK_PLUG_PIN); -++ -++ i2s_codec_write(0x00, 0x0065); //for resume power -++ i2s_codec_write(0x01, 0x0039); //for open pop noise -++ i2s_codec_write(0x01, 0x0079); -++ i2s_codec_write(0x0a, codec_volume); -++ i2s_codec_write(0x0d, codec_volume); -++} -++ -++void suspend_ak4642en(int wr,int rd) -++{ -++ if(wr) //playing -++ { -++ if(jack_plug_level == 0) -++ { -++ i2s_codec_write(0x01, 0x0039); // for close pop noise -++ mdelay(500); -++ i2s_codec_write(0x01, 0x0009); //PLL on I2S -++ i2s_codec_write(0x07, 0x0001); -++ i2s_codec_write(0x11, 0x0000); -++ i2s_codec_write(0x00, 0x0040); -++ i2s_codec_write(0x0f, 0x0008); // for open pop noise -++ -++ } -++ else -++ { -++ //for Speaker output -++ i2s_codec_write(0x02, 0x0020); -++ i2s_codec_write(0x07, 0x0001); -++ i2s_codec_write(0x11, 0x0000); -++ i2s_codec_write(0x02, 0x0000); -++ i2s_codec_write(0x00, 0x0040); // for close pop noise -++ } -++ } -++ -++ if(rd) // recording -++ { -++ i2s_codec_write(0x02, 0x0001); // 5-11 a1 -++ i2s_codec_write(0x07, 0x0001); -++ i2s_codec_write(0x11, 0x0000); -++ mdelay(300); -++ } -++ __gpio_as_output(17); -++ __gpio_clear_pin(17);//disable ak4642 -++ __i2s_disable(); -++} -++ -++static int __init init_ak4642en(void) -++{ -++ set_codec_gpio_pin = set_ak4642en_gpio_pin; -++ each_time_init_codec = each_time_init_ak4642en; -++ clear_codec_mode = clear_ak4642en_mode; -++ -++ set_codec_record = set_ak4642en_record; -++ set_codec_replay = set_ak4642en_replay; -++ set_replay_hp_or_speaker = set_ak4642en_replay; -++ -++ set_codec_speed = set_ak4642en_speed; -++ clear_codec_record = clear_ak4642en_record; -++ clear_codec_replay = clear_ak4642en_replay; -++ -++ codec_mixer_old_info_id_name = ak4642en_mixer_old_info_id_name; -++ codec_mixer_info_id_name = ak4642en_mixer_info_id_name; -++ -++ set_codec_volume = set_ak4642en_volume; -++ -++ set_codec_mic = set_ak4642en_mic; -++ -++ i2s_resume_codec = resume_ak4642en; -++ i2s_suspend_codec = suspend_ak4642en; -++ printk("---> ak4642en initialization!\n"); -++ return 0; -++} -++ -++static void __exit cleanup_ak4642en(void) -++{ -++ spk_hp = 0; -++ i2s_codec_write(0x01, 0x0008);//master,PLL disable -++ //free_irq(JACK_PLUG_IRQ, i2s_controller); -++ __gpio_clear_pin(I2S_PDN); -++ udelay(2); -++ REG_SCC1_CR(SCC1_BASE) &= 0 << 31; -++ udelay(2); -++} -++ -++module_init(init_ak4642en); -++module_exit(cleanup_ak4642en); -+diff -urN linux-2.6.24.7.old/sound/oss/jz_ac97.c linux-2.6.24.7/sound/oss/jz_ac97.c -+--- linux-2.6.24.7.old/sound/oss/jz_ac97.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/oss/jz_ac97.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,2252 @@ -++/* -++ * linux/drivers/sound/jz_ac97.c -++ * -++ * Jz On-Chip AC97 audio driver. -++ * -++ * Copyright (C) 2005 - 2007, Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ * Because the normal application of AUDIO devices are focused on Little_endian, -++ * then we only perform the little endian data format in driver. -++ * -++ */ -++ -++#define __NO_VERSION__ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++//#include -++#include "sound_config.h" -++ -++#define DMA_ID_AC97_TX DMA_ID_AIC_TX -++#define DMA_ID_AC97_RX DMA_ID_AIC_RX -++ -++/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */ -++#define NR_AC97 2 -++ -++#define STANDARD_SPEED 48000 -++#define MAX_RETRY 100 -++ -++static unsigned int k_8000[] = { -++ 0, 42, 85, 128, 170, 213, -++}; -++ -++static unsigned int reload_8000[] = { -++ 1, 0, 0, 0, 0, 0, -++}; -++ -++static unsigned int k_11025[] = { -++ 0, 58, 117, 176, 234, 37, 96, 154, -++ 213, 16, 74, 133, 192, 250, 53, 112, -++ 170, 229, 32, 90, 149, 208, 10, 69, -++ 128, 186, 245, 48, 106, 165, 224, 26, -++ 85, 144, 202, 5, 64, 122, 181, 240, -++ 42, 101, 160, 218, 21, 80, 138, 197, -++}; -++ -++static unsigned int reload_11025[] = { -++ 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -++ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, -++ 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, -++}; -++ -++static unsigned int k_16000[] = { -++ 0, 85, 170, -++}; -++ -++static unsigned int reload_16000[] = { -++ 1, 0, 0, -++}; -++ -++static unsigned int k_22050[] = { -++ 0, 117, 234, 96, 213, 74, 192, 53, -++ 170, 32, 149, 10, 128, 245, 106, 224, -++ 85, 202, 64, 181, 42, 160, 21, 138, -++}; -++ -++static unsigned int reload_22050[] = { -++ 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, -++ 1, 0, 1, 0, 1, 0, 1, 0, -++}; -++ -++static unsigned int k_24000[] = { -++ 0, 128, -++}; -++ -++static unsigned int reload_24000[] = { -++ 1, 0, -++}; -++ -++static unsigned int k_32000[] = { -++ 0, 170, 85, -++}; -++ -++static unsigned int reload_32000[] = { -++ 1, 0, 1, -++}; -++ -++static unsigned int k_44100[] = { -++ 0, 234, 213, 192, 170, 149, 128, 106, -++ 85, 64, 42, 21, -++}; -++ -++static unsigned int reload_44100[] = { -++ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -++}; -++ -++static unsigned int k_48000[] = { -++ 0, -++}; -++ -++static unsigned int reload_48000[] = { -++ 1, -++}; -++ -++ -++static unsigned int f_scale_counts[8] = { -++ 6, 48, 3, 24, 2, 3, 12, 1, -++}; -++ -++static int jz_audio_rate; -++static char jz_audio_format; -++static char jz_audio_channels; -++static int jz_audio_k; /* rate expand multiple */ -++static int jz_audio_q; /* rate expand compensate */ -++static int jz_audio_count; /* total count of voice data */ -++static int last_jz_audio_count; -++ -++static int jz_audio_fragments;//unused fragment amount -++static int jz_audio_fragstotal; -++static int jz_audio_fragsize; -++static int jz_audio_dma_tran_count;//bytes count of one DMA transfer -++ -++static unsigned int f_scale_count; -++static unsigned int *f_scale_array; -++static unsigned int *f_scale_reload; -++static unsigned int f_scale_idx; -++ -++static void (*old_mksound)(unsigned int hz, unsigned int ticks); -++extern void (*kd_mksound)(unsigned int hz, unsigned int ticks); -++extern void jz_set_dma_block_size(int dmanr, int nbyte); -++extern void jz_set_dma_dest_width(int dmanr, int nbit); -++extern void jz_set_dma_src_width(int dmanr, int nbit); -++ -++static void jz_update_filler(int bits, int channels); -++ -++static void Init_In_Out_queue(int fragstotal,int fragsize); -++static void Free_In_Out_queue(int fragstotal,int fragsize); -++ -++static irqreturn_t -++jz_ac97_replay_dma_irq(int irqnr, void *dev_id); -++static irqreturn_t -++jz_ac97_record_dma_irq(int irqnr, void *dev_id); -++ -++static void -++(*replay_filler)(unsigned long src_start, int count, int id); -++static int -++(*record_filler)(unsigned long dst_start, int count, int id); -++ -++static struct file_operations jz_ac97_audio_fops; -++ -++DECLARE_WAIT_QUEUE_HEAD (rx_wait_queue); -++DECLARE_WAIT_QUEUE_HEAD (tx_wait_queue); -++ -++struct jz_ac97_controller_info -++{ -++ int io_base; -++ int dma1; /* play */ -++ int dma2; /* record */ -++ -++ char *name; -++ -++ int dev_audio; -++ struct ac97_codec *ac97_codec[NR_AC97]; -++ -++ unsigned short ac97_features; -++ -++ int opened1; -++ int opened2; -++ -++ unsigned char *tmp1; /* tmp buffer for sample conversions */ -++ unsigned char *tmp2; -++ -++ spinlock_t lock; -++ spinlock_t ioctllock; -++ wait_queue_head_t dac_wait; -++ wait_queue_head_t adc_wait; -++ -++ int nextIn; // byte index to next-in to DMA buffer -++ int nextOut; // byte index to next-out from DMA buffer -++ int count; // current byte count in DMA buffer -++ int finish; // current transfered byte count in DMA buffer -++ unsigned total_bytes; // total bytes written or read -++ unsigned blocks; -++ unsigned error; // over/underrun -++ -++ /* We use two devices, because we can do simultaneous play and record. -++ This keeps track of which device is being used for what purpose; -++ these are the actual device numbers. */ -++ int dev_for_play; -++ int dev_for_record; -++ -++ int playing; -++ int recording; -++ int patched; -++ unsigned long rec_buf_size; -++ unsigned long playback_buf_size; -++ -++#ifdef CONFIG_PM -++ struct pm_dev *pm; -++#endif -++}; -++ -++static struct jz_ac97_controller_info *ac97_controller = NULL; -++ -++static int jz_readAC97Reg(struct ac97_codec *dev, u8 reg); -++static int jz_writeAC97Reg(struct ac97_codec *dev, u8 reg, u16 data); -++static u16 ac97_codec_read(struct ac97_codec *codec, u8 reg); -++static void ac97_codec_write(struct ac97_codec *codec, u8 reg, u16 data); -++ -++#define QUEUE_MAX 2 -++ -++typedef struct buffer_queue_s { -++ int count; -++ int *id; -++ spinlock_t lock; -++} buffer_queue_t; -++ -++static unsigned long *out_dma_buf = NULL; -++static unsigned long *out_dma_pbuf = NULL; -++static unsigned long *out_dma_buf_data_count = NULL; -++static unsigned long *in_dma_buf = NULL; -++static unsigned long *in_dma_pbuf = NULL; -++static unsigned long *in_dma_buf_data_count = NULL; -++ -++static buffer_queue_t out_empty_queue; -++static buffer_queue_t out_full_queue; -++static buffer_queue_t out_busy_queue; -++ -++static buffer_queue_t in_empty_queue; -++static buffer_queue_t in_full_queue; -++static buffer_queue_t in_busy_queue; -++ -++static int first_record_call = 0; -++ -++static inline int get_buffer_id(struct buffer_queue_s *q) -++{ -++ int r, i; -++ unsigned long flags; -++ spin_lock_irqsave(&q->lock, flags); -++ if (q->count == 0) { -++ spin_unlock_irqrestore(&q->lock, flags); -++ return -1; -++ } -++ r = *(q->id + 0); -++ for (i=0;i < q->count-1;i++) -++ *(q->id + i) = *(q->id + (i+1)); -++ q->count --; -++ spin_unlock_irqrestore(&q->lock, flags); -++ return r; -++} -++ -++static inline void put_buffer_id(struct buffer_queue_s *q, int id) -++{ -++ unsigned long flags; -++ spin_lock_irqsave(&q->lock, flags); -++ *(q->id + q->count) = id; -++ q->count ++; -++ spin_unlock_irqrestore(&q->lock, flags); -++} -++ -++static inline int elements_in_queue(struct buffer_queue_s *q) -++{ -++ int r; -++ unsigned long flags; -++ spin_lock_irqsave(&q->lock, flags); -++ r = q->count; -++ spin_unlock_irqrestore(&q->lock, flags); -++ return r; -++} -++ -++/**************************************************************************** -++ * Architecture related routines -++ ****************************************************************************/ -++static inline -++void audio_start_dma(int chan, void *dev_id, unsigned long phyaddr,int count, int mode) -++{ -++ unsigned long flags; -++ struct jz_ac97_controller_info * controller = -++ (struct jz_ac97_controller_info *) dev_id; -++ //for DSP_GETOPTR -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ jz_audio_dma_tran_count = count; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ flags = claim_dma_lock(); -++ disable_dma(chan); -++ clear_dma_ff(chan); -++ set_dma_mode(chan, mode); -++ set_dma_addr(chan, phyaddr); -++ if (count == 0) { -++ count++; -++ printk(KERN_DEBUG "%s: JzSOC DMA controller can't set dma count zero!\n", -++ __FUNCTION__); -++ } -++ set_dma_count(chan, count); -++ enable_dma(chan); -++ release_dma_lock(flags); -++} -++ -++static irqreturn_t -++jz_ac97_record_dma_irq (int irq, void *dev_id) -++{ -++ struct jz_ac97_controller_info * controller = -++ (struct jz_ac97_controller_info *) dev_id; -++ int dma = controller->dma2; -++ int id1, id2; -++ unsigned long flags; -++ -++ disable_dma(dma); -++ if (__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if (__dmac_channel_transmit_end_detected(dma)) { -++ __dmac_channel_clear_transmit_end(dma); -++ -++ //for DSP_GETIPTR -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ id1 = get_buffer_id(&in_busy_queue); -++ put_buffer_id(&in_full_queue, id1); -++ wake_up(&rx_wait_queue); -++ wake_up(&controller->adc_wait); -++ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id2); -++ -++ *(in_dma_buf_data_count + id2) = *(in_dma_buf_data_count + id1); -++ audio_start_dma(dma,dev_id, -++ *(in_dma_pbuf + id2), -++ *(in_dma_buf_data_count + id2), -++ DMA_MODE_READ); -++ } else { -++ in_busy_queue.count = 0; -++ } -++ } -++ return IRQ_HANDLED; -++} -++ -++static irqreturn_t -++jz_ac97_replay_dma_irq (int irq, void *dev_id) -++{ -++ struct jz_ac97_controller_info * controller = -++ (struct jz_ac97_controller_info *) dev_id; -++ int dma = controller->dma1, id; -++ unsigned long flags; -++ -++ disable_dma(dma); -++ if (__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if (__dmac_channel_transmit_end_detected(dma)) { -++ __dmac_channel_clear_transmit_end(dma); -++ //for DSP_GETOPTR -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ if ((id = get_buffer_id(&out_busy_queue)) < 0) { -++ printk(KERN_DEBUG "Strange DMA finish interrupt for AC97 module\n"); -++ } -++ -++ put_buffer_id(&out_empty_queue, id); -++ if ((id = get_buffer_id(&out_full_queue)) >= 0) { -++ put_buffer_id(&out_busy_queue, id); -++ if(*(out_dma_buf_data_count + id) > 0) { -++ audio_start_dma(dma, dev_id, *(out_dma_pbuf + id), -++ *(out_dma_buf_data_count + id), -++ DMA_MODE_WRITE); -++ } -++ } else { -++ out_busy_queue.count = 0; -++ } -++ if (elements_in_queue(&out_empty_queue) > 0) { -++ wake_up(&tx_wait_queue); -++ wake_up(&controller->dac_wait); -++ } -++ } -++ return IRQ_HANDLED; -++} -++ -++/* -++ * Initialize the onchip AC97 controller -++ */ -++static void jz_ac97_initHw(struct jz_ac97_controller_info *controller) -++{ -++ __ac97_disable(); -++ __ac97_reset(); -++ __ac97_enable(); -++ -++ __ac97_cold_reset_codec(); -++ /* wait for a long time to let ac97 controller reset completely, -++ * otherwise, registers except ACFR will be clear by reset, can't be -++ * set correctly. -++ */ -++ udelay(160); -++ -++ __ac97_disable_record(); -++ __ac97_disable_replay(); -++ __ac97_disable_loopback(); -++ -++ /* Check the trigger threshold reset value to detect version */ -++ if (((REG_AIC_FR & AIC_FR_TFTH_MASK) >> AIC_FR_TFTH_BIT) == 8) { -++ printk("JzAC97: patched controller detected.\n"); -++ controller->patched = 1; -++ } else { -++ printk("JzAC97: standard controller detected.\n"); -++ controller->patched = 0; -++ } -++ -++ /* Set FIFO data size. Which shows valid data bits. -++ * -++ */ -++ __ac97_set_oass(8); -++ __ac97_set_iass(8); -++ -++ __ac97_set_xs_stereo(); -++ __ac97_set_rs_stereo(); -++} -++ -++/* -++ * Initialize all of in(out)_empty_queue value -++ */ -++static void Init_In_Out_queue(int fragstotal,int fragsize) -++{ -++ int i; -++ if(out_dma_buf || in_dma_buf) -++ return; -++ in_empty_queue.count = fragstotal; -++ out_empty_queue.count = fragstotal; -++ -++ out_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!out_dma_buf) -++ goto all_mem_err; -++ out_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!out_dma_pbuf) -++ goto all_mem_err; -++ out_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!out_dma_buf_data_count) -++ goto all_mem_err; -++ in_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_buf) -++ goto all_mem_err; -++ in_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_pbuf) -++ goto all_mem_err; -++ in_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_buf_data_count) -++ goto all_mem_err; -++ in_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_empty_queue.id) -++ goto all_mem_err; -++ in_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_full_queue.id) -++ goto all_mem_err; -++ in_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_busy_queue.id) -++ goto all_mem_err; -++ out_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_empty_queue.id) -++ goto all_mem_err; -++ out_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_full_queue.id) -++ goto all_mem_err; -++ out_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_busy_queue.id) -++ goto all_mem_err; -++ -++ for (i=0;i < fragstotal;i++) { -++ *(in_empty_queue.id + i) = i; -++ *(out_empty_queue.id + i) = i; -++ } -++ -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ /*alloc DMA buffer*/ -++ for (i = 0; i < jz_audio_fragstotal; i++) { -++ *(out_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -++ if (*(out_dma_buf + i) == 0) { -++ printk(" can't allocate required DMA(OUT) buffers.\n"); -++ goto mem_failed_out; -++ } -++ *(out_dma_pbuf + i) = virt_to_phys((void *)(*(out_dma_buf + i))); -++ } -++ -++ for (i = 0; i < jz_audio_fragstotal; i++) { -++ *(in_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -++ if (*(in_dma_buf + i) == 0) { -++ printk(" can't allocate required DMA(IN) buffers.\n"); -++ goto mem_failed_in; -++ } -++ *(in_dma_pbuf + i) = virt_to_phys((void *)(*(in_dma_buf + i))); -++ dma_cache_wback_inv(*(in_dma_buf + i), 4096*8);//fragsize -++ *(in_dma_buf + i) = KSEG1ADDR(*(in_dma_buf + i)); -++ } -++ return ; -++ -++ all_mem_err: -++ printk("error:allocate memory occur error!\n"); -++ return ; -++ -++mem_failed_out: -++ -++ for (i = 0; i < jz_audio_fragstotal; i++) { -++ if(*(out_dma_buf + i)) -++ free_pages(*(out_dma_buf + i), get_order(fragsize)); -++ } -++ return ; -++ -++mem_failed_in: -++ -++ for (i = 0; i < jz_audio_fragstotal; i++) { -++ if(*(in_dma_buf + i)) -++ free_pages(*(in_dma_buf + i), get_order(fragsize)); -++ } -++ return ; -++ -++} -++static void Free_In_Out_queue(int fragstotal,int fragsize) -++{ -++ int i; -++ if(out_dma_buf != NULL) -++ { -++ for (i = 0; i < jz_audio_fragstotal; i++) -++ { -++ if(*(out_dma_buf + i)) -++ free_pages(*(out_dma_buf + i), get_order(fragsize)); -++ *(out_dma_buf + i) = 0; -++ } -++ kfree(out_dma_buf); -++ out_dma_buf = NULL; -++ } -++ if(out_dma_pbuf) -++ { -++ kfree(out_dma_pbuf); -++ out_dma_pbuf = NULL; -++ } -++ if(out_dma_buf_data_count) -++ { -++ kfree(out_dma_buf_data_count); -++ out_dma_buf_data_count = NULL; -++ } -++ if(in_dma_buf) -++ { -++ for (i = 0; i < jz_audio_fragstotal; i++) -++ { -++ if(*(in_dma_buf + i)) -++ free_pages(*(in_dma_buf + i), get_order(fragsize)); -++ *(in_dma_buf + i) = 0; -++ } -++ kfree(in_dma_buf); -++ in_dma_buf = NULL; -++ } -++ if(in_dma_pbuf) -++ { -++ kfree(in_dma_pbuf); -++ in_dma_pbuf = NULL; -++ } -++ if(in_dma_buf_data_count) -++ { -++ kfree(in_dma_buf_data_count); -++ in_dma_buf_data_count = NULL; -++ } -++ if(in_empty_queue.id) -++ { -++ kfree(in_empty_queue.id); -++ in_empty_queue.id = NULL; -++ } -++ if(in_full_queue.id) -++ { -++ kfree(in_full_queue.id); -++ in_full_queue.id = NULL; -++ } -++ if(in_busy_queue.id) -++ { -++ kfree(in_busy_queue.id); -++ in_busy_queue.id = NULL; -++ } -++ if(out_empty_queue.id) -++ { -++ kfree(out_empty_queue.id); -++ out_empty_queue.id = NULL; -++ } -++ if(out_full_queue.id) -++ { -++ kfree(out_full_queue.id); -++ out_full_queue.id = NULL; -++ } -++ if(out_busy_queue.id) -++ { -++ kfree(out_busy_queue.id); -++ out_busy_queue.id = NULL; -++ } -++ -++ in_empty_queue.count = fragstotal; -++ out_empty_queue.count = fragstotal; -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ return ; -++} -++ -++/* -++ * Reset everything -++ */ -++static void -++jz_ac97_full_reset(struct jz_ac97_controller_info *controller) -++{ -++ jz_ac97_initHw(controller); -++} -++ -++ -++static void -++jz_ac97_mksound(unsigned int hz, unsigned int ticks) -++{ -++// printk("BEEP - %d %d!\n", hz, ticks); -++} -++ -++static int jz_audio_set_speed(int dev, int rate) -++{ -++ /* 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999 ? */ -++ u32 dacp; -++ struct ac97_codec *codec=ac97_controller->ac97_codec[0]; -++ -++ if (rate > 48000) -++ rate = 48000; -++ if (rate < 8000) -++ rate = 8000; -++ -++ -++ /* Power down the DAC */ -++ dacp=ac97_codec_read(codec, AC97_POWER_CONTROL); -++ ac97_codec_write(codec, AC97_POWER_CONTROL, dacp|0x0200); -++ /* Load the rate; only 48Khz playback available, read always zero */ -++ if ((ac97_controller->patched) && (ac97_controller->ac97_features & 1)) -++ ac97_codec_write(codec, AC97_PCM_FRONT_DAC_RATE, rate); -++ else -++ ac97_codec_write(codec, AC97_PCM_FRONT_DAC_RATE, 48000); -++ -++ /* Power it back up */ -++ ac97_codec_write(codec, AC97_POWER_CONTROL, dacp); -++ -++ jz_audio_rate = rate; -++ jz_audio_k = STANDARD_SPEED / rate; -++ if (rate * jz_audio_k != STANDARD_SPEED) -++ jz_audio_q = rate / ((STANDARD_SPEED / jz_audio_k) - rate ); -++ else -++ jz_audio_q = 0x1fffffff; /* a very big value, don't compensate */ -++ -++ switch (rate) { -++ case 8000: -++ f_scale_count = f_scale_counts[0]; -++ f_scale_array = k_8000; -++ f_scale_reload = reload_8000; -++ break; -++ case 11025: -++ f_scale_count = f_scale_counts[1]; -++ f_scale_array = k_11025; -++ f_scale_reload = reload_11025; -++ break; -++ case 16000: -++ f_scale_count = f_scale_counts[2]; -++ f_scale_array = k_16000; -++ f_scale_reload = reload_16000; -++ break; -++ case 22050: -++ f_scale_count = f_scale_counts[3]; -++ f_scale_array = k_22050; -++ f_scale_reload = reload_22050; -++ break; -++ case 24000: -++ f_scale_count = f_scale_counts[4]; -++ f_scale_array = k_24000; -++ f_scale_reload = reload_24000; -++ break; -++ case 32000: -++ f_scale_count = f_scale_counts[5]; -++ f_scale_array = k_32000; -++ f_scale_reload = reload_32000; -++ break; -++ case 44100: -++ f_scale_count = f_scale_counts[6]; -++ f_scale_array = k_44100; -++ f_scale_reload = reload_44100; -++ break; -++ case 48000: -++ f_scale_count = f_scale_counts[7]; -++ f_scale_array = k_48000; -++ f_scale_reload = reload_48000; -++ break; -++ } -++ f_scale_idx = 0; -++ -++ return jz_audio_rate; -++} -++ -++static int record_fill_1x8_u(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned char data; -++ volatile unsigned char *s = (unsigned char *)(*(in_dma_buf + id)); -++ volatile unsigned char *dp = (unsigned char *)dst_start; -++ -++ while (count > 0) { -++ count -= 2; /* count in dword */ -++ if ((jz_audio_count++ % jz_audio_k) == 0) { -++ cnt++; -++ data = *(s++); -++ *(dp ++) = data + 0x80; -++ s++; /* skip the other channel */ -++ } else { -++ s += 2; /* skip the redundancy */ -++ } -++ if (jz_audio_count - last_jz_audio_count >= jz_audio_q) { -++ jz_audio_count++; -++ last_jz_audio_count = jz_audio_count; -++ count -= 2; -++ s += 2; -++ } -++ } -++ return cnt; -++} -++ -++static int record_fill_2x8_u(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned char d1, d2; -++ volatile unsigned char *s = (unsigned char *)(*(in_dma_buf + id)); -++ volatile unsigned char *dp = (unsigned char *)dst_start; -++ -++ while (count > 0) { -++ count -= 2; -++ if ((jz_audio_count++ % jz_audio_k) == 0) { -++ cnt += 2; -++ d1 = *(s++); -++ *(dp ++) = d1 + 0x80; -++ d2 = *(s++); -++ *(dp ++) = d2 + 0x80; -++ } else { -++ s += 2; /* skip the redundancy */ -++ } -++ if (jz_audio_count - last_jz_audio_count >= jz_audio_q * 2) { -++ jz_audio_count += 2; -++ last_jz_audio_count = jz_audio_count; -++ count -= 2; -++ s += 2; -++ } -++ } -++ return cnt; -++} -++ -++static int record_fill_1x16_s(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned short d1; -++ unsigned short *s = (unsigned short *)(*(in_dma_buf + id)); -++ unsigned short *dp = (unsigned short *)dst_start; -++ -++ while (count > 0) { -++ count -= 2; /* count in dword */ -++ if ((jz_audio_count++ % jz_audio_k) == 0) { -++ cnt += 2; /* count in byte */ -++ d1 = *(s++); -++ *(dp ++) = d1; -++ s++; /* skip the other channel */ -++ } else { -++ s += 2; /* skip the redundancy */ -++ } -++ if (jz_audio_count - last_jz_audio_count >= jz_audio_q * 2) { -++ jz_audio_count += 2; -++ last_jz_audio_count = jz_audio_count; -++ count -= 2; -++ s += 2; -++ } -++ } -++ return cnt; -++} -++ -++static int record_fill_2x16_s(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned short d1, d2; -++ unsigned short *s = (unsigned short *)(*(in_dma_buf + id)); -++ unsigned short *dp = (unsigned short *)dst_start; -++ -++ while (count > 0) { -++ count -= 2; /* count in dword */ -++ if ((jz_audio_count++ % jz_audio_k) == 0) { -++ cnt += 4; /* count in byte */ -++ d1 = *(s++); -++ *(dp ++) = d1; -++ d2 = *(s++); -++ *(dp ++) = d2; -++ } else -++ s += 2; /* skip the redundancy */ -++ -++ if (jz_audio_count - last_jz_audio_count >= jz_audio_q * 4) { -++ jz_audio_count += 4; -++ last_jz_audio_count = jz_audio_count; -++ count -= 2; -++ s += 2; -++ } -++ } -++ return cnt; -++} -++ -++ -++static void replay_fill_1x8_u(unsigned long src_start, int count, int id) -++{ -++ int i, cnt = 0; -++ unsigned char data; -++ unsigned char *s = (unsigned char *)src_start; -++ unsigned char *dp = (unsigned char *)(*(out_dma_buf + id)); -++ -++ while (count > 0) { -++ count--; -++ jz_audio_count++; -++ cnt += jz_audio_k; -++ data = *(s++) - 0x80; -++ for (i=0;i 0) { -++ count -= 2; -++ jz_audio_count += 2; -++ cnt += 2 * jz_audio_k; -++ d1 = *(s++) - 0x80; -++ d2 = *(s++) - 0x80; -++ for (i=0;i= jz_audio_q * 2) { -++ cnt += 2 * jz_audio_k; -++ last_jz_audio_count = jz_audio_count; -++ for (i=0;i= 0) { -++ if (f_scale_reload[f_scale_idx]) { -++ d1 = d2; -++ d2 = *s++; -++ if (!count) -++ break; -++ count -= 2; -++ } -++ d = d1 + (((d2 - d1) * f_scale_array[f_scale_idx]) >> 8); -++ *dp++ = d; -++ *dp++ = d; -++ cnt += 4; -++ f_scale_idx ++; -++ if (f_scale_idx >= f_scale_count) -++ f_scale_idx = 0; -++ } -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++static void replay_fill_2x16_s(unsigned long src_start, int count, int id) -++{ -++ int cnt = 0; -++ static short d11, d12, d21, d22, d1, d2; -++ short *s = (short *)src_start; -++ short *dp = (short *)(*(out_dma_buf + id)); -++ -++ d12 = *s++; -++ d22 = *s++; -++ count -= 4; -++ while (count >= 0) { -++ register unsigned int kvalue; -++ kvalue = f_scale_array[f_scale_idx]; -++ if (f_scale_reload[f_scale_idx]) { -++ d11 = d12; -++ d12 = *s++; -++ d21 = d22; -++ d22 = *s++; -++ if (!count) -++ break; -++ count -= 4; -++ } -++ d1 = d11 + (((d12 - d11)*kvalue) >> 8); -++ d2 = d21 + (((d22 - d21)*kvalue) >> 8); -++ *dp++ = d1; -++ *dp++ = d2; -++ cnt += 4; -++ f_scale_idx ++; -++ if (f_scale_idx >= f_scale_count) -++ f_scale_idx = 0; -++ } -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++static unsigned int jz_audio_set_format(int dev, unsigned int fmt) -++{ -++ switch (fmt) { -++ case AFMT_U8: -++ case AFMT_S16_LE: -++ jz_audio_format = fmt; -++ jz_update_filler(fmt, jz_audio_channels); -++ case AFMT_QUERY: -++ break; -++ } -++ return jz_audio_format; -++} -++ -++static short jz_audio_set_channels(int dev, short channels) -++{ -++ switch (channels) { -++ case 1: -++ __ac97_set_xs_stereo(); // always stereo when recording -++ __ac97_set_rs_stereo(); // always stereo when recording -++ jz_audio_channels = channels; -++ jz_update_filler(jz_audio_format, jz_audio_channels); -++ break; -++ case 2: -++ __ac97_set_xs_stereo(); -++ __ac97_set_rs_stereo(); -++ jz_audio_channels = channels; -++ jz_update_filler(jz_audio_format, jz_audio_channels); -++ break; -++ case 0: -++ break; -++ } -++ return jz_audio_channels; -++} -++ -++ -++static void jz_audio_reset(void) -++{ -++ __ac97_disable_replay(); -++ __ac97_disable_receive_dma(); -++ __ac97_disable_record(); -++ __ac97_disable_transmit_dma(); -++} -++ -++static int jz_audio_release(struct inode *inode, struct file *file); -++static int jz_audio_open(struct inode *inode, struct file *file); -++static int jz_audio_ioctl(struct inode *inode, struct file *file, -++ unsigned int cmd, unsigned long arg); -++static unsigned int jz_audio_poll(struct file *file, -++ struct poll_table_struct *wait); -++static ssize_t jz_audio_write(struct file *file, const char *buffer, -++ size_t count, loff_t *ppos); -++static ssize_t jz_audio_read(struct file *file, char *buffer, -++ size_t count, loff_t *ppos); -++ -++/* static struct file_operations jz_ac97_audio_fops */ -++static struct file_operations jz_ac97_audio_fops = -++{ -++ owner: THIS_MODULE, -++ open: jz_audio_open, -++ release: jz_audio_release, -++ write: jz_audio_write, -++ read: jz_audio_read, -++ poll: jz_audio_poll, -++ ioctl: jz_audio_ioctl -++}; -++ -++/* Read / Write AC97 codec registers */ -++static inline int jz_out_command_ready(void) -++{ -++ int t2 = 1000; -++ int done = 0; -++ -++ while (! done && t2-- > 0) { -++ if (REG32(AC97_ACSR) & AIC_ACSR_CADT) { -++ REG32(AC97_ACSR) &= ~AIC_ACSR_CADT; -++ done = 1; -++ } -++ else -++ udelay (1); -++ } -++ return done; -++} -++ -++static inline int jz_in_status_ready(void) -++{ -++ int t2 = 1000; -++ int done = 0; -++ -++ while (! done && t2-- > 0) { -++ if (REG32(AC97_ACSR) & AIC_ACSR_SADR) { -++ REG32(AC97_ACSR) &= ~AIC_ACSR_SADR; -++ done = 1; -++ } -++ else { -++ if (REG32(AC97_ACSR) & AIC_ACSR_RSTO) { -++ REG32(AC97_ACSR) &= ~AIC_ACSR_RSTO; -++ printk(KERN_DEBUG "%s: RSTO receive status timeout.\n", -++ __FUNCTION__); -++ done = 0; -++ break; -++ } -++ udelay (1); -++ } -++ } -++ return done; -++} -++ -++static int jz_readAC97Reg (struct ac97_codec *dev, u8 reg) -++{ -++ u16 value; -++ -++ if (reg < 128) { -++ u8 ret_reg; -++ __ac97_out_rcmd_addr(reg);//output read addr -++ if (jz_out_command_ready())//judge if send completely? -++ while (jz_in_status_ready()) {//judge if receive completely? -++ ret_reg = __ac97_in_status_addr();//slot1:send addr -++ value = __ac97_in_data(); -++ if (ret_reg == reg) -++ return value; -++ else { -++// printk(KERN_DEBUG "%s: index (0x%02x)->(0x%02x) 0x%x\n", __FUNCTION__, reg, ret_reg, value); -++ return -EINVAL; -++ } -++ } -++ } -++ value = __ac97_in_data(); -++ printk (KERN_DEBUG "timeout while reading AC97 codec (0x%x)\n", reg); -++ return -EINVAL; -++} -++ -++static u16 ac97_codec_read(struct ac97_codec *codec, u8 reg) -++{ -++ int res = jz_readAC97Reg(codec, reg); -++ int count = 0; -++ while (res == -EINVAL) { -++ udelay(1000); -++ __ac97_warm_reset_codec(); -++ udelay(1000); -++ res = jz_readAC97Reg(codec, reg); -++ count ++; -++ if (count > MAX_RETRY){ -++ printk(KERN_WARNING"After try %d when read AC97 codec 0x%x, can't success, give up operate!!\n", -++ MAX_RETRY, reg); -++ break; -++ } -++ } -++ return (u16)res; -++} -++ -++static int jz_writeAC97Reg (struct ac97_codec *dev, u8 reg, u16 value) -++{ -++ //unsigned long flags; -++ int done = 0; -++ -++ //save_and_cli(flags); -++ -++ __ac97_out_wcmd_addr(reg); -++ __ac97_out_data(value); -++ if (jz_out_command_ready()) -++ done = 1; -++ else -++ printk (KERN_DEBUG "Tiemout AC97 codec write (0x%X<==0x%X)\n", reg, value); -++ //restore_flags(flags); -++ return done; -++} -++static void ac97_codec_write(struct ac97_codec *codec, u8 reg, u16 data) -++{ -++ int done = jz_writeAC97Reg(codec, reg, data); -++ int count = 0; -++ while (done == 0) { -++ count ++; -++ udelay (2000); -++ __ac97_warm_reset_codec(); -++ udelay(2000); -++ done = jz_writeAC97Reg(codec, reg, data); -++ if ( count > MAX_RETRY ){ -++ printk (KERN_DEBUG " After try %d when write AC97 codec (0x%x), can't sucess, give up!! \n", -++ MAX_RETRY, reg); -++ break; -++ } -++ } -++} -++ -++/* OSS /dev/mixer file operation methods */ -++ -++static int jz_ac97_open_mixdev(struct inode *inode, struct file *file) -++{ -++ int i; -++ int minor = MINOR(inode->i_rdev); -++ struct jz_ac97_controller_info *controller = ac97_controller; -++ -++ for (i = 0; i < NR_AC97; i++) -++ if (controller->ac97_codec[i] != NULL && -++ controller->ac97_codec[i]->dev_mixer == minor) -++ goto match; -++ -++ if (!controller) -++ return -ENODEV; -++ -++ match: -++ file->private_data = controller->ac97_codec[i]; -++ -++ return 0; -++} -++ -++static int jz_ac97_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, -++ unsigned long arg) -++{ -++ struct ac97_codec *codec = (struct ac97_codec *)file->private_data; -++ -++ return codec->mixer_ioctl(codec, cmd, arg); -++} -++ -++static loff_t jz_ac97_llseek(struct file *file, loff_t offset, int origin) -++{ -++ return -ESPIPE; -++} -++ -++static /*const*/ struct file_operations jz_ac97_mixer_fops = { -++ owner: THIS_MODULE, -++ llseek: jz_ac97_llseek, -++ ioctl: jz_ac97_ioctl_mixdev, -++ open: jz_ac97_open_mixdev, -++}; -++ -++/* AC97 codec initialisation. */ -++static int __init jz_ac97_codec_init(struct jz_ac97_controller_info *controller) -++{ -++ int num_ac97 = 0; -++ int ready_2nd = 0; -++ struct ac97_codec *codec; -++ unsigned short eid; -++ int i = 0; -++ -++ if (__ac97_codec_is_low_power_mode()) { -++ printk(KERN_DEBUG "AC97 codec is low power mode, warm reset ...\n"); -++ __ac97_warm_reset_codec(); -++ udelay(10); -++ } -++ i = 0; -++ while (!__ac97_codec_is_ready()) { -++ i++; -++ if ( i > 100 ) { -++ printk(KERN_WARNING "AC97 codec not ready, failed init ..\n"); -++ return -ENODEV; -++ } -++ udelay(10); -++ } -++ i = 0; -++ -++ /* Reset the mixer. */ -++ for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { -++ if ((codec = kmalloc(sizeof(struct ac97_codec), -++ GFP_KERNEL)) == NULL) -++ return -ENOMEM; -++ memset(codec, 0, sizeof(struct ac97_codec)); -++ -++ /* initialize some basic codec information, -++ other fields will be filled -++ in ac97_probe_codec */ -++ codec->private_data = controller; -++ codec->id = num_ac97; -++ -++ codec->codec_read = ac97_codec_read; -++ codec->codec_write = ac97_codec_write; -++ -++ if (ac97_probe_codec(codec) == 0) -++ break; -++ -++ eid = ac97_codec_read(codec, AC97_EXTENDED_ID); -++ if (eid == 0xFFFF) { -++ printk(KERN_WARNING "Jz AC97: no codec attached?\n"); -++ kfree(codec); -++ break; -++ } -++ -++ controller->ac97_features = eid; -++ -++ if (!(eid & 0x0001)) -++ printk(KERN_WARNING "AC97 codec: only 48Khz playback available.\n"); -++ else { -++ printk(KERN_WARNING "AC97 codec: supports variable sample rate.\n"); -++ /* Enable HPEN: UCB1400 only */ -++ ac97_codec_write(codec, 0x6a, -++ ac97_codec_read(codec, 0x6a) | 0x40); -++ -++ /* Enable variable rate mode */ -++ ac97_codec_write(codec, AC97_EXTENDED_STATUS, 9); -++ ac97_codec_write(codec, -++ AC97_EXTENDED_STATUS, -++ ac97_codec_read(codec, AC97_EXTENDED_STATUS) | 0xE800); -++ /* power up everything, modify this -++ when implementing power saving */ -++ ac97_codec_write(codec, -++ AC97_POWER_CONTROL, -++ ac97_codec_read(codec, AC97_POWER_CONTROL) & ~0x7f00); -++ /* wait for analog ready */ -++ for (i=10; i && ((ac97_codec_read(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--) { -++// current->state = TASK_UNINTERRUPTIBLE; -++// schedule_timeout(HZ/20); -++ } -++ -++ if (!(ac97_codec_read(codec, AC97_EXTENDED_STATUS) & 1)) { -++ printk(KERN_WARNING "Jz AC97: Codec refused to allow VRA, using 48Khz only.\n"); -++ controller->ac97_features &= ~1; -++ } -++ } -++ -++ if ((codec->dev_mixer = -++ register_sound_mixer(&jz_ac97_mixer_fops, -1)) < 0) { -++ printk(KERN_ERR "Jz AC97: couldn't register mixer!\n"); -++ kfree(codec); -++ break; -++ } -++ -++ controller->ac97_codec[num_ac97] = codec; -++ -++ /* if there is no secondary codec at all, don't probe any more */ -++ if (!ready_2nd) -++ return num_ac97+1; -++ } -++ return num_ac97; -++} -++ -++static void jz_update_filler(int format, int channels) -++{ -++#define TYPE(fmt,ch) (((fmt)<<3) | ((ch)&7)) /* up to 8 chans supported. */ -++ -++ -++ switch (TYPE(format, channels)) { -++ default: -++ -++ case TYPE(AFMT_U8, 1): -++ if ((ac97_controller->patched) && -++ (ac97_controller->ac97_features & 1)) { -++ __aic_enable_mono2stereo(); -++ __aic_enable_unsignadj(); -++ jz_set_dma_block_size(ac97_controller->dma1, 16); -++ jz_set_dma_block_size(ac97_controller->dma2, 16); -++ } else { -++ __aic_disable_mono2stereo(); -++ __aic_disable_unsignadj(); -++ jz_set_dma_block_size(ac97_controller->dma1, 4); -++ jz_set_dma_block_size(ac97_controller->dma2, 4); -++ } -++ replay_filler = replay_fill_1x8_u; -++ record_filler = record_fill_1x8_u; -++ __ac97_set_oass(8); -++ __ac97_set_iass(8); -++ jz_set_dma_dest_width(ac97_controller->dma1, 8); -++ jz_set_dma_src_width(ac97_controller->dma2, 8); -++ break; -++ case TYPE(AFMT_U8, 2): -++ if ((ac97_controller->patched) && -++ (ac97_controller->ac97_features & 1)) { -++ __aic_enable_mono2stereo(); -++ __aic_enable_unsignadj(); -++ jz_set_dma_block_size(ac97_controller->dma1, 16); -++ jz_set_dma_block_size(ac97_controller->dma2, 16); -++ } else { -++ __aic_disable_mono2stereo(); -++ __aic_disable_unsignadj(); -++ jz_set_dma_block_size(ac97_controller->dma1, 4); -++ jz_set_dma_block_size(ac97_controller->dma2, 4); -++ } -++ replay_filler = replay_fill_2x8_u; -++ record_filler = record_fill_2x8_u; -++ __ac97_set_oass(8); -++ __ac97_set_iass(8); -++ jz_set_dma_dest_width(ac97_controller->dma1, 8); -++ jz_set_dma_src_width(ac97_controller->dma2, 8); -++ break; -++ case TYPE(AFMT_S16_LE, 1): -++ if ((ac97_controller->patched) && -++ (ac97_controller->ac97_features & 1)) { -++ __aic_enable_mono2stereo(); -++ jz_set_dma_block_size(ac97_controller->dma1, 16); -++ jz_set_dma_block_size(ac97_controller->dma2, 16); -++ } else { -++ __aic_disable_mono2stereo(); -++ jz_set_dma_block_size(ac97_controller->dma1, 4); -++ jz_set_dma_block_size(ac97_controller->dma2, 4); -++ } -++ __aic_disable_unsignadj(); -++ replay_filler = replay_fill_1x16_s; -++ record_filler = record_fill_1x16_s; -++ __ac97_set_oass(16); -++ __ac97_set_iass(16); -++ -++ jz_set_dma_dest_width(ac97_controller->dma1, 16); -++ jz_set_dma_src_width(ac97_controller->dma2, 16); -++ -++ break; -++ -++ case TYPE(AFMT_S16_LE, 2): -++ if ((ac97_controller->patched) && -++ (ac97_controller->ac97_features & 1)) { -++ jz_set_dma_block_size(ac97_controller->dma1, 16); -++ jz_set_dma_block_size(ac97_controller->dma2, 16); -++ } else { -++ jz_set_dma_block_size(ac97_controller->dma1, 4); -++ jz_set_dma_block_size(ac97_controller->dma2, 4); -++ } -++ __aic_disable_mono2stereo(); -++ __aic_disable_unsignadj(); -++ replay_filler = replay_fill_2x16_s; -++ record_filler = record_fill_2x16_s; -++ __ac97_set_oass(16); -++ __ac97_set_iass(16); -++ jz_set_dma_dest_width(ac97_controller->dma1, 16); -++ jz_set_dma_src_width(ac97_controller->dma2, 16); -++ break; -++ } -++} -++ -++#ifdef CONFIG_PROC_FS -++ -++extern struct proc_dir_entry *proc_jz_root; -++ -++static int jz_ac97_init_proc(struct jz_ac97_controller_info *controller) -++{ -++ if (!create_proc_read_entry ("ac97", 0, proc_jz_root, -++ ac97_read_proc, controller->ac97_codec[0])) -++ return -EIO; -++ -++ return 0; -++} -++ -++static void jz_ac97_cleanup_proc(struct jz_ac97_controller_info *controller) -++{ -++} -++ -++#endif -++ -++static void __init attach_jz_ac97(struct jz_ac97_controller_info *controller) -++{ -++ char *name; -++ int adev; -++ -++ name = controller->name; -++ jz_ac97_initHw(controller); -++ -++ /* register /dev/audio ? */ -++ adev = register_sound_dsp(&jz_ac97_audio_fops, -1); -++ if (adev < 0) -++ goto audio_failed; -++ -++ /* initialize AC97 codec and register /dev/mixer */ -++ if (jz_ac97_codec_init(controller) <= 0) -++ goto mixer_failed; -++ -++#ifdef CONFIG_PROC_FS -++ if (jz_ac97_init_proc(controller) < 0) { -++ printk(KERN_ERR "%s: can't create AC97 proc filesystem.\n", name); -++ goto proc_failed; -++ } -++#endif -++ -++ controller->tmp1 = (void *)__get_free_pages(GFP_KERNEL, 8);//4 -++ if (!controller->tmp1) { -++ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -++ goto tmp1_failed; -++ } -++ -++ controller->tmp2 = (void *)__get_free_pages(GFP_KERNEL, 8);//4 -++ if (!controller->tmp2) { -++ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -++ goto tmp2_failed; -++ } -++ -++ if ((controller->dma1 = jz_request_dma(DMA_ID_AC97_TX, "audio dac", -++ jz_ac97_replay_dma_irq, -++ IRQF_DISABLED, controller)) < 0) { -++ printk(KERN_ERR "%s: can't reqeust DMA DAC channel.\n", name); -++ goto dma1_failed; -++ } -++ if ((controller->dma2 = jz_request_dma(DMA_ID_AC97_RX, "audio adc", -++ jz_ac97_record_dma_irq, -++ IRQF_DISABLED, controller)) < 0) { -++ printk(KERN_ERR "%s: can't reqeust DMA ADC channel.\n", name); -++ goto dma2_failed; -++ } -++ -++ printk("Jz On-Chip AC97 controller registered (DAC: DMA%d/IRQ%d, ADC: DMA%d/IRQ%d)\n", -++ controller->dma1, get_dma_done_irq(controller->dma1), -++ controller->dma2, get_dma_done_irq(controller->dma2)); -++ -++ old_mksound = kd_mksound; /* see vt.c */ -++ kd_mksound = jz_ac97_mksound; -++ controller->dev_audio = adev; -++ return; -++ -++ dma2_failed: -++ jz_free_dma(controller->dma1); -++ dma1_failed: -++ free_pages((unsigned long)controller->tmp2, 8);//4 -++ tmp2_failed: -++ free_pages((unsigned long)controller->tmp1, 8);//4 -++ tmp1_failed: -++#ifdef CONFIG_PROC_FS -++ jz_ac97_cleanup_proc(controller); -++#endif -++ proc_failed: -++ /* unregister mixer dev */ -++ mixer_failed: -++ unregister_sound_dsp(adev); -++ audio_failed: -++ return; -++} -++ -++static int __init probe_jz_ac97(struct jz_ac97_controller_info **controller) -++{ -++ if ((*controller = kmalloc(sizeof(struct jz_ac97_controller_info), -++ GFP_KERNEL)) == NULL) { -++ printk(KERN_ERR "Jz AC97 Controller: out of memory.\n"); -++ return -ENOMEM; -++ } -++ memset( *controller, 0, sizeof(struct jz_ac97_controller_info) ); -++ (*controller)->name = "Jz AC97 controller"; -++ (*controller)->opened1 = 0; -++ (*controller)->opened2 = 0; -++ -++ init_waitqueue_head(&(*controller)->adc_wait); -++ init_waitqueue_head(&(*controller)->dac_wait); -++ spin_lock_init(&(*controller)->lock); -++ init_waitqueue_head(&rx_wait_queue); -++ init_waitqueue_head(&tx_wait_queue); -++ -++ return 0; -++} -++ -++static void __exit unload_jz_ac97(struct jz_ac97_controller_info *controller) -++{ -++ int adev = controller->dev_audio; -++ -++ jz_ac97_full_reset (controller); -++ -++ controller->dev_audio = -1; -++ -++ if (old_mksound) -++ kd_mksound = old_mksound; /* Our driver support bell for kb, see vt.c */ -++ -++#ifdef CONFIG_PROC_FS -++ jz_ac97_cleanup_proc(controller); -++#endif -++ -++ jz_free_dma(controller->dma1); -++ jz_free_dma(controller->dma2); -++ -++ free_pages((unsigned long)controller->tmp1, 8);//4 -++ free_pages((unsigned long)controller->tmp2, 8);//4 -++ -++ if (adev >= 0) { -++ //unregister_sound_mixer(audio_devs[adev]->mixer_dev); -++ unregister_sound_dsp(controller->dev_audio); -++ } -++} -++ -++#ifdef CONFIG_PM -++ -++static int reserve_mastervol, reserve_micvol; -++static int reserve_power1, reserve_power2; -++static int reserve_power3, reserve_power4; -++static int reserve_power5, reserve_power6; -++ -++static int jz_ac97_suspend(struct jz_ac97_controller_info *controller, int state) -++{ -++ struct ac97_codec *codec = controller->ac97_codec[0]; -++ -++ /* save codec states */ -++ reserve_mastervol = ac97_codec_read(codec, 0x0002); -++ reserve_micvol = ac97_codec_read(codec, 0x000e); -++ -++ reserve_power1 = ac97_codec_read(codec, 0x0026); -++ reserve_power2 = ac97_codec_read(codec, 0x006c); -++ reserve_power3 = ac97_codec_read(codec, 0x005c); -++ reserve_power4 = ac97_codec_read(codec, 0x0064); -++ reserve_power5 = ac97_codec_read(codec, 0x0066); -++ reserve_power6 = ac97_codec_read(codec, 0x006a); -++ -++ /* put codec into power-saving mode */ -++ ac97_codec_write(codec, 0x5c, 0xffff); -++ ac97_codec_write(codec, 0x64, 0x0000); -++ ac97_codec_write(codec, 0x66, 0x0000); -++ ac97_codec_write(codec, 0x6a, 0x0000); -++ -++ ac97_codec_write(codec, 0x6c, 0x0030); -++ ac97_codec_write(codec, 0x26, 0x3b00); -++ -++ ac97_save_state(codec); -++ __ac97_disable(); -++ -++ return 0; -++} -++ -++static int jz_ac97_resume(struct jz_ac97_controller_info *controller) -++{ -++ struct ac97_codec *codec = controller->ac97_codec[0]; -++ -++ jz_ac97_full_reset(controller); -++ ac97_probe_codec(codec); -++ ac97_restore_state(codec); -++ -++ ac97_codec_write(codec, 0x0026, reserve_power1); -++ ac97_codec_write(codec, 0x006c, reserve_power2); -++ ac97_codec_write(codec, 0x005c, reserve_power3); -++ ac97_codec_write(codec, 0x0064, reserve_power4); -++ ac97_codec_write(codec, 0x0066, reserve_power5); -++ ac97_codec_write(codec, 0x006a, reserve_power6); -++ -++ ac97_codec_write(codec, 0x0002, reserve_mastervol); -++ ac97_codec_write(codec, 0x000e, reserve_micvol); -++ -++ /* Enable variable rate mode */ -++ ac97_codec_write(codec, AC97_EXTENDED_STATUS, 9); -++ ac97_codec_write(codec, -++ AC97_EXTENDED_STATUS, -++ ac97_codec_read(codec, AC97_EXTENDED_STATUS) | 0xE800); -++ -++ return 0; -++} -++ -++static int jz_ac97_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -++{ -++ int ret; -++ struct jz_ac97_controller_info *controller = pm_dev->data; -++ -++ if (!controller) return -EINVAL; -++ -++ switch (req) { -++ case PM_SUSPEND: -++ ret = jz_ac97_suspend(controller, (int)data); -++ break; -++ -++ case PM_RESUME: -++ ret = jz_ac97_resume(controller); -++ break; -++ default: -++ ret = -EINVAL; -++ break; -++ } -++ return ret; -++} -++#endif /* CONFIG_PM */ -++ -++static int __init init_jz_ac97(void) -++{ -++ int errno; -++ -++ if ((errno = probe_jz_ac97(&ac97_controller)) < 0) -++ return errno; -++ attach_jz_ac97(ac97_controller); -++ -++ out_empty_queue.id = NULL; -++ out_full_queue.id = NULL; -++ out_busy_queue.id = NULL; -++ -++ in_empty_queue.id = NULL; -++ in_full_queue.id = NULL; -++ in_busy_queue.id = NULL; -++ -++#ifdef CONFIG_PM -++ ac97_controller->pm = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, -++ jz_ac97_pm_callback); -++ if (ac97_controller->pm) -++ ac97_controller->pm->data = ac97_controller; -++#endif -++ -++ return 0; -++} -++ -++static void __exit cleanup_jz_ac97(void) -++{ -++ unload_jz_ac97(ac97_controller); -++} -++ -++module_init(init_jz_ac97); -++module_exit(cleanup_jz_ac97); -++ -++ -++static int drain_adc(struct jz_ac97_controller_info *ctrl, int nonblock) -++{ -++ DECLARE_WAITQUEUE(wait, current); -++ unsigned long flags; -++ int count; -++ unsigned tmo; -++ -++ add_wait_queue(&ctrl->adc_wait, &wait); -++ for (;;) { -++ set_current_state(TASK_INTERRUPTIBLE); -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma2); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if (count <= 0) -++ break; -++ -++ if (signal_pending(current)) -++ break; -++ if (nonblock) { -++ remove_wait_queue(&ctrl->adc_wait, &wait); -++ current->state = TASK_RUNNING; -++ return -EBUSY; -++ } -++ tmo = (PAGE_SIZE * HZ) / STANDARD_SPEED; -++ tmo *= jz_audio_k * (jz_audio_format == AFMT_S16_LE) ? 2 : 4; -++ tmo /= jz_audio_channels; -++ } -++ remove_wait_queue(&ctrl->adc_wait, &wait); -++ current->state = TASK_RUNNING; -++ if (signal_pending(current)) -++ return -ERESTARTSYS; -++ return 0; -++} -++ -++static int drain_dac(struct jz_ac97_controller_info *ctrl, int nonblock) -++{ -++ DECLARE_WAITQUEUE(wait, current); -++ unsigned long flags; -++ int count; -++ unsigned tmo; -++ -++ add_wait_queue(&(ctrl->dac_wait), &wait); -++ for (;;) { -++ set_current_state(TASK_INTERRUPTIBLE); -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if (count <= 0 && elements_in_queue(&out_full_queue) <= 0) -++ break; -++ if (signal_pending(current)) -++ break; -++ if (nonblock) { -++ remove_wait_queue(&ctrl->dac_wait, &wait); -++ current->state = TASK_RUNNING; -++ return -EBUSY; -++ } -++ tmo = (PAGE_SIZE * HZ) / STANDARD_SPEED; -++ tmo *= jz_audio_k * (jz_audio_format == AFMT_S16_LE) ? 2 : 4; -++ tmo /= jz_audio_channels; -++ } -++ remove_wait_queue(&ctrl->dac_wait, &wait); -++ current->state = TASK_RUNNING; -++ if (signal_pending(current)) -++ return -ERESTARTSYS; -++ return 0; -++} -++ -++/* -++ * Audio operation routines implementation -++ */ -++static int jz_audio_release(struct inode *inode, struct file *file) -++{ -++ struct jz_ac97_controller_info *controller = -++ (struct jz_ac97_controller_info *) file->private_data; -++ unsigned long flags; -++ -++ if (file->f_mode & FMODE_WRITE) { -++ controller->opened1 = 0; -++ drain_dac(controller, file->f_flags & O_NONBLOCK); -++ disable_dma(controller->dma1); -++ set_dma_count(controller->dma1, 0); -++ __ac97_disable_transmit_dma(); -++ __ac97_disable_replay(); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->blocks = 0; -++ controller->nextOut = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ } -++ if (file->f_mode & FMODE_READ) { -++ controller->opened2 = 0; -++ first_record_call = 1; -++ drain_adc(controller, file->f_flags & O_NONBLOCK); -++ disable_dma(controller->dma2); -++ set_dma_count(controller->dma2, 0); -++ __ac97_disable_receive_dma(); -++ __ac97_disable_record(); -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextIn = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ } -++ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ return 0; -++} -++ -++static int jz_audio_open(struct inode *inode, struct file *file) -++{ -++ struct jz_ac97_controller_info *controller= ac97_controller; -++ -++ if (controller == NULL) -++ return -ENODEV; -++ -++ if (file->f_mode & FMODE_WRITE) { -++ if (controller->opened1 == 1) -++ return -EBUSY; -++ controller->opened1 = 1; -++ //for ioctl -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextOut = 0; -++ jz_audio_set_channels(controller->dev_audio, 1); -++ jz_audio_set_format(controller->dev_audio, AFMT_U8); -++ jz_audio_set_speed(controller->dev_audio, 8000); -++ } -++ -++ if (file->f_mode & FMODE_READ) { -++ if (controller->opened2 == 1) -++ return -EBUSY; -++ controller->opened2 = 1; -++ first_record_call = 1; -++ printk(KERN_DEBUG "You'd better apply 48000Hz 16-bit Stereo for record.\n"); -++ //for ioctl -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextIn = 0; -++ jz_audio_set_channels(controller->dev_audio, 2); -++ jz_audio_set_format(controller->dev_audio, AFMT_S16_LE); -++ jz_audio_set_speed(controller->dev_audio, 48000); -++ } -++ -++ last_jz_audio_count = jz_audio_count = 0; -++ file->private_data = controller; -++ -++ jz_audio_fragsize = 8 * PAGE_SIZE; -++ jz_audio_fragstotal = 4; -++ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ return 0; -++} -++ -++static int jz_audio_ioctl(struct inode *inode, struct file *file, -++ unsigned int cmd, unsigned long arg) -++{ -++ struct jz_ac97_controller_info *controller = -++ (struct jz_ac97_controller_info *) file->private_data; -++ int val=0,fullc,busyc,unfinish; -++ unsigned int flags; -++ count_info cinfo; -++ -++ switch (cmd) -++ { -++ case OSS_GETVERSION: -++ return put_user(SOUND_VERSION, (int *)arg); -++ -++ case SNDCTL_DSP_RESET: -++ jz_audio_reset(); -++ return 0; -++ -++ case SNDCTL_DSP_SYNC: -++ if (file->f_mode & FMODE_WRITE) -++ return drain_dac(controller, file->f_flags & O_NONBLOCK); -++ return 0; -++ -++ case SNDCTL_DSP_SPEED: /* set smaple rate */ -++ { -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ if (val >= 0) -++ jz_audio_set_speed(controller->dev_audio, val); -++ return put_user(val, (int *)arg); -++ } -++ -++ case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ jz_audio_set_channels(controller->dev_audio, val ? 2 : 1); -++ return 0; -++ -++ case SNDCTL_DSP_GETBLKSIZE: -++ //return put_user(4*PAGE_SIZE, (int *)arg); -++ return put_user(jz_audio_fragsize , (int *)arg); -++ -++ case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/ -++ return put_user(AFMT_U8 | AFMT_S16_LE, (int *)arg); -++ -++ case SNDCTL_DSP_SETFMT: /* Select sample format */ -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ -++ if (val != AFMT_QUERY) { -++ jz_audio_set_format(controller->dev_audio,val); -++ } else { -++ if (file->f_mode & FMODE_READ) -++ val = (jz_audio_format == 16) ? -++ AFMT_S16_LE : AFMT_U8; -++ else -++ val = (jz_audio_format == 16) ? -++ AFMT_S16_LE : AFMT_U8; -++ } -++ return put_user(val, (int *)arg); -++ -++ case SNDCTL_DSP_CHANNELS: -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ jz_audio_set_channels(controller->dev_audio, val); -++ return put_user(val, (int *)arg); -++ -++ case SNDCTL_DSP_POST: -++ /* FIXME: the same as RESET ?? */ -++ return 0; -++ -++ case SNDCTL_DSP_SUBDIVIDE: -++ return 0; -++ -++ case SNDCTL_DSP_SETFRAGMENT: -++ if(out_dma_buf || in_dma_buf) -++ return -EBUSY; -++ get_user(val, (long *) arg); -++ jz_audio_fragsize = 1 << (val & 0xFFFF);//16 least bits -++ -++ if (jz_audio_fragsize < 4 * PAGE_SIZE) -++ jz_audio_fragsize = 4 * PAGE_SIZE; -++ if (jz_audio_fragsize > (16 * PAGE_SIZE)) //16 PAGE_SIZE -++ jz_audio_fragsize = 16 * PAGE_SIZE; -++ jz_audio_fragstotal = (val >> 16) & 0x7FFF; -++ if (jz_audio_fragstotal < 2) -++ jz_audio_fragstotal = 2; -++ if (jz_audio_fragstotal > 32) -++ jz_audio_fragstotal = 32; -++ -++ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ return 0; -++ -++ case SNDCTL_DSP_GETCAPS: -++ return put_user(DSP_CAP_REALTIME|DSP_CAP_BATCH, (int *)arg); -++ -++ case SNDCTL_DSP_NONBLOCK: -++ file->f_flags |= O_NONBLOCK; -++ return 0; -++ -++ case SNDCTL_DSP_SETDUPLEX: -++ return -EINVAL; -++ -++ case SNDCTL_DSP_GETOSPACE: -++ { -++ audio_buf_info abinfo; -++ int i, bytes = 0; -++ -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ //unused fragment amount -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ jz_audio_fragments = elements_in_queue(&out_empty_queue); -++ for (i = 0; i < jz_audio_fragments; i++) -++ bytes += jz_audio_fragsize; -++ bytes /= jz_audio_k; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ //bytes /= jz_audio_b; -++ abinfo.fragments = jz_audio_fragments; -++ abinfo.fragstotal = jz_audio_fragstotal; -++ abinfo.fragsize = jz_audio_fragsize; -++ abinfo.bytes = bytes; -++ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; -++ } -++ -++ case SNDCTL_DSP_GETISPACE: -++ { -++ audio_buf_info abinfo; -++ int i, bytes = 0; -++ -++ if (!(file->f_mode & FMODE_READ)) -++ return -EINVAL; -++ //unused fragment amount -++ jz_audio_fragments = elements_in_queue(&in_empty_queue); -++ for (i = 0; i < jz_audio_fragments; i++) -++ bytes += jz_audio_fragsize; -++ -++ abinfo.fragments = jz_audio_fragments; -++ abinfo.fragstotal = jz_audio_fragstotal; -++ abinfo.fragsize = jz_audio_fragsize; -++ abinfo.bytes = bytes; -++ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; -++ } -++ case SNDCTL_DSP_GETTRIGGER: -++ val = 0; -++ if (file->f_mode & FMODE_READ && in_dma_buf) //record is at working -++ val |= PCM_ENABLE_INPUT; -++ if (file->f_mode & FMODE_WRITE && out_dma_buf) //playback is at working -++ val |= PCM_ENABLE_OUTPUT; -++ return put_user(val, (int *)arg); -++ -++ case SNDCTL_DSP_SETTRIGGER: -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ /*if (file->f_mode & FMODE_READ) { -++ if (val & PCM_ENABLE_INPUT) { -++ if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) -++ return ret; -++ start_adc(state); -++ } else -++ stop_adc(state); -++ } -++ if (file->f_mode & FMODE_WRITE) { -++ if (val & PCM_ENABLE_OUTPUT) { -++ if (!dmabuf->ready && (ret = prog_dmabuf(state, 0))) -++ return ret; -++ start_dac(state); -++ } else -++ stop_dac(state); -++ }*/ -++ return 0; -++ -++ case SNDCTL_DSP_GETIPTR: -++ if (!(file->f_mode & FMODE_READ)) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ //controller->total_bytes += get_dma_residue(controller->dma2); -++ cinfo.bytes = controller->total_bytes; -++ cinfo.blocks = controller->blocks; -++ cinfo.ptr = controller->nextIn; -++ controller->blocks = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); -++ -++ case SNDCTL_DSP_GETOPTR: -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ //controller->total_bytes += get_dma_residue(controller->dma1); -++ cinfo.bytes = controller->total_bytes; -++ cinfo.blocks = controller->blocks; -++ cinfo.ptr = controller->nextOut; -++ controller->blocks = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); -++ -++ case SNDCTL_DSP_GETODELAY: -++ { -++ int id, i; -++ -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ unfinish = 0; -++ fullc = elements_in_queue(&out_full_queue); -++ busyc = elements_in_queue(&out_busy_queue); -++ -++ for(i = 0;i < fullc ;i ++) -++ { -++ id = *(out_full_queue.id + i); -++ unfinish += *(out_dma_buf_data_count + id); -++ } -++ for(i = 0;i < busyc ;i ++) -++ { -++ id = *(out_busy_queue.id + i); -++ unfinish += get_dma_residue(controller->dma1); -++ } -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ unfinish /= jz_audio_k;//jz_audio_k is jz_audio_b -++ return put_user(val, (int *)arg); -++ } -++ case SOUND_PCM_READ_RATE: -++ return put_user(jz_audio_rate, (int *)arg); -++ case SOUND_PCM_READ_CHANNELS: -++ return put_user(jz_audio_channels, (int *)arg); -++ case SOUND_PCM_READ_BITS: -++ return put_user((jz_audio_format & (AFMT_S8 | AFMT_U8)) ? 8 : 16, (int *)arg); -++ case SNDCTL_DSP_MAPINBUF: -++ case SNDCTL_DSP_MAPOUTBUF: -++ case SNDCTL_DSP_SETSYNCRO: -++ case SOUND_PCM_WRITE_FILTER: -++ case SOUND_PCM_READ_FILTER: -++ return -EINVAL; -++ } -++ return -EINVAL; -++} -++ -++static unsigned int jz_audio_poll(struct file *file, -++ struct poll_table_struct *wait) -++{ -++ struct jz_ac97_controller_info *controller = -++ (struct jz_ac97_controller_info *) file->private_data; -++ unsigned long flags; -++ unsigned int mask = 0; -++ -++ if (file->f_mode & FMODE_WRITE) { -++ if (elements_in_queue(&out_empty_queue) > 0) -++ return POLLOUT | POLLWRNORM; -++ poll_wait(file, &controller->dac_wait, wait); -++ } -++ if (file->f_mode & FMODE_READ) { -++ if (elements_in_queue(&in_full_queue) > 0) -++ return POLLIN | POLLRDNORM; -++ poll_wait(file, &controller->adc_wait, wait); -++ } -++ spin_lock_irqsave(&controller->lock, flags); -++ if (file->f_mode & FMODE_WRITE) { -++ if (elements_in_queue(&out_empty_queue) > 0) -++ mask |= POLLOUT | POLLWRNORM; -++ } -++ else if (file->f_mode & FMODE_READ) { -++ if (elements_in_queue(&in_full_queue) > 0) -++ mask |= POLLIN | POLLRDNORM; -++ } -++ spin_unlock_irqrestore(&controller->lock, flags); -++ return mask; -++} -++ -++static ssize_t jz_audio_read(struct file *file, char *buffer, -++ size_t count, loff_t *ppos) -++{ -++ struct jz_ac97_controller_info *controller = -++ (struct jz_ac97_controller_info *) file->private_data; -++ int id, ret = 0, left_count, copy_count, cnt = 0; -++ unsigned long flags; -++ -++ if (count < 0) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextIn = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ -++ if (count < 2*PAGE_SIZE / jz_audio_k) { -++ copy_count = count * 16 / (jz_audio_channels * jz_audio_format); -++ } else -++ copy_count = ((2*PAGE_SIZE / jz_audio_k + 3) / 4) * 4; -++ left_count = count; -++ -++ if (first_record_call) { -++ first_record_call = 0; -++ if ((id = get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id); -++ *(in_dma_buf_data_count + id) = copy_count * (jz_audio_format/8); -++ __ac97_enable_receive_dma(); -++ __ac97_enable_record(); -++ audio_start_dma(controller->dma2,file->private_data, -++ *(in_dma_pbuf + id), -++ *(in_dma_buf_data_count + id), -++ DMA_MODE_READ); -++ interruptible_sleep_on(&rx_wait_queue); -++ } else -++ BUG(); -++ } -++ -++ while (left_count > 0) { -++ if (elements_in_queue(&in_full_queue) <= 0) { -++ if (file->f_flags & O_NONBLOCK) -++ return ret ? ret : -EAGAIN; -++ else -++ interruptible_sleep_on(&rx_wait_queue); -++ } -++ if (signal_pending(current)) -++ return ret ? ret: -ERESTARTSYS; -++ -++ if ((id = get_buffer_id(&in_full_queue)) >= 0) { -++ cnt = record_filler((unsigned long)controller->tmp2+ret, copy_count, id); -++ put_buffer_id(&in_empty_queue, id); -++ } else -++ BUG(); -++ -++ if (elements_in_queue(&in_busy_queue) == 0) { -++ if ((id=get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id); -++ *(in_dma_buf_data_count + id) = copy_count * (jz_audio_format/8); -++ __ac97_enable_receive_dma(); -++ __ac97_enable_record(); -++ audio_start_dma(controller->dma2,file->private_data, -++ *(in_dma_pbuf + id), -++ *(in_dma_buf_data_count + id), -++ DMA_MODE_READ); -++ } -++ } -++ -++ if (ret + cnt > count) -++ cnt = count - ret; -++ -++ if (copy_to_user(buffer+ret, controller->tmp2+ret, cnt)) -++ return ret ? ret : -EFAULT; -++ -++ ret += cnt; -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextIn += ret; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ left_count -= cnt; -++ } -++ if (ret != count) -++ printk(KERN_DEBUG "%s: count=%d ret=%d jz_audio_count=%d\n", -++ __FUNCTION__, count, ret, jz_audio_count); -++ return ret; -++} -++ -++static ssize_t jz_audio_write(struct file *file, const char *buffer, -++ size_t count, loff_t *ppos) -++{ -++ struct jz_ac97_controller_info *controller = -++ (struct jz_ac97_controller_info *) file->private_data; -++ int id, ret = 0, left_count, copy_count; -++ unsigned int flags; -++ -++ if (count <= 0) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextOut = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ -++ /* The data buffer size of the user space is always a PAGE_SIZE -++ * scale, so the process can be simplified. -++ */ -++ -++ if ((ac97_controller->patched) && (ac97_controller->ac97_features & 1)) -++ copy_count = count; -++ else { -++ if (count < 2*PAGE_SIZE / jz_audio_k) -++ copy_count = count; -++ else -++ copy_count = ((2*PAGE_SIZE / jz_audio_k + 3) / 4) * 4; -++ } -++ left_count = count; -++ -++ if (!(ac97_controller->patched) || !(ac97_controller->ac97_features & 1)) { -++ if (copy_from_user(controller->tmp1, buffer, count)) { -++ printk(KERN_DEBUG "%s: copy_from_user failed.\n", __FUNCTION__); -++ return ret ? ret : -EFAULT; -++ } -++ } -++ -++ while (left_count > 0) { -++ if (elements_in_queue(&out_empty_queue) == 0) { -++ if (file->f_flags & O_NONBLOCK) -++ return ret; -++ else -++ interruptible_sleep_on(&tx_wait_queue); -++ } -++ -++ if (signal_pending(current)) -++ return ret ? ret : -ERESTARTSYS; -++ -++ /* the end fragment size in this write */ -++ if (ret + copy_count > count) -++ copy_count = count - ret; -++ -++ if ((id = get_buffer_id(&out_empty_queue)) >= 0) { -++ if ((ac97_controller->patched) && -++ (ac97_controller->ac97_features & 1)) { -++ if (copy_from_user((char *)(*(out_dma_buf + id)), buffer+ret, copy_count)) { -++ printk(KERN_DEBUG "%s: copy_from_user failed.\n", __FUNCTION__); -++ return ret ? ret : -EFAULT; -++ } -++ *(out_dma_buf_data_count + id) = copy_count; -++ } else -++ replay_filler( -++ (unsigned long)controller->tmp1 + ret, -++ copy_count, id); -++ //when 0,kernel will panic -++ if(*(out_dma_buf_data_count + id) > 0) { -++ put_buffer_id(&out_full_queue, id); -++ dma_cache_wback_inv(*(out_dma_buf + id), *(out_dma_buf_data_count + id)); -++ } else {//when 0,i need refill in empty queue -++ put_buffer_id(&out_empty_queue, id); -++ } -++ } else -++ BUG(); -++ left_count = left_count - copy_count; -++ ret += copy_count; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextOut += ret; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ if (elements_in_queue(&out_busy_queue) == 0) { -++ if ((id=get_buffer_id(&out_full_queue)) >= 0) { -++ put_buffer_id(&out_busy_queue, id); -++ -++ __ac97_enable_transmit_dma(); -++ __ac97_enable_replay(); -++ if(*(out_dma_buf_data_count + id) > 0) { -++ audio_start_dma(controller->dma1,file->private_data, -++ *(out_dma_pbuf + id), -++ *(out_dma_buf_data_count + id), -++ DMA_MODE_WRITE); -++ } -++ } -++ } -++ } -++ -++ if (ret != count) -++ printk(KERN_DEBUG "%s: count=%d ret=%d jz_audio_count=%d\n", -++ __FUNCTION__, count, ret, jz_audio_count); -++ return ret; -++} -++ -++/* this function for the other codec function */ -++struct ac97_codec * find_ac97_codec(void) -++{ -++ if ( ac97_controller ) -++ return ac97_controller->ac97_codec[0]; -++ return 0; -++ -++} -++ -+diff -urN linux-2.6.24.7.old/sound/oss/jz_i2s.c linux-2.6.24.7/sound/oss/jz_i2s.c -+--- linux-2.6.24.7.old/sound/oss/jz_i2s.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/oss/jz_i2s.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,2894 @@ -++/* -++ * linux/drivers/sound/Jz_i2s.c -++ * -++ * JzSOC On-Chip I2S audio driver. -++ * -++ * Copyright (C) 2005 by Junzheng Corp. -++ * Modified by cjfeng on Aug 9,2007,and not any bug on Jz4730 using -++ * dma channel 4&3,noah is tested. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ * Because the normal application of AUDIO devices are focused on Little_endian, -++ * then we only perform the little endian data format in driver. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "sound_config.h" -++ -++#if defined(CONFIG_I2S_DLV) -++#include "jzdlv.h" -++#endif -++ -++#define DPRINTK(args...) printk(args) -++#define DMA_ID_I2S_TX DMA_ID_AIC_TX -++#define DMA_ID_I2S_RX DMA_ID_AIC_RX -++#define NR_I2S 2 -++#define JZCODEC_RW_BUFFER_SIZE 5 -++#define JZCODEC_RW_BUFFER_TOTAL 4 -++ -++#define USE_NONE 1 -++#define USE_MIC 2 -++#define USE_LINEIN 3 -++ -++typedef struct hpvol_shift_s -++{ -++ int hpvol; -++ int shift; -++} hpvol_shift_t; -++ -++mixer_info info; -++_old_mixer_info old_info; -++int codec_volue_shift; -++hpvol_shift_t hpvol_shift_table[72]; -++int abnormal_data_count; -++unsigned long i2s_clk; -++ -++void (*set_codec_mode)(void) = NULL; -++void (*clear_codec_mode)(void) = NULL; -++void (*set_codec_gpio_pin)(void) = NULL; -++void (*each_time_init_codec)(void) = NULL; -++int (*set_codec_startup_param)(void) = NULL; -++void (*set_codec_volume_table)(void) = NULL; -++void (*set_codec_record)(int mode) = NULL; -++void (*set_codec_replay)(void) = NULL; -++void (*set_codec_replay_record)(int mode) = NULL; -++void (*turn_on_codec)(void) = NULL; -++void (*turn_off_codec)(void) = NULL; -++void (*set_codec_speed)(int rate) = NULL; -++void (*reset_codec)(void) = NULL; -++void (*codec_mixer_old_info_id_name)(void) = NULL; -++void (*codec_mixer_info_id_name)(void) = NULL; -++void (*set_codec_bass)(int val) = NULL; -++void (*set_codec_volume)(int val) = NULL; -++void (*set_codec_mic)(int val) = NULL; -++void (*set_codec_line)(int val) = NULL; -++void (*i2s_resume_codec)(void) = NULL; -++void (*i2s_suspend_codec)(int wr,int rd) = NULL; -++void (*init_codec_pin)(void) = NULL; -++void (*set_codec_some_func)(void) = NULL; -++void (*clear_codec_record)(void) = NULL; -++void (*clear_codec_replay)(void) = NULL; -++void (*set_replay_hp_or_speaker)(void) = NULL; -++void (*set_codec_direct_mode)(void) = NULL; -++void (*clear_codec_direct_mode)(void) = NULL; -++void (*set_codec_linein2hp)(void) = NULL; -++void (*clear_codec_linein2hp)(void) = NULL; -++ -++static int jz_audio_rate; -++static int jz_audio_format; -++static int jz_audio_volume; -++static int jz_audio_channels; -++static int jz_audio_b; /* bits expand multiple */ -++static int jz_audio_fragments; /* unused fragment amount */ -++static int jz_audio_fragstotal; -++static int jz_audio_fragsize; -++static int jz_audio_speed; -++ -++static int codec_bass_gain; -++static int audio_mix_modcnt; -++static int jz_audio_dma_tran_count; /* bytes count of one DMA transfer */ -++#if defined(CONFIG_I2S_DLV) -++int jz_mic_only = 1; -++static int jz_codec_config = 0; -++static unsigned long ramp_up_start; -++static unsigned long ramp_up_end; -++static unsigned long gain_up_start; -++static unsigned long gain_up_end; -++static unsigned long ramp_down_start; -++static unsigned long ramp_down_end; -++static unsigned long gain_down_start; -++static unsigned long gain_down_end; -++#endif -++ -++static int codec_mic_gain; -++static int pop_dma_flag; -++static int last_dma_buffer_id; -++static int drain_flag; -++static int use_mic_line_flag; -++ -++static void (*old_mksound)(unsigned int hz, unsigned int ticks); -++extern void (*kd_mksound)(unsigned int hz, unsigned int ticks); -++static void jz_update_filler(int bits, int channels); -++ -++static int Init_In_Out_queue(int fragstotal,int fragsize); -++static int Free_In_Out_queue(int fragstotal,int fragsize); -++static irqreturn_t jz_i2s_replay_dma_irq(int irqnr, void *ref); -++static irqreturn_t jz_i2s_record_dma_irq(int irqnr, void *ref); -++static void (*replay_filler)(signed long src_start, int count, int id); -++static int (*record_filler)(unsigned long dst_start, int count, int id); -++#if defined(CONFIG_I2S_ICODEC) -++static void write_mute_to_dma_buffer(signed long l_sample, signed long r_sample); -++#endif -++static void jz_audio_reset(void); -++static struct file_operations jz_i2s_audio_fops; -++ -++static DECLARE_WAIT_QUEUE_HEAD (rx_wait_queue); -++static DECLARE_WAIT_QUEUE_HEAD (tx_wait_queue); -++static DECLARE_WAIT_QUEUE_HEAD (drain_wait_queue); -++static DECLARE_WAIT_QUEUE_HEAD (pop_wait_queue); -++ -++struct jz_i2s_controller_info -++{ -++ int io_base; -++ int dma1; /* for play */ -++ int dma2; /* for record */ -++ char *name; -++ int dev_audio; -++ struct i2s_codec *i2s_codec[NR_I2S]; -++ int opened1; -++ int opened2; -++ unsigned char *tmp1; /* tmp buffer for sample conversions */ -++ unsigned char *tmp2; -++ spinlock_t lock; -++ spinlock_t ioctllock; -++ -++ wait_queue_head_t dac_wait; -++ wait_queue_head_t adc_wait; -++ int nextIn; /* byte index to next-in to DMA buffer */ -++ int nextOut; /* byte index to next-out from DMA buffer */ -++ int count; /* current byte count in DMA buffer */ -++ int finish; /* current transfered byte count in DMA buffer */ -++ unsigned total_bytes; /* total bytes written or read */ -++ unsigned blocks; -++ unsigned error; /* over/underrun */ -++#ifdef CONFIG_PM -++ struct pm_dev *pm; -++#endif -++}; -++ -++ -++static struct jz_i2s_controller_info *i2s_controller = NULL; -++struct i2s_codec -++{ -++ /* I2S controller connected with */ -++ void *private_data; -++ char *name; -++ int id; -++ int dev_mixer; -++ /* controller specific lower leverl i2s accessing routines */ -++ u16 (*codec_read) (u8 reg); /* the function accessing Codec REGs */ -++ void (*codec_write) (u8 reg, u16 val); -++ /* Wait for codec-ready */ -++ void (*codec_wait) (struct i2s_codec *codec); -++ /* OSS mixer masks */ -++ int modcnt; -++ int supported_mixers; -++ int stereo_mixers; -++ int record_sources; -++ int bit_resolution; -++ /* OSS mixer interface */ -++ int (*read_mixer) (struct i2s_codec *codec, int oss_channel); -++ void (*write_mixer)(struct i2s_codec *codec, int oss_channel, -++ unsigned int left, unsigned int right); -++ int (*recmask_io) (struct i2s_codec *codec, int rw, int mask); -++ int (*mixer_ioctl)(struct i2s_codec *codec, unsigned int cmd, unsigned long arg); -++ /* saved OSS mixer states */ -++ unsigned int mixer_state[SOUND_MIXER_NRDEVICES]; -++}; -++ -++ -++typedef struct buffer_queue_s -++{ -++ int count; -++ int *id; -++ int lock; -++} buffer_queue_t; -++ -++typedef struct left_right_sample_s -++{ -++ signed long left; -++ signed long right; -++} left_right_sample_t; -++ -++static unsigned long pop_turn_onoff_buf; -++static unsigned long pop_turn_onoff_pbuf; -++ -++static unsigned long *out_dma_buf = NULL; -++static unsigned long *out_dma_pbuf = NULL; -++static unsigned long *out_dma_buf_data_count = NULL; -++static unsigned long *in_dma_buf = NULL; -++static unsigned long *in_dma_pbuf = NULL; -++static unsigned long *in_dma_buf_data_count = NULL; -++ -++static buffer_queue_t out_empty_queue; -++static buffer_queue_t out_full_queue; -++static buffer_queue_t out_busy_queue; -++static buffer_queue_t in_empty_queue; -++static buffer_queue_t in_full_queue; -++static buffer_queue_t in_busy_queue; -++static int first_record_call = 0; -++ -++static left_right_sample_t save_last_samples[64]; -++ -++static inline int get_buffer_id(struct buffer_queue_s *q) -++{ -++ int r; -++ unsigned long flags; -++ int i; -++ -++ spin_lock_irqsave(&q->lock, flags); -++ if (q->count == 0) { -++ spin_unlock_irqrestore(&q->lock, flags); -++ return -1; -++ } -++ r = *(q->id + 0); -++ for (i=0;i < q->count-1;i++) -++ *(q->id + i) = *(q->id + (i+1)); -++ q->count --; -++ spin_unlock_irqrestore(&q->lock, flags); -++ -++ return r; -++} -++ -++static inline void put_buffer_id(struct buffer_queue_s *q, int id) -++{ -++ unsigned long flags; -++ -++ spin_lock_irqsave(&q->lock, flags); -++ *(q->id + q->count) = id; -++ q->count ++; -++ spin_unlock_irqrestore(&q->lock, flags); -++} -++ -++static inline int elements_in_queue(struct buffer_queue_s *q) -++{ -++ int r; -++ unsigned long flags; -++ -++ spin_lock_irqsave(&q->lock, flags); -++ r = q->count; -++ spin_unlock_irqrestore(&q->lock, flags); -++ -++ return r; -++} -++ -++static inline void audio_start_dma(int chan, void *dev_id, unsigned long phyaddr,int count, int mode) -++{ -++ unsigned long flags; -++ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ jz_audio_dma_tran_count = count / jz_audio_b; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ flags = claim_dma_lock(); -++ disable_dma(chan); -++ clear_dma_ff(chan); -++#if 1 -++ jz_set_oss_dma(chan, mode, jz_audio_format); -++#else -++ set_dma_mode(chan, mode); -++#endif -++ set_dma_addr(chan, phyaddr); -++ if (count == 0) { -++ count++; -++ printk("JzSOC DMA controller can't set dma 0 count!\n"); -++ } -++ set_dma_count(chan, count); -++ enable_dma(chan); -++ release_dma_lock(flags); -++} -++ -++static irqreturn_t jz_i2s_record_dma_irq (int irq, void *dev_id) -++{ -++ int id1, id2; -++ unsigned long flags; -++ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -++ int dma = controller->dma2; -++ -++ disable_dma(dma); -++ if (__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if (__dmac_channel_transmit_end_detected(dma)) { -++ __dmac_channel_clear_transmit_end(dma); -++ -++ if(drain_flag == 1) -++ wake_up(&drain_wait_queue); -++ /* for DSP_GETIPTR */ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ id1 = get_buffer_id(&in_busy_queue); -++ put_buffer_id(&in_full_queue, id1); -++ -++ wake_up(&rx_wait_queue); -++ wake_up(&controller->adc_wait); -++ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id2); -++ *(in_dma_buf_data_count + id2) = *(in_dma_buf_data_count + id1); -++ dma_cache_wback_inv(*(in_dma_buf + id2), *(in_dma_buf_data_count + id2)); -++ audio_start_dma(dma,dev_id, -++ *(in_dma_pbuf + id2), -++ *(in_dma_buf_data_count + id2), -++ DMA_MODE_READ); -++ } else -++ in_busy_queue.count = 0; -++ } -++ -++ return IRQ_HANDLED; -++} -++ -++static irqreturn_t jz_i2s_replay_dma_irq (int irq, void *dev_id) -++{ -++ int id; -++ unsigned long flags; -++ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -++ int dma = controller->dma1; -++ -++ disable_dma(dma); -++ if (__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if (__dmac_channel_transmit_end_detected(dma)) { -++ __dmac_channel_clear_transmit_end(dma); -++ -++ if(pop_dma_flag == 1) { -++ pop_dma_flag = 0; -++ wake_up(&pop_wait_queue); -++ } else { -++ if(drain_flag == 1) { -++ /* Is replay dma buffer over ? */ -++ if(elements_in_queue(&out_full_queue) <= 0) { -++ drain_flag = 0; -++ wake_up(&drain_wait_queue); -++ } -++ } -++ -++ /* for DSP_GETOPTR */ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ if ((id = get_buffer_id(&out_busy_queue)) < 0) -++ printk(KERN_DEBUG "Strange DMA finish interrupt for I2S module\n"); -++ put_buffer_id(&out_empty_queue, id); -++ if ((id = get_buffer_id(&out_full_queue)) >= 0) { -++ put_buffer_id(&out_busy_queue, id); -++ if(*(out_dma_buf_data_count + id) > 0) { -++ audio_start_dma(dma, dev_id, *(out_dma_pbuf + id), -++ *(out_dma_buf_data_count + id), -++ DMA_MODE_WRITE); -++ last_dma_buffer_id = id; -++ } -++ } else -++ out_busy_queue.count = 0; -++ -++ if (elements_in_queue(&out_empty_queue) > 0) { -++ wake_up(&tx_wait_queue); -++ wake_up(&controller->dac_wait); -++ } -++ } -++ } -++ -++ return IRQ_HANDLED; -++} -++ -++static void jz_i2s_initHw(int set) -++{ -++#if defined(CONFIG_MIPS_JZ_URANUS) -++ i2s_clk = 48000000; -++#else -++ i2s_clk = __cpm_get_i2sclk(); -++#endif -++ __i2s_disable(); -++ if(set) -++ __i2s_reset(); -++ schedule_timeout(5); -++ if(each_time_init_codec) -++ each_time_init_codec(); -++ __i2s_disable_record(); -++ __i2s_disable_replay(); -++ __i2s_disable_loopback(); -++ __i2s_set_transmit_trigger(4); -++ __i2s_set_receive_trigger(3); -++} -++ -++static int Init_In_Out_queue(int fragstotal,int fragsize) -++{ -++ int i; -++ -++ /* recording */ -++ in_empty_queue.count = fragstotal; -++ in_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_buf) -++ goto all_mem_err; -++ in_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_pbuf) -++ goto all_mem_err; -++ in_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_buf_data_count) -++ goto all_mem_err; -++ in_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_empty_queue.id) -++ goto all_mem_err; -++ in_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_full_queue.id) -++ goto all_mem_err; -++ in_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_busy_queue.id) -++ goto all_mem_err; -++ -++ for (i=0;i < fragstotal;i++) -++ *(in_empty_queue.id + i) = i; -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ -++ for (i = 0; i < fragstotal; i++) { -++ *(in_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -++ if (*(in_dma_buf + i) == 0) -++ goto mem_failed_in; -++ *(in_dma_pbuf + i) = virt_to_phys((void *)(*(in_dma_buf + i))); -++ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -++ } -++ -++ /* playing */ -++ out_empty_queue.count = fragstotal; -++ out_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!out_dma_buf) -++ goto all_mem_err; -++ out_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!out_dma_pbuf) -++ goto all_mem_err; -++ out_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ -++ if (!out_dma_buf_data_count) -++ goto all_mem_err; -++ out_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_empty_queue.id) -++ goto all_mem_err; -++ out_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_full_queue.id) -++ goto all_mem_err; -++ out_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_busy_queue.id) -++ goto all_mem_err; -++ for (i=0;i < fragstotal;i++) -++ *(out_empty_queue.id + i) = i; -++ -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ /* alloc DMA buffer */ -++ for (i = 0; i < fragstotal; i++) { -++ *(out_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -++ if (*(out_dma_buf + i) == 0) { -++ printk(" can't allocate required DMA(OUT) buffers.\n"); -++ goto mem_failed_out; -++ } -++ *(out_dma_pbuf + i) = virt_to_phys((void *)(*(out_dma_buf + i))); -++ } -++ -++ return 1; -++all_mem_err: -++ printk("error:allocate memory occur error 1!\n"); -++ return 0; -++mem_failed_out: -++ printk("error:allocate memory occur error 2!\n"); -++ for (i = 0; i < fragstotal; i++) { -++ if(*(out_dma_buf + i)) -++ free_pages(*(out_dma_buf + i), get_order(fragsize)); -++ } -++ -++ return 0; -++mem_failed_in: -++ printk("error:allocate memory occur error 3!\n"); -++ for (i = 0; i < fragstotal; i++) { -++ if(*(in_dma_buf + i)) -++ free_pages(*(in_dma_buf + i), get_order(fragsize)); -++ } -++ return 0; -++} -++ -++static int Free_In_Out_queue(int fragstotal,int fragsize) -++{ -++ int i; -++ /* playing */ -++ if(out_dma_buf != NULL) { -++ for (i = 0; i < fragstotal; i++) { -++ if(*(out_dma_buf + i)) -++ free_pages(*(out_dma_buf + i), get_order(fragsize)); -++ *(out_dma_buf + i) = 0; -++ } -++ kfree(out_dma_buf); -++ out_dma_buf = NULL; -++ } -++ if(out_dma_pbuf) { -++ kfree(out_dma_pbuf); -++ out_dma_pbuf = NULL; -++ } -++ if(out_dma_buf_data_count) { -++ kfree(out_dma_buf_data_count); -++ out_dma_buf_data_count = NULL; -++ } -++ if(out_empty_queue.id) { -++ kfree(out_empty_queue.id); -++ out_empty_queue.id = NULL; -++ } -++ if(out_full_queue.id) { -++ kfree(out_full_queue.id); -++ out_full_queue.id = NULL; -++ } -++ if(out_busy_queue.id) { -++ kfree(out_busy_queue.id); -++ out_busy_queue.id = NULL; -++ } -++ out_empty_queue.count = fragstotal; -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ -++ /* recording */ -++ if(in_dma_buf) { -++ for (i = 0; i < fragstotal; i++) { -++ if(*(in_dma_buf + i)) { -++ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -++ free_pages(*(in_dma_buf + i), get_order(fragsize)); -++ } -++ *(in_dma_buf + i) = 0; -++ } -++ kfree(in_dma_buf); -++ in_dma_buf = NULL; -++ } -++ if(in_dma_pbuf) { -++ kfree(in_dma_pbuf); -++ in_dma_pbuf = NULL; -++ } -++ if(in_dma_buf_data_count) { -++ kfree(in_dma_buf_data_count); -++ in_dma_buf_data_count = NULL; -++ } -++ if(in_empty_queue.id) { -++ kfree(in_empty_queue.id); -++ in_empty_queue.id = NULL; -++ } -++ if(in_full_queue.id) { -++ kfree(in_full_queue.id); -++ in_full_queue.id = NULL; -++ } -++ if(in_busy_queue.id) { -++ kfree(in_busy_queue.id); -++ in_busy_queue.id = NULL; -++ } -++ -++ in_empty_queue.count = fragstotal; -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ -++ return 1; -++} -++ -++static void jz_i2s_full_reset(struct jz_i2s_controller_info *controller) -++{ -++ jz_i2s_initHw(0); -++} -++ -++static int jz_audio_set_speed(int dev, int rate) -++{ -++ /* 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999 ? */ -++ jz_audio_speed = rate; -++#if defined(CONFIG_I2S_DLV) -++ if (rate > 96000) -++ rate = 96000; -++#else -++ if (rate > 48000) -++ rate = 48000; -++#endif -++ if (rate < 8000) -++ rate = 8000; -++ jz_audio_rate = rate; -++ -++ if(set_codec_speed) -++ set_codec_speed(rate); -++ -++ return jz_audio_rate; -++} -++ -++ -++static int record_fill_1x8_u(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long data; -++ volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ volatile unsigned char *dp = (unsigned char*)dst_start; -++ -++ while (count > 0) { -++ count -= 2; /* count in dword */ -++ cnt++; -++ data = *(s++); -++ *(dp ++) = ((data << 16) >> 24) + 0x80; -++ s++; /* skip the other channel */ -++ } -++ -++ return cnt; -++} -++ -++ -++static int record_fill_2x8_u(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long d1, d2; -++ volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ volatile unsigned char *dp = (unsigned char*)dst_start; -++ -++ while (count > 0) { -++ count -= 2; -++ cnt += 2; -++ d1 = *(s++); -++ *(dp ++) = ((d1 << 16) >> 24) + 0x80; -++ d2 = *(s++); -++ *(dp ++) = ((d2 << 16) >> 24) + 0x80; -++ } -++ -++ return cnt; -++} -++ -++ -++static int record_fill_1x16_s(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long d1; -++ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ unsigned short *dp = (unsigned short *)dst_start; -++ -++ while (count > 0) { -++ count -= 2; /* count in dword */ -++ cnt += 2; /* count in byte */ -++ d1 = *(s++); -++ *(dp ++) = (d1 << 16) >> 16; -++ s++; /* skip the other channel */ -++ } -++ -++ return cnt; -++} -++ -++ -++static int record_fill_2x16_s(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long d1, d2; -++ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ unsigned short *dp = (unsigned short *)dst_start; -++ while (count > 0) { -++ count -= 2; /* count in dword */ -++ cnt += 4; /* count in byte */ -++ d1 = *(s++); -++ d2 = *(s++); -++ if(abnormal_data_count > 0) { -++ d1 = d2 = 0; -++ abnormal_data_count --; -++ } -++ *(dp ++) = (d1 << 16) >> 16; -++ *(dp ++) = (d2 << 16) >> 16; -++ } -++ -++ return cnt; -++} -++ -++static void replay_fill_1x8_u(signed long src_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned char data; -++ unsigned long ddata; -++ volatile unsigned char *s = (unsigned char *)src_start; -++ volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); -++ -++ while (count > 0) { -++ count--; -++ cnt += 1; -++ data = *(s++) - 0x80; -++ ddata = (unsigned long) data << 8; -++ *(dp ++) = ddata; -++ *(dp ++) = ddata; -++ -++ /* save last left and right */ -++ if(count == 1) { -++ save_last_samples[id].left = ddata; -++ save_last_samples[id].right = ddata; -++ } -++ } -++ cnt = cnt * 2 * jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++ -++static void replay_fill_2x8_u(signed long src_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned char d1; -++ unsigned long dd1; -++ volatile unsigned char *s = (unsigned char *)src_start; -++ volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); -++ -++ while (count > 0) { -++ count -= 1; -++ cnt += 1 ; -++ d1 = *(s++) - 0x80; -++ dd1 = (unsigned long) d1 << 8; -++ *(dp ++) = dd1; -++ /* save last left */ -++ if(count == 2) -++ save_last_samples[id].left = dd1; -++ /* save last right */ -++ if(count == 1) -++ save_last_samples[id].right = dd1; -++ } -++ cnt *= jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++ -++static void replay_fill_1x16_s(signed long src_start, int count, int id) -++{ -++ int cnt = 0; -++ signed short d1; -++ signed long l1; -++ volatile signed short *s = (signed short *)src_start; -++ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -++ -++ while (count > 0) { -++ count -= 2; -++ cnt += 2 ; -++ d1 = *(s++); -++ l1 = (signed long)d1; -++#if defined(CONFIG_I2S_ICODEC) -++ l1 >>= codec_volue_shift; -++#endif -++ *(dp ++) = l1; -++ *(dp ++) = l1; -++ -++ /* save last left and right */ -++ if(count == 1) { -++ save_last_samples[id].left = l1; -++ save_last_samples[id].right = l1; -++ } -++ } -++ cnt = cnt * 2 * jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++static void replay_fill_2x16_s(signed long src_start, int count, int id) -++{ -++ int cnt = 0; -++ signed short d1; -++ signed long l1; -++ volatile signed short *s = (signed short *)src_start; -++ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -++#if defined(CONFIG_I2S_ICODEC) -++ int mute_cnt = 0; -++ signed long tmp1,tmp2; -++ volatile signed long *before_dp; -++ int sam_rate = jz_audio_rate / 20; -++ -++ tmp1 = tmp2 = 0; -++ while (count > 0) { -++ count -= 2; -++ cnt += 2; -++ d1 = *(s++); -++ -++ l1 = (signed long)d1; -++ l1 >>= codec_volue_shift; -++ -++ if(l1 == 0) { -++ mute_cnt ++; -++ if(mute_cnt >= sam_rate) { -++ before_dp = dp - 10; -++ *(before_dp) = (signed long)1; -++ before_dp = dp - 11; -++ *(before_dp) = (signed long)1; -++ mute_cnt = 0; -++ } -++ } else -++ mute_cnt = 0; -++ -++ *(dp ++) = l1; -++ -++ tmp1 = tmp2; -++ tmp2 = l1; -++ } -++ -++ /* save last left */ -++ save_last_samples[id].left = tmp1; -++ /* save last right */ -++ save_last_samples[id].right = tmp2; -++#endif -++#if defined(CONFIG_I2S_DLV) -++ while (count > 0) { -++ count -= 2; -++ cnt += 2; -++ d1 = *(s++); -++ -++ l1 = (signed long)d1; -++ -++ *(dp ++) = l1; -++ } -++#endif -++ cnt *= jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++static void replay_fill_2x18_s(unsigned long src_start, int count, int id) -++{ -++ int cnt = 0; -++ signed long d1; -++ signed long l1; -++ volatile signed long *s = (signed long *)src_start; -++ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -++ while (count > 0) { -++ count -= 4; -++ cnt += 4; -++ d1 = *(s++); -++ l1 = (signed long)d1; -++ *(dp ++) = l1; -++ } -++ -++ cnt *= jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++static unsigned int jz_audio_set_format(int dev, unsigned int fmt) -++{ -++ switch (fmt) { -++ case AFMT_U8: -++ __i2s_set_oss_sample_size(8); -++ __i2s_set_iss_sample_size(8); -++ jz_audio_format = fmt; -++ jz_update_filler(jz_audio_format,jz_audio_channels); -++ break; -++ case AFMT_S16_LE: -++#if defined(CONFIG_I2S_DLV) -++ /* DAC path and ADC path */ -++ write_codec_file(2, 0x00); -++ //write_codec_file(2, 0x60); -++#endif -++ jz_audio_format = fmt; -++ jz_update_filler(jz_audio_format,jz_audio_channels); -++ __i2s_set_oss_sample_size(16); -++ __i2s_set_iss_sample_size(16); -++ break; -++ case 18: -++ __i2s_set_oss_sample_size(18); -++ jz_audio_format = fmt; -++ jz_update_filler(jz_audio_format,jz_audio_channels); -++ break; -++ case AFMT_QUERY: -++ break; -++ } -++ -++ return jz_audio_format; -++} -++ -++ -++static short jz_audio_set_channels(int dev, short channels) -++{ -++ switch (channels) { -++ case 1: -++ if(set_codec_some_func) -++ set_codec_some_func(); -++ jz_audio_channels = channels; -++ jz_update_filler(jz_audio_format, jz_audio_channels); -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file_bit(1, 1, 6);//CR1.MONO->1 for Mono -++#endif -++ break; -++ case 2: -++ jz_audio_channels = channels; -++ jz_update_filler(jz_audio_format, jz_audio_channels); -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file_bit(1, 0, 6);//CR1.MONO->0 for Stereo -++#endif -++ break; -++ case 0: -++ break; -++ } -++ -++ return jz_audio_channels; -++} -++ -++static void init_codec(void) -++{ -++ /* inititalize internal I2S codec */ -++ if(init_codec_pin) -++ init_codec_pin(); -++ -++#if defined(CONFIG_I2S_ICDC) -++ /* initialize AIC but not reset it */ -++ jz_i2s_initHw(0); -++#endif -++ if(reset_codec) -++ reset_codec(); -++} -++ -++static void jz_audio_reset(void) -++{ -++ __i2s_disable_replay(); -++ __i2s_disable_receive_dma(); -++ __i2s_disable_record(); -++ __i2s_disable_transmit_dma(); -++#if defined(CONFIG_I2S_DLV) -++ REG_AIC_I2SCR = 0x10; -++#endif -++ init_codec(); -++} -++ -++static int jz_audio_release(struct inode *inode, struct file *file); -++static int jz_audio_open(struct inode *inode, struct file *file); -++static int jz_audio_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg); -++static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait); -++static ssize_t jz_audio_write(struct file *file, const char *buffer,size_t count, loff_t *ppos); -++static ssize_t jz_audio_read(struct file *file, char *buffer,size_t count, loff_t *ppos); -++ -++/* static struct file_operations jz_i2s_audio_fops */ -++static struct file_operations jz_i2s_audio_fops = -++{ -++ owner: THIS_MODULE, -++ open: jz_audio_open, -++ release: jz_audio_release, -++ write: jz_audio_write, -++ read: jz_audio_read, -++ poll: jz_audio_poll, -++ ioctl: jz_audio_ioctl -++}; -++ -++static int jz_i2s_open_mixdev(struct inode *inode, struct file *file) -++{ -++ int i; -++ int minor = MINOR(inode->i_rdev); -++ struct jz_i2s_controller_info *controller = i2s_controller; -++ -++ for (i = 0; i < NR_I2S; i++) -++ if (controller->i2s_codec[i] != NULL && controller->i2s_codec[i]->dev_mixer == minor) -++ goto match; -++ -++ if (!controller) -++ return -ENODEV; -++match: -++ file->private_data = controller->i2s_codec[i]; -++ -++ return 0; -++} -++ -++static int jz_i2s_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -++{ -++ struct i2s_codec *codec = (struct i2s_codec *)file->private_data; -++ return codec->mixer_ioctl(codec, cmd, arg); -++} -++ -++static loff_t jz_i2s_llseek(struct file *file, loff_t offset, int origin) -++{ -++ return -ESPIPE; -++} -++ -++static struct file_operations jz_i2s_mixer_fops = -++{ -++ owner: THIS_MODULE, -++ llseek: jz_i2s_llseek, -++ ioctl: jz_i2s_ioctl_mixdev, -++ open: jz_i2s_open_mixdev, -++}; -++ -++static int i2s_mixer_ioctl(struct i2s_codec *codec, unsigned int cmd, unsigned long arg) -++{ -++ int ret; -++ long val = 0; -++ switch (cmd) { -++ case SOUND_MIXER_INFO: -++ -++ if(codec_mixer_info_id_name) -++ codec_mixer_info_id_name(); -++ info.modify_counter = audio_mix_modcnt; -++ -++ return copy_to_user((void *)arg, &info, sizeof(info)); -++ case SOUND_OLD_MIXER_INFO: -++ -++ if(codec_mixer_old_info_id_name) -++ codec_mixer_old_info_id_name(); -++ -++ return copy_to_user((void *)arg, &old_info, sizeof(info)); -++ case SOUND_MIXER_READ_STEREODEVS: -++ -++ return put_user(0, (long *) arg); -++ case SOUND_MIXER_READ_CAPS: -++ -++ val = SOUND_CAP_EXCL_INPUT; -++ return put_user(val, (long *) arg); -++ case SOUND_MIXER_READ_DEVMASK: -++ break; -++ case SOUND_MIXER_READ_RECMASK: -++ break; -++ case SOUND_MIXER_READ_RECSRC: -++ break; -++ case SOUND_MIXER_WRITE_SPEAKER: -++ -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val > 100) -++ val = 100; -++ switch(val) { -++ case 100: -++ if(set_codec_direct_mode) -++ set_codec_direct_mode(); -++ break; -++ case 0: -++ if(clear_codec_direct_mode) -++ clear_codec_direct_mode(); -++ break; -++ } -++ break; -++ case SOUND_MIXER_WRITE_BASS: -++ -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val > 100) -++ val = 100; -++ codec_bass_gain = val; -++ if(set_codec_bass) -++ set_codec_bass(val); -++ -++ return 0; -++ case SOUND_MIXER_READ_BASS: -++ -++ val = codec_bass_gain; -++ ret = val << 8; -++ val = val | ret; -++ -++ return put_user(val, (long *) arg); -++ case SOUND_MIXER_WRITE_VOLUME: -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val > 100) -++ val = 100; -++ -++ jz_audio_volume = val; -++ if(set_codec_volume) -++ set_codec_volume(val); -++ -++ return 0; -++ case SOUND_MIXER_READ_VOLUME: -++ -++ val = jz_audio_volume; -++ ret = val << 8; -++ val = val | ret; -++ -++ return put_user(val, (long *) arg); -++ -++ case SOUND_MIXER_WRITE_MIC: -++ -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val > 100) -++ val = 100; -++ codec_mic_gain = val; -++ use_mic_line_flag = USE_MIC; -++ if(set_codec_mic) -++ set_codec_mic(val); -++ -++ return 0; -++ case SOUND_MIXER_READ_MIC: -++ -++ val = codec_mic_gain; -++ ret = val << 8; -++ val = val | ret; -++ -++ return put_user(val, (long *) arg); -++ -++ case SOUND_MIXER_WRITE_LINE: -++ -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val > 100) -++ val = 100; -++ use_mic_line_flag = USE_LINEIN; -++ codec_mic_gain = val; -++ if(set_codec_line) -++ set_codec_line(val); -++ -++ return 0; -++ case SOUND_MIXER_READ_LINE: -++ -++ val = codec_mic_gain; -++ ret = val << 8; -++ val = val | ret; -++ -++ return put_user(val, (long *) arg); -++ default: -++ return -ENOSYS; -++ } -++ audio_mix_modcnt ++; -++ return 0; -++} -++ -++ -++int i2s_probe_codec(struct i2s_codec *codec) -++{ -++ /* generic OSS to I2S wrapper */ -++ codec->mixer_ioctl = i2s_mixer_ioctl; -++ return 1; -++} -++ -++ -++/* I2S codec initialisation. */ -++static int __init jz_i2s_codec_init(struct jz_i2s_controller_info *controller) -++{ -++ int num_i2s = 0; -++ struct i2s_codec *codec; -++ -++ for (num_i2s = 0; num_i2s < NR_I2S; num_i2s++) { -++ if ((codec = kmalloc(sizeof(struct i2s_codec),GFP_KERNEL)) == NULL) -++ return -ENOMEM; -++ memset(codec, 0, sizeof(struct i2s_codec)); -++ codec->private_data = controller; -++ codec->id = num_i2s; -++ -++ if (i2s_probe_codec(codec) == 0) -++ break; -++ if ((codec->dev_mixer = register_sound_mixer(&jz_i2s_mixer_fops, -1)) < 0) { -++ printk(KERN_ERR "Jz I2S: couldn't register mixer!\n"); -++ kfree(codec); -++ break; -++ } -++ controller->i2s_codec[num_i2s] = codec; -++ } -++ return num_i2s; -++} -++ -++ -++static void jz_update_filler(int format, int channels) -++{ -++#define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3)) -++ -++ switch (TYPE(format, channels)) -++ { -++ -++ case TYPE(AFMT_U8, 1): -++ jz_audio_b = 4; /* 4bytes * 8bits =32bits */ -++ replay_filler = replay_fill_1x8_u; -++ record_filler = record_fill_1x8_u; -++ break; -++ case TYPE(AFMT_U8, 2): -++ jz_audio_b = 4; -++ replay_filler = replay_fill_2x8_u; -++ record_filler = record_fill_2x8_u; -++ break; -++ case TYPE(AFMT_S16_LE, 1): -++ jz_audio_b = 2; /* 2bytes * 16bits =32bits */ -++ replay_filler = replay_fill_1x16_s; -++ record_filler = record_fill_1x16_s; -++ break; -++ case TYPE(AFMT_S16_LE, 2): -++ jz_audio_b = 2; -++ replay_filler = replay_fill_2x16_s; -++ record_filler = record_fill_2x16_s; -++ break; -++ case TYPE(18, 2): -++ jz_audio_b = 1; -++ replay_filler = replay_fill_2x18_s; -++ record_filler = record_fill_2x16_s; -++ break; -++ default: -++ ; -++ } -++} -++ -++ -++#ifdef CONFIG_PROC_FS -++extern struct proc_dir_entry *proc_jz_root; -++int i2s_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) -++{ -++ return 0; -++} -++ -++static int jz_i2s_init_proc(struct jz_i2s_controller_info *controller) -++{ -++ if (!create_proc_read_entry ("i2s", 0, proc_jz_root, i2s_read_proc, controller->i2s_codec[0])) -++ return -EIO; -++ return 0; -++} -++ -++static void jz_i2s_cleanup_proc(struct jz_i2s_controller_info *controller) -++{ -++} -++#endif -++ -++static void __init attach_jz_i2s(struct jz_i2s_controller_info *controller) -++{ -++ char *name; -++ int adev; /* No of Audio device. */ -++ -++ name = controller->name; -++ /* initialize AIC controller and reset it */ -++ jz_i2s_initHw(1); -++ adev = register_sound_dsp(&jz_i2s_audio_fops, -1); -++ if (adev < 0) -++ goto audio_failed; -++ /* initialize I2S codec and register /dev/mixer */ -++ if (jz_i2s_codec_init(controller) <= 0) -++ goto mixer_failed; -++ -++#ifdef CONFIG_PROC_FS -++ if (jz_i2s_init_proc(controller) < 0) { -++ printk(KERN_ERR "%s: can't create I2S proc filesystem.\n", name); -++ goto proc_failed; -++ } -++#endif -++ -++ controller->tmp1 = (void *)__get_free_pages(GFP_KERNEL, 8); -++ if (!controller->tmp1) { -++ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -++ goto tmp1_failed; -++ } -++ controller->tmp2 = (void *)__get_free_pages(GFP_KERNEL, 8); -++ if (!controller->tmp2) { -++ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -++ goto tmp2_failed; -++ } -++ if ((controller->dma2 = jz_request_dma(DMA_ID_I2S_RX, "audio adc", jz_i2s_record_dma_irq, IRQF_DISABLED, controller)) < 0) { -++ printk(KERN_ERR "%s: can't reqeust DMA ADC channel.\n", name); -++ goto dma2_failed; -++ } -++ if ((controller->dma1 = jz_request_dma(DMA_ID_I2S_TX, "audio dac", jz_i2s_replay_dma_irq, IRQF_DISABLED, controller)) < 0) { -++ printk(KERN_ERR "%s: can't reqeust DMA DAC channel.\n", name); -++ goto dma1_failed; -++ } -++ printk("JzSOC On-Chip I2S controller registered (DAC: DMA(play):%d/IRQ%d,\n ADC: DMA(record):%d/IRQ%d)\n", controller->dma1, get_dma_done_irq(controller->dma1), controller->dma2, get_dma_done_irq(controller->dma2)); -++ -++ controller->dev_audio = adev; -++ pop_turn_onoff_buf = __get_free_pages(GFP_KERNEL | GFP_DMA, 8); -++ if(!pop_turn_onoff_buf) -++ printk("pop_turn_onoff_buf alloc is wrong!\n"); -++ pop_turn_onoff_pbuf = virt_to_phys((void *)pop_turn_onoff_buf); -++ -++ return; -++dma2_failed: -++ jz_free_dma(controller->dma1); -++dma1_failed: -++ free_pages((unsigned long)controller->tmp2, 8); -++tmp2_failed: -++ free_pages((unsigned long)controller->tmp1, 8); -++tmp1_failed: -++ -++#ifdef CONFIG_PROC_FS -++ jz_i2s_cleanup_proc(controller); -++#endif -++proc_failed: -++ /* unregister mixer dev */ -++mixer_failed: -++ unregister_sound_dsp(adev); -++audio_failed: -++ return; -++} -++ -++static int __init probe_jz_i2s(struct jz_i2s_controller_info **controller) -++{ -++ if ((*controller = kmalloc(sizeof(struct jz_i2s_controller_info), -++ GFP_KERNEL)) == NULL) { -++ printk(KERN_ERR "Jz I2S Controller: out of memory.\n"); -++ return -ENOMEM; -++ } -++ (*controller)->name = "Jz I2S controller"; -++ (*controller)->opened1 = 0; -++ (*controller)->opened2 = 0; -++ init_waitqueue_head(&(*controller)->adc_wait); -++ init_waitqueue_head(&(*controller)->dac_wait); -++ spin_lock_init(&(*controller)->lock); -++ init_waitqueue_head(&rx_wait_queue); -++ init_waitqueue_head(&tx_wait_queue); -++ init_waitqueue_head(&pop_wait_queue); -++ init_waitqueue_head(&drain_wait_queue); -++ -++ return 0; -++} -++ -++static void __exit unload_jz_i2s(struct jz_i2s_controller_info *controller) -++{ -++ int adev = controller->dev_audio; -++ -++ jz_i2s_full_reset(controller); -++ controller->dev_audio = -1; -++ if (old_mksound) -++ kd_mksound = old_mksound;/* Our driver support bell for kb, see vt.c */ -++ -++#ifdef CONFIG_PROC_FS -++ jz_i2s_cleanup_proc(controller); -++#endif -++ -++ jz_free_dma(controller->dma1); -++ jz_free_dma(controller->dma2); -++ free_pages((unsigned long)controller->tmp1, 8); -++ free_pages((unsigned long)controller->tmp2, 8); -++ free_pages((unsigned long)pop_turn_onoff_buf, 8); -++ -++ if (adev >= 0) { -++ /* unregister_sound_mixer(audio_devs[adev]->mixer_dev); */ -++ unregister_sound_dsp(controller->dev_audio); -++ } -++} -++ -++#ifdef CONFIG_PM -++static int jz_i2s_suspend(struct jz_i2s_controller_info *controller, int state) -++{ -++ if(i2s_suspend_codec) -++ i2s_suspend_codec(controller->opened1,controller->opened2); -++ printk("Aic and codec are suspended!\n"); -++ return 0; -++} -++ -++static int jz_i2s_resume(struct jz_i2s_controller_info *controller) -++{ -++ if(i2s_resume_codec) -++ i2s_resume_codec(); -++ -++#if defined(CONFIG_I2S_AK4642EN) -++ jz_i2s_initHw(0); -++ jz_audio_reset(); -++ __i2s_enable(); -++ jz_audio_set_speed(controller->dev_audio,jz_audio_speed); -++ /* playing */ -++ if(controller->opened1) { -++ if(set_codec_replay) -++ set_codec_replay(); -++ int dma = controller->dma1; -++ int id; -++ unsigned long flags; -++ disable_dma(dma); -++ if(__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if(__dmac_channel_transmit_end_detected(dma)) -++ __dmac_channel_clear_transmit_end(dma); -++ -++ /* for DSP_GETOPTR */ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ while((id = get_buffer_id(&out_busy_queue)) >= 0) -++ put_buffer_id(&out_empty_queue, id); -++ -++ out_busy_queue.count=0; -++ if((id = get_buffer_id(&out_full_queue)) >= 0) { -++ put_buffer_id(&out_empty_queue, id); -++ } -++ if (elements_in_queue(&out_empty_queue) > 0) { -++ wake_up(&tx_wait_queue); -++ wake_up(&controller->dac_wait); -++ } else -++ printk("pm out_empty_queue empty"); -++ } -++ -++ /* recording */ -++ if(controller->opened2) { -++ if(set_codec_record) -++ set_codec_record(use_mic_line_flag); -++ int dma = controller->dma2; -++ int id1, id2; -++ unsigned long flags; -++ disable_dma(dma); -++ if (__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if (__dmac_channel_transmit_end_detected(dma)) { -++ __dmac_channel_clear_transmit_end(dma); -++ } -++ /* for DSP_GETIPTR */ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ id1 = get_buffer_id(&in_busy_queue); -++ put_buffer_id(&in_full_queue, id1); -++ wake_up(&rx_wait_queue); -++ wake_up(&controller->adc_wait); -++ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_full_queue, id2); -++ } -++ in_busy_queue.count = 0; -++ } -++#endif -++ -++ return 0; -++} -++ -++static int jz_i2s_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -++{ -++ int ret; -++ struct jz_i2s_controller_info *controller = pm_dev->data; -++ -++ if (!controller) return -EINVAL; -++ -++ switch (req) { -++ case PM_SUSPEND: -++ ret = jz_i2s_suspend(controller, (int)data); -++ break; -++ case PM_RESUME: -++ ret = jz_i2s_resume(controller); -++ break; -++ default: -++ ret = -EINVAL; -++ break; -++ } -++ return ret; -++} -++#endif /* CONFIG_PM */ -++ -++#if defined(CONFIG_I2S_DLV) -++static irqreturn_t aic_codec_irq(int irq, void *dev_id) -++{ -++ u8 file_9 = read_codec_file(9); -++ u8 file_8 = read_codec_file(8); -++ -++ //printk("--- 8:0x%x 9:0x%x ---\n",file_8,file_9); -++ if ((file_9 & 0x1f) == 0x10) { -++ -++ write_codec_file(8, 0x3f); -++ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ mdelay(300); -++ while ((read_codec_file(9) & 0x4) != 0x4); -++ while ((read_codec_file(9) & 0x10) == 0x10) { -++ write_codec_file(9, 0x10); -++ } -++ write_codec_file_bit(5, 0, 6);//SB_OUT->0 -++ mdelay(300); -++ while ((read_codec_file(9) & 0x8) != 0x8); -++ write_codec_file(9, file_9); -++ write_codec_file(8, file_8); -++ -++ return IRQ_HANDLED; -++ } -++ -++ if (file_9 & 0x8) -++ ramp_up_end = jiffies; -++ else if (file_9 & 0x4) -++ ramp_down_end = jiffies; -++ else if (file_9 & 0x2) -++ gain_up_end = jiffies; -++ else if (file_9 & 0x1) -++ gain_down_end = jiffies; -++ -++ write_codec_file(9, file_9); -++ if (file_9 & 0xf) -++ wake_up(&pop_wait_queue); -++ while (REG_ICDC_RGDATA & 0x100); -++ -++ return IRQ_HANDLED; -++} -++#endif -++ -++static int __init init_jz_i2s(void) -++{ -++ int errno; -++#if defined(CONFIG_I2S_DLV) -++ int retval; -++ ramp_up_start = 0; -++ ramp_up_end = 0; -++ gain_up_start = 0; -++ gain_up_end = 0; -++ ramp_down_start = 0; -++ ramp_down_end = 0; -++ gain_down_start = 0; -++ gain_down_end = 0; -++#endif -++ use_mic_line_flag = USE_NONE; -++ abnormal_data_count = 0; -++ if(set_codec_mode) -++ set_codec_mode(); -++ -++ drain_flag = 0; -++ if ((errno = probe_jz_i2s(&i2s_controller)) < 0) -++ return errno; -++ if(set_codec_gpio_pin) -++ set_codec_gpio_pin(); -++ -++ attach_jz_i2s(i2s_controller); -++ if(set_codec_startup_param) -++ set_codec_startup_param(); -++ if(set_codec_volume_table) -++ set_codec_volume_table(); -++ -++#if defined(CONFIG_I2S_DLV) -++ jz_codec_config = 0; -++ retval = request_irq(IRQ_AIC, aic_codec_irq, IRQF_DISABLED, "aic_codec_irq", NULL); -++ if (retval) { -++ printk("Could not get aic codec irq %d\n", IRQ_AIC); -++ return retval; -++ } -++#endif -++ -++ out_empty_queue.id = NULL; -++ out_full_queue.id = NULL; -++ out_busy_queue.id = NULL; -++ in_empty_queue.id = NULL; -++ in_full_queue.id = NULL; -++ in_busy_queue.id = NULL; -++ -++ jz_audio_fragsize = JZCODEC_RW_BUFFER_SIZE * PAGE_SIZE; -++ jz_audio_fragstotal = JZCODEC_RW_BUFFER_TOTAL ; -++ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ -++#ifdef CONFIG_PM -++ i2s_controller->pm = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, -++ jz_i2s_pm_callback); -++ if (i2s_controller->pm) -++ i2s_controller->pm->data = i2s_controller; -++#endif -++#if defined(CONFIG_I2S_DLV) -++ __cpm_start_idct(); -++ __cpm_start_db(); -++ __cpm_start_me(); -++ __cpm_start_mc(); -++ __cpm_start_ipu(); -++#endif -++ printk("JZ I2S OSS audio driver initialized\n"); -++ -++ return 0; -++} -++ -++static void __exit cleanup_jz_i2s(void) -++{ -++#ifdef CONFIG_PM -++ /* pm_unregister(i2s_controller->pm); */ -++#endif -++#if defined(CONFIG_I2S_DLV) -++ free_irq(IRQ_AIC, NULL); -++#endif -++ unload_jz_i2s(i2s_controller); -++ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ if(clear_codec_mode) -++ clear_codec_mode(); -++} -++ -++module_init(init_jz_i2s); -++module_exit(cleanup_jz_i2s); -++ -++#if defined(CONFIG_SOC_JZ4730) -++static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ DECLARE_WAITQUEUE(wait, current); -++ unsigned long flags; -++ int count,con; -++ -++ if(elements_in_queue(&in_busy_queue) > 0) { -++ if (nonblock) -++ return -EBUSY; -++ drain_flag = 1; -++ sleep_on(&drain_wait_queue); -++ drain_flag = 0; -++ } else { -++ add_wait_queue(&ctrl->adc_wait, &wait); -++ for (con = 0; con < 1000; con ++) { -++ udelay(1); -++ set_current_state(TASK_INTERRUPTIBLE); -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma2); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if (count <= 0) -++ break; -++ if (nonblock) { -++ remove_wait_queue(&ctrl->adc_wait, &wait); -++ current->state = TASK_RUNNING; -++ return -EBUSY; -++ } -++ } -++ remove_wait_queue(&ctrl->adc_wait, &wait); -++ current->state = TASK_RUNNING; -++ } -++ return 0; -++} -++ -++static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ DECLARE_WAITQUEUE(wait, current); -++ unsigned long flags; -++ int count; -++ -++ if(elements_in_queue(&out_full_queue) > 0) { -++ if (nonblock) -++ return -EBUSY; -++ -++ drain_flag = 1; -++ sleep_on(&drain_wait_queue); -++ drain_flag = 0; -++ } else { -++ add_wait_queue(&(ctrl->dac_wait), &wait); -++ for (;;) { -++ set_current_state(TASK_INTERRUPTIBLE); -++ if(elements_in_queue(&out_full_queue) <= 0) { -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if(count <= 0) -++ break; -++ } -++ if (nonblock) { -++ remove_wait_queue(&ctrl->dac_wait, &wait); -++ current->state = TASK_RUNNING; -++ return -EBUSY; -++ } -++ } -++ remove_wait_queue(&ctrl->dac_wait, &wait); -++ current->state = TASK_RUNNING; -++ } -++ -++ return 0; -++} -++#endif -++ -++#if defined(CONFIG_SOC_JZ4740) -++#define MAXDELAY 50000 -++static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ int count,ele,i=0; -++ int tfl; -++ -++ for (;;) { -++ if(!nonblock) {//blocked -++ if ( i < MAXDELAY ) { -++ udelay(10); -++ i++; -++ } else -++ break; -++ -++ ele = elements_in_queue(&out_full_queue); -++ if(ele <= 0) { -++ udelay(10); -++ spin_lock(&ctrl->lock); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock(&ctrl->lock); -++ if (count <= 0) -++ break; -++ } -++ } else {//non-blocked -++ mdelay(100); -++ ele = elements_in_queue(&out_full_queue); -++ -++ if(ele <= 0) { -++ mdelay(100); -++ -++ spin_lock(&ctrl->lock); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock(&ctrl->lock); -++ if (count <= 0) -++ break; -++ } -++ } -++ } -++ -++ /* wait for TX fifo */ -++ while (1) { -++ tfl = __aic_get_transmit_resident(); -++ if (tfl == 0) -++ break; -++ udelay(2); -++ } -++ -++ return 0; -++} -++ -++static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ int count,i=0; -++ -++ for (;;) { -++ if ( i < MAXDELAY ) -++ { -++ udelay(10); -++ i++; -++ } -++ else -++ break; -++ spin_lock(&ctrl->lock); -++ count = get_dma_residue(ctrl->dma2); -++ spin_unlock(&ctrl->lock); -++ if (count <= 0) -++ break; -++ -++ if (nonblock) { -++ return -EBUSY; -++ } -++ } -++ -++ return 0; -++} -++#endif -++ -++#if defined(CONFIG_SOC_JZ4750) -++#define MAXDELAY 50000 -++static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ //DECLARE_WAITQUEUE(wait, current); -++ unsigned long flags; -++ int count,i=0; -++ -++ //add_wait_queue(&ctrl->adc_wait, &wait); -++ for (;;) { -++ if (i < MAXDELAY) { -++ udelay(10); -++ i++; -++ } else -++ break; -++ //set_current_state(TASK_INTERRUPTIBLE); -++ spin_lock_irqsave(&ctrl->lock, flags); -++ //spin_lock(&ctrl->lock); -++ count = get_dma_residue(ctrl->dma2); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ //spin_unlock(&ctrl->lock); -++ if (count <= 0) -++ break; -++ -++ /*if (signal_pending(current)) -++ break;*/ -++ if (nonblock) { -++ //remove_wait_queue(&ctrl->adc_wait, &wait); -++ //current->state = TASK_RUNNING; -++ return -EBUSY; -++ } -++ } -++ //remove_wait_queue(&ctrl->adc_wait, &wait); -++ //current->state = TASK_RUNNING; -++ /*if (signal_pending(current)) -++ return -ERESTARTSYS;*/ -++ return 0; -++} -++static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ unsigned long flags; -++ int count,ele,busyele,emptyele,i=0; -++ -++ for (;;) { -++ if(!nonblock) {//blocked -++ if (i < MAXDELAY) { -++ udelay(10); -++ i++; -++ } else -++ break; -++ -++ ele = elements_in_queue(&out_full_queue); -++ if(ele <= 0) { -++ udelay(200); -++ -++ busyele = elements_in_queue(&out_busy_queue); -++ emptyele = elements_in_queue(&out_empty_queue); -++ if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if (count <= 0) -++ break; -++ } -++ } -++ } else {//non-blocked -++ //mdelay(100); -++ ele = elements_in_queue(&out_full_queue); -++ -++ if(ele <= 0) { -++ //mdelay(100); -++ busyele = elements_in_queue(&out_busy_queue); -++ emptyele = elements_in_queue(&out_empty_queue); -++ -++ if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if (count <= 0) -++ break; -++ } -++ } -++ } -++ } -++ -++ return 0; -++} -++#endif -++ -++static int jz_audio_release(struct inode *inode, struct file *file) -++{ -++ unsigned long flags; -++#if defined(CONFIG_I2S_DLV) -++ unsigned long tfl; -++#endif -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++#if defined(CONFIG_I2S_DLV) -++ jz_codec_config = 0; -++#endif -++ if (controller == NULL) -++ return -ENODEV; -++ -++ pop_dma_flag = 0; -++ -++ if (controller->opened1 == 1 && controller->opened2 == 1) { -++ controller->opened1 = 0; -++ __i2s_enable_transmit_dma(); -++ __i2s_enable_replay(); -++ drain_dac(controller, file->f_flags & O_NONBLOCK); -++#if defined(CONFIG_I2S_DLV) -++ /* wait for fifo empty */ -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ gain_down_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //gain_down_end = jiffies; -++ /*while (1) { -++ tfl = REG_AIC_SR & 0x00003f00; -++ if (tfl == 0) { -++ udelay(500); -++ break; -++ } -++ mdelay(2); -++ }*/ -++ mdelay(100); -++#endif -++ disable_dma(controller->dma1); -++ set_dma_count(controller->dma1, 0); -++ __i2s_disable_transmit_dma(); -++ __i2s_disable_replay(); -++ -++#if defined(CONFIG_I2S_ICODEC) -++ if(clear_codec_replay) -++ clear_codec_replay(); -++#endif -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->blocks = 0; -++ controller->nextOut = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ controller->opened2 = 0; -++ first_record_call = 1; -++ __i2s_enable_receive_dma(); -++ __i2s_enable_record(); -++ drain_adc(controller, file->f_flags & O_NONBLOCK); -++ disable_dma(controller->dma2); -++ set_dma_count(controller->dma2, 0); -++ __i2s_disable_receive_dma(); -++ __i2s_disable_record(); -++#if defined(CONFIG_I2S_ICODEC) -++ if(clear_codec_record) -++ clear_codec_record(); -++#endif -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextIn = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ ramp_down_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //ramp_down_end = jiffies; -++ if (use_mic_line_flag == USE_LINEIN) { -++ unset_record_line_input_audio_with_audio_data_replay(); -++ //printk("3 use_mic_line_flag=%d\n",use_mic_line_flag); -++ } -++ if (use_mic_line_flag == USE_MIC) { -++ unset_record_mic_input_audio_with_audio_data_replay(); -++ //printk("4 use_mic_line_flag=%d\n",use_mic_line_flag); -++ } -++ -++#if 0 -++ unset_record_playing_audio_mixed_with_mic_input_audio(); -++#endif -++#endif -++ __i2s_disable(); -++ if(turn_off_codec) -++ turn_off_codec(); -++ abnormal_data_count = 0; -++ } else if (controller->opened1 == 1) { -++ //controller->opened1 = 0; -++ __i2s_enable_transmit_dma(); -++ __i2s_enable_replay(); -++ drain_dac(controller, file->f_flags & O_NONBLOCK); -++ /* add some mute to anti-pop */ -++#if defined(CONFIG_I2S_ICODEC) -++ //write_mute_to_dma_buffer(save_last_samples[last_dma_buffer_id].left,save_last_samples[last_dma_buffer_id].right); -++#endif -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ gain_down_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //gain_down_end = jiffies; -++ while (1) { -++ tfl = REG_AIC_SR & 0x00003f00; -++ if (tfl == 0) { -++ udelay(500); -++ break; -++ } -++ mdelay(2); -++ } -++#endif -++ disable_dma(controller->dma1); -++ set_dma_count(controller->dma1, 0); -++ __i2s_disable_transmit_dma(); -++ __i2s_disable_replay(); -++#if defined(CONFIG_I2S_ICODEC) -++ if(clear_codec_replay) -++ clear_codec_replay(); -++#endif -++ __aic_flush_fifo(); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->blocks = 0; -++ controller->nextOut = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ ramp_down_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //ramp_down_end = jiffies; -++ unset_audio_data_replay(); -++#endif -++ __i2s_disable(); -++#if defined(CONFIG_I2S_ICODEC) -++ if(turn_off_codec) -++ turn_off_codec(); -++#endif -++ } else if (controller->opened2 == 1) { -++ controller->opened2 = 0; -++ first_record_call = 1; -++ __i2s_enable_receive_dma(); -++ __i2s_enable_record(); -++ drain_adc(controller, file->f_flags & O_NONBLOCK); -++ disable_dma(controller->dma2); -++ set_dma_count(controller->dma2, 0); -++ __i2s_disable_receive_dma(); -++ __i2s_disable_record(); -++#if defined(CONFIG_I2S_ICODEC) -++ if(clear_codec_record) -++ clear_codec_record(); -++#endif -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextIn = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++#if defined(CONFIG_I2S_DLV) -++#if 0 -++ /* unset Record MIC input audio with direct playback */ -++ unset_record_mic_input_audio_with_direct_playback(); -++#endif -++#if 1 -++ /* unset Record MIC input audio without playback */ -++ unset_record_mic_input_audio_without_playback(); -++#endif -++#if 0 -++ /* tested */ -++ /* unset Record LINE input audio without playback */ -++ unset_record_line_input_audio_without_playback(); -++#endif -++#endif -++ __i2s_disable(); -++#if defined(CONFIG_I2S_ICODEC) -++ if(turn_off_codec) -++ turn_off_codec(); -++#endif -++ abnormal_data_count = 0; -++ } -++ -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++/* __cpm_stop_idct(); -++ __cpm_stop_db(); -++ __cpm_stop_me(); -++ __cpm_stop_mc(); -++ __cpm_stop_ipu();*/ -++#endif -++ -++ if (controller->opened1 == 1 && controller->opened2 == 1) { -++ controller->opened1 = 0; -++ controller->opened2 = 0; -++ //print_pop_duration(); -++ //__dmac_disable_module(0); -++ } else if ( controller->opened1 == 1 ) { -++ controller->opened1 = 0; -++ //print_pop_duration(); -++ } else if ( controller->opened2 == 1 ) { -++ controller->opened2 = 0; -++ } -++ -++ return 0; -++} -++ -++static int jz_audio_open(struct inode *inode, struct file *file) -++{ -++ int i; -++ struct jz_i2s_controller_info *controller = i2s_controller; -++#if defined(CONFIG_I2S_DLV) -++ jz_codec_config = 0; -++#endif -++ if (controller == NULL) -++ return -ENODEV; -++ -++ mdelay(2); -++#if defined(CONFIG_I2S_DLV) -++ REG_DMAC_DMACKE(0) = 0x3f; -++#endif -++ pop_dma_flag = 0; -++ if (controller->opened1 == 1 || controller->opened2 == 1 ) { -++ printk("\naudio is busy!\n"); -++ return -EBUSY; -++ } -++ -++ if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { -++ if (controller->opened1 == 1) -++ return -EBUSY; -++ controller->opened1 = 1; -++ /* for ioctl */ -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextOut = 0; -++ -++ for(i=0;i < 64;i++) { -++ save_last_samples[i].left = 0; -++ save_last_samples[i].right = 0; -++ } -++ -++ out_empty_queue.count = jz_audio_fragstotal; -++ for (i=0;i < jz_audio_fragstotal;i++) -++ *(out_empty_queue.id + i) = i; -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ last_dma_buffer_id = 0; -++ -++ if (controller->opened2 == 1) -++ return -EBUSY; -++ -++ controller->opened2 = 1; -++ first_record_call = 1; -++ /* for ioctl */ -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextIn = 0; -++ -++ in_empty_queue.count = jz_audio_fragstotal; -++ for (i=0;i < jz_audio_fragstotal;i++) -++ *(in_empty_queue.id + i) = i; -++ -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ } else if (file->f_mode & FMODE_WRITE) { -++ if (controller->opened1 == 1) -++ return -EBUSY; -++ -++ controller->opened1 = 1; -++ /* for ioctl */ -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextOut = 0; -++ -++ for(i=0;i < 64;i++) { -++ save_last_samples[i].left = 0; -++ save_last_samples[i].right = 0; -++ } -++ -++ out_empty_queue.count = jz_audio_fragstotal; -++ for (i=0;i < jz_audio_fragstotal;i++) -++ *(out_empty_queue.id + i) = i; -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ last_dma_buffer_id = 0; -++ } else if (file->f_mode & FMODE_READ) { -++ if (controller->opened2 == 1) -++ return -EBUSY; -++ -++ controller->opened2 = 1; -++ first_record_call = 1; -++ /* for ioctl */ -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextIn = 0; -++ -++ in_empty_queue.count = jz_audio_fragstotal; -++ for (i=0;i < jz_audio_fragstotal;i++) -++ *(in_empty_queue.id + i) = i; -++ -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ } -++ -++ file->private_data = controller; -++ jz_audio_reset(); -++ REG_AIC_FR |= (1 << 6); -++ if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { -++#if defined(CONFIG_I2S_ICODEC) -++ if (set_codec_replay_record) -++ set_codec_replay_record(use_mic_line_flag); -++#endif -++#if defined(CONFIG_I2S_DLV) -++ if (use_mic_line_flag == USE_NONE) { -++ printk("you select mic or line recording please.or use mic recording!\n"); -++ use_mic_line_flag = USE_MIC; -++ } -++ if (use_mic_line_flag == USE_LINEIN) { -++ /* Record LINE input audio with Audio data replay (full duplex for linein) */ -++ /* codec_test_line */ -++ set_record_line_input_audio_with_audio_data_replay(); -++ -++ } -++ if (use_mic_line_flag == USE_MIC) { -++ /* Record MIC input audio with Audio data replay (full duplex) */ -++ /* codec_test_mic */ -++ set_record_mic_input_audio_with_audio_data_replay(); -++ } -++#if 0 -++ /* Record playing audio mixed with MIC input audio */ -++ set_record_playing_audio_mixed_with_mic_input_audio(); -++#endif -++ -++#endif -++ } else if (file->f_mode & FMODE_WRITE) { -++#if defined(CONFIG_I2S_ICODEC) -++ if(set_codec_replay) -++ set_codec_replay(); -++#endif -++#if defined(CONFIG_I2S_DLV) -++ //mdelay(10); -++ /* Audio data replay */ -++ set_audio_data_replay(); -++#endif -++ } else if (file->f_mode & FMODE_READ) { -++#if defined(CONFIG_I2S_ICODEC) -++ abnormal_data_count = 0; -++ if(set_codec_record) -++ set_codec_record(use_mic_line_flag); -++#endif -++#if defined(CONFIG_I2S_DLV) -++#if 0 -++ /* Record MIC input audio with direct playback */ -++ set_record_mic_input_audio_with_direct_playback(); -++#endif -++ -++#if 1 -++ /* set Record MIC input audio without playback */ -++ set_record_mic_input_audio_without_playback(); -++#endif -++#if 0 -++ /* tested */ -++ /* set Record LINE input audio without playback */ -++ set_record_line_input_audio_without_playback(); -++#endif -++ mdelay(1); -++#endif -++ } -++ -++#if defined(CONFIG_I2S_DLV) -++ __aic_reset(); -++ -++ mdelay(10); -++ REG_AIC_I2SCR = 0x10; -++ mdelay(20); -++ __aic_flush_fifo(); -++#endif -++ -++ __i2s_enable(); -++ -++#if defined(CONFIG_I2S_DLV) -++ ndelay(100); -++ -++ if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { -++#if defined(CONFIG_I2S_DLV) -++ //set SB_ADC or SB_DAC -++ __dmac_enable_module(0); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ ramp_up_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //ramp_up_end = jiffies; -++#endif -++ } else if (file->f_mode & FMODE_WRITE) { -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ ramp_up_start = jiffies; -++ /*while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_RCR = 0x1; -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_RGR = 1;*/ -++ sleep_on(&pop_wait_queue); -++ //ramp_up_end = jiffies; -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++#endif -++ } else if (file->f_mode & FMODE_READ) { -++#if defined(CONFIG_I2S_DLV) -++ if (jz_mic_only) -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ else -++ write_codec_file_bit(5, 0, 7);//SB_DAC->0 -++ mdelay(500); -++#endif -++ } -++#endif -++ return 0; -++} -++ -++ -++static int jz_audio_ioctl(struct inode *inode, struct file *file, -++unsigned int cmd, unsigned long arg) -++{ -++ int val,fullc,busyc,unfinish,newfragstotal,newfragsize; -++ unsigned int flags; -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ count_info cinfo; -++ audio_buf_info abinfo; -++ int id, i; -++ -++ val = 0; -++ switch (cmd) { -++ case OSS_GETVERSION: -++ return put_user(SOUND_VERSION, (int *)arg); -++ case SNDCTL_DSP_RESET: -++#if 0 -++ jz_audio_reset(); -++ __i2s_disable_replay(); -++ __i2s_disable_receive_dma(); -++ __i2s_disable_record(); -++ __i2s_disable_transmit_dma(); -++#endif -++ return 0; -++ case SNDCTL_DSP_SYNC: -++ if (file->f_mode & FMODE_WRITE) -++ return drain_dac(controller, file->f_flags & O_NONBLOCK); -++ return 0; -++ case SNDCTL_DSP_SPEED: -++ /* set smaple rate */ -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ if (val >= 0) -++ jz_audio_set_speed(controller->dev_audio, val); -++ -++ return put_user(val, (int *)arg); -++ case SNDCTL_DSP_STEREO: -++ /* set stereo or mono channel */ -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ jz_audio_set_channels(controller->dev_audio, val ? 2 : 1); -++ -++ return 0; -++ case SNDCTL_DSP_GETBLKSIZE: -++ //return put_user(jz_audio_fragsize / jz_audio_b, (int *)arg); -++ return put_user(jz_audio_fragsize, (int *)arg); -++ case SNDCTL_DSP_GETFMTS: -++ /* Returns a mask of supported sample format*/ -++ return put_user(AFMT_U8 | AFMT_S16_LE, (int *)arg); -++ case SNDCTL_DSP_SETFMT: -++ /* Select sample format */ -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ if (val != AFMT_QUERY) -++ jz_audio_set_format(controller->dev_audio,val); -++ else { -++ if (file->f_mode & FMODE_READ) -++ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -++ else -++ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -++ } -++ -++ return put_user(val, (int *)arg); -++ case SNDCTL_DSP_CHANNELS: -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ jz_audio_set_channels(controller->dev_audio, val); -++ -++ return put_user(val, (int *)arg); -++ case SNDCTL_DSP_POST: -++ /* FIXME: the same as RESET ?? */ -++ return 0; -++ case SNDCTL_DSP_SUBDIVIDE: -++ return 0; -++ case SNDCTL_DSP_SETFRAGMENT: -++ get_user(val, (long *) arg); -++ newfragsize = 1 << (val & 0xFFFF); -++ if (newfragsize < 4 * PAGE_SIZE) -++ newfragsize = 4 * PAGE_SIZE; -++ if (newfragsize > (16 * PAGE_SIZE)) -++ newfragsize = 16 * PAGE_SIZE; -++ -++ newfragstotal = (val >> 16) & 0x7FFF; -++ if (newfragstotal < 2) -++ newfragstotal = 2; -++ if (newfragstotal > 32) -++ newfragstotal = 32; -++ if((jz_audio_fragstotal == newfragstotal) && (jz_audio_fragsize == newfragsize)) -++ return 0; -++ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ mdelay(500); -++ jz_audio_fragstotal = newfragstotal; -++ jz_audio_fragsize = newfragsize; -++ -++ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ mdelay(10); -++ -++ return 0; -++ case SNDCTL_DSP_GETCAPS: -++ return put_user(DSP_CAP_REALTIME|DSP_CAP_BATCH, (int *)arg); -++ case SNDCTL_DSP_NONBLOCK: -++ file->f_flags |= O_NONBLOCK; -++ return 0; -++ case SNDCTL_DSP_SETDUPLEX: -++ return -EINVAL; -++ case SNDCTL_DSP_GETOSPACE: -++ { -++ int i; -++ unsigned long bytes = 0; -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ jz_audio_fragments = elements_in_queue(&out_empty_queue); -++ for (i = 0; i < jz_audio_fragments; i++) -++ bytes += jz_audio_fragsize; -++ -++ if (jz_audio_channels == 2) -++ bytes /= jz_audio_b; -++ else if (jz_audio_channels == 1) -++ bytes /= 4; -++ else -++ printk("SNDCTL_DSP_GETOSPACE : channels is wrong 1!\n"); -++ -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ /* unused fragment amount */ -++ abinfo.fragments = jz_audio_fragments; -++ /* amount of fragments */ -++ abinfo.fragstotal = jz_audio_fragstotal; -++ /* fragment size in bytes */ -++ if (jz_audio_channels == 2) -++ abinfo.fragsize = jz_audio_fragsize / jz_audio_b; -++ else if (jz_audio_channels == 1) -++ abinfo.fragsize = jz_audio_fragsize / 4; -++ else -++ printk("SNDCTL_DSP_GETOSPACE : channels is wrong 2!\n"); -++ -++ /* write size count without blocking in bytes */ -++ abinfo.bytes = (int)bytes; -++ -++ return copy_to_user((void *)arg, &abinfo, -++ sizeof(abinfo)) ? -EFAULT : 0; -++ } -++ case SNDCTL_DSP_GETISPACE: -++ { -++ int i; -++ unsigned long bytes = 0; -++ if (!(file->f_mode & FMODE_READ)) -++ return -EINVAL; -++ jz_audio_fragments = elements_in_queue(&in_empty_queue); -++ for (i = 0; i < jz_audio_fragments; i++) -++ bytes += jz_audio_fragsize; -++ -++ if (jz_audio_channels == 2) -++ bytes /= jz_audio_b; -++ else if (jz_audio_channels == 1) -++ bytes /= 4; -++ else -++ printk("SNDCTL_DSP_GETISPACE : channels is wrong 1!\n"); -++ -++ abinfo.fragments = jz_audio_fragments; -++ abinfo.fragstotal = jz_audio_fragstotal; -++ -++ if (jz_audio_channels == 2) -++ abinfo.fragsize = jz_audio_fragsize / jz_audio_b; -++ else if (jz_audio_channels == 1) -++ abinfo.fragsize = jz_audio_fragsize / 4; -++ else -++ printk("SNDCTL_DSP_GETISPACE : channels is wrong 2!\n"); -++ -++ abinfo.bytes = (int)bytes; -++ -++ return copy_to_user((void *)arg, &abinfo, -++ sizeof(abinfo)) ? -EFAULT : 0; -++ } -++ case SNDCTL_DSP_GETTRIGGER: -++ val = 0; -++ if (file->f_mode & FMODE_READ && in_dma_buf) -++ val |= PCM_ENABLE_INPUT; -++ if (file->f_mode & FMODE_WRITE && out_dma_buf) -++ val |= PCM_ENABLE_OUTPUT; -++ -++ return put_user(val, (int *)arg); -++ case SNDCTL_DSP_SETTRIGGER: -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ return 0; -++ case SNDCTL_DSP_GETIPTR: -++ if (!(file->f_mode & FMODE_READ)) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ cinfo.bytes = controller->total_bytes; -++ cinfo.blocks = controller->blocks; -++ cinfo.ptr = controller->nextIn; -++ controller->blocks = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); -++ case SNDCTL_DSP_GETOPTR: -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ cinfo.bytes = controller->total_bytes; -++ cinfo.blocks = controller->blocks; -++ cinfo.ptr = controller->nextOut; -++ controller->blocks = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); -++ case SNDCTL_DSP_GETODELAY: -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ unfinish = 0; -++ fullc = elements_in_queue(&out_full_queue); -++ busyc = elements_in_queue(&out_busy_queue); -++ for(i = 0;i < fullc ;i ++) { -++ id = *(out_full_queue.id + i); -++ unfinish += *(out_dma_buf_data_count + id); -++ } -++ for(i = 0;i < busyc ;i ++) { -++ id = *(out_busy_queue.id + i); -++ unfinish += get_dma_residue(controller->dma1); -++ } -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ if (jz_audio_channels == 2) -++ unfinish /= jz_audio_b; -++ else if (jz_audio_channels == 1) -++ unfinish /= 4; -++ else -++ printk("SNDCTL_DSP_GETODELAY : channels is wrong !\n"); -++ -++ return put_user(unfinish, (int *) arg); -++ case SOUND_PCM_READ_RATE: -++ return put_user(jz_audio_rate, (int *)arg); -++ case SOUND_PCM_READ_CHANNELS: -++ return put_user(jz_audio_channels, (int *)arg); -++ case SOUND_PCM_READ_BITS: -++ return put_user((jz_audio_format & (AFMT_S8 | AFMT_U8)) ? 8 : 16, (int *)arg); -++ case SNDCTL_DSP_MAPINBUF: -++ case SNDCTL_DSP_MAPOUTBUF: -++ case SNDCTL_DSP_SETSYNCRO: -++ case SOUND_PCM_WRITE_FILTER: -++ case SOUND_PCM_READ_FILTER: -++ return -EINVAL; -++ } -++ return -EINVAL; -++} -++ -++ -++static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait) -++{ -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ unsigned long flags; -++ unsigned int mask = 0; -++ -++ if (file->f_mode & FMODE_WRITE) { -++ if (elements_in_queue(&out_empty_queue) > 0) -++ return POLLOUT | POLLWRNORM; -++ -++ poll_wait(file, &controller->dac_wait, wait); -++ } -++ -++ if (file->f_mode & FMODE_READ) { -++ if (elements_in_queue(&in_full_queue) > 0) -++ return POLLIN | POLLRDNORM; -++ -++ poll_wait(file, &controller->adc_wait, wait); -++ } -++ -++ spin_lock_irqsave(&controller->lock, flags); -++ if (file->f_mode & FMODE_WRITE) { -++ if (elements_in_queue(&out_empty_queue) > 0) -++ mask |= POLLOUT | POLLWRNORM; -++ } else if (file->f_mode & FMODE_READ) { -++ if (elements_in_queue(&in_full_queue) > 0) -++ mask |= POLLIN | POLLRDNORM; -++ } -++ spin_unlock_irqrestore(&controller->lock, flags); -++ -++ return mask; -++} -++ -++static ssize_t jz_audio_read(struct file *file, char *buffer, size_t count, loff_t *ppos) -++{ -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ int id, ret = 0, left_count, copy_count, cnt = 0; -++ unsigned long flags; -++ -++ if (count < 0) -++ return -EINVAL; -++ -++ __i2s_enable_receive_dma(); -++ __i2s_enable_record(); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextIn = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ copy_count = jz_audio_fragsize / 4; -++ -++ left_count = count; -++ if (first_record_call) { -++ first_record_call = 0; -++ audio_read_back_first: -++ if ((id = get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id); -++ spin_lock(&controller->lock); -++ *(in_dma_buf_data_count + id) = copy_count * 4; -++ -++ spin_unlock(&controller->lock); -++ __i2s_enable_receive_dma(); -++ __i2s_enable_record(); -++ dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); -++ audio_start_dma(controller->dma2,file->private_data, -++ *(in_dma_pbuf + id), -++ *(in_dma_buf_data_count + id), -++ DMA_MODE_READ); -++ sleep_on(&rx_wait_queue); -++ } else -++ goto audio_read_back_first; -++ } -++ -++ while (left_count > 0) { -++ audio_read_back_second: -++ if (elements_in_queue(&in_full_queue) <= 0) { -++ if (file->f_flags & O_NONBLOCK) -++ return ret ? ret : -EAGAIN; -++ else -++ sleep_on(&rx_wait_queue); -++ } -++ -++ if ((id = get_buffer_id(&in_full_queue)) >= 0) { -++ spin_lock(&controller->lock); -++ cnt = record_filler((unsigned long)controller->tmp2+ret, copy_count, id); -++ spin_unlock(&controller->lock); -++ put_buffer_id(&in_empty_queue, id); -++ } else -++ goto audio_read_back_second; -++ -++ if (elements_in_queue(&in_busy_queue) == 0) { -++ if ((id=get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id); -++ spin_lock(&controller->lock); -++ *(in_dma_buf_data_count + id) = copy_count * 4; -++ spin_unlock(&controller->lock); -++ -++ dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); -++ audio_start_dma(controller->dma2,file->private_data, -++ *(in_dma_pbuf + id), -++ *(in_dma_buf_data_count + id), -++ DMA_MODE_READ); -++ } -++ } -++ if (ret + cnt > count) { -++ spin_lock(&controller->lock); -++ cnt = count - ret; -++ spin_unlock(&controller->lock); -++ } -++ if (copy_to_user(buffer+ret, controller->tmp2+ret, cnt)) -++ return ret ? ret : -EFAULT; -++ -++ spin_lock(&controller->lock); -++ ret += cnt; -++ spin_unlock(&controller->lock); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextIn += ret; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ spin_lock(&controller->lock); -++ left_count -= cnt; -++ spin_unlock(&controller->lock); -++ } -++ return ret; -++} -++ -++static ssize_t jz_audio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) -++{ -++ int id, ret = 0, left_count, copy_count = 0; -++ unsigned int flags; -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ -++ if (count <= 0) -++ return -EINVAL; -++ -++ if(set_replay_hp_or_speaker) -++ set_replay_hp_or_speaker(); -++ -++ __i2s_enable_transmit_dma(); -++ __i2s_enable_replay(); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextOut = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ if (jz_audio_channels == 2) -++ copy_count = jz_audio_fragsize / jz_audio_b; -++ else if(jz_audio_channels == 1) -++ copy_count = jz_audio_fragsize / 4; -++ left_count = count; -++ if (copy_from_user(controller->tmp1, buffer, count)) { -++ printk("copy_from_user failed:%d",ret); -++ return ret ? ret : -EFAULT; -++ } -++ -++ while (left_count > 0) { -++ audio_write_back: -++ if (file->f_flags & O_NONBLOCK) -++ udelay(2); -++ if (elements_in_queue(&out_empty_queue) == 0) { -++ if (file->f_flags & O_NONBLOCK) -++ return ret; -++ else -++ sleep_on(&tx_wait_queue); -++ } -++ /* the end fragment size in this write */ -++ if (ret + copy_count > count) -++ copy_count = count - ret; -++ if ((id = get_buffer_id(&out_empty_queue)) >= 0) { -++ replay_filler((signed long)controller->tmp1 + ret, copy_count, id); -++ if(*(out_dma_buf_data_count + id) > 0) { -++ put_buffer_id(&out_full_queue, id); -++ dma_cache_wback_inv(*(out_dma_buf + id), *(out_dma_buf_data_count + id)); -++ } else -++ put_buffer_id(&out_empty_queue, id); -++ } else -++ goto audio_write_back; -++ -++ left_count = left_count - copy_count; -++ ret += copy_count; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextOut += ret; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ if (elements_in_queue(&out_busy_queue) == 0) { -++ if ((id=get_buffer_id(&out_full_queue)) >= 0) { -++ put_buffer_id(&out_busy_queue, id); -++ if(*(out_dma_buf_data_count + id) > 0) { -++ audio_start_dma(controller->dma1, -++ file->private_data, -++ *(out_dma_pbuf + id), -++ *(out_dma_buf_data_count + id), -++ DMA_MODE_WRITE); -++ last_dma_buffer_id = id; -++#if defined(CONFIG_I2S_DLV) -++ if (jz_codec_config == 0) { -++ write_codec_file_bit(1, 0, 5); -++ gain_up_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //gain_up_end = jiffies; -++ jz_codec_config = 1; -++ //SB_ADC->1 -++ //write_codec_file_bit(5, 1, 4); -++ //while(1); -++ } -++#endif -++ } -++ } -++ } -++ } -++ -++ return ret; -++} -++ -++#if defined(CONFIG_I2S_ICODEC) -++static void write_mute_to_dma_buffer(signed long l_sample, signed long r_sample) -++{ -++ int i,step_len; -++ unsigned long *pop_buf = (unsigned long*)pop_turn_onoff_buf; -++ unsigned int sample_oss = (REG_AIC_CR & 0x00380000) >> 19; -++ unsigned long l_sample_count,r_sample_count,sample_count; -++ struct jz_i2s_controller_info *controller = i2s_controller; -++ signed int left_sam=0,right_sam=0,l_val,r_val; -++ -++ switch (sample_oss) { -++ case 0x0: -++ break; -++ case 0x1: -++ left_sam = (signed int)l_sample; -++ right_sam = (signed int)r_sample; -++ break; -++ case 0x2: -++ break; -++ case 0x3: -++ break; -++ case 0x4: -++ break; -++ } -++ -++ if(left_sam == 0 && right_sam == 0) -++ return; -++ -++ switch (sample_oss) { -++ case 0x0: -++ break; -++ case 0x1: -++ step_len = jz_audio_speed / 10 * 3; -++ step_len = step_len / 2; -++ step_len = 0x7fff / step_len + 1; -++ -++ l_sample_count = 0; -++ l_val = left_sam; -++ -++ while(1) { -++ if(l_val > 0) { -++ if(l_val >= step_len) { -++ l_val -= step_len; -++ l_sample_count ++; -++ } else -++ break; -++ } -++ -++ if(l_val < 0) { -++ if(l_val <= -step_len) { -++ l_val += step_len; -++ l_sample_count ++; -++ } else -++ break; -++ } -++ -++ if(l_val == 0) -++ break; -++ } -++ -++ r_sample_count = 0; -++ r_val = right_sam; -++ while(1) { -++ if(r_val > 0) { -++ if(r_val >= step_len) { -++ r_val -= step_len; -++ r_sample_count ++; -++ } else -++ break; -++ } -++ -++ if(r_val < 0) { -++ if(r_val <= -step_len) { -++ r_val += step_len; -++ r_sample_count ++; -++ } else -++ break; -++ } -++ -++ if(r_val == 0) -++ break; -++ } -++ /* fill up */ -++ if(l_sample_count > r_sample_count) -++ sample_count = l_sample_count; -++ else -++ sample_count = r_sample_count; -++ -++ l_val = left_sam; -++ r_val = right_sam; -++ for(i=0;i <= sample_count;i++) { -++ -++ *pop_buf = (unsigned long)l_val; -++ pop_buf ++; -++ -++ if(l_val > step_len) -++ l_val -= step_len; -++ else if(l_val < -step_len) -++ l_val += step_len; -++ else if(l_val >= -step_len && l_val <= step_len) -++ l_val = 0; -++ -++ *pop_buf = (unsigned long)r_val; -++ pop_buf ++; -++ if(r_val > step_len) -++ r_val -= step_len; -++ else if(r_val < -step_len) -++ r_val += step_len; -++ else if(r_val >= -step_len && r_val <= step_len) -++ r_val = 0; -++ } -++ -++ *pop_buf = 0; -++ pop_buf ++; -++ *pop_buf = 0; -++ -++ pop_buf ++; -++ sample_count += 2; -++ dma_cache_wback_inv(pop_turn_onoff_buf, sample_count*8); -++ -++ pop_dma_flag = 1; -++ audio_start_dma(controller->dma1,controller,pop_turn_onoff_pbuf,sample_count*8,DMA_MODE_WRITE); -++ sleep_on(&pop_wait_queue); -++ pop_dma_flag = 0; -++ break; -++ case 0x2: -++ break; -++ case 0x3: -++ break; -++ case 0x4: -++ break; -++ } -++} -++#endif -+diff -urN linux-2.6.24.7.old/sound/oss/jz_i2s_4750.c linux-2.6.24.7/sound/oss/jz_i2s_4750.c -+--- linux-2.6.24.7.old/sound/oss/jz_i2s_4750.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/oss/jz_i2s_4750.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,3010 @@ -++/* -++ * linux/drivers/sound/Jz_i2s.c -++ * -++ * JzSOC On-Chip I2S audio driver. -++ * -++ * Copyright (C) 2005 by Junzheng Corp. -++ * Modified by cjfeng on Aug 9,2007,and not any bug on Jz4730 using -++ * dma channel 4&3,noah is tested. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ * Because the normal application of AUDIO devices are focused on Little_endian, -++ * then we only perform the little endian data format in driver. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "sound_config.h" -++ -++#define DPRINTK(args...) printk(args) -++#define DMA_ID_I2S_TX DMA_ID_AIC_TX -++#define DMA_ID_I2S_RX DMA_ID_AIC_RX -++#define NR_I2S 2 -++#define MAXDELAY 50000 -++#define JZCODEC_RW_BUFFER_SIZE 2 -++#define JZCODEC_RW_BUFFER_TOTAL 6 -++ -++typedef struct hpvol_shift_s -++{ -++ int hpvol; -++ int shift; -++} hpvol_shift_t; -++ -++mixer_info info; -++_old_mixer_info old_info; -++int codec_volue_shift; -++hpvol_shift_t hpvol_shift_table[72]; -++int abnormal_data_count; -++unsigned long i2s_clk; -++ -++void (*set_codec_mode)(void) = NULL; -++void (*clear_codec_mode)(void) = NULL; -++void (*set_codec_gpio_pin)(void) = NULL; -++void (*each_time_init_codec)(void) = NULL; -++int (*set_codec_startup_param)(void) = NULL; -++void (*set_codec_volume_table)(void) = NULL; -++void (*set_codec_record)(void) = NULL; -++void (*set_codec_replay)(void) = NULL; -++void (*set_codec_replay_record)(void); -++void (*turn_on_codec)(void) = NULL; -++void (*turn_off_codec)(void) = NULL; -++void (*set_codec_speed)(int rate) = NULL; -++void (*reset_codec)(void) = NULL; -++void (*codec_mixer_old_info_id_name)(void) = NULL; -++void (*codec_mixer_info_id_name)(void) = NULL; -++void (*set_codec_bass)(int val) = NULL; -++void (*set_codec_volume)(int val) = NULL; -++void (*set_codec_mic)(int val) = NULL; -++void (*i2s_resume_codec)(void) = NULL; -++void (*i2s_suspend_codec)(int wr,int rd) = NULL; -++void (*init_codec_pin)(void) = NULL; -++void (*set_codec_some_func)(void) = NULL; -++void (*clear_codec_record)(void) = NULL; -++void (*clear_codec_replay)(void) = NULL; -++void (*set_replay_hp_or_speaker)(void) = NULL; -++void (*set_codec_direct_mode)(void) = NULL; -++void (*clear_codec_direct_mode)(void) = NULL; -++ -++static int jz_audio_rate; -++static int jz_audio_format; -++static int jz_audio_volume; -++static int jz_audio_channels; -++static int jz_audio_b; /* bits expand multiple */ -++static int jz_audio_fragments; /* unused fragment amount */ -++static int jz_audio_fragstotal; -++static int jz_audio_fragsize; -++static int jz_audio_speed; -++ -++static int codec_bass_gain; -++static int audio_mix_modcnt; -++static int jz_audio_dma_tran_count; /* bytes count of one DMA transfer */ -++static int jz_mic_only = 1; -++static int jz_codec_config = 0; -++static unsigned long ramp_up_start; -++static unsigned long ramp_up_end; -++static unsigned long gain_up_start; -++static unsigned long gain_up_end; -++static unsigned long ramp_down_start; -++static unsigned long ramp_down_end; -++static unsigned long gain_down_start; -++static unsigned long gain_down_end; -++ -++static int codec_mic_gain; -++static int pop_dma_flag; -++static int last_dma_buffer_id; -++static int drain_flag; -++ -++static void (*old_mksound)(unsigned int hz, unsigned int ticks); -++extern void (*kd_mksound)(unsigned int hz, unsigned int ticks); -++static void jz_update_filler(int bits, int channels); -++ -++static int Init_In_Out_queue(int fragstotal,int fragsize); -++static int Free_In_Out_queue(int fragstotal,int fragsize); -++static irqreturn_t jz_i2s_replay_dma_irq(int irqnr, void *ref); -++static irqreturn_t jz_i2s_record_dma_irq(int irqnr, void *ref); -++static void (*replay_filler)(signed long src_start, int count, int id); -++static int (*record_filler)(unsigned long dst_start, int count, int id); -++#if defined(CONFIG_I2S_ICODEC) -++static void write_mute_to_dma_buffer(signed long l_sample, signed long r_sample); -++#endif -++static void jz_audio_reset(void); -++static struct file_operations jz_i2s_audio_fops; -++ -++static DECLARE_WAIT_QUEUE_HEAD (rx_wait_queue); -++static DECLARE_WAIT_QUEUE_HEAD (tx_wait_queue); -++static DECLARE_WAIT_QUEUE_HEAD (drain_wait_queue); -++static DECLARE_WAIT_QUEUE_HEAD (pop_wait_queue); -++ -++struct jz_i2s_controller_info -++{ -++ int io_base; -++ int dma1; /* for play */ -++ int dma2; /* for record */ -++ char *name; -++ int dev_audio; -++ struct i2s_codec *i2s_codec[NR_I2S]; -++ int opened1; -++ int opened2; -++ unsigned char *tmp1; /* tmp buffer for sample conversions */ -++ unsigned char *tmp2; -++ spinlock_t lock; -++ spinlock_t ioctllock; -++ -++ wait_queue_head_t dac_wait; -++ wait_queue_head_t adc_wait; -++ int nextIn; /* byte index to next-in to DMA buffer */ -++ int nextOut; /* byte index to next-out from DMA buffer */ -++ int count; /* current byte count in DMA buffer */ -++ int finish; /* current transfered byte count in DMA buffer */ -++ unsigned total_bytes; /* total bytes written or read */ -++ unsigned blocks; -++ unsigned error; /* over/underrun */ -++#ifdef CONFIG_PM -++ struct pm_dev *pm; -++#endif -++}; -++ -++ -++static struct jz_i2s_controller_info *i2s_controller = NULL; -++struct i2s_codec -++{ -++ /* I2S controller connected with */ -++ void *private_data; -++ char *name; -++ int id; -++ int dev_mixer; -++ /* controller specific lower leverl i2s accessing routines */ -++ u16 (*codec_read) (u8 reg); /* the function accessing Codec REGs */ -++ void (*codec_write) (u8 reg, u16 val); -++ /* Wait for codec-ready */ -++ void (*codec_wait) (struct i2s_codec *codec); -++ /* OSS mixer masks */ -++ int modcnt; -++ int supported_mixers; -++ int stereo_mixers; -++ int record_sources; -++ int bit_resolution; -++ /* OSS mixer interface */ -++ int (*read_mixer) (struct i2s_codec *codec, int oss_channel); -++ void (*write_mixer)(struct i2s_codec *codec, int oss_channel, -++ unsigned int left, unsigned int right); -++ int (*recmask_io) (struct i2s_codec *codec, int rw, int mask); -++ int (*mixer_ioctl)(struct i2s_codec *codec, unsigned int cmd, unsigned long arg); -++ /* saved OSS mixer states */ -++ unsigned int mixer_state[SOUND_MIXER_NRDEVICES]; -++}; -++ -++ -++typedef struct buffer_queue_s -++{ -++ int count; -++ int *id; -++ int lock; -++} buffer_queue_t; -++ -++typedef struct left_right_sample_s -++{ -++ signed long left; -++ signed long right; -++} left_right_sample_t; -++ -++static unsigned long pop_turn_onoff_buf; -++static unsigned long pop_turn_onoff_pbuf; -++ -++static unsigned long *out_dma_buf = NULL; -++static unsigned long *out_dma_pbuf = NULL; -++static unsigned long *out_dma_buf_data_count = NULL; -++static unsigned long *in_dma_buf = NULL; -++static unsigned long *in_dma_pbuf = NULL; -++static unsigned long *in_dma_buf_data_count = NULL; -++ -++static buffer_queue_t out_empty_queue; -++static buffer_queue_t out_full_queue; -++static buffer_queue_t out_busy_queue; -++static buffer_queue_t in_empty_queue; -++static buffer_queue_t in_full_queue; -++static buffer_queue_t in_busy_queue; -++static int first_record_call = 0; -++ -++static left_right_sample_t save_last_samples[64]; -++static int read_codec_file(int addr) -++{ -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ mdelay(1); -++ return(__icdc_get_value()); -++} -++ -++#if 0 /* mask warning */ -++static void printk_codec_files(void) -++{ -++ int cnt; -++ -++ printk("\n"); -++ -++ printk("REG_CPM_I2SCDR=0x%08x\n",REG_CPM_I2SCDR); -++ printk("REG_CPM_CLKGR=0x%08x\n",REG_CPM_CLKGR); -++ printk("REG_CPM_CPCCR=0x%08x\n",REG_CPM_CPCCR); -++ printk("REG_AIC_FR=0x%08x\n",REG_AIC_FR); -++ printk("REG_AIC_CR=0x%08x\n",REG_AIC_CR); -++ printk("REG_AIC_I2SCR=0x%08x\n",REG_AIC_I2SCR); -++ printk("REG_AIC_SR=0x%08x\n",REG_AIC_SR); -++ printk("REG_ICDC_RGDATA=0x%08x\n",REG_ICDC_RGDATA); -++ -++ for (cnt = 0; cnt <= 27 ; cnt++) { -++ printk(" ( %d : 0x%x ) ",cnt ,read_codec_file(cnt)); -++ } -++ printk("\n"); -++} -++#endif -++ -++static void write_codec_file(int addr, int val) -++{ -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ __icdc_set_cmd(val); /* write */ -++ mdelay(1); -++ __icdc_set_rgwr(); -++ mdelay(1); -++} -++ -++static int write_codec_file_bit(int addr, int bitval, int mask_bit) -++{ -++ int val; -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ mdelay(1); -++ val = __icdc_get_value(); /* read */ -++ -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ val &= ~(1 << mask_bit); -++ if (bitval == 1) -++ val |= 1 << mask_bit; -++ -++ __icdc_set_cmd(val); /* write */ -++ mdelay(1); -++ __icdc_set_rgwr(); -++ mdelay(1); -++ -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ val = __icdc_get_value(); /* read */ -++ -++ if (((val >> mask_bit) & bitval) == bitval) -++ return 1; -++ else -++ return 0; -++} -++ -++#if 0 /* mask warning */ -++/* set Audio data replay */ -++static void set_audio_data_replay(void) -++{ -++ /* DAC path */ -++ write_codec_file(9, 0xff); -++ //write_codec_file(8, 0x30); -++ write_codec_file(8, 0x20); -++ mdelay(10); -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -++ -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ //mdelay(100); -++ //write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //mdelay(300); -++} -++#endif -++ -++/* unset Audio data replay */ -++static void unset_audio_data_replay(void) -++{ -++ //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ //mdelay(800); -++ //write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ //mdelay(800); -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ write_codec_file_bit(5, 1, 4);//SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++ -++#if 0 /* mask warning */ -++/* set Record MIC input audio without playback */ -++static void set_record_mic_input_audio_without_playback(void) -++{ -++ /* ADC path for MIC IN */ -++ jz_mic_only = 1; -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ mdelay(10); -++ write_codec_file_bit(1, 1, 2); -++ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -++ -++ write_codec_file(22, 0x40);//mic 1 -++ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -++ //write_codec_file_bit(6, 1, 3);// gain set -++ -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ mdelay(100); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ write_codec_file(1, 0x4); -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* unset Record MIC input audio without playback */ -++static void unset_record_mic_input_audio_without_playback(void) -++{ -++ /* ADC path for MIC IN */ -++ jz_mic_only = 0; -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -++ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* set Record LINE input audio without playback */ -++static void set_record_line_input_audio_without_playback(void) -++{ -++ /* ADC path for LINE IN */ -++ jz_mic_only = 1; -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ mdelay(10); -++ write_codec_file(22, 0xf6);//line in 1 -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -++ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -++ mdelay(10); -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ mdelay(100); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ write_codec_file(1, 0x4); -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* unset Record LINE input audio without playback */ -++static void unset_record_line_input_audio_without_playback(void) -++{ -++ /* ADC path for LINE IN */ -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(5, 1, 3);//ONR1.SB_LIN->1 -++ -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -++ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* set Playback LINE input audio direct only */ -++static void set_playback_line_input_audio_direct_only(void) -++{ -++ jz_audio_reset();//or init_codec() -++ REG_AIC_I2SCR = 0x10; -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ mdelay(10); -++ write_codec_file(22, 0xf6);//line in 1 -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ mdelay(10); -++ write_codec_file_bit(1, 1, 2);//CR1.HP_BYPASS->1 -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -++ -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ mdelay(100); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ //write_codec_file_bit(5, 1, 7);//PMR1.SB_DAC->1 -++ //write_codec_file_bit(5, 1, 4);//PMR1.SB_ADC->1 -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* unset Playback LINE input audio direct only */ -++static void unset_playback_line_input_audio_direct_only(void) -++{ -++ write_codec_file_bit(6, 0, 3);//GIM->0 -++ write_codec_file_bit(1, 0, 2);//PMR1.BYPASS->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LINE->1 -++ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -++ mdelay(100); -++ write_codec_file_bit(5, 1, 5);//PMR1.SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* set Record MIC input audio with direct playback */ -++static void set_record_mic_input_audio_with_direct_playback(void) -++{ -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ jz_mic_only = 0; -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ mdelay(10); -++ -++ write_codec_file(22, 0x60);//mic 1 -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -++ write_codec_file_bit(6, 1, 3);// gain set -++ -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ mdelay(100); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ //write_codec_file(1, 0x4); -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* unset Record MIC input audio with direct playback */ -++static void unset_record_mic_input_audio_with_direct_playback(void) -++{ -++ /* ADC path for MIC IN */ -++ jz_mic_only = 0; -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -++ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* set Record playing audio mixed with MIC input audio */ -++static void set_record_playing_audio_mixed_with_mic_input_audio(void) -++{ -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file(9, 0xff); -++ //write_codec_file(8, 0x30); -++ write_codec_file(8, 0x20); -++ mdelay(10); -++ -++ write_codec_file(22, 0x63);//mic 1 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(6, 1, 3);// gain set -++ -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -++ write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 -++ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ write_codec_file_bit(5, 0, 4);//PMR1.SB_MIX->0 -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* unset Record playing audio mixed with MIC input audio */ -++static void unset_record_playing_audio_mixed_with_mic_input_audio(void) -++{ -++ /* ADC path */ -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -++ //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ //write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* set Record MIC input audio with Audio data replay (full duplex) */ -++static void set_record_mic_input_audio_with_audio_data_replay(void) -++{ -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file(9, 0xff); -++ //write_codec_file(8, 0x30); -++ write_codec_file(8, 0x20); -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ -++ write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 -++ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -++ -++ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* unset Record MIC input audio with Audio data replay (full duplex) */ -++static void unset_record_mic_input_audio_with_audio_data_replay(void) -++{ -++ /* ADC path */ -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* set Record LINE input audio with Audio data replay (full duplex for linein) */ -++static void set_record_line_input_audio_with_audio_data_replay(void) -++{ -++ write_codec_file(9, 0xff); -++ //write_codec_file(8, 0x30); -++ write_codec_file(8, 0x20); -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //write_codec_file_bit(22, 1, 7);//CR3.SB_MIC->1 -++ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ -++ -++ //jz_mic_only = 1; -++ write_codec_file(22, 0xc6);//line in 1 -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* unset Record LINE input audio with Audio data replay (full duplex for linein) */ -++static void unset_record_line_input_audio_with_audio_data_replay(void) -++{ -++ /* ADC path */ -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++#endif -++ -++static inline int get_buffer_id(struct buffer_queue_s *q) -++{ -++ int r; -++ unsigned long flags; -++ int i; -++ -++ spin_lock_irqsave(&q->lock, flags); -++ if (q->count == 0) { -++ spin_unlock_irqrestore(&q->lock, flags); -++ return -1; -++ } -++ r = *(q->id + 0); -++ for (i=0;i < q->count-1;i++) -++ *(q->id + i) = *(q->id + (i+1)); -++ q->count --; -++ spin_unlock_irqrestore(&q->lock, flags); -++ -++ return r; -++} -++ -++static inline void put_buffer_id(struct buffer_queue_s *q, int id) -++{ -++ unsigned long flags; -++ -++ spin_lock_irqsave(&q->lock, flags); -++ *(q->id + q->count) = id; -++ q->count ++; -++ spin_unlock_irqrestore(&q->lock, flags); -++} -++ -++static inline int elements_in_queue(struct buffer_queue_s *q) -++{ -++ int r; -++ unsigned long flags; -++ -++ spin_lock_irqsave(&q->lock, flags); -++ r = q->count; -++ spin_unlock_irqrestore(&q->lock, flags); -++ -++ return r; -++} -++ -++static inline void audio_start_dma(int chan, void *dev_id, unsigned long phyaddr,int count, int mode) -++{ -++ unsigned long flags; -++ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ jz_audio_dma_tran_count = count / jz_audio_b; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ flags = claim_dma_lock(); -++ disable_dma(chan); -++ clear_dma_ff(chan); -++ //set_dma_mode(chan, mode); -++ jz_set_oss_dma(chan, mode, jz_audio_format); -++ set_dma_addr(chan, phyaddr); -++ if (count == 0) { -++ count++; -++ printk("JzSOC DMA controller can't set dma 0 count!\n"); -++ } -++ set_dma_count(chan, count); -++ enable_dma(chan); -++ release_dma_lock(flags); -++} -++ -++static irqreturn_t jz_i2s_record_dma_irq (int irq, void *dev_id) -++{ -++ int id1, id2; -++ unsigned long flags; -++ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -++ int dma = controller->dma2; -++ -++ disable_dma(dma); -++ if (__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if (__dmac_channel_transmit_end_detected(dma)) { -++ __dmac_channel_clear_transmit_end(dma); -++ -++ if(drain_flag == 1) -++ wake_up(&drain_wait_queue); -++ /* for DSP_GETIPTR */ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ id1 = get_buffer_id(&in_busy_queue); -++ put_buffer_id(&in_full_queue, id1); -++ -++ wake_up(&rx_wait_queue); -++ wake_up(&controller->adc_wait); -++ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id2); -++ *(in_dma_buf_data_count + id2) = *(in_dma_buf_data_count + id1); -++ dma_cache_wback_inv(*(in_dma_buf + id2), *(in_dma_buf_data_count + id2)); -++ audio_start_dma(dma,dev_id, -++ *(in_dma_pbuf + id2), -++ *(in_dma_buf_data_count + id2), -++ DMA_MODE_READ); -++ } else -++ in_busy_queue.count = 0; -++ } -++ -++ return IRQ_HANDLED; -++} -++ -++static irqreturn_t jz_i2s_replay_dma_irq (int irq, void *dev_id) -++{ -++ int id; -++ unsigned long flags; -++ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -++ int dma = controller->dma1; -++ -++ disable_dma(dma); -++ if (__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if (__dmac_channel_transmit_end_detected(dma)) { -++ __dmac_channel_clear_transmit_end(dma); -++ -++ if(pop_dma_flag == 1) { -++ pop_dma_flag = 0; -++ wake_up(&pop_wait_queue); -++ } else { -++ if(drain_flag == 1) { -++ /* Is replay dma buffer over ? */ -++ if(elements_in_queue(&out_full_queue) <= 0) { -++ drain_flag = 0; -++ wake_up(&drain_wait_queue); -++ } -++ } -++ -++ /* for DSP_GETOPTR */ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ if ((id = get_buffer_id(&out_busy_queue)) < 0) -++ printk(KERN_DEBUG "Strange DMA finish interrupt for I2S module\n"); -++ put_buffer_id(&out_empty_queue, id); -++ if ((id = get_buffer_id(&out_full_queue)) >= 0) { -++ put_buffer_id(&out_busy_queue, id); -++ if(*(out_dma_buf_data_count + id) > 0) { -++ audio_start_dma(dma, dev_id, *(out_dma_pbuf + id), -++ *(out_dma_buf_data_count + id), -++ DMA_MODE_WRITE); -++ last_dma_buffer_id = id; -++ } -++ } else -++ out_busy_queue.count = 0; -++ -++ if (elements_in_queue(&out_empty_queue) > 0) { -++ wake_up(&tx_wait_queue); -++ wake_up(&controller->dac_wait); -++ } -++ } -++ } -++ -++ return IRQ_HANDLED; -++} -++ -++static void jz_i2s_initHw(int set) -++{ -++#if defined(CONFIG_MIPS_JZ_URANUS) -++ i2s_clk = 48000000; -++#else -++ i2s_clk = __cpm_get_i2sclk(); -++#endif -++ __i2s_disable(); -++ if(set) -++ __i2s_reset(); -++ schedule_timeout(5); -++ if(each_time_init_codec) -++ each_time_init_codec(); -++ __i2s_disable_record(); -++ __i2s_disable_replay(); -++ __i2s_disable_loopback(); -++ __i2s_set_transmit_trigger(4); -++ __i2s_set_receive_trigger(3); -++} -++ -++static int Init_In_Out_queue(int fragstotal,int fragsize) -++{ -++ int i; -++ -++ /* recording */ -++ in_empty_queue.count = fragstotal; -++ in_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_buf) -++ goto all_mem_err; -++ in_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_pbuf) -++ goto all_mem_err; -++ in_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_buf_data_count) -++ goto all_mem_err; -++ in_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_empty_queue.id) -++ goto all_mem_err; -++ in_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_full_queue.id) -++ goto all_mem_err; -++ in_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_busy_queue.id) -++ goto all_mem_err; -++ -++ for (i=0;i < fragstotal;i++) -++ *(in_empty_queue.id + i) = i; -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ -++ for (i = 0; i < fragstotal; i++) { -++ *(in_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -++ if (*(in_dma_buf + i) == 0) -++ goto mem_failed_in; -++ *(in_dma_pbuf + i) = virt_to_phys((void *)(*(in_dma_buf + i))); -++ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -++ } -++ -++ /* playing */ -++ out_empty_queue.count = fragstotal; -++ out_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!out_dma_buf) -++ goto all_mem_err; -++ out_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!out_dma_pbuf) -++ goto all_mem_err; -++ out_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ -++ if (!out_dma_buf_data_count) -++ goto all_mem_err; -++ out_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_empty_queue.id) -++ goto all_mem_err; -++ out_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_full_queue.id) -++ goto all_mem_err; -++ out_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_busy_queue.id) -++ goto all_mem_err; -++ for (i=0;i < fragstotal;i++) -++ *(out_empty_queue.id + i) = i; -++ -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ /* alloc DMA buffer */ -++ for (i = 0; i < fragstotal; i++) { -++ *(out_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -++ if (*(out_dma_buf + i) == 0) { -++ printk(" can't allocate required DMA(OUT) buffers.\n"); -++ goto mem_failed_out; -++ } -++ *(out_dma_pbuf + i) = virt_to_phys((void *)(*(out_dma_buf + i))); -++ } -++ -++ return 1; -++all_mem_err: -++ printk("error:allocate memory occur error 1!\n"); -++ return 0; -++mem_failed_out: -++ printk("error:allocate memory occur error 2!\n"); -++ for (i = 0; i < fragstotal; i++) { -++ if(*(out_dma_buf + i)) -++ free_pages(*(out_dma_buf + i), get_order(fragsize)); -++ } -++ -++ return 0; -++mem_failed_in: -++ printk("error:allocate memory occur error 3!\n"); -++ for (i = 0; i < fragstotal; i++) { -++ if(*(in_dma_buf + i)) -++ free_pages(*(in_dma_buf + i), get_order(fragsize)); -++ } -++ return 0; -++} -++ -++static int Free_In_Out_queue(int fragstotal,int fragsize) -++{ -++ int i; -++ /* playing */ -++ if(out_dma_buf != NULL) { -++ for (i = 0; i < fragstotal; i++) { -++ if(*(out_dma_buf + i)) -++ free_pages(*(out_dma_buf + i), get_order(fragsize)); -++ *(out_dma_buf + i) = 0; -++ } -++ kfree(out_dma_buf); -++ out_dma_buf = NULL; -++ } -++ if(out_dma_pbuf) { -++ kfree(out_dma_pbuf); -++ out_dma_pbuf = NULL; -++ } -++ if(out_dma_buf_data_count) { -++ kfree(out_dma_buf_data_count); -++ out_dma_buf_data_count = NULL; -++ } -++ if(out_empty_queue.id) { -++ kfree(out_empty_queue.id); -++ out_empty_queue.id = NULL; -++ } -++ if(out_full_queue.id) { -++ kfree(out_full_queue.id); -++ out_full_queue.id = NULL; -++ } -++ if(out_busy_queue.id) { -++ kfree(out_busy_queue.id); -++ out_busy_queue.id = NULL; -++ } -++ out_empty_queue.count = fragstotal; -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ -++ /* recording */ -++ if(in_dma_buf) { -++ for (i = 0; i < fragstotal; i++) { -++ if(*(in_dma_buf + i)) { -++ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -++ free_pages(*(in_dma_buf + i), get_order(fragsize)); -++ } -++ *(in_dma_buf + i) = 0; -++ } -++ kfree(in_dma_buf); -++ in_dma_buf = NULL; -++ } -++ if(in_dma_pbuf) { -++ kfree(in_dma_pbuf); -++ in_dma_pbuf = NULL; -++ } -++ if(in_dma_buf_data_count) { -++ kfree(in_dma_buf_data_count); -++ in_dma_buf_data_count = NULL; -++ } -++ if(in_empty_queue.id) { -++ kfree(in_empty_queue.id); -++ in_empty_queue.id = NULL; -++ } -++ if(in_full_queue.id) { -++ kfree(in_full_queue.id); -++ in_full_queue.id = NULL; -++ } -++ if(in_busy_queue.id) { -++ kfree(in_busy_queue.id); -++ in_busy_queue.id = NULL; -++ } -++ -++ in_empty_queue.count = fragstotal; -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ -++ return 1; -++} -++ -++static void jz_i2s_full_reset(struct jz_i2s_controller_info *controller) -++{ -++ jz_i2s_initHw(0); -++} -++ -++static int jz_audio_set_speed(int dev, int rate) -++{ -++ /* 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999 ? */ -++ jz_audio_speed = rate; -++ if (rate > 48000) -++ rate = 48000; -++ if (rate < 8000) -++ rate = 8000; -++ jz_audio_rate = rate; -++ -++ if(set_codec_speed) -++ set_codec_speed(rate); -++ -++ return jz_audio_rate; -++} -++ -++ -++static int record_fill_1x8_u(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long data; -++ volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ volatile unsigned char *dp = (unsigned char*)dst_start; -++ -++ while (count > 0) { -++ count -= 2; /* count in dword */ -++ cnt++; -++ data = *(s++); -++ *(dp ++) = ((data << 16) >> 24) + 0x80; -++ s++; /* skip the other channel */ -++ } -++ -++ return cnt; -++} -++ -++ -++static int record_fill_2x8_u(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long d1, d2; -++ volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ volatile unsigned char *dp = (unsigned char*)dst_start; -++ -++ while (count > 0) { -++ count -= 2; -++ cnt += 2; -++ d1 = *(s++); -++ *(dp ++) = ((d1 << 16) >> 24) + 0x80; -++ d2 = *(s++); -++ *(dp ++) = ((d2 << 16) >> 24) + 0x80; -++ } -++ -++ return cnt; -++} -++ -++ -++static int record_fill_1x16_s(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long d1; -++ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ unsigned short *dp = (unsigned short *)dst_start; -++ -++ while (count > 0) { -++ count -= 2; /* count in dword */ -++ cnt += 2; /* count in byte */ -++ d1 = *(s++); -++ *(dp ++) = (d1 << 16) >> 16; -++ s++; /* skip the other channel */ -++ } -++ -++ return cnt; -++} -++ -++ -++static int record_fill_2x16_s(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long d1, d2; -++ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ unsigned short *dp = (unsigned short *)dst_start; -++ while (count > 0) { -++ count -= 2; /* count in dword */ -++ cnt += 4; /* count in byte */ -++ d1 = *(s++); -++ d2 = *(s++); -++ if(abnormal_data_count > 0) { -++ d1 = d2 = 0; -++ abnormal_data_count --; -++ } -++ *(dp ++) = (d1 << 16) >> 16; -++ *(dp ++) = (d2 << 16) >> 16; -++ } -++ -++ return cnt; -++} -++ -++static void replay_fill_1x8_u(signed long src_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned char data; -++ unsigned long ddata; -++ volatile unsigned char *s = (unsigned char *)src_start; -++ volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); -++ -++ while (count > 0) { -++ count--; -++ cnt += 1; -++ data = *(s++) - 0x80; -++ ddata = (unsigned long) data << 8; -++ *(dp ++) = ddata; -++ *(dp ++) = ddata; -++ -++ /* save last left and right */ -++ if(count == 1) { -++ save_last_samples[id].left = ddata; -++ save_last_samples[id].right = ddata; -++ } -++ } -++ cnt = cnt * 2 * jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++ -++static void replay_fill_2x8_u(signed long src_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned char d1; -++ unsigned long dd1; -++ volatile unsigned char *s = (unsigned char *)src_start; -++ volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); -++ -++ while (count > 0) { -++ count -= 1; -++ cnt += 1 ; -++ d1 = *(s++) - 0x80; -++ dd1 = (unsigned long) d1 << 8; -++ *(dp ++) = dd1; -++ /* save last left */ -++ if(count == 2) -++ save_last_samples[id].left = dd1; -++ /* save last right */ -++ if(count == 1) -++ save_last_samples[id].right = dd1; -++ } -++ cnt *= jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++ -++static void replay_fill_1x16_s(signed long src_start, int count, int id) -++{ -++ int cnt = 0; -++ signed short d1; -++ signed long l1; -++ volatile signed short *s = (signed short *)src_start; -++ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -++ -++ while (count > 0) { -++ count -= 2; -++ cnt += 2 ; -++ d1 = *(s++); -++ l1 = (signed long)d1; -++ *(dp ++) = l1; -++ *(dp ++) = l1; -++ -++ /* save last left and right */ -++ if(count == 1) { -++ save_last_samples[id].left = l1; -++ save_last_samples[id].right = l1; -++ } -++ } -++ cnt = cnt * 2 * jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++#if 0 -++static void replay_fill_2x16_s(signed long src_start, int count, int id) -++{ -++ int cnt = 0; -++ signed short d1; -++ signed long l1; -++ int mute_cnt = 0; -++ signed long tmp1,tmp2; -++ volatile signed short *s = (signed short *)src_start; -++ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -++#if defined(CONFIG_I2S_ICDC) -++ volatile signed long *before_dp; -++ int sam_rate = jz_audio_rate / 20; -++ -++ tmp1 = tmp2 = 0; -++ while (count > 0) { -++ count -= 2; -++ cnt += 2; -++ d1 = *(s++); -++ -++ l1 = (signed long)d1; -++ l1 >>= codec_volue_shift; -++ -++ if(l1 == 0) { -++ mute_cnt ++; -++ if(mute_cnt >= sam_rate) { -++ before_dp = dp - 10; -++ *(before_dp) = (signed long)1; -++ before_dp = dp - 11; -++ *(before_dp) = (signed long)1; -++ mute_cnt = 0; -++ } -++ } else -++ mute_cnt = 0; -++ -++ *(dp ++) = l1; -++ -++ tmp1 = tmp2; -++ tmp2 = l1; -++ } -++ -++ /* save last left */ -++ save_last_samples[id].left = tmp1; -++ /* save last right */ -++ save_last_samples[id].right = tmp2; -++#endif -++#if defined(CONFIG_I2S_DLV) -++ while (count > 0) { -++ count -= 2; -++ cnt += 2; -++ d1 = *(s++); -++ -++ l1 = (signed long)d1; -++ -++ *(dp ++) = l1; -++ } -++#endif -++ cnt *= jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++#else -++static void replay_fill_2x16_s(signed long src_start, int count, int id) -++{ -++ int cnt = 0; -++ signed short d1; -++ signed long l1; -++ -++#if 0 -++ volatile signed short *s = (signed short *)src_start; -++ volatile signed short *dp = (signed short*)(*(out_dma_buf + id)); -++ memcpy((char*)dp, (char*)s, count); -++ *(out_dma_buf_data_count + id) = count; -++#else -++ volatile signed short *s = (signed short *)src_start; -++ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -++ while (count > 0) { -++ count -= 2; -++ cnt += 2; -++ d1 = *(s++); -++ -++ l1 = (signed long)d1; -++ -++ *(dp ++) = l1; -++ } -++ cnt *= jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++#endif -++} -++#endif -++ -++ -++static unsigned int jz_audio_set_format(int dev, unsigned int fmt) -++{ -++ switch (fmt) { -++ case AFMT_U8: -++ __i2s_set_oss_sample_size(8); -++ __i2s_set_iss_sample_size(8); -++ jz_audio_format = fmt; -++ jz_update_filler(jz_audio_format, jz_audio_channels); -++ break; -++ case AFMT_S16_LE: -++#if defined(CONFIG_I2S_DLV) -++ /* DAC path and ADC path */ -++ write_codec_file(2, 0x00); -++ //write_codec_file(2, 0x60); -++#endif -++ jz_audio_format = fmt; -++ jz_update_filler(jz_audio_format,jz_audio_channels); -++ /* print all files */ -++ __i2s_set_oss_sample_size(16); -++ __i2s_set_iss_sample_size(16); -++ break; -++ -++ case AFMT_QUERY: -++ break; -++ } -++ -++ return jz_audio_format; -++} -++ -++ -++static short jz_audio_set_channels(int dev, short channels) -++{ -++ switch (channels) { -++ case 1: -++ if(set_codec_some_func) -++ set_codec_some_func(); -++ jz_audio_channels = channels; -++ jz_update_filler(jz_audio_format, jz_audio_channels); -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file_bit(1, 1, 6);//CR1.MONO->1 for Mono -++#endif -++ break; -++ case 2: -++ jz_audio_channels = channels; -++ jz_update_filler(jz_audio_format, jz_audio_channels); -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file_bit(1, 0, 6);//CR1.MONO->0 for Stereo -++#endif -++ break; -++ case 0: -++ break; -++ } -++ -++ return jz_audio_channels; -++} -++ -++static void init_codec(void) -++{ -++ /* inititalize internal I2S codec */ -++ if(init_codec_pin) -++ init_codec_pin(); -++ -++#if defined(CONFIG_I2S_ICDC) -++ /* initialize AIC but not reset it */ -++ jz_i2s_initHw(0); -++#endif -++ if(reset_codec) -++ reset_codec(); -++} -++ -++static void jz_audio_reset(void) -++{ -++ __i2s_disable_replay(); -++ __i2s_disable_receive_dma(); -++ __i2s_disable_record(); -++ __i2s_disable_transmit_dma(); -++#if defined(CONFIG_I2S_DLV) -++ REG_AIC_I2SCR = 0x10; -++#endif -++ init_codec(); -++} -++ -++static int jz_audio_release(struct inode *inode, struct file *file); -++static int jz_audio_open(struct inode *inode, struct file *file); -++static int jz_audio_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg); -++static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait); -++static ssize_t jz_audio_write(struct file *file, const char *buffer,size_t count, loff_t *ppos); -++static ssize_t jz_audio_read(struct file *file, char *buffer,size_t count, loff_t *ppos); -++ -++/* static struct file_operations jz_i2s_audio_fops */ -++static struct file_operations jz_i2s_audio_fops = -++{ -++ owner: THIS_MODULE, -++ open: jz_audio_open, -++ release: jz_audio_release, -++ write: jz_audio_write, -++ read: jz_audio_read, -++ poll: jz_audio_poll, -++ ioctl: jz_audio_ioctl -++}; -++ -++static int jz_i2s_open_mixdev(struct inode *inode, struct file *file) -++{ -++ int i; -++ int minor = MINOR(inode->i_rdev); -++ struct jz_i2s_controller_info *controller = i2s_controller; -++ -++ for (i = 0; i < NR_I2S; i++) -++ if (controller->i2s_codec[i] != NULL && controller->i2s_codec[i]->dev_mixer == minor) -++ goto match; -++ -++ if (!controller) -++ return -ENODEV; -++match: -++ file->private_data = controller->i2s_codec[i]; -++ -++ return 0; -++} -++ -++static int jz_i2s_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -++{ -++ struct i2s_codec *codec = (struct i2s_codec *)file->private_data; -++ return codec->mixer_ioctl(codec, cmd, arg); -++} -++ -++static loff_t jz_i2s_llseek(struct file *file, loff_t offset, int origin) -++{ -++ return -ESPIPE; -++} -++ -++static struct file_operations jz_i2s_mixer_fops = -++{ -++ owner: THIS_MODULE, -++ llseek: jz_i2s_llseek, -++ ioctl: jz_i2s_ioctl_mixdev, -++ open: jz_i2s_open_mixdev, -++}; -++ -++static int i2s_mixer_ioctl(struct i2s_codec *codec, unsigned int cmd, unsigned long arg) -++{ -++ int ret; -++ long val = 0; -++ switch (cmd) { -++ case SOUND_MIXER_INFO: -++ -++ if(codec_mixer_info_id_name) -++ codec_mixer_info_id_name(); -++ info.modify_counter = audio_mix_modcnt; -++ -++ return copy_to_user((void *)arg, &info, sizeof(info)); -++ case SOUND_OLD_MIXER_INFO: -++ -++ if(codec_mixer_old_info_id_name) -++ codec_mixer_old_info_id_name(); -++ -++ return copy_to_user((void *)arg, &old_info, sizeof(info)); -++ case SOUND_MIXER_READ_STEREODEVS: -++ -++ return put_user(0, (long *) arg); -++ case SOUND_MIXER_READ_CAPS: -++ -++ val = SOUND_CAP_EXCL_INPUT; -++ return put_user(val, (long *) arg); -++ case SOUND_MIXER_READ_DEVMASK: -++ break; -++ case SOUND_MIXER_READ_RECMASK: -++ break; -++ case SOUND_MIXER_READ_RECSRC: -++ break; -++ case SOUND_MIXER_WRITE_SPEAKER: -++ -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val > 100) -++ val = 100; -++ switch(val) { -++ case 100: -++ if(set_codec_direct_mode) -++ set_codec_direct_mode(); -++ break; -++ case 0: -++ if(clear_codec_direct_mode) -++ clear_codec_direct_mode(); -++ break; -++ } -++ break; -++ case SOUND_MIXER_WRITE_BASS: -++ -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val > 100) -++ val = 100; -++ codec_bass_gain = val; -++ if(set_codec_bass) -++ set_codec_bass(val); -++ -++ return 0; -++ case SOUND_MIXER_READ_BASS: -++ -++ val = codec_bass_gain; -++ ret = val << 8; -++ val = val | ret; -++ -++ return put_user(val, (long *) arg); -++ case SOUND_MIXER_WRITE_VOLUME: -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val > 100) -++ val = 100; -++ if (val > 31) -++ val = 31; -++ jz_audio_volume = val; -++ -++ if(set_codec_volume) -++ set_codec_volume(val); -++ return 0; -++ case SOUND_MIXER_READ_VOLUME: -++ -++ val = jz_audio_volume; -++ ret = val << 8; -++ val = val | ret; -++ -++ return put_user(val, (long *) arg); -++ case SOUND_MIXER_WRITE_MIC: -++ -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val > 100) -++ val = 100; -++ codec_mic_gain = val; -++ if(set_codec_mic) -++ set_codec_mic(val); -++ -++ return 0; -++ case SOUND_MIXER_READ_MIC: -++ -++ val = codec_mic_gain; -++ ret = val << 8; -++ val = val | ret; -++ -++ return put_user(val, (long *) arg); -++ default: -++ return -ENOSYS; -++ } -++ audio_mix_modcnt ++; -++ return 0; -++} -++ -++ -++int i2s_probe_codec(struct i2s_codec *codec) -++{ -++ /* generic OSS to I2S wrapper */ -++ codec->mixer_ioctl = i2s_mixer_ioctl; -++ return 1; -++} -++ -++ -++/* I2S codec initialisation. */ -++static int __init jz_i2s_codec_init(struct jz_i2s_controller_info *controller) -++{ -++ int num_i2s = 0; -++ struct i2s_codec *codec; -++ -++ for (num_i2s = 0; num_i2s < NR_I2S; num_i2s++) { -++ if ((codec = kmalloc(sizeof(struct i2s_codec),GFP_KERNEL)) == NULL) -++ return -ENOMEM; -++ memset(codec, 0, sizeof(struct i2s_codec)); -++ codec->private_data = controller; -++ codec->id = num_i2s; -++ -++ if (i2s_probe_codec(codec) == 0) -++ break; -++ if ((codec->dev_mixer = register_sound_mixer(&jz_i2s_mixer_fops, -1)) < 0) { -++ printk(KERN_ERR "Jz I2S: couldn't register mixer!\n"); -++ kfree(codec); -++ break; -++ } -++ controller->i2s_codec[num_i2s] = codec; -++ } -++ return num_i2s; -++} -++ -++ -++static void jz_update_filler(int format, int channels) -++{ -++#define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3)) -++ -++ switch (TYPE(format, channels)) -++ { -++ -++ case TYPE(AFMT_U8, 1): -++ jz_audio_b = 4; /* 4bytes * 8bits =32bits */ -++ replay_filler = replay_fill_1x8_u; -++ record_filler = record_fill_1x8_u; -++ break; -++ case TYPE(AFMT_U8, 2): -++ jz_audio_b = 4; -++ replay_filler = replay_fill_2x8_u; -++ record_filler = record_fill_2x8_u; -++ break; -++ case TYPE(AFMT_S16_LE, 1): -++ jz_audio_b = 2; /* 2bytes * 16bits =32bits */ -++ replay_filler = replay_fill_1x16_s; -++ record_filler = record_fill_1x16_s; -++ break; -++ case TYPE(AFMT_S16_LE, 2): -++ jz_audio_b = 2; -++ replay_filler = replay_fill_2x16_s; -++ record_filler = record_fill_2x16_s; -++ break; -++ default: -++ ; -++ } -++} -++ -++ -++#ifdef CONFIG_PROC_FS -++extern struct proc_dir_entry *proc_jz_root; -++int i2s_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) -++{ -++ return 0; -++} -++ -++static int jz_i2s_init_proc(struct jz_i2s_controller_info *controller) -++{ -++ if (!create_proc_read_entry ("i2s", 0, proc_jz_root, i2s_read_proc, controller->i2s_codec[0])) -++ return -EIO; -++ return 0; -++} -++ -++static void jz_i2s_cleanup_proc(struct jz_i2s_controller_info *controller) -++{ -++} -++#endif -++ -++static void __init attach_jz_i2s(struct jz_i2s_controller_info *controller) -++{ -++ char *name; -++ int adev; /* No of Audio device. */ -++ -++ name = controller->name; -++ /* initialize AIC controller and reset it */ -++ jz_i2s_initHw(1); -++ adev = register_sound_dsp(&jz_i2s_audio_fops, -1); -++ if (adev < 0) -++ goto audio_failed; -++ /* initialize I2S codec and register /dev/mixer */ -++ if (jz_i2s_codec_init(controller) <= 0) -++ goto mixer_failed; -++ -++#ifdef CONFIG_PROC_FS -++ if (jz_i2s_init_proc(controller) < 0) { -++ printk(KERN_ERR "%s: can't create I2S proc filesystem.\n", name); -++ goto proc_failed; -++ } -++#endif -++ -++ controller->tmp1 = (void *)__get_free_pages(GFP_KERNEL, 8); -++ if (!controller->tmp1) { -++ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -++ goto tmp1_failed; -++ } -++ controller->tmp2 = (void *)__get_free_pages(GFP_KERNEL, 8); -++ if (!controller->tmp2) { -++ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -++ goto tmp2_failed; -++ } -++ if ((controller->dma2 = jz_request_dma(DMA_ID_I2S_RX, "audio adc", jz_i2s_record_dma_irq, IRQF_DISABLED, controller)) < 0) { -++ printk(KERN_ERR "%s: can't reqeust DMA ADC channel.\n", name); -++ goto dma2_failed; -++ } -++ if ((controller->dma1 = jz_request_dma(DMA_ID_I2S_TX, "audio dac", jz_i2s_replay_dma_irq, IRQF_DISABLED, controller)) < 0) { -++ printk(KERN_ERR "%s: can't reqeust DMA DAC channel.\n", name); -++ goto dma1_failed; -++ } -++ printk("JzSOC On-Chip I2S controller registered (DAC: DMA(play):%d/IRQ%d,\n ADC: DMA(record):%d/IRQ%d)\n", controller->dma1, get_dma_done_irq(controller->dma1), controller->dma2, get_dma_done_irq(controller->dma2)); -++ -++ controller->dev_audio = adev; -++ pop_turn_onoff_buf = __get_free_pages(GFP_KERNEL | GFP_DMA, 8); -++ if(!pop_turn_onoff_buf) -++ printk("pop_turn_onoff_buf alloc is wrong!\n"); -++ pop_turn_onoff_pbuf = virt_to_phys((void *)pop_turn_onoff_buf); -++ -++ return; -++dma2_failed: -++ jz_free_dma(controller->dma1); -++dma1_failed: -++ free_pages((unsigned long)controller->tmp2, 8); -++tmp2_failed: -++ free_pages((unsigned long)controller->tmp1, 8); -++tmp1_failed: -++ -++#ifdef CONFIG_PROC_FS -++ jz_i2s_cleanup_proc(controller); -++#endif -++proc_failed: -++ /* unregister mixer dev */ -++mixer_failed: -++ unregister_sound_dsp(adev); -++audio_failed: -++ return; -++} -++ -++static int __init probe_jz_i2s(struct jz_i2s_controller_info **controller) -++{ -++ if ((*controller = kmalloc(sizeof(struct jz_i2s_controller_info), -++ GFP_KERNEL)) == NULL) { -++ printk(KERN_ERR "Jz I2S Controller: out of memory.\n"); -++ return -ENOMEM; -++ } -++ (*controller)->name = "Jz I2S controller"; -++ (*controller)->opened1 = 0; -++ (*controller)->opened2 = 0; -++ init_waitqueue_head(&(*controller)->adc_wait); -++ init_waitqueue_head(&(*controller)->dac_wait); -++ spin_lock_init(&(*controller)->lock); -++ init_waitqueue_head(&rx_wait_queue); -++ init_waitqueue_head(&tx_wait_queue); -++ init_waitqueue_head(&pop_wait_queue); -++ init_waitqueue_head(&drain_wait_queue); -++ -++ return 0; -++} -++ -++static void __exit unload_jz_i2s(struct jz_i2s_controller_info *controller) -++{ -++ int adev = controller->dev_audio; -++ -++ jz_i2s_full_reset(controller); -++ controller->dev_audio = -1; -++ if (old_mksound) -++ kd_mksound = old_mksound;/* Our driver support bell for kb, see vt.c */ -++ -++#ifdef CONFIG_PROC_FS -++ jz_i2s_cleanup_proc(controller); -++#endif -++ -++ jz_free_dma(controller->dma1); -++ jz_free_dma(controller->dma2); -++ free_pages((unsigned long)controller->tmp1, 8); -++ free_pages((unsigned long)controller->tmp2, 8); -++ free_pages((unsigned long)pop_turn_onoff_buf, 8); -++ -++ if (adev >= 0) { -++ /* unregister_sound_mixer(audio_devs[adev]->mixer_dev); */ -++ unregister_sound_dsp(controller->dev_audio); -++ } -++} -++ -++#ifdef CONFIG_PM -++static int jz_i2s_suspend(struct jz_i2s_controller_info *controller, int state) -++{ -++ if(i2s_suspend_codec) -++ i2s_suspend_codec(controller->opened1,controller->opened2); -++ printk("Aic and codec are suspended!\n"); -++ return 0; -++} -++ -++static int jz_i2s_resume(struct jz_i2s_controller_info *controller) -++{ -++ if(i2s_resume_codec) -++ i2s_resume_codec(); -++ -++#if defined(CONFIG_I2S_AK4642EN) -++ jz_i2s_initHw(0); -++ jz_audio_reset(); -++ __i2s_enable(); -++ jz_audio_set_speed(controller->dev_audio,jz_audio_speed); -++ /* playing */ -++ if(controller->opened1) { -++ if(set_codec_replay) -++ set_codec_replay(); -++ int dma = controller->dma1; -++ int id; -++ unsigned long flags; -++ disable_dma(dma); -++ if(__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if(__dmac_channel_transmit_end_detected(dma)) -++ __dmac_channel_clear_transmit_end(dma); -++ -++ /* for DSP_GETOPTR */ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ while((id = get_buffer_id(&out_busy_queue)) >= 0) -++ put_buffer_id(&out_empty_queue, id); -++ -++ out_busy_queue.count=0; -++ if((id = get_buffer_id(&out_full_queue)) >= 0) { -++ put_buffer_id(&out_empty_queue, id); -++ } -++ if (elements_in_queue(&out_empty_queue) > 0) { -++ wake_up(&tx_wait_queue); -++ wake_up(&controller->dac_wait); -++ } else -++ printk("pm out_empty_queue empty"); -++ } -++ -++ /* recording */ -++ if(controller->opened2) { -++ if(set_codec_record) -++ set_codec_record(); -++ int dma = controller->dma2; -++ int id1, id2; -++ unsigned long flags; -++ disable_dma(dma); -++ if (__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if (__dmac_channel_transmit_end_detected(dma)) { -++ __dmac_channel_clear_transmit_end(dma); -++ } -++ /* for DSP_GETIPTR */ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ id1 = get_buffer_id(&in_busy_queue); -++ put_buffer_id(&in_full_queue, id1); -++ wake_up(&rx_wait_queue); -++ wake_up(&controller->adc_wait); -++ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_full_queue, id2); -++ } -++ in_busy_queue.count = 0; -++ } -++#endif -++ -++ return 0; -++} -++ -++static int jz_i2s_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -++{ -++ int ret; -++ struct jz_i2s_controller_info *controller = pm_dev->data; -++ -++ if (!controller) return -EINVAL; -++ -++ switch (req) { -++ case PM_SUSPEND: -++ ret = jz_i2s_suspend(controller, (int)data); -++ break; -++ case PM_RESUME: -++ ret = jz_i2s_resume(controller); -++ break; -++ default: -++ ret = -EINVAL; -++ break; -++ } -++ return ret; -++} -++#endif /* CONFIG_PM */ -++static irqreturn_t aic_codec_irq(int irq, void *dev_id) -++{ -++ u8 file_9 = read_codec_file(9); -++ u8 file_8 = read_codec_file(8); -++ -++ //printk("--- 8:0x%x 9:0x%x ---\n",file_8,file_9); -++ if ((file_9 & 0x1f) == 0x10) { -++ -++ write_codec_file(8, 0x3f); -++ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ mdelay(300); -++ while ((read_codec_file(9) & 0x4) != 0x4); -++ while ((read_codec_file(9) & 0x10) == 0x10) { -++ write_codec_file(9, 0x10); -++ } -++ write_codec_file_bit(5, 0, 6);//SB_OUT->0 -++ mdelay(300); -++ while ((read_codec_file(9) & 0x8) != 0x8); -++ write_codec_file(9, file_9); -++ write_codec_file(8, file_8); -++ -++ return IRQ_HANDLED; -++ } -++ -++ if (file_9 & 0x8) -++ ramp_up_end = jiffies; -++ else if (file_9 & 0x4) -++ ramp_down_end = jiffies; -++ else if (file_9 & 0x2) -++ gain_up_end = jiffies; -++ else if (file_9 & 0x1) -++ gain_down_end = jiffies; -++ -++ write_codec_file(9, file_9); -++ if (file_9 & 0xf) -++ wake_up(&pop_wait_queue); -++ while (REG_ICDC_RGDATA & 0x100); -++ -++ return IRQ_HANDLED; -++} -++ -++static int __init init_jz_i2s(void) -++{ -++ int errno, retval; -++#if defined(CONFIG_I2S_DLV) -++ -++ ramp_up_start = 0; -++ ramp_up_end = 0; -++ gain_up_start = 0; -++ gain_up_end = 0; -++ ramp_down_start = 0; -++ ramp_down_end = 0; -++ gain_down_start = 0; -++ gain_down_end = 0; -++#endif -++ -++ abnormal_data_count = 0; -++ if(set_codec_mode) -++ set_codec_mode(); -++ -++ drain_flag = 0; -++ if ((errno = probe_jz_i2s(&i2s_controller)) < 0) -++ return errno; -++ if(set_codec_gpio_pin) -++ set_codec_gpio_pin(); -++ -++ attach_jz_i2s(i2s_controller); -++ if(set_codec_startup_param) -++ set_codec_startup_param(); -++#if defined(CONFIG_I2S_DLV) -++ jz_codec_config = 0; -++ retval = request_irq(IRQ_AIC, aic_codec_irq, IRQF_DISABLED, "aic_codec_irq", NULL); -++ if (retval) { -++ printk("Could not get aic codec irq %d\n", IRQ_AIC); -++ return retval; -++ } -++#endif -++ if(set_codec_volume_table) -++ set_codec_volume_table(); -++ -++ out_empty_queue.id = NULL; -++ out_full_queue.id = NULL; -++ out_busy_queue.id = NULL; -++ in_empty_queue.id = NULL; -++ in_full_queue.id = NULL; -++ in_busy_queue.id = NULL; -++ -++ jz_audio_fragsize = JZCODEC_RW_BUFFER_SIZE * PAGE_SIZE; -++ jz_audio_fragstotal = JZCODEC_RW_BUFFER_TOTAL ; -++ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ -++#ifdef CONFIG_PM -++ i2s_controller->pm = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, -++ jz_i2s_pm_callback); -++ if (i2s_controller->pm) -++ i2s_controller->pm->data = i2s_controller; -++#endif -++ -++#if defined(CONFIG_I2S_DLV) -++ __cpm_start_idct(); -++ __cpm_start_db(); -++ __cpm_start_me(); -++ __cpm_start_mc(); -++ __cpm_start_ipu(); -++#endif -++ -++ printk("JZ I2S OSS audio driver initialized\n"); -++ -++ return 0; -++} -++ -++static void __exit cleanup_jz_i2s(void) -++{ -++#ifdef CONFIG_PM -++ /* pm_unregister(i2s_controller->pm); */ -++#endif -++#if defined(CONFIG_I2S_DLV) -++ free_irq(IRQ_AIC, NULL); -++#endif -++ unload_jz_i2s(i2s_controller); -++ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ if(clear_codec_mode) -++ clear_codec_mode(); -++} -++ -++module_init(init_jz_i2s); -++module_exit(cleanup_jz_i2s); -++ -++#if defined(CONFIG_SOC_JZ4730) -++static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ DECLARE_WAITQUEUE(wait, current); -++ unsigned long flags; -++ int count,con; -++ -++ if(elements_in_queue(&in_busy_queue) > 0) { -++ if (nonblock) -++ return -EBUSY; -++ drain_flag = 1; -++ sleep_on(&drain_wait_queue); -++ drain_flag = 0; -++ } else { -++ add_wait_queue(&ctrl->adc_wait, &wait); -++ for (con = 0; con < 1000; con ++) { -++ udelay(1); -++ set_current_state(TASK_INTERRUPTIBLE); -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma2); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if (count <= 0) -++ break; -++ if (nonblock) { -++ remove_wait_queue(&ctrl->adc_wait, &wait); -++ current->state = TASK_RUNNING; -++ return -EBUSY; -++ } -++ } -++ remove_wait_queue(&ctrl->adc_wait, &wait); -++ current->state = TASK_RUNNING; -++ } -++ return 0; -++} -++ -++static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ DECLARE_WAITQUEUE(wait, current); -++ unsigned long flags; -++ int count; -++ -++ if(elements_in_queue(&out_full_queue) > 0) { -++ if (nonblock) -++ return -EBUSY; -++ -++ drain_flag = 1; -++ sleep_on(&drain_wait_queue); -++ drain_flag = 0; -++ } else { -++ add_wait_queue(&(ctrl->dac_wait), &wait); -++ for (;;) { -++ set_current_state(TASK_INTERRUPTIBLE); -++ if(elements_in_queue(&out_full_queue) <= 0) { -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if(count <= 0) -++ break; -++ } -++ if (nonblock) { -++ remove_wait_queue(&ctrl->dac_wait, &wait); -++ current->state = TASK_RUNNING; -++ return -EBUSY; -++ } -++ } -++ remove_wait_queue(&ctrl->dac_wait, &wait); -++ current->state = TASK_RUNNING; -++ } -++ -++ return 0; -++} -++#endif -++ -++#if defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D) -++static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ //DECLARE_WAITQUEUE(wait, current); -++ unsigned long flags; -++ int count,i=0; -++ -++ //add_wait_queue(&ctrl->adc_wait, &wait); -++ for (;;) { -++ if (i < MAXDELAY) { -++ udelay(10); -++ i++; -++ } else -++ break; -++ //set_current_state(TASK_INTERRUPTIBLE); -++ spin_lock_irqsave(&ctrl->lock, flags); -++ //spin_lock(&ctrl->lock); -++ count = get_dma_residue(ctrl->dma2); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ //spin_unlock(&ctrl->lock); -++ if (count <= 0) -++ break; -++ -++ /*if (signal_pending(current)) -++ break;*/ -++ if (nonblock) { -++ //remove_wait_queue(&ctrl->adc_wait, &wait); -++ //current->state = TASK_RUNNING; -++ return -EBUSY; -++ } -++ } -++ //remove_wait_queue(&ctrl->adc_wait, &wait); -++ //current->state = TASK_RUNNING; -++ /*if (signal_pending(current)) -++ return -ERESTARTSYS;*/ -++ return 0; -++} -++static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ unsigned long flags; -++ int count,ele,busyele,emptyele,i=0; -++ -++ for (;;) { -++ if(!nonblock) {//blocked -++ if (i < MAXDELAY) { -++ udelay(10); -++ i++; -++ } else -++ break; -++ -++ ele = elements_in_queue(&out_full_queue); -++ if(ele <= 0) { -++ udelay(200); -++ -++ busyele = elements_in_queue(&out_busy_queue); -++ emptyele = elements_in_queue(&out_empty_queue); -++ if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if (count <= 0) -++ break; -++ } -++ } -++ } else {//non-blocked -++ //mdelay(100); -++ ele = elements_in_queue(&out_full_queue); -++ -++ if(ele <= 0) { -++ //mdelay(100); -++ busyele = elements_in_queue(&out_busy_queue); -++ emptyele = elements_in_queue(&out_empty_queue); -++ -++ if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if (count <= 0) -++ break; -++ } -++ } -++ } -++ } -++ -++ return 0; -++} -++#endif -++ -++#if defined(CONFIG_SOC_JZ4740) -++#define MAXDELAY 50000 -++static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ int count,ele,i=0; -++ -++ for (;;) { -++ if(!nonblock) {//blocked -++ if ( i < MAXDELAY ) { -++ udelay(10); -++ i++; -++ } else -++ break; -++ -++ ele = elements_in_queue(&out_full_queue); -++ if(ele <= 0) { -++ udelay(10); -++ spin_lock(&ctrl->lock); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock(&ctrl->lock); -++ if (count <= 0) -++ break; -++ } -++ } else {//non-blocked -++ mdelay(100); -++ ele = elements_in_queue(&out_full_queue); -++ -++ if(ele <= 0) { -++ mdelay(100); -++ -++ spin_lock(&ctrl->lock); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock(&ctrl->lock); -++ if (count <= 0) -++ break; -++ } -++ } -++ } -++ -++ return 0; -++} -++ -++static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ int count,i=0; -++ -++ for (;;) { -++ if ( i < MAXDELAY ) -++ { -++ udelay(10); -++ i++; -++ } -++ else -++ break; -++ spin_lock(&ctrl->lock); -++ count = get_dma_residue(ctrl->dma2); -++ spin_unlock(&ctrl->lock); -++ if (count <= 0) -++ break; -++ -++ if (nonblock) { -++ return -EBUSY; -++ } -++ } -++ -++ return 0; -++} -++#endif -++ -++static int jz_audio_release(struct inode *inode, struct file *file) -++{ -++ unsigned long flags; -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ unsigned long tfl; -++ -++ if (controller == NULL) -++ return -ENODEV; -++ -++ pop_dma_flag = 0; -++ if (controller->opened1 == 1) { -++ controller->opened1 = 0; -++ __i2s_enable_transmit_dma(); -++ __i2s_enable_replay(); -++ drain_dac(controller, file->f_flags & O_NONBLOCK); -++ /* add some mute to anti-pop */ -++#if defined(CONFIG_I2S_DLV) -++ /* wait for fifo empty */ -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ gain_down_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //gain_down_end = jiffies; -++ while (1) { -++ tfl = REG_AIC_SR & 0x00003f00; -++ if (tfl == 0) { -++ udelay(500); -++ break; -++ } -++ mdelay(2); -++ } -++#endif -++ disable_dma(controller->dma1); -++ set_dma_count(controller->dma1, 0); -++ __i2s_disable_transmit_dma(); -++ __i2s_disable_replay(); -++ __aic_flush_fifo(); -++ if(clear_codec_replay) -++ clear_codec_replay(); -++ __aic_flush_fifo(); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->blocks = 0; -++ controller->nextOut = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ ramp_down_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //ramp_down_end = jiffies; -++ unset_audio_data_replay(); -++#endif -++ __i2s_disable(); -++ if(turn_off_codec) -++ turn_off_codec(); -++ } -++ -++ if (controller->opened2 == 1) { -++ controller->opened2 = 0; -++ first_record_call = 1; -++ __i2s_enable_receive_dma(); -++ __i2s_enable_record(); -++ drain_adc(controller, file->f_flags & O_NONBLOCK); -++ disable_dma(controller->dma2); -++ set_dma_count(controller->dma2, 0); -++ __i2s_disable_receive_dma(); -++ __i2s_disable_record(); -++ -++ if(clear_codec_record) -++ clear_codec_record(); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextIn = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ __i2s_disable(); -++ if(turn_off_codec) -++ turn_off_codec(); -++ abnormal_data_count = 0; -++ } -++ -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++#endif -++ return 0; -++} -++ -++static int jz_audio_open(struct inode *inode, struct file *file) -++{ -++ int i; -++ struct jz_i2s_controller_info *controller = i2s_controller; -++ -++ if (controller == NULL) -++ return -ENODEV; -++ -++ mdelay(2); -++ REG_DMAC_DMACKE(0) = 0x3f; -++ pop_dma_flag = 0; -++ if (controller->opened1 == 1 || controller->opened2 == 1 ) { -++ printk("\naudio is busy!\n"); -++ return -EBUSY; -++ } -++ jz_codec_config = 0; -++ -++ ramp_up_start = 0; -++ ramp_up_end = 0; -++ gain_up_start = 0; -++ gain_up_end = 0; -++ ramp_down_start = 0; -++ ramp_down_end = 0; -++ gain_down_start = 0; -++ gain_down_end = 0; -++ if (file->f_mode & FMODE_WRITE) { -++ if (controller->opened1 == 1) -++ return -EBUSY; -++ -++ controller->opened1 = 1; -++ /* for ioctl */ -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextOut = 0; -++ -++ for(i=0;i < 64;i++) { -++ save_last_samples[i].left = 0; -++ save_last_samples[i].right = 0; -++ } -++ -++ out_empty_queue.count = jz_audio_fragstotal; -++ for (i=0;i < jz_audio_fragstotal;i++) -++ *(out_empty_queue.id + i) = i; -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ last_dma_buffer_id = 0; -++ } -++ -++ if (file->f_mode & FMODE_READ) { -++ if (controller->opened2 == 1) -++ return -EBUSY; -++ -++ controller->opened2 = 1; -++ first_record_call = 1; -++ /* for ioctl */ -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextIn = 0; -++ -++ in_empty_queue.count = jz_audio_fragstotal; -++ for (i=0;i < jz_audio_fragstotal;i++) -++ *(in_empty_queue.id + i) = i; -++ -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ } -++ -++ file->private_data = controller; -++ jz_audio_reset(); -++ REG_AIC_FR |= (1 << 6); -++ -++ if (file->f_mode & FMODE_WRITE) { -++ if(set_codec_replay) -++ set_codec_replay(); -++ } -++ -++ if (file->f_mode & FMODE_READ) { -++ abnormal_data_count = 0; -++ if(set_codec_record) -++ set_codec_record(); -++ } -++ -++#if defined(CONFIG_I2S_DLV) -++ __aic_reset(); -++ -++ mdelay(10); -++ REG_AIC_I2SCR = 0x10; -++ mdelay(20); -++ __aic_flush_fifo(); -++#endif -++ -++ __i2s_enable(); -++ -++#if defined(CONFIG_I2S_DLV) -++ if (file->f_mode & FMODE_WRITE) { -++ -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ ramp_up_start = jiffies; -++ /*while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_RCR = 0x1; -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_RGR = 1;*/ -++ sleep_on(&pop_wait_queue); -++ //ramp_up_end = jiffies; -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ } else if (file->f_mode & FMODE_READ) { -++ if (jz_mic_only) -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ else -++ write_codec_file_bit(5, 0, 7);//SB_DAC->0 -++ mdelay(500); -++ } -++ -++#endif -++ -++ return 0; -++} -++ -++ -++static int jz_audio_ioctl(struct inode *inode, struct file *file, -++unsigned int cmd, unsigned long arg) -++{ -++ int val,fullc,busyc,unfinish,newfragstotal,newfragsize; -++ unsigned int flags; -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ count_info cinfo; -++ audio_buf_info abinfo; -++ int id, i; -++ -++ val = 0; -++ switch (cmd) { -++ case OSS_GETVERSION: -++ return put_user(SOUND_VERSION, (int *)arg); -++ case SNDCTL_DSP_RESET: -++#if 0 -++ jz_audio_reset(); -++ __i2s_disable_replay(); -++ __i2s_disable_receive_dma(); -++ __i2s_disable_record(); -++ __i2s_disable_transmit_dma(); -++#endif -++ return 0; -++ case SNDCTL_DSP_SYNC: -++ if (file->f_mode & FMODE_WRITE) -++ return drain_dac(controller, file->f_flags & O_NONBLOCK); -++ return 0; -++ case SNDCTL_DSP_SPEED: -++ /* set smaple rate */ -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ if (val >= 0) -++ jz_audio_set_speed(controller->dev_audio, val); -++ -++ return put_user(val, (int *)arg); -++ case SNDCTL_DSP_STEREO: -++ /* set stereo or mono channel */ -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ jz_audio_set_channels(controller->dev_audio, val ? 2 : 1); -++ -++ return 0; -++ case SNDCTL_DSP_GETBLKSIZE: -++ //return put_user(jz_audio_fragsize / jz_audio_b, (int *)arg); -++ return put_user(jz_audio_fragsize, (int *)arg); -++ case SNDCTL_DSP_GETFMTS: -++ /* Returns a mask of supported sample format*/ -++ return put_user(AFMT_U8 | AFMT_S16_LE, (int *)arg); -++ case SNDCTL_DSP_SETFMT: -++ /* Select sample format */ -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ if (val != AFMT_QUERY) -++ jz_audio_set_format(controller->dev_audio,val); -++ else { -++ if (file->f_mode & FMODE_READ) -++ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -++ else -++ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -++ } -++ -++ return put_user(val, (int *)arg); -++ case SNDCTL_DSP_CHANNELS: -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ jz_audio_set_channels(controller->dev_audio, val); -++ -++ return put_user(val, (int *)arg); -++ case SNDCTL_DSP_POST: -++ /* FIXME: the same as RESET ?? */ -++ return 0; -++ case SNDCTL_DSP_SUBDIVIDE: -++ return 0; -++ case SNDCTL_DSP_SETFRAGMENT: -++ get_user(val, (long *) arg); -++ newfragsize = 1 << (val & 0xFFFF); -++ if (newfragsize < 4 * PAGE_SIZE) -++ newfragsize = 4 * PAGE_SIZE; -++ if (newfragsize > (16 * PAGE_SIZE)) -++ newfragsize = 16 * PAGE_SIZE; -++ -++ newfragstotal = (val >> 16) & 0x7FFF; -++ if (newfragstotal < 2) -++ newfragstotal = 2; -++ if (newfragstotal > 32) -++ newfragstotal = 32; -++ if((jz_audio_fragstotal == newfragstotal) && (jz_audio_fragsize == newfragsize)) -++ return 0; -++ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ mdelay(500); -++ jz_audio_fragstotal = newfragstotal; -++ jz_audio_fragsize = newfragsize; -++ -++ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ mdelay(10); -++ -++ return 0; -++ case SNDCTL_DSP_GETCAPS: -++ return put_user(DSP_CAP_REALTIME|DSP_CAP_BATCH, (int *)arg); -++ case SNDCTL_DSP_NONBLOCK: -++ file->f_flags |= O_NONBLOCK; -++ return 0; -++ case SNDCTL_DSP_SETDUPLEX: -++ return -EINVAL; -++ case SNDCTL_DSP_GETOSPACE: -++ { -++ int i, bytes = 0; -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ jz_audio_fragments = elements_in_queue(&out_empty_queue); -++ for (i = 0; i < jz_audio_fragments; i++) -++ bytes += jz_audio_fragsize; -++ -++ if (jz_audio_channels == 2) -++ bytes /= jz_audio_b; -++ else if (jz_audio_channels == 1) -++ bytes /= 4; -++ else -++ printk("SNDCTL_DSP_GETOSPACE : channels is wrong 1!\n"); -++ -++ -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ /* unused fragment amount */ -++ abinfo.fragments = jz_audio_fragments; -++ /* amount of fragments */ -++ abinfo.fragstotal = jz_audio_fragstotal; -++ /* fragment size in bytes */ -++ if (jz_audio_channels == 2) -++ abinfo.fragsize = jz_audio_fragsize / jz_audio_b; -++ else if (jz_audio_channels == 1) -++ abinfo.fragsize = jz_audio_fragsize / 4; -++ else -++ printk("SNDCTL_DSP_GETOSPACE : channels is wrong 2!\n"); -++ -++ /* write size count without blocking in bytes */ -++ abinfo.bytes = bytes; -++ -++ return copy_to_user((void *)arg, &abinfo, -++ sizeof(abinfo)) ? -EFAULT : 0; -++ } -++ case SNDCTL_DSP_GETISPACE: -++ { -++ int i, bytes = 0; -++ if (!(file->f_mode & FMODE_READ)) -++ return -EINVAL; -++ jz_audio_fragments = elements_in_queue(&in_empty_queue); -++ for (i = 0; i < jz_audio_fragments; i++) -++ bytes += jz_audio_fragsize; -++ -++ if (jz_audio_channels == 2) -++ bytes /= jz_audio_b; -++ else if (jz_audio_channels == 1) -++ bytes /= 4; -++ else -++ printk("SNDCTL_DSP_GETISPACE : channels is wrong 1!\n"); -++ -++ abinfo.fragments = jz_audio_fragments; -++ abinfo.fragstotal = jz_audio_fragstotal; -++ -++ if (jz_audio_channels == 2) -++ abinfo.fragsize = jz_audio_fragsize / jz_audio_b; -++ else if (jz_audio_channels == 1) -++ abinfo.fragsize = jz_audio_fragsize / 4; -++ else -++ printk("SNDCTL_DSP_GETISPACE : channels is wrong 2!\n"); -++ -++ abinfo.bytes = bytes; -++ -++ return copy_to_user((void *)arg, &abinfo, -++ sizeof(abinfo)) ? -EFAULT : 0; -++ } -++ case SNDCTL_DSP_GETTRIGGER: -++ val = 0; -++ if (file->f_mode & FMODE_READ && in_dma_buf) -++ val |= PCM_ENABLE_INPUT; -++ if (file->f_mode & FMODE_WRITE && out_dma_buf) -++ val |= PCM_ENABLE_OUTPUT; -++ -++ return put_user(val, (int *)arg); -++ case SNDCTL_DSP_SETTRIGGER: -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ return 0; -++ case SNDCTL_DSP_GETIPTR: -++ if (!(file->f_mode & FMODE_READ)) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ cinfo.bytes = controller->total_bytes; -++ cinfo.blocks = controller->blocks; -++ cinfo.ptr = controller->nextIn; -++ controller->blocks = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); -++ case SNDCTL_DSP_GETOPTR: -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ cinfo.bytes = controller->total_bytes; -++ cinfo.blocks = controller->blocks; -++ cinfo.ptr = controller->nextOut; -++ controller->blocks = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); -++ case SNDCTL_DSP_GETODELAY: -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ unfinish = 0; -++ fullc = elements_in_queue(&out_full_queue); -++ busyc = elements_in_queue(&out_busy_queue); -++ for(i = 0;i < fullc ;i ++) { -++ id = *(out_full_queue.id + i); -++ unfinish += *(out_dma_buf_data_count + id); -++ } -++ for(i = 0;i < busyc ;i ++) { -++ id = *(out_busy_queue.id + i); -++ unfinish += get_dma_residue(controller->dma1); -++ } -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ if (jz_audio_channels == 2) -++ unfinish /= jz_audio_b; -++ else if (jz_audio_channels == 1) -++ unfinish /= 4; -++ else -++ printk("SNDCTL_DSP_GETODELAY : channels is wrong !\n"); -++ -++ return put_user(unfinish, (int *) arg); -++ case SOUND_PCM_READ_RATE: -++ return put_user(jz_audio_rate, (int *)arg); -++ case SOUND_PCM_READ_CHANNELS: -++ return put_user(jz_audio_channels, (int *)arg); -++ case SOUND_PCM_READ_BITS: -++ return put_user((jz_audio_format & (AFMT_S8 | AFMT_U8)) ? 8 : 16, (int *)arg); -++ case SNDCTL_DSP_MAPINBUF: -++ case SNDCTL_DSP_MAPOUTBUF: -++ case SNDCTL_DSP_SETSYNCRO: -++ case SOUND_PCM_WRITE_FILTER: -++ case SOUND_PCM_READ_FILTER: -++ return -EINVAL; -++ } -++ return -EINVAL; -++} -++ -++ -++static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait) -++{ -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ unsigned long flags; -++ unsigned int mask = 0; -++ -++ if (file->f_mode & FMODE_WRITE) { -++ if (elements_in_queue(&out_empty_queue) > 0) -++ return POLLOUT | POLLWRNORM; -++ -++ poll_wait(file, &controller->dac_wait, wait); -++ } -++ -++ if (file->f_mode & FMODE_READ) { -++ if (elements_in_queue(&in_full_queue) > 0) -++ return POLLIN | POLLRDNORM; -++ -++ poll_wait(file, &controller->adc_wait, wait); -++ } -++ -++ spin_lock_irqsave(&controller->lock, flags); -++ if (file->f_mode & FMODE_WRITE) { -++ if (elements_in_queue(&out_empty_queue) > 0) -++ mask |= POLLOUT | POLLWRNORM; -++ } else if (file->f_mode & FMODE_READ) { -++ if (elements_in_queue(&in_full_queue) > 0) -++ mask |= POLLIN | POLLRDNORM; -++ } -++ spin_unlock_irqrestore(&controller->lock, flags); -++ -++ return mask; -++} -++ -++static ssize_t jz_audio_read(struct file *file, char *buffer, size_t count, loff_t *ppos) -++{ -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ int id, ret = 0, left_count, copy_count, cnt = 0; -++ unsigned long flags; -++ -++ if (count < 0) -++ return -EINVAL; -++ -++ __i2s_enable_receive_dma(); -++ __i2s_enable_record(); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextIn = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ copy_count = jz_audio_fragsize / 4; -++ -++ left_count = count; -++ if (first_record_call) { -++ first_record_call = 0; -++ audio_read_back_first: -++ if ((id = get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id); -++ spin_lock(&controller->lock); -++ *(in_dma_buf_data_count + id) = copy_count * 4; -++ -++ spin_unlock(&controller->lock); -++ __i2s_enable_receive_dma(); -++ __i2s_enable_record(); -++ dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); -++ audio_start_dma(controller->dma2,file->private_data, -++ *(in_dma_pbuf + id), -++ *(in_dma_buf_data_count + id), -++ DMA_MODE_READ); -++ sleep_on(&rx_wait_queue); -++ } else -++ goto audio_read_back_first; -++ } -++ -++ while (left_count > 0) { -++ audio_read_back_second: -++ if (elements_in_queue(&in_full_queue) <= 0) { -++ if (file->f_flags & O_NONBLOCK) -++ return ret ? ret : -EAGAIN; -++ else -++ sleep_on(&rx_wait_queue); -++ } -++ -++ if ((id = get_buffer_id(&in_full_queue)) >= 0) { -++ spin_lock(&controller->lock); -++ cnt = record_filler((unsigned long)controller->tmp2+ret, copy_count, id); -++ spin_unlock(&controller->lock); -++ put_buffer_id(&in_empty_queue, id); -++ } else -++ goto audio_read_back_second; -++ -++ if (elements_in_queue(&in_busy_queue) == 0) { -++ if ((id=get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id); -++ spin_lock(&controller->lock); -++ *(in_dma_buf_data_count + id) = copy_count * 4; -++ spin_unlock(&controller->lock); -++ -++ dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); -++ audio_start_dma(controller->dma2,file->private_data, -++ *(in_dma_pbuf + id), -++ *(in_dma_buf_data_count + id), -++ DMA_MODE_READ); -++ } -++ } -++ if (ret + cnt > count) { -++ spin_lock(&controller->lock); -++ cnt = count - ret; -++ spin_unlock(&controller->lock); -++ } -++ if (copy_to_user(buffer+ret, controller->tmp2+ret, cnt)) -++ return ret ? ret : -EFAULT; -++ -++ spin_lock(&controller->lock); -++ ret += cnt; -++ spin_unlock(&controller->lock); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextIn += ret; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ spin_lock(&controller->lock); -++ left_count -= cnt; -++ spin_unlock(&controller->lock); -++ } -++ return ret; -++} -++ -++static ssize_t jz_audio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) -++{ -++ int id, ret = 0, left_count, copy_count = 0; -++ unsigned int flags; -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ -++ if (count <= 0) -++ return -EINVAL; -++ -++ if(set_replay_hp_or_speaker) -++ set_replay_hp_or_speaker(); -++ -++ __i2s_enable_transmit_dma(); -++ __i2s_enable_replay(); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextOut = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ if (jz_audio_channels == 2) -++ copy_count = jz_audio_fragsize / jz_audio_b; -++ else if(jz_audio_channels == 1) -++ copy_count = jz_audio_fragsize / 4; -++ left_count = count; -++ if (copy_from_user(controller->tmp1, buffer, count)) { -++ printk("copy_from_user failed:%d",ret); -++ return ret ? ret : -EFAULT; -++ } -++ -++ while (left_count > 0) { -++ audio_write_back: -++ /*if (file->f_flags & O_NONBLOCK) -++ udelay(2);*/ -++ if (elements_in_queue(&out_empty_queue) == 0) { -++ if (file->f_flags & O_NONBLOCK) -++ return ret; -++ else -++ sleep_on(&tx_wait_queue); -++ } -++ /* the end fragment size in this write */ -++ if (ret + copy_count > count) -++ copy_count = count - ret; -++ if ((id = get_buffer_id(&out_empty_queue)) >= 0) { -++ replay_filler((signed long)controller->tmp1 + ret, copy_count, id); -++ if(*(out_dma_buf_data_count + id) > 0) { -++ put_buffer_id(&out_full_queue, id); -++ dma_cache_wback_inv(*(out_dma_buf + id), -++ *(out_dma_buf_data_count + id)); -++ } else -++ put_buffer_id(&out_empty_queue, id); -++ } else -++ goto audio_write_back; -++ -++ left_count = left_count - copy_count; -++ ret += copy_count; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextOut += ret; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ if (elements_in_queue(&out_busy_queue) == 0) { -++ if ((id=get_buffer_id(&out_full_queue)) >= 0) { -++ put_buffer_id(&out_busy_queue, id); -++ -++ if(*(out_dma_buf_data_count + id) > 0) { -++ audio_start_dma(controller->dma1, -++ file->private_data, -++ *(out_dma_pbuf + id), -++ *(out_dma_buf_data_count + id), -++ DMA_MODE_WRITE); -++ last_dma_buffer_id = id; -++ if (jz_codec_config == 0) { -++ write_codec_file_bit(1, 0, 5); -++ gain_up_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //gain_up_end = jiffies; -++ jz_codec_config = 1; -++ //SB_ADC->1 -++ //write_codec_file_bit(5, 1, 4); -++ //while(1); -++ } -++ } -++ } -++ } -++ } -++ -++ return ret; -++} -++ -++#if defined(CONFIG_I2S_ICODEC) -++static void write_mute_to_dma_buffer(signed long l_sample, signed long r_sample) -++{ -++ int i,step_len; -++ unsigned long *pop_buf = (unsigned long*)pop_turn_onoff_buf; -++ unsigned int sample_oss = (REG_AIC_CR & 0x00380000) >> 19; -++ unsigned long l_sample_count,r_sample_count,sample_count; -++ struct jz_i2s_controller_info *controller = i2s_controller; -++ signed int left_sam=0,right_sam=0,l_val,r_val; -++ -++ switch (sample_oss) { -++ case 0x0: -++ break; -++ case 0x1: -++ left_sam = (signed int)l_sample; -++ right_sam = (signed int)r_sample; -++ break; -++ case 0x2: -++ break; -++ case 0x3: -++ break; -++ case 0x4: -++ break; -++ } -++ -++ if(left_sam == 0 && right_sam == 0) -++ return; -++ -++ switch (sample_oss) { -++ case 0x0: -++ break; -++ case 0x1: -++ step_len = jz_audio_speed / 10 * 3; -++ step_len = step_len / 2; -++ step_len = 0x7fff / step_len + 1; -++ -++ l_sample_count = 0; -++ l_val = left_sam; -++ -++ while(1) { -++ if(l_val > 0) { -++ if(l_val >= step_len) { -++ l_val -= step_len; -++ l_sample_count ++; -++ } else -++ break; -++ } -++ -++ if(l_val < 0) { -++ if(l_val <= -step_len) { -++ l_val += step_len; -++ l_sample_count ++; -++ } else -++ break; -++ } -++ -++ if(l_val == 0) -++ break; -++ } -++ -++ r_sample_count = 0; -++ r_val = right_sam; -++ while(1) { -++ if(r_val > 0) { -++ if(r_val >= step_len) { -++ r_val -= step_len; -++ r_sample_count ++; -++ } else -++ break; -++ } -++ -++ if(r_val < 0) { -++ if(r_val <= -step_len) { -++ r_val += step_len; -++ r_sample_count ++; -++ } else -++ break; -++ } -++ -++ if(r_val == 0) -++ break; -++ } -++ /* fill up */ -++ if(l_sample_count > r_sample_count) -++ sample_count = l_sample_count; -++ else -++ sample_count = r_sample_count; -++ -++ l_val = left_sam; -++ r_val = right_sam; -++ for(i=0;i <= sample_count;i++) { -++ -++ *pop_buf = (unsigned long)l_val; -++ pop_buf ++; -++ -++ if(l_val > step_len) -++ l_val -= step_len; -++ else if(l_val < -step_len) -++ l_val += step_len; -++ else if(l_val >= -step_len && l_val <= step_len) -++ l_val = 0; -++ -++ *pop_buf = (unsigned long)r_val; -++ pop_buf ++; -++ if(r_val > step_len) -++ r_val -= step_len; -++ else if(r_val < -step_len) -++ r_val += step_len; -++ else if(r_val >= -step_len && r_val <= step_len) -++ r_val = 0; -++ } -++ -++ *pop_buf = 0; -++ pop_buf ++; -++ *pop_buf = 0; -++ -++ pop_buf ++; -++ sample_count += 2; -++ dma_cache_wback_inv(pop_turn_onoff_buf, sample_count*8); -++ -++ pop_dma_flag = 1; -++ audio_start_dma(controller->dma1,controller,pop_turn_onoff_pbuf,sample_count*8,DMA_MODE_WRITE); -++ sleep_on(&pop_wait_queue); -++ pop_dma_flag = 0; -++ break; -++ case 0x2: -++ break; -++ case 0x3: -++ break; -++ case 0x4: -++ break; -++ } -++} -++#endif -+diff -urN linux-2.6.24.7.old/sound/oss/jz_i2s_dlv_dma_test.c linux-2.6.24.7/sound/oss/jz_i2s_dlv_dma_test.c -+--- linux-2.6.24.7.old/sound/oss/jz_i2s_dlv_dma_test.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/oss/jz_i2s_dlv_dma_test.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,2808 @@ -++/* -++ * linux/drivers/sound/jz_i2s_dlv.c -++ * -++ * JzSOC On-Chip I2S audio driver. -++ * -++ * Copyright (C) 2005 by Junzheng Corp. -++ * Modified by cjfeng on Aug 9,2007,and not any bug on Jz4730 using -++ * dma channel 4&3,noah is tested. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ * Because the normal application of AUDIO devices are focused on Little_endian, -++ * then we only perform the little endian data format in driver. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "sound_config.h" -++ -++#define DPRINTK(args...) printk(args) -++#define DMA_ID_I2S_TX DMA_ID_AIC_TX -++#define DMA_ID_I2S_RX DMA_ID_AIC_RX -++ -++#define NR_I2S 2 -++#define MAXDELAY 50000 -++#define JZCODEC_RW_BUFFER_SIZE 3 -++#define JZCODEC_RW_BUFFER_TOTAL 3 -++#define JZCODEC_USER_BUFFER 6 -++ -++#define USE_NONE 1 -++#define USE_MIC 2 -++#define USE_LINEIN 3 -++ -++static int jz_audio_rate; -++static char jz_audio_format; -++static char jz_audio_volume; -++static char jz_audio_channels; -++static int jz_audio_b; /* bits expand multiple */ -++static int jz_audio_fragments;//unused fragment amount -++static int jz_audio_fragstotal; -++static int jz_audio_fragsize; -++static int jz_audio_speed; -++static int audio_mix_modcnt; -++static int codec_volue_shift; -++static int jz_audio_dma_tran_count;//bytes count of one DMA transfer -++static int jz_mic_only = 1; -++static int jz_codec_config = 0; -++static int use_mic_line_flag; -++static unsigned long ramp_up_start; -++static unsigned long ramp_up_end; -++static unsigned long gain_up_start; -++static unsigned long gain_up_end; -++static unsigned long ramp_down_start; -++static unsigned long ramp_down_end; -++static unsigned long gain_down_start; -++static unsigned long gain_down_end; -++ -++ -++static void jz_update_filler(int bits, int channels); -++static int Init_In_Out_queue(int fragstotal,int fragsize); -++static int Free_In_Out_queue(int fragstotal,int fragsize); -++static irqreturn_t jz_i2s_replay_dma_irq(int irqnr, void *ref); -++static irqreturn_t jz_i2s_record_dma_irq(int irqnr, void *ref); -++static void (*replay_filler)(signed long src_start, int count, int id); -++static int (*record_filler)(unsigned long dst_start, int count, int id); -++static void jz_audio_reset(void); -++ -++static struct file_operations jz_i2s_audio_fops; -++ -++static DECLARE_WAIT_QUEUE_HEAD (rx_wait_queue); -++static DECLARE_WAIT_QUEUE_HEAD (tx_wait_queue); -++static DECLARE_WAIT_QUEUE_HEAD (pop_wait_queue); -++ -++struct jz_i2s_controller_info -++{ -++ int io_base; -++ int dma1; /* play */ -++ int dma2; /* record */ -++ char *name; -++ int dev_audio; -++ struct i2s_codec *i2s_codec[NR_I2S]; -++ int opened1; -++ int opened2; -++ unsigned char *tmp1; /* tmp buffer for sample conversions */ -++ unsigned char *tmp2; -++ spinlock_t lock; -++ spinlock_t ioctllock; -++ -++ wait_queue_head_t dac_wait; -++ wait_queue_head_t adc_wait; -++ int nextIn; // byte index to next-in to DMA buffer -++ int nextOut; // byte index to next-out from DMA buffer -++ int count; // current byte count in DMA buffer -++ int finish; // current transfered byte count in DMA buffer -++ unsigned total_bytes; // total bytes written or read -++ unsigned blocks; -++ unsigned error; // over/underrun -++#ifdef CONFIG_PM -++ struct pm_dev *pm; -++#endif -++}; -++ -++ -++static struct jz_i2s_controller_info *i2s_controller = NULL; -++struct i2s_codec -++{ -++ /* I2S controller connected with */ -++ void *private_data; -++ char *name; -++ int id; -++ int dev_mixer; -++ /* controller specific lower leverl i2s accessing routines */ -++ u16 (*codec_read) (u8 reg);//the function accessing Codec REGs fcj add -++ void (*codec_write) (u8 reg, u16 val);//to AK4642EN,val is 8bit -++ /* Wait for codec-ready. Ok to sleep here. */ -++ void (*codec_wait) (struct i2s_codec *codec); -++ /* OSS mixer masks */ -++ int modcnt; -++ int supported_mixers; -++ int stereo_mixers; -++ int record_sources; -++ int bit_resolution; -++ /* OSS mixer interface */ -++ int (*read_mixer) (struct i2s_codec *codec, int oss_channel); -++ void (*write_mixer)(struct i2s_codec *codec, int oss_channel, -++ unsigned int left, unsigned int right); -++ int (*recmask_io) (struct i2s_codec *codec, int rw, int mask); -++ int (*mixer_ioctl)(struct i2s_codec *codec, unsigned int cmd, unsigned long arg); -++ /* saved OSS mixer states */ -++ unsigned int mixer_state[SOUND_MIXER_NRDEVICES]; -++}; -++ -++ -++typedef struct buffer_queue_s -++{ -++ int count; -++ int *id; -++ int lock; -++} buffer_queue_t; -++ -++typedef struct left_right_sample_s -++{ -++ signed long left; -++ signed long right; -++} left_right_sample_t; -++ -++typedef struct hpvol_shift_s -++{ -++ int hpvol; -++ int shift; -++} hpvol_shift_t; -++ -++static unsigned long *out_dma_buf = NULL; -++static unsigned long *out_dma_pbuf = NULL; -++static unsigned long *out_dma_buf_data_count = NULL; -++static unsigned long *in_dma_buf = NULL; -++static unsigned long *in_dma_pbuf = NULL; -++static unsigned long *in_dma_buf_data_count = NULL; -++ -++static buffer_queue_t out_empty_queue; -++static buffer_queue_t out_full_queue; -++static buffer_queue_t out_busy_queue; -++static buffer_queue_t in_empty_queue; -++static buffer_queue_t in_full_queue; -++static buffer_queue_t in_busy_queue; -++static int first_record_call = 0; -++ -++static int read_codec_file(int addr) -++{ -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ mdelay(1); -++ return(__icdc_get_value()); -++} -++ -++static void printk_codec_files(void) -++{ -++ int cnt; -++ -++ printk("\n"); -++ -++ printk("REG_CPM_I2SCDR=0x%08x\n",REG_CPM_I2SCDR); -++ printk("REG_CPM_CLKGR=0x%08x\n",REG_CPM_CLKGR); -++ printk("REG_CPM_CPCCR=0x%08x\n",REG_CPM_CPCCR); -++ printk("REG_AIC_FR=0x%08x\n",REG_AIC_FR); -++ printk("REG_AIC_CR=0x%08x\n",REG_AIC_CR); -++ printk("REG_AIC_I2SCR=0x%08x\n",REG_AIC_I2SCR); -++ printk("REG_AIC_SR=0x%08x\n",REG_AIC_SR); -++ printk("REG_ICDC_RGDATA=0x%08x\n",REG_ICDC_RGDATA); -++ -++ for (cnt = 0; cnt <= 27 ; cnt++) { -++ printk(" ( %d : 0x%x ) ",cnt ,read_codec_file(cnt)); -++ } -++ printk("\n"); -++} -++ -++static void write_codec_file(int addr, int val) -++{ -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ __icdc_set_cmd(val); /* write */ -++ mdelay(1); -++ __icdc_set_rgwr(); -++ mdelay(1); -++} -++ -++static int write_codec_file_bit(int addr, int bitval, int mask_bit) -++{ -++ int val; -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ mdelay(1); -++ val = __icdc_get_value(); /* read */ -++ -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ val &= ~(1 << mask_bit); -++ if (bitval == 1) -++ val |= 1 << mask_bit; -++ -++ __icdc_set_cmd(val); /* write */ -++ mdelay(1); -++ __icdc_set_rgwr(); -++ mdelay(1); -++ -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ val = __icdc_get_value(); /* read */ -++ -++ if (((val >> mask_bit) & bitval) == bitval) -++ return 1; -++ else -++ return 0; -++} -++ -++/* set Audio data replay */ -++static void set_audio_data_replay() -++{ -++ /* DAC path */ -++ write_codec_file(9, 0xff); -++ //write_codec_file(8, 0x30); -++ write_codec_file(8, 0x20); -++ mdelay(10); -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -++ -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ //mdelay(100); -++ //write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //mdelay(300); -++} -++ -++/* unset Audio data replay */ -++static void unset_audio_data_replay(void) -++{ -++ //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ //mdelay(800); -++ //write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ //mdelay(800); -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ write_codec_file_bit(5, 1, 4);//SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++ -++/* set Record MIC input audio without playback */ -++static void set_record_mic_input_audio_without_playback(void) -++{ -++ /* ADC path for MIC IN */ -++ jz_mic_only = 1; -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ mdelay(10); -++ write_codec_file_bit(1, 1, 2); -++ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -++ -++ write_codec_file(22, 0x40);//mic 1 -++ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -++ //write_codec_file_bit(6, 1, 3);// gain set -++ -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ mdelay(100); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ write_codec_file(1, 0x4); -++} -++ -++/* unset Record MIC input audio without playback */ -++static void unset_record_mic_input_audio_without_playback(void) -++{ -++ /* ADC path for MIC IN */ -++ jz_mic_only = 0; -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -++ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++ -++/* set Record LINE input audio without playback */ -++static void set_record_line_input_audio_without_playback(void) -++{ -++ /* ADC path for LINE IN */ -++ jz_mic_only = 1; -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ mdelay(10); -++ write_codec_file(22, 0xf6);//line in 1 -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -++ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -++ mdelay(10); -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ mdelay(100); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ write_codec_file(1, 0x4); -++} -++ -++/* unset Record LINE input audio without playback */ -++static void unset_record_line_input_audio_without_playback(void) -++{ -++ /* ADC path for LINE IN */ -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(5, 1, 3);//ONR1.SB_LIN->1 -++ -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -++ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++ -++/* set Playback LINE input audio direct only */ -++static void set_playback_line_input_audio_direct_only() -++{ -++ jz_audio_reset();//or init_codec() -++ REG_AIC_I2SCR = 0x10; -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ mdelay(10); -++ write_codec_file(22, 0xf6);//line in 1 -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ mdelay(10); -++ write_codec_file_bit(1, 1, 2);//CR1.HP_BYPASS->1 -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -++ -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ mdelay(100); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ //write_codec_file_bit(5, 1, 7);//PMR1.SB_DAC->1 -++ //write_codec_file_bit(5, 1, 4);//PMR1.SB_ADC->1 -++} -++ -++/* unset Playback LINE input audio direct only */ -++static void unset_playback_line_input_audio_direct_only() -++{ -++ write_codec_file_bit(6, 0, 3);//GIM->0 -++ write_codec_file_bit(1, 0, 2);//PMR1.BYPASS->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LINE->1 -++ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -++ mdelay(100); -++ write_codec_file_bit(5, 1, 5);//PMR1.SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++ -++/* set Record MIC input audio with direct playback */ -++static void set_record_mic_input_audio_with_direct_playback(void) -++{ -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ jz_mic_only = 0; -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ mdelay(10); -++ -++ write_codec_file(22, 0x60);//mic 1 -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -++ write_codec_file_bit(6, 1, 3);// gain set -++ -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ mdelay(100); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ //write_codec_file(1, 0x4); -++} -++ -++/* unset Record MIC input audio with direct playback */ -++static void unset_record_mic_input_audio_with_direct_playback(void) -++{ -++ /* ADC path for MIC IN */ -++ jz_mic_only = 0; -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -++ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++ -++/* set Record playing audio mixed with MIC input audio */ -++static void set_record_playing_audio_mixed_with_mic_input_audio(void) -++{ -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file(9, 0xff); -++ //write_codec_file(8, 0x30); -++ write_codec_file(8, 0x20); -++ mdelay(10); -++ -++ write_codec_file(22, 0x63);//mic 1 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(6, 1, 3);// gain set -++ -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -++ write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 -++ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ write_codec_file_bit(5, 0, 4);//PMR1.SB_MIX->0 -++} -++ -++/* unset Record playing audio mixed with MIC input audio */ -++static void unset_record_playing_audio_mixed_with_mic_input_audio(void) -++{ -++ /* ADC path */ -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -++ //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ //write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++ -++/* set Record MIC input audio with Audio data replay (full duplex) */ -++static void set_record_mic_input_audio_with_audio_data_replay(void) -++{ -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file(9, 0xff); -++ //write_codec_file(8, 0x30); -++ write_codec_file(8, 0x20); -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ -++ write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 -++ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -++ -++ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++} -++ -++/* unset Record MIC input audio with Audio data replay (full duplex) */ -++static void unset_record_mic_input_audio_with_audio_data_replay(void) -++{ -++ /* ADC path */ -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++ -++///////// -++/* set Record LINE input audio with Audio data replay (full duplex for linein) */ -++static void set_record_line_input_audio_with_audio_data_replay(void) -++{ -++ write_codec_file(9, 0xff); -++ //write_codec_file(8, 0x30); -++ write_codec_file(8, 0x20); -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //write_codec_file_bit(22, 1, 7);//CR3.SB_MIC->1 -++ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ -++ -++ //jz_mic_only = 1; -++ write_codec_file(22, 0xc6);//line in 1 -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++} -++ -++/* unset Record LINE input audio with Audio data replay (full duplex for linein) */ -++static void unset_record_line_input_audio_with_audio_data_replay(void) -++{ -++ /* ADC path */ -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++///////// -++ -++static inline int get_buffer_id(struct buffer_queue_s *q) -++{ -++ int r; -++ unsigned long flags; -++ int i; -++ spin_lock_irqsave(&q->lock, flags); -++ //spin_lock(&q->lock); -++ if (q->count == 0) { -++ spin_unlock_irqrestore(&q->lock, flags); -++ //spin_unlock(&q->lock); -++ return -1; -++ } -++ r = *(q->id + 0); -++ for (i=0;i < q->count-1;i++) -++ *(q->id + i) = *(q->id + (i+1)); -++ q->count --; -++ spin_unlock_irqrestore(&q->lock, flags); -++ //spin_unlock(&q->lock); -++ return r; -++} -++ -++static inline void put_buffer_id(struct buffer_queue_s *q, int id) -++{ -++ unsigned long flags; -++ spin_lock_irqsave(&q->lock, flags); -++ //spin_lock(&q->lock); -++ *(q->id + q->count) = id; -++ q->count ++; -++ spin_unlock_irqrestore(&q->lock, flags); -++ //spin_unlock(&q->lock); -++} -++ -++static inline int elements_in_queue(struct buffer_queue_s *q) -++{ -++ int r; -++ unsigned long flags; -++ spin_lock_irqsave(&q->lock, flags); -++ //spin_lock(&q->lock); -++ r = q->count; -++ spin_unlock_irqrestore(&q->lock, flags); -++ //spin_unlock(&q->lock); -++ return r; -++} -++ -++static inline void audio_start_dma(int chan, void *dev_id, unsigned long phyaddr,int count, int mode) -++{ -++ unsigned long flags; -++ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -++ //for DSP_GETOPTR -++ //spin_lock_irqsave(&controller->ioctllock, flags); -++ spin_lock(&controller->ioctllock); -++ jz_audio_dma_tran_count = count; -++ //spin_unlock_irqrestore(&controller->ioctllock, flags); -++ spin_unlock(&controller->ioctllock); -++ flags = claim_dma_lock(); -++ //__dmac_disable_module(0); -++ disable_dma(chan); -++ clear_dma_ff(chan); -++ -++ set_dma_mode(chan, mode); -++ set_dma_addr(chan, phyaddr); -++ if (count == 0) -++ { -++ count++; -++ printk("JzSOC DMA controller can't set dma 0 count!\n"); -++ } -++ -++ set_dma_count(chan, count); -++ enable_dma(chan); -++ //__dmac_enable_module(0); -++ release_dma_lock(flags); -++ //dump_jz_dma_channel(chan); -++ -++ //printk_codec_files(); -++} -++ -++static irqreturn_t jz_i2s_record_dma_irq (int irq, void *dev_id) -++{ -++ int id1, id2; -++ -++ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -++ int dma = controller->dma2; -++ -++ disable_dma(dma); -++ if (__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if (__dmac_channel_transmit_end_detected(dma)) { -++ __dmac_channel_clear_transmit_end(dma); -++ //for DSP_GETIPTR -++ //spin_lock_irqsave(&controller->ioctllock, flags); -++ spin_lock(&controller->ioctllock); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ //spin_unlock_irqrestore(&controller->ioctllock, flags); -++ spin_unlock(&controller->ioctllock); -++ id1 = get_buffer_id(&in_busy_queue); -++ put_buffer_id(&in_full_queue, id1); -++ -++ wake_up(&rx_wait_queue); -++ wake_up(&controller->adc_wait); -++ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id2); -++ *(in_dma_buf_data_count + id2) = *(in_dma_buf_data_count + id1); -++ //write back -++ dma_cache_wback_inv(*(in_dma_buf + id2), *(in_dma_buf_data_count + id2)); -++ audio_start_dma(dma,dev_id, -++ *(in_dma_pbuf + id2), -++ *(in_dma_buf_data_count + id2), -++ DMA_MODE_READ); -++ } -++ else -++ in_busy_queue.count = 0; -++ } -++ return IRQ_HANDLED; -++ -++} -++ -++static irqreturn_t jz_i2s_replay_dma_irq (int irq, void *dev_id) -++{ -++ int id; -++ unsigned long flags; -++ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -++ int dma = controller->dma1; -++ disable_dma(dma); -++ -++ if (__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if (__dmac_channel_transmit_end_detected(dma)) { -++ __dmac_channel_clear_transmit_end(dma); -++ -++ -++ //for DSP_GETOPTR -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ //spin_lock(&controller->ioctllock); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ //spin_unlock(&controller->ioctllock); -++ if ((id = get_buffer_id(&out_busy_queue)) < 0) -++ printk(KERN_DEBUG "Strange DMA finish interrupt for I2S module\n"); -++ put_buffer_id(&out_empty_queue, id); -++ if ((id = get_buffer_id(&out_full_queue)) >= 0) { -++ put_buffer_id(&out_busy_queue, id); //very busy -++ if(*(out_dma_buf_data_count + id) > 0) { -++ audio_start_dma(dma, dev_id, *(out_dma_pbuf + id), -++ *(out_dma_buf_data_count + id), -++ DMA_MODE_WRITE); -++ } -++ } else -++ out_busy_queue.count = 0; -++ -++ if (elements_in_queue(&out_empty_queue) > 0) { -++ wake_up(&tx_wait_queue); -++ wake_up(&controller->dac_wait); -++ } -++ } -++ return IRQ_HANDLED; -++} -++ -++static void jz_i2s_initHw(int set) -++{ -++ __i2s_disable(); -++ //schedule_timeout(5); -++ -++#if defined(CONFIG_I2S_DLV) -++ __i2s_disable(); -++ __i2s_as_slave(); -++ __aic_internal_codec(); -++ //__i2s_set_oss_sample_size(16); -++ //__i2s_set_iss_sample_size(16); -++ -++#endif -++ __i2s_disable_record(); -++ __i2s_disable_replay(); -++ __i2s_disable_loopback(); -++ __i2s_set_transmit_trigger(7); -++ __i2s_set_receive_trigger(8); -++} -++ -++static int Init_In_Out_queue(int fragstotal,int fragsize) -++{ -++ int i; -++ // recording -++ in_empty_queue.count = fragstotal; -++ in_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_buf) -++ goto all_mem_err; -++ in_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_pbuf) -++ goto all_mem_err; -++ in_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_buf_data_count) -++ goto all_mem_err; -++ in_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_empty_queue.id) -++ goto all_mem_err; -++ in_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_full_queue.id) -++ goto all_mem_err; -++ in_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_busy_queue.id) -++ goto all_mem_err; -++ -++ for (i=0;i < fragstotal;i++) -++ *(in_empty_queue.id + i) = i; -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ -++ for (i = 0; i < fragstotal; i++) { -++ *(in_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -++ if (*(in_dma_buf + i) == 0) -++ goto mem_failed_in; -++ *(in_dma_pbuf + i) = virt_to_phys((void *)(*(in_dma_buf + i))); -++ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -++ } -++ -++ //playing -++ out_empty_queue.count = fragstotal; -++ out_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!out_dma_buf) -++ goto all_mem_err; -++ out_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!out_dma_pbuf) -++ goto all_mem_err; -++ out_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ -++ if (!out_dma_buf_data_count) -++ goto all_mem_err; -++ out_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_empty_queue.id) -++ goto all_mem_err; -++ out_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_full_queue.id) -++ goto all_mem_err; -++ out_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_busy_queue.id) -++ goto all_mem_err; -++ for (i=0;i < fragstotal;i++) -++ *(out_empty_queue.id + i) = i; -++ -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ /*alloc DMA buffer*/ -++ for (i = 0; i < fragstotal; i++) { -++ *(out_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -++ if (*(out_dma_buf + i) == 0) { -++ printk(" can't allocate required DMA(OUT) buffers.\n"); -++ goto mem_failed_out; -++ } -++ *(out_dma_pbuf + i) = virt_to_phys((void *)(*(out_dma_buf + i))); -++ } -++ -++ return 1; -++all_mem_err: -++ printk("error:allocate memory occur error 1!\n"); -++ return 0; -++mem_failed_out: -++ printk("error:allocate memory occur error 2!\n"); -++ for (i = 0; i < fragstotal; i++) { -++ if(*(out_dma_buf + i)) -++ free_pages(*(out_dma_buf + i), get_order(fragsize)); -++ } -++ -++ return 0; -++mem_failed_in: -++ printk("error:allocate memory occur error 3!\n"); -++ for (i = 0; i < fragstotal; i++) { -++ if(*(in_dma_buf + i)) -++ free_pages(*(in_dma_buf + i), get_order(fragsize)); -++ } -++ return 0; -++} -++ -++static int Free_In_Out_queue(int fragstotal,int fragsize) -++{ -++ int i; -++ //playing -++ if(out_dma_buf != NULL) { -++ for (i = 0; i < fragstotal; i++) { -++ if(*(out_dma_buf + i)) -++ free_pages(*(out_dma_buf + i), get_order(fragsize)); -++ *(out_dma_buf + i) = 0; //release page error -++ } -++ kfree(out_dma_buf); -++ out_dma_buf = NULL; -++ } -++ if(out_dma_pbuf) { -++ kfree(out_dma_pbuf); -++ out_dma_pbuf = NULL; -++ } -++ if(out_dma_buf_data_count) { -++ kfree(out_dma_buf_data_count); -++ out_dma_buf_data_count = NULL; -++ } -++ if(out_empty_queue.id) { -++ kfree(out_empty_queue.id); -++ out_empty_queue.id = NULL; -++ } -++ if(out_full_queue.id) { -++ kfree(out_full_queue.id); -++ out_full_queue.id = NULL; -++ } -++ if(out_busy_queue.id) { -++ kfree(out_busy_queue.id); -++ out_busy_queue.id = NULL; -++ } -++ out_empty_queue.count = fragstotal; -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ -++ // recording -++ if(in_dma_buf) { -++ for (i = 0; i < fragstotal; i++) { -++ if(*(in_dma_buf + i)) { -++ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -++ free_pages(*(in_dma_buf + i), get_order(fragsize)); -++ } -++ *(in_dma_buf + i) = 0; //release page error -++ } -++ kfree(in_dma_buf); -++ in_dma_buf = NULL; -++ } -++ if(in_dma_pbuf) { -++ kfree(in_dma_pbuf); -++ in_dma_pbuf = NULL; -++ } -++ if(in_dma_buf_data_count) { -++ kfree(in_dma_buf_data_count); -++ in_dma_buf_data_count = NULL; -++ } -++ if(in_empty_queue.id) { -++ kfree(in_empty_queue.id); -++ in_empty_queue.id = NULL; -++ } -++ if(in_full_queue.id) { -++ kfree(in_full_queue.id); -++ in_full_queue.id = NULL; -++ } -++ if(in_busy_queue.id) { -++ kfree(in_busy_queue.id); -++ in_busy_queue.id = NULL; -++ } -++ -++ in_empty_queue.count = fragstotal; -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ -++ return 1; -++} -++ -++static void jz_i2s_full_reset(struct jz_i2s_controller_info *controller) -++{ -++ jz_i2s_initHw(0); -++} -++ -++static int jz_audio_set_speed(int dev, int rate) -++{ -++ /* 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999 ? */ -++ int speed = 0, val; -++ -++ jz_audio_speed = rate; -++ if (rate > 96000) -++ rate = 96000; -++ if (rate < 8000) -++ rate = 8000; -++ jz_audio_rate = rate; -++ -++#if defined(CONFIG_I2S_DLV) -++ speed = 0; -++ switch (rate) { -++ case 8000: -++ speed = 10; -++ break; -++ case 9600: -++ speed = 9; -++ break; -++ case 11025: -++ speed = 8; -++ break; -++ case 12000: -++ speed = 7; -++ break; -++ case 16000: -++ speed = 6; -++ break; -++ case 22050: -++ speed = 5; -++ break; -++ case 24000: -++ speed = 4; -++ break; -++ case 32000: -++ speed = 3; -++ break; -++ case 44100: -++ speed = 2; -++ break; -++ case 48000: -++ speed = 1; -++ break; -++ case 96000: -++ speed = 0; -++ break; -++ default: -++ break; -++ } -++ -++ val = read_codec_file(4); -++ val = (speed << 4) | speed; -++ write_codec_file(4, val); -++ -++#if 0 -++ for (i = 0; i <= 27 ; i++) { -++ printk(" ( CCC %d : 0x%x ) ",i ,read_codec_file(i)); -++ } -++#endif -++ -++#endif -++ return jz_audio_rate; -++} -++ -++static int record_fill_1x8_u(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long data; -++ volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ volatile unsigned char *dp = (unsigned char*)dst_start; -++ while (count > 0) { -++ count -= 2; /* count in dword */ -++ cnt++; -++ data = *(s++); -++ *(dp ++) = ((data << 16) >> 24) + 0x80; -++ s++; /* skip the other channel */ -++ } -++ return cnt; -++} -++ -++static int record_fill_2x8_u(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long d1, d2; -++ volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ volatile unsigned char *dp = (unsigned char*)dst_start; -++ while (count > 0) { -++ count -= 2; -++ cnt += 2; -++ d1 = *(s++); -++ *(dp ++) = ((d1 << 16) >> 24) + 0x80; -++ d2 = *(s++); -++ *(dp ++) = ((d2 << 16) >> 24) + 0x80; -++ } -++ return cnt; -++} -++ -++static int record_fill_1x16_s(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long d1; -++ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ unsigned short *dp = (unsigned short *)dst_start; -++ -++ while (count > 0) { -++ count -= 2; /* count in dword */ -++ cnt += 2; /* count in byte */ -++ d1 = *(s++); -++ *(dp ++) = (d1 << 16) >> 16; -++ s++; /* skip the other channel */ -++ } -++ return cnt; -++} -++ -++ -++static int record_fill_2x16_s(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long d1, d2; -++ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ unsigned short *dp = (unsigned short *)dst_start; -++ -++ while (count > 0) { -++ count -= 2; /* count in dword */ -++ cnt += 4; /* count in byte */ -++ d1 = *(s++); -++ *(dp ++) = (d1 << 16) >> 16; -++ d2 = *(s++); -++ *(dp ++) = (d2 << 16) >> 16; -++ } -++ return cnt; -++} -++ -++static int record_fill_2x24_s(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long d1, d2; -++ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ unsigned short *dp = (unsigned short *)dst_start; -++ -++ while (count > 0) { -++ count -= 4; /* count in dword */ -++ cnt += 4; /* count in byte */ -++ d1 = *(s++); -++ *(dp ++) = (d1 << 24) >> 24; -++ d2 = *(s++); -++ *(dp ++) = (d2 << 24) >> 24; -++ } -++ //printk("--- rec 24 ---\n"); -++ return cnt; -++} -++ -++static void replay_fill_1x8_u(unsigned long src_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned char data; -++ unsigned long ddata; -++ volatile unsigned char *s = (unsigned char *)src_start; -++ volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); -++ while (count > 0) { -++ count--; -++ cnt += 1; -++ data = *(s++) - 0x80; -++ ddata = (unsigned long) data << 8; -++ *(dp ++) = ddata; -++ *(dp ++) = ddata; -++ } -++ cnt = cnt * 2 * jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++static void replay_fill_2x8_u(unsigned long src_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned char d1; -++ unsigned long dd1; -++ volatile unsigned char *s = (unsigned char *)src_start; -++ volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); -++ while (count > 0) { -++ count -= 1; -++ cnt += 1 ; -++ d1 = *(s++) - 0x80; -++ dd1 = (unsigned long) d1 << 8; -++ *(dp ++) = dd1; -++ } -++ cnt *= jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++static void replay_fill_1x16_s(signed long src_start, int count, int id) -++{ -++ int cnt = 0; -++ signed short d1; -++ signed long l1; -++ volatile signed short *s = (signed short *)src_start; -++ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -++ -++ while (count > 0) { -++ count -= 2; -++ cnt += 2 ; -++ d1 = *(s++); -++ l1 = (unsigned long)d1; -++ *(dp ++) = l1; -++ *(dp ++) = l1; -++ } -++ cnt = cnt * 2 * jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++static void replay_fill_2x16_s(signed long src_start, int count, int id) -++{ -++ int cnt = 0; -++ signed short d1; -++ signed long l1; -++ volatile signed short *s = (signed short *)src_start; -++ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -++ -++ while (count > 0) { -++ count -= 2; -++ cnt += 2; -++ d1 = *(s++); -++ -++ l1 = (signed long)d1; -++ -++ *(dp ++) = l1; -++ } -++ -++ cnt *= jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++static unsigned int jz_audio_set_format(int dev, unsigned int fmt) -++{ -++ switch (fmt) { -++ case AFMT_U8: -++ __i2s_set_oss_sample_size(8); -++ __i2s_set_iss_sample_size(8); -++ jz_audio_format = fmt; -++ jz_update_filler(jz_audio_format, jz_audio_channels); -++ break; -++ case AFMT_S16_LE: -++ /* DAC path and ADC path */ -++ write_codec_file(2, 0x00); -++ //write_codec_file(2, 0x60); -++ -++ jz_audio_format = fmt; -++ jz_update_filler(jz_audio_format, jz_audio_channels); -++ -++ /* print all files */ -++ __i2s_set_oss_sample_size(16); -++ __i2s_set_iss_sample_size(16); -++ break; -++ case 18: -++ /* DAC path and ADC path */ -++ write_codec_file(2, 0x28); -++ //write_codec_file(2, 0x60); -++ __i2s_set_oss_sample_size(18); -++ __i2s_set_iss_sample_size(16); -++ jz_audio_format = fmt; -++ jz_update_filler(jz_audio_format,jz_audio_channels); -++ break; -++ case 24: -++ /* DAC path and ADC path */ -++ write_codec_file(2, 0x78); -++ //write_codec_file(2, 0x60); -++ __i2s_set_oss_sample_size(24); -++ __i2s_set_iss_sample_size(24); -++ jz_audio_format = fmt; -++ jz_update_filler(jz_audio_format,jz_audio_channels); -++ break; -++ case AFMT_QUERY: -++ break; -++ } -++ return jz_audio_format; -++} -++ -++static short jz_audio_set_channels(int dev, short channels) -++{ -++ switch (channels) { -++ case 1: -++ /* print all files */ -++ jz_audio_channels = channels; -++ jz_update_filler(jz_audio_format, jz_audio_channels); -++ write_codec_file_bit(1, 1, 6);//CR1.MONO->1 for Mono -++ break; -++ case 2: -++ /* print all files */ -++ jz_audio_channels = channels; -++ jz_update_filler(jz_audio_format, jz_audio_channels); -++ write_codec_file_bit(1, 0, 6);//CR1.MONO->0 for Stereo -++ break; -++ case 0: -++ break; -++ } -++ return jz_audio_channels; -++} -++ -++static void init_codec(void) -++{ -++#if defined(CONFIG_I2S_DLV) -++ /* reset DLV codec. from hibernate mode to sleep mode */ -++ write_codec_file(0, 0xf); -++ write_codec_file_bit(6, 0, 0); -++ write_codec_file_bit(6, 0, 1); -++ mdelay(200); -++ //write_codec_file(0, 0xf); -++ write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0 -++ write_codec_file_bit(5, 0, 4);//PMR1.SB_ADC->0 -++ mdelay(10);//wait for stability -++#endif -++} -++ -++static void jz_audio_reset(void) -++{ -++ __i2s_disable_replay(); -++ __i2s_disable_receive_dma(); -++ __i2s_disable_record(); -++ __i2s_disable_transmit_dma(); -++ REG_AIC_I2SCR = 0x10; -++ init_codec(); -++} -++ -++static int jz_audio_release(struct inode *inode, struct file *file); -++static int jz_audio_open(struct inode *inode, struct file *file); -++static int jz_audio_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg); -++static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait); -++static ssize_t jz_audio_write(struct file *file, const char *buffer,size_t count, loff_t *ppos); -++static ssize_t jz_audio_read(struct file *file, char *buffer,size_t count, loff_t *ppos); -++/* static struct file_operations jz_i2s_audio_fops */ -++static struct file_operations jz_i2s_audio_fops = -++{ -++ owner: THIS_MODULE, -++ open: jz_audio_open, -++ release: jz_audio_release, -++ write: jz_audio_write, -++ read: jz_audio_read, -++ poll: jz_audio_poll, -++ ioctl: jz_audio_ioctl -++}; -++ -++static int jz_i2s_open_mixdev(struct inode *inode, struct file *file) -++{ -++ int i; -++ int minor = MINOR(inode->i_rdev); -++ struct jz_i2s_controller_info *controller = i2s_controller; -++ -++ for (i = 0; i < NR_I2S; i++) -++ if (controller->i2s_codec[i] != NULL && controller->i2s_codec[i]->dev_mixer == minor) -++ goto match; -++ -++ if (!controller) -++ return -ENODEV; -++match: -++ file->private_data = controller->i2s_codec[i]; -++ return 0; -++} -++ -++static int jz_i2s_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -++{ -++ struct i2s_codec *codec = (struct i2s_codec *)file->private_data; -++ return codec->mixer_ioctl(codec, cmd, arg); -++} -++ -++static loff_t jz_i2s_llseek(struct file *file, loff_t offset, int origin) -++{ -++ return -ESPIPE; -++} -++ -++static struct file_operations jz_i2s_mixer_fops = -++{ -++ owner: THIS_MODULE, -++ llseek: jz_i2s_llseek, -++ ioctl: jz_i2s_ioctl_mixdev, -++ open: jz_i2s_open_mixdev, -++}; -++ -++static int i2s_mixer_ioctl(struct i2s_codec *codec, unsigned int cmd, unsigned long arg) -++{ -++ int ret; -++ u8 cur_vol; -++ long val = 0; -++ -++ switch (cmd) { -++ case SOUND_MIXER_INFO: -++ { -++ mixer_info info; -++#if defined(CONFIG_I2S_DLV) -++ strncpy(info.id, "DLV", sizeof(info.id)); -++ strncpy(info.name,"Jz4750 internal codec", sizeof(info.name)); -++#endif -++ -++ info.modify_counter = audio_mix_modcnt; -++ return copy_to_user((void *)arg, &info, sizeof(info)); -++ } -++ case SOUND_OLD_MIXER_INFO: -++ { -++ _old_mixer_info info; -++#if defined(CONFIG_I2S_DLV) -++ strncpy(info.id, "DLV", sizeof(info.id)); -++ strncpy(info.name,"Jz4750 internal codec", sizeof(info.name)); -++#endif -++ -++ return copy_to_user((void *)arg, &info, sizeof(info)); -++ } -++ case SOUND_MIXER_READ_STEREODEVS: -++ return put_user(0, (long *) arg); -++ case SOUND_MIXER_READ_CAPS: -++ val = SOUND_CAP_EXCL_INPUT; -++ return put_user(val, (long *) arg); -++ case SOUND_MIXER_READ_DEVMASK: -++ break; -++ case SOUND_MIXER_READ_RECMASK: -++ break; -++ case SOUND_MIXER_READ_RECSRC: -++ break; -++ case SOUND_MIXER_WRITE_SPEAKER: -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val > 100) -++ val = 100; -++ -++ REG_CPM_I2SCDR = val; -++ printk_codec_files(); -++ break; -++ case SOUND_MIXER_WRITE_BASS: -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val > 100) -++ val = 100; -++#if defined(CONFIG_I2S_DLV) -++#endif -++ return 0; -++ -++ case SOUND_MIXER_READ_BASS: -++#if defined(CONFIG_I2S_DLV) -++#endif -++ return put_user(val, (long *) arg); -++ -++ case SOUND_MIXER_WRITE_VOLUME: -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val == 100) { -++ //REG_CPM_CLKGR |= 0x60; -++ printk("gate clock : 0x%08x\n", REG_CPM_CLKGR); -++ return 100; -++ } -++ if(val == 99) { -++ REG_CPM_CLKGR &= ~0x60; -++ return 99; -++ } -++ if(val == 98) { -++ REG_CPM_CPCCR |= 0x80400000; -++ return 98; -++ } -++ if(val == 97) { -++ REG_CPM_CPCCR &= ~0x8000000; -++ REG_CPM_CPCCR |= 0x0040000; -++ return 97; -++ } -++ if(val > 31) -++ val = 31; -++ -++ jz_audio_volume = val; -++ //printk("\njz_audio_volume=%d\n",jz_audio_volume); -++#if defined(CONFIG_I2S_DLV) -++ cur_vol = val; -++ write_codec_file(17, cur_vol | 0xc0); -++ write_codec_file(18, cur_vol); -++#endif -++ return 0; -++ case SOUND_MIXER_READ_VOLUME: -++#if defined(CONFIG_I2S_DLV) -++ val = jz_audio_volume | jz_audio_volume << 8; -++#endif -++ return put_user(val, (long *) arg); -++ case SOUND_MIXER_WRITE_LINE: -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if (val == 100) { -++ printk("Playback LINE input audio direct only is starting...\n"); -++ printk_codec_files(); -++ set_playback_line_input_audio_direct_only(); -++ printk_codec_files(); -++ return 100; -++ } -++ if (val == 99) { -++ printk("Playback LINE input audio direct only is end\n"); -++ unset_playback_line_input_audio_direct_only(); -++ printk_codec_files(); -++ return 99; -++ } -++ -++ if(val > 31) -++ val = 31; -++#if defined(CONFIG_I2S_DLV) -++ use_mic_line_flag = USE_LINEIN; -++ /* set gain */ -++ cur_vol = val; -++ cur_vol &= 0x1f; -++ write_codec_file(11, cur_vol);//GO1L -++ write_codec_file(12, cur_vol);//GO1R -++#endif -++ return 0; -++ break; -++ case SOUND_MIXER_WRITE_MIC: -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ -++ if(val > 0xf) -++ val = 0xf; -++#if defined(CONFIG_I2S_DLV) -++ use_mic_line_flag = USE_MIC; -++ /* set gain */ -++ //write_codec_file_bit(6, 1, 3);//GIM -++ cur_vol = val; -++ cur_vol |= cur_vol << 4; -++ write_codec_file(19, cur_vol);//GIL,GIR -++#endif -++ return 0; -++ -++ case SOUND_MIXER_READ_MIC: -++#if defined(CONFIG_I2S_DLV) -++#endif -++ -++ return put_user(val, (long *) arg); -++ default: -++ return -ENOSYS; -++ } -++ audio_mix_modcnt ++; -++ -++ return 0; -++} -++ -++int i2s_probe_codec(struct i2s_codec *codec) -++{ -++ /* generic OSS to I2S wrapper */ -++ codec->mixer_ioctl = i2s_mixer_ioctl; -++ return 1; -++} -++ -++ -++/* I2S codec initialisation. */ -++static int __init jz_i2s_codec_init(struct jz_i2s_controller_info *controller) -++{ -++ int num_i2s = 0; -++ struct i2s_codec *codec; -++ -++ for (num_i2s = 0; num_i2s < NR_I2S; num_i2s++) { -++ if ((codec = kmalloc(sizeof(struct i2s_codec),GFP_KERNEL)) == NULL) -++ return -ENOMEM; -++ memset(codec, 0, sizeof(struct i2s_codec)); -++ codec->private_data = controller; -++ codec->id = num_i2s; -++ -++ if (i2s_probe_codec(codec) == 0) -++ break; -++ if ((codec->dev_mixer = register_sound_mixer(&jz_i2s_mixer_fops, -1)) < 0) { -++ printk(KERN_ERR "Jz I2S: couldn't register mixer!\n"); -++ kfree(codec); -++ break; -++ } -++ controller->i2s_codec[num_i2s] = codec; -++ } -++ return num_i2s; -++} -++ -++static void replay_fill_2x18_s(unsigned long src_start, int count, int id) -++{ -++ int cnt = 0; -++ signed long d1; -++ signed long l1; -++ volatile signed long *s = (signed long *)src_start; -++ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -++ while (count > 0) { -++ count -= 4; -++ cnt += 4; -++ d1 = *(s++); -++ l1 = (signed long)d1; -++ *(dp ++) = l1; -++ } -++ -++ cnt *= jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++static void replay_fill_2x24_s(unsigned long src_start, int count, int id) -++{ -++ int cnt = 0; -++ signed long d1; -++ signed long l1; -++ volatile signed long *s = (signed long *)src_start; -++ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -++ while (count > 0) { -++ count -= 4; -++ cnt += 4; -++ d1 = *(s++); -++ l1 = (signed long)d1; -++ *(dp ++) = l1; -++ } -++ -++ cnt *= jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++ //printk("--- play 24 ---\n"); -++} -++ -++static void jz_update_filler(int format, int channels) -++{ -++ #define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3)) -++ -++ switch (TYPE(format, channels)) -++ { -++ default: -++ case TYPE(AFMT_U8, 1): -++ jz_audio_b = 4;//4bytes * 8bits =32bits -++ replay_filler = replay_fill_1x8_u; -++ record_filler = record_fill_1x8_u; -++ break; -++ case TYPE(AFMT_U8, 2): -++ jz_audio_b = 4; -++ replay_filler = replay_fill_2x8_u; -++ record_filler = record_fill_2x8_u; -++ break; -++ case TYPE(AFMT_S16_LE, 1): -++ //2bytes * 16bits =32bits -++ jz_audio_b = 2; -++ replay_filler = replay_fill_1x16_s; -++ record_filler = record_fill_1x16_s; -++ break; -++ case TYPE(AFMT_S16_LE, 2): -++ jz_audio_b = 2; -++ replay_filler = replay_fill_2x16_s; -++ record_filler = record_fill_2x16_s; -++ break; -++ case TYPE(18, 2): -++ jz_audio_b = 1; -++ replay_filler = replay_fill_2x18_s; -++ record_filler = record_fill_2x16_s; -++ break; -++ case TYPE(24, 2): -++ jz_audio_b = 1; -++ replay_filler = replay_fill_2x24_s; -++ record_filler = record_fill_2x24_s; -++ //printk("--- 24 ---\n"); -++ break; -++ } -++} -++ -++ -++#ifdef CONFIG_PROC_FS -++extern struct proc_dir_entry *proc_jz_root; -++ -++int i2s_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) -++{ -++ return 0; -++} -++ -++static int jz_i2s_init_proc(struct jz_i2s_controller_info *controller) -++{ -++ if (!create_proc_read_entry ("i2s", 0, proc_jz_root, i2s_read_proc, controller->i2s_codec[0])) -++ return -EIO; -++ return 0; -++} -++ -++static void jz_i2s_cleanup_proc(struct jz_i2s_controller_info *controller) -++{ -++ ; -++} -++#endif -++ -++static void __init attach_jz_i2s(struct jz_i2s_controller_info *controller) -++{ -++ char *name; -++ int adev;//No of Audio device. -++ name = controller->name; -++ jz_i2s_initHw(1);//initialize AIC controller and reset it -++ /* register /dev/audio */ -++ adev = register_sound_dsp(&jz_i2s_audio_fops, -1); -++ if (adev < 0) -++ goto audio_failed; -++ /* initialize I2S codec and register /dev/mixer */ -++ if (jz_i2s_codec_init(controller) <= 0) -++ goto mixer_failed; -++ -++#ifdef CONFIG_PROC_FS -++ if (jz_i2s_init_proc(controller) < 0) { -++ printk(KERN_ERR "%s: can't create I2S proc filesystem.\n", name); -++ goto proc_failed; -++ } -++#endif -++ -++ controller->tmp1 = (void *)__get_free_pages(GFP_KERNEL, JZCODEC_USER_BUFFER); -++ if (!controller->tmp1) { -++ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -++ goto tmp1_failed; -++ } -++ -++ controller->tmp2 = (void *)__get_free_pages(GFP_KERNEL, JZCODEC_USER_BUFFER); -++ if (!controller->tmp2) { -++ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -++ goto tmp2_failed; -++ } -++ -++ if ((controller->dma1 = jz_request_dma(DMA_ID_I2S_TX, "audio dac", jz_i2s_replay_dma_irq, IRQF_DISABLED, controller)) < 0) { -++ printk(KERN_ERR "%s: can't reqeust DMA DAC channel.\n", name); -++ goto dma1_failed; -++ } -++ if ((controller->dma2 = jz_request_dma(DMA_ID_I2S_RX, "audio adc", jz_i2s_record_dma_irq, IRQF_DISABLED, controller)) < 0) { -++ printk(KERN_ERR "%s: can't reqeust DMA ADC channel.\n", name); -++ goto dma2_failed; -++ } -++ printk("JzSOC On-Chip I2S controller registered (DAC: DMA(play):%d/IRQ%d,\n ADC: DMA(record):%d/IRQ%d)\n", controller->dma1, get_dma_done_irq(controller->dma1), controller->dma2, get_dma_done_irq(controller->dma2)); -++ -++ controller->dev_audio = adev; -++ -++ return; -++dma2_failed: -++ jz_free_dma(controller->dma2); -++dma1_failed: -++ jz_free_dma(controller->dma1); -++ free_pages((unsigned long)controller->tmp2, JZCODEC_USER_BUFFER); -++tmp2_failed: -++tmp1_failed: -++ free_pages((unsigned long)controller->tmp1, JZCODEC_USER_BUFFER); -++ -++#ifdef CONFIG_PROC_FS -++ jz_i2s_cleanup_proc(controller); -++#endif -++proc_failed: -++ /* unregister mixer dev */ -++mixer_failed: -++ unregister_sound_dsp(adev); -++audio_failed: -++ return; -++} -++ -++ -++static int __init probe_jz_i2s(struct jz_i2s_controller_info **controller) -++{ -++ if ((*controller = kmalloc(sizeof(struct jz_i2s_controller_info), -++ GFP_KERNEL)) == NULL) { -++ printk(KERN_ERR "Jz I2S Controller: out of memory.\n"); -++ return -ENOMEM; -++ } -++ (*controller)->name = "Jz I2S controller"; -++ (*controller)->opened1 = 0; -++ (*controller)->opened2 = 0; -++ init_waitqueue_head(&(*controller)->adc_wait); -++ init_waitqueue_head(&(*controller)->dac_wait); -++ spin_lock_init(&(*controller)->lock); -++ init_waitqueue_head(&rx_wait_queue); -++ init_waitqueue_head(&tx_wait_queue); -++ init_waitqueue_head(&pop_wait_queue); -++ -++ return 0; -++} -++ -++static void __exit unload_jz_i2s(struct jz_i2s_controller_info *controller) -++{ -++ int adev = controller->dev_audio; -++ jz_i2s_full_reset (controller); -++ controller->dev_audio = -1; -++ -++#ifdef CONFIG_PROC_FS -++ jz_i2s_cleanup_proc(controller); -++#endif -++ -++ jz_free_dma(controller->dma1); -++ jz_free_dma(controller->dma2); -++ free_pages((unsigned long)controller->tmp1, JZCODEC_USER_BUFFER); -++ free_pages((unsigned long)controller->tmp2, JZCODEC_USER_BUFFER); -++ if (adev >= 0) { -++ //unregister_sound_mixer(audio_devs[adev]->mixer_dev); -++ unregister_sound_dsp(controller->dev_audio); -++ } -++} -++ -++ -++#ifdef CONFIG_PM -++static int jz_i2s_suspend(struct jz_i2s_controller_info *controller, int state) -++{ -++ return 0; -++} -++ -++static int jz_i2s_resume(struct jz_i2s_controller_info *controller) -++{ -++ return 0; -++} -++ -++static int jz_i2s_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -++{ -++ int ret; -++ struct jz_i2s_controller_info *controller = pm_dev->data; -++ -++ if (!controller) return -EINVAL; -++ -++ switch (req) { -++ case PM_SUSPEND: -++ ret = jz_i2s_suspend(controller, (int)data); -++ break; -++ -++ case PM_RESUME: -++ ret = jz_i2s_resume(controller); -++ break; -++ default: -++ ret = -EINVAL; -++ break; -++ } -++ return ret; -++} -++#endif /* CONFIG_PM */ -++ -++ -++static irqreturn_t aic_codec_irq(int irq, void *dev_id) -++{ -++ u8 file_9 = read_codec_file(9); -++ u8 file_8 = read_codec_file(8); -++ -++ //printk("--- 8:0x%x 9:0x%x ---\n",file_8,file_9); -++ if ((file_9 & 0x1f) == 0x10) { -++ -++ write_codec_file(8, 0x3f); -++ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ mdelay(300); -++ while ((read_codec_file(9) & 0x4) != 0x4); -++ while ((read_codec_file(9) & 0x10) == 0x10) { -++ write_codec_file(9, 0x10); -++ } -++ write_codec_file_bit(5, 0, 6);//SB_OUT->0 -++ mdelay(300); -++ while ((read_codec_file(9) & 0x8) != 0x8); -++ write_codec_file(9, file_9); -++ write_codec_file(8, file_8); -++ -++ return IRQ_HANDLED; -++ } -++ -++ if (file_9 & 0x8) -++ ramp_up_end = jiffies; -++ else if (file_9 & 0x4) -++ ramp_down_end = jiffies; -++ else if (file_9 & 0x2) -++ gain_up_end = jiffies; -++ else if (file_9 & 0x1) -++ gain_down_end = jiffies; -++ -++ write_codec_file(9, file_9); -++ if (file_9 & 0xf) -++ wake_up(&pop_wait_queue); -++ while (REG_ICDC_RGDATA & 0x100); -++ -++ return IRQ_HANDLED; -++} -++ -++static int __init init_jz_i2s(void) -++{ -++ int errno, retval; -++ -++#if defined(CONFIG_I2S_DLV) -++ ramp_up_start = 0; -++ ramp_up_end = 0; -++ gain_up_start = 0; -++ gain_up_end = 0; -++ ramp_down_start = 0; -++ ramp_down_end = 0; -++ gain_down_start = 0; -++ gain_down_end = 0; -++ -++ //REG_CPM_CPCCR &= ~(1 << 31); -++ //REG_CPM_CPCCR &= ~(1 << 30); -++ use_mic_line_flag = USE_NONE; -++ write_codec_file(0, 0xf); -++ -++ REG_AIC_I2SCR = 0x10; -++ __i2s_internal_codec(); -++ __i2s_as_slave(); -++ __i2s_select_i2s(); -++ __aic_select_i2s(); -++ __aic_reset(); -++ mdelay(10); -++ REG_AIC_I2SCR = 0x10; -++ mdelay(20); -++ -++ /* power on DLV */ -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ mdelay(10); -++#endif -++ -++ if ((errno = probe_jz_i2s(&i2s_controller)) < 0) -++ return errno; -++ attach_jz_i2s(i2s_controller); -++#if defined(CONFIG_I2S_DLV) -++ __i2s_disable_transmit_intr(); -++ __i2s_disable_receive_intr(); -++ jz_codec_config = 0; -++ retval = request_irq(IRQ_AIC, aic_codec_irq, IRQF_DISABLED, "aic_codec_irq", NULL); -++ if (retval) { -++ printk("Could not get aic codec irq %d\n", IRQ_AIC); -++ return retval; -++ } -++#endif -++ -++ out_empty_queue.id = NULL; -++ out_full_queue.id = NULL; -++ out_busy_queue.id = NULL; -++ in_empty_queue.id = NULL; -++ in_full_queue.id = NULL; -++ in_busy_queue.id = NULL; -++ -++ jz_audio_fragsize = JZCODEC_RW_BUFFER_SIZE * PAGE_SIZE; -++ jz_audio_fragstotal = JZCODEC_RW_BUFFER_TOTAL ; -++ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ -++#ifdef CONFIG_PM -++ i2s_controller->pm = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, -++ jz_i2s_pm_callback); -++ if (i2s_controller->pm) -++ i2s_controller->pm->data = i2s_controller; -++#endif -++ -++ __cpm_start_idct(); -++ __cpm_start_db(); -++ __cpm_start_me(); -++ __cpm_start_mc(); -++ __cpm_start_ipu(); -++ -++ return 0; -++} -++ -++ -++static void __exit cleanup_jz_i2s(void) -++{ -++ unload_jz_i2s(i2s_controller); -++#if defined(CONFIG_I2S_DLV) -++ free_irq(IRQ_AIC, NULL); -++#endif -++ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++} -++ -++module_init(init_jz_i2s); -++module_exit(cleanup_jz_i2s); -++ -++static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ //DECLARE_WAITQUEUE(wait, current); -++ unsigned long flags; -++ int count,i=0; -++ -++ //add_wait_queue(&ctrl->adc_wait, &wait); -++ for (;;) { -++ if (i < MAXDELAY) { -++ udelay(10); -++ i++; -++ } else -++ break; -++ //set_current_state(TASK_INTERRUPTIBLE); -++ spin_lock_irqsave(&ctrl->lock, flags); -++ //spin_lock(&ctrl->lock); -++ count = get_dma_residue(ctrl->dma2); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ //spin_unlock(&ctrl->lock); -++ if (count <= 0) -++ break; -++ -++ /*if (signal_pending(current)) -++ break;*/ -++ if (nonblock) { -++ //remove_wait_queue(&ctrl->adc_wait, &wait); -++ //current->state = TASK_RUNNING; -++ return -EBUSY; -++ } -++ } -++ //remove_wait_queue(&ctrl->adc_wait, &wait); -++ //current->state = TASK_RUNNING; -++ /*if (signal_pending(current)) -++ return -ERESTARTSYS;*/ -++ return 0; -++} -++static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ unsigned long flags; -++ int count,ele,busyele,emptyele,i=0; -++ -++ for (;;) { -++ if(!nonblock) {//blocked -++ if (i < MAXDELAY) { -++ udelay(10); -++ i++; -++ } else -++ break; -++ -++ ele = elements_in_queue(&out_full_queue); -++ if(ele <= 0) { -++ udelay(200); -++ -++ busyele = elements_in_queue(&out_busy_queue); -++ emptyele = elements_in_queue(&out_empty_queue); -++ if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if (count <= 0) -++ break; -++ } -++ } -++ } else {//non-blocked -++ mdelay(100); -++ ele = elements_in_queue(&out_full_queue); -++ -++ if(ele <= 0) { -++ mdelay(100); -++ busyele = elements_in_queue(&out_busy_queue); -++ emptyele = elements_in_queue(&out_empty_queue); -++ -++ if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if (count <= 0) -++ break; -++ } -++ } -++ } -++ } -++ -++ return 0; -++} -++ -++static void print_pop_duration(void) -++{ -++ long diff; -++#if 0 -++ printk(" ramp_up_start=0x%x\n",ramp_up_start); -++ printk(" ramp_up_end =0x%x\n",ramp_up_end); -++ printk(" gain_up_start=0x%x\n",gain_up_start); -++ printk(" gain_up_end =0x%x\n",gain_up_end); -++ -++ printk("ramp_down_start=0x%x\n",ramp_down_start); -++ printk("ramp_down_end =0x%x\n",ramp_down_end); -++ printk("gain_down_start=0x%x\n",gain_down_start); -++ printk("gain_down_end =0x%x\n",gain_down_end); -++#endif -++ -++ diff = (long)ramp_up_end - (long)ramp_up_start; -++ printk("ramp up duration: %d ms\n",diff * 1000 / HZ); -++ diff = (long)gain_up_end - (long)gain_up_start; -++ printk("gain up duration: %d ms\n",diff * 1000 / HZ); -++ diff = (long)gain_down_end - (long)gain_down_start; -++ printk("gain down duration: %d ms\n",diff); -++ diff = (long)ramp_down_end - (long)ramp_down_start; -++ printk("ramp down duration: %d ms\n",diff * 1000 / HZ); -++} -++ -++static int jz_audio_release(struct inode *inode, struct file *file) -++{ -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ unsigned long tfl; -++ -++ jz_codec_config = 0; -++ if (controller == NULL) -++ return -ENODEV; -++ -++ if (controller->opened1 == 1 && controller->opened2 == 1) { -++ __i2s_enable_transmit_dma(); -++ __i2s_enable_replay(); -++ -++ drain_dac(controller, file->f_flags & O_NONBLOCK); -++ /* wait for fifo empty */ -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ gain_down_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //gain_down_end = jiffies; -++ /*while (1) { -++ tfl = REG_AIC_SR & 0x00003f00; -++ if (tfl == 0) { -++ udelay(500); -++ break; -++ } -++ mdelay(2); -++ }*/ -++ mdelay(100); -++ disable_dma(controller->dma1); -++ set_dma_count(controller->dma1, 0); -++ -++ __i2s_disable_transmit_dma(); -++ __i2s_disable_replay(); -++ -++ //spin_lock_irqsave(&controller->ioctllock, flags); -++ spin_lock(&controller->ioctllock); -++ controller->total_bytes = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->blocks = 0; -++ controller->nextOut = 0; -++ //spin_unlock_irqrestore(&controller->ioctllock, flags); -++ spin_unlock(&controller->ioctllock); -++ -++ ///////////////////////// -++ first_record_call = 1; -++ __i2s_enable_receive_dma(); -++ __i2s_enable_record(); -++ drain_adc(controller, file->f_flags & O_NONBLOCK); -++ disable_dma(controller->dma2); -++ set_dma_count(controller->dma2, 0); -++ __i2s_disable_receive_dma(); -++ __i2s_disable_record(); -++ //__aic_flush_fifo(); -++ //spin_lock_irqsave(&controller->ioctllock, flags); -++ spin_lock(&controller->ioctllock); -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextIn = 0; -++ //spin_unlock_irqrestore(&controller->ioctllock, flags); -++ spin_unlock(&controller->ioctllock); -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ ramp_down_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //ramp_down_end = jiffies; -++ if (use_mic_line_flag == USE_LINEIN) { -++ unset_record_line_input_audio_with_audio_data_replay(); -++ //printk("3 use_mic_line_flag=%d\n",use_mic_line_flag); -++ } -++ if (use_mic_line_flag == USE_MIC) { -++ unset_record_mic_input_audio_with_audio_data_replay(); -++ //printk("4 use_mic_line_flag=%d\n",use_mic_line_flag); -++ } -++ -++#if 0 -++ unset_record_playing_audio_mixed_with_mic_input_audio(); -++#endif -++ __i2s_disable(); -++#endif -++ } else if ( controller->opened1 == 1 ) { -++ __i2s_enable_transmit_dma(); -++ __i2s_enable_replay(); -++ drain_dac(controller, file->f_flags & O_NONBLOCK); -++ /* wait for fifo empty */ -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ gain_down_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //gain_down_end = jiffies; -++ while (1) { -++ tfl = REG_AIC_SR & 0x00003f00; -++ if (tfl == 0) { -++ udelay(500); -++ break; -++ } -++ mdelay(2); -++ } -++ disable_dma(controller->dma1); -++ set_dma_count(controller->dma1, 0); -++ -++ __i2s_disable_transmit_dma(); -++ __i2s_disable_replay(); -++ -++ __aic_flush_fifo(); -++ -++ //spin_lock_irqsave(&controller->ioctllock, flags); -++ spin_lock(&controller->ioctllock); -++ controller->total_bytes = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->blocks = 0; -++ controller->nextOut = 0; -++ //spin_unlock_irqrestore(&controller->ioctllock, flags); -++ spin_unlock(&controller->ioctllock); -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ ramp_down_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //ramp_down_end = jiffies; -++ unset_audio_data_replay(); -++#endif -++ __i2s_disable(); -++ } else if ( controller->opened2 == 1 ) { -++ //controller->opened2 = 0; -++ first_record_call = 1; -++ __i2s_enable_receive_dma(); -++ __i2s_enable_record(); -++ drain_adc(controller, file->f_flags & O_NONBLOCK); -++ disable_dma(controller->dma2); -++ set_dma_count(controller->dma2, 0); -++ __i2s_disable_receive_dma(); -++ __i2s_disable_record(); -++ -++ //spin_lock_irqsave(&controller->ioctllock, flags); -++ spin_lock(&controller->ioctllock); -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextIn = 0; -++ //spin_unlock_irqrestore(&controller->ioctllock, flags); -++ spin_unlock(&controller->ioctllock); -++#if defined(CONFIG_I2S_DLV) -++#if 0 -++ /* unset Record MIC input audio with direct playback */ -++ unset_record_mic_input_audio_with_direct_playback(); -++#endif -++#if 1 -++ /* unset Record MIC input audio without playback */ -++ unset_record_mic_input_audio_without_playback(); -++#endif -++#if 0 -++ /* tested */ -++ /* unset Record LINE input audio without playback */ -++ unset_record_line_input_audio_without_playback(); -++#endif -++#endif -++ __i2s_disable(); -++ } -++ -++ if (controller->opened1 == 1 && controller->opened2 == 1) { -++ controller->opened1 = 0; -++ controller->opened2 = 0; -++ print_pop_duration(); -++ //__dmac_disable_module(0); -++ } else if ( controller->opened1 == 1 ) { -++ controller->opened1 = 0; -++ print_pop_duration(); -++ } else if ( controller->opened2 == 1 ) { -++ controller->opened2 = 0; -++ } -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ -++/* __cpm_stop_idct(); -++ __cpm_stop_db(); -++ __cpm_stop_me(); -++ __cpm_stop_mc(); -++ __cpm_stop_ipu();*/ -++ printk("close audio and clear ipu gate : 0x%08x\n", REG_CPM_CLKGR); -++ return 0; -++} -++ -++static int jz_audio_open(struct inode *inode, struct file *file) -++{ -++ int i; -++ struct jz_i2s_controller_info *controller = i2s_controller; -++ if (controller == NULL) -++ return -ENODEV; -++ mdelay(2); -++ REG_DMAC_DMACKE(0) = 0x3f; -++ if (controller->opened1 == 1 || controller->opened2 == 1 ) { -++ printk("\naudio is busy!\n"); -++ return -EBUSY; -++ } -++ jz_codec_config = 0; -++ -++ ramp_up_start = 0; -++ ramp_up_end = 0; -++ gain_up_start = 0; -++ gain_up_end = 0; -++ ramp_down_start = 0; -++ ramp_down_end = 0; -++ gain_down_start = 0; -++ gain_down_end = 0; -++ -++ if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { -++ if (controller->opened1 == 1) -++ return -EBUSY; -++ controller->opened1 = 1; -++ /* for ioctl */ -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextOut = 0; -++ -++ out_empty_queue.count = jz_audio_fragstotal; -++ for (i=0;i < jz_audio_fragstotal;i++) -++ *(out_empty_queue.id + i) = i; -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ -++ if (controller->opened2 == 1) -++ return -EBUSY; -++ -++ controller->opened2 = 1; -++ first_record_call = 1; -++ /* for ioctl */ -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextIn = 0; -++ -++ in_empty_queue.count = jz_audio_fragstotal; -++ for (i=0;i < jz_audio_fragstotal;i++) -++ *(in_empty_queue.id + i) = i; -++ -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ } else if (file->f_mode & FMODE_WRITE) { -++ if (controller->opened1 == 1) -++ return -EBUSY; -++ controller->opened1 = 1; -++ //for ioctl -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextOut = 0; -++ -++ out_empty_queue.count = jz_audio_fragstotal; -++ for (i=0;i < jz_audio_fragstotal;i++) -++ *(out_empty_queue.id + i) = i; -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ } else if (file->f_mode & FMODE_READ) { -++ if (controller->opened2 == 1) -++ return -EBUSY; -++ -++ controller->opened2 = 1; -++ first_record_call = 1; -++ //for ioctl -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextIn = 0; -++ -++ in_empty_queue.count = jz_audio_fragstotal; -++ for (i=0;i < jz_audio_fragstotal;i++) -++ *(in_empty_queue.id + i) = i; -++ -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ } -++ -++ file->private_data = controller; -++ jz_audio_reset();//11.2 -++ -++ if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { -++#if defined(CONFIG_I2S_DLV) -++ -++ if (use_mic_line_flag == USE_LINEIN) { -++ /* Record LINE input audio with Audio data replay (full duplex for linein) */ -++ /* codec_test_line */ -++ set_record_line_input_audio_with_audio_data_replay(); -++ -++ } -++ if (use_mic_line_flag == USE_MIC) { -++ /* Record MIC input audio with Audio data replay (full duplex) */ -++ /* codec_test_mic */ -++ set_record_mic_input_audio_with_audio_data_replay(); -++ } -++#if 0 -++ /* Record playing audio mixed with MIC input audio */ -++ set_record_playing_audio_mixed_with_mic_input_audio(); -++#endif -++ -++#endif -++ } else if (file->f_mode & FMODE_WRITE) { -++#if defined(CONFIG_I2S_DLV) -++ //mdelay(10); -++ /* Audio data replay */ -++ set_audio_data_replay(); -++#endif -++ } else if (file->f_mode & FMODE_READ) { -++#if defined(CONFIG_I2S_DLV) -++#if 0 -++ /* Record MIC input audio with direct playback */ -++ set_record_mic_input_audio_with_direct_playback(); -++#endif -++ -++#if 1 -++ /* set Record MIC input audio without playback */ -++ set_record_mic_input_audio_without_playback(); -++#endif -++#if 0 -++ /* tested */ -++ /* set Record LINE input audio without playback */ -++ set_record_line_input_audio_without_playback(); -++#endif -++ mdelay(1); -++#endif -++ } -++ -++ __aic_reset(); -++ -++ mdelay(10); -++ REG_AIC_I2SCR = 0x10; -++ mdelay(20); -++ __aic_flush_fifo(); -++ __i2s_enable(); -++ ndelay(100); -++ -++ if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { -++#if defined(CONFIG_I2S_DLV) -++ //set SB_ADC or SB_DAC -++ __dmac_enable_module(0); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ ramp_up_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //ramp_up_end = jiffies; -++#endif -++ } else if (file->f_mode & FMODE_WRITE) { -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ ramp_up_start = jiffies; -++ /*while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_RCR = 0x1; -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_RGR = 1;*/ -++ sleep_on(&pop_wait_queue); -++ //ramp_up_end = jiffies; -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++#endif -++ } else if (file->f_mode & FMODE_READ) { -++#if defined(CONFIG_I2S_DLV) -++ if (jz_mic_only) -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ else -++ write_codec_file_bit(5, 0, 7);//SB_DAC->0 -++ mdelay(500); -++#endif -++ } -++ -++ -++ printk("open audio and set ipu gate : 0x%08x\n", REG_CPM_CLKGR); -++ return 0; -++} -++ -++ -++static int jz_audio_ioctl(struct inode *inode, struct file *file, -++unsigned int cmd, unsigned long arg) -++{ -++ int val,fullc,busyc,unfinish,newfragstotal,newfragsize; -++ unsigned int flags; -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ -++ audio_buf_info abinfo; -++ int i, bytes, id; -++ count_info cinfo; -++ val = 0; -++ bytes = 0; -++ switch (cmd) { -++ case OSS_GETVERSION: -++ return put_user(SOUND_VERSION, (int *)arg); -++ case SNDCTL_DSP_RESET: -++ return 0; -++ case SNDCTL_DSP_SYNC: -++ if (file->f_mode & FMODE_WRITE) -++ drain_dac(controller, file->f_flags & O_NONBLOCK); -++ return 0; -++ case SNDCTL_DSP_SPEED: -++ /* set smaple rate */ -++ { -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ if (val >= 0) -++ jz_audio_set_speed(controller->dev_audio, val); -++ return put_user(val, (int *)arg); -++ } -++ case SNDCTL_DSP_STEREO: -++ /* set stereo or mono channel */ -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ jz_audio_set_channels(controller->dev_audio, val ? 2 : 1); -++ return 0; -++ -++ case SNDCTL_DSP_GETBLKSIZE: -++ //return put_user(4*PAGE_SIZE, (int *)arg); -++ return put_user(jz_audio_fragsize , (int *)arg); -++ case SNDCTL_DSP_GETFMTS: -++ /* Returns a mask of supported sample format*/ -++ return put_user(AFMT_U8 | AFMT_S16_LE, (int *)arg); -++ -++ case SNDCTL_DSP_SETFMT: -++ /* Select sample format */ -++ { -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ if (val != AFMT_QUERY) { -++ jz_audio_set_format(controller->dev_audio,val); -++ } else { -++ if (file->f_mode & FMODE_READ) -++ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -++ else -++ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -++ -++ } -++ return put_user(val, (int *)arg); -++ } -++ -++ case SNDCTL_DSP_CHANNELS: -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ jz_audio_set_channels(controller->dev_audio, val); -++ return put_user(val, (int *)arg); -++ -++ case SNDCTL_DSP_POST: -++ /* FIXME: the same as RESET ?? */ -++ return 0; -++ -++ case SNDCTL_DSP_SUBDIVIDE: -++ return 0; -++ -++ case SNDCTL_DSP_SETFRAGMENT: -++ get_user(val, (long *) arg); -++ newfragsize = 1 << (val & 0xFFFF);//16 least bits -++ -++ if (newfragsize < 4 * PAGE_SIZE) -++ newfragsize = 4 * PAGE_SIZE; -++ if (newfragsize > (16 * PAGE_SIZE)) //16 PAGE_SIZE -++ newfragsize = 16 * PAGE_SIZE; -++ -++ newfragstotal = (val >> 16) & 0x7FFF; -++ if (newfragstotal < 2) -++ newfragstotal = 2; -++ if (newfragstotal > 32) -++ newfragstotal = 32; -++ if((jz_audio_fragstotal == newfragstotal) && (jz_audio_fragsize == newfragsize)) -++ return 0; -++ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ mdelay(500); -++ jz_audio_fragstotal = newfragstotal; -++ jz_audio_fragsize = newfragsize; -++ -++ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ mdelay(10); -++ -++ return 0; -++ case SNDCTL_DSP_GETCAPS: -++ return put_user(DSP_CAP_REALTIME|DSP_CAP_BATCH, (int *)arg); -++ case SNDCTL_DSP_NONBLOCK: -++ file->f_flags |= O_NONBLOCK; -++ return 0; -++ case SNDCTL_DSP_SETDUPLEX: -++ return -EINVAL; -++ case SNDCTL_DSP_GETOSPACE: -++ { -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ -++ //unused fragment amount -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ jz_audio_fragments = elements_in_queue(&out_empty_queue); -++ for (i = 0; i < jz_audio_fragments; i++) -++ bytes += jz_audio_fragsize; -++ bytes /= jz_audio_b; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ abinfo.fragments = jz_audio_fragments; -++ abinfo.fragstotal = jz_audio_fragstotal; -++ abinfo.fragsize = jz_audio_fragsize; -++ abinfo.bytes = bytes; -++ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; -++ } -++ case SNDCTL_DSP_GETISPACE: -++ if (!(file->f_mode & FMODE_READ)) -++ return -EINVAL; -++ -++ bytes = 0; -++ //unused fragment amount -++ jz_audio_fragments = elements_in_queue(&in_empty_queue); -++ for (i = 0; i < jz_audio_fragments; i++) -++ bytes += jz_audio_fragsize; -++ bytes /= jz_audio_b; -++ abinfo.fragments = jz_audio_fragments; -++ abinfo.fragstotal = jz_audio_fragstotal; -++ abinfo.fragsize = jz_audio_fragsize; -++ abinfo.bytes = bytes; -++ return copy_to_user((void *)arg, &abinfo, -++ sizeof(abinfo)) ? -EFAULT : 0; -++ case SNDCTL_DSP_GETTRIGGER: -++ val = 0; -++ if (file->f_mode & FMODE_READ && in_dma_buf) -++ val |= PCM_ENABLE_INPUT; -++ if (file->f_mode & FMODE_WRITE && out_dma_buf) -++ val |= PCM_ENABLE_OUTPUT; -++ return put_user(val, (int *)arg); -++ -++ case SNDCTL_DSP_SETTRIGGER: -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ return 0; -++ case SNDCTL_DSP_GETIPTR: -++ if (!(file->f_mode & FMODE_READ)) -++ return -EINVAL; -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ //controller->total_bytes += get_dma_residue(controller->dma2); -++ cinfo.bytes = controller->total_bytes; -++ cinfo.blocks = controller->blocks; -++ cinfo.ptr = controller->nextIn; -++ controller->blocks = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); -++ case SNDCTL_DSP_GETOPTR: -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ //controller->total_bytes += get_dma_residue(controller->dma1); -++ cinfo.bytes = controller->total_bytes; -++ cinfo.blocks = controller->blocks; -++ cinfo.ptr = controller->nextOut; -++ controller->blocks = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); -++ case SNDCTL_DSP_GETODELAY: -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ unfinish = 0; -++ fullc = elements_in_queue(&out_full_queue); -++ busyc = elements_in_queue(&out_busy_queue); -++ for(i = 0;i < fullc ;i ++) { -++ id = *(out_full_queue.id + i); -++ unfinish += *(out_dma_buf_data_count + id); -++ } -++ for(i = 0;i < busyc ;i ++) { -++ id = *(out_busy_queue.id + i); -++ unfinish += get_dma_residue(controller->dma1); -++ } -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ unfinish /= jz_audio_b; -++ return put_user(unfinish, (int *) arg); -++ case SOUND_PCM_READ_RATE: -++ return put_user(jz_audio_rate, (int *)arg); -++ case SOUND_PCM_READ_CHANNELS: -++ return put_user(jz_audio_channels, (int *)arg); -++ case SOUND_PCM_READ_BITS: -++ return put_user((jz_audio_format & (AFMT_S8 | AFMT_U8)) ? 8 : 16, -++ (int *)arg); -++ case SNDCTL_DSP_MAPINBUF: -++ case SNDCTL_DSP_MAPOUTBUF: -++ case SNDCTL_DSP_SETSYNCRO: -++ case SOUND_PCM_WRITE_FILTER: -++ case SOUND_PCM_READ_FILTER: -++ return -EINVAL; -++ } -++ return -EINVAL; -++} -++ -++ -++static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait) -++{ -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ unsigned long flags; -++ unsigned int mask = 0; -++ -++ if (file->f_mode & FMODE_WRITE) { -++ if (elements_in_queue(&out_empty_queue) > 0) -++ return POLLOUT | POLLWRNORM; -++ poll_wait(file, &controller->dac_wait, wait); -++ } -++ -++ if (file->f_mode & FMODE_READ) { -++ if (elements_in_queue(&in_full_queue) > 0) -++ return POLLIN | POLLRDNORM; -++ poll_wait(file, &controller->adc_wait, wait); -++ } -++ spin_lock_irqsave(&controller->lock, flags); -++ if (file->f_mode & FMODE_WRITE) { -++ if (elements_in_queue(&out_empty_queue) > 0) -++ mask |= POLLOUT | POLLWRNORM; -++ } else if (file->f_mode & FMODE_READ) { -++ if (elements_in_queue(&in_full_queue) > 0) -++ mask |= POLLIN | POLLRDNORM; -++ } -++ spin_unlock_irqrestore(&controller->lock, flags); -++ return mask; -++} -++ -++static ssize_t jz_audio_read(struct file *file, char *buffer, size_t count, loff_t *ppos) -++{ -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ int id, ret = 0, left_count, copy_count, cnt = 0; -++ -++ if (count < 0) -++ return -EINVAL; -++ -++ __i2s_enable_receive_dma(); -++ __i2s_enable_record(); -++ //spin_lock_irqsave(&controller->ioctllock, flags); -++ spin_lock(&controller->ioctllock); -++ controller->nextIn = 0; -++ //spin_unlock_irqrestore(&controller->ioctllock, flags); -++ spin_unlock(&controller->ioctllock); -++ -++ spin_lock(&controller->lock); -++ -++ copy_count = jz_audio_fragsize / 4; -++ -++ left_count = count; -++ spin_unlock(&controller->lock); -++ -++ if (first_record_call) { -++ first_record_call = 0; -++ audio_read_back_first: -++ if ((id = get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id); -++ spin_lock(&controller->lock); -++ *(in_dma_buf_data_count + id) = copy_count * 4; -++ spin_unlock(&controller->lock); -++ __i2s_enable_receive_dma(); -++ __i2s_enable_record(); -++ -++ //write back -++ dma_cache_wback_inv(*(in_dma_buf + id), -++ *(in_dma_buf_data_count + id)); -++ audio_start_dma(controller->dma2,file->private_data, -++ *(in_dma_pbuf + id), -++ *(in_dma_buf_data_count + id), -++ DMA_MODE_READ); -++ //interruptible_sleep_on(&rx_wait_queue); -++ sleep_on(&rx_wait_queue); -++ } else -++ goto audio_read_back_first; -++ } -++ -++ while (left_count > 0) { -++ audio_read_back_second: -++ if (elements_in_queue(&in_full_queue) <= 0) { -++ if (file->f_flags & O_NONBLOCK) -++ return ret ? ret : -EAGAIN; -++ else -++ sleep_on(&rx_wait_queue); -++ } -++ /*if (signal_pending(current)) -++ return ret ? ret: -ERESTARTSYS; */ -++ if ((id = get_buffer_id(&in_full_queue)) >= 0) { -++ spin_lock(&controller->lock); -++ cnt = record_filler((unsigned long)controller->tmp2+ret, -++ copy_count, id); -++ spin_unlock(&controller->lock); -++ put_buffer_id(&in_empty_queue, id); -++ } else -++ goto audio_read_back_second; -++ -++ if (elements_in_queue(&in_busy_queue) == 0) { -++ if ((id=get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id); -++ spin_lock(&controller->lock); -++ *(in_dma_buf_data_count + id) = copy_count * 4; -++ spin_unlock(&controller->lock); -++ //write back -++ dma_cache_wback_inv(*(in_dma_buf + id), -++ *(in_dma_buf_data_count + id)); -++ audio_start_dma(controller->dma2,file->private_data, -++ *(in_dma_pbuf + id), -++ *(in_dma_buf_data_count + id), -++ DMA_MODE_READ); -++ } -++ } -++ if (ret + cnt > count) { -++ spin_lock(&controller->lock); -++ cnt = count - ret; -++ spin_unlock(&controller->lock); -++ } -++ if (copy_to_user(buffer+ret, controller->tmp2+ret, cnt)) -++ return ret ? ret : -EFAULT; -++ spin_lock(&controller->lock); -++ ret += cnt; -++ spin_unlock(&controller->lock); -++ //spin_lock_irqsave(&controller->ioctllock, flags); -++ spin_lock(&controller->ioctllock); -++ controller->nextIn += ret; -++ //spin_unlock_irqrestore(&controller->ioctllock, flags); -++ spin_unlock(&controller->ioctllock); -++ spin_lock(&controller->lock); -++ left_count -= cnt; -++ spin_unlock(&controller->lock); -++ }//while (left_count > 0) -++ return ret; -++} -++ -++static ssize_t jz_audio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) -++{ -++ int id, ret = 0, left_count, copy_count = 0, val; -++ unsigned int flags; -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ -++ if (count <= 0) -++ return -EINVAL; -++ -++ __i2s_enable_transmit_dma(); -++ __i2s_enable_replay(); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ //spin_lock(&controller->ioctllock); -++ controller->nextOut = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ //spin_unlock(&controller->ioctllock); -++ if (jz_audio_channels == 2) -++ copy_count = jz_audio_fragsize / jz_audio_b; -++ else if(jz_audio_channels == 1) -++ copy_count = jz_audio_fragsize / 4; -++ -++ left_count = count; -++ if (copy_from_user(controller->tmp1, buffer, count)) { -++ printk("copy_from_user failed:%d",ret); -++ return ret ? ret : -EFAULT; -++ } -++ -++ while (left_count > 0) { -++ audio_write_back: -++ if (file->f_flags & O_NONBLOCK) -++ udelay(2); -++ if (elements_in_queue(&out_empty_queue) == 0) { -++ // all are full -++ if (file->f_flags & O_NONBLOCK) -++ return ret;//no waiting,no block -++ else { -++ sleep_on(&tx_wait_queue);//blocked -++ } -++ } -++ /*if (signal_pending(current)) -++ return ret ? ret : -ERESTARTSYS;*/ -++ /* the end fragment size in this write */ -++ if (ret + copy_count > count) -++ copy_count = count - ret; -++ if ((id = get_buffer_id(&out_empty_queue)) >= 0) { -++ //replay_filler((unsigned long)controller->tmp1 + ret, copy_count, id); -++ replay_filler((signed long)controller->tmp1 + ret, copy_count, id); -++ if(*(out_dma_buf_data_count + id) > 0) { -++ put_buffer_id(&out_full_queue, id); //busy in -++ dma_cache_wback_inv(*(out_dma_buf + id), -++ *(out_dma_buf_data_count + id)); -++ } else -++ put_buffer_id(&out_empty_queue, id); //spare -++ } else -++ goto audio_write_back; -++ -++ left_count = left_count - copy_count; -++ ret += copy_count; -++ //spin_lock_irqsave(&controller->ioctllock, flags); -++ spin_lock(&controller->ioctllock); -++ controller->nextOut += ret; -++ //spin_unlock_irqrestore(&controller->ioctllock, flags); -++ spin_unlock(&controller->ioctllock); -++ if (elements_in_queue(&out_busy_queue) == 0) { -++ if ((id = get_buffer_id(&out_full_queue)) >= 0) { -++ put_buffer_id(&out_busy_queue, id); //first once,next spare -++ -++ if(*(out_dma_buf_data_count + id) > 0) { -++ audio_start_dma(controller->dma1, -++ file->private_data, -++ *(out_dma_pbuf + id), -++ *(out_dma_buf_data_count + id), -++ DMA_MODE_WRITE); -++ if (jz_codec_config == 0) { -++ write_codec_file_bit(1, 0, 5); -++ gain_up_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //gain_up_end = jiffies; -++ jz_codec_config = 1; -++ //SB_ADC->1 -++ //write_codec_file_bit(5, 1, 4); -++ //while(1); -++ } -++ } -++ } -++ } -++ } -++ return ret; -++} -+diff -urN linux-2.6.24.7.old/sound/oss/jz_i2s_for_4750.c linux-2.6.24.7/sound/oss/jz_i2s_for_4750.c -+--- linux-2.6.24.7.old/sound/oss/jz_i2s_for_4750.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/oss/jz_i2s_for_4750.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,2981 @@ -++/* -++ * linux/drivers/sound/Jz_i2s.c -++ * -++ * JzSOC On-Chip I2S audio driver. -++ * -++ * Copyright (C) 2005 by Junzheng Corp. -++ * Modified by cjfeng on Aug 9,2007,and not any bug on Jz4730 using -++ * dma channel 4&3,noah is tested. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ * Because the normal application of AUDIO devices are focused on Little_endian, -++ * then we only perform the little endian data format in driver. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "sound_config.h" -++ -++#define DPRINTK(args...) printk(args) -++#define DMA_ID_I2S_TX DMA_ID_AIC_TX -++#define DMA_ID_I2S_RX DMA_ID_AIC_RX -++#define NR_I2S 2 -++#define MAXDELAY 50000 -++#define JZCODEC_RW_BUFFER_SIZE 2 -++#define JZCODEC_RW_BUFFER_TOTAL 6 -++ -++typedef struct hpvol_shift_s -++{ -++ int hpvol; -++ int shift; -++} hpvol_shift_t; -++ -++mixer_info info; -++_old_mixer_info old_info; -++int codec_volue_shift; -++hpvol_shift_t hpvol_shift_table[72]; -++int abnormal_data_count; -++unsigned long i2s_clk; -++ -++void (*set_codec_mode)(void) = NULL; -++void (*clear_codec_mode)(void) = NULL; -++void (*set_codec_gpio_pin)(void) = NULL; -++void (*each_time_init_codec)(void) = NULL; -++int (*set_codec_startup_param)(void) = NULL; -++void (*set_codec_volume_table)(void) = NULL; -++void (*set_codec_record)(void) = NULL; -++void (*set_codec_replay)(void) = NULL; -++void (*set_codec_replay_record)(void); -++void (*turn_on_codec)(void) = NULL; -++void (*turn_off_codec)(void) = NULL; -++void (*set_codec_speed)(int rate) = NULL; -++void (*reset_codec)(void) = NULL; -++void (*codec_mixer_old_info_id_name)(void) = NULL; -++void (*codec_mixer_info_id_name)(void) = NULL; -++void (*set_codec_bass)(int val) = NULL; -++void (*set_codec_volume)(int val) = NULL; -++void (*set_codec_mic)(int val) = NULL; -++void (*i2s_resume_codec)(void) = NULL; -++void (*i2s_suspend_codec)(int wr,int rd) = NULL; -++void (*init_codec_pin)(void) = NULL; -++void (*set_codec_some_func)(void) = NULL; -++void (*clear_codec_record)(void) = NULL; -++void (*clear_codec_replay)(void) = NULL; -++void (*set_replay_hp_or_speaker)(void) = NULL; -++void (*set_codec_direct_mode)(void) = NULL; -++void (*clear_codec_direct_mode)(void) = NULL; -++ -++static int jz_audio_rate; -++static int jz_audio_format; -++static int jz_audio_volume; -++static int jz_audio_channels; -++static int jz_audio_b; /* bits expand multiple */ -++static int jz_audio_fragments; /* unused fragment amount */ -++static int jz_audio_fragstotal; -++static int jz_audio_fragsize; -++static int jz_audio_speed; -++ -++static int codec_bass_gain; -++static int audio_mix_modcnt; -++static int jz_audio_dma_tran_count; /* bytes count of one DMA transfer */ -++static int jz_mic_only = 1; -++static int jz_codec_config = 0; -++static unsigned long ramp_up_start; -++static unsigned long ramp_up_end; -++static unsigned long gain_up_start; -++static unsigned long gain_up_end; -++static unsigned long ramp_down_start; -++static unsigned long ramp_down_end; -++static unsigned long gain_down_start; -++static unsigned long gain_down_end; -++ -++static int codec_mic_gain; -++static int pop_dma_flag; -++static int last_dma_buffer_id; -++static int drain_flag; -++ -++static void (*old_mksound)(unsigned int hz, unsigned int ticks); -++extern void (*kd_mksound)(unsigned int hz, unsigned int ticks); -++static void jz_update_filler(int bits, int channels); -++ -++static int Init_In_Out_queue(int fragstotal,int fragsize); -++static int Free_In_Out_queue(int fragstotal,int fragsize); -++static irqreturn_t jz_i2s_replay_dma_irq(int irqnr, void *ref); -++static irqreturn_t jz_i2s_record_dma_irq(int irqnr, void *ref); -++static void (*replay_filler)(signed long src_start, int count, int id); -++static int (*record_filler)(unsigned long dst_start, int count, int id); -++#if defined(CONFIG_I2S_ICODEC) -++static void write_mute_to_dma_buffer(signed long l_sample, signed long r_sample); -++#endif -++static void jz_audio_reset(void); -++static struct file_operations jz_i2s_audio_fops; -++ -++static DECLARE_WAIT_QUEUE_HEAD (rx_wait_queue); -++static DECLARE_WAIT_QUEUE_HEAD (tx_wait_queue); -++static DECLARE_WAIT_QUEUE_HEAD (drain_wait_queue); -++static DECLARE_WAIT_QUEUE_HEAD (pop_wait_queue); -++ -++struct jz_i2s_controller_info -++{ -++ int io_base; -++ int dma1; /* for play */ -++ int dma2; /* for record */ -++ char *name; -++ int dev_audio; -++ struct i2s_codec *i2s_codec[NR_I2S]; -++ int opened1; -++ int opened2; -++ unsigned char *tmp1; /* tmp buffer for sample conversions */ -++ unsigned char *tmp2; -++ spinlock_t lock; -++ spinlock_t ioctllock; -++ -++ wait_queue_head_t dac_wait; -++ wait_queue_head_t adc_wait; -++ int nextIn; /* byte index to next-in to DMA buffer */ -++ int nextOut; /* byte index to next-out from DMA buffer */ -++ int count; /* current byte count in DMA buffer */ -++ int finish; /* current transfered byte count in DMA buffer */ -++ unsigned total_bytes; /* total bytes written or read */ -++ unsigned blocks; -++ unsigned error; /* over/underrun */ -++#ifdef CONFIG_PM -++ struct pm_dev *pm; -++#endif -++}; -++ -++ -++static struct jz_i2s_controller_info *i2s_controller = NULL; -++struct i2s_codec -++{ -++ /* I2S controller connected with */ -++ void *private_data; -++ char *name; -++ int id; -++ int dev_mixer; -++ /* controller specific lower leverl i2s accessing routines */ -++ u16 (*codec_read) (u8 reg); /* the function accessing Codec REGs */ -++ void (*codec_write) (u8 reg, u16 val); -++ /* Wait for codec-ready */ -++ void (*codec_wait) (struct i2s_codec *codec); -++ /* OSS mixer masks */ -++ int modcnt; -++ int supported_mixers; -++ int stereo_mixers; -++ int record_sources; -++ int bit_resolution; -++ /* OSS mixer interface */ -++ int (*read_mixer) (struct i2s_codec *codec, int oss_channel); -++ void (*write_mixer)(struct i2s_codec *codec, int oss_channel, -++ unsigned int left, unsigned int right); -++ int (*recmask_io) (struct i2s_codec *codec, int rw, int mask); -++ int (*mixer_ioctl)(struct i2s_codec *codec, unsigned int cmd, unsigned long arg); -++ /* saved OSS mixer states */ -++ unsigned int mixer_state[SOUND_MIXER_NRDEVICES]; -++}; -++ -++ -++typedef struct buffer_queue_s -++{ -++ int count; -++ int *id; -++ int lock; -++} buffer_queue_t; -++ -++typedef struct left_right_sample_s -++{ -++ signed long left; -++ signed long right; -++} left_right_sample_t; -++ -++static unsigned long pop_turn_onoff_buf; -++static unsigned long pop_turn_onoff_pbuf; -++ -++static unsigned long *out_dma_buf = NULL; -++static unsigned long *out_dma_pbuf = NULL; -++static unsigned long *out_dma_buf_data_count = NULL; -++static unsigned long *in_dma_buf = NULL; -++static unsigned long *in_dma_pbuf = NULL; -++static unsigned long *in_dma_buf_data_count = NULL; -++ -++static buffer_queue_t out_empty_queue; -++static buffer_queue_t out_full_queue; -++static buffer_queue_t out_busy_queue; -++static buffer_queue_t in_empty_queue; -++static buffer_queue_t in_full_queue; -++static buffer_queue_t in_busy_queue; -++static int first_record_call = 0; -++ -++static left_right_sample_t save_last_samples[64]; -++static int read_codec_file(int addr) -++{ -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ mdelay(1); -++ return(__icdc_get_value()); -++} -++ -++static void printk_codec_files(void) -++{ -++ int cnt; -++ -++ printk("\n"); -++ -++ printk("REG_CPM_I2SCDR=0x%08x\n",REG_CPM_I2SCDR); -++ printk("REG_CPM_CLKGR=0x%08x\n",REG_CPM_CLKGR); -++ printk("REG_CPM_CPCCR=0x%08x\n",REG_CPM_CPCCR); -++ printk("REG_AIC_FR=0x%08x\n",REG_AIC_FR); -++ printk("REG_AIC_CR=0x%08x\n",REG_AIC_CR); -++ printk("REG_AIC_I2SCR=0x%08x\n",REG_AIC_I2SCR); -++ printk("REG_AIC_SR=0x%08x\n",REG_AIC_SR); -++ printk("REG_ICDC_RGDATA=0x%08x\n",REG_ICDC_RGDATA); -++ -++ for (cnt = 0; cnt <= 27 ; cnt++) { -++ printk(" ( %d : 0x%x ) ",cnt ,read_codec_file(cnt)); -++ } -++ printk("\n"); -++} -++ -++static void write_codec_file(int addr, int val) -++{ -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ __icdc_set_cmd(val); /* write */ -++ mdelay(1); -++ __icdc_set_rgwr(); -++ mdelay(1); -++} -++ -++static int write_codec_file_bit(int addr, int bitval, int mask_bit) -++{ -++ int val; -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ mdelay(1); -++ val = __icdc_get_value(); /* read */ -++ -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ val &= ~(1 << mask_bit); -++ if (bitval == 1) -++ val |= 1 << mask_bit; -++ -++ __icdc_set_cmd(val); /* write */ -++ mdelay(1); -++ __icdc_set_rgwr(); -++ mdelay(1); -++ -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ val = __icdc_get_value(); /* read */ -++ -++ if (((val >> mask_bit) & bitval) == bitval) -++ return 1; -++ else -++ return 0; -++} -++ -++/* set Audio data replay */ -++static void set_audio_data_replay() -++{ -++ /* DAC path */ -++ write_codec_file(9, 0xff); -++ //write_codec_file(8, 0x30); -++ write_codec_file(8, 0x20); -++ mdelay(10); -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -++ -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ //mdelay(100); -++ //write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //mdelay(300); -++} -++ -++/* unset Audio data replay */ -++static void unset_audio_data_replay(void) -++{ -++ //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ //mdelay(800); -++ //write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ //mdelay(800); -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ write_codec_file_bit(5, 1, 4);//SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++ -++/* set Record MIC input audio without playback */ -++static void set_record_mic_input_audio_without_playback(void) -++{ -++ /* ADC path for MIC IN */ -++ jz_mic_only = 1; -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ mdelay(10); -++ write_codec_file_bit(1, 1, 2); -++ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -++ -++ write_codec_file(22, 0x40);//mic 1 -++ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -++ //write_codec_file_bit(6, 1, 3);// gain set -++ -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ mdelay(100); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ write_codec_file(1, 0x4); -++} -++ -++/* unset Record MIC input audio without playback */ -++static void unset_record_mic_input_audio_without_playback(void) -++{ -++ /* ADC path for MIC IN */ -++ jz_mic_only = 0; -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -++ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++ -++/* set Record LINE input audio without playback */ -++static void set_record_line_input_audio_without_playback(void) -++{ -++ /* ADC path for LINE IN */ -++ jz_mic_only = 1; -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ mdelay(10); -++ write_codec_file(22, 0xf6);//line in 1 -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -++ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -++ mdelay(10); -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ mdelay(100); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ write_codec_file(1, 0x4); -++} -++ -++/* unset Record LINE input audio without playback */ -++static void unset_record_line_input_audio_without_playback(void) -++{ -++ /* ADC path for LINE IN */ -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(5, 1, 3);//ONR1.SB_LIN->1 -++ -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -++ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++ -++/* set Playback LINE input audio direct only */ -++static void set_playback_line_input_audio_direct_only() -++{ -++ jz_audio_reset();//or init_codec() -++ REG_AIC_I2SCR = 0x10; -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ mdelay(10); -++ write_codec_file(22, 0xf6);//line in 1 -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ mdelay(10); -++ write_codec_file_bit(1, 1, 2);//CR1.HP_BYPASS->1 -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -++ -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ mdelay(100); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ //write_codec_file_bit(5, 1, 7);//PMR1.SB_DAC->1 -++ //write_codec_file_bit(5, 1, 4);//PMR1.SB_ADC->1 -++} -++ -++/* unset Playback LINE input audio direct only */ -++static void unset_playback_line_input_audio_direct_only() -++{ -++ write_codec_file_bit(6, 0, 3);//GIM->0 -++ write_codec_file_bit(1, 0, 2);//PMR1.BYPASS->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LINE->1 -++ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -++ mdelay(100); -++ write_codec_file_bit(5, 1, 5);//PMR1.SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++ -++/* set Record MIC input audio with direct playback */ -++static void set_record_mic_input_audio_with_direct_playback(void) -++{ -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ jz_mic_only = 0; -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ mdelay(10); -++ -++ write_codec_file(22, 0x60);//mic 1 -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -++ write_codec_file_bit(6, 1, 3);// gain set -++ -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ mdelay(100); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ //write_codec_file(1, 0x4); -++} -++ -++/* unset Record MIC input audio with direct playback */ -++static void unset_record_mic_input_audio_with_direct_playback(void) -++{ -++ /* ADC path for MIC IN */ -++ jz_mic_only = 0; -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -++ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++ -++/* set Record playing audio mixed with MIC input audio */ -++static void set_record_playing_audio_mixed_with_mic_input_audio(void) -++{ -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file(9, 0xff); -++ //write_codec_file(8, 0x30); -++ write_codec_file(8, 0x20); -++ mdelay(10); -++ -++ write_codec_file(22, 0x63);//mic 1 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(6, 1, 3);// gain set -++ -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -++ write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 -++ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ write_codec_file_bit(5, 0, 4);//PMR1.SB_MIX->0 -++} -++ -++/* unset Record playing audio mixed with MIC input audio */ -++static void unset_record_playing_audio_mixed_with_mic_input_audio(void) -++{ -++ /* ADC path */ -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -++ //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ //write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++ -++/* set Record MIC input audio with Audio data replay (full duplex) */ -++static void set_record_mic_input_audio_with_audio_data_replay(void) -++{ -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file(9, 0xff); -++ //write_codec_file(8, 0x30); -++ write_codec_file(8, 0x20); -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ -++ write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 -++ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -++ -++ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++} -++ -++/* unset Record MIC input audio with Audio data replay (full duplex) */ -++static void unset_record_mic_input_audio_with_audio_data_replay(void) -++{ -++ /* ADC path */ -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++ -++///////// -++/* set Record LINE input audio with Audio data replay (full duplex for linein) */ -++static void set_record_line_input_audio_with_audio_data_replay(void) -++{ -++ write_codec_file(9, 0xff); -++ //write_codec_file(8, 0x30); -++ write_codec_file(8, 0x20); -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //write_codec_file_bit(22, 1, 7);//CR3.SB_MIC->1 -++ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ -++ -++ //jz_mic_only = 1; -++ write_codec_file(22, 0xc6);//line in 1 -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++} -++ -++/* unset Record LINE input audio with Audio data replay (full duplex for linein) */ -++static void unset_record_line_input_audio_with_audio_data_replay(void) -++{ -++ /* ADC path */ -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++///////// -++static inline int get_buffer_id(struct buffer_queue_s *q) -++{ -++ int r; -++ unsigned long flags; -++ int i; -++ -++ spin_lock_irqsave(&q->lock, flags); -++ if (q->count == 0) { -++ spin_unlock_irqrestore(&q->lock, flags); -++ return -1; -++ } -++ r = *(q->id + 0); -++ for (i=0;i < q->count-1;i++) -++ *(q->id + i) = *(q->id + (i+1)); -++ q->count --; -++ spin_unlock_irqrestore(&q->lock, flags); -++ -++ return r; -++} -++ -++static inline void put_buffer_id(struct buffer_queue_s *q, int id) -++{ -++ unsigned long flags; -++ -++ spin_lock_irqsave(&q->lock, flags); -++ *(q->id + q->count) = id; -++ q->count ++; -++ spin_unlock_irqrestore(&q->lock, flags); -++} -++ -++static inline int elements_in_queue(struct buffer_queue_s *q) -++{ -++ int r; -++ unsigned long flags; -++ -++ spin_lock_irqsave(&q->lock, flags); -++ r = q->count; -++ spin_unlock_irqrestore(&q->lock, flags); -++ -++ return r; -++} -++ -++static inline void audio_start_dma(int chan, void *dev_id, unsigned long phyaddr,int count, int mode) -++{ -++ unsigned long flags; -++ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ jz_audio_dma_tran_count = count / jz_audio_b; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ flags = claim_dma_lock(); -++ disable_dma(chan); -++ clear_dma_ff(chan); -++ //set_dma_mode(chan, mode); -++ jz_set_oss_dma(chan, mode, jz_audio_format); -++ set_dma_addr(chan, phyaddr); -++ if (count == 0) { -++ count++; -++ printk("JzSOC DMA controller can't set dma 0 count!\n"); -++ } -++ set_dma_count(chan, count); -++ enable_dma(chan); -++ release_dma_lock(flags); -++} -++ -++static irqreturn_t jz_i2s_record_dma_irq (int irq, void *dev_id) -++{ -++ int id1, id2; -++ unsigned long flags; -++ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -++ int dma = controller->dma2; -++ -++ disable_dma(dma); -++ if (__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if (__dmac_channel_transmit_end_detected(dma)) { -++ __dmac_channel_clear_transmit_end(dma); -++ -++ if(drain_flag == 1) -++ wake_up(&drain_wait_queue); -++ /* for DSP_GETIPTR */ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ id1 = get_buffer_id(&in_busy_queue); -++ put_buffer_id(&in_full_queue, id1); -++ -++ wake_up(&rx_wait_queue); -++ wake_up(&controller->adc_wait); -++ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id2); -++ *(in_dma_buf_data_count + id2) = *(in_dma_buf_data_count + id1); -++ dma_cache_wback_inv(*(in_dma_buf + id2), *(in_dma_buf_data_count + id2)); -++ audio_start_dma(dma,dev_id, -++ *(in_dma_pbuf + id2), -++ *(in_dma_buf_data_count + id2), -++ DMA_MODE_READ); -++ } else -++ in_busy_queue.count = 0; -++ } -++ -++ return IRQ_HANDLED; -++} -++ -++static irqreturn_t jz_i2s_replay_dma_irq (int irq, void *dev_id) -++{ -++ int id; -++ unsigned long flags; -++ struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; -++ int dma = controller->dma1; -++ -++ disable_dma(dma); -++ if (__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if (__dmac_channel_transmit_end_detected(dma)) { -++ __dmac_channel_clear_transmit_end(dma); -++ -++ if(pop_dma_flag == 1) { -++ pop_dma_flag = 0; -++ wake_up(&pop_wait_queue); -++ } else { -++ if(drain_flag == 1) { -++ /* Is replay dma buffer over ? */ -++ if(elements_in_queue(&out_full_queue) <= 0) { -++ drain_flag = 0; -++ wake_up(&drain_wait_queue); -++ } -++ } -++ -++ /* for DSP_GETOPTR */ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ if ((id = get_buffer_id(&out_busy_queue)) < 0) -++ printk(KERN_DEBUG "Strange DMA finish interrupt for I2S module\n"); -++ put_buffer_id(&out_empty_queue, id); -++ if ((id = get_buffer_id(&out_full_queue)) >= 0) { -++ put_buffer_id(&out_busy_queue, id); -++ if(*(out_dma_buf_data_count + id) > 0) { -++ audio_start_dma(dma, dev_id, *(out_dma_pbuf + id), -++ *(out_dma_buf_data_count + id), -++ DMA_MODE_WRITE); -++ last_dma_buffer_id = id; -++ } -++ } else -++ out_busy_queue.count = 0; -++ -++ if (elements_in_queue(&out_empty_queue) > 0) { -++ wake_up(&tx_wait_queue); -++ wake_up(&controller->dac_wait); -++ } -++ } -++ } -++ -++ return IRQ_HANDLED; -++} -++ -++static void jz_i2s_initHw(int set) -++{ -++#if defined(CONFIG_MIPS_JZ_URANUS) -++ i2s_clk = 48000000; -++#else -++ i2s_clk = __cpm_get_i2sclk(); -++#endif -++ __i2s_disable(); -++ if(set) -++ __i2s_reset(); -++ schedule_timeout(5); -++ if(each_time_init_codec) -++ each_time_init_codec(); -++ __i2s_disable_record(); -++ __i2s_disable_replay(); -++ __i2s_disable_loopback(); -++ __i2s_set_transmit_trigger(4); -++ __i2s_set_receive_trigger(3); -++} -++ -++static int Init_In_Out_queue(int fragstotal,int fragsize) -++{ -++ int i; -++ -++ /* recording */ -++ in_empty_queue.count = fragstotal; -++ in_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_buf) -++ goto all_mem_err; -++ in_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_pbuf) -++ goto all_mem_err; -++ in_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_buf_data_count) -++ goto all_mem_err; -++ in_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_empty_queue.id) -++ goto all_mem_err; -++ in_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_full_queue.id) -++ goto all_mem_err; -++ in_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_busy_queue.id) -++ goto all_mem_err; -++ -++ for (i=0;i < fragstotal;i++) -++ *(in_empty_queue.id + i) = i; -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ -++ for (i = 0; i < fragstotal; i++) { -++ *(in_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -++ if (*(in_dma_buf + i) == 0) -++ goto mem_failed_in; -++ *(in_dma_pbuf + i) = virt_to_phys((void *)(*(in_dma_buf + i))); -++ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -++ } -++ -++ /* playing */ -++ out_empty_queue.count = fragstotal; -++ out_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!out_dma_buf) -++ goto all_mem_err; -++ out_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!out_dma_pbuf) -++ goto all_mem_err; -++ out_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ -++ if (!out_dma_buf_data_count) -++ goto all_mem_err; -++ out_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_empty_queue.id) -++ goto all_mem_err; -++ out_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_full_queue.id) -++ goto all_mem_err; -++ out_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_busy_queue.id) -++ goto all_mem_err; -++ for (i=0;i < fragstotal;i++) -++ *(out_empty_queue.id + i) = i; -++ -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ /* alloc DMA buffer */ -++ for (i = 0; i < fragstotal; i++) { -++ *(out_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -++ if (*(out_dma_buf + i) == 0) { -++ printk(" can't allocate required DMA(OUT) buffers.\n"); -++ goto mem_failed_out; -++ } -++ *(out_dma_pbuf + i) = virt_to_phys((void *)(*(out_dma_buf + i))); -++ } -++ -++ return 1; -++all_mem_err: -++ printk("error:allocate memory occur error 1!\n"); -++ return 0; -++mem_failed_out: -++ printk("error:allocate memory occur error 2!\n"); -++ for (i = 0; i < fragstotal; i++) { -++ if(*(out_dma_buf + i)) -++ free_pages(*(out_dma_buf + i), get_order(fragsize)); -++ } -++ -++ return 0; -++mem_failed_in: -++ printk("error:allocate memory occur error 3!\n"); -++ for (i = 0; i < fragstotal; i++) { -++ if(*(in_dma_buf + i)) -++ free_pages(*(in_dma_buf + i), get_order(fragsize)); -++ } -++ return 0; -++} -++ -++static int Free_In_Out_queue(int fragstotal,int fragsize) -++{ -++ int i; -++ /* playing */ -++ if(out_dma_buf != NULL) { -++ for (i = 0; i < fragstotal; i++) { -++ if(*(out_dma_buf + i)) -++ free_pages(*(out_dma_buf + i), get_order(fragsize)); -++ *(out_dma_buf + i) = 0; -++ } -++ kfree(out_dma_buf); -++ out_dma_buf = NULL; -++ } -++ if(out_dma_pbuf) { -++ kfree(out_dma_pbuf); -++ out_dma_pbuf = NULL; -++ } -++ if(out_dma_buf_data_count) { -++ kfree(out_dma_buf_data_count); -++ out_dma_buf_data_count = NULL; -++ } -++ if(out_empty_queue.id) { -++ kfree(out_empty_queue.id); -++ out_empty_queue.id = NULL; -++ } -++ if(out_full_queue.id) { -++ kfree(out_full_queue.id); -++ out_full_queue.id = NULL; -++ } -++ if(out_busy_queue.id) { -++ kfree(out_busy_queue.id); -++ out_busy_queue.id = NULL; -++ } -++ out_empty_queue.count = fragstotal; -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ -++ /* recording */ -++ if(in_dma_buf) { -++ for (i = 0; i < fragstotal; i++) { -++ if(*(in_dma_buf + i)) { -++ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -++ free_pages(*(in_dma_buf + i), get_order(fragsize)); -++ } -++ *(in_dma_buf + i) = 0; -++ } -++ kfree(in_dma_buf); -++ in_dma_buf = NULL; -++ } -++ if(in_dma_pbuf) { -++ kfree(in_dma_pbuf); -++ in_dma_pbuf = NULL; -++ } -++ if(in_dma_buf_data_count) { -++ kfree(in_dma_buf_data_count); -++ in_dma_buf_data_count = NULL; -++ } -++ if(in_empty_queue.id) { -++ kfree(in_empty_queue.id); -++ in_empty_queue.id = NULL; -++ } -++ if(in_full_queue.id) { -++ kfree(in_full_queue.id); -++ in_full_queue.id = NULL; -++ } -++ if(in_busy_queue.id) { -++ kfree(in_busy_queue.id); -++ in_busy_queue.id = NULL; -++ } -++ -++ in_empty_queue.count = fragstotal; -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ -++ return 1; -++} -++ -++static void jz_i2s_full_reset(struct jz_i2s_controller_info *controller) -++{ -++ jz_i2s_initHw(0); -++} -++ -++static int jz_audio_set_speed(int dev, int rate) -++{ -++ /* 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999 ? */ -++ jz_audio_speed = rate; -++ if (rate > 48000) -++ rate = 48000; -++ if (rate < 8000) -++ rate = 8000; -++ jz_audio_rate = rate; -++ -++ if(set_codec_speed) -++ set_codec_speed(rate); -++ -++ return jz_audio_rate; -++} -++ -++ -++static int record_fill_1x8_u(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long data; -++ volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ volatile unsigned char *dp = (unsigned char*)dst_start; -++ -++ while (count > 0) { -++ count -= 2; /* count in dword */ -++ cnt++; -++ data = *(s++); -++ *(dp ++) = ((data << 16) >> 24) + 0x80; -++ s++; /* skip the other channel */ -++ } -++ -++ return cnt; -++} -++ -++ -++static int record_fill_2x8_u(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long d1, d2; -++ volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ volatile unsigned char *dp = (unsigned char*)dst_start; -++ -++ while (count > 0) { -++ count -= 2; -++ cnt += 2; -++ d1 = *(s++); -++ *(dp ++) = ((d1 << 16) >> 24) + 0x80; -++ d2 = *(s++); -++ *(dp ++) = ((d2 << 16) >> 24) + 0x80; -++ } -++ -++ return cnt; -++} -++ -++ -++static int record_fill_1x16_s(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long d1; -++ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ unsigned short *dp = (unsigned short *)dst_start; -++ -++ while (count > 0) { -++ count -= 2; /* count in dword */ -++ cnt += 2; /* count in byte */ -++ d1 = *(s++); -++ *(dp ++) = (d1 << 16) >> 16; -++ s++; /* skip the other channel */ -++ } -++ -++ return cnt; -++} -++ -++ -++static int record_fill_2x16_s(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned long d1, d2; -++ unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); -++ unsigned short *dp = (unsigned short *)dst_start; -++ while (count > 0) { -++ count -= 2; /* count in dword */ -++ cnt += 4; /* count in byte */ -++ d1 = *(s++); -++ d2 = *(s++); -++ if(abnormal_data_count > 0) { -++ d1 = d2 = 0; -++ abnormal_data_count --; -++ } -++ *(dp ++) = (d1 << 16) >> 16; -++ *(dp ++) = (d2 << 16) >> 16; -++ } -++ -++ return cnt; -++} -++ -++static void replay_fill_1x8_u(signed long src_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned char data; -++ unsigned long ddata; -++ volatile unsigned char *s = (unsigned char *)src_start; -++ volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); -++ -++ while (count > 0) { -++ count--; -++ cnt += 1; -++ data = *(s++) - 0x80; -++ ddata = (unsigned long) data << 8; -++ *(dp ++) = ddata; -++ *(dp ++) = ddata; -++ -++ /* save last left and right */ -++ if(count == 1) { -++ save_last_samples[id].left = ddata; -++ save_last_samples[id].right = ddata; -++ } -++ } -++ cnt = cnt * 2 * jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++ -++static void replay_fill_2x8_u(signed long src_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned char d1; -++ unsigned long dd1; -++ volatile unsigned char *s = (unsigned char *)src_start; -++ volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); -++ -++ while (count > 0) { -++ count -= 1; -++ cnt += 1 ; -++ d1 = *(s++) - 0x80; -++ dd1 = (unsigned long) d1 << 8; -++ *(dp ++) = dd1; -++ /* save last left */ -++ if(count == 2) -++ save_last_samples[id].left = dd1; -++ /* save last right */ -++ if(count == 1) -++ save_last_samples[id].right = dd1; -++ } -++ cnt *= jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++ -++static void replay_fill_1x16_s(signed long src_start, int count, int id) -++{ -++ int cnt = 0; -++ signed short d1; -++ signed long l1; -++ volatile signed short *s = (signed short *)src_start; -++ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -++ -++ while (count > 0) { -++ count -= 2; -++ cnt += 2 ; -++ d1 = *(s++); -++ l1 = (signed long)d1; -++ *(dp ++) = l1; -++ *(dp ++) = l1; -++ -++ /* save last left and right */ -++ if(count == 1) { -++ save_last_samples[id].left = l1; -++ save_last_samples[id].right = l1; -++ } -++ } -++ cnt = cnt * 2 * jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++#if 0 -++static void replay_fill_2x16_s(signed long src_start, int count, int id) -++{ -++ int cnt = 0; -++ signed short d1; -++ signed long l1; -++ int mute_cnt = 0; -++ signed long tmp1,tmp2; -++ volatile signed short *s = (signed short *)src_start; -++ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -++#if defined(CONFIG_I2S_ICDC) -++ volatile signed long *before_dp; -++ int sam_rate = jz_audio_rate / 20; -++ -++ tmp1 = tmp2 = 0; -++ while (count > 0) { -++ count -= 2; -++ cnt += 2; -++ d1 = *(s++); -++ -++ l1 = (signed long)d1; -++ l1 >>= codec_volue_shift; -++ -++ if(l1 == 0) { -++ mute_cnt ++; -++ if(mute_cnt >= sam_rate) { -++ before_dp = dp - 10; -++ *(before_dp) = (signed long)1; -++ before_dp = dp - 11; -++ *(before_dp) = (signed long)1; -++ mute_cnt = 0; -++ } -++ } else -++ mute_cnt = 0; -++ -++ *(dp ++) = l1; -++ -++ tmp1 = tmp2; -++ tmp2 = l1; -++ } -++ -++ /* save last left */ -++ save_last_samples[id].left = tmp1; -++ /* save last right */ -++ save_last_samples[id].right = tmp2; -++#endif -++#if defined(CONFIG_I2S_DLV) -++ while (count > 0) { -++ count -= 2; -++ cnt += 2; -++ d1 = *(s++); -++ -++ l1 = (signed long)d1; -++ -++ *(dp ++) = l1; -++ } -++#endif -++ cnt *= jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++} -++#else -++static void replay_fill_2x16_s(signed long src_start, int count, int id) -++{ -++ int cnt = 0; -++ signed short d1; -++ signed long l1; -++ int mute_cnt = 0; -++ signed long tmp1,tmp2; -++ -++#if 0 -++ volatile signed short *s = (signed short *)src_start; -++ volatile signed short *dp = (signed short*)(*(out_dma_buf + id)); -++ memcpy((char*)dp, (char*)s, count); -++ *(out_dma_buf_data_count + id) = count; -++#else -++ volatile signed short *s = (signed short *)src_start; -++ volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -++ while (count > 0) { -++ count -= 2; -++ cnt += 2; -++ d1 = *(s++); -++ -++ l1 = (signed long)d1; -++ -++ *(dp ++) = l1; -++ } -++ cnt *= jz_audio_b; -++ *(out_dma_buf_data_count + id) = cnt; -++#endif -++} -++#endif -++ -++ -++static unsigned int jz_audio_set_format(int dev, unsigned int fmt) -++{ -++ switch (fmt) { -++ case AFMT_U8: -++ __i2s_set_oss_sample_size(8); -++ __i2s_set_iss_sample_size(8); -++ jz_audio_format = fmt; -++ jz_update_filler(jz_audio_format, jz_audio_channels); -++ break; -++ case AFMT_S16_LE: -++#if defined(CONFIG_I2S_DLV) -++ /* DAC path and ADC path */ -++ write_codec_file(2, 0x00); -++ //write_codec_file(2, 0x60); -++#endif -++ jz_audio_format = fmt; -++ jz_update_filler(jz_audio_format,jz_audio_channels); -++ /* print all files */ -++ __i2s_set_oss_sample_size(16); -++ __i2s_set_iss_sample_size(16); -++ break; -++ -++ case AFMT_QUERY: -++ break; -++ } -++ -++ return jz_audio_format; -++} -++ -++ -++static short jz_audio_set_channels(int dev, short channels) -++{ -++ switch (channels) { -++ case 1: -++ if(set_codec_some_func) -++ set_codec_some_func(); -++ jz_audio_channels = channels; -++ jz_update_filler(jz_audio_format, jz_audio_channels); -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file_bit(1, 1, 6);//CR1.MONO->1 for Mono -++#endif -++ break; -++ case 2: -++ jz_audio_channels = channels; -++ jz_update_filler(jz_audio_format, jz_audio_channels); -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file_bit(1, 0, 6);//CR1.MONO->0 for Stereo -++#endif -++ break; -++ case 0: -++ break; -++ } -++ -++ return jz_audio_channels; -++} -++ -++static void init_codec(void) -++{ -++ /* inititalize internal I2S codec */ -++ if(init_codec_pin) -++ init_codec_pin(); -++ -++#if defined(CONFIG_I2S_ICDC) -++ /* initialize AIC but not reset it */ -++ jz_i2s_initHw(0); -++#endif -++ if(reset_codec) -++ reset_codec(); -++} -++ -++static void jz_audio_reset(void) -++{ -++ __i2s_disable_replay(); -++ __i2s_disable_receive_dma(); -++ __i2s_disable_record(); -++ __i2s_disable_transmit_dma(); -++#if defined(CONFIG_I2S_DLV) -++ REG_AIC_I2SCR = 0x10; -++#endif -++ init_codec(); -++} -++ -++static int jz_audio_release(struct inode *inode, struct file *file); -++static int jz_audio_open(struct inode *inode, struct file *file); -++static int jz_audio_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg); -++static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait); -++static ssize_t jz_audio_write(struct file *file, const char *buffer,size_t count, loff_t *ppos); -++static ssize_t jz_audio_read(struct file *file, char *buffer,size_t count, loff_t *ppos); -++ -++/* static struct file_operations jz_i2s_audio_fops */ -++static struct file_operations jz_i2s_audio_fops = -++{ -++ owner: THIS_MODULE, -++ open: jz_audio_open, -++ release: jz_audio_release, -++ write: jz_audio_write, -++ read: jz_audio_read, -++ poll: jz_audio_poll, -++ ioctl: jz_audio_ioctl -++}; -++ -++static int jz_i2s_open_mixdev(struct inode *inode, struct file *file) -++{ -++ int i; -++ int minor = MINOR(inode->i_rdev); -++ struct jz_i2s_controller_info *controller = i2s_controller; -++ -++ for (i = 0; i < NR_I2S; i++) -++ if (controller->i2s_codec[i] != NULL && controller->i2s_codec[i]->dev_mixer == minor) -++ goto match; -++ -++ if (!controller) -++ return -ENODEV; -++match: -++ file->private_data = controller->i2s_codec[i]; -++ -++ return 0; -++} -++ -++static int jz_i2s_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -++{ -++ struct i2s_codec *codec = (struct i2s_codec *)file->private_data; -++ return codec->mixer_ioctl(codec, cmd, arg); -++} -++ -++static loff_t jz_i2s_llseek(struct file *file, loff_t offset, int origin) -++{ -++ return -ESPIPE; -++} -++ -++static struct file_operations jz_i2s_mixer_fops = -++{ -++ owner: THIS_MODULE, -++ llseek: jz_i2s_llseek, -++ ioctl: jz_i2s_ioctl_mixdev, -++ open: jz_i2s_open_mixdev, -++}; -++ -++static int i2s_mixer_ioctl(struct i2s_codec *codec, unsigned int cmd, unsigned long arg) -++{ -++ int ret; -++ long val = 0; -++ switch (cmd) { -++ case SOUND_MIXER_INFO: -++ -++ if(codec_mixer_info_id_name) -++ codec_mixer_info_id_name(); -++ info.modify_counter = audio_mix_modcnt; -++ -++ return copy_to_user((void *)arg, &info, sizeof(info)); -++ case SOUND_OLD_MIXER_INFO: -++ -++ if(codec_mixer_old_info_id_name) -++ codec_mixer_old_info_id_name(); -++ -++ return copy_to_user((void *)arg, &old_info, sizeof(info)); -++ case SOUND_MIXER_READ_STEREODEVS: -++ -++ return put_user(0, (long *) arg); -++ case SOUND_MIXER_READ_CAPS: -++ -++ val = SOUND_CAP_EXCL_INPUT; -++ return put_user(val, (long *) arg); -++ case SOUND_MIXER_READ_DEVMASK: -++ break; -++ case SOUND_MIXER_READ_RECMASK: -++ break; -++ case SOUND_MIXER_READ_RECSRC: -++ break; -++ case SOUND_MIXER_WRITE_SPEAKER: -++ -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val > 100) -++ val = 100; -++ switch(val) { -++ case 100: -++ if(set_codec_direct_mode) -++ set_codec_direct_mode(); -++ break; -++ case 0: -++ if(clear_codec_direct_mode) -++ clear_codec_direct_mode(); -++ break; -++ } -++ break; -++ case SOUND_MIXER_WRITE_BASS: -++ -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val > 100) -++ val = 100; -++ codec_bass_gain = val; -++ if(set_codec_bass) -++ set_codec_bass(val); -++ -++ return 0; -++ case SOUND_MIXER_READ_BASS: -++ -++ val = codec_bass_gain; -++ ret = val << 8; -++ val = val | ret; -++ -++ return put_user(val, (long *) arg); -++ case SOUND_MIXER_WRITE_VOLUME: -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val > 100) -++ val = 100; -++ if (val > 31) -++ val = 31; -++ jz_audio_volume = val; -++ -++ if(set_codec_volume) -++ set_codec_volume(val); -++ return 0; -++ case SOUND_MIXER_READ_VOLUME: -++ -++ val = jz_audio_volume; -++ ret = val << 8; -++ val = val | ret; -++ -++ return put_user(val, (long *) arg); -++ case SOUND_MIXER_WRITE_MIC: -++ -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val > 100) -++ val = 100; -++ codec_mic_gain = val; -++ if(set_codec_mic) -++ set_codec_mic(val); -++ -++ return 0; -++ case SOUND_MIXER_READ_MIC: -++ -++ val = codec_mic_gain; -++ ret = val << 8; -++ val = val | ret; -++ -++ return put_user(val, (long *) arg); -++ default: -++ return -ENOSYS; -++ } -++ audio_mix_modcnt ++; -++ return 0; -++} -++ -++ -++int i2s_probe_codec(struct i2s_codec *codec) -++{ -++ /* generic OSS to I2S wrapper */ -++ codec->mixer_ioctl = i2s_mixer_ioctl; -++ return 1; -++} -++ -++ -++/* I2S codec initialisation. */ -++static int __init jz_i2s_codec_init(struct jz_i2s_controller_info *controller) -++{ -++ int num_i2s = 0; -++ struct i2s_codec *codec; -++ -++ for (num_i2s = 0; num_i2s < NR_I2S; num_i2s++) { -++ if ((codec = kmalloc(sizeof(struct i2s_codec),GFP_KERNEL)) == NULL) -++ return -ENOMEM; -++ memset(codec, 0, sizeof(struct i2s_codec)); -++ codec->private_data = controller; -++ codec->id = num_i2s; -++ -++ if (i2s_probe_codec(codec) == 0) -++ break; -++ if ((codec->dev_mixer = register_sound_mixer(&jz_i2s_mixer_fops, -1)) < 0) { -++ printk(KERN_ERR "Jz I2S: couldn't register mixer!\n"); -++ kfree(codec); -++ break; -++ } -++ controller->i2s_codec[num_i2s] = codec; -++ } -++ return num_i2s; -++} -++ -++ -++static void jz_update_filler(int format, int channels) -++{ -++#define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3)) -++ -++ switch (TYPE(format, channels)) -++ { -++ -++ case TYPE(AFMT_U8, 1): -++ jz_audio_b = 4; /* 4bytes * 8bits =32bits */ -++ replay_filler = replay_fill_1x8_u; -++ record_filler = record_fill_1x8_u; -++ break; -++ case TYPE(AFMT_U8, 2): -++ jz_audio_b = 4; -++ replay_filler = replay_fill_2x8_u; -++ record_filler = record_fill_2x8_u; -++ break; -++ case TYPE(AFMT_S16_LE, 1): -++ jz_audio_b = 2; /* 2bytes * 16bits =32bits */ -++ replay_filler = replay_fill_1x16_s; -++ record_filler = record_fill_1x16_s; -++ break; -++ case TYPE(AFMT_S16_LE, 2): -++ jz_audio_b = 2; -++ replay_filler = replay_fill_2x16_s; -++ record_filler = record_fill_2x16_s; -++ break; -++ default: -++ ; -++ } -++} -++ -++ -++#ifdef CONFIG_PROC_FS -++extern struct proc_dir_entry *proc_jz_root; -++int i2s_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) -++{ -++ return 0; -++} -++ -++static int jz_i2s_init_proc(struct jz_i2s_controller_info *controller) -++{ -++ if (!create_proc_read_entry ("i2s", 0, proc_jz_root, i2s_read_proc, controller->i2s_codec[0])) -++ return -EIO; -++ return 0; -++} -++ -++static void jz_i2s_cleanup_proc(struct jz_i2s_controller_info *controller) -++{ -++} -++#endif -++ -++static void __init attach_jz_i2s(struct jz_i2s_controller_info *controller) -++{ -++ char *name; -++ int adev; /* No of Audio device. */ -++ -++ name = controller->name; -++ /* initialize AIC controller and reset it */ -++ jz_i2s_initHw(1); -++ adev = register_sound_dsp(&jz_i2s_audio_fops, -1); -++ if (adev < 0) -++ goto audio_failed; -++ /* initialize I2S codec and register /dev/mixer */ -++ if (jz_i2s_codec_init(controller) <= 0) -++ goto mixer_failed; -++ -++#ifdef CONFIG_PROC_FS -++ if (jz_i2s_init_proc(controller) < 0) { -++ printk(KERN_ERR "%s: can't create I2S proc filesystem.\n", name); -++ goto proc_failed; -++ } -++#endif -++ -++ controller->tmp1 = (void *)__get_free_pages(GFP_KERNEL, 8); -++ if (!controller->tmp1) { -++ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -++ goto tmp1_failed; -++ } -++ controller->tmp2 = (void *)__get_free_pages(GFP_KERNEL, 8); -++ if (!controller->tmp2) { -++ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -++ goto tmp2_failed; -++ } -++ if ((controller->dma2 = jz_request_dma(DMA_ID_I2S_RX, "audio adc", jz_i2s_record_dma_irq, IRQF_DISABLED, controller)) < 0) { -++ printk(KERN_ERR "%s: can't reqeust DMA ADC channel.\n", name); -++ goto dma2_failed; -++ } -++ if ((controller->dma1 = jz_request_dma(DMA_ID_I2S_TX, "audio dac", jz_i2s_replay_dma_irq, IRQF_DISABLED, controller)) < 0) { -++ printk(KERN_ERR "%s: can't reqeust DMA DAC channel.\n", name); -++ goto dma1_failed; -++ } -++ printk("JzSOC On-Chip I2S controller registered (DAC: DMA(play):%d/IRQ%d,\n ADC: DMA(record):%d/IRQ%d)\n", controller->dma1, get_dma_done_irq(controller->dma1), controller->dma2, get_dma_done_irq(controller->dma2)); -++ -++ controller->dev_audio = adev; -++ pop_turn_onoff_buf = __get_free_pages(GFP_KERNEL | GFP_DMA, 8); -++ if(!pop_turn_onoff_buf) -++ printk("pop_turn_onoff_buf alloc is wrong!\n"); -++ pop_turn_onoff_pbuf = virt_to_phys((void *)pop_turn_onoff_buf); -++ -++ return; -++dma2_failed: -++ jz_free_dma(controller->dma1); -++dma1_failed: -++ free_pages((unsigned long)controller->tmp2, 8); -++tmp2_failed: -++ free_pages((unsigned long)controller->tmp1, 8); -++tmp1_failed: -++ -++#ifdef CONFIG_PROC_FS -++ jz_i2s_cleanup_proc(controller); -++#endif -++proc_failed: -++ /* unregister mixer dev */ -++mixer_failed: -++ unregister_sound_dsp(adev); -++audio_failed: -++ return; -++} -++ -++static int __init probe_jz_i2s(struct jz_i2s_controller_info **controller) -++{ -++ if ((*controller = kmalloc(sizeof(struct jz_i2s_controller_info), -++ GFP_KERNEL)) == NULL) { -++ printk(KERN_ERR "Jz I2S Controller: out of memory.\n"); -++ return -ENOMEM; -++ } -++ (*controller)->name = "Jz I2S controller"; -++ (*controller)->opened1 = 0; -++ (*controller)->opened2 = 0; -++ init_waitqueue_head(&(*controller)->adc_wait); -++ init_waitqueue_head(&(*controller)->dac_wait); -++ spin_lock_init(&(*controller)->lock); -++ init_waitqueue_head(&rx_wait_queue); -++ init_waitqueue_head(&tx_wait_queue); -++ init_waitqueue_head(&pop_wait_queue); -++ init_waitqueue_head(&drain_wait_queue); -++ -++ return 0; -++} -++ -++static void __exit unload_jz_i2s(struct jz_i2s_controller_info *controller) -++{ -++ int adev = controller->dev_audio; -++ -++ jz_i2s_full_reset(controller); -++ controller->dev_audio = -1; -++ if (old_mksound) -++ kd_mksound = old_mksound;/* Our driver support bell for kb, see vt.c */ -++ -++#ifdef CONFIG_PROC_FS -++ jz_i2s_cleanup_proc(controller); -++#endif -++ -++ jz_free_dma(controller->dma1); -++ jz_free_dma(controller->dma2); -++ free_pages((unsigned long)controller->tmp1, 8); -++ free_pages((unsigned long)controller->tmp2, 8); -++ free_pages((unsigned long)pop_turn_onoff_buf, 8); -++ -++ if (adev >= 0) { -++ /* unregister_sound_mixer(audio_devs[adev]->mixer_dev); */ -++ unregister_sound_dsp(controller->dev_audio); -++ } -++} -++ -++#ifdef CONFIG_PM -++static int jz_i2s_suspend(struct jz_i2s_controller_info *controller, int state) -++{ -++ if(i2s_suspend_codec) -++ i2s_suspend_codec(controller->opened1,controller->opened2); -++ printk("Aic and codec are suspended!\n"); -++ return 0; -++} -++ -++static int jz_i2s_resume(struct jz_i2s_controller_info *controller) -++{ -++ if(i2s_resume_codec) -++ i2s_resume_codec(); -++ -++#if defined(CONFIG_I2S_AK4642EN) -++ jz_i2s_initHw(0); -++ jz_audio_reset(); -++ __i2s_enable(); -++ jz_audio_set_speed(controller->dev_audio,jz_audio_speed); -++ /* playing */ -++ if(controller->opened1) { -++ if(set_codec_replay) -++ set_codec_replay(); -++ int dma = controller->dma1; -++ int id; -++ unsigned long flags; -++ disable_dma(dma); -++ if(__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if(__dmac_channel_transmit_end_detected(dma)) -++ __dmac_channel_clear_transmit_end(dma); -++ -++ /* for DSP_GETOPTR */ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ while((id = get_buffer_id(&out_busy_queue)) >= 0) -++ put_buffer_id(&out_empty_queue, id); -++ -++ out_busy_queue.count=0; -++ if((id = get_buffer_id(&out_full_queue)) >= 0) { -++ put_buffer_id(&out_empty_queue, id); -++ } -++ if (elements_in_queue(&out_empty_queue) > 0) { -++ wake_up(&tx_wait_queue); -++ wake_up(&controller->dac_wait); -++ } else -++ printk("pm out_empty_queue empty"); -++ } -++ -++ /* recording */ -++ if(controller->opened2) { -++ if(set_codec_record) -++ set_codec_record(); -++ int dma = controller->dma2; -++ int id1, id2; -++ unsigned long flags; -++ disable_dma(dma); -++ if (__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if (__dmac_channel_transmit_end_detected(dma)) { -++ __dmac_channel_clear_transmit_end(dma); -++ } -++ /* for DSP_GETIPTR */ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ id1 = get_buffer_id(&in_busy_queue); -++ put_buffer_id(&in_full_queue, id1); -++ wake_up(&rx_wait_queue); -++ wake_up(&controller->adc_wait); -++ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_full_queue, id2); -++ } -++ in_busy_queue.count = 0; -++ } -++#endif -++ -++ return 0; -++} -++ -++static int jz_i2s_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -++{ -++ int ret; -++ struct jz_i2s_controller_info *controller = pm_dev->data; -++ -++ if (!controller) return -EINVAL; -++ -++ switch (req) { -++ case PM_SUSPEND: -++ ret = jz_i2s_suspend(controller, (int)data); -++ break; -++ case PM_RESUME: -++ ret = jz_i2s_resume(controller); -++ break; -++ default: -++ ret = -EINVAL; -++ break; -++ } -++ return ret; -++} -++#endif /* CONFIG_PM */ -++static irqreturn_t aic_codec_irq(int irq, void *dev_id) -++{ -++ u8 file_9 = read_codec_file(9); -++ u8 file_8 = read_codec_file(8); -++ -++ //printk("--- 8:0x%x 9:0x%x ---\n",file_8,file_9); -++ if ((file_9 & 0x1f) == 0x10) { -++ -++ write_codec_file(8, 0x3f); -++ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ mdelay(300); -++ while ((read_codec_file(9) & 0x4) != 0x4); -++ while ((read_codec_file(9) & 0x10) == 0x10) { -++ write_codec_file(9, 0x10); -++ } -++ write_codec_file_bit(5, 0, 6);//SB_OUT->0 -++ mdelay(300); -++ while ((read_codec_file(9) & 0x8) != 0x8); -++ write_codec_file(9, file_9); -++ write_codec_file(8, file_8); -++ -++ return IRQ_HANDLED; -++ } -++ -++ if (file_9 & 0x8) -++ ramp_up_end = jiffies; -++ else if (file_9 & 0x4) -++ ramp_down_end = jiffies; -++ else if (file_9 & 0x2) -++ gain_up_end = jiffies; -++ else if (file_9 & 0x1) -++ gain_down_end = jiffies; -++ -++ write_codec_file(9, file_9); -++ if (file_9 & 0xf) -++ wake_up(&pop_wait_queue); -++ while (REG_ICDC_RGDATA & 0x100); -++ -++ return IRQ_HANDLED; -++} -++ -++static int __init init_jz_i2s(void) -++{ -++ int errno, retval; -++#if defined(CONFIG_I2S_DLV) -++ -++ ramp_up_start = 0; -++ ramp_up_end = 0; -++ gain_up_start = 0; -++ gain_up_end = 0; -++ ramp_down_start = 0; -++ ramp_down_end = 0; -++ gain_down_start = 0; -++ gain_down_end = 0; -++#endif -++ -++ abnormal_data_count = 0; -++ if(set_codec_mode) -++ set_codec_mode(); -++ -++ drain_flag = 0; -++ if ((errno = probe_jz_i2s(&i2s_controller)) < 0) -++ return errno; -++ if(set_codec_gpio_pin) -++ set_codec_gpio_pin(); -++ -++ attach_jz_i2s(i2s_controller); -++ if(set_codec_startup_param) -++ set_codec_startup_param(); -++#if defined(CONFIG_I2S_DLV) -++ jz_codec_config = 0; -++ retval = request_irq(IRQ_AIC, aic_codec_irq, IRQF_DISABLED, "aic_codec_irq", NULL); -++ if (retval) { -++ printk("Could not get aic codec irq %d\n", IRQ_AIC); -++ return retval; -++ } -++#endif -++ if(set_codec_volume_table) -++ set_codec_volume_table(); -++ -++ out_empty_queue.id = NULL; -++ out_full_queue.id = NULL; -++ out_busy_queue.id = NULL; -++ in_empty_queue.id = NULL; -++ in_full_queue.id = NULL; -++ in_busy_queue.id = NULL; -++ -++ jz_audio_fragsize = JZCODEC_RW_BUFFER_SIZE * PAGE_SIZE; -++ jz_audio_fragstotal = JZCODEC_RW_BUFFER_TOTAL ; -++ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ -++#ifdef CONFIG_PM -++ i2s_controller->pm = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, -++ jz_i2s_pm_callback); -++ if (i2s_controller->pm) -++ i2s_controller->pm->data = i2s_controller; -++#endif -++ -++#if defined(CONFIG_I2S_DLV) -++ __cpm_start_idct(); -++ __cpm_start_db(); -++ __cpm_start_me(); -++ __cpm_start_mc(); -++ __cpm_start_ipu(); -++#endif -++ -++ printk("JZ I2S OSS audio driver initialized\n"); -++ -++ return 0; -++} -++ -++static void __exit cleanup_jz_i2s(void) -++{ -++#ifdef CONFIG_PM -++ /* pm_unregister(i2s_controller->pm); */ -++#endif -++#if defined(CONFIG_I2S_DLV) -++ free_irq(IRQ_AIC, NULL); -++#endif -++ unload_jz_i2s(i2s_controller); -++ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ if(clear_codec_mode) -++ clear_codec_mode(); -++} -++ -++module_init(init_jz_i2s); -++module_exit(cleanup_jz_i2s); -++ -++#if defined(CONFIG_SOC_JZ4730) -++static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ DECLARE_WAITQUEUE(wait, current); -++ unsigned long flags; -++ int count,con; -++ -++ if(elements_in_queue(&in_busy_queue) > 0) { -++ if (nonblock) -++ return -EBUSY; -++ drain_flag = 1; -++ sleep_on(&drain_wait_queue); -++ drain_flag = 0; -++ } else { -++ add_wait_queue(&ctrl->adc_wait, &wait); -++ for (con = 0; con < 1000; con ++) { -++ udelay(1); -++ set_current_state(TASK_INTERRUPTIBLE); -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma2); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if (count <= 0) -++ break; -++ if (nonblock) { -++ remove_wait_queue(&ctrl->adc_wait, &wait); -++ current->state = TASK_RUNNING; -++ return -EBUSY; -++ } -++ } -++ remove_wait_queue(&ctrl->adc_wait, &wait); -++ current->state = TASK_RUNNING; -++ } -++ return 0; -++} -++ -++static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ DECLARE_WAITQUEUE(wait, current); -++ unsigned long flags; -++ int count; -++ -++ if(elements_in_queue(&out_full_queue) > 0) { -++ if (nonblock) -++ return -EBUSY; -++ -++ drain_flag = 1; -++ sleep_on(&drain_wait_queue); -++ drain_flag = 0; -++ } else { -++ add_wait_queue(&(ctrl->dac_wait), &wait); -++ for (;;) { -++ set_current_state(TASK_INTERRUPTIBLE); -++ if(elements_in_queue(&out_full_queue) <= 0) { -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if(count <= 0) -++ break; -++ } -++ if (nonblock) { -++ remove_wait_queue(&ctrl->dac_wait, &wait); -++ current->state = TASK_RUNNING; -++ return -EBUSY; -++ } -++ } -++ remove_wait_queue(&ctrl->dac_wait, &wait); -++ current->state = TASK_RUNNING; -++ } -++ -++ return 0; -++} -++#endif -++ -++#if defined(CONFIG_SOC_JZ4750) -++static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ //DECLARE_WAITQUEUE(wait, current); -++ unsigned long flags; -++ int count,i=0; -++ -++ //add_wait_queue(&ctrl->adc_wait, &wait); -++ for (;;) { -++ if (i < MAXDELAY) { -++ udelay(10); -++ i++; -++ } else -++ break; -++ //set_current_state(TASK_INTERRUPTIBLE); -++ spin_lock_irqsave(&ctrl->lock, flags); -++ //spin_lock(&ctrl->lock); -++ count = get_dma_residue(ctrl->dma2); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ //spin_unlock(&ctrl->lock); -++ if (count <= 0) -++ break; -++ -++ /*if (signal_pending(current)) -++ break;*/ -++ if (nonblock) { -++ //remove_wait_queue(&ctrl->adc_wait, &wait); -++ //current->state = TASK_RUNNING; -++ return -EBUSY; -++ } -++ } -++ //remove_wait_queue(&ctrl->adc_wait, &wait); -++ //current->state = TASK_RUNNING; -++ /*if (signal_pending(current)) -++ return -ERESTARTSYS;*/ -++ return 0; -++} -++static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ unsigned long flags; -++ int count,ele,busyele,emptyele,i=0; -++ -++ for (;;) { -++ if(!nonblock) {//blocked -++ if (i < MAXDELAY) { -++ udelay(10); -++ i++; -++ } else -++ break; -++ -++ ele = elements_in_queue(&out_full_queue); -++ if(ele <= 0) { -++ udelay(200); -++ -++ busyele = elements_in_queue(&out_busy_queue); -++ emptyele = elements_in_queue(&out_empty_queue); -++ if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if (count <= 0) -++ break; -++ } -++ } -++ } else {//non-blocked -++ //mdelay(100); -++ ele = elements_in_queue(&out_full_queue); -++ -++ if(ele <= 0) { -++ //mdelay(100); -++ busyele = elements_in_queue(&out_busy_queue); -++ emptyele = elements_in_queue(&out_empty_queue); -++ -++ if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if (count <= 0) -++ break; -++ } -++ } -++ } -++ } -++ -++ return 0; -++} -++#endif -++ -++#if defined(CONFIG_SOC_JZ4740) -++#define MAXDELAY 50000 -++static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ int count,ele,i=0; -++ -++ for (;;) { -++ if(!nonblock) {//blocked -++ if ( i < MAXDELAY ) { -++ udelay(10); -++ i++; -++ } else -++ break; -++ -++ ele = elements_in_queue(&out_full_queue); -++ if(ele <= 0) { -++ udelay(10); -++ spin_lock(&ctrl->lock); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock(&ctrl->lock); -++ if (count <= 0) -++ break; -++ } -++ } else {//non-blocked -++ mdelay(100); -++ ele = elements_in_queue(&out_full_queue); -++ -++ if(ele <= 0) { -++ mdelay(100); -++ -++ spin_lock(&ctrl->lock); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock(&ctrl->lock); -++ if (count <= 0) -++ break; -++ } -++ } -++ } -++ -++ return 0; -++} -++ -++static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -++{ -++ int count,i=0; -++ -++ for (;;) { -++ if ( i < MAXDELAY ) -++ { -++ udelay(10); -++ i++; -++ } -++ else -++ break; -++ spin_lock(&ctrl->lock); -++ count = get_dma_residue(ctrl->dma2); -++ spin_unlock(&ctrl->lock); -++ if (count <= 0) -++ break; -++ -++ if (nonblock) { -++ return -EBUSY; -++ } -++ } -++ -++ return 0; -++} -++#endif -++ -++static int jz_audio_release(struct inode *inode, struct file *file) -++{ -++ unsigned long flags; -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ unsigned long tfl; -++ -++ if (controller == NULL) -++ return -ENODEV; -++ -++ pop_dma_flag = 0; -++ if (controller->opened1 == 1) { -++ controller->opened1 = 0; -++ __i2s_enable_transmit_dma(); -++ __i2s_enable_replay(); -++ drain_dac(controller, file->f_flags & O_NONBLOCK); -++ /* add some mute to anti-pop */ -++#if defined(CONFIG_I2S_DLV) -++ /* wait for fifo empty */ -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ gain_down_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //gain_down_end = jiffies; -++ while (1) { -++ tfl = REG_AIC_SR & 0x00003f00; -++ if (tfl == 0) { -++ udelay(500); -++ break; -++ } -++ mdelay(2); -++ } -++#endif -++ disable_dma(controller->dma1); -++ set_dma_count(controller->dma1, 0); -++ __i2s_disable_transmit_dma(); -++ __i2s_disable_replay(); -++ __aic_flush_fifo(); -++ if(clear_codec_replay) -++ clear_codec_replay(); -++ __aic_flush_fifo(); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->blocks = 0; -++ controller->nextOut = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ ramp_down_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //ramp_down_end = jiffies; -++ unset_audio_data_replay(); -++#endif -++ __i2s_disable(); -++ if(turn_off_codec) -++ turn_off_codec(); -++ } -++ -++ if (controller->opened2 == 1) { -++ controller->opened2 = 0; -++ first_record_call = 1; -++ __i2s_enable_receive_dma(); -++ __i2s_enable_record(); -++ drain_adc(controller, file->f_flags & O_NONBLOCK); -++ disable_dma(controller->dma2); -++ set_dma_count(controller->dma2, 0); -++ __i2s_disable_receive_dma(); -++ __i2s_disable_record(); -++ -++ if(clear_codec_record) -++ clear_codec_record(); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextIn = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ __i2s_disable(); -++ if(turn_off_codec) -++ turn_off_codec(); -++ abnormal_data_count = 0; -++ } -++ -++#if defined(CONFIG_I2S_DLV) -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++#endif -++ return 0; -++} -++ -++static int jz_audio_open(struct inode *inode, struct file *file) -++{ -++ int i; -++ struct jz_i2s_controller_info *controller = i2s_controller; -++ -++ if (controller == NULL) -++ return -ENODEV; -++ -++ mdelay(2); -++ REG_DMAC_DMACKE(0) = 0x3f; -++ pop_dma_flag = 0; -++ if (controller->opened1 == 1 || controller->opened2 == 1 ) { -++ printk("\naudio is busy!\n"); -++ return -EBUSY; -++ } -++ jz_codec_config = 0; -++ -++ ramp_up_start = 0; -++ ramp_up_end = 0; -++ gain_up_start = 0; -++ gain_up_end = 0; -++ ramp_down_start = 0; -++ ramp_down_end = 0; -++ gain_down_start = 0; -++ gain_down_end = 0; -++ if (file->f_mode & FMODE_WRITE) { -++ if (controller->opened1 == 1) -++ return -EBUSY; -++ -++ controller->opened1 = 1; -++ /* for ioctl */ -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextOut = 0; -++ -++ for(i=0;i < 64;i++) { -++ save_last_samples[i].left = 0; -++ save_last_samples[i].right = 0; -++ } -++ -++ out_empty_queue.count = jz_audio_fragstotal; -++ for (i=0;i < jz_audio_fragstotal;i++) -++ *(out_empty_queue.id + i) = i; -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ last_dma_buffer_id = 0; -++ } -++ -++ if (file->f_mode & FMODE_READ) { -++ if (controller->opened2 == 1) -++ return -EBUSY; -++ -++ controller->opened2 = 1; -++ first_record_call = 1; -++ /* for ioctl */ -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextIn = 0; -++ -++ in_empty_queue.count = jz_audio_fragstotal; -++ for (i=0;i < jz_audio_fragstotal;i++) -++ *(in_empty_queue.id + i) = i; -++ -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ } -++ -++ file->private_data = controller; -++ jz_audio_reset(); -++ REG_AIC_FR |= (1 << 6); -++ -++ if (file->f_mode & FMODE_WRITE) { -++ if(set_codec_replay) -++ set_codec_replay(); -++ } -++ -++ if (file->f_mode & FMODE_READ) { -++ abnormal_data_count = 0; -++ if(set_codec_record) -++ set_codec_record(); -++ } -++ -++#if defined(CONFIG_I2S_DLV) -++ __aic_reset(); -++ -++ mdelay(10); -++ REG_AIC_I2SCR = 0x10; -++ mdelay(20); -++ __aic_flush_fifo(); -++#endif -++ -++ __i2s_enable(); -++ -++#if defined(CONFIG_I2S_DLV) -++ if (file->f_mode & FMODE_WRITE) { -++ -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ ramp_up_start = jiffies; -++ /*while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_RCR = 0x1; -++ while (!(REG_RTC_RCR & RTC_RCR_WRDY)); -++ REG_RTC_RGR = 1;*/ -++ sleep_on(&pop_wait_queue); -++ //ramp_up_end = jiffies; -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ } else if (file->f_mode & FMODE_READ) { -++ if (jz_mic_only) -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ else -++ write_codec_file_bit(5, 0, 7);//SB_DAC->0 -++ mdelay(500); -++ } -++ -++#endif -++ -++ return 0; -++} -++ -++ -++static int jz_audio_ioctl(struct inode *inode, struct file *file, -++unsigned int cmd, unsigned long arg) -++{ -++ int val,fullc,busyc,unfinish,newfragstotal,newfragsize; -++ unsigned int flags; -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ count_info cinfo; -++ audio_buf_info abinfo; -++ int id, i; -++ -++ val = 0; -++ switch (cmd) { -++ case OSS_GETVERSION: -++ return put_user(SOUND_VERSION, (int *)arg); -++ case SNDCTL_DSP_RESET: -++#if 0 -++ jz_audio_reset(); -++ __i2s_disable_replay(); -++ __i2s_disable_receive_dma(); -++ __i2s_disable_record(); -++ __i2s_disable_transmit_dma(); -++#endif -++ return 0; -++ case SNDCTL_DSP_SYNC: -++ if (file->f_mode & FMODE_WRITE) -++ return drain_dac(controller, file->f_flags & O_NONBLOCK); -++ return 0; -++ case SNDCTL_DSP_SPEED: -++ /* set smaple rate */ -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ if (val >= 0) -++ jz_audio_set_speed(controller->dev_audio, val); -++ -++ return put_user(val, (int *)arg); -++ case SNDCTL_DSP_STEREO: -++ /* set stereo or mono channel */ -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ jz_audio_set_channels(controller->dev_audio, val ? 2 : 1); -++ -++ return 0; -++ case SNDCTL_DSP_GETBLKSIZE: -++ //return put_user(jz_audio_fragsize / jz_audio_b, (int *)arg); -++ return put_user(jz_audio_fragsize, (int *)arg); -++ case SNDCTL_DSP_GETFMTS: -++ /* Returns a mask of supported sample format*/ -++ return put_user(AFMT_U8 | AFMT_S16_LE, (int *)arg); -++ case SNDCTL_DSP_SETFMT: -++ /* Select sample format */ -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ if (val != AFMT_QUERY) -++ jz_audio_set_format(controller->dev_audio,val); -++ else { -++ if (file->f_mode & FMODE_READ) -++ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -++ else -++ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -++ } -++ -++ return put_user(val, (int *)arg); -++ case SNDCTL_DSP_CHANNELS: -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ jz_audio_set_channels(controller->dev_audio, val); -++ -++ return put_user(val, (int *)arg); -++ case SNDCTL_DSP_POST: -++ /* FIXME: the same as RESET ?? */ -++ return 0; -++ case SNDCTL_DSP_SUBDIVIDE: -++ return 0; -++ case SNDCTL_DSP_SETFRAGMENT: -++ get_user(val, (long *) arg); -++ newfragsize = 1 << (val & 0xFFFF); -++ if (newfragsize < 4 * PAGE_SIZE) -++ newfragsize = 4 * PAGE_SIZE; -++ if (newfragsize > (16 * PAGE_SIZE)) -++ newfragsize = 16 * PAGE_SIZE; -++ -++ newfragstotal = (val >> 16) & 0x7FFF; -++ if (newfragstotal < 2) -++ newfragstotal = 2; -++ if (newfragstotal > 32) -++ newfragstotal = 32; -++ if((jz_audio_fragstotal == newfragstotal) && (jz_audio_fragsize == newfragsize)) -++ return 0; -++ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ mdelay(500); -++ jz_audio_fragstotal = newfragstotal; -++ jz_audio_fragsize = newfragsize; -++ -++ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ mdelay(10); -++ -++ return 0; -++ case SNDCTL_DSP_GETCAPS: -++ return put_user(DSP_CAP_REALTIME|DSP_CAP_BATCH, (int *)arg); -++ case SNDCTL_DSP_NONBLOCK: -++ file->f_flags |= O_NONBLOCK; -++ return 0; -++ case SNDCTL_DSP_SETDUPLEX: -++ return -EINVAL; -++ case SNDCTL_DSP_GETOSPACE: -++ { -++ int i, bytes = 0; -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ jz_audio_fragments = elements_in_queue(&out_empty_queue); -++ for (i = 0; i < jz_audio_fragments; i++) -++ bytes += jz_audio_fragsize; -++ -++ if (jz_audio_channels == 2) -++ bytes /= jz_audio_b; -++ else if (jz_audio_channels == 1) -++ bytes /= 4; -++ else -++ printk("SNDCTL_DSP_GETOSPACE : channels is wrong 1!\n"); -++ -++ -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ /* unused fragment amount */ -++ abinfo.fragments = jz_audio_fragments; -++ /* amount of fragments */ -++ abinfo.fragstotal = jz_audio_fragstotal; -++ /* fragment size in bytes */ -++ if (jz_audio_channels == 2) -++ abinfo.fragsize = jz_audio_fragsize / jz_audio_b; -++ else if (jz_audio_channels == 1) -++ abinfo.fragsize = jz_audio_fragsize / 4; -++ else -++ printk("SNDCTL_DSP_GETOSPACE : channels is wrong 2!\n"); -++ -++ /* write size count without blocking in bytes */ -++ abinfo.bytes = bytes; -++ -++ return copy_to_user((void *)arg, &abinfo, -++ sizeof(abinfo)) ? -EFAULT : 0; -++ } -++ case SNDCTL_DSP_GETISPACE: -++ { -++ int i, bytes = 0; -++ if (!(file->f_mode & FMODE_READ)) -++ return -EINVAL; -++ jz_audio_fragments = elements_in_queue(&in_empty_queue); -++ for (i = 0; i < jz_audio_fragments; i++) -++ bytes += jz_audio_fragsize; -++ -++ if (jz_audio_channels == 2) -++ bytes /= jz_audio_b; -++ else if (jz_audio_channels == 1) -++ bytes /= 4; -++ else -++ printk("SNDCTL_DSP_GETISPACE : channels is wrong 1!\n"); -++ -++ abinfo.fragments = jz_audio_fragments; -++ abinfo.fragstotal = jz_audio_fragstotal; -++ -++ if (jz_audio_channels == 2) -++ abinfo.fragsize = jz_audio_fragsize / jz_audio_b; -++ else if (jz_audio_channels == 1) -++ abinfo.fragsize = jz_audio_fragsize / 4; -++ else -++ printk("SNDCTL_DSP_GETISPACE : channels is wrong 2!\n"); -++ -++ abinfo.bytes = bytes; -++ -++ return copy_to_user((void *)arg, &abinfo, -++ sizeof(abinfo)) ? -EFAULT : 0; -++ } -++ case SNDCTL_DSP_GETTRIGGER: -++ val = 0; -++ if (file->f_mode & FMODE_READ && in_dma_buf) -++ val |= PCM_ENABLE_INPUT; -++ if (file->f_mode & FMODE_WRITE && out_dma_buf) -++ val |= PCM_ENABLE_OUTPUT; -++ -++ return put_user(val, (int *)arg); -++ case SNDCTL_DSP_SETTRIGGER: -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ return 0; -++ case SNDCTL_DSP_GETIPTR: -++ if (!(file->f_mode & FMODE_READ)) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ cinfo.bytes = controller->total_bytes; -++ cinfo.blocks = controller->blocks; -++ cinfo.ptr = controller->nextIn; -++ controller->blocks = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); -++ case SNDCTL_DSP_GETOPTR: -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ cinfo.bytes = controller->total_bytes; -++ cinfo.blocks = controller->blocks; -++ cinfo.ptr = controller->nextOut; -++ controller->blocks = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); -++ case SNDCTL_DSP_GETODELAY: -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ unfinish = 0; -++ fullc = elements_in_queue(&out_full_queue); -++ busyc = elements_in_queue(&out_busy_queue); -++ for(i = 0;i < fullc ;i ++) { -++ id = *(out_full_queue.id + i); -++ unfinish += *(out_dma_buf_data_count + id); -++ } -++ for(i = 0;i < busyc ;i ++) { -++ id = *(out_busy_queue.id + i); -++ unfinish += get_dma_residue(controller->dma1); -++ } -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ if (jz_audio_channels == 2) -++ unfinish /= jz_audio_b; -++ else if (jz_audio_channels == 1) -++ unfinish /= 4; -++ else -++ printk("SNDCTL_DSP_GETODELAY : channels is wrong !\n"); -++ -++ return put_user(unfinish, (int *) arg); -++ case SOUND_PCM_READ_RATE: -++ return put_user(jz_audio_rate, (int *)arg); -++ case SOUND_PCM_READ_CHANNELS: -++ return put_user(jz_audio_channels, (int *)arg); -++ case SOUND_PCM_READ_BITS: -++ return put_user((jz_audio_format & (AFMT_S8 | AFMT_U8)) ? 8 : 16, (int *)arg); -++ case SNDCTL_DSP_MAPINBUF: -++ case SNDCTL_DSP_MAPOUTBUF: -++ case SNDCTL_DSP_SETSYNCRO: -++ case SOUND_PCM_WRITE_FILTER: -++ case SOUND_PCM_READ_FILTER: -++ return -EINVAL; -++ } -++ return -EINVAL; -++} -++ -++ -++static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait) -++{ -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ unsigned long flags; -++ unsigned int mask = 0; -++ -++ if (file->f_mode & FMODE_WRITE) { -++ if (elements_in_queue(&out_empty_queue) > 0) -++ return POLLOUT | POLLWRNORM; -++ -++ poll_wait(file, &controller->dac_wait, wait); -++ } -++ -++ if (file->f_mode & FMODE_READ) { -++ if (elements_in_queue(&in_full_queue) > 0) -++ return POLLIN | POLLRDNORM; -++ -++ poll_wait(file, &controller->adc_wait, wait); -++ } -++ -++ spin_lock_irqsave(&controller->lock, flags); -++ if (file->f_mode & FMODE_WRITE) { -++ if (elements_in_queue(&out_empty_queue) > 0) -++ mask |= POLLOUT | POLLWRNORM; -++ } else if (file->f_mode & FMODE_READ) { -++ if (elements_in_queue(&in_full_queue) > 0) -++ mask |= POLLIN | POLLRDNORM; -++ } -++ spin_unlock_irqrestore(&controller->lock, flags); -++ -++ return mask; -++} -++ -++static ssize_t jz_audio_read(struct file *file, char *buffer, size_t count, loff_t *ppos) -++{ -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ int id, ret = 0, left_count, copy_count, cnt = 0; -++ unsigned long flags; -++ -++ if (count < 0) -++ return -EINVAL; -++ -++ __i2s_enable_receive_dma(); -++ __i2s_enable_record(); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextIn = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ copy_count = jz_audio_fragsize / 4; -++ -++ left_count = count; -++ if (first_record_call) { -++ first_record_call = 0; -++ audio_read_back_first: -++ if ((id = get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id); -++ spin_lock(&controller->lock); -++ *(in_dma_buf_data_count + id) = copy_count * 4; -++ -++ spin_unlock(&controller->lock); -++ __i2s_enable_receive_dma(); -++ __i2s_enable_record(); -++ dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); -++ audio_start_dma(controller->dma2,file->private_data, -++ *(in_dma_pbuf + id), -++ *(in_dma_buf_data_count + id), -++ DMA_MODE_READ); -++ sleep_on(&rx_wait_queue); -++ } else -++ goto audio_read_back_first; -++ } -++ -++ while (left_count > 0) { -++ audio_read_back_second: -++ if (elements_in_queue(&in_full_queue) <= 0) { -++ if (file->f_flags & O_NONBLOCK) -++ return ret ? ret : -EAGAIN; -++ else -++ sleep_on(&rx_wait_queue); -++ } -++ -++ if ((id = get_buffer_id(&in_full_queue)) >= 0) { -++ spin_lock(&controller->lock); -++ cnt = record_filler((unsigned long)controller->tmp2+ret, copy_count, id); -++ spin_unlock(&controller->lock); -++ put_buffer_id(&in_empty_queue, id); -++ } else -++ goto audio_read_back_second; -++ -++ if (elements_in_queue(&in_busy_queue) == 0) { -++ if ((id=get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id); -++ spin_lock(&controller->lock); -++ *(in_dma_buf_data_count + id) = copy_count * 4; -++ spin_unlock(&controller->lock); -++ -++ dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); -++ audio_start_dma(controller->dma2,file->private_data, -++ *(in_dma_pbuf + id), -++ *(in_dma_buf_data_count + id), -++ DMA_MODE_READ); -++ } -++ } -++ if (ret + cnt > count) { -++ spin_lock(&controller->lock); -++ cnt = count - ret; -++ spin_unlock(&controller->lock); -++ } -++ if (copy_to_user(buffer+ret, controller->tmp2+ret, cnt)) -++ return ret ? ret : -EFAULT; -++ -++ spin_lock(&controller->lock); -++ ret += cnt; -++ spin_unlock(&controller->lock); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextIn += ret; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ spin_lock(&controller->lock); -++ left_count -= cnt; -++ spin_unlock(&controller->lock); -++ } -++ return ret; -++} -++ -++static ssize_t jz_audio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) -++{ -++ int id, ret = 0, left_count, copy_count = 0; -++ unsigned int flags; -++ struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -++ -++ if (count <= 0) -++ return -EINVAL; -++ -++ if(set_replay_hp_or_speaker) -++ set_replay_hp_or_speaker(); -++ -++ __i2s_enable_transmit_dma(); -++ __i2s_enable_replay(); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextOut = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ if (jz_audio_channels == 2) -++ copy_count = jz_audio_fragsize / jz_audio_b; -++ else if(jz_audio_channels == 1) -++ copy_count = jz_audio_fragsize / 4; -++ left_count = count; -++ if (copy_from_user(controller->tmp1, buffer, count)) { -++ printk("copy_from_user failed:%d",ret); -++ return ret ? ret : -EFAULT; -++ } -++ -++ while (left_count > 0) { -++ audio_write_back: -++ /*if (file->f_flags & O_NONBLOCK) -++ udelay(2);*/ -++ if (elements_in_queue(&out_empty_queue) == 0) { -++ if (file->f_flags & O_NONBLOCK) -++ return ret; -++ else -++ sleep_on(&tx_wait_queue); -++ } -++ /* the end fragment size in this write */ -++ if (ret + copy_count > count) -++ copy_count = count - ret; -++ if ((id = get_buffer_id(&out_empty_queue)) >= 0) { -++ replay_filler((signed long)controller->tmp1 + ret, copy_count, id); -++ if(*(out_dma_buf_data_count + id) > 0) { -++ put_buffer_id(&out_full_queue, id); -++ dma_cache_wback_inv(*(out_dma_buf + id), -++ *(out_dma_buf_data_count + id)); -++ } else -++ put_buffer_id(&out_empty_queue, id); -++ } else -++ goto audio_write_back; -++ -++ left_count = left_count - copy_count; -++ ret += copy_count; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextOut += ret; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++ if (elements_in_queue(&out_busy_queue) == 0) { -++ if ((id=get_buffer_id(&out_full_queue)) >= 0) { -++ put_buffer_id(&out_busy_queue, id); -++ -++ if(*(out_dma_buf_data_count + id) > 0) { -++ audio_start_dma(controller->dma1, -++ file->private_data, -++ *(out_dma_pbuf + id), -++ *(out_dma_buf_data_count + id), -++ DMA_MODE_WRITE); -++ last_dma_buffer_id = id; -++ if (jz_codec_config == 0) { -++ write_codec_file_bit(1, 0, 5); -++ gain_up_start = jiffies; -++ sleep_on(&pop_wait_queue); -++ //gain_up_end = jiffies; -++ jz_codec_config = 1; -++ //SB_ADC->1 -++ //write_codec_file_bit(5, 1, 4); -++ //while(1); -++ } -++ } -++ } -++ } -++ } -++ -++ return ret; -++} -++ -++#if defined(CONFIG_I2S_ICODEC) -++static void write_mute_to_dma_buffer(signed long l_sample, signed long r_sample) -++{ -++ int i,step_len; -++ unsigned long *pop_buf = (unsigned long*)pop_turn_onoff_buf; -++ unsigned int sample_oss = (REG_AIC_CR & 0x00380000) >> 19; -++ unsigned long l_sample_count,r_sample_count,sample_count; -++ struct jz_i2s_controller_info *controller = i2s_controller; -++ signed int left_sam=0,right_sam=0,l_val,r_val; -++ -++ switch (sample_oss) { -++ case 0x0: -++ break; -++ case 0x1: -++ left_sam = (signed int)l_sample; -++ right_sam = (signed int)r_sample; -++ break; -++ case 0x2: -++ break; -++ case 0x3: -++ break; -++ case 0x4: -++ break; -++ } -++ -++ if(left_sam == 0 && right_sam == 0) -++ return; -++ -++ switch (sample_oss) { -++ case 0x0: -++ break; -++ case 0x1: -++ step_len = jz_audio_speed / 10 * 3; -++ step_len = step_len / 2; -++ step_len = 0x7fff / step_len + 1; -++ -++ l_sample_count = 0; -++ l_val = left_sam; -++ -++ while(1) { -++ if(l_val > 0) { -++ if(l_val >= step_len) { -++ l_val -= step_len; -++ l_sample_count ++; -++ } else -++ break; -++ } -++ -++ if(l_val < 0) { -++ if(l_val <= -step_len) { -++ l_val += step_len; -++ l_sample_count ++; -++ } else -++ break; -++ } -++ -++ if(l_val == 0) -++ break; -++ } -++ -++ r_sample_count = 0; -++ r_val = right_sam; -++ while(1) { -++ if(r_val > 0) { -++ if(r_val >= step_len) { -++ r_val -= step_len; -++ r_sample_count ++; -++ } else -++ break; -++ } -++ -++ if(r_val < 0) { -++ if(r_val <= -step_len) { -++ r_val += step_len; -++ r_sample_count ++; -++ } else -++ break; -++ } -++ -++ if(r_val == 0) -++ break; -++ } -++ /* fill up */ -++ if(l_sample_count > r_sample_count) -++ sample_count = l_sample_count; -++ else -++ sample_count = r_sample_count; -++ -++ l_val = left_sam; -++ r_val = right_sam; -++ for(i=0;i <= sample_count;i++) { -++ -++ *pop_buf = (unsigned long)l_val; -++ pop_buf ++; -++ -++ if(l_val > step_len) -++ l_val -= step_len; -++ else if(l_val < -step_len) -++ l_val += step_len; -++ else if(l_val >= -step_len && l_val <= step_len) -++ l_val = 0; -++ -++ *pop_buf = (unsigned long)r_val; -++ pop_buf ++; -++ if(r_val > step_len) -++ r_val -= step_len; -++ else if(r_val < -step_len) -++ r_val += step_len; -++ else if(r_val >= -step_len && r_val <= step_len) -++ r_val = 0; -++ } -++ -++ *pop_buf = 0; -++ pop_buf ++; -++ *pop_buf = 0; -++ -++ pop_buf ++; -++ sample_count += 2; -++ dma_cache_wback_inv(pop_turn_onoff_buf, sample_count*8); -++ -++ pop_dma_flag = 1; -++ audio_start_dma(controller->dma1,controller,pop_turn_onoff_pbuf,sample_count*8,DMA_MODE_WRITE); -++ sleep_on(&pop_wait_queue); -++ pop_dma_flag = 0; -++ break; -++ case 0x2: -++ break; -++ case 0x3: -++ break; -++ case 0x4: -++ break; -++ } -++} -++#endif -+diff -urN linux-2.6.24.7.old/sound/oss/jz_pcm_tlv320aic1106_dma.c linux-2.6.24.7/sound/oss/jz_pcm_tlv320aic1106_dma.c -+--- linux-2.6.24.7.old/sound/oss/jz_pcm_tlv320aic1106_dma.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/oss/jz_pcm_tlv320aic1106_dma.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,1839 @@ -++/* -++ * linux/drivers/sound/jz_pcm_tlv320aic1106.c -++ * -++ * JzSOC On-Chip PCM audio driver. -++ * -++ * Copyright (C) 2005 by Ingenic Corp. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ * Because the normal application of AUDIO devices are focused on Little_endian, -++ * then we only perform the little endian data format in driver. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "sound_config.h" -++ -++#define NR_PCM 2 -++#define MAXDELAY 50000 -++#define JZCODEC_RW_BUFFER_SIZE 4 -++#define JZCODEC_RW_BUFFER_TOTAL 3 -++#define JZCODEC_USER_BUFFER 6 -++ -++#define MODE_is_8 0 // 1 is 8 bits, and 0 is 16 bits -++ -++static int jz_audio_rate; -++static char jz_audio_format; -++static char jz_audio_volume; -++static char jz_audio_channels; -++static int jz_audio_fragments;//unused fragment amount -++static int jz_audio_fragstotal; -++static int jz_audio_fragsize; -++static int jz_audio_speed; -++static int jz_audio_dma_tran_count;//bytes count of one DMA transfer -++ -++static void jz_update_filler(int bits, int channels); -++static int Init_In_Out_queue(int fragstotal,int fragsize); -++static int Free_In_Out_queue(int fragstotal,int fragsize); -++static irqreturn_t jz_pcm_irq(int irqnr, void *ref); -++static irqreturn_t jz_pcm_replay_dma_irq(int irqnr, void *ref); -++static irqreturn_t jz_pcm_record_dma_irq(int irqnr, void *ref); -++static void (*replay_filler)(unsigned long src_start, int count, int id); -++static int (*record_filler)(unsigned long dst_start, int count, int id); -++static void dump_pcmc_reg(void); -++ -++static struct file_operations jz_pcm_audio_fops; -++static DECLARE_WAIT_QUEUE_HEAD (rx_wait_queue); -++static DECLARE_WAIT_QUEUE_HEAD (tx_wait_queue); -++ -++struct jz_pcm_controller_info { -++ int io_base; -++ int dma1; /* play */ -++ int dma2; /* record */ -++ char *name; -++ int dev_audio; -++ struct pcm_codec *pcm_codec[NR_PCM]; -++ int opened1; -++ int opened2; -++ unsigned char *tmp1; /* tmp buffer for sample conversions */ -++ unsigned char *tmp2; -++ spinlock_t lock; -++ spinlock_t ioctllock; -++ -++ wait_queue_head_t dac_wait; -++ wait_queue_head_t adc_wait; -++ int nextIn; // byte index to next-in to DMA buffer -++ int nextOut; // byte index to next-out from DMA buffer -++ int count; // current byte count in DMA buffer -++ int finish; // current transfered byte count in DMA buffer -++ unsigned long total_bytes; // total bytes written or read -++ unsigned long blocks; -++ unsigned long error; // over/underrun -++}; -++static struct jz_pcm_controller_info *pcm_controller = NULL; -++ -++struct pcm_codec { -++ /* PCM controller connected with */ -++ void *private_data; -++ char *name; -++ int id; -++ int dev_mixer; -++ /* controller specific lower leverl pcm accessing routines */ -++ u16 (*codec_read) (u8 reg);//the function accessing Codec REGs -++ void (*codec_write) (u8 reg, u16 val); -++ /* Wait for codec-ready. Ok to sleep here. */ -++ void (*codec_wait) (struct pcm_codec *codec); -++ /* OSS mixer masks */ -++ int modcnt; -++ int supported_mixers; -++ int stereo_mixers; -++ int record_sources; -++ int bit_resolution; -++ /* OSS mixer interface */ -++ int (*read_mixer) (struct pcm_codec *codec, int oss_channel); -++ void (*write_mixer)(struct pcm_codec *codec, int oss_channel, -++ unsigned int left, unsigned int right); -++ int (*recmask_io) (struct pcm_codec *codec, int rw, int mask); -++ int (*mixer_ioctl)(struct pcm_codec *codec, unsigned int cmd, unsigned long arg); -++ /* saved OSS mixer states */ -++ unsigned int mixer_state[SOUND_MIXER_NRDEVICES]; -++}; -++ -++typedef struct buffer_queue_s { -++ int count; -++ int *id; -++ int lock; -++} buffer_queue_t; -++ -++static unsigned long *out_dma_buf = NULL; -++static unsigned long *out_dma_pbuf = NULL; -++static unsigned long *out_dma_buf_data_count = NULL; -++static unsigned long *in_dma_buf = NULL; -++static unsigned long *in_dma_pbuf = NULL; -++static unsigned long *in_dma_buf_data_count = NULL; -++ -++static buffer_queue_t out_empty_queue; -++static buffer_queue_t out_full_queue; -++static buffer_queue_t out_busy_queue; -++static buffer_queue_t in_empty_queue; -++static buffer_queue_t in_full_queue; -++static buffer_queue_t in_busy_queue; -++static int first_record_call = 0; -++ -++static inline int get_buffer_id(struct buffer_queue_s *q) -++{ -++ int r, i; -++ unsigned long flags; -++ -++ spin_lock_irqsave(&q->lock, flags); -++ if (q->count == 0) { -++ spin_unlock_irqrestore(&q->lock, flags); -++ return -1; -++ } -++ r = *(q->id + 0); -++ for (i=0;i < q->count-1;i++) -++ *(q->id + i) = *(q->id + (i+1)); -++ q->count --; -++ spin_unlock_irqrestore(&q->lock, flags); -++ -++ return r; -++} -++ -++static inline void put_buffer_id(struct buffer_queue_s *q, int id) -++{ -++ unsigned long flags; -++ -++ spin_lock_irqsave(&q->lock, flags); -++ *(q->id + q->count) = id; -++ q->count ++; -++ spin_unlock_irqrestore(&q->lock, flags); -++} -++ -++static inline int elements_in_queue(struct buffer_queue_s *q) -++{ -++ int r; -++ unsigned long flags; -++ -++ spin_lock_irqsave(&q->lock, flags); -++ r = q->count; -++ spin_unlock_irqrestore(&q->lock, flags); -++ -++ return r; -++} -++ -++static inline void audio_start_dma(int chan, void *dev_id, unsigned long phyaddr,int count, int mode) -++{ -++ unsigned long flags; -++ struct jz_pcm_controller_info * controller = (struct jz_pcm_controller_info *) dev_id; -++ -++ //for DSP_GETOPTR -++ //spin_lock_irqsave(&controller->ioctllock, flags); -++ spin_lock(&controller->ioctllock); -++ jz_audio_dma_tran_count = count; -++ //spin_unlock_irqrestore(&controller->ioctllock, flags); -++ spin_unlock(&controller->ioctllock); -++ flags = claim_dma_lock(); -++ __dmac_disable_module(0);//!!!!!!!!! -++ disable_dma(chan); -++ clear_dma_ff(chan); -++ set_dma_mode(chan, mode); -++#if MODE_is_8 -++ __dmac_channel_set_src_port_width(chan, 8); -++ __dmac_channel_set_dest_port_width(chan, 8); -++ __dmac_channel_set_transfer_unit_8bit(chan); -++#else -++ __dmac_channel_set_src_port_width(chan, 16); -++ __dmac_channel_set_dest_port_width(chan, 16); -++ __dmac_channel_set_transfer_unit_16bit(chan); -++#endif -++ -++ set_dma_addr(chan, phyaddr); -++ if (count == 0) { -++ count++; -++ printk("JzSOC DMA controller can't set dma 0 count!\n"); -++ } -++ -++ set_dma_count(chan, count); -++ enable_dma(chan); -++ __dmac_enable_module(0); -++ release_dma_lock(flags); -++#if 0 -++ //for DSP_GETOPTR on FPGA -++ struct jz_dma_chan *tmpchan = &jz_dma_table[1]; -++ -++ spin_lock(&controller->ioctllock); -++ jz_audio_dma_tran_count = count; -++ spin_unlock(&controller->ioctllock); -++ flags = claim_dma_lock(); -++ disable_dma(chan); -++ clear_dma_ff(chan); -++ set_dma_mode(chan, mode); -++#if MODE_is_8 -++ __dmac_channel_set_src_port_width(chan, 8); -++ __dmac_channel_set_dest_port_width(chan, 8); -++ __dmac_channel_set_transfer_unit_8bit(chan); -++#else -++ __dmac_channel_set_src_port_width(chan, 16); -++ __dmac_channel_set_dest_port_width(chan, 16); -++ __dmac_channel_set_transfer_unit_16bit(chan); -++#endif -++ set_dma_addr(chan, phyaddr); -++ if (count == 0) { -++ count++; -++ printk("JzSOC DMA controller can't set dma 0 count!\n"); -++ } -++ set_dma_count(chan, count); -++ enable_dma(chan); -++ release_dma_lock(flags); -++#if 0 -++ __pcm_enable_tfs_intr(); -++ __pcm_enable_tur_intr(); -++ __pcm_enable_rfs_intr(); -++ __pcm_enable_ror_intr(); -++#endif -++#endif -++} -++ -++static irqreturn_t jz_pcm_record_dma_irq(int irq, void *dev_id) -++{ -++ int id1, id2; -++ struct jz_pcm_controller_info * controller = (struct jz_pcm_controller_info *) dev_id; -++ int dma = controller->dma2; -++ -++ disable_dma(dma); -++ if (__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if (__dmac_channel_transmit_end_detected(dma)) { -++ __dmac_channel_clear_transmit_end(dma); -++ //for DSP_GETIPTR -++ spin_lock(&controller->ioctllock); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock(&controller->ioctllock); -++ id1 = get_buffer_id(&in_busy_queue); -++ put_buffer_id(&in_full_queue, id1); -++ -++ wake_up(&rx_wait_queue); -++ wake_up(&controller->adc_wait); -++ if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id2); -++ *(in_dma_buf_data_count + id2) = *(in_dma_buf_data_count + id1); -++ -++ dma_cache_wback_inv(*(in_dma_buf + id2), *(in_dma_buf_data_count + id2)); -++ audio_start_dma(dma,dev_id, -++ *(in_dma_pbuf + id2), -++ *(in_dma_buf_data_count + id2), -++ DMA_MODE_READ); -++ } else -++ in_busy_queue.count = 0; -++ } -++ -++ return IRQ_HANDLED; -++} -++ -++static irqreturn_t jz_pcm_irq(int irq, void *dev_id) -++{ -++ struct jz_pcm_controller_info * controller = (struct jz_pcm_controller_info *) dev_id; -++ printk("pcm interrupt REG_PCM_INTS : 0x%08x\n",REG_PCM_INTS); -++ -++ return IRQ_HANDLED; -++} -++ -++static irqreturn_t jz_pcm_replay_dma_irq(int irq, void *dev_id) -++{ -++ int id; -++ unsigned long flags; -++ struct jz_pcm_controller_info * controller = (struct jz_pcm_controller_info *) dev_id; -++ int dma = controller->dma1; -++ -++ disable_dma(dma); -++ if (__dmac_channel_address_error_detected(dma)) { -++ printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); -++ __dmac_channel_clear_address_error(dma); -++ } -++ if (__dmac_channel_transmit_end_detected(dma)) { -++ __dmac_channel_clear_transmit_end(dma); -++ //for DSP_GETOPTR -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->total_bytes += jz_audio_dma_tran_count; -++ controller->blocks ++; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ if ((id = get_buffer_id(&out_busy_queue)) < 0) -++ printk(KERN_DEBUG "Strange DMA finish interrupt for PCM module\n"); -++ put_buffer_id(&out_empty_queue, id); -++ if ((id = get_buffer_id(&out_full_queue)) >= 0) { -++ put_buffer_id(&out_busy_queue, id); //very busy -++ if(*(out_dma_buf_data_count + id) > 0) { -++ audio_start_dma(dma, dev_id, *(out_dma_pbuf + id), -++ *(out_dma_buf_data_count + id), -++ DMA_MODE_WRITE); -++ } -++ } else -++ out_busy_queue.count = 0; -++ -++ if (elements_in_queue(&out_empty_queue) > 0) { -++ wake_up(&tx_wait_queue); -++ wake_up(&controller->dac_wait); -++ } -++ } -++ -++ return IRQ_HANDLED; -++} -++ -++static int Init_In_Out_queue(int fragstotal,int fragsize) -++{ -++ int i; -++ // recording -++ in_empty_queue.count = fragstotal; -++ in_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_buf) -++ goto all_mem_err; -++ in_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_pbuf) -++ goto all_mem_err; -++ in_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!in_dma_buf_data_count) -++ goto all_mem_err; -++ in_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_empty_queue.id) -++ goto all_mem_err; -++ in_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_full_queue.id) -++ goto all_mem_err; -++ in_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!in_busy_queue.id) -++ goto all_mem_err; -++ -++ for (i=0;i < fragstotal;i++) -++ *(in_empty_queue.id + i) = i; -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ -++ for (i = 0; i < fragstotal; i++) { -++ *(in_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -++ if (*(in_dma_buf + i) == 0) -++ goto mem_failed_in; -++ *(in_dma_pbuf + i) = virt_to_phys((void *)(*(in_dma_buf + i))); -++ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -++ } -++ -++ //playing -++ out_empty_queue.count = fragstotal; -++ out_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!out_dma_buf) -++ goto all_mem_err; -++ out_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ if (!out_dma_pbuf) -++ goto all_mem_err; -++ out_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); -++ -++ if (!out_dma_buf_data_count) -++ goto all_mem_err; -++ out_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_empty_queue.id) -++ goto all_mem_err; -++ out_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_full_queue.id) -++ goto all_mem_err; -++ out_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); -++ if (!out_busy_queue.id) -++ goto all_mem_err; -++ for (i=0;i < fragstotal;i++) -++ *(out_empty_queue.id + i) = i; -++ -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ /*alloc DMA buffer*/ -++ for (i = 0; i < fragstotal; i++) { -++ *(out_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); -++ if (*(out_dma_buf + i) == 0) { -++ printk(" can't allocate required DMA(OUT) buffers.\n"); -++ goto mem_failed_out; -++ } -++ *(out_dma_pbuf + i) = virt_to_phys((void *)(*(out_dma_buf + i))); -++ } -++ -++ return 1; -++all_mem_err: -++ printk("error:allocate memory occur error 1!\n"); -++ return 0; -++mem_failed_out: -++ printk("error:allocate memory occur error 2!\n"); -++ for (i = 0; i < fragstotal; i++) { -++ if(*(out_dma_buf + i)) -++ free_pages(*(out_dma_buf + i), get_order(fragsize)); -++ } -++ -++ return 0; -++mem_failed_in: -++ printk("error:allocate memory occur error 3!\n"); -++ for (i = 0; i < fragstotal; i++) { -++ if(*(in_dma_buf + i)) -++ free_pages(*(in_dma_buf + i), get_order(fragsize)); -++ } -++ return 0; -++} -++ -++static int Free_In_Out_queue(int fragstotal,int fragsize) -++{ -++ int i; -++ //playing -++ if(out_dma_buf != NULL) { -++ for (i = 0; i < fragstotal; i++) { -++ if(*(out_dma_buf + i)) -++ free_pages(*(out_dma_buf + i), get_order(fragsize)); -++ *(out_dma_buf + i) = 0; //release page error -++ } -++ kfree(out_dma_buf); -++ out_dma_buf = NULL; -++ } -++ if(out_dma_pbuf) { -++ kfree(out_dma_pbuf); -++ out_dma_pbuf = NULL; -++ } -++ if(out_dma_buf_data_count) { -++ kfree(out_dma_buf_data_count); -++ out_dma_buf_data_count = NULL; -++ } -++ if(out_empty_queue.id) { -++ kfree(out_empty_queue.id); -++ out_empty_queue.id = NULL; -++ } -++ if(out_full_queue.id) { -++ kfree(out_full_queue.id); -++ out_full_queue.id = NULL; -++ } -++ if(out_busy_queue.id) { -++ kfree(out_busy_queue.id); -++ out_busy_queue.id = NULL; -++ } -++ out_empty_queue.count = fragstotal; -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ -++ // recording -++ if(in_dma_buf) { -++ for (i = 0; i < fragstotal; i++) { -++ if(*(in_dma_buf + i)) { -++ dma_cache_wback_inv(*(in_dma_buf + i), fragsize); -++ free_pages(*(in_dma_buf + i), get_order(fragsize)); -++ } -++ *(in_dma_buf + i) = 0; //release page error -++ } -++ kfree(in_dma_buf); -++ in_dma_buf = NULL; -++ } -++ if(in_dma_pbuf) { -++ kfree(in_dma_pbuf); -++ in_dma_pbuf = NULL; -++ } -++ if(in_dma_buf_data_count) { -++ kfree(in_dma_buf_data_count); -++ in_dma_buf_data_count = NULL; -++ } -++ if(in_empty_queue.id) { -++ kfree(in_empty_queue.id); -++ in_empty_queue.id = NULL; -++ } -++ if(in_full_queue.id) { -++ kfree(in_full_queue.id); -++ in_full_queue.id = NULL; -++ } -++ if(in_busy_queue.id) { -++ kfree(in_busy_queue.id); -++ in_busy_queue.id = NULL; -++ } -++ -++ in_empty_queue.count = fragstotal; -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ -++ return 1; -++} -++ -++static int jz_audio_set_speed(int dev, int rate) -++{ -++ /* 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000 */ -++ long codec_speed; -++ long speed = 0; -++ -++ jz_audio_speed = rate; -++ if (rate > 48000) -++ rate = 48000; -++ if (rate < 8000) -++ rate = 8000; -++ jz_audio_rate = rate; -++ -++ /*switch (rate) { -++ case 8000: -++ speed = 0; -++ break; -++ case 11025: -++ speed = 1; -++ break; -++ case 12000: -++ speed = 2; -++ break; -++ case 16000: -++ speed = 3; -++ break; -++ case 22050: -++ speed = 4; -++ break; -++ case 24000: -++ speed = 5; -++ break; -++ case 32000: -++ speed = 6; -++ break; -++ case 44100: -++ speed = 7; -++ break; -++ case 48000: -++ speed = 8; -++ break; -++ default: -++ break; -++ } -++ printk("set PCMIN or PCMOUT speed.\n"); -++ __pcm_set_clk_rate(speed); -++ __pcm_set_sync_rate(256);*/ -++ -++ return jz_audio_rate; -++} -++ -++ -++static int record_fill_1x8_u(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ volatile unsigned char *s = (unsigned char*)(*(in_dma_buf + id)); -++ volatile unsigned char *dp = (unsigned char*)dst_start; -++ -++ while (count > 0) { -++ *dp = *s; -++ dp ++; -++ s++; -++ count --; -++ cnt ++; -++ } -++ -++ return cnt; -++} -++ -++static int record_fill_2x8_u(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ volatile unsigned char *s = (unsigned char*)(*(in_dma_buf + id)); -++ volatile unsigned char *dp = (unsigned char*)dst_start; -++ -++#if 1 -++ while (count > 0) { -++ *dp = *s; -++ s ++; -++ dp ++; -++ count --; -++ cnt ++; -++ } -++#else -++ while (count > 0) { -++ *dp = *s; -++ s += 2; //skip right sample -++ dp ++; -++ count -= 2; -++ cnt ++; -++ } -++#endif -++ return cnt; -++} -++ -++static int record_fill_1x16_s(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned short d1; -++ unsigned short *s = (unsigned short*)(*(in_dma_buf + id)); -++ unsigned short *dp = (unsigned short *)dst_start; -++ -++ while (count > 0) { -++ *dp = *s; -++ s ++; -++ dp ++; -++ count -= 2; -++ cnt += 2; -++ } -++ -++ return cnt; -++} -++ -++static int record_fill_2x16_s(unsigned long dst_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned short *s = (unsigned short*)(*(in_dma_buf + id)); -++ unsigned short *dp = (unsigned short *)dst_start; -++ -++#if 1 -++ while (count > 0) { -++ *dp = *s; -++ s ++; -++ dp ++; -++ count -= 2; -++ cnt += 2; -++ } -++#else -++ while (count > 0) { -++ *dp = *s; -++ s += 2; //skip right sample -++ dp ++; -++ count -= 4; -++ cnt += 2;/* count in byte */ -++ } -++#endif -++ -++ return cnt; -++} -++ -++static void replay_fill_1x8_u(unsigned long src_start, int count, int id) -++{ -++#if 0 -++ volatile unsigned char *s = (unsigned char *)src_start; -++ volatile unsigned char *dp = (unsigned char *)(*(out_dma_buf + id)); -++ -++ *(out_dma_buf_data_count + id) = count; -++ while (count > 0) { -++ *dp = *s; -++ dp ++; -++ s ++; -++ count --; -++ } -++#else -++ volatile u8 *s = (u8 *)src_start; -++ volatile u8 *dp = (u8 *)(*(out_dma_buf + id)); -++ -++ *(out_dma_buf_data_count + id) = count; -++ while (count > 0) { -++ *dp = *s; -++ dp ++; -++ s ++; -++ count --; -++ } -++#endif -++} -++ -++static void replay_fill_2x8_u(unsigned long src_start, int count, int id) -++{ -++ volatile unsigned char *s = (unsigned char *)src_start; -++ volatile unsigned char *dp = (unsigned char *)(*(out_dma_buf + id)); -++ -++#if 1 -++ *(out_dma_buf_data_count + id) = count; -++ while (count > 0) { -++ *dp = *s; -++ dp ++; -++ s ++; -++ count --; -++ } -++#else -++ while (count > 0) { -++ *dp = *s; -++ s += 2; //skip right sample -++ dp ++; -++ count -= 2; -++ cnt ++; -++ } -++ *(out_dma_buf_data_count + id) = cnt; -++#endif -++} -++ -++ -++static void replay_fill_1x16_s(unsigned long src_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned short d1, l1; -++ signed short sam_to; -++ volatile unsigned short *s = (unsigned short *)src_start; -++ volatile unsigned short *dp = (unsigned short*)(*(out_dma_buf + id)); -++ -++ while (count > 0) { -++ d1 = *s; -++ -++ sam_to = (signed short)d1; -++ if (sam_to >= 0) { -++ sam_to = 0xfff * sam_to / 0x7fff; -++ } else { -++ sam_to = 0 - sam_to; -++ sam_to = 0xfff * sam_to / 0x7fff; -++ sam_to = 0 - sam_to; -++ } -++ d1 = (unsigned short)sam_to; -++ d1 = d1 << 3; -++ l1 = d1 | jz_audio_volume; -++ -++ *dp = l1; -++ s ++; -++ dp ++; -++ count -= 2; -++ cnt += 2 ; -++ } -++ *(out_dma_buf_data_count + id) = cnt; -++} -++ -++static void replay_fill_2x16_s(unsigned long src_start, int count, int id) -++{ -++ int cnt = 0; -++ unsigned short d1, l1; -++ volatile unsigned short *s = (unsigned short *)src_start; -++ volatile unsigned short *dp = (unsigned short*)(*(out_dma_buf + id)); -++ -++#if 1 -++ while (count > 0) { -++ d1 = *s; -++ l1 = (d1 & 0xfff8) | jz_audio_volume; -++ *dp = l1; -++ s ++; -++ dp ++; -++ count -= 2; -++ cnt += 2 ; -++ } -++ *(out_dma_buf_data_count + id) = cnt; -++#else -++ while (count > 0) { -++ d1 = *s; -++ l1 = (d1 & 0xfff8) | jz_audio_volume; -++ *dp = l1; -++ s += 2; //skip right sample -++ dp ++; -++ count -= 4; -++ cnt += 2; -++ } -++ *(out_dma_buf_data_count + id) = cnt; -++#endif -++} -++ -++static unsigned int jz_audio_set_format(int dev, unsigned int fmt) -++{ -++ switch (fmt) { -++ case AFMT_U8: -++ case AFMT_S16_LE: -++ jz_audio_format = fmt; -++ jz_update_filler(jz_audio_format, jz_audio_channels); -++ case AFMT_QUERY: -++ break; -++ } -++ -++ return jz_audio_format; -++} -++ -++static short jz_audio_set_channels(int dev, short channels) -++{ -++ switch (channels) { -++ case 1: -++ case 2: -++ jz_audio_channels = channels; -++ jz_update_filler(jz_audio_format, jz_audio_channels); -++ break; -++ default: -++ printk("channel number is wrong. %d\n",__LINE__); -++ } -++ -++ return jz_audio_channels; -++} -++ -++static void init_codec(void) -++{ -++ printk("set PCM codec RESET pin on LOW, while MCLK occur.\n"); -++ printk("set LINSEL on LOW(8bits) or HIGH(13bits+3bits for PCMOUT gain).\n"); -++} -++ -++static void jz_audio_reset(void) -++{ -++ __pcm_flush_fifo(); -++ __pcm_disable_txfifo(); -++ __pcm_disable_rxfifo(); -++ __pcm_set_transmit_trigger(7); -++ __pcm_set_receive_trigger(7); -++ __pcm_omsb_next_sync(); -++ __pcm_imsb_next_sync(); -++#if MODE_is_8 -++ __pcm_set_iss(8);//8bits decided by LINSEL -++ __pcm_set_oss(8);//8bits decided by LINSEL -++#else -++ __pcm_set_iss(16);//16bits decided by LINSEL -++ __pcm_set_oss(16); -++#endif -++ __pcm_disable_tfs_intr(); -++ __pcm_disable_tur_intr(); -++ __pcm_disable_rfs_intr(); -++ __pcm_disable_ror_intr(); -++ -++ __pcm_disable_receive_dma(); -++ __pcm_disable_transmit_dma(); -++ -++ //init_codec(); -++} -++ -++static int jz_audio_release(struct inode *inode, struct file *file); -++static int jz_audio_open(struct inode *inode, struct file *file); -++static int jz_audio_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg); -++static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait); -++static ssize_t jz_audio_write(struct file *file, const char *buffer,size_t count, loff_t *ppos); -++static ssize_t jz_audio_read(struct file *file, char *buffer,size_t count, loff_t *ppos); -++ -++/* static struct file_operations jz_pcm_audio_fops */ -++static struct file_operations jz_pcm_audio_fops = -++{ -++ owner: THIS_MODULE, -++ open: jz_audio_open, -++ release: jz_audio_release, -++ write: jz_audio_write, -++ read: jz_audio_read, -++ poll: jz_audio_poll, -++ ioctl: jz_audio_ioctl -++}; -++ -++static int jz_pcm_open_mixdev(struct inode *inode, struct file *file) -++{ -++ int i; -++ int minor = MINOR(inode->i_rdev); -++ struct jz_pcm_controller_info *controller = pcm_controller; -++ -++ for (i = 0; i < NR_PCM; i++) -++ if (controller->pcm_codec[i] != NULL && controller->pcm_codec[i]->dev_mixer == minor) -++ goto match; -++ -++ if (!controller) -++ return -ENODEV; -++match: -++ file->private_data = controller->pcm_codec[i]; -++ -++ return 0; -++} -++ -++static int jz_pcm_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -++{ -++ struct pcm_codec *codec = (struct pcm_codec *)file->private_data; -++ return codec->mixer_ioctl(codec, cmd, arg); -++} -++ -++static loff_t jz_pcm_llseek(struct file *file, loff_t offset, int origin) -++{ -++ return -ESPIPE; -++} -++ -++static struct file_operations jz_pcm_mixer_fops = -++{ -++ owner: THIS_MODULE, -++ llseek: jz_pcm_llseek, -++ ioctl: jz_pcm_ioctl_mixdev, -++ open: jz_pcm_open_mixdev, -++}; -++ -++static int pcm_mixer_ioctl(struct pcm_codec *codec, unsigned int cmd, unsigned long arg) -++{ -++ int ret; -++ long val = 0; -++ -++ switch (cmd) { -++ case SOUND_MIXER_READ_STEREODEVS: -++ return put_user(0, (long *) arg); -++ case SOUND_MIXER_READ_CAPS: -++ val = SOUND_CAP_EXCL_INPUT; -++ return put_user(val, (long *) arg); -++ case SOUND_MIXER_READ_DEVMASK: -++ break; -++ case SOUND_MIXER_READ_RECMASK: -++ break; -++ case SOUND_MIXER_READ_RECSRC: -++ break; -++ case SOUND_MIXER_WRITE_VOLUME: -++ ret = get_user(val, (long *) arg); -++ if (ret) -++ return ret; -++ val = val & 0xff; -++ if(val < 0) -++ val = 0; -++ if(val > 100) -++ val = 100; -++ if (val == 100) { -++ dump_pcmc_reg(); -++ return 100; -++ } -++ val = val / 10; -++ switch (val) { -++ case 0: -++ case 1: -++ jz_audio_volume = 7; -++ break; -++ case 2: -++ jz_audio_volume = 6; -++ break; -++ case 3: -++ jz_audio_volume = 5; -++ break; -++ case 4: -++ jz_audio_volume = 4; -++ break; -++ case 5: -++ jz_audio_volume = 3; -++ break; -++ case 6: -++ jz_audio_volume = 2; -++ break; -++ case 7: -++ case 8: -++ jz_audio_volume = 1; -++ break; -++ case 9: -++ case 10: -++ jz_audio_volume = 0; -++ break; -++ } -++ return 0; -++ case SOUND_MIXER_READ_VOLUME: -++ val = jz_audio_volume; -++ ret = val << 8; -++ val = val | ret; -++ return put_user(val, (long *) arg); -++ case SOUND_MIXER_WRITE_MIC: -++ printk("Can not justify Mic gain to the PCM codec.!\n"); -++ return -ENOSYS; -++ -++ case SOUND_MIXER_READ_MIC: -++ printk("Can not justify Mic gain to the PCM codec.!\n"); -++ return -ENOSYS; -++ default: -++ return -ENOSYS; -++ } -++ -++ return 0; -++} -++ -++ -++int pcm_probe_codec(struct pcm_codec *codec) -++{ -++ /* generic OSS to PCM wrapper */ -++ codec->mixer_ioctl = pcm_mixer_ioctl; -++ return 1; -++} -++ -++/* PCM codec initialisation. */ -++static int __init jz_pcm_codec_init(struct jz_pcm_controller_info *controller) -++{ -++ int num_pcm = 0; -++ struct pcm_codec *codec; -++ -++ for (num_pcm = 0; num_pcm < NR_PCM; num_pcm++) { -++ if ((codec = kmalloc(sizeof(struct pcm_codec),GFP_KERNEL)) == NULL) -++ return -ENOMEM; -++ memset(codec, 0, sizeof(struct pcm_codec)); -++ codec->private_data = controller; -++ codec->id = num_pcm; -++ -++ if (pcm_probe_codec(codec) == 0) -++ break; -++ if ((codec->dev_mixer = register_sound_mixer(&jz_pcm_mixer_fops, -1)) < 0) { -++ printk(KERN_ERR "Jz PCM: couldn't register mixer!\n"); -++ kfree(codec); -++ break; -++ } -++ controller->pcm_codec[num_pcm] = codec; -++ } -++ -++ return num_pcm; -++} -++ -++static void jz_update_filler(int format, int channels) -++{ -++#define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3)) -++ -++ switch (TYPE(format, channels)) { -++ default: -++ case TYPE(AFMT_U8, 1): -++ replay_filler = replay_fill_1x8_u; -++ record_filler = record_fill_1x8_u; -++ break; -++ case TYPE(AFMT_U8, 2): -++ /*replay_filler = replay_fill_2x8_u; -++ record_filler = record_fill_2x8_u;*/ -++ printk("channel is 2. Line:%d\n",__LINE__); -++ break; -++ case TYPE(AFMT_S16_LE, 1): -++ replay_filler = replay_fill_1x16_s; -++ record_filler = record_fill_1x16_s; -++ break; -++ case TYPE(AFMT_S16_LE, 2): -++ /*replay_filler = replay_fill_2x16_s; -++ record_filler = record_fill_2x16_s;*/ -++ printk("channel is 2. Line:%d\n",__LINE__); -++ break; -++ } -++} -++ -++static void __init attach_jz_pcm(struct jz_pcm_controller_info *controller) -++{ -++ char *name; -++ int adev;//No of Audio device. -++ int err; -++ -++ name = controller->name; -++ /* register /dev/audio */ -++ adev = register_sound_dsp(&jz_pcm_audio_fops, -1); -++ if (adev < 0) -++ goto audio_failed; -++ /* initialize PCM codec and register /dev/mixer */ -++ if (jz_pcm_codec_init(controller) <= 0) -++ goto mixer_failed; -++ -++ controller->tmp1 = (void *)__get_free_pages(GFP_KERNEL, JZCODEC_USER_BUFFER); -++ if (!controller->tmp1) { -++ printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); -++ goto tmp1_failed; -++ } -++ printk("DMA_ID_PCM_TX=0x%08x DMA_ID_PCM_RX=0x%08x\n",DMA_ID_PCM_TX ,DMA_ID_PCM_RX); -++ if ((controller->dma1 = jz_request_dma(DMA_ID_PCM_TX, "audio dac", jz_pcm_replay_dma_irq, IRQF_DISABLED, controller)) < 0) { -++ printk(KERN_ERR "%s: can't reqeust DMA DAC channel.\n", name); -++ goto dma1_failed; -++ } -++ if ((controller->dma2 = jz_request_dma(DMA_ID_PCM_RX, "audio adc", jz_pcm_record_dma_irq, IRQF_DISABLED, controller)) < 0) { -++ printk(KERN_ERR "%s: can't reqeust DMA ADC channel.\n", name); -++ goto dma2_failed; -++ } -++ printk("JzSOC On-Chip PCM controller registered (DAC: DMA(play):%d/IRQ%d,\n ADC: DMA(record):%d/IRQ%d)\n", controller->dma1, get_dma_done_irq(controller->dma1), controller->dma2, get_dma_done_irq(controller->dma2)); -++ -++ err = request_irq(IRQ_PCM, jz_pcm_irq, IRQF_DISABLED, "pcm irq", controller); -++ if (err < 0) -++ printk("can't allocate pcm irq.\n"); -++ controller->dev_audio = adev; -++ -++ return; -++dma2_failed: -++ jz_free_dma(controller->dma2); -++dma1_failed: -++ jz_free_dma(controller->dma1); -++tmp1_failed: -++ free_pages((unsigned long)controller->tmp1, JZCODEC_USER_BUFFER); -++ -++mixer_failed: -++ unregister_sound_dsp(adev); -++audio_failed: -++ return; -++} -++ -++ -++static int __init probe_jz_pcm(struct jz_pcm_controller_info **controller) -++{ -++ if ((*controller = kmalloc(sizeof(struct jz_pcm_controller_info), -++ GFP_KERNEL)) == NULL) { -++ printk(KERN_ERR "Jz PCM Controller: out of memory.\n"); -++ return -ENOMEM; -++ } -++ -++ (*controller)->name = "Jz PCM controller"; -++ (*controller)->opened1 = 0; -++ (*controller)->opened2 = 0; -++ init_waitqueue_head(&(*controller)->adc_wait); -++ init_waitqueue_head(&(*controller)->dac_wait); -++ spin_lock_init(&(*controller)->lock); -++ init_waitqueue_head(&rx_wait_queue); -++ init_waitqueue_head(&tx_wait_queue); -++ -++ return 0; -++} -++ -++static void __exit unload_jz_pcm(struct jz_pcm_controller_info *controller) -++{ -++ int adev = controller->dev_audio; -++ -++ __pcm_reset(); -++ schedule_timeout(5); -++ __pcm_disable(); -++ __pcm_clk_disable(); -++ __pcm_flush_fifo(); -++ -++ controller->dev_audio = -1; -++ jz_free_dma(controller->dma1); -++ jz_free_dma(controller->dma2); -++ free_pages((unsigned long)controller->tmp1, JZCODEC_USER_BUFFER); -++ -++ if (adev >= 0) -++ unregister_sound_dsp(controller->dev_audio); -++} -++ -++static int __init init_jz_pcm(void) -++{ -++ int errno; -++ /* 24M OSC ---> CPCCR.ECS ---> PCMCDR.PCMS ---> cpm_pcm_sysclk(X) */ -++ long X = 12000000; //in Hz /* 6.144 MHz <= X <= 264.192 MHz */ -++ -++#if 0 -++ /* pcm_sys_clk is from PLL divsion */ -++ REG_CPM_PCMCDR = 0x8000001b; -++ REG_CPM_CPCCR |= 0x00400000; -++#endif -++ /* pcm_sys_clk is from external clock */ -++ /* reset codec GPF4 */ -++ __gpio_as_output(32 * 5 + 4); -++ __gpio_set_pin(32 * 5 + 4); -++ mdelay(1); -++ -++ __pcm_reset(); -++ schedule_timeout(5); -++ __pcm_clk_disable(); -++ -++ /* set CPM to output cpm-pcm-sysclk ,assume cpm-pcm-sysclk is X Hz */ -++ /* PCMCLK must be 2048000 Hz, it is 256 mutil of PCMSYNC */ -++ //__pcm_set_clk_rate(X, 2048000); -++ __pcm_set_clk_rate(X, 2000000); -++ /* PCMSYNC must be 8000 Hz. 2048000 / 256 = 8000 */ -++ __pcm_set_sync_rate(2048000, 8000); -++ //__pcm_set_sync_rate(2000000, 8000); -++ __pcm_set_sync_len(0); -++ -++ __pcm_flush_fifo(); -++ __pcm_disable_txfifo(); -++ __pcm_disable_rxfifo(); -++ __pcm_set_transmit_trigger(7); -++ __pcm_set_receive_trigger(7); -++ __pcm_omsb_next_sync(); -++ __pcm_imsb_next_sync(); -++ -++#if MODE_is_8 -++ __pcm_set_iss(8);//8bits decided by LINSEL -++ __pcm_set_oss(8); -++#else -++ __pcm_set_iss(16);//16bits decided by LINSEL -++ __pcm_set_oss(16); -++#endif -++ __pcm_set_valid_slot(1); -++ -++ __pcm_disable_tfs_intr(); -++ __pcm_disable_tur_intr(); -++ __pcm_disable_rfs_intr(); -++ __pcm_disable_ror_intr(); -++ -++ __pcm_disable_receive_dma(); -++ __pcm_disable_transmit_dma(); -++ -++ __pcm_last_sample(); -++ __pcm_as_master(); -++ -++ __pcm_enable(); -++ __pcm_clk_enable(); -++ -++ if ((errno = probe_jz_pcm(&pcm_controller)) < 0) -++ return errno; -++ attach_jz_pcm(pcm_controller); -++ -++ out_empty_queue.id = NULL; -++ out_full_queue.id = NULL; -++ out_busy_queue.id = NULL; -++ in_empty_queue.id = NULL; -++ in_full_queue.id = NULL; -++ in_busy_queue.id = NULL; -++ -++ jz_audio_fragsize = JZCODEC_RW_BUFFER_SIZE * PAGE_SIZE; -++ jz_audio_fragstotal = JZCODEC_RW_BUFFER_TOTAL ; -++ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ -++ __gpio_clear_pin(32 * 5 + 4); -++ udelay(100); -++ -++ __gpio_set_pin(32 * 5 + 4); -++ dump_pcmc_reg(); -++ -++ return 0; -++} -++ -++ -++static void __exit cleanup_jz_pcm(void) -++{ -++ unload_jz_pcm(pcm_controller); -++ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++} -++ -++module_init(init_jz_pcm); -++module_exit(cleanup_jz_pcm); -++ -++static int drain_adc(struct jz_pcm_controller_info *ctrl, int nonblock) -++{ -++ unsigned long flags; -++ int count, i=0; -++ -++ for (;;) { -++ if ( i < MAXDELAY ) { -++ udelay(10); -++ i++; -++ } else -++ break; -++ -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma2); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if (count <= 0) -++ break; -++ -++ if (nonblock) -++ return -EBUSY; -++ } -++ -++ return 0; -++} -++static int drain_dac(struct jz_pcm_controller_info *ctrl, int nonblock) -++{ -++ unsigned long flags; -++ int count, ele, i=0; -++ -++ for (;;) { -++ if(!nonblock) {//blocked -++ if ( i < MAXDELAY ) { -++ udelay(10); -++ i++; -++ } else -++ break; -++ -++ ele = elements_in_queue(&out_full_queue); -++ if(ele <= 0) { -++ udelay(10); -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if (count <= 0) -++ break; -++ } -++ } else {//non-blocked -++ mdelay(100); -++ ele = elements_in_queue(&out_full_queue); -++ -++ if(ele <= 0) { -++ mdelay(100); -++ -++ spin_lock_irqsave(&ctrl->lock, flags); -++ count = get_dma_residue(ctrl->dma1); -++ spin_unlock_irqrestore(&ctrl->lock, flags); -++ if (count <= 0) -++ break; -++ } -++ } -++ } -++ -++ return 0; -++} -++ -++static int jz_audio_release(struct inode *inode, struct file *file) -++{ -++ struct jz_pcm_controller_info *controller = (struct jz_pcm_controller_info *) file->private_data; -++ -++ if (controller == NULL) -++ return -ENODEV; -++ -++ if ( controller->opened1 == 1 ) { -++ __pcm_enable_transmit_dma(); -++ __pcm_enable_txfifo(); -++ drain_dac(controller, file->f_flags & O_NONBLOCK); -++ disable_dma(controller->dma1); -++ set_dma_count(controller->dma1, 0); -++ -++ __pcm_disable_transmit_dma(); -++ __pcm_disable_txfifo(); -++ -++ spin_lock(&controller->ioctllock); -++ controller->total_bytes = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->blocks = 0; -++ controller->nextOut = 0; -++ spin_unlock(&controller->ioctllock); -++ //__pcm_disable(); -++ controller->opened1 = 0; -++ } -++ -++ if ( controller->opened2 == 1 ) { -++ first_record_call = 1; -++ __pcm_enable_receive_dma(); -++ __pcm_enable_rxfifo(); -++ drain_adc(controller, file->f_flags & O_NONBLOCK); -++ disable_dma(controller->dma2); -++ set_dma_count(controller->dma2, 0); -++ __pcm_disable_receive_dma(); -++ __pcm_disable_rxfifo(); -++ -++ spin_lock(&controller->ioctllock); -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextIn = 0; -++ spin_unlock(&controller->ioctllock); -++ //__pcm_disable(); -++ controller->opened2 = 0; -++ } -++ __pcm_disable_tfs_intr(); -++ __pcm_disable_tur_intr(); -++ __pcm_disable_rfs_intr(); -++ __pcm_disable_ror_intr(); -++ -++ return 0; -++} -++ -++static int jz_audio_open(struct inode *inode, struct file *file) -++{ -++ int i; -++ struct jz_pcm_controller_info *controller = pcm_controller; -++ -++ if (controller == NULL) -++ return -ENODEV; -++ -++ if (controller->opened1 == 1 || controller->opened2 == 1 ) { -++ printk("\naudio is busy!\n"); -++ return -EBUSY; -++ } -++ REG_DMAC_DMACKE(0) = 0x3f; -++ REG_DMAC_DMACKE(1) = 0x3f; -++ if (file->f_mode & FMODE_WRITE) { -++ if (controller->opened1 == 1) -++ return -EBUSY; -++ controller->opened1 = 1; -++ //for ioctl -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextOut = 0; -++ -++ out_empty_queue.count = jz_audio_fragstotal; -++ for (i=0;i < jz_audio_fragstotal;i++) -++ *(out_empty_queue.id + i) = i; -++ out_busy_queue.count = 0; -++ out_full_queue.count = 0; -++ /* set PCMOUT params */ -++ } -++ -++ if (file->f_mode & FMODE_READ) { -++ if (controller->opened2 == 1) -++ return -EBUSY; -++ controller->opened2 = 1; -++ first_record_call = 1; -++ //for ioctl -++ controller->total_bytes = 0; -++ jz_audio_dma_tran_count = 0; -++ controller->count = 0; -++ controller->finish = 0; -++ controller->blocks = 0; -++ controller->nextIn = 0; -++ in_empty_queue.count = jz_audio_fragstotal; -++ for (i=0;i < jz_audio_fragstotal;i++) -++ *(in_empty_queue.id + i) = i; -++ in_full_queue.count = 0; -++ in_busy_queue.count = 0; -++ /* set PCMIN params */ -++ } -++ -++ file->private_data = controller; -++ jz_audio_reset(); -++ __pcm_enable(); -++ -++ return 0; -++} -++ -++static int jz_audio_ioctl(struct inode *inode, struct file *file, -++ unsigned int cmd, unsigned long arg) -++{ -++ int val,fullc,busyc,unfinish,newfragstotal,newfragsize; -++ unsigned int flags; -++ audio_buf_info abinfo; -++ int i, bytes, id; -++ count_info cinfo; -++ struct jz_pcm_controller_info *controller = (struct jz_pcm_controller_info *) file->private_data; -++ -++ val = 0; -++ bytes = 0; -++ switch (cmd) { -++ case OSS_GETVERSION: -++ return put_user(SOUND_VERSION, (int *)arg); -++ case SNDCTL_DSP_RESET: -++ return 0; -++ case SNDCTL_DSP_SYNC: -++ if (file->f_mode & FMODE_WRITE) -++ drain_dac(controller, file->f_flags & O_NONBLOCK); -++ return 0; -++ case SNDCTL_DSP_SPEED: -++ { -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ /* set smaple rate */ -++ if (val >= 0) -++ jz_audio_set_speed(controller->dev_audio, val); -++ return put_user(val, (int *)arg); -++ } -++ case SNDCTL_DSP_STEREO: -++ /* set stereo or mono channel */ -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ -++ jz_audio_set_channels(controller->dev_audio, val ? 2 : 1); -++ return 0; -++ -++ case SNDCTL_DSP_GETBLKSIZE: -++ //return put_user(4*PAGE_SIZE, (int *)arg); -++ return put_user(jz_audio_fragsize , (int *)arg); -++ case SNDCTL_DSP_GETFMTS: -++ /* Returns a mask of supported sample format*/ -++ return put_user(AFMT_U8 | AFMT_S16_LE, (int *)arg); -++ -++ case SNDCTL_DSP_SETFMT: -++ { -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ /* Select sample format */ -++ if (val != AFMT_QUERY) -++ jz_audio_set_format(controller->dev_audio,val); -++ else -++ if (file->f_mode & FMODE_READ) -++ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -++ else -++ val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; -++ return put_user(val, (int *)arg); -++ } -++ -++ case SNDCTL_DSP_CHANNELS: -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ printk("%s:%s:%d\n",__FILE__,__FUNCTION__,__LINE__); -++ jz_audio_set_channels(controller->dev_audio, val); -++ return put_user(val, (int *)arg); -++ -++ case SNDCTL_DSP_POST: -++ /* FIXME: the same as RESET ?? */ -++ return 0; -++ -++ case SNDCTL_DSP_SUBDIVIDE: -++ return 0; -++ -++ case SNDCTL_DSP_SETFRAGMENT: -++ get_user(val, (long *) arg); -++ newfragsize = 1 << (val & 0xFFFF);//16 least bits -++ -++ if (newfragsize < 4 * PAGE_SIZE) -++ newfragsize = 4 * PAGE_SIZE; -++ if (newfragsize > (16 * PAGE_SIZE)) //16 PAGE_SIZE -++ newfragsize = 16 * PAGE_SIZE; -++ -++ newfragstotal = (val >> 16) & 0x7FFF; -++ if (newfragstotal < 2) -++ newfragstotal = 2; -++ if (newfragstotal > 32) -++ newfragstotal = 32; -++ if((jz_audio_fragstotal == newfragstotal) && (jz_audio_fragsize == newfragsize)) -++ return 0; -++ Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ mdelay(500); -++ jz_audio_fragstotal = newfragstotal; -++ jz_audio_fragsize = newfragsize; -++ -++ Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -++ mdelay(10); -++ -++ return 0; -++ case SNDCTL_DSP_GETCAPS: -++ return put_user(DSP_CAP_REALTIME|DSP_CAP_BATCH, (int *)arg); -++ case SNDCTL_DSP_NONBLOCK: -++ file->f_flags |= O_NONBLOCK; -++ return 0; -++ case SNDCTL_DSP_SETDUPLEX: -++ return -EINVAL; -++ case SNDCTL_DSP_GETOSPACE: -++ { -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ //unused fragment amount -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ jz_audio_fragments = elements_in_queue(&out_empty_queue); -++ for (i = 0; i < jz_audio_fragments; i++) -++ bytes += jz_audio_fragsize; -++ -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ abinfo.fragments = jz_audio_fragments; -++ abinfo.fragstotal = jz_audio_fragstotal; -++ abinfo.fragsize = jz_audio_fragsize; -++ abinfo.bytes = bytes; -++ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; -++ } -++ case SNDCTL_DSP_GETISPACE: -++ if (!(file->f_mode & FMODE_READ)) -++ return -EINVAL; -++ bytes = 0; -++ //unused fragment amount -++ jz_audio_fragments = elements_in_queue(&in_empty_queue); -++ for (i = 0; i < jz_audio_fragments; i++) -++ bytes += jz_audio_fragsize; -++ -++ abinfo.fragments = jz_audio_fragments; -++ abinfo.fragstotal = jz_audio_fragstotal; -++ abinfo.fragsize = jz_audio_fragsize; -++ abinfo.bytes = bytes; -++ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; -++ case SNDCTL_DSP_GETTRIGGER: -++ val = 0; -++ if (file->f_mode & FMODE_READ && in_dma_buf) -++ val |= PCM_ENABLE_INPUT; -++ if (file->f_mode & FMODE_WRITE && out_dma_buf) -++ val |= PCM_ENABLE_OUTPUT; -++ return put_user(val, (int *)arg); -++ -++ case SNDCTL_DSP_SETTRIGGER: -++ if (get_user(val, (int *)arg)) -++ return -EFAULT; -++ return 0; -++ case SNDCTL_DSP_GETIPTR: -++ if (!(file->f_mode & FMODE_READ)) -++ return -EINVAL; -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ cinfo.bytes = controller->total_bytes; -++ cinfo.blocks = controller->blocks; -++ cinfo.ptr = controller->nextIn; -++ controller->blocks = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); -++ case SNDCTL_DSP_GETOPTR: -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ cinfo.bytes = controller->total_bytes; -++ cinfo.blocks = controller->blocks; -++ cinfo.ptr = controller->nextOut; -++ controller->blocks = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); -++ case SNDCTL_DSP_GETODELAY: -++ if (!(file->f_mode & FMODE_WRITE)) -++ return -EINVAL; -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ unfinish = 0; -++ fullc = elements_in_queue(&out_full_queue); -++ busyc = elements_in_queue(&out_busy_queue); -++ for(i = 0;i < fullc ;i ++) { -++ id = *(out_full_queue.id + i); -++ unfinish += *(out_dma_buf_data_count + id); -++ } -++ for(i = 0;i < busyc ;i ++) { -++ id = *(out_busy_queue.id + i); -++ unfinish += get_dma_residue(controller->dma1); -++ } -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ return put_user(unfinish, (int *) arg); -++ case SOUND_PCM_READ_RATE: -++ return put_user(jz_audio_rate, (int *)arg); -++ case SOUND_PCM_READ_CHANNELS: -++ return put_user(jz_audio_channels, (int *)arg); -++ case SOUND_PCM_READ_BITS: -++ return put_user((jz_audio_format & (AFMT_S8 | AFMT_U8)) ? 8 : 16, (int *)arg); -++ case SNDCTL_DSP_MAPINBUF: -++ case SNDCTL_DSP_MAPOUTBUF: -++ case SNDCTL_DSP_SETSYNCRO: -++ case SOUND_PCM_WRITE_FILTER: -++ case SOUND_PCM_READ_FILTER: -++ return -EINVAL; -++ } -++ return -EINVAL; -++} -++ -++static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait) -++{ -++ unsigned long flags; -++ unsigned int mask = 0; -++ struct jz_pcm_controller_info *controller = (struct jz_pcm_controller_info *) file->private_data; -++ -++ if (file->f_mode & FMODE_WRITE) { -++ if (elements_in_queue(&out_empty_queue) > 0) -++ return POLLOUT | POLLWRNORM; -++ poll_wait(file, &controller->dac_wait, wait); -++ } -++ -++ if (file->f_mode & FMODE_READ) { -++ if (elements_in_queue(&in_full_queue) > 0) -++ return POLLIN | POLLRDNORM; -++ poll_wait(file, &controller->adc_wait, wait); -++ } -++ -++ spin_lock_irqsave(&controller->lock, flags); -++ if (file->f_mode & FMODE_WRITE) { -++ if (elements_in_queue(&out_empty_queue) > 0) -++ mask |= POLLOUT | POLLWRNORM; -++ } else if (file->f_mode & FMODE_READ) { -++ if (elements_in_queue(&in_full_queue) > 0) -++ mask |= POLLIN | POLLRDNORM; -++ } -++ spin_unlock_irqrestore(&controller->lock, flags); -++ -++ return mask; -++} -++ -++static ssize_t jz_audio_read(struct file *file, char *buffer, size_t count, loff_t *ppos) -++{ -++ int id, ret = 0, left_count, copy_count, cnt = 0; -++ struct jz_pcm_controller_info *controller = (struct jz_pcm_controller_info *) file->private_data; -++ -++ if (count < 0) -++ return -EINVAL; -++ -++ __pcm_enable_receive_dma(); -++ __pcm_enable_rxfifo(); -++ -++ spin_lock(&controller->ioctllock); -++ controller->nextIn = 0; -++ spin_unlock(&controller->ioctllock); -++ -++ spin_lock(&controller->lock); -++ -++#if 0 -++ if (count < 2 * PAGE_SIZE ) -++ copy_count = count * 16 / (jz_audio_channels * jz_audio_format); -++ else -++ copy_count = 2 * PAGE_SIZE ; -++#else -++ if (count <= jz_audio_fragsize) -++ copy_count = count; -++ else -++ copy_count = jz_audio_fragsize; -++#endif -++ -++ left_count = count; -++ spin_unlock(&controller->lock); -++ -++ if (first_record_call) { -++ first_record_call = 0; -++audio_read_back_first: -++ if ((id = get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id); -++ -++ spin_lock(&controller->lock); -++ *(in_dma_buf_data_count + id) = copy_count; -++ spin_unlock(&controller->lock); -++ -++ dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); -++ audio_start_dma(controller->dma2,file->private_data, -++ *(in_dma_pbuf + id), -++ *(in_dma_buf_data_count + id), -++ DMA_MODE_READ); -++ -++ sleep_on(&rx_wait_queue); -++ } else -++ goto audio_read_back_first; -++ } -++ -++ while (left_count > 0) { -++audio_read_back_second: -++ if (elements_in_queue(&in_full_queue) <= 0) { -++ if (file->f_flags & O_NONBLOCK) -++ return ret ? ret : -EAGAIN; -++ else -++ sleep_on(&rx_wait_queue); -++ } -++ -++ if ((id = get_buffer_id(&in_full_queue)) >= 0) { -++ spin_lock(&controller->lock); -++ cnt = record_filler((unsigned long)controller->tmp1+ret, copy_count, id); -++ spin_unlock(&controller->lock); -++ put_buffer_id(&in_empty_queue, id); -++ } else -++ goto audio_read_back_second; -++ -++ if (elements_in_queue(&in_busy_queue) == 0) { -++ if ((id=get_buffer_id(&in_empty_queue)) >= 0) { -++ put_buffer_id(&in_busy_queue, id); -++ spin_lock(&controller->lock); -++ *(in_dma_buf_data_count + id) = copy_count; -++ spin_unlock(&controller->lock); -++ -++ dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); -++ audio_start_dma(controller->dma2,file->private_data, -++ *(in_dma_pbuf + id), -++ *(in_dma_buf_data_count + id), -++ DMA_MODE_READ); -++ } -++ } -++ if (ret + cnt > count) { -++ spin_lock(&controller->lock); -++ cnt = count - ret; -++ spin_unlock(&controller->lock); -++ } -++ if (copy_to_user(buffer+ret, controller->tmp1+ret, cnt)) -++ return ret ? ret : -EFAULT; -++ spin_lock(&controller->lock); -++ ret += cnt; -++ spin_unlock(&controller->lock); -++ -++ spin_lock(&controller->ioctllock); -++ controller->nextIn += ret; -++ spin_unlock(&controller->ioctllock); -++ -++ spin_lock(&controller->lock); -++ left_count -= cnt; -++ spin_unlock(&controller->lock); -++ } -++ -++ return ret; -++} -++ -++static ssize_t jz_audio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) -++{ -++ int id, ret, left_count, copy_count; -++ unsigned int flags; -++ struct jz_pcm_controller_info *controller = (struct jz_pcm_controller_info *) file->private_data; -++ -++ if (count <= 0) -++ return -EINVAL; -++ -++ __pcm_enable_transmit_dma(); -++ __pcm_enable_txfifo(); -++ -++ spin_lock_irqsave(&controller->ioctllock, flags); -++ controller->nextOut = 0; -++ spin_unlock_irqrestore(&controller->ioctllock, flags); -++ -++#if 0 -++ if (count < 2 * PAGE_SIZE ) -++ copy_count = count; -++ else -++ copy_count = 2 * PAGE_SIZE; -++#else -++ if (count <= jz_audio_fragsize) -++ copy_count = count; -++ else -++ copy_count = jz_audio_fragsize; -++#endif -++ -++ left_count = count; -++ ret = 0; -++ -++ if (copy_from_user(controller->tmp1, buffer, count)) { -++ printk("copy_from_user failed:%d",ret); -++ return ret ? ret : -EFAULT; -++ } -++ -++ while (left_count > 0) { -++audio_write_back: -++ if (elements_in_queue(&out_empty_queue) == 0) { -++ // all are full -++ if (file->f_flags & O_NONBLOCK) -++ return ret; -++ else -++ sleep_on(&tx_wait_queue); -++ } -++ /* the end fragment size in this write */ -++ if (ret + copy_count > count) -++ copy_count = count - ret; -++ if ((id = get_buffer_id(&out_empty_queue)) >= 0) { -++ replay_filler((unsigned long)controller->tmp1 + ret, copy_count, id); -++ if(*(out_dma_buf_data_count + id) > 0) { -++ put_buffer_id(&out_full_queue, id); //busy in -++ dma_cache_wback_inv(*(out_dma_buf + id), *(out_dma_buf_data_count + id)); -++ } else -++ put_buffer_id(&out_empty_queue, id); //spare -++ } else -++ goto audio_write_back; -++ -++ left_count = left_count - copy_count; -++ ret += copy_count;//all is in byte -++ -++ spin_lock(&controller->ioctllock); -++ controller->nextOut += ret; -++ spin_unlock(&controller->ioctllock); -++ -++ if (elements_in_queue(&out_busy_queue) == 0) { -++ if ((id=get_buffer_id(&out_full_queue)) >= 0) { -++ put_buffer_id(&out_busy_queue, id); -++ -++ if(*(out_dma_buf_data_count + id) > 0) { -++ audio_start_dma(controller->dma1, -++ file->private_data, -++ *(out_dma_pbuf + id), -++ *(out_dma_buf_data_count + id), -++ DMA_MODE_WRITE); -++ -++ } -++ } -++ } -++ } -++ -++ return ret; -++} -++ -++static void dump_pcmc_reg(void) -++{ -++ printk("REG_DMAC_DMACKE(0) : 0x%08x\n",REG_DMAC_DMACKE(0)); -++ printk("REG_DMAC_DMACKE(1) : 0x%08x\n",REG_DMAC_DMACKE(1)); -++ printk("REG_CPM_CLKGR=0x%08x\n",REG_CPM_CLKGR); -++ printk("REG_CPM_CPCCR : 0x%08x\n",REG_CPM_CPCCR); -++ printk("REG_CPM_PCMCDR : 0x%08x\n",REG_CPM_PCMCDR); -++ printk("REG_PCM_CLT : 0x%08x\n",REG_PCM_CTL); -++ printk("REG_PCM_CFG : 0x%08x\n",REG_PCM_CFG); -++ printk("REG_PCM_INTC : 0x%08x\n",REG_PCM_INTC); -++ printk("REG_PCM_INTS : 0x%08x\n",REG_PCM_INTS); -++ printk("REG_PCM_DIV : 0x%08x\n",REG_PCM_DIV); -++} -+diff -urN linux-2.6.24.7.old/sound/oss/jzcodec.c linux-2.6.24.7/sound/oss/jzcodec.c -+--- linux-2.6.24.7.old/sound/oss/jzcodec.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/oss/jzcodec.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,443 @@ -++/* -++ * linux/drivers/sound/jzcodec.c -++ * -++ * JzSOC internal audio driver. -++ * -++ */ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "sound_config.h" -++ -++#define USE_NONE 1 -++#define USE_MIC 2 -++#define USE_LINEIN 3 -++ -++typedef struct hpvol_shift_s -++{ -++ int hpvol; -++ int shift; -++} hpvol_shift_t; -++ -++extern mixer_info info; -++extern _old_mixer_info old_info; -++extern int codec_volue_shift; -++extern hpvol_shift_t hpvol_shift_table[72]; -++extern int abnormal_data_count; -++ -++extern void (*set_codec_mode)(void); -++extern void (*each_time_init_codec)(void); -++extern int (*set_codec_startup_param)(void); -++extern void (*set_codec_volume_table)(void); -++extern void (*set_codec_record)(int mode); -++extern void (*set_codec_replay)(void); -++extern void (*set_codec_replay_record)(int mode); -++extern void (*turn_on_codec)(void); -++extern void (*turn_off_codec)(void); -++extern void (*set_codec_speed)(int rate); -++extern void (*reset_codec)(void); -++extern void (*codec_mixer_old_info_id_name)(void); -++extern void (*codec_mixer_info_id_name)(void); -++extern void (*set_codec_bass)(int val); -++extern void (*set_codec_volume)(int val); -++extern void (*set_codec_mic)(int val); -++extern void (*set_codec_line)(int val); -++extern void (*i2s_resume_codec)(void); -++extern void (*i2s_suspend_codec)(void); -++extern void (*set_codec_direct_mode)(void); -++extern void (*clear_codec_direct_mode)(void); -++ -++static int jzcodec_reg[2]; -++ -++void set_jzcodec_mode(void); -++void each_time_init_jzcodec(void); -++int set_jzcodec_startup_param(void); -++void set_jzcodec_volume_table(void); -++void set_jzcodec_replay(void); -++void set_jzcodec_record(int mode); -++void turn_on_jzcodec(void); -++void turn_off_jzcodec(void); -++void set_jzcodec_speed(int rate); -++void reset_jzcodec(void); -++void jzcodec_mixer_old_info_id_name(void); -++void jzcodec_mixer_info_id_name(void); -++void set_jzcodec_bass(int val); -++void set_jzcodec_volume(int val); -++void set_jzcodec_mic(int val); -++void set_jzcodec_line(int val); -++void in_codec_app1(void); -++void in_codec_app12(void); -++void HP_turn_on(void); -++void HP_turn_off(void); -++void resume_jzcodec(void); -++void suspend_jzcodec(void); -++void set_jzcodec_replay_record(int mode); -++ -++void set_jzcodec_mode(void) -++{ -++ __i2s_internal_codec(); -++ __i2s_as_slave(); -++ __i2s_select_i2s(); -++ __aic_select_i2s(); -++ -++ REG_ICDC_CDCCR1 = 0x001b2303; -++ schedule_timeout(1); -++ REG_ICDC_CDCCR1 = 0x001b2302; -++} -++ -++void each_time_init_jzcodec(void) -++{ -++ __i2s_disable(); -++ __i2s_as_slave(); -++ __i2s_set_oss_sample_size(16); -++ __i2s_set_iss_sample_size(16); -++} -++ -++int set_jzcodec_startup_param(void) -++{ -++ REG_ICDC_CDCCR1 = 0x001b2300; -++ schedule_timeout(50); -++ REG_ICDC_CDCCR1 = 0x00033300; -++ schedule_timeout(5); -++ REG_ICDC_CDCCR1 = 0x17026300; -++ -++ return 1; -++} -++void set_jzcodec_volume_table(void) -++{ -++ int errno,hpvol_step,sample_shift; -++ -++ codec_volue_shift = 0; -++ hpvol_step = 3; -++ sample_shift = 0; -++ for(errno = 0;errno < 72;errno++) { -++ hpvol_shift_table[errno].hpvol = hpvol_step; -++ hpvol_shift_table[errno].shift = sample_shift; -++ hpvol_step --; -++ if(hpvol_step <= 0) { -++ hpvol_step = 3; -++ sample_shift ++; -++ } -++ } -++} -++ -++void set_jzcodec_replay(void) -++{ -++ in_codec_app1(); -++} -++ -++void set_jzcodec_record(int mode) -++{ -++ switch (mode) { -++ case USE_NONE: -++ case USE_MIC: -++ in_codec_app12(); -++ abnormal_data_count = 0; -++ break; -++ case USE_LINEIN: -++ REG_ICDC_CDCCR1 = 0x27022000;//for linein -++ mdelay(300); -++ break; -++ } -++} -++ -++void set_jzcodec_replay_record(int mode) -++{ -++ long val = 0; -++ REG_ICDC_CDCCR1 = 0x00037302; -++ mdelay(2); -++ REG_ICDC_CDCCR1 = 0x03006000; -++ mdelay(2); -++ -++ switch (mode) { -++ case USE_NONE: -++ case USE_MIC: -++ REG_ICDC_CDCCR1 = 0x17022000;//for mic -++ break; -++ case USE_LINEIN: -++ REG_ICDC_CDCCR1 = 0x27022000;//for linein -++ break; -++ } -++ -++ val = REG_ICDC_CDCCR2; -++ val &= 0x0000ff00; -++ val |= 0x00170030; -++ REG_ICDC_CDCCR2 = val; -++} -++ -++void turn_on_jzcodec(void) -++{ -++ HP_turn_on(); -++} -++ -++void set_jzcodec_direct_mode(void) -++{ -++ long val = 0; -++ REG_ICDC_CDCCR1 = 0x14000000; -++ val &= 0x0000ff00; -++ val |= 0x001f0033; -++ REG_ICDC_CDCCR2 = val; -++ mdelay(300); -++} -++ -++void clear_jzcodec_direct_mode(void) -++{ -++ HP_turn_off(); -++} -++ -++void turn_off_jzcodec(void) -++{ -++ HP_turn_off(); -++} -++ -++void set_jzcodec_speed(int rate) -++{ -++ long codec_speed,speed = 0; -++ switch (rate) { -++ case 8000: -++ speed = 0; -++ break; -++ case 11025: -++ speed = 1; -++ break; -++ case 12000: -++ speed = 2; -++ break; -++ case 16000: -++ speed = 3; -++ break; -++ case 22050: -++ speed = 4; -++ break; -++ case 24000: -++ speed = 5; -++ break; -++ case 32000: -++ speed = 6; -++ break; -++ case 44100: -++ speed = 7; -++ break; -++ case 48000: -++ speed = 8; -++ break; -++ default: -++ break; -++ } -++ -++ codec_speed = REG_ICDC_CDCCR2; -++ codec_speed |= 0x00000f00; -++ -++ speed = speed << 8; -++ speed |= 0xfffff0ff; -++ codec_speed &= speed; -++ REG_ICDC_CDCCR2 = codec_speed; -++} -++ -++void reset_jzcodec(void) -++{ -++ REG_ICDC_CDCCR1 |= 1; -++ mdelay(1); -++ REG_ICDC_CDCCR1 &= 0xfffffffe; -++} -++ -++void jzcodec_mixer_old_info_id_name(void) -++{ -++ strncpy(info.id, "JZCODEC", sizeof(info.id)); -++ strncpy(info.name,"Jz internal codec", sizeof(info.name)); -++} -++ -++void jzcodec_mixer_info_id_name(void) -++{ -++ strncpy(old_info.id, "JZCODEC", sizeof(old_info.id)); -++ strncpy(old_info.name,"Jz internal codec", sizeof(old_info.name)); -++} -++ -++void set_jzcodec_bass(int val) -++{ -++ int bass_gain = 0; -++ if(val < 25) -++ bass_gain = 0; -++ if(val >= 25 && val < 50) -++ bass_gain = 1; -++ if(val >= 50 && val < 75) -++ bass_gain = 2; -++ if(val >= 75 && val <= 100 ) -++ bass_gain = 3; -++ -++ REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x3 << 4)) | (bass_gain << 4)); -++} -++ -++void set_jzcodec_volume(int val) -++{ -++ unsigned int sample_oss; -++ int index,shift_max,vol_scale,vol_step,codec_volume; -++ shift_max = 0; -++ sample_oss = (REG_AIC_CR & 0x00380000) >> 19; -++ -++ switch(sample_oss) -++ { -++ case 0x0: -++ shift_max = 4; /* 8 bits */ -++ break; -++ case 0x1: -++ shift_max = 10; /* 16 bits */ -++ break; -++ case 0x2: -++ shift_max = 12; /* 18 bits */ -++ break; -++ case 0x3: -++ shift_max = 15; /* 20 bits */ -++ break; -++ case 0x4: -++ shift_max = 19; /* 24 bits */ -++ break; -++ } -++ -++ vol_scale = 3 * (shift_max + 1); -++ vol_step = 100 / vol_scale; -++ -++ for(index = 0;index <= 100;index += vol_step) -++ if( val <= index ) -++ break; -++ -++ if(index == 0) -++ index = vol_step; -++ index = index / vol_step; -++ if(index > vol_scale) -++ index = vol_scale; -++ -++ index = vol_scale - index; -++ codec_volume = hpvol_shift_table[index].hpvol; -++ codec_volue_shift = hpvol_shift_table[index].shift; -++ codec_volume = 3; -++ REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x3)) | codec_volume); -++} -++ -++void set_jzcodec_mic(int val) -++{ -++ long mic_gain; -++ -++ mic_gain = 31 * val /100; -++ REG_ICDC_CDCCR2 = (REG_ICDC_CDCCR2 | (0x3 << 4)); -++ REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x1f << 16)) | (mic_gain << 16)); -++} -++ -++void set_jzcodec_line(int val) -++{ -++ long line_gain; -++ -++ line_gain = 31 * val /100; -++ REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x1f << 16)) | (line_gain << 16)); -++} -++ -++void HP_turn_on(void) -++{ -++ long val = 0; -++ /* simple and slow anti-pop */ -++ REG_ICDC_CDCCR1 = 0x00037302; -++ mdelay(2); -++ REG_ICDC_CDCCR1 = 0x03006000; -++ mdelay(2); -++ REG_ICDC_CDCCR1 = 0x03002000; -++ -++ val = REG_ICDC_CDCCR2; -++ val &= 0x0000ff00; -++ val |= 0x001f0033; -++ REG_ICDC_CDCCR2 = val; -++} -++ -++void HP_turn_off(void) -++{ -++ mdelay(20); -++ REG_ICDC_CDCCR1 = 0x00033300; -++} -++ -++void in_codec_app1(void) -++{ -++ /* test is OK */ -++ HP_turn_on(); -++} -++ -++void in_codec_app12(void) -++{ -++ REG_ICDC_CDCCR1 = 0x14024300; -++ mdelay(300); -++} -++ -++void resume_jzcodec(void) -++{ -++ REG_ICDC_CDCCR2 = 0x00170800; -++ mdelay(2); -++ REG_ICDC_CDCCR1 = 0x001f2102; -++ mdelay(5); -++ REG_ICDC_CDCCR1 = 0x00033302; -++ mdelay(550); -++ REG_ICDC_CDCCR1 = 0x00033300; -++ REG_ICDC_CDCCR1 = jzcodec_reg[0]; -++ REG_ICDC_CDCCR2 = jzcodec_reg[1]; -++} -++ -++void suspend_jzcodec(void) -++{ -++ -++ jzcodec_reg[0] = REG_ICDC_CDCCR1; -++ jzcodec_reg[1] = REG_ICDC_CDCCR2; -++ -++ REG_ICDC_CDCCR1 = 0x001b2302; -++ mdelay(1); -++ REG_ICDC_CDCCR1 = 0x001b2102; -++} -++ -++static int __init init_jzcodec(void) -++{ -++ set_codec_mode = set_jzcodec_mode; -++ each_time_init_codec = each_time_init_jzcodec; -++ -++ set_codec_startup_param = set_jzcodec_startup_param; -++ set_codec_volume_table = set_jzcodec_volume_table; -++ set_codec_record = set_jzcodec_record; -++ set_codec_replay = set_jzcodec_replay; -++ set_codec_replay_record = set_jzcodec_replay_record; -++ turn_on_codec = turn_on_jzcodec; -++ turn_off_codec = turn_off_jzcodec; -++ set_codec_speed = set_jzcodec_speed; -++ reset_codec = reset_jzcodec; -++ codec_mixer_old_info_id_name = jzcodec_mixer_old_info_id_name; -++ codec_mixer_info_id_name = jzcodec_mixer_info_id_name; -++ set_codec_bass = set_jzcodec_bass; -++ set_codec_volume = set_jzcodec_volume; -++ set_codec_mic = set_jzcodec_mic; -++ set_codec_line = set_jzcodec_line; -++ i2s_resume_codec = resume_jzcodec; -++ i2s_suspend_codec = suspend_jzcodec; -++ set_codec_direct_mode = set_jzcodec_direct_mode; -++ clear_codec_direct_mode = clear_jzcodec_direct_mode; -++ -++ return 0; -++} -++ -++ -++static void __exit cleanup_jzcodec(void) -++{ -++ REG_ICDC_CDCCR1 = 0x001b2302; -++ -++} -++ -++module_init(init_jzcodec); -++module_exit(cleanup_jzcodec); -+diff -urN linux-2.6.24.7.old/sound/oss/jzdlv.c linux-2.6.24.7/sound/oss/jzdlv.c -+--- linux-2.6.24.7.old/sound/oss/jzdlv.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/oss/jzdlv.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,644 @@ -++/* -++ * linux/drivers/sound/jzcodec.c -++ * -++ * JzSOC internal audio driver. -++ * -++ */ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "sound_config.h" -++#include "jzdlv.h" -++ -++#define USE_NONE 1 -++#define USE_MIC 2 -++#define USE_LINEIN 3 -++ -++extern mixer_info info; -++extern _old_mixer_info old_info; -++extern int codec_volue_shift; -++ -++extern void (*set_codec_mode)(void); -++extern void (*each_time_init_codec)(void); -++extern int (*set_codec_startup_param)(void); -++extern void (*set_codec_record)(void); -++extern void (*set_codec_replay)(void); -++extern void (*set_codec_replay_record)(void); -++extern void (*turn_on_codec)(void); -++extern void (*turn_off_codec)(void); -++extern void (*set_codec_speed)(int rate); -++extern void (*reset_codec)(void); -++extern void (*codec_mixer_old_info_id_name)(void); -++extern void (*codec_mixer_info_id_name)(void); -++extern void (*set_codec_bass)(int val); -++extern void (*set_codec_volume)(int val); -++extern void (*set_codec_mic)(int val); -++extern void (*set_codec_line)(int val); -++extern void (*i2s_resume_codec)(void); -++extern void (*i2s_suspend_codec)(void); -++extern void (*set_codec_direct_mode)(void); -++extern void (*clear_codec_direct_mode)(void); -++ -++ -++void set_dlv_mode(void); -++void each_time_init_jzcodec(void); -++int set_dlv_startup_param(void); -++void set_dlvjzcodec_volume_table(void); -++void set_dlv_replay(void); -++void set_dlv_record(void); -++void set_dlv_speed(int rate); -++void reset_dlv(void); -++void jzcodec_mixer_old_info_id_name(void); -++void jzcodec_mixer_info_id_name(void); -++void set_dlv_volume(int val); -++void set_dlv_mic(int val); -++ -++extern int jz_mic_only; -++int read_codec_file(int addr) -++{ -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ mdelay(1); -++ return(__icdc_get_value()); -++} -++ -++#if 0 -++void printk_codec_files(void) -++{ -++ int cnt; -++ -++ printk("\n"); -++ -++ printk("REG_CPM_I2SCDR=0x%08x\n",REG_CPM_I2SCDR); -++ printk("REG_CPM_CLKGR=0x%08x\n",REG_CPM_CLKGR); -++ printk("REG_CPM_CPCCR=0x%08x\n",REG_CPM_CPCCR); -++ printk("REG_AIC_FR=0x%08x\n",REG_AIC_FR); -++ printk("REG_AIC_CR=0x%08x\n",REG_AIC_CR); -++ printk("REG_AIC_I2SCR=0x%08x\n",REG_AIC_I2SCR); -++ printk("REG_AIC_SR=0x%08x\n",REG_AIC_SR); -++ printk("REG_ICDC_RGDATA=0x%08x\n",REG_ICDC_RGDATA); -++ -++ for (cnt = 0; cnt <= 27 ; cnt++) { -++ printk(" ( %d : 0x%x ) ",cnt ,read_codec_file(cnt)); -++ } -++ printk("\n"); -++} -++#endif -++ -++void write_codec_file(int addr, int val) -++{ -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ __icdc_set_cmd(val); /* write */ -++ mdelay(1); -++ __icdc_set_rgwr(); -++ mdelay(1); -++} -++ -++int write_codec_file_bit(int addr, int bitval, int mask_bit) -++{ -++ int val; -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ mdelay(1); -++ val = __icdc_get_value(); /* read */ -++ -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ val &= ~(1 << mask_bit); -++ if (bitval == 1) -++ val |= 1 << mask_bit; -++ -++ __icdc_set_cmd(val); /* write */ -++ mdelay(1); -++ __icdc_set_rgwr(); -++ mdelay(1); -++ -++ while (__icdc_rgwr_ready()); -++ __icdc_set_addr(addr); -++ val = __icdc_get_value(); /* read */ -++ -++ if (((val >> mask_bit) & bitval) == bitval) -++ return 1; -++ else -++ return 0; -++} -++void set_dlv_mode(void) -++{ -++ /*REG_CPM_CPCCR &= ~(1 << 31); -++ REG_CPM_CPCCR &= ~(1 << 30);*/ -++ write_codec_file(0, 0xf); -++ -++ REG_AIC_I2SCR = 0x10; -++ __i2s_internal_codec(); -++ __i2s_as_slave(); -++ __i2s_select_i2s(); -++ __aic_select_i2s(); -++ __aic_reset(); -++ mdelay(10); -++ REG_AIC_I2SCR = 0x10; -++ mdelay(20); -++ -++ /* power on DLV */ -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ mdelay(10); -++} -++void reset_dlv_codec(void) -++{ -++ /* reset DLV codec. from hibernate mode to sleep mode */ -++ write_codec_file(0, 0xf); -++ write_codec_file_bit(6, 0, 0); -++ write_codec_file_bit(6, 0, 1); -++ mdelay(200); -++ //write_codec_file(0, 0xf); -++ write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0 -++ write_codec_file_bit(5, 0, 4);//PMR1.SB_ADC->0 -++ mdelay(10);//wait for stability -++} -++ -++void each_time_init_dlv(void) -++{ -++ __i2s_disable(); -++ __i2s_as_slave(); -++ __aic_internal_codec(); -++ __i2s_set_oss_sample_size(16); -++ __i2s_set_iss_sample_size(16); -++} -++ -++int set_dlv_startup_param(void) -++{ -++ __i2s_disable_transmit_intr(); -++ __i2s_disable_receive_intr(); -++ -++ return 1; -++} -++/* set Audio data replay */ -++void set_audio_data_replay(void) -++{ -++ /* DAC path */ -++ write_codec_file(9, 0xff); -++ //write_codec_file(8, 0x30); -++ write_codec_file(8, 0x20); -++ mdelay(10); -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -++ -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ //mdelay(100); -++ //write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //mdelay(300); -++} -++ -++#if 1 /* mask warning */ -++/* set Record MIC input audio without playback */ -++void set_record_mic_input_audio_without_playback(void) -++{ -++ /* ADC path for MIC IN */ -++ jz_mic_only = 1; -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ mdelay(10); -++ write_codec_file_bit(1, 1, 2); -++ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -++ -++ write_codec_file(22, 0x40);//mic 1 -++ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -++ //write_codec_file_bit(6, 1, 3);// gain set -++ -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ mdelay(100); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ write_codec_file(1, 0x4); -++} -++#endif -++ -++#if 1 /* mask warning */ -++/* unset Record MIC input audio without playback */ -++void unset_record_mic_input_audio_without_playback(void) -++{ -++ /* ADC path for MIC IN */ -++ jz_mic_only = 0; -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -++ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* set Record LINE input audio without playback */ -++void set_record_line_input_audio_without_playback(void) -++{ -++ /* ADC path for LINE IN */ -++ jz_mic_only = 1; -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ mdelay(10); -++ write_codec_file(22, 0xf6);//line in 1 -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 -++ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -++ mdelay(10); -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ mdelay(100); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ write_codec_file(1, 0x4); -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* unset Record LINE input audio without playback */ -++void unset_record_line_input_audio_without_playback(void) -++{ -++ /* ADC path for LINE IN */ -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(5, 1, 3);//ONR1.SB_LIN->1 -++ -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -++ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* set Playback LINE input audio direct only */ -++void set_playback_line_input_audio_direct_only(void) -++{ -++ jz_audio_reset();//or init_codec() -++ REG_AIC_I2SCR = 0x10; -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ mdelay(10); -++ write_codec_file(22, 0xf6);//line in 1 -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ mdelay(10); -++ write_codec_file_bit(1, 1, 2);//CR1.HP_BYPASS->1 -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -++ -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ mdelay(100); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ //write_codec_file_bit(5, 1, 7);//PMR1.SB_DAC->1 -++ //write_codec_file_bit(5, 1, 4);//PMR1.SB_ADC->1 -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* unset Playback LINE input audio direct only */ -++void unset_playback_line_input_audio_direct_only(void) -++{ -++ write_codec_file_bit(6, 0, 3);//GIM->0 -++ write_codec_file_bit(1, 0, 2);//PMR1.BYPASS->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LINE->1 -++ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -++ mdelay(100); -++ write_codec_file_bit(5, 1, 5);//PMR1.SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* set Record MIC input audio with direct playback */ -++void set_record_mic_input_audio_with_direct_playback(void) -++{ -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ jz_mic_only = 0; -++ write_codec_file(9, 0xff); -++ write_codec_file(8, 0x3f); -++ mdelay(10); -++ -++ write_codec_file(22, 0x60);//mic 1 -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 -++ write_codec_file_bit(6, 1, 3);// gain set -++ -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ mdelay(100); -++ write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 -++ //write_codec_file(1, 0x4); -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* unset Record MIC input audio with direct playback */ -++void unset_record_mic_input_audio_with_direct_playback(void) -++{ -++ /* ADC path for MIC IN */ -++ jz_mic_only = 0; -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1 -++ write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 -++ write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* set Record playing audio mixed with MIC input audio */ -++void set_record_playing_audio_mixed_with_mic_input_audio(void) -++{ -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file(9, 0xff); -++ //write_codec_file(8, 0x30); -++ write_codec_file(8, 0x20); -++ mdelay(10); -++ -++ write_codec_file(22, 0x63);//mic 1 -++ -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(6, 1, 3);// gain set -++ -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -++ write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 -++ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ write_codec_file_bit(5, 0, 4);//PMR1.SB_MIX->0 -++} -++#endif -++ -++#if 0 /* mask warning */ -++/* unset Record playing audio mixed with MIC input audio */ -++void unset_record_playing_audio_mixed_with_mic_input_audio(void) -++{ -++ /* ADC path */ -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -++ //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ //write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++#endif -++ -++#if 1 /* mask warning */ -++/* set Record MIC input audio with Audio data replay (full duplex) */ -++void set_record_mic_input_audio_with_audio_data_replay(void) -++{ -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file(9, 0xff); -++ //write_codec_file(8, 0x30); -++ write_codec_file(8, 0x20); -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ -++ write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 -++ write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 -++ -++ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++} -++#endif -++ -++#if 1 /* mask warning */ -++/* unset Record MIC input audio with Audio data replay (full duplex) */ -++void unset_record_mic_input_audio_with_audio_data_replay(void) -++{ -++ /* ADC path */ -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++#endif -++ -++#if 1 /* mask warning */ -++/* set Record LINE input audio with Audio data replay (full duplex for linein) */ -++void set_record_line_input_audio_with_audio_data_replay(void) -++{ -++ write_codec_file(9, 0xff); -++ //write_codec_file(8, 0x30); -++ write_codec_file(8, 0x20); -++ write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 -++ write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 -++ write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //write_codec_file_bit(22, 1, 7);//CR3.SB_MIC->1 -++ write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++ -++ -++ //jz_mic_only = 1; -++ write_codec_file(22, 0xc6);//line in 1 -++ write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 -++ write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 -++ write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -++} -++#endif -++ -++#if 1 /* mask warning */ -++/* unset Record LINE input audio with Audio data replay (full duplex for linein) */ -++void unset_record_line_input_audio_with_audio_data_replay(void) -++{ -++ /* ADC path */ -++ write_codec_file_bit(5, 1, 4);//SB_ADC->1 -++ write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 -++ //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 -++ write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ write_codec_file_bit(5, 1, 5);//SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++#endif -++ -++#if 1 -++/* unset Audio data replay */ -++void unset_audio_data_replay(void) -++{ -++ //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 -++ //mdelay(800); -++ //write_codec_file_bit(5, 1, 6);//SB_OUT->1 -++ //mdelay(800); -++ write_codec_file_bit(5, 1, 7);//SB_DAC->1 -++ write_codec_file_bit(5, 1, 4);//SB_MIX->1 -++ write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 -++ write_codec_file_bit(6, 1, 1);//SB->1 -++} -++#endif -++ -++void set_dlv_replay(void) -++{ -++ set_audio_data_replay(); -++} -++ -++void set_dlv_speed(int rate) -++{ -++ int speed = 0, val; -++ speed = 0; -++ switch (rate) { -++ case 8000: -++ speed = 10; -++ break; -++ case 9600: -++ speed = 9; -++ break; -++ case 11025: -++ speed = 8; -++ break; -++ case 12000: -++ speed = 7; -++ break; -++ case 16000: -++ speed = 6; -++ break; -++ case 22050: -++ speed = 5; -++ break; -++ case 24000: -++ speed = 4; -++ break; -++ case 32000: -++ speed = 3; -++ break; -++ case 44100: -++ speed = 2; -++ break; -++ case 48000: -++ speed = 1; -++ break; -++ case 96000: -++ speed = 0; -++ break; -++ default: -++ break; -++ } -++ -++ val = read_codec_file(4); -++ val = (speed << 4) | speed; -++ write_codec_file(4, val); -++} -++ -++void reset_jzcodec(void) -++{ -++ -++} -++ -++void dlv_mixer_old_info_id_name(void) -++{ -++ strncpy(info.id, "JZDLV", sizeof(info.id)); -++ strncpy(info.name,"Jz internal codec dlv on jz4750", sizeof(info.name)); -++} -++ -++void dlv_mixer_info_id_name(void) -++{ -++ strncpy(old_info.id, "JZDLV", sizeof(old_info.id)); -++ strncpy(old_info.name,"Jz internal codec dlv on jz4750", sizeof(old_info.name)); -++} -++ -++void set_dlv_mic(int val) -++{ -++ int cur_vol ; -++ /* set gain */ -++ //write_codec_file_bit(6, 1, 3);//GIM -++ cur_vol = 31 * val / 100; -++ cur_vol |= cur_vol << 4; -++ write_codec_file(19, cur_vol);//GIL,GIR -++} -++ -++void set_dlv_line(int val) -++{ -++ int cur_vol; -++ /* set gain */ -++ cur_vol = 31 * val / 100; -++ cur_vol &= 0x1f; -++ write_codec_file(11, cur_vol);//GO1L -++ write_codec_file(12, cur_vol);//GO1R -++} -++ -++void set_dlv_volume(int val) -++{ -++ unsigned long cur_vol; -++ cur_vol = 31 * (100 - val) / 100; -++ write_codec_file(17, cur_vol | 0xc0); -++ write_codec_file(18, cur_vol); -++} -++ -++static int __init init_dlv(void) -++{ -++ set_codec_mode = set_dlv_mode; -++ each_time_init_codec = each_time_init_dlv; -++ reset_codec = reset_dlv_codec; -++ set_codec_startup_param = set_dlv_startup_param; -++ -++ set_codec_replay = set_dlv_replay; -++ -++ set_codec_speed = set_dlv_speed; -++ -++ codec_mixer_old_info_id_name = dlv_mixer_old_info_id_name; -++ codec_mixer_info_id_name = dlv_mixer_info_id_name; -++ -++ set_codec_volume = set_dlv_volume; -++ set_codec_mic = set_dlv_mic; -++ set_codec_line = set_dlv_line; -++ -++ return 0; -++} -++ -++ -++static void __exit cleanup_dlv(void) -++{ -++ -++} -++ -++module_init(init_dlv); -++module_exit(cleanup_dlv); -+diff -urN linux-2.6.24.7.old/sound/oss/jzdlv.h linux-2.6.24.7/sound/oss/jzdlv.h -+--- linux-2.6.24.7.old/sound/oss/jzdlv.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/oss/jzdlv.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,21 @@ -++/* header file for dlv */ -++void write_codec_file(int addr, int val); -++int read_codec_file(int addr); -++void printk_codec_files(void); -++int write_codec_file_bit(int addr, int bitval, int mask_bit); -++void set_audio_data_replay(void); -++void unset_audio_data_replay(void); -++void set_record_mic_input_audio_without_playback(void); -++void unset_record_mic_input_audio_without_playback(void); -++void set_record_line_input_audio_without_playback(void); -++void unset_record_line_input_audio_without_playback(void); -++void set_playback_line_input_audio_direct_only(void); -++void unset_playback_line_input_audio_direct_only(void); -++void set_record_mic_input_audio_with_direct_playback(void); -++void unset_record_mic_input_audio_with_direct_playback(void); -++void set_record_playing_audio_mixed_with_mic_input_audio(void); -++void unset_record_playing_audio_mixed_with_mic_input_audio(void); -++void set_record_mic_input_audio_with_audio_data_replay(void); -++void unset_record_mic_input_audio_with_audio_data_replay(void); -++void set_record_line_input_audio_with_audio_data_replay(void); -++void unset_record_line_input_audio_with_audio_data_replay(void); -+diff -urN linux-2.6.24.7.old/sound/oss/os.h linux-2.6.24.7/sound/oss/os.h -+--- linux-2.6.24.7.old/sound/oss/os.h 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/sound/oss/os.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -9,7 +9,6 @@ -+ #ifdef __KERNEL__ -+ #include -+ #include -+-#include -+ #include -+ #include -+ #include -+diff -urN linux-2.6.24.7.old/sound/soc/Kconfig linux-2.6.24.7/sound/soc/Kconfig -+--- linux-2.6.24.7.old/sound/soc/Kconfig 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/sound/soc/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -28,6 +28,7 @@ -+ source "sound/soc/pxa/Kconfig" -+ source "sound/soc/s3c24xx/Kconfig" -+ source "sound/soc/sh/Kconfig" -++source "sound/soc/jz4740/Kconfig" -+ -+ # Supported codecs -+ source "sound/soc/codecs/Kconfig" -+diff -urN linux-2.6.24.7.old/sound/soc/Makefile linux-2.6.24.7/sound/soc/Makefile -+--- linux-2.6.24.7.old/sound/soc/Makefile 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/sound/soc/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -1,4 +1,4 @@ -+ snd-soc-core-objs := soc-core.o soc-dapm.o -+ -+ obj-$(CONFIG_SND_SOC) += snd-soc-core.o -+-obj-$(CONFIG_SND_SOC) += codecs/ at91/ pxa/ s3c24xx/ sh/ -++obj-$(CONFIG_SND_SOC) += codecs/ at91/ pxa/ s3c24xx/ sh/ jz4740/ -+diff -urN linux-2.6.24.7.old/sound/soc/codecs/Kconfig linux-2.6.24.7/sound/soc/codecs/Kconfig -+--- linux-2.6.24.7.old/sound/soc/codecs/Kconfig 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/sound/soc/codecs/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -37,3 +37,8 @@ -+ bool -+ depends on SND_SOC_CS4270 -+ -++config SND_SOC_ICODEC -++ tristate "Jz4740 internal codec" -++ depends on SND_SOC && SND_JZ4740_SOC_PAVO && SND_JZ4740_SOC_I2S -++ help -++ Say Y if you want to use internal codec on Ingenic Jz4740 PAVO board. -+diff -urN linux-2.6.24.7.old/sound/soc/codecs/Makefile linux-2.6.24.7/sound/soc/codecs/Makefile -+--- linux-2.6.24.7.old/sound/soc/codecs/Makefile 2008-05-07 01:22:34.000000000 +0200 -++++ linux-2.6.24.7/sound/soc/codecs/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -4,6 +4,7 @@ -+ snd-soc-wm8753-objs := wm8753.o -+ snd-soc-wm9712-objs := wm9712.o -+ snd-soc-cs4270-objs := cs4270.o -++snd-soc-jzcodec-objs := jzcodec.o -+ -+ obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o -+ obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o -+@@ -11,3 +12,4 @@ -+ obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o -+ obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o -+ obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o -++obj-$(CONFIG_SND_SOC_ICODEC) += snd-soc-jzcodec.o -+diff -urN linux-2.6.24.7.old/sound/soc/codecs/jzcodec.c linux-2.6.24.7/sound/soc/codecs/jzcodec.c -+--- linux-2.6.24.7.old/sound/soc/codecs/jzcodec.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/soc/codecs/jzcodec.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,725 @@ -++/* -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "../jz4740/jz4740-pcm.h" -++#include "jzcodec.h" -++ -++#define AUDIO_NAME "jzcodec" -++#define JZCODEC_VERSION "1.0" -++ -++/* -++ * Debug -++ */ -++ -++#define JZCODEC_DEBUG 0 -++ -++#ifdef JZCODEC_DEBUG -++#define dbg(format, arg...) \ -++ printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg) -++#else -++#define dbg(format, arg...) do {} while (0) -++#endif -++#define err(format, arg...) \ -++ printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg) -++#define info(format, arg...) \ -++ printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg) -++#define warn(format, arg...) \ -++ printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg) -++ -++struct snd_soc_codec_device soc_codec_dev_jzcodec; -++ -++/* codec private data */ -++struct jzcodec_priv { -++ unsigned int sysclk; -++}; -++ -++/* -++ * jzcodec register cache -++ */ -++static u32 jzcodec_reg[JZCODEC_CACHEREGNUM / 2]; -++ -++/* -++ * codec register is 16 bits width in ALSA, so we define array to store 16 bits configure paras -++ */ -++static u16 jzcodec_reg_LH[JZCODEC_CACHEREGNUM]; -++ -++/* -++ * read jzcodec register cache -++ */ -++static inline unsigned int jzcodec_read_reg_cache(struct snd_soc_codec *codec, -++ unsigned int reg) -++{ -++ u16 *cache = codec->reg_cache; -++ -++ if (reg >= JZCODEC_CACHEREGNUM) -++ return -1; -++ return cache[reg]; -++} -++ -++/* -++ * write jzcodec register cache -++ */ -++static inline void jzcodec_write_reg_cache(struct snd_soc_codec *codec, -++ unsigned int reg, u16 value) -++{ -++ u16 *cache = codec->reg_cache; -++ u32 reg_val; -++ -++ if (reg >= JZCODEC_CACHEREGNUM) { -++ return; -++ } -++ -++ cache[reg] = value; -++ /* update internal codec register value */ -++ switch (reg) { -++ case 0: -++ case 1: -++ reg_val = cache[0] & 0xffff; -++ reg_val = reg_val | (cache[1] << 16); -++ jzcodec_reg[0] = reg_val; -++ break; -++ case 2: -++ case 3: -++ reg_val = cache[2] & 0xffff; -++ reg_val = reg_val | (cache[3] << 16); -++ jzcodec_reg[1] = reg_val; -++ break; -++ } -++} -++ -++/* -++ * write to the jzcodec register space -++ */ -++static int jzcodec_write(struct snd_soc_codec *codec, unsigned int reg, -++ unsigned int value) -++{ -++ jzcodec_write_reg_cache(codec, reg, value); -++ if(codec->hw_write) -++ codec->hw_write(&value, NULL, reg); -++ return 0; -++} -++ -++static int jzcodec_reset(struct snd_soc_codec *codec) -++{ -++ u16 val; -++ -++ val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); -++ val = val | 0x1; -++ jzcodec_write(codec, ICODEC_1_LOW, val); -++ mdelay(1); -++ -++ val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); -++ val = val & ~0x1; -++ jzcodec_write(codec, ICODEC_1_LOW, val); -++ mdelay(1); -++ -++ return 0; -++} -++ -++static const struct snd_kcontrol_new jzcodec_snd_controls[] = { -++ -++ //SOC_DOUBLE_R("Master Playback Volume", 1, 1, 0, 3, 0), -++ SOC_DOUBLE_R("Master Playback Volume", ICODEC_2_LOW, ICODEC_2_LOW, 0, 3, 0), -++ //SOC_DOUBLE_R("MICBG", ICODEC_2_LOW, ICODEC_2_LOW, 4, 3, 0), -++ //SOC_DOUBLE_R("Line", 2, 2, 0, 31, 0), -++ SOC_DOUBLE_R("Line", ICODEC_2_HIGH, ICODEC_2_HIGH, 0, 31, 0), -++}; -++ -++/* add non dapm controls */ -++static int jzcodec_add_controls(struct snd_soc_codec *codec) -++{ -++ int err, i; -++ -++ for (i = 0; i < ARRAY_SIZE(jzcodec_snd_controls); i++) { -++ if ((err = snd_ctl_add(codec->card, -++ snd_soc_cnew(&jzcodec_snd_controls[i], codec, NULL))) < 0) -++ return err; -++ } -++ -++ return 0; -++} -++ -++static const struct snd_soc_dapm_widget jzcodec_dapm_widgets[] = { -++ SND_SOC_DAPM_OUTPUT("LOUT"), -++ SND_SOC_DAPM_OUTPUT("LHPOUT"), -++ SND_SOC_DAPM_OUTPUT("ROUT"), -++ SND_SOC_DAPM_OUTPUT("RHPOUT"), -++ SND_SOC_DAPM_INPUT("MICIN"), -++ SND_SOC_DAPM_INPUT("RLINEIN"), -++ SND_SOC_DAPM_INPUT("LLINEIN"), -++}; -++ -++static const char *intercon[][3] = { -++ /* output mixer */ -++ {"Output Mixer", "Line Bypass Switch", "Line Input"}, -++ {"Output Mixer", "HiFi Playback Switch", "DAC"}, -++ {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"}, -++ -++ /* outputs */ -++ {"RHPOUT", NULL, "Output Mixer"}, -++ {"ROUT", NULL, "Output Mixer"}, -++ {"LHPOUT", NULL, "Output Mixer"}, -++ {"LOUT", NULL, "Output Mixer"}, -++ -++ /* input mux */ -++ {"Input Mux", "Line In", "Line Input"}, -++ {"Input Mux", "Mic", "Mic Bias"}, -++ {"ADC", NULL, "Input Mux"}, -++ -++ /* inputs */ -++ {"Line Input", NULL, "LLINEIN"}, -++ {"Line Input", NULL, "RLINEIN"}, -++ {"Mic Bias", NULL, "MICIN"}, -++ -++ /* terminator */ -++ {NULL, NULL, NULL}, -++}; -++ -++static int jzcodec_add_widgets(struct snd_soc_codec *codec) -++{ -++ int i,cnt; -++ -++ cnt = ARRAY_SIZE(jzcodec_dapm_widgets); -++ for(i = 0; i < ARRAY_SIZE(jzcodec_dapm_widgets); i++) { -++ snd_soc_dapm_new_control(codec, &jzcodec_dapm_widgets[i]); -++ } -++ -++ /* set up audio path interconnects */ -++ for(i = 0; intercon[i][0] != NULL; i++) { -++ snd_soc_dapm_connect_input(codec, intercon[i][0], -++ intercon[i][1], intercon[i][2]); -++ } -++ -++ snd_soc_dapm_new_widgets(codec); -++ return 0; -++} -++ -++static int jzcodec_hw_params(struct snd_pcm_substream *substream, -++ struct snd_pcm_hw_params *params) -++{ -++ struct snd_soc_pcm_runtime *rtd = substream->private_data; -++ struct snd_soc_device *socdev = rtd->socdev; -++ struct snd_soc_codec *codec = socdev->codec; -++ u16 reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); -++ -++ /* bit size. codec side */ -++ switch (params_format(params)) { -++ case SNDRV_PCM_FORMAT_S16_LE: -++ break; -++ } -++ /* sample rate */ -++ reg_val = reg_val & ~(0xf << 8); -++ -++ switch (params_rate(params)) { -++ case 8000: -++ reg_val |= (0x0 << 8); -++ break; -++ case 11025: -++ reg_val |= (0x1 << 8); -++ break; -++ case 12000: -++ reg_val |= (0x2 << 8); -++ break; -++ case 16000: -++ reg_val |= (0x3 << 8); -++ break; -++ case 22050: -++ reg_val |= (0x4 << 8); -++ break; -++ case 24000: -++ reg_val |= (0x5 << 8); -++ break; -++ case 32000: -++ reg_val |= (0x6 << 8); -++ break; -++ case 44100: -++ reg_val |= (0x7 << 8); -++ break; -++ case 48000: -++ reg_val |= (0x8 << 8); -++ break; -++ default: -++ printk(" invalid rate :0x%08x\n",params_rate(params)); -++ } -++ -++ jzcodec_write(codec, ICODEC_2_LOW, reg_val); -++ return 0; -++} -++ -++static int jzcodec_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -++{ -++ int ret = 0; -++ u16 val; -++ struct snd_soc_pcm_runtime *rtd = substream->private_data; -++ struct snd_soc_device *socdev = rtd->socdev; -++ struct snd_soc_codec *codec = socdev->codec; -++ -++ switch (cmd) { -++ case SNDRV_PCM_TRIGGER_START: -++ //case SNDRV_PCM_TRIGGER_RESUME: -++ //case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -++ -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -++ val = 0x7302; -++ jzcodec_write(codec, ICODEC_1_LOW, val); -++ val = 0x0003; -++ jzcodec_write(codec, ICODEC_1_HIGH, val); -++ mdelay(2); -++ val = 0x6000; -++ jzcodec_write(codec, ICODEC_1_LOW, val); -++ val = 0x0300; -++ jzcodec_write(codec, ICODEC_1_HIGH, val); -++ mdelay(2); -++ val = 0x2000; -++ jzcodec_write(codec, ICODEC_1_LOW, val); -++ val = 0x0300; -++ jzcodec_write(codec, ICODEC_1_HIGH, val); -++ } else { -++ val = 0x4300; -++ jzcodec_write(codec, ICODEC_1_LOW, val); -++ val = 0x1402; -++ jzcodec_write(codec, ICODEC_1_HIGH, val); -++ } -++ break; -++ -++ case SNDRV_PCM_TRIGGER_STOP: -++ //case SNDRV_PCM_TRIGGER_SUSPEND: -++ //case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -++ -++ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { -++ val = 0x3300; -++ jzcodec_write(codec, ICODEC_1_LOW, val); -++ val = 0x0003; -++ jzcodec_write(codec, ICODEC_1_HIGH, val); -++ } else { -++ val = 0x3300; -++ jzcodec_write(codec, ICODEC_1_LOW, val); -++ val = 0x0003; -++ jzcodec_write(codec, ICODEC_1_HIGH, val); -++ } -++ break; -++ -++ default: -++ ret = -EINVAL; -++ } -++ -++ return ret; -++} -++ -++static int jzcodec_pcm_prepare(struct snd_pcm_substream *substream) -++{ -++ /*struct snd_soc_pcm_runtime *rtd = substream->private_data; -++ struct snd_soc_device *socdev = rtd->socdev; -++ struct snd_soc_codec *codec = socdev->codec; */ -++ -++ return 0; -++} -++ -++static void jzcodec_shutdown(struct snd_pcm_substream *substream) -++{ -++ struct snd_soc_pcm_runtime *rtd = substream->private_data; -++ struct snd_soc_device *socdev = rtd->socdev; -++ struct snd_soc_codec *codec = socdev->codec; -++ -++ /* deactivate */ -++ if (!codec->active) { -++ udelay(50); -++ } -++} -++ -++static int jzcodec_mute(struct snd_soc_codec_dai *dai, int mute) -++{ -++ struct snd_soc_codec *codec = dai->codec; -++ u16 reg_val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); -++ -++ if (mute != 0) -++ mute = 1; -++ if (mute) -++ reg_val = reg_val | (0x1 << 14); -++ else -++ reg_val = reg_val & ~(0x1 << 14); -++ -++ jzcodec_write(codec, ICODEC_1_LOW, reg_val); -++ return 0; -++} -++ -++static int jzcodec_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai, -++ int clk_id, unsigned int freq, int dir) -++{ -++ struct snd_soc_codec *codec = codec_dai->codec; -++ struct jzcodec_priv *jzcodec = codec->private_data; -++ -++ jzcodec->sysclk = freq; -++ return 0; -++} -++/* -++ * Set's ADC and Voice DAC format. called by pavo_hw_params() in pavo.c -++ */ -++static int jzcodec_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, -++ unsigned int fmt) -++{ -++ /* struct snd_soc_codec *codec = codec_dai->codec; */ -++ -++ /* set master/slave audio interface. codec side */ -++ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -++ case SND_SOC_DAIFMT_CBM_CFM: -++ /* set master mode for codec */ -++ break; -++ case SND_SOC_DAIFMT_CBS_CFS: -++ /* set slave mode for codec */ -++ break; -++ default: -++ return -EINVAL; -++ } -++ -++ /* interface format . set some parameter for codec side */ -++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -++ case SND_SOC_DAIFMT_I2S: -++ /* set I2S mode for codec */ -++ break; -++ case SND_SOC_DAIFMT_RIGHT_J: -++ /* set right J mode */ -++ break; -++ case SND_SOC_DAIFMT_LEFT_J: -++ /* set left J mode */ -++ break; -++ case SND_SOC_DAIFMT_DSP_A: -++ /* set dsp A mode */ -++ break; -++ case SND_SOC_DAIFMT_DSP_B: -++ /* set dsp B mode */ -++ break; -++ default: -++ return -EINVAL; -++ } -++ -++ /* clock inversion. codec side */ -++ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { -++ case SND_SOC_DAIFMT_NB_NF: -++ break; -++ case SND_SOC_DAIFMT_IB_IF: -++ break; -++ case SND_SOC_DAIFMT_IB_NF: -++ break; -++ case SND_SOC_DAIFMT_NB_IF: -++ break; -++ default: -++ return -EINVAL; -++ } -++ -++ /* jzcodec_write(codec, 0, val); */ -++ return 0; -++} -++ -++static int jzcodec_dapm_event(struct snd_soc_codec *codec, int event) -++{ -++/* u16 reg_val; */ -++ -++ switch (event) { -++ case SNDRV_CTL_POWER_D0: /* full On */ -++ /* vref/mid, osc on, dac unmute */ -++ /* u16 reg_val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); */ -++ /* jzcodec_write(codec, 0, val); */ -++ break; -++ case SNDRV_CTL_POWER_D1: /* partial On */ -++ case SNDRV_CTL_POWER_D2: /* partial On */ -++ break; -++ case SNDRV_CTL_POWER_D3hot: /* Off, with power */ -++ /* everything off except vref/vmid, */ -++ /*reg_val = 0x0800; -++ jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val); -++ reg_val = 0x0017; -++ jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val); -++ REG_ICDC_CDCCR1 = jzcodec_reg[0]; -++ mdelay(2); -++ reg_val = 0x2102; -++ jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val); -++ reg_val = 0x001f; -++ jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val); -++ REG_ICDC_CDCCR1 = jzcodec_reg[0]; -++ mdelay(2); -++ reg_val = 0x3302; -++ jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val); -++ reg_val = 0x0003; -++ jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val); -++ REG_ICDC_CDCCR1 = jzcodec_reg[0];*/ -++ break; -++ case SNDRV_CTL_POWER_D3cold: /* Off, without power */ -++ /* everything off, dac mute, inactive */ -++ /*reg_val = 0x2302; -++ jzcodec_write(codec, ICODEC_1_LOW, reg_val); -++ reg_val = 0x001b; -++ jzcodec_write(codec, ICODEC_1_HIGH, reg_val); -++ mdelay(1); -++ reg_val = 0x2102; -++ jzcodec_write(codec, ICODEC_1_LOW, reg_val); -++ reg_val = 0x001b; -++ jzcodec_write(codec, ICODEC_1_HIGH, reg_val);*/ -++ break; -++ } -++ codec->dapm_state = event; -++ return 0; -++} -++ -++#define JZCODEC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ -++ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ -++ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ -++ SNDRV_PCM_RATE_48000) -++ -++#define JZCODEC_FORMATS (SNDRV_PCM_FORMAT_S8 | SNDRV_PCM_FMTBIT_S16_LE) -++ -++struct snd_soc_codec_dai jzcodec_dai = { -++ .name = "JZCODEC", -++ .playback = { -++ .stream_name = "Playback", -++ .channels_min = 1, -++ .channels_max = 2, -++ .rates = JZCODEC_RATES, -++ .formats = JZCODEC_FORMATS,}, -++ .capture = { -++ .stream_name = "Capture", -++ .channels_min = 1, -++ .channels_max = 2, -++ .rates = JZCODEC_RATES, -++ .formats = JZCODEC_FORMATS,}, -++ .ops = { -++ .trigger = jzcodec_pcm_trigger, -++ .prepare = jzcodec_pcm_prepare, -++ .hw_params = jzcodec_hw_params, -++ .shutdown = jzcodec_shutdown, -++ }, -++ .dai_ops = { -++ .digital_mute = jzcodec_mute, -++ .set_sysclk = jzcodec_set_dai_sysclk, -++ .set_fmt = jzcodec_set_dai_fmt, -++ } -++}; -++EXPORT_SYMBOL_GPL(jzcodec_dai); -++ -++#ifdef CONFIG_PM -++static u16 jzcodec_reg_pm[JZCODEC_CACHEREGNUM]; -++static int jzcodec_suspend(struct platform_device *pdev, pm_message_t state) -++{ -++ struct snd_soc_device *socdev = platform_get_drvdata(pdev); -++ struct snd_soc_codec *codec = socdev->codec; -++ -++ jzcodec_reg_pm[ICODEC_1_LOW] = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); -++ jzcodec_reg_pm[ICODEC_1_HIGH] = jzcodec_read_reg_cache(codec, ICODEC_1_HIGH); -++ jzcodec_reg_pm[ICODEC_2_LOW] = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); -++ jzcodec_reg_pm[ICODEC_2_HIGH] = jzcodec_read_reg_cache(codec, ICODEC_2_HIGH); -++ -++ jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3cold); -++ return 0; -++} -++ -++static int jzcodec_resume(struct platform_device *pdev) -++{ -++ struct snd_soc_device *socdev = platform_get_drvdata(pdev); -++ struct snd_soc_codec *codec = socdev->codec; -++ u16 reg_val; -++ -++ jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3hot); -++ reg_val = jzcodec_reg_pm[ICODEC_1_LOW]; -++ jzcodec_write(codec, ICODEC_1_LOW, reg_val); -++ reg_val = jzcodec_reg_pm[ICODEC_1_HIGH]; -++ jzcodec_write(codec, ICODEC_1_HIGH, reg_val); -++ reg_val = jzcodec_reg_pm[ICODEC_2_LOW]; -++ jzcodec_write(codec, ICODEC_2_LOW, reg_val); -++ reg_val = jzcodec_reg_pm[ICODEC_2_HIGH]; -++ jzcodec_write(codec, ICODEC_2_HIGH, reg_val); -++ -++ jzcodec_dapm_event(codec, codec->suspend_dapm_state); -++ return 0; -++} -++#else -++#define jzcodec_suspend NULL -++#define jzcodec_resume NULL -++#endif -++/* -++ * initialise the JZCODEC driver -++ * register the mixer and dsp interfaces with the kernel -++ */ -++static int jzcodec_init(struct snd_soc_device *socdev) -++{ -++ struct snd_soc_codec *codec = socdev->codec; -++ int reg, ret = 0; -++ u16 reg_val; -++ -++ for (reg = 0; reg < JZCODEC_CACHEREGNUM / 2; reg++) { -++ switch (reg) { -++ case 0: -++ jzcodec_reg[reg] = REG_ICDC_CDCCR1; -++ jzcodec_reg_LH[ICODEC_1_LOW] = jzcodec_reg[reg] & 0xffff; -++ jzcodec_reg_LH[ICODEC_1_HIGH] = (jzcodec_reg[reg] & 0xffff0000) >> 16; -++ break; -++ case 1: -++ jzcodec_reg[reg] = REG_ICDC_CDCCR2; -++ jzcodec_reg_LH[ICODEC_2_LOW] = jzcodec_reg[reg] & 0xffff; -++ jzcodec_reg_LH[ICODEC_2_HIGH] = (jzcodec_reg[reg] & 0xffff0000) >> 16; -++ break; -++ } -++ } -++ -++ codec->name = "JZCODEC"; -++ codec->owner = THIS_MODULE; -++ codec->read = jzcodec_read_reg_cache; -++ codec->write = jzcodec_write; -++ codec->dapm_event = jzcodec_dapm_event; -++ codec->dai = &jzcodec_dai; -++ codec->num_dai = 1; -++ codec->reg_cache_size = sizeof(jzcodec_reg_LH); -++ codec->reg_cache = kmemdup(jzcodec_reg_LH, sizeof(jzcodec_reg_LH), GFP_KERNEL); -++ if (codec->reg_cache == NULL) -++ return -ENOMEM; -++ -++ jzcodec_reset(codec); -++ /* register pcms */ -++ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -++ if (ret < 0) { -++ printk(KERN_ERR "jzcodec: failed to create pcms\n"); -++ goto pcm_err; -++ } -++ -++ /* power on device */ -++ jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3hot); -++ -++ /* clear suspend bit of jz4740 internal codec */ -++ reg_val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); -++ reg_val = reg_val & ~(0x2); -++ jzcodec_write(codec, ICODEC_1_LOW, reg_val); -++ /* set vol bits */ -++ reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); -++ reg_val = reg_val | 0x3; -++ jzcodec_write(codec, ICODEC_2_LOW, reg_val); -++ /* set line in capture gain bits */ -++ reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_HIGH); -++ reg_val = reg_val | 0x1f; -++ jzcodec_write(codec, ICODEC_2_HIGH, reg_val); -++ /* set mic boost gain bits */ -++ reg_val = jzcodec_read_reg_cache(codec, ICODEC_2_LOW); -++ reg_val = reg_val | (0x3 << 4); -++ jzcodec_write(codec, ICODEC_2_LOW, reg_val); -++ mdelay(5); -++ reg_val = 0x3300; -++ jzcodec_write(codec, ICODEC_1_LOW, reg_val); -++ reg_val = 0x0003; -++ jzcodec_write(codec, ICODEC_1_HIGH, reg_val); -++ jzcodec_add_controls(codec); -++ jzcodec_add_widgets(codec); -++ -++ ret = snd_soc_register_card(socdev); -++ if (ret < 0) { -++ printk(KERN_ERR "jzcodec: failed to register card\n"); -++ goto card_err; -++ } -++ return ret; -++ -++card_err: -++ snd_soc_free_pcms(socdev); -++ snd_soc_dapm_free(socdev); -++pcm_err: -++ kfree(codec->reg_cache); -++ return ret; -++} -++ -++static struct snd_soc_device *jzcodec_socdev; -++ -++static int write_codec_reg(u16 * add, char * name, int reg) -++{ -++ switch (reg) { -++ case 0: -++ case 1: -++ REG_ICDC_CDCCR1 = jzcodec_reg[0]; -++ break; -++ case 2: -++ case 3: -++ REG_ICDC_CDCCR2 = jzcodec_reg[1]; -++ break; -++ } -++ return 0; -++} -++ -++static int jzcodec_probe(struct platform_device *pdev) -++{ -++ struct snd_soc_device *socdev = platform_get_drvdata(pdev); -++ struct snd_soc_codec *codec; -++ struct jzcodec_priv *jzcodec; -++ int ret = 0; -++ -++ codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -++ if (codec == NULL) -++ return -ENOMEM; -++ -++ jzcodec = kzalloc(sizeof(struct jzcodec_priv), GFP_KERNEL); -++ if (jzcodec == NULL) { -++ kfree(codec); -++ return -ENOMEM; -++ } -++ -++ codec->private_data = jzcodec; -++ socdev->codec = codec; -++ mutex_init(&codec->mutex); -++ INIT_LIST_HEAD(&codec->dapm_widgets); -++ INIT_LIST_HEAD(&codec->dapm_paths); -++ -++ jzcodec_socdev = socdev; -++ -++ /* Add other interfaces here ,no I2C connection */ -++ codec->hw_write = (hw_write_t)write_codec_reg; -++ ret = jzcodec_init(jzcodec_socdev); -++ -++ if (ret < 0) { -++ codec = jzcodec_socdev->codec; -++ err("failed to initialise jzcodec\n"); -++ kfree(codec); -++ } -++ -++ return ret; -++} -++ -++/* power down chip */ -++static int jzcodec_remove(struct platform_device *pdev) -++{ -++ struct snd_soc_device *socdev = platform_get_drvdata(pdev); -++ struct snd_soc_codec *codec = socdev->codec; -++ -++ if (codec->control_data) -++ jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3cold); -++ -++ snd_soc_free_pcms(socdev); -++ snd_soc_dapm_free(socdev); -++ kfree(codec->private_data); -++ kfree(codec); -++ -++ return 0; -++} -++ -++struct snd_soc_codec_device soc_codec_dev_jzcodec = { -++ .probe = jzcodec_probe, -++ .remove = jzcodec_remove, -++ .suspend = jzcodec_suspend, -++ .resume = jzcodec_resume, -++}; -++ -++EXPORT_SYMBOL_GPL(soc_codec_dev_jzcodec); -++ -++MODULE_DESCRIPTION("ASoC JZCODEC driver"); -++MODULE_AUTHOR("Richard"); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/sound/soc/codecs/jzcodec.h linux-2.6.24.7/sound/soc/codecs/jzcodec.h -+--- linux-2.6.24.7.old/sound/soc/codecs/jzcodec.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/soc/codecs/jzcodec.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,22 @@ -++/* -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef _ICODEC_H -++#define _ICODEC_H -++ -++/* jzcodec register space */ -++#define ICODEC_1_LOW 0x00 /* bit0 -- bit15 in CDCCR1 */ -++#define ICODEC_1_HIGH 0x01 /* bit16 -- bit31 in CDCCR1 */ -++#define ICODEC_2_LOW 0x02 /* bit0 -- bit16 in CDCCR2 */ -++#define ICODEC_2_HIGH 0x03 /* bit16 -- bit31 in CDCCR2 */ -++ -++#define JZCODEC_CACHEREGNUM 4 -++#define JZCODEC_SYSCLK 0 -++ -++extern struct snd_soc_codec_dai jzcodec_dai; -++extern struct snd_soc_codec_device soc_codec_dev_jzcodec; -++ -++#endif -+diff -urN linux-2.6.24.7.old/sound/soc/jz4740/Kconfig linux-2.6.24.7/sound/soc/jz4740/Kconfig -+--- linux-2.6.24.7.old/sound/soc/jz4740/Kconfig 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/soc/jz4740/Kconfig 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,34 @@ -++config SND_JZ4740_SOC -++ tristate "SoC Audio for Ingenic jz4740 chip" -++ depends on (JZ4740_PAVO || JZ4725_DIPPER || JZ4720_VIRGO) && SND_SOC -++ help -++ Say Y or M if you want to add support for codecs attached to -++ the Jz4740 AC97, I2S or SSP interface. You will also need -++ to select the audio interfaces to support below. -++ -++config SND_JZ4740_SOC_PAVO -++ tristate "SoC Audio support for Ingenic Jz4740 PAVO board" -++ depends on SND_JZ4740_SOC -++ help -++ Say Y if you want to add support for SoC audio of internal codec on Ingenic Jz4740 PAVO board. -++ -++config SND_JZ4740_AC97 -++ tristate "select AC97 protocol and AC97 codec pcm core support" -++ depends on SND_JZ4740_SOC && SND_JZ4740_SOC_PAVO -++ select SND_AC97_CODEC -++ help -++ Say Y if you want to add AC97 protocol support for pcm core. -++ -++config SND_JZ4740_SOC_AC97 -++ tristate "SoC Audio (AC97 protocol) for Ingenic jz4740 chip" -++ depends on SND_JZ4740_SOC && SND_JZ4740_AC97 && SND_JZ4740_SOC_PAVO -++ select AC97_BUS -++ select SND_SOC_AC97_BUS -++ help -++ Say Y if you want to use AC97 protocol and ac97 codec on Ingenic Jz4740 PAVO board. -++ -++config SND_JZ4740_SOC_I2S -++ depends on SND_JZ4740_SOC && SND_JZ4740_SOC_PAVO -++ tristate "SoC Audio (I2S protocol) for Ingenic jz4740 chip" -++ help -++ Say Y if you want to use I2S protocol and I2S codec on Ingenic Jz4740 PAVO board. -+diff -urN linux-2.6.24.7.old/sound/soc/jz4740/Makefile linux-2.6.24.7/sound/soc/jz4740/Makefile -+--- linux-2.6.24.7.old/sound/soc/jz4740/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/soc/jz4740/Makefile 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,15 @@ -++# -++# Jz4740 Platform Support -++# -++snd-soc-jz4740-objs := jz4740-pcm.o -++snd-soc-jz4740-ac97-objs := jz4740-ac97.o -++snd-soc-jz4740-i2s-objs := jz4740-i2s.o -++ -++obj-$(CONFIG_SND_JZ4740_SOC) += snd-soc-jz4740.o -++obj-$(CONFIG_SND_JZ4740_SOC_AC97) += snd-soc-jz4740-ac97.o -++obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o -++ -++# Jz4740 Machine Support -++snd-soc-pavo-objs := pavo.o -++ -++obj-$(CONFIG_SND_JZ4740_SOC_PAVO) += snd-soc-pavo.o -+diff -urN linux-2.6.24.7.old/sound/soc/jz4740/jz4740-ac97.c linux-2.6.24.7/sound/soc/jz4740/jz4740-ac97.c -+--- linux-2.6.24.7.old/sound/soc/jz4740/jz4740-ac97.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/soc/jz4740/jz4740-ac97.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,261 @@ -++/* -++ * linux/sound/jz4740-ac97.c -- AC97 support for the Ingenic jz4740 chip. -++ * -++ * Author: Richard -++ * Created: Dec 02, 2007 -++ * Copyright: Ingenic Semiconductor Inc. -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++ -++#include "jz4740-pcm.h" -++#include "jz4740-ac97.h" -++ -++static DEFINE_MUTEX(car_mutex); -++static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); -++static volatile long gsr_bits; -++ -++static unsigned short jz4740_ac97_read(struct snd_ac97 *ac97, -++ unsigned short reg) -++{ -++ unsigned short val = -1; -++ volatile u32 *reg_addr; -++ -++ mutex_lock(&car_mutex); -++ -++out: mutex_unlock(&car_mutex); -++ return val; -++} -++ -++static void jz4740_ac97_write(struct snd_ac97 *ac97, unsigned short reg, -++ unsigned short val) -++{ -++ volatile u32 *reg_addr; -++ -++ mutex_lock(&car_mutex); -++ -++ mutex_unlock(&car_mutex); -++} -++ -++static void jz4740_ac97_warm_reset(struct snd_ac97 *ac97) -++{ -++ gsr_bits = 0; -++} -++ -++static void jz4740_ac97_cold_reset(struct snd_ac97 *ac97) -++{ -++} -++ -++static irqreturn_t jz4740_ac97_irq(int irq, void *dev_id) -++{ -++ long status; -++ return IRQ_NONE; -++} -++ -++struct snd_ac97_bus_ops soc_ac97_ops = { -++ .read = jz4740_ac97_read, -++ .write = jz4740_ac97_write, -++ .warm_reset = jz4740_ac97_warm_reset, -++ .reset = jz4740_ac97_cold_reset, -++}; -++ -++static struct jz4740_pcm_dma_params jz4740_ac97_pcm_stereo_out = { -++ .name = "AC97 PCM Stereo out", -++ .dev_addr = __PREG(PCDR), -++ .drcmr = &DRCMRTXPCDR, -++ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | -++ DCMD_BURST32 | DCMD_WIDTH4, -++}; -++ -++static struct jz4740_pcm_dma_params jz4740_ac97_pcm_stereo_in = { -++ .name = "AC97 PCM Stereo in", -++ .dev_addr = __PREG(PCDR), -++ .drcmr = &DRCMRRXPCDR, -++ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | -++ DCMD_BURST32 | DCMD_WIDTH4, -++}; -++ -++static struct jz4740_pcm_dma_params jz4740_ac97_pcm_aux_mono_out = { -++ .name = "AC97 Aux PCM (Slot 5) Mono out", -++ .dev_addr = __PREG(MODR), -++ .drcmr = &DRCMRTXMODR, -++ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | -++ DCMD_BURST16 | DCMD_WIDTH2, -++}; -++ -++static struct jz4740_pcm_dma_params jz4740_ac97_pcm_aux_mono_in = { -++ .name = "AC97 Aux PCM (Slot 5) Mono in", -++ .dev_addr = __PREG(MODR), -++ .drcmr = &DRCMRRXMODR, -++ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | -++ DCMD_BURST16 | DCMD_WIDTH2, -++}; -++ -++static struct jz4740_pcm_dma_params jz4740_ac97_pcm_mic_mono_in = { -++ .name = "AC97 Mic PCM (Slot 6) Mono in", -++ .dev_addr = __PREG(MCDR), -++ .drcmr = &DRCMRRXMCDR, -++ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | -++ DCMD_BURST16 | DCMD_WIDTH2, -++}; -++ -++#ifdef CONFIG_PM -++static int jz4740_ac97_suspend(struct platform_device *pdev, -++ struct snd_soc_cpu_dai *dai) -++{ -++ return 0; -++} -++ -++static int jz4740_ac97_resume(struct platform_device *pdev, -++ struct snd_soc_cpu_dai *dai) -++{ -++ return 0; -++} -++ -++#else -++#define jz4740_ac97_suspend NULL -++#define jz4740_ac97_resume NULL -++#endif -++ -++static int jz4740_ac97_probe(struct platform_device *pdev) -++{ -++ int ret; -++ -++ return 0; -++} -++ -++static void jz4740_ac97_remove(struct platform_device *pdev) -++{ -++} -++ -++static int jz4740_ac97_hw_params(struct snd_pcm_substream *substream, -++ struct snd_pcm_hw_params *params) -++{ -++ struct snd_soc_pcm_runtime *rtd = substream->private_data; -++ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; -++ -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -++ cpu_dai->dma_data = &jz4740_ac97_pcm_stereo_out; -++ else -++ cpu_dai->dma_data = &jz4740_ac97_pcm_stereo_in; -++ -++ return 0; -++} -++ -++static int jz4740_ac97_hw_aux_params(struct snd_pcm_substream *substream, -++ struct snd_pcm_hw_params *params) -++{ -++ struct snd_soc_pcm_runtime *rtd = substream->private_data; -++ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; -++ -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -++ cpu_dai->dma_data = &jz4740_ac97_pcm_aux_mono_out; -++ else -++ cpu_dai->dma_data = &jz4740_ac97_pcm_aux_mono_in; -++ -++ return 0; -++} -++ -++static int jz4740_ac97_hw_mic_params(struct snd_pcm_substream *substream, -++ struct snd_pcm_hw_params *params) -++{ -++ struct snd_soc_pcm_runtime *rtd = substream->private_data; -++ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; -++ -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -++ return -ENODEV; -++ else -++ cpu_dai->dma_data = &jz4740_ac97_pcm_mic_mono_in; -++ -++ return 0; -++} -++ -++#define JZ4740_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ -++ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ -++ SNDRV_PCM_RATE_48000) -++ -++struct snd_soc_cpu_dai jz4740_ac97_dai[] = { -++{ -++ .name = "jz4740-ac97", -++ .id = 0, -++ .type = SND_SOC_DAI_AC97, -++ .probe = jz4740_ac97_probe, -++ .remove = jz4740_ac97_remove, -++ .suspend = jz4740_ac97_suspend, -++ .resume = jz4740_ac97_resume, -++ .playback = { -++ .stream_name = "AC97 Playback", -++ .channels_min = 2, -++ .channels_max = 2, -++ .rates = JZ4740_AC97_RATES, -++ .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -++ .capture = { -++ .stream_name = "AC97 Capture", -++ .channels_min = 2, -++ .channels_max = 2, -++ .rates = JZ4740_AC97_RATES, -++ .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -++ .ops = { -++ .hw_params = jz4740_ac97_hw_params,}, -++}, -++{ -++ .name = "jz4740-ac97-aux", -++ .id = 1, -++ .type = SND_SOC_DAI_AC97, -++ .playback = { -++ .stream_name = "AC97 Aux Playback", -++ .channels_min = 1, -++ .channels_max = 1, -++ .rates = JZ4740_AC97_RATES, -++ .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -++ .capture = { -++ .stream_name = "AC97 Aux Capture", -++ .channels_min = 1, -++ .channels_max = 1, -++ .rates = JZ4740_AC97_RATES, -++ .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -++ .ops = { -++ .hw_params = jz4740_ac97_hw_aux_params,}, -++}, -++{ -++ .name = "jz4740-ac97-mic", -++ .id = 2, -++ .type = SND_SOC_DAI_AC97, -++ .capture = { -++ .stream_name = "AC97 Mic Capture", -++ .channels_min = 1, -++ .channels_max = 1, -++ .rates = JZ4740_AC97_RATES, -++ .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -++ .ops = { -++ .hw_params = jz4740_ac97_hw_mic_params,}, -++}, -++}; -++ -++EXPORT_SYMBOL_GPL(jz4740_ac97_dai); -++EXPORT_SYMBOL_GPL(soc_ac97_ops); -++ -++MODULE_AUTHOR("Richard"); -++MODULE_DESCRIPTION("AC97 driver for the Ingenic jz4740 chip"); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/sound/soc/jz4740/jz4740-ac97.h linux-2.6.24.7/sound/soc/jz4740/jz4740-ac97.h -+--- linux-2.6.24.7.old/sound/soc/jz4740/jz4740-ac97.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/soc/jz4740/jz4740-ac97.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,21 @@ -++/* -++ * linux/sound/soc/jz4740/jz4740-ac97.h -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef _JZ4740_AC97_H -++#define _JZ4740_AC97_H -++ -++#define JZ4740_DAI_AC97_HIFI 0 -++#define JZ4740_DAI_AC97_AUX 1 -++#define JZ4740_DAI_AC97_MIC 2 -++ -++extern struct snd_soc_cpu_dai jz4740_ac97_dai[3]; -++ -++/* platform data */ -++extern struct snd_ac97_bus_ops jz4740_ac97_ops; -++ -++#endif -+diff -urN linux-2.6.24.7.old/sound/soc/jz4740/jz4740-i2s.c linux-2.6.24.7/sound/soc/jz4740/jz4740-i2s.c -+--- linux-2.6.24.7.old/sound/soc/jz4740/jz4740-i2s.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/soc/jz4740/jz4740-i2s.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,296 @@ -++/* -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "jz4740-pcm.h" -++#include "jz4740-i2s.h" -++ -++static struct jz4740_dma_client jz4740_dma_client_out = { -++ .name = "I2S PCM Stereo out" -++}; -++ -++static struct jz4740_dma_client jz4740_dma_client_in = { -++ .name = "I2S PCM Stereo in" -++}; -++ -++static struct jz4740_pcm_dma_params jz4740_i2s_pcm_stereo_out = { -++ .client = &jz4740_dma_client_out, -++ .channel = DMA_ID_AIC_TX, -++ .dma_addr = AIC_DR, -++ .dma_size = 2, -++}; -++ -++static struct jz4740_pcm_dma_params jz4740_i2s_pcm_stereo_in = { -++ .client = &jz4740_dma_client_in, -++ .channel = DMA_ID_AIC_RX, -++ .dma_addr = AIC_DR, -++ .dma_size = 2, -++}; -++ -++static int jz4740_i2s_startup(struct snd_pcm_substream *substream) -++{ -++ /*struct snd_soc_pcm_runtime *rtd = substream->private_data; -++ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;*/ -++ -++ return 0; -++} -++ -++static int jz4740_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai, -++ unsigned int fmt) -++{ -++ /* interface format */ -++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -++ case SND_SOC_DAIFMT_I2S: -++ /* 1 : ac97 , 0 : i2s */ -++ break; -++ case SND_SOC_DAIFMT_LEFT_J: -++ break; -++ default: -++ return -EINVAL; -++ } -++ -++ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -++ case SND_SOC_DAIFMT_CBS_CFS: -++ /* 0 : slave */ -++ break; -++ case SND_SOC_DAIFMT_CBM_CFS: -++ /* 1 : master */ -++ break; -++ default: -++ break; -++ } -++ -++ return 0; -++} -++ -++/* -++* Set Jz4740 Clock source -++*/ -++static int jz4740_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai, -++ int clk_id, unsigned int freq, int dir) -++{ -++ return 0; -++} -++ -++static void jz4740_snd_tx_ctrl(int on) -++{ -++ if (on) { -++ /* enable replay */ -++ __i2s_enable_transmit_dma(); -++ __i2s_enable_replay(); -++ __i2s_enable(); -++ -++ } else { -++ /* disable replay & capture */ -++ __i2s_disable_replay(); -++ __i2s_disable_record(); -++ __i2s_disable_receive_dma(); -++ __i2s_disable_transmit_dma(); -++ __i2s_disable(); -++ } -++} -++ -++static void jz4740_snd_rx_ctrl(int on) -++{ -++ if (on) { -++ /* enable capture */ -++ __i2s_enable_receive_dma(); -++ __i2s_enable_record(); -++ __i2s_enable(); -++ -++ } else { -++ /* disable replay & capture */ -++ __i2s_disable_replay(); -++ __i2s_disable_record(); -++ __i2s_disable_receive_dma(); -++ __i2s_disable_transmit_dma(); -++ __i2s_disable(); -++ } -++} -++ -++static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, -++ struct snd_pcm_hw_params *params) -++{ -++ struct snd_soc_pcm_runtime *rtd = substream->private_data; -++ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; -++ int channels = params_channels(params); -++ -++ jz4740_snd_rx_ctrl(0); -++ jz4740_snd_rx_ctrl(0); -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -++ cpu_dai->dma_data = &jz4740_i2s_pcm_stereo_out; -++ if (channels == 1) -++ __aic_enable_mono2stereo(); -++ else -++ __aic_disable_mono2stereo(); -++ } else -++ cpu_dai->dma_data = &jz4740_i2s_pcm_stereo_in; -++ -++ switch (params_format(params)) { -++ case SNDRV_PCM_FORMAT_S8: -++ __i2s_set_transmit_trigger(4); -++ __i2s_set_receive_trigger(3); -++ __i2s_set_oss_sample_size(8); -++ __i2s_set_iss_sample_size(8); -++ break; -++ case SNDRV_PCM_FORMAT_S16_LE: -++ /* playback sample:16 bits, burst:16 bytes */ -++ __i2s_set_transmit_trigger(4); -++ /* capture sample:16 bits, burst:16 bytes */ -++ __i2s_set_receive_trigger(3); -++ __i2s_set_oss_sample_size(16); -++ __i2s_set_iss_sample_size(16); -++ break; -++ } -++ -++ return 0; -++} -++ -++static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd) -++{ -++ int ret = 0; -++ switch (cmd) { -++ case SNDRV_PCM_TRIGGER_START: -++ case SNDRV_PCM_TRIGGER_RESUME: -++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -++ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -++ jz4740_snd_rx_ctrl(1); -++ else -++ jz4740_snd_tx_ctrl(1); -++ break; -++ case SNDRV_PCM_TRIGGER_STOP: -++ case SNDRV_PCM_TRIGGER_SUSPEND: -++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -++ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -++ jz4740_snd_rx_ctrl(0); -++ else -++ jz4740_snd_tx_ctrl(0); -++ break; -++ default: -++ ret = -EINVAL; -++ } -++ -++ return ret; -++} -++ -++static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream) -++{ -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -++ } else { -++ } -++ -++ return; -++} -++ -++static int jz4740_i2s_probe(struct platform_device *pdev) -++{ -++ __i2s_internal_codec(); -++ __i2s_as_slave(); -++ __i2s_select_i2s(); -++ __aic_select_i2s(); -++ mdelay(2); -++ -++ __i2s_disable(); -++ __i2s_reset(); -++ mdelay(2); -++ -++ __i2s_disable(); -++ __i2s_internal_codec(); -++ __i2s_as_slave(); -++ __i2s_select_i2s(); -++ __aic_select_i2s(); -++ __i2s_set_oss_sample_size(16); -++ __i2s_set_iss_sample_size(16); -++ __aic_play_lastsample(); -++ -++ __i2s_disable_record(); -++ __i2s_disable_replay(); -++ __i2s_disable_loopback(); -++ __i2s_set_transmit_trigger(7); -++ __i2s_set_receive_trigger(7); -++ -++ jz4740_snd_tx_ctrl(0); -++ jz4740_snd_rx_ctrl(0); -++ -++ return 0; -++} -++ -++#ifdef CONFIG_PM -++static int jz4740_i2s_suspend(struct platform_device *dev, -++ struct snd_soc_cpu_dai *dai) -++{ -++ if (!dai->active) -++ return 0; -++ -++ return 0; -++} -++ -++static int jz4740_i2s_resume(struct platform_device *pdev, -++ struct snd_soc_cpu_dai *dai) -++{ -++ if (!dai->active) -++ return 0; -++ -++ return 0; -++} -++ -++#else -++#define jz4740_i2s_suspend NULL -++#define jz4740_i2s_resume NULL -++#endif -++ -++#define JZ4740_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ -++ SNDRV_PCM_RATE_12000 | SNDRV_PCM_RATE_16000 |\ -++ SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_24000 |\ -++ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ -++ SNDRV_PCM_RATE_48000) -++ -++struct snd_soc_cpu_dai jz4740_i2s_dai = { -++ .name = "jz4740-i2s", -++ .id = 0, -++ .type = SND_SOC_DAI_I2S, -++ .probe = jz4740_i2s_probe, -++ .suspend = jz4740_i2s_suspend, -++ .resume = jz4740_i2s_resume, -++ .playback = { -++ .channels_min = 1, -++ .channels_max = 2, -++ .rates = JZ4740_I2S_RATES, -++ .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, -++ .capture = { -++ .channels_min = 1, -++ .channels_max = 2, -++ .rates = JZ4740_I2S_RATES, -++ .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, -++ .ops = { -++ .startup = jz4740_i2s_startup, -++ .shutdown = jz4740_i2s_shutdown, -++ .trigger = jz4740_i2s_trigger, -++ .hw_params = jz4740_i2s_hw_params,}, -++ .dai_ops = { -++ .set_fmt = jz4740_i2s_set_dai_fmt, -++ .set_sysclk = jz4740_i2s_set_dai_sysclk, -++ }, -++}; -++ -++EXPORT_SYMBOL_GPL(jz4740_i2s_dai); -++ -++/* Module information */ -++MODULE_AUTHOR("Richard, cjfeng@ingenic.cn, www.ingenic.cn"); -++MODULE_DESCRIPTION("jz4740 I2S SoC Interface"); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/sound/soc/jz4740/jz4740-i2s.h linux-2.6.24.7/sound/soc/jz4740/jz4740-i2s.h -+--- linux-2.6.24.7.old/sound/soc/jz4740/jz4740-i2s.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/soc/jz4740/jz4740-i2s.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,18 @@ -++/* -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef _JZ4740_I2S_H -++#define _JZ4740_I2S_H -++ -++/* jz4740 DAI ID's */ -++#define JZ4740_DAI_I2S 0 -++ -++/* I2S clock */ -++#define JZ4740_I2S_SYSCLK 0 -++ -++extern struct snd_soc_cpu_dai jz4740_i2s_dai; -++ -++#endif -+diff -urN linux-2.6.24.7.old/sound/soc/jz4740/jz4740-pcm.c linux-2.6.24.7/sound/soc/jz4740/jz4740-pcm.c -+--- linux-2.6.24.7.old/sound/soc/jz4740/jz4740-pcm.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/soc/jz4740/jz4740-pcm.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,689 @@ -++/* -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include -++#include -++#include -++#include -++ -++#include -++#include "jz4740-pcm.h" -++ -++static long sum_bytes = 0; -++static int first_transfer = 0; -++static int printk_flag = 0; -++static int tran_bit = 0; -++#ifdef CONFIG_SND_OSSEMUL -++static int hw_params_cnt = 0; -++#endif -++ -++struct jz4740_dma_buf_aic { -++ struct jz4740_dma_buf_aic *next; -++ int size; /* buffer size in bytes */ -++ dma_addr_t data; /* start of DMA data */ -++ dma_addr_t ptr; /* where the DMA got to [1] */ -++ void *id; /* client's id */ -++}; -++ -++struct jz4740_runtime_data { -++ spinlock_t lock; -++ int state; -++ int aic_dma_flag; /* start dma transfer or not */ -++ unsigned int dma_loaded; -++ unsigned int dma_limit; -++ unsigned int dma_period; -++ dma_addr_t dma_start; -++ dma_addr_t dma_pos; -++ dma_addr_t dma_end; -++ struct jz4740_pcm_dma_params *params; -++ -++ dma_addr_t user_cur_addr; /* user current write buffer start address */ -++ unsigned int user_cur_len; /* user current write buffer length */ -++ -++ /* buffer list and information */ -++ struct jz4740_dma_buf_aic *curr; /* current dma buffer */ -++ struct jz4740_dma_buf_aic *next; /* next buffer to load */ -++ struct jz4740_dma_buf_aic *end; /* end of queue */ -++ -++}; -++ -++/* identify hardware playback capabilities */ -++static const struct snd_pcm_hardware jz4740_pcm_hardware = { -++ .info = SNDRV_PCM_INFO_MMAP | -++ SNDRV_PCM_INFO_MMAP_VALID | -++ SNDRV_PCM_INFO_INTERLEAVED | -++ SNDRV_PCM_INFO_BLOCK_TRANSFER, -++ .formats = SNDRV_PCM_FMTBIT_S16_LE | -++ SNDRV_PCM_FMTBIT_U16_LE | -++ SNDRV_PCM_FMTBIT_U8 | -++ SNDRV_PCM_FMTBIT_S8, -++ .rates = SNDRV_PCM_RATE_8000_48000/*0x3fe*/, -++ .rate_min = 8000, -++ .rate_min = 48000, -++ .channels_min = 1,//2 -++ .channels_max = 2, -++ .buffer_bytes_max = 128 * 1024,//16 * 1024 -++ .period_bytes_min = PAGE_SIZE, -++ .period_bytes_max = PAGE_SIZE * 2, -++ .periods_min = 2, -++ .periods_max = 128,//16, -++ .fifo_size = 32, -++}; -++ -++/* jz4740__dma_buf_enqueue -++ * -++ * queue an given buffer for dma transfer. -++ * -++ * data the physical address of the buffer data -++ * size the size of the buffer in bytes -++ * -++*/ -++static int jz4740_dma_buf_enqueue(struct jz4740_runtime_data *prtd, dma_addr_t data, int size) -++{ -++ struct jz4740_dma_buf_aic *aic_buf; -++ -++ aic_buf = kzalloc(sizeof(struct jz4740_dma_buf_aic), GFP_KERNEL); -++ if (aic_buf == NULL) { -++ printk("aic buffer allocate failed,no memory!\n"); -++ return -ENOMEM; -++ } -++ aic_buf->next = NULL; -++ aic_buf->data = aic_buf->ptr = data; -++ aic_buf->size = size; -++ if( prtd->curr == NULL) { -++ prtd->curr = aic_buf; -++ prtd->end = aic_buf; -++ prtd->next = NULL; -++ } else { -++ if (prtd->end == NULL) -++ printk("prtd->end is NULL\n"); -++ prtd->end->next = aic_buf; -++ prtd->end = aic_buf; -++ } -++ -++ /* if necessary, update the next buffer field */ -++ if (prtd->next == NULL) -++ prtd->next = aic_buf; -++ -++ return 0; -++} -++ -++ -++void audio_start_dma(struct jz4740_runtime_data *prtd, int mode) -++{ -++ unsigned long flags; -++ struct jz4740_dma_buf_aic *aic_buf; -++ int channel; -++ -++ switch (mode) { -++ case DMA_MODE_WRITE: -++ /* free cur aic_buf */ -++ if (first_transfer == 1) { -++ first_transfer = 0; -++ } else { -++ aic_buf = prtd->curr; -++ if (aic_buf != NULL) { -++ prtd->curr = aic_buf->next; -++ prtd->next = aic_buf->next; -++ aic_buf->next = NULL; -++ kfree(aic_buf); -++ aic_buf = NULL; -++ } -++ } -++ -++ aic_buf = prtd->next; -++ channel = prtd->params->channel; -++ if (aic_buf) { -++ flags = claim_dma_lock(); -++ disable_dma(channel); -++ jz_set_alsa_dma(channel, mode, tran_bit); -++ set_dma_addr(channel, aic_buf->data); -++ set_dma_count(channel, aic_buf->size); -++ enable_dma(channel); -++ release_dma_lock(flags); -++ prtd->aic_dma_flag |= AIC_START_DMA; -++ } else { -++ printk("next buffer is NULL for playback\n"); -++ prtd->aic_dma_flag &= ~AIC_START_DMA; -++ return; -++ } -++ break; -++ case DMA_MODE_READ: -++ /* free cur aic_buf */ -++ if (first_transfer == 1) { -++ first_transfer = 0; -++ } else { -++ aic_buf = prtd->curr; -++ if (aic_buf != NULL) { -++ prtd->curr = aic_buf->next; -++ prtd->next = aic_buf->next; -++ aic_buf->next = NULL; -++ kfree(aic_buf); -++ aic_buf = NULL; -++ } -++ } -++ -++ aic_buf = prtd->next; -++ channel = prtd->params->channel; -++ -++ if (aic_buf) { -++ flags = claim_dma_lock(); -++ disable_dma(channel); -++ jz_set_alsa_dma(channel, mode, tran_bit); -++ set_dma_addr(channel, aic_buf->data); -++ set_dma_count(channel, aic_buf->size); -++ enable_dma(channel); -++ release_dma_lock(flags); -++ prtd->aic_dma_flag |= AIC_START_DMA; -++ } else { -++ printk("next buffer is NULL for capture\n"); -++ prtd->aic_dma_flag &= ~AIC_START_DMA; -++ return; -++ } -++ break; -++ } -++ /* dump_jz_dma_channel(channel); */ -++} -++ -++/* -++ * place a dma buffer onto the queue for the dma system to handle. -++*/ -++static void jz4740_pcm_enqueue(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ struct jz4740_runtime_data *prtd = runtime->private_data; -++ /*struct snd_dma_buffer *buf = &substream->dma_buffer;*/ -++ dma_addr_t pos = prtd->dma_pos; -++ int ret; -++ -++ while (prtd->dma_loaded < prtd->dma_limit) { -++ unsigned long len = prtd->dma_period; -++ -++ if ((pos + len) > prtd->dma_end) { -++ len = prtd->dma_end - pos; -++ } -++ ret = jz4740_dma_buf_enqueue(prtd, pos, len); -++ if (ret == 0) { -++ prtd->dma_loaded++; -++ pos += prtd->dma_period; -++ if (pos >= prtd->dma_end) -++ pos = prtd->dma_start; -++ } else -++ break; -++ } -++ -++ prtd->dma_pos = pos; -++} -++ -++/* -++ * call the function:jz4740_pcm_dma_irq() after DMA has transfered the current buffer -++ */ -++static irqreturn_t jz4740_pcm_dma_irq(int dma_ch, void *dev_id) -++{ -++ struct snd_pcm_substream *substream = dev_id; -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ struct jz4740_runtime_data *prtd = runtime->private_data; -++ /*struct jz4740_dma_buf_aic *aic_buf = prtd->curr;*/ -++ int channel = prtd->params->channel; -++ unsigned long flags; -++ -++ disable_dma(channel); -++ prtd->aic_dma_flag &= ~AIC_START_DMA; -++ /* must clear TT bit in DCCSR to avoid interrupt again */ -++ if (__dmac_channel_transmit_end_detected(channel)) { -++ __dmac_channel_clear_transmit_end(channel); -++ } -++ if (__dmac_channel_transmit_halt_detected(channel)) { -++ __dmac_channel_clear_transmit_halt(channel); -++ } -++ -++ if (__dmac_channel_address_error_detected(channel)) { -++ __dmac_channel_clear_address_error(channel); -++ } -++ -++ if (substream) -++ snd_pcm_period_elapsed(substream); -++ -++ spin_lock(&prtd->lock); -++ prtd->dma_loaded--; -++ if (prtd->state & ST_RUNNING) { -++ jz4740_pcm_enqueue(substream); -++ } -++ spin_unlock(&prtd->lock); -++ -++ local_irq_save(flags); -++ if (prtd->state & ST_RUNNING) { -++ if (prtd->dma_loaded) { -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -++ audio_start_dma(prtd, DMA_MODE_WRITE); -++ else -++ audio_start_dma(prtd, DMA_MODE_READ); -++ } -++ } -++ local_irq_restore(flags); -++ return IRQ_HANDLED; -++} -++ -++/* some parameter about DMA operation */ -++static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream, -++ struct snd_pcm_hw_params *params) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ struct jz4740_runtime_data *prtd = runtime->private_data; -++ struct snd_soc_pcm_runtime *rtd = substream->private_data; -++ struct jz4740_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; -++ size_t totbytes = params_buffer_bytes(params); -++ int ret; -++ -++#ifdef CONFIG_SND_OSSEMUL -++ if (hw_params_cnt) -++ return 0; -++ else -++ hw_params_cnt++ ; -++#endif -++ -++ if (!dma) -++ return 0; -++ -++ switch (params_format(params)) { -++ case SNDRV_PCM_FORMAT_S8: -++ tran_bit = 8; -++ break; -++ case SNDRV_PCM_FORMAT_S16_LE: -++ tran_bit = 16; -++ break; -++ } -++ -++ /* prepare DMA */ -++ prtd->params = dma; -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -++ ret = jz_request_dma(DMA_ID_AIC_TX, prtd->params->client->name, -++ jz4740_pcm_dma_irq, IRQF_DISABLED, substream); -++ if (ret < 0) -++ return ret; -++ prtd->params->channel = ret; -++ } else { -++ ret = jz_request_dma(DMA_ID_AIC_RX, prtd->params->client->name, -++ jz4740_pcm_dma_irq, IRQF_DISABLED, substream); -++ if (ret < 0) -++ return ret; -++ prtd->params->channel = ret; -++ } -++ -++ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); -++ runtime->dma_bytes = totbytes; -++ -++ spin_lock_irq(&prtd->lock); -++ prtd->dma_loaded = 0; -++ prtd->aic_dma_flag = 0; -++ prtd->dma_limit = runtime->hw.periods_min; -++ prtd->dma_period = params_period_bytes(params); -++ prtd->dma_start = runtime->dma_addr; -++ prtd->dma_pos = prtd->dma_start; -++ prtd->dma_end = prtd->dma_start + totbytes; -++ prtd->curr = NULL; -++ prtd->next = NULL; -++ prtd->end = NULL; -++ sum_bytes = 0; -++ first_transfer = 1; -++ printk_flag = 0; -++ -++ __dmac_disable_descriptor(prtd->params->channel); -++ __dmac_channel_disable_irq(prtd->params->channel); -++ spin_unlock_irq(&prtd->lock); -++ -++ return ret; -++} -++ -++static int jz4740_pcm_hw_free(struct snd_pcm_substream *substream) -++{ -++ struct jz4740_runtime_data *prtd = substream->runtime->private_data; -++ -++ snd_pcm_set_runtime_buffer(substream, NULL); -++ if (prtd->params) { -++ jz_free_dma(prtd->params->channel); -++ prtd->params = NULL; -++ } -++ -++ return 0; -++} -++ -++/* set some dma para for playback/capture */ -++static int jz4740_dma_ctrl(int channel) -++{ -++ -++ disable_dma(channel); -++ -++ /* must clear TT bit in DCCSR to avoid interrupt again */ -++ if (__dmac_channel_transmit_end_detected(channel)) { -++ __dmac_channel_clear_transmit_end(channel); -++ } -++ if (__dmac_channel_transmit_halt_detected(channel)) { -++ __dmac_channel_clear_transmit_halt(channel); -++ } -++ -++ if (__dmac_channel_address_error_detected(channel)) { -++ __dmac_channel_clear_address_error(channel); -++ } -++ -++ return 0; -++ -++} -++ -++static int jz4740_pcm_prepare(struct snd_pcm_substream *substream) -++{ -++ struct jz4740_runtime_data *prtd = substream->runtime->private_data; -++ int ret = 0; -++ -++ /* return if this is a bufferless transfer e.g */ -++ if (!prtd->params) -++ return 0; -++ -++ /* flush the DMA channel and DMA channel bit check */ -++ jz4740_dma_ctrl(prtd->params->channel); -++ prtd->dma_loaded = 0; -++ prtd->dma_pos = prtd->dma_start; -++ -++ /* enqueue dma buffers */ -++ jz4740_pcm_enqueue(substream); -++ -++ return ret; -++ -++} -++ -++static int jz4740_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ struct jz4740_runtime_data *prtd = runtime->private_data; -++ -++ int ret = 0; -++ -++ switch (cmd) { -++ case SNDRV_PCM_TRIGGER_START: -++ prtd->state |= ST_RUNNING; -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -++ audio_start_dma(prtd, DMA_MODE_WRITE); -++ } else { -++ audio_start_dma(prtd, DMA_MODE_READ); -++ } -++ -++ break; -++ -++ case SNDRV_PCM_TRIGGER_STOP: -++ case SNDRV_PCM_TRIGGER_SUSPEND: -++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -++ prtd->state &= ~ST_RUNNING; -++ break; -++ -++ case SNDRV_PCM_TRIGGER_RESUME: -++ printk(" RESUME \n"); -++ break; -++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -++ printk(" RESTART \n"); -++ break; -++ -++ default: -++ ret = -EINVAL; -++ } -++ -++ return ret; -++} -++ -++static snd_pcm_uframes_t -++jz4740_pcm_pointer(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ struct jz4740_runtime_data *prtd = runtime->private_data; -++ struct jz4740_dma_buf_aic *aic_buf = prtd->curr; -++ long count,res; -++ -++ dma_addr_t ptr; -++ snd_pcm_uframes_t x; -++ int channel = prtd->params->channel; -++ -++ spin_lock(&prtd->lock); -++#if 1 -++ -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -++ count = get_dma_residue(channel); -++ count = aic_buf->size - count; -++ ptr = aic_buf->data + count; -++ res = ptr - prtd->dma_start; -++ } else { -++ count = get_dma_residue(channel); -++ count = aic_buf->size - count; -++ ptr = aic_buf->data + count; -++ res = ptr - prtd->dma_start; -++ } -++ -++# else -++ -++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -++ if ((prtd->aic_dma_flag & AIC_START_DMA) == 0) { -++ count = get_dma_residue(channel); -++ count = aic_buf->size - count; -++ ptr = aic_buf->data + count; -++ REG_DMAC_DSAR(channel) = ptr; -++ res = ptr - prtd->dma_start; -++ } else { -++ ptr = REG_DMAC_DSAR(channel); -++ if (ptr == 0x0) -++ printk("\ndma address is 00000000 in running!\n"); -++ res = ptr - prtd->dma_start; -++ } -++ } else { -++ if ((prtd->aic_dma_flag & AIC_START_DMA) == 0) { -++ count = get_dma_residue(channel); -++ count = aic_buf->size - count; -++ ptr = aic_buf->data + count; -++ REG_DMAC_DTAR(channel) = ptr; -++ res = ptr - prtd->dma_start; -++ } else { -++ ptr = REG_DMAC_DTAR(channel); -++ if (ptr == 0x0) -++ printk("\ndma address is 00000000 in running!\n"); -++ res = ptr - prtd->dma_start; -++ } -++ } -++#endif -++ spin_unlock(&prtd->lock); -++ x = bytes_to_frames(runtime, res); -++ if (x == runtime->buffer_size) -++ x = 0; -++ -++ return x; -++} -++ -++static int jz4740_pcm_open(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ struct jz4740_runtime_data *prtd; -++ -++#ifdef CONFIG_SND_OSSEMUL -++ hw_params_cnt = 0; -++#endif -++ snd_soc_set_runtime_hwparams(substream, &jz4740_pcm_hardware); -++ prtd = kzalloc(sizeof(struct jz4740_runtime_data), GFP_KERNEL); -++ if (prtd == NULL) -++ return -ENOMEM; -++ -++ spin_lock_init(&prtd->lock); -++ -++ runtime->private_data = prtd; -++ -++ return 0; -++} -++ -++static int jz4740_pcm_close(struct snd_pcm_substream *substream) -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ struct jz4740_runtime_data *prtd = runtime->private_data; -++ struct jz4740_dma_buf_aic *aic_buf = NULL; -++ -++#ifdef CONFIG_SND_OSSEMUL -++ hw_params_cnt = 0; -++#endif -++ -++ if (prtd) -++ aic_buf = prtd->curr; -++ -++ while (aic_buf != NULL) { -++ prtd->curr = aic_buf->next; -++ prtd->next = aic_buf->next; -++ aic_buf->next = NULL; -++ kfree(aic_buf); -++ aic_buf = NULL; -++ aic_buf = prtd->curr; -++ } -++ -++ if (prtd) { -++ prtd->curr = NULL; -++ prtd->next = NULL; -++ prtd->end = NULL; -++ kfree(prtd); -++ } -++ -++ return 0; -++} -++ -++static int jz4740_pcm_mmap(struct snd_pcm_substream *substream, -++ struct vm_area_struct *vma)//include/linux/mm.h -++{ -++ struct snd_pcm_runtime *runtime = substream->runtime; -++ unsigned long start; -++ unsigned long off; -++ u32 len; -++ int ret = -ENXIO; -++ -++ off = vma->vm_pgoff << PAGE_SHIFT; -++ start = runtime->dma_addr; -++ -++ len = PAGE_ALIGN((start & ~PAGE_MASK) + runtime->dma_bytes); -++ start &= PAGE_MASK; -++ -++ if ((vma->vm_end - vma->vm_start + off) > len) { -++ return -EINVAL; -++ } -++ -++ off += start; -++ vma->vm_pgoff = off >> PAGE_SHIFT; -++ vma->vm_flags |= VM_IO; -++ -++#if defined(CONFIG_MIPS32) -++ pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; -++ pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; -++ /* pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; */ -++#endif -++ ret = io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, -++ vma->vm_end - vma->vm_start, -++ vma->vm_page_prot); -++ -++ return ret; -++} -++ -++struct snd_pcm_ops jz4740_pcm_ops = { -++ .open = jz4740_pcm_open, -++ .close = jz4740_pcm_close, -++ .ioctl = snd_pcm_lib_ioctl, -++ .hw_params = jz4740_pcm_hw_params, -++ .hw_free = jz4740_pcm_hw_free, -++ .prepare = jz4740_pcm_prepare, -++ .trigger = jz4740_pcm_trigger, -++ .pointer = jz4740_pcm_pointer, -++ .mmap = jz4740_pcm_mmap, -++}; -++ -++static int jz4740_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -++{ -++ struct snd_pcm_substream *substream = pcm->streams[stream].substream; -++ struct snd_dma_buffer *buf = &substream->dma_buffer; -++ size_t size = jz4740_pcm_hardware.buffer_bytes_max; -++ buf->dev.type = SNDRV_DMA_TYPE_DEV; -++ buf->dev.dev = pcm->card->dev; -++ buf->private_data = NULL; -++ -++ /*buf->area = dma_alloc_coherent(pcm->card->dev, size, -++ &buf->addr, GFP_KERNEL);*/ -++ buf->area = dma_alloc_noncoherent(pcm->card->dev, size, -++ &buf->addr, GFP_KERNEL); -++ if (!buf->area) -++ return -ENOMEM; -++ buf->bytes = size; -++ return 0; -++} -++ -++static void jz4740_pcm_free_dma_buffers(struct snd_pcm *pcm) -++{ -++ struct snd_pcm_substream *substream; -++ struct snd_dma_buffer *buf; -++ int stream; -++ -++ for (stream = 0; stream < 2; stream++) { -++ substream = pcm->streams[stream].substream; -++ if (!substream) -++ continue; -++ -++ buf = &substream->dma_buffer; -++ if (!buf->area) -++ continue; -++ -++ dma_free_noncoherent(pcm->card->dev, buf->bytes, -++ buf->area, buf->addr); -++ buf->area = NULL; -++ } -++} -++ -++static u64 jz4740_pcm_dmamask = DMA_32BIT_MASK; -++ -++int jz4740_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai, -++ struct snd_pcm *pcm) -++{ -++ int ret = 0; -++ -++ if (!card->dev->dma_mask) -++ card->dev->dma_mask = &jz4740_pcm_dmamask; -++ if (!card->dev->coherent_dma_mask) -++ card->dev->coherent_dma_mask = DMA_32BIT_MASK; -++ -++ if (dai->playback.channels_min) { -++ ret = jz4740_pcm_preallocate_dma_buffer(pcm, -++ SNDRV_PCM_STREAM_PLAYBACK); -++ if (ret) -++ goto out; -++ } -++ -++ if (dai->capture.channels_min) { -++ ret = jz4740_pcm_preallocate_dma_buffer(pcm, -++ SNDRV_PCM_STREAM_CAPTURE); -++ if (ret) -++ goto out; -++ } -++ out: -++ -++ return ret; -++} -++ -++struct snd_soc_platform jz4740_soc_platform = { -++ .name = "jz4740-audio", -++ .pcm_ops = &jz4740_pcm_ops, -++ .pcm_new = jz4740_pcm_new, -++ .pcm_free = jz4740_pcm_free_dma_buffers, -++}; -++ -++EXPORT_SYMBOL_GPL(jz4740_soc_platform); -++ -++MODULE_AUTHOR("Richard"); -++MODULE_DESCRIPTION("Ingenic Jz4740 PCM DMA module"); -++MODULE_LICENSE("GPL"); -+diff -urN linux-2.6.24.7.old/sound/soc/jz4740/jz4740-pcm.h linux-2.6.24.7/sound/soc/jz4740/jz4740-pcm.h -+--- linux-2.6.24.7.old/sound/soc/jz4740/jz4740-pcm.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/soc/jz4740/jz4740-pcm.h 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,33 @@ -++/* -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ */ -++ -++#ifndef _JZ4740_PCM_H -++#define _JZ4740_PCM_H -++ -++#include -++ -++#define ST_RUNNING (1<<0) -++#define ST_OPENED (1<<1) -++ -++#define AIC_START_DMA (1<<0) -++#define AIC_END_DMA (1<<1) -++ -++struct jz4740_dma_client { -++ char *name; -++}; -++ -++struct jz4740_pcm_dma_params { -++ struct jz4740_dma_client *client; /* stream identifier */ -++ int channel; /* Channel ID */ -++ dma_addr_t dma_addr; -++ int dma_size; /* Size of the DMA transfer */ -++}; -++ -++/* platform data */ -++extern struct snd_soc_platform jz4740_soc_platform; -++ -++#endif -+diff -urN linux-2.6.24.7.old/sound/soc/jz4740/pavo.c linux-2.6.24.7/sound/soc/jz4740/pavo.c -+--- linux-2.6.24.7.old/sound/soc/jz4740/pavo.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7/sound/soc/jz4740/pavo.c 2009-04-12 18:13:57.000000000 +0200 -+@@ -0,0 +1,360 @@ -++/* -++ * pavo.c -- SoC audio for PAVO -++ * -++ * This program is free software; you can redistribute it and/or modify it -++ * under the terms of the GNU General Public License as published by the -++ * Free Software Foundation; either version 2 of the License, or (at your -++ * option) any later version. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "../codecs/jzcodec.h" -++#include "jz4740-pcm.h" -++#include "jz4740-i2s.h" -++ -++#define PAVO_HP 0 -++#define PAVO_MIC 1 -++#define PAVO_LINE 2 -++#define PAVO_HEADSET 3 -++#define PAVO_HP_OFF 4 -++#define PAVO_SPK_ON 0 -++#define PAVO_SPK_OFF 1 -++ -++ /* audio clock in Hz - rounded from 12.235MHz */ -++#define PAVO_AUDIO_CLOCK 12288000 -++ -++static int pavo_jack_func; -++static int pavo_spk_func; -++ -++unsigned short set_scoop_gpio(struct device *dev, unsigned short bit) -++{ -++ unsigned short gpio_bit = 0; -++ -++ return gpio_bit; -++} -++ -++unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit) -++{ -++ unsigned short gpio_bit = 0; -++ -++ return gpio_bit; -++} -++ -++static void pavo_ext_control(struct snd_soc_codec *codec) -++{ -++ int spk = 0, mic = 0, line = 0, hp = 0, hs = 0; -++ -++ /* set up jack connection */ -++ switch (pavo_jack_func) { -++ case PAVO_HP: -++ hp = 1; -++ /* set = unmute headphone */ -++ //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); -++ //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); -++ break; -++ case PAVO_MIC: -++ mic = 1; -++ /* reset = mute headphone */ -++ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); -++ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); -++ break; -++ case PAVO_LINE: -++ line = 1; -++ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); -++ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); -++ break; -++ case PAVO_HEADSET: -++ hs = 1; -++ mic = 1; -++ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); -++ //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); -++ break; -++ } -++ -++ if (pavo_spk_func == PAVO_SPK_ON) -++ spk = 1; -++ -++ /* set the enpoints to their new connetion states */ -++ snd_soc_dapm_set_endpoint(codec, "Ext Spk", spk); -++ snd_soc_dapm_set_endpoint(codec, "Mic Jack", mic); -++ snd_soc_dapm_set_endpoint(codec, "Line Jack", line); -++ snd_soc_dapm_set_endpoint(codec, "Headphone Jack", hp); -++ snd_soc_dapm_set_endpoint(codec, "Headset Jack", hs); -++ -++ /* signal a DAPM event */ -++ snd_soc_dapm_sync_endpoints(codec); -++} -++ -++static int pavo_startup(struct snd_pcm_substream *substream) -++{ -++ struct snd_soc_pcm_runtime *rtd = substream->private_data; -++ struct snd_soc_codec *codec = rtd->socdev->codec; -++ -++ /* check the jack status at stream startup */ -++ pavo_ext_control(codec); -++ return 0; -++} -++ -++/* we need to unmute the HP at shutdown as the mute burns power on pavo */ -++static void pavo_shutdown(struct snd_pcm_substream *substream) -++{ -++ /*struct snd_soc_pcm_runtime *rtd = substream->private_data; -++ struct snd_soc_codec *codec = rtd->socdev->codec;*/ -++ -++ return; -++} -++ -++static int pavo_hw_params(struct snd_pcm_substream *substream, -++ struct snd_pcm_hw_params *params) -++{ -++ struct snd_soc_pcm_runtime *rtd = substream->private_data; -++ struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; -++ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; -++ int ret = 0; -++ -++ /* set codec DAI configuration */ -++ ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | -++ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); -++ if (ret < 0) -++ return ret; -++ -++ /* set cpu DAI configuration */ -++ ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | -++ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); -++ if (ret < 0) -++ return ret; -++ -++ /* set the codec system clock for DAC and ADC */ -++ ret = codec_dai->dai_ops.set_sysclk(codec_dai, JZCODEC_SYSCLK, 111, -++ SND_SOC_CLOCK_IN); -++ if (ret < 0) -++ return ret; -++ -++ /* set the I2S system clock as input (unused) */ -++ ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, JZ4740_I2S_SYSCLK, 0, -++ SND_SOC_CLOCK_IN); -++ if (ret < 0) -++ return ret; -++ -++ return 0; -++} -++ -++static struct snd_soc_ops pavo_ops = { -++ .startup = pavo_startup, -++ .hw_params = pavo_hw_params, -++ .shutdown = pavo_shutdown, -++}; -++ -++static int pavo_get_jack(struct snd_kcontrol *kcontrol, -++ struct snd_ctl_elem_value *ucontrol) -++{ -++ ucontrol->value.integer.value[0] = pavo_jack_func; -++ return 0; -++} -++ -++static int pavo_set_jack(struct snd_kcontrol *kcontrol, -++ struct snd_ctl_elem_value *ucontrol) -++{ -++ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); -++ -++ if (pavo_jack_func == ucontrol->value.integer.value[0]) -++ return 0; -++ -++ pavo_jack_func = ucontrol->value.integer.value[0]; -++ pavo_ext_control(codec); -++ return 1; -++} -++ -++static int pavo_get_spk(struct snd_kcontrol *kcontrol, -++ struct snd_ctl_elem_value *ucontrol) -++{ -++ ucontrol->value.integer.value[0] = pavo_spk_func; -++ return 0; -++} -++ -++static int pavo_set_spk(struct snd_kcontrol *kcontrol, -++ struct snd_ctl_elem_value *ucontrol) -++{ -++ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); -++ -++ if (pavo_spk_func == ucontrol->value.integer.value[0]) -++ return 0; -++ -++ pavo_spk_func = ucontrol->value.integer.value[0]; -++ pavo_ext_control(codec); -++ return 1; -++} -++ -++static int pavo_amp_event(struct snd_soc_dapm_widget *w, int event) -++{ -++ if (SND_SOC_DAPM_EVENT_ON(event)) -++ //set_scoop_gpio(&corgiscoop_device.dev, PAVO_SCP_APM_ON); -++ ; -++ else -++ //reset_scoop_gpio(&corgiscoop_device.dev, PAVO_SCP_APM_ON); -++ ; -++ -++ return 0; -++} -++ -++static int pavo_mic_event(struct snd_soc_dapm_widget *w, int event) -++{ -++ if (SND_SOC_DAPM_EVENT_ON(event)) -++ //set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS); -++ ; -++ else -++ //reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS); -++ ; -++ -++ return 0; -++} -++ -++/* pavo machine dapm widgets */ -++static const struct snd_soc_dapm_widget jzcodec_dapm_widgets[] = { -++SND_SOC_DAPM_HP("Headphone Jack", NULL), -++SND_SOC_DAPM_MIC("Mic Jack",pavo_mic_event), -++SND_SOC_DAPM_SPK("Ext Spk", pavo_amp_event), -++SND_SOC_DAPM_LINE("Line Jack", NULL), -++SND_SOC_DAPM_HP("Headset Jack", NULL), -++}; -++ -++/* pavo machine audio map (connections to the codec pins) */ -++static const char *audio_map[][3] = { -++ -++ /* headset Jack - in = micin, out = LHPOUT*/ -++ {"Headset Jack", NULL, "LHPOUT"}, -++ -++ /* headphone connected to LHPOUT1, RHPOUT1 */ -++ {"Headphone Jack", NULL, "LHPOUT"}, -++ {"Headphone Jack", NULL, "RHPOUT"}, -++ -++ /* speaker connected to LOUT, ROUT */ -++ {"Ext Spk", NULL, "ROUT"}, -++ {"Ext Spk", NULL, "LOUT"}, -++ -++ /* mic is connected to MICIN (via right channel of headphone jack) */ -++ {"MICIN", NULL, "Mic Jack"}, -++ -++ /* Same as the above but no mic bias for line signals */ -++ {"MICIN", NULL, "Line Jack"}, -++ -++ {NULL, NULL, NULL}, -++}; -++ -++static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset", -++ "Off"}; -++static const char *spk_function[] = {"On", "Off"}; -++static const struct soc_enum pavo_enum[] = { -++ SOC_ENUM_SINGLE_EXT(5, jack_function), -++ SOC_ENUM_SINGLE_EXT(2, spk_function), -++}; -++ -++static const struct snd_kcontrol_new jzcodec_pavo_controls[] = { -++ SOC_ENUM_EXT("Jack Function", pavo_enum[0], pavo_get_jack, -++ pavo_set_jack), -++ SOC_ENUM_EXT("Speaker Function", pavo_enum[1], pavo_get_spk, -++ pavo_set_spk), -++}; -++ -++/* -++ * Pavo for a jzcodec as connected on jz4740 Device -++ */ -++static int pavo_jzcodec_init(struct snd_soc_codec *codec) -++{ -++ int i, err; -++ -++ snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0); -++ snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0); -++ -++ /* Add pavo specific controls */ -++ for (i = 0; i < ARRAY_SIZE(jzcodec_pavo_controls); i++) { -++ err = snd_ctl_add(codec->card, -++ snd_soc_cnew(&jzcodec_pavo_controls[i],codec, NULL)); -++ if (err < 0) -++ return err; -++ } -++ -++ /* Add pavo specific widgets */ -++ for(i = 0; i < ARRAY_SIZE(jzcodec_dapm_widgets); i++) { -++ snd_soc_dapm_new_control(codec, &jzcodec_dapm_widgets[i]); -++ } -++ -++ /* Set up pavo specific audio path audio_map */ -++ for(i = 0; audio_map[i][0] != NULL; i++) { -++ snd_soc_dapm_connect_input(codec, audio_map[i][0], -++ audio_map[i][1], audio_map[i][2]); -++ } -++ -++ snd_soc_dapm_sync_endpoints(codec); -++ return 0; -++} -++ -++/* pavo digital audio interface glue - connects codec <--> CPU */ -++static struct snd_soc_dai_link pavo_dai = { -++ .name = "JZCODEC", -++ .stream_name = "JZCODEC", -++ .cpu_dai = &jz4740_i2s_dai, -++ .codec_dai = &jzcodec_dai, -++ .init = pavo_jzcodec_init, -++ .ops = &pavo_ops, -++}; -++ -++/* pavo audio machine driver */ -++static struct snd_soc_machine snd_soc_machine_pavo = { -++ .name = "Pavo", -++ .dai_link = &pavo_dai, -++ .num_links = 1, -++}; -++ -++/* pavo audio subsystem */ -++static struct snd_soc_device pavo_snd_devdata = { -++ .machine = &snd_soc_machine_pavo, -++ .platform = &jz4740_soc_platform, -++ .codec_dev = &soc_codec_dev_jzcodec, -++ //.codec_data -++}; -++ -++static struct platform_device *pavo_snd_device; -++ -++static int __init pavo_init(void) -++{ -++ int ret; -++ -++ pavo_snd_device = platform_device_alloc("soc-audio", -1); -++ -++ if (!pavo_snd_device) -++ return -ENOMEM; -++ -++ platform_set_drvdata(pavo_snd_device, &pavo_snd_devdata); -++ pavo_snd_devdata.dev = &pavo_snd_device->dev; -++ ret = platform_device_add(pavo_snd_device); -++ -++ if (ret) -++ platform_device_put(pavo_snd_device); -++ -++ return ret; -++} -++ -++static void __exit pavo_exit(void) -++{ -++ platform_device_unregister(pavo_snd_device); -++} -++ -++module_init(pavo_init); -++module_exit(pavo_exit); -++ -++/* Module information */ -++MODULE_AUTHOR("Richard"); -++MODULE_DESCRIPTION("ALSA SoC Pavo"); -++MODULE_LICENSE("GPL"); -Index: target/linux/jz47x0/patches-2.6.24/002-yaffs2_dists.patch -=================================================================== ---- target/linux/jz47x0/patches-2.6.24/002-yaffs2_dists.patch (revision 0) -+++ target/linux/jz47x0/patches-2.6.24/002-yaffs2_dists.patch (revision 0) -@@ -0,0 +1,8842 @@ -+diff -urN linux-2.6.24.7/fs/yaffs2/Kconfig linux-2.6.24.7.new/fs/yaffs2/Kconfig -+--- linux-2.6.24.7/fs/yaffs2/Kconfig 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/Kconfig 2009-04-21 15:01:02.000000000 +0200 -+@@ -2,6 +2,8 @@ -+ # YAFFS file system configurations -+ # -+ -++menu "Yaffs2 Filesystems" -++ -+ config YAFFS_FS -+ tristate "YAFFS2 file system support" -+ default n -+@@ -12,8 +14,8 @@ -+ YAFFS2, or Yet Another Flash Filing System, is a filing system -+ optimised for NAND Flash chips. -+ -+- To compile the YAFFS2 file system support as a module, choose M -+- here: the module will be called yaffs2. -++ To compile the YAFFS2 file system support as a module, choose M here: -++ the module will be called yaffs2. -+ -+ If unsure, say N. -+ -+@@ -27,29 +29,11 @@ -+ help -+ Enable YAFFS1 support -- yaffs for 512 byte / page devices -+ -+- Not needed for 2K-page devices. -+- -+ If unsure, say Y. -+ -+-config YAFFS_9BYTE_TAGS -+- bool "Use older-style on-NAND data format with pageStatus byte" -+- depends on YAFFS_YAFFS1 -+- default n -+- help -+- -+- Older-style on-NAND data format has a "pageStatus" byte to record -+- chunk/page state. This byte is zero when the page is discarded. -+- Choose this option if you have existing on-NAND data using this -+- format that you need to continue to support. New data written -+- also uses the older-style format. Note: Use of this option -+- generally requires that MTD's oob layout be adjusted to use the -+- older-style format. See notes on tags formats and MTD versions. -+- -+- If unsure, say N. -+- -+ config YAFFS_DOES_ECC -+ bool "Lets Yaffs do its own ECC" -+- depends on YAFFS_FS && YAFFS_YAFFS1 && !YAFFS_9BYTE_TAGS -++ depends on YAFFS_FS && YAFFS_YAFFS1 -+ default n -+ help -+ This enables Yaffs to use its own ECC functions instead of using -+@@ -59,12 +43,12 @@ -+ -+ config YAFFS_ECC_WRONG_ORDER -+ bool "Use the same ecc byte order as Steven Hill's nand_ecc.c" -+- depends on YAFFS_FS && YAFFS_DOES_ECC && !YAFFS_9BYTE_TAGS -++ depends on YAFFS_FS && YAFFS_DOES_ECC -+ default n -+ help -+- This makes yaffs_ecc.c use the same ecc byte order as Steven -+- Hill's nand_ecc.c. If not set, then you get the same ecc byte -+- order as SmartMedia. -++ This makes yaffs_ecc.c use the same ecc byte order as -++ Steven Hill's nand_ecc.c. If not set, then you get the -++ same ecc byte order as SmartMedia. -+ -+ If unsure, say N. -+ -+@@ -73,10 +57,39 @@ -+ depends on YAFFS_FS -+ default y -+ help -+- Enable YAFFS2 support -- yaffs for >= 2K bytes per page devices -++ Enable YAFFS2 support -- yaffs for >= 2048 byte / page larger devices -+ -+ If unsure, say Y. -+ -++if SOC_JZ4730 || SOC_JZ4740 -++ -++choice -++ prompt "ECC type for oob area" -++ depends on YAFFS_YAFFS2 -++ default CONFIG_YAFFS_ECC_RS -++ help -++ There are 16 bytes for yaffs2 information in oob which should be checked -++ using some type of ECC. -++ -++config YAFFS_ECC_RS -++ bool "Use soft reed solomon ECC for oob area" -++ select REED_SOLOMON -++ select REED_SOLOMON_ENC8 -++ select REED_SOLOMON_DEC8 -++ help -++ The reed solomon ECC could correct 2 5-bit symbols for 16 bytes in oob. -++ It should be selected for MLC nand. -++ -++config YAFFS_ECC_HAMMING -++ bool "Use hamming ECC for oob area" -++ help -++ The hamming ECC could only correct 1 bit for 16 bytes in oob, but it's -++ a bit faster than reed solomon ECC. It should be selected for SLC nand. -++ -++endchoice -++ -++endif -++ -+ config YAFFS_AUTO_YAFFS2 -+ bool "Autoselect yaffs2 format" -+ depends on YAFFS_YAFFS2 -+@@ -84,8 +97,7 @@ -+ help -+ Without this, you need to explicitely use yaffs2 as the file -+ system type. With this, you can say "yaffs" and yaffs or yaffs2 -+- will be used depending on the device page size (yaffs on -+- 512-byte page devices, yaffs2 on 2K page devices). -++ will be used depending on the device page size. -+ -+ If unsure, say Y. -+ -+@@ -109,57 +121,30 @@ -+ -+ If unsure, say N. -+ -+-config YAFFS_CHECKPOINT_RESERVED_BLOCKS -+- int "Reserved blocks for checkpointing" -+- depends on YAFFS_YAFFS2 -+- default 10 -+- help -+- Give the number of Blocks to reserve for checkpointing. -+- Checkpointing saves the state at unmount so that mounting is -+- much faster as a scan of all the flash to regenerate this state -+- is not needed. These Blocks are reserved per partition, so if -+- you have very small partitions the default (10) may be a mess -+- for you. You can set this value to 0, but that does not mean -+- checkpointing is disabled at all. There only won't be any -+- specially reserved blocks for checkpointing, so if there is -+- enough free space on the filesystem, it will be used for -+- checkpointing. -+- -+- If unsure, leave at default (10), but don't wonder if there are -+- always 2MB used on your large page device partition (10 x 2k -+- pagesize). When using small partitions or when being very small -+- on space, you probably want to set this to zero. -+- -+ config YAFFS_DISABLE_WIDE_TNODES -+ bool "Turn off wide tnodes" -+ depends on YAFFS_FS -+ default n -+ help -+- Wide tnodes are only used for NAND arrays >=32MB for 512-byte -+- page devices and >=128MB for 2k page devices. They use slightly -+- more RAM but are faster since they eliminate chunk group -++ Wide tnodes are only used for large NAND arrays (>=32MB for -++ 512-byte page devices and >=128MB for 2k page devices). They use -++ slightly more RAM but are faster since they eliminate chunk group -+ searching. -+ -+- Setting this to 'y' will force tnode width to 16 bits and save -+- memory but make large arrays slower. -++ Setting this to 'y' will force tnode width to 16 bits and make -++ large arrays slower. -+ -+ If unsure, say N. -+ -+-config YAFFS_ALWAYS_CHECK_CHUNK_ERASED -+- bool "Force chunk erase check" -++config YAFFS_DISABLE_CHUNK_ERASED_CHECK -++ bool "Turn off debug chunk erase check" -+ depends on YAFFS_FS -+- default n -++ default y -+ help -+- Normally YAFFS only checks chunks before writing until an erased -+- chunk is found. This helps to detect any partially written -+- chunks that might have happened due to power loss. -+- -+- Enabling this forces on the test that chunks are erased in flash -+- before writing to them. This takes more time but is potentially -+- a bit more secure. -+- -+- Suggest setting Y during development and ironing out driver -+- issues etc. Suggest setting to N if you want faster writing. -++ Enabling this turns off the test that chunks are erased in flash -++ before writing to them. This is safe, since the write verification -++ will fail. Suggest enabling the test (ie. say N) -++ during development to help debug things. -+ -+ If unsure, say Y. -+ -+@@ -173,3 +158,10 @@ -+ but makes look-ups faster. -+ -+ If unsure, say Y. -++ -++config YAFFS_CHECKPOINT_RESERVED_BLOCKS -++ int 'Reserved blocks for checkpointing' -++ depends on YAFFS_FS -++ default 10 -++ -++endmenu -+diff -urN linux-2.6.24.7/fs/yaffs2/Makefile linux-2.6.24.7.new/fs/yaffs2/Makefile -+--- linux-2.6.24.7/fs/yaffs2/Makefile 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/Makefile 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,11 +1,10 @@ -+ # -+-# Makefile for the linux YAFFS filesystem routines. -++# Makefile for the linux YAFFS2 filesystem routines. -+ # -+ -+-obj-$(CONFIG_YAFFS_FS) += yaffs.o -+- -+-yaffs-y := yaffs_ecc.o yaffs_fs.o yaffs_guts.o yaffs_checkptrw.o -+-yaffs-y += yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o -+-yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o -+-yaffs-y += yaffs_mtdif1.o yaffs_packedtags1.o -+-yaffs-y += yaffs_mtdif.o yaffs_mtdif2.o -++obj-y := yaffs2.o -++obj-$(CONFIG_YAFFS_FS) := yaffs_mtdif.o yaffs_mtdif2.o -++obj-$(CONFIG_YAFFS_FS) += yaffs_ecc.o yaffs_fs.o yaffs_guts.o -++obj-$(CONFIG_YAFFS_FS) += yaffs_packedtags2.o yaffs_qsort.o -++obj-$(CONFIG_YAFFS_FS) += yaffs_tagscompat.o yaffs_tagsvalidity.o -++obj-$(CONFIG_YAFFS_FS) += yaffs_checkptrw.o yaffs_nand.o -+diff -urN linux-2.6.24.7/fs/yaffs2/devextras.h linux-2.6.24.7.new/fs/yaffs2/devextras.h -+--- linux-2.6.24.7/fs/yaffs2/devextras.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/devextras.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ /* -+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+@@ -15,7 +15,7 @@ -+ -+ /* -+ * This file is just holds extra declarations used during development. -+- * Most of these are from kernel includes placed here so we can use them in -++ * Most of these are from kernel includes placed here so we can use them in -+ * applications. -+ * -+ */ -+diff -urN linux-2.6.24.7/fs/yaffs2/moduleconfig.h linux-2.6.24.7.new/fs/yaffs2/moduleconfig.h -+--- linux-2.6.24.7/fs/yaffs2/moduleconfig.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/moduleconfig.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,10 +1,10 @@ -+ /* -+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+ * -+- * Created by Martin Fouts -++ * Created by Martin Fouts -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU Lesser General Public License version 2.1 as -+@@ -44,21 +44,7 @@ -+ -+ /* Default: 10 */ -+ /* Meaning: set the count of blocks to reserve for checkpointing */ -+-#define CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS 10 -+- -+-/* -+-Older-style on-NAND data format has a "pageStatus" byte to record -+-chunk/page state. This byte is zeroed when the page is discarded. -+-Choose this option if you have existing on-NAND data in this format -+-that you need to continue to support. New data written also uses the -+-older-style format. -+-Note: Use of this option generally requires that MTD's oob layout be -+-adjusted to use the older-style format. See notes on tags formats and -+-MTD versions. -+-*/ -+-/* Default: Not selected */ -+-/* Meaning: Use older-style on-NAND data format with pageStatus byte */ -+-#define CONFIG_YAFFS_9BYTE_TAGS -++#define YAFFS_CHECKPOINT_RESERVED_BLOCKS 10 -+ -+ #endif /* YAFFS_OUT_OF_TREE */ -+ -+diff -urN linux-2.6.24.7/fs/yaffs2/utils/Makefile linux-2.6.24.7.new/fs/yaffs2/utils/Makefile -+--- linux-2.6.24.7/fs/yaffs2/utils/Makefile 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7.new/fs/yaffs2/utils/Makefile 2009-04-21 15:01:02.000000000 +0200 -+@@ -0,0 +1,69 @@ -++#Makefile for mkyaffs -++# -++# NB this is not yet suitable for putting into the kernel tree. -++# YAFFS: Yet another Flash File System. A NAND-flash specific file system. -++# -++# Copyright (C) 2002 Aleph One Ltd. -++# for Toby Churchill Ltd and Brightstar Engineering -++# -++# Created by Charles Manning -++# -++# This program is free software; you can redistribute it and/or modify -++# it under the terms of the GNU General Public License version 2 as -++# published by the Free Software Foundation. -++ -++## Change or override KERNELDIR to your kernel -++#KERNELDIR = /usr/src/kernel-headers-2.4.18 -++#CFLAGS = -I$(KERNELDIR)/include -I.. -O2 -Wall -DCONFIG_YAFFS_UTIL -++ -++include ../../../.config -++ -++CFLAGS = -I../../../include -I.. -O2 -Wall -DCONFIG_YAFFS_UTIL -++CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations -++CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline -++ -++ifeq ($(CONFIG_YAFFS_ECC_RS), y) -++CFLAGS+= -DCONFIG_YAFFS_ECC_RS -++endif -++ -++ifeq ($(CONFIG_YAFFS_ECC_HAMMING), y) -++CFLAGS+= -DCONFIG_YAFFS_ECC_HAMMING -++endif -++ -++ -++## Change if you are using a cross-compiler -++MAKETOOLS = #mipsel-linux- -++ -++CC=$(MAKETOOLS)gcc -++ -++COMMONLINKS = yaffs_ecc.c -++COMMONOBJS = $(COMMONLINKS:.c=.o) -++ -++ifeq ($(CONFIG_YAFFS_ECC_RS), y) -++COMMONOBJS += ssfdc_rs_ecc.o -++endif -++ -++MKYAFFSSOURCES = mkyaffsimage.c -++MKYAFFSIMAGEOBJS = $(MKYAFFSSOURCES:.c=.o) -++ -++MKYAFFS2SOURCES = mkyaffs2image.c -++MKYAFFS2LINKS = yaffs_packedtags2.c yaffs_tagsvalidity.c -++MKYAFFS2IMAGEOBJS = $(MKYAFFS2SOURCES:.c=.o) $(MKYAFFS2LINKS:.c=.o) -++ -++all: mkyaffsimage mkyaffs2image -++ -++$(COMMONLINKS) $(MKYAFFSLINKS) $(MKYAFFS2LINKS): -++ ln -s ../$@ $@ -++ -++$(COMMONOBJS) $(MKYAFFSIMAGEOBJS) $(MKYAFFS2IMAGEOBJS) : %.o: %.c -++ $(CC) -c $(CFLAGS) $< -o $@ -++ -++mkyaffsimage: $(COMMONOBJS) $(MKYAFFSIMAGEOBJS) -++ $(CC) -o $@ $(COMMONOBJS) $(MKYAFFSIMAGEOBJS) -++ -++mkyaffs2image: $(COMMONOBJS) $(MKYAFFS2IMAGEOBJS) -++ $(CC) -o $@ $(COMMONOBJS) $(MKYAFFS2IMAGEOBJS) -++ -++ -++clean: -++ rm -f $(COMMONOBJS) $(MKYAFFSIMAGEOBJS) $(MKYAFFS2IMAGEOBJS) $(COMMONLINKS) $(MKYAFFSLINKS) $(MKYAFFS2LINKS) mkyaffsimage mkyaffs2image core -+diff -urN linux-2.6.24.7/fs/yaffs2/utils/README linux-2.6.24.7.new/fs/yaffs2/utils/README -+--- linux-2.6.24.7/fs/yaffs2/utils/README 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7.new/fs/yaffs2/utils/README 2009-04-21 15:01:02.000000000 +0200 -+@@ -0,0 +1,11 @@ -++This directory contains yaffs/yaffs2 tools to make the fs image. -++ -++To build the tools, type 'make'. -++ -++To make yaffs2 image, use next command: -++ -++ $ mkyaffs2image 1 /myroot myroot.yaffs2 -++ -++To burn the yaffs2 image to the NAND, use next command: -++ -++ $ nandwrite -a -o /dev/mtd0 myroot.yaffs2 -+diff -urN linux-2.6.24.7/fs/yaffs2/utils/mkyaffs2image.c linux-2.6.24.7.new/fs/yaffs2/utils/mkyaffs2image.c -+--- linux-2.6.24.7/fs/yaffs2/utils/mkyaffs2image.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7.new/fs/yaffs2/utils/mkyaffs2image.c 2009-04-21 15:01:02.000000000 +0200 -+@@ -0,0 +1,738 @@ -++/* -++ * YAFFS: Yet another FFS. A NAND-flash specific file system. -++ * -++ * makeyaffsimage.c -++ * -++ * Makes a YAFFS file system image that can be used to load up a file system. -++ * -++ * Copyright (C) 2002 Aleph One Ltd. -++ * for Toby Churchill Ltd and Brightstar Engineering -++ * -++ * Created by Charles Manning -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ * -++ * Nick Bane modifications flagged NCB -++ * -++ * Endian handling patches by James Ng. -++ * -++ * mkyaffs2image hacks by NCB -++ * -++ * Changes by Sergey Kubushin flagged KSI -++ * -++ */ -++ -++/* KSI: -++ * All this nightmare should be rewritten from ground up. Why save return -++ * values if nobody checks them? The read/write function returns only one -++ * error, -1. Positive return value does NOT mean read/write operation has -++ * been completed successfully. If somebody opens files, he MUST close them -++ * when they are not longer needed. Only those brave enough can write 64 -++ * bytes from a yaffs_PackedTags2 structure. The list is too long, there is -++ * enough bugs here to write a couple of thick books on how NOT to write -++ * programs... -++ * -++ * And BTW, what was one supposed to do with that file that this horror -++ * occasionally managed to generate? -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "yaffs_ecc.h" -++#include "yaffs_guts.h" -++ -++#include "yaffs_packedtags2.h" -++ -++unsigned yaffs_traceMask=0; -++ -++#define MAX_OBJECTS 100000 -++#define MAX_CHUNKSIZE 8192 -++#define MAX_SPARESIZE 256 -++ -++#define PT2_BYTES 25 -++ -++const char * mkyaffsimage_c_version = "$Id: mkyaffs2image.c,v 1.1.1.1 2008-10-29 14:29:21 lhhuang Exp $"; -++ -++static int chunkSize = 2048; -++static int spareSize = 64; -++static int layout_no; -++ -++static struct nand_oobinfo oob_layout[] = { -++ /* KSI: -++ * Dummy "raw" layout - no ECC, all the bytes are free. Does NOT -++ * really work, only used for compatibility with CVS YAFFS2 that -++ * never ever worked with any stock MTD. -++ */ -++ { -++ .useecc = MTD_NANDECC_AUTOPLACE, -++ .eccbytes = 0, -++ .eccpos = {}, -++ .oobfree = { {0, 64} } -++ }, -++ /* KSI: -++ * Regular MTD AUTOPLACED ECC for large page NAND devices, the -++ * only one existing in stock MTD so far. It corresponds to layout# 1 -++ * in command line arguments. Any other layouts could be added to -++ * the list when they made their way in kernel's MTD. The structure -++ * is simply copied from kernel's drivers/mtd/nand/nand_base.c as-is. -++ */ -++ /* For 2KB pagesize NAND devices */ -++ { -++ .useecc = MTD_NANDECC_AUTOPLACE, -++ .eccbytes = 24, -++ .eccpos = { -++ 40, 41, 42, 43, 44, 45, 46, 47, -++ 48, 49, 50, 51, 52, 53, 54, 55, -++ 56, 57, 58, 59, 60, 61, 62, 63}, -++ .oobfree = { {2, 38} } -++ }, -++ /* For 4KB pagesize NAND devices */ -++ { -++ .useecc = MTD_NANDECC_AUTOPLACE, -++ .eccbytes = 72, -++ .eccpos = { -++ 56, 57, 58, 59, 60, 61, 62, 63, -++ 64, 65, 66, 67, 68, 69, 70, 71, -++ 72, 73, 74, 75, 76, 77, 78, 79, -++ 80, 81, 82, 83, 84, 85, 86, 87, -++ 88, 89, 90, 91, 92, 93, 94, 95, -++ 96, 97, 98, 99, 100, 101, 102, 103, -++ 104, 105, 106, 107, 108, 109, 110, 111, -++ 112, 113, 114, 115, 116, 117, 118, 119, -++ 120, 121, 122, 123, 124, 125, 126, 127}, -++ .oobfree = { {2, 54} } -++ }, -++ /* For 4KB pagesize with 2 planes NAND devices */ -++ { -++ .useecc = MTD_NANDECC_AUTOPLACE, -++ .eccbytes = 72, -++ .eccpos = { -++ 56, 57, 58, 59, 60, 61, 62, 63, -++ 64, 65, 66, 67, 68, 69, 70, 71, -++ 72, 73, 74, 75, 76, 77, 78, 79, -++ 80, 81, 82, 83, 84, 85, 86, 87, -++ 88, 89, 90, 91, 92, 93, 94, 95, -++ 96, 97, 98, 99, 100, 101, 102, 103, -++ 104, 105, 106, 107, 108, 109, 110, 111, -++ 112, 113, 114, 115, 116, 117, 118, 119, -++ 120, 121, 122, 123, 124, 125, 126, 127}, -++ .oobfree = { {2, 54} } -++ }, -++ /* End-of-list marker */ -++ { -++ .useecc = -1, -++ } -++}; -++ -++typedef struct -++{ -++ dev_t dev; -++ ino_t ino; -++ int obj; -++} objItem; -++ -++ -++static objItem obj_list[MAX_OBJECTS]; -++static int n_obj = 0; -++static int obj_id = YAFFS_NOBJECT_BUCKETS + 1; -++ -++static int nObjects = 0, nDirectories = 0, nPages = 0; -++ -++static int outFile; -++ -++static int error; -++ -++static int convert_endian = 0; -++ -++static int obj_compare(const void *a, const void * b) -++{ -++ objItem *oa, *ob; -++ -++ oa = (objItem *)a; -++ ob = (objItem *)b; -++ -++ if(oa->dev < ob->dev) return -1; -++ if(oa->dev > ob->dev) return 1; -++ if(oa->ino < ob->ino) return -1; -++ if(oa->ino > ob->ino) return 1; -++ -++ return 0; -++} -++ -++ -++static void add_obj_to_list(dev_t dev, ino_t ino, int obj) -++{ -++ if(n_obj < MAX_OBJECTS) -++ { -++ obj_list[n_obj].dev = dev; -++ obj_list[n_obj].ino = ino; -++ obj_list[n_obj].obj = obj; -++ n_obj++; -++ qsort(obj_list,n_obj,sizeof(objItem),obj_compare); -++ -++ } -++ else -++ { -++ // oops! not enough space in the object array -++ fprintf(stderr,"Not enough space in object array\n"); -++ exit(2); -++ } -++} -++ -++ -++static int find_obj_in_list(dev_t dev, ino_t ino) -++{ -++ objItem *i = NULL; -++ objItem test; -++ -++ test.dev = dev; -++ test.ino = ino; -++ -++ if(n_obj > 0) -++ { -++ i = bsearch(&test,obj_list,n_obj,sizeof(objItem),obj_compare); -++ } -++ -++ if(i) -++ { -++ return i->obj; -++ } -++ return -1; -++} -++ -++/* KSI: -++ * No big endian for now. This is left for a later time. The existing code -++ * is FUBAR. -++ */ -++#if 0 -++/* This little function converts a little endian tag to a big endian tag. -++ * NOTE: The tag is not usable after this other than calculating the CRC -++ * with. -++ */ -++static void little_to_big_endian(yaffs_Tags *tagsPtr) -++{ -++#if 0 // FIXME NCB -++ yaffs_TagsUnion * tags = (yaffs_TagsUnion* )tagsPtr; // Work in bytes. -++ yaffs_TagsUnion temp; -++ -++ memset(&temp, 0, sizeof(temp)); -++ // Ick, I hate magic numbers. -++ temp.asBytes[0] = ((tags->asBytes[2] & 0x0F) << 4) | ((tags->asBytes[1] & 0xF0) >> 4); -++ temp.asBytes[1] = ((tags->asBytes[1] & 0x0F) << 4) | ((tags->asBytes[0] & 0xF0) >> 4); -++ temp.asBytes[2] = ((tags->asBytes[0] & 0x0F) << 4) | ((tags->asBytes[2] & 0x30) >> 2) | ((tags->asBytes[3] & 0xC0) >> 6); -++ temp.asBytes[3] = ((tags->asBytes[3] & 0x3F) << 2) | ((tags->asBytes[2] & 0xC0) >> 6); -++ temp.asBytes[4] = ((tags->asBytes[6] & 0x03) << 6) | ((tags->asBytes[5] & 0xFC) >> 2); -++ temp.asBytes[5] = ((tags->asBytes[5] & 0x03) << 6) | ((tags->asBytes[4] & 0xFC) >> 2); -++ temp.asBytes[6] = ((tags->asBytes[4] & 0x03) << 6) | (tags->asBytes[7] & 0x3F); -++ temp.asBytes[7] = (tags->asBytes[6] & 0xFC) | ((tags->asBytes[7] & 0xC0) >> 6); -++ -++ // Now copy it back. -++ tags->asBytes[0] = temp.asBytes[0]; -++ tags->asBytes[1] = temp.asBytes[1]; -++ tags->asBytes[2] = temp.asBytes[2]; -++ tags->asBytes[3] = temp.asBytes[3]; -++ tags->asBytes[4] = temp.asBytes[4]; -++ tags->asBytes[5] = temp.asBytes[5]; -++ tags->asBytes[6] = temp.asBytes[6]; -++ tags->asBytes[7] = temp.asBytes[7]; -++#endif -++} -++#endif -++ -++void nandmtd2_pt2buf(unsigned char *buf, yaffs_PackedTags2 *pt) -++{ -++ int i, j = 0, k, n; -++ unsigned char pt2_byte_buf[PT2_BYTES]; -++ -++ *((unsigned int *) &pt2_byte_buf[0]) = pt->t.sequenceNumber; -++ *((unsigned int *) &pt2_byte_buf[4]) = pt->t.objectId; -++ *((unsigned int *) &pt2_byte_buf[8]) = pt->t.chunkId; -++ *((unsigned int *) &pt2_byte_buf[12]) = pt->t.byteCount; -++ pt2_byte_buf[16] = pt->ecc.colParity; -++ pt2_byte_buf[17] = pt->ecc.lineParity & 0xff; -++ pt2_byte_buf[18] = (pt->ecc.lineParity >> 8) & 0xff; -++ pt2_byte_buf[19] = (pt->ecc.lineParity >> 16) & 0xff; -++ pt2_byte_buf[20] = (pt->ecc.lineParity >> 24) & 0xff; -++ pt2_byte_buf[21] = pt->ecc.lineParityPrime & 0xff; -++ pt2_byte_buf[22] = (pt->ecc.lineParityPrime >> 8) & 0xff; -++ pt2_byte_buf[23] = (pt->ecc.lineParityPrime >> 16) & 0xff; -++ pt2_byte_buf[24] = (pt->ecc.lineParityPrime >> 24) & 0xff; -++ -++ k = oob_layout[layout_no].oobfree[j][0]; -++ n = oob_layout[layout_no].oobfree[j][1]; -++ -++ if (n == 0) { -++ fprintf(stderr, "No OOB space for tags"); -++ exit(-1); -++ } -++ -++ for (i = 0; i < PT2_BYTES; i++) { -++ if (n == 0) { -++ j++; -++ k = oob_layout[layout_no].oobfree[j][0]; -++ n = oob_layout[layout_no].oobfree[j][1]; -++ if (n == 0) { -++ fprintf(stderr, "No OOB space for tags"); -++ exit(-1); -++ } -++ } -++ buf[k++] = pt2_byte_buf[i]; -++ n--; -++ } -++} -++ -++static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes) -++{ -++ yaffs_ExtendedTags t; -++ yaffs_PackedTags2 pt; -++ unsigned char spare_buf[MAX_SPARESIZE]; -++ -++ -++ error = write(outFile,data,chunkSize); -++ if(error < 0) return error; -++ -++ yaffs_InitialiseTags(&t); -++ -++ t.chunkId = chunkId; -++// t.serialNumber = 0; -++ t.serialNumber = 1; // **CHECK** -++ t.byteCount = nBytes; -++ t.objectId = objId; -++ -++ t.sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER; -++ -++// added NCB **CHECK** -++ t.chunkUsed = 1; -++ -++/* KSI: Broken anyway -- e.g. &t is pointer to a wrong type... */ -++#if 0 -++ if (convert_endian) -++ { -++ little_to_big_endian(&t); -++ } -++#endif -++ -++ nPages++; -++ -++ yaffs_PackTags2(&pt,&t); -++ -++ memset(spare_buf, 0xff, spareSize); -++ -++ if (layout_no == 0) { -++ memcpy(spare_buf, &pt, sizeof(yaffs_PackedTags2)); -++ } else { -++ nandmtd2_pt2buf(spare_buf, &pt); -++ } -++ -++ return write(outFile,spare_buf,spareSize); -++} -++ -++#define SWAP32(x) ((((x) & 0x000000FF) << 24) | \ -++ (((x) & 0x0000FF00) << 8 ) | \ -++ (((x) & 0x00FF0000) >> 8 ) | \ -++ (((x) & 0xFF000000) >> 24)) -++ -++#define SWAP16(x) ((((x) & 0x00FF) << 8) | \ -++ (((x) & 0xFF00) >> 8)) -++ -++/* KSI: Removed for now. TBD later when the proper util (from scratch) is written */ -++#if 0 -++// This one is easier, since the types are more standard. No funky shifts here. -++static void object_header_little_to_big_endian(yaffs_ObjectHeader* oh) -++{ -++ oh->type = SWAP32(oh->type); // GCC makes enums 32 bits. -++ oh->parentObjectId = SWAP32(oh->parentObjectId); // int -++ oh->sum__NoLongerUsed = SWAP16(oh->sum__NoLongerUsed); // __u16 - Not used, but done for completeness. -++ // name = skip. Char array. Not swapped. -++ oh->yst_mode = SWAP32(oh->yst_mode); -++#ifdef CONFIG_YAFFS_WINCE // WinCE doesn't implement this, but we need to just in case. -++ // In fact, WinCE would be *THE* place where this would be an issue! -++ oh->notForWinCE[0] = SWAP32(oh->notForWinCE[0]); -++ oh->notForWinCE[1] = SWAP32(oh->notForWinCE[1]); -++ oh->notForWinCE[2] = SWAP32(oh->notForWinCE[2]); -++ oh->notForWinCE[3] = SWAP32(oh->notForWinCE[3]); -++ oh->notForWinCE[4] = SWAP32(oh->notForWinCE[4]); -++#else -++ // Regular POSIX. -++ oh->yst_uid = SWAP32(oh->yst_uid); -++ oh->yst_gid = SWAP32(oh->yst_gid); -++ oh->yst_atime = SWAP32(oh->yst_atime); -++ oh->yst_mtime = SWAP32(oh->yst_mtime); -++ oh->yst_ctime = SWAP32(oh->yst_ctime); -++#endif -++ -++ oh->fileSize = SWAP32(oh->fileSize); // Aiee. An int... signed, at that! -++ oh->equivalentObjectId = SWAP32(oh->equivalentObjectId); -++ // alias - char array. -++ oh->yst_rdev = SWAP32(oh->yst_rdev); -++ -++#ifdef CONFIG_YAFFS_WINCE -++ oh->win_ctime[0] = SWAP32(oh->win_ctime[0]); -++ oh->win_ctime[1] = SWAP32(oh->win_ctime[1]); -++ oh->win_atime[0] = SWAP32(oh->win_atime[0]); -++ oh->win_atime[1] = SWAP32(oh->win_atime[1]); -++ oh->win_mtime[0] = SWAP32(oh->win_mtime[0]); -++ oh->win_mtime[1] = SWAP32(oh->win_mtime[1]); -++ oh->roomToGrow[0] = SWAP32(oh->roomToGrow[0]); -++ oh->roomToGrow[1] = SWAP32(oh->roomToGrow[1]); -++ oh->roomToGrow[2] = SWAP32(oh->roomToGrow[2]); -++ oh->roomToGrow[3] = SWAP32(oh->roomToGrow[3]); -++ oh->roomToGrow[4] = SWAP32(oh->roomToGrow[4]); -++ oh->roomToGrow[5] = SWAP32(oh->roomToGrow[5]); -++#else -++ oh->roomToGrow[0] = SWAP32(oh->roomToGrow[0]); -++ oh->roomToGrow[1] = SWAP32(oh->roomToGrow[1]); -++ oh->roomToGrow[2] = SWAP32(oh->roomToGrow[2]); -++ oh->roomToGrow[3] = SWAP32(oh->roomToGrow[3]); -++ oh->roomToGrow[4] = SWAP32(oh->roomToGrow[4]); -++ oh->roomToGrow[5] = SWAP32(oh->roomToGrow[5]); -++ oh->roomToGrow[6] = SWAP32(oh->roomToGrow[6]); -++ oh->roomToGrow[7] = SWAP32(oh->roomToGrow[7]); -++ oh->roomToGrow[8] = SWAP32(oh->roomToGrow[8]); -++ oh->roomToGrow[9] = SWAP32(oh->roomToGrow[9]); -++ oh->roomToGrow[10] = SWAP32(oh->roomToGrow[10]); -++ oh->roomToGrow[11] = SWAP32(oh->roomToGrow[11]); -++#endif -++} -++#endif -++ -++static int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias) -++{ -++ __u8 bytes[MAX_CHUNKSIZE]; -++ -++ -++ yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)bytes; -++ -++ memset(bytes,0xff,chunkSize); -++ -++ oh->type = t; -++ -++ oh->parentObjectId = parent; -++ -++ strncpy(oh->name,name,YAFFS_MAX_NAME_LENGTH); -++ -++ -++ if(t != YAFFS_OBJECT_TYPE_HARDLINK) -++ { -++ oh->yst_mode = s->st_mode; -++ oh->yst_uid = s->st_uid; -++// NCB 12/9/02 oh->yst_gid = s->yst_uid; -++ oh->yst_gid = s->st_gid; -++ oh->yst_atime = s->st_atime; -++ oh->yst_mtime = s->st_mtime; -++ oh->yst_ctime = s->st_ctime; -++ oh->yst_rdev = s->st_rdev; -++ } -++ -++ if(t == YAFFS_OBJECT_TYPE_FILE) -++ { -++ oh->fileSize = s->st_size; -++ } -++ -++ if(t == YAFFS_OBJECT_TYPE_HARDLINK) -++ { -++ oh->equivalentObjectId = equivalentObj; -++ } -++ -++ if(t == YAFFS_OBJECT_TYPE_SYMLINK) -++ { -++ strncpy(oh->alias,alias,YAFFS_MAX_ALIAS_LENGTH); -++ } -++ -++/* KSI: FUBAR. Left for a leter time. */ -++#if 0 -++ if (convert_endian) -++ { -++ object_header_little_to_big_endian(oh); -++ } -++#endif -++ -++ return write_chunk(bytes,objId,0,0xffff); -++ -++} -++ -++ -++static int process_directory(int parent, const char *path) -++{ -++ -++ DIR *dir; -++ struct dirent *entry; -++ -++ nDirectories++; -++ -++ dir = opendir(path); -++ -++ if(dir) -++ { -++ while((entry = readdir(dir)) != NULL) -++ { -++ -++ /* Ignore . and .. */ -++ if(strcmp(entry->d_name,".") && -++ strcmp(entry->d_name,"..")) -++ { -++ char full_name[500]; -++ struct stat stats; -++ int equivalentObj; -++ int newObj; -++ -++ sprintf(full_name,"%s/%s",path,entry->d_name); -++ -++ lstat(full_name,&stats); -++ -++ if(S_ISLNK(stats.st_mode) || -++ S_ISREG(stats.st_mode) || -++ S_ISDIR(stats.st_mode) || -++ S_ISFIFO(stats.st_mode) || -++ S_ISBLK(stats.st_mode) || -++ S_ISCHR(stats.st_mode) || -++ S_ISSOCK(stats.st_mode)) -++ { -++ -++ newObj = obj_id++; -++ nObjects++; -++ -++ printf("Object %d, %s is a ",newObj,full_name); -++ -++ /* We're going to create an object for it */ -++ if((equivalentObj = find_obj_in_list(stats.st_dev, stats.st_ino)) > 0) -++ { -++ /* we need to make a hard link */ -++ printf("hard link to object %d\n",equivalentObj); -++ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_HARDLINK, &stats, parent, entry->d_name, equivalentObj, NULL); -++ } -++ else -++ { -++ -++ add_obj_to_list(stats.st_dev,stats.st_ino,newObj); -++ -++ if(S_ISLNK(stats.st_mode)) -++ { -++ -++ char symname[500]; -++ -++ memset(symname,0, sizeof(symname)); -++ -++ readlink(full_name,symname,sizeof(symname) -1); -++ -++ printf("symlink to \"%s\"\n",symname); -++ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname); -++ -++ } -++ else if(S_ISREG(stats.st_mode)) -++ { -++ printf("file, "); -++ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL); -++ -++ if(error >= 0) -++ { -++ int h; -++ __u8 bytes[MAX_CHUNKSIZE]; -++ int nBytes; -++ int chunk = 0; -++ -++ h = open(full_name,O_RDONLY); -++ if(h >= 0) -++ { -++ memset(bytes,0xff,chunkSize); -++ while((nBytes = read(h,bytes,chunkSize)) > 0) -++ { -++ chunk++; -++ write_chunk(bytes,newObj,chunk,nBytes); -++ memset(bytes,0xff,chunkSize); -++ } -++ if(nBytes < 0) -++ error = nBytes; -++ -++ printf("%d data chunks written\n",chunk); -++ close(h); -++ } -++ else -++ { -++ perror("Error opening file"); -++ } -++ -++ } -++ -++ } -++ else if(S_ISSOCK(stats.st_mode)) -++ { -++ printf("socket\n"); -++ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); -++ } -++ else if(S_ISFIFO(stats.st_mode)) -++ { -++ printf("fifo\n"); -++ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); -++ } -++ else if(S_ISCHR(stats.st_mode)) -++ { -++ printf("character device\n"); -++ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); -++ } -++ else if(S_ISBLK(stats.st_mode)) -++ { -++ printf("block device\n"); -++ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); -++ } -++ else if(S_ISDIR(stats.st_mode)) -++ { -++ printf("directory\n"); -++ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL); -++// NCB modified 10/9/2001 process_directory(1,full_name); -++ process_directory(newObj,full_name); -++ } -++ } -++ } -++ else -++ { -++ printf(" we don't handle this type\n"); -++ } -++ } -++ } -++ /* KSI: -++ * Who is supposed to close those open directories in this -++ * recursive function, lord Byron? Stock "ulimit -n" is 1024 -++ * and e.g. stock Fedora /etc directory has more that 1024 -++ * directories... -++ */ -++ closedir(dir); -++ } -++ -++ return 0; -++ -++} -++ -++void usage(void) -++{ -++ /* ECC for oob should conform with CONFIG_YAFFS_ECC_XX when building linux kernel, but ecc -++ for oob isn't required when using BCH ECC, as oob will be corrected together with data -++ when using BCH ECC. */ -++#if defined(CONFIG_YAFFS_ECC_RS) -++ printf("Reed-solomn ECC will be used for checking 16 bytes for yaffs2 information in oob area.\n" -++ "so, CONFIG_YAFFS_ECC_RS should be selected when building linux kernel.\n"); -++#elif defined(CONFIG_YAFFS_ECC_HAMMING) -++ printf("Hamming ECC will be used for checking 16 bytes for yaffs2 information in oob area.\n" -++ "so, CONFIG_YAFFS_ECC_HAMMING should be selected when building linux kernel.\n"); -++#endif -++ -++ printf("usage: mkyaffs2image layout# dir image_file [convert]\n"); -++ printf("\n" -++ " layout# NAND OOB layout:\n" -++ " 0 - nand_oob_raw, no used, \n" -++ " 1 - nand_oob_64, for 2KB pagesize, \n" -++ " 2 - nand_oob_128, for 2KB pagesize using multiple planes or 4KB pagesize,\n" -++ " 3 - nand_oob_256, for 4KB pagesize using multiple planes\n"); -++ printf(" dir the directory tree to be converted\n"); -++ printf(" image_file the output file to hold the image\n"); -++ printf(" 'convert' make a big-endian img on a little-endian machine. BROKEN !\n"); -++ printf("\n Example:\n" -++ " mkyaffs2image 1 /nfsroot/root26 root26.yaffs2 \n" -++); -++ -++ exit(1); -++} -++ -++int main(int argc, char *argv[]) -++{ -++ struct stat stats; -++ int i; -++ -++ printf("mkyaffs2image: image building tool for YAFFS2 built "__DATE__"\n"); -++ -++ if ((argc < 4) || (sscanf(argv[1], "%u", &layout_no) != 1)) -++ { -++ usage(); -++ } -++ -++ switch (layout_no) { -++ case 0: -++ printf("Warning: it isn't used by JZSOC!\n"); -++ break; -++ case 1: -++ chunkSize = 2048; -++ spareSize = 64; -++ break; -++ case 2: -++ chunkSize = 4096; -++ spareSize = 128; -++ break; -++ case 3: -++ chunkSize = 8192; -++ spareSize = 256; -++ break; -++ default: -++ usage(); -++ } -++ -++ i = 0; -++ -++ while (oob_layout[i].useecc != -1) -++ i++; -++ -++ if (layout_no >= i) -++ usage(); -++ -++ if ((argc == 5) && (!strncmp(argv[4], "convert", strlen("convert")))) -++ { -++ /* KSI: Broken as of now. TBD. Fail. */ -++ usage(); -++ convert_endian = 1; -++ } -++ -++ if(stat(argv[2],&stats) < 0) -++ { -++ printf("Could not stat %s\n",argv[2]); -++ exit(1); -++ } -++ -++ if(!S_ISDIR(stats.st_mode)) -++ { -++ printf(" %s is not a directory\n",argv[2]); -++ exit(1); -++ } -++ -++ outFile = open(argv[3],O_CREAT | O_TRUNC | O_WRONLY, S_IREAD | S_IWRITE); -++ -++ -++ if(outFile < 0) -++ { -++ printf("Could not open output file %s\n",argv[3]); -++ exit(1); -++ } -++ -++ printf("Processing directory %s into image file %s\n",argv[2],argv[3]); -++ error = write_object_header(1, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, 1,"", -1, NULL); -++ -++ if(error) -++ error = process_directory(YAFFS_OBJECTID_ROOT,argv[2]); -++ -++ close(outFile); -++ -++ if(error < 0) -++ { -++ perror("operation incomplete"); -++ exit(1); -++ } -++ else -++ { -++ printf("Operation complete.\n" -++ "%d objects in %d directories\n" -++ "%d NAND pages\n",nObjects, nDirectories, nPages); -++ } -++ -++ close(outFile); -++ -++ exit(0); -++} -++ -+diff -urN linux-2.6.24.7/fs/yaffs2/utils/mkyaffsimage.c linux-2.6.24.7.new/fs/yaffs2/utils/mkyaffsimage.c -+--- linux-2.6.24.7/fs/yaffs2/utils/mkyaffsimage.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7.new/fs/yaffs2/utils/mkyaffsimage.c 2009-04-21 15:01:02.000000000 +0200 -+@@ -0,0 +1,593 @@ -++/* -++ * YAFFS: Yet another FFS. A NAND-flash specific file system. -++ * -++ * makeyaffsimage.c -++ * -++ * Makes a YAFFS file system image that can be used to load up a file system. -++ * -++ * Copyright (C) 2002 Aleph One Ltd. -++ * for Toby Churchill Ltd and Brightstar Engineering -++ * -++ * Created by Charles Manning -++ * -++ * This program is free software; you can redistribute it and/or modify -++ * it under the terms of the GNU General Public License version 2 as -++ * published by the Free Software Foundation. -++ * -++ * -++ * Nick Bane modifications flagged NCB -++ * -++ * Endian handling patches by James Ng. -++ * -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include "yaffs_ecc.h" -++#include "yaffs_guts.h" -++ -++ -++#define MAX_OBJECTS 10000 -++ -++const char * mkyaffsimage_c_version = "$Id: mkyaffsimage.c,v 1.1.1.1 2008-03-28 04:29:21 jlwei Exp $"; -++ -++ -++typedef struct -++{ -++ dev_t dev; -++ ino_t ino; -++ int obj; -++} objItem; -++ -++ -++static objItem obj_list[MAX_OBJECTS]; -++static int n_obj = 0; -++static int obj_id = YAFFS_NOBJECT_BUCKETS + 1; -++ -++static int nObjects, nDirectories, nPages; -++ -++static int outFile; -++ -++static int error; -++ -++static int convert_endian = 0; -++ -++static int obj_compare(const void *a, const void * b) -++{ -++ objItem *oa, *ob; -++ -++ oa = (objItem *)a; -++ ob = (objItem *)b; -++ -++ if(oa->dev < ob->dev) return -1; -++ if(oa->dev > ob->dev) return 1; -++ if(oa->ino < ob->ino) return -1; -++ if(oa->ino > ob->ino) return 1; -++ -++ return 0; -++} -++ -++ -++static void add_obj_to_list(dev_t dev, ino_t ino, int obj) -++{ -++ if(n_obj < MAX_OBJECTS) -++ { -++ obj_list[n_obj].dev = dev; -++ obj_list[n_obj].ino = ino; -++ obj_list[n_obj].obj = obj; -++ n_obj++; -++ qsort(obj_list,n_obj,sizeof(objItem),obj_compare); -++ -++ } -++ else -++ { -++ // oops! not enough space in the object array -++ fprintf(stderr,"Not enough space in object array\n"); -++ exit(2); -++ } -++} -++ -++ -++static int find_obj_in_list(dev_t dev, ino_t ino) -++{ -++ objItem *i = NULL; -++ objItem test; -++ -++ test.dev = dev; -++ test.ino = ino; -++ -++ if(n_obj > 0) -++ { -++ i = bsearch(&test,obj_list,n_obj,sizeof(objItem),obj_compare); -++ } -++ -++ if(i) -++ { -++ return i->obj; -++ } -++ return -1; -++} -++ -++// NCB added 10/9/2002 -++static __u16 yaffs_CalcNameSum(const char *name) -++{ -++ __u16 sum = 0; -++ __u16 i = 1; -++ -++ __u8 *bname = (__u8 *)name; -++ -++ while (*bname) -++ { -++ sum += (*bname) * i; -++ i++; -++ bname++; -++ } -++ return sum; -++} -++ -++ -++static void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare) -++{ -++ yaffs_ECCCalculate(data , spare->ecc1); -++ yaffs_ECCCalculate(&data[256] , spare->ecc2); -++} -++ -++static void yaffs_CalcTagsECC(yaffs_Tags *tags) -++{ -++ // Todo don't do anything yet. Need to calculate ecc -++ unsigned char *b = ((yaffs_TagsUnion *)tags)->asBytes; -++ unsigned i,j; -++ unsigned ecc = 0; -++ unsigned bit = 0; -++ -++ // Clear ECC fields -++ if (!convert_endian) -++ { -++ tags->ecc = 0; -++ } -++ else -++ { -++ // Because we're in "munged tag" mode, we have to clear it manually -++ b[6] &= 0xC0; -++ b[7] &= 0x03; -++ } -++ -++ for(i = 0; i < 8; i++) -++ { -++// NCB modified 20-9-02 for(j = 1; j &0x7f; j<<=1) -++ for(j = 1; j &0xff; j<<=1) -++ { -++ bit++; -++ if(b[i] & j) -++ { -++ ecc ^= bit; -++ } -++ } -++ } -++ -++ // Write out ECC -++ if (!convert_endian) -++ { -++ tags->ecc = ecc; -++ } -++ else -++ { -++ // We have to munge the ECC again. -++ b[6] |= ((ecc >> 6) & 0x3F); -++ b[7] |= ((ecc & 0x3F) << 2); -++ } -++} -++static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr) -++{ -++ yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr; -++ -++ //yaffs_CalcTagsECC(tagsPtr); -++ -++ sparePtr->tagByte0 = tu->asBytes[0]; -++ sparePtr->tagByte1 = tu->asBytes[1]; -++ sparePtr->tagByte2 = tu->asBytes[2]; -++ sparePtr->tagByte3 = tu->asBytes[3]; -++ sparePtr->tagByte4 = tu->asBytes[4]; -++ sparePtr->tagByte5 = tu->asBytes[5]; -++ sparePtr->tagByte6 = tu->asBytes[6]; -++ sparePtr->tagByte7 = tu->asBytes[7]; -++} -++ -++/* This little function converts a little endian tag to a big endian tag. -++ * NOTE: The tag is not usable after this other than calculating the CRC -++ * with. -++ */ -++static void little_to_big_endian(yaffs_Tags *tagsPtr) -++{ -++ yaffs_TagsUnion * tags = (yaffs_TagsUnion* )tagsPtr; // Work in bytes. -++ yaffs_TagsUnion temp; -++ -++ memset(&temp, 0, sizeof(temp)); -++ // Ick, I hate magic numbers. -++ temp.asBytes[0] = ((tags->asBytes[2] & 0x0F) << 4) | ((tags->asBytes[1] & 0xF0) >> 4); -++ temp.asBytes[1] = ((tags->asBytes[1] & 0x0F) << 4) | ((tags->asBytes[0] & 0xF0) >> 4); -++ temp.asBytes[2] = ((tags->asBytes[0] & 0x0F) << 4) | ((tags->asBytes[2] & 0x30) >> 2) | ((tags->asBytes[3] & 0xC0) >> 6); -++ temp.asBytes[3] = ((tags->asBytes[3] & 0x3F) << 2) | ((tags->asBytes[2] & 0xC0) >> 6); -++ temp.asBytes[4] = ((tags->asBytes[6] & 0x03) << 6) | ((tags->asBytes[5] & 0xFC) >> 2); -++ temp.asBytes[5] = ((tags->asBytes[5] & 0x03) << 6) | ((tags->asBytes[4] & 0xFC) >> 2); -++ temp.asBytes[6] = ((tags->asBytes[4] & 0x03) << 6) | (tags->asBytes[7] & 0x3F); -++ temp.asBytes[7] = (tags->asBytes[6] & 0xFC) | ((tags->asBytes[7] & 0xC0) >> 6); -++ -++ // Now copy it back. -++ tags->asBytes[0] = temp.asBytes[0]; -++ tags->asBytes[1] = temp.asBytes[1]; -++ tags->asBytes[2] = temp.asBytes[2]; -++ tags->asBytes[3] = temp.asBytes[3]; -++ tags->asBytes[4] = temp.asBytes[4]; -++ tags->asBytes[5] = temp.asBytes[5]; -++ tags->asBytes[6] = temp.asBytes[6]; -++ tags->asBytes[7] = temp.asBytes[7]; -++} -++ -++static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes) -++{ -++ yaffs_Tags t; -++ yaffs_Spare s; -++ -++ error = write(outFile,data,512); -++ if(error < 0) return error; -++ -++ memset(&t,0xff,sizeof (yaffs_Tags)); -++ memset(&s,0xff,sizeof (yaffs_Spare)); -++ -++ t.chunkId = chunkId; -++ t.serialNumber = 0; -++ t.byteCount = nBytes; -++ t.objectId = objId; -++ -++ if (convert_endian) -++ { -++ little_to_big_endian(&t); -++ } -++ -++ yaffs_CalcTagsECC(&t); -++ yaffs_LoadTagsIntoSpare(&s,&t); -++ yaffs_CalcECC(data,&s); -++ -++ nPages++; -++ -++ return write(outFile,&s,sizeof(yaffs_Spare)); -++ -++} -++ -++#define SWAP32(x) ((((x) & 0x000000FF) << 24) | \ -++ (((x) & 0x0000FF00) << 8 ) | \ -++ (((x) & 0x00FF0000) >> 8 ) | \ -++ (((x) & 0xFF000000) >> 24)) -++ -++#define SWAP16(x) ((((x) & 0x00FF) << 8) | \ -++ (((x) & 0xFF00) >> 8)) -++ -++// This one is easier, since the types are more standard. No funky shifts here. -++static void object_header_little_to_big_endian(yaffs_ObjectHeader* oh) -++{ -++ oh->type = SWAP32(oh->type); // GCC makes enums 32 bits. -++ oh->parentObjectId = SWAP32(oh->parentObjectId); // int -++ oh->sum__NoLongerUsed = SWAP16(oh->sum__NoLongerUsed); // __u16 - Not used, but done for completeness. -++ // name = skip. Char array. Not swapped. -++ oh->yst_mode = SWAP32(oh->yst_mode); -++#ifdef CONFIG_YAFFS_WINCE // WinCE doesn't implement this, but we need to just in case. -++ // In fact, WinCE would be *THE* place where this would be an issue! -++ oh->notForWinCE[0] = SWAP32(oh->notForWinCE[0]); -++ oh->notForWinCE[1] = SWAP32(oh->notForWinCE[1]); -++ oh->notForWinCE[2] = SWAP32(oh->notForWinCE[2]); -++ oh->notForWinCE[3] = SWAP32(oh->notForWinCE[3]); -++ oh->notForWinCE[4] = SWAP32(oh->notForWinCE[4]); -++#else -++ // Regular POSIX. -++ oh->yst_uid = SWAP32(oh->yst_uid); -++ oh->yst_gid = SWAP32(oh->yst_gid); -++ oh->yst_atime = SWAP32(oh->yst_atime); -++ oh->yst_mtime = SWAP32(oh->yst_mtime); -++ oh->yst_ctime = SWAP32(oh->yst_ctime); -++#endif -++ -++ oh->fileSize = SWAP32(oh->fileSize); // Aiee. An int... signed, at that! -++ oh->equivalentObjectId = SWAP32(oh->equivalentObjectId); -++ // alias - char array. -++ oh->yst_rdev = SWAP32(oh->yst_rdev); -++ -++#ifdef CONFIG_YAFFS_WINCE -++ oh->win_ctime[0] = SWAP32(oh->win_ctime[0]); -++ oh->win_ctime[1] = SWAP32(oh->win_ctime[1]); -++ oh->win_atime[0] = SWAP32(oh->win_atime[0]); -++ oh->win_atime[1] = SWAP32(oh->win_atime[1]); -++ oh->win_mtime[0] = SWAP32(oh->win_mtime[0]); -++ oh->win_mtime[1] = SWAP32(oh->win_mtime[1]); -++ oh->roomToGrow[0] = SWAP32(oh->roomToGrow[0]); -++ oh->roomToGrow[1] = SWAP32(oh->roomToGrow[1]); -++ oh->roomToGrow[2] = SWAP32(oh->roomToGrow[2]); -++ oh->roomToGrow[3] = SWAP32(oh->roomToGrow[3]); -++ oh->roomToGrow[4] = SWAP32(oh->roomToGrow[4]); -++ oh->roomToGrow[5] = SWAP32(oh->roomToGrow[5]); -++#else -++ oh->roomToGrow[0] = SWAP32(oh->roomToGrow[0]); -++ oh->roomToGrow[1] = SWAP32(oh->roomToGrow[1]); -++ oh->roomToGrow[2] = SWAP32(oh->roomToGrow[2]); -++ oh->roomToGrow[3] = SWAP32(oh->roomToGrow[3]); -++ oh->roomToGrow[4] = SWAP32(oh->roomToGrow[4]); -++ oh->roomToGrow[5] = SWAP32(oh->roomToGrow[5]); -++ oh->roomToGrow[6] = SWAP32(oh->roomToGrow[6]); -++ oh->roomToGrow[7] = SWAP32(oh->roomToGrow[7]); -++ oh->roomToGrow[8] = SWAP32(oh->roomToGrow[8]); -++ oh->roomToGrow[9] = SWAP32(oh->roomToGrow[9]); -++ oh->roomToGrow[10] = SWAP32(oh->roomToGrow[10]); -++ oh->roomToGrow[11] = SWAP32(oh->roomToGrow[11]); -++#endif -++} -++ -++static int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias) -++{ -++ __u8 bytes[512]; -++ -++ -++ yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)bytes; -++ -++ memset(bytes,0xff,512); -++ -++ oh->type = t; -++ -++ oh->parentObjectId = parent; -++ -++ strncpy(oh->name,name,YAFFS_MAX_NAME_LENGTH); -++ -++ -++ if(t != YAFFS_OBJECT_TYPE_HARDLINK) -++ { -++ oh->yst_mode = s->st_mode; -++ oh->yst_uid = s->st_uid; -++// NCB 12/9/02 oh->yst_gid = s->yst_uid; -++ oh->yst_gid = s->st_gid; -++ oh->yst_atime = s->st_atime; -++ oh->yst_mtime = s->st_mtime; -++ oh->yst_ctime = s->st_ctime; -++ oh->yst_rdev = s->st_rdev; -++ } -++ -++ if(t == YAFFS_OBJECT_TYPE_FILE) -++ { -++ oh->fileSize = s->st_size; -++ } -++ -++ if(t == YAFFS_OBJECT_TYPE_HARDLINK) -++ { -++ oh->equivalentObjectId = equivalentObj; -++ } -++ -++ if(t == YAFFS_OBJECT_TYPE_SYMLINK) -++ { -++ strncpy(oh->alias,alias,YAFFS_MAX_ALIAS_LENGTH); -++ } -++ -++ if (convert_endian) -++ { -++ object_header_little_to_big_endian(oh); -++ } -++ -++ return write_chunk(bytes,objId,0,0xffff); -++ -++} -++ -++ -++static int process_directory(int parent, const char *path) -++{ -++ -++ DIR *dir; -++ struct dirent *entry; -++ -++ nDirectories++; -++ -++ dir = opendir(path); -++ -++ if(dir) -++ { -++ while((entry = readdir(dir)) != NULL) -++ { -++ -++ /* Ignore . and .. */ -++ if(strcmp(entry->d_name,".") && -++ strcmp(entry->d_name,"..")) -++ { -++ char full_name[500]; -++ struct stat stats; -++ int equivalentObj; -++ int newObj; -++ -++ sprintf(full_name,"%s/%s",path,entry->d_name); -++ -++ lstat(full_name,&stats); -++ -++ if(S_ISLNK(stats.st_mode) || -++ S_ISREG(stats.st_mode) || -++ S_ISDIR(stats.st_mode) || -++ S_ISFIFO(stats.st_mode) || -++ S_ISBLK(stats.st_mode) || -++ S_ISCHR(stats.st_mode) || -++ S_ISSOCK(stats.st_mode)) -++ { -++ -++ newObj = obj_id++; -++ nObjects++; -++ -++ printf("Object %d, %s is a ",newObj,full_name); -++ -++ /* We're going to create an object for it */ -++ if((equivalentObj = find_obj_in_list(stats.st_dev, stats.st_ino)) > 0) -++ { -++ /* we need to make a hard link */ -++ printf("hard link to object %d\n",equivalentObj); -++ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_HARDLINK, &stats, parent, entry->d_name, equivalentObj, NULL); -++ } -++ else -++ { -++ -++ add_obj_to_list(stats.st_dev,stats.st_ino,newObj); -++ -++ if(S_ISLNK(stats.st_mode)) -++ { -++ -++ char symname[500]; -++ -++ memset(symname,0, sizeof(symname)); -++ -++ readlink(full_name,symname,sizeof(symname) -1); -++ -++ printf("symlink to \"%s\"\n",symname); -++ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname); -++ -++ } -++ else if(S_ISREG(stats.st_mode)) -++ { -++ printf("file, "); -++ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL); -++ -++ if(error >= 0) -++ { -++ int h; -++ __u8 bytes[512]; -++ int nBytes; -++ int chunk = 0; -++ -++ h = open(full_name,O_RDONLY); -++ if(h >= 0) -++ { -++ memset(bytes,0xff,512); -++ while((nBytes = read(h,bytes,512)) > 0) -++ { -++ chunk++; -++ write_chunk(bytes,newObj,chunk,nBytes); -++ memset(bytes,0xff,512); -++ } -++ if(nBytes < 0) -++ error = nBytes; -++ -++ printf("%d data chunks written\n",chunk); -++ } -++ else -++ { -++ perror("Error opening file"); -++ } -++ close(h); -++ -++ } -++ -++ } -++ else if(S_ISSOCK(stats.st_mode)) -++ { -++ printf("socket\n"); -++ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); -++ } -++ else if(S_ISFIFO(stats.st_mode)) -++ { -++ printf("fifo\n"); -++ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); -++ } -++ else if(S_ISCHR(stats.st_mode)) -++ { -++ printf("character device\n"); -++ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); -++ } -++ else if(S_ISBLK(stats.st_mode)) -++ { -++ printf("block device\n"); -++ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); -++ } -++ else if(S_ISDIR(stats.st_mode)) -++ { -++ printf("directory\n"); -++ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL); -++// NCB modified 10/9/2001 process_directory(1,full_name); -++ process_directory(newObj,full_name); -++ } -++ } -++ } -++ else -++ { -++ printf(" we don't handle this type\n"); -++ } -++ } -++ } -++ } -++ -++ return 0; -++ -++} -++ -++ -++int main(int argc, char *argv[]) -++{ -++ struct stat stats; -++ -++ printf("mkyaffsimage: image building tool for YAFFS built "__DATE__"\n"); -++ -++ if(argc < 3) -++ { -++ printf("usage: mkyaffsimage dir image_file [convert]\n"); -++ printf(" dir the directory tree to be converted\n"); -++ printf(" image_file the output file to hold the image\n"); -++ printf(" 'convert' produce a big-endian image from a little-endian machine\n"); -++ exit(1); -++ } -++ -++ if ((argc == 4) && (!strncmp(argv[3], "convert", strlen("convert")))) -++ { -++ convert_endian = 1; -++ } -++ -++ if(stat(argv[1],&stats) < 0) -++ { -++ printf("Could not stat %s\n",argv[1]); -++ exit(1); -++ } -++ -++ if(!S_ISDIR(stats.st_mode)) -++ { -++ printf(" %s is not a directory\n",argv[1]); -++ exit(1); -++ } -++ -++ outFile = open(argv[2],O_CREAT | O_TRUNC | O_WRONLY, S_IREAD | S_IWRITE); -++ -++ -++ if(outFile < 0) -++ { -++ printf("Could not open output file %s\n",argv[2]); -++ exit(1); -++ } -++ -++ printf("Processing directory %s into image file %s\n",argv[1],argv[2]); -++ error = write_object_header(1, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, 1,"", -1, NULL); -++ if(error) -++ error = process_directory(YAFFS_OBJECTID_ROOT,argv[1]); -++ -++ close(outFile); -++ -++ if(error < 0) -++ { -++ perror("operation incomplete"); -++ exit(1); -++ } -++ else -++ { -++ printf("Operation complete.\n" -++ "%d objects in %d directories\n" -++ "%d NAND pages\n",nObjects, nDirectories, nPages); -++ } -++ -++ close(outFile); -++ -++ exit(0); -++} -++ -+diff -urN linux-2.6.24.7/fs/yaffs2/utils/ssfdc_rs_ecc.c linux-2.6.24.7.new/fs/yaffs2/utils/ssfdc_rs_ecc.c -+--- linux-2.6.24.7/fs/yaffs2/utils/ssfdc_rs_ecc.c 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7.new/fs/yaffs2/utils/ssfdc_rs_ecc.c 2009-04-21 15:01:02.000000000 +0200 -+@@ -0,0 +1,180 @@ -++/* Reed-Solomon decoder -++ * Copyright 2002 Phil Karn, KA9Q -++ * May be used under the terms of the GNU Lesser General Public License (LGPL) -++ */ -++#include "ssfdc_rs_ecc.h" -++ -++#include -++ -++struct CONV_DATA { -++ unsigned char shift0; -++ unsigned char mask0; -++ unsigned char mask1; -++ unsigned char merge_shift; -++} ConvData [8]= { -++ {0x0, 0xff, 0x01, 0x8}, /* 0 */ -++ {0x1, 0x7f, 0x03, 0x7}, /* 1 */ -++ {0x2, 0x3f, 0x07, 0x6}, /* 2 */ -++ {0x3, 0x1f, 0x0f, 0x5}, /* 3 */ -++ {0x4, 0x0f, 0x1f, 0x4}, /* 4 */ -++ {0x5, 0x07, 0x3f, 0x3}, /* 5 */ -++ {0x6, 0x03, 0x7f, 0x2}, /* 6 */ -++ {0x7, 0x01, 0xff, 0x1}, /* 7 */ -++}; -++ -++static void kfree(void *ptr) -++{ -++// return 0; -++} -++ -++static int modnn(struct rs *rs,int x) -++{ -++ while (x >= rs->nn) { -++ x -= rs->nn; -++ x = (x >> rs->mm) + (x & rs->nn); -++ } -++ return x; -++} -++ -++void encode_rs(void *p,data_t *data, unsigned short *bb) -++{ -++ struct rs *rs = (struct rs *)p; -++ int i, j; -++ data_t feedback; -++ -++ memset(bb,0,(rs->nroots)*sizeof(unsigned short)); -++ -++ for(i=0;i<(rs->nn)-(rs->nroots)-(rs->pad);i++){ -++ -++ feedback = (rs->index_of)[data[i] ^ bb[0]]; -++ if(feedback != ((rs->nn))){ -++ for(j=1;j<(rs->nroots);j++) -++ bb[j] ^= (rs->alpha_to)[modnn(rs,feedback + (rs->genpoly)[(rs->nroots)-j])]; -++ } -++ -++ memmove(&bb[0],&bb[1],sizeof(unsigned short)*((rs->nroots)-1)); -++ -++ if(feedback != ((rs->nn))) { -++ bb[(rs->nroots)-1] = (rs->alpha_to)[modnn(rs,feedback + (rs->genpoly)[0])]; -++ } -++ else -++ bb[(rs->nroots)-1] = 0; -++ } -++ -++} -++ -++void free_rs_int(void *p) -++{ -++ struct rs *rs = (struct rs *)p; -++ -++ free(rs->alpha_to); -++ free(rs->index_of); -++ free(rs->genpoly); -++ free(rs); -++} -++ -++/* -++ * init_rs_int - Initialize a Reed-Solomon codec -++ * @symsize: symbol size -++ * @gfpoly: Field generator polynomial coefficients -++ * @fcr: first root of RS code generator polynomial, index form -++ * @prim: primitive element to generate polynomial roots -++ * @nroots: RS code generator polynomial degree (number of roots) -++ */ -++struct rs *init_rs_int(int symsize,int gfpoly,int fcr,int prim,int nroots,int pad) -++{ -++ struct rs *rs; -++#if 0 -++ static unsigned int rs0[64]={0}; -++ static data_t alpha0[512]={0}; -++ static data_t index0[512]={0}; -++ static data_t genepoly0[9]={0}; -++#endif -++ int i, j, sr,root,iprim; -++ -++ rs = ((void *)0); -++ if(symsize < 0 || symsize > 8*sizeof(data_t)){ -++ goto done; -++ } -++ -++ if(fcr < 0 || fcr >= (1<= (1<= (1<= ((1<mm = symsize; -++ rs->nn = (1<pad = pad; -++ rs->alpha_to = (data_t *)malloc(sizeof(data_t)*(rs->nn+1)); -++// rs->alpha_to = alpha0; -++ if(rs->alpha_to == ((void *)0)){ -++ kfree(rs); -++ rs = ((void *)0); -++ goto done; -++ } -++ rs->index_of = (data_t *)malloc(sizeof(data_t)*(rs->nn+1)); -++// rs->index_of = index0; -++ if(rs->index_of == ((void *)0)){ -++ kfree(rs->alpha_to); -++ kfree(rs); -++ rs = ((void *)0); -++ goto done; -++ } -++ rs->index_of[0] = ((rs->nn)); -++ rs->alpha_to[((rs->nn))] = 0; -++ sr = 1; -++ for(i=0;inn;i++){ -++ rs->index_of[sr] = i; -++ rs->alpha_to[i] = sr; -++ sr <<= 1; -++ if(sr & (1<nn; -++ } -++ if(sr != 1){ -++ kfree(rs->alpha_to); -++ kfree(rs->index_of); -++ kfree(rs); -++ rs = ((void *)0); -++ goto done; -++ } -++ rs->genpoly = (data_t *)malloc(sizeof(data_t)*(nroots+1)); -++// rs->genpoly = genepoly0; -++ if(rs->genpoly == ((void *)0)){ -++ kfree(rs->alpha_to); -++ kfree(rs->index_of); -++ kfree(rs); -++ rs = ((void *)0); -++ goto done; -++ } -++ rs->fcr = fcr; -++ rs->prim = prim; -++ rs->nroots = nroots; -++ for(iprim=1;(iprim % prim) != 0;iprim += rs->nn) -++ ; -++ rs->iprim = iprim / prim; -++ rs->genpoly[0] = 1; -++ for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) { -++ rs->genpoly[i+1] = 1; -++ for (j = i; j > 0; j--){ -++ if (rs->genpoly[j] != 0) -++ rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)]; -++ else -++ rs->genpoly[j] = rs->genpoly[j-1]; -++ } -++ rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)]; -++ } -++ for (i = 0; i <= nroots; i++) -++ rs->genpoly[i] = rs->index_of[rs->genpoly[i]]; -++ done:; -++ return rs; -++} -++ -+diff -urN linux-2.6.24.7/fs/yaffs2/utils/ssfdc_rs_ecc.h linux-2.6.24.7.new/fs/yaffs2/utils/ssfdc_rs_ecc.h -+--- linux-2.6.24.7/fs/yaffs2/utils/ssfdc_rs_ecc.h 1970-01-01 01:00:00.000000000 +0100 -++++ linux-2.6.24.7.new/fs/yaffs2/utils/ssfdc_rs_ecc.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -0,0 +1,29 @@ -++#ifndef __SSFDC_RS_ECC_H__ -++#define __SSFDC_RS_ECC_H__ -++ -++/* Stuff common to all the general-purpose Reed-Solomon codecs -++ * Copyright 2004 Phil Karn, KA9Q -++ * May be used under the terms of the GNU Lesser General Public License (LGPL) -++ */ -++ -++/* Reed-Solomon codec control block */ -++typedef unsigned char data_t; -++ -++struct rs { -++ int mm; /* Bits per symbol */ -++ int nn; /* Symbols per block (= (1<nErasedBlocks - dev->nReservedBlocks; -+- -++ -+ T(YAFFS_TRACE_CHECKPOINT, -+ (TSTR("checkpt blocks available = %d" TENDSTR), -+ blocksAvailable)); -+- -+- -++ -++ -+ return (blocksAvailable <= 0) ? 0 : 1; -+ } -+ -+ -++ -+ static int yaffs_CheckpointErase(yaffs_Device *dev) -+ { -+- -++ -+ int i; -++ -+ -+- -+- if(!dev->eraseBlockInNAND) -++ if(!dev->eraseBlockInNAND) -+ return 0; -+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("checking blocks %d to %d"TENDSTR), -+ dev->internalStartBlock,dev->internalEndBlock)); -+- -++ -+ for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) { -+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i); -+ if(bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT){ -+@@ -58,9 +59,9 @@ -+ } -+ } -+ } -+- -++ -+ dev->blocksInCheckpoint = 0; -+- -++ -+ return 1; -+ } -+ -+@@ -72,11 +73,11 @@ -+ T(YAFFS_TRACE_CHECKPOINT, -+ (TSTR("allocating checkpt block: erased %d reserved %d avail %d next %d "TENDSTR), -+ dev->nErasedBlocks,dev->nReservedBlocks,blocksAvailable,dev->checkpointNextBlock)); -+- -++ -+ if(dev->checkpointNextBlock >= 0 && -+ dev->checkpointNextBlock <= dev->internalEndBlock && -+ blocksAvailable > 0){ -+- -++ -+ for(i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++){ -+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i); -+ if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY){ -+@@ -88,7 +89,7 @@ -+ } -+ } -+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("out of checkpt blocks"TENDSTR))); -+- -++ -+ dev->checkpointNextBlock = -1; -+ dev->checkpointCurrentBlock = -1; -+ } -+@@ -97,19 +98,19 @@ -+ { -+ int i; -+ yaffs_ExtendedTags tags; -+- -++ -+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("find next checkpt block: start: blocks %d next %d" TENDSTR), -+ dev->blocksInCheckpoint, dev->checkpointNextBlock)); -+- -+- if(dev->blocksInCheckpoint < dev->checkpointMaxBlocks) -++ -++ if(dev->blocksInCheckpoint < dev->checkpointMaxBlocks) -+ for(i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++){ -+ int chunk = i * dev->nChunksPerBlock; -+ int realignedChunk = chunk - dev->chunkOffset; -+ -+ dev->readChunkWithTagsFromNAND(dev,realignedChunk,NULL,&tags); -+- T(YAFFS_TRACE_CHECKPOINT,(TSTR("find next checkpt block: search: block %d oid %d seq %d eccr %d" TENDSTR), -++ T(YAFFS_TRACE_CHECKPOINT,(TSTR("find next checkpt block: search: block %d oid %d seq %d eccr %d" TENDSTR), -+ i, tags.objectId,tags.sequenceNumber,tags.eccResult)); -+- -++ -+ if(tags.sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA){ -+ /* Right kind of block */ -+ dev->checkpointNextBlock = tags.objectId; -+@@ -130,7 +131,7 @@ -+ -+ int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting) -+ { -+- -++ -+ /* Got the functions we need? */ -+ if (!dev->writeChunkWithTagsToNAND || -+ !dev->readChunkWithTagsFromNAND || -+@@ -140,31 +141,29 @@ -+ -+ if(forWriting && !yaffs_CheckpointSpaceOk(dev)) -+ return 0; -+- -++ -+ if(!dev->checkpointBuffer) -+ dev->checkpointBuffer = YMALLOC_DMA(dev->nDataBytesPerChunk); -+ if(!dev->checkpointBuffer) -+ return 0; -+ -+- -++ -+ dev->checkpointPageSequence = 0; -+- -++ -+ dev->checkpointOpenForWrite = forWriting; -+- -++ -+ dev->checkpointByteCount = 0; -+- dev->checkpointSum = 0; -+- dev->checkpointXor = 0; -+ dev->checkpointCurrentBlock = -1; -+ dev->checkpointCurrentChunk = -1; -+ dev->checkpointNextBlock = dev->internalStartBlock; -+- -++ -+ /* Erase all the blocks in the checkpoint area */ -+ if(forWriting){ -+ memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk); -+ dev->checkpointByteOffset = 0; -+ return yaffs_CheckpointErase(dev); -+- -+- -++ -++ -+ } else { -+ int i; -+ /* Set to a value that will kick off a read */ -+@@ -177,15 +176,7 @@ -+ for(i = 0; i < dev->checkpointMaxBlocks; i++) -+ dev->checkpointBlockList[i] = -1; -+ } -+- -+- return 1; -+-} -+- -+-int yaffs_GetCheckpointSum(yaffs_Device *dev, __u32 *sum) -+-{ -+- __u32 compositeSum; -+- compositeSum = (dev->checkpointSum << 8) | (dev->checkpointXor & 0xFF); -+- *sum = compositeSum; -++ -+ return 1; -+ } -+ -+@@ -196,15 +187,15 @@ -+ int realignedChunk; -+ -+ yaffs_ExtendedTags tags; -+- -++ -+ if(dev->checkpointCurrentBlock < 0){ -+ yaffs_CheckpointFindNextErasedBlock(dev); -+ dev->checkpointCurrentChunk = 0; -+ } -+- -++ -+ if(dev->checkpointCurrentBlock < 0) -+ return 0; -+- -++ -+ tags.chunkDeleted = 0; -+ tags.objectId = dev->checkpointNextBlock; /* Hint to next place to look */ -+ tags.chunkId = dev->checkpointPageSequence + 1; -+@@ -217,25 +208,25 @@ -+ bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT; -+ dev->blocksInCheckpoint++; -+ } -+- -++ -+ chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + dev->checkpointCurrentChunk; -+ -+- -++ -+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint wite buffer nand %d(%d:%d) objid %d chId %d" TENDSTR), -+- chunk, dev->checkpointCurrentBlock, dev->checkpointCurrentChunk,tags.objectId,tags.chunkId)); -+- -++ chunk, dev->checkpointCurrentBlock, dev->checkpointCurrentChunk,tags.objectId,tags.chunkId)); -++ -+ realignedChunk = chunk - dev->chunkOffset; -+- -++ -+ dev->writeChunkWithTagsToNAND(dev,realignedChunk,dev->checkpointBuffer,&tags); -+ dev->checkpointByteOffset = 0; -+- dev->checkpointPageSequence++; -++ dev->checkpointPageSequence++; -+ dev->checkpointCurrentChunk++; -+ if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock){ -+ dev->checkpointCurrentChunk = 0; -+ dev->checkpointCurrentBlock = -1; -+ } -+ memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk); -+- -++ -+ return 1; -+ } -+ -+@@ -245,37 +236,31 @@ -+ int i=0; -+ int ok = 1; -+ -+- -++ -+ __u8 * dataBytes = (__u8 *)data; -+- -+- -++ -++ -+ -+ if(!dev->checkpointBuffer) -+ return 0; -+ -+- if(!dev->checkpointOpenForWrite) -+- return -1; -+- -+ while(i < nBytes && ok) { -++ -+ -+- -+- -+- dev->checkpointBuffer[dev->checkpointByteOffset] = *dataBytes ; -+- dev->checkpointSum += *dataBytes; -+- dev->checkpointXor ^= *dataBytes; -+- -++ -++ dev->checkpointBuffer[dev->checkpointByteOffset] = *dataBytes ; -+ dev->checkpointByteOffset++; -+ i++; -+ dataBytes++; -+ dev->checkpointByteCount++; -+- -+- -++ -++ -+ if(dev->checkpointByteOffset < 0 || -+- dev->checkpointByteOffset >= dev->nDataBytesPerChunk) -++ dev->checkpointByteOffset >= dev->nDataBytesPerChunk) -+ ok = yaffs_CheckpointFlushBuffer(dev); -+ -+ } -+- -++ -+ return i; -+ } -+ -+@@ -285,44 +270,41 @@ -+ int ok = 1; -+ yaffs_ExtendedTags tags; -+ -+- -++ -+ int chunk; -+ int realignedChunk; -+ -+ __u8 *dataBytes = (__u8 *)data; -+- -++ -+ if(!dev->checkpointBuffer) -+ return 0; -+ -+- if(dev->checkpointOpenForWrite) -+- return -1; -+- -+ while(i < nBytes && ok) { -+- -+- -++ -++ -+ if(dev->checkpointByteOffset < 0 || -+ dev->checkpointByteOffset >= dev->nDataBytesPerChunk) { -+- -++ -+ if(dev->checkpointCurrentBlock < 0){ -+ yaffs_CheckpointFindNextCheckpointBlock(dev); -+ dev->checkpointCurrentChunk = 0; -+ } -+- -++ -+ if(dev->checkpointCurrentBlock < 0) -+ ok = 0; -+ else { -+- -+- chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + -++ -++ chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + -+ dev->checkpointCurrentChunk; -+ -+ realignedChunk = chunk - dev->chunkOffset; -+ -+ /* read in the next chunk */ -+ /* printf("read checkpoint page %d\n",dev->checkpointPage); */ -+- dev->readChunkWithTagsFromNAND(dev, realignedChunk, -++ dev->readChunkWithTagsFromNAND(dev, realignedChunk, -+ dev->checkpointBuffer, -+ &tags); -+- -++ -+ if(tags.chunkId != (dev->checkpointPageSequence + 1) || -+ tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA) -+ ok = 0; -+@@ -330,30 +312,28 @@ -+ dev->checkpointByteOffset = 0; -+ dev->checkpointPageSequence++; -+ dev->checkpointCurrentChunk++; -+- -++ -+ if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock) -+ dev->checkpointCurrentBlock = -1; -+ } -+ } -+- -++ -+ if(ok){ -+ *dataBytes = dev->checkpointBuffer[dev->checkpointByteOffset]; -+- dev->checkpointSum += *dataBytes; -+- dev->checkpointXor ^= *dataBytes; -+ dev->checkpointByteOffset++; -+ i++; -+ dataBytes++; -+ dev->checkpointByteCount++; -+ } -+ } -+- -++ -+ return i; -+ } -+ -+ int yaffs_CheckpointClose(yaffs_Device *dev) -+ { -+ -+- if(dev->checkpointOpenForWrite){ -++ if(dev->checkpointOpenForWrite){ -+ if(dev->checkpointByteOffset != 0) -+ yaffs_CheckpointFlushBuffer(dev); -+ } else { -+@@ -373,19 +353,19 @@ -+ dev->nFreeChunks -= dev->blocksInCheckpoint * dev->nChunksPerBlock; -+ dev->nErasedBlocks -= dev->blocksInCheckpoint; -+ -+- -++ -+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint byte count %d" TENDSTR), -+ dev->checkpointByteCount)); -+- -++ -+ if(dev->checkpointBuffer){ -+- /* free the buffer */ -++ /* free the buffer */ -+ YFREE(dev->checkpointBuffer); -+ dev->checkpointBuffer = NULL; -+ return 1; -+ } -+ else -+ return 0; -+- -++ -+ } -+ -+ int yaffs_CheckpointInvalidateStream(yaffs_Device *dev) -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_checkptrw.h linux-2.6.24.7.new/fs/yaffs2/yaffs_checkptrw.h -+--- linux-2.6.24.7/fs/yaffs2/yaffs_checkptrw.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_checkptrw.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ /* -+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+@@ -24,8 +24,6 @@ -+ -+ int yaffs_CheckpointRead(yaffs_Device *dev,void *data, int nBytes); -+ -+-int yaffs_GetCheckpointSum(yaffs_Device *dev, __u32 *sum); -+- -+ int yaffs_CheckpointClose(yaffs_Device *dev); -+ -+ int yaffs_CheckpointInvalidateStream(yaffs_Device *dev); -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_ecc.c linux-2.6.24.7.new/fs/yaffs2/yaffs_ecc.c -+--- linux-2.6.24.7/fs/yaffs2/yaffs_ecc.c 2009-04-21 14:57:10.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_ecc.c 2009-04-21 15:01:02.000000000 +0200 -+@@ -14,9 +14,9 @@ -+ /* -+ * This code implements the ECC algorithm used in SmartMedia. -+ * -+- * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. -++ * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. -+ * The two unused bit are set to 1. -+- * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC -++ * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC -+ * blocks are used on a 512-byte NAND page. -+ * -+ */ -+@@ -29,7 +29,7 @@ -+ */ -+ -+ const char *yaffs_ecc_c_version = -+- "$Id: yaffs_ecc.c,v 1.9 2007-02-14 01:09:06 wookey Exp $"; -++ "$Id: yaffs_ecc.c,v 1.2 2008-07-17 23:07:00 lhhuang Exp $"; -+ -+ #include "yportenv.h" -+ -+@@ -83,17 +83,6 @@ -+ return r; -+ } -+ -+-static int yaffs_CountBits32(unsigned x) -+-{ -+- int r = 0; -+- while (x) { -+- if (x & 1) -+- r++; -+- x >>= 1; -+- } -+- return r; -+-} -+- -+ /* Calculate the ECC for a 256-byte block of data */ -+ void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc) -+ { -+@@ -228,8 +217,8 @@ -+ return 1; /* Corrected the error */ -+ } -+ -+- if ((yaffs_CountBits(d0) + -+- yaffs_CountBits(d1) + -++ if ((yaffs_CountBits(d0) + -++ yaffs_CountBits(d1) + -+ yaffs_CountBits(d2)) == 1) { -+ /* Reccoverable error in ecc */ -+ -+@@ -239,13 +228,115 @@ -+ -+ return 1; /* Corrected the error */ -+ } -+- -++ -+ /* Unrecoverable error */ -+ -+ return -1; -+ -+ } -+ -++#if defined(CONFIG_YAFFS_ECC_RS) -++#ifdef __KERNEL__ -++#include -++struct rs_control *rs_decoder; -++#else -++#include "ssfdc_rs_ecc.h" -++void *rs_init_user; -++#endif -++ -++/* Transfer 16 bytes to 26 5-bit symbols */ -++void Data2Sym(const unsigned char *in, unsigned char *out) -++{ -++ int i, j, shift; -++ -++ for (i = 0; i < 26; i++){ -++ j = (5 * i) >> 3; -++ shift = (5 * i) & 0x7; -++ if (shift > 3) -++ out[i] = ((in[j] >> shift) | (in[j+1] << (8 - shift))) & 0x1f; -++ else -++ out[i] = (in[j] >> shift) & 0x1f; -++ } -++ out[25] &= 0x7; /* the last symbol has only 3 bits */ -++} -++ -++/* -++ * It does reed solomon ECC calcs on 16 bytes of oob data -++ */ -++void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes, -++ yaffs_ECCOther * eccOther) -++{ -++ unsigned short *par = (unsigned short *)&eccOther->lineParity; -++ unsigned char data5[26]; -++ -++ -++ Data2Sym(data, data5); -++ memset(par, 0, 8); -++ -++#ifdef __KERNEL__ -++ /* Encode 26 symbols in data5. Store parities of 4 symbols in -++ * buffer par whose size is 8 bytes(2 bytes per symbol) */ -++ encode_rs8 (rs_decoder, data5, 26, par, 0); -++#else -++ /* init reed solomon ECC for nand oob area -++ * Symbolsize is 5 (bits) -++ * Primitive polynomial is x^5+x^2+1 -++ * first consecutive root is 0 -++ * primitive element to generate roots = 1 -++ * generator polynomial degree (number of roots) = 4 -++ * pad = (1<lineParity; -++ unsigned char data5[26]; -++ int numerr; -++ -++ Data2Sym(data, data5); -++ -++ /* Decode 26 symbols in data5. */ -++ numerr = decode_rs8 (rs_decoder, data5, par, 26, NULL, 0, NULL, 0, NULL); -++ -++ if (numerr == 0) -++ return 0; -++ else if (numerr > 0 && numerr < 3) -++ return 1; -++ else -++ return -1; -++} -++#else -++int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes, -++ yaffs_ECCOther * read_ecc, -++ const yaffs_ECCOther * test_ecc) -++{ -++ return 0; -++} -++#endif -++ -++#else -++ -++static int yaffs_CountBits32(unsigned x) -++{ -++ int r = 0; -++ while (x) { -++ if (x & 1) -++ r++; -++ x >>= 1; -++ } -++ return r; -++} -+ -+ /* -+ * ECCxxxOther does ECC calcs on arbitrary n bytes of data -+@@ -293,7 +384,7 @@ -+ if ((cDelta | lDelta | lDeltaPrime) == 0) -+ return 0; /* no error */ -+ -+- if (lDelta == ~lDeltaPrime && -++ if (lDelta == ~lDeltaPrime && -+ (((cDelta ^ (cDelta >> 1)) & 0x15) == 0x15)) -+ { -+ /* Single bit (recoverable) error in data */ -+@@ -309,7 +400,7 @@ -+ -+ if(lDelta >= nBytes) -+ return -1; -+- -++ -+ data[lDelta] ^= (1 << bit); -+ -+ return 1; /* corrected */ -+@@ -328,4 +419,4 @@ -+ return -1; -+ -+ } -+- -++#endif /* YAFFS_ECC_RS */ -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_ecc.h linux-2.6.24.7.new/fs/yaffs2/yaffs_ecc.h -+--- linux-2.6.24.7/fs/yaffs2/yaffs_ecc.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_ecc.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ /* -+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+@@ -16,9 +16,9 @@ -+ /* -+ * This code implements the ECC algorithm used in SmartMedia. -+ * -+- * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. -++ * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. -+ * The two unused bit are set to 1. -+- * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC -++ * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC -+ * blocks are used on a 512-byte NAND page. -+ * -+ */ -+@@ -32,6 +32,10 @@ -+ unsigned lineParityPrime; -+ } yaffs_ECCOther; -+ -++#if defined(CONFIG_YAFFS_ECC_RS) -++extern struct rs_control *rs_decoder; -++#endif -++ -+ void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc); -+ int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc, -+ const unsigned char *test_ecc); -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_fs.c linux-2.6.24.7.new/fs/yaffs2/yaffs_fs.c -+--- linux-2.6.24.7/fs/yaffs2/yaffs_fs.c 2009-04-21 14:57:10.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_fs.c 2009-04-21 15:01:02.000000000 +0200 -+@@ -23,7 +23,7 @@ -+ * This is the file system front-end to YAFFS that hooks it up to -+ * the VFS. -+ * -+- * Special notes: -++ * Special notes: -+ * >> 2.4: sb->u.generic_sbp points to the yaffs_Device associated with -+ * this superblock -+ * >> 2.6: sb->s_fs_info points to the yaffs_Device associated with this -+@@ -32,7 +32,7 @@ -+ */ -+ -+ const char *yaffs_fs_c_version = -+- "$Id: yaffs_fs.c,v 1.63 2007-09-19 20:35:40 imcd Exp $"; -++ "$Id: yaffs_fs.c,v 1.2 2008-07-17 23:59:16 lhhuang Exp $"; -+ extern const char *yaffs_guts_c_version; -+ -+ #include -+@@ -76,34 +76,23 @@ -+ -+ #endif -+ -+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+-#define WRITE_SIZE_STR "writesize" -+-#define WRITE_SIZE(mtd) (mtd)->writesize -+-#else -+-#define WRITE_SIZE_STR "oobblock" -+-#define WRITE_SIZE(mtd) (mtd)->oobblock -+-#endif -+- -+ #include -+ -+ #include "yportenv.h" -+ #include "yaffs_guts.h" -+ -++unsigned yaffs_traceMask = YAFFS_TRACE_ALWAYS | -++ YAFFS_TRACE_BAD_BLOCKS/* | -++ YAFFS_TRACE_CHECKPOINT*/ -++ /* | 0xFFFFFFFF */; -++ -+ #include -+ #include "yaffs_mtdif.h" -+-#include "yaffs_mtdif1.h" -+ #include "yaffs_mtdif2.h" -+ -+-unsigned int yaffs_traceMask = YAFFS_TRACE_BAD_BLOCKS; -+-unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS; -+- -+-/* Module Parameters */ -+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+-module_param(yaffs_traceMask,uint,0644); -+-module_param(yaffs_wr_attempts,uint,0644); -+-#else -+-MODULE_PARM(yaffs_traceMask,"i"); -+-MODULE_PARM(yaffs_wr_attempts,"i"); -++#if defined(CONFIG_YAFFS_ECC_RS) -++#include -++#include "yaffs_ecc.h" -+ #endif -+ -+ /*#define T(x) printk x */ -+@@ -174,6 +163,8 @@ -+ static int yaffs_write_super(struct super_block *sb); -+ #endif -+ -++static int yaffs_remount_fs(struct super_block *, int *, char *); -++ -+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+ static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf); -+ #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+@@ -213,45 +204,24 @@ -+ .commit_write = yaffs_commit_write, -+ }; -+ -+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) -+-static struct file_operations yaffs_file_operations = { -+- .read = do_sync_read, -+- .write = do_sync_write, -+- .aio_read = generic_file_aio_read, -+- .aio_write = generic_file_aio_write, -+- .mmap = generic_file_mmap, -+- .flush = yaffs_file_flush, -+- .fsync = yaffs_sync_object, -+- .splice_read = generic_file_splice_read, -+- .splice_write = generic_file_splice_write, -+-}; -+- -+-#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) -+- -+ static struct file_operations yaffs_file_operations = { -++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) -+ .read = do_sync_read, -+ .write = do_sync_write, -+ .aio_read = generic_file_aio_read, -+ .aio_write = generic_file_aio_write, -+- .mmap = generic_file_mmap, -+- .flush = yaffs_file_flush, -+- .fsync = yaffs_sync_object, -+- .sendfile = generic_file_sendfile, -+-}; -+- -+ #else -+- -+-static struct file_operations yaffs_file_operations = { -+ .read = generic_file_read, -+ .write = generic_file_write, -++#endif -+ .mmap = generic_file_mmap, -+ .flush = yaffs_file_flush, -+ .fsync = yaffs_sync_object, -+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)) -+ .sendfile = generic_file_sendfile, -+ #endif -++ -+ }; -+-#endif -+ -+ static struct inode_operations yaffs_file_inode_operations = { -+ .setattr = yaffs_setattr, -+@@ -287,6 +257,7 @@ -+ .read_inode = yaffs_read_inode, -+ .put_inode = yaffs_put_inode, -+ .put_super = yaffs_put_super, -++ .remount_fs = yaffs_remount_fs, -+ .delete_inode = yaffs_delete_inode, -+ .clear_inode = yaffs_clear_inode, -+ .sync_fs = yaffs_sync_fs, -+@@ -391,7 +362,7 @@ -+ dentry->d_name.name); -+ -+ obj = yaffs_GetEquivalentObject(obj); /* in case it was a hardlink */ -+- -++ -+ /* Can't hold gross lock when calling yaffs_get_inode() */ -+ yaffs_GrossUnlock(dev); -+ -+@@ -429,6 +400,42 @@ -+ -+ } -+ -++static int yaffs_dump_dev1(yaffs_Device * dev) -++{ -++ printk("startBlock......... %d\n", dev->startBlock); -++ printk("endBlock........... %d\n", dev->endBlock); -++ printk("chunkGroupBits..... %d\n", dev->chunkGroupBits); -++ printk("chunkGroupSize..... %d\n", dev->chunkGroupSize); -++ printk("nErasedBlocks...... %d\n", dev->nErasedBlocks); -++ printk("nTnodesCreated..... %d\n", dev->nTnodesCreated); -++ printk("nFreeTnodes........ %d\n", dev->nFreeTnodes); -++ printk("nObjectsCreated.... %d\n", dev->nObjectsCreated); -++ printk("nFreeObjects....... %d\n", dev->nFreeObjects); -++ printk("nFreeChunks........ %d\n", dev->nFreeChunks); -++ printk("nPageWrites........ %d\n", dev->nPageWrites); -++ printk("nPageReads......... %d\n", dev->nPageReads); -++ printk("nBlockErasures..... %d\n", dev->nBlockErasures); -++ printk("nGCCopies.......... %d\n", dev->nGCCopies); -++ printk("garbageCollections. %d\n", dev->garbageCollections); -++ -++ printk("passiveGCs......... %d\n", dev->passiveGarbageCollections); -++ printk("nRetriedWrites..... %d\n", dev->nRetriedWrites); -++ printk("nRetireBlocks...... %d\n", dev->nRetiredBlocks); -++ printk("eccFixed........... %d\n", dev->eccFixed); -++ printk("eccUnfixed......... %d\n", dev->eccUnfixed); -++ printk("tagsEccFixed....... %d\n", dev->tagsEccFixed); -++ printk("tagsEccUnfixed..... %d\n", dev->tagsEccUnfixed); -++ printk("cacheHits.......... %d\n", dev->cacheHits); -++ printk("nDeletedFiles...... %d\n", dev->nDeletedFiles); -++ printk("nUnlinkedFiles..... %d\n", dev->nUnlinkedFiles); -++ printk("nBackgroudDeletions %d\n", dev->nBackgroundDeletions); -++ printk("useNANDECC......... %d\n", dev->useNANDECC); -++ printk("isYaffs2........... %d\n", dev->isYaffs2); -++ -++ return 1; -++} -++ -++ -+ /* For now put inode is just for debugging -+ * Put inode is called when the inode **structure** is put. -+ */ -+@@ -729,21 +736,21 @@ -+ obj->yst_mode &= ~S_IFMT; -+ obj->yst_mode |= S_IFREG; -+ } -+- -++ -+ break; -+ case YAFFS_OBJECT_TYPE_SYMLINK : -+ if( ! S_ISLNK(mode) ){ -+ obj->yst_mode &= ~S_IFMT; -+ obj->yst_mode |= S_IFLNK; -+ } -+- -++ -+ break; -+ case YAFFS_OBJECT_TYPE_DIRECTORY : -+ if( ! S_ISDIR(mode) ){ -+ obj->yst_mode &= ~S_IFMT; -+ obj->yst_mode |= S_IFDIR; -+ } -+- -++ -+ break; -+ case YAFFS_OBJECT_TYPE_UNKNOWN : -+ case YAFFS_OBJECT_TYPE_HARDLINK : -+@@ -1020,7 +1027,7 @@ -+ int error = -ENOSPC; -+ uid_t uid = current->fsuid; -+ gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; -+- -++ -+ if((dir->i_mode & S_ISGID) && S_ISDIR(mode)) -+ mode |= S_ISGID; -+ -+@@ -1075,7 +1082,7 @@ -+ obj = NULL; /* Do we ever get here? */ -+ break; -+ } -+- -++ -+ /* Can not call yaffs_get_inode() with gross lock held */ -+ yaffs_GrossUnlock(dev); -+ -+@@ -1264,13 +1271,13 @@ -+ target = -+ yaffs_FindObjectByName(yaffs_InodeToObject(new_dir), -+ new_dentry->d_name.name); -+- -+- -++ -++ -+ -+ if (target && -+ target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && -+ !list_empty(&target->variant.directoryVariant.children)) { -+- -++ -+ T(YAFFS_TRACE_OS, (KERN_DEBUG "target is non-empty dir\n")); -+ -+ retVal = YAFFS_FAIL; -+@@ -1278,7 +1285,7 @@ -+ -+ /* Now does unlinking internally using shadowing mechanism */ -+ T(YAFFS_TRACE_OS, (KERN_DEBUG "calling yaffs_RenameObject\n")); -+- -++ -+ retVal = -+ yaffs_RenameObject(yaffs_InodeToObject(old_dir), -+ old_dentry->d_name.name, -+@@ -1390,7 +1397,7 @@ -+ -+ if(dev) -+ yaffs_CheckpointSave(dev); -+- -++ -+ yaffs_GrossUnlock(dev); -+ -+ sb->s_dirt = 0; -+@@ -1421,16 +1428,16 @@ -+ { -+ -+ T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n")); -+- -++ -+ return 0; /* yaffs_do_sync_fs(sb);*/ -+- -++ -+ } -+ -+ -+ static void yaffs_read_inode(struct inode *inode) -+ { -+ /* NB This is called as a side effect of other functions, but -+- * we had to release the lock to prevent deadlocks, so -++ * we had to release the lock to prevent deadlocks, so -+ * need to lock again. -+ */ -+ -+@@ -1441,7 +1448,7 @@ -+ (KERN_DEBUG "yaffs_read_inode for %d\n", (int)inode->i_ino)); -+ -+ yaffs_GrossLock(dev); -+- -++ -+ obj = yaffs_FindObjectByNumber(dev, inode->i_ino); -+ -+ yaffs_FillInodeFromObject(inode, obj); -+@@ -1451,36 +1458,34 @@ -+ -+ static LIST_HEAD(yaffs_dev_list); -+ -+-#if 0 // not used -+ static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data) -+ { -+ yaffs_Device *dev = yaffs_SuperToDevice(sb); -+ -+ if( *flags & MS_RDONLY ) { -+ struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice; -+- -++ -+ T(YAFFS_TRACE_OS, -+ (KERN_DEBUG "yaffs_remount_fs: %s: RO\n", dev->name )); -+ -+ yaffs_GrossLock(dev); -+- -++ -+ yaffs_FlushEntireDeviceCache(dev); -+- -++ -+ yaffs_CheckpointSave(dev); -+- -++ -+ if (mtd->sync) -+ mtd->sync(mtd); -+ -+ yaffs_GrossUnlock(dev); -+ } -+ else { -+- T(YAFFS_TRACE_OS, -++ T(YAFFS_TRACE_OS, -+ (KERN_DEBUG "yaffs_remount_fs: %s: RW\n", dev->name )); -+ } -+- -++ -+ return 0; -+ } -+-#endif -+ -+ static void yaffs_put_super(struct super_block *sb) -+ { -+@@ -1489,7 +1494,7 @@ -+ T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_put_super\n")); -+ -+ yaffs_GrossLock(dev); -+- -++ -+ yaffs_FlushEntireDeviceCache(dev); -+ -+ yaffs_CheckpointSave(dev); -+@@ -1499,12 +1504,12 @@ -+ } -+ -+ yaffs_Deinitialise(dev); -+- -++ -+ yaffs_GrossUnlock(dev); -+ -+ /* we assume this is protected by lock_kernel() in mount/umount */ -+ list_del(&dev->devList); -+- -++ -+ if(dev->spareBuffer){ -+ YFREE(dev->spareBuffer); -+ dev->spareBuffer = NULL; -+@@ -1530,61 +1535,12 @@ -+ static void yaffs_MarkSuperBlockDirty(void *vsb) -+ { -+ struct super_block *sb = (struct super_block *)vsb; -+- -++ -+ T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_MarkSuperBlockDirty() sb = %p\n",sb)); -+ // if(sb) -+ // sb->s_dirt = 1; -+ } -+ -+-typedef struct { -+- int inband_tags; -+- int skip_checkpoint_read; -+- int skip_checkpoint_write; -+- int no_cache; -+-} yaffs_options; -+- -+-#define MAX_OPT_LEN 20 -+-static int yaffs_parse_options(yaffs_options *options, const char *options_str) -+-{ -+- char cur_opt[MAX_OPT_LEN+1]; -+- int p; -+- int error = 0; -+- -+- /* Parse through the options which is a comma seperated list */ -+- -+- while(options_str && *options_str && !error){ -+- memset(cur_opt,0,MAX_OPT_LEN+1); -+- p = 0; -+- -+- while(*options_str && *options_str != ','){ -+- if(p < MAX_OPT_LEN){ -+- cur_opt[p] = *options_str; -+- p++; -+- } -+- options_str++; -+- } -+- -+- if(!strcmp(cur_opt,"inband-tags")) -+- options->inband_tags = 1; -+- else if(!strcmp(cur_opt,"no-cache")) -+- options->no_cache = 1; -+- else if(!strcmp(cur_opt,"no-checkpoint-read")) -+- options->skip_checkpoint_read = 1; -+- else if(!strcmp(cur_opt,"no-checkpoint-write")) -+- options->skip_checkpoint_write = 1; -+- else if(!strcmp(cur_opt,"no-checkpoint")){ -+- options->skip_checkpoint_read = 1; -+- options->skip_checkpoint_write = 1; -+- } else { -+- printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n",cur_opt); -+- error = 1; -+- } -+- -+- } -+- -+- return error; -+-} -+- -+ static struct super_block *yaffs_internal_read_super(int yaffsVersion, -+ struct super_block *sb, -+ void *data, int silent) -+@@ -1596,9 +1552,6 @@ -+ char devname_buf[BDEVNAME_SIZE + 1]; -+ struct mtd_info *mtd; -+ int err; -+- char *data_str = (char *)data; -+- -+- yaffs_options options; -+ -+ sb->s_magic = YAFFS_MAGIC; -+ sb->s_op = &yaffs_super_ops; -+@@ -1614,19 +1567,6 @@ -+ sb->s_dev, -+ yaffs_devname(sb, devname_buf)); -+ -+- if(!data_str) -+- data_str = ""; -+- -+- printk(KERN_INFO "yaffs: passed flags \"%s\"\n",data_str); -+- -+- memset(&options,0,sizeof(options)); -+- -+- if(yaffs_parse_options(&options,data_str)){ -+- /* Option parsing failed */ -+- return NULL; -+- } -+- -+- -+ sb->s_blocksize = PAGE_CACHE_SIZE; -+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT; -+ T(YAFFS_TRACE_OS, ("yaffs_read_super: Using yaffs%d\n", yaffsVersion)); -+@@ -1670,14 +1610,18 @@ -+ T(YAFFS_TRACE_OS, (" writeoob %p\n", mtd->write_oob)); -+ T(YAFFS_TRACE_OS, (" block_isbad %p\n", mtd->block_isbad)); -+ T(YAFFS_TRACE_OS, (" block_markbad %p\n", mtd->block_markbad)); -+- T(YAFFS_TRACE_OS, (" %s %d\n", WRITE_SIZE_STR, WRITE_SIZE(mtd))); -++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -++ T(YAFFS_TRACE_OS, (" writesize %d\n", mtd->writesize)); -++#else -++ T(YAFFS_TRACE_OS, (" oobblock %d\n", mtd->oobblock)); -++#endif -+ T(YAFFS_TRACE_OS, (" oobsize %d\n", mtd->oobsize)); -+ T(YAFFS_TRACE_OS, (" erasesize %d\n", mtd->erasesize)); -+- T(YAFFS_TRACE_OS, (" size %d\n", mtd->size)); -+- -++ T(YAFFS_TRACE_OS, (" size %lld\n", mtd->size)); -++ -+ #ifdef CONFIG_YAFFS_AUTO_YAFFS2 -+ -+- if (yaffsVersion == 1 && -++ if (yaffsVersion == 1 && -+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+ mtd->writesize >= 2048) { -+ #else -+@@ -1685,10 +1629,10 @@ -+ #endif -+ T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n")); -+ yaffsVersion = 2; -+- } -+- -++ } -++ -+ /* Added NCB 26/5/2006 for completeness */ -+- if (yaffsVersion == 2 && -++ if (yaffsVersion == 2 && -+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+ mtd->writesize == 512) { -+ #else -+@@ -1696,7 +1640,7 @@ -+ #endif -+ T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n")); -+ yaffsVersion = 1; -+- } -++ } -+ -+ #endif -+ -+@@ -1747,7 +1691,11 @@ -+ return NULL; -+ } -+ -+- if (WRITE_SIZE(mtd) < YAFFS_BYTES_PER_CHUNK || -++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -++ if (mtd->writesize < YAFFS_BYTES_PER_CHUNK || -++#else -++ if (mtd->oobblock < YAFFS_BYTES_PER_CHUNK || -++#endif -+ mtd->oobsize != YAFFS_BYTES_PER_SPARE) { -+ T(YAFFS_TRACE_ALWAYS, -+ ("yaffs: MTD device does not support have the " -+@@ -1779,17 +1727,14 @@ -+ dev->name = mtd->name; -+ -+ /* Set up the memory size parameters.... */ -+- -+- nBlocks = mtd->size / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK); -+- dev->startBlock = 0; -+- dev->endBlock = nBlocks - 1; -+ dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK; -+ dev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK; -+ dev->nReservedBlocks = 5; -+- dev->nShortOpCaches = (options.no_cache) ? 0 : 10; -++ dev->nShortOpCaches = 10; /* Enable short op caching */ -+ -+ /* ... and the functions. */ -+ if (yaffsVersion == 2) { -++ int block_shift; -+ dev->writeChunkWithTagsToNAND = -+ nandmtd2_WriteChunkWithTagsToNAND; -+ dev->readChunkWithTagsFromNAND = -+@@ -1805,24 +1750,18 @@ -+ dev->nDataBytesPerChunk = mtd->oobblock; -+ dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock; -+ #endif -+- nBlocks = mtd->size / mtd->erasesize; -+- -++ block_shift = ffs(mtd->erasesize) - 1; -++// nBlocks = mtd->size / mtd->erasesize; -++ nBlocks = mtd->size >> block_shift; -+ dev->nCheckpointReservedBlocks = CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS; -+ dev->startBlock = 0; -+ dev->endBlock = nBlocks - 1; -+ } else { -+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+- /* use the MTD interface in yaffs_mtdif1.c */ -+- dev->writeChunkWithTagsToNAND = -+- nandmtd1_WriteChunkWithTagsToNAND; -+- dev->readChunkWithTagsFromNAND = -+- nandmtd1_ReadChunkWithTagsFromNAND; -+- dev->markNANDBlockBad = nandmtd1_MarkNANDBlockBad; -+- dev->queryNANDBlock = nandmtd1_QueryNANDBlock; -+-#else -++ nBlocks = mtd->size / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK); -++ dev->startBlock = 0; -++ dev->endBlock = nBlocks - 1; -+ dev->writeChunkToNAND = nandmtd_WriteChunkToNAND; -+ dev->readChunkFromNAND = nandmtd_ReadChunkFromNAND; -+-#endif -+ dev->isYaffs2 = 0; -+ } -+ /* ... and common functions */ -+@@ -1830,10 +1769,10 @@ -+ dev->initialiseNAND = nandmtd_InitialiseNAND; -+ -+ dev->putSuperFunc = yaffs_MTDPutSuper; -+- -++ -+ dev->superBlock = (void *)sb; -+ dev->markSuperBlockDirty = yaffs_MarkSuperBlockDirty; -+- -++ -+ -+ #ifndef CONFIG_YAFFS_DOES_ECC -+ dev->useNANDECC = 1; -+@@ -1843,9 +1782,6 @@ -+ dev->wideTnodesDisabled = 1; -+ #endif -+ -+- dev->skipCheckpointRead = options.skip_checkpoint_read; -+- dev->skipCheckpointWrite = options.skip_checkpoint_write; -+- -+ /* we assume this is protected by lock_kernel() in mount/umount */ -+ list_add_tail(&dev->devList, &yaffs_dev_list); -+ -+@@ -1858,7 +1794,7 @@ -+ T(YAFFS_TRACE_OS, -+ ("yaffs_read_super: guts initialised %s\n", -+ (err == YAFFS_OK) ? "OK" : "FAILED")); -+- -++ -+ /* Release lock before yaffs_get_inode() */ -+ yaffs_GrossUnlock(dev); -+ -+@@ -1869,7 +1805,6 @@ -+ -+ if (!inode) -+ return NULL; -+- -+ inode->i_op = &yaffs_dir_inode_operations; -+ inode->i_fop = &yaffs_dir_operations; -+ -+@@ -1884,7 +1819,6 @@ -+ return NULL; -+ } -+ sb->s_root = root; -+- -+ T(YAFFS_TRACE_OS, ("yaffs_read_super: done\n")); -+ return sb; -+ } -+@@ -1990,13 +1924,9 @@ -+ { -+ buf += sprintf(buf, "startBlock......... %d\n", dev->startBlock); -+ buf += sprintf(buf, "endBlock........... %d\n", dev->endBlock); -+- buf += sprintf(buf, "nDataBytesPerChunk. %d\n", dev->nDataBytesPerChunk); -+ buf += sprintf(buf, "chunkGroupBits..... %d\n", dev->chunkGroupBits); -+ buf += sprintf(buf, "chunkGroupSize..... %d\n", dev->chunkGroupSize); -+ buf += sprintf(buf, "nErasedBlocks...... %d\n", dev->nErasedBlocks); -+- buf += sprintf(buf, "nReservedBlocks.... %d\n", dev->nReservedBlocks); -+- buf += sprintf(buf, "nCheckptResBlocks.. %d\n", dev->nCheckpointReservedBlocks); -+- buf += sprintf(buf, "blocksInCheckpoint. %d\n", dev->blocksInCheckpoint); -+ buf += sprintf(buf, "nTnodesCreated..... %d\n", dev->nTnodesCreated); -+ buf += sprintf(buf, "nFreeTnodes........ %d\n", dev->nFreeTnodes); -+ buf += sprintf(buf, "nObjectsCreated.... %d\n", dev->nObjectsCreated); -+@@ -2012,7 +1942,6 @@ -+ sprintf(buf, "passiveGCs......... %d\n", -+ dev->passiveGarbageCollections); -+ buf += sprintf(buf, "nRetriedWrites..... %d\n", dev->nRetriedWrites); -+- buf += sprintf(buf, "nShortOpCaches..... %d\n", dev->nShortOpCaches); -+ buf += sprintf(buf, "nRetireBlocks...... %d\n", dev->nRetiredBlocks); -+ buf += sprintf(buf, "eccFixed........... %d\n", dev->eccFixed); -+ buf += sprintf(buf, "eccUnfixed......... %d\n", dev->eccUnfixed); -+@@ -2075,7 +2004,6 @@ -+ /** -+ * Set the verbosity of the warnings and error messages. -+ * -+- * Note that the names can only be a..z or _ with the current code. -+ */ -+ -+ static struct { -+@@ -2087,7 +2015,6 @@ -+ {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS}, -+ {"buffers", YAFFS_TRACE_BUFFERS}, -+ {"bug", YAFFS_TRACE_BUG}, -+- {"checkpt", YAFFS_TRACE_CHECKPOINT}, -+ {"deletion", YAFFS_TRACE_DELETION}, -+ {"erase", YAFFS_TRACE_ERASE}, -+ {"error", YAFFS_TRACE_ERROR}, -+@@ -2099,27 +2026,17 @@ -+ {"scan_debug", YAFFS_TRACE_SCAN_DEBUG}, -+ {"scan", YAFFS_TRACE_SCAN}, -+ {"tracing", YAFFS_TRACE_TRACING}, -+- -+- {"verify", YAFFS_TRACE_VERIFY}, -+- {"verify_nand", YAFFS_TRACE_VERIFY_NAND}, -+- {"verify_full", YAFFS_TRACE_VERIFY_FULL}, -+- {"verify_all", YAFFS_TRACE_VERIFY_ALL}, -+- -+ {"write", YAFFS_TRACE_WRITE}, -+ {"all", 0xffffffff}, -+ {"none", 0}, -+ {NULL, 0}, -+ }; -+ -+-#define MAX_MASK_NAME_LENGTH 40 -+ static int yaffs_proc_write(struct file *file, const char *buf, -+ unsigned long count, void *data) -+ { -+ unsigned rg = 0, mask_bitfield; -+- char *end; -+- char *mask_name; -+- const char *x; -+- char substring[MAX_MASK_NAME_LENGTH+1]; -++ char *end, *mask_name; -+ int i; -+ int done = 0; -+ int add, len = 0; -+@@ -2146,22 +2063,16 @@ -+ break; -+ } -+ mask_name = NULL; -+- -+ mask_bitfield = simple_strtoul(buf + pos, &end, 0); -+ if (end > buf + pos) { -+ mask_name = "numeral"; -+ len = end - (buf + pos); -+- pos += len; -+ done = 0; -+ } else { -+- for(x = buf + pos, i = 0; -+- (*x == '_' || (*x >='a' && *x <= 'z')) && -+- i 1){ -+ if(x & 1) extraBits++; -+ x>>=1; -+ nShifts++; -+ } -+ -+- if(extraBits) -++ if(extraBits) -+ nShifts++; -+- -++ -+ return nShifts; -+ } -+ -+ /* Function to return the number of shifts to get a 1 in bit 0 -+ */ -+- -++ -+ static __u32 ShiftDiv(__u32 x) -+ { -+ int nShifts; -+- -++ -+ nShifts = 0; -+- -++ -+ if(!x) return 0; -+- -++ -+ while( !(x&1)){ -+ x>>=1; -+ nShifts++; -+ } -+- -++ -+ return nShifts; -+ } -+ -+ -+ -+-/* -++/* -+ * Temporary buffer manipulations. -+ */ -+ -+-static int yaffs_InitialiseTempBuffers(yaffs_Device *dev) -+-{ -+- int i; -+- __u8 *buf = (__u8 *)1; -+- -+- memset(dev->tempBuffer,0,sizeof(dev->tempBuffer)); -+- -+- for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) { -+- dev->tempBuffer[i].line = 0; /* not in use */ -+- dev->tempBuffer[i].buffer = buf = -+- YMALLOC_DMA(dev->nDataBytesPerChunk); -+- } -+- -+- return buf ? YAFFS_OK : YAFFS_FAIL; -+- -+-} -+- -+ static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo) -+ { -+ int i, j; -+@@ -290,8 +264,6 @@ -+ return 0; -+ } -+ -+- -+- -+ /* -+ * Chunk bitmap manipulations -+ */ -+@@ -308,16 +280,6 @@ -+ (dev->chunkBitmapStride * (blk - dev->internalStartBlock)); -+ } -+ -+-static Y_INLINE void yaffs_VerifyChunkBitId(yaffs_Device *dev, int blk, int chunk) -+-{ -+- if(blk < dev->internalStartBlock || blk > dev->internalEndBlock || -+- chunk < 0 || chunk >= dev->nChunksPerBlock) { -+- T(YAFFS_TRACE_ERROR, -+- (TSTR("**>> yaffs: Chunk Id (%d:%d) invalid"TENDSTR),blk,chunk)); -+- YBUG(); -+- } -+-} -+- -+ static Y_INLINE void yaffs_ClearChunkBits(yaffs_Device * dev, int blk) -+ { -+ __u8 *blkBits = yaffs_BlockBits(dev, blk); -+@@ -329,8 +291,6 @@ -+ { -+ __u8 *blkBits = yaffs_BlockBits(dev, blk); -+ -+- yaffs_VerifyChunkBitId(dev,blk,chunk); -+- -+ blkBits[chunk / 8] &= ~(1 << (chunk & 7)); -+ } -+ -+@@ -338,16 +298,12 @@ -+ { -+ __u8 *blkBits = yaffs_BlockBits(dev, blk); -+ -+- yaffs_VerifyChunkBitId(dev,blk,chunk); -+- -+ blkBits[chunk / 8] |= (1 << (chunk & 7)); -+ } -+ -+ static Y_INLINE int yaffs_CheckChunkBit(yaffs_Device * dev, int blk, int chunk) -+ { -+ __u8 *blkBits = yaffs_BlockBits(dev, blk); -+- yaffs_VerifyChunkBitId(dev,blk,chunk); -+- -+ return (blkBits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0; -+ } -+ -+@@ -363,495 +319,10 @@ -+ return 0; -+ } -+ -+-static int yaffs_CountChunkBits(yaffs_Device * dev, int blk) -+-{ -+- __u8 *blkBits = yaffs_BlockBits(dev, blk); -+- int i; -+- int n = 0; -+- for (i = 0; i < dev->chunkBitmapStride; i++) { -+- __u8 x = *blkBits; -+- while(x){ -+- if(x & 1) -+- n++; -+- x >>=1; -+- } -+- -+- blkBits++; -+- } -+- return n; -+-} -+- -+-/* -+- * Verification code -+- */ -+- -+-static int yaffs_SkipVerification(yaffs_Device *dev) -+-{ -+- return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL)); -+-} -+- -+-static int yaffs_SkipFullVerification(yaffs_Device *dev) -+-{ -+- return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_FULL)); -+-} -+- -+-static int yaffs_SkipNANDVerification(yaffs_Device *dev) -+-{ -+- return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_NAND)); -+-} -+- -+-static const char * blockStateName[] = { -+-"Unknown", -+-"Needs scanning", -+-"Scanning", -+-"Empty", -+-"Allocating", -+-"Full", -+-"Dirty", -+-"Checkpoint", -+-"Collecting", -+-"Dead" -+-}; -+- -+-static void yaffs_VerifyBlock(yaffs_Device *dev,yaffs_BlockInfo *bi,int n) -+-{ -+- int actuallyUsed; -+- int inUse; -+- -+- if(yaffs_SkipVerification(dev)) -+- return; -+- -+- /* Report illegal runtime states */ -+- if(bi->blockState <0 || bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES) -+- T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has undefined state %d"TENDSTR),n,bi->blockState)); -+- -+- switch(bi->blockState){ -+- case YAFFS_BLOCK_STATE_UNKNOWN: -+- case YAFFS_BLOCK_STATE_SCANNING: -+- case YAFFS_BLOCK_STATE_NEEDS_SCANNING: -+- T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has bad run-state %s"TENDSTR), -+- n,blockStateName[bi->blockState])); -+- } -+- -+- /* Check pages in use and soft deletions are legal */ -+- -+- actuallyUsed = bi->pagesInUse - bi->softDeletions; -+- -+- if(bi->pagesInUse < 0 || bi->pagesInUse > dev->nChunksPerBlock || -+- bi->softDeletions < 0 || bi->softDeletions > dev->nChunksPerBlock || -+- actuallyUsed < 0 || actuallyUsed > dev->nChunksPerBlock) -+- T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has illegal values pagesInUsed %d softDeletions %d"TENDSTR), -+- n,bi->pagesInUse,bi->softDeletions)); -+- -+- -+- /* Check chunk bitmap legal */ -+- inUse = yaffs_CountChunkBits(dev,n); -+- if(inUse != bi->pagesInUse) -+- T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has inconsistent values pagesInUse %d counted chunk bits %d"TENDSTR), -+- n,bi->pagesInUse,inUse)); -+- -+- /* Check that the sequence number is valid. -+- * Ten million is legal, but is very unlikely -+- */ -+- if(dev->isYaffs2 && -+- (bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING || bi->blockState == YAFFS_BLOCK_STATE_FULL) && -+- (bi->sequenceNumber < YAFFS_LOWEST_SEQUENCE_NUMBER || bi->sequenceNumber > 10000000 )) -+- T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has suspect sequence number of %d"TENDSTR), -+- n,bi->sequenceNumber)); -+- -+-} -+- -+-static void yaffs_VerifyCollectedBlock(yaffs_Device *dev,yaffs_BlockInfo *bi,int n) -+-{ -+- yaffs_VerifyBlock(dev,bi,n); -+- -+- /* After collection the block should be in the erased state */ -+- /* TODO: This will need to change if we do partial gc */ -+- -+- if(bi->blockState != YAFFS_BLOCK_STATE_EMPTY){ -+- T(YAFFS_TRACE_ERROR,(TSTR("Block %d is in state %d after gc, should be erased"TENDSTR), -+- n,bi->blockState)); -+- } -+-} -+- -+-static void yaffs_VerifyBlocks(yaffs_Device *dev) -+-{ -+- int i; -+- int nBlocksPerState[YAFFS_NUMBER_OF_BLOCK_STATES]; -+- int nIllegalBlockStates = 0; -+- -+- -+- if(yaffs_SkipVerification(dev)) -+- return; -+- -+- memset(nBlocksPerState,0,sizeof(nBlocksPerState)); -+- -+- -+- for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++){ -+- yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i); -+- yaffs_VerifyBlock(dev,bi,i); -+- -+- if(bi->blockState >=0 && bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES) -+- nBlocksPerState[bi->blockState]++; -+- else -+- nIllegalBlockStates++; -+- -+- } -+- -+- T(YAFFS_TRACE_VERIFY,(TSTR(""TENDSTR))); -+- T(YAFFS_TRACE_VERIFY,(TSTR("Block summary"TENDSTR))); -+- -+- T(YAFFS_TRACE_VERIFY,(TSTR("%d blocks have illegal states"TENDSTR),nIllegalBlockStates)); -+- if(nBlocksPerState[YAFFS_BLOCK_STATE_ALLOCATING] > 1) -+- T(YAFFS_TRACE_VERIFY,(TSTR("Too many allocating blocks"TENDSTR))); -+- -+- for(i = 0; i < YAFFS_NUMBER_OF_BLOCK_STATES; i++) -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("%s %d blocks"TENDSTR), -+- blockStateName[i],nBlocksPerState[i])); -+- -+- if(dev->blocksInCheckpoint != nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT]) -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("Checkpoint block count wrong dev %d count %d"TENDSTR), -+- dev->blocksInCheckpoint, nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT])); -+- -+- if(dev->nErasedBlocks != nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY]) -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("Erased block count wrong dev %d count %d"TENDSTR), -+- dev->nErasedBlocks, nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY])); -+- -+- if(nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING] > 1) -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("Too many collecting blocks %d (max is 1)"TENDSTR), -+- nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING])); -+- -+- T(YAFFS_TRACE_VERIFY,(TSTR(""TENDSTR))); -+- -+-} -+- -+-/* -+- * Verify the object header. oh must be valid, but obj and tags may be NULL in which -+- * case those tests will not be performed. -+- */ -+-static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, yaffs_ExtendedTags *tags, int parentCheck) -+-{ -+- if(yaffs_SkipVerification(obj->myDev)) -+- return; -+- -+- if(!(tags && obj && oh)){ -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("Verifying object header tags %x obj %x oh %x"TENDSTR), -+- (__u32)tags,(__u32)obj,(__u32)oh)); -+- return; -+- } -+- -+- if(oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN || -+- oh->type > YAFFS_OBJECT_TYPE_MAX) -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("Obj %d header type is illegal value 0x%x"TENDSTR), -+- tags->objectId, oh->type)); -+- -+- if(tags->objectId != obj->objectId) -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("Obj %d header mismatch objectId %d"TENDSTR), -+- tags->objectId, obj->objectId)); -+- -+- -+- /* -+- * Check that the object's parent ids match if parentCheck requested. -+- * -+- * Tests do not apply to the root object. -+- */ -+- -+- if(parentCheck && tags->objectId > 1 && !obj->parent) -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("Obj %d header mismatch parentId %d obj->parent is NULL"TENDSTR), -+- tags->objectId, oh->parentObjectId)); -+- -+- -+- if(parentCheck && obj->parent && -+- oh->parentObjectId != obj->parent->objectId && -+- (oh->parentObjectId != YAFFS_OBJECTID_UNLINKED || -+- obj->parent->objectId != YAFFS_OBJECTID_DELETED)) -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("Obj %d header mismatch parentId %d parentObjectId %d"TENDSTR), -+- tags->objectId, oh->parentObjectId, obj->parent->objectId)); -+- -+- -+- if(tags->objectId > 1 && oh->name[0] == 0) /* Null name */ -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("Obj %d header name is NULL"TENDSTR), -+- obj->objectId)); -+- -+- if(tags->objectId > 1 && ((__u8)(oh->name[0])) == 0xff) /* Trashed name */ -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("Obj %d header name is 0xFF"TENDSTR), -+- obj->objectId)); -+-} -+- -+- -+- -+-static int yaffs_VerifyTnodeWorker(yaffs_Object * obj, yaffs_Tnode * tn, -+- __u32 level, int chunkOffset) -+-{ -+- int i; -+- yaffs_Device *dev = obj->myDev; -+- int ok = 1; -+- int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; -+- -+- if (tn) { -+- if (level > 0) { -+- -+- for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++){ -+- if (tn->internal[i]) { -+- ok = yaffs_VerifyTnodeWorker(obj, -+- tn->internal[i], -+- level - 1, -+- (chunkOffset<objectId; -+- -+- chunkOffset <<= YAFFS_TNODES_LEVEL0_BITS; -+- -+- for(i = 0; i < YAFFS_NTNODES_LEVEL0; i++){ -+- __u32 theChunk = yaffs_GetChunkGroupBase(dev,tn,i); -+- -+- if(theChunk > 0){ -+- /* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),tags.objectId,tags.chunkId,theChunk)); */ -+- yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL, &tags); -+- if(tags.objectId != objectId || tags.chunkId != chunkOffset){ -+- T(~0,(TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR), -+- objectId, chunkOffset, theChunk, -+- tags.objectId, tags.chunkId)); -+- } -+- } -+- chunkOffset++; -+- } -+- } -+- } -+- -+- return ok; -+- -+-} -+- -+- -+-static void yaffs_VerifyFile(yaffs_Object *obj) -+-{ -+- int requiredTallness; -+- int actualTallness; -+- __u32 lastChunk; -+- __u32 x; -+- __u32 i; -+- int ok; -+- yaffs_Device *dev; -+- yaffs_ExtendedTags tags; -+- yaffs_Tnode *tn; -+- __u32 objectId; -+- -+- if(obj && yaffs_SkipVerification(obj->myDev)) -+- return; -+- -+- dev = obj->myDev; -+- objectId = obj->objectId; -+- -+- /* Check file size is consistent with tnode depth */ -+- lastChunk = obj->variant.fileVariant.fileSize / dev->nDataBytesPerChunk + 1; -+- x = lastChunk >> YAFFS_TNODES_LEVEL0_BITS; -+- requiredTallness = 0; -+- while (x> 0) { -+- x >>= YAFFS_TNODES_INTERNAL_BITS; -+- requiredTallness++; -+- } -+- -+- actualTallness = obj->variant.fileVariant.topLevel; -+- -+- if(requiredTallness > actualTallness ) -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("Obj %d had tnode tallness %d, needs to be %d"TENDSTR), -+- obj->objectId,actualTallness, requiredTallness)); -+- -+- -+- /* Check that the chunks in the tnode tree are all correct. -+- * We do this by scanning through the tnode tree and -+- * checking the tags for every chunk match. -+- */ -+- -+- if(yaffs_SkipNANDVerification(dev)) -+- return; -+- -+- for(i = 1; i <= lastChunk; i++){ -+- tn = yaffs_FindLevel0Tnode(dev, &obj->variant.fileVariant,i); -+- -+- if (tn) { -+- __u32 theChunk = yaffs_GetChunkGroupBase(dev,tn,i); -+- if(theChunk > 0){ -+- /* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),objectId,i,theChunk)); */ -+- yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL, &tags); -+- if(tags.objectId != objectId || tags.chunkId != i){ -+- T(~0,(TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR), -+- objectId, i, theChunk, -+- tags.objectId, tags.chunkId)); -+- } -+- } -+- } -+- -+- } -+- -+-} -+- -+-static void yaffs_VerifyDirectory(yaffs_Object *obj) -+-{ -+- if(obj && yaffs_SkipVerification(obj->myDev)) -+- return; -+- -+-} -+- -+-static void yaffs_VerifyHardLink(yaffs_Object *obj) -+-{ -+- if(obj && yaffs_SkipVerification(obj->myDev)) -+- return; -+- -+- /* Verify sane equivalent object */ -+-} -+- -+-static void yaffs_VerifySymlink(yaffs_Object *obj) -+-{ -+- if(obj && yaffs_SkipVerification(obj->myDev)) -+- return; -+- -+- /* Verify symlink string */ -+-} -+- -+-static void yaffs_VerifySpecial(yaffs_Object *obj) -+-{ -+- if(obj && yaffs_SkipVerification(obj->myDev)) -+- return; -+-} -+- -+-static void yaffs_VerifyObject(yaffs_Object *obj) -+-{ -+- yaffs_Device *dev; -+- -+- __u32 chunkMin; -+- __u32 chunkMax; -+- -+- __u32 chunkIdOk; -+- __u32 chunkIsLive; -+- -+- if(!obj) -+- return; -+- -+- dev = obj->myDev; -+- -+- if(yaffs_SkipVerification(dev)) -+- return; -+- -+- /* Check sane object header chunk */ -+- -+- chunkMin = dev->internalStartBlock * dev->nChunksPerBlock; -+- chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1; -+- -+- chunkIdOk = (obj->chunkId >= chunkMin && obj->chunkId <= chunkMax); -+- chunkIsLive = chunkIdOk && -+- yaffs_CheckChunkBit(dev, -+- obj->chunkId / dev->nChunksPerBlock, -+- obj->chunkId % dev->nChunksPerBlock); -+- if(!obj->fake && -+- (!chunkIdOk || !chunkIsLive)) { -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("Obj %d has chunkId %d %s %s"TENDSTR), -+- obj->objectId,obj->chunkId, -+- chunkIdOk ? "" : ",out of range", -+- chunkIsLive || !chunkIdOk ? "" : ",marked as deleted")); -+- } -+- -+- if(chunkIdOk && chunkIsLive &&!yaffs_SkipNANDVerification(dev)) { -+- yaffs_ExtendedTags tags; -+- yaffs_ObjectHeader *oh; -+- __u8 *buffer = yaffs_GetTempBuffer(dev,__LINE__); -+- -+- oh = (yaffs_ObjectHeader *)buffer; -+- -+- yaffs_ReadChunkWithTagsFromNAND(dev, obj->chunkId,buffer, &tags); -+- -+- yaffs_VerifyObjectHeader(obj,oh,&tags,1); -+- -+- yaffs_ReleaseTempBuffer(dev,buffer,__LINE__); -+- } -+- -+- /* Verify it has a parent */ -+- if(obj && !obj->fake && -+- (!obj->parent || obj->parent->myDev != dev)){ -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("Obj %d has parent pointer %p which does not look like an object"TENDSTR), -+- obj->objectId,obj->parent)); -+- } -+- -+- /* Verify parent is a directory */ -+- if(obj->parent && obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){ -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("Obj %d's parent is not a directory (type %d)"TENDSTR), -+- obj->objectId,obj->parent->variantType)); -+- } -+- -+- switch(obj->variantType){ -+- case YAFFS_OBJECT_TYPE_FILE: -+- yaffs_VerifyFile(obj); -+- break; -+- case YAFFS_OBJECT_TYPE_SYMLINK: -+- yaffs_VerifySymlink(obj); -+- break; -+- case YAFFS_OBJECT_TYPE_DIRECTORY: -+- yaffs_VerifyDirectory(obj); -+- break; -+- case YAFFS_OBJECT_TYPE_HARDLINK: -+- yaffs_VerifyHardLink(obj); -+- break; -+- case YAFFS_OBJECT_TYPE_SPECIAL: -+- yaffs_VerifySpecial(obj); -+- break; -+- case YAFFS_OBJECT_TYPE_UNKNOWN: -+- default: -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("Obj %d has illegaltype %d"TENDSTR), -+- obj->objectId,obj->variantType)); -+- break; -+- } -+- -+- -+-} -+- -+-static void yaffs_VerifyObjects(yaffs_Device *dev) -+-{ -+- yaffs_Object *obj; -+- int i; -+- struct list_head *lh; -+- -+- if(yaffs_SkipVerification(dev)) -+- return; -+- -+- /* Iterate through the objects in each hash entry */ -+- -+- for(i = 0; i < YAFFS_NOBJECT_BUCKETS; i++){ -+- list_for_each(lh, &dev->objectBucket[i].list) { -+- if (lh) { -+- obj = list_entry(lh, yaffs_Object, hashLink); -+- yaffs_VerifyObject(obj); -+- } -+- } -+- } -+- -+-} -+- -+- -+ /* -+ * Simple hash function. Needs to have a reasonable spread -+ */ -+- -++ -+ static Y_INLINE int yaffs_HashFunction(int n) -+ { -+ n = abs(n); -+@@ -861,7 +332,7 @@ -+ /* -+ * Access functions to useful fake objects -+ */ -+- -++ -+ yaffs_Object *yaffs_Root(yaffs_Device * dev) -+ { -+ return dev->rootDir; -+@@ -876,7 +347,7 @@ -+ /* -+ * Erased NAND checking functions -+ */ -+- -++ -+ int yaffs_CheckFF(__u8 * buffer, int nBytes) -+ { -+ /* Horrible, slow implementation */ -+@@ -898,10 +369,10 @@ -+ int result; -+ -+ result = yaffs_ReadChunkWithTagsFromNAND(dev, chunkInNAND, data, &tags); -+- -++ -+ if(tags.eccResult > YAFFS_ECC_RESULT_NO_ERROR) -+ retval = YAFFS_FAIL; -+- -++ -+ -+ if (!yaffs_CheckFF(data, dev->nDataBytesPerChunk) || tags.chunkUsed) { -+ T(YAFFS_TRACE_NANDACCESS, -+@@ -915,90 +386,91 @@ -+ -+ } -+ -+- -+ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, -+ const __u8 * data, -+ yaffs_ExtendedTags * tags, -+ int useReserve) -+ { -+- int attempts = 0; -+- int writeOk = 0; -+ int chunk; -+ -++ int writeOk = 0; -++ int erasedOk = 1; -++ int attempts = 0; -++ yaffs_BlockInfo *bi; -++ -+ yaffs_InvalidateCheckpoint(dev); -+ -+ do { -+- yaffs_BlockInfo *bi = 0; -+- int erasedOk = 0; -++ chunk = yaffs_AllocateChunk(dev, useReserve,&bi); -+ -+- chunk = yaffs_AllocateChunk(dev, useReserve, &bi); -+- if (chunk < 0) { -+- /* no space */ -+- break; -+- } -+- -+- /* First check this chunk is erased, if it needs -+- * checking. The checking policy (unless forced -+- * always on) is as follows: -+- * -+- * Check the first page we try to write in a block. -+- * If the check passes then we don't need to check any -+- * more. If the check fails, we check again... -+- * If the block has been erased, we don't need to check. -+- * -+- * However, if the block has been prioritised for gc, -+- * then we think there might be something odd about -+- * this block and stop using it. -+- * -+- * Rationale: We should only ever see chunks that have -+- * not been erased if there was a partially written -+- * chunk due to power loss. This checking policy should -+- * catch that case with very few checks and thus save a -+- * lot of checks that are most likely not needed. -+- */ -+- if (bi->gcPrioritise) { -+- yaffs_DeleteChunk(dev, chunk, 1, __LINE__); -+- /* try another chunk */ -+- continue; -+- } -++ if (chunk >= 0) { -++ /* First check this chunk is erased, if it needs checking. -++ * The checking policy (unless forced always on) is as follows: -++ * Check the first page we try to write in a block. -++ * - If the check passes then we don't need to check any more. -++ * - If the check fails, we check again... -++ * If the block has been erased, we don't need to check. -++ * -++ * However, if the block has been prioritised for gc, then -++ * we think there might be something odd about this block -++ * and stop using it. -++ * -++ * Rationale: -++ * We should only ever see chunks that have not been erased -++ * if there was a partially written chunk due to power loss -++ * This checking policy should catch that case with very -++ * few checks and thus save a lot of checks that are most likely not -++ * needed. -++ */ -++ -++ if(bi->gcPrioritise){ -++ yaffs_DeleteChunk(dev, chunk, 1, __LINE__); -++ } else { -++#ifdef CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED -+ -+- /* let's give it a try */ -+- attempts++; -++ bi->skipErasedCheck = 0; -+ -+-#ifdef CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED -+- bi->skipErasedCheck = 0; -+ #endif -+- if (!bi->skipErasedCheck) { -+- erasedOk = yaffs_CheckChunkErased(dev, chunk); -+- if (erasedOk != YAFFS_OK) { -+- T(YAFFS_TRACE_ERROR, -+- (TSTR ("**>> yaffs chunk %d was not erased" -+- TENDSTR), chunk)); -++ if(!bi->skipErasedCheck){ -++ erasedOk = yaffs_CheckChunkErased(dev, chunk); -++ if(erasedOk && !bi->gcPrioritise) -++ bi->skipErasedCheck = 1; -++ } -+ -+- /* try another chunk */ -+- continue; -++ if (!erasedOk) { -++ T(YAFFS_TRACE_ERROR, -++ (TSTR -++ ("**>> yaffs chunk %d was not erased" -++ TENDSTR), chunk)); -++ } else { -++ writeOk = -++ yaffs_WriteChunkWithTagsToNAND(dev, chunk, -++ data, tags); -++ } -++ -++ attempts++; -++ -++ if (writeOk) { -++ /* -++ * Copy the data into the robustification buffer. -++ * NB We do this at the end to prevent duplicates in the case of a write error. -++ * Todo -++ */ -++ yaffs_HandleWriteChunkOk(dev, chunk, data, tags); -++ -++ } else { -++ /* The erased check or write failed */ -++ yaffs_HandleWriteChunkError(dev, chunk, erasedOk); -++ } -+ } -+- bi->skipErasedCheck = 1; -+ } -+ -+- writeOk = yaffs_WriteChunkWithTagsToNAND(dev, chunk, -+- data, tags); -+- if (writeOk != YAFFS_OK) { -+- yaffs_HandleWriteChunkError(dev, chunk, erasedOk); -+- /* try another chunk */ -+- continue; -+- } -+- -+- /* Copy the data into the robustification buffer */ -+- yaffs_HandleWriteChunkOk(dev, chunk, data, tags); -+- -+- } while (writeOk != YAFFS_OK && attempts < yaffs_wr_attempts); -++ } while (chunk >= 0 && !writeOk); -+ -+ if (attempts > 1) { -+ T(YAFFS_TRACE_ERROR, -+- (TSTR("**>> yaffs write required %d attempts" TENDSTR), -+- attempts)); -+- -++ (TSTR("**>> yaffs write required %d attempts" TENDSTR), -++ attempts)); -+ dev->nRetriedWrites += (attempts - 1); -+ } -+ -+@@ -1008,13 +480,13 @@ -+ /* -+ * Block retiring for handling a broken block. -+ */ -+- -++ -+ static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND) -+ { -+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND); -+ -+ yaffs_InvalidateCheckpoint(dev); -+- -++ -+ yaffs_MarkBlockBad(dev, blockInNAND); -+ -+ bi->blockState = YAFFS_BLOCK_STATE_DEAD; -+@@ -1028,7 +500,7 @@ -+ * Functions for robustisizing TODO -+ * -+ */ -+- -++ -+ static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND, -+ const __u8 * data, -+ const yaffs_ExtendedTags * tags) -+@@ -1046,13 +518,28 @@ -+ bi->gcPrioritise = 1; -+ dev->hasPendingPrioritisedGCs = 1; -+ bi->chunkErrorStrikes ++; -+- -++ -+ if(bi->chunkErrorStrikes > 3){ -+ bi->needsRetiring = 1; /* Too many stikes, so retire this */ -+ T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Block struck out" TENDSTR))); -+ -+ } -++ -++ } -++} -+ -++static void yaffs_ReportOddballBlocks(yaffs_Device *dev) -++{ -++ int i; -++ -++ for(i = dev->internalStartBlock; i <= dev->internalEndBlock && (yaffs_traceMask & YAFFS_TRACE_BAD_BLOCKS); i++){ -++ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i); -++ if(bi->needsRetiring || bi->gcPrioritise) -++ T(YAFFS_TRACE_BAD_BLOCKS,(TSTR("yaffs block %d%s%s" TENDSTR), -++ i, -++ bi->needsRetiring ? " needs retiring" : "", -++ bi->gcPrioritise ? " gc prioritised" : "")); -++ -+ } -+ } -+ -+@@ -1061,25 +548,22 @@ -+ -+ int blockInNAND = chunkInNAND / dev->nChunksPerBlock; -+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND); -+- -++ -+ yaffs_HandleChunkError(dev,bi); -+- -+- -++ -+ if(erasedOk ) { -+ /* Was an actual write failure, so mark the block for retirement */ -+ bi->needsRetiring = 1; -+ T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, -+ (TSTR("**>> Block %d needs retiring" TENDSTR), blockInNAND)); -+- -+- -+ } -+- -++ -+ /* Delete the chunk */ -+ yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__); -+ } -+ -+ -+-/*---------------- Name handling functions ------------*/ -++/*---------------- Name handling functions ------------*/ -+ -+ static __u16 yaffs_CalcNameSum(const YCHAR * name) -+ { -+@@ -1088,7 +572,7 @@ -+ -+ YUCHAR *bname = (YUCHAR *) name; -+ if (bname) { -+- while ((*bname) && (i < (YAFFS_MAX_NAME_LENGTH/2))) { -++ while ((*bname) && (i <= YAFFS_MAX_NAME_LENGTH)) { -+ -+ #ifdef CONFIG_YAFFS_CASE_INSENSITIVE -+ sum += yaffs_toupper(*bname) * i; -+@@ -1120,7 +604,7 @@ -+ * The list is hooked together using the first pointer -+ * in the tnode. -+ */ -+- -++ -+ /* yaffs_CreateTnodes creates a bunch more tnodes and -+ * adds them to the tnode free list. -+ * Don't use this function directly -+@@ -1138,7 +622,7 @@ -+ -+ if (nTnodes < 1) -+ return YAFFS_OK; -+- -++ -+ /* Calculate the tnode size in bytes for variable width tnode support. -+ * Must be a multiple of 32-bits */ -+ tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; -+@@ -1175,7 +659,7 @@ -+ next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize]; -+ curr->internal[0] = next; -+ } -+- -++ -+ curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * tnodeSize]; -+ curr->internal[0] = dev->freeTnodes; -+ dev->freeTnodes = (yaffs_Tnode *)mem; -+@@ -1190,13 +674,12 @@ -+ * NB If we can't add this to the management list it isn't fatal -+ * but it just means we can't free this bunch of tnodes later. -+ */ -+- -++ -+ tnl = YMALLOC(sizeof(yaffs_TnodeList)); -+ if (!tnl) { -+ T(YAFFS_TRACE_ERROR, -+ (TSTR -+ ("yaffs: Could not add tnodes to management list" TENDSTR))); -+- return YAFFS_FAIL; -+ -+ } else { -+ tnl->tnodes = newTnodes; -+@@ -1239,11 +722,11 @@ -+ static yaffs_Tnode *yaffs_GetTnode(yaffs_Device * dev) -+ { -+ yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev); -+- -++ -+ if(tn) -+ memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); -+ -+- return tn; -++ return tn; -+ } -+ -+ /* FreeTnode frees up a tnode and puts it back on the free list */ -+@@ -1299,19 +782,19 @@ -+ __u32 bitInWord; -+ __u32 wordInMap; -+ __u32 mask; -+- -++ -+ pos &= YAFFS_TNODES_LEVEL0_MASK; -+ val >>= dev->chunkGroupBits; -+- -++ -+ bitInMap = pos * dev->tnodeWidth; -+ wordInMap = bitInMap /32; -+ bitInWord = bitInMap & (32 -1); -+- -++ -+ mask = dev->tnodeMask << bitInWord; -+- -++ -+ map[wordInMap] &= ~mask; -+ map[wordInMap] |= (mask & (val << bitInWord)); -+- -++ -+ if(dev->tnodeWidth > (32-bitInWord)) { -+ bitInWord = (32 - bitInWord); -+ wordInMap++;; -+@@ -1321,31 +804,31 @@ -+ } -+ } -+ -+-static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos) -++__u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos) -+ { -+ __u32 *map = (__u32 *)tn; -+ __u32 bitInMap; -+ __u32 bitInWord; -+ __u32 wordInMap; -+ __u32 val; -+- -++ -+ pos &= YAFFS_TNODES_LEVEL0_MASK; -+- -++ -+ bitInMap = pos * dev->tnodeWidth; -+ wordInMap = bitInMap /32; -+ bitInWord = bitInMap & (32 -1); -+- -++ -+ val = map[wordInMap] >> bitInWord; -+- -++ -+ if(dev->tnodeWidth > (32-bitInWord)) { -+ bitInWord = (32 - bitInWord); -+ wordInMap++;; -+ val |= (map[wordInMap] << bitInWord); -+ } -+- -++ -+ val &= dev->tnodeMask; -+ val <<= dev->chunkGroupBits; -+- -++ -+ return val; -+ } -+ -+@@ -1394,7 +877,7 @@ -+ while (level > 0 && tn) { -+ tn = tn-> -+ internal[(chunkId >> -+- ( YAFFS_TNODES_LEVEL0_BITS + -++ ( YAFFS_TNODES_LEVEL0_BITS + -+ (level - 1) * -+ YAFFS_TNODES_INTERNAL_BITS) -+ ) & -+@@ -1416,7 +899,7 @@ -+ * If the tn argument is NULL, then a fresh tnode will be added otherwise the specified tn will -+ * be plugged into the ttree. -+ */ -+- -++ -+ static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device * dev, -+ yaffs_FileStructure * fStruct, -+ __u32 chunkId, -+@@ -1453,7 +936,7 @@ -+ if (requiredTallness > fStruct->topLevel) { -+ /* Not tall enough,gotta make the tree taller */ -+ for (i = fStruct->topLevel; i < requiredTallness; i++) { -+- -++ -+ tn = yaffs_GetTnode(dev); -+ -+ if (tn) { -+@@ -1472,7 +955,7 @@ -+ -+ l = fStruct->topLevel; -+ tn = fStruct->top; -+- -++ -+ if(l > 0) { -+ while (l > 0 && tn) { -+ x = (chunkId >> -+@@ -1492,13 +975,13 @@ -+ if(tn->internal[x]) -+ yaffs_FreeTnode(dev,tn->internal[x]); -+ tn->internal[x] = passedTn; -+- -++ -+ } else if(!tn->internal[x]) { -+ /* Don't have one, none passed in */ -+ tn->internal[x] = yaffs_GetTnode(dev); -+ } -+ } -+- -++ -+ tn = tn->internal[x]; -+ l--; -+ } -+@@ -1539,7 +1022,7 @@ -+ -+ /* DeleteWorker scans backwards through the tnode tree and deletes all the -+ * chunks and tnodes in the file -+- * Returns 1 if the tree was deleted. -++ * Returns 1 if the tree was deleted. -+ * Returns 0 if it stopped early due to hitting the limit and the delete is incomplete. -+ */ -+ -+@@ -1653,7 +1136,7 @@ -+ * of the tnode. -+ * Thus, essentially this is the same as DeleteWorker except that the chunks are soft deleted. -+ */ -+- -++ -+ static int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, -+ __u32 level, int chunkOffset) -+ { -+@@ -1694,7 +1177,7 @@ -+ theChunk = yaffs_GetChunkGroupBase(dev,tn,i); -+ if (theChunk) { -+ /* Note this does not find the real chunk, only the chunk group. -+- * We make an assumption that a chunk group is not larger than -++ * We make an assumption that a chunk group is not larger than -+ * a block. -+ */ -+ yaffs_SoftDeleteChunk(dev, theChunk); -+@@ -1796,7 +1279,7 @@ -+ /* Now we have a tree with all the non-zero branches NULL but the height -+ * is the same as it was. -+ * Let's see if we can trim internal tnodes to shorten the tree. -+- * We can do this if only the 0th element in the tnode is in use -++ * We can do this if only the 0th element in the tnode is in use -+ * (ie all the non-zero are NULL) -+ */ -+ -+@@ -1839,18 +1322,13 @@ -+ -+ /* make these things */ -+ newObjects = YMALLOC(nObjects * sizeof(yaffs_Object)); -+- list = YMALLOC(sizeof(yaffs_ObjectList)); -+ -+- if (!newObjects || !list) { -+- if(newObjects) -+- YFREE(newObjects); -+- if(list) -+- YFREE(list); -++ if (!newObjects) { -+ T(YAFFS_TRACE_ALLOCATE, -+ (TSTR("yaffs: Could not allocate more objects" TENDSTR))); -+ return YAFFS_FAIL; -+ } -+- -++ -+ /* Hook them into the free list */ -+ for (i = 0; i < nObjects - 1; i++) { -+ newObjects[i].siblings.next = -+@@ -1864,9 +1342,15 @@ -+ -+ /* Now add this bunch of Objects to a list for freeing up. */ -+ -+- list->objects = newObjects; -+- list->next = dev->allocatedObjectList; -+- dev->allocatedObjectList = list; -++ list = YMALLOC(sizeof(yaffs_ObjectList)); -++ if (!list) { -++ T(YAFFS_TRACE_ALLOCATE, -++ (TSTR("Could not add objects to management list" TENDSTR))); -++ } else { -++ list->objects = newObjects; -++ list->next = dev->allocatedObjectList; -++ dev->allocatedObjectList = list; -++ } -+ -+ return YAFFS_OK; -+ } -+@@ -2123,25 +1607,12 @@ -+ { -+ -+ yaffs_Object *theObject; -+- yaffs_Tnode *tn; -+ -+ if (number < 0) { -+ number = yaffs_CreateNewObjectNumber(dev); -+ } -+ -+ theObject = yaffs_AllocateEmptyObject(dev); -+- if(!theObject) -+- return NULL; -+- -+- if(type == YAFFS_OBJECT_TYPE_FILE){ -+- tn = yaffs_GetTnode(dev); -+- if(!tn){ -+- yaffs_FreeObject(theObject); -+- return NULL; -+- } -+- } -+- -+- -+ -+ if (theObject) { -+ theObject->fake = 0; -+@@ -2168,7 +1639,8 @@ -+ theObject->variant.fileVariant.scannedFileSize = 0; -+ theObject->variant.fileVariant.shrinkSize = 0xFFFFFFFF; /* max __u32 */ -+ theObject->variant.fileVariant.topLevel = 0; -+- theObject->variant.fileVariant.top = tn; -++ theObject->variant.fileVariant.top = -++ yaffs_GetTnode(dev); -+ break; -+ case YAFFS_OBJECT_TYPE_DIRECTORY: -+ INIT_LIST_HEAD(&theObject->variant.directoryVariant. -+@@ -2205,7 +1677,7 @@ -+ return theObject; -+ -+ } -+- -++ -+ -+ static YCHAR *yaffs_CloneString(const YCHAR * str) -+ { -+@@ -2213,8 +1685,7 @@ -+ -+ if (str && *str) { -+ newStr = YMALLOC((yaffs_strlen(str) + 1) * sizeof(YCHAR)); -+- if(newStr) -+- yaffs_strcpy(newStr, str); -++ yaffs_strcpy(newStr, str); -+ } -+ -+ return newStr; -+@@ -2227,7 +1698,7 @@ -+ * aliasString only has meaning for a sumlink. -+ * rdev only has meaning for devices (a subset of special objects) -+ */ -+- -++ -+ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type, -+ yaffs_Object * parent, -+ const YCHAR * name, -+@@ -2238,7 +1709,6 @@ -+ const YCHAR * aliasString, __u32 rdev) -+ { -+ yaffs_Object *in; -+- YCHAR *str; -+ -+ yaffs_Device *dev = parent->myDev; -+ -+@@ -2249,16 +1719,6 @@ -+ -+ in = yaffs_CreateNewObject(dev, -1, type); -+ -+- if(type == YAFFS_OBJECT_TYPE_SYMLINK){ -+- str = yaffs_CloneString(aliasString); -+- if(!str){ -+- yaffs_FreeObject(in); -+- return NULL; -+- } -+- } -+- -+- -+- -+ if (in) { -+ in->chunkId = -1; -+ in->valid = 1; -+@@ -2289,7 +1749,8 @@ -+ -+ switch (type) { -+ case YAFFS_OBJECT_TYPE_SYMLINK: -+- in->variant.symLinkVariant.alias = str; -++ in->variant.symLinkVariant.alias = -++ yaffs_CloneString(aliasString); -+ break; -+ case YAFFS_OBJECT_TYPE_HARDLINK: -+ in->variant.hardLinkVariant.equivalentObject = -+@@ -2298,7 +1759,7 @@ -+ equivalentObject->objectId; -+ list_add(&in->hardLinks, &equivalentObject->hardLinks); -+ break; -+- case YAFFS_OBJECT_TYPE_FILE: -++ case YAFFS_OBJECT_TYPE_FILE: -+ case YAFFS_OBJECT_TYPE_DIRECTORY: -+ case YAFFS_OBJECT_TYPE_SPECIAL: -+ case YAFFS_OBJECT_TYPE_UNKNOWN: -+@@ -2382,7 +1843,7 @@ -+ TENDSTR))); -+ YBUG(); -+ } -+- -++ -+ /* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */ -+ if (obj->myDev->isYaffs2) { -+ unlinkOp = (newDir == obj->myDev->unlinkedDir); -+@@ -2395,9 +1856,9 @@ -+ -+ existingTarget = yaffs_FindObjectByName(newDir, newName); -+ -+- /* If the object is a file going into the unlinked directory, -++ /* If the object is a file going into the unlinked directory, -+ * then it is OK to just stuff it in since duplicate names are allowed. -+- * else only proceed if the new name does not exist and if we're putting -++ * else only proceed if the new name does not exist and if we're putting -+ * it into a directory. -+ */ -+ if ((unlinkOp || -+@@ -2461,7 +1922,7 @@ -+ /* There is a target that is a non-empty directory, so we fail */ -+ return YAFFS_FAIL; /* EEXIST or ENOTEMPTY */ -+ } else if (existingTarget && existingTarget != obj) { -+- /* Nuke the target first, using shadowing, -++ /* Nuke the target first, using shadowing, -+ * but only if it isn't the same object -+ */ -+ yaffs_ChangeObjectName(obj, newDir, newName, force, -+@@ -2479,13 +1940,10 @@ -+ static int yaffs_InitialiseBlocks(yaffs_Device * dev) -+ { -+ int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1; -+- -+- dev->blockInfo = NULL; -+- dev->chunkBits = NULL; -+- -++ -+ dev->allocationBlock = -1; /* force it to get a new one */ -+ -+- /* If the first allocation strategy fails, thry the alternate one */ -++ /* Todo we're assuming the malloc will pass. */ -+ dev->blockInfo = YMALLOC(nBlocks * sizeof(yaffs_BlockInfo)); -+ if(!dev->blockInfo){ -+ dev->blockInfo = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockInfo)); -+@@ -2493,20 +1951,17 @@ -+ } -+ else -+ dev->blockInfoAlt = 0; -+- -+- if(dev->blockInfo){ -+- -+- /* Set up dynamic blockinfo stuff. */ -+- dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; /* round up bytes */ -+- dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks); -+- if(!dev->chunkBits){ -+- dev->chunkBits = YMALLOC_ALT(dev->chunkBitmapStride * nBlocks); -+- dev->chunkBitsAlt = 1; -+- } -+- else -+- dev->chunkBitsAlt = 0; -++ -++ /* Set up dynamic blockinfo stuff. */ -++ dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; /* round up bytes */ -++ dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks); -++ if(!dev->chunkBits){ -++ dev->chunkBits = YMALLOC_ALT(dev->chunkBitmapStride * nBlocks); -++ dev->chunkBitsAlt = 1; -+ } -+- -++ else -++ dev->chunkBitsAlt = 0; -++ -+ if (dev->blockInfo && dev->chunkBits) { -+ memset(dev->blockInfo, 0, nBlocks * sizeof(yaffs_BlockInfo)); -+ memset(dev->chunkBits, 0, dev->chunkBitmapStride * nBlocks); -+@@ -2519,18 +1974,17 @@ -+ -+ static void yaffs_DeinitialiseBlocks(yaffs_Device * dev) -+ { -+- if(dev->blockInfoAlt && dev->blockInfo) -++ if(dev->blockInfoAlt) -+ YFREE_ALT(dev->blockInfo); -+- else if(dev->blockInfo) -++ else -+ YFREE(dev->blockInfo); -+- -+ dev->blockInfoAlt = 0; -+ -+ dev->blockInfo = NULL; -+- -+- if(dev->chunkBitsAlt && dev->chunkBits) -++ -++ if(dev->chunkBitsAlt) -+ YFREE_ALT(dev->chunkBits); -+- else if(dev->chunkBits) -++ else -+ YFREE(dev->chunkBits); -+ dev->chunkBitsAlt = 0; -+ dev->chunkBits = NULL; -+@@ -2587,18 +2041,17 @@ -+ int i; -+ int iterations; -+ int dirtiest = -1; -+- int pagesInUse = 0; -++ int pagesInUse; -+ int prioritised=0; -+ yaffs_BlockInfo *bi; -++ static int nonAggressiveSkip = 0; -+ int pendingPrioritisedExist = 0; -+- -++ -+ /* First let's see if we need to grab a prioritised block */ -+ if(dev->hasPendingPrioritisedGCs){ -+ for(i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++){ -+ -+ bi = yaffs_GetBlockInfo(dev, i); -+- //yaffs_VerifyBlock(dev,bi,i); -+- -+ if(bi->gcPrioritise) { -+ pendingPrioritisedExist = 1; -+ if(bi->blockState == YAFFS_BLOCK_STATE_FULL && -+@@ -2610,7 +2063,7 @@ -+ } -+ } -+ } -+- -++ -+ if(!pendingPrioritisedExist) /* None found, so we can clear this */ -+ dev->hasPendingPrioritisedGCs = 0; -+ } -+@@ -2621,9 +2074,9 @@ -+ * block has only a few pages in use. -+ */ -+ -+- dev->nonAggressiveSkip--; -++ nonAggressiveSkip--; -+ -+- if (!aggressive && (dev->nonAggressiveSkip > 0)) { -++ if (!aggressive && (nonAggressiveSkip > 0)) { -+ return -1; -+ } -+ -+@@ -2662,7 +2115,7 @@ -+ dirtiest = b; -+ pagesInUse = 0; -+ } -+- else -++ else -+ #endif -+ -+ if (bi->blockState == YAFFS_BLOCK_STATE_FULL && -+@@ -2684,7 +2137,7 @@ -+ dev->oldestDirtySequence = 0; -+ -+ if (dirtiest > 0) { -+- dev->nonAggressiveSkip = 4; -++ nonAggressiveSkip = 4; -+ } -+ -+ return dirtiest; -+@@ -2699,11 +2152,11 @@ -+ /* If the block is still healthy erase it and mark as clean. -+ * If the block has had a data failure, then retire it. -+ */ -+- -++ -+ T(YAFFS_TRACE_GC | YAFFS_TRACE_ERASE, -+ (TSTR("yaffs_BlockBecameDirty block %d state %d %s"TENDSTR), -+ blockNo, bi->blockState, (bi->needsRetiring) ? "needs retiring" : "")); -+- -++ -+ bi->blockState = YAFFS_BLOCK_STATE_DIRTY; -+ -+ if (!bi->needsRetiring) { -+@@ -2716,8 +2169,7 @@ -+ } -+ } -+ -+- if (erasedOk && -+- ((yaffs_traceMask & YAFFS_TRACE_ERASE) || !yaffs_SkipVerification(dev))) { -++ if (erasedOk && (yaffs_traceMask & YAFFS_TRACE_ERASE)) { -+ int i; -+ for (i = 0; i < dev->nChunksPerBlock; i++) { -+ if (!yaffs_CheckChunkErased -+@@ -2767,7 +2219,7 @@ -+ -+ return -1; -+ } -+- -++ -+ /* Find an empty block. */ -+ -+ for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) { -+@@ -2808,13 +2260,13 @@ -+ int reservedChunks; -+ int reservedBlocks = dev->nReservedBlocks; -+ int checkpointBlocks; -+- -++ -+ checkpointBlocks = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint; -+ if(checkpointBlocks < 0) -+ checkpointBlocks = 0; -+- -++ -+ reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock); -+- -++ -+ return (dev->nFreeChunks > reservedChunks); -+ } -+ -+@@ -2861,10 +2313,10 @@ -+ -+ if(blockUsedPtr) -+ *blockUsedPtr = bi; -+- -++ -+ return retVal; -+ } -+- -++ -+ T(YAFFS_TRACE_ERROR, -+ (TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR))); -+ -+@@ -2895,7 +2347,6 @@ -+ int cleanups = 0; -+ int i; -+ int isCheckpointBlock; -+- int matchingChunk; -+ -+ int chunksBefore = yaffs_GetErasedChunks(dev); -+ int chunksAfter; -+@@ -2907,7 +2358,7 @@ -+ yaffs_Object *object; -+ -+ isCheckpointBlock = (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT); -+- -++ -+ bi->blockState = YAFFS_BLOCK_STATE_COLLECTING; -+ -+ T(YAFFS_TRACE_TRACING, -+@@ -2936,8 +2387,6 @@ -+ -+ __u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__); -+ -+- yaffs_VerifyBlock(dev,bi,block); -+- -+ for (chunkInBlock = 0, oldChunk = block * dev->nChunksPerBlock; -+ chunkInBlock < dev->nChunksPerBlock -+ && yaffs_StillSomeChunkBits(dev, block); -+@@ -2963,34 +2412,18 @@ -+ chunkInBlock, tags.objectId, tags.chunkId, -+ tags.byteCount)); -+ -+- if(object && !yaffs_SkipVerification(dev)){ -+- if(tags.chunkId == 0) -+- matchingChunk = object->chunkId; -+- else if(object->softDeleted) -+- matchingChunk = oldChunk; /* Defeat the test */ -+- else -+- matchingChunk = yaffs_FindChunkInFile(object,tags.chunkId,NULL); -+- -+- if(oldChunk != matchingChunk) -+- T(YAFFS_TRACE_ERROR, -+- (TSTR("gc: page in gc mismatch: %d %d %d %d"TENDSTR), -+- oldChunk,matchingChunk,tags.objectId, tags.chunkId)); -+- -+- } -+- -+ if (!object) { -+ T(YAFFS_TRACE_ERROR, -+ (TSTR -+- ("page %d in gc has no object: %d %d %d " -+- TENDSTR), oldChunk, -+- tags.objectId, tags.chunkId, tags.byteCount)); -++ ("page %d in gc has no object " -++ TENDSTR), oldChunk)); -+ } -+ -+ if (object && object->deleted -+ && tags.chunkId != 0) { -+ /* Data chunk in a deleted file, throw it away -+ * It's a soft deleted data chunk, -+- * No need to copy this, just forget about it and -++ * No need to copy this, just forget about it and -+ * fix up the object. -+ */ -+ -+@@ -3040,8 +2473,6 @@ -+ oh->shadowsObject = -1; -+ tags.extraShadows = 0; -+ tags.extraIsShrinkHeader = 0; -+- -+- yaffs_VerifyObjectHeader(object,oh,&tags,1); -+ } -+ -+ newChunk = -+@@ -3098,8 +2529,6 @@ -+ -+ } -+ -+- yaffs_VerifyCollectedBlock(dev,bi,block); -+- -+ if (chunksBefore >= (chunksAfter = yaffs_GetErasedChunks(dev))) { -+ T(YAFFS_TRACE_GC, -+ (TSTR -+@@ -3127,26 +2556,26 @@ -+ int aggressive; -+ int gcOk = YAFFS_OK; -+ int maxTries = 0; -+- -++ -+ int checkpointBlockAdjust; -+ -+ if (dev->isDoingGC) { -+ /* Bail out so we don't get recursive gc */ -+ return YAFFS_OK; -+ } -+- -++ -+ /* This loop should pass the first time. -+ * We'll only see looping here if the erase of the collected block fails. -+ */ -+ -+ do { -+ maxTries++; -+- -++ -+ checkpointBlockAdjust = (dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint); -+ if(checkpointBlockAdjust < 0) -+ checkpointBlockAdjust = 0; -+ -+- if (dev->nErasedBlocks < (dev->nReservedBlocks + checkpointBlockAdjust + 2)) { -++ if (dev->nErasedBlocks < (dev->nReservedBlocks + checkpointBlockAdjust)) { -+ /* We need a block soon...*/ -+ aggressive = 1; -+ } else { -+@@ -3326,11 +2755,11 @@ -+ static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode, -+ int chunkInNAND, int inScan) -+ { -+- /* NB inScan is zero unless scanning. -+- * For forward scanning, inScan is > 0; -++ /* NB inScan is zero unless scanning. -++ * For forward scanning, inScan is > 0; -+ * for backward scanning inScan is < 0 -+ */ -+- -++ -+ yaffs_Tnode *tn; -+ yaffs_Device *dev = in->myDev; -+ int existingChunk; -+@@ -3354,7 +2783,7 @@ -+ return YAFFS_OK; -+ } -+ -+- tn = yaffs_AddOrFindLevel0Tnode(dev, -++ tn = yaffs_AddOrFindLevel0Tnode(dev, -+ &in->variant.fileVariant, -+ chunkInInode, -+ NULL); -+@@ -3366,7 +2795,7 @@ -+ -+ if (inScan != 0) { -+ /* If we're scanning then we need to test for duplicates -+- * NB This does not need to be efficient since it should only ever -++ * NB This does not need to be efficient since it should only ever -+ * happen when the power fails during a write, then only one -+ * chunk should ever be affected. -+ * -+@@ -3407,7 +2836,7 @@ -+ -+ } -+ -+- /* NB The deleted flags should be false, otherwise the chunks will -++ /* NB The deleted flags should be false, otherwise the chunks will -+ * not be loaded during a scan -+ */ -+ -+@@ -3418,7 +2847,7 @@ -+ (in->myDev->isYaffs2 || -+ existingChunk <= 0 || -+ ((existingSerial + 1) & 3) == newSerial)) { -+- /* Forward scanning. -++ /* Forward scanning. -+ * Use new -+ * Delete the old one and drop through to update the tnode -+ */ -+@@ -3459,7 +2888,7 @@ -+ (TSTR("Chunk %d not found zero instead" TENDSTR), -+ chunkInNAND)); -+ /* get sane (zero) data if you read a hole */ -+- memset(buffer, 0, in->myDev->nDataBytesPerChunk); -++ memset(buffer, 0, in->myDev->nDataBytesPerChunk); -+ return 0; -+ } -+ -+@@ -3475,17 +2904,10 @@ -+ if (chunkId <= 0) -+ return; -+ -+- -+ dev->nDeletions++; -+ block = chunkId / dev->nChunksPerBlock; -+ page = chunkId % dev->nChunksPerBlock; -+ -+- -+- if(!yaffs_CheckChunkBit(dev,block,page)) -+- T(YAFFS_TRACE_VERIFY, -+- (TSTR("Deleting invalid chunk %d"TENDSTR), -+- chunkId)); -+- -+ bi = yaffs_GetBlockInfo(dev, block); -+ -+ T(YAFFS_TRACE_DELETION, -+@@ -3596,19 +3018,15 @@ -+ -+ int newChunkId; -+ yaffs_ExtendedTags newTags; -+- yaffs_ExtendedTags oldTags; -+ -+ __u8 *buffer = NULL; -+ YCHAR oldName[YAFFS_MAX_NAME_LENGTH + 1]; -+ -+ yaffs_ObjectHeader *oh = NULL; -+ -+- yaffs_strcpy(oldName,"silly old name"); -+- -+ if (!in->fake || force) { -+ -+ yaffs_CheckGarbageCollection(dev); -+- yaffs_CheckObjectDetailsLoaded(in); -+ -+ buffer = yaffs_GetTempBuffer(in->myDev, __LINE__); -+ oh = (yaffs_ObjectHeader *) buffer; -+@@ -3617,10 +3035,7 @@ -+ -+ if (prevChunkId >= 0) { -+ result = yaffs_ReadChunkWithTagsFromNAND(dev, prevChunkId, -+- buffer, &oldTags); -+- -+- yaffs_VerifyObjectHeader(in,oh,&oldTags,0); -+- -++ buffer, NULL); -+ memcpy(oldName, oh->name, sizeof(oh->name)); -+ } -+ -+@@ -3654,7 +3069,7 @@ -+ if (name && *name) { -+ memset(oh->name, 0, sizeof(oh->name)); -+ yaffs_strncpy(oh->name, name, YAFFS_MAX_NAME_LENGTH); -+- } else if (prevChunkId>=0) { -++ } else if (prevChunkId) { -+ memcpy(oh->name, oldName, sizeof(oh->name)); -+ } else { -+ memset(oh->name, 0, sizeof(oh->name)); -+@@ -3708,8 +3123,6 @@ -+ newTags.extraShadows = (oh->shadowsObject > 0) ? 1 : 0; -+ newTags.extraObjectType = in->variantType; -+ -+- yaffs_VerifyObjectHeader(in,oh,&newTags,1); -+- -+ /* Create new chunk in NAND */ -+ newChunkId = -+ yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags, -+@@ -3748,11 +3161,11 @@ -+ -+ /*------------------------ Short Operations Cache ---------------------------------------- -+ * In many situations where there is no high level buffering (eg WinCE) a lot of -+- * reads might be short sequential reads, and a lot of writes may be short -++ * reads might be short sequential reads, and a lot of writes may be short -+ * sequential writes. eg. scanning/writing a jpeg file. -+- * In these cases, a short read/write cache can provide a huge perfomance benefit -++ * In these cases, a short read/write cache can provide a huge perfomance benefit -+ * with dumb-as-a-rock code. -+- * In Linux, the page cache provides read buffering aand the short op cache provides write -++ * In Linux, the page cache provides read buffering aand the short op cache provides write -+ * buffering. -+ * -+ * There are a limited number (~10) of cache chunks per device so that we don't -+@@ -3765,14 +3178,14 @@ -+ int i; -+ yaffs_ChunkCache *cache; -+ int nCaches = obj->myDev->nShortOpCaches; -+- -++ -+ for(i = 0; i < nCaches; i++){ -+ cache = &dev->srCache[i]; -+ if (cache->object == obj && -+ cache->dirty) -+ return 1; -+ } -+- -++ -+ return 0; -+ } -+ -+@@ -3838,7 +3251,7 @@ -+ yaffs_Object *obj; -+ int nCaches = dev->nShortOpCaches; -+ int i; -+- -++ -+ /* Find a dirty object in the cache and flush it... -+ * until there are no further dirty objects. -+ */ -+@@ -3848,18 +3261,18 @@ -+ if (dev->srCache[i].object && -+ dev->srCache[i].dirty) -+ obj = dev->srCache[i].object; -+- -++ -+ } -+ if(obj) -+ yaffs_FlushFilesChunkCache(obj); -+- -++ -+ } while(obj); -+- -++ -+ } -+ -+ -+ /* Grab us a cache chunk for use. -+- * First look for an empty one. -++ * First look for an empty one. -+ * Then look for the least recently used non-dirty one. -+ * Then look for the least recently used dirty one...., flush and look again. -+ */ -+@@ -3871,7 +3284,7 @@ -+ -+ if (dev->nShortOpCaches > 0) { -+ for (i = 0; i < dev->nShortOpCaches; i++) { -+- if (!dev->srCache[i].object) -++ if (!dev->srCache[i].object) -+ return &dev->srCache[i]; -+ } -+ -+@@ -4032,14 +3445,11 @@ -+ static int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev,int head) -+ { -+ yaffs_CheckpointValidity cp; -+- -+- memset(&cp,0,sizeof(cp)); -+- -+ cp.structType = sizeof(cp); -+ cp.magic = YAFFS_MAGIC; -+ cp.version = YAFFS_CHECKPOINT_VERSION; -+ cp.head = (head) ? 1 : 0; -+- -++ -+ return (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp))? -+ 1 : 0; -+ } -+@@ -4048,9 +3458,9 @@ -+ { -+ yaffs_CheckpointValidity cp; -+ int ok; -+- -++ -+ ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp)); -+- -++ -+ if(ok) -+ ok = (cp.structType == sizeof(cp)) && -+ (cp.magic == YAFFS_MAGIC) && -+@@ -4059,20 +3469,20 @@ -+ return ok ? 1 : 0; -+ } -+ -+-static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp, -++static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp, -+ yaffs_Device *dev) -+ { -+ cp->nErasedBlocks = dev->nErasedBlocks; -+ cp->allocationBlock = dev->allocationBlock; -+ cp->allocationPage = dev->allocationPage; -+ cp->nFreeChunks = dev->nFreeChunks; -+- -++ -+ cp->nDeletedFiles = dev->nDeletedFiles; -+ cp->nUnlinkedFiles = dev->nUnlinkedFiles; -+ cp->nBackgroundDeletions = dev->nBackgroundDeletions; -+ cp->sequenceNumber = dev->sequenceNumber; -+ cp->oldestDirtySequence = dev->oldestDirtySequence; -+- -++ -+ } -+ -+ static void yaffs_CheckpointDeviceToDevice(yaffs_Device *dev, -+@@ -4082,7 +3492,7 @@ -+ dev->allocationBlock = cp->allocationBlock; -+ dev->allocationPage = cp->allocationPage; -+ dev->nFreeChunks = cp->nFreeChunks; -+- -++ -+ dev->nDeletedFiles = cp->nDeletedFiles; -+ dev->nUnlinkedFiles = cp->nUnlinkedFiles; -+ dev->nBackgroundDeletions = cp->nBackgroundDeletions; -+@@ -4098,20 +3508,20 @@ -+ __u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1); -+ -+ int ok; -+- -++ -+ /* Write device runtime values*/ -+ yaffs_DeviceToCheckpointDevice(&cp,dev); -+ cp.structType = sizeof(cp); -+- -++ -+ ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp)); -+- -++ -+ /* Write block info */ -+ if(ok) { -+ nBytes = nBlocks * sizeof(yaffs_BlockInfo); -+ ok = (yaffs_CheckpointWrite(dev,dev->blockInfo,nBytes) == nBytes); -+ } -+- -+- /* Write chunk bits */ -++ -++ /* Write chunk bits */ -+ if(ok) { -+ nBytes = nBlocks * dev->chunkBitmapStride; -+ ok = (yaffs_CheckpointWrite(dev,dev->chunkBits,nBytes) == nBytes); -+@@ -4126,28 +3536,28 @@ -+ __u32 nBytes; -+ __u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1); -+ -+- int ok; -+- -++ int ok; -++ -+ ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp)); -+ if(!ok) -+ return 0; -+- -++ -+ if(cp.structType != sizeof(cp)) -+ return 0; -+- -+- -++ -++ -+ yaffs_CheckpointDeviceToDevice(dev,&cp); -+- -++ -+ nBytes = nBlocks * sizeof(yaffs_BlockInfo); -+- -++ -+ ok = (yaffs_CheckpointRead(dev,dev->blockInfo,nBytes) == nBytes); -+- -++ -+ if(!ok) -+ return 0; -+ nBytes = nBlocks * dev->chunkBitmapStride; -+- -++ -+ ok = (yaffs_CheckpointRead(dev,dev->chunkBits,nBytes) == nBytes); -+- -++ -+ return ok ? 1 : 0; -+ } -+ -+@@ -4158,7 +3568,7 @@ -+ cp->objectId = obj->objectId; -+ cp->parentId = (obj->parent) ? obj->parent->objectId : 0; -+ cp->chunkId = obj->chunkId; -+- cp->variantType = obj->variantType; -++ cp->variantType = obj->variantType; -+ cp->deleted = obj->deleted; -+ cp->softDeleted = obj->softDeleted; -+ cp->unlinked = obj->unlinked; -+@@ -4167,7 +3577,7 @@ -+ cp->unlinkAllowed = obj->unlinkAllowed; -+ cp->serial = obj->serial; -+ cp->nDataChunks = obj->nDataChunks; -+- -++ -+ if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) -+ cp->fileSizeOrEquivalentObjectId = obj->variant.fileVariant.fileSize; -+ else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) -+@@ -4178,9 +3588,9 @@ -+ { -+ -+ yaffs_Object *parent; -+- -++ -+ obj->objectId = cp->objectId; -+- -++ -+ if(cp->parentId) -+ parent = yaffs_FindOrCreateObjectByNumber( -+ obj->myDev, -+@@ -4188,12 +3598,12 @@ -+ YAFFS_OBJECT_TYPE_DIRECTORY); -+ else -+ parent = NULL; -+- -++ -+ if(parent) -+ yaffs_AddObjectToDirectory(parent, obj); -+- -++ -+ obj->chunkId = cp->chunkId; -+- obj->variantType = cp->variantType; -++ obj->variantType = cp->variantType; -+ obj->deleted = cp->deleted; -+ obj->softDeleted = cp->softDeleted; -+ obj->unlinked = cp->unlinked; -+@@ -4202,12 +3612,12 @@ -+ obj->unlinkAllowed = cp->unlinkAllowed; -+ obj->serial = cp->serial; -+ obj->nDataChunks = cp->nDataChunks; -+- -++ -+ if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) -+ obj->variant.fileVariant.fileSize = cp->fileSizeOrEquivalentObjectId; -+ else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) -+ obj->variant.hardLinkVariant.equivalentObjectId = cp->fileSizeOrEquivalentObjectId; -+- -++ -+ if(obj->objectId >= YAFFS_NOBJECT_BUCKETS) -+ obj->lazyLoaded = 1; -+ } -+@@ -4250,17 +3660,17 @@ -+ { -+ __u32 endMarker = ~0; -+ int ok = 1; -+- -++ -+ if(obj->variantType == YAFFS_OBJECT_TYPE_FILE){ -+ ok = yaffs_CheckpointTnodeWorker(obj, -+ obj->variant.fileVariant.top, -+ obj->variant.fileVariant.topLevel, -+ 0); -+ if(ok) -+- ok = (yaffs_CheckpointWrite(obj->myDev,&endMarker,sizeof(endMarker)) == -++ ok = (yaffs_CheckpointWrite(obj->myDev,&endMarker,sizeof(endMarker)) == -+ sizeof(endMarker)); -+ } -+- -++ -+ return ok ? 1 : 0; -+ } -+ -+@@ -4271,15 +3681,12 @@ -+ yaffs_Device *dev = obj->myDev; -+ yaffs_FileStructure *fileStructPtr = &obj->variant.fileVariant; -+ yaffs_Tnode *tn; -+- int nread = 0; -+- -++ -+ ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk)); -+- -++ -+ while(ok && (~baseChunk)){ -+- nread++; -+ /* Read level 0 tnode */ -+- -+- -++ -+ /* printf("read tnode at %d\n",baseChunk); */ -+ tn = yaffs_GetTnodeRaw(dev); -+ if(tn) -+@@ -4287,27 +3694,22 @@ -+ (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); -+ else -+ ok = 0; -+- -++ -+ if(tn && ok){ -+ ok = yaffs_AddOrFindLevel0Tnode(dev, -+ fileStructPtr, -+ baseChunk, -+ tn) ? 1 : 0; -+- -+ } -+- -++ -+ if(ok) -+ ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk)); -+- -++ -+ } -+ -+- T(YAFFS_TRACE_CHECKPOINT,( -+- TSTR("Checkpoint read tnodes %d records, last %d. ok %d" TENDSTR), -+- nread,baseChunk,ok)); -+- -+- return ok ? 1 : 0; -++ return ok ? 1 : 0; -+ } -+- -++ -+ -+ static int yaffs_WriteCheckpointObjects(yaffs_Device *dev) -+ { -+@@ -4317,11 +3719,11 @@ -+ int ok = 1; -+ struct list_head *lh; -+ -+- -++ -+ /* Iterate through the objects in each hash entry, -+ * dumping them to the checkpointing stream. -+ */ -+- -++ -+ for(i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++){ -+ list_for_each(lh, &dev->objectBucket[i].list) { -+ if (lh) { -+@@ -4333,9 +3735,9 @@ -+ T(YAFFS_TRACE_CHECKPOINT,( -+ TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %x" TENDSTR), -+ cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj)); -+- -++ -+ ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp)); -+- -++ -+ if(ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE){ -+ ok = yaffs_WriteCheckpointTnodes(obj); -+ } -+@@ -4343,14 +3745,14 @@ -+ } -+ } -+ } -+- -++ -+ /* Dump end of list */ -+ memset(&cp,0xFF,sizeof(yaffs_CheckpointObject)); -+ cp.structType = sizeof(cp); -+- -++ -+ if(ok) -+ ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp)); -+- -++ -+ return ok ? 1 : 0; -+ } -+ -+@@ -4361,22 +3763,20 @@ -+ int ok = 1; -+ int done = 0; -+ yaffs_Object *hardList = NULL; -+- -++ -+ while(ok && !done) { -+ ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp)); -+ if(cp.structType != sizeof(cp)) { -+- T(YAFFS_TRACE_CHECKPOINT,(TSTR("struct size %d instead of %d ok %d"TENDSTR), -+- cp.structType,sizeof(cp),ok)); -++ /* printf("structure parsing failed\n"); */ -+ ok = 0; -+ } -+- -+- T(YAFFS_TRACE_CHECKPOINT,(TSTR("Checkpoint read object %d parent %d type %d chunk %d " TENDSTR), -+- cp.objectId,cp.parentId,cp.variantType,cp.chunkId)); -+- -++ -+ if(ok && cp.objectId == ~0) -+ done = 1; -+ else if(ok){ -+ obj = yaffs_FindOrCreateObjectByNumber(dev,cp.objectId, cp.variantType); -++ T(YAFFS_TRACE_CHECKPOINT,(TSTR("Checkpoint read object %d parent %d type %d chunk %d obj addr %x" TENDSTR), -++ cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj)); -+ if(obj) { -+ yaffs_CheckpointObjectToObject(obj,&cp); -+ if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) { -+@@ -4387,93 +3787,39 @@ -+ hardList; -+ hardList = obj; -+ } -+- -++ -+ } -+ } -+ } -+- -++ -+ if(ok) -+ yaffs_HardlinkFixup(dev,hardList); -+- -++ -+ return ok ? 1 : 0; -+ } -+ -+-static int yaffs_WriteCheckpointSum(yaffs_Device *dev) -+-{ -+- __u32 checkpointSum; -+- int ok; -+- -+- yaffs_GetCheckpointSum(dev,&checkpointSum); -+- -+- ok = (yaffs_CheckpointWrite(dev,&checkpointSum,sizeof(checkpointSum)) == sizeof(checkpointSum)); -+- -+- if(!ok) -+- return 0; -+- -+- return 1; -+-} -+- -+-static int yaffs_ReadCheckpointSum(yaffs_Device *dev) -+-{ -+- __u32 checkpointSum0; -+- __u32 checkpointSum1; -+- int ok; -+- -+- yaffs_GetCheckpointSum(dev,&checkpointSum0); -+- -+- ok = (yaffs_CheckpointRead(dev,&checkpointSum1,sizeof(checkpointSum1)) == sizeof(checkpointSum1)); -+- -+- if(!ok) -+- return 0; -+- -+- if(checkpointSum0 != checkpointSum1) -+- return 0; -+- -+- return 1; -+-} -+- -+- -+ static int yaffs_WriteCheckpointData(yaffs_Device *dev) -+ { -+ -+- int ok = 1; -+- -+- if(dev->skipCheckpointWrite || !dev->isYaffs2){ -+- T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint write" TENDSTR))); -+- ok = 0; -+- } -+- -++ int ok; -++ -++ ok = yaffs_CheckpointOpen(dev,1); -++ -+ if(ok) -+- ok = yaffs_CheckpointOpen(dev,1); -+- -+- if(ok){ -+- T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR))); -+ ok = yaffs_WriteCheckpointValidityMarker(dev,1); -+- } -+- if(ok){ -+- T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint device" TENDSTR))); -++ if(ok) -+ ok = yaffs_WriteCheckpointDevice(dev); -+- } -+- if(ok){ -+- T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint objects" TENDSTR))); -++ if(ok) -+ ok = yaffs_WriteCheckpointObjects(dev); -+- } -+- if(ok){ -+- T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR))); -++ if(ok) -+ ok = yaffs_WriteCheckpointValidityMarker(dev,0); -+- } -+- -+- if(ok){ -+- ok = yaffs_WriteCheckpointSum(dev); -+- } -+- -+- -++ -+ if(!yaffs_CheckpointClose(dev)) -+ ok = 0; -+- -++ -+ if(ok) -+ dev->isCheckpointed = 1; -+- else -++ else -+ dev->isCheckpointed = 0; -+ -+ return dev->isCheckpointed; -+@@ -4481,44 +3827,27 @@ -+ -+ static int yaffs_ReadCheckpointData(yaffs_Device *dev) -+ { -+- int ok = 1; -+- -+- if(dev->skipCheckpointRead || !dev->isYaffs2){ -+- T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint read" TENDSTR))); -+- ok = 0; -+- } -+- -++ int ok; -++ -++ ok = yaffs_CheckpointOpen(dev,0); /* open for read */ -++ -+ if(ok) -+- ok = yaffs_CheckpointOpen(dev,0); /* open for read */ -+- -+- if(ok){ -+- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR))); -+ ok = yaffs_ReadCheckpointValidityMarker(dev,1); -+- } -+- if(ok){ -+- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint device" TENDSTR))); -++ if(ok) -+ ok = yaffs_ReadCheckpointDevice(dev); -+- } -+- if(ok){ -+- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint objects" TENDSTR))); -++ if(ok) -+ ok = yaffs_ReadCheckpointObjects(dev); -+- } -+- if(ok){ -+- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR))); -++ if(ok) -+ ok = yaffs_ReadCheckpointValidityMarker(dev,0); -+- } -++ -+ -+- if(ok){ -+- ok = yaffs_ReadCheckpointSum(dev); -+- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint checksum %d" TENDSTR),ok)); -+- } -+ -+ if(!yaffs_CheckpointClose(dev)) -+ ok = 0; -+ -+ if(ok) -+ dev->isCheckpointed = 1; -+- else -++ else -+ dev->isCheckpointed = 0; -+ -+ return ok ? 1 : 0; -+@@ -4527,7 +3856,7 @@ -+ -+ static void yaffs_InvalidateCheckpoint(yaffs_Device *dev) -+ { -+- if(dev->isCheckpointed || -++ if(dev->isCheckpointed || -+ dev->blocksInCheckpoint > 0){ -+ dev->isCheckpointed = 0; -+ yaffs_CheckpointInvalidateStream(dev); -+@@ -4539,19 +3868,13 @@ -+ -+ int yaffs_CheckpointSave(yaffs_Device *dev) -+ { -+- -++ yaffs_ReportOddballBlocks(dev); -+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("save entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); -+ -+- yaffs_VerifyObjects(dev); -+- yaffs_VerifyBlocks(dev); -+- yaffs_VerifyFreeChunks(dev); -+- -+- if(!dev->isCheckpointed) { -+- yaffs_InvalidateCheckpoint(dev); -++ if(!dev->isCheckpointed) -+ yaffs_WriteCheckpointData(dev); -+- } -+- -+- T(YAFFS_TRACE_ALWAYS,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); -++ -++ T(YAFFS_TRACE_CHECKPOINT,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); -+ -+ return dev->isCheckpointed; -+ } -+@@ -4560,17 +3883,13 @@ -+ { -+ int retval; -+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); -+- -++ -+ retval = yaffs_ReadCheckpointData(dev); -+ -+- if(dev->isCheckpointed){ -+- yaffs_VerifyObjects(dev); -+- yaffs_VerifyBlocks(dev); -+- yaffs_VerifyFreeChunks(dev); -+- } -+- -+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); -+- -++ -++ yaffs_ReportOddballBlocks(dev); -++ -+ return retval; -+ } -+ -+@@ -4606,7 +3925,7 @@ -+ chunk++; -+ -+ /* OK now check for the curveball where the start and end are in -+- * the same chunk. -++ * the same chunk. -+ */ -+ if ((start + n) < dev->nDataBytesPerChunk) { -+ nToCopy = n; -+@@ -4763,7 +4082,7 @@ -+ yaffs_ChunkCache *cache; -+ /* If we can't find the data in the cache, then load the cache */ -+ cache = yaffs_FindChunkCache(in, chunk); -+- -++ -+ if (!cache -+ && yaffs_CheckSpaceForAllocation(in-> -+ myDev)) { -+@@ -4776,12 +4095,12 @@ -+ cache-> -+ data); -+ } -+- else if(cache && -++ else if(cache && -+ !cache->dirty && -+ !yaffs_CheckSpaceForAllocation(in->myDev)){ -+ /* Drop the cache if it was a read cache item and -+ * no space check has been made for it. -+- */ -++ */ -+ cache = NULL; -+ } -+ -+@@ -4945,9 +4264,9 @@ -+ int oldFileSize = in->variant.fileVariant.fileSize; -+ int newSizeOfPartialChunk; -+ int newFullChunks; -+- -++ -+ yaffs_Device *dev = in->myDev; -+- -++ -+ yaffs_AddrToChunk(dev, newSize, &newFullChunks, &newSizeOfPartialChunk); -+ -+ yaffs_FlushFilesChunkCache(in); -+@@ -4969,7 +4288,7 @@ -+ -+ if (newSizeOfPartialChunk != 0) { -+ int lastChunk = 1 + newFullChunks; -+- -++ -+ __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__); -+ -+ /* Got to read and rewrite the last chunk with its new size and zero pad */ -+@@ -4993,8 +4312,8 @@ -+ in->variant.fileVariant.fileSize = newSize; -+ } -+ -+- -+- -++ -++ -+ /* Write a new object header. -+ * show we've shrunk the file, if need be -+ * Do this only if the file is not in the deleted directories. -+@@ -5058,7 +4377,7 @@ -+ -+ if (in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) { -+ /* Move to the unlinked directory so we have a record that it was deleted. */ -+- yaffs_ChangeObjectName(in, in->myDev->deletedDir,"deleted", 0, 0); -++ yaffs_ChangeObjectName(in, in->myDev->deletedDir, NULL, 0, 0); -+ -+ } -+ -+@@ -5096,7 +4415,7 @@ -+ if (immediateDeletion) { -+ retVal = -+ yaffs_ChangeObjectName(in, in->myDev->deletedDir, -+- "deleted", 0, 0); -++ NULL, 0, 0); -+ T(YAFFS_TRACE_TRACING, -+ (TSTR("yaffs: immediate deletion of file %d" TENDSTR), -+ in->objectId)); -+@@ -5109,7 +4428,7 @@ -+ } else { -+ retVal = -+ yaffs_ChangeObjectName(in, in->myDev->unlinkedDir, -+- "unlinked", 0, 0); -++ NULL, 0, 0); -+ } -+ -+ } -+@@ -5313,7 +4632,7 @@ -+ { -+ yaffs_Object *hl; -+ yaffs_Object *in; -+- -++ -+ while (hardList) { -+ hl = hardList; -+ hardList = (yaffs_Object *) (hardList->hardLinks.next); -+@@ -5370,6 +4689,7 @@ -+ int deleted; -+ yaffs_BlockState state; -+ yaffs_Object *hardList = NULL; -++ yaffs_Object *hl; -+ yaffs_BlockInfo *bi; -+ int sequenceNumber; -+ yaffs_ObjectHeader *oh; -+@@ -5377,9 +4697,6 @@ -+ yaffs_Object *parent; -+ int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1; -+ -+- int alloc_failed = 0; -+- -+- -+ __u8 *chunkData; -+ -+ yaffs_BlockIndex *blockIndex = NULL; -+@@ -5389,9 +4706,9 @@ -+ (TSTR("yaffs_Scan is not for YAFFS2!" TENDSTR))); -+ return YAFFS_FAIL; -+ } -+- -++ -+ //TODO Throw all the yaffs2 stuuf out of yaffs_Scan since it is only for yaffs1 format. -+- -++ -+ T(YAFFS_TRACE_SCAN, -+ (TSTR("yaffs_Scan starts intstartblk %d intendblk %d..." TENDSTR), -+ dev->internalStartBlock, dev->internalEndBlock)); -+@@ -5402,8 +4719,6 @@ -+ -+ if (dev->isYaffs2) { -+ blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex)); -+- if(!blockIndex) -+- return YAFFS_FAIL; -+ } -+ -+ /* Scan all the blocks to determine their state */ -+@@ -5485,7 +4800,7 @@ -+ } -+ -+ /* For each block.... */ -+- for (blockIterator = startIterator; !alloc_failed && blockIterator <= endIterator; -++ for (blockIterator = startIterator; blockIterator <= endIterator; -+ blockIterator++) { -+ -+ if (dev->isYaffs2) { -+@@ -5501,7 +4816,7 @@ -+ deleted = 0; -+ -+ /* For each chunk in each block that needs scanning....*/ -+- for (c = 0; !alloc_failed && c < dev->nChunksPerBlock && -++ for (c = 0; c < dev->nChunksPerBlock && -+ state == YAFFS_BLOCK_STATE_NEEDS_SCANNING; c++) { -+ /* Read the tags and decide what to do */ -+ chunk = blk * dev->nChunksPerBlock + c; -+@@ -5520,7 +4835,7 @@ -+ /*T((" %d %d deleted\n",blk,c)); */ -+ } else if (!tags.chunkUsed) { -+ /* An unassigned chunk in the block -+- * This means that either the block is empty or -++ * This means that either the block is empty or -+ * this is the one being allocated from -+ */ -+ -+@@ -5537,9 +4852,9 @@ -+ state = YAFFS_BLOCK_STATE_ALLOCATING; -+ dev->allocationBlock = blk; -+ dev->allocationPage = c; -+- dev->allocationBlockFinder = blk; -++ dev->allocationBlockFinder = blk; -+ /* Set it to here to encourage the allocator to go forth from here. */ -+- -++ -+ /* Yaffs2 sanity check: -+ * This should be the one with the highest sequence number -+ */ -+@@ -5569,20 +4884,12 @@ -+ /* PutChunkIntoFile checks for a clash (two data chunks with -+ * the same chunkId). -+ */ -+- -+- if(!in) -+- alloc_failed = 1; -+- -+- if(in){ -+- if(!yaffs_PutChunkIntoFile(in, tags.chunkId, chunk,1)) -+- alloc_failed = 1; -+- } -+- -++ yaffs_PutChunkIntoFile(in, tags.chunkId, chunk, -++ 1); -+ endpos = -+ (tags.chunkId - 1) * dev->nDataBytesPerChunk + -+ tags.byteCount; -+- if (in && -+- in->variantType == YAFFS_OBJECT_TYPE_FILE -++ if (in->variantType == YAFFS_OBJECT_TYPE_FILE -+ && in->variant.fileVariant.scannedFileSize < -+ endpos) { -+ in->variant.fileVariant. -+@@ -5613,7 +4920,7 @@ -+ tags.objectId); -+ if (in && in->variantType != oh->type) { -+ /* This should not happen, but somehow -+- * Wev'e ended up with an objectId that has been reused but not yet -++ * Wev'e ended up with an objectId that has been reused but not yet -+ * deleted, and worse still it has changed type. Delete the old object. -+ */ -+ -+@@ -5627,17 +4934,14 @@ -+ objectId, -+ oh->type); -+ -+- if(!in) -+- alloc_failed = 1; -+- -+- if (in && oh->shadowsObject > 0) { -++ if (oh->shadowsObject > 0) { -+ yaffs_HandleShadowedObject(dev, -+ oh-> -+ shadowsObject, -+ 0); -+ } -+ -+- if (in && in->valid) { -++ if (in->valid) { -+ /* We have already filled this one. We have a duplicate and need to resolve it. */ -+ -+ unsigned existingSerial = in->serial; -+@@ -5658,7 +4962,7 @@ -+ } -+ } -+ -+- if (in && !in->valid && -++ if (!in->valid && -+ (tags.objectId == YAFFS_OBJECTID_ROOT || -+ tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) { -+ /* We only load some info, don't fiddle with directory structure */ -+@@ -5683,7 +4987,7 @@ -+ #endif -+ in->chunkId = chunk; -+ -+- } else if (in && !in->valid) { -++ } else if (!in->valid) { -+ /* we need to load this info */ -+ -+ in->valid = 1; -+@@ -5752,11 +5056,11 @@ -+ * Since we might scan a hardlink before its equivalent object is scanned -+ * we put them all in a list. -+ * After scanning is complete, we should have all the objects, so we run through this -+- * list and fix up all the chains. -++ * list and fix up all the chains. -+ */ -+ -+ switch (in->variantType) { -+- case YAFFS_OBJECT_TYPE_UNKNOWN: -++ case YAFFS_OBJECT_TYPE_UNKNOWN: -+ /* Todo got a problem */ -+ break; -+ case YAFFS_OBJECT_TYPE_FILE: -+@@ -5791,11 +5095,10 @@ -+ case YAFFS_OBJECT_TYPE_SPECIAL: -+ /* Do nothing */ -+ break; -+- case YAFFS_OBJECT_TYPE_SYMLINK: -+- in->variant.symLinkVariant.alias = -++ case YAFFS_OBJECT_TYPE_SYMLINK: -++ in->variant.symLinkVariant. -++ alias = -+ yaffs_CloneString(oh->alias); -+- if(!in->variant.symLinkVariant.alias) -+- alloc_failed = 1; -+ break; -+ } -+ -+@@ -5826,11 +5129,11 @@ -+ if (blockIndex) { -+ YFREE(blockIndex); -+ } -+- -+- -++ -++ -+ /* Ok, we've done all the scanning. -+ * Fix up the hard link chains. -+- * We should now have scanned all the objects, now it's time to add these -++ * We should now have scanned all the objects, now it's time to add these -+ * hardlinks. -+ */ -+ -+@@ -5857,13 +5160,8 @@ -+ -+ yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__); -+ -+- if(alloc_failed){ -+- return YAFFS_FAIL; -+- } -+- -+ T(YAFFS_TRACE_SCAN, (TSTR("yaffs_Scan ends" TENDSTR))); -+ -+- -+ return YAFFS_OK; -+ } -+ -+@@ -5874,23 +5172,19 @@ -+ yaffs_Device *dev = in->myDev; -+ yaffs_ExtendedTags tags; -+ int result; -+- int alloc_failed = 0; -+- -+- if(!in) -+- return; -+- -++ -+ #if 0 -+ T(YAFFS_TRACE_SCAN,(TSTR("details for object %d %s loaded" TENDSTR), -+ in->objectId, -+ in->lazyLoaded ? "not yet" : "already")); -+ #endif -+- -++ -+ if(in->lazyLoaded){ -+ in->lazyLoaded = 0; -+ chunkData = yaffs_GetTempBuffer(dev, __LINE__); -+ -+ result = yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,&tags); -+- oh = (yaffs_ObjectHeader *) chunkData; -++ oh = (yaffs_ObjectHeader *) chunkData; -+ -+ in->yst_mode = oh->yst_mode; -+ #ifdef CONFIG_YAFFS_WINCE -+@@ -5907,17 +5201,14 @@ -+ in->yst_mtime = oh->yst_mtime; -+ in->yst_ctime = oh->yst_ctime; -+ in->yst_rdev = oh->yst_rdev; -+- -++ -+ #endif -+ yaffs_SetObjectName(in, oh->name); -+- -+- if(in->variantType == YAFFS_OBJECT_TYPE_SYMLINK){ -++ -++ if(in->variantType == YAFFS_OBJECT_TYPE_SYMLINK) -+ in->variant.symLinkVariant.alias = -+ yaffs_CloneString(oh->alias); -+- if(!in->variant.symLinkVariant.alias) -+- alloc_failed = 1; /* Not returned to caller */ -+- } -+- -++ -+ yaffs_ReleaseTempBuffer(dev,chunkData, __LINE__); -+ } -+ } -+@@ -5945,13 +5236,12 @@ -+ int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1; -+ int itsUnlinked; -+ __u8 *chunkData; -+- -++ -+ int fileSize; -+ int isShrink; -+ int foundChunksInBlock; -+ int equivalentObjectId; -+- int alloc_failed = 0; -+- -++ -+ -+ yaffs_BlockIndex *blockIndex = NULL; -+ int altBlockIndex = 0; -+@@ -5971,20 +5261,18 @@ -+ dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER; -+ -+ blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex)); -+- -++ -+ if(!blockIndex) { -+ blockIndex = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockIndex)); -+ altBlockIndex = 1; -+ } -+- -++ -+ if(!blockIndex) { -+ T(YAFFS_TRACE_SCAN, -+ (TSTR("yaffs_Scan() could not allocate block index!" TENDSTR))); -+ return YAFFS_FAIL; -+ } -+- -+- dev->blocksInCheckpoint = 0; -+- -++ -+ chunkData = yaffs_GetTempBuffer(dev, __LINE__); -+ -+ /* Scan all the blocks to determine their state */ -+@@ -6001,15 +5289,15 @@ -+ -+ if(bi->sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA) -+ bi->blockState = state = YAFFS_BLOCK_STATE_CHECKPOINT; -+- -++ -+ T(YAFFS_TRACE_SCAN_DEBUG, -+ (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk, -+ state, sequenceNumber)); -+ -+- -++ -+ if(state == YAFFS_BLOCK_STATE_CHECKPOINT){ -+- dev->blocksInCheckpoint++; -+- -++ /* todo .. fix free space ? */ -++ -+ } else if (state == YAFFS_BLOCK_STATE_DEAD) { -+ T(YAFFS_TRACE_BAD_BLOCKS, -+ (TSTR("block %d is bad" TENDSTR), blk)); -+@@ -6053,12 +5341,14 @@ -+ -+ /* Sort the blocks */ -+ #ifndef CONFIG_YAFFS_USE_OWN_SORT -+- yaffs_qsort(blockIndex, nBlocksToScan, -+- sizeof(yaffs_BlockIndex), ybicmp); -++ { -++ /* Use qsort now. */ -++ qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp); -++ } -+ #else -+ { -+ /* Dungy old bubble sort... */ -+- -++ -+ yaffs_BlockIndex temp; -+ int i; -+ int j; -+@@ -6084,7 +5374,7 @@ -+ (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan)); -+ -+ /* For each block.... backwards */ -+- for (blockIterator = endIterator; !alloc_failed && blockIterator >= startIterator; -++ for (blockIterator = endIterator; blockIterator >= startIterator; -+ blockIterator--) { -+ /* Cooperative multitasking! This loop can run for so -+ long that watchdog timers expire. */ -+@@ -6094,22 +5384,18 @@ -+ blk = blockIndex[blockIterator].block; -+ -+ bi = yaffs_GetBlockInfo(dev, blk); -+- -+- -+ state = bi->blockState; -+ -+ deleted = 0; -+ -+ /* For each chunk in each block that needs scanning.... */ -+ foundChunksInBlock = 0; -+- for (c = dev->nChunksPerBlock - 1; -+- !alloc_failed && c >= 0 && -++ for (c = dev->nChunksPerBlock - 1; c >= 0 && -+ (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING || -+ state == YAFFS_BLOCK_STATE_ALLOCATING); c--) { -+- /* Scan backwards... -++ /* Scan backwards... -+ * Read the tags and decide what to do -+ */ -+- -+ chunk = blk * dev->nChunksPerBlock + c; -+ -+ result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL, -+@@ -6123,14 +5409,14 @@ -+ * it is a chunk that was skipped due to failing the erased -+ * check. Just skip it so that it can be deleted. -+ * But, more typically, We get here when this is an unallocated -+- * chunk and his means that either the block is empty or -++ * chunk and his means that either the block is empty or -+ * this is the one being allocated from -+ */ -+ -+ if(foundChunksInBlock) -+ { -+ /* This is a chunk that was skipped due to failing the erased check */ -+- -++ -+ } else if (c == 0) { -+ /* We're looking at the first chunk in the block so the block is unused */ -+ state = YAFFS_BLOCK_STATE_EMPTY; -+@@ -6140,7 +5426,7 @@ -+ state == YAFFS_BLOCK_STATE_ALLOCATING) { -+ if(dev->sequenceNumber == bi->sequenceNumber) { -+ /* this is the block being allocated from */ -+- -++ -+ T(YAFFS_TRACE_SCAN, -+ (TSTR -+ (" Allocating from %d %d" -+@@ -6149,34 +5435,34 @@ -+ state = YAFFS_BLOCK_STATE_ALLOCATING; -+ dev->allocationBlock = blk; -+ dev->allocationPage = c; -+- dev->allocationBlockFinder = blk; -++ dev->allocationBlockFinder = blk; -+ } -+ else { -+ /* This is a partially written block that is not -+ * the current allocation block. This block must have -+ * had a write failure, so set up for retirement. -+ */ -+- -++ -+ bi->needsRetiring = 1; -+ bi->gcPrioritise = 1; -+- -++ -+ T(YAFFS_TRACE_ALWAYS, -+ (TSTR("Partially written block %d being set for retirement" TENDSTR), -+ blk)); -+ } -+ -+ } -+- -++ -+ } -+ -+ dev->nFreeChunks++; -+- -++ -+ } else if (tags.chunkId > 0) { -+ /* chunkId > 0 so it is a data chunk... */ -+ unsigned int endpos; -+ __u32 chunkBase = -+ (tags.chunkId - 1) * dev->nDataBytesPerChunk; -+- -++ -+ foundChunksInBlock = 1; -+ -+ -+@@ -6187,29 +5473,21 @@ -+ tags. -+ objectId, -+ YAFFS_OBJECT_TYPE_FILE); -+- if(!in){ -+- /* Out of memory */ -+- alloc_failed = 1; -+- } -+- -+- if (in && -+- in->variantType == YAFFS_OBJECT_TYPE_FILE -++ if (in->variantType == YAFFS_OBJECT_TYPE_FILE -+ && chunkBase < -+ in->variant.fileVariant.shrinkSize) { -+ /* This has not been invalidated by a resize */ -+- if(!yaffs_PutChunkIntoFile(in, tags.chunkId, -+- chunk, -1)){ -+- alloc_failed = 1; -+- } -++ yaffs_PutChunkIntoFile(in, tags.chunkId, -++ chunk, -1); -+ -+- /* File size is calculated by looking at the data chunks if we have not -++ /* File size is calculated by looking at the data chunks if we have not -+ * seen an object header yet. Stop this practice once we find an object header. -+ */ -+ endpos = -+ (tags.chunkId - -+ 1) * dev->nDataBytesPerChunk + -+ tags.byteCount; -+- -++ -+ if (!in->valid && /* have not got an object header yet */ -+ in->variant.fileVariant. -+ scannedFileSize < endpos) { -+@@ -6221,7 +5499,7 @@ -+ scannedFileSize; -+ } -+ -+- } else if(in) { -++ } else { -+ /* This chunk has been invalidated by a resize, so delete */ -+ yaffs_DeleteChunk(dev, chunk, 1, __LINE__); -+ -+@@ -6255,7 +5533,7 @@ -+ ) { -+ -+ /* If we don't have valid info then we need to read the chunk -+- * TODO In future we can probably defer reading the chunk and -++ * TODO In future we can probably defer reading the chunk and -+ * living with invalid data until needed. -+ */ -+ -+@@ -6283,12 +5561,12 @@ -+ -+ if (in->valid) { -+ /* We have already filled this one. -+- * We have a duplicate that will be discarded, but -++ * We have a duplicate that will be discarded, but -+ * we first have to suck out resize info if it is a file. -+ */ -+ -+- if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) && -+- ((oh && -++ if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) && -++ ((oh && -+ oh-> type == YAFFS_OBJECT_TYPE_FILE)|| -+ (tags.extraHeaderInfoAvailable && -+ tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE)) -+@@ -6339,7 +5617,7 @@ -+ YAFFS_OBJECTID_LOSTNFOUND)) { -+ /* We only load some info, don't fiddle with directory structure */ -+ in->valid = 1; -+- -++ -+ if(oh) { -+ in->variantType = oh->type; -+ -+@@ -6358,13 +5636,13 @@ -+ in->yst_mtime = oh->yst_mtime; -+ in->yst_ctime = oh->yst_ctime; -+ in->yst_rdev = oh->yst_rdev; -+- -++ -+ #endif -+ } else { -+ in->variantType = tags.extraObjectType; -+ in->lazyLoaded = 1; -+ } -+- -++ -+ in->chunkId = chunk; -+ -+ } else if (!in->valid) { -+@@ -6372,7 +5650,7 @@ -+ -+ in->valid = 1; -+ in->chunkId = chunk; -+- -++ -+ if(oh) { -+ in->variantType = oh->type; -+ -+@@ -6393,12 +5671,12 @@ -+ in->yst_rdev = oh->yst_rdev; -+ #endif -+ -+- if (oh->shadowsObject > 0) -++ if (oh->shadowsObject > 0) -+ yaffs_HandleShadowedObject(dev, -+ oh-> -+ shadowsObject, -+ 1); -+- -++ -+ -+ yaffs_SetObjectName(in, oh->name); -+ parent = -+@@ -6466,11 +5744,11 @@ -+ * Since we might scan a hardlink before its equivalent object is scanned -+ * we put them all in a list. -+ * After scanning is complete, we should have all the objects, so we run -+- * through this list and fix up all the chains. -++ * through this list and fix up all the chains. -+ */ -+ -+ switch (in->variantType) { -+- case YAFFS_OBJECT_TYPE_UNKNOWN: -++ case YAFFS_OBJECT_TYPE_UNKNOWN: -+ /* Todo got a problem */ -+ break; -+ case YAFFS_OBJECT_TYPE_FILE: -+@@ -6479,7 +5757,7 @@ -+ scannedFileSize < fileSize) { -+ /* This covers the case where the file size is greater -+ * than where the data is -+- * This will happen if the file is resized to be larger -++ * This will happen if the file is resized to be larger -+ * than its current data extents. -+ */ -+ in->variant.fileVariant.fileSize = fileSize; -+@@ -6509,21 +5787,16 @@ -+ /* Do nothing */ -+ break; -+ case YAFFS_OBJECT_TYPE_SYMLINK: -+- if(oh){ -++ if(oh) -+ in->variant.symLinkVariant.alias = -+ yaffs_CloneString(oh-> -+ alias); -+- if(!in->variant.symLinkVariant.alias) -+- alloc_failed = 1; -+- } -+ break; -+ } -+ -+ } -+- -+ } -+- -+- } /* End of scanning for each chunk */ -++ } -+ -+ if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) { -+ /* If we got this far while scanning, then the block is fully allocated. */ -+@@ -6541,19 +5814,19 @@ -+ -+ } -+ -+- if (altBlockIndex) -++ if (altBlockIndex) -+ YFREE_ALT(blockIndex); -+ else -+ YFREE(blockIndex); -+- -++ -+ /* Ok, we've done all the scanning. -+ * Fix up the hard link chains. -+- * We should now have scanned all the objects, now it's time to add these -++ * We should now have scanned all the objects, now it's time to add these -+ * hardlinks. -+ */ -+ yaffs_HardlinkFixup(dev,hardList); -+- -+- -++ -++ -+ /* -+ * Sort out state of unlinked and deleted objects. -+ */ -+@@ -6587,10 +5860,6 @@ -+ -+ yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__); -+ -+- if(alloc_failed){ -+- return YAFFS_FAIL; -+- } -+- -+ T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR))); -+ -+ return YAFFS_OK; -+@@ -6601,10 +5870,10 @@ -+ static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj) -+ { -+ yaffs_Device *dev = obj->myDev; -+- -++ -+ if(dev && dev->removeObjectCallback) -+ dev->removeObjectCallback(obj); -+- -++ -+ list_del_init(&obj->siblings); -+ obj->parent = NULL; -+ } -+@@ -6682,7 +5951,7 @@ -+ list_for_each(i, &directory->variant.directoryVariant.children) { -+ if (i) { -+ l = list_entry(i, yaffs_Object, siblings); -+- -++ -+ yaffs_CheckObjectDetailsLoaded(l); -+ -+ /* Special case for lost-n-found */ -+@@ -6690,14 +5959,14 @@ -+ if (yaffs_strcmp(name, YAFFS_LOSTNFOUND_NAME) == 0) { -+ return l; -+ } -+- } else if (yaffs_SumCompare(l->sum, sum) || l->chunkId <= 0) -++ } else if (yaffs_SumCompare(l->sum, sum) || l->chunkId <= 0) -+ { -+ /* LostnFound cunk called Objxxx -+ * Do a real check -+ */ -+ yaffs_GetObjectName(l, buffer, -+ YAFFS_MAX_NAME_LENGTH); -+- if (yaffs_strncmp(name, buffer,YAFFS_MAX_NAME_LENGTH) == 0) { -++ if (yaffs_strcmp(name, buffer) == 0) { -+ return l; -+ } -+ -+@@ -6753,7 +6022,6 @@ -+ if (obj && obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) { -+ /* We want the object id of the equivalent object, not this one */ -+ obj = obj->variant.hardLinkVariant.equivalentObject; -+- yaffs_CheckObjectDetailsLoaded(obj); -+ } -+ return obj; -+ -+@@ -6762,7 +6030,7 @@ -+ int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize) -+ { -+ memset(name, 0, buffSize * sizeof(YCHAR)); -+- -++ -+ yaffs_CheckObjectDetailsLoaded(obj); -+ -+ if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) { -+@@ -6991,16 +6259,15 @@ -+ } -+ -+ -+-static int yaffs_CreateInitialDirectories(yaffs_Device *dev) -++static void yaffs_CreateInitialDirectories(yaffs_Device *dev) -+ { -+ /* Initialise the unlinked, deleted, root and lost and found directories */ -+- -++ -+ dev->lostNFoundDir = dev->rootDir = NULL; -+ dev->unlinkedDir = dev->deletedDir = NULL; -+ -+ dev->unlinkedDir = -+ yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_UNLINKED, S_IFDIR); -+- -+ dev->deletedDir = -+ yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_DELETED, S_IFDIR); -+ -+@@ -7010,18 +6277,11 @@ -+ dev->lostNFoundDir = -+ yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_LOSTNFOUND, -+ YAFFS_LOSTNFOUND_MODE | S_IFDIR); -+- -+- if(dev->lostNFoundDir && dev->rootDir && dev->unlinkedDir && dev->deletedDir){ -+- yaffs_AddObjectToDirectory(dev->rootDir, dev->lostNFoundDir); -+- return YAFFS_OK; -+- } -+- -+- return YAFFS_FAIL; -++ yaffs_AddObjectToDirectory(dev->rootDir, dev->lostNFoundDir); -+ } -+ -+ int yaffs_GutsInitialise(yaffs_Device * dev) -+ { -+- int init_failed = 0; -+ unsigned x; -+ int bits; -+ -+@@ -7049,12 +6309,12 @@ -+ -+ /* Check geometry parameters. */ -+ -+- if ((dev->isYaffs2 && dev->nDataBytesPerChunk < 1024) || -+- (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) || -+- dev->nChunksPerBlock < 2 || -+- dev->nReservedBlocks < 2 || -+- dev->internalStartBlock <= 0 || -+- dev->internalEndBlock <= 0 || -++ if ((dev->isYaffs2 && dev->nDataBytesPerChunk < 1024) || -++ (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) || -++ dev->nChunksPerBlock < 2 || -++ dev->nReservedBlocks < 2 || -++ dev->internalStartBlock <= 0 || -++ dev->internalEndBlock <= 0 || -+ dev->internalEndBlock <= (dev->internalStartBlock + dev->nReservedBlocks + 2) // otherwise it is too small -+ ) { -+ T(YAFFS_TRACE_ALWAYS, -+@@ -7100,9 +6360,9 @@ -+ -+ -+ /* OK now calculate a few things for the device */ -+- -++ -+ /* -+- * Calculate all the chunk size manipulation numbers: -++ * Calculate all the chunk size manipulation numbers: -+ */ -+ /* Start off assuming it is a power of 2 */ -+ dev->chunkShift = ShiftDiv(dev->nDataBytesPerChunk); -+@@ -7121,7 +6381,7 @@ -+ dev->chunkShift = 0; -+ dev->chunkMask = 0; -+ } -+- -++ -+ -+ /* -+ * Calculate chunkGroupBits. -+@@ -7129,9 +6389,9 @@ -+ */ -+ -+ x = dev->nChunksPerBlock * (dev->internalEndBlock + 1); -+- -++ -+ bits = ShiftsGE(x); -+- -++ -+ /* Set up tnode width if wide tnodes are enabled. */ -+ if(!dev->wideTnodesDisabled){ -+ /* bits must be even so that we end up with 32-bit words */ -+@@ -7144,20 +6404,20 @@ -+ } -+ else -+ dev->tnodeWidth = 16; -+- -++ -+ dev->tnodeMask = (1<tnodeWidth)-1; -+- -++ -+ /* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled), -+ * so if the bitwidth of the -+ * chunk range we're using is greater than 16 we need -+ * to figure out chunk shift and chunkGroupSize -+ */ -+- -++ -+ if (bits <= dev->tnodeWidth) -+ dev->chunkGroupBits = 0; -+ else -+ dev->chunkGroupBits = bits - dev->tnodeWidth; -+- -++ -+ -+ dev->chunkGroupSize = 1 << dev->chunkGroupBits; -+ -+@@ -7193,111 +6453,71 @@ -+ dev->hasPendingPrioritisedGCs = 1; /* Assume the worst for now, will get fixed on first GC */ -+ -+ /* Initialise temporary buffers and caches. */ -+- if(!yaffs_InitialiseTempBuffers(dev)) -+- init_failed = 1; -+- -+- dev->srCache = NULL; -+- dev->gcCleanupList = NULL; -+- -+- -+- if (!init_failed && -+- dev->nShortOpCaches > 0) { -++ { -++ int i; -++ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { -++ dev->tempBuffer[i].line = 0; /* not in use */ -++ dev->tempBuffer[i].buffer = -++ YMALLOC_DMA(dev->nDataBytesPerChunk); -++ } -++ } -++ -++ if (dev->nShortOpCaches > 0) { -+ int i; -+- __u8 *buf; -+- int srCacheBytes = dev->nShortOpCaches * sizeof(yaffs_ChunkCache); -+ -+ if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) { -+ dev->nShortOpCaches = YAFFS_MAX_SHORT_OP_CACHES; -+ } -+ -+- buf = dev->srCache = YMALLOC(srCacheBytes); -++ dev->srCache = -++ YMALLOC(dev->nShortOpCaches * sizeof(yaffs_ChunkCache)); -+ -+- if(dev->srCache) -+- memset(dev->srCache,0,srCacheBytes); -+- -+- for (i = 0; i < dev->nShortOpCaches && buf; i++) { -++ for (i = 0; i < dev->nShortOpCaches; i++) { -+ dev->srCache[i].object = NULL; -+ dev->srCache[i].lastUse = 0; -+ dev->srCache[i].dirty = 0; -+- dev->srCache[i].data = buf = YMALLOC_DMA(dev->nDataBytesPerChunk); -++ dev->srCache[i].data = YMALLOC_DMA(dev->nDataBytesPerChunk); -+ } -+- if(!buf) -+- init_failed = 1; -+- -+ dev->srLastUse = 0; -+ } -+ -+ dev->cacheHits = 0; -+- -+- if(!init_failed){ -+- dev->gcCleanupList = YMALLOC(dev->nChunksPerBlock * sizeof(__u32)); -+- if(!dev->gcCleanupList) -+- init_failed = 1; -+- } -++ -++ dev->gcCleanupList = YMALLOC(dev->nChunksPerBlock * sizeof(__u32)); -+ -+ if (dev->isYaffs2) { -+ dev->useHeaderFileSize = 1; -+ } -+- if(!init_failed && !yaffs_InitialiseBlocks(dev)) -+- init_failed = 1; -+ -++ yaffs_InitialiseBlocks(dev); -+ yaffs_InitialiseTnodes(dev); -+ yaffs_InitialiseObjects(dev); -+ -+- if(!init_failed && !yaffs_CreateInitialDirectories(dev)) -+- init_failed = 1; -+- -+- -+- if(!init_failed){ -+- /* Now scan the flash. */ -+- if (dev->isYaffs2) { -+- if(yaffs_CheckpointRestore(dev)) { -+- T(YAFFS_TRACE_ALWAYS, -+- (TSTR("yaffs: restored from checkpoint" TENDSTR))); -+- } else { -+- -+- /* Clean up the mess caused by an aborted checkpoint load -+- * and scan backwards. -+- */ -+- yaffs_DeinitialiseBlocks(dev); -+- yaffs_DeinitialiseTnodes(dev); -+- yaffs_DeinitialiseObjects(dev); -+- -+- -+- dev->nErasedBlocks = 0; -+- dev->nFreeChunks = 0; -+- dev->allocationBlock = -1; -+- dev->allocationPage = -1; -+- dev->nDeletedFiles = 0; -+- dev->nUnlinkedFiles = 0; -+- dev->nBackgroundDeletions = 0; -+- dev->oldestDirtySequence = 0; -++ yaffs_CreateInitialDirectories(dev); -+ -+- if(!init_failed && !yaffs_InitialiseBlocks(dev)) -+- init_failed = 1; -+ -+- yaffs_InitialiseTnodes(dev); -+- yaffs_InitialiseObjects(dev); -+- -+- if(!init_failed && !yaffs_CreateInitialDirectories(dev)) -+- init_failed = 1; -+- -+- if(!init_failed && !yaffs_ScanBackwards(dev)) -+- init_failed = 1; -+- } -+- }else -+- if(!yaffs_Scan(dev)) -+- init_failed = 1; -+- } -++ /* Now scan the flash. */ -++ if (dev->isYaffs2) { -++ if(yaffs_CheckpointRestore(dev)) { -++ T(YAFFS_TRACE_ALWAYS, -++ (TSTR("yaffs: restored from checkpoint" TENDSTR))); -++ } else { -+ -+- if(init_failed){ -+- /* Clean up the mess */ -+- T(YAFFS_TRACE_TRACING, -+- (TSTR("yaffs: yaffs_GutsInitialise() aborted.\n" TENDSTR))); -++ /* Clean up the mess caused by an aborted checkpoint load -++ * and scan backwards. -++ */ -++ yaffs_DeinitialiseBlocks(dev); -++ yaffs_DeinitialiseTnodes(dev); -++ yaffs_DeinitialiseObjects(dev); -++ yaffs_InitialiseBlocks(dev); -++ yaffs_InitialiseTnodes(dev); -++ yaffs_InitialiseObjects(dev); -++ yaffs_CreateInitialDirectories(dev); -+ -+- yaffs_Deinitialise(dev); -+- return YAFFS_FAIL; -+- } -++ yaffs_ScanBackwards(dev); -++ } -++ }else -++ yaffs_Scan(dev); -+ -+ /* Zero out stats */ -+ dev->nPageReads = 0; -+@@ -7309,9 +6529,6 @@ -+ dev->nRetiredBlocks = 0; -+ -+ yaffs_VerifyFreeChunks(dev); -+- yaffs_VerifyBlocks(dev); -+- -+- -+ T(YAFFS_TRACE_TRACING, -+ (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR))); -+ return YAFFS_OK; -+@@ -7326,17 +6543,13 @@ -+ yaffs_DeinitialiseBlocks(dev); -+ yaffs_DeinitialiseTnodes(dev); -+ yaffs_DeinitialiseObjects(dev); -+- if (dev->nShortOpCaches > 0 && -+- dev->srCache) { -++ if (dev->nShortOpCaches > 0) { -+ -+ for (i = 0; i < dev->nShortOpCaches; i++) { -+- if(dev->srCache[i].data) -+- YFREE(dev->srCache[i].data); -+- dev->srCache[i].data = NULL; -++ YFREE(dev->srCache[i].data); -+ } -+ -+ YFREE(dev->srCache); -+- dev->srCache = NULL; -+ } -+ -+ YFREE(dev->gcCleanupList); -+@@ -7394,7 +6607,7 @@ -+ #endif -+ -+ nFree += dev->nDeletedFiles; -+- -++ -+ /* Now count the number of dirty chunks in the cache and subtract those */ -+ -+ { -+@@ -7408,12 +6621,12 @@ -+ nFree -= nDirtyCacheChunks; -+ -+ nFree -= ((dev->nReservedBlocks + 1) * dev->nChunksPerBlock); -+- -++ -+ /* Now we figure out how much to reserve for the checkpoint and report that... */ -+ blocksForCheckpoint = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint; -+ if(blocksForCheckpoint < 0) -+ blocksForCheckpoint = 0; -+- -++ -+ nFree -= (blocksForCheckpoint * dev->nChunksPerBlock); -+ -+ if (nFree < 0) -+@@ -7427,15 +6640,9 @@ -+ -+ static void yaffs_VerifyFreeChunks(yaffs_Device * dev) -+ { -+- int counted; -+- int difference; -+- -+- if(yaffs_SkipVerification(dev)) -+- return; -+- -+- counted = yaffs_CountFreeChunks(dev); -++ int counted = yaffs_CountFreeChunks(dev); -+ -+- difference = dev->nFreeChunks - counted; -++ int difference = dev->nFreeChunks - counted; -+ -+ if (difference) { -+ T(YAFFS_TRACE_ALWAYS, -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_guts.h linux-2.6.24.7.new/fs/yaffs2/yaffs_guts.h -+--- linux-2.6.24.7/fs/yaffs2/yaffs_guts.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_guts.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ /* -+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+@@ -22,11 +22,11 @@ -+ #define YAFFS_OK 1 -+ #define YAFFS_FAIL 0 -+ -+-/* Give us a Y=0x59, -+- * Give us an A=0x41, -+- * Give us an FF=0xFF -++/* Give us a Y=0x59, -++ * Give us an A=0x41, -++ * Give us an FF=0xFF -+ * Give us an S=0x53 -+- * And what have we got... -++ * And what have we got... -+ */ -+ #define YAFFS_MAGIC 0x5941FF53 -+ -+@@ -63,7 +63,9 @@ -+ -+ #define YAFFS_OBJECT_SPACE 0x40000 -+ -+-#define YAFFS_CHECKPOINT_VERSION 3 -++#define YAFFS_NCHECKPOINT_OBJECTS 5000 -++ -++#define YAFFS_CHECKPOINT_VERSION 2 -+ -+ #ifdef CONFIG_YAFFS_UNICODE -+ #define YAFFS_MAX_NAME_LENGTH 127 -+@@ -92,17 +94,11 @@ -+ -+ #define YAFFS_N_TEMP_BUFFERS 4 -+ -+-/* We limit the number attempts at sucessfully saving a chunk of data. -+- * Small-page devices have 32 pages per block; large-page devices have 64. -+- * Default to something in the order of 5 to 10 blocks worth of chunks. -+- */ -+-#define YAFFS_WR_ATTEMPTS (5*64) -+- -+ /* Sequence numbers are used in YAFFS2 to determine block allocation order. -+ * The range is limited slightly to help distinguish bad numbers from good. -+ * This also allows us to perhaps in the future use special numbers for -+ * special purposes. -+- * EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years, -++ * EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years, -+ * and is a larger number than the lifetime of a 2GB device. -+ */ -+ #define YAFFS_LOWEST_SEQUENCE_NUMBER 0x00001000 -+@@ -166,8 +162,6 @@ -+ YAFFS_OBJECT_TYPE_SPECIAL -+ } yaffs_ObjectType; -+ -+-#define YAFFS_OBJECT_TYPE_MAX YAFFS_OBJECT_TYPE_SPECIAL -+- -+ typedef struct { -+ -+ unsigned validMarker0; -+@@ -178,7 +172,7 @@ -+ -+ /* The following stuff only has meaning when we read */ -+ yaffs_ECCResult eccResult; -+- unsigned blockBad; -++ unsigned blockBad; -+ -+ /* YAFFS 1 stuff */ -+ unsigned chunkDeleted; /* The chunk is marked deleted */ -+@@ -244,35 +238,32 @@ -+ /* This block is empty */ -+ -+ YAFFS_BLOCK_STATE_ALLOCATING, -+- /* This block is partially allocated. -++ /* This block is partially allocated. -+ * At least one page holds valid data. -+ * This is the one currently being used for page -+ * allocation. Should never be more than one of these -+ */ -+ -+- YAFFS_BLOCK_STATE_FULL, -++ YAFFS_BLOCK_STATE_FULL, -+ /* All the pages in this block have been allocated. -+ */ -+ -+ YAFFS_BLOCK_STATE_DIRTY, -+- /* All pages have been allocated and deleted. -++ /* All pages have been allocated and deleted. -+ * Erase me, reuse me. -+ */ -+ -+- YAFFS_BLOCK_STATE_CHECKPOINT, -++ YAFFS_BLOCK_STATE_CHECKPOINT, -+ /* This block is assigned to holding checkpoint data. -+ */ -+ -+- YAFFS_BLOCK_STATE_COLLECTING, -++ YAFFS_BLOCK_STATE_COLLECTING, -+ /* This block is being garbage collected */ -+ -+- YAFFS_BLOCK_STATE_DEAD -++ YAFFS_BLOCK_STATE_DEAD -+ /* This block has failed and is not in use */ -+ } yaffs_BlockState; -+ -+-#define YAFFS_NUMBER_OF_BLOCK_STATES (YAFFS_BLOCK_STATE_DEAD + 1) -+- -+- -+ typedef struct { -+ -+ int softDeletions:10; /* number of soft deleted pages */ -+@@ -281,7 +272,7 @@ -+ __u32 needsRetiring:1; /* Data has failed on this block, need to get valid data off */ -+ /* and retire the block. */ -+ __u32 skipErasedCheck: 1; /* If this is set we can skip the erased check on this block */ -+- __u32 gcPrioritise: 1; /* An ECC check or blank check has failed on this block. -++ __u32 gcPrioritise: 1; /* An ECC check or bank check has failed on this block. -+ It should be prioritised for GC */ -+ __u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */ -+ -+@@ -408,7 +399,7 @@ -+ __u8 renameAllowed:1; /* Some objects are not allowed to be renamed. */ -+ __u8 unlinkAllowed:1; -+ __u8 dirty:1; /* the object needs to be written to flash */ -+- __u8 valid:1; /* When the file system is being loaded up, this -++ __u8 valid:1; /* When the file system is being loaded up, this -+ * object might be created before the data -+ * is available (ie. file data records appear before the header). -+ */ -+@@ -430,11 +421,11 @@ -+ -+ /* directory structure stuff */ -+ /* also used for linking up the free list */ -+- struct yaffs_ObjectStruct *parent; -++ struct yaffs_ObjectStruct *parent; -+ struct list_head siblings; -+ -+ /* Where's my object header in NAND? */ -+- int chunkId; -++ int chunkId; -+ -+ int nDataChunks; /* Number of data chunks attached to the file. */ -+ -+@@ -490,26 +481,26 @@ -+ } yaffs_ObjectBucket; -+ -+ -+-/* yaffs_CheckpointObject holds the definition of an object as dumped -++/* yaffs_CheckpointObject holds the definition of an object as dumped -+ * by checkpointing. -+ */ -+ -+ typedef struct { -+ int structType; -+- __u32 objectId; -++ __u32 objectId; -+ __u32 parentId; -+ int chunkId; -+- -++ -+ yaffs_ObjectType variantType:3; -+- __u8 deleted:1; -+- __u8 softDeleted:1; -+- __u8 unlinked:1; -+- __u8 fake:1; -++ __u8 deleted:1; -++ __u8 softDeleted:1; -++ __u8 unlinked:1; -++ __u8 fake:1; -+ __u8 renameAllowed:1; -+ __u8 unlinkAllowed:1; -+- __u8 serial; -+- -+- int nDataChunks; -++ __u8 serial; -++ -++ int nDataChunks; -+ __u32 fileSizeOrEquivalentObjectId; -+ -+ }yaffs_CheckpointObject; -+@@ -539,14 +530,17 @@ -+ int endBlock; /* End block we're allowed to use */ -+ int nReservedBlocks; /* We want this tuneable so that we can reduce */ -+ /* reserved blocks on NOR and RAM. */ -+- -+- -++ -++ /* Stuff used by the partitioned checkpointing mechanism */ -++ int checkpointStartBlock; -++ int checkpointEndBlock; -++ -+ /* Stuff used by the shared space checkpointing mechanism */ -+ /* If this value is zero, then this mechanism is disabled */ -+- -++ -+ int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */ -+ -+- -++ -+ -+ -+ int nShortOpCaches; /* If <= 0, then short op caching is disabled, else -+@@ -561,7 +555,7 @@ -+ * On an mtd this holds the mtd pointer. -+ */ -+ void *superBlock; -+- -++ -+ /* NAND access functions (Must be set before calling YAFFS)*/ -+ -+ int (*writeChunkToNAND) (struct yaffs_DeviceStruct * dev, -+@@ -587,57 +581,53 @@ -+ #endif -+ -+ int isYaffs2; -+- -+- /* The removeObjectCallback function must be supplied by OS flavours that -++ -++ /* The removeObjectCallback function must be supplied by OS flavours that -+ * need it. The Linux kernel does not use this, but yaffs direct does use -+ * it to implement the faster readdir -+ */ -+ void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj); -+- -++ -+ /* Callback to mark the superblock dirsty */ -+ void (*markSuperBlockDirty)(void * superblock); -+- -++ -+ int wideTnodesDisabled; /* Set to disable wide tnodes */ -+- -++ -+ -+ /* End of stuff that must be set before initialisation. */ -+ -+- /* Checkpoint control. Can be set before or after initialisation */ -+- __u8 skipCheckpointRead; -+- __u8 skipCheckpointWrite; -+- -+ /* Runtime parameters. Set up by YAFFS. */ -+ -+ __u16 chunkGroupBits; /* 0 for devices <= 32MB. else log2(nchunks) - 16 */ -+ __u16 chunkGroupSize; /* == 2^^chunkGroupBits */ -+- -++ -+ /* Stuff to support wide tnodes */ -+ __u32 tnodeWidth; -+ __u32 tnodeMask; -+- -++ -+ /* Stuff to support various file offses to chunk/offset translations */ -+ /* "Crumbs" for nDataBytesPerChunk not being a power of 2 */ -+ __u32 crumbMask; -+ __u32 crumbShift; -+ __u32 crumbsPerChunk; -+- -++ -+ /* Straight shifting for nDataBytesPerChunk being a power of 2 */ -+ __u32 chunkShift; -+ __u32 chunkMask; -+- -++ -+ -+ #ifdef __KERNEL__ -+ -+ struct semaphore sem; /* Semaphore for waiting on erasure.*/ -+ struct semaphore grossLock; /* Gross locking semaphore */ -+- __u8 *spareBuffer; /* For mtdif2 use. Don't know the size of the buffer -++ __u8 *spareBuffer; /* For mtdif2 use. Don't know the size of the buffer -+ * at compile time so we have to allocate it. -+ */ -+ void (*putSuperFunc) (struct super_block * sb); -+ #endif -+ -+ int isMounted; -+- -++ -+ int isCheckpointed; -+ -+ -+@@ -646,7 +636,7 @@ -+ int internalEndBlock; -+ int blockOffset; -+ int chunkOffset; -+- -++ -+ -+ /* Runtime checkpointing stuff */ -+ int checkpointPageSequence; /* running sequence number of checkpoint pages */ -+@@ -660,15 +650,13 @@ -+ int checkpointNextBlock; -+ int *checkpointBlockList; -+ int checkpointMaxBlocks; -+- __u32 checkpointSum; -+- __u32 checkpointXor; -+- -++ -+ /* Block Info */ -+ yaffs_BlockInfo *blockInfo; -+ __u8 *chunkBits; /* bitmap of chunks in use */ -+ unsigned blockInfoAlt:1; /* was allocated using alternative strategy */ -+ unsigned chunkBitsAlt:1; /* was allocated using alternative strategy */ -+- int chunkBitmapStride; /* Number of bytes of chunkBits per block. -++ int chunkBitmapStride; /* Number of bytes of chunkBits per block. -+ * Must be consistent with nChunksPerBlock. -+ */ -+ -+@@ -698,7 +686,6 @@ -+ int currentDirtyChecker; /* Used to find current dirtiest block */ -+ -+ __u32 *gcCleanupList; /* objects to delete at the end of a GC. */ -+- int nonAggressiveSkip; /* GC state/mode */ -+ -+ /* Statistcs */ -+ int nPageWrites; -+@@ -716,7 +703,7 @@ -+ int tagsEccUnfixed; -+ int nDeletions; -+ int nUnmarkedDeletions; -+- -++ -+ int hasPendingPrioritisedGCs; /* We think this device might have pending prioritised gcs */ -+ -+ /* Special directories */ -+@@ -727,7 +714,7 @@ -+ * __u8 bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK]; -+ * yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK]; -+ */ -+- -++ -+ int bufferedBlock; /* Which block is buffered here? */ -+ int doingBufferedBlockRewrite; -+ -+@@ -768,7 +755,7 @@ -+ int endBlock; -+ int rfu[100]; -+ } yaffs_SuperBlockHeader; -+- -++ -+ /* The CheckpointDevice structure holds the device information that changes at runtime and -+ * must be preserved over unmount/mount cycles. -+ */ -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_mtdif.c linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif.c -+--- linux-2.6.24.7/fs/yaffs2/yaffs_mtdif.c 2009-04-21 14:57:10.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif.c 2009-04-21 15:01:02.000000000 +0200 -+@@ -12,13 +12,10 @@ -+ */ -+ -+ const char *yaffs_mtdif_c_version = -+- "$Id: yaffs_mtdif.c,v 1.19 2007-02-14 01:09:06 wookey Exp $"; -++ "$Id: yaffs_mtdif.c,v 1.1.1.1 2008-03-28 04:29:21 jlwei Exp $"; -+ -+ #include "yportenv.h" -+- -+- -+ #include "yaffs_mtdif.h" -+- -+ #include "linux/mtd/mtd.h" -+ #include "linux/types.h" -+ #include "linux/time.h" -+@@ -54,6 +51,7 @@ -+ static inline void translate_oob2spare(yaffs_Spare *spare, __u8 *oob) -+ { -+ struct yaffs_NANDSpare *nspare = (struct yaffs_NANDSpare *)spare; -++ -+ spare->tagByte0 = oob[0]; -+ spare->tagByte1 = oob[1]; -+ spare->tagByte2 = oob[2]; -+@@ -68,6 +66,11 @@ -+ spare->ecc2[0] = spare->ecc2[1] = spare->ecc2[2] = 0xff; -+ -+ nspare->eccres1 = nspare->eccres2 = 0; /* FIXME */ -++#if 0 -++ char i; -++ for (i=0;i<8;i++) -++ printk("oob %d :%x",i,oob[i]); -++#endif -+ } -+ #endif -+ -+@@ -78,10 +81,11 @@ -+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+ struct mtd_oob_ops ops; -+ #endif -+- size_t dummy; -++ size_mtd_t dummy; -+ int retval = 0; -+ -+- loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; -++ loff_mtd_t addr = ((loff_mtd_t) chunkInNAND) * dev->nDataBytesPerChunk; -++ -+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+ __u8 spareAsBytes[8]; /* OOB */ -+ -+@@ -142,10 +146,11 @@ -+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+ struct mtd_oob_ops ops; -+ #endif -+- size_t dummy; -++ size_mtd_t dummy; -+ int retval = 0; -+ -+- loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; -++ loff_mtd_t addr = ((loff_mtd_t) chunkInNAND) * dev->nDataBytesPerChunk; -++ -+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+ __u8 spareAsBytes[8]; /* OOB */ -+ -+@@ -164,7 +169,7 @@ -+ ops.datbuf = data; -+ ops.ooboffs = 0; -+ ops.oobbuf = spareAsBytes; -+- retval = mtd->read_oob(mtd, addr, &ops); -++ retval = mtd->read_oob(mtd, addr, &ops); -+ if (dev->useNANDECC) -+ translate_oob2spare(spare, spareAsBytes); -+ } -+@@ -172,7 +177,7 @@ -+ __u8 *spareAsBytes = (__u8 *) spare; -+ -+ if (data && spare) { -+- if (dev->useNANDECC) { -++ if (dev->useNANDECC) { -+ /* Careful, this call adds 2 ints */ -+ /* to the end of the spare data. Calling function */ -+ /* should allocate enough memory for spare, */ -+@@ -208,8 +213,8 @@ -+ int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber) -+ { -+ struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); -+- __u32 addr = -+- ((loff_t) blockNumber) * dev->nDataBytesPerChunk -++ __u64 addr = -++ ((loff_mtd_t) blockNumber) * dev->nDataBytesPerChunk -+ * dev->nChunksPerBlock; -+ struct erase_info ei; -+ int retval = 0; -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_mtdif.h linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif.h -+--- linux-2.6.24.7/fs/yaffs2/yaffs_mtdif.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ /* -+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_mtdif1-compat.c linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif1-compat.c -+--- linux-2.6.24.7/fs/yaffs2/yaffs_mtdif1-compat.c 2009-04-21 14:57:10.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif1-compat.c 1970-01-01 01:00:00.000000000 +0100 -+@@ -1,434 +0,0 @@ -+-From ian@brightstareng.com Fri May 18 15:06:49 2007 -+-From ian@brightstareng.com Fri May 18 15:08:21 2007 -+-Received: from 206.173.66.57.ptr.us.xo.net ([206.173.66.57] helo=zebra.brightstareng.com) -+- by apollo.linkchoose.co.uk with esmtp (Exim 4.60) -+- (envelope-from ) -+- id 1Hp380-00011e-T6 -+- for david.goodenough@linkchoose.co.uk; Fri, 18 May 2007 15:08:21 +0100 -+-Received: from localhost (localhost.localdomain [127.0.0.1]) -+- by zebra.brightstareng.com (Postfix) with ESMTP -+- id 4819F28C004; Fri, 18 May 2007 10:07:49 -0400 (EDT) -+-Received: from zebra.brightstareng.com ([127.0.0.1]) -+- by localhost (zebra [127.0.0.1]) (amavisd-new, port 10024) with ESMTP -+- id 05328-06; Fri, 18 May 2007 10:07:16 -0400 (EDT) -+-Received: from pippin (unknown [192.168.1.25]) -+- by zebra.brightstareng.com (Postfix) with ESMTP -+- id 8BEF528C1BC; Fri, 18 May 2007 10:06:53 -0400 (EDT) -+-From: Ian McDonnell -+-To: David Goodenough -+-Subject: Re: something tested this time -- yaffs_mtdif1-compat.c -+-Date: Fri, 18 May 2007 10:06:49 -0400 -+-User-Agent: KMail/1.9.1 -+-References: <200705142207.06909.ian@brightstareng.com> <200705171131.53536.ian@brightstareng.com> <200705181334.32166.david.goodenough@linkchoose.co.uk> -+-In-Reply-To: <200705181334.32166.david.goodenough@linkchoose.co.uk> -+-Cc: Andrea Conti , -+- Charles Manning -+-MIME-Version: 1.0 -+-Content-Type: Multipart/Mixed; -+- boundary="Boundary-00=_5LbTGmt62YoutxM" -+-Message-Id: <200705181006.49860.ian@brightstareng.com> -+-X-Virus-Scanned: by amavisd-new at brightstareng.com -+-Status: R -+-X-Status: NT -+-X-KMail-EncryptionState: -+-X-KMail-SignatureState: -+-X-KMail-MDN-Sent: -+- -+---Boundary-00=_5LbTGmt62YoutxM -+-Content-Type: text/plain; -+- charset="iso-8859-15" -+-Content-Transfer-Encoding: 7bit -+-Content-Disposition: inline -+- -+-David, Andrea, -+- -+-On Friday 18 May 2007 08:34, you wrote: -+-> Yea team. With this fix in place (I put it in the wrong place -+-> at first) I can now mount and ls the Yaffs partition without -+-> an error messages! -+- -+-Good news! -+- -+-Attached is a newer yaffs_mtdif1.c with a bandaid to help the -+-2.6.18 and 2.6.19 versions of MTD not trip on the oob read. -+-See the LINUX_VERSION_CODE conditional in -+-nandmtd1_ReadChunkWithTagsFromNAND. -+- -+--imcd -+- -+---Boundary-00=_5LbTGmt62YoutxM -+-Content-Type: text/x-csrc; -+- charset="iso-8859-15"; -+- name="yaffs_mtdif1.c" -+-Content-Transfer-Encoding: 7bit -+-Content-Disposition: attachment; -+- filename="yaffs_mtdif1.c" -+- -+-/* -+- * YAFFS: Yet another FFS. A NAND-flash specific file system. -+- * yaffs_mtdif1.c NAND mtd interface functions for small-page NAND. -+- * -+- * Copyright (C) 2002 Aleph One Ltd. -+- * for Toby Churchill Ltd and Brightstar Engineering -+- * -+- * This program is free software; you can redistribute it and/or modify -+- * it under the terms of the GNU General Public License version 2 as -+- * published by the Free Software Foundation. -+- */ -+- -+-/* -+- * This module provides the interface between yaffs_nand.c and the -+- * MTD API. This version is used when the MTD interface supports the -+- * 'mtd_oob_ops' style calls to read_oob and write_oob, circa 2.6.17, -+- * and we have small-page NAND device. -+- * -+- * These functions are invoked via function pointers in yaffs_nand.c. -+- * This replaces functionality provided by functions in yaffs_mtdif.c -+- * and the yaffs_TagsCompatability functions in yaffs_tagscompat.c that are -+- * called in yaffs_mtdif.c when the function pointers are NULL. -+- * We assume the MTD layer is performing ECC (useNANDECC is true). -+- */ -+- -+-#include "yportenv.h" -+-#include "yaffs_guts.h" -+-#include "yaffs_packedtags1.h" -+-#include "yaffs_tagscompat.h" // for yaffs_CalcTagsECC -+- -+-#include "linux/kernel.h" -+-#include "linux/version.h" -+-#include "linux/types.h" -+-#include "linux/mtd/mtd.h" -+- -+-/* Don't compile this module if we don't have MTD's mtd_oob_ops interface */ -+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+- -+-const char *yaffs_mtdif1_c_version = "$Id$"; -+- -+-#ifndef CONFIG_YAFFS_9BYTE_TAGS -+-# define YTAG1_SIZE 8 -+-#else -+-# define YTAG1_SIZE 9 -+-#endif -+- -+-#if 0 -+-/* Use the following nand_ecclayout with MTD when using -+- * CONFIG_YAFFS_9BYTE_TAGS and the older on-NAND tags layout. -+- * If you have existing Yaffs images and the byte order differs from this, -+- * adjust 'oobfree' to match your existing Yaffs data. -+- * -+- * This nand_ecclayout scatters/gathers to/from the old-yaffs layout with the -+- * pageStatus byte (at NAND spare offset 4) scattered/gathered from/to -+- * the 9th byte. -+- * -+- * Old-style on-NAND format: T0,T1,T2,T3,P,B,T4,T5,E0,E1,E2,T6,T7,E3,E4,E5 -+- * We have/need PackedTags1 plus pageStatus: T0,T1,T2,T3,T4,T5,T6,T7,P -+- * where Tn are the tag bytes, En are MTD's ECC bytes, P is the pageStatus -+- * byte and B is the small-page bad-block indicator byte. -+- */ -+-static struct nand_ecclayout nand_oob_16 = { -+- .eccbytes = 6, -+- .eccpos = { 8, 9, 10, 13, 14, 15 }, -+- .oobavail = 9, -+- .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } -+-}; -+-#endif -+- -+-/* Write a chunk (page) of data to NAND. -+- * -+- * Caller always provides ExtendedTags data which are converted to a more -+- * compact (packed) form for storage in NAND. A mini-ECC runs over the -+- * contents of the tags meta-data; used to valid the tags when read. -+- * -+- * - Pack ExtendedTags to PackedTags1 form -+- * - Compute mini-ECC for PackedTags1 -+- * - Write data and packed tags to NAND. -+- * -+- * Note: Due to the use of the PackedTags1 meta-data which does not include -+- * a full sequence number (as found in the larger PackedTags2 form) it is -+- * necessary for Yaffs to re-write a chunk/page (just once) to mark it as -+- * discarded and dirty. This is not ideal: newer NAND parts are supposed -+- * to be written just once. When Yaffs performs this operation, this -+- * function is called with a NULL data pointer -- calling MTD write_oob -+- * without data is valid usage (2.6.17). -+- * -+- * Any underlying MTD error results in YAFFS_FAIL. -+- * Returns YAFFS_OK or YAFFS_FAIL. -+- */ -+-int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev, -+- int chunkInNAND, const __u8 * data, const yaffs_ExtendedTags * etags) -+-{ -+- struct mtd_info * mtd = dev->genericDevice; -+- int chunkBytes = dev->nDataBytesPerChunk; -+- loff_t addr = ((loff_t)chunkInNAND) * chunkBytes; -+- struct mtd_oob_ops ops; -+- yaffs_PackedTags1 pt1; -+- int retval; -+- -+- /* we assume that PackedTags1 and yaffs_Tags are compatible */ -+- compile_time_assertion(sizeof(yaffs_PackedTags1) == 12); -+- compile_time_assertion(sizeof(yaffs_Tags) == 8); -+- -+- yaffs_PackTags1(&pt1, etags); -+- yaffs_CalcTagsECC((yaffs_Tags *)&pt1); -+- -+- /* When deleting a chunk, the upper layer provides only skeletal -+- * etags, one with chunkDeleted set. However, we need to update the -+- * tags, not erase them completely. So we use the NAND write property -+- * that only zeroed-bits stick and set tag bytes to all-ones and -+- * zero just the (not) deleted bit. -+- */ -+-#ifndef CONFIG_YAFFS_9BYTE_TAGS -+- if (etags->chunkDeleted) { -+- memset(&pt1, 0xff, 8); -+- /* clear delete status bit to indicate deleted */ -+- pt1.deleted = 0; -+- } -+-#else -+- ((__u8 *)&pt1)[8] = 0xff; -+- if (etags->chunkDeleted) { -+- memset(&pt1, 0xff, 8); -+- /* zero pageStatus byte to indicate deleted */ -+- ((__u8 *)&pt1)[8] = 0; -+- } -+-#endif -+- -+- memset(&ops, 0, sizeof(ops)); -+- ops.mode = MTD_OOB_AUTO; -+- ops.len = (data) ? chunkBytes : 0; -+- ops.ooblen = YTAG1_SIZE; -+- ops.datbuf = (__u8 *)data; -+- ops.oobbuf = (__u8 *)&pt1; -+- -+- retval = mtd->write_oob(mtd, addr, &ops); -+- if (retval) { -+- yaffs_trace(YAFFS_TRACE_MTD, -+- "write_oob failed, chunk %d, mtd error %d\n", -+- chunkInNAND, retval); -+- } -+- return retval ? YAFFS_FAIL : YAFFS_OK; -+-} -+- -+-/* Return with empty ExtendedTags but add eccResult. -+- */ -+-static int rettags(yaffs_ExtendedTags * etags, int eccResult, int retval) -+-{ -+- if (etags) { -+- memset(etags, 0, sizeof(*etags)); -+- etags->eccResult = eccResult; -+- } -+- return retval; -+-} -+- -+-/* Read a chunk (page) from NAND. -+- * -+- * Caller expects ExtendedTags data to be usable even on error; that is, -+- * all members except eccResult and blockBad are zeroed. -+- * -+- * - Check ECC results for data (if applicable) -+- * - Check for blank/erased block (return empty ExtendedTags if blank) -+- * - Check the PackedTags1 mini-ECC (correct if necessary/possible) -+- * - Convert PackedTags1 to ExtendedTags -+- * - Update eccResult and blockBad members to refect state. -+- * -+- * Returns YAFFS_OK or YAFFS_FAIL. -+- */ -+-int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev, -+- int chunkInNAND, __u8 * data, yaffs_ExtendedTags * etags) -+-{ -+- struct mtd_info * mtd = dev->genericDevice; -+- int chunkBytes = dev->nDataBytesPerChunk; -+- loff_t addr = ((loff_t)chunkInNAND) * chunkBytes; -+- int eccres = YAFFS_ECC_RESULT_NO_ERROR; -+- struct mtd_oob_ops ops; -+- yaffs_PackedTags1 pt1; -+- int retval; -+- int deleted; -+- -+- memset(&ops, 0, sizeof(ops)); -+- ops.mode = MTD_OOB_AUTO; -+- ops.len = (data) ? chunkBytes : 0; -+- ops.ooblen = YTAG1_SIZE; -+- ops.datbuf = data; -+- ops.oobbuf = (__u8 *)&pt1; -+- -+-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) -+- /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug; -+- * help it out with ops.len = ops.ooblen when ops.datbuf == NULL. -+- */ -+- ops.len = (ops.datbuf) ? ops.len : ops.ooblen; -+-#endif -+- /* Read page and oob using MTD. -+- * Check status and determine ECC result. -+- */ -+- retval = mtd->read_oob(mtd, addr, &ops); -+- if (retval) { -+- yaffs_trace(YAFFS_TRACE_MTD, -+- "read_oob failed, chunk %d, mtd error %d\n", -+- chunkInNAND, retval); -+- } -+- -+- switch (retval) { -+- case 0: -+- /* no error */ -+- break; -+- -+- case -EUCLEAN: -+- /* MTD's ECC fixed the data */ -+- eccres = YAFFS_ECC_RESULT_FIXED; -+- dev->eccFixed++; -+- break; -+- -+- case -EBADMSG: -+- /* MTD's ECC could not fix the data */ -+- dev->eccUnfixed++; -+- /* fall into... */ -+- default: -+- rettags(etags, YAFFS_ECC_RESULT_UNFIXED, 0); -+- etags->blockBad = (mtd->block_isbad)(mtd, addr); -+- return YAFFS_FAIL; -+- } -+- -+- /* Check for a blank/erased chunk. -+- */ -+- if (yaffs_CheckFF((__u8 *)&pt1, 8)) { -+- /* when blank, upper layers want eccResult to be <= NO_ERROR */ -+- return rettags(etags, YAFFS_ECC_RESULT_NO_ERROR, YAFFS_OK); -+- } -+- -+-#ifndef CONFIG_YAFFS_9BYTE_TAGS -+- /* Read deleted status (bit) then return it to it's non-deleted -+- * state before performing tags mini-ECC check. pt1.deleted is -+- * inverted. -+- */ -+- deleted = !pt1.deleted; -+- pt1.deleted = 1; -+-#else -+- (void) deleted; /* not used */ -+-#endif -+- -+- /* Check the packed tags mini-ECC and correct if necessary/possible. -+- */ -+- retval = yaffs_CheckECCOnTags((yaffs_Tags *)&pt1); -+- switch (retval) { -+- case 0: -+- /* no tags error, use MTD result */ -+- break; -+- case 1: -+- /* recovered tags-ECC error */ -+- dev->tagsEccFixed++; -+- eccres = YAFFS_ECC_RESULT_FIXED; -+- break; -+- default: -+- /* unrecovered tags-ECC error */ -+- dev->tagsEccUnfixed++; -+- return rettags(etags, YAFFS_ECC_RESULT_UNFIXED, YAFFS_FAIL); -+- } -+- -+- /* Unpack the tags to extended form and set ECC result. -+- * [set shouldBeFF just to keep yaffs_UnpackTags1 happy] -+- */ -+- pt1.shouldBeFF = 0xFFFFFFFF; -+- yaffs_UnpackTags1(etags, &pt1); -+- etags->eccResult = eccres; -+- -+- /* Set deleted state. -+- */ -+-#ifndef CONFIG_YAFFS_9BYTE_TAGS -+- etags->chunkDeleted = deleted; -+-#else -+- etags->chunkDeleted = (yaffs_CountBits(((__u8 *)&pt1)[8]) < 7); -+-#endif -+- return YAFFS_OK; -+-} -+- -+-/* Mark a block bad. -+- * -+- * This is a persistant state. -+- * Use of this function should be rare. -+- * -+- * Returns YAFFS_OK or YAFFS_FAIL. -+- */ -+-int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) -+-{ -+- struct mtd_info * mtd = dev->genericDevice; -+- int blocksize = dev->nChunksPerBlock * dev->nDataBytesPerChunk; -+- int retval; -+- -+- yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", blockNo); -+- -+- retval = mtd->block_markbad(mtd, (loff_t)blocksize * blockNo); -+- return (retval) ? YAFFS_FAIL : YAFFS_OK; -+-} -+- -+-/* Check any MTD prerequists. -+- * -+- * Returns YAFFS_OK or YAFFS_FAIL. -+- */ -+-static int nandmtd1_TestPrerequists(struct mtd_info * mtd) -+-{ -+- /* 2.6.18 has mtd->ecclayout->oobavail */ -+- /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */ -+- int oobavail = mtd->ecclayout->oobavail; -+- -+- if (oobavail < YTAG1_SIZE) { -+- yaffs_trace(YAFFS_TRACE_ERROR, -+- "mtd device has only %d bytes for tags, need %d", -+- oobavail, YTAG1_SIZE); -+- return YAFFS_FAIL; -+- } -+- return YAFFS_OK; -+-} -+- -+-/* Query for the current state of a specific block. -+- * -+- * Examine the tags of the first chunk of the block and return the state: -+- * - YAFFS_BLOCK_STATE_DEAD, the block is marked bad -+- * - YAFFS_BLOCK_STATE_NEEDS_SCANNING, the block is in use -+- * - YAFFS_BLOCK_STATE_EMPTY, the block is clean -+- * -+- * Always returns YAFFS_OK. -+- */ -+-int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, -+- yaffs_BlockState * pState, int *pSequenceNumber) -+-{ -+- struct mtd_info * mtd = dev->genericDevice; -+- int chunkNo = blockNo * dev->nChunksPerBlock; -+- yaffs_ExtendedTags etags; -+- int state = YAFFS_BLOCK_STATE_DEAD; -+- int seqnum = 0; -+- int retval; -+- -+- /* We don't yet have a good place to test for MTD config prerequists. -+- * Do it here as we are called during the initial scan. -+- */ -+- if (nandmtd1_TestPrerequists(mtd) != YAFFS_OK) { -+- return YAFFS_FAIL; -+- } -+- -+- retval = nandmtd1_ReadChunkWithTagsFromNAND(dev, chunkNo, NULL, &etags); -+- if (etags.blockBad) { -+- yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, -+- "block %d is marked bad", blockNo); -+- state = YAFFS_BLOCK_STATE_DEAD; -+- } -+- else if (etags.chunkUsed) { -+- state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; -+- seqnum = etags.sequenceNumber; -+- } -+- else { -+- state = YAFFS_BLOCK_STATE_EMPTY; -+- } -+- -+- *pState = state; -+- *pSequenceNumber = seqnum; -+- -+- /* query always succeeds */ -+- return YAFFS_OK; -+-} -+- -+-#endif /*KERNEL_VERSION*/ -+- -+---Boundary-00=_5LbTGmt62YoutxM-- -+- -+- -+- -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_mtdif1.c linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif1.c -+--- linux-2.6.24.7/fs/yaffs2/yaffs_mtdif1.c 2009-04-21 14:57:10.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif1.c 1970-01-01 01:00:00.000000000 +0100 -+@@ -1,363 +0,0 @@ -+-/* -+- * YAFFS: Yet another FFS. A NAND-flash specific file system. -+- * yaffs_mtdif1.c NAND mtd interface functions for small-page NAND. -+- * -+- * Copyright (C) 2002 Aleph One Ltd. -+- * for Toby Churchill Ltd and Brightstar Engineering -+- * -+- * This program is free software; you can redistribute it and/or modify -+- * it under the terms of the GNU General Public License version 2 as -+- * published by the Free Software Foundation. -+- */ -+- -+-/* -+- * This module provides the interface between yaffs_nand.c and the -+- * MTD API. This version is used when the MTD interface supports the -+- * 'mtd_oob_ops' style calls to read_oob and write_oob, circa 2.6.17, -+- * and we have small-page NAND device. -+- * -+- * These functions are invoked via function pointers in yaffs_nand.c. -+- * This replaces functionality provided by functions in yaffs_mtdif.c -+- * and the yaffs_TagsCompatability functions in yaffs_tagscompat.c that are -+- * called in yaffs_mtdif.c when the function pointers are NULL. -+- * We assume the MTD layer is performing ECC (useNANDECC is true). -+- */ -+- -+-#include "yportenv.h" -+-#include "yaffs_guts.h" -+-#include "yaffs_packedtags1.h" -+-#include "yaffs_tagscompat.h" // for yaffs_CalcTagsECC -+- -+-#include "linux/kernel.h" -+-#include "linux/version.h" -+-#include "linux/types.h" -+-#include "linux/mtd/mtd.h" -+- -+-/* Don't compile this module if we don't have MTD's mtd_oob_ops interface */ -+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+- -+-const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.3 2007/05/15 20:16:11 ian Exp $"; -+- -+-#ifndef CONFIG_YAFFS_9BYTE_TAGS -+-# define YTAG1_SIZE 8 -+-#else -+-# define YTAG1_SIZE 9 -+-#endif -+- -+-#if 0 -+-/* Use the following nand_ecclayout with MTD when using -+- * CONFIG_YAFFS_9BYTE_TAGS and the older on-NAND tags layout. -+- * If you have existing Yaffs images and the byte order differs from this, -+- * adjust 'oobfree' to match your existing Yaffs data. -+- * -+- * This nand_ecclayout scatters/gathers to/from the old-yaffs layout with the -+- * pageStatus byte (at NAND spare offset 4) scattered/gathered from/to -+- * the 9th byte. -+- * -+- * Old-style on-NAND format: T0,T1,T2,T3,P,B,T4,T5,E0,E1,E2,T6,T7,E3,E4,E5 -+- * We have/need PackedTags1 plus pageStatus: T0,T1,T2,T3,T4,T5,T6,T7,P -+- * where Tn are the tag bytes, En are MTD's ECC bytes, P is the pageStatus -+- * byte and B is the small-page bad-block indicator byte. -+- */ -+-static struct nand_ecclayout nand_oob_16 = { -+- .eccbytes = 6, -+- .eccpos = { 8, 9, 10, 13, 14, 15 }, -+- .oobavail = 9, -+- .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } -+-}; -+-#endif -+- -+-/* Write a chunk (page) of data to NAND. -+- * -+- * Caller always provides ExtendedTags data which are converted to a more -+- * compact (packed) form for storage in NAND. A mini-ECC runs over the -+- * contents of the tags meta-data; used to valid the tags when read. -+- * -+- * - Pack ExtendedTags to PackedTags1 form -+- * - Compute mini-ECC for PackedTags1 -+- * - Write data and packed tags to NAND. -+- * -+- * Note: Due to the use of the PackedTags1 meta-data which does not include -+- * a full sequence number (as found in the larger PackedTags2 form) it is -+- * necessary for Yaffs to re-write a chunk/page (just once) to mark it as -+- * discarded and dirty. This is not ideal: newer NAND parts are supposed -+- * to be written just once. When Yaffs performs this operation, this -+- * function is called with a NULL data pointer -- calling MTD write_oob -+- * without data is valid usage (2.6.17). -+- * -+- * Any underlying MTD error results in YAFFS_FAIL. -+- * Returns YAFFS_OK or YAFFS_FAIL. -+- */ -+-int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev, -+- int chunkInNAND, const __u8 * data, const yaffs_ExtendedTags * etags) -+-{ -+- struct mtd_info * mtd = dev->genericDevice; -+- int chunkBytes = dev->nDataBytesPerChunk; -+- loff_t addr = ((loff_t)chunkInNAND) * chunkBytes; -+- struct mtd_oob_ops ops; -+- yaffs_PackedTags1 pt1; -+- int retval; -+- -+- /* we assume that PackedTags1 and yaffs_Tags are compatible */ -+- compile_time_assertion(sizeof(yaffs_PackedTags1) == 12); -+- compile_time_assertion(sizeof(yaffs_Tags) == 8); -+- -+- dev->nPageWrites++; -+- -+- yaffs_PackTags1(&pt1, etags); -+- yaffs_CalcTagsECC((yaffs_Tags *)&pt1); -+- -+- /* When deleting a chunk, the upper layer provides only skeletal -+- * etags, one with chunkDeleted set. However, we need to update the -+- * tags, not erase them completely. So we use the NAND write property -+- * that only zeroed-bits stick and set tag bytes to all-ones and -+- * zero just the (not) deleted bit. -+- */ -+-#ifndef CONFIG_YAFFS_9BYTE_TAGS -+- if (etags->chunkDeleted) { -+- memset(&pt1, 0xff, 8); -+- /* clear delete status bit to indicate deleted */ -+- pt1.deleted = 0; -+- } -+-#else -+- ((__u8 *)&pt1)[8] = 0xff; -+- if (etags->chunkDeleted) { -+- memset(&pt1, 0xff, 8); -+- /* zero pageStatus byte to indicate deleted */ -+- ((__u8 *)&pt1)[8] = 0; -+- } -+-#endif -+- -+- memset(&ops, 0, sizeof(ops)); -+- ops.mode = MTD_OOB_AUTO; -+- ops.len = (data) ? chunkBytes : 0; -+- ops.ooblen = YTAG1_SIZE; -+- ops.datbuf = (__u8 *)data; -+- ops.oobbuf = (__u8 *)&pt1; -+- -+- retval = mtd->write_oob(mtd, addr, &ops); -+- if (retval) { -+- yaffs_trace(YAFFS_TRACE_MTD, -+- "write_oob failed, chunk %d, mtd error %d\n", -+- chunkInNAND, retval); -+- } -+- return retval ? YAFFS_FAIL : YAFFS_OK; -+-} -+- -+-/* Return with empty ExtendedTags but add eccResult. -+- */ -+-static int rettags(yaffs_ExtendedTags * etags, int eccResult, int retval) -+-{ -+- if (etags) { -+- memset(etags, 0, sizeof(*etags)); -+- etags->eccResult = eccResult; -+- } -+- return retval; -+-} -+- -+-/* Read a chunk (page) from NAND. -+- * -+- * Caller expects ExtendedTags data to be usable even on error; that is, -+- * all members except eccResult and blockBad are zeroed. -+- * -+- * - Check ECC results for data (if applicable) -+- * - Check for blank/erased block (return empty ExtendedTags if blank) -+- * - Check the PackedTags1 mini-ECC (correct if necessary/possible) -+- * - Convert PackedTags1 to ExtendedTags -+- * - Update eccResult and blockBad members to refect state. -+- * -+- * Returns YAFFS_OK or YAFFS_FAIL. -+- */ -+-int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev, -+- int chunkInNAND, __u8 * data, yaffs_ExtendedTags * etags) -+-{ -+- struct mtd_info * mtd = dev->genericDevice; -+- int chunkBytes = dev->nDataBytesPerChunk; -+- loff_t addr = ((loff_t)chunkInNAND) * chunkBytes; -+- int eccres = YAFFS_ECC_RESULT_NO_ERROR; -+- struct mtd_oob_ops ops; -+- yaffs_PackedTags1 pt1; -+- int retval; -+- int deleted; -+- -+- dev->nPageReads++; -+- -+- memset(&ops, 0, sizeof(ops)); -+- ops.mode = MTD_OOB_AUTO; -+- ops.len = (data) ? chunkBytes : 0; -+- ops.ooblen = YTAG1_SIZE; -+- ops.datbuf = data; -+- ops.oobbuf = (__u8 *)&pt1; -+- -+-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) -+- /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug; -+- * help it out with ops.len = ops.ooblen when ops.datbuf == NULL. -+- */ -+- ops.len = (ops.datbuf) ? ops.len : ops.ooblen; -+-#endif -+- /* Read page and oob using MTD. -+- * Check status and determine ECC result. -+- */ -+- retval = mtd->read_oob(mtd, addr, &ops); -+- if (retval) { -+- yaffs_trace(YAFFS_TRACE_MTD, -+- "read_oob failed, chunk %d, mtd error %d\n", -+- chunkInNAND, retval); -+- } -+- -+- switch (retval) { -+- case 0: -+- /* no error */ -+- break; -+- -+- case -EUCLEAN: -+- /* MTD's ECC fixed the data */ -+- eccres = YAFFS_ECC_RESULT_FIXED; -+- dev->eccFixed++; -+- break; -+- -+- case -EBADMSG: -+- /* MTD's ECC could not fix the data */ -+- dev->eccUnfixed++; -+- /* fall into... */ -+- default: -+- rettags(etags, YAFFS_ECC_RESULT_UNFIXED, 0); -+- etags->blockBad = (mtd->block_isbad)(mtd, addr); -+- return YAFFS_FAIL; -+- } -+- -+- /* Check for a blank/erased chunk. -+- */ -+- if (yaffs_CheckFF((__u8 *)&pt1, 8)) { -+- /* when blank, upper layers want eccResult to be <= NO_ERROR */ -+- return rettags(etags, YAFFS_ECC_RESULT_NO_ERROR, YAFFS_OK); -+- } -+- -+-#ifndef CONFIG_YAFFS_9BYTE_TAGS -+- /* Read deleted status (bit) then return it to it's non-deleted -+- * state before performing tags mini-ECC check. pt1.deleted is -+- * inverted. -+- */ -+- deleted = !pt1.deleted; -+- pt1.deleted = 1; -+-#else -+- deleted = (yaffs_CountBits(((__u8 *)&pt1)[8]) < 7); -+-#endif -+- -+- /* Check the packed tags mini-ECC and correct if necessary/possible. -+- */ -+- retval = yaffs_CheckECCOnTags((yaffs_Tags *)&pt1); -+- switch (retval) { -+- case 0: -+- /* no tags error, use MTD result */ -+- break; -+- case 1: -+- /* recovered tags-ECC error */ -+- dev->tagsEccFixed++; -+- if (eccres == YAFFS_ECC_RESULT_NO_ERROR) -+- eccres = YAFFS_ECC_RESULT_FIXED; -+- break; -+- default: -+- /* unrecovered tags-ECC error */ -+- dev->tagsEccUnfixed++; -+- return rettags(etags, YAFFS_ECC_RESULT_UNFIXED, YAFFS_FAIL); -+- } -+- -+- /* Unpack the tags to extended form and set ECC result. -+- * [set shouldBeFF just to keep yaffs_UnpackTags1 happy] -+- */ -+- pt1.shouldBeFF = 0xFFFFFFFF; -+- yaffs_UnpackTags1(etags, &pt1); -+- etags->eccResult = eccres; -+- -+- /* Set deleted state */ -+- etags->chunkDeleted = deleted; -+- return YAFFS_OK; -+-} -+- -+-/* Mark a block bad. -+- * -+- * This is a persistant state. -+- * Use of this function should be rare. -+- * -+- * Returns YAFFS_OK or YAFFS_FAIL. -+- */ -+-int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) -+-{ -+- struct mtd_info * mtd = dev->genericDevice; -+- int blocksize = dev->nChunksPerBlock * dev->nDataBytesPerChunk; -+- int retval; -+- -+- yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", blockNo); -+- -+- retval = mtd->block_markbad(mtd, (loff_t)blocksize * blockNo); -+- return (retval) ? YAFFS_FAIL : YAFFS_OK; -+-} -+- -+-/* Check any MTD prerequists. -+- * -+- * Returns YAFFS_OK or YAFFS_FAIL. -+- */ -+-static int nandmtd1_TestPrerequists(struct mtd_info * mtd) -+-{ -+- /* 2.6.18 has mtd->ecclayout->oobavail */ -+- /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */ -+- int oobavail = mtd->ecclayout->oobavail; -+- -+- if (oobavail < YTAG1_SIZE) { -+- yaffs_trace(YAFFS_TRACE_ERROR, -+- "mtd device has only %d bytes for tags, need %d\n", -+- oobavail, YTAG1_SIZE); -+- return YAFFS_FAIL; -+- } -+- return YAFFS_OK; -+-} -+- -+-/* Query for the current state of a specific block. -+- * -+- * Examine the tags of the first chunk of the block and return the state: -+- * - YAFFS_BLOCK_STATE_DEAD, the block is marked bad -+- * - YAFFS_BLOCK_STATE_NEEDS_SCANNING, the block is in use -+- * - YAFFS_BLOCK_STATE_EMPTY, the block is clean -+- * -+- * Always returns YAFFS_OK. -+- */ -+-int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, -+- yaffs_BlockState * pState, int *pSequenceNumber) -+-{ -+- struct mtd_info * mtd = dev->genericDevice; -+- int chunkNo = blockNo * dev->nChunksPerBlock; -+- yaffs_ExtendedTags etags; -+- int state = YAFFS_BLOCK_STATE_DEAD; -+- int seqnum = 0; -+- int retval; -+- -+- /* We don't yet have a good place to test for MTD config prerequists. -+- * Do it here as we are called during the initial scan. -+- */ -+- if (nandmtd1_TestPrerequists(mtd) != YAFFS_OK) { -+- return YAFFS_FAIL; -+- } -+- -+- retval = nandmtd1_ReadChunkWithTagsFromNAND(dev, chunkNo, NULL, &etags); -+- if (etags.blockBad) { -+- yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, -+- "block %d is marked bad", blockNo); -+- state = YAFFS_BLOCK_STATE_DEAD; -+- } -+- else if (etags.chunkUsed) { -+- state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; -+- seqnum = etags.sequenceNumber; -+- } -+- else { -+- state = YAFFS_BLOCK_STATE_EMPTY; -+- } -+- -+- *pState = state; -+- *pSequenceNumber = seqnum; -+- -+- /* query always succeeds */ -+- return YAFFS_OK; -+-} -+- -+-#endif /*KERNEL_VERSION*/ -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_mtdif1.h linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif1.h -+--- linux-2.6.24.7/fs/yaffs2/yaffs_mtdif1.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif1.h 1970-01-01 01:00:00.000000000 +0100 -+@@ -1,28 +0,0 @@ -+-/* -+- * YAFFS: Yet another Flash File System. A NAND-flash specific file system. -+- * -+- * Copyright (C) 2002-2007 Aleph One Ltd. -+- * for Toby Churchill Ltd and Brightstar Engineering -+- * -+- * This program is free software; you can redistribute it and/or modify -+- * it under the terms of the GNU Lesser General Public License version 2.1 as -+- * published by the Free Software Foundation. -+- * -+- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. -+- */ -+- -+-#ifndef __YAFFS_MTDIF1_H__ -+-#define __YAFFS_MTDIF1_H__ -+- -+-int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, -+- const __u8 * data, const yaffs_ExtendedTags * tags); -+- -+-int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, -+- __u8 * data, yaffs_ExtendedTags * tags); -+- -+-int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo); -+- -+-int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, -+- yaffs_BlockState * state, int *sequenceNumber); -+- -+-#endif -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_mtdif2.c linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif2.c -+--- linux-2.6.24.7/fs/yaffs2/yaffs_mtdif2.c 2009-04-21 14:57:10.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif2.c 2009-04-21 15:01:02.000000000 +0200 -+@@ -14,19 +14,152 @@ -+ /* mtd interface for YAFFS2 */ -+ -+ const char *yaffs_mtdif2_c_version = -+- "$Id: yaffs_mtdif2.c,v 1.17 2007-02-14 01:09:06 wookey Exp $"; -++ "$Id: yaffs_mtdif2.c,v 1.1.1.1 2008-03-28 04:29:21 jlwei Exp $"; -+ -+ #include "yportenv.h" -+- -+- -+ #include "yaffs_mtdif2.h" -+- -+ #include "linux/mtd/mtd.h" -+ #include "linux/types.h" -+ #include "linux/time.h" -+ -+ #include "yaffs_packedtags2.h" -+ -++#define PT2_BYTES 25 -++ -++void nandmtd2_pt2buf(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw) -++{ -++ struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); -++ int i, j = 0, k, n; -++ __u8 pt2_byte_buf[PT2_BYTES]; -++ -++ /* Pack buffer with 0xff */ -++ for (i = 0; i < mtd->oobsize; i++) -++ dev->spareBuffer[i] = 0xff; -++ -++ if (!is_raw) { -++ *((unsigned int *) &dev->spareBuffer[0]) = pt->t.sequenceNumber; -++ *((unsigned int *) &dev->spareBuffer[4]) = pt->t.objectId; -++ *((unsigned int *) &dev->spareBuffer[8]) = pt->t.chunkId; -++ *((unsigned int *) &dev->spareBuffer[12]) = pt->t.byteCount; -++ dev->spareBuffer[16] = pt->ecc.colParity; -++ dev->spareBuffer[17] = pt->ecc.lineParity & 0xff; -++ dev->spareBuffer[18] = (pt->ecc.lineParity >> 8) & 0xff; -++ dev->spareBuffer[19] = (pt->ecc.lineParity >> 16) & 0xff; -++ dev->spareBuffer[20] = (pt->ecc.lineParity >> 24) & 0xff; -++ dev->spareBuffer[21] = pt->ecc.lineParityPrime & 0xff; -++ dev->spareBuffer[22] = (pt->ecc.lineParityPrime >> 8) & 0xff; -++ dev->spareBuffer[23] = (pt->ecc.lineParityPrime >> 16) & 0xff; -++ dev->spareBuffer[24] = (pt->ecc.lineParityPrime >> 24) & 0xff; -++ } else { -++ *((unsigned int *) &pt2_byte_buf[0]) = pt->t.sequenceNumber; -++ *((unsigned int *) &pt2_byte_buf[4]) = pt->t.objectId; -++ *((unsigned int *) &pt2_byte_buf[8]) = pt->t.chunkId; -++ *((unsigned int *) &pt2_byte_buf[12]) = pt->t.byteCount; -++ pt2_byte_buf[16] = pt->ecc.colParity; -++ pt2_byte_buf[17] = pt->ecc.lineParity & 0xff; -++ pt2_byte_buf[18] = (pt->ecc.lineParity >> 8) & 0xff; -++ pt2_byte_buf[19] = (pt->ecc.lineParity >> 16) & 0xff; -++ pt2_byte_buf[20] = (pt->ecc.lineParity >> 24) & 0xff; -++ pt2_byte_buf[21] = pt->ecc.lineParityPrime & 0xff; -++ pt2_byte_buf[22] = (pt->ecc.lineParityPrime >> 8) & 0xff; -++ pt2_byte_buf[23] = (pt->ecc.lineParityPrime >> 16) & 0xff; -++ pt2_byte_buf[24] = (pt->ecc.lineParityPrime >> 24) & 0xff; -++ -++// k = mtd->oobinfo.oobfree[j][0]; -++// n = mtd->oobinfo.oobfree[j][1]; -++ -++ k = mtd->ecclayout->oobfree[j].offset; -++ n = mtd->ecclayout->oobfree[j].length; -++ if (n == 0) { -++ T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR))); -++ YBUG(); -++ } -++ -++ for (i = 0; i < PT2_BYTES; i++) { -++ if (n == 0) { -++ j++; -++// k = mtd->oobinfo.oobfree[j][0]; -++// n = mtd->oobinfo.oobfree[j][1]; -++ k = mtd->ecclayout->oobfree[j].offset; -++ n = mtd->ecclayout->oobfree[j].length; -++ -++ if (n == 0) { -++ T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR))); -++ YBUG(); -++ } -++ } -++ dev->spareBuffer[k++] = pt2_byte_buf[i]; -++ n--; -++ } -++ } -++ -++} -++ -++void nandmtd2_buf2pt(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw) -++{ -++ struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); -++ int i, j = 0, k, n; -++ __u8 pt2_byte_buf[PT2_BYTES]; -++ -++ -++ if (!is_raw) { -++ pt->t.sequenceNumber = *((unsigned int *) &dev->spareBuffer[0]); -++ pt->t.objectId = *((unsigned int *) &dev->spareBuffer[4]); -++ pt->t.chunkId = *((unsigned int *) &dev->spareBuffer[8]); -++ pt->t.byteCount = *((unsigned int *) &dev->spareBuffer[12]); -++ pt->ecc.colParity = dev->spareBuffer[16]; -++ pt->ecc.lineParity = (dev->spareBuffer[17] & 0x000000ff) | -++ ((dev->spareBuffer[18] << 8) & 0x0000ff00) | -++ ((dev->spareBuffer[19] << 16) & 0x00ff0000) | -++ ((dev->spareBuffer[20] << 24) & 0xff000000); -++ pt->ecc.lineParityPrime = (dev->spareBuffer[21] & 0x000000ff) | -++ ((dev->spareBuffer[22] << 8) & 0x0000ff00) | -++ ((dev->spareBuffer[23] << 16) & 0x00ff0000) | -++ ((dev->spareBuffer[24] << 24) & 0xff000000); -++ } else { -++// k = mtd->oobinfo.oobfree[j][0]; -++// n = mtd->oobinfo.oobfree[j][1]; -++ -++ k = mtd->ecclayout->oobfree[j].offset; -++ n = mtd->ecclayout->oobfree[j].length; -++ -++ if (n == 0) { -++ T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR))); -++ YBUG(); -++ } -++ -++ for (i = 0; i < PT2_BYTES; i++) { -++ if (n == 0) { -++ j++; -++// k = mtd->oobinfo.oobfree[j][0]; -++// n = mtd->oobinfo.oobfree[j][1]; -++ k = mtd->ecclayout->oobfree[j].offset; -++ n = mtd->ecclayout->oobfree[j].length; -++ -++ if (n == 0) { -++ T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR))); -++ YBUG(); -++ } -++ } -++ pt2_byte_buf[i] = dev->spareBuffer[k++]; -++ n--; -++ } -++ pt->t.sequenceNumber = *((unsigned int *) &pt2_byte_buf[0]); -++ pt->t.objectId = *((unsigned int *) &pt2_byte_buf[4]); -++ pt->t.chunkId = *((unsigned int *) &pt2_byte_buf[8]); -++ pt->t.byteCount = *((unsigned int *) &pt2_byte_buf[12]); -++ pt->ecc.colParity = pt2_byte_buf[16]; -++ pt->ecc.lineParity = (pt2_byte_buf[17] & 0x000000ff) | -++ ((pt2_byte_buf[18] << 8) & 0x0000ff00) | -++ ((pt2_byte_buf[19] << 16) & 0x00ff0000) | -++ ((pt2_byte_buf[20] << 24) & 0xff000000); -++ pt->ecc.lineParityPrime = (pt2_byte_buf[21] & 0x000000ff) | -++ ((pt2_byte_buf[22] << 8) & 0x0000ff00) | -++ ((pt2_byte_buf[23] << 16) & 0x00ff0000) | -++ ((pt2_byte_buf[24] << 24) & 0xff000000); -++ } -++} -++ -+ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, -+ const __u8 * data, -+ const yaffs_ExtendedTags * tags) -+@@ -38,9 +171,7 @@ -+ size_t dummy; -+ #endif -+ int retval = 0; -+- -+- loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; -+- -++ loff_mtd_t addr = ((loff_mtd_t) chunkInNAND) * dev->nDataBytesPerChunk; -+ yaffs_PackedTags2 pt; -+ -+ T(YAFFS_TRACE_MTD, -+@@ -55,12 +186,14 @@ -+ BUG(); /* both tags and data should always be present */ -+ -+ if (data) { -++ nandmtd2_pt2buf(dev, &pt, 0); //modify -+ ops.mode = MTD_OOB_AUTO; -+ ops.ooblen = sizeof(pt); -+ ops.len = dev->nDataBytesPerChunk; -+ ops.ooboffs = 0; -+ ops.datbuf = (__u8 *)data; -+- ops.oobbuf = (void *)&pt; -++// ops.oobbuf = (void *)&pt; //modify -++ ops.oobbuf = (void *)dev->spareBuffer; //modify -+ retval = mtd->write_oob(mtd, addr, &ops); -+ } else -+ BUG(); /* both tags and data should always be present */ -+@@ -70,24 +203,27 @@ -+ } -+ -+ if (data && tags) { -++ nandmtd2_pt2buf(dev, &pt, 0); -+ if (dev->useNANDECC) -+ retval = -+ mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, -+- &dummy, data, (__u8 *) & pt, NULL); -++ &dummy, data, dev->spareBuffer, NULL); -+ else -+ retval = -+ mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, -+- &dummy, data, (__u8 *) & pt, NULL); -++ &dummy, data, dev->spareBuffer, NULL); -+ } else { -+- if (data) -++ if (data) { -+ retval = -+ mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy, -+ data); -+- if (tags) -++ } -++ if (tags) { -++ nandmtd2_pt2buf(dev, &pt, 1); -+ retval = -+ mtd->write_oob(mtd, addr, mtd->oobsize, &dummy, -+- (__u8 *) & pt); -+- -++ dev->spareBuffer); -++ } -+ } -+ #endif -+ -+@@ -104,11 +240,9 @@ -+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+ struct mtd_oob_ops ops; -+ #endif -+- size_t dummy; -++ size_mtd_t dummy; -+ int retval = 0; -+- -+- loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; -+- -++ loff_mtd_t addr = ((loff_mtd_t) chunkInNAND) * dev->nDataBytesPerChunk; -+ yaffs_PackedTags2 pt; -+ -+ T(YAFFS_TRACE_MTD, -+@@ -128,6 +262,7 @@ -+ ops.datbuf = data; -+ ops.oobbuf = dev->spareBuffer; -+ retval = mtd->read_oob(mtd, addr, &ops); -++ nandmtd2_buf2pt(dev, &pt, 0); //modify by yliu -+ } -+ #else -+ if (data && tags) { -+@@ -142,23 +277,25 @@ -+ &dummy, data, dev->spareBuffer, -+ NULL); -+ } -++ nandmtd2_buf2pt(dev, &pt, 0); -+ } else { -+- if (data) -++ if (data) { -+ retval = -+ mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy, -+ data); -+- if (tags) -++ } -++ if (tags) { -+ retval = -+ mtd->read_oob(mtd, addr, mtd->oobsize, &dummy, -+ dev->spareBuffer); -++ nandmtd2_buf2pt(dev, &pt, 1); -++ } -+ } -+ #endif -+ -+- memcpy(&pt, dev->spareBuffer, sizeof(pt)); -+- -+ if (tags) -+ yaffs_UnpackTags2(tags, &pt); -+- -++ -+ if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR) -+ tags->eccResult = YAFFS_ECC_RESULT_UNFIXED; -+ -+@@ -177,7 +314,7 @@ -+ -+ retval = -+ mtd->block_markbad(mtd, -+- blockNo * dev->nChunksPerBlock * -++ (u64)blockNo * dev->nChunksPerBlock * -+ dev->nDataBytesPerChunk); -+ -+ if (retval == 0) -+@@ -195,11 +332,11 @@ -+ -+ T(YAFFS_TRACE_MTD, -+ (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo)); -++ -+ retval = -+ mtd->block_isbad(mtd, -+- blockNo * dev->nChunksPerBlock * -++ (u64)blockNo * dev->nChunksPerBlock * -+ dev->nDataBytesPerChunk); -+- -+ if (retval) { -+ T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR))); -+ -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_mtdif2.h linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif2.h -+--- linux-2.6.24.7/fs/yaffs2/yaffs_mtdif2.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif2.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ /* -+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_nand.c linux-2.6.24.7.new/fs/yaffs2/yaffs_nand.c -+--- linux-2.6.24.7/fs/yaffs2/yaffs_nand.c 2009-04-21 14:57:10.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_nand.c 2009-04-21 15:01:02.000000000 +0200 -+@@ -10,9 +10,9 @@ -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+- -++ -+ const char *yaffs_nand_c_version = -+- "$Id: yaffs_nand.c,v 1.7 2007-02-14 01:09:06 wookey Exp $"; -++ "$Id: yaffs_nand.c,v 1.1.1.1 2008-03-28 04:29:21 jlwei Exp $"; -+ -+ #include "yaffs_nand.h" -+ #include "yaffs_tagscompat.h" -+@@ -25,9 +25,9 @@ -+ { -+ int result; -+ yaffs_ExtendedTags localTags; -+- -++ -+ int realignedChunkInNAND = chunkInNAND - dev->chunkOffset; -+- -++ -+ /* If there are no tags provided, use local tags to get prioritised gc working */ -+ if(!tags) -+ tags = &localTags; -+@@ -39,14 +39,14 @@ -+ result = yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(dev, -+ realignedChunkInNAND, -+ buffer, -+- tags); -+- if(tags && -+- tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR){ -++ tags); -+ -++ if(tags && -++ tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR){ -+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->nChunksPerBlock); -+ yaffs_HandleChunkError(dev,bi); -+ } -+- -++ -+ return result; -+ } -+ -+@@ -57,7 +57,7 @@ -+ { -+ chunkInNAND -= dev->chunkOffset; -+ -+- -++ -+ if (tags) { -+ tags->sequenceNumber = dev->sequenceNumber; -+ tags->chunkUsed = 1; -+@@ -131,4 +131,4 @@ -+ } -+ -+ -+- -++ -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_nand.h linux-2.6.24.7.new/fs/yaffs2/yaffs_nand.h -+--- linux-2.6.24.7/fs/yaffs2/yaffs_nand.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_nand.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ /* -+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_nandemul2k.h linux-2.6.24.7.new/fs/yaffs2/yaffs_nandemul2k.h -+--- linux-2.6.24.7/fs/yaffs2/yaffs_nandemul2k.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_nandemul2k.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ /* -+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_packedtags1.h linux-2.6.24.7.new/fs/yaffs2/yaffs_packedtags1.h -+--- linux-2.6.24.7/fs/yaffs2/yaffs_packedtags1.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_packedtags1.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ /* -+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_packedtags2.c linux-2.6.24.7.new/fs/yaffs2/yaffs_packedtags2.c -+--- linux-2.6.24.7/fs/yaffs2/yaffs_packedtags2.c 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_packedtags2.c 2009-04-21 15:01:02.000000000 +0200 -+@@ -40,7 +40,8 @@ -+ static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt) -+ { -+ T(YAFFS_TRACE_MTD, -+- (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR), -++// T(YAFFS_TRACE_ALWAYS, -++ (TSTR("packed tags obj %x chunk %x byte %x seq %x" TENDSTR), -+ pt->t.objectId, pt->t.chunkId, pt->t.byteCount, -+ pt->t.sequenceNumber)); -+ } -+@@ -48,9 +49,10 @@ -+ static void yaffs_DumpTags2(const yaffs_ExtendedTags * t) -+ { -+ T(YAFFS_TRACE_MTD, -++// T(YAFFS_TRACE_ALWAYS, -+ (TSTR -+- ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte " -+- "%d del %d ser %d seq %d" -++ ("ext.tags eccres %x blkbad %x chused %x obj %x chunk%x byte " -++ "%x del %x ser %x seq %x" -+ TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId, -+ t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber, -+ t->sequenceNumber)); -+@@ -89,10 +91,10 @@ -+ } -+ } -+ -+- yaffs_DumpPackedTags2(pt); -+- yaffs_DumpTags2(t); -++// yaffs_DumpPackedTags2(pt); -++// yaffs_DumpTags2(t); -+ -+-#ifndef YAFFS_IGNORE_TAGS_ECC -++#if !defined(YAFFS_IGNORE_TAGS_ECC) && !defined(CONFIG_MTD_HW_BCH_ECC) -+ { -+ yaffs_ECCCalculateOther((unsigned char *)&pt->t, -+ sizeof(yaffs_PackedTags2TagsPart), -+@@ -103,14 +105,11 @@ -+ -+ void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt) -+ { -+- -+- memset(t, 0, sizeof(yaffs_ExtendedTags)); -+- -+ yaffs_InitialiseTags(t); -+ -+ if (pt->t.sequenceNumber != 0xFFFFFFFF) { -+ /* Page is in use */ -+-#ifdef YAFFS_IGNORE_TAGS_ECC -++#if defined(YAFFS_IGNORE_TAGS_ECC) || defined(CONFIG_MTD_HW_BCH_ECC) -+ { -+ t->eccResult = YAFFS_ECC_RESULT_NO_ERROR; -+ } -+@@ -118,20 +117,23 @@ -+ { -+ yaffs_ECCOther ecc; -+ int result; -++#if defined(CONFIG_YAFFS_ECC_HAMMING) -+ yaffs_ECCCalculateOther((unsigned char *)&pt->t, -+ sizeof -+ (yaffs_PackedTags2TagsPart), -+ &ecc); -++#endif -+ result = -+ yaffs_ECCCorrectOther((unsigned char *)&pt->t, -+ sizeof -+ (yaffs_PackedTags2TagsPart), -+ &pt->ecc, &ecc); -++ -+ switch(result){ -+- case 0: -+- t->eccResult = YAFFS_ECC_RESULT_NO_ERROR; -++ case 0: -++ t->eccResult = YAFFS_ECC_RESULT_NO_ERROR; -+ break; -+- case 1: -++ case 1: -+ t->eccResult = YAFFS_ECC_RESULT_FIXED; -+ break; -+ case -1: -+@@ -175,8 +177,8 @@ -+ } -+ } -+ } -+- -++// printk("\n TAG %d",t->chunkUsed); -+ yaffs_DumpPackedTags2(pt); -+ yaffs_DumpTags2(t); -+- -++// printk("\n TAG %d",t->chunkUsed); -+ } -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_packedtags2.h linux-2.6.24.7.new/fs/yaffs2/yaffs_packedtags2.h -+--- linux-2.6.24.7/fs/yaffs2/yaffs_packedtags2.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_packedtags2.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ /* -+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_qsort.c linux-2.6.24.7.new/fs/yaffs2/yaffs_qsort.c -+--- linux-2.6.24.7/fs/yaffs2/yaffs_qsort.c 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_qsort.c 2009-04-21 15:01:02.000000000 +0200 -+@@ -50,7 +50,7 @@ -+ static __inline void -+ swapfunc(char *a, char *b, int n, int swaptype) -+ { -+- if (swaptype <= 1) -++ if (swaptype <= 1) -+ swapcode(long, a, b, n) -+ else -+ swapcode(char, a, b, n) -+@@ -74,13 +74,8 @@ -+ :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); -+ } -+ -+-#ifndef min -+-#define min(a,b) (((a) < (b)) ? (a) : (b)) -+-#endif -+- -+ void -+-yaffs_qsort(void *aa, size_t n, size_t es, -+- int (*cmp)(const void *, const void *)) -++qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *)) -+ { -+ char *pa, *pb, *pc, *pd, *pl, *pm, *pn; -+ int d, r, swaptype, swap_cnt; -+@@ -137,7 +132,7 @@ -+ } -+ if (swap_cnt == 0) { /* Switch to insertion sort */ -+ for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) -+- for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; -++ for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; -+ pl -= es) -+ swap(pl, pl - es); -+ return; -+@@ -149,12 +144,12 @@ -+ r = min((long)(pd - pc), (long)(pn - pd - es)); -+ vecswap(pb, pn - r, r); -+ if ((r = pb - pa) > es) -+- yaffs_qsort(a, r / es, es, cmp); -+- if ((r = pd - pc) > es) { -++ qsort(a, r / es, es, cmp); -++ if ((r = pd - pc) > es) { -+ /* Iterate rather than recurse to save stack space */ -+ a = pn - r; -+ n = r / es; -+ goto loop; -+ } -+-/* yaffs_qsort(pn - r, r / es, es, cmp);*/ -++/* qsort(pn - r, r / es, es, cmp);*/ -+ } -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_qsort.h linux-2.6.24.7.new/fs/yaffs2/yaffs_qsort.h -+--- linux-2.6.24.7/fs/yaffs2/yaffs_qsort.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_qsort.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ /* -+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+@@ -17,7 +17,7 @@ -+ #ifndef __YAFFS_QSORT_H__ -+ #define __YAFFS_QSORT_H__ -+ -+-extern void yaffs_qsort (void *const base, size_t total_elems, size_t size, -++extern void qsort (void *const base, size_t total_elems, size_t size, -+ int (*cmp)(const void *, const void *)); -+ -+ #endif -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_tagscompat.c linux-2.6.24.7.new/fs/yaffs2/yaffs_tagscompat.c -+--- linux-2.6.24.7/fs/yaffs2/yaffs_tagscompat.c 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_tagscompat.c 2009-04-21 15:01:02.000000000 +0200 -+@@ -45,7 +45,7 @@ -+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 -+ }; -+ -+-int yaffs_CountBits(__u8 x) -++static int yaffs_CountBits(__u8 x) -+ { -+ int retVal; -+ retVal = yaffs_countBitsTable[x]; -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_tagscompat.h linux-2.6.24.7.new/fs/yaffs2/yaffs_tagscompat.h -+--- linux-2.6.24.7/fs/yaffs2/yaffs_tagscompat.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_tagscompat.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ /* -+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+@@ -33,8 +33,4 @@ -+ int blockNo, yaffs_BlockState * -+ state, int *sequenceNumber); -+ -+-void yaffs_CalcTagsECC(yaffs_Tags * tags); -+-int yaffs_CheckECCOnTags(yaffs_Tags * tags); -+-int yaffs_CountBits(__u8 byte); -+- -+ #endif -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_tagsvalidity.h linux-2.6.24.7.new/fs/yaffs2/yaffs_tagsvalidity.h -+--- linux-2.6.24.7/fs/yaffs2/yaffs_tagsvalidity.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffs_tagsvalidity.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ /* -+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+diff -urN linux-2.6.24.7/fs/yaffs2/yaffsinterface.h linux-2.6.24.7.new/fs/yaffs2/yaffsinterface.h -+--- linux-2.6.24.7/fs/yaffs2/yaffsinterface.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yaffsinterface.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ /* -+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+diff -urN linux-2.6.24.7/fs/yaffs2/yportenv.h linux-2.6.24.7.new/fs/yaffs2/yportenv.h -+--- linux-2.6.24.7/fs/yaffs2/yportenv.h 2009-04-09 17:39:09.000000000 +0200 -++++ linux-2.6.24.7.new/fs/yaffs2/yportenv.h 2009-04-21 15:01:02.000000000 +0200 -+@@ -1,5 +1,5 @@ -+ /* -+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+@@ -32,7 +32,6 @@ -+ #endif -+ #include -+ #include -+-#include -+ #include -+ #include -+ #include -+@@ -42,7 +41,6 @@ -+ #define _Y(x) x -+ #define yaffs_strcpy(a,b) strcpy(a,b) -+ #define yaffs_strncpy(a,b,c) strncpy(a,b,c) -+-#define yaffs_strncmp(a,b,c) strncmp(a,b,c) -+ #define yaffs_strlen(s) strlen(s) -+ #define yaffs_sprintf sprintf -+ #define yaffs_toupper(a) toupper(a) -+@@ -62,7 +60,7 @@ -+ // KR - added for use in scan so processes aren't blocked indefinitely. -+ #define YYIELD() schedule() -+ -+-#define YAFFS_ROOT_MODE 0666 -++#define YAFFS_ROOT_MODE 0666 -+ #define YAFFS_LOSTNFOUND_MODE 0666 -+ -+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+@@ -80,14 +78,6 @@ -+ #define TSTR(x) KERN_WARNING x -+ #define TOUT(p) printk p -+ -+-#define yaffs_trace(mask, fmt, args...) \ -+- do { if ((mask) & (yaffs_traceMask|YAFFS_TRACE_ERROR)) \ -+- printk(KERN_WARNING "yaffs: " fmt, ## args); \ -+- } while (0) -+- -+-#define compile_time_assertion(assertion) \ -+- ({ int x = __builtin_choose_expr(assertion, 0, (void)0); (void) x; }) -+- -+ #elif defined CONFIG_YAFFS_DIRECT -+ -+ /* Direct interface */ -+@@ -142,15 +132,9 @@ -+ -+ #endif -+ -+-/* see yaffs_fs.c */ -+-extern unsigned int yaffs_traceMask; -+-extern unsigned int yaffs_wr_attempts; -+- -+-/* -+- * Tracing flags. -+- * The flags masked in YAFFS_TRACE_ALWAYS are always traced. -+- */ -++extern unsigned yaffs_traceMask; -+ -++#define YAFFS_TRACE_ERROR 0x00000001 -+ #define YAFFS_TRACE_OS 0x00000002 -+ #define YAFFS_TRACE_ALLOCATE 0x00000004 -+ #define YAFFS_TRACE_SCAN 0x00000008 -+@@ -166,19 +150,10 @@ -+ #define YAFFS_TRACE_SCAN_DEBUG 0x00002000 -+ #define YAFFS_TRACE_MTD 0x00004000 -+ #define YAFFS_TRACE_CHECKPOINT 0x00008000 -+- -+-#define YAFFS_TRACE_VERIFY 0x00010000 -+-#define YAFFS_TRACE_VERIFY_NAND 0x00020000 -+-#define YAFFS_TRACE_VERIFY_FULL 0x00040000 -+-#define YAFFS_TRACE_VERIFY_ALL 0x000F0000 -+- -+- -+-#define YAFFS_TRACE_ERROR 0x40000000 -++#define YAFFS_TRACE_ALWAYS 0x40000000 -+ #define YAFFS_TRACE_BUG 0x80000000 -+-#define YAFFS_TRACE_ALWAYS 0xF0000000 -+- -+ -+-#define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p);} while(0) -++#define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ERROR)) TOUT(p);} while(0) -+ -+ #ifndef CONFIG_YAFFS_WINCE -+ #define YBUG() T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__))