diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/irq.c linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/irq.c --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/irq.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/irq.c 2007-01-24 17:22:47.000000000 +0100 @@ -0,0 +1,417 @@ +/* +<:copyright-gpl + Copyright 2002 Broadcom Corp. All Rights Reserved. + + This program is free software; you can distribute it and/or modify it + under the terms of the GNU General Public License (Version 2) as + published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +:> +*/ +/* + * Interrupt control functions for Broadcom 963xx MIPS boards + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); + +static void irq_dispatch_int(struct pt_regs *regs) +{ + unsigned int pendingIrqs; + static unsigned int irqBit; + static unsigned int isrNumber = 31; + + pendingIrqs = PERF->IrqStatus & PERF->IrqMask; + if (!pendingIrqs) { + return; + } + + while (1) { + irqBit <<= 1; + isrNumber++; + if (isrNumber == 32) { + isrNumber = 0; + irqBit = 0x1; + } + if (pendingIrqs & irqBit) { + unsigned int irq = isrNumber + INTERNAL_ISR_TABLE_OFFSET; +#if defined(CONFIG_BCM96358) + if (irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3) { + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT)); // Clear + } + else if (irq >= INTERRUPT_ID_EXTERNAL_4 && irq <= INTERRUPT_ID_EXTERNAL_5) { + PERF->ExtIrqCfg1 |= (1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_CLEAR_SHFT)); // Clear + } +#endif + PERF->IrqMask &= ~irqBit; // mask + do_IRQ(irq, regs); + break; + } + } +} + +#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96348) +static void irq_dispatch_ext(uint32 irq, struct pt_regs *regs) +{ + if (!(PERF->ExtIrqCfg & (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)))) { + printk("**** Ext IRQ mask. Should not dispatch ****\n"); + } + /* disable and clear interrupt in the controller */ + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT)); + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)); + do_IRQ(irq, regs); +} +#endif + +static void irq_dispatch_sw(uint32 irq, struct pt_regs *regs) +{ + clear_c0_cause(0x1 << (CAUSEB_IP0 + irq - INTERRUPT_ID_SOFTWARE_0)); + do_IRQ(irq, regs); +} + + +void brcm_irq_dispatch(struct pt_regs *regs) +{ + u32 cause; + while((cause = (read_c0_cause() & read_c0_status() & CAUSEF_IP))) { + if (cause & CAUSEF_IP7) + do_IRQ(MIPS_TIMER_INT, regs); + else if (cause & CAUSEF_IP2) + irq_dispatch_int(regs); +#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96348) + else if (cause & CAUSEF_IP3) + irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_0, regs); + else if (cause & CAUSEF_IP4) + irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_1, regs); + else if (cause & CAUSEF_IP5) + irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_2, regs); + else if (cause & CAUSEF_IP6) + irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_3, regs); +#endif + else if (cause & CAUSEF_IP0) + irq_dispatch_sw(INTERRUPT_ID_SOFTWARE_0, regs); + else if (cause & CAUSEF_IP1) + irq_dispatch_sw(INTERRUPT_ID_SOFTWARE_1, regs); + cli(); + } +} + + +void enable_brcm_irq(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + if( irq >= INTERNAL_ISR_TABLE_OFFSET ) { + PERF->IrqMask |= (1 << (irq - INTERNAL_ISR_TABLE_OFFSET)); + } +#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96348) + else if (irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3) { + /* enable and clear interrupt in the controller */ + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT)); + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)); + } +#endif + else if ((irq == INTERRUPT_ID_SOFTWARE_0) || (irq == INTERRUPT_ID_SOFTWARE_1)) { + set_c0_status(0x1 << (STATUSB_IP0 + irq - INTERRUPT_ID_SOFTWARE_0)); + } + local_irq_restore(flags); +} + +void disable_brcm_irq(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + if( irq >= INTERNAL_ISR_TABLE_OFFSET ) { + PERF->IrqMask &= ~(1 << (irq - INTERNAL_ISR_TABLE_OFFSET)); + } +#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96348) + else if (irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3) { + /* disable interrupt in the controller */ + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)); + } +#endif + else if ((irq == INTERRUPT_ID_SOFTWARE_0) || (irq == INTERRUPT_ID_SOFTWARE_1)) { + clear_c0_status(0x1 << (STATUSB_IP0 + irq - INTERRUPT_ID_SOFTWARE_0)); + } + local_irq_restore(flags); +} + +void ack_brcm_irq(unsigned int irq) +{ + /* Already done in brcm_irq_dispatch */ +} + +unsigned int startup_brcm_irq(unsigned int irq) +{ + enable_brcm_irq(irq); + + return 0; /* never anything pending */ +} + +unsigned int startup_brcm_none(unsigned int irq) +{ + return 0; +} + +void end_brcm_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_brcm_irq(irq); +} + +void end_brcm_none(unsigned int irq) +{ +} + +#if defined (CONFIG_BCM96358) +#define ALLINTS_NOTIMER IE_IRQ0 +#else +#define ALLINTS_NOTIMER (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4) +#endif + +static void __init brcm_irq_setup(void) +{ + extern asmlinkage void brcmIRQ(void); + + clear_c0_status(ST0_BEV); + set_except_vector(0, brcmIRQ); + change_c0_status(ST0_IM, ALLINTS_NOTIMER); + +#ifdef CONFIG_REMOTE_DEBUG + rs_kgdb_hook(0); +#endif +} + +static struct hw_interrupt_type brcm_irq_type = { + .typename = "MIPS", + .startup = startup_brcm_irq, + .shutdown = disable_brcm_irq, + .enable = enable_brcm_irq, + .disable = disable_brcm_irq, + .ack = ack_brcm_irq, + .end = end_brcm_irq, + .set_affinity = NULL +}; + +static struct hw_interrupt_type brcm_irq_no_end_type = { + .typename = "MIPS", + .startup = startup_brcm_none, + .shutdown = disable_brcm_irq, + .enable = enable_brcm_irq, + .disable = disable_brcm_irq, + .ack = ack_brcm_irq, + .end = end_brcm_none, + .set_affinity = NULL +}; + +void __init arch_init_irq(void) +{ + int i; + + for (i = 0; i < NR_IRQS; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &brcm_irq_type; + } + + brcm_irq_setup(); +} + +#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96348) +int request_external_irq(unsigned int irq, + FN_HANDLER handler, + unsigned long irqflags, + const char * devname, + void *dev_id) +{ + unsigned long flags; + + local_irq_save(flags); + + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT)); // Clear + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)); // Mask + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_INSENS_SHFT)); // Edge insesnsitive + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_LEVEL_SHFT)); // Level triggered + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_SENSE_SHFT)); // Low level + + local_irq_restore(flags); + + return( request_irq(irq, handler, irqflags, devname, dev_id) ); +} +#endif + + +unsigned int +neufbox_map_interrupt (FN_HANDLER pfunc, char const *const name, void * param, uint32_t irq) +{ + unsigned long flags; + char * devname = kmalloc(16, GFP_KERNEL); + + + if ( devname ) { + snprintf (devname, 16, name); + } + + /* Set the IRQ description to not automatically enable the interrupt at + * the end of an ISR. The driver that handles the interrupt must + * explicitly call BcmHalInterruptEnable or enable_brcm_irq. This behavior + * is consistent with interrupt handling on VxWorks. + */ + irq_desc[irq].handler = &brcm_irq_no_end_type; + + + local_irq_save (flags); + + if ( irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3 ) { + // Clear + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT)); + // Unmask + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)); + // Edge insesnsitive + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_INSENS_SHFT)); + // Level triggered + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_LEVEL_SHFT)); + // Low level + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_SENSE_SHFT)); + } + else if ( irq >= INTERRUPT_ID_EXTERNAL_4 && irq <= INTERRUPT_ID_EXTERNAL_5 ) { + // Clear + PERF->ExtIrqCfg1 |= (1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_CLEAR_SHFT)); + // Unmask + PERF->ExtIrqCfg1 |= (1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_MASK_SHFT)); + // Edge insesnsitive + PERF->ExtIrqCfg1 &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_INSENS_SHFT)); + // Level triggered + PERF->ExtIrqCfg1 |= (1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_LEVEL_SHFT)); + // Low level + PERF->ExtIrqCfg1 &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_SENSE_SHFT)); + } + + local_irq_restore (flags); + + return request_irq (irq, pfunc, SA_SAMPLE_RANDOM | SA_INTERRUPT, devname, param); +} + + + +unsigned int BcmHalMapInterrupt(FN_HANDLER pfunc, unsigned int param, + unsigned int irq) +{ + int nRet = -1; + char *devname; + + devname = kmalloc(16, GFP_KERNEL); + if (devname) + sprintf( devname, "brcm_%d", irq ); + + /* Set the IRQ description to not automatically enable the interrupt at + * the end of an ISR. The driver that handles the interrupt must + * explicitly call BcmHalInterruptEnable or enable_brcm_irq. This behavior + * is consistent with interrupt handling on VxWorks. + */ + irq_desc[irq].handler = &brcm_irq_no_end_type; + +#if defined(CONFIG_BCM96348) || defined(CONFIG_BCM96358) + if( irq == INTERRUPT_ID_MPI ) { + nRet = request_irq( irq, pfunc, SA_SAMPLE_RANDOM | SA_INTERRUPT | SA_SHIRQ, + devname, (void *) param ); + + } + else +#endif + if( irq >= INTERNAL_ISR_TABLE_OFFSET ) + { +#if defined(CONFIG_BCM96358) + unsigned long flags; + + local_irq_save(flags); + if (irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3) { + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT)); // Clear + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)); // Unmask + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_INSENS_SHFT)); // Edge insesnsitive + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_LEVEL_SHFT)); // Level triggered + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_SENSE_SHFT)); // Low level + } + else if (irq >= INTERRUPT_ID_EXTERNAL_4 && irq <= INTERRUPT_ID_EXTERNAL_5) { + PERF->ExtIrqCfg1 |= (1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_CLEAR_SHFT)); // Clear + PERF->ExtIrqCfg1 |= (1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_MASK_SHFT)); // Unmask + PERF->ExtIrqCfg1 &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_INSENS_SHFT)); // Edge insesnsitive + PERF->ExtIrqCfg1 |= (1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_LEVEL_SHFT)); // Level triggered + PERF->ExtIrqCfg1 &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_SENSE_SHFT)); // Low level + } + local_irq_restore(flags); +#endif + nRet = request_irq( irq, pfunc, SA_SAMPLE_RANDOM | SA_INTERRUPT, + devname, (void *) param ); + + } +#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96348) + else if (irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3) + { + nRet = request_external_irq( irq, pfunc, SA_SAMPLE_RANDOM | SA_INTERRUPT, + devname, (void *) param ); + } +#endif + else if ((irq == INTERRUPT_ID_SOFTWARE_0) || (irq == INTERRUPT_ID_SOFTWARE_1)) + { + nRet = request_irq( irq, pfunc, SA_SAMPLE_RANDOM | SA_INTERRUPT, + devname, (void *) param ); + } + + return( nRet ); +} + + +//*************************************************************************** +// void BcmHalGenerateSoftInterrupt +// +// Triggers a software interrupt. +// +//*************************************************************************** +void BcmHalGenerateSoftInterrupt( unsigned int irq ) +{ + unsigned long flags; + + local_irq_save(flags); + + set_c0_cause(0x1 << (CAUSEB_IP0 + irq - INTERRUPT_ID_SOFTWARE_0)); + + local_irq_restore(flags); +} + +EXPORT_SYMBOL(enable_brcm_irq); +EXPORT_SYMBOL(disable_brcm_irq); +#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96348) +EXPORT_SYMBOL(request_external_irq); +#endif +EXPORT_SYMBOL(BcmHalMapInterrupt); +EXPORT_SYMBOL(neufbox_map_interrupt); +EXPORT_SYMBOL(BcmHalGenerateSoftInterrupt); diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/Kconfig linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/Kconfig --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/Kconfig 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,177 @@ +# Kernel and Driver configuration for Broadcom Commengine ADSL board +choice + prompt "Broadcom Commengine ADSL board" + depends on MIPS_BRCM + default BCM96348 + help + Select different Broadcom ADSL board + +config BCM96338 + bool "96338 ADSL board" + select DMA_NONCOHERENT + +config BCM96348 + bool "96348 ADSL board" + select DMA_NONCOHERENT + +config BCM96358 + bool "96358 ADSL board" + select DMA_NONCOHERENT + +endchoice + +config BCM_BOARD + bool "Support for Broadcom Board" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_SERIAL + bool "Support for Serial Port" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ENET + tristate "Support for Ethernet" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_USB + tristate "Support for USB" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_WLAN + tristate "Support for Wireless" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_MIMO + bool "EWC 802.11n MIMO Support" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_PCI + bool "Support for PCI" + depends on BCM96338 || BCM96348 || BCM96358 + select PCI + +config BCM_ATMAPI + tristate "Support for ATM" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ATMTEST + tristate "Support for ATM Diagnostic" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ADSL + tristate "Support for ADSL" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ENDPOINT + tristate "Support for VOICE" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_BCMPROF + tristate "Support for profiling" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_PROCFS + tristate "Support for PROCFS" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_VDSL + tristate "Support for VDSL" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_SECURITY + tristate "Support for SECURITY" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_HPNA + tristate "Support for HPNA" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_BOARD_IMPL + int "Implementation index for ADSL Board" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_SERIAL_IMPL + int "Implementation index for Serial" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ENET_IMPL + int "Implementation index for Ethernet" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_USB_IMPL + int "Implementation index for USB" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_WLAN_IMPL + int "Implementation index for WIRELESS" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ATMAPI_IMPL + int "Implementation index for ATM" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ATMTEST_IMPL + int "Implementation index for ATM Diagnostic" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_BLAA_IMPL + int "Implementation index for BLAA" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ADSL_IMPL + int "Implementation index for ADSL" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ENDPOINT_IMPL + int "Implementation index for VOICE" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_BCMPROF_IMPL + int "Implementation index for PROFILING" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_PROCFS_IMPL + int "Implementation index for PROCFS" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_SECURITY_IMPL + int "Implementation index for SECURITY" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_HPNA_IMPL + int "Implementation index for HPNA" + depends on BCM96338 || BCM96348 || BCM96358 + +choice + prompt "Root File System" + depends on MIPS_BRCM + default ROOTFS_SQUASHFS + help + Select root file system on the board flash. + +config ROOTFS_SQUASHFS + bool "SQUASHFS" +config ROOTFS_CRAMFS + bool "CRAMFS" +config ROOTFS_JFFS2 + bool "JFFS2" +config ROOTFS_NFS + bool "NFS" + +endchoice + +config ROOT_FLASHFS + string "flash partition" + depends on ROOTFS_SQUASHFS || ROOTFS_CRAMFS || ROOTFS_JFFS2 + default "root=31:0 ro noinitrd" if ROOTFS_SQUASHFS = y || ROOTFS_CRAMFS = y + default "root=31:2 ro noinitrd" if ROOTFS_JFFS2 = y + help + This is the root file system partition on flash memory + +config ROOT_NFS_DIR + string "NFS server path" + depends on ROOTFS_NFS + default "/opt/bcm96338/targets/96338R/fs" if BCM96338 = y + default "/opt/bcm96348/targets/96348R/fs" if BCM96348 = y + default "/opt/bcm96358/targets/96358R/fs" if BCM96358 = y + help + This is the path of NFS server (host system) diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/Makefile linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/Makefile --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/Makefile 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,23 @@ +# +# Makefile for generic Broadcom MIPS boards +# +# Copyright (C) 2004 Broadcom Corporation +# +obj-y := irq.o prom.o setup.o time.o ser_init.o + +SRCBASE := $(TOPDIR) +EXTRA_CFLAGS += -I$(INC_BRCMBOARDPARMS_PATH)/$(BRCM_BOARD) -I$(SRCBASE)/include -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) +#EXTRA_CFLAGS += -I$(INC_ADSLDRV_PATH) -DDBG +EXTRA_CFLAGS += -I$(INC_ADSLDRV_PATH) + + +ifeq "$(ADSL)" "ANNEX_B" +EXTRA_CFLAGS += -DADSL_ANNEXB +endif +ifeq "$(ADSL)" "SADSL" +EXTRA_CFLAGS += -DADSL_SADSL +endif +ifeq "$(ADSL)" "ANNEX_C" +EXTRA_CFLAGS += -DADSL_ANNEXC +endif + diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/prom.c linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/prom.c --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/prom.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/prom.c 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,261 @@ +/* +<:copyright-gpl + Copyright 2004 Broadcom Corp. All Rights Reserved. + + This program is free software; you can distribute it and/or modify it + under the terms of the GNU General Public License (Version 2) as + published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +:> +*/ +/* + * prom.c: PROM library initialization code. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "boardparms.h" +#include "softdsl/AdslCoreDefs.h" + + +extern int do_syslog(int, char *, int); +extern void serial_init(void); +extern void __init InitNvramInfo( void ); +extern void kerSysFlashInit( void ); +extern unsigned long get_nvram_start_addr(void); +void __init create_root_nfs_cmdline( char *cmdline ); + +#if defined(CONFIG_BCM96338) +#define CPU_CLOCK 240000000 +#define MACH_BCM MACH_BCM96338 +#endif +#if defined(CONFIG_BCM96348) +void __init calculateCpuSpeed(void); +static unsigned long cpu_speed; +#define CPU_CLOCK cpu_speed +#define MACH_BCM MACH_BCM96348 +#endif +#if defined(CONFIG_BCM96358) +void __init calculateCpuSpeed(void); +static unsigned long cpu_speed; +#define CPU_CLOCK cpu_speed +#define MACH_BCM MACH_BCM96358 +#endif + +const char *get_system_type(void) +{ + PNVRAM_DATA pNvramData = (PNVRAM_DATA) get_nvram_start_addr(); + + return( pNvramData->szBoardId ); +} + +unsigned long getMemorySize(void) +{ + unsigned long ulSdramType = BOARD_SDRAM_TYPE; + + unsigned long ulSdramSize; + + switch( ulSdramType ) + { + case BP_MEMORY_16MB_1_CHIP: + case BP_MEMORY_16MB_2_CHIP: + ulSdramSize = 16 * 1024 * 1024; + break; + case BP_MEMORY_32MB_1_CHIP: + case BP_MEMORY_32MB_2_CHIP: + ulSdramSize = 32 * 1024 * 1024; + break; + case BP_MEMORY_64MB_2_CHIP: + ulSdramSize = 64 * 1024 * 1024; + break; + default: + ulSdramSize = 8 * 1024 * 1024; + break; + } + + return ulSdramSize; +} + +/* -------------------------------------------------------------------------- + Name: prom_init + -------------------------------------------------------------------------- */ +void __init prom_init(void) +{ + extern ulong r4k_interval; + + serial_init(); + + kerSysFlashInit(); + + do_syslog(8, NULL, 8); + + printk( "%s prom init\n", get_system_type() ); + + PERF->IrqMask = 0; + + arcs_cmdline[0] = '\0'; + +#if defined(CONFIG_ROOT_NFS) + create_root_nfs_cmdline( arcs_cmdline ); +#elif defined(CONFIG_ROOT_FLASHFS) + strcpy(arcs_cmdline, CONFIG_ROOT_FLASHFS); +#endif + +#if defined(CONFIG_BCM96358) && defined(CONFIG_BCM_ENDPOINT_MODULE) + add_memory_region(0, (getMemorySize() - 1024*1024), BOOT_MEM_RAM); +#else + add_memory_region(0, (getMemorySize() - ADSL_SDRAM_IMAGE_SIZE), BOOT_MEM_RAM); +#endif + +#if defined(CONFIG_BCM96348) || defined(CONFIG_BCM96358) + calculateCpuSpeed(); +#endif + /* Count register increments every other clock */ + r4k_interval = CPU_CLOCK / HZ / 2; + mips_hpt_frequency = CPU_CLOCK / 2; + + mips_machgroup = MACH_GROUP_BRCM; + mips_machtype = MACH_BCM; +} + +/* -------------------------------------------------------------------------- + Name: prom_free_prom_memory +Abstract: + -------------------------------------------------------------------------- */ +void __init prom_free_prom_memory(void) +{ + +} + + +#if defined(CONFIG_ROOT_NFS) +/* This function reads in a line that looks something like this: + * + * + * CFE bootline=bcmEnet(0,0)host:vmlinux e=192.169.0.100:ffffff00 h=192.169.0.1 + * + * + * and retuns in the cmdline parameter some that looks like this: + * + * CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/opt/targets/96345R/fs + * ip=192.168.0.100:192.168.0.1::255.255.255.0::eth0:off rw" + */ +#define BOOT_LINE_ADDR 0x0 +#define HEXDIGIT(d) ((d >= '0' && d <= '9') ? (d - '0') : ((d | 0x20) - 'W')) +#define HEXBYTE(b) (HEXDIGIT((b)[0]) << 4) + HEXDIGIT((b)[1]) +extern unsigned long get_nvram_start_addr(void); + +void __init create_root_nfs_cmdline( char *cmdline ) +{ + char root_nfs_cl[] = "root=/dev/nfs nfsroot=%s:" CONFIG_ROOT_NFS_DIR + " ip=%s:%s::%s::eth0:off rw"; + + char *localip = NULL; + char *hostip = NULL; + char mask[16] = ""; + PNVRAM_DATA pNvramData = (PNVRAM_DATA) get_nvram_start_addr(); + char bootline[128] = ""; + char *p = bootline; + + memcpy(bootline, pNvramData->szBootline, sizeof(bootline)); + while( *p ) + { + if( p[0] == 'e' && p[1] == '=' ) + { + /* Found local ip address */ + p += 2; + localip = p; + while( *p && *p != ' ' && *p != ':' ) + p++; + if( *p == ':' ) + { + /* Found network mask (eg FFFFFF00 */ + *p++ = '\0'; + sprintf( mask, "%u.%u.%u.%u", HEXBYTE(p), HEXBYTE(p + 2), + HEXBYTE(p + 4), HEXBYTE(p + 6) ); + p += 4; + } + else if( *p == ' ' ) + *p++ = '\0'; + } + else if( p[0] == 'h' && p[1] == '=' ) + { + /* Found host ip address */ + p += 2; + hostip = p; + while( *p && *p != ' ' ) + p++; + if( *p == ' ' ) + *p++ = '\0'; + } + else + p++; + } + + if( localip && hostip ) + sprintf( cmdline, root_nfs_cl, hostip, localip, hostip, mask ); +} +#endif + +#if defined(CONFIG_BCM96348) +/* ********************************************************************* + * calculateCpuSpeed() + * Calculate the BCM6348 CPU speed by reading the PLL strap register + * and applying the following formula: + * cpu_clk = (.25 * 64MHz freq) * (N1 + 1) * (N2 + 2) / (M1_CPU + 1) + * Input parameters: + * none + * Return value: + * none + ********************************************************************* */ +void __init calculateCpuSpeed(void) +{ + UINT32 pllStrap = PERF->PllStrap; + int n1 = (pllStrap & PLL_N1_MASK) >> PLL_N1_SHFT; + int n2 = (pllStrap & PLL_N2_MASK) >> PLL_N2_SHFT; + int m1cpu = (pllStrap & PLL_M1_CPU_MASK) >> PLL_M1_CPU_SHFT; + + cpu_speed = (16 * (n1 + 1) * (n2 + 2) / (m1cpu + 1)) * 1000000; +} +#endif + +#if defined(CONFIG_BCM96358) +/* ********************************************************************* + * calculateCpuSpeed() + * Calculate the BCM6358 CPU speed by reading the PLL Config register + * and applying the following formula: + * Fcpu_clk = (25 * MIPSDDR_NDIV) / MIPS_MDIV + * Input parameters: + * none + * Return value: + * none + ********************************************************************* */ +void __init calculateCpuSpeed(void) +{ + UINT32 pllConfig = DDR->MIPSDDRPLLConfig; + int numerator; + + cpu_speed = 64000000 / ((pllConfig & MIPS_MDIV_MASK) >> MIPS_MDIV_SHFT); + numerator = (((pllConfig & MIPSDDR_N2_MASK) >> MIPSDDR_N2_SHFT) * ((pllConfig & MIPSDDR_N1_MASK) >> MIPSDDR_N1_SHFT)); + cpu_speed = (cpu_speed * numerator) / 4; + +} +#endif diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/ser_init.c linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/ser_init.c --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/ser_init.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/ser_init.c 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,175 @@ +/* +<:copyright-gpl + Copyright 2004 Broadcom Corp. All Rights Reserved. + + This program is free software; you can distribute it and/or modify it + under the terms of the GNU General Public License (Version 2) as + published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +:> +*/ +/* + * Broadcom bcm63xx serial port initialization, also prepare for printk + * by registering with console_init + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#define SER63XX_DEFAULT_BAUD 115200 +#define BD_BCM63XX_TIMER_CLOCK_INPUT (FPERIPH) +#define stUart ((volatile Uart * const) UART_BASE) + +// Transmit interrupts +#define TXINT (TXFIFOEMT | TXUNDERR | TXOVFERR) +// Receive interrupts +#define RXINT (RXFIFONE | RXOVFERR) + +/* -------------------------------------------------------------------------- + Name: serial_init + Purpose: Initalize the UART +-------------------------------------------------------------------------- */ +void __init serial_init(void) +{ + UINT32 tmpVal = SER63XX_DEFAULT_BAUD; + ULONG clockFreqHz; + + /* Dissable channel's receiver and transmitter. */ + stUart->control &= ~(BRGEN|TXEN|RXEN); + + /*--------------------------------------------------------------------*/ + /* Write the table value to the clock select register. */ + /* DPullen - this is the equation to use: */ + /* value = clockFreqHz / baud / 32-1; */ + /* (snmod) Actually you should also take into account any necessary */ + /* rounding. Divide by 16, look at lsb, if 0, divide by 2 */ + /* and subtract 1. If 1, just divide by 2 */ + /*--------------------------------------------------------------------*/ + clockFreqHz = BD_BCM63XX_TIMER_CLOCK_INPUT; + tmpVal = (clockFreqHz / tmpVal) / 16; + if( tmpVal & 0x01 ) + tmpVal /= 2; //Rounding up, so sub is already accounted for + else + tmpVal = (tmpVal / 2) - 1; // Rounding down so we must sub 1 + stUart->baudword = tmpVal; + + /* Finally, re-enable the transmitter and receiver. */ + stUart->control |= (BRGEN|TXEN|RXEN); + + stUart->config = (BITS8SYM | ONESTOP); + // Set the FIFO interrupt depth ... stUart->fifocfg = 0xAA; + stUart->fifoctl = RSTTXFIFOS | RSTRXFIFOS; + stUart->intMask = 0; + stUart->intMask = RXINT | TXINT; +} + + +/* prom_putc() + * Output a character to the UART + */ +void prom_putc(char c) +{ + /* Wait for Tx uffer to empty */ + while (! (READ16(stUart->intStatus) & TXFIFOEMT)); + /* Send character */ + stUart->Data = c; +} + +/* prom_puts() + * Write a string to the UART + */ +void prom_puts(const char *s) +{ + while (*s) { + if (*s == '\n') { + prom_putc('\r'); + } + prom_putc(*s++); + } +} + + +/* prom_getc_nowait() + * Returns a character from the UART + * Returns -1 if no characters available or corrupted + */ +int prom_getc_nowait(void) +{ + uint16 uStatus; + int cData = -1; + + uStatus = READ16(stUart->intStatus); + + if (uStatus & RXFIFONE) { /* Do we have a character? */ + cData = READ16(stUart->Data) & 0xff; /* Read character */ + if (uStatus & (RXFRAMERR | RXPARERR)) { /* If we got an error, throw it away */ + cData = -1; + } + } + + return cData; +} + +/* prom_getc() + * Returns a charcter from the serial port + * Will block until it receives a valid character +*/ +char prom_getc(void) +{ + int cData = -1; + + /* Loop until we get a valid character */ + while(cData == -1) { + cData = prom_getc_nowait(); + } + return (char) cData; +} + +/* prom_testc() + * Returns 0 if no characters available + */ +int prom_testc(void) +{ + uint16 uStatus; + + uStatus = READ16(stUart->intStatus); + + return (uStatus & RXFIFONE); +} + +#if CONFIG_REMOTE_DEBUG +/* Prevent other code from writing to the serial port */ +void _putc(char c) { } +void _puts(const char *ptr) { } +#else +/* Low level outputs call prom routines */ +void _putc(char c) { + prom_putc(c); +} +void _puts(const char *ptr) { + prom_puts(ptr); +} +#endif diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/setup.c linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/setup.c --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/setup.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/setup.c 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,571 @@ +/* +<:copyright-gpl + Copyright 2002 Broadcom Corp. All Rights Reserved. + + This program is free software; you can distribute it and/or modify it + under the terms of the GNU General Public License (Version 2) as + published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +:> +*/ +/* + * Generic setup routines for Broadcom 963xx MIPS boards + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +extern void brcm_timer_setup(struct irqaction *irq); +extern unsigned long getMemorySize(void); + +#include + +#if defined(CONFIG_PCI) +#include +#include +#include +#endif + +/* This function should be in a board specific directory. For now, + * assume that all boards that include this file use a Broadcom chip + * with a soft reset bit in the PLL control register. + */ +static void brcm_machine_restart(char *command) +{ + PERF->pll_control |= SOFT_RESET; +} + +static void brcm_machine_halt(void) +{ + printk("System halted\n"); + while (1); +} + +#if defined(CONFIG_PCI) + +static void mpi_SetLocalPciConfigReg(uint32 reg, uint32 value) +{ + /* write index then value */ + MPI->pcicfgcntrl = PCI_CFG_REG_WRITE_EN + reg;; + MPI->pcicfgdata = value; +} + +static uint32 mpi_GetLocalPciConfigReg(uint32 reg) +{ + /* write index then get value */ + MPI->pcicfgcntrl = PCI_CFG_REG_WRITE_EN + reg;; + return MPI->pcicfgdata; +} + +/* + * mpi_ResetPcCard: Set/Reset the PcCard + */ +static void mpi_ResetPcCard(int cardtype, BOOL bReset) +{ + if (cardtype == MPI_CARDTYPE_NONE) { + return; + } + + if (cardtype == MPI_CARDTYPE_CARDBUS) { + bReset = ! bReset; + } + + if (bReset) { + MPI->pcmcia_cntl1 = (MPI->pcmcia_cntl1 & ~PCCARD_CARD_RESET); + } else { + MPI->pcmcia_cntl1 = (MPI->pcmcia_cntl1 | PCCARD_CARD_RESET); + } +} + +/* + * mpi_ConfigCs: Configure an MPI/EBI chip select + */ +static void mpi_ConfigCs(uint32 cs, uint32 base, uint32 size, uint32 flags) +{ + MPI->cs[cs].base = ((base & 0x1FFFFFFF) | size); + MPI->cs[cs].config = flags; +} + +/* + * mpi_InitPcmciaSpace + */ +static void mpi_InitPcmciaSpace(void) +{ + // ChipSelect 4 controls PCMCIA Memory accesses + mpi_ConfigCs(PCMCIA_COMMON_BASE, pcmciaMem, EBI_SIZE_1M, (EBI_WORD_WIDE|EBI_ENABLE)); + // ChipSelect 5 controls PCMCIA Attribute accesses + mpi_ConfigCs(PCMCIA_ATTRIBUTE_BASE, pcmciaAttr, EBI_SIZE_1M, (EBI_WORD_WIDE|EBI_ENABLE)); + // ChipSelect 6 controls PCMCIA I/O accesses + mpi_ConfigCs(PCMCIA_IO_BASE, pcmciaIo, EBI_SIZE_64K, (EBI_WORD_WIDE|EBI_ENABLE)); + + MPI->pcmcia_cntl2 = ((PCMCIA_ATTR_ACTIVE << RW_ACTIVE_CNT_BIT) | + (PCMCIA_ATTR_INACTIVE << INACTIVE_CNT_BIT) | + (PCMCIA_ATTR_CE_SETUP << CE_SETUP_CNT_BIT) | + (PCMCIA_ATTR_CE_HOLD << CE_HOLD_CNT_BIT)); + + MPI->pcmcia_cntl2 |= (PCMCIA_HALFWORD_EN | PCMCIA_BYTESWAP_DIS); +} + +/* + * cardtype_vcc_detect: PC Card's card detect and voltage sense connection + * + * CD1#/ CD2#/ VS1#/ VS2#/ Card Initial Vcc + * CCD1# CCD2# CVS1 CVS2 Type + * + * GND GND open open 16-bit 5 vdc + * + * GND GND GND open 16-bit 3.3 vdc + * + * GND GND open GND 16-bit x.x vdc + * + * GND GND GND GND 16-bit 3.3 & x.x vdc + * + *==================================================================== + * + * CVS1 GND CCD1# open CardBus 3.3 vdc + * + * GND CVS2 open CCD2# CardBus x.x vdc + * + * GND CVS1 CCD2# open CardBus y.y vdc + * + * GND CVS2 GND CCD2# CardBus 3.3 & x.x vdc + * + * CVS2 GND open CCD1# CardBus x.x & y.y vdc + * + * GND CVS1 CCD2# open CardBus 3.3, x.x & y.y vdc + * + */ +static int cardtype_vcc_detect(void) +{ + uint32 data32; + int cardtype; + + cardtype = MPI_CARDTYPE_NONE; + MPI->pcmcia_cntl1 = (CARDBUS_ENABLE|PCMCIA_GPIO_ENABLE); // Turn on the output enables and drive + // the CVS pins to 0. + data32 = MPI->pcmcia_cntl1; + switch (data32 & (CD2_IN|CD1_IN)) // Test CD1# and CD2#, see if card is plugged in. + { + case (CD2_IN|CD1_IN): // No Card is in the slot. + printk("MPI: No Card is in the PCMCIA slot\n"); + break; + + case CD2_IN: // Partial insertion, No CD2#. + printk("MPI: Card in the PCMCIA slot partial insertion, no CD2 signal\n"); + break; + + case CD1_IN: // Partial insertion, No CD1#. + printk("MPI: Card in the PCMCIA slot partial insertion, no CD1 signal\n"); + break; + + case 0x00000000: + MPI->pcmcia_cntl1 = (CARDBUS_ENABLE|PCMCIA_GPIO_ENABLE|VS2_OEN|VS1_OEN); + // Turn off the CVS output enables and + // float the CVS pins. + mdelay(1); + data32 = MPI->pcmcia_cntl1; + // Read the Register. + switch (data32 & (VS2_IN|VS1_IN)) // See what is on the CVS pins. + { + case 0x00000000: // CVS1 and CVS2 are tied to ground, only 1 option. + printk("MPI: Detected 3.3 & x.x 16-bit PCMCIA card\n"); + cardtype = MPI_CARDTYPE_PCMCIA; + break; + + case VS1_IN: // CVS1 is open or tied to CCD1/CCD2 and CVS2 is tied to ground. + // 2 valid voltage options. + switch (data32 & (CD2_IN|CD1_IN)) // Test the values of CCD1 and CCD2. + { + case (CD2_IN|CD1_IN): // CCD1 and CCD2 are tied to 1 of the CVS pins. + // This is not a valid combination. + printk("MPI: Unknown card plugged into slot\n"); + break; + + case CD2_IN: // CCD2 is tied to either CVS1 or CVS2. + MPI->pcmcia_cntl1 = (CARDBUS_ENABLE|PCMCIA_GPIO_ENABLE|VS2_OEN); // Drive CVS1 to a 0. + mdelay(1); + data32 = MPI->pcmcia_cntl1; + if (data32 & CD2_IN) { // CCD2 is tied to CVS2, not valid. + printk("MPI: Unknown card plugged into slot\n"); + } else { // CCD2 is tied to CVS1. + printk("MPI: Detected 3.3, x.x and y.y Cardbus card\n"); + cardtype = MPI_CARDTYPE_CARDBUS; + } + break; + + case CD1_IN: // CCD1 is tied to either CVS1 or CVS2. + // This is not a valid combination. + printk("MPI: Unknown card plugged into slot\n"); + break; + + case 0x00000000: // CCD1 and CCD2 are tied to ground. + printk("MPI: Detected x.x vdc 16-bit PCMCIA card\n"); + cardtype = MPI_CARDTYPE_PCMCIA; + break; + } + break; + + case VS2_IN: // CVS2 is open or tied to CCD1/CCD2 and CVS1 is tied to ground. + // 2 valid voltage options. + switch (data32 & (CD2_IN|CD1_IN)) // Test the values of CCD1 and CCD2. + { + case (CD2_IN|CD1_IN): // CCD1 and CCD2 are tied to 1 of the CVS pins. + // This is not a valid combination. + printk("MPI: Unknown card plugged into slot\n"); + break; + + case CD2_IN: // CCD2 is tied to either CVS1 or CVS2. + MPI->pcmcia_cntl1 = (CARDBUS_ENABLE|PCMCIA_GPIO_ENABLE|VS1_OEN);// Drive CVS2 to a 0. + mdelay(1); + data32 = MPI->pcmcia_cntl1; + if (data32 & CD2_IN) { // CCD2 is tied to CVS1, not valid. + printk("MPI: Unknown card plugged into slot\n"); + } else {// CCD2 is tied to CVS2. + printk("MPI: Detected 3.3 and x.x Cardbus card\n"); + cardtype = MPI_CARDTYPE_CARDBUS; + } + break; + + case CD1_IN: // CCD1 is tied to either CVS1 or CVS2. + // This is not a valid combination. + printk("MPI: Unknown card plugged into slot\n"); + break; + + case 0x00000000: // CCD1 and CCD2 are tied to ground. + cardtype = MPI_CARDTYPE_PCMCIA; + printk("MPI: Detected 3.3 vdc 16-bit PCMCIA card\n"); + break; + } + break; + + case (VS2_IN|VS1_IN): // CVS1 and CVS2 are open or tied to CCD1/CCD2. + // 5 valid voltage options. + + switch (data32 & (CD2_IN|CD1_IN)) // Test the values of CCD1 and CCD2. + { + case (CD2_IN|CD1_IN): // CCD1 and CCD2 are tied to 1 of the CVS pins. + // This is not a valid combination. + printk("MPI: Unknown card plugged into slot\n"); + break; + + case CD2_IN: // CCD2 is tied to either CVS1 or CVS2. + // CCD1 is tied to ground. + MPI->pcmcia_cntl1 = (CARDBUS_ENABLE|PCMCIA_GPIO_ENABLE|VS1_OEN);// Drive CVS2 to a 0. + mdelay(1); + data32 = MPI->pcmcia_cntl1; + if (data32 & CD2_IN) { // CCD2 is tied to CVS1. + printk("MPI: Detected y.y vdc Cardbus card\n"); + } else { // CCD2 is tied to CVS2. + printk("MPI: Detected x.x vdc Cardbus card\n"); + } + cardtype = MPI_CARDTYPE_CARDBUS; + break; + + case CD1_IN: // CCD1 is tied to either CVS1 or CVS2. + // CCD2 is tied to ground. + + MPI->pcmcia_cntl1 = (CARDBUS_ENABLE|PCMCIA_GPIO_ENABLE|VS1_OEN);// Drive CVS2 to a 0. + mdelay(1); + data32 = MPI->pcmcia_cntl1; + if (data32 & CD1_IN) {// CCD1 is tied to CVS1. + printk("MPI: Detected 3.3 vdc Cardbus card\n"); + } else { // CCD1 is tied to CVS2. + printk("MPI: Detected x.x and y.y Cardbus card\n"); + } + cardtype = MPI_CARDTYPE_CARDBUS; + break; + + case 0x00000000: // CCD1 and CCD2 are tied to ground. + cardtype = MPI_CARDTYPE_PCMCIA; + printk("MPI: Detected 5 vdc 16-bit PCMCIA card\n"); + break; + } + break; + + default: + printk("MPI: Unknown card plugged into slot\n"); + break; + + } + } + return cardtype; +} + +/* + * mpi_DetectPcCard: Detect the plugged in PC-Card + * Return: < 0 => Unknown card detected + * 0 => No card detected + * 1 => 16-bit card detected + * 2 => 32-bit CardBus card detected + */ +static int mpi_DetectPcCard(void) +{ + int cardtype; + + cardtype = cardtype_vcc_detect(); + switch(cardtype) { + case MPI_CARDTYPE_PCMCIA: + MPI->pcmcia_cntl1 &= ~(CARDBUS_ENABLE|PCMCIA_ENABLE|PCMCIA_GPIO_ENABLE); // disable enable bits + MPI->pcmcia_cntl1 |= (PCMCIA_ENABLE | PCMCIA_GPIO_ENABLE); + mpi_InitPcmciaSpace(); + mpi_ResetPcCard(cardtype, FALSE); + // Hold card in reset for 10ms + mdelay(10); + mpi_ResetPcCard(cardtype, TRUE); + // Let card come out of reset + mdelay(100); + break; + case MPI_CARDTYPE_CARDBUS: + // 8 => CardBus Enable + // 1 => PCI Slot Number + // C => Float VS1 & VS2 + MPI->pcmcia_cntl1 = (MPI->pcmcia_cntl1 & 0xFFFF0000) | + CARDBUS_ENABLE | + (CARDBUS_SLOT << 8)| + VS2_OEN | + VS1_OEN | PCMCIA_GPIO_ENABLE; + /* access to this memory window will be to/from CardBus */ + MPI->l2pmremap1 |= CARDBUS_MEM; + + // Need to reset the Cardbus Card. There's no CardManager to do this, + // and we need to be ready for PCI configuration. + mpi_ResetPcCard(cardtype, FALSE); + // Hold card in reset for 10ms + mdelay(10); + mpi_ResetPcCard(cardtype, TRUE); + // Let card come out of reset + mdelay(100); + break; + default: + break; + } + return cardtype; +} + +static int mpi_init(void) +{ + unsigned long data; + unsigned int chipid; + unsigned int chiprev; + unsigned int sdramsize; + unsigned int modesel; + + chipid = (PERF->RevID & 0xFFFF0000) >> 16; + chiprev = (PERF->RevID & 0xFF); + sdramsize = getMemorySize(); + +#if defined(CONFIG_BCM96348) + /* + * Init the pci interface + */ + data = GPIO->GPIOMode; // GPIO mode register + data |= GROUP2_PCI | GROUP1_MII_PCCARD; // PCI internal arbiter + Cardbus + GPIO->GPIOMode = data; // PCI internal arbiter +#endif + /* + * CardBus support is defaulted to Slot 0 + * because there is no external IDSEL for CardBus. To disable + * the CardBus and allow a standard PCI card in Slot 0 + * set the cbus_idsel field to 0x1f. + */ + /* + uData = MPI->pcmcia_cntl1; + uData |= CARDBUS_IDSEL; + MPI->pcmcia_cntl1 = uData; + */ + + // UBUS to PCI address range + // Memory Window 1. Used for devices in slot 0. Potentially can be CardBus + MPI->l2pmrange1 = ~(BCM_PCI_MEM_SIZE_16MB-1); + // UBUS to PCI Memory base address. This is akin to the ChipSelect base + // register. + MPI->l2pmbase1 = BCM_CB_MEM_BASE & BCM_PCI_ADDR_MASK; + // UBUS to PCI Remap Address. Replaces the masked address bits in the + // range register with this setting. + // Also, enable direct I/O and direct Memory accesses + MPI->l2pmremap1 = (BCM_PCI_MEM_BASE | MEM_WINDOW_EN); + + // Memory Window 2. Used for devices in other slots + MPI->l2pmrange2 = ~(BCM_PCI_MEM_SIZE_16MB-1); + // UBUS to PCI Memory base address. + MPI->l2pmbase2 = BCM_PCI_MEM_BASE & BCM_PCI_ADDR_MASK; + // UBUS to PCI Remap Address + MPI->l2pmremap2 = (BCM_PCI_MEM_BASE | MEM_WINDOW_EN); + + // Setup PCI I/O Window range. Give 64K to PCI I/O + MPI->l2piorange = ~(BCM_PCI_IO_SIZE_64KB-1); + // UBUS to PCI I/O base address + MPI->l2piobase = BCM_PCI_IO_BASE & BCM_PCI_ADDR_MASK; + // UBUS to PCI I/O Window remap + MPI->l2pioremap = (BCM_PCI_IO_BASE | MEM_WINDOW_EN); + + // enable PCI related GPIO pins and data swap between system and PCI bus + MPI->locbuscntrl = (EN_PCI_GPIO | DIR_U2P_NOSWAP); + + /* Enable BusMaster and Memory access mode */ + data = mpi_GetLocalPciConfigReg(PCI_COMMAND); + data |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + mpi_SetLocalPciConfigReg(PCI_COMMAND, data); + + /* Configure two 16 MByte PCI to System memory regions. */ + /* These memory regions are used when PCI device is a bus master */ + /* Accesses to the SDRAM from PCI bus will be "byte swapped" for this region */ + mpi_SetLocalPciConfigReg(PCI_BASE_ADDRESS_3, BCM_HOST_MEM_SPACE1); + +#if defined(CONFIG_BCM96348) + MPI->sp0remap = 0x0; +#else + MPI->sp0remap = MEM_WINDOW_EN; +#endif + + /* Accesses to the SDRAM from PCI bus will be "byte swapped" for this region */ + mpi_SetLocalPciConfigReg(PCI_BASE_ADDRESS_4, BCM_HOST_MEM_SPACE2); + +#if defined(CONFIG_BCM96348) + MPI->sp1remap = 0x0; +#else + MPI->sp1remap = MEM_WINDOW_EN; +#endif + + modesel = MPI->pcimodesel; + modesel &= ~PCI_INT_BUS_RD_PREFETCH; +#if defined(CONFIG_BCM96348) + modesel |= 0x80; +#else + modesel |= 0x100; +#endif + MPI->pcimodesel = modesel; + + if (!((chipid == 0x6348) && ((chiprev & 0xF0) == 0xa0))) { + MPI->sp0range = ~(sdramsize-1); + MPI->sp1range = ~(sdramsize-1); + } + /* + * Change PCI Cfg Reg. offset 0x40 to PCI memory read retry count infinity + * by set 0 in bit 8~15. This resolve read Bcm4306 srom return 0xffff in + * first read. + */ + data = mpi_GetLocalPciConfigReg(BRCM_PCI_CONFIG_TIMER); + data &= ~BRCM_PCI_CONFIG_TIMER_RETRY_MASK; + data |= 0x00000080; + mpi_SetLocalPciConfigReg(BRCM_PCI_CONFIG_TIMER, data); + + /* enable pci interrupt */ + MPI->locintstat |= (EXT_PCI_INT << 16); + +#if !defined(CONFIG_BCM_VDSL) + mpi_DetectPcCard(); +#endif + + ioport_resource.start = BCM_PCI_IO_BASE; + ioport_resource.end = BCM_PCI_IO_BASE + BCM_PCI_IO_SIZE_64KB; + + return 0; +} +#endif + +static int __init bcm63xx_hw_init(void) +{ +#if defined(CONFIG_PCI) + /* MPI initialization */ + mpi_init(); +#endif + +#if defined(CONFIG_USB) +#if defined(CONFIG_BCM96348) + PERF->blkEnables |= USBH_CLK_EN; + mdelay(100); + *USBH = USBH_BYTE_SWAP; +#else + USBH->SwapControl = EHCI_ENDIAN_SWAP | OHCI_ENDIAN_SWAP; + USBH->TestPortControl = 0x001c0020; +#endif +#endif + + return 0; +} + +arch_initcall(bcm63xx_hw_init); + +static int __init brcm63xx_setup(void) +{ + extern int panic_timeout; + + _machine_restart = brcm_machine_restart; + _machine_halt = brcm_machine_halt; + _machine_power_off = brcm_machine_halt; + + board_timer_setup = brcm_timer_setup; + + panic_timeout = 1; + + return 0; +} + +early_initcall(brcm63xx_setup); + +/*************************************************************************** + * C++ New and delete operator functions + ***************************************************************************/ + +/* void *operator new(unsigned int sz) */ +void *_Znwj(unsigned int sz) +{ + return( kmalloc(sz, GFP_KERNEL) ); +} + +/* void *operator new[](unsigned int sz)*/ +void *_Znaj(unsigned int sz) +{ + return( kmalloc(sz, GFP_KERNEL) ); +} + +/* placement new operator */ +/* void *operator new (unsigned int size, void *ptr) */ +void *ZnwjPv(unsigned int size, void *ptr) +{ + return ptr; +} + +/* void operator delete(void *m) */ +void _ZdlPv(void *m) +{ + kfree(m); +} + +/* void operator delete[](void *m) */ +void _ZdaPv(void *m) +{ + kfree(m); +} + +EXPORT_SYMBOL(_Znwj); +EXPORT_SYMBOL(_Znaj); +EXPORT_SYMBOL(ZnwjPv); +EXPORT_SYMBOL(_ZdlPv); +EXPORT_SYMBOL(_ZdaPv); + diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/time.c linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/time.c --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/time.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/time.c 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,277 @@ +/* +<:copyright-gpl + Copyright 2004 Broadcom Corp. All Rights Reserved. + + This program is free software; you can distribute it and/or modify it + under the terms of the GNU General Public License (Version 2) as + published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +:> +*/ +/* + * Setup time for Broadcom 963xx MIPS boards + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +unsigned long r4k_interval; /* Amount to increment compare reg each time */ +static unsigned long r4k_cur; /* What counter should be at next timer irq */ + +/* Cycle counter value at the previous timer interrupt.. */ +static unsigned int timerhi = 0, timerlo = 0; + +extern volatile unsigned long wall_jiffies; + +/* Optional board-specific timer routine */ +void (*board_timer_interrupt)(int irq, void *dev_id, struct pt_regs * regs); + +static inline void ack_r4ktimer(unsigned long newval) +{ + write_c0_compare(newval); +} + +/* + * There are a lot of conceptually broken versions of the MIPS timer interrupt + * handler floating around. This one is rather different, but the algorithm + * is provably more robust. + */ +static irqreturn_t brcm_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int count; + + if (r4k_interval == 0) + goto null; + + do { + do_timer(regs); + + if (board_timer_interrupt) + board_timer_interrupt(irq, dev_id, regs); + + r4k_cur += r4k_interval; + ack_r4ktimer(r4k_cur); + + } while (((count = (unsigned long)read_c0_count()) + - r4k_cur) < 0x7fffffff); + + if (!jiffies) { + /* + * If jiffies has overflowed in this timer_interrupt we must + * update the timer[hi]/[lo] to make do_fast_gettimeoffset() + * quotient calc still valid. -arca + */ + timerhi = timerlo = 0; + } else { + /* + * The cycle counter is only 32 bit which is good for about + * a minute at current count rates of upto 150MHz or so. + */ + timerhi += (count < timerlo); /* Wrap around */ + timerlo = count; + } + + return IRQ_HANDLED; + +null: + ack_r4ktimer(0); + return IRQ_NONE; +} + +static struct irqaction brcm_timer_action = { + .handler = brcm_timer_interrupt, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, + .name = "timer", + .next = NULL, + .dev_id = brcm_timer_interrupt, +}; + + +void __init brcm_timer_setup(struct irqaction *irq) +{ + r4k_cur = (read_c0_count() + r4k_interval); + write_c0_compare(r4k_cur); + + /* we are using the cpu counter for timer interrupts */ + irq->handler = no_action; /* we use our own handler */ + setup_irq(MIPS_TIMER_INT, &brcm_timer_action); + set_c0_status(IE_IRQ5); +} + +#if 0 +/* This is for machines which generate the exact clock. */ +#define USECS_PER_JIFFY (1000000/HZ) +#define USECS_PER_JIFFY_FRAC (0x100000000*1000000/HZ&0xffffffff) + +static void call_do_div64_32( unsigned long *res, unsigned int high, + unsigned int low, unsigned long base ) +{ + do_div64_32(*res, high, low, base); +} + +/* + * FIXME: Does playing with the RP bit in c0_status interfere with this code? + */ +static unsigned long do_fast_gettimeoffset(void) +{ + u32 count; + unsigned long res, tmp; + + /* Last jiffy when do_fast_gettimeoffset() was called. */ + static unsigned long last_jiffies=0; + unsigned long quotient; + + /* + * Cached "1/(clocks per usec)*2^32" value. + * It has to be recalculated once each jiffy. + */ + static unsigned long cached_quotient=0; + + tmp = jiffies; + + quotient = cached_quotient; + + if (tmp && last_jiffies != tmp) { + last_jiffies = tmp; +#ifdef CONFIG_CPU_MIPS32 + if (last_jiffies != 0) { + + unsigned long r0; + /* gcc 3.0.1 gets an internal compiler error if there are two + * do_div64_32 inline macros. To work around this problem, + * do_div64_32 is called as a function. + */ + call_do_div64_32(&r0, timerhi, timerlo, tmp); + call_do_div64_32("ient, USECS_PER_JIFFY, + USECS_PER_JIFFY_FRAC, r0); + + cached_quotient = quotient; + + } +#else + __asm__(".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "lwu\t%0,%2\n\t" + "dsll32\t$1,%1,0\n\t" + "or\t$1,$1,%0\n\t" + "ddivu\t$0,$1,%3\n\t" + "mflo\t$1\n\t" + "dsll32\t%0,%4,0\n\t" + "nop\n\t" + "ddivu\t$0,%0,$1\n\t" + "mflo\t%0\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=&r" (quotient) + :"r" (timerhi), + "m" (timerlo), + "r" (tmp), + "r" (USECS_PER_JIFFY) + :"$1"); + cached_quotient = quotient; +#endif + } + + /* Get last timer tick in absolute kernel time */ + count = read_c0_count(); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; + + __asm__("multu\t%1,%2\n\t" + "mfhi\t%0" + :"=r" (res) + :"r" (count), + "r" (quotient)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY-1; + + return res; +} + +void do_gettimeofday(struct timeval *tv) +{ + unsigned int flags; + + read_lock_irqsave (&xtime_lock, flags); + tv->tv_sec = xtime.tv_sec; + tv->tv_usec = xtime.tv_nsec/1000; + tv->tv_usec += do_fast_gettimeoffset(); + + /* + * xtime is atomically updated in timer_bh. jiffies - wall_jiffies + * is nonzero if the timer bottom half hasnt executed yet. + */ + if (jiffies - wall_jiffies) + tv->tv_usec += USECS_PER_JIFFY; + + read_unlock_irqrestore (&xtime_lock, flags); + + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } +} + +EXPORT_SYMBOL(do_gettimeofday); + +int do_settimeofday(struct timespec *tv) +{ + write_lock_irq (&xtime_lock); + + /* This is revolting. We need to set the xtime.tv_usec correctly. + * However, the value in this location is is value at the last tick. + * Discover what correction gettimeofday would have done, and then + * undo it! + */ + tv->tv_nsec -= do_fast_gettimeoffset()*NSEC_PER_USEC; + + if (tv->tv_nsec < 0) { + tv->tv_nsec += 1000000*NSEC_PER_USEC; + tv->tv_sec--; + } + + xtime.tv_sec = tv->tv_sec; + xtime.tv_nsec = tv->tv_nsec; + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; + + write_unlock_irq (&xtime_lock); +} + +EXPORT_SYMBOL(do_settimeofday); + +#endif diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/generic/dbg_io.c linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/generic/dbg_io.c --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/generic/dbg_io.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/generic/dbg_io.c 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,260 @@ +/* +<:copyright-gpl + Copyright 2003 Broadcom Corp. All Rights Reserved. + + This program is free software; you can distribute it and/or modify it + under the terms of the GNU General Public License (Version 2) as + published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +:> +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#undef PRNT /* define for debug printing */ + +#define UART16550_BAUD_2400 2400 +#define UART16550_BAUD_4800 4800 +#define UART16550_BAUD_9600 9600 +#define UART16550_BAUD_19200 19200 +#define UART16550_BAUD_38400 38400 +#define UART16550_BAUD_57600 57600 +#define UART16550_BAUD_115200 115200 + +#define UART16550_PARITY_NONE 0 +#define UART16550_PARITY_ODD 0x08 +#define UART16550_PARITY_EVEN 0x18 +#define UART16550_PARITY_MARK 0x28 +#define UART16550_PARITY_SPACE 0x38 + +#define UART16550_DATA_5BIT 0x0 +#define UART16550_DATA_6BIT 0x1 +#define UART16550_DATA_7BIT 0x2 +#define UART16550_DATA_8BIT 0x3 + +#define UART16550_STOP_1BIT 0x0 +#define UART16550_STOP_2BIT 0x4 + +volatile Uart * stUart = UART_BASE; + +#define WRITE16(addr, value) ((*(volatile UINT16 *)((ULONG)&addr)) = value) + +/* Low level UART routines from promcon.c */ +extern void prom_putc(char c); +extern char prom_getc(void); +extern int prom_getc_nowait(void); +extern int prom_testc(void); + +extern void set_debug_traps(void); +extern void breakpoint(void); +extern void enable_brcm_irq(unsigned int); +extern void set_async_breakpoint(unsigned int epc); + +#ifdef CONFIG_GDB_CONSOLE +extern void register_gdb_console(void); +#endif + +int gdb_initialized = 0; + +#define GDB_BUF_SIZE 512 /* power of 2, please */ + +static char gdb_buf[GDB_BUF_SIZE] ; +static int gdb_buf_in_inx ; +static atomic_t gdb_buf_in_cnt ; +static int gdb_buf_out_inx ; + +void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) +{ + /* Do nothing, assume boot loader has already set up serial port */ + printk("debugInit called\n"); +} + +/* + * Get a char if available, return -1 if nothing available. + * Empty the receive buffer first, then look at the interface hardware. + */ +static int read_char(void) +{ + if (atomic_read(&gdb_buf_in_cnt) != 0) /* intr routine has q'd chars */ + { + int chr ; + + chr = gdb_buf[gdb_buf_out_inx++] ; + gdb_buf_out_inx &= (GDB_BUF_SIZE - 1) ; + atomic_dec(&gdb_buf_in_cnt) ; + return(chr) ; + } + return(prom_getc_nowait()) ; /* read from hardware */ +} /* read_char */ + +/* + * This is the receiver interrupt routine for the GDB stub. + * It will receive a limited number of characters of input + * from the gdb host machine and save them up in a buffer. + * + * When the gdb stub routine getDebugChar() is called it + * draws characters out of the buffer until it is empty and + * then reads directly from the serial port. + * + * We do not attempt to write chars from the interrupt routine + * since the stubs do all of that via putDebugChar() which + * writes one byte after waiting for the interface to become + * ready. + * + * The debug stubs like to run with interrupts disabled since, + * after all, they run as a consequence of a breakpoint in + * the kernel. + * + * Perhaps someone who knows more about the tty driver than I + * care to learn can make this work for any low level serial + * driver. + */ +static void gdb_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + int chr ; + int more; + do + { + chr = prom_getc_nowait() ; + more = prom_testc(); + if (chr < 0) continue ; + + /* If we receive a Ctrl-C then this is GDB trying to break in */ + if (chr == 3) + { + /* Replace current instruction with breakpoint */ + set_async_breakpoint(regs->cp0_epc); + //breakpoint(); + } + +#ifdef PRNT + printk("gdb_interrupt: chr=%02x '%c', more = %x\n", + chr, chr > ' ' && chr < 0x7F ? chr : ' ', more) ; +#endif + + if (atomic_read(&gdb_buf_in_cnt) >= GDB_BUF_SIZE) + { /* buffer overflow, clear it */ + gdb_buf_in_inx = 0 ; + atomic_set(&gdb_buf_in_cnt, 0) ; + gdb_buf_out_inx = 0 ; + break ; + } + + gdb_buf[gdb_buf_in_inx++] = chr ; + gdb_buf_in_inx &= (GDB_BUF_SIZE - 1) ; + atomic_inc(&gdb_buf_in_cnt) ; + } + while (more !=0); + +} /* gdb_interrupt */ + +/* + * getDebugChar + * + * This is a GDB stub routine. It waits for a character from the + * serial interface and then returns it. If there is no serial + * interface connection then it returns a bogus value which will + * almost certainly cause the system to hang. + */ +int getDebugChar(void) +{ + volatile int chr ; + +#ifdef PRNT + printk("getDebugChar: ") ; +#endif + + while ( (chr = read_char()) < 0 ) ; + +#ifdef PRNT + printk("%c\n", chr > ' ' && chr < 0x7F ? chr : ' ') ; +#endif + return(chr) ; + +} /* getDebugChar */ + +/* + * putDebugChar + * + * This is a GDB stub routine. It waits until the interface is ready + * to transmit a char and then sends it. If there is no serial + * interface connection then it simply returns to its caller, having + * pretended to send the char. + */ +int putDebugChar(unsigned char chr) +{ +#ifdef PRNT + printk("putDebugChar: chr=%02x '%c'\n", chr, + chr > ' ' && chr < 0x7F ? chr : ' ') ; +#endif + + prom_putc(chr) ; /* this routine will wait */ + return 1; + +} /* putDebugChar */ + +/* Just a NULL routine for testing. */ +void gdb_null(void) +{ +} + +void rs_kgdb_hook(int tty_no) +{ + printk("rs_kgdb_hook: tty %d\n", tty_no); + + /* Call GDB routine to setup the exception vectors for the debugger */ + set_debug_traps(); + + printk("Breaking into debugger...\n"); + breakpoint(); + gdb_null() ; + printk("Connected.\n"); + + gdb_initialized = 1; + +#ifdef CONFIG_GDB_CONSOLE + register_gdb_console(); +#endif +} + +void kgdb_hook_irq() +{ + int retval ; + uint16 uMask; + + printk("GDB: Hooking UART interrupt\n"); + + retval = request_irq(INTERRUPT_ID_UART, + gdb_interrupt, + SA_INTERRUPT, + "GDB-stub", NULL); + + if (retval != 0) + printk("gdb_hook: request_irq(irq=%d) failed: %d\n", INTERRUPT_ID_UART, retval); + + // Enable UART config Rx not empty IRQ + uMask = READ16(stUart->intMask) ; + // printk("intMask: 0x%x\n", uMask); + WRITE16(stUart->intMask, uMask | RXFIFONE); +} + + diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/generic/int-handler.S linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/generic/int-handler.S --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/generic/int-handler.S 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/generic/int-handler.S 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,59 @@ +/* +<:copyright-gpl + Copyright 2002 Broadcom Corp. All Rights Reserved. + + This program is free software; you can distribute it and/or modify it + under the terms of the GNU General Public License (Version 2) as + published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +:> +*/ +/* + * Generic interrupt handler for Broadcom MIPS boards + */ + +#include + +#include +#include +#include +#include + +/* + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 Combined hardware interrupt (hw0) + * 3 Hardware + * 4 Hardware + * 5 Hardware + * 6 Hardware + * 7 R4k timer + */ + + .text + .set noreorder + .set noat + .align 5 + NESTED(brcmIRQ, PT_SIZE, sp) + SAVE_ALL + CLI + .set noreorder + .set at + + jal brcm_irq_dispatch + move a0, sp + + j ret_from_irq + nop + + END(brcmIRQ) diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/generic/Makefile linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/generic/Makefile --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/generic/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/generic/Makefile 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,11 @@ +# +# Makefile for generic Broadcom MIPS boards +# +# Copyright (C) 2001 Broadcom Corporation +# +obj-y := int-handler.o + +ifdef CONFIG_REMOTE_DEBUG +obj-y += dbg_io.o +endif + diff -Naur linux-mips-2.6.8.1-orig/arch/mips/defconfig linux-mips-2.6.8.1-bcm/arch/mips/defconfig --- linux-mips-2.6.8.1-orig/arch/mips/defconfig 2004-08-22 12:44:19.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/defconfig 1970-01-01 01:00:00.000000000 +0100 @@ -1,883 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -# CONFIG_64BIT is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y -CONFIG_BROKEN_ON_SMP=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_HOTPLUG is not set -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_EMBEDDED=y -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_MACH_VR41XX is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_MACH_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_MOMENCO_JAGUAR_ATX is not set -# CONFIG_PMC_YOSEMITE is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -CONFIG_SGI_IP22=y -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_HAVE_DEC_LOCK=y -CONFIG_ARC=y -CONFIG_DMA_NONCOHERENT=y -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_IRQ_CPU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_BOOT_ELF32=y -CONFIG_MIPS_L1_CACHE_SHIFT=5 -CONFIG_ARC32=y -# CONFIG_FB is not set -CONFIG_ARC_CONSOLE=y -CONFIG_ARC_PROMLIB=y - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -CONFIG_CPU_R5000=y -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_RM9000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_PAGE_SIZE_4KB=y -# CONFIG_PAGE_SIZE_8KB is not set -# CONFIG_PAGE_SIZE_16KB is not set -# CONFIG_PAGE_SIZE_64KB is not set -CONFIG_BOARD_SCACHE=y -CONFIG_IP22_CPU_SCACHE=y -# CONFIG_64BIT_PHYS_ADDR is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -# CONFIG_EISA is not set -CONFIG_MMU=y - -# -# Executable file formats -# -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -CONFIG_TRAD_SIGNALS=y -CONFIG_BINFMT_IRIX=y - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_SCSI=y -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_ST=y -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=y -# CONFIG_BLK_DEV_SR_VENDOR is not set -# CONFIG_CHR_DEV_SG is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI Transport Attributes -# -CONFIG_SCSI_SPI_ATTRS=m -# CONFIG_SCSI_FC_ATTRS is not set - -# -# SCSI low-level drivers -# -CONFIG_SGIWD93_SCSI=y -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_IPCOMP=m - -# -# IP: Virtual Server Configuration -# -CONFIG_IP_VS=m -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=12 - -# -# IPVS transport protocol load balancing support -# -CONFIG_IP_VS_PROTO_TCP=y -CONFIG_IP_VS_PROTO_UDP=y -CONFIG_IP_VS_PROTO_ESP=y -CONFIG_IP_VS_PROTO_AH=y - -# -# IPVS scheduler -# -CONFIG_IP_VS_RR=m -CONFIG_IP_VS_WRR=m -CONFIG_IP_VS_LC=m -CONFIG_IP_VS_WLC=m -CONFIG_IP_VS_LBLC=m -CONFIG_IP_VS_LBLCR=m -CONFIG_IP_VS_DH=m -CONFIG_IP_VS_SH=m -CONFIG_IP_VS_SED=m -CONFIG_IP_VS_NQ=m - -# -# IPVS application helper -# -CONFIG_IP_VS_FTP=m -CONFIG_IPV6=m -CONFIG_IPV6_PRIVACY=y -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_IPRANGE=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_RECENT=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_NAT_AMANDA=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_CLASSIFY=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_TARGET_NOTRACK=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_MATCH_ADDRTYPE=m -CONFIG_IP_NF_MATCH_REALM=m - -# -# IPv6: Netfilter Configuration -# -CONFIG_IP6_NF_QUEUE=m -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -CONFIG_IP6_NF_RAW=m -CONFIG_XFRM=y -CONFIG_XFRM_USER=m - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IP_SCTP=m -# CONFIG_SCTP_DBG_MSG is not set -# CONFIG_SCTP_DBG_OBJCNT is not set -# CONFIG_SCTP_HMAC_NONE is not set -# CONFIG_SCTP_HMAC_SHA1 is not set -CONFIG_SCTP_HMAC_MD5=y -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -CONFIG_NET_DIVERT=y -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -# CONFIG_NET_SCH_CLK_JIFFIES is not set -CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y -# CONFIG_NET_SCH_CLK_CPU is not set -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_HFSC=m -CONFIG_NET_SCH_PRIO=m -CONFIG_NET_SCH_RED=m -CONFIG_NET_SCH_SFQ=m -CONFIG_NET_SCH_TEQL=m -CONFIG_NET_SCH_TBF=m -CONFIG_NET_SCH_GRED=m -CONFIG_NET_SCH_DSMARK=m -CONFIG_NET_SCH_NETEM=m -CONFIG_NET_SCH_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -CONFIG_NET_CLS_TCINDEX=m -CONFIG_NET_CLS_ROUTE4=m -CONFIG_NET_CLS_ROUTE=y -CONFIG_NET_CLS_FW=m -CONFIG_NET_CLS_U32=m -# CONFIG_CLS_U32_PERF is not set -# CONFIG_NET_CLS_IND is not set -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -# CONFIG_NET_CLS_ACT is not set -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -CONFIG_NETDEVICES=y -CONFIG_DUMMY=m -CONFIG_BONDING=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -CONFIG_ETHERTAP=m - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -CONFIG_SGISEEQ=y - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices -# - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_IP22_ZILOG=m -CONFIG_SERIAL_CORE=m -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -# CONFIG_SOFT_WATCHDOG is not set -CONFIG_INDYDOG=m -# CONFIG_RTC is not set -CONFIG_SGI_DS1286=m -# CONFIG_GEN_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_AGP is not set -# CONFIG_DRM is not set -CONFIG_RAW_DRIVER=m -CONFIG_MAX_RAW_DEVS=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Dallas's 1-wire bus -# -# CONFIG_W1 is not set - -# -# Misc devices -# - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# Graphics support -# - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_SGI_NEWPORT_CONSOLE=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FONT_8x16=y - -# -# Logo configuration -# -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -# CONFIG_LOGO_LINUX_CLUT224 is not set -CONFIG_LOGO_SGI_CLUT224=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# File systems -# -CONFIG_EXT2_FS=m -# CONFIG_EXT2_FS_XATTR is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -CONFIG_XFS_FS=m -# CONFIG_XFS_RT is not set -CONFIG_XFS_QUOTA=y -CONFIG_XFS_SECURITY=y -# CONFIG_XFS_POSIX_ACL is not set -CONFIG_MINIX_FS=m -# CONFIG_ROMFS_FS is not set -CONFIG_QUOTA=y -# CONFIG_QFMT_V1 is not set -CONFIG_QFMT_V2=m -CONFIG_QUOTACTL=y -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_ZISOFS_FS=m -CONFIG_UDF_FS=m -CONFIG_UDF_NLS=y - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_KCORE=y -CONFIG_SYSFS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_EFS_FS=m -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -# CONFIG_NFSD_V4 is not set -CONFIG_NFSD_TCP=y -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=m -CONFIG_SUNRPC=m -CONFIG_SUNRPC_GSS=m -CONFIG_RPCSEC_GSS_KRB5=m -CONFIG_SMB_FS=m -CONFIG_SMB_NLS_DEFAULT=y -CONFIG_SMB_NLS_REMOTE="cp437" -CONFIG_CIFS=m -# CONFIG_CIFS_STATS is not set -# CONFIG_CIFS_XATTR is not set -# CONFIG_CIFS_POSIX is not set -# CONFIG_NCP_FS is not set -CONFIG_CODA_FS=m -# CONFIG_CODA_FS_OLD_API is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_EFI_PARTITION is not set - -# -# Native Language Support -# -CONFIG_NLS=m -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m -CONFIG_NLS_ASCII=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_UTF8=m - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=y -CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRYPTO_SERPENT=y -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_TEA=m -CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_KHAZAD=m -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_CRC32C=m -CONFIG_CRYPTO_TEST=m - -# -# Library routines -# -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC32 is not set -CONFIG_LIBCRC32C=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff -Naur linux-mips-2.6.8.1-orig/arch/mips/Kconfig linux-mips-2.6.8.1-bcm/arch/mips/Kconfig --- linux-mips-2.6.8.1-orig/arch/mips/Kconfig 2004-08-03 08:07:02.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/Kconfig 2006-12-20 18:48:49.000000000 +0100 @@ -27,6 +27,17 @@ menu "Machine selection" +# CONFIG_MIPS_BRCM Begin Broadcom changed code. + +config MIPS_BRCM + bool "Support for the Broadcom boards" + help + This is a family of boards based on the Broadcom MIPS32 + +source "arch/mips/brcm-boards/bcm963xx/Kconfig" + +# CONFIG_MIPS_BRCM End Broadcom changed code. + config MACH_JAZZ bool "Support for the Jazz family of machines" select ISA diff -Naur linux-mips-2.6.8.1-orig/arch/mips/kernel/cpu-probe.c linux-mips-2.6.8.1-bcm/arch/mips/kernel/cpu-probe.c --- linux-mips-2.6.8.1-orig/arch/mips/kernel/cpu-probe.c 2004-05-19 17:31:49.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/kernel/cpu-probe.c 2006-12-20 18:48:38.000000000 +0100 @@ -108,6 +108,9 @@ /* case CPU_20KC:*/ case CPU_24K: case CPU_25KF: +/* case CPU_BCM6338:*/ +/* case CPU_BCM6348:*/ +/* case CPU_BCM6358:*/ cpu_wait = r4k_wait; printk(" available.\n"); break; @@ -538,6 +541,27 @@ } } +#if defined(CONFIG_MIPS_BRCM) +static inline void cpu_probe_broadcom(struct cpuinfo_mips *c) +{ + decode_config1(c); + switch (c->processor_id & 0xff00) { + case PRID_IMP_BCM6338: + c->cputype = CPU_BCM6338; + break; + case PRID_IMP_BCM6348: + c->cputype = CPU_BCM6348; + break; + case PRID_IMP_BCM6358: + c->cputype = CPU_BCM6358; + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } +} +#endif + static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c) { decode_config1(c); @@ -576,6 +600,11 @@ case PRID_COMP_SIBYTE: cpu_probe_sibyte(c); break; +#if defined(CONFIG_MIPS_BRCM) + case PRID_COMP_BROADCOM: + cpu_probe_broadcom(c); + break; +#endif case PRID_COMP_SANDCRAFT: cpu_probe_sandcraft(c); diff -Naur linux-mips-2.6.8.1-orig/arch/mips/kernel/Makefile linux-mips-2.6.8.1-bcm/arch/mips/kernel/Makefile --- linux-mips-2.6.8.1-orig/arch/mips/kernel/Makefile 2004-06-24 23:49:57.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/kernel/Makefile 2006-12-20 18:48:38.000000000 +0100 @@ -8,6 +8,13 @@ ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \ time.o traps.o unaligned.o +# CONFIG_MIPS_BRCM Begin Broadcom added code. +# gcc 3.4.x reorders code with -Os and -O2, breaking the save_static stuff. +CFLAGS_syscall.o := -O1 +CFLAGS_signal.o := -O1 +CFLAGS_signal32.o := -O1 +# CONFIG_MIPS_BRCM End Broadcom added code. + ifdef CONFIG_MODULES obj-y += mips_ksyms.o module.o obj-$(CONFIG_MIPS32) += module-elf32.o diff -Naur linux-mips-2.6.8.1-orig/arch/mips/kernel/proc.c linux-mips-2.6.8.1-bcm/arch/mips/kernel/proc.c --- linux-mips-2.6.8.1-orig/arch/mips/kernel/proc.c 2004-03-24 11:37:26.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/kernel/proc.c 2006-12-20 18:48:38.000000000 +0100 @@ -75,6 +75,11 @@ [CPU_VR4133] "NEC VR4133", [CPU_VR4181] "NEC VR4181", [CPU_VR4181A] "NEC VR4181A", +#if defined(CONFIG_MIPS_BRCM) + [CPU_BCM6338] "BCM6338", + [CPU_BCM6348] "BCM6348", + [CPU_BCM6358] "BCM6358", +#endif [CPU_SR71000] "Sandcraft SR71000" }; diff -Naur linux-mips-2.6.8.1-orig/arch/mips/kernel/setup.c linux-mips-2.6.8.1-bcm/arch/mips/kernel/setup.c --- linux-mips-2.6.8.1-orig/arch/mips/kernel/setup.c 2004-06-28 23:04:12.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/kernel/setup.c 2006-12-20 18:48:38.000000000 +0100 @@ -78,7 +78,9 @@ * mips_io_port_base is the begin of the address space to which x86 style * I/O ports are mapped. */ -const unsigned long mips_io_port_base = -1; + +const unsigned long mips_io_port_base = KSEG1; + EXPORT_SYMBOL(mips_io_port_base); /* diff -Naur linux-mips-2.6.8.1-orig/arch/mips/kernel/time.c linux-mips-2.6.8.1-bcm/arch/mips/kernel/time.c --- linux-mips-2.6.8.1-orig/arch/mips/kernel/time.c 2004-06-08 22:35:30.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/kernel/time.c 2006-12-20 18:48:38.000000000 +0100 @@ -274,11 +274,15 @@ /* .. relative to previous jiffy (32 bits is enough) */ count -= timerlo; - + __asm__("multu %1,%2" : "=h" (res) : "r" (count), "r" (sll32_usecs_per_cycle) +#if defined(CONFIG_MIPS_BRCM) + : "lo"); +#else : "lo", "accum"); +#endif /* * Due to possible jiffies inconsistencies, we need to check @@ -333,7 +337,11 @@ __asm__("multu %1,%2" : "=h" (res) : "r" (count), "r" (quotient) +#if defined(CONFIG_MIPS_BRCM) + : "lo"); +#else : "lo", "accum"); +#endif /* * Due to possible jiffies inconsistencies, we need to check @@ -375,7 +383,11 @@ : "r" (timerhi), "m" (timerlo), "r" (tmp), "r" (USECS_PER_JIFFY), "r" (USECS_PER_JIFFY_FRAC) +#if defined(CONFIG_MIPS_BRCM) + : "hi", "lo"); +#else : "hi", "lo", "accum"); +#endif cached_quotient = quotient; } } @@ -389,7 +401,11 @@ __asm__("multu %1,%2" : "=h" (res) : "r" (count), "r" (quotient) +#if defined(CONFIG_MIPS_BRCM) + : "lo"); +#else : "lo", "accum"); +#endif /* * Due to possible jiffies inconsistencies, we need to check @@ -738,6 +754,7 @@ board_timer_setup(&timer_irqaction); } + #define FEBRUARY 2 #define STARTOFTIME 1970 #define SECDAY 86400L diff -Naur linux-mips-2.6.8.1-orig/arch/mips/kernel/traps.c linux-mips-2.6.8.1-bcm/arch/mips/kernel/traps.c --- linux-mips-2.6.8.1-orig/arch/mips/kernel/traps.c 2004-06-28 23:04:12.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/kernel/traps.c 2006-12-20 18:48:38.000000000 +0100 @@ -246,6 +246,13 @@ static spinlock_t die_lock = SPIN_LOCK_UNLOCKED; +#if defined(CONFIG_MIPS_BRCM) +#ifdef CONFIG_REMOTE_DEBUG +#include +extern void handle_exception(struct gdb_regs *regs); +#endif +#endif + NORET_TYPE void __die(const char * str, struct pt_regs * regs, const char * file, const char * func, unsigned long line) { @@ -258,6 +265,29 @@ printk(" in %s:%s, line %ld", file, func, line); printk("[#%d]:\n", ++die_counter); show_registers(regs); +#if defined(CONFIG_MIPS_BRCM) +#ifdef CONFIG_REMOTE_DEBUG + { + struct gdb_regs regs2; + int i; + long *ptr; + + ptr = ®s2.reg0; + /* Copy registers to GDB structure */ + for(i=0; i<32;i++) + *ptr++ = regs->regs[i]; + + regs2.lo = regs->lo; + regs2.hi = regs->hi; + regs2.cp0_epc = regs->cp0_epc; + regs2.cp0_badvaddr = regs->cp0_badvaddr; + regs2.cp0_status = regs->cp0_status; + regs2.cp0_cause = regs->cp0_cause; + + handle_exception(®s2); /* Break to GDB */ + } +#endif +#endif spin_unlock_irq(&die_lock); do_exit(SIGSEGV); } diff -Naur linux-mips-2.6.8.1-orig/arch/mips/Makefile linux-mips-2.6.8.1-bcm/arch/mips/Makefile --- linux-mips-2.6.8.1-orig/arch/mips/Makefile 2004-07-01 00:05:24.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/Makefile 2006-12-20 18:48:49.000000000 +0100 @@ -41,8 +41,14 @@ endif ifdef CONFIG_CROSSCOMPILE +# CONFIG_MIPS_BRCM Begin Broadcom added code. +ifdef CONFIG_MIPS_BRCM +#CROSS_COMPILE := $(tool-prefix) +else CROSS_COMPILE := $(tool-prefix) endif +# CONFIG_MIPS_BRCM End Broadcom added code. +endif # # GCC uses -G 0 -mabicalls -fpic as default. We don't want PIC in the kernel @@ -57,6 +63,9 @@ cflags-y := -I $(TOPDIR)/include/asm/gcc cflags-y += -G 0 -mno-abicalls -fno-pic -pipe cflags-y += $(call check_gcc, -finline-limit=100000,) +ifeq ($(strip $(JTAG_KERNEL_DEBUG)),y) +cflags-y += -g +endif LDFLAGS_vmlinux += -G 0 -static -n MODFLAGS += -mlong-calls @@ -64,6 +73,12 @@ check_warning = $(shell if $(CC) $(1) -c -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi) +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +ifdef CONFIG_MIPS_BRCM +cflags-$(CONFIG_REMOTE_DEBUG) += -ggdb +endif +# CONFIG_MIPS_BRCM End Broadcom changed code. + # # Use: $(call set_gccflags,,,,,) # @@ -302,6 +317,20 @@ libs-$(CONFIG_BAGET_MIPS) += arch/mips/baget/ arch/mips/baget/prom/ load-$(CONFIG_BAGET_MIPS) += 0x80001000 +# CONFIG_MIPS_BRCM Begin Broadcom added code. +ifdef CONFIG_MIPS_BRCM +# +# Broadcom board +core-$(CONFIG_BCM96338) += arch/mips/brcm-boards/generic/ arch/mips/brcm-boards/bcm963xx/ +cflags-$(CONFIG_BCM96338) += -Iinclude/asm-mips/mach-bcm963xx +core-$(CONFIG_BCM96348) += arch/mips/brcm-boards/generic/ arch/mips/brcm-boards/bcm963xx/ +cflags-$(CONFIG_BCM96348) += -Iinclude/asm-mips/mach-bcm963xx +core-$(CONFIG_BCM96358) += arch/mips/brcm-boards/generic/ arch/mips/brcm-boards/bcm963xx/ +cflags-$(CONFIG_BCM96358) += -Iinclude/asm-mips/mach-bcm963xx +load-$(CONFIG_MIPS_BRCM) += 0x80010000 +endif +# CONFIG_MIPS_BRCM End Broadcom added code. + # # Cobalt Server # diff -Naur linux-mips-2.6.8.1-orig/arch/mips/mm/c-r4k.c linux-mips-2.6.8.1-bcm/arch/mips/mm/c-r4k.c --- linux-mips-2.6.8.1-orig/arch/mips/mm/c-r4k.c 2004-07-16 14:06:13.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/mm/c-r4k.c 2006-12-20 18:48:47.000000000 +0100 @@ -803,6 +803,11 @@ if (!(config & MIPS_CONF_M)) panic("Don't know how to probe P-caches on this cpu."); +#if defined(CONFIG_MIPS_BRCM) + printk("brcm mips: enabling icache and dcache...\n"); + /* Enable caches */ + write_c0_diag(read_c0_diag() | 0xC0000000); +#endif /* * So we seem to be a MIPS32 or MIPS64 CPU * So let's probe the I-cache ... diff -Naur linux-mips-2.6.8.1-orig/arch/mips/mm/fault.c linux-mips-2.6.8.1-bcm/arch/mips/mm/fault.c --- linux-mips-2.6.8.1-orig/arch/mips/mm/fault.c 2004-04-19 18:36:35.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/mm/fault.c 2006-12-20 18:48:47.000000000 +0100 @@ -1,237 +1,237 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1995 - 2000 by Ralf Baechle - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* For unblank_screen() */ -#include - -#include -#include -#include -#include -#include -#include - -/* - * This routine handles page faults. It determines the address, - * and the problem, and then passes it off to one of the appropriate - * routines. - */ -asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, - unsigned long address) -{ - struct vm_area_struct * vma = NULL; - struct task_struct *tsk = current; - struct mm_struct *mm = tsk->mm; - const int field = sizeof(unsigned long) * 2; - siginfo_t info; - -#if 0 - printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", smp_processor_id(), - current->comm, current->pid, field, address, write, - field, regs->cp0_epc); -#endif - - info.si_code = SEGV_MAPERR; - - /* - * We fault-in kernel-space virtual memory on-demand. The - * 'reference' page table is init_mm.pgd. - * - * NOTE! We MUST NOT take any locks for this case. We may - * be in an interrupt or a critical region, and should - * only copy the information from the master page table, - * nothing more. - */ - if (unlikely(address >= VMALLOC_START)) - goto vmalloc_fault; - - /* - * If we're in an interrupt or have no user - * context, we must not take the fault.. - */ - if (in_atomic() || !mm) - goto bad_area_nosemaphore; - - down_read(&mm->mmap_sem); - vma = find_vma(mm, address); - if (!vma) - goto bad_area; - if (vma->vm_start <= address) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (expand_stack(vma, address)) - goto bad_area; -/* - * Ok, we have a good vm_area for this memory access, so - * we can handle it.. - */ -good_area: - info.si_code = SEGV_ACCERR; - - if (write) { - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area; - } else { - if (!(vma->vm_flags & (VM_READ | VM_EXEC))) - goto bad_area; - } - -survive: - /* - * If for any reason at all we couldn't handle the fault, - * make sure we exit gracefully rather than endlessly redo - * the fault. - */ - switch (handle_mm_fault(mm, vma, address, write)) { - case VM_FAULT_MINOR: - tsk->min_flt++; - break; - case VM_FAULT_MAJOR: - tsk->maj_flt++; - break; - case VM_FAULT_SIGBUS: - goto do_sigbus; - case VM_FAULT_OOM: - goto out_of_memory; - default: - BUG(); - } - - up_read(&mm->mmap_sem); - return; - -/* - * Something tried to access memory that isn't in our memory map.. - * Fix it, but check if it's kernel or user first.. - */ -bad_area: - up_read(&mm->mmap_sem); - -bad_area_nosemaphore: - /* User mode accesses just cause a SIGSEGV */ - if (user_mode(regs)) { - tsk->thread.cp0_badvaddr = address; - tsk->thread.error_code = write; -#if 0 - printk("do_page_fault() #2: sending SIGSEGV to %s for " - "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n", - tsk->comm, - write ? "write access to" : "read access from", - field, address, - field, (unsigned long) regs->cp0_epc, - field, (unsigned long) regs->regs[31]); -#endif - info.si_signo = SIGSEGV; - info.si_errno = 0; - /* info.si_code has been set above */ - info.si_addr = (void *) address; - force_sig_info(SIGSEGV, &info, tsk); - return; - } - -no_context: - /* Are we prepared to handle this kernel fault? */ - if (fixup_exception(regs)) { - current->thread.cp0_baduaddr = address; - return; - } - - /* - * Oops. The kernel tried to access some bad page. We'll have to - * terminate things with extreme prejudice. - */ - - bust_spinlocks(1); - - printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at " - "virtual address %0*lx, epc == %0*lx, ra == %0*lx\n", - smp_processor_id(), field, address, field, regs->cp0_epc, - field, regs->regs[31]); - die("Oops", regs); - -/* - * We ran out of memory, or some other thing happened to us that made - * us unable to handle the page fault gracefully. - */ -out_of_memory: - up_read(&mm->mmap_sem); - if (tsk->pid == 1) { - yield(); - down_read(&mm->mmap_sem); - goto survive; - } - printk("VM: killing process %s\n", tsk->comm); - if (user_mode(regs)) - do_exit(SIGKILL); - goto no_context; - -do_sigbus: - up_read(&mm->mmap_sem); - - /* Kernel mode? Handle exceptions or die */ - if (!user_mode(regs)) - goto no_context; - - /* - * Send a sigbus, regardless of whether we were in kernel - * or user mode. - */ - tsk->thread.cp0_badvaddr = address; - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRERR; - info.si_addr = (void *) address; - force_sig_info(SIGBUS, &info, tsk); - - return; - -vmalloc_fault: - { - /* - * Synchronize this task's top level page-table - * with the 'reference' page table. - * - * Do _not_ use "tsk" here. We might be inside - * an interrupt in the middle of a task switch.. - */ - int offset = __pgd_offset(address); - pgd_t *pgd, *pgd_k; - pmd_t *pmd, *pmd_k; - pte_t *pte_k; - - pgd = (pgd_t *) pgd_current[smp_processor_id()] + offset; - pgd_k = init_mm.pgd + offset; - - if (!pgd_present(*pgd_k)) - goto no_context; - set_pgd(pgd, *pgd_k); - - pmd = pmd_offset(pgd, address); - pmd_k = pmd_offset(pgd_k, address); - if (!pmd_present(*pmd_k)) - goto no_context; - set_pmd(pmd, *pmd_k); - - pte_k = pte_offset_kernel(pmd_k, address); - if (!pte_present(*pte_k)) - goto no_context; - return; - } -} +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995 - 2000 by Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* For unblank_screen() */ +#include + +#include +#include +#include +#include +#include +#include + +/* + * This routine handles page faults. It determines the address, + * and the problem, and then passes it off to one of the appropriate + * routines. + */ +asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, + unsigned long address) +{ + struct vm_area_struct * vma = NULL; + struct task_struct *tsk = current; + struct mm_struct *mm = tsk->mm; + const int field = sizeof(unsigned long) * 2; + siginfo_t info; + +#if 0 + printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", smp_processor_id(), + current->comm, current->pid, field, address, write, + field, regs->cp0_epc); +#endif + + info.si_code = SEGV_MAPERR; + + /* + * We fault-in kernel-space virtual memory on-demand. The + * 'reference' page table is init_mm.pgd. + * + * NOTE! We MUST NOT take any locks for this case. We may + * be in an interrupt or a critical region, and should + * only copy the information from the master page table, + * nothing more. + */ + if (unlikely(address >= VMALLOC_START)) + goto vmalloc_fault; + + /* + * If we're in an interrupt or have no user + * context, we must not take the fault.. + */ + if (in_atomic() || !mm) + goto bad_area_nosemaphore; + + down_read(&mm->mmap_sem); + vma = find_vma(mm, address); + if (!vma) + goto bad_area; + if (vma->vm_start <= address) + goto good_area; + if (!(vma->vm_flags & VM_GROWSDOWN)) + goto bad_area; + if (expand_stack(vma, address)) + goto bad_area; +/* + * Ok, we have a good vm_area for this memory access, so + * we can handle it.. + */ +good_area: + info.si_code = SEGV_ACCERR; + + if (write) { + if (!(vma->vm_flags & VM_WRITE)) + goto bad_area; + } else { + if (!(vma->vm_flags & (VM_READ | VM_EXEC))) + goto bad_area; + } + +survive: + /* + * If for any reason at all we couldn't handle the fault, + * make sure we exit gracefully rather than endlessly redo + * the fault. + */ + switch (handle_mm_fault(mm, vma, address, write)) { + case VM_FAULT_MINOR: + tsk->min_flt++; + break; + case VM_FAULT_MAJOR: + tsk->maj_flt++; + break; + case VM_FAULT_SIGBUS: + goto do_sigbus; + case VM_FAULT_OOM: + goto out_of_memory; + default: + BUG(); + } + + up_read(&mm->mmap_sem); + return; + +/* + * Something tried to access memory that isn't in our memory map.. + * Fix it, but check if it's kernel or user first.. + */ +bad_area: + up_read(&mm->mmap_sem); + +bad_area_nosemaphore: + /* User mode accesses just cause a SIGSEGV */ + if (user_mode(regs)) { + tsk->thread.cp0_badvaddr = address; + tsk->thread.error_code = write; +#if 1 + printk("do_page_fault() #2: sending SIGSEGV to %s for " + "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n", + tsk->comm, + write ? "write access to" : "read access from", + field, address, + field, (unsigned long) regs->cp0_epc, + field, (unsigned long) regs->regs[31]); +#endif + info.si_signo = SIGSEGV; + info.si_errno = 0; + /* info.si_code has been set above */ + info.si_addr = (void *) address; + force_sig_info(SIGSEGV, &info, tsk); + return; + } + +no_context: + /* Are we prepared to handle this kernel fault? */ + if (fixup_exception(regs)) { + current->thread.cp0_baduaddr = address; + return; + } + + /* + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. + */ + + bust_spinlocks(1); + + printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at " + "virtual address %0*lx, epc == %0*lx, ra == %0*lx\n", + smp_processor_id(), field, address, field, regs->cp0_epc, + field, regs->regs[31]); + die("Oops", regs); + +/* + * We ran out of memory, or some other thing happened to us that made + * us unable to handle the page fault gracefully. + */ +out_of_memory: + up_read(&mm->mmap_sem); + if (tsk->pid == 1) { + yield(); + down_read(&mm->mmap_sem); + goto survive; + } + printk("VM: killing process %s\n", tsk->comm); + if (user_mode(regs)) + do_exit(SIGKILL); + goto no_context; + +do_sigbus: + up_read(&mm->mmap_sem); + + /* Kernel mode? Handle exceptions or die */ + if (!user_mode(regs)) + goto no_context; + + /* + * Send a sigbus, regardless of whether we were in kernel + * or user mode. + */ + tsk->thread.cp0_badvaddr = address; + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_ADRERR; + info.si_addr = (void *) address; + force_sig_info(SIGBUS, &info, tsk); + + return; + +vmalloc_fault: + { + /* + * Synchronize this task's top level page-table + * with the 'reference' page table. + * + * Do _not_ use "tsk" here. We might be inside + * an interrupt in the middle of a task switch.. + */ + int offset = __pgd_offset(address); + pgd_t *pgd, *pgd_k; + pmd_t *pmd, *pmd_k; + pte_t *pte_k; + + pgd = (pgd_t *) pgd_current[smp_processor_id()] + offset; + pgd_k = init_mm.pgd + offset; + + if (!pgd_present(*pgd_k)) + goto no_context; + set_pgd(pgd, *pgd_k); + + pmd = pmd_offset(pgd, address); + pmd_k = pmd_offset(pgd_k, address); + if (!pmd_present(*pmd_k)) + goto no_context; + set_pmd(pmd, *pmd_k); + + pte_k = pte_offset_kernel(pmd_k, address); + if (!pte_present(*pte_k)) + goto no_context; + return; + } +} diff -Naur linux-mips-2.6.8.1-orig/arch/mips/pci/fixup-bcm63xx.c linux-mips-2.6.8.1-bcm/arch/mips/pci/fixup-bcm63xx.c --- linux-mips-2.6.8.1-orig/arch/mips/pci/fixup-bcm63xx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/pci/fixup-bcm63xx.c 2006-12-20 18:48:43.000000000 +0100 @@ -0,0 +1,84 @@ +/* +<:copyright-gpl + Copyright 2002 Broadcom Corp. All Rights Reserved. + + This program is free software; you can distribute it and/or modify it + under the terms of the GNU General Public License (Version 2) as + published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +:> +*/ +#include +#include +#include + +#include +#include +#include + +static char irq_tab_bcm63xx[] __initdata = { + [0] = INTERRUPT_ID_MPI, + [1] = INTERRUPT_ID_MPI, +#if defined(CONFIG_USB) + [USB_HOST_SLOT] = INTERRUPT_ID_USBH, +#if !defined(CONFIG_BCM96348) + [USB20_HOST_SLOT] = INTERRUPT_ID_USBH20 +#endif +#endif +}; + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + return irq_tab_bcm63xx[slot]; +} + +static void bcm63xx_fixup(struct pci_dev *dev) +{ + uint32 memaddr; + uint32 size; + uint32 resno; + + memaddr = pci_resource_start(dev, 0); + size = pci_resource_len(dev, 0); + + switch (PCI_SLOT(dev->devfn)) { + case 0: + // Move device in slot 0 to a different memory range + // In case this is a CB device, it will be accessed via l2pmremap1 + // which will have CARDBUS_MEM bit set + for (resno = 0; resno < 6; resno++) { + if (dev->resource[resno].end && (dev->resource[resno].start < BCM_CB_MEM_BASE)) { + dev->resource[resno].start += (BCM_CB_MEM_BASE - BCM_PCI_MEM_BASE); + dev->resource[resno].end += (BCM_CB_MEM_BASE - BCM_PCI_MEM_BASE); + } + } + break; + +#if defined(CONFIG_USB) + case USB_HOST_SLOT: + dev->resource[0].start = USB_OHCI_BASE; + dev->resource[0].end = USB_OHCI_BASE+USB_BAR0_MEM_SIZE-1; + break; + +#if !defined(CONFIG_BCM96348) + case USB20_HOST_SLOT: + dev->resource[0].start = USB_EHCI_BASE; + dev->resource[0].end = USB_EHCI_BASE+USB_BAR0_MEM_SIZE-1; + break; +#endif +#endif + } +} + +struct pci_fixup pcibios_fixups[] = { + { PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, bcm63xx_fixup }, + {0} +}; diff -Naur linux-mips-2.6.8.1-orig/arch/mips/pci/Makefile linux-mips-2.6.8.1-bcm/arch/mips/pci/Makefile --- linux-mips-2.6.8.1-orig/arch/mips/pci/Makefile 2004-07-01 00:05:24.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/pci/Makefile 2006-12-20 18:48:43.000000000 +0100 @@ -17,6 +17,8 @@ obj-$(CONFIG_MIPS_NILE4) += ops-nile4.o obj-$(CONFIG_MIPS_TX3927) += ops-jmr3927.o obj-$(CONFIG_PCI_VR41XX) += ops-vr41xx.o pci-vr41xx.o +obj-$(CONFIG_PCI_VR41XX) += ops-vr41xx.o pci-vr41xx.o +obj-$(CONFIG_BCM_PCI) += fixup-bcm63xx.o pci-bcm63xx.o ops-bcm63xx.o # # These are still pretty much in the old state, watch, go blind. @@ -51,3 +53,7 @@ obj-$(CONFIG_TOSHIBA_RBTX4927) += fixup-rbtx4927.o ops-tx4927.o obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o + +ifeq "$(CONFIG_BCM_PCI)" "y" +EXTRA_CFLAGS += -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) +endif diff -Naur linux-mips-2.6.8.1-orig/arch/mips/pci/ops-bcm63xx.c linux-mips-2.6.8.1-bcm/arch/mips/pci/ops-bcm63xx.c --- linux-mips-2.6.8.1-orig/arch/mips/pci/ops-bcm63xx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/pci/ops-bcm63xx.c 2006-12-20 18:48:43.000000000 +0100 @@ -0,0 +1,408 @@ +/* +<:copyright-gpl + Copyright 2002 Broadcom Corp. All Rights Reserved. + + This program is free software; you can distribute it and/or modify it + under the terms of the GNU General Public License (Version 2) as + published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +:> +*/ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#if defined(CONFIG_USB) +#if 0 +#define DPRINT(x...) printk(x) +#else +#define DPRINT(x...) +#endif + +static int pci63xx_int_usb_read(unsigned int devfn, int where, u32 * value, int size); +static int pci63xx_int_usb_write(unsigned int devfn, int where, u32 * value, int size); + +static bool usb_mem_size_rd = FALSE; +static uint32 usb_mem_base = 0; +static uint32 usb_cfg_space_cmd_reg = 0; + +#if !defined(CONFIG_BCM96348) +static int pci63xx_int_usb20_read(unsigned int devfn, int where, u32 * value, int size); +static int pci63xx_int_usb20_write(unsigned int devfn, int where, u32 * value, int size); + +static bool usb20_mem_size_rd = FALSE; +static uint32 usb20_mem_base = 0; +static uint32 usb20_cfg_space_cmd_reg = 0; +#endif + +#endif +static bool pci_mem_size_rd = FALSE; + +static volatile MpiRegisters * mpi = (MpiRegisters *)(MPI_BASE); + +static void mpi_SetupPciConfigAccess(uint32 addr) +{ + mpi->l2pcfgctl = (DIR_CFG_SEL | DIR_CFG_USEREG | addr) & ~CONFIG_TYPE; +} + +static void mpi_ClearPciConfigAccess(void) +{ + mpi->l2pcfgctl = 0x00000000; +} + +#if defined(CONFIG_USB) +/* -------------------------------------------------------------------------- + Name: pci63xx_int_usb_write +Abstract: PCI Config write on internal device(s) + -------------------------------------------------------------------------- */ +static int pci63xx_int_usb_write(unsigned int devfn, int where, u32 * value, int size) +{ + switch (size) { + case 1: + DPRINT("W => Slot: %d Where: %2X Len: %d Data: %02X\n", + PCI_SLOT(devfn), where, size, *value); + break; + case 2: + DPRINT("W => Slot: %d Where: %2X Len: %d Data: %04X\n", + PCI_SLOT(devfn), where, size, *value); + switch (where) { + case PCI_COMMAND: + usb_cfg_space_cmd_reg = *value; + break; + default: + break; + } + break; + case 4: + DPRINT("W => Slot: %d Where: %2X Len: %d Data: %08lX\n", + PCI_SLOT(devfn), where, size, *value); + switch (where) { + case PCI_BASE_ADDRESS_0: + if (*value == 0xffffffff) { + usb_mem_size_rd = TRUE; + } else { + usb_mem_base = *value; + } + break; + default: + break; + } + break; + default: + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +/* -------------------------------------------------------------------------- + Name: pci63xx_int_usb_read +Abstract: PCI Config read on internal device(s) + -------------------------------------------------------------------------- */ +static int pci63xx_int_usb_read(unsigned int devfn, int where, u32 * value, int size) +{ + uint32 retValue = 0xFFFFFFFF; + + // For now, this is specific to the USB Host controller. We can + // make it more general if we have to... + // Emulate PCI Config accesses + switch (where) { + case PCI_VENDOR_ID: + case PCI_DEVICE_ID: + retValue = PCI_VENDOR_ID_BROADCOM | 0x63000000; + break; + case PCI_COMMAND: + case PCI_STATUS: + retValue = (0x0006 << 16) | usb_cfg_space_cmd_reg; + break; + case PCI_CLASS_REVISION: + case PCI_CLASS_DEVICE: + retValue = (PCI_CLASS_SERIAL_USB << 16) | (0x10 << 8) | 0x01; + break; + case PCI_BASE_ADDRESS_0: + if (usb_mem_size_rd) { + retValue = USB_BAR0_MEM_SIZE; + } else { + if (usb_mem_base != 0) + retValue = usb_mem_base; + else + retValue = USB_OHCI_BASE; + } + usb_mem_size_rd = FALSE; + break; + case PCI_CACHE_LINE_SIZE: + case PCI_LATENCY_TIMER: + retValue = 0; + break; + case PCI_HEADER_TYPE: + retValue = PCI_HEADER_TYPE_NORMAL; + break; + case PCI_SUBSYSTEM_VENDOR_ID: + retValue = PCI_VENDOR_ID_BROADCOM; + break; + case PCI_SUBSYSTEM_ID: + retValue = 0x6300; + break; + case PCI_INTERRUPT_LINE: + retValue = INTERRUPT_ID_USBH; + break; + default: + break; + } + + switch (size) { + case 1: + *value = (retValue >> ((where & 3) << 3)) & 0xff; + DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %02X\n", + PCI_SLOT(devfn), where, size, *value); + break; + case 2: + *value = (retValue >> ((where & 3) << 3)) & 0xffff; + DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %04X\n", + PCI_SLOT(devfn), where, size, *value); + break; + case 4: + *value = retValue; + DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %08lX\n", + PCI_SLOT(devfn), where, size, *value); + break; + default: + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +#if !defined(CONFIG_BCM96348) +/* -------------------------------------------------------------------------- + Name: pci63xx_int_usb20_write +Abstract: PCI Config write on internal device(s) + -------------------------------------------------------------------------- */ +static int pci63xx_int_usb20_write(unsigned int devfn, int where, u32 * value, int size) +{ + switch (size) { + case 1: + DPRINT("W => Slot: %d Where: %2X Len: %d Data: %02X\n", + PCI_SLOT(devfn), where, size, *value); + break; + case 2: + DPRINT("W => Slot: %d Where: %2X Len: %d Data: %04X\n", + PCI_SLOT(devfn), where, size, *value); + switch (where) { + case PCI_COMMAND: + usb20_cfg_space_cmd_reg = *value; + break; + default: + break; + } + break; + case 4: + DPRINT("W => Slot: %d Where: %2X Len: %d Data: %08lX\n", + PCI_SLOT(devfn), where, size, *value); + switch (where) { + case PCI_BASE_ADDRESS_0: + if (*value == 0xffffffff) { + usb20_mem_size_rd = TRUE; + } else { + usb20_mem_base = *value; + } + break; + default: + break; + } + break; + default: + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +/* -------------------------------------------------------------------------- + Name: pci63xx_int_usb20_read +Abstract: PCI Config read on internal device(s) + -------------------------------------------------------------------------- */ +static int pci63xx_int_usb20_read(unsigned int devfn, int where, u32 * value, int size) +{ + uint32 retValue = 0xFFFFFFFF; + + // For now, this is specific to the USB Host controller. We can + // make it more general if we have to... + // Emulate PCI Config accesses + switch (where) { + case PCI_VENDOR_ID: + case PCI_DEVICE_ID: + retValue = PCI_VENDOR_ID_BROADCOM | 0x63000000; + break; + case PCI_COMMAND: + case PCI_STATUS: + retValue = (0x0006 << 16) | usb20_cfg_space_cmd_reg; + break; + case PCI_CLASS_REVISION: + case PCI_CLASS_DEVICE: + retValue = (PCI_CLASS_SERIAL_USB << 16) | (0x20 << 8) | 0x01; + break; + case PCI_BASE_ADDRESS_0: + if (usb20_mem_size_rd) { + retValue = USB_BAR0_MEM_SIZE; + } else { + if (usb20_mem_base != 0) + retValue = usb20_mem_base; + else + retValue = USB_EHCI_BASE; + } + usb20_mem_size_rd = FALSE; + break; + case PCI_CACHE_LINE_SIZE: + case PCI_LATENCY_TIMER: + retValue = 0; + break; + case PCI_HEADER_TYPE: + retValue = PCI_HEADER_TYPE_NORMAL; + break; + case PCI_SUBSYSTEM_VENDOR_ID: + retValue = PCI_VENDOR_ID_BROADCOM; + break; + case PCI_SUBSYSTEM_ID: + retValue = 0x6300; + break; + case PCI_INTERRUPT_LINE: + retValue = INTERRUPT_ID_USBH20; + break; + default: + break; + } + + switch (size) { + case 1: + *value = (retValue >> ((where & 3) << 3)) & 0xff; + DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %02X\n", + PCI_SLOT(devfn), where, size, *value); + break; + case 2: + *value = (retValue >> ((where & 3) << 3)) & 0xffff; + DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %04X\n", + PCI_SLOT(devfn), where, size, *value); + break; + case 4: + *value = retValue; + DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %08lX\n", + PCI_SLOT(devfn), where, size, *value); + break; + default: + break; + } + + return PCIBIOS_SUCCESSFUL; +} +#endif +#endif + +static int bcm63xx_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + volatile unsigned char *ioBase = (unsigned char *)(mpi->l2piobase | KSEG1); + uint32 data; + +#if defined(CONFIG_USB) + if (PCI_SLOT(devfn) == USB_HOST_SLOT) + return pci63xx_int_usb_read(devfn, where, val, size); +#if !defined(CONFIG_BCM96348) + if (PCI_SLOT(devfn) == USB20_HOST_SLOT) + return pci63xx_int_usb20_read(devfn, where, val, size); +#endif +#endif + + mpi_SetupPciConfigAccess(BCM_PCI_CFG(PCI_SLOT(devfn), PCI_FUNC(devfn), where)); + data = *(uint32 *)ioBase; + switch(size) { + case 1: + *val = (data >> ((where & 3) << 3)) & 0xff; + break; + case 2: + *val = (data >> ((where & 3) << 3)) & 0xffff; + break; + case 4: + *val = data; + /* Special case for reading PCI device range */ + if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5)) { + if (pci_mem_size_rd) { + /* bcm63xx PCI memory window minimum size is 64K */ + /* preserve the lower 4 bits */ + if ((*val & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) + *val &= (PCI_SIZE_64K + ~PCI_BASE_ADDRESS_MEM_MASK); + } + } + break; + default: + break; + } + pci_mem_size_rd = FALSE; + mpi_ClearPciConfigAccess(); + + return PCIBIOS_SUCCESSFUL; +} + +static int bcm63xx_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + volatile unsigned char *ioBase = (unsigned char *)(mpi->l2piobase | KSEG1); + uint32 data; + +#if defined(CONFIG_USB) + if (PCI_SLOT(devfn) == USB_HOST_SLOT) + return pci63xx_int_usb_write(devfn, where, &val, size); +#if !defined(CONFIG_BCM96348) + if (PCI_SLOT(devfn) == USB20_HOST_SLOT) + return pci63xx_int_usb20_write(devfn, where, &val, size); +#endif +#endif + mpi_SetupPciConfigAccess(BCM_PCI_CFG(PCI_SLOT(devfn), PCI_FUNC(devfn), where)); + data = *(uint32 *)ioBase; + switch(size) { + case 1: + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + break; + case 2: + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + break; + case 4: + data = val; + /* Special case for reading PCI device range */ + if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5)) { + if (val == 0xffffffff) + pci_mem_size_rd = TRUE; + } + break; + default: + break; + } + *(uint32 *)ioBase = data; + udelay(500); + mpi_ClearPciConfigAccess(); + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops bcm63xx_pci_ops = { + .read = bcm63xx_pcibios_read, + .write = bcm63xx_pcibios_write +}; diff -Naur linux-mips-2.6.8.1-orig/arch/mips/pci/pci-bcm63xx.c linux-mips-2.6.8.1-bcm/arch/mips/pci/pci-bcm63xx.c --- linux-mips-2.6.8.1-orig/arch/mips/pci/pci-bcm63xx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/pci/pci-bcm63xx.c 2006-12-20 18:48:43.000000000 +0100 @@ -0,0 +1,56 @@ +/* +<:copyright-gpl + Copyright 2002 Broadcom Corp. All Rights Reserved. + + This program is free software; you can distribute it and/or modify it + under the terms of the GNU General Public License (Version 2) as + published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +:> +*/ +#include +#include +#include +#include + +#include +#include + +static struct resource bcm_pci_io_resource = { + .name = "bcm63xx pci IO space", + .start = BCM_PCI_IO_BASE, + .end = BCM_PCI_IO_BASE + BCM_PCI_IO_SIZE_64KB - 1, + .flags = IORESOURCE_IO +}; + +static struct resource bcm_pci_mem_resource = { + .name = "bcm63xx pci memory space", + .start = BCM_PCI_MEM_BASE, + .end = BCM_PCI_MEM_BASE + BCM_PCI_MEM_SIZE_16MB - 1, + .flags = IORESOURCE_MEM +}; + +extern struct pci_ops bcm63xx_pci_ops; + +struct pci_controller bcm63xx_controller = { + .pci_ops = &bcm63xx_pci_ops, + .io_resource = &bcm_pci_io_resource, + .mem_resource = &bcm_pci_mem_resource, +}; + +static int __init bcm63xx_pci_init(void) +{ + register_pci_controller(&bcm63xx_controller); + + return 0; +} + +arch_initcall(bcm63xx_pci_init); diff -Naur linux-mips-2.6.8.1-orig/.cvsignore linux-mips-2.6.8.1-bcm/.cvsignore --- linux-mips-2.6.8.1-orig/.cvsignore 2004-04-28 15:54:52.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/.cvsignore 1970-01-01 01:00:00.000000000 +0100 @@ -1,16 +0,0 @@ -!core -.config -.*.cmd -.hdepend -.tmp* -.version -Module.symvers -System.map -vmlinux -vmlinux.64 -vmlinux.ecoff -vmlinux.rm200 -modules -nohup.out -build-log -build-log-summary diff -Naur linux-mips-2.6.8.1-orig/drivers/mtd/maps/bcm963xx.c linux-mips-2.6.8.1-bcm/drivers/mtd/maps/bcm963xx.c --- linux-mips-2.6.8.1-orig/drivers/mtd/maps/bcm963xx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/drivers/mtd/maps/bcm963xx.c 2007-01-08 16:04:36.000000000 +0100 @@ -0,0 +1,124 @@ +/* + * A simple flash mapping code for BCM963xx board flash memory + * It is simple because it only treats all the flash memory as ROM + * It is used with chips/map_rom.c + * + * Song Wang (songw@broadcom.com) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#define VERSION "1.0" + +#define PARTITION_NUM 6 + + + + +static struct mtd_info *mymtd; +static struct mtd_partition brcm_partition_info [PARTITION_NUM]; + + + +static struct map_info main_physmap_map = { + .name = "8MB NOR flash", + .bankwidth = 2, +}; + +static int __init init_brcm_physmap(void) +{ + printk("9box mtd driver v%s\n", VERSION); + + + main_physmap_map.size = ( 8 << 20 ); + main_physmap_map.map_priv_1 = EFIXO_BOOT; + main_physmap_map.virt = EFIXO_BOOT; + + + /* Set map_priv_2 to the amount of flash memory that is memory mapped to + * the flash base address. On the BCM6338, serial flash parts are only + * memory mapped up to 1MB even though the flash part may be bigger. + */ + + if ( main_physmap_map.map_priv_1 == NULL ) { + printk("Wrong rootfs starting address\n"); + return -EIO; + } + + if ( main_physmap_map.size <= 0 ) { + printk("Wrong rootfs size\n"); + return -EIO; + } + + mymtd = do_map_probe ("cfi_probe", &main_physmap_map); + + if ( mymtd == NULL ) { + return -EIO; + } + + brcm_partition_info[0].name = "bootloader"; + brcm_partition_info[0].offset = EFIXO_CFE_START; + brcm_partition_info[0].size = EFIXO_CFE_SIZE; + brcm_partition_info[0].mask_flags = MTD_WRITEABLE; + + brcm_partition_info[1].name = "main kernel+fs"; + brcm_partition_info[1].offset = EFIXO_MAIN_START + EFIXO_TAG_SIZE; + brcm_partition_info[1].size = EFIXO_MAIN_SIZE - EFIXO_TAG_SIZE; + brcm_partition_info[1].mask_flags = MTD_WRITEABLE; + + brcm_partition_info[2].name = "jffs2"; + brcm_partition_info[2].offset = EFIXO_JFFS2_START; + brcm_partition_info[2].size = EFIXO_JFFS2_SIZE; + brcm_partition_info[2].mask_flags = 0; + + brcm_partition_info[3].name = "rescue kernel+fs"; + brcm_partition_info[3].offset = EFIXO_RESCUE_START + EFIXO_TAG_SIZE; + brcm_partition_info[3].size = EFIXO_RESCUE_SIZE - EFIXO_TAG_SIZE; + brcm_partition_info[3].mask_flags = MTD_WRITEABLE; + + brcm_partition_info[4].name = "adsl driver"; + brcm_partition_info[4].offset = EFIXO_ADSL_START; + brcm_partition_info[4].size = EFIXO_ADSL_SIZE; + brcm_partition_info[4].mask_flags = 0; + + brcm_partition_info[5].name = "nvram"; + brcm_partition_info[5].offset = EFIXO_NVRAM_START; + brcm_partition_info[5].size = EFIXO_NVRAM_SIZE; + brcm_partition_info[5].mask_flags = 0; + + add_mtd_partitions (mymtd, brcm_partition_info, PARTITION_NUM); + + return 0; +} + +static void __exit cleanup_brcm_physmap(void) +{ + if ( mymtd ) { + del_mtd_device (mymtd); + map_destroy (mymtd); + } + if ( main_physmap_map.map_priv_1 ) { + main_physmap_map.map_priv_1 = 0; + } +} + +module_init (init_brcm_physmap); +module_exit (cleanup_brcm_physmap); + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Song Wang songw@broadcom.com"); +MODULE_DESCRIPTION("Configurable MTD map driver for read-only root file system"); diff -Naur linux-mips-2.6.8.1-orig/drivers/mtd/maps/Kconfig linux-mips-2.6.8.1-bcm/drivers/mtd/maps/Kconfig --- linux-mips-2.6.8.1-orig/drivers/mtd/maps/Kconfig 2004-08-14 18:16:43.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/drivers/mtd/maps/Kconfig 2006-12-20 18:49:16.000000000 +0100 @@ -60,6 +60,12 @@ Ignore this option if you use run-time physmap configuration (i.e., run-time calling physmap_configure()). +config MTD_BCM963XX + tristate "Broadcom 963xx ADSL board flash memory support" + depends on MIPS_BRCM + help + Broadcom 963xx ADSL board flash memory + config MTD_SUN_UFLASH tristate "Sun Microsystems userflash support" depends on (SPARC32 || SPARC64) && MTD_CFI diff -Naur linux-mips-2.6.8.1-orig/drivers/mtd/maps/Makefile linux-mips-2.6.8.1-bcm/drivers/mtd/maps/Makefile --- linux-mips-2.6.8.1-orig/drivers/mtd/maps/Makefile 2004-07-20 22:21:21.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/drivers/mtd/maps/Makefile 2006-12-20 18:49:16.000000000 +0100 @@ -68,3 +68,7 @@ obj-$(CONFIG_MTD_PB1100) += pb1xxx-flash.o obj-$(CONFIG_MTD_PB1500) += pb1xxx-flash.o obj-$(CONFIG_MTD_DB1X00) += db1x00-flash.o +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +obj-$(CONFIG_MTD_BCM963XX) += bcm963xx.o +EXTRA_CFLAGS += -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) +# CONFIG_MIPS_BRCM End Broadcom changed code. diff -Naur linux-mips-2.6.8.1-orig/drivers/net/ppp_generic.c linux-mips-2.6.8.1-bcm/drivers/net/ppp_generic.c --- linux-mips-2.6.8.1-orig/drivers/net/ppp_generic.c 2004-08-13 09:18:54.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/drivers/net/ppp_generic.c 2006-12-20 18:51:02.000000000 +0100 @@ -51,6 +51,13 @@ #define PPP_VERSION "2.4.2" +#if defined(CONFIG_MIPS_BRCM) +#include +#define QOS_HIGH_PRIO 3 +#define QOS_MED_PRIO 2 +#define QOS_LOW_PRIO 1 +#endif + /* * Network protocols we support. */ @@ -66,6 +73,11 @@ #define MPHDRLEN_SSN 4 /* ditto with short sequence numbers */ #define MIN_FRAG_SIZE 64 +#if defined(CONFIG_MIPS_BRCM) +#define OFFSET1 10 +#define OFFSET2 100000 +#endif + /* * An instance of /dev/ppp can be associated with either a ppp * interface unit or a ppp channel. In both cases, file->private_data @@ -459,6 +471,11 @@ kfree_skb(skb); goto out; } + +#if defined(CONFIG_MIPS_BRCM) + skb->nfmark = QOS_HIGH_PRIO; + skb->nfcache |= NFC_ALTERED; +#endif skb_queue_tail(&pf->xq, skb); @@ -1008,6 +1025,49 @@ ppp_xmit_unlock(ppp); } +#if defined(CONFIG_MIPS_BRCM) +/* + * Excluding timestamp for packet generated from ADSL modem + * these include WAN-side RIP,dnsprobe + */ +static int +brcm_on_demand_filter(char *data) +{ + unsigned short udp_port=0; + +#if 0 + char cmd; + + printk("%02x%02x%02x%02x\n%02x%02x%02x%02x\n",data[2],data[3],data[4],data[5],data[6],data[7],data[8],data[9]); + printk("%02x%02x%02x%02x\n%02x%02x%02x%02x\n",data[10],data[11],data[12],data[13],data[14],data[15],data[16],data[17]); + printk("%02x%02x%02x%02x\n",data[18],data[19],data[20],data[21]); +#endif + + if ( data[11] == 0x2 ) /* IGMP */ + return 0; + if ( data[11] == 0x11 ) { /* UDP */ + udp_port= (data[24]<< 8) + data[25]; + if ( udp_port == 123 ) { /* ntpclient */ + return 0; + } + if ( udp_port == 53 ) { + if ( data[45] == 'r' && data[46] == 'o' && data[47] == 'o' && data[48] =='t') + + return 0; + } + else if (udp_port == 520) { /* RIP */ +#if 0 + cmd = data[30]; // 1=request, 2=reply + if ( cmd == 1) +#endif + return 0; + } + } + + return 1; +} +#endif + /* * Compress and send a frame. * The caller should have locked the xmit path, @@ -1020,6 +1080,15 @@ struct sk_buff *new_skb; int len; unsigned char *cp; +#if defined(CONFIG_MIPS_BRCM) + unsigned char *data; + int timestamp = 1; + + if ( proto == PPP_IP) { + data = skb->data; + timestamp = brcm_on_demand_filter(data); + } +#endif if (proto < 0x8000) { #ifdef CONFIG_PPP_FILTER @@ -1039,10 +1108,16 @@ if (!(ppp->active_filter && sk_run_filter(skb, ppp->active_filter, ppp->active_len) == 0)) +#if defined(CONFIG_MIPS_BRCM) + if (timestamp) +#endif ppp->last_xmit = jiffies; skb_pull(skb, 2); #else /* for data packets, record the time */ +#if defined(CONFIG_MIPS_BRCM) + if (timestamp) +#endif ppp->last_xmit = jiffies; #endif /* CONFIG_PPP_FILTER */ } @@ -1126,6 +1201,10 @@ if (ppp->flags & SC_LOOP_TRAFFIC) { if (ppp->file.rq.qlen > PPP_MAX_RQLEN) goto drop; +#if defined(CONFIG_MIPS_BRCM) + if (!timestamp) + goto drop; +#endif skb_queue_tail(&ppp->file.rq, skb); wake_up_interruptible(&ppp->file.rwait); return; @@ -1476,11 +1555,36 @@ slhc_toss(ppp->vj); } +#if defined(CONFIG_MIPS_BRCM) +static int +brcm_mcast_filter(char *data) +{ + struct iphdr *encap; + + encap = (struct iphdr *)(data + 2); + if ( MULTICAST(encap->daddr)) { + if ( !LOCAL_MCAST(encap->daddr)) { // real mcast data + //printk("bcm_mcast_filer: 0x%x \n",encap->daddr); + return 1; // no timestamp + } + else + return 0; + } + else + return 0; +} +#endif + static void ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) { struct sk_buff *ns; int proto, len, npi; +#if defined(CONFIG_MIPS_BRCM) + struct sk_buff *tmp; + int timestamp=0; + unsigned char *data; +#endif /* * Decompress the frame, if compressed. @@ -1492,6 +1596,13 @@ skb = ppp_decompress_frame(ppp, skb); proto = PPP_PROTO(skb); + +#if defined(CONFIG_MIPS_BRCM) + if (proto == PPP_IP) { + data = skb->data; + timestamp = brcm_mcast_filter(data); + } +#endif switch (proto) { case PPP_VJC_COMP: /* decompress VJ compressed packets */ @@ -1569,6 +1680,15 @@ /* check if the packet passes the pass and active filters */ /* the filter instructions are constructed assuming a four-byte PPP header on each packet */ +#if defined(CONFIG_MIPS_BRCM) + if (skb_headroom(skb) < 2) { + tmp = alloc_skb(skb->len+2,GFP_ATOMIC); + skb_reserve(tmp, 2); + memcpy(skb_put(tmp, skb->len), skb->data, skb->len); + kfree_skb(skb); + skb = tmp; + } +#endif *skb_push(skb, 2) = 0; if (ppp->pass_filter && sk_run_filter(skb, ppp->pass_filter, @@ -1581,9 +1701,15 @@ if (!(ppp->active_filter && sk_run_filter(skb, ppp->active_filter, ppp->active_len) == 0)) +#if defined(CONFIG_MIPS_BRCM) + if (timestamp) +#endif ppp->last_recv = jiffies; skb_pull(skb, 2); #else +#if defined(CONFIG_MIPS_BRCM) + if (timestamp) +#endif ppp->last_recv = jiffies; #endif /* CONFIG_PPP_FILTER */ @@ -2319,6 +2445,9 @@ struct net_device *dev = NULL; int ret = -ENOMEM; int i; +#if defined(CONFIG_MIPS_BRCM) + int num1, num2, num3; +#endif ppp = kmalloc(sizeof(struct ppp), GFP_KERNEL); if (!ppp) @@ -2356,6 +2485,17 @@ /* Initialize the new ppp unit */ ppp->file.index = unit; + +#if defined(CONFIG_MIPS_BRCM) + if ((unit+1) > OFFSET1) + { + num1 = unit / (OFFSET2*OFFSET1); + num2 = (unit - OFFSET2*OFFSET1*num1) / OFFSET1; + num3 = (unit - OFFSET2*OFFSET1*num1) - OFFSET1*num2; + sprintf(dev->name, "ppp_%d_%d_%d", num1, num2, num3); + } + else +#endif sprintf(dev->name, "ppp%d", unit); ret = register_netdev(dev); diff -Naur linux-mips-2.6.8.1-orig/drivers/usb/core/hub.c linux-mips-2.6.8.1-bcm/drivers/usb/core/hub.c --- linux-mips-2.6.8.1-orig/drivers/usb/core/hub.c 2004-08-06 02:33:29.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/drivers/usb/core/hub.c 2007-01-08 16:04:37.000000000 +0100 @@ -1280,9 +1280,9 @@ * unchanged for 100ms it returns the port status. */ -#define HUB_DEBOUNCE_TIMEOUT 1500 +#define HUB_DEBOUNCE_TIMEOUT 15000 #define HUB_DEBOUNCE_STEP 25 -#define HUB_DEBOUNCE_STABLE 100 +#define HUB_DEBOUNCE_STABLE 1000 static int hub_port_debounce(struct usb_device *hdev, int port) { @@ -1606,7 +1606,6 @@ } portstatus = status; } - /* Return now if nothing is connected */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) { diff -Naur linux-mips-2.6.8.1-orig/drivers/usb/host/ehci-hcd.c linux-mips-2.6.8.1-bcm/drivers/usb/host/ehci-hcd.c --- linux-mips-2.6.8.1-orig/drivers/usb/host/ehci-hcd.c 2004-07-20 22:21:23.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/drivers/usb/host/ehci-hcd.c 2006-12-20 18:51:24.000000000 +0100 @@ -786,13 +786,24 @@ /* PCI errors [4.15.2.4] */ if (unlikely ((status & STS_FATAL) != 0)) { + + /* bogus "fatal" IRQs appear on some chips... why? */ + status = readl (&ehci->regs->status); + dbg_cmd (ehci, "fatal", readl (&ehci->regs->command)); + dbg_status (ehci, "fatal", status); + if (status & STS_HALT) { + ehci_err (ehci, "fatal error\n"); dead: ehci_reset (ehci); + + writel (0, &ehci->regs->configured_flag); + /* generic layer kills/unlinks all urbs, then * uses ehci_stop to clean up the rest */ bh = 1; + } } if (bh) diff -Naur linux-mips-2.6.8.1-orig/drivers/usb/host/Makefile linux-mips-2.6.8.1-bcm/drivers/usb/host/Makefile --- linux-mips-2.6.8.1-orig/drivers/usb/host/Makefile 2003-06-02 12:48:42.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/drivers/usb/host/Makefile 2006-12-20 18:51:24.000000000 +0100 @@ -8,3 +8,7 @@ obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_SL811HS) += hc_sl811.o + +ifeq ($(CONFIG_BCM96348),y) +EXTRA_CFLAGS += -DCONFIG_SWAP_IO_SPACE -D__MIPSEB__ +endif \ Pas de fin de ligne à la fin du fichier. diff -Naur linux-mips-2.6.8.1-orig/drivers/usb/storage/transport.c linux-mips-2.6.8.1-bcm/drivers/usb/storage/transport.c --- linux-mips-2.6.8.1-orig/drivers/usb/storage/transport.c 2004-06-30 19:26:48.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/drivers/usb/storage/transport.c 2006-12-20 18:51:22.000000000 +0100 @@ -110,7 +110,7 @@ complete(urb_done_ptr); } - + /* This is the timeout handler which will cancel an URB when its timeout * expires. */ @@ -180,7 +180,7 @@ usb_unlink_urb(us->current_urb); } } - + /* submit the timeout timer, if a timeout was requested */ if (timeout > 0) { init_timer(&to_timer); @@ -193,7 +193,7 @@ /* wait for the completion of the URB */ wait_for_completion(&urb_done); clear_bit(US_FLIDX_URB_ACTIVE, &us->flags); - + /* clean up the timeout timer */ if (timeout > 0) del_timer_sync(&to_timer); @@ -207,7 +207,7 @@ * termination. Return codes are usual -Exxx, *not* USB_STOR_XFER_xxx. */ int usb_stor_control_msg(struct us_data *us, unsigned int pipe, - u8 request, u8 requesttype, u16 value, u16 index, + u8 request, u8 requesttype, u16 value, u16 index, void *data, u16 size, int timeout) { int status; @@ -224,8 +224,8 @@ us->cr->wLength = cpu_to_le16(size); /* fill and submit the URB */ - usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe, - (unsigned char*) us->cr, data, size, + usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe, + (unsigned char*) us->cr, data, size, usb_stor_blocking_completion, NULL); status = usb_stor_msg_common(us, timeout); @@ -364,8 +364,8 @@ us->cr->wLength = cpu_to_le16(size); /* fill and submit the URB */ - usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe, - (unsigned char*) us->cr, data, size, + usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe, + (unsigned char*) us->cr, data, size, usb_stor_blocking_completion, NULL); result = usb_stor_msg_common(us, 0); @@ -423,7 +423,7 @@ /* store the actual length of the data transferred */ if (act_len) *act_len = us->current_urb->actual_length; - return interpret_urb_result(us, pipe, length, result, + return interpret_urb_result(us, pipe, length, result, us->current_urb->actual_length); } @@ -502,7 +502,7 @@ length_left -= partial; } else { /* no scatter-gather, just make the request */ - result = usb_stor_bulk_transfer_buf(us, pipe, buf, + result = usb_stor_bulk_transfer_buf(us, pipe, buf, length_left, &partial); length_left -= partial; } @@ -575,7 +575,7 @@ } /* - * If we have a failure, we're going to do a REQUEST_SENSE + * If we have a failure, we're going to do a REQUEST_SENSE * automatically. Note that we differentiate between a command * "failure" and an "error" in the transport mechanism. */ @@ -683,12 +683,12 @@ US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", srb->sense_buffer[0], srb->sense_buffer[2] & 0xf, - srb->sense_buffer[12], + srb->sense_buffer[12], srb->sense_buffer[13]); #ifdef CONFIG_USB_STORAGE_DEBUG usb_stor_show_sense( srb->sense_buffer[2] & 0xf, - srb->sense_buffer[12], + srb->sense_buffer[12], srb->sense_buffer[13]); #endif @@ -758,8 +758,8 @@ /* COMMAND STAGE */ /* let's send the command via the control pipe */ result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, - US_CBI_ADSC, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, + US_CBI_ADSC, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, srb->cmnd, srb->cmd_len); /* check the return code for the command */ @@ -778,7 +778,7 @@ /* DATA STAGE */ /* transfer the data payload for this command, if one exists*/ if (transfer_length) { - pipe = srb->sc_data_direction == SCSI_DATA_READ ? + pipe = srb->sc_data_direction == SCSI_DATA_READ ? us->recv_bulk_pipe : us->send_bulk_pipe; result = usb_stor_bulk_transfer_sg(us, pipe, srb->request_buffer, transfer_length, @@ -794,7 +794,7 @@ /* STATUS STAGE */ result = usb_stor_intr_transfer(us, us->iobuf, 2); - US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", + US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", us->iobuf[0], us->iobuf[1]); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -815,7 +815,7 @@ return USB_STOR_TRANSPORT_GOOD; } - /* If not UFI, we interpret the data as a result code + /* If not UFI, we interpret the data as a result code * The first byte should always be a 0x0. * * Some bogus devices don't follow that rule. They stuff the ASC @@ -830,9 +830,9 @@ /* The second byte & 0x0F should be 0x0 for good, otherwise error */ switch (us->iobuf[1] & 0x0F) { - case 0x00: + case 0x00: return USB_STOR_TRANSPORT_GOOD; - case 0x01: + case 0x01: goto Failed; } return USB_STOR_TRANSPORT_ERROR; @@ -857,8 +857,8 @@ /* COMMAND STAGE */ /* let's send the command via the control pipe */ result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, - US_CBI_ADSC, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, + US_CBI_ADSC, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, srb->cmnd, srb->cmd_len); /* check the return code for the command */ @@ -877,7 +877,7 @@ /* DATA STAGE */ /* transfer the data payload for this command, if one exists*/ if (transfer_length) { - unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? + unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? us->recv_bulk_pipe : us->send_bulk_pipe; result = usb_stor_bulk_transfer_sg(us, pipe, srb->request_buffer, transfer_length, @@ -908,20 +908,22 @@ int result; /* issue the command */ + us->iobuf[0] = 0; result = usb_stor_control_msg(us, us->recv_ctrl_pipe, - US_BULK_GET_MAX_LUN, - USB_DIR_IN | USB_TYPE_CLASS | + US_BULK_GET_MAX_LUN, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, us->iobuf, 1, HZ); - US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", + US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", result, us->iobuf[0]); /* if we have a successful request, return the result */ - if (result == 1) +/* if (result == 1)*/ + if (result >= 0) return us->iobuf[0]; - /* + /* * Some devices (i.e. Iomega Zip100) need this -- apparently * the bulk pipes get STALLed when the GetMaxLUN request is * processed. This is, in theory, harmless to all other devices @@ -967,7 +969,7 @@ US_DEBUGP("Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n", le32_to_cpu(bcb->Signature), bcb->Tag, le32_to_cpu(bcb->DataTransferLength), bcb->Flags, - (bcb->Lun >> 4), (bcb->Lun & 0x0F), + (bcb->Lun >> 4), (bcb->Lun & 0x0F), bcb->Length); result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, US_BULK_CB_WRAP_LEN, NULL); @@ -978,7 +980,7 @@ /* DATA STAGE */ /* send/receive data payload, if there is any */ if (transfer_length) { - unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? + unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? us->recv_bulk_pipe : us->send_bulk_pipe; result = usb_stor_bulk_transfer_sg(us, pipe, srb->request_buffer, transfer_length, @@ -1033,11 +1035,11 @@ /* check bulk status */ residue = le32_to_cpu(bcs->Residue); US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n", - le32_to_cpu(bcs->Signature), bcs->Tag, + le32_to_cpu(bcs->Signature), bcs->Tag, residue, bcs->Status); if ((bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) && bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) || - bcs->Tag != srb->serial_number || + bcs->Tag != srb->serial_number || bcs->Status > US_BULK_STAT_PHASE) { US_DEBUGP("Bulk logical error\n"); return USB_STOR_TRANSPORT_ERROR; @@ -1045,16 +1047,20 @@ /* try to compute the actual residue, based on how much data * was really transferred and what the device tells us */ - residue = min(residue, transfer_length); - srb->resid = max(srb->resid, (int) residue); + /*residue = min(residue, transfer_length); + srb->resid = max(srb->resid, (int) residue);*/ + if (!(us->flags & US_FL_IGNORE_RESIDUE)) { + residue = min(residue, transfer_length); + srb->resid = max(srb->resid, (int) residue); + } /* based on the status code, we report good or bad */ switch (bcs->Status) { case US_BULK_STAT_OK: /* device babbled -- return fake sense data */ if (fake_sense) { - memcpy(srb->sense_buffer, - usb_stor_sense_invalidCDB, + memcpy(srb->sense_buffer, + usb_stor_sense_invalidCDB, sizeof(usb_stor_sense_invalidCDB)); return USB_STOR_TRANSPORT_NO_SENSE; } @@ -1159,7 +1165,7 @@ memset(us->iobuf, 0xFF, CB_RESET_CMD_SIZE); us->iobuf[0] = SEND_DIAGNOSTIC; us->iobuf[1] = 4; - return usb_stor_reset_common(us, US_CBI_ADSC, + return usb_stor_reset_common(us, US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, us->iobuf, CB_RESET_CMD_SIZE); } @@ -1171,7 +1177,7 @@ { US_DEBUGP("%s called\n", __FUNCTION__); - return usb_stor_reset_common(us, US_BULK_RESET_REQUEST, + return usb_stor_reset_common(us, US_BULK_RESET_REQUEST, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, NULL, 0); } diff -Naur linux-mips-2.6.8.1-orig/drivers/usb/storage/unusual_devs.h linux-mips-2.6.8.1-bcm/drivers/usb/storage/unusual_devs.h --- linux-mips-2.6.8.1-orig/drivers/usb/storage/unusual_devs.h 2004-07-20 22:21:24.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/drivers/usb/storage/unusual_devs.h 2006-12-20 18:51:22.000000000 +0100 @@ -45,10 +45,10 @@ * */ -UNUSUAL_DEV( 0x03ee, 0x0000, 0x0000, 0x0245, +UNUSUAL_DEV( 0x03ee, 0x0000, 0x0000, 0x0245, "Mitsumi", "CD-R/RW Drive", - US_SC_8020, US_PR_CBI, NULL, 0), + US_SC_8020, US_PR_CBI, NULL, 0), UNUSUAL_DEV( 0x03ee, 0x6901, 0x0000, 0x0100, "Mitsumi", @@ -56,21 +56,21 @@ US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), -UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200, +UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200, "HP", "CD-Writer+", - US_SC_8070, US_PR_CB, NULL, 0), + US_SC_8070, US_PR_CB, NULL, 0), #ifdef CONFIG_USB_STORAGE_HP8200e -UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, +UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, "HP", "CD-Writer+ 8200e", - US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0), + US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0), -UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, +UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, "HP", "CD-Writer+ CD-4e", - US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0), + US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0), #endif /* : I don't know the name of the bridge @@ -171,7 +171,7 @@ /* Reported by Kriston Fincher * Patch submitted by Sean Millichamp * This is to support the Panasonic PalmCam PV-SD4090 - * This entry is needed because the device reports Sub=ff + * This entry is needed because the device reports Sub=ff */ UNUSUAL_DEV( 0x04da, 0x0901, 0x0100, 0x0200, "Panasonic", @@ -188,19 +188,19 @@ /* Most of the following entries were developed with the help of * Shuttle/SCM directly. */ -UNUSUAL_DEV( 0x04e6, 0x0001, 0x0200, 0x0200, +UNUSUAL_DEV( 0x04e6, 0x0001, 0x0200, 0x0200, "Matshita", "LS-120", US_SC_8020, US_PR_CB, NULL, 0), -UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100, +UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100, "Shuttle", "eUSCSI Bridge", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, - US_FL_SCM_MULT_TARG ), + US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, + US_FL_SCM_MULT_TARG ), #ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999, +UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999, "Sandisk", "ImageMate SDDR09", US_SC_SCSI, US_PR_EUSB_SDDR09, NULL, @@ -210,45 +210,45 @@ UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, "SCM Microsystems", "eUSB SmartMedia / CompactFlash Adapter", - US_SC_SCSI, US_PR_DPCM_USB, sddr09_init, - 0), + US_SC_SCSI, US_PR_DPCM_USB, sddr09_init, + 0), #endif -UNUSUAL_DEV( 0x04e6, 0x0006, 0x0100, 0x0205, +UNUSUAL_DEV( 0x04e6, 0x0006, 0x0100, 0x0205, "Shuttle", "eUSB MMC Adapter", - US_SC_SCSI, US_PR_DEVICE, NULL, - US_FL_SINGLE_LUN), + US_SC_SCSI, US_PR_DEVICE, NULL, + US_FL_SINGLE_LUN), -UNUSUAL_DEV( 0x04e6, 0x0007, 0x0100, 0x0200, +UNUSUAL_DEV( 0x04e6, 0x0007, 0x0100, 0x0200, "Sony", "Hifd", - US_SC_SCSI, US_PR_CB, NULL, - US_FL_SINGLE_LUN), + US_SC_SCSI, US_PR_CB, NULL, + US_FL_SINGLE_LUN), -UNUSUAL_DEV( 0x04e6, 0x0009, 0x0200, 0x0200, +UNUSUAL_DEV( 0x04e6, 0x0009, 0x0200, 0x0200, "Shuttle", "eUSB ATA/ATAPI Adapter", US_SC_8020, US_PR_CB, NULL, 0), -UNUSUAL_DEV( 0x04e6, 0x000a, 0x0200, 0x0200, +UNUSUAL_DEV( 0x04e6, 0x000a, 0x0200, 0x0200, "Shuttle", "eUSB CompactFlash Adapter", US_SC_8020, US_PR_CB, NULL, 0), -UNUSUAL_DEV( 0x04e6, 0x000B, 0x0100, 0x0100, +UNUSUAL_DEV( 0x04e6, 0x000B, 0x0100, 0x0100, "Shuttle", "eUSCSI Bridge", - US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, - US_FL_SCM_MULT_TARG ), + US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, + US_FL_SCM_MULT_TARG ), -UNUSUAL_DEV( 0x04e6, 0x000C, 0x0100, 0x0100, +UNUSUAL_DEV( 0x04e6, 0x000C, 0x0100, 0x0100, "Shuttle", "eUSCSI Bridge", - US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, - US_FL_SCM_MULT_TARG ), + US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, + US_FL_SCM_MULT_TARG ), -UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200, +UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200, "Shuttle", "CD-RW Device", US_SC_8020, US_PR_CB, NULL, 0), @@ -260,7 +260,7 @@ US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), -/* Iomega Clik! Drive +/* Iomega Clik! Drive * Reported by David Chatenay * The reason this is needed is not fully known. */ @@ -270,23 +270,30 @@ US_SC_8070, US_PR_BULK, NULL, US_FL_FIX_INQUIRY ), +/* Reported by Iacopo Spalletti */ +UNUSUAL_DEV( 0x052b, 0x1807, 0x0100, 0x0100, + "Tekom Technologies, Inc", + "300_CAMERA", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + /* This entry is needed because the device reports Sub=ff */ -UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450, +UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450, "Sony", - "DSC-S30/S70/S75/505V/F505/F707/F717/P8", + "DSC-S30/S70/S75/505V/F505/F707/F717/P8", US_SC_SCSI, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN | US_FL_MODE_XLATE ), /* This entry is needed because the device reports Sub=ff */ -UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0500, +UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0500, "Sony", - "DSC-T1", + "DSC-T1", US_SC_8070, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN | US_FL_MODE_XLATE ), /* Reported by wim@geeks.nl */ -UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100, +UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100, "Sony", "Memorystick NW-MS7", US_SC_DEVICE, US_PR_DEVICE, NULL, @@ -300,21 +307,21 @@ 0 ), #endif -UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100, +UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100, "Sony", "Memorystick MSAC-US1", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), /* Submitted by Klaus Mueller */ -UNUSUAL_DEV( 0x054c, 0x002e, 0x0106, 0x0310, +UNUSUAL_DEV( 0x054c, 0x002e, 0x0106, 0x0310, "Sony", "Handycam", US_SC_SCSI, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN | US_FL_MODE_XLATE), /* Submitted by Rajesh Kumble Nayak */ -UNUSUAL_DEV( 0x054c, 0x002e, 0x0500, 0x0500, +UNUSUAL_DEV( 0x054c, 0x002e, 0x0500, 0x0500, "Sony", "Handycam HC-85", US_SC_UFI, US_PR_DEVICE, NULL, @@ -332,7 +339,7 @@ "PEG N760c Memorystick", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), - + UNUSUAL_DEV( 0x054c, 0x0069, 0x0000, 0x9999, "Sony", "Memorystick MSC-U03", @@ -352,7 +359,7 @@ "PEG Mass Storage", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), - + /* Submitted by Frank Engel */ UNUSUAL_DEV( 0x054c, 0x0099, 0x0000, 0x9999, "Sony", @@ -360,14 +367,14 @@ US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), - -UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299, + +UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299, "Y-E Data", "Flashbuster-U", US_SC_DEVICE, US_PR_CB, NULL, US_FL_SINGLE_LUN), -UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999, +UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999, "Y-E Data", "Flashbuster-U", US_SC_DEVICE, US_PR_DEVICE, NULL, @@ -379,10 +386,10 @@ "Digital Camera EX-20 DSC", US_SC_8070, US_PR_DEVICE, NULL, 0 ), -UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200, +UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200, "LaCie", "USB Hard Disk", - US_SC_RBC, US_PR_CB, NULL, 0 ), + US_SC_RBC, US_PR_CB, NULL, 0 ), /* Submitted by Jol Bourquard */ UNUSUAL_DEV( 0x05ab, 0x0060, 0x1104, 0x1110, @@ -442,11 +449,11 @@ US_FL_FIX_INQUIRY ), /* Submitted Alexander Oltu */ -UNUSUAL_DEV( 0x05e3, 0x0701, 0x0000, 0xffff, - "Genesys Logic", +UNUSUAL_DEV( 0x05e3, 0x0701, 0x0000, 0xffff, + "Genesys Logic", "USB to IDE Optical", US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_MODE_XLATE ), + US_FL_MODE_XLATE ), /* Reported by Peter Marks * Like the SIIG unit above, this unit needs an INQUIRY to ask for exactly @@ -469,13 +476,13 @@ US_SC_SCSI, US_PR_BULK, NULL, US_FL_FIX_INQUIRY | US_FL_MODE_XLATE), -UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100, +UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100, "TEAC", "Floppy Drive", - US_SC_UFI, US_PR_CB, NULL, 0 ), + US_SC_UFI, US_PR_CB, NULL, 0 ), #ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100, +UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100, "Olympus", "Camedia MAUSB-2", US_SC_SCSI, US_PR_EUSB_SDDR09, NULL, @@ -494,7 +501,7 @@ "DIMAGE E223", US_SC_SCSI, US_PR_DEVICE, NULL, 0 ), -UNUSUAL_DEV( 0x0693, 0x0002, 0x0100, 0x0100, +UNUSUAL_DEV( 0x0693, 0x0002, 0x0100, 0x0100, "Hagiwara", "FlashGate SmartMedia", US_SC_SCSI, US_PR_BULK, NULL, 0 ), @@ -502,15 +509,15 @@ UNUSUAL_DEV( 0x0693, 0x0005, 0x0100, 0x0100, "Hagiwara", "Flashgate", - US_SC_SCSI, US_PR_BULK, NULL, 0 ), + US_SC_SCSI, US_PR_BULK, NULL, 0 ), -UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200, +UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200, "Sandisk", "ImageMate SDDR-05a", US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN ), -UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009, +UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009, "Sandisk", "ImageMate SDDR-31", US_SC_DEVICE, US_PR_DEVICE, NULL, @@ -523,7 +530,7 @@ US_FL_SINGLE_LUN ), #ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999, +UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999, "Sandisk", "ImageMate SDDR-09", US_SC_SCSI, US_PR_EUSB_SDDR09, NULL, @@ -537,17 +544,17 @@ US_SC_QIC, US_PR_FREECOM, freecom_init, 0), #endif -UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0133, +UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0133, "Microtech", "USB-SCSI-DB25", US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, - US_FL_SCM_MULT_TARG ), + US_FL_SCM_MULT_TARG ), -UNUSUAL_DEV( 0x07af, 0x0005, 0x0100, 0x0100, +UNUSUAL_DEV( 0x07af, 0x0005, 0x0100, 0x0100, "Microtech", "USB-SCSI-HD50", US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, - US_FL_SCM_MULT_TARG ), + US_FL_SCM_MULT_TARG ), #ifdef CONFIG_USB_STORAGE_DPCM UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, @@ -604,7 +611,7 @@ US_SC_SCSI, US_PR_DATAFAB, NULL, US_FL_MODE_XLATE ), #endif - + #ifdef CONFIG_USB_STORAGE_SDDR55 /* Contributed by Peter Waechtler */ UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999, @@ -668,7 +675,7 @@ US_FL_FIX_INQUIRY), /* Aiptek PocketCAM 3Mega - * Nicolas DUPEUX + * Nicolas DUPEUX */ UNUSUAL_DEV( 0x08ca, 0x2011, 0x0000, 0x9999, "AIPTEK", @@ -733,7 +740,7 @@ "Optio S/S4", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), - + #ifdef CONFIG_USB_STORAGE_ISD200 UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, "ATI", @@ -791,7 +798,14 @@ "Solid state disk", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), - + +/* Reported by Rastislav Stanik */ +UNUSUAL_DEV( 0x0ea0, 0x6828, 0x0110, 0x0110, + "USB", + "Flash Disk", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + /* Reported by Kevin Cernekee * Tested on hardware version 1.10. * Entry is needed only for the initializer function override. @@ -814,7 +828,7 @@ US_FL_MODE_XLATE ), #ifdef CONFIG_USB_STORAGE_SDDR55 -UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999, +UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999, "Sandisk", "ImageMate SDDR55", US_SC_SCSI, US_PR_SDDR55, NULL, diff -Naur linux-mips-2.6.8.1-orig/drivers/usb/storage/usb.h linux-mips-2.6.8.1-bcm/drivers/usb/storage/usb.h --- linux-mips-2.6.8.1-orig/drivers/usb/storage/usb.h 2004-06-26 17:15:20.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/drivers/usb/storage/usb.h 2006-12-20 18:51:22.000000000 +0100 @@ -54,7 +54,7 @@ struct us_data; /* - * Unusual device list definitions + * Unusual device list definitions */ struct us_unusual_dev { @@ -70,10 +70,11 @@ #define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */ #define US_FL_MODE_XLATE 0 /* [no longer used] */ #define US_FL_NEED_OVERRIDE 0x00000004 /* unusual_devs entry is necessary */ -#define US_FL_IGNORE_SER 0 /* [no longer used] */ +#define US_FL_IGNORE_SER 0 /* [no longer used] */ #define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */ #define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs faking */ #define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */ +#define US_FL_IGNORE_RESIDUE 0x00000100 /* reported residue is wrong */ /* Dynamic flag definitions: used in set_bit() etc. */ #define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */ @@ -135,7 +136,7 @@ u8 max_lun; u8 ifnum; /* interface number */ - u8 ep_bInterval; /* interrupt interval */ + u8 ep_bInterval; /* interrupt interval */ /* function pointers for this device */ trans_cmnd transport; /* transport function */ diff -Naur linux-mips-2.6.8.1-orig/fs/cramfs/inode.c linux-mips-2.6.8.1-bcm/fs/cramfs/inode.c --- linux-mips-2.6.8.1-orig/fs/cramfs/inode.c 2004-04-23 17:54:18.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/fs/cramfs/inode.c 2006-12-20 18:46:33.000000000 +0100 @@ -426,11 +426,32 @@ return NULL; } +#ifdef DEBUG +static void dumpHex(unsigned char *start, int len) +{ + unsigned char *ptr = start, + *end = start + len; + int i; + + while (ptr < end) { + for (i=0;i<16 && ptr < end;i++) + printk("%4x", *ptr++); + printk("\n"); + } +} +#endif + static int cramfs_readpage(struct file *file, struct page * page) { struct inode *inode = page->mapping->host; u32 maxblock, bytes_filled; void *pgdata; +#if defined(CONFIG_MIPS_BRCM) +#ifdef CONFIG_LZMA_FS_INFLATE + extern int decompress_lzma_7z(unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size); + char *p; +#endif +#endif maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; bytes_filled = 0; @@ -446,19 +467,50 @@ compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) - start_offset); up(&read_mutex); pgdata = kmap(page); +#if defined(CONFIG_MIPS_BRCM) + /* Move the initilization done here first */ + memset(pgdata, 0, PAGE_CACHE_SIZE); +#endif + if (compr_len == 0) ; /* hole */ else { down(&read_mutex); +#ifdef CONFIG_ZLIB_FS_INFLATE + bytes_filled = cramfs_uncompress_block(pgdata, PAGE_CACHE_SIZE, cramfs_read(sb, start_offset, compr_len), compr_len); +#endif + +#ifdef CONFIG_LZMA_FS_INFLATE + p = cramfs_read(sb, start_offset, compr_len); +#ifdef DEBUG + printk("Input data, size =%d\n",compr_len); + dumpHex((unsigned char *)p,compr_len); +#endif + if (decompress_lzma_7z(p, compr_len, + pgdata,PAGE_CACHE_SIZE) != 0) { + printk("Error while decompressing!\n"); + } +#ifdef DEBUG + printk("Output data, size =%d\n",bytes_filled); + dumpHex((unsigned char *)pgdata,bytes_filled); +#endif +#endif + up(&read_mutex); } } else pgdata = kmap(page); + +#if defined(CONFIG_MIPS_BRCM) + /* memset(pgdata + bytes_filled, 0, PAGE_CACHE_SIZE - bytes_filled); */ +#else memset(pgdata + bytes_filled, 0, PAGE_CACHE_SIZE - bytes_filled); +#endif + kunmap(page); flush_dcache_page(page); SetPageUptodate(page); @@ -509,13 +561,26 @@ static int __init init_cramfs_fs(void) { - cramfs_uncompress_init(); +#if defined(CONFIG_MIPS_BRCM) +#ifdef CONFIG_ZLIB_FS_INFLATE + cramfs_uncompress_init(); +#endif +#else + cramfs_uncompress_init(); +#endif return register_filesystem(&cramfs_fs_type); } static void __exit exit_cramfs_fs(void) { - cramfs_uncompress_exit(); +#if defined(CONFIG_MIPS_BRCM) +#ifdef CONFIG_ZLIB_FS_INFLATE + cramfs_uncompress_exit(); +#endif +#else + cramfs_uncompress_exit(); +#endif + unregister_filesystem(&cramfs_fs_type); } diff -Naur linux-mips-2.6.8.1-orig/fs/cramfs/Makefile linux-mips-2.6.8.1-bcm/fs/cramfs/Makefile --- linux-mips-2.6.8.1-orig/fs/cramfs/Makefile 2003-06-02 12:48:43.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/fs/cramfs/Makefile 2006-12-20 18:46:33.000000000 +0100 @@ -4,4 +4,16 @@ obj-$(CONFIG_CRAMFS) += cramfs.o +#cramfs-objs := inode.o uncompress.o + +# CONFIG_MIPS_BRCM Begin Broadcom changed code. + +ifdef CONFIG_ZLIB_FS_INFLATE cramfs-objs := inode.o uncompress.o +else +ifdef CONFIG_LZMA_FS_INFLATE +cramfs-objs := inode.o ../inflate_lzma/7zlzma.o ../inflate_lzma/LZMADecoder.o ../inflate_lzma/IInOutStreams.o +endif +endif + +# CONFIG_MIPS_BRCM End Broadcom changed code. diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/7z.h linux-mips-2.6.8.1-bcm/fs/inflate_lzma/7z.h --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/7z.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/7z.h 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,16 @@ +#ifndef __7Z_H +#define __7Z_H + +#if defined __cplusplus +extern "C" +{ +#endif + +int decompress_lzma_7z(unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size); + +#if defined __cplusplus +} +#endif + +#endif + diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/7zlzma.c linux-mips-2.6.8.1-bcm/fs/inflate_lzma/7zlzma.c --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/7zlzma.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/7zlzma.c 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,57 @@ +#include "7z.h" + +#ifdef _HOST_TOOL +#include "stdio.h" +#endif + +#include "LZMADecoder.h" + + +static LzmaDecoder cc; +ISequentialInStream in_stream; +ISequentialOutStream out_stream; +int decompress_lzma_7z( unsigned char* in_data, + unsigned in_size, + unsigned char* out_data, + unsigned out_size) { +// LzmaDecoder cc; + int RC; + UINT64 in_size_l = in_size; + UINT64 out_size_l = out_size; + + + InStreamInit(in_data, in_size); + + OutStreamInit((char *)out_data, out_size); + + LzmaDecoderConstructor(&cc); + + if ((RC = LzmaDecoderReadCoderProperties(&cc)) != S_OK) + { + return RC; + } + + if (LzmaDecoderCode(&cc, &in_size_l, &out_size_l) != S_OK) + { + return -2; + } + + if (out_stream.size != out_size) + { + return -3; + } + + if ( out_stream.overflow ) + { + return -4; + } + + return 0; +} + +//BRCM modification +#ifdef __KERNEL__ +EXPORT_SYMBOL(decompress_lzma_7z); +#endif + + diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/AriBitCoder.h linux-mips-2.6.8.1-bcm/fs/inflate_lzma/AriBitCoder.h --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/AriBitCoder.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/AriBitCoder.h 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,51 @@ +#ifndef __COMPRESSION_BITCODER_H +#define __COMPRESSION_BITCODER_H + +#include "RangeCoder.h" + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) + +#define kNumMoveReducingBits 2 + + +typedef UINT32 CBitDecoder; + +INLINE void BitDecoderInit(CBitDecoder *bitDecoder) + { + *bitDecoder = kBitModelTotal / 2; + } + +#if 0 +UINT32 BitDecode(ISequentialInStream *in_stream, CBitDecoder *bitDecoder, CRangeDecoder *aRangeDecoder); +#else +INLINE UINT32 BitDecode(ISequentialInStream *in_stream, CBitDecoder *bitDecoder, CRangeDecoder *aRangeDecoder) + { + UINT32 aNewBound = (aRangeDecoder->m_Range >> kNumBitModelTotalBits) * (*bitDecoder); + if (aRangeDecoder->m_Code < aNewBound) + { + aRangeDecoder->m_Range = aNewBound; + *bitDecoder += (kBitModelTotal - *bitDecoder) >> kNumMoveBits; + if (aRangeDecoder->m_Range < kTopValue) + { + aRangeDecoder->m_Code = (aRangeDecoder->m_Code << 8) | InStreamReadByte(in_stream); + aRangeDecoder->m_Range <<= 8; + } + return 0; + } + else + { + aRangeDecoder->m_Range -= aNewBound; + aRangeDecoder->m_Code -= aNewBound; + *bitDecoder -= (*bitDecoder) >> kNumMoveBits; + if (aRangeDecoder->m_Range < kTopValue) + { + aRangeDecoder->m_Code = (aRangeDecoder->m_Code << 8) | InStreamReadByte(in_stream); + aRangeDecoder->m_Range <<= 8; + } + return 1; + } + } +#endif + +#endif diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/BitTreeCoder.h linux-mips-2.6.8.1-bcm/fs/inflate_lzma/BitTreeCoder.h --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/BitTreeCoder.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/BitTreeCoder.h 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,160 @@ +#ifndef __BITTREECODER_H +#define __BITTREECODER_H + +#include "AriBitCoder.h" +#include "RCDefs.h" + +//BRCM modification start +#ifdef _HOST_TOOL +#include "stdio.h" +#include "stdlib.h" +#include "malloc.h" +#endif + +#ifdef _CFE_ +#include "lib_malloc.h" +#include "lib_printf.h" +#define malloc(x) KMALLOC(x, 0) +#endif + +#ifdef __KERNEL__ +#include +#include +#include +#define printf printk +//#define malloc(x) kmalloc(x,GFP_KERNEL) +#define malloc(x) vmalloc(x) +#define free(x) vfree(x) +#endif +//BRCM modification end + +////////////////////////// +// CBitTreeDecoder + +typedef struct CBitTreeDecoder +{ + UINT32 m_NumBitLevels; + CBitDecoder *m_Models; +} CBitTreeDecoder; + +// ~CBitTreeDecoder() { free(m_Models); } +INLINE void BitTreeDecoderInit(CBitTreeDecoder *bitTreeDecoder, UINT32 aNumBitLevels) + { + int i; + bitTreeDecoder->m_NumBitLevels = aNumBitLevels; + bitTreeDecoder->m_Models = (CBitDecoder *)malloc( sizeof(CBitDecoder) * (1 << bitTreeDecoder->m_NumBitLevels)); + //BRCM modification + //printf("malloc in BitTreeDecoderInit=%d\n",sizeof(CBitDecoder) * (1 << bitTreeDecoder->m_NumBitLevels)); + if (!bitTreeDecoder->m_Models) { + printf("Error in allocating memory for bitTreeDecoder!\n"); + return; + } + for(i = 1; i < (1 << aNumBitLevels); i++) + BitDecoderInit(&bitTreeDecoder->m_Models[i]); + } +INLINE UINT32 BitTreeDecode(ISequentialInStream *in_stream, CBitTreeDecoder *bitTreeDecoder, CRangeDecoder *aRangeDecoder) + { + UINT32 aModelIndex = 1; + UINT32 aRange = aRangeDecoder->m_Range; + UINT32 aCode = aRangeDecoder->m_Code; + UINT32 aBitIndex; + for(aBitIndex = bitTreeDecoder->m_NumBitLevels; aBitIndex > 0; aBitIndex--) + { + RC_GETBIT(kNumMoveBits, bitTreeDecoder->m_Models[aModelIndex], aModelIndex) + } + aRangeDecoder->m_Range = aRange; + aRangeDecoder->m_Code = aCode; + return aModelIndex - (1 << bitTreeDecoder->m_NumBitLevels); + } + + +//////////////////////////////// +// CReverseBitTreeDecoder2 + +typedef struct CReverseBitTreeDecoder2 +{ + UINT32 m_NumBitLevels; + CBitDecoder *m_Models; +} CReverseBitTreeDecoder2; + +// CReverseBitTreeDecoder2(): m_Models(0) { } +// ~CReverseBitTreeDecoder2() { free(m_Models); } +INLINE BOOL ReverseBitTreeDecoder2Create(CReverseBitTreeDecoder2 *reverseBitTreeDecoder2, UINT32 aNumBitLevels) + { + reverseBitTreeDecoder2->m_NumBitLevels = aNumBitLevels; + reverseBitTreeDecoder2->m_Models = (CBitDecoder *)malloc( sizeof(CBitDecoder) * (1 << reverseBitTreeDecoder2->m_NumBitLevels)); + //printf("malloc in ReverseBitTreeDecoder2Create=%d\n",sizeof(CBitDecoder) * (1 << reverseBitTreeDecoder2->m_NumBitLevels)); + if (!reverseBitTreeDecoder2->m_Models) { + printf("Error in allocating memory for reverseBitTreeDecoder2!\n"); + return 0; + } + return (reverseBitTreeDecoder2->m_Models != 0); + } +INLINE void ReverseBitTreeDecoder2Init(CReverseBitTreeDecoder2 *reverseBitTreeDecoder2) + { + UINT32 aNumModels = 1 << reverseBitTreeDecoder2->m_NumBitLevels; + UINT32 i; + for(i = 1; i < aNumModels; i++) + BitDecoderInit(&reverseBitTreeDecoder2->m_Models[i]); + } +INLINE UINT32 ReverseBitTreeDecoder2Decode(ISequentialInStream *in_stream, CReverseBitTreeDecoder2 *reverseBitTreeDecoder2, CRangeDecoder *aRangeDecoder) + { + UINT32 aModelIndex = 1; + UINT32 aSymbol = 0; + UINT32 aRange = aRangeDecoder->m_Range; + UINT32 aCode = aRangeDecoder->m_Code; + UINT32 aBitIndex; + for(aBitIndex = 0; aBitIndex < reverseBitTreeDecoder2->m_NumBitLevels; aBitIndex++) + { + RC_GETBIT2(kNumMoveBits, reverseBitTreeDecoder2->m_Models[aModelIndex], aModelIndex, ; , aSymbol |= (1 << aBitIndex)) + } + aRangeDecoder->m_Range = aRange; + aRangeDecoder->m_Code = aCode; + return aSymbol; + } + + +//////////////////////////// +// CReverseBitTreeDecoder + +typedef struct CReverseBitTreeDecoder +{ + UINT32 m_NumBitLevels; + CBitDecoder *m_Models; +} CReverseBitTreeDecoder; + +// CReverseBitTreeDecoder(): m_Models(0) { } +// ~CReverseBitTreeDecoder() { free(m_Models); } +INLINE void ReverseBitTreeDecoderInit(CReverseBitTreeDecoder *reverseBitTreeDecoder, UINT32 aNumBitLevels) + { + int i; + reverseBitTreeDecoder->m_NumBitLevels = aNumBitLevels; + reverseBitTreeDecoder->m_Models = (CBitDecoder *)malloc( sizeof(CBitDecoder) * (1 << reverseBitTreeDecoder->m_NumBitLevels)); + //printf("malloc in ReverseBitTreeDecoderInit=%d\n",sizeof(CBitDecoder) * (1 << reverseBitTreeDecoder->m_NumBitLevels)); + if (!reverseBitTreeDecoder->m_Models) { + printf("Error in allocating memory for reverseBitTreeDecoder!\n"); + return; + } + for(i = 1; i < (1 << reverseBitTreeDecoder->m_NumBitLevels); i++) + BitDecoderInit(&reverseBitTreeDecoder->m_Models[i]); + } + +INLINE UINT32 ReverseBitTreeDecoderDecode(ISequentialInStream *in_stream, CReverseBitTreeDecoder *reverseBitTreeDecoder, CRangeDecoder *aRangeDecoder) + { + UINT32 aModelIndex = 1; + UINT32 aSymbol = 0; + UINT32 aRange = aRangeDecoder->m_Range; + UINT32 aCode = aRangeDecoder->m_Code; + UINT32 aBitIndex; + for(aBitIndex = 0; aBitIndex < reverseBitTreeDecoder->m_NumBitLevels; aBitIndex++) + { + RC_GETBIT2(kNumMoveBits, reverseBitTreeDecoder->m_Models[aModelIndex], aModelIndex, ; , aSymbol |= (1 << aBitIndex)) + } + aRangeDecoder->m_Range = aRange; + aRangeDecoder->m_Code = aCode; + return aSymbol; + } + + + +#endif diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/IInOutStreams.c linux-mips-2.6.8.1-bcm/fs/inflate_lzma/IInOutStreams.c --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/IInOutStreams.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/IInOutStreams.c 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,38 @@ +#include "IInOutStreams.h" +// BRCM modification +static void *lib_memcpy(void *dest,const void *src,size_t cnt); +static void *lib_memcpy(void *dest,const void *src,size_t cnt) +{ + unsigned char *d; + const unsigned char *s; + + d = (unsigned char *) dest; + s = (const unsigned char *) src; + + while (cnt) { + *d++ = *s++; + cnt--; + } + + return dest; +} + +HRESULT InStreamRead(void *aData, UINT32 aSize, UINT32* aProcessedSize) { + if (aSize > in_stream.remainingBytes) + aSize = in_stream.remainingBytes; + *aProcessedSize = aSize; + lib_memcpy(aData, in_stream.data, aSize); // brcm modification + in_stream.remainingBytes -= aSize; + in_stream.data += aSize; + return S_OK; + } + +#if 0 +BYTE InStreamReadByte() + { + if (in_stream.remainingBytes == 0) + return 0x0; + in_stream.remainingBytes--; + return (BYTE) *in_stream.data++; + } +#endif diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/IInOutStreams.h linux-mips-2.6.8.1-bcm/fs/inflate_lzma/IInOutStreams.h --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/IInOutStreams.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/IInOutStreams.h 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,62 @@ +#ifndef __IINOUTSTREAMS_H +#define __IINOUTSTREAMS_H + +#include "Portable.h" + +typedef struct ISequentialInStream +{ + unsigned char* data; + unsigned remainingBytes; +} ISequentialInStream; + +extern ISequentialInStream in_stream; + +INLINE void InStreamInit(unsigned char * Adata, unsigned Asize) + { + in_stream.data = Adata; + in_stream.remainingBytes = Asize; + } + +HRESULT InStreamRead(void *aData, UINT32 aSize, UINT32* aProcessedSize); + +#if 0 +BYTE InStreamReadByte(); +#else +INLINE BYTE InStreamReadByte(ISequentialInStream *in_stream) + { + if (in_stream->remainingBytes == 0) + return 0x0; + in_stream->remainingBytes--; + return (BYTE) *in_stream->data++; + } +#endif + + + +typedef struct ISequentialOutStream +{ + char* data; + unsigned size; + BOOL overflow; + unsigned total; +} ISequentialOutStream; + +extern ISequentialOutStream out_stream; + +#define OutStreamInit(Adata, Asize) \ +{ \ + out_stream.data = Adata; \ + out_stream.size = Asize; \ + out_stream.overflow = FALSE; \ + out_stream.total = 0; \ +} + +#define OutStreamSizeSet(newsize) \ + { \ + out_stream.total = newsize; \ + if (out_stream.total > out_stream.size) \ + out_stream.overflow = TRUE; \ + } + + +#endif diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/LenCoder.h linux-mips-2.6.8.1-bcm/fs/inflate_lzma/LenCoder.h --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/LenCoder.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/LenCoder.h 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,75 @@ +#ifndef __LENCODER_H +#define __LENCODER_H + +#include "BitTreeCoder.h" + + +#define kNumPosStatesBitsMax 4 +#define kNumPosStatesMax 16 + + +#define kNumPosStatesBitsEncodingMax 4 +#define kNumPosStatesEncodingMax 16 + + +//#define kNumMoveBits 5 + +#define kNumLenBits 3 +#define kNumLowSymbols (1 << kNumLenBits) + +#define kNumMidBits 3 +#define kNumMidSymbols (1 << kNumMidBits) + +#define kNumHighBits 8 + +#define kNumSymbolsTotal (kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits)) + +typedef struct LenDecoder +{ + CBitDecoder m_Choice; + CBitDecoder m_Choice2; + CBitTreeDecoder m_LowCoder[kNumPosStatesMax]; + CBitTreeDecoder m_MidCoder[kNumPosStatesMax]; + CBitTreeDecoder m_HighCoder; + UINT32 m_NumPosStates; +} LenDecoder; + +INLINE void LenDecoderCreate(LenDecoder *lenCoder, UINT32 aNumPosStates) + { + lenCoder->m_NumPosStates = aNumPosStates; + } + +INLINE void LenDecoderInit(LenDecoder *lenCoder) + { + UINT32 aPosState; + BitDecoderInit(&lenCoder->m_Choice); + for (aPosState = 0; aPosState < lenCoder->m_NumPosStates; aPosState++) + { + BitTreeDecoderInit(&lenCoder->m_LowCoder[aPosState],kNumLenBits); + BitTreeDecoderInit(&lenCoder->m_MidCoder[aPosState],kNumMidBits); + } + BitTreeDecoderInit(&lenCoder->m_HighCoder,kNumHighBits); + BitDecoderInit(&lenCoder->m_Choice2); + } + +INLINE UINT32 LenDecode(ISequentialInStream *in_stream, LenDecoder *lenCoder, CRangeDecoder *aRangeDecoder, UINT32 aPosState) + { + if(BitDecode(in_stream, &lenCoder->m_Choice, aRangeDecoder) == 0) + return BitTreeDecode(in_stream, &lenCoder->m_LowCoder[aPosState],aRangeDecoder); + else + { + UINT32 aSymbol = kNumLowSymbols; + if(BitDecode(in_stream, &lenCoder->m_Choice2, aRangeDecoder) == 0) + aSymbol += BitTreeDecode(in_stream, &lenCoder->m_MidCoder[aPosState],aRangeDecoder); + else + { + aSymbol += kNumMidSymbols; + aSymbol += BitTreeDecode(in_stream, &lenCoder->m_HighCoder,aRangeDecoder); + } + return aSymbol; + } + } + + + +#endif diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/LiteralCoder.h linux-mips-2.6.8.1-bcm/fs/inflate_lzma/LiteralCoder.h --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/LiteralCoder.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/LiteralCoder.h 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,146 @@ +#ifndef __LITERALCODER_H +#define __LITERALCODER_H + +#include "AriBitCoder.h" +#include "RCDefs.h" + +//BRCM modification start +#ifdef _HOST_TOOL +#include "stdio.h" +#include "malloc.h" +#endif + +#ifdef _CFE_ +#include "lib_malloc.h" +#include "lib_printf.h" +#define malloc(x) KMALLOC(x, 0) +#define free(x) KFREE(x) +#endif + +#ifdef __KERNEL__ +#include +#include +#define printf printk +//#define malloc(x) kmalloc(x,GFP_KERNEL) +#define malloc(x) vmalloc(x) +#define free(x) vfree(x) +#endif +//BRCM modification end + +//#define kNumMoveBits 5 + +typedef struct LitDecoder2 +{ + CBitDecoder m_Decoders[3][1 << 8]; +} LitDecoder2; + + +INLINE void LitDecoder2Init(LitDecoder2 *litDecoder2) + { + int i, j; + for (i = 0; i < 3; i++) + for (j = 1; j < (1 << 8); j++) + BitDecoderInit(&litDecoder2->m_Decoders[i][j]); + } + +INLINE BYTE LitDecoder2DecodeNormal(ISequentialInStream *in_stream, LitDecoder2 *litDecoder2, CRangeDecoder *aRangeDecoder) + { + UINT32 aSymbol = 1; + UINT32 aRange = aRangeDecoder->m_Range; + UINT32 aCode = aRangeDecoder->m_Code; + do + { + RC_GETBIT(kNumMoveBits, litDecoder2->m_Decoders[0][aSymbol], aSymbol) + } + while (aSymbol < 0x100); + aRangeDecoder->m_Range = aRange; + aRangeDecoder->m_Code = aCode; + return aSymbol; + } + +INLINE BYTE LitDecoder2DecodeWithMatchByte(ISequentialInStream *in_stream, LitDecoder2 *litDecoder2, CRangeDecoder *aRangeDecoder, BYTE aMatchByte) + { + UINT32 aSymbol = 1; + UINT32 aRange = aRangeDecoder->m_Range; + UINT32 aCode = aRangeDecoder->m_Code; + do + { + UINT32 aBit; + UINT32 aMatchBit = (aMatchByte >> 7) & 1; + aMatchByte <<= 1; + RC_GETBIT2(kNumMoveBits, litDecoder2->m_Decoders[1 + aMatchBit][aSymbol], aSymbol, + aBit = 0, aBit = 1) + if (aMatchBit != aBit) + { + while (aSymbol < 0x100) + { + RC_GETBIT(kNumMoveBits, litDecoder2->m_Decoders[0][aSymbol], aSymbol) + } + break; + } + } + while (aSymbol < 0x100); + aRangeDecoder->m_Range = aRange; + aRangeDecoder->m_Code = aCode; + return aSymbol; + } + + +typedef struct LitDecoder +{ + LitDecoder2 *m_Coders; + UINT32 m_NumPrevBits; + UINT32 m_NumPosBits; + UINT32 m_PosMask; +} LitDecoder; + + +// LitDecoder(): m_Coders(0) {} +// ~LitDecoder() { Free(); } + +/* +INLINE void LitDecoderFree(LitDecoder *litDecoder) + { + free( (char *) litDecoder->m_Coders ); + litDecoder->m_Coders = 0; + } +*/ + +INLINE void LitDecoderCreate(LitDecoder *litDecoder, UINT32 aNumPosBits, UINT32 aNumPrevBits) + { +// LitDecoderFree(litDecoder); + UINT32 aNumStates; + litDecoder->m_NumPosBits = aNumPosBits; + litDecoder->m_PosMask = (1 << aNumPosBits) - 1; + litDecoder->m_NumPrevBits = aNumPrevBits; + aNumStates = 1 << (aNumPrevBits + aNumPosBits); + litDecoder->m_Coders = (LitDecoder2*) malloc( sizeof( LitDecoder2 ) * aNumStates ); + //printf("malloc in LitDecoderCreate=%d\n",sizeof( LitDecoder2 ) * aNumStates); + if (litDecoder->m_Coders == 0) + printf( "Error allocating memory for LitDecoder m_Coders!\n" ); + } + +INLINE void LitDecoderInit(LitDecoder *litDecoder) + { + UINT32 i; + UINT32 aNumStates = 1 << (litDecoder->m_NumPrevBits + litDecoder->m_NumPosBits); + for (i = 0; i < aNumStates; i++) + LitDecoder2Init(&litDecoder->m_Coders[i]); + } + +INLINE UINT32 LitDecoderGetState(LitDecoder *litDecoder, UINT32 aPos, BYTE aPrevByte) + { + return ((aPos & litDecoder->m_PosMask) << litDecoder->m_NumPrevBits) + (aPrevByte >> (8 - litDecoder->m_NumPrevBits)); + } + +INLINE BYTE LitDecodeNormal(ISequentialInStream *in_stream, LitDecoder *litDecoder, CRangeDecoder *aRangeDecoder, UINT32 aPos, BYTE aPrevByte) + { + return LitDecoder2DecodeNormal(in_stream, &litDecoder->m_Coders[LitDecoderGetState(litDecoder, aPos, aPrevByte)], aRangeDecoder); + } + +INLINE BYTE LitDecodeWithMatchByte(ISequentialInStream *in_stream, LitDecoder *litDecoder, CRangeDecoder *aRangeDecoder, UINT32 aPos, BYTE aPrevByte, BYTE aMatchByte) + { + return LitDecoder2DecodeWithMatchByte(in_stream, &litDecoder->m_Coders[LitDecoderGetState(litDecoder, aPos, aPrevByte)], aRangeDecoder, aMatchByte); + } + +#endif diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/LZMADecoder.c linux-mips-2.6.8.1-bcm/fs/inflate_lzma/LZMADecoder.c --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/LZMADecoder.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/LZMADecoder.c 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,398 @@ +#include "Portable.h" +#ifdef _HOST_TOOL +#include "stdio.h" +#endif +#include "LZMADecoder.h" + + +//#define RETURN_E_OUTOFMEMORY_IF_FALSE(x) { if (!(x)) return E_OUTOFMEMORY; } + + +static UINT32 kDistStart[kDistTableSizeMax]; +struct WindowOut out_window; + +/* + * BRCM modification: free all the allocated buffer by malloc + * + */ +static void LzmaDecoderFreeBuffer(LzmaDecoder *lzmaDecoder) +{ + int i,aPosState; + + //printf("free lzmaDecoder->m_LiteralDecoder\n"); + free((&lzmaDecoder->m_LiteralDecoder)->m_Coders); + + for (i = 0; i < kNumLenToPosStates; i++) { + //printf("free lzmaDecoder->m_PosSlotDecoder\n"); + free((&lzmaDecoder->m_PosSlotDecoder[i])->m_Models); + } + // from LenDecoderInit(&lzmaDecoder->m_LenDecoder; + for (aPosState = 0; aPosState < (&lzmaDecoder->m_LenDecoder)->m_NumPosStates; aPosState++) { + //printf("free lzmaDecoder->m_PosSlotDecoder\n"); + free( (&(&lzmaDecoder->m_LenDecoder)->m_LowCoder[aPosState])->m_Models ); + //printf("free lzmaDecoder->m_PosSlotDecoder\n"); + free( (&(&lzmaDecoder->m_LenDecoder)->m_MidCoder[aPosState])->m_Models ); + } + //printf("free lzmaDecoder->m_PosSlotDecoder\n"); + free( (&(&lzmaDecoder->m_LenDecoder)->m_HighCoder)->m_Models ); + + + // from LenDecoderInit(&lzmaDecoder->m_RepMatchLenDecoder); + for (aPosState = 0; aPosState < (&lzmaDecoder->m_RepMatchLenDecoder)->m_NumPosStates; aPosState++) { + //printf("free lzmaDecoder->m_PosSlotDecoder\n"); + free( (&(&lzmaDecoder->m_RepMatchLenDecoder)->m_LowCoder[aPosState])->m_Models ); + //printf("free lzmaDecoder->m_PosSlotDecoder\n"); + free( (&(&lzmaDecoder->m_RepMatchLenDecoder)->m_MidCoder[aPosState])->m_Models ); + } + //printf("free lzmaDecoder->m_PosSlotDecoder\n"); + free( (&(&lzmaDecoder->m_RepMatchLenDecoder)->m_HighCoder)->m_Models ); + + + //printf("free lzmaDecoder->m_PosAlignDecoder\n"); + free((&lzmaDecoder->m_PosAlignDecoder)->m_Models); + + for(i = 0; i < kNumPosModels; i++) { + //printf("free lzmaDecoder->m_PosDecoders\n"); + free((&lzmaDecoder->m_PosDecoders[i])->m_Models); + } + +} + +HRESULT LzmaDecoderSetDictionarySize( + LzmaDecoder *lzmaDecoder, + UINT32 aDictionarySize) +{ + if (aDictionarySize > (1 << kDicLogSizeMax)) + return E_INVALIDARG; + +// UINT32 aWindowReservSize = MyMax(aDictionarySize, UINT32(1 << 21)); + + if (lzmaDecoder->m_DictionarySize != aDictionarySize) + { + lzmaDecoder->m_DictionarySize = aDictionarySize; + } + return S_OK; +} + +HRESULT LzmaDecoderSetLiteralProperties( + LzmaDecoder *lzmaDecoder, + UINT32 aLiteralPosStateBits, + UINT32 aLiteralContextBits) +{ + if (aLiteralPosStateBits > 8) + return E_INVALIDARG; + if (aLiteralContextBits > 8) + return E_INVALIDARG; + LitDecoderCreate(&lzmaDecoder->m_LiteralDecoder, aLiteralPosStateBits, aLiteralContextBits); + return S_OK; +} + +HRESULT LzmaDecoderSetPosBitsProperties( + LzmaDecoder *lzmaDecoder, + UINT32 aNumPosStateBits) +{ + UINT32 aNumPosStates; + if (aNumPosStateBits > (UINT32) kNumPosStatesBitsMax) + return E_INVALIDARG; + aNumPosStates = 1 << aNumPosStateBits; + LenDecoderCreate(&lzmaDecoder->m_LenDecoder, aNumPosStates); + LenDecoderCreate(&lzmaDecoder->m_RepMatchLenDecoder, aNumPosStates); + lzmaDecoder->m_PosStateMask = aNumPosStates - 1; + return S_OK; +} + + +void LzmaDecoderConstructor(LzmaDecoder *lzmaDecoder) +{ + lzmaDecoder->m_DictionarySize = ((UINT32)-1); + LzmaDecoderCreate(lzmaDecoder); +} + +HRESULT LzmaDecoderCreate(LzmaDecoder *lzmaDecoder) +{ + int i; + for(i = 0; i < kNumPosModels; i++) + { + if (!(ReverseBitTreeDecoder2Create(&lzmaDecoder->m_PosDecoders[i],kDistDirectBits[kStartPosModelIndex + i]))) + return E_OUTOFMEMORY;; + } + return S_OK; +} + + +HRESULT LzmaDecoderInit(LzmaDecoder *lzmaDecoder) +{ + int i; + UINT32 j; + + RangeDecoderInit(&in_stream, &lzmaDecoder->m_RangeDecoder); + + OutWindowInit(); + + for(i = 0; i < kNumStates; i++) + { + for (j = 0; j <= lzmaDecoder->m_PosStateMask; j++) + { + BitDecoderInit(&lzmaDecoder->m_MainChoiceDecoders[i][j]); + BitDecoderInit(&lzmaDecoder->m_MatchRepShortChoiceDecoders[i][j]); + } + BitDecoderInit(&lzmaDecoder->m_MatchChoiceDecoders[i]); + BitDecoderInit(&lzmaDecoder->m_MatchRepChoiceDecoders[i]); + BitDecoderInit(&lzmaDecoder->m_MatchRep1ChoiceDecoders[i]); + BitDecoderInit(&lzmaDecoder->m_MatchRep2ChoiceDecoders[i]); + } + + LitDecoderInit(&lzmaDecoder->m_LiteralDecoder); + + for (i = 0; i < (int) kNumLenToPosStates; i++) + BitTreeDecoderInit(&lzmaDecoder->m_PosSlotDecoder[i],kNumPosSlotBits); + + for(i = 0; i < kNumPosModels; i++) + ReverseBitTreeDecoder2Init(&lzmaDecoder->m_PosDecoders[i]); + + LenDecoderInit(&lzmaDecoder->m_LenDecoder); + LenDecoderInit(&lzmaDecoder->m_RepMatchLenDecoder); + + ReverseBitTreeDecoderInit(&lzmaDecoder->m_PosAlignDecoder, kNumAlignBits); + return S_OK; + +} + +HRESULT LzmaDecoderCodeReal( + LzmaDecoder *lzmaDecoder, + UINT64 *anInSize, + UINT64 *anOutSize) +{ + BOOL aPeviousIsMatch = FALSE; + BYTE aPreviousByte = 0; + UINT32 aRepDistances[kNumRepDistances]; + int i; + UINT64 aNowPos64 = 0; + UINT64 aSize = *anOutSize; + ISequentialInStream my_in_stream; +// WindowOut out_window; + CState aState; + + CStateInit(&aState); + + if (anOutSize == NULL) + { + printf("CodeReal: invalid argument %x\n", (UINT32) anOutSize ); + return E_INVALIDARG; + } + + + LzmaDecoderInit(lzmaDecoder); + + my_in_stream.data = in_stream.data; + my_in_stream.remainingBytes = in_stream.remainingBytes; + + for(i = 0 ; i < (int) kNumRepDistances; i++) + aRepDistances[i] = 0; + + //while(aNowPos64 < aSize) + while(my_in_stream.remainingBytes > 0) + { + UINT64 aNext = MyMin(aNowPos64 + (1 << 18), aSize); + while(aNowPos64 < aNext) + { + UINT32 aPosState = (UINT32)(aNowPos64) & lzmaDecoder->m_PosStateMask; + if (BitDecode(&my_in_stream, + &lzmaDecoder->m_MainChoiceDecoders[aState][aPosState], + &lzmaDecoder->m_RangeDecoder) == (UINT32) kMainChoiceLiteralIndex) + { + CStateUpdateChar(&aState); + if(aPeviousIsMatch) + { + BYTE aMatchByte = OutWindowGetOneByte(0 - aRepDistances[0] - 1); + aPreviousByte = LitDecodeWithMatchByte(&my_in_stream, + &lzmaDecoder->m_LiteralDecoder, + &lzmaDecoder->m_RangeDecoder, + (UINT32)(aNowPos64), + aPreviousByte, + aMatchByte); + aPeviousIsMatch = FALSE; + } + else + aPreviousByte = LitDecodeNormal(&my_in_stream, + &lzmaDecoder->m_LiteralDecoder, + &lzmaDecoder->m_RangeDecoder, + (UINT32)(aNowPos64), + aPreviousByte); + OutWindowPutOneByte(aPreviousByte); + aNowPos64++; + } + else + { + UINT32 aDistance, aLen; + aPeviousIsMatch = TRUE; + if(BitDecode(&my_in_stream, + &lzmaDecoder->m_MatchChoiceDecoders[aState], + &lzmaDecoder->m_RangeDecoder) == (UINT32) kMatchChoiceRepetitionIndex) + { + if(BitDecode(&my_in_stream, + &lzmaDecoder->m_MatchRepChoiceDecoders[aState], + &lzmaDecoder->m_RangeDecoder) == 0) + { + if(BitDecode(&my_in_stream, + &lzmaDecoder->m_MatchRepShortChoiceDecoders[aState][aPosState], + &lzmaDecoder->m_RangeDecoder) == 0) + { + CStateUpdateShortRep(&aState); + aPreviousByte = OutWindowGetOneByte(0 - aRepDistances[0] - 1); + OutWindowPutOneByte(aPreviousByte); + aNowPos64++; + continue; + } + aDistance = aRepDistances[0]; + } + else + { + if(BitDecode(&my_in_stream, + &lzmaDecoder->m_MatchRep1ChoiceDecoders[aState], + &lzmaDecoder->m_RangeDecoder) == 0) + { + aDistance = aRepDistances[1]; + aRepDistances[1] = aRepDistances[0]; + } + else + { + if (BitDecode(&my_in_stream, + &lzmaDecoder->m_MatchRep2ChoiceDecoders[aState], + &lzmaDecoder->m_RangeDecoder) == 0) + { + aDistance = aRepDistances[2]; + } + else + { + aDistance = aRepDistances[3]; + aRepDistances[3] = aRepDistances[2]; + } + aRepDistances[2] = aRepDistances[1]; + aRepDistances[1] = aRepDistances[0]; + } + aRepDistances[0] = aDistance; + } + aLen = LenDecode(&my_in_stream, + &lzmaDecoder->m_RepMatchLenDecoder, + &lzmaDecoder->m_RangeDecoder, + aPosState) + kMatchMinLen; + CStateUpdateRep(&aState); + } + else + { + UINT32 aPosSlot; + aLen = kMatchMinLen + LenDecode(&my_in_stream, + &lzmaDecoder->m_LenDecoder, + &lzmaDecoder->m_RangeDecoder, + aPosState); + CStateUpdateMatch(&aState); + aPosSlot = BitTreeDecode(&my_in_stream, + &lzmaDecoder->m_PosSlotDecoder[GetLenToPosState(aLen)], + &lzmaDecoder->m_RangeDecoder); + if (aPosSlot >= (UINT32) kStartPosModelIndex) + { + aDistance = kDistStart[aPosSlot]; + if (aPosSlot < (UINT32) kEndPosModelIndex) + aDistance += ReverseBitTreeDecoder2Decode(&my_in_stream, + &lzmaDecoder->m_PosDecoders[aPosSlot - kStartPosModelIndex], + &lzmaDecoder->m_RangeDecoder); + else + { + aDistance += (RangeDecodeDirectBits(&my_in_stream, + &lzmaDecoder->m_RangeDecoder, + kDistDirectBits[aPosSlot] - kNumAlignBits) << kNumAlignBits); + aDistance += ReverseBitTreeDecoderDecode(&my_in_stream, + &lzmaDecoder->m_PosAlignDecoder, + &lzmaDecoder->m_RangeDecoder); + } + } + else + aDistance = aPosSlot; + + + aRepDistances[3] = aRepDistances[2]; + aRepDistances[2] = aRepDistances[1]; + aRepDistances[1] = aRepDistances[0]; + + aRepDistances[0] = aDistance; + } + if (aDistance >= aNowPos64) + { + printf("CodeReal: invalid data\n" ); + return E_INVALIDDATA; + } + OutWindowCopyBackBlock(aDistance, aLen); + aNowPos64 += aLen; + aPreviousByte = OutWindowGetOneByte(0 - 1); + } + } + } + + //BRCM modification + LzmaDecoderFreeBuffer(lzmaDecoder); + + OutWindowFlush(); + return S_OK; +} + +HRESULT LzmaDecoderCode( + LzmaDecoder *lzmaDecoder, + UINT64 *anInSize, + UINT64 *anOutSize) +{ + + UINT32 aStartValue = 0; + int i; + + for (i = 0; i < kDistTableSizeMax; i++) + { + kDistStart[i] = aStartValue; + aStartValue += (1 << kDistDirectBits[i]); + } + return LzmaDecoderCodeReal( + lzmaDecoder, + anInSize, + anOutSize); +} + +HRESULT LzmaDecoderReadCoderProperties(LzmaDecoder *lzmaDecoder) +{ + UINT32 aNumPosStateBits; + UINT32 aLiteralPosStateBits; + UINT32 aLiteralContextBits; + UINT32 aDictionarySize; + BYTE aRemainder; + UINT32 aProcessesedSize; + + BYTE aByte; + RETURN_IF_NOT_S_OK(InStreamRead(&aByte, + sizeof(aByte), + &aProcessesedSize)); + + if (aProcessesedSize != sizeof(aByte)) + return E_INVALIDARG; + + aLiteralContextBits = aByte % 9; + aRemainder = aByte / 9; + aLiteralPosStateBits = aRemainder % 5; + aNumPosStateBits = aRemainder / 5; + + RETURN_IF_NOT_S_OK(InStreamRead(&aDictionarySize, + sizeof(aDictionarySize), + &aProcessesedSize)); + + if (aProcessesedSize != sizeof(aDictionarySize)) + return E_INVALIDARG; + + RETURN_IF_NOT_S_OK( LzmaDecoderSetDictionarySize(lzmaDecoder, + aDictionarySize) ); + RETURN_IF_NOT_S_OK( LzmaDecoderSetLiteralProperties(lzmaDecoder, + aLiteralPosStateBits, + aLiteralContextBits) ); + RETURN_IF_NOT_S_OK( LzmaDecoderSetPosBitsProperties(lzmaDecoder, + aNumPosStateBits) ); + + return S_OK; +} + diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/LZMADecoder.h linux-mips-2.6.8.1-bcm/fs/inflate_lzma/LZMADecoder.h --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/LZMADecoder.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/LZMADecoder.h 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,60 @@ +#ifndef __LZARITHMETIC_DECODER_H +#define __LZARITHMETIC_DECODER_H + +#include "WindowOut.h" +#include "LZMA.h" +#include "LenCoder.h" +#include "LiteralCoder.h" + + +typedef struct LzmaDecoder +{ + CRangeDecoder m_RangeDecoder; + + CBitDecoder m_MainChoiceDecoders[kNumStates][kNumPosStatesMax]; + CBitDecoder m_MatchChoiceDecoders[kNumStates]; + CBitDecoder m_MatchRepChoiceDecoders[kNumStates]; + CBitDecoder m_MatchRep1ChoiceDecoders[kNumStates]; + CBitDecoder m_MatchRep2ChoiceDecoders[kNumStates]; + CBitDecoder m_MatchRepShortChoiceDecoders[kNumStates][kNumPosStatesMax]; + + CBitTreeDecoder m_PosSlotDecoder[kNumLenToPosStates]; + + CReverseBitTreeDecoder2 m_PosDecoders[kNumPosModels]; + CReverseBitTreeDecoder m_PosAlignDecoder; + + LenDecoder m_LenDecoder; + LenDecoder m_RepMatchLenDecoder; + + LitDecoder m_LiteralDecoder; + + UINT32 m_DictionarySize; + + UINT32 m_PosStateMask; +} LzmaDecoder; + + HRESULT LzmaDecoderCreate(LzmaDecoder *lzmaDecoder); + + HRESULT LzmaDecoderInit(LzmaDecoder *lzmaDecoder); + +//static inline HRESULT LzmaDecoderFlush() { return OutWindowFlush(); } + + HRESULT LzmaDecoderCodeReal( + LzmaDecoder *lzmaDecoder, +// ISequentialInStream *in_stream, + UINT64 *anInSize, +// WindowOut *out_window, + UINT64 *anOutSize); + + + void LzmaDecoderConstructor( LzmaDecoder *lzmaDecoder ); + + HRESULT LzmaDecoderCode( LzmaDecoder *lzmaDecoder, UINT64 *anInSize, UINT64 *anOutSize); + HRESULT LzmaDecoderReadCoderProperties(LzmaDecoder *lzmaDecoder ); + + HRESULT LzmaDecoderSetDictionarySize(LzmaDecoder *lzmaDecoder, UINT32 aDictionarySize); + HRESULT LzmaDecoderSetLiteralProperties(LzmaDecoder *lzmaDecoder, UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits); + HRESULT LzmaDecoderSetPosBitsProperties(LzmaDecoder *lzmaDecoder, UINT32 aNumPosStateBits); + + +#endif diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/LZMA.h linux-mips-2.6.8.1-bcm/fs/inflate_lzma/LZMA.h --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/LZMA.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/LZMA.h 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,83 @@ +#include "LenCoder.h" + +#ifndef __LZMA_H +#define __LZMA_H + + +#define kNumRepDistances 4 + +#define kNumStates 12 + +static const BYTE kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; +static const BYTE kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; +static const BYTE kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; +static const BYTE kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + +typedef BYTE CState; + +INLINE void CStateInit(CState *m_Index) + { *m_Index = 0; } +INLINE void CStateUpdateChar(CState *m_Index) + { *m_Index = kLiteralNextStates[*m_Index]; } +INLINE void CStateUpdateMatch(CState *m_Index) + { *m_Index = kMatchNextStates[*m_Index]; } +INLINE void CStateUpdateRep(CState *m_Index) + { *m_Index = kRepNextStates[*m_Index]; } +INLINE void CStateUpdateShortRep(CState *m_Index) + { *m_Index = kShortRepNextStates[*m_Index]; } + + +#define kNumPosSlotBits 6 +#define kDicLogSizeMax 28 +#define kDistTableSizeMax 56 + +//extern UINT32 kDistStart[kDistTableSizeMax]; +static const BYTE kDistDirectBits[kDistTableSizeMax] = +{ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, + 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, + 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26 +}; + +#define kNumLenToPosStates 4 +INLINE UINT32 GetLenToPosState(UINT32 aLen) +{ + aLen -= 2; + if (aLen < kNumLenToPosStates) + return aLen; + return kNumLenToPosStates - 1; +} + +#define kMatchMinLen 2 + +#define kMatchMaxLen (kMatchMinLen + kNumSymbolsTotal - 1) + +#define kNumAlignBits 4 +#define kAlignTableSize 16 +#define kAlignMask 15 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumPosModels 10 + +#define kNumFullDistances (1 << (kEndPosModelIndex / 2)) + + +#define kMainChoiceLiteralIndex 0 +#define kMainChoiceMatchIndex 1 + +#define kMatchChoiceDistanceIndex0 +#define kMatchChoiceRepetitionIndex 1 + +#define kNumMoveBitsForMainChoice 5 +#define kNumMoveBitsForPosCoders 5 + +#define kNumMoveBitsForAlignCoders 5 + +#define kNumMoveBitsForPosSlotCoder 5 + +#define kNumLitPosStatesBitsEncodingMax 4 +#define kNumLitContextBitsMax 8 + + +#endif diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/Makefile linux-mips-2.6.8.1-bcm/fs/inflate_lzma/Makefile --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/Makefile 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,6 @@ + +BSPOBJS += \ + 7zlzma.o \ + LZMADecoder.o \ + IInOutStreams.o \ + diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/Portable.h linux-mips-2.6.8.1-bcm/fs/inflate_lzma/Portable.h --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/Portable.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/Portable.h 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,59 @@ +#ifndef __PORTABLE_H +#define __PORTABLE_H + +//BRCM modification +#ifdef _HOST_TOOL +#include +#endif + +#ifdef _CFE_ +#include +#endif + +#ifdef __KERNEL__ +#include +#endif + +//bcm +//#ifdef __GNUC__ +//#include +//#define INLINE static inline +//#else +typedef char INT8; +typedef unsigned char UINT8; +typedef short INT16; +typedef unsigned short UINT16; +typedef int INT32; +typedef unsigned int UINT32; +typedef int BOOL; +#define INLINE static inline +//#define INLINE static __inline__ +//#endif +typedef long long INT64; // %%%% Changed from "long long" +typedef unsigned long long UINT64; // %%%% Changed from "long long" + +typedef UINT8 BYTE; +typedef UINT16 WORD; +typedef UINT32 DWORD; + +typedef unsigned UINT_PTR; +#define FALSE 0 +#define TRUE 1 + +#define HRESULT int +#define S_OK 0 +#define E_INVALIDARG -1 +#define E_OUTOFMEMORY -2 +#define E_FAIL -3 +#define E_INTERNAL_ERROR -4 +#define E_INVALIDDATA -5 + +#define MyMin( a, b ) ( a < b ? a : b ) + +#define MyMax( a, b ) ( a > b ? a : b ) + +#define kNumMoveBits 5 + +#define RETURN_IF_NOT_S_OK(x) { HRESULT __aResult_ = (x); if(__aResult_ != S_OK) return __aResult_; } + +#endif diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/RangeCoder.h linux-mips-2.6.8.1-bcm/fs/inflate_lzma/RangeCoder.h --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/RangeCoder.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/RangeCoder.h 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,56 @@ +#ifndef __COMPRESSION_RANGECODER_H +#define __COMPRESSION_RANGECODER_H + +#include "IInOutStreams.h" + +#define kNumTopBits 24 +#define kTopValue (1 << kNumTopBits) + +typedef struct CRangeDecoder +{ + UINT32 m_Range; + UINT32 m_Code; +} CRangeDecoder; + + + +INLINE void RangeDecoderInit( + ISequentialInStream *in_stream, + CRangeDecoder *rangeDecoder) + { + int i; + rangeDecoder->m_Code = 0; + rangeDecoder->m_Range = (UINT32)(-1); + for(i = 0; i < 5; i++) + rangeDecoder->m_Code = (rangeDecoder->m_Code << 8) | InStreamReadByte(in_stream); + } + +INLINE UINT32 RangeDecodeDirectBits( + ISequentialInStream *in_stream, + CRangeDecoder *rangeDecoder, + UINT32 aNumTotalBits) + { + UINT32 aRange = rangeDecoder->m_Range; + UINT32 aCode = rangeDecoder->m_Code; + UINT32 aResult = 0; + UINT32 i; + for (i = aNumTotalBits; i > 0; i--) + { + UINT32 t; + aRange >>= 1; + t = (aCode - aRange) >> 31; + aCode -= aRange & (t - 1); + aResult = (aResult << 1) | (1 - t); + + if (aRange < kTopValue) + { + aCode = (aCode << 8) | InStreamReadByte(in_stream); + aRange <<= 8; + } + } + rangeDecoder->m_Range = aRange; + rangeDecoder->m_Code = aCode; + return aResult; + } + +#endif diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/RCDefs.h linux-mips-2.6.8.1-bcm/fs/inflate_lzma/RCDefs.h --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/RCDefs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/RCDefs.h 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,43 @@ +#ifndef __RCDEFS_H +#define __RCDEFS_H + +#include "AriBitCoder.h" + +/* +#define RC_INIT_VAR \ + UINT32 aRange = aRangeDecoder->m_Range; \ + UINT32 aCode = aRangeDecoder->m_Code; + +#define RC_FLUSH_VAR \ + aRangeDecoder->m_Range = aRange; \ + aRangeDecoder->m_Code = aCode; +*/ + + +#if 1 +#define RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, Action0, Action1) \ + {UINT32 aNewBound = (aRange >> kNumBitModelTotalBits) * aProb; \ + if (aCode < aNewBound) \ + { \ + Action0; \ + aRange = aNewBound; \ + aProb += (kBitModelTotal - aProb) >> aNumMoveBits; \ + aModelIndex <<= 1; \ + } \ + else \ + { \ + Action1; \ + aRange -= aNewBound; \ + aCode -= aNewBound; \ + aProb -= (aProb) >> aNumMoveBits; \ + aModelIndex = (aModelIndex << 1) + 1; \ + }} \ + if (aRange < kTopValue) \ + { \ + aCode = (aCode << 8) | InStreamReadByte(in_stream); \ + aRange <<= 8; } + +#define RC_GETBIT(aNumMoveBits, aProb, aModelIndex) RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, ; , ;) +#endif + +#endif diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/vxTypesOld.h linux-mips-2.6.8.1-bcm/fs/inflate_lzma/vxTypesOld.h --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/vxTypesOld.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/vxTypesOld.h 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,289 @@ +/* vxTypesOld.h - old VxWorks type definition header */ + +/* Copyright 1984-1997 Wind River Systems, Inc. */ + +/* +modification history +-------------------- +02c,15aug97,cym added simnt support. +02d,26mar97,cdp added Thumb (ARM7TDMI_T) support. +02c,28nov96,cdp added ARM support. +02b,28sep95,ms removed "static __inline__" (SPR #4500) +02b,12jul95,ism added simsolaris support +02a,19mar95,dvs removed tron references. +01z,01sep94,ism fixed comment as per SPR# 1512. +01y,02dec93,pme added Am29K family support. +01x,12jun93,rrr vxsim. +02a,26may94,yao added PPC support. +01w,09jun93,hdn added support for I80X86 +01v,12feb93,srh added C++ versions of FUNCPTR, et al. +01u,13nov92,dnw added definition of VOID (SPR #1781) +01t,02oct92,srh replaced conditional around volatile, const, and signed so + they won't be elided when __STDC__ is defined. + added __cplusplus to __STDC__ condition. +01s,22sep92,rrr added support for c++ +01r,08sep92,smb made some additions for the MIPS. +01q,07sep92,smb added __STDC__ and modes to maintain compatibility with 5.0 +01p,07jul92,rrr moved STACK_GROW and ENDIAN to vxArch.h +01o,03jul92,smb changed name from vxTypes.h. +01n,26may92,rrr the tree shuffle +01m,25nov91,llk included sys/types.h. +01l,04oct91,rrr passed through the ansification filter + -fixed #else and #endif + -removed TINY and UTINY + -changed VOID to void + -changed ASMLANGUAGE to _ASMLANGUAGE + -changed copyright notice +01k,01oct91,jpb fixed MIPS conditional for undefined CPU_FAMILY. +01j,20sep91,wmd conditionalized out defines for const, unsigned and volatile + for the MIPS architecture. +01i,02aug91,ajm added support for MIPS_R3k. +01h,15may91,gae added define for "signed" when not available for pre-ANSI. +01g,29apr91,hdn added defines and macros for TRON architecture. +01f,28apr91,del added defines of __volatile__ and __const__ if !_STDC_ + && _GNUC__ +01f,24mar91,del added INSTR * define for I960. +01e,28jan91,kdl added DBLFUNCPTR and FLTFUNCPTR. +01d,25oct90,dnw changed void to void except when linting. +01c,05oct90,shl added copyright notice. + made #endif ANSI style. +01b,10aug90,dnw added VOIDFUNCPTR +01a,29may90,del written. +*/ + +/* +DESCRIPTION +This header file contains a mixture of stuff. +1) the old style typedefs (ie. POSIX now says they must end with _t). + These will be phased out gradually. +2) a mechanism for getting rid of const warning which are produced by the + GNU C compiler. Hopefully, this will be removed in the future. +3) macros that are so longer needed for vxWorks source code but maybe needed + by some customer applications and are therefore provided for backward + compatability. +4) system III typedefs (used by netinet) which do not fit in anywhere else. + +*/ + +#ifndef __INCvxTypesOldh +#define __INCvxTypesOldh + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sys/types.h" + +/* vxWorks types */ + +typedef char INT8; +typedef short INT16; +typedef int INT32; + +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef unsigned int UINT32; + +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned int UINT; +typedef unsigned long ULONG; + +typedef int BOOL; +typedef int STATUS; +typedef int ARGINT; + +typedef void VOID; + +#ifdef __cplusplus +typedef int (*FUNCPTR) (...); /* ptr to function returning int */ +typedef void (*VOIDFUNCPTR) (...); /* ptr to function returning void */ +typedef double (*DBLFUNCPTR) (...); /* ptr to function returning double*/ +typedef float (*FLTFUNCPTR) (...); /* ptr to function returning float */ +#else +typedef int (*FUNCPTR) (); /* ptr to function returning int */ +typedef void (*VOIDFUNCPTR) (); /* ptr to function returning void */ +typedef double (*DBLFUNCPTR) (); /* ptr to function returning double*/ +typedef float (*FLTFUNCPTR) (); /* ptr to function returning float */ +#endif /* _cplusplus */ + + +/* This structure and the following definitions are needed to get rid + of const warning produced by the GNU C compiler. + */ + +#if defined(__STDC__) || defined(__cplusplus) +typedef union + { + long pm_int; + void *pm_v; + const void *pm_cv; + char *pm_c; + unsigned char *pm_uc; + + signed char *pm_sc; + const char *pm_cc; + const unsigned char *pm_cuc; + const signed char *pm_csc; + short *pm_s; + ushort_t *pm_us; + const short *pm_cs; + const ushort_t *pm_cus; + int *pm_i; + uint_t *pm_ui; + const int *pm_ci; + const uint_t *pm_cui; + long *pm_l; + ulong_t *pm_ul; + const long *pm_cl; + const ulong_t *pm_cul; + + int8_t *pm_i8; + uint8_t *pm_ui8; + const int8_t *pm_ci8; + const uint8_t *pm_cui8; + int16_t *pm_i16; + uint16_t *pm_ui16; + const int16_t *pm_ci16; + const uint16_t *pm_cui16; + int32_t *pm_i32; + uint32_t *pm_ui32; + const int32_t *pm_ci32; + const uint32_t *pm_cui32; +#if _ARCH_MOVE_SIZE > 4 + int64_t *pm_i64; + const int64_t *pm_ci64; +#if _ARCH_MOVE_SIZE > 8 + int128_t *pm_i128; + const int128_t *pm_ci128; +#endif +#endif + } pointer_mix_t; + +#define CHAR_FROM_CONST(x) (char *)(x) +#define VOID_FROM_CONST(x) (void *)(x) + +#endif /* __STDC__ */ + +#define STACK_DIR _ARCH_STACK_DIR +#define ALIGN_MEMORY _ARCH_ALIGN_MEMORY +#define ALIGN_STACK _ARCH_ALIGN_STACK +#define ALIGN_REGS _ARCH_ALIGN_REGS + +#define NBBY 8 /* number of bits in a byte */ + +/* modes - must match O_RDONLY/O_WRONLY/O_RDWR in ioLib.h! */ + +#define READ 0 +#define WRITE 1 +#define UPDATE 2 + +/* Select uses bit masks of file descriptors in longs. + * These macros manipulate such bit fields (the filesystem macros use chars). + * FD_SETSIZE may be defined by the user, but the default here + * should be >= maxFiles parameter in iosInit call found in usrConfig.c. + * If this define is changed, recompile the source, or else select() will + * not work. + */ + +#ifndef FD_SETSIZE +#define FD_SETSIZE 256 +#endif /* FD_SETSIZE */ + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ +#ifndef howmany +#define howmany(x, y) ((unsigned int)(((x)+((y)-1)))/(unsigned int)(y)) +#endif /* howmany */ + +typedef struct fd_set + { + fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)]; + } fd_set; + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) + + +/* system III typedefs (used by netinet) */ + +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; +typedef unsigned short ushort; + + +/* historical definitions - now obsolete */ + +typedef char TBOOL; /* obsolete */ + + +/* architecture dependent typedefs */ + +#ifdef CPU_FAMILY + +#if CPU_FAMILY==MC680X0 +typedef unsigned short INSTR; /* word-aligned instructions */ +#endif /* CPU_FAMILY==MC680X0 */ + +#if CPU_FAMILY==SPARC || CPU_FAMILY==MIPS || CPU_FAMILY==SIMSPARCSUNOS || CPU_FAMILY==SIMHPPA || CPU_FAMILY==SIMSPARCSOLARIS +typedef unsigned long INSTR; /* 32 bit word-aligned instructions */ +#endif /* CPU_FAMILY==SPARC || CPU_FAMILY==MIPS || CPU_FAMILY==SIMSPARCSUNOS || CPU_FAMILY==SIMHPPA || CPU_FAMILY==SIMSPARCSOLARIS */ + +#if CPU_FAMILY==I960 +typedef unsigned long INSTR; /* 32 bit word-aligned instructions */ +#endif /* CPU_FAMILY==I960 */ + +#if CPU_FAMILY==I80X86 || CPU_FAMILY==SIMNT +typedef unsigned char INSTR; /* char instructions */ +#endif /* CPU_FAMILY==I80X86 || CPU_FAMILY==SIMNT */ + +#if CPU_FAMILY==AM29XXX +typedef unsigned long INSTR; /* 32 bit word-aligned instructions */ +#endif /* CPU_FAMILY==AM29XXX */ + +#if (CPU_FAMILY==PPC) +typedef unsigned long INSTR; /* 32 bit word-aligned instructions */ +#endif /* (CPU_FAMILY==PPC) */ + +#if CPU_FAMILY==ARM +#if CPU==ARM7TDMI_T +typedef unsigned short INSTR; /* 16 bit instructions */ +#else +typedef unsigned long INSTR; /* 32 bit word-aligned instructions */ +#endif +#endif /* CPU_FAMILY==ARM */ + +#endif /* CPU_FAMILY */ + +/* ANSI type qualifiers */ + +#if !defined(__STDC__) && !defined(__cplusplus) + +#ifdef __GNUC__ +#define volatile __volatile__ +#define const __const__ +#define signed __signed__ +#else +#if !(defined(CPU_FAMILY) && CPU_FAMILY==MIPS) +#define volatile +#define const +#define signed +#endif /* !(defined(CPU_FAMILY) && CPU_FAMILY==MIPS) */ +#endif /* __GNUC__ */ + +#endif /* !defined(__STDC__) && !defined(__cplusplus) */ + +#if CPU_FAMILY==MIPS +#define CHAR_FROM_CONST(x) (char *)(x) +#define VOID_FROM_CONST(x) (void *)(x) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __INCvxTypesOldh */ diff -Naur linux-mips-2.6.8.1-orig/fs/inflate_lzma/WindowOut.h linux-mips-2.6.8.1-bcm/fs/inflate_lzma/WindowOut.h --- linux-mips-2.6.8.1-orig/fs/inflate_lzma/WindowOut.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/inflate_lzma/WindowOut.h 2006-12-20 18:46:30.000000000 +0100 @@ -0,0 +1,47 @@ +#ifndef __STREAM_WINDOWOUT_H +#define __STREAM_WINDOWOUT_H + +#include "IInOutStreams.h" + +typedef struct WindowOut +{ + BYTE *Buffer; + UINT32 Pos; +} WindowOut; + +extern WindowOut out_window; + +#define OutWindowInit() \ + { \ + out_window.Buffer = (BYTE *) out_stream.data; \ + out_window.Pos = 0; \ + } + +#define OutWindowFlush() \ + { \ + OutStreamSizeSet( out_window.Pos ); \ + } + +// BRCM modification +INLINE void OutWindowCopyBackBlock(UINT32 aDistance, UINT32 aLen) + { + BYTE *p = out_window.Buffer + out_window.Pos; + UINT32 i; + aDistance++; + for(i = 0; i < aLen; i++) + p[i] = p[i - aDistance]; + out_window.Pos += aLen; + } + + +#define OutWindowPutOneByte(aByte) \ + { \ + out_window.Buffer[out_window.Pos++] = aByte; \ + } + +#define OutWindowGetOneByte(anIndex) \ + (out_window.Buffer[out_window.Pos + anIndex]) + + + +#endif diff -Naur linux-mips-2.6.8.1-orig/fs/Kconfig linux-mips-2.6.8.1-bcm/fs/Kconfig --- linux-mips-2.6.8.1-orig/fs/Kconfig 2004-08-13 09:18:55.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/fs/Kconfig 2006-12-20 18:46:52.000000000 +0100 @@ -1212,9 +1212,36 @@ endchoice +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +config SQUASHFS + tristate "SquashFS 2.0 - Squashed file system support" +# select ZLIB_INFLATE + help + Saying Y here includes support for SquashFs 2.0 (Compressed Read-Only File + System). Squashfs is a highly compressed read-only filesystem for Linux. + It uses zlib compression to compress both files, inodes and directories. + Inodes in the system are very small and all blocks are packed to minimise + data overhead. Block sizes greater than 4K are supported up to a maximum of 64K. + + Squashfs is intended for general read-only filesystem use, for archival + use (i.e. in cases where a .tar.gz file may be used), and in embedded + systems where low overhead is needed. Further information and filesystem tools + are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read . The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. +# CONFIG_MIPS_BRCM End Broadcom changed code. + config CRAMFS tristate "Compressed ROM file system support" - select ZLIB_INFLATE +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +# select ZLIB_INFLATE +# CONFIG_MIPS_BRCM End Broadcom changed code. help Saying Y here includes support for CramFs (Compressed ROM File System). CramFs is designed to be a simple, small, and compressed @@ -1230,6 +1257,22 @@ directory /) cannot be compiled as a module. If unsure, say N. + +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +choice + prompt "Decompression method" + depends on SQUASHFS || CRAMFS + default LZMA_FS_INFLATE + +config LZMA_FS_INFLATE + bool "LZMA" + +config ZLIB_FS_INFLATE + bool "ZLIB" + select ZLIB_INFLATE + +endchoice +# CONFIG_MIPS_BRCM End Broadcom changed code. config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" diff -Naur linux-mips-2.6.8.1-orig/fs/Makefile linux-mips-2.6.8.1-bcm/fs/Makefile --- linux-mips-2.6.8.1-orig/fs/Makefile 2004-06-06 04:12:50.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/fs/Makefile 2006-12-20 18:46:52.000000000 +0100 @@ -50,6 +50,9 @@ obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +obj-$(CONFIG_SQUASHFS) += squashfs/ +# CONFIG_MIPS_BRCM End Broadcom changed code. obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -Naur linux-mips-2.6.8.1-orig/fs/partitions/Kconfig linux-mips-2.6.8.1-bcm/fs/partitions/Kconfig --- linux-mips-2.6.8.1-orig/fs/partitions/Kconfig 2004-06-26 17:15:22.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/fs/partitions/Kconfig 2006-12-20 18:46:16.000000000 +0100 @@ -100,7 +100,7 @@ config MSDOS_PARTITION bool "PC BIOS (MSDOS partition tables) support" if PARTITION_ADVANCED - default y if !PARTITION_ADVANCED && !AMIGA && !ATARI && !MAC && !SGI_IP22 && !ARM && !SGI_IP27 + default n if !PARTITION_ADVANCED && !AMIGA && !ATARI && !MAC && !SGI_IP22 && !ARM && !SGI_IP27 help Say Y here if you would like to use hard disks under Linux which were partitioned on an x86 PC (not necessarily by DOS). diff -Naur linux-mips-2.6.8.1-orig/fs/seq_file.c linux-mips-2.6.8.1-bcm/fs/seq_file.c --- linux-mips-2.6.8.1-orig/fs/seq_file.c 2004-08-13 09:18:55.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/fs/seq_file.c 2006-12-20 18:46:52.000000000 +0100 @@ -14,337 +14,351 @@ #include /** - * seq_open - initialize sequential file - * @file: file we initialize - * @op: method table describing the sequence + * seq_open - initialize sequential file + * @file: file we initialize + * @op: method table describing the sequence * - * seq_open() sets @file, associating it with a sequence described - * by @op. @op->start() sets the iterator up and returns the first - * element of sequence. @op->stop() shuts it down. @op->next() - * returns the next element of sequence. @op->show() prints element - * into the buffer. In case of error ->start() and ->next() return - * ERR_PTR(error). In the end of sequence they return %NULL. ->show() - * returns 0 in case of success and negative number in case of error. + * seq_open() sets @file, associating it with a sequence described + * by @op. @op->start() sets the iterator up and returns the first + * element of sequence. @op->stop() shuts it down. @op->next() + * returns the next element of sequence. @op->show() prints element + * into the buffer. In case of error ->start() and ->next() return + * ERR_PTR(error). In the end of sequence they return %NULL. ->show() + * returns 0 in case of success and negative number in case of error. */ int seq_open(struct file *file, struct seq_operations *op) { - struct seq_file *p = kmalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return -ENOMEM; - memset(p, 0, sizeof(*p)); - sema_init(&p->sem, 1); - p->op = op; - file->private_data = p; - - /* SEQ files support lseek, but not pread/pwrite */ - file->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE); - return 0; + struct seq_file *p = kmalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + memset(p, 0, sizeof(*p)); + sema_init(&p->sem, 1); + p->op = op; + file->private_data = p; + + /* SEQ files support lseek, but not pread/pwrite */ + file->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE); + return 0; } EXPORT_SYMBOL(seq_open); /** - * seq_read - ->read() method for sequential files. - * @file, @buf, @size, @ppos: see file_operations method + * seq_read - ->read() method for sequential files. + * @file, @buf, @size, @ppos: see file_operations method * - * Ready-made ->f_op->read() + * Ready-made ->f_op->read() */ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) { - struct seq_file *m = (struct seq_file *)file->private_data; - size_t copied = 0; - loff_t pos; - size_t n; - void *p; - int err = 0; - - down(&m->sem); - /* grab buffer if we didn't have one */ - if (!m->buf) { - m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL); - if (!m->buf) - goto Enomem; - } - /* if not empty - flush it first */ - if (m->count) { - n = min(m->count, size); - err = copy_to_user(buf, m->buf + m->from, n); - if (err) - goto Efault; - m->count -= n; - m->from += n; - size -= n; - buf += n; - copied += n; - if (!m->count) - m->index++; - if (!size) - goto Done; - } - /* we need at least one record in buffer */ - while (1) { - pos = m->index; - p = m->op->start(m, &pos); - err = PTR_ERR(p); - if (!p || IS_ERR(p)) - break; - err = m->op->show(m, p); - if (err) - break; - if (m->count < m->size) - goto Fill; - m->op->stop(m, p); - kfree(m->buf); - m->buf = kmalloc(m->size <<= 1, GFP_KERNEL); - if (!m->buf) - goto Enomem; - m->count = 0; - } - m->op->stop(m, p); - m->count = 0; - goto Done; + struct seq_file *m = (struct seq_file *)file->private_data; + size_t copied = 0; + loff_t pos; + size_t n; + void *p; + int err = 0; + + down(&m->sem); + /* grab buffer if we didn't have one */ + if (!m->buf) { + m->buf = kmalloc(m->size = PAGE_SIZE+1, GFP_KERNEL); + if (!m->buf) + goto Enomem; + } + /* if not empty - flush it first */ + if (m->count) { + n = min(m->count, size); + err = copy_to_user(buf, m->buf + m->from, n); + if (err) + goto Efault; + m->count -= n; + m->from += n; + size -= n; + buf += n; + copied += n; + if (!m->count) + m->index++; + if (!size) + goto Done; + } + /* we need at least one record in buffer */ + while (1) { + pos = m->index; + p = m->op->start(m, &pos); + err = PTR_ERR(p); + if (!p || IS_ERR(p)) + break; + err = m->op->show(m, p); + if (err) + break; + if (m->count < m->size) + goto Fill; + m->op->stop(m, p); + kfree(m->buf); + m->buf = kmalloc(m->size <<= 1, GFP_KERNEL); + if (!m->buf) + goto Enomem; + m->count = 0; + } + m->op->stop(m, p); + m->count = 0; + goto Done; Fill: - /* they want more? let's try to get some more */ - while (m->count < size) { - size_t offs = m->count; - loff_t next = pos; - p = m->op->next(m, p, &next); - if (!p || IS_ERR(p)) { - err = PTR_ERR(p); - break; - } - err = m->op->show(m, p); - if (err || m->count == m->size) { - m->count = offs; - break; - } - pos = next; - } - m->op->stop(m, p); - n = min(m->count, size); - err = copy_to_user(buf, m->buf, n); - if (err) - goto Efault; - copied += n; - m->count -= n; - if (m->count) - m->from = n; - else - pos++; - m->index = pos; + /* they want more? let's try to get some more */ + while (m->count < size) { + size_t offs = m->count; + loff_t next = pos; + p = m->op->next(m, p, &next); + if (!p || IS_ERR(p)) { + err = PTR_ERR(p); + break; + } + err = m->op->show(m, p); +//BRCM modification begin +// if (err || m->count == m->size) { + if (err) { +//BRCM modification end + m->count = offs; + break; + } + pos = next; + } + m->op->stop(m, p); + n = min(m->count, size); + err = copy_to_user(buf, m->buf, n); + if (err) + goto Efault; + copied += n; + m->count -= n; + + if (m->count) + m->from = n; + else + pos++; + m->index = pos; + Done: - if (!copied) - copied = err; - else - *ppos += copied; - up(&m->sem); - return copied; + if (!copied) + copied = err; + else + *ppos += copied; + + up(&m->sem); + return copied; Enomem: - err = -ENOMEM; - goto Done; + err = -ENOMEM; + goto Done; Efault: - err = -EFAULT; - goto Done; + err = -EFAULT; + goto Done; } EXPORT_SYMBOL(seq_read); static int traverse(struct seq_file *m, loff_t offset) { - loff_t pos = 0; - int error = 0; - void *p; - - m->index = 0; - m->count = m->from = 0; - if (!offset) - return 0; - if (!m->buf) { - m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL); - if (!m->buf) - return -ENOMEM; - } - p = m->op->start(m, &m->index); - while (p) { - error = PTR_ERR(p); - if (IS_ERR(p)) - break; - error = m->op->show(m, p); - if (error) - break; - if (m->count == m->size) - goto Eoverflow; - if (pos + m->count > offset) { - m->from = offset - pos; - m->count -= m->from; - break; - } - pos += m->count; - m->count = 0; - if (pos == offset) { - m->index++; - break; - } - p = m->op->next(m, p, &m->index); - } - m->op->stop(m, p); - return error; + loff_t pos = 0; + int error = 0; + void *p; + + m->index = 0; + m->count = m->from = 0; + if (!offset) + return 0; + if (!m->buf) { + m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL); + if (!m->buf) + return -ENOMEM; + } + p = m->op->start(m, &m->index); + while (p) { + error = PTR_ERR(p); + if (IS_ERR(p)) + break; + error = m->op->show(m, p); + if (error) + break; + if (m->count == m->size) + goto Eoverflow; + if (pos + m->count > offset) { + m->from = offset - pos; + m->count -= m->from; + break; + } + pos += m->count; + m->count = 0; + if (pos == offset) { + m->index++; + break; + } + p = m->op->next(m, p, &m->index); + } + m->op->stop(m, p); + return error; Eoverflow: - m->op->stop(m, p); - kfree(m->buf); - m->buf = kmalloc(m->size <<= 1, GFP_KERNEL); - return !m->buf ? -ENOMEM : -EAGAIN; + m->op->stop(m, p); + kfree(m->buf); + m->buf = kmalloc(m->size <<= 1, GFP_KERNEL); + return !m->buf ? -ENOMEM : -EAGAIN; } /** - * seq_lseek - ->llseek() method for sequential files. - * @file, @offset, @origin: see file_operations method + * seq_lseek - ->llseek() method for sequential files. + * @file, @offset, @origin: see file_operations method * - * Ready-made ->f_op->llseek() + * Ready-made ->f_op->llseek() */ loff_t seq_lseek(struct file *file, loff_t offset, int origin) { - struct seq_file *m = (struct seq_file *)file->private_data; - long long retval = -EINVAL; + struct seq_file *m = (struct seq_file *)file->private_data; + long long retval = -EINVAL; - down(&m->sem); - switch (origin) { - case 1: - offset += file->f_pos; - case 0: - if (offset < 0) - break; - retval = offset; - if (offset != file->f_pos) { - while ((retval=traverse(m, offset)) == -EAGAIN) - ; - if (retval) { - /* with extreme prejudice... */ - file->f_pos = 0; - m->index = 0; - m->count = 0; - } else { - retval = file->f_pos = offset; - } - } - } - up(&m->sem); - return retval; + down(&m->sem); + switch (origin) { + case 1: + offset += file->f_pos; + case 0: + if (offset < 0) + break; + retval = offset; + if (offset != file->f_pos) { + while ((retval=traverse(m, offset)) == -EAGAIN) + ; + if (retval) { + /* with extreme prejudice... */ + file->f_pos = 0; + m->index = 0; + m->count = 0; + } else { + retval = file->f_pos = offset; + } + } + } + up(&m->sem); + return retval; } EXPORT_SYMBOL(seq_lseek); /** - * seq_release - free the structures associated with sequential file. - * @file: file in question - * @inode: file->f_dentry->d_inode + * seq_release - free the structures associated with sequential file. + * @file: file in question + * @inode: file->f_dentry->d_inode * - * Frees the structures associated with sequential file; can be used - * as ->f_op->release() if you don't have private data to destroy. + * Frees the structures associated with sequential file; can be used + * as ->f_op->release() if you don't have private data to destroy. */ int seq_release(struct inode *inode, struct file *file) { - struct seq_file *m = (struct seq_file *)file->private_data; - kfree(m->buf); - kfree(m); - return 0; + struct seq_file *m = (struct seq_file *)file->private_data; + kfree(m->buf); + kfree(m); + return 0; } EXPORT_SYMBOL(seq_release); /** - * seq_escape - print string into buffer, escaping some characters - * @m: target buffer - * @s: string - * @esc: set of characters that need escaping + * seq_escape - print string into buffer, escaping some characters + * @m: target buffer + * @s: string + * @esc: set of characters that need escaping * - * Puts string into buffer, replacing each occurrence of character from - * @esc with usual octal escape. Returns 0 in case of success, -1 - in - * case of overflow. + * Puts string into buffer, replacing each occurrence of character from + * @esc with usual octal escape. Returns 0 in case of success, -1 - in + * case of overflow. */ int seq_escape(struct seq_file *m, const char *s, const char *esc) { - char *end = m->buf + m->size; + char *end = m->buf + m->size; char *p; - char c; + char c; for (p = m->buf + m->count; (c = *s) != '\0' && p < end; s++) { - if (!strchr(esc, c)) { - *p++ = c; - continue; - } - if (p + 3 < end) { - *p++ = '\\'; - *p++ = '0' + ((c & 0300) >> 6); - *p++ = '0' + ((c & 070) >> 3); - *p++ = '0' + (c & 07); - continue; - } - m->count = m->size; - return -1; + if (!strchr(esc, c)) { + *p++ = c; + continue; + } + if (p + 3 < end) { + *p++ = '\\'; + *p++ = '0' + ((c & 0300) >> 6); + *p++ = '0' + ((c & 070) >> 3); + *p++ = '0' + (c & 07); + continue; + } + m->count = m->size; + return -1; } - m->count = p - m->buf; + m->count = p - m->buf; return 0; } EXPORT_SYMBOL(seq_escape); int seq_printf(struct seq_file *m, const char *f, ...) { - va_list args; - int len; - - if (m->count < m->size) { - va_start(args, f); - len = vsnprintf(m->buf + m->count, m->size - m->count, f, args); - va_end(args); - if (m->count + len < m->size) { - m->count += len; - return 0; - } - } - m->count = m->size; - return -1; + va_list args; + int len; +//BRCM modification begin + int count, size, max; + count = m->count; + size = m->size; + max = size - count; +//BRCM modification end + if (m->count < m->size) { + va_start(args, f); +//BRCM modification begin + // len = vsnprintf(m->buf + m->count, m->size - m->count, f, args); + len = vsnprintf(m->buf + m->count, max, f, args); +//BRCM modification end + va_end(args); + if (m->count + len < m->size) { + m->count += len; + return 0; + } + } + m->count = m->size; + return -1; } EXPORT_SYMBOL(seq_printf); int seq_path(struct seq_file *m, - struct vfsmount *mnt, struct dentry *dentry, - char *esc) + struct vfsmount *mnt, struct dentry *dentry, + char *esc) { - if (m->count < m->size) { - char *s = m->buf + m->count; - char *p = d_path(dentry, mnt, s, m->size - m->count); - if (!IS_ERR(p)) { - while (s <= p) { - char c = *p++; - if (!c) { - p = m->buf + m->count; - m->count = s - m->buf; - return s - p; - } else if (!strchr(esc, c)) { - *s++ = c; - } else if (s + 4 > p) { - break; - } else { - *s++ = '\\'; - *s++ = '0' + ((c & 0300) >> 6); - *s++ = '0' + ((c & 070) >> 3); - *s++ = '0' + (c & 07); - } - } - } - } - m->count = m->size; - return -1; + if (m->count < m->size) { + char *s = m->buf + m->count; + char *p = d_path(dentry, mnt, s, m->size - m->count); + if (!IS_ERR(p)) { + while (s <= p) { + char c = *p++; + if (!c) { + p = m->buf + m->count; + m->count = s - m->buf; + return s - p; + } else if (!strchr(esc, c)) { + *s++ = c; + } else if (s + 4 > p) { + break; + } else { + *s++ = '\\'; + *s++ = '0' + ((c & 0300) >> 6); + *s++ = '0' + ((c & 070) >> 3); + *s++ = '0' + (c & 07); + } + } + } + } + m->count = m->size; + return -1; } EXPORT_SYMBOL(seq_path); static void *single_start(struct seq_file *p, loff_t *pos) { - return NULL + (*pos == 0); + return NULL + (*pos == 0); } static void *single_next(struct seq_file *p, void *v, loff_t *pos) { - ++*pos; - return NULL; + ++*pos; + return NULL; } static void single_stop(struct seq_file *p, void *v) @@ -352,64 +366,64 @@ } int single_open(struct file *file, int (*show)(struct seq_file *, void *), - void *data) + void *data) { - struct seq_operations *op = kmalloc(sizeof(*op), GFP_KERNEL); - int res = -ENOMEM; + struct seq_operations *op = kmalloc(sizeof(*op), GFP_KERNEL); + int res = -ENOMEM; - if (op) { - op->start = single_start; - op->next = single_next; - op->stop = single_stop; - op->show = show; - res = seq_open(file, op); - if (!res) - ((struct seq_file *)file->private_data)->private = data; - else - kfree(op); - } - return res; + if (op) { + op->start = single_start; + op->next = single_next; + op->stop = single_stop; + op->show = show; + res = seq_open(file, op); + if (!res) + ((struct seq_file *)file->private_data)->private = data; + else + kfree(op); + } + return res; } EXPORT_SYMBOL(single_open); int single_release(struct inode *inode, struct file *file) { - struct seq_operations *op = ((struct seq_file *)file->private_data)->op; - int res = seq_release(inode, file); - kfree(op); - return res; + struct seq_operations *op = ((struct seq_file *)file->private_data)->op; + int res = seq_release(inode, file); + kfree(op); + return res; } EXPORT_SYMBOL(single_release); int seq_release_private(struct inode *inode, struct file *file) { - struct seq_file *seq = file->private_data; + struct seq_file *seq = file->private_data; - kfree(seq->private); - seq->private = NULL; - return seq_release(inode, file); + kfree(seq->private); + seq->private = NULL; + return seq_release(inode, file); } EXPORT_SYMBOL(seq_release_private); int seq_putc(struct seq_file *m, char c) { - if (m->count < m->size) { - m->buf[m->count++] = c; - return 0; - } - return -1; + if (m->count < m->size) { + m->buf[m->count++] = c; + return 0; + } + return -1; } EXPORT_SYMBOL(seq_putc); int seq_puts(struct seq_file *m, const char *s) { - int len = strlen(s); - if (m->count + len < m->size) { - memcpy(m->buf + m->count, s, len); - m->count += len; - return 0; - } - m->count = m->size; - return -1; + int len = strlen(s); + if (m->count + len < m->size) { + memcpy(m->buf + m->count, s, len); + m->count += len; + return 0; + } + m->count = m->size; + return -1; } EXPORT_SYMBOL(seq_puts); diff -Naur linux-mips-2.6.8.1-orig/fs/squashfs/inode.c linux-mips-2.6.8.1-bcm/fs/squashfs/inode.c --- linux-mips-2.6.8.1-orig/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/squashfs/inode.c 2006-12-20 18:46:45.000000000 +0100 @@ -0,0 +1,1666 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004 Phillip Lougher + * + * 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, + * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#if defined(CONFIG_MIPS_BRCM) +/*#define SQUASHFS_1_0_COMPATIBILITY*/ +#else +#define SQUASHFS_1_0_COMPATIBILITY +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) if(!silent) printk(KERN_ERR "SQUASHFS error: "s, ## args) +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static void squashfs_put_super(struct super_block *); +static int squashfs_statfs(struct super_block *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readpage4K(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, struct nameidata *); +static unsigned int read_data(struct super_block *s, char *buffer, + unsigned int index, unsigned int length, int, unsigned int *next_index); +static int squashfs_get_cached_block(struct super_block *s, char *buffer, + unsigned int block, unsigned int offset, int length, + unsigned int *next_block, unsigned int *next_offset); +static struct inode *squashfs_iget(struct super_block *s, squashfs_inode inode); +static unsigned int read_blocklist(struct inode *inode, int index, int readahead_blks, + char *block_list, char **block_p, unsigned int *bsize); +static void squashfs_put_super(struct super_block *s); +static struct super_block *squashfs_get_sb(struct file_system_type *, int, const char *, void *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +#ifdef SQUASHFS_1_0_COMPATIBILITY +static int squashfs_readpage_lessthan4K(struct file *file, struct page *page); +static struct inode *squashfs_iget_1(struct super_block *s, squashfs_inode inode); +static unsigned int read_blocklist_1(struct inode *inode, int index, int readahead_blks, + char *block_list, char **block_p, unsigned int *bsize); +#endif + +DECLARE_MUTEX(read_data_mutex); + +#ifdef CONFIG_ZLIB_FS_INFLATE +static z_stream stream; +#endif + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV + }; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, +}; + +static struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +static struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static struct address_space_operations squashfs_aops_4K = { + .readpage = squashfs_readpage4K +}; + +#ifdef SQUASHFS_1_0_COMPATIBILITY +static struct address_space_operations squashfs_aops_lessthan4K = { + .readpage = squashfs_readpage_lessthan4K +}; +#endif + +static struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +static struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + + +static unsigned int read_data(struct super_block *s, char *buffer, + unsigned int index, unsigned int length, int datablock, unsigned int *next_index) +{ + squashfs_sb_info *msBlk = (squashfs_sb_info *)s->s_fs_info; + struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >> msBlk->devblksize_log2) + 2]; + unsigned int offset = index & ((1 << msBlk->devblksize_log2) - 1); + unsigned int cur_index = index >> msBlk->devblksize_log2; + int bytes, avail_bytes, b, k; + char *c_buffer; + unsigned int compressed; + unsigned int c_byte = length; +#if defined(CONFIG_MIPS_BRCM) +#ifdef CONFIG_LZMA_FS_INFLATE + extern int decompress_lzma_7z(unsigned char* in_data, unsigned in_size, + unsigned char* out_data, unsigned out_size); +#endif + b = 1; +#endif + + if(c_byte) { + bytes = msBlk->devblksize - offset; + if(datablock) { + c_buffer = (compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte)) ? msBlk->read_data : buffer; + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + } else { + c_buffer = (compressed = SQUASHFS_COMPRESSED(c_byte)) ? msBlk->read_data : buffer; + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + } + + TRACE("Block @ 0x%x, %scompressed size %d\n", index, compressed ? "" : "un", (unsigned int) c_byte); + + if(!(bh[0] = sb_getblk(s, cur_index))) + goto block_release; + for(b = 1; bytes < c_byte; b++) { + if(!(bh[b] = sb_getblk(s, ++cur_index))) + goto block_release; + bytes += msBlk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + unsigned short temp; + if(!(bh[0] = sb_bread(s, cur_index))) + goto read_failure; + + if(msBlk->devblksize - offset == 1) { + if(msBlk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) (bh[0]->b_data + offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) (bh[0]->b_data + offset)); + brelse(bh[0]); + if(!(bh[0] = sb_bread(s, ++cur_index))) + goto read_failure; + if(msBlk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) bh[0]->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) bh[0]->b_data); + c_byte = temp; + offset = 1; + } + else { + if(msBlk->swap) { + unsigned short temp; + ((unsigned char *) &temp)[1] = *((unsigned char *) (bh[0]->b_data + offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) (bh[0]->b_data + offset + 1)); + c_byte = temp; + } else + c_byte = *((unsigned short *) (bh[0]->b_data + offset)); + offset += 2; + } + if(SQUASHFS_CHECK_DATA(msBlk->sBlk.flags)) { + if(offset == msBlk->devblksize) { + brelse(bh[0]); + if(!(bh[0] = sb_bread(s, ++cur_index))) + goto read_failure; + offset = 0; + } + if(*((unsigned char *) (bh[0]->b_data + offset)) != SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", index); + brelse(bh[0]); + return 0; + } + offset ++; + } + + bytes = msBlk->devblksize - offset; + if(datablock) { + c_buffer = (compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte)) ? msBlk->read_data : buffer; + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + } else { + c_buffer = (compressed = SQUASHFS_COMPRESSED(c_byte)) ? msBlk->read_data : buffer; + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + } + + TRACE("Block @ 0x%x, %scompressed size %d\n", index, compressed ? "" : "un", (unsigned int) c_byte); + + for(b = 1; bytes < c_byte; b++) { + if(!(bh[b] = sb_getblk(s, ++cur_index))) + goto block_release; + bytes += msBlk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if(compressed) + down(&read_data_mutex); + + for(bytes = 0, k = 0; k < b; k++) { + avail_bytes = (c_byte - bytes) > (msBlk->devblksize - offset) ? msBlk->devblksize - offset : c_byte - bytes; + wait_on_buffer(bh[k]); + memcpy(c_buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + /* + * uncompress block + */ + if(compressed) { +#ifdef CONFIG_ZLIB_FS_INFLATE + int zlib_err; + + stream.next_in = c_buffer; + stream.avail_in = c_byte; + stream.next_out = buffer; + stream.avail_out = msBlk->read_size; + if(((zlib_err = zlib_inflateInit(&stream)) != Z_OK) || + ((zlib_err = zlib_inflate(&stream, Z_FINISH)) != Z_STREAM_END) || + ((zlib_err = zlib_inflateEnd(&stream)) != Z_OK)) { + ERROR("zlib_fs returned unexpected result 0x%x\n", zlib_err); + bytes = 0; + } else + bytes = stream.total_out; +#endif +#if defined(CONFIG_MIPS_BRCM) +#ifdef CONFIG_LZMA_FS_INFLATE + TRACE("Calling decompress_lzma_7z: buffer_in size=%d, buffer_out size=%d\n", + c_byte, msBlk->read_size); + if ((bytes = decompress_lzma_7z(c_buffer, c_byte, buffer, msBlk->read_size)) < 0) { + ERROR("lzma_fs error while decompressing!\n"); + bytes = 0; + } else + bytes = msBlk->read_size; + TRACE("Done with decompress_lzma_7z: output size=%d\n", bytes); +#endif +#endif + up(&read_data_mutex); + } + + if(next_index) + *next_index = index + c_byte + (length ? 0 : (SQUASHFS_CHECK_DATA(msBlk->sBlk.flags) ? 3 : 2)); + + return bytes; + +block_release: + while(--b >= 0) brelse(bh[b]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + return 0; +} + + +static int squashfs_get_cached_block(struct super_block *s, char *buffer, + unsigned int block, unsigned int offset, int length, + unsigned int *next_block, unsigned int *next_offset) +{ + squashfs_sb_info *msBlk = (squashfs_sb_info *)s->s_fs_info; + int n, i, bytes, return_length = length; + unsigned int next_index; + + TRACE("Entered squashfs_get_cached_block [%x:%x]\n", block, offset); + + for(;;) { + for(i = 0; i < SQUASHFS_CACHED_BLKS; i++) + if(msBlk->block_cache[i].block == block) + break; + + down(&msBlk->block_cache_mutex); + if(i == SQUASHFS_CACHED_BLKS) { + /* read inode header block */ + for(i = msBlk->next_cache, n = SQUASHFS_CACHED_BLKS; n ; n --, i = (i + 1) % SQUASHFS_CACHED_BLKS) + if(msBlk->block_cache[i].block != SQUASHFS_USED_BLK) + break; + if(n == 0) { + wait_queue_t wait; + + init_waitqueue_entry(&wait, current); + add_wait_queue(&msBlk->waitq, &wait); + up(&msBlk->block_cache_mutex); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + set_current_state(TASK_RUNNING); + remove_wait_queue(&msBlk->waitq, &wait); + continue; + } + msBlk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS; + + if(msBlk->block_cache[i].block == SQUASHFS_INVALID_BLK) { + if(!(msBlk->block_cache[i].data = (unsigned char *) + kmalloc(SQUASHFS_METADATA_SIZE, GFP_KERNEL))) { + ERROR("Failed to allocate cache block\n"); + up(&msBlk->block_cache_mutex); + return 0; + } + } + + msBlk->block_cache[i].block = SQUASHFS_USED_BLK; + up(&msBlk->block_cache_mutex); + if(!(msBlk->block_cache[i].length = read_data(s, msBlk->block_cache[i].data, block, 0, 0, + &next_index))) { + ERROR("Unable to read cache block [%x:%x]\n", block, offset); + return 0; + } + down(&msBlk->block_cache_mutex); + wake_up(&msBlk->waitq); + msBlk->block_cache[i].block = block; + msBlk->block_cache[i].next_index = next_index; + TRACE("Read cache block [%x:%x]\n", block, offset); + } + + if(msBlk->block_cache[i].block != block) { + up(&msBlk->block_cache_mutex); + continue; + } + + if((bytes = msBlk->block_cache[i].length - offset) >= length) { + if(buffer) + memcpy(buffer, msBlk->block_cache[i].data + offset, length); + if(msBlk->block_cache[i].length - offset == length) { + *next_block = msBlk->block_cache[i].next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + + up(&msBlk->block_cache_mutex); + return return_length; + } else { + if(buffer) { + memcpy(buffer, msBlk->block_cache[i].data + offset, bytes); + buffer += bytes; + } + block = msBlk->block_cache[i].next_index; + up(&msBlk->block_cache_mutex); + length -= bytes; + offset = 0; + } + } +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, unsigned int *fragment_start_block, unsigned int *fragment_size) +{ + squashfs_sb_info *msBlk = (squashfs_sb_info *)s->s_fs_info; + unsigned int start_block = msBlk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + squashfs_fragment_entry fragment_entry; + + if(msBlk->swap) { + squashfs_fragment_entry sfragment_entry; + + if(!squashfs_get_cached_block(s, (char *) &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + return 0; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if(!squashfs_get_cached_block(s, (char *) &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + return 0; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; +} + + +void release_cached_fragment(squashfs_sb_info *msBlk, struct squashfs_fragment_cache *fragment) +{ + down(&msBlk->fragment_mutex); + fragment->locked --; + wake_up(&msBlk->fragment_wait_queue); + up(&msBlk->fragment_mutex); +} + + +struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, unsigned int start_block, int length) +{ + int i, n; + squashfs_sb_info *msBlk = (squashfs_sb_info *)s->s_fs_info; + + for(;;) { + down(&msBlk->fragment_mutex); + for(i = 0; i < SQUASHFS_CACHED_FRAGMENTS && msBlk->fragment[i].block != start_block; i++); + if(i == SQUASHFS_CACHED_FRAGMENTS) { + for(i = msBlk->next_fragment, n = SQUASHFS_CACHED_FRAGMENTS; + n && msBlk->fragment[i].locked; n--, i = (i + 1) % SQUASHFS_CACHED_FRAGMENTS); + + if(n == 0) { + wait_queue_t wait; + + init_waitqueue_entry(&wait, current); + add_wait_queue(&msBlk->fragment_wait_queue, &wait); + up(&msBlk->fragment_mutex); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + set_current_state(TASK_RUNNING); + remove_wait_queue(&msBlk->fragment_wait_queue, &wait); + continue; + } + msBlk->next_fragment = (msBlk->next_fragment + 1) % SQUASHFS_CACHED_FRAGMENTS; + + if(msBlk->fragment[i].data == NULL) + if(!(msBlk->fragment[i].data = (unsigned char *) + kmalloc(SQUASHFS_FILE_MAX_SIZE, GFP_KERNEL))) { + ERROR("Failed to allocate fragment cache block\n"); + up(&msBlk->fragment_mutex); + return NULL; + } + + msBlk->fragment[i].block = SQUASHFS_INVALID_BLK; + msBlk->fragment[i].locked = 1; + up(&msBlk->fragment_mutex); + if(!(msBlk->fragment[i].length = read_data(s, msBlk->fragment[i].data, start_block, length, + 1, NULL))) { + ERROR("Unable to read fragment cache block [%x]\n", start_block); + msBlk->fragment[i].locked = 0; + return NULL; + } + msBlk->fragment[i].block = start_block; + TRACE("New fragment %d, start block %d, locked %d\n", i, msBlk->fragment[i].block, msBlk->fragment[i].locked); + return &msBlk->fragment[i]; + } + + msBlk->fragment[i].locked ++; + up(&msBlk->fragment_mutex); + + TRACE("Got fragment %d, start block %d, locked %d\n", i, msBlk->fragment[i].block, msBlk->fragment[i].locked); + return &msBlk->fragment[i]; + } +} + + +#ifdef SQUASHFS_1_0_COMPATIBILITY +static struct inode *squashfs_iget_1(struct super_block *s, squashfs_inode inode) +{ + struct inode *i = new_inode(s); + squashfs_sb_info *msBlk = (squashfs_sb_info *)s->s_fs_info; + squashfs_super_block *sBlk = &msBlk->sBlk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + sBlk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int next_block, next_offset; + squashfs_base_inode_header_1 inodeb; + + TRACE("Entered squashfs_iget_1\n"); + + if(msBlk->swap) { + squashfs_base_inode_header_1 sinodeb; + + if(!squashfs_get_cached_block(s, (char *) &sinodeb, block, offset, + sizeof(sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_1(&inodeb, &sinodeb, sizeof(sinodeb)); + } else + if(!squashfs_get_cached_block(s, (char *) &inodeb, block, offset, + sizeof(inodeb), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = 1; + + i->i_mtime.tv_sec = sBlk->mkfs_time; + i->i_atime.tv_sec = sBlk->mkfs_time; + i->i_ctime.tv_sec = sBlk->mkfs_time; + + if(inodeb.inode_type != SQUASHFS_IPC_TYPE) + i->i_uid = msBlk->uid[((inodeb.inode_type - 1) / SQUASHFS_TYPES) * 16 + inodeb.uid]; + i->i_ino = SQUASHFS_MK_VFS_INODE(block - sBlk->inode_table_start, offset); + + i->i_mode = inodeb.mode; + + switch(inodeb.inode_type == SQUASHFS_IPC_TYPE ? SQUASHFS_IPC_TYPE : (inodeb.inode_type - 1) % SQUASHFS_TYPES + 1) { + case SQUASHFS_FILE_TYPE: { + squashfs_reg_inode_header_1 inodep; + + if(msBlk->swap) { + squashfs_reg_inode_header_1 sinodep; + + if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep), + &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_1(&inodep, &sinodep); + } else + if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep), + &next_block, &next_offset)) + goto failed_read; + + i->i_size = inodep.file_size; + i->i_fop = &generic_ro_fops; + if(sBlk->block_size > 4096) + i->i_data.a_ops = &squashfs_aops; + else if(sBlk->block_size == 4096) + i->i_data.a_ops = &squashfs_aops_4K; + else + i->i_data.a_ops = &squashfs_aops_lessthan4K; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep.mtime; + i->i_atime.tv_sec = inodep.mtime; + i->i_ctime.tv_sec = inodep.mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->fragment_start_block = SQUASHFS_INVALID_BLK; + SQUASHFS_I(i)->fragment_offset = 0; + SQUASHFS_I(i)->start_block = inodep.start_block; + SQUASHFS_I(i)->block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + TRACE("File inode %x:%x, start_block %x, block_list_start %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep.start_block, next_block, next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + squashfs_dir_inode_header_1 inodep; + + if(msBlk->swap) { + squashfs_dir_inode_header_1 sinodep; + + if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep), + &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_1(&inodep, &sinodep); + } else + if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep), + &next_block, &next_offset)) + goto failed_read; + + i->i_size = inodep.file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep.mtime; + i->i_atime.tv_sec = inodep.mtime; + i->i_ctime.tv_sec = inodep.mtime; + SQUASHFS_I(i)->start_block = inodep.start_block; + SQUASHFS_I(i)->offset = inodep.offset; + TRACE("Directory inode %x:%x, start_block %x, offset %x\n", SQUASHFS_INODE_BLK(inode), offset, + inodep.start_block, inodep.offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + squashfs_symlink_inode_header_1 inodep; + + if(msBlk->swap) { + squashfs_symlink_inode_header_1 sinodep; + + if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep), + &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(&inodep, &sinodep); + } else + if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep), + &next_block, &next_offset)) + goto failed_read; + + i->i_size = inodep.symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + TRACE("Symbolic link inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + squashfs_dev_inode_header_1 inodep; + + if(msBlk->swap) { + squashfs_dev_inode_header_1 sinodep; + + if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep), + &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_1(&inodep, &sinodep); + } else + if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep), + &next_block, &next_offset)) + goto failed_read; + + i->i_size = 0; + i->i_mode |= (inodeb.inode_type == SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep.rdev)); + TRACE("Device inode %x:%x, rdev %x\n", SQUASHFS_INODE_BLK(inode), offset, inodep.rdev); + break; + } + case SQUASHFS_IPC_TYPE: { + squashfs_ipc_inode_header_1 inodep; + + if(msBlk->swap) { + squashfs_ipc_inode_header_1 sinodep; + + if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep), + &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER_1(&inodep, &sinodep); + } else + if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep), + &next_block, &next_offset)) + goto failed_read; + + i->i_size = 0; + i->i_mode |= (inodep.type == SQUASHFS_FIFO_TYPE) ? S_IFIFO : S_IFSOCK; + i->i_uid = msBlk->uid[inodep.offset * 16 + inodeb.uid]; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", inodeb.inode_type); + goto failed_read1; + } + + if(inodeb.guid == 15) + i->i_gid = i->i_uid; + else + i->i_gid = msBlk->guid[inodeb.guid]; + + return i; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return NULL; +} +#endif + + +static struct inode *squashfs_iget(struct super_block *s, squashfs_inode inode) +{ + struct inode *i = new_inode(s); + squashfs_sb_info *msBlk = (squashfs_sb_info *)s->s_fs_info; + squashfs_super_block *sBlk = &msBlk->sBlk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + sBlk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int next_block, next_offset; + squashfs_base_inode_header inodeb; + + TRACE("Entered squashfs_iget\n"); + + if(msBlk->swap) { + squashfs_base_inode_header sinodeb; + + if(!squashfs_get_cached_block(s, (char *) &sinodeb, block, offset, + sizeof(sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(&inodeb, &sinodeb, sizeof(sinodeb)); + } else + if(!squashfs_get_cached_block(s, (char *) &inodeb, block, offset, + sizeof(inodeb), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = 1; + + i->i_mtime.tv_sec = sBlk->mkfs_time; + i->i_atime.tv_sec = sBlk->mkfs_time; + i->i_ctime.tv_sec = sBlk->mkfs_time; + + i->i_uid = msBlk->uid[inodeb.uid]; + i->i_ino = SQUASHFS_MK_VFS_INODE(block - sBlk->inode_table_start, offset); + + i->i_mode = inodeb.mode; + + switch(inodeb.inode_type) { + case SQUASHFS_FILE_TYPE: { + squashfs_reg_inode_header inodep; + + if(msBlk->swap) { + squashfs_reg_inode_header sinodep; + + if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep), + &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(&inodep, &sinodep); + } else + if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep), + &next_block, &next_offset)) + goto failed_read; + + SQUASHFS_I(i)->fragment_start_block = SQUASHFS_INVALID_BLK; + if(inodep.fragment != SQUASHFS_INVALID_BLK && !get_fragment_location(s, inodep.fragment, + &SQUASHFS_I(i)->fragment_start_block, &SQUASHFS_I(i)->fragment_size)) + goto failed_read; + + SQUASHFS_I(i)->fragment_offset = inodep.offset; + i->i_size = inodep.file_size; + i->i_fop = &generic_ro_fops; + if(sBlk->block_size > 4096) + i->i_data.a_ops = &squashfs_aops; + else + i->i_data.a_ops = &squashfs_aops_4K; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep.mtime; + i->i_atime.tv_sec = inodep.mtime; + i->i_ctime.tv_sec = inodep.mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->start_block = inodep.start_block; + SQUASHFS_I(i)->block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + TRACE("File inode %x:%x, start_block %x, block_list_start %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep.start_block, next_block, next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + squashfs_dir_inode_header inodep; + + if(msBlk->swap) { + squashfs_dir_inode_header sinodep; + + if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep), + &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(&inodep, &sinodep); + } else + if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep), + &next_block, &next_offset)) + goto failed_read; + + i->i_size = inodep.file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep.mtime; + i->i_atime.tv_sec = inodep.mtime; + i->i_ctime.tv_sec = inodep.mtime; + SQUASHFS_I(i)->start_block = inodep.start_block; + SQUASHFS_I(i)->offset = inodep.offset; + TRACE("Directory inode %x:%x, start_block %x, offset %x\n", SQUASHFS_INODE_BLK(inode), offset, + inodep.start_block, inodep.offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + squashfs_symlink_inode_header inodep; + + if(msBlk->swap) { + squashfs_symlink_inode_header sinodep; + + if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep), + &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep); + } else + if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep), + &next_block, &next_offset)) + goto failed_read; + + i->i_size = inodep.symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + TRACE("Symbolic link inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + squashfs_dev_inode_header inodep; + + if(msBlk->swap) { + squashfs_dev_inode_header sinodep; + + if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep), + &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(&inodep, &sinodep); + } else + if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep), + &next_block, &next_offset)) + goto failed_read; + + i->i_size = 0; + i->i_mode |= (inodeb.inode_type == SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep.rdev)); + TRACE("Device inode %x:%x, rdev %x\n", SQUASHFS_INODE_BLK(inode), offset, inodep.rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + i->i_size = 0; + i->i_mode |= (inodeb.inode_type == SQUASHFS_FIFO_TYPE) ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", inodeb.inode_type); + goto failed_read1; + } + + if(inodeb.guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msBlk->guid[inodeb.guid]; + + return i; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return NULL; +} + + +static int squashfs_fill_super(struct super_block *s, + void *data, int silent) +{ + squashfs_sb_info *msBlk; + squashfs_super_block *sBlk; + int i; + char b[BDEVNAME_SIZE]; + + TRACE("Entered squashfs_read_superblock\n"); + + if(!(msBlk = (squashfs_sb_info *) s->s_fs_info = (void *) kmalloc(sizeof(squashfs_sb_info), GFP_KERNEL))) { + ERROR("Failed to allocate superblock\n"); + return -ENOMEM; + } + sBlk = &msBlk->sBlk; + + msBlk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msBlk->devblksize_log2 = ffz(~msBlk->devblksize); + + init_MUTEX(&msBlk->read_page_mutex); + init_MUTEX(&msBlk->block_cache_mutex); + init_MUTEX(&msBlk->fragment_mutex); + + init_waitqueue_head(&msBlk->waitq); + init_waitqueue_head(&msBlk->fragment_wait_queue); + + if(!read_data(s, (char *) sBlk, SQUASHFS_START, sizeof(squashfs_super_block) | SQUASHFS_COMPRESSED_BIT, 0, NULL)) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + msBlk->swap = 0; + if((s->s_magic = sBlk->s_magic) != SQUASHFS_MAGIC) { + if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) { + squashfs_super_block sblk; + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", bdevname(s->s_bdev, b)); + SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); + memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); + msBlk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ +#ifdef SQUASHFS_1_0_COMPATIBILITY + if((sBlk->s_major != 1) && (sBlk->s_major != 2 || sBlk->s_minor > SQUASHFS_MINOR)) { + SERROR("Major/Minor mismatch, filesystem is (%d:%d), I support (1 : x) or (2 : <= %d)\n", + sBlk->s_major, sBlk->s_minor, SQUASHFS_MINOR); + goto failed_mount; + } + if(sBlk->s_major == 1) + sBlk->block_size = sBlk->block_size_1; +#else + if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, filesystem is (%d:%d), I support (%d: <= %d)\n", + sBlk->s_major, sBlk->s_minor, SQUASHFS_MAJOR, SQUASHFS_MINOR); + goto failed_mount; + } +#endif + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); + TRACE("Check data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not"); + TRACE("Filesystem size %d bytes\n", sBlk->bytes_used); + TRACE("Block size %d\n", sBlk->block_size); + TRACE("Number of inodes %d\n", sBlk->inodes); + if(sBlk->s_major > 1) + TRACE("Number of fragments %d\n", sBlk->fragments); + TRACE("Number of uids %d\n", sBlk->no_uids); + TRACE("Number of gids %d\n", sBlk->no_guids); + TRACE("sBlk->inode_table_start %x\n", sBlk->inode_table_start); + TRACE("sBlk->directory_table_start %x\n", sBlk->directory_table_start); + if(sBlk->s_major > 1) + TRACE("sBlk->fragment_table_start %x\n", sBlk->fragment_table_start); + TRACE("sBlk->uid_start %x\n", sBlk->uid_start); + + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_ops; + + /* Init inode_table block pointer array */ + if(!(msBlk->block_cache = (squashfs_cache *) kmalloc(sizeof(squashfs_cache) * SQUASHFS_CACHED_BLKS, GFP_KERNEL))) { + ERROR("Failed to allocate block cache\n"); + goto failed_mount; + } + + for(i = 0; i < SQUASHFS_CACHED_BLKS; i++) + msBlk->block_cache[i].block = SQUASHFS_INVALID_BLK; + + msBlk->next_cache = 0; + + /* Allocate read_data block */ + msBlk->read_size = (sBlk->block_size < SQUASHFS_METADATA_SIZE) ? SQUASHFS_METADATA_SIZE : sBlk->block_size; + if(!(msBlk->read_data = (char *) kmalloc(msBlk->read_size, GFP_KERNEL))) { + ERROR("Failed to allocate read_data block\n"); + goto failed_mount1; + } + + /* Allocate read_page block */ + if(sBlk->block_size > PAGE_CACHE_SIZE && + !(msBlk->read_page = (char *) kmalloc(sBlk->block_size, GFP_KERNEL))) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount2; + } + + /* Allocate uid and gid tables */ + if(!(msBlk->uid = (squashfs_uid *) kmalloc((sBlk->no_uids + + sBlk->no_guids) * sizeof(squashfs_uid), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount3; + } + msBlk->guid = msBlk->uid + sBlk->no_uids; + + if(msBlk->swap) { + squashfs_uid suid[sBlk->no_uids + sBlk->no_guids]; + + if(!read_data(s, (char *) &suid, sBlk->uid_start, ((sBlk->no_uids + sBlk->no_guids) * + sizeof(squashfs_uid)) | SQUASHFS_COMPRESSED_BIT, 0, NULL)) { + SERROR("unable to read uid/gid table\n"); + goto failed_mount4; + } + SQUASHFS_SWAP_DATA(msBlk->uid, suid, (sBlk->no_uids + sBlk->no_guids), (sizeof(squashfs_uid) * 8)); + } else + if(!read_data(s, (char *) msBlk->uid, sBlk->uid_start, ((sBlk->no_uids + sBlk->no_guids) * + sizeof(squashfs_uid)) | SQUASHFS_COMPRESSED_BIT, 0, NULL)) { + SERROR("unable to read uid/gid table\n"); + goto failed_mount4; + } + + +#ifdef SQUASHFS_1_0_COMPATIBILITY + if(sBlk->s_major == 1) { + msBlk->iget = squashfs_iget_1; + msBlk->read_blocklist = read_blocklist_1; + msBlk->fragment = (struct squashfs_fragment_cache *) msBlk->fragment_index = NULL; + goto allocate_root; + } +#endif + msBlk->iget = squashfs_iget; + msBlk->read_blocklist = read_blocklist; + + if(!(msBlk->fragment = (struct squashfs_fragment_cache *) kmalloc(sizeof(struct squashfs_fragment_cache) * SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) { + ERROR("Failed to allocate fragment block cache\n"); + goto failed_mount4; + } + + for(i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { + msBlk->fragment[i].locked = 0; + msBlk->fragment[i].block = SQUASHFS_INVALID_BLK; + msBlk->fragment[i].data = NULL; + } + + msBlk->next_fragment = 0; + + /* Allocate fragment index table */ + if(!(msBlk->fragment_index = (squashfs_fragment_index *) kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount5; + } + + if(SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments) && + !read_data(s, (char *) msBlk->fragment_index, sBlk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments) | SQUASHFS_COMPRESSED_BIT, 0, NULL)) { + SERROR("unable to read fragment index table\n"); + goto failed_mount6; + } + + if(msBlk->swap) { + int i; + squashfs_fragment_index fragment; + + for(i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), &msBlk->fragment_index[i], 1); + msBlk->fragment_index[i] = fragment; + } + } + +#ifdef SQUASHFS_1_0_COMPATIBILITY +allocate_root: +#endif + if(!(s->s_root = d_alloc_root((msBlk->iget)(s, sBlk->root_inode)))) { + ERROR("Root inode create failed\n"); + goto failed_mount5; + } + + TRACE("Leaving squashfs_read_super\n"); + return 0; + +failed_mount6: + kfree(msBlk->fragment_index); +failed_mount5: + kfree(msBlk->fragment); +failed_mount4: + kfree(msBlk->uid); +failed_mount3: + kfree(msBlk->read_page); +failed_mount2: + kfree(msBlk->read_data); +failed_mount1: + kfree(msBlk->block_cache); +failed_mount: + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; +} + + +static int squashfs_statfs(struct super_block *s, struct kstatfs *buf) +{ + squashfs_super_block *sBlk = &((squashfs_sb_info *)s->s_fs_info)->sBlk; + + TRACE("Entered squashfs_statfs\n"); + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sBlk->block_size; + buf->f_blocks = ((sBlk->bytes_used - 1) >> sBlk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sBlk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes; + int block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %d, start block %x, offset %x\n", + page->index, SQUASHFS_I(inode)->start_block, SQUASHFS_I(inode)->offset); + + for(length = 0; length < index; length += bytes) { + if(!(bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, offset, + PAGE_CACHE_SIZE, &block, &offset))) { + ERROR("Unable to read symbolic link [%x:%x]\n", block, offset); + goto skip_read; + } + } + + if(length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + bytes = (inode->i_size - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : inode->i_size - length; + if(!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, bytes, &block, &offset))) + ERROR("Unable to read symbolic link [%x:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +#define SIZE 256 + +#ifdef SQUASHFS_1_0_COMPATIBILITY +static unsigned int read_blocklist_1(struct inode *inode, int index, int readahead_blks, + char *block_list, char **block_p, unsigned int *bsize) +{ + squashfs_sb_info *msBlk = (squashfs_sb_info *)inode->i_sb->s_fs_info; + unsigned short *block_listp; + int i = 0; + int block_ptr = SQUASHFS_I(inode)->block_list_start; + int offset = SQUASHFS_I(inode)->offset; + int block = SQUASHFS_I(inode)->start_block; + + for(;;) { + int blocks = (index + readahead_blks - i); + if(blocks > (SIZE >> 1)) { + if((index - i) <= (SIZE >> 1)) + blocks = index - i; + else + blocks = SIZE >> 1; + } + + if(msBlk->swap) { + unsigned char sblock_list[SIZE]; + if(!squashfs_get_cached_block(inode->i_sb, (char *) sblock_list, block_ptr, offset, blocks << 1, &block_ptr, &offset)) { + ERROR("Unable to read block list [%d:%x]\n", block_ptr, offset); + return 0; + } + SQUASHFS_SWAP_SHORTS(((unsigned short *)block_list), ((unsigned short *)sblock_list), blocks); + } else + if(!squashfs_get_cached_block(inode->i_sb, (char *) block_list, block_ptr, offset, blocks << 1, &block_ptr, &offset)) { + ERROR("Unable to read block list [%d:%x]\n", block_ptr, offset); + return 0; + } + for(block_listp = (unsigned short *) block_list; i < index && blocks; i ++, block_listp ++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE(*block_listp); + if(blocks >= readahead_blks) + break; + } + + if(bsize) + *bsize = SQUASHFS_COMPRESSED_SIZE(*block_listp) | (!SQUASHFS_COMPRESSED(*block_listp) ? SQUASHFS_COMPRESSED_BIT_BLOCK : 0); + else + (unsigned short *) *block_p = block_listp; + return block; +} +#endif + + +static unsigned int read_blocklist(struct inode *inode, int index, int readahead_blks, + char *block_list, char **block_p, unsigned int *bsize) +{ + squashfs_sb_info *msBlk = (squashfs_sb_info *)inode->i_sb->s_fs_info; + unsigned int *block_listp; + int i = 0; + int block_ptr = SQUASHFS_I(inode)->block_list_start; + int offset = SQUASHFS_I(inode)->offset; + int block = SQUASHFS_I(inode)->start_block; + + for(;;) { + int blocks = (index + readahead_blks - i); + if(blocks > (SIZE >> 2)) { + if((index - i) <= (SIZE >> 2)) + blocks = index - i; + else + blocks = SIZE >> 2; + } + + if(msBlk->swap) { + unsigned char sblock_list[SIZE]; + if(!squashfs_get_cached_block(inode->i_sb, (char *) sblock_list, block_ptr, offset, blocks << 2, &block_ptr, &offset)) { + ERROR("Unable to read block list [%d:%x]\n", block_ptr, offset); + return 0; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), ((unsigned int *)sblock_list), blocks); + } else + if(!squashfs_get_cached_block(inode->i_sb, (char *) block_list, block_ptr, offset, blocks << 2, &block_ptr, &offset)) { + ERROR("Unable to read block list [%d:%x]\n", block_ptr, offset); + return 0; + } + for(block_listp = (unsigned int *) block_list; i < index && blocks; i ++, block_listp ++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + if(blocks >= readahead_blks) + break; + } + + *bsize = *block_listp; + return block; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + squashfs_sb_info *msBlk = (squashfs_sb_info *)inode->i_sb->s_fs_info; + squashfs_super_block *sBlk = &msBlk->sBlk; + unsigned char block_list[SIZE]; + unsigned int bsize, block, i = 0, bytes = 0, byte_offset = 0; + int index = page->index >> (sBlk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr = kmap(page); + struct squashfs_fragment_cache *fragment; + char *data_ptr = msBlk->read_page; + + int mask = (1 << (sBlk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + + TRACE("Entered squashfs_readpage, page index %x, start block %x\n", (unsigned int) page->index, + SQUASHFS_I(inode)->start_block); + + if(page->index >= ((inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)) + goto skip_read; + + if(SQUASHFS_I(inode)->fragment_start_block == SQUASHFS_INVALID_BLK || index < (inode->i_size >> sBlk->block_log)) { + if((block = (msBlk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize)) == 0) + goto skip_read; + + down(&msBlk->read_page_mutex); + if(!(bytes = read_data(inode->i_sb, msBlk->read_page, block, bsize, 1, NULL))) { + ERROR("Unable to read page, block %x, size %x\n", block, bsize); + up(&msBlk->read_page_mutex); + goto skip_read; + } + } else { + if((fragment = get_cached_fragment(inode->i_sb, SQUASHFS_I(inode)->fragment_start_block, SQUASHFS_I(inode)->fragment_size)) == NULL) { + ERROR("Unable to read page, block %x, size %x\n", SQUASHFS_I(inode)->fragment_start_block, (int) SQUASHFS_I(inode)->fragment_size); + goto skip_read; + } + bytes = SQUASHFS_I(inode)->fragment_offset + (inode->i_size & (sBlk->block_size - 1)); + byte_offset = SQUASHFS_I(inode)->fragment_offset; + data_ptr = fragment->data; + } + + for(i = start_index; i <= end_index && byte_offset < bytes; i++, byte_offset += PAGE_CACHE_SIZE) { + struct page *push_page; + int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : bytes - byte_offset; + + TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n", bytes, i, byte_offset, available_bytes); + + if(i == page->index) { + memcpy(pageaddr, data_ptr + byte_offset, available_bytes); + memset(pageaddr + available_bytes, 0, PAGE_CACHE_SIZE - available_bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + } else if((push_page = grab_cache_page_nowait(page->mapping, i))) { + void *pageaddr = kmap(push_page); + memcpy(pageaddr, data_ptr + byte_offset, available_bytes); + memset(pageaddr + available_bytes, 0, PAGE_CACHE_SIZE - available_bytes); + kunmap(push_page); + flush_dcache_page(push_page); + SetPageUptodate(push_page); + unlock_page(push_page); + page_cache_release(push_page); + } + } + + if(SQUASHFS_I(inode)->fragment_start_block == SQUASHFS_INVALID_BLK || index < (inode->i_size >> sBlk->block_log)) + up(&msBlk->read_page_mutex); + else + release_cached_fragment(msBlk, fragment); + + return 0; + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +static int squashfs_readpage4K(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + squashfs_sb_info *msBlk = (squashfs_sb_info *)inode->i_sb->s_fs_info; + squashfs_super_block *sBlk = &msBlk->sBlk; + unsigned char block_list[SIZE]; + unsigned int bsize, block, bytes = 0; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_readpage4K, page index %x, start block %x\n", (unsigned int) page->index, + SQUASHFS_I(inode)->start_block); + + if(page->index >= ((inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)) + goto skip_read; + + if(page->index < (inode->i_size >> sBlk->block_log)) { + block = (msBlk->read_blocklist)(inode, page->index, 1, block_list, NULL, &bsize); + + if(!(bytes = read_data(inode->i_sb, pageaddr, block, bsize, 1, NULL))) + ERROR("Unable to read page, block %x, size %x\n", block, bsize); + } else { + struct squashfs_fragment_cache *fragment; + + if((fragment = get_cached_fragment(inode->i_sb, SQUASHFS_I(inode)->fragment_start_block, SQUASHFS_I(inode)->fragment_size)) == NULL) + ERROR("Unable to read page, block %x, size %x\n", SQUASHFS_I(inode)->fragment_start_block, (int) SQUASHFS_I(inode)->fragment_size); + else { + bytes = inode->i_size & (sBlk->block_size - 1); + memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->fragment_offset, bytes); + release_cached_fragment(msBlk, fragment); + } + } + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +#ifdef SQUASHFS_1_0_COMPATIBILITY +static int squashfs_readpage_lessthan4K(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + squashfs_sb_info *msBlk = (squashfs_sb_info *)inode->i_sb->s_fs_info; + squashfs_super_block *sBlk = &msBlk->sBlk; + unsigned char block_list[SIZE]; + unsigned short *block_listp, block, bytes = 0; + int index = page->index << (PAGE_CACHE_SHIFT - sBlk->block_log); + int file_blocks = ((inode->i_size - 1) >> sBlk->block_log) + 1; + int readahead_blks = 1 << (PAGE_CACHE_SHIFT - sBlk->block_log); + void *pageaddr = kmap(page); + + int i_end = index + (1 << (PAGE_CACHE_SHIFT - sBlk->block_log)); + int byte; + + TRACE("Entered squashfs_readpage_lessthan4K, page index %x, start block %x\n", (unsigned int) page->index, + SQUASHFS_I(inode)->start_block); + + block = read_blocklist_1(inode, index, readahead_blks, block_list, (char **) &block_listp, NULL); + + if(i_end > file_blocks) + i_end = file_blocks; + + while(index < i_end) { + if(!(byte = read_data(inode->i_sb, pageaddr, block, *block_listp, 0, NULL))) { + ERROR("Unable to read page, block %x, size %x\n", block, *block_listp); + goto skip_read; + } + block += SQUASHFS_COMPRESSED_SIZE(*block_listp); + pageaddr += byte; + bytes += byte; + index ++; + block_listp ++; + } + +skip_read: + memset(pageaddr, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} +#endif + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + squashfs_sb_info *msBlk = (squashfs_sb_info *)i->i_sb->s_fs_info; + squashfs_super_block *sBlk = &msBlk->sBlk; + int next_block = SQUASHFS_I(i)->start_block + sBlk->directory_table_start, next_offset = + SQUASHFS_I(i)->offset, length = 0, dirs_read = 0, dir_count; + squashfs_dir_header dirh; + char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; + squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; + + TRACE("Entered squashfs_readdir [%x:%x]\n", next_block, next_offset); + + lock_kernel(); + while(length < i->i_size) { + /* read directory header */ + if(msBlk->swap) { + squashfs_dir_header sdirh; + if(!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if(!squashfs_get_cached_block(i->i_sb, (char *) &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while(dir_count--) { + if(msBlk->swap) { + squashfs_dir_entry sdire; + if(!squashfs_get_cached_block(i->i_sb, (char *) &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if(!squashfs_get_cached_block(i->i_sb, (char *) dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + length += sizeof(*dire); + } + + if(!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + length += dire->size + 1; + + if(file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", (unsigned int) dirent, + dire->name, dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, squashfs_filetype_table[dire->type]); + + if(filldir(dirent, dire->name, dire->size + 1, file->f_pos, SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset), squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + unlock_kernel(); + return dirs_read; + } + + file->f_pos = length; + dirs_read ++; + } + } + + unlock_kernel(); + return dirs_read; + +failed_read: + unlock_kernel(); + ERROR("Unable to read directory block [%x:%x]\n", next_block, next_offset); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, struct nameidata *nd) +{ + const char *name =dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + squashfs_sb_info *msBlk = (squashfs_sb_info *)i->i_sb->s_fs_info; + squashfs_super_block *sBlk = &msBlk->sBlk; + int next_block = SQUASHFS_I(i)->start_block + sBlk->directory_table_start, next_offset = + SQUASHFS_I(i)->offset, length = 0, dir_count; + squashfs_dir_header dirh; + char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN]; + squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; + + TRACE("Entered squashfs_lookup [%x:%x]\n", next_block, next_offset); + + lock_kernel(); + while(length < i->i_size) { + /* read directory header */ + if(msBlk->swap) { + squashfs_dir_header sdirh; + if(!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, next_block, next_offset, + sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if(!squashfs_get_cached_block(i->i_sb, (char *) &dirh, next_block, next_offset, + sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while(dir_count--) { + if(msBlk->swap) { + squashfs_dir_entry sdire; + if(!squashfs_get_cached_block(i->i_sb, (char *) &sdire, + next_block,next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if(!squashfs_get_cached_block(i->i_sb, (char *) dire, + next_block,next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + length += sizeof(*dire); + } + + if(!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + length += dire->size + 1; + + if((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode ino = SQUASHFS_MKINODE(dirh.start_block, dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode %x:%x\n", + name, dirh.start_block, dire->offset); + + inode = (msBlk->iget)(i->i_sb, ino); + + goto exit_loop; + } + } + } + +exit_loop: + d_add(dentry, inode); + unlock_kernel(); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%x:%x]\n", next_block, next_offset); + goto exit_loop; +} + + +static void squashfs_put_super(struct super_block *s) +{ + if(s->s_fs_info) { + squashfs_sb_info *sbi = (squashfs_sb_info *) s->s_fs_info; + if(sbi->block_cache) kfree(sbi->block_cache); + if(sbi->read_data) kfree(sbi->read_data); + if(sbi->read_page) kfree(sbi->read_page); + if(sbi->uid) kfree(sbi->uid); + if(sbi->fragment) kfree(sbi->fragment); + if(sbi->fragment_index) kfree(sbi->fragment_index); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static struct super_block *squashfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if(err) + return err; + +#ifdef CONFIG_ZLIB_FS_INFLATE + if(!(stream.workspace = (char *) vmalloc(zlib_inflate_workspacesize()))) { + ERROR("Failed to allocate zlib workspace\n"); + destroy_inodecache(); + return -ENOMEM; + } +#endif + + if((err = register_filesystem(&squashfs_fs_type))) { +#ifdef CONFIG_ZLIB_FS_INFLATE + vfree(stream.workspace); +#endif + destroy_inodecache(); + } + + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ +#ifdef CONFIG_ZLIB_FS_INFLATE + vfree(stream.workspace); +#endif + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static kmem_cache_t * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = (struct squashfs_inode_info *)kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL); + if (!ei) + return NULL; + return &ei->vfs_inode; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = (struct squashfs_inode_info *) foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == + SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + + +static int init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), + 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + init_once, NULL); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + if (kmem_cache_destroy(squashfs_inode_cachep)) + printk(KERN_INFO "squashfs_inode_cache: not all structures were freed\n"); +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher "); +MODULE_LICENSE("GPL"); diff -Naur linux-mips-2.6.8.1-orig/fs/squashfs/Makefile linux-mips-2.6.8.1-bcm/fs/squashfs/Makefile --- linux-mips-2.6.8.1-orig/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/fs/squashfs/Makefile 2006-12-20 18:46:45.000000000 +0100 @@ -0,0 +1,20 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o + +#squashfs-objs := inode.o + +# CONFIG_MIPS_BRCM Begin Broadcom changed code. + +ifdef CONFIG_ZLIB_FS_INFLATE +squashfs-objs := inode.o +else +ifdef CONFIG_LZMA_FS_INFLATE +squashfs-objs := inode.o ../inflate_lzma/7zlzma.o ../inflate_lzma/LZMADecoder.o ../inflate_lzma/IInOutStreams.o +endif +endif + +# CONFIG_MIPS_BRCM End Broadcom changed code. + diff -Naur linux-mips-2.6.8.1-orig/include/asm-mips/addrspace.h linux-mips-2.6.8.1-bcm/include/asm-mips/addrspace.h --- linux-mips-2.6.8.1-orig/include/asm-mips/addrspace.h 2003-11-30 02:52:25.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/asm-mips/addrspace.h 2006-12-20 18:43:47.000000000 +0100 @@ -11,7 +11,13 @@ #define _ASM_ADDRSPACE_H #include +#ifdef __KERNEL__ +#if defined(CONFIG_BCM_ENDPOINT_MODULE) +#include +#else #include +#endif +#endif /* * Configure language diff -Naur linux-mips-2.6.8.1-orig/include/asm-mips/bitops.h linux-mips-2.6.8.1-bcm/include/asm-mips/bitops.h --- linux-mips-2.6.8.1-orig/include/asm-mips/bitops.h 2004-08-19 11:54:23.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/asm-mips/bitops.h 2006-12-20 18:43:47.000000000 +0100 @@ -14,6 +14,7 @@ #include #include /* sigh ... */ #include +#include #if (_MIPS_SZLONG == 32) #define SZLONG_LOG 5 diff -Naur linux-mips-2.6.8.1-orig/include/asm-mips/bootinfo.h linux-mips-2.6.8.1-bcm/include/asm-mips/bootinfo.h --- linux-mips-2.6.8.1-orig/include/asm-mips/bootinfo.h 2004-06-26 17:15:24.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/asm-mips/bootinfo.h 2006-12-20 18:43:47.000000000 +0100 @@ -210,6 +210,16 @@ #define MACH_GROUP_TITAN 22 /* PMC-Sierra Titan */ #define MACH_TITAN_YOSEMITE 1 /* PMC-Sierra Yosemite */ +#if defined(CONFIG_MIPS_BRCM) +/* + * Valid machtype for group BRCM + */ +#define MACH_GROUP_BRCM 23 /* Broadcom boards */ +#define MACH_BCM96338 0 +#define MACH_BCM96348 1 +#define MACH_BCM96358 2 +#endif + #define CL_SIZE COMMAND_LINE_SIZE const char *get_system_type(void); diff -Naur linux-mips-2.6.8.1-orig/include/asm-mips/cpu.h linux-mips-2.6.8.1-bcm/include/asm-mips/cpu.h --- linux-mips-2.6.8.1-orig/include/asm-mips/cpu.h 2004-01-19 19:23:16.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/asm-mips/cpu.h 2006-12-20 18:43:47.000000000 +0100 @@ -71,6 +71,11 @@ #define PRID_IMP_4KEMPR2 0x9100 #define PRID_IMP_4KSD 0x9200 #define PRID_IMP_24K 0x9300 +#if defined(CONFIG_MIPS_BRCM) +#define PRID_IMP_BCM6338 0x9000 +#define PRID_IMP_BCM6348 0x9100 +#define PRID_IMP_BCM6358 0xA000 +#endif #define PRID_IMP_UNKNOWN 0xff00 @@ -177,7 +182,14 @@ #define CPU_VR4133 56 #define CPU_AU1550 57 #define CPU_24K 58 +#if defined(CONFIG_MIPS_BRCM) +#define CPU_BCM6338 59 +#define CPU_BCM6348 60 +#define CPU_BCM6358 61 +#define CPU_LAST 61 +#else #define CPU_LAST 58 +#endif /* * ISA Level encodings diff -Naur linux-mips-2.6.8.1-orig/include/asm-mips/mach-bcm963xx/cpu-feature-overrides.h linux-mips-2.6.8.1-bcm/include/asm-mips/mach-bcm963xx/cpu-feature-overrides.h --- linux-mips-2.6.8.1-orig/include/asm-mips/mach-bcm963xx/cpu-feature-overrides.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/asm-mips/mach-bcm963xx/cpu-feature-overrides.h 2006-12-20 18:43:44.000000000 +0100 @@ -0,0 +1,40 @@ +#ifndef __ASM_MACH_BCM963XX_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_BCM963XX_CPU_FEATURE_OVERRIDES_H + +#define cpu_has_tlb 1 +#define cpu_has_4kex 4 +#define cpu_has_4ktlb 8 +#define cpu_has_fpu 0 +#define cpu_has_32fpr 0 +#define cpu_has_counter 0x40 +#define cpu_has_watch 0 +#define cpu_has_mips16 0 +#if defined(CONFIG_BCM96358) +// Use IVEC for TP0 +#define cpu_has_divec 0 +#else +#define cpu_has_divec 0x200 +#endif +#define cpu_has_vce 0 +#define cpu_has_cache_cdex_p 0 +#define cpu_has_cache_cdex_s 0 +#define cpu_has_prefetch 0 +#define cpu_has_mcheck 0x2000 +#define cpu_has_ejtag 0x4000 +#define cpu_has_llsc 0x10000 +#define cpu_has_vtag_icache 0 +#define cpu_has_ic_fills_f_dc 0 + +#define cpu_has_nofpuex 0 +#define cpu_has_64bits 0 +#define cpu_has_64bit_zero_reg 0 +#define cpu_has_64bit_gp_regs 0 +#define cpu_has_64bit_addresses 0 + +#define cpu_has_subset_pcaches 0 + +#define cpu_dcache_line_size() 16 +#define cpu_icache_line_size() 16 +#define cpu_scache_line_size() 0 + +#endif /* __ASM_MACH_BCM963XX_CPU_FEATURE_OVERRIDES_H */ diff -Naur linux-mips-2.6.8.1-orig/include/asm-mips/mach-generic/param.h linux-mips-2.6.8.1-bcm/include/asm-mips/mach-generic/param.h --- linux-mips-2.6.8.1-orig/include/asm-mips/mach-generic/param.h 2003-11-18 02:17:48.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/asm-mips/mach-generic/param.h 2006-12-20 18:43:40.000000000 +0100 @@ -8,6 +8,14 @@ #ifndef __ASM_MACH_GENERIC_PARAM_H #define __ASM_MACH_GENERIC_PARAM_H +/* Header file config.h, which defines CONFIG_MIPS_BRCM, is not included by + * all files that include this header file. Therefore, unconditionally + * define HZ to 200. + */ +#if 1 /* defined(CONFIG_MIPS_BRCM) */ +#define HZ 200 /* Internal kernel timer frequency */ +#else #define HZ 1000 /* Internal kernel timer frequency */ +#endif #endif /* __ASM_MACH_GENERIC_PARAM_H */ diff -Naur linux-mips-2.6.8.1-orig/include/asm-mips/mipsregs.h linux-mips-2.6.8.1-bcm/include/asm-mips/mipsregs.h --- linux-mips-2.6.8.1-orig/include/asm-mips/mipsregs.h 2004-05-19 18:02:20.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/asm-mips/mipsregs.h 2006-12-20 18:43:47.000000000 +0100 @@ -747,9 +747,11 @@ #define read_c0_status() __read_32bit_c0_register($12, 0) #define write_c0_status(val) __write_32bit_c0_register($12, 0, val) +#define read_c0_status_sel(sel) __read_32bit_c0_register($12, sel) #define read_c0_cause() __read_32bit_c0_register($13, 0) #define write_c0_cause(val) __write_32bit_c0_register($13, 0, val) +#define read_c0_cause_sel(sel) __read_32bit_c0_register($13, sel) #define read_c0_epc() __read_ulong_c0_register($14, 0) #define write_c0_epc(val) __write_ulong_c0_register($14, 0, val) @@ -859,6 +861,9 @@ #define read_c0_errorepc() __read_ulong_c0_register($30, 0) #define write_c0_errorepc(val) __write_ulong_c0_register($30, 0, val) +#define read_c0_desave() __read_ulong_c0_register($31, 0) +#define write_c0_desave(val) __write_ulong_c0_register($31, 0, val) + /* * Macros to access the floating point coprocessor control registers */ diff -Naur linux-mips-2.6.8.1-orig/include/asm-mips/page.h linux-mips-2.6.8.1-bcm/include/asm-mips/page.h --- linux-mips-2.6.8.1-orig/include/asm-mips/page.h 2004-08-20 14:02:18.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/asm-mips/page.h 2006-12-20 18:43:47.000000000 +0100 @@ -13,7 +13,11 @@ #ifdef __KERNEL__ +#if defined(CONFIG_BCM_ENDPOINT_MODULE) +#include +#else #include +#endif #endif diff -Naur linux-mips-2.6.8.1-orig/include/asm-mips/param.h linux-mips-2.6.8.1-bcm/include/asm-mips/param.h --- linux-mips-2.6.8.1-orig/include/asm-mips/param.h 2004-03-11 17:46:57.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/asm-mips/param.h 2006-12-20 18:43:47.000000000 +0100 @@ -12,7 +12,9 @@ #ifdef __KERNEL__ # include /* Internal kernel timer frequency */ + # define USER_HZ 100 /* .. some user interfaces are in "ticks" */ + # define CLOCKS_PER_SEC (USER_HZ) /* like times() */ #endif diff -Naur linux-mips-2.6.8.1-orig/include/asm-mips/timex.h linux-mips-2.6.8.1-bcm/include/asm-mips/timex.h --- linux-mips-2.6.8.1-orig/include/asm-mips/timex.h 2003-11-18 02:17:47.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/asm-mips/timex.h 2006-12-20 18:43:47.000000000 +0100 @@ -31,7 +31,11 @@ * no reason to make this a separate architecture. */ +#if defined(CONFIG_BCM_ENDPOINT_MODULE) +#include +#else #include +#endif /* * Standard way to access the cycle counter. diff -Naur linux-mips-2.6.8.1-orig/include/linux/atmbr2684.h linux-mips-2.6.8.1-bcm/include/linux/atmbr2684.h --- linux-mips-2.6.8.1-orig/include/linux/atmbr2684.h 2003-06-05 20:24:11.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/atmbr2684.h 2006-12-20 18:45:06.000000000 +0100 @@ -78,6 +78,13 @@ __u8 vpn_id[7]; int send_padding; /* unsupported */ int min_size; /* we will pad smaller packets than this */ +#if defined(CONFIG_MIPS_BRCM) +#define FILTER_PPPOE 1 + int proto_filter; /* protocol filter flag, current only PPPoE */ + unsigned short vlan_id; /* vlan id (0-4096) */ + +#endif + }; /* diff -Naur linux-mips-2.6.8.1-orig/include/linux/atmdev.h linux-mips-2.6.8.1-bcm/include/linux/atmdev.h --- linux-mips-2.6.8.1-orig/include/linux/atmdev.h 2004-08-06 02:33:31.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/atmdev.h 2006-12-20 18:45:06.000000000 +0100 @@ -104,6 +104,9 @@ #define ATM_BACKEND_RAW 0 #define ATM_BACKEND_PPP 1 /* PPPoATM - RFC2364 */ #define ATM_BACKEND_BR2684 2 /* Bridged RFC1483/2684 */ +#if defined(CONFIG_MIPS_BRCM) +#define ATM_BACKEND_RT2684 3 /* Routed RFC1483/2684 */ +#endif /* for ATM_GETTYPE */ #define ATM_ITFTYP_LEN 8 /* maximum length of interface type name */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/atm.h linux-mips-2.6.8.1-bcm/include/linux/atm.h --- linux-mips-2.6.8.1-orig/include/linux/atm.h 2004-06-26 17:15:25.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/atm.h 2006-12-20 18:45:06.000000000 +0100 @@ -48,6 +48,9 @@ #define ATM_AAL2 2 /* AAL2 (VBR) */ #define ATM_AAL34 3 /* AAL3/4 (data) */ #define ATM_AAL5 5 /* AAL5 (data) */ +#if defined(CONFIG_MIPS_BRCM) +#define ATM_BCM_AAL0 14 /* "raw" ATM cells */ +#endif /* * socket option name coding functions diff -Naur linux-mips-2.6.8.1-orig/include/linux/atmrt2684.h linux-mips-2.6.8.1-bcm/include/linux/atmrt2684.h --- linux-mips-2.6.8.1-orig/include/linux/atmrt2684.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/atmrt2684.h 2006-12-20 18:45:06.000000000 +0100 @@ -0,0 +1,48 @@ +#ifndef _LINUX_ATMRT2684_H +#define _LINUX_ATMRT2684_H + +#include +#include /* For IFNAMSIZ */ + +#define RT2684_ENCAPS_NULL (0) /* VC-mux */ +#define RT2684_ENCAPS_LLC (1) +#define RT2684_ENCAPS_AUTODETECT (2) /* Unsuported */ + +/* + * This is for the ATM_NEWBACKENDIF call - these are like socket families: + * the first element of the structure is the backend number and the rest + * is per-backend specific + */ +struct atm_newif_rt2684 { + atm_backend_t backend_num; /* ATM_BACKEND_RT2684 */ + char ifname[IFNAMSIZ]; +}; + +/* + * This structure is used to specify a rt2684 interface - either by a + * positive integer (returned by ATM_NEWBACKENDIF) or the interfaces name + */ +#define RT2684_FIND_BYNOTHING (0) +#define RT2684_FIND_BYNUM (1) +#define RT2684_FIND_BYIFNAME (2) +struct rt2684_if_spec { + int method; /* RT2684_FIND_* */ + union { + char ifname[IFNAMSIZ]; + int devnum; + } spec; +}; + +/* + * This is for the ATM_SETBACKEND call - these are like socket families: + * the first element of the structure is the backend number and the rest + * is per-backend specific + */ +struct atm_backend_rt2684 { + atm_backend_t backend_num; /* ATM_BACKEND_RT2684 */ + struct rt2684_if_spec ifspec; + unsigned char encaps; /* RT2684_ENCAPS_* */ +}; + + +#endif /* _LINUX_ATMRT2684_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/if_arp.h linux-mips-2.6.8.1-bcm/include/linux/if_arp.h --- linux-mips-2.6.8.1-orig/include/linux/if_arp.h 2004-06-09 16:12:13.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/if_arp.h 2006-12-20 18:45:06.000000000 +0100 @@ -40,6 +40,10 @@ #define ARPHRD_METRICOM 23 /* Metricom STRIP (new IANA id) */ #define ARPHRD_IEEE1394 24 /* IEEE 1394 IPv4 - RFC 2734 */ #define ARPHRD_EUI64 27 /* EUI-64 */ +#if defined(CONFIG_MIPS_BRCM) +#define ARPHRD_CPCS 28 /* CPCS */ +#define ARPHRD_DSL 29 /* ADSL */ +#endif #define ARPHRD_INFINIBAND 32 /* InfiniBand */ /* Dummy types for non ARP hardware */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/mmzone.h linux-mips-2.6.8.1-bcm/include/linux/mmzone.h --- linux-mips-2.6.8.1-orig/include/linux/mmzone.h 2004-08-13 09:18:55.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/mmzone.h 2006-12-20 18:45:05.000000000 +0100 @@ -232,7 +232,13 @@ * go. A value of 12 for DEF_PRIORITY implies that we will scan 1/4096th of the * queues ("queue_length >> 12") during an aging round. */ + +#if 0 #define DEF_PRIORITY 12 +#else +/* No swap disk, not possible to swap out pages. Start from highest priority to scan more area for free pages*/ +#define DEF_PRIORITY 0 +#endif /* * One allocation request operates on a zonelist. A zonelist diff -Naur linux-mips-2.6.8.1-orig/include/linux/module.h linux-mips-2.6.8.1-bcm/include/linux/module.h --- linux-mips-2.6.8.1-orig/include/linux/module.h 2004-06-28 23:04:16.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/module.h 2006-12-20 18:45:06.000000000 +0100 @@ -188,7 +188,7 @@ __EXPORT_SYMBOL(sym, "") #define EXPORT_SYMBOL_GPL(sym) \ - __EXPORT_SYMBOL(sym, "_gpl") + __EXPORT_SYMBOL(sym, "") #endif @@ -548,7 +548,7 @@ #ifdef MODULE /* DEPRECATED: Do not use. */ #define MODULE_PARM(var,type) \ -struct obsolete_modparm __parm_##var __attribute__((section("__obsparm"))) = \ +struct obsolete_modparm __parm_##var __attribute_used__ __attribute__((section("__obsparm"),unused)) = \ { __stringify(var), type }; static inline void __deprecated MOD_INC_USE_COUNT(struct module *module) diff -Naur linux-mips-2.6.8.1-orig/include/linux/mroute.h linux-mips-2.6.8.1-bcm/include/linux/mroute.h --- linux-mips-2.6.8.1-orig/include/linux/mroute.h 2004-06-09 16:12:13.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/mroute.h 2006-12-20 18:45:06.000000000 +0100 @@ -179,9 +179,10 @@ #define MFC_LINES 64 #ifdef __BIG_ENDIAN -#define MFC_HASH(a,b) ((((a)>>24)^((b)>>26))&(MFC_LINES-1)) +/* brcm IGMP Proxy */ +#define MFC_HASH(a,b,c) ((((a)>>24)^((b)>>26)+ (c) )&(MFC_LINES-1)) #else -#define MFC_HASH(a,b) (((a)^((b)>>2))&(MFC_LINES-1)) +#define MFC_HASH(a,b,c) (((a)^((b)>>2)+ (c) )&(MFC_LINES-1)) #endif #endif diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_bridge/ebt_ftos_t.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_bridge/ebt_ftos_t.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_bridge/ebt_ftos_t.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_bridge/ebt_ftos_t.h 2006-12-20 18:44:46.000000000 +0100 @@ -0,0 +1,12 @@ +#ifndef __LINUX_BRIDGE_EBT_FTOS_T_H +#define __LINUX_BRIDGE_EBT_FTOS_T_H + +struct ebt_ftos_t_info +{ + unsigned char ftos; + // EBT_ACCEPT, EBT_DROP or EBT_CONTINUE or EBT_RETURN + int target; +}; +#define EBT_FTOS_TARGET "ftos" + +#endif diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_bridge/ebt_time.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_bridge/ebt_time.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_bridge/ebt_time.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_bridge/ebt_time.h 2006-12-20 18:44:46.000000000 +0100 @@ -0,0 +1,14 @@ +#ifndef __LINUX_BRIDGE_EBT_TIME_H +#define __LINUX_BRIDGE_EBT_TIME_H + + +struct ebt_time_info { + u_int8_t days_match; /* 1 bit per day. -SMTWTFS */ + u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */ + u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */ + u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */ +}; + +#define EBT_TIME_MATCH "time" + +#endif /* __LINUX_BRIDGE_EBT_TIME_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_helpers.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_helpers.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_helpers.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_helpers.h 2006-12-20 18:45:06.000000000 +0100 @@ -0,0 +1,133 @@ +/* + * Helpers for netfiler modules. This file provides implementations for basic + * functions such as strncasecmp(), etc. + * + * gcc will warn for defined but unused functions, so we only include the + * functions requested. The following macros are used: + * NF_NEED_STRNCASECMP nf_strncasecmp() + * NF_NEED_STRTOU16 nf_strtou16() + * NF_NEED_STRTOU32 nf_strtou32() + */ +#ifndef _NETFILTER_HELPERS_H +#define _NETFILTER_HELPERS_H + +/* Only include these functions for kernel code. */ +#ifdef __KERNEL__ + +#include +#define iseol(c) ( (c) == '\r' || (c) == '\n' ) + +/* + * The standard strncasecmp() + */ +#ifdef NF_NEED_STRNCASECMP +static int +nf_strncasecmp(const char* s1, const char* s2, u_int32_t len) +{ + if (s1 == NULL || s2 == NULL) + { + if (s1 == NULL && s2 == NULL) + { + return 0; + } + return (s1 == NULL) ? -1 : 1; + } + while (len > 0 && tolower(*s1) == tolower(*s2)) + { + len--; + s1++; + s2++; + } + return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) ); +} +#endif /* NF_NEED_STRNCASECMP */ + +/* + * Parse a string containing a 16-bit unsigned integer. + * Returns the number of chars used, or zero if no number is found. + */ +#ifdef NF_NEED_STRTOU16 +static int +nf_strtou16(const char* pbuf, u_int16_t* pval) +{ + int n = 0; + + *pval = 0; + while (isdigit(pbuf[n])) + { + *pval = (*pval * 10) + (pbuf[n] - '0'); + n++; + } + + return n; +} +#endif /* NF_NEED_STRTOU16 */ + +/* + * Parse a string containing a 32-bit unsigned integer. + * Returns the number of chars used, or zero if no number is found. + */ +#ifdef NF_NEED_STRTOU32 +static int +nf_strtou32(const char* pbuf, u_int32_t* pval) +{ + int n = 0; + + *pval = 0; + while (pbuf[n] >= '0' && pbuf[n] <= '9') + { + *pval = (*pval * 10) + (pbuf[n] - '0'); + n++; + } + + return n; +} +#endif /* NF_NEED_STRTOU32 */ + +/* + * Given a buffer and length, advance to the next line and mark the current + * line. + */ +#ifdef NF_NEED_NEXTLINE +static int +nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) +{ + uint off = *poff; + uint physlen = 0; + + if (off >= len) + { + return 0; + } + + while (p[off] != '\n') + { + if (len-off <= 1) + { + return 0; + } + + physlen++; + off++; + } + + /* if we saw a crlf, physlen needs adjusted */ + if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') + { + physlen--; + } + + /* advance past the newline */ + off++; + + *plineoff = *poff; + *plinelen = physlen; + *poff = off; + + return 1; +} +#endif /* NF_NEED_NEXTLINE */ + +#endif /* __KERNEL__ */ + +#endif /* _NETFILTER_HELPERS_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_dtx8.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_dtx8.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_dtx8.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_dtx8.h 2006-12-20 18:45:03.000000000 +0100 @@ -0,0 +1,6 @@ +#define DTX8INITIAL 47624 +#define DTX8MIN 2300 +#define DTX8MAX 2400 +#define DTX8MAXEXPECTED (DTX8MAX - DTX8MIN +1) +#define MAXDTX8_PORTS 1 + diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_esp.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_esp.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_esp.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_esp.h 2006-12-20 18:45:03.000000000 +0100 @@ -0,0 +1,59 @@ +/***************************************************************************** +// +// Copyright (c) 2000-2002 Broadcom Corporation +// All Rights Reserved +// No portions of this material may be reproduced in any form without the +// written permission of: +// Broadcom Corporation +// 16215 Alton Parkway +// Irvine, California 92619 +// All information contained in this document is Broadcom Corporation +// company private, proprietary, and trade secret. +// +****************************************************************************** +// +// Filename: ip_conntrack_esp.h +// Author: Pavan Kumar +// Creation Date: 05/27/04 +// +// Description: +// Implements the ESP ALG connectiontracking data structures. +// +*****************************************************************************/ +#ifndef _IP_CONNTRACK_ESP_H +#define _IP_CONNTRACK_ESP_H +/* FTP tracking. */ + +#ifndef __KERNEL__ +#error Only in kernel. +#endif + +#include + +/* Protects ftp part of conntracks */ +DECLARE_LOCK_EXTERN(ip_esp_lock); + +struct esphdr { + u_int32_t spi; + u_int32_t seq; +}; + +/* This structure is per expected connection */ +struct ip_ct_esp_expect +{ + /* We record spi and source IP address: all in + * host order. */ + + u_int32_t spi; /* Security Parameter Identifier */ + u_int32_t saddr; /* source IP address in the orig dir */ + u_int32_t daddr; /* remote IP address in the orig dir */ +}; + +/* This structure exists only once per master */ +struct ip_ct_esp_master { + u_int32_t spi; + u_int32_t saddr; + u_int32_t daddr; +}; + +#endif /* _IP_CONNTRACK_ESP_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack.h 2004-06-26 17:15:26.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack.h 2006-12-20 18:45:03.000000000 +0100 @@ -51,29 +51,50 @@ #include #include +#include +#ifdef __KERNEL__ +#include +#endif /* per conntrack: protocol private data */ union ip_conntrack_proto { /* insert conntrack proto private data here */ + struct ip_ct_gre gre; struct ip_ct_tcp tcp; struct ip_ct_icmp icmp; }; union ip_conntrack_expect_proto { /* insert expect proto private data here */ + struct ip_ct_gre_expect gre; }; /* Add protocol helper include file here */ +#include +#include #include #include #include +#if defined(CONFIG_IP_NF_RTSP) || defined(CONFIG_IP_NF_RTSP_MODULE) +#include +#endif +#ifdef __KERNEL__ +#include +#endif + + /* per expectation: application helper private data */ union ip_conntrack_expect_help { /* insert conntrack helper private data (expect) here */ + struct ip_ct_pptp_expect exp_pptp_info; + struct ip_ct_h225_expect exp_h225_info; struct ip_ct_amanda_expect exp_amanda_info; struct ip_ct_ftp_expect exp_ftp_info; struct ip_ct_irc_expect exp_irc_info; +#if defined(CONFIG_IP_NF_RTSP) || defined(CONFIG_IP_NF_RTSP_MODULE) + struct ip_ct_rtsp_expect exp_rtsp_info; +#endif #ifdef CONFIG_IP_NF_NAT_NEEDED union { @@ -85,16 +106,40 @@ /* per conntrack: application helper private data */ union ip_conntrack_help { /* insert conntrack helper private data (master) here */ + struct ip_ct_pptp_master ct_pptp_info; + struct ip_ct_h225_master ct_h225_info; struct ip_ct_ftp_master ct_ftp_info; struct ip_ct_irc_master ct_irc_info; +#if defined(CONFIG_IP_NF_RTSP) || defined(CONFIG_IP_NF_RTSP_MODULE) + struct ip_ct_rtsp_master ct_rtsp_info; +#endif + +#ifdef __KERNEL__ + struct ip_ct_esp_master ct_esp_info; + struct ip_ct_ipsec_master ct_ipsec_info; +#endif + }; #ifdef CONFIG_IP_NF_NAT_NEEDED #include +#include +#ifdef __KERNEL__ +#include +#include +#include +#endif + /* per conntrack: nat application helper private data */ union ip_conntrack_nat_help { /* insert nat helper private data here */ + struct ip_nat_pptp nat_pptp_info; +#ifdef __KERNEL__ + struct ip_nat_esp_info esp_info; + struct ip_nat_ipsec_info ipsec_info; +#endif + }; #endif @@ -204,9 +249,16 @@ defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE) int masq_index; #endif +#if defined(CONFIG_IP_NF_RTSP) || defined(CONFIG_IP_NF_RTSP_MODULE) + struct ip_nat_rtsp_info rtsp_info; +#endif } nat; #endif /* CONFIG_IP_NF_NAT_NEEDED */ +#if defined(CONFIG_IP_NF_CONNTRACK_MARK) + unsigned long mark; +#endif + }; /* get master conntrack via master expectation */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_h323.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_h323.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2006-12-20 18:45:03.000000000 +0100 @@ -0,0 +1,31 @@ +#ifndef _IP_CONNTRACK_H323_H +#define _IP_CONNTRACK_H323_H +/* H.323 connection tracking. */ + +#ifdef __KERNEL__ +/* Protects H.323 related data */ +#include +DECLARE_LOCK_EXTERN(ip_h323_lock); +#endif + +/* Default H.225 port */ +#define H225_PORT 1720 + +/* This structure is per expected connection */ +struct ip_ct_h225_expect { + u_int16_t port; /* Port of the H.225 helper/RTCP/RTP channel */ + enum ip_conntrack_dir dir; /* Direction of the original connection */ + unsigned int offset; /* offset of the address in the payload */ +}; + +/* This structure exists only once per master */ +struct ip_ct_h225_master { + int is_h225; /* H.225 or H.245 connection */ +#ifdef CONFIG_IP_NF_NAT_NEEDED + enum ip_conntrack_dir dir; /* Direction of the original connection */ + u_int32_t seq[IP_CT_DIR_MAX]; /* Exceptional packet mangling for signal addressess... */ + unsigned int offset[IP_CT_DIR_MAX]; /* ...and the offset of the addresses in the payload */ +#endif +}; + +#endif /* _IP_CONNTRACK_H323_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_ipsec.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_ipsec.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_ipsec.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_ipsec.h 2006-12-20 18:45:03.000000000 +0100 @@ -0,0 +1,61 @@ +/***************************************************************************** +// +// Copyright (c) 2000-2002 Broadcom Corporation +// All Rights Reserved +// No portions of this material may be reproduced in any form without the +// written permission of: +// Broadcom Corporation +// 16215 Alton Parkway +// Irvine, California 92619 +// All information contained in this document is Broadcom Corporation +// company private, proprietary, and trade secret. +// +****************************************************************************** +// +// Filename: ip_conntrack_ipsec.h +// Author: Pavan Kumar +// Creation Date: 05/27/04 +// +// Description: +// Implements the IPSec ALG connectiontracking data structures. +// +*****************************************************************************/ +#ifndef _IP_CONNTRACK_IPSEC_H +#define _IP_CONNTRACK_IPSEC_H +/* FTP tracking. */ + +#ifndef __KERNEL__ +#error Only in kernel. +#endif + +#include + +#define IPSEC_UDP_PORT 500 + +/* Protects ftp part of conntracks */ +DECLARE_LOCK_EXTERN(ip_ipsec_lock); + +struct isakmphdr { + u_int32_t initcookie[2]; + u_int32_t respcookie[2]; +}; + +/* This structure is per expected connection */ +struct ip_ct_ipsec_expect +{ + /* We record initiator cookie and source IP address: all in + * host order. */ + + /* source cookie */ + u_int32_t initcookie[2]; /* initiator cookie */ + u_int32_t respcookie[2]; /* initiator cookie */ + u_int32_t saddr; /* source IP address in the orig dir */ +}; + +/* This structure exists only once per master */ +struct ip_ct_ipsec_master { + u_int32_t initcookie[2]; + u_int32_t saddr; +}; + +#endif /* _IP_CONNTRACK_IPSEC_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_pptp.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_pptp.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_pptp.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_pptp.h 2006-12-20 18:45:03.000000000 +0100 @@ -0,0 +1,310 @@ +/* PPTP constants and structs */ +#ifndef _CONNTRACK_PPTP_H +#define _CONNTRACK_PPTP_H + +/* state of the control session */ +enum pptp_ctrlsess_state { + PPTP_SESSION_NONE, /* no session present */ + PPTP_SESSION_ERROR, /* some session error */ + PPTP_SESSION_STOPREQ, /* stop_sess request seen */ + PPTP_SESSION_REQUESTED, /* start_sess request seen */ + PPTP_SESSION_CONFIRMED, /* session established */ +}; + +/* state of the call inside the control session */ +enum pptp_ctrlcall_state { + PPTP_CALL_NONE, + PPTP_CALL_ERROR, + PPTP_CALL_OUT_REQ, + PPTP_CALL_OUT_CONF, + PPTP_CALL_IN_REQ, + PPTP_CALL_IN_REP, + PPTP_CALL_IN_CONF, + PPTP_CALL_CLEAR_REQ, +}; + + +/* conntrack private data */ +struct ip_ct_pptp_master { + enum pptp_ctrlsess_state sstate; /* session state */ + + /* everything below is going to be per-expectation in newnat, + * since there could be more than one call within one session */ + enum pptp_ctrlcall_state cstate; /* call state */ + u_int16_t pac_call_id; /* call id of PAC, host byte order */ + u_int16_t pns_call_id; /* call id of PNS, host byte order */ +}; + +/* conntrack_expect private member */ +struct ip_ct_pptp_expect { + enum pptp_ctrlcall_state cstate; /* call state */ + u_int16_t pac_call_id; /* call id of PAC */ + u_int16_t pns_call_id; /* call id of PNS */ +}; + + +#ifdef __KERNEL__ + +#include +DECLARE_LOCK_EXTERN(ip_pptp_lock); + +#define IP_CONNTR_PPTP PPTP_CONTROL_PORT + +#define PPTP_CONTROL_PORT 1723 + +#define PPTP_PACKET_CONTROL 1 +#define PPTP_PACKET_MGMT 2 + +#define PPTP_MAGIC_COOKIE 0x1a2b3c4d + +struct pptp_pkt_hdr { + __u16 packetLength; + __u16 packetType; + __u32 magicCookie; +}; + +/* PptpControlMessageType values */ +#define PPTP_START_SESSION_REQUEST 1 +#define PPTP_START_SESSION_REPLY 2 +#define PPTP_STOP_SESSION_REQUEST 3 +#define PPTP_STOP_SESSION_REPLY 4 +#define PPTP_ECHO_REQUEST 5 +#define PPTP_ECHO_REPLY 6 +#define PPTP_OUT_CALL_REQUEST 7 +#define PPTP_OUT_CALL_REPLY 8 +#define PPTP_IN_CALL_REQUEST 9 +#define PPTP_IN_CALL_REPLY 10 +#define PPTP_IN_CALL_CONNECT 11 +#define PPTP_CALL_CLEAR_REQUEST 12 +#define PPTP_CALL_DISCONNECT_NOTIFY 13 +#define PPTP_WAN_ERROR_NOTIFY 14 +#define PPTP_SET_LINK_INFO 15 + +#define PPTP_MSG_MAX 15 + +/* PptpGeneralError values */ +#define PPTP_ERROR_CODE_NONE 0 +#define PPTP_NOT_CONNECTED 1 +#define PPTP_BAD_FORMAT 2 +#define PPTP_BAD_VALUE 3 +#define PPTP_NO_RESOURCE 4 +#define PPTP_BAD_CALLID 5 +#define PPTP_REMOVE_DEVICE_ERROR 6 + +struct PptpControlHeader { + __u16 messageType; + __u16 reserved; +}; + +/* FramingCapability Bitmap Values */ +#define PPTP_FRAME_CAP_ASYNC 0x1 +#define PPTP_FRAME_CAP_SYNC 0x2 + +/* BearerCapability Bitmap Values */ +#define PPTP_BEARER_CAP_ANALOG 0x1 +#define PPTP_BEARER_CAP_DIGITAL 0x2 + +struct PptpStartSessionRequest { + __u16 protocolVersion; + __u8 reserved1; + __u8 reserved2; + __u32 framingCapability; + __u32 bearerCapability; + __u16 maxChannels; + __u16 firmwareRevision; + __u8 hostName[64]; + __u8 vendorString[64]; +}; + +/* PptpStartSessionResultCode Values */ +#define PPTP_START_OK 1 +#define PPTP_START_GENERAL_ERROR 2 +#define PPTP_START_ALREADY_CONNECTED 3 +#define PPTP_START_NOT_AUTHORIZED 4 +#define PPTP_START_UNKNOWN_PROTOCOL 5 + +struct PptpStartSessionReply { + __u16 protocolVersion; + __u8 resultCode; + __u8 generalErrorCode; + __u32 framingCapability; + __u32 bearerCapability; + __u16 maxChannels; + __u16 firmwareRevision; + __u8 hostName[64]; + __u8 vendorString[64]; +}; + +/* PptpStopReasons */ +#define PPTP_STOP_NONE 1 +#define PPTP_STOP_PROTOCOL 2 +#define PPTP_STOP_LOCAL_SHUTDOWN 3 + +struct PptpStopSessionRequest { + __u8 reason; +}; + +/* PptpStopSessionResultCode */ +#define PPTP_STOP_OK 1 +#define PPTP_STOP_GENERAL_ERROR 2 + +struct PptpStopSessionReply { + __u8 resultCode; + __u8 generalErrorCode; +}; + +struct PptpEchoRequest { + __u32 identNumber; +}; + +/* PptpEchoReplyResultCode */ +#define PPTP_ECHO_OK 1 +#define PPTP_ECHO_GENERAL_ERROR 2 + +struct PptpEchoReply { + __u32 identNumber; + __u8 resultCode; + __u8 generalErrorCode; + __u16 reserved; +}; + +/* PptpFramingType */ +#define PPTP_ASYNC_FRAMING 1 +#define PPTP_SYNC_FRAMING 2 +#define PPTP_DONT_CARE_FRAMING 3 + +/* PptpCallBearerType */ +#define PPTP_ANALOG_TYPE 1 +#define PPTP_DIGITAL_TYPE 2 +#define PPTP_DONT_CARE_BEARER_TYPE 3 + +struct PptpOutCallRequest { + __u16 callID; + __u16 callSerialNumber; + __u32 minBPS; + __u32 maxBPS; + __u32 bearerType; + __u32 framingType; + __u16 packetWindow; + __u16 packetProcDelay; + __u16 reserved1; + __u16 phoneNumberLength; + __u16 reserved2; + __u8 phoneNumber[64]; + __u8 subAddress[64]; +}; + +/* PptpCallResultCode */ +#define PPTP_OUTCALL_CONNECT 1 +#define PPTP_OUTCALL_GENERAL_ERROR 2 +#define PPTP_OUTCALL_NO_CARRIER 3 +#define PPTP_OUTCALL_BUSY 4 +#define PPTP_OUTCALL_NO_DIAL_TONE 5 +#define PPTP_OUTCALL_TIMEOUT 6 +#define PPTP_OUTCALL_DONT_ACCEPT 7 + +struct PptpOutCallReply { + __u16 callID; + __u16 peersCallID; + __u8 resultCode; + __u8 generalErrorCode; + __u16 causeCode; + __u32 connectSpeed; + __u16 packetWindow; + __u16 packetProcDelay; + __u32 physChannelID; +}; + +struct PptpInCallRequest { + __u16 callID; + __u16 callSerialNumber; + __u32 callBearerType; + __u32 physChannelID; + __u16 dialedNumberLength; + __u16 dialingNumberLength; + __u8 dialedNumber[64]; + __u8 dialingNumber[64]; + __u8 subAddress[64]; +}; + +/* PptpInCallResultCode */ +#define PPTP_INCALL_ACCEPT 1 +#define PPTP_INCALL_GENERAL_ERROR 2 +#define PPTP_INCALL_DONT_ACCEPT 3 + +struct PptpInCallReply { + __u16 callID; + __u16 peersCallID; + __u8 resultCode; + __u8 generalErrorCode; + __u16 packetWindow; + __u16 packetProcDelay; + __u16 reserved; +}; + +struct PptpInCallConnected { + __u16 peersCallID; + __u16 reserved; + __u32 connectSpeed; + __u16 packetWindow; + __u16 packetProcDelay; + __u32 callFramingType; +}; + +struct PptpClearCallRequest { + __u16 callID; + __u16 reserved; +}; + +struct PptpCallDisconnectNotify { + __u16 callID; + __u8 resultCode; + __u8 generalErrorCode; + __u16 causeCode; + __u16 reserved; + __u8 callStatistics[128]; +}; + +struct PptpWanErrorNotify { + __u16 peersCallID; + __u16 reserved; + __u32 crcErrors; + __u32 framingErrors; + __u32 hardwareOverRuns; + __u32 bufferOverRuns; + __u32 timeoutErrors; + __u32 alignmentErrors; +}; + +struct PptpSetLinkInfo { + __u16 peersCallID; + __u16 reserved; + __u32 sendAccm; + __u32 recvAccm; +}; + + +struct pptp_priv_data { + __u16 call_id; + __u16 mcall_id; + __u16 pcall_id; +}; + +union pptp_ctrl_union { + struct PptpStartSessionRequest sreq; + struct PptpStartSessionReply srep; + struct PptpStopSessionRequest streq; + struct PptpStopSessionReply strep; + struct PptpOutCallRequest ocreq; + struct PptpOutCallReply ocack; + struct PptpInCallRequest icreq; + struct PptpInCallReply icack; + struct PptpInCallConnected iccon; + struct PptpClearCallRequest clrreq; + struct PptpCallDisconnectNotify disc; + struct PptpWanErrorNotify wanerr; + struct PptpSetLinkInfo setlink; +}; + +#endif /* __KERNEL__ */ +#endif /* _CONNTRACK_PPTP_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_protocol.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_protocol.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_protocol.h 2003-06-05 14:25:52.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_protocol.h 2006-12-20 18:45:03.000000000 +0100 @@ -62,5 +62,6 @@ extern struct ip_conntrack_protocol ip_conntrack_protocol_tcp; extern struct ip_conntrack_protocol ip_conntrack_protocol_udp; extern struct ip_conntrack_protocol ip_conntrack_protocol_icmp; +extern struct ip_conntrack_protocol ip_conntrack_protocol_esp; extern int ip_conntrack_protocol_tcp_init(void); #endif /*_IP_CONNTRACK_PROTOCOL_H*/ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h 2006-12-20 18:45:03.000000000 +0100 @@ -0,0 +1,123 @@ +#ifndef _CONNTRACK_PROTO_GRE_H +#define _CONNTRACK_PROTO_GRE_H +#include + +/* GRE PROTOCOL HEADER */ + +/* GRE Version field */ +#define GRE_VERSION_1701 0x0 +#define GRE_VERSION_PPTP 0x1 + +/* GRE Protocol field */ +#define GRE_PROTOCOL_PPTP 0x880B + +/* GRE Flags */ +#define GRE_FLAG_C 0x80 +#define GRE_FLAG_R 0x40 +#define GRE_FLAG_K 0x20 +#define GRE_FLAG_S 0x10 +#define GRE_FLAG_A 0x80 + +#define GRE_IS_C(f) ((f)&GRE_FLAG_C) +#define GRE_IS_R(f) ((f)&GRE_FLAG_R) +#define GRE_IS_K(f) ((f)&GRE_FLAG_K) +#define GRE_IS_S(f) ((f)&GRE_FLAG_S) +#define GRE_IS_A(f) ((f)&GRE_FLAG_A) + +/* GRE is a mess: Four different standards */ +struct gre_hdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u16 rec:3, + srr:1, + seq:1, + key:1, + routing:1, + csum:1, + version:3, + reserved:4, + ack:1; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u16 csum:1, + routing:1, + key:1, + seq:1, + srr:1, + rec:3, + ack:1, + reserved:4, + version:3; +#else +#error "Adjust your defines" +#endif + __u16 protocol; +}; + +/* modified GRE header for PPTP */ +struct gre_hdr_pptp { + __u8 flags; /* bitfield */ + __u8 version; /* should be GRE_VERSION_PPTP */ + __u16 protocol; /* should be GRE_PROTOCOL_PPTP */ + __u16 payload_len; /* size of ppp payload, not inc. gre header */ + __u16 call_id; /* peer's call_id for this session */ + __u32 seq; /* sequence number. Present if S==1 */ + __u32 ack; /* seq number of highest packet recieved by */ + /* sender in this session */ +}; + + +/* this is part of ip_conntrack */ +struct ip_ct_gre { + unsigned int stream_timeout; + unsigned int timeout; +}; + +/* this is part of ip_conntrack_expect */ +struct ip_ct_gre_expect { + struct ip_ct_gre_keymap *keymap_orig, *keymap_reply; +}; + +#ifdef __KERNEL__ +struct ip_conntrack_expect; + +/* structure for original <-> reply keymap */ +struct ip_ct_gre_keymap { + struct list_head list; + + struct ip_conntrack_tuple tuple; +}; + + +/* add new tuple->key_reply pair to keymap */ +int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp, + struct ip_conntrack_tuple *t, + int reply); + +/* change an existing keymap entry */ +void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km, + struct ip_conntrack_tuple *t); + +/* delete keymap entries */ +void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp); + + +/* get pointer to gre key, if present */ +static inline u_int32_t *gre_key(struct gre_hdr *greh) +{ + if (!greh->key) + return NULL; + if (greh->csum || greh->routing) + return (u_int32_t *) (greh+sizeof(*greh)+4); + return (u_int32_t *) (greh+sizeof(*greh)); +} + +/* get pointer ot gre csum, if present */ +static inline u_int16_t *gre_csum(struct gre_hdr *greh) +{ + if (!greh->csum) + return NULL; + return (u_int16_t *) (greh+sizeof(*greh)); +} + +#endif /* __KERNEL__ */ + +#endif /* _CONNTRACK_PROTO_GRE_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_pt.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_pt.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_pt.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_pt.h 2006-12-20 18:45:03.000000000 +0100 @@ -0,0 +1,33 @@ +#ifndef _IP_CONNTRACK_PT_H +#define _IP_CONNTRACK_PT_H +/* PT tracking. */ + +#ifndef __KERNEL__ +#error Only in kernel. +#endif + +#include + +/* Protects pt part of conntracks */ +DECLARE_LOCK_EXTERN(ip_pt_lock); + +enum ip_ct_pt_type +{ + /* from client */ + IP_CT_OUTGOING_PORT, +}; + +/* We record pt ip/port here: all in + host order. */ +struct ip_ct_pt +{ + /* This tells NAT that this is an pt connection */ + int is_pt; + /* 0 means not found yet */ + u_int32_t len; + enum ip_ct_pt_type pttype; + /* Port that was to be used */ + u_int16_t port; +}; + +#endif /* _IP_CONNTRACK_PT_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 2006-12-20 18:45:03.000000000 +0100 @@ -0,0 +1,68 @@ +/* + * RTSP extension for IP connection tracking. + * (C) 2003 by Tom Marshall + * based on ip_conntrack_irc.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _IP_CONNTRACK_RTSP_H +#define _IP_CONNTRACK_RTSP_H + +/* #define IP_NF_RTSP_DEBUG */ +#define IP_NF_RTSP_VERSION "0.01" + +/* port block types */ +typedef enum { + pb_single, /* client_port=x */ + pb_range, /* client_port=x-y */ + pb_discon /* client_port=x/y (rtspbis) */ +} portblock_t; + +/* We record seq number and length of rtsp headers here, all in host order. */ + +/* + * This structure is per expected connection. It is a member of struct + * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored + * there and we are expected to only store the length of the data which + * needs replaced. If a packet contains multiple RTSP messages, we create + * one expected connection per message. + * + * We use these variables to mark the entire header block. This may seem + * like overkill, but the nature of RTSP requires it. A header may appear + * multiple times in a message. We must treat two Transport headers the + * same as one Transport header with two entries. + */ +struct ip_ct_rtsp_expect +{ + u_int32_t len; /* length of header block */ + portblock_t pbtype; /* Type of port block that was requested */ + u_int16_t loport; /* Port that was requested, low or first */ + u_int16_t hiport; /* Port that was requested, high or second */ +#if 0 + uint method; /* RTSP method */ + uint cseq; /* CSeq from request */ +#endif +}; + +/* This structure exists only once per master */ +struct ip_ct_rtsp_master +{ + /* Empty (?) */ +}; + + +#ifdef __KERNEL__ + +#include + +#define RTSP_PORT 554 + +/* Protects rtsp part of conntracks */ +DECLARE_LOCK_EXTERN(ip_rtsp_lock); + +#endif /* __KERNEL__ */ + +#endif /* _IP_CONNTRACK_RTSP_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_tuple.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2003-10-09 15:09:36.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2006-12-20 18:45:03.000000000 +0100 @@ -14,7 +14,7 @@ union ip_conntrack_manip_proto { /* Add other protocols here. */ - u_int16_t all; + u_int32_t all; struct { u_int16_t port; @@ -25,6 +25,12 @@ struct { u_int16_t id; } icmp; + struct { + u_int32_t key; + } gre; + struct { + u_int16_t spi; + } esp; }; /* The manipulable part of the tuple. */ @@ -44,7 +50,7 @@ u_int32_t ip; union { /* Add other protocols here. */ - u_int16_t all; + u_int64_t all; struct { u_int16_t port; @@ -55,6 +61,14 @@ struct { u_int8_t type, code; } icmp; + struct { + u_int16_t protocol; + u_int8_t version; + u_int32_t key; + } gre; + struct { + u_int16_t spi; + } esp; } u; /* The protocol. */ @@ -80,10 +94,16 @@ #ifdef __KERNEL__ #define DUMP_TUPLE(tp) \ -DEBUGP("tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n", \ +DEBUGP("tuple %p: %u %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", \ (tp), (tp)->dst.protonum, \ - NIPQUAD((tp)->src.ip), ntohs((tp)->src.u.all), \ - NIPQUAD((tp)->dst.ip), ntohs((tp)->dst.u.all)) + NIPQUAD((tp)->src.ip), ntohl((tp)->src.u.all), \ + NIPQUAD((tp)->dst.ip), ntohl((tp)->dst.u.all)) + +#define DUMP_TUPLE_RAW(x) \ + DEBUGP("tuple %p: %u %u.%u.%u.%u:0x%08x -> %u.%u.%u.%u:0x%08x\n",\ + (x), (x)->dst.protonum, \ + NIPQUAD((x)->src.ip), ntohl((x)->src.u.all), \ + NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.all)) #define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL) diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_wm.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_wm.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_conntrack_wm.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_conntrack_wm.h 2006-12-20 18:45:03.000000000 +0100 @@ -0,0 +1,8 @@ +DECLARE_LOCK_EXTERN(ip_wm_lock); +//#define WMINITIAL 1755 +#define WMINITIAL 554 +#define WMMIN 7000 +#define WMMAX 7007 +#define WMMAXEXPECTED (WMMAX - WMMIN +1) +#define MAXWM_PORTS 1 + diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_nat_esp.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_nat_esp.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_nat_esp.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_nat_esp.h 2006-12-20 18:45:03.000000000 +0100 @@ -0,0 +1,19 @@ +#ifndef _IP_ALG_ESP_H +#define _IP_ALG_ESP_H +/* ESP extension for NAT alteration. */ + +#ifndef __KERNEL__ +#error Only in kernel. +#endif + +/* Protects IPSec part of conntracks */ +DECLARE_LOCK_EXTERN(ip_esp_lock); + +struct ip_nat_esp_info +{ + u_int32_t spi; /* Security Parameter Id */ + u_int32_t saddr; /* Orig Source IP address */ + u_int32_t daddr; /* Remote IP address */ +}; + +#endif /* _IP_ALG_ESP_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_nat_ipsec.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_nat_ipsec.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_nat_ipsec.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_nat_ipsec.h 2006-12-20 18:45:03.000000000 +0100 @@ -0,0 +1,19 @@ +#ifndef _IP_NAT_IPSEC_H +#define _IP_NAT_IPSEC_H +/* IPSec extension for UDP NAT alteration. */ + +#ifndef __KERNEL__ +#error Only in kernel. +#endif + +/* Protects IPSec part of conntracks */ +DECLARE_LOCK_EXTERN(ip_ipsec_lock); + +struct ip_nat_ipsec_info +{ + u_int32_t initcookie[2]; /* Initiator cookie */ + u_int32_t respcookie[2]; /* Responder cookie */ + u_int32_t saddr; /* Orig Source IP address */ +}; + +#endif /* _IP_NAT_IPSEC_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_nat_pptp.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_nat_pptp.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_nat_pptp.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_nat_pptp.h 2006-12-20 18:45:03.000000000 +0100 @@ -0,0 +1,11 @@ +/* PPTP constants and structs */ +#ifndef _NAT_PPTP_H +#define _NAT_PPTP_H + +/* conntrack private data */ +struct ip_nat_pptp { + u_int16_t pns_call_id; /* NAT'ed PNS call id */ + u_int16_t pac_call_id; /* NAT'ed PAC call id */ +}; + +#endif /* _NAT_PPTP_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_nat_rtsp.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_nat_rtsp.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ip_nat_rtsp.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ip_nat_rtsp.h 2006-12-20 18:45:03.000000000 +0100 @@ -0,0 +1,17 @@ +#ifndef _IP_NAT_RTSP_H +#define _IP_NAT_RTSP_H +/* RTSP extension for UDP NAT alteration. */ + +#ifndef __KERNEL__ +#error Only in kernel. +#endif + +/* Protects RTSP part of conntracks */ +DECLARE_LOCK_EXTERN(ip_rtp_lock); + +struct ip_nat_rtsp_info +{ + u_int32_t orig_port; /* Client Port */ +}; + +#endif /* _IP_NAT_RTSP_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ipt_connlimit.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ipt_connlimit.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ipt_connlimit.h 2006-12-20 18:45:03.000000000 +0100 @@ -0,0 +1,12 @@ +#ifndef _IPT_CONNLIMIT_H +#define _IPT_CONNLIMIT_H + +struct ipt_connlimit_data; + +struct ipt_connlimit_info { + int limit; + int inverse; + u_int32_t mask; + struct ipt_connlimit_data *data; +}; +#endif /* _IPT_CONNLIMIT_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ipt_FTOS.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ipt_FTOS.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_ipv4/ipt_FTOS.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_ipv4/ipt_FTOS.h 2006-12-20 18:45:03.000000000 +0100 @@ -0,0 +1,16 @@ +/* Set TOS field in header to any value + * + * (C) 2000 by Matthew G. Marsh + * + * This software is distributed under GNU GPL v2, 1991 + * + * ipt_FTOS.h borrowed heavily from ipt_TOS.h 11/09/2000 +*/ +#ifndef _IPT_FTOS_H +#define _IPT_FTOS_H + +struct ipt_FTOS_info { + u_int8_t ftos; +}; + +#endif /*_IPT_FTOS_H*/ diff -Naur linux-mips-2.6.8.1-orig/include/linux/netfilter_mime.h linux-mips-2.6.8.1-bcm/include/linux/netfilter_mime.h --- linux-mips-2.6.8.1-orig/include/linux/netfilter_mime.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/netfilter_mime.h 2006-12-20 18:45:06.000000000 +0100 @@ -0,0 +1,89 @@ +/* + * MIME functions for netfilter modules. This file provides implementations + * for basic MIME parsing. MIME headers are used in many protocols, such as + * HTTP, RTSP, SIP, etc. + * + * gcc will warn for defined but unused functions, so we only include the + * functions requested. The following macros are used: + * NF_NEED_MIME_NEXTLINE nf_mime_nextline() + */ +#ifndef _NETFILTER_MIME_H +#define _NETFILTER_MIME_H + +/* Only include these functions for kernel code. */ +#ifdef __KERNEL__ + +#include + +/* + * Given a buffer and length, advance to the next line and mark the current + * line. If the current line is empty, *plinelen will be set to zero. If + * not, it will be set to the actual line length (including CRLF). + * + * 'line' in this context means logical line (includes LWS continuations). + * Returns 1 on success, 0 on failure. + */ +#ifdef NF_NEED_MIME_NEXTLINE +static int +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) +{ + uint off = *poff; + uint physlen = 0; + int is_first_line = 1; + + if (off >= len) + { + return 0; + } + + do + { + while (p[off] != '\n') + { + if (len-off <= 1) + { + return 0; + } + + physlen++; + off++; + } + + /* if we saw a crlf, physlen needs adjusted */ + if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') + { + physlen--; + } + + /* advance past the newline */ + off++; + + /* check for an empty line */ + if (physlen == 0) + { + break; + } + + /* check for colon on the first physical line */ + if (is_first_line) + { + is_first_line = 0; + if (memchr(p+(*poff), ':', physlen) == NULL) + { + return 0; + } + } + } + while (p[off] == ' ' || p[off] == '\t'); + + *plineoff = *poff; + *plinelen = (physlen == 0) ? 0 : (off - *poff); + *poff = off; + + return 1; +} +#endif /* NF_NEED_MIME_NEXTLINE */ + +#endif /* __KERNEL__ */ + +#endif /* _NETFILTER_MIME_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/param.h linux-mips-2.6.8.1-bcm/include/linux/param.h --- linux-mips-2.6.8.1-orig/include/linux/param.h 1997-06-01 05:17:01.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/param.h 2006-12-20 18:45:06.000000000 +0100 @@ -1,6 +1,9 @@ #ifndef _LINUX_PARAM_H #define _LINUX_PARAM_H +#if defined(CONFIG_BCM_ENDPOINT_MODULE) +#include +#else #include - +#endif #endif diff -Naur linux-mips-2.6.8.1-orig/include/linux/preempt.h linux-mips-2.6.8.1-bcm/include/linux/preempt.h --- linux-mips-2.6.8.1-orig/include/linux/preempt.h 2004-03-11 17:46:58.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/preempt.h 2006-12-20 18:45:06.000000000 +0100 @@ -9,6 +9,8 @@ #include #include +#ifdef __KERNEL__ + #define preempt_count() (current_thread_info()->preempt_count) #define inc_preempt_count() \ @@ -58,4 +60,14 @@ #endif +#else /* __KERNEL__ */ + +/* We need to disable much of the above in order to build iptables. + * Create unresolvable references so there are no surprises. */ +asmlinkage void preempt_disable(void); +asmlinkage void preempt_enable(void); +asmlinkage int preempt_count(void); + +#endif /* __KERNEL__ */ + #endif /* __LINUX_PREEMPT_H */ diff -Naur linux-mips-2.6.8.1-orig/include/linux/skbuff.h linux-mips-2.6.8.1-bcm/include/linux/skbuff.h --- linux-mips-2.6.8.1-orig/include/linux/skbuff.h 2004-08-13 09:18:55.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/skbuff.h 2006-12-20 18:45:06.000000000 +0100 @@ -247,6 +247,10 @@ unsigned short protocol, security; +#if defined(CONFIG_MIPS_BRCM) + char extif[64]; +#endif + void (*destructor)(struct sk_buff *skb); #ifdef CONFIG_NETFILTER unsigned long nfmark; @@ -272,6 +276,27 @@ #endif #endif +#if defined(CONFIG_MIPS_BRCM) +#define FROM_WAN 0x1000 +#define FREE_DATA 0 +#define FREE_SKB 1 + /* Call back function to return the buffer or skb itself back to the free queue + * if the buffer or skb is pre-allocated and reused in our drivers such as atm or eth driver. + * It's called by kfree_skbmem or skb_release_data depending on + * whether the flag is FREE_SKB or FREE_DATA + */ + void (*retfreeq_cb)(void *context, void *obj, int flag); + void *retfreeq_context; + /* retfreeq_skb_prealloc : flag to indicate whether the skb is + * preallocated by our drivers. Cloned skb should NOT have this flag set. + * retfreeq_data_prealloc: flag to indicate whether the data buffer associated + * with the skb is preallocated by the drivers. (Song Wang: songw@broadcom.com) + */ + unsigned char retfreeq_skb_prealloc; + unsigned char retfreeq_data_prealloc; + /* Flag to indicate where the skb is received from, used for WAN2WAN blocking */ + unsigned short rcvfrom; +#endif /* These elements must be at the end, see alloc_skb() for details. */ @@ -314,6 +339,47 @@ /* Internal */ #define skb_shinfo(SKB) ((struct skb_shared_info *)((SKB)->end)) +#if defined(CONFIG_MIPS_BRCM) +/** + * skb_headerinit - initialize a socket buffer header + * @size: size to allocate + * @skb: skb allocated by caller + * @data: data buffer allocated by caller + * @retfreeq_cb: callback function to free data buffer and skb + * @retskb_ctx: context value passed to retfreeq_cb + * + * Initializes the socket buffer and assigns the data buffer to it. + * + */ +static inline void skb_hdrinit(unsigned int offset, unsigned int size, + struct sk_buff *skb, unsigned char *data, + void (*retfreeq_cb)(void *, void *, int), void *retfreeq_ctx, + unsigned short rcvfrom) +{ + memset(skb, 0, offsetof(struct sk_buff, truesize)); + + skb->truesize = size + sizeof(struct sk_buff); + atomic_set(&skb->users, 1); + skb->head = data - offset; + skb->data = data; + skb->tail = data + size; + skb->end = (unsigned char *) (((unsigned long) data + size + 0x0f) & ~0x0f); + skb->len = size; + skb->nfmark |= rcvfrom; + + skb->retfreeq_cb = retfreeq_cb; + skb->retfreeq_context = retfreeq_ctx; + skb->retfreeq_skb_prealloc = 1; + skb->retfreeq_data_prealloc = 1; + + atomic_set(&(skb_shinfo(skb)->dataref), 1); + skb_shinfo(skb)->nr_frags = 0; + skb_shinfo(skb)->tso_size = 0; + skb_shinfo(skb)->tso_segs = 0; + skb_shinfo(skb)->frag_list = NULL; +} +#endif + /** * skb_queue_empty - check if a queue is empty * @list: queue head @@ -1105,6 +1171,19 @@ extern void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len); +static inline void *skb_header_pointer(const struct sk_buff *skb, int offset, + int len, void *buffer) +{ + int hlen = skb_headlen(skb); + + if (offset + len <= hlen) + return skb->data + offset; + + if (skb_copy_bits(skb, offset, buffer, len) < 0) + return NULL; + + return buffer; + } extern void skb_init(void); extern void skb_add_mtu(int mtu); diff -Naur linux-mips-2.6.8.1-orig/include/linux/sockios.h linux-mips-2.6.8.1-bcm/include/linux/sockios.h --- linux-mips-2.6.8.1-orig/include/linux/sockios.h 2004-06-06 04:12:55.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/sockios.h 2006-12-20 18:45:06.000000000 +0100 @@ -122,6 +122,13 @@ #define SIOCBRADDIF 0x89a2 /* add interface to bridge */ #define SIOCBRDELIF 0x89a3 /* remove interface from bridge */ + +/***********************BRCM global ioctl calls*****************************/ +#define SIOC_BRCM_GLOBAL_BASE 0x89c0 +#define SIOCGIFTRANSSTART (SIOC_BRCM_GLOBAL_BASE+0) /* Used by SNMP */ +#define SIOCCIFSTATS (SIOC_BRCM_GLOBAL_BASE+1) /* Clean up the Stats of a device */ + + /* Device private ioctl calls */ /* diff -Naur linux-mips-2.6.8.1-orig/include/linux/squashfs_fs.h linux-mips-2.6.8.1-bcm/include/linux/squashfs_fs.h --- linux-mips-2.6.8.1-orig/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/squashfs_fs.h 2006-12-20 18:45:06.000000000 +0100 @@ -0,0 +1,474 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004 Phillip Lougher + * + * 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, + * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#define SQUASHFS_MAJOR 2 +#define SQUASHFS_MINOR 0 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 65536 +#define SQUASHFS_FILE_LOG 16 + +#define SQUASHFS_FILE_MAX_SIZE 65536 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_BLK ((long long) 0xffffffff) +#define SQUASHFS_USED_BLK ((long long) 0xfffffffe) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, SQUASHFS_NOI) +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, SQUASHFS_NOD) +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, SQUASHFS_NOF) +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, SQUASHFS_NO_FRAG) +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, SQUASHFS_ALWAYS_FRAG) +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, SQUASHFS_DUPLICATE) +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, SQUASHFS_CHECK) +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, duplicate_checking) (noi | (nod << 1) | (check_data << 2) | (nof << 3) | (no_frag << 4) | (always_frag << 5) | (duplicate_checking << 6)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an uncompressed + * offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode)(((squashfs_inode) (A) << 16)\ + + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + ((b) >> 2) + 1)) + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +typedef unsigned int squashfs_fragment_index; +#define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(squashfs_fragment_entry)) +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / SQUASHFS_METADATA_SIZE) +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % SQUASHFS_METADATA_SIZE) +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE) +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) * sizeof(squashfs_fragment_index)) +#define SQUASHFS_CACHED_FRAGMENTS 3 + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 32 +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << (SQUASHFS_MAX_FILE_SIZE_LOG - 1)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* + * definitions for structures on disk + */ + +typedef unsigned int squashfs_block; +typedef long long squashfs_inode; + +typedef unsigned int squashfs_uid; + +typedef struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used; + unsigned int uid_start; + unsigned int guid_start; + unsigned int inode_table_start; + unsigned int directory_table_start; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start; +} __attribute__ ((packed)) squashfs_super_block; + +typedef struct { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)) squashfs_base_inode_header; + +typedef squashfs_base_inode_header squashfs_ipc_inode_header; + +typedef struct { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)) squashfs_dev_inode_header; + +typedef struct { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)) squashfs_symlink_inode_header; + +typedef struct { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + squashfs_block start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:SQUASHFS_MAX_FILE_SIZE_LOG; + unsigned short block_list[0]; +} __attribute__ ((packed)) squashfs_reg_inode_header; + +typedef struct { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)) squashfs_dir_inode_header; + +typedef union { + squashfs_base_inode_header base; + squashfs_dev_inode_header dev; + squashfs_symlink_inode_header symlink; + squashfs_reg_inode_header reg; + squashfs_dir_inode_header dir; + squashfs_ipc_inode_header ipc; +} squashfs_inode_header; + +typedef struct { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)) squashfs_dir_entry; + +typedef struct { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)) squashfs_dir_header; + + +typedef struct { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)) squashfs_fragment_entry; + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem on a + * machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_MEMSET(s, d, sizeof(squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 472, 32);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_ipc_inode_header)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dev_inode_header));\ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, SQUASHFS_MAX_FILE_SIZE_LOG);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_MEMSET(s, d, sizeof(squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +#ifdef SQUASHFS_1_0_COMPATIBILITY +typedef struct { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)) squashfs_base_inode_header_1; + +typedef struct { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)) squashfs_ipc_inode_header_1; + +typedef struct { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)) squashfs_dev_inode_header_1; + +typedef struct { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)) squashfs_symlink_inode_header_1; + +typedef struct { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + squashfs_block start_block; + unsigned int file_size:SQUASHFS_MAX_FILE_SIZE_LOG; + unsigned short block_list[0]; +} __attribute__ ((packed)) squashfs_reg_inode_header_1; + +typedef struct { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)) squashfs_dir_inode_header_1; + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4);\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, sizeof(squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, sizeof(squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, SQUASHFS_MAX_FILE_SIZE_LOG);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} +#endif + +#ifdef __KERNEL__ +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing architectures + */ +#include +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + int bits;\ + int b_pos = pos % 8;\ + unsigned long long val = 0;\ + unsigned char *s = (unsigned char *)p + (pos / 8);\ + unsigned char *d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); +#endif +#endif diff -Naur linux-mips-2.6.8.1-orig/include/linux/squashfs_fs_i.h linux-mips-2.6.8.1-bcm/include/linux/squashfs_fs_i.h --- linux-mips-2.6.8.1-orig/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/squashfs_fs_i.h 2006-12-20 18:45:06.000000000 +0100 @@ -0,0 +1,34 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004 Phillip Lougher + * + * 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, + * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +typedef struct squashfs_inode_info { + unsigned int start_block; + unsigned int block_list_start; + unsigned int offset; + unsigned int fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + struct inode vfs_inode; + } squashfs_inode_info; +#endif diff -Naur linux-mips-2.6.8.1-orig/include/linux/squashfs_fs_sb.h linux-mips-2.6.8.1-bcm/include/linux/squashfs_fs_sb.h --- linux-mips-2.6.8.1-orig/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/include/linux/squashfs_fs_sb.h 2006-12-20 18:45:06.000000000 +0100 @@ -0,0 +1,65 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004 Phillip Lougher + * + * 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, + * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include + +typedef struct { + unsigned int block; + int length; + unsigned int next_index; + char *data; + } squashfs_cache; + +struct squashfs_fragment_cache { + unsigned int block; + int length; + unsigned int locked; + char *data; + }; + +typedef struct squashfs_sb_info { + squashfs_super_block sBlk; + int devblksize; + int devblksize_log2; + int swap; + squashfs_cache *block_cache; + struct squashfs_fragment_cache *fragment; + int next_cache; + int next_fragment; + squashfs_uid *uid; + squashfs_uid *guid; + squashfs_fragment_index *fragment_index; + unsigned int read_size; + char *read_data; + char *read_page; + struct semaphore read_page_mutex; + struct semaphore block_cache_mutex; + struct semaphore fragment_mutex; + wait_queue_head_t waitq; + wait_queue_head_t fragment_wait_queue; + struct inode *(*iget)(struct super_block *s, squashfs_inode inode); + unsigned int (*read_blocklist)(struct inode *inode, int index, int readahead_blks, + char *block_list, char **block_p, unsigned int *bsize); + } squashfs_sb_info; +#endif diff -Naur linux-mips-2.6.8.1-orig/include/linux/syscalls.h linux-mips-2.6.8.1-bcm/include/linux/syscalls.h --- linux-mips-2.6.8.1-orig/include/linux/syscalls.h 2004-06-26 17:15:25.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/syscalls.h 2006-12-20 18:45:06.000000000 +0100 @@ -438,6 +438,8 @@ asmlinkage long sys_msgget(key_t key, int msgflg); asmlinkage long sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg); +asmlinkage long kernel_sys_msgsnd(int msqid, struct msgbuf __user *msgp, + size_t msgsz, int msgflg); asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, long msgtyp, int msgflg); asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); diff -Naur linux-mips-2.6.8.1-orig/include/linux/sysctl.h linux-mips-2.6.8.1-bcm/include/linux/sysctl.h --- linux-mips-2.6.8.1-orig/include/linux/sysctl.h 2004-08-13 09:18:56.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/sysctl.h 2006-12-20 18:45:05.000000000 +0100 @@ -133,6 +133,7 @@ KERN_NGROUPS_MAX=63, /* int: NGROUPS_MAX */ KERN_SPARC_SCONS_PWROFF=64, /* int: serial console power-off halt */ KERN_HZ_TIMER=65, /* int: hz timer on or off */ + KERN_DEFER_SOFTIRQS=66, /* int: defer all softirqs to ksoftirqd */ }; diff -Naur linux-mips-2.6.8.1-orig/include/linux/time.h linux-mips-2.6.8.1-bcm/include/linux/time.h --- linux-mips-2.6.8.1-orig/include/linux/time.h 2004-06-09 16:12:13.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/time.h 2006-12-20 18:45:06.000000000 +0100 @@ -41,7 +41,11 @@ * Have the 32 bit jiffies value wrap 5 minutes after boot * so jiffies wrap bugs show up earlier. */ +#if defined(CONFIG_MIPS_BRCM) +#define INITIAL_JIFFIES 0 +#else #define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ)) +#endif /* * Change timeval to jiffies, trying to avoid the diff -Naur linux-mips-2.6.8.1-orig/include/linux/topology.h linux-mips-2.6.8.1-bcm/include/linux/topology.h --- linux-mips-2.6.8.1-orig/include/linux/topology.h 2004-04-12 22:23:40.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/linux/topology.h 2006-12-20 18:45:05.000000000 +0100 @@ -32,7 +32,11 @@ #include #include +#if defined(CONFIG_BCM_ENDPOINT_MODULE) +#include +#else #include +#endif #ifndef nr_cpus_node #define nr_cpus_node(node) \ diff -Naur linux-mips-2.6.8.1-orig/include/net/pkt_sched.h linux-mips-2.6.8.1-bcm/include/net/pkt_sched.h --- linux-mips-2.6.8.1-orig/include/net/pkt_sched.h 2004-08-13 09:18:56.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/net/pkt_sched.h 2006-12-20 18:44:26.000000000 +0100 @@ -101,8 +101,7 @@ static inline void *qdisc_priv(struct Qdisc *q) { - return (char *)q + ((sizeof(struct Qdisc) + QDISC_ALIGN_CONST) - & ~QDISC_ALIGN_CONST); + return (unsigned int)((char *)q + (sizeof(struct Qdisc) + QDISC_ALIGN_CONST)) & ~(QDISC_ALIGN_CONST); } struct qdisc_rate_table diff -Naur linux-mips-2.6.8.1-orig/include/net/sock.h linux-mips-2.6.8.1-bcm/include/net/sock.h --- linux-mips-2.6.8.1-orig/include/net/sock.h 2004-07-20 22:21:26.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/include/net/sock.h 2006-12-20 18:44:26.000000000 +0100 @@ -257,6 +257,9 @@ struct sk_buff *sk_send_head; int sk_write_pending; void *sk_security; +#if defined(CONFIG_MIPS_BRCM) + char extdev[64]; +#endif __u8 sk_queue_shrunk; /* three bytes hole, try to pack */ void (*sk_state_change)(struct sock *sk); diff -Naur linux-mips-2.6.8.1-orig/init/do_mounts_rd.c linux-mips-2.6.8.1-bcm/init/do_mounts_rd.c --- linux-mips-2.6.8.1-orig/init/do_mounts_rd.c 2004-06-06 04:12:56.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/init/do_mounts_rd.c 2006-12-20 18:46:10.000000000 +0100 @@ -5,6 +5,9 @@ #include #include #include +#if defined(CONFIG_MIPS_BRCM) +#include +#endif #include #include @@ -39,6 +42,9 @@ * numbers could not be found. * * We currently check for the following magic numbers: +#if defined(CONFIG_MIPS_BRCM) + * squashfs +#endif * minix * ext2 * romfs @@ -53,6 +59,9 @@ struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; +#if defined(CONFIG_MIPS_BRCM) + struct squashfs_super_block *squashfsb; +#endif int nblocks = -1; unsigned char *buf; @@ -64,6 +73,9 @@ ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; +#if defined(CONFIG_MIPS_BRCM) + squashfsb = (struct squashfs_super_block *) buf; +#endif memset(buf, 0xe5, size); /* @@ -101,6 +113,17 @@ goto done; } +#if defined(CONFIG_MIPS_BRCM) + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } +#endif + /* * Read block 1 to test for minix and ext2 superblock */ diff -Naur linux-mips-2.6.8.1-orig/ipc/msg.c linux-mips-2.6.8.1-bcm/ipc/msg.c --- linux-mips-2.6.8.1-orig/ipc/msg.c 2004-07-09 04:16:52.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/ipc/msg.c 2006-12-20 18:47:16.000000000 +0100 @@ -15,6 +15,7 @@ * (c) 1999 Manfred Spraul */ +#include #include #include #include @@ -539,6 +540,96 @@ return 0; } +#if defined(CONFIG_MIPS_BRCM) +asmlinkage long kernel_sys_msgsnd (int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg) +{ + struct msg_queue *msq; + struct msg_msg *msg; + long mtype; + int err; + + if (msgsz > msg_ctlmax || (long) msgsz < 0 || msqid < 0) + return -EINVAL; + //if (get_user(mtype, &msgp->mtype)) + // return -EFAULT; + mtype = msgp->mtype; + if (mtype < 1) + return -EINVAL; + + msg = kernel_load_msg(msgp->mtext, msgsz); + if(IS_ERR(msg)) + return PTR_ERR(msg); + + msg->m_type = mtype; + msg->m_ts = msgsz; + + msq = msg_lock(msqid); + err=-EINVAL; + if(msq==NULL) + goto out_free; +retry: + err= -EIDRM; + if (msg_checkid(msq,msqid)) + goto out_unlock_free; + + err=-EACCES; + if (ipcperms(&msq->q_perm, S_IWUGO)) + goto out_unlock_free; + + err = security_msg_queue_msgsnd(msq, msg, msgflg); + if (err) + goto out_unlock_free; + + if(msgsz + msq->q_cbytes > msq->q_qbytes || + 1 + msq->q_qnum > msq->q_qbytes) { + struct msg_sender s; + + if(msgflg&IPC_NOWAIT) { + err=-EAGAIN; + goto out_unlock_free; + } + ss_add(msq, &s); + msg_unlock(msq); + schedule(); + current->state= TASK_RUNNING; + + msq = msg_lock(msqid); + err = -EIDRM; + if(msq==NULL) + goto out_free; + ss_del(&s); + + if (signal_pending(current)) { + err=-EINTR; + goto out_unlock_free; + } + goto retry; + } + + msq->q_lspid = current->tgid; + msq->q_stime = get_seconds(); + + if(!pipelined_send(msq,msg)) { + /* noone is waiting for this message, enqueue it */ + list_add_tail(&msg->m_list,&msq->q_messages); + msq->q_cbytes += msgsz; + msq->q_qnum++; + atomic_add(msgsz,&msg_bytes); + atomic_inc(&msg_hdrs); + } + + err = 0; + msg = NULL; + +out_unlock_free: + msg_unlock(msq); +out_free: + if(msg!=NULL) + free_msg(msg); + return err; +} +#endif + asmlinkage long sys_msgsnd (int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg) { struct msg_queue *msq; @@ -828,3 +919,11 @@ return len; } #endif +#if defined(CONFIG_MIPS_BRCM) +EXPORT_SYMBOL(sys_msgget); +EXPORT_SYMBOL(sys_msgsnd); +EXPORT_SYMBOL(sys_msgrcv); +EXPORT_SYMBOL(sys_msgctl); +EXPORT_SYMBOL(kernel_sys_msgsnd); +#endif + diff -Naur linux-mips-2.6.8.1-orig/ipc/msgutil.c linux-mips-2.6.8.1-bcm/ipc/msgutil.c --- linux-mips-2.6.8.1-orig/ipc/msgutil.c 2004-06-06 04:12:56.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/ipc/msgutil.c 2006-12-20 18:47:16.000000000 +0100 @@ -25,6 +25,76 @@ #define DATALEN_MSG (PAGE_SIZE-sizeof(struct msg_msg)) #define DATALEN_SEG (PAGE_SIZE-sizeof(struct msg_msgseg)) +#if defined(CONFIG_MIPS_BRCM) +struct msg_msg *kernel_load_msg(const void __user *src, int len) +{ + struct msg_msg *msg; + struct msg_msgseg **pseg; + int err; + int alen; + + alen = len; + if (alen > DATALEN_MSG) + alen = DATALEN_MSG; + + msg = (struct msg_msg *)kmalloc(sizeof(*msg) + alen, GFP_ATOMIC); + if (msg == NULL) + return ERR_PTR(-ENOMEM); + + msg->next = NULL; + msg->security = NULL; + +#if 0 + if (copy_from_user(msg + 1, src, alen)) { + err = -EFAULT; + goto out_err; + } +#endif + memcpy(msg+1,src,alen); + + len -= alen; + //src = ((char __user *)src) + alen; + src = ((char*)src) + alen; + pseg = &msg->next; + while (len > 0) { + struct msg_msgseg *seg; + alen = len; + if (alen > DATALEN_SEG) + alen = DATALEN_SEG; + seg = (struct msg_msgseg *)kmalloc(sizeof(*seg) + alen, + GFP_ATOMIC); + if (seg == NULL) { + err = -ENOMEM; + goto out_err; + } + *pseg = seg; + seg->next = NULL; +#if 0 + if (copy_from_user(seg + 1, src, alen)) { + err = -EFAULT; + goto out_err; + } +#endif + memcpy(seg+1,src,alen); + pseg = &seg->next; + len -= alen; + //src = ((char __user *)src) + alen; + src = ((char *)src) + alen; + } + + err = security_msg_msg_alloc(msg); + if (err) + goto out_err; + + return msg; + +out_err: + free_msg(msg); + return ERR_PTR(err); +} + +#endif + struct msg_msg *load_msg(const void __user *src, int len) { struct msg_msg *msg; diff -Naur linux-mips-2.6.8.1-orig/kernel/sched.c linux-mips-2.6.8.1-bcm/kernel/sched.c --- linux-mips-2.6.8.1-orig/kernel/sched.c 2004-08-06 02:33:31.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/kernel/sched.c 2006-12-20 18:43:16.000000000 +0100 @@ -2372,7 +2372,10 @@ { struct list_head *tmp, *next; - list_for_each_safe(tmp, next, &q->task_list) { + if ( (&q->task_list)->next == 0 ) { + printk(KERN_INFO "Empty list(should be ok)\n"); + } else { + list_for_each_safe(tmp, next, &q->task_list) { wait_queue_t *curr; unsigned flags; curr = list_entry(tmp, wait_queue_t, task_list); @@ -2381,6 +2384,7 @@ (flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive) break; + } } } diff -Naur linux-mips-2.6.8.1-orig/kernel/softirq.c linux-mips-2.6.8.1-bcm/kernel/softirq.c --- linux-mips-2.6.8.1-orig/kernel/softirq.c 2004-04-23 17:54:22.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/kernel/softirq.c 2006-12-20 18:43:16.000000000 +0100 @@ -17,6 +17,9 @@ #include #include + +#include + /* - No shared variables, all the data are CPU local. - If a softirq needs serialization, let it serialize itself @@ -44,6 +47,8 @@ static DEFINE_PER_CPU(struct task_struct *, ksoftirqd); +int defer_softirqs = 1; + /* * we cannot loop indefinitely here to avoid userspace starvation, * but we also don't want to introduce a worst case 1/HZ latency @@ -70,10 +75,10 @@ */ #define MAX_SOFTIRQ_RESTART 10 -asmlinkage void __do_softirq(void) +asmlinkage void ___do_softirq(void) { struct softirq_action *h; - __u32 pending; + __u32 pending, mask; int max_restart = MAX_SOFTIRQ_RESTART; pending = local_softirq_pending(); @@ -87,11 +92,26 @@ h = softirq_vec; + mask = 1; do { - if (pending & 1) + if (pending & mask) { + pending ^= mask; /* clear the bit */ h->action(h); + if (unlikely(defer_softirqs && need_resched())) { + /* + * We are interrupting softirq processing + * to allow for preemption to occur. Add + * back any non-processed pending bits to + * this CPU's mask: + */ + local_irq_disable(); + local_softirq_pending() |= pending; + local_irq_enable(); + goto out; + } + } h++; - pending >>= 1; + mask <<= 1; } while (pending); local_irq_disable(); @@ -103,9 +123,34 @@ if (pending) wakeup_softirqd(); +out: __local_bh_enable(); } +asmlinkage void __do_softirq(void) +{ + if (likely(defer_softirqs)) { + /* + * 'preempt harder'. Push all softirq processing off + * to ksoftirqd. This makes softirq related latencies + * much more predictable since they run from process + * context instead of hardirq context. + */ + if (local_softirq_pending()) + wakeup_softirqd(); + return; + } + ___do_softirq(); +} + +asmlinkage void _do_softirq(void) +{ + local_irq_disable(); + ___do_softirq(); + local_irq_enable(); +} + + #ifndef __ARCH_HAS_DO_SOFTIRQ asmlinkage void do_softirq(void) @@ -322,8 +367,15 @@ static int ksoftirqd(void * __bind_cpu) { - set_user_nice(current, 19); +#if 1 + set_user_nice(current, -5); current->flags |= PF_NOFREEZE; +#else /* alternative if we want more priority for ksoftirqd */ + struct sched_param param = { .sched_priority = MAX_RT_PRIO/4-1 }; + param.sched_priority = 1; + sys_sched_setscheduler(current->pid, SCHED_RR, ¶m); + current->flags |= PF_NOFREEZE; +#endif set_current_state(TASK_INTERRUPTIBLE); @@ -340,7 +392,7 @@ preempt_disable(); if (cpu_is_offline((long)__bind_cpu)) goto wait_to_die; - do_softirq(); + _do_softirq(); preempt_enable(); cond_resched(); } diff -Naur linux-mips-2.6.8.1-orig/kernel/sysctl.c linux-mips-2.6.8.1-bcm/kernel/sysctl.c --- linux-mips-2.6.8.1-orig/kernel/sysctl.c 2004-08-14 18:16:44.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/kernel/sysctl.c 2006-12-20 18:43:16.000000000 +0100 @@ -50,6 +50,7 @@ #if defined(CONFIG_SYSCTL) /* External variables not in a header file. */ +extern int defer_softirqs; extern int panic_timeout; extern int C_A_D; extern int sysctl_overcommit_memory; @@ -268,6 +269,14 @@ .proc_handler = &proc_dointvec, }, { + .ctl_name = KERN_DEFER_SOFTIRQS, + .procname = "defer_softirqs", + .data = &defer_softirqs, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { .ctl_name = KERN_CORE_USES_PID, .procname = "core_uses_pid", .data = &core_uses_pid, diff -Naur linux-mips-2.6.8.1-orig/LOST.config linux-mips-2.6.8.1-bcm/LOST.config --- linux-mips-2.6.8.1-orig/LOST.config 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/LOST.config 2007-03-05 19:14:45.000000000 +0100 @@ -0,0 +1,1139 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_HOTPLUG=y +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +# CONFIG_FUTEX is not set +# CONFIG_EPOLL is not set +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# Machine selection +# +CONFIG_MIPS_BRCM=y +# CONFIG_BCM96338 is not set +# CONFIG_BCM96348 is not set +CONFIG_BCM96358=y +CONFIG_BCM_BOARD=y +CONFIG_BCM_SERIAL=y +CONFIG_BCM_ENET=m +CONFIG_BCM_USB=m +CONFIG_BCM_WLAN=m +# CONFIG_BCM_MIMO is not set +CONFIG_BCM_PCI=y +CONFIG_BCM_ATMAPI=m +# CONFIG_BCM_ATMTEST is not set +CONFIG_BCM_ADSL=m +CONFIG_BCM_ENDPOINT=m +# CONFIG_BCM_BCMPROF is not set +# CONFIG_BCM_PROCFS is not set +# CONFIG_BCM_VDSL is not set +# CONFIG_BCM_SECURITY is not set +# CONFIG_BCM_HPNA is not set +CONFIG_BCM_BOARD_IMPL=1 +CONFIG_BCM_SERIAL_IMPL=1 +CONFIG_BCM_ENET_IMPL=2 +CONFIG_BCM_USB_IMPL=2 +CONFIG_BCM_WLAN_IMPL=1 +CONFIG_BCM_ATMAPI_IMPL=1 +CONFIG_BCM_ATMTEST_IMPL=1 +CONFIG_BCM_BLAA_IMPL=1 +CONFIG_BCM_ADSL_IMPL=1 +CONFIG_BCM_ENDPOINT_IMPL=1 +CONFIG_BCM_BCMPROF_IMPL=1 +CONFIG_BCM_PROCFS_IMPL=1 +CONFIG_BCM_SECURITY_IMPL=1 +CONFIG_BCM_HPNA_IMPL=0 +CONFIG_ROOTFS_SQUASHFS=y +# CONFIG_ROOTFS_CRAMFS is not set +# CONFIG_ROOTFS_JFFS2 is not set +# CONFIG_ROOTFS_NFS is not set +CONFIG_ROOT_FLASHFS="root=31:1 ro noinitrd" +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_PREEMPT=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y + +# +# PCMCIA/CardBus support +# +# CONFIG_PCMCIA is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y +# CONFIG_BINFMT_IRIX is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +# CONFIG_MTD_CHAR is not set +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_AMDSTD_RETRY=0 +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_BCM963XX=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_ROUTE_FWMARK is not set +# CONFIG_IP_ROUTE_NAT is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_TOS is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +CONFIG_IP_MROUTE=y +# CONFIG_IP_PIMSM_V1 is not set +# CONFIG_IP_PIMSM_V2 is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +# CONFIG_BRIDGE_NETFILTER is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=y +CONFIG_IP_NF_FTP=y +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_TFTP=m +# CONFIG_IP_NF_AMANDA is not set +# CONFIG_IP_NF_DTX8 is not set +# CONFIG_IP_NF_WM is not set +CONFIG_IP_NF_PT=m +CONFIG_IP_NF_IPSEC=m +CONFIG_IP_NF_RTSP=m +# CONFIG_IP_NF_QUEUE is not set +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_LIMIT=m +# CONFIG_IP_NF_MATCH_IPRANGE is not set +# CONFIG_IP_NF_MATCH_MAC is not set +# CONFIG_IP_NF_MATCH_PKTTYPE is not set +CONFIG_IP_NF_MATCH_MARK=y +# CONFIG_IP_NF_MATCH_MULTIPORT is not set +CONFIG_IP_NF_MATCH_TOS=y +# CONFIG_IP_NF_MATCH_RECENT is not set +# CONFIG_IP_NF_MATCH_ECN is not set +CONFIG_IP_NF_MATCH_DSCP=m +# CONFIG_IP_NF_MATCH_AH_ESP is not set +# CONFIG_IP_NF_MATCH_LENGTH is not set +# CONFIG_IP_NF_MATCH_TTL is not set +# CONFIG_IP_NF_MATCH_TCPMSS is not set +# CONFIG_IP_NF_MATCH_HELPER is not set +CONFIG_IP_NF_MATCH_STATE=y +CONFIG_IP_NF_MATCH_CONNLIMIT=m +# CONFIG_IP_NF_MATCH_CONNTRACK is not set +# CONFIG_IP_NF_MATCH_OWNER is not set +CONFIG_IP_NF_FILTER=y +# CONFIG_IP_NF_TARGET_REJECT is not set +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_REDIRECT=y +# CONFIG_IP_NF_TARGET_NETMAP is not set +# CONFIG_IP_NF_TARGET_SAME is not set +# CONFIG_IP_NF_NAT_LOCAL is not set +# CONFIG_IP_NF_NAT_SNMP_BASIC is not set +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=y +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_NAT_IPSEC=m +CONFIG_IP_NF_NAT_RTSP=m +CONFIG_IP_NF_MANGLE=y +# CONFIG_IP_NF_TARGET_TOS is not set +CONFIG_IP_NF_TARGET_FTOS=y +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_DSCP is not set +CONFIG_IP_NF_TARGET_MARK=y +CONFIG_IP_NF_TARGET_CLASSIFY=y +CONFIG_IP_NF_TARGET_LOG=y +# CONFIG_IP_NF_TARGET_ULOG is not set +CONFIG_IP_NF_TARGET_TCPMSS=y +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_RAW is not set +# CONFIG_IP_NF_MATCH_ADDRTYPE is not set +# CONFIG_IP_NF_MATCH_REALM is not set +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_NAT_PPTP=m + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_BRIDGE_EBT_T_FILTER=y +# CONFIG_BRIDGE_EBT_T_NAT is not set +# CONFIG_BRIDGE_EBT_802_3 is not set +# CONFIG_BRIDGE_EBT_AMONG is not set +# CONFIG_BRIDGE_EBT_ARP is not set +CONFIG_BRIDGE_EBT_IP=y +# CONFIG_BRIDGE_EBT_LIMIT is not set +CONFIG_BRIDGE_EBT_MARK=y +# CONFIG_BRIDGE_EBT_PKTTYPE is not set +# CONFIG_BRIDGE_EBT_STP is not set +CONFIG_BRIDGE_EBT_VLAN=y +CONFIG_BRIDGE_EBT_TIME=y +# CONFIG_BRIDGE_EBT_ARPREPLY is not set +# CONFIG_BRIDGE_EBT_DNAT is not set +CONFIG_BRIDGE_EBT_MARK_T=y +# CONFIG_BRIDGE_EBT_REDIRECT is not set +# CONFIG_BRIDGE_EBT_SNAT is not set +CONFIG_BRIDGE_EBT_FTOS_T=y +CONFIG_BRIDGE_EBT_LOG=y + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +CONFIG_ATM=y +# CONFIG_ATM_CLIP is not set +# CONFIG_ATM_LANE is not set +CONFIG_ATM_BR2684=y +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_ATM_RT2684=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CLK_JIFFIES=y +CONFIG_NET_SCH_CBQ=y +CONFIG_NET_SCH_HTB=y +# CONFIG_NET_SCH_HFSC is not set +CONFIG_NET_SCH_ATM=y +CONFIG_NET_SCH_PRIO=y +# CONFIG_NET_SCH_RED is not set +CONFIG_NET_SCH_SFQ=y +# CONFIG_NET_SCH_TEQL is not set +CONFIG_NET_SCH_TBF=y +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_NETEM is not set +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_QOS=y +CONFIG_NET_ESTIMATOR=y +CONFIG_NET_CLS=y +CONFIG_NET_CLS_TCINDEX=y +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_ROUTE is not set +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +# CONFIG_CLS_U32_PERF is not set +# CONFIG_NET_CLS_IND is not set +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_CLS_POLICE=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +# CONFIG_HERMES is not set +# CONFIG_ATMEL is not set + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +# CONFIG_PRISM54 is not set +CONFIG_NET_WIRELESS=y + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_TCP is not set +# CONFIG_ATM_LANAI is not set +# CONFIG_ATM_ENI is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_ZATM is not set +# CONFIG_ATM_NICSTAR is not set +# CONFIG_ATM_IDT77252 is not set +# CONFIG_ATM_AMBASSADOR is not set +# CONFIG_ATM_HORIZON is not set +# CONFIG_ATM_IA is not set +# CONFIG_ATM_FORE200E_MAYBE is not set +# CONFIG_ATM_HE is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=y +CONFIG_PPPOATM=y +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Userland interfaces +# + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set +# CONFIG_SERIO_I8042 is not set + +# +# Input Device Drivers +# + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=8 +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=y + +# +# Video For Linux +# + +# +# Video Adapters +# +# CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_STRADIS is not set +# CONFIG_VIDEO_MXB is not set +# CONFIG_VIDEO_DPC is not set +# CONFIG_VIDEO_HEXIUM_ORION is not set +# CONFIG_VIDEO_HEXIUM_GEMINI is not set + +# +# Radio Adapters +# +# CONFIG_RADIO_GEMTEK_PCI is not set +# CONFIG_RADIO_MAXIRADIO is not set +# CONFIG_RADIO_MAESTRO is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB=y +CONFIG_USB_DEBUG=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_UHCI_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_USB_ACM is not set +CONFIG_USB_PRINTER=y +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_RW_DETECT is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_HP8200e is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set + +# +# USB Human Interface Devices (HID) +# +CONFIG_USB_HID=y + +# +# Input core support is needed for USB HID input layer or HIDBP support +# +CONFIG_USB_HIDDEV=y + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set +# CONFIG_USB_VICAM is not set +# CONFIG_USB_DSBR is not set +# CONFIG_USB_IBMCAM is not set +# CONFIG_USB_KONICAWC is not set +# CONFIG_USB_OV511 is not set +# CONFIG_USB_PWC is not set +# CONFIG_USB_SE401 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_STV680 is not set + +# +# USB Network adaptors +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_TIGL is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_SPEEDTOUCH is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_TEST is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=y +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_NAND is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +CONFIG_JFFS2_RUBIN=y +# CONFIG_JFFS2_CMODE_NONE is not set +# CONFIG_JFFS2_CMODE_PRIORITY is not set +CONFIG_JFFS2_CMODE_SIZE=y +CONFIG_SQUASHFS=y +# CONFIG_CRAMFS is not set +CONFIG_LZMA_FS_INFLATE=y +# CONFIG_ZLIB_FS_INFLATE is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +CONFIG_NLS_CODEPAGE_852=y +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +CONFIG_NLS_ISO8859_15=y +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +CONFIG_CRC_CCITT=y +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Naur linux-mips-2.6.8.1-orig/Makefile linux-mips-2.6.8.1-bcm/Makefile --- linux-mips-2.6.8.1-orig/Makefile 2004-08-14 20:13:22.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/Makefile 2006-12-20 18:52:27.000000000 +0100 @@ -403,6 +403,12 @@ core-y := usr/ endif # KBUILD_EXTMOD +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +export HPATH := $(TOPDIR)/include +brcmdrivers-y := $(INC_BRCMBOARDPARMS_PATH)/$(BRCM_BOARD)/ $(BRCMDRIVERS_DIR)/ $(INC_FLASH_PATH)/ +BRCMDRIVERS := $(brcmdrivers-y) +# CONFIG_MIPS_BRCM End Broadcom changed code. + ifeq ($(dot-config),1) # In this section, we need .config @@ -471,6 +477,10 @@ # makefile but the arguement can be passed to make if needed. # +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +INSTALL_MOD_PATH := $(PROFILE_DIR)/modules +# CONFIG_MIPS_BRCM End Broadcom changed code. + MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) export MODLIB @@ -478,18 +488,25 @@ ifeq ($(KBUILD_EXTMOD),) core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ +# CONFIG_MIPS_BRCM Begin Broadcom changed code. vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ $(core-y) $(core-m) $(drivers-y) $(drivers-m) \ + $(brcmdrivers-y) $(brcmdrivers-m) \ $(net-y) $(net-m) $(libs-y) $(libs-m))) vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \ $(init-n) $(init-) \ $(core-n) $(core-) $(drivers-n) $(drivers-) \ + $(brcmdrivers-n) $(brcmdrivers-) \ $(net-n) $(net-) $(libs-n) $(libs-)))) +# CONFIG_MIPS_BRCM End Broadcom changed code. init-y := $(patsubst %/, %/built-in.o, $(init-y)) core-y := $(patsubst %/, %/built-in.o, $(core-y)) drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y)) +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +brcmdrivers-y := $(patsubst %/, %/built-in.o, $(brcmdrivers-y)) +# CONFIG_MIPS_BRCM End Broadcom changed code. net-y := $(patsubst %/, %/built-in.o, $(net-y)) libs-y1 := $(patsubst %/, %/lib.a, $(libs-y)) libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y)) @@ -505,7 +522,8 @@ # we cannot yet know if we will need to relink vmlinux. # So we descend into init/ inside the rule for vmlinux again. head-y += $(HEAD) -vmlinux-objs := $(head-y) $(init-y) $(core-y) $(libs-y) $(drivers-y) $(net-y) +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +vmlinux-objs := $(head-y) $(init-y) $(core-y) $(libs-y) $(drivers-y) $(brcmdrivers-y) $(net-y) quiet_cmd_vmlinux__ = LD $@ define cmd_vmlinux__ @@ -514,11 +532,13 @@ $(core-y) \ $(libs-y) \ $(drivers-y) \ + $(brcmdrivers-y) \ $(net-y) \ --end-group \ $(filter .tmp_kallsyms%,$^) \ -o $@ endef +# CONFIG_MIPS_BRCM End Broadcom changed code. # set -e makes the rule exit immediately on error @@ -601,8 +621,10 @@ $(rule_verify_kallsyms) endef -vmlinux: $(vmlinux-objs) $(kallsyms.o) arch/$(ARCH)/kernel/vmlinux.lds.s FORCE +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +vmlinux: preparebrcmdriver $(vmlinux-objs) $(kallsyms.o) arch/$(ARCH)/kernel/vmlinux.lds.s FORCE $(call if_changed_rule,vmlinux) +# CONFIG_MIPS_BRCM End Broadcom changed code. # The actual objects are generated when descending, # make sure no implicit rule kicks in @@ -624,7 +646,12 @@ # A multi level approach is used. prepare1 is updated first, then prepare0. # prepare-all is the collection point for the prepare targets. -.PHONY: prepare-all prepare prepare0 prepare1 prepare2 +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +.PHONY: prepare-all prepare prepare0 prepare1 prepare2 preparebrcmdriver + +preparebrcmdriver: + $(Q)$(MAKE) -C $(BRCMDRIVERS_DIR) symlinks +# CONFIG_MIPS_BRCM End Broadcom changed code. # prepare 2 generate Makefile to be placed in output directory, if # using a seperate output directory. This allows convinient use @@ -741,7 +768,9 @@ # Build modules .PHONY: modules -modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +modules: preparebrcmdriver $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) +# CONFIG_MIPS_BRCM End Broadcom changed code. @echo ' Building modules, stage 2.'; $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost @@ -752,23 +781,31 @@ # Target to install modules .PHONY: modules_install -modules_install: _modinst_ _modinst_post +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +#modules_install: _modinst_ _modinst_post +#We have no need for it "_modinst_post" +modules_install: _modinst_ +# CONFIG_MIPS_BRCM End Broadcom changed code. .PHONY: _modinst_ _modinst_: - @if [ -z "`$(DEPMOD) -V | grep module-init-tools`" ]; then \ - echo "Warning: you may need to install module-init-tools"; \ - echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\ - sleep 1; \ - fi +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +# @if [ -z "`$(DEPMOD) -V | grep module-init-tools`" ]; then \ +# echo "Warning: you may need to install module-init-tools"; \ +# echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\ +# sleep 1; \ +# fi +# CONFIG_MIPS_BRCM End Broadcom changed code. @rm -rf $(MODLIB)/kernel @rm -f $(MODLIB)/source @mkdir -p $(MODLIB)/kernel - @ln -s $(srctree) $(MODLIB)/source - @if [ ! $(objtree) -ef $(MODLIB)/build ]; then \ - rm -f $(MODLIB)/build ; \ - ln -s $(objtree) $(MODLIB)/build ; \ - fi +# CONFIG_MIPS_BRCM Begin Broadcom changed code +# @ln -s $(srctree) $(MODLIB)/source +# @if [ ! $(objtree) -ef $(MODLIB)/build ]; then \ +# rm -f $(MODLIB)/build ; \ +# ln -s $(objtree) $(MODLIB)/build ; \ +# fi +# CONFIG_MIPS_BRCM End Broadcom changed code. $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modinst # If System.map exists, run depmod. This deliberately does not have a @@ -851,10 +888,12 @@ clean: archclean $(clean-dirs) $(call cmd,rmdirs) $(call cmd,rmfiles) - @find . $(RCS_FIND_IGNORE) \ +# CONFIG_MIPS_BRCM Begin Broadcom changed code. + @find . $(BRCMDRIVERS) $(RCS_FIND_IGNORE) \ \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \ -type f -print | xargs rm -f +# CONFIG_MIPS_BRCM End Broadcom changed code. # mrproper - Delete all generated files, including .config # diff -Naur linux-mips-2.6.8.1-orig/mm/oom_kill.c linux-mips-2.6.8.1-bcm/mm/oom_kill.c --- linux-mips-2.6.8.1-orig/mm/oom_kill.c 2004-08-06 02:33:32.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/mm/oom_kill.c 2006-12-20 18:47:15.000000000 +0100 @@ -266,6 +266,11 @@ if (since < HZ*5) goto out_unlock; +#if defined(CONFIG_MIPS_BRCM) + /* Killing processes on an embedded system won't help */ + /* Print a warning message instead */ + printk("Warning: Low memory condition - consider removing some software components\n"); +#else /* * Ok, really out of memory. Kill something. */ @@ -278,6 +283,7 @@ spin_unlock(&oom_lock); oom_kill(); spin_lock(&oom_lock); +#endif reset: /* diff -Naur linux-mips-2.6.8.1-orig/mm/page_alloc.c linux-mips-2.6.8.1-bcm/mm/page_alloc.c --- linux-mips-2.6.8.1-orig/mm/page_alloc.c 2004-08-13 09:18:56.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/mm/page_alloc.c 2006-12-20 18:47:15.000000000 +0100 @@ -1880,6 +1880,7 @@ for_each_zone(zone) { spin_lock_irqsave(&zone->lru_lock, flags); +#if 0 if (is_highmem(zone)) { /* * Often, highmem doesn't need to reserve any pages. @@ -1902,9 +1903,15 @@ zone->pages_min = (pages_min * zone->present_pages) / lowmem_pages; } - zone->pages_low = zone->pages_min * 2; zone->pages_high = zone->pages_min * 3; +#else + /* Tuned watermarks for better out of memory performance on our swapless system */ + zone->pages_min = 0; /* disable aggressive scanning as it can lock up the system */ + zone->pages_low = 42; + zone->pages_high = 44; +#endif + spin_unlock_irqrestore(&zone->lru_lock, flags); } } diff -Naur linux-mips-2.6.8.1-orig/mm/vmscan.c linux-mips-2.6.8.1-bcm/mm/vmscan.c --- linux-mips-2.6.8.1-orig/mm/vmscan.c 2004-08-06 02:33:32.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/mm/vmscan.c 2006-12-20 18:47:15.000000000 +0100 @@ -1065,6 +1065,7 @@ shrink_slab(sc.nr_scanned, GFP_KERNEL, lru_pages); sc.nr_reclaimed += reclaim_state->reclaimed_slab; total_reclaimed += sc.nr_reclaimed; + total_scanned += sc.nr_scanned; if (zone->all_unreclaimable) continue; if (zone->pages_scanned > zone->present_pages * 2) diff -Naur linux-mips-2.6.8.1-orig/net/8021q/vlan_dev.c linux-mips-2.6.8.1-bcm/net/8021q/vlan_dev.c --- linux-mips-2.6.8.1-orig/net/8021q/vlan_dev.c 2004-08-14 18:16:44.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/8021q/vlan_dev.c 2007-01-19 17:16:58.000000000 +0100 @@ -244,7 +244,10 @@ /* TODO: Add a more specific counter here. */ stats->rx_errors++; } - rcu_read_lock(); + // OG Path comment ou lock to unlock + // http://oss.sgi.com/projects/netdev/archive/2004-09/msg00254.html + //rcu_read_lock(); + rcu_read_unlock(); return 0; } diff -Naur linux-mips-2.6.8.1-orig/net/atm/br2684.c linux-mips-2.6.8.1-bcm/net/atm/br2684.c --- linux-mips-2.6.8.1-orig/net/atm/br2684.c 2004-08-06 02:33:32.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/atm/br2684.c 2006-12-20 18:45:18.000000000 +0100 @@ -34,6 +34,8 @@ * if we need space for the header */ /* #define FASTER_VERSION */ +//#define VLAN_DEBUG +//#define SKB_DEBUG #ifdef DEBUG #define DPRINTK(format, args...) printk(KERN_DEBUG "br2684: " format, ##args) @@ -79,6 +81,17 @@ #ifndef FASTER_VERSION unsigned copies_needed, copies_failed; #endif /* FASTER_VERSION */ +#if defined(CONFIG_MIPS_BRCM) + /* Protocol filter flag, currently only PPPoE. + When turned on, all non-PPPoE traffic will be dropped + on this PVC */ + int proto_filter; +#ifdef SUPPORT_VLAN + unsigned short vlan_id; /* vlan id (0-4096) */ +#endif // SUPPORT_VLAN + + +#endif }; struct br2684_dev { @@ -90,6 +103,10 @@ int mac_was_set; }; +#if defined(CONFIG_MIPS_BRCM) +#define MIN_PKT_SIZE 70 +#endif + /* * This lock should be held for writing any time the list of devices or * their attached vcc's could be altered. It should be held for reading @@ -145,6 +162,70 @@ return NULL; } +#ifdef SUPPORT_VLAN +#include +/** + * vlan_tag_insert - regular VLAN tag inserting + * @skb: skbuff to tag + * @tag: VLAN tag to insert + * + * Inserts the VLAN tag into @skb as part of the payload + * Returns a VLAN tagged skb. If a new skb is created, @skb is freed. + * + * Following the skb_unshare() example, in case of error, the calling function + * doesn't have to worry about freeing the original skb. + */ +#define ATM_HEADER_LEN 10 +#define ATM_AND_MAC_LEN ((ATM_HEADER_LEN) + (2 * VLAN_ETH_ALEN)) + +struct atm_vlan_ethhdr { + unsigned char h_atm_stuff[ATM_HEADER_LEN]; /* atm stuff 10 bytes */ + unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ + unsigned char h_source[ETH_ALEN]; /* source ether addr */ + unsigned short h_vlan_proto; /* Should always be 0x8100 */ + unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID */ + unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */ +}; + +static inline struct sk_buff *vlan_tag_insert(struct sk_buff *skb, unsigned short tag) +{ + struct atm_vlan_ethhdr *veth; + + if (skb_headroom(skb) < VLAN_HLEN) { + struct sk_buff *sk_tmp = skb; + skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN); + kfree_skb(sk_tmp); + if (!skb) { + printk(KERN_ERR "vlan: failed to realloc headroom\n"); + return NULL; + } + } else { + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) { + printk(KERN_ERR "vlan: failed to unshare skbuff\n"); + return NULL; + } + } + + veth = (struct atm_vlan_ethhdr *)skb_push(skb, VLAN_HLEN); + + /* Move the mac addresses to the beginning of the new header. */ + memmove(skb->data, skb->data + VLAN_HLEN, (2 * VLAN_ETH_ALEN) + ATM_HEADER_LEN); + + /* first, the ethernet type */ + veth->h_vlan_proto = __constant_htons(ETH_P_8021Q); + + /* now, the tag */ + veth->h_vlan_TCI = htons(tag); + + skb->protocol = __constant_htons(ETH_P_8021Q); + skb->mac.raw -= VLAN_HLEN; + skb->nh.raw -= VLAN_HLEN; + + return skb; +} +#endif // SUPPORT_VLAN + /* * Send a packet out a particular vcc. Not to useful right now, but paves * the way for multiple vcc's per itf. Returns true if we can send, @@ -154,6 +235,7 @@ struct br2684_vcc *brvcc) { struct atm_vcc *atmvcc; + #ifdef FASTER_VERSION if (brvcc->encaps == e_llc) memcpy(skb_push(skb, 8), llc_oui_pid_pad, 8); @@ -178,7 +260,56 @@ else memset(skb->data, 0, 2); #endif /* FASTER_VERSION */ - skb_debug(skb); + +#if defined(CONFIG_MIPS_BRCM) + if (skb->len < MIN_PKT_SIZE) + { + struct sk_buff *skb2=skb_copy_expand(skb, 0, MIN_PKT_SIZE - skb->len, GFP_ATOMIC); + dev_kfree_skb(skb); + if (skb2 == NULL) { + brvcc->copies_failed++; + return 0; + } + skb = skb2; + memset(skb->tail, 0, MIN_PKT_SIZE - skb->len); + skb_put(skb, MIN_PKT_SIZE - skb->len); + } +#endif + +#ifdef SUPPORT_VLAN +#ifdef VLAN_DEBUG + printk("=====> br2684_xmit_vcc bef add vlan tag, skb->len=0x%04x\n", skb->len); + skb_debug(skb); +#endif // VLAN_DEBUG + + /* Construct the second two bytes. This field looks something + * like: + * usr_priority: 3 bits (high bits) + * CFI 1 bit + * VLAN ID 12 bits (low bits) + */ + //brvcc->vlan_id |= vlan_dev_get_egress_qos_mask(dev, skb); + /* bit 3-0 of the 32-bit nfmark is the atm priority, set by iptables + * bit 7-4 is the Ethernet switch physical port number, set by lan port drivers. + * bit 8-11 is the wanVlan priority bits + */ + if (brvcc->vlan_id != 0xffff) { + brvcc->vlan_id &= 0xffff0fff; // clear the priority bits first + // if bit 8-11 is set (none zeros), add in the priority bits + if (skb->nfmark & 0x0000f000) { + brvcc->vlan_id |= (skb->nfmark & 0x0000f000); + } + skb = vlan_tag_insert(skb, brvcc->vlan_id); + if (!skb) { + brdev->stats.tx_dropped++; + return 1; + } +#ifdef VLAN_DEBUG + printk("=====> br2684_xmit_vcc aft add vlan tag, skb->len=%d\n", skb->len); + skb_debug(skb); +#endif // VLAN_DEBUG + } +#endif // SUPPORT_VLAN ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc; DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev); @@ -194,7 +325,13 @@ ATM_SKB(skb)->atm_options = atmvcc->atm_options; brdev->stats.tx_packets++; brdev->stats.tx_bytes += skb->len; +#if defined(CONFIG_MIPS_BRCM) + if (atmvcc->send(atmvcc, skb) != 0) + brdev->stats.tx_dropped++; +#else atmvcc->send(atmvcc, skb); +#endif + return 1; } @@ -209,7 +346,6 @@ { struct br2684_dev *brdev = BRPRIV(dev); struct br2684_vcc *brvcc; - DPRINTK("br2684_start_xmit, skb->dst=%p\n", skb->dst); read_lock(&devs_lock); brvcc = pick_outgoing_vcc(skb, brdev); @@ -222,6 +358,23 @@ read_unlock(&devs_lock); return -EUNATCH; } + +#if defined(CONFIG_MIPS_BRCM) + if (brvcc->proto_filter & FILTER_PPPOE) { + if ((skb->protocol != htons(ETH_P_PPP_DISC)) && (skb->protocol != htons(ETH_P_PPP_SES))) { + DPRINTK("non-PPPOE packet dropped on TX dev %s\n", dev->name); + dev_kfree_skb(skb); + read_unlock(&devs_lock); + return 0; + } + } +#endif + +#ifdef VLAN_DEBUG + if (brvcc->vlan_id != 0xffff) + printk("=====> br2684_start_xmit vlan_id=0x%04x\n", brvcc->vlan_id); +#endif // VLAN_DEBUG + if (!br2684_xmit_vcc(skb, brdev, brvcc)) { /* * We should probably use netif_*_queue() here, but that @@ -424,8 +577,10 @@ } return; } +#if defined(CONFIG_MIPS_BRCM) + //skb->__unused=FROM_WAN; +#endif - skb_debug(skb); atm_return(atmvcc, skb->truesize); DPRINTK("skb from brdev %p\n", brdev); if (brvcc->encaps == e_llc) { @@ -455,6 +610,28 @@ dev_kfree_skb(skb); /* dev_ not needed? */ return; } +#ifdef SUPPORT_VLAN + if (brvcc->vlan_id != 0xffff) { /* Vcc was configured to be vlan tagged*/ + unsigned tmp[ATM_AND_MAC_LEN]; +#ifdef VLAN_DEBUG + printk("=====> before removing vlan id\n"); + skb_debug(skb); +#endif +/* +** There exist a situation where we tag vlan id upstream. But DSLAM sends untagged frame downstream. So we need to check this situation before we move data around +*/ +//eddie added if {} + if ( skb->data[22] == 0x81 && skb->data[23] == 0x0) { + memcpy(tmp, skb->data, ATM_AND_MAC_LEN); + skb_pull(skb, VLAN_HLEN); + memcpy(skb->data, tmp, ATM_AND_MAC_LEN); + } +#ifdef VLAN_DEBUG + printk("=====> after removing vlan id\n"); + skb_debug(skb); +#endif + } +#endif // SUPPORT_VLAN #ifdef FASTER_VERSION /* FIXME: tcpdump shows that pointer to mac header is 2 bytes earlier, @@ -478,10 +655,20 @@ return; } #endif /* CONFIG_ATM_BR2684_IPFILTER */ - skb->dev = net_dev; +#if defined(CONFIG_MIPS_BRCM) + if (brvcc->proto_filter & FILTER_PPPOE) { + if ((skb->protocol != htons(ETH_P_PPP_DISC)) && (skb->protocol != htons(ETH_P_PPP_SES))) { + DPRINTK("non-PPPOE packet dropped on RX dev %s\n", net_dev->name); + dev_kfree_skb(skb); + return; + } + } +#endif + + skb->dev = net_dev; ATM_SKB(skb)->vcc = atmvcc; /* needed ? */ DPRINTK("received packet's protocol: %x\n", ntohs(skb->protocol)); - skb_debug(skb); + if (unlikely(!(net_dev->flags & IFF_UP))) { /* sigh, interface is down */ brdev->stats.rx_dropped++; @@ -491,6 +678,7 @@ brdev->stats.rx_packets++; brdev->stats.rx_bytes += skb->len; memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); + netif_rx(skb); } @@ -554,6 +742,12 @@ atmvcc->user_back = brvcc; brvcc->encaps = (enum br2684_encaps) be.encaps; brvcc->old_push = atmvcc->push; +#if defined(CONFIG_MIPS_BRCM) + brvcc->proto_filter |= be.proto_filter; +#ifdef SUPPORT_VLAN + brvcc->vlan_id = be.vlan_id; +#endif // SUPPORT_VLAN +#endif barrier(); atmvcc->push = br2684_push; skb_queue_head_init(©); diff -Naur linux-mips-2.6.8.1-orig/net/atm/common.c linux-mips-2.6.8.1-bcm/net/atm/common.c --- linux-mips-2.6.8.1-orig/net/atm/common.c 2004-06-28 23:04:17.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/atm/common.c 2006-12-20 18:45:18.000000000 +0100 @@ -240,8 +240,15 @@ default: printk(KERN_WARNING "ATM: AAL problems ... " "(%d)\n",aal); - /* fall through */ + /* fall through */ case ATM_AAL5: +#if defined(CONFIG_MIPS_BRCM) + /* Use a big max sdu within Linux. It will be verified by the + * Broadcom ATM driver. + */ + case ATM_AAL2: + case ATM_BCM_AAL0: +#endif max_sdu = ATM_MAX_AAL5_PDU; } if (!tp->max_sdu) tp->max_sdu = max_sdu; @@ -362,6 +369,13 @@ vcc->qos.aal = ATM_AAL5; /* fall through */ case ATM_AAL5: +#if defined(CONFIG_MIPS_BRCM) + /* All aal types must call atm_init_aal5 so that send packets go to + * the Broadcom blaa driver. + */ + case ATM_AAL2: + case ATM_BCM_AAL0: +#endif error = atm_init_aal5(vcc); vcc->stats = &dev->stats.aal5; break; @@ -413,6 +427,18 @@ else if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) return -EINVAL; +#if defined(CONFIG_MIPS_BRCM) + DPRINTK("vcc_connect (TX: cl %d,bw %d-%d,sdu %d; " + "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n", + vcc->qos.txtp.traffic_class,vcc->qos.txtp.min_pcr, + vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu, + vcc->qos.rxtp.traffic_class,vcc->qos.rxtp.min_pcr, + vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu, + vcc->qos.aal == ATM_AAL5 ? "" : (vcc->qos.aal == ATM_AAL0 || + vcc->qos.aal == ATM_BCM_AAL0) ? "" : " ??? code ", + (vcc->qos.aal == ATM_AAL0 || vcc->qos.aal == ATM_BCM_AAL0) ? 0 + : vcc->qos.aal); +#else DPRINTK("vcc_connect (TX: cl %d,bw %d-%d,sdu %d; " "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n", vcc->qos.txtp.traffic_class,vcc->qos.txtp.min_pcr, @@ -421,6 +447,7 @@ vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu, vcc->qos.aal == ATM_AAL5 ? "" : vcc->qos.aal == ATM_AAL0 ? "" : " ??? code ",vcc->qos.aal == ATM_AAL0 ? 0 : vcc->qos.aal); +#endif if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) return -EBADFD; if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS || diff -Naur linux-mips-2.6.8.1-orig/net/atm/Makefile linux-mips-2.6.8.1-bcm/net/atm/Makefile --- linux-mips-2.6.8.1-orig/net/atm/Makefile 2003-09-30 16:27:31.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/atm/Makefile 2006-12-20 18:45:18.000000000 +0100 @@ -1,6 +1,9 @@ # # Makefile for the ATM Protocol Families. # +ifneq ($(strip $(BUILD_BRCM_VLAN)),) +CFLAGS += -DSUPPORT_VLAN +endif atm-y := addr.o pvc.o signaling.o svc.o ioctl.o common.o atm_misc.o raw.o resources.o mpoa-objs := mpc.o mpoa_caches.o mpoa_proc.o @@ -11,6 +14,10 @@ obj-$(CONFIG_ATM_BR2684) += br2684.o atm-$(subst m,y,$(CONFIG_ATM_BR2684)) += ipcommon.o atm-$(subst m,y,$(CONFIG_NET_SCH_ATM)) += ipcommon.o +# CONFIG_MIPS_BRCM Begin Broadcom added code. +obj-$(CONFIG_ATM_RT2684) += rt2684.o +atm-$(subst m,y,$(CONFIG_ATM_RT2684)) += ipcommon.o +# CONFIG_MIPS_BRCM End Broadcom added code. atm-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_ATM_LANE) += lec.o diff -Naur linux-mips-2.6.8.1-orig/net/atm/rt2684.c linux-mips-2.6.8.1-bcm/net/atm/rt2684.c --- linux-mips-2.6.8.1-orig/net/atm/rt2684.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/atm/rt2684.c 2006-12-20 18:45:18.000000000 +0100 @@ -0,0 +1,693 @@ +/* + * net/atm/rt2684.c - RFC1577 Classical IP over ATM + * + * shrinked version: only handles encapsulation + * (no atmarp handling) + * + * Song Wang (songw@broadcom.com) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ipcommon.h" + +/*#define DEBUG*/ +#ifdef DEBUG +#define DPRINTK(format, args...) printk(KERN_DEBUG "rt2684: " format, ##args) +#else +#define DPRINTK(format, args...) +#endif + +#ifdef SKB_DEBUG +static void skb_debug(const struct sk_buff *skb) +{ +#define NUM2PRINT 50 + char buf[NUM2PRINT * 3 + 1]; /* 3 chars per byte */ + int i = 0; + for (i = 0; i < skb->len && i < NUM2PRINT; i++) { + sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]); + } + printk(KERN_DEBUG "rt2684: skb: %s\n", buf); +} +#else +#define skb_debug(skb) do {} while (0) +#endif + +struct rt2684_vcc { + struct atm_vcc *atmvcc; + struct rt2684_dev *rtdev; + + int xoff; /* 1 if send buffer is full */ + unsigned long last_use; /* last send or receive operation */ + unsigned long idle_timeout; /* keep open idle for so many jiffies*/ + void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb); + /* keep old push fn for chaining */ + void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); + /* keep old pop fn for chaining */ + unsigned char encap; /* 0: NULL, 1: LLC/SNAP */ + struct list_head rtvccs; + + +#ifdef CONFIG_ATM_rt2684_IPFILTER + struct rt2684_filter filter; +#endif /* CONFIG_ATM_rt2684_IPFILTER */ +#ifndef FASTER_VERSION + unsigned copies_needed, copies_failed; +#endif /* FASTER_VERSION */ +}; + +struct rt2684_dev { + struct net_device net_dev; + struct list_head rt2684_devs; + int number; + struct list_head rtvccs; /* one device <=> one vcc (before xmas) */ + struct net_device_stats stats; + spinlock_t xoff_lock; /* ensures that pop is atomic (SMP) */ + +}; + +/* + * This lock should be held for writing any time the list of devices or + * their attached vcc's could be altered. It should be held for reading + * any time these are being queried. Note that we sometimes need to + * do read-locking under interrupt context, so write locking must block + * the current CPU's interrupts + */ +static rwlock_t devs_lock = RW_LOCK_UNLOCKED; + +static LIST_HEAD(rt2684_devs); + +static const unsigned char llc_oui[] = { + 0xaa, /* DSAP: non-ISO */ + 0xaa, /* SSAP: non-ISO */ + 0x03, /* Ctrl: Unnumbered Information Command PDU */ + 0x00, /* OUI: EtherType */ + 0x00, + 0x00 }; + +static inline struct rt2684_dev *RTPRIV(const struct net_device *net_dev) +{ + return (struct rt2684_dev *) ((char *) (net_dev) - + (unsigned long) (&((struct rt2684_dev *) 0)->net_dev)); +} + +static inline struct rt2684_dev *list_entry_rtdev(const struct list_head *le) +{ + return list_entry(le, struct rt2684_dev, rt2684_devs); +} + +static inline struct rt2684_vcc *RT2684_VCC(const struct atm_vcc *atmvcc) +{ + return (struct rt2684_vcc *) (atmvcc->user_back); +} + +static inline struct rt2684_vcc *list_entry_rtvcc(const struct list_head *le) +{ + return list_entry(le, struct rt2684_vcc, rtvccs); +} + +/* Caller should hold read_lock(&devs_lock) */ +static struct rt2684_dev *rt2684_find_dev(const struct rt2684_if_spec *s) +{ + struct list_head *lh; + struct rt2684_dev *rtdev; + switch (s->method) { + case RT2684_FIND_BYNUM: + list_for_each(lh, &rt2684_devs) { + rtdev = list_entry_rtdev(lh); + if (rtdev->number == s->spec.devnum) + return rtdev; + } + break; + case RT2684_FIND_BYIFNAME: + list_for_each(lh, &rt2684_devs) { + rtdev = list_entry_rtdev(lh); + if (!strncmp(rtdev->net_dev.name, s->spec.ifname, + sizeof rtdev->net_dev.name)) + return rtdev; + } + break; + } + return NULL; +} + +static inline struct rt2684_vcc *pick_outgoing_vcc(struct sk_buff *skb, + struct rt2684_dev *rtdev) +{ + return list_empty(&rtdev->rtvccs) ? NULL : + list_entry_rtvcc(rtdev->rtvccs.next); /* 1 vcc/dev right now */ +} + +/* + * Send a packet out a particular vcc. + */ +static int rt2684_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct rt2684_dev *rtdev = RTPRIV(dev); + struct rt2684_vcc *rtvcc; + struct atm_vcc *atmvcc; + int old; + unsigned long flags; + + DPRINTK("rt2684_start_xmit, skb->dst=%p\n", skb->dst); + read_lock(&devs_lock); + rtvcc = pick_outgoing_vcc(skb, rtdev); + if (rtvcc == NULL) { + DPRINTK("no vcc attached to dev %s\n", dev->name); + rtdev->stats.tx_errors++; + rtdev->stats.tx_carrier_errors++; + /* netif_stop_queue(dev); */ + dev_kfree_skb(skb); + read_unlock(&devs_lock); + return -EUNATCH; + } + + if (rtvcc->encap) { + void *here; + + here = skb_push(skb,RFC1483LLC_LEN); + memcpy(here,llc_oui,sizeof(llc_oui)); + ((u16 *) here)[3] = skb->protocol; + } + + skb_debug(skb); + ATM_SKB(skb)->vcc = atmvcc = rtvcc->atmvcc; + DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev); + if (!atm_may_send(atmvcc, skb->truesize)) { + /* we free this here for now, because we cannot know in a higher + layer whether the skb point it supplied wasn't freed yet. + now, it always is. + */ + dev_kfree_skb(skb); + return 0; + } + atomic_add(skb->truesize,&atmvcc->sk->sk_wmem_alloc); + ATM_SKB(skb)->atm_options = atmvcc->atm_options; + rtvcc->last_use = jiffies; + DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n",skb,atmvcc,atmvcc->dev); + old = xchg(&rtvcc->xoff,1); /* assume XOFF ... */ + if (old) { + printk(KERN_WARNING "rt2684_start_xmit: XOFF->XOFF transition\n"); + return 0; + } + rtdev->stats.tx_packets++; + rtdev->stats.tx_bytes += skb->len; + if( atmvcc->send(atmvcc, skb) != 0 ) + rtdev->stats.tx_dropped++; + + if (atm_may_send(atmvcc,0)) { + rtvcc->xoff = 0; + return 0; + } + spin_lock_irqsave(&rtdev->xoff_lock,flags); + netif_stop_queue(dev); /* XOFF -> throttle immediately */ + barrier(); + if (!rtvcc->xoff) + netif_start_queue(dev); + /* Oh, we just raced with rt2684_pop. netif_start_queue should be + good enough, because nothing should really be asleep because + of the brief netif_stop_queue. If this isn't true or if it + changes, use netif_wake_queue instead. */ + spin_unlock_irqrestore(&rtdev->xoff_lock,flags); + + read_unlock(&devs_lock); + return 0; +} + +static struct net_device_stats *rt2684_get_stats(struct net_device *dev) +{ + DPRINTK("rt2684_get_stats\n"); + return &RTPRIV(dev)->stats; +} + +#ifdef CONFIG_ATM_rt2684_IPFILTER +/* this IOCTL is experimental. */ +static int rt2684_setfilt(struct atm_vcc *atmvcc, unsigned long arg) +{ + struct rt2684_vcc *rtvcc; + struct rt2684_filter_set fs; + + if (copy_from_user(&fs, (void *) arg, sizeof fs)) + return -EFAULT; + if (fs.ifspec.method != RT2684_FIND_BYNOTHING) { + /* + * This is really a per-vcc thing, but we can also search + * by device + */ + struct rt2684_dev *rtdev; + read_lock(&devs_lock); + rtdev = rt2684_find_dev(&fs.ifspec); + if (rtdev == NULL || list_empty(&rtdev->rtvccs) || + rtdev->rtvccs.next != rtdev->rtvccs.prev) /* >1 VCC */ + rtvcc = NULL; + else + rtvcc = list_entry_rtvcc(rtdev->rtvccs.next); + read_unlock(&devs_lock); + if (rtvcc == NULL) + return -ESRCH; + } else + rtvcc = rt2684_VCC(atmvcc); + memcpy(&rtvcc->filter, &fs.filter, sizeof(rtvcc->filter)); + return 0; +} + +/* Returns 1 if packet should be dropped */ +static inline int +packet_fails_filter(u16 type, struct rt2684_vcc *rtvcc, struct sk_buff *skb) +{ + if (rtvcc->filter.netmask == 0) + return 0; /* no filter in place */ + if (type == __constant_htons(ETH_P_IP) && + (((struct iphdr *) (skb->data))->daddr & rtvcc->filter. + netmask) == rtvcc->filter.prefix) + return 0; + if (type == __constant_htons(ETH_P_ARP)) + return 0; + /* TODO: we should probably filter ARPs too.. don't want to have + * them returning values that don't make sense, or is that ok? + */ + return 1; /* drop */ +} +#endif /* CONFIG_ATM_rt2684_IPFILTER */ + +static void rt2684_close_vcc(struct rt2684_vcc *rtvcc) +{ + DPRINTK("removing VCC %p from dev %p\n", rtvcc, rtvcc->rtdev); + write_lock_irq(&devs_lock); + list_del(&rtvcc->rtvccs); + write_unlock_irq(&devs_lock); + rtvcc->atmvcc->user_back = NULL; /* what about vcc->recvq ??? */ + rtvcc->old_push(rtvcc->atmvcc, NULL); /* pass on the bad news */ + kfree(rtvcc); +} + +static void rt2684_pop(struct atm_vcc *atmvcc,struct sk_buff *skb) +{ + struct rt2684_vcc *rtvcc = RT2684_VCC(atmvcc); + struct rt2684_dev *rtdev = rtvcc->rtdev; + struct net_device *dev = skb->dev; + int old; + unsigned long flags; + + DPRINTK("rt2684_pop(vcc %p)\n",atmvcc); + rtvcc->old_pop(atmvcc,skb); + /* skb->dev == NULL in outbound ARP packets */ + if (!dev) return; + spin_lock_irqsave(&rtdev->xoff_lock,flags); + if (atm_may_send(atmvcc,0)) { + old = xchg(&rtvcc->xoff,0); + if (old) netif_wake_queue(dev); + } + spin_unlock_irqrestore(&rtdev->xoff_lock,flags); +} + +/* when AAL5 PDU comes in: */ +static void rt2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) +{ + struct rt2684_vcc *rtvcc = RT2684_VCC(atmvcc); + struct rt2684_dev *rtdev = rtvcc->rtdev; + + DPRINTK("rt2684_push\n"); + + if (skb == NULL) { /* skb==NULL means VCC is being destroyed */ + rt2684_close_vcc(rtvcc); + return; + } + +#if defined(CONFIG_MIPS_BRCM) +// skb->__unused=FROM_WAN; +#endif + skb_debug(skb); + atm_return(atmvcc, skb->truesize); + DPRINTK("skb from rtdev %p\n", rtdev); + + skb->dev = &rtdev->net_dev; + if (!skb->dev) { + dev_kfree_skb_any(skb); + return; + } + ATM_SKB(skb)->vcc = atmvcc; + skb->mac.raw = skb->data; + if (!rtvcc->encap || skb->len < RFC1483LLC_LEN || memcmp(skb->data, + llc_oui,sizeof(llc_oui))) skb->protocol = htons(ETH_P_IP); + else { + skb->protocol = ((u16 *) skb->data)[3]; + skb_pull(skb,RFC1483LLC_LEN); + } + DPRINTK("received packet's protocol: %x\n", ntohs(skb->protocol)); + skb_debug(skb); + rtvcc->last_use = jiffies; + if (!(rtdev->net_dev.flags & IFF_UP)) { /* sigh, interface is down */ + rtdev->stats.rx_dropped++; + dev_kfree_skb(skb); + return; + } + rtdev->stats.rx_packets++; + rtdev->stats.rx_bytes += skb->len; + memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); + netif_rx(skb); +} + +/* assign a vcc to a dev +Note: we do not have explicit unassign, but look at _push() +*/ +static int rt2684_regvcc(struct atm_vcc *atmvcc, unsigned long arg) +{ + + int err; + struct rt2684_vcc *rtvcc; + struct sk_buff_head copy; + struct sk_buff *skb; + struct rt2684_dev *rtdev; + struct atm_backend_rt2684 be; + + if (copy_from_user(&be, (void *) arg, sizeof be)) { + return -EFAULT; + } + write_lock_irq(&devs_lock); + /* Find the atmxxx device according to the interface name */ + rtdev = rt2684_find_dev(&be.ifspec); + if (rtdev == NULL) { + printk(KERN_ERR + "rt2684: tried to attach to non-existant device\n"); + err = -ENXIO; + goto error; + } + if (atmvcc->push == NULL) { + err = -EBADFD; + goto error; + } + if (!list_empty(&rtdev->rtvccs)) { /* Only 1 VCC/dev right now */ + err = -EEXIST; + goto error; + } + rtvcc = kmalloc(sizeof(struct rt2684_vcc), GFP_KERNEL); + if (!rtvcc) { + err = -ENOMEM; + goto error; + } + memset(rtvcc, 0, sizeof(struct rt2684_vcc)); + DPRINTK("rt2684_regvcc vcc=%p, encaps=%d, rtvcc=%p\n", atmvcc, be.encaps, + rtvcc); + list_add(&rtvcc->rtvccs, &rtdev->rtvccs); + write_unlock_irq(&devs_lock); + rtvcc->rtdev = rtdev; + rtvcc->atmvcc = atmvcc; + atmvcc->user_back = rtvcc; + + rtvcc->xoff = 0; + //rtvcc->encap = 1; + rtvcc->encap = be.encaps; + rtvcc->last_use = jiffies; + //rtvcc->idle_timeout = timeout*HZ; + rtvcc->old_push = atmvcc->push; + rtvcc->old_pop = atmvcc->pop; + atmvcc->push = rt2684_push; + atmvcc->pop = rt2684_pop; + + skb_queue_head_init(©); + skb_migrate(&atmvcc->sk->sk_receive_queue,©); + /* re-process everything received between connection setup and MKIP */ + while ((skb = skb_dequeue(©))) { + unsigned int len = skb->len; + + rt2684_push(atmvcc,skb); + RTPRIV(skb->dev)->stats.rx_packets--; + RTPRIV(skb->dev)->stats.rx_bytes -= len; + } + return 0; + + error: + write_unlock_irq(&devs_lock); + return err; +} + + +/* Initialize net device atmxxx */ +static int rt2684_initdev(struct net_device *dev) +{ + DPRINTK("rt2684_initdev %s\n",dev->name); + dev->hard_start_xmit = rt2684_start_xmit; + /* sg_xmit ... */ + dev->hard_header = NULL; + dev->rebuild_header = NULL; + dev->set_mac_address = NULL; + dev->hard_header_parse = NULL; + dev->hard_header_cache = NULL; + dev->header_cache_update = NULL; + dev->change_mtu = NULL; + dev->do_ioctl = NULL; + dev->get_stats = rt2684_get_stats; + dev->type = ARPHRD_PPP; /* We are not using atmarp, so set to PPP */ + dev->hard_header_len = RFC1483LLC_LEN; + dev->mtu = RFC1626_MTU; + dev->addr_len = 0; + dev->tx_queue_len = 100; /* "normal" queue (packets) */ + /* When using a "real" qdisc, the qdisc determines the queue */ + /* length. tx_queue_len is only used for the default case, */ + /* without any more elaborate queuing. 100 is a reasonable */ + /* compromise between decent burst-tolerance and protection */ + /* against memory hogs. */ + /* Using the same set of flags as PPP */ + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + return 0; +} + +static int rt2684_create(unsigned long arg) +{ + int err; + struct rt2684_dev *rtdev; + struct atm_newif_rt2684 ni; + + DPRINTK("rt2684_create\n"); + /* + * We track module use by vcc's NOT the devices they're on. We're + * protected here against module death by the kernel_lock, but if + * we need to sleep we should make sure that the module doesn't + * disappear under us. + */ + if (copy_from_user(&ni, (void *) arg, sizeof ni)) { + return -EFAULT; + } + + /* Create atmxxx device */ + if ((rtdev = kmalloc(sizeof(struct rt2684_dev), GFP_KERNEL)) == NULL) { + return -ENOMEM; + } + memset(rtdev, 0, sizeof(struct rt2684_dev)); + INIT_LIST_HEAD(&rtdev->rtvccs); + + write_lock_irq(&devs_lock); + rtdev->number = list_empty(&rt2684_devs) ? 1 : + list_entry_rtdev(rt2684_devs.prev)->number + 1; + list_add_tail(&rtdev->rt2684_devs, &rt2684_devs); + write_unlock_irq(&devs_lock); + + if (ni.ifname[0] != '\0') { + memcpy(rtdev->net_dev.name, ni.ifname, + sizeof(rtdev->net_dev.name)); + rtdev->net_dev.name[sizeof(rtdev->net_dev.name) - 1] = '\0'; + } else + sprintf(rtdev->net_dev.name, "atm%d", rtdev->number); + + DPRINTK("registered netdev %s\n", rtdev->net_dev.name); + + rtdev->net_dev.init = rt2684_initdev; + spin_lock_init(&rtdev->xoff_lock); + + /* open, stop, do_ioctl ? */ + err = register_netdev(&rtdev->net_dev); + if (err < 0) { + printk(KERN_ERR "rt2684_create: register_netdev failed\n"); + write_lock_irq(&devs_lock); + list_del(&rtdev->rt2684_devs); + write_unlock_irq(&devs_lock); + kfree(rtdev); + return err; + } + return 0; +} + +/* + * This handles ioctls actually performed on our vcc - we must return + * -ENOIOCTLCMD for any unrecognized ioctl + * + * Called from common.c: atm_backend_t b is used to differentiate + * different ioctl hooks. + */ +static int rt2684_ioctl(struct socket *sock, unsigned int cmd, + unsigned long arg) +{ + int err; + struct atm_vcc *atmvcc = ATM_SD(sock); + + DPRINTK("rt2684_ioctl\n"); + switch(cmd) { + case ATM_SETBACKEND: + case ATM_NEWBACKENDIF: { + atm_backend_t b; + err = get_user(b, (atm_backend_t *) arg); + if (err) + return -EFAULT; + if (b != ATM_BACKEND_RT2684) + return -ENOIOCTLCMD; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (cmd == ATM_SETBACKEND) + return rt2684_regvcc(atmvcc, arg); + else + return rt2684_create(arg); + } +#ifdef CONFIG_ATM_rt2684_IPFILTER + case rt2684_SETFILT: + if (atmvcc->push != rt2684_push) + return -ENOIOCTLCMD; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + err = rt2684_setfilt(atmvcc, arg); + return err; +#endif /* CONFIG_ATM_rt2684_IPFILTER */ + } + return -ENOIOCTLCMD; +} + +static struct atm_ioctl rt2684_ioctl_ops = { + .owner = THIS_MODULE, + .ioctl = rt2684_ioctl, +}; + +/* Never put more than 256 bytes in at once */ +static int rt2684_proc_engine(loff_t pos, char *buf) +{ + struct list_head *lhd, *lhc; + struct rt2684_dev *rtdev; + struct rt2684_vcc *rtvcc; + list_for_each(lhd, &rt2684_devs) { + rtdev = list_entry_rtdev(lhd); + if (pos-- == 0) + return sprintf(buf, "dev %.16s: num=%d\n", + rtdev->net_dev.name, + rtdev->number); + list_for_each(lhc, &rtdev->rtvccs) { + rtvcc = list_entry_rtvcc(lhc); + if (pos-- == 0) + return sprintf(buf, " vcc %d.%d.%d: encaps=%s" +#ifndef FASTER_VERSION + ", failed copies %u/%u" +#endif /* FASTER_VERSION */ + "\n", rtvcc->atmvcc->dev->number, + rtvcc->atmvcc->vpi, rtvcc->atmvcc->vci, + (rtvcc->encap == 1) ? "LLC" : "NULL" +#ifndef FASTER_VERSION + , rtvcc->copies_failed + , rtvcc->copies_needed +#endif /* FASTER_VERSION */ + ); +#ifdef CONFIG_ATM_rt2684_IPFILTER +#define b1(var, byte) ((u8 *) &rtvcc->filter.var)[byte] +#define bs(var) b1(var, 0), b1(var, 1), b1(var, 2), b1(var, 3) + if (rtvcc->filter.netmask != 0 && pos-- == 0) + return sprintf(buf, " filter=%d.%d.%d.%d/" + "%d.%d.%d.%d\n", bs(prefix), bs(netmask)); +#undef bs +#undef b1 +#endif /* CONFIG_ATM_rt2684_IPFILTER */ + } + } + return 0; +} + +static ssize_t rt2684_proc_read(struct file *file, char *buf, size_t count, + loff_t *pos) +{ + unsigned long page; + int len = 0, x, left; + page = __get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + left = PAGE_SIZE - 256; + if (count < left) + left = count; + read_lock(&devs_lock); + for (;;) { + x = rt2684_proc_engine(*pos, &((char *) page)[len]); + if (x == 0) + break; + if (x > left) + /* + * This should only happen if the user passed in + * a "count" too small for even one line + */ + x = -EINVAL; + if (x < 0) { + len = x; + break; + } + len += x; + left -= x; + (*pos)++; + if (left < 256) + break; + } + read_unlock(&devs_lock); + if (len > 0 && copy_to_user(buf, (char *) page, len)) + len = -EFAULT; + free_page(page); + return len; +} + +static struct file_operations rt2684_proc_operations = { + .read = rt2684_proc_read, +}; + +extern struct proc_dir_entry *atm_proc_root; /* from proc.c */ + + +static int __init rt2684_init(void) +{ +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *p; + if ((p = create_proc_entry("rt2684", 0, atm_proc_root)) == NULL) + return -ENOMEM; + p->proc_fops = &rt2684_proc_operations; +#endif + register_atm_ioctl(&rt2684_ioctl_ops); + return 0; +} + +static void __exit rt2684_exit(void) +{ + struct rt2684_dev *rtdev; + + deregister_atm_ioctl(&rt2684_ioctl_ops); +#ifdef CONFIG_PROC_FS + remove_proc_entry("rt2684", atm_proc_root); +#endif + while (!list_empty(&rt2684_devs)) { + rtdev = list_entry_rtdev(rt2684_devs.next); + unregister_netdev(&rtdev->net_dev); + list_del(&rtdev->rt2684_devs); + kfree(rtdev); + } +} + +module_init(rt2684_init); +module_exit(rt2684_exit); + +MODULE_AUTHOR("Song Wang"); +MODULE_DESCRIPTION("RFC2684 routed protocols over ATM/AAL5 (for IPoA)"); +MODULE_LICENSE("GPL"); diff -Naur linux-mips-2.6.8.1-orig/net/bridge/br_device.c linux-mips-2.6.8.1-bcm/net/bridge/br_device.c --- linux-mips-2.6.8.1-orig/net/bridge/br_device.c 2004-08-06 02:33:32.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/bridge/br_device.c 2006-12-20 18:45:35.000000000 +0100 @@ -41,8 +41,12 @@ skb_pull(skb, ETH_HLEN); rcu_read_lock(); - if (dest[0] & 1) + if (dest[0] & 1) { +#if defined(CONFIG_MIPS_BRCM) + if (!mc_forward(br, skb, (unsigned char *) dest, 0, 0)) +#endif br_flood_deliver(br, skb, 0); + } else if ((dst = __br_fdb_get(br, dest)) != NULL) br_deliver(dst->dst, skb); else diff -Naur linux-mips-2.6.8.1-orig/net/bridge/br_fdb.c linux-mips-2.6.8.1-bcm/net/bridge/br_fdb.c --- linux-mips-2.6.8.1-orig/net/bridge/br_fdb.c 2004-08-06 02:33:32.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/bridge/br_fdb.c 2006-12-20 18:45:35.000000000 +0100 @@ -80,6 +80,150 @@ br_fdb_put(f); } + +#if defined(CONFIG_MIPS_BRCM) +void dolist(struct net_bridge *br) +{ + struct net_bridge_mc_fdb_entry *dst; + struct list_head *lh; + + + if (!br) + return; + + printk("bridge device group source timeout\n"); + list_for_each_rcu(lh, &br->mc_list) { + dst = (struct net_bridge_mc_fdb_entry *) list_entry(lh, struct net_bridge_mc_fdb_entry, list); + printk("%s %s ", br->dev->name, dst->dst->dev->name); + addr_debug((unsigned char *) &dst->addr); + printk(" "); + addr_debug((unsigned char *) &dst->host); + printk(" %d\n", (int) (dst->tstamp - jiffies)/HZ); + } +} + +int br_mc_fdb_update(struct net_bridge *br, struct net_bridge_port *prt, unsigned char *dest, unsigned char *host) +{ + struct net_bridge_mc_fdb_entry *dst; + struct list_head *lh; + int ret = 0; + + list_for_each_rcu(lh, &br->mc_list) { + dst = (struct net_bridge_mc_fdb_entry *) list_entry(lh, struct net_bridge_mc_fdb_entry, list); + if (!memcmp(&dst->addr, dest, ETH_ALEN)) { + dst->tstamp = jiffies + QUERY_TIMEOUT*HZ; + if (!memcmp(&dst->host, host, ETH_ALEN)) + ret = 1; + } + } + + return ret; +} + +struct net_bridge_mc_fdb_entry *br_mc_fdb_get(struct net_bridge *br, struct net_bridge_port *prt, unsigned char *dest, unsigned char *host) +{ + struct net_bridge_mc_fdb_entry *dst; + struct list_head *lh; + + list_for_each_rcu(lh, &br->mc_list) { + dst = (struct net_bridge_mc_fdb_entry *) list_entry(lh, struct net_bridge_mc_fdb_entry, list); + if ((!memcmp(&dst->addr, dest, ETH_ALEN)) && (!memcmp(&dst->host, host, ETH_ALEN))) { + if (dst->dst == prt) + return dst; + } + } + + return NULL; +} + +extern mac_addr upnp_addr; + +int br_mc_fdb_add(struct net_bridge *br, struct net_bridge_port *prt, unsigned char *dest, unsigned char *host) +{ + struct net_bridge_mc_fdb_entry *mc_fdb; + + //printk("--- add mc entry ---\n"); + + if (!memcmp(dest, &upnp_addr, ETH_ALEN)) + return 0; + + if (br_mc_fdb_update(br, prt, dest, host)) + return 0; + + mc_fdb = kmalloc(sizeof(struct net_bridge_mc_fdb_entry), GFP_KERNEL); + if (!mc_fdb) + return ENOMEM; + memcpy(mc_fdb->addr.addr, dest, ETH_ALEN); + memcpy(mc_fdb->host.addr, host, ETH_ALEN); + mc_fdb->dst = prt; + mc_fdb->tstamp = jiffies + QUERY_TIMEOUT*HZ;; + spin_lock_bh(&br->mcl_lock); + list_add_tail_rcu(&mc_fdb->list, &br->mc_list); + spin_unlock_bh(&br->mcl_lock); + + if (!br->start_timer) { + init_timer(&br->igmp_timer); + br->igmp_timer.expires = jiffies + TIMER_CHECK_TIMEOUT*HZ; + br->igmp_timer.function = query_timeout; + br->igmp_timer.data = (unsigned long) br; + add_timer(&br->igmp_timer); + br->start_timer = 1; + } + + return 1; +} + +void br_mc_fdb_cleanup(struct net_bridge *br) +{ + struct net_bridge_mc_fdb_entry *dst; + struct list_head *lh; + struct list_head *tmp; + + spin_lock_bh(&br->mcl_lock); + list_for_each_safe_rcu(lh, tmp, &br->mc_list) { + dst = (struct net_bridge_mc_fdb_entry *) list_entry(lh, struct net_bridge_mc_fdb_entry, list); + list_del_rcu(&dst->list); + kfree(dst); + } + spin_unlock_bh(&br->mcl_lock); +} + +void br_mc_fdb_remove_grp(struct net_bridge *br, struct net_bridge_port *prt, unsigned char *dest) +{ + struct net_bridge_mc_fdb_entry *dst; + struct list_head *lh; + struct list_head *tmp; + + spin_lock_bh(&br->mcl_lock); + list_for_each_safe_rcu(lh, tmp, &br->mc_list) { + dst = (struct net_bridge_mc_fdb_entry *) list_entry(lh, struct net_bridge_mc_fdb_entry, list); + if ((!memcmp(&dst->addr, dest, ETH_ALEN)) && (dst->dst == prt)) { + list_del_rcu(&dst->list); + kfree(dst); + } + } + spin_unlock_bh(&br->mcl_lock); +} + +int br_mc_fdb_remove(struct net_bridge *br, struct net_bridge_port *prt, unsigned char *dest, unsigned char *host) +{ + struct net_bridge_mc_fdb_entry *mc_fdb; + + //printk("--- remove mc entry ---\n"); + + if ((mc_fdb = br_mc_fdb_get(br, prt, dest, host))) { + spin_lock_bh(&br->mcl_lock); + list_del_rcu(&mc_fdb->list); + kfree(mc_fdb); + spin_unlock_bh(&br->mcl_lock); + + return 1; + } + + return 0; +} +#endif + void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) { struct net_bridge *br = p->br; @@ -297,11 +441,15 @@ */ if (is_local) return 0; - + +#if 0 /* Begin Broadcom commented out code */ + if (net_ratelimit()) printk(KERN_WARNING "%s: received packet with " " own address as source address\n", source->dev->name); + +#endif /* End Broadcom commented out code */ return -EEXIST; } diff -Naur linux-mips-2.6.8.1-orig/net/bridge/br_forward.c linux-mips-2.6.8.1-bcm/net/bridge/br_forward.c --- linux-mips-2.6.8.1-orig/net/bridge/br_forward.c 2004-08-14 18:16:44.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/bridge/br_forward.c 2006-12-20 18:45:35.000000000 +0100 @@ -26,11 +26,36 @@ p->state != BR_STATE_FORWARDING) return 0; +#if defined(CONFIG_MIPS_BRCM) + /* + * Do not forward any packets received from + * one WAN interface to other WAN interfaces in multiple PVC case + * In the following condition, if a new interface is added, please + * add the check to compare the first 3 chars from the name as + * shown below. Using strcmp will be expensive in this path. + */ + if ((skb->nfmark & FROM_WAN) && + ((*(p->dev->name) == 'n') && + (*(p->dev->name + 1) == 'a') && + (*(p->dev->name + 2) == 's'))) + return 0; +#endif + return 1; } int br_dev_queue_push_xmit(struct sk_buff *skb) { +#if defined(CONFIG_MIPS_BRCM) + // Just to make it consistent with 2.4 so it will not surprise the customers.(Should be more intelligent.) +#ifdef CONFIG_BRIDGE_NETFILTER + /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */ + nf_bridge_maybe_copy_header(skb); +#endif + skb_push(skb, ETH_HLEN); + + dev_queue_xmit(skb); +#else if (skb->len > skb->dev->mtu) kfree_skb(skb); else { @@ -42,6 +67,7 @@ dev_queue_xmit(skb); } +#endif return 0; } diff -Naur linux-mips-2.6.8.1-orig/net/bridge/br_if.c linux-mips-2.6.8.1-bcm/net/bridge/br_if.c --- linux-mips-2.6.8.1-orig/net/bridge/br_if.c 2004-08-06 02:33:32.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/bridge/br_if.c 2006-12-20 18:45:35.000000000 +0100 @@ -24,6 +24,10 @@ #include "br_private.h" +#if defined(CONFIG_MIPS_BRCM) +int snooping = 0; +#endif + /* * Determine initial path cost based on speed. * using recommendations from 802.1d standard @@ -127,6 +131,8 @@ del_nbp(p); } + br_mc_fdb_cleanup(br); + del_timer_sync(&br->gc_timer); br_sysfs_delbr(br->dev); @@ -155,6 +161,11 @@ br->bridge_id.prio[1] = 0x00; memset(br->bridge_id.addr, 0, ETH_ALEN); +#if defined(CONFIG_MIPS_BRCM) + br->lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&br->mc_list); + br->hash_lock = SPIN_LOCK_UNLOCKED; +#endif br->stp_enabled = 0; br->designated_root = br->bridge_id; br->root_path_cost = 0; diff -Naur linux-mips-2.6.8.1-orig/net/bridge/br_input.c linux-mips-2.6.8.1-bcm/net/bridge/br_input.c --- linux-mips-2.6.8.1-orig/net/bridge/br_input.c 2004-08-06 02:33:32.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/bridge/br_input.c 2006-12-20 18:45:35.000000000 +0100 @@ -17,8 +17,17 @@ #include #include #include +#if defined(CONFIG_MIPS_BRCM) +#include +#include +#include +#endif #include "br_private.h" +#if defined(CONFIG_MIPS_BRCM) +#define SNOOPING_BLOCKING_MODE 2 +#endif + const unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; static int br_pass_frame_up_finish(struct sk_buff *skb) @@ -26,6 +35,27 @@ #ifdef CONFIG_NETFILTER_DEBUG skb->nf_debug = 0; #endif +#if defined(CONFIG_MIPS_BRCM) + /* If pass up to IP, remove VLAN header */ + if (skb->protocol == __constant_htons(ETH_P_8021Q)) { + unsigned short proto; + struct vlan_hdr *vhdr = (struct vlan_hdr *)(skb->data); + + skb = skb_share_check(skb, GFP_ATOMIC); + if (skb) { + memmove(skb->data - ETH_HLEN + VLAN_HLEN, + skb->data - ETH_HLEN, 12); + skb_pull(skb, VLAN_HLEN); + skb->mac.raw += VLAN_HLEN; + skb->nh.raw += VLAN_HLEN; + skb->h.raw += VLAN_HLEN; + } + /* make sure protocol is correct before passing up */ + proto = vhdr->h_vlan_encapsulated_proto; + skb->protocol = proto; + /* TODO: do we need to assign skb->priority? */ + } +#endif netif_rx(skb); return 0; @@ -45,16 +75,160 @@ br_pass_frame_up_finish); } +void query_timeout(unsigned long ptr) +{ + struct net_bridge_mc_fdb_entry *dst; + struct list_head *tmp; + struct list_head *lh; + struct net_bridge *br; + + br = (struct net_bridge *) ptr; + + spin_lock_bh(&br->mcl_lock); + list_for_each_safe_rcu(lh, tmp, &br->mc_list) { + dst = (struct net_bridge_mc_fdb_entry *) list_entry(lh, struct net_bridge_mc_fdb_entry, list); + if (jiffies > dst->tstamp) { + list_del_rcu(&dst->list); + kfree(dst); + } + } + spin_unlock_bh(&br->mcl_lock); + + mod_timer(&br->igmp_timer, jiffies + TIMER_CHECK_TIMEOUT*HZ); +} + +void addr_debug(unsigned char *dest) +{ +#define NUM2PRINT 50 + char buf[NUM2PRINT * 3 + 1]; /* 3 chars per byte */ + int i = 0; + for (i = 0; i < 6 && i < NUM2PRINT; i++) { + sprintf(buf + i * 3, "%2.2x ", 0xff & dest[i]); + } + printk("%s ", buf); +} + + +#if defined(CONFIG_MIPS_BRCM) +void addr_conv(unsigned char *in, char * out) +{ + sprintf(out, "%02x%02x%02x%02x%02x%02x", in[0], in[1], in[2], in[3], in[4], in[5]); +} + +mac_addr upnp_addr = {{0x01, 0x00, 0x5e, 0x7f, 0xff, 0xfa}}; +mac_addr sys1_addr = {{0x01, 0x00, 0x5e, 0x00, 0x00, 0x01}}; +mac_addr sys2_addr = {{0x01, 0x00, 0x5e, 0x00, 0x00, 0x02}}; +mac_addr ospf1_addr = {{0x01, 0x00, 0x5e, 0x00, 0x00, 0x05}}; +mac_addr ospf2_addr = {{0x01, 0x00, 0x5e, 0x00, 0x00, 0x06}}; +mac_addr ripv2_addr = {{0x01, 0x00, 0x5e, 0x00, 0x00, 0x09}}; +mac_addr sys_addr = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; + +int control_filter(unsigned char *dest) +{ + if ((!memcmp(dest, &upnp_addr, ETH_ALEN)) || + (!memcmp(dest, &sys1_addr, ETH_ALEN)) || + (!memcmp(dest, &sys2_addr, ETH_ALEN)) || + (!memcmp(dest, &ospf1_addr, ETH_ALEN)) || + (!memcmp(dest, &ospf2_addr, ETH_ALEN)) || + (!memcmp(dest, &sys_addr, ETH_ALEN)) || + (!memcmp(dest, &ripv2_addr, ETH_ALEN))) + return 0; + else + return 1; +} + +int mc_forward(struct net_bridge *br, struct sk_buff *skb, unsigned char *dest,int forward, int clone) +{ + struct net_bridge_mc_fdb_entry *dst; + struct list_head *lh; + int status = 0; + struct sk_buff *skb2; + struct net_bridge_port *p; + unsigned char tmp[6]; + + if (!snooping) + return 0; + + if ((snooping == SNOOPING_BLOCKING_MODE) && control_filter(dest)) + status = 1; + + if (skb->data[9] == IPPROTO_IGMP) { + // For proxy; need to add some intelligence here + if (!br->proxy) { + if (skb->data[24] == IGMPV2_HOST_MEMBERSHIP_REPORT && + skb->protocol == __constant_htons(ETH_P_IP)) + br_mc_fdb_add(br, skb->dev->br_port, dest, skb->mac.ethernet->h_source); + else if (skb->data[24] == IGMP_HOST_LEAVE_MESSAGE) { + tmp[0] = 0x01; + tmp[1] = 0x00; + tmp[2] = 0x5e; + tmp[3] = 0x7F & skb->data[29]; + tmp[4] = skb->data[30]; + tmp[5] = skb->data[31]; + br_mc_fdb_remove(br, skb->dev->br_port, tmp, skb->mac.ethernet->h_source); + } + else + ; + } + return status; + } + + /* + if (clone) { + struct sk_buff *skb3; + + if ((skb3 = skb_clone(skb, GFP_ATOMIC)) == NULL) { + br->statistics.tx_dropped++; + return; + } + + skb = skb3; + } + */ + + list_for_each_rcu(lh, &br->mc_list) { + dst = (struct net_bridge_mc_fdb_entry *) list_entry(lh, struct net_bridge_mc_fdb_entry, list); + if (!memcmp(&dst->addr, dest, ETH_ALEN)) { + if (!dst->dst->dirty) { + skb2 = skb_clone(skb, GFP_ATOMIC); + if (forward) + br_forward(dst->dst, skb2); + else + br_deliver(dst->dst, skb2); + } + dst->dst->dirty = 1; + status = 1; + } + } + if (status) { + list_for_each_entry_rcu(p, &br->port_list, list) { + p->dirty = 0; + } + } + + if ((!forward) && (status)) + kfree_skb(skb); + + return status; +} +#endif + int br_handle_frame_finish(struct sk_buff *skb) { struct net_bridge *br; unsigned char *dest; +#if defined(CONFIG_MIPS_BRCM) + unsigned char *src; +#endif struct net_bridge_fdb_entry *dst; struct net_bridge_port *p; int passedup; dest = skb->mac.ethernet->h_dest; - +#if defined(CONFIG_MIPS_BRCM) + src = skb->mac.ethernet->h_source; +#endif + rcu_read_lock(); p = skb->dev->br_port; smp_read_barrier_depends(); @@ -77,6 +251,31 @@ } if (dest[0] & 1) { +#if defined(CONFIG_MIPS_BRCM) + if (snooping && br->proxy) { + if (skb->data[9] == IPPROTO_IGMP) { + char destS[16]; + char srcS[16]; + + if (skb->data[24] == IGMP_HOST_LEAVE_MESSAGE) { + unsigned char tmp[6]; + + tmp[0] = 0x01; + tmp[1] = 0x00; + tmp[2] = 0x5e; + tmp[3] = 0x7F & skb->data[29]; + tmp[4] = skb->data[30]; + tmp[5] = skb->data[31]; + addr_conv(tmp, destS); + } + else + addr_conv(dest, destS); + addr_conv(src, srcS); + sprintf(skb->extif, "%s %s %s/%s", br->dev->name, p->dev->name, destS, srcS); + } + } + if (!mc_forward(br, skb, dest, 1, !passedup)) +#endif br_flood_forward(br, skb, !passedup); if (!passedup) br_pass_frame_up(br, skb); diff -Naur linux-mips-2.6.8.1-orig/net/bridge/br_ioctl.c linux-mips-2.6.8.1-bcm/net/bridge/br_ioctl.c --- linux-mips-2.6.8.1-orig/net/bridge/br_ioctl.c 2004-06-26 17:15:27.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/bridge/br_ioctl.c 2006-12-20 18:45:35.000000000 +0100 @@ -20,6 +20,14 @@ #include #include "br_private.h" +#if defined(CONFIG_MIPS_BRCM) +#define BRCTL_SET_PORT_SNOOPING 21 +#define BRCTL_CLEAR_PORT_SNOOPING 22 +#define BRCTL_ENABLE_SNOOPING 23 +#define BRCTL_SHOW_SNOOPING 24 +#define SIOCBRSHOWSNOOPING 24 +#endif + /* called with RTNL */ static int get_bridge_ifindices(int *indices, int num) { @@ -45,6 +53,33 @@ } } +#if defined(CONFIG_MIPS_BRCM) +int br_set_port_snooping(struct net_bridge_port *p, void __user * userbuf) +{ + unsigned char tmp[26]; + + if (copy_from_user(tmp, userbuf, sizeof(tmp))) + return -EFAULT; + br_mc_fdb_add(p->br, p, tmp, tmp+6); + return 0; +} + +int br_clear_port_snooping(struct net_bridge_port *p, void __user * userbuf) +{ + unsigned char tmp[26]; + unsigned char all[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + if (copy_from_user(tmp, userbuf, sizeof(tmp))) + return -EFAULT; + p->br->proxy = 1; + if (!memcmp(tmp+6, all, 6)) + br_mc_fdb_remove_grp(p->br, p, tmp); + else + br_mc_fdb_remove(p->br, p, tmp, tmp+6); + return 1; +} +#endif + /* * Format up to a page worth of forwarding table entries * userbuf -- where to copy result @@ -283,6 +318,42 @@ return ret; } +#if defined(CONFIG_MIPS_BRCM) + case BRCTL_SET_PORT_SNOOPING: + { + struct net_bridge_port *p; + int ret = 0; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + spin_lock_bh(&br->lock); + if ((p = br_get_port(br, args[1])) == NULL) + ret = -EINVAL; + else + br_set_port_snooping(p, (void __user *) args[2]); + spin_unlock_bh(&br->lock); + return ret; + } + + case BRCTL_CLEAR_PORT_SNOOPING: + { + struct net_bridge_port *p; + int ret = 0; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + spin_lock_bh(&br->lock); + if ((p = br_get_port(br, args[1])) == NULL) + ret = -EINVAL; + else + br_clear_port_snooping(p, (void __user *) args[2]); + spin_unlock_bh(&br->lock); + return ret; + } +#endif + case BRCTL_SET_PATH_COST: { struct net_bridge_port *p; @@ -356,6 +427,38 @@ return br_del_bridge(buf); } + +#if defined(CONFIG_MIPS_BRCM) + case BRCTL_SHOW_SNOOPING: + { + char buf[IFNAMSIZ]; + struct net_device *dev; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (copy_from_user(buf, (void __user *)args[1], IFNAMSIZ)) + return -EFAULT; + + buf[IFNAMSIZ-1] = 0; + + dev = __dev_get_by_name(buf); + if (dev == NULL) + return -ENXIO; /* Could not find device */ + dolist(netdev_priv(dev)); + + return 0; + } + + case BRCTL_ENABLE_SNOOPING: + { + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + snooping = args[1]; + return 0; + } +#endif } return -EOPNOTSUPP; @@ -385,6 +488,28 @@ return br_del_bridge(buf); } +#if defined(CONFIG_MIPS_BRCM) + case SIOCBRSHOWSNOOPING: + { + char buf[IFNAMSIZ]; + struct net_device *dev; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (copy_from_user(buf, uarg, IFNAMSIZ)) + return -EFAULT; + + buf[IFNAMSIZ-1] = 0; + + dev = __dev_get_by_name(buf); + if (dev == NULL) + return -ENXIO; /* Could not find device */ + dolist(netdev_priv(dev)); + + return 0; + } +#endif } return -EOPNOTSUPP; } @@ -406,3 +531,4 @@ pr_debug("Bridge does not support ioctl 0x%x\n", cmd); return -EOPNOTSUPP; } + diff -Naur linux-mips-2.6.8.1-orig/net/bridge/br_private.h linux-mips-2.6.8.1-bcm/net/bridge/br_private.h --- linux-mips-2.6.8.1-orig/net/bridge/br_private.h 2004-08-06 02:33:32.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/bridge/br_private.h 2006-12-20 18:45:35.000000000 +0100 @@ -27,6 +27,12 @@ #define BR_PORT_BITS 10 #define BR_MAX_PORTS (1<hello_timer, jiffies + br->hello_time); br_config_bpdu_generation(br); + // brcm + br->dev->trans_start = jiffies * 100 / HZ; + list_for_each_entry(p, &br->port_list, list) { if ((p->dev->flags & IFF_UP) && netif_carrier_ok(p->dev)) br_stp_enable_port(p); @@ -75,6 +78,9 @@ br->topology_change_detected = 0; spin_unlock(&br->lock); + // brcm + br->dev->trans_start = jiffies * 100 / HZ; + del_timer_sync(&br->hello_timer); del_timer_sync(&br->topology_change_timer); del_timer_sync(&br->tcn_timer); diff -Naur linux-mips-2.6.8.1-orig/net/bridge/netfilter/ebt_ftos.c linux-mips-2.6.8.1-bcm/net/bridge/netfilter/ebt_ftos.c --- linux-mips-2.6.8.1-orig/net/bridge/netfilter/ebt_ftos.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/bridge/netfilter/ebt_ftos.c 2006-12-20 18:45:35.000000000 +0100 @@ -0,0 +1,101 @@ +/* + * ebt_ftos + * + * Authors: + * Song Wang + * + * Feb, 2004 + * + */ + +// The ftos target can be used in any chain +#include +#include +#include +#include +#include +#include +#include + + +static int ebt_target_ftos(struct sk_buff **pskb, unsigned int hooknr, + const struct net_device *in, const struct net_device *out, + const void *data, unsigned int datalen) +{ + struct ebt_ftos_t_info *ftosinfo = (struct ebt_ftos_t_info *)data; + struct iphdr *iph; + + /* if VLAN frame, we need to point to correct network header */ + if ((*pskb)->protocol == __constant_htons(ETH_P_8021Q)) + iph = (struct iphdr *)((*pskb)->nh.raw + VLAN_HLEN); + else + iph = (*pskb)->nh.iph; + + if (iph->tos != ftosinfo->ftos) { + /* Need to recalculate IP header checksum after altering TOS byte */ + u_int16_t diffs[2]; + + /* raw socket (tcpdump) may have clone of incoming + skb: don't disturb it --RR */ + if (skb_cloned(*pskb) && !(*pskb)->sk) { + struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC); + if (!nskb) + return NF_DROP; + kfree_skb(*pskb); + *pskb = nskb; + if ((*pskb)->protocol == __constant_htons(ETH_P_8021Q)) + iph = (struct iphdr *)((*pskb)->nh.raw + VLAN_HLEN); + else + iph = (*pskb)->nh.iph; + } + + + diffs[0] = htons(iph->tos) ^ 0xFFFF; + iph->tos = ftosinfo->ftos; + diffs[1] = htons(iph->tos); + iph->check = csum_fold(csum_partial((char *)diffs, + sizeof(diffs), + iph->check^0xFFFF)); + (*pskb)->nfcache |= NFC_ALTERED; + } + return ftosinfo->target; +} + +static int ebt_target_ftos_check(const char *tablename, unsigned int hookmask, + const struct ebt_entry *e, void *data, unsigned int datalen) +{ + struct ebt_ftos_t_info *info = (struct ebt_ftos_t_info *)data; + + if (datalen != sizeof(struct ebt_ftos_t_info)) + return -EINVAL; + if (BASE_CHAIN && info->target == EBT_RETURN) + return -EINVAL; + CLEAR_BASE_CHAIN_BIT; + if (INVALID_TARGET) + return -EINVAL; + return 0; +} + +static struct ebt_target ftos_target = +{ + .name = EBT_FTOS_TARGET, + .target = ebt_target_ftos, + .check = ebt_target_ftos_check, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + return ebt_register_target(&ftos_target); +} + +static void __exit fini(void) +{ + ebt_unregister_target(&ftos_target); +} + +module_init(init); +module_exit(fini); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Song Wang, songw@broadcom.com"); +MODULE_DESCRIPTION("Target to overwrite the full TOS byte in IP header"); diff -Naur linux-mips-2.6.8.1-orig/net/bridge/netfilter/ebt_time.c linux-mips-2.6.8.1-bcm/net/bridge/netfilter/ebt_time.c --- linux-mips-2.6.8.1-orig/net/bridge/netfilter/ebt_time.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/bridge/netfilter/ebt_time.c 2006-12-20 18:45:35.000000000 +0100 @@ -0,0 +1,199 @@ +/* + Description: EBTables time match extension kernelspace module. + Authors: Song Wang , ported from netfilter/iptables + The following is the original disclaimer. + + This is a module which is used for time matching + It is using some modified code from dietlibc (localtime() function) + that you can find at http://www.fefe.de/dietlibc/ + This file is distributed under the terms of the GNU General Public + License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL + 2001-05-04 Fabrice MARIE : initial development. + 2001-21-05 Fabrice MARIE : bug fix in the match code, + thanks to "Zeng Yu" for bug report. + 2001-26-09 Fabrice MARIE : force the match to be in LOCAL_IN or PRE_ROUTING only. + 2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack, + added Nguyen Dang Phuoc Dong patch to support timezones. +*/ + +#include +#include +#include +#include +#include + +static unsigned char debug; +MODULE_PARM(debug, "0-1b"); +MODULE_PARM_DESC(debug, "debug=1 is turn on debug messages"); +MODULE_AUTHOR("Song Wang "); +MODULE_DESCRIPTION("Match timestamp"); +MODULE_LICENSE("GPL"); + +#define DEBUG_MSG(...) if (debug) printk (KERN_DEBUG "ebt_time: " __VA_ARGS__) + +struct tm +{ + int tm_sec; /* Seconds. [0-60] (1 leap second) */ + int tm_min; /* Minutes. [0-59] */ + int tm_hour; /* Hours. [0-23] */ + int tm_mday; /* Day. [1-31] */ + int tm_mon; /* Month. [0-11] */ + int tm_year; /* Year - 1900. */ + int tm_wday; /* Day of week. [0-6] */ + int tm_yday; /* Days in year.[0-365] */ + int tm_isdst; /* DST. [-1/0/1]*/ + + long int tm_gmtoff; /* we don't care, we count from GMT */ + const char *tm_zone; /* we don't care, we count from GMT */ +}; + +void localtime(const time_t *timepr, struct tm *r); + +static int ebt_filter_time(const struct sk_buff *skb, + const struct net_device *in, const struct net_device *out, const void *data, + unsigned int datalen) + +{ + const struct ebt_time_info *info = (struct ebt_time_info *)data; /* match info for rule */ + struct tm currenttime; /* time human readable */ + u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1}; + u_int16_t packet_time; + struct timeval kerneltimeval; + time_t packet_local_time; + + /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */ + if (info->kerneltime) + { + do_gettimeofday(&kerneltimeval); + packet_local_time = kerneltimeval.tv_sec; + } + else + packet_local_time = skb->stamp.tv_sec; + + /* Transform the timestamp of the packet, in a human readable form */ + localtime(&packet_local_time, ¤ttime); + DEBUG_MSG("currenttime: Y-%d M-%d D-%d H-%d M-%d S-%d, Day: W-%d\n", + currenttime.tm_year, currenttime.tm_mon, currenttime.tm_mday, + currenttime.tm_hour, currenttime.tm_min, currenttime.tm_sec, + currenttime.tm_wday); + + /* check if we match this timestamp, we start by the days... */ + if (info->days_match != 0) { + if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday]) + return EBT_NOMATCH; /* the day doesn't match */ + } + + /* ... check the time now */ + packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min; + if ((packet_time < info->time_start) || (packet_time > info->time_stop)) + return EBT_NOMATCH; + + /* here we match ! */ + return EBT_MATCH; +} + +static int ebt_time_check(const char *tablename, unsigned int hookmask, + const struct ebt_entry *e, void *data, unsigned int datalen) + +{ + struct ebt_time_info *info = (struct ebt_time_info *)data; /* match info for rule */ + + /* First, check that we are in the correct hook */ + /* PRE_ROUTING, LOCAL_IN or FROWARD */ +#if 0 + if (hookmask + & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_IN) | (1 << NF_BR_FORWARD) | (1 << NF_BR_LOCAL_OUT))) + { + printk("ebt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n"); + return -EINVAL; + } +#endif + /* we use the kerneltime if we are in forward or output */ + info->kerneltime = 1; +#if 0 + if (hookmask & ~((1 << NF_BR_FORWARD) | (1 << NF_BR_LOCAL_OUT))) + /* if not, we use the skb time */ + info->kerneltime = 0; +#endif + + /* Check the size */ + if (datalen != sizeof(struct ebt_time_info)) + return -EINVAL; + /* Now check the coherence of the data ... */ + if ((info->time_start > 1439) || /* 23*60+59 = 1439*/ + (info->time_stop > 1439)) + { + printk(KERN_WARNING "ebt_time: invalid argument\n"); + return -EINVAL; + } + + return 0; +} + +static struct ebt_match time_match = +{ + .name = EBT_TIME_MATCH, + .match = ebt_filter_time, + .check = ebt_time_check, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + DEBUG_MSG("ebt_time loading\n"); + return ebt_register_match(&time_match); +} + +static void __exit fini(void) +{ + ebt_unregister_match(&time_match); + DEBUG_MSG("ebt_time unloaded\n"); +} + +module_init(init); +module_exit(fini); + + +/* The part below is borowed and modified from dietlibc */ + +/* seconds per day */ +#define SPD 24*60*60 + +void localtime(const time_t *timepr, struct tm *r) { + time_t i; + time_t timep; + extern struct timezone sys_tz; + const unsigned int __spm[12] = + { 0, + (31), + (31+28), + (31+28+31), + (31+28+31+30), + (31+28+31+30+31), + (31+28+31+30+31+30), + (31+28+31+30+31+30+31), + (31+28+31+30+31+30+31+31), + (31+28+31+30+31+30+31+31+30), + (31+28+31+30+31+30+31+31+30+31), + (31+28+31+30+31+30+31+31+30+31+30), + }; + register time_t work; + + timep = (*timepr) - (sys_tz.tz_minuteswest * 60); + work=timep%(SPD); + r->tm_sec=work%60; work/=60; + r->tm_min=work%60; r->tm_hour=work/60; + work=timep/(SPD); + r->tm_wday=(4+work)%7; + for (i=1970; ; ++i) { + register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365; + if (work>k) + work-=k; + else + break; + } + r->tm_year=i-1900; + for (i=11; i && __spm[i]>work; --i) ; + r->tm_mon=i; + r->tm_mday=work-__spm[i]+1; +} diff -Naur linux-mips-2.6.8.1-orig/net/bridge/netfilter/Kconfig linux-mips-2.6.8.1-bcm/net/bridge/netfilter/Kconfig --- linux-mips-2.6.8.1-orig/net/bridge/netfilter/Kconfig 2004-01-10 05:59:57.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/bridge/netfilter/Kconfig 2006-12-20 18:45:35.000000000 +0100 @@ -133,6 +133,16 @@ 802.1Q vlan fields. To compile it as a module, choose M here. If unsure, say N. +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +config BRIDGE_EBT_TIME + tristate "ebt: time filter support" + depends on BRIDGE_NF_EBTABLES + help + This option adds the system time match, which allows the filtering + of system time when a frame arrives. + + To compile it as a module, choose M here. If unsure, say N. +# CONFIG_MIPS_BRCM End Broadcom changed code. # # targets # @@ -182,6 +192,16 @@ source address of frames. To compile it as a module, choose M here. If unsure, say N. +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +config BRIDGE_EBT_FTOS_T + tristate "ebt: ftos target support" + depends on BRIDGE_NF_EBTABLES + help + This option adds the ftos target, which allows altering the full TOS byte + in IP frames. + + To compile it as a module, choose M here. If unsure, say N. +# CONFIG_MIPS_BRCM End Broadcom changed code. # # watchers # diff -Naur linux-mips-2.6.8.1-orig/net/bridge/netfilter/Makefile linux-mips-2.6.8.1-bcm/net/bridge/netfilter/Makefile --- linux-mips-2.6.8.1-orig/net/bridge/netfilter/Makefile 2003-10-19 02:50:12.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/bridge/netfilter/Makefile 2006-12-20 18:45:35.000000000 +0100 @@ -15,10 +15,13 @@ obj-$(CONFIG_BRIDGE_EBT_ARP) += ebt_arp.o obj-$(CONFIG_BRIDGE_EBT_IP) += ebt_ip.o obj-$(CONFIG_BRIDGE_EBT_LIMIT) += ebt_limit.o -obj-$(CONFIG_BRIDGE_EBT_MARK) += ebt_mark_m.o +obj-$(CONFIG_BRIDGE_EBT_MARK_T) += ebt_mark_m.o obj-$(CONFIG_BRIDGE_EBT_PKTTYPE) += ebt_pkttype.o obj-$(CONFIG_BRIDGE_EBT_STP) += ebt_stp.o obj-$(CONFIG_BRIDGE_EBT_VLAN) += ebt_vlan.o +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +obj-$(CONFIG_BRIDGE_EBT_TIME) += ebt_time.o +# CONFIG_MIPS_BRCM End Broadcom changed code. # targets obj-$(CONFIG_BRIDGE_EBT_ARPREPLY) += ebt_arpreply.o @@ -26,6 +29,9 @@ obj-$(CONFIG_BRIDGE_EBT_DNAT) += ebt_dnat.o obj-$(CONFIG_BRIDGE_EBT_REDIRECT) += ebt_redirect.o obj-$(CONFIG_BRIDGE_EBT_SNAT) += ebt_snat.o +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +obj-$(CONFIG_BRIDGE_EBT_FTOS_T) += ebt_ftos.o +# CONFIG_MIPS_BRCM End Broadcom changed code. # watchers obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o diff -Naur linux-mips-2.6.8.1-orig/net/core/dev.c linux-mips-2.6.8.1-bcm/net/core/dev.c --- linux-mips-2.6.8.1-orig/net/core/dev.c 2004-08-06 02:33:32.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/core/dev.c 2006-12-20 18:45:21.000000000 +0100 @@ -1249,6 +1249,12 @@ /* We are no longer a clone, even if we were. */ skb->cloned = 0; +#if defined(CONFIG_MIPS_BRCM) + /* The data buffer of this skb is not pre-allocated any more + * even the skb itself is pre-allocated. (songw) + */ + skb->retfreeq_data_prealloc = 0; +#endif skb->tail += skb->data_len; skb->data_len = 0; @@ -1703,6 +1709,21 @@ struct packet_type **pt_prev, int *ret) { #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) +#if defined(CONFIG_MIPS_BRCM) + if (skb->dev->br_port && skb->pkt_type != PACKET_LOOPBACK) { + if (skb->protocol == __constant_htons(ETH_P_PPP_SES)|| + skb->protocol == __constant_htons(ETH_P_PPP_DISC)) { + if (!memcmp(skb->mac.ethernet->h_dest,skb->dev->dev_addr,ETH_ALEN)) + goto skipbridge; + } + *ret = handle_bridge(skb, *pt_prev); + if (br_handle_frame_hook(skb) == 0) + return 1; + + *pt_prev = NULL; + } +skipbridge: +#else if (skb->dev->br_port && skb->pkt_type != PACKET_LOOPBACK) { *ret = handle_bridge(skb, *pt_prev); if (br_handle_frame_hook(skb) == 0) @@ -1711,6 +1732,7 @@ *pt_prev = NULL; } #endif +#endif return 0; } @@ -2477,10 +2499,25 @@ (currently unused) */ return -EOPNOTSUPP; +#if defined(CONFIG_MIPS_BRCM) + case SIOCGIFTRANSSTART: + ifr->ifr_ifru.ifru_ivalue = dev->trans_start; + return 0; +#endif + case SIOCGIFMTU: /* Get the MTU of a device */ ifr->ifr_mtu = dev->mtu; return 0; +#if defined(CONFIG_MIPS_BRCM) + case SIOCCIFSTATS: /* Clean up the Stats of a device */ + { + struct net_device_stats * pStats = dev->get_stats(dev); + memset(pStats, 0, sizeof(struct net_device_stats)); + } + return 0; +#endif + case SIOCSIFMTU: /* Set the MTU of a device */ return dev_set_mtu(dev, ifr->ifr_mtu); @@ -2663,6 +2700,9 @@ case SIOCGIFMAP: case SIOCGIFINDEX: case SIOCGIFTXQLEN: +#if defined(CONFIG_MIPS_BRCM) + case SIOCGIFTRANSSTART: +#endif dev_load(ifr.ifr_name); read_lock(&dev_base_lock); ret = dev_ifsioc(&ifr, cmd); @@ -2761,6 +2801,9 @@ */ default: if (cmd == SIOCWANDEV || +#if defined(CONFIG_MIPS_BRCM) + cmd == SIOCCIFSTATS || +#endif (cmd >= SIOCDEVPRIVATE && cmd <= SIOCDEVPRIVATE + 15)) { dev_load(ifr.ifr_name); @@ -2873,6 +2916,11 @@ dev->iflink = -1; +#if defined(CONFIG_MIPS_BRCM) + /* Init dev->last_stats in case CONFIG_SYSFS is disabled */ + dev->last_stats = dev->get_stats; +#endif + /* Init, if this function is available */ if (dev->init) { ret = dev->init(dev); @@ -2882,7 +2930,7 @@ goto out_err; } } - + if (!dev_valid_name(dev->name)) { ret = -EINVAL; goto out_err; @@ -3001,6 +3049,25 @@ "waiting for %s to become free. Usage " "count = %d\n", dev->name, atomic_read(&dev->refcnt)); +#if defined(SUPPORT_TC) + /* decrement on ppp net work device reference count (refcnt) + * in sch_generic.c could result -1 and it should be reset to 0 + */ + if (atomic_read(&dev->refcnt) == -1 && strstr(dev->name, "ppp_")) { + printk("dev->name = %s, dev->refcnt=%d\n", dev->name, atomic_read(&dev->refcnt)); + atomic_set(&dev->refcnt, 0); + printk("after reset to 0, dev->refcnt=%d\n", atomic_read(&dev->refcnt)); + } +#endif + +#if defined(CONFIG_MIPS_BRCM) + /* if eth? device reference counter goes to negative, reset to 0 and get out the while loop */ + if (atomic_read(&dev->refcnt) < 0 && strstr(dev->name, "eth")) { + atomic_set(&dev->refcnt, 0); + printk("Reset to 0, dev->refcnt=%d.\n", atomic_read(&dev->refcnt)); + } +#endif + warning_time = jiffies; } } diff -Naur linux-mips-2.6.8.1-orig/net/core/Makefile linux-mips-2.6.8.1-bcm/net/core/Makefile --- linux-mips-2.6.8.1-orig/net/core/Makefile 2004-06-26 17:15:27.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/core/Makefile 2006-12-20 18:45:21.000000000 +0100 @@ -2,6 +2,10 @@ # Makefile for the Linux networking core. # +ifneq ($(strip $(BRCM_KERNEL_NETQOS)),) +CFLAGS += -DSUPPORT_TC +endif + obj-y := sock.o skbuff.o iovec.o datagram.o stream.o scm.o obj-$(CONFIG_SYSCTL) += sysctl_net_core.o diff -Naur linux-mips-2.6.8.1-orig/net/core/skbuff.c linux-mips-2.6.8.1-bcm/net/core/skbuff.c --- linux-mips-2.6.8.1-orig/net/core/skbuff.c 2004-08-13 09:18:56.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/core/skbuff.c 2006-12-20 18:45:21.000000000 +0100 @@ -198,7 +198,18 @@ if (skb_shinfo(skb)->frag_list) skb_drop_fraglist(skb); - kfree(skb->head); +#if defined(CONFIG_MIPS_BRCM) + /* + * If skb->retfreeq_data_prealloc is 1, that means the data buffer was pre-allocated + * by our network driver. (songw) + */ + if (skb->retfreeq_cb && skb->retfreeq_data_prealloc == 1) { + (*skb->retfreeq_cb)(skb->retfreeq_context, skb->head, FREE_DATA); + skb->retfreeq_data_prealloc = 0; + } + else +#endif + kfree(skb->head); } } @@ -208,7 +219,17 @@ void kfree_skbmem(struct sk_buff *skb) { skb_release_data(skb); - kmem_cache_free(skbuff_head_cache, skb); + +#if defined(CONFIG_MIPS_BRCM) + /* + * If skb->retfreeq_skb_prealloc is 1, that means the skb was pre-allocated + * by our network driver. (songw) + */ + if (skb->retfreeq_cb && skb->retfreeq_skb_prealloc == 1) + (*skb->retfreeq_cb)(skb->retfreeq_context, skb, FREE_SKB); + else +#endif + kmem_cache_free(skbuff_head_cache, skb); } /** @@ -333,6 +354,14 @@ #endif #endif +#if defined(CONFIG_MIPS_BRCM) + n->retfreeq_skb_prealloc = 0; + C(retfreeq_data_prealloc); + C(retfreeq_cb); + C(retfreeq_context); + C(rcvfrom); + memcpy(n->extif, skb->extif, sizeof(skb->extif)); +#endif C(truesize); atomic_set(&n->users, 1); C(head); @@ -391,6 +420,13 @@ #endif new->tc_index = old->tc_index; #endif +#if defined(CONFIG_MIPS_BRCM) + new->rcvfrom = old->rcvfrom; + new->retfreeq_cb = NULL; + new->retfreeq_context = NULL; + new->retfreeq_skb_prealloc = 0; + new->retfreeq_data_prealloc = 0; +#endif atomic_set(&new->users, 1); } @@ -549,6 +585,13 @@ skb->h.raw += off; skb->nh.raw += off; skb->cloned = 0; +#if defined(CONFIG_MIPS_BRCM) + /* The data buffer of this skb is not pre-allocated any more + * even the skb itself is pre-allocated. (songw) + */ + skb->retfreeq_data_prealloc = 0; +#endif + atomic_set(&skb_shinfo(skb)->dataref, 1); return 0; diff -Naur linux-mips-2.6.8.1-orig/net/core/sock.c linux-mips-2.6.8.1-bcm/net/core/sock.c --- linux-mips-2.6.8.1-orig/net/core/sock.c 2004-08-13 09:18:56.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/core/sock.c 2006-12-20 18:45:21.000000000 +0100 @@ -1289,6 +1289,15 @@ EXPORT_SYMBOL(sock_common_recvmsg); +#if defined(CONFIG_MIPS_BRCM) +int sock_get_extif(struct sock *sk, char __user *extif) +{ + return copy_to_user(extif, sk->extdev, sizeof(sk->extdev)) ? -EFAULT: 0; +} + +EXPORT_SYMBOL(sock_get_extif); +#endif + /* * Set socket options on an inet socket. */ diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/af_inet.c linux-mips-2.6.8.1-bcm/net/ipv4/af_inet.c --- linux-mips-2.6.8.1-orig/net/ipv4/af_inet.c 2004-07-09 04:16:53.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/ipv4/af_inet.c 2006-12-20 18:45:32.000000000 +0100 @@ -743,6 +743,10 @@ return err; } +#if defined(CONFIG_MIPS_BRCM) +#define SIOCGEXTIF 0x8908 +#endif + /* * ioctl() calls you can issue on an INET socket. Most of these are * device configuration and stuff and very rarely used. Some ioctls @@ -772,6 +776,11 @@ case SIOCSARP: err = arp_ioctl(cmd, (void __user *)arg); break; +#if defined(CONFIG_MIPS_BRCM) + case SIOCGEXTIF: + err = sock_get_extif(sk, (char __user *)arg); + break; +#endif case SIOCGIFADDR: case SIOCSIFADDR: case SIOCGIFBRDADDR: diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/fib_hash.c linux-mips-2.6.8.1-bcm/net/ipv4/fib_hash.c --- linux-mips-2.6.8.1-orig/net/ipv4/fib_hash.c 2003-09-30 16:27:31.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/ipv4/fib_hash.c 2006-12-20 18:45:32.000000000 +0100 @@ -252,6 +252,7 @@ { int i; struct fn_zone *fz = kmalloc(sizeof(struct fn_zone), GFP_KERNEL); + if (!fz) return NULL; @@ -275,6 +276,7 @@ for (i=z+1; i<=32; i++) if (table->fn_zones[i]) break; + write_lock_bh(&fib_hash_lock); if (i>32) { /* No more specific masks, we are the first. */ @@ -473,6 +475,7 @@ FTprint("tb(%d)_insert: %d %08x/%d %d %08x\n", tb->tb_id, r->rtm_type, rta->rta_dst ? *(u32*)rta->rta_dst : 0, z, rta->rta_oif ? *rta->rta_oif : -1, rta->rta_prefsrc ? *(u32*)rta->rta_prefsrc : 0); + if (z > 32) return -EINVAL; fz = table->fn_zones[z]; @@ -648,6 +651,7 @@ FTprint("tb(%d)_delete: %d %08x/%d %d\n", tb->tb_id, r->rtm_type, rta->rta_dst ? *(u32*)rta->rta_dst : 0, z, rta->rta_oif ? *rta->rta_oif : -1); + if (z > 32) return -EINVAL; if ((fz = table->fn_zones[z]) == NULL) @@ -914,9 +918,10 @@ for (iter->zone = table->fn_zone_list; iter->zone; iter->zone = iter->zone->fz_next) { int maxslot; - +#if 0 //BRCM_BEGIN if (!iter->zone->fz_next) continue; +#endif //BRCM_END iter->hash = iter->zone->fz_hash; maxslot = iter->zone->fz_divisor; @@ -924,7 +929,6 @@ for (iter->bucket = 0; iter->bucket < maxslot; ++iter->bucket, ++iter->hash) { iter->node = *iter->hash; - if (iter->node) goto out; } diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/igmp.c linux-mips-2.6.8.1-bcm/net/ipv4/igmp.c --- linux-mips-2.6.8.1-orig/net/ipv4/igmp.c 2004-08-06 02:33:32.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/ipv4/igmp.c 2006-12-20 18:45:32.000000000 +0100 @@ -1050,6 +1050,10 @@ } #endif +#if defined(CONFIG_MIPS_BRCM) +#define IGMP_RIP_ROUTER htonl(0xE0000009L) +#endif + static void igmp_group_dropped(struct ip_mc_list *im) { struct in_device *in_dev = im->interface; @@ -1066,6 +1070,11 @@ if (im->multiaddr == IGMP_ALL_HOSTS) return; +#if defined(CONFIG_MIPS_BRCM) + if (im->multiaddr == IGMP_RIP_ROUTER) + return; +#endif + reporter = im->reporter; igmp_stop_timer(im); @@ -1100,6 +1109,11 @@ if (im->multiaddr == IGMP_ALL_HOSTS) return; +#if defined(CONFIG_MIPS_BRCM) + if (im->multiaddr == IGMP_RIP_ROUTER) + return; +#endif + if (in_dev->dead) return; if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev)) { diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/ipmr.c linux-mips-2.6.8.1-bcm/net/ipv4/ipmr.c --- linux-mips-2.6.8.1-orig/net/ipv4/ipmr.c 2004-08-06 02:33:32.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/ipv4/ipmr.c 2006-12-20 18:45:32.000000000 +0100 @@ -456,6 +456,19 @@ return 0; } +#if defined(CONFIG_MIPS_BRCM) +static struct mfc_cache *ipmr_cache_find(__u32 origin, __u32 mcastgrp,unsigned int ifindex) +{ + int line=MFC_HASH(mcastgrp,htonl(0x00000000),ifindex); + struct mfc_cache *c; + + for (c=mfc_cache_array[line]; c; c = c->next) { + if ( c->mfc_mcastgrp==mcastgrp) + break; + } + return c; +} +#else static struct mfc_cache *ipmr_cache_find(__u32 origin, __u32 mcastgrp) { int line=MFC_HASH(mcastgrp,origin); @@ -467,6 +480,7 @@ } return c; } +#endif /* * Allocate a multicast cache entry @@ -689,7 +703,11 @@ int line; struct mfc_cache *c, **cp; +#if defined(CONFIG_MIPS_BRCM) + line=MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr,mfc->mfcc_parent); +#else line=MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); +#endif for (cp=&mfc_cache_array[line]; (c=*cp) != NULL; cp = &c->next) { if (c->mfc_origin == mfc->mfcc_origin.s_addr && @@ -710,7 +728,11 @@ int line; struct mfc_cache *uc, *c, **cp; +#if defined(CONFIG_MIPS_BRCM) + line=MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr,mfc->mfcc_parent); +#else line=MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); +#endif for (cp=&mfc_cache_array[line]; (c=*cp) != NULL; cp = &c->next) { if (c->mfc_origin == mfc->mfcc_origin.s_addr && @@ -1015,7 +1037,11 @@ struct sioc_sg_req sr; struct sioc_vif_req vr; struct vif_device *vif; +#if defined(CONFIG_MIPS_BRCM) + struct mfc_cache *c=NULL; +#else struct mfc_cache *c; +#endif switch(cmd) { @@ -1044,7 +1070,11 @@ return -EFAULT; read_lock(&mrt_lock); +#if defined(CONFIG_MIPS_BRCM) + // c = ipmr_cache_find(sr.src.s_addr, sr.grp.s_addr); +#else c = ipmr_cache_find(sr.src.s_addr, sr.grp.s_addr); +#endif if (c) { sr.pktcnt = c->mfc_un.res.pkt; sr.bytecnt = c->mfc_un.res.bytes; @@ -1330,6 +1360,9 @@ { struct mfc_cache *cache; int local = ((struct rtable*)skb->dst)->rt_flags&RTCF_LOCAL; +#if defined(CONFIG_MIPS_BRCM) + struct net_device *dev=skb->dev; +#endif /* Packet is looped back after forward, it should not be forwarded second time, but still can be delivered locally. @@ -1359,7 +1392,12 @@ } read_lock(&mrt_lock); +#if defined(CONFIG_MIPS_BRCM) + cache = ipmr_cache_find(skb->nh.iph->saddr, skb->nh.iph->daddr,dev->ifindex); +#else cache = ipmr_cache_find(skb->nh.iph->saddr, skb->nh.iph->daddr); +#endif + /* * No usable cache entry @@ -1566,9 +1604,16 @@ int err; struct mfc_cache *cache; struct rtable *rt = (struct rtable*)skb->dst; +#if defined(CONFIG_MIPS_BRCM) + struct net_device *dev=skb->dev; +#endif read_lock(&mrt_lock); +#if defined(CONFIG_MIPS_BRCM) + cache = ipmr_cache_find(rt->rt_src, rt->rt_dst,dev->ifindex); +#else cache = ipmr_cache_find(rt->rt_src, rt->rt_dst); +#endif if (cache==NULL) { struct net_device *dev; diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/ip_output.c linux-mips-2.6.8.1-bcm/net/ipv4/ip_output.c --- linux-mips-2.6.8.1-orig/net/ipv4/ip_output.c 2004-08-06 02:33:32.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/ipv4/ip_output.c 2006-12-20 18:45:32.000000000 +0100 @@ -405,6 +405,11 @@ to->priority = from->priority; to->protocol = from->protocol; to->security = from->security; + + // OG 2006-11-08 + // fix leak cf : http://lists.linuxcoding.com/rhl/2005/msg21777.html + + dst_release(to->dst); to->dst = dst_clone(from->dst); to->dev = from->dev; diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_core.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_core.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_core.c 2004-06-26 17:15:27.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_core.c 2006-12-20 18:45:29.000000000 +0100 @@ -64,7 +64,11 @@ LIST_HEAD(protocol_list); static LIST_HEAD(helpers); unsigned int ip_conntrack_htable_size = 0; -int ip_conntrack_max; +#ifdef CONFIG_MIPS_BRCM +int ip_conntrack_max=0; +#else +static int ip_conntrack_max=0; +#endif static atomic_t ip_conntrack_count = ATOMIC_INIT(0); struct list_head *ip_conntrack_hash; static kmem_cache_t *ip_conntrack_cachep; @@ -143,6 +147,7 @@ tuple->src.ip = iph->saddr; tuple->dst.ip = iph->daddr; tuple->dst.protonum = iph->protocol; + tuple->src.u.all = tuple->dst.u.all = 0; return protocol->pkt_to_tuple(skb, dataoff, tuple); } @@ -156,6 +161,8 @@ inverse->dst.ip = orig->src.ip; inverse->dst.protonum = orig->dst.protonum; + inverse->src.u.all = inverse->dst.u.all = 0; + return protocol->invert_tuple(inverse, orig); } @@ -603,6 +610,36 @@ return dropped; } +#if defined(CONFIG_MIPS_BRCM) +static inline int regardless(const struct ip_conntrack_tuple_hash *i) +{ + return 1; +} + +static int regardless_drop(struct list_head *chain) +{ + /* Traverse backwards: gives us oldest, which is roughly LRU */ + struct ip_conntrack_tuple_hash *h; + int dropped = 0; + + READ_LOCK(&ip_conntrack_lock); + h = LIST_FIND_B(chain, regardless, struct ip_conntrack_tuple_hash *); + if (h) + atomic_inc(&h->ctrack->ct_general.use); + READ_UNLOCK(&ip_conntrack_lock); + + if (!h) + return dropped; + + if (del_timer(&h->ctrack->timeout)) { + death_by_timeout((unsigned long)h->ctrack); + dropped = 1; + } + ip_conntrack_put(h->ctrack); + return dropped; +} +#endif + static inline int helper_cmp(const struct ip_conntrack_helper *i, const struct ip_conntrack_tuple *rtuple) { @@ -643,14 +680,20 @@ chain about to put into (in case they're trying to bomb one hash chain). */ unsigned int next = (drop_next++)%ip_conntrack_htable_size; - + if (!early_drop(&ip_conntrack_hash[next]) && !early_drop(&ip_conntrack_hash[hash])) { +#if defined(CONFIG_MIPS_BRCM) + /* Sorry, we have to kick one out regardless. */ + while (!regardless_drop(&ip_conntrack_hash[next])) + next = (drop_next++)%ip_conntrack_htable_size; +#else if (net_ratelimit()) printk(KERN_WARNING "ip_conntrack: table full, dropping" " packet.\n"); return ERR_PTR(-ENOMEM); +#endif } } @@ -718,6 +761,9 @@ __set_bit(IPS_EXPECTED_BIT, &conntrack->status); conntrack->master = expected; expected->sibling = conntrack; +#if CONFIG_IP_NF_CONNTRACK_MARK + conntrack->mark = expected->expectant->mark; +#endif LIST_DELETE(&ip_conntrack_expect_list, expected); expected->expectant->expecting--; nf_conntrack_get(&master_ct(conntrack)->infos[0]); @@ -797,6 +843,7 @@ /* Never happen */ if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) { + return NF_ACCEPT; if (net_ratelimit()) { printk(KERN_ERR "ip_conntrack_in: Frag of proto %u (hook=%u)\n", (*pskb)->nh.iph->protocol, hooknum); @@ -974,8 +1021,8 @@ * so there is no need to use the tuple lock too */ DEBUGP("ip_conntrack_expect_related %p\n", related_to); - DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple); - DEBUGP("mask: "); DUMP_TUPLE(&expect->mask); + DEBUGP("tuple: "); DUMP_TUPLE_RAW(&expect->tuple); + DEBUGP("mask: "); DUMP_TUPLE_RAW(&expect->mask); old = LIST_FIND(&ip_conntrack_expect_list, resent_expect, struct ip_conntrack_expect *, &expect->tuple, @@ -1070,13 +1117,13 @@ WRITE_LOCK(&ip_conntrack_expect_tuple_lock); DEBUGP("change_expect:\n"); - DEBUGP("exp tuple: "); DUMP_TUPLE(&expect->tuple); - DEBUGP("exp mask: "); DUMP_TUPLE(&expect->mask); - DEBUGP("newtuple: "); DUMP_TUPLE(newtuple); + DEBUGP("exp tuple: "); DUMP_TUPLE_RAW(&expect->tuple); + DEBUGP("exp mask: "); DUMP_TUPLE_RAW(&expect->mask); + DEBUGP("newtuple: "); DUMP_TUPLE_RAW(newtuple); if (expect->ct_tuple.dst.protonum == 0) { /* Never seen before */ DEBUGP("change expect: never seen before\n"); - if (!ip_ct_tuple_equal(&expect->tuple, newtuple) + if (!ip_ct_tuple_mask_cmp(&expect->tuple, newtuple, &expect->mask) && LIST_FIND(&ip_conntrack_expect_list, expect_clash, struct ip_conntrack_expect *, newtuple, &expect->mask)) { /* Force NAT to find an unused tuple */ @@ -1395,6 +1442,9 @@ } ip_conntrack_max = 8 * ip_conntrack_htable_size; +#ifdef CONFIG_MIPS_BRCM + ip_conntrack_max=0; +#endif printk("ip_conntrack version %s (%u buckets, %d max)" " - %Zd bytes per conntrack\n", IP_CONNTRACK_VERSION, ip_conntrack_htable_size, ip_conntrack_max, @@ -1426,6 +1476,7 @@ list_append(&protocol_list, &ip_conntrack_protocol_tcp); list_append(&protocol_list, &ip_conntrack_protocol_udp); list_append(&protocol_list, &ip_conntrack_protocol_icmp); + list_append(&protocol_list, &ip_conntrack_protocol_esp); WRITE_UNLOCK(&ip_conntrack_lock); for (i = 0; i < ip_conntrack_htable_size; i++) diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_ftp.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_ftp.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_ftp.c 2004-07-20 22:21:27.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_ftp.c 2006-12-20 18:45:29.000000000 +0100 @@ -25,7 +25,11 @@ MODULE_DESCRIPTION("ftp connection tracking helper"); /* This is slow, but it's simple. --RR */ +#if defined(CONFIG_MIPS_BRCM) +static char ftp_buffer[16384]; +#else static char ftp_buffer[65536]; +#endif DECLARE_LOCK(ip_ftp_lock); struct module *ip_conntrack_ftp = THIS_MODULE; diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_gre.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_gre.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_gre.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_gre.c 2006-12-20 18:45:29.000000000 +0100 @@ -0,0 +1,350 @@ +/* + * ip_conntrack_proto_gre.c - Version 2.0 + * + * Connection tracking protocol helper module for GRE. + * + * GRE is a generic encapsulation protocol, which is generally not very + * suited for NAT, as it has no protocol-specific part as port numbers. + * + * It has an optional key field, which may help us distinguishing two + * connections between the same two hosts. + * + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 + * + * PPTP is built on top of a modified version of GRE, and has a mandatory + * field called "CallID", which serves us for the same purpose as the key + * field in plain GRE. + * + * Documentation about PPTP can be found in RFC 2637 + * + * (C) 2000-2004 by Harald Welte + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +DECLARE_RWLOCK(ip_ct_gre_lock); +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_ct_gre_lock) +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_ct_gre_lock) + +#include +#include +#include +#include + +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE"); + +/* shamelessly stolen from ip_conntrack_proto_udp.c */ +#define GRE_TIMEOUT (30*HZ) +#define GRE_STREAM_TIMEOUT (180*HZ) + +#if 0 +#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args) +#define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x\n", \ + NIPQUAD((x)->src.ip), ntohl((x)->src.u.gre.key), \ + NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.gre.key)) +#else +#define DEBUGP(x, args...) +#define DUMP_TUPLE_GRE(x) +#endif + +/* GRE KEYMAP HANDLING FUNCTIONS */ +static LIST_HEAD(gre_keymap_list); + +static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km, + const struct ip_conntrack_tuple *t) +{ + return ((km->tuple.src.ip == t->src.ip) && + (km->tuple.dst.ip == t->dst.ip) && + (km->tuple.dst.protonum == t->dst.protonum) && + (km->tuple.dst.u.all == t->dst.u.all)); +} + +/* look up the source key for a given tuple */ +static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t) +{ + struct ip_ct_gre_keymap *km; + u_int32_t key; + + READ_LOCK(&ip_ct_gre_lock); + km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn, + struct ip_ct_gre_keymap *, t); + if (!km) { + READ_UNLOCK(&ip_ct_gre_lock); + return 0; + } + + key = km->tuple.src.u.gre.key; + READ_UNLOCK(&ip_ct_gre_lock); + + return key; +} + +/* add a single keymap entry, associate with specified expect */ +int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp, + struct ip_conntrack_tuple *t, int reply) +{ + struct ip_ct_gre_keymap *km; + + km = kmalloc(sizeof(*km), GFP_ATOMIC); + if (!km) + return -1; + + /* initializing list head should be sufficient */ + memset(km, 0, sizeof(*km)); + + memcpy(&km->tuple, t, sizeof(*t)); + + if (!reply) + exp->proto.gre.keymap_orig = km; + else + exp->proto.gre.keymap_reply = km; + + DEBUGP("adding new entry %p: ", km); + DUMP_TUPLE_GRE(&km->tuple); + + WRITE_LOCK(&ip_ct_gre_lock); + list_append(&gre_keymap_list, km); + WRITE_UNLOCK(&ip_ct_gre_lock); + + return 0; +} + +/* change the tuple of a keymap entry (used by nat helper) */ +void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km, + struct ip_conntrack_tuple *t) +{ + DEBUGP("changing entry %p to: ", km); + DUMP_TUPLE_GRE(t); + + WRITE_LOCK(&ip_ct_gre_lock); + memcpy(&km->tuple, t, sizeof(km->tuple)); + WRITE_UNLOCK(&ip_ct_gre_lock); +} + +/* destroy the keymap entries associated with specified expect */ +void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp) +{ + DEBUGP("entering for exp %p\n", exp); + WRITE_LOCK(&ip_ct_gre_lock); + if (exp->proto.gre.keymap_orig) { + DEBUGP("removing %p from list\n", exp->proto.gre.keymap_orig); + list_del(&exp->proto.gre.keymap_orig->list); + kfree(exp->proto.gre.keymap_orig); + exp->proto.gre.keymap_orig = NULL; + } + if (exp->proto.gre.keymap_reply) { + DEBUGP("removing %p from list\n", exp->proto.gre.keymap_reply); + list_del(&exp->proto.gre.keymap_reply->list); + kfree(exp->proto.gre.keymap_reply); + exp->proto.gre.keymap_reply = NULL; + } + WRITE_UNLOCK(&ip_ct_gre_lock); +} + + +/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */ + +/* invert gre part of tuple */ +static int gre_invert_tuple(struct ip_conntrack_tuple *tuple, + const struct ip_conntrack_tuple *orig) +{ + tuple->dst.u.gre.key = orig->src.u.gre.key; + tuple->src.u.gre.key = orig->dst.u.gre.key; + + return 1; +} + +/* gre hdr info to tuple */ +static int gre_pkt_to_tuple(const struct sk_buff *skb, + unsigned int dataoff, + struct ip_conntrack_tuple *tuple) +{ + struct gre_hdr _grehdr, *grehdr; + struct gre_hdr_pptp _pgrehdr, *pgrehdr; + u_int32_t srckey; + + grehdr = skb_header_pointer(skb, dataoff, sizeof(_grehdr), &_grehdr); + /* PPTP header is variable length, only need up to the call_id field */ + pgrehdr = skb_header_pointer(skb, dataoff, 8, &_pgrehdr); + + if (!grehdr || !pgrehdr) + return 0; + + switch (grehdr->version) { + case GRE_VERSION_1701: + if (!grehdr->key) { + DEBUGP("Can't track GRE without key\n"); + return 0; + } + tuple->dst.u.gre.key = *(gre_key(grehdr)); + break; + + case GRE_VERSION_PPTP: + if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) { + DEBUGP("GRE_VERSION_PPTP but unknown proto\n"); + return 0; + } + tuple->dst.u.gre.key = htonl(ntohs(pgrehdr->call_id)); + break; + + default: + printk(KERN_WARNING "unknown GRE version %hu\n", + grehdr->version); + return 0; + } + + srckey = gre_keymap_lookup(tuple); + + tuple->src.u.gre.key = srckey; +#if 0 + DEBUGP("found src key %x for tuple ", ntohl(srckey)); + DUMP_TUPLE_GRE(tuple); +#endif + + return 1; +} + +/* print gre part of tuple */ +static int gre_print_tuple(struct seq_file *s, + const struct ip_conntrack_tuple *tuple) +{ + return 0; +/* + return seq_printf(s, "srckey=0x%x dstkey=0x%x ", + ntohl(tuple->src.u.gre.key), + ntohl(tuple->dst.u.gre.key)); +*/ +} + +/* print private data for conntrack */ +static int gre_print_conntrack(struct seq_file *s, + const struct ip_conntrack *ct) +{ + return 0; +/* + return seq_printf(s, "timeout=%u, stream_timeout=%u ", + (ct->proto.gre.timeout / HZ), + (ct->proto.gre.stream_timeout / HZ)); +*/ +} + +/* Returns verdict for packet, and may modify conntrack */ +static int gre_packet(struct ip_conntrack *ct, + struct sk_buff *skb, + enum ip_conntrack_info conntrackinfo) +{ + /* If we've seen traffic both ways, this is a GRE connection. + * Extend timeout. */ + if (ct->status & IPS_SEEN_REPLY) { + //ip_ct_refresh_acct(ct, conntrackinfo, skb, + // ct->proto.gre.stream_timeout); + ip_ct_refresh(ct,ct->proto.gre.stream_timeout); + /* Also, more likely to be important, and not a probe. */ + set_bit(IPS_ASSURED_BIT, &ct->status); + } else + // ip_ct_refresh_acct(ct, conntrackinfo, skb, + // ct->proto.gre.timeout); + + ip_ct_refresh(ct,ct->proto.gre.timeout); + return NF_ACCEPT; +} + +/* Called when a new connection for this protocol found. */ +static int gre_new(struct ip_conntrack *ct, + const struct sk_buff *skb) +{ + DEBUGP(": "); + DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + + /* initialize to sane value. Ideally a conntrack helper + * (e.g. in case of pptp) is increasing them */ + ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT; + ct->proto.gre.timeout = GRE_TIMEOUT; + + return 1; +} + +/* Called when a conntrack entry has already been removed from the hashes + * and is about to be deleted from memory */ +static void gre_destroy(struct ip_conntrack *ct) +{ + struct ip_conntrack_expect *master = ct->master; + + DEBUGP(" entering\n"); + + if (!master) { + DEBUGP("no master exp for ct %p\n", ct); + return; + } + + ip_ct_gre_keymap_destroy(master); +} + +/* protocol helper struct */ +static struct ip_conntrack_protocol gre = { + .proto = IPPROTO_GRE, + .name = "gre", + .pkt_to_tuple = gre_pkt_to_tuple, + .invert_tuple = gre_invert_tuple, + .print_tuple = gre_print_tuple, + .print_conntrack = gre_print_conntrack, + .packet = gre_packet, + .new = gre_new, + .destroy = gre_destroy, + .exp_matches_pkt = NULL, + .me = THIS_MODULE +}; + +/* ip_conntrack_proto_gre initialization */ +static int __init init(void) +{ + int retcode; + + if ((retcode = ip_conntrack_protocol_register(&gre))) { + printk(KERN_ERR "Unable to register conntrack protocol " + "helper for gre: %d\n", retcode); + return -EIO; + } + + return 0; +} + +static void __exit fini(void) +{ + struct list_head *pos, *n; + + /* delete all keymap entries */ + WRITE_LOCK(&ip_ct_gre_lock); + list_for_each_safe(pos, n, &gre_keymap_list) { + DEBUGP("deleting keymap %p at module unload time\n", pos); + list_del(pos); + kfree(pos); + } + WRITE_UNLOCK(&ip_ct_gre_lock); + + ip_conntrack_protocol_unregister(&gre); +} + +EXPORT_SYMBOL(ip_ct_gre_keymap_add); +EXPORT_SYMBOL(ip_ct_gre_keymap_change); +EXPORT_SYMBOL(ip_ct_gre_keymap_destroy); + +module_init(init); +module_exit(fini); diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_h323.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_h323.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_h323.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_h323.c 2006-12-20 18:45:29.000000000 +0100 @@ -0,0 +1,342 @@ +/* + * H.323 'brute force' extension for H.323 connection tracking. + * Jozsef Kadlecsik + * (c) 2005 Max Kellermann + * + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project. + * (http://www.coritel.it/projects/sofia/nat/) + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind' + * the unregistered helpers to the conntrack entries. + */ + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Jozsef Kadlecsik "); +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module"); +MODULE_LICENSE("GPL"); + +/* This is slow, but it's simple. --RR */ +static char h323_buffer[65536]; +static DECLARE_LOCK(h323_buffer_lock); + +DECLARE_LOCK(ip_h323_lock); +struct module *ip_conntrack_h323 = THIS_MODULE; + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +/* FIXME: This should be in userspace. Later. */ +static int h245_help(struct sk_buff *skb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo) +{ + struct iphdr *iph = skb->nh.iph; + struct tcphdr _tcph, *tcph; + unsigned char *data; + unsigned char *data_limit; + unsigned dataoff, datalen; + int dir = CTINFO2DIR(ctinfo); + struct ip_ct_h225_master *info = &ct->help.ct_h225_info; + struct ip_conntrack_expect *exp; + struct ip_ct_h225_expect *exp_info; + u_int16_t data_port; + u_int32_t data_ip; + unsigned int i; + int ret; + + /* Until there's been traffic both ways, don't look in packets. */ + if (ctinfo != IP_CT_ESTABLISHED + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { + DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo); + return NF_ACCEPT; + } + + tcph = skb_header_pointer(skb, skb->nh.iph->ihl*4, + sizeof(_tcph), &_tcph); + if (tcph == NULL) + return NF_ACCEPT; + + DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n", + NIPQUAD(iph->saddr), ntohs(tcph->source), + NIPQUAD(iph->daddr), ntohs(tcph->dest)); + + dataoff = skb->nh.iph->ihl*4 + tcph->doff*4; + /* No data? */ + if (dataoff >= skb->len) { + DEBUGP("ct_h245_help: skblen = %u\n", skb->len); + return NF_ACCEPT; + } + datalen = skb->len - dataoff; + + LOCK_BH(&h323_buffer_lock); + data = skb_header_pointer(skb, dataoff, + datalen, h323_buffer); + BUG_ON(data == NULL); + + data_limit = data + datalen - 6; + /* bytes: 0123 45 + ipadrr port */ + for (i = 0; data <= data_limit; data++, i++) { + data_ip = *((u_int32_t *)data); + if (data_ip == iph->saddr) { + data_port = *((u_int16_t *)(data + 4)); + + /* update the H.225 info */ + DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n", + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip), + NIPQUAD(iph->saddr), ntohs(data_port)); + + exp = ip_conntrack_expect_alloc(); + if (exp == NULL) { + ret = NF_ACCEPT; + goto out; + } + + exp_info = &exp->help.exp_h225_info; + + LOCK_BH(&ip_h323_lock); + info->is_h225 = H225_PORT + 1; + exp_info->port = data_port; + exp_info->dir = dir; + exp_info->offset = i; + + exp->seq = ntohl(tcph->seq) + i; + + exp->tuple = ((struct ip_conntrack_tuple) + { { ct->tuplehash[!dir].tuple.src.ip, + { 0 } }, + { data_ip, + { .tcp = { data_port } }, + IPPROTO_UDP }}); + exp->mask = ((struct ip_conntrack_tuple) + { { 0xFFFFFFFF, { 0 } }, + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }}); + + exp->expectfn = NULL; + + /* Ignore failure; should only happen with NAT */ + ip_conntrack_expect_related(exp, ct); + + UNLOCK_BH(&ip_h323_lock); + } + } + + ret = NF_ACCEPT; + out: + UNLOCK_BH(&h323_buffer_lock); + return ret; +} + +/* H.245 helper is not registered! */ +static struct ip_conntrack_helper h245 = { + .name = "H.245", + .flags = IP_CT_HELPER_F_REUSE_EXPECT, + .max_expected = 8, + .timeout = 1, + .tuple = { .dst = { .protonum = IPPROTO_TCP } }, + .mask = { .src = { .u = { 0xFFFF } }, + .dst = { .protonum = 0xFFFF } }, + .help = h245_help +}; + +static int h225_expect(struct ip_conntrack *ct) +{ + WRITE_LOCK(&ip_conntrack_lock); + ct->helper = &h245; + DEBUGP("h225_expect: helper for %p added\n", ct); + WRITE_UNLOCK(&ip_conntrack_lock); + + return NF_ACCEPT; /* unused */ +} + +/* FIXME: This should be in userspace. Later. */ +static int h225_help(struct sk_buff *skb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo) +{ + struct iphdr *iph = skb->nh.iph; + struct tcphdr _tcph, *tcph; + unsigned char *data; + unsigned char *data_limit; + unsigned dataoff, datalen; + int dir = CTINFO2DIR(ctinfo); + struct ip_ct_h225_master *info = &ct->help.ct_h225_info; + struct ip_conntrack_expect *exp; + struct ip_ct_h225_expect *exp_info; + u_int16_t data_port; + u_int32_t data_ip; + unsigned int i; + int ret; + + /* Until there's been traffic both ways, don't look in packets. */ + if (ctinfo != IP_CT_ESTABLISHED + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { + DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo); + return NF_ACCEPT; + } + + tcph = skb_header_pointer(skb, skb->nh.iph->ihl*4, + sizeof(_tcph), &_tcph); + if (tcph == NULL) + return NF_ACCEPT; + + DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n", + NIPQUAD(iph->saddr), ntohs(tcph->source), + NIPQUAD(iph->daddr), ntohs(tcph->dest)); + + dataoff = skb->nh.iph->ihl*4 + tcph->doff*4; + /* No data? */ + if (dataoff >= skb->len) { + DEBUGP("ct_h225_help: skblen = %u\n", skb->len); + return NF_ACCEPT; + } + datalen = skb->len - dataoff; + + LOCK_BH(&h323_buffer_lock); + data = skb_header_pointer(skb, dataoff, + datalen, h323_buffer); + BUG_ON(data == NULL); + + data_limit = data + datalen - 6; + /* bytes: 0123 45 + ipadrr port */ + for (i = 0; data <= data_limit; data++, i++) { + data_ip = *((u_int32_t *)data); + if (data_ip == iph->saddr) { + data_port = *((u_int16_t *)(data + 4)); + if (data_port == tcph->source) { + /* Signal address */ + DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n", + NIPQUAD(iph->saddr)); + /* Update the H.225 info so that NAT can mangle the address/port + even when we have no expected connection! */ +#ifdef CONFIG_IP_NF_NAT_NEEDED + LOCK_BH(&ip_h323_lock); + info->dir = dir; + info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i; + info->offset[IP_CT_DIR_ORIGINAL] = i; + UNLOCK_BH(&ip_h323_lock); +#endif + } else { + /* update the H.225 info */ + exp = ip_conntrack_expect_alloc(); + if (exp == NULL) { + ret = NF_ACCEPT; + goto out; + } + + exp_info = &exp->help.exp_h225_info; + + LOCK_BH(&ip_h323_lock); + info->is_h225 = H225_PORT; + exp_info->port = data_port; + exp_info->dir = dir; + exp_info->offset = i; + + exp->seq = ntohl(tcph->seq) + i; + + exp->tuple = ((struct ip_conntrack_tuple) + { { ct->tuplehash[!dir].tuple.src.ip, + { 0 } }, + { data_ip, + { .tcp = { data_port } }, + IPPROTO_TCP }}); + exp->mask = ((struct ip_conntrack_tuple) + { { 0xFFFFFFFF, { 0 } }, + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }}); + + exp->expectfn = h225_expect; + + /* Ignore failure */ + ip_conntrack_expect_related(exp, ct); + + DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n", + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip), + NIPQUAD(iph->saddr), ntohs(data_port)); + + UNLOCK_BH(&ip_h323_lock); + } +#ifdef CONFIG_IP_NF_NAT_NEEDED + } else if (data_ip == iph->daddr) { + data_port = *((u_int16_t *)(data + 4)); + if (data_port == tcph->dest) { + /* Signal address */ + DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n", + NIPQUAD(iph->daddr)); + /* Update the H.225 info so that NAT can mangle the address/port + even when we have no expected connection! */ + LOCK_BH(&ip_h323_lock); + info->dir = dir; + info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i; + info->offset[IP_CT_DIR_REPLY] = i; + UNLOCK_BH(&ip_h323_lock); + } +#endif + } + } + + ret = NF_ACCEPT; + out: + UNLOCK_BH(&h323_buffer_lock); + return ret; +} + +static struct ip_conntrack_helper h225 = { + .name = "H.225", + .flags = IP_CT_HELPER_F_REUSE_EXPECT, + .me = THIS_MODULE, + .max_expected = 2, + .timeout = 240, + .tuple = { .src = { .ip = 0, + .u = { .tcp = { .port = + __constant_htons(H225_PORT) } } + }, + .dst = { .ip = 0, + .u = { .all = 0 }, + .protonum = IPPROTO_TCP + } + }, + .mask = { .src = { .ip = 0, + .u = { .tcp = { .port = 0xffff } } + }, + .dst = { .ip = 0, + .u = { .all = 0 }, + .protonum = 0xffff + } + }, + .help = h225_help +}; + +static int __init init(void) +{ + printk("ip_conntrack_h323: init \n"); + return ip_conntrack_helper_register(&h225); +} + +static void __exit fini(void) +{ + /* Unregister H.225 helper */ + ip_conntrack_helper_unregister(&h225); +} + +EXPORT_SYMBOL(ip_h323_lock); + +PROVIDES_CONNTRACK(h225); +PROVIDES_CONNTRACK(h245); +module_init(init); +module_exit(fini); diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_pptp.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_pptp.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_pptp.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_pptp.c 2006-12-20 18:45:29.000000000 +0100 @@ -0,0 +1,719 @@ +/* + * ip_conntrack_pptp.c - Version 2.0 + * + * Connection tracking support for PPTP (Point to Point Tunneling Protocol). + * PPTP is a a protocol for creating virtual private networks. + * It is a specification defined by Microsoft and some vendors + * working with Microsoft. PPTP is built on top of a modified + * version of the Internet Generic Routing Encapsulation Protocol. + * GRE is defined in RFC 1701 and RFC 1702. Documentation of + * PPTP can be found in RFC 2637 + * + * (C) 2000-2005 by Harald Welte + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + * + * Limitations: + * - We blindly assume that control connections are always + * established in PNS->PAC direction. This is a violation + * of RFFC2673 + * + * TODO: - finish support for multiple calls within one session + * (needs expect reservations in newnat) + * - testing of incoming PPTP calls + * + * Changes: + * 2002-02-05 - Version 1.3 + * - Call ip_conntrack_unexpect_related() from + * pptp_timeout_related() to destroy expectations in case + * CALL_DISCONNECT_NOTIFY or tcp fin packet was seen + * (Philip Craig ) + * - Add Version information at module loadtime + * 2002-02-10 - Version 1.6 + * - move to C99 style initializers + * - remove second expectation if first arrives + * 2004-10-22 - Version 2.0 + * - merge Mandrake's 2.6.x port with recent 2.6.x API changes + * - fix lots of linear skb assumptions from Mandrake's port + * 2005-06-10 - Version 2.1 + * - use ip_conntrack_expect_free() instead of kfree() on the + * expect's (which are from the slab for quite some time) + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define IP_CT_PPTP_VERSION "2.1" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP"); + +DECLARE_LOCK(ip_pptp_lock); + +#if 0 +#include "ip_conntrack_pptp_priv.h" +#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args) +#else +#define DEBUGP(format, args...) +#endif + +#define SECS *HZ +#define MINS * 60 SECS +#define HOURS * 60 MINS +#define DAYS * 24 HOURS + +#define PPTP_GRE_TIMEOUT (10 MINS) +#define PPTP_GRE_STREAM_TIMEOUT (5 DAYS) + +static int pptp_expectfn(struct ip_conntrack *ct) +{ + struct ip_conntrack *master; + struct ip_conntrack_expect *exp; + + DEBUGP("increasing timeouts\n"); + /* increase timeout of GRE data channel conntrack entry */ + ct->proto.gre.timeout = PPTP_GRE_TIMEOUT; + ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT; + + master = master_ct(ct); + if (!master) { + DEBUGP(" no master!!!\n"); + return 0; + } + + exp = ct->master; + if (!exp) { + DEBUGP("no expectation!!\n"); + return 0; + } + + DEBUGP("completing tuples with ct info\n"); + /* we can do this, since we're unconfirmed */ + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key == + htonl(master->help.ct_pptp_info.pac_call_id)) { + /* assume PNS->PAC */ + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = + htonl(master->help.ct_pptp_info.pns_call_id); + ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key = + htonl(master->help.ct_pptp_info.pns_call_id); + } else { + /* assume PAC->PNS */ + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = + htonl(master->help.ct_pptp_info.pac_call_id); + ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key = + htonl(master->help.ct_pptp_info.pac_call_id); + } + + /* delete other expectation */ + if (exp->expected_list.next != &exp->expected_list) { + struct ip_conntrack_expect *other_exp; + struct list_head *cur_item, *next; + + for (cur_item = master->sibling_list.next; + cur_item != &master->sibling_list; cur_item = next) { + next = cur_item->next; + other_exp = list_entry(cur_item, + struct ip_conntrack_expect, + expected_list); + /* remove only if occurred at same sequence number */ + if (other_exp != exp && other_exp->seq == exp->seq) { + DEBUGP("unexpecting other direction\n"); + ip_ct_gre_keymap_destroy(other_exp); + ip_conntrack_unexpect_related(other_exp); + } + } + } + + return 0; +} + +/* timeout GRE data connections */ +static int pptp_timeout_related(struct ip_conntrack *ct) +{ + struct list_head *cur_item, *next; + struct ip_conntrack_expect *exp; + + /* FIXME: do we have to lock something ? */ + for (cur_item = ct->sibling_list.next; + cur_item != &ct->sibling_list; cur_item = next) { + next = cur_item->next; + exp = list_entry(cur_item, struct ip_conntrack_expect, + expected_list); + + ip_ct_gre_keymap_destroy(exp); + if (!exp->sibling) { + ip_conntrack_unexpect_related(exp); + continue; + } + + DEBUGP("setting timeout of conntrack %p to 0\n", + exp->sibling); + exp->sibling->proto.gre.timeout = 0; + exp->sibling->proto.gre.stream_timeout = 0; + /* refresh_acct will not modify counters if skb == NULL */ + //ip_ct_refresh_acct(exp->sibling, 0, NULL, 0); + ip_ct_refresh(exp->sibling, 0); + } + + return 0; +} + +/* expect GRE connections (PNS->PAC and PAC->PNS direction) */ +static inline int +exp_gre(struct ip_conntrack *master, + u_int32_t seq, + u_int16_t callid, + u_int16_t peer_callid) +{ + struct ip_conntrack_tuple inv_tuple; + struct ip_conntrack_tuple exp_tuples[] = { + /* tuple in original direction, PNS->PAC */ + { .src = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip, + .u = { .gre = { .key = htonl(ntohs(peer_callid)) } } + }, + .dst = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip, + .u = { .gre = { .key = htonl(ntohs(callid)) } }, + .protonum = IPPROTO_GRE + }, + }, + /* tuple in reply direction, PAC->PNS */ + { .src = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip, + .u = { .gre = { .key = htonl(ntohs(callid)) } } + }, + .dst = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip, + .u = { .gre = { .key = htonl(ntohs(peer_callid)) } }, + .protonum = IPPROTO_GRE + }, + } + }, *exp_tuple; + + for (exp_tuple = exp_tuples; exp_tuple < &exp_tuples[2]; exp_tuple++) { + struct ip_conntrack_expect *exp; + + exp = ip_conntrack_expect_alloc(); + if (exp == NULL) + return 1; + + memcpy(&exp->tuple, exp_tuple, sizeof(exp->tuple)); + + exp->mask.src.ip = 0xffffffff; + exp->mask.src.u.all = 0; + exp->mask.dst.u.all = 0; + exp->mask.dst.u.gre.key = 0xffffffff; + exp->mask.dst.ip = 0xffffffff; + exp->mask.dst.protonum = 0xffff; + + exp->seq = seq; + exp->expectfn = pptp_expectfn; + + exp->help.exp_pptp_info.pac_call_id = ntohs(callid); + exp->help.exp_pptp_info.pns_call_id = ntohs(peer_callid); + + DEBUGP("calling expect_related "); + DUMP_TUPLE_RAW(&exp->tuple); + + /* Add GRE keymap entries */ + if (ip_ct_gre_keymap_add(exp, &exp->tuple, 0) != 0) { + //ip_conntrack_expect_free(exp); + ip_conntrack_expect_put(exp); + return 1; + } + + invert_tuplepr(&inv_tuple, &exp->tuple); + if (ip_ct_gre_keymap_add(exp, &inv_tuple, 1) != 0) { + ip_ct_gre_keymap_destroy(exp); + //ip_conntrack_expect_free(exp); + ip_conntrack_expect_put(exp); + return 1; + } + + if (ip_conntrack_expect_related(exp, master) != 0) { + ip_ct_gre_keymap_destroy(exp); + //ip_conntrack_expect_free(exp); + ip_conntrack_expect_put(exp); + DEBUGP("cannot expect_related()\n"); + return 1; + } + } + + return 0; +} + +static inline int +pptp_inbound_pkt(struct sk_buff *skb, + struct tcphdr *tcph, + unsigned int ctlhoff, + size_t datalen, + struct ip_conntrack *ct) +{ + struct PptpControlHeader _ctlh, *ctlh; + unsigned int reqlen; + union pptp_ctrl_union _pptpReq, *pptpReq; + struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; + u_int16_t msg, *cid, *pcid; + u_int32_t seq; + + ctlh = skb_header_pointer(skb, ctlhoff, sizeof(_ctlh), &_ctlh); + if (unlikely(!ctlh)) { + DEBUGP("error during skb_header_pointer\n"); + return NF_ACCEPT; + } + + reqlen = datalen - sizeof(struct pptp_pkt_hdr) - sizeof(_ctlh); + pptpReq = skb_header_pointer(skb, ctlhoff+sizeof(_ctlh), + reqlen, &_pptpReq); + if (unlikely(!pptpReq)) { + DEBUGP("error during skb_header_pointer\n"); + return NF_ACCEPT; + } + + msg = ntohs(ctlh->messageType); + DEBUGP("inbound control message %s\n", strMName[msg]); + + switch (msg) { + case PPTP_START_SESSION_REPLY: + if (reqlen < sizeof(_pptpReq.srep)) { + DEBUGP("%s: short packet\n", strMName[msg]); + break; + } + + /* server confirms new control session */ + if (info->sstate < PPTP_SESSION_REQUESTED) { + DEBUGP("%s without START_SESS_REQUEST\n", + strMName[msg]); + break; + } + if (pptpReq->srep.resultCode == PPTP_START_OK) + info->sstate = PPTP_SESSION_CONFIRMED; + else + info->sstate = PPTP_SESSION_ERROR; + break; + + case PPTP_STOP_SESSION_REPLY: + if (reqlen < sizeof(_pptpReq.strep)) { + DEBUGP("%s: short packet\n", strMName[msg]); + break; + } + + /* server confirms end of control session */ + if (info->sstate > PPTP_SESSION_STOPREQ) { + DEBUGP("%s without STOP_SESS_REQUEST\n", + strMName[msg]); + break; + } + if (pptpReq->strep.resultCode == PPTP_STOP_OK) + info->sstate = PPTP_SESSION_NONE; + else + info->sstate = PPTP_SESSION_ERROR; + break; + + case PPTP_OUT_CALL_REPLY: + if (reqlen < sizeof(_pptpReq.ocack)) { + DEBUGP("%s: short packet\n", strMName[msg]); + break; + } + + /* server accepted call, we now expect GRE frames */ + if (info->sstate != PPTP_SESSION_CONFIRMED) { + DEBUGP("%s but no session\n", strMName[msg]); + break; + } + if (info->cstate != PPTP_CALL_OUT_REQ && + info->cstate != PPTP_CALL_OUT_CONF) { + DEBUGP("%s without OUTCALL_REQ\n", strMName[msg]); + break; + } + if (pptpReq->ocack.resultCode != PPTP_OUTCALL_CONNECT) { + info->cstate = PPTP_CALL_NONE; + break; + } + + cid = &pptpReq->ocack.callID; + pcid = &pptpReq->ocack.peersCallID; + + info->pac_call_id = ntohs(*cid); + + if (htons(info->pns_call_id) != *pcid) { + DEBUGP("%s for unknown callid %u\n", + strMName[msg], ntohs(*pcid)); + break; + } + + DEBUGP("%s, CID=%X, PCID=%X\n", strMName[msg], + ntohs(*cid), ntohs(*pcid)); + + info->cstate = PPTP_CALL_OUT_CONF; + + seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr) + + sizeof(struct PptpControlHeader) + + ((void *)pcid - (void *)pptpReq); + + if (exp_gre(ct, seq, *cid, *pcid) != 0) + printk("ip_conntrack_pptp: error during exp_gre\n"); + break; + + case PPTP_IN_CALL_REQUEST: + if (reqlen < sizeof(_pptpReq.icack)) { + DEBUGP("%s: short packet\n", strMName[msg]); + break; + } + + /* server tells us about incoming call request */ + if (info->sstate != PPTP_SESSION_CONFIRMED) { + DEBUGP("%s but no session\n", strMName[msg]); + break; + } + pcid = &pptpReq->icack.peersCallID; + DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid)); + info->cstate = PPTP_CALL_IN_REQ; + info->pac_call_id = ntohs(*pcid); + break; + + case PPTP_IN_CALL_CONNECT: + if (reqlen < sizeof(_pptpReq.iccon)) { + DEBUGP("%s: short packet\n", strMName[msg]); + break; + } + + /* server tells us about incoming call established */ + if (info->sstate != PPTP_SESSION_CONFIRMED) { + DEBUGP("%s but no session\n", strMName[msg]); + break; + } + if (info->sstate != PPTP_CALL_IN_REP + && info->sstate != PPTP_CALL_IN_CONF) { + DEBUGP("%s but never sent IN_CALL_REPLY\n", + strMName[msg]); + break; + } + + pcid = &pptpReq->iccon.peersCallID; + cid = &info->pac_call_id; + + if (info->pns_call_id != ntohs(*pcid)) { + DEBUGP("%s for unknown CallID %u\n", + strMName[msg], ntohs(*cid)); + break; + } + + DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid)); + info->cstate = PPTP_CALL_IN_CONF; + + /* we expect a GRE connection from PAC to PNS */ + seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr) + + sizeof(struct PptpControlHeader) + + ((void *)pcid - (void *)pptpReq); + + if (exp_gre(ct, seq, *cid, *pcid) != 0) + printk("ip_conntrack_pptp: error during exp_gre\n"); + + break; + + case PPTP_CALL_DISCONNECT_NOTIFY: + if (reqlen < sizeof(_pptpReq.disc)) { + DEBUGP("%s: short packet\n", strMName[msg]); + break; + } + + /* server confirms disconnect */ + cid = &pptpReq->disc.callID; + DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid)); + info->cstate = PPTP_CALL_NONE; + + /* untrack this call id, unexpect GRE packets */ + pptp_timeout_related(ct); + break; + + case PPTP_WAN_ERROR_NOTIFY: + break; + + case PPTP_ECHO_REQUEST: + case PPTP_ECHO_REPLY: + /* I don't have to explain these ;) */ + break; + default: + DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX) + ? strMName[msg]:strMName[0], msg); + break; + } + + return NF_ACCEPT; + +} + +static inline int +pptp_outbound_pkt(struct sk_buff *skb, + struct tcphdr *tcph, + unsigned int ctlhoff, + size_t datalen, + struct ip_conntrack *ct) +{ + struct PptpControlHeader _ctlh, *ctlh; + unsigned int reqlen; + union pptp_ctrl_union _pptpReq, *pptpReq; + struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; + u_int16_t msg, *cid, *pcid; + + ctlh = skb_header_pointer(skb, ctlhoff, sizeof(_ctlh), &_ctlh); + if (!ctlh) + return NF_ACCEPT; + + reqlen = datalen - sizeof(struct pptp_pkt_hdr) - sizeof(_ctlh); + pptpReq = skb_header_pointer(skb, ctlhoff+sizeof(_ctlh), reqlen, + &_pptpReq); + if (!pptpReq) + return NF_ACCEPT; + + msg = ntohs(ctlh->messageType); + DEBUGP("outbound control message %s\n", strMName[msg]); + + switch (msg) { + case PPTP_START_SESSION_REQUEST: + /* client requests for new control session */ + if (info->sstate != PPTP_SESSION_NONE) { + DEBUGP("%s but we already have one", + strMName[msg]); + } + info->sstate = PPTP_SESSION_REQUESTED; + break; + case PPTP_STOP_SESSION_REQUEST: + /* client requests end of control session */ + info->sstate = PPTP_SESSION_STOPREQ; + break; + + case PPTP_OUT_CALL_REQUEST: + if (reqlen < sizeof(_pptpReq.ocreq)) { + DEBUGP("%s: short packet\n", strMName[msg]); + /* FIXME: break; */ + } + + /* client initiating connection to server */ + if (info->sstate != PPTP_SESSION_CONFIRMED) { + DEBUGP("%s but no session\n", + strMName[msg]); + break; + } + info->cstate = PPTP_CALL_OUT_REQ; + /* track PNS call id */ + cid = &pptpReq->ocreq.callID; + DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid)); + info->pns_call_id = ntohs(*cid); + break; + case PPTP_IN_CALL_REPLY: + if (reqlen < sizeof(_pptpReq.icack)) { + DEBUGP("%s: short packet\n", strMName[msg]); + break; + } + + /* client answers incoming call */ + if (info->cstate != PPTP_CALL_IN_REQ + && info->cstate != PPTP_CALL_IN_REP) { + DEBUGP("%s without incall_req\n", + strMName[msg]); + break; + } + if (pptpReq->icack.resultCode != PPTP_INCALL_ACCEPT) { + info->cstate = PPTP_CALL_NONE; + break; + } + pcid = &pptpReq->icack.peersCallID; + if (info->pac_call_id != ntohs(*pcid)) { + DEBUGP("%s for unknown call %u\n", + strMName[msg], ntohs(*pcid)); + break; + } + DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*pcid)); + /* part two of the three-way handshake */ + info->cstate = PPTP_CALL_IN_REP; + info->pns_call_id = ntohs(pptpReq->icack.callID); + break; + + case PPTP_CALL_CLEAR_REQUEST: + /* client requests hangup of call */ + if (info->sstate != PPTP_SESSION_CONFIRMED) { + DEBUGP("CLEAR_CALL but no session\n"); + break; + } + /* FUTURE: iterate over all calls and check if + * call ID is valid. We don't do this without newnat, + * because we only know about last call */ + info->cstate = PPTP_CALL_CLEAR_REQ; + break; + case PPTP_SET_LINK_INFO: + break; + case PPTP_ECHO_REQUEST: + case PPTP_ECHO_REPLY: + /* I don't have to explain these ;) */ + break; + default: + DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)? + strMName[msg]:strMName[0], msg); + /* unknown: no need to create GRE masq table entry */ + break; + } + + return NF_ACCEPT; +} + + +/* track caller id inside control connection, call expect_related */ +static int +conntrack_pptp_help(struct sk_buff *skb, + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) + +{ + struct pptp_pkt_hdr _pptph, *pptph; + + struct tcphdr _tcph, *tcph; + u_int32_t tcplen = skb->len - skb->nh.iph->ihl * 4; + u_int32_t datalen; + void *datalimit; + int dir = CTINFO2DIR(ctinfo); + struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; + unsigned int nexthdr_off; + + int oldsstate, oldcstate; + int ret; + + /* don't do any tracking before tcp handshake complete */ + if (ctinfo != IP_CT_ESTABLISHED + && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) { + DEBUGP("ctinfo = %u, skipping\n", ctinfo); + return NF_ACCEPT; + } + + nexthdr_off = skb->nh.iph->ihl*4; + tcph = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_tcph), + &_tcph); + if (!tcph) + return NF_ACCEPT; + + /* not a complete TCP header? */ + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) { + DEBUGP("tcplen = %u\n", tcplen); + return NF_ACCEPT; + } + + + datalen = tcplen - tcph->doff * 4; + + /* checksum invalid? */ + if (tcp_v4_check(tcph, tcplen, skb->nh.iph->saddr, skb->nh.iph->daddr, + csum_partial((char *) tcph, tcplen, 0))) { + printk(KERN_NOTICE __FILE__ ": bad csum\n"); + /* W2K PPTP server sends TCP packets with wrong checksum :(( */ + //return NF_ACCEPT; + } + + if (tcph->fin || tcph->rst) { + DEBUGP("RST/FIN received, timeouting GRE\n"); + /* can't do this after real newnat */ + info->cstate = PPTP_CALL_NONE; + + /* untrack this call id, unexpect GRE packets */ + pptp_timeout_related(ct); + } + + nexthdr_off += tcph->doff*4; + pptph = skb_header_pointer(skb, skb->nh.iph->ihl*4 + tcph->doff*4, + sizeof(_pptph), &_pptph); + if (!pptph) { + DEBUGP("no full PPTP header, can't track\n"); + return NF_ACCEPT; + } + + datalimit = (void *) pptph + datalen; + + /* if it's not a control message we can't do anything with it */ + if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL || + ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) { + DEBUGP("not a control packet\n"); + return NF_ACCEPT; + } + + oldsstate = info->sstate; + oldcstate = info->cstate; + + LOCK_BH(&ip_pptp_lock); + + nexthdr_off += sizeof(_pptph); + /* FIXME: We just blindly assume that the control connection is always + * established from PNS->PAC. However, RFC makes no guarantee */ + if (dir == IP_CT_DIR_ORIGINAL) + /* client -> server (PNS -> PAC) */ + ret = pptp_outbound_pkt(skb, tcph, nexthdr_off, datalen, ct); + else + /* server -> client (PAC -> PNS) */ + ret = pptp_inbound_pkt(skb, tcph, nexthdr_off, datalen, ct); + DEBUGP("sstate: %d->%d, cstate: %d->%d\n", + oldsstate, info->sstate, oldcstate, info->cstate); + UNLOCK_BH(&ip_pptp_lock); + + return ret; +} + +/* control protocol helper */ +static struct ip_conntrack_helper pptp = { + .list = { NULL, NULL }, + .name = "pptp", + .flags = IP_CT_HELPER_F_REUSE_EXPECT, + .me = THIS_MODULE, + .max_expected = 2, + .timeout = 0, + .tuple = { .src = { .ip = 0, + .u = { .tcp = { .port = + __constant_htons(PPTP_CONTROL_PORT) } } + }, + .dst = { .ip = 0, + .u = { .all = 0 }, + .protonum = IPPROTO_TCP + } + }, + .mask = { .src = { .ip = 0, + .u = { .tcp = { .port = 0xffff } } + }, + .dst = { .ip = 0, + .u = { .all = 0 }, + .protonum = 0xffff + } + }, + .help = conntrack_pptp_help +}; + +/* ip_conntrack_pptp initialization */ +static int __init init(void) +{ + int retcode; + + DEBUGP(__FILE__ ": registering helper\n"); + if ((retcode = ip_conntrack_helper_register(&pptp))) { + printk(KERN_ERR "Unable to register conntrack application " + "helper for pptp: %d\n", retcode); + return -EIO; + } + + printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION); + return 0; +} + +static void __exit fini(void) +{ + ip_conntrack_helper_unregister(&pptp); + printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION); +} + +module_init(init); +module_exit(fini); + +EXPORT_SYMBOL(ip_pptp_lock); diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_proto_esp.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_proto_esp.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_proto_esp.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_proto_esp.c 2006-12-20 18:45:29.000000000 +0100 @@ -0,0 +1,406 @@ +/* +<:copyright-gpl + Copyright 2002 Broadcom Corp. All Rights Reserved. + + This program is free software; you can distribute it and/or modify it + under the terms of the GNU General Public License (Version 2) as + published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +:> +*/ +/****************************************************************************** +// +// Filename: ip_conntrack_proto_esp.c +// Author: Pavan Kumar +// Creation Date: 05/27/04 +// +// Description: +// Implements the ESP ALG connectiontracking. +// +*****************************************************************************/ +#include +#include +#include +#include +#include +#ifdef CONFIG_MIPS_BRCM +#include +#endif +#include +#include + +#define ESP_REF_TMOUT (30 * HZ) +#define ESP_CONN_TMOUT (60 * HZ * 6) +#define ESP_TMOUT_COUNT (ESP_CONN_TMOUT/ESP_REF_TMOUT) + +#ifdef CONFIG_MIPS_BRCM +#define ESP_UNREPLIEDDNS_TIMEOUT (1*HZ) +#endif + +#define IPSEC_FREE 0 +#define IPSEC_INUSE 1 +#define MAX_PORTS 64 +#define TEMP_SPI_START 1500 + +struct _esp_table { + u_int32_t l_spi; + u_int32_t r_spi; + u_int32_t l_ip; + u_int32_t r_ip; + u_int32_t timeout; + u_int16_t tspi; + struct ip_conntrack *ct; + struct timer_list refresh_timer; + int timer_active; + int pkt_rcvd; + int ntimeouts; + int inuse; +}; + +static struct _esp_table esp_table[MAX_PORTS]; + +#if 0 +#define DEBUGP(format, args...) printk(__FILE__ ":" __FUNCTION__ ": " \ + format, ## args) +#else +#define DEBUGP(format, args...) +#endif + +static u_int16_t cur_spi = 0; + +static void +esp_free_entry(int index) +{ + if (esp_table[index].inuse) { + if (esp_table[index].timer_active) { +#if IP_CONNTRACK_ESP_DEBUG + printk (KERN_DEBUG "%s:%s Deleting timer index %d\n", + __FILE__, __FUNCTION__, index); +#endif + del_timer(&esp_table[index].refresh_timer); + } + memset(&esp_table[index], 0, sizeof(struct _esp_table)); + } +} + +static void +esp_refresh_ct(unsigned long data) +{ + struct _esp_table *esp_entry = NULL; + + if (data > MAX_PORTS) { + return; + } + + esp_entry = &esp_table[data]; + if ( esp_entry == NULL ) { + return; + } +#if IP_CONNTRACK_ESP_DEBUG + printk(KERN_DEBUG "ntimeouts %d pkt_rcvd %d entry %p data %lu ct %p\n", + esp_entry->ntimeouts, esp_entry->pkt_rcvd, esp_entry, data, + esp_entry->ct); +#endif + if (esp_entry->pkt_rcvd) { + esp_entry->pkt_rcvd = 0; + esp_entry->ntimeouts = 0; + } else { + esp_entry->ntimeouts++; + if (esp_entry->ntimeouts >= ESP_TMOUT_COUNT) { + esp_free_entry(data); + return; + } + } + esp_entry->refresh_timer.expires = jiffies + ESP_REF_TMOUT; + esp_entry->refresh_timer.function = esp_refresh_ct; + esp_entry->refresh_timer.data = data; + ip_ct_refresh(esp_entry->ct, ESP_CONN_TMOUT); + add_timer(&esp_entry->refresh_timer); + esp_entry->timer_active = 1; +#if IP_CONNTRACK_ESP_DEBUG + printk(KERN_DEBUG "%s:%s Refreshed timer pkt_rcvd %d timeouts %d\n", + __FILE__, __FUNCTION__, esp_entry->pkt_rcvd, esp_entry->ntimeouts); +#endif +} + +/* + * Allocate a free IPSEC table entry. + */ +struct _esp_table *alloc_esp_entry ( void ) +{ + int idx = 0; + struct _esp_table *esp_entry = esp_table; + + for ( ; idx < MAX_PORTS; idx++ ) { + if ( esp_entry->inuse == IPSEC_FREE ) { + esp_entry->tspi = cur_spi = TEMP_SPI_START + idx; + esp_entry->inuse = IPSEC_INUSE; +#if IP_CONNTRACK_ESP_DEBUG + printk ( KERN_DEBUG "%s:%s New esp_entry at idx %d entry %p" + " tspi %u cspi %u\n", __FILE__, __FUNCTION__, idx, + esp_entry, esp_entry->tspi, cur_spi ); +#endif + init_timer(&esp_entry->refresh_timer); + esp_entry->refresh_timer.data = idx; + esp_entry->pkt_rcvd = 0; + esp_entry->refresh_timer.expires = jiffies + ESP_REF_TMOUT; + esp_entry->refresh_timer.function = esp_refresh_ct; + add_timer(&esp_entry->refresh_timer); + esp_entry->timer_active = 1; + return esp_entry; + } + esp_entry++; + } + return NULL; +} + +/* + * Search an ESP table entry by the Security Parameter Identifier (SPI). + */ +struct _esp_table *search_esp_entry_by_spi ( const struct esphdr *esph, + u_int32_t daddr ) +{ + int idx = 0; + struct _esp_table *esp_entry = esp_table; + +#if IP_CONNTRACK_ESP_DEBUG + printk ( KERN_DEBUG "%s:%s (0x%x) %u.%u.%u.%u\n", __FILE__, __FUNCTION__, + ntohl(esph->spi), NIPQUAD(daddr)); +#endif + for ( ; idx < MAX_PORTS; idx++, esp_entry++ ) { + if ( esp_entry->inuse == IPSEC_FREE ) { + continue; + } + /* If we have seen traffic both ways */ + if ( esp_entry->l_spi != 0 && esp_entry->r_spi != 0 ) { + if ( esp_entry->l_spi == ntohl(esph->spi) || + esp_entry->r_spi == ntohl(esph->spi) ) { +#if IP_CONNTRACK_ESP_DEBUG + printk (KERN_DEBUG "%s:%s Both Ways Traffic Entry %p\n", + __FILE__, __FUNCTION__, esp_entry); +#endif + return esp_entry; + } + continue; + } + /* If we have seen traffic only one way */ + if ( esp_entry->l_spi == 0 || esp_entry->r_spi == 0 ) { + /* We have traffic from local */ + if ( esp_entry->l_spi ) { + if ( ntohl(esph->spi) == esp_entry->l_spi ) { +#if IP_CONNTRACK_ESP_DEBUG + printk (KERN_DEBUG "%s:%s One Way Traffic From Local Entry %p\n", + __FILE__, __FUNCTION__, esp_entry); +#endif + return esp_entry; + } + /* This must be the first packet from remote */ + esp_entry->r_spi = ntohl(esph->spi); + esp_entry->r_ip = ntohl(daddr); +#if IP_CONNTRACK_ESP_DEBUG + printk (KERN_DEBUG "%s:%s First Packet from Remote Entry %p\n", + __FILE__, __FUNCTION__, esp_entry); +#endif + return esp_entry; + /* We have seen traffic only from remote */ + } else if ( esp_entry->r_spi ) { + if ( ntohl(esph->spi) == esp_entry->r_spi ) { +#if IP_CONNTRACK_ESP_DEBUG + printk (KERN_DEBUG "%s:%s One Way Traffic From Remote Entry %p\n", + __FILE__, __FUNCTION__, esp_entry); +#endif + return esp_entry; + } + /* This must be the first packet from local */ + esp_entry->l_spi = ntohl(esph->spi); +#if IP_CONNTRACK_ESP_DEBUG + printk (KERN_DEBUG "%s:%s First Packet From Remote Entry %p\n", + __FILE__, __FUNCTION__, esp_entry); +#endif + return esp_entry; + } + } + } +#if IP_CONNTRACK_ESP_DEBUG + printk (KERN_DEBUG "%s:%s No Entry\n", __FILE__, __FUNCTION__); +#endif + return NULL; +} + +static int esp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, + struct ip_conntrack_tuple *tuple) +{ + struct esphdr esph; + struct _esp_table *esp_entry; + const struct iphdr *iph = skb->nh.iph; + + if (skb_copy_bits(skb, dataoff, &esph, sizeof(esph)) != 0) + return 0; +#if IP_CONNTRACK_ESP_DEBUG + printk ( KERN_DEBUG "%s:%s (0x%x) IP Pkt Hdr %u.%u.%u.%u <-> %u.%u.%u.%u\n", + __FILE__, __FUNCTION__, ntohl(esph.spi), + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); + printk ( KERN_DEBUG "%s:%s (0x%x) %u.%u.%u.%u <-> %u.%u.%u.%u\n", + __FILE__, __FUNCTION__, ntohl(esph.spi), + NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip) ); +#endif + + if ( (esp_entry = search_esp_entry_by_spi ( &esph, tuple->dst.ip ) ) == NULL ) { + esp_entry = alloc_esp_entry(); + if ( esp_entry == NULL ) { + return 0; + } + esp_entry->l_spi = ntohl(esph.spi); + esp_entry->l_ip = ntohl(tuple->src.ip); + } +#if IP_CONNTRACK_ESP_DEBUG + printk ( KERN_DEBUG "%s:%s tspi %u cspi %u spi 0x%x seq 0x%x" + " sip %u.%u.%u.%u dip %u.%u.%u.%u\n", __FILE__, + __FUNCTION__, esp_entry->tspi, cur_spi, + ntohl(esph.spi), ntohl(esph.seq), + NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip) ); +#endif + tuple->dst.u.esp.spi = esp_entry->tspi; + tuple->src.u.esp.spi = esp_entry->tspi; + esp_entry->pkt_rcvd++; + return 1; +} + +static int esp_invert_tuple(struct ip_conntrack_tuple *tuple, + const struct ip_conntrack_tuple *orig) +{ +#if IP_CONNTRACK_ESP_DEBUG + printk ( KERN_DEBUG "%s:%s cspi 0x%x dspi 0x%x sspi 0x%x" + " %u.%u.%u.%u <-> %u.%u.%u.%u\n", + __FILE__, __FUNCTION__, cur_spi, orig->dst.u.esp.spi, + orig->src.u.esp.spi, NIPQUAD(tuple->src.ip), + NIPQUAD(tuple->dst.ip) ); +#endif + tuple->src.u.esp.spi = orig->dst.u.esp.spi; + tuple->dst.u.esp.spi = orig->src.u.esp.spi; + return 1; +} + +/* Print out the per-protocol part of the tuple. */ +static unsigned int esp_print_tuple(char *buffer, + const struct ip_conntrack_tuple *tuple) +{ + return sprintf(buffer, "sport=%u dport=%u ", + ntohs(tuple->src.u.esp.spi), ntohs(tuple->dst.u.esp.spi)); +} + +/* Print out the private part of the conntrack. */ +static unsigned int esp_print_conntrack(char *buffer, + const struct ip_conntrack *conntrack) +{ + return 0; +} + +/* Returns verdict for packet, and may modify conntracktype */ +static int esp_packet(struct ip_conntrack *conntrack, + const struct sk_buff *skb, + enum ip_conntrack_info conntrackinfo) +{ + const struct iphdr *iph = skb->nh.iph; + const struct esphdr *esph = (void *)iph + iph->ihl*4; + struct _esp_table *esp_entry; + +#if IP_CONNTRACK_ESP_DEBUG + printk ( KERN_DEBUG "%s:%s (0x%x) %u.%u.%u.%u <-> %u.%u.%u.%u %s\n", + __FILE__, __FUNCTION__, ntohl(esph->spi), + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr), + (conntrackinfo == IP_CT_NEW ) ? "CT_NEW" : "SEEN_REPLY" ); +#endif + /* + * This should not happen. We get into this routine only if there is + * an existing stream. + */ +#if IP_CONNTRACK_ESP_DEBUG + printk(KERN_DEBUG "%s:%s conntrackinfo %d\n", __FILE__, __FUNCTION__, conntrackinfo); +#endif + if (conntrackinfo == IP_CT_NEW ) { +#if IP_CONNTRACK_ESP_DEBUG + printk ( KERN_DEBUG "%s:%s IP_CT_NEW (0x%x) %u.%u.%u.%u <-> %u.%u.%u.%u\n", + __FILE__, __FUNCTION__, esph->spi, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); +#endif + if ( (esp_entry = search_esp_entry_by_spi ( esph, + iph->daddr ) ) == NULL ) { + esp_entry = alloc_esp_entry (); + if ( esp_entry == NULL ) { + /* All entries are currently in use */ + printk ( KERN_DEBUG "%s:%s All connections in use\n", + __FILE__, __FUNCTION__); + return NF_DROP; + } + esp_entry->l_spi = ntohl(esph->spi); + esp_entry->l_ip = ntohl(iph->saddr); + esp_entry->r_spi = 0; + } + esp_entry->pkt_rcvd++; +#if IP_CONNTRACK_ESP_DEBUG + printk( KERN_DEBUG "%s:%s Received COUNT %d\n", __FILE__, __FUNCTION__, esp_entry->pkt_rcvd); +#endif + } + /* If we've seen traffic both ways, this is some kind of UDP + stream. Extend timeout. */ +#if IP_CONNTRACK_ESP_DEBUG + printk(KERN_DEBUG "%s:%s status %lu\n", __FILE__, __FUNCTION__, conntrack->status); +#endif + if (conntrack->status & IPS_SEEN_REPLY) { + ip_ct_refresh(conntrack, ESP_CONN_TMOUT); + /* Also, more likely to be important, and not a probe */ + set_bit(IPS_ASSURED_BIT, &conntrack->status); + } else { + ip_ct_refresh(conntrack, ESP_REF_TMOUT); + } + //esp_entry = search_esp_entry_by_spi ( esph, iph->daddr ); + + return NF_ACCEPT; +} + +/* Called when a new connection for this protocol found. */ +static int esp_new(struct ip_conntrack *conntrack, const struct sk_buff *skb) +{ + const struct iphdr *iph = skb->nh.iph; + const struct esphdr *esph = (void *)iph + iph->ihl*4; + struct _esp_table *esp_entry; +#if IP_CONNTRACK_ESP_DEBUG + printk ( KERN_DEBUG "%s:%s (0x%x) %u.%u.%u.%u <-> %u.%u.%u.%u\n", + __FILE__, __FUNCTION__, ntohl(esph->spi), + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); +#endif + if ( (esp_entry = search_esp_entry_by_spi ( esph, iph->daddr ) ) == NULL ) { + /* + * Check if this is the same LAN client creating another session. + * If this is true, then the LAN IP address will be the same with + * a new SPI value. This would indicate that the entire transaction + * using the previous value of SPI is now not required. + */ + esp_entry = alloc_esp_entry (); + if ( esp_entry == NULL ) { + /* All entries are currently in use */ + printk ( KERN_DEBUG "%s:%s All connections in use\n", + __FILE__, __FUNCTION__); + return NF_DROP; + } + esp_entry->l_spi = ntohl(esph->spi); + esp_entry->l_ip = ntohl(iph->saddr); + esp_entry->r_spi = 0; + } + esp_entry->pkt_rcvd++; + esp_entry->ct = conntrack; + return 1; +} + +struct ip_conntrack_protocol ip_conntrack_protocol_esp += { { NULL, NULL }, IPPROTO_ESP, "esp", + esp_pkt_to_tuple, esp_invert_tuple, esp_print_tuple, esp_print_conntrack, + esp_packet, esp_new, NULL }; diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_proto_icmp.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_proto_icmp.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2004-02-19 04:06:36.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2006-12-20 18:45:29.000000000 +0100 @@ -14,7 +14,11 @@ #include #include +#ifdef CONFIG_MIPS_BRCM +unsigned long ip_ct_icmp_timeout = 4*HZ; +#else unsigned long ip_ct_icmp_timeout = 30*HZ; +#endif #if 0 #define DEBUGP printk @@ -100,6 +104,9 @@ return NF_ACCEPT; } +#ifdef CONFIG_MIPS_BRCM +extern int ip_conntrack_max; +#endif /* Called when a new connection for this protocol found. */ static int icmp_new(struct ip_conntrack *conntrack, const struct sk_buff *skb) @@ -109,6 +116,11 @@ [ICMP_TIMESTAMP] = 1, [ICMP_INFO_REQUEST] = 1, [ICMP_ADDRESS] = 1 }; +#ifdef CONFIG_MIPS_BRCM + if ( ip_conntrack_max == 0) + return NF_DROP; +#endif + if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new) || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) { diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_proto_udp.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_proto_udp.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2004-02-19 04:06:36.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2006-12-20 18:45:29.000000000 +0100 @@ -11,12 +11,19 @@ #include #include #include +#if defined(CONFIG_MIPS_BRCM) +#include +#endif #include #include unsigned long ip_ct_udp_timeout = 30*HZ; unsigned long ip_ct_udp_timeout_stream = 180*HZ; +#if defined(CONFIG_MIPS_BRCM) +unsigned long ip_ct_udp_unreplieddns_timeout = 1*HZ; +#endif + static int udp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, struct ip_conntrack_tuple *tuple) @@ -69,7 +76,28 @@ /* Also, more likely to be important, and not a probe */ set_bit(IPS_ASSURED_BIT, &conntrack->status); } else +#if defined(CONFIG_MIPS_BRCM) + { + /* Special handling of UNRPLIED DNS query packet: Song Wang + * Before NAT and WAN interface are UP, during that time window, + * if a DNS query is sent out, there will be an UNRPLIED DNS connection track entry + * in which expected src/dst are private IP addresses in the tuple. + * After NAT and WAN interface are UP, the UNRPLIED DNS connection track + * entry should go away ASAP to enable the establishment of the tuple with + * the expected src/dst that are public IP addresses. + */ + struct iphdr *iph = skb->nh.iph; + struct udphdr *udph = (void *)iph + iph->ihl * 4; + __u16 dport = ntohs(udph->dest); + + if (dport == 53) + ip_ct_refresh(conntrack, ip_ct_udp_unreplieddns_timeout); + else + ip_ct_refresh(conntrack, ip_ct_udp_timeout); + } +#else ip_ct_refresh(conntrack, ip_ct_udp_timeout); +#endif return NF_ACCEPT; } diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_rtsp.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_rtsp.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_rtsp.c 2006-12-20 18:45:29.000000000 +0100 @@ -0,0 +1,888 @@ +/* + * RTSP extension for IP connection tracking + * (C) 2003 by Tom Marshall + * based on ip_conntrack_irc.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Module load syntax: + * insmod ip_conntrack_rtsp.o ports=port1,port2,...port + * max_outstanding=n setup_timeout=secs + * + * If no ports are specified, the default will be port 554. + * + * With max_outstanding you can define the maximum number of not yet + * answered SETUP requests per RTSP session (default 8). + * With setup_timeout you can specify how long the system waits for + * an expected data channel (default 300 seconds). + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#define NF_NEED_STRNCASECMP +#define NF_NEED_STRTOU16 +#define NF_NEED_STRTOU32 +#define NF_NEED_NEXTLINE +#include +#define NF_NEED_MIME_NEXTLINE +#include + +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */ + +/* + * To enable debugging, replace the line below with #define IP_NF_RTSP_DEBUG 1 + */ +#undef IP_NF_RTSP_DEBUG +#define INFOP(args...) printk(KERN_INFO args) +#ifdef IP_NF_RTSP_DEBUG +#define DEBUGP(args...) printk(KERN_DEBUG "%s:%s ", __FILE__, __FUNCTION__); \ + printk(args) +#else +#define DEBUGP(args...) +#endif + +#define MAX_PORTS 8 +static int ports[MAX_PORTS]; +static int num_ports = 0; +static int max_outstanding = 8; +static unsigned int setup_timeout = 300; + +/* This is slow, but it's simple. --RR */ +static char rtsp_buffer[65536]; + +MODULE_AUTHOR("Tom Marshall "); +MODULE_DESCRIPTION("RTSP connection tracking module"); +MODULE_LICENSE("GPL"); +#ifdef MODULE_PARM +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i"); +MODULE_PARM_DESC(ports, "port numbers of RTSP servers"); +MODULE_PARM(max_outstanding, "i"); +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session"); +//MODULE_PARM(setup_timeout, "i"); +//MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels"); +#endif + +DECLARE_LOCK(ip_rtsp_lock); +struct module* ip_conntrack_rtsp = THIS_MODULE; + +/* + * Max mappings we will allow for one RTSP connection (for RTP, the number + * of allocated ports is twice this value). Note that SMIL burns a lot of + * ports so keep this reasonably high. If this is too low, you will see a + * lot of "no free client map entries" messages. + */ +#define MAX_PORT_MAPS 16 +static u_int16_t g_tr_port = 7000; + +#define PAUSE_TIMEOUT (5 * HZ) +#define RTSP_PAUSE_TIMEOUT (6 * HZ) + +/*** default port list was here in the masq code: 554, 3030, 4040 ***/ + +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } +/* + * Structure to hold the mappings from client to NAT vice versa. If we + * mangle UDP ports in the outgoing SETUP message, we must properly + * mangle them in the return direction so that the client will + * process the packets appropriately. + */ +struct _rtsp_data_ports { + u_int32_t client_ip; + u_int16_t client_tcp_port; + u_int16_t client_udp_lo; + u_int16_t client_udp_hi; + portblock_t pbtype; + u_int16_t nat_udp_lo; + u_int16_t nat_udp_hi; + struct timer_list pause_timeout; + struct ip_conntrack *ct_lo; + struct ip_conntrack *ct_hi; + int timeout_active; + int in_use; +} rtsp_data_ports[MAX_PORT_MAPS]; + +static u_int16_t rtsp_nat_to_client_pmap(u_int16_t nat_port); + +static void +save_ct(struct ip_conntrack *ct) +{ + int i = 0; + struct ip_conntrack_tuple *tp = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + + for (i = 0; i < MAX_PORT_MAPS; i++) + { + if (!rtsp_data_ports[i].in_use) + { + continue; + } + if (rtsp_data_ports[i].nat_udp_lo == ntohs((tp)->dst.u.all)) + { + rtsp_data_ports[i].ct_lo = ct; + break; + } + else if (rtsp_data_ports[i].nat_udp_hi == ntohs((tp)->dst.u.all)) + { + rtsp_data_ports[i].ct_hi = ct; + break; + } + } +} + +static void +rtsp_pause_timeout(unsigned long data) +{ + int index = (int)data; + struct _rtsp_data_ports *rtsp_data = &rtsp_data_ports[index]; + struct ip_conntrack *ct_lo = rtsp_data->ct_lo; + + if (rtsp_data->in_use) { + rtsp_data->pause_timeout.expires = jiffies + PAUSE_TIMEOUT; + rtsp_data->pause_timeout.function = rtsp_pause_timeout; + rtsp_data->pause_timeout.data = data; + rtsp_data->timeout_active = 1; + ip_ct_refresh(ct_lo, RTSP_PAUSE_TIMEOUT); + add_timer(&rtsp_data->pause_timeout); + } +} + +static void +ip_conntrack_rtsp_proc_play(struct ip_conntrack *ct, const struct iphdr *iph) +{ + int i = 0; + struct tcphdr *tcph = (void *)iph + iph->ihl * 4; + + for (i = 0; i < MAX_PORT_MAPS; i++) + { + if (!rtsp_data_ports[i].in_use) + { + continue; + } + DEBUGP("Searching client info IP %u.%u.%u.%u->%hu PORTS (%hu-%hu)\n", + NIPQUAD(iph->saddr), tcph->source, rtsp_data_ports[i].client_udp_lo, + rtsp_data_ports[i].client_udp_hi); + if ((rtsp_data_ports[i].client_ip == iph->saddr) && + (rtsp_data_ports[i].client_tcp_port == tcph->source)) + { + DEBUGP("Found client info SRC IP %u.%u.%u.%u TCP PORT %hu UDP PORTS (%hu-%hu)\n", + NIPQUAD(iph->saddr), tcph->source, rtsp_data_ports[i].client_udp_lo, + rtsp_data_ports[i].client_udp_hi); + if (rtsp_data_ports[i].timeout_active) + { + del_timer(&rtsp_data_ports[i].pause_timeout); + rtsp_data_ports[i].timeout_active = 0; + } + } + } +} + +static void +ip_conntrack_rtsp_proc_pause(struct ip_conntrack *ct, const struct iphdr *iph) +{ + int i = 0; + struct tcphdr *tcph = (void *)iph + iph->ihl * 4; + struct ip_conntrack_tuple *tp_lo; + struct ip_conntrack_tuple *tp_hi; + struct ip_conntrack *ct_lo; + struct ip_conntrack *ct_hi; + + for (i = 0; i < MAX_PORT_MAPS; i++) + { + if (!rtsp_data_ports[i].in_use) + { + continue; + } + DEBUGP("Searching client info IP %u.%u.%u.%u->%hu PORTS (%hu-%hu)\n", + NIPQUAD(iph->saddr), tcph->source, rtsp_data_ports[i].client_udp_lo, + rtsp_data_ports[i].client_udp_hi); + if ((rtsp_data_ports[i].client_ip == iph->saddr) && + (rtsp_data_ports[i].client_tcp_port == tcph->source)) + { + DEBUGP("Found client info SRC IP %u.%u.%u.%u TCP PORT %hu UDP PORTS (%hu-%hu)\n", + NIPQUAD(iph->saddr), tcph->source, rtsp_data_ports[i].client_udp_lo, + rtsp_data_ports[i].client_udp_hi); + if (rtsp_data_ports[i].timeout_active != 0 || + rtsp_data_ports[i].ct_lo == NULL) + { + break; + } + rtsp_data_ports[i].pause_timeout.expires = jiffies + PAUSE_TIMEOUT; + rtsp_data_ports[i].pause_timeout.function = rtsp_pause_timeout; + rtsp_data_ports[i].pause_timeout.data = (unsigned long)i; + add_timer(&rtsp_data_ports[i].pause_timeout); + rtsp_data_ports[i].timeout_active = 1; + rtsp_data_ports[i].ct_lo = ct; + tp_lo = &ct_lo->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + tp_hi = &ct_hi->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + ip_ct_refresh(ct, RTSP_PAUSE_TIMEOUT); + } + } +} + +static int +rtp_expect(struct ip_conntrack *ct) +{ + u_int16_t nat_port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port; + u_int16_t orig_port = 0; + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); + orig_port = rtsp_nat_to_client_pmap(nat_port); + if (orig_port) + { + ct->nat.rtsp_info.orig_port = orig_port; + } else { + return NF_DROP; + } + DEBUGP("UDP client port %hu\n", ct->nat.rtsp_info.orig_port); + save_ct(ct); + + return NF_ACCEPT; +} + +/* + * Maps client ports that are overlapping with other client UDP transport to + * new NAT ports that will be tracked and converted back to client assigned + * UDP ports. + * Return (N/A) + */ +static int +rtsp_client_to_nat_pmap(struct ip_ct_rtsp_expect *prtspexp, const struct iphdr *iph, + struct ip_conntrack *ct) +{ + int i = 0; + int rc = 0; + struct tcphdr *tcph = (void *)iph + iph->ihl * 4; + + DEBUGP("IP %u.%u.%u.%u->%u.%u.%u.%u PORTS (%hu-%hu)\n", NIPQUAD(iph->saddr), + NIPQUAD(iph->daddr), tcph->source, tcph->dest); + + for (i = 0; i < MAX_PORT_MAPS; i++) { + if (rtsp_data_ports[i].in_use) { + DEBUGP("Index %d in_use flag %d IP %u.%u.%u.%u CLIENT %hu-%hu NAT %hu-%hu\n", i, + rtsp_data_ports[i].in_use, NIPQUAD(rtsp_data_ports[i].client_ip), + rtsp_data_ports[i].client_udp_lo, rtsp_data_ports[i].client_udp_hi, + rtsp_data_ports[i].nat_udp_lo, rtsp_data_ports[i].nat_udp_hi); + if (ntohl(iph->saddr) == rtsp_data_ports[i].client_ip && + ntohs(tcph->source) == rtsp_data_ports[i].client_tcp_port && + ntohs(prtspexp->loport) == rtsp_data_ports[i].client_udp_lo && + ntohs(prtspexp->hiport) == rtsp_data_ports[i].client_udp_hi) + { + prtspexp->loport = rtsp_data_ports[i].nat_udp_lo; + prtspexp->hiport = rtsp_data_ports[i].nat_udp_hi; + return rc = 2; + } + continue; + } + rtsp_data_ports[i].client_ip = ntohl(iph->saddr); + rtsp_data_ports[i].client_tcp_port = ntohs(tcph->source); + rtsp_data_ports[i].client_udp_lo = ntohs(prtspexp->loport); + rtsp_data_ports[i].client_udp_hi = ntohs(prtspexp->hiport); + rtsp_data_ports[i].pbtype = prtspexp->pbtype; + rtsp_data_ports[i].in_use = 1; + init_timer(&rtsp_data_ports[i].pause_timeout); + DEBUGP("Mapped at index %d ORIGINAL PORTS %hu-%hu\n", i, + ntohs(prtspexp->loport), ntohs(prtspexp->hiport)); + prtspexp->loport = rtsp_data_ports[i].nat_udp_lo = g_tr_port++; + prtspexp->hiport = rtsp_data_ports[i].nat_udp_hi = g_tr_port++; + DEBUGP("NEW PORTS %hu-%hu\n", ntohs(prtspexp->loport), ntohs(prtspexp->hiport)); + return rc = 1; + } + return rc; +} + +/* + * Performs NAT to client port mapping. Incoming UDP ports are looked up and + * appropriate client ports are extracted from the table and returned. + * Return client_udp_port or 0 when no matches found. + */ +static u_int16_t +rtsp_nat_to_client_pmap(u_int16_t nat_port) +{ + int i = 0; + u_int16_t tr_port = 0; + + for (i = 0; i < MAX_PORT_MAPS; i++) { + if (!rtsp_data_ports[i].in_use) { + continue; + } + /* + * Check if the UDP ports match any of our NAT ports and return + * the client UDP ports. + */ + DEBUGP("Searching at index %d NAT_PORT %hu CLIENT PORTS (%hu-%hu)\n", i, + ntohs(nat_port), rtsp_data_ports[i].client_udp_lo, + rtsp_data_ports[i].client_udp_hi); + if (ntohs(nat_port) == rtsp_data_ports[i].nat_udp_lo || + ntohs(nat_port) == rtsp_data_ports[i].client_udp_lo) { + tr_port = rtsp_data_ports[i].client_udp_lo; + DEBUGP("Found at index %d NAT_PORT %hu CLIENT PORTS (%hu-%hu) tr_port %hu\n", i, + nat_port, rtsp_data_ports[i].client_udp_lo, + rtsp_data_ports[i].client_udp_hi, tr_port); + } else if (ntohs(nat_port) == rtsp_data_ports[i].nat_udp_hi || + ntohs(nat_port) == rtsp_data_ports[i].client_udp_hi) { + tr_port = rtsp_data_ports[i].client_udp_hi; + DEBUGP("Found at index %d NAT_PORT %hu CLIENT PORTS %hu-%hu tr_port %hu\n", i, + nat_port, rtsp_data_ports[i].client_udp_lo, + rtsp_data_ports[i].client_udp_hi, tr_port); + return tr_port; + } + } + return tr_port; +} + +static void +ip_conntrack_rtsp_proc_teardown(struct iphdr *iph) +{ + int i = 0; + struct tcphdr *tcph = (void *)iph + iph->ihl * 4; + + for (i = 0; i < MAX_PORT_MAPS; i++) + { + if (!rtsp_data_ports[i].in_use) + { + continue; + } + DEBUGP("Searching client info IP %u.%u.%u.%u->%hu PORTS (%hu-%hu)\n", + NIPQUAD(iph->saddr), tcph->source, rtsp_data_ports[i].client_udp_lo, + rtsp_data_ports[i].client_udp_hi); + if ((rtsp_data_ports[i].client_ip == iph->saddr) && + (rtsp_data_ports[i].client_tcp_port == tcph->source)) + { + DEBUGP("Found client info SRC IP %u.%u.%u.%u TCP PORT %hu UDP PORTS (%hu-%hu)\n", + NIPQUAD(iph->saddr), tcph->source, rtsp_data_ports[i].client_udp_lo, + rtsp_data_ports[i].client_udp_hi); + if (rtsp_data_ports[i].timeout_active) + { + del_timer(&rtsp_data_ports[i].pause_timeout); + rtsp_data_ports[i].timeout_active = 0; + } + memset(&rtsp_data_ports[i], 0, sizeof(struct _rtsp_data_ports)); + rtsp_data_ports[i].in_use = 0; + //break; + } + } +} + +static void * +find_char(void *str, int ch, size_t len) +{ + unsigned char *pStr = NULL; + if (len != 0) { + pStr = str; + } + do { + if (*pStr++ == ch) { + return ((void *)(pStr - 1)); + } + } while (--len != 0); + return (NULL); +} + +/* + * Parse an RTSP packet. + * + * Returns zero if parsing failed. + * + * Parameters: + * IN ptcp tcp data pointer + * IN tcplen tcp data len + * IN/OUT ptcpoff points to current tcp offset + * OUT phdrsoff set to offset of rtsp headers + * OUT phdrslen set to length of rtsp headers + * OUT pcseqoff set to offset of CSeq header + * OUT pcseqlen set to length of CSeq header + */ +static int +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff, + uint* phdrsoff, uint* phdrslen, + uint* pcseqoff, uint* pcseqlen) +{ + uint entitylen = 0; + uint lineoff; + uint linelen; + + if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) + { + return 0; + } + + *phdrsoff = *ptcpoff; + while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) + { + if (linelen == 0) + { + if (entitylen > 0) + { + *ptcpoff += min(entitylen, tcplen - *ptcpoff); + } + break; + } + if (lineoff+linelen > tcplen) + { + INFOP("!! overrun !!\n"); + break; + } + + if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0) + { + *pcseqoff = lineoff; + *pcseqlen = linelen; + } + if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0) + { + uint off = lineoff+15; + SKIP_WSPACE(ptcp+lineoff, linelen, off); + nf_strtou32(ptcp+off, &entitylen); + } + } + *phdrslen = (*ptcpoff) - (*phdrsoff); + + return 1; +} + +/* + * Find lo/hi client ports (if any) in transport header + * In: + * ptcp, tcplen = packet + * tranoff, tranlen = buffer to search + * + * Out: + * pport_lo, pport_hi = lo/hi ports (host endian) + * + * Returns nonzero if any client ports found + * + * Note: it is valid (and expected) for the client to request multiple + * transports, so we need to parse the entire line. + */ +static int +rtsp_parse_transport(char* ptran, uint tranlen, + struct ip_ct_rtsp_expect* prtspexp) +{ + int rc = 0; + uint off = 0; + + if (tranlen < 10 || !iseol(ptran[tranlen-1]) || + nf_strncasecmp(ptran, "Transport:", 10) != 0) + { + INFOP("sanity check failed\n"); + return 0; + } + DEBUGP("tran='%.*s'\n", (int)tranlen, ptran); + off += 10; + SKIP_WSPACE(ptran, tranlen, off); + + /* Transport: tran;field;field=val,tran;field;field=val,... */ + while (off < tranlen) + { + const char* pparamend; + uint nextparamoff; + + pparamend = find_char(ptran+off, ',', tranlen-off); + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; + nextparamoff = pparamend-ptran; + + while (off < nextparamoff) + { + const char* pfieldend; + uint nextfieldoff; + + pfieldend = find_char(ptran+off, ';', nextparamoff-off); + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; + + if (strncmp(ptran+off, "client_port=", 12) == 0) + { + u_int16_t port; + uint numlen; + + off += 12; + numlen = nf_strtou16(ptran+off, &port); + off += numlen; + if (prtspexp->loport != 0 && prtspexp->loport != port) + { + DEBUGP("multiple ports found, port %hu ignored\n", port); + } + else + { + prtspexp->loport = prtspexp->hiport = port; + DEBUGP("DASH or SLASH 0x%x\n", ptran[off]); + if (ptran[off] == '-') + { + off++; + numlen = nf_strtou16(ptran+off, &port); + off += numlen; + prtspexp->pbtype = pb_range; + prtspexp->hiport = port; + + // If we have a range, assume rtp: + // loport must be even, hiport must be loport+1 + if ((prtspexp->loport & 0x0001) != 0 || + prtspexp->hiport != prtspexp->loport+1) + { + DEBUGP("incorrect range: %hu-%hu, correcting\n", + prtspexp->loport, prtspexp->hiport); + prtspexp->loport &= 0xfffe; + prtspexp->hiport = prtspexp->loport+1; + } + } + else if (ptran[off] == '/') + { + off++; + numlen = nf_strtou16(ptran+off, &port); + off += numlen; + prtspexp->pbtype = pb_discon; + prtspexp->hiport = port; + } + rc = 1; + } + } + + /* + * Note we don't look for the destination parameter here. + * If we are using NAT, the NAT module will handle it. If not, + * and the client is sending packets elsewhere, the expectation + * will quietly time out. + */ + + off = nextfieldoff; + } + + off = nextparamoff; + } + + return rc; +} + +/*** conntrack functions ***/ + +/* outbound packet: client->server */ +static int +help_out(struct iphdr* iph, char* pdata, size_t datalen, + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo) +{ + int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */ + uint dataoff = 0; + struct tcphdr *tcph = (void *)iph + iph->ihl * 4; + + struct ip_conntrack_expect exp; + + while (dataoff < datalen) + { + uint cmdoff = dataoff; + uint hdrsoff = 0; + uint hdrslen = 0; + uint cseqoff = 0; + uint cseqlen = 0; + uint lineoff = 0; + uint linelen = 0; + uint off; + int rc; + uint port = 0; + struct ip_conntrack_expect *new_exp = NULL; + int ret = 0; + + if (!rtsp_parse_message(pdata, datalen, &dataoff, + &hdrsoff, &hdrslen, + &cseqoff, &cseqlen)) + { + break; /* not a valid message */ + } + + if (strncmp(pdata+cmdoff, "PLAY ", 5) == 0) + { + ip_conntrack_rtsp_proc_play(ct, iph); + continue; + } + + if (strncmp(pdata+cmdoff, "PAUSE ", 6) == 0) + { + ip_conntrack_rtsp_proc_pause(ct, iph); + continue; + } + + if (strncmp(pdata+cmdoff, "TEARDOWN ", 6) == 0) + { + ip_conntrack_rtsp_proc_teardown(iph); /* TEARDOWN message */ + continue; + } + + if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0) + { + continue; /* not a SETUP message */ + } + DEBUGP("found a setup message\n"); + + memset(&exp, 0, sizeof(exp)); + + off = 0; + + while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off, + &lineoff, &linelen)) + { + if (linelen == 0) + { + break; + } + if (off > hdrsoff+hdrslen) + { + INFOP("!! overrun !!"); + break; + } + + if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0) + { + rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen, + &exp.help.exp_rtsp_info); + } + } + + if (exp.help.exp_rtsp_info.loport == 0) + { + DEBUGP("no udp transports found\n"); + continue; /* no udp transports found */ + } + + DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n", + (int)exp.help.exp_rtsp_info.pbtype, + exp.help.exp_rtsp_info.loport, + exp.help.exp_rtsp_info.hiport); + + LOCK_BH(&ip_rtsp_lock); + /* + * Translate the original ports to the NAT ports and note them + * down to translate back in the return direction. + */ + if (!(ret = rtsp_client_to_nat_pmap(&exp.help.exp_rtsp_info, iph, ct))) + { + DEBUGP("Dropping the packet. No more space in the mapping table\n"); + UNLOCK_BH(&ip_rtsp_lock); + return NF_DROP; + } + port = exp.help.exp_rtsp_info.loport; + while (port <= exp.help.exp_rtsp_info.hiport) { + /* + * Allocate expectation for tracking this connection + */ + new_exp = ip_conntrack_expect_alloc(); + if (!new_exp) { + INFOP("Failed to get a new expectation entry\n"); + UNLOCK_BH(&ip_rtsp_lock); + return NF_DROP; + } + memcpy(new_exp, &exp, sizeof(struct ip_conntrack_expect)); + new_exp->seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */ + new_exp->help.exp_rtsp_info.len = hdrslen; + + DEBUGP("Adding UDP port %hu,%hu\n", htons(port), ntohs(port)); + + new_exp->tuple = ct->tuplehash[!dir].tuple; + if (ret == 2) { + new_exp->tuple.dst.u.udp.port = htons(g_tr_port); + g_tr_port++; + } else + new_exp->tuple.dst.u.udp.port = htons(port); + new_exp->tuple.dst.protonum = IPPROTO_UDP; + new_exp->mask.src.ip = 0xffffffff; + new_exp->mask.dst.ip = 0xffffffff; + //new_exp->mask.dst.u.udp.port = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff; + new_exp->mask.dst.u.udp.port = 0xffff; + new_exp->expectfn = rtp_expect; + new_exp->mask.dst.protonum = 0xffff; + + DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n", + NIPQUAD(new_exp->tuple.src.ip), + ntohs(new_exp->tuple.src.u.tcp.port), + NIPQUAD(new_exp->tuple.dst.ip), + ntohs(new_exp->tuple.dst.u.tcp.port)); + + /* pass the request off to the nat helper */ + rc = ip_conntrack_expect_related(new_exp, ct); + if (rc == 0) + { + DEBUGP("ip_conntrack_expect_related succeeded loport\n"); + } + else + { + DEBUGP("ip_conntrack_expect_related loport failed (%d)\n", rc); + } + port++; + } + UNLOCK_BH(&ip_rtsp_lock); + } + + return NF_ACCEPT; +} + +/* inbound packet: server->client */ +static int +help_in(struct tcphdr* tcph, char* pdata, size_t datalen, + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo) +{ + return NF_ACCEPT; +} + +static int +help(struct sk_buff* skb, + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo) +{ + uint dataoff; + struct iphdr *iph = skb->nh.iph; + struct tcphdr tcph; + char* data; + uint datalen; + + /* Until there's been traffic both ways, don't look in packets. */ + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) + { + DEBUGP("conntrackinfo = %u\n", ctinfo); + return NF_ACCEPT; + } + + /* Not whole TCP header? */ + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) != 0) + { + return NF_ACCEPT; + } + + /* No data? */ + dataoff = skb->nh.iph->ihl*4 + tcph.doff*4; + if ( skb->nh.iph->ihl*4 + tcph.doff*4 >= skb->len) + { + return NF_ACCEPT; + } + + LOCK_BH(&ip_rtsp_lock); + skb_copy_bits(skb, dataoff, rtsp_buffer, skb->len - dataoff); + data = rtsp_buffer; + datalen = skb->len - dataoff; + switch (CTINFO2DIR(ctinfo)) + { + case IP_CT_DIR_ORIGINAL: + help_out(iph, data, datalen, ct, ctinfo); + break; + case IP_CT_DIR_REPLY: + help_in(&tcph, data, datalen, ct, ctinfo); + break; + default: + /* oops */ + break; + } + UNLOCK_BH(&ip_rtsp_lock); + + return NF_ACCEPT; +} + +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS]; +static char rtsp_names[MAX_PORTS][10]; + +static void +fini(void) +{ + int i; + for (i = 0; i < num_ports; i++) + { + DEBUGP("unregistering port %d\n", ports[i]); + ip_conntrack_helper_unregister(&rtsp_helpers[i]); + } + for (i = 0; i < MAX_PORT_MAPS; i++) + { + if (!rtsp_data_ports[i].in_use) + { + continue; + } + if (rtsp_data_ports[i].timeout_active == 1) { + del_timer(&rtsp_data_ports[i].pause_timeout); + } + } +} + +static int __init +init(void) +{ + int i, ret; + struct ip_conntrack_helper *hlpr; + char *tmpname; + + printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n"); + + if (max_outstanding < 1) + { + printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n"); + return -EBUSY; + } + if (setup_timeout < 0) + { + printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n"); + return -EBUSY; + } + + /* If no port given, default to standard rtsp port */ + if (ports[0] == 0) + { + ports[0] = RTSP_PORT; + } + + for (i = 0; i < MAX_PORT_MAPS; i++) + { + memset(&rtsp_data_ports[i], 0, sizeof(struct _rtsp_data_ports)); + rtsp_data_ports[i].in_use = 0; + } + + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) + { + hlpr = &rtsp_helpers[i]; + memset(hlpr, 0, sizeof(struct ip_conntrack_helper)); + hlpr->tuple.src.u.tcp.port = htons(ports[i]); + hlpr->tuple.dst.protonum = IPPROTO_TCP; + hlpr->mask.src.u.tcp.port = 0xFFFF; + hlpr->mask.dst.protonum = 0xFFFF; + hlpr->max_expected = max_outstanding; + hlpr->timeout = 0; + hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT; + hlpr->me = ip_conntrack_rtsp; + hlpr->help = help; + + tmpname = &rtsp_names[i][0]; + if (ports[i] == RTSP_PORT) + { + sprintf(tmpname, "rtsp"); + } + else + { + sprintf(tmpname, "rtsp-%d", i); + } + hlpr->name = tmpname; + + DEBUGP("port #%d: %d\n", i, ports[i]); + + ret = ip_conntrack_helper_register(hlpr); + + if (ret) + { + printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]); + fini(); + return -EBUSY; + } + num_ports++; + } + return 0; +} + +PROVIDES_CONNTRACK(rtsp); +EXPORT_SYMBOL(ip_rtsp_lock); + +module_init(init); +module_exit(fini); diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_standalone.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_standalone.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-06-26 17:15:27.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_conntrack_standalone.c 2006-12-20 18:45:29.000000000 +0100 @@ -194,6 +194,10 @@ /* We've seen it coming out the other side: confirm it */ return ip_conntrack_confirm(*pskb); } +#if defined(CONFIG_MIPS_BRCM) +#define IGMP_RIP_ROUTER htonl(0xE0000009L) +#define IGMP_UPNP_ROUTER htonl(0xEFFFFFFAL) +#endif static unsigned int ip_conntrack_defrag(unsigned int hooknum, struct sk_buff **pskb, @@ -206,12 +210,18 @@ if ((*pskb)->nfct) return NF_ACCEPT; - /* Gather fragments. */ - if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { - *pskb = ip_ct_gather_frags(*pskb); + if ( MULTICAST((*pskb)->nh.iph->daddr)) + return NF_ACCEPT; + + + //if ((*pskb)->nh.iph->daddr == IGMP_RIP_ROUTER || (*pskb)->nh.iph->daddr == IGMP_UPNP_ROUTER)) { + /* Gather fragments. */ + if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { + *pskb = ip_ct_gather_frags(*pskb); if (!*pskb) return NF_STOLEN; - } + } + //} return NF_ACCEPT; } diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_nat_gre.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_nat_gre.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_nat_gre.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_nat_gre.c 2006-12-20 18:45:29.000000000 +0100 @@ -0,0 +1,214 @@ +/* + * ip_nat_proto_gre.c - Version 2.0 + * + * NAT protocol helper module for GRE. + * + * GRE is a generic encapsulation protocol, which is generally not very + * suited for NAT, as it has no protocol-specific part as port numbers. + * + * It has an optional key field, which may help us distinguishing two + * connections between the same two hosts. + * + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 + * + * PPTP is built on top of a modified version of GRE, and has a mandatory + * field called "CallID", which serves us for the same purpose as the key + * field in plain GRE. + * + * Documentation about PPTP can be found in RFC 2637 + * + * (C) 2000-2004 by Harald Welte + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + * + */ + +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE"); + +#if 0 +#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \ + __FUNCTION__, ## args) +#else +#define DEBUGP(x, args...) +#endif + +/* is key in given range between min and max */ +static int +gre_in_range(const struct ip_conntrack_tuple *tuple, + enum ip_nat_manip_type maniptype, + const union ip_conntrack_manip_proto *min, + const union ip_conntrack_manip_proto *max) +{ + u_int32_t key; + + if (maniptype == IP_NAT_MANIP_SRC) + key = tuple->src.u.gre.key; + else + key = tuple->dst.u.gre.key; + + return ntohl(key) >= ntohl(min->gre.key) + && ntohl(key) <= ntohl(max->gre.key); +} + +/* generate unique tuple ... */ +static int +gre_unique_tuple(struct ip_conntrack_tuple *tuple, + const struct ip_nat_range *range, + enum ip_nat_manip_type maniptype, + const struct ip_conntrack *conntrack) +{ + u_int32_t min, i, range_size; + u_int32_t key = 0, *keyptr; + + if (maniptype == IP_NAT_MANIP_SRC) + keyptr = &tuple->src.u.gre.key; + else + keyptr = &tuple->dst.u.gre.key; + + if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) { + DEBUGP("%p: NATing GRE PPTP\n", conntrack); + min = 1; + range_size = 0xffff; + } else { + min = ntohl(range->min.gre.key); + range_size = ntohl(range->max.gre.key) - min + 1; + } + + DEBUGP("min = %u, range_size = %u\n", min, range_size); + + for (i = 0; i < range_size; i++, key++) { + *keyptr = htonl(min + key % range_size); + if (!ip_nat_used_tuple(tuple, conntrack)) + return 1; + } + + DEBUGP("%p: no NAT mapping\n", conntrack); + + return 0; +} + +/* manipulate a GRE packet according to maniptype */ +static int +gre_manip_pkt(struct sk_buff **pskb, + unsigned int iphdroff, + const struct ip_conntrack_manip *manip, + enum ip_nat_manip_type maniptype) +{ + struct gre_hdr *greh; + struct gre_hdr_pptp *pgreh; + struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); + unsigned int hdroff = iphdroff + iph->ihl*4; + + /* pgreh includes two optional 32bit fields which are not required + * to be there. That's where the magic '8' comes from */ + if (!skb_ip_make_writable(pskb, hdroff + sizeof(*pgreh)-8)) + return 0; + + greh = (void *)(*pskb)->data + hdroff; + pgreh = (struct gre_hdr_pptp *) greh; + + /* we only have destination manip of a packet, since 'source key' + * is not present in the packet itself */ + if (maniptype == IP_NAT_MANIP_DST) { + /* key manipulation is always dest */ + switch (greh->version) { + case 0: + if (!greh->key) { + DEBUGP("can't nat GRE w/o key\n"); + break; + } + if (greh->csum) { + /* FIXME: Never tested this code... */ + *(gre_csum(greh)) = + ip_nat_cheat_check(~*(gre_key(greh)), + manip->u.gre.key, + *(gre_csum(greh))); + } + *(gre_key(greh)) = manip->u.gre.key; + break; + case GRE_VERSION_PPTP: + DEBUGP("call_id -> 0x%04x\n", + ntohl(manip->u.gre.key)); + pgreh->call_id = htons(ntohl(manip->u.gre.key)); + break; + default: + DEBUGP("can't nat unknown GRE version\n"); + return 0; + break; + } + } + return 1; +} + +/* print out a nat tuple */ +static unsigned int +gre_print(char *buffer, + const struct ip_conntrack_tuple *match, + const struct ip_conntrack_tuple *mask) +{ + unsigned int len = 0; + + if (mask->src.u.gre.key) + len += sprintf(buffer + len, "srckey=0x%x ", + ntohl(match->src.u.gre.key)); + + if (mask->dst.u.gre.key) + len += sprintf(buffer + len, "dstkey=0x%x ", + ntohl(match->src.u.gre.key)); + + return len; +} + +/* print a range of keys */ +static unsigned int +gre_print_range(char *buffer, const struct ip_nat_range *range) +{ + if (range->min.gre.key != 0 + || range->max.gre.key != 0xFFFF) { + if (range->min.gre.key == range->max.gre.key) + return sprintf(buffer, "key 0x%x ", + ntohl(range->min.gre.key)); + else + return sprintf(buffer, "keys 0x%u-0x%u ", + ntohl(range->min.gre.key), + ntohl(range->max.gre.key)); + } else + return 0; +} + +/* nat helper struct */ +static struct ip_nat_protocol gre = { + .name = "GRE", + .protonum = IPPROTO_GRE, + .manip_pkt = gre_manip_pkt, + .in_range = gre_in_range, + .unique_tuple = gre_unique_tuple, + .print = gre_print, + .print_range = gre_print_range +}; + +static int __init init(void) +{ + if (ip_nat_protocol_register(&gre)) + return -EIO; + + return 0; +} + +static void __exit fini(void) +{ + ip_nat_protocol_unregister(&gre); +} + +module_init(init); +module_exit(fini); diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_nat_h323.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_nat_h323.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_nat_h323.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_nat_h323.c 2006-12-20 18:45:29.000000000 +0100 @@ -0,0 +1,431 @@ +/* + * H.323 'brute force' extension for NAT alteration. + * Jozsef Kadlecsik + * (c) 2005 Max Kellermann + * + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project. + * (http://www.coritel.it/projects/sofia/nat.html) + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind' + * the unregistered helpers to the conntrack entries. + */ + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Jozsef Kadlecsik "); +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module"); +MODULE_LICENSE("GPL"); + +DECLARE_LOCK_EXTERN(ip_h323_lock); +struct module *ip_nat_h323 = THIS_MODULE; + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +/* FIXME: Time out? --RR */ + +static unsigned int +h225_nat_expected(struct sk_buff **pskb, + unsigned int hooknum, + struct ip_conntrack *ct, + struct ip_nat_info *info); + +static unsigned int h225_nat_help(struct ip_conntrack *ct, + struct ip_conntrack_expect *exp, + struct ip_nat_info *info, + enum ip_conntrack_info ctinfo, + unsigned int hooknum, + struct sk_buff **pskb); + +static struct ip_nat_helper h245 = { + .list = { NULL, NULL }, + .name = "H.245", + .flags = 0, + .me = THIS_MODULE, + .tuple = { .src = { .ip = 0, + .u = { .tcp = { .port = 0 } } + }, + .dst = { .ip = 0, + .u = { .all = 0 }, + .protonum = IPPROTO_TCP + } + }, + .mask = { .src = { .ip = 0, + .u = { .tcp = { .port = 0xffff } } + }, + .dst = { .ip = 0, + .u = { .all = 0 }, + .protonum = 0xffff + } + }, + .help = h225_nat_help, + .expect = h225_nat_expected +}; + +static unsigned int +h225_nat_expected(struct sk_buff **pskb, + unsigned int hooknum, + struct ip_conntrack *ct, + struct ip_nat_info *info) +{ + struct ip_nat_multi_range mr; + u_int32_t newdstip, newsrcip, newip; + u_int16_t port; + struct ip_ct_h225_expect *exp_info; + struct ip_ct_h225_master *master_info; + struct ip_conntrack *master = master_ct(ct); + unsigned int is_h225, ret; + + IP_NF_ASSERT(info); + IP_NF_ASSERT(master); + + IP_NF_ASSERT(!(info->initialized & (1<master->expectant->help.ct_h225_info; + exp_info = &ct->master->help.exp_h225_info; + + LOCK_BH(&ip_h323_lock); + + DEBUGP("master: "); + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple); + DEBUGP("conntrack: "); + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + if (exp_info->dir == IP_CT_DIR_ORIGINAL) { + /* Make connection go to the client. */ + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n", + NIPQUAD(newsrcip), NIPQUAD(newdstip)); + } else { + /* Make the connection go to the server */ + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip; + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n", + NIPQUAD(newsrcip), NIPQUAD(newdstip)); + } + port = exp_info->port; + is_h225 = master_info->is_h225 == H225_PORT; + UNLOCK_BH(&ip_h323_lock); + + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) + newip = newsrcip; + else + newip = newdstip; + + DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip)); + + /* We don't want to manip the per-protocol, just the IPs... */ + mr.rangesize = 1; + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS; + mr.range[0].min_ip = mr.range[0].max_ip = newip; + + /* ... unless we're doing a MANIP_DST, in which case, make + sure we map to the correct port */ + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) { + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED; + mr.range[0].min = mr.range[0].max + = ((union ip_conntrack_manip_proto) + { .tcp = { port } }); + } + + ret = ip_nat_setup_info(ct, &mr, hooknum); + + if (is_h225) { + DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct); + /* NAT expectfn called with ip_nat_lock write-locked */ + info->helper = &h245; + } + return ret; +} + +static int h323_signal_address_fixup(struct ip_conntrack *ct, + struct sk_buff **pskb, + enum ip_conntrack_info ctinfo) +{ + struct iphdr *iph = (*pskb)->nh.iph; + struct tcphdr _tcph, *tcph; + u_int32_t tcplen, datalen; + struct ip_ct_h225_master *info = &ct->help.ct_h225_info; + struct { + u_int32_t ip; + u_int16_t port; + } __attribute__ ((__packed__)) newdata; + int i; + int ret; + + tcph = skb_header_pointer(*pskb, iph->ihl * 4, sizeof(_tcph), &_tcph); + if (tcph == NULL) + return NF_ACCEPT; + + tcplen = (*pskb)->len - iph->ihl * 4; + datalen = tcplen - tcph->doff * 4; + + MUST_BE_LOCKED(&ip_h323_lock); + + DEBUGP("h323_signal_address_fixup: %s %s\n", + between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen) + ? "yes" : "no", + between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen) + ? "yes" : "no"); + if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen) + || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen))) + return 1; + + DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n", + info->offset[IP_CT_DIR_ORIGINAL], + info->offset[IP_CT_DIR_REPLY], + tcplen); + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); + + for (i = 0; i < IP_CT_DIR_MAX; i++) { + DEBUGP("h323_signal_address_fixup: %s %s\n", + info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply", + i == IP_CT_DIR_ORIGINAL ? "caller" : "callee"); + if (!between(info->seq[i], ntohl(tcph->seq), + ntohl(tcph->seq) + datalen)) + continue; + if (!between(info->seq[i] + 6, ntohl(tcph->seq), + ntohl(tcph->seq) + datalen)) { + /* Partial retransmisison. It's a cracker being funky. */ + if (net_ratelimit()) { + printk("H.323_NAT: partial packet %u/6 in %u/%u\n", + info->seq[i], + ntohl(tcph->seq), + ntohl(tcph->seq) + datalen); + } + return 0; + } + + /* Change address inside packet to match way we're mapping + this connection. */ + if (i == IP_CT_DIR_ORIGINAL) { + newdata.ip = ct->tuplehash[!info->dir].tuple.dst.ip; + newdata.port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port; + } else { + newdata.ip = ct->tuplehash[!info->dir].tuple.src.ip; + newdata.port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port; + } + + /* Modify the packet */ + ret = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, + info->seq[i] - ntohl(tcph->seq), + sizeof(newdata), + (const char*)&newdata, sizeof(newdata)); + if (!ret) + return 0; + } + + return 1; +} + +static int h323_data_fixup(struct ip_ct_h225_expect *info, + struct ip_conntrack *ct, + struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct ip_conntrack_expect *expect) +{ + struct { + u_int32_t ip; + u_int16_t port; + } __attribute__ ((__packed__)) newdata; + struct ip_conntrack_tuple newtuple; + struct iphdr *iph = (*pskb)->nh.iph; + struct tcphdr _tcph, *tcph; + u_int32_t tcplen; + struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info; + int is_h225; + int ret; + + tcph = skb_header_pointer(*pskb, iph->ihl * 4, sizeof(_tcph), &_tcph); + if (tcph == NULL) + return NF_ACCEPT; + + tcplen = (*pskb)->len - iph->ihl * 4; + + MUST_BE_LOCKED(&ip_h323_lock); + DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen); + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); + + if (!between(expect->seq + 6, ntohl(tcph->seq), + ntohl(tcph->seq) + tcplen - tcph->doff * 4)) { + /* Partial retransmisison. It's a cracker being funky. */ + if (net_ratelimit()) { + printk("H.323_NAT: partial packet %u/6 in %u/%u\n", + expect->seq, + ntohl(tcph->seq), + ntohl(tcph->seq) + tcplen - tcph->doff * 4); + } + return 0; + } + + /* Change address inside packet to match way we're mapping + this connection. */ + if (info->dir == IP_CT_DIR_REPLY) { + /* Must be where client thinks server is */ + newdata.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; + /* Expect something from client->server */ + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; + } else { + /* Must be where server thinks client is */ + newdata.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; + /* Expect something from server->client */ + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip; + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; + } + + is_h225 = (master_info->is_h225 == H225_PORT); + + if (is_h225) { + newtuple.dst.protonum = IPPROTO_TCP; + newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port; + } else { + newtuple.dst.protonum = IPPROTO_UDP; + newtuple.src.u.udp.port = expect->tuple.src.u.udp.port; + } + + /* Try to get same port: if not, try to change it. */ + for (newdata.port = ntohs(info->port); newdata.port != 0; newdata.port++) { + if (is_h225) + newtuple.dst.u.tcp.port = htons(newdata.port); + else + newtuple.dst.u.udp.port = htons(newdata.port); + + if (ip_conntrack_change_expect(expect, &newtuple) == 0) + break; + } + if (newdata.port == 0) { + DEBUGP("h323_data_fixup: no free port found!\n"); + return 0; + } + + newdata.port = htons(newdata.port); + + /* Modify the packet */ + ret = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, + expect->seq - ntohl(tcph->seq), + sizeof(newdata), + (const char*)&newdata, sizeof(newdata)); + if (!ret) + return 0; + + return 1; +} + +static unsigned int h225_nat_help(struct ip_conntrack *ct, + struct ip_conntrack_expect *exp, + struct ip_nat_info *info, + enum ip_conntrack_info ctinfo, + unsigned int hooknum, + struct sk_buff **pskb) +{ + int dir; + struct ip_ct_h225_expect *exp_info; + + /* Only mangle things once: original direction in POST_ROUTING + and reply direction on PRE_ROUTING. */ + dir = CTINFO2DIR(ctinfo); + DEBUGP("nat_h323: dir %s at hook %s\n", + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY", + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING" + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING" + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"); + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL) + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) { + DEBUGP("nat_h323: Not touching dir %s at hook %s\n", + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY", + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING" + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING" + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"); + return NF_ACCEPT; + } + + if (!exp) { + LOCK_BH(&ip_h323_lock); + if (!h323_signal_address_fixup(ct, pskb, ctinfo)) { + UNLOCK_BH(&ip_h323_lock); + return NF_DROP; + } + UNLOCK_BH(&ip_h323_lock); + return NF_ACCEPT; + } + + exp_info = &exp->help.exp_h225_info; + + LOCK_BH(&ip_h323_lock); + if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) { + UNLOCK_BH(&ip_h323_lock); + return NF_DROP; + } + UNLOCK_BH(&ip_h323_lock); + + return NF_ACCEPT; +} + +static struct ip_nat_helper h225 = { + .list = { NULL, NULL }, + .name = "H.225", + .flags = IP_NAT_HELPER_F_ALWAYS, + .me = THIS_MODULE, + .tuple = { .src = { .ip = 0, + .u = { .tcp = { .port = + __constant_htons(H225_PORT) } } + }, + .dst = { .ip = 0, + .u = { .all = 0 }, + .protonum = IPPROTO_TCP + } + }, + .mask = { .src = { .ip = 0, + .u = { .tcp = { .port = 0xffff } } + }, + .dst = { .ip = 0, + .u = { .all = 0 }, + .protonum = 0xffff + } + }, + .help = h225_nat_help, + .expect = h225_nat_expected +}; + +static int __init init(void) +{ + int ret; + + printk("ip_nat_h323: initialize the module!\n"); + ret = ip_nat_helper_register(&h225); + + if (ret != 0) + printk("ip_nat_h323: cannot initialize the module!\n"); + + return ret; +} + +static void __exit fini(void) +{ + ip_nat_helper_unregister(&h225); +} + +NEEDS_CONNTRACK(h225); +NEEDS_CONNTRACK(h245); +module_init(init); +module_exit(fini); diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_nat_pptp.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_nat_pptp.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_nat_pptp.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_nat_pptp.c 2006-12-20 18:45:29.000000000 +0100 @@ -0,0 +1,481 @@ +/* + * ip_nat_pptp.c - Version 2.0 + * + * NAT support for PPTP (Point to Point Tunneling Protocol). + * PPTP is a a protocol for creating virtual private networks. + * It is a specification defined by Microsoft and some vendors + * working with Microsoft. PPTP is built on top of a modified + * version of the Internet Generic Routing Encapsulation Protocol. + * GRE is defined in RFC 1701 and RFC 1702. Documentation of + * PPTP can be found in RFC 2637 + * + * (C) 2000-2004 by Harald Welte + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + * + * TODO: - Support for multiple calls within one session + * (needs netfilter newnat code) + * - NAT to a unique tuple, not to TCP source port + * (needs netfilter tuple reservation) + * + * Changes: + * 2002-02-10 - Version 1.3 + * - Use ip_nat_mangle_tcp_packet() because of cloned skb's + * in local connections (Philip Craig ) + * - add checks for magicCookie and pptp version + * - make argument list of pptp_{out,in}bound_packet() shorter + * - move to C99 style initializers + * - print version number at module loadtime + * 2003-09-22 - Version 1.5 + * - use SNATed tcp sourceport as callid, since we get called before + * TCP header is mangled (Philip Craig ) + * 2004-10-22 - Version 2.0 + * - kernel 2.6.x version + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IP_NAT_PPTP_VERSION "2.0" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP"); + + +#if 0 +#include "ip_conntrack_pptp_priv.h" +#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \ + __FUNCTION__, ## args) +#else +#define DEBUGP(format, args...) +#endif + +static unsigned int +pptp_nat_expected(struct sk_buff **pskb, + unsigned int hooknum, + struct ip_conntrack *ct, + struct ip_nat_info *info) +{ + struct ip_conntrack *master = master_ct(ct); + struct ip_nat_multi_range mr; + struct ip_ct_pptp_master *ct_pptp_info; + struct ip_nat_pptp *nat_pptp_info; + u_int32_t newip, newcid; + int ret; + + IP_NF_ASSERT(info); + IP_NF_ASSERT(master); + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum)))); + + DEBUGP("we have a connection!\n"); + + LOCK_BH(&ip_pptp_lock); + ct_pptp_info = &master->help.ct_pptp_info; + nat_pptp_info = &master->nat.help.nat_pptp_info; + + /* need to alter GRE tuple because conntrack expectfn() used 'wrong' + * (unmanipulated) values */ + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) { + DEBUGP("completing tuples with NAT info \n"); + /* we can do this, since we're unconfirmed */ + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key == + htonl(ct_pptp_info->pac_call_id)) { + /* assume PNS->PAC */ + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = + htonl(nat_pptp_info->pns_call_id); + ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key = + htonl(nat_pptp_info->pns_call_id); + newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip; + newcid = htonl(nat_pptp_info->pac_call_id); + } else { + /* assume PAC->PNS */ + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = + htonl(nat_pptp_info->pac_call_id); + ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key = + htonl(nat_pptp_info->pac_call_id); + newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; + newcid = htonl(nat_pptp_info->pns_call_id); + } + } else { + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key == + htonl(ct_pptp_info->pac_call_id)) { + /* assume PNS->PAC */ + newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; + newcid = htonl(ct_pptp_info->pns_call_id); + } + else { + /* assume PAC->PNS */ + newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; + newcid = htonl(ct_pptp_info->pac_call_id); + } + } + + mr.rangesize = 1; + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED; + mr.range[0].min_ip = mr.range[0].max_ip = newip; + mr.range[0].min = mr.range[0].max = + ((union ip_conntrack_manip_proto ) { newcid }); + DEBUGP("change ip to %u.%u.%u.%u\n", + NIPQUAD(newip)); + DEBUGP("change key to 0x%x\n", ntohl(newcid)); + ret = ip_nat_setup_info(ct, &mr, hooknum); + + UNLOCK_BH(&ip_pptp_lock); + + return ret; + +} + +/* outbound packets == from PNS to PAC */ +static inline unsigned int +pptp_outbound_pkt(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + struct ip_conntrack_expect *exp) + +{ + struct iphdr *iph = (*pskb)->nh.iph; + struct tcphdr *tcph = (void *) iph + iph->ihl*4; + struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *) + ((void *)tcph + tcph->doff*4); + + struct PptpControlHeader *ctlh; + union pptp_ctrl_union *pptpReq; + struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info; + struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info; + + u_int16_t msg, *cid = NULL, new_callid; + + /* FIXME: size checks !!! */ + ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph)); + pptpReq = (void *) ((void *) ctlh + sizeof(*ctlh)); + + new_callid = htons(ct_pptp_info->pns_call_id); + + switch (msg = ntohs(ctlh->messageType)) { + case PPTP_OUT_CALL_REQUEST: + cid = &pptpReq->ocreq.callID; + /* FIXME: ideally we would want to reserve a call ID + * here. current netfilter NAT core is not able to do + * this :( For now we use TCP source port. This breaks + * multiple calls within one control session */ + + /* save original call ID in nat_info */ + nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id; + + /* don't use tcph->source since we are at a DSTmanip + * hook (e.g. PREROUTING) and pkt is not mangled yet */ + new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port; + + /* save new call ID in ct info */ + ct_pptp_info->pns_call_id = ntohs(new_callid); + break; + case PPTP_IN_CALL_REPLY: + cid = &pptpReq->icreq.callID; + break; + case PPTP_CALL_CLEAR_REQUEST: + cid = &pptpReq->clrreq.callID; + break; + default: + DEBUGP("unknown outbound packet 0x%04x:%s\n", msg, + (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]); + /* fall through */ + + case PPTP_SET_LINK_INFO: + /* only need to NAT in case PAC is behind NAT box */ + case PPTP_START_SESSION_REQUEST: + case PPTP_START_SESSION_REPLY: + case PPTP_STOP_SESSION_REQUEST: + case PPTP_STOP_SESSION_REPLY: + case PPTP_ECHO_REQUEST: + case PPTP_ECHO_REPLY: + /* no need to alter packet */ + return NF_ACCEPT; + } + + IP_NF_ASSERT(cid); + + DEBUGP("altering call id from 0x%04x to 0x%04x\n", + ntohs(*cid), ntohs(new_callid)); + + /* mangle packet */ + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)cid - (void *)pptph, + sizeof(new_callid), (char *)&new_callid, + sizeof(new_callid)); + + return NF_ACCEPT; +} + +/* inbound packets == from PAC to PNS */ +static inline unsigned int +pptp_inbound_pkt(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + struct ip_conntrack_expect *oldexp) +{ + struct iphdr *iph = (*pskb)->nh.iph; + struct tcphdr *tcph = (void *) iph + iph->ihl*4; + struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *) + ((void *)tcph + tcph->doff*4); + + struct PptpControlHeader *ctlh; + union pptp_ctrl_union *pptpReq; + struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info; + struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info; + + u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL; + u_int32_t old_dst_ip; + + struct ip_conntrack_tuple t, inv_t; + struct ip_conntrack_tuple *orig_t, *reply_t; + + /* FIXME: size checks !!! */ + ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph)); + pptpReq = (void *) ((void *) ctlh + sizeof(*ctlh)); + + new_pcid = htons(nat_pptp_info->pns_call_id); + + switch (msg = ntohs(ctlh->messageType)) { + case PPTP_OUT_CALL_REPLY: + pcid = &pptpReq->ocack.peersCallID; + cid = &pptpReq->ocack.callID; + if (!oldexp) { + DEBUGP("outcall but no expectation\n"); + break; + } + old_dst_ip = oldexp->tuple.dst.ip; + t = oldexp->tuple; + invert_tuplepr(&inv_t, &t); + + /* save original PAC call ID in nat_info */ + nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id; + + /* alter expectation */ + orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; + if (t.src.ip == orig_t->src.ip && t.dst.ip == orig_t->dst.ip) { + /* expectation for PNS->PAC direction */ + t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id); + t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id); + inv_t.src.ip = reply_t->src.ip; + inv_t.dst.ip = reply_t->dst.ip; + inv_t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id); + inv_t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id); + } else { + /* expectation for PAC->PNS direction */ + t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id); + t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id); + inv_t.src.ip = orig_t->src.ip; + inv_t.dst.ip = orig_t->dst.ip; + inv_t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id); + inv_t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id); + } + + if (!ip_conntrack_change_expect(oldexp, &t)) { + DEBUGP("successfully changed expect\n"); + } else { + DEBUGP("can't change expect\n"); + } + if (oldexp->proto.gre.keymap_orig) + ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_orig, + &t); + if (oldexp->proto.gre.keymap_reply) + ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_reply, + &inv_t); + break; + case PPTP_IN_CALL_CONNECT: + pcid = &pptpReq->iccon.peersCallID; + if (!oldexp) + break; + old_dst_ip = oldexp->tuple.dst.ip; + t = oldexp->tuple; + + /* alter expectation, no need for callID */ + if (t.dst.ip == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip) { + /* expectation for PNS->PAC direction */ + t.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; + } else { + /* expectation for PAC->PNS direction */ + t.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; + } + + if (!ip_conntrack_change_expect(oldexp, &t)) { + DEBUGP("successfully changed expect\n"); + } else { + DEBUGP("can't change expect\n"); + } + break; + case PPTP_IN_CALL_REQUEST: + /* only need to nat in case PAC is behind NAT box */ + break; + case PPTP_WAN_ERROR_NOTIFY: + pcid = &pptpReq->wanerr.peersCallID; + break; + case PPTP_CALL_DISCONNECT_NOTIFY: + pcid = &pptpReq->disc.callID; + break; + + default: + DEBUGP("unknown inbound packet %s\n", + (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]); + /* fall through */ + + case PPTP_START_SESSION_REQUEST: + case PPTP_START_SESSION_REPLY: + case PPTP_STOP_SESSION_REQUEST: + case PPTP_STOP_SESSION_REPLY: + case PPTP_ECHO_REQUEST: + case PPTP_ECHO_REPLY: + /* no need to alter packet */ + return NF_ACCEPT; + } + + /* mangle packet */ + IP_NF_ASSERT(pcid); + DEBUGP("altering peer call id from 0x%04x to 0x%04x\n", + ntohs(*pcid), ntohs(new_pcid)); + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)pcid - (void *)pptph, + sizeof(new_pcid), (char *)&new_pcid, + sizeof(new_pcid)); + + if (new_cid) { + IP_NF_ASSERT(cid); + DEBUGP("altering call id from 0x%04x to 0x%04x\n", + ntohs(*cid), ntohs(new_cid)); + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, + (void *)cid - (void *)pptph, + sizeof(new_cid), (char *)&new_cid, + sizeof(new_cid)); + } + + /* great, at least we don't need to resize packets */ + return NF_ACCEPT; +} + + +static unsigned int tcp_help(struct ip_conntrack *ct, + struct ip_conntrack_expect *exp, + struct ip_nat_info *info, + enum ip_conntrack_info ctinfo, + unsigned int hooknum, struct sk_buff **pskb) +{ + struct iphdr *iph = (*pskb)->nh.iph; + struct tcphdr *tcph = (void *) iph + iph->ihl*4; + unsigned int datalen = (*pskb)->len - iph->ihl*4 - tcph->doff*4; + struct pptp_pkt_hdr *pptph; + + int dir; + + DEBUGP("entering\n"); + + /* Only mangle things once: DST for original direction + and SRC for reply direction. */ + dir = CTINFO2DIR(ctinfo); + if (!((HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC + && dir == IP_CT_DIR_ORIGINAL) + || (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST + && dir == IP_CT_DIR_REPLY))) { + DEBUGP("Not touching dir %s at hook %s\n", + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY", + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING" + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING" + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" + : hooknum == NF_IP_LOCAL_IN ? "INPUT" : "???"); + return NF_ACCEPT; + } + + /* if packet is too small, just skip it */ + if (datalen < sizeof(struct pptp_pkt_hdr)+ + sizeof(struct PptpControlHeader)) { + DEBUGP("pptp packet too short\n"); + return NF_ACCEPT; + } + + pptph = (struct pptp_pkt_hdr *) ((void *)tcph + tcph->doff*4); + + /* if it's not a control message, we can't handle it */ + if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL || + ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) { + DEBUGP("not a pptp control packet\n"); + return NF_ACCEPT; + } + + LOCK_BH(&ip_pptp_lock); + + if (dir == IP_CT_DIR_ORIGINAL) { + /* reuqests sent by client to server (PNS->PAC) */ + pptp_outbound_pkt(pskb, ct, ctinfo, exp); + } else { + /* response from the server to the client (PAC->PNS) */ + pptp_inbound_pkt(pskb, ct, ctinfo, exp); + } + + UNLOCK_BH(&ip_pptp_lock); + + return NF_ACCEPT; +} + +/* nat helper struct for control connection */ +static struct ip_nat_helper pptp_tcp_helper = { + .list = { NULL, NULL }, + .name = "pptp", + .flags = IP_NAT_HELPER_F_ALWAYS, + .me = THIS_MODULE, + .tuple = { .src = { .ip = 0, + .u = { .tcp = { .port = + __constant_htons(PPTP_CONTROL_PORT) } + } + }, + .dst = { .ip = 0, + .u = { .all = 0 }, + .protonum = IPPROTO_TCP + } + }, + + .mask = { .src = { .ip = 0, + .u = { .tcp = { .port = 0xFFFF } } + }, + .dst = { .ip = 0, + .u = { .all = 0 }, + .protonum = 0xFFFF + } + }, + .help = tcp_help, + .expect = pptp_nat_expected +}; + + +static int __init init(void) +{ + DEBUGP("%s: registering NAT helper\n", __FILE__); + if (ip_nat_helper_register(&pptp_tcp_helper)) { + printk(KERN_ERR "Unable to register NAT application helper " + "for pptp\n"); + return -EIO; + } + + printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION); + return 0; +} + +static void __exit fini(void) +{ + DEBUGP("cleanup_module\n" ); + ip_nat_helper_unregister(&pptp_tcp_helper); + printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION); +} + +module_init(init); +module_exit(fini); diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_nat_proto_esp.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_nat_proto_esp.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_nat_proto_esp.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_nat_proto_esp.c 2006-12-20 18:45:29.000000000 +0100 @@ -0,0 +1,154 @@ +/* +<:copyright-gpl + Copyright 2002 Broadcom Corp. All Rights Reserved. + + This program is free software; you can distribute it and/or modify it + under the terms of the GNU General Public License (Version 2) as + published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +:> +*/ +/****************************************************************************** +// +// Filename: ip_nat_proto_esp.c +// Author: Pavan Kumar +// Creation Date: 05/27/04 +// +// Description: +// Implements the ESP ALG connectiontracking. +// +*****************************************************************************/ +#include +#include +#include +#include +#include + +#include +#include +#include + +#define TEMP_SPI_START 1500 + +static int +esp_in_range(const struct ip_conntrack_tuple *tuple, + enum ip_nat_manip_type maniptype, + const union ip_conntrack_manip_proto *min, + const union ip_conntrack_manip_proto *max) +{ + //printk ( KERN_DEBUG "%s:%s spi %hu dpi %hu sip %u.%u.%u.%u dip %u.%u.%u.%u\n", + // __FILE__, __FUNCTION__, ntohs(tuple->src.u.esp.spi), + // ntohs(tuple->dst.u.esp.spi), NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip) ); + return 1; +} + +static int +esp_unique_tuple(struct ip_conntrack_tuple *tuple, + const struct ip_nat_range *range, + enum ip_nat_manip_type maniptype, + const struct ip_conntrack *conntrack) +{ + static u_int16_t id = 0, *tspi; + unsigned int range_size = 0x40; + unsigned int i; + + //printk ( KERN_DEBUG "%s:%s manitype %d sip %u.%u.%u.%u dip %u.%u.%u.%u" + // " sspi %u dspi %u\n", __FILE__, __FUNCTION__, maniptype, + // NIPQUAD(tuple->src.ip), + // NIPQUAD(tuple->dst.ip), tuple->src.u.esp.spi, tuple->dst.u.esp.spi ); + /* If no range specified... */ + if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) + range_size = 0x40; + + if ( maniptype == IP_NAT_MANIP_SRC ) { + tspi = &tuple->src.u.esp.spi; + } else { + tspi = &tuple->dst.u.esp.spi; + } + + for (i = 0; i < range_size; i++, id++) { + *tspi = TEMP_SPI_START + (id % range_size); + if (!ip_nat_used_tuple(tuple, conntrack)) + return 1; + } + + return 0; +} + +static int +esp_manip_pkt(struct sk_buff **pskb, + unsigned int hdroff, + const struct ip_conntrack_manip *manip, + enum ip_nat_manip_type maniptype) +{ + u_int32_t oldip; + //struct esphdr *hdr = (void *)(*pskb)->data + hdroff; + + if (maniptype == IP_NAT_MANIP_SRC) { + /* Get rid of src ip and src pt */ + oldip = (*pskb)->nh.iph->saddr; + //printk ( KERN_DEBUG "%s:%s MANIP_SRC oldip %u.%u.%u.%u daddr" + // " %u.%u.%u.%u manip %u.%u.%u.%u spi 0x%x seq 0x%x\n", + // __FILE__, __FUNCTION__, NIPQUAD(oldip), NIPQUAD(iph->daddr), + // NIPQUAD(manip->ip), ntohl(hdr->spi), + // ntohl(hdr->seq) ); + } else { + /* Get rid of dst ip and dst pt */ + oldip = (*pskb)->nh.iph->daddr; + //printk ( KERN_DEBUG "%s:%s MANIP_DST oldip %u.%u.%u.%u saddr" + // " %u.%u.%u.%u manip %u.%u.%u.%u spi 0x%x seq 0x%x\n", + // __FILE__, __FUNCTION__, NIPQUAD(oldip), NIPQUAD(iph->saddr), + // NIPQUAD(manip->ip), ntohl(hdr->spi), + // ntohl(hdr->seq) ); + } + return 1; +} + +static unsigned int +esp_print(char *buffer, + const struct ip_conntrack_tuple *match, + const struct ip_conntrack_tuple *mask) +{ + unsigned int len = 0; + + //printk ( KERN_DEBUG "%s:%s mask spi %u dpi %u\n", + // __FILE__, __FUNCTION__, mask->src.u.esp.spi, mask->dst.u.esp.spi ); + if (mask->src.u.esp.spi) + len += sprintf(buffer + len, "spi=%u ", + ntohs(match->src.u.esp.spi)); + + return len; +} + +static unsigned int +esp_print_range(char *buffer, const struct ip_nat_range *range) +{ + //printk ( KERN_DEBUG "%s:%s min %u max %u\n", __FILE__, __FUNCTION__, + // ntohs(range->min.esp.spi), ntohs(range->max.esp.spi) ); + if (range->min.esp.spi != 0 ) { + return sprintf(buffer, "port %u ", + ntohs(range->min.esp.spi)); + } else if ( range->max.esp.spi != 0 ) { + return sprintf(buffer, "ports %u-%u ", + ntohs(range->min.esp.spi), + ntohs(range->max.esp.spi)); + } + else return 0; +} + +struct ip_nat_protocol ip_nat_protocol_esp += { { NULL, NULL }, "ESP", IPPROTO_ESP, + esp_manip_pkt, + esp_in_range, + esp_unique_tuple, + esp_print, + esp_print_range +}; diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_nat_rtsp.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_nat_rtsp.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_nat_rtsp.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_nat_rtsp.c 2006-12-20 18:45:29.000000000 +0100 @@ -0,0 +1,660 @@ +/* + * RTSP extension for TCP NAT alteration + * (C) 2003 by Tom Marshall + * based on ip_nat_irc.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Module load syntax: + * insmod ip_nat_rtsp.o ports=port1,port2,...port + * stunaddr=
+ * destaction=[auto|strip|none] + * + * If no ports are specified, the default will be port 554 only. + * + * stunaddr specifies the address used to detect that a client is using STUN. + * If this address is seen in the destination parameter, it is assumed that + * the client has already punched a UDP hole in the firewall, so we don't + * mangle the client_port. If none is specified, it is autodetected. It + * only needs to be set if you have multiple levels of NAT. It should be + * set to the external address that the STUN clients detect. Note that in + * this case, it will not be possible for clients to use UDP with servers + * between the NATs. + * + * If no destaction is specified, auto is used. + * destaction=auto: strip destination parameter if it is not stunaddr. + * destaction=strip: always strip destination parameter (not recommended). + * destaction=none: do not touch destination parameter (not recommended). + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#define NF_NEED_STRNCASECMP +#define NF_NEED_STRTOU16 +#include +#define NF_NEED_MIME_NEXTLINE +#include + +/* + * To enable debugging, replace the line below with #define IP_NF_RTSP_DEBUG 1 + */ +#undef IP_NF_RTSP_DEBUG +#define INFOP(args...) printk(args) +#ifdef IP_NF_RTSP_DEBUG +#define DUMP_TUPLE(args...) +#define DEBUGP(args...) printk(KERN_DEBUG "%s:%s ", __FILE__, __FUNCTION__); \ + printk(args) +#else +#define DEBUGP(args...) +#endif + +#define MAX_PORTS 8 +#define DSTACT_AUTO 0 +#define DSTACT_STRIP 1 +#define DSTACT_NONE 2 +#define MAX_NAT_PORTS 16 + +static int ports[MAX_PORTS]; +static char* stunaddr = NULL; +static char* destaction = NULL; + +static int num_ports = 0; +static u_int32_t extip = 0; +static int dstact = 0; + +MODULE_AUTHOR("Tom Marshall "); +MODULE_DESCRIPTION("RTSP network address translation module"); +MODULE_LICENSE("GPL"); +#ifdef MODULE_PARM +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i"); +MODULE_PARM_DESC(ports, "port numbers of RTSP servers"); +MODULE_PARM(stunaddr, "s"); +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN"); +MODULE_PARM(destaction, "s"); +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)"); +#endif + +/* protects rtsp part of conntracks */ +DECLARE_LOCK_EXTERN(ip_rtsp_lock); + +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } + +/*** helper functions ***/ + +static void * +rtsp_nat_find_char(void *str, int ch, size_t len) +{ + unsigned char *pStr = NULL; + if (len != 0) { + pStr = str; + } + do { + if (*pStr++ == ch) { + return ((void *)(pStr - 1)); + } + } while (--len != 0); + return (NULL); +} + +static void +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen) +{ + struct iphdr* iph = (struct iphdr*)skb->nh.iph; + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl*4); + + *pptcpdata = (char*)tcph + tcph->doff*4; + *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata; +} + +/*** nat functions ***/ + +/* + * Mangle the "Transport:" header: + * - Replace all occurences of "client_port=" + * - Handle destination parameter + * + * In: + * ct, ctinfo = conntrack context + * pskb = packet + * tranoff = Transport header offset from TCP data + * tranlen = Transport header length (incl. CRLF) + * rport_lo = replacement low port (host endian) + * rport_hi = replacement high port (host endian) + * + * Returns packet size difference. + * + * Assumes that a complete transport header is present, ending with CR or LF + */ +static int +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo, + struct ip_conntrack_expect* exp, + struct sk_buff** pskb, uint tranoff, uint tranlen) +{ + char* ptcp; + uint tcplen; + char* ptran; + char rbuf1[16]; /* Replacement buffer (one port) */ + uint rbuf1len; /* Replacement len (one port) */ + char rbufa[16]; /* Replacement buffer (all ports) */ + uint rbufalen; /* Replacement len (all ports) */ + u_int32_t newip; + u_int16_t loport, hiport; + uint off = 0; + uint diff; /* Number of bytes we removed */ + + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info; + struct ip_conntrack_tuple t; + + char szextaddr[15+1]; + uint extaddrlen; + int is_stun; + + get_skb_tcpdata(*pskb, &ptcp, &tcplen); + ptran = ptcp+tranoff; + + if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen || + tranlen < 10 || !iseol(ptran[tranlen-1]) || + nf_strncasecmp(ptran, "Transport:", 10) != 0) + { + INFOP("sanity check failed\n"); + return 0; + } + off += 10; + SKIP_WSPACE(ptcp+tranoff, tranlen, off); + + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; + t = exp->tuple; + t.dst.ip = newip; + + extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip)) + : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip)); + DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto")); + DEBUGP("Found Transport message %s\n", ptran); + + rbuf1len = rbufalen = 0; + switch (prtspexp->pbtype) + { + case pb_single: + loport = prtspexp->loport; + DEBUGP("PB_SINGLE: LO_PORT %hu\n", loport); + if (loport != 0) + { + rbuf1len = sprintf(rbuf1, "%hu", loport); + rbufalen = sprintf(rbufa, "%hu", loport); + } + break; + case pb_range: + loport = prtspexp->loport; + DEBUGP("PB_RANGE: LO_PORT %hu\n", loport); + if (loport != 0) + { + rbuf1len = sprintf(rbuf1, "%hu", loport); + rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1); + DEBUGP("MANGLING to ports (%hu-%hu) rbuf1 %s rbufa %s\n", prtspexp->loport, prtspexp->loport+1, + rbuf1, rbufa); + } + break; + case pb_discon: + DEBUGP("PB_DISCON:n"); + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */ + { + DEBUGP("Original UDP PORT value is %hu exp loport %hu hiport %hu\n", t.dst.u.udp.port, + prtspexp->loport, prtspexp->hiport); + // Do not transpose the ports yet. If you do, you better register a helper + // to mangle them correctly when you receive packets on those ports. + //t.dst.u.udp.port = htons(loport); + if (ip_conntrack_change_expect(exp, &t) == 0) + { + DEBUGP("using port %hu (1 of 2)\n", loport); + break; + } + } + for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */ + { + t.dst.u.udp.port = htons(hiport); + if (ip_conntrack_change_expect(exp, &t) == 0) + { + DEBUGP("using port %hu (2 of 2)\n", hiport); + break; + } + } + if (loport != 0 && hiport != 0) + { + rbuf1len = sprintf(rbuf1, "%hu", loport); + if (hiport == loport+1) + { + rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport); + DEBUGP("Ports %hu-%hu\n", loport, hiport); + } + else + { + rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport); + DEBUGP("ports %hu-%hu\n", loport, hiport); + } + } + break; + default: + /* oops */ + break; + } + + if (rbuf1len == 0) + { + DEBUGP("Cannot get replacement ports\n"); + return 0; /* cannot get replacement port(s) */ + } + + /* Transport: tran;field;field=val,tran;field;field=val,... */ + while (off < tranlen) + { + uint saveoff; + const char* pparamend; + uint nextparamoff; + + pparamend = rtsp_nat_find_char(ptran+off, ',', tranlen-off); + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; + nextparamoff = pparamend-ptcp; + + /* + * We pass over each param twice. On the first pass, we look for a + * destination= field. It is handled by the security policy. If it + * is present, allowed, and equal to our external address, we assume + * that STUN is being used and we leave the client_port= field alone. + */ + is_stun = 0; + saveoff = off; + while (off < nextparamoff) + { + const char* pfieldend; + uint nextfieldoff; + + pfieldend = rtsp_nat_find_char(ptran+off, ';', nextparamoff-off); + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; + + if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0) + { + if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0) + { + is_stun = 1; + } + if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun)) + { + diff = nextfieldoff-off; + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, + off, diff, NULL, 0)) + { + /* mangle failed, all we can do is bail */ + DEBUGP("mangle failed bailing out now\n"); + return 0; + } + get_skb_tcpdata(*pskb, &ptcp, &tcplen); + ptran = ptcp+tranoff; + tranlen -= diff; + nextparamoff -= diff; + nextfieldoff -= diff; + } + } + + off = nextfieldoff; + } + if (is_stun) + { + continue; + } + off = saveoff; + while (off < nextparamoff) + { + const char* pfieldend; + uint nextfieldoff; + + pfieldend = rtsp_nat_find_char(ptran+off, ';', nextparamoff-off); + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; + + DEBUGP("off %d nextparamoff %d %s\n", off, nextparamoff, ptran+off); + if (strncmp(ptran+off, "client_port=", 12) == 0) + { + u_int16_t port; + uint numlen; + uint origoff; + uint origlen; + char* rbuf = rbuf1; + uint rbuflen = rbuf1len; + + off += 12; + origoff = (ptran-ptcp)+off; + origlen = 0; + numlen = nf_strtou16(ptran+off, &port); + off += numlen; + origlen += numlen; + DEBUGP("Checking port %hu expec port %hu rbufa %s rbufalen %d\n", + port, prtspexp->loport, rbufa, rbufalen); + if (ptran[off] == '-' || ptran[off] == '/') + { + off++; + origlen++; + numlen = nf_strtou16(ptran+off, &port); + off += numlen; + origlen += numlen; + rbuf = rbufa; + rbuflen = rbufalen; + } + + /* + * note we cannot just memcpy() if the sizes are the same. + * the mangle function does skb resizing, checks for a + * cloned skb, and updates the checksums. + * + * parameter 4 below is offset from start of tcp data. + */ + diff = origlen-rbuflen; + DEBUGP("Before mangle rbuf %s diff %d ptran %s\n", rbuf, diff, ptran+off); + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, + origoff, origlen, rbuf, rbuflen)) + { + /* mangle failed, all we can do is bail */ + DEBUGP("MANGLE Failed\n"); + return 0; + } + get_skb_tcpdata(*pskb, &ptcp, &tcplen); + ptran = ptcp+tranoff; + tranlen -= diff; + nextparamoff -= diff; + nextfieldoff -= diff; + DEBUGP("After mangle nextparamoff %d nextfieldoff %d ptran %s\n", + nextparamoff, nextfieldoff, ptran); + break; + } + off = nextfieldoff; + } + + off = nextparamoff; + } + + return 1; +} + +static unsigned int +expected(struct sk_buff** pskb, uint hooknum, + struct ip_conntrack* ct, struct ip_nat_info* info) +{ + struct ip_nat_multi_range mr; + u_int32_t newdstip, newsrcip, newip; + + struct ip_conntrack *master = master_ct(ct); + + IP_NF_ASSERT(info); + IP_NF_ASSERT(master); + + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum)))); + + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; + newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip; + + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); + DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u CLIENT PORT %hu\n", + NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip), ct->nat.rtsp_info.orig_port); + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple); + + mr.rangesize = 1; + /* + * We don't want to manip the per-protocol, just the IPs. Actually we + * did manipulate the UDP ports + */ + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS; + mr.range[0].min_ip = mr.range[0].max_ip = newip; + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED; + mr.range[0].min.udp.port = mr.range[0].max.udp.port = ct->nat.rtsp_info.orig_port; + + return ip_nat_setup_info(ct, &mr, hooknum); +} + +static uint +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo, + struct ip_conntrack_expect* exp, struct sk_buff** pskb) +{ + char* ptcp; + uint tcplen; + uint hdrsoff; + uint hdrslen; + uint lineoff; + uint linelen; + uint off; + + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph; + struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4); + + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info; + + get_skb_tcpdata(*pskb, &ptcp, &tcplen); + + hdrsoff = exp->seq - ntohl(tcph->seq); + hdrslen = prtspexp->len; + off = hdrsoff; + + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); + + DEBUGP("SRC IP %u.%u.%u.%u DST IP %u.%u.%u.%u PORTS %hu-%hu\n", + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr), prtspexp->loport, + prtspexp->hiport); + while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen)) + { + if (linelen == 0) + { + break; + } + if (off > hdrsoff+hdrslen) + { + INFOP("!! overrun !!\n"); + break; + } + DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); + + if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) + { + uint oldtcplen = tcplen; + if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen)) + { + break; + } + get_skb_tcpdata(*pskb, &ptcp, &tcplen); + hdrslen -= (oldtcplen-tcplen); + off -= (oldtcplen-tcplen); + lineoff -= (oldtcplen-tcplen); + linelen -= (oldtcplen-tcplen); + DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); + } + } + DEBUGP("SRC IP %u.%u.%u.%u DST IP %u.%u.%u.%u PORTS (%hu-%hu)\n", + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr), tcph->source, tcph->dest); + + return NF_ACCEPT; +} + +static uint +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo, + struct ip_conntrack_expect* exp, struct sk_buff** pskb) +{ + /* XXX: unmangle */ + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); + return NF_ACCEPT; +} + +static uint +help(struct ip_conntrack* ct, + struct ip_conntrack_expect* exp, + struct ip_nat_info* info, + enum ip_conntrack_info ctinfo, + unsigned int hooknum, + struct sk_buff** pskb) +{ + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph; + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4); + uint datalen; + int dir; + struct ip_ct_rtsp_expect* ct_rtsp_info; + int rc = NF_ACCEPT; + + DEBUGP("SRC IP %u.%u.%u.%u DST IP %u.%u.%u.%u PORTS %hu-%hu\n", + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr), tcph->source, + tcph->dest); + if (ct == NULL || exp == NULL || info == NULL || pskb == NULL) + { + DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb); + return NF_ACCEPT; + } + + ct_rtsp_info = &exp->help.exp_rtsp_info; + + /* + * Only mangle things once: original direction in POST_ROUTING + * and reply direction on PRE_ROUTING. + */ + dir = CTINFO2DIR(ctinfo); + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL) + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) + { + DEBUGP("Not touching dir %s at hook %s\n", + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY", + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING" + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING" + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"); + return NF_ACCEPT; + } + DEBUGP("got beyond not touching\n"); + + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4; + + LOCK_BH(&ip_rtsp_lock); + + switch (dir) + { + case IP_CT_DIR_ORIGINAL: + rc = help_out(ct, ctinfo, exp, pskb); + break; + case IP_CT_DIR_REPLY: + rc = help_in(ct, ctinfo, exp, pskb); + break; + default: + /* oops */ + break; + } + UNLOCK_BH(&ip_rtsp_lock); + + return rc; +} + +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS]; +static char rtsp_names[MAX_PORTS][10]; + +/* This function is intentionally _NOT_ defined as __exit */ +static void +fini(void) +{ + int i; + + for (i = 0; i < num_ports; i++) + { + DEBUGP("unregistering helper for port %d\n", ports[i]); + ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]); + } +} + +static int __init +init(void) +{ + int ret = 0; + int i; + struct ip_nat_helper* hlpr; + char* tmpname; + + printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n"); + + if (ports[0] == 0) + { + ports[0] = RTSP_PORT; + } + + for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) + { + hlpr = &ip_nat_rtsp_helpers[i]; + memset(hlpr, 0, sizeof(struct ip_nat_helper)); + + hlpr->tuple.dst.protonum = IPPROTO_TCP; + hlpr->tuple.src.u.tcp.port = htons(ports[i]); + hlpr->mask.src.u.tcp.port = 0xFFFF; + hlpr->mask.dst.protonum = 0xFFFF; + hlpr->help = help; + hlpr->flags = 0; + hlpr->me = THIS_MODULE; + hlpr->expect = expected; + + tmpname = &rtsp_names[i][0]; + if (ports[i] == RTSP_PORT) + { + sprintf(tmpname, "rtsp"); + } + else + { + sprintf(tmpname, "rtsp-%d", i); + } + hlpr->name = tmpname; + + DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name); + ret = ip_nat_helper_register(hlpr); + + if (ret) + { + printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]); + fini(); + return 1; + } + num_ports++; + } + if (stunaddr != NULL) + { + extip = in_aton(stunaddr); + } + if (destaction != NULL) + { + if (strcmp(destaction, "auto") == 0) + { + dstact = DSTACT_AUTO; + } + if (strcmp(destaction, "strip") == 0) + { + dstact = DSTACT_STRIP; + } + if (strcmp(destaction, "none") == 0) + { + dstact = DSTACT_NONE; + } + } + return ret; +} + +NEEDS_CONNTRACK(rtsp); + +module_init(init); +module_exit(fini); diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_nat_standalone.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_nat_standalone.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ip_nat_standalone.c 2004-06-26 17:15:27.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ip_nat_standalone.c 2006-12-20 18:45:29.000000000 +0100 @@ -199,6 +199,9 @@ I'm starting to have nightmares about fragments. */ + if ( MULTICAST((*pskb)->nh.iph->daddr)) + return NF_ACCEPT; + if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { *pskb = ip_ct_gather_frags(*pskb); diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ipt_connlimit.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ipt_connlimit.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ipt_connlimit.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ipt_connlimit.c 2006-12-20 18:45:29.000000000 +0100 @@ -0,0 +1,230 @@ +/* + * netfilter module to limit the number of parallel tcp + * connections per IP address. + * (c) 2000 Gerd Knorr + * Nov 2002: Martin Bene : + * only ignore TIME_WAIT or gone connections + * + * based on ... + * + * Kernel module to match connection tracking information. + * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au). + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG 0 + +MODULE_LICENSE("GPL"); + +/* we'll save the tuples of all connections we care about */ +struct ipt_connlimit_conn +{ + struct list_head list; + struct ip_conntrack_tuple tuple; +}; + +struct ipt_connlimit_data { + spinlock_t lock; + struct list_head iphash[256]; +}; + +static int ipt_iphash(u_int32_t addr) +{ + int hash; + + hash = addr & 0xff; + hash ^= (addr >> 8) & 0xff; + hash ^= (addr >> 16) & 0xff; + hash ^= (addr >> 24) & 0xff; + return hash; +} + +static int count_them(struct ipt_connlimit_data *data, + u_int32_t addr, u_int32_t mask, + struct ip_conntrack *ct) +{ +#if DEBUG + const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv", + "fin_wait", "time_wait", "close", "close_wait", + "last_ack", "listen" }; +#endif + int addit = 1, matches = 0; + struct ip_conntrack_tuple tuple; + struct ip_conntrack_tuple_hash *found; + struct ipt_connlimit_conn *conn; + struct list_head *hash,*lh; + + spin_lock(&data->lock); + tuple = ct->tuplehash[0].tuple; + hash = &data->iphash[ipt_iphash(addr & mask)]; + + /* check the saved connections */ + for (lh = hash->next; lh != hash; lh = lh->next) { + conn = list_entry(lh,struct ipt_connlimit_conn,list); + found = ip_conntrack_find_get(&conn->tuple,ct); + if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) && + found != NULL && + found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) { + /* Just to be sure we have it only once in the list. + We should'nt see tuples twice unless someone hooks this + into a table without "-p tcp --syn" */ + addit = 0; + } +#if DEBUG + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n", + ipt_iphash(addr & mask), + NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port), + NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port), + (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone"); +#endif + if (NULL == found) { + /* this one is gone */ + lh = lh->prev; + list_del(lh->next); + kfree(conn); + continue; + } + if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) { + /* we don't care about connections which are + closed already -> ditch it */ + lh = lh->prev; + list_del(lh->next); + kfree(conn); + nf_conntrack_put(&found->ctrack->infos[0]); + continue; + } + if ((addr & mask) == (conn->tuple.src.ip & mask)) { + /* same source IP address -> be counted! */ + matches++; + } + nf_conntrack_put(&found->ctrack->infos[0]); + } + if (addit) { + /* save the new connection in our list */ +#if DEBUG + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n", + ipt_iphash(addr & mask), + NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port), + NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port)); +#endif + conn = kmalloc(sizeof(*conn),GFP_ATOMIC); + if (NULL == conn) + return -1; + memset(conn,0,sizeof(*conn)); + INIT_LIST_HEAD(&conn->list); + conn->tuple = tuple; + list_add(&conn->list,hash); + matches++; + } + spin_unlock(&data->lock); + return matches; +} + +static int +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + int *hotdrop) +{ + const struct ipt_connlimit_info *info = matchinfo; + int connections, match; + struct ip_conntrack *ct; + enum ip_conntrack_info ctinfo; + + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); + if (NULL == ct) { + printk("ipt_connlimit: Oops: invalid ct state ?\n"); + *hotdrop = 1; + return 0; + } + connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct); + if (-1 == connections) { + printk("ipt_connlimit: Hmm, kmalloc failed :-(\n"); + *hotdrop = 1; /* let's free some memory :-) */ + return 0; + } + match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit); +#if DEBUG + printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u " + "connections=%d limit=%d match=%s\n", + NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask), + connections, info->limit, match ? "yes" : "no"); +#endif + + return match; +} + +static int check(const char *tablename, + const struct ipt_ip *ip, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + struct ipt_connlimit_info *info = matchinfo; + int i; + + /* verify size */ + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info))) + return 0; + + /* refuse anything but tcp */ + if (ip->proto != IPPROTO_TCP) + return 0; + + /* init private data */ + info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL); + spin_lock_init(&(info->data->lock)); + for (i = 0; i < 256; i++) + INIT_LIST_HEAD(&(info->data->iphash[i])); + + return 1; +} + +static void destroy(void *matchinfo, unsigned int matchinfosize) +{ + struct ipt_connlimit_info *info = matchinfo; + struct ipt_connlimit_conn *conn; + struct list_head *hash; + int i; + + /* cleanup */ + for (i = 0; i < 256; i++) { + hash = &(info->data->iphash[i]); + while (hash != hash->next) { + conn = list_entry(hash->next,struct ipt_connlimit_conn,list); + list_del(hash->next); + kfree(conn); + } + } + kfree(info->data); +} + +static struct ipt_match connlimit_match = { + .name = "connlimit", + .match = &match, + .checkentry = &check, + .destroy = &destroy, + .me = THIS_MODULE +}; + +static int __init init(void) +{ + return ipt_register_match(&connlimit_match); +} + +static void __exit fini(void) +{ + ipt_unregister_match(&connlimit_match); +} + +module_init(init); +module_exit(fini); diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ipt_FTOS.c linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ipt_FTOS.c --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/ipt_FTOS.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/ipt_FTOS.c 2006-12-20 18:45:29.000000000 +0100 @@ -0,0 +1,109 @@ +/* Set TOS field in header to any value + * + * (C) 2000 by Matthew G. Marsh + * + * This software is distributed under GNU GPL v2, 1991 + * + * ipt_FTOS.c borrowed heavily from ipt_TOS.c 11/09/2000 + * + * Updated 3/4/02 - added in Rusty's skb_clone fix + * - added MODULE Political License + * - redid checksum routine somewhat +*/ + +#include +#include +#include +#include + +#include +#include + +static unsigned int +target(struct sk_buff **pskb, + unsigned int hooknum, + const struct net_device *in, + const struct net_device *out, + const void *targinfo, + void *userinfo) +{ + struct iphdr *iph = (*pskb)->nh.iph; + const struct ipt_FTOS_info *ftosinfo = targinfo; + + if ((iph->tos & IPTOS_TOS_MASK) != ftosinfo->ftos) { + u_int16_t diffs[2]; + + /* raw socket (tcpdump) may have clone of incoming + skb: don't disturb it --RR */ + if (skb_cloned(*pskb) && !(*pskb)->sk) { + struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC); + if (!nskb) + return NF_DROP; + kfree_skb(*pskb); + *pskb = nskb; + iph = (*pskb)->nh.iph; + } + + diffs[0] = htons(iph->tos) ^ 0xFFFF; + iph->tos = ftosinfo->ftos; + diffs[1] = htons(iph->tos); + iph->check = csum_fold(csum_partial((char *)diffs, + sizeof(diffs), + iph->check^0xFFFF)); + (*pskb)->nfcache |= NFC_ALTERED; + } + return IPT_CONTINUE; +} + +static int +checkentry(const char *tablename, + const struct ipt_entry *e, + void *targinfo, + unsigned int targinfosize, + unsigned int hook_mask) +{ + const u_int8_t ftos = ((struct ipt_FTOS_info *)targinfo)->ftos; + + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_FTOS_info))) { + printk(KERN_WARNING "FTOS: targinfosize %u != %Zu\n", + targinfosize, + IPT_ALIGN(sizeof(struct ipt_FTOS_info))); + return 0; + } + + if (strcmp(tablename, "mangle") != 0) { + printk(KERN_WARNING "FTOS: can only be called from \"mangle\" table, not \"%s\"\n", tablename); + return 0; + } + + return 1; +} + +#if defined(CONFIG_MIPS_BRCM) +static struct ipt_target ipt_ftos_reg = { + .name = "FTOS", + .target = target, + .checkentry = checkentry, + .me = THIS_MODULE, +}; +#else +static struct ipt_target ipt_ftos_reg += { { NULL, NULL }, "FTOS", target, checkentry, NULL, THIS_MODULE }; +#endif + +static int __init init(void) +{ + if (ipt_register_target(&ipt_ftos_reg)) + return -EINVAL; + + return 0; +} + +static void __exit fini(void) +{ + ipt_unregister_target(&ipt_ftos_reg); +} + +module_init(init); +module_exit(fini); +MODULE_LICENSE("GPL"); diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/Kconfig linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/Kconfig --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/Kconfig 2004-06-30 19:26:51.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/Kconfig 2006-12-20 18:45:29.000000000 +0100 @@ -29,6 +29,16 @@ To compile it as a module, choose M here. If unsure, say Y. +config IP_NF_H323 + tristate "H323 protocol support" + depends on IP_NF_CONNTRACK + help + Tracking H323 connections is problematic: special helpers are + required for tracking them, and doing masquerading and other forms + of Network Address Translation on them. + + To compile it as a module, choose M here. If unsure, say Y. + config IP_NF_IRC tristate "IRC protocol support" depends on IP_NF_CONNTRACK @@ -68,6 +78,51 @@ To compile it as a module, choose M here. If unsure, say Y. +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +config IP_NF_DTX8 + tristate "DirectX8 protocol support" + depends on IP_NF_CONNTRACK + help + Microsoft DirectX support. + + To compile it as a module, choose M here. If unsure, say Y. + +config IP_NF_WM + tristate "Windows MMS protocol support" + depends on IP_NF_CONNTRACK + help + Microsoft Windows Media Player support. + + To compile it as a module, choose M here. If unsure, say Y. + +config IP_NF_PT + tristate "Port Triggering support" + depends on IP_NF_CONNTRACK + help + Port Triggering support + + To compile it as a module, choose M here. If unsure, say Y. + +config IP_NF_IPSEC + tristate "IPSec support" + depends on IP_NF_CONNTRACK + help + IPSec support + + To compile it as a module, choose M here. If unsure, say Y. + +# CONFIG_MIPS_BRCM End Broadcom changed code. + +config IP_NF_RTSP + tristate "RTSP protocol support" + depends on IP_NF_CONNTRACK + help + Support the RTSP protocol. This allows UDP transports to be setup + properly, including RTP and RDT. + + If you want to compile it as a module, say M here and read + . If unsure, say `Y'. + config IP_NF_QUEUE tristate "Userspace queueing via NETLINK" help @@ -244,6 +299,16 @@ To compile it as a module, choose M here. If unsure, say N. +config IP_NF_MATCH_CONNLIMIT + tristate 'Connections/IP limit match support' + depends on IP_NF_IPTABLES + help + This match allows you to restrict the number of parallel TCP + connections to a server per client IP address (or address block). + + If you want to compile it as a module, say M here and read + Documentation/modules.txt. If unsure, say `N'. + config IP_NF_MATCH_CONNTRACK tristate "Connection tracking match support" depends on IP_NF_CONNTRACK && IP_NF_IPTABLES @@ -396,6 +461,12 @@ default IP_NF_NAT if IP_NF_FTP=y default m if IP_NF_FTP=m +config IP_NF_NAT_H323 + tristate + depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n + default IP_NF_NAT if IP_NF_H323=y + default m if IP_NF_H323=m + config IP_NF_NAT_TFTP tristate depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n @@ -408,6 +479,20 @@ default IP_NF_NAT if IP_NF_AMANDA=y default m if IP_NF_AMANDA=m +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +config IP_NF_NAT_IPSEC + tristate + depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n + default IP_NF_NAT if IP_NF_IPSEC=y + default m if IP_NF_IPSEC=m +# CONFIG_MIPS_BRCM End Broadcom changed code. + +config IP_NF_NAT_RTSP + tristate + depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n + default IP_NF_NAT if IP_NF_RTSP=y + default m if IP_NF_RTSP=m + config IP_NF_MANGLE tristate "Packet mangling" depends on IP_NF_IPTABLES @@ -428,6 +513,17 @@ To compile it as a module, choose M here. If unsure, say N. +config IP_NF_TARGET_FTOS + tristate "FTOS target support" + depends on IP_NF_MANGLE + help + This option adds a `FTOS' target, which allows you to create rules in + the `mangle' table which alter the Type Of Service field of an IP + packet prior to routing. + + To compile it as a module, choose M here. If unsure, say N. + + config IP_NF_TARGET_ECN tristate "ECN target support" depends on IP_NF_MANGLE @@ -628,5 +724,26 @@ If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say `N'. +config IP_NF_PPTP + tristate 'PPTP protocol support' + help + This module adds support for PPTP (Point to Point Tunnelling Protocol, + RFC2637) conncection tracking and NAT. + + If you are running PPTP sessions over a stateful firewall or NAT box, + you may want to enable this feature. + + Please note that not all PPTP modes of operation are supported yet. + For more info, read top of the file net/ipv4/netfilter/ip_conntrack_pptp.c + + If you want to compile it as a module, say M here and read + Documentation/modules.txt. If unsure, say `N'. + +config IP_NF_NAT_PPTP + tristate + depends on IP_NF_NAT!=n && IP_NF_PPTP!=n + default IP_NF_NAT if IP_NF_PPTP=y + default m if IP_NF_PPTP=m + endmenu diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/netfilter/Makefile linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/Makefile --- linux-mips-2.6.8.1-orig/net/ipv4/netfilter/Makefile 2004-06-26 17:15:27.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/ipv4/netfilter/Makefile 2006-12-20 18:45:29.000000000 +0100 @@ -3,8 +3,10 @@ # # objects for the conntrack and NAT core (used by standalone and backw. compat) -ip_nf_conntrack-objs := ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o -ip_nf_nat-objs := ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o +# CONFIG_MIPS_BRCM Begin Broadcom changed code. Add ESP +ip_nf_conntrack-objs := ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o ip_conntrack_proto_esp.o +ip_nf_nat-objs := ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o ip_nat_proto_esp.o +# CONFIG_MIPS_BRCM End Broadcom changed code. # objects for the standalone - connection tracking / NAT ip_conntrack-objs := ip_conntrack_standalone.o $(ip_nf_conntrack-objs) @@ -24,12 +26,35 @@ obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o +obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o ip_conntrack_gre.o +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o # NAT helpers obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o +obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o ip_nat_gre.o +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o + +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +BCMALG_DIR := ./broadcom +# DirectX8 support +obj-$(CONFIG_IP_NF_DTX8) += $(BCMALG_DIR)/ip_conntrack_dtx8.o $(BCMALG_DIR)/ip_nat_dtx8.o + +# MicroSoft Media Player UDP support +obj-$(CONFIG_IP_NF_WM) += $(BCMALG_DIR)/ip_conntrack_wm.o $(BCMALG_DIR)/ip_nat_wm.o + +# Port Triggerng support +obj-$(CONFIG_IP_NF_PT) += $(BCMALG_DIR)/ip_conntrack_pt.o $(BCMALG_DIR)/ip_nat_pt.o + +# IPSec support +obj-$(CONFIG_IP_NF_IPSEC) += $(BCMALG_DIR)/ip_conntrack_ipsec.o +obj-$(CONFIG_IP_NF_NAT_IPSEC) += $(BCMALG_DIR)/ip_nat_ipsec.o + +# CONFIG_MIPS_BRCM End Broadcom changed code. # generic IP tables obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o @@ -62,6 +87,7 @@ obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o @@ -72,6 +98,9 @@ # targets obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +obj-$(CONFIG_IP_NF_TARGET_FTOS) += ipt_FTOS.o +# CONFIG_MIPS_BRCM End Broadcom changed code. obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/raw.c linux-mips-2.6.8.1-bcm/net/ipv4/raw.c --- linux-mips-2.6.8.1-orig/net/ipv4/raw.c 2004-08-06 02:33:32.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/ipv4/raw.c 2006-12-20 18:45:32.000000000 +0100 @@ -535,6 +535,10 @@ if (!skb) goto out; +#if defined(CONFIG_MIPS_BRCM) + sprintf(sk->extdev, "%s ", skb->extif); +#endif + copied = skb->len; if (len < copied) { msg->msg_flags |= MSG_TRUNC; diff -Naur linux-mips-2.6.8.1-orig/net/ipv4/route.c linux-mips-2.6.8.1-bcm/net/ipv4/route.c --- linux-mips-2.6.8.1-orig/net/ipv4/route.c 2004-08-13 09:18:56.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/ipv4/route.c 2006-12-20 18:45:32.000000000 +0100 @@ -2803,7 +2803,11 @@ } ipv4_dst_ops.gc_thresh = (rt_hash_mask + 1); +#if defined(CONFIG_MIPS_BRCM) + ip_rt_max_size = (rt_hash_mask + 1) * 2; +#else ip_rt_max_size = (rt_hash_mask + 1) * 16; +#endif rt_cache_stat = alloc_percpu(struct rt_cache_stat); if (!rt_cache_stat) diff -Naur linux-mips-2.6.8.1-orig/net/Kconfig linux-mips-2.6.8.1-bcm/net/Kconfig --- linux-mips-2.6.8.1-orig/net/Kconfig 2004-08-14 18:16:44.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/Kconfig 2006-12-20 18:45:39.000000000 +0100 @@ -294,6 +294,16 @@ large number of IP-only vcc's. Do not enable this unless you are sure you know what you are doing. +# CONFIG_MIPS_BRCM Begin Broadcom added code. +config ATM_RT2684 + tristate "RFC1483/2684 Routed protocols" + depends on ATM && INET + help + ATM PVCs can carry PPP PDUs according to RFC2364. This is a simplified + point-to-point PPPoA implementation without atmarp support. +# CONFIG_MIPS_BRCM End Broadcom added code. + + config BRIDGE tristate "802.1d Ethernet Bridging" ---help--- diff -Naur linux-mips-2.6.8.1-orig/net/sched/Kconfig linux-mips-2.6.8.1-bcm/net/sched/Kconfig --- linux-mips-2.6.8.1-orig/net/sched/Kconfig 2004-08-06 02:33:33.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/sched/Kconfig 2006-12-20 18:45:19.000000000 +0100 @@ -1,61 +1,15 @@ # # Traffic control configuration. # -choice - prompt "Packet scheduler clock source" - depends on NET_SCHED - default NET_SCH_CLK_JIFFIES - help - Packet schedulers need a monotonic clock that increments at a static - rate. The kernel provides several suitable interfaces, each with - different properties: - - - high resolution (us or better) - - fast to read (minimal locking, no i/o access) - - synchronized on all processors - - handles cpu clock frequency changes - - but nothing provides all of the above. - config NET_SCH_CLK_JIFFIES - bool "Timer interrupt" - help + tristate "Timer interrupt" + depends on NET_SCHED + ---help--- Say Y here if you want to use the timer interrupt (jiffies) as clock source. This clock source is fast, synchronized on all processors and handles cpu clock frequency changes, but its resolution is too low for accurate shaping except at very low speed. -config NET_SCH_CLK_GETTIMEOFDAY - bool "gettimeofday" - help - Say Y here if you want to use gettimeofday as clock source. This clock - source has high resolution, is synchronized on all processors and - handles cpu clock frequency changes, but it is slow. - - Choose this if you need a high resolution clock source but can't use - the CPU's cycle counter. - -config NET_SCH_CLK_CPU - bool "CPU cycle counter" - depends on X86_TSC || X86_64 || ALPHA || SPARC64 || PPC64 || IA64 - help - Say Y here if you want to use the CPU's cycle counter as clock source. - This is a cheap and high resolution clock source, but on some - architectures it is not synchronized on all processors and doesn't - handle cpu clock frequency changes. - - The useable cycle counters are: - - x86/x86_64 - Timestamp Counter - alpha - Cycle Counter - sparc64 - %ticks register - ppc64 - Time base - ia64 - Interval Time Counter - - Choose this if your CPU's cycle counter is working properly. - -endchoice - config NET_SCH_CBQ tristate "CBQ packet scheduler" depends on NET_SCHED diff -Naur linux-mips-2.6.8.1-orig/net/sched/Makefile linux-mips-2.6.8.1-bcm/net/sched/Makefile --- linux-mips-2.6.8.1-orig/net/sched/Makefile 2004-07-20 22:21:28.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/sched/Makefile 2006-12-20 18:45:19.000000000 +0100 @@ -2,6 +2,10 @@ # Makefile for the Linux Traffic Control Unit. # +ifneq ($(strip $(BRCM_KERNEL_NETQOS)),) +CFLAGS += -DSUPPORT_TC +endif + obj-y := sch_generic.o obj-$(CONFIG_NET_SCHED) += sch_api.o sch_fifo.o diff -Naur linux-mips-2.6.8.1-orig/net/sched/sch_api.c linux-mips-2.6.8.1-bcm/net/sched/sch_api.c --- linux-mips-2.6.8.1-orig/net/sched/sch_api.c 2004-08-13 09:18:56.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/sched/sch_api.c 2006-12-20 18:45:19.000000000 +0100 @@ -389,7 +389,8 @@ { int err; struct rtattr *kind = tca[TCA_KIND-1]; - struct Qdisc *sch = NULL; + void *p = NULL; + struct Qdisc *sch; struct Qdisc_ops *ops; int size; @@ -407,12 +408,18 @@ if (ops == NULL) goto err_out; - size = sizeof(*sch) + ops->priv_size; + /* ensure that the Qdisc and the private data are 32-byte aligned */ + size = ((sizeof(*sch) + QDISC_ALIGN_CONST) & ~QDISC_ALIGN_CONST); + size += ops->priv_size + QDISC_ALIGN_CONST; - sch = kmalloc(size, GFP_KERNEL); + p = kmalloc(size, GFP_KERNEL); err = -ENOBUFS; - if (!sch) + if (!p) goto err_out; + memset(p, 0, size); + sch = (struct Qdisc *)(((unsigned long)p + QDISC_ALIGN_CONST) + & ~QDISC_ALIGN_CONST); + sch->padded = (char *)sch - (char *)p; /* Grrr... Resolve race condition with module unload */ @@ -420,8 +427,6 @@ if (ops != qdisc_lookup_ops(kind)) goto err_out; - memset(sch, 0, size); - INIT_LIST_HEAD(&sch->list); skb_queue_head_init(&sch->q); @@ -470,8 +475,8 @@ err_out: *errp = err; - if (sch) - kfree(sch); + if (p) + kfree(p); return NULL; } diff -Naur linux-mips-2.6.8.1-orig/net/sched/sch_generic.c linux-mips-2.6.8.1-bcm/net/sched/sch_generic.c --- linux-mips-2.6.8.1-orig/net/sched/sch_generic.c 2004-08-13 09:18:56.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/sched/sch_generic.c 2006-12-20 18:45:19.000000000 +0100 @@ -546,6 +546,15 @@ #endif BUG_TRAP(!timer_pending(&dev->watchdog_timer)); qdisc_unlock_tree(dev); + + /* decrement on ppp net work device reference count since TC (pfifo) is not releasing it. */ +#if defined(SUPPORT_TC) + if (strstr(dev->name, "ppp_") && atomic_read(&dev->refcnt) > 1) { + printk("dev_shutdown, dec ppp device refcnt, dev->refcnt=%d\n", atomic_read(&dev->refcnt)); + dev_put(dev); + } +#endif + } EXPORT_SYMBOL(__netdev_watchdog_up); diff -Naur linux-mips-2.6.8.1-orig/net/socket.c linux-mips-2.6.8.1-bcm/net/socket.c --- linux-mips-2.6.8.1-orig/net/socket.c 2004-08-13 09:18:56.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/net/socket.c 2006-12-20 18:45:39.000000000 +0100 @@ -1091,12 +1091,16 @@ deadlock in module load. */ if (family == PF_INET && type == SOCK_PACKET) { +#if defined(CONFIG_MIPS_BRCM) + family = PF_PACKET; +#else static int warned; if (!warned) { warned = 1; printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n", current->comm); } family = PF_PACKET; +#endif } err = security_socket_create(family, type, protocol, kern); diff -Naur linux-mips-2.6.8.1-orig/PROD.config linux-mips-2.6.8.1-bcm/PROD.config --- linux-mips-2.6.8.1-orig/PROD.config 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/PROD.config 2006-12-20 18:52:27.000000000 +0100 @@ -0,0 +1,1114 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_HOTPLUG=y +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +# CONFIG_KALLSYMS is not set +# CONFIG_FUTEX is not set +# CONFIG_EPOLL is not set +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# Machine selection +# +CONFIG_MIPS_BRCM=y +# CONFIG_BCM96338 is not set +# CONFIG_BCM96348 is not set +CONFIG_BCM96358=y +CONFIG_BCM_BOARD=y +CONFIG_BCM_SERIAL=y +CONFIG_BCM_ENET=m +CONFIG_BCM_USB=m +CONFIG_BCM_WLAN=m +# CONFIG_BCM_MIMO is not set +CONFIG_BCM_PCI=y +CONFIG_BCM_ATMAPI=m +# CONFIG_BCM_ATMTEST is not set +CONFIG_BCM_ADSL=m +CONFIG_BCM_ENDPOINT=m +# CONFIG_BCM_BCMPROF is not set +# CONFIG_BCM_PROCFS is not set +# CONFIG_BCM_VDSL is not set +# CONFIG_BCM_SECURITY is not set +# CONFIG_BCM_HPNA is not set +CONFIG_BCM_BOARD_IMPL=1 +CONFIG_BCM_SERIAL_IMPL=1 +CONFIG_BCM_ENET_IMPL=2 +CONFIG_BCM_USB_IMPL=2 +CONFIG_BCM_WLAN_IMPL=1 +CONFIG_BCM_ATMAPI_IMPL=1 +CONFIG_BCM_ATMTEST_IMPL=1 +CONFIG_BCM_BLAA_IMPL=1 +CONFIG_BCM_ADSL_IMPL=1 +CONFIG_BCM_ENDPOINT_IMPL=1 +CONFIG_BCM_BCMPROF_IMPL=1 +CONFIG_BCM_PROCFS_IMPL=1 +CONFIG_BCM_SECURITY_IMPL=1 +CONFIG_BCM_HPNA_IMPL=0 +CONFIG_ROOTFS_SQUASHFS=y +# CONFIG_ROOTFS_CRAMFS is not set +# CONFIG_ROOTFS_JFFS2 is not set +# CONFIG_ROOTFS_NFS is not set +CONFIG_ROOT_FLASHFS="root=31:0 ro noinitrd" +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_PREEMPT=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +# CONFIG_PCI_LEGACY_PROC is not set +# CONFIG_PCI_NAMES is not set +CONFIG_MMU=y + +# +# PCMCIA/CardBus support +# +# CONFIG_PCMCIA is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y +# CONFIG_BINFMT_IRIX is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +# CONFIG_MTD_CHAR is not set +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_AMDSTD_RETRY=0 +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +CONFIG_MTD_ROM=y +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_BCM963XX=y +# CONFIG_MTD_CSTM_MIPS_IXX is not set +# CONFIG_MTD_PCI is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_ROUTE_FWMARK is not set +# CONFIG_IP_ROUTE_NAT is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_TOS is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +CONFIG_IP_MROUTE=y +# CONFIG_IP_PIMSM_V1 is not set +# CONFIG_IP_PIMSM_V2 is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +# CONFIG_BRIDGE_NETFILTER is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=y +CONFIG_IP_NF_FTP=y +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_TFTP=m +# CONFIG_IP_NF_AMANDA is not set +# CONFIG_IP_NF_DTX8 is not set +# CONFIG_IP_NF_WM is not set +CONFIG_IP_NF_PT=m +CONFIG_IP_NF_IPSEC=m +CONFIG_IP_NF_RTSP=m +# CONFIG_IP_NF_QUEUE is not set +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_LIMIT=m +# CONFIG_IP_NF_MATCH_IPRANGE is not set +# CONFIG_IP_NF_MATCH_MAC is not set +# CONFIG_IP_NF_MATCH_PKTTYPE is not set +CONFIG_IP_NF_MATCH_MARK=y +# CONFIG_IP_NF_MATCH_MULTIPORT is not set +CONFIG_IP_NF_MATCH_TOS=y +# CONFIG_IP_NF_MATCH_RECENT is not set +# CONFIG_IP_NF_MATCH_ECN is not set +CONFIG_IP_NF_MATCH_DSCP=m +# CONFIG_IP_NF_MATCH_AH_ESP is not set +# CONFIG_IP_NF_MATCH_LENGTH is not set +# CONFIG_IP_NF_MATCH_TTL is not set +# CONFIG_IP_NF_MATCH_TCPMSS is not set +# CONFIG_IP_NF_MATCH_HELPER is not set +CONFIG_IP_NF_MATCH_STATE=y +CONFIG_IP_NF_MATCH_CONNLIMIT=m +# CONFIG_IP_NF_MATCH_CONNTRACK is not set +# CONFIG_IP_NF_MATCH_OWNER is not set +CONFIG_IP_NF_FILTER=y +# CONFIG_IP_NF_TARGET_REJECT is not set +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_REDIRECT=y +# CONFIG_IP_NF_TARGET_NETMAP is not set +# CONFIG_IP_NF_TARGET_SAME is not set +# CONFIG_IP_NF_NAT_LOCAL is not set +# CONFIG_IP_NF_NAT_SNMP_BASIC is not set +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=y +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_NAT_IPSEC=m +CONFIG_IP_NF_NAT_RTSP=m +CONFIG_IP_NF_MANGLE=y +# CONFIG_IP_NF_TARGET_TOS is not set +CONFIG_IP_NF_TARGET_FTOS=y +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_DSCP is not set +CONFIG_IP_NF_TARGET_MARK=y +CONFIG_IP_NF_TARGET_CLASSIFY=y +CONFIG_IP_NF_TARGET_LOG=y +# CONFIG_IP_NF_TARGET_ULOG is not set +CONFIG_IP_NF_TARGET_TCPMSS=y +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_RAW is not set +# CONFIG_IP_NF_MATCH_ADDRTYPE is not set +# CONFIG_IP_NF_MATCH_REALM is not set +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_NAT_PPTP=m + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_BRIDGE_EBT_T_FILTER=y +# CONFIG_BRIDGE_EBT_T_NAT is not set +# CONFIG_BRIDGE_EBT_802_3 is not set +# CONFIG_BRIDGE_EBT_AMONG is not set +# CONFIG_BRIDGE_EBT_ARP is not set +CONFIG_BRIDGE_EBT_IP=y +# CONFIG_BRIDGE_EBT_LIMIT is not set +CONFIG_BRIDGE_EBT_MARK=y +# CONFIG_BRIDGE_EBT_PKTTYPE is not set +# CONFIG_BRIDGE_EBT_STP is not set +CONFIG_BRIDGE_EBT_VLAN=y +CONFIG_BRIDGE_EBT_TIME=y +# CONFIG_BRIDGE_EBT_ARPREPLY is not set +# CONFIG_BRIDGE_EBT_DNAT is not set +CONFIG_BRIDGE_EBT_MARK_T=y +# CONFIG_BRIDGE_EBT_REDIRECT is not set +# CONFIG_BRIDGE_EBT_SNAT is not set +CONFIG_BRIDGE_EBT_FTOS_T=y +CONFIG_BRIDGE_EBT_LOG=y + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +CONFIG_ATM=y +# CONFIG_ATM_CLIP is not set +# CONFIG_ATM_LANE is not set +CONFIG_ATM_BR2684=y +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_ATM_RT2684=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CLK_JIFFIES=y +CONFIG_NET_SCH_CBQ=y +CONFIG_NET_SCH_HTB=y +# CONFIG_NET_SCH_HFSC is not set +CONFIG_NET_SCH_ATM=y +CONFIG_NET_SCH_PRIO=y +# CONFIG_NET_SCH_RED is not set +CONFIG_NET_SCH_SFQ=y +# CONFIG_NET_SCH_TEQL is not set +CONFIG_NET_SCH_TBF=y +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_NETEM is not set +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_QOS=y +CONFIG_NET_ESTIMATOR=y +CONFIG_NET_CLS=y +CONFIG_NET_CLS_TCINDEX=y +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_ROUTE is not set +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +# CONFIG_CLS_U32_PERF is not set +# CONFIG_NET_CLS_IND is not set +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_CLS_POLICE=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +# CONFIG_HERMES is not set +# CONFIG_ATMEL is not set + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +# CONFIG_PRISM54 is not set +CONFIG_NET_WIRELESS=y + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_TCP is not set +# CONFIG_ATM_LANAI is not set +# CONFIG_ATM_ENI is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_ZATM is not set +# CONFIG_ATM_NICSTAR is not set +# CONFIG_ATM_IDT77252 is not set +# CONFIG_ATM_AMBASSADOR is not set +# CONFIG_ATM_HORIZON is not set +# CONFIG_ATM_IA is not set +# CONFIG_ATM_FORE200E_MAYBE is not set +# CONFIG_ATM_HE is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=y +CONFIG_PPPOATM=y +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Userland interfaces +# + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set +# CONFIG_SERIO_I8042 is not set + +# +# Input Device Drivers +# + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=8 +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_EHCI_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_UHCI_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_USB_ACM is not set +CONFIG_USB_PRINTER=y +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_RW_DETECT is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_HP8200e is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set + +# +# USB Human Interface Devices (HID) +# +# CONFIG_USB_HID is not set + +# +# Input core support is needed for USB HID input layer or HIDBP support +# + +# +# USB HID Boot Protocol drivers +# + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network adaptors +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_TIGL is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_SPEEDTOUCH is not set +# CONFIG_USB_PHIDGETSERVO is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=y +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_NAND is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +CONFIG_JFFS2_RUBIN=y +# CONFIG_JFFS2_CMODE_NONE is not set +# CONFIG_JFFS2_CMODE_PRIORITY is not set +CONFIG_JFFS2_CMODE_SIZE=y +CONFIG_SQUASHFS=y +# CONFIG_CRAMFS is not set +CONFIG_LZMA_FS_INFLATE=y +# CONFIG_ZLIB_FS_INFLATE is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +CONFIG_NLS_CODEPAGE_852=y +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +CONFIG_NLS_ISO8859_15=y +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +CONFIG_CRC_CCITT=y +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Naur linux-mips-2.6.8.1-orig/RESCUE.config linux-mips-2.6.8.1-bcm/RESCUE.config --- linux-mips-2.6.8.1-orig/RESCUE.config 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/RESCUE.config 2006-12-20 18:52:27.000000000 +0100 @@ -0,0 +1,757 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +# CONFIG_AUDIT is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_HOTPLUG is not set +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +# CONFIG_KALLSYMS is not set +# CONFIG_FUTEX is not set +# CONFIG_EPOLL is not set +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODULE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# Machine selection +# +CONFIG_MIPS_BRCM=y +# CONFIG_BCM96338 is not set +# CONFIG_BCM96348 is not set +CONFIG_BCM96358=y +CONFIG_BCM_BOARD=y +CONFIG_BCM_SERIAL=y +CONFIG_BCM_ENET=m +# CONFIG_BCM_USB is not set +# CONFIG_BCM_WLAN is not set +# CONFIG_BCM_MIMO is not set +CONFIG_BCM_PCI=y +CONFIG_BCM_ATMAPI=m +# CONFIG_BCM_ATMTEST is not set +CONFIG_BCM_ADSL=m +# CONFIG_BCM_ENDPOINT is not set +# CONFIG_BCM_BCMPROF is not set +# CONFIG_BCM_PROCFS is not set +# CONFIG_BCM_VDSL is not set +# CONFIG_BCM_SECURITY is not set +# CONFIG_BCM_HPNA is not set +CONFIG_BCM_BOARD_IMPL=1 +CONFIG_BCM_SERIAL_IMPL=1 +CONFIG_BCM_ENET_IMPL=2 +CONFIG_BCM_USB_IMPL=2 +CONFIG_BCM_WLAN_IMPL=1 +CONFIG_BCM_ATMAPI_IMPL=1 +CONFIG_BCM_ATMTEST_IMPL=1 +CONFIG_BCM_BLAA_IMPL=1 +CONFIG_BCM_ADSL_IMPL=1 +CONFIG_BCM_ENDPOINT_IMPL=1 +CONFIG_BCM_BCMPROF_IMPL=1 +CONFIG_BCM_PROCFS_IMPL=1 +CONFIG_BCM_SECURITY_IMPL=1 +CONFIG_BCM_HPNA_IMPL=0 +CONFIG_ROOTFS_SQUASHFS=y +# CONFIG_ROOTFS_CRAMFS is not set +# CONFIG_ROOTFS_JFFS2 is not set +# CONFIG_ROOTFS_NFS is not set +CONFIG_ROOT_FLASHFS="root=31:3 ro noinitrd" +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_PREEMPT=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +# CONFIG_PCI_LEGACY_PROC is not set +# CONFIG_PCI_NAMES is not set +CONFIG_MMU=y + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y +# CONFIG_BINFMT_IRIX is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +# CONFIG_MTD_CHAR is not set +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_AMDSTD_RETRY=0 +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_BCM963XX=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set +# CONFIG_IP_NF_PPTP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +CONFIG_ATM=y +# CONFIG_ATM_CLIP is not set +# CONFIG_ATM_LANE is not set +CONFIG_ATM_BR2684=y +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_ATM_RT2684=y +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_TCP is not set +# CONFIG_ATM_LANAI is not set +# CONFIG_ATM_ENI is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_ZATM is not set +# CONFIG_ATM_NICSTAR is not set +# CONFIG_ATM_IDT77252 is not set +# CONFIG_ATM_AMBASSADOR is not set +# CONFIG_ATM_HORIZON is not set +# CONFIG_ATM_IA is not set +# CONFIG_ATM_FORE200E_MAYBE is not set +# CONFIG_ATM_HE is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=y +CONFIG_PPPOATM=y +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Userland interfaces +# + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set +# CONFIG_SERIO_I8042 is not set + +# +# Input Device Drivers +# + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=8 +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_SYSFS is not set +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_SQUASHFS=y +# CONFIG_CRAMFS is not set +CONFIG_LZMA_FS_INFLATE=y +# CONFIG_ZLIB_FS_INFLATE is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_EXPORTFS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +CONFIG_NLS_CODEPAGE_852=y +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_CRC_CCITT=y +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set diff -Naur linux-mips-2.6.8.1-orig/scripts/kconfig/lkc.h linux-mips-2.6.8.1-bcm/scripts/kconfig/lkc.h --- linux-mips-2.6.8.1-orig/scripts/kconfig/lkc.h 2003-06-23 01:10:01.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/scripts/kconfig/lkc.h 2006-12-20 18:45:41.000000000 +0100 @@ -59,9 +59,6 @@ struct file *file_lookup(const char *name); int file_write_dep(const char *name); -extern struct menu *current_entry; -extern struct menu *current_menu; - /* symbol.c */ void sym_init(void); void sym_clear_all_valid(void); diff -Naur linux-mips-2.6.8.1-orig/scripts/kconfig/menu.c linux-mips-2.6.8.1-bcm/scripts/kconfig/menu.c --- linux-mips-2.6.8.1-orig/scripts/kconfig/menu.c 2004-02-19 04:06:37.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/scripts/kconfig/menu.c 2006-12-20 18:45:41.000000000 +0100 @@ -10,7 +10,6 @@ #include "lkc.h" struct menu rootmenu; -struct menu *current_menu, *current_entry; static struct menu **last_entry_ptr; struct file *file_list; diff -Naur linux-mips-2.6.8.1-orig/scripts/kconfig/zconf.tab.c_shipped linux-mips-2.6.8.1-bcm/scripts/kconfig/zconf.tab.c_shipped --- linux-mips-2.6.8.1-orig/scripts/kconfig/zconf.tab.c_shipped 2003-06-23 01:10:01.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/scripts/kconfig/zconf.tab.c_shipped 2006-12-20 18:45:41.000000000 +0100 @@ -175,6 +175,8 @@ struct symbol *symbol_hash[257]; +static struct menu *current_menu, *current_entry; + #define YYERROR_VERBOSE diff -Naur linux-mips-2.6.8.1-orig/scripts/kconfig/zconf.y linux-mips-2.6.8.1-bcm/scripts/kconfig/zconf.y --- linux-mips-2.6.8.1-orig/scripts/kconfig/zconf.y 2003-06-23 01:10:01.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/scripts/kconfig/zconf.y 2006-12-20 18:45:41.000000000 +0100 @@ -25,6 +25,8 @@ struct symbol *symbol_hash[257]; +static struct menu *current_menu, *current_entry; + #define YYERROR_VERBOSE %} %expect 40 diff -Naur linux-mips-2.6.8.1-orig/scripts/lxdialog/Makefile linux-mips-2.6.8.1-bcm/scripts/lxdialog/Makefile --- linux-mips-2.6.8.1-orig/scripts/lxdialog/Makefile 2004-03-11 17:47:01.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/scripts/lxdialog/Makefile 2006-12-20 18:45:40.000000000 +0100 @@ -21,6 +21,14 @@ lxdialog-objs := checklist.o menubox.o textbox.o yesno.o inputbox.o \ util.o lxdialog.o msgbox.o +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +%.o: %.c + $(HOSTCC) $(HOST_EXTRACFLAGS) -c -o $@ $< + +lxdialog: $(obj)/ncurses $(lxdialog-objs) + $(HOSTCC) -o lxdialog $(lxdialog-objs) $(HOST_LOADLIBES) +# CONFIG_MIPS_BRCM End Broadcom changed code. + .PHONY: $(obj)/ncurses $(obj)/ncurses: @echo "main() {}" > lxtemp.c diff -Naur linux-mips-2.6.8.1-orig/scripts/Makefile.build linux-mips-2.6.8.1-bcm/scripts/Makefile.build --- linux-mips-2.6.8.1-orig/scripts/Makefile.build 2004-04-12 22:23:42.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/scripts/Makefile.build 2006-12-20 18:45:42.000000000 +0100 @@ -172,6 +172,27 @@ %.o: %.c FORCE $(call if_changed_rule,cc_o_c) +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +# C++ support +cmd_cc_o_cpp = $(CXX) $(c_flags) -c -o $@ $< +quiet_cmd_cc_o_cpp = C++ $(quiet_modtag) $@ + +define rule_cc_o_cpp + $(if $($(quiet)cmd_checksrc),echo ' $($(quiet)cmd_checksrc)';) \ + $(cmd_checksrc) \ + $(if $($(quiet)cmd_cc_o_cpp),echo ' $($(quiet)cmd_cc_o_cpp)';) \ + $(cmd_cc_o_cpp); \ + $(cmd_modversions) \ + scripts/basic/fixdep $(depfile) $@ '$(cmd_cc_o_cpp)' > $(@D)/.$(@F).tmp; \ + rm -f $(depfile); \ + mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd +endef + +%.o: %.cpp FORCE + $(call if_changed_rule,cc_o_cpp) +# CONFIG_MIPS_BRCM End Broadcom changed code. + + # Single-part modules are special since we need to mark them in $(MODVERDIR) $(single-used-m): %.o: %.c FORCE diff -Naur linux-mips-2.6.8.1-orig/scripts/mod/modpost.c linux-mips-2.6.8.1-bcm/scripts/mod/modpost.c --- linux-mips-2.6.8.1-orig/scripts/mod/modpost.c 2004-08-06 02:33:33.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/scripts/mod/modpost.c 2006-12-20 18:45:40.000000000 +0100 @@ -458,7 +458,7 @@ va_start(ap, fmt); len = vsnprintf(tmp, SZ, fmt, ap); if (buf->size - buf->pos < len + 1) { - buf->size += 128; + buf->size += 4096; buf->p = realloc(buf->p, buf->size); } strncpy(buf->p + buf->pos, tmp, len + 1); diff -Naur linux-mips-2.6.8.1-orig/UPGRADE.config linux-mips-2.6.8.1-bcm/UPGRADE.config --- linux-mips-2.6.8.1-orig/UPGRADE.config 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/UPGRADE.config 2006-12-20 18:52:27.000000000 +0100 @@ -0,0 +1,757 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +# CONFIG_AUDIT is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_HOTPLUG is not set +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +# CONFIG_KALLSYMS is not set +# CONFIG_FUTEX is not set +# CONFIG_EPOLL is not set +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODULE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# Machine selection +# +CONFIG_MIPS_BRCM=y +# CONFIG_BCM96338 is not set +# CONFIG_BCM96348 is not set +CONFIG_BCM96358=y +CONFIG_BCM_BOARD=y +CONFIG_BCM_SERIAL=y +CONFIG_BCM_ENET=m +# CONFIG_BCM_USB is not set +# CONFIG_BCM_WLAN is not set +# CONFIG_BCM_MIMO is not set +CONFIG_BCM_PCI=y +CONFIG_BCM_ATMAPI=m +# CONFIG_BCM_ATMTEST is not set +CONFIG_BCM_ADSL=m +# CONFIG_BCM_ENDPOINT is not set +# CONFIG_BCM_BCMPROF is not set +# CONFIG_BCM_PROCFS is not set +# CONFIG_BCM_VDSL is not set +# CONFIG_BCM_SECURITY is not set +# CONFIG_BCM_HPNA is not set +CONFIG_BCM_BOARD_IMPL=1 +CONFIG_BCM_SERIAL_IMPL=1 +CONFIG_BCM_ENET_IMPL=2 +CONFIG_BCM_USB_IMPL=2 +CONFIG_BCM_WLAN_IMPL=1 +CONFIG_BCM_ATMAPI_IMPL=1 +CONFIG_BCM_ATMTEST_IMPL=1 +CONFIG_BCM_BLAA_IMPL=1 +CONFIG_BCM_ADSL_IMPL=1 +CONFIG_BCM_ENDPOINT_IMPL=1 +CONFIG_BCM_BCMPROF_IMPL=1 +CONFIG_BCM_PROCFS_IMPL=1 +CONFIG_BCM_SECURITY_IMPL=1 +CONFIG_BCM_HPNA_IMPL=0 +CONFIG_ROOTFS_SQUASHFS=y +# CONFIG_ROOTFS_CRAMFS is not set +# CONFIG_ROOTFS_JFFS2 is not set +# CONFIG_ROOTFS_NFS is not set +CONFIG_ROOT_FLASHFS="root=31:1 ro noinitrd" +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_PREEMPT=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +# CONFIG_PCI_LEGACY_PROC is not set +# CONFIG_PCI_NAMES is not set +CONFIG_MMU=y + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y +# CONFIG_BINFMT_IRIX is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +# CONFIG_MTD_CHAR is not set +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_AMDSTD_RETRY=0 +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_BCM963XX=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set +# CONFIG_IP_NF_PPTP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +CONFIG_ATM=y +# CONFIG_ATM_CLIP is not set +# CONFIG_ATM_LANE is not set +CONFIG_ATM_BR2684=y +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_ATM_RT2684=y +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_TCP is not set +# CONFIG_ATM_LANAI is not set +# CONFIG_ATM_ENI is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_ZATM is not set +# CONFIG_ATM_NICSTAR is not set +# CONFIG_ATM_IDT77252 is not set +# CONFIG_ATM_AMBASSADOR is not set +# CONFIG_ATM_HORIZON is not set +# CONFIG_ATM_IA is not set +# CONFIG_ATM_FORE200E_MAYBE is not set +# CONFIG_ATM_HE is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=y +CONFIG_PPPOATM=y +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Userland interfaces +# + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set +# CONFIG_SERIO_I8042 is not set + +# +# Input Device Drivers +# + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=8 +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_SYSFS is not set +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_SQUASHFS=y +# CONFIG_CRAMFS is not set +CONFIG_LZMA_FS_INFLATE=y +# CONFIG_ZLIB_FS_INFLATE is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_EXPORTFS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +CONFIG_NLS_CODEPAGE_852=y +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_CRC_CCITT=y +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set