From b2e9356130713d84e719c84ccf98850e266e2f6b Mon Sep 17 00:00:00 2001 From: Sanjeev Premi Date: Wed, 12 Oct 2011 16:33:50 +0530 Subject: omap: Unify run_shell() in xload configuration Currently, there are multiple definitions of run_shell() for each board that can be build in "xload" configuration. Now there is only one function used by all boards. The functions defined in xload.c are used only when "xload" configuration used; but it gets compiled unconditionally. This has been fixed as well. Signed-off-by: Sanjeev Premi Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Sascha Hauer --- arch/arm/boards/omap/board-beagle.c | 31 ---------------------------- arch/arm/boards/panda/board.c | 19 ----------------- arch/arm/boards/pcm049/board.c | 30 --------------------------- arch/arm/mach-omap/Makefile | 3 ++- arch/arm/mach-omap/xload.c | 41 +++++++++++++++++++++++++++++++++++++ 5 files changed, 43 insertions(+), 81 deletions(-) diff --git a/arch/arm/boards/omap/board-beagle.c b/arch/arm/boards/omap/board-beagle.c index bfb08f7042..e5f0f94492 100644 --- a/arch/arm/boards/omap/board-beagle.c +++ b/arch/arm/boards/omap/board-beagle.c @@ -313,34 +313,3 @@ static int beagle_devices_init(void) return 0; } device_initcall(beagle_devices_init); - -#ifdef CONFIG_SHELL_NONE - -int run_shell(void) -{ - int (*func)(void) = NULL; - - switch (omap3_bootsrc()) { - case OMAP_BOOTSRC_MMC1: - printf("booting from MMC1\n"); - func = omap_xload_boot_mmc(); - break; - case OMAP_BOOTSRC_UNKNOWN: - printf("unknown boot source. Fall back to nand\n"); - case OMAP_BOOTSRC_NAND: - printf("booting from NAND\n"); - func = omap_xload_boot_nand(SZ_128K, SZ_256K); - break; - } - - if (!func) { - printf("booting failed\n"); - while (1); - } - - shutdown_barebox(); - func(); - - while (1); -} -#endif diff --git a/arch/arm/boards/panda/board.c b/arch/arm/boards/panda/board.c index 6a149aaeaa..be3ad77826 100644 --- a/arch/arm/boards/panda/board.c +++ b/arch/arm/boards/panda/board.c @@ -170,22 +170,3 @@ static int panda_env_init(void) } late_initcall(panda_env_init); #endif - - -#ifdef CONFIG_SHELL_NONE -int run_shell(void) -{ - int (*func)(void); - - func = omap_xload_boot_mmc(); - if (!func) { - printf("booting failed\n"); - while (1); - } - - shutdown_barebox(); - func(); - - while (1); -} -#endif diff --git a/arch/arm/boards/pcm049/board.c b/arch/arm/boards/pcm049/board.c index 8de333f0d9..30e24bc777 100644 --- a/arch/arm/boards/pcm049/board.c +++ b/arch/arm/boards/pcm049/board.c @@ -112,33 +112,3 @@ static int pcm049_devices_init(void) return 0; } device_initcall(pcm049_devices_init); - -#ifdef CONFIG_SHELL_NONE -int run_shell(void) -{ - int (*func)(void) = NULL; - - switch (omap4_bootsrc()) { - case OMAP_BOOTSRC_MMC1: - printf("booting from MMC1\n"); - func = omap_xload_boot_mmc(); - break; - case OMAP_BOOTSRC_UNKNOWN: - printf("unknown boot source. Fall back to nand\n"); - case OMAP_BOOTSRC_NAND: - printf("booting from NAND\n"); - func = omap_xload_boot_nand(SZ_128K, SZ_256K); - break; - } - - if (!func) { - printf("booting failed\n"); - while (1); - } - - shutdown_barebox(); - func(); - - while (1); -} -#endif diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile index 7204746000..07bf30afab 100644 --- a/arch/arm/mach-omap/Makefile +++ b/arch/arm/mach-omap/Makefile @@ -25,4 +25,5 @@ obj-$(CONFIG_ARCH_OMAP3) += omap3_core.o omap3_generic.o obj-$(CONFIG_ARCH_OMAP4) += omap4_generic.o omap4_clock.o obj-$(CONFIG_OMAP3_CLOCK_CONFIG) += omap3_clock_core.o omap3_clock.o obj-$(CONFIG_OMAP_GPMC) += gpmc.o devices-gpmc-nand.o -obj-y += gpio.o xload.o +obj-$(CONFIG_SHELL_NONE) += xload.o +obj-y += gpio.o diff --git a/arch/arm/mach-omap/xload.c b/arch/arm/mach-omap/xload.c index 216b9b5aba..a52a8ba58f 100644 --- a/arch/arm/mach-omap/xload.c +++ b/arch/arm/mach-omap/xload.c @@ -52,3 +52,44 @@ void *omap_xload_boot_mmc(void) return buf; } + +enum omap_boot_src omap_bootsrc(void) +{ +#if defined(CONFIG_ARCH_OMAP3) + return omap3_bootsrc(); +#elif defined(CONFIG_ARCH_OMAP4) + return omap4_bootsrc(); +#endif +} + +/* + * Replaces the default shell in xload configuration + */ +int run_shell(void) +{ + int (*func)(void) = NULL; + + switch (omap_bootsrc()) + { + case OMAP_BOOTSRC_MMC1: + printf("booting from MMC1\n"); + func = omap_xload_boot_mmc(); + break; + case OMAP_BOOTSRC_UNKNOWN: + printf("unknown boot source. Fall back to nand\n"); + case OMAP_BOOTSRC_NAND: + printf("booting from NAND\n"); + func = omap_xload_boot_nand(SZ_128K, SZ_256K); + break; + } + + if (!func) { + printf("booting failed\n"); + while (1); + } + + shutdown_barebox(); + func(); + + while (1); +} -- cgit v1.2.3 From a2ca100344c22bcc66eece3554c7870a164a83b9 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 28 Oct 2011 14:43:49 +0200 Subject: mci: implement multi block write This speeds up writes to MMC/SD cards significantly. Signed-off-by: Sascha Hauer --- drivers/mci/mci-core.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index 09f7e29dc1..7bae06a207 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -107,12 +107,20 @@ static void *sector_buf; * @return Transaction status (0 on success) */ #ifdef CONFIG_MCI_WRITE -static int mci_block_write(struct device_d *mci_dev, const void *src, unsigned blocknum) +static int mci_block_write(struct device_d *mci_dev, const void *src, unsigned blocknum, + int blocks) { struct mci *mci = GET_MCI_DATA(mci_dev); struct mci_cmd cmd; struct mci_data data; const void *buf; + unsigned mmccmd; + int ret; + + if (blocks > 1) + mmccmd = MMC_CMD_WRITE_MULTIPLE_BLOCK; + else + mmccmd = MMC_CMD_WRITE_SINGLE_BLOCK; if ((unsigned long)src & 0x3) { memcpy(sector_buf, src, 512); @@ -122,16 +130,29 @@ static int mci_block_write(struct device_d *mci_dev, const void *src, unsigned b } mci_setup_cmd(&cmd, - MMC_CMD_WRITE_SINGLE_BLOCK, + mmccmd, mci->high_capacity != 0 ? blocknum : blocknum * mci->write_bl_len, MMC_RSP_R1); data.src = buf; - data.blocks = 1; + data.blocks = blocks; data.blocksize = mci->write_bl_len; data.flags = MMC_DATA_WRITE; - return mci_send_cmd(mci_dev, &cmd, &data); + ret = mci_send_cmd(mci_dev, &cmd, &data); + if (ret) + return ret; + + if (blocks > 1) { + mci_setup_cmd(&cmd, + MMC_CMD_STOP_TRANSMISSION, + 0, MMC_RSP_R1b); + ret = mci_send_cmd(mci_dev, &cmd, NULL); + if (ret) + return ret; + } + + return ret; } #endif -- cgit v1.2.3 From 50a62491c5dbacf065fa7ee9733cfa5aa9123b58 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 28 Oct 2011 14:44:09 +0200 Subject: mci: remove unnecessary loops We used to loop around the sectors in mci_sd_write/mci_sd_read. Now that we have multi block read and write this is not necessary anymore. Signed-off-by: Sascha Hauer --- drivers/mci/mci-core.c | 51 +++++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index 7bae06a207..138efcc931 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -987,21 +987,17 @@ static int mci_sd_write(struct device_d *disk_dev, uint64_t sector_start, return -EINVAL; } - while (sector_count) { - /* size of the block number field in the MMC/SD command is 32 bit only */ - if (sector_start > MAX_BUFFER_NUMBER) { - pr_debug("Cannot handle block number %llu. Too large!\n", - sector_start); - return -EINVAL; - } - rc = mci_block_write(mci_dev, buffer, sector_start); - if (rc != 0) { - pr_debug("Writing block %u failed with %d\n", (unsigned)sector_start, rc); - return rc; - } - sector_count--; - buffer += mci->write_bl_len; - sector_start++; + /* size of the block number field in the MMC/SD command is 32 bit only */ + if (sector_start > MAX_BUFFER_NUMBER) { + pr_debug("Cannot handle block number %llu. Too large!\n", + sector_start); + return -EINVAL; + } + + rc = mci_block_write(mci_dev, buffer, sector_start, sector_count); + if (rc != 0) { + pr_debug("Writing block %u failed with %d\n", (unsigned)sector_start, rc); + return rc; } return 0; @@ -1035,21 +1031,16 @@ static int mci_sd_read(struct device_d *disk_dev, uint64_t sector_start, return -EINVAL; } - while (sector_count) { - int now = min(sector_count, 32U); - if (sector_start > MAX_BUFFER_NUMBER) { - pr_err("Cannot handle block number %u. Too large!\n", - (unsigned)sector_start); - return -EINVAL; - } - rc = mci_read_block(mci_dev, buffer, (unsigned)sector_start, now); - if (rc != 0) { - pr_debug("Reading block %u failed with %d\n", (unsigned)sector_start, rc); - return rc; - } - sector_count -= now; - buffer += mci->read_bl_len * now; - sector_start += now; + if (sector_start > MAX_BUFFER_NUMBER) { + pr_err("Cannot handle block number %u. Too large!\n", + (unsigned)sector_start); + return -EINVAL; + } + + rc = mci_read_block(mci_dev, buffer, (unsigned)sector_start, sector_count); + if (rc != 0) { + pr_debug("Reading block %u failed with %d\n", (unsigned)sector_start, rc); + return rc; } return 0; -- cgit v1.2.3 From 115320526c8a609182429c74bd5ca779fb459a02 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 2 Nov 2011 16:23:30 +0100 Subject: ARM i.MX53: enable l2 cache Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/imx53.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-imx/imx53.c b/arch/arm/mach-imx/imx53.c index 698a05a0fb..7f3c5ba813 100644 --- a/arch/arm/mach-imx/imx53.c +++ b/arch/arm/mach-imx/imx53.c @@ -85,16 +85,11 @@ int mx53_init_lowlevel(void) u32 r; /* ARM errata ID #468414 */ - __asm__ __volatile__("mrc 15, 0, %0, c1, c0, 1":"=r"(r)); + __asm__ __volatile__("mrc 15, 0, %0, c1, c0, 1":"=r"(r)); r |= (1 << 5); /* enable L1NEON bit */ + r &= ~(1 << 1); /* explicitly disable L2 cache */ __asm__ __volatile__("mcr 15, 0, %0, c1, c0, 1" : : "r"(r)); - /* explicitly disable L2 cache */ - __asm__ __volatile__("mrc 15, 0, %0, c1, c0, 1":"=r"(r)); - r &= ~(1 << 1); - __asm__ __volatile__("mcr 15, 0, %0, c1, c0, 1" : : "r"(r)); - - /* reconfigure L2 cache aux control reg */ r = 0xc0 | /* tag RAM */ 0x4 | /* data RAM */ @@ -104,6 +99,10 @@ int mx53_init_lowlevel(void) __asm__ __volatile__("mcr 15, 1, %0, c9, c0, 2" : : "r"(r)); + __asm__ __volatile__("mrc 15, 0, %0, c1, c0, 1":"=r"(r)); + r |= 1 << 1; /* enable L2 cache */ + __asm__ __volatile__("mcr 15, 0, %0, c1, c0, 1" : : "r"(r)); + /* * AIPS setup - Only setup MPROTx registers. * The PACR default values are good. -- cgit v1.2.3 From 77e81882692a4612905aeb25a684d1ed9e4828de Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Wed, 16 Nov 2011 10:10:24 +0100 Subject: Mini2440: Everything's now present to provide USB host feature The S3C2440 CPU comes with an internal OHCI the generic part of Barebox already supports. Just add the missing part. Signed-off-by: Juergen Beisert Signed-off-by: Sascha Hauer --- arch/arm/boards/mini2440/mini2440.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boards/mini2440/mini2440.c b/arch/arm/boards/mini2440/mini2440.c index 43510238e0..56e2668540 100644 --- a/arch/arm/boards/mini2440/mini2440.c +++ b/arch/arm/boards/mini2440/mini2440.c @@ -313,6 +313,8 @@ static int mini2440_devices_init(void) IORESOURCE_MEM, &mci_data); add_generic_device("s3c_fb", 0, NULL, S3C2410_LCD_BASE, 0, IORESOURCE_MEM, &s3c24x0_fb_data); + add_generic_device("ohci", 0, NULL, S3C2410_USB_HOST_BASE, 0x100, + IORESOURCE_MEM, NULL); armlinux_set_bootparams((void*)CS6_BASE + 0x100); armlinux_set_architecture(MACH_TYPE_MINI2440); -- cgit v1.2.3 From a59471d133e0f80e7e1095b0cb161e31341694ad Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Thu, 27 Oct 2011 19:50:42 +0800 Subject: sandbox: move ELFCLASS detection to asm/elf.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit now we can detect the host build from gcc macro and cross compile the sandbox Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Cc: Loïc Minier Signed-off-by: Sascha Hauer --- arch/sandbox/Makefile | 13 ------------- arch/sandbox/include/asm/elf.h | 11 ++++++++++- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/arch/sandbox/Makefile b/arch/sandbox/Makefile index b88f1f60f8..9fd18a23b5 100644 --- a/arch/sandbox/Makefile +++ b/arch/sandbox/Makefile @@ -36,19 +36,6 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ -e s/s390x/s390/ -e s/parisc64/parisc/ \ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ ) -ifeq ($(SUBARCH),x86_64) -ELF_CLASS := ELFCLASS64 -endif -ifeq ($(SUBARCH),i386) -ELF_CLASS := ELFCLASS32 -endif -ifeq ($(SUBARCH),powerpc) -ELF_CLASS := ELFCLASS32 -endif - -CPPFLAGS += -DELF_CLASS="$(ELF_CLASS)" -export ELF_CLASS - archprepare: maketools PHONY += maketools diff --git a/arch/sandbox/include/asm/elf.h b/arch/sandbox/include/asm/elf.h index b60d24890c..3939336ccb 100644 --- a/arch/sandbox/include/asm/elf.h +++ b/arch/sandbox/include/asm/elf.h @@ -1,2 +1,11 @@ +#ifndef __ASM_SANDBOX_ELF_H__ +#define __ASM_SANDBOX_ELF_H__ -/* nothing yet */ +#if __SIZEOF_POINTER__ == 8 +#define ELF_CLASS ELFCLASS64 +#define CONFIG_PHYS_ADDR_T_64BIT +#else +#define ELF_CLASS ELFCLASS32 +#endif + +#endif /* __ASM_SANDBOX_ELF_H__ */ -- cgit v1.2.3 From 7bb009c74480153b02a2e0d976a136bf7716e2ab Mon Sep 17 00:00:00 2001 From: Hubert Feurstein Date: Tue, 22 Nov 2011 11:24:44 +0100 Subject: commands/cp: add verbose mode which displays progress bar Signed-off-by: Hubert Feurstein Signed-off-by: Sascha Hauer --- commands/cp.c | 26 ++++++++++++++++++++------ drivers/usb/gadget/dfu.c | 2 +- include/libbb.h | 2 +- lib/copy_file.c | 21 ++++++++++++++++++++- 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/commands/cp.c b/commands/cp.c index 342810528b..f78e3de013 100644 --- a/commands/cp.c +++ b/commands/cp.c @@ -32,6 +32,7 @@ #include #include #include +#include /** * @param[in] cmdtp FIXME @@ -44,8 +45,21 @@ static int do_cp(struct command *cmdtp, int argc, char *argv[]) struct stat statbuf; int last_is_dir = 0; int i; + int opt; + int verbose = 0; + int argc_min; - if (argc < 3) + while ((opt = getopt(argc, argv, "v")) > 0) { + switch (opt) { + case 'v': + verbose = 1; + break; + } + } + + argc_min = optind + 2; + + if (argc < argc_min) return COMMAND_ERROR_USAGE; if (!stat(argv[argc - 1], &statbuf)) { @@ -53,21 +67,21 @@ static int do_cp(struct command *cmdtp, int argc, char *argv[]) last_is_dir = 1; } - if (argc > 3 && !last_is_dir) { + if (argc > argc_min && !last_is_dir) { printf("cp: target `%s' is not a directory\n", argv[argc - 1]); return 1; } - for (i = 1; i < argc - 1; i++) { + for (i = optind; i < argc - 1; i++) { if (last_is_dir) { char *dst; dst = concat_path_file(argv[argc - 1], basename(argv[i])); - ret = copy_file(argv[i], dst); + ret = copy_file(argv[i], dst, verbose); if (ret) goto out; free(dst); } else { - ret = copy_file(argv[i], argv[argc - 1]); + ret = copy_file(argv[i], argv[argc - 1], verbose); if (ret) goto out; } @@ -79,7 +93,7 @@ out: } BAREBOX_CMD_HELP_START(cp) -BAREBOX_CMD_HELP_USAGE("cp \n") +BAREBOX_CMD_HELP_USAGE("cp [-v] \n") BAREBOX_CMD_HELP_SHORT("copy file from to .\n") BAREBOX_CMD_HELP_END diff --git a/drivers/usb/gadget/dfu.c b/drivers/usb/gadget/dfu.c index 1387c6da22..0a0d244106 100644 --- a/drivers/usb/gadget/dfu.c +++ b/drivers/usb/gadget/dfu.c @@ -259,7 +259,7 @@ static int handle_dnload(struct usb_function *f, const struct usb_ctrlrequest *c ret = -EINVAL; goto err_out; } - ret = copy_file(DFU_TEMPFILE, dfu_devs[dfualt].dev); + ret = copy_file(DFU_TEMPFILE, dfu_devs[dfualt].dev, 0); if (ret) { printf("copy file failed\n"); ret = -EINVAL; diff --git a/include/libbb.h b/include/libbb.h index 0962969559..2d17c3fc95 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -26,7 +26,7 @@ int recursive_action(const char *fileName, unsigned flags, char * safe_strncpy(char *dst, const char *src, size_t size); -int copy_file(const char *src, const char *dst); +int copy_file(const char *src, const char *dst, int verbose); int process_escape_sequence(const char *source, char *dest, int destlen); diff --git a/lib/copy_file.c b/lib/copy_file.c index 809befe369..967806c3b0 100644 --- a/lib/copy_file.c +++ b/lib/copy_file.c @@ -4,20 +4,23 @@ #include #include #include +#include #define RW_BUF_SIZE (ulong)4096 /** * @param[in] src FIXME * @param[out] dst FIXME + * @param[in] verbose FIXME */ -int copy_file(const char *src, const char *dst) +int copy_file(const char *src, const char *dst, int verbose) { char *rw_buf = NULL; int srcfd = 0, dstfd = 0; int r, w; int ret = 1; void *buf; + int total = 0; rw_buf = xmalloc(RW_BUF_SIZE); @@ -33,6 +36,15 @@ int copy_file(const char *src, const char *dst) goto out; } + if (verbose) { + struct stat statbuf; + + if (stat(src, &statbuf) < 0) + statbuf.st_size = 0; + + init_progression_bar(statbuf.st_size); + } + while(1) { r = read(srcfd, rw_buf, RW_BUF_SIZE); if (r < 0) { @@ -51,11 +63,18 @@ int copy_file(const char *src, const char *dst) } buf += w; r -= w; + total += w; } + + if (verbose) + show_progress(total); } ret = 0; out: + if (verbose) + putchar('\n'); + free(rw_buf); if (srcfd > 0) close(srcfd); -- cgit v1.2.3 From 52ef4af579d1755e0879ced30aa2038386d42c20 Mon Sep 17 00:00:00 2001 From: Franck Jullien Date: Thu, 24 Nov 2011 21:46:32 +0100 Subject: crypto: Add crc7 function This function in used by the MCI over SPI driver. Signed-off-by: Franck Jullien Signed-off-by: Sascha Hauer --- crypto/Kconfig | 3 +++ crypto/Makefile | 1 + crypto/crc7.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/crc7.h | 14 +++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 crypto/crc7.c create mode 100644 include/crc7.h diff --git a/crypto/Kconfig b/crypto/Kconfig index a391ae65a3..a6fc1b8f86 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -4,6 +4,9 @@ config CRC32 config CRC16 bool +config CRC7 + bool + menuconfig DIGEST bool "Digest " diff --git a/crypto/Makefile b/crypto/Makefile index 955a66de48..7c5b035b73 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_CRC32) += crc32.o obj-$(CONFIG_CRC16) += crc16.o +obj-$(CONFIG_CRC7) += crc7.o obj-$(CONFIG_MD5) += md5.o obj-$(CONFIG_SHA1) += sha1.o obj-$(CONFIG_SHA224) += sha2.o diff --git a/crypto/crc7.c b/crypto/crc7.c new file mode 100644 index 0000000000..8022199d61 --- /dev/null +++ b/crypto/crc7.c @@ -0,0 +1,63 @@ +/* + * crc7.c + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include +#include + + +/* Table for CRC-7 (polynomial x^7 + x^3 + 1) */ +const u8 crc7_syndrome_table[256] = { + 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, + 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, + 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26, + 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e, + 0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d, + 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45, + 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14, + 0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c, + 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, + 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13, + 0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42, + 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a, + 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, + 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21, + 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70, + 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38, + 0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e, + 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36, + 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67, + 0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f, + 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, + 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, + 0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55, + 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d, + 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a, + 0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52, + 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03, + 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b, + 0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28, + 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60, + 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31, + 0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79 +}; + +/** + * crc7 - update the CRC7 for the data buffer + * @crc: previous CRC7 value + * @buffer: data pointer + * @len: number of bytes in the buffer + * Context: any + * + * Returns the updated CRC7 value. + */ +u8 crc7(u8 crc, const u8 *buffer, size_t len) +{ + while (len--) + crc = crc7_byte(crc, *buffer++); + return crc; +} +EXPORT_SYMBOL(crc7); diff --git a/include/crc7.h b/include/crc7.h new file mode 100644 index 0000000000..0c41cc341f --- /dev/null +++ b/include/crc7.h @@ -0,0 +1,14 @@ +#ifndef _LINUX_CRC7_H +#define _LINUX_CRC7_H +#include + +extern const u8 crc7_syndrome_table[256]; + +static inline u8 crc7_byte(u8 crc, u8 data) +{ + return crc7_syndrome_table[(crc << 1) ^ data]; +} + +extern u8 crc7(u8 crc, const u8 *buffer, size_t len); + +#endif -- cgit v1.2.3 From 2aad209b78fcd617ba89d4e29cac09b6948eace3 Mon Sep 17 00:00:00 2001 From: Franck Jullien Date: Thu, 24 Nov 2011 21:46:33 +0100 Subject: mci: Add MCI over SPI support This patch adds MMC over SPI support to mci-core.c and mci_spi.c driver. This driver is useful when SOC doesn't have built-in MCI component. Tested with nios, 2Go SD-CARD and FAT file system. Signed-off-by: Franck Jullien Signed-off-by: Sascha Hauer --- drivers/mci/Kconfig | 17 ++ drivers/mci/Makefile | 1 + drivers/mci/mci-core.c | 69 ++++++-- drivers/mci/mci_spi.c | 435 +++++++++++++++++++++++++++++++++++++++++++++++++ include/mci.h | 18 ++ 5 files changed, 524 insertions(+), 16 deletions(-) create mode 100644 drivers/mci/mci_spi.c diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig index 0d5a0e0814..641f278a86 100644 --- a/drivers/mci/Kconfig +++ b/drivers/mci/Kconfig @@ -80,4 +80,21 @@ config MCI_ATMEL Enable this entry to add support to read and write SD cards on a Atmel AT91. +config MCI_SPI + bool "MMC/SD over SPI" + help + Some systems access MMC/SD/SDIO cards using a SPI controller + instead of using a "native" MMC/SD/SDIO controller. This has a + disadvantage of being relatively high overhead, but a compensating + advantage of working on many systems without dedicated MMC/SD/SDIO + controllers. + +config MMC_SPI_CRC_ON + bool "Enable CRC protection for transfers" + select CRC7 + select CRC16 + depends on MCI_SPI + help + Enable CRC protection for transfers + endif diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile index 4fc00461e9..d7482dc8a2 100644 --- a/drivers/mci/Makefile +++ b/drivers/mci/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_MCI_IMX) += imx.o obj-$(CONFIG_MCI_IMX_ESDHC) += imx-esdhc.o obj-$(CONFIG_MCI_OMAP_HSMMC) += omap_hsmmc.o obj-$(CONFIG_MCI_ATMEL) += atmel_mci.o +obj-$(CONFIG_MCI_SPI) += mci_spi.o diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index 138efcc931..3043688552 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -239,6 +239,7 @@ static int sd_send_op_cond(struct device_d *mci_dev) int timeout = 1000; int err; unsigned voltages; + unsigned busy; /* * Most cards do not answer if some reserved bits @@ -258,7 +259,7 @@ static int sd_send_op_cond(struct device_d *mci_dev) } mci_setup_cmd(&cmd, SD_CMD_APP_SEND_OP_COND, - voltages | (mci->version == SD_VERSION_2 ? OCR_HCS : 0), + mmc_host_is_spi(host) ? 0 : (voltages | (mci->version == SD_VERSION_2 ? OCR_HCS : 0)), MMC_RSP_R3); err = mci_send_cmd(mci_dev, &cmd, NULL); if (err) { @@ -266,7 +267,13 @@ static int sd_send_op_cond(struct device_d *mci_dev) return err; } udelay(1000); - } while ((!(cmd.response[0] & OCR_BUSY)) && timeout--); + + if (mmc_host_is_spi(host)) + busy = cmd.response[0] & R1_SPI_IDLE; + else + busy = !(cmd.response[0] & OCR_BUSY); + + } while (busy && timeout--); if (timeout <= 0) { pr_debug("SD operation condition set timed out\n"); @@ -276,6 +283,13 @@ static int sd_send_op_cond(struct device_d *mci_dev) if (mci->version != SD_VERSION_2) mci->version = SD_VERSION_1_0; + if (mmc_host_is_spi(host)) { /* read OCR for spi */ + mci_setup_cmd(&cmd, MMC_CMD_SPI_READ_OCR, 0, MMC_RSP_R3); + err = mci_send_cmd(mci_dev, &cmd, NULL); + if (err) + return err; + } + mci->ocr = cmd.response[0]; mci->high_capacity = ((mci->ocr & OCR_HCS) == OCR_HCS); @@ -474,11 +488,17 @@ static int sd_change_freq(struct device_d *mci_dev) struct mci *mci = GET_MCI_DATA(mci_dev); struct mci_cmd cmd; struct mci_data data; +#ifdef CONFIG_MCI_SPI + struct mci_host *host = GET_MCI_PDATA(mci_dev); +#endif uint32_t *switch_status = sector_buf; uint32_t *scr = sector_buf; int timeout; int err; + if (mmc_host_is_spi(host)) + return 0; + pr_debug("Changing transfer frequency\n"); mci->card_caps = 0; @@ -769,10 +789,23 @@ static int mci_startup(struct device_d *mci_dev) struct mci_cmd cmd; int err; +#ifdef CONFIG_MMC_SPI_CRC_ON + if (mmc_host_is_spi(host)) { /* enable CRC check for spi */ + + mci_setup_cmd(&cmd, MMC_CMD_SPI_CRC_ON_OFF, 1, MMC_RSP_R1); + err = mci_send_cmd(mci_dev, &cmd, NULL); + + if (err) { + pr_debug("Can't enable CRC check : %d\n", err); + return err; + } + } +#endif + pr_debug("Put the Card in Identify Mode\n"); /* Put the Card in Identify Mode */ - mci_setup_cmd(&cmd, MMC_CMD_ALL_SEND_CID, 0, MMC_RSP_R2); + mci_setup_cmd(&cmd, mmc_host_is_spi(host) ? MMC_CMD_SEND_CID : MMC_CMD_ALL_SEND_CID, 0, MMC_RSP_R2); err = mci_send_cmd(mci_dev, &cmd, NULL); if (err) { pr_debug("Can't bring card into identify mode: %d\n", err); @@ -789,12 +822,14 @@ static int mci_startup(struct device_d *mci_dev) * For SD cards, get the Relatvie Address. * This also puts the cards into Standby State */ - pr_debug("Get/Set relative address\n"); - mci_setup_cmd(&cmd, SD_CMD_SEND_RELATIVE_ADDR, mci->rca << 16, MMC_RSP_R6); - err = mci_send_cmd(mci_dev, &cmd, NULL); - if (err) { - pr_debug("Get/Set relative address failed: %d\n", err); - return err; + if (!mmc_host_is_spi(host)) { /* cmd not supported in spi */ + pr_debug("Get/Set relative address\n"); + mci_setup_cmd(&cmd, SD_CMD_SEND_RELATIVE_ADDR, mci->rca << 16, MMC_RSP_R6); + err = mci_send_cmd(mci_dev, &cmd, NULL); + if (err) { + pr_debug("Get/Set relative address failed: %d\n", err); + return err; + } } if (IS_SD(mci)) @@ -835,13 +870,15 @@ static int mci_startup(struct device_d *mci_dev) pr_debug("Read block length: %u, Write block length: %u\n", mci->read_bl_len, mci->write_bl_len); - pr_debug("Select the card, and put it into Transfer Mode\n"); - /* Select the card, and put it into Transfer Mode */ - mci_setup_cmd(&cmd, MMC_CMD_SELECT_CARD, mci->rca << 16, MMC_RSP_R1b); - err = mci_send_cmd(mci_dev, &cmd, NULL); - if (err) { - pr_debug("Putting in transfer mode failed: %d\n", err); - return err; + if (!mmc_host_is_spi(host)) { /* cmd not supported in spi */ + pr_debug("Select the card, and put it into Transfer Mode\n"); + /* Select the card, and put it into Transfer Mode */ + mci_setup_cmd(&cmd, MMC_CMD_SELECT_CARD, mci->rca << 16, MMC_RSP_R1b); + err = mci_send_cmd(mci_dev, &cmd, NULL); + if (err) { + pr_debug("Putting in transfer mode failed: %d\n", err); + return err; + } } if (IS_SD(mci)) diff --git a/drivers/mci/mci_spi.c b/drivers/mci/mci_spi.c new file mode 100644 index 0000000000..124e49b9c2 --- /dev/null +++ b/drivers/mci/mci_spi.c @@ -0,0 +1,435 @@ +/* + * (C) Copyright 2011 - Franck JULLIEN + * + * This code was inspired from u-boot mmc_spi.c: + * Copyright (C) 2010 Thomas Chou + * + * and linux mmc_spi.c: + * (C) Copyright 2005, Intec Automation, + * Mike Lavender (mike@steroidmicros) + * (C) Copyright 2006-2007, David Brownell + * (C) Copyright 2007, Axis Communications, + * Hans-Peter Nilsson (hp@axis.com) + * (C) Copyright 2007, ATRON electronic GmbH, + * Jan Nikitenko + * + * 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 + +#define to_spi_host(mci) container_of(mci, struct mmc_spi_host, mci) +#define spi_setup(spi) spi->master->setup(spi) + +/* Response tokens used to ack each block written: */ +#define SPI_MMC_RESPONSE_CODE(x) ((x) & 0x1f) +#define SPI_RESPONSE_ACCEPTED ((2 << 1)|1) + +/* Read and write blocks start with these tokens and end with crc; + * on error, read tokens act like a subset of R2_SPI_* values. + */ +#define SPI_TOKEN_SINGLE 0xFE /* single block r/w, multiblock read */ +#define SPI_TOKEN_MULTI_WRITE 0xFC /* multiblock write */ +#define SPI_TOKEN_STOP_TRAN 0xFD /* terminate multiblock write */ + +/* MMC SPI commands start with a start bit "0" and a transmit bit "1" */ +#define MMC_SPI_CMD(x) (0x40 | (x & 0x3F)) + +#define MMC_SPI_BLOCKSIZE 512 + +/* timeout value */ +#define CTOUT 8 +#define RTOUT 3000000 /* 1 sec */ +#define WTOUT 3000000 /* 1 sec */ + +#ifndef CONFIG_MMC_SPI_CRC_ON +/* Note that while the CRC, in general, is ignored in SPI mode, the very first + * command must be followed by a valid CRC, since the card is not yet in SPI mode. + * The CRC byte for a CMD0 command with a zero argument is a constant 0x4A. For + * simplicity, this CRC byte is always sent with every command. + */ + +static inline u8 crc7(u8 crc, const u8 *buffer, size_t len) +{ + /* This is the crc7 value for a CMD0 command with a zero argument. + * It'll be left shifted and ored with '1' in mmc_spi_command_send + * to give 0x95 (also known as the CMD0 constant CRC value...) + */ + return 0x4A; +} +#endif + +struct mmc_spi_host { + struct mci_host mci; + struct spi_device *spi; + struct device_d *dev; + + /* for bulk data transfers */ + struct spi_transfer t_tx; + struct spi_message m_tx; + + /* for status readback */ + struct spi_transfer t_rx; + struct spi_message m_rx; + + void *ones; +}; + +static char *maptype(struct mci_cmd *cmd) +{ + switch (cmd->resp_type) { + case MMC_RSP_NONE: return "NONE"; + case MMC_RSP_R1: return "R1"; + case MMC_RSP_R1b: return "R1B"; + case MMC_RSP_R2: return "R2/R5"; + case MMC_RSP_R3: return "R3/R4/R7"; + default: return "?"; + } +} + +static inline int mmc_cs_off(struct mmc_spi_host *host) +{ + /* chipselect will always be inactive after setup() */ + return spi_setup(host->spi); +} + +static int +mmc_spi_readbytes(struct mmc_spi_host *host, unsigned len, void *data) +{ + int status; + + host->t_rx.len = len; + host->t_rx.rx_buf = data; + + status = spi_sync(host->spi, &host->m_rx); + + return status; +} + +static int +mmc_spi_writebytes(struct mmc_spi_host *host, unsigned len, void *data) +{ + int status; + + host->t_tx.len = len; + host->t_tx.tx_buf = data; + + status = spi_sync(host->spi, &host->m_tx); + + return status; +} + +static int mmc_spi_command_send(struct mmc_spi_host *host, struct mci_cmd *cmd) +{ + uint8_t r1; + uint8_t command[7]; + int i; + + command[0] = 0xff; + command[1] = MMC_SPI_CMD(cmd->cmdidx); + command[2] = cmd->cmdarg >> 24; + command[3] = cmd->cmdarg >> 16; + command[4] = cmd->cmdarg >> 8; + command[5] = cmd->cmdarg; + command[6] = (crc7(0, &command[1], 5) << 1) | 0x01; + + mmc_spi_writebytes(host, 7, command); + + for (i = 0; i < CTOUT; i++) { + mmc_spi_readbytes(host, 1, &r1); + if (i && ((r1 & 0x80) == 0)) { /* r1 response */ + dev_dbg(host->dev, "%s: CMD%d, TRY %d, RESP %x\n", __func__, cmd->cmdidx, i, r1); + break; + } + } + + return r1; +} + +static uint mmc_spi_readdata(struct mmc_spi_host *host, void *xbuf, + uint32_t bcnt, uint32_t bsize) +{ + uint8_t *buf = xbuf; + uint8_t r1; + uint16_t crc; + int i; + + while (bcnt--) { + for (i = 0; i < RTOUT; i++) { + mmc_spi_readbytes(host, 1, &r1); + if (r1 != 0xff) /* data token */ + break; + } + if (r1 == SPI_TOKEN_SINGLE) { + mmc_spi_readbytes(host, bsize, buf); + mmc_spi_readbytes(host, 2, &crc); +#ifdef CONFIG_MMC_SPI_CRC_ON + if (swab16(cyg_crc16(buf, bsize)) != crc) { + dev_dbg(host->dev, "%s: CRC error\n", __func__); + r1 = R1_SPI_COM_CRC; + break; + } +#endif + r1 = 0; + } else { + r1 = R1_SPI_ERROR; + break; + } + buf += bsize; + } + + return r1; +} + +static uint mmc_spi_writedata(struct mmc_spi_host *host, const void *xbuf, + uint32_t bcnt, uint32_t bsize, int multi) +{ + const uint8_t *buf = xbuf; + uint8_t r1; + uint16_t crc = 0; + uint8_t tok[2]; + int i; + + tok[0] = 0xff; + tok[1] = multi ? SPI_TOKEN_MULTI_WRITE : SPI_TOKEN_SINGLE; + + while (bcnt--) { +#ifdef CONFIG_MMC_SPI_CRC_ON + crc = swab16(cyg_crc16((u8 *)buf, bsize)); +#endif + mmc_spi_writebytes(host, 2, tok); + mmc_spi_writebytes(host, bsize, (void *)buf); + mmc_spi_writebytes(host, 2, &crc); + + for (i = 0; i < CTOUT; i++) { + mmc_spi_readbytes(host, 1, &r1); + if ((r1 & 0x11) == 0x01) /* response token */ + break; + } + + dev_dbg(host->dev,"%s : TOKEN%d RESP 0x%X\n", __func__, i, r1); + if (SPI_MMC_RESPONSE_CODE(r1) == SPI_RESPONSE_ACCEPTED) { + for (i = 0; i < WTOUT; i++) { /* wait busy */ + mmc_spi_readbytes(host, 1, &r1); + if (i && r1 == 0xff) { + r1 = 0; + break; + } + } + if (i == WTOUT) { + dev_dbg(host->dev, "%s: wtout %x\n", __func__, r1); + r1 = R1_SPI_ERROR; + break; + } + } else { + dev_dbg(host->dev, "%s: err %x\n", __func__, r1); + r1 = R1_SPI_COM_CRC; + break; + } + buf += bsize; + } + + if (multi && bcnt == -1) { /* stop multi write */ + tok[1] = SPI_TOKEN_STOP_TRAN; + mmc_spi_writebytes(host, 2, tok); + for (i = 0; i < WTOUT; i++) { /* wait busy */ + mmc_spi_readbytes(host, 1, &r1); + if (i && r1 == 0xff) { + r1 = 0; + break; + } + } + if (i == WTOUT) { + dev_dbg(host->dev, "%s: wstop %x\n", __func__, r1); + r1 = R1_SPI_ERROR; + } + } + + return r1; +} + +static int mmc_spi_request(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) +{ + struct mmc_spi_host *host = to_spi_host(mci); + uint8_t r1; + int i; + int ret = 0; + + dev_dbg(host->dev, "%s : CMD%02d, RESP %s, ARG 0x%X\n", __func__, + cmd->cmdidx, maptype(cmd), cmd->cmdarg); + + r1 = mmc_spi_command_send(host, cmd); + + cmd->response[0] = r1; + + if (r1 == 0xff) { /* no response */ + ret = -ETIME; + goto done; + } else if (r1 & R1_SPI_COM_CRC) { + ret = -ECOMM; + goto done; + } else if (r1 & ~R1_SPI_IDLE) { /* other errors */ + ret = -ETIME; + goto done; + } else if (cmd->resp_type == MMC_RSP_R2) { + r1 = mmc_spi_readdata(host, cmd->response, 1, 16); + for (i = 0; i < 4; i++) + cmd->response[i] = swab32(cmd->response[i]); + dev_dbg(host->dev, "MMC_RSP_R2 -> %x %x %x %x\n", cmd->response[0], cmd->response[1], + cmd->response[2], cmd->response[3]); + } else if (!data) { + switch (cmd->cmdidx) { + case SD_CMD_SEND_IF_COND: + case MMC_CMD_SPI_READ_OCR: + mmc_spi_readbytes(host, 4, cmd->response); + cmd->response[0] = swab32(cmd->response[0]); + break; + } + } else { + if (data->flags == MMC_DATA_READ) { + dev_dbg(host->dev, "%s : DATA READ, %x blocks, bsize = 0x%X\n", __func__, + data->blocks, data->blocksize); + r1 = mmc_spi_readdata(host, data->dest, + data->blocks, data->blocksize); + } else if (data->flags == MMC_DATA_WRITE) { + dev_dbg(host->dev, "%s : DATA WRITE, %x blocks, bsize = 0x%X\n", __func__, + data->blocks, data->blocksize); + r1 = mmc_spi_writedata(host, data->src, + data->blocks, data->blocksize, + (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK)); + } + if (r1 & R1_SPI_COM_CRC) + ret = -ECOMM; + else if (r1) + ret = -ETIME; + } + +done: + mmc_cs_off(host); + return ret; + +return 0; + +} + +static void mmc_spi_set_ios(struct mci_host *mci, struct device_d *mci_dev, + unsigned bus_width, unsigned clock) +{ + struct mmc_spi_host *host = to_spi_host(mci); + + spi_setup(host->spi); +} + +static int mmc_spi_init(struct mci_host *mci, struct device_d *mci_dev) +{ + struct mmc_spi_host *host = to_spi_host(mci); + mmc_spi_readbytes(host, 10, NULL); + + /* + * Do a burst with chipselect active-high. We need to do this to + * meet the requirement of 74 clock cycles with both chipselect + * and CMD (MOSI) high before CMD0 ... after the card has been + * powered up to Vdd(min), and so is ready to take commands. + * + * Some cards are particularly needy of this (e.g. Viking "SD256") + * while most others don't seem to care. + * + * Note that this is one of the places MMC/SD plays games with the + * SPI protocol. Another is that when chipselect is released while + * the card returns BUSY status, the clock must issue several cycles + * with chipselect high before the card will stop driving its output. + */ + + host->spi->mode |= SPI_CS_HIGH; + if (spi_setup(host->spi) != 0) { + /* Just warn; most cards work without it. */ + dev_warn(&host->spi->dev, + "can't change chip-select polarity\n"); + host->spi->mode &= ~SPI_CS_HIGH; + } else { + mmc_spi_readbytes(host, 18, NULL); + + host->spi->mode &= ~SPI_CS_HIGH; + if (spi_setup(host->spi) != 0) { + /* Wot, we can't get the same setup we had before? */ + dev_err(&host->spi->dev, + "can't restore chip-select polarity\n"); + } + } + + return 0; +} + +static int spi_mci_probe(struct device_d *dev) +{ + struct spi_device *spi = (struct spi_device *)dev->type_data; + struct mmc_spi_host *host; + void *ones; + + host = xzalloc(sizeof(*host)); + host->mci.send_cmd = mmc_spi_request; + host->mci.set_ios = mmc_spi_set_ios; + host->mci.init = mmc_spi_init; + + host->dev = dev; + host->spi = spi; + dev->priv = host; + + ones = xmalloc(MMC_SPI_BLOCKSIZE); + memset(ones, 0xff, MMC_SPI_BLOCKSIZE); + + host->ones = ones; + + spi_message_init(&host->m_tx); + spi_message_init(&host->m_rx); + + spi_message_add_tail(&host->t_tx, &host->m_tx); + spi_message_add_tail(&host->t_rx, &host->m_rx); + + host->t_rx.tx_buf = host->ones; + host->t_rx.cs_change = 1; + + host->t_tx.cs_change = 1; + + host->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34; + host->mci.host_caps = MMC_CAP_SPI; + + mci_register(&host->mci); + + return 0; +} + +static struct driver_d spi_mci_driver = { + .name = "spi_mci", + .probe = spi_mci_probe, +}; + +static int spi_mci_init_driver(void) +{ + register_driver(&spi_mci_driver); + return 0; +} + +device_initcall(spi_mci_init_driver); diff --git a/include/mci.h b/include/mci.h index 69cffe8d3f..d581f99929 100644 --- a/include/mci.h +++ b/include/mci.h @@ -49,6 +49,7 @@ #define MMC_MODE_HS 0x001 #define MMC_MODE_HS_52MHz 0x010 +#define MMC_CAP_SPI 0x020 #define MMC_MODE_4BIT 0x100 #define MMC_MODE_8BIT 0x200 @@ -56,6 +57,12 @@ #define IS_SD(x) (x->version & SD_VERSION_SD) +#ifdef CONFIG_MCI_SPI +#define mmc_host_is_spi(host) ((host)->host_caps & MMC_CAP_SPI) +#else +#define mmc_host_is_spi(host) 0 +#endif + #define MMC_DATA_READ 1 #define MMC_DATA_WRITE 2 @@ -78,6 +85,8 @@ #define MMC_CMD_WRITE_SINGLE_BLOCK 24 #define MMC_CMD_WRITE_MULTIPLE_BLOCK 25 #define MMC_CMD_APP_CMD 55 +#define MMC_CMD_SPI_READ_OCR 58 +#define MMC_CMD_SPI_CRC_ON_OFF 59 #define SD_CMD_SEND_RELATIVE_ADDR 3 #define SD_CMD_SWITCH_FUNC 6 @@ -155,6 +164,15 @@ #define R1_ILLEGAL_COMMAND (1 << 22) #define R1_APP_CMD (1 << 5) +#define R1_SPI_IDLE (1 << 0) +#define R1_SPI_ERASE_RESET (1 << 1) +#define R1_SPI_ILLEGAL_COMMAND (1 << 2) +#define R1_SPI_COM_CRC (1 << 3) +#define R1_SPI_ERASE_SEQ (1 << 4) +#define R1_SPI_ADDRESS (1 << 5) +#define R1_SPI_PARAMETER (1 << 6) +#define R1_SPI_ERROR (1 << 7) + /* response types */ #define MMC_RSP_PRESENT (1 << 0) #define MMC_RSP_136 (1 << 1) /* 136 bit response */ -- cgit v1.2.3 From 146bea9b9b79f38047f14799c959280cea50c4bf Mon Sep 17 00:00:00 2001 From: Franck Jullien Date: Thu, 24 Nov 2011 21:46:34 +0100 Subject: spi/altera_spi: Add cs_change support The Linux kernel says (spi.h) : * All SPI transfers start with the relevant chipselect active. Normally * it stays selected until after the last transfer in a message. Drivers * can affect the chipselect signal using cs_change. * * (i) If the transfer isn't the last one in the message, this flag is * used to make the chipselect briefly go inactive in the middle of the * message. Toggling chipselect in this way may be needed to terminate * a chip command, letting a single spi_message perform all of group of * chip transactions together. * * (ii) When the transfer is the last one in the message, the chip may * stay selected until the next transfer. On multi-device SPI busses * with nothing blocking messages going to other devices, this is just * a performance hint; starting a message to another device deselects * this one. But in other cases, this can be used to ensure correctness. * Some devices need protocol transactions to be built from a series of * spi_message submissions, where the content of one message is * determined by the results of previous messages and where the whole * transaction * ends when the chipselect goes intactive. In other words, cs_change changes the default chipselect *behavior*. Support of cs_change is necessary to implement the mci spi driver. This patch also fix few things: Passing the bus number to the brand new master device. Disable chipselect during master->setup. Signed-off-by: Franck Jullien Signed-off-by: Sascha Hauer --- arch/nios2/include/asm/spi.h | 1 + drivers/spi/altera_spi.c | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/arch/nios2/include/asm/spi.h b/arch/nios2/include/asm/spi.h index 4e576b9922..6c5740c340 100644 --- a/arch/nios2/include/asm/spi.h +++ b/arch/nios2/include/asm/spi.h @@ -8,6 +8,7 @@ struct spi_altera_master { int spi_mode; int databits; int speed; + int bus_num; }; struct altera_spi { diff --git a/drivers/spi/altera_spi.c b/drivers/spi/altera_spi.c index 4fd82fb905..6cf9942d9d 100644 --- a/drivers/spi/altera_spi.c +++ b/drivers/spi/altera_spi.c @@ -25,6 +25,9 @@ #include #include #include +#include + +static void altera_spi_cs_inactive(struct spi_device *spi); static int altera_spi_setup(struct spi_device *spi) { @@ -49,6 +52,8 @@ static int altera_spi_setup(struct spi_device *spi) return -1; } + altera_spi_cs_inactive(spi); + dev_dbg(master->dev, " mode 0x%08x, bits_per_word: %d, speed: %d\n", spi->mode, spi->bits_per_word, altera_spi->speed); @@ -167,19 +172,38 @@ static int altera_spi_transfer(struct spi_device *spi, struct spi_message *mesg) struct altera_spi *altera_spi = container_of(spi->master, struct altera_spi, master); struct nios_spi *nios_spi = altera_spi->regs; struct spi_transfer *t; + unsigned int cs_change; + const int nsecs = 50; altera_spi_cs_active(spi); + cs_change = 0; + mesg->actual_length = 0; list_for_each_entry(t, &mesg->transfers, transfer_list) { + + if (cs_change) { + ndelay(nsecs); + altera_spi_cs_inactive(spi); + ndelay(nsecs); + altera_spi_cs_active(spi); + } + + cs_change = t->cs_change; + mesg->actual_length += altera_spi_do_xfer(spi, t); + + if (cs_change) { + altera_spi_cs_active(spi); + } } /* Wait the end of any pending transfer */ while ((readl(&nios_spi->status) & NIOS_SPI_TMT) == 0); - altera_spi_cs_inactive(spi); + if (!cs_change) + altera_spi_cs_inactive(spi); return 0; } @@ -199,6 +223,7 @@ static int altera_spi_probe(struct device_d *dev) master->setup = altera_spi_setup; master->transfer = altera_spi_transfer; master->num_chipselect = pdata->num_chipselect; + master->bus_num = pdata->bus_num; altera_spi->regs = dev_request_mem_region(dev, 0); altera_spi->databits = pdata->databits; -- cgit v1.2.3 From 77fe6dce51cf3c691dbf5a8bb7bdf9efb0eb8204 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 26 Nov 2011 13:26:54 +0100 Subject: arm: trivial renaming create_sections Rename create_section into create_sections, as the function is used to create multiple sections, and in particular it creates the 4096 sections of 1MBytes to have a 1:1 flat mapping of the 4GBytes address space. Signed-off-by: Robert Jarzmik Signed-off-by: Sascha Hauer --- arch/arm/cpu/mmu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c index 4446813d0a..8e4e81aa9c 100644 --- a/arch/arm/cpu/mmu.c +++ b/arch/arm/cpu/mmu.c @@ -9,7 +9,7 @@ static unsigned long *ttb; -static void create_section(unsigned long virt, unsigned long phys, int size_m, +static void create_sections(unsigned long virt, unsigned long phys, int size_m, unsigned int flags) { int i; @@ -226,7 +226,7 @@ static int mmu_init(void) asm volatile ("mcr p15,0,%0,c3,c0,0" : : "r"(i) /*:*/); /* create a flat mapping using 1MiB sections */ - create_section(0, 0, 4096, PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | + create_sections(0, 0, 4096, PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT); vectors_init(); @@ -237,7 +237,7 @@ static int mmu_init(void) * below */ for_each_memory_bank(bank) - create_section(bank->start, bank->start, bank->size >> 20, + create_sections(bank->start, bank->start, bank->size >> 20, PMD_SECT_DEF_CACHED); asm volatile ( -- cgit v1.2.3 From 0c871d19dd7dcc48a4b14e0efeebcfb61bedb867 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Thu, 24 Nov 2011 13:43:39 +0100 Subject: USB Mass Storage driver: Fix compile time warning drivers/usb/storage/usb.c: In function 'usb_stor_blk_io': drivers/usb/storage/usb.c:257:16: warning: comparison of distinct pointer types lacks a cast Signed-off-by: Juergen Beisert Signed-off-by: Sascha Hauer --- drivers/usb/storage/usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index d033b291c2..6dba8ccaca 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -193,7 +193,7 @@ static int usb_stor_write_10(ccb *srb, struct us_data *us, * Disk driver interface ***********************************************************************/ -#define US_MAX_IO_BLK 32U +#define US_MAX_IO_BLK 32 enum { io_rd, io_wr }; -- cgit v1.2.3 From 3ca9f1812fc5cb231c11480021886a4e7cfadf97 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Thu, 24 Nov 2011 13:43:40 +0100 Subject: Create a unique cdev number for on demand devices For disk like devices attached to MCI, ATA or USB it depends on the order they will be recognized. So an unique number for all disk like devices is required. Signed-off-by: Juergen Beisert Signed-off-by: Sascha Hauer --- fs/devfs-core.c | 14 ++++++++++++++ include/driver.h | 1 + 2 files changed, 15 insertions(+) diff --git a/fs/devfs-core.c b/fs/devfs-core.c index 519e18e6b7..9bc3126d6b 100644 --- a/fs/devfs-core.c +++ b/fs/devfs-core.c @@ -40,6 +40,20 @@ struct cdev *cdev_by_name(const char *filename) return NULL; } +int cdev_find_free_index(const char *basename) +{ + int i; + char fname[100]; + + for (i = 0; i < 1000; i++) { + snprintf(fname, sizeof(fname), "%s%d", basename, i); + if (cdev_by_name(fname) == NULL) + return i; + } + + return -EBUSY; /* all indexes are used */ +} + struct cdev *cdev_open(const char *name, unsigned long flags) { struct cdev *cdev = cdev_by_name(name); diff --git a/include/driver.h b/include/driver.h index 80de0c8377..fe9d37ae3d 100644 --- a/include/driver.h +++ b/include/driver.h @@ -394,6 +394,7 @@ struct cdev { int devfs_create(struct cdev *); int devfs_remove(struct cdev *); +int cdev_find_free_index(const char *); struct cdev *cdev_by_name(const char *filename); struct cdev *cdev_open(const char *name, unsigned long flags); void cdev_close(struct cdev *cdev); -- cgit v1.2.3 From 6a3bdfdbade159c218a427542abbdb9f525e1370 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Thu, 24 Nov 2011 13:43:41 +0100 Subject: ATA/DISK: Add generic disk support when enabling the BIOS disk driver The BIOS based disk driver makes no sense without the generic disk support. Signed-off-by: Juergen Beisert Signed-off-by: Sascha Hauer --- drivers/ata/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index d7f4dcbfe3..6a57e5cd36 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -21,6 +21,7 @@ comment "interface types" config ATA_BIOS bool "BIOS based" + select ATA_DISK depends on X86_BIOS_BRINGUP help Gain disk drive access via int13 calls to the standard PC-BIOS. -- cgit v1.2.3 From 092366c1a953e0c62b9f2f4d4ac908249339f629 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Thu, 24 Nov 2011 13:43:42 +0100 Subject: ATA/DISK: Enabling write support does not belong to 'drive types' Signed-off-by: Juergen Beisert Signed-off-by: Sascha Hauer --- drivers/ata/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 6a57e5cd36..5be1805550 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -6,12 +6,12 @@ menuconfig ATA if ATA -comment "drive types" - config ATA_WRITE select BLOCK_WRITE bool "support writing to ATA drives" +comment "drive types" + config ATA_DISK bool "disk drives" help -- cgit v1.2.3 From bda834847dd7570e0effc4762fbfc4e05d705a24 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Thu, 24 Nov 2011 13:43:43 +0100 Subject: ATA/DISK: Reorganize file structure and names for future updates 'ATA' means more an interface than a disk drive. Change the names to reflect their real meaning. Signed-off-by: Juergen Beisert Signed-off-by: Sascha Hauer --- drivers/Makefile | 2 +- drivers/ata/Kconfig | 23 +++++++++++++---------- drivers/ata/Makefile | 2 +- drivers/ata/disk_drive.c | 4 ++-- drivers/mci/Kconfig | 4 ++-- 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/Makefile b/drivers/Makefile index 16b3bb129f..592c39e6d9 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -4,7 +4,7 @@ obj-y += serial/ obj-y += mtd/ obj-y += nor/ obj-y += usb/ -obj-$(CONFIG_ATA) += ata/ +obj-$(CONFIG_DISK) += ata/ obj-$(CONFIG_SPI) += spi/ obj-$(CONFIG_I2C) += i2c/ obj-$(CONFIG_MCI) += mci/ diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 5be1805550..025ff942b7 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -1,27 +1,30 @@ -menuconfig ATA +menuconfig DISK select BLOCK - bool "ATA " + bool "Disk support " help - Add support for ATA types of drives like harddisks and CDROMs. + Add support for disk like drives like harddisks, CDROMs, SD cards and + CF cards. -if ATA +if DISK -config ATA_WRITE +config DISK_WRITE select BLOCK_WRITE - bool "support writing to ATA drives" + bool "support writing to disk drives" comment "drive types" -config ATA_DISK - bool "disk drives" +config DISK_DRIVE + bool "Generic disk drives" help - Add support for regular disk drives + Add support for generic disk drives. Common behaviour for this kind + of devices is using a partition table in the first sector. Say Y here + if you intend to work with disk drives (also CF cards and SD cards). comment "interface types" config ATA_BIOS bool "BIOS based" - select ATA_DISK + select DISK_DRIVE depends on X86_BIOS_BRINGUP help Gain disk drive access via int13 calls to the standard PC-BIOS. diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 30d15ccb02..c3260d70f8 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -1,6 +1,6 @@ # drive types -obj-$(CONFIG_ATA_DISK) += disk_drive.o +obj-$(CONFIG_DISK_DRIVE) += disk_drive.o # interface types diff --git a/drivers/ata/disk_drive.c b/drivers/ata/disk_drive.c index 6a5dc873f7..c2a6a5120d 100644 --- a/drivers/ata/disk_drive.c +++ b/drivers/ata/disk_drive.c @@ -144,7 +144,7 @@ static int atablk_read(struct block_device *blk, void *buf, int block, return atablk->intf->read(atablk->dev, block, num_blocks, buf); } -#ifdef CONFIG_ATA_WRITE +#ifdef CONFIG_DISK_WRITE static int atablk_write(struct block_device *blk, const void *buf, int block, int num_blocks) { @@ -156,7 +156,7 @@ static int atablk_write(struct block_device *blk, const void *buf, int block, static struct block_device_ops ataops = { .read = atablk_read, -#ifdef CONFIG_ATA_WRITE +#ifdef CONFIG_DISK_WRITE .write = atablk_write, #endif }; diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig index 641f278a86..148c389ecc 100644 --- a/drivers/mci/Kconfig +++ b/drivers/mci/Kconfig @@ -1,7 +1,7 @@ menuconfig MCI bool "MCI drivers " - select ATA - select ATA_DISK + select DISK + select DISK_DRIVE help Add support for MCI drivers, used to handle MMC and SD cards -- cgit v1.2.3 From 0084116bcc281051fa756661579a17f374a6de0a Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Thu, 24 Nov 2011 13:43:44 +0100 Subject: ATA/DISK: The BIOS based disk driver is not an interface Using the BIOS to access attached hard disks means a full disk driver, not only an interface to the drives. Signed-off-by: Juergen Beisert Signed-off-by: Sascha Hauer --- drivers/ata/Kconfig | 6 +- drivers/ata/Makefile | 2 +- drivers/ata/bios.c | 290 ------------------------------------------ drivers/ata/disk_bios_drive.c | 290 ++++++++++++++++++++++++++++++++++++++++++ drivers/ata/disk_drive.c | 10 +- 5 files changed, 299 insertions(+), 299 deletions(-) delete mode 100644 drivers/ata/bios.c create mode 100644 drivers/ata/disk_bios_drive.c diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 025ff942b7..f3b29397c6 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -20,9 +20,7 @@ config DISK_DRIVE of devices is using a partition table in the first sector. Say Y here if you intend to work with disk drives (also CF cards and SD cards). -comment "interface types" - -config ATA_BIOS +config DISK_BIOS bool "BIOS based" select DISK_DRIVE depends on X86_BIOS_BRINGUP @@ -32,4 +30,6 @@ config ATA_BIOS media to work on. Disadvantage is: Due to its 16 bit nature it is slow. +comment "interface types" + endif diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index c3260d70f8..10f3957453 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -1,7 +1,7 @@ # drive types obj-$(CONFIG_DISK_DRIVE) += disk_drive.o +obj-$(CONFIG_DISK_BIOS) += disk_bios_drive.o # interface types -obj-$(CONFIG_ATA_BIOS) += bios.o diff --git a/drivers/ata/bios.c b/drivers/ata/bios.c deleted file mode 100644 index 6e2377c7ea..0000000000 --- a/drivers/ata/bios.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) 2009 Juergen Beisert, Pengutronix - * - * Mostly stolen from the GRUB2 project - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, 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 - * - */ - -/** - * @file - * @brief Media communication layer through the standard 16 bit PC-BIOS - * - * This communication driver does all accesses to the boot medium via 16 bit - * real mode calls into the standard BIOS. Due to this method, its possible - * to use all the medias to boot from that are supported by the BIOS. This - * also includes emulated only medias. - * - * To be able to call the real mode BIOS, this driver must switch back to - * real mode for each access. This will slow down the access a little bit, but - * we are a boot loader here, not an operating system... - * - * Note: We need scratch memory for the BIOS communication, because the BIOS - * can only handle memory below 0xA0000. So we must copy all data between - * the flat mode buffers and realmode buffers. - * - * Note: This driver makes no sense on other architectures than x86. - * - * Note: This driver does only support LBA addressing. Currently no CHS! - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * Sector count handled in one count - * - * @todo 127 are always possible, some BIOS manufacturer supports up to 255. - * Is it's worth to detect Phoenic's restriction? - */ -#define SECTORS_AT_ONCE 64 - -/** Size of one sector in bytes */ -#define SECTOR_SIZE 512 - -/** Command to read sectors from media */ -#define BIOS_READ_CMD 0 - -/** Command to write sectors to media */ -#define BIOS_WRT_CMD 1 - -/** - * "Disk Address Packet Structure" to be used when calling - * BIOS's int13, function 0x42/0x43 - */ -struct DAPS -{ - uint8_t size; /**< always '16' */ - uint8_t res1; /**< always '0' */ - int8_t count; /**< number of sectors 0...127 */ - uint8_t res2; /**< always '0' */ - uint16_t offset; /**< buffer address: offset */ - uint16_t segment; /**< buffer address: segment */ - uint64_t lba; /**< LBA of the start sector */ -} __attribute__ ((packed)); - -/** - * Collection of data we need to know about the connected drive - */ -struct media_access { - int drive_no; /**< drive number used by the BIOS */ - int is_cdrom; /**< drive is a CDROM e.g. no write support */ -}; - -/** - * Scratch memory for BIOS communication to handle data in chunks of 32 kiB - * - * Note: This variable is located in the .bss segment, assuming it is located - * below 0xA0000. If not, the BIOS is not able to read or store any data - * from/to it. The variable must also aligned to a 16 byte boundary to easify - * linear to segment:offset address conversion. - */ -static uint8_t scratch_buffer[SECTORS_AT_ONCE * SECTOR_SIZE] __attribute__((aligned(16))); - -/** - * Communication buffer for the 16 bit int13 BIOS call - * - * Note: This variable is located in the .bss segment, assuming it is located - * below 0xA0000. If not, the BIOS is not able to read or store any data - * from/to it. The variable must also aligned to a 16 byte boundary to easify - * linear to segment:offset conversion. - */ -static struct DAPS bios_daps __attribute__((aligned(16))); - -/** - * @param media our data we need to do the access - * @param cmd Command to forward to the BIOS - * @param sector_start LBA of the start sector - * @param sector_count Sector count - * @param buffer Buffer to read from or write to (in the low memory area) - * @return 0 on success, anything else on failure - */ -static int biosdisk_bios_call(struct media_access *media, int cmd, uint64_t sector_start, unsigned sector_count, void *buffer) -{ - int rc; - - /* prepare the DAPS for the int13 call */ - bios_daps.size = sizeof(struct DAPS); - bios_daps.res1 = 0; - bios_daps.count = sector_count; /* always less than 128! */ - bios_daps.res2 = 0; - bios_daps.segment = (unsigned long)buffer >> 4; - bios_daps.offset = (unsigned long)buffer - (unsigned long)(bios_daps.segment << 4); - bios_daps.lba = sector_start; - - if (cmd == BIOS_READ_CMD) - rc = bios_disk_rw_int13_extensions(0x42, media->drive_no, &bios_daps); - else if (cmd == BIOS_WRT_CMD) - rc = bios_disk_rw_int13_extensions(0x43, media->drive_no, &bios_daps); - else - return -1; - - return rc; -} - -/** - * Read a chunk of sectors from media - * @param dev our data we need to do the access - * @param sector_start Sector's LBA number to start read from - * @param sector_count Sectors to read - * @param buffer Buffer to read into - * @return 0 on success, anything else on failure - * - * This routine expects the buffer has the correct size to store all data! - */ -static int biosdisk_read(struct device_d *dev, uint64_t sector_start, unsigned sector_count, void *buffer) -{ - int rc; - struct ata_interface *intf = dev->platform_data; - struct media_access *media = intf->priv; - - while (sector_count >= SECTORS_AT_ONCE) { - rc = biosdisk_bios_call(media, BIOS_READ_CMD, sector_start, SECTORS_AT_ONCE, scratch_buffer); - if (rc != 0) - return rc; - __builtin_memcpy(buffer, scratch_buffer, sizeof(scratch_buffer)); - buffer += sizeof(scratch_buffer); - sector_start += SECTORS_AT_ONCE; - sector_count -= SECTORS_AT_ONCE; - }; - - /* Are sectors still remaining? */ - if (sector_count) { - rc = biosdisk_bios_call(media, BIOS_READ_CMD, sector_start, sector_count, scratch_buffer); - __builtin_memcpy(buffer, scratch_buffer, sector_count * SECTOR_SIZE); - } else - rc = 0; - - return rc; -} - -/** - * Write a chunk of sectors to media - * @param dev our data we need to do the access - * @param sector_start Sector's LBA number to start write to - * @param sector_count Sectors to write - * @param buffer Buffer to write from - * @return 0 on success, anything else on failure - * - * This routine expects the buffer has the correct size to read all data! - */ -static int biosdisk_write(struct device_d *dev, uint64_t sector_start, unsigned sector_count, const void *buffer) -{ - int rc; - struct ata_interface *intf = dev->platform_data; - struct media_access *media = intf->priv; - - while (sector_count >= SECTORS_AT_ONCE) { - __builtin_memcpy(scratch_buffer, buffer, sizeof(scratch_buffer)); - rc = biosdisk_bios_call(media, BIOS_WRT_CMD, sector_start, SECTORS_AT_ONCE, scratch_buffer); - if (rc != 0) - return rc; - buffer += sizeof(scratch_buffer); - sector_start += SECTORS_AT_ONCE; - sector_count -= SECTORS_AT_ONCE; - }; - - /* Are sectors still remaining? */ - if (sector_count) { - __builtin_memcpy(scratch_buffer, buffer, sector_count * SECTOR_SIZE); - rc = biosdisk_bios_call(media, BIOS_WRT_CMD, sector_start, sector_count, scratch_buffer); - } else - rc = 0; - - return rc; -} - -/** - * Probe for connected drives and register them - * - * Detecting if a drive is present is done by simply reading its MBR. - * - * FIXME: Relation between BIOS disk numbering scheme and our representation - * here in barebox (and later on in the linux kernel) - */ -static int biosdisk_probe(struct device_d *dev) -{ - int drive, rc; - struct media_access media, *m; - struct device_d *drive_dev; - struct ata_interface *p; - - for (drive = 0x80; drive < 0x90; drive++) { - media.drive_no = drive; - media.is_cdrom = 0; /* don't know yet */ - rc = biosdisk_bios_call(&media, BIOS_READ_CMD, 0, 1, scratch_buffer); - if (rc != 0) - continue; - - printf("BIOSdrive %d seems valid. Registering...\n", media.drive_no); - - drive_dev = xzalloc(sizeof(struct device_d) + sizeof(struct media_access) + sizeof(struct ata_interface)); - if (drive_dev == NULL) { - dev_err(dev, "Out of memory\n"); - return -1; - } - m = (struct media_access*)&drive_dev[1]; - p = (struct ata_interface*)&m[1]; - - m->drive_no = drive; - m->is_cdrom = 0; - - p->write = biosdisk_write; - p->read = biosdisk_read; - p->priv = m; - - strcpy(drive_dev->name, "biosdisk"); - drive_dev->id = drive - 0x80; - drive_dev->resource[0].start = 0; - drive_dev->platform_data = p; - - register_device(drive_dev); - } - - return 0; -} - -static struct driver_d biosdisk_driver = { - .name = "biosdrive", - .probe = biosdisk_probe, -}; - -static int biosdisk_init(void) -{ - /* sanity */ - if (scratch_buffer > (uint8_t*)0x9FFFF) { - printf("BIOS driver: Scratch memory not in real mode area. Cannot continue!\n"); - return -EIO; - } - if (&bios_daps > (struct DAPS*)0x9FFFF) { - printf("BIOS driver: DAPS memory not in real mode area. Cannot continue!\n"); - return -EIO; - } - - register_driver(&biosdisk_driver); - return 0; -} - -device_initcall(biosdisk_init); diff --git a/drivers/ata/disk_bios_drive.c b/drivers/ata/disk_bios_drive.c new file mode 100644 index 0000000000..6e2377c7ea --- /dev/null +++ b/drivers/ata/disk_bios_drive.c @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2009 Juergen Beisert, Pengutronix + * + * Mostly stolen from the GRUB2 project + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, 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 + * + */ + +/** + * @file + * @brief Media communication layer through the standard 16 bit PC-BIOS + * + * This communication driver does all accesses to the boot medium via 16 bit + * real mode calls into the standard BIOS. Due to this method, its possible + * to use all the medias to boot from that are supported by the BIOS. This + * also includes emulated only medias. + * + * To be able to call the real mode BIOS, this driver must switch back to + * real mode for each access. This will slow down the access a little bit, but + * we are a boot loader here, not an operating system... + * + * Note: We need scratch memory for the BIOS communication, because the BIOS + * can only handle memory below 0xA0000. So we must copy all data between + * the flat mode buffers and realmode buffers. + * + * Note: This driver makes no sense on other architectures than x86. + * + * Note: This driver does only support LBA addressing. Currently no CHS! + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * Sector count handled in one count + * + * @todo 127 are always possible, some BIOS manufacturer supports up to 255. + * Is it's worth to detect Phoenic's restriction? + */ +#define SECTORS_AT_ONCE 64 + +/** Size of one sector in bytes */ +#define SECTOR_SIZE 512 + +/** Command to read sectors from media */ +#define BIOS_READ_CMD 0 + +/** Command to write sectors to media */ +#define BIOS_WRT_CMD 1 + +/** + * "Disk Address Packet Structure" to be used when calling + * BIOS's int13, function 0x42/0x43 + */ +struct DAPS +{ + uint8_t size; /**< always '16' */ + uint8_t res1; /**< always '0' */ + int8_t count; /**< number of sectors 0...127 */ + uint8_t res2; /**< always '0' */ + uint16_t offset; /**< buffer address: offset */ + uint16_t segment; /**< buffer address: segment */ + uint64_t lba; /**< LBA of the start sector */ +} __attribute__ ((packed)); + +/** + * Collection of data we need to know about the connected drive + */ +struct media_access { + int drive_no; /**< drive number used by the BIOS */ + int is_cdrom; /**< drive is a CDROM e.g. no write support */ +}; + +/** + * Scratch memory for BIOS communication to handle data in chunks of 32 kiB + * + * Note: This variable is located in the .bss segment, assuming it is located + * below 0xA0000. If not, the BIOS is not able to read or store any data + * from/to it. The variable must also aligned to a 16 byte boundary to easify + * linear to segment:offset address conversion. + */ +static uint8_t scratch_buffer[SECTORS_AT_ONCE * SECTOR_SIZE] __attribute__((aligned(16))); + +/** + * Communication buffer for the 16 bit int13 BIOS call + * + * Note: This variable is located in the .bss segment, assuming it is located + * below 0xA0000. If not, the BIOS is not able to read or store any data + * from/to it. The variable must also aligned to a 16 byte boundary to easify + * linear to segment:offset conversion. + */ +static struct DAPS bios_daps __attribute__((aligned(16))); + +/** + * @param media our data we need to do the access + * @param cmd Command to forward to the BIOS + * @param sector_start LBA of the start sector + * @param sector_count Sector count + * @param buffer Buffer to read from or write to (in the low memory area) + * @return 0 on success, anything else on failure + */ +static int biosdisk_bios_call(struct media_access *media, int cmd, uint64_t sector_start, unsigned sector_count, void *buffer) +{ + int rc; + + /* prepare the DAPS for the int13 call */ + bios_daps.size = sizeof(struct DAPS); + bios_daps.res1 = 0; + bios_daps.count = sector_count; /* always less than 128! */ + bios_daps.res2 = 0; + bios_daps.segment = (unsigned long)buffer >> 4; + bios_daps.offset = (unsigned long)buffer - (unsigned long)(bios_daps.segment << 4); + bios_daps.lba = sector_start; + + if (cmd == BIOS_READ_CMD) + rc = bios_disk_rw_int13_extensions(0x42, media->drive_no, &bios_daps); + else if (cmd == BIOS_WRT_CMD) + rc = bios_disk_rw_int13_extensions(0x43, media->drive_no, &bios_daps); + else + return -1; + + return rc; +} + +/** + * Read a chunk of sectors from media + * @param dev our data we need to do the access + * @param sector_start Sector's LBA number to start read from + * @param sector_count Sectors to read + * @param buffer Buffer to read into + * @return 0 on success, anything else on failure + * + * This routine expects the buffer has the correct size to store all data! + */ +static int biosdisk_read(struct device_d *dev, uint64_t sector_start, unsigned sector_count, void *buffer) +{ + int rc; + struct ata_interface *intf = dev->platform_data; + struct media_access *media = intf->priv; + + while (sector_count >= SECTORS_AT_ONCE) { + rc = biosdisk_bios_call(media, BIOS_READ_CMD, sector_start, SECTORS_AT_ONCE, scratch_buffer); + if (rc != 0) + return rc; + __builtin_memcpy(buffer, scratch_buffer, sizeof(scratch_buffer)); + buffer += sizeof(scratch_buffer); + sector_start += SECTORS_AT_ONCE; + sector_count -= SECTORS_AT_ONCE; + }; + + /* Are sectors still remaining? */ + if (sector_count) { + rc = biosdisk_bios_call(media, BIOS_READ_CMD, sector_start, sector_count, scratch_buffer); + __builtin_memcpy(buffer, scratch_buffer, sector_count * SECTOR_SIZE); + } else + rc = 0; + + return rc; +} + +/** + * Write a chunk of sectors to media + * @param dev our data we need to do the access + * @param sector_start Sector's LBA number to start write to + * @param sector_count Sectors to write + * @param buffer Buffer to write from + * @return 0 on success, anything else on failure + * + * This routine expects the buffer has the correct size to read all data! + */ +static int biosdisk_write(struct device_d *dev, uint64_t sector_start, unsigned sector_count, const void *buffer) +{ + int rc; + struct ata_interface *intf = dev->platform_data; + struct media_access *media = intf->priv; + + while (sector_count >= SECTORS_AT_ONCE) { + __builtin_memcpy(scratch_buffer, buffer, sizeof(scratch_buffer)); + rc = biosdisk_bios_call(media, BIOS_WRT_CMD, sector_start, SECTORS_AT_ONCE, scratch_buffer); + if (rc != 0) + return rc; + buffer += sizeof(scratch_buffer); + sector_start += SECTORS_AT_ONCE; + sector_count -= SECTORS_AT_ONCE; + }; + + /* Are sectors still remaining? */ + if (sector_count) { + __builtin_memcpy(scratch_buffer, buffer, sector_count * SECTOR_SIZE); + rc = biosdisk_bios_call(media, BIOS_WRT_CMD, sector_start, sector_count, scratch_buffer); + } else + rc = 0; + + return rc; +} + +/** + * Probe for connected drives and register them + * + * Detecting if a drive is present is done by simply reading its MBR. + * + * FIXME: Relation between BIOS disk numbering scheme and our representation + * here in barebox (and later on in the linux kernel) + */ +static int biosdisk_probe(struct device_d *dev) +{ + int drive, rc; + struct media_access media, *m; + struct device_d *drive_dev; + struct ata_interface *p; + + for (drive = 0x80; drive < 0x90; drive++) { + media.drive_no = drive; + media.is_cdrom = 0; /* don't know yet */ + rc = biosdisk_bios_call(&media, BIOS_READ_CMD, 0, 1, scratch_buffer); + if (rc != 0) + continue; + + printf("BIOSdrive %d seems valid. Registering...\n", media.drive_no); + + drive_dev = xzalloc(sizeof(struct device_d) + sizeof(struct media_access) + sizeof(struct ata_interface)); + if (drive_dev == NULL) { + dev_err(dev, "Out of memory\n"); + return -1; + } + m = (struct media_access*)&drive_dev[1]; + p = (struct ata_interface*)&m[1]; + + m->drive_no = drive; + m->is_cdrom = 0; + + p->write = biosdisk_write; + p->read = biosdisk_read; + p->priv = m; + + strcpy(drive_dev->name, "biosdisk"); + drive_dev->id = drive - 0x80; + drive_dev->resource[0].start = 0; + drive_dev->platform_data = p; + + register_device(drive_dev); + } + + return 0; +} + +static struct driver_d biosdisk_driver = { + .name = "biosdrive", + .probe = biosdisk_probe, +}; + +static int biosdisk_init(void) +{ + /* sanity */ + if (scratch_buffer > (uint8_t*)0x9FFFF) { + printf("BIOS driver: Scratch memory not in real mode area. Cannot continue!\n"); + return -EIO; + } + if (&bios_daps > (struct DAPS*)0x9FFFF) { + printf("BIOS driver: DAPS memory not in real mode area. Cannot continue!\n"); + return -EIO; + } + + register_driver(&biosdisk_driver); + return 0; +} + +device_initcall(biosdisk_init); diff --git a/drivers/ata/disk_drive.c b/drivers/ata/disk_drive.c index c2a6a5120d..c5c1ee9bfb 100644 --- a/drivers/ata/disk_drive.c +++ b/drivers/ata/disk_drive.c @@ -61,7 +61,7 @@ struct partition_entry { * @param table partition table * @return size in sectors */ -#ifdef CONFIG_ATA_BIOS +#ifdef CONFIG_DISK_BIOS static unsigned long disk_guess_size(struct device_d *dev, struct partition_entry *table) { int part_order[4] = {0, 1, 2, 3}; @@ -186,14 +186,14 @@ static int disk_probe(struct device_d *dev) * the drive ordering must not correspond to the Linux drive order, * use the 'biosdisk' name instead. */ -#ifdef CONFIG_ATA_BIOS +#ifdef CONFIG_DISK_BIOS if (strcmp(dev->driver->name, "biosdisk") == 0) atablk->blk.cdev.name = asprintf("biosdisk%d", dev->id); else #endif atablk->blk.cdev.name = asprintf("disk%d", dev->id); -#ifdef CONFIG_ATA_BIOS +#ifdef CONFIG_DISK_BIOS /* On x86, BIOS based disks are coming without a valid .size field */ if (dev->resource[0].size == 0) { /* guess the size of this drive if not otherwise given */ @@ -223,7 +223,7 @@ on_error: return rc; } -#ifdef CONFIG_ATA_BIOS +#ifdef CONFIG_DISK_BIOS static struct driver_d biosdisk_driver = { .name = "biosdisk", .probe = disk_probe, @@ -237,7 +237,7 @@ static struct driver_d disk_driver = { static int disk_init(void) { -#ifdef CONFIG_ATA_BIOS +#ifdef CONFIG_DISK_BIOS register_driver(&biosdisk_driver); #endif register_driver(&disk_driver); -- cgit v1.2.3 From 0748a120fbf2786c45f23234a07406ac5a9d2fd2 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Thu, 24 Nov 2011 13:43:45 +0100 Subject: ATA/DISK: Share important constants and structures Signed-off-by: Juergen Beisert Signed-off-by: Sascha Hauer --- include/disks.h | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 include/disks.h diff --git a/include/disks.h b/include/disks.h new file mode 100644 index 0000000000..ec136d4ee4 --- /dev/null +++ b/include/disks.h @@ -0,0 +1,39 @@ +/* + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef DISKS_H +#define DISKS_H + +struct block_device; + +/** Size of one sector in bytes */ +#define SECTOR_SIZE 512 + +/** Size of one sector in bit shift */ +#define SECTOR_SHIFT 9 + +/** + * Description of one partition table entry (D*S type) + */ +struct partition_entry { + uint8_t boot_indicator; /*! Maybe marked as an active partition */ + uint8_t chs_begin[3]; /*! Start of the partition in cylinders, heads and sectors */ + uint8_t type; /*! Filesystem type */ + uint8_t chs_end[3]; /*! End of the partition in cylinders, heads and sectors */ + uint32_t partition_start; /*! Start of the partition in LBA notation */ + uint32_t partition_size; /*! Start of the partition in LBA notation */ +} __attribute__ ((packed)); + +#endif /* DISKS_H */ -- cgit v1.2.3 From 967a2675ba32c88140a1656aa21256baac525986 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Thu, 24 Nov 2011 13:43:46 +0100 Subject: DISK: Add common partition handling for disk like media This covers disk like media like SD card, CF cards, regular hard disks and also USB mass storage devices. Most common used partition table is still of DOS type. This implementation is prepared to support more partition types in the future. Signed-off-by: Juergen Beisert Signed-off-by: Sascha Hauer --- common/Kconfig | 18 +++++ common/Makefile | 2 + common/partitions.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/disks.h | 2 + 4 files changed, 222 insertions(+) create mode 100644 common/partitions.c diff --git a/common/Kconfig b/common/Kconfig index 8e96920e48..1318e7d747 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -406,6 +406,24 @@ config PARTITION bool prompt "Enable Partitions" +if PARTITION + +config PARTITION_DISK + bool "DISK partition support" + help + Add support for handling common partition tables on all kind of disk + like devices (harddisks, CF cards, SD cards and so on) + +if PARTITION_DISK + +config PARTITION_DISK_DOS + bool "DOS partition support" + help + Add support to handle partitions in DOS style. + +endif +endif + config DEFAULT_ENVIRONMENT bool default y diff --git a/common/Makefile b/common/Makefile index 7bb8ea4322..3edf38f3ba 100644 --- a/common/Makefile +++ b/common/Makefile @@ -7,6 +7,8 @@ obj-$(CONFIG_ENV_HANDLING) += environment.o obj-$(CONFIG_AUTO_COMPLETE) += complete.o obj-$(CONFIG_POLLER) += poller.o obj-$(CONFIG_BLOCK) += block.o +obj-$(CONFIG_PARTITION_DISK) += partitions.o + obj-$(CONFIG_CMD_LOADS) += s_record.o obj-$(CONFIG_OFTREE) += oftree.o diff --git a/common/partitions.c b/common/partitions.c new file mode 100644 index 0000000000..e4f3ad69e3 --- /dev/null +++ b/common/partitions.c @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2009...2011 Juergen Beisert, Pengutronix + * + * 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 + * + */ + +/** + * @file + * @brief Generic support for partition tables on disk like media + * + * @todo Support for disks larger than 4 GiB + * @todo Reliable size detection for BIOS based disks (on x86 only) + */ +#include +#include +#include +#include +#include +#include + +struct partition { + uint64_t first_sec; + uint64_t size; +}; + +struct partition_desc { + int used_entries; + struct partition parts[8]; +}; + +/** + * Reject values which cannot be used in Barebox + * @param val Value to be check + * @return 0 if value can be used in Barebox, -EINVAL if not + * + * @note this routine can be removed when Barebox uses file offsets larger + * than 32 bit + */ +static int check_offset_value(uint64_t val) +{ +#if 1 /* until Barebox can handle 64 bit offsets */ + if (val > (__INT_MAX__ / SECTOR_SIZE)) + return -EINVAL; +#endif + return 0; +} + +/** + * Guess the size of the disk, based on the partition table entries + * @param dev device to create partitions for + * @param table partition table + * @return sector count + */ +static int disk_guess_size(struct device_d *dev, struct partition_entry *table) +{ + uint64_t size = 0; + int i; + + for (i = 0; i < 4; i++) { + if (table[i].partition_start != 0) { + size += get_unaligned(&table[i].partition_start) - size; + size += get_unaligned(&table[i].partition_size); + } + } + /* limit disk sector counts we can't handle due to 32 bit limits */ + if (check_offset_value(size) != 0) { + dev_warn(dev, "Warning: Sector count limited due to 31 bit" + "contraints\n"); + size = __INT_MAX__ / SECTOR_SIZE; + } + + return (int)size; +} + +/** + * Check if a DOS like partition describes this block device + * @param blk Block device to register to + * @param pd Where to store the partition information + * + * It seems at least on ARM this routine canot use temp. stack space for the + * sector. So, keep the malloc/free. + */ +static void __maybe_unused try_dos_partition(struct block_device *blk, + struct partition_desc *pd) +{ + uint8_t *buffer; + struct partition_entry *table; + struct partition pentry; + int i, rc; + + buffer = xmalloc(SECTOR_SIZE); + + /* read in the MBR to get the partition table */ + rc = blk->ops->read(blk, buffer, 0, 1); + if (rc != 0) { + dev_err(blk->dev, "Cannot read MBR/partition table\n"); + goto on_error; + } + + if ((buffer[510] != 0x55) || (buffer[511] != 0xAA)) { + dev_info(blk->dev, "No partition table found\n"); + goto on_error; + } + + table = (struct partition_entry *)&buffer[446]; + + /* valid for x86 BIOS based disks only */ + if (blk->num_blocks == 0) + blk->num_blocks = disk_guess_size(blk->dev, table); + + for (i = 0; i < 4; i++) { + pentry.first_sec = get_unaligned(&table[i].partition_start); + pentry.size = get_unaligned(&table[i].partition_size); + + /* do we have to ignore this partition due to limitations? */ + if (check_offset_value(pentry.first_sec) != 0) + continue; + if (check_offset_value(pentry.size) != 0) + continue; + + if (pentry.first_sec != 0) { + pd->parts[pd->used_entries].first_sec = pentry.first_sec; + pd->parts[pd->used_entries].size = pentry.size; + pd->used_entries++; + } else { + dev_dbg(blk->dev, "Skipping empty partition %d\n", i); + } + } + +on_error: + free(buffer); +} + +/** + * Register one partition on the given block device + * @param blk Block device to register to + * @param part Partition description + * @param no Partition number + * @return 0 on success + */ +static int register_one_partition(struct block_device *blk, + struct partition *part, int no) +{ + char partition_name[19]; + + sprintf(partition_name, "%s.%d", blk->cdev.name, no); + dev_dbg(blk->dev, "Registering partition %s on drive %s\n", + partition_name, blk->cdev.name); + return devfs_add_partition(blk->cdev.name, + part->first_sec * SECTOR_SIZE, + part->size * SECTOR_SIZE, + DEVFS_PARTITION_FIXED, partition_name); +} + +/** + * Try to collect partition information on the given block device + * @param blk Block device to examine + * @return 0 most of the time, negative value else + * + * It is not a failure if no partition information is found + */ +int parse_partition_table(struct block_device *blk) +{ + struct partition_desc pdesc = { .used_entries = 0, }; + int i; + int rc = 0; + +#ifdef CONFIG_PARTITION_DISK_DOS + try_dos_partition(blk, &pdesc); +#endif + if (!pdesc.used_entries) + return 0; + + /* at least one partition description found */ + for (i = 0; i < pdesc.used_entries; i++) { + rc = register_one_partition(blk, &pdesc.parts[i], i); + if (rc != 0) + dev_err(blk->dev, + "Failed to register partition %d on %s (%d)\n", + i, blk->cdev.name, rc); + if (rc != -ENODEV) + rc = 0; + } + + return rc; +} diff --git a/include/disks.h b/include/disks.h index ec136d4ee4..9932750a24 100644 --- a/include/disks.h +++ b/include/disks.h @@ -36,4 +36,6 @@ struct partition_entry { uint32_t partition_size; /*! Start of the partition in LBA notation */ } __attribute__ ((packed)); +extern int parse_partition_table(struct block_device*); + #endif /* DISKS_H */ -- cgit v1.2.3 From 82db23d3f4c1de25bbd4b222a3bd9e81d00414f8 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Thu, 24 Nov 2011 13:43:47 +0100 Subject: Use generic block layer to access the drives and do partition parsing Change all relevant blockdevice users to the simplified interface. Signed-off-by: Juergen Beisert Signed-off-by: Sascha Hauer --- drivers/ata/Kconfig | 2 + drivers/ata/disk_bios_drive.c | 102 +++++++++++++++++-------------- drivers/mci/Kconfig | 1 - drivers/mci/mci-core.c | 135 +++++++++++++++++++++++++----------------- drivers/usb/storage/Kconfig | 1 + drivers/usb/storage/usb.c | 124 ++++++++++++++++++++++---------------- drivers/usb/storage/usb.h | 8 +-- include/mci.h | 3 +- 8 files changed, 219 insertions(+), 157 deletions(-) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index f3b29397c6..a85958c7a1 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -1,5 +1,7 @@ menuconfig DISK select BLOCK + select PARTITION + select PARTITION_DISK bool "Disk support " help Add support for disk like drives like harddisks, CDROMs, SD cards and diff --git a/drivers/ata/disk_bios_drive.c b/drivers/ata/disk_bios_drive.c index 6e2377c7ea..78672454c0 100644 --- a/drivers/ata/disk_bios_drive.c +++ b/drivers/ata/disk_bios_drive.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Juergen Beisert, Pengutronix + * Copyright (C) 2009...2011 Juergen Beisert, Pengutronix * * Mostly stolen from the GRUB2 project * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc. @@ -43,15 +43,13 @@ * Note: This driver does only support LBA addressing. Currently no CHS! */ -#include -#include +#include #include -#include -#include -#include #include -#include #include +#include +#include +#include /** * Sector count handled in one count @@ -61,9 +59,6 @@ */ #define SECTORS_AT_ONCE 64 -/** Size of one sector in bytes */ -#define SECTOR_SIZE 512 - /** Command to read sectors from media */ #define BIOS_READ_CMD 0 @@ -89,10 +84,13 @@ struct DAPS * Collection of data we need to know about the connected drive */ struct media_access { + struct block_device blk; /**< the main device */ int drive_no; /**< drive number used by the BIOS */ int is_cdrom; /**< drive is a CDROM e.g. no write support */ }; +#define to_media_access(x) container_of((x), struct media_access, blk) + /** * Scratch memory for BIOS communication to handle data in chunks of 32 kiB * @@ -146,19 +144,23 @@ static int biosdisk_bios_call(struct media_access *media, int cmd, uint64_t sect /** * Read a chunk of sectors from media - * @param dev our data we need to do the access - * @param sector_start Sector's LBA number to start read from - * @param sector_count Sectors to read + * @param blk All info about the block device we need * @param buffer Buffer to read into + * @param block Sector's LBA number to start read from + * @param num_blocks Sector count to read * @return 0 on success, anything else on failure * * This routine expects the buffer has the correct size to store all data! + * + * @note Due to 'block' is of type 'int' only small disks can be handled! */ -static int biosdisk_read(struct device_d *dev, uint64_t sector_start, unsigned sector_count, void *buffer) +static int biosdisk_read(struct block_device *blk, void *buffer, int block, + int num_blocks) { int rc; - struct ata_interface *intf = dev->platform_data; - struct media_access *media = intf->priv; + uint64_t sector_start = block; + unsigned sector_count = num_blocks; + struct media_access *media = to_media_access(blk); while (sector_count >= SECTORS_AT_ONCE) { rc = biosdisk_bios_call(media, BIOS_READ_CMD, sector_start, SECTORS_AT_ONCE, scratch_buffer); @@ -182,19 +184,23 @@ static int biosdisk_read(struct device_d *dev, uint64_t sector_start, unsigned s /** * Write a chunk of sectors to media - * @param dev our data we need to do the access - * @param sector_start Sector's LBA number to start write to - * @param sector_count Sectors to write + * @param blk All info about the block device we need * @param buffer Buffer to write from + * @param block Sector's LBA number to start write to + * @param num_blocks Sector count to write * @return 0 on success, anything else on failure * * This routine expects the buffer has the correct size to read all data! + * + * @note Due to 'block' is of type 'int' only small disks can be handled! */ -static int biosdisk_write(struct device_d *dev, uint64_t sector_start, unsigned sector_count, const void *buffer) +static int __maybe_unused biosdisk_write(struct block_device *blk, + const void *buffer, int block, int num_blocks) { int rc; - struct ata_interface *intf = dev->platform_data; - struct media_access *media = intf->priv; + uint64_t sector_start = block; + unsigned sector_count = num_blocks; + struct media_access *media = to_media_access(blk); while (sector_count >= SECTORS_AT_ONCE) { __builtin_memcpy(scratch_buffer, buffer, sizeof(scratch_buffer)); @@ -216,6 +222,13 @@ static int biosdisk_write(struct device_d *dev, uint64_t sector_start, unsigned return rc; } +static struct block_device_ops bios_ata = { + .read = biosdisk_read, +#ifdef CONFIG_BLOCK_WRITE + .write = biosdisk_write, +#endif +}; + /** * Probe for connected drives and register them * @@ -228,8 +241,6 @@ static int biosdisk_probe(struct device_d *dev) { int drive, rc; struct media_access media, *m; - struct device_d *drive_dev; - struct ata_interface *p; for (drive = 0x80; drive < 0x90; drive++) { media.drive_no = drive; @@ -240,27 +251,32 @@ static int biosdisk_probe(struct device_d *dev) printf("BIOSdrive %d seems valid. Registering...\n", media.drive_no); - drive_dev = xzalloc(sizeof(struct device_d) + sizeof(struct media_access) + sizeof(struct ata_interface)); - if (drive_dev == NULL) { - dev_err(dev, "Out of memory\n"); - return -1; + m = xzalloc(sizeof(struct media_access)); + + m->blk.dev = dev; + m->blk.ops = &bios_ata; + /* + * keep the 'blk.num_blocks' member 0, as we don't know + * the size of this disk yet! + */ + rc = cdev_find_free_index("disk"); + if (rc < 0) + pr_err("Cannot find a free number for the disk node\n"); + m->blk.cdev.name = asprintf("disk%d", rc); + m->blk.blockbits = SECTOR_SHIFT; + + rc = blockdevice_register(&m->blk); + if (rc != 0) { + dev_err(dev, "Cannot register BIOSdrive %d\n", + media.drive_no); + free(m); + return rc; } - m = (struct media_access*)&drive_dev[1]; - p = (struct ata_interface*)&m[1]; - - m->drive_no = drive; - m->is_cdrom = 0; - - p->write = biosdisk_write; - p->read = biosdisk_read; - p->priv = m; - strcpy(drive_dev->name, "biosdisk"); - drive_dev->id = drive - 0x80; - drive_dev->resource[0].start = 0; - drive_dev->platform_data = p; - - register_device(drive_dev); + /* create partitions on demand */ + rc = parse_partition_table(&m->blk); + if (rc != 0) + dev_warn(dev, "No partition table found\n"); } return 0; diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig index 148c389ecc..00c28f1b48 100644 --- a/drivers/mci/Kconfig +++ b/drivers/mci/Kconfig @@ -1,7 +1,6 @@ menuconfig MCI bool "MCI drivers " select DISK - select DISK_DRIVE help Add support for MCI drivers, used to handle MMC and SD cards diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index 3043688552..1da7aff048 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -36,7 +36,8 @@ #include #include #include -#include +#include +#include #define MAX_BUFFER_NUMBER 0xffffffff @@ -104,10 +105,10 @@ static void *sector_buf; * @param mci_dev MCI instance * @param src Where to read from to write to the card * @param blocknum Block number to write + * @param blocks Block count to write * @return Transaction status (0 on success) */ -#ifdef CONFIG_MCI_WRITE -static int mci_block_write(struct device_d *mci_dev, const void *src, unsigned blocknum, +static int mci_block_write(struct device_d *mci_dev, const void *src, int blocknum, int blocks) { struct mci *mci = GET_MCI_DATA(mci_dev); @@ -154,7 +155,6 @@ static int mci_block_write(struct device_d *mci_dev, const void *src, unsigned b return ret; } -#endif /** * Read one block of data from the card @@ -163,7 +163,7 @@ static int mci_block_write(struct device_d *mci_dev, const void *src, unsigned b * @param blocknum Block number to read * @param blocks number of blocks to read */ -static int mci_read_block(struct device_d *mci_dev, void *dst, unsigned blocknum, +static int mci_read_block(struct device_d *mci_dev, void *dst, int blocknum, int blocks) { struct mci *mci = GET_MCI_DATA(mci_dev); @@ -856,14 +856,14 @@ static int mci_startup(struct device_d *mci_dev) mci_extract_card_capacity_from_csd(mci_dev); /* sanitiy? */ - if (mci->read_bl_len > 512) { - mci->read_bl_len = 512; + if (mci->read_bl_len > SECTOR_SIZE) { + mci->read_bl_len = SECTOR_SIZE; pr_debug("Limiting max. read block size down to %u\n", mci->read_bl_len); } - if (mci->write_bl_len > 512) { - mci->write_bl_len = 512; + if (mci->write_bl_len > SECTOR_SIZE) { + mci->write_bl_len = SECTOR_SIZE; pr_debug("Limiting max. write block size down to %u\n", mci->read_bl_len); } @@ -994,73 +994,68 @@ static int sd_send_if_cond(struct device_d *mci_dev) return 0; } -/* ------------------ attach to the ATA API --------------------------- */ +/* ------------------ attach to the blocklayer --------------------------- */ /** * Write a chunk of sectors to media - * @param disk_dev Disk device instance - * @param sector_start Sector's number to start write to - * @param sector_count Sectors to write + * @param blk All info about the block device we need * @param buffer Buffer to write from + * @param block Sector's number to start write to + * @param num_blocks Sector count to write * @return 0 on success, anything else on failure * * This routine expects the buffer has the correct size to read all data! */ -#ifdef CONFIG_MCI_WRITE -static int mci_sd_write(struct device_d *disk_dev, uint64_t sector_start, - unsigned sector_count, const void *buffer) +static int __maybe_unused mci_sd_write(struct block_device *blk, + const void *buffer, int block, int num_blocks) { - struct ata_interface *intf = disk_dev->platform_data; - struct device_d *mci_dev = intf->priv; + struct device_d *mci_dev = blk->dev; struct mci *mci = GET_MCI_DATA(mci_dev); int rc; - pr_debug("%s: Write %u block(s), starting at %u\n", - __func__, sector_count, (unsigned)sector_start); + pr_debug("%s: Write %d block(s), starting at %d\n", + __func__, num_blocks, block); - if (mci->write_bl_len != 512) { - pr_debug("MMC/SD block size is not 512 bytes (its %u bytes instead)\n", - mci->read_bl_len); + if (mci->write_bl_len != SECTOR_SIZE) { + pr_debug("MMC/SD block size is not %d bytes (its %u bytes instead)\n", + SECTOR_SIZE, mci->read_bl_len); return -EINVAL; } /* size of the block number field in the MMC/SD command is 32 bit only */ - if (sector_start > MAX_BUFFER_NUMBER) { - pr_debug("Cannot handle block number %llu. Too large!\n", - sector_start); + if (block > MAX_BUFFER_NUMBER) { + pr_debug("Cannot handle block number %d. Too large!\n", block); return -EINVAL; } - rc = mci_block_write(mci_dev, buffer, sector_start, sector_count); + rc = mci_block_write(mci_dev, buffer, block, num_blocks); if (rc != 0) { - pr_debug("Writing block %u failed with %d\n", (unsigned)sector_start, rc); + pr_debug("Writing block %d failed with %d\n", block, rc); return rc; } return 0; } -#endif /** - * Read a chunk of sectors from media - * @param disk_dev Disk device instance - * @param sector_start Sector's number to start read from - * @param sector_count Sectors to read + * Read a chunk of sectors from the drive + * @param blk All info about the block device we need * @param buffer Buffer to read into + * @param block Sector's LBA number to start read from + * @param num_blocks Sector count to read * @return 0 on success, anything else on failure * * This routine expects the buffer has the correct size to store all data! */ -static int mci_sd_read(struct device_d *disk_dev, uint64_t sector_start, - unsigned sector_count, void *buffer) +static int mci_sd_read(struct block_device *blk, void *buffer, int block, + int num_blocks) { - struct ata_interface *intf = disk_dev->platform_data; - struct device_d *mci_dev = intf->priv; + struct device_d *mci_dev = blk->dev; struct mci *mci = GET_MCI_DATA(mci_dev); int rc; - pr_debug("%s: Read %u block(s), starting at %u\n", - __func__, sector_count, (unsigned)sector_start); + pr_debug("%s: Read %d block(s), starting at %d\n", + __func__, num_blocks, block); if (mci->read_bl_len != 512) { pr_debug("MMC/SD block size is not 512 bytes (its %u bytes instead)\n", @@ -1068,15 +1063,14 @@ static int mci_sd_read(struct device_d *disk_dev, uint64_t sector_start, return -EINVAL; } - if (sector_start > MAX_BUFFER_NUMBER) { - pr_err("Cannot handle block number %u. Too large!\n", - (unsigned)sector_start); + if (block > MAX_BUFFER_NUMBER) { + pr_err("Cannot handle block number %d. Too large!\n", block); return -EINVAL; } - rc = mci_read_block(mci_dev, buffer, (unsigned)sector_start, sector_count); + rc = mci_read_block(mci_dev, buffer, block, num_blocks); if (rc != 0) { - pr_debug("Reading block %u failed with %d\n", (unsigned)sector_start, rc); + pr_debug("Reading block %d failed with %d\n", block, rc); return rc; } @@ -1215,6 +1209,25 @@ static int mci_check_if_already_initialized(struct device_d *mci_dev) return 0; } +static int mci_calc_blk_cnt(uint64_t cap, unsigned shift) +{ + unsigned ret = cap >> shift; + + if (ret > 0x7fffffff) { + pr_warn("Limiting card size due to 31 bit contraints\n"); + return 0x7fffffff; + } + + return (int)ret; +} + +static struct block_device_ops mci_ops = { + .read = mci_sd_read, +#ifdef CONFIG_BLOCK_WRITE + .write = mci_sd_write, +#endif +}; + /** * Probe an MCI card at the given host interface * @param mci_dev MCI device instance @@ -1224,9 +1237,7 @@ static int mci_card_probe(struct device_d *mci_dev) { struct mci *mci = GET_MCI_DATA(mci_dev); struct mci_host *host = GET_MCI_PDATA(mci_dev); - struct ata_interface *p; int rc; - struct device_d *dev; /* start with a host interface reset */ rc = (host->init)(host, mci_dev); @@ -1270,16 +1281,29 @@ static int mci_card_probe(struct device_d *mci_dev) * An MMC/SD card acts like an ordinary disk. * So, re-use the disk driver to gain access to this media */ - p = xzalloc(sizeof(struct ata_interface)); + mci->blk.dev = mci_dev; + mci->blk.ops = &mci_ops; -#ifdef CONFIG_MCI_WRITE - p->write = mci_sd_write; -#endif - p->read = mci_sd_read; - p->priv = mci_dev; + rc = cdev_find_free_index("disk"); + if (rc == -1) + pr_err("Cannot find a free number for the disk node\n"); + + mci->blk.cdev.name = asprintf("disk%d", rc); + mci->blk.blockbits = SECTOR_SHIFT; + mci->blk.num_blocks = mci_calc_blk_cnt(mci->capacity, mci->blk.blockbits); + + rc = blockdevice_register(&mci->blk); + if (rc != 0) { + dev_err(mci_dev, "Failed to register MCI/SD blockdevice\n"); + goto on_error; + } - dev = add_generic_device("disk", -1, NULL, 0, mci->capacity, IORESOURCE_MEM, p); - dev_add_child(&host->dev, dev); + /* create partitions on demand */ + rc = parse_partition_table(&mci->blk); + if (rc != 0) { + dev_warn(mci_dev, "No partition table found\n"); + rc = 0; /* it's not a failure */ + } pr_debug("SD Card successfully added\n"); @@ -1410,8 +1434,9 @@ device_initcall(mci_init); */ int mci_register(struct mci_host *host) { - struct device_d *mci_dev = &host->dev; + struct device_d *mci_dev = xzalloc(sizeof(struct device_d)); + mci_dev->id = -1; strcpy(mci_dev->name, mci_driver.name); mci_dev->platform_data = (void*)host; dev_add_child(host->hw_dev, mci_dev); diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index f6c8c06b1e..b80c039117 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -1,2 +1,3 @@ config USB_STORAGE tristate "USB Mass Storage support" + select DISK diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 6dba8ccaca..ef07c54d60 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -195,33 +195,32 @@ static int usb_stor_write_10(ccb *srb, struct us_data *us, #define US_MAX_IO_BLK 32 +#define to_usb_mass_storage(x) container_of((x), struct us_blk_dev, blk) + enum { io_rd, io_wr }; /* Read / write a chunk of sectors on media */ -static int usb_stor_blk_io(int io_op, struct device_d *disk_dev, - uint64_t sector_start, unsigned sector_count, - void *buffer) +static int usb_stor_blk_io(int io_op, struct block_device *disk_dev, + int sector_start, int sector_count, void *buffer) { - struct ata_interface *pata_if = disk_dev->platform_data; - struct us_blk_dev *pblk_dev = (struct us_blk_dev *)pata_if->priv; + struct us_blk_dev *pblk_dev = to_usb_mass_storage(disk_dev); struct us_data *us = pblk_dev->us; ccb us_ccb; - ushort const sector_size = 512; unsigned sectors_done; if (sector_count == 0) return 0; /* check for unsupported block size */ - if (pblk_dev->blksz != sector_size) { - US_DEBUGP("%s: unsupported block size %lu\n", - __func__, pblk_dev->blksz); + if (pblk_dev->blk.blockbits != SECTOR_SHIFT) { + US_DEBUGP("%s: unsupported block shift %d\n", + __func__, pblk_dev->blk.blockbits); return -EINVAL; } /* check for invalid sector_start */ - if (sector_start >= pblk_dev->blknum || sector_start > (ulong)-1) { - US_DEBUGP("%s: start sector %llu too large\n", + if (sector_start >= pblk_dev->blk.num_blocks || sector_start > (ulong)-1) { + US_DEBUGP("%s: start sector %d too large\n", __func__, sector_start); return -EINVAL; } @@ -242,21 +241,21 @@ static int usb_stor_blk_io(int io_op, struct device_d *disk_dev, sector_count = INT_MAX; US_DEBUGP("Restricting I/O to %u blocks\n", sector_count); } - if (sector_start + sector_count > pblk_dev->blknum) { - sector_count = pblk_dev->blknum - sector_start; + if (sector_start + sector_count > pblk_dev->blk.num_blocks) { + sector_count = pblk_dev->blk.num_blocks - sector_start; US_DEBUGP("Restricting I/O to %u blocks\n", sector_count); } /* read / write the requested data */ - US_DEBUGP("%s %u block(s), starting from %llu\n", + US_DEBUGP("%s %u block(s), starting from %d\n", ((io_op == io_rd) ? "Read" : "Write"), sector_count, sector_start); sectors_done = 0; while (sector_count > 0) { int result; - ushort n = (ushort)min(sector_count, US_MAX_IO_BLK); - us_ccb.pdata = buffer + sectors_done * sector_size; - us_ccb.datalen = n * (ulong)sector_size; + unsigned n = min(sector_count, US_MAX_IO_BLK); + us_ccb.pdata = buffer + (sectors_done * SECTOR_SIZE); + us_ccb.datalen = n * SECTOR_SIZE; if (io_op == io_rd) result = usb_stor_read_10(&us_ccb, us, (ulong)sector_start, n); @@ -264,7 +263,7 @@ static int usb_stor_blk_io(int io_op, struct device_d *disk_dev, result = usb_stor_write_10(&us_ccb, us, (ulong)sector_start, n); if (result != 0) { - US_DEBUGP("I/O error at sector %llu\n", sector_start); + US_DEBUGP("I/O error at sector %d\n", sector_start); break; } sector_start += n; @@ -274,27 +273,31 @@ static int usb_stor_blk_io(int io_op, struct device_d *disk_dev, usb_disable_asynch(0); - US_DEBUGP("Successful I/O of %u blocks\n", sectors_done); + US_DEBUGP("Successful I/O of %d blocks\n", sectors_done); return (sector_count != 0) ? -EIO : 0; } /* Write a chunk of sectors to media */ -static int usb_stor_blk_write(struct device_d *disk_dev, uint64_t sector_start, - unsigned sector_count, const void *buffer) +static int __maybe_unused usb_stor_blk_write(struct block_device *blk, + const void *buffer, int block, int num_blocks) { - return usb_stor_blk_io(io_wr, disk_dev, sector_start, sector_count, - (void *)buffer); + return usb_stor_blk_io(io_wr, blk, block, num_blocks, (void *)buffer); } /* Read a chunk of sectors from media */ -static int usb_stor_blk_read(struct device_d *disk_dev, uint64_t sector_start, - unsigned sector_count, void *buffer) +static int usb_stor_blk_read(struct block_device *blk, void *buffer, int block, + int num_blocks) { - return usb_stor_blk_io(io_rd, disk_dev, sector_start, sector_count, - buffer); + return usb_stor_blk_io(io_rd, blk, block, num_blocks, buffer); } +static struct block_device_ops usb_mass_storage_ops = { + .read = usb_stor_blk_read, +#ifdef CONFIG_BLOCK_WRITE + .write = usb_stor_blk_write, +#endif +}; /*********************************************************************** * Block device routines @@ -302,6 +305,16 @@ static int usb_stor_blk_read(struct device_d *disk_dev, uint64_t sector_start, static unsigned char us_io_buf[512]; +static int usb_limit_blk_cnt(unsigned cnt) +{ + if (cnt > 0x7fffffff) { + pr_warn("Limiting device size due to 31 bit contraints\n"); + return 0x7fffffff; + } + + return (int)cnt; +} + /* Prepare a disk device */ static int usb_stor_init_blkdev(struct us_blk_dev *pblk_dev) { @@ -313,7 +326,7 @@ static int usb_stor_init_blkdev(struct us_blk_dev *pblk_dev) us_ccb.pdata = us_io_buf; us_ccb.lun = pblk_dev->lun; - pblk_dev->blknum = 0; + pblk_dev->blk.num_blocks = 0; usb_disable_asynch(1); /* get device info */ @@ -350,11 +363,12 @@ static int usb_stor_init_blkdev(struct us_blk_dev *pblk_dev) } pcap = (unsigned long *)us_ccb.pdata; US_DEBUGP("Read Capacity returns: 0x%lx, 0x%lx\n", pcap[0], pcap[1]); - pblk_dev->blknum = be32_to_cpu(pcap[0]); - pblk_dev->blksz = be32_to_cpu(pcap[1]); - pblk_dev->blknum++; - US_DEBUGP("Capacity = 0x%llx, blocksz = 0x%lx\n", - pblk_dev->blknum, pblk_dev->blksz); + pblk_dev->blk.num_blocks = usb_limit_blk_cnt(be32_to_cpu(pcap[0]) + 1); + if (be32_to_cpu(pcap[1]) != SECTOR_SIZE) + pr_warn("Support only %d bytes sectors\n", SECTOR_SIZE); + pblk_dev->blk.blockbits = SECTOR_SHIFT; + US_DEBUGP("Capacity = 0x%x, blockshift = 0x%x\n", + pblk_dev->blk.num_blocks, pblk_dev->blk.blockbits); Exit: usb_disable_asynch(0); @@ -362,39 +376,45 @@ Exit: } /* Create and register a disk device for the specified LUN */ -static int usb_stor_add_blkdev(struct us_data *us, unsigned char lun) +static int usb_stor_add_blkdev(struct us_data *us, struct device_d *dev, + unsigned char lun) { struct us_blk_dev *pblk_dev; - struct device_d *pdev; - struct ata_interface *pata_if; int result; - /* allocate blk dev data */ - pblk_dev = (struct us_blk_dev *)malloc(sizeof(struct us_blk_dev)); - if (!pblk_dev) - return -ENOMEM; - memset(pblk_dev, 0, sizeof(struct us_blk_dev)); + /* allocate a new USB block device */ + pblk_dev = xzalloc(sizeof(struct us_blk_dev)); /* initialize blk dev data */ + pblk_dev->blk.dev = dev; + pblk_dev->blk.ops = &usb_mass_storage_ops; pblk_dev->us = us; pblk_dev->lun = lun; - pata_if = &pblk_dev->ata_if; - pata_if->read = &usb_stor_blk_read; - pata_if->write = &usb_stor_blk_write; - pata_if->priv = pblk_dev; - pdev = &pblk_dev->dev; - strcpy(pdev->name, "disk"); - pdev->platform_data = pata_if; /* read some info and get the unit ready */ result = usb_stor_init_blkdev(pblk_dev); if (result < 0) goto BadDevice; - /* register disk device */ - result = register_device(pdev); - if (result < 0) + result = cdev_find_free_index("disk"); + if (result == -1) + pr_err("Cannot find a free number for the disk node\n"); + pr_info("Using index %d for the new disk\n", result); + + pblk_dev->blk.cdev.name = asprintf("disk%d", result); + pblk_dev->blk.blockbits = SECTOR_SHIFT; + + result = blockdevice_register(&pblk_dev->blk); + if (result != 0) { + dev_err(dev, "Failed to register blockdevice\n"); goto BadDevice; + } + + /* create partitions on demand */ + result = parse_partition_table(&pblk_dev->blk); + if (result != 0) + dev_warn(dev, "No partition table found\n"); + list_add_tail(&pblk_dev->list, &us_blkdev_list); US_DEBUGP("USB disk device successfully added\n"); @@ -485,7 +505,7 @@ static int usb_stor_scan(struct usb_device *usbdev, struct us_data *us) /* register a disk device for each active LUN */ for (lun=0; lun<=us->max_lun; lun++) { - if (usb_stor_add_blkdev(us, lun) == 0) + if (usb_stor_add_blkdev(us, &usbdev->dev, lun) == 0) num_devs++; } diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 17a1e1263e..59423934dd 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -26,7 +26,8 @@ #define _STORAGE_USB_H_ #include -#include +#include +#include #include #include @@ -85,10 +86,7 @@ struct us_data { /* one us_blk_dev object allocated per LUN */ struct us_blk_dev { struct us_data *us; /* LUN's enclosing dev */ - struct device_d dev; /* intf to generic driver */ - struct ata_interface ata_if; /* intf to "disk" driver */ - uint64_t blknum; /* capacity */ - unsigned long blksz; /* block size */ + struct block_device blk; /* the blockdevice for the dev */ unsigned char lun; /* the LUN of this blk dev */ struct list_head list; /* siblings */ }; diff --git a/include/mci.h b/include/mci.h index d581f99929..d3b3082fc1 100644 --- a/include/mci.h +++ b/include/mci.h @@ -31,6 +31,7 @@ #define _MCI_H_ #include +#include /* Firmware revisions for SD cards */ #define SD_VERSION_SD 0x20000 @@ -212,7 +213,6 @@ struct mci_data { /** host information */ struct mci_host { struct device_d *hw_dev; /**< the host MCI hardware device */ - struct device_d dev; /**< our device */ unsigned voltages; unsigned host_caps; /**< Host's interface capabilities, refer MMC_VDD_* */ unsigned f_min; /**< host interface lower limit */ @@ -230,6 +230,7 @@ struct mci_host { /** MMC/SD and interface instance information */ struct mci { + struct block_device blk; /**< the blockdevice for the card */ unsigned version; /** != 0 when a high capacity card is connected (OCR -> OCR_HCS) */ int high_capacity; -- cgit v1.2.3 From 1e56da922b5a9e83e6b31693f86898cf4ffa5718 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Thu, 24 Nov 2011 13:43:48 +0100 Subject: Remove 'disk_drive.c' as it is now replaced by generic partition handling Signed-off-by: Juergen Beisert Signed-off-by: Sascha Hauer --- drivers/ata/Kconfig | 8 -- drivers/ata/Makefile | 1 - drivers/ata/disk_drive.c | 247 ----------------------------------------------- 3 files changed, 256 deletions(-) delete mode 100644 drivers/ata/disk_drive.c diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index a85958c7a1..86b5673a36 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -15,16 +15,8 @@ config DISK_WRITE comment "drive types" -config DISK_DRIVE - bool "Generic disk drives" - help - Add support for generic disk drives. Common behaviour for this kind - of devices is using a partition table in the first sector. Say Y here - if you intend to work with disk drives (also CF cards and SD cards). - config DISK_BIOS bool "BIOS based" - select DISK_DRIVE depends on X86_BIOS_BRINGUP help Gain disk drive access via int13 calls to the standard PC-BIOS. diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 10f3957453..e2b41b7896 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -1,6 +1,5 @@ # drive types -obj-$(CONFIG_DISK_DRIVE) += disk_drive.o obj-$(CONFIG_DISK_BIOS) += disk_bios_drive.o # interface types diff --git a/drivers/ata/disk_drive.c b/drivers/ata/disk_drive.c deleted file mode 100644 index c5c1ee9bfb..0000000000 --- a/drivers/ata/disk_drive.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (C) 2009 Juergen Beisert, Pengutronix - * - * 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 - * - */ - -/** - * @file - * @brief Generic disk drive support - * - * @todo Support for disks larger than 4 GiB - * @todo Reliable size detection for BIOS based disks (on x86 only) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * Description of one partition table entry (D*S type) - */ -struct partition_entry { - uint8_t boot_indicator; - uint8_t chs_begin[3]; - uint8_t type; - uint8_t chs_end[3]; - uint32_t partition_start; - uint32_t partition_size; -} __attribute__ ((packed)); - -/** one for all */ -#define SECTOR_SIZE 512 - -/** - * Guess the size of the disk, based on the partition table entries - * @param dev device to create partitions for - * @param table partition table - * @return size in sectors - */ -#ifdef CONFIG_DISK_BIOS -static unsigned long disk_guess_size(struct device_d *dev, struct partition_entry *table) -{ - int part_order[4] = {0, 1, 2, 3}; - unsigned long size = 0; - int i; - - /* TODO order the partitions */ - - for (i = 0; i < 4; i++) { - if (table[part_order[i]].partition_start != 0) { - size += table[part_order[i]].partition_start - size; /* the gap */ - size += table[part_order[i]].partition_size; - } - } -#if 1 -/* limit disk sizes we can't handle due to 32 bit limits */ - if (size > 0x7fffff) { - dev_warn(dev, "Warning: Size limited due to 32 bit contraints\n"); - size = 0x7fffff; - } -#endif - return size; -} -#endif - -/** - * Register partitions found on the drive - * @param dev device to create partitions for - * @param table partition table - * @return 0 on success - */ -static int disk_register_partitions(struct device_d *dev, struct partition_entry *table) -{ - int part_order[4] = {0, 1, 2, 3}; - int i, rc; - char drive_name[16], partition_name[19]; - u32 partition_start, partition_size; - - /* TODO order the partitions */ - - for (i = 0; i < 4; i++) { - partition_start = get_unaligned(&table[part_order[i]].partition_start); - partition_size = get_unaligned(&table[part_order[i]].partition_size); - - sprintf(drive_name, "%s%d", dev->name, dev->id); - sprintf(partition_name, "%s%d.%d", dev->name, dev->id, i); - if (partition_start != 0) { -#if 1 -/* ignore partitions we can't handle due to 32 bit limits */ - if (partition_start > 0x7fffff) - continue; - if (partition_size > 0x7fffff) - continue; -#endif - dev_dbg(dev, "Registering partition %s to drive %s\n", - partition_name, drive_name); - rc = devfs_add_partition(drive_name, - partition_start * SECTOR_SIZE, - partition_size * SECTOR_SIZE, - DEVFS_PARTITION_FIXED, partition_name); - if (rc != 0) - dev_err(dev, "Failed to register partition %s (%d)\n", partition_name, rc); - } - } - - return 0; -} - -struct ata_block_device { - struct block_device blk; - struct device_d *dev; - struct ata_interface *intf; -}; - -static int atablk_read(struct block_device *blk, void *buf, int block, - int num_blocks) -{ - struct ata_block_device *atablk = container_of(blk, struct ata_block_device, blk); - - return atablk->intf->read(atablk->dev, block, num_blocks, buf); -} - -#ifdef CONFIG_DISK_WRITE -static int atablk_write(struct block_device *blk, const void *buf, int block, - int num_blocks) -{ - struct ata_block_device *atablk = container_of(blk, struct ata_block_device, blk); - - return atablk->intf->write(atablk->dev, block, num_blocks, buf); -} -#endif - -static struct block_device_ops ataops = { - .read = atablk_read, -#ifdef CONFIG_DISK_WRITE - .write = atablk_write, -#endif -}; - -/** - * Probe the connected disk drive - */ -static int disk_probe(struct device_d *dev) -{ - uint8_t *sector; - int rc; - struct ata_interface *intf = dev->platform_data; - struct ata_block_device *atablk = xzalloc(sizeof(*atablk)); - - sector = xmalloc(SECTOR_SIZE); - - rc = intf->read(dev, 0, 1, sector); - if (rc != 0) { - dev_err(dev, "Cannot read MBR of this device\n"); - rc = -ENODEV; - goto on_error; - } - - /* - * BIOS based disks needs special handling. Not the driver can - * enumerate the hardware, the BIOS did it already. To show the user - * the drive ordering must not correspond to the Linux drive order, - * use the 'biosdisk' name instead. - */ -#ifdef CONFIG_DISK_BIOS - if (strcmp(dev->driver->name, "biosdisk") == 0) - atablk->blk.cdev.name = asprintf("biosdisk%d", dev->id); - else -#endif - atablk->blk.cdev.name = asprintf("disk%d", dev->id); - -#ifdef CONFIG_DISK_BIOS - /* On x86, BIOS based disks are coming without a valid .size field */ - if (dev->resource[0].size == 0) { - /* guess the size of this drive if not otherwise given */ - dev->resource[0].size = disk_guess_size(dev, - (struct partition_entry*)§or[446]) * SECTOR_SIZE; - dev_info(dev, "Drive size guessed to %u kiB\n", dev->resource[0].size / 1024); - } -#endif - atablk->blk.num_blocks = dev->resource[0].size / SECTOR_SIZE; - atablk->blk.ops = &ataops; - atablk->blk.blockbits = 9; - atablk->dev = dev; - atablk->intf = intf; - blockdevice_register(&atablk->blk); - - if ((sector[510] != 0x55) || (sector[511] != 0xAA)) { - dev_info(dev, "No partition table found\n"); - rc = 0; - goto on_error; - } - - - rc = disk_register_partitions(dev, (struct partition_entry*)§or[446]); - -on_error: - free(sector); - return rc; -} - -#ifdef CONFIG_DISK_BIOS -static struct driver_d biosdisk_driver = { - .name = "biosdisk", - .probe = disk_probe, -}; -#endif - -static struct driver_d disk_driver = { - .name = "disk", - .probe = disk_probe, -}; - -static int disk_init(void) -{ -#ifdef CONFIG_DISK_BIOS - register_driver(&biosdisk_driver); -#endif - register_driver(&disk_driver); - return 0; -} - -device_initcall(disk_init); -- cgit v1.2.3 From fb491506ad58c4631b9b5dd2e6e2981be9774870 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Thu, 24 Nov 2011 13:43:49 +0100 Subject: ATA/DISK: Remove the now unused header This file is obsolete now. Signed-off-by: Juergen Beisert Signed-off-by: Sascha Hauer --- include/ata.h | 39 --------------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 include/ata.h diff --git a/include/ata.h b/include/ata.h deleted file mode 100644 index d56399ea75..0000000000 --- a/include/ata.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2009 Juergen Beisert, Pengutronix - * - * 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 - * - */ - -/** - * @file - * @brief Declarations to communicate with ATA types of drives - */ - -#include -#include - -/** - * Access functions from drives through the specified interface - */ -struct ata_interface { - /** write a count of sectors from a buffer to the drive */ - int (*write)(struct device_d*, uint64_t, unsigned, const void*); - /** read a count of sectors from the drive into the buffer */ - int (*read)(struct device_d*, uint64_t, unsigned, void*); - /** private interface data */ - void *priv; -}; -- cgit v1.2.3 From 16db801f4dc17e26faaaa7dccff39233fcc863f3 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Fri, 25 Nov 2011 15:36:17 +0100 Subject: ATA Disk Support: Add support for native ATA type drives This changed patch removes more of the u-boot like code and replace it with kernel like code. commit 2a8966936af6b54573483ade559d0633e489b515 Author: Juergen Beisert Date: Fri Sep 30 15:06:26 2011 +0200 ATA Disk Support: Add support for native ATA type drives Signed-off-by: Juergen Beisert Signed-off-by: Sascha Hauer --- drivers/ata/Kconfig | 6 + drivers/ata/Makefile | 1 + drivers/ata/disk_ata_drive.c | 618 +++++++++++++++++++++++++++++++++++++++++++ include/ata_drive.h | 100 +++++++ 4 files changed, 725 insertions(+) create mode 100644 drivers/ata/disk_ata_drive.c create mode 100644 include/ata_drive.h diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 86b5673a36..f4334c2ce9 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -24,6 +24,12 @@ config DISK_BIOS media to work on. Disadvantage is: Due to its 16 bit nature it is slow. +config DISK_ATA + bool "ATA type drives" + select DISK_DRIVE + help + Support for native ATA/IDE drives + comment "interface types" endif diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index e2b41b7896..cdbcbe7dbb 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -1,6 +1,7 @@ # drive types obj-$(CONFIG_DISK_BIOS) += disk_bios_drive.o +obj-$(CONFIG_DISK_ATA) += disk_ata_drive.o # interface types diff --git a/drivers/ata/disk_ata_drive.c b/drivers/ata/disk_ata_drive.c new file mode 100644 index 0000000000..4602af3c0d --- /dev/null +++ b/drivers/ata/disk_ata_drive.c @@ -0,0 +1,618 @@ +/* + * Copyright (C) 2011 Juergen Beisert, Pengutronix + * + * Inspired from various soures like http://wiki.osdev.org/ATA_PIO_Mode, + * u-boot and the linux kernel + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ATA_CMD_ID_DEVICE 0xEC +#define ATA_CMD_RD_CONF 0x40 +#define ATA_CMD_RD 0x20 +#define ATA_CMD_WR 0x30 + +#define DISK_MASTER 0 +#define DISK_SLAVE 1 + +/* max timeout for a rotating disk in [ms] */ +#define MAX_TIMEOUT 5000 + +/** + * Collection of data we need to know about this drive + */ +struct ata_drive_access { + struct block_device blk; /**< the main device */ + struct ata_ioports *io; /**< register file */ + uint16_t id[(SECTOR_SIZE / sizeof(uint16_t))]; +}; + +#define to_ata_drive_access(x) container_of((x), struct ata_drive_access, blk) + +#define ata_id_u32(id,n) \ + (((uint32_t) (id)[(n) + 1] << 16) | ((uint32_t) (id)[(n)])) +#define ata_id_u64(id,n) \ + ( ((uint64_t) (id)[(n) + 3] << 48) | \ + ((uint64_t) (id)[(n) + 2] << 32) | \ + ((uint64_t) (id)[(n) + 1] << 16) | \ + ((uint64_t) (id)[(n) + 0]) ) + +#define ata_id_has_lba(id) ((id)[49] & (1 << 9)) + +/* drive's status flags */ +#define ATA_STATUS_BUSY (1 << 7) +#define ATA_STATUS_READY (1 << 6) +#define ATA_STATUS_WR_FLT (1 << 5) +#define ATA_STATUS_DRQ (1 << 4) +#define ATA_STATUS_CORR (1 << 3) +#define ATA_STATUS_ERROR (1 << 1) +/* command flags */ +#define LBA_FLAG (1 << 6) +#define ATA_DEVCTL_SOFT_RESET (1 << 2) +#define ATA_DEVCTL_INTR_DISABLE (1 << 1) + +enum { + ATA_ID_SERNO = 10, +#define ATA_ID_SERNO_LEN 20 + ATA_ID_FW_REV = 23, +#define ATA_ID_FW_REV_LEN 8 + ATA_ID_PROD = 27, +#define ATA_ID_PROD_LEN 40 + ATA_ID_CAPABILITY = 49, + ATA_ID_FIELD_VALID = 53, + ATA_ID_LBA_CAPACITY = 60, + ATA_ID_MWDMA_MODES = 63, + ATA_ID_PIO_MODES = 64, + ATA_ID_QUEUE_DEPTH = 75, + ATA_ID_MAJOR_VER = 80, + ATA_ID_COMMAND_SET_1 = 82, + ATA_ID_COMMAND_SET_2 = 83, + ATA_ID_CFSSE = 84, + ATA_ID_CFS_ENABLE_1 = 85, + ATA_ID_CFS_ENABLE_2 = 86, + ATA_ID_CSF_DEFAULT = 87, + ATA_ID_UDMA_MODES = 88, + ATA_ID_HW_CONFIG = 93, + ATA_ID_LBA_CAPACITY_2 = 100, +}; + +static int ata_id_is_valid(const uint16_t *id) +{ + if ((id[ATA_ID_FIELD_VALID] & 1) == 0) { + pr_debug("Drive's ID seems invalid\n"); + return -EINVAL; + } + + return 0; +} + +static inline int ata_id_has_lba48(const uint16_t *id) +{ + if ((id[ATA_ID_COMMAND_SET_2] & 0xC000) != 0x4000) + return 0; + if (!ata_id_u64(id, ATA_ID_LBA_CAPACITY_2)) + return 0; + return id[ATA_ID_COMMAND_SET_2] & (1 << 10); +} + +static uint64_t ata_id_n_sectors(uint16_t *id) +{ + if (ata_id_has_lba(id)) { + if (ata_id_has_lba48(id)) + return ata_id_u64(id, ATA_ID_LBA_CAPACITY_2); + else + return ata_id_u32(id, ATA_ID_LBA_CAPACITY); + } + + return 0; +} + +static void ata_id_string(const uint16_t *id, unsigned char *s, + unsigned ofs, unsigned len) +{ + unsigned c; + + while (len > 0) { + c = id[ofs] >> 8; + *s = c; + s++; + + c = id[ofs] & 0xff; + *s = c; + s++; + + ofs++; + len -= 2; + } +} + +static void ata_id_c_string(const uint16_t *id, unsigned char *s, + unsigned ofs, unsigned len) +{ + unsigned char *p; + + ata_id_string(id, s, ofs, len - 1); + + p = s + strnlen((char *)s, len - 1); + while (p > s && p[-1] == ' ') + p--; + *p = '\0'; +} + +static void __maybe_unused ata_dump_id(uint16_t *id) +{ + unsigned char serial[ATA_ID_SERNO_LEN + 1]; + unsigned char firmware[ATA_ID_FW_REV_LEN + 1]; + unsigned char product[ATA_ID_PROD_LEN + 1]; + uint64_t n_sectors; + + /* Serial number */ + ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial)); + printf("S/N: %s\n\r", serial); + + /* Firmware version */ + ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware)); + printf("Firmware version: %s\n\r", firmware); + + /* Product model */ + ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product)); + printf("Product model number: %s\n\r", product); + + /* Total sectors of device */ + n_sectors = ata_id_n_sectors(id); + printf("Capablity: %lld sectors\n\r", n_sectors); + + printf ("id[49]: capabilities = 0x%04x\n" + "id[53]: field valid = 0x%04x\n" + "id[63]: mwdma = 0x%04x\n" + "id[64]: pio = 0x%04x\n" + "id[75]: queue depth = 0x%04x\n", + id[ATA_ID_CAPABILITY], + id[ATA_ID_FIELD_VALID], + id[ATA_ID_MWDMA_MODES], + id[ATA_ID_PIO_MODES], + id[ATA_ID_QUEUE_DEPTH]); + + printf ("id[76]: sata capablity = 0x%04x\n" + "id[78]: sata features supported = 0x%04x\n" + "id[79]: sata features enable = 0x%04x\n", + id[76], /* FIXME */ + id[78], /* FIXME */ + id[79]); /* FIXME */ + + printf ("id[80]: major version = 0x%04x\n" + "id[81]: minor version = 0x%04x\n" + "id[82]: command set supported 1 = 0x%04x\n" + "id[83]: command set supported 2 = 0x%04x\n" + "id[84]: command set extension = 0x%04x\n", + id[ATA_ID_MAJOR_VER], + id[81], /* FIXME */ + id[ATA_ID_COMMAND_SET_1], + id[ATA_ID_COMMAND_SET_2], + id[ATA_ID_CFSSE]); + printf ("id[85]: command set enable 1 = 0x%04x\n" + "id[86]: command set enable 2 = 0x%04x\n" + "id[87]: command set default = 0x%04x\n" + "id[88]: udma = 0x%04x\n" + "id[93]: hardware reset result = 0x%04x\n", + id[ATA_ID_CFS_ENABLE_1], + id[ATA_ID_CFS_ENABLE_2], + id[ATA_ID_CSF_DEFAULT], + id[ATA_ID_UDMA_MODES], + id[ATA_ID_HW_CONFIG]); +} + +/** + * Swap little endian data on demand + * @param buf Buffer with little endian word data + * @param wds 16 bit word count + * + * ATA disks report their ID data in little endian notation on a 16 bit word + * base. So swap the buffer content if the running CPU differs in their + * endiaeness. + */ +static void ata_fix_endianess(uint16_t *buf, unsigned wds) +{ +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned u; + + for (u = 0; u < wds; u++) + buf[u] = le16_to_cpu(buf[u]); +#endif +} + +/** + * Read the status register of the ATA drive + * @param io Register file + * @return Register's content + */ +static uint8_t ata_rd_status(struct ata_ioports *io) +{ + return readb(io->status_addr); +} + +/** + * Wait until the disk is busy or time out + * @param io Register file + * @param timeout Timeout in [ms] + * @return 0 on success, -ETIMEDOUT else + */ +static int ata_wait_busy(struct ata_ioports *io, unsigned timeout) +{ + uint8_t status; + uint64_t start = get_time_ns(); + uint64_t toffs = timeout * 1000 * 1000; + + do { + status = ata_rd_status(io); + if (status & ATA_STATUS_BUSY) + return 0; + } while (!is_timeout(start, toffs)); + + return -ETIMEDOUT; +} + +/** + * Wait until the disk is ready again or time out + * @param io Register file + * @param timeout Timeout in [ms] + * @return 0 on success, -ETIMEDOUT else + * + * This function is useful to check if the disk has accepted a command. + */ +static int ata_wait_ready(struct ata_ioports *io, unsigned timeout) +{ + uint8_t status; + uint64_t start = get_time_ns(); + uint64_t toffs = timeout * 1000 * 1000; + + do { + status = ata_rd_status(io); + if (!(status & ATA_STATUS_BUSY)) { + if (status & ATA_STATUS_READY) + return 0; + } + } while (!is_timeout(start, toffs)); + + return -ETIMEDOUT; +} + +/** + * Setup the sector number in LBA notation (LBA28) + * @param io Register file + * @param drive 0 master drive, 1 slave drive + * @param num Sector number + * + * @todo LBA48 support + */ +static int ata_set_lba_sector(struct ata_ioports *io, unsigned drive, uint64_t num) +{ + if (num > 0x0FFFFFFF || drive > 1) + return -EINVAL; + + writeb(0xA0 | LBA_FLAG | drive << 4 | num >> 24, io->device_addr); + writeb(0x00, io->error_addr); + writeb(0x01, io->nsect_addr); + writeb(num, io->lbal_addr); /* 0 ... 7 */ + writeb(num >> 8, io->lbam_addr); /* 8 ... 15 */ + writeb(num >> 16, io->lbah_addr); /* 16 ... 23 */ + + return 0; +} + +/** + * Write an ATA command into the disk + * @param io Register file + * @param cmd Command to write + * @return 0 on success + */ +static int ata_wr_cmd(struct ata_ioports *io, uint8_t cmd) +{ + int rc; + + rc = ata_wait_ready(io, MAX_TIMEOUT); + if (rc != 0) + return rc; + + writeb(cmd, io->command_addr); + return 0; +} + +/** + * Write a new value into the "device control register" + * @param io Register file + * @param val Value to write + */ +static void ata_wr_dev_ctrl(struct ata_ioports *io, uint8_t val) +{ + writeb(val, io->ctl_addr); +} + +/** + * Read one sector from the drive (always SECTOR_SIZE bytes at once) + * @param io Register file + * @param buf Buffer to read the data into + */ +static void ata_rd_sector(struct ata_ioports *io, void *buf) +{ + unsigned u = SECTOR_SIZE / sizeof(uint16_t); + uint16_t *b = buf; + + if (io->dataif_be) { + for (; u > 0; u--) + *b++ = be16_to_cpu(readw(io->data_addr)); + } else { + for (; u > 0; u--) + *b++ = le16_to_cpu(readw(io->data_addr)); + } +} + +/** + * Write one sector into the drive + * @param io Register file + * @param buf Buffer to read the data from + */ +static void ata_wr_sector(struct ata_ioports *io, const void *buf) +{ + unsigned u = SECTOR_SIZE / sizeof(uint16_t); + const uint16_t *b = buf; + + if (io->dataif_be) { + for (; u > 0; u--) + writew(cpu_to_be16(*b++), io->data_addr); + } else { + for (; u > 0; u--) + writew(cpu_to_le16(*b++), io->data_addr); + } +} + +/** + * Read the ATA disk's description info + * @param d All we need to know about the disk + * @return 0 on success + */ +static int ata_get_id(struct ata_drive_access *d) +{ + int rc; + + writeb(0xA0, d->io->device_addr); /* FIXME drive */ + writeb(0x00, d->io->lbal_addr); + writeb(0x00, d->io->lbam_addr); + writeb(0x00, d->io->lbah_addr); + + rc = ata_wr_cmd(d->io, ATA_CMD_ID_DEVICE); + if (rc != 0) + return rc; + + rc = ata_wait_ready(d->io, MAX_TIMEOUT); + if (rc != 0) + return rc; + + ata_rd_sector(d->io, &d->id); + + ata_fix_endianess(d->id, SECTOR_SIZE / sizeof(uint16_t)); + + return ata_id_is_valid(d->id); +} + +static int ata_reset(struct ata_ioports *io) +{ + int rc; + uint8_t reg; + + /* try a hard reset first (if available) */ + if (io->reset != NULL) { + pr_debug("%s: Resetting drive...\n", __func__); + io->reset(1); + rc = ata_wait_busy(io, 500); + io->reset(0); + if (rc == 0) { + rc = ata_wait_ready(io, MAX_TIMEOUT); + if (rc != 0) + return rc; + } else { + pr_debug("%s: Drive does not respond to RESET line. Ignored\n", + __func__); + } + } + + /* try a soft reset */ + ata_wr_dev_ctrl(io, ATA_DEVCTL_SOFT_RESET | ATA_DEVCTL_INTR_DISABLE); + rc = ata_wait_busy(io, MAX_TIMEOUT); /* does the drive accept the command? */ + if (rc != 0) { + pr_debug("%s: Drive fails on soft reset\n", __func__); + return rc; + } + ata_wr_dev_ctrl(io, ATA_DEVCTL_INTR_DISABLE); + rc = ata_wait_ready(io, MAX_TIMEOUT); + if (rc != 0) { + pr_debug("%s: Drive fails after soft reset\n", __func__); + return rc; + } + + reg = ata_rd_status(io) & 0xf; + + if (reg == 0xf) { + pr_debug("%s: Seems no drive connected!\n", __func__); + return -ENODEV; + } + + return 0; +} + +/** + * Read a chunk of sectors from the drive + * @param blk All info about the block device we need + * @param buffer Buffer to read into + * @param block Sector's LBA number to start read from + * @param num_blocks Sector count to read + * @return 0 on success, anything else on failure + * + * This routine expects the buffer has the correct size to store all data! + * + * @note Due to 'block' is of type 'int' only small disks can be handled! + * @todo Optimize the read loop + */ +static int ata_read(struct block_device *blk, void *buffer, int block, + int num_blocks) +{ + int rc; + uint64_t sector = block; + struct ata_drive_access *drv = to_ata_drive_access(blk); + + while (num_blocks) { + rc = ata_set_lba_sector(drv->io, DISK_MASTER, sector); + if (rc != 0) + return rc; + rc = ata_wr_cmd(drv->io, ATA_CMD_RD); + if (rc != 0) + return rc; + rc = ata_wait_ready(drv->io, MAX_TIMEOUT); + if (rc != 0) + return rc; + ata_rd_sector(drv->io, buffer); + num_blocks--; + sector++; + buffer += SECTOR_SIZE; + } + + return 0; +} + +/** + * Write a chunk of sectors into the drive + * @param blk All info about the block device we need + * @param buffer Buffer to write from + * @param block Sector's number to start write to + * @param num_blocks Sector count to write + * @return 0 on success, anything else on failure + * + * This routine expects the buffer has the correct size to read all data! + * + * @note Due to 'block' is of type 'int' only small disks can be handled! + * @todo Optimize the write loop + */ +static int __maybe_unused ata_write(struct block_device *blk, + const void *buffer, int block, int num_blocks) +{ + int rc; + uint64_t sector = block; + struct ata_drive_access *drv = to_ata_drive_access(blk); + + while (num_blocks) { + rc = ata_set_lba_sector(drv->io, DISK_MASTER, sector); + if (rc != 0) + return rc; + rc = ata_wr_cmd(drv->io, ATA_CMD_WR); + if (rc != 0) + return rc; + ata_wr_sector(drv->io, buffer); + num_blocks--; + sector++; + buffer += SECTOR_SIZE; + } + + return 0; +} + +static struct block_device_ops ata_ops = { + .read = ata_read, +#ifdef CONFIG_BLOCK_WRITE + .write = ata_write, +#endif +}; + +/* until Barebox can handle 64 bit offsets */ +static int limit_disk_size(uint64_t val) +{ + if (val > (__INT_MAX__ / SECTOR_SIZE)) + return (__INT_MAX__ / SECTOR_SIZE); + return (int)val; +} + +/** + * Register an ATA drive behind an IDE like interface + * @param dev The interface device + * @param io ATA register file description + * @return 0 on success + */ +int register_ata_drive(struct device_d *dev, struct ata_ioports *io) +{ + int rc; + struct ata_drive_access *drive; + + drive = xzalloc(sizeof(struct ata_drive_access)); + + drive->io = io; + drive->blk.dev = dev; + drive->blk.ops = &ata_ops; + + rc = ata_reset(io); + if (rc) { + dev_dbg(dev, "Resetting failed\n"); + goto on_error; + } + + rc = ata_get_id(drive); + if (rc != 0) { + dev_dbg(dev, "Reading ID failed\n"); + goto on_error; + } + +#ifdef DEBUG + ata_dump_id(drive->id); +#endif + rc = cdev_find_free_index("disk"); + if (rc == -1) + pr_err("Cannot find a free index for the disk node\n"); + + drive->blk.num_blocks = limit_disk_size(ata_id_n_sectors(drive->id)); + drive->blk.cdev.name = asprintf("disk%d", rc); + drive->blk.blockbits = SECTOR_SHIFT; + + rc = blockdevice_register(&drive->blk); + if (rc != 0) { + dev_err(dev, "Failed to register blockdevice\n"); + goto on_error; + } + + /* create partitions on demand */ + rc = parse_partition_table(&drive->blk); + if (rc != 0) + dev_warn(dev, "No partition table found\n"); + + return 0; + +on_error: + free(drive); + return rc; +} + +/** + * @file + * @brief Generic ATA disk drive support + * + * Please be aware: This driver covers only a subset of the available ATA drives + * + * @todo Support for disks larger than 4 GiB + * @todo LBA48 + * @todo CHS + */ diff --git a/include/ata_drive.h b/include/ata_drive.h new file mode 100644 index 0000000000..cdd8049f0d --- /dev/null +++ b/include/ata_drive.h @@ -0,0 +1,100 @@ +/* + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef ATA_DISK_H +# define ATA_DISK + +/* IDE register file */ +#define IDE_REG_DATA 0x00 +#define IDE_REG_ERR 0x01 +#define IDE_REG_NSECT 0x02 +#define IDE_REG_LBAL 0x03 +#define IDE_REG_LBAM 0x04 +#define IDE_REG_LBAH 0x05 +#define IDE_REG_DEVICE 0x06 +#define IDE_REG_STATUS 0x07 + +#define IDE_REG_FEATURE IDE_REG_ERR /* and their aliases */ +#define IDE_REG_CMD IDE_REG_STATUS + +#define IDE_REG_ALT_STATUS 0x00 +#define IDE_REG_DEV_CTL 0x00 +#define IDE_REG_DRV_ADDR 0x01 + +/** addresses of each individual IDE drive register */ +struct ata_ioports { + void __iomem *cmd_addr; + void __iomem *data_addr; + void __iomem *error_addr; + void __iomem *feature_addr; + void __iomem *nsect_addr; + void __iomem *lbal_addr; + void __iomem *lbam_addr; + void __iomem *lbah_addr; + void __iomem *device_addr; + void __iomem *status_addr; + void __iomem *command_addr; + void __iomem *altstatus_addr; + void __iomem *ctl_addr; + void __iomem *alt_dev_addr; + + /* hard reset line handling */ + void (*reset)(int); /* true: assert reset, false: de-assert reset */ + int dataif_be; /* true if 16 bit data register is big endian */ +}; + +struct device_d; +extern int register_ata_drive(struct device_d*, struct ata_ioports*); + +/** + * @file + * @brief Register file examples of generic types of ATA devices + * + * PC IDE: + * + * Offset Read Write Note + *----------------------------------------------------------- + * 0x1f0 data data 16 bit register + * 0x1f1 error feature + * 0x1f2 sec cnt set cnt + * 0x1f3 sec no sec no + * 0x1f4 cyl low cyl low + * 0x1f5 cyl high cyl high + * 0x1f6 head head + * 0x1f7 status command + * 0x3f6 alt status dev cntrl + * 0x3f7 drv addr + * + * PCMCIA memory mapped: + * + * Offset Read Write Note + *----------------------------------------------------------- + * 0x0 data data 16 bit register + * 0x1 error feature + * 0x2 sec cnt set cnt + * 0x3 sec no sec no + * 0x4 cyl low cyl low + * 0x5 cyl high cyl high + * 0x6 head head + * 0x7 status command + * 0x8 data data 16 bit or 8 bit register (even byte) + * 0x9 data data 8 bit register (odd byte) + * 0xd error feature dup of offset 1 + * 0xe alt status dev cntrl + * 0xf drv addr + * 0x400 data data 16 bit area with 1 kiB in size + */ + +#endif /* ATA_DISK */ -- cgit v1.2.3 From 55ebf18c6603dd8d93c4a6a9d57ca390c9028c37 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Thu, 24 Nov 2011 13:43:51 +0100 Subject: Add driver for IDE like interfaces This simple driver enables a generic driver for ATA type of devices to get access to the so called 'register file' of an ATA drive. Signed-off-by: Juergen Beisert Signed-off-by: Sascha Hauer --- drivers/ata/Kconfig | 7 +++ drivers/ata/Makefile | 1 + drivers/ata/intf_platform_ide.c | 130 ++++++++++++++++++++++++++++++++++++++++ include/platform_ide.h | 32 ++++++++++ 4 files changed, 170 insertions(+) create mode 100644 drivers/ata/intf_platform_ide.c create mode 100644 include/platform_ide.h diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index f4334c2ce9..fe6f5e6f5d 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -32,4 +32,11 @@ config DISK_ATA comment "interface types" +config DISK_INTF_PLATFORM_IDE + bool "Platform IDE" + select DISK_ATA + help + Generic platform driver for simple IDE like interfaces to a connected + ATA device. + endif diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index cdbcbe7dbb..2560076d26 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_DISK_ATA) += disk_ata_drive.o # interface types +obj-$(CONFIG_DISK_INTF_PLATFORM_IDE) += intf_platform_ide.o diff --git a/drivers/ata/intf_platform_ide.c b/drivers/ata/intf_platform_ide.c new file mode 100644 index 0000000000..1955a9cb6c --- /dev/null +++ b/drivers/ata/intf_platform_ide.c @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2011 Juergen Beisert, Pengutronix + * + * Derived from the Linux kernel: Generic platform device PATA driver + * Copyright (C) 2006 - 2007 Paul Mundt + * Based on pata_pcmcia: + * Copyright 2005-2006 Red Hat Inc, all rights reserved. + * + * 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. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +/** + * Setup the register specific addresses for an ATA like divice + * @param reg_base Base address of the standard ATA like registers + * @param alt_base Base address of the alternate ATA like registers + * @param ioaddr Register file structure to setup + * @param shift Shift offset between registers + * + * Some of the registers have different names but use the same offset. This is + * due to the fact read or write access at the same offset reaches different + * registers. + */ +static void platform_ide_setup_port(void *reg_base, void *alt_base, + struct ata_ioports *ioaddr, unsigned shift) +{ + /* standard registers (0 ... 7) */ + ioaddr->cmd_addr = reg_base; + + ioaddr->data_addr = reg_base + (IDE_REG_DATA << shift); + + ioaddr->error_addr = reg_base + (IDE_REG_ERR << shift); + ioaddr->feature_addr = reg_base + (IDE_REG_FEATURE << shift); + + ioaddr->nsect_addr = reg_base + (IDE_REG_NSECT << shift); + + ioaddr->lbal_addr = reg_base + (IDE_REG_LBAL << shift); + + ioaddr->lbam_addr = reg_base + (IDE_REG_LBAM << shift); + + ioaddr->lbah_addr = reg_base + (IDE_REG_LBAH << shift); + + ioaddr->device_addr = reg_base + (IDE_REG_DEVICE << shift); + + ioaddr->status_addr = reg_base + (IDE_REG_STATUS << shift); + ioaddr->command_addr = reg_base + (IDE_REG_CMD << shift); + + ioaddr->altstatus_addr = alt_base + (IDE_REG_ALT_STATUS << shift); + ioaddr->ctl_addr = alt_base + (IDE_REG_DEV_CTL << shift); + + ioaddr->alt_dev_addr = alt_base + (IDE_REG_DRV_ADDR << shift); +} + +static int platform_ide_probe(struct device_d *dev) +{ + int rc; + struct ide_port_info *pdata = dev->platform_data; + struct ata_ioports *io; + void *reg_base, *alt_base; + + if (pdata == NULL) { + dev_err(dev, "No platform data. Cannot continue\n"); + return -EINVAL; + } + + io = xzalloc(sizeof(struct ata_ioports)); + reg_base = dev_request_mem_region(dev, 0); + alt_base = dev_request_mem_region(dev, 1); + platform_ide_setup_port(reg_base, alt_base, io, pdata->ioport_shift); + io->reset = pdata->reset; + io->dataif_be = pdata->dataif_be; + + rc = register_ata_drive(dev, io); + if (rc != 0) { + dev_err(dev, "Cannot register IDE interface\n"); + free(io); + } + + return rc; +} + +static struct driver_d platform_ide_driver = { + .name = "ide_intf", + .probe = platform_ide_probe, +}; + +static int platform_ide_init(void) +{ + return register_driver(&platform_ide_driver); +} + +device_initcall(platform_ide_init); + +/** + * @file + * @brief Interface driver for an ATA drive behind an IDE like interface + * + * This communication driver does all accesses to the drive via memory IO + * instructions. + * + * This kind of interface is also useable for regular bus like access, when + * there is no dedicated IDE available. + * + * "IDE like" means the platform data defines addresses to the register file + * of the attached ATA drive. + * + * This driver does not change any access timings due to the fact it has no idea + * how to do so. So, do not expect an impressive data throughput. + * + * @todo Support also the IO port access method, the x86 architecture is using + */ diff --git a/include/platform_ide.h b/include/platform_ide.h new file mode 100644 index 0000000000..f71fbfbc01 --- /dev/null +++ b/include/platform_ide.h @@ -0,0 +1,32 @@ +/* + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __PLATFORM_IDE_H +#define __PLATFORM_IDE_H + +struct ide_port_info { + /* + * I/O port shift, for platforms with ports that are + * constantly spaced and need larger than the 1-byte + * spacing + */ + unsigned ioport_shift; + int dataif_be; /* true if 16 bit data register is big endian */ + + /* handle hard reset of this port */ + void (*reset)(int); /* true: assert reset, false: de-assert reset */ +}; + +#endif /* __PLATFORM_IDE_H */ -- cgit v1.2.3 From 81dbc7421e1ae1a5adcc25857fc134e7cdfd5325 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 09:34:31 +0100 Subject: mmc spi: add missing dependency on SPI Signed-off-by: Sascha Hauer --- drivers/mci/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig index 00c28f1b48..897aa4da88 100644 --- a/drivers/mci/Kconfig +++ b/drivers/mci/Kconfig @@ -81,6 +81,7 @@ config MCI_ATMEL config MCI_SPI bool "MMC/SD over SPI" + depends on SPI help Some systems access MMC/SD/SDIO cards using a SPI controller instead of using a "native" MMC/SD/SDIO controller. This has a -- cgit v1.2.3 From 3db0a1e7fe77c185973267de875826aba8069244 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 09:35:18 +0100 Subject: mmc spi: compile fix Without CRC support the mmc spi driver fails to compile with the following: drivers/mci/mci_spi.c:74:18: error: static declaration of 'crc7' follows non-static declaration Signed-off-by: Sascha Hauer --- drivers/mci/mci_spi.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/mci/mci_spi.c b/drivers/mci/mci_spi.c index 124e49b9c2..653910bf7f 100644 --- a/drivers/mci/mci_spi.c +++ b/drivers/mci/mci_spi.c @@ -64,23 +64,6 @@ #define RTOUT 3000000 /* 1 sec */ #define WTOUT 3000000 /* 1 sec */ -#ifndef CONFIG_MMC_SPI_CRC_ON -/* Note that while the CRC, in general, is ignored in SPI mode, the very first - * command must be followed by a valid CRC, since the card is not yet in SPI mode. - * The CRC byte for a CMD0 command with a zero argument is a constant 0x4A. For - * simplicity, this CRC byte is always sent with every command. - */ - -static inline u8 crc7(u8 crc, const u8 *buffer, size_t len) -{ - /* This is the crc7 value for a CMD0 command with a zero argument. - * It'll be left shifted and ored with '1' in mmc_spi_command_send - * to give 0x95 (also known as the CMD0 constant CRC value...) - */ - return 0x4A; -} -#endif - struct mmc_spi_host { struct mci_host mci; struct spi_device *spi; @@ -141,6 +124,14 @@ mmc_spi_writebytes(struct mmc_spi_host *host, unsigned len, void *data) return status; } +/* + * Note that while the CRC, in general, is ignored in SPI mode, the very first + * command must be followed by a valid CRC, since the card is not yet in SPI mode. + * The CRC byte for a CMD0 command with a zero argument is a constant 0x4A. For + * simplicity, this CRC byte is always sent with every command. + */ +#define MMC_SPI_CMD0_CRC ((0x4a << 1) | 0x1) + static int mmc_spi_command_send(struct mmc_spi_host *host, struct mci_cmd *cmd) { uint8_t r1; @@ -153,7 +144,11 @@ static int mmc_spi_command_send(struct mmc_spi_host *host, struct mci_cmd *cmd) command[3] = cmd->cmdarg >> 16; command[4] = cmd->cmdarg >> 8; command[5] = cmd->cmdarg; +#ifdef CONFIG_MMC_SPI_CRC_ON command[6] = (crc7(0, &command[1], 5) << 1) | 0x01; +#else + command[6] = MMC_SPI_CMD0_CRC; +#endif mmc_spi_writebytes(host, 7, command); -- cgit v1.2.3 From 38884dabbe6a86feb5d9763cd160083f85b1848b Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 27 Nov 2011 16:32:05 +0100 Subject: remove irq support fragments We never had interrupt support in barebox and we have no plans to add interrupt support. Even if we do I doubt the current fragments of irq support are helpful, so remove them. Signed-off-by: Sascha Hauer --- arch/arm/cpu/exceptions.S | 21 --- arch/nios2/cpu/Makefile | 1 - arch/nios2/cpu/cpu.c | 3 - arch/nios2/cpu/exceptions.S | 9 - arch/nios2/cpu/interrupts.c | 140 --------------- arch/nios2/lib/board.c | 3 - arch/nios2/lib/bootm.c | 4 - arch/ppc/lib/Makefile | 1 - arch/ppc/lib/board.c | 7 - arch/ppc/lib/interrupts.c | 133 -------------- arch/ppc/mach-mpc5xxx/Makefile | 1 - arch/ppc/mach-mpc5xxx/interrupts.c | 349 ------------------------------------- arch/ppc/mach-mpc5xxx/start.S | 9 - arch/sandbox/os/common.c | 8 - commands/bootm.c | 2 - drivers/net/macb.c | 13 -- include/common.h | 19 -- 17 files changed, 723 deletions(-) delete mode 100644 arch/nios2/cpu/interrupts.c delete mode 100644 arch/ppc/lib/interrupts.c delete mode 100644 arch/ppc/mach-mpc5xxx/interrupts.c diff --git a/arch/arm/cpu/exceptions.S b/arch/arm/cpu/exceptions.S index a87975529e..6f35d408f4 100644 --- a/arch/arm/cpu/exceptions.S +++ b/arch/arm/cpu/exceptions.S @@ -140,25 +140,6 @@ data_abort: .globl irq .globl fiq -#ifdef CONFIG_USE_IRQ - - .align 5 -irq: - get_irq_stack - irq_save_user_regs - bl do_irq - irq_restore_user_regs - - .align 5 -fiq: - get_fiq_stack - /* someone ought to write a more effiction fiq_save_user_regs */ - irq_save_user_regs - bl do_fiq - irq_restore_user_regs - -#else - .align 5 irq: get_bad_stack @@ -171,5 +152,3 @@ fiq: bad_save_user_regs bl do_fiq -#endif - diff --git a/arch/nios2/cpu/Makefile b/arch/nios2/cpu/Makefile index f15c7217d1..0b59ec57c1 100644 --- a/arch/nios2/cpu/Makefile +++ b/arch/nios2/cpu/Makefile @@ -1,6 +1,5 @@ obj-y += start.o obj-y += exceptions.o obj-y += cpu.o -obj-$(CONFIG_USE_IRQ) += interrupts.o obj-y += traps.o extra-y += barebox.lds diff --git a/arch/nios2/cpu/cpu.c b/arch/nios2/cpu/cpu.c index 102b12e06f..44ddf3ccd3 100644 --- a/arch/nios2/cpu/cpu.c +++ b/arch/nios2/cpu/cpu.c @@ -26,9 +26,6 @@ void __noreturn reset_cpu(ulong ignored) { -#ifdef CONFIG_USE_IRQ - disable_interrupts(); -#endif /* indirect call to go beyond 256MB limitation of toolchain */ nios2_callr(RESET_ADDR); diff --git a/arch/nios2/cpu/exceptions.S b/arch/nios2/cpu/exceptions.S index 8e024cefa3..402e5afd29 100644 --- a/arch/nios2/cpu/exceptions.S +++ b/arch/nios2/cpu/exceptions.S @@ -82,16 +82,7 @@ _exception: rdctl et, ipending beq et, r0, 0f -#ifdef CONFIG_USE_IRQ - - /* HARDWARE INTERRUPT: Call interrupt handler */ - movhi r3, %hi(external_interrupt) - ori r3, r3, %lo(external_interrupt) - mov r4, sp /* ptr to regs */ - callr r3 -#else br _exception_return -#endif /* Return address fixup: execution resumes by re-issue of * interrupted instruction at ea-4 (ea == r29). Here we do diff --git a/arch/nios2/cpu/interrupts.c b/arch/nios2/cpu/interrupts.c deleted file mode 100644 index f443bfdec5..0000000000 --- a/arch/nios2/cpu/interrupts.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * (C) Copyright 2000-2002 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2004, Psyent Corporation - * Scott McNutt - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/****************************************************************************/ - -struct irq_action { - interrupt_handler_t *handler; - void *arg; - int count; -}; - -static struct irq_action vecs[32]; - -/****************************************************************************/ - -int disable_interrupts(void) -{ - int val = rdctl(CTL_STATUS); - wrctl(CTL_STATUS, val & ~STATUS_IE); - return val & STATUS_IE; -} - -void enable_interrupts(void) -{ - int val = rdctl(CTL_STATUS); - wrctl(CTL_STATUS, val | STATUS_IE); -} - -void external_interrupt(struct pt_regs *regs) -{ - unsigned irqs; - struct irq_action *act; - - /* Evaluate only irqs that are both enabled AND pending */ - irqs = rdctl(CTL_IENABLE) & rdctl(CTL_IPENDING); - act = vecs; - - /* Assume (as does the Nios2 HAL) that bit 0 is highest - * priority. NOTE: There is ALWAYS a handler assigned - * (the default if no other). - */ - while (irqs) { - if (irqs & 1) { - act->handler(act->arg); - act->count++; - } - irqs >>= 1; - act++; - } - -} - -static void def_hdlr(void *arg) -{ - unsigned irqs = rdctl(CTL_IENABLE); - - /* Disable the individual interrupt -- with gratuitous - * warning. - */ - irqs &= ~(1 << (int)arg); - wrctl(CTL_IENABLE, irqs); - printf("WARNING: Disabling unhandled interrupt: %d\n", - (int)arg); -} - -/*************************************************************************/ -void irq_install_handler(int irq, interrupt_handler_t *hdlr, void *arg) -{ - int flag; - struct irq_action *act; - unsigned ena = rdctl(CTL_IENABLE); - - if ((irq < 0) || (irq > 31)) - return; - act = &vecs[irq]; - - flag = disable_interrupts(); - if (hdlr) { - act->handler = hdlr; - act->arg = arg; - ena |= (1 << irq); /* enable */ - } else { - act->handler = def_hdlr; - act->arg = (void *)irq; - ena &= ~(1 << irq); /* disable */ - } - wrctl(CTL_IENABLE, ena); - - if (flag) - enable_interrupts(); -} - - -int interrupt_init(void) -{ - int i; - - /* Assign the default handler to all */ - for (i = 0; i < 32; i++) { - vecs[i].handler = def_hdlr; - vecs[i].arg = (void *)i; - vecs[i].count = 0; - } - - enable_interrupts(); - return 0; -} - diff --git a/arch/nios2/lib/board.c b/arch/nios2/lib/board.c index 07f045b3aa..d50f05adee 100644 --- a/arch/nios2/lib/board.c +++ b/arch/nios2/lib/board.c @@ -40,8 +40,5 @@ core_initcall(altera_mem_malloc_init); void arch_shutdown(void) { -#ifdef CONFIG_USE_IRQ - disable_interrupts(); -#endif } diff --git a/arch/nios2/lib/bootm.c b/arch/nios2/lib/bootm.c index 34e2bd262a..c38243f9a3 100644 --- a/arch/nios2/lib/bootm.c +++ b/arch/nios2/lib/bootm.c @@ -43,10 +43,6 @@ static int do_bootm_linux(struct image_data *idata) kernel = (void (*)(int, int, int, const char *))ntohl(os_header->ih_ep); -#ifdef CONFIG_USE_IRQ - disable_interrupts(); -#endif - if (relocate_image(idata->os, (void *)ntohl(os_header->ih_load))) return -1; diff --git a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile index c35fd08d49..b611ddf7ea 100644 --- a/arch/ppc/lib/Makefile +++ b/arch/ppc/lib/Makefile @@ -1,7 +1,6 @@ obj-y += bat_rw.o obj-y += board.o obj-y += extable.o -obj-$(CONFIG_USE_IRQ) += interrupts.o obj-y += kgdb.o obj-y += ppcstring.o obj-y += ticks.o diff --git a/arch/ppc/lib/board.c b/arch/ppc/lib/board.c index 82ba458fcc..0b610a5c95 100644 --- a/arch/ppc/lib/board.c +++ b/arch/ppc/lib/board.c @@ -63,13 +63,6 @@ void board_init_r (ulong end_of_ram) */ trap_init (0); - /* - * Enable Interrupts - */ -#ifdef CONFIG_USE_IRQ - interrupt_init (); -#endif - /* Initialization complete - start the monitor */ start_barebox(); diff --git a/arch/ppc/lib/interrupts.c b/arch/ppc/lib/interrupts.c deleted file mode 100644 index 72ddf36459..0000000000 --- a/arch/ppc/lib/interrupts.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * (C) Copyright 2000-2002 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2003 - * Gleb Natapov - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#ifdef CONFIG_STATUS_LED -#include -#endif - -#ifdef CONFIG_SHOW_ACTIVITY - extern void board_show_activity (ulong); -#endif /* CONFIG_SHOW_ACTIVITY */ - -#ifndef CFG_WATCHDOG_FREQ -#define CFG_WATCHDOG_FREQ (CFG_HZ / 2) -#endif - -extern int interrupt_init_cpu (unsigned *); -extern void timer_interrupt_cpu (struct pt_regs *); - -static unsigned decrementer_count; /* count value for 1e6/HZ microseconds */ - -static __inline__ unsigned long get_msr (void) -{ - unsigned long msr; - - asm volatile ("mfmsr %0":"=r" (msr):); - - return msr; -} - -static __inline__ void set_msr (unsigned long msr) -{ - asm volatile ("mtmsr %0"::"r" (msr)); -} - -static __inline__ unsigned long get_dec (void) -{ - unsigned long val; - - asm volatile ("mfdec %0":"=r" (val):); - - return val; -} - - -static __inline__ void set_dec (unsigned long val) -{ - if (val) - asm volatile ("mtdec %0"::"r" (val)); -} - - -void enable_interrupts (void) -{ - set_msr (get_msr () | MSR_EE); -} - -/* returns flag if MSR_EE was set before */ -int disable_interrupts (void) -{ - ulong msr = get_msr (); - - set_msr (msr & ~MSR_EE); - return ((msr & MSR_EE) != 0); -} - -int interrupt_init (void) -{ - int ret; - - /* call cpu specific function from $(CPU)/interrupts.c */ - ret = interrupt_init_cpu (&decrementer_count); - - if (ret) - return ret; - - set_dec (decrementer_count); - - set_msr (get_msr () | MSR_EE); - - return (0); -} - -static volatile ulong timestamp = 0; - -void timer_interrupt (struct pt_regs *regs) -{ - /* call cpu specific function from $(CPU)/interrupts.c */ - timer_interrupt_cpu (regs); - - /* Restore Decrementer Count */ - set_dec (decrementer_count); - - timestamp++; - -#if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG) - if ((timestamp % (CFG_WATCHDOG_FREQ)) == 0) - WATCHDOG_RESET (); -#endif /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */ - -#ifdef CONFIG_STATUS_LED - status_led_tick (timestamp); -#endif /* CONFIG_STATUS_LED */ - -#ifdef CONFIG_SHOW_ACTIVITY - board_show_activity (timestamp); -#endif /* CONFIG_SHOW_ACTIVITY */ -} diff --git a/arch/ppc/mach-mpc5xxx/Makefile b/arch/ppc/mach-mpc5xxx/Makefile index e07062cb29..be68c995c5 100644 --- a/arch/ppc/mach-mpc5xxx/Makefile +++ b/arch/ppc/mach-mpc5xxx/Makefile @@ -5,7 +5,6 @@ obj-y += speed.o obj-y += traps.o extra-y += start.o obj-$(CONFIG_MPC5200) += firmware_sc_task_bestcomm.impl.o -obj-$(CONFIG_USE_IRQ) += interrupts.o obj-$(CONFIG_REGINFO) += reginfo.o #obj-y += firmware_sc_task.impl.o diff --git a/arch/ppc/mach-mpc5xxx/interrupts.c b/arch/ppc/mach-mpc5xxx/interrupts.c deleted file mode 100644 index 4838bc5f70..0000000000 --- a/arch/ppc/mach-mpc5xxx/interrupts.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - * (C) Copyright 2006 - * Detlev Zundel, DENX Software Engineering, dzu@denx.de - * - * (C) Copyright -2003 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2001 - * Josh Huber , Mission Critical Linux, Inc. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -/* this section was ripped out of arch/ppc/syslib/mpc52xx_pic.c in the - * Linux 2.6 source with the following copyright. - * - * Based on (well, mostly copied from) the code from the 2.4 kernel by - * Dale Farnsworth and Kent Borg. - * - * Copyright (C) 2004 Sylvain Munaut - * Copyright (C) 2003 Montavista Software, Inc - */ - -#include -#include -#include -#include -#include -#include -#include - -struct irq_action { - interrupt_handler_t *handler; - void *arg; - ulong count; -}; - -static struct irq_action irq_handlers[NR_IRQS]; - -static struct mpc5xxx_intr *intr; -static struct mpc5xxx_sdma *sdma; - -static void mpc5xxx_ic_disable(unsigned int irq) -{ - u32 val; - - if (irq == MPC5XXX_IRQ0) { - val = in_be32(&intr->ctrl); - val &= ~(1 << 11); - out_be32(&intr->ctrl, val); - } else if (irq < MPC5XXX_IRQ1) { - BUG(); - } else if (irq <= MPC5XXX_IRQ3) { - val = in_be32(&intr->ctrl); - val &= ~(1 << (10 - (irq - MPC5XXX_IRQ1))); - out_be32(&intr->ctrl, val); - } else if (irq < MPC5XXX_SDMA_IRQ_BASE) { - val = in_be32(&intr->main_mask); - val |= 1 << (16 - (irq - MPC5XXX_MAIN_IRQ_BASE)); - out_be32(&intr->main_mask, val); - } else if (irq < MPC5XXX_PERP_IRQ_BASE) { - val = in_be32(&sdma->IntMask); - val |= 1 << (irq - MPC5XXX_SDMA_IRQ_BASE); - out_be32(&sdma->IntMask, val); - } else { - val = in_be32(&intr->per_mask); - val |= 1 << (31 - (irq - MPC5XXX_PERP_IRQ_BASE)); - out_be32(&intr->per_mask, val); - } -} - -static void mpc5xxx_ic_enable(unsigned int irq) -{ - u32 val; - - if (irq == MPC5XXX_IRQ0) { - val = in_be32(&intr->ctrl); - val |= 1 << 11; - out_be32(&intr->ctrl, val); - } else if (irq < MPC5XXX_IRQ1) { - BUG(); - } else if (irq <= MPC5XXX_IRQ3) { - val = in_be32(&intr->ctrl); - val |= 1 << (10 - (irq - MPC5XXX_IRQ1)); - out_be32(&intr->ctrl, val); - } else if (irq < MPC5XXX_SDMA_IRQ_BASE) { - val = in_be32(&intr->main_mask); - val &= ~(1 << (16 - (irq - MPC5XXX_MAIN_IRQ_BASE))); - out_be32(&intr->main_mask, val); - } else if (irq < MPC5XXX_PERP_IRQ_BASE) { - val = in_be32(&sdma->IntMask); - val &= ~(1 << (irq - MPC5XXX_SDMA_IRQ_BASE)); - out_be32(&sdma->IntMask, val); - } else { - val = in_be32(&intr->per_mask); - val &= ~(1 << (31 - (irq - MPC5XXX_PERP_IRQ_BASE))); - out_be32(&intr->per_mask, val); - } -} - -static void mpc5xxx_ic_ack(unsigned int irq) -{ - u32 val; - - /* - * Only some irqs are reset here, others in interrupting hardware. - */ - - switch (irq) { - case MPC5XXX_IRQ0: - val = in_be32(&intr->ctrl); - val |= 0x08000000; - out_be32(&intr->ctrl, val); - break; - case MPC5XXX_CCS_IRQ: - val = in_be32(&intr->enc_status); - val |= 0x00000400; - out_be32(&intr->enc_status, val); - break; - case MPC5XXX_IRQ1: - val = in_be32(&intr->ctrl); - val |= 0x04000000; - out_be32(&intr->ctrl, val); - break; - case MPC5XXX_IRQ2: - val = in_be32(&intr->ctrl); - val |= 0x02000000; - out_be32(&intr->ctrl, val); - break; - case MPC5XXX_IRQ3: - val = in_be32(&intr->ctrl); - val |= 0x01000000; - out_be32(&intr->ctrl, val); - break; - default: - if (irq >= MPC5XXX_SDMA_IRQ_BASE - && irq < (MPC5XXX_SDMA_IRQ_BASE + MPC5XXX_SDMA_IRQ_NUM)) { - out_be32(&sdma->IntPend, - 1 << (irq - MPC5XXX_SDMA_IRQ_BASE)); - } - break; - } -} - -static void mpc5xxx_ic_disable_and_ack(unsigned int irq) -{ - mpc5xxx_ic_disable(irq); - mpc5xxx_ic_ack(irq); -} - -static void mpc5xxx_ic_end(unsigned int irq) -{ - mpc5xxx_ic_enable(irq); -} - -void mpc5xxx_init_irq(void) -{ - u32 intr_ctrl; - - /* Remap the necessary zones */ - intr = (struct mpc5xxx_intr *)(MPC5XXX_ICTL); - sdma = (struct mpc5xxx_sdma *)(MPC5XXX_SDMA); - - /* Disable all interrupt sources. */ - out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */ - out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */ - out_be32(&intr->per_mask, 0x7ffffc00); /* 1 means disabled */ - out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */ - intr_ctrl = in_be32(&intr->ctrl); - intr_ctrl |= 0x0f000000 | /* clear IRQ 0-3 */ - 0x00ff0000 | /* IRQ 0-3 level sensitive low active */ - 0x00001000 | /* MEE master external enable */ - 0x00000000 | /* 0 means disable IRQ 0-3 */ - 0x00000001; /* CEb route critical normally */ - out_be32(&intr->ctrl, intr_ctrl); - - /* Zero a bunch of the priority settings. */ - out_be32(&intr->per_pri1, 0); - out_be32(&intr->per_pri2, 0); - out_be32(&intr->per_pri3, 0); - out_be32(&intr->main_pri1, 0); - out_be32(&intr->main_pri2, 0); -} - -int mpc5xxx_get_irq(struct pt_regs *regs) -{ - u32 status; - int irq = -1; - - status = in_be32(&intr->enc_status); - - if (status & 0x00000400) { /* critical */ - irq = (status >> 8) & 0x3; - if (irq == 2) /* high priority peripheral */ - goto peripheral; - irq += MPC5XXX_CRIT_IRQ_BASE; - } else if (status & 0x00200000) { /* main */ - irq = (status >> 16) & 0x1f; - if (irq == 4) /* low priority peripheral */ - goto peripheral; - irq += MPC5XXX_MAIN_IRQ_BASE; - } else if (status & 0x20000000) { /* peripheral */ - peripheral: - irq = (status >> 24) & 0x1f; - if (irq == 0) { /* bestcomm */ - status = in_be32(&sdma->IntPend); - irq = ffs(status) + MPC5XXX_SDMA_IRQ_BASE - 1; - } else - irq += MPC5XXX_PERP_IRQ_BASE; - } - - return irq; -} - -/****************************************************************************/ - -int interrupt_init_cpu(ulong * decrementer_count) -{ - *decrementer_count = get_timebase_clock() / 1000; - - mpc5xxx_init_irq(); - - return 0; -} - -/****************************************************************************/ - -/* - * Handle external interrupts - */ -void external_interrupt(struct pt_regs *regs) -{ - int irq, unmask = 1; - - irq = mpc5xxx_get_irq(regs); - - mpc5xxx_ic_disable_and_ack(irq); - - enable_interrupts(); - - if (irq_handlers[irq].handler != NULL) - (*irq_handlers[irq].handler) (irq_handlers[irq].arg); - else { - printf("\nBogus External Interrupt IRQ %d\n", irq); - /* - * turn off the bogus interrupt, otherwise it - * might repeat forever - */ - unmask = 0; - } - - if (unmask) - mpc5xxx_ic_end(irq); -} - -void timer_interrupt_cpu(struct pt_regs *regs) -{ - /* nothing to do here */ - return; -} - -/****************************************************************************/ - -/* - * Install and free a interrupt handler. - */ - -void irq_install_handler(int irq, interrupt_handler_t * handler, void *arg) -{ - if (irq < 0 || irq >= NR_IRQS) { - printf("irq_install_handler: bad irq number %d\n", irq); - return; - } - - if (irq_handlers[irq].handler != NULL) - printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n", - (ulong) handler, (ulong) irq_handlers[irq].handler); - - irq_handlers[irq].handler = handler; - irq_handlers[irq].arg = arg; - - mpc5xxx_ic_enable(irq); -} - -void irq_free_handler(int irq) -{ - if (irq < 0 || irq >= NR_IRQS) { - printf("irq_free_handler: bad irq number %d\n", irq); - return; - } - - mpc5xxx_ic_disable(irq); - - irq_handlers[irq].handler = NULL; - irq_handlers[irq].arg = NULL; -} - -/****************************************************************************/ - -#if (CONFIG_COMMANDS & CFG_CMD_IRQ) -void do_irqinfo(struct command * cmdtp, bd_t * bd, int flag, int argc, char *argv[]) -{ - int irq, re_enable; - u32 intr_ctrl; - char *irq_config[] = { "level sensitive, active high", - "edge sensitive, rising active edge", - "edge sensitive, falling active edge", - "level sensitive, active low" - }; - - re_enable = disable_interrupts(); - - intr_ctrl = in_be32(&intr->ctrl); - printf("Interrupt configuration:\n"); - - for (irq = 0; irq <= 3; irq++) { - printf("IRQ%d: %s\n", irq, - irq_config[(intr_ctrl >> (22 - 2 * irq)) & 0x3]); - } - - puts("\nInterrupt-Information:\n" "Nr Routine Arg Count\n"); - - for (irq = 0; irq < NR_IRQS; irq++) - if (irq_handlers[irq].handler != NULL) - printf("%02d %08lx %08lx %ld\n", irq, - (ulong) irq_handlers[irq].handler, - (ulong) irq_handlers[irq].arg, - irq_handlers[irq].count); - - if (re_enable) - enable_interrupts(); -} -#endif diff --git a/arch/ppc/mach-mpc5xxx/start.S b/arch/ppc/mach-mpc5xxx/start.S index dc53c8a226..7a4c16bb87 100644 --- a/arch/ppc/mach-mpc5xxx/start.S +++ b/arch/ppc/mach-mpc5xxx/start.S @@ -140,11 +140,6 @@ _start_of_vectors: /* Instruction Storage exception. */ STD_EXCEPTION(0x400, InstStorage, UnknownException) -/* External Interrupt exception. */ -#ifdef CONFIG_USE_IRQ - STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt) -#endif - /* Alignment exception. */ . = 0x600 Alignment: @@ -184,11 +179,7 @@ ProgramCheck: /* I guess we could implement decrementer, and may have * to someday for timekeeping. */ -#ifdef CONFIG_USE_IRQ - STD_EXCEPTION(0x900, Decrementer, timer_interrupt) -#else STD_EXCEPTION(0x900, Decrementer, UnknownException) -#endif STD_EXCEPTION(0xa00, Trap_0a, UnknownException) STD_EXCEPTION(0xb00, Trap_0b, UnknownException) STD_EXCEPTION(0xc00, SystemCall, UnknownException) diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c index 5074a06c80..1c5ae5d34b 100644 --- a/arch/sandbox/os/common.c +++ b/arch/sandbox/os/common.c @@ -124,14 +124,6 @@ void __attribute__((noreturn)) reset_cpu(unsigned long addr) exit(0); } -void enable_interrupts(void) -{ -} - -void disable_interrupt(void) -{ -} - int linux_read(int fd, void *buf, size_t count) { ssize_t ret; diff --git a/commands/bootm.c b/commands/bootm.c index f11138afba..731b74dcee 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -331,8 +331,6 @@ static int do_bootm(struct command *cmdtp, int argc, char *argv[]) * recover from any failures any more... */ - disable_interrupts(); - puts ("OK\n"); /* loop through the registered handlers */ diff --git a/drivers/net/macb.c b/drivers/net/macb.c index c1f7f68484..e1cfd85d68 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -302,18 +302,14 @@ static int macb_phy_read(struct mii_device *mdev, int addr, int reg) unsigned long netctl; unsigned long netstat; unsigned long frame; - int iflag; int value; uint64_t start; debug("%s\n", __func__); - iflag = disable_interrupts(); netctl = readl(macb->regs + MACB_NCR); netctl |= MACB_BIT(MPE); writel(netctl, macb->regs + MACB_NCR); - if (iflag) - enable_interrupts(); frame = (MACB_BF(SOF, 1) | MACB_BF(RW, 2) @@ -334,12 +330,9 @@ static int macb_phy_read(struct mii_device *mdev, int addr, int reg) frame = readl(macb->regs + MACB_MAN); value = MACB_BFEXT(DATA, frame); - iflag = disable_interrupts(); netctl = readl(macb->regs + MACB_NCR); netctl &= ~MACB_BIT(MPE); writel(netctl, macb->regs + MACB_NCR); - if (iflag) - enable_interrupts(); return value; } @@ -355,12 +348,9 @@ static int macb_phy_write(struct mii_device *mdev, int addr, int reg, int value) debug("%s\n", __func__); - iflag = disable_interrupts(); netctl = readl(macb->regs + MACB_NCR); netctl |= MACB_BIT(MPE); writel(netctl, macb->regs + MACB_NCR); - if (iflag) - enable_interrupts(); frame = (MACB_BF(SOF, 1) | MACB_BF(RW, 1) @@ -374,12 +364,9 @@ static int macb_phy_write(struct mii_device *mdev, int addr, int reg, int value) netstat = readl(macb->regs + MACB_NSR); } while (!(netstat & MACB_BIT(IDLE))); - iflag = disable_interrupts(); netctl = readl(macb->regs + MACB_NCR); netctl &= ~MACB_BIT(MPE); writel(netctl, macb->regs + MACB_NCR); - if (iflag) - enable_interrupts(); return 0; } diff --git a/include/common.h b/include/common.h index e34bbea82f..d63ad023ba 100644 --- a/include/common.h +++ b/include/common.h @@ -107,25 +107,6 @@ long get_ram_size (volatile long *, long); /* $(CPU)/cpu.c */ void __noreturn reset_cpu(unsigned long addr); -/* $(CPU)/interrupts.c */ -//void timer_interrupt (struct pt_regs *); -//void external_interrupt (struct pt_regs *); -void irq_install_handler(int, interrupt_handler_t *, void *); -void irq_free_handler (int); -#ifdef CONFIG_USE_IRQ -void enable_interrupts (void); -int disable_interrupts (void); -#else -static inline void enable_interrupts(void) -{ -} - -static inline int disable_interrupts(void) -{ - return 0; -} -#endif - /* lib_$(ARCH)/time.c */ void udelay (unsigned long); void mdelay (unsigned long); -- cgit v1.2.3 From ad9ef4c148744fca79581fc705d06ff654de975b Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 27 Nov 2011 11:49:16 +0100 Subject: MAKEALL: use '.' instead of 'source' 'source' is not available on dash. Signed-off-by: Sascha Hauer --- MAKEALL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAKEALL b/MAKEALL index e987de2b3f..25b99774db 100755 --- a/MAKEALL +++ b/MAKEALL @@ -234,7 +234,7 @@ then CONFIG="./${CONFIG}" fi - source "${CONFIG}" + . "${CONFIG}" fi [ -d "${LOGDIR}" ] || mkdir ${LOGDIR} || exit 1 -- cgit v1.2.3 From 020a30be0d9a3b56a98c4e4094d13d3b4e3bd4eb Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sat, 26 Nov 2011 21:33:59 +0100 Subject: add magicvar command The magicvar command gives an overview about all environment variables with a special meaning. Signed-off-by: Sascha Hauer --- arch/arm/lib/barebox.lds.S | 4 ++++ arch/blackfin/boards/ipe337/barebox.lds.S | 4 ++++ arch/mips/lib/barebox.lds.S | 4 ++++ arch/nios2/cpu/barebox.lds.S | 4 ++++ arch/ppc/boards/pcm030/barebox.lds.S | 4 ++++ arch/sandbox/board/barebox.lds.S | 5 +++++ arch/x86/lib/barebox.lds.S | 9 ++++++++- commands/Kconfig | 14 ++++++++++++++ commands/Makefile | 1 + commands/magicvar.c | 20 +++++++++++++++++++ include/asm-generic/barebox.lds.h | 2 ++ include/magicvar.h | 32 +++++++++++++++++++++++++++++++ 12 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 commands/magicvar.c create mode 100644 include/magicvar.h diff --git a/arch/arm/lib/barebox.lds.S b/arch/arm/lib/barebox.lds.S index 81a91236c0..f05f34523c 100644 --- a/arch/arm/lib/barebox.lds.S +++ b/arch/arm/lib/barebox.lds.S @@ -80,6 +80,10 @@ SECTIONS .barebox_cmd : { BAREBOX_CMDS } __barebox_cmd_end = .; + __barebox_magicvar_start = .; + .barebox_magicvar : { BAREBOX_MAGICVARS } + __barebox_magicvar_end = .; + __barebox_initcalls_start = .; .barebox_initcalls : { INITCALLS } __barebox_initcalls_end = .; diff --git a/arch/blackfin/boards/ipe337/barebox.lds.S b/arch/blackfin/boards/ipe337/barebox.lds.S index 571eeb113b..25ca988815 100644 --- a/arch/blackfin/boards/ipe337/barebox.lds.S +++ b/arch/blackfin/boards/ipe337/barebox.lds.S @@ -71,6 +71,10 @@ SECTIONS .barebox_cmd : { BAREBOX_CMDS } ___barebox_cmd_end = .; + __barebox_magicvar_start = .; + .barebox_magicvar : { BAREBOX_MAGICVARS } + __barebox_magicvar_end = .; + ___barebox_initcalls_start = .; .barebox_initcalls : { INITCALLS } ___barebox_initcalls_end = .; diff --git a/arch/mips/lib/barebox.lds.S b/arch/mips/lib/barebox.lds.S index ba4c0afc11..7746ea0c71 100644 --- a/arch/mips/lib/barebox.lds.S +++ b/arch/mips/lib/barebox.lds.S @@ -56,6 +56,10 @@ SECTIONS .barebox_cmd : { BAREBOX_CMDS } __barebox_cmd_end = .; + __barebox_magicvar_start = .; + .barebox_magicvar : { BAREBOX_MAGICVARS } + __barebox_magicvar_end = .; + __barebox_initcalls_start = .; .barebox_initcalls : { INITCALLS } __barebox_initcalls_end = .; diff --git a/arch/nios2/cpu/barebox.lds.S b/arch/nios2/cpu/barebox.lds.S index 2b626fb51e..934eaf7cac 100644 --- a/arch/nios2/cpu/barebox.lds.S +++ b/arch/nios2/cpu/barebox.lds.S @@ -56,6 +56,10 @@ SECTIONS .barebox_cmd : { BAREBOX_CMDS } __barebox_cmd_end = .; + __barebox_magicvar_start = .; + .barebox_magicvar : { BAREBOX_MAGICVARS } + __barebox_magicvar_end = .; + __barebox_initcalls_start = .; .barebox_initcalls : { INITCALLS } __barebox_initcalls_end = .; diff --git a/arch/ppc/boards/pcm030/barebox.lds.S b/arch/ppc/boards/pcm030/barebox.lds.S index 4aacfc5f12..7dda039dbb 100644 --- a/arch/ppc/boards/pcm030/barebox.lds.S +++ b/arch/ppc/boards/pcm030/barebox.lds.S @@ -102,6 +102,10 @@ SECTIONS .barebox_cmd : { BAREBOX_CMDS } __barebox_cmd_end = .; + __barebox_magicvar_start = .; + .barebox_magicvar : { BAREBOX_MAGICVARS } + __barebox_magicvar_end = .; + __barebox_initcalls_start = .; .barebox_initcalls : { INITCALLS } __barebox_initcalls_end = .; diff --git a/arch/sandbox/board/barebox.lds.S b/arch/sandbox/board/barebox.lds.S index 76975eea63..db5b7deb23 100644 --- a/arch/sandbox/board/barebox.lds.S +++ b/arch/sandbox/board/barebox.lds.S @@ -7,6 +7,11 @@ SECTIONS __barebox_initcalls : { INITCALLS } __barebox_initcalls_end = .; + . = ALIGN(64); + __barebox_magicvar_start = .; + .barebox_magicvar : { BAREBOX_MAGICVARS } + __barebox_magicvar_end = .; + . = ALIGN(64); __barebox_cmd_start = .; __barebox_cmd : { BAREBOX_CMDS } diff --git a/arch/x86/lib/barebox.lds.S b/arch/x86/lib/barebox.lds.S index fffc3a55c6..716cea6a68 100644 --- a/arch/x86/lib/barebox.lds.S +++ b/arch/x86/lib/barebox.lds.S @@ -170,7 +170,14 @@ SECTIONS . = ALIGN(4); } > barebox - .barebox_initcalls : AT ( LOADADDR(.barebox_cmd) + SIZEOF (.barebox_cmd) ) { + .barebox_magicvars : AT ( LOADADDR(.barebox_cmd) + SIZEOF (.barebox_cmd) ) { + __barebox_magicvar_start = .; + .barebox_magicvar : { BAREBOX_MAGICVARS } + __barebox_magicvar_end = .; + . = ALIGN(4); + } > barebox + + .barebox_initcalls : AT ( LOADADDR(.barebox_magicvars) + SIZEOF (.barebox_magicvars) ) { __barebox_initcalls_start = .; INITCALLS __barebox_initcalls_end = .; diff --git a/commands/Kconfig b/commands/Kconfig index 18ab840916..78b9d2a0e6 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -383,6 +383,20 @@ config CMD_HELP default y prompt "help" +config CMD_MAGICVAR + tristate + prompt "magicvar" + help + barebox has some shell variables with special meanings. This + command shows the available magic variables. + +config CMD_MAGICVAR_HELP + bool + prompt "display description" + depends on CMD_MAGICVAR + help + Also display a description to the magic variables + config CMD_DEVINFO tristate default y diff --git a/commands/Makefile b/commands/Makefile index 5c519169c3..9b3a349bd2 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -58,3 +58,4 @@ obj-$(CONFIG_CMD_LED_TRIGGER) += trigger.o obj-$(CONFIG_CMD_USB) += usb.o obj-$(CONFIG_CMD_TIME) += time.o obj-$(CONFIG_CMD_OFTREE) += oftree.o +obj-$(CONFIG_CMD_MAGICVAR) += magicvar.o diff --git a/commands/magicvar.c b/commands/magicvar.c new file mode 100644 index 0000000000..31606d2afa --- /dev/null +++ b/commands/magicvar.c @@ -0,0 +1,20 @@ +#include +#include +#include + +static int do_magicvar(struct command *cmdtp, int argc, char *argv[]) +{ + struct magicvar *m; + + for (m = &__barebox_magicvar_start; + m != &__barebox_magicvar_end; + m++) + printf("%-32s %s\n", m->name, m->description); + + return 0; +} + +BAREBOX_CMD_START(magicvar) + .cmd = do_magicvar, + .usage = "List information about magic variables", +BAREBOX_CMD_END diff --git a/include/asm-generic/barebox.lds.h b/include/asm-generic/barebox.lds.h index 8aee5d2ce4..5467d3a8a0 100644 --- a/include/asm-generic/barebox.lds.h +++ b/include/asm-generic/barebox.lds.h @@ -24,3 +24,5 @@ #define BAREBOX_CMDS KEEP(*(SORT_BY_NAME(.barebox_cmd*))) #define BAREBOX_SYMS KEEP(*(__usymtab)) + +#define BAREBOX_MAGICVARS KEEP(*(SORT_BY_NAME(.barebox_magicvar*))) diff --git a/include/magicvar.h b/include/magicvar.h new file mode 100644 index 0000000000..d27a2e32a3 --- /dev/null +++ b/include/magicvar.h @@ -0,0 +1,32 @@ +#ifndef __MAGIC_VARS_H +#define __MAGIC_VARS_H + +#include + +struct magicvar { + const char *name; + const char *description; +}; + +extern struct magicvar __barebox_magicvar_start; +extern struct magicvar __barebox_magicvar_end; + +#ifdef CONFIG_CMD_MAGICVAR_HELP +#define MAGICVAR_DESCRIPTION(d) (d) +#else +#define MAGICVAR_DESCRIPTION(d) NULL +#endif + +#ifdef CONFIG_CMD_MAGICVAR +#define BAREBOX_MAGICVAR(_name, _description) \ +extern const struct magicvar __barebox_magicvar_##_name; \ +const struct magicvar __barebox_magicvar_##_name \ + __attribute__ ((unused,section (".barebox_magicvar_" __stringify(_name)))) = { \ + .name = #_name, \ + .description = MAGICVAR_DESCRIPTION(_description), \ +}; +#else +#define BAREBOX_MAGICVAR(_name, _description) +#endif + +#endif /* __MAGIC_VARS_H */ -- cgit v1.2.3 From f84fb129c703a682e37ba05f1ba2ea2b567a14d8 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 27 Nov 2011 13:02:48 +0100 Subject: bootm: Add bootargs magicvar Signed-off-by: Sascha Hauer --- commands/bootm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/commands/bootm.c b/commands/bootm.c index f11138afba..ada790ee97 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -42,6 +42,7 @@ #include #include #include +#include #include /* @@ -367,6 +368,8 @@ BAREBOX_CMD_START(bootm) BAREBOX_CMD_HELP(cmd_bootm_help) BAREBOX_CMD_END +BAREBOX_MAGICVAR(bootargs, "Linux Kernel parameters"); + /** * @page bootm_command -- cgit v1.2.3 From 51845b0ce0b42e6e08114751888a8e800d5cf637 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 27 Nov 2011 13:00:29 +0100 Subject: ARM i.MX boot: Add barebox_loc magicvar Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/boot.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c index f13d956bf1..8b82655d4f 100644 --- a/arch/arm/mach-imx/boot.c +++ b/arch/arm/mach-imx/boot.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -88,4 +89,6 @@ static int imx_25_35_boot_save_loc(void) coredevice_initcall(imx_25_35_boot_save_loc); +BAREBOX_MAGICVAR(barebox_loc, "The source barebox has been booted from"); + #endif -- cgit v1.2.3 From 76dca8279e820d3d6c254d2a8dcdd788f0d4c6e1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 27 Nov 2011 13:00:47 +0100 Subject: hush: Add magicvars Signed-off-by: Sascha Hauer --- common/hush.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/common/hush.c b/common/hush.c index 573bd3ef1d..b59e59dd17 100644 --- a/common/hush.c +++ b/common/hush.c @@ -122,6 +122,7 @@ #include #include #include +#include #include /*cmd_boot.c*/ @@ -540,6 +541,8 @@ static int builtin_getopt(struct p_context *ctx, struct child_prog *child) return 0; } + +BAREBOX_MAGICVAR(OPTARG, "optarg for hush builtin getopt"); #endif /* run_pipe_real() starts all the jobs, but doesn't wait for anything @@ -1721,6 +1724,11 @@ BAREBOX_CMD_START(getopt) BAREBOX_CMD_END #endif +BAREBOX_MAGICVAR(PATH, "colon seperated list of pathes to search for executables"); +#ifdef CONFIG_HUSH_FANCY_PROMPT +BAREBOX_MAGICVAR(PS1, "hush prompt"); +#endif + /** * @file * @brief A prototype Bourne shell grammar parser -- cgit v1.2.3 From 7766c288ff6e6defd7565af73a3407c3c414eb94 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 27 Nov 2011 13:01:00 +0100 Subject: dhcp: Add magicvars Signed-off-by: Sascha Hauer --- net/dhcp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/dhcp.c b/net/dhcp.c index d1781bc6b0..2ce9090639 100644 --- a/net/dhcp.c +++ b/net/dhcp.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #define OPT_SIZE 312 /* Minimum DHCP Options size per RFC2131 - results in 576 byte pkt */ @@ -482,3 +483,8 @@ BAREBOX_CMD_START(dhcp) .usage = "invoke dhcp client to obtain ip/boot params", BAREBOX_CMD_END +BAREBOX_MAGICVAR(bootfile, "bootfile returned from DHCP request"); +BAREBOX_MAGICVAR(nameserver, "Nameserver returned from DHCP request"); +BAREBOX_MAGICVAR(hostname, "hostname returned from DHCP request"); +BAREBOX_MAGICVAR(domainname, "domainname returned from DHCP request"); +BAREBOX_MAGICVAR(rootpath, "rootpath returned from DHCP request"); -- cgit v1.2.3 From 88611e7448842749ccdd7193f4e0fc4d0a2bbe6c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 25 Nov 2011 19:12:54 +0100 Subject: bootm: remove dead code Signed-off-by: Sascha Hauer --- commands/bootm.c | 47 ----------------------------------------------- 1 file changed, 47 deletions(-) diff --git a/commands/bootm.c b/commands/bootm.c index a4d1c367f0..d0bb35062a 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -45,57 +45,10 @@ #include #include -/* - * Continue booting an OS image; caller already has: - * - copied image header to global variable `header' - * - checked header magic number, checksums (both header & image), - * - verified image architecture (PPC) and type (KERNEL or MULTI), - * - loaded (first part of) image to header load address, - * - disabled interrupts. - */ -typedef void boot_os_Fcn(struct command *cmdtp, int flag, - int argc, char *argv[], - ulong addr, /* of image to boot */ - ulong *len_ptr, /* multi-file image length table */ - int verify); /* getenv("verify")[0] != 'n' */ - #ifndef CFG_BOOTM_LEN #define CFG_BOOTM_LEN 0x800000 /* use 8MByte as default max gunzip size */ #endif -#ifdef CONFIG_SILENT_CONSOLE -static void -fixup_silent_linux () -{ - char buf[256], *start, *end; - char *cmdline = getenv ("bootargs"); - - /* Only fix cmdline when requested */ - if (!(gd->flags & GD_FLG_SILENT)) - return; - - debug ("before silent fix-up: %s\n", cmdline); - if (cmdline) { - if ((start = strstr (cmdline, "console=")) != NULL) { - end = strchr (start, ' '); - strncpy (buf, cmdline, (start - cmdline + 8)); - if (end) - strcpy (buf + (start - cmdline + 8), end); - else - buf[start - cmdline + 8] = '\0'; - } else { - strcpy (buf, cmdline); - strcat (buf, " console="); - } - } else { - strcpy (buf, "console="); - } - - setenv ("bootargs", buf); - debug ("after silent fix-up: %s\n", buf); -} -#endif /* CONFIG_SILENT_CONSOLE */ - struct image_handle_data* image_handle_data_get_by_num(struct image_handle* handle, int num) { if (!handle || num < 0 || num >= handle->nb_data_entries) -- cgit v1.2.3 From ac4854be5e67b4d19884fb4462982d91ca9bc815 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 25 Nov 2011 19:09:07 +0100 Subject: factor out iminfo command The rests of U-Boots iminfo command are sitting in commands/bootm.c and are in a nonusable state. Factor it out to its own file and make it work again. Signed-off-by: Sascha Hauer --- commands/Kconfig | 6 +++++ commands/Makefile | 1 + commands/bootm.c | 79 ------------------------------------------------------- commands/iminfo.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ common/image.c | 2 +- include/image.h | 3 --- 6 files changed, 79 insertions(+), 83 deletions(-) create mode 100644 commands/iminfo.c diff --git a/commands/Kconfig b/commands/Kconfig index 78b9d2a0e6..93f14b278e 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -309,6 +309,12 @@ config CMD_BOOTM_SHOW_TYPE depends on CMD_BOOTM prompt "show image information" +config CMD_IMINFO + bool + prompt "iminfo" + help + Show information about uImages + config CMD_BOOTZ tristate default y diff --git a/commands/Makefile b/commands/Makefile index 9b3a349bd2..45f9ccfd56 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-$(CONFIG_CMD_IMINFO) += iminfo.o obj-$(CONFIG_CMD_LINUX16) += linux16.o obj-$(CONFIG_CMD_LOADB) += loadb.o xyzModem.o obj-$(CONFIG_CMD_LOADY) += loadb.o xyzModem.o diff --git a/commands/bootm.c b/commands/bootm.c index d0bb35062a..8936897a04 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -321,85 +321,6 @@ BAREBOX_CMD_END BAREBOX_MAGICVAR(bootargs, "Linux Kernel parameters"); -/** - * @page bootm_command - -\todo What does bootm do, what kind of image does it boot? - - */ - -#ifdef CONFIG_CMD_IMI -static int do_iminfo(struct command *cmdtp, int argc, char *argv[]) -{ - int arg; - ulong addr; - int rcode=0; - - if (argc < 2) { - return image_info (load_addr); - } - - for (arg=1; arg ih_hcrc = 0; - - if (crc32 (0, (uchar *)data, len) != checksum) { - puts (" Bad Header Checksum\n"); - return 1; - } - - /* for multi-file images we need the data part, too */ - print_image_hdr ((image_header_t *)addr); - - data = addr + image_get_header_size(); - len = image_get_size(hdr); - - puts (" Verifying Checksum ... "); - if (crc32 (0, (uchar *)data, len) != image_get_dcrc(hdr)) { - puts (" Bad Data CRC\n"); - return 1; - } - puts ("OK\n"); - return 0; -} - -BAREBOX_CMD_HELP_START(iminfo) -BAREBOX_CMD_HELP_USAGE("iminfo\n") -BAREBOX_CMD_HELP_SHORT("Print header information for an application image.\n") -BAREBOX_CMD_HELP_END - -BAREBOX_CMD_START(iminfo) - .cmd = do_iminfo, - .usage = "print header information for an application image", - BAREBOX_CMD_HELP(cmd_iminfo_help) -BAREBOX_CMD_END - -#endif /* CONFIG_CMD_IMI */ - #ifdef CONFIG_BZLIB void bz_internal_error(int errcode) { diff --git a/commands/iminfo.c b/commands/iminfo.c new file mode 100644 index 0000000000..2fde9bc09c --- /dev/null +++ b/commands/iminfo.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include +#include + +static int image_info(image_header_t *hdr) +{ + u32 len, checksum; + + if (image_get_magic(hdr) != IH_MAGIC) { + puts (" Bad Magic Number\n"); + return 1; + } + + len = image_get_header_size(); + + checksum = image_get_hcrc(hdr); + hdr->ih_hcrc = 0; + + if (crc32 (0, hdr, len) != checksum) { + puts (" Bad Header Checksum\n"); + return 1; + } + + image_print_contents(hdr, NULL); + + return 0; +} + +static int do_iminfo(struct command *cmdtp, int argc, char *argv[]) +{ + int rcode = 1; + int fd; + int ret; + image_header_t hdr; + + if (argc != 2) + return COMMAND_ERROR_USAGE; + + fd = open(argv[1], O_RDONLY); + if (fd < 0) { + perror("open"); + return 1; + } + + ret = read(fd, &hdr, sizeof(image_header_t)); + if (ret != sizeof(image_header_t)) + goto err_out; + + printf("Image at %s:\n", argv[1]); + image_info(&hdr); + +err_out: + close(fd); + + return rcode; +} + +BAREBOX_CMD_HELP_START(iminfo) +BAREBOX_CMD_HELP_USAGE("iminfo\n") +BAREBOX_CMD_HELP_SHORT("Print header information for an application image.\n") +BAREBOX_CMD_HELP_END + +BAREBOX_CMD_START(iminfo) + .cmd = do_iminfo, + .usage = "print header information for an application image", + BAREBOX_CMD_HELP(cmd_iminfo_help) +BAREBOX_CMD_END diff --git a/common/image.c b/common/image.c index 4a6402d8b9..939fe4b75d 100644 --- a/common/image.c +++ b/common/image.c @@ -290,7 +290,7 @@ void image_print_contents(const image_header_t *hdr, void *data) printf ("%sEntry Point: %08x\n", p, image_get_ep(hdr)); type = image_get_type(hdr); - if (type == IH_TYPE_MULTI || type == IH_TYPE_SCRIPT) { + if (data && (type == IH_TYPE_MULTI || type == IH_TYPE_SCRIPT)) { int i; ulong img_data, len; ulong count = image_multi_count(data); diff --git a/include/image.h b/include/image.h index 691bf2d88b..f3a9949e54 100644 --- a/include/image.h +++ b/include/image.h @@ -335,9 +335,6 @@ void image_print_size(uint32_t size); void image_print_contents(const image_header_t *hdr, void *data); -/* commamds/bootm.c */ -void print_image_hdr (image_header_t *hdr); - /* * Load an image into memory. Returns a pointer to the loaded * image. -- cgit v1.2.3 From 248e5f1cbed581c1bf6288831b6888e2166fb952 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sat, 26 Nov 2011 13:53:21 +0100 Subject: compile in simple_strtoull Signed-off-by: Sascha Hauer --- include/common.h | 2 -- lib/vsprintf.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/include/common.h b/include/common.h index d63ad023ba..68ccbd9b61 100644 --- a/include/common.h +++ b/include/common.h @@ -115,9 +115,7 @@ int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp); /* lib_generic/vsprintf.c */ ulong simple_strtoul(const char *cp,char **endp,unsigned int base); -#ifdef CFG_64BIT_VSPRINTF unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base); -#endif long simple_strtol(const char *cp,char **endp,unsigned int base); /* lib_generic/crc32.c */ diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 54e162f063..4165f97485 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -56,7 +56,6 @@ long simple_strtol(const char *cp,char **endp,unsigned int base) } EXPORT_SYMBOL(simple_strtol); -#ifdef CFG_64BIT_STRTOUL unsigned long long simple_strtoull (const char *cp, char **endp, unsigned int base) { unsigned long long result = 0, value; @@ -84,7 +83,6 @@ unsigned long long simple_strtoull (const char *cp, char **endp, unsigned int ba *endp = (char *) cp; return result; } -#endif /* CFG_64BIT_STRTOUL */ /* we use this so that we can do without the ctype library */ #define is_digit(c) ((c) >= '0' && (c) <= '9') -- cgit v1.2.3 From a94db01cdce44acc50c7ad8ebcb9040b0020fabd Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sat, 26 Nov 2011 13:53:42 +0100 Subject: introduce some env helpers Signed-off-by: Sascha Hauer --- common/env.c | 22 ++++++++++++++++++++++ include/environment.h | 3 +++ 2 files changed, 25 insertions(+) diff --git a/common/env.c b/common/env.c index 05ed71418e..e57a520a35 100644 --- a/common/env.c +++ b/common/env.c @@ -251,3 +251,25 @@ int export(const char *varname) return 0; } EXPORT_SYMBOL(export); + +void export_env_ull(const char *name, unsigned long long val) +{ + char *valstr = asprintf("%lld", val); + + setenv(name, valstr); + export(name); + + kfree(valstr); +} +EXPORT_SYMBOL(export_env_ull); + +unsigned long long getenv_ull(const char *name) +{ + const char *valstr = getenv(name); + + if (!valstr) + return 0; + + return simple_strtoull(valstr, NULL, 0); +} +EXPORT_SYMBOL(getenv_ull); diff --git a/include/environment.h b/include/environment.h index da032e21d6..6d38755ae7 100644 --- a/include/environment.h +++ b/include/environment.h @@ -59,6 +59,9 @@ static inline int setenv(const char *var, const char *val) } #endif +void export_env_ull(const char *name, unsigned long long val); +unsigned long long getenv_ull(const char *name); + int env_pop_context(void); int env_push_context(void); -- cgit v1.2.3 From 06656eb05e61628edc2f8ecf0d4ad4dd23fd4486 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sat, 26 Nov 2011 13:54:05 +0100 Subject: armlinux: cleanup linux vars arch_number is currently exported to the environment but not read back on boot time which is rather confusing. system_rev and system_serial are not exported to the environment but can be set in board specific code. This patch exports all these variables to the environment and reads them back on boot time. All variables get a armlinux_ prefix, so the arch_number environment variable gets renamed. Signed-off-by: Sascha Hauer --- arch/arm/lib/armlinux.c | 92 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 65 insertions(+), 27 deletions(-) diff --git a/arch/arm/lib/armlinux.c b/arch/arm/lib/armlinux.c index d8ca47706d..ebe41372a2 100644 --- a/arch/arm/lib/armlinux.c +++ b/arch/arm/lib/armlinux.c @@ -45,11 +45,67 @@ #include static struct tag *params; -static int armlinux_architecture = 0; static void *armlinux_bootparams = NULL; -static unsigned int system_rev; -static u64 system_serial; +#ifndef CONFIG_ENVIRONMENT_VARIABLES +static int armlinux_architecture; +static u32 armlinux_system_rev; +static u64 armlinux_system_serial; +#endif + +void armlinux_set_architecture(int architecture) +{ +#ifdef CONFIG_ENVIRONMENT_VARIABLES + export_env_ull("armlinux_architecture", architecture); +#else + armlinux_architecture = architecture; +#endif +} + +int armlinux_get_architecture(void) +{ +#ifdef CONFIG_ENVIRONMENT_VARIABLES + return getenv_ull("armlinux_architecture"); +#else + return armlinux_architecture; +#endif +} + +void armlinux_set_revision(unsigned int rev) +{ +#ifdef CONFIG_ENVIRONMENT_VARIABLES + export_env_ull("armlinux_system_rev", rev); +#else + return armlinux_system_rev; +#endif +} + +unsigned int armlinux_get_revision(void) +{ +#ifdef CONFIG_ENVIRONMENT_VARIABLES + return getenv_ull("armlinux_system_rev"); +#else + return armlinux_system_rev; +#endif +} + +void armlinux_set_serial(u64 serial) +{ +#ifdef CONFIG_ENVIRONMENT_VARIABLES + export_env_ull("armlinux_system_serial", serial); +#else + armlinux_system_serial = serial; +#endif +} + +u64 armlinux_get_serial(void) +{ +#ifdef CONFIG_ENVIRONMENT_VARIABLES + return getenv_ull("armlinux_system_serial"); +#else + return armlinux_system_serial; +#endif +} static void setup_start_tag(void) { @@ -117,6 +173,8 @@ static void setup_commandline_tag(const char *commandline, int swap) static void setup_revision_tag(void) { + u32 system_rev = armlinux_get_revision(); + if (system_rev) { params->hdr.tag = ATAG_REVISION; params->hdr.size = tag_size(tag_revision); @@ -129,6 +187,8 @@ static void setup_revision_tag(void) static void setup_serial_tag(void) { + u64 system_serial = armlinux_get_serial(); + if (system_serial) { params->hdr.tag = ATAG_SERIAL; params->hdr.size = tag_size(tag_serialnr); @@ -176,7 +236,7 @@ static void setup_tags(struct image_data *data, int swap) setup_end_tag(); printf("commandline: %s\n" - "arch_number: %d\n", commandline, armlinux_architecture); + "arch_number: %d\n", commandline, armlinux_get_architecture()); } @@ -185,28 +245,6 @@ void armlinux_set_bootparams(void *params) armlinux_bootparams = params; } -void armlinux_set_architecture(int architecture) -{ - char *arch_number = asprintf("%d", architecture); - - armlinux_architecture = architecture; - - setenv("arch_number", arch_number); - export("arch_number"); - - kfree(arch_number); -} - -void armlinux_set_revision(unsigned int rev) -{ - system_rev = rev; -} - -void armlinux_set_serial(u64 serial) -{ - system_serial = serial; -} - void start_linux(void *adr, int swap, struct image_data *data) { void (*kernel)(int zero, int arch, void *params) = adr; @@ -229,5 +267,5 @@ void start_linux(void *adr, int swap, struct image_data *data) __asm__ __volatile__("mcr p15, 0, %0, c1, c0" :: "r" (reg)); } - kernel(0, armlinux_architecture, params); + kernel(0, armlinux_get_architecture(), params); } -- cgit v1.2.3 From d1595f140f72e15a730a453827520430659b68b1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sat, 26 Nov 2011 13:55:53 +0100 Subject: ARM bootm: remove now obsolete args Now that the arch_number and system_rev variables can be set from the environment we don't need the old bootm command line switch mechanism anymore. Signed-off-by: Sascha Hauer --- arch/arm/lib/bootm.c | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 87bf3b323e..a104aaa371 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -44,36 +44,7 @@ static int do_bootm_linux(struct image_data *data) return -1; } -static int image_handle_cmdline_parse(struct image_data *data, int opt, - char *optarg) -{ - int ret = 1; - int no; - - switch (opt) { - case 'a': - no = simple_strtoul(optarg, NULL, 0); - armlinux_set_architecture(no); - ret = 0; - break; - case 'R': - no = simple_strtoul(optarg, NULL, 0); - armlinux_set_revision(no); - ret = 0; - break; - default: - break; - } - - return ret; -} - static struct image_handler handler = { - .cmdline_options = "a:R:", - .cmdline_parse = image_handle_cmdline_parse, - .help_string = " -a use architecture number \n" - " -R use system revison \n", - .bootm = do_bootm_linux, .image_type = IH_OS_LINUX, }; -- cgit v1.2.3 From 05b11670997997862ae18bb28ca70710afe75f95 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 27 Nov 2011 15:25:37 +0100 Subject: bootm: handle initrds inline Signed-off-by: Sascha Hauer --- commands/bootm.c | 78 ++++++++++++++++++++------------------------------------ 1 file changed, 28 insertions(+), 50 deletions(-) diff --git a/commands/bootm.c b/commands/bootm.c index 8936897a04..056ada52b0 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -142,55 +142,6 @@ static struct image_handle *get_fake_image_handle(struct image_data *data, int n return handle; } -static int initrd_handler_parse_options(struct image_data *data, int opt, - char *optarg) -{ - uint32_t initrd_start; - - switch(opt) { - case 'L': - if (!data->initrd) { - eprintf("Warning -L ingnored. Specify the initrd first\n"); - break; - } - initrd_start = simple_strtoul(optarg, NULL, 0); - printf("initrd_start=0x%x\n", initrd_start); - data->initrd->header.ih_load = cpu_to_uimage(initrd_start); - break; - case 'r': - printf("use initrd %s\n", optarg); - /* check for multi image @ */ - if (optarg[0] == '@') { - int num = simple_strtol(optarg + 1, NULL, 0); - - data->initrd = get_fake_image_handle(data, num); - } else { - data->initrd = map_image(optarg, data->verify); - } - if (!data->initrd) - return -1; - break; - default: - return 1; - } - - return 0; -} - -static struct image_handler initrd_handler = { - .cmdline_options = "r:L:", - .cmdline_parse = initrd_handler_parse_options, - .help_string = " -r specify an initrd image\n" - " -L specify initrd load address", -}; - -static int initrd_register_image_handler(void) -{ - return register_image_handler(&initrd_handler); -} - -late_initcall(initrd_register_image_handler); - static int handler_parse_options(struct image_data *data, int opt, char *optarg) { struct image_handler *handler; @@ -217,13 +168,14 @@ static int do_bootm(struct command *cmdtp, int argc, char *argv[]) struct image_handle *os_handle, *initrd_handle = NULL; struct image_handler *handler; struct image_data data; + u32 initrd_start; char options[53]; /* worst case: whole alphabet with colons */ memset(&data, 0, sizeof(struct image_data)); data.verify = 1; /* Collect options from registered handlers */ - strcpy(options, "nh"); + strcpy(options, "nhr:L:"); list_for_each_entry(handler, &handler_list, list) { if (handler->cmdline_options) strcat(options, handler->cmdline_options); @@ -243,6 +195,28 @@ static int do_bootm(struct command *cmdtp, int argc, char *argv[]) } return 0; + case 'L': + if (!data.initrd) { + eprintf("Warning -L ingnored. Specify the initrd first\n"); + break; + } + initrd_start = simple_strtoul(optarg, NULL, 0); + printf("initrd_start=0x%x\n", initrd_start); + data.initrd->header.ih_load = cpu_to_uimage(initrd_start); + break; + case 'r': + printf("use initrd %s\n", optarg); + /* check for multi image @ */ + if (optarg[0] == '@') { + int num = simple_strtol(optarg + 1, NULL, 0); + + data.initrd = get_fake_image_handle(&data, num); + } else { + data.initrd = map_image(optarg, data.verify); + } + if (!data.initrd) + return -1; + break; default: break; } @@ -270,6 +244,8 @@ static int do_bootm(struct command *cmdtp, int argc, char *argv[]) switch(opt) { case 'h': case 'n': + case 'L': + case 'r': break; default: if (!handler_parse_options(&data, opt, optarg)) @@ -311,6 +287,8 @@ BAREBOX_CMD_HELP_START(bootm) BAREBOX_CMD_HELP_USAGE("bootm [-n] image\n") BAREBOX_CMD_HELP_SHORT("Boot an application image.\n") BAREBOX_CMD_HELP_OPT ("-n", "Do not verify the image (speeds up boot process)\n") +BAREBOX_CMD_HELP_OPT ("-r ","specify an initrd image\n") +BAREBOX_CMD_HELP_OPT ("-L ","specify initrd load address") BAREBOX_CMD_HELP_END BAREBOX_CMD_START(bootm) -- cgit v1.2.3 From 479c6e9506ecfe0b24407a9b3caefc3ed0c480d1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 27 Nov 2011 15:33:55 +0100 Subject: bootm: remove image handler options Signed-off-by: Sascha Hauer --- commands/bootm.c | 55 +------------------------------------------------------ include/boot.h | 4 ---- 2 files changed, 1 insertion(+), 58 deletions(-) diff --git a/commands/bootm.c b/commands/bootm.c index 056ada52b0..9f3f354e66 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -142,25 +142,6 @@ static struct image_handle *get_fake_image_handle(struct image_data *data, int n return handle; } -static int handler_parse_options(struct image_data *data, int opt, char *optarg) -{ - struct image_handler *handler; - int ret; - - list_for_each_entry(handler, &handler_list, list) { - if (!handler->cmdline_parse) - continue; - - ret = handler->cmdline_parse(data, opt, optarg); - if (ret > 0) - continue; - - return ret; - } - - return -1; -} - static int do_bootm(struct command *cmdtp, int argc, char *argv[]) { int opt; @@ -169,32 +150,15 @@ static int do_bootm(struct command *cmdtp, int argc, char *argv[]) struct image_handler *handler; struct image_data data; u32 initrd_start; - char options[53]; /* worst case: whole alphabet with colons */ memset(&data, 0, sizeof(struct image_data)); data.verify = 1; - /* Collect options from registered handlers */ - strcpy(options, "nhr:L:"); - list_for_each_entry(handler, &handler_list, list) { - if (handler->cmdline_options) - strcat(options, handler->cmdline_options); - } - - while((opt = getopt(argc, argv, options)) > 0) { + while ((opt = getopt(argc, argv, "nr:L:")) > 0) { switch(opt) { case 'n': data.verify = 0; break; - case 'h': - printf("bootm advanced options:\n"); - - list_for_each_entry(handler, &handler_list, list) { - if (handler->help_string) - printf("%s\n", handler->help_string); - } - - return 0; case 'L': if (!data.initrd) { eprintf("Warning -L ingnored. Specify the initrd first\n"); @@ -238,23 +202,6 @@ static int do_bootm(struct command *cmdtp, int argc, char *argv[]) goto err_out; } - optind = 0; - - while((opt = getopt(argc, argv, options)) > 0) { - switch(opt) { - case 'h': - case 'n': - case 'L': - case 'r': - break; - default: - if (!handler_parse_options(&data, opt, optarg)) - continue; - - return 1; - } - } - /* * We have reached the point of no return: we are going to * overwrite all exception vector code, so we cannot easily diff --git a/include/boot.h b/include/boot.h index 623f443c19..4901598eb3 100644 --- a/include/boot.h +++ b/include/boot.h @@ -14,10 +14,6 @@ struct image_data { struct image_handler { struct list_head list; - char *cmdline_options; - int (*cmdline_parse)(struct image_data *data, int opt, char *optarg); - char *help_string; - int image_type; int (*bootm)(struct image_data *data); }; -- cgit v1.2.3 From 72bdddcca38dd8ad234c8a8d98651c01c503296a Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 27 Nov 2011 15:57:03 +0100 Subject: bootm: fix various memory leaks Signed-off-by: Sascha Hauer --- commands/bootm.c | 19 +++++++++++-------- common/image.c | 1 + 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/commands/bootm.c b/commands/bootm.c index 9f3f354e66..6255c03e7d 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -146,10 +146,11 @@ static int do_bootm(struct command *cmdtp, int argc, char *argv[]) { int opt; image_header_t *os_header; - struct image_handle *os_handle, *initrd_handle = NULL; + struct image_handle *os_handle = NULL; struct image_handler *handler; struct image_data data; u32 initrd_start; + int ret = 1; memset(&data, 0, sizeof(struct image_data)); data.verify = 1; @@ -179,19 +180,21 @@ static int do_bootm(struct command *cmdtp, int argc, char *argv[]) data.initrd = map_image(optarg, data.verify); } if (!data.initrd) - return -1; + goto err_out; break; default: break; } } - if (optind == argc) - return COMMAND_ERROR_USAGE; + if (optind == argc) { + ret = COMMAND_ERROR_USAGE; + goto err_out; + } os_handle = map_image(argv[optind], data.verify); if (!os_handle) - return 1; + goto err_out; data.os = os_handle; os_header = &os_handle->header; @@ -225,9 +228,9 @@ static int do_bootm(struct command *cmdtp, int argc, char *argv[]) err_out: if (os_handle) unmap_image(os_handle); - if (initrd_handle) - unmap_image(initrd_handle); - return 1; + if (data.initrd) + unmap_image(data.initrd); + return ret; } BAREBOX_CMD_HELP_START(bootm) diff --git a/common/image.c b/common/image.c index 939fe4b75d..d68889bc0f 100644 --- a/common/image.c +++ b/common/image.c @@ -404,6 +404,7 @@ err_out: close(fd); if (handle->flags & IH_MALLOC) free(handle->data); + free(handle->data_entries); free(handle); return NULL; } -- cgit v1.2.3 From 19a0c370aa0d575a17679a76f226b591e68c2ff7 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 27 Nov 2011 16:20:51 +0100 Subject: bootm: do not require -L after -r Signed-off-by: Sascha Hauer --- commands/bootm.c | 13 +++++-------- include/boot.h | 1 + 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/commands/bootm.c b/commands/bootm.c index 6255c03e7d..9ae4e2287c 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -149,11 +149,11 @@ static int do_bootm(struct command *cmdtp, int argc, char *argv[]) struct image_handle *os_handle = NULL; struct image_handler *handler; struct image_data data; - u32 initrd_start; int ret = 1; memset(&data, 0, sizeof(struct image_data)); data.verify = 1; + data.initrd_address = ~0; while ((opt = getopt(argc, argv, "nr:L:")) > 0) { switch(opt) { @@ -161,13 +161,7 @@ static int do_bootm(struct command *cmdtp, int argc, char *argv[]) data.verify = 0; break; case 'L': - if (!data.initrd) { - eprintf("Warning -L ingnored. Specify the initrd first\n"); - break; - } - initrd_start = simple_strtoul(optarg, NULL, 0); - printf("initrd_start=0x%x\n", initrd_start); - data.initrd->header.ih_load = cpu_to_uimage(initrd_start); + data.initrd_address = simple_strtoul(optarg, NULL, 0); break; case 'r': printf("use initrd %s\n", optarg); @@ -187,6 +181,9 @@ static int do_bootm(struct command *cmdtp, int argc, char *argv[]) } } + if (data.initrd && data.initrd_address != ~0) + data.initrd->header.ih_load = cpu_to_uimage(data.initrd_address); + if (optind == argc) { ret = COMMAND_ERROR_USAGE; goto err_out; diff --git a/include/boot.h b/include/boot.h index 4901598eb3..b22514b462 100644 --- a/include/boot.h +++ b/include/boot.h @@ -9,6 +9,7 @@ struct image_data { struct image_handle *initrd; const char *oftree; int verify; + unsigned long initrd_address; }; struct image_handler { -- cgit v1.2.3 From 6dbe704263ebcfc243bcce7af0b718c67bdbd54c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 27 Nov 2011 16:36:43 +0100 Subject: bootm: fix typo, update help str Signed-off-by: Sascha Hauer --- commands/bootm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commands/bootm.c b/commands/bootm.c index 9ae4e2287c..a486b508dc 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -122,7 +122,7 @@ int register_image_handler(struct image_handler *handler) /* * generate a image_handle from a multi_image - * this image_handle can be free by unmap_image + * this image_handle can be freed by unmap_image */ static struct image_handle *get_fake_image_handle(struct image_data *data, int num) { @@ -231,7 +231,7 @@ err_out: } BAREBOX_CMD_HELP_START(bootm) -BAREBOX_CMD_HELP_USAGE("bootm [-n] image\n") +BAREBOX_CMD_HELP_USAGE("bootm [OPTIONS] image\n") BAREBOX_CMD_HELP_SHORT("Boot an application image.\n") BAREBOX_CMD_HELP_OPT ("-n", "Do not verify the image (speeds up boot process)\n") BAREBOX_CMD_HELP_OPT ("-r ","specify an initrd image\n") -- cgit v1.2.3 From ec4ee82ca96a6a4867cd3f2e58fed4afd816d14a Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 27 Nov 2011 17:03:05 +0100 Subject: bootm relocate_image: honour load_address the uImage should be relocated to load_address. This is handled correctly in gzip/bzip2 compressed images, but not in uncompressed images. fix this. Also, when a variable is not used once without casting to another type it probably means that its type is wrong. Signed-off-by: Sascha Hauer --- commands/bootm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/commands/bootm.c b/commands/bootm.c index a486b508dc..ff9b18520f 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -62,28 +62,28 @@ int relocate_image(struct image_handle *handle, void *load_address) image_header_t *hdr = &handle->header; unsigned long len = image_get_size(hdr); struct image_handle_data *iha; - unsigned long data; + void *data; #if defined CONFIG_CMD_BOOTM_ZLIB || defined CONFIG_CMD_BOOTM_BZLIB - uint unc_len = CFG_BOOTM_LEN; + uint unc_len = BOOTM_LEN; #endif iha = image_handle_data_get_by_num(handle, 0); - data = (unsigned long)(iha->data); + data = iha->data; switch (image_get_comp(hdr)) { case IH_COMP_NONE: - if(image_get_load(hdr) == data) { + if (load_address == data) { printf (" XIP ... "); } else { - memmove ((void *) image_get_load(hdr), (uchar *)data, len); + memmove(load_address, data, len); } break; #ifdef CONFIG_CMD_BOOTM_ZLIB case IH_COMP_GZIP: printf (" Uncompressing ... "); if (gunzip (load_address, unc_len, - (uchar *)data, &len) != 0) + data, &len) != 0) return -1; break; #endif @@ -96,7 +96,7 @@ int relocate_image(struct image_handle *handle, void *load_address) * at most 2300 KB of memory. */ if (BZ2_bzBuffToBuffDecompress (load_address, - &unc_len, (char *)data, len, + &unc_len, data, len, MALLOC_SIZE < (4096 * 1024), 0) != BZ_OK) return -1; -- cgit v1.2.3 From 351058fa51dbc010c37906b46ecf67a41dbbad8d Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 27 Nov 2011 17:51:22 +0100 Subject: bootm: push relocate_image up to the generic command All handlers used to just relocate the image without any checks, so we are doomed if we write outside of SDRAM or will overwrite ourselves. Move the relocation up to the generic part where we have a chance of catching these issues. Signed-off-by: Sascha Hauer --- arch/arm/lib/bootm.c | 7 ------- arch/blackfin/lib/blackfin_linux.c | 3 --- arch/nios2/lib/bootm.c | 3 --- arch/ppc/lib/ppclinux.c | 3 --- commands/bootm.c | 17 +++++++++++++++++ 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index a104aaa371..5b85ba9d31 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -29,13 +29,6 @@ static int do_bootm_linux(struct image_data *data) debug("## Transferring control to Linux (at address 0x%p) ...\n", theKernel); - if (relocate_image(data->os, (void *)image_get_load(os_header))) - return -1; - - if (data->initrd) - if (relocate_image(data->initrd, (void *)image_get_load(&data->initrd->header))) - return -1; - /* we assume that the kernel is in place */ printf("\nStarting kernel %s...\n\n", data->initrd ? "with initrd " : ""); diff --git a/arch/blackfin/lib/blackfin_linux.c b/arch/blackfin/lib/blackfin_linux.c index a20cf55748..9da9ec4e58 100644 --- a/arch/blackfin/lib/blackfin_linux.c +++ b/arch/blackfin/lib/blackfin_linux.c @@ -50,9 +50,6 @@ static int do_bootm_linux(struct image_data *idata) appl = (int (*)(char *))image_get_ep(os_header); printf("Starting Kernel at 0x%p\n", appl); - if (relocate_image(os_handle, (void *)image_get_load(os_header))) - return -1; - icache_disable(); strncpy(cmdlinedest, cmdline, 0x1000); diff --git a/arch/nios2/lib/bootm.c b/arch/nios2/lib/bootm.c index c38243f9a3..b5b344f499 100644 --- a/arch/nios2/lib/bootm.c +++ b/arch/nios2/lib/bootm.c @@ -43,9 +43,6 @@ static int do_bootm_linux(struct image_data *idata) kernel = (void (*)(int, int, int, const char *))ntohl(os_header->ih_ep); - if (relocate_image(idata->os, (void *)ntohl(os_header->ih_load))) - return -1; - /* kernel parameters passing * r4 : NIOS magic * r5 : initrd start diff --git a/arch/ppc/lib/ppclinux.c b/arch/ppc/lib/ppclinux.c index 531c215817..471b3037fe 100644 --- a/arch/ppc/lib/ppclinux.c +++ b/arch/ppc/lib/ppclinux.c @@ -200,9 +200,6 @@ static int do_bootm_linux(struct image_data *idata) kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))image_get_ep(os_header); /* FIXME */ - if (relocate_image(idata->os, (void *)image_get_load(os_header))) - return -1; - #if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500) unlock_ram_in_cache(); #endif diff --git a/commands/bootm.c b/commands/bootm.c index ff9b18520f..cad7b21261 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -210,6 +210,23 @@ static int do_bootm(struct command *cmdtp, int argc, char *argv[]) puts ("OK\n"); + /* + * FIXME: we do not check at all whether + * - we will write the image to sdram + * - we overwrite ourselves + * - kernel and initrd overlap + */ + ret = relocate_image(data.os, (void *)image_get_load(os_header)); + if (ret) + goto err_out; + + if (data.initrd) { + ret = relocate_image(data.initrd, + (void *)image_get_load(&data.initrd->header)); + if (ret) + goto err_out; + } + /* loop through the registered handlers */ list_for_each_entry(handler, &handler_list, list) { if (image_get_os(os_header) == handler->image_type) { -- cgit v1.2.3 From d4950552f5c7e95b04f9a69809542080483ca77d Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 27 Nov 2011 17:43:26 +0100 Subject: bootm: use initrd_address and initrd_size Make these fields in struct image_data the reference for image handlers Signed-off-by: Sascha Hauer --- arch/arm/lib/armlinux.c | 10 +++++----- commands/bootm.c | 11 ++++++----- include/boot.h | 1 + 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/arch/arm/lib/armlinux.c b/arch/arm/lib/armlinux.c index ebe41372a2..6c001e7e37 100644 --- a/arch/arm/lib/armlinux.c +++ b/arch/arm/lib/armlinux.c @@ -200,7 +200,7 @@ static void setup_serial_tag(void) } } -static void setup_initrd_tag(image_header_t *header) +static void setup_initrd_tag(unsigned long start, unsigned long size) { /* an ATAG_INITRD node tells the kernel where the compressed * ramdisk can be found. ATAG_RDIMG is a better name, actually. @@ -208,8 +208,8 @@ static void setup_initrd_tag(image_header_t *header) params->hdr.tag = ATAG_INITRD2; params->hdr.size = tag_size(tag_initrd); - params->u.initrd.start = image_get_load(header); - params->u.initrd.size = image_get_data_size(header); + params->u.initrd.start = start; + params->u.initrd.size = size; params = tag_next(params); } @@ -228,8 +228,8 @@ static void setup_tags(struct image_data *data, int swap) setup_memory_tags(); setup_commandline_tag(commandline, swap); - if (data && data->initrd) - setup_initrd_tag (&data->initrd->header); + if (data && (data->initrd_size > 0)) + setup_initrd_tag(data->initrd_address, data->initrd_size); setup_revision_tag(); setup_serial_tag(); diff --git a/commands/bootm.c b/commands/bootm.c index cad7b21261..0722e92461 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -181,9 +181,6 @@ static int do_bootm(struct command *cmdtp, int argc, char *argv[]) } } - if (data.initrd && data.initrd_address != ~0) - data.initrd->header.ih_load = cpu_to_uimage(data.initrd_address); - if (optind == argc) { ret = COMMAND_ERROR_USAGE; goto err_out; @@ -221,8 +218,12 @@ static int do_bootm(struct command *cmdtp, int argc, char *argv[]) goto err_out; if (data.initrd) { - ret = relocate_image(data.initrd, - (void *)image_get_load(&data.initrd->header)); + if (data.initrd && data.initrd_address == ~0) + data.initrd_address = uimage_to_cpu(data.initrd->header.ih_load); + + data.initrd_size = image_get_data_size(&data.initrd->header); + + ret = relocate_image(data.initrd, (void *)data.initrd_address); if (ret) goto err_out; } diff --git a/include/boot.h b/include/boot.h index b22514b462..b67e034801 100644 --- a/include/boot.h +++ b/include/boot.h @@ -10,6 +10,7 @@ struct image_data { const char *oftree; int verify; unsigned long initrd_address; + unsigned long initrd_size; }; struct image_handler { -- cgit v1.2.3 From 42a691328e450613fbab5a2314988f6fd34f7703 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 13:42:45 +0100 Subject: armlinux: remove unnecessary include Signed-off-by: Sascha Hauer --- arch/arm/lib/armlinux.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/lib/armlinux.c b/arch/arm/lib/armlinux.c index 6c001e7e37..45752dc609 100644 --- a/arch/arm/lib/armlinux.c +++ b/arch/arm/lib/armlinux.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From a5f5945c79bc317f84d396ba69b982a8e9d897c4 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 13:43:02 +0100 Subject: arm bootm: remove unnecessary include Signed-off-by: Sascha Hauer --- arch/arm/lib/bootm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 5b85ba9d31..031a2698ec 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From f400980638b4d6388689f298c8a538d3979dad39 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 13:43:24 +0100 Subject: scripts/mkimage.c: remove unnecessary include Signed-off-by: Sascha Hauer --- scripts/mkimage.c | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/mkimage.c b/scripts/mkimage.c index 3beab91fad..b219cb8f2b 100644 --- a/scripts/mkimage.c +++ b/scripts/mkimage.c @@ -33,7 +33,6 @@ char *cmdname; -#include "../include/zlib.h" #include "../crypto/crc32.c" //extern unsigned long crc32 (unsigned long crc, const char *buf, unsigned int len); -- cgit v1.2.3 From 5930f100aac7cebd4e45d4ec6c16e1cf5b2a1274 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 12:50:28 +0100 Subject: use kernel bunzip implementation The kernel uncompression functions have a unified API. Switch to the kernel implementation to unify the different uncompression APIs. As a bonus the kernel implementation is much smaller. Signed-off-by: Sascha Hauer --- commands/bootm.c | 23 +- include/bunzip2.h | 10 + lib/Makefile | 2 +- lib/decompress_bunzip2.c | 756 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 779 insertions(+), 12 deletions(-) create mode 100644 include/bunzip2.h create mode 100644 lib/decompress_bunzip2.c diff --git a/commands/bootm.c b/commands/bootm.c index 0722e92461..79a16d4745 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -43,6 +42,7 @@ #include #include #include +#include #include #ifndef CFG_BOOTM_LEN @@ -57,12 +57,18 @@ struct image_handle_data* image_handle_data_get_by_num(struct image_handle* hand return &handle->data_entries[num]; } +static void unzip_error(char *x) +{ + puts(x); +} + int relocate_image(struct image_handle *handle, void *load_address) { image_header_t *hdr = &handle->header; unsigned long len = image_get_size(hdr); struct image_handle_data *iha; void *data; + int ret; #if defined CONFIG_CMD_BOOTM_ZLIB || defined CONFIG_CMD_BOOTM_BZLIB uint unc_len = BOOTM_LEN; @@ -90,16 +96,11 @@ int relocate_image(struct image_handle *handle, void *load_address) #ifdef CONFIG_CMD_BOOTM_BZLIB case IH_COMP_BZIP2: printf (" Uncompressing ... "); - /* - * If we've got less than 4 MB of malloc() space, - * use slower decompression algorithm which requires - * at most 2300 KB of memory. - */ - if (BZ2_bzBuffToBuffDecompress (load_address, - &unc_len, data, len, - MALLOC_SIZE < (4096 * 1024), 0) - != BZ_OK) - return -1; + + ret = bunzip2(data, len, NULL, NULL, load_address, NULL, + unzip_error); + if (ret) + return ret; break; #endif default: diff --git a/include/bunzip2.h b/include/bunzip2.h new file mode 100644 index 0000000000..115272137a --- /dev/null +++ b/include/bunzip2.h @@ -0,0 +1,10 @@ +#ifndef DECOMPRESS_BUNZIP2_H +#define DECOMPRESS_BUNZIP2_H + +int bunzip2(unsigned char *inbuf, int len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *output, + int *pos, + void(*error)(char *x)); +#endif diff --git a/lib/Makefile b/lib/Makefile index eccdfff141..b02191adba 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -15,7 +15,7 @@ obj-y += libgen.o obj-y += stringlist.o obj-y += recursive_action.o obj-y += make_directory.o -obj-$(CONFIG_BZLIB) += bzlib.o bzlib_crctable.o bzlib_decompress.o bzlib_huffman.o bzlib_randtable.o +obj-$(CONFIG_BZLIB) += decompress_bunzip2.o obj-$(CONFIG_ZLIB) += zlib.o gunzip.o obj-$(CONFIG_CMDLINE_EDITING) += readline.o obj-$(CONFIG_SIMPLE_READLINE) += readline_simple.o diff --git a/lib/decompress_bunzip2.c b/lib/decompress_bunzip2.c new file mode 100644 index 0000000000..4b6edd16a8 --- /dev/null +++ b/lib/decompress_bunzip2.c @@ -0,0 +1,756 @@ +/* vi: set sw = 4 ts = 4: */ +/* Small bzip2 deflate implementation, by Rob Landley (rob@landley.net). + + Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), + which also acknowledges contributions by Mike Burrows, David Wheeler, + Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, + Robert Sedgewick, and Jon L. Bentley. + + This code is licensed under the LGPLv2: + LGPL (http://www.gnu.org/copyleft/lgpl.html +*/ + +/* + Size and speed optimizations by Manuel Novoa III (mjn3@codepoet.org). + + More efficient reading of Huffman codes, a streamlined read_bunzip() + function, and various other tweaks. In (limited) tests, approximately + 20% faster than bzcat on x86 and about 10% faster on arm. + + Note that about 2/3 of the time is spent in read_unzip() reversing + the Burrows-Wheeler transformation. Much of that time is delay + resulting from cache misses. + + I would ask that anyone benefiting from this work, especially those + using it in commercial products, consider making a donation to my local + non-profit hospice organization in the name of the woman I loved, who + passed away Feb. 12, 2003. + + In memory of Toni W. Hagan + + Hospice of Acadiana, Inc. + 2600 Johnston St., Suite 200 + Lafayette, LA 70503-3240 + + Phone (337) 232-1234 or 1-800-738-2226 + Fax (337) 232-1297 + + http://www.hospiceacadiana.com/ + + Manuel + */ + +/* + Made it fit for running in Linux Kernel by Alain Knaff (alain@knaff.lu) +*/ + +#include +#include + +#ifdef STATIC +#define PREBOOT +#else +#include +#endif /* STATIC */ + +#ifndef INT_MAX +#define INT_MAX 0x7fffffff +#endif + +/* Constants for Huffman coding */ +#define MAX_GROUPS 6 +#define GROUP_SIZE 50 /* 64 would have been more efficient */ +#define MAX_HUFCODE_BITS 20 /* Longest Huffman code allowed */ +#define MAX_SYMBOLS 258 /* 256 literals + RUNA + RUNB */ +#define SYMBOL_RUNA 0 +#define SYMBOL_RUNB 1 + +/* Status return values */ +#define RETVAL_OK 0 +#define RETVAL_LAST_BLOCK (-1) +#define RETVAL_NOT_BZIP_DATA (-2) +#define RETVAL_UNEXPECTED_INPUT_EOF (-3) +#define RETVAL_UNEXPECTED_OUTPUT_EOF (-4) +#define RETVAL_DATA_ERROR (-5) +#define RETVAL_OUT_OF_MEMORY (-6) +#define RETVAL_OBSOLETE_INPUT (-7) + +/* Other housekeeping constants */ +#define BZIP2_IOBUF_SIZE 4096 + +/* This is what we know about each Huffman coding group */ +struct group_data { + /* We have an extra slot at the end of limit[] for a sentinal value. */ + int limit[MAX_HUFCODE_BITS+1]; + int base[MAX_HUFCODE_BITS]; + int permute[MAX_SYMBOLS]; + int minLen, maxLen; +}; + +/* Structure holding all the housekeeping data, including IO buffers and + memory that persists between calls to bunzip */ +struct bunzip_data { + /* State for interrupting output loop */ + int writeCopies, writePos, writeRunCountdown, writeCount, writeCurrent; + /* I/O tracking data (file handles, buffers, positions, etc.) */ + int (*fill)(void*, unsigned int); + int inbufCount, inbufPos /*, outbufPos*/; + unsigned char *inbuf /*,*outbuf*/; + unsigned int inbufBitCount, inbufBits; + /* The CRC values stored in the block header and calculated from the + data */ + unsigned int crc32Table[256], headerCRC, totalCRC, writeCRC; + /* Intermediate buffer and its size (in bytes) */ + unsigned int *dbuf, dbufSize; + /* These things are a bit too big to go on the stack */ + unsigned char selectors[32768]; /* nSelectors = 15 bits */ + struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */ + int io_error; /* non-zero if we have IO error */ + int byteCount[256]; + unsigned char symToByte[256], mtfSymbol[256]; +}; + + +/* Return the next nnn bits of input. All reads from the compressed input + are done through this function. All reads are big endian */ +static unsigned int get_bits(struct bunzip_data *bd, char bits_wanted) +{ + unsigned int bits = 0; + + /* If we need to get more data from the byte buffer, do so. + (Loop getting one byte at a time to enforce endianness and avoid + unaligned access.) */ + while (bd->inbufBitCount < bits_wanted) { + /* If we need to read more data from file into byte buffer, do + so */ + if (bd->inbufPos == bd->inbufCount) { + if (bd->io_error) + return 0; + bd->inbufCount = bd->fill(bd->inbuf, BZIP2_IOBUF_SIZE); + if (bd->inbufCount <= 0) { + bd->io_error = RETVAL_UNEXPECTED_INPUT_EOF; + return 0; + } + bd->inbufPos = 0; + } + /* Avoid 32-bit overflow (dump bit buffer to top of output) */ + if (bd->inbufBitCount >= 24) { + bits = bd->inbufBits&((1 << bd->inbufBitCount)-1); + bits_wanted -= bd->inbufBitCount; + bits <<= bits_wanted; + bd->inbufBitCount = 0; + } + /* Grab next 8 bits of input from buffer. */ + bd->inbufBits = (bd->inbufBits << 8)|bd->inbuf[bd->inbufPos++]; + bd->inbufBitCount += 8; + } + /* Calculate result */ + bd->inbufBitCount -= bits_wanted; + bits |= (bd->inbufBits >> bd->inbufBitCount)&((1 << bits_wanted)-1); + + return bits; +} + +/* Unpacks the next block and sets up for the inverse burrows-wheeler step. */ + +static int get_next_block(struct bunzip_data *bd) +{ + struct group_data *hufGroup = NULL; + int *base = NULL; + int *limit = NULL; + int dbufCount, nextSym, dbufSize, groupCount, selector, + i, j, k, t, runPos, symCount, symTotal, nSelectors, *byteCount; + unsigned char uc, *symToByte, *mtfSymbol, *selectors; + unsigned int *dbuf, origPtr; + + dbuf = bd->dbuf; + dbufSize = bd->dbufSize; + selectors = bd->selectors; + byteCount = bd->byteCount; + symToByte = bd->symToByte; + mtfSymbol = bd->mtfSymbol; + + /* Read in header signature and CRC, then validate signature. + (last block signature means CRC is for whole file, return now) */ + i = get_bits(bd, 24); + j = get_bits(bd, 24); + bd->headerCRC = get_bits(bd, 32); + if ((i == 0x177245) && (j == 0x385090)) + return RETVAL_LAST_BLOCK; + if ((i != 0x314159) || (j != 0x265359)) + return RETVAL_NOT_BZIP_DATA; + /* We can add support for blockRandomised if anybody complains. + There was some code for this in busybox 1.0.0-pre3, but nobody ever + noticed that it didn't actually work. */ + if (get_bits(bd, 1)) + return RETVAL_OBSOLETE_INPUT; + origPtr = get_bits(bd, 24); + if (origPtr > dbufSize) + return RETVAL_DATA_ERROR; + /* mapping table: if some byte values are never used (encoding things + like ascii text), the compression code removes the gaps to have fewer + symbols to deal with, and writes a sparse bitfield indicating which + values were present. We make a translation table to convert the + symbols back to the corresponding bytes. */ + t = get_bits(bd, 16); + symTotal = 0; + for (i = 0; i < 16; i++) { + if (t&(1 << (15-i))) { + k = get_bits(bd, 16); + for (j = 0; j < 16; j++) + if (k&(1 << (15-j))) + symToByte[symTotal++] = (16*i)+j; + } + } + /* How many different Huffman coding groups does this block use? */ + groupCount = get_bits(bd, 3); + if (groupCount < 2 || groupCount > MAX_GROUPS) + return RETVAL_DATA_ERROR; + /* nSelectors: Every GROUP_SIZE many symbols we select a new + Huffman coding group. Read in the group selector list, + which is stored as MTF encoded bit runs. (MTF = Move To + Front, as each value is used it's moved to the start of the + list.) */ + nSelectors = get_bits(bd, 15); + if (!nSelectors) + return RETVAL_DATA_ERROR; + for (i = 0; i < groupCount; i++) + mtfSymbol[i] = i; + for (i = 0; i < nSelectors; i++) { + /* Get next value */ + for (j = 0; get_bits(bd, 1); j++) + if (j >= groupCount) + return RETVAL_DATA_ERROR; + /* Decode MTF to get the next selector */ + uc = mtfSymbol[j]; + for (; j; j--) + mtfSymbol[j] = mtfSymbol[j-1]; + mtfSymbol[0] = selectors[i] = uc; + } + /* Read the Huffman coding tables for each group, which code + for symTotal literal symbols, plus two run symbols (RUNA, + RUNB) */ + symCount = symTotal+2; + for (j = 0; j < groupCount; j++) { + unsigned char length[MAX_SYMBOLS], temp[MAX_HUFCODE_BITS+1]; + int minLen, maxLen, pp; + /* Read Huffman code lengths for each symbol. They're + stored in a way similar to mtf; record a starting + value for the first symbol, and an offset from the + previous value for everys symbol after that. + (Subtracting 1 before the loop and then adding it + back at the end is an optimization that makes the + test inside the loop simpler: symbol length 0 + becomes negative, so an unsigned inequality catches + it.) */ + t = get_bits(bd, 5)-1; + for (i = 0; i < symCount; i++) { + for (;;) { + if (((unsigned)t) > (MAX_HUFCODE_BITS-1)) + return RETVAL_DATA_ERROR; + + /* If first bit is 0, stop. Else + second bit indicates whether to + increment or decrement the value. + Optimization: grab 2 bits and unget + the second if the first was 0. */ + + k = get_bits(bd, 2); + if (k < 2) { + bd->inbufBitCount++; + break; + } + /* Add one if second bit 1, else + * subtract 1. Avoids if/else */ + t += (((k+1)&2)-1); + } + /* Correct for the initial -1, to get the + * final symbol length */ + length[i] = t+1; + } + /* Find largest and smallest lengths in this group */ + minLen = maxLen = length[0]; + + for (i = 1; i < symCount; i++) { + if (length[i] > maxLen) + maxLen = length[i]; + else if (length[i] < minLen) + minLen = length[i]; + } + + /* Calculate permute[], base[], and limit[] tables from + * length[]. + * + * permute[] is the lookup table for converting + * Huffman coded symbols into decoded symbols. base[] + * is the amount to subtract from the value of a + * Huffman symbol of a given length when using + * permute[]. + * + * limit[] indicates the largest numerical value a + * symbol with a given number of bits can have. This + * is how the Huffman codes can vary in length: each + * code with a value > limit[length] needs another + * bit. + */ + hufGroup = bd->groups+j; + hufGroup->minLen = minLen; + hufGroup->maxLen = maxLen; + /* Note that minLen can't be smaller than 1, so we + adjust the base and limit array pointers so we're + not always wasting the first entry. We do this + again when using them (during symbol decoding).*/ + base = hufGroup->base-1; + limit = hufGroup->limit-1; + /* Calculate permute[]. Concurrently, initialize + * temp[] and limit[]. */ + pp = 0; + for (i = minLen; i <= maxLen; i++) { + temp[i] = limit[i] = 0; + for (t = 0; t < symCount; t++) + if (length[t] == i) + hufGroup->permute[pp++] = t; + } + /* Count symbols coded for at each bit length */ + for (i = 0; i < symCount; i++) + temp[length[i]]++; + /* Calculate limit[] (the largest symbol-coding value + *at each bit length, which is (previous limit << + *1)+symbols at this level), and base[] (number of + *symbols to ignore at each bit length, which is limit + *minus the cumulative count of symbols coded for + *already). */ + pp = t = 0; + for (i = minLen; i < maxLen; i++) { + pp += temp[i]; + /* We read the largest possible symbol size + and then unget bits after determining how + many we need, and those extra bits could be + set to anything. (They're noise from + future symbols.) At each level we're + really only interested in the first few + bits, so here we set all the trailing + to-be-ignored bits to 1 so they don't + affect the value > limit[length] + comparison. */ + limit[i] = (pp << (maxLen - i)) - 1; + pp <<= 1; + base[i+1] = pp-(t += temp[i]); + } + limit[maxLen+1] = INT_MAX; /* Sentinal value for + * reading next sym. */ + limit[maxLen] = pp+temp[maxLen]-1; + base[minLen] = 0; + } + /* We've finished reading and digesting the block header. Now + read this block's Huffman coded symbols from the file and + undo the Huffman coding and run length encoding, saving the + result into dbuf[dbufCount++] = uc */ + + /* Initialize symbol occurrence counters and symbol Move To + * Front table */ + for (i = 0; i < 256; i++) { + byteCount[i] = 0; + mtfSymbol[i] = (unsigned char)i; + } + /* Loop through compressed symbols. */ + runPos = dbufCount = symCount = selector = 0; + for (;;) { + /* Determine which Huffman coding group to use. */ + if (!(symCount--)) { + symCount = GROUP_SIZE-1; + if (selector >= nSelectors) + return RETVAL_DATA_ERROR; + hufGroup = bd->groups+selectors[selector++]; + base = hufGroup->base-1; + limit = hufGroup->limit-1; + } + /* Read next Huffman-coded symbol. */ + /* Note: It is far cheaper to read maxLen bits and + back up than it is to read minLen bits and then an + additional bit at a time, testing as we go. + Because there is a trailing last block (with file + CRC), there is no danger of the overread causing an + unexpected EOF for a valid compressed file. As a + further optimization, we do the read inline + (falling back to a call to get_bits if the buffer + runs dry). The following (up to got_huff_bits:) is + equivalent to j = get_bits(bd, hufGroup->maxLen); + */ + while (bd->inbufBitCount < hufGroup->maxLen) { + if (bd->inbufPos == bd->inbufCount) { + j = get_bits(bd, hufGroup->maxLen); + goto got_huff_bits; + } + bd->inbufBits = + (bd->inbufBits << 8)|bd->inbuf[bd->inbufPos++]; + bd->inbufBitCount += 8; + }; + bd->inbufBitCount -= hufGroup->maxLen; + j = (bd->inbufBits >> bd->inbufBitCount)& + ((1 << hufGroup->maxLen)-1); +got_huff_bits: + /* Figure how how many bits are in next symbol and + * unget extras */ + i = hufGroup->minLen; + while (j > limit[i]) + ++i; + bd->inbufBitCount += (hufGroup->maxLen - i); + /* Huffman decode value to get nextSym (with bounds checking) */ + if ((i > hufGroup->maxLen) + || (((unsigned)(j = (j>>(hufGroup->maxLen-i))-base[i])) + >= MAX_SYMBOLS)) + return RETVAL_DATA_ERROR; + nextSym = hufGroup->permute[j]; + /* We have now decoded the symbol, which indicates + either a new literal byte, or a repeated run of the + most recent literal byte. First, check if nextSym + indicates a repeated run, and if so loop collecting + how many times to repeat the last literal. */ + if (((unsigned)nextSym) <= SYMBOL_RUNB) { /* RUNA or RUNB */ + /* If this is the start of a new run, zero out + * counter */ + if (!runPos) { + runPos = 1; + t = 0; + } + /* Neat trick that saves 1 symbol: instead of + or-ing 0 or 1 at each bit position, add 1 + or 2 instead. For example, 1011 is 1 << 0 + + 1 << 1 + 2 << 2. 1010 is 2 << 0 + 2 << 1 + + 1 << 2. You can make any bit pattern + that way using 1 less symbol than the basic + or 0/1 method (except all bits 0, which + would use no symbols, but a run of length 0 + doesn't mean anything in this context). + Thus space is saved. */ + t += (runPos << nextSym); + /* +runPos if RUNA; +2*runPos if RUNB */ + + runPos <<= 1; + continue; + } + /* When we hit the first non-run symbol after a run, + we now know how many times to repeat the last + literal, so append that many copies to our buffer + of decoded symbols (dbuf) now. (The last literal + used is the one at the head of the mtfSymbol + array.) */ + if (runPos) { + runPos = 0; + if (dbufCount+t >= dbufSize) + return RETVAL_DATA_ERROR; + + uc = symToByte[mtfSymbol[0]]; + byteCount[uc] += t; + while (t--) + dbuf[dbufCount++] = uc; + } + /* Is this the terminating symbol? */ + if (nextSym > symTotal) + break; + /* At this point, nextSym indicates a new literal + character. Subtract one to get the position in the + MTF array at which this literal is currently to be + found. (Note that the result can't be -1 or 0, + because 0 and 1 are RUNA and RUNB. But another + instance of the first symbol in the mtf array, + position 0, would have been handled as part of a + run above. Therefore 1 unused mtf position minus 2 + non-literal nextSym values equals -1.) */ + if (dbufCount >= dbufSize) + return RETVAL_DATA_ERROR; + i = nextSym - 1; + uc = mtfSymbol[i]; + /* Adjust the MTF array. Since we typically expect to + *move only a small number of symbols, and are bound + *by 256 in any case, using memmove here would + *typically be bigger and slower due to function call + *overhead and other assorted setup costs. */ + do { + mtfSymbol[i] = mtfSymbol[i-1]; + } while (--i); + mtfSymbol[0] = uc; + uc = symToByte[uc]; + /* We have our literal byte. Save it into dbuf. */ + byteCount[uc]++; + dbuf[dbufCount++] = (unsigned int)uc; + } + /* At this point, we've read all the Huffman-coded symbols + (and repeated runs) for this block from the input stream, + and decoded them into the intermediate buffer. There are + dbufCount many decoded bytes in dbuf[]. Now undo the + Burrows-Wheeler transform on dbuf. See + http://dogma.net/markn/articles/bwt/bwt.htm + */ + /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ + j = 0; + for (i = 0; i < 256; i++) { + k = j+byteCount[i]; + byteCount[i] = j; + j = k; + } + /* Figure out what order dbuf would be in if we sorted it. */ + for (i = 0; i < dbufCount; i++) { + uc = (unsigned char)(dbuf[i] & 0xff); + dbuf[byteCount[uc]] |= (i << 8); + byteCount[uc]++; + } + /* Decode first byte by hand to initialize "previous" byte. + Note that it doesn't get output, and if the first three + characters are identical it doesn't qualify as a run (hence + writeRunCountdown = 5). */ + if (dbufCount) { + if (origPtr >= dbufCount) + return RETVAL_DATA_ERROR; + bd->writePos = dbuf[origPtr]; + bd->writeCurrent = (unsigned char)(bd->writePos&0xff); + bd->writePos >>= 8; + bd->writeRunCountdown = 5; + } + bd->writeCount = dbufCount; + + return RETVAL_OK; +} + +/* Undo burrows-wheeler transform on intermediate buffer to produce output. + If start_bunzip was initialized with out_fd =-1, then up to len bytes of + data are written to outbuf. Return value is number of bytes written or + error (all errors are negative numbers). If out_fd!=-1, outbuf and len + are ignored, data is written to out_fd and return is RETVAL_OK or error. +*/ + +static int read_bunzip(struct bunzip_data *bd, char *outbuf, int len) +{ + const unsigned int *dbuf; + int pos, xcurrent, previous, gotcount; + + /* If last read was short due to end of file, return last block now */ + if (bd->writeCount < 0) + return bd->writeCount; + + gotcount = 0; + dbuf = bd->dbuf; + pos = bd->writePos; + xcurrent = bd->writeCurrent; + + /* We will always have pending decoded data to write into the output + buffer unless this is the very first call (in which case we haven't + Huffman-decoded a block into the intermediate buffer yet). */ + + if (bd->writeCopies) { + /* Inside the loop, writeCopies means extra copies (beyond 1) */ + --bd->writeCopies; + /* Loop outputting bytes */ + for (;;) { + /* If the output buffer is full, snapshot + * state and return */ + if (gotcount >= len) { + bd->writePos = pos; + bd->writeCurrent = xcurrent; + bd->writeCopies++; + return len; + } + /* Write next byte into output buffer, updating CRC */ + outbuf[gotcount++] = xcurrent; + bd->writeCRC = (((bd->writeCRC) << 8) + ^bd->crc32Table[((bd->writeCRC) >> 24) + ^xcurrent]); + /* Loop now if we're outputting multiple + * copies of this byte */ + if (bd->writeCopies) { + --bd->writeCopies; + continue; + } +decode_next_byte: + if (!bd->writeCount--) + break; + /* Follow sequence vector to undo + * Burrows-Wheeler transform */ + previous = xcurrent; + pos = dbuf[pos]; + xcurrent = pos&0xff; + pos >>= 8; + /* After 3 consecutive copies of the same + byte, the 4th is a repeat count. We count + down from 4 instead *of counting up because + testing for non-zero is faster */ + if (--bd->writeRunCountdown) { + if (xcurrent != previous) + bd->writeRunCountdown = 4; + } else { + /* We have a repeated run, this byte + * indicates the count */ + bd->writeCopies = xcurrent; + xcurrent = previous; + bd->writeRunCountdown = 5; + /* Sometimes there are just 3 bytes + * (run length 0) */ + if (!bd->writeCopies) + goto decode_next_byte; + /* Subtract the 1 copy we'd output + * anyway to get extras */ + --bd->writeCopies; + } + } + /* Decompression of this block completed successfully */ + bd->writeCRC = ~bd->writeCRC; + bd->totalCRC = ((bd->totalCRC << 1) | + (bd->totalCRC >> 31)) ^ bd->writeCRC; + /* If this block had a CRC error, force file level CRC error. */ + if (bd->writeCRC != bd->headerCRC) { + bd->totalCRC = bd->headerCRC+1; + return RETVAL_LAST_BLOCK; + } + } + + /* Refill the intermediate buffer by Huffman-decoding next + * block of input */ + /* (previous is just a convenient unused temp variable here) */ + previous = get_next_block(bd); + if (previous) { + bd->writeCount = previous; + return (previous != RETVAL_LAST_BLOCK) ? previous : gotcount; + } + bd->writeCRC = 0xffffffffUL; + pos = bd->writePos; + xcurrent = bd->writeCurrent; + goto decode_next_byte; +} + +static int nofill(void *buf, unsigned int len) +{ + return -1; +} + +/* Allocate the structure, read file header. If in_fd ==-1, inbuf must contain + a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are + ignored, and data is read from file handle into temporary buffer. */ +static int start_bunzip(struct bunzip_data **bdp, void *inbuf, int len, + int (*fill)(void*, unsigned int)) +{ + struct bunzip_data *bd; + unsigned int i, j, c; + const unsigned int BZh0 = + (((unsigned int)'B') << 24)+(((unsigned int)'Z') << 16) + +(((unsigned int)'h') << 8)+(unsigned int)'0'; + + /* Figure out how much data to allocate */ + i = sizeof(struct bunzip_data); + + /* Allocate bunzip_data. Most fields initialize to zero. */ + bd = *bdp = malloc(i); + if (!bd) + return RETVAL_OUT_OF_MEMORY; + memset(bd, 0, sizeof(struct bunzip_data)); + /* Setup input buffer */ + bd->inbuf = inbuf; + bd->inbufCount = len; + if (fill != NULL) + bd->fill = fill; + else + bd->fill = nofill; + + /* Init the CRC32 table (big endian) */ + for (i = 0; i < 256; i++) { + c = i << 24; + for (j = 8; j; j--) + c = c&0x80000000 ? (c << 1)^0x04c11db7 : (c << 1); + bd->crc32Table[i] = c; + } + + /* Ensure that file starts with "BZh['1'-'9']." */ + i = get_bits(bd, 32); + if (((unsigned int)(i-BZh0-1)) >= 9) + return RETVAL_NOT_BZIP_DATA; + + /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of + uncompressed data. Allocate intermediate buffer for block. */ + bd->dbufSize = 100000*(i-BZh0); + + bd->dbuf = malloc(bd->dbufSize * sizeof(int)); + if (!bd->dbuf) + return RETVAL_OUT_OF_MEMORY; + return RETVAL_OK; +} + +/* Example usage: decompress src_fd to dst_fd. (Stops at end of bzip2 data, + not end of file.) */ +int bunzip2(unsigned char *buf, int len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *outbuf, + int *pos, + void(*error)(char *x)) +{ + struct bunzip_data *bd; + int i = -1; + unsigned char *inbuf; + + if (flush) + outbuf = malloc(BZIP2_IOBUF_SIZE); + + if (!outbuf) { + error("Could not allocate output bufer"); + return RETVAL_OUT_OF_MEMORY; + } + if (buf) + inbuf = buf; + else + inbuf = malloc(BZIP2_IOBUF_SIZE); + if (!inbuf) { + error("Could not allocate input bufer"); + i = RETVAL_OUT_OF_MEMORY; + goto exit_0; + } + i = start_bunzip(&bd, inbuf, len, fill); + if (!i) { + for (;;) { + i = read_bunzip(bd, outbuf, BZIP2_IOBUF_SIZE); + if (i <= 0) + break; + if (!flush) + outbuf += i; + else + if (i != flush(outbuf, i)) { + i = RETVAL_UNEXPECTED_OUTPUT_EOF; + break; + } + } + } + /* Check CRC and release memory */ + if (i == RETVAL_LAST_BLOCK) { + if (bd->headerCRC != bd->totalCRC) + error("Data integrity error when decompressing."); + else + i = RETVAL_OK; + } else if (i == RETVAL_UNEXPECTED_OUTPUT_EOF) { + error("Compressed file ends unexpectedly"); + } + if (!bd) + goto exit_1; + if (bd->dbuf) + free(bd->dbuf); + if (pos) + *pos = bd->inbufPos; + free(bd); +exit_1: + if (!buf) + free(inbuf); +exit_0: + if (flush) + free(outbuf); + return i; +} + +#ifdef PREBOOT +STATIC int INIT decompress(unsigned char *buf, int len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *outbuf, + int *pos, + void(*error)(char *x)) +{ + return bunzip2(buf, len - 4, fill, flush, outbuf, pos, error); +} +#endif -- cgit v1.2.3 From 15fcc719abbfe8f42057eeec275ce574ba2fbdd0 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 12:51:39 +0100 Subject: remove old bzlib Signed-off-by: Sascha Hauer --- include/bzlib.h | 329 ---------- lib/bzlib.c | 1592 ------------------------------------------------ lib/bzlib_crctable.c | 145 ----- lib/bzlib_decompress.c | 674 -------------------- lib/bzlib_huffman.c | 229 ------- lib/bzlib_randtable.c | 126 ---- 6 files changed, 3095 deletions(-) delete mode 100644 include/bzlib.h delete mode 100644 lib/bzlib.c delete mode 100644 lib/bzlib_crctable.c delete mode 100644 lib/bzlib_decompress.c delete mode 100644 lib/bzlib_huffman.c delete mode 100644 lib/bzlib_randtable.c diff --git a/include/bzlib.h b/include/bzlib.h deleted file mode 100644 index 4b0f820fed..0000000000 --- a/include/bzlib.h +++ /dev/null @@ -1,329 +0,0 @@ -/* - * This file is a modified version of bzlib.h from the bzip2-1.0.2 - * distribution which can be found at http://sources.redhat.com/bzip2/ - */ - -/*-------------------------------------------------------------*/ -/*--- Public header file for the library. ---*/ -/*--- bzlib.h ---*/ -/*-------------------------------------------------------------*/ - -/*-- - This file is a part of bzip2 and/or libbzip2, a program and - library for lossless, block-sorting data compression. - - Copyright (C) 1996-2002 Julian R Seward. 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. 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. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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. - - Julian Seward, Cambridge, UK. - jseward@acm.org - bzip2/libbzip2 version 1.0 of 21 March 2000 - - This program is based on (at least) the work of: - Mike Burrows - David Wheeler - Peter Fenwick - Alistair Moffat - Radford Neal - Ian H. Witten - Robert Sedgewick - Jon L. Bentley - - For more information on these sources, see the manual. ---*/ - - -#ifndef _BZLIB_H -#define _BZLIB_H - -/* Configure for barebox environment */ -#define BZ_NO_STDIO -#define BZ_NO_COMPRESS -/* End of configuration for barebox environment */ - -#ifdef __cplusplus -extern "C" { -#endif - -#define BZ_RUN 0 -#define BZ_FLUSH 1 -#define BZ_FINISH 2 - -#define BZ_OK 0 -#define BZ_RUN_OK 1 -#define BZ_FLUSH_OK 2 -#define BZ_FINISH_OK 3 -#define BZ_STREAM_END 4 -#define BZ_SEQUENCE_ERROR (-1) -#define BZ_PARAM_ERROR (-2) -#define BZ_MEM_ERROR (-3) -#define BZ_DATA_ERROR (-4) -#define BZ_DATA_ERROR_MAGIC (-5) -#define BZ_IO_ERROR (-6) -#define BZ_UNEXPECTED_EOF (-7) -#define BZ_OUTBUFF_FULL (-8) -#define BZ_CONFIG_ERROR (-9) - -typedef - struct { - char *next_in; - unsigned int avail_in; - unsigned int total_in_lo32; - unsigned int total_in_hi32; - - char *next_out; - unsigned int avail_out; - unsigned int total_out_lo32; - unsigned int total_out_hi32; - - void *state; - - void *(*bzalloc)(void *,int,int); - void (*bzfree)(void *,void *); - void *opaque; - } - bz_stream; - - -#ifndef BZ_IMPORT -#define BZ_EXPORT -#endif - -#ifdef _WIN32 -# include -# ifdef small - /* windows.h define small to char */ -# undef small -# endif -# ifdef BZ_EXPORT -# define BZ_API(func) WINAPI func -# define BZ_EXTERN extern -# else - /* import windows dll dynamically */ -# define BZ_API(func) (WINAPI * func) -# define BZ_EXTERN -# endif -#else -# define BZ_API(func) func -# define BZ_EXTERN extern -#endif - - -/*-- Core (low-level) library functions --*/ - -BZ_EXTERN int BZ_API(BZ2_bzCompressInit) ( - bz_stream* strm, - int blockSize100k, - int verbosity, - int workFactor - ); - -BZ_EXTERN int BZ_API(BZ2_bzCompress) ( - bz_stream* strm, - int action - ); - -BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) ( - bz_stream* strm - ); - -BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) ( - bz_stream *strm, - int verbosity, - int small - ); - -BZ_EXTERN int BZ_API(BZ2_bzDecompress) ( - bz_stream* strm - ); - -BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) ( - bz_stream *strm - ); - - -/*-- High(er) level library functions --*/ - -#ifndef BZ_NO_STDIO -#define BZ_MAX_UNUSED 5000 - -/* Need a definitition for FILE */ -#include - -typedef void BZFILE; - -BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) ( - int* bzerror, - FILE* f, - int verbosity, - int small, - void* unused, - int nUnused - ); - -BZ_EXTERN void BZ_API(BZ2_bzReadClose) ( - int* bzerror, - BZFILE* b - ); - -BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) ( - int* bzerror, - BZFILE* b, - void** unused, - int* nUnused - ); - -BZ_EXTERN int BZ_API(BZ2_bzRead) ( - int* bzerror, - BZFILE* b, - void* buf, - int len - ); - -BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) ( - int* bzerror, - FILE* f, - int blockSize100k, - int verbosity, - int workFactor - ); - -BZ_EXTERN void BZ_API(BZ2_bzWrite) ( - int* bzerror, - BZFILE* b, - void* buf, - int len - ); - -BZ_EXTERN void BZ_API(BZ2_bzWriteClose) ( - int* bzerror, - BZFILE* b, - int abandon, - unsigned int* nbytes_in, - unsigned int* nbytes_out - ); - -BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) ( - int* bzerror, - BZFILE* b, - int abandon, - unsigned int* nbytes_in_lo32, - unsigned int* nbytes_in_hi32, - unsigned int* nbytes_out_lo32, - unsigned int* nbytes_out_hi32 - ); -#endif - - -/*-- Utility functions --*/ - -BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) ( - char* dest, - unsigned int* destLen, - char* source, - unsigned int sourceLen, - int blockSize100k, - int verbosity, - int workFactor - ); - -BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) ( - char* dest, - unsigned int* destLen, - char* source, - unsigned int sourceLen, - int small, - int verbosity - ); - - -/*-- - Code contributed by Yoshioka Tsuneo - (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp), - to support better zlib compatibility. - This code is not _officially_ part of libbzip2 (yet); - I haven't tested it, documented it, or considered the - threading-safeness of it. - If this code breaks, please contact both Yoshioka and me. ---*/ - -BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) ( - void - ); - -#ifndef BZ_NO_STDIO -BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) ( - const char *path, - const char *mode - ); - -BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) ( - int fd, - const char *mode - ); - -BZ_EXTERN int BZ_API(BZ2_bzread) ( - BZFILE* b, - void* buf, - int len - ); - -BZ_EXTERN int BZ_API(BZ2_bzwrite) ( - BZFILE* b, - void* buf, - int len - ); - -BZ_EXTERN int BZ_API(BZ2_bzflush) ( - BZFILE* b - ); - -BZ_EXTERN void BZ_API(BZ2_bzclose) ( - BZFILE* b - ); - -BZ_EXTERN const char * BZ_API(BZ2_bzerror) ( - BZFILE *b, - int *errnum - ); -#endif - -#ifdef __cplusplus -} -#endif - -#endif - -/*-------------------------------------------------------------*/ -/*--- end bzlib.h ---*/ -/*-------------------------------------------------------------*/ diff --git a/lib/bzlib.c b/lib/bzlib.c deleted file mode 100644 index 4c928cadc8..0000000000 --- a/lib/bzlib.c +++ /dev/null @@ -1,1592 +0,0 @@ -#include -#include -#include - -/* - * This file is a modified version of bzlib.c from the bzip2-1.0.2 - * distribution which can be found at http://sources.redhat.com/bzip2/ - */ - -/*-------------------------------------------------------------*/ -/*--- Library top-level functions. ---*/ -/*--- bzlib.c ---*/ -/*-------------------------------------------------------------*/ - -/*-- - This file is a part of bzip2 and/or libbzip2, a program and - library for lossless, block-sorting data compression. - - Copyright (C) 1996-2002 Julian R Seward. 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. 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. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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. - - Julian Seward, Cambridge, UK. - jseward@acm.org - bzip2/libbzip2 version 1.0 of 21 March 2000 - - This program is based on (at least) the work of: - Mike Burrows - David Wheeler - Peter Fenwick - Alistair Moffat - Radford Neal - Ian H. Witten - Robert Sedgewick - Jon L. Bentley - - For more information on these sources, see the manual. ---*/ - -/*-- - CHANGES - ~~~~~~~ - 0.9.0 -- original version. - - 0.9.0a/b -- no changes in this file. - - 0.9.0c - * made zero-length BZ_FLUSH work correctly in bzCompress(). - * fixed bzWrite/bzRead to ignore zero-length requests. - * fixed bzread to correctly handle read requests after EOF. - * wrong parameter order in call to bzDecompressInit in - bzBuffToBuffDecompress. Fixed. ---*/ - -#include "bzlib_private.h" - -/*---------------------------------------------------*/ -/*--- Compression stuff ---*/ -/*---------------------------------------------------*/ - - -/*---------------------------------------------------*/ -#ifndef BZ_NO_STDIO -void BZ2_bz__AssertH__fail ( int errcode ) -{ - fprintf(stderr, - "\n\nbzip2/libbzip2: internal error number %d.\n" - "This is a bug in bzip2/libbzip2, %s.\n" - "Please report it to me at: jseward@acm.org. If this happened\n" - "when you were using some program which uses libbzip2 as a\n" - "component, you should also report this bug to the author(s)\n" - "of that program. Please make an effort to report this bug;\n" - "timely and accurate bug reports eventually lead to higher\n" - "quality software. Thanks. Julian Seward, 30 December 2001.\n\n", - errcode, - BZ2_bzlibVersion() - ); - - if (errcode == 1007) { - fprintf(stderr, - "\n*** A special note about internal error number 1007 ***\n" - "\n" - "Experience suggests that a common cause of i.e. 1007\n" - "is unreliable memory or other hardware. The 1007 assertion\n" - "just happens to cross-check the results of huge numbers of\n" - "memory reads/writes, and so acts (unintendedly) as a stress\n" - "test of your memory system.\n" - "\n" - "I suggest the following: try compressing the file again,\n" - "possibly monitoring progress in detail with the -vv flag.\n" - "\n" - "* If the error cannot be reproduced, and/or happens at different\n" - " points in compression, you may have a flaky memory system.\n" - " Try a memory-test program. I have used Memtest86\n" - " (www.memtest86.com). At the time of writing it is free (GPLd).\n" - " Memtest86 tests memory much more thorougly than your BIOSs\n" - " power-on test, and may find failures that the BIOS doesn't.\n" - "\n" - "* If the error can be repeatably reproduced, this is a bug in\n" - " bzip2, and I would very much like to hear about it. Please\n" - " let me know, and, ideally, save a copy of the file causing the\n" - " problem -- without which I will be unable to investigate it.\n" - "\n" - ); - } - - exit(3); -} -#endif - - -/*---------------------------------------------------*/ -static -int bz_config_ok ( void ) -{ - if (sizeof(int) != 4) return 0; - if (sizeof(short) != 2) return 0; - if (sizeof(char) != 1) return 0; - return 1; -} - - -/*---------------------------------------------------*/ -static -void* default_bzalloc ( void* opaque, Int32 items, Int32 size ) -{ - void* v = malloc ( items * size ); - return v; -} - -static -void default_bzfree ( void* opaque, void* addr ) -{ - if (addr != NULL) free ( addr ); -} - -#ifndef BZ_NO_COMPRESS -/*---------------------------------------------------*/ -static -void prepare_new_block ( EState* s ) -{ - Int32 i; - s->nblock = 0; - s->numZ = 0; - s->state_out_pos = 0; - BZ_INITIALISE_CRC ( s->blockCRC ); - for (i = 0; i < 256; i++) s->inUse[i] = False; - s->blockNo++; -} - - -/*---------------------------------------------------*/ -static -void init_RL ( EState* s ) -{ - s->state_in_ch = 256; - s->state_in_len = 0; -} - - -static -Bool isempty_RL ( EState* s ) -{ - if (s->state_in_ch < 256 && s->state_in_len > 0) - return False; else - return True; -} - -/*---------------------------------------------------*/ -int BZ_API(BZ2_bzCompressInit) - ( bz_stream* strm, - int blockSize100k, - int verbosity, - int workFactor ) -{ - Int32 n; - EState* s; - - if (!bz_config_ok()) return BZ_CONFIG_ERROR; - - if (strm == NULL || - blockSize100k < 1 || blockSize100k > 9 || - workFactor < 0 || workFactor > 250) - return BZ_PARAM_ERROR; - - if (workFactor == 0) workFactor = 30; - if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; - if (strm->bzfree == NULL) strm->bzfree = default_bzfree; - - s = BZALLOC( sizeof(EState) ); - if (s == NULL) return BZ_MEM_ERROR; - s->strm = strm; - - s->arr1 = NULL; - s->arr2 = NULL; - s->ftab = NULL; - - n = 100000 * blockSize100k; - s->arr1 = BZALLOC( n * sizeof(UInt32) ); - s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) ); - s->ftab = BZALLOC( 65537 * sizeof(UInt32) ); - - if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) { - if (s->arr1 != NULL) BZFREE(s->arr1); - if (s->arr2 != NULL) BZFREE(s->arr2); - if (s->ftab != NULL) BZFREE(s->ftab); - if (s != NULL) BZFREE(s); - return BZ_MEM_ERROR; - } - - s->blockNo = 0; - s->state = BZ_S_INPUT; - s->mode = BZ_M_RUNNING; - s->combinedCRC = 0; - s->blockSize100k = blockSize100k; - s->nblockMAX = 100000 * blockSize100k - 19; - s->verbosity = verbosity; - s->workFactor = workFactor; - - s->block = (UChar*)s->arr2; - s->mtfv = (UInt16*)s->arr1; - s->zbits = NULL; - s->ptr = (UInt32*)s->arr1; - - strm->state = s; - strm->total_in_lo32 = 0; - strm->total_in_hi32 = 0; - strm->total_out_lo32 = 0; - strm->total_out_hi32 = 0; - init_RL ( s ); - prepare_new_block ( s ); - return BZ_OK; -} - - -/*---------------------------------------------------*/ -static -void add_pair_to_block ( EState* s ) -{ - Int32 i; - UChar ch = (UChar)(s->state_in_ch); - for (i = 0; i < s->state_in_len; i++) { - BZ_UPDATE_CRC( s->blockCRC, ch ); - } - s->inUse[s->state_in_ch] = True; - switch (s->state_in_len) { - case 1: - s->block[s->nblock] = (UChar)ch; s->nblock++; - break; - case 2: - s->block[s->nblock] = (UChar)ch; s->nblock++; - s->block[s->nblock] = (UChar)ch; s->nblock++; - break; - case 3: - s->block[s->nblock] = (UChar)ch; s->nblock++; - s->block[s->nblock] = (UChar)ch; s->nblock++; - s->block[s->nblock] = (UChar)ch; s->nblock++; - break; - default: - s->inUse[s->state_in_len-4] = True; - s->block[s->nblock] = (UChar)ch; s->nblock++; - s->block[s->nblock] = (UChar)ch; s->nblock++; - s->block[s->nblock] = (UChar)ch; s->nblock++; - s->block[s->nblock] = (UChar)ch; s->nblock++; - s->block[s->nblock] = ((UChar)(s->state_in_len-4)); - s->nblock++; - break; - } -} - - -/*---------------------------------------------------*/ -static -void flush_RL ( EState* s ) -{ - if (s->state_in_ch < 256) add_pair_to_block ( s ); - init_RL ( s ); -} - - -/*---------------------------------------------------*/ -#define ADD_CHAR_TO_BLOCK(zs,zchh0) \ -{ \ - UInt32 zchh = (UInt32)(zchh0); \ - /*-- fast track the common case --*/ \ - if (zchh != zs->state_in_ch && \ - zs->state_in_len == 1) { \ - UChar ch = (UChar)(zs->state_in_ch); \ - BZ_UPDATE_CRC( zs->blockCRC, ch ); \ - zs->inUse[zs->state_in_ch] = True; \ - zs->block[zs->nblock] = (UChar)ch; \ - zs->nblock++; \ - zs->state_in_ch = zchh; \ - } \ - else \ - /*-- general, uncommon cases --*/ \ - if (zchh != zs->state_in_ch || \ - zs->state_in_len == 255) { \ - if (zs->state_in_ch < 256) \ - add_pair_to_block ( zs ); \ - zs->state_in_ch = zchh; \ - zs->state_in_len = 1; \ - } else { \ - zs->state_in_len++; \ - } \ -} - - -/*---------------------------------------------------*/ -static -Bool copy_input_until_stop ( EState* s ) -{ - Bool progress_in = False; - - if (s->mode == BZ_M_RUNNING) { - - /*-- fast track the common case --*/ - while (True) { - /*-- block full? --*/ - if (s->nblock >= s->nblockMAX) break; - /*-- no input? --*/ - if (s->strm->avail_in == 0) break; - progress_in = True; - ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); - s->strm->next_in++; - s->strm->avail_in--; - s->strm->total_in_lo32++; - if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; - } - - } else { - - /*-- general, uncommon case --*/ - while (True) { - /*-- block full? --*/ - if (s->nblock >= s->nblockMAX) break; - /*-- no input? --*/ - if (s->strm->avail_in == 0) break; - /*-- flush/finish end? --*/ - if (s->avail_in_expect == 0) break; - progress_in = True; - ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); - s->strm->next_in++; - s->strm->avail_in--; - s->strm->total_in_lo32++; - if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; - s->avail_in_expect--; - } - } - return progress_in; -} - - -/*---------------------------------------------------*/ -static -Bool copy_output_until_stop ( EState* s ) -{ - Bool progress_out = False; - - while (True) { - - /*-- no output space? --*/ - if (s->strm->avail_out == 0) break; - - /*-- block done? --*/ - if (s->state_out_pos >= s->numZ) break; - - progress_out = True; - *(s->strm->next_out) = s->zbits[s->state_out_pos]; - s->state_out_pos++; - s->strm->avail_out--; - s->strm->next_out++; - s->strm->total_out_lo32++; - if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; - } - - return progress_out; -} - - -/*---------------------------------------------------*/ -static -Bool handle_compress ( bz_stream* strm ) -{ - Bool progress_in = False; - Bool progress_out = False; - EState* s = strm->state; - - while (True) { - - if (s->state == BZ_S_OUTPUT) { - progress_out |= copy_output_until_stop ( s ); - if (s->state_out_pos < s->numZ) break; - if (s->mode == BZ_M_FINISHING && - s->avail_in_expect == 0 && - isempty_RL(s)) break; - prepare_new_block ( s ); - s->state = BZ_S_INPUT; - if (s->mode == BZ_M_FLUSHING && - s->avail_in_expect == 0 && - isempty_RL(s)) break; - } - - if (s->state == BZ_S_INPUT) { - progress_in |= copy_input_until_stop ( s ); - if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) { - flush_RL ( s ); - BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) ); - s->state = BZ_S_OUTPUT; - } - else - if (s->nblock >= s->nblockMAX) { - BZ2_compressBlock ( s, False ); - s->state = BZ_S_OUTPUT; - } - else - if (s->strm->avail_in == 0) { - break; - } - } - - } - - return progress_in || progress_out; -} - - -/*---------------------------------------------------*/ -int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action ) -{ - Bool progress; - EState* s; - if (strm == NULL) return BZ_PARAM_ERROR; - s = strm->state; - if (s == NULL) return BZ_PARAM_ERROR; - if (s->strm != strm) return BZ_PARAM_ERROR; - - preswitch: - switch (s->mode) { - - case BZ_M_IDLE: - return BZ_SEQUENCE_ERROR; - - case BZ_M_RUNNING: - if (action == BZ_RUN) { - progress = handle_compress ( strm ); - return progress ? BZ_RUN_OK : BZ_PARAM_ERROR; - } - else - if (action == BZ_FLUSH) { - s->avail_in_expect = strm->avail_in; - s->mode = BZ_M_FLUSHING; - goto preswitch; - } - else - if (action == BZ_FINISH) { - s->avail_in_expect = strm->avail_in; - s->mode = BZ_M_FINISHING; - goto preswitch; - } - else - return BZ_PARAM_ERROR; - - case BZ_M_FLUSHING: - if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR; - if (s->avail_in_expect != s->strm->avail_in) - return BZ_SEQUENCE_ERROR; - progress = handle_compress ( strm ); - if (s->avail_in_expect > 0 || !isempty_RL(s) || - s->state_out_pos < s->numZ) return BZ_FLUSH_OK; - s->mode = BZ_M_RUNNING; - return BZ_RUN_OK; - - case BZ_M_FINISHING: - if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR; - if (s->avail_in_expect != s->strm->avail_in) - return BZ_SEQUENCE_ERROR; - progress = handle_compress ( strm ); - if (!progress) return BZ_SEQUENCE_ERROR; - if (s->avail_in_expect > 0 || !isempty_RL(s) || - s->state_out_pos < s->numZ) return BZ_FINISH_OK; - s->mode = BZ_M_IDLE; - return BZ_STREAM_END; - } - return BZ_OK; /*--not reached--*/ -} - - -/*---------------------------------------------------*/ -int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm ) -{ - EState* s; - if (strm == NULL) return BZ_PARAM_ERROR; - s = strm->state; - if (s == NULL) return BZ_PARAM_ERROR; - if (s->strm != strm) return BZ_PARAM_ERROR; - - if (s->arr1 != NULL) BZFREE(s->arr1); - if (s->arr2 != NULL) BZFREE(s->arr2); - if (s->ftab != NULL) BZFREE(s->ftab); - BZFREE(strm->state); - - strm->state = NULL; - - return BZ_OK; -} -#endif /* BZ_NO_COMPRESS */ - -/*---------------------------------------------------*/ -/*--- Decompression stuff ---*/ -/*---------------------------------------------------*/ - -/*---------------------------------------------------*/ -int BZ_API(BZ2_bzDecompressInit) - ( bz_stream* strm, - int verbosity, - int small ) -{ - DState* s; - - if (!bz_config_ok()) return BZ_CONFIG_ERROR; - - if (strm == NULL) return BZ_PARAM_ERROR; - if (small != 0 && small != 1) return BZ_PARAM_ERROR; - if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR; - - if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; - if (strm->bzfree == NULL) strm->bzfree = default_bzfree; - - s = BZALLOC( sizeof(DState) ); - if (s == NULL) return BZ_MEM_ERROR; - s->strm = strm; - strm->state = s; - s->state = BZ_X_MAGIC_1; - s->bsLive = 0; - s->bsBuff = 0; - s->calculatedCombinedCRC = 0; - strm->total_in_lo32 = 0; - strm->total_in_hi32 = 0; - strm->total_out_lo32 = 0; - strm->total_out_hi32 = 0; - s->smallDecompress = (Bool)small; - s->ll4 = NULL; - s->ll16 = NULL; - s->tt = NULL; - s->currBlockNo = 0; - s->verbosity = verbosity; - - return BZ_OK; -} - - -/*---------------------------------------------------*/ -static -void unRLE_obuf_to_output_FAST ( DState* s ) -{ - UChar k1; - - if (s->blockRandomised) { - - while (True) { - /* try to finish existing run */ - while (True) { - if (s->strm->avail_out == 0) return; - if (s->state_out_len == 0) break; - *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; - BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); - s->state_out_len--; - s->strm->next_out++; - s->strm->avail_out--; - s->strm->total_out_lo32++; - if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; - } - - /* can a new run be started? */ - if (s->nblock_used == s->save_nblock+1) return; - - - s->state_out_len = 1; - s->state_out_ch = s->k0; - BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; - k1 ^= BZ_RAND_MASK; s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) continue; - if (k1 != s->k0) { s->k0 = k1; continue; }; - - s->state_out_len = 2; - BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; - k1 ^= BZ_RAND_MASK; s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) continue; - if (k1 != s->k0) { s->k0 = k1; continue; }; - - s->state_out_len = 3; - BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; - k1 ^= BZ_RAND_MASK; s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) continue; - if (k1 != s->k0) { s->k0 = k1; continue; }; - - BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; - k1 ^= BZ_RAND_MASK; s->nblock_used++; - s->state_out_len = ((Int32)k1) + 4; - BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; - s->k0 ^= BZ_RAND_MASK; s->nblock_used++; - } - - } else { - - /* restore */ - UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC; - UChar c_state_out_ch = s->state_out_ch; - Int32 c_state_out_len = s->state_out_len; - Int32 c_nblock_used = s->nblock_used; - Int32 c_k0 = s->k0; - UInt32* c_tt = s->tt; - UInt32 c_tPos = s->tPos; - char* cs_next_out = s->strm->next_out; - unsigned int cs_avail_out = s->strm->avail_out; - /* end restore */ - - UInt32 avail_out_INIT = cs_avail_out; - Int32 s_save_nblockPP = s->save_nblock+1; - unsigned int total_out_lo32_old; - - while (True) { - - /* try to finish existing run */ - if (c_state_out_len > 0) { - while (True) { - if (cs_avail_out == 0) goto return_notr; - if (c_state_out_len == 1) break; - *( (UChar*)(cs_next_out) ) = c_state_out_ch; - BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); - c_state_out_len--; - cs_next_out++; - cs_avail_out--; - } - s_state_out_len_eq_one: - { - if (cs_avail_out == 0) { - c_state_out_len = 1; goto return_notr; - }; - *( (UChar*)(cs_next_out) ) = c_state_out_ch; - BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); - cs_next_out++; - cs_avail_out--; - } - } - /* can a new run be started? */ - if (c_nblock_used == s_save_nblockPP) { - c_state_out_len = 0; goto return_notr; - }; - c_state_out_ch = c_k0; - BZ_GET_FAST_C(k1); c_nblock_used++; - if (k1 != c_k0) { - c_k0 = k1; goto s_state_out_len_eq_one; - }; - if (c_nblock_used == s_save_nblockPP) - goto s_state_out_len_eq_one; - - c_state_out_len = 2; - BZ_GET_FAST_C(k1); c_nblock_used++; - if (c_nblock_used == s_save_nblockPP) continue; - if (k1 != c_k0) { c_k0 = k1; continue; }; - - c_state_out_len = 3; - BZ_GET_FAST_C(k1); c_nblock_used++; - if (c_nblock_used == s_save_nblockPP) continue; - if (k1 != c_k0) { c_k0 = k1; continue; }; - - BZ_GET_FAST_C(k1); c_nblock_used++; - c_state_out_len = ((Int32)k1) + 4; - BZ_GET_FAST_C(c_k0); c_nblock_used++; - } - - return_notr: - total_out_lo32_old = s->strm->total_out_lo32; - s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out); - if (s->strm->total_out_lo32 < total_out_lo32_old) - s->strm->total_out_hi32++; - - /* save */ - s->calculatedBlockCRC = c_calculatedBlockCRC; - s->state_out_ch = c_state_out_ch; - s->state_out_len = c_state_out_len; - s->nblock_used = c_nblock_used; - s->k0 = c_k0; - s->tt = c_tt; - s->tPos = c_tPos; - s->strm->next_out = cs_next_out; - s->strm->avail_out = cs_avail_out; - /* end save */ - } -} - - -/*---------------------------------------------------*/ -__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab ) -{ - Int32 nb, na, mid; - nb = 0; - na = 256; - do { - mid = (nb + na) >> 1; - if (indx >= cftab[mid]) nb = mid; else na = mid; - } - while (na - nb != 1); - return nb; -} - - -/*---------------------------------------------------*/ -static -void unRLE_obuf_to_output_SMALL ( DState* s ) -{ - UChar k1; - - if (s->blockRandomised) { - - while (True) { - /* try to finish existing run */ - while (True) { - if (s->strm->avail_out == 0) return; - if (s->state_out_len == 0) break; - *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; - BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); - s->state_out_len--; - s->strm->next_out++; - s->strm->avail_out--; - s->strm->total_out_lo32++; - if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; - } - - /* can a new run be started? */ - if (s->nblock_used == s->save_nblock+1) return; - - - s->state_out_len = 1; - s->state_out_ch = s->k0; - BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; - k1 ^= BZ_RAND_MASK; s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) continue; - if (k1 != s->k0) { s->k0 = k1; continue; }; - - s->state_out_len = 2; - BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; - k1 ^= BZ_RAND_MASK; s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) continue; - if (k1 != s->k0) { s->k0 = k1; continue; }; - - s->state_out_len = 3; - BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; - k1 ^= BZ_RAND_MASK; s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) continue; - if (k1 != s->k0) { s->k0 = k1; continue; }; - - BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; - k1 ^= BZ_RAND_MASK; s->nblock_used++; - s->state_out_len = ((Int32)k1) + 4; - BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; - s->k0 ^= BZ_RAND_MASK; s->nblock_used++; - } - - } else { - - while (True) { - /* try to finish existing run */ - while (True) { - if (s->strm->avail_out == 0) return; - if (s->state_out_len == 0) break; - *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; - BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); - s->state_out_len--; - s->strm->next_out++; - s->strm->avail_out--; - s->strm->total_out_lo32++; - if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; - } - - /* can a new run be started? */ - if (s->nblock_used == s->save_nblock+1) return; - - s->state_out_len = 1; - s->state_out_ch = s->k0; - BZ_GET_SMALL(k1); s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) continue; - if (k1 != s->k0) { s->k0 = k1; continue; }; - - s->state_out_len = 2; - BZ_GET_SMALL(k1); s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) continue; - if (k1 != s->k0) { s->k0 = k1; continue; }; - - s->state_out_len = 3; - BZ_GET_SMALL(k1); s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) continue; - if (k1 != s->k0) { s->k0 = k1; continue; }; - - BZ_GET_SMALL(k1); s->nblock_used++; - s->state_out_len = ((Int32)k1) + 4; - BZ_GET_SMALL(s->k0); s->nblock_used++; - } - - } -} - - -/*---------------------------------------------------*/ -int BZ_API(BZ2_bzDecompress) ( bz_stream *strm ) -{ - DState* s; - if (strm == NULL) return BZ_PARAM_ERROR; - s = strm->state; - if (s == NULL) return BZ_PARAM_ERROR; - if (s->strm != strm) return BZ_PARAM_ERROR; - - while (True) { -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - WATCHDOG_RESET(); -#endif - if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR; - if (s->state == BZ_X_OUTPUT) { - if (s->smallDecompress) - unRLE_obuf_to_output_SMALL ( s ); else - unRLE_obuf_to_output_FAST ( s ); - if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) { - BZ_FINALISE_CRC ( s->calculatedBlockCRC ); - if (s->verbosity >= 3) - VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC, - s->calculatedBlockCRC ); - if (s->verbosity >= 2) VPrintf0 ( "]" ); - if (s->calculatedBlockCRC != s->storedBlockCRC) - return BZ_DATA_ERROR; - s->calculatedCombinedCRC - = (s->calculatedCombinedCRC << 1) | - (s->calculatedCombinedCRC >> 31); - s->calculatedCombinedCRC ^= s->calculatedBlockCRC; - s->state = BZ_X_BLKHDR_1; - } else { - return BZ_OK; - } - } - if (s->state >= BZ_X_MAGIC_1) { - Int32 r = BZ2_decompress ( s ); - if (r == BZ_STREAM_END) { - if (s->verbosity >= 3) - VPrintf2 ( "\n combined CRCs: stored = 0x%x, computed = 0x%x", - s->storedCombinedCRC, s->calculatedCombinedCRC ); - if (s->calculatedCombinedCRC != s->storedCombinedCRC) - return BZ_DATA_ERROR; - return r; - } - if (s->state != BZ_X_OUTPUT) return r; - } - } - - AssertH ( 0, 6001 ); - - return 0; /*NOTREACHED*/ -} - - -/*---------------------------------------------------*/ -int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm ) -{ - DState* s; - if (strm == NULL) return BZ_PARAM_ERROR; - s = strm->state; - if (s == NULL) return BZ_PARAM_ERROR; - if (s->strm != strm) return BZ_PARAM_ERROR; - - if (s->tt != NULL) BZFREE(s->tt); - if (s->ll16 != NULL) BZFREE(s->ll16); - if (s->ll4 != NULL) BZFREE(s->ll4); - - BZFREE(strm->state); - strm->state = NULL; - - return BZ_OK; -} - - -#ifndef BZ_NO_STDIO -/*---------------------------------------------------*/ -/*--- File I/O stuff ---*/ -/*---------------------------------------------------*/ - -#define BZ_SETERR(eee) \ -{ \ - if (bzerror != NULL) *bzerror = eee; \ - if (bzf != NULL) bzf->lastErr = eee; \ -} - -typedef - struct { - FILE* handle; - Char buf[BZ_MAX_UNUSED]; - Int32 bufN; - Bool writing; - bz_stream strm; - Int32 lastErr; - Bool initialisedOk; - } - bzFile; - - -/*---------------------------------------------*/ -static Bool myfeof ( FILE* f ) -{ - Int32 c = fgetc ( f ); - if (c == EOF) return True; - ungetc ( c, f ); - return False; -} - - -/*---------------------------------------------------*/ -BZFILE* BZ_API(BZ2_bzWriteOpen) - ( int* bzerror, - FILE* f, - int blockSize100k, - int verbosity, - int workFactor ) -{ - Int32 ret; - bzFile* bzf = NULL; - - BZ_SETERR(BZ_OK); - - if (f == NULL || - (blockSize100k < 1 || blockSize100k > 9) || - (workFactor < 0 || workFactor > 250) || - (verbosity < 0 || verbosity > 4)) - { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; - - if (ferror(f)) - { BZ_SETERR(BZ_IO_ERROR); return NULL; }; - - bzf = malloc ( sizeof(bzFile) ); - if (bzf == NULL) - { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; - - BZ_SETERR(BZ_OK); - bzf->initialisedOk = False; - bzf->bufN = 0; - bzf->handle = f; - bzf->writing = True; - bzf->strm.bzalloc = NULL; - bzf->strm.bzfree = NULL; - bzf->strm.opaque = NULL; - - if (workFactor == 0) workFactor = 30; - ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, - verbosity, workFactor ); - if (ret != BZ_OK) - { BZ_SETERR(ret); free(bzf); return NULL; }; - - bzf->strm.avail_in = 0; - bzf->initialisedOk = True; - return bzf; -} - - -/*---------------------------------------------------*/ -void BZ_API(BZ2_bzWrite) - ( int* bzerror, - BZFILE* b, - void* buf, - int len ) -{ - Int32 n, n2, ret; - bzFile* bzf = (bzFile*)b; - - BZ_SETERR(BZ_OK); - if (bzf == NULL || buf == NULL || len < 0) - { BZ_SETERR(BZ_PARAM_ERROR); return; }; - if (!(bzf->writing)) - { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; - if (ferror(bzf->handle)) - { BZ_SETERR(BZ_IO_ERROR); return; }; - - if (len == 0) - { BZ_SETERR(BZ_OK); return; }; - - bzf->strm.avail_in = len; - bzf->strm.next_in = buf; - - while (True) { - bzf->strm.avail_out = BZ_MAX_UNUSED; - bzf->strm.next_out = bzf->buf; - ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN ); - if (ret != BZ_RUN_OK) - { BZ_SETERR(ret); return; }; - - if (bzf->strm.avail_out < BZ_MAX_UNUSED) { - n = BZ_MAX_UNUSED - bzf->strm.avail_out; - n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), - n, bzf->handle ); - if (n != n2 || ferror(bzf->handle)) - { BZ_SETERR(BZ_IO_ERROR); return; }; - } - - if (bzf->strm.avail_in == 0) - { BZ_SETERR(BZ_OK); return; }; - } -} - - -/*---------------------------------------------------*/ -void BZ_API(BZ2_bzWriteClose) - ( int* bzerror, - BZFILE* b, - int abandon, - unsigned int* nbytes_in, - unsigned int* nbytes_out ) -{ - BZ2_bzWriteClose64 ( bzerror, b, abandon, - nbytes_in, NULL, nbytes_out, NULL ); -} - - -void BZ_API(BZ2_bzWriteClose64) - ( int* bzerror, - BZFILE* b, - int abandon, - unsigned int* nbytes_in_lo32, - unsigned int* nbytes_in_hi32, - unsigned int* nbytes_out_lo32, - unsigned int* nbytes_out_hi32 ) -{ - Int32 n, n2, ret; - bzFile* bzf = (bzFile*)b; - - if (bzf == NULL) - { BZ_SETERR(BZ_OK); return; }; - if (!(bzf->writing)) - { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; - if (ferror(bzf->handle)) - { BZ_SETERR(BZ_IO_ERROR); return; }; - - if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0; - if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0; - if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0; - if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0; - - if ((!abandon) && bzf->lastErr == BZ_OK) { - while (True) { - bzf->strm.avail_out = BZ_MAX_UNUSED; - bzf->strm.next_out = bzf->buf; - ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH ); - if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END) - { BZ_SETERR(ret); return; }; - - if (bzf->strm.avail_out < BZ_MAX_UNUSED) { - n = BZ_MAX_UNUSED - bzf->strm.avail_out; - n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), - n, bzf->handle ); - if (n != n2 || ferror(bzf->handle)) - { BZ_SETERR(BZ_IO_ERROR); return; }; - } - - if (ret == BZ_STREAM_END) break; - } - } - - if ( !abandon && !ferror ( bzf->handle ) ) { - fflush ( bzf->handle ); - if (ferror(bzf->handle)) - { BZ_SETERR(BZ_IO_ERROR); return; }; - } - - if (nbytes_in_lo32 != NULL) - *nbytes_in_lo32 = bzf->strm.total_in_lo32; - if (nbytes_in_hi32 != NULL) - *nbytes_in_hi32 = bzf->strm.total_in_hi32; - if (nbytes_out_lo32 != NULL) - *nbytes_out_lo32 = bzf->strm.total_out_lo32; - if (nbytes_out_hi32 != NULL) - *nbytes_out_hi32 = bzf->strm.total_out_hi32; - - BZ_SETERR(BZ_OK); - BZ2_bzCompressEnd ( &(bzf->strm) ); - free ( bzf ); -} - - -/*---------------------------------------------------*/ -BZFILE* BZ_API(BZ2_bzReadOpen) - ( int* bzerror, - FILE* f, - int verbosity, - int small, - void* unused, - int nUnused ) -{ - bzFile* bzf = NULL; - int ret; - - BZ_SETERR(BZ_OK); - - if (f == NULL || - (small != 0 && small != 1) || - (verbosity < 0 || verbosity > 4) || - (unused == NULL && nUnused != 0) || - (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED))) - { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; - - if (ferror(f)) - { BZ_SETERR(BZ_IO_ERROR); return NULL; }; - - bzf = malloc ( sizeof(bzFile) ); - if (bzf == NULL) - { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; - - BZ_SETERR(BZ_OK); - - bzf->initialisedOk = False; - bzf->handle = f; - bzf->bufN = 0; - bzf->writing = False; - bzf->strm.bzalloc = NULL; - bzf->strm.bzfree = NULL; - bzf->strm.opaque = NULL; - - while (nUnused > 0) { - bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++; - unused = ((void*)( 1 + ((UChar*)(unused)) )); - nUnused--; - } - - ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small ); - if (ret != BZ_OK) - { BZ_SETERR(ret); free(bzf); return NULL; }; - - bzf->strm.avail_in = bzf->bufN; - bzf->strm.next_in = bzf->buf; - - bzf->initialisedOk = True; - return bzf; -} - - -/*---------------------------------------------------*/ -void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b ) -{ - bzFile* bzf = (bzFile*)b; - - BZ_SETERR(BZ_OK); - if (bzf == NULL) - { BZ_SETERR(BZ_OK); return; }; - - if (bzf->writing) - { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; - - if (bzf->initialisedOk) - (void)BZ2_bzDecompressEnd ( &(bzf->strm) ); - free ( bzf ); -} - - -/*---------------------------------------------------*/ -int BZ_API(BZ2_bzRead) - ( int* bzerror, - BZFILE* b, - void* buf, - int len ) -{ - Int32 n, ret; - bzFile* bzf = (bzFile*)b; - - BZ_SETERR(BZ_OK); - - if (bzf == NULL || buf == NULL || len < 0) - { BZ_SETERR(BZ_PARAM_ERROR); return 0; }; - - if (bzf->writing) - { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; }; - - if (len == 0) - { BZ_SETERR(BZ_OK); return 0; }; - - bzf->strm.avail_out = len; - bzf->strm.next_out = buf; - - while (True) { - - if (ferror(bzf->handle)) - { BZ_SETERR(BZ_IO_ERROR); return 0; }; - - if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) { - n = fread ( bzf->buf, sizeof(UChar), - BZ_MAX_UNUSED, bzf->handle ); - if (ferror(bzf->handle)) - { BZ_SETERR(BZ_IO_ERROR); return 0; }; - bzf->bufN = n; - bzf->strm.avail_in = bzf->bufN; - bzf->strm.next_in = bzf->buf; - } - - ret = BZ2_bzDecompress ( &(bzf->strm) ); - - if (ret != BZ_OK && ret != BZ_STREAM_END) - { BZ_SETERR(ret); return 0; }; - - if (ret == BZ_OK && myfeof(bzf->handle) && - bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0) - { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; }; - - if (ret == BZ_STREAM_END) - { BZ_SETERR(BZ_STREAM_END); - return len - bzf->strm.avail_out; }; - if (bzf->strm.avail_out == 0) - { BZ_SETERR(BZ_OK); return len; }; - - } - - return 0; /*not reached*/ -} - - -/*---------------------------------------------------*/ -void BZ_API(BZ2_bzReadGetUnused) - ( int* bzerror, - BZFILE* b, - void** unused, - int* nUnused ) -{ - bzFile* bzf = (bzFile*)b; - if (bzf == NULL) - { BZ_SETERR(BZ_PARAM_ERROR); return; }; - if (bzf->lastErr != BZ_STREAM_END) - { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; - if (unused == NULL || nUnused == NULL) - { BZ_SETERR(BZ_PARAM_ERROR); return; }; - - BZ_SETERR(BZ_OK); - *nUnused = bzf->strm.avail_in; - *unused = bzf->strm.next_in; -} -#endif - - -/*---------------------------------------------------*/ -/*--- Misc convenience stuff ---*/ -/*---------------------------------------------------*/ -#ifndef BZ_NO_COMPRESS -/*---------------------------------------------------*/ -int BZ_API(BZ2_bzBuffToBuffCompress) - ( char* dest, - unsigned int* destLen, - char* source, - unsigned int sourceLen, - int blockSize100k, - int verbosity, - int workFactor ) -{ - bz_stream strm; - int ret; - - if (dest == NULL || destLen == NULL || - source == NULL || - blockSize100k < 1 || blockSize100k > 9 || - verbosity < 0 || verbosity > 4 || - workFactor < 0 || workFactor > 250) - return BZ_PARAM_ERROR; - - if (workFactor == 0) workFactor = 30; - strm.bzalloc = NULL; - strm.bzfree = NULL; - strm.opaque = NULL; - ret = BZ2_bzCompressInit ( &strm, blockSize100k, - verbosity, workFactor ); - if (ret != BZ_OK) return ret; - - strm.next_in = source; - strm.next_out = dest; - strm.avail_in = sourceLen; - strm.avail_out = *destLen; - - ret = BZ2_bzCompress ( &strm, BZ_FINISH ); - if (ret == BZ_FINISH_OK) goto output_overflow; - if (ret != BZ_STREAM_END) goto errhandler; - - /* normal termination */ - *destLen -= strm.avail_out; - BZ2_bzCompressEnd ( &strm ); - return BZ_OK; - - output_overflow: - BZ2_bzCompressEnd ( &strm ); - return BZ_OUTBUFF_FULL; - - errhandler: - BZ2_bzCompressEnd ( &strm ); - return ret; -} -#endif /* BZ_NO_COMPRESS */ - -/*---------------------------------------------------*/ -int BZ_API(BZ2_bzBuffToBuffDecompress) - ( char* dest, - unsigned int* destLen, - char* source, - unsigned int sourceLen, - int small, - int verbosity ) -{ - bz_stream strm; - int ret; - - if (destLen == NULL || source == NULL) - return BZ_PARAM_ERROR; - - strm.bzalloc = NULL; - strm.bzfree = NULL; - strm.opaque = NULL; - ret = BZ2_bzDecompressInit ( &strm, verbosity, small ); - if (ret != BZ_OK) return ret; - - strm.next_in = source; - strm.next_out = dest; - strm.avail_in = sourceLen; - strm.avail_out = *destLen; - - ret = BZ2_bzDecompress ( &strm ); - if (ret == BZ_OK) goto output_overflow_or_eof; - if (ret != BZ_STREAM_END) goto errhandler; - - /* normal termination */ - *destLen -= strm.avail_out; - BZ2_bzDecompressEnd ( &strm ); - return BZ_OK; - - output_overflow_or_eof: - if (strm.avail_out > 0) { - BZ2_bzDecompressEnd ( &strm ); - return BZ_UNEXPECTED_EOF; - } else { - BZ2_bzDecompressEnd ( &strm ); - return BZ_OUTBUFF_FULL; - }; - - errhandler: - BZ2_bzDecompressEnd ( &strm ); - return ret; -} - - -/*---------------------------------------------------*/ -/*-- - Code contributed by Yoshioka Tsuneo - (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp), - to support better zlib compatibility. - This code is not _officially_ part of libbzip2 (yet); - I haven't tested it, documented it, or considered the - threading-safeness of it. - If this code breaks, please contact both Yoshioka and me. ---*/ -/*---------------------------------------------------*/ - -/*---------------------------------------------------*/ -/*-- - return version like "0.9.0c". ---*/ -const char * BZ_API(BZ2_bzlibVersion)(void) -{ - return BZ_VERSION; -} - - -#ifndef BZ_NO_STDIO -/*---------------------------------------------------*/ - -#if defined(_WIN32) || defined(OS2) || defined(MSDOS) -# include -# include -# define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) -#else -# define SET_BINARY_MODE(file) -#endif -static -BZFILE * bzopen_or_bzdopen - ( const char *path, /* no use when bzdopen */ - int fd, /* no use when bzdopen */ - const char *mode, - int open_mode) /* bzopen: 0, bzdopen:1 */ -{ - int bzerr; - char unused[BZ_MAX_UNUSED]; - int blockSize100k = 9; - int writing = 0; - char mode2[10] = ""; - FILE *fp = NULL; - BZFILE *bzfp = NULL; - int verbosity = 0; - int workFactor = 30; - int smallMode = 0; - int nUnused = 0; - - if (mode == NULL) return NULL; - while (*mode) { - switch (*mode) { - case 'r': - writing = 0; break; - case 'w': - writing = 1; break; - case 's': - smallMode = 1; break; - default: - if (isdigit((int)(*mode))) { - blockSize100k = *mode-BZ_HDR_0; - } - } - mode++; - } - strcat(mode2, writing ? "w" : "r" ); - strcat(mode2,"b"); /* binary mode */ - - if (open_mode==0) { - if (path==NULL || strcmp(path,"")==0) { - fp = (writing ? stdout : stdin); - SET_BINARY_MODE(fp); - } else { - fp = fopen(path,mode2); - } - } else { -#ifdef BZ_STRICT_ANSI - fp = NULL; -#else - fp = fdopen(fd,mode2); -#endif - } - if (fp == NULL) return NULL; - - if (writing) { - /* Guard against total chaos and anarchy -- JRS */ - if (blockSize100k < 1) blockSize100k = 1; - if (blockSize100k > 9) blockSize100k = 9; - bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k, - verbosity,workFactor); - } else { - bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode, - unused,nUnused); - } - if (bzfp == NULL) { - if (fp != stdin && fp != stdout) fclose(fp); - return NULL; - } - return bzfp; -} - - -/*---------------------------------------------------*/ -/*-- - open file for read or write. - ex) bzopen("file","w9") - case path="" or NULL => use stdin or stdout. ---*/ -BZFILE * BZ_API(BZ2_bzopen) - ( const char *path, - const char *mode ) -{ - return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0); -} - - -/*---------------------------------------------------*/ -BZFILE * BZ_API(BZ2_bzdopen) - ( int fd, - const char *mode ) -{ - return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1); -} - - -/*---------------------------------------------------*/ -int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len ) -{ - int bzerr, nread; - if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0; - nread = BZ2_bzRead(&bzerr,b,buf,len); - if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) { - return nread; - } else { - return -1; - } -} - - -/*---------------------------------------------------*/ -int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len ) -{ - int bzerr; - - BZ2_bzWrite(&bzerr,b,buf,len); - if(bzerr == BZ_OK){ - return len; - }else{ - return -1; - } -} - - -/*---------------------------------------------------*/ -int BZ_API(BZ2_bzflush) (BZFILE *b) -{ - /* do nothing now... */ - return 0; -} - - -/*---------------------------------------------------*/ -void BZ_API(BZ2_bzclose) (BZFILE* b) -{ - int bzerr; - FILE *fp = ((bzFile *)b)->handle; - - if (b==NULL) {return;} - if(((bzFile*)b)->writing){ - BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL); - if(bzerr != BZ_OK){ - BZ2_bzWriteClose(NULL,b,1,NULL,NULL); - } - }else{ - BZ2_bzReadClose(&bzerr,b); - } - if(fp!=stdin && fp!=stdout){ - fclose(fp); - } -} - - -/*---------------------------------------------------*/ -/*-- - return last error code ---*/ -static char *bzerrorstrings[] = { - "OK" - ,"SEQUENCE_ERROR" - ,"PARAM_ERROR" - ,"MEM_ERROR" - ,"DATA_ERROR" - ,"DATA_ERROR_MAGIC" - ,"IO_ERROR" - ,"UNEXPECTED_EOF" - ,"OUTBUFF_FULL" - ,"CONFIG_ERROR" - ,"???" /* for future */ - ,"???" /* for future */ - ,"???" /* for future */ - ,"???" /* for future */ - ,"???" /* for future */ - ,"???" /* for future */ -}; - - -const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum) -{ - int err = ((bzFile *)b)->lastErr; - - if(err>0) err = 0; - *errnum = err; - return bzerrorstrings[err*-1]; -} -#endif diff --git a/lib/bzlib_crctable.c b/lib/bzlib_crctable.c deleted file mode 100644 index 325b96643e..0000000000 --- a/lib/bzlib_crctable.c +++ /dev/null @@ -1,145 +0,0 @@ -#include - -/*-------------------------------------------------------------*/ -/*--- Table for doing CRCs ---*/ -/*--- crctable.c ---*/ -/*-------------------------------------------------------------*/ - -/*-- - This file is a part of bzip2 and/or libbzip2, a program and - library for lossless, block-sorting data compression. - - Copyright (C) 1996-2002 Julian R Seward. 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. 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. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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. - - Julian Seward, Cambridge, UK. - jseward@acm.org - bzip2/libbzip2 version 1.0 of 21 March 2000 - - This program is based on (at least) the work of: - Mike Burrows - David Wheeler - Peter Fenwick - Alistair Moffat - Radford Neal - Ian H. Witten - Robert Sedgewick - Jon L. Bentley - - For more information on these sources, see the manual. ---*/ - - -#include "bzlib_private.h" - -/*-- - I think this is an implementation of the AUTODIN-II, - Ethernet & FDDI 32-bit CRC standard. Vaguely derived - from code by Rob Warnock, in Section 51 of the - comp.compression FAQ. ---*/ - -UInt32 BZ2_crc32Table[256] = { - - /*-- Ugly, innit? --*/ - - 0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L, - 0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L, - 0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L, - 0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL, - 0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L, - 0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L, - 0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L, - 0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL, - 0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L, - 0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L, - 0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L, - 0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL, - 0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L, - 0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L, - 0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L, - 0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL, - 0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL, - 0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L, - 0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L, - 0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL, - 0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL, - 0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L, - 0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L, - 0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL, - 0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL, - 0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L, - 0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L, - 0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL, - 0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL, - 0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L, - 0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L, - 0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL, - 0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L, - 0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL, - 0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL, - 0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L, - 0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L, - 0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL, - 0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL, - 0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L, - 0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L, - 0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL, - 0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL, - 0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L, - 0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L, - 0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL, - 0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL, - 0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L, - 0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L, - 0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL, - 0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L, - 0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L, - 0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L, - 0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL, - 0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L, - 0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L, - 0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L, - 0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL, - 0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L, - 0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L, - 0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L, - 0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL, - 0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L, - 0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L -}; - - -/*-------------------------------------------------------------*/ -/*--- end crctable.c ---*/ -/*-------------------------------------------------------------*/ diff --git a/lib/bzlib_decompress.c b/lib/bzlib_decompress.c deleted file mode 100644 index 4412b8a23e..0000000000 --- a/lib/bzlib_decompress.c +++ /dev/null @@ -1,674 +0,0 @@ -#include -#include -#include - -/*-------------------------------------------------------------*/ -/*--- Decompression machinery ---*/ -/*--- decompress.c ---*/ -/*-------------------------------------------------------------*/ - -/*-- - This file is a part of bzip2 and/or libbzip2, a program and - library for lossless, block-sorting data compression. - - Copyright (C) 1996-2002 Julian R Seward. 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. 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. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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. - - Julian Seward, Cambridge, UK. - jseward@acm.org - bzip2/libbzip2 version 1.0 of 21 March 2000 - - This program is based on (at least) the work of: - Mike Burrows - David Wheeler - Peter Fenwick - Alistair Moffat - Radford Neal - Ian H. Witten - Robert Sedgewick - Jon L. Bentley - - For more information on these sources, see the manual. ---*/ - - -#include "bzlib_private.h" - - -/*---------------------------------------------------*/ -static -void makeMaps_d ( DState* s ) -{ - Int32 i; - s->nInUse = 0; - for (i = 0; i < 256; i++) - if (s->inUse[i]) { - s->seqToUnseq[s->nInUse] = i; - s->nInUse++; - } -} - - -/*---------------------------------------------------*/ -#define RETURN(rrr) \ - { retVal = rrr; goto save_state_and_return; }; - -#define GET_BITS(lll,vvv,nnn) \ - case lll: s->state = lll; \ - while (True) { \ - if (s->bsLive >= nnn) { \ - UInt32 v; \ - v = (s->bsBuff >> \ - (s->bsLive-nnn)) & ((1 << nnn)-1); \ - s->bsLive -= nnn; \ - vvv = v; \ - break; \ - } \ - if (s->strm->avail_in == 0) RETURN(BZ_OK); \ - s->bsBuff \ - = (s->bsBuff << 8) | \ - ((UInt32) \ - (*((UChar*)(s->strm->next_in)))); \ - s->bsLive += 8; \ - s->strm->next_in++; \ - s->strm->avail_in--; \ - s->strm->total_in_lo32++; \ - if (s->strm->total_in_lo32 == 0) \ - s->strm->total_in_hi32++; \ - } - -#define GET_UCHAR(lll,uuu) \ - GET_BITS(lll,uuu,8) - -#define GET_BIT(lll,uuu) \ - GET_BITS(lll,uuu,1) - -/*---------------------------------------------------*/ -#define GET_MTF_VAL(label1,label2,lval) \ -{ \ - if (groupPos == 0) { \ - groupNo++; \ - if (groupNo >= nSelectors) \ - RETURN(BZ_DATA_ERROR); \ - groupPos = BZ_G_SIZE; \ - gSel = s->selector[groupNo]; \ - gMinlen = s->minLens[gSel]; \ - gLimit = &(s->limit[gSel][0]); \ - gPerm = &(s->perm[gSel][0]); \ - gBase = &(s->base[gSel][0]); \ - } \ - groupPos--; \ - zn = gMinlen; \ - GET_BITS(label1, zvec, zn); \ - while (1) { \ - if (zn > 20 /* the longest code */) \ - RETURN(BZ_DATA_ERROR); \ - if (zvec <= gLimit[zn]) break; \ - zn++; \ - GET_BIT(label2, zj); \ - zvec = (zvec << 1) | zj; \ - }; \ - if (zvec - gBase[zn] < 0 \ - || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \ - RETURN(BZ_DATA_ERROR); \ - lval = gPerm[zvec - gBase[zn]]; \ -} - - -/*---------------------------------------------------*/ -Int32 BZ2_decompress ( DState* s ) -{ - UChar uc; - Int32 retVal; - Int32 minLen, maxLen; - bz_stream* strm = s->strm; - - /* stuff that needs to be saved/restored */ - Int32 i; - Int32 j; - Int32 t; - Int32 alphaSize; - Int32 nGroups; - Int32 nSelectors; - Int32 EOB; - Int32 groupNo; - Int32 groupPos; - Int32 nextSym; - Int32 nblockMAX; - Int32 nblock; - Int32 es; - Int32 N; - Int32 curr; - Int32 zt; - Int32 zn; - Int32 zvec; - Int32 zj; - Int32 gSel; - Int32 gMinlen; - Int32* gLimit; - Int32* gBase; - Int32* gPerm; - - if (s->state == BZ_X_MAGIC_1) { - /*initialise the save area*/ - s->save_i = 0; - s->save_j = 0; - s->save_t = 0; - s->save_alphaSize = 0; - s->save_nGroups = 0; - s->save_nSelectors = 0; - s->save_EOB = 0; - s->save_groupNo = 0; - s->save_groupPos = 0; - s->save_nextSym = 0; - s->save_nblockMAX = 0; - s->save_nblock = 0; - s->save_es = 0; - s->save_N = 0; - s->save_curr = 0; - s->save_zt = 0; - s->save_zn = 0; - s->save_zvec = 0; - s->save_zj = 0; - s->save_gSel = 0; - s->save_gMinlen = 0; - s->save_gLimit = NULL; - s->save_gBase = NULL; - s->save_gPerm = NULL; - } - - /*restore from the save area*/ - i = s->save_i; - j = s->save_j; - t = s->save_t; - alphaSize = s->save_alphaSize; - nGroups = s->save_nGroups; - nSelectors = s->save_nSelectors; - EOB = s->save_EOB; - groupNo = s->save_groupNo; - groupPos = s->save_groupPos; - nextSym = s->save_nextSym; - nblockMAX = s->save_nblockMAX; - nblock = s->save_nblock; - es = s->save_es; - N = s->save_N; - curr = s->save_curr; - zt = s->save_zt; - zn = s->save_zn; - zvec = s->save_zvec; - zj = s->save_zj; - gSel = s->save_gSel; - gMinlen = s->save_gMinlen; - gLimit = s->save_gLimit; - gBase = s->save_gBase; - gPerm = s->save_gPerm; - - retVal = BZ_OK; - - switch (s->state) { - - GET_UCHAR(BZ_X_MAGIC_1, uc); - if (uc != BZ_HDR_B) RETURN(BZ_DATA_ERROR_MAGIC); - - GET_UCHAR(BZ_X_MAGIC_2, uc); - if (uc != BZ_HDR_Z) RETURN(BZ_DATA_ERROR_MAGIC); - - GET_UCHAR(BZ_X_MAGIC_3, uc) - if (uc != BZ_HDR_h) RETURN(BZ_DATA_ERROR_MAGIC); - - GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8) - if (s->blockSize100k < (BZ_HDR_0 + 1) || - s->blockSize100k > (BZ_HDR_0 + 9)) RETURN(BZ_DATA_ERROR_MAGIC); - s->blockSize100k -= BZ_HDR_0; - - if (s->smallDecompress) { - s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) ); - s->ll4 = BZALLOC( - ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar) - ); - if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR); - } else { - s->tt = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) ); - if (s->tt == NULL) RETURN(BZ_MEM_ERROR); - } - - GET_UCHAR(BZ_X_BLKHDR_1, uc); - - if (uc == 0x17) goto endhdr_2; - if (uc != 0x31) RETURN(BZ_DATA_ERROR); - GET_UCHAR(BZ_X_BLKHDR_2, uc); - if (uc != 0x41) RETURN(BZ_DATA_ERROR); - GET_UCHAR(BZ_X_BLKHDR_3, uc); - if (uc != 0x59) RETURN(BZ_DATA_ERROR); - GET_UCHAR(BZ_X_BLKHDR_4, uc); - if (uc != 0x26) RETURN(BZ_DATA_ERROR); - GET_UCHAR(BZ_X_BLKHDR_5, uc); - if (uc != 0x53) RETURN(BZ_DATA_ERROR); - GET_UCHAR(BZ_X_BLKHDR_6, uc); - if (uc != 0x59) RETURN(BZ_DATA_ERROR); - - s->currBlockNo++; - if (s->verbosity >= 2) - VPrintf1 ( "\n [%d: huff+mtf ", s->currBlockNo ); - - s->storedBlockCRC = 0; - GET_UCHAR(BZ_X_BCRC_1, uc); - s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); - GET_UCHAR(BZ_X_BCRC_2, uc); - s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); - GET_UCHAR(BZ_X_BCRC_3, uc); - s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); - GET_UCHAR(BZ_X_BCRC_4, uc); - s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); - - GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1); - - s->origPtr = 0; - GET_UCHAR(BZ_X_ORIGPTR_1, uc); - s->origPtr = (s->origPtr << 8) | ((Int32)uc); - GET_UCHAR(BZ_X_ORIGPTR_2, uc); - s->origPtr = (s->origPtr << 8) | ((Int32)uc); - GET_UCHAR(BZ_X_ORIGPTR_3, uc); - s->origPtr = (s->origPtr << 8) | ((Int32)uc); - - if (s->origPtr < 0) - RETURN(BZ_DATA_ERROR); - if (s->origPtr > 10 + 100000*s->blockSize100k) - RETURN(BZ_DATA_ERROR); - - /*--- Receive the mapping table ---*/ - for (i = 0; i < 16; i++) { - GET_BIT(BZ_X_MAPPING_1, uc); - if (uc == 1) - s->inUse16[i] = True; else - s->inUse16[i] = False; - } - - for (i = 0; i < 256; i++) s->inUse[i] = False; - - for (i = 0; i < 16; i++) - if (s->inUse16[i]) - for (j = 0; j < 16; j++) { - GET_BIT(BZ_X_MAPPING_2, uc); - if (uc == 1) s->inUse[i * 16 + j] = True; - } - makeMaps_d ( s ); - if (s->nInUse == 0) RETURN(BZ_DATA_ERROR); - alphaSize = s->nInUse+2; - - /*--- Now the selectors ---*/ - GET_BITS(BZ_X_SELECTOR_1, nGroups, 3); - if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR); - GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15); - if (nSelectors < 1) RETURN(BZ_DATA_ERROR); - for (i = 0; i < nSelectors; i++) { - j = 0; - while (True) { - GET_BIT(BZ_X_SELECTOR_3, uc); - if (uc == 0) break; - j++; - if (j >= nGroups) RETURN(BZ_DATA_ERROR); - } - s->selectorMtf[i] = j; - } - - /*--- Undo the MTF values for the selectors. ---*/ - { - UChar pos[BZ_N_GROUPS], tmp, v; - for (v = 0; v < nGroups; v++) pos[v] = v; - - for (i = 0; i < nSelectors; i++) { - v = s->selectorMtf[i]; - tmp = pos[v]; - while (v > 0) { pos[v] = pos[v-1]; v--; } - pos[0] = tmp; - s->selector[i] = tmp; - } - } - - /*--- Now the coding tables ---*/ - for (t = 0; t < nGroups; t++) { - GET_BITS(BZ_X_CODING_1, curr, 5); - for (i = 0; i < alphaSize; i++) { - while (True) { - if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR); - GET_BIT(BZ_X_CODING_2, uc); - if (uc == 0) break; - GET_BIT(BZ_X_CODING_3, uc); - if (uc == 0) curr++; else curr--; - } - s->len[t][i] = curr; - } - } - - /*--- Create the Huffman decoding tables ---*/ - for (t = 0; t < nGroups; t++) { - minLen = 32; - maxLen = 0; - for (i = 0; i < alphaSize; i++) { - if (s->len[t][i] > maxLen) maxLen = s->len[t][i]; - if (s->len[t][i] < minLen) minLen = s->len[t][i]; - } - BZ2_hbCreateDecodeTables ( - &(s->limit[t][0]), - &(s->base[t][0]), - &(s->perm[t][0]), - &(s->len[t][0]), - minLen, maxLen, alphaSize - ); - s->minLens[t] = minLen; - } - - /*--- Now the MTF values ---*/ - - EOB = s->nInUse+1; - nblockMAX = 100000 * s->blockSize100k; - groupNo = -1; - groupPos = 0; - - for (i = 0; i <= 255; i++) s->unzftab[i] = 0; - - /*-- MTF init --*/ - { - Int32 ii, jj, kk; - kk = MTFA_SIZE-1; - for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) { - for (jj = MTFL_SIZE-1; jj >= 0; jj--) { - s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj); - kk--; - } - s->mtfbase[ii] = kk + 1; - } - } - /*-- end MTF init --*/ - - nblock = 0; - GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym); - - while (True) { - -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - WATCHDOG_RESET(); -#endif - if (nextSym == EOB) break; - - if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) { - - es = -1; - N = 1; - do { - if (nextSym == BZ_RUNA) es = es + (0+1) * N; else - if (nextSym == BZ_RUNB) es = es + (1+1) * N; - N = N * 2; - GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym); - } - while (nextSym == BZ_RUNA || nextSym == BZ_RUNB); - - es++; - uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ]; - s->unzftab[uc] += es; - - if (s->smallDecompress) - while (es > 0) { - if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); - s->ll16[nblock] = (UInt16)uc; - nblock++; - es--; - } - else - while (es > 0) { - if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); - s->tt[nblock] = (UInt32)uc; - nblock++; - es--; - }; - - continue; - - } else { - - if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); - - /*-- uc = MTF ( nextSym-1 ) --*/ - { - Int32 ii, jj, kk, pp, lno, off; - UInt32 nn; - nn = (UInt32)(nextSym - 1); - - if (nn < MTFL_SIZE) { - /* avoid general-case expense */ - pp = s->mtfbase[0]; - uc = s->mtfa[pp+nn]; - while (nn > 3) { - Int32 z = pp+nn; - s->mtfa[(z) ] = s->mtfa[(z)-1]; - s->mtfa[(z)-1] = s->mtfa[(z)-2]; - s->mtfa[(z)-2] = s->mtfa[(z)-3]; - s->mtfa[(z)-3] = s->mtfa[(z)-4]; - nn -= 4; - } - while (nn > 0) { - s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--; - }; - s->mtfa[pp] = uc; - } else { - /* general case */ - lno = nn / MTFL_SIZE; - off = nn % MTFL_SIZE; - pp = s->mtfbase[lno] + off; - uc = s->mtfa[pp]; - while (pp > s->mtfbase[lno]) { - s->mtfa[pp] = s->mtfa[pp-1]; pp--; - }; - s->mtfbase[lno]++; - while (lno > 0) { - s->mtfbase[lno]--; - s->mtfa[s->mtfbase[lno]] - = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1]; - lno--; - } - s->mtfbase[0]--; - s->mtfa[s->mtfbase[0]] = uc; - if (s->mtfbase[0] == 0) { - kk = MTFA_SIZE-1; - for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) { -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - WATCHDOG_RESET(); -#endif - for (jj = MTFL_SIZE-1; jj >= 0; jj--) { - s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj]; - kk--; - } - s->mtfbase[ii] = kk + 1; - } - } - } - } - /*-- end uc = MTF ( nextSym-1 ) --*/ - - s->unzftab[s->seqToUnseq[uc]]++; - if (s->smallDecompress) - s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else - s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]); - nblock++; - - GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym); - continue; - } - } - - /* Now we know what nblock is, we can do a better sanity - check on s->origPtr. - */ - if (s->origPtr < 0 || s->origPtr >= nblock) - RETURN(BZ_DATA_ERROR); - - s->state_out_len = 0; - s->state_out_ch = 0; - BZ_INITIALISE_CRC ( s->calculatedBlockCRC ); - s->state = BZ_X_OUTPUT; - if (s->verbosity >= 2) VPrintf0 ( "rt+rld" ); - - /*-- Set up cftab to facilitate generation of T^(-1) --*/ - s->cftab[0] = 0; - for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1]; - for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1]; - - if (s->smallDecompress) { - - /*-- Make a copy of cftab, used in generation of T --*/ - for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i]; - - /*-- compute the T vector --*/ - for (i = 0; i < nblock; i++) { - uc = (UChar)(s->ll16[i]); - SET_LL(i, s->cftabCopy[uc]); - s->cftabCopy[uc]++; - } - - /*-- Compute T^(-1) by pointer reversal on T --*/ - i = s->origPtr; - j = GET_LL(i); - do { - Int32 tmp = GET_LL(j); - SET_LL(j, i); - i = j; - j = tmp; - } - while (i != s->origPtr); - -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - WATCHDOG_RESET(); -#endif - s->tPos = s->origPtr; - s->nblock_used = 0; - if (s->blockRandomised) { - BZ_RAND_INIT_MASK; - BZ_GET_SMALL(s->k0); s->nblock_used++; - BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; - } else { - BZ_GET_SMALL(s->k0); s->nblock_used++; - } - - } else { - -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - WATCHDOG_RESET(); -#endif - /*-- compute the T^(-1) vector --*/ - for (i = 0; i < nblock; i++) { - uc = (UChar)(s->tt[i] & 0xff); - s->tt[s->cftab[uc]] |= (i << 8); - s->cftab[uc]++; - } - - s->tPos = s->tt[s->origPtr] >> 8; - s->nblock_used = 0; - if (s->blockRandomised) { - BZ_RAND_INIT_MASK; - BZ_GET_FAST(s->k0); s->nblock_used++; - BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; - } else { - BZ_GET_FAST(s->k0); s->nblock_used++; - } - - } - - RETURN(BZ_OK); - - - endhdr_2: - - GET_UCHAR(BZ_X_ENDHDR_2, uc); - if (uc != 0x72) RETURN(BZ_DATA_ERROR); - GET_UCHAR(BZ_X_ENDHDR_3, uc); - if (uc != 0x45) RETURN(BZ_DATA_ERROR); - GET_UCHAR(BZ_X_ENDHDR_4, uc); - if (uc != 0x38) RETURN(BZ_DATA_ERROR); - GET_UCHAR(BZ_X_ENDHDR_5, uc); - if (uc != 0x50) RETURN(BZ_DATA_ERROR); - GET_UCHAR(BZ_X_ENDHDR_6, uc); - if (uc != 0x90) RETURN(BZ_DATA_ERROR); - - s->storedCombinedCRC = 0; - GET_UCHAR(BZ_X_CCRC_1, uc); - s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); - GET_UCHAR(BZ_X_CCRC_2, uc); - s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); - GET_UCHAR(BZ_X_CCRC_3, uc); - s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); - GET_UCHAR(BZ_X_CCRC_4, uc); - s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); - - s->state = BZ_X_IDLE; - RETURN(BZ_STREAM_END); - - default: AssertH ( False, 4001 ); - } - - AssertH ( False, 4002 ); - - save_state_and_return: - - s->save_i = i; - s->save_j = j; - s->save_t = t; - s->save_alphaSize = alphaSize; - s->save_nGroups = nGroups; - s->save_nSelectors = nSelectors; - s->save_EOB = EOB; - s->save_groupNo = groupNo; - s->save_groupPos = groupPos; - s->save_nextSym = nextSym; - s->save_nblockMAX = nblockMAX; - s->save_nblock = nblock; - s->save_es = es; - s->save_N = N; - s->save_curr = curr; - s->save_zt = zt; - s->save_zn = zn; - s->save_zvec = zvec; - s->save_zj = zj; - s->save_gSel = gSel; - s->save_gMinlen = gMinlen; - s->save_gLimit = gLimit; - s->save_gBase = gBase; - s->save_gPerm = gPerm; - - return retVal; -} - - -/*-------------------------------------------------------------*/ -/*--- end decompress.c ---*/ -/*-------------------------------------------------------------*/ diff --git a/lib/bzlib_huffman.c b/lib/bzlib_huffman.c deleted file mode 100644 index 801b8ec39a..0000000000 --- a/lib/bzlib_huffman.c +++ /dev/null @@ -1,229 +0,0 @@ -#include - -/*-------------------------------------------------------------*/ -/*--- Huffman coding low-level stuff ---*/ -/*--- huffman.c ---*/ -/*-------------------------------------------------------------*/ - -/*-- - This file is a part of bzip2 and/or libbzip2, a program and - library for lossless, block-sorting data compression. - - Copyright (C) 1996-2002 Julian R Seward. 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. 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. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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. - - Julian Seward, Cambridge, UK. - jseward@acm.org - bzip2/libbzip2 version 1.0 of 21 March 2000 - - This program is based on (at least) the work of: - Mike Burrows - David Wheeler - Peter Fenwick - Alistair Moffat - Radford Neal - Ian H. Witten - Robert Sedgewick - Jon L. Bentley - - For more information on these sources, see the manual. ---*/ - - -#include "bzlib_private.h" - -/*---------------------------------------------------*/ -#define WEIGHTOF(zz0) ((zz0) & 0xffffff00) -#define DEPTHOF(zz1) ((zz1) & 0x000000ff) -#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3)) - -#define ADDWEIGHTS(zw1,zw2) \ - (WEIGHTOF(zw1)+WEIGHTOF(zw2)) | \ - (1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2))) - -#define UPHEAP(z) \ -{ \ - Int32 zz, tmp; \ - zz = z; tmp = heap[zz]; \ - while (weight[tmp] < weight[heap[zz >> 1]]) { \ - heap[zz] = heap[zz >> 1]; \ - zz >>= 1; \ - } \ - heap[zz] = tmp; \ -} - -#define DOWNHEAP(z) \ -{ \ - Int32 zz, yy, tmp; \ - zz = z; tmp = heap[zz]; \ - while (True) { \ - yy = zz << 1; \ - if (yy > nHeap) break; \ - if (yy < nHeap && \ - weight[heap[yy+1]] < weight[heap[yy]]) \ - yy++; \ - if (weight[tmp] < weight[heap[yy]]) break; \ - heap[zz] = heap[yy]; \ - zz = yy; \ - } \ - heap[zz] = tmp; \ -} - - -/*---------------------------------------------------*/ -void BZ2_hbMakeCodeLengths ( UChar *len, - Int32 *freq, - Int32 alphaSize, - Int32 maxLen ) -{ - /*-- - Nodes and heap entries run from 1. Entry 0 - for both the heap and nodes is a sentinel. - --*/ - Int32 nNodes, nHeap, n1, n2, i, j, k; - Bool tooLong; - - Int32 heap [ BZ_MAX_ALPHA_SIZE + 2 ]; - Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ]; - Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ]; - - for (i = 0; i < alphaSize; i++) - weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8; - - while (True) { - - nNodes = alphaSize; - nHeap = 0; - - heap[0] = 0; - weight[0] = 0; - parent[0] = -2; - - for (i = 1; i <= alphaSize; i++) { - parent[i] = -1; - nHeap++; - heap[nHeap] = i; - UPHEAP(nHeap); - } - - AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 ); - - while (nHeap > 1) { - n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1); - n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1); - nNodes++; - parent[n1] = parent[n2] = nNodes; - weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]); - parent[nNodes] = -1; - nHeap++; - heap[nHeap] = nNodes; - UPHEAP(nHeap); - } - - AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 ); - - tooLong = False; - for (i = 1; i <= alphaSize; i++) { - j = 0; - k = i; - while (parent[k] >= 0) { k = parent[k]; j++; } - len[i-1] = j; - if (j > maxLen) tooLong = True; - } - - if (! tooLong) break; - - for (i = 1; i < alphaSize; i++) { - j = weight[i] >> 8; - j = 1 + (j / 2); - weight[i] = j << 8; - } - } -} - - -/*---------------------------------------------------*/ -void BZ2_hbAssignCodes ( Int32 *code, - UChar *length, - Int32 minLen, - Int32 maxLen, - Int32 alphaSize ) -{ - Int32 n, vec, i; - - vec = 0; - for (n = minLen; n <= maxLen; n++) { - for (i = 0; i < alphaSize; i++) - if (length[i] == n) { code[i] = vec; vec++; }; - vec <<= 1; - } -} - - -/*---------------------------------------------------*/ -void BZ2_hbCreateDecodeTables ( Int32 *limit, - Int32 *base, - Int32 *perm, - UChar *length, - Int32 minLen, - Int32 maxLen, - Int32 alphaSize ) -{ - Int32 pp, i, j, vec; - - pp = 0; - for (i = minLen; i <= maxLen; i++) - for (j = 0; j < alphaSize; j++) - if (length[j] == i) { perm[pp] = j; pp++; }; - - for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0; - for (i = 0; i < alphaSize; i++) base[length[i]+1]++; - - for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1]; - - for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0; - vec = 0; - - for (i = minLen; i <= maxLen; i++) { - vec += (base[i+1] - base[i]); - limit[i] = vec-1; - vec <<= 1; - } - for (i = minLen + 1; i <= maxLen; i++) - base[i] = ((limit[i-1] + 1) << 1) - base[i]; -} - - -/*-------------------------------------------------------------*/ -/*--- end huffman.c ---*/ -/*-------------------------------------------------------------*/ diff --git a/lib/bzlib_randtable.c b/lib/bzlib_randtable.c deleted file mode 100644 index e620c3ea96..0000000000 --- a/lib/bzlib_randtable.c +++ /dev/null @@ -1,126 +0,0 @@ -#include - -/*-------------------------------------------------------------*/ -/*--- Table for randomising repetitive blocks ---*/ -/*--- randtable.c ---*/ -/*-------------------------------------------------------------*/ - -/*-- - This file is a part of bzip2 and/or libbzip2, a program and - library for lossless, block-sorting data compression. - - Copyright (C) 1996-2002 Julian R Seward. 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. 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. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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. - - Julian Seward, Cambridge, UK. - jseward@acm.org - bzip2/libbzip2 version 1.0 of 21 March 2000 - - This program is based on (at least) the work of: - Mike Burrows - David Wheeler - Peter Fenwick - Alistair Moffat - Radford Neal - Ian H. Witten - Robert Sedgewick - Jon L. Bentley - - For more information on these sources, see the manual. ---*/ - - -#include "bzlib_private.h" - - -/*---------------------------------------------*/ -Int32 BZ2_rNums[512] = { - 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, - 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, - 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, - 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, - 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, - 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, - 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, - 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, - 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, - 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, - 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, - 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, - 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, - 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, - 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, - 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, - 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, - 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, - 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, - 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, - 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, - 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, - 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, - 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, - 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, - 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, - 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, - 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, - 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, - 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, - 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, - 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, - 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, - 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, - 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, - 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, - 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, - 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, - 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, - 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, - 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, - 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, - 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, - 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, - 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, - 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, - 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, - 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, - 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, - 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, - 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, - 936, 638 -}; - - -/*-------------------------------------------------------------*/ -/*--- end randtable.c ---*/ -/*-------------------------------------------------------------*/ - -- cgit v1.2.3 From 4b09cdc798ef62602f874a4da03d2a54ca60b4ae Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 13:46:09 +0100 Subject: add kernel gunzip implementation The kernel uncompression functions have a unified API so use this implementation to get it. Signed-off-by: Sascha Hauer --- commands/bootm.c | 10 +- include/common.h | 2 - include/gunzip.h | 10 + include/linux/zconf.h | 57 +++ include/linux/zlib.h | 711 ++++++++++++++++++++++++++++++ include/linux/zutil.h | 106 +++++ lib/Makefile | 2 +- lib/decompress_inflate.c | 183 ++++++++ lib/zlib_inflate/Makefile | 18 + lib/zlib_inflate/inffast.c | 363 ++++++++++++++++ lib/zlib_inflate/inffast.h | 11 + lib/zlib_inflate/inffixed.h | 94 ++++ lib/zlib_inflate/inflate.c | 918 +++++++++++++++++++++++++++++++++++++++ lib/zlib_inflate/inflate.h | 111 +++++ lib/zlib_inflate/inftrees.c | 315 ++++++++++++++ lib/zlib_inflate/inftrees.h | 59 +++ lib/zlib_inflate/infutil.c | 47 ++ lib/zlib_inflate/infutil.h | 25 ++ lib/zlib_inflate/modules.builtin | 1 + 19 files changed, 3036 insertions(+), 7 deletions(-) create mode 100644 include/gunzip.h create mode 100644 include/linux/zconf.h create mode 100644 include/linux/zlib.h create mode 100644 include/linux/zutil.h create mode 100644 lib/decompress_inflate.c create mode 100644 lib/zlib_inflate/Makefile create mode 100644 lib/zlib_inflate/inffast.c create mode 100644 lib/zlib_inflate/inffast.h create mode 100644 lib/zlib_inflate/inffixed.h create mode 100644 lib/zlib_inflate/inflate.c create mode 100644 lib/zlib_inflate/inflate.h create mode 100644 lib/zlib_inflate/inftrees.c create mode 100644 lib/zlib_inflate/inftrees.h create mode 100644 lib/zlib_inflate/infutil.c create mode 100644 lib/zlib_inflate/infutil.h create mode 100644 lib/zlib_inflate/modules.builtin diff --git a/commands/bootm.c b/commands/bootm.c index 79a16d4745..e2ed9bec50 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -88,9 +88,11 @@ int relocate_image(struct image_handle *handle, void *load_address) #ifdef CONFIG_CMD_BOOTM_ZLIB case IH_COMP_GZIP: printf (" Uncompressing ... "); - if (gunzip (load_address, unc_len, - data, &len) != 0) - return -1; + + ret = gunzip(data, len, NULL, NULL, load_address, NULL, + unzip_error); + if (ret) + return ret; break; #endif #ifdef CONFIG_CMD_BOOTM_BZLIB diff --git a/include/common.h b/include/common.h index 68ccbd9b61..d594e630e4 100644 --- a/include/common.h +++ b/include/common.h @@ -111,8 +111,6 @@ void __noreturn reset_cpu(unsigned long addr); void udelay (unsigned long); void mdelay (unsigned long); -int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp); - /* lib_generic/vsprintf.c */ ulong simple_strtoul(const char *cp,char **endp,unsigned int base); unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base); diff --git a/include/gunzip.h b/include/gunzip.h new file mode 100644 index 0000000000..8c0aef1ba5 --- /dev/null +++ b/include/gunzip.h @@ -0,0 +1,10 @@ +#ifndef INFLATE_H +#define INFLATE_H + +int gunzip(unsigned char *inbuf, int len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *output, + int *pos, + void(*error_fn)(char *x)); +#endif diff --git a/include/linux/zconf.h b/include/linux/zconf.h new file mode 100644 index 0000000000..9e8750e82a --- /dev/null +++ b/include/linux/zconf.h @@ -0,0 +1,57 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef _ZCONF_H +#define _ZCONF_H + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# define MAX_MEM_LEVEL 8 +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* default windowBits for decompression. MAX_WBITS is for compression only */ +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif + +/* default memLevel */ +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif + + /* Type declarations */ + +typedef unsigned char Byte; /* 8 bits */ +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ +typedef void *voidp; + +#endif /* _ZCONF_H */ diff --git a/include/linux/zlib.h b/include/linux/zlib.h new file mode 100644 index 0000000000..d8bd20c89a --- /dev/null +++ b/include/linux/zlib.h @@ -0,0 +1,711 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors 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. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef _ZLIB_H +#define _ZLIB_H + +#include + +/* zlib deflate based on ZLIB_VERSION "1.1.3" */ +/* zlib inflate based on ZLIB_VERSION "1.2.3" */ + +/* + This is a modified version of zlib for use inside the Linux kernel. + The main changes are to perform all memory allocation in advance. + + Inflation Changes: + * Z_PACKET_FLUSH is added and used by ppp_deflate. Before returning + this checks there is no more input data available and the next data + is a STORED block. It also resets the mode to be read for the next + data, all as per PPP requirements. + * Addition of zlib_inflateIncomp which copies incompressible data into + the history window and adjusts the accoutning without calling + zlib_inflate itself to inflate the data. +*/ + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +struct internal_state; + +typedef struct z_stream_s { + const Byte *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Byte *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state *state; /* not visible by applications */ + + void *workspace; /* memory allocated for this stream */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_PACKET_FLUSH 2 +#define Z_SYNC_FLUSH 3 +#define Z_FULL_FLUSH 4 +#define Z_FINISH 5 +#define Z_BLOCK 6 /* Only for inflate at present */ +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + + /* basic functions */ + +extern int zlib_deflate_workspacesize (int windowBits, int memLevel); +/* + Returns the number of bytes that needs to be allocated for a per- + stream workspace with the specified parameters. A pointer to this + number of bytes should be returned in stream->workspace before + you call zlib_deflateInit() or zlib_deflateInit2(). If you call + zlib_deflateInit(), specify windowBits = MAX_WBITS and memLevel = + MAX_MEM_LEVEL here. If you call zlib_deflateInit2(), the windowBits + and memLevel parameters passed to zlib_deflateInit2() must not + exceed those passed here. +*/ + +/* +extern int deflateInit (z_streamp strm, int level); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +extern int zlib_deflate (z_streamp strm, int flush); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + 0.1% larger than avail_in plus 12 bytes. If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). +*/ + + +extern int zlib_deflateEnd (z_streamp strm); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +extern int zlib_inflate_workspacesize (void); +/* + Returns the number of bytes that needs to be allocated for a per- + stream workspace. A pointer to this number of bytes should be + returned in stream->workspace before calling zlib_inflateInit(). +*/ + +/* +extern int zlib_inflateInit (z_streamp strm); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, and workspace must be initialized before by + the caller. If next_in is not NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +extern int zlib_inflate (z_streamp strm, int flush); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it gets to the next deflate block boundary. When decoding the + zlib or gzip format, this will cause inflate() to return immediately after + the header and before the first block. When doing a raw inflate, inflate() + will go ahead and process the first block, and will return when it gets to + the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +extern int zlib_inflateEnd (z_streamp strm); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +extern int deflateInit2 (z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match). Filtered data consists mostly of small values with a + somewhat random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of Z_FILTERED is to force more + Huffman coding and less string matching; it is somewhat intermediate + between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects + the compression ratio but not the correctness of the compressed output even + if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +#if 0 +extern int zlib_deflateSetDictionary (z_streamp strm, + const Byte *dictionary, + uInt dictLength); +#endif +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the Adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +#if 0 +extern int zlib_deflateCopy (z_streamp dest, z_streamp source); +#endif + +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +extern int zlib_deflateReset (z_streamp strm); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +static inline unsigned long deflateBound(unsigned long s) +{ + return s + ((s + 7) >> 3) + ((s + 63) >> 6) + 11; +} + +#if 0 +extern int zlib_deflateParams (z_streamp strm, int level, int strategy); +#endif +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +/* +extern int inflateInit2 (z_streamp strm, int windowBits); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) +*/ + +extern int zlib_inflateSetDictionary (z_streamp strm, + const Byte *dictionary, + uInt dictLength); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +#if 0 +extern int zlib_inflateSync (z_streamp strm); +#endif +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +extern int zlib_inflateReset (z_streamp strm); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +extern int zlib_inflateIncomp (z_stream *strm); +/* + This function adds the data at next_in (avail_in bytes) to the output + history without performing any output. There must be no pending output, + and the decompressor must be expecting to see the start of a block. + Calling this function is equivalent to decompressing a stored block + containing the data at next_in (except that the data is not output). +*/ + +#define zlib_deflateInit(strm, level) \ + zlib_deflateInit2((strm), (level), Z_DEFLATED, MAX_WBITS, \ + DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY) +#define zlib_inflateInit(strm) \ + zlib_inflateInit2((strm), DEF_WBITS) + +extern int zlib_deflateInit2(z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy); +extern int zlib_inflateInit2(z_streamp strm, int windowBits); + +#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +/* Utility function: initialize zlib, unpack binary blob, clean up zlib, + * return len or negative error code. */ +extern int zlib_inflate_blob(void *dst, unsigned dst_sz, const void *src, unsigned src_sz); + +#endif /* _ZLIB_H */ diff --git a/include/linux/zutil.h b/include/linux/zutil.h new file mode 100644 index 0000000000..6adfa9a6ff --- /dev/null +++ b/include/linux/zutil.h @@ -0,0 +1,106 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h,v 1.1 2000/01/01 03:32:23 davem Exp $ */ + +#ifndef _Z_UTIL_H +#define _Z_UTIL_H + +#include +#include +#include + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + + /* common constants */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + + /* Common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + + /* functions */ + +typedef uLong (*check_func) (uLong check, const Byte *buf, + uInt len); + + + /* checksum functions */ + +#define BASE 65521L /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* ========================================================================= */ +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ +static inline uLong zlib_adler32(uLong adler, + const Byte *buf, + uInt len) +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + s1 %= BASE; + s2 %= BASE; + } + return (s2 << 16) | s1; +} + +#endif /* _Z_UTIL_H */ diff --git a/lib/Makefile b/lib/Makefile index b02191adba..f0abc21c22 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -16,7 +16,7 @@ obj-y += stringlist.o obj-y += recursive_action.o obj-y += make_directory.o obj-$(CONFIG_BZLIB) += decompress_bunzip2.o -obj-$(CONFIG_ZLIB) += zlib.o gunzip.o +obj-$(CONFIG_ZLIB) += decompress_inflate.o zlib_inflate/ obj-$(CONFIG_CMDLINE_EDITING) += readline.o obj-$(CONFIG_SIMPLE_READLINE) += readline_simple.o obj-$(CONFIG_GLOB) += fnmatch.o diff --git a/lib/decompress_inflate.c b/lib/decompress_inflate.c new file mode 100644 index 0000000000..d246d4dc7e --- /dev/null +++ b/lib/decompress_inflate.c @@ -0,0 +1,183 @@ +#ifdef STATIC +/* Pre-boot environment: included */ + +/* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots + * errors about console_printk etc... on ARM */ +#define _LINUX_KERNEL_H + +#include "zlib_inflate/inftrees.c" +#include "zlib_inflate/inffast.c" +#include "zlib_inflate/inflate.c" + +#else /* STATIC */ +/* initramfs et al: linked */ + +#include +#include +#include + +#include "zlib_inflate/inftrees.h" +#include "zlib_inflate/inffast.h" +#include "zlib_inflate/inflate.h" + +#include "zlib_inflate/infutil.h" + +#endif /* STATIC */ + +#define GZIP_IOBUF_SIZE (16*1024) + +static int nofill(void *buffer, unsigned int len) +{ + return -1; +} + +/* Included from initramfs et al code */ +int gunzip(unsigned char *buf, int len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *out_buf, + int *pos, + void(*error)(char *x)) { + u8 *zbuf; + struct z_stream_s *strm; + int rc; + size_t out_len; + + rc = -1; + if (flush) { + out_len = 0x8000; /* 32 K */ + out_buf = malloc(out_len); + } else { + out_len = 0x7fffffff; /* no limit */ + } + if (!out_buf) { + error("Out of memory while allocating output buffer"); + goto gunzip_nomem1; + } + + if (buf) + zbuf = buf; + else { + zbuf = malloc(GZIP_IOBUF_SIZE); + len = 0; + } + if (!zbuf) { + error("Out of memory while allocating input buffer"); + goto gunzip_nomem2; + } + + strm = malloc(sizeof(*strm)); + if (strm == NULL) { + error("Out of memory while allocating z_stream"); + goto gunzip_nomem3; + } + + strm->workspace = malloc(flush ? zlib_inflate_workspacesize() : + sizeof(struct inflate_state)); + if (strm->workspace == NULL) { + error("Out of memory while allocating workspace"); + goto gunzip_nomem4; + } + + if (!fill) + fill = nofill; + + if (len == 0) + len = fill(zbuf, GZIP_IOBUF_SIZE); + + /* verify the gzip header */ + if (len < 10 || + zbuf[0] != 0x1f || zbuf[1] != 0x8b || zbuf[2] != 0x08) { + if (pos) + *pos = 0; + error("Not a gzip file"); + goto gunzip_5; + } + + /* skip over gzip header (1f,8b,08... 10 bytes total + + * possible asciz filename) + */ + strm->next_in = zbuf + 10; + strm->avail_in = len - 10; + /* skip over asciz filename */ + if (zbuf[3] & 0x8) { + do { + /* + * If the filename doesn't fit into the buffer, + * the file is very probably corrupt. Don't try + * to read more data. + */ + if (strm->avail_in == 0) { + error("header error"); + goto gunzip_5; + } + --strm->avail_in; + } while (*strm->next_in++); + } + + strm->next_out = out_buf; + strm->avail_out = out_len; + + rc = zlib_inflateInit2(strm, -MAX_WBITS); + + if (!flush) { + WS(strm)->inflate_state.wsize = 0; + WS(strm)->inflate_state.window = NULL; + } + + while (rc == Z_OK) { + if (strm->avail_in == 0) { + /* TODO: handle case where both pos and fill are set */ + len = fill(zbuf, GZIP_IOBUF_SIZE); + if (len < 0) { + rc = -1; + error("read error"); + break; + } + strm->next_in = zbuf; + strm->avail_in = len; + } + rc = zlib_inflate(strm, 0); + + /* Write any data generated */ + if (flush && strm->next_out > out_buf) { + int l = strm->next_out - out_buf; + if (l != flush(out_buf, l)) { + rc = -1; + error("write error"); + break; + } + strm->next_out = out_buf; + strm->avail_out = out_len; + } + + /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */ + if (rc == Z_STREAM_END) { + rc = 0; + break; + } else if (rc != Z_OK) { + error("uncompression error"); + rc = -1; + } + } + + zlib_inflateEnd(strm); + if (pos) + /* add + 8 to skip over trailer */ + *pos = strm->next_in - zbuf+8; + +gunzip_5: + free(strm->workspace); +gunzip_nomem4: + free(strm); +gunzip_nomem3: + if (!buf) + free(zbuf); +gunzip_nomem2: + if (flush) + free(out_buf); +gunzip_nomem1: + return rc; /* returns Z_OK (0) if successful */ +} + +#define decompress gunzip diff --git a/lib/zlib_inflate/Makefile b/lib/zlib_inflate/Makefile new file mode 100644 index 0000000000..8e95fcd3c9 --- /dev/null +++ b/lib/zlib_inflate/Makefile @@ -0,0 +1,18 @@ +# +# This is a modified version of zlib, which does all memory +# allocation ahead of time. +# +# This is only the decompression, see zlib_deflate for the +# the compression +# +# Decompression needs to be serialized for each memory +# allocation. +# +# (The upsides of the simplification is that you can't get in +# any nasty situations wrt memory management, and that the +# uncompression can be done without blocking on allocation). +# + +obj-$(CONFIG_ZLIB) += zlib_inflate.o + +zlib_inflate-objs := inffast.o inflate.o inftrees.o diff --git a/lib/zlib_inflate/inffast.c b/lib/zlib_inflate/inffast.c new file mode 100644 index 0000000000..2c13ecc5bb --- /dev/null +++ b/lib/zlib_inflate/inffast.c @@ -0,0 +1,363 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +union uu { + unsigned short us; + unsigned char b[2]; +}; + +/* Endian independed version */ +static inline unsigned short +get_unaligned16(const unsigned short *p) +{ + union uu mm; + unsigned char *b = (unsigned char *)p; + + mm.b[0] = b[0]; + mm.b[1] = b[1]; + return mm.us; +} + +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +# define UP_UNALIGNED(a) get_unaligned16((a)++) +#else +# define OFF 1 +# define PUP(a) *++(a) +# define UP_UNALIGNED(a) get_unaligned16(++(a)) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + + - @start: inflate()'s starting value for strm->avail_out + */ +void inflate_fast(z_streamp strm, unsigned start) +{ + struct inflate_state *state; + const unsigned char *in; /* local strm->next_in */ + const unsigned char *last; /* while in < last, enough input available */ + unsigned char *out; /* local strm->next_out */ + unsigned char *beg; /* inflate()'s initial strm->next_out */ + unsigned char *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const *lcode; /* local strm->lencode */ + code const *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + unsigned short *sout; + unsigned long loops; + + from = out - dist; /* copy direct from output */ + /* minimum length is three */ + /* Align out addr */ + if (!((long)(out - 1 + OFF) & 1)) { + PUP(out) = PUP(from); + len--; + } + sout = (unsigned short *)(out - OFF); + if (dist > 2) { + unsigned short *sfrom; + + sfrom = (unsigned short *)(from - OFF); + loops = len >> 1; + do +#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + PUP(sout) = PUP(sfrom); +#else + PUP(sout) = UP_UNALIGNED(sfrom); +#endif + while (--loops); + out = (unsigned char *)sout + OFF; + from = (unsigned char *)sfrom + OFF; + } else { /* dist == 1 or dist == 2 */ + unsigned short pat16; + + pat16 = *(sout-1+OFF); + if (dist == 1) { + union uu mm; + /* copy one char pattern to both bytes */ + mm.us = pat16; + mm.b[0] = mm.b[1]; + pat16 = mm.us; + } + loops = len >> 1; + do + PUP(sout) = pat16; + while (--loops); + out = (unsigned char *)sout + OFF; + } + if (len & 1) + PUP(out) = PUP(from); + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/lib/zlib_inflate/inffast.h b/lib/zlib_inflate/inffast.h new file mode 100644 index 0000000000..40315d9fdd --- /dev/null +++ b/lib/zlib_inflate/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast (z_streamp strm, unsigned start); diff --git a/lib/zlib_inflate/inffixed.h b/lib/zlib_inflate/inffixed.h new file mode 100644 index 0000000000..75ed4b5978 --- /dev/null +++ b/lib/zlib_inflate/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/lib/zlib_inflate/inflate.c b/lib/zlib_inflate/inflate.c new file mode 100644 index 0000000000..f5ce87b080 --- /dev/null +++ b/lib/zlib_inflate/inflate.c @@ -0,0 +1,918 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Based on zlib 1.2.3 but modified for the Linux Kernel by + * Richard Purdie + * + * Changes mainly for static instead of dynamic memory allocation + * + */ + +#include +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" +#include "infutil.h" + +int zlib_inflate_workspacesize(void) +{ + return sizeof(struct inflate_workspace); +} + +int zlib_inflateReset(z_streamp strm) +{ + struct inflate_state *state; + + if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + + /* Initialise Window */ + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + + return Z_OK; +} + +#if 0 +int zlib_inflatePrime(z_streamp strm, int bits, int value) +{ + struct inflate_state *state; + + if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} +#endif + +int zlib_inflateInit2(z_streamp strm, int windowBits) +{ + struct inflate_state *state; + + if (strm == NULL) return Z_STREAM_ERROR; + strm->msg = NULL; /* in case we return an error */ + + state = &WS(strm)->inflate_state; + strm->state = (struct internal_state *)state; + + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; + } + if (windowBits < 8 || windowBits > 15) { + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = &WS(strm)->working_window[0]; + + return zlib_inflateReset(strm); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. This returns fixed tables from inffixed.h. + */ +static void zlib_fixedtables(struct inflate_state *state) +{ +# include "inffixed.h" + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. This is only called when a window is already in use, or when + output has been written during this inflate call, but the end of the deflate + stream has not been reached yet. It is also called to window dictionary data + when a dictionary is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +static void zlib_updatewindow(z_streamp strm, unsigned out) +{ + struct inflate_state *state; + unsigned copy, dist; + + state = (struct inflate_state *)strm->state; + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + memcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + memcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + memcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } +} + + +/* + * At the end of a Deflate-compressed PPP packet, we expect to have seen + * a `stored' block type value but not the (zero) length bytes. + */ +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +static int zlib_inflateSyncPacket(z_streamp strm) +{ + struct inflate_state *state; + + if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + + if (state->mode == STORED && state->bits == 0) { + state->mode = TYPE; + return Z_OK; + } + return Z_DATA_ERROR; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#define UPDATE(check, buf, len) zlib_adler32(check, buf, len) + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int zlib_inflate(z_streamp strm, int flush) +{ + struct inflate_state *state; + const unsigned char *next; /* next input */ + unsigned char *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Do not check for strm->next_out == NULL here as ppc zImage + inflates to strm->next_out = 0 */ + + if (strm == NULL || strm->state == NULL || + (strm->next_in == NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state *)strm->state; + + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); + if ( + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + strm->adler = state->check = zlib_adler32(0L, NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = zlib_adler32(0L, NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + state->mode = STORED; + break; + case 1: /* fixed block */ + zlib_fixedtables(state); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + memcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const *)(state->next); + state->lenbits = 7; + ret = zlib_inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const *)(state->next); + state->lenbits = 9; + ret = zlib_inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const *)(state->next); + state->distbits = 6; + ret = zlib_inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + state->mode = LIT; + break; + } + if (this.op & 32) { + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + } + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call zlib_updatewindow() to create and/or update the window state. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + zlib_updatewindow(strm, out); + + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + + if (flush == Z_PACKET_FLUSH && ret == Z_OK && + strm->avail_out != 0 && strm->avail_in == 0) + return zlib_inflateSyncPacket(strm); + + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + + return ret; +} + +int zlib_inflateEnd(z_streamp strm) +{ + if (strm == NULL || strm->state == NULL) + return Z_STREAM_ERROR; + return Z_OK; +} + +#if 0 +int zlib_inflateSetDictionary(z_streamp strm, const Byte *dictionary, + uInt dictLength) +{ + struct inflate_state *state; + unsigned long id; + + /* check state */ + if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = zlib_adler32(0L, NULL, 0); + id = zlib_adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + zlib_updatewindow(strm, strm->avail_out); + + if (dictLength > state->wsize) { + memcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + memcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + return Z_OK; +} +#endif + +#if 0 +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, zlib_syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +static unsigned zlib_syncsearch(unsigned *have, unsigned char *buf, + unsigned len) +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} +#endif + +#if 0 +int zlib_inflateSync(z_streamp strm) +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state *state; + + /* check parameters */ + if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + zlib_syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = zlib_syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + zlib_inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} +#endif + +/* + * This subroutine adds the data at next_in/avail_in to the output history + * without performing any output. The output buffer must be "caught up"; + * i.e. no pending output but this should always be the case. The state must + * be waiting on the start of a block (i.e. mode == TYPE or HEAD). On exit, + * the output will also be caught up, and the checksum will have been updated + * if need be. + */ +int zlib_inflateIncomp(z_stream *z) +{ + struct inflate_state *state = (struct inflate_state *)z->state; + Byte *saved_no = z->next_out; + uInt saved_ao = z->avail_out; + + if (state->mode != TYPE && state->mode != HEAD) + return Z_DATA_ERROR; + + /* Setup some variables to allow misuse of updateWindow */ + z->avail_out = 0; + z->next_out = (unsigned char*)z->next_in + z->avail_in; + + zlib_updatewindow(z, z->avail_in); + + /* Restore saved variables */ + z->avail_out = saved_ao; + z->next_out = saved_no; + + z->adler = state->check = + UPDATE(state->check, z->next_in, z->avail_in); + + z->total_out += z->avail_in; + z->total_in += z->avail_in; + z->next_in += z->avail_in; + state->total += z->avail_in; + z->avail_in = 0; + + return Z_OK; +} diff --git a/lib/zlib_inflate/inflate.h b/lib/zlib_inflate/inflate.h new file mode 100644 index 0000000000..3d17b3d1b2 --- /dev/null +++ b/lib/zlib_inflate/inflate.h @@ -0,0 +1,111 @@ +#ifndef INFLATE_H +#define INFLATE_H + +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + /* gz_headerp head; */ /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const *lencode; /* starting table for length/literal codes */ + code const *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; +#endif diff --git a/lib/zlib_inflate/inftrees.c b/lib/zlib_inflate/inftrees.c new file mode 100644 index 0000000000..3fe6ce5b53 --- /dev/null +++ b/lib/zlib_inflate/inftrees.c @@ -0,0 +1,315 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include +#include "inftrees.h" + +#define MAXBITS 15 + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int zlib_inflate_table(codetype type, unsigned short *lens, unsigned codes, + code **table, unsigned *bits, unsigned short *work) +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code *next; /* next available space in table */ + const unsigned short *base; /* base value table to use */ + const unsigned short *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)1; + this.val = (unsigned short)0; + *(*table)++ = this; /* make a table to force an error */ + *(*table)++ = this; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/lib/zlib_inflate/inftrees.h b/lib/zlib_inflate/inftrees.h new file mode 100644 index 0000000000..b70b4731ac --- /dev/null +++ b/lib/zlib_inflate/inftrees.h @@ -0,0 +1,59 @@ +#ifndef INFTREES_H +#define INFTREES_H + +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1444 code structures (852 for length/literals + and 592 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 2048 +#define MAXD 592 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int zlib_inflate_table (codetype type, unsigned short *lens, + unsigned codes, code **table, + unsigned *bits, unsigned short *work); +#endif diff --git a/lib/zlib_inflate/infutil.c b/lib/zlib_inflate/infutil.c new file mode 100644 index 0000000000..f452ba6040 --- /dev/null +++ b/lib/zlib_inflate/infutil.c @@ -0,0 +1,47 @@ +#include +#include + +/* Utility function: initialize zlib, unpack binary blob, clean up zlib, + * return len or negative error code. + */ +int zlib_inflate_blob(void *gunzip_buf, unsigned int sz, + const void *buf, unsigned int len) +{ + const u8 *zbuf = buf; + struct z_stream_s *strm; + int rc; + + rc = -ENOMEM; + strm = kmalloc(sizeof(*strm), GFP_KERNEL); + if (strm == NULL) + goto gunzip_nomem1; + strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); + if (strm->workspace == NULL) + goto gunzip_nomem2; + + /* gzip header (1f,8b,08... 10 bytes total + possible asciz filename) + * expected to be stripped from input + */ + strm->next_in = zbuf; + strm->avail_in = len; + strm->next_out = gunzip_buf; + strm->avail_out = sz; + + rc = zlib_inflateInit2(strm, -MAX_WBITS); + if (rc == Z_OK) { + rc = zlib_inflate(strm, Z_FINISH); + /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */ + if (rc == Z_STREAM_END) + rc = sz - strm->avail_out; + else + rc = -EINVAL; + zlib_inflateEnd(strm); + } else + rc = -EINVAL; + + kfree(strm->workspace); +gunzip_nomem2: + kfree(strm); +gunzip_nomem1: + return rc; /* returns Z_OK (0) if successful */ +} diff --git a/lib/zlib_inflate/infutil.h b/lib/zlib_inflate/infutil.h new file mode 100644 index 0000000000..e7dea7a88a --- /dev/null +++ b/lib/zlib_inflate/infutil.h @@ -0,0 +1,25 @@ +/* infutil.h -- types and macros common to blocks and codes + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +#ifndef _INFUTIL_H +#define _INFUTIL_H + +#include + +/* memory allocation for inflation */ + +struct inflate_workspace { + struct inflate_state inflate_state; + unsigned char working_window[1 << MAX_WBITS]; +}; + +#define WS(z) ((struct inflate_workspace *)(z->workspace)) + +#endif diff --git a/lib/zlib_inflate/modules.builtin b/lib/zlib_inflate/modules.builtin new file mode 100644 index 0000000000..720622562c --- /dev/null +++ b/lib/zlib_inflate/modules.builtin @@ -0,0 +1 @@ +kernel/lib/zlib_inflate/zlib_inflate.ko -- cgit v1.2.3 From e3394a7010dfed2ba378761c69bfa1d676e411ea Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 13:47:27 +0100 Subject: remove old zlib Signed-off-by: Sascha Hauer --- include/zlib.h | 434 ------------ lib/gunzip.c | 85 --- lib/zlib.c | 2158 -------------------------------------------------------- 3 files changed, 2677 deletions(-) delete mode 100644 include/zlib.h delete mode 100644 lib/gunzip.c delete mode 100644 lib/zlib.c diff --git a/include/zlib.h b/include/zlib.h deleted file mode 100644 index e441494d0d..0000000000 --- a/include/zlib.h +++ /dev/null @@ -1,434 +0,0 @@ -/* - * This file is derived from zlib.h and zconf.h from the zlib-0.95 - * distribution by Jean-loup Gailly and Mark Adler, with some additions - * by Paul Mackerras to aid in implementing Deflate compression and - * decompression for PPP packets. - */ - -/* - * ==FILEVERSION 960122== - * - * This marker is used by the Linux installation script to determine - * whether an up-to-date version of this file is already installed. - */ - -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 0.95, Aug 16th, 1995. - - Copyright (C) 1995 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors 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. - - Jean-loup Gailly Mark Adler - gzip@prep.ai.mit.edu madler@alumni.caltech.edu - */ - -#ifndef _ZLIB_H -#define _ZLIB_H - -/* #include "zconf.h" */ /* included directly here */ - -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */ - -/* - The library does not install any signal handler. It is recommended to - add at least a handler for SIGSEGV when decompressing; the library checks - the consistency of the input data whenever possible but may go nuts - for some forms of corrupted input. - */ - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints - * at addresses which are not a multiple of their size. - * Under DOS, -DFAR=far or -DFAR=__far may be needed. - */ - -#ifndef STDC -# if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus) -# define STDC -# endif -#endif - -#ifdef __MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */ -# include -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -#ifndef FAR -# define FAR -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2 */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - 1 << (windowBits+2) + 1 << (memLevel+9) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -typedef unsigned char Byte; /* 8 bits */ -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -typedef Byte FAR Bytef; -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -/* end of original zconf.h */ - -#define ZLIB_VERSION "0.95P" - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed - data. This version of the library supports only one compression method - (deflation) but other algorithms may be added later and will have the same - stream interface. - - For compression the application must provide the output buffer and - may optionally provide the input buffer for optimization. For decompression, - the application must provide the input buffer and may optionally provide - the output buffer for optimization. - - Compression can be done in a single step if the buffers are large - enough (for example if an input file is mmap'ed), or can be done by - repeated calls of the compression function. In the latter case, the - application must provide more input and/or consume the output - (providing more output space) before each call. -*/ - -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address, uInt nbytes)); - -typedef void (*cb_func) OF((Bytef *buf, uInt len)); - -struct internal_state; - -typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ - - Bytef *next_out; /* next output byte should be put there */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ - - char *msg; /* last error message, NULL if no error */ - struct internal_state FAR *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidp opaque; /* private data object passed to zalloc and zfree */ - - Byte data_type; /* best guess about the data type: ascii or binary */ - - cb_func outcb; /* called regularly just before blocks of output */ - -} z_stream; - -/* - The application must update next_in and avail_in when avail_in has - dropped to zero. It must update next_out and avail_out when avail_out - has dropped to zero. The application must initialize zalloc, zfree and - opaque before calling the init function. All other fields are set by the - compression library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this - if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, - pointers returned by zalloc for objects of exactly 65536 bytes *must* - have their offset normalized to zero. The default allocation function - provided by this library ensures this (see zutil.c). To reduce memory - requirements and avoid any allocation of 64K objects, at the expense of - compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or - progress reports. After compression, total_in holds the total size of - the uncompressed data and may be saved for use in the decompressor - (particularly if the decompressor wants to decompress everything in - a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 -#define Z_FULL_FLUSH 2 -#define Z_SYNC_FLUSH 3 /* experimental: partial_flush + byte align */ -#define Z_FINISH 4 -#define Z_PACKET_FLUSH 5 -/* See deflate() below for the usage of these constants */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -/* error codes for the compression/decompression functions */ - -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_DEFAULT_STRATEGY 0 - -#define Z_BINARY 0 -#define Z_ASCII 1 -#define Z_UNKNOWN 2 -/* Used to set the data_type field */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -extern char *zlib_version; -/* The application can compare zlib_version and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is - not compatible with the zlib.h header file used by the application. - */ - - /* basic functions */ - -extern int inflateInit OF((z_stream *strm)); -/* - Initializes the internal stream state for decompression. The fields - zalloc and zfree must be initialized before by the caller. If zalloc and - zfree are set to Z_NULL, inflateInit updates them to use default allocation - functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory. msg is set to null if there is no error message. - inflateInit does not perform any decompression: this will be done by - inflate(). -*/ - - -extern int inflate OF((z_stream *strm, int flush)); -/* - Performs one or both of the following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing - will resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() always provides as much output as possible - (until there is no more input data or no more space in the output buffer). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating the next_* and avail_* values accordingly. - The application can consume the uncompressed output when it wants, for - example when the output buffer is full (avail_out == 0), or after each - call of inflate(). - - If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH, - inflate flushes as much output as possible to the output buffer. The - flushing behavior of inflate is not specified for values of the flush - parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the - current implementation actually flushes as much output as possible - anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data - has been consumed, it is expecting to see the length field of a stored - block; if not, it returns Z_DATA_ERROR. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step - (a single call of inflate), the parameter flush should be set to - Z_FINISH. In this case all pending input is processed and all pending - output is flushed; avail_out must be large enough to hold all the - uncompressed data. (The size of the uncompressed data may have been saved - by the compressor for this purpose.) The next operation on this stream must - be inflateEnd to deallocate the decompression state. The use of Z_FINISH - is never required, but can be used to inform inflate that a faster routine - may be used for the single inflate() call. - - inflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if the end of the - compressed data has been reached and all uncompressed output has been - produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if - the stream structure was inconsistent (for example if next_in or next_out - was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no - progress is possible or if there was not enough room in the output buffer - when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then - call inflateSync to look for a good compression block. */ - - -extern int inflateEnd OF((z_stream *strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - /* advanced functions */ - -extern int inflateInit2 OF((z_stream *strm, - int windowBits)); -/* - This is another version of inflateInit with more compression options. The - fields next_out, zalloc and zfree must be initialized before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library (the value 16 will be allowed soon). The - default value is 15 if inflateInit is used instead. If a compressed stream - with a larger window size is given as input, inflate() will return with - the error code Z_DATA_ERROR instead of trying to allocate a larger window. - - If next_out is not null, the library will use this buffer for the history - buffer; the buffer must either be large enough to hold the entire output - data, or have at least 1< -#include -#include - -#define ZALLOC_ALIGNMENT 16 - -static void *zalloc(void *x, unsigned items, unsigned size) -{ - void *p; - - size *= items; - size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1); - - p = malloc (size); - - return (p); -} - -static void zfree(void *x, void *addr, unsigned nb) -{ - free (addr); -} - -#define HEAD_CRC 2 -#define EXTRA_FIELD 4 -#define ORIG_NAME 8 -#define COMMENT 0x10 -#define RESERVED 0xe0 - -#define DEFLATED 8 - -int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp) -{ - z_stream s; - int r, i, flags; - - /* skip header */ - i = 10; - flags = src[3]; - if (src[2] != DEFLATED || (flags & RESERVED) != 0) { - puts ("Error: Bad gzipped data\n"); - return (-1); - } - if ((flags & EXTRA_FIELD) != 0) - i = 12 + src[10] + (src[11] << 8); - if ((flags & ORIG_NAME) != 0) - while (src[i++] != 0) - ; - if ((flags & COMMENT) != 0) - while (src[i++] != 0) - ; - if ((flags & HEAD_CRC) != 0) - i += 2; - if (i >= *lenp) { - puts ("Error: gunzip out of data in header\n"); - return (-1); - } - - s.zalloc = zalloc; - s.zfree = zfree; -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - s.outcb = (cb_func)WATCHDOG_RESET; -#else - s.outcb = Z_NULL; -#endif /* CONFIG_HW_WATCHDOG */ - - r = inflateInit2(&s, -MAX_WBITS); - if (r != Z_OK) { - printf ("Error: inflateInit2() returned %d\n", r); - return (-1); - } - s.next_in = src + i; - s.avail_in = *lenp - i; - s.next_out = dst; - s.avail_out = dstlen; - r = inflate(&s, Z_FINISH); - if (r != Z_OK && r != Z_STREAM_END) { - printf ("Error: inflate() returned %d\n", r); - return (-1); - } - *lenp = s.next_out - (unsigned char *) dst; - inflateEnd(&s); - - return (0); -} diff --git a/lib/zlib.c b/lib/zlib.c deleted file mode 100644 index 699a6f2c23..0000000000 --- a/lib/zlib.c +++ /dev/null @@ -1,2158 +0,0 @@ -/* - * This file is derived from various .h and .c files from the zlib-0.95 - * distribution by Jean-loup Gailly and Mark Adler, with some additions - * by Paul Mackerras to aid in implementing Deflate compression and - * decompression for PPP packets. See zlib.h for conditions of - * distribution and use. - * - * Changes that have been made include: - * - changed functions not used outside this file to "local" - * - added minCompression parameter to deflateInit2 - * - added Z_PACKET_FLUSH (see zlib.h for details) - * - added inflateIncomp - */ - -/*+++++*/ -/* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* From: zutil.h,v 1.9 1995/05/03 17:27:12 jloup Exp */ - -#define _Z_UTIL_H - -#include "zlib.h" - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - -#define FAR - -typedef unsigned char uch; -typedef uch FAR uchf; -typedef unsigned short ush; -typedef ush FAR ushf; -typedef unsigned long ulg; - -extern char *z_errmsg[]; /* indexed by 1-zlib_error */ - -#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err) -/* To be used only when the state is known to be valid */ - -#ifndef NULL -#define NULL ((void *) 0) -#endif - - /* common constants */ - -#define DEFLATED 8 - -#ifndef DEF_WBITS -# define DEF_WBITS MAX_WBITS -#endif -/* default windowBits for decompression. MAX_WBITS is for compression only */ - -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -/* default memLevel */ - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -/* The three kinds of block type */ - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ - - /* functions */ - -#include -#define zmemcpy memcpy -#define zmemzero(dest, len) memset(dest, 0, len) - -/* Diagnostic functions */ -#ifdef DEBUG_ZLIB -# include -# ifndef verbose -# define verbose 0 -# endif -# define Assert(cond,msg) {if(!(cond)) z_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 - - -typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len)); - -/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */ -/* void zcfree OF((voidpf opaque, voidpf ptr)); */ - -#define ZALLOC(strm, items, size) \ - (*((strm)->zalloc))((strm)->opaque, (items), (size)) -#define ZFREE(strm, addr, size) \ - (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size)) -#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);} - -/* deflate.h -- internal compression state - * Copyright (C) 1995 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/*+++++*/ -/* infblock.h -- header to use infblock.c - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -struct inflate_blocks_state; -typedef struct inflate_blocks_state FAR inflate_blocks_statef; - -local inflate_blocks_statef * inflate_blocks_new OF(( - z_stream *z, - check_func c, /* check function */ - uInt w)); /* window size */ - -local int inflate_blocks OF(( - inflate_blocks_statef *, - z_stream *, - int)); /* initial return code */ - -local void inflate_blocks_reset OF(( - inflate_blocks_statef *, - z_stream *, - uLongf *)); /* check value on output */ - -local int inflate_blocks_free OF(( - inflate_blocks_statef *, - z_stream *, - uLongf *)); /* check value on output */ - -local int inflate_addhistory OF(( - inflate_blocks_statef *, - z_stream *)); - -local int inflate_packet_flush OF(( - inflate_blocks_statef *)); - -/*+++++*/ -/* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Huffman code lookup table entry--this entry is four bytes for machines - that have 16-bit pointers (e.g. PC's in the small or medium model). */ - -typedef struct inflate_huft_s FAR inflate_huft; - -struct inflate_huft_s { - union { - struct { - Byte Exop; /* number of extra bits or operation */ - Byte Bits; /* number of bits in this code or subcode */ - } what; - uInt Nalloc; /* number of these allocated here */ - Bytef *pad; /* pad structure to a power of 2 (4 bytes for */ - } word; /* 16-bit, 8 bytes for 32-bit machines) */ - union { - uInt Base; /* literal, length base, or distance base */ - inflate_huft *Next; /* pointer to next level of table */ - } more; -}; - -#ifdef DEBUG_ZLIB - local uInt inflate_hufts; -#endif - -local int inflate_trees_bits OF(( - uIntf *, /* 19 code lengths */ - uIntf *, /* bits tree desired/actual depth */ - inflate_huft * FAR *, /* bits tree result */ - z_stream *)); /* for zalloc, zfree functions */ - -local int inflate_trees_dynamic OF(( - uInt, /* number of literal/length codes */ - uInt, /* number of distance codes */ - uIntf *, /* that many (total) code lengths */ - uIntf *, /* literal desired/actual bit depth */ - uIntf *, /* distance desired/actual bit depth */ - inflate_huft * FAR *, /* literal/length tree result */ - inflate_huft * FAR *, /* distance tree result */ - z_stream *)); /* for zalloc, zfree functions */ - -local int inflate_trees_fixed OF(( - uIntf *, /* literal desired/actual bit depth */ - uIntf *, /* distance desired/actual bit depth */ - inflate_huft * FAR *, /* literal/length tree result */ - inflate_huft * FAR *)); /* distance tree result */ - -local int inflate_trees_free OF(( - inflate_huft *, /* tables to free */ - z_stream *)); /* for zfree function */ - - -/*+++++*/ -/* infcodes.h -- header to use infcodes.c - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -struct inflate_codes_state; -typedef struct inflate_codes_state FAR inflate_codes_statef; - -local inflate_codes_statef *inflate_codes_new OF(( - uInt, uInt, - inflate_huft *, inflate_huft *, - z_stream *)); - -local int inflate_codes OF(( - inflate_blocks_statef *, - z_stream *, - int)); - -local void inflate_codes_free OF(( - inflate_codes_statef *, - z_stream *)); - - -/*+++++*/ -/* inflate.c -- zlib interface to inflate modules - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* inflate private state */ -struct internal_state { - - /* mode */ - enum { - METHOD, /* waiting for method byte */ - FLAG, /* waiting for flag byte */ - BLOCKS, /* decompressing blocks */ - CHECK4, /* four check bytes to go */ - CHECK3, /* three check bytes to go */ - CHECK2, /* two check bytes to go */ - CHECK1, /* one check byte to go */ - DONE, /* finished check, done */ - BAD} /* got an error--stay here */ - mode; /* current inflate mode */ - - /* mode dependent information */ - union { - uInt method; /* if FLAGS, method byte */ - struct { - uLong was; /* computed check value */ - uLong need; /* stream check value */ - } check; /* if CHECK, check values to compare */ - uInt marker; /* if BAD, inflateSync's marker bytes count */ - } sub; /* submode */ - - /* mode independent information */ - int nowrap; /* flag for no wrapper */ - uInt wbits; /* log2(window size) (8..15, defaults to 15) */ - inflate_blocks_statef - *blocks; /* current inflate_blocks state */ - -}; - - -int inflateReset(z) -z_stream *z; -{ - uLong c; - - if (z == Z_NULL || z->state == Z_NULL) - return Z_STREAM_ERROR; - z->total_in = z->total_out = 0; - z->msg = Z_NULL; - z->state->mode = z->state->nowrap ? BLOCKS : METHOD; - inflate_blocks_reset(z->state->blocks, z, &c); - Trace((stderr, "inflate: reset\n")); - return Z_OK; -} - - -int inflateEnd(z) -z_stream *z; -{ - uLong c; - - if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->blocks != Z_NULL) - inflate_blocks_free(z->state->blocks, z, &c); - ZFREE(z, z->state, sizeof(struct internal_state)); - z->state = Z_NULL; - Trace((stderr, "inflate: end\n")); - return Z_OK; -} - - -int inflateInit2(z, w) -z_stream *z; -int w; -{ - /* initialize state */ - if (z == Z_NULL) - return Z_STREAM_ERROR; -/* if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */ -/* if (z->zfree == Z_NULL) z->zfree = zcfree; */ - if ((z->state = (struct internal_state FAR *) - ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) - return Z_MEM_ERROR; - z->state->blocks = Z_NULL; - - /* handle undocumented nowrap option (no zlib header or check) */ - z->state->nowrap = 0; - if (w < 0) - { - w = - w; - z->state->nowrap = 1; - } - - /* set window size */ - if (w < 8 || w > 15) - { - inflateEnd(z); - return Z_STREAM_ERROR; - } - z->state->wbits = (uInt)w; - - /* create inflate_blocks state */ - if ((z->state->blocks = - inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w)) - == Z_NULL) - { - inflateEnd(z); - return Z_MEM_ERROR; - } - Trace((stderr, "inflate: allocated\n")); - - /* reset state */ - inflateReset(z); - return Z_OK; -} - - -int inflateInit(z) -z_stream *z; -{ - return inflateInit2(z, DEF_WBITS); -} - - -#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;} -#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) - -int inflate(z, f) -z_stream *z; -int f; -{ - int r; - uInt b; - - if (z == Z_NULL || z->next_in == Z_NULL) - return Z_STREAM_ERROR; - r = Z_BUF_ERROR; - while (1) switch (z->state->mode) - { - case METHOD: - NEEDBYTE - if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED) - { - z->state->mode = BAD; - z->msg = "unknown compression method"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - if ((z->state->sub.method >> 4) + 8 > z->state->wbits) - { - z->state->mode = BAD; - z->msg = "invalid window size"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - z->state->mode = FLAG; - case FLAG: - NEEDBYTE - if ((b = NEXTBYTE) & 0x20) - { - z->state->mode = BAD; - z->msg = "invalid reserved bit"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - if (((z->state->sub.method << 8) + b) % 31) - { - z->state->mode = BAD; - z->msg = "incorrect header check"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - Trace((stderr, "inflate: zlib header ok\n")); - z->state->mode = BLOCKS; - case BLOCKS: - r = inflate_blocks(z->state->blocks, z, r); - if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0) - r = inflate_packet_flush(z->state->blocks); - if (r == Z_DATA_ERROR) - { - z->state->mode = BAD; - z->state->sub.marker = 0; /* can try inflateSync */ - break; - } - if (r != Z_STREAM_END) - return r; - r = Z_OK; - inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); - if (z->state->nowrap) - { - z->state->mode = DONE; - break; - } - z->state->mode = CHECK4; - case CHECK4: - NEEDBYTE - z->state->sub.check.need = (uLong)NEXTBYTE << 24; - z->state->mode = CHECK3; - case CHECK3: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 16; - z->state->mode = CHECK2; - case CHECK2: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 8; - z->state->mode = CHECK1; - case CHECK1: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE; - - if (z->state->sub.check.was != z->state->sub.check.need) - { - z->state->mode = BAD; - z->msg = "incorrect data check"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - Trace((stderr, "inflate: zlib check ok\n")); - z->state->mode = DONE; - case DONE: - return Z_STREAM_END; - case BAD: - return Z_DATA_ERROR; - default: - return Z_STREAM_ERROR; - } - - empty: - if (f != Z_PACKET_FLUSH) - return r; - z->state->mode = BAD; - z->state->sub.marker = 0; /* can try inflateSync */ - return Z_DATA_ERROR; -} - -/* - * This subroutine adds the data at next_in/avail_in to the output history - * without performing any output. The output buffer must be "caught up"; - * i.e. no pending output (hence s->read equals s->write), and the state must - * be BLOCKS (i.e. we should be willing to see the start of a series of - * BLOCKS). On exit, the output will also be caught up, and the checksum - * will have been updated if need be. - */ - -int inflateIncomp(z) -z_stream *z; -{ - if (z->state->mode != BLOCKS) - return Z_DATA_ERROR; - return inflate_addhistory(z->state->blocks, z); -} - - -int inflateSync(z) -z_stream *z; -{ - uInt n; /* number of bytes to look at */ - Bytef *p; /* pointer to bytes */ - uInt m; /* number of marker bytes found in a row */ - uLong r, w; /* temporaries to save total_in and total_out */ - - /* set up */ - if (z == Z_NULL || z->state == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->mode != BAD) - { - z->state->mode = BAD; - z->state->sub.marker = 0; - } - if ((n = z->avail_in) == 0) - return Z_BUF_ERROR; - p = z->next_in; - m = z->state->sub.marker; - - /* search */ - while (n && m < 4) - { - if (*p == (Byte)(m < 2 ? 0 : 0xff)) - m++; - else if (*p) - m = 0; - else - m = 4 - m; - p++, n--; - } - - /* restore */ - z->total_in += p - z->next_in; - z->next_in = p; - z->avail_in = n; - z->state->sub.marker = m; - - /* return no joy or set up to restart on a new block */ - if (m != 4) - return Z_DATA_ERROR; - r = z->total_in; w = z->total_out; - inflateReset(z); - z->total_in = r; z->total_out = w; - z->state->mode = BLOCKS; - return Z_OK; -} - -#undef NEEDBYTE -#undef NEXTBYTE - -/*+++++*/ -/* infutil.h -- types and macros common to blocks and codes - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* inflate blocks semi-private state */ -struct inflate_blocks_state { - - /* mode */ - enum { - TYPE, /* get type bits (3, including end bit) */ - LENS, /* get lengths for stored */ - STORED, /* processing stored block */ - TABLE, /* get table lengths */ - BTREE, /* get bit lengths tree for a dynamic block */ - DTREE, /* get length, distance trees for a dynamic block */ - CODES, /* processing fixed or dynamic block */ - DRY, /* output remaining window bytes */ - DONEB, /* finished last block, done */ - BADB} /* got a data error--stuck here */ - mode; /* current inflate_block mode */ - - /* mode dependent information */ - union { - uInt left; /* if STORED, bytes left to copy */ - struct { - uInt table; /* table lengths (14 bits) */ - uInt index; /* index into blens (or border) */ - uIntf *blens; /* bit lengths of codes */ - uInt bb; /* bit length tree depth */ - inflate_huft *tb; /* bit length decoding tree */ - int nblens; /* # elements allocated at blens */ - } trees; /* if DTREE, decoding info for trees */ - struct { - inflate_huft *tl, *td; /* trees to free */ - inflate_codes_statef - *codes; - } decode; /* if CODES, current state */ - } sub; /* submode */ - uInt last; /* true if this block is the last block */ - - /* mode independent information */ - uInt bitk; /* bits in bit buffer */ - uLong bitb; /* bit buffer */ - Bytef *window; /* sliding window */ - Bytef *end; /* one byte after sliding window */ - Bytef *read; /* window read pointer */ - Bytef *write; /* window write pointer */ - check_func checkfn; /* check function */ - uLong check; /* check on output */ - -}; - - -/* defines for inflate input/output */ -/* update pointers and return */ -#define UPDBITS {s->bitb=b;s->bitk=k;} -#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} -#define UPDOUT {s->write=q;} -#define UPDATE {UPDBITS UPDIN UPDOUT} -#define LEAVE {UPDATE return inflate_flush(s,z,r);} -/* get bytes and bits */ -#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} -#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} -#define NEXTBYTE (n--,*p++) -#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} -/* output bytes */ -#define WAVAIL (qread?s->read-q-1:s->end-q) -#define LOADOUT {q=s->write;m=WAVAIL;} -#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}} -#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} -#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} -#define OUTBYTE(a) {*q++=(Byte)(a);m--;} -/* load local pointers */ -#define LOAD {LOADIN LOADOUT} - -/* - * The IBM 150 firmware munges the data right after _etext[]. This - * protects it. -- Cort - */ -/* And'ing with mask[n] masks the lower n bits */ -local uInt inflate_mask[] = { - 0x0000, - 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, - 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -}; - -/* copy as much as possible from the sliding window to the output area */ -local int inflate_flush OF(( - inflate_blocks_statef *, - z_stream *, - int)); - -/*+++++*/ -/* inffast.h -- header to use inffast.c - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -local int inflate_fast OF(( - uInt, - uInt, - inflate_huft *, - inflate_huft *, - inflate_blocks_statef *, - z_stream *)); - - -/*+++++*/ -/* infblock.c -- interpret and process block types to last block - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* Table for deflate from PKZIP's appnote.txt. */ -local uInt border[] = { /* Order of the bit length code lengths */ - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - -/* - Notes beyond the 1.93a appnote.txt: - - 1. Distance pointers never point before the beginning of the output - stream. - 2. Distance pointers can point back across blocks, up to 32k away. - 3. There is an implied maximum of 7 bits for the bit length table and - 15 bits for the actual data. - 4. If only one code exists, then it is encoded using one bit. (Zero - would be more efficient, but perhaps a little confusing.) If two - codes exist, they are coded using one bit each (0 and 1). - 5. There is no way of sending zero distance codes--a dummy must be - sent if there are none. (History: a pre 2.0 version of PKZIP would - store blocks with no distance codes, but this was discovered to be - too harsh a criterion.) Valid only for 1.93a. 2.04c does allow - zero distance codes, which is sent as one code of zero bits in - length. - 6. There are up to 286 literal/length codes. Code 256 represents the - end-of-block. Note however that the static length tree defines - 288 codes just to fill out the Huffman codes. Codes 286 and 287 - cannot be used though, since there is no length base or extra bits - defined for them. Similarily, there are up to 30 distance codes. - However, static trees define 32 codes (all 5 bits) to fill out the - Huffman codes, but the last two had better not show up in the data. - 7. Unzip can check dynamic Huffman blocks for complete code sets. - The exception is that a single code would not be complete (see #4). - 8. The five bits following the block type is really the number of - literal codes sent minus 257. - 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits - (1+6+6). Therefore, to output three times the length, you output - three codes (1+1+1), whereas to output four times the same length, - you only need two codes (1+3). Hmm. - 10. In the tree reconstruction algorithm, Code = Code + Increment - only if BitLength(i) is not zero. (Pretty obvious.) - 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) - 12. Note: length code 284 can represent 227-258, but length code 285 - really is 258. The last length deserves its own, short code - since it gets used a lot in very redundant files. The length - 258 is special since 258 - 3 (the min match length) is 255. - 13. The literal/length and distance code bit lengths are read as a - single stream of lengths. It is possible (and advantageous) for - a repeat code (16, 17, or 18) to go across the boundary between - the two sets of lengths. - */ - - -local void inflate_blocks_reset(s, z, c) -inflate_blocks_statef *s; -z_stream *z; -uLongf *c; -{ - if (s->checkfn != Z_NULL) - *c = s->check; - if (s->mode == BTREE || s->mode == DTREE) - ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt)); - if (s->mode == CODES) - { - inflate_codes_free(s->sub.decode.codes, z); - inflate_trees_free(s->sub.decode.td, z); - inflate_trees_free(s->sub.decode.tl, z); - } - s->mode = TYPE; - s->bitk = 0; - s->bitb = 0; - s->read = s->write = s->window; - if (s->checkfn != Z_NULL) - s->check = (*s->checkfn)(0L, Z_NULL, 0); - if (z->outcb != Z_NULL) - (*z->outcb)(Z_NULL, 0); - Trace((stderr, "inflate: blocks reset\n")); -} - - -local inflate_blocks_statef *inflate_blocks_new(z, c, w) -z_stream *z; -check_func c; -uInt w; -{ - inflate_blocks_statef *s; - - if ((s = (inflate_blocks_statef *)ZALLOC - (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) - return s; - if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) - { - ZFREE(z, s, sizeof(struct inflate_blocks_state)); - return Z_NULL; - } - s->end = s->window + w; - s->checkfn = c; - s->mode = TYPE; - Trace((stderr, "inflate: blocks allocated\n")); - inflate_blocks_reset(s, z, &s->check); - return s; -} - - -local int inflate_blocks(s, z, r) -inflate_blocks_statef *s; -z_stream *z; -int r; -{ - uInt t; /* temporary storage */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input based on current state */ - while (1) switch (s->mode) - { - case TYPE: - NEEDBITS(3) - t = (uInt)b & 7; - s->last = t & 1; - switch (t >> 1) - { - case 0: /* stored */ - Trace((stderr, "inflate: stored block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - t = k & 7; /* go to byte boundary */ - DUMPBITS(t) - s->mode = LENS; /* get length of stored block */ - break; - case 1: /* fixed */ - Trace((stderr, "inflate: fixed codes block%s\n", - s->last ? " (last)" : "")); - { - uInt bl, bd; - inflate_huft *tl, *td; - - inflate_trees_fixed(&bl, &bd, &tl, &td); - s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); - if (s->sub.decode.codes == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - s->sub.decode.tl = Z_NULL; /* don't try to free these */ - s->sub.decode.td = Z_NULL; - } - DUMPBITS(3) - s->mode = CODES; - break; - case 2: /* dynamic */ - Trace((stderr, "inflate: dynamic codes block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - s->mode = TABLE; - break; - case 3: /* illegal */ - DUMPBITS(3) - s->mode = BADB; - z->msg = "invalid block type"; - r = Z_DATA_ERROR; - LEAVE - } - break; - case LENS: - NEEDBITS(32) - if (((~b) >> 16) != (b & 0xffff)) - { - s->mode = BADB; - z->msg = "invalid stored block lengths"; - r = Z_DATA_ERROR; - LEAVE - } - s->sub.left = (uInt)b & 0xffff; - b = k = 0; /* dump bits */ - Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); - s->mode = s->sub.left ? STORED : TYPE; - break; - case STORED: - if (n == 0) - LEAVE - NEEDOUT - t = s->sub.left; - if (t > n) t = n; - if (t > m) t = m; - zmemcpy(q, p, t); - p += t; n -= t; - q += t; m -= t; - if ((s->sub.left -= t) != 0) - break; - Tracev((stderr, "inflate: stored end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - s->mode = s->last ? DRY : TYPE; - break; - case TABLE: - NEEDBITS(14) - s->sub.trees.table = t = (uInt)b & 0x3fff; -#ifndef PKZIP_BUG_WORKAROUND - if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) - { - s->mode = BADB; - z->msg = "too many length or distance symbols"; - r = Z_DATA_ERROR; - LEAVE - } -#endif - t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); - if (t < 19) - t = 19; - if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - s->sub.trees.nblens = t; - DUMPBITS(14) - s->sub.trees.index = 0; - Tracev((stderr, "inflate: table sizes ok\n")); - s->mode = BTREE; - case BTREE: - while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) - { - NEEDBITS(3) - s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; - DUMPBITS(3) - } - while (s->sub.trees.index < 19) - s->sub.trees.blens[border[s->sub.trees.index++]] = 0; - s->sub.trees.bb = 7; - t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, - &s->sub.trees.tb, z); - if (t != Z_OK) - { - r = t; - if (r == Z_DATA_ERROR) - s->mode = BADB; - LEAVE - } - s->sub.trees.index = 0; - Tracev((stderr, "inflate: bits tree ok\n")); - s->mode = DTREE; - case DTREE: - while (t = s->sub.trees.table, - s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) - { - inflate_huft *h; - uInt i, j, c; - - t = s->sub.trees.bb; - NEEDBITS(t) - h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); - t = h->word.what.Bits; - c = h->more.Base; - if (c < 16) - { - DUMPBITS(t) - s->sub.trees.blens[s->sub.trees.index++] = c; - } - else /* c == 16..18 */ - { - i = c == 18 ? 7 : c - 14; - j = c == 18 ? 11 : 3; - NEEDBITS(t + i) - DUMPBITS(t) - j += (uInt)b & inflate_mask[i]; - DUMPBITS(i) - i = s->sub.trees.index; - t = s->sub.trees.table; - if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || - (c == 16 && i < 1)) - { - s->mode = BADB; - z->msg = "invalid bit length repeat"; - r = Z_DATA_ERROR; - LEAVE - } - c = c == 16 ? s->sub.trees.blens[i - 1] : 0; - do { - s->sub.trees.blens[i++] = c; - } while (--j); - s->sub.trees.index = i; - } - } - inflate_trees_free(s->sub.trees.tb, z); - s->sub.trees.tb = Z_NULL; - { - uInt bl, bd; - inflate_huft *tl, *td; - inflate_codes_statef *c; - - bl = 9; /* must be <= 9 for lookahead assumptions */ - bd = 6; /* must be <= 9 for lookahead assumptions */ - t = s->sub.trees.table; - t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), - s->sub.trees.blens, &bl, &bd, &tl, &td, z); - if (t != Z_OK) - { - if (t == (uInt)Z_DATA_ERROR) - s->mode = BADB; - r = t; - LEAVE - } - Tracev((stderr, "inflate: trees ok\n")); - if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) - { - inflate_trees_free(td, z); - inflate_trees_free(tl, z); - r = Z_MEM_ERROR; - LEAVE - } - ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt)); - s->sub.decode.codes = c; - s->sub.decode.tl = tl; - s->sub.decode.td = td; - } - s->mode = CODES; - case CODES: - UPDATE - if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) - return inflate_flush(s, z, r); - r = Z_OK; - inflate_codes_free(s->sub.decode.codes, z); - inflate_trees_free(s->sub.decode.td, z); - inflate_trees_free(s->sub.decode.tl, z); - LOAD - Tracev((stderr, "inflate: codes end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - if (!s->last) - { - s->mode = TYPE; - break; - } - if (k > 7) /* return unused byte, if any */ - { - Assert(k < 16, "inflate_codes grabbed too many bytes") - k -= 8; - n++; - p--; /* can always return one */ - } - s->mode = DRY; - case DRY: - FLUSH - if (s->read != s->write) - LEAVE - s->mode = DONEB; - case DONEB: - r = Z_STREAM_END; - LEAVE - case BADB: - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -} - - -local int inflate_blocks_free(s, z, c) -inflate_blocks_statef *s; -z_stream *z; -uLongf *c; -{ - inflate_blocks_reset(s, z, c); - ZFREE(z, s->window, s->end - s->window); - ZFREE(z, s, sizeof(struct inflate_blocks_state)); - Trace((stderr, "inflate: blocks freed\n")); - return Z_OK; -} - -/* - * This subroutine adds the data at next_in/avail_in to the output history - * without performing any output. The output buffer must be "caught up"; - * i.e. no pending output (hence s->read equals s->write), and the state must - * be BLOCKS (i.e. we should be willing to see the start of a series of - * BLOCKS). On exit, the output will also be caught up, and the checksum - * will have been updated if need be. - */ -local int inflate_addhistory(s, z) -inflate_blocks_statef *s; -z_stream *z; -{ - uLong b; /* bit buffer */ /* NOT USED HERE */ - uInt k; /* bits in bit buffer */ /* NOT USED HERE */ - uInt t; /* temporary storage */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - - if (s->read != s->write) - return Z_STREAM_ERROR; - if (s->mode != TYPE) - return Z_DATA_ERROR; - - /* we're ready to rock */ - LOAD - /* while there is input ready, copy to output buffer, moving - * pointers as needed. - */ - while (n) { - t = n; /* how many to do */ - /* is there room until end of buffer? */ - if (t > m) t = m; - /* update check information */ - if (s->checkfn != Z_NULL) - s->check = (*s->checkfn)(s->check, q, t); - /* output callback */ - if (z->outcb != Z_NULL) - (*z->outcb)(q, t); - zmemcpy(q, p, t); - q += t; - p += t; - n -= t; - z->total_out += t; - s->read = q; /* drag read pointer forward */ -/* WRAP */ /* expand WRAP macro by hand to handle s->read */ - if (q == s->end) { - s->read = q = s->window; - m = WAVAIL; - } - } - UPDATE - return Z_OK; -} - - -/* - * At the end of a Deflate-compressed PPP packet, we expect to have seen - * a `stored' block type value but not the (zero) length bytes. - */ -local int inflate_packet_flush(s) - inflate_blocks_statef *s; -{ - if (s->mode != LENS) - return Z_DATA_ERROR; - s->mode = TYPE; - return Z_OK; -} - - -/*+++++*/ -/* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* simplify the use of the inflate_huft type with some defines */ -#define base more.Base -#define next more.Next -#define exop word.what.Exop -#define bits word.what.Bits - - -local int huft_build OF(( - uIntf *, /* code lengths in bits */ - uInt, /* number of codes */ - uInt, /* number of "simple" codes */ - uIntf *, /* list of base values for non-simple codes */ - uIntf *, /* list of extra bits for non-simple codes */ - inflate_huft * FAR*,/* result: starting table */ - uIntf *, /* maximum lookup bits (returns actual) */ - z_stream *)); /* for zalloc function */ - -local voidpf falloc OF(( - voidpf, /* opaque pointer (not used) */ - uInt, /* number of items */ - uInt)); /* size of item */ - -local void ffree OF(( - voidpf q, /* opaque pointer (not used) */ - voidpf p, /* what to free (not used) */ - uInt n)); /* number of bytes (not used) */ - -/* Tables for deflate from PKZIP's appnote.txt. */ -local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - /* actually lengths - 2; also see note #13 above about 258 */ -local uInt cplext[] = { /* Extra bits for literal codes 257..285 */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */ -local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; -local uInt cpdext[] = { /* Extra bits for distance codes */ - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; - -/* - Huffman code decoding is performed using a multi-level table lookup. - The fastest way to decode is to simply build a lookup table whose - size is determined by the longest code. However, the time it takes - to build this table can also be a factor if the data being decoded - is not very long. The most common codes are necessarily the - shortest codes, so those codes dominate the decoding time, and hence - the speed. The idea is you can have a shorter table that decodes the - shorter, more probable codes, and then point to subsidiary tables for - the longer codes. The time it costs to decode the longer codes is - then traded against the time it takes to make longer tables. - - This results of this trade are in the variables lbits and dbits - below. lbits is the number of bits the first level table for literal/ - length codes can decode in one step, and dbits is the same thing for - the distance codes. Subsequent tables are also less than or equal to - those sizes. These values may be adjusted either when all of the - codes are shorter than that, in which case the longest code length in - bits is used, or when the shortest code is *longer* than the requested - table size, in which case the length of the shortest code in bits is - used. - - There are two different values for the two tables, since they code a - different number of possibilities each. The literal/length table - codes 286 possible values, or in a flat code, a little over eight - bits. The distance table codes 30 possible values, or a little less - than five bits, flat. The optimum values for speed end up being - about one bit more than those, so lbits is 8+1 and dbits is 5+1. - The optimum values may differ though from machine to machine, and - possibly even between compilers. Your mileage may vary. - */ - - -/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ -#define BMAX 15 /* maximum bit length of any code */ -#define N_MAX 288 /* maximum number of codes in any set */ - -#ifdef DEBUG_ZLIB - uInt inflate_hufts; -#endif - -local int huft_build(b, n, s, d, e, t, m, zs) -uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ -uInt n; /* number of codes (assumed <= N_MAX) */ -uInt s; /* number of simple-valued codes (0..s-1) */ -uIntf *d; /* list of base values for non-simple codes */ -uIntf *e; /* list of extra bits for non-simple codes */ -inflate_huft * FAR *t; /* result: starting table */ -uIntf *m; /* maximum lookup bits, returns actual */ -z_stream *zs; /* for zalloc function */ -/* Given a list of code lengths and a maximum table size, make a set of - tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR - if the given code set is incomplete (the tables are still built in this - case), Z_DATA_ERROR if the input is invalid (all zero length codes or an - over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */ -{ - - uInt a; /* counter for codes of length k */ - uInt c[BMAX+1]; /* bit length count table */ - uInt f; /* i repeats in table every f entries */ - int g; /* maximum code length */ - int h; /* table level */ - register uInt i; /* counter, current code */ - register uInt j; /* counter */ - register int k; /* number of bits in current code */ - int l; /* bits per table (returned in m) */ - register uIntf *p; /* pointer into c[], b[], or v[] */ - inflate_huft *q; /* points to current table */ - struct inflate_huft_s r; /* table entry for structure assignment */ - inflate_huft *u[BMAX]; /* table stack */ - uInt v[N_MAX]; /* values in order of bit length */ - register int w; /* bits before this table == (l * h) */ - uInt x[BMAX+1]; /* bit offsets, then code stack */ - uIntf *xp; /* pointer into x */ - int y; /* number of dummy codes added */ - uInt z; /* number of entries in current table */ - - - /* Generate counts for each bit length */ - p = c; -#define C0 *p++ = 0; -#define C2 C0 C0 C0 C0 -#define C4 C2 C2 C2 C2 - C4 /* clear c[]--assume BMAX+1 is 16 */ - p = b; i = n; - do { - c[*p++]++; /* assume all entries <= BMAX */ - } while (--i); - if (c[0] == n) /* null input--all zero length codes */ - { - *t = (inflate_huft *)Z_NULL; - *m = 0; - return Z_OK; - } - - - /* Find minimum and maximum length, bound *m by those */ - l = *m; - for (j = 1; j <= BMAX; j++) - if (c[j]) - break; - k = j; /* minimum code length */ - if ((uInt)l < j) - l = j; - for (i = BMAX; i; i--) - if (c[i]) - break; - g = i; /* maximum code length */ - if ((uInt)l > i) - l = i; - *m = l; - - - /* Adjust last length count to fill out codes, if needed */ - for (y = 1 << j; j < i; j++, y <<= 1) - if ((y -= c[j]) < 0) - return Z_DATA_ERROR; - if ((y -= c[i]) < 0) - return Z_DATA_ERROR; - c[i] += y; - - - /* Generate starting offsets into the value table for each length */ - x[1] = j = 0; - p = c + 1; xp = x + 2; - while (--i) { /* note that i == g from above */ - *xp++ = (j += *p++); - } - - - /* Make a table of values in order of bit lengths */ - p = b; i = 0; - do { - if ((j = *p++) != 0) - v[x[j]++] = i; - } while (++i < n); - - - /* Generate the Huffman codes and for each, make the table entries */ - x[0] = i = 0; /* first Huffman code is zero */ - p = v; /* grab values in bit order */ - h = -1; /* no tables yet--level -1 */ - w = -l; /* bits decoded == (l * h) */ - u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ - q = (inflate_huft *)Z_NULL; /* ditto */ - z = 0; /* ditto */ - - /* go through the bit lengths (k already is bits in shortest code) */ - for (; k <= g; k++) - { - a = c[k]; - while (a--) - { - /* here i is the Huffman code of length k bits for value *p */ - /* make tables up to required level */ - while (k > w + l) - { - h++; - w += l; /* previous table always l bits */ - - /* compute minimum size table less than or equal to l bits */ - z = (z = g - w) > (uInt)l ? l : z; /* table size upper limit */ - if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ - { /* too few codes for k-w bit table */ - f -= a + 1; /* deduct codes from patterns left */ - xp = c + k; - if (j < z) - while (++j < z) /* try smaller tables up to z bits */ - { - if ((f <<= 1) <= *++xp) - break; /* enough codes to use up j bits */ - f -= *xp; /* else deduct codes from patterns */ - } - } - z = 1 << j; /* table entries for j-bit table */ - - /* allocate and link in new table */ - if ((q = (inflate_huft *)ZALLOC - (zs,z + 1,sizeof(inflate_huft))) == Z_NULL) - { - if (h) - inflate_trees_free(u[0], zs); - return Z_MEM_ERROR; /* not enough memory */ - } - q->word.Nalloc = z + 1; -#ifdef DEBUG_ZLIB - inflate_hufts += z + 1; -#endif - *t = q + 1; /* link to list for huft_free() */ - *(t = &(q->next)) = Z_NULL; - u[h] = ++q; /* table starts after link */ - - /* connect to last table, if there is one */ - if (h) - { - x[h] = i; /* save pattern for backing up */ - r.bits = (Byte)l; /* bits to dump before this table */ - r.exop = (Byte)j; /* bits in this table */ - r.next = q; /* pointer to this table */ - j = i >> (w - l); /* (get around Turbo C bug) */ - u[h-1][j] = r; /* connect to last table */ - } - } - - /* set up table entry in r */ - r.bits = (Byte)(k - w); - if (p >= v + n) - r.exop = 128 + 64; /* out of values--invalid code */ - else if (*p < s) - { - r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ - r.base = *p++; /* simple code is just the value */ - } - else - { - r.exop = (Byte)e[*p - s] + 16 + 64; /* non-simple--look up in lists */ - r.base = d[*p++ - s]; - } - - /* fill code-like entries with r */ - f = 1 << (k - w); - for (j = i >> w; j < z; j += f) - q[j] = r; - - /* backwards increment the k-bit code i */ - for (j = 1 << (k - 1); i & j; j >>= 1) - i ^= j; - i ^= j; - - /* backup over finished tables */ - while ((i & ((1 << w) - 1)) != x[h]) - { - h--; /* don't need to update q */ - w -= l; - } - } - } - - - /* Return Z_BUF_ERROR if we were given an incomplete table */ - return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; -} - - -local int inflate_trees_bits(c, bb, tb, z) -uIntf *c; /* 19 code lengths */ -uIntf *bb; /* bits tree desired/actual depth */ -inflate_huft * FAR *tb; /* bits tree result */ -z_stream *z; /* for zfree function */ -{ - int r; - - r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z); - if (r == Z_DATA_ERROR) - z->msg = "oversubscribed dynamic bit lengths tree"; - else if (r == Z_BUF_ERROR) - { - inflate_trees_free(*tb, z); - z->msg = "incomplete dynamic bit lengths tree"; - r = Z_DATA_ERROR; - } - return r; -} - - -local int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z) -uInt nl; /* number of literal/length codes */ -uInt nd; /* number of distance codes */ -uIntf *c; /* that many (total) code lengths */ -uIntf *bl; /* literal desired/actual bit depth */ -uIntf *bd; /* distance desired/actual bit depth */ -inflate_huft * FAR *tl; /* literal/length tree result */ -inflate_huft * FAR *td; /* distance tree result */ -z_stream *z; /* for zfree function */ -{ - int r; - - /* build literal/length tree */ - if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK) - { - if (r == Z_DATA_ERROR) - z->msg = "oversubscribed literal/length tree"; - else if (r == Z_BUF_ERROR) - { - inflate_trees_free(*tl, z); - z->msg = "incomplete literal/length tree"; - r = Z_DATA_ERROR; - } - return r; - } - - /* build distance tree */ - if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK) - { - if (r == Z_DATA_ERROR) - z->msg = "oversubscribed literal/length tree"; - else if (r == Z_BUF_ERROR) { -#ifdef PKZIP_BUG_WORKAROUND - r = Z_OK; - } -#else - inflate_trees_free(*td, z); - z->msg = "incomplete literal/length tree"; - r = Z_DATA_ERROR; - } - inflate_trees_free(*tl, z); - return r; -#endif - } - - /* done */ - return Z_OK; -} - - -/* build fixed tables only once--keep them here */ -local int fixed_lock = 0; -local int fixed_built = 0; -#define FIXEDH 530 /* number of hufts used by fixed tables */ -local uInt fixed_left = FIXEDH; -local inflate_huft fixed_mem[FIXEDH]; -local uInt fixed_bl; -local uInt fixed_bd; -local inflate_huft *fixed_tl; -local inflate_huft *fixed_td; - - -local voidpf falloc(q, n, s) -voidpf q; /* opaque pointer (not used) */ -uInt n; /* number of items */ -uInt s; /* size of item */ -{ - Assert(s == sizeof(inflate_huft) && n <= fixed_left, - "inflate_trees falloc overflow"); - if (q) s++; /* to make some compilers happy */ - fixed_left -= n; - return (voidpf)(fixed_mem + fixed_left); -} - - -local void ffree(q, p, n) -voidpf q; -voidpf p; -uInt n; -{ - Assert(0, "inflate_trees ffree called!"); - if (q) q = p; /* to make some compilers happy */ -} - - -local int inflate_trees_fixed(bl, bd, tl, td) -uIntf *bl; /* literal desired/actual bit depth */ -uIntf *bd; /* distance desired/actual bit depth */ -inflate_huft * FAR *tl; /* literal/length tree result */ -inflate_huft * FAR *td; /* distance tree result */ -{ - /* build fixed tables if not built already--lock out other instances */ - while (++fixed_lock > 1) - fixed_lock--; - if (!fixed_built) - { - int k; /* temporary variable */ - unsigned c[288]; /* length list for huft_build */ - z_stream z; /* for falloc function */ - - /* set up fake z_stream for memory routines */ - z.zalloc = falloc; - z.zfree = ffree; - z.opaque = Z_NULL; - - /* literal table */ - for (k = 0; k < 144; k++) - c[k] = 8; - for (; k < 256; k++) - c[k] = 9; - for (; k < 280; k++) - c[k] = 7; - for (; k < 288; k++) - c[k] = 8; - fixed_bl = 7; - huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z); - - /* distance table */ - for (k = 0; k < 30; k++) - c[k] = 5; - fixed_bd = 5; - huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z); - - /* done */ - fixed_built = 1; - } - fixed_lock--; - *bl = fixed_bl; - *bd = fixed_bd; - *tl = fixed_tl; - *td = fixed_td; - return Z_OK; -} - - -local int inflate_trees_free(t, z) -inflate_huft *t; /* table to free */ -z_stream *z; /* for zfree function */ -/* Free the malloc'ed tables built by huft_build(), which makes a linked - list of the tables it made, with the links in a dummy first entry of - each table. */ -{ - register inflate_huft *p, *q; - - /* Go through linked list, freeing from the malloced (t[-1]) address. */ - p = t; - while (p != Z_NULL) - { - q = (--p)->next; - ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft)); - p = q; - } - return Z_OK; -} - -/*+++++*/ -/* infcodes.c -- process literals and length/distance pairs - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* simplify the use of the inflate_huft type with some defines */ -#define base more.Base -#define next more.Next -#define exop word.what.Exop -#define bits word.what.Bits - -/* inflate codes private state */ -struct inflate_codes_state { - - /* mode */ - enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - START, /* x: set up for LEN */ - LEN, /* i: get length/literal/eob next */ - LENEXT, /* i: getting length extra (have base) */ - DIST, /* i: get distance next */ - DISTEXT, /* i: getting distance extra */ - COPY, /* o: copying bytes in window, waiting for space */ - LIT, /* o: got literal, waiting for output space */ - WASH, /* o: got eob, possibly still output waiting */ - END, /* x: got eob and all data flushed */ - BADCODE} /* x: got error */ - mode; /* current inflate_codes mode */ - - /* mode dependent information */ - uInt len; - union { - struct { - inflate_huft *tree; /* pointer into tree */ - uInt need; /* bits needed */ - } code; /* if LEN or DIST, where in tree */ - uInt lit; /* if LIT, literal */ - struct { - uInt get; /* bits to get for extra */ - uInt dist; /* distance back to copy from */ - } copy; /* if EXT or COPY, where and how much */ - } sub; /* submode */ - - /* mode independent information */ - Byte lbits; /* ltree bits decoded per branch */ - Byte dbits; /* dtree bits decoder per branch */ - inflate_huft *ltree; /* literal/length/eob tree */ - inflate_huft *dtree; /* distance tree */ - -}; - - -local inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) -uInt bl, bd; -inflate_huft *tl, *td; -z_stream *z; -{ - inflate_codes_statef *c; - - if ((c = (inflate_codes_statef *) - ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) - { - c->mode = START; - c->lbits = (Byte)bl; - c->dbits = (Byte)bd; - c->ltree = tl; - c->dtree = td; - Tracev((stderr, "inflate: codes new\n")); - } - return c; -} - - -local int inflate_codes(s, z, r) -inflate_blocks_statef *s; -z_stream *z; -int r; -{ - uInt j; /* temporary storage */ - inflate_huft *t; /* temporary pointer */ - uInt e; /* extra bits or operation */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - Bytef *f; /* pointer to copy strings from */ - inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input and output based on current state */ - while (1) switch (c->mode) - { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - case START: /* x: set up for LEN */ -#ifndef SLOW - if (m >= 258 && n >= 10) - { - UPDATE - r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); - LOAD - if (r != Z_OK) - { - c->mode = r == Z_STREAM_END ? WASH : BADCODE; - break; - } - } -#endif /* !SLOW */ - c->sub.code.need = c->lbits; - c->sub.code.tree = c->ltree; - c->mode = LEN; - case LEN: /* i: get length/literal/eob next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e == 0) /* literal */ - { - c->sub.lit = t->base; - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", t->base)); - c->mode = LIT; - break; - } - if (e & 16) /* length */ - { - c->sub.copy.get = e & 15; - c->len = t->base; - c->mode = LENEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t->next; - break; - } - if (e & 32) /* end of block */ - { - Tracevv((stderr, "inflate: end of block\n")); - c->mode = WASH; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = "invalid literal/length code"; - r = Z_DATA_ERROR; - LEAVE - case LENEXT: /* i: getting length extra (have base) */ - j = c->sub.copy.get; - NEEDBITS(j) - c->len += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - c->sub.code.need = c->dbits; - c->sub.code.tree = c->dtree; - Tracevv((stderr, "inflate: length %u\n", c->len)); - c->mode = DIST; - case DIST: /* i: get distance next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e & 16) /* distance */ - { - c->sub.copy.get = e & 15; - c->sub.copy.dist = t->base; - c->mode = DISTEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t->next; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = "invalid distance code"; - r = Z_DATA_ERROR; - LEAVE - case DISTEXT: /* i: getting distance extra */ - j = c->sub.copy.get; - NEEDBITS(j) - c->sub.copy.dist += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); - c->mode = COPY; - case COPY: /* o: copying bytes in window, waiting for space */ -#ifndef __TURBOC__ /* Turbo C bug for following expression */ - f = (uInt)(q - s->window) < c->sub.copy.dist ? - s->end - (c->sub.copy.dist - (q - s->window)) : - q - c->sub.copy.dist; -#else - f = q - c->sub.copy.dist; - if ((uInt)(q - s->window) < c->sub.copy.dist) - f = s->end - (c->sub.copy.dist - (q - s->window)); -#endif - while (c->len) - { - NEEDOUT - OUTBYTE(*f++) - if (f == s->end) - f = s->window; - c->len--; - } - c->mode = START; - break; - case LIT: /* o: got literal, waiting for output space */ - NEEDOUT - OUTBYTE(c->sub.lit) - c->mode = START; - break; - case WASH: /* o: got eob, possibly more output */ - FLUSH - if (s->read != s->write) - LEAVE - c->mode = END; - case END: - r = Z_STREAM_END; - LEAVE - case BADCODE: /* x: got error */ - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -} - - -local void inflate_codes_free(c, z) -inflate_codes_statef *c; -z_stream *z; -{ - ZFREE(z, c, sizeof(struct inflate_codes_state)); - Tracev((stderr, "inflate: codes free\n")); -} - -/*+++++*/ -/* inflate_util.c -- data and routines common to blocks and codes - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* copy as much as possible from the sliding window to the output area */ -local int inflate_flush(s, z, r) -inflate_blocks_statef *s; -z_stream *z; -int r; -{ - uInt n; - Bytef *p, *q; - - /* local copies of source and destination pointers */ - p = z->next_out; - q = s->read; - - /* compute number of bytes to copy as far as end of window */ - n = (uInt)((q <= s->write ? s->write : s->end) - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - s->check = (*s->checkfn)(s->check, q, n); - - /* output callback */ - if (z->outcb != Z_NULL) - (*z->outcb)(q, n); - - /* copy as far as end of window */ - zmemcpy(p, q, n); - p += n; - q += n; - - /* see if more to copy at beginning of window */ - if (q == s->end) - { - /* wrap pointers */ - q = s->window; - if (s->write == s->end) - s->write = s->window; - - /* compute bytes to copy */ - n = (uInt)(s->write - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - s->check = (*s->checkfn)(s->check, q, n); - - /* output callback */ - if (z->outcb != Z_NULL) - (*z->outcb)(q, n); - - /* copy */ - zmemcpy(p, q, n); - p += n; - q += n; - } - - /* update pointers */ - z->next_out = p; - s->read = q; - - /* done */ - return r; -} - - -/*+++++*/ -/* inffast.c -- process literals and length/distance pairs fast - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* simplify the use of the inflate_huft type with some defines */ -#define base more.Base -#define next more.Next -#define exop word.what.Exop -#define bits word.what.Bits - -/* macros for bit input with no checking and for returning unused bytes */ -#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<>3);p-=c;k&=7;} - -/* Called with number of bytes left to write in window at least 258 - (the maximum string length) and number of input bytes available - at least ten. The ten bytes are six bytes for the longest length/ - distance pair plus four bytes for overloading the bit buffer. */ - -local int inflate_fast(bl, bd, tl, td, s, z) -uInt bl, bd; -inflate_huft *tl, *td; -inflate_blocks_statef *s; -z_stream *z; -{ - inflate_huft *t; /* temporary pointer */ - uInt e; /* extra bits or operation */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - uInt ml; /* mask for literal/length tree */ - uInt md; /* mask for distance tree */ - uInt c; /* bytes to copy */ - uInt d; /* distance back to copy from */ - Bytef *r; /* copy source pointer */ - - /* load input, output, bit values */ - LOAD - - /* initialize masks */ - ml = inflate_mask[bl]; - md = inflate_mask[bd]; - - /* do until not enough input or output space for fast loop */ - do { /* assume called with m >= 258 && n >= 10 */ - /* get literal/length code */ - GRABBITS(20) /* max bits for literal/length code */ - if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) - { - DUMPBITS(t->bits) - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: * literal '%c'\n" : - "inflate: * literal 0x%02x\n", t->base)); - *q++ = (Byte)t->base; - m--; - continue; - } - do { - DUMPBITS(t->bits) - if (e & 16) - { - /* get extra bits for length */ - e &= 15; - c = t->base + ((uInt)b & inflate_mask[e]); - DUMPBITS(e) - Tracevv((stderr, "inflate: * length %u\n", c)); - - /* decode distance base of block to copy */ - GRABBITS(15); /* max bits for distance code */ - e = (t = td + ((uInt)b & md))->exop; - do { - DUMPBITS(t->bits) - if (e & 16) - { - /* get extra bits to add to distance base */ - e &= 15; - GRABBITS(e) /* get extra bits (up to 13) */ - d = t->base + ((uInt)b & inflate_mask[e]); - DUMPBITS(e) - Tracevv((stderr, "inflate: * distance %u\n", d)); - - /* do the copy */ - m -= c; - if ((uInt)(q - s->window) >= d) /* offset before dest */ - { /* just copy */ - r = q - d; - *q++ = *r++; c--; /* minimum count is three, */ - *q++ = *r++; c--; /* so unroll loop a little */ - } - else /* else offset after destination */ - { - e = d - (q - s->window); /* bytes from offset to end */ - r = s->end - e; /* pointer to offset */ - if (c > e) /* if source crosses, */ - { - c -= e; /* copy to end of window */ - do { - *q++ = *r++; - } while (--e); - r = s->window; /* copy rest from start of window */ - } - } - do { /* copy all or what's left */ - *q++ = *r++; - } while (--c); - break; - } - else if ((e & 64) == 0) - e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop; - else - { - z->msg = "invalid distance code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - } while (1); - break; - } - if ((e & 64) == 0) - { - if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0) - { - DUMPBITS(t->bits) - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: * literal '%c'\n" : - "inflate: * literal 0x%02x\n", t->base)); - *q++ = (Byte)t->base; - m--; - break; - } - } - else if (e & 32) - { - Tracevv((stderr, "inflate: * end of block\n")); - UNGRAB - UPDATE - return Z_STREAM_END; - } - else - { - z->msg = "invalid literal/length code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - } while (1); - } while (m >= 258 && n >= 10); - - /* not enough input or output--restore pointers and return */ - UNGRAB - UPDATE - return Z_OK; -} - - -/*+++++*/ -/* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */ - -char *zlib_version = ZLIB_VERSION; - -char *z_errmsg[] = { -"stream end", /* Z_STREAM_END 1 */ -"", /* Z_OK 0 */ -"file error", /* Z_ERRNO (-1) */ -"stream error", /* Z_STREAM_ERROR (-2) */ -"data error", /* Z_DATA_ERROR (-3) */ -"insufficient memory", /* Z_MEM_ERROR (-4) */ -"buffer error", /* Z_BUF_ERROR (-5) */ -""}; - - -/*+++++*/ -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */ - -#define BASE 65521L /* largest prime smaller than 65536 */ -#define NMAX 5552 -/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - -#define DO1(buf) {s1 += *buf++; s2 += s1;} -#define DO2(buf) DO1(buf); DO1(buf); -#define DO4(buf) DO2(buf); DO2(buf); -#define DO8(buf) DO4(buf); DO4(buf); -#define DO16(buf) DO8(buf); DO8(buf); - -/* ========================================================================= */ -uLong adler32(adler, buf, len) - uLong adler; - Bytef *buf; - uInt len; -{ - unsigned long s1 = adler & 0xffff; - unsigned long s2 = (adler >> 16) & 0xffff; - int k; - - if (buf == Z_NULL) return 1L; - - while (len > 0) { - k = len < NMAX ? len : NMAX; - len -= k; - while (k >= 16) { - DO16(buf); - k -= 16; - } - if (k != 0) do { - DO1(buf); - } while (--k); - s1 %= BASE; - s2 %= BASE; - } - return (s2 << 16) | s1; -} -- cgit v1.2.3 From 1aac831cca66d7ac70e369a09c944c0a54547d32 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 13:52:32 +0100 Subject: lib: prompt for uncompression functions Allow the user to manually select the uncompression support he wants to have so that we have a single point where a user can see which uncompression support will be compiled in. Signed-off-by: Sascha Hauer --- lib/Kconfig | 6 ++++-- lib/lzo/Kconfig | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/Kconfig b/lib/Kconfig index 531398f7c1..e16dd35715 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -1,8 +1,9 @@ +menu "Library routines" config ZLIB - bool + bool "include gzip uncompression support" config BZLIB - bool + bool "include bzip2 uncompression support" config GENERIC_FIND_NEXT_BIT def_bool n @@ -18,3 +19,4 @@ config FDT config OFTREE select FDT bool +endmenu diff --git a/lib/lzo/Kconfig b/lib/lzo/Kconfig index 4016785838..03c3350897 100644 --- a/lib/lzo/Kconfig +++ b/lib/lzo/Kconfig @@ -1,4 +1,5 @@ config LZO_DECOMPRESS + bool "include lzo uncompression support" bool config LZO_COMPRESS -- cgit v1.2.3 From 32daa5509a68f58fe365fadafdb5b1ec5d72fff5 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 15:56:31 +0100 Subject: bootm: do not select uncompression methods Instead, let the user select them manually so that bootm supports all compression types compiled in. Signed-off-by: Sascha Hauer --- commands/Kconfig | 12 ------------ commands/bootm.c | 4 ++-- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/commands/Kconfig b/commands/Kconfig index 93f14b278e..6b21a2ea7d 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -292,18 +292,6 @@ config CMD_BOOTM select CRC32 prompt "bootm" -config CMD_BOOTM_ZLIB - bool - depends on CMD_BOOTM - select ZLIB - prompt "bootm with zlib support" - -config CMD_BOOTM_BZLIB - bool - depends on CMD_BOOTM - select BZLIB - prompt "bootm with bzlib support" - config CMD_BOOTM_SHOW_TYPE bool depends on CMD_BOOTM diff --git a/commands/bootm.c b/commands/bootm.c index e2ed9bec50..01ad4c7da6 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -85,7 +85,7 @@ int relocate_image(struct image_handle *handle, void *load_address) memmove(load_address, data, len); } break; -#ifdef CONFIG_CMD_BOOTM_ZLIB +#ifdef CONFIG_ZLIB case IH_COMP_GZIP: printf (" Uncompressing ... "); @@ -95,7 +95,7 @@ int relocate_image(struct image_handle *handle, void *load_address) return ret; break; #endif -#ifdef CONFIG_CMD_BOOTM_BZLIB +#ifdef CONFIG_BZLIB case IH_COMP_BZIP2: printf (" Uncompressing ... "); -- cgit v1.2.3 From b6996039f622ccc8488176e211bf41315f9691c6 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 25 Nov 2011 18:49:14 +0100 Subject: add file detection support Several filetypes can be autodetected. Barebox could make use of this in several ways: - Add a command to detect filetypes - detect arm zImages and uImages to unify the different boot commands - maybe detect UBI or JFFS2 images to construct parts of the kernel command line - select correct uncompression function based on filetype This patch adds basic support to detect filetypes. Signed-off-by: Sascha Hauer --- common/Makefile | 1 + common/filetype.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/filetype.h | 23 +++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 common/filetype.c create mode 100644 include/filetype.h diff --git a/common/Makefile b/common/Makefile index 3edf38f3ba..55d9dbcb43 100644 --- a/common/Makefile +++ b/common/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_CMD_BOOTM) += image.o obj-y += startup.o obj-y += misc.o obj-y += memsize.o +obj-y += filetype.o obj-$(CONFIG_MENU) += menu.o obj-$(CONFIG_PASSWORD) += password.o obj-$(CONFIG_MODULES) += module.o diff --git a/common/filetype.c b/common/filetype.c new file mode 100644 index 0000000000..5635d40af0 --- /dev/null +++ b/common/filetype.c @@ -0,0 +1,99 @@ +/* + * filetype.c - detect filetypes + * + * Copyright (c) 2011 Sascha Hauer , Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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. + */ +#include +#include +#include +#include +#include +#include + +static const char *filetype_str[] = { + [filetype_unknown] = "unknown", + [filetype_arm_zimage] = "arm Linux zImage", + [filetype_lzo_compressed] = "lzo compressed", + [filetype_arm_barebox] = "arm barebox image", + [filetype_uimage] = "U-Boot uImage", + [filetype_ubi] = "UBI image", + [filetype_jffs2] = "JFFS2 image", + [filetype_gzip] = "gzip compressed", + [filetype_bzip2] = "bzip2 compressed", +}; + +const char *file_type_to_string(enum filetype f) +{ + if (f < ARRAY_SIZE(filetype_str)) + return filetype_str[f]; + + return NULL; +} + +enum filetype file_detect_type(void *_buf) +{ + u32 *buf = _buf; + u8 *buf8 = _buf; + + if (buf[8] == 0x65726162 && buf[9] == 0x00786f62) + return filetype_arm_barebox; + if (buf[9] == 0x016f2818 || buf[9] == 0x18286f01) + return filetype_arm_zimage; + if (buf8[0] == 0x89 && buf8[1] == 0x4c && buf8[2] == 0x5a && + buf8[3] == 0x4f) + return filetype_lzo_compressed; + if (buf[0] == be32_to_cpu(0x27051956)) + return filetype_uimage; + if (buf[0] == 0x23494255) + return filetype_ubi; + if (buf[0] == 0x20031985) + return filetype_jffs2; + if (buf8[0] == 0x1f && buf8[1] == 0x8b && buf8[2] == 0x08) + return filetype_gzip; + if (buf8[0] == 'B' && buf8[1] == 'Z' && buf8[2] == 'h' && + buf8[3] > '0' && buf8[3] <= '9') + return filetype_bzip2; + + return filetype_unknown; +} + +enum filetype file_name_detect_type(const char *filename) +{ + int fd, ret; + void *buf; + enum filetype type = filetype_unknown; + + fd = open(filename, O_RDONLY); + if (fd < 0) + return fd; + + buf = xmalloc(512); + + ret = read(fd, buf, 512); + if (ret != 512) + goto err_out; + + type = file_detect_type(buf); + +err_out: + close(fd); + free(buf); + + return type; +} diff --git a/include/filetype.h b/include/filetype.h new file mode 100644 index 0000000000..64d32ef8b0 --- /dev/null +++ b/include/filetype.h @@ -0,0 +1,23 @@ +#ifndef __FILE_TYPE_H +#define __FILE_TYPE_H + +/* + * List of file types we know + */ +enum filetype { + filetype_unknown, + filetype_arm_zimage, + filetype_lzo_compressed, + filetype_arm_barebox, + filetype_uimage, + filetype_ubi, + filetype_jffs2, + filetype_gzip, + filetype_bzip2, +}; + +const char *file_type_to_string(enum filetype f); +enum filetype file_detect_type(void *_buf); +enum filetype file_name_detect_type(const char *filename); + +#endif /* __FILE_TYPE_H */ -- cgit v1.2.3 From 83d0904980531a4ac96ebc1f5becc52422536dbe Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 21:39:12 +0100 Subject: lzo: export decompress_unlzo function Signed-off-by: Sascha Hauer --- include/lzo.h | 6 ++++++ lib/decompress_unlzo.c | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/lzo.h b/include/lzo.h index 569498596e..b4a514f1f3 100644 --- a/include/lzo.h +++ b/include/lzo.h @@ -43,4 +43,10 @@ int lzo1x_decompress_safe(const unsigned char *src, size_t src_len, int unlzo(int in_fd, int out_fd, int *dest_len); +int decompress_unlzo(u8 *input, int in_len, + int (*fill) (void *, unsigned int), + int (*flush) (void *, unsigned int), + u8 *output, int *posp, + void (*error) (char *x)); + #endif diff --git a/lib/decompress_unlzo.c b/lib/decompress_unlzo.c index 0ae3d4d049..5c0587e57c 100644 --- a/lib/decompress_unlzo.c +++ b/lib/decompress_unlzo.c @@ -106,7 +106,7 @@ static inline int parse_header(u8 *input, int *skip, int in_len) return 1; } -static inline int __unlzo(u8 *input, int in_len, +int decompress_unlzo(u8 *input, int in_len, int (*fill) (void *, unsigned int), int (*flush) (void *, unsigned int), u8 *output, int *posp, @@ -307,5 +307,5 @@ int unlzo(int _in_fd, int _out_fd, int *dest_len) { in_fd = _in_fd; out_fd = _out_fd; - return __unlzo(NULL, 0, unlzo_fill, unlzo_flush, NULL, NULL, unlzo_error); + return decompress_unlzo(NULL, 0, unlzo_fill, unlzo_flush, NULL, NULL, unlzo_error); } -- cgit v1.2.3 From eb1c2e7de651b90f12864303ec965084d7206761 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 21:40:58 +0100 Subject: Add generic uncompress function uncompress() has the same prototype as the various kernel decompress functions. It automatically detects the compression type and selects the correct uncompress function. Signed-off-by: Sascha Hauer --- include/uncompress.h | 19 ++++++ lib/Makefile | 1 + lib/uncompress.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 include/uncompress.h create mode 100644 lib/uncompress.c diff --git a/include/uncompress.h b/include/uncompress.h new file mode 100644 index 0000000000..d146c90768 --- /dev/null +++ b/include/uncompress.h @@ -0,0 +1,19 @@ +#ifndef __UNCOMPRESS_H +#define __UNCOMPRESS_H + +int uncompress(unsigned char *inbuf, int len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *output, + int *pos, + void(*error_fn)(char *x)); + +int uncompress_fd_to_fd(int infd, int outfd, + void(*error_fn)(char *x)); + +int uncompress_fd_to_buf(int infd, void *output, + void(*error_fn)(char *x)); + +void uncompress_err_stdout(char *); + +#endif /* __UNCOMPRESS_H */ diff --git a/lib/Makefile b/lib/Makefile index f0abc21c22..e35d4b190b 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -33,3 +33,4 @@ obj-$(CONFIG_MD5) += md5.o obj-$(CONFIG_SHA1) += sha1.o obj-$(CONFIG_SHA256) += sha256.o obj-$(CONFIG_FDT) += fdt/ +obj-y += uncompress.o diff --git a/lib/uncompress.c b/lib/uncompress.c new file mode 100644 index 0000000000..80982f34d6 --- /dev/null +++ b/lib/uncompress.c @@ -0,0 +1,159 @@ +/* + * uncompress.c - uncompress files + * + * Copyright (c) 2011 Sascha Hauer , Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void *uncompress_buf; +static unsigned int uncompress_size; + +void uncompress_err_stdout(char *x) +{ + printf("%s\n", x); +} + +static int (*uncompress_fill_fn)(void*, unsigned int); + +static int uncompress_fill(void *buf, unsigned int len) +{ + int total = 0; + + if (uncompress_size) { + int now = min(len, uncompress_size); + + memcpy(buf, uncompress_buf, now); + uncompress_size -= now; + len -= now; + total = now; + buf += now; + } + + if (len) { + int ret = uncompress_fill_fn(buf, len); + if (ret < 0) + return ret; + total += ret; + } + + return total; +} + +int uncompress(unsigned char *inbuf, int len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *output, + int *pos, + void(*error_fn)(char *x)) +{ + enum filetype ft; + int (*compfn)(unsigned char *inbuf, int len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *output, + int *pos, + void(*error)(char *x)); + int ret; + char *err; + + BUG_ON(uncompress_size); + + if (inbuf) { + ft = file_detect_type(inbuf); + } else { + if (!fill) + return -EINVAL; + + uncompress_fill_fn = fill; + uncompress_buf = xzalloc(32); + uncompress_size = 32; + + ret = fill(uncompress_buf, 32); + if (ret < 0) + goto err; + + ft = file_detect_type(uncompress_buf); + } + + switch (ft) { +#ifdef CONFIG_BZLIB + case filetype_bzip2: + compfn = bunzip2; + break; +#endif +#ifdef CONFIG_ZLIB + case filetype_gzip: + compfn = gunzip; + break; +#endif +#ifdef CONFIG_LZO_DECOMPRESS + case filetype_lzo_compressed: + compfn = decompress_unlzo; + break; +#endif + default: + err = asprintf("cannot handle filetype %s", file_type_to_string(ft)); + error_fn(err); + free(err); + ret = -ENOSYS; + goto err; + } + + ret = compfn(inbuf, len, fill ? uncompress_fill : NULL, + flush, output, pos, error_fn); +err: + free(uncompress_buf); + uncompress_size = 0; + + return ret; +} + +static int uncompress_infd, uncompress_outfd; + +static int fill_fd(void *buf, unsigned int len) +{ + return read(uncompress_infd, buf, len); +} + +static int flush_fd(void *buf, unsigned int len) +{ + return write(uncompress_outfd, buf, len); +} + +int uncompress_fd_to_fd(int infd, int outfd, + void(*error_fn)(char *x)) +{ + uncompress_infd = infd; + uncompress_outfd = outfd; + + return uncompress(NULL, 0, + fill_fd, + flush_fd, + NULL, + NULL, + error_fn); +} -- cgit v1.2.3 From 1f56f817112df3e3644c4039c806e770620ca692 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 21:50:54 +0100 Subject: add generic uncompress command Using the new uncompress function we can now implement a command which can uncompress all known compression types. This supplements the unlzo command. Signed-off-by: Sascha Hauer --- commands/Kconfig | 10 ++++---- commands/Makefile | 2 +- commands/uncompress.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ commands/unlzo.c | 69 -------------------------------------------------- 4 files changed, 76 insertions(+), 75 deletions(-) create mode 100644 commands/uncompress.c delete mode 100644 commands/unlzo.c diff --git a/commands/Kconfig b/commands/Kconfig index 6b21a2ea7d..c2492fa6c9 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -422,13 +422,13 @@ config CMD_GPIO include gpio_set_value, gpio_get_value, gpio_direction_input and gpio_direction_output commands to control gpios. -config CMD_UNLZO +config CMD_UNCOMPRESS bool - select LZO_DECOMPRESS - prompt "unlzo" + prompt "uncompress" help - Say yes here to get the unlzo command. lzo is a fast compression - algorithm by Markus Franz Xaver Johannes Oberhumer. + Say yes here to get the uncompress command. uncompress handles + lzo, gzip and bzip2 compressed files depending on the compiled + in compression libraries config CMD_I2C bool diff --git a/commands/Makefile b/commands/Makefile index 45f9ccfd56..f82dcfa8dd 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -48,7 +48,7 @@ obj-$(CONFIG_CMD_INSMOD) += insmod.o obj-$(CONFIG_CMD_BMP) += bmp.o obj-$(CONFIG_USB_GADGET_DFU) += dfu.o obj-$(CONFIG_CMD_GPIO) += gpio.o -obj-$(CONFIG_CMD_UNLZO) += unlzo.o +obj-$(CONFIG_CMD_UNCOMPRESS) += uncompress.o obj-$(CONFIG_CMD_I2C) += i2c.o obj-$(CONFIG_CMD_UBI) += ubi.o obj-$(CONFIG_CMD_MENU) += menu.o diff --git a/commands/uncompress.c b/commands/uncompress.c new file mode 100644 index 0000000000..fff62275bb --- /dev/null +++ b/commands/uncompress.c @@ -0,0 +1,70 @@ +/* + * uncompress.c - uncompress a lzo compressed file + * + * Copyright (c) 2010 Sascha Hauer , Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +static int do_uncompress(struct command *cmdtp, int argc, char *argv[]) +{ + int from, to, ret; + + if (argc != 3) + return COMMAND_ERROR_USAGE; + + from = open(argv[1], O_RDONLY); + if (from < 0) { + perror("open"); + return 1; + } + + to = open(argv[2], O_WRONLY | O_CREAT); + if (to < 0) { + perror("open"); + ret = 1; + goto exit_close; + } + + ret = uncompress_fd_to_fd(from, to, uncompress_err_stdout); + + if (ret) + printf("failed to decompress\n"); + + close(to); +exit_close: + close(from); + return ret; +} + +static const __maybe_unused char cmd_uncompress_help[] = +"Usage: uncompress \n" +"Uncompress a compressed file\n"; + +BAREBOX_CMD_START(uncompress) + .cmd = do_uncompress, + .usage = "lzop ", + BAREBOX_CMD_HELP(cmd_uncompress_help) +BAREBOX_CMD_END + diff --git a/commands/unlzo.c b/commands/unlzo.c deleted file mode 100644 index 0b6dd4b961..0000000000 --- a/commands/unlzo.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * unlzo.c - uncompress a lzo compressed file - * - * Copyright (c) 2010 Sascha Hauer , Pengutronix - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include - -static int do_unlzo(struct command *cmdtp, int argc, char *argv[]) -{ - int from, to, ret, retlen; - - if (argc != 3) - return COMMAND_ERROR_USAGE; - - from = open(argv[1], O_RDONLY); - if (from < 0) { - perror("open"); - return 1; - } - - to = open(argv[2], O_WRONLY | O_CREAT); - if (to < 0) { - perror("open"); - ret = 1; - goto exit_close; - } - - ret = unlzo(from, to, &retlen); - if (ret) - printf("failed to decompress\n"); - - close(to); -exit_close: - close(from); - return ret; -} - -static const __maybe_unused char cmd_unlzo_help[] = -"Usage: unlzo \n" -"Uncompress a lzo compressed file\n"; - -BAREBOX_CMD_START(unlzo) - .cmd = do_unlzo, - .usage = "lzop ", - BAREBOX_CMD_HELP(cmd_unlzo_help) -BAREBOX_CMD_END - -- cgit v1.2.3 From 4de10d263ac2105624820c3e0c3aaa16bca3354c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 23:04:00 +0100 Subject: update configs and default envs for uncompress uncompress is the replacement for unlzo. Adjust environments and defconfigs accordingly. Signed-off-by: Sascha Hauer --- arch/arm/boards/eukrea_cpuimx25/env/bin/init_board | 2 +- arch/arm/boards/eukrea_cpuimx27/env/bin/init | 2 +- arch/arm/boards/eukrea_cpuimx35/env/bin/init_board | 2 +- arch/arm/boards/eukrea_cpuimx51/env/bin/init_board | 2 +- arch/arm/configs/at91rm9200ek_defconfig | 2 +- arch/arm/configs/at91sam9261ek_defconfig | 2 +- arch/arm/configs/at91sam9g10ek_defconfig | 2 +- arch/arm/configs/at91sam9m10g45ek_defconfig | 2 +- arch/arm/configs/cupid_defconfig | 2 +- arch/arm/configs/eukrea_cpuimx25_defconfig | 2 +- arch/arm/configs/eukrea_cpuimx27_defconfig | 2 +- arch/arm/configs/eukrea_cpuimx35_defconfig | 2 +- arch/arm/configs/eukrea_cpuimx51_defconfig | 2 +- arch/arm/configs/freescale_mx35_3stack_defconfig | 2 +- arch/arm/configs/freescale_mx53_loco_defconfig | 2 +- arch/arm/configs/neso_defconfig | 2 +- arch/arm/configs/nhk8815_defconfig | 2 +- arch/arm/configs/omap3530_beagle_defconfig | 2 +- arch/arm/configs/panda_defconfig | 2 +- arch/arm/configs/pca100_defconfig | 2 +- arch/arm/configs/pcm037_defconfig | 2 +- arch/arm/configs/pcm043_defconfig | 2 +- arch/arm/configs/pcm049_defconfig | 2 +- arch/arm/configs/pm9261_defconfig | 2 +- arch/arm/configs/pm9g45_defconfig | 2 +- arch/arm/configs/scb9328_defconfig | 2 +- arch/arm/configs/versatilepb_defconfig | 2 +- arch/mips/configs/dlink-dir-320_defconfig | 2 +- arch/mips/configs/qemu-malta_defconfig | 2 +- defaultenv/bin/boot | 2 +- 30 files changed, 30 insertions(+), 30 deletions(-) diff --git a/arch/arm/boards/eukrea_cpuimx25/env/bin/init_board b/arch/arm/boards/eukrea_cpuimx25/env/bin/init_board index 72b4ab32cd..2199b88904 100644 --- a/arch/arm/boards/eukrea_cpuimx25/env/bin/init_board +++ b/arch/arm/boards/eukrea_cpuimx25/env/bin/init_board @@ -4,7 +4,7 @@ if [ -f /env/logo.bmp ]; then bmp /env/logo.bmp fb0.enable=1 elif [ -f /env/logo.bmp.lzo ]; then - unlzo /env/logo.bmp.lzo /logo.bmp + uncompress /env/logo.bmp.lzo /logo.bmp bmp /logo.bmp fb0.enable=1 fi diff --git a/arch/arm/boards/eukrea_cpuimx27/env/bin/init b/arch/arm/boards/eukrea_cpuimx27/env/bin/init index aefd67cc34..f84ace9324 100644 --- a/arch/arm/boards/eukrea_cpuimx27/env/bin/init +++ b/arch/arm/boards/eukrea_cpuimx27/env/bin/init @@ -20,7 +20,7 @@ if [ -f /env/logo.bmp ]; then bmp /env/logo.bmp fb0.enable=1 elif [ -f /env/logo.bmp.lzo ]; then - unlzo /env/logo.bmp.lzo /logo.bmp + uncompress /env/logo.bmp.lzo /logo.bmp bmp /logo.bmp fb0.enable=1 fi diff --git a/arch/arm/boards/eukrea_cpuimx35/env/bin/init_board b/arch/arm/boards/eukrea_cpuimx35/env/bin/init_board index 173ecf9b57..cb624e57aa 100644 --- a/arch/arm/boards/eukrea_cpuimx35/env/bin/init_board +++ b/arch/arm/boards/eukrea_cpuimx35/env/bin/init_board @@ -5,7 +5,7 @@ if [ -f /env/logo.bmp ]; then fb0.enable=1 gpio_set_value 1 1 elif [ -f /env/logo.bmp.lzo ]; then - unlzo /env/logo.bmp.lzo /logo.bmp + uncompress /env/logo.bmp.lzo /logo.bmp bmp /logo.bmp fb0.enable=1 gpio_set_value 1 1 diff --git a/arch/arm/boards/eukrea_cpuimx51/env/bin/init_board b/arch/arm/boards/eukrea_cpuimx51/env/bin/init_board index 173ecf9b57..cb624e57aa 100644 --- a/arch/arm/boards/eukrea_cpuimx51/env/bin/init_board +++ b/arch/arm/boards/eukrea_cpuimx51/env/bin/init_board @@ -5,7 +5,7 @@ if [ -f /env/logo.bmp ]; then fb0.enable=1 gpio_set_value 1 1 elif [ -f /env/logo.bmp.lzo ]; then - unlzo /env/logo.bmp.lzo /logo.bmp + uncompress /env/logo.bmp.lzo /logo.bmp bmp /logo.bmp fb0.enable=1 gpio_set_value 1 1 diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig index 0c10f889fb..584bfdfd20 100644 --- a/arch/arm/configs/at91rm9200ek_defconfig +++ b/arch/arm/configs/at91rm9200ek_defconfig @@ -33,7 +33,7 @@ CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y # CONFIG_SPI is not set CONFIG_DRIVER_CFI=y # CONFIG_DRIVER_CFI_INTEL is not set diff --git a/arch/arm/configs/at91sam9261ek_defconfig b/arch/arm/configs/at91sam9261ek_defconfig index c753eb38f2..a4adee93fb 100644 --- a/arch/arm/configs/at91sam9261ek_defconfig +++ b/arch/arm/configs/at91sam9261ek_defconfig @@ -33,7 +33,7 @@ CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y diff --git a/arch/arm/configs/at91sam9g10ek_defconfig b/arch/arm/configs/at91sam9g10ek_defconfig index d39639ae58..9271b68286 100644 --- a/arch/arm/configs/at91sam9g10ek_defconfig +++ b/arch/arm/configs/at91sam9g10ek_defconfig @@ -27,7 +27,7 @@ CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y diff --git a/arch/arm/configs/at91sam9m10g45ek_defconfig b/arch/arm/configs/at91sam9m10g45ek_defconfig index 9699f5bcff..548fe6ccf2 100644 --- a/arch/arm/configs/at91sam9m10g45ek_defconfig +++ b/arch/arm/configs/at91sam9m10g45ek_defconfig @@ -37,7 +37,7 @@ CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y diff --git a/arch/arm/configs/cupid_defconfig b/arch/arm/configs/cupid_defconfig index b842469b72..3f5038f3e6 100644 --- a/arch/arm/configs/cupid_defconfig +++ b/arch/arm/configs/cupid_defconfig @@ -35,7 +35,7 @@ CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_BMP=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y diff --git a/arch/arm/configs/eukrea_cpuimx25_defconfig b/arch/arm/configs/eukrea_cpuimx25_defconfig index 7fa20422ef..2a697be705 100644 --- a/arch/arm/configs/eukrea_cpuimx25_defconfig +++ b/arch/arm/configs/eukrea_cpuimx25_defconfig @@ -35,7 +35,7 @@ CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_BMP=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_CMD_I2C=y CONFIG_CMD_LED=y CONFIG_CMD_LED_TRIGGER=y diff --git a/arch/arm/configs/eukrea_cpuimx27_defconfig b/arch/arm/configs/eukrea_cpuimx27_defconfig index 75b849badf..93de428e15 100644 --- a/arch/arm/configs/eukrea_cpuimx27_defconfig +++ b/arch/arm/configs/eukrea_cpuimx27_defconfig @@ -33,7 +33,7 @@ CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_BMP=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_CMD_I2C=y CONFIG_NET=y CONFIG_NET_DHCP=y diff --git a/arch/arm/configs/eukrea_cpuimx35_defconfig b/arch/arm/configs/eukrea_cpuimx35_defconfig index 6964332f33..7bbe0d5437 100644 --- a/arch/arm/configs/eukrea_cpuimx35_defconfig +++ b/arch/arm/configs/eukrea_cpuimx35_defconfig @@ -34,7 +34,7 @@ CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_BMP=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_CMD_I2C=y CONFIG_NET=y CONFIG_NET_DHCP=y diff --git a/arch/arm/configs/eukrea_cpuimx51_defconfig b/arch/arm/configs/eukrea_cpuimx51_defconfig index a9fca84460..39fe962ce2 100644 --- a/arch/arm/configs/eukrea_cpuimx51_defconfig +++ b/arch/arm/configs/eukrea_cpuimx51_defconfig @@ -32,7 +32,7 @@ CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_PING=y diff --git a/arch/arm/configs/freescale_mx35_3stack_defconfig b/arch/arm/configs/freescale_mx35_3stack_defconfig index 2c0e5137e8..c8d159f442 100644 --- a/arch/arm/configs/freescale_mx35_3stack_defconfig +++ b/arch/arm/configs/freescale_mx35_3stack_defconfig @@ -29,7 +29,7 @@ CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_BMP=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_CMD_I2C=y CONFIG_NET=y CONFIG_NET_DHCP=y diff --git a/arch/arm/configs/freescale_mx53_loco_defconfig b/arch/arm/configs/freescale_mx53_loco_defconfig index 8e4a7ce328..cb07f85a47 100644 --- a/arch/arm/configs/freescale_mx53_loco_defconfig +++ b/arch/arm/configs/freescale_mx53_loco_defconfig @@ -33,7 +33,7 @@ CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y diff --git a/arch/arm/configs/neso_defconfig b/arch/arm/configs/neso_defconfig index 1b533df1fa..dcc2f70bf4 100644 --- a/arch/arm/configs/neso_defconfig +++ b/arch/arm/configs/neso_defconfig @@ -34,7 +34,7 @@ CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_BMP=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y diff --git a/arch/arm/configs/nhk8815_defconfig b/arch/arm/configs/nhk8815_defconfig index b81afe2a71..597e9dd442 100644 --- a/arch/arm/configs/nhk8815_defconfig +++ b/arch/arm/configs/nhk8815_defconfig @@ -34,7 +34,7 @@ CONFIG_CMD_RESET=y CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y diff --git a/arch/arm/configs/omap3530_beagle_defconfig b/arch/arm/configs/omap3530_beagle_defconfig index 8a12154cac..e0688ae40a 100644 --- a/arch/arm/configs/omap3530_beagle_defconfig +++ b/arch/arm/configs/omap3530_beagle_defconfig @@ -31,7 +31,7 @@ CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_CMD_I2C=y CONFIG_NET=y CONFIG_NET_DHCP=y diff --git a/arch/arm/configs/panda_defconfig b/arch/arm/configs/panda_defconfig index 3ea24664d6..27592e5fc2 100644 --- a/arch/arm/configs/panda_defconfig +++ b/arch/arm/configs/panda_defconfig @@ -34,7 +34,7 @@ CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y diff --git a/arch/arm/configs/pca100_defconfig b/arch/arm/configs/pca100_defconfig index 88e7b9f5e8..29e02c5327 100644 --- a/arch/arm/configs/pca100_defconfig +++ b/arch/arm/configs/pca100_defconfig @@ -33,7 +33,7 @@ CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_PING=y diff --git a/arch/arm/configs/pcm037_defconfig b/arch/arm/configs/pcm037_defconfig index d9525a215c..ec43317abd 100644 --- a/arch/arm/configs/pcm037_defconfig +++ b/arch/arm/configs/pcm037_defconfig @@ -31,7 +31,7 @@ CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y diff --git a/arch/arm/configs/pcm043_defconfig b/arch/arm/configs/pcm043_defconfig index 3c728ed3fc..e47bb35aa7 100644 --- a/arch/arm/configs/pcm043_defconfig +++ b/arch/arm/configs/pcm043_defconfig @@ -36,7 +36,7 @@ CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y diff --git a/arch/arm/configs/pcm049_defconfig b/arch/arm/configs/pcm049_defconfig index ed20f1bb06..9b4c341f53 100644 --- a/arch/arm/configs/pcm049_defconfig +++ b/arch/arm/configs/pcm049_defconfig @@ -35,7 +35,7 @@ CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y diff --git a/arch/arm/configs/pm9261_defconfig b/arch/arm/configs/pm9261_defconfig index 0bd9483e75..89aa0335e6 100644 --- a/arch/arm/configs/pm9261_defconfig +++ b/arch/arm/configs/pm9261_defconfig @@ -34,7 +34,7 @@ CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y diff --git a/arch/arm/configs/pm9g45_defconfig b/arch/arm/configs/pm9g45_defconfig index 20bfd718fe..bf9af22cfa 100644 --- a/arch/arm/configs/pm9g45_defconfig +++ b/arch/arm/configs/pm9g45_defconfig @@ -37,7 +37,7 @@ CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y diff --git a/arch/arm/configs/scb9328_defconfig b/arch/arm/configs/scb9328_defconfig index 73ef2382eb..49556467c5 100644 --- a/arch/arm/configs/scb9328_defconfig +++ b/arch/arm/configs/scb9328_defconfig @@ -28,7 +28,7 @@ CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_CMD_LED=y CONFIG_CMD_LED_TRIGGER=y CONFIG_NET=y diff --git a/arch/arm/configs/versatilepb_defconfig b/arch/arm/configs/versatilepb_defconfig index 6ffdf2897d..1b51d91b21 100644 --- a/arch/arm/configs/versatilepb_defconfig +++ b/arch/arm/configs/versatilepb_defconfig @@ -32,7 +32,7 @@ CONFIG_CMD_RESET=y CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y diff --git a/arch/mips/configs/dlink-dir-320_defconfig b/arch/mips/configs/dlink-dir-320_defconfig index dbce0b938b..88c0e836bc 100644 --- a/arch/mips/configs/dlink-dir-320_defconfig +++ b/arch/mips/configs/dlink-dir-320_defconfig @@ -41,7 +41,7 @@ CONFIG_CMD_RESET=y CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y diff --git a/arch/mips/configs/qemu-malta_defconfig b/arch/mips/configs/qemu-malta_defconfig index b6f53cab0f..eac21e7082 100644 --- a/arch/mips/configs/qemu-malta_defconfig +++ b/arch/mips/configs/qemu-malta_defconfig @@ -40,7 +40,7 @@ CONFIG_CMD_RESET=y CONFIG_CMD_GO=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y -CONFIG_CMD_UNLZO=y +CONFIG_CMD_UNCOMPRESS=y CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y diff --git a/defaultenv/bin/boot b/defaultenv/bin/boot index 6761d84514..90ebf9a3da 100644 --- a/defaultenv/bin/boot +++ b/defaultenv/bin/boot @@ -124,6 +124,6 @@ elif [ x$kernelimage_type = xraw ]; then fi bootu /dev/ram0.kernelraw elif [ x$kernelimage_type = xraw_lzo ]; then - unlzo $kdev /dev/ram0.kernelraw + uncompress $kdev /dev/ram0.kernelraw bootu /dev/ram0.kernelraw fi -- cgit v1.2.3 From 62493a5fe14d80807452c5728303157a0194e888 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 21:52:25 +0100 Subject: remove now unused unlzo function Signed-off-by: Sascha Hauer --- include/lzo.h | 2 -- lib/decompress_unlzo.c | 25 ------------------------- 2 files changed, 27 deletions(-) diff --git a/include/lzo.h b/include/lzo.h index b4a514f1f3..0530a6806d 100644 --- a/include/lzo.h +++ b/include/lzo.h @@ -41,8 +41,6 @@ int lzo1x_decompress_safe(const unsigned char *src, size_t src_len, #define LZO_E_INPUT_NOT_CONSUMED (-8) #define LZO_E_NOT_YET_IMPLEMENTED (-9) -int unlzo(int in_fd, int out_fd, int *dest_len); - int decompress_unlzo(u8 *input, int in_len, int (*fill) (void *, unsigned int), int (*flush) (void *, unsigned int), diff --git a/lib/decompress_unlzo.c b/lib/decompress_unlzo.c index 5c0587e57c..000bd704c3 100644 --- a/lib/decompress_unlzo.c +++ b/lib/decompress_unlzo.c @@ -284,28 +284,3 @@ exit_1: exit: return ret; } - -static int in_fd; -static int out_fd; - -static int unlzo_fill(void *buf, unsigned int len) -{ - return read(in_fd, buf, len); -} - -static int unlzo_flush(void *buf, unsigned int len) -{ - return write(out_fd, buf, len); -} - -static void unlzo_error(char *s) -{ - printf("%s\n", s); -} - -int unlzo(int _in_fd, int _out_fd, int *dest_len) -{ - in_fd = _in_fd; - out_fd = _out_fd; - return decompress_unlzo(NULL, 0, unlzo_fill, unlzo_flush, NULL, NULL, unlzo_error); -} -- cgit v1.2.3 From ad4537ba92ef49c4ed0590a52e5f0033efb7e225 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 28 Nov 2011 22:07:15 +0100 Subject: bootm: use generic uncompress function This simplifies the code somewhat. The user visible change here is that we now ignore the compression specified in the uImage. Instead we detect the compression type from the data which also means that we now support lzo compressed uImages. Signed-off-by: Sascha Hauer --- commands/bootm.c | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/commands/bootm.c b/commands/bootm.c index 01ad4c7da6..3bef6e78a3 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -42,7 +41,7 @@ #include #include #include -#include +#include #include #ifndef CFG_BOOTM_LEN @@ -57,11 +56,6 @@ struct image_handle_data* image_handle_data_get_by_num(struct image_handle* hand return &handle->data_entries[num]; } -static void unzip_error(char *x) -{ - puts(x); -} - int relocate_image(struct image_handle *handle, void *load_address) { image_header_t *hdr = &handle->header; @@ -85,30 +79,13 @@ int relocate_image(struct image_handle *handle, void *load_address) memmove(load_address, data, len); } break; -#ifdef CONFIG_ZLIB - case IH_COMP_GZIP: - printf (" Uncompressing ... "); - - ret = gunzip(data, len, NULL, NULL, load_address, NULL, - unzip_error); - if (ret) - return ret; - break; -#endif -#ifdef CONFIG_BZLIB - case IH_COMP_BZIP2: + default: printf (" Uncompressing ... "); - - ret = bunzip2(data, len, NULL, NULL, load_address, NULL, - unzip_error); + ret = uncompress(data, len, NULL, NULL, load_address, NULL, + uncompress_err_stdout); if (ret) return ret; break; -#endif - default: - printf("Unimplemented compression type %d\n", - image_get_comp(hdr)); - return -1; } return 0; -- cgit v1.2.3 From 27169b62f66d9dff1ce4c83ac124c2ff39f20b23 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 29 Nov 2011 21:13:55 +0100 Subject: bootm: remove dead code Signed-off-by: Sascha Hauer --- commands/bootm.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/commands/bootm.c b/commands/bootm.c index 3bef6e78a3..859ec28a26 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -44,10 +44,6 @@ #include #include -#ifndef CFG_BOOTM_LEN -#define CFG_BOOTM_LEN 0x800000 /* use 8MByte as default max gunzip size */ -#endif - struct image_handle_data* image_handle_data_get_by_num(struct image_handle* handle, int num) { if (!handle || num < 0 || num >= handle->nb_data_entries) @@ -64,10 +60,6 @@ int relocate_image(struct image_handle *handle, void *load_address) void *data; int ret; -#if defined CONFIG_CMD_BOOTM_ZLIB || defined CONFIG_CMD_BOOTM_BZLIB - uint unc_len = BOOTM_LEN; -#endif - iha = image_handle_data_get_by_num(handle, 0); data = iha->data; -- cgit v1.2.3 From e88417b5ef9de74944bf3d8fa86f184abbac68ea Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 28 Nov 2011 12:46:56 +0100 Subject: nand: base: Improve error reporting if reading NAND-ID fails - use KERN_ERR for messages when NAND-ID detection fails - report the IDs also if not found - print the errno if nand_scan failed Signed-off-by: Wolfram Sang Signed-off-by: Sascha Hauer --- drivers/mtd/nand/nand_base.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 2710f6a309..ec0f4a3e11 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1067,7 +1067,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, tmp_id = chip->read_byte(mtd); if (tmp_manf != *maf_id || tmp_id != dev_id) { - printk(KERN_INFO "%s: second ID read did not match " + printk(KERN_ERR "%s: second ID read did not match " "%02x,%02x against %02x,%02x\n", __func__, *maf_id, dev_id, tmp_manf, tmp_id); return ERR_PTR(-ENODEV); @@ -1081,8 +1081,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, } } - if (!type) + if (!type) { + printk(KERN_ERR "NAND type unknown: %02x,%02x\n", *maf_id, dev_id); return ERR_PTR(-ENODEV); + } if (!mtd->name) mtd->name = type->name; @@ -1209,7 +1211,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips) type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id); if (IS_ERR(type)) { - printk(KERN_WARNING "No NAND device found!!!\n"); + printk(KERN_WARNING "No NAND device found (%ld)!\n", PTR_ERR(type)); chip->select_chip(mtd, -1); return PTR_ERR(type); } -- cgit v1.2.3 From 70f7691d4110c4384e058ae3e64003ca9ad963a6 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 1 Dec 2011 22:24:04 +0100 Subject: fix malloc space sizes end is start + size - 1, not start + size. Signed-off-by: Sascha Hauer --- arch/arm/lib/arm.c | 2 +- arch/blackfin/lib/board.c | 2 +- arch/mips/lib/memory.c | 2 +- arch/nios2/lib/board.c | 2 +- arch/ppc/lib/board.c | 2 +- arch/sandbox/os/common.c | 2 +- arch/x86/lib/memory.c | 4 ++-- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/lib/arm.c b/arch/arm/lib/arm.c index c85aae14a0..80b62e988d 100644 --- a/arch/arm/lib/arm.c +++ b/arch/arm/lib/arm.c @@ -7,7 +7,7 @@ static int arm_mem_malloc_init(void) { mem_malloc_init((void *)MALLOC_BASE, - (void *)(MALLOC_BASE + MALLOC_SIZE)); + (void *)(MALLOC_BASE + MALLOC_SIZE - 1)); return 0; } diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c index d1b39fa347..bf5c1b64a5 100644 --- a/arch/blackfin/lib/board.c +++ b/arch/blackfin/lib/board.c @@ -38,7 +38,7 @@ int blackfin_mem_malloc_init(void) { mem_malloc_init((void *)(MALLOC_BASE), - (void *)(MALLOC_BASE + MALLOC_SIZE)); + (void *)(MALLOC_BASE + MALLOC_SIZE - 1)); return 0; } diff --git a/arch/mips/lib/memory.c b/arch/mips/lib/memory.c index ad9f6a6a40..8d2d51b72b 100644 --- a/arch/mips/lib/memory.c +++ b/arch/mips/lib/memory.c @@ -26,7 +26,7 @@ static int mips_mem_malloc_init(void) { mem_malloc_init((void *)MALLOC_BASE, - (void *)(MALLOC_BASE + MALLOC_SIZE)); + (void *)(MALLOC_BASE + MALLOC_SIZE - 1)); return 0; } core_initcall(mips_mem_malloc_init); diff --git a/arch/nios2/lib/board.c b/arch/nios2/lib/board.c index d50f05adee..ed3af49a86 100644 --- a/arch/nios2/lib/board.c +++ b/arch/nios2/lib/board.c @@ -31,7 +31,7 @@ int altera_mem_malloc_init(void) { mem_malloc_init((void *)(NIOS_SOPC_TEXT_BASE - MALLOC_SIZE), - (void *)(NIOS_SOPC_TEXT_BASE)); + (void *)(NIOS_SOPC_TEXT_BASE - 1)); return 0; } diff --git a/arch/ppc/lib/board.c b/arch/ppc/lib/board.c index 0b610a5c95..0e839eb053 100644 --- a/arch/ppc/lib/board.c +++ b/arch/ppc/lib/board.c @@ -56,7 +56,7 @@ void board_init_r (ulong end_of_ram) debug("malloc_end: 0x%08x\n", malloc_end); debug("TEXT_BASE after relocation: 0x%08x\n", _text_base); - mem_malloc_init((void *)(malloc_end - MALLOC_SIZE), (void *)malloc_end); + mem_malloc_init((void *)(malloc_end - MALLOC_SIZE), (void *)(malloc_end - 1)); /* * Setup trap handlers diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c index 1c5ae5d34b..9258c66156 100644 --- a/arch/sandbox/os/common.c +++ b/arch/sandbox/os/common.c @@ -262,7 +262,7 @@ int main(int argc, char *argv[]) printf("unable to get malloc space\n"); exit(1); } - mem_malloc_init(ram, ram + malloc_size); + mem_malloc_init(ram, ram + malloc_size - 1); while (1) { int option_index = 0; diff --git a/arch/x86/lib/memory.c b/arch/x86/lib/memory.c index fa7bc03962..1774ef34fd 100644 --- a/arch/x86/lib/memory.c +++ b/arch/x86/lib/memory.c @@ -54,12 +54,12 @@ static int x86_mem_malloc_init(void) */ if (memory_size >= (15 * 1024 * 1024 + MALLOC_SIZE)) mem_malloc_init((void*)(16 * 1024 * 1024), - (void*)(16 * 1024 * 1024) + MALLOC_SIZE); + (void*)(16 * 1024 * 1024 + MALLOC_SIZE - 1)); else return -1; #else mem_malloc_init((void *)MALLOC_BASE, - (void *)(MALLOC_BASE + MALLOC_SIZE)); + (void *)(MALLOC_BASE + MALLOC_SIZE - 1)); #endif return 0; } -- cgit v1.2.3 From 200ae6b4eef9f6041016887f71fc01c5daee6f69 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 1 Dec 2011 21:44:02 +0100 Subject: add resource management functions It is time to track our memory usage. Add a simple resource management. Signed-off-by: Sascha Hauer --- common/Makefile | 1 + common/resource.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/ioport.h | 14 ++++++ 3 files changed, 136 insertions(+) create mode 100644 common/resource.c diff --git a/common/Makefile b/common/Makefile index 55d9dbcb43..9bce47943c 100644 --- a/common/Makefile +++ b/common/Makefile @@ -27,6 +27,7 @@ obj-y += startup.o obj-y += misc.o obj-y += memsize.o obj-y += filetype.o +obj-y += resource.o obj-$(CONFIG_MENU) += menu.o obj-$(CONFIG_PASSWORD) += password.o obj-$(CONFIG_MODULES) += module.o diff --git a/common/resource.c b/common/resource.c new file mode 100644 index 0000000000..63e9c49ca1 --- /dev/null +++ b/common/resource.c @@ -0,0 +1,121 @@ +/* + * resource.c - barebox resource management + * + * Copyright (c) 2011 Sascha Hauer , Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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. + */ +#include +#include +#include +#include +#include + +static int init_resource(struct resource *res, const char *name) +{ + INIT_LIST_HEAD(&res->children); + res->parent = NULL; + res->name = xstrdup(name); + + return 0; +} + +/* + * request a region. + * This will succedd when the requested region is completely inside + * the parent resource and does not conflict with any of the child + * resources. + */ +struct resource *request_region(struct resource *parent, + const char *name, resource_size_t start, + resource_size_t size) +{ + struct resource *r, *new; + + /* outside parent resource? */ + if (start < parent->start || + start + size > parent->start + parent->size) { + debug("%s: 0x%08x:0x%08x outside parent resource 0x%08x:0x%08x\n", + __func__, start, size, parent->start, + parent->size); + return NULL; + } + + /* + * We keep the list of child resources ordered which helps + * us searching for conflicts here. + */ + list_for_each_entry(r, &parent->children, sibling) { + if (start + size <= r->start) + goto ok; + if (start >= r->start + r->size) + continue; + debug("%s: 0x%08x:0x%08x conflicts with 0x%08x:0x%08x\n", + __func__, start, size, r->start, r->size); + return NULL; + } + +ok: + debug("%s ok: 0x%08x 0x%08x\n", __func__, start, size); + + new = xzalloc(sizeof(*new)); + init_resource(new, name); + new->start = start; + new->size = size; + new->parent = parent; + list_add_tail(&new->sibling, &r->sibling); + + return new; +} + +/* + * release a region previously requested with request_region + */ +int release_region(struct resource *res) +{ + if (!list_empty(&res->children)) + return -EBUSY; + + list_del(&res->sibling); + free((char *)res->name); + free(res); + + return 0; +} + +/* The root resource for the whole io space */ +struct resource iomem_resource = { + .start = 0, + .size = ~0, +}; + +/* + * request a region inside the io space + */ +struct resource *request_iomem_region(const char *name, + resource_size_t start, resource_size_t size) +{ + return request_region(&iomem_resource, name, start, size); +} + +static int iomem_init(void) +{ + init_resource(&iomem_resource, "iomem"); + + return 0; +} +postcore_initcall(iomem_init); diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 51431158d3..c837b53491 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -20,6 +20,9 @@ struct resource { resource_size_t size; const char *name; unsigned long flags; + struct resource *parent; + struct list_head children; + struct list_head sibling; }; /* @@ -111,5 +114,16 @@ static inline unsigned long resource_type(const struct resource *res) return res->flags & IORESOURCE_TYPE_BITS; } +struct resource *request_iomem_region(const char *name, + resource_size_t start, resource_size_t size); + +struct resource *request_region(struct resource *parent, + const char *name, resource_size_t start, + resource_size_t size); + +int release_region(struct resource *res); + +extern struct resource iomem_resource; + #endif /* __ASSEMBLY__ */ #endif /* _LINUX_IOPORT_H */ -- cgit v1.2.3 From 32f163f67c10ff7415baee2d022459cc859d84b1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 1 Dec 2011 21:47:23 +0100 Subject: add iomem command to show iomem usage Signed-off-by: Sascha Hauer --- commands/Kconfig | 7 +++++++ commands/Makefile | 1 + commands/iomem.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 commands/iomem.c diff --git a/commands/Kconfig b/commands/Kconfig index c2492fa6c9..2badea3b7b 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -215,6 +215,13 @@ config CMD_MEMINFO tristate prompt "meminfo" +config CMD_IOMEM + tristate + prompt "iomem" + help + Show information about iomem usage. Pendant to 'cat /proc/iomem' + under Linux. + config CMD_MEMORY bool default y diff --git a/commands/Makefile b/commands/Makefile index f82dcfa8dd..e95fdc375d 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -60,3 +60,4 @@ obj-$(CONFIG_CMD_USB) += usb.o obj-$(CONFIG_CMD_TIME) += time.o obj-$(CONFIG_CMD_OFTREE) += oftree.o obj-$(CONFIG_CMD_MAGICVAR) += magicvar.o +obj-$(CONFIG_CMD_IOMEM) += iomem.o diff --git a/commands/iomem.c b/commands/iomem.c new file mode 100644 index 0000000000..78566c1f5b --- /dev/null +++ b/commands/iomem.c @@ -0,0 +1,56 @@ +/* + * iomem.c - barebox iomem command + * + * Copyright (c) 2011 Sascha Hauer , Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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. + */ +#include +#include + +static void __print_resources(struct resource *res, int indent) +{ + struct resource *r; + int i; + + for (i = 0; i < indent; i++) + printf(" "); + + printf("0x%08x - 0x%08x (size 0x%08x) %s\n", res->start, + res->start + res->size - 1, + res->size, res->name); + + list_for_each_entry(r, &res->children, sibling) + __print_resources(r, indent + 1); +} + +static void print_resources(struct resource *res) +{ + __print_resources(res, 0); +} + +static int do_iomem(struct command *cmdtp, int argc, char *argv[]) +{ + print_resources(&iomem_resource); + + return 0; +} + +BAREBOX_CMD_START(iomem) + .cmd = do_iomem, + .usage = "show iomem usage", +BAREBOX_CMD_END -- cgit v1.2.3 From ec8dd2542847c4e161d8fc521dfc6af0ed25c896 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 1 Dec 2011 22:09:49 +0100 Subject: register sdram as resources Also, request the sdram regions used by the barebox binary, bss, malloc space and stack. Signed-off-by: Sascha Hauer --- common/memory.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/memory.h | 5 +++++ 2 files changed, 63 insertions(+) diff --git a/common/memory.c b/common/memory.c index 0ba9a18e88..7d0f4cab2a 100644 --- a/common/memory.c +++ b/common/memory.c @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include /* * Begin and End of memory area for malloc(), and current "brk" @@ -50,6 +53,33 @@ void mem_malloc_init(void *start, void *end) malloc_brk = malloc_start; } +static int mem_malloc_resource(void) +{ + /* + * Normally it's a bug when one of these fails, + * but we have some setups where some of these + * regions are outside of sdram in which case + * the following fails. + */ + request_sdram_region("malloc space", + malloc_start, + malloc_end - malloc_start + 1); + request_sdram_region("barebox", + (unsigned long)&_stext, + (unsigned long)&_etext - + (unsigned long)&_stext + 1); + request_sdram_region("bss", + (unsigned long)&__bss_start, + (unsigned long)&__bss_stop - + (unsigned long)&__bss_start + 1); +#ifdef STACK_BASE + request_sdram_region("stack", STACK_BASE, STACK_SIZE); +#endif + + return 0; +} +coredevice_initcall(mem_malloc_resource); + static void *sbrk_no_zero(ptrdiff_t increment) { unsigned long old = malloc_brk; @@ -82,6 +112,10 @@ void barebox_add_memory_bank(const char *name, resource_size_t start, struct memory_bank *bank = xzalloc(sizeof(*bank)); struct device_d *dev; + bank->res = request_iomem_region(name, start, size); + + BUG_ON(!bank->res); + dev = add_mem_device(name, start, size, IORESOURCE_MEM_WRITEABLE); bank->dev = dev; @@ -91,6 +125,30 @@ void barebox_add_memory_bank(const char *name, resource_size_t start, list_add_tail(&bank->list, &memory_banks); } +/* + * Request a region from the registered sdram + */ +struct resource *request_sdram_region(const char *name, resource_size_t start, + resource_size_t size) +{ + struct memory_bank *bank; + + for_each_memory_bank(bank) { + struct resource *res; + + res = request_region(bank->res, name, start, size); + if (res) + return res; + } + + return NULL; +} + +int release_sdram_region(struct resource *res) +{ + return release_region(res); +} + #ifdef CONFIG_OFTREE /* diff --git a/include/memory.h b/include/memory.h index cb185afa65..4be4340b14 100644 --- a/include/memory.h +++ b/include/memory.h @@ -13,6 +13,7 @@ struct memory_bank { struct device_d *dev; unsigned long start; unsigned long size; + struct resource *res; }; extern struct list_head memory_banks; @@ -22,4 +23,8 @@ void barebox_add_memory_bank(const char *name, resource_size_t start, #define for_each_memory_bank(mem) list_for_each_entry(mem, &memory_banks, list) +struct resource *request_sdram_region(const char *name, resource_size_t start, + resource_size_t size); +int release_sdram_region(struct resource *res); + #endif -- cgit v1.2.3 From 18e845efd935c2a4bf79c2ed2fbd9766c18af3f9 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 1 Dec 2011 22:15:00 +0100 Subject: implement resource management for platform devices Signed-off-by: Sascha Hauer --- drivers/base/driver.c | 29 +++++++++++++++++++++++++++-- include/driver.h | 6 +----- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 0b80103144..0132e7dcf8 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -214,7 +214,7 @@ int register_driver(struct driver_d *drv) } EXPORT_SYMBOL(register_driver); -void __iomem *dev_get_mem_region(struct device_d *dev, int num) +static struct resource *dev_get_resource(struct device_d *dev, int num) { int i, n = 0; @@ -222,15 +222,40 @@ void __iomem *dev_get_mem_region(struct device_d *dev, int num) struct resource *res = &dev->resource[i]; if (resource_type(res) == IORESOURCE_MEM) { if (n == num) - return (void __force __iomem *)res->start; + return res; n++; } } return NULL; } + +void __iomem *dev_get_mem_region(struct device_d *dev, int num) +{ + struct resource *res; + + res = dev_get_resource(dev, num); + if (!res) + return res; + + return (void __force __iomem *)res->start; +} EXPORT_SYMBOL(dev_get_mem_region); +void __iomem *dev_request_mem_region(struct device_d *dev, int num) +{ + struct resource *res; + + res = dev_get_resource(dev, num); + if (!res) + return NULL; + + res = request_iomem_region(dev_name(dev), res->start, res->size); + + return (void __force __iomem *)res->start; +} +EXPORT_SYMBOL(dev_request_mem_region); + int dev_protect(struct device_d *dev, size_t count, unsigned long offset, int prot) { printf("%s: currently broken\n", __func__); diff --git a/include/driver.h b/include/driver.h index fe9d37ae3d..bbe724833f 100644 --- a/include/driver.h +++ b/include/driver.h @@ -190,11 +190,7 @@ void __iomem *dev_get_mem_region(struct device_d *dev, int num); /* * exlusively request register base 'num' for a device */ -static inline void __iomem *dev_request_mem_region(struct device_d *dev, int num) -{ - /* no resource tracking yet */ - return dev_get_mem_region(dev, num); -} +void __iomem *dev_request_mem_region(struct device_d *dev, int num); /* * register a generic device -- cgit v1.2.3 From 36c47ce426cbe7aea59fab4c0218fe07cd80bdc0 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 3 Dec 2011 18:02:00 +0100 Subject: arm/mach-pxa: Initial Intel/Marvell PXA support The core support was brought by Marc and Sascha. The cache choice was fixed by Luotao Fu. Some gpio and devices addons were provided by Robert. Signed-off-by: Luotao Fu Signed-off-by: Sascha Hauer Signed-off-by: Marc Kleine-Budde Signed-off-by: Robert Jarzmik Signed-off-by: Sascha Hauer --- arch/arm/Kconfig | 5 + arch/arm/Makefile | 2 + arch/arm/cpu/Kconfig | 5 + arch/arm/mach-pxa/Kconfig | 37 +++ arch/arm/mach-pxa/Makefile | 6 + arch/arm/mach-pxa/clocksource.c | 45 +++ arch/arm/mach-pxa/common.c | 37 +++ arch/arm/mach-pxa/devices.c | 49 +++ arch/arm/mach-pxa/gpio.c | 68 ++++ arch/arm/mach-pxa/include/mach/clock.h | 16 + arch/arm/mach-pxa/include/mach/devices.h | 26 ++ arch/arm/mach-pxa/include/mach/gpio.h | 132 ++++++++ arch/arm/mach-pxa/include/mach/hardware.h | 31 ++ arch/arm/mach-pxa/include/mach/mfp-pxa27x.h | 438 +++++++++++++++++++++++++ arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h | 133 ++++++++ arch/arm/mach-pxa/include/mach/mfp.h | 21 ++ arch/arm/mach-pxa/include/mach/pxa-regs.h | 33 ++ arch/arm/mach-pxa/include/mach/pxa27x-regs.h | 6 + arch/arm/mach-pxa/include/mach/pxa2xx-regs.h | 267 +++++++++++++++ arch/arm/mach-pxa/include/mach/regs-intc.h | 34 ++ arch/arm/mach-pxa/include/mach/regs-ost.h | 34 ++ arch/arm/mach-pxa/include/plat/gpio.h | 74 +++++ arch/arm/mach-pxa/include/plat/mfp.h | 468 +++++++++++++++++++++++++++ arch/arm/mach-pxa/mfp-pxa2xx.c | 189 +++++++++++ arch/arm/mach-pxa/speed-pxa27x.c | 20 ++ drivers/serial/Kconfig | 4 + drivers/serial/Makefile | 1 + drivers/serial/serial_pxa.c | 201 ++++++++++++ 28 files changed, 2382 insertions(+) create mode 100644 arch/arm/mach-pxa/Kconfig create mode 100644 arch/arm/mach-pxa/Makefile create mode 100644 arch/arm/mach-pxa/clocksource.c create mode 100644 arch/arm/mach-pxa/common.c create mode 100644 arch/arm/mach-pxa/devices.c create mode 100644 arch/arm/mach-pxa/gpio.c create mode 100644 arch/arm/mach-pxa/include/mach/clock.h create mode 100644 arch/arm/mach-pxa/include/mach/devices.h create mode 100644 arch/arm/mach-pxa/include/mach/gpio.h create mode 100644 arch/arm/mach-pxa/include/mach/hardware.h create mode 100644 arch/arm/mach-pxa/include/mach/mfp-pxa27x.h create mode 100644 arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h create mode 100644 arch/arm/mach-pxa/include/mach/mfp.h create mode 100644 arch/arm/mach-pxa/include/mach/pxa-regs.h create mode 100644 arch/arm/mach-pxa/include/mach/pxa27x-regs.h create mode 100644 arch/arm/mach-pxa/include/mach/pxa2xx-regs.h create mode 100644 arch/arm/mach-pxa/include/mach/regs-intc.h create mode 100644 arch/arm/mach-pxa/include/mach/regs-ost.h create mode 100644 arch/arm/mach-pxa/include/plat/gpio.h create mode 100644 arch/arm/mach-pxa/include/plat/mfp.h create mode 100644 arch/arm/mach-pxa/mfp-pxa2xx.c create mode 100644 arch/arm/mach-pxa/speed-pxa27x.c create mode 100644 drivers/serial/serial_pxa.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index b15728e38d..40677a35ae 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -62,6 +62,10 @@ config ARCH_NOMADIK config ARCH_OMAP bool "TI OMAP" +config ARCH_PXA + bool "Intel/Marvell PXA based" + select GENERIC_GPIO + config ARCH_S3C24xx bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443" select CPU_ARM920T @@ -81,6 +85,7 @@ source arch/arm/mach-mxs/Kconfig source arch/arm/mach-netx/Kconfig source arch/arm/mach-nomadik/Kconfig source arch/arm/mach-omap/Kconfig +source arch/arm/mach-pxa/Kconfig source arch/arm/mach-s3c24xx/Kconfig source arch/arm/mach-versatile/Kconfig diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 0c42f3d1ea..913a90ed71 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -27,6 +27,7 @@ arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t # This selects how we optimise for the processor. tune-$(CONFIG_CPU_ARM920T) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi +tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale ifeq ($(CONFIG_AEABI),y) CFLAGS_ABI :=-mabi=aapcs-linux -mno-thumb-interwork @@ -50,6 +51,7 @@ machine-$(CONFIG_ARCH_MXS) := mxs machine-$(CONFIG_ARCH_NOMADIK) := nomadik machine-$(CONFIG_ARCH_NETX) := netx machine-$(CONFIG_ARCH_OMAP) := omap +machine-$(CONFIG_ARCH_PXA) := pxa machine-$(CONFIG_ARCH_S3C24xx) := s3c24xx machine-$(CONFIG_ARCH_VERSATILE) := versatile diff --git a/arch/arm/cpu/Kconfig b/arch/arm/cpu/Kconfig index 5337c46420..f55e8626a8 100644 --- a/arch/arm/cpu/Kconfig +++ b/arch/arm/cpu/Kconfig @@ -45,6 +45,11 @@ config CPU_V7 bool select CPU_32v7 +# Xscale PXA25x, PXA27x +config CPU_XSCALE + bool + select CPU_32v4T + # Figure out what processor architecture version we should be using. # This defines the compiler instruction set which depends on the machine type. config CPU_32v4T diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig new file mode 100644 index 0000000000..9e3c53ac77 --- /dev/null +++ b/arch/arm/mach-pxa/Kconfig @@ -0,0 +1,37 @@ +if ARCH_PXA + +config ARCH_TEXT_BASE + hex + +config BOARDINFO + string + +# ---------------------------------------------------------- + +config ARCH_PXA2XX + bool + select CPU_XSCALE + +choice + prompt "Intel/Marvell PXA Processor" + +config ARCH_PXA27X + bool "PXA27x" + select ARCH_PXA2XX + +endchoice + +# ---------------------------------------------------------- + +if ARCH_PXA27X + +choice + prompt "PXA27x Board Type" + +endchoice + +endif + +# ---------------------------------------------------------- + +endif diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile new file mode 100644 index 0000000000..c01a9e0281 --- /dev/null +++ b/arch/arm/mach-pxa/Makefile @@ -0,0 +1,6 @@ +obj-y += clocksource.o +obj-y += common.o +obj-y += gpio.o + +obj-$(CONFIG_ARCH_PXA2XX) += mfp-pxa2xx.o +obj-$(CONFIG_ARCH_PXA27X) += speed-pxa27x.o diff --git a/arch/arm/mach-pxa/clocksource.c b/arch/arm/mach-pxa/clocksource.c new file mode 100644 index 0000000000..04d090a748 --- /dev/null +++ b/arch/arm/mach-pxa/clocksource.c @@ -0,0 +1,45 @@ +/* + * (C) Copyright 2009 Sascha Hauer + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +#define OSCR 0x40A00010 + +uint64_t pxa_clocksource_read(void) +{ + return readl(OSCR); +} + +static struct clocksource cs = { + .read = pxa_clocksource_read, + .mask = 0xffffffff, + .shift = 20, +}; + +static int clocksource_init(void) +{ + cs.mult = clocksource_hz2mult(3250000, cs.shift); + + init_clock(&cs); + + return 0; +} + +core_initcall(clocksource_init); diff --git a/arch/arm/mach-pxa/common.c b/arch/arm/mach-pxa/common.c new file mode 100644 index 0000000000..82e81b75d9 --- /dev/null +++ b/arch/arm/mach-pxa/common.c @@ -0,0 +1,37 @@ +/* + * (C) Copyright 2009 Sascha Hauer + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#define OSMR3 0x40A0000C +#define OSCR 0x40A00010 +#define OSSR 0x40A00014 +#define OWER 0x40A00018 + +#define OWER_WME (1 << 0) /* Watch-dog Match Enable */ +#define OSSR_M3 (1 << 3) /* Match status channel 3 */ + +void reset_cpu(ulong addr) +{ + /* Initialize the watchdog and let it fire */ + writel(OWER_WME, OWER); + writel(OSSR_M3, OSSR); + writel(readl(OSCR) + 368640, OSMR3); /* ... in 100 ms */ + + while (1); +} diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c new file mode 100644 index 0000000000..1a396f1258 --- /dev/null +++ b/arch/arm/mach-pxa/devices.c @@ -0,0 +1,49 @@ +/* + * (C) 2011 Robert Jarzmik + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include +#include +#include + +static inline struct device_d *pxa_add_device(char *name, int id, void *base, + int size, void *pdata) +{ + return add_generic_device(name, id, NULL, (resource_size_t)base, size, + IORESOURCE_MEM, pdata); +} + +struct device_d *pxa_add_i2c(void *base, int id, + struct i2c_platform_data *pdata) +{ + return pxa_add_device("i2c-pxa", id, base, 0x1000, pdata); +} + +struct device_d *pxa_add_uart(void *base, int id) +{ + return pxa_add_device("pxa_serial", id, base, 0x1000, NULL); +} + +struct device_d *pxa_add_fb(void *base, struct pxafb_platform_data *pdata) +{ + return pxa_add_device("pxafb", -1, base, 0x1000, pdata); +} + +struct device_d *pxa_add_mmc(void *base, int id, void *pdata) +{ + return pxa_add_device("pxa-mmc", id, base, 0x1000, pdata); +} diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c new file mode 100644 index 0000000000..4e98493e73 --- /dev/null +++ b/arch/arm/mach-pxa/gpio.c @@ -0,0 +1,68 @@ +/* + * Generic PXA GPIO handling + * + * Author: Nicolas Pitre + * Created: Jun 15, 2001 + * Copyright: MontaVista Software 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 + +int pxa_last_gpio; + +struct pxa_gpio_chip { + void __iomem *regbase; +}; + +static struct pxa_gpio_chip *pxa_gpio_chips; + +#define for_each_gpio_chip(i, c) \ + for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++) + +static int __init pxa_init_gpio_chip(int gpio_end) +{ + int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1; + struct pxa_gpio_chip *chips; + + chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL); + if (chips == NULL) { + pr_err("%s: failed to allocate GPIO chips\n", __func__); + return -ENOMEM; + } + + for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) + chips[i].regbase = (void __iomem *)GPIO_BANK(i); + + pxa_gpio_chips = chips; + return 0; +} + +int __init pxa_init_gpio(int start, int end) +{ + struct pxa_gpio_chip *c; + int err, gpio; + + pxa_last_gpio = end; + + /* Initialize GPIO chips */ + err = pxa_init_gpio_chip(end); + if (err) + return err; + + for_each_gpio_chip(gpio, c) { + /* clear all GPIO edge detects */ + __raw_writel(0, c->regbase + GFER_OFFSET); + __raw_writel(0, c->regbase + GRER_OFFSET); + __raw_writel(~0, c->regbase + GEDR_OFFSET); + } + + return 0; +} diff --git a/arch/arm/mach-pxa/include/mach/clock.h b/arch/arm/mach-pxa/include/mach/clock.h new file mode 100644 index 0000000000..cd0ab8ea3f --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/clock.h @@ -0,0 +1,16 @@ + +/* + * clock.h - definitions of the PXA clock functions + * + * Copyright (C) 2010 by Marc Kleine-Budde + * + * This file is released under the GPLv2 + * + */ + +#ifndef __MACH_CLOCK_H +#define __MACH_CLOCK_H + +unsigned long pxa_get_uartclk(void); + +#endif /* !__MACH_CLOCK_H */ diff --git a/arch/arm/mach-pxa/include/mach/devices.h b/arch/arm/mach-pxa/include/mach/devices.h new file mode 100644 index 0000000000..e205b7c7f2 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/devices.h @@ -0,0 +1,26 @@ +/* + * (C) 2011 Robert Jarzmik + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include + +struct device_d *pxa_add_i2c(void *base, int id, + struct i2c_platform_data *pdata); +struct device_d *pxa_add_uart(void *base, int id); +struct device_d *pxa_add_fb(void *base, struct pxafb_platform_data *pdata); +struct device_d *pxa_add_mmc(void *base, int id, void *pdata); + diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h new file mode 100644 index 0000000000..e6724e1caf --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/gpio.h @@ -0,0 +1,132 @@ +/* + * arch/arm/mach-pxa/include/mach/gpio.h + * + * PXA GPIO wrappers for arch-neutral GPIO calls + * + * Written by Philipp Zabel + * + * 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. + * + */ + +#ifndef __ASM_ARCH_PXA_GPIO_H +#define __ASM_ARCH_PXA_GPIO_H + +#include + +#define GPIO_REGS_VIRT (0x40E00000) + +#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) +#define GPIO_REG(x) (*(volatile u32 *)(GPIO_REGS_VIRT + (x))) + +/* GPIO Pin Level Registers */ +#define GPLR0 GPIO_REG(BANK_OFF(0) + 0x00) +#define GPLR1 GPIO_REG(BANK_OFF(1) + 0x00) +#define GPLR2 GPIO_REG(BANK_OFF(2) + 0x00) +#define GPLR3 GPIO_REG(BANK_OFF(3) + 0x00) + +/* GPIO Pin Direction Registers */ +#define GPDR0 GPIO_REG(BANK_OFF(0) + 0x0c) +#define GPDR1 GPIO_REG(BANK_OFF(1) + 0x0c) +#define GPDR2 GPIO_REG(BANK_OFF(2) + 0x0c) +#define GPDR3 GPIO_REG(BANK_OFF(3) + 0x0c) + +/* GPIO Pin Output Set Registers */ +#define GPSR0 GPIO_REG(BANK_OFF(0) + 0x18) +#define GPSR1 GPIO_REG(BANK_OFF(1) + 0x18) +#define GPSR2 GPIO_REG(BANK_OFF(2) + 0x18) +#define GPSR3 GPIO_REG(BANK_OFF(3) + 0x18) + +/* GPIO Pin Output Clear Registers */ +#define GPCR0 GPIO_REG(BANK_OFF(0) + 0x24) +#define GPCR1 GPIO_REG(BANK_OFF(1) + 0x24) +#define GPCR2 GPIO_REG(BANK_OFF(2) + 0x24) +#define GPCR3 GPIO_REG(BANK_OFF(3) + 0x24) + +/* GPIO Rising Edge Detect Registers */ +#define GRER0 GPIO_REG(BANK_OFF(0) + 0x30) +#define GRER1 GPIO_REG(BANK_OFF(1) + 0x30) +#define GRER2 GPIO_REG(BANK_OFF(2) + 0x30) +#define GRER3 GPIO_REG(BANK_OFF(3) + 0x30) + +/* GPIO Falling Edge Detect Registers */ +#define GFER0 GPIO_REG(BANK_OFF(0) + 0x3c) +#define GFER1 GPIO_REG(BANK_OFF(1) + 0x3c) +#define GFER2 GPIO_REG(BANK_OFF(2) + 0x3c) +#define GFER3 GPIO_REG(BANK_OFF(3) + 0x3c) + +/* GPIO Edge Detect Status Registers */ +#define GEDR0 GPIO_REG(BANK_OFF(0) + 0x48) +#define GEDR1 GPIO_REG(BANK_OFF(1) + 0x48) +#define GEDR2 GPIO_REG(BANK_OFF(2) + 0x48) +#define GEDR3 GPIO_REG(BANK_OFF(3) + 0x48) + +/* GPIO Alternate Function Select Registers */ +#define GAFR0_L GPIO_REG(0x0054) +#define GAFR0_U GPIO_REG(0x0058) +#define GAFR1_L GPIO_REG(0x005C) +#define GAFR1_U GPIO_REG(0x0060) +#define GAFR2_L GPIO_REG(0x0064) +#define GAFR2_U GPIO_REG(0x0068) +#define GAFR3_L GPIO_REG(0x006C) +#define GAFR3_U GPIO_REG(0x0070) + +/* More handy macros. The argument is a literal GPIO number. */ + +#define GPIO_bit(x) (1 << ((x) & 0x1f)) + +#define GPLR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x00) +#define GPDR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x0c) +#define GPSR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x18) +#define GPCR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x24) +#define GRER(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x30) +#define GFER(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x3c) +#define GEDR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x48) +#define GAFR(x) GPIO_REG(0x54 + (((x) & 0x70) >> 2)) + + +#define NR_BUILTIN_GPIO 128 + +#define gpio_to_bank(gpio) ((gpio) >> 5) + +#ifdef CONFIG_CPU_PXA26x +/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted, + * as well as their Alternate Function value being '1' for GPIO in GAFRx. + */ +static inline int __gpio_is_inverted(unsigned gpio) +{ + return cpu_is_pxa25x() && gpio > 85; +} +#else +static inline int __gpio_is_inverted(unsigned gpio) { return 0; } +#endif + +/* + * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate + * function of a GPIO, and GPDRx cannot be altered once configured. It + * is attributed as "occupied" here (I know this terminology isn't + * accurate, you are welcome to propose a better one :-) + */ +static inline int __gpio_is_occupied(unsigned gpio) +{ + if (cpu_is_pxa27x() || cpu_is_pxa25x()) { + int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3; + int dir = GPDR(gpio) & GPIO_bit(gpio); + + if (__gpio_is_inverted(gpio)) + return af != 1 || dir == 0; + else + return af != 0 || dir != 0; + } else + return GPDR(gpio) & GPIO_bit(gpio); +} +#include +#endif diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h new file mode 100644 index 0000000000..e53085cdde --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/hardware.h @@ -0,0 +1,31 @@ +/* + * (c) 2010 by Marc Kleine-Budde + * + * Copyright (C) 2010 by Marc Kleine-Budde + * + * This file is released under the GPLv2 + * + */ + +#ifndef __MACH_HARDWARE_H +#define __MACH_HARDWARE_H + +#ifdef CONFIG_ARCH_PXA2XX +#define cpu_is_pxa2xx() (1) +#else +#define cpi_is_pxa2xx() (0) +#endif + +#ifdef CONFIG_ARCH_PXA25X +#define cpu_is_pxa25x() (1) +#else +#define cpu_is_pxa25x() (0) +#endif + +#ifdef CONFIG_ARCH_PXA27X +#define cpu_is_pxa27x() (1) +#else +#define cpu_is_pxa27x() (0) +#endif + +#endif /* !__MACH_HARDWARE_H */ diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h new file mode 100644 index 0000000000..6543c05f47 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h @@ -0,0 +1,438 @@ +#ifndef __ASM_ARCH_MFP_PXA27X_H +#define __ASM_ARCH_MFP_PXA27X_H + +/* + * NOTE: for those special-function bidirectional GPIOs, as described + * in the "PXA27x Developer's Manual" Section 24.4.2.1, only its input + * alternative is preserved, the direction is actually selected by the + * specific controller, and this should work in most cases. + */ + +#include + +/* Note: GPIO3/GPIO4 will be driven by Power I2C when PCFR/PI2C_EN + * bit is set, regardless of the GPIO configuration + */ +#define GPIO3_GPIO MFP_CFG_IN(GPIO3, AF0) +#define GPIO4_GPIO MFP_CFG_IN(GPIO4, AF0) + +/* GPIO */ +#define GPIO85_GPIO MFP_CFG_IN(GPIO85, AF0) +#define GPIO86_GPIO MFP_CFG_IN(GPIO86, AF0) +#define GPIO87_GPIO MFP_CFG_IN(GPIO87, AF0) +#define GPIO88_GPIO MFP_CFG_IN(GPIO88, AF0) +#define GPIO89_GPIO MFP_CFG_IN(GPIO89, AF0) +#define GPIO90_GPIO MFP_CFG_IN(GPIO90, AF0) +#define GPIO91_GPIO MFP_CFG_IN(GPIO91, AF0) +#define GPIO92_GPIO MFP_CFG_IN(GPIO92, AF0) +#define GPIO93_GPIO MFP_CFG_IN(GPIO93, AF0) +#define GPIO94_GPIO MFP_CFG_IN(GPIO94, AF0) +#define GPIO95_GPIO MFP_CFG_IN(GPIO95, AF0) +#define GPIO96_GPIO MFP_CFG_IN(GPIO96, AF0) +#define GPIO97_GPIO MFP_CFG_IN(GPIO97, AF0) +#define GPIO98_GPIO MFP_CFG_IN(GPIO98, AF0) +#define GPIO99_GPIO MFP_CFG_IN(GPIO99, AF0) +#define GPIO100_GPIO MFP_CFG_IN(GPIO100, AF0) +#define GPIO101_GPIO MFP_CFG_IN(GPIO101, AF0) +#define GPIO102_GPIO MFP_CFG_IN(GPIO102, AF0) +#define GPIO103_GPIO MFP_CFG_IN(GPIO103, AF0) +#define GPIO104_GPIO MFP_CFG_IN(GPIO104, AF0) +#define GPIO105_GPIO MFP_CFG_IN(GPIO105, AF0) +#define GPIO106_GPIO MFP_CFG_IN(GPIO106, AF0) +#define GPIO107_GPIO MFP_CFG_IN(GPIO107, AF0) +#define GPIO108_GPIO MFP_CFG_IN(GPIO108, AF0) +#define GPIO109_GPIO MFP_CFG_IN(GPIO109, AF0) +#define GPIO110_GPIO MFP_CFG_IN(GPIO110, AF0) +#define GPIO111_GPIO MFP_CFG_IN(GPIO111, AF0) +#define GPIO112_GPIO MFP_CFG_IN(GPIO112, AF0) +#define GPIO113_GPIO MFP_CFG_IN(GPIO113, AF0) +#define GPIO114_GPIO MFP_CFG_IN(GPIO114, AF0) +#define GPIO115_GPIO MFP_CFG_IN(GPIO115, AF0) +#define GPIO116_GPIO MFP_CFG_IN(GPIO116, AF0) +#define GPIO117_GPIO MFP_CFG_IN(GPIO117, AF0) +#define GPIO118_GPIO MFP_CFG_IN(GPIO118, AF0) +#define GPIO119_GPIO MFP_CFG_IN(GPIO119, AF0) +#define GPIO120_GPIO MFP_CFG_IN(GPIO120, AF0) + +/* Crystal and Clock Signals */ +#define GPIO9_HZ_CLK MFP_CFG_OUT(GPIO9, AF1, DRIVE_LOW) +#define GPIO10_HZ_CLK MFP_CFG_OUT(GPIO10, AF1, DRIVE_LOW) +#define GPIO11_48_MHz MFP_CFG_OUT(GPIO11, AF3, DRIVE_LOW) +#define GPIO12_48_MHz MFP_CFG_OUT(GPIO12, AF3, DRIVE_LOW) +#define GPIO13_CLK_EXT MFP_CFG_IN(GPIO13, AF1) + +/* OS Timer Signals */ +#define GPIO11_EXT_SYNC_0 MFP_CFG_IN(GPIO11, AF1) +#define GPIO12_EXT_SYNC_1 MFP_CFG_IN(GPIO12, AF1) +#define GPIO9_CHOUT_0 MFP_CFG_OUT(GPIO9, AF3, DRIVE_LOW) +#define GPIO10_CHOUT_1 MFP_CFG_OUT(GPIO10, AF3, DRIVE_LOW) +#define GPIO11_CHOUT_0 MFP_CFG_OUT(GPIO11, AF1, DRIVE_LOW) +#define GPIO12_CHOUT_1 MFP_CFG_OUT(GPIO12, AF1, DRIVE_LOW) + +/* SDRAM and Static Memory I/O Signals */ +#define GPIO20_nSDCS_2 MFP_CFG_OUT(GPIO20, AF1, DRIVE_HIGH) +#define GPIO21_nSDCS_3 MFP_CFG_OUT(GPIO21, AF1, DRIVE_HIGH) +#define GPIO15_nCS_1 MFP_CFG_OUT(GPIO15, AF2, DRIVE_HIGH) +#define GPIO78_nCS_2 MFP_CFG_OUT(GPIO78, AF2, DRIVE_HIGH) +#define GPIO79_nCS_3 MFP_CFG_OUT(GPIO79, AF2, DRIVE_HIGH) +#define GPIO80_nCS_4 MFP_CFG_OUT(GPIO80, AF2, DRIVE_HIGH) +#define GPIO33_nCS_5 MFP_CFG_OUT(GPIO33, AF2, DRIVE_HIGH) + +/* Miscellaneous I/O and DMA Signals */ +#define GPIO21_DVAL_0 MFP_CFG_OUT(GPIO21, AF2, DRIVE_HIGH) +#define GPIO116_DVAL_0 MFP_CFG_OUT(GPIO116, AF1, DRIVE_HIGH) +#define GPIO33_DVAL_1 MFP_CFG_OUT(GPIO33, AF1, DRIVE_HIGH) +#define GPIO96_DVAL_1 MFP_CFG_OUT(GPIO96, AF2, DRIVE_HIGH) +#define GPIO18_RDY MFP_CFG_IN(GPIO18, AF1) +#define GPIO20_DREQ_0 MFP_CFG_IN(GPIO20, AF1) +#define GPIO115_DREQ_0 MFP_CFG_IN(GPIO115, AF1) +#define GPIO80_DREQ_1 MFP_CFG_IN(GPIO80, AF1) +#define GPIO97_DREQ_1 MFP_CFG_IN(GPIO97, AF2) +#define GPIO85_DREQ_2 MFP_CFG_IN(GPIO85, AF2) +#define GPIO100_DREQ_2 MFP_CFG_IN(GPIO100, AF2) + +/* Alternate Bus Master Mode I/O Signals */ +#define GPIO20_MBREQ MFP_CFG_IN(GPIO20, AF2) +#define GPIO80_MBREQ MFP_CFG_IN(GPIO80, AF2) +#define GPIO96_MBREQ MFP_CFG_IN(GPIO96, AF2) +#define GPIO115_MBREQ MFP_CFG_IN(GPIO115, AF3) +#define GPIO21_MBGNT MFP_CFG_OUT(GPIO21, AF3, DRIVE_LOW) +#define GPIO33_MBGNT MFP_CFG_OUT(GPIO33, AF3, DRIVE_LOW) +#define GPIO97_MBGNT MFP_CFG_OUT(GPIO97, AF2, DRIVE_LOW) +#define GPIO116_MBGNT MFP_CFG_OUT(GPIO116, AF3, DRIVE_LOW) + +/* PC CARD */ +#define GPIO15_nPCE_1 MFP_CFG_OUT(GPIO15, AF1, DRIVE_HIGH) +#define GPIO85_nPCE_1 MFP_CFG_OUT(GPIO85, AF1, DRIVE_HIGH) +#define GPIO86_nPCE_1 MFP_CFG_OUT(GPIO86, AF1, DRIVE_HIGH) +#define GPIO102_nPCE_1 MFP_CFG_OUT(GPIO102, AF1, DRIVE_HIGH) +#define GPIO54_nPCE_2 MFP_CFG_OUT(GPIO54, AF2, DRIVE_HIGH) +#define GPIO78_nPCE_2 MFP_CFG_OUT(GPIO78, AF1, DRIVE_HIGH) +#define GPIO87_nPCE_2 MFP_CFG_IN(GPIO87, AF1) +#define GPIO55_nPREG MFP_CFG_OUT(GPIO55, AF2, DRIVE_HIGH) +#define GPIO50_nPIOR MFP_CFG_OUT(GPIO50, AF2, DRIVE_HIGH) +#define GPIO51_nPIOW MFP_CFG_OUT(GPIO51, AF2, DRIVE_HIGH) +#define GPIO49_nPWE MFP_CFG_OUT(GPIO49, AF2, DRIVE_HIGH) +#define GPIO48_nPOE MFP_CFG_OUT(GPIO48, AF2, DRIVE_HIGH) +#define GPIO57_nIOIS16 MFP_CFG_IN(GPIO57, AF1) +#define GPIO56_nPWAIT MFP_CFG_IN(GPIO56, AF1) +#define GPIO79_PSKTSEL MFP_CFG_OUT(GPIO79, AF1, DRIVE_HIGH) +#define GPIO104_PSKTSEL MFP_CFG_OUT(GPIO104, AF1, DRIVE_HIGH) + +/* I2C */ +#define GPIO117_I2C_SCL MFP_CFG_IN(GPIO117, AF1) +#define GPIO118_I2C_SDA MFP_CFG_IN(GPIO118, AF1) + +/* FFUART */ +#define GPIO9_FFUART_CTS MFP_CFG_IN(GPIO9, AF3) +#define GPIO26_FFUART_CTS MFP_CFG_IN(GPIO26, AF3) +#define GPIO35_FFUART_CTS MFP_CFG_IN(GPIO35, AF1) +#define GPIO100_FFUART_CTS MFP_CFG_IN(GPIO100, AF3) +#define GPIO10_FFUART_DCD MFP_CFG_IN(GPIO10, AF1) +#define GPIO36_FFUART_DCD MFP_CFG_IN(GPIO36, AF1) +#define GPIO33_FFUART_DSR MFP_CFG_IN(GPIO33, AF2) +#define GPIO37_FFUART_DSR MFP_CFG_IN(GPIO37, AF1) +#define GPIO38_FFUART_RI MFP_CFG_IN(GPIO38, AF1) +#define GPIO89_FFUART_RI MFP_CFG_IN(GPIO89, AF3) +#define GPIO19_FFUART_RXD MFP_CFG_IN(GPIO19, AF3) +#define GPIO33_FFUART_RXD MFP_CFG_IN(GPIO33, AF1) +#define GPIO34_FFUART_RXD MFP_CFG_IN(GPIO34, AF1) +#define GPIO41_FFUART_RXD MFP_CFG_IN(GPIO41, AF1) +#define GPIO53_FFUART_RXD MFP_CFG_IN(GPIO53, AF1) +#define GPIO85_FFUART_RXD MFP_CFG_IN(GPIO85, AF1) +#define GPIO96_FFUART_RXD MFP_CFG_IN(GPIO96, AF3) +#define GPIO102_FFUART_RXD MFP_CFG_IN(GPIO102, AF3) +#define GPIO16_FFUART_TXD MFP_CFG_OUT(GPIO16, AF3, DRIVE_HIGH) +#define GPIO37_FFUART_TXD MFP_CFG_OUT(GPIO37, AF3, DRIVE_HIGH) +#define GPIO39_FFUART_TXD MFP_CFG_OUT(GPIO39, AF2, DRIVE_HIGH) +#define GPIO83_FFUART_TXD MFP_CFG_OUT(GPIO83, AF2, DRIVE_HIGH) +#define GPIO99_FFUART_TXD MFP_CFG_OUT(GPIO99, AF3, DRIVE_HIGH) +#define GPIO27_FFUART_RTS MFP_CFG_OUT(GPIO27, AF3, DRIVE_HIGH) +#define GPIO41_FFUART_RTS MFP_CFG_OUT(GPIO41, AF2, DRIVE_HIGH) +#define GPIO83_FFUART_RTS MFP_CFG_OUT(GPIO83, AF3, DRIVE_HIGH) +#define GPIO98_FFUART_RTS MFP_CFG_OUT(GPIO98, AF3, DRIVE_HIGH) +#define GPIO40_FFUART_DTR MFP_CFG_OUT(GPIO40, AF2, DRIVE_HIGH) +#define GPIO82_FFUART_DTR MFP_CFG_OUT(GPIO82, AF3, DRIVE_HIGH) + +/* BTUART */ +#define GPIO44_BTUART_CTS MFP_CFG_IN(GPIO44, AF1) +#define GPIO42_BTUART_RXD MFP_CFG_IN(GPIO42, AF1) +#define GPIO45_BTUART_RTS MFP_CFG_OUT(GPIO45, AF2, DRIVE_HIGH) +#define GPIO43_BTUART_TXD MFP_CFG_OUT(GPIO43, AF2, DRIVE_HIGH) + +/* STUART */ +#define GPIO46_STUART_RXD MFP_CFG_IN(GPIO46, AF2) +#define GPIO47_STUART_TXD MFP_CFG_OUT(GPIO47, AF1, DRIVE_HIGH) + +/* FICP */ +#define GPIO42_FICP_RXD MFP_CFG_IN(GPIO42, AF2) +#define GPIO46_FICP_RXD MFP_CFG_IN(GPIO46, AF1) +#define GPIO43_FICP_TXD MFP_CFG_OUT(GPIO43, AF1, DRIVE_HIGH) +#define GPIO47_FICP_TXD MFP_CFG_OUT(GPIO47, AF2, DRIVE_HIGH) + +/* PWM 0/1/2/3 */ +#define GPIO11_PWM2_OUT MFP_CFG_OUT(GPIO11, AF2, DRIVE_LOW) +#define GPIO12_PWM3_OUT MFP_CFG_OUT(GPIO12, AF2, DRIVE_LOW) +#define GPIO16_PWM0_OUT MFP_CFG_OUT(GPIO16, AF2, DRIVE_LOW) +#define GPIO17_PWM1_OUT MFP_CFG_OUT(GPIO17, AF2, DRIVE_LOW) +#define GPIO38_PWM1_OUT MFP_CFG_OUT(GPIO38, AF3, DRIVE_LOW) +#define GPIO46_PWM2_OUT MFP_CFG_OUT(GPIO46, AF2, DRIVE_LOW) +#define GPIO47_PWM3_OUT MFP_CFG_OUT(GPIO47, AF3, DRIVE_LOW) +#define GPIO79_PWM2_OUT MFP_CFG_OUT(GPIO79, AF3, DRIVE_LOW) +#define GPIO80_PWM3_OUT MFP_CFG_OUT(GPIO80, AF3, DRIVE_LOW) +#define GPIO115_PWM1_OUT MFP_CFG_OUT(GPIO115, AF3, DRIVE_LOW) + +/* AC97 */ +#define GPIO31_AC97_SYNC MFP_CFG_OUT(GPIO31, AF2, DRIVE_LOW) +#define GPIO94_AC97_SYNC MFP_CFG_OUT(GPIO94, AF1, DRIVE_LOW) +#define GPIO30_AC97_SDATA_OUT MFP_CFG_OUT(GPIO30, AF2, DRIVE_LOW) +#define GPIO93_AC97_SDATA_OUT MFP_CFG_OUT(GPIO93, AF1, DRIVE_LOW) +#define GPIO45_AC97_SYSCLK MFP_CFG_OUT(GPIO45, AF1, DRIVE_LOW) +#define GPIO89_AC97_SYSCLK MFP_CFG_OUT(GPIO89, AF1, DRIVE_LOW) +#define GPIO98_AC97_SYSCLK MFP_CFG_OUT(GPIO98, AF1, DRIVE_LOW) +#define GPIO95_AC97_nRESET MFP_CFG_OUT(GPIO95, AF1, DRIVE_LOW) +#define GPIO113_AC97_nRESET MFP_CFG_OUT(GPIO113, AF2, DRIVE_LOW) +#define GPIO28_AC97_BITCLK MFP_CFG_IN(GPIO28, AF1) +#define GPIO29_AC97_SDATA_IN_0 MFP_CFG_IN(GPIO29, AF1) +#define GPIO116_AC97_SDATA_IN_0 MFP_CFG_IN(GPIO116, AF2) +#define GPIO99_AC97_SDATA_IN_1 MFP_CFG_IN(GPIO99, AF2) + +/* I2S */ +#define GPIO28_I2S_BITCLK_IN MFP_CFG_IN(GPIO28, AF2) +#define GPIO28_I2S_BITCLK_OUT MFP_CFG_OUT(GPIO28, AF1, DRIVE_LOW) +#define GPIO29_I2S_SDATA_IN MFP_CFG_IN(GPIO29, AF2) +#define GPIO30_I2S_SDATA_OUT MFP_CFG_OUT(GPIO30, AF1, DRIVE_LOW) +#define GPIO31_I2S_SYNC MFP_CFG_OUT(GPIO31, AF1, DRIVE_LOW) +#define GPIO113_I2S_SYSCLK MFP_CFG_OUT(GPIO113, AF1, DRIVE_LOW) + +/* SSP 1 */ +#define GPIO23_SSP1_SCLK MFP_CFG_OUT(GPIO23, AF2, DRIVE_LOW) +#define GPIO29_SSP1_SCLK MFP_CFG_IN(GPIO29, AF3) +#define GPIO27_SSP1_SYSCLK MFP_CFG_OUT(GPIO27, AF1, DRIVE_LOW) +#define GPIO53_SSP1_SYSCLK MFP_CFG_OUT(GPIO53, AF3, DRIVE_LOW) +#define GPIO24_SSP1_SFRM MFP_CFG_IN(GPIO24, AF2) +#define GPIO28_SSP1_SFRM MFP_CFG_IN(GPIO28, AF3) +#define GPIO25_SSP1_TXD MFP_CFG_OUT(GPIO25, AF2, DRIVE_LOW) +#define GPIO57_SSP1_TXD MFP_CFG_OUT(GPIO57, AF3, DRIVE_LOW) +#define GPIO26_SSP1_RXD MFP_CFG_IN(GPIO26, AF1) +#define GPIO27_SSP1_SCLKEN MFP_CFG_IN(GPIO27, AF2) + +/* SSP 2 */ +#define GPIO19_SSP2_SCLK MFP_CFG_IN(GPIO19, AF1) +#define GPIO22_SSP2_SCLK MFP_CFG_IN(GPIO22, AF3) +#define GPIO29_SSP2_SCLK MFP_CFG_OUT(GPIO29, AF3, DRIVE_LOW) +#define GPIO36_SSP2_SCLK MFP_CFG_IN(GPIO36, AF2) +#define GPIO50_SSP2_SCLK MFP_CFG_IN(GPIO50, AF3) +#define GPIO22_SSP2_SYSCLK MFP_CFG_OUT(GPIO22, AF2, DRIVE_LOW) +#define GPIO14_SSP2_SFRM MFP_CFG_IN(GPIO14, AF2) +#define GPIO37_SSP2_SFRM MFP_CFG_IN(GPIO37, AF2) +#define GPIO87_SSP2_SFRM MFP_CFG_OUT(GPIO87, AF3, DRIVE_LOW) +#define GPIO88_SSP2_SFRM MFP_CFG_IN(GPIO88, AF3) +#define GPIO13_SSP2_TXD MFP_CFG_OUT(GPIO13, AF1, DRIVE_LOW) +#define GPIO38_SSP2_TXD MFP_CFG_OUT(GPIO38, AF2, DRIVE_LOW) +#define GPIO87_SSP2_TXD MFP_CFG_OUT(GPIO87, AF1, DRIVE_LOW) +#define GPIO89_SSP2_TXD MFP_CFG_OUT(GPIO89, AF3, DRIVE_LOW) +#define GPIO11_SSP2_RXD MFP_CFG_IN(GPIO11, AF2) +#define GPIO29_SSP2_RXD MFP_CFG_OUT(GPIO29, AF1, DRIVE_LOW) +#define GPIO40_SSP2_RXD MFP_CFG_IN(GPIO40, AF1) +#define GPIO86_SSP2_RXD MFP_CFG_IN(GPIO86, AF1) +#define GPIO88_SSP2_RXD MFP_CFG_IN(GPIO88, AF2) +#define GPIO22_SSP2_EXTCLK MFP_CFG_IN(GPIO22, AF1) +#define GPIO27_SSP2_EXTCLK MFP_CFG_IN(GPIO27, AF1) +#define GPIO22_SSP2_SCLKEN MFP_CFG_IN(GPIO22, AF2) +#define GPIO23_SSP2_SCLKEN MFP_CFG_IN(GPIO23, AF2) + +/* SSP 3 */ +#define GPIO34_SSP3_SCLK MFP_CFG_IN(GPIO34, AF3) +#define GPIO40_SSP3_SCLK MFP_CFG_OUT(GPIO40, AF3, DRIVE_LOW) +#define GPIO52_SSP3_SCLK MFP_CFG_IN(GPIO52, AF2) +#define GPIO84_SSP3_SCLK MFP_CFG_IN(GPIO84, AF1) +#define GPIO45_SSP3_SYSCLK MFP_CFG_OUT(GPIO45, AF3, DRIVE_LOW) +#define GPIO35_SSP3_SFRM MFP_CFG_IN(GPIO35, AF3) +#define GPIO39_SSP3_SFRM MFP_CFG_IN(GPIO39, AF3) +#define GPIO83_SSP3_SFRM MFP_CFG_IN(GPIO83, AF1) +#define GPIO35_SSP3_TXD MFP_CFG_OUT(GPIO35, AF3, DRIVE_LOW) +#define GPIO38_SSP3_TXD MFP_CFG_OUT(GPIO38, AF1, DRIVE_LOW) +#define GPIO81_SSP3_TXD MFP_CFG_OUT(GPIO81, AF1, DRIVE_LOW) +#define GPIO41_SSP3_RXD MFP_CFG_IN(GPIO41, AF3) +#define GPIO82_SSP3_RXD MFP_CFG_IN(GPIO82, AF1) +#define GPIO89_SSP3_RXD MFP_CFG_IN(GPIO89, AF1) + +/* MMC */ +#define GPIO32_MMC_CLK MFP_CFG_OUT(GPIO32, AF2, DRIVE_LOW) +#define GPIO92_MMC_DAT_0 MFP_CFG_IN(GPIO92, AF1) +#define GPIO109_MMC_DAT_1 MFP_CFG_IN(GPIO109, AF1) +#define GPIO110_MMC_DAT_2 MFP_CFG_IN(GPIO110, AF1) +#define GPIO111_MMC_DAT_3 MFP_CFG_IN(GPIO111, AF1) +#define GPIO112_MMC_CMD MFP_CFG_IN(GPIO112, AF1) + +/* LCD */ +#define GPIO58_LCD_LDD_0 MFP_CFG_OUT(GPIO58, AF2, DRIVE_LOW) +#define GPIO59_LCD_LDD_1 MFP_CFG_OUT(GPIO59, AF2, DRIVE_LOW) +#define GPIO60_LCD_LDD_2 MFP_CFG_OUT(GPIO60, AF2, DRIVE_LOW) +#define GPIO61_LCD_LDD_3 MFP_CFG_OUT(GPIO61, AF2, DRIVE_LOW) +#define GPIO62_LCD_LDD_4 MFP_CFG_OUT(GPIO62, AF2, DRIVE_LOW) +#define GPIO63_LCD_LDD_5 MFP_CFG_OUT(GPIO63, AF2, DRIVE_LOW) +#define GPIO64_LCD_LDD_6 MFP_CFG_OUT(GPIO64, AF2, DRIVE_LOW) +#define GPIO65_LCD_LDD_7 MFP_CFG_OUT(GPIO65, AF2, DRIVE_LOW) +#define GPIO66_LCD_LDD_8 MFP_CFG_OUT(GPIO66, AF2, DRIVE_LOW) +#define GPIO67_LCD_LDD_9 MFP_CFG_OUT(GPIO67, AF2, DRIVE_LOW) +#define GPIO68_LCD_LDD_10 MFP_CFG_OUT(GPIO68, AF2, DRIVE_LOW) +#define GPIO69_LCD_LDD_11 MFP_CFG_OUT(GPIO69, AF2, DRIVE_LOW) +#define GPIO70_LCD_LDD_12 MFP_CFG_OUT(GPIO70, AF2, DRIVE_LOW) +#define GPIO71_LCD_LDD_13 MFP_CFG_OUT(GPIO71, AF2, DRIVE_LOW) +#define GPIO72_LCD_LDD_14 MFP_CFG_OUT(GPIO72, AF2, DRIVE_LOW) +#define GPIO73_LCD_LDD_15 MFP_CFG_OUT(GPIO73, AF2, DRIVE_LOW) +#define GPIO86_LCD_LDD_16 MFP_CFG_OUT(GPIO86, AF2, DRIVE_LOW) +#define GPIO87_LCD_LDD_17 MFP_CFG_OUT(GPIO87, AF2, DRIVE_LOW) +#define GPIO74_LCD_FCLK MFP_CFG_OUT(GPIO74, AF2, DRIVE_LOW) +#define GPIO75_LCD_LCLK MFP_CFG_OUT(GPIO75, AF2, DRIVE_LOW) +#define GPIO76_LCD_PCLK MFP_CFG_OUT(GPIO76, AF2, DRIVE_LOW) +#define GPIO77_LCD_BIAS MFP_CFG_OUT(GPIO77, AF2, DRIVE_LOW) +#define GPIO14_LCD_VSYNC MFP_CFG_IN(GPIO14, AF1) +#define GPIO19_LCD_CS MFP_CFG_OUT(GPIO19, AF2, DRIVE_LOW) + +/* Keypad */ +#define GPIO93_KP_DKIN_0 MFP_CFG_IN(GPIO93, AF1) +#define GPIO94_KP_DKIN_1 MFP_CFG_IN(GPIO94, AF1) +#define GPIO95_KP_DKIN_2 MFP_CFG_IN(GPIO95, AF1) +#define GPIO96_KP_DKIN_3 MFP_CFG_IN(GPIO96, AF1) +#define GPIO97_KP_DKIN_4 MFP_CFG_IN(GPIO97, AF1) +#define GPIO98_KP_DKIN_5 MFP_CFG_IN(GPIO98, AF1) +#define GPIO99_KP_DKIN_6 MFP_CFG_IN(GPIO99, AF1) +#define GPIO13_KP_KDIN_7 MFP_CFG_IN(GPIO13, AF2) +#define GPIO100_KP_MKIN_0 MFP_CFG_IN(GPIO100, AF1) +#define GPIO101_KP_MKIN_1 MFP_CFG_IN(GPIO101, AF1) +#define GPIO102_KP_MKIN_2 MFP_CFG_IN(GPIO102, AF1) +#define GPIO34_KP_MKIN_3 MFP_CFG_IN(GPIO34, AF2) +#define GPIO37_KP_MKIN_3 MFP_CFG_IN(GPIO37, AF3) +#define GPIO97_KP_MKIN_3 MFP_CFG_IN(GPIO97, AF3) +#define GPIO98_KP_MKIN_4 MFP_CFG_IN(GPIO98, AF3) +#define GPIO38_KP_MKIN_4 MFP_CFG_IN(GPIO38, AF2) +#define GPIO39_KP_MKIN_4 MFP_CFG_IN(GPIO39, AF1) +#define GPIO16_KP_MKIN_5 MFP_CFG_IN(GPIO16, AF1) +#define GPIO90_KP_MKIN_5 MFP_CFG_IN(GPIO90, AF1) +#define GPIO99_KP_MKIN_5 MFP_CFG_IN(GPIO99, AF3) +#define GPIO17_KP_MKIN_6 MFP_CFG_IN(GPIO17, AF1) +#define GPIO91_KP_MKIN_6 MFP_CFG_IN(GPIO91, AF1) +#define GPIO95_KP_MKIN_6 MFP_CFG_IN(GPIO95, AF3) +#define GPIO13_KP_MKIN_7 MFP_CFG_IN(GPIO13, AF3) +#define GPIO36_KP_MKIN_7 MFP_CFG_IN(GPIO36, AF3) +#define GPIO103_KP_MKOUT_0 MFP_CFG_OUT(GPIO103, AF2, DRIVE_HIGH) +#define GPIO104_KP_MKOUT_1 MFP_CFG_OUT(GPIO104, AF2, DRIVE_HIGH) +#define GPIO105_KP_MKOUT_2 MFP_CFG_OUT(GPIO105, AF2, DRIVE_HIGH) +#define GPIO106_KP_MKOUT_3 MFP_CFG_OUT(GPIO106, AF2, DRIVE_HIGH) +#define GPIO107_KP_MKOUT_4 MFP_CFG_OUT(GPIO107, AF2, DRIVE_HIGH) +#define GPIO108_KP_MKOUT_5 MFP_CFG_OUT(GPIO108, AF2, DRIVE_HIGH) +#define GPIO35_KP_MKOUT_6 MFP_CFG_OUT(GPIO35, AF2, DRIVE_HIGH) +#define GPIO22_KP_MKOUT_7 MFP_CFG_OUT(GPIO22, AF1, DRIVE_HIGH) +#define GPIO40_KP_MKOUT_6 MFP_CFG_OUT(GPIO40, AF1, DRIVE_HIGH) +#define GPIO41_KP_MKOUT_7 MFP_CFG_OUT(GPIO41, AF1, DRIVE_HIGH) +#define GPIO96_KP_MKOUT_6 MFP_CFG_OUT(GPIO96, AF3, DRIVE_HIGH) + +/* USB P3 */ +#define GPIO10_USB_P3_5 MFP_CFG_IN(GPIO10, AF3) +#define GPIO11_USB_P3_1 MFP_CFG_IN(GPIO11, AF3) +#define GPIO30_USB_P3_2 MFP_CFG_OUT(GPIO30, AF3, DRIVE_LOW) +#define GPIO31_USB_P3_6 MFP_CFG_OUT(GPIO31, AF3, DRIVE_LOW) +#define GPIO56_USB_P3_4 MFP_CFG_OUT(GPIO56, AF1, DRIVE_LOW) +#define GPIO86_USB_P3_5 MFP_CFG_IN(GPIO86, AF3) +#define GPIO87_USB_P3_1 MFP_CFG_IN(GPIO87, AF3) +#define GPIO90_USB_P3_5 MFP_CFG_IN(GPIO90, AF2) +#define GPIO91_USB_P3_1 MFP_CFG_IN(GPIO91, AF2) +#define GPIO113_USB_P3_3 MFP_CFG_IN(GPIO113, AF3) + +/* USB P2 */ +#define GPIO34_USB_P2_2 MFP_CFG_OUT(GPIO34, AF1, DRIVE_LOW) +#define GPIO35_USB_P2_1 MFP_CFG_IN(GPIO35, AF2) +#define GPIO36_USB_P2_4 MFP_CFG_OUT(GPIO36, AF1, DRIVE_LOW) +#define GPIO37_USB_P2_8 MFP_CFG_OUT(GPIO37, AF1, DRIVE_LOW) +#define GPIO38_USB_P2_3 MFP_CFG_IN(GPIO38, AF3) +#define GPIO39_USB_P2_6 MFP_CFG_OUT(GPIO39, AF1, DRIVE_LOW) +#define GPIO40_USB_P2_5 MFP_CFG_IN(GPIO40, AF3) +#define GPIO41_USB_P2_7 MFP_CFG_IN(GPIO41, AF2) +#define GPIO53_USB_P2_3 MFP_CFG_IN(GPIO53, AF2) + +/* USB Host Port 1/2 */ +#define GPIO88_USBH1_PWR MFP_CFG_IN(GPIO88, AF1) +#define GPIO89_USBH1_PEN MFP_CFG_OUT(GPIO89, AF2, DRIVE_LOW) +#define GPIO119_USBH2_PWR MFP_CFG_IN(GPIO119, AF1) +#define GPIO120_USBH2_PEN MFP_CFG_OUT(GPIO120, AF2, DRIVE_LOW) + +/* QCI - default to Master Mode: CIF_FV/CIF_LV Direction In */ +#define GPIO115_CIF_DD_3 MFP_CFG_IN(GPIO115, AF2) +#define GPIO116_CIF_DD_2 MFP_CFG_IN(GPIO116, AF1) +#define GPIO12_CIF_DD_7 MFP_CFG_IN(GPIO12, AF2) +#define GPIO17_CIF_DD_6 MFP_CFG_IN(GPIO17, AF2) +#define GPIO23_CIF_MCLK MFP_CFG_OUT(GPIO23, AF1, DRIVE_LOW) +#define GPIO24_CIF_FV MFP_CFG_IN(GPIO24, AF1) +#define GPIO25_CIF_LV MFP_CFG_IN(GPIO25, AF1) +#define GPIO26_CIF_PCLK MFP_CFG_IN(GPIO26, AF2) +#define GPIO27_CIF_DD_0 MFP_CFG_IN(GPIO27, AF3) +#define GPIO42_CIF_MCLK MFP_CFG_OUT(GPIO42, AF3, DRIVE_LOW) +#define GPIO43_CIF_FV MFP_CFG_IN(GPIO43, AF3) +#define GPIO44_CIF_LV MFP_CFG_IN(GPIO44, AF3) +#define GPIO45_CIF_PCLK MFP_CFG_IN(GPIO45, AF3) +#define GPIO47_CIF_DD_0 MFP_CFG_IN(GPIO47, AF1) +#define GPIO48_CIF_DD_5 MFP_CFG_IN(GPIO48, AF1) +#define GPIO50_CIF_DD_3 MFP_CFG_IN(GPIO50, AF1) +#define GPIO51_CIF_DD_2 MFP_CFG_IN(GPIO51, AF1) +#define GPIO52_CIF_DD_4 MFP_CFG_IN(GPIO52, AF1) +#define GPIO53_CIF_MCLK MFP_CFG_OUT(GPIO53, AF2, DRIVE_LOW) +#define GPIO54_CIF_PCLK MFP_CFG_IN(GPIO54, AF3) +#define GPIO55_CIF_DD_1 MFP_CFG_IN(GPIO55, AF1) +#define GPIO81_CIF_DD_0 MFP_CFG_IN(GPIO81, AF2) +#define GPIO82_CIF_DD_5 MFP_CFG_IN(GPIO82, AF3) +#define GPIO83_CIF_DD_4 MFP_CFG_IN(GPIO83, AF3) +#define GPIO84_CIF_FV MFP_CFG_IN(GPIO84, AF3) +#define GPIO85_CIF_LV MFP_CFG_IN(GPIO85, AF3) +#define GPIO90_CIF_DD_4 MFP_CFG_IN(GPIO90, AF3) +#define GPIO91_CIF_DD_5 MFP_CFG_IN(GPIO91, AF3) +#define GPIO93_CIF_DD_6 MFP_CFG_IN(GPIO93, AF2) +#define GPIO94_CIF_DD_5 MFP_CFG_IN(GPIO94, AF2) +#define GPIO95_CIF_DD_4 MFP_CFG_IN(GPIO95, AF2) +#define GPIO98_CIF_DD_0 MFP_CFG_IN(GPIO98, AF2) +#define GPIO103_CIF_DD_3 MFP_CFG_IN(GPIO103, AF1) +#define GPIO104_CIF_DD_2 MFP_CFG_IN(GPIO104, AF1) +#define GPIO105_CIF_DD_1 MFP_CFG_IN(GPIO105, AF1) +#define GPIO106_CIF_DD_9 MFP_CFG_IN(GPIO106, AF1) +#define GPIO107_CIF_DD_8 MFP_CFG_IN(GPIO107, AF1) +#define GPIO108_CIF_DD_7 MFP_CFG_IN(GPIO108, AF1) +#define GPIO114_CIF_DD_1 MFP_CFG_IN(GPIO114, AF1) + +/* Universal Subscriber ID Interface */ +#define GPIO114_UVS0 MFP_CFG_OUT(GPIO114, AF2, DRIVE_LOW) +#define GPIO115_nUVS1 MFP_CFG_OUT(GPIO115, AF2, DRIVE_LOW) +#define GPIO116_nUVS2 MFP_CFG_OUT(GPIO116, AF2, DRIVE_LOW) +#define GPIO14_UCLK MFP_CFG_OUT(GPIO14, AF3, DRIVE_LOW) +#define GPIO91_UCLK MFP_CFG_OUT(GPIO91, AF2, DRIVE_LOW) +#define GPIO19_nURST MFP_CFG_OUT(GPIO19, AF3, DRIVE_LOW) +#define GPIO90_nURST MFP_CFG_OUT(GPIO90, AF2, DRIVE_LOW) +#define GPIO116_UDET MFP_CFG_IN(GPIO116, AF3) +#define GPIO114_UEN MFP_CFG_OUT(GPIO114, AF1, DRIVE_LOW) +#define GPIO115_UEN MFP_CFG_OUT(GPIO115, AF1, DRIVE_LOW) + +/* Mobile Scalable Link (MSL) Interface */ +#define GPIO81_BB_OB_DAT_0 MFP_CFG_OUT(GPIO81, AF2, DRIVE_LOW) +#define GPIO48_BB_OB_DAT_1 MFP_CFG_OUT(GPIO48, AF1, DRIVE_LOW) +#define GPIO50_BB_OB_DAT_2 MFP_CFG_OUT(GPIO50, AF1, DRIVE_LOW) +#define GPIO51_BB_OB_DAT_3 MFP_CFG_OUT(GPIO51, AF1, DRIVE_LOW) +#define GPIO52_BB_OB_CLK MFP_CFG_OUT(GPIO52, AF1, DRIVE_LOW) +#define GPIO53_BB_OB_STB MFP_CFG_OUT(GPIO53, AF1, DRIVE_LOW) +#define GPIO54_BB_OB_WAIT MFP_CFG_IN(GPIO54, AF2) +#define GPIO82_BB_IB_DAT_0 MFP_CFG_IN(GPIO82, AF2) +#define GPIO55_BB_IB_DAT_1 MFP_CFG_IN(GPIO55, AF2) +#define GPIO56_BB_IB_DAT_2 MFP_CFG_IN(GPIO56, AF2) +#define GPIO57_BB_IB_DAT_3 MFP_CFG_IN(GPIO57, AF2) +#define GPIO83_BB_IB_CLK MFP_CFG_IN(GPIO83, AF2) +#define GPIO84_BB_IB_STB MFP_CFG_IN(GPIO84, AF2) +#define GPIO85_BB_IB_WAIT MFP_CFG_OUT(GPIO85, AF2, DRIVE_LOW) + +/* Memory Stick Host Controller */ +#define GPIO92_MSBS MFP_CFG_OUT(GPIO92, AF2, DRIVE_LOW) +#define GPIO109_MSSDIO MFP_CFG_IN(GPIO109, AF2) +#define GPIO112_nMSINS MFP_CFG_IN(GPIO112, AF2) +#define GPIO32_MSSCLK MFP_CFG_OUT(GPIO32, AF1, DRIVE_LOW) + +extern int keypad_set_wake(unsigned int on); +#endif /* __ASM_ARCH_MFP_PXA27X_H */ diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h new file mode 100644 index 0000000000..658b28ed12 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h @@ -0,0 +1,133 @@ +#ifndef __ASM_ARCH_MFP_PXA2XX_H +#define __ASM_ARCH_MFP_PXA2XX_H + +#include + +/* + * the following MFP_xxx bit definitions in mfp.h are re-used for pxa2xx: + * + * MFP_PIN(x) + * MFP_AFx + * MFP_LPM_DRIVE_{LOW, HIGH} + * MFP_LPM_EDGE_x + * + * other MFP_x bit definitions will be ignored + * + * and adds the below two bits specifically for pxa2xx: + * + * bit 23 - Input/Output (PXA2xx specific) + * bit 24 - Wakeup Enable(PXA2xx specific) + */ + +#define MFP_DIR_IN (0x0 << 23) +#define MFP_DIR_OUT (0x1 << 23) +#define MFP_DIR_MASK (0x1 << 23) +#define MFP_DIR(x) (((x) >> 23) & 0x1) + +#define MFP_LPM_CAN_WAKEUP (0x1 << 24) +#define WAKEUP_ON_EDGE_RISE (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_RISE) +#define WAKEUP_ON_EDGE_FALL (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_FALL) +#define WAKEUP_ON_EDGE_BOTH (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_BOTH) + +/* specifically for enabling wakeup on keypad GPIOs */ +#define WAKEUP_ON_LEVEL_HIGH (MFP_LPM_CAN_WAKEUP) + +#define MFP_CFG_IN(pin, af) \ + ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DIR_MASK)) |\ + (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_DIR_IN)) + +/* NOTE: pins configured as output _must_ provide a low power state, + * and this state should help to minimize the power dissipation. + */ +#define MFP_CFG_OUT(pin, af, state) \ + ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DIR_MASK | MFP_LPM_STATE_MASK)) |\ + (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_DIR_OUT | MFP_LPM_##state)) + +/* Common configurations for pxa25x and pxa27x + * + * Note: pins configured as GPIO are always initialized to input + * so not to cause any side effect + */ +#define GPIO0_GPIO MFP_CFG_IN(GPIO0, AF0) +#define GPIO1_GPIO MFP_CFG_IN(GPIO1, AF0) +#define GPIO9_GPIO MFP_CFG_IN(GPIO9, AF0) +#define GPIO10_GPIO MFP_CFG_IN(GPIO10, AF0) +#define GPIO11_GPIO MFP_CFG_IN(GPIO11, AF0) +#define GPIO12_GPIO MFP_CFG_IN(GPIO12, AF0) +#define GPIO13_GPIO MFP_CFG_IN(GPIO13, AF0) +#define GPIO14_GPIO MFP_CFG_IN(GPIO14, AF0) +#define GPIO15_GPIO MFP_CFG_IN(GPIO15, AF0) +#define GPIO16_GPIO MFP_CFG_IN(GPIO16, AF0) +#define GPIO17_GPIO MFP_CFG_IN(GPIO17, AF0) +#define GPIO18_GPIO MFP_CFG_IN(GPIO18, AF0) +#define GPIO19_GPIO MFP_CFG_IN(GPIO19, AF0) +#define GPIO20_GPIO MFP_CFG_IN(GPIO20, AF0) +#define GPIO21_GPIO MFP_CFG_IN(GPIO21, AF0) +#define GPIO22_GPIO MFP_CFG_IN(GPIO22, AF0) +#define GPIO23_GPIO MFP_CFG_IN(GPIO23, AF0) +#define GPIO24_GPIO MFP_CFG_IN(GPIO24, AF0) +#define GPIO25_GPIO MFP_CFG_IN(GPIO25, AF0) +#define GPIO26_GPIO MFP_CFG_IN(GPIO26, AF0) +#define GPIO27_GPIO MFP_CFG_IN(GPIO27, AF0) +#define GPIO28_GPIO MFP_CFG_IN(GPIO28, AF0) +#define GPIO29_GPIO MFP_CFG_IN(GPIO29, AF0) +#define GPIO30_GPIO MFP_CFG_IN(GPIO30, AF0) +#define GPIO31_GPIO MFP_CFG_IN(GPIO31, AF0) +#define GPIO32_GPIO MFP_CFG_IN(GPIO32, AF0) +#define GPIO33_GPIO MFP_CFG_IN(GPIO33, AF0) +#define GPIO34_GPIO MFP_CFG_IN(GPIO34, AF0) +#define GPIO35_GPIO MFP_CFG_IN(GPIO35, AF0) +#define GPIO36_GPIO MFP_CFG_IN(GPIO36, AF0) +#define GPIO37_GPIO MFP_CFG_IN(GPIO37, AF0) +#define GPIO38_GPIO MFP_CFG_IN(GPIO38, AF0) +#define GPIO39_GPIO MFP_CFG_IN(GPIO39, AF0) +#define GPIO40_GPIO MFP_CFG_IN(GPIO40, AF0) +#define GPIO41_GPIO MFP_CFG_IN(GPIO41, AF0) +#define GPIO42_GPIO MFP_CFG_IN(GPIO42, AF0) +#define GPIO43_GPIO MFP_CFG_IN(GPIO43, AF0) +#define GPIO44_GPIO MFP_CFG_IN(GPIO44, AF0) +#define GPIO45_GPIO MFP_CFG_IN(GPIO45, AF0) +#define GPIO46_GPIO MFP_CFG_IN(GPIO46, AF0) +#define GPIO47_GPIO MFP_CFG_IN(GPIO47, AF0) +#define GPIO48_GPIO MFP_CFG_IN(GPIO48, AF0) +#define GPIO49_GPIO MFP_CFG_IN(GPIO49, AF0) +#define GPIO50_GPIO MFP_CFG_IN(GPIO50, AF0) +#define GPIO51_GPIO MFP_CFG_IN(GPIO51, AF0) +#define GPIO52_GPIO MFP_CFG_IN(GPIO52, AF0) +#define GPIO53_GPIO MFP_CFG_IN(GPIO53, AF0) +#define GPIO54_GPIO MFP_CFG_IN(GPIO54, AF0) +#define GPIO55_GPIO MFP_CFG_IN(GPIO55, AF0) +#define GPIO56_GPIO MFP_CFG_IN(GPIO56, AF0) +#define GPIO57_GPIO MFP_CFG_IN(GPIO57, AF0) +#define GPIO58_GPIO MFP_CFG_IN(GPIO58, AF0) +#define GPIO59_GPIO MFP_CFG_IN(GPIO59, AF0) +#define GPIO60_GPIO MFP_CFG_IN(GPIO60, AF0) +#define GPIO61_GPIO MFP_CFG_IN(GPIO61, AF0) +#define GPIO62_GPIO MFP_CFG_IN(GPIO62, AF0) +#define GPIO63_GPIO MFP_CFG_IN(GPIO63, AF0) +#define GPIO64_GPIO MFP_CFG_IN(GPIO64, AF0) +#define GPIO65_GPIO MFP_CFG_IN(GPIO65, AF0) +#define GPIO66_GPIO MFP_CFG_IN(GPIO66, AF0) +#define GPIO67_GPIO MFP_CFG_IN(GPIO67, AF0) +#define GPIO68_GPIO MFP_CFG_IN(GPIO68, AF0) +#define GPIO69_GPIO MFP_CFG_IN(GPIO69, AF0) +#define GPIO70_GPIO MFP_CFG_IN(GPIO70, AF0) +#define GPIO71_GPIO MFP_CFG_IN(GPIO71, AF0) +#define GPIO72_GPIO MFP_CFG_IN(GPIO72, AF0) +#define GPIO73_GPIO MFP_CFG_IN(GPIO73, AF0) +#define GPIO74_GPIO MFP_CFG_IN(GPIO74, AF0) +#define GPIO75_GPIO MFP_CFG_IN(GPIO75, AF0) +#define GPIO76_GPIO MFP_CFG_IN(GPIO76, AF0) +#define GPIO77_GPIO MFP_CFG_IN(GPIO77, AF0) +#define GPIO78_GPIO MFP_CFG_IN(GPIO78, AF0) +#define GPIO79_GPIO MFP_CFG_IN(GPIO79, AF0) +#define GPIO80_GPIO MFP_CFG_IN(GPIO80, AF0) +#define GPIO81_GPIO MFP_CFG_IN(GPIO81, AF0) +#define GPIO82_GPIO MFP_CFG_IN(GPIO82, AF0) +#define GPIO83_GPIO MFP_CFG_IN(GPIO83, AF0) +#define GPIO84_GPIO MFP_CFG_IN(GPIO84, AF0) + +extern void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num); +extern void pxa2xx_mfp_set_lpm(int mfp, unsigned long lpm); +extern int gpio_set_wake(unsigned int gpio, unsigned int on); +#endif /* __ASM_ARCH_MFP_PXA2XX_H */ diff --git a/arch/arm/mach-pxa/include/mach/mfp.h b/arch/arm/mach-pxa/include/mach/mfp.h new file mode 100644 index 0000000000..271e249ae3 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/mfp.h @@ -0,0 +1,21 @@ +/* + * arch/arm/mach-pxa/include/mach/mfp.h + * + * Multi-Function Pin Definitions + * + * Copyright (C) 2007 Marvell International Ltd. + * + * 2007-8-21: eric miao + * initial version + * + * 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_ARCH_MFP_H +#define __ASM_ARCH_MFP_H + +#include + +#endif /* __ASM_ARCH_MFP_H */ diff --git a/arch/arm/mach-pxa/include/mach/pxa-regs.h b/arch/arm/mach-pxa/include/mach/pxa-regs.h new file mode 100644 index 0000000000..c32d2ae704 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/pxa-regs.h @@ -0,0 +1,33 @@ +/* + * (c) 2010 by Marc Kleine-Budde + * + * Copyright (C) 2010 by Marc Kleine-Budde + * + * This file is released under the GPLv2 + * + */ + +#ifndef __MACH_PXA_REGS_H +#define __MACH_PXA_REGS_H + +#ifndef __ASSEMBLY__ +# define __REG(x) (*((volatile u32 *)(x))) +# define __REG16(x) (*(volatile u16 *)(x)) +# define __REG2(x, y) (*(volatile u32 *)((u32)&__REG(x) + (y))) +#else +# define __REG(x) (x) +# define __REG16(x) (x) +# define __REG2(x, y) ((x) + (y)) +#endif + +#ifdef CONFIG_ARCH_PXA2XX +# include +#endif + +#ifdef CONFIG_ARCH_PXA27X +# include +#else +# error "unknown PXA soc type" +#endif + +#endif /* !__MACH_PXA_REGS_H */ diff --git a/arch/arm/mach-pxa/include/mach/pxa27x-regs.h b/arch/arm/mach-pxa/include/mach/pxa27x-regs.h new file mode 100644 index 0000000000..f4d88d47ab --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/pxa27x-regs.h @@ -0,0 +1,6 @@ +#ifndef __MACH_PXA27X_REGS +#define __MACH_PXA27X_REGS + +/* this file intentionally left blank */ + +#endif /* !__MACH_PXA27X_REGS */ diff --git a/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h b/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h new file mode 100644 index 0000000000..4762d8a71e --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h @@ -0,0 +1,267 @@ +/* + * arch/arm/mach-pxa/include/mach/pxa2xx-regs.h + * + * Taken from pxa-regs.h by Russell King + * + * Author: Nicolas Pitre + * Copyright: MontaVista Software 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 __PXA2XX_REGS_H +#define __PXA2XX_REGS_H + +#include + +/* + * PXA Chip selects + */ +#define PXA_CS0_PHYS 0x00000000 +#define PXA_CS1_PHYS 0x04000000 +#define PXA_CS2_PHYS 0x08000000 +#define PXA_CS3_PHYS 0x0C000000 +#define PXA_CS4_PHYS 0x10000000 +#define PXA_CS5_PHYS 0x14000000 + +/* + * Memory controller + */ +#define MDCNFG_OFFSET 0x00000000 +#define MDREFR_OFFSET 0x00000004 +#define MSC0_OFFSET 0x00000008 +#define MSC1_OFFSET 0x0000000C +#define MSC2_OFFSET 0x00000010 +#define MECR_OFFSET 0x00000014 +#define SXCNFG_OFFSET 0x0000001C +#define FLYCNFG_OFFSET 0x00000020 +#define MCMEM0_OFFSET 0x00000028 +#define MCMEM1_OFFSET 0x0000002C +#define MCATT0_OFFSET 0x00000030 +#define MCATT1_OFFSET 0x00000034 +#define MCIO0_OFFSET 0x00000038 +#define MCIO1_OFFSET 0x0000003C +#define MDMRS_OFFSET 0x00000040 + +#define MDCNFG __REG(0x48000000) /* SDRAM Configuration Register 0 */ +#define MDREFR __REG(0x48000004) /* SDRAM Refresh Control Register */ +#define MSC0 __REG(0x48000008) /* Static Memory Control Register 0 */ +#define MSC1 __REG(0x4800000C) /* Static Memory Control Register 1 */ +#define MSC2 __REG(0x48000010) /* Static Memory Control Register 2 */ +#define MECR __REG(0x48000014) /* Expansion Memory (PCMCIA/Compact Flash) Bus Configuration */ +#define SXLCR __REG(0x48000018) /* LCR value to be written to SDRAM-Timing Synchronous Flash */ +#define SXCNFG __REG(0x4800001C) /* Synchronous Static Memory Control Register */ +#define SXMRS __REG(0x48000024) /* MRS value to be written to Synchronous Flash or SMROM */ +#define MCMEM0 __REG(0x48000028) /* Card interface Common Memory Space Socket 0 Timing */ +#define MCMEM1 __REG(0x4800002C) /* Card interface Common Memory Space Socket 1 Timing */ +#define MCATT0 __REG(0x48000030) /* Card interface Attribute Space Socket 0 Timing Configuration */ +#define MCATT1 __REG(0x48000034) /* Card interface Attribute Space Socket 1 Timing Configuration */ +#define MCIO0 __REG(0x48000038) /* Card interface I/O Space Socket 0 Timing Configuration */ +#define MCIO1 __REG(0x4800003C) /* Card interface I/O Space Socket 1 Timing Configuration */ +#define MDMRS __REG(0x48000040) /* MRS value to be written to SDRAM */ +#define BOOT_DEF __REG(0x48000044) /* Read-Only Boot-Time Register. Contains BOOT_SEL and PKG_SEL */ + +/* + * More handy macros for PCMCIA + * + * Arg is socket number + */ +#define MCMEM(s) __REG2(0x48000028, (s)<<2 ) /* Card interface Common Memory Space Socket s Timing */ +#define MCATT(s) __REG2(0x48000030, (s)<<2 ) /* Card interface Attribute Space Socket s Timing Configuration */ +#define MCIO(s) __REG2(0x48000038, (s)<<2 ) /* Card interface I/O Space Socket s Timing Configuration */ + +/* MECR register defines */ +#define MECR_NOS (1 << 0) /* Number Of Sockets: 0 -> 1 sock, 1 -> 2 sock */ +#define MECR_CIT (1 << 1) /* Card Is There: 0 -> no card, 1 -> card inserted */ + +#define MDCNFG_DE0 (1 << 0) /* SDRAM Bank 0 Enable */ +#define MDCNFG_DE1 (1 << 1) /* SDRAM Bank 1 Enable */ +#define MDCNFG_DE2 (1 << 16) /* SDRAM Bank 2 Enable */ +#define MDCNFG_DE3 (1 << 17) /* SDRAM Bank 3 Enable */ + +#define MDREFR_K0DB4 (1 << 29) /* SDCLK0 Divide by 4 Control/Status */ +#define MDREFR_K2FREE (1 << 25) /* SDRAM Free-Running Control */ +#define MDREFR_K1FREE (1 << 24) /* SDRAM Free-Running Control */ +#define MDREFR_K0FREE (1 << 23) /* SDRAM Free-Running Control */ +#define MDREFR_SLFRSH (1 << 22) /* SDRAM Self-Refresh Control/Status */ +#define MDREFR_APD (1 << 20) /* SDRAM/SSRAM Auto-Power-Down Enable */ +#define MDREFR_K2DB2 (1 << 19) /* SDCLK2 Divide by 2 Control/Status */ +#define MDREFR_K2RUN (1 << 18) /* SDCLK2 Run Control/Status */ +#define MDREFR_K1DB2 (1 << 17) /* SDCLK1 Divide by 2 Control/Status */ +#define MDREFR_K1RUN (1 << 16) /* SDCLK1 Run Control/Status */ +#define MDREFR_E1PIN (1 << 15) /* SDCKE1 Level Control/Status */ +#define MDREFR_K0DB2 (1 << 14) /* SDCLK0 Divide by 2 Control/Status */ +#define MDREFR_K0RUN (1 << 13) /* SDCLK0 Run Control/Status */ +#define MDREFR_E0PIN (1 << 12) /* SDCKE0 Level Control/Status */ + +/* + * Power Manager + */ + +#define PMCR __REG(0x40F00000) /* Power Manager Control Register */ +#define PSSR __REG(0x40F00004) /* Power Manager Sleep Status Register */ +#define PSPR __REG(0x40F00008) /* Power Manager Scratch Pad Register */ +#define PWER __REG(0x40F0000C) /* Power Manager Wake-up Enable Register */ +#define PRER __REG(0x40F00010) /* Power Manager GPIO Rising-Edge Detect Enable Register */ +#define PFER __REG(0x40F00014) /* Power Manager GPIO Falling-Edge Detect Enable Register */ +#define PEDR __REG(0x40F00018) /* Power Manager GPIO Edge Detect Status Register */ +#define PCFR __REG(0x40F0001C) /* Power Manager General Configuration Register */ +#define PGSR0 __REG(0x40F00020) /* Power Manager GPIO Sleep State Register for GP[31-0] */ +#define PGSR1 __REG(0x40F00024) /* Power Manager GPIO Sleep State Register for GP[63-32] */ +#define PGSR2 __REG(0x40F00028) /* Power Manager GPIO Sleep State Register for GP[84-64] */ +#define PGSR3 __REG(0x40F0002C) /* Power Manager GPIO Sleep State Register for GP[118-96] */ +#define RCSR __REG(0x40F00030) /* Reset Controller Status Register */ + +#define PSLR __REG(0x40F00034) /* Power Manager Sleep Config Register */ +#define PSTR __REG(0x40F00038) /* Power Manager Standby Config Register */ +#define PSNR __REG(0x40F0003C) /* Power Manager Sense Config Register */ +#define PVCR __REG(0x40F00040) /* Power Manager VoltageControl Register */ +#define PKWR __REG(0x40F00050) /* Power Manager KB Wake-up Enable Reg */ +#define PKSR __REG(0x40F00054) /* Power Manager KB Level-Detect Register */ +#define PCMD(x) __REG2(0x40F00080, (x)<<2) +#define PCMD0 __REG(0x40F00080 + 0 * 4) +#define PCMD1 __REG(0x40F00080 + 1 * 4) +#define PCMD2 __REG(0x40F00080 + 2 * 4) +#define PCMD3 __REG(0x40F00080 + 3 * 4) +#define PCMD4 __REG(0x40F00080 + 4 * 4) +#define PCMD5 __REG(0x40F00080 + 5 * 4) +#define PCMD6 __REG(0x40F00080 + 6 * 4) +#define PCMD7 __REG(0x40F00080 + 7 * 4) +#define PCMD8 __REG(0x40F00080 + 8 * 4) +#define PCMD9 __REG(0x40F00080 + 9 * 4) +#define PCMD10 __REG(0x40F00080 + 10 * 4) +#define PCMD11 __REG(0x40F00080 + 11 * 4) +#define PCMD12 __REG(0x40F00080 + 12 * 4) +#define PCMD13 __REG(0x40F00080 + 13 * 4) +#define PCMD14 __REG(0x40F00080 + 14 * 4) +#define PCMD15 __REG(0x40F00080 + 15 * 4) +#define PCMD16 __REG(0x40F00080 + 16 * 4) +#define PCMD17 __REG(0x40F00080 + 17 * 4) +#define PCMD18 __REG(0x40F00080 + 18 * 4) +#define PCMD19 __REG(0x40F00080 + 19 * 4) +#define PCMD20 __REG(0x40F00080 + 20 * 4) +#define PCMD21 __REG(0x40F00080 + 21 * 4) +#define PCMD22 __REG(0x40F00080 + 22 * 4) +#define PCMD23 __REG(0x40F00080 + 23 * 4) +#define PCMD24 __REG(0x40F00080 + 24 * 4) +#define PCMD25 __REG(0x40F00080 + 25 * 4) +#define PCMD26 __REG(0x40F00080 + 26 * 4) +#define PCMD27 __REG(0x40F00080 + 27 * 4) +#define PCMD28 __REG(0x40F00080 + 28 * 4) +#define PCMD29 __REG(0x40F00080 + 29 * 4) +#define PCMD30 __REG(0x40F00080 + 30 * 4) +#define PCMD31 __REG(0x40F00080 + 31 * 4) + +#define PCMD_MBC (1<<12) +#define PCMD_DCE (1<<11) +#define PCMD_LC (1<<10) +/* FIXME: PCMD_SQC need be checked. */ +#define PCMD_SQC (3<<8) /* currently only bit 8 is changeable, + bit 9 should be 0 all day. */ +#define PVCR_VCSA (0x1<<14) +#define PVCR_CommandDelay (0xf80) +#define PCFR_PI2C_EN (0x1 << 6) + +#define PSSR_OTGPH (1 << 6) /* OTG Peripheral control Hold */ +#define PSSR_RDH (1 << 5) /* Read Disable Hold */ +#define PSSR_PH (1 << 4) /* Peripheral Control Hold */ +#define PSSR_STS (1 << 3) /* Standby Mode Status */ +#define PSSR_VFS (1 << 2) /* VDD Fault Status */ +#define PSSR_BFS (1 << 1) /* Battery Fault Status */ +#define PSSR_SSS (1 << 0) /* Software Sleep Status */ + +#define PSLR_SL_ROD (1 << 20) /* Sleep-Mode/Depp-Sleep Mode nRESET_OUT Disable */ + +#define PCFR_RO (1 << 15) /* RDH Override */ +#define PCFR_PO (1 << 14) /* PH Override */ +#define PCFR_GPROD (1 << 12) /* GPIO nRESET_OUT Disable */ +#define PCFR_L1_EN (1 << 11) /* Sleep Mode L1 converter Enable */ +#define PCFR_FVC (1 << 10) /* Frequency/Voltage Change */ +#define PCFR_DC_EN (1 << 7) /* Sleep/deep-sleep DC-DC Converter Enable */ +#define PCFR_PI2CEN (1 << 6) /* Enable PI2C controller */ +#define PCFR_GPR_EN (1 << 4) /* nRESET_GPIO Pin Enable */ +#define PCFR_DS (1 << 3) /* Deep Sleep Mode */ +#define PCFR_FS (1 << 2) /* Float Static Chip Selects */ +#define PCFR_FP (1 << 1) /* Float PCMCIA controls */ +#define PCFR_OPDE (1 << 0) /* 3.6864 MHz oscillator power-down enable */ + +#define RCSR_GPR (1 << 3) /* GPIO Reset */ +#define RCSR_SMR (1 << 2) /* Sleep Mode */ +#define RCSR_WDR (1 << 1) /* Watchdog Reset */ +#define RCSR_HWR (1 << 0) /* Hardware Reset */ + +#define PWER_GPIO(Nb) (1 << Nb) /* GPIO [0..15] wake-up enable */ +#define PWER_GPIO0 PWER_GPIO(0) /* GPIO [0] wake-up enable */ +#define PWER_GPIO1 PWER_GPIO(1) /* GPIO [1] wake-up enable */ +#define PWER_GPIO2 PWER_GPIO(2) /* GPIO [2] wake-up enable */ +#define PWER_GPIO3 PWER_GPIO(3) /* GPIO [3] wake-up enable */ +#define PWER_GPIO4 PWER_GPIO(4) /* GPIO [4] wake-up enable */ +#define PWER_GPIO5 PWER_GPIO(5) /* GPIO [5] wake-up enable */ +#define PWER_GPIO6 PWER_GPIO(6) /* GPIO [6] wake-up enable */ +#define PWER_GPIO7 PWER_GPIO(7) /* GPIO [7] wake-up enable */ +#define PWER_GPIO8 PWER_GPIO(8) /* GPIO [8] wake-up enable */ +#define PWER_GPIO9 PWER_GPIO(9) /* GPIO [9] wake-up enable */ +#define PWER_GPIO10 PWER_GPIO(10) /* GPIO [10] wake-up enable */ +#define PWER_GPIO11 PWER_GPIO(11) /* GPIO [11] wake-up enable */ +#define PWER_GPIO12 PWER_GPIO(12) /* GPIO [12] wake-up enable */ +#define PWER_GPIO13 PWER_GPIO(13) /* GPIO [13] wake-up enable */ +#define PWER_GPIO14 PWER_GPIO(14) /* GPIO [14] wake-up enable */ +#define PWER_GPIO15 PWER_GPIO(15) /* GPIO [15] wake-up enable */ +#define PWER_RTC 0x80000000 /* RTC alarm wake-up enable */ + +/* + * PXA2xx specific Core clock definitions + */ +#define CCCR __REG(0x41300000) /* Core Clock Configuration Register */ +#define CCSR __REG(0x4130000C) /* Core Clock Status Register */ +#define CKEN __REG(0x41300004) /* Clock Enable Register */ +#define OSCC __REG(0x41300008) /* Oscillator Configuration Register */ + +#define CCCR_N_MASK 0x0380 /* Run Mode Frequency to Turbo Mode Frequency Multiplier */ +#define CCCR_M_MASK 0x0060 /* Memory Frequency to Run Mode Frequency Multiplier */ +#define CCCR_L_MASK 0x001f /* Crystal Frequency to Memory Frequency Multiplier */ + +#define CKEN_AC97CONF (1 << 31) /* AC97 Controller Configuration */ +#define CKEN_CAMERA (1 << 24) /* Camera Interface Clock Enable */ +#define CKEN_SSP1 (1 << 23) /* SSP1 Unit Clock Enable */ +#define CKEN_MEMC (1 << 22) /* Memory Controller Clock Enable */ +#define CKEN_MEMSTK (1 << 21) /* Memory Stick Host Controller */ +#define CKEN_IM (1 << 20) /* Internal Memory Clock Enable */ +#define CKEN_KEYPAD (1 << 19) /* Keypad Interface Clock Enable */ +#define CKEN_USIM (1 << 18) /* USIM Unit Clock Enable */ +#define CKEN_MSL (1 << 17) /* MSL Unit Clock Enable */ +#define CKEN_LCD (1 << 16) /* LCD Unit Clock Enable */ +#define CKEN_PWRI2C (1 << 15) /* PWR I2C Unit Clock Enable */ +#define CKEN_I2C (1 << 14) /* I2C Unit Clock Enable */ +#define CKEN_FICP (1 << 13) /* FICP Unit Clock Enable */ +#define CKEN_MMC (1 << 12) /* MMC Unit Clock Enable */ +#define CKEN_USB (1 << 11) /* USB Unit Clock Enable */ +#define CKEN_ASSP (1 << 10) /* ASSP (1 << SSP3) Clock Enable */ +#define CKEN_USBHOST (1 << 10) /* USB Host Unit Clock Enable */ +#define CKEN_OSTIMER (1 << 9) /* OS Timer Unit Clock Enable */ +#define CKEN_NSSP (1 << 9) /* NSSP (1 << SSP2) Clock Enable */ +#define CKEN_I2S (1 << 8) /* I2S Unit Clock Enable */ +#define CKEN_BTUART (1 << 7) /* BTUART Unit Clock Enable */ +#define CKEN_FFUART (1 << 6) /* FFUART Unit Clock Enable */ +#define CKEN_STUART (1 << 5) /* STUART Unit Clock Enable */ +#define CKEN_HWUART (1 << 4) /* HWUART Unit Clock Enable */ +#define CKEN_SSP3 (1 << 4) /* SSP3 Unit Clock Enable */ +#define CKEN_SSP (1 << 3) /* SSP Unit Clock Enable */ +#define CKEN_SSP2 (1 << 3) /* SSP2 Unit Clock Enable */ +#define CKEN_AC97 (1 << 2) /* AC97 Unit Clock Enable */ +#define CKEN_PWM1 (1 << 1) /* PWM1 Clock Enable */ +#define CKEN_PWM0 (1 << 0) /* PWM0 Clock Enable */ + +#define OSCC_OON (1 << 1) /* 32.768kHz OON (write-once only bit) */ +#define OSCC_OOK (1 << 0) /* 32.768kHz OOK (read-only bit) */ + +/* PWRMODE register M field values */ + +#define PWRMODE_IDLE 0x1 +#define PWRMODE_STANDBY 0x2 +#define PWRMODE_SLEEP 0x3 +#define PWRMODE_DEEPSLEEP 0x7 + +#endif diff --git a/arch/arm/mach-pxa/include/mach/regs-intc.h b/arch/arm/mach-pxa/include/mach/regs-intc.h new file mode 100644 index 0000000000..68464ce1c1 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/regs-intc.h @@ -0,0 +1,34 @@ +#ifndef __ASM_MACH_REGS_INTC_H +#define __ASM_MACH_REGS_INTC_H + +#include + +/* + * Interrupt Controller + */ + +#define ICIP __REG(0x40D00000) /* Interrupt Controller IRQ Pending Register */ +#define ICMR __REG(0x40D00004) /* Interrupt Controller Mask Register */ +#define ICLR __REG(0x40D00008) /* Interrupt Controller Level Register */ +#define ICFP __REG(0x40D0000C) /* Interrupt Controller FIQ Pending Register */ +#define ICPR __REG(0x40D00010) /* Interrupt Controller Pending Register */ +#define ICCR __REG(0x40D00014) /* Interrupt Controller Control Register */ +#define ICHP __REG(0x40D00018) /* Interrupt Controller Highest Priority Register */ + +#define ICIP2 __REG(0x40D0009C) /* Interrupt Controller IRQ Pending Register 2 */ +#define ICMR2 __REG(0x40D000A0) /* Interrupt Controller Mask Register 2 */ +#define ICLR2 __REG(0x40D000A4) /* Interrupt Controller Level Register 2 */ +#define ICFP2 __REG(0x40D000A8) /* Interrupt Controller FIQ Pending Register 2 */ +#define ICPR2 __REG(0x40D000AC) /* Interrupt Controller Pending Register 2 */ + +#define ICIP3 __REG(0x40D00130) /* Interrupt Controller IRQ Pending Register 3 */ +#define ICMR3 __REG(0x40D00134) /* Interrupt Controller Mask Register 3 */ +#define ICLR3 __REG(0x40D00138) /* Interrupt Controller Level Register 3 */ +#define ICFP3 __REG(0x40D0013C) /* Interrupt Controller FIQ Pending Register 3 */ +#define ICPR3 __REG(0x40D00140) /* Interrupt Controller Pending Register 3 */ + +#define IPR(x) __REG(0x40D0001C + (x < 32 ? (x << 2) \ + : (x < 64 ? (0x94 + ((x - 32) << 2)) \ + : (0x128 + ((x - 64) << 2))))) + +#endif /* __ASM_MACH_REGS_INTC_H */ diff --git a/arch/arm/mach-pxa/include/mach/regs-ost.h b/arch/arm/mach-pxa/include/mach/regs-ost.h new file mode 100644 index 0000000000..a3e5f86ef6 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/regs-ost.h @@ -0,0 +1,34 @@ +#ifndef __ASM_MACH_REGS_OST_H +#define __ASM_MACH_REGS_OST_H + +#include + +/* + * OS Timer & Match Registers + */ + +#define OSMR0 __REG(0x40A00000) /* */ +#define OSMR1 __REG(0x40A00004) /* */ +#define OSMR2 __REG(0x40A00008) /* */ +#define OSMR3 __REG(0x40A0000C) /* */ +#define OSMR4 __REG(0x40A00080) /* */ +#define OSCR __REG(0x40A00010) /* OS Timer Counter Register */ +#define OSCR4 __REG(0x40A00040) /* OS Timer Counter Register */ +#define OMCR4 __REG(0x40A000C0) /* */ +#define OSSR __REG(0x40A00014) /* OS Timer Status Register */ +#define OWER __REG(0x40A00018) /* OS Timer Watchdog Enable Register */ +#define OIER __REG(0x40A0001C) /* OS Timer Interrupt Enable Register */ + +#define OSSR_M3 (1 << 3) /* Match status channel 3 */ +#define OSSR_M2 (1 << 2) /* Match status channel 2 */ +#define OSSR_M1 (1 << 1) /* Match status channel 1 */ +#define OSSR_M0 (1 << 0) /* Match status channel 0 */ + +#define OWER_WME (1 << 0) /* Watchdog Match Enable */ + +#define OIER_E3 (1 << 3) /* Interrupt enable channel 3 */ +#define OIER_E2 (1 << 2) /* Interrupt enable channel 2 */ +#define OIER_E1 (1 << 1) /* Interrupt enable channel 1 */ +#define OIER_E0 (1 << 0) /* Interrupt enable channel 0 */ + +#endif /* __ASM_MACH_REGS_OST_H */ diff --git a/arch/arm/mach-pxa/include/plat/gpio.h b/arch/arm/mach-pxa/include/plat/gpio.h new file mode 100644 index 0000000000..4c7b5266fb --- /dev/null +++ b/arch/arm/mach-pxa/include/plat/gpio.h @@ -0,0 +1,74 @@ +#ifndef __PLAT_GPIO_H +#define __PLAT_GPIO_H + +#include + +/* + * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with + * one set of registers. The register offsets are organized below: + * + * GPLR GPDR GPSR GPCR GRER GFER GEDR + * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048 + * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C + * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050 + * + * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148 + * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C + * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150 + * + * NOTE: + * BANK 3 is only available on PXA27x and later processors. + * BANK 4 and 5 are only available on PXA935 + */ + +#define GPIO_BANK(n) (GPIO_REGS_VIRT + BANK_OFF(n)) + +#define GPLR_OFFSET 0x00 +#define GPDR_OFFSET 0x0C +#define GPSR_OFFSET 0x18 +#define GPCR_OFFSET 0x24 +#define GRER_OFFSET 0x30 +#define GFER_OFFSET 0x3C +#define GEDR_OFFSET 0x48 + +static inline int gpio_get_value(unsigned gpio) +{ + return GPLR(gpio) & GPIO_bit(gpio); +} + +static inline void gpio_set_value(unsigned gpio, int value) +{ + if (value) + GPSR(gpio) = GPIO_bit(gpio); + else + GPCR(gpio) = GPIO_bit(gpio); +} + +static inline int gpio_direction_input(unsigned gpio) +{ + if (__gpio_is_inverted(gpio)) + GPDR(gpio) |= GPIO_bit(gpio); + else + GPDR(gpio) &= ~GPIO_bit(gpio); + return 0; +} + +static inline int gpio_direction_output(unsigned gpio, int value) +{ + gpio_set_value(gpio, value); + if (__gpio_is_inverted(gpio)) + GPDR(gpio) &= ~GPIO_bit(gpio); + else + GPDR(gpio) |= GPIO_bit(gpio); + return 0; +} + +/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85). + * Those cases currently cause holes in the GPIO number space, the + * actual number of the last GPIO is recorded by 'pxa_last_gpio'. + */ +extern int pxa_last_gpio; + +extern int pxa_init_gpio(int start, int end); + +#endif /* __PLAT_GPIO_H */ diff --git a/arch/arm/mach-pxa/include/plat/mfp.h b/arch/arm/mach-pxa/include/plat/mfp.h new file mode 100644 index 0000000000..755b02062b --- /dev/null +++ b/arch/arm/mach-pxa/include/plat/mfp.h @@ -0,0 +1,468 @@ +/* + * arch/arm/plat-pxa/include/plat/mfp.h + * + * Common Multi-Function Pin Definitions + * + * Copyright (C) 2007 Marvell International Ltd. + * + * 2007-8-21: eric miao + * initial version + * + * 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_PLAT_MFP_H +#define __ASM_PLAT_MFP_H + +#define mfp_to_gpio(m) ((m) % 256) + +/* list of all the configurable MFP pins */ +enum { + MFP_PIN_INVALID = -1, + + MFP_PIN_GPIO0 = 0, + MFP_PIN_GPIO1, + MFP_PIN_GPIO2, + MFP_PIN_GPIO3, + MFP_PIN_GPIO4, + MFP_PIN_GPIO5, + MFP_PIN_GPIO6, + MFP_PIN_GPIO7, + MFP_PIN_GPIO8, + MFP_PIN_GPIO9, + MFP_PIN_GPIO10, + MFP_PIN_GPIO11, + MFP_PIN_GPIO12, + MFP_PIN_GPIO13, + MFP_PIN_GPIO14, + MFP_PIN_GPIO15, + MFP_PIN_GPIO16, + MFP_PIN_GPIO17, + MFP_PIN_GPIO18, + MFP_PIN_GPIO19, + MFP_PIN_GPIO20, + MFP_PIN_GPIO21, + MFP_PIN_GPIO22, + MFP_PIN_GPIO23, + MFP_PIN_GPIO24, + MFP_PIN_GPIO25, + MFP_PIN_GPIO26, + MFP_PIN_GPIO27, + MFP_PIN_GPIO28, + MFP_PIN_GPIO29, + MFP_PIN_GPIO30, + MFP_PIN_GPIO31, + MFP_PIN_GPIO32, + MFP_PIN_GPIO33, + MFP_PIN_GPIO34, + MFP_PIN_GPIO35, + MFP_PIN_GPIO36, + MFP_PIN_GPIO37, + MFP_PIN_GPIO38, + MFP_PIN_GPIO39, + MFP_PIN_GPIO40, + MFP_PIN_GPIO41, + MFP_PIN_GPIO42, + MFP_PIN_GPIO43, + MFP_PIN_GPIO44, + MFP_PIN_GPIO45, + MFP_PIN_GPIO46, + MFP_PIN_GPIO47, + MFP_PIN_GPIO48, + MFP_PIN_GPIO49, + MFP_PIN_GPIO50, + MFP_PIN_GPIO51, + MFP_PIN_GPIO52, + MFP_PIN_GPIO53, + MFP_PIN_GPIO54, + MFP_PIN_GPIO55, + MFP_PIN_GPIO56, + MFP_PIN_GPIO57, + MFP_PIN_GPIO58, + MFP_PIN_GPIO59, + MFP_PIN_GPIO60, + MFP_PIN_GPIO61, + MFP_PIN_GPIO62, + MFP_PIN_GPIO63, + MFP_PIN_GPIO64, + MFP_PIN_GPIO65, + MFP_PIN_GPIO66, + MFP_PIN_GPIO67, + MFP_PIN_GPIO68, + MFP_PIN_GPIO69, + MFP_PIN_GPIO70, + MFP_PIN_GPIO71, + MFP_PIN_GPIO72, + MFP_PIN_GPIO73, + MFP_PIN_GPIO74, + MFP_PIN_GPIO75, + MFP_PIN_GPIO76, + MFP_PIN_GPIO77, + MFP_PIN_GPIO78, + MFP_PIN_GPIO79, + MFP_PIN_GPIO80, + MFP_PIN_GPIO81, + MFP_PIN_GPIO82, + MFP_PIN_GPIO83, + MFP_PIN_GPIO84, + MFP_PIN_GPIO85, + MFP_PIN_GPIO86, + MFP_PIN_GPIO87, + MFP_PIN_GPIO88, + MFP_PIN_GPIO89, + MFP_PIN_GPIO90, + MFP_PIN_GPIO91, + MFP_PIN_GPIO92, + MFP_PIN_GPIO93, + MFP_PIN_GPIO94, + MFP_PIN_GPIO95, + MFP_PIN_GPIO96, + MFP_PIN_GPIO97, + MFP_PIN_GPIO98, + MFP_PIN_GPIO99, + MFP_PIN_GPIO100, + MFP_PIN_GPIO101, + MFP_PIN_GPIO102, + MFP_PIN_GPIO103, + MFP_PIN_GPIO104, + MFP_PIN_GPIO105, + MFP_PIN_GPIO106, + MFP_PIN_GPIO107, + MFP_PIN_GPIO108, + MFP_PIN_GPIO109, + MFP_PIN_GPIO110, + MFP_PIN_GPIO111, + MFP_PIN_GPIO112, + MFP_PIN_GPIO113, + MFP_PIN_GPIO114, + MFP_PIN_GPIO115, + MFP_PIN_GPIO116, + MFP_PIN_GPIO117, + MFP_PIN_GPIO118, + MFP_PIN_GPIO119, + MFP_PIN_GPIO120, + MFP_PIN_GPIO121, + MFP_PIN_GPIO122, + MFP_PIN_GPIO123, + MFP_PIN_GPIO124, + MFP_PIN_GPIO125, + MFP_PIN_GPIO126, + MFP_PIN_GPIO127, + + MFP_PIN_GPIO128, + MFP_PIN_GPIO129, + MFP_PIN_GPIO130, + MFP_PIN_GPIO131, + MFP_PIN_GPIO132, + MFP_PIN_GPIO133, + MFP_PIN_GPIO134, + MFP_PIN_GPIO135, + MFP_PIN_GPIO136, + MFP_PIN_GPIO137, + MFP_PIN_GPIO138, + MFP_PIN_GPIO139, + MFP_PIN_GPIO140, + MFP_PIN_GPIO141, + MFP_PIN_GPIO142, + MFP_PIN_GPIO143, + MFP_PIN_GPIO144, + MFP_PIN_GPIO145, + MFP_PIN_GPIO146, + MFP_PIN_GPIO147, + MFP_PIN_GPIO148, + MFP_PIN_GPIO149, + MFP_PIN_GPIO150, + MFP_PIN_GPIO151, + MFP_PIN_GPIO152, + MFP_PIN_GPIO153, + MFP_PIN_GPIO154, + MFP_PIN_GPIO155, + MFP_PIN_GPIO156, + MFP_PIN_GPIO157, + MFP_PIN_GPIO158, + MFP_PIN_GPIO159, + MFP_PIN_GPIO160, + MFP_PIN_GPIO161, + MFP_PIN_GPIO162, + MFP_PIN_GPIO163, + MFP_PIN_GPIO164, + MFP_PIN_GPIO165, + MFP_PIN_GPIO166, + MFP_PIN_GPIO167, + MFP_PIN_GPIO168, + MFP_PIN_GPIO169, + MFP_PIN_GPIO170, + MFP_PIN_GPIO171, + MFP_PIN_GPIO172, + MFP_PIN_GPIO173, + MFP_PIN_GPIO174, + MFP_PIN_GPIO175, + MFP_PIN_GPIO176, + MFP_PIN_GPIO177, + MFP_PIN_GPIO178, + MFP_PIN_GPIO179, + MFP_PIN_GPIO180, + MFP_PIN_GPIO181, + MFP_PIN_GPIO182, + MFP_PIN_GPIO183, + MFP_PIN_GPIO184, + MFP_PIN_GPIO185, + MFP_PIN_GPIO186, + MFP_PIN_GPIO187, + MFP_PIN_GPIO188, + MFP_PIN_GPIO189, + MFP_PIN_GPIO190, + MFP_PIN_GPIO191, + + MFP_PIN_GPIO255 = 255, + + MFP_PIN_GPIO0_2, + MFP_PIN_GPIO1_2, + MFP_PIN_GPIO2_2, + MFP_PIN_GPIO3_2, + MFP_PIN_GPIO4_2, + MFP_PIN_GPIO5_2, + MFP_PIN_GPIO6_2, + MFP_PIN_GPIO7_2, + MFP_PIN_GPIO8_2, + MFP_PIN_GPIO9_2, + MFP_PIN_GPIO10_2, + MFP_PIN_GPIO11_2, + MFP_PIN_GPIO12_2, + MFP_PIN_GPIO13_2, + MFP_PIN_GPIO14_2, + MFP_PIN_GPIO15_2, + MFP_PIN_GPIO16_2, + MFP_PIN_GPIO17_2, + + MFP_PIN_ULPI_STP, + MFP_PIN_ULPI_NXT, + MFP_PIN_ULPI_DIR, + + MFP_PIN_nXCVREN, + MFP_PIN_DF_CLE_nOE, + MFP_PIN_DF_nADV1_ALE, + MFP_PIN_DF_SCLK_E, + MFP_PIN_DF_SCLK_S, + MFP_PIN_nBE0, + MFP_PIN_nBE1, + MFP_PIN_DF_nADV2_ALE, + MFP_PIN_DF_INT_RnB, + MFP_PIN_DF_nCS0, + MFP_PIN_DF_nCS1, + MFP_PIN_nLUA, + MFP_PIN_nLLA, + MFP_PIN_DF_nWE, + MFP_PIN_DF_ALE_nWE, + MFP_PIN_DF_nRE_nOE, + MFP_PIN_DF_ADDR0, + MFP_PIN_DF_ADDR1, + MFP_PIN_DF_ADDR2, + MFP_PIN_DF_ADDR3, + MFP_PIN_DF_IO0, + MFP_PIN_DF_IO1, + MFP_PIN_DF_IO2, + MFP_PIN_DF_IO3, + MFP_PIN_DF_IO4, + MFP_PIN_DF_IO5, + MFP_PIN_DF_IO6, + MFP_PIN_DF_IO7, + MFP_PIN_DF_IO8, + MFP_PIN_DF_IO9, + MFP_PIN_DF_IO10, + MFP_PIN_DF_IO11, + MFP_PIN_DF_IO12, + MFP_PIN_DF_IO13, + MFP_PIN_DF_IO14, + MFP_PIN_DF_IO15, + MFP_PIN_DF_nCS0_SM_nCS2, + MFP_PIN_DF_nCS1_SM_nCS3, + MFP_PIN_SM_nCS0, + MFP_PIN_SM_nCS1, + MFP_PIN_DF_WEn, + MFP_PIN_DF_REn, + MFP_PIN_DF_CLE_SM_OEn, + MFP_PIN_DF_ALE_SM_WEn, + MFP_PIN_DF_RDY0, + MFP_PIN_DF_RDY1, + + MFP_PIN_SM_SCLK, + MFP_PIN_SM_BE0, + MFP_PIN_SM_BE1, + MFP_PIN_SM_ADV, + MFP_PIN_SM_ADVMUX, + MFP_PIN_SM_RDY, + + MFP_PIN_MMC1_DAT7, + MFP_PIN_MMC1_DAT6, + MFP_PIN_MMC1_DAT5, + MFP_PIN_MMC1_DAT4, + MFP_PIN_MMC1_DAT3, + MFP_PIN_MMC1_DAT2, + MFP_PIN_MMC1_DAT1, + MFP_PIN_MMC1_DAT0, + MFP_PIN_MMC1_CMD, + MFP_PIN_MMC1_CLK, + MFP_PIN_MMC1_CD, + MFP_PIN_MMC1_WP, + + /* additional pins on PXA930 */ + MFP_PIN_GSIM_UIO, + MFP_PIN_GSIM_UCLK, + MFP_PIN_GSIM_UDET, + MFP_PIN_GSIM_nURST, + MFP_PIN_PMIC_INT, + MFP_PIN_RDY, + + MFP_PIN_MAX, +}; + +/* + * a possible MFP configuration is represented by a 32-bit integer + * + * bit 0.. 9 - MFP Pin Number (1024 Pins Maximum) + * bit 10..12 - Alternate Function Selection + * bit 13..15 - Drive Strength + * bit 16..18 - Low Power Mode State + * bit 19..20 - Low Power Mode Edge Detection + * bit 21..22 - Run Mode Pull State + * + * to facilitate the definition, the following macros are provided + * + * MFP_CFG_DEFAULT - default MFP configuration value, with + * alternate function = 0, + * drive strength = fast 3mA (MFP_DS03X) + * low power mode = default + * edge detection = none + * + * MFP_CFG - default MFPR value with alternate function + * MFP_CFG_DRV - default MFPR value with alternate function and + * pin drive strength + * MFP_CFG_LPM - default MFPR value with alternate function and + * low power mode + * MFP_CFG_X - default MFPR value with alternate function, + * pin drive strength and low power mode + */ + +typedef unsigned long mfp_cfg_t; + +#define MFP_PIN(x) ((x) & 0x3ff) + +#define MFP_AF0 (0x0 << 10) +#define MFP_AF1 (0x1 << 10) +#define MFP_AF2 (0x2 << 10) +#define MFP_AF3 (0x3 << 10) +#define MFP_AF4 (0x4 << 10) +#define MFP_AF5 (0x5 << 10) +#define MFP_AF6 (0x6 << 10) +#define MFP_AF7 (0x7 << 10) +#define MFP_AF_MASK (0x7 << 10) +#define MFP_AF(x) (((x) >> 10) & 0x7) + +#define MFP_DS01X (0x0 << 13) +#define MFP_DS02X (0x1 << 13) +#define MFP_DS03X (0x2 << 13) +#define MFP_DS04X (0x3 << 13) +#define MFP_DS06X (0x4 << 13) +#define MFP_DS08X (0x5 << 13) +#define MFP_DS10X (0x6 << 13) +#define MFP_DS13X (0x7 << 13) +#define MFP_DS_MASK (0x7 << 13) +#define MFP_DS(x) (((x) >> 13) & 0x7) + +#define MFP_LPM_DEFAULT (0x0 << 16) +#define MFP_LPM_DRIVE_LOW (0x1 << 16) +#define MFP_LPM_DRIVE_HIGH (0x2 << 16) +#define MFP_LPM_PULL_LOW (0x3 << 16) +#define MFP_LPM_PULL_HIGH (0x4 << 16) +#define MFP_LPM_FLOAT (0x5 << 16) +#define MFP_LPM_INPUT (0x6 << 16) +#define MFP_LPM_STATE_MASK (0x7 << 16) +#define MFP_LPM_STATE(x) (((x) >> 16) & 0x7) + +#define MFP_LPM_EDGE_NONE (0x0 << 19) +#define MFP_LPM_EDGE_RISE (0x1 << 19) +#define MFP_LPM_EDGE_FALL (0x2 << 19) +#define MFP_LPM_EDGE_BOTH (0x3 << 19) +#define MFP_LPM_EDGE_MASK (0x3 << 19) +#define MFP_LPM_EDGE(x) (((x) >> 19) & 0x3) + +#define MFP_PULL_NONE (0x0 << 21) +#define MFP_PULL_LOW (0x1 << 21) +#define MFP_PULL_HIGH (0x2 << 21) +#define MFP_PULL_BOTH (0x3 << 21) +#define MFP_PULL_FLOAT (0x4 << 21) +#define MFP_PULL_MASK (0x7 << 21) +#define MFP_PULL(x) (((x) >> 21) & 0x7) + +#define MFP_CFG_DEFAULT (MFP_AF0 | MFP_DS03X | MFP_LPM_DEFAULT |\ + MFP_LPM_EDGE_NONE | MFP_PULL_NONE) + +#define MFP_CFG(pin, af) \ + ((MFP_CFG_DEFAULT & ~MFP_AF_MASK) |\ + (MFP_PIN(MFP_PIN_##pin) | MFP_##af)) + +#define MFP_CFG_DRV(pin, af, drv) \ + ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DS_MASK)) |\ + (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_##drv)) + +#define MFP_CFG_LPM(pin, af, lpm) \ + ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_LPM_STATE_MASK)) |\ + (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_LPM_##lpm)) + +#define MFP_CFG_X(pin, af, drv, lpm) \ + ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DS_MASK | MFP_LPM_STATE_MASK)) |\ + (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_##drv | MFP_LPM_##lpm)) + +#if defined(CONFIG_PXA3xx) || defined(CONFIG_ARCH_MMP) +/* + * each MFP pin will have a MFPR register, since the offset of the + * register varies between processors, the processor specific code + * should initialize the pin offsets by mfp_init() + * + * mfp_init_base() - accepts a virtual base for all MFPR registers and + * initialize the MFP table to a default state + * + * mfp_init_addr() - accepts a table of "mfp_addr_map" structure, which + * represents a range of MFP pins from "start" to "end", with the offset + * begining at "offset", to define a single pin, let "end" = -1. + * + * use + * + * MFP_ADDR_X() to define a range of pins + * MFP_ADDR() to define a single pin + * MFP_ADDR_END to signal the end of pin offset definitions + */ +struct mfp_addr_map { + unsigned int start; + unsigned int end; + unsigned long offset; +}; + +#define MFP_ADDR_X(start, end, offset) \ + { MFP_PIN_##start, MFP_PIN_##end, offset } + +#define MFP_ADDR(pin, offset) \ + { MFP_PIN_##pin, -1, offset } + +#define MFP_ADDR_END { MFP_PIN_INVALID, 0 } + +void __init mfp_init_base(unsigned long mfpr_base); +void __init mfp_init_addr(struct mfp_addr_map *map); + +/* + * mfp_{read, write}() - for direct read/write access to the MFPR register + * mfp_config() - for configuring a group of MFPR registers + * mfp_config_lpm() - configuring all low power MFPR registers for suspend + * mfp_config_run() - configuring all run time MFPR registers after resume + */ +unsigned long mfp_read(int mfp); +void mfp_write(int mfp, unsigned long mfpr_val); +void mfp_config(unsigned long *mfp_cfgs, int num); +void mfp_config_run(void); +void mfp_config_lpm(void); +#endif /* CONFIG_PXA3xx || CONFIG_ARCH_MMP */ + +#endif /* __ASM_PLAT_MFP_H */ diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c new file mode 100644 index 0000000000..4f393c4d47 --- /dev/null +++ b/arch/arm/mach-pxa/mfp-pxa2xx.c @@ -0,0 +1,189 @@ +/* + * linux/arch/arm/mach-pxa/mfp-pxa2xx.c + * + * PXA2xx pin mux configuration support + * + * The GPIOs on PXA2xx can be configured as one of many alternate + * functions, this is by concept samilar to the MFP configuration + * on PXA3xx, what's more important, the low power pin state and + * wakeup detection are also supported by the same framework. + * + * 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 + +#define PGSR(x) __REG2(0x40F00020, (x) << 2) +#define __GAFR(u, x) __REG2((u) ? 0x40E00058 : 0x40E00054, (x) << 3) +#define GAFR_L(x) __GAFR(0, x) +#define GAFR_U(x) __GAFR(1, x) + +struct gpio_desc { + unsigned valid:1; + unsigned dir_inverted:1; + unsigned long config; +}; + +static struct gpio_desc gpio_desc[MFP_PIN_GPIO127 + 1]; + +static unsigned long gpdr_lpm[4]; + +static int __mfp_config_gpio(unsigned gpio, unsigned long c) +{ + unsigned long gafr, mask = GPIO_bit(gpio); + int bank = gpio_to_bank(gpio); + int uorl = !!(gpio & 0x10); /* GAFRx_U or GAFRx_L ? */ + int shft = (gpio & 0xf) << 1; + int fn = MFP_AF(c); + int is_out = (c & MFP_DIR_OUT) ? 1 : 0; + + if (fn > 3) + return -EINVAL; + + /* alternate function and direction at run-time */ + gafr = (uorl == 0) ? GAFR_L(bank) : GAFR_U(bank); + gafr = (gafr & ~(0x3 << shft)) | (fn << shft); + + if (uorl == 0) + GAFR_L(bank) = gafr; + else + GAFR_U(bank) = gafr; + + if (is_out ^ gpio_desc[gpio].dir_inverted) + GPDR(gpio) |= mask; + else + GPDR(gpio) &= ~mask; + + /* alternate function and direction at low power mode */ + switch (c & MFP_LPM_STATE_MASK) { + case MFP_LPM_DRIVE_HIGH: + PGSR(bank) |= mask; + is_out = 1; + break; + case MFP_LPM_DRIVE_LOW: + PGSR(bank) &= ~mask; + is_out = 1; + break; + case MFP_LPM_DEFAULT: + break; + default: + /* warning and fall through, treat as MFP_LPM_DEFAULT */ + pr_warning("%s: GPIO%d: unsupported low power mode\n", + __func__, gpio); + break; + } + + if (is_out ^ gpio_desc[gpio].dir_inverted) + gpdr_lpm[bank] |= mask; + else + gpdr_lpm[bank] &= ~mask; + + return 0; +} + +static inline int __mfp_validate(int mfp) +{ + int gpio = mfp_to_gpio(mfp); + + if ((mfp > MFP_PIN_GPIO127) || !gpio_desc[gpio].valid) { + pr_warning("%s: GPIO%d is invalid pin\n", __func__, gpio); + return -1; + } + + return gpio; +} + +void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num) +{ + unsigned long *c; + int i, gpio; + + for (i = 0, c = mfp_cfgs; i < num; i++, c++) { + + gpio = __mfp_validate(MFP_PIN(*c)); + if (gpio < 0) + continue; + + gpio_desc[gpio].config = *c; + __mfp_config_gpio(gpio, *c); + } +} + +void pxa2xx_mfp_set_lpm(int mfp, unsigned long lpm) +{ + unsigned long c; + int gpio; + + gpio = __mfp_validate(mfp); + if (gpio < 0) + return; + + c = gpio_desc[gpio].config; + c = (c & ~MFP_LPM_STATE_MASK) | lpm; + __mfp_config_gpio(gpio, c); +} + +static void __init pxa25x_mfp_init(void) +{ + int i; + + for (i = 0; i <= pxa_last_gpio; i++) + gpio_desc[i].valid = 1; + + /* PXA26x has additional 4 GPIOs (86/87/88/89) which has the + * direction bit inverted in GPDR2. See PXA26x DM 4.1.1. + */ + for (i = 86; i <= pxa_last_gpio; i++) + gpio_desc[i].dir_inverted = 1; +} + +static void __init pxa27x_mfp_init(void) +{ + int i; + + for (i = 0; i <= pxa_last_gpio; i++) { + /* + * skip GPIO2, 5, 6, 7, 8, they are not + * valid pins allow configuration + */ + if (i == 2 || i == 5 || i == 6 || i == 7 || i == 8) + continue; + + gpio_desc[i].valid = 1; + } +} + +static int __init pxa2xx_mfp_init(void) +{ + int i; + + if (!cpu_is_pxa2xx()) + return 0; + + if (cpu_is_pxa25x()) + pxa25x_mfp_init(); + + if (cpu_is_pxa27x()) { + pxa_init_gpio(2, 120); + pxa27x_mfp_init(); + } + + /* clear RDH bit to enable GPIO receivers after reset/sleep exit */ + PSSR = PSSR_RDH; + + /* initialize gafr_run[], pgsr_lpm[] from existing values */ + for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) + gpdr_lpm[i] = GPDR(i * 32); + + return 0; +} +postcore_initcall(pxa2xx_mfp_init); diff --git a/arch/arm/mach-pxa/speed-pxa27x.c b/arch/arm/mach-pxa/speed-pxa27x.c new file mode 100644 index 0000000000..e8d147fc5d --- /dev/null +++ b/arch/arm/mach-pxa/speed-pxa27x.c @@ -0,0 +1,20 @@ +/* + * clock.h - implementation of the PXA clock functions + * + * Copyright (C) 2010 by Marc Kleine-Budde + * + * This file is released under the GPLv2 + * + */ + +#include +#include +#include + +/* Crystal clock: 13MHz */ +#define BASE_CLK 13000000 + +unsigned long pxa_get_uartclk(void) +{ + return 14857000; +} diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index c2bee79bb4..592d543508 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -92,4 +92,8 @@ config DRIVER_SERIAL_S3C24X0_AUTOSYNC Say Y here if you want to use the auto flow feature of this UART. RTS and CTS will be handled by the hardware when enabled. +config DRIVER_SERIAL_PXA + bool "PXA serial driver" + depends on ARCH_PXA + endmenu diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 411b8c535d..a7021252f7 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_DRIVER_SERIAL_PL010) += serial_pl010.o obj-$(CONFIG_DRIVER_SERIAL_S3C24X0) += serial_s3c24x0.o obj-$(CONFIG_DRIVER_SERIAL_ALTERA) += serial_altera.o obj-$(CONFIG_DRIVER_SERIAL_ALTERA_JTAG) += serial_altera_jtag.o +obj-$(CONFIG_DRIVER_SERIAL_PXA) += serial_pxa.o diff --git a/drivers/serial/serial_pxa.c b/drivers/serial/serial_pxa.c new file mode 100644 index 0000000000..d295235ee3 --- /dev/null +++ b/drivers/serial/serial_pxa.c @@ -0,0 +1,201 @@ +/* + * (c) 2009 Sascha Hauer + * 2010 by Marc Kleine-Budde + * + * 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. + * + */ + +#include +#include +#include +#include + +#include +#include + +#define RBR 0x00 /* Receive Buffer Register (read only) */ +#define THR 0x00 /* Transmit Holding Register (write only) */ +#define IER 0x04 /* Interrupt Enable Register (read/write) */ +#define IIR 0x08 /* Interrupt ID Register (read only) */ +#define FCR 0x08 /* FIFO Control Register (write only) */ +#define LCR 0x0c /* Line Control Register (read/write) */ +#define MCR 0x10 /* Modem Control Register (read/write) */ +#define LSR 0x14 /* Line Status Register (read only) */ +#define MSR 0x18 /* Modem Status Register (read only) */ +#define SPR 0x1c /* Scratch Pad Register (read/write) */ +#define ISR 0x20 /* Infrared Selection Register (read/write) */ +#define DLL 0x00 /* Divisor Latch Low Register (DLAB = 1) (read/write) */ +#define DLH 0x04 /* Divisor Latch High Register (DLAB = 1) (read/write) */ + +#define IER_DMAE (1 << 7) /* DMA Requests Enable */ +#define IER_UUE (1 << 6) /* UART Unit Enable */ +#define IER_NRZE (1 << 5) /* NRZ coding Enable */ +#define IER_RTIOE (1 << 4) /* Receiver Time Out Interrupt Enable */ +#define IER_MIE (1 << 3) /* Modem Interrupt Enable */ +#define IER_RLSE (1 << 2) /* Receiver Line Status Interrupt Enable */ +#define IER_TIE (1 << 1) /* Transmit Data request Interrupt Enable */ +#define IER_RAVIE (1 << 0) /* Receiver Data Available Interrupt Enable */ + +#define IIR_FIFOES1 (1 << 7) /* FIFO Mode Enable Status */ +#define IIR_FIFOES0 (1 << 6) /* FIFO Mode Enable Status */ +#define IIR_TOD (1 << 3) /* Time Out Detected */ +#define IIR_IID2 (1 << 2) /* Interrupt Source Encoded */ +#define IIR_IID1 (1 << 1) /* Interrupt Source Encoded */ +#define IIR_IP (1 << 0) /* Interrupt Pending (active low) */ + +#define FCR_ITL2 (1 << 7) /* Interrupt Trigger Level */ +#define FCR_ITL1 (1 << 6) /* Interrupt Trigger Level */ +#define FCR_RESETTF (1 << 2) /* Reset Transmitter FIFO */ +#define FCR_RESETRF (1 << 1) /* Reset Receiver FIFO */ +#define FCR_TRFIFOE (1 << 0) /* Transmit and Receive FIFO Enable */ +#define FCR_ITL_1 (0) +#define FCR_ITL_8 (FCR_ITL1) +#define FCR_ITL_16 (FCR_ITL2) +#define FCR_ITL_32 (FCR_ITL2 | F CR_ITL1) + +#define LCR_DLAB (1 << 7) /* Divisor Latch Access Bit */ +#define LCR_SB (1 << 6) /* Set Break */ +#define LCR_STKYP (1 << 5) /* Sticky Parity */ +#define LCR_EPS (1 << 4) /* Even Parity Select */ +#define LCR_PEN (1 << 3) /* Parity Enable */ +#define LCR_STB (1 << 2) /* Stop Bit */ +#define LCR_WLS1 (1 << 1) /* Word Length Select */ +#define LCR_WLS0 (1 << 0) /* Word Length Select */ +#define LCR_WLEN8 (LCR_WLS1 | LCR_WLS0) + /* Wordlength: 8 bits */ + +#define LSR_FIFOE (1 << 7) /* FIFO Error Status */ +#define LSR_TEMT (1 << 6) /* Transmitter Empty */ +#define LSR_TDRQ (1 << 5) /* Transmit Data Request */ +#define LSR_BI (1 << 4) /* Break Interrupt */ +#define LSR_FE (1 << 3) /* Framing Error */ +#define LSR_PE (1 << 2) /* Parity Error */ +#define LSR_OE (1 << 1) /* Overrun Error */ +#define LSR_DR (1 << 0) /* Data Ready */ + +#define MCR_LOOP (1 << 4) /* */ +#define MCR_OUT2 (1 << 3) /* force MSR_DCD in loopback mode */ +#define MCR_OUT1 (1 << 2) /* force MSR_RI in loopback mode */ +#define MCR_RTS (1 << 1) /* Request to Send */ +#define MCR_DTR (1 << 0) /* Data Terminal Ready */ + +#define MSR_DCD (1 << 7) /* Data Carrier Detect */ +#define MSR_RI (1 << 6) /* Ring Indicator */ +#define MSR_DSR (1 << 5) /* Data Set Ready */ +#define MSR_CTS (1 << 4) /* Clear To Send */ +#define MSR_DDCD (1 << 3) /* Delta Data Carrier Detect */ +#define MSR_TERI (1 << 2) /* Trailing Edge Ring Indicator */ +#define MSR_DDSR (1 << 1) /* Delta Data Set Ready */ +#define MSR_DCTS (1 << 0) /* Delta Clear To Send */ + +struct pxa_serial_priv { + void __iomem *regs; + struct console_device cdev; +}; + +static void __iomem *to_regs(struct console_device *cdev) +{ + struct pxa_serial_priv *priv = + container_of(cdev, struct pxa_serial_priv, cdev); + return priv->regs; +} + +static void pxa_serial_putc(struct console_device *cdev, char c) +{ + while (!(readl(to_regs(cdev) + LSR) & LSR_TEMT)); + + writel(c, to_regs(cdev) + THR); +} + +static int pxa_serial_tstc(struct console_device *cdev) +{ + return readl(to_regs(cdev) + LSR) & LSR_DR; +} + +static int pxa_serial_getc(struct console_device *cdev) +{ + while (!(readl(to_regs(cdev) + LSR) & LSR_DR)); + + return readl(to_regs(cdev) + RBR) & 0xff; +} + +static void pxa_serial_flush(struct console_device *cdev) +{ +} + +static int pxa_serial_setbaudrate(struct console_device *cdev, int baudrate) +{ + unsigned char cval = LCR_WLEN8; /* 8N1 */ + unsigned int quot; + + /* enable uart */ + writel(IER_UUE, to_regs(cdev) + IER); + + /* write divisor */ + quot = (pxa_get_uartclk() + (8 * baudrate)) / (16 * baudrate); + + writel(cval | LCR_DLAB, to_regs(cdev) + LCR); /* set DLAB */ + writel(quot & 0xff, to_regs(cdev) + DLL); + /* + * work around Errata #75 according to Intel(R) PXA27x + * Processor Family Specification Update (Nov 2005) + */ + readl(to_regs(cdev) + DLL); + writel(quot >> 8, to_regs(cdev) + DLH); + writel(cval, to_regs(cdev) + LCR); /* reset DLAB */ + + /* enable fifos */ + writel(FCR_TRFIFOE, to_regs(cdev) + FCR); + + return 0; +} + +static int pxa_serial_probe(struct device_d *dev) +{ + struct console_device *cdev; + struct pxa_serial_priv *priv; + + priv = xzalloc(sizeof(*priv)); + cdev = &priv->cdev; + priv->regs = dev_request_mem_region(dev, 0); + + dev->type_data = cdev; + cdev->dev = dev; + cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR; + cdev->tstc = pxa_serial_tstc; + cdev->putc = pxa_serial_putc; + cdev->getc = pxa_serial_getc; + cdev->flush = pxa_serial_flush; + cdev->setbrg = pxa_serial_setbaudrate; + + console_register(cdev); + + return 0; +} + +static void pxa_serial_remove(struct device_d *dev) +{ + free(dev->type_data); +} + +static struct driver_d pxa_serial_driver = { + .name = "pxa_serial", + .probe = pxa_serial_probe, + .remove = pxa_serial_remove, +}; + +static int pxa_serial_init(void) +{ + return register_driver(&pxa_serial_driver); +} + +console_initcall(pxa_serial_init); -- cgit v1.2.3 From 8675e8c5757b49aeb03ee53acf79f835eddf2d28 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 1 Dec 2011 17:12:34 +0100 Subject: mci imx esdhc: enable i.MX53 fix for i.MX51 aswell Signed-off-by: Sascha Hauer --- drivers/mci/imx-esdhc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index a0e61f0d01..94b2738f1d 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -107,7 +107,8 @@ u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data) xfertyp |= XFERTYP_RSPTYP_48_BUSY; else if (cmd->resp_type & MMC_RSP_PRESENT) xfertyp |= XFERTYP_RSPTYP_48; - if (cpu_is_mx53() && cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) + if ((cpu_is_mx51() || cpu_is_mx53()) && + cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) xfertyp |= SDHCI_CMD_ABORTCMD; return XFERTYP_CMD(cmd->cmdidx) | xfertyp; -- cgit v1.2.3 From cf46bb52c6e4d349e86142f8c4f07516eb487df2 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 4 Dec 2011 13:48:48 +0100 Subject: ARM i.MX53: Adjust MMC clock frequencies to 200MHz Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/imx53.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/mach-imx/imx53.c b/arch/arm/mach-imx/imx53.c index 7f3c5ba813..64bec867ff 100644 --- a/arch/arm/mach-imx/imx53.c +++ b/arch/arm/mach-imx/imx53.c @@ -173,6 +173,15 @@ int mx53_init_lowlevel(void) r = readl(ccm + MX5_CCM_CSCDR1); r &= ~0x3f; r |= 0x0a; + + r &= ~MX5_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK; + r &= ~MX5_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK; + r |= 1 << MX5_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET; + + r &= ~MX5_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_MASK; + r &= ~MX5_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK; + r |= 1 << MX5_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET; + writel(r, ccm + MX5_CCM_CSCDR1); /* Restore the default values in the Gate registers */ -- cgit v1.2.3 From 2a169b51b174e72e7a7787548aff73fdb42fa891 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 4 Dec 2011 13:49:13 +0100 Subject: mci imx-esdhc: do not overwrite probed host caps The caps are read from the hardware but overwritten afterwards. Fix this. Signed-off-by: Sascha Hauer --- drivers/mci/imx-esdhc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index 94b2738f1d..d19b6da4c5 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -485,7 +485,6 @@ static int fsl_esdhc_probe(struct device_d *dev) host->mci.send_cmd = esdhc_send_cmd; host->mci.set_ios = esdhc_set_ios; host->mci.init = esdhc_init; - host->mci.host_caps = MMC_MODE_4BIT; host->mci.hw_dev = dev; host->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34; -- cgit v1.2.3 From 35869a211f3f5afc8c7bb16c28d62acea3842161 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 5 Dec 2011 15:19:24 +0100 Subject: fix cramfs support broken since zlib update cramfs does not compile since we updated zlib to the kernel version. Fix this by using the kernel version of uncompress.c Signed-off-by: Sascha Hauer --- fs/cramfs/cramfs.c | 2 +- fs/cramfs/uncompress.c | 93 +++++++++++++++++----------------------------- include/cramfs/cramfs_fs.h | 4 +- 3 files changed, 38 insertions(+), 61 deletions(-) diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c index b9ab50f432..bdbb47ecf2 100644 --- a/fs/cramfs/cramfs.c +++ b/fs/cramfs/cramfs.c @@ -337,7 +337,7 @@ static int cramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t size) if (priv->curr_base < 0 || priv->curr_base != base) { cdev_read(priv->cdev, cramfs_read_buf, 4096, base, 0); - priv->curr_block_len = cramfs_uncompress_block(priv->buf, + priv->curr_block_len = cramfs_uncompress_block(priv->buf, 4096, cramfs_read_buf, 4096); if (priv->curr_block_len <= 0) break; diff --git a/fs/cramfs/uncompress.c b/fs/cramfs/uncompress.c index 659869bfe4..b7887bd654 100644 --- a/fs/cramfs/uncompress.c +++ b/fs/cramfs/uncompress.c @@ -1,12 +1,7 @@ /* * uncompress.c * - * Copyright (C) 1999 Linus Torvalds - * Copyright (C) 2000-2002 Transmeta 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. + * (C) Copyright 1999 Linus Torvalds * * cramfs interfaces to the uncompression library. There's really just * three entrypoints: @@ -22,81 +17,63 @@ #include #include -#include -#include +#include +#include +#include +#include +#include static z_stream stream; - -#define ZALLOC_ALIGNMENT 16 - -static void *zalloc (void *x, unsigned items, unsigned size) -{ - void *p; - - size *= items; - size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1); - - p = malloc (size); - - return (p); -} - -static void zfree (void *x, void *addr, unsigned nb) -{ - free (addr); -} +static int initialized; /* Returns length of decompressed data. */ -int cramfs_uncompress_block (void *dst, void *src, int srclen) +int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen) { int err; - inflateReset (&stream); - stream.next_in = src; stream.avail_in = srclen; stream.next_out = dst; - stream.avail_out = 4096 * 2; + stream.avail_out = dstlen; - err = inflate (&stream, Z_FINISH); + err = zlib_inflateReset(&stream); + if (err != Z_OK) { + printk("zlib_inflateReset error %d\n", err); + zlib_inflateEnd(&stream); + zlib_inflateInit(&stream); + } + err = zlib_inflate(&stream, Z_FINISH); if (err != Z_STREAM_END) goto err; return stream.total_out; - err: - /*printf ("Error %d while decompressing!\n", err); */ - /*printf ("%p(%d)->%p\n", src, srclen, dst); */ - return -1; +err: + printk("Error %d while decompressing!\n", err); + printk("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen); + return -EIO; } -int cramfs_uncompress_init (void) +int cramfs_uncompress_init(void) { - int err; - - stream.zalloc = zalloc; - stream.zfree = zfree; - stream.next_in = 0; - stream.avail_in = 0; - -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - stream.outcb = (cb_func) WATCHDOG_RESET; -#else - stream.outcb = Z_NULL; -#endif /* CONFIG_HW_WATCHDOG */ - - err = inflateInit (&stream); - if (err != Z_OK) { - printf ("Error: inflateInit2() returned %d\n", err); - return -1; + if (!initialized++) { + stream.workspace = malloc(zlib_inflate_workspacesize()); + if ( !stream.workspace ) { + initialized = 0; + return -ENOMEM; + } + stream.next_in = NULL; + stream.avail_in = 0; + zlib_inflateInit(&stream); } - return 0; } -int cramfs_uncompress_exit (void) +void cramfs_uncompress_exit(void) { - inflateEnd (&stream); - return 0; + if (!--initialized) { + zlib_inflateEnd(&stream); + vfree(stream.workspace); + } } diff --git a/include/cramfs/cramfs_fs.h b/include/cramfs/cramfs_fs.h index 3d3c56f5a3..af2940be05 100644 --- a/include/cramfs/cramfs_fs.h +++ b/include/cramfs/cramfs_fs.h @@ -119,8 +119,8 @@ struct cramfs_super { #endif /* Uncompression interfaces to the underlying zlib */ -int cramfs_uncompress_block(void *dst, void *src, int srclen); +int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen); int cramfs_uncompress_init(void); -int cramfs_uncompress_exit(void); +void cramfs_uncompress_exit(void); #endif /* __CRAMFS_H */ -- cgit v1.2.3 From 3a7dc44d931497af8680271363e5f055be9c72dc Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sat, 26 Nov 2011 21:34:36 +0100 Subject: add armlinux specific magicvar descriptions Signed-off-by: Sascha Hauer --- arch/arm/lib/armlinux.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/lib/armlinux.c b/arch/arm/lib/armlinux.c index 45752dc609..bd9b72a8ac 100644 --- a/arch/arm/lib/armlinux.c +++ b/arch/arm/lib/armlinux.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -52,6 +53,10 @@ static u32 armlinux_system_rev; static u64 armlinux_system_serial; #endif +BAREBOX_MAGICVAR(armlinux_architecture, "ARM machine ID"); +BAREBOX_MAGICVAR(armlinux_system_rev, "ARM system revision"); +BAREBOX_MAGICVAR(armlinux_system_serial, "ARM system serial"); + void armlinux_set_architecture(int architecture) { #ifdef CONFIG_ENVIRONMENT_VARIABLES -- cgit v1.2.3 From 14273e7be2e09b33cb164ed19e3d44c29c249e0e Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 30 Nov 2011 09:01:07 +0100 Subject: ramfs: increase chunk size to 8192 bytes dlmalloc seems to work more efficient with this chunk size. Copying a bigger file (3MB) takes 271ms vs. 125ms on a i.MX27 board. Even bigger chunk sizes do not further improve performance. Signed-off-by: Sascha Hauer --- fs/ramfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ramfs.c b/fs/ramfs.c index db417e13fc..5e352f277a 100644 --- a/fs/ramfs.c +++ b/fs/ramfs.c @@ -30,7 +30,7 @@ #include #include -#define CHUNK_SIZE 4096 +#define CHUNK_SIZE (4096 * 2) struct ramfs_chunk { char *data; -- cgit v1.2.3 From 133788546c7b00616332ae76c7744f072fe7a543 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Mon, 5 Dec 2011 16:19:00 +0100 Subject: mx53: fix devid for imx53_add_mmc1/2 Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/include/mach/devices-imx53.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-imx/include/mach/devices-imx53.h b/arch/arm/mach-imx/include/mach/devices-imx53.h index 70e7671620..bc32048180 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx53.h +++ b/arch/arm/mach-imx/include/mach/devices-imx53.h @@ -43,12 +43,12 @@ static inline struct device_d *imx53_add_mmc0(void *pdata) static inline struct device_d *imx53_add_mmc1(void *pdata) { - return imx_add_esdhc((void *)MX53_ESDHC2_BASE_ADDR, 0, pdata); + return imx_add_esdhc((void *)MX53_ESDHC2_BASE_ADDR, 1, pdata); } static inline struct device_d *imx53_add_mmc2(void *pdata) { - return imx_add_esdhc((void *)MX53_ESDHC3_BASE_ADDR, 0, pdata); + return imx_add_esdhc((void *)MX53_ESDHC3_BASE_ADDR, 2, pdata); } static inline struct device_d *imx53_add_nand(struct imx_nand_platform_data *pdata) -- cgit v1.2.3 From 521c8ff41ecb2e125daa6bfcdbaec63800db7058 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Mon, 5 Dec 2011 16:19:01 +0100 Subject: imx-esdhc: add support of card detect Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/devices.c | 2 +- arch/arm/mach-imx/include/mach/devices-imx25.h | 2 +- arch/arm/mach-imx/include/mach/devices-imx35.h | 6 ++-- arch/arm/mach-imx/include/mach/devices-imx51.h | 4 +-- arch/arm/mach-imx/include/mach/devices-imx53.h | 6 ++-- arch/arm/mach-imx/include/mach/devices.h | 3 +- arch/arm/mach-imx/include/mach/esdhc.h | 43 ++++++++++++++++++++++++++ drivers/mci/imx-esdhc.c | 37 ++++++++++++++++++++++ 8 files changed, 92 insertions(+), 11 deletions(-) create mode 100644 arch/arm/mach-imx/include/mach/esdhc.h diff --git a/arch/arm/mach-imx/devices.c b/arch/arm/mach-imx/devices.c index 5b062f5f0f..6cd50f31f5 100644 --- a/arch/arm/mach-imx/devices.c +++ b/arch/arm/mach-imx/devices.c @@ -48,7 +48,7 @@ struct device_d *imx_add_mmc(void *base, int id, void *pdata) return imx_add_device("imx-mmc", id, base, 0x1000, pdata); } -struct device_d *imx_add_esdhc(void *base, int id, void *pdata) +struct device_d *imx_add_esdhc(void *base, int id, struct esdhc_platform_data *pdata) { return imx_add_device("imx-esdhc", id, base, 0x1000, pdata); } diff --git a/arch/arm/mach-imx/include/mach/devices-imx25.h b/arch/arm/mach-imx/include/mach/devices-imx25.h index eff59773f7..bd9dd0a914 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx25.h +++ b/arch/arm/mach-imx/include/mach/devices-imx25.h @@ -36,7 +36,7 @@ static inline struct device_d *imx25_add_fec(struct fec_platform_data *pdata) return imx_add_fec((void *)IMX_FEC_BASE, pdata); } -static inline struct device_d *imx25_add_mmc0(void *pdata) +static inline struct device_d *imx25_add_mmc0(struct esdhc_platform_data *pdata) { return imx_add_esdhc((void *)0x53fb4000, 0, pdata); } diff --git a/arch/arm/mach-imx/include/mach/devices-imx35.h b/arch/arm/mach-imx/include/mach/devices-imx35.h index 69f4b36709..6c0d750050 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx35.h +++ b/arch/arm/mach-imx/include/mach/devices-imx35.h @@ -41,17 +41,17 @@ static inline struct device_d *imx35_add_fec(struct fec_platform_data *pdata) return imx_add_fec((void *)IMX_FEC_BASE, pdata); } -static inline struct device_d *imx35_add_mmc0(void *pdata) +static inline struct device_d *imx35_add_mmc0(struct esdhc_platform_data *pdata) { return imx_add_esdhc((void *)IMX_SDHC1_BASE, 0, pdata); } -static inline struct device_d *imx35_add_mmc1(void *pdata) +static inline struct device_d *imx35_add_mmc1(struct esdhc_platform_data *pdata) { return imx_add_esdhc((void *)IMX_SDHC2_BASE, 1, pdata); } -static inline struct device_d *imx35_add_mmc2(void *pdata) +static inline struct device_d *imx35_add_mmc2(struct esdhc_platform_data *pdata) { return imx_add_esdhc((void *)IMX_SDHC3_BASE, 2, pdata); } diff --git a/arch/arm/mach-imx/include/mach/devices-imx51.h b/arch/arm/mach-imx/include/mach/devices-imx51.h index 23410a90d5..d9bed8c886 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx51.h +++ b/arch/arm/mach-imx/include/mach/devices-imx51.h @@ -42,12 +42,12 @@ static inline struct device_d *imx51_add_fec(struct fec_platform_data *pdata) return imx_add_fec((void *)MX51_MXC_FEC_BASE_ADDR, pdata); } -static inline struct device_d *imx51_add_mmc0(void *pdata) +static inline struct device_d *imx51_add_mmc0(struct esdhc_platform_data *pdata) { return imx_add_esdhc((void *)MX51_MMC_SDHC1_BASE_ADDR, 0, pdata); } -static inline struct device_d *imx51_add_mmc1(void *pdata) +static inline struct device_d *imx51_add_mmc1(struct esdhc_platform_data *pdata) { return imx_add_esdhc((void *)MX51_MMC_SDHC2_BASE_ADDR, 1, pdata); } diff --git a/arch/arm/mach-imx/include/mach/devices-imx53.h b/arch/arm/mach-imx/include/mach/devices-imx53.h index bc32048180..bc01420161 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx53.h +++ b/arch/arm/mach-imx/include/mach/devices-imx53.h @@ -36,17 +36,17 @@ static inline struct device_d *imx53_add_fec(struct fec_platform_data *pdata) return imx_add_fec((void *)MX53_FEC_BASE_ADDR, pdata); } -static inline struct device_d *imx53_add_mmc0(void *pdata) +static inline struct device_d *imx53_add_mmc0(struct esdhc_platform_data *pdata) { return imx_add_esdhc((void *)MX53_ESDHC1_BASE_ADDR, 0, pdata); } -static inline struct device_d *imx53_add_mmc1(void *pdata) +static inline struct device_d *imx53_add_mmc1(struct esdhc_platform_data *pdata) { return imx_add_esdhc((void *)MX53_ESDHC2_BASE_ADDR, 1, pdata); } -static inline struct device_d *imx53_add_mmc2(void *pdata) +static inline struct device_d *imx53_add_mmc2(struct esdhc_platform_data *pdata) { return imx_add_esdhc((void *)MX53_ESDHC3_BASE_ADDR, 2, pdata); } diff --git a/arch/arm/mach-imx/include/mach/devices.h b/arch/arm/mach-imx/include/mach/devices.h index 7338ac56ed..f0f730a3c5 100644 --- a/arch/arm/mach-imx/include/mach/devices.h +++ b/arch/arm/mach-imx/include/mach/devices.h @@ -5,6 +5,7 @@ #include #include #include +#include struct device_d *imx_add_fec(void *base, struct fec_platform_data *pdata); struct device_d *imx_add_spi(void *base, int id, struct spi_imx_master *pdata); @@ -14,5 +15,5 @@ struct device_d *imx_add_nand(void *base, struct imx_nand_platform_data *pdata); struct device_d *imx_add_fb(void *base, struct imx_fb_platform_data *pdata); struct device_d *imx_add_ipufb(void *base, struct imx_ipu_fb_platform_data *pdata); struct device_d *imx_add_mmc(void *base, int id, void *pdata); -struct device_d *imx_add_esdhc(void *base, int id, void *pdata); +struct device_d *imx_add_esdhc(void *base, int id, struct esdhc_platform_data *pdata); diff --git a/arch/arm/mach-imx/include/mach/esdhc.h b/arch/arm/mach-imx/include/mach/esdhc.h new file mode 100644 index 0000000000..aaf97481f4 --- /dev/null +++ b/arch/arm/mach-imx/include/mach/esdhc.h @@ -0,0 +1,43 @@ +/* + * Copyright 2010 Wolfram Sang + * + * 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; version 2 + * of the License. + */ + +#ifndef __ASM_ARCH_IMX_ESDHC_H +#define __ASM_ARCH_IMX_ESDHC_H + +enum wp_types { + ESDHC_WP_NONE, /* no WP, neither controller nor gpio */ + ESDHC_WP_CONTROLLER, /* mmc controller internal WP */ + ESDHC_WP_GPIO, /* external gpio pin for WP */ +}; + +enum cd_types { + ESDHC_CD_NONE, /* no CD, neither controller nor gpio */ + ESDHC_CD_CONTROLLER, /* mmc controller internal CD */ + ESDHC_CD_GPIO, /* external gpio pin for CD */ + ESDHC_CD_PERMANENT, /* no CD, card permanently wired to host */ +}; + +/** + * struct esdhc_platform_data - platform data for esdhc on i.MX + * + * ESDHC_WP(CD)_CONTROLLER type is not available on i.MX25/35. + * + * @wp_gpio: gpio for write_protect + * @cd_gpio: gpio for card_detect interrupt + * @wp_type: type of write_protect method (see wp_types enum above) + * @cd_type: type of card_detect method (see cd_types enum above) + */ + +struct esdhc_platform_data { + unsigned int wp_gpio; + unsigned int cd_gpio; + enum wp_types wp_type; + enum cd_types cd_type; +}; +#endif /* __ASM_ARCH_IMX_ESDHC_H */ diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index d19b6da4c5..fe55697638 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include "imx-esdhc.h" @@ -392,6 +394,31 @@ static void esdhc_set_ios(struct mci_host *mci, struct device_d *dev, } +static int esdhc_card_detect(struct fsl_esdhc_host *host) +{ + struct fsl_esdhc *regs = host->regs; + struct esdhc_platform_data *pdata = host->dev->platform_data; + int ret; + + if (!pdata) + return 1; + + switch (pdata->cd_type) { + case ESDHC_CD_NONE: + case ESDHC_CD_PERMANENT: + return 1; + case ESDHC_CD_CONTROLLER: + return !(esdhc_read32(®s->prsstat) & PRSSTAT_WPSPL); + case ESDHC_CD_GPIO: + ret = gpio_direction_input(pdata->cd_gpio); + if (ret) + return ret; + return gpio_get_value(pdata->cd_gpio) ? 0 : 1; + } + + return 0; +} + static int esdhc_init(struct mci_host *mci, struct device_d *dev) { struct fsl_esdhc_host *host = to_fsl_esdhc(mci); @@ -399,6 +426,16 @@ static int esdhc_init(struct mci_host *mci, struct device_d *dev) int timeout = 1000; int ret = 0; + ret = esdhc_card_detect(host); + + if (ret == 0) + return -ENODEV; + + if (ret < 0) + return ret; + + ret = 0; + /* Enable cache snooping */ if (host && !host->no_snoop) esdhc_write32(®s->scr, 0x00000040); -- cgit v1.2.3 From 3555e9794e02c874da42e8a663cd205f1982d2c3 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Mon, 5 Dec 2011 16:19:02 +0100 Subject: mx53 loco: update sd support update to use card detect add sd3 card support Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Sascha Hauer --- arch/arm/boards/freescale-mx53-loco/board.c | 36 ++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/arch/arm/boards/freescale-mx53-loco/board.c b/arch/arm/boards/freescale-mx53-loco/board.c index 6a5ef37adf..aec2254428 100644 --- a/arch/arm/boards/freescale-mx53-loco/board.c +++ b/arch/arm/boards/freescale-mx53-loco/board.c @@ -72,6 +72,22 @@ static struct pad_desc loco_pads[] = { MX53_PAD_SD1_DATA3__ESDHC1_DAT3, /* SD1_CD */ MX53_PAD_EIM_DA13__GPIO3_13, + + /* SD3 */ + MX53_PAD_PATA_DATA8__ESDHC3_DAT0, + MX53_PAD_PATA_DATA9__ESDHC3_DAT1, + MX53_PAD_PATA_DATA10__ESDHC3_DAT2, + MX53_PAD_PATA_DATA11__ESDHC3_DAT3, + MX53_PAD_PATA_DATA0__ESDHC3_DAT4, + MX53_PAD_PATA_DATA1__ESDHC3_DAT5, + MX53_PAD_PATA_DATA2__ESDHC3_DAT6, + MX53_PAD_PATA_DATA3__ESDHC3_DAT7, + MX53_PAD_PATA_IORDY__ESDHC3_CLK, + MX53_PAD_PATA_RESET_B__ESDHC3_CMD, + /* SD3_CD */ + MX53_PAD_EIM_DA11__GPIO3_11, + /* SD3_WP */ + MX53_PAD_EIM_DA12__GPIO3_12, }; static int loco_mem_init(void) @@ -92,11 +108,29 @@ static void loco_fec_reset(void) gpio_set_value(LOCO_FEC_PHY_RST, 1); } +#define LOCO_SD3_CD IMX_GPIO_NR(3, 11) +#define LOCO_SD3_WP IMX_GPIO_NR(3, 12) +#define LOCO_SD1_CD IMX_GPIO_NR(3, 13) + +static struct esdhc_platform_data loco_sd1_data = { + .cd_gpio = LOCO_SD1_CD, + .cd_type = ESDHC_CD_GPIO, + .wp_type = ESDHC_WP_NONE, +}; + +static struct esdhc_platform_data loco_sd3_data = { + .cd_gpio = LOCO_SD3_CD, + .wp_gpio = LOCO_SD3_WP, + .cd_type = ESDHC_CD_GPIO, + .wp_type = ESDHC_WP_GPIO, +}; + static int loco_devices_init(void) { imx51_iim_register_fec_ethaddr(); imx53_add_fec(&fec_info); - imx53_add_mmc0(NULL); + imx53_add_mmc0(&loco_sd1_data); + imx53_add_mmc2(&loco_sd3_data); loco_fec_reset(); -- cgit v1.2.3 From 2504dcd33209db69ebb48ae7d1c5834cdc5c023f Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Mon, 5 Dec 2011 16:19:03 +0100 Subject: imx: add mx53 SMD board support with: - uarts - sd and emmc - fec Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Sascha Hauer --- arch/arm/Makefile | 1 + arch/arm/boards/freescale-mx53-smd/Makefile | 2 + arch/arm/boards/freescale-mx53-smd/board.c | 170 ++++++++++++++++++++++ arch/arm/boards/freescale-mx53-smd/config.h | 24 +++ arch/arm/boards/freescale-mx53-smd/env/config | 51 +++++++ arch/arm/boards/freescale-mx53-smd/flash_header.c | 101 +++++++++++++ arch/arm/boards/freescale-mx53-smd/mx53-smd.dox | 4 + arch/arm/configs/freescale_mx53_smd_defconfig | 51 +++++++ arch/arm/mach-imx/Kconfig | 5 + arch/arm/mach-imx/include/mach/devices-imx53.h | 5 + 10 files changed, 414 insertions(+) create mode 100644 arch/arm/boards/freescale-mx53-smd/Makefile create mode 100644 arch/arm/boards/freescale-mx53-smd/board.c create mode 100644 arch/arm/boards/freescale-mx53-smd/config.h create mode 100644 arch/arm/boards/freescale-mx53-smd/env/config create mode 100644 arch/arm/boards/freescale-mx53-smd/flash_header.c create mode 100644 arch/arm/boards/freescale-mx53-smd/mx53-smd.dox create mode 100644 arch/arm/configs/freescale_mx53_smd_defconfig diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 913a90ed71..6f5f3433b1 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -105,6 +105,7 @@ board-$(CONFIG_MACH_CHUMBY) := chumby_falconwing board-$(CONFIG_MACH_TX28) := karo-tx28 board-$(CONFIG_MACH_FREESCALE_MX51_PDK) := freescale-mx51-pdk board-$(CONFIG_MACH_FREESCALE_MX53_LOCO) := freescale-mx53-loco +board-$(CONFIG_MACH_FREESCALE_MX53_SMD) := freescale-mx53-smd board-$(CONFIG_MACH_GUF_CUPID) := guf-cupid board-$(CONFIG_MACH_MINI2440) := mini2440 board-$(CONFIG_MACH_USB_A9260) := usb-a926x diff --git a/arch/arm/boards/freescale-mx53-smd/Makefile b/arch/arm/boards/freescale-mx53-smd/Makefile new file mode 100644 index 0000000000..b56ce7f50d --- /dev/null +++ b/arch/arm/boards/freescale-mx53-smd/Makefile @@ -0,0 +1,2 @@ +obj-y += board.o +obj-y += flash_header.o diff --git a/arch/arm/boards/freescale-mx53-smd/board.c b/arch/arm/boards/freescale-mx53-smd/board.c new file mode 100644 index 0000000000..325458eb23 --- /dev/null +++ b/arch/arm/boards/freescale-mx53-smd/board.c @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2007 Sascha Hauer, Pengutronix + * Copyright (C) 2011 Marc Kleine-Budde + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static struct fec_platform_data fec_info = { + .xcv_type = RMII, +}; + +static struct pad_desc smd_pads[] = { + /* UART1 */ + MX53_PAD_CSI0_DAT10__UART1_TXD_MUX, + MX53_PAD_CSI0_DAT11__UART1_RXD_MUX, + + /* UART2 */ + MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX, + MX53_PAD_PATA_DMARQ__UART2_TXD_MUX, + + /* UART3 */ + MX53_PAD_PATA_CS_0__UART3_TXD_MUX, + MX53_PAD_PATA_CS_1__UART3_RXD_MUX, + MX53_PAD_PATA_DA_1__UART3_CTS, + MX53_PAD_PATA_DA_2__UART3_RTS, + + /* FEC */ + MX53_PAD_FEC_MDC__FEC_MDC, + MX53_PAD_FEC_MDIO__FEC_MDIO, + MX53_PAD_FEC_REF_CLK__FEC_TX_CLK, + MX53_PAD_FEC_RX_ER__FEC_RX_ER, + MX53_PAD_FEC_CRS_DV__FEC_RX_DV, + MX53_PAD_FEC_RXD1__FEC_RDATA_1, + MX53_PAD_FEC_RXD0__FEC_RDATA_0, + MX53_PAD_FEC_TX_EN__FEC_TX_EN, + MX53_PAD_FEC_TXD1__FEC_TDATA_1, + MX53_PAD_FEC_TXD0__FEC_TDATA_0, + /* FEC_nRST */ + MX53_PAD_PATA_DA_0__GPIO7_6, + + /* SD1 */ + MX53_PAD_SD1_CMD__ESDHC1_CMD, + MX53_PAD_SD1_CLK__ESDHC1_CLK, + MX53_PAD_SD1_DATA0__ESDHC1_DAT0, + MX53_PAD_SD1_DATA1__ESDHC1_DAT1, + MX53_PAD_SD1_DATA2__ESDHC1_DAT2, + MX53_PAD_SD1_DATA3__ESDHC1_DAT3, + /* SD1_CD */ + MX53_PAD_EIM_DA13__GPIO3_13, + /* SD1_WP */ + MX53_PAD_KEY_ROW2__GPIO4_11, + + /* SD3 */ + MX53_PAD_PATA_DATA8__ESDHC3_DAT0, + MX53_PAD_PATA_DATA9__ESDHC3_DAT1, + MX53_PAD_PATA_DATA10__ESDHC3_DAT2, + MX53_PAD_PATA_DATA11__ESDHC3_DAT3, + MX53_PAD_PATA_DATA0__ESDHC3_DAT4, + MX53_PAD_PATA_DATA1__ESDHC3_DAT5, + MX53_PAD_PATA_DATA2__ESDHC3_DAT6, + MX53_PAD_PATA_DATA3__ESDHC3_DAT7, + MX53_PAD_PATA_IORDY__ESDHC3_CLK, + MX53_PAD_PATA_RESET_B__ESDHC3_CMD, +}; + +static int smd_mem_init(void) +{ + arm_add_mem_device("ram0", 0x70000000, SZ_512M); + arm_add_mem_device("ram1", 0xb0000000, SZ_512M); + + return 0; +} +mem_initcall(smd_mem_init); + +#define SMD_FEC_PHY_RST IMX_GPIO_NR(7, 6) + +static void smd_fec_reset(void) +{ + gpio_direction_output(SMD_FEC_PHY_RST, 0); + mdelay(1); + gpio_set_value(SMD_FEC_PHY_RST, 1); +} + +#define LOCO_SD1_CD IMX_GPIO_NR(3, 13) +#define LOCO_SD1_WP IMX_GPIO_NR(4, 11) + +static struct esdhc_platform_data loco_sd1_data = { + .cd_gpio = LOCO_SD1_CD, + .wp_gpio = LOCO_SD1_WP, + .cd_type = ESDHC_CD_GPIO, + .wp_type = ESDHC_WP_GPIO, +}; + +static struct esdhc_platform_data loco_sd3_data = { + .wp_type = ESDHC_WP_NONE, + .cd_type = ESDHC_CD_PERMANENT, +}; + +static int smd_devices_init(void) +{ + imx51_iim_register_fec_ethaddr(); + imx53_add_fec(&fec_info); + imx53_add_mmc0(&loco_sd1_data); + imx53_add_mmc2(&loco_sd3_data); + + smd_fec_reset(); + + armlinux_set_bootparams((void *)0x70000100); + armlinux_set_architecture(MACH_TYPE_MX53_SMD); + + return 0; +} +device_initcall(smd_devices_init); + +static int smd_part_init(void) +{ + devfs_add_partition("disk0", 0x00000, 0x40000, PARTITION_FIXED, "self0"); + devfs_add_partition("disk0", 0x40000, 0x20000, PARTITION_FIXED, "env0"); + + return 0; +} +late_initcall(smd_part_init); + +static int smd_console_init(void) +{ + mxc_iomux_v3_setup_multiple_pads(smd_pads, ARRAY_SIZE(smd_pads)); + + mx53_init_lowlevel(); + + imx53_add_uart0(); + imx53_add_uart1(); + imx53_add_uart2(); + return 0; +} +console_initcall(smd_console_init); diff --git a/arch/arm/boards/freescale-mx53-smd/config.h b/arch/arm/boards/freescale-mx53-smd/config.h new file mode 100644 index 0000000000..b7effe5d28 --- /dev/null +++ b/arch/arm/boards/freescale-mx53-smd/config.h @@ -0,0 +1,24 @@ +/** + * @file + * @brief Global defintions for the ARM i.MX51 based babbage board + * + * 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 __CONFIG_H +#define __CONFIG_H + +#endif /* __CONFIG_H */ diff --git a/arch/arm/boards/freescale-mx53-smd/env/config b/arch/arm/boards/freescale-mx53-smd/env/config new file mode 100644 index 0000000000..3659a629a9 --- /dev/null +++ b/arch/arm/boards/freescale-mx53-smd/env/config @@ -0,0 +1,51 @@ +#!/bin/sh + +machine=loco +eth0.serverip= +user= + +# use 'dhcp' to do dhcp in barebox and in kernel +# use 'none' if you want to skip kernel ip autoconfiguration +ip=dhcp + +# or set your networking parameters here +#eth0.ipaddr=a.b.c.d +#eth0.netmask=a.b.c.d +#eth0.gateway=a.b.c.d +#eth0.serverip=a.b.c.d + +# can be either 'nfs', 'tftp', 'nor' or 'nand' +kernel_loc=tftp +# can be either 'net', 'nor', 'nand' or 'initrd' +rootfs_loc=net + +# can be either 'jffs2' or 'ubifs' +rootfs_type=ubifs +rootfsimage=root-$machine.$rootfs_type + +# The image type of the kernel. Can be uimage, zimage, raw, or raw_lzo +kernelimage_type=zimage +kernelimage=zImage-$machine +#kernelimage_type=uimage +#kernelimage=uImage-$machine +#kernelimage_type=raw +#kernelimage=Image-$machine +#kernelimage_type=raw_lzo +#kernelimage=Image-$machine.lzo + +if [ -n $user ]; then + kernelimage="$user"-"$kernelimage" + nfsroot="$eth0.serverip:/home/$user/nfsroot/$machine" + rootfsimage="$user"-"$rootfsimage" +else + nfsroot="$eth0.serverip:/path/to/nfs/root" +fi + +autoboot_timeout=3 + +bootargs="console=ttymxc0,115200" + +disk_parts="256k(barebox)ro,128k(bareboxenv),4M(kernel),-(root)" + +# set a fancy prompt (if support is compiled in) +PS1="\e[1;32mbarebox@\e[1;31m\h:\w\e[0m " diff --git a/arch/arm/boards/freescale-mx53-smd/flash_header.c b/arch/arm/boards/freescale-mx53-smd/flash_header.c new file mode 100644 index 0000000000..490e223f0e --- /dev/null +++ b/arch/arm/boards/freescale-mx53-smd/flash_header.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2011 Marc Kleine-Budde + * + * 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. + * + */ + +#include +#include +#include + +void __naked __flash_header_start go(void) +{ + __asm__ __volatile__("b exception_vectors\n"); +} + +struct imx_dcd_v2_entry __dcd_entry_section dcd_entry[] = { + { .addr = cpu_to_be32(0x53fa8554), .val = cpu_to_be32(0x00300000), }, + { .addr = cpu_to_be32(0x53fa8558), .val = cpu_to_be32(0x00300040), }, + { .addr = cpu_to_be32(0x53fa8560), .val = cpu_to_be32(0x00300000), }, + { .addr = cpu_to_be32(0x53fa8564), .val = cpu_to_be32(0x00300040), }, + { .addr = cpu_to_be32(0x53fa8568), .val = cpu_to_be32(0x00300040), }, + { .addr = cpu_to_be32(0x53fa8570), .val = cpu_to_be32(0x00300000), }, + { .addr = cpu_to_be32(0x53fa8574), .val = cpu_to_be32(0x00300000), }, + { .addr = cpu_to_be32(0x53fa8578), .val = cpu_to_be32(0x00300000), }, + { .addr = cpu_to_be32(0x53fa857c), .val = cpu_to_be32(0x00300040), }, + { .addr = cpu_to_be32(0x53fa8580), .val = cpu_to_be32(0x00300040), }, + { .addr = cpu_to_be32(0x53fa8584), .val = cpu_to_be32(0x00300000), }, + { .addr = cpu_to_be32(0x53fa8588), .val = cpu_to_be32(0x00300000), }, + { .addr = cpu_to_be32(0x53fa8590), .val = cpu_to_be32(0x00300040), }, + { .addr = cpu_to_be32(0x53fa8594), .val = cpu_to_be32(0x00300000), }, + { .addr = cpu_to_be32(0x53fa86f0), .val = cpu_to_be32(0x00300000), }, + { .addr = cpu_to_be32(0x53fa86f4), .val = cpu_to_be32(0x00000000), }, + { .addr = cpu_to_be32(0x53fa86fc), .val = cpu_to_be32(0x00000000), }, + { .addr = cpu_to_be32(0x53fa8714), .val = cpu_to_be32(0x00000000), }, + { .addr = cpu_to_be32(0x53fa8718), .val = cpu_to_be32(0x00300000), }, + { .addr = cpu_to_be32(0x53fa871c), .val = cpu_to_be32(0x00300000), }, + { .addr = cpu_to_be32(0x53fa8720), .val = cpu_to_be32(0x00300000), }, + { .addr = cpu_to_be32(0x53fa8724), .val = cpu_to_be32(0x04000000), }, + { .addr = cpu_to_be32(0x53fa8728), .val = cpu_to_be32(0x00300000), }, + { .addr = cpu_to_be32(0x53fa872c), .val = cpu_to_be32(0x00300000), }, + { .addr = cpu_to_be32(0x63fd9088), .val = cpu_to_be32(0x35343535), }, + { .addr = cpu_to_be32(0x63fd9090), .val = cpu_to_be32(0x4d444c44), }, + { .addr = cpu_to_be32(0x63fd907c), .val = cpu_to_be32(0x01370138), }, + { .addr = cpu_to_be32(0x63fd9080), .val = cpu_to_be32(0x013b013c), }, + { .addr = cpu_to_be32(0x63fd9018), .val = cpu_to_be32(0x00011740), }, + { .addr = cpu_to_be32(0x63fd9000), .val = cpu_to_be32(0xc3190000), }, + { .addr = cpu_to_be32(0x63fd900c), .val = cpu_to_be32(0x9f5152e3), }, + { .addr = cpu_to_be32(0x63fd9010), .val = cpu_to_be32(0xb68e8a63), }, + { .addr = cpu_to_be32(0x63fd9014), .val = cpu_to_be32(0x01ff00db), }, + { .addr = cpu_to_be32(0x63fd902c), .val = cpu_to_be32(0x000026d2), }, + { .addr = cpu_to_be32(0x63fd9030), .val = cpu_to_be32(0x009f0e21), }, + { .addr = cpu_to_be32(0x63fd9008), .val = cpu_to_be32(0x12273030), }, + { .addr = cpu_to_be32(0x63fd9004), .val = cpu_to_be32(0x0002002d), }, + { .addr = cpu_to_be32(0x63fd901c), .val = cpu_to_be32(0x00008032), }, + { .addr = cpu_to_be32(0x63fd901c), .val = cpu_to_be32(0x00008033), }, + { .addr = cpu_to_be32(0x63fd901c), .val = cpu_to_be32(0x00028031), }, + { .addr = cpu_to_be32(0x63fd901c), .val = cpu_to_be32(0x052080b0), }, + { .addr = cpu_to_be32(0x63fd901c), .val = cpu_to_be32(0x04008040), }, + { .addr = cpu_to_be32(0x63fd901c), .val = cpu_to_be32(0x0000803a), }, + { .addr = cpu_to_be32(0x63fd901c), .val = cpu_to_be32(0x0000803b), }, + { .addr = cpu_to_be32(0x63fd901c), .val = cpu_to_be32(0x00028039), }, + { .addr = cpu_to_be32(0x63fd901c), .val = cpu_to_be32(0x05208138), }, + { .addr = cpu_to_be32(0x63fd901c), .val = cpu_to_be32(0x04008048), }, + { .addr = cpu_to_be32(0x63fd9020), .val = cpu_to_be32(0x00005800), }, + { .addr = cpu_to_be32(0x63fd9040), .val = cpu_to_be32(0x04b80003), }, + { .addr = cpu_to_be32(0x63fd9058), .val = cpu_to_be32(0x00022227), }, + { .addr = cpu_to_be32(0x63fd901c), .val = cpu_to_be32(0x00000000), }, +}; + +#define APP_DEST CONFIG_TEXT_BASE + +struct imx_flash_header_v2 __flash_header_section flash_header = { + .header.tag = IVT_HEADER_TAG, + .header.length = cpu_to_be16(32), + .header.version = IVT_VERSION, + + .entry = APP_DEST + 0x1000, + .dcd_ptr = APP_DEST + 0x400 + offsetof(struct imx_flash_header_v2, dcd), + .boot_data_ptr = APP_DEST + 0x400 + offsetof(struct imx_flash_header_v2, boot_data), + .self = APP_DEST + 0x400, + + .boot_data.start = APP_DEST, + .boot_data.size = 0x40000, + + .dcd.header.tag = DCD_HEADER_TAG, + .dcd.header.length = cpu_to_be16(sizeof(struct imx_dcd) + sizeof(dcd_entry)), + .dcd.header.version = DCD_VERSION, + + .dcd.command.tag = DCD_COMMAND_WRITE_TAG, + .dcd.command.length = cpu_to_be16(sizeof(struct imx_dcd_command) + sizeof(dcd_entry)), + .dcd.command.param = DCD_COMMAND_WRITE_PARAM, +}; diff --git a/arch/arm/boards/freescale-mx53-smd/mx53-smd.dox b/arch/arm/boards/freescale-mx53-smd/mx53-smd.dox new file mode 100644 index 0000000000..19605088f6 --- /dev/null +++ b/arch/arm/boards/freescale-mx53-smd/mx53-smd.dox @@ -0,0 +1,4 @@ +/** @page board_loco Freescale i.MX53 SMD Board + + +*/ diff --git a/arch/arm/configs/freescale_mx53_smd_defconfig b/arch/arm/configs/freescale_mx53_smd_defconfig new file mode 100644 index 0000000000..1548b0551e --- /dev/null +++ b/arch/arm/configs/freescale_mx53_smd_defconfig @@ -0,0 +1,51 @@ +CONFIG_ARCH_IMX=y +CONFIG_ARCH_IMX53=y +CONFIG_MACH_FREESCALE_MX53_SMD=y +CONFIG_IMX_IIM=y +CONFIG_IMX_IIM_FUSE_BLOW=y +CONFIG_AEABI=y +CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_ARM_UNWIND=y +CONFIG_MMU=y +CONFIG_TEXT_BASE=0x7ff00000 +CONFIG_MALLOC_SIZE=0x2000000 +CONFIG_KALLSYMS=y +CONFIG_LONGHELP=y +CONFIG_GLOB=y +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y +CONFIG_DEFAULT_ENVIRONMENT_PATH="defaultenv arch/arm/boards/freescale-mx53-smd/env/" +CONFIG_DEBUG_INFO=y +CONFIG_CMD_EDIT=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_LOADENV=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_UNCOMPRESS=y +CONFIG_NET=y +CONFIG_NET_DHCP=y +CONFIG_NET_NFS=y +CONFIG_NET_PING=y +CONFIG_NET_TFTP=y +CONFIG_NET_TFTP_PUSH=y +CONFIG_NET_NETCONSOLE=y +CONFIG_DRIVER_NET_FEC_IMX=y +# CONFIG_SPI is not set +CONFIG_MCI=y +CONFIG_MCI_STARTUP=y +CONFIG_MCI_IMX_ESDHC=y +CONFIG_FS_FAT=y +CONFIG_FS_FAT_WRITE=y +CONFIG_FS_FAT_LFN=y diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 984d9dc361..726920f29b 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -20,6 +20,7 @@ config ARCH_TEXT_BASE default 0xa7e00000 if MACH_NESO default 0x97f00000 if MACH_MX51_PDK default 0x7ff00000 if MACH_MX53_LOCO + default 0x7ff00000 if MACH_MX53_SMD default 0x87f00000 if MACH_GUF_CUPID default 0x93d00000 if MACH_TX25 @@ -40,6 +41,7 @@ config BOARDINFO default "Garz+Fricke Neso" if MACH_NESO default "Freescale i.MX51 PDK" if MACH_FREESCALE_MX51_PDK default "Freescale i.MX53 LOCO" if MACH_FREESCALE_MX53_LOCO + default "Freescale i.MX53 SMD" if MACH_FREESCALE_MX53_SMD default "Garz+Fricke Cupid" if MACH_GUF_CUPID default "Ka-Ro tx25" if MACH_TX25 @@ -402,6 +404,9 @@ choice config MACH_FREESCALE_MX53_LOCO bool "Freescale i.MX53 LOCO" +config MACH_FREESCALE_MX53_SMD + bool "Freescale i.MX53 SMD" + endchoice endif diff --git a/arch/arm/mach-imx/include/mach/devices-imx53.h b/arch/arm/mach-imx/include/mach/devices-imx53.h index bc01420161..1fc2417afd 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx53.h +++ b/arch/arm/mach-imx/include/mach/devices-imx53.h @@ -31,6 +31,11 @@ static inline struct device_d *imx53_add_uart1(void) return imx_add_uart((void *)MX53_UART2_BASE_ADDR, 1); } +static inline struct device_d *imx53_add_uart2(void) +{ + return imx_add_uart((void *)MX53_UART3_BASE_ADDR, 2); +} + static inline struct device_d *imx53_add_fec(struct fec_platform_data *pdata) { return imx_add_fec((void *)MX53_FEC_BASE_ADDR, pdata); -- cgit v1.2.3 From ea8314d19f6441061232549ec41ab0e21abd74ca Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Thu, 24 Nov 2011 04:01:26 +0100 Subject: console: add console unregistering Some console are transient, like the USB connected serial console which should be removed when the USB connection is severed. Enable console removal for such devices. Signed-off-by: Robert Jarzmik Signed-off-by: Sascha Hauer --- common/console.c | 24 ++++++++++++++++++------ common/console_simple.c | 4 ++++ include/console.h | 1 + 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/common/console.c b/common/console.c index 944dd07197..219148d097 100644 --- a/common/console.c +++ b/common/console.c @@ -154,13 +154,9 @@ int console_register(struct console_device *newcdev) list_add_tail(&newcdev->list, &console_list); - if (console_output_buffer) { - while (kfifo_getc(console_output_buffer, &ch) == 0) - console_putc(CONSOLE_STDOUT, ch); - kfifo_free(console_output_buffer); - console_output_buffer = NULL; - } + while (kfifo_getc(console_output_buffer, &ch) == 0) + console_putc(CONSOLE_STDOUT, ch); if (first) barebox_banner(); @@ -168,6 +164,22 @@ int console_register(struct console_device *newcdev) } EXPORT_SYMBOL(console_register); +int console_unregister(struct console_device *cdev) +{ + struct device_d *dev = &cdev->class_dev; + int status; + + list_del(&cdev->list); + if (list_empty(&console_list)) + initialized = CONSOLE_UNINITIALIZED; + + status = unregister_device(dev); + if (!status) + memset(cdev, 0, sizeof(*cdev)); + return status; +} +EXPORT_SYMBOL(console_unregister); + static int getc_raw(void) { struct console_device *cdev; diff --git a/common/console_simple.c b/common/console_simple.c index 7304d8ee05..7e0619db02 100644 --- a/common/console_simple.c +++ b/common/console_simple.c @@ -157,3 +157,7 @@ int console_register(struct console_device *newcdev) } return 0; } + +int console_unregister(struct console_device *cdev) +{ +} diff --git a/include/console.h b/include/console.h index 3bcc5dbbc0..c0817f6371 100644 --- a/include/console.h +++ b/include/console.h @@ -49,6 +49,7 @@ struct console_device { }; int console_register(struct console_device *cdev); +int console_unregister(struct console_device *cdev); extern struct list_head console_list; #define for_each_console(console) list_for_each_entry(console, &console_list, list) -- cgit v1.2.3 From 75139ca334144dd1a7180b5fc6504abf629bd222 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Thu, 24 Nov 2011 04:01:27 +0100 Subject: usb/gadget: add pxa27x_udc driver Adapt mainline kernel pxa27x_udc driver to barebox : - remove function header comments as they are in mainline - test it with serial gadget Signed-off-by: Robert Jarzmik Signed-off-by: Sascha Hauer --- arch/arm/mach-pxa/include/mach/udc_pxa2xx.h | 26 + drivers/usb/gadget/Kconfig | 7 + drivers/usb/gadget/Makefile | 1 + drivers/usb/gadget/pxa27x_udc.c | 1524 +++++++++++++++++++++++++++ drivers/usb/gadget/pxa27x_udc.h | 393 +++++++ 5 files changed, 1951 insertions(+) create mode 100644 arch/arm/mach-pxa/include/mach/udc_pxa2xx.h create mode 100644 drivers/usb/gadget/pxa27x_udc.c create mode 100644 drivers/usb/gadget/pxa27x_udc.h diff --git a/arch/arm/mach-pxa/include/mach/udc_pxa2xx.h b/arch/arm/mach-pxa/include/mach/udc_pxa2xx.h new file mode 100644 index 0000000000..dcdd36a3b4 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/udc_pxa2xx.h @@ -0,0 +1,26 @@ +/* + * arch/arm/mach-pxa/include/mach/udc_pxa2xx.h + * + * This supports machine-specific differences in how the PXA2xx + * USB Device Controller (UDC) is wired. + * + * It is set in linux/arch/arm/mach-pxa/.c or in + * linux/arch/mach-ixp4xx/.c and used in + * the probe routine of linux/drivers/usb/gadget/pxa2xx_udc.c + */ + +struct pxa2xx_udc_mach_info { + int (*udc_is_connected)(void); /* do we see host? */ + void (*udc_command)(int cmd); +#define PXA2XX_UDC_CMD_CONNECT 0 /* let host see us */ +#define PXA2XX_UDC_CMD_DISCONNECT 1 /* so host won't see us */ + + /* Boards following the design guidelines in the developer's manual, + * with on-chip GPIOs not Lubbock's weird hardware, can have a sane + * VBUS IRQ and omit the methods above. Store the GPIO number + * here. Note that sometimes the signals go through inverters... + */ + bool gpio_pullup_inverted; + int gpio_pullup; /* high == pullup activated */ +}; + diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index b8375c661e..472c591c35 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -14,6 +14,13 @@ config USB_GADGET_DRIVER_ARC prompt "Arc OTG device core" depends on ARCH_IMX select USB_GADGET_DUALSPEED + +config USB_GADGET_DRIVER_PXA27X + bool + prompt "PXA27x gadget driver" + depends on ARCH_PXA + select USB_GADGET_DUALSPEED + select POLLER endchoice choice diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 804bb914bc..e034786dc8 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_USB_GADGET) += composite.o config.o usbstring.o epautoconf.o obj-$(CONFIG_USB_GADGET_SERIAL) += u_serial.o serial.o f_serial.o f_acm.o obj-$(CONFIG_USB_GADGET_DFU) += dfu.o obj-$(CONFIG_USB_GADGET_DRIVER_ARC) += fsl_udc.o +obj-$(CONFIG_USB_GADGET_DRIVER_PXA27X) += pxa27x_udc.o diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c new file mode 100644 index 0000000000..d0dbee9824 --- /dev/null +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -0,0 +1,1524 @@ +/* + * Handles the Intel 27x USB Device Controller (UDC) + * + * Inspired by original driver by Frank Becker, David Brownell, and others. + * Copyright (C) 2008 Robert Jarzmik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Taken from linux-2.6 kernel and adapted to barebox. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pxa27x_udc.h" +#include +#include + +#define DRIVER_VERSION "2008-04-18" +#define DRIVER_DESC "PXA 27x USB Device Controller driver" + +static const char driver_name[] = "pxa27x_udc"; +static struct pxa_udc *the_controller; + +static void handle_ep(struct pxa_ep *ep); + +static int is_match_usb_pxa(struct udc_usb_ep *udc_usb_ep, struct pxa_ep *ep, + int config, int interface, int altsetting) +{ + if (usb_endpoint_num(&udc_usb_ep->desc) != ep->addr) + return 0; + if (usb_endpoint_dir_in(&udc_usb_ep->desc) != ep->dir_in) + return 0; + if (usb_endpoint_type(&udc_usb_ep->desc) != ep->type) + return 0; + if ((ep->config != config) || (ep->interface != interface) + || (ep->alternate != altsetting)) + return 0; + return 1; +} + +static struct pxa_ep *find_pxa_ep(struct pxa_udc *udc, + struct udc_usb_ep *udc_usb_ep) +{ + int i; + struct pxa_ep *ep; + int cfg = udc->config; + int iface = udc->last_interface; + int alt = udc->last_alternate; + + if (udc_usb_ep == &udc->udc_usb_ep[0]) + return &udc->pxa_ep[0]; + + for (i = 1; i < NR_PXA_ENDPOINTS; i++) { + ep = &udc->pxa_ep[i]; + if (is_match_usb_pxa(udc_usb_ep, ep, cfg, iface, alt)) + return ep; + } + return NULL; +} + +static void update_pxa_ep_matches(struct pxa_udc *udc) +{ + int i; + struct udc_usb_ep *udc_usb_ep; + + for (i = 1; i < NR_USB_ENDPOINTS; i++) { + udc_usb_ep = &udc->udc_usb_ep[i]; + if (udc_usb_ep->pxa_ep) + udc_usb_ep->pxa_ep = find_pxa_ep(udc, udc_usb_ep); + } +} + +static void pio_irq_enable(struct pxa_ep *ep) +{ + struct pxa_udc *udc = ep->dev; + int index = EPIDX(ep); + u32 udcicr0 = udc_readl(udc, UDCICR0); + u32 udcicr1 = udc_readl(udc, UDCICR1); + + if (index < 16) + udc_writel(udc, UDCICR0, udcicr0 | (3 << (index * 2))); + else + udc_writel(udc, UDCICR1, udcicr1 | (3 << ((index - 16) * 2))); +} + +static void pio_irq_disable(struct pxa_ep *ep) +{ + struct pxa_udc *udc = ep->dev; + int index = EPIDX(ep); + u32 udcicr0 = udc_readl(udc, UDCICR0); + u32 udcicr1 = udc_readl(udc, UDCICR1); + + if (index < 16) + udc_writel(udc, UDCICR0, udcicr0 & ~(3 << (index * 2))); + else + udc_writel(udc, UDCICR1, udcicr1 & ~(3 << ((index - 16) * 2))); +} + +static inline void udc_set_mask_UDCCR(struct pxa_udc *udc, int mask) +{ + u32 udccr = udc_readl(udc, UDCCR); + udc_writel(udc, UDCCR, + (udccr & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS)); +} + +static inline void udc_clear_mask_UDCCR(struct pxa_udc *udc, int mask) +{ + u32 udccr = udc_readl(udc, UDCCR); + udc_writel(udc, UDCCR, + (udccr & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS)); +} + +static inline void ep_write_UDCCSR(struct pxa_ep *ep, int mask) +{ + if (is_ep0(ep)) + mask |= UDCCSR0_ACM; + udc_ep_writel(ep, UDCCSR, mask); +} + +static int ep_count_bytes_remain(struct pxa_ep *ep) +{ + if (ep->dir_in) + return -EOPNOTSUPP; + return udc_ep_readl(ep, UDCBCR) & 0x3ff; +} + +static int ep_is_empty(struct pxa_ep *ep) +{ + int ret; + + if (!is_ep0(ep) && ep->dir_in) + return -EOPNOTSUPP; + if (is_ep0(ep)) + ret = !(udc_ep_readl(ep, UDCCSR) & UDCCSR0_RNE); + else + ret = !(udc_ep_readl(ep, UDCCSR) & UDCCSR_BNE); + return ret; +} + +static int ep_is_full(struct pxa_ep *ep) +{ + if (is_ep0(ep)) + return udc_ep_readl(ep, UDCCSR) & UDCCSR0_IPR; + if (!ep->dir_in) + return -EOPNOTSUPP; + return !(udc_ep_readl(ep, UDCCSR) & UDCCSR_BNF); +} + +static int epout_has_pkt(struct pxa_ep *ep) +{ + if (!is_ep0(ep) && ep->dir_in) + return -EOPNOTSUPP; + if (is_ep0(ep)) + return udc_ep_readl(ep, UDCCSR) & UDCCSR0_OPC; + return udc_ep_readl(ep, UDCCSR) & UDCCSR_PC; +} + +static void set_ep0state(struct pxa_udc *udc, int state) +{ + struct pxa_ep *ep = &udc->pxa_ep[0]; + char *old_stname = EP0_STNAME(udc); + + udc->ep0state = state; + ep_dbg(ep, "state=%s->%s, udccsr0=0x%03x, udcbcr=%d\n", old_stname, + EP0_STNAME(udc), udc_ep_readl(ep, UDCCSR), + udc_ep_readl(ep, UDCBCR)); +} + +static void ep0_idle(struct pxa_udc *dev) +{ + set_ep0state(dev, WAIT_FOR_SETUP); +} + +static __init void pxa_ep_setup(struct pxa_ep *ep) +{ + u32 new_udccr; + + new_udccr = ((ep->config << UDCCONR_CN_S) & UDCCONR_CN) + | ((ep->interface << UDCCONR_IN_S) & UDCCONR_IN) + | ((ep->alternate << UDCCONR_AISN_S) & UDCCONR_AISN) + | ((EPADDR(ep) << UDCCONR_EN_S) & UDCCONR_EN) + | ((EPXFERTYPE(ep) << UDCCONR_ET_S) & UDCCONR_ET) + | ((ep->dir_in) ? UDCCONR_ED : 0) + | ((ep->fifo_size << UDCCONR_MPS_S) & UDCCONR_MPS) + | UDCCONR_EE; + + udc_ep_writel(ep, UDCCR, new_udccr); +} + +static __init void pxa_eps_setup(struct pxa_udc *dev) +{ + unsigned int i; + + dev_dbg(dev->dev, "%s: dev=%p\n", __func__, dev); + + for (i = 1; i < NR_PXA_ENDPOINTS; i++) + pxa_ep_setup(&dev->pxa_ep[i]); +} + +static struct usb_request *pxa_ep_alloc_request(struct usb_ep *_ep) +{ + struct pxa27x_request *req; + + req = xzalloc(sizeof *req); + if (!req) + return NULL; + + INIT_LIST_HEAD(&req->queue); + req->in_use = 0; + req->udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep); + + return &req->req; +} + +static void pxa_ep_free_request(struct usb_ep *_ep, struct usb_request *_req) +{ + struct pxa27x_request *req; + + req = container_of(_req, struct pxa27x_request, req); + WARN_ON(!list_empty(&req->queue)); + kfree(req); +} + +static void ep_add_request(struct pxa_ep *ep, struct pxa27x_request *req) +{ + if (unlikely(!req)) + return; + ep_vdbg(ep, "req:%p, lg=%d, udccsr=0x%03x\n", req, + req->req.length, udc_ep_readl(ep, UDCCSR)); + + req->in_use = 1; + list_add_tail(&req->queue, &ep->queue); + pio_irq_enable(ep); +} + +static void ep_del_request(struct pxa_ep *ep, struct pxa27x_request *req) +{ + if (unlikely(!req)) + return; + ep_vdbg(ep, "req:%p, lg=%d, udccsr=0x%03x\n", req, + req->req.length, udc_ep_readl(ep, UDCCSR)); + + list_del_init(&req->queue); + req->in_use = 0; + if (!is_ep0(ep) && list_empty(&ep->queue)) + pio_irq_disable(ep); +} + +static void req_done(struct pxa_ep *ep, struct pxa27x_request *req, int status) +{ + ep_del_request(ep, req); + if (likely(req->req.status == -EINPROGRESS)) + req->req.status = status; + else + status = req->req.status; + + if (status && status != -ESHUTDOWN) + ep_dbg(ep, "complete req %p stat %d len %u/%u\n", + &req->req, status, + req->req.actual, req->req.length); + + req->req.complete(&req->udc_usb_ep->usb_ep, &req->req); +} + +static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req) +{ + req_done(ep, req, 0); +} + +static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req) +{ + set_ep0state(ep->dev, OUT_STATUS_STAGE); + ep_end_out_req(ep, req); + ep0_idle(ep->dev); +} + +static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req) +{ + req_done(ep, req, 0); +} + +static void ep0_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req) +{ + set_ep0state(ep->dev, IN_STATUS_STAGE); + ep_end_in_req(ep, req); +} + +static void nuke(struct pxa_ep *ep, int status) +{ + struct pxa27x_request *req; + + while (!list_empty(&ep->queue)) { + req = list_entry(ep->queue.next, struct pxa27x_request, queue); + req_done(ep, req, status); + } +} + +static int read_packet(struct pxa_ep *ep, struct pxa27x_request *req) +{ + u32 *buf; + int bytes_ep, bufferspace, count, i; + + bytes_ep = ep_count_bytes_remain(ep); + bufferspace = req->req.length - req->req.actual; + + buf = (u32 *)(req->req.buf + req->req.actual); + + if (likely(!ep_is_empty(ep))) + count = min(bytes_ep, bufferspace); + else /* zlp */ + count = 0; + + for (i = count; i > 0; i -= 4) + *buf++ = udc_ep_readl(ep, UDCDR); + req->req.actual += count; + + ep_write_UDCCSR(ep, UDCCSR_PC); + + return count; +} + +static int write_packet(struct pxa_ep *ep, struct pxa27x_request *req, + unsigned int max) +{ + int length, count, remain, i; + u32 *buf; + u8 *buf_8; + + buf = (u32 *)(req->req.buf + req->req.actual); + prefetch(buf); + + length = min(req->req.length - req->req.actual, max); + req->req.actual += length; + + remain = length & 0x3; + count = length & ~(0x3); + for (i = count; i > 0 ; i -= 4) + udc_ep_writel(ep, UDCDR, *buf++); + + buf_8 = (u8 *)buf; + for (i = remain; i > 0; i--) + udc_ep_writeb(ep, UDCDR, *buf_8++); + + ep_vdbg(ep, "length=%d+%d, udccsr=0x%03x\n", count, remain, + udc_ep_readl(ep, UDCCSR)); + + return length; +} + +static int read_fifo(struct pxa_ep *ep, struct pxa27x_request *req) +{ + int count, is_short, completed = 0; + + while (epout_has_pkt(ep)) { + count = read_packet(ep, req); + + is_short = (count < ep->fifo_size); + ep_dbg(ep, "read udccsr:%03x, count:%d bytes%s req %p %d/%d\n", + udc_ep_readl(ep, UDCCSR), count, is_short ? "/S" : "", + &req->req, req->req.actual, req->req.length); + + /* completion */ + if (is_short || req->req.actual == req->req.length) { + completed = 1; + break; + } + /* finished that packet. the next one may be waiting... */ + } + return completed; +} + +static int write_fifo(struct pxa_ep *ep, struct pxa27x_request *req) +{ + unsigned max; + int count, is_short, is_last = 0, completed = 0, totcount = 0; + u32 udccsr; + + max = ep->fifo_size; + do { + is_short = 0; + + udccsr = udc_ep_readl(ep, UDCCSR); + if (udccsr & UDCCSR_PC) { + ep_vdbg(ep, "Clearing Transmit Complete, udccsr=%x\n", + udccsr); + ep_write_UDCCSR(ep, UDCCSR_PC); + } + if (udccsr & UDCCSR_TRN) { + ep_vdbg(ep, "Clearing Underrun on, udccsr=%x\n", + udccsr); + ep_write_UDCCSR(ep, UDCCSR_TRN); + } + + count = write_packet(ep, req, max); + totcount += count; + + /* last packet is usually short (or a zlp) */ + if (unlikely(count < max)) { + is_last = 1; + 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->fifo_size); + } + + if (is_short) + ep_write_UDCCSR(ep, UDCCSR_SP); + + /* requests complete when all IN data is in the FIFO */ + if (is_last) { + completed = 1; + break; + } + } while (!ep_is_full(ep)); + + ep_dbg(ep, "wrote count:%d bytes%s%s, left:%d req=%p\n", + totcount, is_last ? "/L" : "", is_short ? "/S" : "", + req->req.length - req->req.actual, &req->req); + + return completed; +} + +static int read_ep0_fifo(struct pxa_ep *ep, struct pxa27x_request *req) +{ + int count, is_short, completed = 0; + + while (epout_has_pkt(ep)) { + count = read_packet(ep, req); + ep_write_UDCCSR(ep, UDCCSR0_OPC); + + is_short = (count < ep->fifo_size); + ep_dbg(ep, "read udccsr:%03x, count:%d bytes%s req %p %d/%d\n", + udc_ep_readl(ep, UDCCSR), count, is_short ? "/S" : "", + &req->req, req->req.actual, req->req.length); + + if (is_short || req->req.actual >= req->req.length) { + completed = 1; + break; + } + } + + return completed; +} + +static int write_ep0_fifo(struct pxa_ep *ep, struct pxa27x_request *req) +{ + unsigned count; + int is_last, is_short; + + count = write_packet(ep, req, EP0_FIFO_SIZE); + + is_short = (count < EP0_FIFO_SIZE); + is_last = ((count == 0) || (count < EP0_FIFO_SIZE)); + + /* Sends either a short packet or a 0 length packet */ + if (unlikely(is_short)) + ep_write_UDCCSR(ep, UDCCSR0_IPR); + + ep_dbg(ep, "in %d bytes%s%s, %d left, req=%p, udccsr0=0x%03x\n", + count, is_short ? "/S" : "", is_last ? "/L" : "", + req->req.length - req->req.actual, + &req->req, udc_ep_readl(ep, UDCCSR)); + + return is_last; +} + +static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req) +{ + struct udc_usb_ep *udc_usb_ep; + struct pxa_ep *ep; + struct pxa27x_request *req; + struct pxa_udc *dev; + int rc = 0; + int is_first_req; + unsigned length; + + req = container_of(_req, struct pxa27x_request, req); + udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep); + + if (unlikely(!_req || !_req->complete || !_req->buf)) + return -EINVAL; + + if (unlikely(!_ep)) + return -EINVAL; + + dev = udc_usb_ep->dev; + ep = udc_usb_ep->pxa_ep; + if (unlikely(!ep)) + return -EINVAL; + + dev = ep->dev; + if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) { + ep_dbg(ep, "bogus device state\n"); + return -ESHUTDOWN; + } + + /* iso is always one packet per request, that's the only way + * we can report per-packet status. that also helps with dma. + */ + if (unlikely(EPXFERTYPE_is_ISO(ep) + && req->req.length > ep->fifo_size)) + return -EMSGSIZE; + + is_first_req = list_empty(&ep->queue); + ep_dbg(ep, "queue req %p(first=%s), len %d buf %p\n", + _req, is_first_req ? "yes" : "no", + _req->length, _req->buf); + + if (!ep->enabled) { + _req->status = -ESHUTDOWN; + rc = -ESHUTDOWN; + goto out_locked; + } + + if (req->in_use) { + ep_err(ep, "refusing to queue req %p (already queued)\n", req); + goto out_locked; + } + + length = _req->length; + _req->status = -EINPROGRESS; + _req->actual = 0; + + ep_add_request(ep, req); + + if (is_ep0(ep)) { + switch (dev->ep0state) { + case WAIT_ACK_SET_CONF_INTERF: + if (length == 0) { + ep_end_in_req(ep, req); + } else { + ep_err(ep, "got a request of %d bytes while" + "in state WAIT_ACK_SET_CONF_INTERF\n", + length); + ep_del_request(ep, req); + rc = -EL2HLT; + } + ep0_idle(ep->dev); + break; + case IN_DATA_STAGE: + if (!ep_is_full(ep)) + if (write_ep0_fifo(ep, req)) + ep0_end_in_req(ep, req); + break; + case OUT_DATA_STAGE: + if ((length == 0) || !epout_has_pkt(ep)) + if (read_ep0_fifo(ep, req)) + ep0_end_out_req(ep, req); + break; + default: + ep_err(ep, "odd state %s to send me a request\n", + EP0_STNAME(ep->dev)); + ep_del_request(ep, req); + rc = -EL2HLT; + break; + } + } else { + handle_ep(ep); + } + +out: + return rc; +out_locked: + goto out; +} + +static int pxa_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) +{ + struct pxa_ep *ep; + struct udc_usb_ep *udc_usb_ep; + struct pxa27x_request *req; + int rc = -EINVAL; + + if (!_ep) + return rc; + udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep); + ep = udc_usb_ep->pxa_ep; + if (!ep || is_ep0(ep)) + return rc; + + /* make sure it's actually queued on this endpoint */ + list_for_each_entry(req, &ep->queue, queue) { + if (&req->req == _req) { + rc = 0; + break; + } + } + + if (!rc) + req_done(ep, req, -ECONNRESET); + return rc; +} + +static int pxa_ep_set_halt(struct usb_ep *_ep, int value) +{ + struct pxa_ep *ep; + struct udc_usb_ep *udc_usb_ep; + int rc; + + + if (!_ep) + return -EINVAL; + udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep); + ep = udc_usb_ep->pxa_ep; + if (!ep || is_ep0(ep)) + return -EINVAL; + + if (value == 0) { + /* + * This path (reset toggle+halt) is needed to implement + * SET_INTERFACE on normal hardware. but it can't be + * done from software on the PXA UDC, and the hardware + * forgets to do it as part of SET_INTERFACE automagic. + */ + ep_dbg(ep, "only host can clear halt\n"); + return -EROFS; + } + + rc = -EAGAIN; + if (ep->dir_in && (ep_is_full(ep) || !list_empty(&ep->queue))) + goto out; + + /* FST, FEF bits are the same for control and non control endpoints */ + rc = 0; + ep_write_UDCCSR(ep, UDCCSR_FST | UDCCSR_FEF); + if (is_ep0(ep)) + set_ep0state(ep->dev, STALL); + +out: + return rc; +} + +static int pxa_ep_fifo_status(struct usb_ep *_ep) +{ + struct pxa_ep *ep; + struct udc_usb_ep *udc_usb_ep; + + if (!_ep) + return -ENODEV; + udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep); + ep = udc_usb_ep->pxa_ep; + if (!ep || is_ep0(ep)) + return -ENODEV; + + if (ep->dir_in) + return -EOPNOTSUPP; + if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN || ep_is_empty(ep)) + return 0; + else + return ep_count_bytes_remain(ep) + 1; +} + +static void pxa_ep_fifo_flush(struct usb_ep *_ep) +{ + struct pxa_ep *ep; + struct udc_usb_ep *udc_usb_ep; + + if (!_ep) + return; + udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep); + ep = udc_usb_ep->pxa_ep; + if (!ep || is_ep0(ep)) + return; + + if (unlikely(!list_empty(&ep->queue))) + ep_dbg(ep, "called while queue list not empty\n"); + ep_dbg(ep, "called\n"); + + /* for OUT, just read and discard the FIFO contents. */ + if (!ep->dir_in) { + while (!ep_is_empty(ep)) + udc_ep_readl(ep, UDCDR); + } else { + /* most IN status is the same, but ISO can't stall */ + ep_write_UDCCSR(ep, + UDCCSR_PC | UDCCSR_FEF | UDCCSR_TRN + | (EPXFERTYPE_is_ISO(ep) ? 0 : UDCCSR_SST)); + } +} + +static int pxa_ep_enable(struct usb_ep *_ep, + const struct usb_endpoint_descriptor *desc) +{ + struct pxa_ep *ep; + struct udc_usb_ep *udc_usb_ep; + struct pxa_udc *udc; + + if (!_ep || !desc) + return -EINVAL; + + udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep); + if (udc_usb_ep->pxa_ep) { + ep = udc_usb_ep->pxa_ep; + ep_warn(ep, "usb_ep %s already enabled, doing nothing\n", + _ep->name); + } else { + ep = find_pxa_ep(udc_usb_ep->dev, udc_usb_ep); + } + + if (!ep || is_ep0(ep)) { + dev_err(udc_usb_ep->dev->dev, + "unable to match pxa_ep for ep %s\n", + _ep->name); + return -EINVAL; + } + + if ((desc->bDescriptorType != USB_DT_ENDPOINT) + || (ep->type != usb_endpoint_type(desc))) { + ep_err(ep, "type mismatch\n"); + return -EINVAL; + } + + if (ep->fifo_size < le16_to_cpu(desc->wMaxPacketSize)) { + ep_err(ep, "bad maxpacket\n"); + return -ERANGE; + } + + udc_usb_ep->pxa_ep = ep; + udc = ep->dev; + + if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) { + ep_err(ep, "bogus device state\n"); + return -ESHUTDOWN; + } + + ep->enabled = 1; + + /* flush fifo (mostly for OUT buffers) */ + pxa_ep_fifo_flush(_ep); + + ep_dbg(ep, "enabled\n"); + return 0; +} + +static int pxa_ep_disable(struct usb_ep *_ep) +{ + struct pxa_ep *ep; + struct udc_usb_ep *udc_usb_ep; + + if (!_ep) + return -EINVAL; + + udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep); + ep = udc_usb_ep->pxa_ep; + if (!ep || is_ep0(ep) || !list_empty(&ep->queue)) + return -EINVAL; + + ep->enabled = 0; + nuke(ep, -ESHUTDOWN); + + pxa_ep_fifo_flush(_ep); + udc_usb_ep->pxa_ep = NULL; + + ep_dbg(ep, "disabled\n"); + return 0; +} + +static struct usb_ep_ops pxa_ep_ops = { + .enable = pxa_ep_enable, + .disable = pxa_ep_disable, + + .alloc_request = pxa_ep_alloc_request, + .free_request = pxa_ep_free_request, + + .queue = pxa_ep_queue, + .dequeue = pxa_ep_dequeue, + + .set_halt = pxa_ep_set_halt, + .fifo_status = pxa_ep_fifo_status, + .fifo_flush = pxa_ep_fifo_flush, +}; + +static void dplus_pullup(struct pxa_udc *udc, int on) +{ + if (on) { + if (udc->mach->gpio_pullup > 0) + gpio_set_value(udc->mach->gpio_pullup, + !udc->mach->gpio_pullup_inverted); + if (udc->mach->udc_command) + udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT); + } else { + if (udc->mach->gpio_pullup > 0) + gpio_set_value(udc->mach->gpio_pullup, + udc->mach->gpio_pullup_inverted); + if (udc->mach->udc_command) + udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); + } + udc->pullup_on = on; +} + +/** + * pxa_udc_get_frame - Returns usb frame number + * @_gadget: usb gadget + */ +static int pxa_udc_get_frame(struct usb_gadget *_gadget) +{ + struct pxa_udc *udc = to_gadget_udc(_gadget); + + return udc_readl(udc, UDCFNR) & 0x7ff; +} + +static int pxa_udc_wakeup(struct usb_gadget *_gadget) +{ + struct pxa_udc *udc = to_gadget_udc(_gadget); + + /* host may not have enabled remote wakeup */ + if ((udc_readl(udc, UDCCR) & UDCCR_DWRE) == 0) + return -EHOSTUNREACH; + udc_set_mask_UDCCR(udc, UDCCR_UDR); + return 0; +} + +static void udc_enable(struct pxa_udc *udc); +static void udc_disable(struct pxa_udc *udc); + +static int should_enable_udc(struct pxa_udc *udc) +{ + int put_on; + + put_on = ((udc->pullup_on) && (udc->driver)); + put_on &= udc->vbus_sensed; + return put_on; +} + +static int should_disable_udc(struct pxa_udc *udc) +{ + int put_off; + + put_off = ((!udc->pullup_on) || (!udc->driver)); + put_off |= !udc->vbus_sensed; + return put_off; +} + +static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active) +{ + struct pxa_udc *udc = to_gadget_udc(_gadget); + + if ((udc->mach->gpio_pullup < 0) && !udc->mach->udc_command) + return -EOPNOTSUPP; + + dplus_pullup(udc, is_active); + + if (should_enable_udc(udc)) + udc_enable(udc); + if (should_disable_udc(udc)) + udc_disable(udc); + return 0; +} + +static int pxa_udc_vbus_session(struct usb_gadget *_gadget, int is_active) +{ + struct pxa_udc *udc = to_gadget_udc(_gadget); + + udc->vbus_sensed = is_active; + if (should_enable_udc(udc)) + udc_enable(udc); + if (should_disable_udc(udc)) + udc_disable(udc); + + return 0; +} + +static const struct usb_gadget_ops pxa_udc_ops = { + .get_frame = pxa_udc_get_frame, + .wakeup = pxa_udc_wakeup, + .pullup = pxa_udc_pullup, + .vbus_session = pxa_udc_vbus_session, +}; + +static void clk_enable(void) +{ + CKEN |= CKEN_USB; +} + +static void clk_disable(void) +{ + CKEN &= ~CKEN_USB; +} + +static void udc_disable(struct pxa_udc *udc) +{ + if (!udc->enabled) + return; + + udc_writel(udc, UDCICR0, 0); + udc_writel(udc, UDCICR1, 0); + + udc_clear_mask_UDCCR(udc, UDCCR_UDE); + clk_disable(); + + ep0_idle(udc); + udc->gadget.speed = USB_SPEED_UNKNOWN; + + udc->enabled = 0; +} + +static __init void udc_init_data(struct pxa_udc *dev) +{ + int i; + struct pxa_ep *ep; + + /* device/ep0 records init */ + INIT_LIST_HEAD(&dev->gadget.ep_list); + INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); + dev->udc_usb_ep[0].pxa_ep = &dev->pxa_ep[0]; + ep0_idle(dev); + + /* PXA endpoints init */ + for (i = 0; i < NR_PXA_ENDPOINTS; i++) { + ep = &dev->pxa_ep[i]; + + ep->enabled = is_ep0(ep); + INIT_LIST_HEAD(&ep->queue); + } + + /* USB endpoints init */ + for (i = 1; i < NR_USB_ENDPOINTS; i++) + list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list, + &dev->gadget.ep_list); +} + +static void udc_enable(struct pxa_udc *udc) +{ + if (udc->enabled) + return; + + udc_writel(udc, UDCICR0, 0); + udc_writel(udc, UDCICR1, 0); + udc_clear_mask_UDCCR(udc, UDCCR_UDE); + + clk_enable(); + + ep0_idle(udc); + udc->gadget.speed = USB_SPEED_FULL; + memset(&udc->stats, 0, sizeof(udc->stats)); + + udc_set_mask_UDCCR(udc, UDCCR_UDE); + ep_write_UDCCSR(&udc->pxa_ep[0], UDCCSR0_ACM); + udelay(2); + if (udc_readl(udc, UDCCR) & UDCCR_EMCE) + dev_err(udc->dev, "Configuration errors, udc disabled\n"); + + /* + * Caller must be able to sleep in order to cope with startup transients + */ + mdelay(100); + + /* enable suspend/resume and reset irqs */ + udc_writel(udc, UDCICR1, + UDCICR1_IECC | UDCICR1_IERU + | UDCICR1_IESU | UDCICR1_IERS); + + pio_irq_enable(&udc->pxa_ep[0]); + udc->enabled = 1; +} + +int usb_gadget_register_driver(struct usb_gadget_driver *driver) +{ + struct pxa_udc *udc = the_controller; + int retval; + + if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind + || !driver->disconnect || !driver->setup) + return -EINVAL; + if (!udc) + return -ENODEV; + if (udc->driver) + return -EBUSY; + + /* first hook up the driver ... */ + udc->driver = driver; + dplus_pullup(udc, 1); + + retval = driver->bind(&udc->gadget); + if (retval) { + dev_err(udc->dev, "bind to function %s --> error %d\n", + driver->function, retval); + goto bind_fail; + } + dev_dbg(udc->dev, "registered gadget function '%s'\n", + driver->function); + + if (should_enable_udc(udc)) + udc_enable(udc); + return 0; + +bind_fail: + return retval; +} +EXPORT_SYMBOL(usb_gadget_register_driver); + +static void stop_activity(struct pxa_udc *udc, struct usb_gadget_driver *driver) +{ + int i; + + /* don't disconnect drivers more than once */ + if (udc->gadget.speed == USB_SPEED_UNKNOWN) + driver = NULL; + udc->gadget.speed = USB_SPEED_UNKNOWN; + + for (i = 0; i < NR_USB_ENDPOINTS; i++) + pxa_ep_disable(&udc->udc_usb_ep[i].usb_ep); + + if (driver) + driver->disconnect(&udc->gadget); +} + +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) +{ + struct pxa_udc *udc = the_controller; + + if (!udc) + return -ENODEV; + if (!driver || driver != udc->driver || !driver->unbind) + return -EINVAL; + + stop_activity(udc, driver); + udc_disable(udc); + dplus_pullup(udc, 0); + + driver->disconnect(&udc->gadget); + driver->unbind(&udc->gadget); + udc->driver = NULL; + + /* + dev_info(udc->dev, "unregistered gadget driver '%s'\n", + driver->driver.name); + */ + return 0; +} +EXPORT_SYMBOL(usb_gadget_unregister_driver); + +static void handle_ep0_ctrl_req(struct pxa_udc *udc, + struct pxa27x_request *req) +{ + struct pxa_ep *ep = &udc->pxa_ep[0]; + union { + struct usb_ctrlrequest r; + u32 word[2]; + } u; + int i; + int have_extrabytes = 0; + + nuke(ep, -EPROTO); + + /* + * In the PXA320 manual, in the section about Back-to-Back setup + * packets, it describes this situation. The solution is to set OPC to + * get rid of the status packet, and then continue with the setup + * packet. Generalize to pxa27x CPUs. + */ + if (epout_has_pkt(ep) && (ep_count_bytes_remain(ep) == 0)) + ep_write_UDCCSR(ep, UDCCSR0_OPC); + + /* read SETUP packet */ + for (i = 0; i < 2; i++) { + if (unlikely(ep_is_empty(ep))) + goto stall; + u.word[i] = udc_ep_readl(ep, UDCDR); + } + + have_extrabytes = !ep_is_empty(ep); + while (!ep_is_empty(ep)) { + i = udc_ep_readl(ep, UDCDR); + ep_err(ep, "wrong to have extra bytes for setup : 0x%08x\n", i); + } + + ep_dbg(ep, "SETUP %02x.%02x v%04x i%04x l%04x\n", + u.r.bRequestType, u.r.bRequest, + le16_to_cpu(u.r.wValue), le16_to_cpu(u.r.wIndex), + le16_to_cpu(u.r.wLength)); + if (unlikely(have_extrabytes)) + goto stall; + + if (u.r.bRequestType & USB_DIR_IN) + set_ep0state(udc, IN_DATA_STAGE); + else + set_ep0state(udc, OUT_DATA_STAGE); + + /* Tell UDC to enter Data Stage */ + ep_write_UDCCSR(ep, UDCCSR0_SA | UDCCSR0_OPC); + + i = udc->driver->setup(&udc->gadget, &u.r); + if (i < 0) + goto stall; +out: + return; +stall: + ep_dbg(ep, "protocol STALL, udccsr0=%03x err %d\n", + udc_ep_readl(ep, UDCCSR), i); + ep_write_UDCCSR(ep, UDCCSR0_FST | UDCCSR0_FTF); + set_ep0state(udc, STALL); + goto out; +} + +static void handle_ep0(struct pxa_udc *udc, int fifo_irq, int opc_irq) +{ + u32 udccsr0; + struct pxa_ep *ep = &udc->pxa_ep[0]; + struct pxa27x_request *req = NULL; + int completed = 0; + + if (!list_empty(&ep->queue)) + req = list_entry(ep->queue.next, struct pxa27x_request, queue); + + udccsr0 = udc_ep_readl(ep, UDCCSR); + ep_dbg(ep, "state=%s, req=%p, udccsr0=0x%03x, udcbcr=%d, irq_msk=%x\n", + EP0_STNAME(udc), req, udccsr0, udc_ep_readl(ep, UDCBCR), + (fifo_irq << 1 | opc_irq)); + + if (udccsr0 & UDCCSR0_SST) { + ep_dbg(ep, "clearing stall status\n"); + nuke(ep, -EPIPE); + ep_write_UDCCSR(ep, UDCCSR0_SST); + ep0_idle(udc); + } + + if (udccsr0 & UDCCSR0_SA) { + nuke(ep, 0); + set_ep0state(udc, SETUP_STAGE); + } + + switch (udc->ep0state) { + case WAIT_FOR_SETUP: + /* + * Hardware bug : beware, we cannot clear OPC, since we would + * miss a potential OPC irq for a setup packet. + * So, we only do ... nothing, and hope for a next irq with + * UDCCSR0_SA set. + */ + break; + case SETUP_STAGE: + udccsr0 &= UDCCSR0_CTRL_REQ_MASK; + if (likely(udccsr0 == UDCCSR0_CTRL_REQ_MASK)) + handle_ep0_ctrl_req(udc, req); + break; + case IN_DATA_STAGE: /* GET_DESCRIPTOR */ + if (epout_has_pkt(ep)) + ep_write_UDCCSR(ep, UDCCSR0_OPC); + if (req && !ep_is_full(ep)) + completed = write_ep0_fifo(ep, req); + if (completed) + ep0_end_in_req(ep, req); + break; + case OUT_DATA_STAGE: /* SET_DESCRIPTOR */ + if (epout_has_pkt(ep) && req) + completed = read_ep0_fifo(ep, req); + if (completed) + ep0_end_out_req(ep, req); + break; + case STALL: + ep_write_UDCCSR(ep, UDCCSR0_FST); + break; + case IN_STATUS_STAGE: + /* + * Hardware bug : beware, we cannot clear OPC, since we would + * miss a potential PC irq for a setup packet. + * So, we only put the ep0 into WAIT_FOR_SETUP state. + */ + if (opc_irq) + ep0_idle(udc); + break; + case OUT_STATUS_STAGE: + case WAIT_ACK_SET_CONF_INTERF: + ep_warn(ep, "should never get in %s state here!!!\n", + EP0_STNAME(ep->dev)); + ep0_idle(udc); + break; + } +} + +static void handle_ep(struct pxa_ep *ep) +{ + struct pxa27x_request *req; + int completed; + u32 udccsr; + int is_in = ep->dir_in; + int loop = 0; + + do { + completed = 0; + udccsr = udc_ep_readl(ep, UDCCSR); + + if (likely(!list_empty(&ep->queue))) + req = list_entry(ep->queue.next, + struct pxa27x_request, queue); + else + req = NULL; + + ep_dbg(ep, "req:%p, udccsr 0x%03x loop=%d\n", + req, udccsr, loop++); + + if (unlikely(udccsr & (UDCCSR_SST | UDCCSR_TRN))) + udc_ep_writel(ep, UDCCSR, + udccsr & (UDCCSR_SST | UDCCSR_TRN)); + if (!req) + break; + + if (unlikely(is_in)) { + if (likely(!ep_is_full(ep))) + completed = write_fifo(ep, req); + } else { + if (likely(epout_has_pkt(ep))) + completed = read_fifo(ep, req); + } + + if (completed) { + if (is_in) + ep_end_in_req(ep, req); + else + ep_end_out_req(ep, req); + } + } while (completed); + + return; +} + +static void pxa27x_change_configuration(struct pxa_udc *udc, int config) +{ + struct usb_ctrlrequest req ; + + dev_dbg(udc->dev, "config=%d\n", config); + + udc->config = config; + udc->last_interface = 0; + udc->last_alternate = 0; + + req.bRequestType = 0; + req.bRequest = USB_REQ_SET_CONFIGURATION; + req.wValue = config; + req.wIndex = 0; + req.wLength = 0; + + set_ep0state(udc, WAIT_ACK_SET_CONF_INTERF); + udc->driver->setup(&udc->gadget, &req); +} + +static void pxa27x_change_interface(struct pxa_udc *udc, int iface, int alt) +{ + struct usb_ctrlrequest req; + + dev_dbg(udc->dev, "interface=%d, alternate setting=%d\n", iface, alt); + + udc->last_interface = iface; + udc->last_alternate = alt; + + req.bRequestType = USB_RECIP_INTERFACE; + req.bRequest = USB_REQ_SET_INTERFACE; + req.wValue = alt; + req.wIndex = iface; + req.wLength = 0; + + set_ep0state(udc, WAIT_ACK_SET_CONF_INTERF); + ep_write_UDCCSR(&udc->pxa_ep[0], UDCCSR0_AREN); + udc->driver->setup(&udc->gadget, &req); +} + +static void irq_handle_data(struct pxa_udc *udc) +{ + int i; + struct pxa_ep *ep; + u32 udcisr0 = udc_readl(udc, UDCISR0) & UDCCISR0_EP_MASK; + u32 udcisr1 = udc_readl(udc, UDCISR1) & UDCCISR1_EP_MASK; + + if (udcisr0 & UDCISR_INT_MASK) { + udc_writel(udc, UDCISR0, UDCISR_INT(0, UDCISR_INT_MASK)); + handle_ep0(udc, !!(udcisr0 & UDCICR_FIFOERR), + !!(udcisr0 & UDCICR_PKTCOMPL)); + } + + udcisr0 >>= 2; + for (i = 1; udcisr0 != 0 && i < 16; udcisr0 >>= 2, i++) { + if (!(udcisr0 & UDCISR_INT_MASK)) + continue; + + udc_writel(udc, UDCISR0, UDCISR_INT(i, UDCISR_INT_MASK)); + + WARN_ON(i >= ARRAY_SIZE(udc->pxa_ep)); + if (i < ARRAY_SIZE(udc->pxa_ep)) { + ep = &udc->pxa_ep[i]; + if (ep->enabled) + handle_ep(ep); + } + } + + for (i = 16; udcisr1 != 0 && i < 24; udcisr1 >>= 2, i++) { + udc_writel(udc, UDCISR1, UDCISR_INT(i - 16, UDCISR_INT_MASK)); + if (!(udcisr1 & UDCISR_INT_MASK)) + continue; + + WARN_ON(i >= ARRAY_SIZE(udc->pxa_ep)); + if (i < ARRAY_SIZE(udc->pxa_ep)) { + ep = &udc->pxa_ep[i]; + if (ep->enabled) + handle_ep(ep); + } + } + +} + +static void irq_udc_suspend(struct pxa_udc *udc) +{ + udc_writel(udc, UDCISR1, UDCISR1_IRSU); + + if (udc->gadget.speed != USB_SPEED_UNKNOWN + && udc->driver && udc->driver->suspend) + udc->driver->suspend(&udc->gadget); + ep0_idle(udc); +} + +static void irq_udc_resume(struct pxa_udc *udc) +{ + udc_writel(udc, UDCISR1, UDCISR1_IRRU); + + if (udc->gadget.speed != USB_SPEED_UNKNOWN + && udc->driver && udc->driver->resume) + udc->driver->resume(&udc->gadget); +} + +static void irq_udc_reconfig(struct pxa_udc *udc) +{ + unsigned config, interface, alternate, config_change; + u32 udccr = udc_readl(udc, UDCCR); + + udc_writel(udc, UDCISR1, UDCISR1_IRCC); + + config = (udccr & UDCCR_ACN) >> UDCCR_ACN_S; + config_change = (config != udc->config); + if (config_change) + update_pxa_ep_matches(udc); + udc_set_mask_UDCCR(udc, UDCCR_SMAC); + ep_write_UDCCSR(&udc->pxa_ep[0], UDCCSR0_AREN); + + pxa27x_change_configuration(udc, config); + interface = (udccr & UDCCR_AIN) >> UDCCR_AIN_S; + alternate = (udccr & UDCCR_AAISN) >> UDCCR_AAISN_S; + + /* + * barebox specific: do not call change interface, as change_config has + * already setup the gadget. + * pxa27x_change_interface(udc, interface, alternate); + */ +} + +static void irq_udc_reset(struct pxa_udc *udc) +{ + u32 udccr = udc_readl(udc, UDCCR); + struct pxa_ep *ep = &udc->pxa_ep[0]; + + dev_info(udc->dev, "USB reset\n"); + udc_writel(udc, UDCISR1, UDCISR1_IRRS); + + if ((udccr & UDCCR_UDA) == 0) { + dev_dbg(udc->dev, "USB reset start\n"); + stop_activity(udc, udc->driver); + } + udc->gadget.speed = USB_SPEED_FULL; + + nuke(ep, -EPROTO); + ep_write_UDCCSR(ep, UDCCSR0_FTF | UDCCSR0_OPC); + ep0_idle(udc); +} + +int usb_gadget_poll(void) +{ + struct pxa_udc *udc = the_controller; + u32 udcisr0 = udc_readl(udc, UDCISR0); + u32 udcisr1 = udc_readl(udc, UDCISR1); + u32 udccr = udc_readl(udc, UDCCR); + u32 udcisr1_spec; + int ret = 0; + + udc->vbus_sensed = udc->mach->udc_is_connected(); + if (should_enable_udc(udc)) + udc_enable(udc); + if (should_disable_udc(udc)) { + stop_activity(udc, udc->driver); + udc_disable(udc); + } + + if (!udc->enabled) + return -EIO; + + dev_dbg(udc->dev, "Interrupt, UDCISR0:0x%08x, UDCISR1:0x%08x, " + "UDCCR:0x%08x\n", udcisr0, udcisr1, udccr); + + udcisr1_spec = udcisr1 & 0xf8000000; + if (unlikely(udcisr1_spec & UDCISR1_IRSU)) + irq_udc_suspend(udc); + if (unlikely(udcisr1_spec & UDCISR1_IRRU)) + irq_udc_resume(udc); + if (unlikely(udcisr1_spec & UDCISR1_IRCC)) + irq_udc_reconfig(udc); + if (unlikely(udcisr1_spec & UDCISR1_IRRS)) + irq_udc_reset(udc); + if (udcisr1_spec) + ret = 1; + + if ((udcisr0 & UDCCISR0_EP_MASK) | (udcisr1 & UDCCISR1_EP_MASK)) { + irq_handle_data(udc); + ret = 1; + } + + return ret; +} + +static struct pxa_udc memory = { + .gadget = { + .ops = &pxa_udc_ops, + .ep0 = &memory.udc_usb_ep[0].usb_ep, + .name = driver_name, + }, + + .udc_usb_ep = { + USB_EP_CTRL, + USB_EP_OUT_BULK(1), + USB_EP_IN_BULK(2), + USB_EP_IN_ISO(3), + USB_EP_OUT_ISO(4), + USB_EP_IN_INT(5), + }, + + .pxa_ep = { + PXA_EP_CTRL, + /* Endpoints for gadget zero */ + PXA_EP_OUT_BULK(1, 1, 3, 0, 0), + PXA_EP_IN_BULK(2, 2, 3, 0, 0), + /* Endpoints for ether gadget, file storage gadget */ + PXA_EP_OUT_BULK(3, 1, 1, 0, 0), + PXA_EP_IN_BULK(4, 2, 1, 0, 0), + PXA_EP_IN_ISO(5, 3, 1, 0, 0), + PXA_EP_OUT_ISO(6, 4, 1, 0, 0), + PXA_EP_IN_INT(7, 5, 1, 0, 0), + /* Endpoints for RNDIS, serial */ + PXA_EP_OUT_BULK(8, 1, 2, 0, 0), + PXA_EP_IN_BULK(9, 2, 2, 0, 0), + PXA_EP_IN_INT(10, 5, 2, 0, 0), + /* + * All the following endpoints are only for completion. They + * won't never work, as multiple interfaces are really broken on + * the pxa. + */ + PXA_EP_OUT_BULK(11, 1, 2, 1, 0), + PXA_EP_IN_BULK(12, 2, 2, 1, 0), + /* Endpoint for CDC Ether */ + PXA_EP_OUT_BULK(13, 1, 1, 1, 1), + PXA_EP_IN_BULK(14, 2, 1, 1, 1), + } +}; + +static int __init pxa_udc_probe(struct device_d *dev) +{ + struct pxa_udc *udc = &memory; + int gpio; + + udc->regs = dev_request_mem_region(dev, 0); + if (!udc->regs) + return -ENXIO; + + udc->dev = dev; + udc->mach = dev->platform_data; + + gpio = udc->mach->gpio_pullup; + if (gpio >= 0) { + gpio_direction_output(gpio, + udc->mach->gpio_pullup_inverted); + } + + udc->vbus_sensed = 0; + + the_controller = udc; + udc_init_data(udc); + pxa_eps_setup(udc); + return 0; +} + +#define pxa27x_clear_otgph() do {} while (0) + +static struct driver_d udc_driver = { + .name = "pxa27x-udc", + .probe = pxa_udc_probe, +}; + +static int pxa27x_udc_poller(struct poller_struct *poller) +{ + return usb_gadget_poll(); +} +static struct poller_struct poller = { + .func = pxa27x_udc_poller +}; + +static int __init pxa27x_udc_init(void) +{ + register_driver(&udc_driver); + poller_register(&poller); + return 0; +} + +device_initcall(pxa27x_udc_init); diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h new file mode 100644 index 0000000000..eace2e4055 --- /dev/null +++ b/drivers/usb/gadget/pxa27x_udc.h @@ -0,0 +1,393 @@ +/* + * linux/drivers/usb/gadget/pxa27x_udc.h + * Intel PXA27x on-chip full speed USB device controller + * + * Inspired by original driver by Frank Becker, David Brownell, and others. + * Copyright (C) 2008 Robert Jarzmik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Taken from linux-2.6 kernel and adapted to barebox. + */ + +#ifndef __LINUX_USB_GADGET_PXA27X_H +#define __LINUX_USB_GADGET_PXA27X_H + +/* + * Register definitions + */ +/* Offsets */ +#define UDCCR 0x0000 /* UDC Control Register */ +#define UDCICR0 0x0004 /* UDC Interrupt Control Register0 */ +#define UDCICR1 0x0008 /* UDC Interrupt Control Register1 */ +#define UDCISR0 0x000C /* UDC Interrupt Status Register 0 */ +#define UDCISR1 0x0010 /* UDC Interrupt Status Register 1 */ +#define UDCFNR 0x0014 /* UDC Frame Number Register */ +#define UDCOTGICR 0x0018 /* UDC On-The-Go interrupt control */ +#define UP2OCR 0x0020 /* USB Port 2 Output Control register */ +#define UP3OCR 0x0024 /* USB Port 3 Output Control register */ +#define UDCCSRn(x) (0x0100 + ((x)<<2)) /* UDC Control/Status register */ +#define UDCBCRn(x) (0x0200 + ((x)<<2)) /* UDC Byte Count Register */ +#define UDCDRn(x) (0x0300 + ((x)<<2)) /* UDC Data Register */ +#define UDCCRn(x) (0x0400 + ((x)<<2)) /* UDC Control Register */ + +#define UDCCR_OEN (1 << 31) /* On-the-Go Enable */ +#define UDCCR_AALTHNP (1 << 30) /* A-device Alternate Host Negotiation + Protocol Port Support */ +#define UDCCR_AHNP (1 << 29) /* A-device Host Negotiation Protocol + Support */ +#define UDCCR_BHNP (1 << 28) /* B-device Host Negotiation Protocol + Enable */ +#define UDCCR_DWRE (1 << 16) /* Device Remote Wake-up Enable */ +#define UDCCR_ACN (0x03 << 11) /* Active UDC configuration Number */ +#define UDCCR_ACN_S 11 +#define UDCCR_AIN (0x07 << 8) /* Active UDC interface Number */ +#define UDCCR_AIN_S 8 +#define UDCCR_AAISN (0x07 << 5) /* Active UDC Alternate Interface + Setting Number */ +#define UDCCR_AAISN_S 5 +#define UDCCR_SMAC (1 << 4) /* Switch Endpoint Memory to Active + Configuration */ +#define UDCCR_EMCE (1 << 3) /* Endpoint Memory Configuration + Error */ +#define UDCCR_UDR (1 << 2) /* UDC Resume */ +#define UDCCR_UDA (1 << 1) /* UDC Active */ +#define UDCCR_UDE (1 << 0) /* UDC Enable */ + +#define UDCICR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2)) +#define UDCICR1_IECC (1 << 31) /* IntEn - Configuration Change */ +#define UDCICR1_IESOF (1 << 30) /* IntEn - Start of Frame */ +#define UDCICR1_IERU (1 << 29) /* IntEn - Resume */ +#define UDCICR1_IESU (1 << 28) /* IntEn - Suspend */ +#define UDCICR1_IERS (1 << 27) /* IntEn - Reset */ +#define UDCICR_FIFOERR (1 << 1) /* FIFO Error interrupt for EP */ +#define UDCICR_PKTCOMPL (1 << 0) /* Packet Complete interrupt for EP */ +#define UDCICR_INT_MASK (UDCICR_FIFOERR | UDCICR_PKTCOMPL) + +#define UDCISR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2)) +#define UDCISR1_IRCC (1 << 31) /* IntReq - Configuration Change */ +#define UDCISR1_IRSOF (1 << 30) /* IntReq - Start of Frame */ +#define UDCISR1_IRRU (1 << 29) /* IntReq - Resume */ +#define UDCISR1_IRSU (1 << 28) /* IntReq - Suspend */ +#define UDCISR1_IRRS (1 << 27) /* IntReq - Reset */ +#define UDCISR_INT_MASK (UDCICR_FIFOERR | UDCICR_PKTCOMPL) + +#define UDCOTGICR_IESF (1 << 24) /* OTG SET_FEATURE command recvd */ +#define UDCOTGICR_IEXR (1 << 17) /* Extra Transceiver Interrupt + Rising Edge Interrupt Enable */ +#define UDCOTGICR_IEXF (1 << 16) /* Extra Transceiver Interrupt + Falling Edge Interrupt Enable */ +#define UDCOTGICR_IEVV40R (1 << 9) /* OTG Vbus Valid 4.0V Rising Edge + Interrupt Enable */ +#define UDCOTGICR_IEVV40F (1 << 8) /* OTG Vbus Valid 4.0V Falling Edge + Interrupt Enable */ +#define UDCOTGICR_IEVV44R (1 << 7) /* OTG Vbus Valid 4.4V Rising Edge + Interrupt Enable */ +#define UDCOTGICR_IEVV44F (1 << 6) /* OTG Vbus Valid 4.4V Falling Edge + Interrupt Enable */ +#define UDCOTGICR_IESVR (1 << 5) /* OTG Session Valid Rising Edge + Interrupt Enable */ +#define UDCOTGICR_IESVF (1 << 4) /* OTG Session Valid Falling Edge + Interrupt Enable */ +#define UDCOTGICR_IESDR (1 << 3) /* OTG A-Device SRP Detect Rising + Edge Interrupt Enable */ +#define UDCOTGICR_IESDF (1 << 2) /* OTG A-Device SRP Detect Falling + Edge Interrupt Enable */ +#define UDCOTGICR_IEIDR (1 << 1) /* OTG ID Change Rising Edge + Interrupt Enable */ +#define UDCOTGICR_IEIDF (1 << 0) /* OTG ID Change Falling Edge + Interrupt Enable */ + +/* Host Port 2 field bits */ +#define UP2OCR_CPVEN (1 << 0) /* Charge Pump Vbus Enable */ +#define UP2OCR_CPVPE (1 << 1) /* Charge Pump Vbus Pulse Enable */ + /* Transceiver enablers */ +#define UP2OCR_DPPDE (1 << 2) /* D+ Pull Down Enable */ +#define UP2OCR_DMPDE (1 << 3) /* D- Pull Down Enable */ +#define UP2OCR_DPPUE (1 << 4) /* D+ Pull Up Enable */ +#define UP2OCR_DMPUE (1 << 5) /* D- Pull Up Enable */ +#define UP2OCR_DPPUBE (1 << 6) /* D+ Pull Up Bypass Enable */ +#define UP2OCR_DMPUBE (1 << 7) /* D- Pull Up Bypass Enable */ +#define UP2OCR_EXSP (1 << 8) /* External Transceiver Speed Control */ +#define UP2OCR_EXSUS (1 << 9) /* External Transceiver Speed Enable */ +#define UP2OCR_IDON (1 << 10) /* OTG ID Read Enable */ +#define UP2OCR_HXS (1 << 16) /* Transceiver Output Select */ +#define UP2OCR_HXOE (1 << 17) /* Transceiver Output Enable */ +#define UP2OCR_SEOS (1 << 24) /* Single-Ended Output Select */ + +#define UDCCSR0_ACM (1 << 9) /* Ack Control Mode */ +#define UDCCSR0_AREN (1 << 8) /* Ack Response Enable */ +#define UDCCSR0_SA (1 << 7) /* Setup Active */ +#define UDCCSR0_RNE (1 << 6) /* Receive FIFO Not Empty */ +#define UDCCSR0_FST (1 << 5) /* Force Stall */ +#define UDCCSR0_SST (1 << 4) /* Sent Stall */ +#define UDCCSR0_DME (1 << 3) /* DMA Enable */ +#define UDCCSR0_FTF (1 << 2) /* Flush Transmit FIFO */ +#define UDCCSR0_IPR (1 << 1) /* IN Packet Ready */ +#define UDCCSR0_OPC (1 << 0) /* OUT Packet Complete */ + +#define UDCCSR_DPE (1 << 9) /* Data Packet Error */ +#define UDCCSR_FEF (1 << 8) /* Flush Endpoint FIFO */ +#define UDCCSR_SP (1 << 7) /* Short Packet Control/Status */ +#define UDCCSR_BNE (1 << 6) /* Buffer Not Empty (IN endpoints) */ +#define UDCCSR_BNF (1 << 6) /* Buffer Not Full (OUT endpoints) */ +#define UDCCSR_FST (1 << 5) /* Force STALL */ +#define UDCCSR_SST (1 << 4) /* Sent STALL */ +#define UDCCSR_DME (1 << 3) /* DMA Enable */ +#define UDCCSR_TRN (1 << 2) /* Tx/Rx NAK */ +#define UDCCSR_PC (1 << 1) /* Packet Complete */ +#define UDCCSR_FS (1 << 0) /* FIFO needs service */ + +#define UDCCONR_CN (0x03 << 25) /* Configuration Number */ +#define UDCCONR_CN_S 25 +#define UDCCONR_IN (0x07 << 22) /* Interface Number */ +#define UDCCONR_IN_S 22 +#define UDCCONR_AISN (0x07 << 19) /* Alternate Interface Number */ +#define UDCCONR_AISN_S 19 +#define UDCCONR_EN (0x0f << 15) /* Endpoint Number */ +#define UDCCONR_EN_S 15 +#define UDCCONR_ET (0x03 << 13) /* Endpoint Type: */ +#define UDCCONR_ET_S 13 +#define UDCCONR_ET_INT (0x03 << 13) /* Interrupt */ +#define UDCCONR_ET_BULK (0x02 << 13) /* Bulk */ +#define UDCCONR_ET_ISO (0x01 << 13) /* Isochronous */ +#define UDCCONR_ET_NU (0x00 << 13) /* Not used */ +#define UDCCONR_ED (1 << 12) /* Endpoint Direction */ +#define UDCCONR_MPS (0x3ff << 2) /* Maximum Packet Size */ +#define UDCCONR_MPS_S 2 +#define UDCCONR_DE (1 << 1) /* Double Buffering Enable */ +#define UDCCONR_EE (1 << 0) /* Endpoint Enable */ + +#define UDCCR_MASK_BITS (UDCCR_OEN | UDCCR_SMAC | UDCCR_UDR | UDCCR_UDE) +#define UDCCSR_WR_MASK (UDCCSR_DME | UDCCSR_FST) +#define UDC_FNR_MASK (0x7ff) +#define UDC_BCR_MASK (0x3ff) + +/* + * UDCCR = UDC Endpoint Configuration Registers + * UDCCSR = UDC Control/Status Register for this EP + * UDCBCR = UDC Byte Count Remaining (contents of OUT fifo) + * UDCDR = UDC Endpoint Data Register (the fifo) + */ +#define ofs_UDCCR(ep) (UDCCRn(ep->idx)) +#define ofs_UDCCSR(ep) (UDCCSRn(ep->idx)) +#define ofs_UDCBCR(ep) (UDCBCRn(ep->idx)) +#define ofs_UDCDR(ep) (UDCDRn(ep->idx)) + +/* Register access macros */ +#define udc_ep_readl(ep, reg) \ + readl((ep)->dev->regs + ofs_##reg(ep)) +#define udc_ep_writel(ep, reg, value) \ + writel((value), ep->dev->regs + ofs_##reg(ep)) +#define udc_ep_readb(ep, reg) \ + readb((ep)->dev->regs + ofs_##reg(ep)) +#define udc_ep_writeb(ep, reg, value) \ + writeb((value), ep->dev->regs + ofs_##reg(ep)) +#define udc_readl(dev, reg) \ + readl((dev)->regs + (reg)) +#define udc_writel(udc, reg, value) \ + writel((value), (udc)->regs + (reg)) + +#define UDCCSR_MASK (UDCCSR_FST | UDCCSR_DME) +#define UDCCISR0_EP_MASK (~0) +#define UDCCISR1_EP_MASK 0xffff +#define UDCCSR0_CTRL_REQ_MASK (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE) + +#define EPIDX(ep) (ep->idx) +#define EPADDR(ep) (ep->addr) +#define EPXFERTYPE(ep) (ep->type) +#define EPNAME(ep) (ep->name) +#define is_ep0(ep) (!ep->idx) +#define EPXFERTYPE_is_ISO(ep) (EPXFERTYPE(ep) == USB_ENDPOINT_XFER_ISOC) + +/* + * Endpoint definition helpers + */ +#define USB_EP_DEF(addr, bname, dir, type, maxpkt) \ +{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, }, \ + .desc = { .bEndpointAddress = addr | (dir ? USB_DIR_IN : 0), \ + .bmAttributes = type, \ + .wMaxPacketSize = maxpkt, }, \ + .dev = &memory \ +} +#define USB_EP_BULK(addr, bname, dir) \ + USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE) +#define USB_EP_ISO(addr, bname, dir) \ + USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE) +#define USB_EP_INT(addr, bname, dir) \ + USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE) +#define USB_EP_IN_BULK(n) USB_EP_BULK(n, "ep" #n "in-bulk", 1) +#define USB_EP_OUT_BULK(n) USB_EP_BULK(n, "ep" #n "out-bulk", 0) +#define USB_EP_IN_ISO(n) USB_EP_ISO(n, "ep" #n "in-iso", 1) +#define USB_EP_OUT_ISO(n) USB_EP_ISO(n, "ep" #n "out-iso", 0) +#define USB_EP_IN_INT(n) USB_EP_INT(n, "ep" #n "in-int", 1) +#define USB_EP_CTRL USB_EP_DEF(0, "ep0", 0, 0, EP0_FIFO_SIZE) + +#define PXA_EP_DEF(_idx, _addr, dir, _type, maxpkt, _config, iface, altset) \ +{ \ + .dev = &memory, \ + .name = "ep" #_idx, \ + .idx = _idx, .enabled = 0, \ + .dir_in = dir, .addr = _addr, \ + .config = _config, .interface = iface, .alternate = altset, \ + .type = _type, .fifo_size = maxpkt, \ +} +#define PXA_EP_BULK(_idx, addr, dir, config, iface, alt) \ + PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE, \ + config, iface, alt) +#define PXA_EP_ISO(_idx, addr, dir, config, iface, alt) \ + PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE, \ + config, iface, alt) +#define PXA_EP_INT(_idx, addr, dir, config, iface, alt) \ + PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE, \ + config, iface, alt) +#define PXA_EP_IN_BULK(i, adr, c, f, a) PXA_EP_BULK(i, adr, 1, c, f, a) +#define PXA_EP_OUT_BULK(i, adr, c, f, a) PXA_EP_BULK(i, adr, 0, c, f, a) +#define PXA_EP_IN_ISO(i, adr, c, f, a) PXA_EP_ISO(i, adr, 1, c, f, a) +#define PXA_EP_OUT_ISO(i, adr, c, f, a) PXA_EP_ISO(i, adr, 0, c, f, a) +#define PXA_EP_IN_INT(i, adr, c, f, a) PXA_EP_INT(i, adr, 1, c, f, a) +#define PXA_EP_CTRL PXA_EP_DEF(0, 0, 0, 0, EP0_FIFO_SIZE, 0, 0, 0) + +struct pxa27x_udc; + +struct stats { + unsigned long in_ops; + unsigned long out_ops; + unsigned long in_bytes; + unsigned long out_bytes; + unsigned long irqs; +}; + +/** + * struct udc_usb_ep - container of each usb_ep structure + * @usb_ep: usb endpoint + * @desc: usb descriptor, especially type and address + * @dev: udc managing this endpoint + * @pxa_ep: matching pxa_ep (cache of find_pxa_ep() call) + */ +struct udc_usb_ep { + struct usb_ep usb_ep; + struct usb_endpoint_descriptor desc; + struct pxa_udc *dev; + struct pxa_ep *pxa_ep; +}; + +struct pxa_ep { + struct pxa_udc *dev; + + struct list_head queue; + unsigned enabled:1; + + unsigned idx:5; + char *name; + + /* + * Specific pxa endpoint data, needed for hardware initialization + */ + unsigned dir_in:1; + unsigned addr:4; + unsigned config:2; + unsigned interface:3; + unsigned alternate:3; + unsigned fifo_size; + unsigned type; +}; + +struct pxa27x_request { + struct usb_request req; + struct udc_usb_ep *udc_usb_ep; + unsigned in_use:1; + struct list_head queue; +}; + +enum ep0_state { + WAIT_FOR_SETUP, + SETUP_STAGE, + IN_DATA_STAGE, + OUT_DATA_STAGE, + IN_STATUS_STAGE, + OUT_STATUS_STAGE, + STALL, + WAIT_ACK_SET_CONF_INTERF +}; + +static char *ep0_state_name[] = { + "WAIT_FOR_SETUP", "SETUP_STAGE", "IN_DATA_STAGE", "OUT_DATA_STAGE", + "IN_STATUS_STAGE", "OUT_STATUS_STAGE", "STALL", + "WAIT_ACK_SET_CONF_INTERF" +}; +#define EP0_STNAME(udc) ep0_state_name[(udc)->ep0state] + +#define EP0_FIFO_SIZE 16U +#define BULK_FIFO_SIZE 64U +#define ISO_FIFO_SIZE 256U +#define INT_FIFO_SIZE 16U + +struct udc_stats { + unsigned long irqs_reset; + unsigned long irqs_suspend; + unsigned long irqs_resume; + unsigned long irqs_reconfig; +}; + +#define NR_USB_ENDPOINTS (1 + 5) /* ep0 + ep1in-bulk + .. + ep3in-iso */ +#define NR_PXA_ENDPOINTS (1 + 14) /* ep0 + epA + epB + .. + epX */ + +struct pxa_udc { + void __iomem *regs; + int irq; + struct clk *clk; + struct device_d *dev; + + struct usb_gadget gadget; + struct usb_gadget_driver *driver; + struct pxa2xx_udc_mach_info *mach; + + enum ep0_state ep0state; + struct udc_stats stats; + + struct udc_usb_ep udc_usb_ep[NR_USB_ENDPOINTS]; + struct pxa_ep pxa_ep[NR_PXA_ENDPOINTS]; + + unsigned enabled:1; + unsigned pullup_on:1; + unsigned pullup_resume:1; + unsigned vbus_sensed:1; + unsigned config:2; + unsigned last_interface:3; + unsigned last_alternate:3; + +}; + +static inline struct pxa_udc *to_gadget_udc(struct usb_gadget *gadget) +{ + return container_of(gadget, struct pxa_udc, gadget); +} + +/* + * Debugging/message support + */ +#define ep_dbg(ep, fmt, arg...) \ + dev_dbg(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg) +#define ep_vdbg(ep, fmt, arg...) \ + dev_dbg(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg) +#define ep_err(ep, fmt, arg...) \ + dev_err(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg) +#define ep_info(ep, fmt, arg...) \ + dev_info(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg) +#define ep_warn(ep, fmt, arg...) \ + dev_warn(ep->dev->dev, "%s:%s:" fmt, EPNAME(ep), __func__, ## arg) + +#endif /* __LINUX_USB_GADGET_PXA27X_H */ -- cgit v1.2.3 From 34e5b6029f05884b0dbabeb74183438c8168da6a Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Thu, 24 Nov 2011 04:01:28 +0100 Subject: usb/gadget: use generic usb_gadget_poll() in u_serial Use the generic gadget polling function instead of the specific fsl function. This is a fix from a leftover in gadget development. Signed-off-by: Robert Jarzmik Signed-off-by: Sascha Hauer --- drivers/usb/gadget/u_serial.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index d3baed74de..8c2c8fa132 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -382,7 +382,7 @@ static void serial_putc(struct console_device *cdev, char c) status = usb_ep_queue(in, req); while (list_empty(pool)) - fsl_udc_irq(); + usb_gadget_poll(); } static int serial_tstc(struct console_device *cdev) @@ -475,7 +475,7 @@ static int do_mycdev(struct command *cmdtp, int argc, char *argv[]) printf("%c", i); mdelay(500); for (j = 0; j < 100; j++) - fsl_udc_irq(); + usb_gadget_poll(); } return 0; } @@ -522,4 +522,3 @@ printf("%s\n", __func__); gs_free_requests(gser->out, &port->read_pool); gs_free_requests(gser->in, &port->write_pool); } - -- cgit v1.2.3 From 8173427d8d95a021963a7d0b63d5399334392eb0 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Thu, 24 Nov 2011 04:01:29 +0100 Subject: usb/gadget: add USB serial connect and disconnect The serial gadget can only work if the serial function is properly connected on USB trigger (ie. on SET_CONFIGURATION or SET_INTERFACE USB message triggering set_alt() in composite.c). Make this connection and handle also the disconnection in f_serial. Signed-off-by: Robert Jarzmik Signed-off-by: Sascha Hauer --- drivers/usb/gadget/f_serial.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c index 5b7eb2c1c5..b93310573d 100644 --- a/drivers/usb/gadget/f_serial.c +++ b/drivers/usb/gadget/f_serial.c @@ -16,7 +16,6 @@ #include "gadget_chips.h" #include "u_serial.h" - /* * This function packages a simple "generic serial" port with no real * control mechanisms, just raw data transfer over two bulk endpoints. @@ -140,6 +139,7 @@ static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt) gser->hs.in, gser->fs.in); gser->port.out_desc = ep_choose(cdev->gadget, gser->hs.out, gser->fs.out); + gserial_connect(&gser->port, gser->port_num); } return 0; @@ -147,7 +147,10 @@ static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt) static void gser_disable(struct usb_function *f) { + struct f_gser *gser = func_to_gser(f); + DBG(cdev, "generic ttyGS%d deactivated\n", gser->port_num); + gserial_disconnect(&gser->port); } /*-------------------------------------------------------------------------*/ -- cgit v1.2.3 From 699a4a1eca1ba836159f1ce4dec440bc22b7f3e8 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Thu, 24 Nov 2011 04:01:30 +0100 Subject: usb/gadget: make serial gadget resistant to cable unplug As USB can have its cable plugged out anytime, make the serial gadget reliable in case of unplugging : - unregister the gadget_serial provided console - don't stay forever in the read loop if connection was cut This behaviour relies on correct implementation of usb_gadget_poll(), which should return an error if the USB cable was removed. Signed-off-by: Robert Jarzmik Signed-off-by: Sascha Hauer --- drivers/usb/gadget/u_serial.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 8c2c8fa132..49aedc23ef 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -367,12 +367,13 @@ static void serial_putc(struct console_device *cdev, char c) struct gs_port *port = container_of(cdev, struct gs_port, cdev); struct list_head *pool = &port->write_pool; - struct usb_ep *in = port->port_usb->in; + struct usb_ep *in; struct usb_request *req; int status; if (list_empty(pool)) return; + in = port->port_usb->in; req = list_entry(pool->next, struct usb_request, list); req->length = 1; @@ -381,8 +382,8 @@ static void serial_putc(struct console_device *cdev, char c) *(unsigned char *)req->buf = c; status = usb_ep_queue(in, req); - while (list_empty(pool)) - usb_gadget_poll(); + while (status >= 0 && list_empty(pool)) + status = usb_gadget_poll(); } static int serial_tstc(struct console_device *cdev) @@ -399,7 +400,10 @@ static int serial_getc(struct console_device *cdev) struct gs_port, cdev); unsigned char ch; - while (kfifo_getc(port->recv_fifo, &ch)); + if (!port->port_usb) + return -EIO; + while (kfifo_getc(port->recv_fifo, &ch)) + usb_gadget_poll(); return ch; } @@ -421,6 +425,10 @@ int gserial_connect(struct gserial *gser, u8 port_num) /* we "know" gserial_cleanup() hasn't been called */ port = ports[port_num].port; + /* In case of multiple activation (ie. multiple SET_INTERFACE) */ + if (port->port_usb) + return 0; + /* activate the endpoints */ status = usb_ep_enable(gser->in, gser->in_desc); if (status < 0) @@ -498,7 +506,9 @@ BAREBOX_CMD_END void gserial_disconnect(struct gserial *gser) { struct gs_port *port = gser->ioport; -printf("%s\n", __func__); + struct console_device *cdev; + + printf("%s\n", __func__); if (!port) return; @@ -518,7 +528,9 @@ printf("%s\n", __func__); gser->in->driver_data = NULL; /* finally, free any unused/unusable I/O buffers */ - gs_free_requests(gser->out, &port->read_pool); gs_free_requests(gser->in, &port->write_pool); + + cdev = &port->cdev; + console_unregister(cdev); } -- cgit v1.2.3 From 3bb6ee8dd530d01724ceb7c3d5bb68bd1898726a Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Mon, 5 Dec 2011 16:10:36 +0100 Subject: mci: add the probe parameter if any error happened during the probe as example today if the timeout happened we can not probe the SD card again Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Sascha Hauer --- drivers/mci/mci-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index 1da7aff048..e9fe87ca40 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -1380,7 +1380,7 @@ static int mci_probe(struct device_d *mci_dev) #ifdef CONFIG_MCI_STARTUP /* if enabled, probe the attached card immediately */ rc = mci_card_probe(mci_dev); - if (rc == -ENODEV) { + if (rc) { /* * If it fails, add the 'probe' parameter to give the user * a chance to insert a card and try again. Note: This may fail -- cgit v1.2.3 From 35c0475a6d85cbbc2ca3ff526c330dceee0c2215 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 6 Dec 2011 17:10:11 +0100 Subject: storage/usb.c: fix test_unit_ready This is needed for the ohci-at91 to work. In u-boot this function was transmitting a cmdlen of 12, by the initial commit. There are similar functions like usb_request_sense, usb_read_capacity nearby which also transmit 12 byte per default on u-boot, which probably also need a fix. Signed-off-by: Michael Grzeschik Signed-off-by: Sascha Hauer --- drivers/usb/storage/usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index ef07c54d60..865ba8ec47 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -96,8 +96,8 @@ static int usb_stor_test_unit_ready(ccb *srb, struct us_data *us) retries = 10; do { US_DEBUGP("SCSI_TST_U_RDY\n"); - memset(&srb->cmd[0], 0, 6); - srb->cmdlen = 6; + memset(&srb->cmd[0], 0, 12); + srb->cmdlen = 12; srb->cmd[0] = SCSI_TST_U_RDY; srb->datalen = 0; result = us->transport(srb, us); -- cgit v1.2.3 From f60f6c58e24fe0facb77e516b5b4f1acf7c36582 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 6 Dec 2011 17:10:12 +0100 Subject: atmel_mci: check for device id we use to address the right slot We have to check which sd card slot we use. The registered mmc_id is the the correct parameter for this. Signed-off-by: Michael Grzeschik Signed-off-by: Sascha Hauer --- drivers/mci/atmel_mci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mci/atmel_mci.c b/drivers/mci/atmel_mci.c index 4a29cad18f..15668fc78b 100644 --- a/drivers/mci/atmel_mci.c +++ b/drivers/mci/atmel_mci.c @@ -369,6 +369,8 @@ static void mci_set_ios(struct mci_host *mci, struct device_d *mci_dev, atmel_mci_writel(host, AT91_MCI_SDCR, AT91_MCI_SDCBUS_1BIT); break; } + atmel_mci_writel(host, AT91_MCI_SDCR, atmel_mci_readl(host, AT91_MCI_SDCR) + | host->hw_dev->id); if (clock) { atmel_set_clk_rate(host, clock); -- cgit v1.2.3 From 0cbda4e76aaa19157b35e50ec15bf3ded54c79ef Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 6 Dec 2011 17:10:13 +0100 Subject: at91sam9260_devices: properly set slot id Signed-off-by: Michael Grzeschik Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/at91sam9260_devices.c | 34 ++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 9d1acda7fe..177f770816 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -261,18 +261,32 @@ void at91_add_device_mci(short mmc_id, struct atmel_mci_platform_data *data) /* CLK */ at91_set_A_periph(AT91_PIN_PA8, 0); - /* CMD */ - at91_set_A_periph(AT91_PIN_PA7, 1); - - /* DAT0, maybe DAT1..DAT3 */ - at91_set_A_periph(AT91_PIN_PA6, 1); - if (data->bus_width == 4) { - at91_set_A_periph(AT91_PIN_PA9, 1); - at91_set_A_periph(AT91_PIN_PA10, 1); - at91_set_A_periph(AT91_PIN_PA11, 1); + + if (mmc_id == 0) { + /* CMD */ + at91_set_A_periph(AT91_PIN_PA7, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA6, 1); + if (data->bus_width == 4) { + at91_set_A_periph(AT91_PIN_PA9, 1); + at91_set_A_periph(AT91_PIN_PA10, 1); + at91_set_A_periph(AT91_PIN_PA11, 1); + } + } else if (mmc_id == 1) { + /* CMD */ + at91_set_B_periph(AT91_PIN_PA1, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_B_periph(AT91_PIN_PA0, 1); + if (data->bus_width == 4) { + at91_set_B_periph(AT91_PIN_PA3, 1); + at91_set_B_periph(AT91_PIN_PA4, 1); + at91_set_B_periph(AT91_PIN_PA5, 1); + } } - dev = add_generic_device("atmel_mci", 0, NULL, AT91SAM9260_BASE_MCI, SZ_16K, + dev = add_generic_device("atmel_mci", mmc_id, NULL, AT91SAM9260_BASE_MCI, SZ_16K, IORESOURCE_MEM, data); } #else -- cgit v1.2.3 From 1a46f8b6d4ffb5a223897c0605d060b6dc5f794e Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 6 Dec 2011 17:10:14 +0100 Subject: at91sam9260_devices: add flag to change ETX{2,3} pincfg on add_device_eth Signed-off-by: Michael Grzeschik Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/at91sam9260_devices.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 177f770816..be1fdd927e 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -63,8 +63,13 @@ void at91_add_device_eth(struct at91_ether_platform_data *data) at91_set_B_periph(AT91_PIN_PA25, 0); /* ERX2 */ at91_set_B_periph(AT91_PIN_PA26, 0); /* ERX3 */ at91_set_B_periph(AT91_PIN_PA27, 0); /* ERXCK */ - at91_set_B_periph(AT91_PIN_PA23, 0); /* ETX2 */ - at91_set_B_periph(AT91_PIN_PA24, 0); /* ETX3 */ + if (data->flags & AT91SAM_ETX2_ETX3_ALTERNATIVE) { + at91_set_B_periph(AT91_PIN_PA10, 0); /* ETX2 */ + at91_set_B_periph(AT91_PIN_PA11, 0); /* ETX3 */ + } else { + at91_set_B_periph(AT91_PIN_PA23, 0); /* ETX2 */ + at91_set_B_periph(AT91_PIN_PA24, 0); /* ETX3 */ + } at91_set_B_periph(AT91_PIN_PA22, 0); /* ETXER */ } -- cgit v1.2.3 From ffec9ea1c73d0ba173bd6c419e80fc2daa4a5e42 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 6 Dec 2011 17:10:15 +0100 Subject: arm: update mach-types Signed-off-by: Michael Grzeschik Signed-off-by: Sascha Hauer --- arch/arm/tools/mach-types | 473 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 460 insertions(+), 13 deletions(-) diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 35acbf0424..d5930268c8 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,7 +12,7 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Wed Mar 30 09:36:58 2011 +# Last update: Tue Dec 6 15:54:16 2011 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -1319,6 +1319,7 @@ mistral MACH_MISTRAL MISTRAL 1315 msm MACH_MSM MSM 1316 ct5910 MACH_CT5910 CT5910 1317 ct5912 MACH_CT5912 CT5912 1318 +argonst_mp MACH_HYNET_INE HYNET_INE 1319 hynet_app MACH_HYNET_APP HYNET_APP 1320 msm7200 MACH_MSM7200 MSM7200 1321 msm7600 MACH_MSM7600 MSM7600 1322 @@ -1557,7 +1558,7 @@ otter MACH_OTTER OTTER 1561 davinci_ldk MACH_DAVINCI_LDK DAVINCI_LDK 1562 phreedom MACH_PHREEDOM PHREEDOM 1563 sg310 MACH_SG310 SG310 1564 -ts_x09 MACH_TS209 TS209 1565 +ts209 MACH_TS209 TS209 1565 at91cap9adk MACH_AT91CAP9ADK AT91CAP9ADK 1566 tion9315 MACH_TION9315 TION9315 1567 mast MACH_MAST MAST 1568 @@ -1960,7 +1961,7 @@ ethernut5 MACH_ETHERNUT5 ETHERNUT5 1971 arm11 MACH_ARM11 ARM11 1972 cpuat9260 MACH_CPUAT9260 CPUAT9260 1973 cpupxa255 MACH_CPUPXA255 CPUPXA255 1974 -eukrea_cpuimx27 MACH_CPUIMX27 CPUIMX27 1975 +eukrea_cpuimx27 MACH_EUKREA_CPUIMX27 EUKREA_CPUIMX27 1975 cheflux MACH_CHEFLUX CHEFLUX 1976 eb_cpux9k2 MACH_EB_CPUX9K2 EB_CPUX9K2 1977 opcotec MACH_OPCOTEC OPCOTEC 1978 @@ -2554,6 +2555,7 @@ magnolia2 MACH_MAGNOLIA2 MAGNOLIA2 2573 emxx MACH_EMXX EMXX 2574 outlaw MACH_OUTLAW OUTLAW 2575 riot_bei2 MACH_RIOT_BEI2 RIOT_BEI2 2576 +riot_gx2 MACH_RIOT_VOX RIOT_VOX 2577 riot_x37 MACH_RIOT_X37 RIOT_X37 2578 mega25mx MACH_MEGA25MX MEGA25MX 2579 benzina2 MACH_BENZINA2 BENZINA2 2580 @@ -2567,7 +2569,7 @@ p3600 MACH_P3600 P3600 2587 dlt2 MACH_DLT2 DLT2 2588 df3120 MACH_DF3120 DF3120 2589 ecucore_9g20 MACH_ECUCORE_9G20 ECUCORE_9G20 2590 -nautel_lpc3240 MACH_NAUTEL_LPC3240 NAUTEL_LPC3240 2591 +nautel_am35xx MACH_NAUTEL_LPC3240 NAUTEL_LPC3240 2591 glacier MACH_GLACIER GLACIER 2592 phrazer_bulldog MACH_PHRAZER_BULLDOG PHRAZER_BULLDOG 2593 omap3_bulldog MACH_OMAP3_BULLDOG OMAP3_BULLDOG 2594 @@ -2599,7 +2601,7 @@ fujitsu_tvstbsoc1 MACH_FUJITSU_TVSTBSOC1 FUJITSU_TVSTBSOC1 2621 lexikon MACH_LEXIKON LEXIKON 2622 mini2440v2 MACH_MINI2440V2 MINI2440V2 2623 icontrol MACH_ICONTROL ICONTROL 2624 -gplugd MACH_SHEEVAD SHEEVAD 2625 +gplugd MACH_GPLUGD GPLUGD 2625 qsd8x50a_st1_1 MACH_QSD8X50A_ST1_1 QSD8X50A_ST1_1 2626 qsd8x50a_st1_5 MACH_QSD8X50A_ST1_5 QSD8X50A_ST1_5 2627 bee MACH_BEE BEE 2628 @@ -2652,7 +2654,7 @@ htcpanther_cdma MACH_HTCPANTHER_CDMA HTCPANTHER_CDMA 2674 reb01 MACH_REB01 REB01 2675 aquila MACH_AQUILA AQUILA 2676 spark_sls_hw2 MACH_SPARK_SLS_HW2 SPARK_SLS_HW2 2677 -sheeva_esata MACH_ESATA_SHEEVAPLUG ESATA_SHEEVAPLUG 2678 +esata_sheevaplug MACH_ESATA_SHEEVAPLUG ESATA_SHEEVAPLUG 2678 msm7x30_surf MACH_MSM7X30_SURF MSM7X30_SURF 2679 micro2440 MACH_MICRO2440 MICRO2440 2680 am2440 MACH_AM2440 AM2440 2681 @@ -2724,7 +2726,7 @@ vpnext_mpu MACH_VPNEXT_MPU VPNEXT_MPU 2747 bcmring_tablet_v1 MACH_BCMRING_TABLET_V1 BCMRING_TABLET_V1 2748 sgarm10 MACH_SGARM10 SGARM10 2749 cm_t3517 MACH_CM_T3517 CM_T3517 2750 -omap3_cps MACH_OMAP3_CPS OMAP3_CPS 2751 +dig297 MACH_OMAP3_CPS OMAP3_CPS 2751 axar1500_receiver MACH_AXAR1500_RECEIVER AXAR1500_RECEIVER 2752 wbd222 MACH_WBD222 WBD222 2753 mt65xx MACH_MT65XX MT65XX 2754 @@ -2748,6 +2750,7 @@ oreo_controller MACH_OREO_CONTROLLER OREO_CONTROLLER 2773 kopin_models MACH_KOPIN_MODELS KOPIN_MODELS 2774 ttc_vision2 MACH_TTC_VISION2 TTC_VISION2 2775 cns3420vb MACH_CNS3420VB CNS3420VB 2776 +lpc_evo MACH_LPC2 LPC2 2777 olympus MACH_OLYMPUS OLYMPUS 2778 vortex MACH_VORTEX VORTEX 2779 s5pc200 MACH_S5PC200 S5PC200 2780 @@ -2789,8 +2792,8 @@ teton_bga MACH_TETON_BGA TETON_BGA 2816 snapper9g45 MACH_SNAPPER9G45 SNAPPER9G45 2817 tam3517 MACH_TAM3517 TAM3517 2818 pdc100 MACH_PDC100 PDC100 2819 -eukrea_cpuimx25sd MACH_EUKREA_CPUIMX25 EUKREA_CPUIMX25 2820 -eukrea_cpuimx35sd MACH_EUKREA_CPUIMX35 EUKREA_CPUIMX35 2821 +eukrea_cpuimx25sd MACH_EUKREA_CPUIMX25SD EUKREA_CPUIMX25SD 2820 +eukrea_cpuimx35sd MACH_EUKREA_CPUIMX35SD EUKREA_CPUIMX35SD 2821 eukrea_cpuimx51sd MACH_EUKREA_CPUIMX51SD EUKREA_CPUIMX51SD 2822 eukrea_cpuimx51 MACH_EUKREA_CPUIMX51 EUKREA_CPUIMX51 2823 p565 MACH_P565 P565 2824 @@ -3018,6 +3021,7 @@ s5pc110_crespo MACH_S5PC110_CRESPO S5PC110_CRESPO 3052 controltek9g20 MACH_CONTROLTEK9G20 CONTROLTEK9G20 3053 tin307 MACH_TIN307 TIN307 3054 tin510 MACH_TIN510 TIN510 3055 +ep3505 MACH_EP3517 EP3517 3056 bluecheese MACH_BLUECHEESE BLUECHEESE 3057 tem3x30 MACH_TEM3X30 TEM3X30 3058 harvest_desoto MACH_HARVEST_DESOTO HARVEST_DESOTO 3059 @@ -3236,7 +3240,7 @@ omapl138_case_a3 MACH_OMAPL138_CASE_A3 OMAPL138_CASE_A3 3280 uemd MACH_UEMD UEMD 3281 ccwmx51mut MACH_CCWMX51MUT CCWMX51MUT 3282 rockhopper MACH_ROCKHOPPER ROCKHOPPER 3283 -nookcolor MACH_NOOKCOLOR NOOKCOLOR 3284 +encore MACH_ENCORE ENCORE 3284 hkdkc100 MACH_HKDKC100 HKDKC100 3285 ts42xx MACH_TS42XX TS42XX 3286 aebl MACH_AEBL AEBL 3287 @@ -3247,9 +3251,9 @@ isc3 MACH_ISC3 ISC3 3291 rascal MACH_RASCAL RASCAL 3292 hrefv60 MACH_HREFV60 HREFV60 3293 tpt_2_0 MACH_TPT_2_0 TPT_2_0 3294 -pyramid_td MACH_PYRAMID_TD PYRAMID_TD 3295 +pydtd MACH_PYRAMID_TD PYRAMID_TD 3295 splendor MACH_SPLENDOR SPLENDOR 3296 -guf_planet MACH_GUF_PLANET GUF_PLANET 3297 +guf_vincell MACH_GUF_PLANET GUF_PLANET 3297 msm8x60_qt MACH_MSM8X60_QT MSM8X60_QT 3298 htc_hd_mini MACH_HTC_HD_MINI HTC_HD_MINI 3299 athene MACH_ATHENE ATHENE 3300 @@ -3348,7 +3352,7 @@ geneva_b5 MACH_GENEVA_B5 GENEVA_B5 3393 spear1340 MACH_SPEAR1340 SPEAR1340 3394 rexmas MACH_REXMAS REXMAS 3395 msm8960_cdp MACH_MSM8960_CDP MSM8960_CDP 3396 -msm8960_mdp MACH_MSM8960_MDP MSM8960_MDP 3397 +msm8960_mtp MACH_MSM8960_MDP MSM8960_MDP 3397 msm8960_fluid MACH_MSM8960_FLUID MSM8960_FLUID 3398 msm8960_apq MACH_MSM8960_APQ MSM8960_APQ 3399 helios_v2 MACH_HELIOS_V2 HELIOS_V2 3400 @@ -3396,3 +3400,446 @@ nuc740evb MACH_NUC740EVB NUC740EVB 3441 nuc745evb MACH_NUC745EVB NUC745EVB 3442 transcede MACH_TRANSCEDE TRANSCEDE 3443 mora MACH_MORA MORA 3444 +nda_evm MACH_NDA_EVM NDA_EVM 3445 +timu MACH_TIMU TIMU 3446 +expressh MACH_EXPRESSH EXPRESSH 3447 +veridis_a300 MACH_VERIDIS_A300 VERIDIS_A300 3448 +dm368_leopard MACH_DM368_LEOPARD DM368_LEOPARD 3449 +omap_mcop MACH_OMAP_MCOP OMAP_MCOP 3450 +tritip MACH_TRITIP TRITIP 3451 +sm1k MACH_SM1K SM1K 3452 +monch MACH_MONCH MONCH 3453 +curacao MACH_CURACAO CURACAO 3454 +origen MACH_ORIGEN ORIGEN 3455 +epc10 MACH_EPC10 EPC10 3456 +sgh_i740 MACH_SGH_I740 SGH_I740 3457 +tuna MACH_TUNA TUNA 3458 +mx51_tulip MACH_MX51_TULIP MX51_TULIP 3459 +mx51_aster7 MACH_MX51_ASTER7 MX51_ASTER7 3460 +acro37xbrd MACH_ACRO37XBRD ACRO37XBRD 3461 +elke MACH_ELKE ELKE 3462 +sbc6000x MACH_SBC6000X SBC6000X 3463 +r1801e MACH_R1801E R1801E 3464 +h1600 MACH_H1600 H1600 3465 +mini210 MACH_MINI210 MINI210 3466 +mini8168 MACH_MINI8168 MINI8168 3467 +pc7308 MACH_PC7308 PC7308 3468 +ge863pro3 MACH_GE863 GE863 3469 +kmm2m01 MACH_KMM2M01 KMM2M01 3470 +mx51erebus MACH_MX51EREBUS MX51EREBUS 3471 +wm8650refboard MACH_WM8650REFBOARD WM8650REFBOARD 3472 +tuxrail MACH_TUXRAIL TUXRAIL 3473 +arthur MACH_ARTHUR ARTHUR 3474 +doorboy MACH_DOORBOY DOORBOY 3475 +xarina MACH_XARINA XARINA 3476 +roverx7 MACH_ROVERX7 ROVERX7 3477 +sdvr MACH_SDVR SDVR 3478 +acer_maya MACH_ACER_MAYA ACER_MAYA 3479 +pico MACH_PICO PICO 3480 +cwmx233 MACH_CWMX233 CWMX233 3481 +cwam1808 MACH_CWAM1808 CWAM1808 3482 +cwdm365 MACH_CWDM365 CWDM365 3483 +mx51_moray MACH_MX51_MORAY MX51_MORAY 3484 +thales_cbc MACH_THALES_CBC THALES_CBC 3485 +bluepoint MACH_BLUEPOINT BLUEPOINT 3486 +dir665 MACH_DIR665 DIR665 3487 +acmerover1 MACH_ACMEROVER1 ACMEROVER1 3488 +shooter_ct MACH_SHOOTER_CT SHOOTER_CT 3489 +bliss MACH_BLISS BLISS 3490 +blissc MACH_BLISSC BLISSC 3491 +thales_adc MACH_THALES_ADC THALES_ADC 3492 +ubisys_p9d_evp MACH_UBISYS_P9D_EVP UBISYS_P9D_EVP 3493 +atdgp318 MACH_ATDGP318 ATDGP318 3494 +dma210u MACH_DMA210U DMA210U 3495 +em_t3 MACH_EM_T3 EM_T3 3496 +htx3250 MACH_HTX3250 HTX3250 3497 +g50 MACH_G50 G50 3498 +eco5 MACH_ECO5 ECO5 3499 +wintergrasp MACH_WINTERGRASP WINTERGRASP 3500 +puro MACH_PURO PURO 3501 +shooter_k MACH_SHOOTER_K SHOOTER_K 3502 +nspire MACH_NSPIRE NSPIRE 3503 +mickxx MACH_MICKXX MICKXX 3504 +lxmb MACH_LXMB LXMB 3505 +tmdxscbp6618x MACH_TMDXSCBP6616X TMDXSCBP6616X 3506 +adam MACH_ADAM ADAM 3507 +b1004 MACH_B1004 B1004 3508 +oboea MACH_OBOEA OBOEA 3509 +a1015 MACH_A1015 A1015 3510 +robin_vbdt30 MACH_ROBIN_VBDT30 ROBIN_VBDT30 3511 +tegra_enterprise MACH_TEGRA_ENTERPRISE TEGRA_ENTERPRISE 3512 +rfl108200_mk10 MACH_RFL108200_MK10 RFL108200_MK10 3513 +rfl108300_mk16 MACH_RFL108300_MK16 RFL108300_MK16 3514 +rover_v7 MACH_ROVER_V7 ROVER_V7 3515 +miphone MACH_MIPHONE MIPHONE 3516 +femtobts MACH_FEMTOBTS FEMTOBTS 3517 +monopoli MACH_MONOPOLI MONOPOLI 3518 +boss MACH_BOSS BOSS 3519 +davinci_dm368_vtam MACH_DAVINCI_DM368_VTAM DAVINCI_DM368_VTAM 3520 +clcon MACH_CLCON CLCON 3521 +nokia_rm696 MACH_NOKIA_RM696 NOKIA_RM696 3522 +tahiti MACH_TAHITI TAHITI 3523 +fighter MACH_FIGHTER FIGHTER 3524 +sgh_i710 MACH_SGH_I710 SGH_I710 3525 +integreproscb MACH_INTEGREPROSCB INTEGREPROSCB 3526 +monza MACH_MONZA MONZA 3527 +calimain MACH_CALIMAIN CALIMAIN 3528 +mx6q_sabreauto MACH_MX6Q_SABREAUTO MX6Q_SABREAUTO 3529 +gma01x MACH_GMA01X GMA01X 3530 +sbc51 MACH_SBC51 SBC51 3531 +fit MACH_FIT FIT 3532 +steelhead MACH_STEELHEAD STEELHEAD 3533 +panther MACH_PANTHER PANTHER 3534 +msm8960_liquid MACH_MSM8960_LIQUID MSM8960_LIQUID 3535 +lexikonct MACH_LEXIKONCT LEXIKONCT 3536 +ns2816_stb MACH_NS2816_STB NS2816_STB 3537 +sei_mm2_lpc3250 MACH_SEI_MM2_LPC3250 SEI_MM2_LPC3250 3538 +cmimx53 MACH_CMIMX53 CMIMX53 3539 +sandwich MACH_SANDWICH SANDWICH 3540 +chief MACH_CHIEF CHIEF 3541 +pogo_e02 MACH_POGO_E02 POGO_E02 3542 +mikrap_x168 MACH_MIKRAP_X168 MIKRAP_X168 3543 +htcmozart MACH_HTCMOZART HTCMOZART 3544 +htcgold MACH_HTCGOLD HTCGOLD 3545 +mt72xx MACH_MT72XX MT72XX 3546 +mx51_ivy MACH_MX51_IVY MX51_IVY 3547 +mx51_lvd MACH_MX51_LVD MX51_LVD 3548 +omap3_wiser2 MACH_OMAP3_WISER2 OMAP3_WISER2 3549 +dreamplug MACH_DREAMPLUG DREAMPLUG 3550 +cobas_c_111 MACH_COBAS_C_111 COBAS_C_111 3551 +cobas_u_411 MACH_COBAS_U_411 COBAS_U_411 3552 +hssd MACH_HSSD HSSD 3553 +iom35x MACH_IOM35X IOM35X 3554 +psom_omap MACH_PSOM_OMAP PSOM_OMAP 3555 +iphone_2g MACH_IPHONE_2G IPHONE_2G 3556 +iphone_3g MACH_IPHONE_3G IPHONE_3G 3557 +ipod_touch_1g MACH_IPOD_TOUCH_1G IPOD_TOUCH_1G 3558 +pharos_tpc MACH_PHAROS_TPC PHAROS_TPC 3559 +mx53_hydra MACH_MX53_HYDRA MX53_HYDRA 3560 +ns2816_dev_board MACH_NS2816_DEV_BOARD NS2816_DEV_BOARD 3561 +iphone_3gs MACH_IPHONE_3GS IPHONE_3GS 3562 +iphone_4 MACH_IPHONE_4 IPHONE_4 3563 +ipod_touch_4g MACH_IPOD_TOUCH_4G IPOD_TOUCH_4G 3564 +dragon_e1100 MACH_DRAGON_E1100 DRAGON_E1100 3565 +topside MACH_TOPSIDE TOPSIDE 3566 +irisiii MACH_IRISIII IRISIII 3567 +deto_macarm9 MACH_DETO_MACARM9 DETO_MACARM9 3568 +eti_d1 MACH_ETI_D1 ETI_D1 3569 +som3530sdk MACH_SOM3530SDK SOM3530SDK 3570 +oc_engine MACH_OC_ENGINE OC_ENGINE 3571 +apq8064_sim MACH_APQ8064_SIM APQ8064_SIM 3572 +alps MACH_ALPS ALPS 3575 +tny_t3730 MACH_TNY_T3730 TNY_T3730 3576 +geryon_nfe MACH_GERYON_NFE GERYON_NFE 3577 +ns2816_ref_board MACH_NS2816_REF_BOARD NS2816_REF_BOARD 3578 +silverstone MACH_SILVERSTONE SILVERSTONE 3579 +mtt2440 MACH_MTT2440 MTT2440 3580 +ynicdb MACH_YNICDB YNICDB 3581 +bct MACH_BCT BCT 3582 +tuscan MACH_TUSCAN TUSCAN 3583 +xbt_sam9g45 MACH_XBT_SAM9G45 XBT_SAM9G45 3584 +enbw_cmc MACH_ENBW_CMC ENBW_CMC 3585 +msm8x60_dragon MACH_APQ8060_DRAGON APQ8060_DRAGON 3586 +ch104mx257 MACH_CH104MX257 CH104MX257 3587 +openpri MACH_OPENPRI OPENPRI 3588 +am335xevm MACH_AM335XEVM AM335XEVM 3589 +picodmb MACH_PICODMB PICODMB 3590 +waluigi MACH_WALUIGI WALUIGI 3591 +punicag7 MACH_PUNICAG7 PUNICAG7 3592 +ipad_1g MACH_IPAD_1G IPAD_1G 3593 +appletv_2g MACH_APPLETV_2G APPLETV_2G 3594 +mach_ecog45 MACH_MACH_ECOG45 MACH_ECOG45 3595 +ait_cam_enc_4xx MACH_AIT_CAM_ENC_4XX AIT_CAM_ENC_4XX 3596 +runnymede MACH_RUNNYMEDE RUNNYMEDE 3597 +play MACH_PLAY PLAY 3598 +hw90260 MACH_HW90260 HW90260 3599 +tagh MACH_TAGH TAGH 3600 +filbert MACH_FILBERT FILBERT 3601 +getinge_netcomv3 MACH_GETINGE_NETCOMV3 GETINGE_NETCOMV3 3602 +cw20 MACH_CW20 CW20 3603 +cinema MACH_CINEMA CINEMA 3604 +cinema_tea MACH_CINEMA_TEA CINEMA_TEA 3605 +cinema_coffee MACH_CINEMA_COFFEE CINEMA_COFFEE 3606 +cinema_juice MACH_CINEMA_JUICE CINEMA_JUICE 3607 +linux_pad MACH_THEPAD THEPAD 3608 +mx53_mirage2 MACH_MX53_MIRAGE2 MX53_MIRAGE2 3609 +mx53_efikasb MACH_MX53_EFIKASB MX53_EFIKASB 3610 +stm_b2000 MACH_STM_B2000 STM_B2000 3612 +m28evk MACH_M28EVK M28EVK 3613 +pda MACH_PDA PDA 3614 +meraki_mr58 MACH_MERAKI_MR58 MERAKI_MR58 3615 +kota2 MACH_KOTA2 KOTA2 3616 +letcool MACH_LETCOOL LETCOOL 3617 +mx27iat MACH_MX27IAT MX27IAT 3618 +apollo_td MACH_APOLLO_TD APOLLO_TD 3619 +arena MACH_ARENA ARENA 3620 +gsngateway MACH_GSNGATEWAY GSNGATEWAY 3621 +lf2000 MACH_LF2000 LF2000 3622 +bonito MACH_BONITO BONITO 3623 +asymptote MACH_ASYMPTOTE ASYMPTOTE 3624 +bst2brd MACH_BST2BRD BST2BRD 3625 +tx335s MACH_TX335S TX335S 3626 +pelco_tesla MACH_PELCO_TESLA PELCO_TESLA 3627 +rrhtestplat MACH_RRHTESTPLAT RRHTESTPLAT 3628 +vidtonic_pro MACH_VIDTONIC_PRO VIDTONIC_PRO 3629 +pl_apollo MACH_PL_APOLLO PL_APOLLO 3630 +pl_phoenix MACH_PL_PHOENIX PL_PHOENIX 3631 +m28cu3 MACH_M28CU3 M28CU3 3632 +vvbox_hd MACH_VVBOX_HD VVBOX_HD 3633 +coreware_sam9260_ MACH_COREWARE_SAM9260_ COREWARE_SAM9260_ 3634 +marmaduke MACH_MARMADUKE MARMADUKE 3635 +amg_xlcore_camera MACH_AMG_XLCORE_CAMERA AMG_XLCORE_CAMERA 3636 +omap3_egf MACH_OMAP3_EGF OMAP3_EGF 3637 +smdk4212 MACH_SMDK4212 SMDK4212 3638 +dnp9200 MACH_DNP9200 DNP9200 3639 +tf101 MACH_TF101 TF101 3640 +omap3silvio MACH_OMAP3SILVIO OMAP3SILVIO 3641 +picasso2 MACH_PICASSO2 PICASSO2 3642 +vangogh2 MACH_VANGOGH2 VANGOGH2 3643 +olpc_xo_1_75 MACH_OLPC_XO_1_75 OLPC_XO_1_75 3644 +gx400 MACH_GX400 GX400 3645 +gs300 MACH_GS300 GS300 3646 +acer_a9 MACH_ACER_A9 ACER_A9 3647 +vivow_evm MACH_VIVOW_EVM VIVOW_EVM 3648 +veloce_cxq MACH_VELOCE_CXQ VELOCE_CXQ 3649 +veloce_cxm MACH_VELOCE_CXM VELOCE_CXM 3650 +p1852 MACH_P1852 P1852 3651 +naxy100 MACH_NAXY100 NAXY100 3652 +taishan MACH_TAISHAN TAISHAN 3653 +touchlink MACH_TOUCHLINK TOUCHLINK 3654 +stm32f103ze MACH_STM32F103ZE STM32F103ZE 3655 +mcx MACH_MCX MCX 3656 +stm_nmhdk_fli7610 MACH_STM_NMHDK_FLI7610 STM_NMHDK_FLI7610 3657 +top28x MACH_TOP28X TOP28X 3658 +okl4vp_microvisor MACH_OKL4VP_MICROVISOR OKL4VP_MICROVISOR 3659 +pop MACH_POP POP 3660 +layer MACH_LAYER LAYER 3661 +trondheim MACH_TRONDHEIM TRONDHEIM 3662 +eva MACH_EVA EVA 3663 +trust_taurus MACH_TRUST_TAURUS TRUST_TAURUS 3664 +ns2816_huashan MACH_NS2816_HUASHAN NS2816_HUASHAN 3665 +ns2816_yangcheng MACH_NS2816_YANGCHENG NS2816_YANGCHENG 3666 +p852 MACH_P852 P852 3667 +flea3 MACH_FLEA3 FLEA3 3668 +bowfin MACH_BOWFIN BOWFIN 3669 +mv88de3100 MACH_MV88DE3100 MV88DE3100 3670 +pia_am35x MACH_PIA_AM35X PIA_AM35X 3671 +cedar MACH_CEDAR CEDAR 3672 +picasso_e MACH_PICASSO_E PICASSO_E 3673 +samsung_e60 MACH_SAMSUNG_E60 SAMSUNG_E60 3674 +msm9615_cdp MACH_MDM9615 MDM9615 3675 +sdvr_mini MACH_SDVR_MINI SDVR_MINI 3676 +omap3_ij3k MACH_OMAP3_IJ3K OMAP3_IJ3K 3677 +modasmc1 MACH_MODASMC1 MODASMC1 3678 +apq8064_rumi3 MACH_APQ8064_RUMI3 APQ8064_RUMI3 3679 +matrix506 MACH_MATRIX506 MATRIX506 3680 +msm9615_mtp MACH_MSM9615_MTP MSM9615_MTP 3681 +dm36x_spawndc MACH_DM36X_SPAWNDC DM36X_SPAWNDC 3682 +sff792 MACH_SFF792 SFF792 3683 +am335xiaevm MACH_AM335XIAEVM AM335XIAEVM 3684 +g3c2440 MACH_G3C2440 G3C2440 3685 +tion270 MACH_TION270 TION270 3686 +w22q7arm02 MACH_W22Q7ARM02 W22Q7ARM02 3687 +omap_cat MACH_OMAP_CAT OMAP_CAT 3688 +at91sam9n12ek MACH_AT91SAM9N12EK AT91SAM9N12EK 3689 +morrison MACH_MORRISON MORRISON 3690 +svdu MACH_SVDU SVDU 3691 +lpp01 MACH_LPP01 LPP01 3692 +ubc283 MACH_UBC283 UBC283 3693 +zeppelin MACH_ZEPPELIN ZEPPELIN 3694 +motus MACH_MOTUS MOTUS 3695 +neomainboard MACH_NEOMAINBOARD NEOMAINBOARD 3696 +devkit3250 MACH_DEVKIT3250 DEVKIT3250 3697 +devkit7000 MACH_DEVKIT7000 DEVKIT7000 3698 +fmc_uic MACH_FMC_UIC FMC_UIC 3699 +fmc_dcm MACH_FMC_DCM FMC_DCM 3700 +batwm MACH_BATWM BATWM 3701 +atlas6cb MACH_ATLAS6CB ATLAS6CB 3702 +quattro_f MACH_QUATTROF QUATTROF 3703 +quattro_u MACH_QUATTROU QUATTROU 3704 +blue MACH_BLUE BLUE 3705 +colorado MACH_COLORADO COLORADO 3706 +popc MACH_POPC POPC 3707 +promwad_jade MACH_PROMWAD_JADE PROMWAD_JADE 3708 +amp MACH_AMP AMP 3709 +gnet_amp MACH_GNET_AMP GNET_AMP 3710 +toques MACH_TOQUES TOQUES 3711 +apx4devkit MACH_APX4 APX4 3712 +dct_storm MACH_DCT_STORM DCT_STORM 3713 +dm8168z3 MACH_Z3 Z3 3714 +owl MACH_OWL OWL 3715 +cogent_csb1741 MACH_COGENT_CSB1741 COGENT_CSB1741 3716 +omap3_kiko MACH_OMAP3 OMAP3 3717 +adillustra610 MACH_ADILLUSTRA610 ADILLUSTRA610 3718 +ecafe_na04 MACH_ECAFE_NA04 ECAFE_NA04 3719 +popct MACH_POPCT POPCT 3720 +omap3_helena MACH_OMAP3_HELENA OMAP3_HELENA 3721 +ach MACH_ACH ACH 3722 +module_dtb MACH_MODULE_DTB MODULE_DTB 3723 +ratebox MACH_RACKBOX RACKBOX 3724 +oslo_elisabeth MACH_OSLO_ELISABETH OSLO_ELISABETH 3725 +tt01 MACH_TT01 TT01 3726 +msm8930_cdp MACH_MSM8930_CDP MSM8930_CDP 3727 +msm8930_mtp MACH_MSM8930_MTP MSM8930_MTP 3728 +msm8930_fluid MACH_MSM8930_FLUID MSM8930_FLUID 3729 +ltu11 MACH_LTU11 LTU11 3730 +am1808_spawnco MACH_AM1808_SPAWNCO AM1808_SPAWNCO 3731 +flx6410 MACH_FLX6410 FLX6410 3732 +mx6q_qsb MACH_MX6Q_QSB MX6Q_QSB 3733 +mx53_plt424 MACH_MX53_PLT424 MX53_PLT424 3734 +jasmine MACH_JASMINE JASMINE 3735 +l138_owlboard_plus MACH_L138_OWLBOARD_PLUS L138_OWLBOARD_PLUS 3736 +wr21 MACH_WR21 WR21 3737 +peaboy MACH_PEABOY PEABOY 3739 +mx28_plato MACH_MX28_PLATO MX28_PLATO 3740 +kacom2 MACH_KACOM2 KACOM2 3741 +slco MACH_SLCO SLCO 3742 +imx51pico MACH_IMX51PICO IMX51PICO 3743 +glink1 MACH_GLINK1 GLINK1 3744 +diamond MACH_DIAMOND DIAMOND 3745 +d9000 MACH_D9000 D9000 3746 +w5300e01 MACH_W5300E01 W5300E01 3747 +im6000 MACH_IM6000 IM6000 3748 +mx51_fred51 MACH_MX51_FRED51 MX51_FRED51 3749 +stm32f2 MACH_STM32F2 STM32F2 3750 +ville MACH_VILLE VILLE 3751 +ptip_murnau MACH_PTIP_MURNAU PTIP_MURNAU 3752 +ptip_classic MACH_PTIP_CLASSIC PTIP_CLASSIC 3753 +mx53grb MACH_MX53GRB MX53GRB 3754 +gagarin MACH_GAGARIN GAGARIN 3755 +msm7627a_qrd1 MACH_MSM7X27A_QRD1 MSM7X27A_QRD1 3756 +nas2big MACH_NAS2BIG NAS2BIG 3757 +superfemto MACH_SUPERFEMTO SUPERFEMTO 3758 +teufel MACH_TEUFEL TEUFEL 3759 +dinara MACH_DINARA DINARA 3760 +vanquish MACH_VANQUISH VANQUISH 3761 +zipabox1 MACH_ZIPABOX1 ZIPABOX1 3762 +u9540 MACH_U9540 U9540 3763 +jet MACH_JET JET 3764 +smdk4412 MACH_SMDK4412 SMDK4412 3765 +elite MACH_ELITE ELITE 3766 +spear320_hmi MACH_SPEAR320_HMI SPEAR320_HMI 3767 +ontario MACH_ONTARIO ONTARIO 3768 +mx6q_sabrelite MACH_MX6Q_SABRELITE MX6Q_SABRELITE 3769 +vc200 MACH_VC200 VC200 3770 +msm7625a_ffa MACH_MSM7625A_FFA MSM7625A_FFA 3771 +msm7625a_surf MACH_MSM7625A_SURF MSM7625A_SURF 3772 +benthossbp MACH_BENTHOSSBP BENTHOSSBP 3773 +smdk5210 MACH_SMDK5210 SMDK5210 3774 +empq2300 MACH_EMPQ2300 EMPQ2300 3775 +minipos MACH_MINIPOS MINIPOS 3776 +omap5_sevm MACH_OMAP5_SEVM OMAP5_SEVM 3777 +shelter MACH_SHELTER SHELTER 3778 +omap3_devkit8500 MACH_OMAP3_DEVKIT8500 OMAP3_DEVKIT8500 3779 +edgetd MACH_EDGETD EDGETD 3780 +copperyard MACH_COPPERYARD COPPERYARD 3781 +edge MACH_EDGE EDGE 3782 +edge_u MACH_EDGE_U EDGE_U 3783 +edge_td MACH_EDGE_TD EDGE_TD 3784 +wdss MACH_WDSS WDSS 3785 +dl_pb25 MACH_DL_PB25 DL_PB25 3786 +dss11 MACH_DSS11 DSS11 3787 +cpa MACH_CPA CPA 3788 +aptp2000 MACH_APTP2000 APTP2000 3789 +marzen MACH_MARZEN MARZEN 3790 +st_turbine MACH_ST_TURBINE ST_TURBINE 3791 +gtl_it3300 MACH_GTL_IT3300 GTL_IT3300 3792 +mx6_mule MACH_MX6_MULE MX6_MULE 3793 +v7pxa_dt MACH_V7PXA_DT V7PXA_DT 3794 +v7mmp_dt MACH_V7MMP_DT V7MMP_DT 3795 +dragon7 MACH_DRAGON7 DRAGON7 3796 +krome MACH_KROME KROME 3797 +oratisdante MACH_ORATISDANTE ORATISDANTE 3798 +fathom MACH_FATHOM FATHOM 3799 +dns325 MACH_DNS325 DNS325 3800 +sarnen MACH_SARNEN SARNEN 3801 +ubisys_g1 MACH_UBISYS_G1 UBISYS_G1 3802 +mx53_pf1 MACH_MX53_PF1 MX53_PF1 3803 +asanti MACH_ASANTI ASANTI 3804 +volta MACH_VOLTA VOLTA 3805 +potenza MACH_S5P6450 S5P6450 3806 +knight MACH_KNIGHT KNIGHT 3807 +beaglebone MACH_BEAGLEBONE BEAGLEBONE 3808 +becker MACH_BECKER BECKER 3809 +fc360 MACH_FC360 FC360 3810 +pmi2_xls MACH_PMI2_XLS PMI2_XLS 3811 +taranto MACH_TARANTO TARANTO 3812 +plutux MACH_PLUTUX PLUTUX 3813 +ipmp_medcom MACH_IPMP_MEDCOM IPMP_MEDCOM 3814 +absolut MACH_ABSOLUT ABSOLUT 3815 +awpb3 MACH_AWPB3 AWPB3 3816 +nfp32xx_dt MACH_NFP32XX_DT NFP32XX_DT 3817 +dl_pb53 MACH_DL_PB53 DL_PB53 3818 +acu_ii MACH_ACU_II ACU_II 3819 +avalon MACH_AVALON AVALON 3820 +sphinx MACH_SPHINX SPHINX 3821 +titan_t MACH_TITAN_T TITAN_T 3822 +harvest_boris MACH_HARVEST_BORIS HARVEST_BORIS 3823 +mach_msm7x30_m3s MACH_MACH_MSM7X30_M3S MACH_MSM7X30_M3S 3824 +smdk5250 MACH_SMDK5250 SMDK5250 3825 +imxt_lite MACH_IMXT_LITE IMXT_LITE 3826 +imxt_std MACH_IMXT_STD IMXT_STD 3827 +imxt_log MACH_IMXT_LOG IMXT_LOG 3828 +imxt_nav MACH_IMXT_NAV IMXT_NAV 3829 +imxt_full MACH_IMXT_FULL IMXT_FULL 3830 +ag09015 MACH_AG09015 AG09015 3831 +am3517_mt_ventoux MACH_AM3517_MT_VENTOUX AM3517_MT_VENTOUX 3832 +dp1arm9 MACH_DP1ARM9 DP1ARM9 3833 +picasso_m MACH_PICASSO_M PICASSO_M 3834 +video_gadget MACH_VIDEO_GADGET VIDEO_GADGET 3835 +mtt_om3x MACH_MTT_OM3X MTT_OM3X 3836 +mx6q_arm2 MACH_MX6Q_ARM2 MX6Q_ARM2 3837 +picosam9g45 MACH_PICOSAM9G45 PICOSAM9G45 3838 +vpm_dm365 MACH_VPM_DM365 VPM_DM365 3839 +bonfire MACH_BONFIRE BONFIRE 3840 +mt2p2d MACH_MT2P2D MT2P2D 3841 +sigpda01 MACH_SIGPDA01 SIGPDA01 3842 +cn27 MACH_CN27 CN27 3843 +mx25_cwtap MACH_MX25_CWTAP MX25_CWTAP 3844 +apf28 MACH_APF28 APF28 3845 +pelco_maxwell MACH_PELCO_MAXWELL PELCO_MAXWELL 3846 +ge_phoenix MACH_GE_PHOENIX GE_PHOENIX 3847 +empc_a500 MACH_EMPC_A500 EMPC_A500 3848 +ims_arm9 MACH_IMS_ARM9 IMS_ARM9 3849 +mini2416 MACH_MINI2416 MINI2416 3850 +mini2450 MACH_MINI2450 MINI2450 3851 +mini310 MACH_MINI310 MINI310 3852 +spear_hurricane MACH_SPEAR_HURRICANE SPEAR_HURRICANE 3853 +mt7208 MACH_MT7208 MT7208 3854 +lpc178x MACH_LPC178X LPC178X 3855 +farleys MACH_FARLEYS FARLEYS 3856 +efm32gg_dk3750 MACH_EFM32GG_DK3750 EFM32GG_DK3750 3857 +zeus_board MACH_ZEUS_BOARD ZEUS_BOARD 3858 +cc51 MACH_CC51 CC51 3859 +fxi_c210 MACH_FXI_C210 FXI_C210 3860 +msm8627_cdp MACH_MSM8627_CDP MSM8627_CDP 3861 +msm8627_mtp MACH_MSM8627_MTP MSM8627_MTP 3862 +armadillo800eva MACH_ARMADILLO800EVA ARMADILLO800EVA 3863 +primou MACH_PRIMOU PRIMOU 3864 +primoc MACH_PRIMOC PRIMOC 3865 +primoct MACH_PRIMOCT PRIMOCT 3866 +a9500 MACH_A9500 A9500 3867 +pue_td MACH_PULSE_TD PULSE_TD 3868 +pluto MACH_PLUTO PLUTO 3869 +acfx100 MACH_ACFX100 ACFX100 3870 +msm8625_rumi3 MACH_MSM8625_RUMI3 MSM8625_RUMI3 3871 +valente MACH_VALENTE VALENTE 3872 +crfs_rfeye MACH_CRFS_RFEYE CRFS_RFEYE 3873 +rfeye MACH_RFEYE RFEYE 3874 +phidget_sbc3 MACH_PHIDGET_SBC3 PHIDGET_SBC3 3875 +tcw_mika MACH_TCW_MIKA TCW_MIKA 3876 +imx28_egf MACH_IMX28_EGF IMX28_EGF 3877 +valente_wx MACH_VALENTE_WX VALENTE_WX 3878 +huangshans MACH_HUANGSHANS HUANGSHANS 3879 +bosphorus1 MACH_BOSPHORUS1 BOSPHORUS1 3880 +prima MACH_PRIMA PRIMA 3881 +meson3_skt MACH_M3_SKT M3_SKT 3882 +meson3_ref MACH_M3_REF M3_REF 3883 +evita_ulk MACH_EVITA_ULK EVITA_ULK 3884 +merisc600 MACH_MERISC600 MERISC600 3885 +dolak MACH_DOLAK DOLAK 3886 +sbc53 MACH_SBC53 SBC53 3887 +elite_ulk MACH_ELITE_ULK ELITE_ULK 3888 +pov2 MACH_POV2 POV2 3889 +ipod_touch_2g MACH_IPOD_TOUCH_2G IPOD_TOUCH_2G 3890 +da850_pqab MACH_DA850_PQAB DA850_PQAB 3891 -- cgit v1.2.3 From b81c695e6f64f9abdf07ccb8c65313dfecde738e Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 6 Dec 2011 17:10:16 +0100 Subject: platform: add support for aizo dSS11 Signed-off-by: Michael Grzeschik Signed-off-by: Sascha Hauer --- arch/arm/Makefile | 1 + arch/arm/boards/dss11/Makefile | 1 + arch/arm/boards/dss11/config.h | 6 ++ arch/arm/boards/dss11/env/config | 42 +++++++++++ arch/arm/boards/dss11/init.c | 156 +++++++++++++++++++++++++++++++++++++++ arch/arm/mach-at91/Kconfig | 8 ++ 6 files changed, 214 insertions(+) create mode 100644 arch/arm/boards/dss11/Makefile create mode 100644 arch/arm/boards/dss11/config.h create mode 100644 arch/arm/boards/dss11/env/config create mode 100644 arch/arm/boards/dss11/init.c diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 6f5f3433b1..e5e951cd32 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -66,6 +66,7 @@ board-$(CONFIG_MACH_AT91SAM9263EK) := at91sam9263ek board-$(CONFIG_MACH_AT91SAM9G10EK) := at91sam9261ek board-$(CONFIG_MACH_AT91SAM9G20EK) := at91sam9260ek board-$(CONFIG_MACH_AT91SAM9M10G45EK) := at91sam9m10g45ek +board-$(CONFIG_MACH_DSS11) := dss11 board-$(CONFIG_MACH_EDB9301) := edb93xx board-$(CONFIG_MACH_EDB9302) := edb93xx board-$(CONFIG_MACH_EDB9302A) := edb93xx diff --git a/arch/arm/boards/dss11/Makefile b/arch/arm/boards/dss11/Makefile new file mode 100644 index 0000000000..eb072c0161 --- /dev/null +++ b/arch/arm/boards/dss11/Makefile @@ -0,0 +1 @@ +obj-y += init.o diff --git a/arch/arm/boards/dss11/config.h b/arch/arm/boards/dss11/config.h new file mode 100644 index 0000000000..006820cf21 --- /dev/null +++ b/arch/arm/boards/dss11/config.h @@ -0,0 +1,6 @@ +#ifndef __CONFIG_H +#define __CONFIG_H + +#define AT91_MAIN_CLOCK 18432000 /* 18.432 MHz crystal */ + +#endif /* __CONFIG_H */ diff --git a/arch/arm/boards/dss11/env/config b/arch/arm/boards/dss11/env/config new file mode 100644 index 0000000000..5c9be7d6df --- /dev/null +++ b/arch/arm/boards/dss11/env/config @@ -0,0 +1,42 @@ +#!/bin/sh + +# use 'dhcp' to do dhcp in barebox and in kernel +# use 'none' if you want to skip kernel ip autoconfiguration +ip=dhcp + +# or set your networking parameters here +#eth0.ipaddr=a.b.c.d +#eth0.netmask=a.b.c.d +#eth0.gateway=a.b.c.d +#eth0.serverip=a.b.c.d + +# can be either 'nfs', 'tftp' or 'nand' +kernel_loc=tftp +# can be either 'net', 'nand' or 'initrd' +rootfs_loc=net + +# can be either 'jffs2' or 'ubifs' +rootfs_type=ubifs +rootfsimage=root.$rootfs_type + +# The image type of the kernel. Can be uimage, zimage, raw, or raw_lzo +#kernelimage_type=zimage +#kernelimage=zImage +kernelimage_type=uimage +kernelimage=uImage +#kernelimage_type=raw +#kernelimage=Image +#kernelimage_type=raw_lzo +#kernelimage=Image.lzo + +nand_device=atmel_nand +nand_parts="128k(bootstrap),512k(barebox)ro,512k(barebox-env),2M(kernel-rescue),2M(kernel-prod),32M(rootfs-rescue),200M(rootfs-prod),-(config)" +rootfs_mtdblock_nand=4 + +autoboot_timeout=3 + +bootargs="console=ttyS0,115200" + +# set a fancy prompt (if support is compiled in) +PS1="\e[1;32mbarebox@\e[1;31m\h:\w\e[0m " + diff --git a/arch/arm/boards/dss11/init.c b/arch/arm/boards/dss11/init.c new file mode 100644 index 0000000000..96c4eefa77 --- /dev/null +++ b/arch/arm/boards/dss11/init.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2011 Michael Grzeschik + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct atmel_nand_data nand_pdata = { + .ale = 21, + .cle = 22, +/* .det_pin = ... not connected */ + .ecc_mode = NAND_ECC_HW, + .rdy_pin = AT91_PIN_PC13, + .enable_pin = AT91_PIN_PC14, + .bus_width_16 = 1, +}; + +static struct sam9_smc_config dss11_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 3, + .nrd_pulse = 3, + .ncs_write_pulse = 3, + .nwe_pulse = 3, + + .read_cycle = 5, + .write_cycle = 5, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE, + .tdf_cycles = 2, +}; + +static void dss11_add_device_nand(void) +{ + /* setup bus-width (16) */ + dss11_nand_smc_config.mode |= AT91_SMC_DBW_16; + + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(3, &dss11_nand_smc_config); + + at91_add_device_nand(&nand_pdata); +} + +static struct at91_ether_platform_data macb_pdata = { + .phy_addr = 0, + .flags = AT91SAM_ETX2_ETX3_ALTERNATIVE, +}; + +static void dss11_phy_reset(void) +{ + unsigned long rstc; + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_EMAC); + + at91_set_gpio_input(AT91_PIN_PA14, 0); + at91_set_gpio_input(AT91_PIN_PA15, 0); + at91_set_gpio_input(AT91_PIN_PA17, 0); + at91_set_gpio_input(AT91_PIN_PA25, 0); + at91_set_gpio_input(AT91_PIN_PA26, 0); + at91_set_gpio_input(AT91_PIN_PA28, 0); + + rstc = at91_sys_read(AT91_RSTC_MR) & AT91_RSTC_ERSTL; + + /* Need to reset PHY -> 500ms reset */ + at91_sys_write(AT91_RSTC_MR, AT91_RSTC_KEY | + (AT91_RSTC_ERSTL & (0x0d << 8)) | + AT91_RSTC_URSTEN); + + at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_EXTRST); + + /* Wait for end hardware reset */ + while (!(at91_sys_read(AT91_RSTC_SR) & AT91_RSTC_NRSTL)); + + /* Restore NRST value */ + at91_sys_write(AT91_RSTC_MR, AT91_RSTC_KEY | + (rstc) | + AT91_RSTC_URSTEN); +} + +static struct atmel_mci_platform_data dss11_mci_data = { + .bus_width = 4, + .host_caps = MMC_MODE_HS, +}; + +static struct at91_usbh_data dss11_usbh_data = { + .ports = 2, +}; + +static int dss11_mem_init(void) +{ + at91_add_device_sdram(64 * 1024 * 1024); + + return 0; +} +mem_initcall(dss11_mem_init); + +static int dss11_devices_init(void) +{ + dss11_add_device_nand(); + dss11_phy_reset(); + at91_add_device_eth(&macb_pdata); + at91_add_device_mci(1, &dss11_mci_data); + at91_add_device_usbh_ohci(&dss11_usbh_data); + + armlinux_set_bootparams((void *)(AT91_CHIPSELECT_1 + 0x100)); + armlinux_set_architecture(MACH_TYPE_DSS11); + + devfs_add_partition("nand0", 0x00000, 0x20000, PARTITION_FIXED, "bootstrap"); + dev_add_bb_dev("bootstrap", "bootstrap.bb"); + devfs_add_partition("nand0", 0x20000, 0x40000, PARTITION_FIXED, "barebox"); + dev_add_bb_dev("barebox", "barebox.bb"); + devfs_add_partition("nand0", 0x60000, 0x40000, PARTITION_FIXED, "barebox-env"); + dev_add_bb_dev("barebox-env", "env0"); + + return 0; +} +device_initcall(dss11_devices_init); + +static int dss11_console_init(void) +{ + at91_register_uart(0, 0); + return 0; +} +console_initcall(dss11_console_init); diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 2ac23b5f19..e0e17bb651 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -20,6 +20,7 @@ config BOARDINFO default "Ronetix PM9261" if MACH_PM9261 default "Ronetix PM9263" if MACH_PM9263 default "Ronetix PM9G45" if MACH_PM9G45 + default "Aizo dSS11" if MACH_DSS11 config HAVE_NAND_ATMEL_BUSWIDTH_16 bool @@ -175,6 +176,13 @@ config MACH_USB_A9G20 Select this if you are using a Calao Systems USB-A9G20. +config MACH_DSS11 + bool "aizo dSS11" + select HAVE_NAND_ATMEL_BUSWIDTH_16 + help + Select this if you are using aizo dSS11 + that embeds only one SD/MMC slot. + endchoice endif -- cgit v1.2.3 From 901aad7d73817fc7cde657b4305c4ab0005c1903 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 6 Dec 2011 17:10:17 +0100 Subject: dss11: add defconfig Signed-off-by: Michael Grzeschik Signed-off-by: Sascha Hauer --- arch/arm/configs/dss11_defconfig | 48 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 arch/arm/configs/dss11_defconfig diff --git a/arch/arm/configs/dss11_defconfig b/arch/arm/configs/dss11_defconfig new file mode 100644 index 0000000000..71143c920e --- /dev/null +++ b/arch/arm/configs/dss11_defconfig @@ -0,0 +1,48 @@ +CONFIG_ARCH_AT91SAM9G20=y +CONFIG_MACH_DSS11=y +CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_PARTITION_DISK_DOS=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y +CONFIG_CMD_EDIT=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_LOADENV=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_LED=y +CONFIG_NET=y +CONFIG_NET_DHCP=y +CONFIG_NET_NFS=y +CONFIG_NET_PING=y +CONFIG_NET_TFTP=y +CONFIG_NET_TFTP_PUSH=y +CONFIG_DRIVER_NET_MACB=y +CONFIG_DRIVER_SPI_ATMEL=y +CONFIG_MTD=y +CONFIG_NAND=y +# CONFIG_NAND_ECC_HW_SYNDROME is not set +# CONFIG_NAND_ECC_HW_NONE is not set +CONFIG_NAND_ATMEL=y +CONFIG_UBI=y +CONFIG_DISK_WRITE=y +CONFIG_USB=y +CONFIG_USB_OHCI=y +CONFIG_USB_OHCI_AT91=y +CONFIG_USB_STORAGE=y +CONFIG_MCI=y +CONFIG_MCI_STARTUP=y +# CONFIG_MCI_WRITE is not set +CONFIG_MCI_ATMEL=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_LED_GPIO_RGB=y +CONFIG_LED_TRIGGERS=y +CONFIG_FS_FAT=y +CONFIG_FS_FAT_WRITE=y +CONFIG_FS_FAT_LFN=y -- cgit v1.2.3 From 1e06aef681a078dbc51ec36a602c9be9735b8ab9 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sat, 3 Dec 2011 06:47:50 +0100 Subject: sanbox: add linux_execve and linux_exec command this will allow to execute a program of the host from barebox Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Sascha Hauer --- arch/sandbox/mach-sandbox/include/mach/linux.h | 2 ++ arch/sandbox/os/common.c | 22 ++++++++++++++++++++++ commands/Kconfig | 6 ++++++ commands/Makefile | 1 + 4 files changed, 31 insertions(+) diff --git a/arch/sandbox/mach-sandbox/include/mach/linux.h b/arch/sandbox/mach-sandbox/include/mach/linux.h index 7c2386d247..5917fe93de 100644 --- a/arch/sandbox/mach-sandbox/include/mach/linux.h +++ b/arch/sandbox/mach-sandbox/include/mach/linux.h @@ -10,6 +10,8 @@ ssize_t linux_write(int fd, const void *buf, size_t count); off_t linux_lseek(int fildes, off_t offset); int linux_tstc(int fd); +int linux_execve(const char * filename, char *const argv[], char *const envp[]); + int barebox_register_console(char *name_template, int stdinfd, int stdoutfd); struct linux_console_data { diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c index 9258c66156..92b7dbb2c7 100644 --- a/arch/sandbox/os/common.c +++ b/arch/sandbox/os/common.c @@ -45,6 +45,7 @@ #include #include #include +#include /* * ...except the ones needed to connect with barebox */ @@ -185,6 +186,27 @@ off_t linux_lseek(int fd, off_t offset) return lseek(fd, offset, SEEK_SET); } +int linux_execve(const char * filename, char *const argv[], char *const envp[]) +{ + pid_t pid, tpid; + int execve_status; + + pid = fork(); + + if (pid == -1) { + perror("linux_execve"); + return pid; + } else if (pid == 0) { + exit(execve(filename, argv, envp)); + } else { + do { + tpid = wait(&execve_status); + } while(tpid != pid); + + return execve_status; + } +} + extern void start_barebox(void); extern void mem_malloc_init(void *start, void *end); diff --git a/commands/Kconfig b/commands/Kconfig index 2badea3b7b..ebc9c7f2d0 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -107,6 +107,12 @@ config CMD_TIME checking for ctrl-c, so the time command can be used with commands which are interruptible with ctrl-c. +config CMD_LINUX_EXEC + bool "linux exec" + depends on LINUX + help + This command executes a command on the Linux host. + endmenu menu "file commands " diff --git a/commands/Makefile b/commands/Makefile index e95fdc375d..aa013de107 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -61,3 +61,4 @@ obj-$(CONFIG_CMD_TIME) += time.o obj-$(CONFIG_CMD_OFTREE) += oftree.o obj-$(CONFIG_CMD_MAGICVAR) += magicvar.o obj-$(CONFIG_CMD_IOMEM) += iomem.o +obj-$(CONFIG_CMD_LINUX_EXEC) += linux_exec.o -- cgit v1.2.3 From 8b3d10265da20b8be6138799cee704d53dee1c63 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 7 Dec 2011 10:40:19 +0100 Subject: mci Kconfig: select DISK_WRITE instead of ATA_WRITE ATA_WRITE does not exist anymore. DISK_WRITE is the successor for it. Signed-off-by: Sascha Hauer --- drivers/mci/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig index 897aa4da88..6ed21cd2a4 100644 --- a/drivers/mci/Kconfig +++ b/drivers/mci/Kconfig @@ -27,7 +27,7 @@ config MCI_INFO config MCI_WRITE bool "Support writing to MCI cards" default y - select ATA_WRITE + select DISK_WRITE comment "--- MCI host drivers ---" -- cgit v1.2.3