diff options
Diffstat (limited to 'target/linux/rdc')
27 files changed, 3798 insertions, 0 deletions
diff --git a/target/linux/rdc/Makefile b/target/linux/rdc/Makefile new file mode 100644 index 000000000..5af5e85c6 --- /dev/null +++ b/target/linux/rdc/Makefile @@ -0,0 +1,38 @@ +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk + +ARCH:=i386 +BOARD:=rdc +BOARDNAME:=RDC321x x86 +FEATURES:=squashfs jffs2 broken + +LINUX_VERSION:=2.6.22.4 + +define Target/Description + Build firmware images for RDC321x based routers + (e.g. Airlink101 AR525W, Linksys WRT54R, Sitecom WL-153) +endef + +include $(INCLUDE_DIR)/kernel-build.mk + +ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),y) + define Kernel/SetInitramfs + echo "r6040 parent=wlan0" > $(TARGET_DIR)/etc/modules.d/99-r6040 + $(RM) $(TARGET_DIR)/sbin/init + ln -s /etc/preinit $(TARGET_DIR)/sbin/init + sed -i 's,exec /sbin/init,exec /bin/busybox init,g' $(TARGET_DIR)/etc/preinit + sed -i 's,/sbin/init,/bin/busybox init,g' $(TARGET_DIR)/init + mv $(TARGET_DIR)/init $(TARGET_DIR)/linuxrc + sed -i 's,eth0,eth1,g' $(TARGET_DIR)/etc/config/network + endef +endif + +# include the profiles +-include profiles/*.mk + +$(eval $(call BuildKernel)) diff --git a/target/linux/rdc/base-files/default/etc/diag.sh b/target/linux/rdc/base-files/default/etc/diag.sh new file mode 100644 index 000000000..8d5c38262 --- /dev/null +++ b/target/linux/rdc/base-files/default/etc/diag.sh @@ -0,0 +1,19 @@ +#!/bin/sh +# Copyright (C) 2007 OpenWrt.org + +set_led() { + local led="$1" + local state="$2" + [ -d "/sys/class/leds/rdc321x:$led" ] && echo "$state" > "/sys/class/leds/rdc321x:$led/brightness" +} + +set_state() { + case "$1" in + preinit) + set_led dmz 1 + ;; + done) + set_led dmz 0 + ;; + esac +} diff --git a/target/linux/rdc/config/default b/target/linux/rdc/config/default new file mode 100644 index 000000000..381a961e9 --- /dev/null +++ b/target/linux/rdc/config/default @@ -0,0 +1,313 @@ +# CONFIG_60XX_WDT is not set +# CONFIG_8139TOO is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_AGP is not set +# CONFIG_ALIM1535_WDT is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_ATA=m +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_PIIX=m +# CONFIG_ATM_DRIVERS is not set +CONFIG_BASE_SMALL=0 +CONFIG_BINFMT_AOUT=m +CONFIG_BINFMT_MISC=m +CONFIG_BITREVERSE=y +# CONFIG_BLK_DEV_HD is not set +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDE=m +CONFIG_BLK_DEV_IDEDISK=m +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_BROADCOM_PHY is not set +CONFIG_CLOCKSOURCE_WATCHDOG=y +# CONFIG_COMPAT_VDSO is not set +# CONFIG_CPU5_WDT is not set +# CONFIG_CPU_FREQ is not set +CONFIG_CRYPTO_AES_586=m +CONFIG_CRYPTO_DEV_GEODE=m +# CONFIG_CRYPTO_DEV_PADLOCK is not set +CONFIG_CRYPTO_TWOFISH_586=m +# CONFIG_CS5535_GPIO is not set +# CONFIG_DCDBAS is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_DELL_RBU is not set +CONFIG_DEVPORT=y +CONFIG_DMI=y +CONFIG_DOUBLEFAULT=y +# CONFIG_E100 is not set +CONFIG_EARLY_PRINTK=y +# CONFIG_EDAC is not set +# CONFIG_EDD is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_FIXED_PHY is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_GEN_RTC is not set +# CONFIG_HANGCHECK_TIMER is not set +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HID=m +# CONFIG_HIGHMEM4G is not set +# CONFIG_HIGHMEM64G is not set +# CONFIG_HIGH_RES_TIMERS is not set +# CONFIG_HPET_TIMER is not set +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_AMD is not set +# CONFIG_HW_RANDOM_GEODE is not set +# CONFIG_HW_RANDOM_INTEL is not set +# CONFIG_HW_RANDOM_VIA is not set +CONFIG_HZ=250 +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +CONFIG_I2C=m +# CONFIG_I2C_ALGOBIT is not set +CONFIG_I2C_BOARDINFO=y +# CONFIG_I6300ESB_WDT is not set +# CONFIG_I8K is not set +# CONFIG_IB700_WDT is not set +# CONFIG_IBMASR is not set +# CONFIG_IBM_ASM is not set +CONFIG_ICPLUS_PHY=y +CONFIG_IDE=m +# CONFIG_IDEPCI_PCIBUS_ORDER is not set +# CONFIG_IDE_ARM is not set +# CONFIG_IDE_GENERIC is not set +# CONFIG_IDE_PROC_FS is not set +# CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INPUT=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_YEALINK=m +CONFIG_IOSCHED_CFQ=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_ISA is not set +CONFIG_ISA_DMA_API=y +# CONFIG_ITCO_WDT is not set +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_RUBIN=y +CONFIG_JFS_FS=m +CONFIG_KEXEC=y +CONFIG_KTIME_SCALAR=y +# CONFIG_KVM is not set +CONFIG_LBD=y +CONFIG_LEDS_RDC3211=y +CONFIG_LSF=y +# CONFIG_M386 is not set +CONFIG_M486=y +# CONFIG_M586 is not set +# CONFIG_M586MMX is not set +# CONFIG_M586TSC is not set +# CONFIG_M686 is not set +# CONFIG_MACHZ_WDT is not set +# CONFIG_MACINTOSH_DRIVERS is not set +CONFIG_MATH_EMULATION=y +# CONFIG_MCA is not set +# CONFIG_MCORE2 is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MEFFICEON is not set +# CONFIG_MGEODEGX1 is not set +# CONFIG_MGEODE_LX is not set +# CONFIG_MICROCODE is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MPENTIUM4 is not set +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +CONFIG_MTD=y +# CONFIG_MTD_ABSENT is not set +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_MTD_BLOCK2MTD is not set +CONFIG_MTD_CFI=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_CONCAT=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +CONFIG_MTD_MAP_BANK_WIDTH_2=y +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_NETSC520 is not set +# CONFIG_MTD_ONENAND is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_PNC2000 is not set +# CONFIG_MTD_RAM is not set +CONFIG_MTD_RDC3210=y +CONFIG_MTD_RDC3210_ALLOW_JFFS2=y +CONFIG_MTD_RDC3210_BUSWIDTH=2 +# CONFIG_MTD_RDC3210_FACTORY_PRESENT is not set +CONFIG_MTD_RDC3210_SIZE=0x400000 +# CONFIG_MTD_RDC3210_STATIC_MAP is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_SC520CDP is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_TS5500 is not set +# CONFIG_MTRR is not set +# CONFIG_MVIAC3_2 is not set +# CONFIG_MVIAC7 is not set +# CONFIG_MWAVE is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NETDEV_1000 is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_NET_VENDOR_3COM is not set +CONFIG_NLS_ISO8859_2=m +CONFIG_NOHIGHMEM=y +# CONFIG_NO_HZ is not set +CONFIG_NR_QUICK=1 +# CONFIG_NSC_GPIO is not set +CONFIG_NVRAM=y +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PARAVIRT is not set +CONFIG_PATA_ARTOP=m +# CONFIG_PC8736x_GPIO is not set +# CONFIG_PC87413_WDT is not set +CONFIG_PCCARD=m +CONFIG_PCCARD_NONSTATIC=m +# CONFIG_PCIEPORTBUS is not set +# CONFIG_PCIPCWATCHDOG is not set +CONFIG_PCI_BIOS=y +CONFIG_PCI_DIRECT=y +CONFIG_PCI_GOANY=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOMMCONFIG is not set +CONFIG_PCMCIA=m +CONFIG_PHYLIB=y +CONFIG_PHYSICAL_ALIGN=0x100000 +CONFIG_PHYSICAL_START=0x100000 +# CONFIG_PNPACPI is not set +# CONFIG_QSEMI_PHY is not set +CONFIG_QUICKLIST=y +CONFIG_R6040=m +# CONFIG_R6040_NAPI is not set +# CONFIG_RELOCATABLE is not set +# CONFIG_RTC is not set +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +# CONFIG_SBC8360_WDT is not set +# CONFIG_SBC_EPX_C3_WATCHDOG is not set +# CONFIG_SC1200_WDT is not set +# CONFIG_SC520_WDT is not set +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_WAIT_SCAN=m +# CONFIG_SCx200 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_SECCOMP is not set +CONFIG_SEMAPHORE_SLEEPERS=y +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SMP is not set +# CONFIG_SMSC37B787_WDT is not set +# CONFIG_SMSC_PHY is not set +CONFIG_SOFT_WATCHDOG=m +# CONFIG_SONYPI is not set +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_TELCLOCK is not set +# CONFIG_TICK_ONESHOT is not set +# CONFIG_TOSHIBA is not set +CONFIG_UID16=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_EHCI_HCD=m +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_SPLIT_ISO is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_HCD=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set +# CONFIG_USB_UHCI_HCD is not set +CONFIG_V4L_USB_DRIVERS=y +# CONFIG_VGASTATE is not set +# CONFIG_VIA_RHINE is not set +CONFIG_VIDEO_CAPTURE_DRIVERS=y +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_V4L1=y +# CONFIG_VM86 is not set +# CONFIG_VMSPLIT_1G is not set +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_2G_OPT is not set +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_3G_OPT is not set +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_W83627HF_WDT is not set +# CONFIG_W83697HF_WDT is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_W83977F_WDT is not set +# CONFIG_WAFER_WDT is not set +CONFIG_X86=y +CONFIG_X86_32=y +CONFIG_X86_ALIGNMENT_16=y +# CONFIG_X86_BIGSMP is not set +CONFIG_X86_BIOS_REBOOT=y +CONFIG_X86_BSWAP=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_CPUID=y +# CONFIG_X86_ELAN is not set +# CONFIG_X86_ES7000 is not set +CONFIG_X86_F00F_BUG=y +# CONFIG_X86_GENERIC is not set +# CONFIG_X86_GENERICARCH is not set +CONFIG_X86_INVLPG=y +CONFIG_X86_L1_CACHE_SHIFT=4 +# CONFIG_X86_MCE is not set +CONFIG_X86_MINIMUM_CPU_MODEL=4 +CONFIG_X86_MSR=y +# CONFIG_X86_NUMAQ is not set +# CONFIG_X86_PC is not set +CONFIG_X86_POPAD_OK=y +CONFIG_X86_PPRO_FENCE=y +CONFIG_X86_RDC=y +CONFIG_X86_REBOOTFIXUPS=y +# CONFIG_X86_SUMMIT is not set +# CONFIG_X86_UP_APIC is not set +# CONFIG_X86_VISWS is not set +# CONFIG_X86_VOYAGER is not set +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_XADD=y diff --git a/target/linux/rdc/config/profile-wl153 b/target/linux/rdc/config/profile-wl153 new file mode 100644 index 000000000..3ab59a881 --- /dev/null +++ b/target/linux/rdc/config/profile-wl153 @@ -0,0 +1,2 @@ +# CONFIG_MTD_RDC3210_ALLOW_JFFS2 is not set +CONFIG_MTD_RDC3210_SIZE=0x200000 diff --git a/target/linux/rdc/files/arch/i386/kernel/cpu/rdc.c b/target/linux/rdc/files/arch/i386/kernel/cpu/rdc.c new file mode 100644 index 000000000..f4b9083bf --- /dev/null +++ b/target/linux/rdc/files/arch/i386/kernel/cpu/rdc.c @@ -0,0 +1,24 @@ +#include <linux/init.h> +#include <linux/bitops.h> +#include <linux/mm.h> +#include <asm/io.h> +#include <asm/processor.h> + +#include "cpu.h" + +static struct cpu_dev rdc_cpu_dev __cpuinitdata = { + .c_vendor = "RDC", + .c_models = { + { .vendor = X86_VENDOR_RDC, .family = 4, .model_names = + { + [0] = "R861x(-G)", + } + }, + }, +}; + +int __init rdc_init_cpu(void) +{ + cpu_devs[X86_VENDOR_RDC] = &rdc_cpu_dev; + return 0; +} diff --git a/target/linux/rdc/files/arch/i386/mach-rdc/Makefile b/target/linux/rdc/files/arch/i386/mach-rdc/Makefile new file mode 100644 index 000000000..5961bc791 --- /dev/null +++ b/target/linux/rdc/files/arch/i386/mach-rdc/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the RDC321x specific parts of the kernel +# +obj-$(CONFIG_X86_RDC) := gpio.o platform.o wdt.o + diff --git a/target/linux/rdc/files/arch/i386/mach-rdc/gpio.c b/target/linux/rdc/files/arch/i386/mach-rdc/gpio.c new file mode 100644 index 000000000..dbd03270f --- /dev/null +++ b/target/linux/rdc/files/arch/i386/mach-rdc/gpio.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2007, OpenWrt.org, Florian Fainelli <florian@openwrt.org> + * RDC321x architecture specific GPIO support + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/autoconf.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/types.h> +#include <linux/module.h> +#include <linux/delay.h> + +#include <asm/mach-rdc/rdc321x_defs.h> + +static inline int rdc_gpio_is_valid(unsigned gpio) +{ + return (gpio <= RDC_MAX_GPIO); +} + +static unsigned int rdc_gpio_read(unsigned gpio) +{ + unsigned int val; + + val = 0x80000000 | (7 << 11) | ((gpio&0x20?0x84:0x48)); + outl(val, RDC3210_CFGREG_ADDR); + udelay(10); + val = inl(RDC3210_CFGREG_DATA); + val |= (0x1 << (gpio & 0x1F)); + outl(val, RDC3210_CFGREG_DATA); + udelay(10); + val = 0x80000000 | (7 << 11) | ((gpio&0x20?0x88:0x4C)); + outl(val, RDC3210_CFGREG_ADDR); + udelay(10); + val = inl(RDC3210_CFGREG_DATA); + + return val; +} + +static void rdc_gpio_write(unsigned int val) +{ + if (val) { + outl(val, RDC3210_CFGREG_DATA); + udelay(10); + } +} + +int rdc_gpio_get_value(unsigned gpio) +{ + if (rdc_gpio_is_valid(gpio)) + return (int)rdc_gpio_read(gpio); + else + return -EINVAL; +} +EXPORT_SYMBOL(rdc_gpio_get_value); + +void rdc_gpio_set_value(unsigned gpio, int value) +{ + unsigned int val; + + if (!rdc_gpio_is_valid(gpio)) + return; + + val = rdc_gpio_read(gpio); + + if (value) + val &= ~(0x1 << (gpio & 0x1F)); + else + val |= (0x1 << (gpio & 0x1F)); + + rdc_gpio_write(val); +} +EXPORT_SYMBOL(rdc_gpio_set_value); + +int rdc_gpio_direction_input(unsigned gpio) +{ + return 0; +} +EXPORT_SYMBOL(rdc_gpio_direction_input); + +int rdc_gpio_direction_output(unsigned gpio, int value) +{ + return 0; +} +EXPORT_SYMBOL(rdc_gpio_direction_output); + + diff --git a/target/linux/rdc/files/arch/i386/mach-rdc/platform.c b/target/linux/rdc/files/arch/i386/mach-rdc/platform.c new file mode 100644 index 000000000..6809dcdd3 --- /dev/null +++ b/target/linux/rdc/files/arch/i386/mach-rdc/platform.c @@ -0,0 +1,83 @@ +/* + * $Id: platform.c 8331 2007-08-03 15:59:23Z florian $ + * + * Generic RDC321x platform devices + * + * Copyright (C) 2007 OpenWrt.org + * Copyright (C) 2007 Florian Fainelli <florian@openwrt.org> + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/device.h> +#include <linux/platform_device.h> + +#include <asm/gpio.h> + +#define PFX "rdc321x: " + +/* FIXME : Flash */ +static struct resource rdc_flash_resource[] = { + [0] = { + .start = (u32)-CONFIG_MTD_RDC3210_SIZE, + .end = (u32)-1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device rdc_flash_device = { + .name = "rdc321x-flash", + .id = -1, + .num_resources = ARRAY_SIZE(rdc_flash_resource), + .resource = rdc_flash_resource, +}; + +/* LEDS */ +static struct platform_device rdc321x_leds = { + .name = "rdc321x-leds", + .id = -1, + .num_resources = 0, +}; + +static struct platform_device rdc321x_wdt = { + .name = "rdc321x-wdt", + .id = -1, + .num_resources = 0, +}; + +static int __init rdc_board_setup(void) +{ + int err; + + err = platform_device_register(&rdc_flash_device); + if (err) + printk(KERN_ALERT PFX "failed to register flash\n"); + + err = platform_device_register(&rdc321x_leds); + if (err) + printk(KERN_ALERT PFX "failed to register LEDS\n"); + + err = platform_device_register(&rdc321x_wdt); + printk(KERN_ALERT PFX "failed to register watchdog\n"); + + return err; +} + +arch_initcall(rdc_board_setup); diff --git a/target/linux/rdc/files/arch/i386/mach-rdc/wdt.c b/target/linux/rdc/files/arch/i386/mach-rdc/wdt.c new file mode 100644 index 000000000..39956f35a --- /dev/null +++ b/target/linux/rdc/files/arch/i386/mach-rdc/wdt.c @@ -0,0 +1,272 @@ +/* + * RDC321x watchdog driver + * + * Copyright (C) 2007 Florian Fainelli <florian@openwrt.org> + * + * This driver is highly inspired from the cpu5_wdt driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/miscdevice.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/timer.h> +#include <linux/completion.h> +#include <linux/jiffies.h> +#include <linux/platform_device.h> +#include <linux/watchdog.h> + +#include <asm/io.h> +#include <asm/uaccess.h> + +#include <asm/mach-rdc/rdc321x_defs.h> + +#define RDC_WDT_MASK 0x80000000 /* Mask */ +#define RDC_WDT_EN 0x00800000 /* Enable bit */ +#define RDC_WDT_WTI 0x00200000 /* Generate a CPU reset/NMI/WDT irq when WDT timeout is reached */ +#define RDC_WDT_RST 0x00100000 /* Reset bit */ +#define RDC_WDT_WIF 0x00040000 /* WDT IRQ Flag */ +#define RDC_WDT_IRT 0x00000100 /* IRQ Routing table */ +#define RDC_WDT_CNT 0x00000001 /* WDT count */ + +#define RDC_CLS_TMR 0x80003844 /* Clear timer */ + +#define RDC_WDT_INTERVAL (HZ/10+1) + +int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +static int ticks = 1000; + +/* some device data */ + +static struct { + struct completion stop; + volatile int running; + struct timer_list timer; + volatile int queue; + int default_ticks; + unsigned long inuse; +} rdc321x_wdt_device; + +/* generic helper functions */ + +static void rdc321x_wdt_trigger(unsigned long unused) +{ + if( rdc321x_wdt_device.running ) + ticks--; + + /* keep watchdog alive */ + outl(RDC_WDT_EN|inl(RDC3210_CFGREG_DATA), RDC3210_CFGREG_DATA); + + /* requeue?? */ + if (rdc321x_wdt_device.queue && ticks) + mod_timer(&rdc321x_wdt_device.timer, jiffies + RDC_WDT_INTERVAL); + else { + /* ticks doesn't matter anyway */ + complete(&rdc321x_wdt_device.stop); + } + +} + +static void rdc321x_wdt_reset(void) +{ + ticks = rdc321x_wdt_device.default_ticks; +} + +static void rdc321x_wdt_start(void) +{ + if (!rdc321x_wdt_device.queue) { + rdc321x_wdt_device.queue = 1; + + /* Clear the timer */ + outl(RDC_CLS_TMR, RDC3210_CFGREG_ADDR); + + /* Enable watchdog and set the timeout to 81.92 us */ + outl(RDC_WDT_EN|RDC_WDT_CNT, RDC3210_CFGREG_DATA); + + mod_timer(&rdc321x_wdt_device.timer, jiffies + RDC_WDT_INTERVAL); + } + + /* if process dies, counter is not decremented */ + rdc321x_wdt_device.running++; +} + +static int rdc321x_wdt_stop(void) +{ + if (rdc321x_wdt_device.running) + rdc321x_wdt_device.running = 0; + + ticks = rdc321x_wdt_device.default_ticks; + + return -EIO; +} + +/* filesystem operations */ + +static int rdc321x_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(0, &rdc321x_wdt_device.inuse)) + return -EBUSY; + + return nonseekable_open(inode, file); +} + +static int rdc321x_wdt_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &rdc321x_wdt_device.inuse); + return 0; +} + +static int rdc321x_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + unsigned int value; + static struct watchdog_info ident = + { + .options = WDIOF_CARDRESET, + .identity = "RDC321x WDT", + }; + + switch(cmd) { + case WDIOC_KEEPALIVE: + rdc321x_wdt_reset(); + break; + case WDIOC_GETSTATUS: + /* Read the value from the DATA register */ + value = inl(RDC3210_CFGREG_DATA); + if ( copy_to_user(argp, &value, sizeof(int)) ) + return -EFAULT; + break; + case WDIOC_GETSUPPORT: + if ( copy_to_user(argp, &ident, sizeof(ident)) ) + return -EFAULT; + break; + case WDIOC_SETOPTIONS: + if ( copy_from_user(&value, argp, sizeof(int)) ) + return -EFAULT; + switch(value) { + case WDIOS_ENABLECARD: + rdc321x_wdt_start(); + break; + case WDIOS_DISABLECARD: + return rdc321x_wdt_stop(); + default: + return -EINVAL; + } + break; + default: + return -ENOTTY; + } + return 0; +} + +static ssize_t rdc321x_wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) +{ + if ( !count ) + return -EIO; + + rdc321x_wdt_reset(); + + return count; +} + +static const struct file_operations rdc321x_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .ioctl = rdc321x_wdt_ioctl, + .open = rdc321x_wdt_open, + .write = rdc321x_wdt_write, + .release = rdc321x_wdt_release, +}; + +static struct miscdevice rdc321x_wdt_misc = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &rdc321x_wdt_fops, +}; + +static int __devinit rdc321x_wdt_probe(struct platform_device *pdev) +{ + int err; + + if ( (err = misc_register(&rdc321x_wdt_misc)) < 0 ) { + printk(KERN_ERR PFX "misc_register failed\n"); + return err; + } + + /* Reset the watchdog */ + outl(RDC_WDT_RST, RDC3210_CFGREG_DATA); + + init_completion(&rdc321x_wdt_device.stop); + rdc321x_wdt_device.queue = 0; + + clear_bit(0, &rdc321x_wdt_device.inuse); + + setup_timer(&rdc321x_wdt_device.timer, rdc321x_wdt_trigger, 0); + + rdc321x_wdt_device.default_ticks = ticks; + + printk(KERN_INFO PFX "init success\n"); + + return 0; +} + +static int rdc321x_wdt_remove(struct platform_device *pdev) +{ + if (rdc321x_wdt_device.queue) { + rdc321x_wdt_device.queue = 0; + wait_for_completion(&rdc321x_wdt_device.stop); + } + + misc_deregister(&rdc321x_wdt_misc); + + return 0; +} + +static struct platform_driver rdc321x_wdt_driver = { + .probe = rdc321x_wdt_probe, + .remove = rdc321x_wdt_remove, + .driver = { + .owner = THIS_MODULE, + .name = "rdc321x_wdt", + }, +}; + +static int __init rdc321x_wdt_init(void) +{ + return platform_driver_register(&rdc321x_wdt_driver); +} + +static void __exit rdc321x_wdt_exit(void) +{ + platform_driver_unregister(&rdc321x_wdt_driver); +} + +module_init(rdc321x_wdt_init); +module_exit(rdc321x_wdt_exit); + +MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); +MODULE_DESCRIPTION("RDC321x watchdog driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/target/linux/rdc/files/drivers/leds/leds-rdc3211.c b/target/linux/rdc/files/drivers/leds/leds-rdc3211.c new file mode 100644 index 000000000..ae068af14 --- /dev/null +++ b/target/linux/rdc/files/drivers/leds/leds-rdc3211.c @@ -0,0 +1,71 @@ +/* + * LED driver for RDC3211 boards + * + * Copyright 2007 Florian Fainelli <florian@openwrt.org> + * + * 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 <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/leds.h> +#include <linux/err.h> + +#include <asm/gpio.h> + +static void rdc321x_led_set(struct led_classdev *led_cdev, enum led_brightness brightness) +{ + gpio_set_value(1, brightness ? 1 : 0); +} + +/* The DMZ led is at GPIO line 1 */ +static struct led_classdev rdc321x_dmz_led = { + .name = "rdc321x:dmz", + .brightness_set = rdc321x_led_set, +}; + +static int rdc321x_leds_probe(struct platform_device *pdev) +{ + return led_classdev_register(&pdev->dev, &rdc321x_dmz_led); +} + +static int rdc321x_leds_remove(struct platform_device *pdev) +{ + led_classdev_unregister(&rdc321x_dmz_led); + return 0; +} + +static struct platform_driver rdc321x_leds_driver = { + .probe = rdc321x_leds_probe, + .remove = rdc321x_leds_remove, + .driver = { + .name = "rdc321x-leds", + .owner = THIS_MODULE, + } +}; + +static int __init rdc321x_leds_init(void) +{ + int ret; + + ret = platform_driver_register(&rdc321x_leds_driver); + + return ret; +} + +static void __exit rdc321x_leds_exit(void) +{ + platform_driver_unregister(&rdc321x_leds_driver); +} + +module_init(rdc321x_leds_init); +module_exit(rdc321x_leds_exit); + +MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); +MODULE_DESCRIPTION("RDC321x LED driver"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/rdc/files/drivers/mtd/maps/imghdr.h b/target/linux/rdc/files/drivers/mtd/maps/imghdr.h new file mode 100644 index 000000000..7232b7061 --- /dev/null +++ b/target/linux/rdc/files/drivers/mtd/maps/imghdr.h @@ -0,0 +1,25 @@ +#ifndef GT_IMGHDR_H +#define GT_IMGHDR_H + +#define GTIMG_MAGIC "GMTK" + +/* Product ID */ +#define PID_RTL_AIRGO 1 +#define PID_RTL_RALINK 2 +#define PID_RDC_AIRGO 3 +#define PID_RDC_RALINK 5 /* White Lable */ + +/* Gemtek */ +typedef struct +{ + u8 magic[4]; /* ASICII: GMTK */ + u32 checksum; /* CRC32 */ + u32 version; /* x.x.x.x */ + u32 kernelsz; /* The size of the kernel image */ + u32 imagesz; /* The length of this image file ( kernel + romfs + this header) */ + u32 pid; /* Product ID */ + u32 fastcksum; /* Partial CRC32 on (First(256), medium(256), last(512)) */ + u32 reserved; +}gt_imghdr_t; + +#endif diff --git a/target/linux/rdc/files/drivers/mtd/maps/rdc3210.c b/target/linux/rdc/files/drivers/mtd/maps/rdc3210.c new file mode 100644 index 000000000..fb2a3f854 --- /dev/null +++ b/target/linux/rdc/files/drivers/mtd/maps/rdc3210.c @@ -0,0 +1,379 @@ +/******************************************************************* + * Simple Flash mapping for RDC3210 * + * * + * 2005.03.23 * + * Dante Su (dante_su@gemtek.com.tw) * + * Copyright (C) 2005 Gemtek Corporation * + *******************************************************************/ + +#include <linux/module.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <asm/io.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/map.h> +#include <linux/mtd/partitions.h> +#include <linux/autoconf.h> +#include <linux/sched.h> +#include <linux/squashfs_fs.h> + +static struct mtd_info *rdc3210_mtd; + +struct map_info rdc3210_map = +{ + .name = "RDC3210 Flash", + .size = CONFIG_MTD_RDC3210_SIZE, + .bankwidth = CONFIG_MTD_RDC3210_BUSWIDTH, +}; + +/* Dante: This is the default static mapping, however this is nothing but a hint. (Say dynamic mapping) */ +static struct mtd_partition rdc3210_parts[] = +{ +#if CONFIG_MTD_RDC3210_SIZE == 0x400000 + { name: "linux", offset: 0, size: 0x003C0000 }, /* 3840 KB = (Kernel + ROMFS) = (768 KB + 3072 KB) */ + { name: "romfs", offset: 0x000C0000, size: 0x00300000 }, /* 3072 KB */ + { name: "nvram", offset: 0x003C0000, size: 0x00010000 }, /* 64 KB */ +#ifdef CONFIG_MTD_RDC3210_FACTORY_PRESENT + { name: "factory", offset: 0x003D0000, size: 0x00010000 }, /* 64 KB */ +#endif + { name: "bootldr", offset: 0x003E0000, size: 0x00020000 }, /* 128 KB */ +#elif CONFIG_MTD_RDC3210_SIZE == 0x200000 + { name: "linux", offset: 0x00008000, size: 0x001E8000 }, + { name: "romfs", offset: 0x000C8000, size: 0x00128000 }, + { name: "nvram", offset: 0x00000000, size: 0x00008000 }, /* 64 KB */ +#ifdef CONFIG_MTD_RDC3210_FACTORY_PRESENT +#error Unsupported configuration! +#endif + { name: "bootldr", offset: 0x001F0000, size: 0x00010000 }, +#else +#error Unsupported configuration! +#endif +}; + +static __u32 crctab[257] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, + 0 +}; + +static __u32 crc32(__u8 * buf, __u32 len) +{ + register int i; + __u32 sum; + register __u32 s0; + s0 = ~0; + for (i = 0; i < len; i++) { + s0 = (s0 >> 8) ^ crctab[(__u8) (s0 & 0xFF) ^ buf[i]]; + } + sum = ~s0; + return sum; +} + +static void erase_callback(struct erase_info *done) +{ + wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv; + wake_up(wait_q); +} + +static int erase_write (struct mtd_info *mtd, unsigned long pos, + int len, const char *buf) +{ + struct erase_info erase; + DECLARE_WAITQUEUE(wait, current); + wait_queue_head_t wait_q; + size_t retlen; + int ret; + + /* + * First, let's erase the flash block. + */ + + init_waitqueue_head(&wait_q); + erase.mtd = mtd; + erase.callback = erase_callback; + erase.addr = pos; + erase.len = len; + erase.priv = (u_long)&wait_q; + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&wait_q, &wait); + + ret = mtd->erase(mtd, &erase); + if (ret) { + set_current_state(TASK_RUNNING); + remove_wait_queue(&wait_q, &wait); + printk (KERN_WARNING "erase of region [0x%lx, 0x%x] " + "on \"%s\" failed\n", + pos, len, mtd->name); + return ret; + } + + schedule(); /* Wait for erase to finish. */ + remove_wait_queue(&wait_q, &wait); + + /* + * Next, writhe data to flash. + */ + + ret = mtd->write (mtd, pos, len, &retlen, buf); + if (ret) + return ret; + if (retlen != len) + return -EIO; + return 0; +} + +static int __init init_rdc3210_map(void) +{ + rdc3210_map.phys = -rdc3210_map.size; + printk(KERN_NOTICE "flash device: %x at %x\n", rdc3210_map.size, rdc3210_map.phys); + + rdc3210_map.map_priv_1 = (unsigned long)(rdc3210_map.virt = ioremap_nocache(rdc3210_map.phys, rdc3210_map.size)); + + if (!rdc3210_map.map_priv_1) + { + printk("Failed to ioremap\n"); + return -EIO; + } + rdc3210_mtd = do_map_probe("cfi_probe", &rdc3210_map); +#ifdef CONFIG_MTD_RDC3210_STATIC_MAP /* Dante: This is for fixed map */ + if (rdc3210_mtd) + { + rdc3210_mtd->module = THIS_MODULE; + add_mtd_partitions(rdc3210_mtd, rdc3210_parts, sizeof(rdc3210_parts)/sizeof(rdc3210_parts[0])); + return 0; + } +#else /* Dante: This is for dynamic mapping */ + +#include "imghdr.h" + + typedef struct { + u8 magic[4]; + u32 kernelsz, ramdisksz; + u8 magic2[4]; + u32 sz2; + }sc_imghdr_t; + + if (rdc3210_mtd) + { // Dante + sc_imghdr_t *hdr2= (sc_imghdr_t *)(rdc3210_map.map_priv_1); + gt_imghdr_t *hdr = (gt_imghdr_t *)hdr2 +#ifdef CONFIG_MTD_RDC3210_ALLOW_JFFS2 + , *ptmp +#endif + ; + int len, tmp, tmp2, tmp3, tmp4, hdr_type = 0; + + if(!memcmp(hdr->magic, GTIMG_MAGIC, 4)) + { + hdr_type = 1; + tmp = hdr->kernelsz + sizeof(gt_imghdr_t); + tmp2 = rdc3210_mtd->erasesize; + tmp3 = ((tmp / 32) + ((tmp % 32) ? 1 : 0)) * 32; + tmp4 = ((tmp / tmp2) + ((tmp % tmp2) ? 1 : 0)) * tmp2; + } +#ifndef CONFIG_MTD_RDC3210_ALLOW_JFFS2 + else if (!memcmp(hdr2->magic, "CSYS", 4)) + { + hdr_type = 2; + tmp = hdr2->ramdisksz + hdr2->kernelsz + sizeof(sc_imghdr_t); + tmp2 = rdc3210_mtd->erasesize; + tmp3 = ((tmp / 32) + ((tmp % 32) ? 1 : 0)) * 32; + tmp4 = ((tmp / tmp2) + ((tmp % tmp2) ? 1 : 0)) * tmp2; + } +#endif + else + { + iounmap((void *)rdc3210_map.map_priv_1); + rdc3210_map.map_priv_1 = 0L; + rdc3210_map.virt = NULL; + printk("Invalid MAGIC for Firmware Image!!!\n"); + return -EIO; + } +#ifdef CONFIG_MTD_RDC3210_ALLOW_JFFS2 + tmp = (tmp3 == tmp4) ? tmp4 + tmp2 : tmp4; + if ((ptmp = (gt_imghdr_t *)vmalloc(tmp)) == NULL) + { + iounmap((void *)rdc3210_map.map_priv_1); + rdc3210_map.map_priv_1 = 0L; + rdc3210_map.virt = NULL; + printk("Can't allocate 0x%08x for flash-reading buffer!\n", tmp); + return -ENOMEM; + } + if (rdc3210_mtd->read(rdc3210_mtd, 0, tmp, &len, (__u8 *)ptmp) || len != tmp) + { + vfree(ptmp); + iounmap((void *)rdc3210_map.map_priv_1); + rdc3210_map.map_priv_1 = 0L; + rdc3210_map.virt = NULL; + printk("Can't read that much flash! Read 0x%08x of it.\n", len); + return -EIO; + } +#endif +#ifdef CONFIG_MTD_RDC3210_FACTORY_PRESENT + /* 1. Adjust Redboot */ + tmp = rdc3210_mtd->size - rdc3210_parts[4].size; + rdc3210_parts[4].offset = tmp - (tmp % tmp2); + rdc3210_parts[4].size = rdc3210_mtd->size - rdc3210_parts[4].offset; + + /* 2. Adjust Factory Default */ + tmp -= rdc3210_parts[3].size; + rdc3210_parts[3].offset = tmp - (tmp % tmp2); + rdc3210_parts[3].size = rdc3210_parts[4].offset - rdc3210_parts[3].offset; +#else + /* 1. Adjust Redboot */ + tmp = rdc3210_mtd->size - rdc3210_parts[3].size; + rdc3210_parts[3].offset = tmp - (tmp % tmp2); + rdc3210_parts[3].size = rdc3210_mtd->size - rdc3210_parts[3].offset; +#endif + if (hdr_type == 1) { + /* 3. Adjust NVRAM */ +#ifdef CONFIG_MTD_RDC3210_ALLOW_JFFS2 + if (*(__u32 *)(((unsigned char *)ptmp)+tmp3) == SQUASHFS_MAGIC) + { + len = 1; + tmp4 = tmp3; + tmp = hdr->imagesz; + rdc3210_parts[2].name = "rootfs_data"; + rdc3210_parts[2].offset = rdc3210_parts[0].offset + (((tmp / tmp2) + ((tmp % tmp2) ? 1 : 0)) * tmp2); + } + else +#else + tmp4 = tmp3; +#endif + { + len = 0; + tmp -= rdc3210_parts[2].size; + rdc3210_parts[2].offset = tmp - (tmp % tmp2); + } + rdc3210_parts[2].size = rdc3210_parts[3].offset - rdc3210_parts[2].offset; + } + else if (hdr_type == 2) + { + len = 0; + tmp4 = tmp3; + } + + /* 4. Adjust Linux (Kernel + ROMFS) */ + rdc3210_parts[0].size = rdc3210_parts[len + hdr_type + 1].offset - rdc3210_parts[0].offset; + + /* 5. Adjust ROMFS */ + rdc3210_parts[1].offset = rdc3210_parts[0].offset + tmp4; + rdc3210_parts[1].size = rdc3210_parts[hdr_type + 1].offset - rdc3210_parts[1].offset; +#ifdef CONFIG_MTD_RDC3210_ALLOW_JFFS2 + if (!(hdr->reserved || len)) + { + __u8 buf[1024]; + ptmp->reserved = hdr->imagesz; + ptmp->imagesz = tmp4; + ptmp->checksum = ptmp->fastcksum = 0; + memcpy(buf, ptmp, 0x100); + memcpy(buf + 0x100, ((__u8 *)ptmp) + ((tmp4 >> 1) - ((tmp4 & 0x6) >> 1)), 0x100); + memcpy(buf + 0x200, ((__u8 *)ptmp) + (tmp4 - 0x200), 0x200); + ptmp->fastcksum = crc32(buf, sizeof(buf)); + ptmp->checksum = crc32((__u8 *)ptmp, tmp4); + if (rdc3210_mtd->unlock) rdc3210_mtd->unlock(rdc3210_mtd, 0, tmp2); + if ((len = erase_write(rdc3210_mtd, 0, tmp2, (char *)ptmp))) + { + vfree(ptmp); + iounmap((void *)rdc3210_map.map_priv_1); + rdc3210_map.map_priv_1 = 0L; + rdc3210_map.virt = NULL; + printk("Couldn't erase! Got %d.\n", len); + return len; + } + if (rdc3210_mtd->sync) rdc3210_mtd->sync(rdc3210_mtd); + } + vfree(ptmp); +#endif + rdc3210_mtd->owner = THIS_MODULE; + add_mtd_partitions(rdc3210_mtd, rdc3210_parts, sizeof(rdc3210_parts)/sizeof(rdc3210_parts[0])); + return 0; + } +#endif + iounmap((void *)rdc3210_map.map_priv_1); + rdc3210_map.map_priv_1 = 0L; + rdc3210_map.virt = NULL; + return -ENXIO; +} + +static void __exit cleanup_rdc3210_map(void) +{ + if (rdc3210_mtd) + { + del_mtd_partitions(rdc3210_mtd); + map_destroy(rdc3210_mtd); + } + + if (rdc3210_map.map_priv_1) + { + iounmap((void *)rdc3210_map.map_priv_1); + rdc3210_map.map_priv_1 = 0L; + rdc3210_map.virt = NULL; + } +} + +module_init(init_rdc3210_map); +module_exit(cleanup_rdc3210_map); diff --git a/target/linux/rdc/files/drivers/net/r6040.c b/target/linux/rdc/files/drivers/net/r6040.c new file mode 100644 index 000000000..376b6ecfe --- /dev/null +++ b/target/linux/rdc/files/drivers/net/r6040.c @@ -0,0 +1,1041 @@ +/* r6040.c: A RDC R6040 FastEthernet driver for linux. */ +/* + Re-written 2004 by Sten Wang. + + Copyright 1994-2000 by Donald Becker. + Copyright 1993 United States Government as represented by the + Director, National Security Agency. This software may be used and + distributed according to the terms of the GNU General Public License, + incorporated herein by reference. + + This driver is for RDC R6040 FastEthernet MAC series. + For kernel version after 2.4.22 + + Modification List + ---------- ------------------------------------------------ + 08-24-2006 Support at linux 2.6.10 above + 03-24-2006 Support NAPI + 03-21-2006 By Charies,change spin_lock_irqsave(lp->lock, flags) to + spin_lock_irqsave(&lp->lock, flags) in set_multicast_list + 03-15-2006 Modify the set_multicast_list ,due to when re-plug the ethernet, + it will forget the previous setting + 07-12-2005 Tim, modify the set_multicast_list + 03-28-2005 Tim, modify some error mac register offset in + function set_multicast_list + 03-27-2005 Tim, Add the internal state machine reset + Sten, If multicast address more than 4, enter PROM mode + Changed rdc to r6040 + 12-22-2004 Sten Init MAC MBCR register=0x012A + PHY_CAP = 0x01E1 + + Need to Do LIst: + 1. If multicast address more than 4, use the multicast address hash +*/ + +#define DRV_NAME "r6040" +#define DRV_VERSION "0.13" +#define DRV_RELDATE "24Aug2006" + +/* PHY CHIP Address */ +#define PHY1_ADDR 1 /* For MAC1 */ +#define PHY2_ADDR 2 /* For MAC2 */ +#define PHY_MODE 0x3100 /* PHY CHIP Register 0 */ +#define PHY_CAP 0x01E1 /* PHY CHIP Register 4 */ + +/* Time in jiffies before concluding the transmitter is hung. */ +#define TX_TIMEOUT (6000 * HZ / 1000) +#define TIMER_WUT (jiffies + HZ * 1)/* timer wakeup time : 1 second */ + +/* RDC MAC ID */ +#define RDC_MAC_ID 0x6040 + +/* RDC MAC I/O Size */ +#define R6040_IO_SIZE 256 + +/* RDC Chip PCI Command */ +#define R6040_PCI_CMD 0x0005 /* IO, Master */ + +/* MAX RDC MAC */ +#define MAX_MAC 2 + +/* MAC setting */ +#define TX_DCNT 0x80 /* TX descriptor count */ +#define RX_DCNT 0x80 /* RX descriptor count */ +#define MAX_BUF_SIZE 0x600 +#define ALLOC_DESC_SIZE ((TX_DCNT+RX_DCNT)*sizeof(struct r6040_descriptor)+0x10) +#define MBCR_DEFAULT 0x012A /* MAC Bus Control Register */ + +/* Debug enable or not */ +#define RDC_DEBUG 0 + +#if RDC_DEBUG > 1 +#define RDC_DBUG(msg, value) printk("%s %x\n", msg, value); +#else +#define RDC_DBUG(msg, value) +#endif + + +#include <linux/module.h> +#include <linux/version.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) +#include <linux/moduleparam.h> +#endif +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/timer.h> +#include <linux/errno.h> +#include <linux/ioport.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/init.h> +#include <linux/delay.h> /* for udelay() */ +#include <linux/mii.h> +#include <linux/ethtool.h> +#include <linux/crc32.h> +#include <linux/spinlock.h> + +#include <asm/processor.h> +#include <asm/bitops.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/uaccess.h> + +MODULE_AUTHOR("Sten Wang <sten.wang@rdc.com.tw>"); +MODULE_LICENSE("GPL"); +#ifdef CONFIG_R6040_NAPI +MODULE_DESCRIPTION("RDC R6040 NAPI PCI FastEthernet Driver"); +#else +MODULE_DESCRIPTION("RDC R6040 PCI FastEthernet Driver"); +#endif + +#define R6040_INT_MASK 0x0011 + +struct r6040_descriptor { + u16 status, len; /* 0-3 */ + u32 buf; /* 4-7 */ + u32 ndesc; /* 8-B */ + u32 rev1; /* C-F */ + char *vbufp; /* 10-13 */ + struct r6040_descriptor *vndescp; /* 14-17 */ + struct sk_buff *skb_ptr; /* 18-1B */ + u32 rev2; /* 1C-1F */ +} __attribute__(( aligned(32) )); + +struct r6040_private { + struct net_device_stats stats; + spinlock_t lock; + struct timer_list timer; + struct pci_dev *pdev; + + struct r6040_descriptor *rx_insert_ptr; + struct r6040_descriptor *rx_remove_ptr; + struct r6040_descriptor *tx_insert_ptr; + struct r6040_descriptor *tx_remove_ptr; + u16 tx_free_desc, rx_free_desc, phy_addr, phy_mode; + u16 mcr0, mcr1; + dma_addr_t desc_dma; + char *desc_pool; + u16 switch_sig; +}; + +struct r6040_chip_info { + const char *name; + u16 pci_flags; + int io_size; + int drv_flags; +}; + +#ifdef CONFIG_R6040_NAPI +static int NAPI_status; +#endif + +static int __devinitdata printed_version; +#ifdef CONFIG_R6040_NAPI +static char version[] __devinitdata = + KERN_INFO DRV_NAME ": RDC R6040 NAPI net driver, version "DRV_VERSION " (" DRV_RELDATE ")\n"; +#else +static char version[] __devinitdata = + KERN_INFO DRV_NAME ": RDC R6040 net driver, version "DRV_VERSION " (" DRV_RELDATE ")\n"; +#endif +static struct r6040_chip_info r6040_chip_info[] __devinitdata = +{ + { "RDC R6040 Knight", R6040_PCI_CMD, R6040_IO_SIZE, 0} +}; +static char *parent = NULL; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) +static int NUM_MAC_TABLE = 2 ; +module_param(parent, charp, 0444); +#else +MODULE_PARM(parent, "s"); +#endif +MODULE_PARM_DESC(parent, "Parent network device name"); + +static int phy_table[] = { 0x1, 0x2}; +static u8 adr_table[2][8] = {{0x00, 0x00, 0x60, 0x00, 0x00, 0x01}, {0x00, 0x00, 0x60, 0x00, 0x00, 0x02}}; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10) + module_param_array(adr_table, int, &NUM_MAC_TABLE, 0644); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) + module_param_array(adr_table, int, NUM_MAC_TABLE, 0644); +#else + MODULE_PARM(adr_table, "2-4i"); +#endif +MODULE_PARM_DESC(adr_table, "MAC Address (assigned)"); + +static int r6040_open(struct net_device *dev); +static int r6040_start_xmit(struct sk_buff *skb, struct net_device *dev); +static irqreturn_t r6040_interrupt(int irq, void *dev_id); +static struct net_device_stats *r6040_get_stats(struct net_device *dev); +static int r6040_close(struct net_device *dev); +static void set_multicast_list(struct net_device *dev); +static struct ethtool_ops netdev_ethtool_ops; +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); +static void r6040_down(struct net_device *dev); +static void r6040_up(struct net_device *dev); +static void r6040_tx_timeout (struct net_device *dev); +static void r6040_timer(unsigned long); + +static int phy_mode_chk(struct net_device *dev); +static int phy_read(int ioaddr, int phy_adr, int reg_idx); +static void phy_write(int ioaddr, int phy_adr, int reg_idx, int dat); +static void rx_buf_alloc(struct r6040_private *lp,struct net_device *dev); +#ifdef CONFIG_R6040_NAPI +static int r6040_poll(struct net_device *netdev, int *budget); +#endif + + +static int __devinit r6040_init_one (struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct net_device *dev; + struct r6040_private *lp; + int ioaddr, io_size, err; + static int card_idx = -1; + int chip_id = (int)ent->driver_data; + + RDC_DBUG("r6040_init_one()", 0); + + if (printed_version++) + printk(version); + + if ((err = pci_enable_device (pdev))) + return err; + + /* this should always be supported */ + if (pci_set_dma_mask(pdev, 0xffffffff)) { + printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses not supported by the card!?\n"); + return -ENODEV; + } + + /* IO Size check */ + io_size = r6040_chip_info[chip_id].io_size; + if (pci_resource_len (pdev, 0) < io_size) { + return -ENODEV; + } + + ioaddr = pci_resource_start (pdev, 0); /* IO map base address */ + pci_set_master(pdev); + + dev = alloc_etherdev(sizeof(struct r6040_private)); + if (dev == NULL) + return -ENOMEM; + SET_MODULE_OWNER(dev); + + if (pci_request_regions(pdev, DRV_NAME)) { + printk(KERN_ERR DRV_NAME ": Failed to request PCI regions\n"); + err = -ENODEV; + goto err_out_disable; + } + + /* Init system & device */ + lp = dev->priv; + dev->base_addr = ioaddr; + dev->irq = pdev->irq; + + spin_lock_init(&lp->lock); + pci_set_drvdata(pdev, dev); + + /* Set MAC address */ + card_idx++; + memcpy(dev->dev_addr, (u8 *)&adr_table[card_idx][0], 6); + + /* Link new device into r6040_root_dev */ + lp->pdev = pdev; + + /* Init RDC private data */ + lp->mcr0 = 0x1002; + lp->phy_addr = phy_table[card_idx]; + lp->switch_sig = 0; + + /* The RDC-specific entries in the device structure. */ + dev->open = &r6040_open; + dev->hard_start_xmit = &r6040_start_xmit; + dev->stop = &r6040_close; + dev->get_stats = &r6040_get_stats; + dev->set_multicast_list = &set_multicast_list; + dev->do_ioctl = &netdev_ioctl; + dev->ethtool_ops = &netdev_ethtool_ops; + dev->tx_timeout = &r6040_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; +#ifdef CONFIG_R6040_NAPI + dev->poll = &r6040_poll; + dev->weight = 64; +#endif + + /* Register net device. After this dev->name assign */ + if ((err = register_netdev(dev))) { + printk(KERN_ERR DRV_NAME ": Failed to register net device\n"); + goto err_out_res; + } + + netif_carrier_on(dev); + return 0; + +err_out_res: + pci_release_regions(pdev); +err_out_disable: + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + kfree(dev); + + return err; +} + +static void __devexit r6040_remove_one (struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + + unregister_netdev(dev); + pci_release_regions(pdev); + kfree(dev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); +} + +static int +r6040_open(struct net_device *dev) +{ + struct r6040_private *lp = dev->priv; + int i; + + RDC_DBUG("r6040_open()", 0); + + /* Request IRQ and Register interrupt handler */ + i = request_irq(dev->irq, &r6040_interrupt, SA_SHIRQ, dev->name, dev); + if (i) return i; + + /* Allocate Descriptor memory */ + lp->desc_pool = pci_alloc_consistent(lp->pdev, ALLOC_DESC_SIZE, &lp->desc_dma); + if (!lp->desc_pool) return -ENOMEM; + + r6040_up(dev); + + netif_start_queue(dev); + + if (lp->switch_sig != 0x0243) + { + /* set and active a timer process */ + init_timer(&lp->timer); + lp->timer.expires = TIMER_WUT; + lp->timer.data = (unsigned long)dev; + lp->timer.function = &r6040_timer; + add_timer(&lp->timer); + } + return 0; +} + +static void +r6040_tx_timeout (struct net_device *dev) +{ + struct r6040_private *lp = dev->priv; + //int ioaddr = dev->base_addr; + //struct r6040_descriptor *descptr = lp->tx_remove_ptr; + + RDC_DBUG("r6040_tx_timeout()", 0); + + /* Transmitter timeout, serious problems. */ + /* Sten: Nothing need to do so far. */ + printk(KERN_ERR DRV_NAME ": Big Trobule, transmit timeout/n"); + lp->stats.tx_errors++; + netif_stop_queue(dev); + +//printk("<RDC> XMT timedout: CR0 %x, CR40 %x, CR3C %x, CR2C %x, CR30 %x, CR34 %x, CR38 %x\n", inw(ioaddr), inw(ioaddr+0x40), inw(ioaddr+0x3c), inw(ioaddr+0x2c), inw(ioaddr+0x30), inw(ioaddr+0x34), inw(ioaddr+0x38)); + +//printk("<RDC> XMT_TO: %08lx:%04x %04x %08lx %08lx %08lx %08lx\n", descptr, descptr->status, descptr->len, descptr->buf, descptr->skb_ptr, descptr->ndesc, descptr->vndescp); +} + + +static int +r6040_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct r6040_private *lp = dev->priv; + struct r6040_descriptor *descptr; + int ioaddr = dev->base_addr; + unsigned long flags; + + RDC_DBUG("r6040_start_xmit()", 0); + + if (skb == NULL) /* NULL skb directly return */ + return 0; + if (skb->len >= MAX_BUF_SIZE) { /* Packet too long, drop it */ + dev_kfree_skb(skb); + return 0; + } + + /* Critical Section */ + spin_lock_irqsave(&lp->lock, flags); + + /* TX resource check */ + if (!lp->tx_free_desc) { + spin_unlock_irqrestore(&lp->lock, flags); + printk(KERN_ERR DRV_NAME ": NO TX DESC "); + return 1; + } + + /* Statistic Counter */ + lp->stats.tx_packets++; + lp->stats.tx_bytes += skb->len; + + /* Set TX descriptor & Transmit it */ + lp->tx_free_desc--; + descptr = lp->tx_insert_ptr; + if (skb->len < 0x3c) descptr->len = 0x3c; + else descptr->len = skb->len; + descptr->skb_ptr = skb; + descptr->buf = cpu_to_le32(pci_map_single(lp->pdev, skb->data, skb->len, PCI_DMA_TODEVICE)); + descptr->status = 0x8000; + outw(0x01, ioaddr + 0x14); + lp->tx_insert_ptr = descptr->vndescp; + +#if RDC_DEBUG + printk("Xmit(): %08lx:%04x %04x %08lx %08lx %08lx %08lx\n", descptr, descptr->status, descptr->len, descptr->buf, descptr->skb_ptr, descptr->ndesc, descptr->vndescp); +#endif + + /* If no tx resource, stop */ + if (!lp->tx_free_desc) + netif_stop_queue(dev); + + dev->trans_start = jiffies; + spin_unlock_irqrestore(&lp->lock, flags); + return 0; +} + +/* The RDC interrupt handler. */ +static irqreturn_t +r6040_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct r6040_private *lp; + struct r6040_descriptor *descptr; + struct sk_buff *skb_ptr; + int ioaddr, status; + unsigned long flags; +#ifdef CONFIG_R6040_NAPI + int handled = 1; +#else + int handled = 0; +#endif + + RDC_DBUG("r6040_interrupt()", 0); + if (dev == NULL) { + printk (KERN_ERR DRV_NAME ": INT() unknown device.\n"); + return IRQ_RETVAL(handled); + } + + lp = (struct r6040_private *)dev->priv; + spin_lock_irqsave(&lp->lock, flags); + + /* Check MAC Interrupt status */ + ioaddr = dev->base_addr; + outw(0x0, ioaddr + 0x40); /* Mask Off RDC MAC interrupt */ + status = inw(ioaddr + 0x3c); /* Read INTR status and clear */ + + +#ifdef CONFIG_R6040_NAPI + + if(netif_rx_schedule_prep(dev)) + { + NAPI_status = status ; + __netif_rx_schedule(dev); + } + + spin_unlock_irqrestore(&lp->lock, flags); + return IRQ_RETVAL(handled); +#else + /* TX interrupt request */ + if (status & 0x10) { + handled = 1; + descptr = lp->tx_remove_ptr; + while(lp->tx_free_desc < TX_DCNT) { + if (descptr->status & 0x8000) break; /* Not complte */ + skb_ptr = descptr->skb_ptr; + pci_unmap_single(lp->pdev, descptr->buf, skb_ptr->len, PCI_DMA_TODEVICE); + dev_kfree_skb_irq(skb_ptr); /* Free buffer */ + descptr->skb_ptr = 0; + descptr = descptr->vndescp; /* To next descriptor */ + lp->tx_free_desc++; + } + lp->tx_remove_ptr = descptr; + if (lp->tx_free_desc) netif_wake_queue(dev); + } + + /* RX interrupt request */ + if (status & 0x01) { + handled = 1; + descptr = lp->rx_remove_ptr; + while(lp->rx_free_desc) { + if (descptr->status & 0x8000) break; /* No Rx packet */ + skb_ptr = descptr->skb_ptr; + descptr->skb_ptr = 0; + skb_ptr->dev = dev; + skb_put(skb_ptr, descptr->len - 4); + pci_unmap_single(lp->pdev, descptr->buf, MAX_BUF_SIZE, PCI_DMA_FROMDEVICE); + skb_ptr->protocol = eth_type_trans(skb_ptr, dev); + netif_rx(skb_ptr); /* Send to upper layer */ + lp->stats.rx_packets++; + lp->stats.rx_bytes += descptr->len; + descptr = descptr->vndescp; /* To next descriptor */ + lp->rx_free_desc--; + } + lp->rx_remove_ptr = descptr; + } + + /* Allocate new RX buffer */ + if (lp->rx_free_desc < RX_DCNT) rx_buf_alloc(lp,dev); + + outw(R6040_INT_MASK, ioaddr + 0x40); /* TX/RX interrupt enable */ + spin_unlock_irqrestore(&lp->lock, flags); +#endif + return IRQ_RETVAL(handled); +} + + +static struct net_device_stats * +r6040_get_stats(struct net_device *dev) +{ + struct r6040_private *lp = dev->priv; + + RDC_DBUG("r6040_get_stats()", 0); + return &lp->stats; +} + +/* + * Set or clear the multicast filter for this adaptor. + */ +static void +set_multicast_list(struct net_device *dev) +{ + struct r6040_private *lp = dev->priv; + struct dev_mc_list *mcptr; + int ioaddr = dev->base_addr; + u16 *adrp, i; + unsigned long flags; + + RDC_DBUG("set_multicast_list()", 0); + + /* MAC Address */ + adrp = (u16 *) dev->dev_addr; + outw(adrp[0], ioaddr + 0x68); + outw(adrp[1], ioaddr + 0x6A); + outw(adrp[2], ioaddr + 0x6C); + + +#if RDC_DEBUG + printk("MAC ADDR: %04x %04x %04x\n", adrp[0], adrp[1], adrp[2]); +#endif + + /* Promiscous Mode */ + spin_lock_irqsave(&lp->lock, flags); + i = inw(ioaddr) & ~0x0120; /* Clear AMCP & PROM */ + if (dev->flags & IFF_PROMISC) + { + i |= 0x0020; + lp->mcr0 |= 0x0020 ; + } + if (dev->mc_count > 4) i |= 0x0020; /* Too many multicast address */ + outw(i, ioaddr); + spin_unlock_irqrestore(&lp->lock, flags); + + /* Multicast Address */ + if (dev->mc_count > 4) /* Wait to do: Hash Table for multicast */ + return; + + /* Multicast Address 1~4 case */ + for (i = 0, mcptr = dev->mc_list; (i<dev->mc_count) && (i<4); i++) { + adrp = (u16 *)mcptr->dmi_addr; + outw(adrp[0], ioaddr + 0x70 + 8*i); + outw(adrp[1], ioaddr + 0x72 + 8*i); + outw(adrp[2], ioaddr + 0x74 + 8*i); + mcptr = mcptr->next; +#if RDC_DEBUG + printk("M_ADDR: %04x %04x %04x\n", adrp[0], adrp[1], adrp[2]); +#endif + } + for (i = dev->mc_count; i < 4; i++) { + outw(0xffff, ioaddr + 0x68 + 8*i); + outw(0xffff, ioaddr + 0x6A + 8*i); + outw(0xffff, ioaddr + 0x6C + 8*i); + } +} + +static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct r6040_private *rp = dev->priv; + + strcpy (info->driver, DRV_NAME); + strcpy (info->version, DRV_VERSION); + strcpy (info->bus_info, pci_name(rp->pdev)); +} + +static struct ethtool_ops netdev_ethtool_ops = { + .get_drvinfo = netdev_get_drvinfo, +}; + +static int +r6040_close(struct net_device *dev) +{ + struct r6040_private *lp = dev->priv; + + RDC_DBUG("r6040_close()", 0); + + /* deleted timer */ + del_timer_sync(&lp->timer); + + spin_lock_irq(&lp->lock); + + netif_stop_queue(dev); + + r6040_down(dev); + + spin_unlock_irq(&lp->lock); + + return 0; +} + +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct r6040_private *lp = dev->priv; + + RDC_DBUG("netdev_ioctl()", 0); + if (lp->switch_sig == 0x0243 && cmd == SIOCDEVPRIVATE) + { + unsigned long *data = (unsigned long *)rq->ifr_data, args[4]; + int ioaddr = dev->base_addr; + unsigned int val; + + data = (unsigned long *)rq->ifr_data; + if (copy_from_user(args, data, 4*sizeof(unsigned long))) + return -EFAULT; + + /* port priority */ + if(args[0]&(1<<31))phy_write(ioaddr,29,19,(phy_read(ioaddr,29,19)|0x2000)); /* port 0 */ + if(args[0]&(1<<29))phy_write(ioaddr,29,19,(phy_read(ioaddr,29,19)|0x0020)); /* port 1 */ + if(args[0]&(1<<27))phy_write(ioaddr,29,20,(phy_read(ioaddr,29,20)|0x2000)); /* port 2 */ + if(args[0]&(1<<25))phy_write(ioaddr,29,20,(phy_read(ioaddr,29,20)|0x0020)); /* port 3 */ + + } + return -EOPNOTSUPP; +} + +/** + Stop RDC MAC and Free the allocated resource + */ +static void r6040_down(struct net_device *dev) +{ + struct r6040_private *lp = dev->priv; + int i; + int ioaddr = dev->base_addr; + + RDC_DBUG("r6040_down()", 0); + + /* Stop MAC */ + outw(0x0000, ioaddr + 0x40); /* Mask Off Interrupt */ + outw(0x0001, ioaddr + 0x04); /* Reset RDC MAC */ + i = 0; + do{}while((i++ < 2048) && (inw(ioaddr + 0x04) & 0x1)); + + free_irq(dev->irq, dev); + + /* Free RX buffer */ + for (i = 0; i < RX_DCNT; i++) { + if (lp->rx_insert_ptr->skb_ptr) { + pci_unmap_single(lp->pdev, lp->rx_insert_ptr->buf, MAX_BUF_SIZE, PCI_DMA_FROMDEVICE); + dev_kfree_skb(lp->rx_insert_ptr->skb_ptr); + lp->rx_insert_ptr->skb_ptr = 0; + } + lp->rx_insert_ptr = lp->rx_insert_ptr->vndescp; + } + + /* Free TX buffer */ + for (i = 0; i < TX_DCNT; i++) { + if (lp->tx_insert_ptr->skb_ptr) { + pci_unmap_single(lp->pdev, lp->tx_insert_ptr->buf, MAX_BUF_SIZE, PCI_DMA_TODEVICE); + dev_kfree_skb(lp->tx_insert_ptr->skb_ptr); + lp->rx_insert_ptr->skb_ptr = 0; + } + lp->tx_insert_ptr = lp->tx_insert_ptr->vndescp; + } + + /* Free Descriptor memory */ + pci_free_consistent(lp->pdev, ALLOC_DESC_SIZE, lp->desc_pool, lp->desc_dma); +} + + + +#ifdef CONFIG_R6040_NAPI +static int r6040_poll(struct net_device *dev, int *budget) +{ + struct r6040_private *lp; + struct r6040_descriptor *descptr; + struct sk_buff *skb_ptr; + int ioaddr, status; + unsigned long flags; + + + ioaddr = dev->base_addr; + lp = (struct r6040_private *)dev->priv; + unsigned long rx_work = dev->quota ; + unsigned long rx ; + + +#if 1 + /* TX interrupt request */ + if (NAPI_status & 0x10) { + + descptr = lp->tx_remove_ptr; + while(lp->tx_free_desc < TX_DCNT) { + if (descptr->status & 0x8000) break; /* Not complte */ + skb_ptr = descptr->skb_ptr; + pci_unmap_single(lp->pdev, descptr->buf, skb_ptr->len, PCI_DMA_TODEVICE); + dev_kfree_skb_irq(skb_ptr); /* Free buffer */ + descptr->skb_ptr = 0; + descptr = descptr->vndescp; /* To next descriptor */ + lp->tx_free_desc++; + } + lp->tx_remove_ptr = descptr; + if (lp->tx_free_desc) netif_wake_queue(dev); + } +#endif +#if 1 + /* RX interrupt request */ + if (NAPI_status & 0x01) { + + descptr = lp->rx_remove_ptr; + while(lp->rx_free_desc) { + if (descptr->status & 0x8000) break; /* No Rx packet */ + skb_ptr = descptr->skb_ptr; + descptr->skb_ptr = 0; + skb_ptr->dev = dev; + skb_put(skb_ptr, descptr->len - 4); + pci_unmap_single(lp->pdev, descptr->buf, MAX_BUF_SIZE, PCI_DMA_FROMDEVICE); + skb_ptr->protocol = eth_type_trans(skb_ptr, dev); + netif_receive_skb(skb_ptr); /* Send to upper layer */ + lp->stats.rx_packets++; + lp->stats.rx_bytes += descptr->len; + descptr = descptr->vndescp; /* To next descriptor */ + lp->rx_free_desc--; + } + lp->rx_remove_ptr = descptr; + + } + /* Allocate new RX buffer */ + if (lp->rx_free_desc < RX_DCNT) rx_buf_alloc(lp,dev); + + local_irq_disable(); + netif_rx_complete(dev); + outw(R6040_INT_MASK,ioaddr + 0x40); + local_irq_enable(); + return 0; +#endif +} +#endif + +/* Init RDC MAC */ +static void r6040_up(struct net_device *dev) +{ + struct r6040_private *lp = dev->priv; + struct r6040_descriptor *descptr; + int i; + int ioaddr = dev->base_addr; + u32 tmp_addr; + dma_addr_t desc_dma, start_dma; + + RDC_DBUG("r6040_up()", 0); + + /* Initilize */ + lp->tx_free_desc = TX_DCNT; + lp->rx_free_desc = 0; + + /* Init descriptor */ + memset(lp->desc_pool, 0, ALLOC_DESC_SIZE); /* Let all descriptor = 0 */ + lp->tx_insert_ptr = (struct r6040_descriptor *)lp->desc_pool; + lp->tx_remove_ptr = lp->tx_insert_ptr; + lp->rx_insert_ptr = (struct r6040_descriptor *)lp->tx_insert_ptr+TX_DCNT; + lp->rx_remove_ptr = lp->rx_insert_ptr; + + /* Init TX descriptor */ + descptr = lp->tx_insert_ptr; + desc_dma = lp->desc_dma; + start_dma = desc_dma; + for (i = 0; i < TX_DCNT; i++) { + descptr->ndesc = cpu_to_le32(desc_dma + sizeof(struct r6040_descriptor)); + descptr->vndescp = (descptr + 1); + descptr = (descptr + 1); + desc_dma += sizeof(struct r6040_descriptor); + } + (descptr - 1)->ndesc = cpu_to_le32(start_dma); + (descptr - 1)->vndescp = lp->tx_insert_ptr; + + /* Init RX descriptor */ + start_dma = desc_dma; + descptr = lp->rx_insert_ptr; + for (i = 0; i < RX_DCNT; i++) { + descptr->ndesc = cpu_to_le32(desc_dma + sizeof(struct r6040_descriptor)); + descptr->vndescp = (descptr + 1); + descptr = (descptr + 1); + desc_dma += sizeof(struct r6040_descriptor); + } + (descptr - 1)->ndesc = cpu_to_le32(start_dma); + (descptr - 1)->vndescp = lp->rx_insert_ptr; + + /* Allocate buffer for RX descriptor */ + rx_buf_alloc(lp,dev); + +#if RDC_DEBUG +descptr = lp->tx_insert_ptr; +for (i = 0; i < TX_DCNT; i++) { + printk("%08lx:%04x %04x %08lx %08lx %08lx %08lx\n", descptr, descptr->status, descptr->len, descptr->buf, descptr->skb_ptr, descptr->ndesc, descptr->vndescp); + descptr = descptr->vndescp; +} +descptr = lp->rx_insert_ptr; +for (i = 0; i < RX_DCNT; i++) { + printk("%08lx:%04x %04x %08lx %08lx %08lx %08lx\n", descptr, descptr->status, descptr->len, descptr->buf, descptr->skb_ptr, descptr->ndesc, descptr->vndescp); + descptr = descptr->vndescp; +} +#endif + + /* MAC operation register */ + outw(0x01, ioaddr+0x04); /* Reset MAC */ + outw(2 , ioaddr+0xAC); /* Reset internal state machine */ + outw(0 , ioaddr+0xAC); + udelay(5000); + + /* TX and RX descriptor start Register */ + tmp_addr = cpu_to_le32(lp->tx_insert_ptr); + tmp_addr = virt_to_bus((volatile void *)tmp_addr); + outw((u16) tmp_addr, ioaddr+0x2c); + outw(tmp_addr >> 16, ioaddr+0x30); + tmp_addr = cpu_to_le32(lp->rx_insert_ptr); + tmp_addr = virt_to_bus((volatile void *)tmp_addr); + outw((u16) tmp_addr, ioaddr+0x34); + outw(tmp_addr >> 16, ioaddr+0x38); + + /* Buffer Size Register */ + outw(MAX_BUF_SIZE, ioaddr+0x18); + + if ((lp->switch_sig = phy_read(ioaddr, 0, 2)) == 0x0243) // ICPlus IP175C Signature + { + phy_write(ioaddr, 29,31, 0x175C); //Enable registers + lp->phy_mode = 0x8000; + } else { + /* PHY Mode Check */ + phy_write(ioaddr, lp->phy_addr, 4, PHY_CAP); + phy_write(ioaddr, lp->phy_addr, 0, PHY_MODE); + + if (PHY_MODE == 0x3100) + lp->phy_mode = phy_mode_chk(dev); + else + lp->phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0; + } + /* MAC Bus Control Register */ + outw(MBCR_DEFAULT, ioaddr+0x8); + + /* MAC TX/RX Enable */ + lp->mcr0 |= lp->phy_mode; + outw(lp->mcr0, ioaddr); + + /* set interrupt waiting time and packet numbers */ + outw(0x0802, ioaddr + 0x0C); + outw(0x0802, ioaddr + 0x10); + + /* upgrade performance (by RDC guys) */ + phy_write(ioaddr,30,17,(phy_read(ioaddr,30,17)|0x4000)); //bit 14=1 + phy_write(ioaddr,30,17,~((~phy_read(ioaddr,30,17))|0x2000)); //bit 13=0 + phy_write(ioaddr,0,19,0x0000); + phy_write(ioaddr,0,30,0x01F0); + + /* Interrupt Mask Register */ + outw(R6040_INT_MASK, ioaddr + 0x40); +} + +/* + A periodic timer routine + Polling PHY Chip Link Status +*/ +static void r6040_timer(unsigned long data) +{ + struct net_device *dev=(struct net_device *)data; + struct r6040_private *lp = dev->priv; + u16 ioaddr = dev->base_addr, phy_mode; + + RDC_DBUG("r6040_timer()", 0); + + /* Polling PHY Chip Status */ + if (PHY_MODE == 0x3100) + phy_mode = phy_mode_chk(dev); + else phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0; + + if (phy_mode != lp->phy_mode) { + lp->phy_mode = phy_mode; + lp->mcr0 = (lp->mcr0 & 0x7fff) | phy_mode; + outw(lp->mcr0, ioaddr); + printk("<RDC> Link Change %x \n", inw(ioaddr)); + } + + /* Debug */ +// printk("<RDC> Timer: CR0 %x CR40 %x CR3C %x\n", inw(ioaddr), inw(ioaddr+0x40), inw(ioaddr+0x3c)); + + /* Timer active again */ + lp->timer.expires = TIMER_WUT; + add_timer(&lp->timer); +} + +/* Allocate skb buffer for rx descriptor */ +static void rx_buf_alloc(struct r6040_private *lp,struct net_device *dev) +{ + struct r6040_descriptor *descptr; + int ioaddr = dev->base_addr ; + + RDC_DBUG("rx_buf_alloc()", 0); + descptr = lp->rx_insert_ptr; + while(lp->rx_free_desc < RX_DCNT){ + descptr->skb_ptr = dev_alloc_skb(MAX_BUF_SIZE); + if (!descptr->skb_ptr) break; + descptr->buf = cpu_to_le32(pci_map_single(lp->pdev, descptr->skb_ptr->tail, MAX_BUF_SIZE, PCI_DMA_FROMDEVICE)); + descptr->status = 0x8000; + descptr = descptr->vndescp; + lp->rx_free_desc++; + outw(lp->mcr0 | 0x0002, ioaddr); //Trigger Rx DMA + } + lp->rx_insert_ptr = descptr; +} + +/* Status of PHY CHIP */ +static int phy_mode_chk(struct net_device *dev) +{ + struct r6040_private *lp = dev->priv; + int ioaddr = dev->base_addr, phy_dat; + + RDC_DBUG("phy_mode_chk()", 0); + + /* PHY Link Status Check */ + phy_dat = phy_read(ioaddr, lp->phy_addr, 1); + if (!(phy_dat & 0x4)) return 0x8000; /* Link Failed, full duplex */ + + /* PHY Chip Auto-Negotiation Status */ + phy_dat = phy_read(ioaddr, lp->phy_addr, 1); + if (phy_dat & 0x0020) { + /* Auto Negotiation Mode */ + phy_dat = phy_read(ioaddr, lp->phy_addr, 5); + phy_dat &= phy_read(ioaddr, lp->phy_addr, 4); + if (phy_dat & 0x140) phy_dat = 0x8000; + else phy_dat = 0; + } else { + /* Force Mode */ + phy_dat = phy_read(ioaddr, lp->phy_addr, 0); + if (phy_dat & 0x100) phy_dat = 0x8000; + else phy_dat = 0x0000; + } + + return phy_dat; +}; + +/* Read a word data from PHY Chip */ +static int phy_read(int ioaddr, int phy_addr, int reg_idx) +{ + int i = 0; + + RDC_DBUG("phy_read()", 0); + outw(0x2000 + reg_idx + (phy_addr << 8), ioaddr + 0x20); + do{}while( (i++ < 2048) && (inw(ioaddr + 0x20) & 0x2000) ); + + return inw(ioaddr + 0x24); +} + +/* Write a word data from PHY Chip */ +static void phy_write(int ioaddr, int phy_addr, int reg_idx, int dat) +{ + int i = 0; + + RDC_DBUG("phy_write()", 0); + outw(dat, ioaddr + 0x28); + outw(0x4000 + reg_idx + (phy_addr << 8), ioaddr + 0x20); + do{}while( (i++ < 2048) && (inw(ioaddr + 0x20) & 0x4000) ); +} + +enum { + RDC_6040 = 0 +}; + +static struct pci_device_id r6040_pci_tbl[] = { + {0x17F3, 0x6040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RDC_6040}, + //{0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RDC_6040}, + {0,} /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, r6040_pci_tbl); + +static struct pci_driver r6040_driver = { + .name = "r6040", + .id_table = r6040_pci_tbl, + .probe = r6040_init_one, + .remove = __devexit_p(r6040_remove_one), +}; + + +static int __init r6040_init (void) +{ + RDC_DBUG("r6040_init()", 0); + + printk(version); + printed_version = 1; + + if (parent != NULL) + { + struct net_device *the_parent = dev_get_by_name(parent); + + if (the_parent == NULL) + { + printk (KERN_ERR DRV_NAME ": Unknown device \"%s\" specified.\n", parent); + return -EINVAL; + } + memcpy((u8 *)&adr_table[0][0], the_parent->dev_addr, 6); + memcpy((u8 *)&adr_table[1][0], the_parent->dev_addr, 6); + ++*(u8 *)&adr_table[0][5]; + } + return pci_register_driver (&r6040_driver); +} + + +static void __exit r6040_cleanup (void) +{ + RDC_DBUG("r6040_cleanup()", 0); + pci_unregister_driver (&r6040_driver); +} + +module_init(r6040_init); +module_exit(r6040_cleanup); + + +/* + * Local variables: + * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c r6040.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" + * c-indent-level: 4 + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff --git a/target/linux/rdc/files/include/asm-i386/gpio.h b/target/linux/rdc/files/include/asm-i386/gpio.h new file mode 100644 index 000000000..ff87fca0c --- /dev/null +++ b/target/linux/rdc/files/include/asm-i386/gpio.h @@ -0,0 +1,6 @@ +#ifndef _ASM_I386_GPIO_H +#define _ASM_I386_GPIO_H + +#include <gpio.h> + +#endif /* _ASM_I386_GPIO_H */ diff --git a/target/linux/rdc/files/include/asm-i386/mach-generic/gpio.h b/target/linux/rdc/files/include/asm-i386/mach-generic/gpio.h new file mode 100644 index 000000000..5305dcb96 --- /dev/null +++ b/target/linux/rdc/files/include/asm-i386/mach-generic/gpio.h @@ -0,0 +1,15 @@ +#ifndef __ASM_MACH_GENERIC_GPIO_H +#define __ASM_MACH_GENERIC_GPIO_H + +int gpio_request(unsigned gpio, const char *label); +void gpio_free(unsigned gpio); +int gpio_direction_input(unsigned gpio); +int gpio_direction_output(unsigned gpio, int value); +int gpio_get_value(unsigned gpio); +void gpio_set_value(unsigned gpio, int value); +int gpio_to_irq(unsigned gpio); +int irq_to_gpio(unsigned irq); + +#include <asm-generic/gpio.h> /* cansleep wrappers */ + +#endif /* __ASM_MACH_GENERIC_GPIO_H */ diff --git a/target/linux/rdc/files/include/asm-i386/mach-rdc/gpio.h b/target/linux/rdc/files/include/asm-i386/mach-rdc/gpio.h new file mode 100644 index 000000000..2368bd758 --- /dev/null +++ b/target/linux/rdc/files/include/asm-i386/mach-rdc/gpio.h @@ -0,0 +1,56 @@ +#ifndef _RDC_GPIO_H +#define _RDC_GPIO_H + +extern int rdc_gpio_get_value(unsigned gpio); +extern void rdc_gpio_set_value(unsigned gpio, int value); +extern int rdc_gpio_direction_input(unsigned gpio); +extern int rdc_gpio_direction_output(unsigned gpio, int value); + + +/* Wrappers for the arch-neutral GPIO API */ + +static inline int gpio_request(unsigned gpio, const char *label) +{ + /* Not yet implemented */ + return 0; +} + +static inline void gpio_free(unsigned gpio) +{ + /* Not yet implemented */ +} + +static inline int gpio_direction_input(unsigned gpio) +{ + return rdc_gpio_direction_input(gpio); +} + +static inline int gpio_direction_output(unsigned gpio, int value) +{ + return rdc_gpio_direction_output(gpio, value); +} + +static inline int gpio_get_value(unsigned gpio) +{ + return rdc_gpio_get_value(gpio); +} + +static inline void gpio_set_value(unsigned gpio, int value) +{ + rdc_gpio_set_value(gpio, value); +} + +static inline int gpio_to_irq(unsigned gpio) +{ + return gpio; +} + +static inline int irq_to_gpio(unsigned irq) +{ + return irq; +} + +/* For cansleep */ +#include <asm-generic/gpio.h> + +#endif /* _RDC_GPIO_H_ */ diff --git a/target/linux/rdc/files/include/asm-i386/mach-rdc/rdc321x_defs.h b/target/linux/rdc/files/include/asm-i386/mach-rdc/rdc321x_defs.h new file mode 100644 index 000000000..838ba8f64 --- /dev/null +++ b/target/linux/rdc/files/include/asm-i386/mach-rdc/rdc321x_defs.h @@ -0,0 +1,6 @@ +#define PFX "rdc321x: " + +/* General purpose configuration and data registers */ +#define RDC3210_CFGREG_ADDR 0x0CF8 +#define RDC3210_CFGREG_DATA 0x0CFC +#define RDC_MAX_GPIO 0x3A diff --git a/target/linux/rdc/image/Makefile b/target/linux/rdc/image/Makefile new file mode 100644 index 000000000..52e4f4a39 --- /dev/null +++ b/target/linux/rdc/image/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/image.mk + +define Image/Prepare + $(CP) $(LINUX_DIR)/arch/i386/boot/bzImage $(KDIR)/bzImage +endef + +define trxalign/jffs2-128k +bs=128k +endef +define trxalign/jffs2-64k +bs=64k +endef +define trxalign/squashfs +bs=1024 +endef + +define Image/Build/ar525w + touch $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1)-$(2).img + mv $(KDIR)/root.$(1) $(KDIR)/root.tmp + dd of=$(KDIR)/root.$(1) if=$(KDIR)/root.tmp $(call trxalign/$(1)) conv=sync + $(RM) $(KDIR)/root.tmp + $(STAGING_DIR_HOST)/bin/airlink -b 1 -j $(shell bash -c 'echo $$[$(3)]') $(KDIR)/bzImage $(KDIR)/root.$(1) $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1)-$(2).img +endef + +define Image/Build/wl153 + ls -l $(KDIR)/bzImage | sed -r 's/^[^[:blank:]]+[[:blank:]]+[^[:blank:]]+[[:blank:]]+[^[:blank:]]+[[:blank:]]+[^[:blank:]]+[[:blank:]]+([^[:blank:]]+).+$$$$/\1/' | xargs printf '%.8x' > $(KDIR)/bzSize + gzip -9c $(KDIR)/root.$(1) > $(KDIR)/root.$(1).gz + ls -l $(KDIR)/root.$(1).gz | sed -r 's/^[^[:blank:]]+[[:blank:]]+[^[:blank:]]+[[:blank:]]+[^[:blank:]]+[[:blank:]]+[^[:blank:]]+[[:blank:]]+([^[:blank:]]+).+$$$$/\1/' | xargs printf '%.8x' > $(KDIR)/rdSize + echo -ne "\x$$$$(cut -c 7,8 < $(KDIR)/bzSize)\x$$$$(cut -c 5,6 < $(KDIR)/bzSize)\x$$$$(cut -c 3,4 < $(KDIR)/bzSize)\x$$$$(cut -c 1,2 < $(KDIR)/bzSize)" > $(KDIR)/bzSize.tmp + echo -n 'CSYS' > $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1)-$(2).img + cat $(KDIR)/bzSize.tmp >> $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1)-$(2).img + echo -ne "\x$$$$(cut -c 7,8 < $(KDIR)/rdSize)\x$$$$(cut -c 5,6 < $(KDIR)/rdSize)\x$$$$(cut -c 3,4 < $(KDIR)/rdSize)\x$$$$(cut -c 1,2 < $(KDIR)/rdSize)WRRM" >> $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1)-$(2).img + cat $(KDIR)/bzSize.tmp $(KDIR)/bzImage $(KDIR)/root.$(1).gz >> $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1)-$(2).img + $(RM) $(KDIR)/bzSize.tmp $(KDIR)/bzSize $(KDIR)/rdSize +endef + +define Image/Build + $(CP) $(KDIR)/bzImage $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL).bzImage + $(call Image/Build/$(PROFILE),$(1),$(PROFILE),$(patsubst jffs2-%k,%,$(1))) +endef + +$(eval $(call BuildImage)) diff --git a/target/linux/rdc/patches/000-rdc_fixes.patch b/target/linux/rdc/patches/000-rdc_fixes.patch new file mode 100644 index 000000000..306fac79a --- /dev/null +++ b/target/linux/rdc/patches/000-rdc_fixes.patch @@ -0,0 +1,71 @@ +diff -urN linux-2.6.19/arch/i386/Kconfig linux-2.6.19.new/arch/i386/Kconfig +--- linux-2.6.19/arch/i386/Kconfig 2006-11-29 22:57:37.000000000 +0100 ++++ linux-2.6.19.new/arch/i386/Kconfig 2006-12-17 17:13:33.000000000 +0100 +@@ -180,6 +180,14 @@ + Only choose this option if you have such a system, otherwise you + should say N here. + ++config X86_RDC ++ bool "Support for RDC 3211 boards" ++ help ++ Support for RDC 3211 systems. Say 'Y' here if the kernel is ++ supposed to run on an IA-32 RDC R3211 system. ++ Only choose this option if you have such as system, otherwise you ++ should say N here. ++ + endchoice + + config ACPI_SRAT +diff -urN linux-2.6.19/arch/i386/Makefile linux-2.6.19.new/arch/i386/Makefile +--- linux-2.6.19/arch/i386/Makefile 2006-11-29 22:57:37.000000000 +0100 ++++ linux-2.6.19.new/arch/i386/Makefile 2006-12-17 17:13:33.000000000 +0100 +@@ -92,6 +92,10 @@ + mflags-$(CONFIG_X86_ES7000) := -Iinclude/asm-i386/mach-es7000 + mcore-$(CONFIG_X86_ES7000) := mach-default + core-$(CONFIG_X86_ES7000) := arch/i386/mach-es7000/ ++# RDC subarch support ++mflags-$(CONFIG_X86_RDC) := -Iinclude/asm-i386/mach-rdc ++mcore-$(CONFIG_X86_RDC) := mach-default ++core-$(CONFIG_X86_RDC) += arch/i386/mach-rdc/ + + # default subarch .h files + mflags-y += -Iinclude/asm-i386/mach-default +--- timex.h 2007-08-07 10:44:03.816112250 -0700 ++++ linux/include/asm-i386/timex.h 2007-08-07 10:48:47.905866750 -0700 +@@ -11,6 +11,8 @@ + + #ifdef CONFIG_X86_ELAN + # define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */ ++#elif defined(CONFIG_X86_RDC) ++# define CLOCK_TICK_RATE 1041667 /* Underlying HZ for R8610 */ + #else + # define CLOCK_TICK_RATE 1193182 /* Underlying HZ */ + #endif +--- reboot_fixups.c 2007-08-07 12:02:00.908412250 -0700 ++++ linux/arch/i386/kernel/reboot_fixups.c 2007-08-07 12:18:49.391438500 -0700 +@@ -13,6 +13,17 @@ + #include <linux/pci.h> + #include <asm/reboot_fixups.h> + #include <asm/msr.h> ++ ++static void r8610_reset(struct pci_dev *dev) ++{ ++ int i; ++ ++ outl(0x80003840,0xCF8); ++ i=inl(0xCFC); ++ i |= 0x1600; ++ outl(i,0xCFC); ++ outb(1,0x92); ++} + + static void cs5530a_warm_reset(struct pci_dev *dev) + { +@@ -40,6 +53,7 @@ + }; + + static struct device_fixup fixups_table[] = { ++{ 0x17F3, 0x6030, r8610_reset }, + { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset }, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, cs5536_warm_reset }, + }; diff --git a/target/linux/rdc/patches/001-rdc3210_flash_map.patch b/target/linux/rdc/patches/001-rdc3210_flash_map.patch new file mode 100644 index 000000000..0c407a114 --- /dev/null +++ b/target/linux/rdc/patches/001-rdc3210_flash_map.patch @@ -0,0 +1,65 @@ +diff -urN linux-2.6.17/drivers/mtd/maps/Kconfig linux-2.6.17.new/drivers/mtd/maps/Kconfig +--- linux-2.6.17/drivers/mtd/maps/Kconfig 2006-06-18 03:49:35.000000000 +0200 ++++ linux-2.6.17.new/drivers/mtd/maps/Kconfig 2006-09-24 20:28:11.000000000 +0200 +@@ -76,6 +76,50 @@ + PNC-2000 is the name of Network Camera product from PHOTRON + Ltd. in Japan. It uses CFI-compliant flash. + ++config MTD_RDC3210 ++ tristate "CFI Flash device mapped on RDC3210" ++ depends on X86 && MTD_CFI && MTD_PARTITIONS ++ help ++ RDC-3210 is the flash device we find on Ralink reference board. ++ ++config MTD_RDC3210_STATIC_MAP ++ bool "Partitions on RDC3210 mapped statically" if MTD_RDC3210 ++ select MTD_RDC3210_FACTORY_PRESENT ++ help ++ The mapping driver will use the static partition map for the ++ RDC-3210 flash device. ++ ++config MTD_RDC3210_FACTORY_PRESENT ++ bool "Reserve a partition on RDC3210 for factory presets" ++ depends on MTD_RDC3210 ++ default y ++ help ++ The mapping driver will reserve a partition on the RDC-3210 flash ++ device for resetting flash contents to factory defaults. ++ ++config MTD_RDC3210_ALLOW_JFFS2 ++ bool "JFFS2 filesystem usable in a partition on RDC3210" ++ depends on MTD_RDC3210 && !MTD_RDC3210_STATIC_MAP ++ help ++ The mapping driver will align a partition on the RDC-3210 flash ++ device to an erase-block boundary so that a JFFS2 filesystem may ++ reside on it. ++ ++config MTD_RDC3210_SIZE ++ hex "Amount of flash memory on RDC3210" ++ depends on MTD_RDC3210 ++ default "0x400000" ++ help ++ Total size in bytes of the RDC-3210 flash device ++ ++config MTD_RDC3210_BUSWIDTH ++ int "Width of CFI Flash device mapped on RDC3210" ++ depends on MTD_RDC3210 ++ default "2" ++ help ++ Number of bytes addressed on the RDC-3210 flash device before ++ addressing the same chip again ++ + config MTD_SC520CDP + tristate "CFI Flash device mapped on AMD SC520 CDP" + depends on X86 && MTD_CFI && MTD_CONCAT +diff -urN linux-2.6.17/drivers/mtd/maps/Makefile linux-2.6.17.new/drivers/mtd/maps/Makefile +--- linux-2.6.17/drivers/mtd/maps/Makefile 2006-06-18 03:49:35.000000000 +0200 ++++ linux-2.6.17.new/drivers/mtd/maps/Makefile 2006-09-24 20:26:10.000000000 +0200 +@@ -28,6 +28,7 @@ + obj-$(CONFIG_MTD_PHYSMAP) += physmap.o + obj-$(CONFIG_MTD_PNC2000) += pnc2000.o + obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o ++obj-$(CONFIG_MTD_RDC3210) += rdc3210.o + obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o + obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o + obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o diff --git a/target/linux/rdc/patches/002-r6040_ethernet.patch b/target/linux/rdc/patches/002-r6040_ethernet.patch new file mode 100644 index 000000000..1b9302524 --- /dev/null +++ b/target/linux/rdc/patches/002-r6040_ethernet.patch @@ -0,0 +1,39 @@ +diff -urN linux-2.6.17/drivers/net/Kconfig linux-2.6.17.new/drivers/net/Kconfig +--- linux-2.6.17/drivers/net/Kconfig 2006-06-18 03:49:35.000000000 +0200 ++++ linux-2.6.17.new/drivers/net/Kconfig 2006-09-25 13:14:27.000000000 +0200 +@@ -1358,6 +1358,24 @@ + <file:Documentation/networking/net-modules.txt>. The module will be + called apricot. + ++config R6040 ++ tristate "RDC Fast-Ethernet support (EXPERIMENTAL)" ++ depends on NET_PCI && EXPERIMENTAL ++ select MII ++ help ++ If you have a network (Ethernet) controller of this type, say Y and ++ read the Ethernet-HOWTO, available from ++ <http://www.tldp.org/docs.html#howto>. ++ ++ To compile this driver as a module, choose M here and read ++ <file:Documentation/networking/net-modules.txt>. The module will be ++ called r6040. ++ ++ ++config R6040_NAPI ++ bool "NAPI support for R6040" ++ depends on R6040 ++ default y + config B44 + tristate "Broadcom 4400 ethernet support (EXPERIMENTAL)" + depends on NET_PCI && PCI && EXPERIMENTAL +diff -urN linux-2.6.17/drivers/net/Makefile linux-2.6.17.new/drivers/net/Makefile +--- linux-2.6.17/drivers/net/Makefile 2006-06-18 03:49:35.000000000 +0200 ++++ linux-2.6.17.new/drivers/net/Makefile 2006-09-25 13:14:45.000000000 +0200 +@@ -106,6 +106,7 @@ + obj-$(CONFIG_NE3210) += ne3210.o 8390.o + obj-$(CONFIG_NET_SB1250_MAC) += sb1250-mac.o + obj-$(CONFIG_B44) += b44.o ++obj-$(CONFIG_R6040) += r6040.o + obj-$(CONFIG_FORCEDETH) += forcedeth.o + obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o + diff --git a/target/linux/rdc/patches/003-rootfstype.patch b/target/linux/rdc/patches/003-rootfstype.patch new file mode 100644 index 000000000..34ac3d0a7 --- /dev/null +++ b/target/linux/rdc/patches/003-rootfstype.patch @@ -0,0 +1,11 @@ +--- linux-2.6.19.2/init/do_mounts.c 2007-01-10 11:10:37.000000000 -0800 ++++ foo/init/do_mounts.c 2007-04-05 13:15:37.000000000 -0700 +@@ -243,6 +243,8 @@ + { + char *s = page; + ++ if (!root_fs_names) ++ root_fs_names = "squashfs,jffs2"; + if (root_fs_names) { + strcpy(page, root_fs_names); + while (*s++) { diff --git a/target/linux/rdc/patches/004-rdc3211_leds.patch b/target/linux/rdc/patches/004-rdc3211_leds.patch new file mode 100644 index 000000000..2e704aa60 --- /dev/null +++ b/target/linux/rdc/patches/004-rdc3211_leds.patch @@ -0,0 +1,27 @@ +diff -urN linux-2.6.19.2/drivers/leds/Kconfig linux-2.6.19.2.new/drivers/leds/Kconfig +--- linux-2.6.19.2/drivers/leds/Kconfig 2007-01-10 20:10:37.000000000 +0100 ++++ linux-2.6.19.2.new/drivers/leds/Kconfig 2007-04-16 22:09:40.000000000 +0200 +@@ -76,6 +76,12 @@ + This option enables support for the Soekris net4801 and net4826 error + LED. + ++config LEDS_RDC3211 ++ tristate "LED Support for RDC3211 boards" ++ depends on LEDS_CLASS && X86_RDC ++ help ++ This option enables support for the RDC3211 various LEDs. ++ + comment "LED Triggers" + + config LEDS_TRIGGERS +diff -urN linux-2.6.21.1/drivers/leds/Makefile linux-2.6.21.1.new/drivers/leds/Makefile +--- linux-2.6.21.1/drivers/leds/Makefile 2007-04-27 23:49:26.000000000 +0200 ++++ linux-2.6.21.1.new/drivers/leds/Makefile 2007-05-25 12:19:13.000000000 +0200 +@@ -16,6 +16,7 @@ + obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o + obj-$(CONFIG_LEDS_H1940) += leds-h1940.o + obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o ++obj-$(CONFIG_LEDS_RDC3211) += leds-rdc3211.o + + # LED Triggers + obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o diff --git a/target/linux/rdc/patches/005-rdc_x86_cpu_type.patch b/target/linux/rdc/patches/005-rdc_x86_cpu_type.patch new file mode 100644 index 000000000..185ec13f7 --- /dev/null +++ b/target/linux/rdc/patches/005-rdc_x86_cpu_type.patch @@ -0,0 +1,22 @@ +diff -urN linux-2.6.22.1/arch/i386/kernel/cpu/Makefile linux-2.6.22.1.new/arch/i386/kernel/cpu/Makefile +--- linux-2.6.22.1/arch/i386/kernel/cpu/Makefile 2007-08-11 22:16:24.000000000 +0200 ++++ linux-2.6.22.1.new/arch/i386/kernel/cpu/Makefile 2007-08-13 16:37:32.000000000 +0200 +@@ -12,6 +12,7 @@ + obj-y += rise.o + obj-y += nexgen.o + obj-y += umc.o ++obj-$(CONFIG_X86_RDC) += rdc.o + + obj-$(CONFIG_X86_MCE) += mcheck/ + +diff -urN linux-2.6.22.1/arch/i386/kernel/cpu/Makefile linux-2.6.22.1.new/arch/i386/kernel/cpu/Makefile +--- linux-2.6.22.1/include/asm-i386/processor.h 2007-08-13 16:42:25.000000000 +0200 ++++ linux-2.6.22.1.new/include/asm-i386/processor.h 2007-08-13 16:51:19.000000000 +0200 +@@ -92,6 +92,7 @@ + #define X86_VENDOR_TRANSMETA 7 + #define X86_VENDOR_NSC 8 + #define X86_VENDOR_NUM 9 ++#define X86_VENDOR_RDC 10 + #define X86_VENDOR_UNKNOWN 0xff + + /* diff --git a/target/linux/rdc/patches/600-x86_lzma.patch b/target/linux/rdc/patches/600-x86_lzma.patch new file mode 100644 index 000000000..bb10f1fdc --- /dev/null +++ b/target/linux/rdc/patches/600-x86_lzma.patch @@ -0,0 +1,1042 @@ +diff -Naur linux-old/arch/i386/boot/compressed/LzmaDecode.c linux-lzma/arch/i386/boot/compressed/LzmaDecode.c +--- linux-old/arch/i386/boot/compressed/LzmaDecode.c 1969-12-31 19:00:00.000000000 -0500 ++++ linux-lzma/arch/i386/boot/compressed/LzmaDecode.c 2005-06-05 00:07:38.000000000 -0400 +@@ -0,0 +1,586 @@ ++/* ++ LzmaDecode.c ++ LZMA Decoder (optimized for Speed version) ++ ++ LZMA SDK 4.17 Copyright (c) 1999-2005 Igor Pavlov (2005-04-05) ++ http://www.7-zip.org/ ++ ++ LZMA SDK is licensed under two licenses: ++ 1) GNU Lesser General Public License (GNU LGPL) ++ 2) Common Public License (CPL) ++ It means that you can select one of these two licenses and ++ follow rules of that license. ++ ++ SPECIAL EXCEPTION: ++ Igor Pavlov, as the author of this Code, expressly permits you to ++ statically or dynamically link your Code (or bind by name) to the ++ interfaces of this file without subjecting your linked Code to the ++ terms of the CPL or GNU LGPL. Any modifications or additions ++ to this file, however, are subject to the LGPL or CPL terms. ++*/ ++ ++#include "LzmaDecode.h" ++ ++#ifndef Byte ++#define Byte unsigned char ++#endif ++ ++#define kNumTopBits 24 ++#define kTopValue ((UInt32)1 << kNumTopBits) ++ ++#define kNumBitModelTotalBits 11 ++#define kBitModelTotal (1 << kNumBitModelTotalBits) ++#define kNumMoveBits 5 ++ ++#define RC_READ_BYTE (*Buffer++) ++ ++#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \ ++ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }} ++ ++#ifdef _LZMA_IN_CB ++ ++#define RC_TEST { if (Buffer == BufferLim) \ ++ { UInt32 size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \ ++ BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }} ++ ++#define RC_INIT Buffer = BufferLim = 0; RC_INIT2 ++ ++#else ++ ++#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; } ++ ++#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 ++ ++#endif ++ ++#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } ++ ++#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound) ++#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits; ++#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits; ++ ++#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \ ++ { UpdateBit0(p); mi <<= 1; A0; } else \ ++ { UpdateBit1(p); mi = (mi + mi) + 1; A1; } ++ ++#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;) ++ ++#define RangeDecoderBitTreeDecode(probs, numLevels, res) \ ++ { int i = numLevels; res = 1; \ ++ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \ ++ res -= (1 << numLevels); } ++ ++ ++#define kNumPosBitsMax 4 ++#define kNumPosStatesMax (1 << kNumPosBitsMax) ++ ++#define kLenNumLowBits 3 ++#define kLenNumLowSymbols (1 << kLenNumLowBits) ++#define kLenNumMidBits 3 ++#define kLenNumMidSymbols (1 << kLenNumMidBits) ++#define kLenNumHighBits 8 ++#define kLenNumHighSymbols (1 << kLenNumHighBits) ++ ++#define LenChoice 0 ++#define LenChoice2 (LenChoice + 1) ++#define LenLow (LenChoice2 + 1) ++#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) ++#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) ++#define kNumLenProbs (LenHigh + kLenNumHighSymbols) ++ ++ ++#define kNumStates 12 ++#define kNumLitStates 7 ++ ++#define kStartPosModelIndex 4 ++#define kEndPosModelIndex 14 ++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) ++ ++#define kNumPosSlotBits 6 ++#define kNumLenToPosStates 4 ++ ++#define kNumAlignBits 4 ++#define kAlignTableSize (1 << kNumAlignBits) ++ ++#define kMatchMinLen 2 ++ ++#define IsMatch 0 ++#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) ++#define IsRepG0 (IsRep + kNumStates) ++#define IsRepG1 (IsRepG0 + kNumStates) ++#define IsRepG2 (IsRepG1 + kNumStates) ++#define IsRep0Long (IsRepG2 + kNumStates) ++#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) ++#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) ++#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) ++#define LenCoder (Align + kAlignTableSize) ++#define RepLenCoder (LenCoder + kNumLenProbs) ++#define Literal (RepLenCoder + kNumLenProbs) ++ ++#if Literal != LZMA_BASE_SIZE ++StopCompilingDueBUG ++#endif ++ ++#ifdef _LZMA_OUT_READ ++ ++typedef struct _LzmaVarState ++{ ++ Byte *Buffer; ++ Byte *BufferLim; ++ UInt32 Range; ++ UInt32 Code; ++ #ifdef _LZMA_IN_CB ++ ILzmaInCallback *InCallback; ++ #endif ++ Byte *Dictionary; ++ UInt32 DictionarySize; ++ UInt32 DictionaryPos; ++ UInt32 GlobalPos; ++ UInt32 Reps[4]; ++ int lc; ++ int lp; ++ int pb; ++ int State; ++ int RemainLen; ++ Byte TempDictionary[4]; ++} LzmaVarState; ++ ++int LzmaDecoderInit( ++ unsigned char *buffer, UInt32 bufferSize, ++ int lc, int lp, int pb, ++ unsigned char *dictionary, UInt32 dictionarySize, ++ #ifdef _LZMA_IN_CB ++ ILzmaInCallback *InCallback ++ #else ++ unsigned char *inStream, UInt32 inSize ++ #endif ++ ) ++{ ++ Byte *Buffer; ++ Byte *BufferLim; ++ UInt32 Range; ++ UInt32 Code; ++ LzmaVarState *vs = (LzmaVarState *)buffer; ++ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState)); ++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp)); ++ UInt32 i; ++ if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState)) ++ return LZMA_RESULT_NOT_ENOUGH_MEM; ++ vs->Dictionary = dictionary; ++ vs->DictionarySize = dictionarySize; ++ vs->DictionaryPos = 0; ++ vs->GlobalPos = 0; ++ vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1; ++ vs->lc = lc; ++ vs->lp = lp; ++ vs->pb = pb; ++ vs->State = 0; ++ vs->RemainLen = 0; ++ dictionary[dictionarySize - 1] = 0; ++ for (i = 0; i < numProbs; i++) ++ p[i] = kBitModelTotal >> 1; ++ ++ #ifdef _LZMA_IN_CB ++ RC_INIT; ++ #else ++ RC_INIT(inStream, inSize); ++ #endif ++ vs->Buffer = Buffer; ++ vs->BufferLim = BufferLim; ++ vs->Range = Range; ++ vs->Code = Code; ++ #ifdef _LZMA_IN_CB ++ vs->InCallback = InCallback; ++ #endif ++ ++ return LZMA_RESULT_OK; ++} ++ ++int LzmaDecode(unsigned char *buffer, ++ unsigned char *outStream, UInt32 outSize, ++ UInt32 *outSizeProcessed) ++{ ++ LzmaVarState *vs = (LzmaVarState *)buffer; ++ Byte *Buffer = vs->Buffer; ++ Byte *BufferLim = vs->BufferLim; ++ UInt32 Range = vs->Range; ++ UInt32 Code = vs->Code; ++ #ifdef _LZMA_IN_CB ++ ILzmaInCallback *InCallback = vs->InCallback; ++ #endif ++ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState)); ++ int state = vs->State; ++ Byte previousByte; ++ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; ++ UInt32 nowPos = 0; ++ UInt32 posStateMask = (1 << (vs->pb)) - 1; ++ UInt32 literalPosMask = (1 << (vs->lp)) - 1; ++ int lc = vs->lc; ++ int len = vs->RemainLen; ++ UInt32 globalPos = vs->GlobalPos; ++ ++ Byte *dictionary = vs->Dictionary; ++ UInt32 dictionarySize = vs->DictionarySize; ++ UInt32 dictionaryPos = vs->DictionaryPos; ++ ++ Byte tempDictionary[4]; ++ if (dictionarySize == 0) ++ { ++ dictionary = tempDictionary; ++ dictionarySize = 1; ++ tempDictionary[0] = vs->TempDictionary[0]; ++ } ++ ++ if (len == -1) ++ { ++ *outSizeProcessed = 0; ++ return LZMA_RESULT_OK; ++ } ++ ++ while(len != 0 && nowPos < outSize) ++ { ++ UInt32 pos = dictionaryPos - rep0; ++ if (pos >= dictionarySize) ++ pos += dictionarySize; ++ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; ++ if (++dictionaryPos == dictionarySize) ++ dictionaryPos = 0; ++ len--; ++ } ++ if (dictionaryPos == 0) ++ previousByte = dictionary[dictionarySize - 1]; ++ else ++ previousByte = dictionary[dictionaryPos - 1]; ++#else ++ ++int LzmaDecode( ++ Byte *buffer, UInt32 bufferSize, ++ int lc, int lp, int pb, ++ #ifdef _LZMA_IN_CB ++ ILzmaInCallback *InCallback, ++ #else ++ unsigned char *inStream, UInt32 inSize, ++ #endif ++ unsigned char *outStream, UInt32 outSize, ++ UInt32 *outSizeProcessed) ++{ ++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp)); ++ CProb *p = (CProb *)buffer; ++ ++ UInt32 i; ++ int state = 0; ++ Byte previousByte = 0; ++ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; ++ UInt32 nowPos = 0; ++ UInt32 posStateMask = (1 << pb) - 1; ++ UInt32 literalPosMask = (1 << lp) - 1; ++ int len = 0; ++ ++ Byte *Buffer; ++ Byte *BufferLim; ++ UInt32 Range; ++ UInt32 Code; ++ ++ if (bufferSize < numProbs * sizeof(CProb)) ++ return LZMA_RESULT_NOT_ENOUGH_MEM; ++ for (i = 0; i < numProbs; i++) ++ p[i] = kBitModelTotal >> 1; ++ ++ ++ #ifdef _LZMA_IN_CB ++ RC_INIT; ++ #else ++ RC_INIT(inStream, inSize); ++ #endif ++#endif ++ ++ *outSizeProcessed = 0; ++ while(nowPos < outSize) ++ { ++ CProb *prob; ++ UInt32 bound; ++ int posState = (int)( ++ (nowPos ++ #ifdef _LZMA_OUT_READ ++ + globalPos ++ #endif ++ ) ++ & posStateMask); ++ ++ prob = p + IsMatch + (state << kNumPosBitsMax) + posState; ++ IfBit0(prob) ++ { ++ int symbol = 1; ++ UpdateBit0(prob) ++ prob = p + Literal + (LZMA_LIT_SIZE * ++ ((( ++ (nowPos ++ #ifdef _LZMA_OUT_READ ++ + globalPos ++ #endif ++ ) ++ & literalPosMask) << lc) + (previousByte >> (8 - lc)))); ++ ++ if (state >= kNumLitStates) ++ { ++ int matchByte; ++ #ifdef _LZMA_OUT_READ ++ UInt32 pos = dictionaryPos - rep0; ++ if (pos >= dictionarySize) ++ pos += dictionarySize; ++ matchByte = dictionary[pos]; ++ #else ++ matchByte = outStream[nowPos - rep0]; ++ #endif ++ do ++ { ++ int bit; ++ CProb *probLit; ++ matchByte <<= 1; ++ bit = (matchByte & 0x100); ++ probLit = prob + 0x100 + bit + symbol; ++ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break) ++ } ++ while (symbol < 0x100); ++ } ++ while (symbol < 0x100) ++ { ++ CProb *probLit = prob + symbol; ++ RC_GET_BIT(probLit, symbol) ++ } ++ previousByte = (Byte)symbol; ++ ++ outStream[nowPos++] = previousByte; ++ #ifdef _LZMA_OUT_READ ++ dictionary[dictionaryPos] = previousByte; ++ if (++dictionaryPos == dictionarySize) ++ dictionaryPos = 0; ++ #endif ++ if (state < 4) state = 0; ++ else if (state < 10) state -= 3; ++ else state -= 6; ++ } ++ else ++ { ++ UpdateBit1(prob); ++ prob = p + IsRep + state; ++ IfBit0(prob) ++ { ++ UpdateBit0(prob); ++ rep3 = rep2; ++ rep2 = rep1; ++ rep1 = rep0; ++ state = state < kNumLitStates ? 0 : 3; ++ prob = p + LenCoder; ++ } ++ else ++ { ++ UpdateBit1(prob); ++ prob = p + IsRepG0 + state; ++ IfBit0(prob) ++ { ++ UpdateBit0(prob); ++ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState; ++ IfBit0(prob) ++ { ++ #ifdef _LZMA_OUT_READ ++ UInt32 pos; ++ #endif ++ UpdateBit0(prob); ++ if (nowPos ++ #ifdef _LZMA_OUT_READ ++ + globalPos ++ #endif ++ == 0) ++ return LZMA_RESULT_DATA_ERROR; ++ state = state < kNumLitStates ? 9 : 11; ++ #ifdef _LZMA_OUT_READ ++ pos = dictionaryPos - rep0; ++ if (pos >= dictionarySize) ++ pos += dictionarySize; ++ previousByte = dictionary[pos]; ++ dictionary[dictionaryPos] = previousByte; ++ if (++dictionaryPos == dictionarySize) ++ dictionaryPos = 0; ++ #else ++ previousByte = outStream[nowPos - rep0]; ++ #endif ++ outStream[nowPos++] = previousByte; ++ continue; ++ } ++ else ++ { ++ UpdateBit1(prob); ++ } ++ } ++ else ++ { ++ UInt32 distance; ++ UpdateBit1(prob); ++ prob = p + IsRepG1 + state; ++ IfBit0(prob) ++ { ++ UpdateBit0(prob); ++ distance = rep1; ++ } ++ else ++ { ++ UpdateBit1(prob); ++ prob = p + IsRepG2 + state; ++ IfBit0(prob) ++ { ++ UpdateBit0(prob); ++ distance = rep2; ++ } ++ else ++ { ++ UpdateBit1(prob); ++ distance = rep3; ++ rep3 = rep2; ++ } ++ rep2 = rep1; ++ } ++ rep1 = rep0; ++ rep0 = distance; ++ } ++ state = state < kNumLitStates ? 8 : 11; ++ prob = p + RepLenCoder; ++ } ++ { ++ int numBits, offset; ++ CProb *probLen = prob + LenChoice; ++ IfBit0(probLen) ++ { ++ UpdateBit0(probLen); ++ probLen = prob + LenLow + (posState << kLenNumLowBits); ++ offset = 0; ++ numBits = kLenNumLowBits; ++ } ++ else ++ { ++ UpdateBit1(probLen); ++ probLen = prob + LenChoice2; ++ IfBit0(probLen) ++ { ++ UpdateBit0(probLen); ++ probLen = prob + LenMid + (posState << kLenNumMidBits); ++ offset = kLenNumLowSymbols; ++ numBits = kLenNumMidBits; ++ } ++ else ++ { ++ UpdateBit1(probLen); ++ probLen = prob + LenHigh; ++ offset = kLenNumLowSymbols + kLenNumMidSymbols; ++ numBits = kLenNumHighBits; ++ } ++ } ++ RangeDecoderBitTreeDecode(probLen, numBits, len); ++ len += offset; ++ } ++ ++ if (state < 4) ++ { ++ int posSlot; ++ state += kNumLitStates; ++ prob = p + PosSlot + ++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << ++ kNumPosSlotBits); ++ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot); ++ if (posSlot >= kStartPosModelIndex) ++ { ++ int numDirectBits = ((posSlot >> 1) - 1); ++ rep0 = (2 | ((UInt32)posSlot & 1)); ++ if (posSlot < kEndPosModelIndex) ++ { ++ rep0 <<= numDirectBits; ++ prob = p + SpecPos + rep0 - posSlot - 1; ++ } ++ else ++ { ++ numDirectBits -= kNumAlignBits; ++ do ++ { ++ RC_NORMALIZE ++ Range >>= 1; ++ rep0 <<= 1; ++ if (Code >= Range) ++ { ++ Code -= Range; ++ rep0 |= 1; ++ } ++ } ++ while (--numDirectBits != 0); ++ prob = p + Align; ++ rep0 <<= kNumAlignBits; ++ numDirectBits = kNumAlignBits; ++ } ++ { ++ int i = 1; ++ int mi = 1; ++ do ++ { ++ CProb *prob3 = prob + mi; ++ RC_GET_BIT2(prob3, mi, ; , rep0 |= i); ++ i <<= 1; ++ } ++ while(--numDirectBits != 0); ++ } ++ } ++ else ++ rep0 = posSlot; ++ if (++rep0 == (UInt32)(0)) ++ { ++ /* it's for stream version */ ++ len = -1; ++ break; ++ } ++ } ++ ++ len += kMatchMinLen; ++ if (rep0 > nowPos ++ #ifdef _LZMA_OUT_READ ++ + globalPos || rep0 > dictionarySize ++ #endif ++ ) ++ return LZMA_RESULT_DATA_ERROR; ++ do ++ { ++ #ifdef _LZMA_OUT_READ ++ UInt32 pos = dictionaryPos - rep0; ++ if (pos >= dictionarySize) ++ pos += dictionarySize; ++ previousByte = dictionary[pos]; ++ dictionary[dictionaryPos] = previousByte; ++ if (++dictionaryPos == dictionarySize) ++ dictionaryPos = 0; ++ #else ++ previousByte = outStream[nowPos - rep0]; ++ #endif ++ len--; ++ outStream[nowPos++] = previousByte; ++ } ++ while(len != 0 && nowPos < outSize); ++ } ++ } ++ RC_NORMALIZE; ++ ++ #ifdef _LZMA_OUT_READ ++ vs->Buffer = Buffer; ++ vs->BufferLim = BufferLim; ++ vs->Range = Range; ++ vs->Code = Code; ++ vs->DictionaryPos = dictionaryPos; ++ vs->GlobalPos = globalPos + nowPos; ++ vs->Reps[0] = rep0; ++ vs->Reps[1] = rep1; ++ vs->Reps[2] = rep2; ++ vs->Reps[3] = rep3; ++ vs->State = state; ++ vs->RemainLen = len; ++ vs->TempDictionary[0] = tempDictionary[0]; ++ #endif ++ ++ *outSizeProcessed = nowPos; ++ return LZMA_RESULT_OK; ++} +diff -Naur linux-old/arch/i386/boot/compressed/LzmaDecode.h linux-lzma/arch/i386/boot/compressed/LzmaDecode.h +--- linux-old/arch/i386/boot/compressed/LzmaDecode.h 1969-12-31 19:00:00.000000000 -0500 ++++ linux-lzma/arch/i386/boot/compressed/LzmaDecode.h 2005-06-05 00:07:39.000000000 -0400 +@@ -0,0 +1,100 @@ ++/* ++ LzmaDecode.h ++ LZMA Decoder interface ++ ++ LZMA SDK 4.16 Copyright (c) 1999-2005 Igor Pavlov (2005-03-18) ++ http://www.7-zip.org/ ++ ++ LZMA SDK is licensed under two licenses: ++ 1) GNU Lesser General Public License (GNU LGPL) ++ 2) Common Public License (CPL) ++ It means that you can select one of these two licenses and ++ follow rules of that license. ++ ++ SPECIAL EXCEPTION: ++ Igor Pavlov, as the author of this code, expressly permits you to ++ statically or dynamically link your code (or bind by name) to the ++ interfaces of this file without subjecting your linked code to the ++ terms of the CPL or GNU LGPL. Any modifications or additions ++ to this file, however, are subject to the LGPL or CPL terms. ++*/ ++ ++#ifndef __LZMADECODE_H ++#define __LZMADECODE_H ++ ++/* #define _LZMA_IN_CB */ ++/* Use callback for input data */ ++ ++/* #define _LZMA_OUT_READ */ ++/* Use read function for output data */ ++ ++/* #define _LZMA_PROB32 */ ++/* It can increase speed on some 32-bit CPUs, ++ but memory usage will be doubled in that case */ ++ ++/* #define _LZMA_LOC_OPT */ ++/* Enable local speed optimizations inside code */ ++ ++#ifndef UInt32 ++#ifdef _LZMA_UINT32_IS_ULONG ++#define UInt32 unsigned long ++#else ++#define UInt32 unsigned int ++#endif ++#endif ++ ++#ifdef _LZMA_PROB32 ++#define CProb UInt32 ++#else ++#define CProb unsigned short ++#endif ++ ++#define LZMA_RESULT_OK 0 ++#define LZMA_RESULT_DATA_ERROR 1 ++#define LZMA_RESULT_NOT_ENOUGH_MEM 2 ++ ++#ifdef _LZMA_IN_CB ++typedef struct _ILzmaInCallback ++{ ++ int (*Read)(void *object, unsigned char **buffer, UInt32 *bufferSize); ++} ILzmaInCallback; ++#endif ++ ++#define LZMA_BASE_SIZE 1846 ++#define LZMA_LIT_SIZE 768 ++ ++/* ++bufferSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)))* sizeof(CProb) ++bufferSize += 100 in case of _LZMA_OUT_READ ++by default CProb is unsigned short, ++but if specify _LZMA_PROB_32, CProb will be UInt32(unsigned int) ++*/ ++ ++#ifdef _LZMA_OUT_READ ++int LzmaDecoderInit( ++ unsigned char *buffer, UInt32 bufferSize, ++ int lc, int lp, int pb, ++ unsigned char *dictionary, UInt32 dictionarySize, ++ #ifdef _LZMA_IN_CB ++ ILzmaInCallback *inCallback ++ #else ++ unsigned char *inStream, UInt32 inSize ++ #endif ++); ++#endif ++ ++int LzmaDecode( ++ unsigned char *buffer, ++ #ifndef _LZMA_OUT_READ ++ UInt32 bufferSize, ++ int lc, int lp, int pb, ++ #ifdef _LZMA_IN_CB ++ ILzmaInCallback *inCallback, ++ #else ++ unsigned char *inStream, UInt32 inSize, ++ #endif ++ #endif ++ unsigned char *outStream, UInt32 outSize, ++ UInt32 *outSizeProcessed); ++ ++#endif +diff -Naur linux-old/arch/i386/boot/compressed/lzma_misc.c linux-lzma/arch/i386/boot/compressed/lzma_misc.c +--- linux-old/arch/i386/boot/compressed/lzma_misc.c 1969-12-31 19:00:00.000000000 -0500 ++++ linux-lzma/arch/i386/boot/compressed/lzma_misc.c 2005-06-04 21:33:48.000000000 -0400 +@@ -0,0 +1,281 @@ ++/* ++ * lzma_misc.c ++ * ++ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 ++ * puts by Nick Holloway 1993, better puts by Martin Mares 1995 ++ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 ++ * ++ * Decompress LZMA compressed vmlinuz ++ * Version 0.9 Copyright (c) Ming-Ching Tiew mctiew@yahoo.com ++ * Program adapted from misc.c for 2.6 kernel ++ * Forward ported to latest 2.6 version of misc.c by ++ * Felix Fietkau <nbd@openwrt.org> ++ */ ++ ++#undef CONFIG_PARAVIRT ++#include <linux/linkage.h> ++#include <linux/vmalloc.h> ++#include <linux/screen_info.h> ++#include <asm/io.h> ++#include <asm/page.h> ++#include <asm/boot.h> ++ ++/* WARNING!! ++ * This code is compiled with -fPIC and it is relocated dynamically ++ * at run time, but no relocation processing is performed. ++ * This means that it is not safe to place pointers in static structures. ++ */ ++ ++/* ++ * Getting to provable safe in place decompression is hard. ++ * Worst case behaviours need to be analized. ++ * Background information: ++ * ++ * The file layout is: ++ * magic[2] ++ * method[1] ++ * flags[1] ++ * timestamp[4] ++ * extraflags[1] ++ * os[1] ++ * compressed data blocks[N] ++ * crc[4] orig_len[4] ++ * ++ * resulting in 18 bytes of non compressed data overhead. ++ * ++ * Files divided into blocks ++ * 1 bit (last block flag) ++ * 2 bits (block type) ++ * ++ * 1 block occurs every 32K -1 bytes or when there 50% compression has been achieved. ++ * The smallest block type encoding is always used. ++ * ++ * stored: ++ * 32 bits length in bytes. ++ * ++ * fixed: ++ * magic fixed tree. ++ * symbols. ++ * ++ * dynamic: ++ * dynamic tree encoding. ++ * symbols. ++ * ++ * ++ * The buffer for decompression in place is the length of the ++ * uncompressed data, plus a small amount extra to keep the algorithm safe. ++ * The compressed data is placed at the end of the buffer. The output ++ * pointer is placed at the start of the buffer and the input pointer ++ * is placed where the compressed data starts. Problems will occur ++ * when the output pointer overruns the input pointer. ++ * ++ * The output pointer can only overrun the input pointer if the input ++ * pointer is moving faster than the output pointer. A condition only ++ * triggered by data whose compressed form is larger than the uncompressed ++ * form. ++ * ++ * The worst case at the block level is a growth of the compressed data ++ * of 5 bytes per 32767 bytes. ++ * ++ * The worst case internal to a compressed block is very hard to figure. ++ * The worst case can at least be boundined by having one bit that represents ++ * 32764 bytes and then all of the rest of the bytes representing the very ++ * very last byte. ++ * ++ * All of which is enough to compute an amount of extra data that is required ++ * to be safe. To avoid problems at the block level allocating 5 extra bytes ++ * per 32767 bytes of data is sufficient. To avoind problems internal to a block ++ * adding an extra 32767 bytes (the worst case uncompressed block size) is ++ * sufficient, to ensure that in the worst case the decompressed data for ++ * block will stop the byte before the compressed data for a block begins. ++ * To avoid problems with the compressed data's meta information an extra 18 ++ * bytes are needed. Leading to the formula: ++ * ++ * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size. ++ * ++ * Adding 8 bytes per 32K is a bit excessive but much easier to calculate. ++ * Adding 32768 instead of 32767 just makes for round numbers. ++ * Adding the decompressor_size is necessary as it musht live after all ++ * of the data as well. Last I measured the decompressor is about 14K. ++ * 10K of actuall data and 4K of bss. ++ * ++ */ ++ ++/* ++ * gzip declarations ++ */ ++ ++#define OF(args) args ++#define STATIC static ++ ++#undef memcpy ++ ++typedef unsigned char uch; ++typedef unsigned short ush; ++typedef unsigned long ulg; ++ ++#define WSIZE 0x80000000 /* Window size must be at least 32k, ++ * and a power of two ++ * We don't actually have a window just ++ * a huge output buffer so I report ++ * a 2G windows size, as that should ++ * always be larger than our output buffer. ++ */ ++ ++static uch *inbuf; /* input buffer */ ++static uch *window; /* Sliding window buffer, (and final output buffer) */ ++ ++static unsigned insize; /* valid bytes in inbuf */ ++static unsigned inptr; /* index of next byte to be processed in inbuf */ ++static unsigned long workspace; ++ ++#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) ++ ++/* Diagnostic functions */ ++#ifdef DEBUG ++# define Assert(cond,msg) {if(!(cond)) error(msg);} ++# define Trace(x) fprintf x ++# define Tracev(x) {if (verbose) fprintf x ;} ++# define Tracevv(x) {if (verbose>1) fprintf x ;} ++# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} ++# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} ++#else ++# define Assert(cond,msg) ++# define Trace(x) ++# define Tracev(x) ++# define Tracevv(x) ++# define Tracec(c,x) ++# define Tracecv(c,x) ++#endif ++ ++static int fill_inbuf(void); ++ ++/* ++ * This is set up by the setup-routine at boot-time ++ */ ++static unsigned char *real_mode; /* Pointer to real-mode data */ ++extern unsigned char input_data[]; ++extern int input_len; ++ ++static void error(char *x); ++static void *memcpy(void *dest, const void *src, unsigned n); ++ ++#ifdef CONFIG_X86_NUMAQ ++void *xquad_portio; ++#endif ++ ++static void* memcpy(void* dest, const void* src, unsigned n) ++{ ++ int i; ++ char *d = (char *)dest, *s = (char *)src; ++ ++ for (i=0;i<n;i++) d[i] = s[i]; ++ return dest; ++} ++ ++/* =========================================================================== ++ * Fill the input buffer. This is called only when the buffer is empty ++ * and at least one byte is really needed. ++ */ ++static int fill_inbuf(void) ++{ ++ error("ran out of input data"); ++ return 0; ++} ++ ++ ++// When using LZMA in callback, the compressed length is not needed. ++// Otherwise you need a special version of lzma compression program ++// which will pad the compressed length in the header. ++#define _LZMA_IN_CB ++#include "LzmaDecode.h" ++#include "LzmaDecode.c" ++ ++static int read_byte(void *object, unsigned char **buffer, UInt32 *bufferSize); ++ ++ ++/* ++ * Do the lzma decompression ++ * When using LZMA in callback, the end of input stream is automatically determined ++ */ ++static int lzma_unzip(void) ++{ ++ ++ unsigned int i; /* temp value */ ++ unsigned int lc; /* literal context bits */ ++ unsigned int lp; /* literal pos state bits */ ++ unsigned int pb; /* pos state bits */ ++ unsigned int uncompressedSize = 0; ++ unsigned char* p; ++ ++ ILzmaInCallback callback; ++ callback.Read = read_byte; ++ ++ /* lzma args */ ++ i = get_byte(); ++ lc = i % 9, i = i / 9; ++ lp = i % 5, pb = i / 5; ++ ++ /* skip dictionary size */ ++ for (i = 0; i < 4; i++) ++ get_byte(); ++ // get uncompressedSize ++ p= (char*)&uncompressedSize; ++ for (i = 0; i < 4; i++) ++ *p++ = get_byte(); ++ ++ //get compressedSize ++ for (i = 0; i < 4; i++) ++ get_byte(); ++ ++ // point it beyond uncompresedSize ++ //workspace = window + uncompressedSize; ++ ++ /* decompress kernel */ ++ if (LzmaDecode((unsigned char*)workspace, ~0, lc, lp, pb, &callback, ++ (unsigned char*)window, uncompressedSize, &i) == LZMA_RESULT_OK) ++ return 0; ++ else ++ return 1; ++} ++ ++ ++#ifdef _LZMA_IN_CB ++static int read_byte(void *object, unsigned char **buffer, UInt32 *bufferSize) ++{ ++ static unsigned int i = 0; ++ static unsigned char val; ++ *bufferSize = 1; ++ val = get_byte(); ++ *buffer = &val; ++ return LZMA_RESULT_OK; ++} ++#endif ++ ++static void error(char *x) ++{ ++ while(1); /* Halt */ ++} ++ ++asmlinkage void decompress_kernel(void *rmode, unsigned long end, ++ uch *input_data, unsigned long input_len, uch *output) ++{ ++ real_mode = rmode; ++ ++ window = output; ++ inbuf = input_data; /* Input buffer */ ++ insize = input_len; ++ inptr = 0; ++ ++ if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1)) ++ error("Destination address not CONFIG_PHYSICAL_ALIGN aligned"); ++ if ((workspace = end) > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff)) ++ error("Destination address too large"); ++#ifndef CONFIG_RELOCATABLE ++ if ((u32)output != LOAD_PHYSICAL_ADDR) ++ error("Wrong destination address"); ++#endif ++ ++ lzma_unzip(); ++ return; ++} +diff -Naur linux-old/arch/i386/boot/compressed/Makefile linux-lzma/arch/i386/boot/compressed/Makefile +--- linux-old/arch/i386/boot/compressed/Makefile 2005-06-04 21:53:40.000000000 -0400 ++++ linux-lzma/arch/i386/boot/compressed/Makefile 2005-06-05 00:25:23.000000000 -0400 +@@ -4,7 +4,7 @@ + # create a compressed vmlinux image from the original vmlinux + # + +-targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o \ ++targets := vmlinux vmlinux.bin vmlinux.bin.lzma head.o lzma_misc.o piggy.o \ + vmlinux.bin.all vmlinux.relocs + EXTRA_AFLAGS := -traditional + +@@ -17,7 +17,7 @@ + $(call cc-option,-fno-stack-protector) + LDFLAGS := -m elf_i386 + +-$(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE ++$(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/lzma_misc.o $(obj)/piggy.o FORCE + $(call if_changed,ld) + @: + +@@ -37,14 +37,14 @@ + $(call if_changed,relocbin) + + ifdef CONFIG_RELOCATABLE +-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE +- $(call if_changed,gzip) ++$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin.all FORCE ++ $(call if_changed,lzma) + else +-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE +- $(call if_changed,gzip) ++$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE ++ $(call if_changed,lzma) + endif + + LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T + +-$(obj)/piggy.o: $(src)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE ++$(obj)/piggy.o: $(src)/vmlinux.scr $(obj)/vmlinux.bin.lzma FORCE + $(call if_changed,ld) +diff -urN linux-2.6.19.2/scripts/Makefile.lib linux-2.6.19.2.new/scripts/Makefile.lib +--- linux-2.6.19.2/scripts/Makefile.lib 2007-01-10 20:10:37.000000000 +0100 ++++ linux-2.6.19.2.new/scripts/Makefile.lib 2007-04-15 23:51:54.000000000 +0200 +@@ -162,4 +162,9 @@ + quiet_cmd_gzip = GZIP $@ + cmd_gzip = gzip -f -9 < $< > $@ + +- ++# LZMA ++# ++quiet_cmd_lzma = LZMA $@ ++cmd_lzma = bash -e scripts/lzma_kern $< $@ -lc7 -lp0 -pb0 ++# to use lzmacomp, ++# cmd_lzma = lzmacomp $< 700 > $@ +diff -u linux/scripts/lzma_kern linux/scripts/lzma_kern +--- linux/scripts/lzma_kern 2007-07-27 20:18:17.013014750 -0700 ++++ linux/scripts/lzma_kern 2007-07-27 20:18:17.013014750 -0700 +@@ -0,0 +1,4 @@ ++get-size() { echo "$5" ;} ++printf -v len '%.8x' "$(get-size $(ls -l "$1"))" ++lzma e "$@" ++echo -ne "\x$(echo $len | cut -c 7,8)\x$(echo $len | cut -c 5,6)\x$(echo $len | cut -c 3,4)\x$(echo $len | cut -c 1,2)" >> "$2" diff --git a/target/linux/rdc/profiles/AR525W.mk b/target/linux/rdc/profiles/AR525W.mk new file mode 100644 index 000000000..5c01554d4 --- /dev/null +++ b/target/linux/rdc/profiles/AR525W.mk @@ -0,0 +1,13 @@ +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/ar525w + NAME:=AirLink101 AR525W + PACKAGES:=kmod-rt61-pci kmod-r6040 +endef +$(eval $(call Profile,ar525w)) + diff --git a/target/linux/rdc/profiles/WL-153.mk b/target/linux/rdc/profiles/WL-153.mk new file mode 100644 index 000000000..f030455b2 --- /dev/null +++ b/target/linux/rdc/profiles/WL-153.mk @@ -0,0 +1,13 @@ +# +# Copyright (C) 2007 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/wl153 + NAME:=Sitecom WL-153 + PACKAGES:=kmod-rt61-pci kmod-r6040 +endef +$(eval $(call Profile,wl153)) + |