diff options
235 files changed, 12741 insertions, 7687 deletions
@@ -234,7 +234,7 @@ then CONFIG="./${CONFIG}" fi - source "${CONFIG}" + . "${CONFIG}" fi [ -d "${LOGDIR}" ] || mkdir ${LOGDIR} || exit 1 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..e5e951cd32 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 @@ -64,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 @@ -103,6 +106,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/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 <mgr@pengutronix.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 <common.h> +#include <net.h> +#include <mci.h> +#include <init.h> +#include <environment.h> +#include <fec.h> +#include <asm/armlinux.h> +#include <generated/mach-types.h> +#include <partition.h> +#include <fs.h> +#include <fcntl.h> +#include <asm/io.h> +#include <asm/hardware.h> +#include <nand.h> +#include <linux/mtd/nand.h> +#include <mach/board.h> +#include <mach/at91sam9_smc.h> +#include <mach/sam9_smc.h> +#include <gpio.h> +#include <mach/io.h> +#include <mach/at91_pmc.h> +#include <mach/at91_rstc.h> + +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/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/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(); 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 <mkl@pengutronix.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 <common.h> +#include <environment.h> +#include <fcntl.h> +#include <fec.h> +#include <fs.h> +#include <init.h> +#include <nand.h> +#include <net.h> +#include <partition.h> +#include <sizes.h> + +#include <generated/mach-types.h> + +#include <mach/imx-regs.h> +#include <mach/iomux-mx53.h> +#include <mach/devices-imx53.h> +#include <mach/generic.h> +#include <mach/gpio.h> +#include <mach/imx-nand.h> +#include <mach/iim.h> +#include <mach/imx53.h> + +#include <asm/armlinux.h> +#include <io.h> +#include <asm/mmu.h> + +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/include/ata.h b/arch/arm/boards/freescale-mx53-smd/config.h index d56399ea75..b7effe5d28 100644 --- a/include/ata.h +++ b/arch/arm/boards/freescale-mx53-smd/config.h @@ -1,5 +1,6 @@ -/* - * Copyright (C) 2009 Juergen Beisert, Pengutronix +/** + * @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 @@ -8,32 +9,16 @@ * * 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 + * 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 <types.h> -#include <driver.h> +#ifndef __CONFIG_H +#define __CONFIG_H -/** - * 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; -}; +#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 <mkl@pengutronix.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 <common.h> +#include <asm/byteorder.h> +#include <mach/imx-flash-header.h> + +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/boards/mini2440/mini2440.c b/arch/arm/boards/mini2440/mini2440.c index b8042f2d85..b4cc0f89e8 100644 --- a/arch/arm/boards/mini2440/mini2440.c +++ b/arch/arm/boards/mini2440/mini2440.c @@ -314,6 +314,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); 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/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/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 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/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/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/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/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/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 ( 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/arm/lib/armlinux.c b/arch/arm/lib/armlinux.c index d8ca47706d..bd9b72a8ac 100644 --- a/arch/arm/lib/armlinux.c +++ b/arch/arm/lib/armlinux.c @@ -27,7 +27,6 @@ #include <driver.h> #include <environment.h> #include <image.h> -#include <zlib.h> #include <init.h> #include <fs.h> #include <linux/list.h> @@ -37,6 +36,7 @@ #include <errno.h> #include <memory.h> #include <of.h> +#include <magicvar.h> #include <asm/byteorder.h> #include <asm/setup.h> @@ -45,11 +45,71 @@ #include <asm/system.h> 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 + +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 + 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 +177,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 +191,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); @@ -140,7 +204,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. @@ -148,8 +212,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); } @@ -168,15 +232,15 @@ 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(); setup_end_tag(); printf("commandline: %s\n" - "arch_number: %d\n", commandline, armlinux_architecture); + "arch_number: %d\n", commandline, armlinux_get_architecture()); } @@ -185,28 +249,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 +271,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); } 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/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 87bf3b323e..031a2698ec 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -4,7 +4,6 @@ #include <driver.h> #include <environment.h> #include <image.h> -#include <zlib.h> #include <init.h> #include <fs.h> #include <linux/list.h> @@ -29,13 +28,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 " : ""); @@ -44,36 +36,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 <arch> use architecture number <arch>\n" - " -R <system_rev> use system revison <system_rev>\n", - .bootm = do_bootm_linux, .image_type = IH_OS_LINUX, }; 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. <http://www.calao-systems.com> +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 diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 9d1acda7fe..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 */ } @@ -261,18 +266,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 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/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 <common.h> #include <environment.h> #include <init.h> +#include <magicvar.h> #include <io.h> #include <mach/imx-regs.h> @@ -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 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/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 */ 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 70e7671620..1fc2417afd 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx53.h +++ b/arch/arm/mach-imx/include/mach/devices-imx53.h @@ -31,24 +31,29 @@ 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); } -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, 0, 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, 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) 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 <mach/imx-nand.h> #include <mach/imxfb.h> #include <mach/imx-ipu-fb.h> +#include <mach/esdhc.h> 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 <w.sang@pengutronix.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; 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/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); +} 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 <s.hauer@pengutronix.de> + * + * 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 <common.h> +#include <init.h> +#include <clock.h> +#include <asm/io.h> + +#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 <s.hauer@pengutronix.de> + * + * 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 <common.h> +#include <asm/io.h> + +#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 <robert.jarzmik@free.fr> + * + * 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 <common.h> +#include <driver.h> +#include <mach/devices.h> +#include <mach/pxafb.h> + +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 <common.h> +#include <errno.h> + +#include <mach/gpio.h> +#include <asm/io.h> + +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 <mkl@pengutronix.de> + * + * 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 <robert.jarzmik@free.fr> + * + * 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 <i2c/i2c.h> +#include <mach/pxafb.h> + +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 <philipp.zabel@gmail.com> + * + * 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 <mach/hardware.h> + +#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 <plat/gpio.h> +#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 <mkl@pengutronix.de> + * + * Copyright (C) 2010 by Marc Kleine-Budde <mkl@pengutronix.de> + * + * 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 <mach/mfp-pxa2xx.h> + +/* 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 <plat/mfp.h> + +/* + * 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 <eric.miao@marvell.com> + * 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 <plat/mfp.h> + +#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 <mkl@pengutronix.de> + * + * Copyright (C) 2010 by Marc Kleine-Budde <mkl@pengutronix.de> + * + * 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 <mach/pxa2xx-regs.h> +#endif + +#ifdef CONFIG_ARCH_PXA27X +# include <mach/pxa27x-regs.h> +#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 <mach/hardware.h> + +/* + * 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 <mach/hardware.h> + +/* + * 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 <mach/hardware.h> + +/* + * 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/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/<machine>.c or in + * linux/arch/mach-ixp4xx/<machine>.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/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 <mach/gpio.h> + +/* + * 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 <eric.miao@marvell.com> + * 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 <common.h> +#include <errno.h> +#include <init.h> + +#include <mach/gpio.h> +#include <mach/hardware.h> +#include <mach/mfp-pxa2xx.h> +#include <mach/pxa-regs.h> + +#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 <mkl@pengutronix.de> + * + * This file is released under the GPLv2 + * + */ + +#include <common.h> +#include <mach/clock.h> +#include <mach/pxa-regs.h> + +/* Crystal clock: 13MHz */ +#define BASE_CLK 13000000 + +unsigned long pxa_get_uartclk(void) +{ + return 14857000; +} 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 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/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/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/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/arch/mips/lib/barebox.lds.S b/arch/mips/lib/barebox.lds.S index 0c57368c24..a60728485c 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/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/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/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/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 <www.psyent.com> - * Scott McNutt <smcnutt@psyent.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <nios2.h> -#include <asm/nios2-io.h> -#include <asm/types.h> -#include <io.h> -#include <asm/ptrace.h> -#include <common.h> -#include <command.h> -#include <watchdog.h> - -/****************************************************************************/ - -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/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/arch/nios2/lib/board.c b/arch/nios2/lib/board.c index 07f045b3aa..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; } @@ -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..b5b344f499 100644 --- a/arch/nios2/lib/bootm.c +++ b/arch/nios2/lib/bootm.c @@ -43,13 +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; - /* kernel parameters passing * r4 : NIOS magic * r5 : initrd start 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/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..0e839eb053 100644 --- a/arch/ppc/lib/board.c +++ b/arch/ppc/lib/board.c @@ -56,20 +56,13 @@ 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 */ 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 <gnatapov@mrv.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/processor.h> -#include <watchdog.h> -#ifdef CONFIG_STATUS_LED -#include <status_led.h> -#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/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/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 <huber@mclx.com>, 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 <dfarnsworth@mvista.com> and Kent Borg. - * - * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com> - * Copyright (C) 2003 Montavista Software, Inc - */ - -#include <common.h> -#include <asm/processor.h> -#include <io.h> -#include <command.h> -#include <mach/sdma.h> -#include <asm/bitops.h> -#include <mach/clocks.h> - -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/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/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 @@ -8,6 +8,11 @@ SECTIONS __barebox_initcalls_end = .; . = ALIGN(64); + __barebox_magicvar_start = .; + .barebox_magicvar : { BAREBOX_MAGICVARS } + __barebox_magicvar_end = .; + + . = ALIGN(64); __barebox_cmd_start = .; __barebox_cmd : { BAREBOX_CMDS } __barebox_cmd_end = .; 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__ */ 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 5074a06c80..92b7dbb2c7 100644 --- a/arch/sandbox/os/common.c +++ b/arch/sandbox/os/common.c @@ -45,6 +45,7 @@ #include <errno.h> #include <signal.h> #include <sys/select.h> +#include <sys/wait.h> /* * ...except the ones needed to connect with barebox */ @@ -124,14 +125,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; @@ -193,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); @@ -270,7 +284,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/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/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; } diff --git a/commands/Kconfig b/commands/Kconfig index 18ab840916..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 " @@ -215,6 +221,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 @@ -292,23 +305,17 @@ 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 prompt "show image information" +config CMD_IMINFO + bool + prompt "iminfo" + help + Show information about uImages + config CMD_BOOTZ tristate default y @@ -383,6 +390,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 @@ -414,13 +435,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 5c519169c3..aa013de107 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 @@ -47,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 @@ -58,3 +59,6 @@ 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 +obj-$(CONFIG_CMD_IOMEM) += iomem.o +obj-$(CONFIG_CMD_LINUX_EXEC) += linux_exec.o diff --git a/commands/bootm.c b/commands/bootm.c index f11138afba..859ec28a26 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -30,8 +30,6 @@ #include <command.h> #include <image.h> #include <malloc.h> -#include <zlib.h> -#include <bzlib.h> #include <environment.h> #include <asm/byteorder.h> #include <xfuncs.h> @@ -42,59 +40,10 @@ #include <boot.h> #include <rtc.h> #include <init.h> +#include <magicvar.h> +#include <uncompress.h> #include <asm-generic/memory_layout.h> -/* - * 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) @@ -108,50 +57,27 @@ 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; - -#if defined CONFIG_CMD_BOOTM_ZLIB || defined CONFIG_CMD_BOOTM_BZLIB - uint unc_len = CFG_BOOTM_LEN; -#endif + void *data; + int ret; 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) - return -1; - break; -#endif -#ifdef CONFIG_CMD_BOOTM_BZLIB - case IH_COMP_BZIP2: + default: 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, (char *)data, len, - MALLOC_SIZE < (4096 * 1024), 0) - != BZ_OK) - return -1; + 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; @@ -168,7 +94,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) { @@ -188,118 +114,53 @@ 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 @<num> */ - 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 <initrd> specify an initrd image\n" - " -L <load addr> 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; - 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; 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; - char options[53]; /* worst case: whole alphabet with colons */ + int ret = 1; memset(&data, 0, sizeof(struct image_data)); data.verify = 1; + data.initrd_address = ~0; - /* Collect options from registered handlers */ - strcpy(options, "nh"); - 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); + case 'L': + data.initrd_address = simple_strtoul(optarg, NULL, 0); + break; + case 'r': + printf("use initrd %s\n", optarg); + /* check for multi image @<num> */ + 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); } - - return 0; + if (!data.initrd) + 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; @@ -310,31 +171,35 @@ 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': - 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 * recover from any failures any more... */ - disable_interrupts(); - 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) { + 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; + } + /* loop through the registered handlers */ list_for_each_entry(handler, &handler_list, list) { if (image_get_os(os_header) == handler->image_type) { @@ -350,15 +215,17 @@ 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) -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 <initrd>","specify an initrd image\n") +BAREBOX_CMD_HELP_OPT ("-L <load addr>","specify initrd load address") BAREBOX_CMD_HELP_END BAREBOX_CMD_START(bootm) @@ -367,84 +234,7 @@ BAREBOX_CMD_START(bootm) BAREBOX_CMD_HELP(cmd_bootm_help) BAREBOX_CMD_END -/** - * @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 <argc; ++arg) { - addr = simple_strtoul(argv[arg], NULL, 16); - if (image_info (addr) != 0) rcode = 1; - } - return rcode; -} - -static int image_info (ulong addr) -{ - ulong data, len, checksum; - image_header_t *hdr = &header; - - printf ("\n## Checking Image at %08lx ...\n", addr); - - /* Copy header so we can blank CRC field for re-calculation */ - memmove (&header, (char *)addr, image_get_header_size()); - - if (image_get_magic(hdr) != IH_MAGIC) { - puts (" Bad Magic Number\n"); - return 1; - } - - data = (ulong)&header; - len = image_get_header_size(); - - checksum = image_get_hcrc(hdr); - hdr->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 */ +BAREBOX_MAGICVAR(bootargs, "Linux Kernel parameters"); #ifdef CONFIG_BZLIB void bz_internal_error(int errcode) 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 <fs.h> #include <malloc.h> #include <libgen.h> +#include <getopt.h> /** * @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 <source> <destination>\n") +BAREBOX_CMD_HELP_USAGE("cp [-v] <source> <destination>\n") BAREBOX_CMD_HELP_SHORT("copy file from <source> to <destination>.\n") BAREBOX_CMD_HELP_END 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 <common.h> +#include <command.h> +#include <image.h> +#include <fs.h> +#include <malloc.h> +#include <fcntl.h> +#include <errno.h> + +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/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 <s.hauer@pengutronix.de>, 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 <common.h> +#include <command.h> + +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 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 <common.h> +#include <command.h> +#include <magicvar.h> + +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/commands/unlzo.c b/commands/uncompress.c index 0b6dd4b961..fff62275bb 100644 --- a/commands/unlzo.c +++ b/commands/uncompress.c @@ -1,5 +1,5 @@ /* - * unlzo.c - uncompress a lzo compressed file + * uncompress.c - uncompress a lzo compressed file * * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix * @@ -25,11 +25,11 @@ #include <errno.h> #include <fcntl.h> #include <fs.h> -#include <lzo.h> +#include <uncompress.h> -static int do_unlzo(struct command *cmdtp, int argc, char *argv[]) +static int do_uncompress(struct command *cmdtp, int argc, char *argv[]) { - int from, to, ret, retlen; + int from, to, ret; if (argc != 3) return COMMAND_ERROR_USAGE; @@ -47,7 +47,8 @@ static int do_unlzo(struct command *cmdtp, int argc, char *argv[]) goto exit_close; } - ret = unlzo(from, to, &retlen); + ret = uncompress_fd_to_fd(from, to, uncompress_err_stdout); + if (ret) printf("failed to decompress\n"); @@ -57,13 +58,13 @@ exit_close: return ret; } -static const __maybe_unused char cmd_unlzo_help[] = -"Usage: unlzo <infile> <outfile>\n" -"Uncompress a lzo compressed file\n"; +static const __maybe_unused char cmd_uncompress_help[] = +"Usage: uncompress <infile> <outfile>\n" +"Uncompress a compressed file\n"; -BAREBOX_CMD_START(unlzo) - .cmd = do_unlzo, +BAREBOX_CMD_START(uncompress) + .cmd = do_uncompress, .usage = "lzop <infile> <outfile>", - BAREBOX_CMD_HELP(cmd_unlzo_help) + BAREBOX_CMD_HELP(cmd_uncompress_help) BAREBOX_CMD_END 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..9bce47943c 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 @@ -24,6 +26,8 @@ obj-$(CONFIG_CMD_BOOTM) += image.o 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/console.c b/common/console.c index e5c0581381..cab8689252 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 61a233d1b5..73e4752cd8 100644 --- a/common/console_simple.c +++ b/common/console_simple.c @@ -164,3 +164,7 @@ int console_register(struct console_device *newcdev) } return 0; } + +int console_unregister(struct console_device *cdev) +{ +} 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/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 <s.hauer@pengutronix.de>, 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 <common.h> +#include <filetype.h> +#include <asm/byteorder.h> +#include <fcntl.h> +#include <fs.h> +#include <malloc.h> + +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/common/hush.c b/common/hush.c index 573bd3ef1d..b59e59dd17 100644 --- a/common/hush.c +++ b/common/hush.c @@ -122,6 +122,7 @@ #include <glob.h> #include <getopt.h> #include <libbb.h> +#include <magicvar.h> #include <linux/list.h> /*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 diff --git a/common/image.c b/common/image.c index 4a6402d8b9..d68889bc0f 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); @@ -404,6 +404,7 @@ err_out: close(fd); if (handle->flags & IH_MALLOC) free(handle->data); + free(handle->data_entries); free(handle); return NULL; } 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 <of.h> #include <init.h> #include <libfdt.h> +#include <linux/ioport.h> +#include <asm-generic/memory_layout.h> +#include <asm/sections.h> /* * 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/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 <common.h> +#include <malloc.h> +#include <errno.h> +#include <block.h> +#include <asm/unaligned.h> +#include <disks.h> + +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/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 <s.hauer@pengutronix.de>, 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 <common.h> +#include <malloc.h> +#include <errno.h> +#include <init.h> +#include <linux/ioport.h> + +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/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 <common.h> +#include <crc7.h> + + +/* 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/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 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 d7f4dcbfe3..fe6f5e6f5d 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -1,25 +1,21 @@ -menuconfig ATA +menuconfig DISK select BLOCK - bool "ATA " + select PARTITION + select PARTITION_DISK + 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 -comment "drive types" - -config ATA_WRITE +config DISK_WRITE select BLOCK_WRITE - bool "support writing to ATA drives" - -config ATA_DISK - bool "disk drives" - help - Add support for regular disk drives + bool "support writing to disk drives" -comment "interface types" +comment "drive types" -config ATA_BIOS +config DISK_BIOS bool "BIOS based" depends on X86_BIOS_BRINGUP help @@ -28,4 +24,19 @@ config ATA_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" + +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 30d15ccb02..2560076d26 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -1,7 +1,8 @@ # drive types -obj-$(CONFIG_ATA_DISK) += disk_drive.o +obj-$(CONFIG_DISK_BIOS) += disk_bios_drive.o +obj-$(CONFIG_DISK_ATA) += disk_ata_drive.o # interface types -obj-$(CONFIG_ATA_BIOS) += bios.o +obj-$(CONFIG_DISK_INTF_PLATFORM_IDE) += intf_platform_ide.o 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 <common.h> +#include <xfuncs.h> +#include <io.h> +#include <malloc.h> +#include <errno.h> +#include <clock.h> +#include <block.h> +#include <ata_drive.h> +#include <disks.h> + +#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/drivers/ata/bios.c b/drivers/ata/disk_bios_drive.c index 6e2377c7ea..78672454c0 100644 --- a/drivers/ata/bios.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 <stdio.h> -#include <linux/types.h> +#include <common.h> #include <init.h> -#include <driver.h> -#include <string.h> -#include <xfuncs.h> #include <asm/syslib.h> -#include <ata.h> #include <errno.h> +#include <block.h> +#include <disks.h> +#include <malloc.h> /** * 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/ata/disk_drive.c b/drivers/ata/disk_drive.c deleted file mode 100644 index a9d0deefe4..0000000000 --- a/drivers/ata/disk_drive.c +++ /dev/null @@ -1,248 +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 <stdio.h> -#include <init.h> -#include <driver.h> -#include <types.h> -#include <ata.h> -#include <xfuncs.h> -#include <errno.h> -#include <string.h> -#include <linux/kernel.h> -#include <malloc.h> -#include <common.h> -#include <block.h> -#include <asm/unaligned.h> - -/** - * 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_ATA_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_ATA_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_ATA_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_ATA_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 - /* 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->blk.dev = dev; - 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_ATA_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_ATA_BIOS - register_driver(&biosdisk_driver); -#endif - register_driver(&disk_driver); - return 0; -} - -device_initcall(disk_init); 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 <common.h> +#include <init.h> +#include <xfuncs.h> +#include <malloc.h> +#include <errno.h> +#include <ata_drive.h> +#include <platform_ide.h> + +/** + * 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/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/drivers/mci/Kconfig b/drivers/mci/Kconfig index 0d5a0e0814..6ed21cd2a4 100644 --- a/drivers/mci/Kconfig +++ b/drivers/mci/Kconfig @@ -1,7 +1,6 @@ menuconfig MCI bool "MCI drivers " - select ATA - select ATA_DISK + select DISK help Add support for MCI drivers, used to handle MMC and SD cards @@ -28,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 ---" @@ -80,4 +79,22 @@ 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" + 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 + 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/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); diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index a0e61f0d01..fe55697638 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -36,6 +36,8 @@ #include <asm/mmu.h> #include <mach/clock.h> #include <mach/generic.h> +#include <mach/esdhc.h> +#include <gpio.h> #include "imx-esdhc.h" @@ -107,7 +109,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; @@ -391,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); @@ -398,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); @@ -484,7 +522,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; diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index 09f7e29dc1..e9fe87ca40 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -36,7 +36,8 @@ #include <errno.h> #include <asm-generic/div64.h> #include <asm/byteorder.h> -#include <ata.h> +#include <block.h> +#include <disks.h> #define MAX_BUFFER_NUMBER 0xffffffff @@ -104,15 +105,23 @@ 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); 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,18 +131,30 @@ 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 /** * Read one block of data from the card @@ -142,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); @@ -218,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 @@ -237,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) { @@ -245,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"); @@ -255,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); @@ -453,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; @@ -748,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); @@ -768,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)) @@ -800,27 +856,29 @@ 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); } 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)) @@ -936,77 +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; } - 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 (block > MAX_BUFFER_NUMBER) { + pr_debug("Cannot handle block number %d. Too large!\n", block); + return -EINVAL; + } + + rc = mci_block_write(mci_dev, buffer, block, num_blocks); + if (rc != 0) { + 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", @@ -1014,21 +1063,15 @@ 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 (block > MAX_BUFFER_NUMBER) { + pr_err("Cannot handle block number %d. Too large!\n", block); + return -EINVAL; + } + + rc = mci_read_block(mci_dev, buffer, block, num_blocks); + if (rc != 0) { + pr_debug("Reading block %d failed with %d\n", block, rc); + return rc; } return 0; @@ -1166,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 @@ -1175,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); @@ -1221,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"); - dev = add_generic_device("disk", -1, NULL, 0, mci->capacity, IORESOURCE_MEM, p); - dev_add_child(&host->dev, dev); + 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; + } + + /* 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"); @@ -1307,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 @@ -1361,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/mci/mci_spi.c b/drivers/mci/mci_spi.c new file mode 100644 index 0000000000..653910bf7f --- /dev/null +++ b/drivers/mci/mci_spi.c @@ -0,0 +1,430 @@ +/* + * (C) Copyright 2011 - Franck JULLIEN <elec4fun@gmail.com> + * + * This code was inspired from u-boot mmc_spi.c: + * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw> + * + * 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 <jan.nikitenko@gmail.com> + * + * 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 <common.h> +#include <init.h> +#include <errno.h> +#include <clock.h> +#include <asm/io.h> +#include <driver.h> +#include <spi/spi.h> +#include <mci.h> +#include <crc.h> +#include <crc7.h> + +#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 */ + +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; +} + +/* + * 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; + 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; +#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); + + 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/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); } 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/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 <s.hauer@pengutronix.de> + * 2010 by Marc Kleine-Budde <kernel@pengutronix.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 <common.h> +#include <driver.h> +#include <init.h> +#include <malloc.h> + +#include <mach/clock.h> +#include <asm/io.h> + +#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); 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 <io.h> #include <asm/spi.h> #include <asm/nios2-io.h> +#include <clock.h> + +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; 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/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/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); } /*-------------------------------------------------------------------------*/ 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 <common.h> +#include <errno.h> +#include <clock.h> +#include <io.h> +#include <gpio.h> +#include <init.h> +#include <poller.h> + +#include <usb/ch9.h> +#include <usb/gadget.h> + +#include "pxa27x_udc.h" +#include <mach/udc_pxa2xx.h> +#include <mach/pxa-regs.h> + +#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 */ diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index d3baed74de..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)) - fsl_udc_irq(); + 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) @@ -475,7 +483,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; } @@ -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,8 +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); +} 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 d033b291c2..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); @@ -193,35 +193,34 @@ 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 + +#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 <usb/usb.h> -#include <ata.h> +#include <block.h> +#include <disks.h> #include <scsi.h> #include <linux/list.h> @@ -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/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 <common.h> #include <malloc.h> -#include <watchdog.h> -#include <zlib.h> +#include <linux/kernel.h> +#include <errno.h> +#include <linux/zlib.h> +#include <asm/byteorder.h> +#include <cramfs/cramfs_fs.h> 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/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/fs/ramfs.c b/fs/ramfs.c index db417e13fc..5e352f277a 100644 --- a/fs/ramfs.c +++ b/fs/ramfs.c @@ -30,7 +30,7 @@ #include <linux/stat.h> #include <xfuncs.h> -#define CHUNK_SIZE 4096 +#define CHUNK_SIZE (4096 * 2) struct ramfs_chunk { char *data; 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/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 */ diff --git a/include/boot.h b/include/boot.h index 623f443c19..b67e034801 100644 --- a/include/boot.h +++ b/include/boot.h @@ -9,15 +9,13 @@ struct image_data { struct image_handle *initrd; const char *oftree; int verify; + unsigned long initrd_address; + unsigned long initrd_size; }; 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); }; 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/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 <windows.h> -# 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 <stdio.h> - -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/include/common.h b/include/common.h index e34bbea82f..d594e630e4 100644 --- a/include/common.h +++ b/include/common.h @@ -107,36 +107,13 @@ 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); -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/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) 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 */ 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 <common.h> + +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 diff --git a/include/disks.h b/include/disks.h new file mode 100644 index 0000000000..9932750a24 --- /dev/null +++ b/include/disks.h @@ -0,0 +1,41 @@ +/* + * 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)); + +extern int parse_partition_table(struct block_device*); + +#endif /* DISKS_H */ diff --git a/include/driver.h b/include/driver.h index 80de0c8377..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 @@ -394,6 +390,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); 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); 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 */ 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/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. 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/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 */ 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 <linux/zconf.h> + +/* 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 <linux/zlib.h> +#include <linux/string.h> +#include <linux/kernel.h> + +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/include/lzo.h b/include/lzo.h index 569498596e..0530a6806d 100644 --- a/include/lzo.h +++ b/include/lzo.h @@ -41,6 +41,10 @@ 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), + u8 *output, int *posp, + void (*error) (char *x)); #endif 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 <linux/stringify.h> + +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 */ diff --git a/include/mci.h b/include/mci.h index 69cffe8d3f..d3b3082fc1 100644 --- a/include/mci.h +++ b/include/mci.h @@ -31,6 +31,7 @@ #define _MCI_H_ #include <linux/list.h> +#include <block.h> /* Firmware revisions for SD cards */ #define SD_VERSION_SD 0x20000 @@ -49,6 +50,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 +58,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 +86,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 +165,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 */ @@ -194,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 */ @@ -212,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; 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 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 */ 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/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 <unix.h> -#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<<windowBits bytes. If next_out is null, the - library will allocate its own buffer (and leave next_out null). next_in - need not be provided here but must be provided by the application for the - next call of inflate(). - - If the history buffer is provided by the application, next_out must - never be changed by the application since the decompressor maintains - history information inside this buffer from call to call; the application - can only reset next_out to the beginning of the history buffer when - avail_out is zero and all output has been consumed. - - 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 - windowBits < 8). msg is set to null if there is no error message. - inflateInit2 does not perform any decompression: this will be done by - inflate(). -*/ - -extern int inflateSync OF((z_stream *strm)); -/* - Skips invalid compressed data until the special marker (see deflate() - above) can be found, or until all available input is skipped. No output - is provided. - - inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no marker 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 inflateReset OF((z_stream *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 inflateIncomp OF((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). -*/ - - /* checksum functions */ - -/* - This function is not related to compression but is exported - anyway because it might be useful in applications using the - compression library. -*/ - -extern uLong adler32 OF((uLong adler, Bytef *buf, uInt len)); - -/* - 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, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -#ifndef _Z_UTIL_H - struct internal_state {int dummy;}; /* hack for buggy compilers */ -#endif - -#endif /* _ZLIB_H */ 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/Makefile b/lib/Makefile index cb72842585..ae76b4c9a7 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -15,8 +15,8 @@ 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_ZLIB) += zlib.o gunzip.o +obj-$(CONFIG_BZLIB) += decompress_bunzip2.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 @@ -30,3 +30,4 @@ obj-y += show_progress.o obj-$(CONFIG_LZO_DECOMPRESS) += decompress_unlzo.o obj-$(CONFIG_PROCESS_ESCAPE_SEQUENCE) += process_escape_sequence.o obj-$(CONFIG_FDT) += fdt/ +obj-y += uncompress.o 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 <config.h> -#include <common.h> -#include <watchdog.h> - -/* - * 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 <fcntl.h> -# include <io.h> -# 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 <config.h> - -/*-------------------------------------------------------------*/ -/*--- 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 <config.h> -#include <common.h> -#include <watchdog.h> - -/*-------------------------------------------------------------*/ -/*--- 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 <config.h> - -/*-------------------------------------------------------------*/ -/*--- 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 <config.h> - -/*-------------------------------------------------------------*/ -/*--- 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 ---*/ -/*-------------------------------------------------------------*/ - 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 <errno.h> #include <malloc.h> #include <libbb.h> +#include <progress.h> #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); 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 <common.h> +#include <malloc.h> + +#ifdef STATIC +#define PREBOOT +#else +#include <bunzip2.h> +#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 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 <linux/zutil.h> +#include <common.h> +#include <malloc.h> + +#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/decompress_unlzo.c b/lib/decompress_unlzo.c index 0ae3d4d049..000bd704c3 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, @@ -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 __unlzo(NULL, 0, unlzo_fill, unlzo_flush, NULL, NULL, unlzo_error); -} diff --git a/lib/gunzip.c b/lib/gunzip.c deleted file mode 100644 index c41568afd6..0000000000 --- a/lib/gunzip.c +++ /dev/null @@ -1,85 +0,0 @@ -#include <common.h> -#include <zlib.h> -#include <malloc.h> - -#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/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 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 <s.hauer@pengutronix.de>, 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 <common.h> +#include <uncompress.h> +#include <bunzip2.h> +#include <gunzip.h> +#include <lzo.h> +#include <errno.h> +#include <filetype.h> +#include <malloc.h> +#include <fs.h> + +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); +} 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') 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 <linux/string.h> -#define zmemcpy memcpy -#define zmemzero(dest, len) memset(dest, 0, len) - -/* Diagnostic functions */ -#ifdef DEBUG_ZLIB -# include <stdio.h> -# 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)<<k;k+=8;}} -#define DUMPBITS(j) {b>>=(j);k-=(j);} -/* output bytes */ -#define WAVAIL (q<s->read?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)<<k;k+=8;}} -#define UNGRAB {n+=(c=k>>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; -} 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 <linux/zutil.h> +#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 <richard@openedhand.com> + * + * Changes mainly for static instead of dynamic memory allocation + * + */ + +#include <linux/zutil.h> +#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 <linux/zutil.h> +#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 <linux/zutil.h> +#include <errno.h> + +/* 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 <linux/zlib.h> + +/* 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 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 <net.h> #include <libbb.h> #include <errno.h> +#include <magicvar.h> #include <linux/err.h> #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"); 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); |