diff options
Diffstat (limited to 'target')
22 files changed, 3022 insertions, 0 deletions
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 0000000000..f4b9083bfc --- /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 0000000000..5961bc7910 --- /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 0000000000..dbd03270f1 --- /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 0000000000..31af6fcc30 --- /dev/null +++ b/target/linux/rdc/files/arch/i386/mach-rdc/platform.c @@ -0,0 +1,114 @@ +/* + * $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 <linux/version.h> +#include <linux/leds.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> + +#include <asm/gpio.h> + +/* 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 gpio_led default_leds[] = { + { .name = "rdc321x:dmz", .gpio = 1, }, +}; + +static struct gpio_led_platform_data rdc321x_led_data = { + .num_leds = ARRAY_SIZE(default_leds), + .leds = default_leds, +}; + +static struct platform_device rdc321x_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &rdc321x_led_data, + } +}; + +/* Watchdog */ +static struct platform_device rdc321x_wdt = { + .name = "rdc321x-wdt", + .id = -1, + .num_resources = 0, +}; + +/* Button */ +static struct gpio_keys_button rdc321x_gpio_btn[] = { + { + .gpio = 0, + .code = BTN_0, + .desc = "Reset", + .active_low = 1, + } +}; + +static struct gpio_keys_platform_data rdc321x_gpio_btn_data = { + .buttons = rdc321x_gpio_btn, + .nbuttons = ARRAY_SIZE(rdc321x_gpio_btn), +}; + +static struct platform_device rdc321x_button = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &rdc321x_gpio_btn_data, + } +}; + +static struct platform_device *rdc321x_devs[] = { + &rdc_flash_device, + &rdc321x_leds, + &rdc321x_wdt, + &rdc321x_button +}; + +static int __init rdc_board_setup(void) +{ + return platform_add_devices(rdc321x_devs, ARRAY_SIZE(rdc321x_devs)); +} + +arch_initcall(rdc_board_setup); diff --git a/target/linux/rdc/files/arch/i386/mach-rdc/setup.c b/target/linux/rdc/files/arch/i386/mach-rdc/setup.c new file mode 100644 index 0000000000..ad206c3d05 --- /dev/null +++ b/target/linux/rdc/files/arch/i386/mach-rdc/setup.c @@ -0,0 +1,14 @@ +/* + * Machine specific setup for generic + */ + +#include <linux/init.h> +#include <linux/interrupt.h> +#include <asm/arch_hooks.h> +#include <asm/io.h> +#include <asm/setup.h> + +char * __init machine_specific_memory_setup(void) +{ + return "RDC R-321x"; +} 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 0000000000..13b69f68ab --- /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/include/asm-i386/gpio.h b/target/linux/rdc/files/include/asm-i386/gpio.h new file mode 100644 index 0000000000..ff87fca0ca --- /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 0000000000..5305dcb96d --- /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 0000000000..2368bd7583 --- /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 0000000000..838ba8f64f --- /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/files/include/asm-x86/gpio.h b/target/linux/rdc/files/include/asm-x86/gpio.h new file mode 100644 index 0000000000..ff87fca0ca --- /dev/null +++ b/target/linux/rdc/files/include/asm-x86/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-x86/mach-generic/gpio.h b/target/linux/rdc/files/include/asm-x86/mach-generic/gpio.h new file mode 100644 index 0000000000..5305dcb96d --- /dev/null +++ b/target/linux/rdc/files/include/asm-x86/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-x86/mach-rdc/gpio.h b/target/linux/rdc/files/include/asm-x86/mach-rdc/gpio.h new file mode 100644 index 0000000000..2368bd7583 --- /dev/null +++ b/target/linux/rdc/files/include/asm-x86/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-x86/mach-rdc/rdc321x_defs.h b/target/linux/rdc/files/include/asm-x86/mach-rdc/rdc321x_defs.h new file mode 100644 index 0000000000..838ba8f64f --- /dev/null +++ b/target/linux/rdc/files/include/asm-x86/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/patches-2.6.23/001-rdc3210_flash_map.patch b/target/linux/rdc/patches-2.6.23/001-rdc3210_flash_map.patch new file mode 100644 index 0000000000..0c407a114a --- /dev/null +++ b/target/linux/rdc/patches-2.6.23/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-2.6.23/001-x86_generic_gpio.patch b/target/linux/rdc/patches-2.6.23/001-x86_generic_gpio.patch new file mode 100644 index 0000000000..db3d866a1b --- /dev/null +++ b/target/linux/rdc/patches-2.6.23/001-x86_generic_gpio.patch @@ -0,0 +1,15 @@ +diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig +index 97b64d7..f8c1d32 100644 +--- a/arch/i386/Kconfig ++++ b/arch/i386/Kconfig +@@ -79,6 +79,10 @@ config GENERIC_BUG + default y + depends on BUG + ++config GENERIC_GPIO ++ bool ++ default n ++ + config GENERIC_HWEIGHT + bool + default y diff --git a/target/linux/rdc/patches-2.6.23/002-r6040_ethernet.patch b/target/linux/rdc/patches-2.6.23/002-r6040_ethernet.patch new file mode 100644 index 0000000000..8ff6af1c7e --- /dev/null +++ b/target/linux/rdc/patches-2.6.23/002-r6040_ethernet.patch @@ -0,0 +1,1090 @@ +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 -urN linux-2.6.23/drivers/net/r6040.c linux-2.6.23.new/drivers/net/r6040.c +--- linux-2.6.23/drivers/net/r6040.c 2006-06-18 03:49:35.000000000 +0200 ++++ linux-2.6.23.new/drivers/net/r6040.c 2006-09-25 13:14:45.000000000 +0200 +@@ -0,0 +1,1048 @@ ++/* 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 ++ ---------- ------------------------------------------------ ++ 10-07-2007 Clean up the driver using checkpatch ++ 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 */ ++ ++/* PHY settings */ ++#define ICPLUS_PHY_ID 0x0243 ++ ++/* Debug enable or not */ ++#define RDC_DEBUG 0 ++ ++#if RDC_DEBUG > 1 ++#define RDC_DBUG(msg, value) printk(KERN_ERR "%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> ++#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>, Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>, Florian Fainelli <florian@openwrt.org>"); ++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; /* driver 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; ++ ++#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(KERN_INFO "%s\n", version); ++ ++ err = pci_enable_device(pdev); ++ if (err) ++ 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 */ ++ err = register_netdev(dev); ++ if (err) { ++ 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 != ICPLUS_PHY_ID) { ++ /* 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 == ICPLUS_PHY_ID && 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)) == ICPLUS_PHY_ID) { ++ 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(KERN_INFO "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[] = { ++ {PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RDC_6040}, ++ /*{0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RDC_6040},*/ ++ {0,} ++}; ++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(KERN_INFO "%s\n", 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); diff --git a/target/linux/rdc/patches-2.6.23/003-rootfstype.patch b/target/linux/rdc/patches-2.6.23/003-rootfstype.patch new file mode 100644 index 0000000000..34ac3d0a71 --- /dev/null +++ b/target/linux/rdc/patches-2.6.23/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-2.6.23/004-rdc_fixes.patch b/target/linux/rdc/patches-2.6.23/004-rdc_fixes.patch new file mode 100644 index 0000000000..7b87773cf1 --- /dev/null +++ b/target/linux/rdc/patches-2.6.23/004-rdc_fixes.patch @@ -0,0 +1,73 @@ +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,16 @@ + 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" ++ select GENERIC_GPIO ++ select LEDS_GPIO ++ 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[] = { ++{ PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030, 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-2.6.23/005-rdc_x86_cpu_type.patch b/target/linux/rdc/patches-2.6.23/005-rdc_x86_cpu_type.patch new file mode 100644 index 0000000000..9e0eefb09e --- /dev/null +++ b/target/linux/rdc/patches-2.6.23/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 0xff + #define X86_VENDOR_UNKNOWN 0xff + + /* diff --git a/target/linux/rdc/patches-2.6.23/006-pci_ids.patch b/target/linux/rdc/patches-2.6.23/006-pci_ids.patch new file mode 100644 index 0000000000..cd4c01d920 --- /dev/null +++ b/target/linux/rdc/patches-2.6.23/006-pci_ids.patch @@ -0,0 +1,18 @@ +diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h +index 55f307f..4a1aa34 100644 +--- a/include/linux/pci_ids.h ++++ b/include/linux/pci_ids.h +@@ -2076,6 +2076,13 @@ + #define PCI_DEVICE_ID_HERC_WIN 0x5732 + #define PCI_DEVICE_ID_HERC_UNI 0x5832 + ++#define PCI_VENDOR_ID_RDC 0x17f3 ++#define PCI_DEVICE_ID_RDC_R6020 0x6020 ++#define PCI_DEVICE_ID_RDC_R6030 0x6030 ++#define PCI_DEVICE_ID_RDC_R6040 0x6040 ++#define PCI_DEVICE_ID_RDC_R6060 0x6060 ++#define PCI_DEVICE_ID_RDC_R6061 0x6061 ++ + #define PCI_VENDOR_ID_SITECOM 0x182d + #define PCI_DEVICE_ID_SITECOM_DC105V2 0x3069 + diff --git a/target/linux/rdc/patches-2.6.23/600-x86_lzma.patch b/target/linux/rdc/patches-2.6.23/600-x86_lzma.patch new file mode 100644 index 0000000000..bb10f1fdcc --- /dev/null +++ b/target/linux/rdc/patches-2.6.23/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" |