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, whi