]> git.neil.brown.name Git - history.git/commitdiff
Import 2.4.0-test6pre10 2.4.0-test6pre10
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:37:46 +0000 (15:37 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:37:46 +0000 (15:37 -0500)
143 files changed:
Documentation/Configure.help
arch/i386/kernel/apm.c
arch/mips/sgi/kernel/setup.c
arch/mips64/sgi-ip22/ip22-setup.c
arch/sh/boot/compressed/Makefile
arch/sh/boot/compressed/head.S
arch/sh/config.in
arch/sh/defconfig
arch/sh/kernel/Makefile
arch/sh/kernel/cf-enabler.c
arch/sh/kernel/entry.S
arch/sh/kernel/io.c [new file with mode: 0644]
arch/sh/kernel/io_generic.c
arch/sh/kernel/io_hd64461.c
arch/sh/kernel/io_se.c
arch/sh/kernel/io_unknown.c [new file with mode: 0644]
arch/sh/kernel/irq.c
arch/sh/kernel/irq_imask.c
arch/sh/kernel/irq_ipr.c
arch/sh/kernel/led_se.c [new file with mode: 0644]
arch/sh/kernel/mach_hp600.c [new file with mode: 0644]
arch/sh/kernel/mach_se.c [new file with mode: 0644]
arch/sh/kernel/mach_unknown.c [new file with mode: 0644]
arch/sh/kernel/pci-sh.c
arch/sh/kernel/semaphore.c
arch/sh/kernel/setup.c
arch/sh/kernel/setup_cqreek.c [new file with mode: 0644]
arch/sh/kernel/setup_hd64461.c
arch/sh/kernel/setup_se.c
arch/sh/kernel/sh_bios.c
arch/sh/kernel/signal.c
arch/sh/kernel/time.c
arch/sh/lib/Makefile
arch/sh/lib/checksum.S
arch/sh/lib/strcasecmp.c [new file with mode: 0644]
arch/sh/mm/Makefile
arch/sh/mm/cache.c
arch/sh/mm/fault.c
arch/sh/vmlinux.lds.S
arch/sparc/config.in
arch/sparc/defconfig
arch/sparc/mm/generic.c
arch/sparc/mm/init.c
arch/sparc/mm/io-unit.c
arch/sparc/mm/iommu.c
arch/sparc/mm/srmmu.c
arch/sparc/mm/sun4c.c
arch/sparc64/kernel/Makefile
arch/sparc64/kernel/rtrap.S
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/mm/fault.c
arch/sparc64/mm/generic.c
arch/sparc64/mm/init.c
drivers/acorn/char/keyb_arc.c
drivers/acorn/char/keyb_ps2.c
drivers/acorn/scsi/fas216.c
drivers/block/ll_rw_blk.c
drivers/block/md.c
drivers/block/raid1.c
drivers/block/raid5.c
drivers/block/xd.h
drivers/char/busmouse.c
drivers/char/console.c
drivers/char/drm/drmP.h
drivers/char/hp600_keyb.c
drivers/char/scan_keyb.c
drivers/char/sh-sci.c
drivers/char/sh-sci.h
drivers/net/Config.in
drivers/net/bmac.c
drivers/net/eepro100.c
drivers/net/gmac.c
drivers/net/hydra.c
drivers/net/pcmcia/com20020_cs.c
drivers/net/pcmcia/ray_cs.c
drivers/net/pppoe.c
drivers/net/sis900.c
drivers/net/sis900.h
drivers/net/stnic.c
drivers/pci/pci.ids
drivers/video/Config.in
drivers/video/acornfb.c
drivers/video/hitfb.c
fs/Config.in
fs/jffs/Makefile
fs/jffs/inode-v23.c
fs/jffs/intrep.c
fs/jffs/intrep.h
fs/jffs/jffs_fm.c
fs/jffs/jffs_fm.h
fs/partitions/acorn.c
fs/partitions/acorn.h
include/asm-alpha/page.h
include/asm-arm/arch-sa1100/mmzone.h
include/asm-arm/page.h
include/asm-i386/page.h
include/asm-ia64/page.h
include/asm-m68k/page.h
include/asm-mips/page.h
include/asm-mips64/mmzone.h
include/asm-mips64/page.h
include/asm-ppc/page.h
include/asm-s390/page.h
include/asm-sh/bugs.h
include/asm-sh/delay.h
include/asm-sh/dma.h
include/asm-sh/hd64461.h
include/asm-sh/ide.h
include/asm-sh/io.h
include/asm-sh/io_generic.h [new file with mode: 0644]
include/asm-sh/io_hd64461.h [new file with mode: 0644]
include/asm-sh/io_od.h [new file with mode: 0644]
include/asm-sh/io_se.h [new file with mode: 0644]
include/asm-sh/io_unknown.h [new file with mode: 0644]
include/asm-sh/irq.h
include/asm-sh/keyboard.h
include/asm-sh/machvec.h [new file with mode: 0644]
include/asm-sh/machvec_init.h [new file with mode: 0644]
include/asm-sh/mmu_context.h
include/asm-sh/page.h
include/asm-sh/pci.h
include/asm-sh/pgtable.h
include/asm-sh/processor.h
include/asm-sparc/page.h
include/asm-sparc/pgtable.h
include/asm-sparc64/mmu_context.h
include/asm-sparc64/page.h
include/asm-sparc64/pgtable.h
include/asm-sparc64/processor.h
include/linux/blk.h
include/linux/blkdev.h
include/linux/brlock.h
include/linux/highmem.h
include/linux/jffs.h
include/linux/mm.h
include/linux/pci_ids.h
include/video/fbcon.h
kernel/fork.c
kernel/timer.c
net/atm/mpc.c
net/ipv4/ip_options.c
net/packet/af_packet.c
net/socket.c

index baf746b70b25253569db3a55fca6380baf43cf0a..310172e91fe741fdcc4440b677a95ec7b9e8cffa 100644 (file)
@@ -8920,8 +8920,15 @@ CONFIG_EEPRO100
 
 Enable Power Management (EXPERIMENTAL)
 CONFIG_EEPRO100_PM
-  If you want to play around with power management code
-  that has been reported to lock up some machines, say Y here.
+  Many Intel EtherExpress PRO/100 PCI network cards are capable
+  of providing power management capabilities.  To make use of these
+  capabilities, say Y.
+
+  WARNING:  This option is intended for kernel developers and testers.
+  It is still very experimental, with some people reporting complete
+  lockups.
+
+  It is recommended to say N here.
 
 ICL EtherTeam 16i/32 support (EXPERIMENTAL)
 CONFIG_ETH16I
index 039ba695c87b0d3cc7e83b3e44df8d4c54468193..9a4084292277b0ca341dc9a6d2d1d2e5f59bca79 100644 (file)
@@ -410,7 +410,7 @@ static const lookup_t error_table[] = {
 #ifndef CONFIG_APM_ALLOW_INTS
 #      define APM_DO_CLI       __cli()
 #else
-#      define APM_DO_CLI
+#      define APM_DO_CLI       __sti()
 #endif
 #ifdef APM_ZERO_SEGS
 #      define APM_DECL_SEGS \
index f511e98de95d5e87516308e2ac29e44d34d459cd..bfd831a90f4afcdcc8b995b9c36b7f645cc0cc75 100644 (file)
@@ -130,9 +130,9 @@ static void __init sgi_irq_setup(void)
 
 int __init page_is_ram(unsigned long pagenr)
 {
-       if (pagenr < MAP_NR(PAGE_OFFSET + 0x2000UL))
+       if ((pagenr<<PAGE_SHIFT) < 0x2000UL)
                return 1;
-       if (pagenr > MAP_NR(PAGE_OFFSET + 0x08002000))
+       if ((pagenr<<PAGE_SHIFT) > 0x08002000)
                return 1;
        return 0;
 }
index 82aa098c5ee185168325c511ab67ac6bb0661e0b..808e00a3ff11a55124daa425f2583d74c5fc9234 100644 (file)
@@ -114,9 +114,9 @@ struct kbd_ops sgi_kbd_ops = {
 
 int __init page_is_ram(unsigned long pagenr)
 {
-       if (pagenr < MAP_NR(PAGE_OFFSET + 0x2000UL))
+       if ((pagenr<<PAGE_SHIFT) < 0x2000UL)
                return 1;
-       if (pagenr > MAP_NR(PAGE_OFFSET + 0x08002000))
+       if ((pagenr<<PAGE_SHIFT) > 0x08002000)
                return 1;
        return 0;
 }
index d62db272223d2b0619c177205e9583f465aec3a1..bd419991bd54ff6f511053bbce19a4ba5b41ed7f 100644 (file)
@@ -18,7 +18,7 @@ ZLDFLAGS = -e startup -T $(TOPDIR)/arch/sh/vmlinux.lds
 #
 # ZIMAGE_OFFSET is the load offset of the compression loader
 #
-ZIMAGE_OFFSET = $(shell printf "0x%8x" $$[0x80000000+0x$(CONFIG_MEMORY_START)+0x200000+0x10000+0x400])
+ZIMAGE_OFFSET = $(shell printf "0x%8x" $$[0x80000000+0x$(CONFIG_MEMORY_START)+0x200000+0x10000])
 
 ZLINKFLAGS = -Ttext $(ZIMAGE_OFFSET) $(ZLDFLAGS)
 
index d270d1b47a90a7e5735ea2b73282c3da1a56bb2d..86a3acf825beddc2500b6b169dbf20536aca6cc9 100644 (file)
@@ -10,6 +10,9 @@
 
        .global startup
 startup:
+       /* Load initial status register */
+       mov.l   init_sr, r1
+       ldc     r1, sr
 
        /* First clear BSS */
        mov.l   end_addr, r1
@@ -20,10 +23,6 @@ l1:
        cmp/eq  r1,r2
        bf      l1
 
-       /* Load initial status register */
-       mov.l   init_sr, r1
-       ldc     r1, sr
-       
        /* Set the initial pointer. */
        mov.l   init_stack_addr, r0
        mov.l   @r0, r15
@@ -44,7 +43,7 @@ bss_start_addr:
 end_addr:
        .long   _end
 init_sr:
-       .long   0x50000000      /* Privileged mode, Bank=0, Block=1, I3-I0=0 */
+       .long   0x40000000      /* Privileged mode, Bank=0, Block=0, I3-I0=0 */
 init_stack_addr:
        .long   stack_start
 decompress_kernel_addr:
index 2d0790bde548a4cfabbba672d6f089d3c81edacc..fa36d92f750e540d7c377c9c8c6bc6564a121de4 100644 (file)
@@ -28,12 +28,19 @@ choice 'SuperH system type'                                 \
        "Generic                CONFIG_SH_GENERIC               \
         SolutionEngine         CONFIG_SH_SOLUTION_ENGINE       \
         Overdrive              CONFIG_SH_OVERDRIVE             \
-        HP600                  CONFIG_SH_HP600" Generic
+        HP600                  CONFIG_SH_HP600                 \
+        CqREEK                 CONFIG_SH_CQREEK                \
+        BareCPU                CONFIG_SH_UNKNOWN" Generic
 
 choice 'Processor type' \
-   "SH7708 CONFIG_CPU_SUBTYPE_SH7708 \
+   "SH7707 CONFIG_CPU_SUBTYPE_SH7707 \
+    SH7708 CONFIG_CPU_SUBTYPE_SH7708 \
     SH7709 CONFIG_CPU_SUBTYPE_SH7709 \
     SH7750 CONFIG_CPU_SUBTYPE_SH7750" SH7708
+if [ "$CONFIG_CPU_SUBTYPE_SH7707" = "y" ]; then
+   define_bool CONFIG_CPU_SH3 y
+   define_bool CONFIG_CPU_SH4 n
+fi
 if [ "$CONFIG_CPU_SUBTYPE_SH7708" = "y" ]; then
    define_bool CONFIG_CPU_SH3 y
    define_bool CONFIG_CPU_SH4 n
@@ -52,7 +59,6 @@ if [ "$CONFIG_SH_SOLUTION_ENGINE" = "y" -o "$CONFIG_SH_HP600" = "y" -o \
   define_hex CONFIG_MEMORY_START 0c000000
 else
   hex 'Physical memory start address' CONFIG_MEMORY_START 08000000
-  hex 'I/O port offset address' CONFIG_IOPORT_START ba000000
 fi
 endmenu
 
@@ -178,6 +184,12 @@ bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
 if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
    int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
 fi
+
+if [ "$CONFIG_SH_GENERIC" = "y" -o \
+     "$CONFIG_SH_OVERDRIVE" = "y" -o "$CONFIG_SH_SOLUTION_ENGINE" = "y" ]; then
+  bool 'Heartbeat LED' CONFIG_HEARTBEAT
+fi
+
 if [ "$CONFIG_PARPORT" != "n" ]; then
    dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
    if [ "$CONFIG_PRINTER" != "n" ]; then
@@ -221,7 +233,8 @@ comment 'Kernel hacking'
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 bool 'Use LinuxSH standard BIOS' CONFIG_SH_STANDARD_BIOS
 if [ "$CONFIG_SH_STANDARD_BIOS" = "y" ]; then
-    bool 'GDB Stub kernel debug' CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
-    bool 'Early printk support' CONFIG_SH_EARLY_PRINTK
+   hex ' GDB Stub VBR' CONFIG_GDB_STUB_VBR a0000000
+   bool 'GDB Stub kernel debug' CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
+   bool 'Early printk support' CONFIG_SH_EARLY_PRINTK
 fi
 endmenu
index e1d9d172591620942d44307ab2793dd141e333c2..5ffc0e0abbde9db678aa5086627e13ad001c8a11 100644 (file)
@@ -21,6 +21,8 @@ CONFIG_SH_GENERIC=y
 # CONFIG_SH_SOLUTION_ENGINE is not set
 # CONFIG_SH_OVERDRIVE is not set
 # CONFIG_SH_HP600 is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
 CONFIG_CPU_SUBTYPE_SH7708=y
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
@@ -28,7 +30,6 @@ CONFIG_CPU_SH3=y
 # CONFIG_CPU_SH4 is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_MEMORY_START=0c000000
-CONFIG_IOPORT_START=ba000000
 
 #
 # General setup
@@ -139,6 +140,7 @@ CONFIG_SERIAL_CONSOLE=y
 # Unix 98 PTY support
 #
 # CONFIG_UNIX98_PTYS is not set
+# CONFIG_HEARTBEAT is not set
 
 #
 # File systems
@@ -200,4 +202,5 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_MAGIC_SYSRQ is not set
 CONFIG_SH_STANDARD_BIOS=y
 CONFIG_DEBUG_KERNEL_WITH_GDB_STUB=y
+CONFIG_GDB_STUB_VBR=a0000000
 CONFIG_SH_EARLY_PRINTK=y
index 7b38522958cdc6958a39d04feff2041879834804..c9de70daf7b9fe1f4f2acfe7c70390b47bada740 100644 (file)
@@ -11,8 +11,8 @@
 
 O_TARGET := kernel.o
 O_OBJS   := process.o signal.o entry.o traps.o irq.o irq_ipr.o \
-            ptrace.o setup.o time.o sys_sh.o semaphore.o pci-sh.o \
-           irq_imask.o
+            ptrace.o setup.o time.o sys_sh.o semaphore.o \
+            irq_imask.o io.o
 OX_OBJS  := sh_ksyms.o
 MX_OBJS  :=
 
@@ -21,26 +21,45 @@ O_OBJS += cf-enabler.o
 endif
 
 ifdef CONFIG_SH_GENERIC
+
+O_OBJS += mach_se.o setup_se.o setup_cqreek.o io_se.o led_se.o \
+         mach_hp600.o io_hd64461.o \
+         mach_unknown.o io_unknown.o \
+         io_generic.o
+
+else
+
+ifdef CONFIG_SH_HP600
+O_OBJS += mach_hp600.o io_hd64461.o io_generic.o
+endif
+
+ifdef CONFIG_SH_OVERDRIVE
 O_OBJS += io_generic.o
 endif
 
 ifdef CONFIG_SH_SOLUTION_ENGINE
-O_OBJS += setup_se.o io_se.o
+O_OBJS += mach_se.o setup_se.o io_se.o io_generic.o led_se.o
 endif
 
-ifdef CONFIG_SH_OVERDRIVE
-O_OBJS += setup_od.o io_generic.o
+ifdef CONFIG_SH_CQREEK
+O_OBJS += setup_cqreek.o
+endif
+
+ifdef CONFIG_SH_UNKNOWN
+O_OBJS += mach_unknown.o io_unknown.o io_generic.o
 endif
 
-ifdef CONFIG_SH_HP600
-O_OBJS += io_hd64461.o
 endif
 
 ifdef CONFIG_CPU_SH4
 O_OBJS += fpu.o
 endif
 
-ifdef CONFIG_HD64461
+ifdef CONFIG_PCI
+O_OBJS += pci-sh.o 
+endif
+
+ifneq ($(CONFIG_SH_GENERIC)$(CONFIG_HD64461),)
 O_OBJS += setup_hd64461.o
 endif
 
index 3727c7264810e585043196bfecb2642666cb4b3d..c446a115179a423f80c7fc727af838a2cf8d42c8 100644 (file)
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#ifdef CONFIG_SH_SOLUTION_ENGINE
 #include <asm/hitachi_se.h>
+
+
 /*
+ * SolutionEngine
+ *
  * 0xB8400000 : Common Memory
  * 0xB8500000 : Attribute
  * 0xB8600000 : I/O
  */
 
-int __init cf_init(void)
+static int __init cf_init_se(void)
 {
        if ((ctrl_inw(MRSHPC_CSR) & 0x000c) != 0)
                return 0;       /* Not detected */
@@ -68,11 +71,15 @@ int __init cf_init(void)
        ctrl_outb(0x42, PA_MRSHPC_MW2 + 0x200);
        return 0;
 }
-#else /* then generic system type */
+
 #define CF_CIS_BASE    0xb8000000
 /*
  * You can connect Compact Flash directly to the bus of SuperH.
  * This is the enabler for that.
+ *
+ * SIM: How generic is this really? It looks pretty board, or at
+ * least SH sub-type, specific to me.
+ * I know it doesn't work on the Overdrive!
  */
 
 /*
@@ -81,7 +88,7 @@ int __init cf_init(void)
  * 0xBA000000 : I/O
  */
 
-int __init cf_init(void)
+static int __init cf_init_default(void)
 {
        /* Enable the card, and set the level interrupt */
        ctrl_outw(0x0042, CF_CIS_BASE+0x0200);
@@ -89,6 +96,13 @@ int __init cf_init(void)
        disable_irq(14);
        return 0;
 }
-#endif
+
+int __init cf_init(void)
+{
+       if (MACH_SE) {
+               return cf_init_se();
+       }
+       return cf_init_default();
+}
 
 __initcall (cf_init);
index 450d4982446f933aa5c4e5f7136272c349a73190..4e57175e76aa439581ef155c3a03611540ce6db9 100644 (file)
@@ -62,7 +62,7 @@ ENOSYS = 38
 #if defined(__sh3__)
 TRA     = 0xffffffd0
 EXPEVT  = 0xffffffd4
-#ifdef CONFIG_CPU_SUBTYPE_SH7709
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
 INTEVT  = 0xa4000000           ! INTEVTE2(0xa4000000)
 #else
 INTEVT  = 0xffffffd8
@@ -182,7 +182,7 @@ tlb_protection_violation_store:
 1:     .long   SYMBOL_NAME(do_page_fault)
 2:     .long   MMU_TEA
 
-#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
+#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS)
        .align  2
        /* Unwind the stack and jmp to the debug entry */
 debug_kernel:
@@ -219,12 +219,12 @@ debug_kernel:
         ldc    $k1, $ssr
        .align  2
 1:     .long   0x300000f0
-2:     .long   0xa0000100
+2:     .long   CONFIG_GDB_STUB_VBR + 0x100
 #endif
 
        .align  2
 debug_trap:    
-#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
+#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS)
        mov     #SR, $r0
        mov.l   @($r0,$r15), $r0        ! get status register
        shll    $r0
@@ -829,7 +829,7 @@ ENTRY(interrupt_table)
        .long   SYMBOL_NAME(do_IRQ)     !      rovi
        .long   SYMBOL_NAME(do_IRQ)
        .long   SYMBOL_NAME(do_IRQ)
-#if defined(CONFIG_CPU_SUBTYPE_SH7709)
+#if  defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
        .long   SYMBOL_NAME(do_IRQ)     ! 32 IRQ  irq0
        .long   SYMBOL_NAME(do_IRQ)     ! 33      irq1
        .long   SYMBOL_NAME(do_IRQ)     ! 34      irq2
@@ -859,6 +859,11 @@ ENTRY(interrupt_table)
        .long   SYMBOL_NAME(do_IRQ)     ! 58      bri2
        .long   SYMBOL_NAME(do_IRQ)     ! 59      txi2
        .long   SYMBOL_NAME(do_IRQ)     ! 60 ADC  adi
+#if defined(CONFIG_CPU_SUBTYPE_SH7707)
+       .long   SYMBOL_NAME(do_IRQ)     ! 61 LCDC lcdi
+       .long   SYMBOL_NAME(do_IRQ)     ! 62 PCC  pcc0i
+       .long   SYMBOL_NAME(do_IRQ)     ! 63      pcc1i
+#endif
 #elif defined(__SH4__)
        .long   SYMBOL_NAME(do_IRQ)     ! Hitachi UDI
        .long   SYMBOL_NAME(do_IRQ)     ! GPIO
diff --git a/arch/sh/kernel/io.c b/arch/sh/kernel/io.c
new file mode 100644 (file)
index 0000000..27f250f
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * linux/arch/sh/kernel/io_generic.c
+ *
+ * Copyright (C) 2000  Stuart Menefy
+ *
+ * Provide real functions which expand to whatever the header file defined.
+ * Also definitions of machine independant IO functions.
+ */
+
+#include <linux/config.h>
+#include <asm/io.h>
+
+unsigned int _inb(unsigned long port)
+{
+       return __inb(port);
+}
+
+unsigned int _inw(unsigned long port)
+{
+       return __inw(port);
+}
+
+unsigned int _inl(unsigned long port)
+{
+       return __inl(port);
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+       __outb(b, port);
+}
+
+void _outw(unsigned short b, unsigned long port)
+{
+       __outw(b, port);
+}
+
+void _outl(unsigned int b, unsigned long port)
+{
+       __outl(b, port);
+}
+
+unsigned int _inb_p(unsigned long port)
+{
+       return __inb_p(port);
+}
+
+unsigned int _inw_p(unsigned long port)
+{
+       return __inw_p(port);
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+       __outb_p(b, port);
+}
+
+void _outw_p(unsigned short b, unsigned long port)
+{
+       __outw_p(b, port);
+}
+
+void _insb(unsigned long port, void *buffer, unsigned long count)
+{
+       return __insb(port, buffer, count);
+}
+
+void _insw(unsigned long port, void *buffer, unsigned long count)
+{
+       __insw(port, buffer, count);
+}
+
+void _insl(unsigned long port, void *buffer, unsigned long count)
+{
+       __insl(port, buffer, count);
+}
+
+void _outsb(unsigned long port, const void *buffer, unsigned long count)
+{
+       __outsb(port, buffer, count);
+}
+
+void _outsw(unsigned long port, const void *buffer, unsigned long count)
+{
+       __outsw(port, buffer, count);
+}
+
+void _outsl(unsigned long port, const void *buffer, unsigned long count)
+{
+       __outsl(port, buffer, count);
+
+}
+
+unsigned long ___raw_readb(unsigned long addr)
+{
+       return __readb(addr);
+}
+
+unsigned long ___raw_readw(unsigned long addr)
+{
+       return __readw(addr);
+}
+
+unsigned long ___raw_readl(unsigned long addr)
+{
+       return __readl(addr);
+}
+
+unsigned long _readb(unsigned long addr)
+{
+       unsigned long r = __readb(addr);
+       mb();
+       return r;
+}
+
+unsigned long _readw(unsigned long addr)
+{
+       unsigned long r = __readw(addr);
+       mb();
+       return r;
+}
+
+unsigned long _readl(unsigned long addr)
+{
+       unsigned long r = __readl(addr);
+       mb();
+       return r;
+}
+
+void ___raw_writeb(unsigned char b, unsigned long addr)
+{
+       __writeb(b, addr);
+}
+
+void ___raw_writew(unsigned short b, unsigned long addr)
+{
+       __writew(b, addr);
+}
+
+void ___raw_writel(unsigned int b, unsigned long addr)
+{
+       __writel(b, addr);
+}
+
+void _writeb(unsigned char b, unsigned long addr)
+{
+       __writeb(b, addr);
+       mb();
+}
+
+void _writew(unsigned short b, unsigned long addr)
+{
+       __writew(b, addr);
+       mb();
+}
+
+void _writel(unsigned int b, unsigned long addr)
+{
+       __writel(b, addr);
+       mb();
+}
+
+/*
+ * Copy data from IO memory space to "real" memory space.
+ * This needs to be optimized.
+ */
+void  memcpy_fromio(void * to, unsigned long from, unsigned long count)
+{
+        while (count) {
+                count--;
+                *(char *) to = readb(from);
+                ((char *) to)++;
+                from++;
+        }
+}
+/*
+ * Copy data from "real" memory space to IO memory space.
+ * This needs to be optimized.
+ */
+void  memcpy_toio(unsigned long to, const void * from, unsigned long count)
+{
+        while (count) {
+                count--;
+                writeb(*(char *) from, to);
+                ((char *) from)++;
+                to++;
+        }
+}
+/*
+ * "memset" on IO memory space.
+ * This needs to be optimized.
+ */
+void  memset_io(unsigned long dst, int c, unsigned long count)
+{
+        while (count) {
+                count--;
+                writeb(c, dst);
+                dst++;
+        }
+}
index 1faa01ce33bd65863ab62552288d2b2429c7286e..9e57934505a7d2fc605734c351ac13b0a258ad84 100644 (file)
@@ -4,7 +4,8 @@
  *
  * Copyright (C) 2000  Niibe Yutaka
  *
- * Generic I/O routine.
+ * Generic I/O routine. These can be used where a machine specific version
+ * is not required.
  *
  * 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
@@ -14,6 +15,7 @@
 
 #include <linux/config.h>
 #include <asm/io.h>
+#include <asm/machvec.h>
 
 #if defined(__sh3__)
 /* I'm not sure SH7709 has this kind of bug */
 #define DUMMY_READ_AREA6         0xba000000
 #endif
 
-#define PORT2ADDR(x) (CONFIG_IOPORT_START+(x))
+#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x))
+
+unsigned long generic_io_base;
 
 static inline void delay(void)
 {
        ctrl_inw(0xa0000000);
 }
 
-unsigned long inb(unsigned int port)
+unsigned long generic_inb(unsigned int port)
 {
        return *(volatile unsigned char*)PORT2ADDR(port);
 }
 
-unsigned long inb_p(unsigned int port)
+unsigned long generic_inw(unsigned int port)
+{
+       return *(volatile unsigned short*)PORT2ADDR(port);
+}
+
+unsigned long generic_inl(unsigned int port)
+{
+       return *(volatile unsigned long*)PORT2ADDR(port);
+}
+
+unsigned long generic_inb_p(unsigned int port)
 {
        unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
 
@@ -41,23 +55,29 @@ unsigned long inb_p(unsigned int port)
        return v;
 }
 
-unsigned long inw(unsigned int port)
+unsigned long generic_inw_p(unsigned int port)
 {
-       return *(volatile unsigned short*)PORT2ADDR(port);
+       unsigned long v = *(volatile unsigned short*)PORT2ADDR(port);
+
+       delay();
+       return v;
 }
 
-unsigned long inl(unsigned int port)
+unsigned long generic_inl_p(unsigned int port)
 {
-       return *(volatile unsigned long*)PORT2ADDR(port);
+       unsigned long v = *(volatile unsigned long*)PORT2ADDR(port);
+
+       delay();
+       return v;
 }
 
-void insb(unsigned int port, void *buffer, unsigned long count)
+void generic_insb(unsigned int port, void *buffer, unsigned long count)
 {
        unsigned char *buf=buffer;
        while(count--) *buf++=inb(port);
 }
 
-void insw(unsigned int port, void *buffer, unsigned long count)
+void generic_insw(unsigned int port, void *buffer, unsigned long count)
 {
        unsigned short *buf=buffer;
        while(count--) *buf++=inw(port);
@@ -66,7 +86,7 @@ void insw(unsigned int port, void *buffer, unsigned long count)
 #endif
 }
 
-void insl(unsigned int port, void *buffer, unsigned long count)
+void generic_insl(unsigned int port, void *buffer, unsigned long count)
 {
        unsigned long *buf=buffer;
        while(count--) *buf++=inl(port);
@@ -75,34 +95,46 @@ void insl(unsigned int port, void *buffer, unsigned long count)
 #endif
 }
 
-void outb(unsigned long b, unsigned int port)
+void generic_outb(unsigned long b, unsigned int port)
 {
        *(volatile unsigned char*)PORT2ADDR(port) = b;
 }
 
-void outb_p(unsigned long b, unsigned int port)
+void generic_outw(unsigned long b, unsigned int port)
+{
+       *(volatile unsigned short*)PORT2ADDR(port) = b;
+}
+
+void generic_outl(unsigned long b, unsigned int port)
+{
+        *(volatile unsigned long*)PORT2ADDR(port) = b;
+}
+
+void generic_outb_p(unsigned long b, unsigned int port)
 {
        *(volatile unsigned char*)PORT2ADDR(port) = b;
        delay();
 }
 
-void outw(unsigned long b, unsigned int port)
+void generic_outw_p(unsigned long b, unsigned int port)
 {
        *(volatile unsigned short*)PORT2ADDR(port) = b;
+       delay();
 }
 
-void outl(unsigned long b, unsigned int port)
+void generic_outl_p(unsigned long b, unsigned int port)
 {
-        *(volatile unsigned long*)PORT2ADDR(port) = b;
+       *(volatile unsigned long*)PORT2ADDR(port) = b;
+       delay();
 }
 
-void outsb(unsigned int port, const void *buffer, unsigned long count)
+void generic_outsb(unsigned int port, const void *buffer, unsigned long count)
 {
        const unsigned char *buf=buffer;
        while(count--) outb(*buf++, port);
 }
 
-void outsw(unsigned int port, const void *buffer, unsigned long count)
+void generic_outsw(unsigned int port, const void *buffer, unsigned long count)
 {
        const unsigned short *buf=buffer;
        while(count--) outw(*buf++, port);
@@ -111,7 +143,7 @@ void outsw(unsigned int port, const void *buffer, unsigned long count)
 #endif
 }
 
-void outsl(unsigned int port, const void *buffer, unsigned long count)
+void generic_outsl(unsigned int port, const void *buffer, unsigned long count)
 {
        const unsigned long *buf=buffer;
        while(count--) outl(*buf++, port);
@@ -119,3 +151,52 @@ void outsl(unsigned int port, const void *buffer, unsigned long count)
        ctrl_inb (DUMMY_READ_AREA6);
 #endif
 }
+
+unsigned long generic_readb(unsigned long addr)
+{
+       return *(volatile unsigned char*)addr;
+}
+
+unsigned long generic_readw(unsigned long addr)
+{
+       return *(volatile unsigned short*)addr;
+}
+
+unsigned long generic_readl(unsigned long addr)
+{
+       return *(volatile unsigned long*)addr;
+}
+
+void generic_writeb(unsigned char b, unsigned long addr)
+{
+       *(volatile unsigned char*)addr = b;
+}
+
+void generic_writew(unsigned short b, unsigned long addr)
+{
+       *(volatile unsigned short*)addr = b;
+}
+
+void generic_writel(unsigned int b, unsigned long addr)
+{
+        *(volatile unsigned long*)addr = b;
+}
+
+void * generic_ioremap(unsigned long offset, unsigned long size)
+{
+       return (void *) P2SEGADDR(offset);
+}
+
+void * generic_ioremap_nocache (unsigned long offset, unsigned long size)
+{
+       return (void *) P2SEGADDR(offset);
+}
+
+void generic_iounmap(void *addr)
+{
+}
+
+unsigned long generic_isa_port2addr(unsigned long offset)
+{
+       return offset + generic_io_base;
+}
index 7c655942b6601e82cc35d7a3d9cca459d086d08f..3fbe6f2d0af30f8ebaaa79377a0c702711bc1729 100644 (file)
 
 static __inline__ unsigned long PORT2ADDR(unsigned long port)
 {
+       /* 16550A: HD64461 internal */
+       if (0x3f8<=port && port<=0x3ff)
+               return CONFIG_HD64461_IOBASE + 0x8000 + ((port-0x3f8)<<1);
+       if (0x2f8<=port && port<=0x2ff)
+               return CONFIG_HD64461_IOBASE + 0x7000 + ((port-0x2f8)<<1);
+
+#ifdef CONFIG_HD64461_ENABLER
+       /* NE2000: HD64461 PCMCIA channel 0 (I/O) */
+       if (0x300<=port && port<=0x31f)
+               return 0xba000000 + port;
+
+       /* ide0: HD64461 PCMCIA channel 1 (memory) */
+       /* On HP690, CF in slot 1 is configured as a memory card
+          device.  See CF+ and CompactFlash Specification for the
+          detail of CF's memory mapped addressing. */
+       if (0x1f0<=port && port<=0x1f7) return 0xb5000000 + port;
+       if (port == 0x3f6) return 0xb50001fe;
+#endif
+
+       /* ??? */
+       if (port < 0x10000) return 0xa0000000 + port;
+
        /* HD64461 internal devices (0xb0000000) */
-       if (port < 0x10000) return CONFIG_HD64461_IOBASE + port;
+       if (port < 0x20000) return CONFIG_HD64461_IOBASE + port - 0x10000;
 
        /* PCMCIA channel 0, I/O (0xba000000) */
-       if (port < 0x20000) return 0xba000000 + port - 0x10000;
+       if (port < 0x30000) return 0xba000000 + port - 0x20000;
 
-       /* PCMCIA channel 1, memory (0xb5000000)
-          SH7709 cannot support I/O card attached to Area 5 */
-       if (port < 0x30000) return 0xb5000000 + port - 0x20000;
+       /* PCMCIA channel 1, memory (0xb5000000) */
+       if (port < 0x40000) return 0xb5000000 + port - 0x30000;
 
        /* Whole physical address space (0xa0000000) */
        return 0xa0000000 + (port & 0x1fffffff);
@@ -29,80 +50,80 @@ static inline void delay(void)
        ctrl_inw(0xa0000000);
 }
 
-unsigned long inb(unsigned int port)
+unsigned long hd64461_inb(unsigned int port)
 {
        return *(volatile unsigned char*)PORT2ADDR(port);
 }
 
-unsigned long inb_p(unsigned int port)
+unsigned long hd64461_inb_p(unsigned int port)
 {
        unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
        delay();
        return v;
 }
 
-unsigned long inw(unsigned int port)
+unsigned long hd64461_inw(unsigned int port)
 {
        return *(volatile unsigned short*)PORT2ADDR(port);
 }
 
-unsigned long inl(unsigned int port)
+unsigned long hd64461_inl(unsigned int port)
 {
        return *(volatile unsigned long*)PORT2ADDR(port);
 }
 
-void insb(unsigned int port, void *buffer, unsigned long count)
+void hd64461_insb(unsigned int port, void *buffer, unsigned long count)
 {
        unsigned char *buf=buffer;
        while(count--) *buf++=inb(port);
 }
 
-void insw(unsigned int port, void *buffer, unsigned long count)
+void hd64461_insw(unsigned int port, void *buffer, unsigned long count)
 {
        unsigned short *buf=buffer;
        while(count--) *buf++=inw(port);
 }
 
-void insl(unsigned int port, void *buffer, unsigned long count)
+void hd64461_insl(unsigned int port, void *buffer, unsigned long count)
 {
        unsigned long *buf=buffer;
        while(count--) *buf++=inl(port);
 }
 
-void outb(unsigned long b, unsigned int port)
+void hd64461_outb(unsigned long b, unsigned int port)
 {
        *(volatile unsigned char*)PORT2ADDR(port) = b;
 }
 
-void outb_p(unsigned long b, unsigned int port)
+void hd64461_outb_p(unsigned long b, unsigned int port)
 {
        *(volatile unsigned char*)PORT2ADDR(port) = b;
        delay();
 }
 
-void outw(unsigned long b, unsigned int port)
+void hd64461_outw(unsigned long b, unsigned int port)
 {
        *(volatile unsigned short*)PORT2ADDR(port) = b;
 }
 
-void outl(unsigned long b, unsigned int port)
+void hd64461_outl(unsigned long b, unsigned int port)
 {
         *(volatile unsigned long*)PORT2ADDR(port) = b;
 }
 
-void outsb(unsigned int port, const void *buffer, unsigned long count)
+void hd64461_outsb(unsigned int port, const void *buffer, unsigned long count)
 {
        const unsigned char *buf=buffer;
        while(count--) outb(*buf++, port);
 }
 
-void outsw(unsigned int port, const void *buffer, unsigned long count)
+void hd64461_outsw(unsigned int port, const void *buffer, unsigned long count)
 {
        const unsigned short *buf=buffer;
        while(count--) outw(*buf++, port);
 }
 
-void outsl(unsigned int port, const void *buffer, unsigned long count)
+void hd64461_outsl(unsigned int port, const void *buffer, unsigned long count)
 {
        const unsigned long *buf=buffer;
        while(count--) outl(*buf++, port);
index a16c4738d39e5fdf16c6d915a35b236bb9d67ffb..4d9eeca3b7e7b7a61e32108b2d7804b4970042ba 100644 (file)
@@ -56,7 +56,7 @@ shifted_port(unsigned int port)
   printk("bad PC-like io %s for port 0x%x at 0x%08x\n", \
         #name, (port), (__u32) __builtin_return_address(0))
 
-unsigned long inb(unsigned int port)
+unsigned long se_inb(unsigned int port)
 {
        if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
                return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
@@ -66,7 +66,7 @@ unsigned long inb(unsigned int port)
                return (*port2adr(port))&0xff; 
 }
 
-unsigned long inb_p(unsigned int port)
+unsigned long se_inb_p(unsigned int port)
 {
        unsigned long v;
 
@@ -80,7 +80,7 @@ unsigned long inb_p(unsigned int port)
        return v;
 }
 
-unsigned long inw(unsigned int port)
+unsigned long se_inw(unsigned int port)
 {
        if (port >= 0x2000 ||
            (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
@@ -90,13 +90,13 @@ unsigned long inw(unsigned int port)
        return 0;
 }
 
-unsigned long inl(unsigned int port)
+unsigned long se_inl(unsigned int port)
 {
        maybebadio(inl, port);
        return 0;
 }
 
-void outb(unsigned long value, unsigned int port)
+void se_outb(unsigned long value, unsigned int port)
 {
        if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
                *(__u8 *)(sh_pcic_io_wbase + port) = value; 
@@ -106,7 +106,7 @@ void outb(unsigned long value, unsigned int port)
                *(port2adr(port)) = value;
 }
 
-void outb_p(unsigned long value, unsigned int port)
+void se_outb_p(unsigned long value, unsigned int port)
 {
        if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
                *(__u8 *)(sh_pcic_io_wbase + port) = value; 
@@ -117,7 +117,7 @@ void outb_p(unsigned long value, unsigned int port)
        delay();
 }
 
-void outw(unsigned long value, unsigned int port)
+void se_outw(unsigned long value, unsigned int port)
 {
        if (port >= 0x2000 ||
            (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
@@ -126,12 +126,12 @@ void outw(unsigned long value, unsigned int port)
                maybebadio(outw, port);
 }
 
-void outl(unsigned long value, unsigned int port)
+void se_outl(unsigned long value, unsigned int port)
 {
        maybebadio(outl, port);
 }
 
-void insb(unsigned int port, void *addr, unsigned long count)
+void se_insb(unsigned int port, void *addr, unsigned long count)
 {
        volatile __u16 *p = port2adr(port);
 
@@ -148,19 +148,19 @@ void insb(unsigned int port, void *addr, unsigned long count)
        }
 }
 
-void insw(unsigned int port, void *addr, unsigned long count)
+void se_insw(unsigned int port, void *addr, unsigned long count)
 {
        volatile __u16 *p = port2adr(port);
        while (count--)
                *((__u16 *) addr)++ = *p;
 }
 
-void insl(unsigned int port, void *addr, unsigned long count)
+void se_insl(unsigned int port, void *addr, unsigned long count)
 {
        maybebadio(insl, port);
 }
 
-void outsb(unsigned int port, const void *addr, unsigned long count)
+void se_outsb(unsigned int port, const void *addr, unsigned long count)
 {
        volatile __u16 *p = port2adr(port);
 
@@ -177,24 +177,54 @@ void outsb(unsigned int port, const void *addr, unsigned long count)
        }
 }
 
-void outsw(unsigned int port, const void *addr, unsigned long count)
+void se_outsw(unsigned int port, const void *addr, unsigned long count)
 {
        volatile __u16 *p = port2adr(port);
        while (count--)
                *p = *((__u16 *) addr)++;
 }
 
-void outsl(unsigned int port, const void *addr, unsigned long count)
+void se_outsl(unsigned int port, const void *addr, unsigned long count)
 {
        maybebadio(outsw, port);
 }
+
+unsigned long se_readb(unsigned long addr)
+{
+       return *(volatile unsigned char*)addr;
+}
+
+unsigned long se_readw(unsigned long addr)
+{
+       return *(volatile unsigned short*)addr;
+}
+
+unsigned long se_readl(unsigned long addr)
+{
+       return *(volatile unsigned long*)addr;
+}
+
+void se_writeb(unsigned char b, unsigned long addr)
+{
+       *(volatile unsigned char*)addr = b;
+}
+
+void se_writew(unsigned short b, unsigned long addr)
+{
+       *(volatile unsigned short*)addr = b;
+}
+
+void se_writel(unsigned int b, unsigned long addr)
+{
+        *(volatile unsigned long*)addr = b;
+}
 \f
 /* Map ISA bus address to the real address. Only for PCMCIA.  */
 
 /* ISA page descriptor.  */
 static __u32 sh_isa_memmap[256];
 
-int
+static int
 sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
 {
        int idx;
@@ -212,7 +242,7 @@ sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
 }
 
 unsigned long
-sh_isa_slot(unsigned long offset)
+se_isa_port2addr(unsigned long offset)
 {
        int idx;
 
diff --git a/arch/sh/kernel/io_unknown.c b/arch/sh/kernel/io_unknown.c
new file mode 100644 (file)
index 0000000..a0407ca
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * linux/arch/sh/kernel/io_unknown.c
+ *
+ * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * I/O routine for unknown hardware.
+ */
+
+static unsigned int unknown_handler(void)
+{
+       return 0;
+}
+
+#define UNKNOWN_ALIAS(fn) \
+       void unknown_##fn(void) __attribute__ ((alias ("unknown_handler")));
+
+UNKNOWN_ALIAS(inb)
+UNKNOWN_ALIAS(inw)
+UNKNOWN_ALIAS(inl)
+UNKNOWN_ALIAS(outb)
+UNKNOWN_ALIAS(outw)
+UNKNOWN_ALIAS(outl)
+UNKNOWN_ALIAS(inb_p)
+UNKNOWN_ALIAS(inw_p)
+UNKNOWN_ALIAS(inl_p)
+UNKNOWN_ALIAS(outb_p)
+UNKNOWN_ALIAS(outw_p)
+UNKNOWN_ALIAS(outl_p)
+UNKNOWN_ALIAS(insb)
+UNKNOWN_ALIAS(insw)
+UNKNOWN_ALIAS(insl)
+UNKNOWN_ALIAS(outsb)
+UNKNOWN_ALIAS(outsw)
+UNKNOWN_ALIAS(outsl)
+UNKNOWN_ALIAS(readb)
+UNKNOWN_ALIAS(readw)
+UNKNOWN_ALIAS(readl)
+UNKNOWN_ALIAS(writeb)
+UNKNOWN_ALIAS(writew)
+UNKNOWN_ALIAS(writel)
+UNKNOWN_ALIAS(isa_port2addr)
+UNKNOWN_ALIAS(ioremap)
+UNKNOWN_ALIAS(ioremap_nocache)
+UNKNOWN_ALIAS(iounmap)
index a353b0995100734556250b337673108409eaf0cc..6451c4c9effee2ef227134923823d3513fd9ac5e 100644 (file)
 #include <asm/irq.h>
 #include <linux/irq.h>
 
-#ifdef CONFIG_HD64461
-#include <asm/hd64461.h>
-#endif
-
 /*
  * Micro-access to controllers is serialized over the whole
  * system. We never hold this lock when we call the actual
@@ -94,6 +90,7 @@ struct hw_interrupt_type no_irq_type = {
  * Generic, controller-independent functions:
  */
 
+#if defined(CONFIG_PROC_FS)
 int get_irq_list(char *buf)
 {
        int i, j;
@@ -105,7 +102,7 @@ int get_irq_list(char *buf)
                p += sprintf(p, "CPU%d       ",j);
        *p++ = '\n';
 
-       for (i = 0 ; i < NR_IRQS ; i++) {
+       for (i = 0 ; i < ACTUAL_NR_IRQS ; i++) {
                action = irq_desc[i].action;
                if (!action) 
                        continue;
@@ -120,6 +117,7 @@ int get_irq_list(char *buf)
        }
        return p - buf;
 }
+#endif
 
 /*
  * This should really return information about whether
@@ -243,18 +241,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
                     "shlr      %0\n\t"
                     "add       #-16, %0\n\t"
                     :"=z" (irq));
-#if defined(CONFIG_HD64461)
-       if (irq == CONFIG_HD64461_IRQ) {
-               unsigned short bit;
-               unsigned short nirr = inw(HD64461_NIRR);
-               unsigned short nimr = inw(HD64461_NIMR);
-               nirr &= ~nimr;
-               for (bit = 1, irq = 0; irq < 16; bit <<= 1, irq++)
-                       if (nirr & bit) break;
-               if (irq == 16) irq = CONFIG_HD64461_IRQ;
-               else irq += HD64461_IRQBASE;
-       }
-#endif
+       irq = irq_demux(irq);
 
        kstat.irqs[cpu][irq]++;
        desc = irq_desc + irq;
@@ -330,7 +317,7 @@ int request_irq(unsigned int irq,
        int retval;
        struct irqaction * action;
 
-       if (irq >= NR_IRQS)
+       if (irq >= ACTUAL_NR_IRQS)
                return -EINVAL;
        if (!handler)
                return -EINVAL;
@@ -358,7 +345,7 @@ void free_irq(unsigned int irq, void *dev_id)
        struct irqaction **p;
        unsigned long flags;
 
-       if (irq >= NR_IRQS)
+       if (irq >= ACTUAL_NR_IRQS)
                return;
 
        spin_lock_irqsave(&irq_controller_lock,flags);
@@ -408,7 +395,7 @@ unsigned long probe_irq_on(void)
        for (i = NR_IRQS-1; i > 0; i--) {
                if (!irq_desc[i].action) {
                        irq_desc[i].status |= IRQ_AUTODETECT | IRQ_WAITING;
-                       if(irq_desc[i].handler->startup(i))
+                       if (irq_desc[i].handler->startup(i))
                                irq_desc[i].status |= IRQ_PENDING;
                }
        }
@@ -430,7 +417,7 @@ unsigned long probe_irq_on(void)
 
                if (!(status & IRQ_AUTODETECT))
                        continue;
-               
+
                /* It triggered already - consider it spurious. */
                if (!(status & IRQ_WAITING)) {
                        irq_desc[i].status = status & ~IRQ_AUTODETECT;
index 7237ba3b5e26cb7b99019e250c9cd3b205645afd..8ac95823b6adf45f4533afce8531adbc3c3126da 100644 (file)
@@ -8,6 +8,9 @@
  *
  */
 
+/* NOTE: Will not work on level 15 */
+
+
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/kernel_stat.h>
@@ -71,7 +74,7 @@ void static inline set_interrupt_registers(int ip)
                     : "r" (~0xf0), "r" (ip << 4));
 }
 
-void disable_imask_irq(unsigned int irq)
+static void disable_imask_irq(unsigned int irq)
 {
        clear_bit(irq, &imask_mask);
        if (interrupt_priority < IMASK_PRIORITY - irq)
index 8b6b0f5ee17a153f23b9f0b6a0295dfa8611d59c..f229e8a12f58bbe0eafc81a71968a739f43cf7e7 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/machvec.h>
 
 struct ipr_data {
        unsigned int addr;      /* Address of Interrupt Priority Register */
@@ -29,15 +30,8 @@ struct ipr_data {
 };
 static struct ipr_data ipr_data[NR_IRQS];
 
-void set_ipr_data(unsigned int irq, unsigned int addr, int pos, int priority)
-{
-       ipr_data[irq].addr = addr;
-       ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */
-       ipr_data[irq].priority = priority;
-}
-
 static void enable_ipr_irq(unsigned int irq);
-void disable_ipr_irq(unsigned int irq);
+static void disable_ipr_irq(unsigned int irq);
 
 /* shutdown is same as "disable" */
 #define shutdown_ipr_irq disable_ipr_irq
@@ -61,7 +55,7 @@ static struct hw_interrupt_type ipr_irq_type = {
        end_ipr_irq
 };
 
-void disable_ipr_irq(unsigned int irq)
+static void disable_ipr_irq(unsigned int irq)
 {
        unsigned long val, flags;
        unsigned int addr = ipr_data[irq].addr;
@@ -90,18 +84,11 @@ static void enable_ipr_irq(unsigned int irq)
        restore_flags(flags);
 }
 
-void make_ipr_irq(unsigned int irq)
-{
-       disable_irq_nosync(irq);
-       irq_desc[irq].handler = &ipr_irq_type;
-       disable_ipr_irq(irq);
-}
-
 static void mask_and_ack_ipr(unsigned int irq)
 {
        disable_ipr_irq(irq);
 
-#ifdef CONFIG_CPU_SUBTYPE_SH7709
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
        /* This is needed when we use edge triggered setting */
        /* XXX: Is it really needed? */
        if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) {
@@ -118,18 +105,39 @@ static void end_ipr_irq(unsigned int irq)
        enable_ipr_irq(irq);
 }
 
+void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority)
+{
+       disable_irq_nosync(irq);
+       ipr_data[irq].addr = addr;
+       ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */
+       ipr_data[irq].priority = priority;
+
+       irq_desc[irq].handler = &ipr_irq_type;
+       disable_ipr_irq(irq);
+}
+
 void __init init_IRQ(void)
 {
-       int i;
+       make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
+       make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
 
-       for (i = TIMER_IRQ; i < NR_IRQS; i++) {
-               irq_desc[i].handler = &ipr_irq_type;
-       }
+       make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+       make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+       make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+
+#ifdef SCIF_ERI_IRQ
+       make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+       make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+       make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+#endif
 
-       set_ipr_data(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
-       set_ipr_data(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
+#ifdef IRDA_ERI_IRQ
+       make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+       make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+       make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+#endif
 
-#ifdef CONFIG_CPU_SUBTYPE_SH7709
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
        /*
         * Initialize the Interrupt Controller (INTC)
         * registers to their power on values
@@ -161,11 +169,16 @@ void __init init_IRQ(void)
         * You should set corresponding bits of PFC to "00"
         * to enable these interrupts.
         */
-       set_ipr_data(IRQ0_IRQ, IRQ0_IRP_ADDR, IRQ0_IRP_POS, IRQ0_PRIORITY);
-       set_ipr_data(IRQ1_IRQ, IRQ1_IRP_ADDR, IRQ1_IRP_POS, IRQ1_PRIORITY);
-       set_ipr_data(IRQ2_IRQ, IRQ2_IRP_ADDR, IRQ2_IRP_POS, IRQ2_PRIORITY);
-       set_ipr_data(IRQ3_IRQ, IRQ3_IRP_ADDR, IRQ3_IRP_POS, IRQ3_PRIORITY);
-       set_ipr_data(IRQ4_IRQ, IRQ4_IRP_ADDR, IRQ4_IRP_POS, IRQ4_PRIORITY);
-       set_ipr_data(IRQ5_IRQ, IRQ5_IRP_ADDR, IRQ5_IRP_POS, IRQ5_PRIORITY);
-#endif /* CONFIG_CPU_SUBTYPE_SH7709 */
+       make_ipr_irq(IRQ0_IRQ, IRQ0_IRP_ADDR, IRQ0_IRP_POS, IRQ0_PRIORITY);
+       make_ipr_irq(IRQ1_IRQ, IRQ1_IRP_ADDR, IRQ1_IRP_POS, IRQ1_PRIORITY);
+       make_ipr_irq(IRQ2_IRQ, IRQ2_IRP_ADDR, IRQ2_IRP_POS, IRQ2_PRIORITY);
+       make_ipr_irq(IRQ3_IRQ, IRQ3_IRP_ADDR, IRQ3_IRP_POS, IRQ3_PRIORITY);
+       make_ipr_irq(IRQ4_IRQ, IRQ4_IRP_ADDR, IRQ4_IRP_POS, IRQ4_PRIORITY);
+       make_ipr_irq(IRQ5_IRQ, IRQ5_IRP_ADDR, IRQ5_IRP_POS, IRQ5_PRIORITY);
+#endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 */
+
+       /* Perform the machine specific initialisation */
+       if (sh_mv.mv_init_irq != NULL) {
+               sh_mv.mv_init_irq();
+       }
 }
diff --git a/arch/sh/kernel/led_se.c b/arch/sh/kernel/led_se.c
new file mode 100644 (file)
index 0000000..0476f1b
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * linux/arch/sh/kernel/led_se.c
+ *
+ * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * This file contains Solution Engine specific LED code.
+ */
+
+#include <linux/config.h>
+
+static void mach_led(int position, int value)
+{
+       volatile unsigned short* p = (volatile unsigned short*)0xb0c00000;
+
+       if (value) {
+               *p |= (1<<8);
+       } else {
+               *p &= ~(1<<8);
+       }
+}
+
+#ifdef CONFIG_HEARTBEAT
+
+#include <linux/sched.h>
+
+/* Cycle the LED's in the clasic Knightrider/Sun pattern */
+void heartbeat_se(void)
+{
+       static unsigned int cnt = 0, period = 0;
+       volatile unsigned short* p = (volatile unsigned short*)0xb0c00000;
+       static unsigned bit = 0, up = 1;
+
+       cnt += 1;
+       if (cnt < period) {
+               return;
+       }
+
+       cnt = 0;
+
+       /* Go through the points (roughly!):
+        * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
+        */
+       period = 110 - ( (300<<FSHIFT)/
+                        ((avenrun[0]/5) + (3<<FSHIFT)) );
+
+       if (up) {
+               if (bit == 7) {
+                       bit--;
+                       up=0;
+               } else {
+                       bit ++;
+               }
+       } else {
+               if (bit == 0) {
+                       bit++;
+                       up=1;
+               } else {
+                       bit--;
+               }
+       }
+       *p = 1<<(bit+8);
+
+}
+#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/kernel/mach_hp600.c b/arch/sh/kernel/mach_hp600.c
new file mode 100644 (file)
index 0000000..6f68d1a
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * linux/arch/sh/kernel/mach_hp600.c
+ *
+ * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Machine vector for the HP600
+ */
+
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+
+#include <asm/io_hd64461.h>
+#include <asm/io_generic.h>
+#include <asm/irq.h>
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_hp600 __initmv = {
+       mv_name:                "HP600",
+
+       mv_nr_irqs:             80, /* HD64461_IRQBASE+16, see hd64461.h */
+
+       mv_inb:                 hd64461_inb,
+       mv_inw:                 hd64461_inw,
+       mv_inl:                 hd64461_inl,
+       mv_outb:                hd64461_outb,
+       mv_outw:                hd64461_outw,
+       mv_outl:                hd64461_outl,
+
+       mv_inb_p:               hd64461_inb_p,
+       mv_inw_p:               hd64461_inw,
+       mv_inl_p:               hd64461_inl,
+       mv_outb_p:              hd64461_outb_p,
+       mv_outw_p:              hd64461_outw,
+       mv_outl_p:              hd64461_outl,
+
+       mv_insb:                hd64461_insb,
+       mv_insw:                hd64461_insw,
+       mv_insl:                hd64461_insl,
+       mv_outsb:               hd64461_outsb,
+       mv_outsw:               hd64461_outsw,
+       mv_outsl:               hd64461_outsl,
+
+       mv_readb:               generic_readb,
+       mv_readw:               generic_readw,
+       mv_readl:               generic_readl,
+       mv_writeb:              generic_writeb,
+       mv_writew:              generic_writew,
+       mv_writel:              generic_writel,
+
+       mv_irq_demux:           hd64461_irq_demux,
+
+       mv_hw_hp600:            1,
+       mv_hw_hd64461:          1,
+};
+ALIAS_MV(hp600)
diff --git a/arch/sh/kernel/mach_se.c b/arch/sh/kernel/mach_se.c
new file mode 100644 (file)
index 0000000..ce142a3
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * linux/arch/sh/kernel/mach_se.c
+ *
+ * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Machine vector for the Hitachi SolutionEngine
+ */
+
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+
+#include <asm/io_se.h>
+
+void heartbeat_se(void);
+void setup_se(void);
+void init_se_IRQ(void);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_se __initmv = {
+       mv_name:                "SolutionEngine",
+
+#if defined(__SH4__)
+       mv_nr_irqs:             48,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
+       mv_nr_irqs:             32,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
+       mv_nr_irqs:             61,
+#endif
+
+       mv_inb:                 se_inb,
+       mv_inw:                 se_inw,
+       mv_inl:                 se_inl,
+       mv_outb:                se_outb,
+       mv_outw:                se_outw,
+       mv_outl:                se_outl,
+
+       mv_inb_p:               se_inb_p,
+       mv_inw_p:               se_inw,
+       mv_inl_p:               se_inl,
+       mv_outb_p:              se_outb_p,
+       mv_outw_p:              se_outw,
+       mv_outl_p:              se_outl,
+
+       mv_insb:                se_insb,
+       mv_insw:                se_insw,
+       mv_insl:                se_insl,
+       mv_outsb:               se_outsb,
+       mv_outsw:               se_outsw,
+       mv_outsl:               se_outsl,
+
+       mv_readb:               se_readb,
+       mv_readw:               se_readw,
+       mv_readl:               se_readl,
+       mv_writeb:              se_writeb,
+       mv_writew:              se_writew,
+       mv_writel:              se_writel,
+
+       mv_ioremap:             generic_ioremap,
+       mv_ioremap_nocache:     generic_ioremap_nocache,
+       mv_iounmap:             generic_iounmap,
+
+       mv_isa_port2addr:       se_isa_port2addr,
+
+       mv_init_arch:           setup_se,
+       mv_init_irq:            init_se_IRQ,
+#ifdef CONFIG_HEARTBEAT
+       mv_heartbeat:           heartbeat_se,
+#endif
+
+       mv_hw_se:               1,
+};
+ALIAS_MV(se)
diff --git a/arch/sh/kernel/mach_unknown.c b/arch/sh/kernel/mach_unknown.c
new file mode 100644 (file)
index 0000000..895a65c
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * linux/arch/sh/kernel/mach_unknown.c
+ *
+ * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Machine specific code for an unknown machine (internal peripherials only)
+ */
+
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+
+#include <asm/io_unknown.h>
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_unknown __initmv = {
+       mv_name:                "Unknown",
+
+#if defined(__SH4__)
+       mv_nr_irqs:             48,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
+       mv_nr_irqs:             32,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
+       mv_nr_irqs:             61,
+#endif
+
+       mv_inb:                 unknown_inb,
+       mv_inw:                 unknown_inw,
+       mv_inl:                 unknown_inl,
+       mv_outb:                unknown_outb,
+       mv_outw:                unknown_outw,
+       mv_outl:                unknown_outl,
+
+       mv_inb_p:               unknown_inb_p,
+       mv_inw_p:               unknown_inw_p,
+       mv_inl_p:               unknown_inl_p,
+       mv_outb_p:              unknown_outb_p,
+       mv_outw_p:              unknown_outw_p,
+       mv_outl_p:              unknown_outl_p,
+
+       mv_insb:                unknown_insb,
+       mv_insw:                unknown_insw,
+       mv_insl:                unknown_insl,
+       mv_outsb:               unknown_outsb,
+       mv_outsw:               unknown_outsw,
+       mv_outsl:               unknown_outsl,
+
+       mv_readb:               unknown_readb,
+       mv_readw:               unknown_readw,
+       mv_readl:               unknown_readl,
+       mv_writeb:              unknown_writeb,
+       mv_writew:              unknown_writew,
+       mv_writel:              unknown_writel,
+
+       mv_ioremap:             unknown_ioremap,
+       mv_ioremap_nocache:     unknown_ioremap_nocache,
+       mv_iounmap:             unknown_iounmap,
+
+       mv_isa_port2addr:       unknown_isa_port2addr,
+};
+ALIAS_MV(unknown)
index 3613596f7246f489c3029b6e90f28f2d730b42f9..a4a6c6918f26b7f2efe2eafcf2856f23da8391ab 100644 (file)
@@ -4,9 +4,22 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/errno.h>
+#include <asm/machvec.h>
 
-unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
-                            unsigned long start, unsigned long size)
+void __init pcibios_init(void)
 {
-       return start;
+       if (sh_mv.mv_init_pci != NULL) {
+               sh_mv.mv_init_pci();
+       }
 }
+
+/* Haven't done anything here as yet */
+char * __init pcibios_setup(char *str)
+{
+       return str;
+}
+
+/* We don't have anything here to fixup */
+struct pci_fixup pcibios_fixups[] = {
+       {0, 0, 0, NULL}
+};
index c958745b59b61126e3023160080d1a2902f7c32f..f733501c1cc674877bc20709290a20db2bf79d80 100644 (file)
@@ -12,6 +12,8 @@
 #include <asm/semaphore.h>
 #include <asm/semaphore-helper.h>
 
+spinlock_t semaphore_wake_lock;
+
 /*
  * Semaphores are implemented using a two-way counter:
  * The "count" variable is decremented for each process
index be56f8570491f086cde7732f670c33f381f798aa..aaea2e6df23d881777a00f45afdff9b817941d2d 100644 (file)
 #endif
 #include <linux/bootmem.h>
 #include <linux/console.h>
+#include <linux/ctype.h>
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/io_generic.h>
 #include <asm/smp.h>
+#include <asm/machvec.h>
 #ifdef CONFIG_SH_EARLY_PRINTK
 #include <asm/sh_bios.h>
 #endif
@@ -53,10 +56,18 @@ extern int rd_prompt;               /* 1 = prompt for ramdisk, 0 = don't prompt */
 extern int rd_image_start;     /* starting block # of image */
 #endif
 
+#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
+struct sh_machine_vector sh_mv;
+#endif
+
 extern void fpu_init(void);
 extern int root_mountflags;
 extern int _text, _etext, _edata, _end;
 
+#define MV_NAME_SIZE 32
+
+static struct sh_machine_vector* __init get_mv_byname(const char* name);
+
 /*
  * This is set up by the setup-routine at boot-time
  */
@@ -180,8 +191,10 @@ void sh_console_unregister(void)
 
 #endif
 
-
-static inline void parse_mem_cmdline (char ** cmdline_p)
+static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
+                                 struct sh_machine_vector** mvp,
+                                 unsigned long *mv_io_base,
+                                 int *mv_mmio_enable)
 {
        char c = ' ', *to = command_line, *from = COMMAND_LINE;
        int len = 0;
@@ -208,6 +221,35 @@ static inline void parse_mem_cmdline (char ** cmdline_p)
                                memory_end = memory_start + mem_size;
                        }
                }
+               if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
+                       char* mv_end;
+                       char* mv_comma;
+                       int mv_len;
+                       if (to != command_line)
+                               to--;
+                       from += 6;
+                       mv_end = strchr(from, ' ');
+                       if (mv_end == NULL)
+                               mv_end = from + strlen(from);
+
+                       mv_comma = strchr(from, ',');
+                       if ((mv_comma != NULL) && (mv_comma < mv_end)) {
+                               int ints[3];
+                               get_options(mv_comma+1, ARRAY_SIZE(ints), ints);
+                               *mv_io_base = ints[1];
+                               *mv_mmio_enable = ints[2];
+                               mv_len = mv_comma - from;
+                       } else {
+                               mv_len = mv_end - from;
+                       }
+                       if (mv_len > (MV_NAME_SIZE-1))
+                               mv_len = MV_NAME_SIZE-1;
+                       memcpy(mv_name, from, mv_len);
+                       mv_name[mv_len] = '\0';
+                       from = mv_end;
+
+                       *mvp = get_mv_byname(mv_name);
+               }
                c = *(from++);
                if (!c)
                        break;
@@ -221,6 +263,10 @@ static inline void parse_mem_cmdline (char ** cmdline_p)
 
 void __init setup_arch(char **cmdline_p)
 {
+       struct sh_machine_vector *mv = NULL;
+       char mv_name[MV_NAME_SIZE] = "";
+       unsigned long mv_io_base = 0;
+       int mv_mmio_enable = 0;
        unsigned long bootmap_size;
        unsigned long start_pfn, max_pfn, max_low_pfn;
 
@@ -248,7 +294,58 @@ void __init setup_arch(char **cmdline_p)
        data_resource.start = virt_to_bus(&_etext);
        data_resource.end = virt_to_bus(&_edata)-1;
 
-       parse_mem_cmdline(cmdline_p);
+       parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable);
+
+#ifdef CONFIG_SH_GENERIC
+       if (mv == NULL) {
+               extern struct sh_machine_vector mv_unknown;
+               mv = &mv_unknown;
+               if (*mv_name != '\0') {
+                       printk("Warning: Unsupported machine %s, using unknown\n",
+                              mv_name);
+               }
+       }
+       sh_mv = *mv;
+#endif
+#ifdef CONFIG_SH_UNKNOWN
+       sh_mv = mv_unknown;
+#endif
+
+#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
+       if (mv_io_base != 0) {
+               sh_mv.mv_inb = generic_inb;
+               sh_mv.mv_inw = generic_inw;
+               sh_mv.mv_inl = generic_inl;
+               sh_mv.mv_outb = generic_outb;
+               sh_mv.mv_outw = generic_outw;
+               sh_mv.mv_outl = generic_outl;
+
+               sh_mv.mv_inb_p = generic_inb_p;
+               sh_mv.mv_inw_p = generic_inw_p;
+               sh_mv.mv_inl_p = generic_inl_p;
+               sh_mv.mv_outb_p = generic_outb_p;
+               sh_mv.mv_outw_p = generic_outw_p;
+               sh_mv.mv_outl_p = generic_outl_p;
+
+               sh_mv.mv_insb = generic_insb;
+               sh_mv.mv_insw = generic_insw;
+               sh_mv.mv_insl = generic_insl;
+               sh_mv.mv_outsb = generic_outsb;
+               sh_mv.mv_outsw = generic_outsw;
+               sh_mv.mv_outsl = generic_outsl;
+
+               sh_mv.mv_isa_port2addr = generic_isa_port2addr;
+               generic_io_base = mv_io_base;
+       }
+       if (mv_mmio_enable != 0) {
+               sh_mv.mv_readb = generic_readb;
+               sh_mv.mv_readw = generic_readw;
+               sh_mv.mv_readl = generic_readl;
+               sh_mv.mv_writeb = generic_writeb;
+               sh_mv.mv_writew = generic_writew;
+               sh_mv.mv_writel = generic_writel;
+       }
+#endif
 
 #define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
 #define PFN_DOWN(x)    ((x) >> PAGE_SHIFT)
@@ -358,6 +455,11 @@ void __init setup_arch(char **cmdline_p)
 #endif
 #endif
 
+       /* Perform the machine specific initialisation */
+       if (sh_mv.mv_init_arch != NULL) {
+               sh_mv.mv_init_arch();
+       }
+
 #if defined(__SH4__)
        /* We already grab/initialized FPU in head.S.  Make it consisitent. */
        init_task.used_math = 1;
@@ -366,10 +468,32 @@ void __init setup_arch(char **cmdline_p)
        paging_init();
 }
 
+struct sh_machine_vector* __init get_mv_byname(const char* name)
+{
+       extern int strcasecmp(const char *, const char *);
+       extern long __machvec_start, __machvec_end;
+       struct sh_machine_vector *all_vecs =
+               (struct sh_machine_vector *)&__machvec_start;
+
+       int i, n = ((unsigned long)&__machvec_end
+                   - (unsigned long)&__machvec_start)/
+               sizeof(struct sh_machine_vector);
+
+       for (i = 0; i < n; ++i) {
+               struct sh_machine_vector *mv = &all_vecs[i];
+               if (mv == NULL)
+                       continue;
+               if (strcasecmp(name, mv->mv_name) == 0) {
+                       return mv;
+               }
+       }
+       return NULL;
+}
+
 /*
  *     Get CPU information for use by the procfs.
  */
-
+#ifdef CONFIG_PROC_FS
 int get_cpuinfo(char *buffer)
 {
        char *p = buffer;
@@ -384,6 +508,7 @@ int get_cpuinfo(char *buffer)
        p += sprintf(p, "bogomips\t: %lu.%02lu\n\n",
                     (loops_per_sec+2500)/500000,
                     ((loops_per_sec+2500)/5000) % 100);
+       p += sprintf(p, "Machine: %s\n", sh_mv.mv_name);
 
 #define PRINT_CLOCK(name, value) \
        p += sprintf(p, name " clock: %d.%02dMHz\n", \
@@ -395,3 +520,4 @@ int get_cpuinfo(char *buffer)
 
        return p - buffer;
 }
+#endif
diff --git a/arch/sh/kernel/setup_cqreek.c b/arch/sh/kernel/setup_cqreek.c
new file mode 100644 (file)
index 0000000..3e04221
--- /dev/null
@@ -0,0 +1,224 @@
+/* $Id: setup_cqreek.c,v 1.1 2000/08/05 06:25:23 gniibe Exp $
+ *
+ * arch/sh/kernel/setup_cqreek.c
+ *
+ * Copyright (C) 2000  Niibe Yutaka
+ *
+ * CqREEK IDE/ISA Bridge Support.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/io_generic.h>
+#include <asm/irq.h>
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+
+#define BRIDGE_FEATURE         0x0002
+
+#define BRIDGE_IDE_CTRL                0x0018
+#define BRIDGE_IDE_INTR_LVL            0x001A
+#define BRIDGE_IDE_INTR_MASK   0x001C
+#define BRIDGE_IDE_INTR_STAT   0x001E
+
+#define BRIDGE_ISA_CTRL                0x0028
+#define BRIDGE_ISA_INTR_LVL            0x002A
+#define BRIDGE_ISA_INTR_MASK   0x002C
+#define BRIDGE_ISA_INTR_STAT   0x002E
+
+#define IDE_OFFSET 0xA4000000UL
+#define ISA_OFFSET 0xA4A00000UL
+\f
+static unsigned long cqreek_port2addr(unsigned long port)
+{
+       if (0x0000<=port && port<=0x0040)
+               return IDE_OFFSET + port;
+       if ((0x01f0<=port && port<=0x01f7) || port == 0x03f6)
+               return IDE_OFFSET + port;
+
+       return ISA_OFFSET + port;
+}
+
+static void disable_cqreek_irq(unsigned int irq)
+{
+       unsigned long flags;
+       unsigned short mask;
+
+       save_and_cli(flags);
+       /* Disable IRQ */
+       mask = inw(BRIDGE_ISA_INTR_MASK) & ~(1 << irq);
+       outw_p(mask, BRIDGE_ISA_INTR_MASK);
+       restore_flags(flags);
+}
+
+static void enable_cqreek_irq(unsigned int irq)
+{
+       unsigned long flags;
+       unsigned short mask;
+
+       save_and_cli(flags);
+       /* Enable IRQ */
+       mask = inw(BRIDGE_ISA_INTR_MASK) | (1 << irq);
+       outw_p(mask, BRIDGE_ISA_INTR_MASK);
+       restore_flags(flags);
+}
+
+#define CLEAR_AT_ACCEPT
+
+static void mask_and_ack_cqreek(unsigned int irq)
+{
+       inw(BRIDGE_ISA_INTR_STAT);
+       disable_cqreek_irq(irq);
+#ifdef CLEAR_AT_ACCEPT
+       /* Clear IRQ (it might be edge IRQ) */
+       outw_p((1<<irq), BRIDGE_ISA_INTR_STAT);
+#endif
+}
+
+static void end_cqreek_irq(unsigned int irq)
+{
+#ifndef CLEAR_AT_ACCEPT
+       /* Clear IRQ (it might be edge IRQ) */
+       outw_p((1<<irq), BRIDGE_ISA_INTR_STAT);
+#endif
+       enable_cqreek_irq(irq);
+}
+
+static unsigned int startup_cqreek_irq(unsigned int irq)
+{ 
+       enable_cqreek_irq(irq);
+       return 0;
+}
+
+static void shutdown_cqreek_irq(unsigned int irq)
+{
+       disable_cqreek_irq(irq);
+}
+
+static struct hw_interrupt_type cqreek_irq_type = {
+       "CQREEK-IRQ",
+       startup_cqreek_irq,
+       shutdown_cqreek_irq,
+       enable_cqreek_irq,
+       disable_cqreek_irq,
+       mask_and_ack_cqreek,
+       end_cqreek_irq
+};
+
+static int has_ide, has_isa;
+
+/* XXX: This is just for test for my NE2000 ISA board
+   What we really need is virtualized IRQ and demultiplexer like HP600 port */
+void __init init_cqreek_IRQ(void)
+{
+       if (has_ide)
+               make_ipr_irq(14, IDE_OFFSET+BRIDGE_IDE_INTR_LVL, 0, 0x0f-14);
+
+       if (has_isa) {
+               /* XXX: Err... we may need demultiplexer for ISA irq... */
+               irq_desc[10].handler = &cqreek_irq_type;
+               irq_desc[10].status = IRQ_DISABLED;
+               irq_desc[10].action = 0;
+               irq_desc[10].depth = 1;
+
+               disable_cqreek_irq(10);
+       }
+}
+
+/*
+ * Initialize the board
+ */
+void __init setup_cqreek(void)
+{
+       int i;
+/* udelay is not available at setup time yet... */
+#define DELAY() do {for (i=0; i<10000; i++) ctrl_inw(0xa0000000);} while(0)
+
+       if ((inw (BRIDGE_FEATURE) & 1)) { /* We have IDE interface */
+               outw_p(0, BRIDGE_IDE_INTR_LVL);
+               outw_p(0, BRIDGE_IDE_INTR_MASK);
+
+               outw_p(0, BRIDGE_IDE_CTRL);
+               DELAY();
+
+               outw_p(0x8000, BRIDGE_IDE_CTRL);
+               DELAY();
+
+               outw_p(0xffff, BRIDGE_IDE_INTR_STAT); /* Clear interrupt status */
+               outw_p(0x0f-14, BRIDGE_IDE_INTR_LVL); /* Use 14 IPR */
+               outw_p(1, BRIDGE_IDE_INTR_MASK); /* Enable interrupt */
+               has_ide=1;
+       }
+
+       if ((inw (BRIDGE_FEATURE) & 2)) { /* We have ISA interface */
+               outw_p(0, BRIDGE_ISA_INTR_LVL);
+               outw_p(0, BRIDGE_ISA_INTR_MASK);
+
+               outw_p(0, BRIDGE_ISA_CTRL);
+               DELAY();
+               outw_p(0x8000, BRIDGE_ISA_CTRL);
+               DELAY();
+
+               outw_p(0xffff, BRIDGE_ISA_INTR_STAT); /* Clear interrupt status */
+               outw_p(0x0f-10, BRIDGE_ISA_INTR_LVL); /* Use 10 IPR */
+               outw_p(0xfff8, BRIDGE_ISA_INTR_MASK); /* Enable interrupt */
+               has_isa=1;
+       }
+
+       printk(KERN_INFO "CqREEK Setup (IDE=%d, ISA=%d)...done\n", has_ide, has_isa);
+}
+\f
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_cqreek __initmv = {
+       mv_name:                "CqREEK",
+
+#if defined(__SH4__)
+       mv_nr_irqs:             48,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
+       mv_nr_irqs:             32,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
+       mv_nr_irqs:             61,
+#endif
+
+       mv_inb:                 generic_inb,
+       mv_inw:                 generic_inw,
+       mv_inl:                 generic_inl,
+       mv_outb:                generic_outb,
+       mv_outw:                generic_outw,
+       mv_outl:                generic_outl,
+
+       mv_inb_p:               generic_inb_p,
+       mv_inw_p:               generic_inw_p,
+       mv_inl_p:               generic_inl_p,
+       mv_outb_p:              generic_outb_p,
+       mv_outw_p:              generic_outw_p,
+       mv_outl_p:              generic_outl_p,
+
+       mv_insb:                generic_insb,
+       mv_insw:                generic_insw,
+       mv_insl:                generic_insl,
+       mv_outsb:               generic_outsb,
+       mv_outsw:               generic_outsw,
+       mv_outsl:               generic_outsl,
+
+       mv_readb:               generic_readb,
+       mv_readw:               generic_readw,
+       mv_readl:               generic_readl,
+       mv_writeb:              generic_writeb,
+       mv_writew:              generic_writew,
+       mv_writel:              generic_writel,
+
+       mv_init_arch:           setup_cqreek,
+       mv_init_irq:            init_cqreek_IRQ,
+
+       mv_port2addr:           cqreek_port2addr,
+       mv_isa_port2addr:       cqreek_port2addr,
+};
+ALIAS_MV(cqreek)
index 0ee07e887d84fb826a4bb398432505df7c6823fa..6132e420d59c5af1d0d4fdcad1b09b020f1caefa 100644 (file)
@@ -92,6 +92,20 @@ static void hd64461_interrupt(int irq, void *dev_id, struct pt_regs *regs)
               inw(HD64461_NIRR), inw(HD64461_NIMR));
 }
 
+int hd64461_irq_demux(int irq)
+{
+       if (irq == CONFIG_HD64461_IRQ) {
+               unsigned short bit;
+               unsigned short nirr = inw(HD64461_NIRR);
+               unsigned short nimr = inw(HD64461_NIMR);
+               nirr &= ~nimr;
+               for (bit = 1, irq = 0; irq < 16; bit <<= 1, irq++)
+                       if (nirr & bit) break;
+               if (irq == 16) irq = CONFIG_HD64461_IRQ;
+               else irq += HD64461_IRQBASE;
+       }
+       return irq;
+}
 
 static struct irqaction irq0  = { hd64461_interrupt, SA_INTERRUPT, 0, "HD64461", NULL, NULL};
 
@@ -100,10 +114,13 @@ int __init setup_hd64461(void)
 {
        int i;
 
+       if (!MACH_HD64461)
+               return 0;
+
        printk(KERN_INFO "HD64461 configured at 0x%x on irq %d(mapped into %d to %d)\n",
               CONFIG_HD64461_IOBASE, CONFIG_HD64461_IRQ,
               HD64461_IRQBASE, HD64461_IRQBASE+15);
-#if 1
+#ifdef CONFIG_CPU_SUBTYPE_SH7709
        /* IRQ line for HD64461 should be set level trigger mode("10"). */
        /* And this should be done earlier than the kernel starts. */
        ctrl_outw(0x0200, INTC_ICR1); /* when connected to IRQ4. */
index cd9436fff55e459567caf9b3ebd37b4421b4470d..8b2f599723fa8d5c2387541f115672ac177430e9 100644 (file)
@@ -73,10 +73,8 @@ static void __init init_smsc(void)
 /*
  * Initialize IRQ setting
  */
-static void __init init_se_IRQ(void)
+void __init init_se_IRQ(void)
 {
-       int i;
-
        /*
         * Super I/O (Just mimic PC):
         *  1: keyboard
@@ -88,43 +86,34 @@ static void __init init_se_IRQ(void)
         * 12: mouse
         * 14: ide0
         */
-       set_ipr_data(14, BCR_ILCRA, 2, 0x0f-14);
-       set_ipr_data(12, BCR_ILCRA, 1, 0x0f-12); 
-       set_ipr_data( 8, BCR_ILCRB, 1, 0x0f- 8); 
-       set_ipr_data( 6, BCR_ILCRC, 3, 0x0f- 6);
-       set_ipr_data( 5, BCR_ILCRC, 2, 0x0f- 5);
-       set_ipr_data( 4, BCR_ILCRC, 1, 0x0f- 4);
-       set_ipr_data( 3, BCR_ILCRC, 0, 0x0f- 3);
-       set_ipr_data( 1, BCR_ILCRD, 3, 0x0f- 1);
-
-       set_ipr_data(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */
-
-       set_ipr_data( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */
-       set_ipr_data(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */
-       set_ipr_data( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */
-       set_ipr_data( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */
+       make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14);
+       make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12); 
+       make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8); 
+       make_ipr_irq( 6, BCR_ILCRC, 3, 0x0f- 6);
+       make_ipr_irq( 5, BCR_ILCRC, 2, 0x0f- 5);
+       make_ipr_irq( 4, BCR_ILCRC, 1, 0x0f- 4);
+       make_ipr_irq( 3, BCR_ILCRC, 0, 0x0f- 3);
+       make_ipr_irq( 1, BCR_ILCRD, 3, 0x0f- 1);
+
+       make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */
+
+       make_ipr_irq( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */
+       make_ipr_irq(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */
+       make_ipr_irq( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */
+       make_ipr_irq( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */
 
        /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
        /* NOTE: #2 and #13 are not used on PC */
-       set_ipr_data(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */
-       set_ipr_data( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */
-
-       for (i = 0; i < 15; i++) {
-               make_ipr_irq(i);
-       }
+       make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */
+       make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */
 }
 
+
 /*
  * Initialize the board
  */
-int __init setup_se(void)
+void __init setup_se(void)
 {
-       init_se_IRQ();
        init_smsc();
        /* XXX: RTC setting comes here */
-
-       printk(KERN_INFO "Hitach SolutionEngine Setup...done\n");
-       return 0;
 }
-
-module_init(setup_se);
index a24b4a8427a4e6c30431e1b0b02c13cb48336334..12f71624911996cf0e20231bd11dc068eacd694b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: sh_bios.c,v 1.2 2000/07/26 04:37:32 gniibe Exp $
  *
  *  linux/arch/sh/kernel/sh_bios.c
  *  C interface for trapping into the standard LinuxSH BIOS.
index 221af3022170ed3229e0afeef90a698901220ff7..9bdddc9d9305784bbcfd3ac96022beef5d6795f4 100644 (file)
@@ -198,13 +198,16 @@ static inline int save_sigcontext_fpu(struct sigcontext *sc)
 {
        struct task_struct *tsk = current;
        unsigned long flags;
+       int val;
 
        if (!tsk->used_math) {
-               __copy_to_user(&sc->sc_ownedfp, 0, sizeof(int));
+         val = 0;
+               __copy_to_user(&sc->sc_ownedfp, &val, sizeof(int));
                return 0;
        }
 
-       __copy_to_user(&sc->sc_ownedfp, 1, sizeof(int));
+       val = 1;
+       __copy_to_user(&sc->sc_ownedfp, &val, sizeof(int));
 
        /* This will cause a "finit" to be triggered by the next
           attempted FPU operation by the 'current' process.
index 2c73255f4785551ed87af3c1adcfe675d2154b07..f1e8d28bf15d228cd8d6df3451e1946650a53ac3 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/delay.h>
+#include <asm/machvec.h>
 
 #include <linux/timex.h>
 #include <linux/irq.h>
@@ -226,6 +227,11 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
                sh_do_profile(regs->pc);
 #endif
 
+#ifdef CONFIG_HEARTBEAT
+       if (sh_mv.mv_heartbeat != NULL) 
+               sh_mv.mv_heartbeat();
+#endif
+
        /*
         * If we have an externally synchronized Linux clock, then update
         * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
@@ -441,11 +447,11 @@ void __init time_init(void)
                tmp  = (frqcr & 0x2000) >> 11;
                tmp |= frqcr & 0x0003;
                pfc = pfc_table[tmp];
-#ifdef CONFIG_SH_HP600
-               master_clock = cpu_clock/6;
-#else
-               master_clock = cpu_clock;
-#endif
+               if (MACH_HP600) {
+                       master_clock = cpu_clock/6;
+               } else {
+                       master_clock = cpu_clock;
+               }
                bus_clock = master_clock/pfc;
        }
 #elif defined(__SH4__)
index 7af24f1c3c0acde7c05b23cf111040c6d2352dd5..a0d344cb9749bd95e3fbafbfde83e6afb42c2199 100644 (file)
@@ -7,6 +7,6 @@
 
 L_TARGET = lib.a
 L_OBJS  = delay.o memcpy.o memset.o memmove.o memchr.o old-checksum.o \
-         checksum.o
+         checksum.o strcasecmp.o
 
 include $(TOPDIR)/Rules.make
index b34a65383df734400412fb1056db30008166f116..3317b3cccb36063e25ae70e0e5b0f65a8e57fb86 100644 (file)
@@ -185,15 +185,65 @@ ENTRY(csum_partial_copy_generic)
        mov.l   r5,@-r15
        mov.l   r6,@-r15
 
+       mov     #3, r0                  ! Check src and dest are equally aligned
+       mov     r4, r1
+       and     r0, r1
+       and     r5, r0
+       cmp/eq  r1, r0
+       bf      3f                      ! Different alignments, use slow version
+       tst     #1,r0                   ! Check dest word aligned
+       bf      3f                      ! If not, do it the slow way
+
        mov     #2,r0
-       tst     r0,r5                   ! Check alignment. 
+       tst     r0,r5                   ! Check dest alignment. 
        bt      2f                      ! Jump if alignment is ok.
        add     #-2,r6                  ! Alignment uses up two bytes.
        cmp/pz  r6                      ! Jump if we had at least two bytes.
        bt/s    1f
         clrt
        bra     4f
-        add    #2,r6                   ! $r6 was < 2.  Deal with it.
+        add    #2,r6                   ! $r6 was < 2.  Deal with it.
+
+3:     ! Handle different src and dest alinments.
+       ! This is not common, so simple byte by byte copy will do.
+       mov     r6, r2
+       shlr    r6
+       tst     r6, r6
+       bt      4f
+       clrt
+SRC(5: mov.b   @r4+,r0 )
+DST(   mov.b   r0,@r5  )
+       add     #1, r5
+SRC(   mov.b   @r4+,r1 )
+DST(   mov.b   r1,@r5  )
+       add     #1,r5
+
+       extu.b  r0,r0
+       extu.b  r1,r1
+#ifdef __LITTLE_ENDIAN__
+       shll8   r1
+#else
+       shll8   r0
+#endif
+       or      r1,r0   
+
+       addc    r0,r7
+       movt    r0
+       dt      r6
+       bf/s    5b
+        cmp/eq #1,r0
+       mov     #0,r0
+       addc    r0, r7
+
+       mov     r2, r0
+       tst     #1, r0
+       bt      7f      
+       bra     5f
+        clrt
+
+       ! src and dest equally aligned, but to a two byte boundary.
+       ! Handle first two bytes as a special case
+       .align  5
 SRC(1: mov.w   @r4+,r0 )
 DST(   mov.w   r0,@r5  )
        add     #2,r5
diff --git a/arch/sh/lib/strcasecmp.c b/arch/sh/lib/strcasecmp.c
new file mode 100644 (file)
index 0000000..4e57a21
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ *  linux/arch/alpha/lib/strcasecmp.c
+ */
+
+#include <linux/string.h>
+
+
+/* We handle nothing here except the C locale.  Since this is used in
+   only one place, on strings known to contain only 7 bit ASCII, this
+   is ok.  */
+
+int strcasecmp(const char *a, const char *b)
+{
+       int ca, cb;
+
+       do {
+               ca = *a++ & 0xff;
+               cb = *b++ & 0xff;
+               if (ca >= 'A' && ca <= 'Z')
+                       ca += 'a' - 'A';
+               if (cb >= 'A' && cb <= 'Z')
+                       cb += 'a' - 'A';
+       } while (ca == cb && ca != '\0');
+
+       return ca - cb;
+}
index 981c25380d76cf1c3c4c093a49dcea36e01c6576..1f1815600b80d30b8bd62bb1ef8f4923c5772f70 100644 (file)
@@ -8,6 +8,6 @@
 # Note 2! The CFLAGS definition is now in the main makefile...
 
 O_TARGET := mm.o
-O_OBJS  := init.o fault.o ioremap.o extable.o cache.o
+O_OBJS  := init.o fault.o extable.o cache.o # ioremap.o 
 
 include $(TOPDIR)/Rules.make
index 56f444bf41cb985e9c91cf3a8acd0dcdd0b0a5f6..af494b9a3a2e236576335777a663d90fd2080456 100644 (file)
@@ -207,6 +207,9 @@ static void icache_purge_range(unsigned long start, unsigned long end)
         * compared the tag of cache and if it's not matched, nothing
         * will be occurred.  (We can avoid flushing other caches.)
         * 
+        * NOTE: We can use A-bit feature here, because we have valid
+        * entriy in TLB (at least in UTLB), as dcache_wback_range is
+        * called before this function is called.
         */
        for (v = start; v < end; v+=L1_CACHE_BYTES) {
                addr = CACHE_IC_ADDRESS_ARRAY | (v&CACHE_IC_ENTRY_MASK)
@@ -225,8 +228,12 @@ static void icache_purge_range(unsigned long start, unsigned long end)
  */
 void flush_icache_range(unsigned long start, unsigned long end)
 {
+       unsigned long flags;
+
+       save_and_cli(flags);
        dcache_wback_range(start, end);
        icache_purge_range(start, end);
+       restore_flags(flags);
 }
 
 /*
@@ -238,11 +245,6 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *pg)
 {
        unsigned long phys, addr, data, i;
 
-       /*
-        * Alas, we don't know where the virtual address is,
-        * So, we can't use icache_purge_range().
-        */
-
        /* Physical address of this page */
        phys = (pg - mem_map)*PAGE_SIZE + __MEMORY_START;
 
@@ -259,6 +261,30 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *pg)
        back_to_P1();
 }
 
+/*
+ * Write back & invalidate the D-cache of the page.
+ * (To avoid "alias" issues)
+ */
+void flush_dcache_page(struct page *pg)
+{
+       unsigned long phys, addr, data, i;
+
+       /* Physical address of this page */
+       phys = (pg - mem_map)*PAGE_SIZE + __MEMORY_START;
+
+       jump_to_P2();
+       /* Loop all the D-cache */
+       for (i=0; i<CACHE_OC_NUM_ENTRIES; i++) {
+               addr = CACHE_OC_ADDRESS_ARRAY| (i<<CACHE_OC_ENTRY_SHIFT);
+               data = ctrl_inl(addr);
+               if ((data & CACHE_VALID) && (data&PAGE_MASK) == phys) {
+                       data &= ~(CACHE_VALID|CACHE_UPDATED);
+                       ctrl_outl(data, addr);
+               }
+       }
+       back_to_P1();
+}
+
 void flush_cache_all(void)
 {
        unsigned long addr, data, i;
@@ -298,56 +324,64 @@ void flush_cache_mm(struct mm_struct *mm)
        flush_cache_all();
 }
 
+/*
+ * Write back and invalidate D-caches.
+ *
+ * START, END: Virtual Address (U0 address)
+ *
+ * NOTE: We need to flush the _physical_ page entry.
+ * Flushing the cache lines for U0 only isn't enough.
+ * We need to flush for P1 too, which may contain aliases.
+ */
 void flush_cache_range(struct mm_struct *mm, unsigned long start,
                       unsigned long end)
 {
        /*
-        * Calling
-        *      dcache_flush_range(start, end);
-        * is not good for the purpose of this function.  That is,
-        * flushing cache lines indexed by the virtual address is not
-        * sufficient.
-        *
-        * Instead, we need to flush the relevant cache lines which
-        * hold the data of the corresponding physical memory, as we
-        * have "alias" issues.
-        *
-        * This is needed because, kernel accesses the memory through
-        * P1-area (and/or U0-area) and user-space accesses through U0-area.
-        * And P1-area and U0-area may use different cache lines for
-        * same physical memory.
+        * We could call flush_cache_page for the pages of these range,
+        * but it's not efficient (scan the caches all the time...).
         *
-        * If we would call dcache_flush_range(), the line of P1-area
-        * could remain in the cache, unflushed.
+        * We can't use A-bit magic, as there's the case we don't have
+        * valid entry on TLB.
         */
-       unsigned long addr, data, v;
-
-       start &= ~(L1_CACHE_BYTES-1);
-       jump_to_P2();
-
-       for (v = start; v < end; v+=L1_CACHE_BYTES) {
-               addr = CACHE_OC_ADDRESS_ARRAY |
-                       (v&CACHE_OC_ENTRY_PHYS_MASK) | 0x8 /* A-bit */;
-               data = (v&0xfffffc00); /* Update=0, Valid=0 */
-
-               /* Try all the cases for aliases */
-               ctrl_outl(data, addr);
-               ctrl_outl(data, addr | 0x1000);
-               ctrl_outl(data, addr | 0x2000);
-               ctrl_outl(data, addr | 0x3000);
-       }
-       back_to_P1();
+       flush_cache_all();
 }
 
+/*
+ * Write back and invalidate D-caches for the page.
+ *
+ * ADDR: Virtual Address (U0 address)
+ *
+ * NOTE: We need to flush the _physical_ page entry.
+ * Flushing the cache lines for U0 only isn't enough.
+ * We need to flush for P1 too, which may contain aliases.
+ */
 void flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
 {
-       /* XXX: Umm... this flush out all the cache lines.  Any improvement? */
-       flush_cache_range(vma->vm_mm, addr, addr+PAGE_SIZE);
+       pgd_t *dir;
+       pmd_t *pmd;
+       pte_t *pte;
+       pte_t entry;
+       unsigned long phys;
+       struct page *pg;
+
+       dir = pgd_offset(vma->vm_mm, addr);
+       pmd = pmd_offset(dir, addr);
+       if (pmd_none(*pmd))
+               return;
+       if (pmd_bad(*pmd))
+               return;
+       pte = pte_offset(pmd, addr);
+       entry = *pte;
+       if (pte_none(entry) || !pte_present(entry))
+               return;
+       phys = pte_val(entry)&PAGE_MASK;
+       pg = virt_to_page(__va(phys));
+       flush_dcache_page(pg);
 }
 
 /*
  * After accessing the memory from kernel space (P1-area), we need to 
- * write back the cache line, to avoid "alias" issues.
+ * write back the cache line to maintain DMA coherency.
  *
  * We search the D-cache to see if we have the entries corresponding to
  * the page, and if found, write back them.
index 9dd6ae4516967d4b2612e77bb5e355deda7e96d7..f2e342f0bef31e28281d968c4ab951792c0c041d 100644 (file)
@@ -115,7 +115,8 @@ static void handle_vmalloc_fault(struct mm_struct *mm, unsigned long address)
         * ITLB is not affected by "ldtlb" instruction.
         * So, we need to flush the entry by ourselves.
         */
-       __flush_tlb_page(mm, address&PAGE_MASK);
+       if (mm)
+               __flush_tlb_page(mm, address&PAGE_MASK);
 #endif
        update_mmu_cache(NULL, address, entry);
 }
@@ -281,15 +282,14 @@ void update_mmu_cache(struct vm_area_struct * vma,
        save_and_cli(flags);
 
 #if defined(__SH4__)
-       if ((vma->vm_flags & VM_SHARED)) {
+       if (vma && (vma->vm_flags & VM_SHARED)) {
+               struct page *pg;
+
                pteval = pte_val(pte);
                pteval &= PAGE_MASK; /* Physicall page address */
-
                __flush_tlb_phys(vma->vm_mm, pteval);
-
-               /* It would be good we had routine which takes
-                  physical memory as argument */
-               flush_cache_page(vma, address&PAGE_MASK);
+               pg = virt_to_page(__va(pteval));
+               flush_dcache_page(pg);
        }
 #endif
 
index 1a7c2e8206701fdf417f044b58bafe199f9c97de..ad1fc1c1b57616ab22ecdf0fcd7e8c04c1b53166 100644 (file)
@@ -61,6 +61,9 @@ SECTIONS
   __initcall_start = .;
   .initcall.init : { *(.initcall.init) }
   __initcall_end = .;
+  __machvec_start = .;
+  .machvec.init : { *(.machvec.init) }
+  __machvec_end = .;
   . = ALIGN(4096);
   __init_end = .;
 
index 570f8632585945dba70faefe65c18f3e5ef1b7e0..e603d2a641085fef5643d629d15d4b0ed4c8bbdb 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.99 2000/08/01 04:53:58 anton Exp $
+# $Id: config.in,v 1.100 2000/08/07 18:06:54 anton Exp $
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/config-language.txt.
 #
@@ -86,13 +86,23 @@ comment 'Block devices'
 
 bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD
 
-bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD
-if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then
-   tristate '  Linear (append) mode' CONFIG_MD_LINEAR
-   tristate '  RAID-0 (striping) mode' CONFIG_MD_STRIPED
-#   tristate '  RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING
-#   tristate '  RAID-4/RAID-5 mode' CONFIG_MD_RAID5
-fi
+tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
+dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
+
+#tristate 'Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM N
+#if [ "$CONFIG_BLK_DEV_LVM" != "n" ]; then
+#   bool '   LVM information in proc filesystem' CONFIG_LVM_PROC_FS Y
+#fi
+
+tristate 'Multiple devices driver support' CONFIG_BLK_DEV_MD
+dep_tristate '  Linear (append) mode' CONFIG_MD_LINEAR $CONFIG_BLK_DEV_MD
+dep_tristate '  RAID-0 (striping) mode' CONFIG_MD_RAID0 $CONFIG_BLK_DEV_MD
+dep_tristate '  RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD
+dep_tristate '  RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD
+#if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_RAID0" = "y" -o "$CONFIG_MD_RAID1" = "y" -o "$CONFIG_MD_RAID5" = "y" ]; then
+#        bool '  Boot support' CONFIG_MD_BOOT
+#        bool '  Auto Detect support' CONFIG_AUTODETECT_RAID
+#fi
 
 tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
 if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
@@ -100,9 +110,6 @@ if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
 fi
 dep_bool '  Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM
 
-tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
-tristate 'Network block device support' CONFIG_BLK_DEV_NBD
-
 endmenu
 
 if [ "$CONFIG_NET" = "y" ]; then
index c58948e7177e91bde99af3c61d8ef9944d9a8d79..8bac6f8e3bee09c93ec12e971eaee3098fc95f36 100644 (file)
@@ -2,6 +2,7 @@
 # Automatically generated make config: don't edit
 #
 CONFIG_UID16=y
+CONFIG_HIGHMEM=y
 
 #
 # Code maturity level options
@@ -108,14 +109,16 @@ CONFIG_SUN_AURORA=m
 # Block devices
 #
 CONFIG_BLK_DEV_FD=y
-CONFIG_BLK_DEV_MD=y
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
-CONFIG_MD_STRIPED=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID5=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_NBD=m
 
 #
 # Networking options
index ad74d0ed2a5f1603fa94ac12ff63ebc7b1dafe27..dedb18f01ed6e735b0576d6385fceca57a684936 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: generic.c,v 1.9 1999/12/27 06:30:03 anton Exp $
+/* $Id: generic.c,v 1.10 2000/08/09 00:00:15 davem Exp $
  * generic.c: Generic Sparc mm routines that are not dependent upon
  *            MMU type but are Sparc specific.
  *
index 3d42e0c630e7d750648cdbb15f6a3c018db85360..b0d45d82a60ede3908eeb8398765ce02c30923ec 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.89 2000/08/01 04:53:58 anton Exp $
+/*  $Id: init.c,v 1.90 2000/08/09 00:00:15 davem Exp $
  *  linux/arch/sparc/mm/init.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
index f395f06f540c49e655eeac26babba4b11ebf3e7e..1679384d6bf1a8055a0bd36af5c0aa8c6c95b6f5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: io-unit.c,v 1.21 2000/02/06 22:55:45 zaitcev Exp $
+/* $Id: io-unit.c,v 1.22 2000/08/09 00:00:15 davem Exp $
  * io-unit.c:  IO-UNIT specific routines for memory management.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek    (jj@sunsite.mff.cuni.cz)
index e48128479ca78f33f9dca671e14bdbfcd97a97d6..058fdd0d1781ab3b790c1083e8328a50208154e3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: iommu.c,v 1.19 2000/02/06 22:55:45 zaitcev Exp $
+/* $Id: iommu.c,v 1.20 2000/08/09 00:00:15 davem Exp $
  * iommu.c:  IOMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
index 7e76841de03495edc81d4189c0b8a523229d0a00..96fbf1b889a8fecbe7e6f59f38e8dcc995d86de0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.219 2000/08/01 04:53:58 anton Exp $
+/* $Id: srmmu.c,v 1.220 2000/08/09 00:00:15 davem Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
index 717269b6807ee8710ccf6cc924d3a94980496cdc..0ce0ca1e82368899df6596beb2ecbae162d317b9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.196 2000/07/07 07:33:11 anton Exp $
+/* $Id: sun4c.c,v 1.197 2000/08/09 00:00:15 davem Exp $
  * sun4c.c: Doing in software what should be done in hardware.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
index dab4e3bcf149528c14c60eea4e84d9bbb6021a70..c93f2efc8aebe8c17d79d1d4224455f920f5b432 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.60 2000/07/16 18:21:24 ecd Exp $
+# $Id: Makefile,v 1.61 2000/08/09 08:25:19 jj Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -64,7 +64,7 @@ binfmt_elf32.o: $(TOPDIR)/fs/binfmt_elf.c
 ifneq ($(NEW_GCC),y)
   CMODEL_CFLAG := -mmedlow
 else
-  CMODEL_CFLAG := -mcmodel=medlow
+  CMODEL_CFLAG := -m64 -mcmodel=medlow
 endif
 
 check_asm: dummy
index 3295938e6935546c7257be8e28d78ebe00356687..729ecd9117586bb4793f79b93ecd73aa34a311bc 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.51 2000/07/28 09:43:39 davem Exp $
+/* $Id: rtrap.S,v 1.53 2000/08/06 05:20:35 davem Exp $
  * rtrap.S: Preparing for return from trap on Sparc V9.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
index 7d8a71d6af463a685e28ce284d11b6d496432f90..e77d8a3856d7f1cc9a17ea2aad7d7da4634784cc 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.158 2000/07/29 00:55:49 davem Exp $
+/* $Id: sys_sparc32.c,v 1.159 2000/08/08 02:47:50 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -1037,7 +1037,8 @@ asmlinkage int sys32_utime(char * filename, struct utimbuf32 *times)
 
 struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; };
 
-typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *);
+typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
+typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
 
 static long do_readv_writev32(int type, struct file *file,
                              const struct iovec32 *vector, u32 count)
@@ -1047,14 +1048,15 @@ static long do_readv_writev32(int type, struct file *file,
        struct iovec *iov=iovstack, *ivp;
        struct inode *inode;
        long retval, i;
-       IO_fn_t fn;
+       io_fn_t fn;
+       iov_fn_t fnv;
 
        /* First get the "struct iovec" from user memory and
         * verify all the pointers
         */
        if (!count)
                return 0;
-       if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+       if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
                return -EFAULT;
        if (count > UIO_MAXIOV)
                return -EINVAL;
@@ -1086,33 +1088,19 @@ static long do_readv_writev32(int type, struct file *file,
        retval = locks_verify_area((type == VERIFY_WRITE
                                    ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
                                   inode, file, file->f_pos, tot_len);
-       if (retval) {
-               if (iov != iovstack)
-                       kfree(iov);
-               return retval;
-       }
+       if (retval)
+               goto out;
 
-       /* Then do the actual IO.  Note that sockets need to be handled
-        * specially as they have atomicity guarantees and can handle
-        * iovec's natively
-        */
-       if (inode->i_sock) {
-               int err;
-               err = sock_readv_writev(type, inode, file, iov, count, tot_len);
-               if (iov != iovstack)
-                       kfree(iov);
-               return err;
+       /* VERIFY_WRITE actually means a read, as we write to user space */
+       fnv = (type == VERIFY_WRITE ? file->f_op->readv : file->f_op->writev);
+       if (fnv) {
+               retval = fnv(file, iov, count, &file->f_pos);
+               goto out;
        }
 
-       if (!file->f_op) {
-               if (iov != iovstack)
-                       kfree(iov);
-               return -EINVAL;
-       }
-       /* VERIFY_WRITE actually means a read, as we write to user space */
-       fn = file->f_op->read;
-       if (type == VERIFY_READ)
-               fn = (IO_fn_t) file->f_op->write;               
+       fn = (type == VERIFY_WRITE ? file->f_op->read :
+             (io_fn_t) file->f_op->write);
+
        ivp = iov;
        while (count > 0) {
                void * base;
@@ -1124,17 +1112,18 @@ static long do_readv_writev32(int type, struct file *file,
                count--;
                nr = fn(file, base, len, &file->f_pos);
                if (nr < 0) {
-                       if (retval)
-                               break;
-                       retval = nr;
+                       if (!retval)
+                               retval = nr;
                        break;
                }
                retval += nr;
                if (nr != len)
                        break;
        }
+out:
        if (iov != iovstack)
                kfree(iov);
+
        return retval;
 }
 
@@ -1147,7 +1136,8 @@ asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
        if(!file)
                goto bad_file;
 
-       if (file->f_op && file->f_op->read && (file->f_mode & FMODE_READ))
+       if (file->f_op && (file->f_mode & FMODE_READ) &&
+           (file->f_op->readv || file->f_op->read))
                ret = do_readv_writev32(VERIFY_WRITE, file, vector, count);
        fput(file);
 
@@ -1163,7 +1153,8 @@ asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
        file = fget(fd);
        if(!file)
                goto bad_file;
-       if (file->f_op && file->f_op->write && (file->f_mode & FMODE_WRITE))
+       if (file->f_op && (file->f_mode & FMODE_WRITE) &&
+           (file->f_op->writev || file->f_op->write))
                ret = do_readv_writev32(VERIFY_READ, file, vector, count);
        fput(file);
 
index cd4b3365c18173236540777f2e8b7d6ab6a4d31a..8c9b7c9fd240495b4d5638a1fa26dff131fce781 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.48 2000/05/03 06:37:03 davem Exp $
+/* $Id: fault.c,v 1.49 2000/08/09 00:00:15 davem Exp $
  * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
index c469c60626553c7a654fdf3ad9560e7ca65b3879..68b77cfab4d35f6ea1809781e5ff4445446a787b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: generic.c,v 1.13 1999/12/20 05:02:33 davem Exp $
+/* $Id: generic.c,v 1.14 2000/08/09 00:00:15 davem Exp $
  * generic.c: Generic Sparc mm routines that are not dependent upon
  *            MMU type but are Sparc specific.
  *
index 63994c51d388ac389b319d99a8e7232fe4ec26b5..7eef978365c5c46dc7f67a69494083ae0c74fd1b 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.153 2000/07/27 01:05:15 davem Exp $
+/*  $Id: init.c,v 1.154 2000/08/09 00:00:15 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
index 4e37bb9d0115b9baf75a9fb117cfa9c8add678e3..93dd19ff3dbeacf9e5d2cb3b65724d14a5e79d50 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "../../char/busmouse.h"
 
+extern struct tasklet_struct keyboard_tasklet;
 extern void kbd_reset_kdown(void);
 
 #define VERSION 108
@@ -402,7 +403,7 @@ static void a5kkbd_rx(int irq, void *dev_id, struct pt_regs *regs)
 {
        kbd_pt_regs = regs;
        if (handle_rawcode(inb(IOC_KARTRX)))
-               mark_bh (KEYBOARD_BH);
+               tasklet_schedule(&keyboard_tasklet);
 }
 
 static void a5kkbd_tx(int irq, void *dev_id, struct pt_regs *regs)
index 8d26b37b141990e54d8dd2ac43a9104d5065fddd..abd25b16dfacc15350512877f9417038a7e9c711 100644 (file)
@@ -341,6 +341,5 @@ int __init ps2kbd_init_hw(void)
        (void)IOMD_KARTRX;
        restore_flags (flags);
 
-       printk (KERN_INFO "PS/2 keyboard driver v%d.%02d\n", VERSION/100, VERSION%100);
        return 0;
 }
index 85503d5340a133757115ae8cdfb0ab034af208a7..c0f39caeae28ae0a28651a54cf3ae0b0f3275787 100644 (file)
@@ -2463,7 +2463,7 @@ int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
         * IRQs after the sleep.
         */
        spin_unlock_irq(&io_request_lock);
-       scsi_sleep(5);
+       scsi_sleep(25*HZ/100);
        spin_lock_irq(&io_request_lock);
 
        /*
@@ -2628,7 +2628,7 @@ int fas216_init(struct Scsi_Host *instance)
         * scsi standard says wait 250ms
         */
        spin_unlock_irq(&io_request_lock);
-       scsi_sleep(5);
+       scsi_sleep(25*HZ/100);
        spin_lock_irq(&io_request_lock);
 
        outb(info->scsi.cfg[0], REG_CNTL1(info));
index cf6e99878a0a806dfdf2e06a215be8b206d85ad4..5c1fda2c3d6a5bc35ffa4a398bfa748925320107 100644 (file)
@@ -842,10 +842,10 @@ end_io:
        return 0;
 }
 
-void generic_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
+void generic_make_request (int rw, struct buffer_head * bh)
 {
        int major = MAJOR(bh->b_rdev);
-
+       request_queue_t *q;
        if (blk_size[major]) {
                unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1;
                unsigned int sector, count;
@@ -877,12 +877,21 @@ void generic_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
         * still free to implement/resolve their own stacking
         * by explicitly returning 0)
         */
-       while (q->make_request_fn(q, rw, bh))
-               /* NOTE: we don't repeat the blk_size check even though we now have a
-                * new device.  stacking drivers are expected to know what
-                * they are doing.
-                */
+       /* NOTE: we don't repeat the blk_size check for each new device.
+        * Stacking drivers are expected to know what they are doing.
+        */
+       do {
                q = blk_get_queue(bh->b_rdev);
+               if (!q) {
+                       printk(KERN_ERR
+                              "generic_make_request: Trying to access nonexistent block-device %s (%ld)\n",
+                              kdevname(bh->b_rdev), bh->b_rsector);
+                       buffer_IO_error(bh);
+                       break;
+               }
+
+       }
+       while (q->make_request_fn(q, rw, bh));
 }
 
 /* This function can be used to request a number of buffers from a block
@@ -892,19 +901,11 @@ void generic_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
 void ll_rw_block(int rw, int nr, struct buffer_head * bhs[])
 {
        struct buffer_head *bh;
-       request_queue_t *q;
        unsigned int major;
        int correct_size;
        int i;
 
        major = MAJOR(bhs[0]->b_dev);
-       q = blk_get_queue(bhs[0]->b_dev);
-       if (!q) {
-               printk(KERN_ERR
-       "ll_rw_block: Trying to read nonexistent block-device %s (%ld)\n",
-               kdevname(bhs[0]->b_dev), bhs[0]->b_blocknr);
-               goto sorry;
-       }
 
        /* Determine correct block size for this device. */
        correct_size = BLOCK_SIZE;
@@ -948,7 +949,7 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bhs[])
                bh->b_rdev = bh->b_dev;
                bh->b_rsector = bh->b_blocknr * (bh->b_size>>9);
 
-               generic_make_request(q, rw, bh);
+               generic_make_request(rw, bh);
        }
        return;
 
index 9774233cca079641856fec0966b4b81731ab99f2..d54669fc8950e7befccada33f813becf0bfa2bd7 100644 (file)
@@ -2741,7 +2741,7 @@ static int md_ioctl (struct inode *inode, struct file *file,
                        if (md_copy_from_user(&info, (void*)arg, sizeof(info)))
                                err = -EFAULT;
                        else
-                               err = add_new_disk(mddev, (void *)arg);
+                               err = add_new_disk(mddev, &info);
                        goto done_unlock;
                }
                case HOT_REMOVE_DISK:
index baf839b1d5639888c72e415b5aa6756f05ee8c55..4c364712a3305209cde645ffe9db4da445a6da34 100644 (file)
@@ -551,7 +551,6 @@ static int raid1_make_request (mddev_t *mddev, int rw,
        int disks = MD_SB_DISKS;
        int i, sum_bhs = 0, sectors;
        struct mirror_info *mirror;
-       request_queue_t *q;
 
        if (!buffer_locked(bh))
                BUG();
@@ -628,8 +627,7 @@ static int raid1_make_request (mddev_t *mddev, int rw,
        /*      bh_req->b_rsector = bh->n_rsector; */
                bh_req->b_end_io = raid1_end_request;
                bh_req->b_private = r1_bh;
-               q = blk_get_queue(bh_req->b_rdev);
-               generic_make_request (q, rw, bh_req);
+               generic_make_request (rw, bh_req);
                return 0;
        }
 
@@ -704,8 +702,7 @@ static int raid1_make_request (mddev_t *mddev, int rw,
        while(bh) {
                struct buffer_head *bh2 = bh;
                bh = bh->b_next;
-               q = blk_get_queue(bh2->b_rdev);
-               generic_make_request(q, rw, bh2);
+               generic_make_request(rw, bh2);
        }
        return (0);
 }
@@ -1124,7 +1121,6 @@ static void raid1d (void *data)
        struct raid1_bh *r1_bh;
        struct buffer_head *bh;
        unsigned long flags;
-       request_queue_t *q;
        mddev_t *mddev;
        kdev_t dev;
 
@@ -1206,8 +1202,7 @@ static void raid1d (void *data)
                                while (mbh) {
                                        struct buffer_head *bh1 = mbh;
                                        mbh = mbh->b_next;
-                                       q = blk_get_queue(bh1->b_rdev);
-                                       generic_make_request(q, WRITE, bh1);
+                                       generic_make_request(WRITE, bh1);
                                        md_sync_acct(bh1->b_rdev, bh1->b_size/512);
                                }
                        } else {
@@ -1220,8 +1215,7 @@ static void raid1d (void *data)
                                        printk (REDIRECT_SECTOR,
                                                partition_name(bh->b_dev), bh->b_blocknr);
                                        bh->b_rdev = bh->b_dev;
-                                       q = blk_get_queue(bh->b_rdev);
-                                       generic_make_request (q, READ, bh);
+                                       generic_make_request(READ, bh);
                                }
                        }
 
@@ -1238,8 +1232,7 @@ static void raid1d (void *data)
                                printk (REDIRECT_SECTOR,
                                        partition_name(bh->b_dev), bh->b_blocknr);
                                bh->b_rdev = bh->b_dev;
-                               q = blk_get_queue(bh->b_rdev);
-                               generic_make_request (q, r1_bh->cmd, bh);
+                               generic_make_request (r1_bh->cmd, bh);
                        }
                        break;
                }
@@ -1348,7 +1341,6 @@ static int raid1_sync_request (mddev_t *mddev, unsigned long block_nr)
 {
        raid1_conf_t *conf = mddev_to_conf(mddev);
        struct mirror_info *mirror;
-       request_queue_t *q;
        struct raid1_bh *r1_bh;
        struct buffer_head *bh;
        int bsize;
@@ -1435,8 +1427,7 @@ static int raid1_sync_request (mddev_t *mddev, unsigned long block_nr)
        bh->b_rsector = block_nr<<1;
        init_waitqueue_head(&bh->b_wait);
 
-       q = blk_get_queue(bh->b_rdev);
-       generic_make_request(q, READ, bh);
+       generic_make_request(READ, bh);
        md_sync_acct(bh->b_rdev, bh->b_size/512);
 
        return (bsize >> 10);
index 346cc2759a5f9e39dd2061b03677871d20ff9353..5d575a7f55cc1506fbbc729d4dfa2be3bf4e4ace 100644 (file)
@@ -1017,7 +1017,6 @@ static void handle_stripe_write (mddev_t *mddev , raid5_conf_t *conf,
        int nr_failed_other, int nr_cache_overwrite, int nr_failed_overwrite)
 {
        int i, allclean;
-       request_queue_t *q;
        unsigned int block;
        struct buffer_head *bh;
        int method1 = INT_MAX, method2 = INT_MAX;
@@ -1088,21 +1087,18 @@ static void handle_stripe_write (mddev_t *mddev , raid5_conf_t *conf,
                                        PRINTK("writing spare %d\n", i);
                                        atomic_inc(&sh->nr_pending);
                                        bh->b_dev = bh->b_rdev = conf->spare->dev;
-                                       q = blk_get_queue(bh->b_rdev);
-                                       generic_make_request(q, WRITERAW, bh);
+                                       generic_make_request(WRITERAW, bh);
                                } else {
 #if 0
                                        atomic_inc(&sh->nr_pending);
                                        bh->b_dev = bh->b_rdev = conf->disks[i].dev;
-                                       q = blk_get_queue(bh->b_rdev);
-                                       generic_make_request(q, WRITERAW, bh);
+                                       generic_make_request(WRITERAW, bh);
 #else
                                        if (!allclean || (i==sh->pd_idx)) {
                                                PRINTK("writing dirty %d\n", i);
                                                atomic_inc(&sh->nr_pending);
                                                bh->b_dev = bh->b_rdev = conf->disks[i].dev;
-                                               q = blk_get_queue(bh->b_rdev);
-                                               generic_make_request(q, WRITERAW, bh);
+                                               generic_make_request(WRITERAW, bh);
                                        } else {
                                                PRINTK("not writing clean %d\n", i);
                                                raid5_end_request(bh, 1);
@@ -1147,8 +1143,7 @@ static void handle_stripe_write (mddev_t *mddev , raid5_conf_t *conf,
                lock_get_bh(sh->bh_old[i]);
                atomic_inc(&sh->nr_pending);
                sh->bh_old[i]->b_dev = sh->bh_old[i]->b_rdev = conf->disks[i].dev;
-               q = blk_get_queue(sh->bh_old[i]->b_rdev);
-               generic_make_request(q, READ, sh->bh_old[i]);
+               generic_make_request(READ, sh->bh_old[i]);
                atomic_dec(&sh->bh_old[i]->b_count);
        }
        PRINTK("handle_stripe() %lu, reading %d old buffers\n", sh->sector, md_atomic_read(&sh->nr_pending));
@@ -1163,7 +1158,6 @@ static void handle_stripe_read (mddev_t *mddev , raid5_conf_t *conf,
        int nr_failed_other, int nr_cache_overwrite, int nr_failed_overwrite)
 {
        int i;
-       request_queue_t *q;
        int method1 = INT_MAX;
 
        method1 = nr_read - nr_cache_overwrite;
@@ -1194,8 +1188,7 @@ static void handle_stripe_read (mddev_t *mddev , raid5_conf_t *conf,
                        lock_get_bh(sh->bh_old[i]);
                        atomic_inc(&sh->nr_pending);
                        sh->bh_old[i]->b_dev = sh->bh_old[i]->b_rdev = conf->disks[i].dev;
-                       q = blk_get_queue(sh->bh_old[i]->b_rdev);
-                       generic_make_request(q, READ, sh->bh_old[i]);
+                       generic_make_request(READ, sh->bh_old[i]);
                        atomic_dec(&sh->bh_old[i]->b_count);
                }
                PRINTK("handle_stripe() %lu, phase READ_OLD, pending %d buffers\n", sh->sector, md_atomic_read(&sh->nr_pending));
@@ -1224,8 +1217,7 @@ static void handle_stripe_read (mddev_t *mddev , raid5_conf_t *conf,
                lock_get_bh(sh->bh_req[i]);
                atomic_inc(&sh->nr_pending);
                sh->bh_req[i]->b_dev = sh->bh_req[i]->b_rdev = conf->disks[i].dev;
-               q = blk_get_queue(sh->bh_req[i]->b_rdev);
-               generic_make_request(q, READ, sh->bh_req[i]);
+               generic_make_request(READ, sh->bh_req[i]);
                atomic_dec(&sh->bh_req[i]->b_count);
        }
        PRINTK("handle_stripe() %lu, phase READ, pending %d\n", sh->sector, md_atomic_read(&sh->nr_pending));
@@ -1239,7 +1231,6 @@ static void handle_stripe_sync (mddev_t *mddev , raid5_conf_t *conf,
        int parity, int parity_failed, int nr_cache, int nr_cache_other,
        int nr_failed_other, int nr_cache_overwrite, int nr_failed_overwrite)
 {
-       request_queue_t *q;
        struct buffer_head *bh;
        int i, pd_idx;
        
@@ -1262,8 +1253,7 @@ static void handle_stripe_sync (mddev_t *mddev , raid5_conf_t *conf,
                        lock_get_bh(bh);
                        atomic_inc(&sh->nr_pending);
                        bh->b_dev = bh->b_rdev = conf->disks[i].dev;
-                       q = blk_get_queue(bh->b_rdev);
-                       generic_make_request(q, READ, bh);
+                       generic_make_request(READ, bh);
                        md_sync_acct(bh->b_rdev, bh->b_size/512);
                        atomic_dec(&sh->bh_old[i]->b_count);
                }
@@ -1292,8 +1282,7 @@ static void handle_stripe_sync (mddev_t *mddev , raid5_conf_t *conf,
                                atomic_inc(&sh->nr_pending);
                                lock_get_bh(bh);
                                bh->b_dev = bh->b_rdev = conf->spare->dev;
-                               q = blk_get_queue(bh->b_rdev);
-                               generic_make_request(q, WRITERAW, bh);
+                               generic_make_request(WRITERAW, bh);
                                md_sync_acct(bh->b_rdev, bh->b_size/512);
                                atomic_dec(&bh->b_count);
                PRINTK("handle_stripe_sync() %lu, phase WRITE, pending %d buffers\n", sh->sector, md_atomic_read(&sh->nr_pending));
@@ -1319,8 +1308,7 @@ static void handle_stripe_sync (mddev_t *mddev , raid5_conf_t *conf,
                lock_get_bh(bh);
                atomic_inc(&sh->nr_pending);
                bh->b_dev = bh->b_rdev = conf->disks[pd_idx].dev;
-               q = blk_get_queue(bh->b_rdev);
-               generic_make_request(q, WRITERAW, bh);
+               generic_make_request(WRITERAW, bh);
                md_sync_acct(bh->b_rdev, bh->b_size/512);
                atomic_dec(&bh->b_count);
                PRINTK("handle_stripe_sync() %lu phase WRITE, pending %d buffers\n",
index 1612f321d0fe035ac33cbf2fdda3d7753862ceab..7babb59b96d041cd108b18ed9423da98ec898b9b 100644 (file)
@@ -103,7 +103,6 @@ typedef struct {
        const char *name;
 } XD_SIGNATURE;
 
-static int xd_setup (char *);
 #ifndef MODULE
 static int xd_manual_geo_init (char *command);
 #endif /* MODULE */
index 9bfe4b2b3c528d4be188401ac9104dcd0b89e38e..9a983bb3e3bf1ba95fda9200a50303e8872e9d6b 100644 (file)
@@ -172,12 +172,10 @@ static int busmouse_release(struct inode *inode, struct file *file)
        busmouse_fasync(-1, file, 0);
 
        if (--mse->active == 0) {
-               if (mse->ops) {
-                       if (mse->ops->release)
-                               ret = mse->ops->release(inode, file);
-                       if (mse->ops->owner)
-                               __MOD_DEC_USE_COUNT(mse->ops->owner);
-               }
+               if (mse->ops->release)
+                       ret = mse->ops->release(inode, file);
+               if (mse->ops->owner)
+                       __MOD_DEC_USE_COUNT(mse->ops->owner);
                mse->ready = 0;
        }
        unlock_kernel();
@@ -189,7 +187,7 @@ static int busmouse_open(struct inode *inode, struct file *file)
 {
        struct busmouse_data *mse;
        unsigned int mousedev;
-       int ret = -ENODEV;
+       int ret;
 
        mousedev = DEV_TO_MOUSE(inode->i_rdev);
        if (mousedev >= NR_MICE)
@@ -197,13 +195,15 @@ static int busmouse_open(struct inode *inode, struct file *file)
 
        down(&mouse_sem);
        mse = busmouse_data[mousedev];
-       if (!mse)
-               /* shouldn't happen, but... */
+       ret = -ENODEV;
+       if (!mse || !mse->ops)  /* shouldn't happen, but... */
                goto end;
-       
-       if (mse->ops && mse->ops->owner)
-               __MOD_INC_USE_COUNT(mse->ops->owner);
-       if (mse->ops && mse->ops->open) {
+
+       if (mse->ops->owner && !try_inc_mod_count(mse->ops->owner))
+               goto end;
+
+       ret = 0;
+       if (mse->ops->open) {
                ret = mse->ops->open(inode, file);
                if (ret && mse->ops->owner)
                        __MOD_DEC_USE_COUNT(mse->ops->owner);
@@ -222,10 +222,7 @@ static int busmouse_open(struct inode *inode, struct file *file)
        mse->ready   = 0;
        mse->dxpos   = 0;
        mse->dypos   = 0;
-       if (mse->ops)
-               mse->buttons = mse->ops->init_button_state;
-       else
-               mse->buttons = 7;
+       mse->buttons = mse->ops->init_button_state;
 
        spin_unlock_irq(&mse->lock);
 end:
index 3f51c056a05ec3a9a46a358c0bed918684eda140..67654551c29b8cd52f97d68d9bcf6f8ee169b22e 100644 (file)
@@ -2674,6 +2674,7 @@ void unblank_screen(void)
        console_blanked = 0;
        if (console_blank_hook)
                console_blank_hook(0);
+       set_palette(currcons);
        if (sw->con_blank(vc_cons[currcons].d, 0))
                /* Low-level driver cannot restore -> do it ourselves */
                update_screen(fg_console);
index 4f85d07ca931fd8fc79d68df1bba3e27b11ef0a9..0fa205717850c4fe62911a2dbba9d09ba529ff82 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/version.h>
 #include <linux/sched.h>
 #include <linux/smp_lock.h>    /* For (un)lock_kernel */
+#include <linux/mm.h>
 #include <asm/io.h>
 #include <asm/mman.h>
 #include <asm/uaccess.h>
@@ -140,7 +141,7 @@ typedef struct wait_queue *wait_queue_head_t;
 #endif
 
                                /* virt_to_page added in 2.4.0-test6 */
-#ifndef virt_to_page
+#if LINUX_VERSION_CODE < 0x020400
 #define virt_to_page(kaddr) (mem_map + MAP_NR(kaddr))
 #endif
 
index 7e48ad82149b6f4d0a8c45a64303e9ed59b656a0..4a109265a38f806dc0350879466cdbe4d984f12a 100644 (file)
@@ -5,7 +5,9 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/init.h>
+#include <asm/delay.h>
 #include <asm/io.h>
 #include "scan_keyb.h"
 
@@ -23,7 +25,7 @@ static const unsigned char hp690_japanese_table[]={
        0x00, 0x00, 0x00, 0x2c, 0x00, 0x1c, 0x28, 0x35,
        0x31, 0x30, 0x32, 0x33, 0x34, 0x2f, 0x2e, 0x2d,
 
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x50,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x50,
        0x7b, 0x38, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -46,25 +48,35 @@ static const unsigned char hp690_japanese_table[]={
 };
 
 
+static const unsigned char hp690_switch[]= {
+       0xfd, 0xff,
+       0xdf, 0xff,
+       0x7f, 0xff,
+       0xff, 0xfe,
+       0xff, 0xfd,
+       0xff, 0xf7,
+       0xff, 0xbf,
+       0xff, 0x7f,
+};
+
+
 static void hp690_japanese_scan_kbd(unsigned char *s)
 {
-       ctrl_outb(0xfd, PDDR); ctrl_outb(0xff, PEDR);
-       *s++=ctrl_inb(PCDR); *s++=ctrl_inb(PFDR);
-       ctrl_outb(0xdf, PDDR); ctrl_outb(0xff, PEDR);
-       *s++=ctrl_inb(PCDR); *s++=ctrl_inb(PFDR);
-       ctrl_outb(0x7f, PDDR); ctrl_outb(0xff, PEDR);
-       *s++=ctrl_inb(PCDR); *s++=ctrl_inb(PFDR);
-       ctrl_outb(0xff, PDDR); ctrl_outb(0xfe, PEDR);
-       *s++=ctrl_inb(PCDR); *s++=ctrl_inb(PFDR);
-       ctrl_outb(0xff, PDDR); ctrl_outb(0xfd, PEDR);
-       *s++=ctrl_inb(PCDR); *s++=ctrl_inb(PFDR);
-       ctrl_outb(0xff, PDDR); ctrl_outb(0xf7, PEDR);
-       *s++=ctrl_inb(PCDR); *s++=ctrl_inb(PFDR);
-       ctrl_outb(0xff, PDDR); ctrl_outb(0xbf, PEDR);
-       *s++=ctrl_inb(PCDR); *s++=ctrl_inb(PFDR);
-       ctrl_outb(0xff, PDDR); ctrl_outb(0x7f, PEDR);
-       *s++=ctrl_inb(PCDR); *s++=ctrl_inb(PFDR);
-       *s++=ctrl_inb(PGDR); *s++=ctrl_inb(PHDR);
+       int i;
+       unsigned const char *t=hp690_switch;
+
+       for(i=0; i<9; i++) {
+               ctrl_outb(*t++, PDDR);
+               ctrl_outb(*t++, PEDR);
+               *s++=ctrl_inb(PCDR);
+               *s++=ctrl_inb(PFDR);
+       }
+
+       ctrl_outb(0xff, PDDR);
+       ctrl_outb(0xff, PEDR);
+
+       *s++=ctrl_inb(PGDR);
+       *s++=ctrl_inb(PHDR);
 }
 
 
index 7ec7034e0ff7f8959ff8d64505e59a0394fc9609..1936e0b6eeb46b60a54b6a45455a755243620175 100644 (file)
@@ -91,9 +91,9 @@ int register_scan_keyboard(void (*scan)(unsigned char *buffer),
 
        kbd->s0=kbd->s1=NULL;
        if((kbd->s0=kmalloc(length, GFP_KERNEL))==NULL)
-               goto error_out;
+               goto error_mem_free;
        if((kbd->s1=kmalloc(length, GFP_KERNEL))==NULL)
-               goto error_out;
+               goto error_mem_free;
 
        kbd->scan(kbd->s0);
        kbd->scan(kbd->s1);
index 12ab34d721f57a7d16e4ebb468f1a99640a540b6..0605674e07552576fc39aad73233c2ec8591f5d6 100644 (file)
@@ -60,8 +60,10 @@ static int sercons_baud;
 static void sci_init_pins_sci(struct sci_port* port, unsigned int cflag);
 #ifndef SCI_ONLY
 static void sci_init_pins_scif(struct sci_port* port, unsigned int cflag);
-#endif
+#if defined(__sh3__)
 static void sci_init_pins_irda(struct sci_port* port, unsigned int cflag);
+#endif
+#endif
 static void sci_disable_tx_interrupts(void *ptr);
 static void sci_enable_tx_interrupts(void *ptr);
 static void sci_disable_rx_interrupts(void *ptr);
@@ -106,6 +108,8 @@ static void put_char(struct sci_port *port, char c)
        restore_flags(flags);
 }
 
+#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
+
 static void handle_error(struct sci_port *port)
 {                              /* Clear error flags */
        sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
@@ -133,8 +137,6 @@ static int get_char(struct sci_port *port)
        return c;
 }
 
-#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
-
 /* Taken from sh-stub.c of GDB 4.18 */
 static const char hexchars[] = "0123456789abcdef";
 
@@ -221,7 +223,7 @@ static void sci_init_pins_sci(struct sci_port* port, unsigned int cflag)
 
 #if defined(SCIF_ONLY) || defined(SCI_AND_SCIF)
 #if defined(__sh3__)
-/* For SH7709, SH7709A, SH7729 */
+/* For SH7707, SH7709, SH7709A, SH7729 */
 static void sci_init_pins_scif(struct sci_port* port, unsigned int cflag)
 {
        unsigned int fcr_val = 0;
@@ -328,7 +330,7 @@ static void sci_set_baud(struct sci_port *port, int baud)
                t = BPS_38400;
                break;
        default:
-               printk(KERN_INFO "sci: unsupported baud rate: %d, use 115200 instead.\n", baud);
+               printk(KERN_INFO "sci: unsupported baud rate: %d, using 115200 instead.\n", baud);
        case 115200:
                t = BPS_115200;
                break;
@@ -412,6 +414,17 @@ static int sci_set_real_termios(void *ptr)
  *                   the interrupt related routines                       *
  * ********************************************************************** */
 
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ */
+static inline void sci_sched_event(struct sci_port *port, int event)
+{
+       port->event |= 1 << event;
+       queue_task(&port->tqueue, &tq_immediate);
+       mark_bh(IMMEDIATE_BH);
+}
+
 static void sci_transmit_chars(struct sci_port *port)
 {
        int count, i;
@@ -459,6 +472,8 @@ static void sci_transmit_chars(struct sci_port *port)
                }
                sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
 
+               port->icount.tx += count;
+
                /* Update the kernel buffer end */
                port->gs.xmit_tail = (port->gs.xmit_tail + count) & (SERIAL_XMIT_SIZE-1);
 
@@ -467,12 +482,8 @@ static void sci_transmit_chars(struct sci_port *port)
                port->gs.xmit_cnt -= count;
        }
 
-       if (port->gs.xmit_cnt <= port->gs.wakeup_chars) {
-               if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                   port->gs.tty->ldisc.write_wakeup)
-                       (port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
-               wake_up_interruptible(&port->gs.tty->write_wait);
-       }
+       if (port->gs.xmit_cnt <= port->gs.wakeup_chars)
+               sci_sched_event(port, SCI_EVENT_WRITE_WAKEUP);
 
        save_and_cli(flags);
        ctrl = sci_in(port, SCSCR);
@@ -530,6 +541,7 @@ static inline void sci_receive_chars(struct sci_port *port)
                tty->flip.flag_buf_ptr += count;
 
                copied += count;
+               port->icount.rx += count;
        }
 
        if (copied)
@@ -572,6 +584,23 @@ static void sci_er_interrupt(int irq, void *ptr, struct pt_regs *regs)
        sci_tx_interrupt(irq, ptr, regs);
 }
 
+static void do_softint(void *private_)
+{
+       struct sci_port *port = (struct sci_port *) private_;
+       struct tty_struct       *tty;
+       
+       tty = port->gs.tty;
+       if (!tty)
+               return;
+
+       if (test_and_clear_bit(SCI_EVENT_WRITE_WAKEUP, &port->event)) {
+               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+                   tty->ldisc.write_wakeup)
+                       (tty->ldisc.write_wakeup)(tty);
+               wake_up_interruptible(&tty->write_wait);
+       }
+}
+
 /* ********************************************************************** *
  *                Here are the routines that actually                     *
  *              interface with the generic_serial driver                  *
@@ -675,6 +704,10 @@ static int sci_open(struct tty_struct * tty, struct file * filp)
        port->gs.tty = tty;
        port->gs.count++;
 
+       port->event = 0;
+       port->tqueue.routine = do_softint;
+       port->tqueue.data = port;
+
        /*
         * Start up serial port
         */
@@ -841,9 +874,22 @@ static int sci_read_proc(char *page, char **start, off_t off, int count,
         len += sprintf(page, "sciinfo:0.1\n");
        for (i = 0; i < SCI_NPORTS && len < 4000; i++) {
                port = &sci_ports[i];
-               len += sprintf(page+len, "%d: uart:%s address: %08x\n", i,
+               len += sprintf(page+len, "%d: uart:%s address: %08x", i,
                               (port->type == PORT_SCI) ? "SCI" : "SCIF",
                               port->base);
+               len += sprintf(page+len, " baud:%d", port->gs.baud);
+               len += sprintf(page+len, " tx:%d rx:%d",
+                              port->icount.tx, port->icount.rx);
+
+               if (port->icount.frame)
+                       len += sprintf(page+len, " fe:%d", port->icount.frame);
+               if (port->icount.parity)
+                       len += sprintf(page+len, " pe:%d", port->icount.parity);
+               if (port->icount.brk)
+                       len += sprintf(page+len, " brk:%d", port->icount.brk);
+               if (port->icount.overrun)
+                       len += sprintf(page+len, " oe:%d", port->icount.overrun);
+               len += sprintf(page+len, "\n");
        }
        return len;
 }
@@ -923,6 +969,11 @@ static int sci_init_drivers(void)
                init_waitqueue_head(&port->gs.open_wait);
                init_waitqueue_head(&port->gs.close_wait);
                port->old_cflag = 0;
+               port->icount.cts = port->icount.dsr = 
+                       port->icount.rng = port->icount.dcd = 0;
+               port->icount.rx = port->icount.tx = 0;
+               port->icount.frame = port->icount.parity = 0;
+               port->icount.overrun = port->icount.brk = 0;
        }
 
        return 0;
@@ -943,8 +994,6 @@ int __init sci_init(void)
                printk("ttySC%d at 0x%08x is a %s\n", j, port->base,
                       (port->type == PORT_SCI) ? "SCI" : "SCIF");
                for (i=0; i<3; i++) {
-                       set_ipr_data(port->irqs[i], port->intc_addr, port->intc_pos, SCI_PRIORITY);
-
                        if (request_irq(port->irqs[i], handlers[i], SA_INTERRUPT,
                                        "sci", port)) {
                                printk(KERN_ERR "sci: Cannot allocate irq.\n");
index b9ecad78b8bd52f0d69183a4e2531033b9b18ea1..c38e97c52c1e5e1462d61f0fbde959a113bce268 100644 (file)
 #define SCIx_RXI_IRQ 1
 #define SCIx_TXI_IRQ 2
 
-/*                     ERI, RXI, TXI,   INTC reg, INTC pos */
-#define SCI_IRQS      { 23,  24,  25 }, INTC_IPRB, 1
-#define SH3_SCIF_IRQS { 56,  57,  59 }, INTC_IPRE, 1
-#define SH3_IRDA_IRQS { 52,  53,  55 }, INTC_IPRE, 2
-#define SH4_SCIF_IRQS { 40,  41,  43 }, INTC_IPRC, 1
+/*                     ERI, RXI, TXI,  */
+#define SCI_IRQS      { 23,  24,  25 }
+#define SH3_SCIF_IRQS { 56,  57,  59 }
+#define SH3_IRDA_IRQS { 52,  53,  55 }
+#define SH4_SCIF_IRQS { 40,  41,  43 }
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7708)
 # define SCI_NPORTS 1
 # define SCSPTR 0xffffff7c /* 8 bit */
 # define SCSCR_INIT(port)          0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCI_ONLY
-#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
 # define SCI_NPORTS 3
 # define SCI_INIT { \
-  { {}, PORT_SCI,  0xfffffe80, SCI_IRQS,        sci_init_pins_sci  }, \
-  { {}, PORT_SCIF, 0xA4000150, SH3_SCIF_IRQS, sci_init_pins_scif },   \
-  { {}, PORT_SCIF, 0xA4000140, SH3_IRDA_IRQS, sci_init_pins_irda }    \
+  { {}, PORT_SCI,  0xfffffe80, SCI_IRQS,      sci_init_pins_sci  }, \
+  { {}, PORT_SCIF, 0xA4000150, SH3_SCIF_IRQS, sci_init_pins_scif }, \
+  { {}, PORT_SCIF, 0xA4000140, SH3_IRDA_IRQS, sci_init_pins_irda }  \
 }
 # define SCPCR  0xA4000116 /* 16 bit SCI and SCIF */
 # define SCPDR  0xA4000136 /* 8  bit SCI and SCIF */
 #define SCI_CTRL_FLAGS_TE   0x20 /* all */
 #define SCI_CTRL_FLAGS_RE   0x10 /* all */
 /*      SCI_CTRL_FLAGS_REIE 0x08  * 7750 SCIF */
-/*      SCI_CTRL_FLAGS_MPIE 0x08  * 7708 SCI, 7709 SCI, 7750 SCI */
-/*      SCI_CTRL_FLAGS_TEIE 0x04  * 7708 SCI, 7709 SCI, 7750 SCI */
+/*      SCI_CTRL_FLAGS_MPIE 0x08  * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+/*      SCI_CTRL_FLAGS_TEIE 0x04  * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
 /*      SCI_CTRL_FLAGS_CKE1 0x02  * all */
-/*      SCI_CTRL_FLAGS_CKE0 0x01  * 7708 SCI, 7709 SCI/SCIF, 7750 SCI */
+/*      SCI_CTRL_FLAGS_CKE0 0x01  * 7707 SCI/SCIF, 7708 SCI, 7709 SCI/SCIF, 7750 SCI */
 
 /* SCxSR SCI */
-#define SCI_TDRE  0x80 /* 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_RDRF  0x40 /* 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_ORER  0x20 /* 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_FER   0x10 /* 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_PER   0x08 /* 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_TEND  0x04 /* 7708 SCI, 7709 SCI, 7750 SCI */
-/*      SCI_MPB   0x02  * 7708 SCI, 7709 SCI, 7750 SCI */
-/*      SCI_MPBT  0x01  * 7708 SCI, 7709 SCI, 7750 SCI */
+#define SCI_TDRE  0x80 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+#define SCI_RDRF  0x40 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+#define SCI_ORER  0x20 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+#define SCI_FER   0x10 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+#define SCI_PER   0x08 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+#define SCI_TEND  0x04 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+/*      SCI_MPB   0x02  * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+/*      SCI_MPBT  0x01  * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
 
 #define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ORER)
 
 /* SCxSR SCIF */
-#define SCIF_ER    0x0080 /* 7709 SCIF, 7750 SCIF */
-#define SCIF_TEND  0x0040 /* 7709 SCIF, 7750 SCIF */
-#define SCIF_TDFE  0x0020 /* 7709 SCIF, 7750 SCIF */
-#define SCIF_BRK   0x0010 /* 7709 SCIF, 7750 SCIF */
-#define SCIF_FER   0x0008 /* 7709 SCIF, 7750 SCIF */
-#define SCIF_PER   0x0004 /* 7709 SCIF, 7750 SCIF */
-#define SCIF_RDF   0x0002 /* 7709 SCIF, 7750 SCIF */
-#define SCIF_DR    0x0001 /* 7709 SCIF, 7750 SCIF */
+#define SCIF_ER    0x0080 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */
+#define SCIF_TEND  0x0040 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */
+#define SCIF_TDFE  0x0020 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */
+#define SCIF_BRK   0x0010 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */
+#define SCIF_FER   0x0008 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */
+#define SCIF_PER   0x0004 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */
+#define SCIF_RDF   0x0002 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */
+#define SCIF_DR    0x0001 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */
 
 #define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
 
 #define SCFCR_TFRST 0x0004
 #define SCFCR_MCE   0x0008
 
-#define SCI_PRIORITY   3
-
 #define SCI_MAJOR              204
 #define SCI_MINOR_START                8
 
 
 #define SCI_MAGIC 0xbabeface
 
+/*
+ * Events are used to schedule things to happen at timer-interrupt
+ * time, instead of at rs interrupt time.
+ */
+#define SCI_EVENT_WRITE_WAKEUP 0
+
 struct sci_port {
        struct gs_port gs;
        int type;
        unsigned int base;
        unsigned char irqs[3]; /* ERI, RXI, TXI */
-       unsigned int intc_addr, intc_pos;
        void (*init_pins)(struct sci_port* port, unsigned int cflag);
        unsigned int old_cflag;
+       struct async_icount icount;
+       struct tq_struct tqueue;
+       unsigned long event;
 };
 
 #define SCI_IN(size, offset)                                   \
index 2238ce5a9de0e9837d52f68be2e669d19dabcef9..2f9442b22522c5450242357f66a2fcfaee2c3a29 100644 (file)
@@ -51,7 +51,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
    if [ "$CONFIG_SGI_IP27" = "y" ]; then
       bool '  SGI IOC3 Ethernet' CONFIG_SGI_IOC3_ETH
    fi
-   if [ "$CONFIG_SUPERH" = "y" -a "$CONFIG_SH_SOLUTION_ENGINE" = "y" ]; then
+   if [ "$CONFIG_SUPERH" = "y" ]; then
       tristate '  National DP83902AV  support' CONFIG_STNIC
    fi
    bool '  3COM cards' CONFIG_NET_VENDOR_3COM
index 1c297dbec58e3943a4d3c85a0584e6da7b1478af..2542fa2d0b42aee3e163a352981aabe590d9cd2b 100644 (file)
@@ -1292,6 +1292,12 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus)
 
        dev = init_etherdev(NULL, PRIV_BYTES);
 
+       if (!dev) {
+               printk(KERN_ERR "init_etherdev failed, out of memory for BMAC %s\n",
+                      bmac->full_name);
+               return;
+       }
+
        dev->base_addr = (unsigned long)
                ioremap(bmac->addrs[0].address, bmac->addrs[0].size);
        dev->irq = bmac->intrs[0].line;
index 233b1e4d35f1050effd67507dac2fe23e2e272b0..c343bc53c7119d4d46fd28b30bfb4a060379025b 100644 (file)
@@ -568,8 +568,11 @@ static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 };
 static int eepro100_init_one(struct pci_dev *pdev,
                const struct pci_device_id *ent);
 static void eepro100_remove_one (struct pci_dev *pdev);
+
+#ifdef CONFIG_EEPRO100_PM
 static void eepro100_suspend (struct pci_dev *pdev);
 static void eepro100_resume (struct pci_dev *pdev);
+#endif /* CONFIG_EEPRO100_PM */
 
 static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len);
 static int mdio_read(long ioaddr, int phy_id, int location);
@@ -2182,6 +2185,9 @@ static void set_rx_mode(struct net_device *dev)
        sp->rx_mode = new_rx_mode;
 }
 \f
+
+#ifdef CONFIG_EEPRO100_PM
+
 static void eepro100_suspend(struct pci_dev *pdev)
 {
        struct net_device *dev = pdev->driver_data;
@@ -2214,6 +2220,8 @@ static void eepro100_resume(struct pci_dev *pdev)
        set_rx_mode(dev);
 }
 
+#endif /* CONFIG_EEPRO100_PM */
+
 static void __devexit eepro100_remove_one (struct pci_dev *pdev)
 {
        struct net_device *dev = pdev->driver_data;
@@ -2252,7 +2260,8 @@ static struct pci_driver eepro100_driver = {
        id_table:       eepro100_pci_tbl,
        probe:          eepro100_init_one,
        remove:         eepro100_remove_one,
-#if 0  /* These seem to be broken.. */
+
+#ifdef CONFIG_EEPRO100_PM
        suspend:        eepro100_suspend,
        resume:         eepro100_resume,
 #endif
index 17d32829489e6227ef947d980e92e5e1064e13bc..0457d374f27b32909e12b5c8d37519ac8b6060c6 100644 (file)
@@ -5,6 +5,10 @@
  * Copyright (C) 2000 Paul Mackerras & Ben. Herrenschmidt
  * 
  * portions based on sunhme.c by David S. Miller
+ *
+ * Changes:
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/06/2000
+ * - check init_etherdev return in gmac_probe1
  * 
  */
 
@@ -1178,7 +1182,13 @@ gmac_probe1(struct device_node *gmac)
        }
 
        dev = init_etherdev(0, sizeof(struct gmac));
-       memset(dev->priv, 0, sizeof(struct gmac));
+
+       if (!dev) {
+               printk(KERN_ERR "GMAC: init_etherdev failed, out of memory\n");
+               free_page(tx_descpage);
+               free_page(rx_descpage);
+               return;
+       }
 
        gm = (struct gmac *) dev->priv;
        dev->base_addr = gmac->addrs[0].address;
index 8e5511da17a6138e7b12bae9d32a1e65628561f0..fd2c79235da98e9d8ad72351db3d161c3a096fbf 100644 (file)
 /* The Amiganet is a Zorro-II board made by Hydra Systems. It contains a    */
 /* NS8390 NIC (network interface controller) clone, 16 or 64K on-board RAM  */
 /* and 10BASE-2 (thin coax) and AUI connectors.                             */
+/*                                                                          */
+/* Changes                                                                  */
+/* Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/06/2000            */
+/* - check init_etherdev in hydra_probe                                     */
+/* - dev->priv is already zeroed by init_etherdev                           */
 
 
 #include <linux/module.h>
@@ -176,8 +181,13 @@ int __init hydra_probe(struct net_device *dev)
                strcpy(z->name, "Hydra Ethernet Card");
 
                dev = init_etherdev(NULL, sizeof(struct hydra_private));
-               memset(dev->priv, 0, sizeof(struct hydra_private));
-    
+
+               if (!dev) {
+                       release_mem_region(base_addr, 0x20);
+                       release_mem_region(board, 0x4000);
+                       continue;
+               }
+
                for(j = 0; j < ETHER_ADDR_LEN; j++)
                        dev->dev_addr[j] = *((u8 *)ZTWO_VADDR(board + HYDRA_ADDRPROM + 2*j));
     
index 0c914aec2faf75d81e609619bbe1c8037accffb4..8d7bc5392268b97913af0015662e3c1e51392f75 100644 (file)
  * modified by SRC, incorporated herein by reference.
  * 
  * **********************
+ * Changes:
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/08/2000
+ * - reorganize kmallocs in com20020_attach, checking all for failure
+ *   and releasing the previous allocations if one fails
+ * **********************
  * 
  * For more details, see drivers/net/arcnet.c
  *
@@ -198,7 +203,24 @@ static dev_link_t *com20020_attach(void)
     link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
     if (!link)
        return NULL;
+
+    info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
+    if (!info)
+       goto fail_alloc_info;
+
+    lp =  kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
+    if (!lp)
+       goto fail_alloc_lp;
+
+    dev = dev_alloc("arc%d", &ret);
+    if (!dev)
+       goto fail_alloc_dev;
+
+    memset(info, 0, sizeof(struct com20020_dev_t));
+    memset(lp, 0, sizeof(struct arcnet_local));
     memset(link, 0, sizeof(struct dev_link_t));
+    dev->priv = lp;
+
     link->release.function = &com20020_release;
     link->release.data = (u_long)link;
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -216,19 +238,6 @@ static dev_link_t *com20020_attach(void)
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.Present = PRESENT_OPTION;
 
-    info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
-    if (!info)
-       return NULL;
-    memset(info, 0, sizeof(struct com20020_dev_t));
-
-    dev = dev_alloc("arc%d", &ret);
-    if (!dev)
-       return NULL;
-    lp = dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
-    if (!lp)
-       return NULL;
-    memset(lp, 0, sizeof(struct arcnet_local));
-
     /* fill in our module parameters as defaults */
     dev->dev_addr[0] = node;
     lp->timeout = timeout;
@@ -260,6 +269,14 @@ static dev_link_t *com20020_attach(void)
     }
 
     return link;
+
+fail_alloc_dev:
+    kfree(lp);
+fail_alloc_lp:
+    kfree(info);
+fail_alloc_info:
+    kfree(link);
+    return NULL;
 } /* com20020_attach */
 
 /*======================================================================
index 2819408451930970e2977b63bd76eeaef4735304..4415239ab52d87806bfd9f36836be23cee0fce7a 100644 (file)
  * 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
+ *
+ * Changes:
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/08/2000
+ * - reorganize kmallocs in ray_attach, checking all for failure
+ *   and releasing the previous allocations if one fails
+ *
  * 
 =============================================================================*/
 
@@ -333,7 +339,25 @@ static dev_link_t *ray_attach(void)
 
     /* Initialize the dev_link_t structure */
     link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
+
+    if (!link)
+           return NULL;
+
+    /* Allocate space for private device-specific data */
+    dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
+
+    if (!dev)
+           goto fail_alloc_dev;
+
+    local = kmalloc(sizeof(ray_dev_t), GFP_KERNEL);
+
+    if (!local)
+           goto fail_alloc_local;
+
     memset(link, 0, sizeof(struct dev_link_t));
+    memset(dev, 0, sizeof(struct net_device));
+    memset(local, 0, sizeof(ray_dev_t));
+
     link->release.function = &ray_release;
     link->release.data = (u_long)link;
 
@@ -355,14 +379,9 @@ static dev_link_t *ray_attach(void)
     link->conf.ConfigIndex = 1;
     link->conf.Present = PRESENT_OPTION;
 
-    /* Allocate space for private device-specific data */
-    dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
-    memset(dev, 0, sizeof(struct net_device));
     link->priv = dev;
     link->irq.Instance = dev;
     
-    local = kmalloc(sizeof(ray_dev_t), GFP_KERNEL);
-    memset(local, 0, sizeof(ray_dev_t));
     dev->priv = local;
     local->finder = link;
     link->dev = &local->node;
@@ -416,6 +435,12 @@ static dev_link_t *ray_attach(void)
     }
     DEBUG(2,"ray_cs ray_attach ending\n");
     return link;
+
+fail_alloc_local:
+    kfree(dev);
+fail_alloc_dev:
+    kfree(link);
+    return NULL;
 } /* ray_attach */
 /*=============================================================================
     This deletes a driver "instance".  The device is de-registered
index 84dc28025bfd5660bad7b8a46ace07600da69bb9..0f624fccdcebb5c7686dca4e6ce9e371e71c6426 100644 (file)
@@ -5,12 +5,13 @@
  * PPPoE --- PPP over Ethernet (RFC 2516)
  *
  *
- * Version:    0.6.0
+ * Version:    0.6.1
  *
  * 030700 :     Fixed connect logic to allow for disconnect.
  * 270700 :    Fixed potential SMP problems; we must protect against 
  *             simultaneous invocation of ppp_input 
  *             and ppp_unregister_channel.
+ * 040800 :    Respect reference count mechanisms on net-devices.
  *
  *             Module reference count is decremented in the right spot now,
  *             guards against sock_put not actually freeing the sk 
@@ -169,36 +170,6 @@ static struct pppox_opt *__delete_item(unsigned long sid, char *addr)
        return ret;
 }
 
-static struct pppox_opt *__find_on_dev(struct net_device *dev,
-                                      struct pppox_opt *start)
-{
-       struct pppox_opt *po;
-       int hash;
-
-       if (start != NULL) {
-               hash = hash_item(start->pppoe_pa.sid, start->pppoe_pa.remote);
-               po   = start;
-       } else {
-               hash = 0;
-               po   = NULL;
-
-               while (!po && ++hash < PPPOE_HASH_SIZE)
-                       po = item_hash_table[hash];
-       }
-       
-       while (po && (po->pppoe_dev != dev)){
-               if (po->next) {
-                       po = po->next;
-               } else {
-                       po = NULL;
-                       while (!po && ++hash < PPPOE_HASH_SIZE)
-                               po = item_hash_table[hash];
-               }
-       }
-
-       return po;
-}
-
 /**********************************************************************
  *
  *  Set/get/delete/rehash items
@@ -248,17 +219,7 @@ static inline struct pppox_opt *delete_item(unsigned long sid, char *addr)
        return ret;
 }
 
-static struct pppox_opt *find_on_dev(struct net_device *dev,
-                                    struct pppox_opt *start)
-{
-       struct pppox_opt *po;
-       read_lock_bh(&pppoe_hash_lock);
-       po = __find_on_dev(dev,start);
-       if(po)
-               sock_hold(po->sk);
-       read_unlock_bh(&pppoe_hash_lock);
-       return po;
-}
+
 
 /***************************************************************************
  *
@@ -272,6 +233,7 @@ static int pppoe_device_event(struct notifier_block *this,
        int error = NOTIFY_DONE;
        struct net_device *dev = (struct net_device *) ptr;
        struct pppox_opt *po = NULL;
+       int hash = 0;
        
        /* Only look at sockets that are using this specific device. */
        switch (event) {
@@ -281,20 +243,40 @@ static int pppoe_device_event(struct notifier_block *this,
             */
        case NETDEV_GOING_DOWN:
        case NETDEV_DOWN:
-               do {
-                       po = find_on_dev(dev, po);
-                       if(!po)
-                               break;
-                       
-                       lock_sock(po->sk);
-                       if (po->sk->state & PPPOX_CONNECTED)
-                               pppox_unbind_sock(po->sk);
-
-                       release_sock(po->sk);
-                       sock_put(po->sk);
 
-               } while (1);
+               /* Find every socket on this device and kill it. */
+               read_lock_bh(&pppoe_hash_lock);
 
+               while (!po && hash < PPPOE_HASH_SIZE){
+                       po = item_hash_table[hash];
+                       ++hash;
+               }
+       
+               while (po && hash < PPPOE_HASH_SIZE){
+                       if(po->pppoe_dev == dev){
+                               lock_sock(po->sk);
+                               if (po->sk->state & (PPPOX_CONNECTED|PPPOX_BOUND)){
+                                       pppox_unbind_sock(po->sk);
+                               
+                                       dev_put(po->pppoe_dev);
+                                       po->pppoe_dev = NULL;
+
+                                       po->sk->state = PPPOX_DEAD;
+                                       po->sk->state_change(po->sk);
+                               }
+                               release_sock(po->sk);
+                       }
+                       if (po->next) {
+                               po = po->next;
+                       } else {
+                               po = NULL;
+                               while (!po && hash < PPPOE_HASH_SIZE){
+                                       po = item_hash_table[hash];
+                                       ++hash;
+                               }
+                       }
+               }
+               read_unlock_bh(&pppoe_hash_lock);
                break;
        default:
                break;
@@ -320,34 +302,32 @@ static struct notifier_block pppoe_notifier = {
  ***********************************************************************/
 int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb){
        struct pppox_opt  *po=sk->protinfo.pppox;
+       struct pppox_opt *relay_po = NULL;
 
        if (sk->state & PPPOX_BOUND) {
                skb_pull(skb, sizeof(struct pppoe_hdr));
                
                ppp_input(&po->chan, skb);
        } else if( sk->state & PPPOX_RELAY ){
-               struct pppox_opt *relay_po;
 
                relay_po = get_item_by_addr( &po->pppoe_relay );
 
                if( relay_po == NULL  ||
                    !( relay_po->sk->state & PPPOX_CONNECTED ) ){
-                       sock_put(relay_po->sk);
                        goto abort;
                }
                
                skb_pull(skb, sizeof(struct pppoe_hdr));
                if( !__pppoe_xmit( relay_po->sk , skb) ){
-                       sock_put(relay_po->sk);
                        goto abort;
                }
-
        } else {
                sock_queue_rcv_skb(sk, skb);
        }
        return 1;
 abort:
-       sock_put(sk);
+       if(relay_po)
+               sock_put(relay_po->sk);
        return 0;
 
 }
@@ -462,20 +442,19 @@ struct packet_type pppoed_ptype = {
        NULL
 };
 
-/**********************************************************************
+/***********************************************************************
  *
- * The destruct hook --- this can be trashed if there is no need for
- * the sock to clear its receive queue?
+ * Really kill the socket. (Called from sock_put if refcnt == 0.)
  *
- *********************************************************************/
-void sock_pppoe_destruct(struct sock *sk)
+ **********************************************************************/
+void pppoe_sock_destruct(struct sock *sk)
 {
        if (sk->protinfo.destruct_hook)
                kfree(sk->protinfo.destruct_hook);
-
        MOD_DEC_USE_COUNT;
 }
 
+
 /***********************************************************************
  *
  * Initialize a new struct sock.
@@ -505,6 +484,7 @@ static int pppoe_create(struct socket *sock)
        sk->pprev = NULL;
        sk->state = PPPOX_NONE;
        sk->type = SOCK_STREAM;
+       sk->destruct = pppoe_sock_destruct;
 
        sk->protinfo.pppox = kmalloc(sizeof(struct pppox_opt), GFP_KERNEL);
        if (!sk->protinfo.pppox) {
@@ -546,6 +526,9 @@ int pppoe_release(struct socket *sock)
        po = sk->protinfo.pppox;
        if (po->pppoe_pa.sid)
                delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
+               
+       if (po->pppoe_dev)
+           dev_put(po->pppoe_dev);
 
        /* Should also do a queue purge here */
 
@@ -555,7 +538,6 @@ int pppoe_release(struct socket *sock)
        skb_queue_purge(&sk->receive_queue);
 
        sock_put(sk);
-       MOD_DEC_USE_COUNT;
 
        return error;
 }
@@ -576,14 +558,15 @@ int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
        if (sp->sa_protocol != PX_PROTO_OE)
                goto end;
 
+       /* Check for already bound sockets */
        error = -EBUSY;
        if ((sk->state & PPPOX_CONNECTED) && sp->sa_addr.pppoe.sid)
                goto end;
 
-       dev = dev_get_by_name(sp->sa_addr.pppoe.dev);
-               
-       error = -ENODEV;
-       if (!dev)
+       /* Check for already disconnected sockets, 
+          on attempts to disconnect */
+       error = -EALREADY;
+       if((sk->state & PPPOX_DEAD) && !sp->sa_addr.pppoe.sid )
                goto end;
 
        error = 0;
@@ -593,6 +576,8 @@ int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
                /* Delete the old binding */
                delete_item(po->pppoe_pa.sid,po->pppoe_pa.remote);
 
+               dev_put(po->pppoe_dev);
+
                memset(po, 0, sizeof(struct pppox_opt));
                po->sk = sk;
 
@@ -601,6 +586,14 @@ int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
 
        /* Don't re-bind if sid==0 */
        if (sp->sa_addr.pppoe.sid != 0) {
+               dev = dev_get_by_name(sp->sa_addr.pppoe.dev);
+           
+               error = -ENODEV;
+               if (!dev)
+                       goto end;
+
+               if( ! (dev->flags & IFF_UP) )
+                       goto end;
                memcpy(&po->pppoe_pa,
                       &sp->sa_addr.pppoe,
                       sizeof(struct pppoe_addr));
@@ -773,6 +766,8 @@ int pppoe_sendmsg(struct socket *sock, struct msghdr *m,
        hdr.code = 0;
        hdr.sid = sk->num;
 
+       lock_sock(sk);
+
        dev = sk->protinfo.pppox->pppoe_dev;
 
        skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32,
@@ -785,14 +780,19 @@ int pppoe_sendmsg(struct socket *sock, struct msghdr *m,
        /* Reserve space for headers. */
        skb_reserve(skb, dev->hard_header_len);
        skb->nh.raw = skb->data;
-       skb->dev = dev;
+
+       skb->rx_dev = skb->dev = dev;
+       dev_hold(skb->rx_dev);
+
        skb->priority = sk->priority;
        skb->protocol = __constant_htons(ETH_P_PPP_SES);
 
        ph = (struct pppoe_hdr *) skb_put(skb, total_len + sizeof(struct pppoe_hdr));
        start = (char *) &ph->tag[0];
 
-       copied = memcpy_fromiovec( start, m->msg_iov, m->msg_iovlen);
+       error = copied = memcpy_fromiovec( start, m->msg_iov, m->msg_iovlen);
+       if( error <= 0 )
+           goto end;
 
        dev->hard_header(skb, dev, ETH_P_PPP_SES,
                         sk->protinfo.pppox->pppoe_pa.remote,
@@ -803,9 +803,9 @@ int pppoe_sendmsg(struct socket *sock, struct msghdr *m,
        ph->length = htons(copied);
 
        dev_queue_xmit(skb);
-       return copied;
 
 end:
+       release_sock(sk);
        return error;
 }
 
@@ -860,7 +860,12 @@ int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
        skb->protocol = __constant_htons(ETH_P_PPP_SES);
 
        skb->nh.raw = skb->data;
-       skb->dev = dev;
+
+       /* Change device of skb, update reference counts */
+       if(skb->rx_dev)
+           dev_put(skb->rx_dev);
+       skb->rx_dev = skb->dev = dev;
+       dev_hold(skb->rx_dev);
 
        dev->hard_header(skb, dev, ETH_P_PPP_SES,
                         sk->protinfo.pppox->pppoe_pa.remote,
index d709ac2ca5a57fa8823c96b6ca33e08e1718c10d..3a03fa964bebc229883b23987f8a358a4cacc259 100644 (file)
@@ -1,8 +1,8 @@
 /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
    Copyright 1999 Silicon Integrated System Corporation 
-   Revision:   1.07    Mar. 07 2000
-   
-   Modified from the driver which is originally written by Donald Becker. 
+   Revision:   1.07.01 Aug. 08 2000
+
+   Modified from the driver which is originally written by Donald Becker.
    
    This software may be used and distributed according to the terms
    of the GNU Public License (GPL), incorporated herein by reference.
    preliminary Rev. 1.0 Jan. 18, 1998
    http://www.sis.com.tw/support/databook.htm
 
+   Rev 1.07.01 Aug. 08 2000 Ollie Lho minor update fro SiS 630E and SiS 630E A1
    Rev 1.07 Mar. 07 2000 Ollie Lho bug fix in Rx buffer ring
    Rev 1.06.04 Feb. 11 2000 Jeff Garzik <jgarzik@mandrakesoft.com> softnet and init for kernel 2.4
    Rev 1.06.03 Dec. 23 1999 Ollie Lho Third release
-   Rev 1.06.02 Nov. 23 1999 Ollie Lho bug in mac probing fixed 
+   Rev 1.06.02 Nov. 23 1999 Ollie Lho bug in mac probing fixed
    Rev 1.06.01 Nov. 16 1999 Ollie Lho CRC calculation provide by Joseph Zbiciak (im14u2c@primenet.com)
    Rev 1.06 Nov. 4 1999 Ollie Lho (ollie@sis.com.tw) Second release
-   Rev 1.05.05 Oct. 29 1999 Ollie Lho (ollie@sis.com.tw) Single buffer Tx/Rx  
+   Rev 1.05.05 Oct. 29 1999 Ollie Lho (ollie@sis.com.tw) Single buffer Tx/Rx
    Chin-Shan Li (lcs@sis.com.tw) Added AMD Am79c901 HomePNA PHY support
    Rev 1.05 Aug. 7 1999 Jim Huang (cmhuang@sis.com.tw) Initial release
 */
@@ -53,7 +54,7 @@
 #include "sis900.h"
 
 static const char *version =
-"sis900.c: v1.07  03/07/2000\n";
+"sis900.c: v1.07.01  08/08/2000\n";
 
 static int max_interrupt_work = 20;
 static int multicast_filter_limit = 128;
@@ -109,23 +110,23 @@ struct mii_phy {
 };
 
 typedef struct _BufferDesc {
-       u32     link;
-       u32     cmdsts;
-       u32     bufptr;
+       u32     link;
+       u32     cmdsts;
+       u32     bufptr;
 } BufferDesc;
 
 struct sis900_private {
        struct net_device_stats stats;
        struct pci_dev * pci_dev;
-       
+
        spinlock_t lock;
 
        struct mii_phy * mii;
        unsigned int cur_phy;
 
-       struct timer_list timer;                        /* Link status detection timer. */
+       struct timer_list timer;                        /* Link status detection timer. */
 
-       unsigned int cur_rx, dirty_rx;
+       unsigned int cur_rx, dirty_rx;          /* producer/comsumer pointers for Tx/Rx ring */
        unsigned int cur_tx, dirty_tx;
 
        /* The saved address of a sent/receive-in-place packet buffer */
@@ -196,32 +197,102 @@ static int __init sis900_probe (struct pci_dev *pci_dev, const struct pci_device
        return 0;
 }
 
-static struct net_device * __init sis900_mac_probe (struct pci_dev * pci_dev, char * card_name)
+/* older SiS900 and friends, use EEPROM to store MAC address */
+static int sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
 {
-       struct sis900_private *sis_priv;
        long ioaddr = pci_resource_start(pci_dev, 0);
-       struct net_device *net_dev = NULL;
-       int irq = pci_dev->irq;
        u16 signature;
        int i;
 
-       if ((net_dev = init_etherdev(net_dev, 0)) == NULL)
-               return NULL;
-
        /* check to see if we have sane EEPROM */
        signature = (u16) read_eeprom(ioaddr, EEPROMSignature);    
        if (signature == 0xffff || signature == 0x0000) {
                printk (KERN_INFO "%s: Error EERPOM read %x\n", 
                        net_dev->name, signature);
+               return 0;
+       }
+
+       /* get MAC address from EEPROM */
+       for (i = 0; i < 3; i++)
+               ((u16 *)(net_dev->dev_addr))[i] = read_eeprom(ioaddr, i+EEPROMMACAddr);
+
+       return 1;
+}
+
+/* SiS630E model, use APC CMOS RAM to store MAC address */
+static int sis630e_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
+{
+       struct pci_dev *isa_bridge = NULL;
+       u8 reg;
+       int i;
+
+       if ((isa_bridge = pci_find_device(0x1039, 0x0008, isa_bridge)) == NULL) {
+               printk("%s: Can not find ISA bridge\n", net_dev->name);
+               return 0;
+       }
+       pci_read_config_byte(isa_bridge, 0x48, &reg);
+       pci_write_config_byte(isa_bridge, 0x48, reg | 0x40);
+
+       for (i = 0; i < 6; i++) {
+               outb(0x09 + i, 0x70);
+               ((u8 *)(net_dev->dev_addr))[i] = inb(0x71); 
+       }
+       pci_write_config_byte(isa_bridge, 0x48, reg & ~0x40);
+
+       return 1;
+}
+
+/* SiS630E A1, The Mac address is hardcoded in the RFCR register so it is actually not necessary to
+   probe the MAC address */
+static int sis630ea1_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
+{
+       long ioaddr = pci_resource_start(pci_dev, 0);
+       u32 reg;
+       int i;
+
+       /* reload MAC address */
+       reg = inl(ioaddr + cr);
+       outl(reg | RELOAD, ioaddr + cr);
+
+       reg = inl(ioaddr + cr);
+       outl(reg & ~RELOAD, ioaddr + cr);
+
+       for (i = 0; i < 3; i++) {
+               outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr);
+               ((u16 *)(net_dev->dev_addr))[i] = inl(ioaddr + rfdr);
+       }
+
+       return 1;
+}
+
+static struct net_device * __init sis900_mac_probe (struct pci_dev * pci_dev, char * card_name)
+{
+       struct sis900_private *sis_priv;
+       long ioaddr = pci_resource_start(pci_dev, 0);
+       struct net_device *net_dev = NULL;
+       int irq = pci_dev->irq;
+       int i, ret = 0;
+       u8 revision;
+
+       if ((net_dev = init_etherdev(net_dev, 0)) == NULL)
+               return NULL;
+
+       pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
+       if (revision == SIS630E_REV)
+               ret = sis630e_get_mac_addr(pci_dev, net_dev);
+       else if (revision == SIS630EA1_REV)
+               ret = sis630ea1_get_mac_addr(pci_dev, net_dev);
+       else
+               ret = sis900_get_mac_addr(pci_dev, net_dev);
+
+       if (ret == 0) {
+               unregister_netdevice(net_dev);
                return NULL;
        }
 
+       /* print some information about our NIC */
        printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", net_dev->name,
               card_name, ioaddr, irq);
-
-       /* get MAC address from EEPROM */
-       for (i = 0; i < 3; i++)
-               ((u16 *)(net_dev->dev_addr))[i] = read_eeprom(ioaddr, i+EEPROMMACAddr);
        for (i = 0; i < 5; i++)
                printk("%2.2x:", (u8)net_dev->dev_addr[i]);
        printk("%2.2x.\n", net_dev->dev_addr[i]);
@@ -269,58 +340,69 @@ static int __init sis900_mii_probe (struct net_device * net_dev)
 {
        struct sis900_private * sis_priv = (struct sis900_private *)net_dev->priv;
        int phy_addr;
-       
+       u8 revision;
+
        sis_priv->mii = NULL;
-       
+
        /* search for total of 32 possible mii phy addresses */
        for (phy_addr = 0; phy_addr < 32; phy_addr++) {
                u16 mii_status;
                u16 phy_id0, phy_id1;
                int i;
-               
+
                mii_status = mdio_read(net_dev, phy_addr, MII_STATUS);
                if (mii_status == 0xffff || mii_status == 0x0000)
                        /* the mii is not accessable, try next one */
                        continue;
-               
+
                phy_id0 = mdio_read(net_dev, phy_addr, MII_PHY_ID0);
                phy_id1 = mdio_read(net_dev, phy_addr, MII_PHY_ID1);
-               
+
                /* search our mii table for the current mii */ 
                for (i = 0; mii_chip_table[i].phy_id1; i++)
                        if (phy_id0 == mii_chip_table[i].phy_id0) {
                                struct mii_phy * mii_phy;
-                               
-                               printk(KERN_INFO 
+
+                               printk(KERN_INFO
                                       "%s: %s transceiver found at address %d.\n",
-                                      net_dev->name, mii_chip_table[i].name, 
+                                      net_dev->name, mii_chip_table[i].name,
                                       phy_addr);;
                                if ((mii_phy = kmalloc(sizeof(struct mii_phy), GFP_KERNEL)) != NULL) {
                                        mii_phy->chip_info = mii_chip_table+i;
                                        mii_phy->phy_addr = phy_addr;
-                                       mii_phy->status = mdio_read(net_dev, phy_addr, 
+                                       mii_phy->status = mdio_read(net_dev, phy_addr,
                                                                    MII_STATUS);
                                        mii_phy->next = sis_priv->mii;
                                        sis_priv->mii = mii_phy;
                                }
-                               /* the current mii is on our mii_info_table, 
+                               /* the current mii is on our mii_info_table,
                                   try next address */
                                break;
                        }
        }
-       
+
        if (sis_priv->mii == NULL) {
-               printk(KERN_INFO "%s: No MII transceivers found!\n", 
+               printk(KERN_INFO "%s: No MII transceivers found!\n",
                       net_dev->name);
                return 0;
        }
 
-       /* arbitrary choose that last PHY and current PHY */
+       /* arbitrary choose that last PHY as current PHY */
        sis_priv->cur_phy = sis_priv->mii->phy_addr;
        printk(KERN_INFO "%s: Using %s as default\n", net_dev->name,
               sis_priv->mii->chip_info->name);
 
-       if (sis_priv->mii->status & MII_STAT_LINK) 
+       pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision);
+       if (revision == SIS630E_REV) {
+               /* SiS 630E has some bugs on default value of PHY registers */
+               mdio_write(net_dev, sis_priv->cur_phy, MII_ANADV, 0x05e1);
+               mdio_write(net_dev, sis_priv->cur_phy, MII_CONFIG1, 0x22);
+               mdio_write(net_dev, sis_priv->cur_phy, MII_CONFIG2, 0xff00);
+               mdio_write(net_dev, sis_priv->cur_phy, MII_MASK, 0xffc0);
+               mdio_write(net_dev, sis_priv->cur_phy, MII_CONTROL, 0x1000);    
+       }
+
+       if (sis_priv->mii->status & MII_STAT_LINK)
                sis_priv->LinkOn = TRUE;
        else
                sis_priv->LinkOn = FALSE;
@@ -365,7 +447,7 @@ static u16 read_eeprom(long ioaddr, int location)
                retval = (retval << 1) | ((inl(ee_addr) & EEDO) ? 1 : 0);
                eeprom_delay();
        }
-               
+
        /* Terminate the EEPROM access. */
        outl(0, ee_addr);
        eeprom_delay();
@@ -426,6 +508,8 @@ static u16 mdio_read(struct net_device *net_dev, int phy_id, int location)
                outl(MDC, mdio_addr);
                mdio_delay();
        }
+       outl(0x00, mdio_addr);
+
        return retval;
 }
 
@@ -454,10 +538,10 @@ static void mdio_write(struct net_device *net_dev, int phy_id, int location, int
                outl(dataval, mdio_addr);
                mdio_delay();
                outl(dataval | MDC, mdio_addr);
-               mdio_delay();
+               mdio_delay();
        }
        mdio_delay();
-       
+
        /* Clear out extra bits. */
        for (i = 2; i > 0; i--) {
                outb(0, mdio_addr);
@@ -465,6 +549,8 @@ static void mdio_write(struct net_device *net_dev, int phy_id, int location, int
                outb(MDC, mdio_addr);
                mdio_delay();
        }
+       outl(0x00, mdio_addr);
+
        return;
 }
 
@@ -518,7 +604,7 @@ sis900_init_rxfilter (struct net_device * net_dev)
        long ioaddr = net_dev->base_addr;
        u32 rfcrSave;
        u32 i;
-       
+
        rfcrSave = inl(rfcr + ioaddr);
 
        /* disable packet filtering before setting filter */
@@ -547,12 +633,12 @@ static void
 sis900_init_tx_ring(struct net_device *net_dev)
 {
        struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv;
-       long ioaddr = net_dev->base_addr; 
+       long ioaddr = net_dev->base_addr;
        int i;
-       
+
        sis_priv->tx_full = 0;
        sis_priv->dirty_tx = sis_priv->cur_tx = 0;
-       
+
        for (i = 0; i < NUM_TX_DESC; i++) {
                sis_priv->tx_skbuff[i] = NULL;
 
@@ -563,21 +649,21 @@ sis900_init_tx_ring(struct net_device *net_dev)
        sis_priv->tx_ring[i-1].link = (u32) virt_to_bus(&sis_priv->tx_ring[0]);
 
        /* load Transmit Descriptor Register */
-       outl(virt_to_bus(&sis_priv->tx_ring[0]), ioaddr + txdp); 
+       outl(virt_to_bus(&sis_priv->tx_ring[0]), ioaddr + txdp);
        if (sis900_debug > 2)
-               printk(KERN_INFO "%s: TX descriptor register loaded with: %8.8x\n", 
+               printk(KERN_INFO "%s: TX descriptor register loaded with: %8.8x\n",
                       net_dev->name, inl(ioaddr + txdp));
 }
 
-/* Initialize the Rx descriptor ring, pre-allocate recevie buffers */ 
+/* Initialize the Rx descriptor ring, pre-allocate recevie buffers */
 static void 
-sis900_init_rx_ring(struct net_device *net_dev) 
-{ 
-       struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv; 
-       long ioaddr = net_dev->base_addr; 
+sis900_init_rx_ring(struct net_device *net_dev)
+{
+       struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv;
+       long ioaddr = net_dev->base_addr;
        int i;
-       sis_priv->cur_rx = 0; 
+
+       sis_priv->cur_rx = 0;
        sis_priv->dirty_rx = 0;
 
        /* init RX descriptor */
@@ -596,8 +682,8 @@ sis900_init_rx_ring(struct net_device *net_dev)
 
                if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
                        /* not enough memory for skbuff, this makes a "hole"
-                          on the buffer ring, it is not clear how the 
-                          hardware will react to this kind of degenerated 
+                          on the buffer ring, it is not clear how the
+                          hardware will react to this kind of degenerated
                           buffer */
                        break;
                }
@@ -611,7 +697,7 @@ sis900_init_rx_ring(struct net_device *net_dev)
        /* load Receive Descriptor Register */
        outl(virt_to_bus(&sis_priv->rx_ring[0]), ioaddr + rxdp);
        if (sis900_debug > 2)
-               printk(KERN_INFO "%s: RX descriptor register loaded with: %8.8x\n", 
+               printk(KERN_INFO "%s: RX descriptor register loaded with: %8.8x\n",
                       net_dev->name, inl(ioaddr + rxdp));
 }
 /* on each timer ticks we check two things, Link Status (ON/OFF) and 
@@ -625,11 +711,12 @@ static void sis900_timer(unsigned long data)
        static int next_tick = 5*HZ;
        u16 status;
 
+       status = mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS);
        status = mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS);
 
        /* current mii phy is failed to link, try another one */
-       while (!(status & MII_STAT_LINK)) {             
-               if (mii_phy->next == NULL) { 
+       while (!(status & MII_STAT_LINK)) {
+               if (mii_phy->next == NULL) {
                        if (sis_priv->LinkOn) {
                                /* link stat change from ON to OFF */
                                next_tick = HZ;
@@ -653,11 +740,13 @@ static void sis900_timer(unsigned long data)
                if (mii_phy->phy_addr != sis_priv->cur_phy) {
                        printk(KERN_INFO "%s: Changing transceiver to %s\n",
                               net_dev->name, mii_phy->chip_info->name);
+                       /* disable previous PHY */
                        status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL);
-                       mdio_write(net_dev, sis_priv->cur_phy, 
+                       mdio_write(net_dev, sis_priv->cur_phy,
                                   MII_CONTROL, status | MII_CNTL_ISOLATE);
+                       /* enable next PHY */
                        status = mdio_read(net_dev, mii_phy->phy_addr, MII_CONTROL);
-                       mdio_write(net_dev, mii_phy->phy_addr, 
+                       mdio_write(net_dev, mii_phy->phy_addr,
                                   MII_CONTROL, status & ~MII_CNTL_ISOLATE);
                        sis_priv->cur_phy = mii_phy->phy_addr;
                }
@@ -700,7 +789,7 @@ static void sis900_read_mode(struct net_device *net_dev, int phy_addr, int *spee
 {
        int i = 0;
        u32 status;
-       
+
        /* STSOUT register is Latched on Transition, read operation updates it */
        while (i++ < 2)
                status = mdio_read(net_dev, phy_addr, MII_STSOUT);
@@ -718,9 +807,9 @@ static void sis900_read_mode(struct net_device *net_dev, int phy_addr, int *spee
        if (status & MII_STSOUT_LINK_FAIL)
                printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
        else
-               printk(KERN_INFO "%s: Media Link On %s %s-duplex \n", 
+               printk(KERN_INFO "%s: Media Link On %s %s-duplex \n",
                       net_dev->name,
-                      *speed == HW_SPEED_100_MBPS ? 
+                      *speed == HW_SPEED_100_MBPS ?
                       "100mbps" : "10mbps",
                       *duplex == FDX_CAPABLE_FULL_SELECTED ?
                       "full" : "half");
@@ -729,7 +818,7 @@ static void amd79c901_read_mode(struct net_device *net_dev, int phy_addr, int *s
 {
        int i;
        u16 status;
-       
+
        for (i = 0; i < 2; i++)
                status = mdio_read(net_dev, phy_addr, MII_STATUS);
 
@@ -747,22 +836,21 @@ static void amd79c901_read_mode(struct net_device *net_dev, int phy_addr, int *s
                        *duplex = FDX_CAPABLE_HALF_SELECTED;
 
                if (status & MII_STSSUM_LINK)
-                       printk(KERN_INFO "%s: Media Link On %s %s-duplex \n", 
+                       printk(KERN_INFO "%s: Media Link On %s %s-duplex \n",
                               net_dev->name,
-                              *speed == HW_SPEED_100_MBPS ? 
+                              *speed == HW_SPEED_100_MBPS ?
                               "100mbps" : "10mbps",
                               *duplex == FDX_CAPABLE_FULL_SELECTED ?
                               "full" : "half");
                else
                        printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
-                       
        }
        else {
                /* HomePNA */
                *speed = HW_SPEED_HOME;
                *duplex = FDX_CAPABLE_HALF_SELECTED;
                if (status & MII_STAT_LINK)
-                       printk(KERN_INFO "%s: Media Link On 1mbps half-duplex \n", 
+                       printk(KERN_INFO "%s: Media Link On 1mbps half-duplex \n",
                               net_dev->name);
                else
                        printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
@@ -777,7 +865,7 @@ static void sis900_tx_timeout(struct net_device *net_dev)
 
        printk(KERN_INFO "%s: Transmit timeout, status %8.8x %8.8x \n",
               net_dev->name, inl(ioaddr + cr), inl(ioaddr + isr));
-       
+
        /* Disable interrupts by clearing the interrupt mask. */
        outl(0x0000, ioaddr + imr);
 
@@ -864,7 +952,7 @@ static void sis900_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 
        do {
                status = inl(ioaddr + isr);
-               
+
                if ((status & (HIBERR|TxURN|TxERR|TxIDLE|RxORN|RxERR|RxOK)) == 0)
                        /* nothing intresting happened */
                        break;
@@ -891,7 +979,7 @@ static void sis900_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                        break;
                }
        } while (1);
-       
+
        if (sis900_debug > 3)
                printk(KERN_INFO "%s: exiting interrupt, "
                       "interrupt status = 0x%#8.8x.\n",
@@ -909,17 +997,17 @@ static int sis900_rx(struct net_device *net_dev)
        long ioaddr = net_dev->base_addr;
        unsigned int entry = sis_priv->cur_rx % NUM_RX_DESC;
        u32 rx_status = sis_priv->rx_ring[entry].cmdsts;
-       
+
        if (sis900_debug > 3)
                printk(KERN_INFO "sis900_rx, cur_rx:%4.4d, dirty_rx:%4.4d "
                       "status:0x%8.8x\n",
                       sis_priv->cur_rx, sis_priv->dirty_rx, rx_status);
-       
+
        while (rx_status & OWN) {
                unsigned int rx_size;
-               
+
                rx_size = (rx_status & DSIZE) - CRC_SIZE;
-               
+
                if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
                        /* corrupted packet received */
                        if (sis900_debug > 3)
@@ -939,15 +1027,15 @@ static int sis900_rx(struct net_device *net_dev)
                        sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE;
                } else {
                        struct sk_buff * skb;
-                       
+
                        /* This situation should never happen, but due to
                           some unknow bugs, it is possible that
-                          we are working on NULL sk_buff :-( */                        
+                          we are working on NULL sk_buff :-( */
                        if (sis_priv->rx_skbuff[entry] == NULL) {
                                printk(KERN_INFO "%s: NULL pointer " 
                                       "encountered in Rx ring, skipping\n",
                                       net_dev->name);
-                               break;                  
+                               break;
                        }
 
                        /* gvie the socket buffer to upper layers */
@@ -990,14 +1078,14 @@ static int sis900_rx(struct net_device *net_dev)
                entry = sis_priv->cur_rx % NUM_RX_DESC;
                rx_status = sis_priv->rx_ring[entry].cmdsts;
        } // while
-       
+
        /* refill the Rx buffer, what if the rate of refilling is slower than 
           consuming ?? */
        for (;sis_priv->cur_rx - sis_priv->dirty_rx > 0; sis_priv->dirty_rx++) {
                struct sk_buff *skb;
-               
+
                entry = sis_priv->dirty_rx % NUM_RX_DESC;
-               
+
                if (sis_priv->rx_skbuff[entry] == NULL) {
                        if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
                                /* not enough memory for skbuff, this makes a "hole"
@@ -1018,7 +1106,7 @@ static int sis900_rx(struct net_device *net_dev)
        }
        /* re-enable the potentially idle receive state matchine */
        outl(RxENA , ioaddr + cr );
-       
+
        return 0;
 }
 
@@ -1027,21 +1115,21 @@ static int sis900_rx(struct net_device *net_dev)
 static void sis900_finish_xmit (struct net_device *net_dev)
 {
        struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv;
-       
+
        for (; sis_priv->dirty_tx < sis_priv->cur_tx; sis_priv->dirty_tx++) {
                unsigned int entry;
                u32 tx_status;
-               
+
                entry = sis_priv->dirty_tx % NUM_TX_DESC;
                tx_status = sis_priv->tx_ring[entry].cmdsts;
-               
+
                if (tx_status & OWN) {
                        /* The packet is not transmited yet (owned by hardware) !
                           Note: the interrupt is generated only when Tx Machine
                           is idle, so this is an almost impossible case */
                        break;
                }
-               
+
                if (tx_status & (ABORT | UNDERRUN | OWCOLL)) {
                        /* packet unsuccessfully transmited */
                        if (sis900_debug > 3)
@@ -1069,8 +1157,8 @@ static void sis900_finish_xmit (struct net_device *net_dev)
                sis_priv->tx_ring[entry].bufptr = 0;
                sis_priv->tx_ring[entry].cmdsts = 0;
        }
-       
-       if (sis_priv->tx_full && netif_queue_stopped(net_dev) && 
+
+       if (sis_priv->tx_full && netif_queue_stopped(net_dev) &&
            sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC - 4) {
                /* The ring is no longer full, clear tx_full and schedule more transmission
                   by netif_wake_queue(net_dev) */
@@ -1085,7 +1173,7 @@ sis900_close(struct net_device *net_dev)
        long ioaddr = net_dev->base_addr;
        struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv;
        int i;
-       
+
        netif_stop_queue(net_dev);
 
        /* Disable interrupts by clearing the interrupt mask. */
index c63a3212a08c3fad5cc67b5c1bc6b34bf8878ca5..93609cd0805e38ae75f9d7d81aaa142f8c230322 100644 (file)
@@ -25,19 +25,20 @@ enum sis900_registers {
        ier=0x18,               //Interrupt Enable Register
        epar=0x18,              //Enhanced PHY Access Register
        txdp=0x20,              //Transmit Descriptor Pointer Register
-       txcfg=0x24,             //Transmit Configuration Register
-       rxdp=0x30,              //Receive Descriptor Pointer Register
-       rxcfg=0x34,             //Receive Configuration Register
-       flctrl=0x38,            //Flow Control Register
-       rxlen=0x3c,             //Receive Packet Length Register
-       rfcr=0x48,              //Receive Filter Control Register
-       rfdr=0x4C,              //Receive Filter Data Register
-       pmctrl=0xB0,            //Power Management Control Register
-       pmer=0xB4               //Power Management Wake-up Event Register
+        txcfg=0x24,             //Transmit Configuration Register
+        rxdp=0x30,              //Receive Descriptor Pointer Register
+        rxcfg=0x34,             //Receive Configuration Register
+        flctrl=0x38,            //Flow Control Register
+        rxlen=0x3c,             //Receive Packet Length Register
+        rfcr=0x48,              //Receive Filter Control Register
+        rfdr=0x4C,              //Receive Filter Data Register
+        pmctrl=0xB0,            //Power Management Control Register
+        pmer=0xB4               //Power Management Wake-up Event Register
 };
 
 /* Symbolic names for bits in various registers */
 enum sis900_command_register_bits {
+       RELOAD  = 0x00000400,
        RESET   = 0x00000100, SWI = 0x00000080, RxRESET = 0x00000020,
        TxRESET = 0x00000010, RxDIS = 0x00000008, RxENA = 0x00000004,
        TxDIS   = 0x00000002, TxENA = 0x00000001
@@ -216,6 +217,10 @@ enum mii_stssum_register_bits {
        MII_STSSUM_AUTO = 0x0002, MII_STSSUM_SPD  = 0x0001
 };
 
+enum sis630_revision_id {
+       SIS630E_REV = 0x81, SIS630EA1_REV = 0x83
+};
+
 #define FDX_CAPABLE_DUPLEX_UNKNOWN      0
 #define FDX_CAPABLE_HALF_SELECTED       1
 #define FDX_CAPABLE_FULL_SELECTED       2
index c1787a186db3438a605c0eac06b7a37cf0d70fce..e652711197e92a6536105b12a32d628364d82ceb 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/hitachi_se.h>
+#include <asm/machvec.h>
 
 #include "8390.h"
 
@@ -100,6 +101,10 @@ int __init stnic_probe(void)
   tmp.base_addr = 0x1000;
   dev = &tmp;
 
+  /* If we are not running on a SolutionEngine, give up now */
+  if (! MACH_SE)
+    return -ENODEV;
+
   if (load_8390_module ("stnic.c"))
     return -ENOSYS;
 
index 96b4ba97cbfdafffc27a5f86e93e4b859702db16..0c3a2f53364932cc75805ba4d52d10680bc54fa3 100644 (file)
 1105  Sigma Designs, Inc.
        8300  REALmagic Hollywood Plus DVD Decoder
 1106  VIA Technologies, Inc.
-       0305  VT8363 [KT133]
+       0305  VT8363/8365 [KT133/KM133]
        0391  VT8371 [KX133]
-       0501  VT8501
+       0501  VT8501 [Apollo MVP4]
        0505  VT82C505
        0561  VT82C561
-       0571  VT82C586 IDE [Apollo]
+       0571  Bus Master IDE
        0576  VT82C576 3V [Apollo Master]
        0585  VT82C585VP [Apollo VP1/VPX]
        0586  VT82C586/A/B PCI-to-ISA [Apollo VP]
                1106 0000  MVP3 ISA Bridge
        0595  VT82C595 [Apollo VP2]
-       0596  VT82C596 ISA [Apollo PRO]
+       0596  VT82C596 ISA [Mobile South]
                1106 0000  VT82C596/A/B PCI to ISA Bridge
                1458 0596  VT82C596/A/B PCI to ISA Bridge
        0597  VT82C597 [Apollo VP3]
        0598  VT82C598 [Apollo MVP3]
-       0601  VT8601
+       0601  VT8601 [Apollo ProMedia]
+       0605  VT8605 [ProSavage PM133]
        0680  VT82C680 [Apollo P6]
-       0686  VT82C686 [Apollo Super]
+       0686  VT82C686 [Apollo Super South]
                1106 0000  VT82C686/A PCI to ISA Bridge
                1106 0686  VT82C686/A PCI to ISA Bridge
-       0691  VT82C691 [Apollo PRO]
+       0691  VT82C693A/694x [Apollo PRO133x]
                1458 0691  VT82C691 Apollo Pro System Controller
+       0698  VT82C693A [Ppollo Pro133 AGP]
        0693  VT82C693 [Apollo Pro Plus]
        0926  VT82C926 [Amazon]
        1000  VT82C570MV
        1106  VT82C570MV
        1571  VT82C416MV
        1595  VT82C595/97 [Apollo VP2/97]
-       3038  VT82C586B USB
+       3038  UHCI USB
                1234 0925  MVP3 USB Controller
        3040  VT82C586B ACPI
        3043  VT86C100A [Rhine 10/100]
                1106 0100  VT86C100A Fast Ethernet Adapter
                1186 1400  DFE-530TX
        3044  OHCI Compliant IEEE 1394 Host Controller
+       3050  VT82C596 Power Management
+       3051  VT82C596 Power Management
        3057  VT82C686 [Apollo Super ACPI]
-       3058  VT82C686 [Apollo Super AC97/Audio]
+       3058  AC97 Audio Controller
                1462 3091  MS-6309 Onboard Audio
-       3068  VT82C686 [Apollo Super AC97/Modem]
+       3059  AC97 Audio Controller
+       3065  Ethernet Controller
+       3068  AC97 Modem Controller
+       3074  VT8233 PCI to ISA Bridge
+       3091  VT8633 [Apollo Pro266]
+       3099  VT8367 [KT266]
        5030  VT82C596 ACPI [Apollo PRO]
        6100  VT85C100A [Rhine II]
        8231  VT8231 [PCI-to-ISA Bridge]
-       8305  VT8363 [PCI-PCI Bridge]
-       8391  VT8371 [PCI-PCI Bridge]
-       8501  VT8501
+       8235  VT8235 Power Management
+       8305  VT8365 [KM133 AGP]
+       8391  VT8363/8371 [KT133/KX133 AGP] 
+       8501  VT8501 [Apollo MVP4 AGP]
        8596  VT82C596 [Apollo PRO AGP]
        8597  VT82C597 [Apollo VP3 AGP]
-       8598  VT82C598 [Apollo MVP3 AGP]
-       8601  VT8601
+       8598  VT82C598/694x [Apollo MVP3/Pro133x AGP]
+       8601  VT8601 [Apollo ProMedia AGP]
+       8605  VT8605 [PM133 AGP]
+       B091  VT8633 [Apollo Pro266 AGP]
+       B099  VT8367 [KT266 AGP]
        8691  VT82C691 [Apollo Pro]
 1107  Stratus Computers
        0576  VIA VT82C570MV [Apollo] (Wrong vendor ID!)
index fe26b4c0132775b6f2ab098f4b9f0ce9ce619d4d..360e77998e8b707001cdcc627511095f4fd67a7f 100644 (file)
@@ -30,9 +30,7 @@ if [ "$CONFIG_FB" = "y" ]; then
    if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
       bool '  Acorn VIDC support' CONFIG_FB_ACORN
    fi
-   if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then
-      tristate '  Cyber2000 support' CONFIG_FB_CYBER2000
-   fi
+   tristate '  Cyber2000 support' CONFIG_FB_CYBER2000
    if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
       bool '  SA-1100 LCD support' CONFIG_FB_SA1100
    fi
index e5e0e4aadb6c7ea7ed9be28ae4bcfb5eb1888882..5eb9970a294d87e6cc0e89c5732645b2645ba5fc 100644 (file)
@@ -1663,8 +1663,12 @@ acornfb_init(void)
                         sizeof(modedb) / sizeof(*modedb),
                         &acornfb_default_mode, DEFAULT_BPP);
 
-       if (!rc && fb_find_mode(&init_var, &fb_info, NULL, NULL, 0,
-                               &acornfb_default_mode, DEFAULT_BPP)) {
+       /*
+        * If we didn't find an exact match, try the
+        * generic database.
+        */
+       if (rc != 1 && fb_find_mode(&init_var, &fb_info, NULL, NULL, 0,
+                                   &acornfb_default_mode, DEFAULT_BPP)) {
                printk("Acornfb: no valid mode found\n");
        }
 
index e48d8a74ca81231109a3ff7c512eab04194ce800..91b2b77ebd58c88acea7f2463e1927e612524085 100644 (file)
@@ -110,8 +110,10 @@ static int hitfb_encode_fix(struct fb_fix_screeninfo *fix,
     default:
     case 8:
        fix->line_length = par->x;
+       break;
     case 16:
        fix->line_length = par->x*2;
+       break;
     }
 
     return 0;
index 851c547265c5f5cdabc36368480910b850453d1d..e48f7549692104c39364321deb4b9377bea1a700 100644 (file)
@@ -25,6 +25,9 @@ dep_tristate '    UMSDOS: Unix-like file system on top of standard MSDOS fs' CON
 dep_tristate '  VFAT (Windows-95) fs support' CONFIG_VFAT_FS $CONFIG_FAT_FS
 dep_tristate 'EFS file system support (read only) (EXPERIMENTAL)' CONFIG_EFS_FS $CONFIG_EXPERIMENTAL
 dep_tristate 'Journalling Flash File System (JFFS) support (EXPERIMENTAL)' CONFIG_JFFS_FS $CONFIG_EXPERIMENTAL $CONFIG_MTD
+if [ "$CONFIG_JFFS_FS" != "n" ] ; then
+       int 'JFFS debugging verbosity (0 = quiet, 3 = noisy)' CONFIG_JFFS_FS_VERBOSE 0
+fi
 tristate 'Compressed ROM file system support' CONFIG_CRAMFS
 tristate 'Simple RAM-based file system support' CONFIG_RAMFS
 
index 63d25594a939810a072da23346745243c496d3c4..541816171acd9da9c4056126a897b6c7f00f72d0 100644 (file)
@@ -1,18 +1,21 @@
 #
 # Makefile for the linux Journalling Flash FileSystem (JFFS) routines.
 #
+# $Id: Makefile,v 1.7 2000/08/04 12:46:34 dwmw2 Exp $
+#
 # Note! Dependencies are done automagically by 'make dep', which also
 # removes any old dependencies. DON'T put your own dependencies here
 # unless it's something special (ie not a .c file).
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
-ifndef CONFIG_MTD
+ifndef CONFIG_JFFS_FS
 
 # We're being invoked outside a normal kernel build. Fake it
 EXTRA_CFLAGS= -I$(shell pwd)/../../include
 
 # You need to change this to build for 2.2, dunno how to check for it.
+
 #INODE_O := inode-v22.o
 INODE_O := inode-v23.o
 
index 06ac42709dc41a34647a857d005ff388ea25e7aa..9ea2223d3f52fc12f57de1b898384bfb05693561 100644 (file)
@@ -1,19 +1,21 @@
 /*
  * JFFS -- Journalling Flash File System, Linux implementation.
  *
- * Copyright (C) 1999, 2000  Finn Hakansson, Axis Communications, Inc.
+ * Copyright (C) 1999, 2000  Axis Communications AB.
+ *
+ * Created by Finn Hakansson <finn@axis.com>.
  *
  * This 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.
  *
- * $Id: inode-v23.c,v 1.17 2000/07/06 20:35:19 prumpf Exp $
+ * $Id: inode-v23.c,v 1.33 2000/08/09 15:59:06 dwmw2 Exp $
  *
  *
  * Ported to Linux 2.3.x and MTD:
  * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
- * 
+ *
  */
 
 /* inode.c -- Contains the code that is called from the VFS.  */
  * maybe other stuff do to.
  */
 
-#include <linux/config.h>
+/* Argh. Some architectures have kernel_thread in asm/processor.h
+   Some have it in unistd.h and you need to define __KERNEL_SYSCALLS__
+   Pass me a baseball bat and the person responsible.
+   dwmw2
+*/
+#define __KERNEL_SYSCALLS__
+#include <linux/sched.h>
+#include <linux/unistd.h>
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include "jffs_fm.h"
 #include "intrep.h"
 
-#if defined(CONFIG_JFFS_FS_VERBOSE) && CONFIG_JFFS_FS_VERBOSE
-#define D(x) x
-#else
-#define D(x)
-#endif
-#define D1(x) D(x)
-#define D2(x) 
-#define D3(x) 
-#define ASSERT(x) x
-
 static int jffs_remove(struct inode *dir, struct dentry *dentry, int type);
 
 static struct super_operations jffs_ops;
@@ -64,22 +64,24 @@ static struct file_operations jffs_dir_operations;
 static struct inode_operations jffs_dir_inode_operations;
 static struct address_space_operations jffs_address_operations;
 
+
 /* Called by the VFS at mount time to initialize the whole file system.  */
 static struct super_block *
 jffs_read_super(struct super_block *sb, void *data, int silent)
 {
        kdev_t dev = sb->s_dev;
        struct inode *root_inode;
+       struct jffs_control *c;
 
-       printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n",
-              kdevname(dev));
+       D1(printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n",
+                 kdevname(dev)));
 
-       if (MAJOR(dev)!=MTD_BLOCK_MAJOR) {
-         printk(KERN_WARNING "JFFS: Trying to mount non-mtd device.\n");
-         return 0;
+       if (MAJOR(dev) != MTD_BLOCK_MAJOR) {
+               printk(KERN_WARNING "JFFS: Trying to mount a "
+                      "non-mtd device.\n");
+               return 0;
        }
 
-       set_blocksize(dev, PAGE_CACHE_SIZE);
        sb->s_blocksize = PAGE_CACHE_SIZE;
        sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
        sb->u.generic_sbp = (void *) 0;
@@ -98,19 +100,36 @@ jffs_read_super(struct super_block *sb, void *data, int silent)
        root_inode = iget(sb, JFFS_MIN_INO);
        if (!root_inode)
                goto jffs_sb_err2;
-       
+
        /* Get the root directory of this file system.  */
        if (!(sb->s_root = d_alloc_root(root_inode))) {
                goto jffs_sb_err3;
        }
 
-#ifdef USE_GC
-       /* Do a garbage collect every time we mount.  */
-       jffs_garbage_collect((struct jffs_control *)sb->u.generic_sbp);
-#endif
+       c = (struct jffs_control *) sb->u.generic_sbp;
 
-       printk(KERN_NOTICE "JFFS: Successfully mounted device %s.\n",
-              kdevname(dev));
+       /* Set the Garbage Collection thresholds */
+
+       /* GC if free space goes below 5% of the total size */
+       c->gc_minfree_threshold = c->fmc->flash_size / 20;
+
+       if (c->gc_minfree_threshold < c->fmc->sector_size)
+               c->gc_minfree_threshold = c->fmc->sector_size;
+
+       /* GC if dirty space exceeds 33% of the total size. */
+       c->gc_maxdirty_threshold = c->fmc->flash_size / 3;
+
+       if (c->gc_maxdirty_threshold < c->fmc->sector_size)
+               c->gc_maxdirty_threshold = c->fmc->sector_size;
+
+
+       c->thread_pid = kernel_thread (jffs_garbage_collect_thread, 
+                                       (void *) c, 
+                                       CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+       D1(printk(KERN_NOTICE "JFFS: GC thread pid=%d.\n", (int) c->thread_pid));
+
+       D1(printk(KERN_NOTICE "JFFS: Successfully mounted device %s.\n",
+              kdevname(dev)));
        return sb;
 
 jffs_sb_err3:
@@ -118,7 +137,6 @@ jffs_sb_err3:
 jffs_sb_err2:
        jffs_cleanup_control((struct jffs_control *)sb->u.generic_sbp);
 jffs_sb_err1:
-       
        printk(KERN_WARNING "JFFS: Failed to mount device %s.\n",
               kdevname(dev));
        return 0;
@@ -129,14 +147,27 @@ jffs_sb_err1:
 static void
 jffs_put_super(struct super_block *sb)
 {
-       kdev_t dev = sb->s_dev;
+       struct jffs_control *c = (struct jffs_control *) sb->u.generic_sbp;
+       D1(kdev_t dev = sb->s_dev);
+
        D2(printk("jffs_put_super()\n"));
+
+       D1(printk (KERN_NOTICE "jffs_put_super(): Telling gc thread to die.\n"));
+       if (c->gc_task) {
+               send_sig(SIGQUIT, c->gc_task, 1);
+               send_sig(SIGCONT, c->gc_task, 1);
+       }
+       down (&c->gc_thread_sem);
+
+       D1(printk (KERN_NOTICE "jffs_put_super(): Successfully waited on thread.\n"));
+
        sb->s_dev = 0;
        jffs_cleanup_control((struct jffs_control *)sb->u.generic_sbp);
-       printk(KERN_NOTICE "JFFS: Successfully unmounted device %s.\n",
-              kdevname(dev));
+       D1(printk(KERN_NOTICE "JFFS: Successfully unmounted device %s.\n",
+              kdevname(dev)));
 }
 
+
 /* This function is called when user commands like chmod, chgrp and
    chown are executed. System calls like trunc() results in a call
    to this function.  */
@@ -165,9 +196,9 @@ jffs_setattr(struct dentry *dentry, struct iattr *iattr)
 
        c = f->c;
        fmc = c->fmc;
-        update_all = iattr->ia_valid & ATTR_FORCE;
+       update_all = iattr->ia_valid & ATTR_FORCE;
 
-       if (!JFFS_ENOUGH_SPACE(fmc)) {
+       if (!JFFS_ENOUGH_SPACE(c)) {
                if ( (update_all || iattr->ia_valid & ATTR_SIZE)
                     && (iattr->ia_size < f->size) ) {
                        /* See this case where someone is trying to
@@ -212,7 +243,7 @@ jffs_setattr(struct dentry *dentry, struct iattr *iattr)
        raw_inode.spare = 0;
        raw_inode.rename = 0;
        raw_inode.deleted = 0;
-       
+
        if (update_all || iattr->ia_valid & ATTR_MODE) {
                raw_inode.mode = iattr->ia_mode;
                inode->i_mode = iattr->ia_mode;
@@ -282,13 +313,16 @@ jffs_setattr(struct dentry *dentry, struct iattr *iattr)
        }
 
        jffs_insert_node(c, f, &raw_inode, 0, new_node);
-       
+
        mark_inode_dirty(inode);
-       
+
        return 0;
 } /* jffs_notify_change()  */
 
-struct inode * jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode, int * err)
+
+struct inode *
+jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode,
+              int * err)
 {
        struct super_block * sb;
        struct inode * inode;
@@ -299,7 +333,7 @@ struct inode * jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *r
                *err = -ENOMEM;
                return NULL;
        }
-       
+
        sb = dir->i_sb;
        c = (struct jffs_control *)sb->u.generic_sbp;
 
@@ -315,12 +349,12 @@ struct inode * jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *r
        inode->i_atime = raw_inode->atime;
        inode->i_mtime = raw_inode->mtime;
        inode->i_ctime = raw_inode->ctime;
-       inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat), not the fs block size */
-       inode->i_blocks = 0;
+       inode->i_blksize = PAGE_SIZE;
+       inode->i_blocks = (raw_inode->dsize + PAGE_SIZE - 1) >> PAGE_SHIFT;
        inode->i_version = 0;
        inode->i_flags = sb->s_flags;
        inode->u.generic_ip = (void *)jffs_find_file(c, raw_inode->ino);
-       
+
        insert_inode_hash(inode);
 
        return inode;
@@ -343,7 +377,7 @@ jffs_statfs(struct super_block *sb, struct statfs *buf)
                       + jffs_free_size2(fmc) / PAGE_CACHE_SIZE)
                      - (fmc->min_free_size / PAGE_CACHE_SIZE);
        buf->f_bavail = buf->f_bfree;
-       
+
        /* Find out how many files there are in the filesystem.  */
        buf->f_files = jffs_foreach_file(c, jffs_file_count);
        buf->f_ffree = buf->f_bfree;
@@ -352,10 +386,11 @@ jffs_statfs(struct super_block *sb, struct statfs *buf)
        return 0;
 }
 
+
 /* Rename a file.  */
 int
 jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
-            struct inode *new_dir, struct dentry *new_dentry)
+           struct inode *new_dir, struct dentry *new_dentry)
 {
        struct jffs_raw_inode raw_inode;
        struct jffs_control *c;
@@ -382,14 +417,14 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
                return -1;
        });
 
-       if (!JFFS_ENOUGH_SPACE(c->fmc)) {
+       if (!JFFS_ENOUGH_SPACE(c)) {
                D1(printk("jffs_rename(): Free size = %u\n",
                          jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
                D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
                return -ENOSPC;
        }
-       
-       /* Find the the old directory.  */
+
+       /* Find the old directory.  */
        result = -ENOTDIR;
        if (!(old_dir_f = (struct jffs_file *)old_dir->u.generic_ip)) {
                D(printk("jffs_rename(): Old dir invalid.\n"));
@@ -402,8 +437,8 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
                                  old_dentry->d_name.len))) {
                goto jffs_rename_end;
        }
-       
-       /* Try to find the new directory's node.  */
+
+       /* Find the new directory.  */
        result = -ENOTDIR;
        if (!(new_dir_f = (struct jffs_file *)new_dir->u.generic_ip)) {
                D(printk("jffs_rename(): New dir invalid.\n"));
@@ -450,27 +485,31 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
        if ((del_f = jffs_find_child(new_dir_f, new_dentry->d_name.name,
                                     new_dentry->d_name.len))) {
                raw_inode.rename = 1;
-               /*raw_inode.mode = del_f->ino;*/
+               raw_inode.dsize = sizeof(__u32);
+               rename_data = del_f->ino;
        }
 
        /* Write the new node to the flash memory.  */
-       if ((result = jffs_write_node(c, node, &raw_inode, new_dentry->d_name.name,
+       if ((result = jffs_write_node(c, node, &raw_inode,
+                                     new_dentry->d_name.name,
                                      (unsigned char*)&rename_data)) < 0) {
                D(printk("jffs_rename(): Failed to write node to flash.\n"));
                kfree(node);
                DJM(no_jffs_node--);
                goto jffs_rename_end;
        }
+       raw_inode.dsize = 0;
 
        if (raw_inode.rename) {
                /* The file with the same name must be deleted.  */
-               c->fmc->no_call_gc = 1; /* TODO: What kind of locking is this? */
-               if ((result = jffs_remove(new_dir, new_dentry, del_f->mode)) < 0) {
+               down(&c->fmc->gclock);
+               if ((result = jffs_remove(new_dir, new_dentry,
+                                         del_f->mode)) < 0) {
                        /* This is really bad.  */
                        printk(KERN_ERR "JFFS: An error occurred in "
                               "rename().\n");
                }
-               c->fmc->no_call_gc = 0;
+               up(&c->fmc->gclock);
        }
 
        if (old_dir_f != new_dir_f) {
@@ -501,7 +540,6 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
        }
 
 jffs_rename_end:
-       
        return result;
 } /* jffs_rename()  */
 
@@ -524,13 +562,14 @@ jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                        return 0;
                }
                filp->f_pos = 1;
-       } 
+       }
        if (filp->f_pos == 1) {
                if (inode->i_ino == JFFS_MIN_INO) {
                        ddino = JFFS_MIN_INO;
                }
                else {
-                       ddino = ((struct jffs_file *)inode->u.generic_ip)->pino;
+                       ddino = ((struct jffs_file *)
+                                inode->u.generic_ip)->pino;
                }
                D3(printk("jffs_readdir(): \"..\" %u\n", ddino));
                if (filldir(dirent, "..", 2, filp->f_pos, ddino) < 0)
@@ -549,7 +588,7 @@ jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                        return 0;
                filp->f_pos++;
        }
-       
+
        return filp->f_pos;
 } /* jffs_readdir()  */
 
@@ -565,10 +604,10 @@ jffs_lookup(struct inode *dir, struct dentry *dentry)
        int r = 0;
        const char *name;
        struct inode *inode = NULL;
-       
+
        len = dentry->d_name.len;
        name = dentry->d_name.name;
-       
+
        D3({
                char *s = (char *)kmalloc(len + 1, GFP_KERNEL);
                memcpy(s, name, len);
@@ -576,7 +615,7 @@ jffs_lookup(struct inode *dir, struct dentry *dentry)
                printk("jffs_lookup(): dir: 0x%p, name: \"%s\"\n", dir, s);
                kfree(s);
        });
-       
+
        r = -ENAMETOOLONG;
        if (len > JFFS_MAX_NAME_LEN) {
                goto jffs_lookup_end;
@@ -584,7 +623,8 @@ jffs_lookup(struct inode *dir, struct dentry *dentry)
 
        r = -EACCES;
        if (!(d = (struct jffs_file *)dir->u.generic_ip)) {
-               D(printk("jffs_lookup(): No such inode! (%lu)\n", dir->i_ino));
+               D(printk("jffs_lookup(): No such inode! (%lu)\n",
+                        dir->i_ino));
                goto jffs_lookup_end;
        }
 
@@ -610,10 +650,10 @@ jffs_lookup(struct inode *dir, struct dentry *dentry)
                          f, name, d, d->ino));
                inode = NULL;
        }
-       
+
        d_add(dentry, inode);
        return NULL;
-       
+
 jffs_lookup_end:
        return ERR_PTR(r);
 } /* jffs_lookup()  */
@@ -665,9 +705,9 @@ jffs_readpage(struct file *file, struct page *page)
        flush_dcache_page(page);
 
        UnlockPage(page);
-       
+
        put_page(page);
-       
+
        D3(printk("jffs_readpage(): Leaving...\n"));
 
        return result;
@@ -686,7 +726,7 @@ jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        int dir_mode;
        int result = 0;
        int err;
-       
+
        D1({
                int len = dentry->d_name.len;
                char *_name = (char *) kmalloc(len + 1, GFP_KERNEL);
@@ -707,7 +747,7 @@ jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
        c = dir_f->c;
 
-       if (!JFFS_ENOUGH_SPACE(c->fmc)) {
+       if (!JFFS_ENOUGH_SPACE(c)) {
                D1(printk("jffs_mkdir(): Free size = %u\n",
                          jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
                D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
@@ -718,7 +758,7 @@ jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        dir_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX)
                              & ~current->fs->umask);
        if (dir->i_mode & S_ISGID) {
-                dir_mode |= S_ISGID;
+               dir_mode |= S_ISGID;
        }
 
        /* Create a node and initialize it as much as needed.  */
@@ -754,7 +794,8 @@ jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        raw_inode.deleted = 0;
 
        /* Write the new node to the flash.  */
-       if ((result = jffs_write_node(c, node, &raw_inode, dentry->d_name.name, 0)) < 0) {
+       if ((result = jffs_write_node(c, node, &raw_inode,
+                                     dentry->d_name.name, 0)) < 0) {
                D(printk("jffs_mkdir(): jffs_write_node() failed.\n"));
                kfree(node);
                DJM(no_jffs_node--);
@@ -762,15 +803,17 @@ jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        }
 
        /* Insert the new node into the file system.  */
-       if ((result = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name, node))<0)
-         goto jffs_mkdir_end;
-       
+       if ((result = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name,
+                                      node)) < 0) {
+               goto jffs_mkdir_end;
+       }
+
        inode = jffs_new_inode(dir, &raw_inode, &err);
        if (inode == NULL) {
                result = err;
                goto jffs_mkdir_end;
        }
-       
+
        inode->i_op = &jffs_dir_inode_operations;
        inode->i_fop = &jffs_dir_operations;
 
@@ -839,7 +882,8 @@ jffs_remove(struct inode *dir, struct dentry *dentry, int type)
                        result = -ENOTEMPTY;
                        goto jffs_remove_end;
                }
-        } else if (S_ISDIR(del_f->mode)) {
+       }
+       else if (S_ISDIR(del_f->mode)) {
                D(printk("jffs_remove(): node is a directory "
                         "but it shouldn't be.\n"));
                result = -EPERM;
@@ -847,7 +891,7 @@ jffs_remove(struct inode *dir, struct dentry *dentry, int type)
        }
 
        inode = dentry->d_inode;
-       
+
        result = -EIO;
        if (del_f->ino != inode->i_ino)
                goto jffs_remove_end;
@@ -936,7 +980,7 @@ jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
        dir_f = (struct jffs_file *)dir->u.generic_ip;
        c = dir_f->c;
 
-       if (!JFFS_ENOUGH_SPACE(c->fmc)) {
+       if (!JFFS_ENOUGH_SPACE(c)) {
                D1(printk("jffs_mknod(): Free size = %u\n",
                          jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
                D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
@@ -985,7 +1029,8 @@ jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
        }
 
        /* Insert the new node into the file system.  */
-       if ((err = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name, node)) < 0) {
+       if ((err = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name,
+                                   node)) < 0) {
                result = err;
                goto jffs_mknod_end;
        }
@@ -995,11 +1040,11 @@ jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
                result = err;
                goto jffs_mknod_end;
        }
-       
+
        init_special_inode(inode, mode, rdev);
 
        d_instantiate(dentry, inode);
-       
+
        goto jffs_mknod_end;
 
 jffs_mknod_err:
@@ -1021,7 +1066,7 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
        struct jffs_file *dir_f;
        struct jffs_node *node;
        struct inode *inode;
-       
+
        int symname_len = strlen(symname);
        int err;
 
@@ -1033,7 +1078,8 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
                _name[len] = '\0';
                memcpy(_symname, symname, symname_len);
                _symname[symname_len] = '\0';
-               printk("***jffs_symlink(): dir = 0x%p, dentry->dname.name = \"%s\", "
+               printk("***jffs_symlink(): dir = 0x%p, "
+                      "dentry->dname.name = \"%s\", "
                       "symname = \"%s\"\n", dir, _name, _symname);
                kfree(_name);
                kfree(_symname);
@@ -1048,7 +1094,7 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 
        c = dir_f->c;
 
-       if (!JFFS_ENOUGH_SPACE(c->fmc)) {
+       if (!JFFS_ENOUGH_SPACE(c)) {
                D1(printk("jffs_symlink(): Free size = %u\n",
                          jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
                D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
@@ -1058,7 +1104,7 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
        /* Create a node and initialize it as much as needed.  */
        if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node),
                                                  GFP_KERNEL))) {
-               D(printk("jffs_symlink(): Allocation failed: node == NULL\n"));
+               D(printk("jffs_symlink(): Allocation failed: node = NULL\n"));
                return -ENOMEM;
        }
        DJM(no_jffs_node++);
@@ -1095,7 +1141,8 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
        }
 
        /* Insert the new node into the file system.  */
-       if ((err = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name, node)) < 0) {
+       if ((err = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name,
+                                   node)) < 0) {
                return err;
        }
 
@@ -1103,7 +1150,7 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
        if (inode == NULL) {
                return err;
        }
-       
+
        inode->i_op = &page_symlink_inode_operations;
        inode->i_mapping->a_ops = &jffs_address_operations;
 
@@ -1112,14 +1159,15 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
        return 0;
 } /* jffs_symlink()  */
 
-/* Create an inode inside a JFFS directory (dir) and return it.  
+
+/* Create an inode inside a JFFS directory (dir) and return it.
  *
  * By the time this is called, we already have created
  * the directory cache entry for the new file, but it
  * is so far negative - it has no inode.
  *
  * If the create succeeds, we fill in the inode information
- * with d_instantiate(). 
+ * with d_instantiate().
  */
 static int
 jffs_create(struct inode *dir, struct dentry *dentry, int mode)
@@ -1149,7 +1197,7 @@ jffs_create(struct inode *dir, struct dentry *dentry, int mode)
 
        c = dir_f->c;
 
-       if (!JFFS_ENOUGH_SPACE(c->fmc)) {
+       if (!JFFS_ENOUGH_SPACE(c)) {
                D1(printk("jffs_create(): Free size = %u\n",
                          jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
                D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
@@ -1187,7 +1235,8 @@ jffs_create(struct inode *dir, struct dentry *dentry, int mode)
        raw_inode.deleted = 0;
 
        /* Write the new node to the flash.  */
-       if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name, 0)) < 0) {
+       if ((err = jffs_write_node(c, node, &raw_inode,
+                                  dentry->d_name.name, 0)) < 0) {
                D(printk("jffs_create(): jffs_write_node() failed.\n"));
                kfree(node);
                DJM(no_jffs_node--);
@@ -1195,7 +1244,8 @@ jffs_create(struct inode *dir, struct dentry *dentry, int mode)
        }
 
        /* Insert the new node into the file system.  */
-       if ((err = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name, node)) < 0) {
+       if ((err = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name,
+                                   node)) < 0) {
                return err;
        }
 
@@ -1211,33 +1261,35 @@ jffs_create(struct inode *dir, struct dentry *dentry, int mode)
        inode->i_mapping->nrpages = 0;
 
        d_instantiate(dentry, inode);
-       
+
        return 0;
 } /* jffs_create()  */
 
 
 /* Write, append or rewrite data to an existing file.  */
 static ssize_t
-jffs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
+jffs_file_write(struct file *filp, const char *buf, size_t count,
+               loff_t *ppos)
 {
        struct jffs_raw_inode raw_inode;
        struct jffs_control *c;
        struct jffs_file *f;
        struct jffs_node *node;
-       struct dentry *dentry = filp->f_dentry; 
-       struct inode *inode = dentry->d_inode; 
+       struct dentry *dentry = filp->f_dentry;
+       struct inode *inode = dentry->d_inode;
+       unsigned char *vbuf;
        int written = 0;
        loff_t pos;
        int err;
 
        inode = filp->f_dentry->d_inode;
-       
+
        D2(printk("***jffs_file_write(): inode: 0x%p (ino: %lu), "
                  "filp: 0x%p, buf: 0x%p, count: %d\n",
                  inode, inode->i_ino, filp, buf, count));
 
        down(&inode->i_sem);
-       
+
        pos = *ppos;
        err = -EINVAL;
        if (pos < 0)
@@ -1254,7 +1306,7 @@ jffs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
                err = -ENOSPC;
                goto out;
        }
-       
+
        if (!S_ISREG(inode->i_mode)) {
                D(printk("jffs_file_write(): inode->i_mode == 0x%08x\n",
                         inode->i_mode));
@@ -1268,10 +1320,10 @@ jffs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
                err = -EINVAL;
                goto out;
        }
-       
+
        c = f->c;
 
-       if (!JFFS_ENOUGH_SPACE(c->fmc)) {
+       if (!JFFS_ENOUGH_SPACE(c)) {
                D1(printk("jffs_file_write(): Free size = %u\n",
                          jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
                D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
@@ -1282,16 +1334,35 @@ jffs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
        if (filp->f_flags & O_APPEND)
                pos = inode->i_size;
 
+
+       if (!(vbuf = kmalloc(count, GFP_KERNEL))) {
+               D(printk("jffs_file_write(): failed to allocate bounce buffer. Fix me to use page cache\n"));
+               err = -ENOMEM;
+               goto out;
+       }
+
+       /* FIXME: This is entirely gratuitous use of bounce buffers.
+          Get a clue and use the page cache. 
+          /me wanders off to get a crash course on Linux VFS
+          dwmw2
+       */
+       if (copy_from_user(vbuf, buf, count)) {
+               kfree(vbuf);
+               return -EFAULT;
+       }
+               
+
        /* Things are going to be written so we could allocate and
           initialize the necessary data structures now.  */
        if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node),
                                                  GFP_KERNEL))) {
                D(printk("jffs_file_write(): node == 0\n"));
                err = -ENOMEM;
+               kfree(vbuf);
                goto out;
        }
        DJM(no_jffs_node++);
-       node->data_offset = f->size;
+       node->data_offset = pos;
        node->removed_size = 0;
 
        /* Initialize the raw inode.  */
@@ -1300,7 +1371,7 @@ jffs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
        raw_inode.pino = f->pino;
        raw_inode.version = f->highest_version + 1;
        raw_inode.mode = f->mode;
-       
+
        raw_inode.uid = f->uid;
        raw_inode.gid = f->gid;
        /*
@@ -1310,7 +1381,7 @@ jffs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
        raw_inode.atime = CURRENT_TIME;
        raw_inode.mtime = raw_inode.atime;
        raw_inode.ctime = f->ctime;
-       raw_inode.offset = f->size;
+       raw_inode.offset = pos;
        raw_inode.dsize = count;
        raw_inode.rsize = 0;
        raw_inode.nsize = 0;
@@ -1319,25 +1390,28 @@ jffs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
        raw_inode.rename = 0;
        raw_inode.deleted = 0;
 
+       if (pos < f->size) {
+               node->removed_size = raw_inode.rsize = jffs_min(count, f->size - pos);
+       }
 
-       /* TODO: BAAAAAAAAD! buf is a userspace-pointer, and should be
-                treated as such, with copy_from_user etc...
-         */
        /* Write the new node to the flash.  */
        if ((written = jffs_write_node(c, node, &raw_inode, 0,
-                                      (const unsigned char *)buf)) < 0) {
+                                      (const unsigned char *)vbuf)) < 0) {
                D(printk("jffs_file_write(): jffs_write_node() failed.\n"));
                kfree(node);
+               kfree(vbuf);
                DJM(no_jffs_node--);
                err = written;
                goto out;
        }
 
+       kfree(vbuf);
+
        /* Insert the new node into the file system.  */
        if ((err = jffs_insert_node(c, f, &raw_inode, 0, node)) < 0) {
                goto out;
        }
-       
+
        pos += written;
        *ppos = pos;
 
@@ -1365,7 +1439,8 @@ jffs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 {
        struct jffs_control *c;
 
-       D2(printk("***jffs_ioctl(): cmd = 0x%08x, arg = 0x%08lx\n", cmd, arg));
+       D2(printk("***jffs_ioctl(): cmd = 0x%08x, arg = 0x%08lx\n",
+                 cmd, arg));
 
        if (!(c = (struct jffs_control *)inode->i_sb->u.generic_sbp)) {
                printk(KERN_ERR "JFFS: Bad inode in ioctl() call. "
@@ -1402,10 +1477,10 @@ jffs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                               fst.size, fst.used, fst.dirty,
                               fst.begin, fst.end);
                        if (copy_to_user((struct jffs_flash_status *)arg,
-                                        &fst, sizeof(struct jffs_flash_status))) {
+                                        &fst,
+                                        sizeof(struct jffs_flash_status))) {
                          return -EFAULT;
                        }
-                       
                }
                break;
        default:
@@ -1417,9 +1492,17 @@ jffs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 
 
 static struct address_space_operations jffs_address_operations = {
-        readpage: jffs_readpage,
+       readpage: jffs_readpage,
 };
 
+static int jffs_fsync(struct file *f, struct dentry *d, int datasync)
+{
+       /* We currently have O_SYNC operations at all times. 
+          Do nothing
+       */
+       return 0;
+}
+
 
 static struct file_operations jffs_file_operations =
 {
@@ -1427,19 +1510,23 @@ static struct file_operations jffs_file_operations =
        write: jffs_file_write,      /* write */
        ioctl: jffs_ioctl,           /* ioctl */
        mmap:  generic_file_mmap,    /* mmap */
+       fsync: jffs_fsync,
 };
 
+
 static struct inode_operations jffs_file_inode_operations =
 {
        lookup:  jffs_lookup,          /* lookup */
        setattr: jffs_setattr,
 };
 
+
 static struct file_operations jffs_dir_operations =
 {
        readdir:        jffs_readdir,
 };
 
+
 static struct inode_operations jffs_dir_inode_operations =
 {
        create:   jffs_create,
@@ -1453,6 +1540,7 @@ static struct inode_operations jffs_dir_inode_operations =
        setattr:  jffs_setattr,
 };
 
+
 /* Initialize an inode for the VFS.  */
 static void
 jffs_read_inode(struct inode *inode)
@@ -1483,7 +1571,7 @@ jffs_read_inode(struct inode *inode)
        inode->i_mtime = f->mtime;
        inode->i_ctime = f->ctime;
        inode->i_blksize = PAGE_SIZE;
-       inode->i_blocks = 0;
+       inode->i_blocks = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
        if (S_ISREG(inode->i_mode)) {
                inode->i_op = &jffs_file_inode_operations;
                inode->i_fop = &jffs_file_operations;
@@ -1494,44 +1582,42 @@ jffs_read_inode(struct inode *inode)
                inode->i_fop = &jffs_dir_operations;
        }
        else if (S_ISLNK(inode->i_mode)) {
-                inode->i_op = &page_symlink_inode_operations;
+               inode->i_op = &page_symlink_inode_operations;
                inode->i_mapping->a_ops = &jffs_address_operations;
-       } else {
-         /* If the node is a device of some sort, then the number of the
-            device should be read from the flash memory and then added
-            to the inode's i_rdev member.  */
+       }
+       else {
+               /* If the node is a device of some sort, then the number of
+                  the device should be read from the flash memory and then
+                  added to the inode's i_rdev member.  */
                kdev_t rdev;
                jffs_read_data(f, (char *)&rdev, 0, sizeof(kdev_t));
                init_special_inode(inode, inode->i_mode, kdev_t_to_nr(rdev));
        }
 }
 
+
 void
 jffs_delete_inode(struct inode *inode)
 {
+       D3(printk("jffs_delete_inode(): inode->i_ino == %lu\n",
+                 inode->i_ino));
 
-        D3(printk("jffs_delete_inode(): inode->i_ino == %lu\n", inode->i_ino));
-
-       lock_kernel();
-       
+       lock_kernel();
        inode->i_size = 0;
-
        clear_inode(inode);
-
        unlock_kernel();
 }
 
+
 void
 jffs_write_super(struct super_block *sb)
 {
-#ifdef USE_GC
        struct jffs_control *c = (struct jffs_control *)sb->u.generic_sbp;
-       
-       if(!c->fmc->no_call_gc)
-               jffs_garbage_collect(c);
-#endif
+
+       jffs_garbage_collect_trigger(c);
 }
 
+
 static struct super_operations jffs_ops =
 {
        read_inode:   jffs_read_inode,
@@ -1541,12 +1627,15 @@ static struct super_operations jffs_ops =
        statfs:       jffs_statfs,
 };
 
+
 static DECLARE_FSTYPE_DEV(jffs_fs_type, "jffs", jffs_read_super);
 
 static int __init
 init_jffs_fs(void)
 {
-       printk("JFFS version " JFFS_VERSION_STRING ", (C) 1999, 2000  Axis Communications AB\n");
+       printk("JFFS version "
+              JFFS_VERSION_STRING
+              ", (C) 1999, 2000  Axis Communications AB\n");
        return register_filesystem(&jffs_fs_type);
 }
 
index 039aaa04e854223f5acc3fb0d1a909b2856a1acc..adb2e0c46b5d7141eb1e81e11962162de80aa10e 100644 (file)
@@ -10,7 +10,7 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * $Id: intrep.c,v 1.15 2000/06/27 15:33:43 dwmw2 Exp $
+ * $Id: intrep.c,v 1.39 2000/08/09 13:23:36 dwmw2 Exp $
  *
  * Ported to Linux 2.3.x and MTD:
  * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
@@ -23,7 +23,7 @@
 /*
  * Todo list:
  *
- * memcpy_to_flash() and memcpy_from_flash()-functions.
+ * memcpy_to_flash() and memcpy_from_flash() functions.
  *
  * Implementation of hard links.
  *
@@ -43,9 +43,6 @@
  * Implement more meaning of the nlink member in various data structures.
  * nlink could be used in conjunction with hard links for instance.
  *
- * Fix the rename stuff. (I.e. if we have two files `a' and `b' and we
- * do a `mv b a'.) Half of this is already implemented.
- *
  * Better memory management. Allocate data structures in larger chunks
  * if possible.
  *
@@ -57,8 +54,8 @@
  * information to be able to debug (or to supervise) JFFS during run-time.
  *
  */
+
 #define __NO_VERSION__
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/malloc.h>
 #include <linux/jffs.h>
@@ -69,6 +66,9 @@
 #include <asm/semaphore.h>
 #include <asm/byteorder.h>
 #include <linux/version.h>
+#include <linux/smp_lock.h>
+#include <linux/sched.h>
+
 
 #include "intrep.h"
 #include "jffs_fm.h"
 #define set_current_state(x) do{current->state = x;} while (0)
 #endif
 
-#if defined(CONFIG_JFFS_FS_VERBOSE) && CONFIG_JFFS_FS_VERBOSE
-#define D(x) x
-#else
-#define D(x)
-#endif
-#define D1(x) D(x)
-#define D2(x) 
-#define D3(x) 
-#define ASSERT(x) x
-
 #if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG
 long no_jffs_file = 0;
 long no_jffs_node = 0;
@@ -192,50 +182,53 @@ jffs_hexdump(struct mtd_info *mtd, loff_t pos, int size)
 }
 #endif
 
-#define flash_safe_acquire(arg) 
-#define flash_safe_release(arg) 
+#define flash_safe_acquire(arg)
+#define flash_safe_release(arg)
+
 
 static int
 flash_safe_read(struct mtd_info *mtd, loff_t from,
                u_char *buf, size_t count)
 {
-  size_t retlen;
-  
-  MTD_READ(mtd, from, count, &retlen, buf);
-  if (retlen != count) {
-    printk("Didn't read all bytes in flash_safe_read()\n");
-  }
-  return retlen;
+       size_t retlen;
+
+       MTD_READ(mtd, from, count, &retlen, buf);
+       if (retlen != count) {
+               printk("Didn't read all bytes in flash_safe_read()\n");
+       }
+       return retlen;
 }
 
+
 static __u32
 flash_read_u32(struct mtd_info *mtd, loff_t from)
 {
-  size_t retlen;
-  __u32 ret;
-  
-  MTD_READ(mtd, from, 4, &retlen, (unsigned char *)&ret);
-  if (retlen != 4) {
-    printk("Didn't read all bytes in flash_read_u32()\n");
-    return 0;
-  }
+       size_t retlen;
+       __u32 ret;
+
+       MTD_READ(mtd, from, 4, &retlen, (unsigned char *)&ret);
+       if (retlen != 4) {
+               printk("Didn't read all bytes in flash_read_u32()\n");
+               return 0;
+       }
 
-  return ret;
+       return ret;
 }
 
+
 static __u8
 flash_read_u8(struct mtd_info *mtd, loff_t from)
 {
-  size_t retlen;
-  __u8 ret;
-  
-  MTD_READ(mtd, from, 1, &retlen, &ret);
-  if (retlen != 1) {
-    printk("Didn't read all bytes in flash_read_u32()\n");
-    return 0;
-  }
+       size_t retlen;
+       __u8 ret;
 
-  return ret;
+       MTD_READ(mtd, from, 1, &retlen, &ret);
+       if (retlen != 1) {
+               printk("Didn't read a byte in flash_read_u8()\n");
+               return 0;
+       }
+
+       return ret;
 }
 
 
@@ -243,95 +236,100 @@ static int
 flash_safe_write(struct mtd_info *mtd, loff_t to,
                 const u_char *buf, size_t count)
 {
-  size_t retlen;
+       size_t retlen;
 
-  MTD_WRITE(mtd, to, count, &retlen, buf);
-  if (retlen != count) {
-    printk("Didn't write all bytes in flash_safe_write()\n");
-  }
-  return retlen;
+       MTD_WRITE(mtd, to, count, &retlen, buf);
+       if (retlen != count) {
+               printk("Didn't write all bytes in flash_safe_write()\n");
+       }
+       return retlen;
 }
 
+
 static int
 flash_memset(struct mtd_info *mtd, loff_t to,
             const u_char c, size_t size)
 {
-  static unsigned char pattern[16];
-  int i;
+       static unsigned char pattern[16];
+       int i;
 
-  /* fill up pattern */
-  
-  for(i = 0; i < 16; i++)
-    pattern[i] = c;
+       /* fill up pattern */
 
-  /* write as many 16-byte chunks as we can */
-  
-  while(size >= 16) {
-    flash_safe_write(mtd, to, pattern, 16);
-    size -= 16;
-    to += 16;
-  }
+       for(i = 0; i < 16; i++)
+               pattern[i] = c;
 
-  /* and the rest */
-  
-  if(size)
-    flash_safe_write(mtd, to, pattern, size);
+       /* write as many 16-byte chunks as we can */
 
-  return size;
+       while (size >= 16) {
+               flash_safe_write(mtd, to, pattern, 16);
+               size -= 16;
+               to += 16;
+       }
+
+       /* and the rest */
+
+       if(size)
+               flash_safe_write(mtd, to, pattern, size);
+
+       return size;
 }
 
-static void intrep_erase_callback(struct erase_info *done)
+
+static void
+intrep_erase_callback(struct erase_info *done)
 {
-  wait_queue_head_t *wait_q;
+       wait_queue_head_t *wait_q;
 
-  wait_q = (wait_queue_head_t *)done->priv;
+       wait_q = (wait_queue_head_t *)done->priv;
 
-  wake_up(wait_q);
+       wake_up(wait_q);
 }
 
+
 static int
 flash_erase_region(struct mtd_info *mtd, loff_t start,
                   size_t size)
 {
-  struct erase_info *erase;
-  DECLARE_WAITQUEUE(wait, current);
-  wait_queue_head_t wait_q;
+       struct erase_info *erase;
+       DECLARE_WAITQUEUE(wait, current);
+       wait_queue_head_t wait_q;
 
-  erase = kmalloc(sizeof(struct erase_info), GFP_KERNEL);
-  if (!erase) 
-    return -ENOMEM;
+       erase = kmalloc(sizeof(struct erase_info), GFP_KERNEL);
+       if (!erase)
+               return -ENOMEM;
 
-  init_waitqueue_head(&wait_q);
+       init_waitqueue_head(&wait_q);
 
-  erase->mtd = mtd;
-  erase->callback = intrep_erase_callback;
-  erase->addr = start;
-  erase->len = size;
-  erase->priv = (u_long)&wait_q;
+       erase->mtd = mtd;
+       erase->callback = intrep_erase_callback;
+       erase->addr = start;
+       erase->len = size;
+       erase->priv = (u_long)&wait_q;
 
-  set_current_state(TASK_INTERRUPTIBLE);
-  add_wait_queue(&wait_q, &wait);
-       
-  if (MTD_ERASE(mtd, erase) < 0) {
-    set_current_state(TASK_RUNNING);
-    remove_wait_queue(&wait_q, &wait);
-    kfree(erase);
-    
-    printk(KERN_WARNING "flash: erase of region [0x%ld, 0x%ld] totally failed\n",
-          (long)start, (long)start + size);
-    
-    return -1;
-  }
-
-  schedule(); /* Wait for flash to finish. */
-  /* FIXME: We could have been interrupted here. We don't deal with it */
-  remove_wait_queue(&wait_q, &wait);
-
-  kfree(erase);
-
-  return 0;
+       set_current_state(TASK_INTERRUPTIBLE);
+       add_wait_queue(&wait_q, &wait);
+
+       if (MTD_ERASE(mtd, erase) < 0) {
+               set_current_state(TASK_RUNNING);
+               remove_wait_queue(&wait_q, &wait);
+               kfree(erase);
+
+               printk(KERN_WARNING "flash: erase of region [0x%lx, 0x%lx] "
+                      "totally failed\n", (long)start, (long)start + size);
+
+               return -1;
+       }
+
+       schedule(); /* Wait for flash to finish. */
+       /* FIXME: We could have been interrupted here. We don't deal with it */
+       remove_wait_queue(&wait_q, &wait);
+
+       kfree(erase);
+
+       return 0;
 }
 
+
 inline int
 jffs_min(int a, int b)
 {
@@ -359,6 +357,7 @@ jffs_checksum(const void *data, int size)
        return sum;
 }
 
+
 __u32
 jffs_checksum_flash(struct mtd_info *mtd, loff_t start, int size)
 {
@@ -371,6 +370,17 @@ jffs_checksum_flash(struct mtd_info *mtd, loff_t start, int size)
        return sum;
 }
 
+static __inline__ void jffs_fm_write_lock(struct jffs_fmcontrol *fmc)
+{
+       down(&fmc->wlock);
+}
+
+static __inline__ void jffs_fm_write_unlock(struct jffs_fmcontrol *fmc)
+{
+       up(&fmc->wlock);
+}
+
+
 /* Create and initialize a new struct jffs_file.  */
 static struct jffs_file *
 jffs_create_file(struct jffs_control *c,
@@ -417,12 +427,13 @@ jffs_create_control(kdev_t dev)
                goto fail_hash;
        }
        DJM(no_hash++);
-       for (i=0;i<c->hash_len;i++) 
+       for (i = 0; i < c->hash_len; i++)
                INIT_LIST_HEAD(&c->hash[i]);
        if (!(c->fmc = jffs_build_begin(c, dev))) {
                goto fail_fminit;
        }
        c->next_ino = JFFS_MIN_INO + 1;
+       c->delete_list = (struct jffs_delete_list *) 0;
        return c;
 
 fail_fminit:
@@ -449,9 +460,17 @@ jffs_cleanup_control(struct jffs_control *c)
                return;
        }
 
+       while (c->delete_list) {
+               struct jffs_delete_list *delete_list_element;
+               delete_list_element = c->delete_list;
+               c->delete_list = c->delete_list->next;
+               kfree(delete_list_element);
+       }
+
        /* Free all files and nodes.  */
        if (c->hash) {
                jffs_foreach_file(c, jffs_free_node_list);
+               jffs_foreach_file(c, jffs_free_file);
                kfree(c->hash);
                DJM(no_hash--);
        }
@@ -525,6 +544,18 @@ jffs_build_fs(struct super_block *sb)
                }
        }
 
+       while (c->delete_list) {
+               struct jffs_file *f;
+               struct jffs_delete_list *delete_list_element;
+
+               if ((f = jffs_find_file(c, c->delete_list->ino))) {
+                       f->deleted = 1;
+               }
+               delete_list_element = c->delete_list;
+               c->delete_list = c->delete_list->next;
+               kfree(delete_list_element);
+       }
+
        /* Remove deleted nodes.  */
        if ((err = jffs_foreach_file(c, jffs_possibly_delete_file)) < 0) {
                printk(KERN_ERR "JFFS: Failed to remove deleted nodes.\n");
@@ -570,46 +601,60 @@ jffs_scan_flash(struct jffs_control *c)
        __u32 checksum;
        __u8 tmp_accurate;
        __u16 tmp_chksum;
+       __u32 deleted_file;
        loff_t pos = fmc->flash_start;
        loff_t start;
        loff_t end = fmc->flash_start + fmc->flash_size;
 
-       D1(printk("jffs_scan_flash(): start pos = 0x%ld, end = 0x%ld\n",
+       D1(printk("jffs_scan_flash(): start pos = 0x%lx, end = 0x%lx\n",
                  (long)pos, (long)end));
 
        flash_safe_acquire(fmc->mtd);
 
        /* Start the scan.  */
        while (pos < end) {
+               deleted_file = 0;
 
                /* Remember the position from where we started this scan.  */
                start = pos;
 
                switch (flash_read_u32(fmc->mtd, pos)) {
                case JFFS_EMPTY_BITMASK:
-                       /* We have found 0xff on this block.  We have to
-                          scan the rest of the block to be sure it is
-                          filled with 0xff.  */
-                       D1(printk("jffs_scan_flash(): 0xff at pos 0x%ld.\n",
+                       /* We have found 0xff at this position.  We have to
+                          scan the rest of the flash till the end or till
+                          something else than 0xff is found.  */
+                       D1(printk("jffs_scan_flash(): 0xff at pos 0x%lx.\n",
                                  (long)pos));
                        for (; pos < end
                               && JFFS_EMPTY_BITMASK == flash_read_u32(fmc->mtd, pos);
                             pos += 4);
                        D1(printk("jffs_scan_flash(): 0xff ended at "
-                                 "pos 0x%ld.\n", (long)pos));
+                                 "pos 0x%lx.\n", (long)pos));
+
+                       /* If some free space ends in the middle of a sector,
+                               treat it as dirty rather than clean.
+                          This is to handle the case where one thread 
+                          allocated space for a node, but didn't get to
+                          actually _write_ it before power was lost, leaving
+                          a gap in the log. Shifting all node writes into
+                          a single kernel thread will fix the original problem.
+                       */
+                       if ((__u32) pos % fmc->sector_size) {
+                               jffs_fmalloced(fmc, (__u32) start,
+                                              (__u32) (pos - start), 0);
+                       }
                        continue;
 
                case JFFS_DIRTY_BITMASK:
-                       /* We have found 0x00 on this block.  We have to
-                          scan as far as possible to find out how much
-                          is dirty.  */
-                       D1(printk("jffs_scan_flash(): 0x00 at pos 0x%ld.\n",
+                       /* We have found 0x00 at this position.  Scan as far
+                          as possible to find out how much is dirty.  */
+                       D1(printk("jffs_scan_flash(): 0x00 at pos 0x%lx.\n",
                                  (long)pos));
                        for (; pos < end
                               && JFFS_DIRTY_BITMASK == flash_read_u32(fmc->mtd, pos);
                             pos += 4);
                        D1(printk("jffs_scan_flash(): 0x00 ended at "
-                                 "pos 0x%ld.\n", (long)pos));
+                                 "pos 0x%lx.\n", (long)pos));
                        jffs_fmalloced(fmc, (__u32) start,
                                       (__u32) (pos - start), 0);
                        continue;
@@ -622,8 +667,9 @@ jffs_scan_flash(struct jffs_control *c)
                bad_inode:
                        /* We're f*cked.  This is not solved yet.  We have
                           to scan for the magic pattern.  */
-                       D1(printk("*************** Dirty flash memory or bad inode: "
-                                 "hexdump(pos = 0x%ld, len = 128):\n",
+                       D1(printk("*************** Dirty flash memory or "
+                                 "bad inode: "
+                                 "hexdump(pos = 0x%lx, len = 128):\n",
                                  (long)pos));
                        D1(jffs_hexdump(fmc->mtd, pos, 128));
                        for (pos += 4; pos < end; pos += 4) {
@@ -642,7 +688,7 @@ jffs_scan_flash(struct jffs_control *c)
                }
 
                /* We have found the beginning of an inode.  Create a
-                  node for it.  */
+                  node for it unless there already is one available.  */
                if (!node) {
                        if (!(node = (struct jffs_node *)
                                     kmalloc(sizeof(struct jffs_node),
@@ -655,7 +701,8 @@ jffs_scan_flash(struct jffs_control *c)
 
                /* Read the next raw inode.  */
 
-               flash_safe_read(fmc->mtd, pos, (u_char *) &raw_inode, sizeof(struct jffs_raw_inode));
+               flash_safe_read(fmc->mtd, pos, (u_char *) &raw_inode,
+                               sizeof(struct jffs_raw_inode));
 
                /* When we compute the checksum for the inode, we never
                   count the 'accurate' or the 'checksum' fields.  */
@@ -668,7 +715,7 @@ jffs_scan_flash(struct jffs_control *c)
                raw_inode.accurate = tmp_accurate;
                raw_inode.chksum = tmp_chksum;
 
-               D3(printk("*** We have found this raw inode at pos 0x%ld "
+               D3(printk("*** We have found this raw inode at pos 0x%lx "
                          "on the flash:\n", (long)pos));
                D3(jffs_print_raw_inode(&raw_inode));
 
@@ -689,6 +736,15 @@ jffs_scan_flash(struct jffs_control *c)
                if (raw_inode.nsize > JFFS_MAX_NAME_LEN) {
                        goto bad_inode;
                }
+
+               if (raw_inode.rename && raw_inode.dsize != sizeof(__u32)) {
+                       printk(KERN_WARNING "jffs_scan_flash: Found a "
+                              "rename node with dsize %u.\n",
+                              raw_inode.dsize);
+                       jffs_print_raw_inode(&raw_inode);
+                       goto bad_inode;
+               }
+
                /* The node's data segment should not exceed a
                   certain length.  */
                if (raw_inode.dsize > fmc->max_chunk_size) {
@@ -728,20 +784,26 @@ jffs_scan_flash(struct jffs_control *c)
                        }
                }
 
-               /* Read the data in order to be sure it matches the
-                  checksum.  */
-               checksum = jffs_checksum_flash(fmc->mtd, pos, raw_inode.dsize);
-               pos += raw_inode.dsize + JFFS_GET_PAD_BYTES(raw_inode.dsize);
+               /* Read the data, if it exists, in order to be sure it
+                  matches the checksum.  */
+               if (raw_inode.dsize) {
+                       if (raw_inode.rename) {
+                               deleted_file = flash_read_u32(fmc->mtd, pos);
+                       }
+                       checksum = jffs_checksum_flash(fmc->mtd, pos, raw_inode.dsize);
+                       pos += raw_inode.dsize
+                              + JFFS_GET_PAD_BYTES(raw_inode.dsize);
 
-               if (checksum != raw_inode.dchksum) {
-                       D1(printk("jffs_scan_flash(): Bad checksum: "
-                                 "checksum = %u, "
-                                 "raw_inode.dchksum = %u\n",
-                                 checksum, raw_inode.dchksum));
-                       jffs_fmalloced(fmc, (__u32) start,
-                                      (__u32) (pos - start), 0);
-                       /* Reuse this unused struct jffs_node.  */
-                       continue;
+                       if (checksum != raw_inode.dchksum) {
+                               D1(printk("jffs_scan_flash(): Bad checksum: "
+                                         "checksum = %u, "
+                                         "raw_inode.dchksum = %u\n",
+                                         checksum, raw_inode.dchksum));
+                               jffs_fmalloced(fmc, (__u32) start,
+                                              (__u32) (pos - start), 0);
+                               /* Reuse this unused struct jffs_node.  */
+                               continue;
+                       }
                }
 
                check_node:
@@ -780,6 +842,23 @@ jffs_scan_flash(struct jffs_control *c)
                                       "(err = %d)\n", err);
                                break;
                        }
+                       if (raw_inode.rename) {
+                               struct jffs_delete_list *dl
+                               = (struct jffs_delete_list *)
+                                 kmalloc(sizeof(struct jffs_delete_list),
+                                         GFP_KERNEL);
+                               if (!dl) {
+                                       D(printk("jffs_scan_flash: !dl\n"));
+                                       kfree(node);
+                                       DJM(no_jffs_node--);
+                                       flash_safe_release(fmc->flash_part);
+                                       return -ENOMEM;
+                               }
+                               dl->ino = deleted_file;
+                               dl->next = c->delete_list;
+                               c->delete_list = dl;
+                               node->data_size = 0;
+                       }
                        D3(jffs_print_node(node));
                        node = 0; /* Don't free the node!  */
                }
@@ -815,7 +894,8 @@ jffs_insert_node(struct jffs_control *c, struct jffs_file *f,
        int update_name = 0;
        int insert_into_tree = 0;
 
-       D2(printk("jffs_insert_node(): ino = %u, version = %u, name = \"%s\"\n",
+       D2(printk("jffs_insert_node(): ino = %u, version = %u, "
+                 "name = \"%s\"\n",
                  raw_inode->ino, raw_inode->version,
                  ((name && *name) ? name : "")));
 
@@ -942,11 +1022,9 @@ jffs_insert_node(struct jffs_control *c, struct jffs_file *f,
                        }
                        jffs_remove_redundant_nodes(f);
                }
-#ifdef USE_GC
-               if (!c->fmc->no_call_gc) {
-                       jffs_garbage_collect(c);
-               }
-#endif
+
+               jffs_garbage_collect_trigger(c);
+
                D3(printk("jffs_insert_node(): ---------------------------"
                          "------------------------------------------- 2\n"));
        }
@@ -1247,8 +1325,8 @@ jffs_write_dummy_node(struct jffs_control *c, struct jffs_fm *dirty_fm)
                                            (u_char *)&raw_inode,
                                            sizeof(struct jffs_raw_inode)))
                    < 0) {
-                       printk(KERN_ERR "JFFS: jffs_write_dummy_node: "
-                              "flash_safe_write failed!\n");
+                       printk(KERN_ERR "JFFS: jffs_write_dummy_node: "
+                              "flash_safe_write failed!\n");
                        return err;
                }
        }
@@ -1262,6 +1340,7 @@ jffs_write_dummy_node(struct jffs_control *c, struct jffs_fm *dirty_fm)
        return 0;
 }
 
+
 /* Write a raw inode, possibly its name and possibly some data.  */
 int
 jffs_write_node(struct jffs_control *c, struct jffs_node *node,
@@ -1269,7 +1348,7 @@ jffs_write_node(struct jffs_control *c, struct jffs_node *node,
                const char *name, const unsigned char *data)
 {
        struct jffs_fmcontrol *fmc = c->fmc;
-       struct jffs_fm *fm;
+       struct jffs_fm *fm = NULL;
        __u32 pos;
        int err;
        __u32 total_name_size = raw_inode->nsize
@@ -1296,30 +1375,54 @@ jffs_write_node(struct jffs_control *c, struct jffs_node *node,
                  (name ? name : ""), raw_inode->ino,
                  raw_inode->version, total_size));
 
-       /* First try to allocate some flash memory.  */
-       if ((err = jffs_fmalloc(fmc, total_size, node, &fm)) < 0) {
-               D(printk("jffs_write_node(): jffs_fmalloc(0x%p, %u) "
-                        "failed!\n", fmc, total_size));
-               return err;
-       }
-       else if (!fm->nodes) {
-               /* The jffs_fm struct that we got is not good enough.
-                  Make that space dirty.  */
-               if ((err = jffs_write_dummy_node(c, fm)) < 0) {
-                       D(printk("jffs_write_node(): "
-                                "jffs_write_dummy_node(): Failed!\n"));
-                       kfree(fm);
-                       DJM(no_jffs_fm--);
+       jffs_fm_write_lock(fmc);
+
+       while (!fm) {
+
+               /* First try to allocate some flash memory.  */
+               err = jffs_fmalloc(fmc, total_size, node, &fm);
+               
+               if (err == -ENOSPC) {
+                       /* Just out of space. GC and try again */
+                       if (fmc->dirty_size < fmc->sector_size) {
+                               D(printk("jffs_write_node(): jffs_fmalloc(0x%p, %u) "
+                                        "failed, no dirty space to GC\n", fmc,
+                                        total_size));
+                               return err;
+                       }
+                       
+                       D1(printk(KERN_INFO "jffs_write_node(): Calling jffs_garbage_collect_now()\n"));
+                       jffs_fm_write_unlock(fmc);
+                       if ((err = jffs_garbage_collect_now(c))) {
+                               D(printk("jffs_write_node(): jffs_garbage_collect_now() failed\n"));
+                               return err;
+                       }
+                       jffs_fm_write_lock(fmc);
+                       continue;
+               } 
+
+               if (err < 0) {
+                       jffs_fm_write_unlock(fmc);
+
+                       D(printk("jffs_write_node(): jffs_fmalloc(0x%p, %u) "
+                                "failed!\n", fmc, total_size));
                        return err;
                }
-               /* Get a new one.  */
-               if ((err = jffs_fmalloc(fmc, total_size, node, &fm)) < 0) {
-                       D(printk("jffs_write_node(): Second "
-                                "jffs_fmalloc(0x%p, %u) failed!\n",
-                                fmc, total_size));
-                       return err;
+
+               if (!fm->nodes) {
+                       /* The jffs_fm struct that we got is not good enough.
+                          Make that space dirty and try again  */
+                       if ((err = jffs_write_dummy_node(c, fm)) < 0) {
+                               kfree(fm);
+                               DJM(no_jffs_fm--);
+                               jffs_fm_write_unlock(fmc);
+                               D(printk("jffs_write_node(): "
+                                        "jffs_write_dummy_node(): Failed!\n"));
+                               return err;
+                       }
+                       fm = NULL;
                }
-       }
+       } /* while(!fm) */
        node->fm = fm;
 
        ASSERT(if (fm->nodes == 0) {
@@ -1341,7 +1444,7 @@ jffs_write_node(struct jffs_control *c, struct jffs_node *node,
        raw_inode->accurate = 0xff;
 
        D3(printk("jffs_write_node(): About to write this raw inode to the "
-                 "flash at pos 0x%ld:\n", (long)pos));
+                 "flash at pos 0x%lx:\n", (long)pos));
        D3(jffs_print_raw_inode(raw_inode));
 
        /* Step 1: Write the raw jffs inode to the flash.  */
@@ -1350,8 +1453,9 @@ jffs_write_node(struct jffs_control *c, struct jffs_node *node,
                                    sizeof(struct jffs_raw_inode))) < 0) {
                jffs_fmfree_partly(fmc, fm,
                                   total_name_size + total_data_size);
-               printk(KERN_ERR "JFFS: jffs_write_node: Failed to write "
-                      "raw_inode.\n");
+               jffs_fm_write_unlock(fmc);
+               printk(KERN_ERR "JFFS: jffs_write_node: Failed to write "
+                      "raw_inode.\n");
                return err;
        }
        pos += sizeof(struct jffs_raw_inode);
@@ -1359,9 +1463,10 @@ jffs_write_node(struct jffs_control *c, struct jffs_node *node,
        /* Step 2: Write the name, if there is any.  */
        if (raw_inode->nsize) {
                if ((err = flash_safe_write(fmc->mtd, pos,
-                                           (u_char *)name,
+                                           (u_char *)name,
                                            raw_inode->nsize)) < 0) {
                        jffs_fmfree_partly(fmc, fm, total_data_size);
+                       jffs_fm_write_unlock(fmc);
                        printk(KERN_ERR "JFFS: jffs_write_node: Failed to "
                               "write the name.\n");
                        return err;
@@ -1374,12 +1479,13 @@ jffs_write_node(struct jffs_control *c, struct jffs_node *node,
                if ((err = flash_safe_write(fmc->mtd, pos, data,
                                            raw_inode->dsize)) < 0) {
                        jffs_fmfree_partly(fmc, fm, 0);
-                        printk(KERN_ERR "JFFS: jffs_write_node: Failed to "
+                       jffs_fm_write_unlock(fmc);
+                       printk(KERN_ERR "JFFS: jffs_write_node: Failed to "
                               "write the data.\n");
                        return err;
                }
        }
-
+       jffs_fm_write_unlock(fmc);
        D3(printk("jffs_write_node(): Leaving...\n"));
        return raw_inode->dsize;
 } /* jffs_write_node()  */
@@ -1498,7 +1604,7 @@ jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *))
 }
 
 
-/* Free all memory associated with a file.  */
+/* Free all nodes associated with a file.  */
 int
 jffs_free_node_list(struct jffs_file *f)
 {
@@ -1518,6 +1624,23 @@ jffs_free_node_list(struct jffs_file *f)
 }
 
 
+/* Free a file and its name.  */
+int
+jffs_free_file(struct jffs_file *f)
+{
+       D3(printk("jffs_free_file: f #%u, \"%s\"\n",
+                 f->ino, (f->name ? f->name : "")));
+
+       if (f->name) {
+               kfree(f->name);
+               DJM(no_name--);
+       }
+       kfree(f);
+       DJM(no_jffs_file--);
+       return 0;
+}
+
+
 /* See if a file is deleted. If so, mark that file's nodes as obsolete.  */
 int
 jffs_possibly_delete_file(struct jffs_file *f)
@@ -1533,7 +1656,8 @@ jffs_possibly_delete_file(struct jffs_file *f)
        });
 
        if (f->deleted) {
-               /* First try to remove all older versions.  */
+               /* First try to remove all older versions.  Commence with
+                  the oldest node.  */
                for (n = f->version_head; n; n = n->version_next) {
                        if (!n->fm) {
                                continue;
@@ -1543,15 +1667,12 @@ jffs_possibly_delete_file(struct jffs_file *f)
                        }
                }
                /* Unlink the file from the filesystem.  */
-               jffs_unlink_file_from_tree(f);
+               if (!f->c->building_fs) {
+                       jffs_unlink_file_from_tree(f);
+               }
                jffs_unlink_file_from_hash(f);
                jffs_free_node_list(f);
-               if (f->name) {
-                       kfree(f->name);
-                       DJM(no_name--);
-               }
-               kfree(f);
-               DJM(no_jffs_file--);
+               jffs_free_file(f);
        }
        return 0;
 }
@@ -1589,7 +1710,7 @@ jffs_build_file(struct jffs_file *f)
 
    Starting offset of area to be removed is node->data_offset,
    and the length of the area is in node->removed_size.   */
-static void
+static int
 jffs_delete_data(struct jffs_file *f, struct jffs_node *node)
 {
        struct jffs_node *n;
@@ -1604,7 +1725,7 @@ jffs_delete_data(struct jffs_file *f, struct jffs_node *node)
            && f->range_tail->data_offset + f->range_tail->data_size
               == offset) {
                /* A simple append; nothing to remove or no node to split.  */
-               return;
+               return 0;
        }
 
        /* Find the node where we should begin the removal.  */
@@ -1616,7 +1737,7 @@ jffs_delete_data(struct jffs_file *f, struct jffs_node *node)
        if (!n) {
                /* If there's no data in the file there's no data to
                   remove either.  */
-               return;
+               return 0;
        }
 
        if (n->data_offset > offset) {
@@ -1626,7 +1747,7 @@ jffs_delete_data(struct jffs_file *f, struct jffs_node *node)
        }
        else if (n->data_offset < offset) {
                /* See if the node has to be split into two parts.  */
-               if (n->data_offset + n->data_size < offset + remove_size) {
+               if (n->data_offset + n->data_size > offset + remove_size) {
                        /* Do the split.  */
                        struct jffs_node *new_node;
                        D3(printk("jffs_delete_data(): Split node with "
@@ -1636,18 +1757,15 @@ jffs_delete_data(struct jffs_file *f, struct jffs_node *node)
                                         kmalloc(sizeof(struct jffs_node),
                                                 GFP_KERNEL))) {
                                D(printk("jffs_delete_data(): -ENOMEM\n"));
-                               return;
+                               return -ENOMEM;
                        }
                        DJM(no_jffs_node++);
 
                        new_node->ino = n->ino;
                        new_node->version = n->version;
                        new_node->data_offset = offset;
-                       new_node->data_size = n->data_size
-                                             - (remove_size
-                                                + (offset - n->data_offset));
-                       new_node->fm_offset = n->fm_offset + n->data_size
-                                             + remove_size;
+                       new_node->data_size = n->data_size - (remove_size + (offset - n->data_offset));
+                       new_node->fm_offset = n->fm_offset + (remove_size + (offset - n->data_offset));
                        new_node->name_size = n->name_size;
                        new_node->fm = n->fm;
                        new_node->version_prev = n;
@@ -1671,7 +1789,12 @@ jffs_delete_data(struct jffs_file *f, struct jffs_node *node)
                        /* A very interesting can of worms.  */
                        n->range_next = new_node;
                        n->data_size = offset - n->data_offset;
-                       jffs_add_node(new_node);
+                       if (new_node->fm)
+                               jffs_add_node(new_node);
+                       else {
+                               D1(printk(KERN_WARNING "jffs_delete_data(): Splitting an empty node (file hold).\n!"));
+                               D1(printk(KERN_WARNING "FIXME: Did dwmw2 do the right thing here?\n"));
+                       }
                        n = new_node->range_next;
                        remove_size = 0;
                }
@@ -1693,8 +1816,9 @@ jffs_delete_data(struct jffs_file *f, struct jffs_node *node)
                        remove_size -= n->data_size;
                        n = n->range_next;
                        D3(printk("jffs_delete_data(): Removing node: "
-                                 "ino: %u, version: %u\n",
-                                 p->ino, p->version));
+                                 "ino: %u, version: %u%s\n",
+                                 p->ino, p->version,
+                                 (p->fm ? "" : " (virtual)")));
                        if (p->fm) {
                                jffs_fmfree(f->c->fmc, p->fm, p);
                        }
@@ -1720,12 +1844,13 @@ jffs_delete_data(struct jffs_file *f, struct jffs_node *node)
 
        f->size -= node->removed_size;
        D3(printk("jffs_delete_data(): f->size = %d\n", f->size));
+       return 0;
 } /* jffs_delete_data()  */
 
 
 /* Insert some data into a file.  Prior to the call to this function,
-   jffs_delete_data() should be called.  */
-static void
+   jffs_delete_data should be called.  */
+static int
 jffs_insert_data(struct jffs_file *f, struct jffs_node *node)
 {
        D3(printk("jffs_insert_data(): node->data_offset = %u, "
@@ -1733,7 +1858,7 @@ jffs_insert_data(struct jffs_file *f, struct jffs_node *node)
                  node->data_offset, node->data_size, f->size));
 
        /* Find the position where we should insert data.  */
-
+       retry:
        if (node->data_offset == f->size) {
                /* A simple append.  This is the most common operation.  */
                node->range_next = 0;
@@ -1775,7 +1900,7 @@ jffs_insert_data(struct jffs_file *f, struct jffs_node *node)
                                printk(KERN_ERR "jffs_insert_data(): "
                                       "Couldn't find a place to insert "
                                       "the data!\n");
-                               return;
+                               return -1;
                        });
                }
 
@@ -1788,38 +1913,84 @@ jffs_insert_data(struct jffs_file *f, struct jffs_node *node)
                f->size += node->data_size;
        }
        else if (node->data_offset > f->size) {
-               /* Not implemented yet.  */
-#if 0
-               /* Below is some example code for future use if we decide
-                  to implement it.  */
-               /* This is code that isn't supported by VFS. So there aren't
-                  really any reasons to implement it yet.  */
-               if (!f->range_head) {
-                       if (node->data_offset > f->size) {
-                               if (!(nn = jffs_alloc_node())) {
-                                       D(printk("jffs_insert_data(): "
-                                                "Allocation failed.\n"));
-                                       return;
+               /* Okay.  This is tricky.  This means that we want to insert
+                  data at a place that is beyond the limits of the file as
+                  it is constructed right now.  This is actually a common
+                  event that for instance could occur during the mounting
+                  of the file system if a large file have been truncated,
+                  rewritten and then only partially garbage collected.  */
+
+               struct jffs_node *n;
+
+               /* We need a place holder for the data that is missing in
+                  front of this insertion.  This "virtual node" will not
+                  be associated with any space on the flash device.  */
+               struct jffs_node *virtual_node;
+               if (!(virtual_node = (struct jffs_node *)
+                                    kmalloc(sizeof(struct jffs_node),
+                                            GFP_KERNEL))) {
+                       return -ENOMEM;
+               }
+
+               D(printk("jffs_insert_data: Inserting a virtual node.\n"));
+               D(printk("  node->data_offset = %u\n", node->data_offset));
+               D(printk("  f->size = %u\n", f->size));
+
+               virtual_node->ino = node->ino;
+               virtual_node->version = node->version;
+               virtual_node->removed_size = 0;
+               virtual_node->fm_offset = 0;
+               virtual_node->name_size = 0;
+               virtual_node->fm = 0; /* This is a virtual data holder.  */
+               virtual_node->version_prev = 0;
+               virtual_node->version_next = 0;
+               virtual_node->range_next = 0;
+
+               /* Are there any data at all in the file yet?  */
+               if (f->range_head) {
+                       virtual_node->data_offset
+                       = f->range_tail->data_offset
+                         + f->range_tail->data_size;
+                       virtual_node->data_size
+                       = node->data_offset - virtual_node->data_offset;
+                       virtual_node->range_prev = f->range_tail;
+                       f->range_tail->range_next = virtual_node;
+               }
+               else {
+                       virtual_node->data_offset = 0;
+                       virtual_node->data_size = node->data_offset;
+                       virtual_node->range_prev = 0;
+                       f->range_head = virtual_node;
+               }
+
+               f->range_tail = virtual_node;
+               f->size += virtual_node->data_size;
+
+               /* Insert this virtual node in the version list as well.  */
+               for (n = f->version_head; n ; n = n->version_next) {
+                       if (n->version == virtual_node->version) {
+                               virtual_node->version_prev = n->version_prev;
+                               n->version_prev = virtual_node;
+                               if (virtual_node->version_prev) {
+                                       virtual_node->version_prev
+                                       ->version_next = virtual_node;
+                               }
+                               else {
+                                       f->version_head = virtual_node;
                                }
-                               nn->version = JFFS_MAGIC_BITMASK;
-                               nn->data_offset = 0;
-                               nn->data_size = node->data_offset;
-                               nn->removed_size = 0;
-                               nn->fm_offset = 0;
-                               nn->name_size = 0;
-                               nn->fm = 0; /* This is a virtual data holder.  */
-                               nn->version_prev = 0;
-                               nn->version_next = 0;
-                               nn->range_prev = 0;
-                               nn->range_next = 0;
-                               nh->range_head = nn;
-                               nh->range_tail = nn;
+                               virtual_node->version_next = n;
+                               break;
                        }
                }
-#endif
+
+               D(jffs_print_node(virtual_node));
+
+               /* Make a new try to insert the node.  */
+               goto retry;
        }
 
        D3(printk("jffs_insert_data(): f->size = %d\n", f->size));
+       return 0;
 }
 
 
@@ -1828,6 +1999,8 @@ jffs_insert_data(struct jffs_file *f, struct jffs_node *node)
 static int
 jffs_update_file(struct jffs_file *f, struct jffs_node *node)
 {
+       int err;
+
        D3(printk("jffs_update_file(): ino: %u, version: %u\n",
                  f->ino, node->version));
 
@@ -1841,15 +2014,21 @@ jffs_update_file(struct jffs_file *f, struct jffs_node *node)
                        /* data_offset == X  */
                        /* data_size == 0  */
                        /* remove_size != 0  */
-                       jffs_delete_data(f, node);
+                       if ((err = jffs_delete_data(f, node)) < 0) {
+                               return err;
+                       }
                }
        }
        else {
                /* data_offset == X  */
                /* data_size != 0  */
                /* remove_size == Y  */
-               jffs_delete_data(f, node);
-               jffs_insert_data(f, node);
+               if ((err = jffs_delete_data(f, node)) < 0) {
+                       return err;
+               }
+               if ((err = jffs_insert_data(f, node)) < 0) {
+                       return err;
+               }
        }
        return 0;
 }
@@ -1868,7 +2047,7 @@ jffs_print_node(struct jffs_node *n)
        D(printk("        0x%08x, /* fm_offset  */\n", n->fm_offset));
        D(printk("        0x%02x,       /* name_size  */\n", n->name_size));
        D(printk("        0x%p, /* fm,  fm->offset: %u  */\n",
-                n->fm, n->fm->offset));
+                n->fm, (n->fm ? n->fm->offset : 0)));
        D(printk("        0x%p, /* version_prev  */\n", n->version_prev));
        D(printk("        0x%p, /* version_next  */\n", n->version_next));
        D(printk("        0x%p, /* range_prev  */\n", n->range_prev));
@@ -1979,6 +2158,7 @@ jffs_print_tree(struct jffs_file *first_file, int indent)
 {
        struct jffs_file *f;
        char *space;
+       int dir;
 
        if (!first_file) {
                return;
@@ -1993,10 +2173,11 @@ jffs_print_tree(struct jffs_file *first_file, int indent)
        space[indent] = '\0';
 
        for (f = first_file; f; f = f->sibling_next) {
-               printk("%s%s (ino: %u, highest_version: %u, size: %u)\n",
-                      space, (f->name ? f->name : "/"),
+               dir = S_ISDIR(f->mode);
+               printk("%s%s%s (ino: %u, highest_version: %u, size: %u)\n",
+                      space, (f->name ? f->name : ""), (dir ? "/" : ""),
                       f->ino, f->highest_version, f->size);
-               if (S_ISDIR(f->mode)) {
+               if (dir) {
                        jffs_print_tree(f->children, indent + 2);
                }
        }
@@ -2053,7 +2234,6 @@ jffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, int size)
        }
        DJM(no_jffs_node++);
        new_node->data_offset = node->data_offset;
-       new_node->data_size = size;
        new_node->removed_size = size;
        total_name_size = f->nsize + JFFS_GET_PAD_BYTES(f->nsize);
        total_data_size = size + JFFS_GET_PAD_BYTES(size);
@@ -2062,23 +2242,28 @@ jffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, int size)
        new_node->fm_offset = sizeof(struct jffs_raw_inode)
                              + total_name_size;
 
+       jffs_fm_write_lock(fmc);
+
        if ((err = jffs_fmalloc(fmc, total_size, new_node, &fm)) < 0) {
+               DJM(no_jffs_node--);
+               jffs_fm_write_unlock(fmc);
                D(printk("jffs_rewrite_data(): Failed to allocate fm.\n"));
                kfree(new_node);
-               DJM(no_jffs_node--);
                return err;
        }
        else if (!fm->nodes) {
                /* The jffs_fm struct that we got is not good enough.  */
                if ((err = jffs_write_dummy_node(c, fm)) < 0) {
+                       DJM(no_jffs_fm--);
+                       jffs_fm_write_unlock(fmc);
                        D(printk("jffs_rewrite_data(): "
                                 "jffs_write_dummy_node() Failed!\n"));
                        kfree(fm);
-                       DJM(no_jffs_fm--);
                        return err;
                }
                /* Get a new one.  */
                if ((err = jffs_fmalloc(fmc, total_size, node, &fm)) < 0) {
+                       jffs_fm_write_unlock(fmc);
                        D(printk("jffs_rewrite_data(): Second "
                                 "jffs_fmalloc(0x%p, %u) failed!\n",
                                 fmc, total_size));
@@ -2127,10 +2312,11 @@ jffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, int size)
                                    sizeof(struct jffs_raw_inode)
                                    - sizeof(__u32)
                                    - sizeof(__u16) - sizeof(__u16))) < 0) {
-                printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during "
-                         "rewrite. (raw inode)\n");
                jffs_fmfree_partly(fmc, fm,
                                   total_name_size + total_data_size);
+               jffs_fm_write_unlock(fmc);
+               printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during "
+                      "rewrite. (raw inode)\n");
                return err;
        }
        pos += sizeof(struct jffs_raw_inode);
@@ -2142,9 +2328,10 @@ jffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, int size)
                if ((err = flash_safe_write(fmc->mtd, pos,
                                            (u_char *)f->name,
                                            f->nsize)) < 0) {
-                        printk(KERN_ERR "JFFS: jffs_rewrite_data: Write "
-                               "error during rewrite. (name)\n");
                        jffs_fmfree_partly(fmc, fm, total_data_size);
+                       jffs_fm_write_unlock(fmc);
+                       printk(KERN_ERR "JFFS: jffs_rewrite_data: Write "
+                              "error during rewrite. (name)\n");
                        return err;
                }
                pos += total_name_size;
@@ -2166,19 +2353,22 @@ jffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, int size)
                        __u32 s = jffs_min(size, PAGE_SIZE);
                        if ((r = jffs_read_data(f, (char *)page,
                                                offset, s)) < s) {
-                                printk(KERN_ERR "JFFS: jffs_rewrite_data: "
+                               free_page((unsigned long)page);
+                               jffs_fmfree_partly(fmc, fm, 0);
+                               jffs_fm_write_unlock(fmc);
+                               printk(KERN_ERR "JFFS: jffs_rewrite_data: "
                                         "jffs_read_data() "
                                         "failed! (r = %d)\n", r);
-                               jffs_fmfree_partly(fmc, fm, 0);
                                return -1;
                        }
                        if ((err = flash_safe_write(fmc->mtd,
                                                    pos, page, r)) < 0) {
-                                printk(KERN_ERR "JFFS: jffs_rewrite_data: "
-                                       "Write error during rewrite. "
-                                       "(data)\n");
                                free_page((unsigned long)page);
                                jffs_fmfree_partly(fmc, fm, 0);
+                               jffs_fm_write_unlock(fmc);
+                               printk(KERN_ERR "JFFS: jffs_rewrite_data: "
+                                      "Write error during rewrite. "
+                                      "(data)\n");
                                return err;
                        }
                        pos += r;
@@ -2202,14 +2392,16 @@ jffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, int size)
                                &raw_inode)[JFFS_RAW_INODE_DCHKSUM_OFFSET],
                                sizeof(__u32) + sizeof(__u16)
                                + sizeof(__u16))) < 0) {
-                printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during "
-                         "rewrite. (checksum)\n");
                jffs_fmfree_partly(fmc, fm, 0);
+               jffs_fm_write_unlock(fmc);
+               printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during "
+                      "rewrite. (checksum)\n");
                return err;
        }
 
        /* Now make the file system aware of the newly written node.  */
        jffs_insert_node(c, f, &raw_inode, f->name, new_node);
+       jffs_fm_write_unlock(fmc);
 
        D3(printk("jffs_rewrite_data(): Leaving...\n"));
        return 0;
@@ -2219,6 +2411,7 @@ jffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, int size)
 /* jffs_garbage_collect_next implements one step in the garbage collect
    process and is often called multiple times at each occasion of a
    garbage collect.  */
+
 int
 jffs_garbage_collect_next(struct jffs_control *c)
 {
@@ -2226,8 +2419,8 @@ jffs_garbage_collect_next(struct jffs_control *c)
        struct jffs_node *node;
        struct jffs_file *f;
        int size;
-        int data_size;
-        int total_name_size;
+       int data_size;
+       int total_name_size;
        int free_size = fmc->flash_size - (fmc->used_size + fmc->dirty_size);
        __u32 free_chunk_size1 = jffs_free_size1(fmc);
        D2(__u32 free_chunk_size2 = jffs_free_size2(fmc));
@@ -2235,17 +2428,17 @@ jffs_garbage_collect_next(struct jffs_control *c)
        /* Get the oldest node in the flash.  */
        node = jffs_get_oldest_node(fmc);
        ASSERT(if (!node) {
-                printk(KERN_ERR "JFFS: jffs_garbage_collect_next: "
-                       "No oldest node found!\n");
+               printk(KERN_ERR "JFFS: jffs_garbage_collect_next: "
+                      "No oldest node found!\n");
                return -1;
        });
 
        /* Find its corresponding file too.  */
        f = jffs_find_file(c, node->ino);
        ASSERT(if (!f) {
-                printk(KERN_ERR "JFFS: jffs_garbage_collect_next: "
-                       "No file to garbage collect! "
-                       "(ino = 0x%08x)\n", node->ino);
+               printk(KERN_ERR "JFFS: jffs_garbage_collect_next: "
+                      "No file to garbage collect! "
+                      "(ino = 0x%08x)\n", node->ino);
                return -1;
        });
 
@@ -2254,23 +2447,25 @@ jffs_garbage_collect_next(struct jffs_control *c)
                  (f->name ? f->name : ""), node->ino, node->version));
 
        /* Compute how much we want to rewrite at the moment.  */
-        data_size = f->size - node->data_offset;
-        total_name_size = f->nsize + JFFS_GET_PAD_BYTES(f->nsize);
-        size = sizeof(struct jffs_raw_inode) + total_name_size
-               + data_size + JFFS_GET_PAD_BYTES(data_size);
+       data_size = f->size - node->data_offset;
+       total_name_size = f->nsize + JFFS_GET_PAD_BYTES(f->nsize);
+       size = sizeof(struct jffs_raw_inode) + total_name_size
+              + data_size + JFFS_GET_PAD_BYTES(data_size);
 
-        D2(printk("  total_name_size: %u\n", total_name_size));
-        D2(printk("  data_size: %u\n", data_size));
+       D2(printk("  total_name_size: %u\n", total_name_size));
+       D2(printk("  data_size: %u\n", data_size));
        D2(printk("  size: %u\n", size));
        D2(printk("  f->nsize: %u\n", f->nsize));
        D2(printk("  f->size: %u\n", f->size));
+       D2(printk("  node->data_offset: %u\n", node->data_offset));
        D2(printk("  free_chunk_size1: %u\n", free_chunk_size1));
        D2(printk("  free_chunk_size2: %u\n", free_chunk_size2));
+       D2(printk("  node->fm->offset: 0x%08x\n", node->fm->offset));
 
        if (size > fmc->max_chunk_size) {
                size = fmc->max_chunk_size;
-                data_size = size - sizeof(struct jffs_raw_inode)
-                            - total_name_size;
+               data_size = size - sizeof(struct jffs_raw_inode)
+                           - total_name_size;
        }
        if (size > free_chunk_size1) {
 
@@ -2282,11 +2477,11 @@ jffs_garbage_collect_next(struct jffs_control *c)
                        = jffs_fmalloced(fmc,
                                         fmc->tail->offset + fmc->tail->size,
                                         free_chunk_size1, NULL);
-                        if (!dirty_fm) {
-                                printk(KERN_ERR "JFFS: "
-                                       "jffs_garbage_collect_next: "
-                                       "Failed to allocate `dirty' "
-                                       "flash memory!\n");
+                       if (!dirty_fm) {
+                               printk(KERN_ERR "JFFS: "
+                                      "jffs_garbage_collect_next: "
+                                      "Failed to allocate `dirty' "
+                                      "flash memory!\n");
                                return -1;
                        }
                        jffs_write_dummy_node(c, dirty_fm);
@@ -2294,24 +2489,24 @@ jffs_garbage_collect_next(struct jffs_control *c)
                }
 
                size = free_chunk_size1;
-                data_size = size - sizeof(struct jffs_raw_inode)
-                            - total_name_size;
+               data_size = size - sizeof(struct jffs_raw_inode)
+                           - total_name_size;
        }
 
        D2(printk("  size: %u (again)\n", size));
 
        if (free_size - size < fmc->sector_size) {
                /* Just rewrite that node (or even less).  */
-                jffs_rewrite_data(f, node,
-                                  jffs_min(node->data_size, data_size));
+               jffs_rewrite_data(f, node,
+                                 jffs_min(node->data_size, data_size));
        }
        else {
                size -= (sizeof(struct jffs_raw_inode) + f->nsize);
-                jffs_rewrite_data(f, node, data_size);
+               jffs_rewrite_data(f, node, data_size);
        }
 
 jffs_garbage_collect_next_end:
-        D3(printk("jffs_garbage_collect_next: Leaving...\n"));
+       D3(printk("jffs_garbage_collect_next: Leaving...\n"));
        return 0;
 } /* jffs_garbage_collect_next */
 
@@ -2319,7 +2514,9 @@ jffs_garbage_collect_next_end:
 /* If an obsolete node is partly going to be erased due to garbage
    collection, the part that isn't going to be erased must be filled
    with zeroes so that the scan of the flash will work smoothly next
-   time.
+   time.  (The data in the file could for instance be a JFFS image
+   which could cause enormous confusion during a scan of the flash
+   device if we didn't do this.)
      There are two phases in this procedure: First, the clearing of
    the name and data parts of the node. Second, possibly also clearing
    a part of the raw inode as well.  If the box is power cycled during
@@ -2400,19 +2597,19 @@ jffs_try_to_erase(struct jffs_control *c)
 
        D2(printk("jffs_try_to_erase(): erase_size = %ld\n", erase_size));
 
-        if (erase_size == 0) {
-                return 0;
-        }
-        else if (erase_size < 0) {
-                printk(KERN_ERR "JFFS: jffs_try_to_erase: "
-                       "jffs_erasable_size returned %ld.\n", erase_size);
+       if (erase_size == 0) {
+               return 0;
+       }
+       else if (erase_size < 0) {
+               printk(KERN_ERR "JFFS: jffs_try_to_erase: "
+                      "jffs_erasable_size returned %ld.\n", erase_size);
                return erase_size;
        }
 
-        if ((err = jffs_clear_end_of_node(c, erase_size)) < 0) {
-                printk(KERN_ERR "JFFS: jffs_try_to_erase: "
-                       "Clearing of node failed.\n");
-                return err;
+       if ((err = jffs_clear_end_of_node(c, erase_size)) < 0) {
+               printk(KERN_ERR "JFFS: jffs_try_to_erase: "
+                      "Clearing of node failed.\n");
+               return err;
        }
 
        offset = fmc->head->offset - fmc->flash_start;
@@ -2444,7 +2641,7 @@ jffs_try_to_erase(struct jffs_control *c)
 
                for (; pos < end; pos += 4) {
                        if (*(__u32 *)pos != JFFS_EMPTY_BITMASK) {
-                               printk("JFFS: Erase failed! pos = 0x%ld\n",
+                               printk("JFFS: Erase failed! pos = 0x%lx\n",
                                       (long)pos);
                                jffs_hexdump(fmc->mtd, pos,
                                             jffs_min(256, end - pos));
@@ -2475,7 +2672,7 @@ jffs_try_to_erase(struct jffs_control *c)
 
 
 /* There are different criteria that should trigger a garbage collect:
-   
+
    1. There is too much dirt in the memory.
    2. The free space is becoming small.
    3. There are many versions of a node.
@@ -2485,27 +2682,26 @@ jffs_try_to_erase(struct jffs_control *c)
    should not be too large (span more than one sector in the flash memory
    for exemple).  Of course there is a limit on how intelligent this garbage
    collection can be.  */
+
 int
-jffs_garbage_collect(struct jffs_control *c)
+jffs_garbage_collect_now(struct jffs_control *c)
 {
        struct jffs_fmcontrol *fmc = c->fmc;
        long erased_total = 0;
        long erased;
        int result = 0;
        D1(int i = 1);
-
-       D2(printk("***jffs_garbage_collect(): fmc->dirty_size = %u\n",
+       D2(printk("***jffs_garbage_collect_now(): fmc->dirty_size = %u\n",
                  fmc->dirty_size));
        D2(jffs_print_fmcontrol(fmc));
 
-       c->fmc->no_call_gc = 1;
+       down(&fmc->gclock);
 
-       /* While there is too much dirt left and it is possible
-          to garbage collect, do so.  */
+       /* If it is possible to garbage collect, do so.  */
 
-       while (fmc->dirty_size >= fmc->sector_size) {
+       if (fmc->dirty_size >= fmc->sector_size) {
 
-               D1(printk("***jffs_garbage_collect(): round #%u, "
+               D1(printk("***jffs_garbage_collect_now(): round #%u, "
                         "fmc->dirty_size = %u\n", i++, fmc->dirty_size));
                D2(jffs_print_fmcontrol(fmc));
 
@@ -2533,7 +2729,7 @@ jffs_garbage_collect(struct jffs_control *c)
                        }
                        else {
                                /* What should we do here?  */
-                               D(printk("   jffs_garbage_collect(): "
+                               D(printk("   jffs_garbage_collect_now(): "
                                         "erased: %ld, free_size: %u\n",
                                         erased, free_size));
                                result = -1;
@@ -2541,19 +2737,204 @@ jffs_garbage_collect(struct jffs_control *c)
                        }
                }
 
-               D1(printk("   jffs_garbage_collect(): erased: %ld\n", erased));
+               D1(printk("   jffs_garbage_collect_now(): erased: %ld\n", erased));
                erased_total += erased;
                DJM(jffs_print_memory_allocation_statistics());
        }
 
-
 gc_end:
-       c->fmc->no_call_gc = 0;
+       up(&fmc->gclock);
 
-       D3(printk("   jffs_garbage_collect(): Leaving...\n"));
+       D3(printk("   jffs_garbage_collect_now(): Leaving...\n"));
        D1(if (erased_total) {
                printk("erased_total = %ld\n", erased_total);
                jffs_print_fmcontrol(fmc);
        });
+
+       if (!erased_total && !result)
+               return -ENOSPC;
+
        return result;
+} /* jffs_garbage_collect_now() */
+
+
+/* Determine if it is reasonable to start garbage collection.
+   We start a gc pass if either:
+   - The number of free bytes < MIN_FREE_BYTES && at least one
+     block is dirty, OR
+   - The number of dirty bytes > MAX_DIRTY_BYTES
+*/
+static inline int thread_should_wake (struct jffs_control *c)
+{
+       __u32 nfree = c->fmc->flash_size - c->fmc->used_size - c->fmc->dirty_size;
+
+       D1(printk (KERN_NOTICE "thread_should_wake(): free=%d, dirty=%d, blocksize=%d.\n",
+                  nfree, c->fmc->dirty_size, c->fmc->sector_size));
+
+       /* If there's not enough dirty space to free a block, there's no point. */
+       if (c->fmc->dirty_size < c->fmc->sector_size)
+               return 0;
+
+       /* If there are fewer free bytes than the threshold, GC */
+       if (nfree < c->gc_minfree_threshold)
+               return 1;
+
+       /* If there are more dirty bytes than the threshold, GC */
+       if (c->fmc->dirty_size > c->gc_maxdirty_threshold)
+               return 1;
+       
+       /* FIXME: What about the "There are many versions of a node" condition? */
+
+       return 0;
 }
+
+
+void jffs_garbage_collect_trigger(struct jffs_control *c)
+{
+       /* NOTE: We rely on the fact that we have the BKL here.
+        * Otherwise, the gc_task could go away between the check
+        * and the wake_up_process()
+        */
+       if (c->gc_task && thread_should_wake(c))
+               send_sig(SIGHUP, c->gc_task, 1);
+}
+  
+
+/* Kernel threads  take (void *) as arguments.   Thus we pass
+   the jffs_control data as a (void *) and then cast it. */
+int
+jffs_garbage_collect_thread(void *ptr)
+{
+        struct jffs_control *c = (struct jffs_control *) ptr;
+       struct jffs_fmcontrol *fmc = c->fmc;
+       long erased_total = 0;
+       long erased;
+       int result = 0;
+       D1(int i = 1);
+
+       c->gc_task = current;
+
+       lock_kernel();
+       exit_mm(c->gc_task);
+
+       current->session = 1;
+       current->pgrp = 1;
+       init_MUTEX_LOCKED(&c->gc_thread_sem); /* barrier */ 
+       spin_lock_irq(&current->sigmask_lock);
+       siginitsetinv (&current->blocked, sigmask(SIGHUP) | sigmask(SIGQUIT) | sigmask(SIGSTOP) | sigmask(SIGCONT));
+       recalc_sigpending(current);
+       spin_unlock_irq(&current->sigmask_lock);
+       strcpy(current->comm, "jffs_gcd");
+
+       D1(printk (KERN_NOTICE "jffs_garbage_collect_thread(): Starting infinite loop.\n"));
+
+       for (;;) {
+               /* See if we need to start gc.  If we don't, go to sleep.
+                  
+                  Current implementation is a BAD THING(tm).  If we try 
+                  to unmount the FS, the unmount operation will sleep waiting
+                  for this thread to exit.  We need to arrange to send it a
+                  sig before the umount process sleeps.
+               */
+               
+               if (!thread_should_wake(c))
+                       set_current_state (TASK_INTERRUPTIBLE);
+               
+               schedule(); /* Yes, we do this even if we want to go
+                                      on immediately - we're a low priority 
+                                      background task. */
+
+               /* Put_super will send a SIGQUIT and then wait on the sem. 
+                */
+               while (signal_pending(current)) {
+                       siginfo_t info;
+                       unsigned long signr;
+
+                       spin_lock_irq(&current->sigmask_lock);
+                       signr = dequeue_signal(&current->blocked, &info);
+                       spin_unlock_irq(&current->sigmask_lock);
+
+                       switch(signr) {
+                       case SIGSTOP:
+                               D1(printk("jffs_garbage_collect_thread(): SIGSTOP received.\n"));
+                               set_current_state(TASK_STOPPED);
+                               schedule();
+                               break;
+
+                       case SIGQUIT:
+                               D1(printk("jffs_garbage_collect_thread(): SIGQUIT received.\n"));
+                               c->gc_task = NULL;
+                               up(&c->gc_thread_sem);
+                               unlock_kernel();
+                               return(0);
+                       }
+               }
+
+
+               D1(printk (KERN_NOTICE "jffs_garbage_collect_thread(): collecting.\n"));
+//             printk (KERN_NOTICE "free=%d, dirty=%d, blocksize=%ld.\n", count_free_bytes(c), count_dirty_bytes(c), c->sb->s_blocksize);
+
+               D2(printk("***jffs_garbage_collect_thread(): fmc->dirty_size = %u\n",
+                         fmc->dirty_size));
+               D2(jffs_print_fmcontrol(fmc));
+               
+               if (fmc->dirty_size < fmc->sector_size) {
+                       printk(KERN_WARNING "jffs_garbage_collect_thread with insufficient dirty space (0x%x)\n", fmc->dirty_size);
+                       continue;
+               }
+
+               down(&c->fmc->gclock);
+                       
+               D1(printk("***jffs_garbage_collect_thread(): round #%u, "
+                         "fmc->dirty_size = %u\n", i++, fmc->dirty_size));
+               D2(jffs_print_fmcontrol(fmc));
+               
+               /* At least one sector should be able to free now.  */
+               if ((erased = jffs_try_to_erase(c)) < 0) {
+                       printk(KERN_WARNING "JFFS: Error in "
+                              "garbage collector.\n");
+                       result = erased;
+                       goto gc_end;
+               }
+               else if (erased == 0) {
+                       __u32 free_size = fmc->flash_size
+                               - (fmc->used_size
+                                  + fmc->dirty_size);
+                       
+                       if (free_size > 0) {
+                               /* Let's dare to make a garbage collect.  */
+                               if ((result = jffs_garbage_collect_next(c))
+                                   < 0) {
+                                       printk(KERN_ERR "JFFS: Something "
+                                              "has gone seriously wrong "
+                                              "with a garbage collect.\n");
+                                       goto gc_end;
+                               }
+                       }
+                       else {
+                               /* What should we do here?  */
+                               D(printk("   jffs_garbage_collect(): "
+                                        "erased: %ld, free_size: %u\n",
+                                        erased, free_size));
+                               result = -1;
+                               goto gc_end;
+                       }
+               }
+
+               D1(printk("   jffs_garbage_collect(): erased: %ld\n", erased));
+               erased_total += erased;
+               DJM(jffs_print_memory_allocation_statistics());
+       
+               
+       gc_end:
+               up(&c->fmc->gclock);
+               
+               D3(printk("   jffs_garbage_collect(): Leaving...\n"));
+               D1(if (erased_total) {
+                       printk("erased_total = %ld\n", erased_total);
+                       jffs_print_fmcontrol(fmc);
+               });
+       
+       } /* for (;;) */
+} /* jffs_garbage_collect_thread() */
+
index 3336c69e649e1ac91dd1d35a4c9eb278f6d89d6c..d4638af201f51d1531c6911e4a2f4eef49808162 100644 (file)
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * $Id: intrep.h,v 1.2 2000/05/24 13:13:56 alex Exp $
+ * $Id: intrep.h,v 1.6 2000/08/04 14:29:17 dwmw2 Exp $
  *
  */
 
 #ifndef __LINUX_JFFS_INTREP_H__
 #define __LINUX_JFFS_INTREP_H__
-
+#include "jffs_fm.h"
 inline int jffs_min(int a, int b);
 inline int jffs_max(int a, int b);
 __u32 jffs_checksum(const void *data, int size);
@@ -34,6 +34,7 @@ void jffs_free_node(struct jffs_node *node);
 
 int jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *));
 int jffs_free_node_list(struct jffs_file *f);
+int jffs_free_file(struct jffs_file *f);
 int jffs_possibly_delete_file(struct jffs_file *f);
 int jffs_build_file(struct jffs_file *f);
 int jffs_insert_file_into_hash(struct jffs_file *f);
@@ -49,7 +50,26 @@ int jffs_write_node(struct jffs_control *c, struct jffs_node *node,
 int jffs_read_data(struct jffs_file *f, char *buf, __u32 read_offset, __u32 size);
 
 /* Garbage collection stuff.  */
-int jffs_garbage_collect(struct jffs_control *c);
+int jffs_garbage_collect_thread(void *c);
+void jffs_garbage_collect_trigger(struct jffs_control *c);
+int jffs_garbage_collect_now(struct jffs_control *c);
+
+/* Is there enough space on the flash?  */
+static inline int JFFS_ENOUGH_SPACE(struct jffs_control *c)
+{
+       struct jffs_fmcontrol *fmc = c->fmc;
+
+       while (1) {
+               if ((fmc->flash_size - (fmc->used_size + fmc->dirty_size)) 
+                       >= fmc->min_free_size) {
+                       return 1;
+               }
+               if (fmc->dirty_size < fmc->sector_size)
+                       return 0;
+
+               jffs_garbage_collect_now(c);
+       }
+}
 
 /* For debugging purposes.  */
 void jffs_print_node(struct jffs_node *n);
index abdb759a5096df0011b342748579768d093f8613..3140b8a53bc0b615265c7d76db32c45e64e248bd 100644 (file)
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * $Id: jffs_fm.c,v 1.8 2000/07/13 13:15:33 scote1 Exp $
+ * $Id: jffs_fm.c,v 1.14 2000/08/09 14:26:35 dwmw2 Exp $
  *
  * Ported to Linux 2.3.x and MTD:
  * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
  *
  */
 #define __NO_VERSION__
-#include <linux/config.h>
 #include <linux/malloc.h>
 #include <linux/blkdev.h>
 #include <linux/jffs.h>
 #include "jffs_fm.h"
 
-#if defined(CONFIG_JFFS_FS_VERBOSE) && CONFIG_JFFS_FS_VERBOSE
-#define D(x) x
-#else
-#define D(x)
-#endif
-#define D1(x) D(x)
-#define D2(x) 
-#define D3(x) 
-#define ASSERT(x) x
-
 #if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
 static int jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset);
 #endif
@@ -72,12 +61,13 @@ jffs_build_begin(struct jffs_control *c, kdev_t dev)
        fmc->max_chunk_size = fmc->sector_size >> 1;
        fmc->min_free_size = (fmc->sector_size << 1) - fmc->max_chunk_size;
        fmc->mtd = mtd;
-       fmc->no_call_gc = 0;
+       init_MUTEX(&fmc->gclock);
        fmc->c = c;
        fmc->head = 0;
        fmc->tail = 0;
        fmc->head_extra = 0;
        fmc->tail_extra = 0;
+       init_MUTEX(&fmc->wlock);
        return fmc;
 }
 
@@ -425,18 +415,18 @@ int
 jffs_add_node(struct jffs_node *node)
 {
        struct jffs_node_ref *ref;
-       struct jffs_fm *fm = node->fm;
-       int s = sizeof(struct jffs_node_ref);
 
        D3(printk("jffs_add_node(): ino = %u\n", node->ino));
 
-       if (!(ref = (struct jffs_node_ref *)kmalloc(s, GFP_KERNEL))) {
+       ref = (struct jffs_node_ref *)kmalloc(sizeof(struct jffs_node_ref),
+                                             GFP_KERNEL);
+       if (!ref)
                return -ENOMEM;
-       }
+
        DJM(no_jffs_node_ref++);
        ref->node = node;
-       ref->next = fm->nodes;
-       fm->nodes = ref;
+       ref->next = node->fm->nodes;
+       node->fm->nodes = ref;
        return 0;
 }
 
@@ -614,16 +604,16 @@ jffs_flash_erasable_size(struct mtd_info *mtd, __u32 offset, __u32 size)
         ssize = mtd->erasesize;
 
        if (offset % ssize) {
-               printk(KERN_WARNING "jffs_flash_erasable_size() given non-aligned offset %lx (erasesize %lx)\n", offset, ssize);
+               printk(KERN_WARNING "jffs_flash_erasable_size() given non-aligned offset %x (erasesize %lx)\n", offset, ssize);
                /* The offset is not sector size aligned.  */
                return -1;
        }
        else if (offset > mtd->size) {
-               printk(KERN_WARNING "jffs_flash_erasable_size given offset off the end of device (%lx > %lx)\n", offset, mtd->size);
+               printk(KERN_WARNING "jffs_flash_erasable_size given offset off the end of device (%x > %lx)\n", offset, mtd->size);
                return -2;
        }
        else if (offset + size > mtd->size) {
-               printk(KERN_WARNING "jffs_flash_erasable_size() given length which runs off the end of device (ofs %lx + len %lx = %lx, > %lx)\n", offset,size, offset+size, mtd->size);
+               printk(KERN_WARNING "jffs_flash_erasable_size() given length which runs off the end of device (ofs %x + len %x = %x, > %lx)\n", offset,size, offset+size, mtd->size);
                return -3;
        }
 
index 1461d788a78361e7fc489e2863559289efa04dad..82077d9d1ca6b94d3c5de96df77c93a33c81d21d 100644 (file)
@@ -10,7 +10,7 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * $Id: jffs_fm.h,v 1.3 2000/07/04 16:15:42 dwmw2 Exp $
+ * $Id: jffs_fm.h,v 1.7 2000/08/08 09:10:39 dwmw2 Exp $
  *
  * Ported to Linux 2.3.x and MTD:
  * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
@@ -23,6 +23,7 @@
 #include <linux/types.h>
 #include <linux/jffs.h>
 #include <linux/mtd/mtd.h>
+#include <linux/config.h>
 
 /* The alignment between two nodes in the flash memory.  */
 #define JFFS_ALIGN_SIZE 4
 /* Mark the on-flash space as obsolete when appropriate.  */
 #define JFFS_MARK_OBSOLETE 0
 
-#define CONFIG_JFFS_FS_VERBOSE 0
+#ifndef CONFIG_JFFS_FS_VERBOSE
+#define CONFIG_JFFS_FS_VERBOSE 1
+#endif
+
+#if CONFIG_JFFS_FS_VERBOSE > 0
+#define D(x) x
+#define D1(x) D(x)
+#else
+#define D(x)
+#define D1(x)
+#endif
+
+#if CONFIG_JFFS_FS_VERBOSE > 1
+#define D2(x) D(x)
+#else
+#define D2(x)
+#endif
+
+#if CONFIG_JFFS_FS_VERBOSE > 2
+#define D3(x) D(x)
+#else
+#define D3(x)
+#endif
+
+#define ASSERT(x) x
 
 /* How many padding bytes should be inserted between two chunks of data
    on the flash?  */
                                  - ((__u32)(size) % JFFS_ALIGN_SIZE)) \
                                  % JFFS_ALIGN_SIZE)
 
-/* Is there enough space on the flash?  */
-#define JFFS_ENOUGH_SPACE(fmc) (((fmc)->flash_size - (fmc)->used_size \
-                                - (fmc)->dirty_size) >= (fmc)->min_free_size)
-
-
 struct jffs_node_ref
 {
        struct jffs_node *node;
@@ -71,12 +91,13 @@ struct jffs_fmcontrol
                                 to perform garbage collections.  */
        __u32 max_chunk_size; /* The maximum size of a chunk of data.  */
        struct mtd_info *mtd;
-       __u32 no_call_gc;
+       struct semaphore gclock;
        struct jffs_control *c;
        struct jffs_fm *head;
        struct jffs_fm *tail;
        struct jffs_fm *head_extra;
        struct jffs_fm *tail_extra;
+       struct semaphore wlock;  
 };
 
 /* Notice the two members head_extra and tail_extra in the jffs_control
index 0e1ba2d77df43c5a4e20228cf648cdc5a1814774..fc13e8698b7758ee3442835af667d081cdcc4b2a 100644 (file)
@@ -1,11 +1,10 @@
 /*
  * linux/arch/arm/drivers/block/adfspart.c
  *
- * Copyright (c) 1996,1997 Russell King.
+ * Copyright (c) 1996-2000 Russell King.
  *
  * Scan ADFS partitions on hard disk drives.
  */
-
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/kdev_t.h>
@@ -30,17 +29,9 @@ adfspart_setgeometry(kdev_t dev, unsigned int secspertrack, unsigned int heads,
 #endif
 }
 
-#define LINUX_NATIVE_MAGIC 0xdeafa1de
-#define LINUX_SWAP_MAGIC   0xdeafab1e
-
-struct linux_part {
-       unsigned long magic;
-       unsigned long start_sect;
-       unsigned long nr_sects;
-};
-
-static struct adfs_discrecord *adfs_partition(struct gendisk *hd, char *name, char *data,
-                                          unsigned long first_sector, unsigned int minor)
+static struct adfs_discrecord *
+adfs_partition(struct gendisk *hd, char *name, char *data,
+              unsigned long first_sector, int minor)
 {
        struct adfs_discrecord *dr;
        unsigned int nr_sects;
@@ -63,8 +54,9 @@ static struct adfs_discrecord *adfs_partition(struct gendisk *hd, char *name, ch
 }
 
 #ifdef CONFIG_ACORN_PARTITION_RISCIX
-static int riscix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sect,
-                            unsigned int minor, unsigned long nr_sects)
+static int
+riscix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sect,
+                int minor, unsigned long nr_sects)
 {
        struct buffer_head *bh;
        struct riscix_record *rr;
@@ -76,7 +68,8 @@ static int riscix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_
        printk(" [RISCiX]");
 
        add_gd_partition(hd, riscix_minor = minor++, first_sect, nr_sects);
-       hd->sizes[riscix_minor] = hd->part[riscix_minor].nr_sects >> (BLOCK_SIZE_BITS - 9);
+       hd->sizes[riscix_minor] = hd->part[riscix_minor].nr_sects >>
+                                       (BLOCK_SIZE_BITS - 9);
        dev = MKDEV(hd->major, riscix_minor);
 
        if (!(bh = bread(dev, 0, 1024)))
@@ -109,8 +102,9 @@ static int riscix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_
 }
 #endif
 
-static int linux_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sect,
-                           unsigned int minor, unsigned long nr_sects)
+static int
+linux_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sect,
+               int minor, unsigned long nr_sects)
 {
        struct buffer_head *bh;
        struct linux_part *linuxp;
@@ -122,7 +116,8 @@ static int linux_partition(struct gendisk *hd, kdev_t dev, unsigned long first_s
        printk(" [Linux]");
 
        add_gd_partition(hd, linux_minor = minor++, first_sect, nr_sects);
-       hd->sizes[linux_minor] = hd->part[linux_minor].nr_sects >> (BLOCK_SIZE_BITS - 9);
+       hd->sizes[linux_minor] = hd->part[linux_minor].nr_sects >>
+                                       (BLOCK_SIZE_BITS - 9);
        dev = MKDEV(hd->major, linux_minor);
 
        if (!(bh = bread(dev, 0, 1024)))
@@ -151,8 +146,9 @@ static int linux_partition(struct gendisk *hd, kdev_t dev, unsigned long first_s
 }
 
 #ifdef CONFIG_ACORN_PARTITION_CUMANA
-static int adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
-                                 unsigned int minor)
+static int
+adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev,
+                     unsigned long first_sector, int minor)
 {
        unsigned int start_blk = 0, mask = (1 << hd->minor_shift) - 1;
        struct buffer_head *bh = NULL;
@@ -163,16 +159,17 @@ static int adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev, unsigned long f
                return 0;
 
        /*
-        * Try Cumana style partitions - sector 3 contains ADFS boot block with pointer
-        * to next 'drive'.
+        * Try Cumana style partitions - sector 3 contains ADFS boot block
+        * with pointer to next 'drive'.
         *
-        * There are unknowns in this code - is the 'cylinder number' of the next
-        * partition relative to the start of this one - I'm assuming it is.
+        * There are unknowns in this code - is the 'cylinder number' of the
+        * next partition relative to the start of this one - I'm assuming
+        * it is.
         *
         * Also, which ID did Cumana use?
         *
-        * This is totally unfinished, and will require more work to get it going.
-        * Hence it is totally untested.
+        * This is totally unfinished, and will require more work to get it
+        * going. Hence it is totally untested.
         */
        do {
                struct adfs_discrecord *dr;
@@ -184,7 +181,8 @@ static int adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev, unsigned long f
                if (!(bh = bread(dev, start_blk + 3, 1024)))
                        return -1;
 
-               dr = adfs_partition(hd, name, bh->b_data, first_sector, minor++);
+               dr = adfs_partition(hd, name, bh->b_data,
+                                   first_sector, minor++);
                if (!dr)
                        break;
                name = NULL;
@@ -206,13 +204,16 @@ static int adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev, unsigned long f
                        break;
 
 #ifdef CONFIG_ACORN_PARTITION_RISCIX
-               case PARTITION_RISCIX_SCSI: /* RiscIX - we don't know how to find the next one. */
-                       minor = riscix_partition(hd, dev, first_sector, minor, nr_sects);
+               case PARTITION_RISCIX_SCSI:
+                       /* RISCiX - we don't know how to find the next one. */
+                       minor = riscix_partition(hd, dev, first_sector,
+                                                minor, nr_sects);
                        break;
 #endif
 
                case PARTITION_LINUX:
-                       minor = linux_partition(hd, dev, first_sector, minor, nr_sects);
+                       minor = linux_partition(hd, dev, first_sector,
+                                               minor, nr_sects);
                        break;
                }
                brelse(bh);
@@ -221,7 +222,7 @@ static int adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev, unsigned long f
                        return minor;
        } while (1);
        if (bh)
-               brelse(bh);
+               bforget(bh);
        return first ? 0 : 1;
 }
 #endif
@@ -241,8 +242,9 @@ static int adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev, unsigned long f
  *         hda1 = ADFS partition on first drive.
  *         hda2 = non-ADFS partition.
  */
-static int adfspart_check_ADFS(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
-                               unsigned int minor)
+static int
+adfspart_check_ADFS(struct gendisk *hd, kdev_t dev,
+                  unsigned long first_sector, int minor)
 {
        unsigned long start_sect, nr_sects, sectscyl, heads;
        struct buffer_head *bh;
@@ -256,12 +258,13 @@ static int adfspart_check_ADFS(struct gendisk *hd, kdev_t dev, unsigned long fir
 
        dr = adfs_partition(hd, "ADFS", bh->b_data, first_sector, minor++);
        if (!dr) {
-               brelse(bh);
+               bforget(bh);
                return 0;
        }
 
        heads = dr->heads + ((dr->lowsector >> 6) & 1);
-       adfspart_setgeometry(dev, dr->secspertrack, heads, hd->part[MINOR(dev)].nr_sects);
+       adfspart_setgeometry(dev, dr->secspertrack, heads,
+                            hd->part[MINOR(dev)].nr_sects);
        sectscyl = dr->secspertrack * heads;
 
        /*
@@ -272,21 +275,19 @@ static int adfspart_check_ADFS(struct gendisk *hd, kdev_t dev, unsigned long fir
 
        if (start_sect) {
                first_sector += start_sect;
-               /*
-                * we now have a problem - how to set the origional disk size if the
-                * disk doesn't report it, since there is no standard way of getting
-                * that info.
-                */
+
                switch (bh->b_data[0x1fc] & 15) {
 #ifdef CONFIG_ACORN_PARTITION_RISCIX
                case PARTITION_RISCIX_SCSI:
                case PARTITION_RISCIX_MFM:
-                       minor = riscix_partition(hd, dev, first_sector, minor, nr_sects);
+                       minor = riscix_partition(hd, dev, first_sector,
+                                                minor, nr_sects);
                        break;
 #endif
 
                case PARTITION_LINUX:
-                       minor = linux_partition(hd, dev, first_sector, minor, nr_sects);
+                       minor = linux_partition(hd, dev, first_sector,
+                                               minor, nr_sects);
                        break;
                }
        }
@@ -326,13 +327,14 @@ static int adfspart_check_ICSLinux(kdev_t dev, unsigned long block)
  *         hda2 = ADFS partition 1 on first drive.
  *             ..etc..
  */
-static int adfspart_check_ICS(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
-                              unsigned int minor)
+static int
+adfspart_check_ICS(struct gendisk *hd, kdev_t dev,
+                  unsigned long first_sector, int minor)
 {
        struct buffer_head *bh;
        unsigned long sum;
        unsigned int i, mask = (1 << hd->minor_shift) - 1;
-       struct ics_part { unsigned long start; signed long size; } *p;
+       struct ics_part *p;
 
        if(get_ptable_blocksize(dev)!=1024)
                return 0;
@@ -349,9 +351,9 @@ static int adfspart_check_ICS(struct gendisk *hd, kdev_t dev, unsigned long firs
        for (i = 0, sum = 0x50617274; i < 508; i++)
                sum += bh->b_data[i];
 
-       sum -= le32_to_cpu(*(unsigned long *)(&bh->b_data[508]));
+       sum -= le32_to_cpu(*(__u32 *)(&bh->b_data[508]));
        if (sum) {
-               brelse(bh);
+               bforget(bh);
                return 0; /* not ICS partition table */
        }
 
@@ -392,15 +394,6 @@ static int adfspart_check_ICS(struct gendisk *hd, kdev_t dev, unsigned long firs
 #endif
 
 #ifdef CONFIG_ACORN_PARTITION_POWERTEC
-struct ptec_partition {
-       u32 unused1;
-       u32 unused2;
-       u32 start;
-       u32 size;
-       u32 unused5;
-       char type[8];
-};
-       
 /*
  * Purpose: allocate ICS partitions.
  * Params : hd         - pointer to gendisk structure to store partition info.
@@ -413,8 +406,9 @@ struct ptec_partition {
  *         hda2 = ADFS partition 1 on first drive.
  *             ..etc..
  */
-static int adfspart_check_POWERTEC(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
-                                  unsigned int minor)
+static int
+adfspart_check_POWERTEC(struct gendisk *hd, kdev_t dev,
+                       unsigned long first_sector, int minor)
 {
        struct buffer_head *bh;
        struct ptec_partition *p;
@@ -428,7 +422,7 @@ static int adfspart_check_POWERTEC(struct gendisk *hd, kdev_t dev, unsigned long
                checksum += bh->b_data[i];
 
        if (checksum != bh->b_data[511]) {
-               brelse(bh);
+               bforget(bh);
                return 0;
        }
 
@@ -452,44 +446,44 @@ static int adfspart_check_POWERTEC(struct gendisk *hd, kdev_t dev, unsigned long
 }
 #endif
 
+static int (*partfn[])(struct gendisk *, kdev_t, unsigned long, int) = {
+#ifdef CONFIG_ACORN_PARTITION_ICS
+       adfspart_check_ICS,
+#endif
+#ifdef CONFIG_ACORN_PARTITION_CUMANA
+       adfspart_check_CUMANA,
+#endif
+#ifdef CONFIG_ACORN_PARTITION_ADFS
+       adfspart_check_ADFS,
+#endif
+#ifdef CONFIG_ACORN_PARTITION_POWERTEC
+       adfspart_check_POWERTEC,
+#endif
+       NULL
+};
 /*
  * Purpose: initialise all the partitions on an ADFS drive.
- *          These may be other ADFS partitions or a Linux/RiscBSD/RiscIX
+ *          These may be other ADFS partitions or a Linux/RiscBSD/RISCiX
  *         partition.
  *
- * Params : hd          - pointer to gendisk structure to store devices partitions.
- *          dev                 - device number to access
- *         first_sector - first available sector on the disk.
- *         minor        - first available minor on this device.
+ * Params : hd         - pointer to gendisk structure
+ *          dev                - device number to access
+ *         first_sect  - first available sector on the disk.
+ *         first_minor - first available minor on this device.
  *
  * Returns: -1 on error, 0 if not ADFS format, 1 if ok.
  */
 int acorn_partition(struct gendisk *hd, kdev_t dev,
-                   unsigned long first_sector, int first_part_minor)
+                   unsigned long first_sect, int first_minor)
 {
-       int r = 0;
+       int r = 0, i;
 
-#ifdef CONFIG_ACORN_PARTITION_ICS
-       if (r == 0)
-               r = adfspart_check_ICS(hd, dev, first_sector, first_part_minor);
-#endif
-#ifdef CONFIG_ACORN_PARTITION_CUMANA
-       if (r == 0)    
-               r = adfspart_check_CUMANA(hd, dev, first_sector, first_part_minor);
-#endif
-#ifdef CONFIG_ACORN_PARTITION_ADFS
-       if (r == 0)
-               r = adfspart_check_ADFS(hd, dev, first_sector, first_part_minor);
-#endif
-#ifdef CONFIG_ACORN_PARTITION_POWERTEC
-       if (r == 0)
-               r = adfspart_check_POWERTEC(hd, dev, first_sector, first_part_minor);
-#endif
-       if (r < 0) {
-               if (warn_no_part)
-                       printk(" unable to read boot sectors / partition sectors\n");
-       } else if (r) {
+       for (i = 0; partfn[i] && r == 0; i++)
+               r = partfn[i](hd, dev, first_sect, first_minor);
+
+       if (r < 0 && warn_no_part)
+               printk(" unable to read boot sectors / partition sectors\n");
+       if (r > 0)
                printk("\n");
-       }
        return r;
 }
index 748c7c83f78c6d0a8a7107c50824ef7014207a91..e1d0a3830e8ba816cf908734487004e1a89969e8 100644 (file)
 #define PARTITION_LINUX                9
 
 struct riscix_part {
-       unsigned long  start;
-       unsigned long  length;
-       unsigned long  one;
+       __u32  start;
+       __u32  length;
+       __u32  one;
        char name[16];
 };
 
 struct riscix_record {
-       unsigned long  magic;
+       __u32  magic;
 #define RISCIX_MAGIC   (0x4a657320)
-       unsigned long  date;
+       __u32  date;
        struct riscix_part part[8];
 };
 
-int
-acorn_partition(struct gendisk *hd, kdev_t dev,
-               unsigned long first_sector, int first_part_minor);
+#define LINUX_NATIVE_MAGIC 0xdeafa1de
+#define LINUX_SWAP_MAGIC   0xdeafab1e
+
+struct linux_part {
+       __u32 magic;
+       __u32 start_sect;
+       __u32 nr_sects;
+};
+
+struct ics_part {
+       __u32 start;
+       __s32 size;
+};
+
+struct ptec_partition {
+       __u32 unused1;
+       __u32 unused2;
+       __u32 start;
+       __u32 size;
+       __u32 unused5;
+       char type[8];
+};
+       
+
+int acorn_partition(struct gendisk *hd, kdev_t dev,
+                  unsigned long first_sect, int first_minor);
 
index 62a72144f3db3678b867948732f4af5746b4b0f4..41afdcbd82a675199ef6c18b45a74ab61bda9314 100644 (file)
@@ -140,7 +140,8 @@ extern __inline__ int get_order(unsigned long size)
 
 #define __pa(x)                        ((unsigned long) (x) - PAGE_OFFSET)
 #define __va(x)                        ((void *)((unsigned long) (x) + PAGE_OFFSET))
-#define MAP_NR(addr)           (__pa(addr) >> PAGE_SHIFT)
+#define virt_to_page(kaddr)    (mem_map + (__pa(kaddr) >> PAGE_SHIFT))
+#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
 
 #endif /* __KERNEL__ */
 
index b7abea6f778ba7c84a3cf6c3ece85246a49dd76c..c721a1d55137fdef65db4c8afcef8b5919b67b93 100644 (file)
@@ -79,3 +79,5 @@ extern pg_data_t sa1100_node_data[];
                (((unsigned long)ADDR_TO_MAPBASE((kaddr)) - PAGE_OFFSET) / \
                sizeof(mem_map_t)))
 
+#define virt_to_page(kaddr)    (mem_map + MAP_NR(kaddr))
+#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
index 10f470048b673888bb5b4f6dfe684d09b6f871d1..4f24702a21b07343ad2cc43cbb7e18e24469a7a7 100644 (file)
@@ -92,6 +92,8 @@ extern __inline__ int get_order(unsigned long size)
 
 #ifndef CONFIG_DISCONTIGMEM
 #define MAP_NR(addr)           ((__pa(addr) - PHYS_OFFSET) >> PAGE_SHIFT)
+#define virt_to_page(kaddr)    (mem_map + ((__pa(kaddr) - PHYS_OFFSET) >> PAGE_SHIFT))
+#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
 #endif
 
 #endif
index 78d07c2073df8ee2ae47a2b51a89812be2be0660..7a070fa530a16f1f2ad1eb6c687a22fdc367570e 100644 (file)
@@ -116,8 +116,9 @@ extern __inline__ int get_order(unsigned long size)
 #define PAGE_OFFSET            ((unsigned long)__PAGE_OFFSET)
 #define __pa(x)                        ((unsigned long)(x)-PAGE_OFFSET)
 #define __va(x)                        ((void *)((unsigned long)(x)+PAGE_OFFSET))
-#define MAP_NR(addr)           (__pa(addr) >> PAGE_SHIFT)
-#define PHYSMAP_NR(addr)       ((unsigned long)(addr) >> PAGE_SHIFT)
+#define virt_to_page(kaddr)    (mem_map + (__pa(kaddr) >> PAGE_SHIFT))
+#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
+
 
 #endif /* __KERNEL__ */
 
index 445e42376df19ed228d15c7236c4aa3c38b246ae..f046dad8643b73a82977c10ad7bebe7dbdfed343 100644 (file)
@@ -82,7 +82,7 @@ typedef unsigned long pgprot_t;
 #  endif /* !STRICT_MM_TYPECHECKS */
 
 /*
- * Note: the MAP_NR() macro can't use __pa() because MAP_NR(X) MUST
+ * Note: the MAP_NR_*() macro can't use __pa() because MAP_NR_*(X) MUST
  * map to something >= max_mapnr if X is outside the identity mapped
  * kernel space.
  */
@@ -100,12 +100,13 @@ typedef unsigned long pgprot_t;
 #define MAP_NR_SN1(addr)       (((unsigned long) (addr) - PAGE_OFFSET) >> PAGE_SHIFT)
 
 #ifdef CONFIG_IA64_GENERIC
-# define MAP_NR(addr)  platform_map_nr(addr)
+# define virt_to_page(kaddr)   (mem_map + platform_map_nr(kaddr))
 #elif defined (CONFIG_IA64_SN_SN1_SIM)
-# define MAP_NR(addr)  MAP_NR_SN1(addr)
+# define virt_to_page(kaddr)   (mem_map + MAP_NR_SN1(kaddr))
 #else
-# define MAP_NR(addr)  MAP_NR_DENSE(addr)
+# define virt_to_page(kaddr)   (mem_map + MAP_NR_DENSE(kaddr))
 #endif
+#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
 
 # endif /* __KERNEL__ */
 
index 7cf002fb752843ce927a08ae30be2b1f63a557e5..80e5269a2448e6ca9158a6779c206c999e632f0a 100644 (file)
@@ -160,6 +160,8 @@ static inline void *__va(unsigned long x)
 #endif /* CONFIG_SUN3 */
 
 #define MAP_NR(addr)           (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
+#define virt_to_page(kaddr)    (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
+#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
 
 #ifndef CONFIG_SUN3
 #define BUG() do { \
index fd391fb85741f2324e076d8665968cceba28c3c0..124a6d14240a3e21bfd30397d79cd98ac147c18c 100644 (file)
@@ -75,7 +75,8 @@ extern __inline__ int get_order(unsigned long size)
 #define PAGE_OFFSET    0x80000000UL
 #define __pa(x)                ((unsigned long) (x) - PAGE_OFFSET)
 #define __va(x)                ((void *)((unsigned long) (x) + PAGE_OFFSET))
-#define MAP_NR(addr)   (__pa(addr) >> PAGE_SHIFT)
+#define virt_to_page(kaddr)    (mem_map + (__pa(kaddr) >> PAGE_SHIFT))
+#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
 
 #endif /* defined (__KERNEL__) */
 
index 2c6af1d755e4e8d242da57e678f1686e385311d4..7b06e7a91a57747af1f4193d7d10ca8bd7e4c49b 100644 (file)
@@ -73,7 +73,7 @@ extern plat_pg_data_t *plat_node_data[];
 #define LOCAL_MAP_NR(kvaddr) \
        (((unsigned long)(kvaddr)-LOCAL_BASE_ADDR((kvaddr))) >> PAGE_SHIFT)
 
-#define MAP_NR(kaddr)  (((unsigned long)(kaddr) > (unsigned long)high_memory)\
+#define MIPS64_NR(kaddr) (((unsigned long)(kaddr) > (unsigned long)high_memory)\
                ? (max_mapnr + 1) : (LOCAL_MAP_NR((kaddr)) + \
                (((unsigned long)ADDR_TO_MAPBASE((kaddr)) - PAGE_OFFSET) / \
                sizeof(mem_map_t))))
@@ -82,6 +82,9 @@ extern plat_pg_data_t *plat_node_data[];
        -1) ? 0 : (test_bit(LOCAL_MAP_NR((addr)), \
        NODE_DATA(KVADDR_TO_NID((unsigned long)addr))->valid_addr_bitmap)))
 
+#define virt_to_page(kaddr)    (mem_map + MIPS64_NR(kaddr))
+#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
+
 #endif /* CONFIG_DISCONTIGMEM */
 
 #endif /* _ASM_MMZONE_H_ */
index 16c45aac546ecd85ea638802336752d65d05f91e..47f7d79062535d51787ca8934302ff04ad26e3d4 100644 (file)
@@ -69,7 +69,8 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 #define __pa(x)                ((unsigned long) (x) - PAGE_OFFSET)
 #define __va(x)                ((void *)((unsigned long) (x) + PAGE_OFFSET))
 #ifndef CONFIG_DISCONTIGMEM
-#define MAP_NR(addr)   (__pa(addr) >> PAGE_SHIFT)
+#define virt_to_page(kaddr)    (mem_map + (__pa(kaddr) >> PAGE_SHIFT))
+#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
 #endif
 
 #endif /* defined (__KERNEL__) */
index a4f6b0a4bfb92f1e75aa2b79b25c39cdd4291d92..dee0ced3a0669e585b416327a955b5d53ce76008 100644 (file)
@@ -114,8 +114,9 @@ static inline void* ___va(unsigned long p)
 #define __pa(x) ___pa ((unsigned long)(x))
 #define __va(x) ___va ((unsigned long)(x))
 
-#define MAP_NR(addr)           (((unsigned long)addr-PAGE_OFFSET) >> PAGE_SHIFT)
 #define MAP_PAGE_RESERVED      (1<<15)
+#define virt_to_page(kaddr)    (mem_map + (((unsigned long)kaddr-PAGE_OFFSET) >> PAGE_SHIFT))
+#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
 
 extern unsigned long get_zero_page_fast(void);
 
index 49be624a9fb0bd9d4db15f9147c67ef640a34cdd..e259b2bff0933861864a4a73b139022be98b68cd 100644 (file)
@@ -112,8 +112,8 @@ typedef unsigned long pgprot_t;
 #define PAGE_OFFSET             ((unsigned long)__PAGE_OFFSET)
 #define __pa(x)                 ((unsigned long)(x)-PAGE_OFFSET)
 #define __va(x)                 ((void *)((unsigned long)(x)+PAGE_OFFSET))
-#define MAP_NR(addr)            (__pa(addr) >> PAGE_SHIFT)
-#define PHYSMAP_NR(addr)       ((unsigned long)(addr) >> PAGE_SHIFT)
+#define virt_to_page(kaddr)    (mem_map + (__pa(kaddr) >> PAGE_SHIFT))
+#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
 
 #endif                                 /* __KERNEL__                       */
 
index 99728234a1b44a04f5adfc5e90111e5395b15cda..ed5c57692e4d869effc25396b76f1d02244094a2 100644 (file)
 static void __init check_bugs(void)
 {
        extern unsigned long loops_per_sec;
+       char *p= &system_utsname.machine[2]; /* "sh" */
 
        cpu_data->loops_per_sec = loops_per_sec;
        
        switch (cpu_data->type) {
        case CPU_SH7708:
-               printk("CPU: SH7708/SH7709\n");
+               *p++ = '3';
+               printk("CPU: SH7707/SH7708/SH7709\n");
                break;
        case CPU_SH7729:
+               *p++ = '3';
                printk("CPU: SH7709A/SH7729\n");
                break;
        case CPU_SH7750:
+               *p++ = '4';
                printk("CPU: SH7750\n");
                break;
        default:
                printk("CPU: ??????\n");
                break;
        }
+
+#ifndef __LITTLE_ENDIAN__
+       /* 'eb' means 'Endian Big' */
+       *p++ = 'e';
+       *p++ = 'b';
+#endif
+       *p = '\0';
 }
 #endif /* __ASM_SH_BUGS_H */
index f8cb1d0bc5272583bcab9a566ab17bdc1d944eb5..7495d31c894ca16e44ebec25820e1514b2aa09b5 100644 (file)
@@ -33,7 +33,7 @@ extern __inline__ void __udelay(unsigned long usecs, unsigned long lps)
 #ifdef CONFIG_SMP
 #define __udelay_val cpu_data[smp_processor_id()].udelay_val
 #else
-#define __udelay_val loops_per_sec
+#define __udelay_val (current_cpu_data.loops_per_sec)
 #endif
 
 #define udelay(usecs) __udelay((usecs),__udelay_val)
index b5a7f0bea73b1ee36edc79d155dd548791a62aaa..f20096234ce9c062328e87e521b270137c9f0fcd 100644 (file)
 extern int request_dma(unsigned int dmanr, const char * device_id);    /* reserve a DMA channel */
 extern void free_dma(unsigned int dmanr);      /* release it again */
 
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy   (0)
+#endif
+
+
 #endif /* __ASM_SH_DMA_H */
index 1f5851fccb4da71fb35afe2d454068bb77ec0738..f4f49ff9cb93bdadbf60584aeecd21b945f542a8 100644 (file)
@@ -7,31 +7,38 @@
  */
 #include <linux/config.h>
 
-#define HD64461_CPTWAR 0x1030  
-#define HD64461_CPTWDR 0x1032
-#define HD64461_CPTRAR 0x1034  
-#define HD64461_CPTRDR 0x1036
+#define HD64461_STBCR  0x10000
+#define HD64461_SYSCR  0x10002
+#define HD64461_SCPUCR 0x10004
 
-#define HD64461_PCC0ISR         0x2000
-#define HD64461_PCC0GCR         0x2002
-#define HD64461_PCC0CSCR        0x2004
-#define HD64461_PCC0CSCIER      0x2006
-#define HD64461_PCC0SCR         0x2008
-#define HD64461_PCC1ISR         0x2010
-#define HD64461_PCC1GCR         0x2012
-#define HD64461_PCC1CSCR        0x2014
-#define HD64461_PCC1CSCIER      0x2016
-#define HD64461_PCC1SCR         0x2018
-#define HD64461_P0OCR           0x202a
-#define HD64461_P1OCR           0x202c
-#define HD64461_PGCR            0x202e
+#define HD64461_CPTWAR 0x11030 
+#define HD64461_CPTWDR 0x11032
+#define HD64461_CPTRAR 0x11034 
+#define HD64461_CPTRDR 0x11036
 
-#define HD64461_NIRR           0x5000
-#define HD64461_NIMR           0x5002
+#define HD64461_PCC0ISR         0x12000
+#define HD64461_PCC0GCR         0x12002
+#define HD64461_PCC0CSCR        0x12004
+#define HD64461_PCC0CSCIER      0x12006
+#define HD64461_PCC0SCR         0x12008
+#define HD64461_PCC1ISR         0x12010
+#define HD64461_PCC1GCR         0x12012
+#define HD64461_PCC1CSCR        0x12014
+#define HD64461_PCC1CSCIER      0x12016
+#define HD64461_PCC1SCR         0x12018
+#define HD64461_P0OCR           0x1202a
+#define HD64461_P1OCR           0x1202c
+#define HD64461_PGCR            0x1202e
+
+#define HD64461_NIRR           0x15000
+#define HD64461_NIMR           0x15002
 
 #ifndef CONFIG_HD64461_IOBASE
 #define CONFIG_HD64461_IOBASE  0xb0000000
 #endif
+#ifndef CONFIG_HD64461_IRQ
+#define CONFIG_HD64461_IRQ     36
+#endif
 
 #define HD64461_IRQBASE        64
 
index 1112ea36c21970dd125b0dba14ba3089cb2c15ce..25570cea253ede556532622d9dcc7d64f9d21074 100644 (file)
@@ -15,6 +15,7 @@
 #ifdef __KERNEL__
 
 #include <linux/config.h>
+#include <asm/machvec.h>
 
 #ifndef MAX_HWIFS
 #define MAX_HWIFS      1
 
 #define ide__sti()     __sti()
 
+static __inline__ int ide_default_irq_hp600(ide_ioreg_t base)
+{
+       switch (base) {
+               case 0x01f0: return 77;
+               case 0x0170: return 77;
+               default:
+                       return 0;
+       }
+}
+
 static __inline__ int ide_default_irq(ide_ioreg_t base)
 {
+       if (MACH_HP600) {
+               return ide_default_irq_hp600(base);
+       }
        switch (base) {
-#ifdef CONFIG_SH_HP600
-               case 0x201f0: return 77;
-               case 0x20170: return 77;
-#else
                case 0x01f0: return 14;
                case 0x0170: return 15;
-#endif
                default:
                        return 0;
        }
 }
 
-static __inline__ ide_ioreg_t ide_default_io_base(int index)
+static __inline__ ide_ioreg_t ide_default_io_base_hp600(int index)
 {
        switch (index) {
-#ifdef CONFIG_SH_HP600
                case 0: 
-                       return 0x201f0;
+                       return 0x01f0;
                case 1: 
-                       return 0x20170;
-#else
+                       return 0x0170;
+               default:
+                       return 0;
+       }
+}
+
+static __inline__ ide_ioreg_t ide_default_io_base(int index)
+{
+       if (MACH_HP600) {
+               return ide_default_io_base_hp600(index);
+       }
+       switch (index) {
                case 0: 
                        return 0x1f0;
                case 1: 
                        return 0x170;
-#endif
                default:
                        return 0;
        }
index 0d516620c71202e8f87b4b01549421131f17eb77..8c7d7f2695bf1505595ea7e7197cff9e13ab3aad 100644 (file)
  *    read{b,w,l}/write{b,w,l} are for PCI,
  *    while in{b,w,l}/out{b,w,l} are for ISA
  * These may (will) be platform specific function.
+ * In addition we have 'pausing' versions: in{b,w,l}_p/out{b,w,l}_p
+ * and 'string' versions: ins{b,w,l}/outs{b,w,l}
+ * For read{b,w,l} and write{b,w,l} there are also __raw versions, which
+ * do not have a memory barrier after them.
  *
  * In addition, we have 
  *   ctrl_in{b,w,l}/ctrl_out{b,w,l} for SuperH specific I/O.
  *   which are processor specific.
  */
 
+/*
+ * We follow the Alpha convention here:
+ *  __inb expands to an inline function call (which either calls via the
+ *        mach_vec if generic, or a machine specific implementation)
+ *  _inb  is a real function call (note ___raw fns are _ version of __raw)
+ *  inb   by default expands to _inb, but the machine specif code may
+ *        define it to __inb if it chooses.
+ */
+
 #include <asm/cache.h>
+#include <asm/system.h>
+#include <linux/config.h>
 
-#define inw_p  inw
-#define outw_p outw
+/*
+ * Depending on which platform we are running on, we need different
+ * I/O functions.
+ */
 
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
+#ifdef __KERNEL__
+#ifdef CONFIG_SH_GENERIC
+
+/* In a generic kernel, we always go through the machine vector.  */
+
+#include <asm/machvec.h>
+
+# define __inb(p)      sh_mv.mv_inb((p))
+# define __inw(p)      sh_mv.mv_inw((p))
+# define __inl(p)      sh_mv.mv_inl((p))
+# define __outb(x,p)   sh_mv.mv_outb((x),(p))
+# define __outw(x,p)   sh_mv.mv_outw((x),(p))
+# define __outl(x,p)   sh_mv.mv_outl((x),(p))
+
+# define __inb_p(p)    sh_mv.mv_inb_p((p))
+# define __inw_p(p)    sh_mv.mv_inw_p((p))
+# define __inl_p(p)    sh_mv.mv_inl_p((p))
+# define __outb_p(x,p) sh_mv.mv_outb_p((x),(p))
+# define __outw_p(x,p) sh_mv.mv_outw_p((x),(p))
+# define __outl_p(x,p) sh_mv.mv_outl_p((x),(p))
+
+#define __insb(p,b,c)  sh_mv.mv_insb((p), (b), (c))
+#define __insw(p,b,c)  sh_mv.mv_insw((p), (b), (c))
+#define __insl(p,b,c)  sh_mv.mv_insl((p), (b), (c))
+#define __outsb(p,b,c) sh_mv.mv_outsb((p), (b), (c))
+#define __outsw(p,b,c) sh_mv.mv_outsw((p), (b), (c))
+#define __outsl(p,b,c) sh_mv.mv_outsl((p), (b), (c))
+
+# define __readb(a)    sh_mv.mv_readb((a))
+# define __readw(a)    sh_mv.mv_readw((a))
+# define __readl(a)    sh_mv.mv_readl((a))
+# define __writeb(v,a) sh_mv.mv_writeb((v),(a))
+# define __writew(v,a) sh_mv.mv_writew((v),(a))
+# define __writel(v,a) sh_mv.mv_writel((v),(a))
+
+# define __ioremap(a,s)        sh_mv.mv_ioremap((a), (s))
+# define __ioremap_nocache(a,s)        sh_mv.mv_ioremap_nocache((a), (s))
+# define __iounmap(a)  sh_mv.mv_iounmap((a))
+
+# define __isa_port2addr(a)    sh_mv.mv_isa_port2addr(a)
+
+# define inb           __inb
+# define inw           __inw
+# define inl           __inl
+# define outb          __outb
+# define outw          __outw
+# define outl          __outl
+
+# define inb_p         __inb_p
+# define inw_p         __inw_p
+# define inl_p         __inl_p
+# define outb_p                __outb_p
+# define outw_p                __outw_p
+# define outl_p                __outl_p
+
+# define insb          __insb
+# define insw          __insw
+# define insl          __insl
+# define outsb         __outsb
+# define outsw         __outsw
+# define outsl         __outsl
+
+# define __raw_readb   __readb
+# define __raw_readw   __readw
+# define __raw_readl   __readl
+# define __raw_writeb  __writeb
+# define __raw_writew  __writew
+# define __raw_writel  __writel
+
+#else
+
+/* Control operations through platform specific headers */
+# define __WANT_IO_DEF
+
+# if defined(CONFIG_SH_HP600)
+#  include <asm/io_hd64461.h>
+# elif defined(CONFIG_SH_OVERDRIVE)
+#  include <asm/io_od.h>
+# elif defined(CONFIG_SH_SOLUTION_ENGINE)
+#  include <asm/io_se.h>
+# elif defined(CONFIG_SH_UNKNOWN)
+#  include <asm/io_unknown.h>
+# else
+#  error "What system is this?"
+#endif
+
+#undef __WANT_IO_DEF
+
+#endif /* GENERIC */
+#endif /* __KERNEL__ */
 
-extern __inline__ unsigned long readb(unsigned long addr)
-{
-       return *(volatile unsigned char*)addr;
-}
+/* These are always function calls, in both kernel and user space */
+extern unsigned int    _inb (unsigned long port);
+extern unsigned int    _inw (unsigned long port);
+extern unsigned int    _inl (unsigned long port);
+extern void            _outb (unsigned char b,unsigned long port);
+extern void            _outw (unsigned short w,unsigned long port);
+extern void            _outl (unsigned int l,unsigned long port);
+extern unsigned int    _inb_p (unsigned long port);
+extern unsigned int    _inw_p (unsigned long port);
+extern unsigned int    _inl_p (unsigned long port);
+extern void            _outb_p (unsigned char b,unsigned long port);
+extern void            _outw_p (unsigned short w,unsigned long port);
+extern void            _outl_p (unsigned int l,unsigned long port);
+extern void            _insb (unsigned long port, void *dst, unsigned long count);
+extern void            _insw (unsigned long port, void *dst, unsigned long count);
+extern void            _insl (unsigned long port, void *dst, unsigned long count);
+extern void            _outsb (unsigned long port, const void *src, unsigned long count);
+extern void            _outsw (unsigned long port, const void *src, unsigned long count);
+extern void            _outsl (unsigned long port, const void *src, unsigned long count);
+extern unsigned long   _readb(unsigned long addr);
+extern unsigned long   _readw(unsigned long addr);
+extern unsigned long   _readl(unsigned long addr);
+extern void            _writeb(unsigned char b, unsigned long addr);
+extern void            _writew(unsigned short b, unsigned long addr);
+extern void            _writel(unsigned int b, unsigned long addr);
 
-extern __inline__ unsigned long readw(unsigned long addr)
-{
-       return *(volatile unsigned short*)addr;
-}
+#ifdef __KERNEL__
+extern unsigned long   ___raw_readb(unsigned long addr);
+extern unsigned long   ___raw_readw(unsigned long addr);
+extern unsigned long   ___raw_readl(unsigned long addr);
+extern unsigned long   ___raw_readq(unsigned long addr);
+extern void            ___raw_writeb(unsigned char b, unsigned long addr);
+extern void            ___raw_writew(unsigned short b, unsigned long addr);
+extern void            ___raw_writel(unsigned int b, unsigned long addr);
+extern void            ___raw_writeq(unsigned long b, unsigned long addr);
+#endif
 
-extern __inline__ unsigned long readl(unsigned long addr)
-{
-       return *(volatile unsigned long*)addr;
-}
+#ifdef __KERNEL__
+/*
+ * The platform header files may define some of these macros to use
+ * the inlined versions where appropriate.  These macros may also be
+ * redefined by userlevel programs.
+ */
+#ifndef inb
+# define inb(p)                _inb(p)
+#endif
+#ifndef inw
+# define inw(p)                _inw(p)
+#endif
+#ifndef inl
+# define inl(p)                _inl(p)
+#endif
+
+#ifndef outb
+# define outb(b,p)     _outb((b),(p))
+#endif
+#ifndef outw
+# define outw(w,p)     _outw((w),(p))
+#endif
+#ifndef outl
+# define outl(l,p)     _outl((l),(p))
+#endif
+
+#ifndef inb_p
+# define inb_p         _inb_p
+#endif
+#ifndef inw_p
+# define inw_p         _inw_p
+#endif
+#ifndef inl_p
+# define inl_p         _inl_p
+#endif
+
+#ifndef outb_p
+# define outb_p                _outb_p
+#endif
+#ifndef outw_p
+# define outw_p                _outw_p
+#endif
+#ifndef outl_p
+# define outl_p                _outl_p
+#endif
+
+#ifndef insb
+# define insb(p,d,c)   _insb((p),(d),(c))
+#endif
+#ifndef insw
+# define insw(p,d,c)   _insw((p),(d),(c))
+#endif
+#ifndef insl
+# define insl(p,d,c)   _insl((p),(d),(c))
+#endif
+#ifndef outsb
+# define outsb(p,s,c)  _outsb((p),(s),(c))
+#endif
+#ifndef outsw
+# define outsw(p,s,c)  _outsw((p),(s),(c))
+#endif
+#ifndef outsl
+# define outsl(p,s,c)  _outsl((p),(s),(c))
+#endif
+
+#ifdef __raw_readb
+# define readb(a)      ({ unsigned long r_ = __raw_readb(a); mb(); r_; })
+#endif
+#ifdef __raw_readw
+# define readw(a)      ({ unsigned long r_ = __raw_readw(a); mb(); r_; })
+#endif
+#ifdef __raw_readl
+# define readl(a)      ({ unsigned long r_ = __raw_readl(a); mb(); r_; })
+#endif
+
+#ifdef __raw_writeb
+# define writeb(v,a)   ({ __raw_writeb((v),(a)); mb(); })
+#endif
+#ifdef __raw_writew
+# define writew(v,a)   ({ __raw_writew((v),(a)); mb(); })
+#endif
+#ifdef __raw_writel
+# define writel(v,a)   ({ __raw_writel((v),(a)); mb(); })
+#endif
+
+#ifndef __raw_readb
+# define __raw_readb(a)        ___raw_readb((unsigned long)(a))
+#endif
+#ifndef __raw_readw
+# define __raw_readw(a)        ___raw_readw((unsigned long)(a))
+#endif
+#ifndef __raw_readl
+# define __raw_readl(a)        ___raw_readl((unsigned long)(a))
+#endif
+
+#ifndef __raw_writeb
+# define __raw_writeb(v,a)  ___raw_writeb((v),(unsigned long)(a))
+#endif
+#ifndef __raw_writew
+# define __raw_writew(v,a)  ___raw_writew((v),(unsigned long)(a))
+#endif
+#ifndef __raw_writel
+# define __raw_writel(v,a)  ___raw_writel((v),(unsigned long)(a))
+#endif
+
+#ifndef readb
+# define readb(a)      _readb((unsigned long)(a))
+#endif
+#ifndef readw
+# define readw(a)      _readw((unsigned long)(a))
+#endif
+#ifndef readl
+# define readl(a)      _readl((unsigned long)(a))
+#endif
+
+#ifndef writeb
+# define writeb(v,a)   _writeb((v),(unsigned long)(a))
+#endif
+#ifndef writew
+# define writew(v,a)   _writew((v),(unsigned long)(a))
+#endif
+#ifndef writel
+# define writel(v,a)   _writel((v),(unsigned long)(a))
+#endif
+
+#else 
+
+/* Userspace declarations.  */
+
+extern unsigned int    inb(unsigned long port);
+extern unsigned int    inw(unsigned long port);
+extern unsigned int    inl(unsigned long port);
+extern void            outb(unsigned char b,unsigned long port);
+extern void            outw(unsigned short w,unsigned long port);
+extern void            outl(unsigned int l,unsigned long port);
+extern void            insb (unsigned long port, void *dst, unsigned long count);
+extern void            insw (unsigned long port, void *dst, unsigned long count);
+extern void            insl (unsigned long port, void *dst, unsigned long count);
+extern void            outsb (unsigned long port, const void *src, unsigned long count);
+extern void            outsw (unsigned long port, const void *src, unsigned long count);
+extern void            outsl (unsigned long port, const void *src, unsigned long count);
+extern unsigned long   readb(unsigned long addr);
+extern unsigned long   readw(unsigned long addr);
+extern unsigned long   readl(unsigned long addr);
+extern void            writeb(unsigned char b, unsigned long addr);
+extern void            writew(unsigned short b, unsigned long addr);
+extern void            writel(unsigned int b, unsigned long addr);
 
-extern __inline__ void writeb(unsigned char b, unsigned long addr)
-{
-       *(volatile unsigned char*)addr = b;
-}
+#endif /* __KERNEL__ */
 
-extern __inline__ void writew(unsigned short b, unsigned long addr)
-{
-       *(volatile unsigned short*)addr = b;
-}
+#ifdef __KERNEL__
 
-extern __inline__ void writel(unsigned int b, unsigned long addr)
+/*
+ * If the platform has PC-like I/O, this function converts the offset into
+ * an address.
+ */
+extern __inline__ unsigned long isa_port2addr(unsigned long offset)
 {
-        *(volatile unsigned long*)addr = b;
+       return __isa_port2addr(offset);
 }
 
-extern unsigned long inb(unsigned int port);
-extern unsigned long inb_p(unsigned int port);
-extern unsigned long inw(unsigned int port);
-extern unsigned long inl(unsigned int port);
-extern void insb(unsigned int port, void *addr, unsigned long count);
-extern void insw(unsigned int port, void *addr, unsigned long count);
-extern void insl(unsigned int port, void *addr, unsigned long count);
-
-extern void outb(unsigned long value, unsigned int port);
-extern void outb_p(unsigned long value, unsigned int port);
-extern void outw(unsigned long value, unsigned int port);
-extern void outl(unsigned long value, unsigned int port);
-extern void outsb(unsigned int port, const void *addr, unsigned long count);
-extern void outsw(unsigned int port, const void *addr, unsigned long count);
-extern void outsl(unsigned int port, const void *addr, unsigned long count);
-
-/*
- * If the platform has PC-like I/O, this function gives us the address
- * from the offset.
- */
-extern unsigned long sh_isa_slot(unsigned long offset);
-
-#define isa_readb(a) readb(sh_isa_slot(a))
-#define isa_readw(a) readw(sh_isa_slot(a))
-#define isa_readl(a) readl(sh_isa_slot(a))
-#define isa_writeb(b,a) writeb(b,sh_isa_slot(a))
-#define isa_writew(w,a) writew(w,sh_isa_slot(a))
-#define isa_writel(l,a) writel(l,sh_isa_slot(a))
+#define isa_readb(a) readb(isa_port2addr(a))
+#define isa_readw(a) readw(isa_port2addr(a))
+#define isa_readl(a) readl(isa_port2addr(a))
+#define isa_writeb(b,a) writeb(b,isa_port2addr(a))
+#define isa_writew(w,a) writew(w,isa_port2addr(a))
+#define isa_writel(l,a) writel(l,isa_port2addr(a))
 #define isa_memset_io(a,b,c) \
-  memset((void *)(sh_isa_slot((unsigned long)a)),(b),(c))
+  memset((void *)(isa_port2addr((unsigned long)a)),(b),(c))
 #define isa_memcpy_fromio(a,b,c) \
-  memcpy((a),(void *)(sh_isa_slot((unsigned long)(b))),(c))
+  memcpy((a),(void *)(isa_port2addr((unsigned long)(b))),(c))
 #define isa_memcpy_toio(a,b,c) \
-  memcpy((void *)(sh_isa_slot((unsigned long)(a))),(b),(c))
+  memcpy((void *)(isa_port2addr((unsigned long)(a))),(b),(c))
 
+/* We really want to try and get these to memcpy etc */
+extern void memcpy_fromio(void *, unsigned long, unsigned long);
+extern void memcpy_toio(unsigned long, const void *, unsigned long);
+extern void memset_io(unsigned long, int, unsigned long);
+
+/* SuperH on-chip I/O functions */
 extern __inline__ unsigned long ctrl_inb(unsigned long addr)
 {
        return *(volatile unsigned char*)addr;
@@ -115,8 +372,6 @@ extern __inline__ void ctrl_outl(unsigned int b, unsigned long addr)
         *(volatile unsigned long*)addr = b;
 }
 
-#ifdef __KERNEL__
-
 #define IO_SPACE_LIMIT 0xffffffff
 
 #include <asm/addrspace.h>
@@ -135,8 +390,8 @@ extern __inline__ void * phys_to_virt(unsigned long address)
        return (void *)P1SEGADDR(address);
 }
 
-extern void * ioremap(unsigned long phys_addr, unsigned long size);
-extern void iounmap(void *addr);
+#define virt_to_bus virt_to_phys
+#define bus_to_virt phys_to_virt
 
 /*
  * readX/writeX() are used to access memory mapped devices. On some
@@ -152,9 +407,9 @@ extern void iounmap(void *addr);
  * We cheat a bit and always return uncachable areas until we've fixed
  * the drivers to handle caching properly.  
  */
-extern __inline__ void * ioremap(unsigned long offset, unsigned long size)
+static __inline__ void * ioremap(unsigned long offset, unsigned long size)
 {
-       return (void *) P2SEGADDR(offset);
+       return __ioremap(offset, size);
 }
 
 /*
@@ -162,13 +417,14 @@ extern __inline__ void * ioremap(unsigned long offset, unsigned long size)
  * it's useful if some control registers are in such an area and write combining
  * or read caching is not desirable:
  */
-extern __inline__ void * ioremap_nocache (unsigned long offset, unsigned long size)
+static __inline__ void * ioremap_nocache (unsigned long offset, unsigned long size)
 {
-       return (void *) P2SEGADDR(offset);
+       return __ioremap_nocache(offset, size);
 }
 
-extern __inline__ void iounmap(void *addr)
+static __inline__ void iounmap(void *addr)
 {
+       return __iounmap(addr);
 }
 
 static __inline__ int check_signature(unsigned long io_addr,
diff --git a/include/asm-sh/io_generic.h b/include/asm-sh/io_generic.h
new file mode 100644 (file)
index 0000000..92d9019
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * include/asm-sh/io_generic.h
+ *
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Generic IO functions
+ */
+
+#ifndef _ASM_SH_IO_GENERIC_H
+#define _ASM_SH_IO_GENERIC_H
+
+extern unsigned long generic_io_base;
+
+extern unsigned long generic_inb(unsigned int port);
+extern unsigned long generic_inw(unsigned int port);
+extern unsigned long generic_inl(unsigned int port);
+
+extern void generic_outb(unsigned long value, unsigned int port);
+extern void generic_outw(unsigned long value, unsigned int port);
+extern void generic_outl(unsigned long value, unsigned int port);
+
+extern unsigned long generic_inb_p(unsigned int port);
+extern unsigned long generic_inw_p(unsigned int port);
+extern unsigned long generic_inl_p(unsigned int port);
+extern void generic_outb_p(unsigned long value, unsigned int port);
+extern void generic_outw_p(unsigned long value, unsigned int port);
+extern void generic_outl_p(unsigned long value, unsigned int port);
+
+extern void generic_insb(unsigned int port, void *addr, unsigned long count);
+extern void generic_insw(unsigned int port, void *addr, unsigned long count);
+extern void generic_insl(unsigned int port, void *addr, unsigned long count);
+extern void generic_outsb(unsigned int port, const void *addr, unsigned long count);
+extern void generic_outsw(unsigned int port, const void *addr, unsigned long count);
+extern void generic_outsl(unsigned int port, const void *addr, unsigned long count);
+
+extern unsigned long generic_readb(unsigned long addr);
+extern unsigned long generic_readw(unsigned long addr);
+extern unsigned long generic_readl(unsigned long addr);
+extern void generic_writeb(unsigned char b, unsigned long addr);
+extern void generic_writew(unsigned short b, unsigned long addr);
+extern void generic_writel(unsigned int b, unsigned long addr);
+
+extern void *generic_ioremap(unsigned long offset, unsigned long size);
+extern void *generic_ioremap_nocache (unsigned long offset, unsigned long size);
+extern void generic_iounmap(void *addr);
+
+extern unsigned long generic_isa_port2addr(unsigned long offset);
+
+#endif /* _ASM_SH_IO_GENERIC_H */
diff --git a/include/asm-sh/io_hd64461.h b/include/asm-sh/io_hd64461.h
new file mode 100644 (file)
index 0000000..2574a39
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * include/asm-sh/io_hd64461.h
+ *
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for an HD64461
+ */
+
+#ifndef _ASM_SH_IO_HD64461_H
+#define _ASM_SH_IO_HD64461_H
+
+#include <asm/io_generic.h>
+
+extern unsigned long hd64461_inb(unsigned int port);
+extern unsigned long hd64461_inw(unsigned int port);
+extern unsigned long hd64461_inl(unsigned int port);
+
+extern void hd64461_outb(unsigned long value, unsigned int port);
+extern void hd64461_outw(unsigned long value, unsigned int port);
+extern void hd64461_outl(unsigned long value, unsigned int port);
+
+extern unsigned long hd64461_inb_p(unsigned int port);
+extern void hd64461_outb_p(unsigned long value, unsigned int port);
+
+extern void hd64461_insb(unsigned int port, void *addr, unsigned long count);
+extern void hd64461_insw(unsigned int port, void *addr, unsigned long count);
+extern void hd64461_insl(unsigned int port, void *addr, unsigned long count);
+extern void hd64461_outsb(unsigned int port, const void *addr, unsigned long count);
+extern void hd64461_outsw(unsigned int port, const void *addr, unsigned long count);
+extern void hd64461_outsl(unsigned int port, const void *addr, unsigned long count);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb                 hd64461_inb
+# define __inw                 hd64461_inw
+# define __inl                 hd64461_inl
+# define __outb                        hd64461_outb
+# define __outw                        hd64461_outw
+# define __outl                        hd64461_outl
+
+# define __inb_p               hd64461_inb_p
+# define __inw_p               hd64461_inw
+# define __inl_p               hd64461_inl
+# define __outb_p              hd64461_outb_p
+# define __outw_p              hd64461_outw
+# define __outl_p              hd64461_outl
+
+# define __insb                        hd64461_insb
+# define __insw                        hd64461_insw
+# define __insl                        hd64461_insl
+# define __outsb               hd64461_outsb
+# define __outsw               hd64461_outsw
+# define __outsl               hd64461_outsl
+
+# define __readb               generic_readb
+# define __readw               generic_readw
+# define __readl               generic_readl
+# define __writeb              generic_writeb
+# define __writew              generic_writew
+# define __writel              generic_writel
+
+#endif
+
+#endif /* _ASM_SH_IO_HD64461_H */
diff --git a/include/asm-sh/io_od.h b/include/asm-sh/io_od.h
new file mode 100644 (file)
index 0000000..3a7e477
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * include/asm-sh/io_od.h
+ *
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for an STMicroelectronics Overdrive
+ */
+
+#ifndef _ASM_SH_IO_OD_H
+#define _ASM_SH_IO_OD_H
+
+#include <asm/io_generic.h>
+
+extern unsigned long od_inb(unsigned int port);
+extern unsigned long od_inw(unsigned int port);
+extern unsigned long od_inl(unsigned int port);
+
+extern void od_outb(unsigned long value, unsigned int port);
+extern void od_outw(unsigned long value, unsigned int port);
+extern void od_outl(unsigned long value, unsigned int port);
+
+extern unsigned long od_inb_p(unsigned int port);
+extern unsigned long od_inw_p(unsigned int port);
+extern unsigned long od_inl_p(unsigned int port);
+extern void od_outb_p(unsigned long value, unsigned int port);
+extern void od_outw_p(unsigned long value, unsigned int port);
+extern void od_outl_p(unsigned long value, unsigned int port);
+
+extern void od_insb(unsigned int port, void *addr, unsigned long count);
+extern void od_insw(unsigned int port, void *addr, unsigned long count);
+extern void od_insl(unsigned int port, void *addr, unsigned long count);
+extern void od_outsb(unsigned int port, const void *addr, unsigned long count);
+extern void od_outsw(unsigned int port, const void *addr, unsigned long count);
+extern void od_outsl(unsigned int port, const void *addr, unsigned long count);
+
+extern unsigned long od_isa_port2addr(unsigned long offset);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb                 od_inb
+# define __inw                 od_inw
+# define __inl                 od_inl
+# define __outb                        od_outb
+# define __outw                        od_outw
+# define __outl                        od_outl
+
+# define __inb_p               od_inb_p
+# define __inw_p               od_inw_p
+# define __inl_p               od_inl_p
+# define __outb_p              od_outb_p
+# define __outw_p              od_outw_p
+# define __outl_p              od_outl_p
+
+# define __insb                        od_insb
+# define __insw                        od_insw
+# define __insl                        od_insl
+# define __outsb               od_outsb
+# define __outsw               od_outsw
+# define __outsl               od_outsl
+
+# define __readb               generic_readb
+# define __readw               generic_readw
+# define __readl               generic_readl
+# define __writeb              generic_writeb
+# define __writew              generic_writew
+# define __writel              generic_writel
+
+# define __isa_port2addr       od_isa_port2addr
+# define __ioremap             generic_ioremap
+# define __ioremap_nocache     generic_ioremap_nocache
+# define __iounmap             generic_iounmap
+
+#endif
+
+#endif /* _ASM_SH_IO_OD_H */
diff --git a/include/asm-sh/io_se.h b/include/asm-sh/io_se.h
new file mode 100644 (file)
index 0000000..d97457d
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * include/asm-sh/io_se.h
+ *
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for an Hitachi SolutionEngine
+ */
+
+#ifndef _ASM_SH_IO_SE_H
+#define _ASM_SH_IO_SE_H
+
+#include <asm/io_generic.h>
+
+extern unsigned long se_inb(unsigned int port);
+extern unsigned long se_inw(unsigned int port);
+extern unsigned long se_inl(unsigned int port);
+
+extern void se_outb(unsigned long value, unsigned int port);
+extern void se_outw(unsigned long value, unsigned int port);
+extern void se_outl(unsigned long value, unsigned int port);
+
+extern unsigned long se_inb_p(unsigned int port);
+extern void se_outb_p(unsigned long value, unsigned int port);
+
+extern void se_insb(unsigned int port, void *addr, unsigned long count);
+extern void se_insw(unsigned int port, void *addr, unsigned long count);
+extern void se_insl(unsigned int port, void *addr, unsigned long count);
+extern void se_outsb(unsigned int port, const void *addr, unsigned long count);
+extern void se_outsw(unsigned int port, const void *addr, unsigned long count);
+extern void se_outsl(unsigned int port, const void *addr, unsigned long count);
+
+extern unsigned long se_readb(unsigned long addr);
+extern unsigned long se_readw(unsigned long addr);
+extern unsigned long se_readl(unsigned long addr);
+extern void se_writeb(unsigned char b, unsigned long addr);
+extern void se_writew(unsigned short b, unsigned long addr);
+extern void se_writel(unsigned int b, unsigned long addr);
+
+extern unsigned long se_isa_port2addr(unsigned long offset);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb                 se_inb
+# define __inw                 se_inw
+# define __inl                 se_inl
+# define __outb                        se_outb
+# define __outw                        se_outw
+# define __outl                        se_outl
+
+# define __inb_p               se_inb_p
+# define __inw_p               se_inw
+# define __inl_p               se_inl
+# define __outb_p              se_outb_p
+# define __outw_p              se_outw
+# define __outl_p              se_outl
+
+# define __insb                        se_insb
+# define __insw                        se_insw
+# define __insl                        se_insl
+# define __outsb               se_outsb
+# define __outsw               se_outsw
+# define __outsl               se_outsl
+
+# define __readb               se_readb
+# define __readw               se_readw
+# define __readl               se_readl
+# define __writeb              se_writeb
+# define __writew              se_writew
+# define __writel              se_writel
+
+# define __isa_port2addr       se_isa_port2addr
+# define __ioremap             generic_ioremap
+# define __ioremap_nocache     generic_ioremap_nocache
+# define __iounmap             generic_iounmap
+
+#endif
+
+#endif /* _ASM_SH_IO_SE_H */
diff --git a/include/asm-sh/io_unknown.h b/include/asm-sh/io_unknown.h
new file mode 100644 (file)
index 0000000..b638f2b
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * include/asm-sh/io_unknown.h
+ *
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for use when we don't know what machine we are on
+ */
+
+#ifndef _ASM_SH_IO_UNKNOWN_H
+#define _ASM_SH_IO_UNKNOWN_H
+
+extern unsigned long unknown_inb(unsigned int port);
+extern unsigned long unknown_inw(unsigned int port);
+extern unsigned long unknown_inl(unsigned int port);
+
+extern void unknown_outb(unsigned long value, unsigned int port);
+extern void unknown_outw(unsigned long value, unsigned int port);
+extern void unknown_outl(unsigned long value, unsigned int port);
+
+extern unsigned long unknown_inb_p(unsigned int port);
+extern unsigned long unknown_inw_p(unsigned int port);
+extern unsigned long unknown_inl_p(unsigned int port);
+extern void unknown_outb_p(unsigned long value, unsigned int port);
+extern void unknown_outw_p(unsigned long value, unsigned int port);
+extern void unknown_outl_p(unsigned long value, unsigned int port);
+
+extern void unknown_insb(unsigned int port, void *addr, unsigned long count);
+extern void unknown_insw(unsigned int port, void *addr, unsigned long count);
+extern void unknown_insl(unsigned int port, void *addr, unsigned long count);
+extern void unknown_outsb(unsigned int port, const void *addr, unsigned long count);
+extern void unknown_outsw(unsigned int port, const void *addr, unsigned long count);
+extern void unknown_outsl(unsigned int port, const void *addr, unsigned long count);
+
+extern unsigned long unknown_readb(unsigned long addr);
+extern unsigned long unknown_readw(unsigned long addr);
+extern unsigned long unknown_readl(unsigned long addr);
+extern void unknown_writeb(unsigned char b, unsigned long addr);
+extern void unknown_writew(unsigned short b, unsigned long addr);
+extern void unknown_writel(unsigned int b, unsigned long addr);
+
+extern unsigned long unknown_isa_port2addr(unsigned long offset);
+extern void * unknown_ioremap(unsigned long offset, unsigned long size);
+extern void * unknown_ioremap_nocache (unsigned long offset, unsigned long size);
+extern void unknown_iounmap(void *addr);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb                 unknown_inb
+# define __inw                 unknown_inw
+# define __inl                 unknown_inl
+# define __outb                        unknown_outb
+# define __outw                        unknown_outw
+# define __outl                        unknown_outl
+
+# define __inb_p               unknown_inb_p
+# define __inw_p               unknown_inw_p
+# define __inl_p               unknown_inl_p
+# define __outb_p              unknown_outb_p
+# define __outw_p              unknown_outw_p
+# define __outl_p              unknown_outl_p
+
+# define __insb                        unknown_insb
+# define __insw                        unknown_insw
+# define __insl                        unknown_insl
+# define __outsb               unknown_outsb
+# define __outsw               unknown_outsw
+# define __outsl               unknown_outsl
+
+# define __readb               unknown_readb
+# define __readw               unknown_readw
+# define __readl               unknown_readl
+# define __writeb              unknown_writeb
+# define __writew              unknown_writew
+# define __writel              unknown_writel
+
+# define __isa_port2addr       unknown_isa_port2addr
+# define __ioremap             unknown_ioremap
+# define __ioremap_nocache     unknown_ioremap_nocache
+# define __iounmap             unknown_iounmap
+
+#endif
+
+#endif /* _ASM_SH_IO_UNKNOWN_H */
index 951ad2e9f6681adb33d4814325234738b857fb99..48016e3f958aeef32c7d25e7ab724385f053ea37 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/config.h>
+#include <asm/machvec.h>
 
 #if defined(__sh3__)
 #define INTC_IPRA      0xfffffee2UL
 #define RTC_IPR_POS     0
 #define RTC_PRIORITY   TIMER_PRIORITY
 
+#define SCI_ERI_IRQ    23
+#define SCI_RXI_IRQ    24
+#define SCI_TXI_IRQ    25
+#define SCI_IPR_ADDR   INTC_IPRB
+#define SCI_IPR_POS    1
+#define SCI_PRIORITY   3
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
+#define SCIF_ERI_IRQ   56
+#define SCIF_RXI_IRQ   57
+#define SCIF_TXI_IRQ   59
+#define SCIF_IPR_ADDR  INTC_IPRE
+#define SCIF_IPR_POS   1
+#define SCIF_PRIORITY  3
+
+#define IRDA_ERI_IRQ   52
+#define IRDA_RXI_IRQ   53
+#define IRDA_TXI_IRQ   55
+#define IRDA_IPR_ADDR  INTC_IPRE
+#define IRDA_IPR_POS   2
+#define IRDA_PRIORITY  3
+#elif defined(CONFIG_CPU_SUBTYPE_SH7750)
+#define SCIF_ERI_IRQ   40
+#define SCIF_RXI_IRQ   41
+#define SCIF_TXI_IRQ   43
+#define SCIF_IPR_ADDR  INTC_IPRC
+#define SCIF_IPR_POS   1
+#define SCIF_PRIORITY  3
+#endif
+
+#ifdef CONFIG_SH_GENERIC
+/* In a generic kernel, NR_IRQS is an upper bound, and we should use
+ * ACTUAL_NR_IRQS (which uses the machine vector) to get the correct value.
+ */
+#define NR_IRQS 80
+#define ACTUAL_NR_IRQS (sh_mv.mv_nr_irqs)
+#else
 #if defined(__SH4__)
 /*
  * 48 = 32+16
@@ -40,6 +78,8 @@
  *
  */
 #define NR_IRQS        48
+#elif defined(CONFIG_CPU_SUBTYPE_SH7707)
+#define NR_IRQS 64
 #elif defined(CONFIG_CPU_SUBTYPE_SH7708)
 #define NR_IRQS 32
 #elif defined(CONFIG_CPU_SUBTYPE_SH7709)
@@ -49,6 +89,8 @@
 #define NR_IRQS 61
 #endif
 #endif
+#define ACTUAL_NR_IRQS NR_IRQS
+#endif
 
 extern void disable_irq(unsigned int);
 extern void disable_irq_nosync(unsigned int);
@@ -57,12 +99,11 @@ extern void enable_irq(unsigned int);
 /*
  * Function for "on chip support modules".
  */
-extern void set_ipr_data(unsigned int irq, unsigned int addr,
+extern void make_ipr_irq(unsigned int irq, unsigned int addr,
                         int pos,  int priority);
-extern void make_ipr_irq(unsigned int irq);
 extern void make_imask_irq(unsigned int irq);
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7709)
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
 #define INTC_IRR0      0xa4000004UL
 #define INTC_IRR1      0xa4000006UL
 #define INTC_IRR2      0xa4000008UL
@@ -75,6 +116,9 @@ extern void make_imask_irq(unsigned int irq);
 #define INTC_IPRC      0xa4000016UL
 #define INTC_IPRD      0xa4000018UL
 #define INTC_IPRE      0xa400001aUL
+#if defined(CONFIG_CPU_SUBTYPE_SH7707)
+#define INTC_IPRF      0xa400001cUL
+#endif
 
 #define IRQ0_IRQ       32
 #define IRQ1_IRQ       33
@@ -105,4 +149,19 @@ extern void make_imask_irq(unsigned int irq);
 #define IRQ5_PRIORITY  1
 #endif
 
+extern int hd64461_irq_demux(int irq);
+
+#ifdef CONFIG_SH_GENERIC
+extern __inline__ int irq_demux(int irq) {
+       if (sh_mv.mv_irq_demux) {
+               irq = sh_mv.mv_irq_demux(irq);
+       }
+       return irq;
+}
+#elif defined(CONFIG_HD64461)
+#define irq_demux(irq) hd64461_irq_demux(irq)
+#else
+#define irq_demux(irq) irq
+#endif
+
 #endif /* __ASM_SH_IRQ_H */
index 9a64c5113c449dde76fd6b1eb9be9e24ba13f1ed..f1b8eb142d0d9a881da7e9d7916707643ebc3419 100644 (file)
@@ -3,7 +3,8 @@
 /*
  *     $Id: keyboard.h,v 1.1 2000/06/10 21:45:48 yaegashi Exp $
  */
-#include <linux/config.h>
+
+#include <asm/machvec.h>
 
 static __inline__ int kbd_setkeycode(unsigned int scancode,
                                     unsigned int keycode)
@@ -32,13 +33,13 @@ static __inline__ void kbd_leds(unsigned char leds)
 {
 }
 
-#ifdef CONFIG_SH_HP600
-void __init hp600_kbd_init_hw(void);
-#define kbd_init_hw hp600_kbd_init_hw
-#else
+extern void hp600_kbd_init_hw(void);
+
 static __inline__ void kbd_init_hw(void)
 {
+       if (MACH_HP600) {
+               hp600_kbd_init_hw();
+       }
 }
-#endif
 
 #endif
diff --git a/include/asm-sh/machvec.h b/include/asm-sh/machvec.h
new file mode 100644 (file)
index 0000000..918bf96
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * include/asm-sh/machvec.h
+ *
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ */
+
+#ifndef _ASM_SH_MACHVEC_H
+#define _ASM_SH_MACHVEC_H 1
+
+#include <linux/config.h>
+#include <linux/types.h>
+
+struct sh_machine_vector
+{
+       const char *mv_name;
+
+       int mv_nr_irqs;
+
+       unsigned long (*mv_inb)(unsigned int);
+       unsigned long (*mv_inw)(unsigned int);
+       unsigned long (*mv_inl)(unsigned int);
+       void (*mv_outb)(unsigned long, unsigned int);
+       void (*mv_outw)(unsigned long, unsigned int);
+       void (*mv_outl)(unsigned long, unsigned int);
+
+       unsigned long (*mv_inb_p)(unsigned int);
+       unsigned long (*mv_inw_p)(unsigned int);
+       unsigned long (*mv_inl_p)(unsigned int);
+       void (*mv_outb_p)(unsigned long, unsigned int);
+       void (*mv_outw_p)(unsigned long, unsigned int);
+       void (*mv_outl_p)(unsigned long, unsigned int);
+
+       void (*mv_insb)(unsigned int port, void *addr, unsigned long count);
+       void (*mv_insw)(unsigned int port, void *addr, unsigned long count);
+       void (*mv_insl)(unsigned int port, void *addr, unsigned long count);
+       void (*mv_outsb)(unsigned int port, const void *addr, unsigned long count);
+       void (*mv_outsw)(unsigned int port, const void *addr, unsigned long count);
+       void (*mv_outsl)(unsigned int port, const void *addr, unsigned long count);
+       
+       unsigned long (*mv_readb)(unsigned long);
+       unsigned long (*mv_readw)(unsigned long);
+       unsigned long (*mv_readl)(unsigned long);
+       void (*mv_writeb)(unsigned char, unsigned long);
+       void (*mv_writew)(unsigned short, unsigned long);
+       void (*mv_writel)(unsigned int, unsigned long);
+
+       void* (*mv_ioremap)(unsigned long offset, unsigned long size);
+       void* (*mv_ioremap_nocache)(unsigned long offset, unsigned long size);
+       void (*mv_iounmap)(void *addr);
+
+       unsigned long (*mv_port2addr)(unsigned long offset);
+       unsigned long (*mv_isa_port2addr)(unsigned long offset);
+
+       int (*mv_irq_demux)(int irq);
+
+       void (*mv_init_arch)(void);
+       void (*mv_init_irq)(void);
+       void (*mv_init_pci)(void);
+       void (*mv_kill_arch)(int);
+
+       void (*mv_heartbeat)(void);
+
+       unsigned int mv_hw_se : 1;
+       unsigned int mv_hw_hp600 : 1;
+       unsigned int mv_hw_hd64461 : 1;
+};
+
+extern struct sh_machine_vector sh_mv;
+
+/* Machine check macros */
+#ifdef CONFIG_SH_GENERIC
+#define MACH_SE                (sh_mv.mv_hw_se)
+#define MACH_HP600     (sh_mv.mv_hw_hp600)
+#define MACH_HD64461   (sh_mv.mv_hw_hd64461)
+#else
+# ifdef CONFIG_SH_SOLUTION_ENGINE
+#  define MACH_SE              1
+# else
+#  define MACH_SE              0
+# endif
+# ifdef CONFIG_SH_HP600
+#  define MACH_HP600           1
+# else
+#  define MACH_HP600           0
+# endif
+# ifdef CONFIG_HD64461
+#  define MACH_HD64461         1
+# else
+#  define MACH_HD64461         0
+# endif
+#endif
+
+#endif /* _ASM_SH_MACHVEC_H */
diff --git a/include/asm-sh/machvec_init.h b/include/asm-sh/machvec_init.h
new file mode 100644 (file)
index 0000000..3e82b3f
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * include/asm-sh/machvec_init.h
+ *
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * This file has goodies to help simplify instantiation of machine vectors.
+ */
+
+#ifndef __SH_MACHVEC_INIT_H
+#define __SH_MACHVEC_INIT_H
+
+/*
+ * In a GENERIC kernel, we have lots of these vectors floating about,
+ * all but one of which we want to go away.  In a non-GENERIC kernel,
+ * we want only one, ever.
+ *
+ * Accomplish this in the GENERIC kernel by puting all of the vectors
+ * in the .init.data section where they'll go away.  We'll copy the
+ * one we want to the real alpha_mv vector in setup_arch.
+ *
+ * Accomplish this in a non-GENERIC kernel by ifdef'ing out all but
+ * one of the vectors, which will not reside in .init.data.  We then
+ * alias this one vector to alpha_mv, so no copy is needed.
+ *
+ * Upshot: set __initdata to nothing for non-GENERIC kernels.
+ *
+ * Note we do the same thing for the UNKNOWN kernel, as we need to write
+ * to the machine vector while setting it up.
+ */
+
+#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
+#define __initmv __attribute__((unused,__section__ (".machvec.init")))
+#define ALIAS_MV(x)
+#else
+#define __initmv
+
+/* GCC actually has a syntax for defining aliases, but is under some
+   delusion that you shouldn't be able to declare it extern somewhere
+   else beforehand.  Fine.  We'll do it ourselves.  */
+#if 0
+#define ALIAS_MV(system) \
+  struct sh_machine_vector sh_mv __attribute__((alias("mv_"#system)));
+#else
+#define ALIAS_MV(system) \
+  asm(".global sh_mv\nsh_mv = mv_"#system );
+#endif
+#endif /* GENERIC */
+
+#endif /* __SH_MACHVEC_INIT_H */
index 0f48339b273814936e522a08a51f88882c042892..82517a5af3abb5eecfedee2a726b89f4306015c5 100644 (file)
@@ -164,15 +164,15 @@ extern __inline__ void switch_mm(struct mm_struct *prev,
                                 struct mm_struct *next,
                                 struct task_struct *tsk, unsigned int cpu)
 {
-       set_bit(cpu, &next->cpu_vm_mask);
        if (prev != next) {
                unsigned long __pgdir = (unsigned long)next->pgd;
 
+               clear_bit(cpu, &prev->cpu_vm_mask);
+               set_bit(cpu, &next->cpu_vm_mask);
                __asm__ __volatile__("mov.l     %0, %1"
                                     : /* no output */
                                     : "r" (__pgdir), "m" (__m(MMU_TTB)));
                activate_context(next);
-               clear_bit(cpu, &prev->cpu_vm_mask);
        }
 }
 
index 1348466a9383af239fa8ecf18c764e6abf00e714..dcac85fa6a8d529977579c23180bbc977df50a77 100644 (file)
@@ -65,7 +65,8 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 #define PAGE_OFFSET            (0x80000000)
 #define __pa(x)                        ((unsigned long)(x)-PAGE_OFFSET)
 #define __va(x)                        ((void *)((unsigned long)(x)+PAGE_OFFSET))
-#define MAP_NR(addr)           ((__pa(addr)-__MEMORY_START) >> PAGE_SHIFT)
+#define virt_to_page(kaddr)    (mem_map + ((__pa(kaddr)-__MEMORY_START) >> PAGE_SHIFT))
+#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
 
 #ifndef __ASSEMBLY__
 
index 34398480a5cf10e4b74fac8bf70331462fdc02d2..2c3ce9038ed5bc553ff950ed73f296866f7c96e5 100644 (file)
@@ -9,6 +9,15 @@
 
 #define pcibios_assign_all_busses()    0
 
+/* These are currently the correct values for the STM overdrive board. 
+ * We need some way of setting this on a board specific way, it will 
+ * not be the same on other boards I think
+ */
+#if 1 /* def CONFIG_SH_OVERDRIVE */
+#define PCIBIOS_MIN_IO         0x2000
+#define PCIBIOS_MIN_MEM                0x10000000
+#endif
+
 extern inline void pcibios_set_master(struct pci_dev *dev)
 {
        /* No special bus mastering setup handling */
@@ -59,7 +68,7 @@ extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
  * until either pci_unmap_single or pci_dma_sync_single is performed.
  */
 extern inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
-                                       size_t size)
+                                       size_t size,int directoin)
 {
        return virt_to_bus(ptr);
 }
@@ -72,7 +81,7 @@ extern inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
  * whatever the device wrote there.
  */
 extern inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
-                                   size_t size)
+                                   size_t size,int direction)
 {
        /* Nothing to do */
 }
@@ -93,7 +102,7 @@ extern inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
  * the same here.
  */
 extern inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-                            int nents)
+                            int nents,int direction)
 {
        return nents;
 }
@@ -103,7 +112,7 @@ extern inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
  * pci_unmap_single() above.
  */
 extern inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-                               int nents)
+                               int nents,int direction)
 {
        /* Nothing to do */
 }
@@ -119,7 +128,7 @@ extern inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
  */
 extern inline void pci_dma_sync_single(struct pci_dev *hwdev,
                                       dma_addr_t dma_handle,
-                                      size_t size)
+                                      size_t size,int direction)
 {
        /* Nothing to do */
 }
@@ -132,7 +141,7 @@ extern inline void pci_dma_sync_single(struct pci_dev *hwdev,
  */
 extern inline void pci_dma_sync_sg(struct pci_dev *hwdev,
                                   struct scatterlist *sg,
-                                  int nelems)
+                                  int nelems,int direction)
 {
        /* Nothing to do */
 }
index 867cf06acbf5abbb8e7ef88851b84dbbfa5d212c..df3e8edf2b8e5c543fe656d8a745da0ea0429e49 100644 (file)
@@ -23,6 +23,7 @@ extern void paging_init(void);
  *  - flush_cache_page(mm, vmaddr) flushes a single page
  *  - flush_cache_range(mm, start, end) flushes a range of pages
  *
+ *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
  *  - flush_page_to_ram(page) write back kernel page to ram
  *  - flush_icache_range(start, end) flushes(invalidates) a range for icache
  *  - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
@@ -48,6 +49,7 @@ extern void flush_cache_range(struct mm_struct *mm, unsigned long start,
                              unsigned long end);
 extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr);
 extern void flush_page_to_ram(struct page *page);
+extern void flush_dcache_page(struct page *pg);
 extern void flush_icache_range(unsigned long start, unsigned long end);
 extern void flush_icache_page(struct vm_area_struct *vma, struct page *pg);
 #endif
@@ -99,6 +101,9 @@ extern unsigned long empty_zero_page[1024];
 #define _PAGE_USER     0x040  /* PR1-bit : user space access allowed */
 #define _PAGE_PROTNONE 0x080  /* software: if not present */
 /*                     0x100     V-bit   : page is valid */
+/*                     0x200     can be used as software flag */
+/*                     0x400     can be used as software flag */
+/*                     0x800     can be used as software flag */
 
 #if defined(__sh3__)
 /* Mask which drop software flags */
index 77cbe9c1ee884fbce9926d5b8d074378e927233e..38d8dbe7c9eca14fadd06341f4f74e0017495224 100644 (file)
@@ -21,7 +21,7 @@
  *  CPU type and hardware bug flags. Kept separately for each CPU.
  */
 enum cpu_type {
-       CPU_SH7708,             /* Represents 7708, 7708S, 7708R, 7709 */
+       CPU_SH7708,             /* Represents 7707, 7708, 7708S, 7708R, 7709 */
        CPU_SH7729,             /* Represents 7709A, 7729 */
        CPU_SH7750,
        CPU_SH_NONE
index c727c06d8a9e358b69b7a7917f6219b0a3d1c58a..47022fbba04c09ccf1ee6f73713b68ef23ba833b 100644 (file)
@@ -177,7 +177,8 @@ extern __inline__ int get_order(unsigned long size)
 #define PAGE_OFFSET    0xf0000000
 #define __pa(x)                 ((unsigned long)(x) - PAGE_OFFSET)
 #define __va(x)                 ((void *)((unsigned long) (x) + PAGE_OFFSET))
-#define MAP_NR(addr)            (__pa(addr) >> PAGE_SHIFT)
+#define virt_to_page(kaddr)    (mem_map + (__pa(kaddr) >> PAGE_SHIFT))
+#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
 
 #endif /* __KERNEL__ */
 
index 5fc50713292b772bf83dc0eb3218bb637f02b0f9..2debbf0849658ffee4562d67d21d6eaffb08584f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.99 2000/08/05 13:30:34 davem Exp $ */
+/* $Id: pgtable.h,v 1.101 2000/08/09 00:00:17 davem Exp $ */
 #ifndef _SPARC_PGTABLE_H
 #define _SPARC_PGTABLE_H
 
@@ -147,9 +147,6 @@ extern pte_t pg3[1024];
 
 extern unsigned long ptr_in_current_pgd;
 
-/* the no. of pointers that fit on a page: this will go away */
-#define PTRS_PER_PAGE   (PAGE_SIZE/sizeof(void*))
-
 /* Here is a trick, since mmap.c need the initializer elements for
  * protection_map[] to be constant at compile time, I set the following
  * to all zeros.  I set it to the real values after I link in the
index d6ef977d9aa87a03b1f4e73492a9568979e71274..ea7b83d5b6b81b243bc5189a2847578cf9668dfb 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmu_context.h,v 1.42 2000/02/08 07:47:03 davem Exp $ */
+/* $Id: mmu_context.h,v 1.43 2000/08/09 08:04:45 davem Exp $ */
 #ifndef __SPARC64_MMU_CONTEXT_H
 #define __SPARC64_MMU_CONTEXT_H
 
@@ -29,11 +29,9 @@ extern void get_new_mmu_context(struct mm_struct *mm);
 
 /* Initialize a new mmu context.  This is invoked when a new
  * address space instance (unique or shared) is instantiated.
- * A fresh mm_struct is cleared out to zeros, so this need not
- * do anything on Sparc64 since the only thing we care about
- * is that mm->context is an invalid context (ie. zero).
+ * This just needs to set mm->context to an invalid context.
  */
-#define init_new_context(__tsk, __mm)  do { } while(0)
+#define init_new_context(__tsk, __mm)  ((__mm)->context = 0UL)
 
 /* Destroy a dead context.  This occurs when mmput drops the
  * mm_users count to zero, the mmaps have been released, and
index 79f4d7448a603e9b90295bd1275cadf800dcf3a8..86bd2640298e25feafb28804f95840539154c979 100644 (file)
@@ -105,7 +105,8 @@ register unsigned long PAGE_OFFSET asm("g4");
 
 #define __pa(x)                        ((unsigned long)(x) - PAGE_OFFSET)
 #define __va(x)                        ((void *)((unsigned long) (x) + PAGE_OFFSET))
-#define MAP_NR(addr)           ((__pa(addr)-phys_base) >> PAGE_SHIFT)
+#define virt_to_page(kaddr)    (mem_map + ((__pa(kaddr)-phys_base) >> PAGE_SHIFT))
+#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
 
 #define virt_to_phys __pa
 #define phys_to_virt __va
index 3318578f36dab2388ee2bcf38f8449505f1b4097..c47527736d847102a0e64e3dc10c6962655ee771 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.128 2000/08/05 13:30:34 davem Exp $
+/* $Id: pgtable.h,v 1.130 2000/08/09 00:00:17 davem Exp $
  * pgtable.h: SpitFire page table operations.
  *
  * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -57,9 +57,6 @@
 #define PMD_TABLE_SIZE 0x2000  /* 2048 entries 4 bytes each */
 #define PGD_TABLE_SIZE 0x1000  /* 1024 entries 4 bytes each */
 
-/* the no. of pointers that fit on a page */
-#define PTRS_PER_PAGE  (1UL << (PAGE_SHIFT-3))
-
 /* NOTE: TLB miss handlers depend heavily upon where this is. */
 #define VMALLOC_START          0x0000000140000000UL
 #define VMALLOC_VMADDR(x)      ((unsigned long)(x))
index 37433eace43fe29dbd2e41b9cbbe239ce2609189..eae8b7bdb62b13f3cc0fed3a9719ab0a09e39c08 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.64 2000/05/09 17:40:15 davem Exp $
+/* $Id: processor.h,v 1.65 2000/08/09 00:00:17 davem Exp $
  * include/asm-sparc64/processor.h
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
index ce00d0602ae2136fc4ee7a0d64d43661597fd1b2..7786175290362feec5c3706c4bd79a6d8858d299 100644 (file)
@@ -85,7 +85,7 @@ void initrd_init(void);
  * code duplication in drivers.
  */
 
-extern inline void blkdev_dequeue_request(struct request * req)
+static inline void blkdev_dequeue_request(struct request * req)
 {
        if (req->e) {
                req->e->dequeue_fn(req);
@@ -99,6 +99,9 @@ void end_that_request_last(struct request *req);
 
 #if defined(MAJOR_NR) || defined(IDE_DRIVER)
 
+#undef DEVICE_ON
+#undef DEVICE_OFF
+
 /*
  * Add entries as needed.
  */
@@ -106,8 +109,6 @@ void end_that_request_last(struct request *req);
 #ifdef IDE_DRIVER
 
 #define DEVICE_NR(device)      (MINOR(device) >> PARTN_BITS)
-#define DEVICE_ON(device)      /* nothing */
-#define DEVICE_OFF(device)     /* nothing */
 #define DEVICE_NAME "ide"
 
 #elif (MAJOR_NR == RAMDISK_MAJOR)
@@ -116,8 +117,6 @@ void end_that_request_last(struct request *req);
 #define DEVICE_NAME "ramdisk"
 #define DEVICE_REQUEST rd_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device) 
-#define DEVICE_OFF(device)
 #define DEVICE_NO_RANDOM
 
 #elif (MAJOR_NR == Z2RAM_MAJOR)
@@ -126,8 +125,6 @@ void end_that_request_last(struct request *req);
 #define DEVICE_NAME "Z2RAM"
 #define DEVICE_REQUEST do_z2_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == FLOPPY_MAJOR)
 
@@ -137,7 +134,6 @@ static void floppy_off(unsigned int nr);
 #define DEVICE_INTR do_floppy
 #define DEVICE_REQUEST do_fd_request
 #define DEVICE_NR(device) ( (MINOR(device) & 3) | ((MINOR(device) & 0x80 ) >> 5 ))
-#define DEVICE_ON(device)
 #define DEVICE_OFF(device) floppy_off(DEVICE_NR(device))
 
 #elif (MAJOR_NR == HD_MAJOR)
@@ -148,16 +144,12 @@ static void floppy_off(unsigned int nr);
 #define TIMEOUT_VALUE (6*HZ)
 #define DEVICE_REQUEST do_hd_request
 #define DEVICE_NR(device) (MINOR(device)>>6)
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (SCSI_DISK_MAJOR(MAJOR_NR))
 
 #define DEVICE_NAME "scsidisk"
 #define TIMEOUT_VALUE (2*HZ)
 #define DEVICE_NR(device) (((MAJOR(device) & SD_MAJOR_MASK) << (8 - 4)) + (MINOR(device) >> 4))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 /* Kludge to use the same number for both char and block major numbers */
 #elif  (MAJOR_NR == MD_MAJOR) && defined(MD_DRIVER)
@@ -165,47 +157,35 @@ static void floppy_off(unsigned int nr);
 #define DEVICE_NAME "Multiple devices driver"
 #define DEVICE_REQUEST do_md_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == SCSI_TAPE_MAJOR)
 
 #define DEVICE_NAME "scsitape"
 #define DEVICE_INTR do_st  
 #define DEVICE_NR(device) (MINOR(device) & 0x7f)
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == SCSI_CDROM_MAJOR)
 
 #define DEVICE_NAME "CD-ROM"
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == XT_DISK_MAJOR)
 
 #define DEVICE_NAME "xt disk"
 #define DEVICE_REQUEST do_xd_request
 #define DEVICE_NR(device) (MINOR(device) >> 6)
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == PS2ESDI_MAJOR)
 
 #define DEVICE_NAME "PS/2 ESDI"
 #define DEVICE_REQUEST do_ps2esdi_request
 #define DEVICE_NR(device) (MINOR(device) >> 6)
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == CDU31A_CDROM_MAJOR)
 
 #define DEVICE_NAME "CDU31A"
 #define DEVICE_REQUEST do_cdu31a_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == ACSI_MAJOR) && (defined(CONFIG_ATARI_ACSI) || defined(CONFIG_ATARI_ACSI_MODULE))
 
@@ -213,8 +193,6 @@ static void floppy_off(unsigned int nr);
 #define DEVICE_INTR do_acsi
 #define DEVICE_REQUEST do_acsi_request
 #define DEVICE_NR(device) (MINOR(device) >> 4)
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == MITSUMI_CDROM_MAJOR)
 
@@ -222,8 +200,6 @@ static void floppy_off(unsigned int nr);
 /* #define DEVICE_INTR do_mcd */
 #define DEVICE_REQUEST do_mcd_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == MITSUMI_X_CDROM_MAJOR)
 
@@ -231,48 +207,36 @@ static void floppy_off(unsigned int nr);
 /* #define DEVICE_INTR do_mcdx */
 #define DEVICE_REQUEST do_mcdx_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == MATSUSHITA_CDROM_MAJOR)
 
 #define DEVICE_NAME "Matsushita CD-ROM controller #1"
 #define DEVICE_REQUEST do_sbpcd_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == MATSUSHITA_CDROM2_MAJOR)
 
 #define DEVICE_NAME "Matsushita CD-ROM controller #2"
 #define DEVICE_REQUEST do_sbpcd2_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == MATSUSHITA_CDROM3_MAJOR)
 
 #define DEVICE_NAME "Matsushita CD-ROM controller #3"
 #define DEVICE_REQUEST do_sbpcd3_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == MATSUSHITA_CDROM4_MAJOR)
 
 #define DEVICE_NAME "Matsushita CD-ROM controller #4"
 #define DEVICE_REQUEST do_sbpcd4_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == AZTECH_CDROM_MAJOR)
 
 #define DEVICE_NAME "Aztech CD-ROM"
 #define DEVICE_REQUEST do_aztcd_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == CDU535_CDROM_MAJOR)
 
@@ -280,55 +244,41 @@ static void floppy_off(unsigned int nr);
 #define DEVICE_INTR do_cdu535
 #define DEVICE_REQUEST do_cdu535_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == GOLDSTAR_CDROM_MAJOR)
 
 #define DEVICE_NAME "Goldstar R420"
 #define DEVICE_REQUEST do_gscd_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == CM206_CDROM_MAJOR)
 #define DEVICE_NAME "Philips/LMS CD-ROM cm206"
 #define DEVICE_REQUEST do_cm206_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == OPTICS_CDROM_MAJOR)
 
 #define DEVICE_NAME "DOLPHIN 8000AT CD-ROM"
 #define DEVICE_REQUEST do_optcd_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == SANYO_CDROM_MAJOR)
 
 #define DEVICE_NAME "Sanyo H94A CD-ROM"
 #define DEVICE_REQUEST do_sjcd_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == APBLOCK_MAJOR)
 
 #define DEVICE_NAME "apblock"
 #define DEVICE_REQUEST ap_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device) 
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == DDV_MAJOR)
 
 #define DEVICE_NAME "ddv"
 #define DEVICE_REQUEST ddv_request
 #define DEVICE_NR(device) (MINOR(device)>>PARTN_BITS)
-#define DEVICE_ON(device) 
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == MFM_ACORN_MAJOR)
 
@@ -336,41 +286,30 @@ static void floppy_off(unsigned int nr);
 #define DEVICE_INTR do_mfm
 #define DEVICE_REQUEST do_mfm_request
 #define DEVICE_NR(device) (MINOR(device) >> 6)
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == NBD_MAJOR)
 
 #define DEVICE_NAME "nbd"
 #define DEVICE_REQUEST do_nbd_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device) 
-#define DEVICE_OFF(device)
-
 
 #elif (MAJOR_NR == MDISK_MAJOR)
 
 #define DEVICE_NAME "mdisk"
 #define DEVICE_REQUEST mdisk_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device) 
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == DASD_MAJOR)
 
 #define DEVICE_NAME "dasd"
 #define DEVICE_REQUEST do_dasd_request
 #define DEVICE_NR(device) (MINOR(device) >> PARTN_BITS)
-#define DEVICE_ON(device) 
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == I2O_MAJOR)
 
 #define DEVICE_NAME "I2O block"
 #define DEVICE_REQUEST do_i2ob_request
 #define DEVICE_NR(device) (MINOR(device)>>4)
-#define DEVICE_ON(device) 
-#define DEVICE_OFF(device)
 
 #elif (MAJOR_NR == COMPAQ_SMART2_MAJOR)
 
@@ -378,11 +317,18 @@ static void floppy_off(unsigned int nr);
 #define TIMEOUT_VALUE (25*HZ)
 #define DEVICE_REQUEST do_ida_request0
 #define DEVICE_NR(device) (MINOR(device) >> 4)
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
 
 #endif /* MAJOR_NR == whatever */
 
+/* provide DEVICE_xxx defaults, if not explicitly defined
+ * above in the MAJOR_NR==xxx if-elif tree */
+#ifndef DEVICE_ON
+#define DEVICE_ON(device) do {} while (0)
+#endif
+#ifndef DEVICE_OFF
+#define DEVICE_OFF(device) do {} while (0)
+#endif
+
 #if (MAJOR_NR != SCSI_TAPE_MAJOR)
 #if !defined(IDE_DRIVER)
 
@@ -434,7 +380,7 @@ static void (DEVICE_REQUEST)(request_queue_t *);
 
 #if ! SCSI_BLK_MAJOR(MAJOR_NR) && (MAJOR_NR != COMPAQ_SMART2_MAJOR)
 
-static void end_request(int uptodate) {
+static inline void end_request(int uptodate) {
        struct request *req = CURRENT;
 
        if (end_that_request_first(req, uptodate, DEVICE_NAME))
index 44853fbe78fe2ff996c5100aadb744c3a8922286..851bf3c534fe12c6951edcd8112e9ab8293c4f1f 100644 (file)
@@ -150,8 +150,7 @@ extern struct sec_size * blk_sec[MAX_BLKDEV];
 extern struct blk_dev_struct blk_dev[MAX_BLKDEV];
 extern void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size);
 extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct block_device_operations *ops, long size);
-extern void generic_make_request(request_queue_t *q, int rw,
-                                               struct buffer_head * bh);
+extern void generic_make_request(int rw, struct buffer_head * bh);
 extern request_queue_t *blk_get_queue(kdev_t dev);
 extern void blkdev_release_request(struct request *);
 
index e68940b0f91351a7ea78946b2716999cd6225fa1..2fd39cac9ef4e573d97c15c1c4a918e029361240 100644 (file)
@@ -77,7 +77,7 @@ extern void __br_lock_usage_bug (void);
 
 #ifdef __BRLOCK_USE_ATOMICS
 
-extern inline void br_read_lock (enum brlock_indices idx)
+static inline void br_read_lock (enum brlock_indices idx)
 {
        /*
         * This causes a link-time bug message if an
@@ -89,7 +89,7 @@ extern inline void br_read_lock (enum brlock_indices idx)
        read_lock(&__brlock_array[smp_processor_id()][idx]);
 }
 
-extern inline void br_read_unlock (enum brlock_indices idx)
+static inline void br_read_unlock (enum brlock_indices idx)
 {
        if (idx >= __BR_END)
                __br_lock_usage_bug();
@@ -98,7 +98,7 @@ extern inline void br_read_unlock (enum brlock_indices idx)
 }
 
 #else /* ! __BRLOCK_USE_ATOMICS */
-extern inline void br_read_lock (enum brlock_indices idx)
+static inline void br_read_lock (enum brlock_indices idx)
 {
        unsigned int *ctr;
        spinlock_t *lock;
@@ -124,7 +124,7 @@ again:
        }
 }
 
-extern inline void br_read_unlock (enum brlock_indices idx)
+static inline void br_read_unlock (enum brlock_indices idx)
 {
        unsigned int *ctr;
 
@@ -143,14 +143,14 @@ extern inline void br_read_unlock (enum brlock_indices idx)
 extern void FASTCALL(__br_write_lock (enum brlock_indices idx));
 extern void FASTCALL(__br_write_unlock (enum brlock_indices idx));
 
-extern inline void br_write_lock (enum brlock_indices idx)
+static inline void br_write_lock (enum brlock_indices idx)
 {
        if (idx >= __BR_END)
                __br_lock_usage_bug();
        __br_write_lock(idx);
 }
 
-extern inline void br_write_unlock (enum brlock_indices idx)
+static inline void br_write_unlock (enum brlock_indices idx)
 {
        if (idx >= __BR_END)
                __br_lock_usage_bug();
index bde78147519f9901240c2e861ac2b4b4f411d439..3cd0250eed7ac6c0faa18dc12fd48e1101216999 100644 (file)
@@ -32,7 +32,7 @@ static __inline__ unsigned long kmap(struct page * page) {
 #endif /* CONFIG_HIGHMEM */
 
 /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */
-extern inline void clear_user_highpage(struct page *page, unsigned long vaddr)
+static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
 {
        unsigned long kaddr;
 
@@ -41,7 +41,7 @@ extern inline void clear_user_highpage(struct page *page, unsigned long vaddr)
        kunmap(page);
 }
 
-extern inline void clear_highpage(struct page *page)
+static inline void clear_highpage(struct page *page)
 {
        unsigned long kaddr;
 
@@ -50,7 +50,7 @@ extern inline void clear_highpage(struct page *page)
        kunmap(page);
 }
 
-extern inline void memclear_highpage(struct page *page, unsigned int offset, unsigned int size)
+static inline void memclear_highpage(struct page *page, unsigned int offset, unsigned int size)
 {
        unsigned long kaddr;
 
@@ -64,7 +64,7 @@ extern inline void memclear_highpage(struct page *page, unsigned int offset, uns
 /*
  * Same but also flushes aliased cache contents to RAM.
  */
-extern inline void memclear_highpage_flush(struct page *page, unsigned int offset, unsigned int size)
+static inline void memclear_highpage_flush(struct page *page, unsigned int offset, unsigned int size)
 {
        unsigned long kaddr;
 
@@ -76,7 +76,7 @@ extern inline void memclear_highpage_flush(struct page *page, unsigned int offse
        kunmap(page);
 }
 
-extern inline void copy_user_highpage(struct page *to, struct page *from, unsigned long vaddr)
+static inline void copy_user_highpage(struct page *to, struct page *from, unsigned long vaddr)
 {
        unsigned long vfrom, vto;
 
@@ -87,7 +87,7 @@ extern inline void copy_user_highpage(struct page *to, struct page *from, unsign
        kunmap(to);
 }
 
-extern inline void copy_highpage(struct page *to, struct page *from)
+static inline void copy_highpage(struct page *to, struct page *from)
 {
        unsigned long vfrom, vto;
 
index 07621e2d55b549ff9d79f01d738bdba63ac32740..61e7b66fe39b71a1d79de6754d9e67b50b82cbf1 100644 (file)
@@ -1,14 +1,16 @@
 /*
  * JFFS -- Journalling Flash File System, Linux implementation.
  *
- * Copyright (C) 1999, 2000  Finn Hakansson, Axis Communications, Inc.
+ * Copyright (C) 1999, 2000  Axis Communications AB.
+ *
+ * Created by Finn Hakansson <finn@axis.com>.
  *
  * This 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.
  *
- * $Id: jffs.h,v 1.5 2000/06/13 14:22:48 alex Exp $
+ * $Id: jffs.h,v 1.11 2000/08/04 12:46:34 dwmw2 Exp $
  *
  * Ported to Linux 2.3.x and MTD:
  * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
@@ -59,9 +61,6 @@
 #define JFFS_MODIFY_DATA  0x04
 #define JFFS_MODIFY_EXIST 0x08
 
-/* Using the garbage collection mechanism.  */
-#define USE_GC
-
 struct jffs_control;
 
 /* The JFFS raw inode structure: Used for storage on physical media.  */
@@ -87,7 +86,7 @@ struct jffs_raw_inode
        __u8 nsize;       /* Name length.  */
        __u8 nlink;       /* Number of links.  */
        __u8 spare : 6;   /* For future use.  */
-       __u8 rename : 1;  /* Is this a special rename?  */
+       __u8 rename : 1;  /* Rename to a name of an already existing file?  */
        __u8 deleted : 1; /* Has this file been deleted?  */
        __u8 accurate;    /* The inode is obsolete if accurate == 0.  */
        __u32 dchksum;    /* Checksum for the data.  */
@@ -161,17 +160,34 @@ struct jffs_file
 };
 
 
+/* This is just a definition of a simple list used for keeping track of
+   files deleted due to a rename.  This list is only used during the
+   mounting of the file system and only if there have been rename operations
+   earlier.  */
+struct jffs_delete_list
+{
+       __u32 ino;
+       struct jffs_delete_list *next;
+};
+
+
 /* A struct for the overall file system control.  Pointers to
    jffs_control structs are named `c' in the source code.  */
 struct jffs_control
 {
-       struct super_block *sb;  /* Reference to the VFS super block.  */
-       struct jffs_file *root;  /* The root directory file.  */
-       struct list_head *hash; /* Hash table for finding files by ino.  */
-       struct jffs_fmcontrol *fmc; /* Flash memory control structure.  */
-       __u32 hash_len;    /* The size of the hash table.  */
-       __u32 next_ino;    /* Next inode number to use for new files.  */
-       __u16 building_fs; /* Is the file system being built right now?  */
+       struct super_block *sb;         /* Reference to the VFS super block.  */
+       struct jffs_file *root;         /* The root directory file.  */
+       struct list_head *hash;         /* Hash table for finding files by ino.  */
+       struct jffs_fmcontrol *fmc;     /* Flash memory control structure.  */
+       __u32 hash_len;                 /* The size of the hash table.  */
+       __u32 next_ino;                 /* Next inode number to use for new files.  */
+       __u16 building_fs;              /* Is the file system being built right now?  */
+       struct jffs_delete_list *delete_list; /* Track deleted files.  */
+       pid_t thread_pid;               /* GC thread's PID */
+       struct task_struct *gc_task;    /* GC task struct */
+       struct semaphore gc_thread_sem; /* GC thread exit mutex */
+       __u32 gc_minfree_threshold;     /* GC trigger thresholds */
+       __u32 gc_maxdirty_threshold;
 };
 
 
index 94e30f7c7a6c8e6e5b7ddbf56e57190d3eb9b8d0..a248e939f749f758c43d18d3730f6b0ee7feae2b 100644 (file)
@@ -338,9 +338,6 @@ extern unsigned long FASTCALL(get_zeroed_page(int gfp_mask));
 #define __get_dma_pages(gfp_mask, order) \
                __get_free_pages((gfp_mask) | GFP_DMA,(order))
 
-#define virt_to_page(kaddr)    (mem_map + MAP_NR(kaddr))
-#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
-
 /*
  * The old interface name will be removed in 2.5:
  */
index 9f445ec6a293331cb51029fc340e43923f2538a8..f12c936d88743b7aa787f7cad0b059806638b88d 100644 (file)
 #define PCI_DEVICE_ID_TTI_HPT366       0x0004
 
 #define PCI_VENDOR_ID_VIA              0x1106
+#define PCI_DEVICE_ID_VIA_8363_0       0x0305
 #define PCI_DEVICE_ID_VIA_8371_0       0x0391
 #define PCI_DEVICE_ID_VIA_8501_0       0x0501
-#define PCI_DEVICE_ID_VIA_8601_0       0x0601
 #define PCI_DEVICE_ID_VIA_82C505       0x0505
 #define PCI_DEVICE_ID_VIA_82C561       0x0561
 #define PCI_DEVICE_ID_VIA_82C586_1     0x0571
 #define PCI_DEVICE_ID_VIA_82C596       0x0596
 #define PCI_DEVICE_ID_VIA_82C597_0     0x0597
 #define PCI_DEVICE_ID_VIA_82C598_0     0x0598
+#define PCI_DEVICE_ID_VIA_8601_0       0x0601
+#define PCI_DEVICE_ID_VIA_8605_0       0x0605
 #define PCI_DEVICE_ID_VIA_82C680       0x0680
 #define PCI_DEVICE_ID_VIA_82C686       0x0686
 #define PCI_DEVICE_ID_VIA_82C691       0x0691
 #define PCI_DEVICE_ID_VIA_82C693       0x0693
+#define PCI_DEVICE_ID_VIA_82C693_1     0x0698
 #define PCI_DEVICE_ID_VIA_82C926       0x0926
 #define PCI_DEVICE_ID_VIA_82C416       0x1571
 #define PCI_DEVICE_ID_VIA_82C595_97    0x1595
 #define PCI_DEVICE_ID_VIA_82C586_2     0x3038
 #define PCI_DEVICE_ID_VIA_82C586_3     0x3040
+#define PCI_DEVICE_ID_VIA_6305         0x3044
+#define PCI_DEVICE_ID_VIA_82C596_3     0x3050
+#define PCI_DEVICE_ID_VIA_82C596B_3    0x3051
 #define PCI_DEVICE_ID_VIA_82C686_4     0x3057
 #define PCI_DEVICE_ID_VIA_82C686_5     0x3058
+#define PCI_DEVICE_ID_VIA_8233_5       0x3059
+#define PCI_DEVICE_ID_VIA_8233_7       0x3065
 #define PCI_DEVICE_ID_VIA_82C686_6     0x3068
+#define PCI_DEVICE_ID_VIA_8233_0       0x3074
+#define PCI_DEVICE_ID_VIA_8633_0       0x3091
+#define PCI_DEVICE_ID_VIA_8367_0       0x3099
 #define PCI_DEVICE_ID_VIA_86C100A      0x6100
 #define PCI_DEVICE_ID_VIA_8231         0x8231
+#define PCI_DEVICE_ID_VIA_8231_4       0x8235
+#define PCI_DEVICE_ID_VIA_8365_1       0x8305
 #define PCI_DEVICE_ID_VIA_8371_1       0x8391
 #define PCI_DEVICE_ID_VIA_8501_1       0x8501
 #define PCI_DEVICE_ID_VIA_82C597_1     0x8597
 #define PCI_DEVICE_ID_VIA_82C598_1     0x8598
 #define PCI_DEVICE_ID_VIA_8601_1       0x8601
+#define PCI_DEVICE_ID_VIA_8505_1       0X8605
+#define PCI_DEVICE_ID_VIA_8633_1       0xB091
+#define PCI_DEVICE_ID_VIA_8367_1       0xB099
 
 #define PCI_VENDOR_ID_SMC2             0x1113
 #define PCI_DEVICE_ID_SMC2_1211TX      0x1211
index e5f26faa45357b080ea6bdfaa319223accc5046b..332cabf7e4f65b6f1fe50faa902462a6c7f596f0 100644 (file)
@@ -681,32 +681,37 @@ static __inline__ void *fb_memmove(void *d, const void *s, size_t count)
        while (count--)
            fb_writeb(fb_readb(src++), dst++);
     } else {
-       dst = (unsigned long) d + count - 1;
-       src = (unsigned long) s + count - 1;
+       dst = (unsigned long) d + count;
+       src = (unsigned long) s + count;
 
        if ((count < 8) || ((dst ^ src) & 3))
            goto restdown;
 
        if (dst & 1) {
-           fb_writeb(fb_readb(src--), dst--);
+           src--;
+           dst--;
            count--;
+           fb_writeb(fb_readb(src), dst);
        }
        if (dst & 2) {
-           fb_writew(fb_readw(src), dst);
            src -= 2;
            dst -= 2;
            count -= 2;
+           fb_writew(fb_readw(src), dst);
        }
        while (count > 3) {
-           fb_writel(fb_readl(src), dst);
            src -= 4;
            dst -= 4;
            count -= 4;
+           fb_writel(fb_readl(src), dst);
        }
 
     restdown:
-       while (count--)
-           fb_writeb(fb_readb(src--), dst--);
+       while (count--) {
+           src--;
+           dst--;
+           fb_writeb(fb_readb(src), dst);
+       }
     }
 
     return d;
@@ -744,32 +749,37 @@ static __inline__ void fast_memmove(char *d, const char *s, size_t count)
        while (count--)
            fb_writeb(fb_readb(src++), dst++);
     } else {
-       dst = (unsigned long) d + count - 1;
-       src = (unsigned long) s + count - 1;
+       dst = (unsigned long) d + count;
+       src = (unsigned long) s + count;
 
        if ((count < 8) || ((dst ^ src) & 3))
            goto restdown;
 
        if (dst & 1) {
-           fb_writeb(fb_readb(src--), dst--);
+           src--;
+           dst--;
            count--;
+           fb_writeb(fb_readb(src), dst);
        }
        if (dst & 2) {
-           fb_writew(fb_readw(src), dst);
            src -= 2;
            dst -= 2;
            count -= 2;
+           fb_writew(fb_readw(src), dst);
        }
        while (count > 3) {
-           fb_writel(fb_readl(src), dst);
            src -= 4;
            dst -= 4;
            count -= 4;
+           fb_writel(fb_readl(src), dst);
        }
 
     restdown:
-       while (count--)
-           fb_writeb(fb_readb(src--), dst--);
+       while (count--) {
+           src--;
+           dst--;
+           fb_writeb(fb_readb(src), dst);
+       }
     }
 }
 
index f77eaa4eefc08b006dca9bf21b61eac4186cd30b..641de8b220f21d9093311983ae81c37ee4f8d7ef 100644 (file)
@@ -131,6 +131,7 @@ static inline int dup_mmap(struct mm_struct * mm)
        flush_cache_mm(current->mm);
        mm->locked_vm = 0;
        mm->mmap = NULL;
+       mm->mmap_avl = NULL;
        mm->mmap_cache = NULL;
        mm->map_count = 0;
        mm->context = 0;
@@ -301,7 +302,6 @@ static inline int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
        }
 
        retval = -ENOMEM;
-       mm = mm_alloc();
        mm = allocate_mm();
        if (!mm)
                goto fail_nomem;
index 92d8af4b5109e87df7983a7b27c764fd1f7e833d..6b8538715ebff1270c16e64e1848702c20aaa82b 100644 (file)
@@ -163,9 +163,9 @@ static inline void internal_add_timer(struct timer_list *timer)
 
 /* Initialize both explicitly - let's try to have them in the same cache line */
 spinlock_t timerlist_lock = SPIN_LOCK_UNLOCKED;
-volatile struct timer_list * volatile running_timer = NULL;
 
 #ifdef CONFIG_SMP
+volatile struct timer_list * volatile running_timer = NULL;
 #define timer_enter(t) do { running_timer = t; mb(); } while (0)
 #define timer_exit() do { running_timer = NULL; } while (0)
 #define timer_is_running(t) (running_timer == t)
@@ -173,8 +173,6 @@ volatile struct timer_list * volatile running_timer = NULL;
 #else
 #define timer_enter(t)         do { } while (0)
 #define timer_exit()           do { } while (0)
-#define timer_is_running(t)    (0)
-#define timer_synchronize(t)   do { (void)(t); barrier(); } while(0)
 #endif
 
 void add_timer(struct timer_list *timer)
index 68cd8a034cf13e7110de3ac670177c53294416d1..cb6179483cb42ca38d9eac6609abcfc311de051a 100644 (file)
@@ -166,7 +166,7 @@ struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos)
                return entry;
        }
 
-       entry = kmalloc(sizeof(struct atm_qos), GFP_KERNEL);
+       entry = kmalloc(sizeof(struct atm_mpoa_qos), GFP_KERNEL);
        if (entry == NULL) {
                printk("mpoa: atm_mpoa_add_qos: out of memory\n");
                return entry;
index 53e664444588d075b859c6e10892f777295b46df..b511e29fd5b1427ab8363f16b43e4592b89d1cdf 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The options processing module for ip.c
  *
- * Version:    $Id: ip_options.c,v 1.19 2000/07/26 01:04:17 davem Exp $
+ * Version:    $Id: ip_options.c,v 1.20 2000/08/09 09:17:00 davem Exp $
  *
  * Authors:    A.N.Kuznetsov
  *             
@@ -498,8 +498,10 @@ int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen, in
        memset(opt, 0, sizeof(struct ip_options));
        if (optlen) {
                if (user) {
-                       if (copy_from_user(opt->__data, data, optlen))
+                       if (copy_from_user(opt->__data, data, optlen)) {
+                               kfree(opt);
                                return -EFAULT;
+                       }
                } else
                        memcpy(opt->__data, data, optlen);
        }
index bf557e2537cb3f0f76135d03de9f1edbd69d1ead..7a484606bbae6308477ebd251c0ddc2aee787633 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             PACKET - implements raw packet sockets.
  *
- * Version:    $Id: af_packet.c,v 1.37 2000/07/26 01:04:21 davem Exp $
+ * Version:    $Id: af_packet.c,v 1.39 2000/08/09 08:04:45 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
index 2993991dd4802647fb8c4eab3cbcce5faa7349de..f0565ed3e259155327ce30aa2fb1aae3acec5d69 100644 (file)
@@ -1372,7 +1372,6 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr *msg, unsigned flags)
        {
                if (ctl_len > sizeof(ctl))
                {
-                       err = -ENOBUFS;
                        ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
                        if (ctl_buf == NULL) 
                                goto out_freeiov;